This document contains the code for the AURORA ELA analysis. In this analysis, we will explore the relationship between childhood trauma (CTQ) and pain outcomes in the AURORA dataset. We will perform correlation analysis, linear models, repeated measures models, and assess the relationship between CTQ and pain outcome trajectories. This is a preliminary draft of the analysis that will be completed over the next 2 weeks.

Set up

Import libraries

rm(list=ls())

libraries <- c("tidyverse", "rstatix", "MASS","corrplot", "nlme", "sjPlot", "readxl", "nnet", "broom", "lmtest", "forcats","car", "highcharter", "ggplot2", "corrr", "ggcorrplot", "gridExtra", "skimr", "pROC", "gtsummary", "dunn.test", "tidyr", "purrr", "dplyr")

suppressMessages(suppressWarnings(
  invisible(lapply(libraries, library, character.only = TRUE))))

Define plot elements


Import all freeze 4 datasets

Note: For the purpose of this draft code file, Lauren has already combined all of the freeze 4 datasets into one file. This pre-combined file, called ELA_full_data_raw.csv below, will be used for the initial analysis. The full file import code will be rendered and applied in the final script

#Read in the dataset
data_1 <- read.csv("AURORA_full_update02102022_New.csv",check.names=F)[-1]

#freeze 4 datasets
AURORA_Freeze_4_general_mod <- read_csv("AURORA_Freeze_4_general_mod.csv",na = ".")
AURORA_Freeze_4_demogr_mod <- read_csv("AURORA_Freeze_4_demogr_mod.csv",na = ".")
AURORA_Freeze_4_pain_mod <- read_csv("AURORA_Freeze_4_pain_mod.csv",na = ".")

AURORA_Freeze_4_ctq_mod <- read_csv("AURORA_Freeze_4_ctq_mod.csv",na = ".")
AURORA_F4_CTQ_item <- readxl::read_excel("AURORA_F4_CTQ_item.xlsx")
#AURORA_Freeze_4_pdi_mod <- read_csv("AURORA_Freeze_4_pdi_mod.csv",na = ".")
SiteID <- read_excel("SiteID.xlsx")
FZ4_df <- AURORA_Freeze_4_demogr_mod %>% inner_join(AURORA_F4_CTQ_item,by="PID") %>% 
  inner_join(AURORA_Freeze_4_pain_mod,by="PID") %>% 
  inner_join(AURORA_Freeze_4_ctq_mod,by="PID") %>% 
  #inner_join(AURORA_Freeze_4_pdi_mod,by="PID") %>% 
  inner_join(SiteID,by="PID") %>% 
  mutate(Site_New = case_when(SiteID %in% c("Baystate","BMC", "Beth Israel", "BWH", "Cooper","Einstein","Jefferson","MGH","Miriam","Penn","Rhode Island","St. John","St. Joseph","Temple","UMass") ~ "NorthEast",SiteID %in% c("Baylor", "Emory ED", "Jacksonville","UAB","UNC","UT Houston","UT Southwestern","Vanderbilt") ~ "SouthEast", SiteID %in% c("39","49","Beaumont Royal Oak","Beaumont Troy","Eskenazi","Henry Ford","Cincinnati","Indiana","WashU","WashU DP") ~ "Midwest")) %>% 
  convert_as_factor(Site_New,ED_GenderBirthCert,ED_GenderNow,ED_Marital,ED_RaceEthCode,ED_highestgrade,WK2_EmploymentCode,WK2_IncomeCode) %>% 
  mutate_at(vars(contains("WK2_Childhood")),as.numeric) %>% dplyr::select(-SiteID) %>% #2682
  mutate(WK2_Bullying_Total = WK2_ChildhoodBullying+WK2_ChildhoodHitOrHurt) %>% 
  inner_join(data_1 %>% dplyr::select(PID,WK8_Pain_C,M3_Pain_C,M6_Pain_C),by="PID") %>% 
  filter(is.na(WK2_CTQSF_SexAbu_RS) == F) %>% 
  filter(is.na(WK2_CTQSF_PhyAbu_RS)== F) %>% 
  filter(is.na(WK2_CTQSF_EmoAbu_RS)== F) %>% 
  filter(is.na(WK2_CTQSF_EmoNeg_RS) == F) %>% 
  filter(is.na(WK2_CTQSF_PhyNeg_RS) == F) %>% 
  filter(is.na(WK2_Bullying_Total) == F) %>% #2483
  mutate(log_WK2_CTQSF_Total_RS = log2(WK2_CTQSF_Total_RS+1),log_ED_NowPain=log2(ED_NowPain+1))


Below: Read in the completed dataframe with each of the separate AURORA files. Lauren did this on her end for ease of use in this draft code analysis. Latent class trajectories also imported.

Troubleshooting why the R environment is all fucked up and nothing works

#rm(list = ls())
#install.packages("dplyr")
library(readxl)
library(dplyr)

Trauma_df <- read_excel("AURORA_Freeze_4_trauma_mod.xlsx")

# Explicitly set select to refer to dplyr::select
select <- dplyr::select
rename <- dplyr::rename
# Import datasets
FZ4_df <- read_csv("ELA_full_data_raw.csv")
New names:
• `` -> `...1`
Rows: 2483 Columns: 78
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (1): Site_New
dbl (77): ...1, PID, ED_GenderBirthCert, ED_GenderNow, ED_Age, ED_Marital, ED_RaceEthCode, ED_highestgrade, BMI, WK2_Employment...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
pain_trajectory <- read_csv("pain_latent_class_4.csv")
Rows: 2943 Columns: 6
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): pain_Class_MostLikely
dbl (5): PID, Probability_Class1, Probability_Class2, Probability_Class3, Probability_Class4

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
PTSD_df <- read_excel("AURORA_Freeze_4_ptsd_mod.xlsx")
Trauma_df <- read_excel("AURORA_Freeze_4_trauma_mod.xlsx")
Injury_df <- read_excel("AURORA_Freeze_4_injury_mod.xlsx")
ADI_df <- read_excel("AURORA_Freeze_4_ses_mod.xlsx",na = ".")

# Combine datasets
df_traj <- FZ4_df %>%
  inner_join(Trauma_df %>% select(PID, ED_Event_BroadClass), by = "PID") %>%
  inner_join(Injury_df %>% select(PID, ED_Concussion), by = "PID") %>%
  inner_join(ADI_df %>% select(PID, ADI_NatRank), by = "PID") %>%
  inner_join(pain_trajectory %>% select(PID, pain_Class_MostLikely), by = "PID") 

#export <- df_traj[,c(2,82,70)]
#write.csv(export, "ELA_full_data.csv")
#import xiady df AURORA_Construct_Score_FS_Frz4_Data.csv
df_xiaodi <- read_csv("AURORA_Construct_Score_FS_Frz4_Data.csv")
Rows: 2887 Columns: 141
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (140): Pain_1, Pain_9, Pain_21, Pain_31, Pain_43, Pain_53, Pain_67, Pain_77, Pain_105, Pain_147, Pain_196, Pain_238, Pain_2...
dbl   (1): PID

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#get rid of everything but the variables that start with Pain
df_xiaodi2 <- df_xiaodi %>% select(PID, starts_with("Pain")) %>% as.data.frame()


#  bind it by PID to our data set and send me a simpler CSV that is just PID, Pain Trajectory, and Pain Scores for all the time points?

pain_scores_df <- df_traj[,c(2,82)]

#join pain_scores_df and df_xiaodi2 by PID
xiaodi_df_for_Lauren <- pain_scores_df %>% inner_join(df_xiaodi2, by = "PID") 

#write csv of xiaodi_df_for_Lauren
write.csv(xiaodi_df_for_Lauren, "xiaodi_df_for_Lauren.csv")


Clean dataframe

Relevel and refactor features

Refactor pain trajectories and Relevel to “low pain” as the reference group

#df_traj$pain_Class_MostLikely

#df_traj <- df_traj %>% rename(Pain_Class = pain_Class_MostLikely)

names(df_traj)[names(df_traj) == "pain_Class_MostLikely"] <- "Pain_Class"


df_traj <- df_traj %>%
  mutate(Pain_Class = case_when(
    Pain_Class == "Class 1" ~ "moderate recovery",
    Pain_Class == "Class 2" ~ "moderate",
    Pain_Class == "Class 3" ~ "low",
    Pain_Class == "Class 4" ~ "high",
    TRUE ~ as.character(Pain_Class)  # This handles any unexpected values
  )) %>%
  mutate(Pain_Class = factor(Pain_Class)) %>%
  mutate(Pain_Class = relevel(Pain_Class, ref = "low"))

Factorize and rename categorical variables

factor_vars <- c("ED_GenderBirthCert", "ED_Event_BroadClass", "ED_Marital", 
                 "WK2_EmploymentCode", "ED_highestgrade", "ED_RaceEthCode", "PRE_Pain_MdSv")
df_traj[factor_vars] <- lapply(df_traj[factor_vars], as.factor)

#in gender, change 1 to male and 2 to female
df_traj$ED_GenderBirthCert <- ifelse(df_traj$ED_GenderBirthCert == 1, "Male", "Female")

#in pre pain, change 1 to yes and 0 to no .. is this correct?
df_traj$PRE_Pain_MdSv <- ifelse(df_traj$PRE_Pain_MdSv == 1, "Yes", "No")

# Convert continuous variables to numeric
df_traj$ED_PDI_RS <- as.numeric(df_traj$ED_PDI_RS)
df_traj$ED_Concussion <- as.numeric(df_traj$ED_Concussion)
Warning: NAs introduced by coercion
#rename WK2 CTQ total column to CTQ_Total
df_traj <- df_traj %>%
  rename(CTQ_Total = WK2_CTQSF_Total_RS)

general clean up, renaming, removing negatives

#Make any value less than 0 in the bullying total == NA
df_traj$WK2_Bullying_Total <- ifelse(df_traj$WK2_Bullying_Total < 0, NA, df_traj$WK2_Bullying_Total)

#Make any value less than 0 in ADI == NA
df_traj$ADI_NatRank <- ifelse(df_traj$ADI_NatRank < 0, NA, df_traj$ADI_NatRank)


#3 bullying rows have negative numbers

#remove the rows in WK2_Bullying_Total that contain negative values


df_traj <- df_traj %>% filter(WK2_Bullying_Total >= 0)

relevel categories for trauma type

df_traj <- df_traj %>%
  mutate(ED_Event_BroadClass = case_when(
    ED_Event_BroadClass == "1" ~ "MVC/Non-motor Collision",
    ED_Event_BroadClass == "6" ~ "MVC/Non-motor Collision",
    ED_Event_BroadClass == "2" ~ "Physical/Sexual Abuse",
    ED_Event_BroadClass == "3" ~ "Physical/Sexual Abuse",
    ED_Event_BroadClass == "4" ~ "Other",
    ED_Event_BroadClass == "5" ~ "Other",
    ED_Event_BroadClass == "7" ~ "Other",
    ED_Event_BroadClass == "8" ~ "Other",
    ED_Event_BroadClass == "9" ~ "Other",
    ED_Event_BroadClass == "10" ~ "Other",
    ED_Event_BroadClass == "11" ~ "Other",
    TRUE ~ as.character(ED_Event_BroadClass)  # Keeps any other values unchanged
  ))

# Convert ED_Event broad class to factor
df_traj$ED_Event_BroadClass <- factor(df_traj$ED_Event_BroadClass)

table(df_traj$ED_Event_BroadClass)

MVC/Non-motor Collision                   Other   Physical/Sexual Abuse 
                   1909                     340                     231 


Relevel categories for education

#relevel education category
# 1- did not finish HS (codes 0-12) 2- HS grad + some college (codes 13-15) 3- college grad (Bachelors or Associates) (codes 16-18) 4- post grad codes(19-21)
df_traj <- df_traj %>%
  mutate(ED_highestgrade = case_when(
    ED_highestgrade == "0" ~ "Did not finish HS",
    ED_highestgrade == "1" ~ "Did not finish HS",
    ED_highestgrade == "7" ~ "Did not finish HS",
    ED_highestgrade == "8" ~ "Did not finish HS",
    ED_highestgrade == "9" ~ "Did not finish HS",
    ED_highestgrade == "10" ~ "Did not finish HS",
    ED_highestgrade == "11" ~ "Did not finish HS",
    ED_highestgrade == "12" ~ "Did not finish HS",
    ED_highestgrade == "13" ~ "HS Grad/Some College",
    ED_highestgrade == "14" ~ "HS Grad/Some College",
    ED_highestgrade == "15" ~ "HS Grad/Some College",
    ED_highestgrade == "16" ~ "Bach or Assoc degree",
    ED_highestgrade == "17" ~ "Bach or Assoc degree",
    ED_highestgrade == "18" ~ "Bach or Assoc degree",
    ED_highestgrade == "19" ~ "Post-graduate education",
    ED_highestgrade == "20" ~ "Post-graduate education",
    ED_highestgrade == "21" ~ "Post-graduate education",
    ED_highestgrade == "-7" ~ NA,
    ED_highestgrade == "-5" ~ NA,
    TRUE ~ as.character(ED_highestgrade)  # Keeps any other values unchanged
  ))

# Convert to factor
df_traj$ED_highestgrade <- factor(df_traj$ED_highestgrade)

table(df_traj$ED_highestgrade)

   Bach or Assoc degree       Did not finish HS    HS Grad/Some College Post-graduate education 
                    695                     267                    1321                     189 


Re-level marriage category

#relevel marrital status category
#marital status 1-married 2-separated 3-divorced 4-annulled 5-widowed 6-single
#4. marriage - combine 2+3+4+5 as a single category

df_traj <- df_traj %>%
  mutate(ED_Marital = case_when(
    ED_Marital == "1" ~ "Married",
    ED_Marital == "2" ~ "Divorced/Widowed",
    ED_Marital == "3" ~ "Divorced/Widowed",
    ED_Marital == "4" ~ "Divorced/Widowed",
    ED_Marital == "5" ~ "Divorced/Widowed",
    ED_Marital == "6" ~ "Single",
    TRUE ~ as.character(ED_Marital)  # Keeps any other values unchanged
  ))

# Convert to factor
df_traj$ED_Marital <- factor(df_traj$ED_Marital)

table(df_traj$ED_Marital)

Divorced/Widowed          Married           Single 
             446              539             1483 


#relevel ED_RaceEthCode
#1 = Hispanuic, 2 = NH White, 3 = NH Black, 4 = Other
df_traj <- df_traj %>%
  mutate(ED_RaceEthCode = case_when(
    ED_RaceEthCode == "1" ~ "Hispanic",
    ED_RaceEthCode == "2" ~ "White",
    ED_RaceEthCode == "3" ~ "Black",
    ED_RaceEthCode == "4" ~ "Other",
    TRUE ~ as.character(ED_RaceEthCode)  # Keeps any other values unchanged
  ))

#convert to factor
df_traj$ED_RaceEthCode <- factor(df_traj$ED_RaceEthCode)

Subset to final df for analysis

Subset df_traj to our final df that will be used for model analysis, keep only the features needed

df <- df_traj %>%
  select(Pain_Class,ED_Age, Site_New, ED_RaceEthCode, ED_GenderBirthCert, ADI_NatRank, CTQ_Total, 
         BMI, PRE_Pain_MdSv, WK2_EmploymentCode, ED_Marital, ED_highestgrade, 
         ED_Concussion, ED_Event_BroadClass, ED_PDI_RS, WK2_CTQSF_PhyAbu_RS, WK2_CTQSF_EmoAbu_RS, WK2_CTQSF_SexAbu_RS, WK2_CTQSF_PhyNeg_RS, WK2_CTQSF_EmoNeg_RS, WK2_Bullying_Total)


Add the CTQ triad score that is a combination of bullying, physical abuse, and emotional abuse scores

#add combination CTQ score
df$CTQ_Triad <- df$WK2_Bullying_Total + df$WK2_CTQSF_PhyAbu_RS + df$WK2_CTQSF_EmoAbu_RS

#print the rows that have NA in the CTQ triad
df %>% filter(is.na(CTQ_Triad))
#Confirms that for the CTQ triad, if any of the additive features contain NA, then the final score is NA
#make all of df[,c(2,6:8)]) numeric
df[,c(2,6:8)] <- lapply(df[,c(2,6:8)], as.numeric)


Binary scores for later models

df$Bullying_Any <- ifelse(df$WK2_Bullying_Total > 0, 1, 0)
df$PhyAbu_Any <- ifelse(df$WK2_CTQSF_PhyAbu_RS > 0, 1, 0)
df$EmoAbu_Any <- ifelse(df$WK2_CTQSF_EmoAbu_RS > 0, 1, 0)
df$SexAbu_Any <- ifelse(df$WK2_CTQSF_SexAbu_RS > 0, 1, 0)
df$PhyNeg_Any <- ifelse(df$WK2_CTQSF_PhyNeg_RS > 0, 1, 0)
df$EmoNeg_Any <- ifelse(df$WK2_CTQSF_EmoNeg_RS > 0, 1, 0)
df$CTQ_Any <- ifelse(df$CTQ_Total > 0, 1, 0)

Z-transform scaling

#scale
df_z <- df %>% mutate(across(where(is.numeric), ~ scale(.)))

#summary(df_z)



Preliminary Analysis



Summary table of data

suppressMessages(suppressWarnings(
  df %>%
    tbl_summary(statistic = all_continuous() ~ "{mean} ({sd})", 
              digits = all_continuous() ~ 2) ))
Characteristic N = 2,4801
Pain_Class
    low 1,070 (43%)
    high 352 (14%)
    moderate 590 (24%)
    moderate recovery 468 (19%)
ED_Age 36.09 (13.31)
Site_New
    Midwest 960 (39%)
    NorthEast 1,053 (42%)
    SouthEast 467 (19%)
ED_RaceEthCode
    Black 1,213 (49%)
    Hispanic 278 (11%)
    Other 91 (3.7%)
    White 891 (36%)
    Unknown 7
ED_GenderBirthCert
    Female 1,554 (63%)
    Male 926 (37%)
ADI_NatRank 63.93 (27.57)
    Unknown 80
CTQ_Total 9.50 (9.79)
BMI 30.13 (8.32)
    Unknown 158
PRE_Pain_MdSv 777 (31%)
    Unknown 10
WK2_EmploymentCode
    1 1,816 (73%)
    2 65 (2.6%)
    3 55 (2.2%)
    4 96 (3.9%)
    5 446 (18%)
    Unknown 2
ED_Marital
    Divorced/Widowed 446 (18%)
    Married 539 (22%)
    Single 1,483 (60%)
    Unknown 12
ED_highestgrade
    Bach or Assoc degree 695 (28%)
    Did not finish HS 267 (11%)
    HS Grad/Some College 1,321 (53%)
    Post-graduate education 189 (7.6%)
    Unknown 8
ED_Concussion 112 (4.5%)
    Unknown 1
ED_Event_BroadClass
    MVC/Non-motor Collision 1,909 (77%)
    Other 340 (14%)
    Physical/Sexual Abuse 231 (9.3%)
ED_PDI_RS 13.92 (7.24)
    Unknown 139
WK2_CTQSF_PhyAbu_RS
    0 1,391 (56%)
    1 219 (8.8%)
    2 250 (10%)
    3 128 (5.2%)
    4 194 (7.8%)
    5 66 (2.7%)
    6 83 (3.3%)
    7 29 (1.2%)
    8 120 (4.8%)
WK2_CTQSF_EmoAbu_RS
    0 853 (34%)
    1 288 (12%)
    2 323 (13%)
    3 177 (7.1%)
    4 249 (10%)
    5 143 (5.8%)
    6 152 (6.1%)
    7 110 (4.4%)
    8 185 (7.5%)
WK2_CTQSF_SexAbu_RS 1.93 (3.35)
WK2_CTQSF_PhyNeg_RS
    0 1,334 (54%)
    1 231 (9.3%)
    2 277 (11%)
    3 181 (7.3%)
    4 170 (6.9%)
    5 105 (4.2%)
    6 79 (3.2%)
    7 36 (1.5%)
    8 67 (2.7%)
WK2_CTQSF_EmoNeg_RS
    0 1,196 (48%)
    1 167 (6.7%)
    2 301 (12%)
    3 149 (6.0%)
    4 269 (11%)
    5 128 (5.2%)
    6 141 (5.7%)
    7 41 (1.7%)
    8 88 (3.5%)
WK2_Bullying_Total
    0 503 (20%)
    1 273 (11%)
    2 421 (17%)
    3 305 (12%)
    4 377 (15%)
    5 185 (7.5%)
    6 165 (6.7%)
    7 106 (4.3%)
    8 145 (5.8%)
CTQ_Triad 7.08 (6.29)
Bullying_Any 1,977 (80%)
PhyAbu_Any 1,089 (44%)
EmoAbu_Any 1,627 (66%)
SexAbu_Any 867 (35%)
PhyNeg_Any 1,146 (46%)
EmoNeg_Any 1,284 (52%)
CTQ_Any 1,977 (80%)
1 n (%); Mean (SD)

# Ensure columns 16 to 22 are numeric
df[16:22] <- lapply(df[16:22], as.numeric)

# Create the summary table
suppressMessages(suppressWarnings(
  df %>%
    tbl_summary(
      by = Pain_Class, 
      statistic = all_continuous() ~ "{mean} ({sd})", 
      digits = all_continuous() ~ 2
    ) %>% add_p() ))
Characteristic low, N = 1,0701 high, N = 3521 moderate, N = 5901 moderate recovery, N = 4681 p-value2
ED_Age 33.36 (12.52) 40.89 (13.19) 37.61 (13.12) 36.81 (14.00) <0.001
Site_New



0.3
    Midwest 432 (40%) 139 (39%) 216 (37%) 173 (37%)
    NorthEast 441 (41%) 136 (39%) 267 (45%) 209 (45%)
    SouthEast 197 (18%) 77 (22%) 107 (18%) 86 (18%)
ED_RaceEthCode



<0.001
    Black 521 (49%) 210 (60%) 285 (49%) 197 (42%)
    Hispanic 122 (11%) 37 (11%) 77 (13%) 42 (9.0%)
    Other 39 (3.6%) 12 (3.4%) 23 (3.9%) 17 (3.6%)
    White 387 (36%) 93 (26%) 201 (34%) 210 (45%)
    Unknown 1 0 4 2
ED_GenderBirthCert



<0.001
    Female 605 (57%) 237 (67%) 409 (69%) 303 (65%)
    Male 465 (43%) 115 (33%) 181 (31%) 165 (35%)
ADI_NatRank 62.03 (28.04) 70.74 (26.08) 66.28 (26.76) 60.04 (27.52) <0.001
    Unknown 41 8 14 17
CTQ_Total 8.02 (9.02) 12.09 (10.63) 10.75 (10.33) 9.37 (9.54) <0.001
BMI 29.17 (7.95) 32.15 (9.44) 30.95 (8.28) 29.75 (7.93) <0.001
    Unknown 78 21 38 21
PRE_Pain_MdSv 189 (18%) 214 (61%) 251 (43%) 123 (27%) <0.001
    Unknown 2 1 3 4
WK2_EmploymentCode



<0.001
    1 861 (81%) 203 (58%) 409 (69%) 343 (73%)
    2 14 (1.3%) 19 (5.4%) 17 (2.9%) 15 (3.2%)
    3 15 (1.4%) 10 (2.8%) 17 (2.9%) 13 (2.8%)
    4 44 (4.1%) 9 (2.6%) 13 (2.2%) 30 (6.4%)
    5 135 (13%) 111 (32%) 134 (23%) 66 (14%)
    Unknown 1 0 0 1
ED_Marital



<0.001
    Divorced/Widowed 169 (16%) 83 (24%) 122 (21%) 72 (16%)
    Married 215 (20%) 72 (20%) 134 (23%) 118 (25%)
    Single 683 (64%) 197 (56%) 329 (56%) 274 (59%)
    Unknown 3 0 5 4
ED_highestgrade



<0.001
    Bach or Assoc degree 283 (26%) 95 (27%) 173 (29%) 144 (31%)
    Did not finish HS 89 (8.3%) 56 (16%) 78 (13%) 44 (9.4%)
    HS Grad/Some College 609 (57%) 183 (52%) 307 (52%) 222 (48%)
    Post-graduate education 89 (8.3%) 15 (4.3%) 29 (4.9%) 56 (12%)
    Unknown 0 3 3 2
ED_Concussion 46 (4.3%) 12 (3.4%) 29 (4.9%) 25 (5.3%) 0.6
    Unknown 0 0 1 0
ED_Event_BroadClass



0.12
    MVC/Non-motor Collision 814 (76%) 268 (76%) 469 (79%) 358 (76%)
    Other 152 (14%) 40 (11%) 76 (13%) 72 (15%)
    Physical/Sexual Abuse 104 (9.7%) 44 (13%) 45 (7.6%) 38 (8.1%)
ED_PDI_RS 12.49 (7.09) 15.81 (7.33) 15.00 (7.07) 14.49 (7.13) <0.001
    Unknown 43 27 42 27
WK2_CTQSF_PhyAbu_RS




    0 673 (63%) 159 (45%) 292 (49%) 267 (57%)
    1 92 (8.6%) 20 (5.7%) 54 (9.2%) 53 (11%)
    2 94 (8.8%) 44 (13%) 63 (11%) 49 (10%)
    3 50 (4.7%) 22 (6.3%) 36 (6.1%) 20 (4.3%)
    4 66 (6.2%) 37 (11%) 57 (9.7%) 34 (7.3%)
    5 23 (2.1%) 13 (3.7%) 21 (3.6%) 9 (1.9%)
    6 27 (2.5%) 14 (4.0%) 28 (4.7%) 14 (3.0%)
    7 11 (1.0%) 4 (1.1%) 8 (1.4%) 6 (1.3%)
    8 34 (3.2%) 39 (11%) 31 (5.3%) 16 (3.4%)
WK2_CTQSF_EmoAbu_RS



<0.001
    0 447 (42%) 92 (26%) 174 (29%) 140 (30%)
    1 136 (13%) 30 (8.5%) 53 (9.0%) 69 (15%)
    2 132 (12%) 42 (12%) 81 (14%) 68 (15%)
    3 71 (6.6%) 29 (8.2%) 48 (8.1%) 29 (6.2%)
    4 100 (9.3%) 30 (8.5%) 62 (11%) 57 (12%)
    5 46 (4.3%) 25 (7.1%) 42 (7.1%) 30 (6.4%)
    6 49 (4.6%) 30 (8.5%) 43 (7.3%) 30 (6.4%)
    7 36 (3.4%) 21 (6.0%) 37 (6.3%) 16 (3.4%)
    8 53 (5.0%) 53 (15%) 50 (8.5%) 29 (6.2%)
WK2_CTQSF_SexAbu_RS 1.43 (2.94) 2.63 (3.87) 2.37 (3.65) 2.00 (3.24) <0.001
WK2_CTQSF_PhyNeg_RS



0.11
    0 610 (57%) 175 (50%) 293 (50%) 256 (55%)
    1 95 (8.9%) 33 (9.4%) 58 (9.8%) 45 (9.6%)
    2 110 (10%) 38 (11%) 78 (13%) 51 (11%)
    3 67 (6.3%) 32 (9.1%) 48 (8.1%) 34 (7.3%)
    4 63 (5.9%) 31 (8.8%) 41 (6.9%) 35 (7.5%)
    5 35 (3.3%) 15 (4.3%) 33 (5.6%) 22 (4.7%)
    6 35 (3.3%) 14 (4.0%) 19 (3.2%) 11 (2.4%)
    7 15 (1.4%) 6 (1.7%) 11 (1.9%) 4 (0.9%)
    8 40 (3.7%) 8 (2.3%) 9 (1.5%) 10 (2.1%)
WK2_CTQSF_EmoNeg_RS



0.13
    0 545 (51%) 163 (46%) 263 (45%) 225 (48%)
    1 72 (6.7%) 24 (6.8%) 47 (8.0%) 24 (5.1%)
    2 133 (12%) 37 (11%) 76 (13%) 55 (12%)
    3 68 (6.4%) 20 (5.7%) 32 (5.4%) 29 (6.2%)
    4 91 (8.5%) 47 (13%) 78 (13%) 53 (11%)
    5 45 (4.2%) 18 (5.1%) 37 (6.3%) 28 (6.0%)
    6 55 (5.1%) 23 (6.5%) 35 (5.9%) 28 (6.0%)
    7 15 (1.4%) 6 (1.7%) 8 (1.4%) 12 (2.6%)
    8 46 (4.3%) 14 (4.0%) 14 (2.4%) 14 (3.0%)
WK2_Bullying_Total



<0.001
    0 256 (24%) 62 (18%) 114 (19%) 71 (15%)
    1 135 (13%) 29 (8.2%) 54 (9.2%) 55 (12%)
    2 194 (18%) 42 (12%) 91 (15%) 94 (20%)
    3 137 (13%) 37 (11%) 71 (12%) 60 (13%)
    4 151 (14%) 55 (16%) 93 (16%) 78 (17%)
    5 56 (5.2%) 36 (10%) 57 (9.7%) 36 (7.7%)
    6 63 (5.9%) 26 (7.4%) 44 (7.5%) 32 (6.8%)
    7 39 (3.6%) 24 (6.8%) 27 (4.6%) 16 (3.4%)
    8 39 (3.6%) 41 (12%) 39 (6.6%) 26 (5.6%)
CTQ_Triad 5.90 (5.84) 9.33 (7.09) 7.96 (6.47) 6.98 (5.78) <0.001
Bullying_Any 814 (76%) 290 (82%) 476 (81%) 397 (85%) <0.001
PhyAbu_Any 397 (37%) 193 (55%) 298 (51%) 201 (43%) <0.001
EmoAbu_Any 623 (58%) 260 (74%) 416 (71%) 328 (70%) <0.001
SexAbu_Any 297 (28%) 148 (42%) 238 (40%) 184 (39%) <0.001
PhyNeg_Any 460 (43%) 177 (50%) 297 (50%) 212 (45%) 0.012
EmoNeg_Any 525 (49%) 189 (54%) 327 (55%) 243 (52%) 0.078
CTQ_Any 805 (75%) 301 (86%) 490 (83%) 381 (81%) <0.001
1 Mean (SD); n (%)
2 Kruskal-Wallis rank sum test; Pearson’s Chi-squared test


Category distribution plots

p1 <- ggplot(df_traj %>% filter(!is.na(ED_Event_BroadClass)), aes(x = ED_Event_BroadClass, fill=ED_Event_BroadClass)) +
  geom_bar(color="black") + theme(legend.position = "none") +
    geom_text(stat = 'count', aes(label = ..count..), vjust = 1.5) +
  labs(title = "Counts of Trauma Type", y = "Count") + gghisto2

p2 <- ggplot(df_traj %>% filter(!is.na(ED_highestgrade)), aes(x = ED_highestgrade, fill=ED_highestgrade)) +
  geom_bar(color="black") + theme(legend.position = "none") +
    geom_text(stat = 'count', aes(label = ..count..), vjust = 1.5) +
  labs(title = "Counts of Education",
       y = "Count") + gghisto2

p3 <- ggplot(df_traj %>% filter(!is.na(ED_Marital)), aes(x = ED_Marital, fill=ED_Marital)) +
  geom_bar(color="black") + theme(legend.position = "none") +
    geom_text(stat = 'count', aes(label = ..count..), vjust = 1.5) +
  labs(title = "Counts of Marital Status",
       y = "Count")  + gghisto2

p4 <- ggplot(df_traj %>% filter(!is.na(Pain_Class)), aes(x = Pain_Class, fill=Pain_Class)) +
  geom_bar(color="black") + theme(legend.position = "none") +
    geom_text(stat = 'count', aes(label = ..count..), vjust = 1.5) +
  labs(title = "Counts of Pain Class",
       y = "Count") + gghisto2

grid.arrange(p1, p2, p3, p4, ncol = 2)


SEX x CTQ stats+plots

#Look at the relationship between ED_GenderBirthCert and CTQ_Total
t.test(CTQ_Total ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  CTQ_Total by ED_GenderBirthCert
t = 5.9715, df = 2265.3, p-value = 2.722e-09
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 1.535354 3.036842
sample estimates:
mean in group Female   mean in group Male 
           10.355212             8.069114 
p1 <- ggplot(df, aes(x = ED_GenderBirthCert, y = CTQ_Total)) +
  geom_boxplot(lwd = .9, fill=c("pink","skyblue")) +
  labs(title = "CTQ Composite by Gender",
       x = " ",
       y = "CTQ Composite") + gghisto

# Sexual assault CTQ x Sex
t.test(WK2_CTQSF_SexAbu_RS ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  WK2_CTQSF_SexAbu_RS by ED_GenderBirthCert
t = 10.874, df = 2462.5, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 1.095160 1.577066
sample estimates:
mean in group Female   mean in group Male 
            2.431145             1.095032 
p2 <- ggplot(df, aes(x = ED_GenderBirthCert, y = WK2_CTQSF_SexAbu_RS)) +
  geom_boxplot(lwd = .9, fill=c("pink","skyblue")) +
  labs(title = "Sexual Abuse by Gender",
       x = " ",
       y = "Sexual Abuse Score") + gghisto

# physical abuse x Sex
t.test(WK2_CTQSF_PhyAbu_RS ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  WK2_CTQSF_PhyAbu_RS by ED_GenderBirthCert
t = 3.8607, df = 2199.9, p-value = 0.0001163
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 0.1738492 0.5327784
sample estimates:
mean in group Female   mean in group Male 
            1.692407             1.339093 
p3 <- ggplot(df, aes(x = ED_GenderBirthCert, y = WK2_CTQSF_PhyAbu_RS)) +
  geom_boxplot(lwd = .9, fill=c("pink","skyblue")) +
  labs(title = "Physical Abuse by Gender",
       x = " ",
       y = "Physical Abuse Score") + gghisto

# physical neglect x sex
t.test(WK2_CTQSF_PhyNeg_RS ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  WK2_CTQSF_PhyNeg_RS by ED_GenderBirthCert
t = -2.0304, df = 1876.9, p-value = 0.04246
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 -0.359130499 -0.006219423
sample estimates:
mean in group Female   mean in group Male 
            1.462033             1.644708 
p4 <- ggplot(df, aes(x = ED_GenderBirthCert, y = WK2_CTQSF_PhyNeg_RS)) +
  geom_boxplot(lwd = .9, fill=c("pink","skyblue")) +
  labs(title = "Physical Neglect by Gender",
       x = " ",
       y = "Physical Neglect Score") + gghisto

#emotional abuse x sex
t.test(WK2_CTQSF_EmoAbu_RS ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  WK2_CTQSF_EmoAbu_RS by ED_GenderBirthCert
t = 8.046, df = 2232.8, p-value = 1.375e-15
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 0.6276099 1.0321326
sample estimates:
mean in group Female   mean in group Male 
            2.865508             2.035637 
p5 <- ggplot(df, aes(x = ED_GenderBirthCert, y = WK2_CTQSF_EmoAbu_RS)) +
  geom_boxplot(lwd = .9, fill=c("pink","skyblue")) +
  labs(title = "Emotional Abuse by Gender",
       x = " ",
       y = "Emotional Abuse Score") + gghisto

#emotional neglect x sex
t.test(WK2_CTQSF_EmoNeg_RS ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  WK2_CTQSF_EmoNeg_RS by ED_GenderBirthCert
t = -0.51873, df = 1971.3, p-value = 0.604
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 -0.2415469  0.1404965
sample estimates:
mean in group Female   mean in group Male 
            1.904118             1.954644 
p6 <- ggplot(df, aes(x = ED_GenderBirthCert, y = WK2_CTQSF_EmoNeg_RS)) +
  geom_boxplot(lwd = .9, fill=c("pink","skyblue")) +
  labs(title = "Emotional Neglect by Gender",
       x = " ",
       y = "Emotional Neglect Score") + gghisto

#bullying x sex
p7 <- ggplot(df, aes(x = ED_GenderBirthCert, y = WK2_Bullying_Total)) +
  geom_boxplot(lwd = .9, fill=c("pink","skyblue")) +
  labs(title = "Bullying by Gender",
       x = " ",
       y = "Bullying Score") + gghisto

ctq.sex.plots <- grid.arrange(p1, p2, p3, p4, p5, p6, p7, ncol = 3)


#save these plots to a pdf
#ggsave("ctq.sex.plots.pdf", ctq.sex.plots, width = 12, height = 10)


#welches t test for sex differences in bullying
t.test(WK2_Bullying_Total ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  WK2_Bullying_Total by ED_GenderBirthCert
t = 0.093303, df = 2028.3, p-value = 0.9257
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 -0.1815477  0.1996852
sample estimates:
mean in group Female   mean in group Male 
            2.969112             2.960043 


RACE x CTQ stats

#Look at the relationship between RACE and each CTQ category
# List of CTQ categories and their corresponding columns
ctq_tests <- list(
  CTQ_Total = "CTQ_Total",
  Physical_Abuse = "WK2_CTQSF_PhyAbu_RS",
  Physical_Neglect = "WK2_CTQSF_PhyNeg_RS",
  Emotional_Abuse = "WK2_CTQSF_EmoAbu_RS",
  Emotional_Neglect = "WK2_CTQSF_EmoNeg_RS",
  Sexual_Abuse = "WK2_CTQSF_SexAbu_RS",
  Bullying = "WK2_Bullying_Total"
)

# Initialize a vector to store significant results
significant_tests <- c()

# Perform Kruskal-Wallis test and Dunn's test for each CTQ category
for (name in names(ctq_tests)) {
  cat("Testing:", name, "\n")
  kw_test <- kruskal.test(df[[ctq_tests[[name]]]] ~ df$ED_RaceEthCode)
  print(kw_test)  
  if (kw_test$p.value < 0.05) {
    cat("Kruskal-Wallis test significant (p < 0.05). Performing Dunn's test...\n")
    dunn_result <- dunn.test(df[[ctq_tests[[name]]]], df$ED_RaceEthCode, method = "bh") 
    print(dunn_result)
    significant_tests <- c(significant_tests, name)
  } else {
    cat("Kruskal-Wallis test not significant (p >= 0.05). Skipping Dunn's test.\n")
  }
  cat("\n") 
}
Testing: CTQ_Total 

    Kruskal-Wallis rank sum test

data:  df[[ctq_tests[[name]]]] by df$ED_RaceEthCode
Kruskal-Wallis chi-squared = 7.7918, df = 3, p-value = 0.05052

Kruskal-Wallis test not significant (p >= 0.05). Skipping Dunn's test.

Testing: Physical_Abuse 

    Kruskal-Wallis rank sum test

data:  df[[ctq_tests[[name]]]] by df$ED_RaceEthCode
Kruskal-Wallis chi-squared = 7.5855, df = 3, p-value = 0.0554

Kruskal-Wallis test not significant (p >= 0.05). Skipping Dunn's test.

Testing: Physical_Neglect 

    Kruskal-Wallis rank sum test

data:  df[[ctq_tests[[name]]]] by df$ED_RaceEthCode
Kruskal-Wallis chi-squared = 16.152, df = 3, p-value = 0.001056

Kruskal-Wallis test significant (p < 0.05). Performing Dunn's test...
  Kruskal-Wallis rank sum test

data: x and group
Kruskal-Wallis chi-squared = 16.1517, df = 3, p-value = 0

                           Comparison of x by group                            
                             (Benjamini-Hochberg)                              
Col Mean-|
Row Mean |      Black   Hispanic      Other
---------+---------------------------------
Hispanic |  -2.334541
         |    0.0196*
         |
   Other |  -0.005352   1.280521
         |     0.4979     0.1503
         |
   White |   2.476521   3.850210   0.998172
         |    0.0199*    0.0004*     0.1909

alpha = 0.05
Reject Ho if p <= alpha/2
$chi2
[1] 16.1517

$Z
[1] -2.33454133 -0.00535235  1.28052161  2.47652115  3.85021063  0.99817227

$P
[1] 9.783697e-03 4.978647e-01 1.001809e-01 6.633488e-03 5.900814e-05 1.590979e-01

$P.adjusted
[1] 0.0195673948 0.4978647316 0.1502713109 0.0199004649 0.0003540489 0.1909174969

$comparisons
[1] "Black - Hispanic" "Black - Other"    "Hispanic - Other" "Black - White"    "Hispanic - White" "Other - White"   


Testing: Emotional_Abuse 

    Kruskal-Wallis rank sum test

data:  df[[ctq_tests[[name]]]] by df$ED_RaceEthCode
Kruskal-Wallis chi-squared = 21.301, df = 3, p-value = 9.116e-05

Kruskal-Wallis test significant (p < 0.05). Performing Dunn's test...
  Kruskal-Wallis rank sum test

data: x and group
Kruskal-Wallis chi-squared = 21.3011, df = 3, p-value = 0

                           Comparison of x by group                            
                             (Benjamini-Hochberg)                              
Col Mean-|
Row Mean |      Black   Hispanic      Other
---------+---------------------------------
Hispanic |  -2.330242
         |     0.0297
         |
   Other |  -0.628512   0.717342
         |     0.3178     0.3549
         |
   White |  -4.472250  -0.616834  -1.172279
         |    0.0000*     0.2687     0.2411

alpha = 0.05
Reject Ho if p <= alpha/2
$chi2
[1] 21.30109

$Z
[1] -2.3302421 -0.6285124  0.7173426 -4.4722501 -0.6168349 -1.1722795

$P
[1] 9.896680e-03 2.648341e-01 2.365814e-01 3.870042e-06 2.686718e-01 1.205424e-01

$P.adjusted
[1] 2.969004e-02 3.178010e-01 3.548720e-01 2.322025e-05 2.686718e-01 2.410849e-01

$comparisons
[1] "Black - Hispanic" "Black - Other"    "Hispanic - Other" "Black - White"    "Hispanic - White" "Other - White"   


Testing: Emotional_Neglect 

    Kruskal-Wallis rank sum test

data:  df[[ctq_tests[[name]]]] by df$ED_RaceEthCode
Kruskal-Wallis chi-squared = 6.728, df = 3, p-value = 0.08109

Kruskal-Wallis test not significant (p >= 0.05). Skipping Dunn's test.

Testing: Sexual_Abuse 

    Kruskal-Wallis rank sum test

data:  df[[ctq_tests[[name]]]] by df$ED_RaceEthCode
Kruskal-Wallis chi-squared = 9.7111, df = 3, p-value = 0.02119

Kruskal-Wallis test significant (p < 0.05). Performing Dunn's test...
  Kruskal-Wallis rank sum test

data: x and group
Kruskal-Wallis chi-squared = 9.7111, df = 3, p-value = 0.02

                           Comparison of x by group                            
                             (Benjamini-Hochberg)                              
Col Mean-|
Row Mean |      Black   Hispanic      Other
---------+---------------------------------
Hispanic |  -0.965636
         |     0.3342
         |
   Other |   0.415519   0.905601
         |     0.3389     0.2739
         |
   White |   2.570674   2.585689   0.620256
         |    0.0152*    0.0292*     0.3211

alpha = 0.05
Reject Ho if p <= alpha/2
$chi2
[1] 9.711097

$Z
[1] -0.9656370  0.4155199  0.9056014  2.5706744  2.5856895  0.6202568

$P
[1] 0.167112936 0.338880672 0.182573441 0.005075035 0.004859222 0.267544376

$P.adjusted
[1] 0.33422587 0.33888067 0.27386016 0.01522510 0.02915533 0.32105325

$comparisons
[1] "Black - Hispanic" "Black - Other"    "Hispanic - Other" "Black - White"    "Hispanic - White" "Other - White"   


Testing: Bullying 

    Kruskal-Wallis rank sum test

data:  df[[ctq_tests[[name]]]] by df$ED_RaceEthCode
Kruskal-Wallis chi-squared = 14.311, df = 3, p-value = 0.002511

Kruskal-Wallis test significant (p < 0.05). Performing Dunn's test...
  Kruskal-Wallis rank sum test

data: x and group
Kruskal-Wallis chi-squared = 14.3111, df = 3, p-value = 0

                           Comparison of x by group                            
                             (Benjamini-Hochberg)                              
Col Mean-|
Row Mean |      Black   Hispanic      Other
---------+---------------------------------
Hispanic |  -1.381831
         |     0.1670
         |
   Other |   0.107357   0.857417
         |     0.4573     0.2347
         |
   White |  -3.684295  -1.028753  -1.583135
         |    0.0007*     0.2277     0.1701

alpha = 0.05
Reject Ho if p <= alpha/2
$chi2
[1] 14.31115

$Z
[1] -1.3818314  0.1073575  0.8574171 -3.6842953 -1.0287538 -1.5831355

$P
[1] 0.0835117408 0.4572526697 0.1956072094 0.0001146681 0.1517976943 0.0566952918

$P.adjusted
[1] 0.1670234816 0.4572526697 0.2347286513 0.0006880087 0.2276965414 0.1700858754

$comparisons
[1] "Black - Hispanic" "Black - Other"    "Hispanic - Other" "Black - White"    "Hispanic - White" "Other - White"   
# Print names of significant CTQ categories
if (length(significant_tests) > 0) {
  cat("CTQ categories with significant Kruskal-Wallis test and corresponding Dunn's test results:\n")
  cat(paste(significant_tests, collapse = "\n"))
} else {
  cat("No CTQ categories with significant Kruskal-Wallis test.\n")
}
CTQ categories with significant Kruskal-Wallis test and corresponding Dunn's test results:
Physical_Neglect
Emotional_Abuse
Sexual_Abuse
Bullying
library(knitr)
library(gt)

df %>%
  group_by(ED_RaceEthCode) %>%
  summarize(
    Mean_CTQ_Tot = mean(CTQ_Total, na.rm = TRUE),
    SD_CTQ_Tot = sd(CTQ_Total, na.rm = TRUE),
    Mean_Phys_Abuse = mean(WK2_CTQSF_PhyAbu_RS, na.rm = TRUE),
    SD_Phys_Abuse = sd(WK2_CTQSF_PhyAbu_RS, na.rm = TRUE),
    Mean_Phys_Neglect = mean(WK2_CTQSF_PhyNeg_RS, na.rm = TRUE),
    SD_Phys_Neglect = sd(WK2_CTQSF_PhyNeg_RS, na.rm = TRUE),
    Mean_Emo_Abuse = mean(WK2_CTQSF_EmoAbu_RS, na.rm = TRUE),
    SD_Emo_Abuse = sd(WK2_CTQSF_EmoAbu_RS, na.rm = TRUE),
    Mean_Emo_Neglect = mean(WK2_CTQSF_EmoNeg_RS, na.rm = TRUE),
    SD_Emo_Neglect = sd(WK2_CTQSF_EmoNeg_RS, na.rm = TRUE),
    Mean_Sex_Abuse = mean(WK2_CTQSF_SexAbu_RS, na.rm = TRUE),
    SD_Sex_Abuse = sd(WK2_CTQSF_SexAbu_RS, na.rm = TRUE),
    Mean_Bullying = mean(WK2_Bullying_Total, na.rm = TRUE),
    SD_Bullying = sd(WK2_Bullying_Total, na.rm = TRUE)
  ) %>%
  gt() %>%
  tab_header(
    title = "Mean and Standard Deviation of CTQ Scores by Race"
  ) %>%
  fmt_number(
    columns = vars(starts_with("Mean"), starts_with("SD")),
    decimals = 2
  )
Mean and Standard Deviation of CTQ Scores by Race
ED_RaceEthCode Mean_CTQ_Tot SD_CTQ_Tot Mean_Phys_Abuse SD_Phys_Abuse Mean_Phys_Neglect SD_Phys_Neglect Mean_Emo_Abuse SD_Emo_Abuse Mean_Emo_Neglect SD_Emo_Neglect Mean_Sex_Abuse SD_Sex_Abuse Mean_Bullying SD_Bullying
Black 9.62 10.03 1.54 2.30 1.65 2.31 2.33 2.57 1.98 2.48 2.13 3.56 2.83 2.43
Hispanic 10.91 10.37 1.90 2.48 1.82 2.16 2.75 2.72 2.18 2.34 2.26 3.62 3.04 2.44
Other 9.44 9.15 1.68 2.35 1.62 2.24 2.48 2.59 1.91 2.37 1.75 2.86 2.77 2.34
White 8.93 9.32 1.48 2.25 1.27 1.86 2.81 2.68 1.78 2.18 1.58 2.97 3.16 2.26
NA 6.71 7.61 0.57 1.13 1.00 1.15 2.29 3.09 1.29 1.80 1.57 3.36 2.29 3.15


ADI and PDI

library(ggpubr)

cor_results <- list(
  "ADI vs PDI" = cor.test(df$ADI_NatRank, df$ED_PDI_RS, use="complete.obs", method = "spearman"),
  "ADI vs CTQ" = cor.test(df$ADI_NatRank, df$CTQ_Total, use="complete.obs", method = "spearman"),
  "PDI vs CTQ" = cor.test(df$ED_PDI_RS, df$CTQ_Total, use="complete.obs", method = "spearman"))

#print the number of complete cases for each of ADI, PDI, and CTQ
sum(complete.cases(df$ADI_NatRank))
[1] 2400
sum(complete.cases(df$ED_PDI_RS))
[1] 2341
sum(complete.cases(df$CTQ_Total))
[1] 2480
#print the number of complete cases overlapping between PDI and ADI
sum(complete.cases(df$ADI_NatRank, df$ED_PDI_RS))
[1] 2263
data.frame(
  Comparison = names(cor_results),
  rho = sapply(cor_results, function(x) round(x$estimate, 6)),
  p_value = sapply(cor_results, function(x) round(x$p.value, 6)))
#plot of PDI x CTQ
p1 <- ggplot(df, aes(x = ED_PDI_RS, y = CTQ_Total)) +
  geom_point(alpha = 0.3, size=3) +  
  geom_smooth(method = "lm", se = FALSE, color = "magenta3", lwd=3) +  
  stat_cor(method = "spearman", label.x = 3, label.y = max(df$CTQ_Total)-2) + 
  labs(title = "Scatter Plot of PDI vs CTQ Total",
       x = "PDI", y = "CTQ Total") + gghisto

#Plot of ADI x CTQ
p2 <- ggplot(df, aes(x = ADI_NatRank, y = CTQ_Total)) +
  geom_point(alpha = 0.3, size=3) +  
  geom_smooth(method = "lm", se = FALSE, color = "purple3", lwd=3) +  
  stat_cor(method = "spearman", label.x = 3, label.y = max(df$CTQ_Total)-2) + 
  labs(title = "Scatter Plot of ADI vs CTQ Total",
       x = "ADI", y = "CTQ Total") + gghisto

grid.arrange(p1,p2)
`geom_smooth()` using formula = 'y ~ x'
`geom_smooth()` using formula = 'y ~ x'

CTQ x RACE plots

p7 <- ggplot(df %>% filter(!is.na(ED_RaceEthCode)), aes(x = ED_RaceEthCode, y = CTQ_Total, fill = ED_RaceEthCode)) +
  geom_boxplot(lwd = .9) +
  theme(legend.position = "none") +
  labs(title = "Composite CTQ by Race",
       x = " ", y = "CTQ Composite Score") + gghisto

# Sexual assault CTQ x race
p8 <- ggplot(df %>% filter(!is.na(ED_RaceEthCode)), aes(x = ED_RaceEthCode, y = WK2_CTQSF_SexAbu_RS, fill = ED_RaceEthCode)) +
  geom_boxplot(lwd = .9) +
  theme(legend.position = "none") +
  labs(title = "Sexual Abuse by Race",
       x = " ", y = "Sexual Abuse Score") + gghisto

# physical abuse x race
p9 <- ggplot(df %>% filter(!is.na(ED_RaceEthCode)), aes(x = ED_RaceEthCode, y = WK2_CTQSF_PhyAbu_RS, fill = ED_RaceEthCode)) +
  geom_boxplot(lwd = .9) +
  theme(legend.position = "none") +
  labs(title = "Physical Abuse by Race",
       x = " ", y = "Physical Abuse Score") + gghisto

# physical neglect x race
p10 <- ggplot(df %>% filter(!is.na(ED_RaceEthCode)), aes(x = ED_RaceEthCode, y = WK2_CTQSF_PhyNeg_RS, fill = ED_RaceEthCode)) +
  geom_boxplot(lwd = .9) +
  theme(legend.position = "none") +
  labs(title = "Physical Neglect by Race",
       x = " ", y = "Physical Neglect Score") + gghisto

#emotional abuse x race
p11 <- ggplot(df %>% filter(!is.na(ED_RaceEthCode)), aes(x = ED_RaceEthCode, y = WK2_CTQSF_EmoAbu_RS, fill = ED_RaceEthCode)) + geom_boxplot(lwd = .9) +
theme(legend.position = "none") +
  labs(title = "Emotional Abuse by Race",
       x = " ", y = "Emotional Abuse Score") + gghisto

#emotional neglect x race
p12 <- ggplot(df %>% filter(!is.na(ED_RaceEthCode)), aes(x = ED_RaceEthCode, y = WK2_CTQSF_EmoNeg_RS, fill = ED_RaceEthCode)) + geom_boxplot(lwd = .9) + labs(title = "Emotional Neglect by Race",
       x = " ", y = "Emotional Neglect Score") + 
  theme(legend.position = "none") + gghisto

#bullying x race
p13 <- ggplot(df %>% filter(!is.na(ED_RaceEthCode)), aes(x = ED_RaceEthCode, y = WK2_Bullying_Total, fill = ED_RaceEthCode)) + geom_boxplot(lwd = .9) + labs(title = "Bullying by Race", 
       x = " ", y = "Bullying Score") + 
  theme(legend.position = "none") + gghisto                                                                                                                                                         
                                                                                                                                    

ctq.race.plots_simple <- grid.arrange(p7, p8, p9, p10, p11, p12, p13, ncol = 3) 


#save as pdf
#ggsave("ctq.race.plots_simple.pdf", ctq.race.plots_simple, width = 12, height = 10)

Plots for supplementary section of paper

  1. one out put of two graphs: one graph with CTQ total by sex, and other graph is CTQ total by race. and add sig notation for sex, ns for race
  2. make graphs of subtypes (incl bullying instead of ctq total) so we have 2x3 table and include asterisks for sig
library(ggsignif)


ggplot(df, aes(x = ED_GenderBirthCert, y = CTQ_Total, fill = ED_GenderBirthCert)) +
  geom_boxplot() +
  labs(title = "Boxplot of CTQ Total by Sex",
       x = "Sex",
       y = "CTQ Total") +
  scale_fill_manual(values = c("pink", "skyblue")) + gghisto


#ttest of ctq total by sex
t.test(CTQ_Total ~ ED_GenderBirthCert, data = df)

    Welch Two Sample t-test

data:  CTQ_Total by ED_GenderBirthCert
t = 5.9715, df = 2265.3, p-value = 2.722e-09
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 1.535354 3.036842
sample estimates:
mean in group Female   mean in group Male 
           10.355212             8.069114 

Descriptive stats for paper

#calculate the % of participants reported experiencing at least one instance of any type of ELA (i.e. either CTQ≥1 or childhood Bullying ≥1)  and the M (SD) for composite CTQ
df %>% 
  summarize(perc_any_ELA = mean(CTQ_Total >= 1 | WK2_Bullying_Total >= 1, na.rm = TRUE),
            mean_CTQ = mean(CTQ_Total, na.rm = TRUE),
            sd_CTQ = sd(CTQ_Total, na.rm = TRUE))

how many people had at a score of 1 or more for at least two different CTQ subtypes

# Create a logical matrix where TRUE indicates a score of 1 or more
logical_matrix <- df %>%
  select(WK2_CTQSF_PhyAbu_RS, WK2_CTQSF_PhyNeg_RS, WK2_CTQSF_EmoAbu_RS, 
         WK2_CTQSF_EmoNeg_RS, WK2_CTQSF_SexAbu_RS, WK2_Bullying_Total) %>%
  mutate(across(everything(), ~ . >= 1))

# Count the number of TRUE values in each row
df$ctq_total_count <- rowSums(logical_matrix)

# Filter individuals with at least 2 CTQ subtypes with scores of 1 or more
sum(df$ctq_total_count >= 2)
[1] 1906
#what is the most common ctq subtype with percentages out of 2480
df %>% 
  select(WK2_CTQSF_PhyAbu_RS, WK2_CTQSF_PhyNeg_RS, WK2_CTQSF_EmoAbu_RS, 
         WK2_CTQSF_EmoNeg_RS, WK2_CTQSF_SexAbu_RS, WK2_Bullying_Total) %>%
  pivot_longer(cols = everything(), names_to = "CTQ_Subtype", values_to = "Score") %>%
  filter(Score >= 1) %>%
  count(CTQ_Subtype) %>%
  arrange(desc(n)) %>%
  mutate(perc = n/2480)
#how many cases in the df had either bullying score 1+ or total CTQ score 1+
df %>% filter(CTQ_Total >= 1 | WK2_Bullying_Total >= 1) %>% nrow()
[1] 2260
#ttest comparing ctq in men vs women
t.test(CTQ_Total ~ ED_GenderBirthCert, data = df)

    Welch Two Sample t-test

data:  CTQ_Total by ED_GenderBirthCert
t = 5.9715, df = 2265.3, p-value = 2.722e-09
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 1.535354 3.036842
sample estimates:
mean in group Female   mean in group Male 
           10.355212             8.069114 
#caclulcate std in addition to means for sex
df %>% 
  group_by(ED_GenderBirthCert) %>% 
  summarize(mean_CTQ = mean(CTQ_Total, na.rm = TRUE),
            sd_CTQ = sd(CTQ_Total, na.rm = TRUE))

#welches t test for sex differences in bullying
t.test(WK2_Bullying_Total ~ ED_GenderBirthCert, data = df,var.equal = FALSE)

    Welch Two Sample t-test

data:  WK2_Bullying_Total by ED_GenderBirthCert
t = 0.093303, df = 2028.3, p-value = 0.9257
alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
95 percent confidence interval:
 -0.1815477  0.1996852
sample estimates:
mean in group Female   mean in group Male 
            2.969112             2.960043 


Correlations table csv

# Define the columns to correlate
columns <- colnames(df)[16:22]

#spearman correlation between bullying and each CTQ type
cor.test(df$WK2_Bullying_Total, df$WK2_CTQSF_PhyAbu_RS, method = "spearman")

    Spearman's rank correlation rho

data:  df$WK2_Bullying_Total and df$WK2_CTQSF_PhyAbu_RS
S = 1315924699, p-value < 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.4823606 
cor.test(df$WK2_Bullying_Total, df$WK2_CTQSF_EmoAbu_RS, method = "spearman")

    Spearman's rank correlation rho

data:  df$WK2_Bullying_Total and df$WK2_CTQSF_EmoAbu_RS
S = 1041136106, p-value < 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
     rho 
0.590453 
cor.test(df$WK2_Bullying_Total, df$WK2_CTQSF_SexAbu_RS, method = "spearman")

    Spearman's rank correlation rho

data:  df$WK2_Bullying_Total and df$WK2_CTQSF_SexAbu_RS
S = 1629551991, p-value < 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.3589905 
cor.test(df$WK2_Bullying_Total, df$WK2_CTQSF_PhyNeg_RS, method = "spearman")

    Spearman's rank correlation rho

data:  df$WK2_Bullying_Total and df$WK2_CTQSF_PhyNeg_RS
S = 2093431990, p-value < 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.1765161 
cor.test(df$WK2_Bullying_Total, df$WK2_CTQSF_EmoNeg_RS, method = "spearman")

    Spearman's rank correlation rho

data:  df$WK2_Bullying_Total and df$WK2_CTQSF_EmoNeg_RS
S = 1937158406, p-value < 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.2379887 
# Function to calculate Spearman correlations, p-values, and number of complete cases
correlation_summary <- function(x, y) {
  cor_test <- cor.test(df[[x]], df[[y]], method = "spearman")
  
  tibble(
    Variable1 = x,
    Variable2 = y,
    Rho = cor_test$estimate,
    P_Value = cor_test$p.value,
  )
}

# Create a summary table
all_ctq_correlations <- expand_grid(Variable1 = columns, Variable2 = columns) %>%
  filter(Variable1 != Variable2) %>%
  pmap_dfr(~ correlation_summary(..1, ..2))

#save ctq correlations to a csv
write.csv(all_ctq_correlations, "all_ELA_correlations_for_Lauren.csv")

Heatmap of correlations

# Compute the correlation matrix
cor_matrix <- cor(df[,c(16:22)], use = "complete.obs", method="spearman")

#make a table that gives the correlation rho, p-value, and sample size for each spearman correlation
cor_table <- cor.mtest(df[,c(16:22)], conf.level = 0.95, method = "spearman")
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
Warning in cor.test.default(x = mat[, i], y = mat[, j], ...) :
  Cannot compute exact p-value with ties
#save cor_matrix as a csv
write.csv(cor_matrix, "ELA_cor_matrix_for_Lauren.csv")

# Plot the correlation matrix
ggcorrplot(cor_matrix, lab = TRUE)


corrplot(cor_matrix, method = "color", type = "upper",
         tl.col = "black", tl.srt = 45, addCoef.col = "black",
         col = colorRampPalette(c("blue", "white", "red"))(200))

Explore data validity

Examine data distributions

Models

Model 1: Base Model

Main multi-nominal regression model with CTQ as a predictor variable, including our standard covariates (same in linear models), and latent pain trajectories as the dependent variables. Model 2 is this with extra features. extract marginal means from base model for making graphs

#pain trajectory ~ age + sex + race + site + CTQ
m1 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Total, data = df)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3121.158684
iter  20 value 3081.890408
iter  30 value 3080.574683
final  value 3080.567070 
converged
#view output
tidy(m1, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5))) 
#examine variance inflation factor to assess collinearity
vif(m1)
Warning in vif.default(m1) : No intercept: vifs may not be sensible.
                        GVIF Df GVIF^(1/(2*Df))
ED_Age             12.103902  1        3.479066
Site_New            3.792135  2        1.395471
ED_RaceEthCode      3.031107  3        1.203003
ED_GenderBirthCert  1.753030  1        1.324021
CTQ_Total           2.846424  1        1.687135

Variance Inflation Factor (VIF) is used to detect multicollinearity. VIF > 10: Indicates high multicollinearity that might be problematic. VIF between 5 and 10: Moderate multicollinearity that might need addressing. VIF < 5: Generally considered acceptable.


Repeat this but with the z transformed data

# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3121.158684
iter  20 value 3081.890408
iter  30 value 3080.574683
final  value 3080.567070 
converged

Model 2: Additional Features

m2 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Total + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2728.643818
iter  20 value 2569.897008
iter  30 value 2493.320633
iter  40 value 2482.429441
iter  50 value 2482.132928
final  value 2482.128451 
converged
tidy(m2, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

vif(m2)
Warning in vif.default(m2) : No intercept: vifs may not be sensible.
                         GVIF Df GVIF^(1/(2*Df))
ED_Age              17.705104  1        4.207743
Site_New             4.738180  2        1.475377
ED_RaceEthCode       4.058971  3        1.262998
ED_GenderBirthCert   1.941989  1        1.393553
CTQ_Total            3.011481  1        1.735362
BMI                 18.363059  1        4.285214
PRE_Pain_MdSv        3.067245  1        1.751355
ED_Marital          10.289081  2        1.790994
ADI_NatRank         12.774041  1        3.574079
ED_Event_BroadClass  2.156177  2        1.211772
ED_PDI_RS            7.261573  1        2.694731

Investigate Collineator between categorical variables

# Create a list of categorical variables to test
categorical_vars <- c("ED_GenderBirthCert", "ED_Marital", "ED_RaceEthCode", "ED_Event_BroadClass", "Pain_Class")

# Generate all combinations of categorical variables
combinations <- combn(categorical_vars, 2, simplify = FALSE)

# Function to perform chi-square test and return results
perform_chisq_test <- function(var1, var2, data) {
  table_data <- table(data[[var1]], data[[var2]])
  test_result <- chisq.test(table_data)
  result <- list(
    variables = paste(var1, "vs", var2),
    chi2 = test_result$statistic,
    p_value = test_result$p.value
  )
  return(result)
}

# Perform chi-square tests on all combinations
results <- lapply(combinations, function(vars) perform_chisq_test(vars[1], vars[2], df))

# Print results
for (result in results) {
  cat("Chi-Square Test for", result$variables, "\n")
  cat("Chi-Square Statistic:", result$chi2, "\n")
  cat("P-Value:", result$p_value, "\n\n")
}
Chi-Square Test for ED_GenderBirthCert vs ED_Marital 
Chi-Square Statistic: 3.114948 
P-Value: 0.2106676 

Chi-Square Test for ED_GenderBirthCert vs ED_RaceEthCode 
Chi-Square Statistic: 6.604558 
P-Value: 0.08562894 

Chi-Square Test for ED_GenderBirthCert vs ED_Event_BroadClass 
Chi-Square Statistic: 40.6724 
P-Value: 1.47265e-09 

Chi-Square Test for ED_GenderBirthCert vs Pain_Class 
Chi-Square Statistic: 32.45815 
P-Value: 4.19001e-07 

Chi-Square Test for ED_Marital vs ED_RaceEthCode 
Chi-Square Statistic: 98.24693 
P-Value: 5.82338e-19 

Chi-Square Test for ED_Marital vs ED_Event_BroadClass 
Chi-Square Statistic: 43.78164 
P-Value: 7.121953e-09 

Chi-Square Test for ED_Marital vs Pain_Class 
Chi-Square Statistic: 23.03797 
P-Value: 0.0007838599 

Chi-Square Test for ED_RaceEthCode vs ED_Event_BroadClass 
Chi-Square Statistic: 64.35096 
P-Value: 5.852822e-12 

Chi-Square Test for ED_RaceEthCode vs Pain_Class 
Chi-Square Statistic: 36.85666 
P-Value: 2.791426e-05 

Chi-Square Test for ED_Event_BroadClass vs Pain_Class 
Chi-Square Statistic: 10.04633 
P-Value: 0.1227143 
library(chisq.posthoc.test)
chisq.posthoc.test(table(df$ED_RaceEthCode, df$ED_GenderBirthCert), method = "bonferroni")

Explore interactions between race and other categories

ggplot(df %>% drop_na(ED_RaceEthCode, ED_Marital), aes(x = ED_RaceEthCode, fill = ED_RaceEthCode)) +
  geom_bar() + facet_wrap(~ ED_Marital) +
  scale_x_discrete(labels = c("1" = "Hispanic", 
                              "2" = "NH White", 
                              "3" = "NH Black", 
                              "4" = "Other"))+
  labs(title = "Counts of Race Ethnicity by Marital Status",
       x = "Race Ethnicity", y = "Count", fill = "Race Ethnicity") + gghisto


ggplot(df %>% drop_na(ED_RaceEthCode, ED_GenderBirthCert), aes(x = ED_RaceEthCode, fill = ED_RaceEthCode)) +
  geom_bar() + facet_wrap(~ ED_GenderBirthCert) +
  scale_x_discrete(labels = c("1" = "Hispanic", 
                              "2" = "NH White", 
                              "3" = "NH Black", 
                              "4" = "Other"))+
  labs(title = "Counts of Race Ethnicity by Sex",
       x = "Race Ethnicity", y = "Count", fill = "Race Ethnicity") + gghisto


ggplot(df %>% drop_na(ED_RaceEthCode, ED_highestgrade), aes(x = ED_RaceEthCode, fill = ED_RaceEthCode)) +
  geom_bar() + facet_wrap(~ ED_highestgrade) +
  scale_x_discrete(labels = c("1" = "Hispanic", 
                              "2" = "NH White", 
                              "3" = "NH Black", 
                              "4" = "Other"))+
  labs(title = "Counts of Race Ethnicity by Education",
       x = "Race Ethnicity", y = "Count", fill = "Race Ethnicity") + gghisto

Model 3: Sex*CTQ interaction

#3rd model is same as M2 but with sex*CTQ interaction
m3 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Total + BMI + PRE_Pain_MdSv + ED_Concussion + ED_PDI_RS + ED_GenderBirthCert*CTQ_Total, data = df_traj)
# weights:  60 (42 variable)
initial  value 3013.803941 
iter  10 value 2870.075351
iter  20 value 2714.636983
iter  30 value 2589.651923
iter  40 value 2585.457059
iter  50 value 2585.072939
iter  50 value 2585.072937
iter  50 value 2585.072937
final  value 2585.072937 
converged
tidy(m3, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Models 4-8: CTQ subtypes

#4th model is same as m0 but only week 2 emotional abuse scale
m4 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_EmoAbu_RS, data = df_traj)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3132.788294
iter  20 value 3070.120682
iter  30 value 3066.510436
final  value 3066.318761 
converged
tidy(m4, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))
#5th model is physical abuse
m5 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_PhyAbu_RS, data = df_traj)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3145.463616
iter  20 value 3084.213076
iter  30 value 3080.832860
final  value 3080.817912 
converged
tidy(m5, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))%>% 
  filter(term == "CTQ_Total")

#physical abuse*sex interaction term added
m5b <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_PhyAbu_RS + WK2_CTQSF_PhyAbu_RS*ED_GenderBirthCert, data = df_traj)
# weights:  44 (30 variable)
initial  value 3428.305955 
iter  10 value 3143.496277
iter  20 value 3082.081866
iter  30 value 3076.082550
final  value 3075.806127 
converged
tidy(m5b, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))
#6th model is sexual abuse
m6 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_SexAbu_RS, data = df_traj)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3146.612453
iter  20 value 3093.939191
iter  30 value 3092.521772
final  value 3092.509370 
converged
tidy(m6, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))
#7th model is emotional neglect
m7 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_EmoNeg_RS, data = df_traj)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3132.722284
iter  20 value 3107.694318
iter  30 value 3106.839218
final  value 3106.761270 
converged
tidy(m7, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))
#8th model is physical neglect
m8 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_PhyNeg_RS, data = df_traj)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3152.638071
iter  20 value 3109.332828
iter  30 value 3106.398970
final  value 3106.263598 
converged
tidy(m8, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 9: Physical and emotional abuse interaction + full m2 model

m9 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_EmoAbu_RS*WK2_CTQSF_PhyAbu_RS + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  80 (57 variable)
initial  value 2905.672981 
iter  10 value 2727.290452
iter  20 value 2611.579846
iter  30 value 2508.943598
iter  40 value 2474.114807
iter  50 value 2469.785722
iter  60 value 2469.681778
final  value 2469.679010 
converged

Model 10: Base model + Bullying

#10th model is bullying
m10 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_Bullying_Total, data = df_traj)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3138.794431
iter  20 value 3079.793835
iter  30 value 3076.555381
final  value 3076.498578 
converged
tidy(m10, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 11: Base Model + Bullying + Physical Abuse + Emotional Abuse

m11 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_EmoAbu_RS + WK2_Bullying_Total + WK2_CTQSF_PhyAbu_RS , data = df)
# weights:  48 (33 variable)
initial  value 3428.305955 
iter  10 value 3168.445796
iter  20 value 3089.370072
iter  30 value 3058.198215
final  value 3057.237154 
converged
tidy(m11, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 12: Base Model + CTQ_Triad

m12 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Triad, data = df)
# weights:  40 (27 variable)
initial  value 3428.305955 
iter  10 value 3112.030561
iter  20 value 3063.137502
iter  30 value 3062.108928
final  value 3062.073356 
converged
tidy(m12, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

vif(m12)
Warning in vif.default(m12) : No intercept: vifs may not be sensible.
                        GVIF Df GVIF^(1/(2*Df))
ED_Age             12.129317  1        3.482717
Site_New            3.808734  2        1.396996
ED_RaceEthCode      3.076682  3        1.205999
ED_GenderBirthCert  1.749248  1        1.322591
CTQ_Triad           3.496597  1        1.869919

Model 13: M2 + CTQ_Triad

m13 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Triad + BMI + PRE_Pain_MdSv + ED_Concussion + ED_Event_BroadClass + ED_PDI_RS + ADI_NatRank, data = df)
# weights:  68 (48 variable)
initial  value 2915.377041 
iter  10 value 2739.210619
iter  20 value 2565.857079
iter  30 value 2498.108035
iter  40 value 2488.122117
iter  50 value 2487.250228
final  value 2487.224804 
converged
tidy(m13, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 14: M2 + CTQ*race interaction

m14 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Total + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS + CTQ_Total*ED_RaceEthCode, data = df)
# weights:  84 (60 variable)
initial  value 2905.672981 
iter  10 value 2722.907873
iter  20 value 2616.833003
iter  30 value 2546.832934
iter  40 value 2481.950826
iter  50 value 2476.768761
iter  60 value 2476.190099
final  value 2476.169849 
converged
tidy(m14, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 15: M2 + CTQ*Sex interaction

m15 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Total + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS + CTQ_Total*ED_GenderBirthCert, data = df)
# weights:  76 (54 variable)
initial  value 2905.672981 
iter  10 value 2726.539466
iter  20 value 2582.710939
iter  30 value 2500.600668
iter  40 value 2481.028857
iter  50 value 2479.968836
iter  60 value 2479.937970
final  value 2479.937758 
converged
tidy(m15, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Models 16-21: M2 + each CTQ subtype + bullying

#physical abuse m16
m16 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_PhyAbu_RS + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2733.545607
iter  20 value 2587.983556
iter  30 value 2490.024136
iter  40 value 2478.329919
iter  50 value 2477.954484
final  value 2477.951022 
converged
#physical neglect m17
m17 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_PhyNeg_RS + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.903857
iter  20 value 2584.668068
iter  30 value 2501.712727
iter  40 value 2491.840790
iter  50 value 2491.513528
final  value 2491.509037 
converged
#emotional abuse m18
m18 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_EmoAbu_RS + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2734.160534
iter  20 value 2554.474284
iter  30 value 2483.807215
iter  40 value 2474.618814
iter  50 value 2474.329602
final  value 2474.325487 
converged
#emotional neglect m19
m19 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_EmoNeg_RS + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.219498
iter  20 value 2566.620944
iter  30 value 2499.532281
iter  40 value 2490.809627
iter  50 value 2490.346968
iter  60 value 2490.335809
iter  60 value 2490.335809
iter  60 value 2490.335809
final  value 2490.335809 
converged
#sexual abuse m20
m20 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_CTQSF_SexAbu_RS + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2735.598816
iter  20 value 2574.704703
iter  30 value 2497.418532
iter  40 value 2487.061070
iter  50 value 2486.784705
final  value 2486.781308 
converged
#bullying m21
m21 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + WK2_Bullying_Total + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2743.100075
iter  20 value 2578.785565
iter  30 value 2490.684674
iter  40 value 2479.988106
iter  50 value 2479.503675
iter  60 value 2479.495449
iter  60 value 2479.495449
iter  60 value 2479.495449
final  value 2479.495449 
converged
tidy(m16, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5))) 

tidy(m17, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5))) 

tidy(m18, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5))) 

tidy(m19, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5))) 

tidy(m20, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5))) 

tidy(m21, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5))) 

Model 22: m1 + Sex*CTQ

m22 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Total + ED_GenderBirthCert*CTQ_Total, data = df)
# weights:  44 (30 variable)
initial  value 3428.305955 
iter  10 value 3209.314694
iter  20 value 3081.328543
iter  30 value 3076.161084
final  value 3075.998418 
converged
tidy(m22, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 23: m1 + Race*CTQ

m23 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + CTQ_Total + ED_RaceEthCode*CTQ_Total, data = df)
# weights:  52 (36 variable)
initial  value 3428.305955 
iter  10 value 3235.013363
iter  20 value 3129.374452
iter  30 value 3075.511681
iter  40 value 3073.881816
final  value 3073.873786 
converged
tidy(m23, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 24: m2 female only


df_fem <- df %>% filter(ED_GenderBirthCert == "Female")

m24 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + CTQ_Total + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data=df_fem)
# weights:  68 (48 variable)
initial  value 1821.590791 
iter  10 value 1749.478705
iter  20 value 1646.945986
iter  30 value 1598.150436
iter  40 value 1595.869432
iter  50 value 1595.840267
final  value 1595.840098 
converged
tidy(m24, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 25: m2 male only

df_male <- df %>% filter(ED_GenderBirthCert == "Male")

m25 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + CTQ_Total + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data=df_male)
# weights:  68 (48 variable)
initial  value 1084.082190 
iter  10 value 961.847223
iter  20 value 902.498097
iter  30 value 870.184813
iter  40 value 868.729204
final  value 868.722781 
converged
tidy(m25, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Models 26-31: M2 + BINARY INDICATORS

M26: M2 + PhyAbu ANY

#Model 2 but instead of physical abuse score, its a binary score of whether or not the pt had any physical abuse

m26 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + PhyAbu_Any + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.488587
iter  20 value 2541.484969
iter  30 value 2487.267864
iter  40 value 2481.676257
iter  50 value 2481.372709
final  value 2481.370969 
converged
tidy(m26, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))%>%
  mutate(p_adj_bh = p.adjust(p.value, method = "BH"))

Model 27: M2 + Emo_Abuse ANY

#Model 2 but instead of emotional abuse score, its a binary score of whether or not the pt had any emotional abuse

m27 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + EmoAbu_Any + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.813403
iter  20 value 2538.022720
iter  30 value 2486.831808
iter  40 value 2482.419118
iter  50 value 2482.179920
final  value 2482.179663 
converged
tidy(m27, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 28: M2 + Emo_Neglect ANY

#Model 2 but instead of emotional neglect score, its a binary score of whether or not the pt had any emotional neglect

m28 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + EmoNeg_Any + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.932187
iter  20 value 2547.032244
iter  30 value 2494.450942
iter  40 value 2490.221890
iter  50 value 2490.039676
final  value 2490.038322 
converged
tidy(m28, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 29: M2 + Phy_Neglect ANY

#Model 2 but instead of physical neglect score, its a binary score of whether or not the pt had any physical neglect

m29 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + PhyNeg_Any + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.969951
iter  20 value 2547.879003
iter  30 value 2493.444387
iter  40 value 2489.112052
iter  50 value 2488.981415
final  value 2488.979319 
converged
tidy(m29, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 30: M2 + Sexual Abuse ANY

#Model 2 but instead of sexual abuse score, its a binary score of whether or not the pt had any sexual abuse

m30 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + SexAbu_Any + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.651133
iter  20 value 2542.048381
iter  30 value 2490.932778
iter  40 value 2486.717375
iter  50 value 2486.504995
final  value 2486.501431 
converged
tidy(m30, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 31: M2 + Bullying ANY

#Model 2 but instead of bullying score, its a binary score of whether or not the pt had any bullying

m31 <- multinom(Pain_Class ~ ED_Age + Site_New + ED_RaceEthCode + ED_GenderBirthCert + Bullying_Any + BMI + PRE_Pain_MdSv + ED_Marital + ADI_NatRank + ED_Event_BroadClass + ED_PDI_RS, data = df)
# weights:  72 (51 variable)
initial  value 2905.672981 
iter  10 value 2746.435587
iter  20 value 2546.950367
iter  30 value 2494.299098
iter  40 value 2488.287607
iter  50 value 2488.161517
final  value 2488.159906 
converged
tidy(m31, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))

Model 32: Stepwise Selection

#write a model that does multinomial stepwise selection to predict pain_class from  the best features from df

#rewrite stepwise code to remove missing values

invisible(capture.output(
stepwise_selection <- stepAIC(
  multinom(Pain_Class ~ ., data = drop_na(df)),
  direction = "both",
  trace = 0)
))
Warning in stepAIC(multinom(Pain_Class ~ ., data = drop_na(df)), direction = "both",  :
  0 df terms are changing AIC
# Initial features (excluding the response variable 'Pain_Class')
initial_features <- names(df)[names(df) != "Pain_Class"]
included_features <- names(coef(stepwise_selection))
excluded_features <- setdiff(initial_features, included_features)

# Print included and excluded features
cat("Included features:\n")
Included features:
print(included_features)
NULL
cat("\nExcluded features:\n")

Excluded features:
print(excluded_features)
 [1] "ED_Age"              "Site_New"            "ED_RaceEthCode"      "ED_GenderBirthCert"  "ADI_NatRank"        
 [6] "CTQ_Total"           "BMI"                 "PRE_Pain_MdSv"       "WK2_EmploymentCode"  "ED_Marital"         
[11] "ED_highestgrade"     "ED_Concussion"       "ED_Event_BroadClass" "ED_PDI_RS"           "WK2_CTQSF_PhyAbu_RS"
[16] "WK2_CTQSF_EmoAbu_RS" "WK2_CTQSF_SexAbu_RS" "WK2_CTQSF_PhyNeg_RS" "WK2_CTQSF_EmoNeg_RS" "WK2_Bullying_Total" 
[21] "CTQ_Triad"           "Bullying_Any"        "PhyAbu_Any"          "EmoAbu_Any"          "SexAbu_Any"         
[26] "PhyNeg_Any"          "EmoNeg_Any"          "CTQ_Any"             "ctq_total_count"    

Model 33-34 Pre-pain logistic regression

Email from Lauren 3-Aug-24

We wanted to make sure to include an analysis that closely mirrors our first animal figure (prior to SPS/TSE exposure, animals with ELA have increase pain-like behavior). I do not think we have done anything like this yet. Can you run an analysis to test whether there is a difference in PrePain rates/odds based on ELA?

I think this would either be a logistic regression using the CTQ composite and (separately) the Bullying composite, or a chi-square/z-proportion test and we could group CTQ and Bullying into high and low based on their median score (CTQ>6 and Bullying>3) or just use the “any CTQ” and “any Bullying variables”.

# Create binary variables for high/low CTQ and Bullying
df <- df %>%
  mutate(
    CTQ_HighLow = ifelse(CTQ_Total > 6, "High", "Low"),
    Bullying_HighLow = ifelse(WK2_Bullying_Total > 3, "High", "Low"))

# Create binary variable for PRE_Pain_MdSv
df$PRE_Pain_MdSv2 <- ifelse(df$PRE_Pain_MdSv == "Yes", 1, 0)

# M33 Logistic regression using CTQ composite
m33 <- glm(PRE_Pain_MdSv2 ~ CTQ_Total, data = df, family = "binomial")

tidy(m33, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric)))

# M34 Logistic regression using Bullying composite
m34 <- glm(PRE_Pain_MdSv2 ~ WK2_Bullying_Total, data = df, family = "binomial")
tidy(m34, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric)))

# Chi-square test for CTQ_HighLow
chisq.test(table(df$CTQ_HighLow, df$PRE_Pain_MdSv))

    Pearson's Chi-squared test with Yates' continuity correction

data:  table(df$CTQ_HighLow, df$PRE_Pain_MdSv)
X-squared = 33.911, df = 1, p-value = 5.77e-09
# Chi-square test for Bullying_HighLow
chisq.test(table(df$Bullying_HighLow, df$PRE_Pain_MdSv))

    Pearson's Chi-squared test with Yates' continuity correction

data:  table(df$Bullying_HighLow, df$PRE_Pain_MdSv)
X-squared = 17.926, df = 1, p-value = 2.297e-05
# chi-square test for any CTQ
chisq.test(table(df$CTQ_Any, df$PRE_Pain_MdSv))

    Pearson's Chi-squared test with Yates' continuity correction

data:  table(df$CTQ_Any, df$PRE_Pain_MdSv)
X-squared = 23.917, df = 1, p-value = 1.006e-06
# chi-square test for any bullying
chisq.test(table(df$Bullying_Any, df$PRE_Pain_MdSv))

    Pearson's Chi-squared test with Yates' continuity correction

data:  table(df$Bullying_Any, df$PRE_Pain_MdSv)
X-squared = 4.2373, df = 1, p-value = 0.03955

ANOVA for race x CTQ

#ANOVA on race vs CTQ
#ANOVA on ED_RaceEthCode versus CTQ

anova_result <- aov(CTQ_Total ~ ED_RaceEthCode, data = df)
summary(anova_result)
                 Df Sum Sq Mean Sq F value Pr(>F)  
ED_RaceEthCode    3    862  287.37       3 0.0295 *
Residuals      2469 236484   95.78                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
7 observations deleted due to missingness
TukeyHSD(anova_result)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = CTQ_Total ~ ED_RaceEthCode, data = df)

$ED_RaceEthCode
                     diff        lwr        upr     p adj
Hispanic-Black  1.2832267 -0.3897563  2.9562097 0.1989380
Other-Black    -0.1836877 -2.9182839  2.5509085 0.9981705
White-Black    -0.6973222 -1.8074146  0.4127702 0.3703250
Other-Hispanic -1.4669144 -4.5055288  1.5717001 0.6007039
White-Hispanic -1.9805489 -3.7089778 -0.2521200 0.0171293
White-Other    -0.5136345 -3.2824990  2.2552300 0.9641946
#ANOVA on pain trajectory by CTQ
result <- aov(CTQ_Total ~ Pain_Class, data = df)
summary(result)
              Df Sum Sq Mean Sq F value   Pr(>F)    
Pain_Class     3   5647  1882.4   20.08 7.39e-13 ***
Residuals   2476 232101    93.7                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
TukeyHSD(result)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = CTQ_Total ~ Pain_Class, data = df)

$Pain_Class
                                diff         lwr        upr     p adj
high-low                    4.074087  2.54471191  5.6034614 0.0000000
moderate-low                2.734025  1.45769353  4.0103565 0.0000002
moderate recovery-low       1.357109 -0.02229229  2.7365107 0.0557627
moderate-high              -1.340062 -3.01637594  0.3362527 0.1683568
moderate recovery-high     -2.716977 -4.47304012 -0.9609148 0.0004163
moderate recovery-moderate -1.376916 -2.91762703  0.1637954 0.0988564


Model Comparison

m1 #base model m2 #base model + additional features m12 #base model + CTQ_Triad m13 #m2 + CTQ_T

m16 #m2 + physical abuse m17 #m2 + physical neglect m18 #m2 + emotional abuse m19 #m2 + emotional neglect m20 #m2 + sexual abuse m21 #m2 + bullying

# List of all models
model_names <- paste0("m", 1:31)
models <- lapply(model_names, get)

#remove m25 from list of models
model_names2 <- model_names[-25]
models2 <- lapply(model_names2, get)


Stepwise selection of best model


Compare AIC/BIC

# Function to get AIC and BIC
get_aic_bic <- function(model) c(AIC = AIC(model), BIC = BIC(model))

# Apply the function to all models, sort results
compared_m <- as.data.frame(t(sapply(models, get_aic_bic)))
compared_m <- cbind(model = model_names, compared_m)
compared_m <- compared_m[order(compared_m$BIC), ]

# Print the results
print(compared_m)

#m18 is m2 + emotional abuse
#m13 is m2 + triad
#m16 is m2 + physical abuse
#m21 is m2 + bullying
#m2 is our main model
#m20 is m2 + sexual abuse
#m19 is m2 + emotional neglect

Use multi-class ROC curves

Trying this with m1, base model

# Load required library
library(pROC)

# Predict probabilities for m25
probs1 <- predict(m25, df, type = "probs")

# Create one-vs-rest ROC curves
roc_list <- list()
auroc_values <- numeric(length(colnames(probs1)))  # Initialize vector for AUROC values

for (class in colnames(probs1)) {
  roc_list[[class]] <- roc(as.numeric(df$Pain_Class == class), probs1[,class])
  auroc_values[class] <- auc(roc_list[[class]])  # Calculate AUROC
}
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
# Plot ROC curves
plot(roc_list[[1]], main = "ROC Curves for Each Class", col = 1, lwd = 2)
for (i in 2:length(roc_list)) {
  plot(roc_list[[i]], add = TRUE, col = i, lwd = 2)
}

# Add AUROC values as text directly on the plot
# Use a fixed position or adjust as needed
text_positions <- c(0.8, 0.7, 0.6, 0.5, 0.4, 0.3)  # Adjust as necessary for your plot

for (i in 1:length(roc_list)) {
  text(x = 0.6, y = text_positions[i], 
       labels = paste0(names(roc_list)[i], ": AUROC = ", round(auroc_values[i], 3)),
       pos = 4, cex = 0.8, col = i)
}

# Add legend to the plot
legend("bottomright", legend = names(roc_list), col = 1:length(roc_list), lwd = 2, bty = "n")

Examine confusion matrix

library(caret)
Loading required package: lattice

Attaching package: ‘caret’

The following object is masked from ‘package:purrr’:

    lift
# Function to compute confusion matrix with model names
get_confusion_matrix <- function(model, data, model_name) {
  predictions <- predict(model, newdata = data, type = "class")
  cm <- confusionMatrix(predictions, data$Pain_Class)
  return(list(model = model_name, confusion_matrix = cm))}

# Compute confusion matrices with model names
model_names <- c("m2", "m25")
models <- lapply(model_names, get)

conf_matrices <- mapply(get_confusion_matrix, models, MoreArgs = list(data = df), model_name = model_names, SIMPLIFY = FALSE)

# Print the confusion matrices with model names
for (cm in conf_matrices) {
  cat("Model:", cm$model, "\n")
  print(cm$confusion_matrix)
  cat("\n")}
Model: m2 
Confusion Matrix and Statistics

                   Reference
Prediction          low high moderate moderate recovery
  low               798  121      294               304
  high               27   80       58                30
  moderate           77   89      128                55
  moderate recovery   8    5        9                13

Overall Statistics
                                          
               Accuracy : 0.4862          
                 95% CI : (0.4646, 0.5078)
    No Information Rate : 0.4342          
    P-Value [Acc > NIR] : 9.46e-07        
                                          
                  Kappa : 0.1852          
                                          
 Mcnemar's Test P-Value : < 2.2e-16       

Statistics by Class:

                     Class: low Class: high Class: moderate Class: moderate recovery
Sensitivity              0.8769     0.27119         0.26176                 0.032338
Specificity              0.3938     0.93615         0.86248                 0.987013
Pos Pred Value           0.5260     0.41026         0.36676                 0.371429
Neg Pred Value           0.8066     0.88690         0.79336                 0.811257
Prevalence               0.4342     0.14074         0.23330                 0.191794
Detection Rate           0.3807     0.03817         0.06107                 0.006202
Detection Prevalence     0.7238     0.09303         0.16651                 0.016698
Balanced Accuracy        0.6353     0.60367         0.56212                 0.509676

Model: m25 
Confusion Matrix and Statistics

                   Reference
Prediction          low high moderate moderate recovery
  low               787  124      301               300
  high               34   77       60                42
  moderate           64   81      102                44
  moderate recovery  25   13       26                16

Overall Statistics
                                         
               Accuracy : 0.4685         
                 95% CI : (0.447, 0.4901)
    No Information Rate : 0.4342         
    P-Value [Acc > NIR] : 0.0008348      
                                         
                  Kappa : 0.1601         
                                         
 Mcnemar's Test P-Value : < 2.2e-16      

Statistics by Class:

                     Class: low Class: high Class: moderate Class: moderate recovery
Sensitivity              0.8648     0.26102         0.20859                 0.039801
Specificity              0.3887     0.92449         0.88239                 0.962220
Pos Pred Value           0.5205     0.36150         0.35052                 0.200000
Neg Pred Value           0.7894     0.88423         0.78560                 0.808532
Prevalence               0.4342     0.14074         0.23330                 0.191794
Detection Rate           0.3755     0.03674         0.04866                 0.007634
Detection Prevalence     0.7214     0.10162         0.13884                 0.038168
Balanced Accuracy        0.6268     0.59275         0.54549                 0.501010


Corrections testing

for m1, m2, m2 + each subtype, m2 + each subtype ANY likelihood ratio test m1 vs m2

BH Function

apply_bh_correction <- function(models, model_names) {
  correct_model <- function(model) {
    model_results <- tidy(model, exponentiate = TRUE) %>%
      filter(term != "(Intercept)") %>%
      select(y.level,term, estimate, p.value)
    
    model_results <- model_results %>%
      mutate(p_adj_bh = p.adjust(p.value, method = "BH")) %>%
      mutate(
        p.value = round(p.value, digits = 6),
        p_adj_bh = round(p_adj_bh, digits = 6)
      ) %>%
      mutate(
        p.value = format(p.value, scientific = FALSE),
        p_adj_bh = format(p_adj_bh, scientific = FALSE)
      )
    return(model_results)
  }
  
  corrected_models <- lapply(models, correct_model)
  names(corrected_models) <- model_names
  
  return(corrected_models)
}

BH Corrected M1-M2

models_list_bases <- list(m1,m2)
model_names <- c("m1", "m2")
adjusted_models <- apply_bh_correction(models_list_bases, model_names)

cat("MODEL 1 BH CORRECTED")
MODEL 1 BH CORRECTED
tidy(m1, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))  %>%
        filter(term != "(Intercept)") %>%
      select(y.level,term, estimate, p.value)%>%
      mutate(p_adj_bh = p.adjust(p.value, method = "BH"))

cat("\n \n MODEL 2 BH CORRECTED")

 
 MODEL 2 BH CORRECTED
tidy(m2, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))  %>%
        filter(term != "(Intercept)") %>%
      select(y.level,term, estimate, p.value)%>%
      mutate(p_adj_bh = p.adjust(p.value, method = "BH"))

BH Corrected M13 Triad

Within

cat("MODEL 13 BH CORRECTED")
MODEL 13 BH CORRECTED
tidy(m13, exponentiate = TRUE, conf.int = TRUE) %>%
  mutate(across(where(is.numeric), ~ round(., 5)))  %>%
        filter(term != "(Intercept)") %>%
      select(y.level,term, estimate, p.value)%>%
      mutate(p_adj_bh = p.adjust(p.value, method = "BH"))

Extract Adj p-val

#function to get adjusted p values from list of models
extract_p_values <- function(model_df, model_name) {
  model_df %>%
    mutate(model = model_name) %>%
    select(y.level, term, p.value,p_adj_bh, model)}

BH Across M16-M21

perform BH corrections on the values in combined_p_values_m16_m21

#BH corrections for models with subtypes m16-m21

#make first set of adjusted within p vals
models_list_subtypes <- list(m16, m17, m18, m19, m20, m21)
model_names2 <- c("m16", "m17", "m18", "m19", "m20", "m21")
adjusted_models2 <- apply_bh_correction(models_list_subtypes, model_names2)

combined_p_values_m16_m21 <- map2_dfr(adjusted_models2, paste0("m", 16:21), extract_p_values)

double_corrected_p_values_16_m21 <- combined_p_values_m16_m21 %>%
  mutate(p_adj_bh_2 = p.adjust(as.numeric(p_adj_bh), method = "BH")) %>%
  mutate(
    p_adj_bh_2 = round(p_adj_bh_2, digits = 6),
    p_adj_bh_2 = format(p_adj_bh_2, scientific = FALSE)  )

double_corrected_p_values_16_m21

BH Across M26-M31

#BH BETWEEN Corrections for models with binary indicators m26-m31

models_list_ANY <- list(m26, m27, m28, m29, m30, m31)
model_names3 <- c("m26", "m27", "m28", "m29", "m30", "m31")
adjusted_models3 <- apply_bh_correction(models_list_ANY, model_names3)

double_corrected_p_values_m26_m31 <- map2_dfr(adjusted_models3, paste0("m", 26:31), extract_p_values)

#perform BH corrections on the values in double_corrected_p_values_m26_m31
double_corrected_p_values_m26_m31 <- double_corrected_p_values_m26_m31 %>%
  mutate(p_adj_bh_2 = p.adjust(as.numeric(p_adj_bh), method = "BH")) %>%
  mutate(
    p_adj_bh_2 = round(p_adj_bh_2, digits = 6),
    p_adj_bh_2 = format(p_adj_bh_2, scientific = FALSE)  )

double_corrected_p_values_m26_m31

Tables for Manuscript

Table 1. General

Table 1a: Socio-demographic variables

table1a_features <- c("ED_GenderBirthCert", "ED_Age", "ED_RaceEthCode","BMI", "ADI_NatRank")

suppressMessages(suppressWarnings(
  df %>%
    select(all_of(table1a_features)) %>%
    tbl_summary(statistic = all_continuous() ~ "{mean} ({sd})", 
      digits = all_continuous() ~ 2)))
Characteristic N = 2,4801
ED_GenderBirthCert
    Female 1,554 (63%)
    Male 926 (37%)
ED_Age 36.09 (13.31)
ED_RaceEthCode
    Black 1,213 (49%)
    Hispanic 278 (11%)
    Other 91 (3.7%)
    White 891 (36%)
    Unknown 7
BMI 30.13 (8.32)
    Unknown 158
ADI_NatRank 63.93 (27.57)
    Unknown 80
1 n (%); Mean (SD)


Table 1b: ED/Trauma-related variable.names

table1b_features <- c("Site_New", "ED_Event_BroadClass", "ED_PDI_RS")

suppressMessages(suppressWarnings(
df %>%
    select(all_of(table1b_features)) %>%
    tbl_summary(statistic = all_continuous() ~ "{mean} ({sd})", 
      digits = all_continuous() ~ 2)))
Characteristic N = 2,4801
Site_New
    Midwest 960 (39%)
    NorthEast 1,053 (42%)
    SouthEast 467 (19%)
ED_Event_BroadClass
    MVC/Non-motor Collision 1,909 (77%)
    Other 340 (14%)
    Physical/Sexual Abuse 231 (9.3%)
ED_PDI_RS 13.92 (7.24)
    Unknown 139
1 n (%); Mean (SD)


Table 1c: Past pain/stress variables

table1c_features <- c("PRE_Pain_MdSv", "CTQ_Any","CTQ_Total","PhyAbu_Any", "WK2_CTQSF_PhyAbu_RS", "EmoAbu_Any","WK2_CTQSF_EmoAbu_RS", "SexAbu_Any", "WK2_CTQSF_SexAbu_RS", "PhyNeg_Any", "WK2_CTQSF_PhyNeg_RS", "EmoNeg_Any", "WK2_CTQSF_EmoNeg_RS", "Bullying_Any", "WK2_Bullying_Total")

# Create a named list to specify the type of each variable
type_list <- list(
  WK2_CTQSF_PhyAbu_RS = "continuous",
  WK2_CTQSF_EmoAbu_RS = "continuous",
  WK2_CTQSF_SexAbu_RS = "continuous",
  WK2_CTQSF_PhyNeg_RS = "continuous",
  WK2_CTQSF_EmoNeg_RS = "continuous",
  WK2_Bullying_Total = "continuous")

# Generate the summary table
suppressMessages(suppressWarnings(
  df %>%
    select(all_of(table1c_features)) %>%
    tbl_summary(
      statistic = all_continuous() ~ "{mean} ({sd})",
      digits = all_continuous() ~ 2,
      type = type_list)))
Characteristic N = 2,4801
PRE_Pain_MdSv 777 (31%)
    Unknown 10
CTQ_Any 1,977 (80%)
CTQ_Total 9.50 (9.79)
PhyAbu_Any 1,089 (44%)
WK2_CTQSF_PhyAbu_RS 1.56 (2.31)
EmoAbu_Any 1,627 (66%)
WK2_CTQSF_EmoAbu_RS 2.56 (2.64)
SexAbu_Any 867 (35%)
WK2_CTQSF_SexAbu_RS 1.93 (3.35)
PhyNeg_Any 1,146 (46%)
WK2_CTQSF_PhyNeg_RS 1.53 (2.14)
EmoNeg_Any 1,284 (52%)
WK2_CTQSF_EmoNeg_RS 1.92 (2.36)
Bullying_Any 1,977 (80%)
WK2_Bullying_Total 2.97 (2.37)
1 n (%); Mean (SD)


Table 1. Compared Pain Classes

table1_class_features <- c("Pain_Class","ED_GenderBirthCert", "ED_Age", "ED_RaceEthCode","BMI", "ADI_NatRank","Site_New", "ED_Event_BroadClass", "ED_PDI_RS","PRE_Pain_MdSv", "CTQ_Any","CTQ_Total","PhyAbu_Any", "WK2_CTQSF_PhyAbu_RS", "EmoAbu_Any","WK2_CTQSF_EmoAbu_RS", "SexAbu_Any", "WK2_CTQSF_SexAbu_RS", "PhyNeg_Any", "WK2_CTQSF_PhyNeg_RS", "EmoNeg_Any", "WK2_CTQSF_EmoNeg_RS", "Bullying_Any", "WK2_Bullying_Total")

# Create a named list to specify the type of each variable
type_list <- list(
  WK2_CTQSF_PhyAbu_RS = "continuous",
  WK2_CTQSF_EmoAbu_RS = "continuous",
  WK2_CTQSF_SexAbu_RS = "continuous",
  WK2_CTQSF_PhyNeg_RS = "continuous",
  WK2_CTQSF_EmoNeg_RS = "continuous",
  WK2_Bullying_Total = "continuous")

# Generate the summary table and compare across class and add p

suppressMessages(suppressWarnings(
  df %>%
    select(all_of(table1_class_features)) %>%
    tbl_summary(
      by = Pain_Class,
      statistic = all_continuous() ~ "{mean} ({sd})",
      digits = all_continuous() ~ 2,
      type = type_list) %>% add_p)) 
Characteristic low, N = 1,0701 high, N = 3521 moderate, N = 5901 moderate recovery, N = 4681 p-value2
ED_GenderBirthCert



<0.001
    Female 605 (57%) 237 (67%) 409 (69%) 303 (65%)
    Male 465 (43%) 115 (33%) 181 (31%) 165 (35%)
ED_Age 33.36 (12.52) 40.89 (13.19) 37.61 (13.12) 36.81 (14.00) <0.001
ED_RaceEthCode



<0.001
    Black 521 (49%) 210 (60%) 285 (49%) 197 (42%)
    Hispanic 122 (11%) 37 (11%) 77 (13%) 42 (9.0%)
    Other 39 (3.6%) 12 (3.4%) 23 (3.9%) 17 (3.6%)
    White 387 (36%) 93 (26%) 201 (34%) 210 (45%)
    Unknown 1 0 4 2
BMI 29.17 (7.95) 32.15 (9.44) 30.95 (8.28) 29.75 (7.93) <0.001
    Unknown 78 21 38 21
ADI_NatRank 62.03 (28.04) 70.74 (26.08) 66.28 (26.76) 60.04 (27.52) <0.001
    Unknown 41 8 14 17
Site_New



0.3
    Midwest 432 (40%) 139 (39%) 216 (37%) 173 (37%)
    NorthEast 441 (41%) 136 (39%) 267 (45%) 209 (45%)
    SouthEast 197 (18%) 77 (22%) 107 (18%) 86 (18%)
ED_Event_BroadClass



0.12
    MVC/Non-motor Collision 814 (76%) 268 (76%) 469 (79%) 358 (76%)
    Other 152 (14%) 40 (11%) 76 (13%) 72 (15%)
    Physical/Sexual Abuse 104 (9.7%) 44 (13%) 45 (7.6%) 38 (8.1%)
ED_PDI_RS 12.49 (7.09) 15.81 (7.33) 15.00 (7.07) 14.49 (7.13) <0.001
    Unknown 43 27 42 27
PRE_Pain_MdSv 189 (18%) 214 (61%) 251 (43%) 123 (27%) <0.001
    Unknown 2 1 3 4
CTQ_Any 805 (75%) 301 (86%) 490 (83%) 381 (81%) <0.001
CTQ_Total 8.02 (9.02) 12.09 (10.63) 10.75 (10.33) 9.37 (9.54) <0.001
PhyAbu_Any 397 (37%) 193 (55%) 298 (51%) 201 (43%) <0.001
WK2_CTQSF_PhyAbu_RS 1.23 (2.08) 2.30 (2.74) 1.85 (2.41) 1.38 (2.13) <0.001
EmoAbu_Any 623 (58%) 260 (74%) 416 (71%) 328 (70%) <0.001
WK2_CTQSF_EmoAbu_RS 2.07 (2.45) 3.40 (2.92) 2.94 (2.71) 2.55 (2.51) <0.001
SexAbu_Any 297 (28%) 148 (42%) 238 (40%) 184 (39%) <0.001
WK2_CTQSF_SexAbu_RS 1.43 (2.94) 2.63 (3.87) 2.37 (3.65) 2.00 (3.24) <0.001
PhyNeg_Any 460 (43%) 177 (50%) 297 (50%) 212 (45%) 0.012
WK2_CTQSF_PhyNeg_RS 1.47 (2.22) 1.69 (2.17) 1.61 (2.08) 1.44 (2.03) 0.028
EmoNeg_Any 525 (49%) 189 (54%) 327 (55%) 243 (52%) 0.078
WK2_CTQSF_EmoNeg_RS 1.81 (2.36) 2.07 (2.43) 1.98 (2.27) 2.00 (2.39) 0.080
Bullying_Any 814 (76%) 290 (82%) 476 (81%) 397 (85%) <0.001
WK2_Bullying_Total 2.60 (2.25) 3.63 (2.63) 3.17 (2.42) 3.05 (2.25) <0.001
1 n (%); Mean (SD)
2 Pearson’s Chi-squared test; Kruskal-Wallis rank sum test

What % were bullied?

# What % were bullied?
df %>%
  summarize(
    N = n(),
    Bullying_Any = sum(Bullying_Any == 1),
    Percent_Bullied = round(Bullying_Any / N * 100, 2))

#boxplot of each ctq type 
df %>%
  pivot_longer(
    cols = starts_with("WK2_CTQSF"),
    names_to = "CTQ_Type",
    values_to = "Score") %>%
  ggplot(aes(x = CTQ_Type, y = Score)) +
  geom_boxplot() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

KW function

kruskal_wallis_results <- function(df, features, group_var) {
  test_feature <- function(feature) {
    if (!feature %in% names(df)) {
      return(data.frame(
        Feature = feature,
        Chi_Square = NA,
        P_Value = NA
      ))}
    kw_test <- tryCatch(
      kruskal.test(df[[feature]] ~ df[[group_var]]),
      error = function(e) {
        return(list(statistic = NA, p.value = NA))
      })
    chi_squared <- kw_test$statistic
    p_value <- kw_test$p.value
    
    return(data.frame(
      Feature = feature,
      Chi_Square = chi_squared,
      P_Value = p_value
    ))}
  
  results <- map_dfr(features, test_feature)
  return(results)
}

continuous_features <- c("WK2_CTQSF_PhyAbu_RS", "WK2_CTQSF_EmoAbu_RS", "WK2_CTQSF_SexAbu_RS", 
                         "WK2_CTQSF_PhyNeg_RS", "WK2_CTQSF_EmoNeg_RS", "WK2_Bullying_Total", 
                         "ED_Age", "BMI", "ADI_NatRank", "ED_PDI_RS")

kw_table <- kruskal_wallis_results(df, continuous_features, "Pain_Class")

kw_table
#save kw table as csv
write.csv(kw_table, "kw_table.csv")

chi sq function

#run chi square test for all categorical variables
chi_sq_results <- function(df, features, group_var) {
  test_feature <- function(feature) {
    if (!feature %in% names(df)) {
      return(data.frame(
        Feature = feature,
        Chi_Square = NA,
        P_Value = NA
      ))}
    chi_sq_test <- tryCatch(
      chisq.test(table(df[[feature]], df[[group_var]])),
      error = function(e) {
        return(list(statistic = NA, p.value = NA))
      })
    chi_squared <- chi_sq_test$statistic
    p_value <- chi_sq_test$p.value
    
    return(data.frame(
      Feature = feature,
      Chi_Square = chi_squared,
      P_Value = p_value
    ))}
  
  results <- map_dfr(features, test_feature)
  return(results)
}

categorical_features <- c("ED_GenderBirthCert", "ED_RaceEthCode", "Site_New", "ED_Event_BroadClass", "PRE_Pain_MdSv", "CTQ_Any", "PhyAbu_Any", "EmoAbu_Any", "SexAbu_Any", "PhyNeg_Any", "EmoNeg_Any", "Bullying_Any")

chi.sq_table <- chi_sq_results(df, categorical_features, "Pain_Class")

chi.sq_table

#save chi sq table as csv
write.csv(chi.sq_table, "chi_sq_table.csv")

examine age by Pain Class

df %>%
  group_by(Pain_Class) %>%
  summarize(
    Mean_Age = mean(ED_Age, na.rm = TRUE),
    SD_Age = sd(ED_Age, na.rm = TRUE),
    Median_Age = median(ED_Age, na.rm = TRUE),
    IQR_Age = IQR(ED_Age, na.rm = TRUE),
    N = n())

ELA + previous pain relationship


#print number of people who had moderate or severe pain
summary_df <- data.frame(
  N = nrow(df),
  PRE_Pain_MdSv = sum(df$PRE_Pain_MdSv == "Yes"),
  Percent_Pain = round(sum(df$PRE_Pain_MdSv == "Yes") / nrow(df) * 100, 2))

t <- table(df$PRE_Pain_MdSv)

#make the table `t` percentages 
t

  No  Yes 
1693  777 
prop.table(t) * 100

      No      Yes 
68.54251 31.45749 
df$PRE_Pain_MdSv <- as.factor(df$PRE_Pain_MdSv)
df$CTQ_Any <- as.factor(df$CTQ_Any)
df$Bullying_Any <- as.factor(df$Bullying_Any)

chisq.test(table(df$PRE_Pain_MdSv, df$Bullying_Any))

    Pearson's Chi-squared test with Yates' continuity correction

data:  table(df$PRE_Pain_MdSv, df$Bullying_Any)
X-squared = 4.2373, df = 1, p-value = 0.03955
chisq.test(table(df$PRE_Pain_MdSv, df$CTQ_Any))

    Pearson's Chi-squared test with Yates' continuity correction

data:  table(df$PRE_Pain_MdSv, df$CTQ_Any)
X-squared = 23.917, df = 1, p-value = 1.006e-06
m35 <- glm(PRE_Pain_MdSv ~ CTQ_Total, data = df, family = binomial)
tidy(m35, exponentiate = TRUE, conf.int = TRUE) 

m36 <- glm(PRE_Pain_MdSv ~ WK2_Bullying_Total, data = df, family = binomial)
tidy(m36, exponentiate = TRUE, conf.int = TRUE)


ELA + previous pain z score normalized

df$CTQ_Total_z <- scale(df$CTQ_Total)
df$WK2_Bullying_Total_z <- scale(df$WK2_Bullying_Total)

model_ctq_z <- glm(PRE_Pain_MdSv ~ CTQ_Total_z, data = df, family = "binomial")
tidy(model_ctq_z, exponentiate = TRUE, conf.int = TRUE)

model_bullying_z <- glm(PRE_Pain_MdSv ~ WK2_Bullying_Total_z, data = df, family = "binomial")
tidy(model_bullying_z, exponentiate = TRUE, conf.int = TRUE)

Subset for Lauren

#make a csv that contains PID, Pain_Class, CTQ_Total, and Bullying score
df_Lauren <- df_traj %>% select(PID, Pain_Class, CTQ_Total, WK2_Bullying_Total)

#remove NA values from df_lauren
df_Lauren <- df_Lauren %>% drop_na()

write.csv(df_Lauren, "df_2480_Freeze4_data_Lauren.csv")

Notes

TO COMPLETE JULY 29:

check and clean each feature data (✓) re-code trauma types~ (✓) run multicollinearity test (3) for each ctq subtypes, ttest and plot for gender (✓) for each ctq subtype, tteset and plot for race (✓) ANOVA on race vs CTQ (✓) new CTQ combo variable model (✓) run multicollinearity on newly added features (✓) add income and re-cat education to m2 (✓) base model + CTQ*race (✓)

notes july 30th

  1. add marital status 4 to divorce category (✓)
  2. check frequencies of all categories in all variables (✓)
  3. marital status 1-married 2-separated 3-divorced 4-annulled 5-widowed 6-single (✓)
  4. marriage - combine 2+3+4+5 as a single category (✓)
  5. education - all negatives are missing for different reasons = NA (✓)
  6. Lauren will email Alice the education category info (✓)
  7. 1- did not finish HS (codes 0-12) 2- HS grad + some college (codes 13-15) 3- college grad (Bachelors or Associates) (codes 16-18) 4- post grad codes(19-21) (✓)
  8. Use ADI instead of income (✓)

july 30th run these and send results today

  1. run M2 with a CTQ::race interaction and a separate model with CTQ::Sex interaction (✓)
  2. Run M2 with each CTQ subtype and bullying (✓)
  3. scale normalize each feature so they can be compared across one another / can claim which are more or less associated with post trauma pain (✓)
  4. compare triad based model vs completed ctq model, use AIC/BIC and other measurements of fit to show “better” model (✓)
  5. redo ANOVAs as KW and show pairwise comparison posthoc. for race (✓)
  6. make a demographics table with significance by pain trajectory (✓)
  7. anesthesia research abstract

July 31st notes

  1. redo analysis with the original df i was using/ the FREEZE 4 df (✓)
  2. one out put of two graphs: one graph with CTQ total by sex, and other graph is CTQ total by race. and add stars/significance notation for sex, ns for race
  3. make graphs of subtypes (incl bullying instead of ctq total) so we have 2x3 table and include asterisks for sig

July 31 request from Lauren

  1. Table 1: sample characteristics for full cohort
  2. Supplementary Table 2: sample characteristics split by pain trajectories
  3. Supplementary Table 3: ELA subtype correlation heatmap/table
LS0tCnRpdGxlOiAiQVVST1JBIEVMQSBBbmFseXNpcyIKYXV0aG9yOiAiQWxpY2UiCmRhdGU6ICIwNy8yMS8yMDI0IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIGRvY3VtZW50IGNvbnRhaW5zIHRoZSBjb2RlIGZvciB0aGUgQVVST1JBIEVMQSBhbmFseXNpcy4gSW4gdGhpcyBhbmFseXNpcywgd2Ugd2lsbCBleHBsb3JlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBjaGlsZGhvb2QgdHJhdW1hIChDVFEpIGFuZCBwYWluIG91dGNvbWVzIGluIHRoZSBBVVJPUkEgZGF0YXNldC4gV2Ugd2lsbCBwZXJmb3JtIGNvcnJlbGF0aW9uIGFuYWx5c2lzLCBsaW5lYXIgbW9kZWxzLCByZXBlYXRlZCBtZWFzdXJlcyBtb2RlbHMsIGFuZCBhc3Nlc3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENUUSBhbmQgcGFpbiBvdXRjb21lIHRyYWplY3Rvcmllcy4gVGhpcyBpcyBhIHByZWxpbWluYXJ5IGRyYWZ0IG9mIHRoZSBhbmFseXNpcyB0aGF0IHdpbGwgYmUgY29tcGxldGVkIG92ZXIgdGhlIG5leHQgMiB3ZWVrcy4KCiMjIyBTZXQgdXAKCiMjIyMgSW1wb3J0IGxpYnJhcmllcwoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJtKGxpc3Q9bHMoKSkKCmxpYnJhcmllcyA8LSBjKCJ0aWR5dmVyc2UiLCAicnN0YXRpeCIsICJNQVNTIiwiY29ycnBsb3QiLCAibmxtZSIsICJzalBsb3QiLCAicmVhZHhsIiwgIm5uZXQiLCAiYnJvb20iLCAibG10ZXN0IiwgImZvcmNhdHMiLCJjYXIiLCAiaGlnaGNoYXJ0ZXIiLCAiZ2dwbG90MiIsICJjb3JyciIsICJnZ2NvcnJwbG90IiwgImdyaWRFeHRyYSIsICJza2ltciIsICJwUk9DIiwgImd0c3VtbWFyeSIsICJkdW5uLnRlc3QiLCAidGlkeXIiLCAicHVycnIiLCAiZHBseXIiKQoKc3VwcHJlc3NNZXNzYWdlcyhzdXBwcmVzc1dhcm5pbmdzKAogIGludmlzaWJsZShsYXBwbHkobGlicmFyaWVzLCBsaWJyYXJ5LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSkpCmBgYAoKIyMjIyBEZWZpbmUgcGxvdCBlbGVtZW50cwoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KZ2doaXN0byA8LSBsaXN0KAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLCBjb2xvcj0iY29ybmZsb3dlcmJsdWUiLCBzaXplPTEyLCBhbmdsZT0gMCksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkLml0YWxpYyIsIGNvbG9yPSJyb3lhbGJsdWU0IiwgCiAgICAgICAgICBzaXplPTE2LCBhbmdsZT0wKSwgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsZmFjZT0iYm9sZCIpKSkKCmdnaGlzdG8yIDwtIGxpc3QoCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsIGNvbG9yPSJjb3JuZmxvd2VyYmx1ZSIsIHNpemU9OCwgYW5nbGU9NiksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiwgY29sb3I9InJveWFsYmx1ZTQiLCAKICAgICAgICAgIHNpemU9MTIpLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE0LGZhY2U9ImJvbGQiKSwKICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCxmYWNlPSJib2xkLml0YWxpYyIpKSkKCmNvbG9yX2ZpbGwgPC0gc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiMSIgPSAidmlvbGV0cmVkMSIsICIyIiA9ICJzdGVlbGJsdWUxIikpIApgYGAKCjxicj4KCiMjIyMgSW1wb3J0IGFsbCBmcmVlemUgNCBkYXRhc2V0cwoKKk5vdGU6IEZvciB0aGUgcHVycG9zZSBvZiB0aGlzIGRyYWZ0IGNvZGUgZmlsZSwgTGF1cmVuIGhhcyBhbHJlYWR5IGNvbWJpbmVkIGFsbCBvZiB0aGUgZnJlZXplIDQgZGF0YXNldHMgaW50byBvbmUgZmlsZS4gVGhpcyBwcmUtY29tYmluZWQgZmlsZSwgY2FsbGVkIGBFTEFfZnVsbF9kYXRhX3Jhdy5jc3ZgIGJlbG93LCB3aWxsIGJlIHVzZWQgZm9yIHRoZSBpbml0aWFsIGFuYWx5c2lzLiBUaGUgZnVsbCBmaWxlIGltcG9ydCBjb2RlIHdpbGwgYmUgcmVuZGVyZWQgYW5kIGFwcGxpZWQgaW4gdGhlIGZpbmFsIHNjcmlwdCogXHZzcGFjZXstNXRydWVtbX0KCmBgYHtyLCBldmFsPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojUmVhZCBpbiB0aGUgZGF0YXNldApkYXRhXzEgPC0gcmVhZC5jc3YoIkFVUk9SQV9mdWxsX3VwZGF0ZTAyMTAyMDIyX05ldy5jc3YiLGNoZWNrLm5hbWVzPUYpWy0xXQoKI2ZyZWV6ZSA0IGRhdGFzZXRzCkFVUk9SQV9GcmVlemVfNF9nZW5lcmFsX21vZCA8LSByZWFkX2NzdigiQVVST1JBX0ZyZWV6ZV80X2dlbmVyYWxfbW9kLmNzdiIsbmEgPSAiLiIpCkFVUk9SQV9GcmVlemVfNF9kZW1vZ3JfbW9kIDwtIHJlYWRfY3N2KCJBVVJPUkFfRnJlZXplXzRfZGVtb2dyX21vZC5jc3YiLG5hID0gIi4iKQpBVVJPUkFfRnJlZXplXzRfcGFpbl9tb2QgPC0gcmVhZF9jc3YoIkFVUk9SQV9GcmVlemVfNF9wYWluX21vZC5jc3YiLG5hID0gIi4iKQoKQVVST1JBX0ZyZWV6ZV80X2N0cV9tb2QgPC0gcmVhZF9jc3YoIkFVUk9SQV9GcmVlemVfNF9jdHFfbW9kLmNzdiIsbmEgPSAiLiIpCkFVUk9SQV9GNF9DVFFfaXRlbSA8LSByZWFkeGw6OnJlYWRfZXhjZWwoIkFVUk9SQV9GNF9DVFFfaXRlbS54bHN4IikKI0FVUk9SQV9GcmVlemVfNF9wZGlfbW9kIDwtIHJlYWRfY3N2KCJBVVJPUkFfRnJlZXplXzRfcGRpX21vZC5jc3YiLG5hID0gIi4iKQpTaXRlSUQgPC0gcmVhZF9leGNlbCgiU2l0ZUlELnhsc3giKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpGWjRfZGYgPC0gQVVST1JBX0ZyZWV6ZV80X2RlbW9ncl9tb2QgJT4lIGlubmVyX2pvaW4oQVVST1JBX0Y0X0NUUV9pdGVtLGJ5PSJQSUQiKSAlPiUgCiAgaW5uZXJfam9pbihBVVJPUkFfRnJlZXplXzRfcGFpbl9tb2QsYnk9IlBJRCIpICU+JSAKICBpbm5lcl9qb2luKEFVUk9SQV9GcmVlemVfNF9jdHFfbW9kLGJ5PSJQSUQiKSAlPiUgCiAgI2lubmVyX2pvaW4oQVVST1JBX0ZyZWV6ZV80X3BkaV9tb2QsYnk9IlBJRCIpICU+JSAKICBpbm5lcl9qb2luKFNpdGVJRCxieT0iUElEIikgJT4lIAogIG11dGF0ZShTaXRlX05ldyA9IGNhc2Vfd2hlbihTaXRlSUQgJWluJSBjKCJCYXlzdGF0ZSIsIkJNQyIsICJCZXRoIElzcmFlbCIsICJCV0giLCAiQ29vcGVyIiwiRWluc3RlaW4iLCJKZWZmZXJzb24iLCJNR0giLCJNaXJpYW0iLCJQZW5uIiwiUmhvZGUgSXNsYW5kIiwiU3QuIEpvaG4iLCJTdC4gSm9zZXBoIiwiVGVtcGxlIiwiVU1hc3MiKSB+ICJOb3J0aEVhc3QiLFNpdGVJRCAlaW4lIGMoIkJheWxvciIsICJFbW9yeSBFRCIsICJKYWNrc29udmlsbGUiLCJVQUIiLCJVTkMiLCJVVCBIb3VzdG9uIiwiVVQgU291dGh3ZXN0ZXJuIiwiVmFuZGVyYmlsdCIpIH4gIlNvdXRoRWFzdCIsIFNpdGVJRCAlaW4lIGMoIjM5IiwiNDkiLCJCZWF1bW9udCBSb3lhbCBPYWsiLCJCZWF1bW9udCBUcm95IiwiRXNrZW5hemkiLCJIZW5yeSBGb3JkIiwiQ2luY2lubmF0aSIsIkluZGlhbmEiLCJXYXNoVSIsIldhc2hVIERQIikgfiAiTWlkd2VzdCIpKSAlPiUgCiAgY29udmVydF9hc19mYWN0b3IoU2l0ZV9OZXcsRURfR2VuZGVyQmlydGhDZXJ0LEVEX0dlbmRlck5vdyxFRF9NYXJpdGFsLEVEX1JhY2VFdGhDb2RlLEVEX2hpZ2hlc3RncmFkZSxXSzJfRW1wbG95bWVudENvZGUsV0syX0luY29tZUNvZGUpICU+JSAKICBtdXRhdGVfYXQodmFycyhjb250YWlucygiV0syX0NoaWxkaG9vZCIpKSxhcy5udW1lcmljKSAlPiUgZHBseXI6OnNlbGVjdCgtU2l0ZUlEKSAlPiUgIzI2ODIKICBtdXRhdGUoV0syX0J1bGx5aW5nX1RvdGFsID0gV0syX0NoaWxkaG9vZEJ1bGx5aW5nK1dLMl9DaGlsZGhvb2RIaXRPckh1cnQpICU+JSAKICBpbm5lcl9qb2luKGRhdGFfMSAlPiUgZHBseXI6OnNlbGVjdChQSUQsV0s4X1BhaW5fQyxNM19QYWluX0MsTTZfUGFpbl9DKSxieT0iUElEIikgJT4lIAogIGZpbHRlcihpcy5uYShXSzJfQ1RRU0ZfU2V4QWJ1X1JTKSA9PSBGKSAlPiUgCiAgZmlsdGVyKGlzLm5hKFdLMl9DVFFTRl9QaHlBYnVfUlMpPT0gRikgJT4lIAogIGZpbHRlcihpcy5uYShXSzJfQ1RRU0ZfRW1vQWJ1X1JTKT09IEYpICU+JSAKICBmaWx0ZXIoaXMubmEoV0syX0NUUVNGX0Vtb05lZ19SUykgPT0gRikgJT4lIAogIGZpbHRlcihpcy5uYShXSzJfQ1RRU0ZfUGh5TmVnX1JTKSA9PSBGKSAlPiUgCiAgZmlsdGVyKGlzLm5hKFdLMl9CdWxseWluZ19Ub3RhbCkgPT0gRikgJT4lICMyNDgzCiAgbXV0YXRlKGxvZ19XSzJfQ1RRU0ZfVG90YWxfUlMgPSBsb2cyKFdLMl9DVFFTRl9Ub3RhbF9SUysxKSxsb2dfRURfTm93UGFpbj1sb2cyKEVEX05vd1BhaW4rMSkpCmBgYAoKPGJyPgoKQmVsb3c6IFJlYWQgaW4gdGhlIGNvbXBsZXRlZCBkYXRhZnJhbWUgd2l0aCBlYWNoIG9mIHRoZSBzZXBhcmF0ZSBBVVJPUkEgZmlsZXMuIExhdXJlbiBkaWQgdGhpcyBvbiBoZXIgZW5kIGZvciBlYXNlIG9mIHVzZSBpbiB0aGlzIGRyYWZ0IGNvZGUgYW5hbHlzaXMuIExhdGVudCBjbGFzcyB0cmFqZWN0b3JpZXMgYWxzbyBpbXBvcnRlZC4gCgpcdnNwYWNley01dHJ1ZW1tfQoKVHJvdWJsZXNob290aW5nIHdoeSB0aGUgUiBlbnZpcm9ubWVudCBpcyBhbGwgZnVja2VkIHVwIGFuZCBub3RoaW5nIHdvcmtzCmBgYHtyfQojcm0obGlzdCA9IGxzKCkpCiNpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGRwbHlyKQoKVHJhdW1hX2RmIDwtIHJlYWRfZXhjZWwoIkFVUk9SQV9GcmVlemVfNF90cmF1bWFfbW9kLnhsc3giKQoKIyBFeHBsaWNpdGx5IHNldCBzZWxlY3QgdG8gcmVmZXIgdG8gZHBseXI6OnNlbGVjdApzZWxlY3QgPC0gZHBseXI6OnNlbGVjdApyZW5hbWUgPC0gZHBseXI6OnJlbmFtZQpgYGAKCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBJbXBvcnQgZGF0YXNldHMKRlo0X2RmIDwtIHJlYWRfY3N2KCJFTEFfZnVsbF9kYXRhX3Jhdy5jc3YiKQpwYWluX3RyYWplY3RvcnkgPC0gcmVhZF9jc3YoInBhaW5fbGF0ZW50X2NsYXNzXzQuY3N2IikKUFRTRF9kZiA8LSByZWFkX2V4Y2VsKCJBVVJPUkFfRnJlZXplXzRfcHRzZF9tb2QueGxzeCIpClRyYXVtYV9kZiA8LSByZWFkX2V4Y2VsKCJBVVJPUkFfRnJlZXplXzRfdHJhdW1hX21vZC54bHN4IikKSW5qdXJ5X2RmIDwtIHJlYWRfZXhjZWwoIkFVUk9SQV9GcmVlemVfNF9pbmp1cnlfbW9kLnhsc3giKQpBRElfZGYgPC0gcmVhZF9leGNlbCgiQVVST1JBX0ZyZWV6ZV80X3Nlc19tb2QueGxzeCIsbmEgPSAiLiIpCgojIENvbWJpbmUgZGF0YXNldHMKZGZfdHJhaiA8LSBGWjRfZGYgJT4lCiAgaW5uZXJfam9pbihUcmF1bWFfZGYgJT4lIHNlbGVjdChQSUQsIEVEX0V2ZW50X0Jyb2FkQ2xhc3MpLCBieSA9ICJQSUQiKSAlPiUKICBpbm5lcl9qb2luKEluanVyeV9kZiAlPiUgc2VsZWN0KFBJRCwgRURfQ29uY3Vzc2lvbiksIGJ5ID0gIlBJRCIpICU+JQogIGlubmVyX2pvaW4oQURJX2RmICU+JSBzZWxlY3QoUElELCBBRElfTmF0UmFuayksIGJ5ID0gIlBJRCIpICU+JQogIGlubmVyX2pvaW4ocGFpbl90cmFqZWN0b3J5ICU+JSBzZWxlY3QoUElELCBwYWluX0NsYXNzX01vc3RMaWtlbHkpLCBieSA9ICJQSUQiKSAKCiNleHBvcnQgPC0gZGZfdHJhalssYygyLDgyLDcwKV0KI3dyaXRlLmNzdihleHBvcnQsICJFTEFfZnVsbF9kYXRhLmNzdiIpCmBgYAoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojaW1wb3J0IHhpYWR5IGRmIEFVUk9SQV9Db25zdHJ1Y3RfU2NvcmVfRlNfRnJ6NF9EYXRhLmNzdgpkZl94aWFvZGkgPC0gcmVhZF9jc3YoIkFVUk9SQV9Db25zdHJ1Y3RfU2NvcmVfRlNfRnJ6NF9EYXRhLmNzdiIpCgojZ2V0IHJpZCBvZiBldmVyeXRoaW5nIGJ1dCB0aGUgdmFyaWFibGVzIHRoYXQgc3RhcnQgd2l0aCBQYWluCmRmX3hpYW9kaTIgPC0gZGZfeGlhb2RpICU+JSBzZWxlY3QoUElELCBzdGFydHNfd2l0aCgiUGFpbiIpKSAlPiUgYXMuZGF0YS5mcmFtZSgpCgoKIyAgYmluZCBpdCBieSBQSUQgdG8gb3VyIGRhdGEgc2V0IGFuZCBzZW5kIG1lIGEgc2ltcGxlciBDU1YgdGhhdCBpcyBqdXN0IFBJRCwgUGFpbiBUcmFqZWN0b3J5LCBhbmQgUGFpbiBTY29yZXMgZm9yIGFsbCB0aGUgdGltZSBwb2ludHM/CgpwYWluX3Njb3Jlc19kZiA8LSBkZl90cmFqWyxjKDIsODIpXQoKI2pvaW4gcGFpbl9zY29yZXNfZGYgYW5kIGRmX3hpYW9kaTIgYnkgUElECnhpYW9kaV9kZl9mb3JfTGF1cmVuIDwtIHBhaW5fc2NvcmVzX2RmICU+JSBpbm5lcl9qb2luKGRmX3hpYW9kaTIsIGJ5ID0gIlBJRCIpIAoKI3dyaXRlIGNzdiBvZiB4aWFvZGlfZGZfZm9yX0xhdXJlbgp3cml0ZS5jc3YoeGlhb2RpX2RmX2Zvcl9MYXVyZW4sICJ4aWFvZGlfZGZfZm9yX0xhdXJlbi5jc3YiKQpgYGAKCjxicj4KCiMjIyBDbGVhbiBkYXRhZnJhbWUKIyMjIyBSZWxldmVsIGFuZCByZWZhY3RvciBmZWF0dXJlcwoKUmVmYWN0b3IgcGFpbiB0cmFqZWN0b3JpZXMgYW5kIFJlbGV2ZWwgdG8gImxvdyBwYWluIiBhcyB0aGUgcmVmZXJlbmNlIGdyb3VwCmBgYHtyfQojZGZfdHJhaiRwYWluX0NsYXNzX01vc3RMaWtlbHkKCiNkZl90cmFqIDwtIGRmX3RyYWogJT4lIHJlbmFtZShQYWluX0NsYXNzID0gcGFpbl9DbGFzc19Nb3N0TGlrZWx5KQoKbmFtZXMoZGZfdHJhailbbmFtZXMoZGZfdHJhaikgPT0gInBhaW5fQ2xhc3NfTW9zdExpa2VseSJdIDwtICJQYWluX0NsYXNzIgoKCmRmX3RyYWogPC0gZGZfdHJhaiAlPiUKICBtdXRhdGUoUGFpbl9DbGFzcyA9IGNhc2Vfd2hlbigKICAgIFBhaW5fQ2xhc3MgPT0gIkNsYXNzIDEiIH4gIm1vZGVyYXRlIHJlY292ZXJ5IiwKICAgIFBhaW5fQ2xhc3MgPT0gIkNsYXNzIDIiIH4gIm1vZGVyYXRlIiwKICAgIFBhaW5fQ2xhc3MgPT0gIkNsYXNzIDMiIH4gImxvdyIsCiAgICBQYWluX0NsYXNzID09ICJDbGFzcyA0IiB+ICJoaWdoIiwKICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIoUGFpbl9DbGFzcykgICMgVGhpcyBoYW5kbGVzIGFueSB1bmV4cGVjdGVkIHZhbHVlcwogICkpICU+JQogIG11dGF0ZShQYWluX0NsYXNzID0gZmFjdG9yKFBhaW5fQ2xhc3MpKSAlPiUKICBtdXRhdGUoUGFpbl9DbGFzcyA9IHJlbGV2ZWwoUGFpbl9DbGFzcywgcmVmID0gImxvdyIpKQpgYGAKCkZhY3Rvcml6ZSBhbmQgcmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwpgYGB7cn0KZmFjdG9yX3ZhcnMgPC0gYygiRURfR2VuZGVyQmlydGhDZXJ0IiwgIkVEX0V2ZW50X0Jyb2FkQ2xhc3MiLCAiRURfTWFyaXRhbCIsIAogICAgICAgICAgICAgICAgICJXSzJfRW1wbG95bWVudENvZGUiLCAiRURfaGlnaGVzdGdyYWRlIiwgIkVEX1JhY2VFdGhDb2RlIiwgIlBSRV9QYWluX01kU3YiKQpkZl90cmFqW2ZhY3Rvcl92YXJzXSA8LSBsYXBwbHkoZGZfdHJhaltmYWN0b3JfdmFyc10sIGFzLmZhY3RvcikKCiNpbiBnZW5kZXIsIGNoYW5nZSAxIHRvIG1hbGUgYW5kIDIgdG8gZmVtYWxlCmRmX3RyYWokRURfR2VuZGVyQmlydGhDZXJ0IDwtIGlmZWxzZShkZl90cmFqJEVEX0dlbmRlckJpcnRoQ2VydCA9PSAxLCAiTWFsZSIsICJGZW1hbGUiKQoKI2luIHByZSBwYWluLCBjaGFuZ2UgMSB0byB5ZXMgYW5kIDAgdG8gbm8gLi4gaXMgdGhpcyBjb3JyZWN0PwpkZl90cmFqJFBSRV9QYWluX01kU3YgPC0gaWZlbHNlKGRmX3RyYWokUFJFX1BhaW5fTWRTdiA9PSAxLCAiWWVzIiwgIk5vIikKCiMgQ29udmVydCBjb250aW51b3VzIHZhcmlhYmxlcyB0byBudW1lcmljCmRmX3RyYWokRURfUERJX1JTIDwtIGFzLm51bWVyaWMoZGZfdHJhaiRFRF9QRElfUlMpCmRmX3RyYWokRURfQ29uY3Vzc2lvbiA8LSBhcy5udW1lcmljKGRmX3RyYWokRURfQ29uY3Vzc2lvbikKCiNyZW5hbWUgV0syIENUUSB0b3RhbCBjb2x1bW4gdG8gQ1RRX1RvdGFsCmRmX3RyYWogPC0gZGZfdHJhaiAlPiUKICByZW5hbWUoQ1RRX1RvdGFsID0gV0syX0NUUVNGX1RvdGFsX1JTKQpgYGAKCmdlbmVyYWwgY2xlYW4gdXAsIHJlbmFtaW5nLCByZW1vdmluZyBuZWdhdGl2ZXMKYGBge3J9CiNNYWtlIGFueSB2YWx1ZSBsZXNzIHRoYW4gMCBpbiB0aGUgYnVsbHlpbmcgdG90YWwgPT0gTkEKZGZfdHJhaiRXSzJfQnVsbHlpbmdfVG90YWwgPC0gaWZlbHNlKGRmX3RyYWokV0syX0J1bGx5aW5nX1RvdGFsIDwgMCwgTkEsIGRmX3RyYWokV0syX0J1bGx5aW5nX1RvdGFsKQoKI01ha2UgYW55IHZhbHVlIGxlc3MgdGhhbiAwIGluIEFESSA9PSBOQQpkZl90cmFqJEFESV9OYXRSYW5rIDwtIGlmZWxzZShkZl90cmFqJEFESV9OYXRSYW5rIDwgMCwgTkEsIGRmX3RyYWokQURJX05hdFJhbmspCmBgYAo8YnI+CgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIzMgYnVsbHlpbmcgcm93cyBoYXZlIG5lZ2F0aXZlIG51bWJlcnMKCiNyZW1vdmUgdGhlIHJvd3MgaW4gV0syX0J1bGx5aW5nX1RvdGFsIHRoYXQgY29udGFpbiBuZWdhdGl2ZSB2YWx1ZXMKCgpkZl90cmFqIDwtIGRmX3RyYWogJT4lIGZpbHRlcihXSzJfQnVsbHlpbmdfVG90YWwgPj0gMCkKYGBgCgpyZWxldmVsIGNhdGVnb3JpZXMgZm9yIHRyYXVtYSB0eXBlCmBgYHtyfQpkZl90cmFqIDwtIGRmX3RyYWogJT4lCiAgbXV0YXRlKEVEX0V2ZW50X0Jyb2FkQ2xhc3MgPSBjYXNlX3doZW4oCiAgICBFRF9FdmVudF9Ccm9hZENsYXNzID09ICIxIiB+ICJNVkMvTm9uLW1vdG9yIENvbGxpc2lvbiIsCiAgICBFRF9FdmVudF9Ccm9hZENsYXNzID09ICI2IiB+ICJNVkMvTm9uLW1vdG9yIENvbGxpc2lvbiIsCiAgICBFRF9FdmVudF9Ccm9hZENsYXNzID09ICIyIiB+ICJQaHlzaWNhbC9TZXh1YWwgQWJ1c2UiLAogICAgRURfRXZlbnRfQnJvYWRDbGFzcyA9PSAiMyIgfiAiUGh5c2ljYWwvU2V4dWFsIEFidXNlIiwKICAgIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgPT0gIjQiIH4gIk90aGVyIiwKICAgIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgPT0gIjUiIH4gIk90aGVyIiwKICAgIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgPT0gIjciIH4gIk90aGVyIiwKICAgIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgPT0gIjgiIH4gIk90aGVyIiwKICAgIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgPT0gIjkiIH4gIk90aGVyIiwKICAgIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgPT0gIjEwIiB+ICJPdGhlciIsCiAgICBFRF9FdmVudF9Ccm9hZENsYXNzID09ICIxMSIgfiAiT3RoZXIiLAogICAgVFJVRSB+IGFzLmNoYXJhY3RlcihFRF9FdmVudF9Ccm9hZENsYXNzKSAgIyBLZWVwcyBhbnkgb3RoZXIgdmFsdWVzIHVuY2hhbmdlZAogICkpCgojIENvbnZlcnQgRURfRXZlbnQgYnJvYWQgY2xhc3MgdG8gZmFjdG9yCmRmX3RyYWokRURfRXZlbnRfQnJvYWRDbGFzcyA8LSBmYWN0b3IoZGZfdHJhaiRFRF9FdmVudF9Ccm9hZENsYXNzKQoKdGFibGUoZGZfdHJhaiRFRF9FdmVudF9Ccm9hZENsYXNzKQpgYGAKCjxicj4KClJlbGV2ZWwgY2F0ZWdvcmllcyBmb3IgZWR1Y2F0aW9uCgpgYGB7cn0KI3JlbGV2ZWwgZWR1Y2F0aW9uIGNhdGVnb3J5CiMgMS0gZGlkIG5vdCBmaW5pc2ggSFMgKGNvZGVzIDAtMTIpIDItIEhTIGdyYWQgKyBzb21lIGNvbGxlZ2UgKGNvZGVzIDEzLTE1KSAzLSBjb2xsZWdlIGdyYWQgKEJhY2hlbG9ycyBvciBBc3NvY2lhdGVzKSAoY29kZXMgMTYtMTgpIDQtIHBvc3QgZ3JhZCBjb2RlcygxOS0yMSkKZGZfdHJhaiA8LSBkZl90cmFqICU+JQogIG11dGF0ZShFRF9oaWdoZXN0Z3JhZGUgPSBjYXNlX3doZW4oCiAgICBFRF9oaWdoZXN0Z3JhZGUgPT0gIjAiIH4gIkRpZCBub3QgZmluaXNoIEhTIiwKICAgIEVEX2hpZ2hlc3RncmFkZSA9PSAiMSIgfiAiRGlkIG5vdCBmaW5pc2ggSFMiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICI3IiB+ICJEaWQgbm90IGZpbmlzaCBIUyIsCiAgICBFRF9oaWdoZXN0Z3JhZGUgPT0gIjgiIH4gIkRpZCBub3QgZmluaXNoIEhTIiwKICAgIEVEX2hpZ2hlc3RncmFkZSA9PSAiOSIgfiAiRGlkIG5vdCBmaW5pc2ggSFMiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxMCIgfiAiRGlkIG5vdCBmaW5pc2ggSFMiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxMSIgfiAiRGlkIG5vdCBmaW5pc2ggSFMiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxMiIgfiAiRGlkIG5vdCBmaW5pc2ggSFMiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxMyIgfiAiSFMgR3JhZC9Tb21lIENvbGxlZ2UiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxNCIgfiAiSFMgR3JhZC9Tb21lIENvbGxlZ2UiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxNSIgfiAiSFMgR3JhZC9Tb21lIENvbGxlZ2UiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxNiIgfiAiQmFjaCBvciBBc3NvYyBkZWdyZWUiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxNyIgfiAiQmFjaCBvciBBc3NvYyBkZWdyZWUiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxOCIgfiAiQmFjaCBvciBBc3NvYyBkZWdyZWUiLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIxOSIgfiAiUG9zdC1ncmFkdWF0ZSBlZHVjYXRpb24iLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIyMCIgfiAiUG9zdC1ncmFkdWF0ZSBlZHVjYXRpb24iLAogICAgRURfaGlnaGVzdGdyYWRlID09ICIyMSIgfiAiUG9zdC1ncmFkdWF0ZSBlZHVjYXRpb24iLAogICAgRURfaGlnaGVzdGdyYWRlID09ICItNyIgfiBOQSwKICAgIEVEX2hpZ2hlc3RncmFkZSA9PSAiLTUiIH4gTkEsCiAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKEVEX2hpZ2hlc3RncmFkZSkgICMgS2VlcHMgYW55IG90aGVyIHZhbHVlcyB1bmNoYW5nZWQKICApKQoKIyBDb252ZXJ0IHRvIGZhY3RvcgpkZl90cmFqJEVEX2hpZ2hlc3RncmFkZSA8LSBmYWN0b3IoZGZfdHJhaiRFRF9oaWdoZXN0Z3JhZGUpCgp0YWJsZShkZl90cmFqJEVEX2hpZ2hlc3RncmFkZSkKYGBgCgo8YnI+CgpSZS1sZXZlbCBtYXJyaWFnZSBjYXRlZ29yeQoKYGBge3J9CiNyZWxldmVsIG1hcnJpdGFsIHN0YXR1cyBjYXRlZ29yeQojbWFyaXRhbCBzdGF0dXMgMS1tYXJyaWVkIDItc2VwYXJhdGVkIDMtZGl2b3JjZWQgNC1hbm51bGxlZCA1LXdpZG93ZWQgNi1zaW5nbGUKIzQuIG1hcnJpYWdlIC0gY29tYmluZSAyKzMrNCs1IGFzIGEgc2luZ2xlIGNhdGVnb3J5CgpkZl90cmFqIDwtIGRmX3RyYWogJT4lCiAgbXV0YXRlKEVEX01hcml0YWwgPSBjYXNlX3doZW4oCiAgICBFRF9NYXJpdGFsID09ICIxIiB+ICJNYXJyaWVkIiwKICAgIEVEX01hcml0YWwgPT0gIjIiIH4gIkRpdm9yY2VkL1dpZG93ZWQiLAogICAgRURfTWFyaXRhbCA9PSAiMyIgfiAiRGl2b3JjZWQvV2lkb3dlZCIsCiAgICBFRF9NYXJpdGFsID09ICI0IiB+ICJEaXZvcmNlZC9XaWRvd2VkIiwKICAgIEVEX01hcml0YWwgPT0gIjUiIH4gIkRpdm9yY2VkL1dpZG93ZWQiLAogICAgRURfTWFyaXRhbCA9PSAiNiIgfiAiU2luZ2xlIiwKICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIoRURfTWFyaXRhbCkgICMgS2VlcHMgYW55IG90aGVyIHZhbHVlcyB1bmNoYW5nZWQKICApKQoKIyBDb252ZXJ0IHRvIGZhY3RvcgpkZl90cmFqJEVEX01hcml0YWwgPC0gZmFjdG9yKGRmX3RyYWokRURfTWFyaXRhbCkKCnRhYmxlKGRmX3RyYWokRURfTWFyaXRhbCkKYGBgCgo8YnI+CgpgYGB7cn0KI3JlbGV2ZWwgRURfUmFjZUV0aENvZGUKIzEgPSBIaXNwYW51aWMsIDIgPSBOSCBXaGl0ZSwgMyA9IE5IIEJsYWNrLCA0ID0gT3RoZXIKZGZfdHJhaiA8LSBkZl90cmFqICU+JQogIG11dGF0ZShFRF9SYWNlRXRoQ29kZSA9IGNhc2Vfd2hlbigKICAgIEVEX1JhY2VFdGhDb2RlID09ICIxIiB+ICJIaXNwYW5pYyIsCiAgICBFRF9SYWNlRXRoQ29kZSA9PSAiMiIgfiAiV2hpdGUiLAogICAgRURfUmFjZUV0aENvZGUgPT0gIjMiIH4gIkJsYWNrIiwKICAgIEVEX1JhY2VFdGhDb2RlID09ICI0IiB+ICJPdGhlciIsCiAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKEVEX1JhY2VFdGhDb2RlKSAgIyBLZWVwcyBhbnkgb3RoZXIgdmFsdWVzIHVuY2hhbmdlZAogICkpCgojY29udmVydCB0byBmYWN0b3IKZGZfdHJhaiRFRF9SYWNlRXRoQ29kZSA8LSBmYWN0b3IoZGZfdHJhaiRFRF9SYWNlRXRoQ29kZSkKYGBgCgoKIyMjIyBTdWJzZXQgdG8gZmluYWwgZGYgZm9yIGFuYWx5c2lzCgpTdWJzZXQgZGZfdHJhaiB0byBvdXIgZmluYWwgZGYgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIG1vZGVsIGFuYWx5c2lzLCBrZWVwIG9ubHkgdGhlIGZlYXR1cmVzIG5lZWRlZApgYGB7cn0KZGYgPC0gZGZfdHJhaiAlPiUKICBzZWxlY3QoUGFpbl9DbGFzcyxFRF9BZ2UsIFNpdGVfTmV3LCBFRF9SYWNlRXRoQ29kZSwgRURfR2VuZGVyQmlydGhDZXJ0LCBBRElfTmF0UmFuaywgQ1RRX1RvdGFsLCAKICAgICAgICAgQk1JLCBQUkVfUGFpbl9NZFN2LCBXSzJfRW1wbG95bWVudENvZGUsIEVEX01hcml0YWwsIEVEX2hpZ2hlc3RncmFkZSwgCiAgICAgICAgIEVEX0NvbmN1c3Npb24sIEVEX0V2ZW50X0Jyb2FkQ2xhc3MsIEVEX1BESV9SUywgV0syX0NUUVNGX1BoeUFidV9SUywgV0syX0NUUVNGX0Vtb0FidV9SUywgV0syX0NUUVNGX1NleEFidV9SUywgV0syX0NUUVNGX1BoeU5lZ19SUywgV0syX0NUUVNGX0Vtb05lZ19SUywgV0syX0J1bGx5aW5nX1RvdGFsKQpgYGAKCjxicj4KCkFkZCB0aGUgQ1RRIHRyaWFkIHNjb3JlIHRoYXQgaXMgYSBjb21iaW5hdGlvbiBvZiBidWxseWluZywgcGh5c2ljYWwgYWJ1c2UsIGFuZCBlbW90aW9uYWwgYWJ1c2Ugc2NvcmVzCmBgYHtyfQojYWRkIGNvbWJpbmF0aW9uIENUUSBzY29yZQpkZiRDVFFfVHJpYWQgPC0gZGYkV0syX0J1bGx5aW5nX1RvdGFsICsgZGYkV0syX0NUUVNGX1BoeUFidV9SUyArIGRmJFdLMl9DVFFTRl9FbW9BYnVfUlMKCiNwcmludCB0aGUgcm93cyB0aGF0IGhhdmUgTkEgaW4gdGhlIENUUSB0cmlhZApkZiAlPiUgZmlsdGVyKGlzLm5hKENUUV9UcmlhZCkpCiNDb25maXJtcyB0aGF0IGZvciB0aGUgQ1RRIHRyaWFkLCBpZiBhbnkgb2YgdGhlIGFkZGl0aXZlIGZlYXR1cmVzIGNvbnRhaW4gTkEsIHRoZW4gdGhlIGZpbmFsIHNjb3JlIGlzIE5BCmBgYAoKCmBgYHtyfQojbWFrZSBhbGwgb2YgZGZbLGMoMiw2OjgpXSkgbnVtZXJpYwpkZlssYygyLDY6OCldIDwtIGxhcHBseShkZlssYygyLDY6OCldLCBhcy5udW1lcmljKQpgYGAKCjxicj4KCgpCaW5hcnkgc2NvcmVzIGZvciBsYXRlciBtb2RlbHMKYGBge3J9CmRmJEJ1bGx5aW5nX0FueSA8LSBpZmVsc2UoZGYkV0syX0J1bGx5aW5nX1RvdGFsID4gMCwgMSwgMCkKZGYkUGh5QWJ1X0FueSA8LSBpZmVsc2UoZGYkV0syX0NUUVNGX1BoeUFidV9SUyA+IDAsIDEsIDApCmRmJEVtb0FidV9BbnkgPC0gaWZlbHNlKGRmJFdLMl9DVFFTRl9FbW9BYnVfUlMgPiAwLCAxLCAwKQpkZiRTZXhBYnVfQW55IDwtIGlmZWxzZShkZiRXSzJfQ1RRU0ZfU2V4QWJ1X1JTID4gMCwgMSwgMCkKZGYkUGh5TmVnX0FueSA8LSBpZmVsc2UoZGYkV0syX0NUUVNGX1BoeU5lZ19SUyA+IDAsIDEsIDApCmRmJEVtb05lZ19BbnkgPC0gaWZlbHNlKGRmJFdLMl9DVFFTRl9FbW9OZWdfUlMgPiAwLCAxLCAwKQpkZiRDVFFfQW55IDwtIGlmZWxzZShkZiRDVFFfVG90YWwgPiAwLCAxLCAwKQpgYGAKIyMjIyBaLXRyYW5zZm9ybSBzY2FsaW5nCgpgYGB7cn0KI3NjYWxlCmRmX3ogPC0gZGYgJT4lIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gc2NhbGUoLikpKQoKI3N1bW1hcnkoZGZfeikKYGBgCgo8YnI+Cgo8YnI+CgojIyMgUHJlbGltaW5hcnkgQW5hbHlzaXMKClx2c3BhY2V7LTV0cnVlbW19Cgo8YnI+Cgo8L2JyPgoKIyMjIyBTdW1tYXJ5IHRhYmxlIG9mIGRhdGEKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdXBwcmVzc01lc3NhZ2VzKHN1cHByZXNzV2FybmluZ3MoCiAgZGYgJT4lCiAgICB0Ymxfc3VtbWFyeShzdGF0aXN0aWMgPSBhbGxfY29udGludW91cygpIH4gInttZWFufSAoe3NkfSkiLCAKICAgICAgICAgICAgICBkaWdpdHMgPSBhbGxfY29udGludW91cygpIH4gMikgKSkKCiMgRW5zdXJlIGNvbHVtbnMgMTYgdG8gMjIgYXJlIG51bWVyaWMKZGZbMTY6MjJdIDwtIGxhcHBseShkZlsxNjoyMl0sIGFzLm51bWVyaWMpCgojIENyZWF0ZSB0aGUgc3VtbWFyeSB0YWJsZQpzdXBwcmVzc01lc3NhZ2VzKHN1cHByZXNzV2FybmluZ3MoCiAgZGYgJT4lCiAgICB0Ymxfc3VtbWFyeSgKICAgICAgYnkgPSBQYWluX0NsYXNzLCAKICAgICAgc3RhdGlzdGljID0gYWxsX2NvbnRpbnVvdXMoKSB+ICJ7bWVhbn0gKHtzZH0pIiwgCiAgICAgIGRpZ2l0cyA9IGFsbF9jb250aW51b3VzKCkgfiAyCiAgICApICU+JSBhZGRfcCgpICkpCmBgYAoKPGJyPgoKIyMjIyBDYXRlZ29yeSBkaXN0cmlidXRpb24gcGxvdHMKCmBgYHtyfQpwMSA8LSBnZ3Bsb3QoZGZfdHJhaiAlPiUgZmlsdGVyKCFpcy5uYShFRF9FdmVudF9Ccm9hZENsYXNzKSksIGFlcyh4ID0gRURfRXZlbnRfQnJvYWRDbGFzcywgZmlsbD1FRF9FdmVudF9Ccm9hZENsYXNzKSkgKwogIGdlb21fYmFyKGNvbG9yPSJibGFjayIpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3RleHQoc3RhdCA9ICdjb3VudCcsIGFlcyhsYWJlbCA9IC4uY291bnQuLiksIHZqdXN0ID0gMS41KSArCiAgbGFicyh0aXRsZSA9ICJDb3VudHMgb2YgVHJhdW1hIFR5cGUiLCB5ID0gIkNvdW50IikgKyBnZ2hpc3RvMgoKcDIgPC0gZ2dwbG90KGRmX3RyYWogJT4lIGZpbHRlcighaXMubmEoRURfaGlnaGVzdGdyYWRlKSksIGFlcyh4ID0gRURfaGlnaGVzdGdyYWRlLCBmaWxsPUVEX2hpZ2hlc3RncmFkZSkpICsKICBnZW9tX2Jhcihjb2xvcj0iYmxhY2siKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV90ZXh0KHN0YXQgPSAnY291bnQnLCBhZXMobGFiZWwgPSAuLmNvdW50Li4pLCB2anVzdCA9IDEuNSkgKwogIGxhYnModGl0bGUgPSAiQ291bnRzIG9mIEVkdWNhdGlvbiIsCiAgICAgICB5ID0gIkNvdW50IikgKyBnZ2hpc3RvMgoKcDMgPC0gZ2dwbG90KGRmX3RyYWogJT4lIGZpbHRlcighaXMubmEoRURfTWFyaXRhbCkpLCBhZXMoeCA9IEVEX01hcml0YWwsIGZpbGw9RURfTWFyaXRhbCkpICsKICBnZW9tX2Jhcihjb2xvcj0iYmxhY2siKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV90ZXh0KHN0YXQgPSAnY291bnQnLCBhZXMobGFiZWwgPSAuLmNvdW50Li4pLCB2anVzdCA9IDEuNSkgKwogIGxhYnModGl0bGUgPSAiQ291bnRzIG9mIE1hcml0YWwgU3RhdHVzIiwKICAgICAgIHkgPSAiQ291bnQiKSAgKyBnZ2hpc3RvMgoKcDQgPC0gZ2dwbG90KGRmX3RyYWogJT4lIGZpbHRlcighaXMubmEoUGFpbl9DbGFzcykpLCBhZXMoeCA9IFBhaW5fQ2xhc3MsIGZpbGw9UGFpbl9DbGFzcykpICsKICBnZW9tX2Jhcihjb2xvcj0iYmxhY2siKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV90ZXh0KHN0YXQgPSAnY291bnQnLCBhZXMobGFiZWwgPSAuLmNvdW50Li4pLCB2anVzdCA9IDEuNSkgKwogIGxhYnModGl0bGUgPSAiQ291bnRzIG9mIFBhaW4gQ2xhc3MiLAogICAgICAgeSA9ICJDb3VudCIpICsgZ2doaXN0bzIKCmdyaWQuYXJyYW5nZShwMSwgcDIsIHAzLCBwNCwgbmNvbCA9IDIpCmBgYAoKPGJyPgoKIyMjIyBTRVggeCBDVFEgc3RhdHMrcGxvdHMKCmBgYHtyfQojTG9vayBhdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRURfR2VuZGVyQmlydGhDZXJ0IGFuZCBDVFFfVG90YWwKdC50ZXN0KENUUV9Ub3RhbCB+IEVEX0dlbmRlckJpcnRoQ2VydCwgZGF0YSA9IGRmLHZhci5lcXVhbCA9IEZBTFNFKQpwMSA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gRURfR2VuZGVyQmlydGhDZXJ0LCB5ID0gQ1RRX1RvdGFsKSkgKwogIGdlb21fYm94cGxvdChsd2QgPSAuOSwgZmlsbD1jKCJwaW5rIiwic2t5Ymx1ZSIpKSArCiAgbGFicyh0aXRsZSA9ICJDVFEgQ29tcG9zaXRlIGJ5IEdlbmRlciIsCiAgICAgICB4ID0gIiAiLAogICAgICAgeSA9ICJDVFEgQ29tcG9zaXRlIikgKyBnZ2hpc3RvCgojIFNleHVhbCBhc3NhdWx0IENUUSB4IFNleAp0LnRlc3QoV0syX0NUUVNGX1NleEFidV9SUyB+IEVEX0dlbmRlckJpcnRoQ2VydCwgZGF0YSA9IGRmLHZhci5lcXVhbCA9IEZBTFNFKQpwMiA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gRURfR2VuZGVyQmlydGhDZXJ0LCB5ID0gV0syX0NUUVNGX1NleEFidV9SUykpICsKICBnZW9tX2JveHBsb3QobHdkID0gLjksIGZpbGw9YygicGluayIsInNreWJsdWUiKSkgKwogIGxhYnModGl0bGUgPSAiU2V4dWFsIEFidXNlIGJ5IEdlbmRlciIsCiAgICAgICB4ID0gIiAiLAogICAgICAgeSA9ICJTZXh1YWwgQWJ1c2UgU2NvcmUiKSArIGdnaGlzdG8KCiMgcGh5c2ljYWwgYWJ1c2UgeCBTZXgKdC50ZXN0KFdLMl9DVFFTRl9QaHlBYnVfUlMgfiBFRF9HZW5kZXJCaXJ0aENlcnQsIGRhdGEgPSBkZix2YXIuZXF1YWwgPSBGQUxTRSkKcDMgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IEVEX0dlbmRlckJpcnRoQ2VydCwgeSA9IFdLMl9DVFFTRl9QaHlBYnVfUlMpKSArCiAgZ2VvbV9ib3hwbG90KGx3ZCA9IC45LCBmaWxsPWMoInBpbmsiLCJza3libHVlIikpICsKICBsYWJzKHRpdGxlID0gIlBoeXNpY2FsIEFidXNlIGJ5IEdlbmRlciIsCiAgICAgICB4ID0gIiAiLAogICAgICAgeSA9ICJQaHlzaWNhbCBBYnVzZSBTY29yZSIpICsgZ2doaXN0bwoKIyBwaHlzaWNhbCBuZWdsZWN0IHggc2V4CnQudGVzdChXSzJfQ1RRU0ZfUGh5TmVnX1JTIH4gRURfR2VuZGVyQmlydGhDZXJ0LCBkYXRhID0gZGYsdmFyLmVxdWFsID0gRkFMU0UpCnA0IDwtIGdncGxvdChkZiwgYWVzKHggPSBFRF9HZW5kZXJCaXJ0aENlcnQsIHkgPSBXSzJfQ1RRU0ZfUGh5TmVnX1JTKSkgKwogIGdlb21fYm94cGxvdChsd2QgPSAuOSwgZmlsbD1jKCJwaW5rIiwic2t5Ymx1ZSIpKSArCiAgbGFicyh0aXRsZSA9ICJQaHlzaWNhbCBOZWdsZWN0IGJ5IEdlbmRlciIsCiAgICAgICB4ID0gIiAiLAogICAgICAgeSA9ICJQaHlzaWNhbCBOZWdsZWN0IFNjb3JlIikgKyBnZ2hpc3RvCgojZW1vdGlvbmFsIGFidXNlIHggc2V4CnQudGVzdChXSzJfQ1RRU0ZfRW1vQWJ1X1JTIH4gRURfR2VuZGVyQmlydGhDZXJ0LCBkYXRhID0gZGYsdmFyLmVxdWFsID0gRkFMU0UpCnA1IDwtIGdncGxvdChkZiwgYWVzKHggPSBFRF9HZW5kZXJCaXJ0aENlcnQsIHkgPSBXSzJfQ1RRU0ZfRW1vQWJ1X1JTKSkgKwogIGdlb21fYm94cGxvdChsd2QgPSAuOSwgZmlsbD1jKCJwaW5rIiwic2t5Ymx1ZSIpKSArCiAgbGFicyh0aXRsZSA9ICJFbW90aW9uYWwgQWJ1c2UgYnkgR2VuZGVyIiwKICAgICAgIHggPSAiICIsCiAgICAgICB5ID0gIkVtb3Rpb25hbCBBYnVzZSBTY29yZSIpICsgZ2doaXN0bwoKI2Vtb3Rpb25hbCBuZWdsZWN0IHggc2V4CnQudGVzdChXSzJfQ1RRU0ZfRW1vTmVnX1JTIH4gRURfR2VuZGVyQmlydGhDZXJ0LCBkYXRhID0gZGYsdmFyLmVxdWFsID0gRkFMU0UpCnA2IDwtIGdncGxvdChkZiwgYWVzKHggPSBFRF9HZW5kZXJCaXJ0aENlcnQsIHkgPSBXSzJfQ1RRU0ZfRW1vTmVnX1JTKSkgKwogIGdlb21fYm94cGxvdChsd2QgPSAuOSwgZmlsbD1jKCJwaW5rIiwic2t5Ymx1ZSIpKSArCiAgbGFicyh0aXRsZSA9ICJFbW90aW9uYWwgTmVnbGVjdCBieSBHZW5kZXIiLAogICAgICAgeCA9ICIgIiwKICAgICAgIHkgPSAiRW1vdGlvbmFsIE5lZ2xlY3QgU2NvcmUiKSArIGdnaGlzdG8KCiNidWxseWluZyB4IHNleApwNyA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gRURfR2VuZGVyQmlydGhDZXJ0LCB5ID0gV0syX0J1bGx5aW5nX1RvdGFsKSkgKwogIGdlb21fYm94cGxvdChsd2QgPSAuOSwgZmlsbD1jKCJwaW5rIiwic2t5Ymx1ZSIpKSArCiAgbGFicyh0aXRsZSA9ICJCdWxseWluZyBieSBHZW5kZXIiLAogICAgICAgeCA9ICIgIiwKICAgICAgIHkgPSAiQnVsbHlpbmcgU2NvcmUiKSArIGdnaGlzdG8KCmN0cS5zZXgucGxvdHMgPC0gZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBuY29sID0gMykKCiNzYXZlIHRoZXNlIHBsb3RzIHRvIGEgcGRmCiNnZ3NhdmUoImN0cS5zZXgucGxvdHMucGRmIiwgY3RxLnNleC5wbG90cywgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTApCgoKI3dlbGNoZXMgdCB0ZXN0IGZvciBzZXggZGlmZmVyZW5jZXMgaW4gYnVsbHlpbmcKdC50ZXN0KFdLMl9CdWxseWluZ19Ub3RhbCB+IEVEX0dlbmRlckJpcnRoQ2VydCwgZGF0YSA9IGRmLHZhci5lcXVhbCA9IEZBTFNFKQpgYGAKCjxicj4KCiMjIyMgUkFDRSB4IENUUSBzdGF0cwoKYGBge3J9CiNMb29rIGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBSQUNFIGFuZCBlYWNoIENUUSBjYXRlZ29yeQojIExpc3Qgb2YgQ1RRIGNhdGVnb3JpZXMgYW5kIHRoZWlyIGNvcnJlc3BvbmRpbmcgY29sdW1ucwpjdHFfdGVzdHMgPC0gbGlzdCgKICBDVFFfVG90YWwgPSAiQ1RRX1RvdGFsIiwKICBQaHlzaWNhbF9BYnVzZSA9ICJXSzJfQ1RRU0ZfUGh5QWJ1X1JTIiwKICBQaHlzaWNhbF9OZWdsZWN0ID0gIldLMl9DVFFTRl9QaHlOZWdfUlMiLAogIEVtb3Rpb25hbF9BYnVzZSA9ICJXSzJfQ1RRU0ZfRW1vQWJ1X1JTIiwKICBFbW90aW9uYWxfTmVnbGVjdCA9ICJXSzJfQ1RRU0ZfRW1vTmVnX1JTIiwKICBTZXh1YWxfQWJ1c2UgPSAiV0syX0NUUVNGX1NleEFidV9SUyIsCiAgQnVsbHlpbmcgPSAiV0syX0J1bGx5aW5nX1RvdGFsIgopCgojIEluaXRpYWxpemUgYSB2ZWN0b3IgdG8gc3RvcmUgc2lnbmlmaWNhbnQgcmVzdWx0cwpzaWduaWZpY2FudF90ZXN0cyA8LSBjKCkKCiMgUGVyZm9ybSBLcnVza2FsLVdhbGxpcyB0ZXN0IGFuZCBEdW5uJ3MgdGVzdCBmb3IgZWFjaCBDVFEgY2F0ZWdvcnkKZm9yIChuYW1lIGluIG5hbWVzKGN0cV90ZXN0cykpIHsKICBjYXQoIlRlc3Rpbmc6IiwgbmFtZSwgIlxuIikKICBrd190ZXN0IDwtIGtydXNrYWwudGVzdChkZltbY3RxX3Rlc3RzW1tuYW1lXV1dXSB+IGRmJEVEX1JhY2VFdGhDb2RlKQogIHByaW50KGt3X3Rlc3QpICAKICBpZiAoa3dfdGVzdCRwLnZhbHVlIDwgMC4wNSkgewogICAgY2F0KCJLcnVza2FsLVdhbGxpcyB0ZXN0IHNpZ25pZmljYW50IChwIDwgMC4wNSkuIFBlcmZvcm1pbmcgRHVubidzIHRlc3QuLi5cbiIpCiAgICBkdW5uX3Jlc3VsdCA8LSBkdW5uLnRlc3QoZGZbW2N0cV90ZXN0c1tbbmFtZV1dXV0sIGRmJEVEX1JhY2VFdGhDb2RlLCBtZXRob2QgPSAiYmgiKSAKICAgIHByaW50KGR1bm5fcmVzdWx0KQogICAgc2lnbmlmaWNhbnRfdGVzdHMgPC0gYyhzaWduaWZpY2FudF90ZXN0cywgbmFtZSkKICB9IGVsc2UgewogICAgY2F0KCJLcnVza2FsLVdhbGxpcyB0ZXN0IG5vdCBzaWduaWZpY2FudCAocCA+PSAwLjA1KS4gU2tpcHBpbmcgRHVubidzIHRlc3QuXG4iKQogIH0KICBjYXQoIlxuIikgCn0KCiMgUHJpbnQgbmFtZXMgb2Ygc2lnbmlmaWNhbnQgQ1RRIGNhdGVnb3JpZXMKaWYgKGxlbmd0aChzaWduaWZpY2FudF90ZXN0cykgPiAwKSB7CiAgY2F0KCJDVFEgY2F0ZWdvcmllcyB3aXRoIHNpZ25pZmljYW50IEtydXNrYWwtV2FsbGlzIHRlc3QgYW5kIGNvcnJlc3BvbmRpbmcgRHVubidzIHRlc3QgcmVzdWx0czpcbiIpCiAgY2F0KHBhc3RlKHNpZ25pZmljYW50X3Rlc3RzLCBjb2xsYXBzZSA9ICJcbiIpKQp9IGVsc2UgewogIGNhdCgiTm8gQ1RRIGNhdGVnb3JpZXMgd2l0aCBzaWduaWZpY2FudCBLcnVza2FsLVdhbGxpcyB0ZXN0LlxuIikKfQpgYGAKCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShrbml0cikKbGlicmFyeShndCkKCmRmICU+JQogIGdyb3VwX2J5KEVEX1JhY2VFdGhDb2RlKSAlPiUKICBzdW1tYXJpemUoCiAgICBNZWFuX0NUUV9Ub3QgPSBtZWFuKENUUV9Ub3RhbCwgbmEucm0gPSBUUlVFKSwKICAgIFNEX0NUUV9Ub3QgPSBzZChDVFFfVG90YWwsIG5hLnJtID0gVFJVRSksCiAgICBNZWFuX1BoeXNfQWJ1c2UgPSBtZWFuKFdLMl9DVFFTRl9QaHlBYnVfUlMsIG5hLnJtID0gVFJVRSksCiAgICBTRF9QaHlzX0FidXNlID0gc2QoV0syX0NUUVNGX1BoeUFidV9SUywgbmEucm0gPSBUUlVFKSwKICAgIE1lYW5fUGh5c19OZWdsZWN0ID0gbWVhbihXSzJfQ1RRU0ZfUGh5TmVnX1JTLCBuYS5ybSA9IFRSVUUpLAogICAgU0RfUGh5c19OZWdsZWN0ID0gc2QoV0syX0NUUVNGX1BoeU5lZ19SUywgbmEucm0gPSBUUlVFKSwKICAgIE1lYW5fRW1vX0FidXNlID0gbWVhbihXSzJfQ1RRU0ZfRW1vQWJ1X1JTLCBuYS5ybSA9IFRSVUUpLAogICAgU0RfRW1vX0FidXNlID0gc2QoV0syX0NUUVNGX0Vtb0FidV9SUywgbmEucm0gPSBUUlVFKSwKICAgIE1lYW5fRW1vX05lZ2xlY3QgPSBtZWFuKFdLMl9DVFFTRl9FbW9OZWdfUlMsIG5hLnJtID0gVFJVRSksCiAgICBTRF9FbW9fTmVnbGVjdCA9IHNkKFdLMl9DVFFTRl9FbW9OZWdfUlMsIG5hLnJtID0gVFJVRSksCiAgICBNZWFuX1NleF9BYnVzZSA9IG1lYW4oV0syX0NUUVNGX1NleEFidV9SUywgbmEucm0gPSBUUlVFKSwKICAgIFNEX1NleF9BYnVzZSA9IHNkKFdLMl9DVFFTRl9TZXhBYnVfUlMsIG5hLnJtID0gVFJVRSksCiAgICBNZWFuX0J1bGx5aW5nID0gbWVhbihXSzJfQnVsbHlpbmdfVG90YWwsIG5hLnJtID0gVFJVRSksCiAgICBTRF9CdWxseWluZyA9IHNkKFdLMl9CdWxseWluZ19Ub3RhbCwgbmEucm0gPSBUUlVFKQogICkgJT4lCiAgZ3QoKSAlPiUKICB0YWJfaGVhZGVyKAogICAgdGl0bGUgPSAiTWVhbiBhbmQgU3RhbmRhcmQgRGV2aWF0aW9uIG9mIENUUSBTY29yZXMgYnkgUmFjZSIKICApICU+JQogIGZtdF9udW1iZXIoCiAgICBjb2x1bW5zID0gdmFycyhzdGFydHNfd2l0aCgiTWVhbiIpLCBzdGFydHNfd2l0aCgiU0QiKSksCiAgICBkZWNpbWFscyA9IDIKICApCmBgYAoKPGJyPgoKIyMjIyBBREkgYW5kIFBESQoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoZ2dwdWJyKQoKY29yX3Jlc3VsdHMgPC0gbGlzdCgKICAiQURJIHZzIFBESSIgPSBjb3IudGVzdChkZiRBRElfTmF0UmFuaywgZGYkRURfUERJX1JTLCB1c2U9ImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9ICJzcGVhcm1hbiIpLAogICJBREkgdnMgQ1RRIiA9IGNvci50ZXN0KGRmJEFESV9OYXRSYW5rLCBkZiRDVFFfVG90YWwsIHVzZT0iY29tcGxldGUub2JzIiwgbWV0aG9kID0gInNwZWFybWFuIiksCiAgIlBESSB2cyBDVFEiID0gY29yLnRlc3QoZGYkRURfUERJX1JTLCBkZiRDVFFfVG90YWwsIHVzZT0iY29tcGxldGUub2JzIiwgbWV0aG9kID0gInNwZWFybWFuIikpCgojcHJpbnQgdGhlIG51bWJlciBvZiBjb21wbGV0ZSBjYXNlcyBmb3IgZWFjaCBvZiBBREksIFBESSwgYW5kIENUUQpzdW0oY29tcGxldGUuY2FzZXMoZGYkQURJX05hdFJhbmspKQpzdW0oY29tcGxldGUuY2FzZXMoZGYkRURfUERJX1JTKSkKc3VtKGNvbXBsZXRlLmNhc2VzKGRmJENUUV9Ub3RhbCkpCgojcHJpbnQgdGhlIG51bWJlciBvZiBjb21wbGV0ZSBjYXNlcyBvdmVybGFwcGluZyBiZXR3ZWVuIFBESSBhbmQgQURJCnN1bShjb21wbGV0ZS5jYXNlcyhkZiRBRElfTmF0UmFuaywgZGYkRURfUERJX1JTKSkKCmRhdGEuZnJhbWUoCiAgQ29tcGFyaXNvbiA9IG5hbWVzKGNvcl9yZXN1bHRzKSwKICByaG8gPSBzYXBwbHkoY29yX3Jlc3VsdHMsIGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsIDYpKSwKICBwX3ZhbHVlID0gc2FwcGx5KGNvcl9yZXN1bHRzLCBmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsIDYpKSkKYGBgCgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiNwbG90IG9mIFBESSB4IENUUQpwMSA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gRURfUERJX1JTLCB5ID0gQ1RRX1RvdGFsKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIHNpemU9MykgKyAgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAibWFnZW50YTMiLCBsd2Q9MykgKyAgCiAgc3RhdF9jb3IobWV0aG9kID0gInNwZWFybWFuIiwgbGFiZWwueCA9IDMsIGxhYmVsLnkgPSBtYXgoZGYkQ1RRX1RvdGFsKS0yKSArIAogIGxhYnModGl0bGUgPSAiU2NhdHRlciBQbG90IG9mIFBESSB2cyBDVFEgVG90YWwiLAogICAgICAgeCA9ICJQREkiLCB5ID0gIkNUUSBUb3RhbCIpICsgZ2doaXN0bwoKI1Bsb3Qgb2YgQURJIHggQ1RRCnAyIDwtIGdncGxvdChkZiwgYWVzKHggPSBBRElfTmF0UmFuaywgeSA9IENUUV9Ub3RhbCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zLCBzaXplPTMpICsgIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInB1cnBsZTMiLCBsd2Q9MykgKyAgCiAgc3RhdF9jb3IobWV0aG9kID0gInNwZWFybWFuIiwgbGFiZWwueCA9IDMsIGxhYmVsLnkgPSBtYXgoZGYkQ1RRX1RvdGFsKS0yKSArIAogIGxhYnModGl0bGUgPSAiU2NhdHRlciBQbG90IG9mIEFESSB2cyBDVFEgVG90YWwiLAogICAgICAgeCA9ICJBREkiLCB5ID0gIkNUUSBUb3RhbCIpICsgZ2doaXN0bwoKZ3JpZC5hcnJhbmdlKHAxLHAyKQpgYGAKCiMjIyMgQ1RRIHggUkFDRSBwbG90cwoKYGBge3J9CnA3IDwtIGdncGxvdChkZiAlPiUgZmlsdGVyKCFpcy5uYShFRF9SYWNlRXRoQ29kZSkpLCBhZXMoeCA9IEVEX1JhY2VFdGhDb2RlLCB5ID0gQ1RRX1RvdGFsLCBmaWxsID0gRURfUmFjZUV0aENvZGUpKSArCiAgZ2VvbV9ib3hwbG90KGx3ZCA9IC45KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJDb21wb3NpdGUgQ1RRIGJ5IFJhY2UiLAogICAgICAgeCA9ICIgIiwgeSA9ICJDVFEgQ29tcG9zaXRlIFNjb3JlIikgKyBnZ2hpc3RvCgojIFNleHVhbCBhc3NhdWx0IENUUSB4IHJhY2UKcDggPC0gZ2dwbG90KGRmICU+JSBmaWx0ZXIoIWlzLm5hKEVEX1JhY2VFdGhDb2RlKSksIGFlcyh4ID0gRURfUmFjZUV0aENvZGUsIHkgPSBXSzJfQ1RRU0ZfU2V4QWJ1X1JTLCBmaWxsID0gRURfUmFjZUV0aENvZGUpKSArCiAgZ2VvbV9ib3hwbG90KGx3ZCA9IC45KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJTZXh1YWwgQWJ1c2UgYnkgUmFjZSIsCiAgICAgICB4ID0gIiAiLCB5ID0gIlNleHVhbCBBYnVzZSBTY29yZSIpICsgZ2doaXN0bwoKIyBwaHlzaWNhbCBhYnVzZSB4IHJhY2UKcDkgPC0gZ2dwbG90KGRmICU+JSBmaWx0ZXIoIWlzLm5hKEVEX1JhY2VFdGhDb2RlKSksIGFlcyh4ID0gRURfUmFjZUV0aENvZGUsIHkgPSBXSzJfQ1RRU0ZfUGh5QWJ1X1JTLCBmaWxsID0gRURfUmFjZUV0aENvZGUpKSArCiAgZ2VvbV9ib3hwbG90KGx3ZCA9IC45KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJQaHlzaWNhbCBBYnVzZSBieSBSYWNlIiwKICAgICAgIHggPSAiICIsIHkgPSAiUGh5c2ljYWwgQWJ1c2UgU2NvcmUiKSArIGdnaGlzdG8KCiMgcGh5c2ljYWwgbmVnbGVjdCB4IHJhY2UKcDEwIDwtIGdncGxvdChkZiAlPiUgZmlsdGVyKCFpcy5uYShFRF9SYWNlRXRoQ29kZSkpLCBhZXMoeCA9IEVEX1JhY2VFdGhDb2RlLCB5ID0gV0syX0NUUVNGX1BoeU5lZ19SUywgZmlsbCA9IEVEX1JhY2VFdGhDb2RlKSkgKwogIGdlb21fYm94cGxvdChsd2QgPSAuOSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnModGl0bGUgPSAiUGh5c2ljYWwgTmVnbGVjdCBieSBSYWNlIiwKICAgICAgIHggPSAiICIsIHkgPSAiUGh5c2ljYWwgTmVnbGVjdCBTY29yZSIpICsgZ2doaXN0bwoKI2Vtb3Rpb25hbCBhYnVzZSB4IHJhY2UKcDExIDwtIGdncGxvdChkZiAlPiUgZmlsdGVyKCFpcy5uYShFRF9SYWNlRXRoQ29kZSkpLCBhZXMoeCA9IEVEX1JhY2VFdGhDb2RlLCB5ID0gV0syX0NUUVNGX0Vtb0FidV9SUywgZmlsbCA9IEVEX1JhY2VFdGhDb2RlKSkgKyBnZW9tX2JveHBsb3QobHdkID0gLjkpICsKdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJFbW90aW9uYWwgQWJ1c2UgYnkgUmFjZSIsCiAgICAgICB4ID0gIiAiLCB5ID0gIkVtb3Rpb25hbCBBYnVzZSBTY29yZSIpICsgZ2doaXN0bwoKI2Vtb3Rpb25hbCBuZWdsZWN0IHggcmFjZQpwMTIgPC0gZ2dwbG90KGRmICU+JSBmaWx0ZXIoIWlzLm5hKEVEX1JhY2VFdGhDb2RlKSksIGFlcyh4ID0gRURfUmFjZUV0aENvZGUsIHkgPSBXSzJfQ1RRU0ZfRW1vTmVnX1JTLCBmaWxsID0gRURfUmFjZUV0aENvZGUpKSArIGdlb21fYm94cGxvdChsd2QgPSAuOSkgKyBsYWJzKHRpdGxlID0gIkVtb3Rpb25hbCBOZWdsZWN0IGJ5IFJhY2UiLAogICAgICAgeCA9ICIgIiwgeSA9ICJFbW90aW9uYWwgTmVnbGVjdCBTY29yZSIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIGdnaGlzdG8KCiNidWxseWluZyB4IHJhY2UKcDEzIDwtIGdncGxvdChkZiAlPiUgZmlsdGVyKCFpcy5uYShFRF9SYWNlRXRoQ29kZSkpLCBhZXMoeCA9IEVEX1JhY2VFdGhDb2RlLCB5ID0gV0syX0J1bGx5aW5nX1RvdGFsLCBmaWxsID0gRURfUmFjZUV0aENvZGUpKSArIGdlb21fYm94cGxvdChsd2QgPSAuOSkgKyBsYWJzKHRpdGxlID0gIkJ1bGx5aW5nIGJ5IFJhY2UiLCAKICAgICAgIHggPSAiICIsIHkgPSAiQnVsbHlpbmcgU2NvcmUiKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyBnZ2hpc3RvICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKY3RxLnJhY2UucGxvdHNfc2ltcGxlIDwtIGdyaWQuYXJyYW5nZShwNywgcDgsIHA5LCBwMTAsIHAxMSwgcDEyLCBwMTMsIG5jb2wgPSAzKSAKCiNzYXZlIGFzIHBkZgojZ2dzYXZlKCJjdHEucmFjZS5wbG90c19zaW1wbGUucGRmIiwgY3RxLnJhY2UucGxvdHNfc2ltcGxlLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCkKCmBgYAojIyMjIFBsb3RzIGZvciBzdXBwbGVtZW50YXJ5IHNlY3Rpb24gb2YgcGFwZXIKMS4gb25lIG91dCBwdXQgb2YgdHdvIGdyYXBoczogb25lIGdyYXBoIHdpdGggQ1RRIHRvdGFsIGJ5IHNleCwgYW5kIG90aGVyIGdyYXBoIGlzIENUUSB0b3RhbCBieSByYWNlLiBhbmQgYWRkIHNpZyBub3RhdGlvbiBmb3Igc2V4LCBucyBmb3IgcmFjZQoyLiBtYWtlIGdyYXBocyBvZiBzdWJ0eXBlcyAoaW5jbCBidWxseWluZyBpbnN0ZWFkIG9mIGN0cSB0b3RhbCkgc28gd2UgaGF2ZSAyeDMgdGFibGUgYW5kIGluY2x1ZGUgYXN0ZXJpc2tzIGZvciBzaWcKYGBge3J9CmxpYnJhcnkoZ2dzaWduaWYpCgoKZ2dwbG90KGRmLCBhZXMoeCA9IEVEX0dlbmRlckJpcnRoQ2VydCwgeSA9IENUUV9Ub3RhbCwgZmlsbCA9IEVEX0dlbmRlckJpcnRoQ2VydCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgbGFicyh0aXRsZSA9ICJCb3hwbG90IG9mIENUUSBUb3RhbCBieSBTZXgiLAogICAgICAgeCA9ICJTZXgiLAogICAgICAgeSA9ICJDVFEgVG90YWwiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygicGluayIsICJza3libHVlIikpICsgZ2doaXN0bwoKI3R0ZXN0IG9mIGN0cSB0b3RhbCBieSBzZXgKdC50ZXN0KENUUV9Ub3RhbCB+IEVEX0dlbmRlckJpcnRoQ2VydCwgZGF0YSA9IGRmKQpgYGAKCiMjIyMgIERlc2NyaXB0aXZlIHN0YXRzIGZvciBwYXBlcgpgYGB7cn0KI2NhbGN1bGF0ZSB0aGUgJSBvZiBwYXJ0aWNpcGFudHMgcmVwb3J0ZWQgZXhwZXJpZW5jaW5nIGF0IGxlYXN0IG9uZSBpbnN0YW5jZSBvZiBhbnkgdHlwZSBvZiBFTEEgKGkuZS4gZWl0aGVyIENUUeKJpTEgb3IgY2hpbGRob29kIEJ1bGx5aW5nIOKJpTEpICBhbmQgdGhlIE0gKFNEKSBmb3IgY29tcG9zaXRlIENUUQpkZiAlPiUgCiAgc3VtbWFyaXplKHBlcmNfYW55X0VMQSA9IG1lYW4oQ1RRX1RvdGFsID49IDEgfCBXSzJfQnVsbHlpbmdfVG90YWwgPj0gMSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgbWVhbl9DVFEgPSBtZWFuKENUUV9Ub3RhbCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc2RfQ1RRID0gc2QoQ1RRX1RvdGFsLCBuYS5ybSA9IFRSVUUpKQpgYGAKCmhvdyBtYW55IHBlb3BsZSBoYWQgYXQgYSBzY29yZSBvZiAxIG9yIG1vcmUgZm9yIGF0IGxlYXN0IHR3byBkaWZmZXJlbnQgQ1RRIHN1YnR5cGVzCmBgYHtyfQojIENyZWF0ZSBhIGxvZ2ljYWwgbWF0cml4IHdoZXJlIFRSVUUgaW5kaWNhdGVzIGEgc2NvcmUgb2YgMSBvciBtb3JlCmxvZ2ljYWxfbWF0cml4IDwtIGRmICU+JQogIHNlbGVjdChXSzJfQ1RRU0ZfUGh5QWJ1X1JTLCBXSzJfQ1RRU0ZfUGh5TmVnX1JTLCBXSzJfQ1RRU0ZfRW1vQWJ1X1JTLCAKICAgICAgICAgV0syX0NUUVNGX0Vtb05lZ19SUywgV0syX0NUUVNGX1NleEFidV9SUywgV0syX0J1bGx5aW5nX1RvdGFsKSAlPiUKICBtdXRhdGUoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgfiAuID49IDEpKQoKIyBDb3VudCB0aGUgbnVtYmVyIG9mIFRSVUUgdmFsdWVzIGluIGVhY2ggcm93CmRmJGN0cV90b3RhbF9jb3VudCA8LSByb3dTdW1zKGxvZ2ljYWxfbWF0cml4KQoKIyBGaWx0ZXIgaW5kaXZpZHVhbHMgd2l0aCBhdCBsZWFzdCAyIENUUSBzdWJ0eXBlcyB3aXRoIHNjb3JlcyBvZiAxIG9yIG1vcmUKc3VtKGRmJGN0cV90b3RhbF9jb3VudCA+PSAyKQoKI3doYXQgaXMgdGhlIG1vc3QgY29tbW9uIGN0cSBzdWJ0eXBlIHdpdGggcGVyY2VudGFnZXMgb3V0IG9mIDI0ODAKZGYgJT4lIAogIHNlbGVjdChXSzJfQ1RRU0ZfUGh5QWJ1X1JTLCBXSzJfQ1RRU0ZfUGh5TmVnX1JTLCBXSzJfQ1RRU0ZfRW1vQWJ1X1JTLCAKICAgICAgICAgV0syX0NUUVNGX0Vtb05lZ19SUywgV0syX0NUUVNGX1NleEFidV9SUywgV0syX0J1bGx5aW5nX1RvdGFsKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiQ1RRX1N1YnR5cGUiLCB2YWx1ZXNfdG8gPSAiU2NvcmUiKSAlPiUKICBmaWx0ZXIoU2NvcmUgPj0gMSkgJT4lCiAgY291bnQoQ1RRX1N1YnR5cGUpICU+JQogIGFycmFuZ2UoZGVzYyhuKSkgJT4lCiAgbXV0YXRlKHBlcmMgPSBuLzI0ODApCmBgYAoKCmBgYHtyfQojaG93IG1hbnkgY2FzZXMgaW4gdGhlIGRmIGhhZCBlaXRoZXIgYnVsbHlpbmcgc2NvcmUgMSsgb3IgdG90YWwgQ1RRIHNjb3JlIDErCmRmICU+JSBmaWx0ZXIoQ1RRX1RvdGFsID49IDEgfCBXSzJfQnVsbHlpbmdfVG90YWwgPj0gMSkgJT4lIG5yb3coKQoKI3R0ZXN0IGNvbXBhcmluZyBjdHEgaW4gbWVuIHZzIHdvbWVuCnQudGVzdChDVFFfVG90YWwgfiBFRF9HZW5kZXJCaXJ0aENlcnQsIGRhdGEgPSBkZikKCiNjYWNsdWxjYXRlIHN0ZCBpbiBhZGRpdGlvbiB0byBtZWFucyBmb3Igc2V4CmRmICU+JSAKICBncm91cF9ieShFRF9HZW5kZXJCaXJ0aENlcnQpICU+JSAKICBzdW1tYXJpemUobWVhbl9DVFEgPSBtZWFuKENUUV9Ub3RhbCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc2RfQ1RRID0gc2QoQ1RRX1RvdGFsLCBuYS5ybSA9IFRSVUUpKQoKI3dlbGNoZXMgdCB0ZXN0IGZvciBzZXggZGlmZmVyZW5jZXMgaW4gYnVsbHlpbmcKdC50ZXN0KFdLMl9CdWxseWluZ19Ub3RhbCB+IEVEX0dlbmRlckJpcnRoQ2VydCwgZGF0YSA9IGRmLHZhci5lcXVhbCA9IEZBTFNFKQpgYGAKCgoKPGJyPgoKIyMjIyBDb3JyZWxhdGlvbnMgdGFibGUgY3N2CgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBEZWZpbmUgdGhlIGNvbHVtbnMgdG8gY29ycmVsYXRlCmNvbHVtbnMgPC0gY29sbmFtZXMoZGYpWzE2OjIyXQoKI3NwZWFybWFuIGNvcnJlbGF0aW9uIGJldHdlZW4gYnVsbHlpbmcgYW5kIGVhY2ggQ1RRIHR5cGUKY29yLnRlc3QoZGYkV0syX0J1bGx5aW5nX1RvdGFsLCBkZiRXSzJfQ1RRU0ZfUGh5QWJ1X1JTLCBtZXRob2QgPSAic3BlYXJtYW4iKQpjb3IudGVzdChkZiRXSzJfQnVsbHlpbmdfVG90YWwsIGRmJFdLMl9DVFFTRl9FbW9BYnVfUlMsIG1ldGhvZCA9ICJzcGVhcm1hbiIpCmNvci50ZXN0KGRmJFdLMl9CdWxseWluZ19Ub3RhbCwgZGYkV0syX0NUUVNGX1NleEFidV9SUywgbWV0aG9kID0gInNwZWFybWFuIikKY29yLnRlc3QoZGYkV0syX0J1bGx5aW5nX1RvdGFsLCBkZiRXSzJfQ1RRU0ZfUGh5TmVnX1JTLCBtZXRob2QgPSAic3BlYXJtYW4iKQpjb3IudGVzdChkZiRXSzJfQnVsbHlpbmdfVG90YWwsIGRmJFdLMl9DVFFTRl9FbW9OZWdfUlMsIG1ldGhvZCA9ICJzcGVhcm1hbiIpCgoKIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgU3BlYXJtYW4gY29ycmVsYXRpb25zLCBwLXZhbHVlcywgYW5kIG51bWJlciBvZiBjb21wbGV0ZSBjYXNlcwpjb3JyZWxhdGlvbl9zdW1tYXJ5IDwtIGZ1bmN0aW9uKHgsIHkpIHsKICBjb3JfdGVzdCA8LSBjb3IudGVzdChkZltbeF1dLCBkZltbeV1dLCBtZXRob2QgPSAic3BlYXJtYW4iKQogIAogIHRpYmJsZSgKICAgIFZhcmlhYmxlMSA9IHgsCiAgICBWYXJpYWJsZTIgPSB5LAogICAgUmhvID0gY29yX3Rlc3QkZXN0aW1hdGUsCiAgICBQX1ZhbHVlID0gY29yX3Rlc3QkcC52YWx1ZSwKICApCn0KCiMgQ3JlYXRlIGEgc3VtbWFyeSB0YWJsZQphbGxfY3RxX2NvcnJlbGF0aW9ucyA8LSBleHBhbmRfZ3JpZChWYXJpYWJsZTEgPSBjb2x1bW5zLCBWYXJpYWJsZTIgPSBjb2x1bW5zKSAlPiUKICBmaWx0ZXIoVmFyaWFibGUxICE9IFZhcmlhYmxlMikgJT4lCiAgcG1hcF9kZnIofiBjb3JyZWxhdGlvbl9zdW1tYXJ5KC4uMSwgLi4yKSkKCiNzYXZlIGN0cSBjb3JyZWxhdGlvbnMgdG8gYSBjc3YKd3JpdGUuY3N2KGFsbF9jdHFfY29ycmVsYXRpb25zLCAiYWxsX0VMQV9jb3JyZWxhdGlvbnNfZm9yX0xhdXJlbi5jc3YiKQpgYGAKCiMjIyMgSGVhdG1hcCBvZiBjb3JyZWxhdGlvbnMKCmBgYHtyfQojIENvbXB1dGUgdGhlIGNvcnJlbGF0aW9uIG1hdHJpeApjb3JfbWF0cml4IDwtIGNvcihkZlssYygxNjoyMildLCB1c2UgPSAiY29tcGxldGUub2JzIiwgbWV0aG9kPSJzcGVhcm1hbiIpCgojbWFrZSBhIHRhYmxlIHRoYXQgZ2l2ZXMgdGhlIGNvcnJlbGF0aW9uIHJobywgcC12YWx1ZSwgYW5kIHNhbXBsZSBzaXplIGZvciBlYWNoIHNwZWFybWFuIGNvcnJlbGF0aW9uCmNvcl90YWJsZSA8LSBjb3IubXRlc3QoZGZbLGMoMTY6MjIpXSwgY29uZi5sZXZlbCA9IDAuOTUsIG1ldGhvZCA9ICJzcGVhcm1hbiIpCgoKI3NhdmUgY29yX21hdHJpeCBhcyBhIGNzdgp3cml0ZS5jc3YoY29yX21hdHJpeCwgIkVMQV9jb3JfbWF0cml4X2Zvcl9MYXVyZW4uY3N2IikKCiMgUGxvdCB0aGUgY29ycmVsYXRpb24gbWF0cml4CmdnY29ycnBsb3QoY29yX21hdHJpeCwgbGFiID0gVFJVRSkKCmNvcnJwbG90KGNvcl9tYXRyaXgsIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLAogICAgICAgICB0bC5jb2wgPSAiYmxhY2siLCB0bC5zcnQgPSA0NSwgYWRkQ29lZi5jb2wgPSAiYmxhY2siLAogICAgICAgICBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDIwMCkpCmBgYAoKIyMjIyBFeHBsb3JlIGRhdGEgdmFsaWRpdHkKCgoKRXhhbWluZSBkYXRhIGRpc3RyaWJ1dGlvbnMKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQpwMSA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gQ1RRX1RvdGFsLCBmaWxsID0gRURfR2VuZGVyQmlydGhDZXJ0KSkgKyAKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQsIGxpbmV3aWR0aD0xLjUpICsgCiAgbGFicyh0aXRsZSA9ICJEZW5zaXR5IFBsb3Qgb2YgQ1RRIFRvdGFsIGJ5IFNleCIsCiAgICAgICB4ID0gIkNUUSBTY29yZSIsCiAgICAgICB5ID0gIkRlbnNpdHkiKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJob3RwaW5rIiwic2t5Ymx1ZSIpKSArCiAgZ2doaXN0byArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjc1KSkKCnAyIDwtIGdncGxvdChuYS5vbWl0KGRmWywgYygiQ1RRX1RvdGFsIiwgIkVEX1JhY2VFdGhDb2RlIildKSwgYWVzKHggPSBDVFFfVG90YWwsIGZpbGwgPSBFRF9SYWNlRXRoQ29kZSkpICsgCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC40LCBsaW5ld2lkdGggPSAxLjUpICsgCiAgbGFicyh0aXRsZSA9ICJEZW5zaXR5IFBsb3Qgb2YgQ1RRIFRvdGFsIGJ5IFJhY2UvRXRobmljaXR5IiwKICAgICAgIHggPSAiQ1RRIFNjb3JlIiwKICAgICAgIHkgPSAiRGVuc2l0eSIpICsgCiAgZ2doaXN0byArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjgsIDAuNzUpKQoKcDMgPC0gZ2dwbG90KG5hLm9taXQoZGZbLCBjKCJDVFFfVG90YWwiLCAiUFJFX1BhaW5fTWRTdiIpXSksIGFlcyh4ID0gQ1RRX1RvdGFsLCBmaWxsID0gYXMuZmFjdG9yKFBSRV9QYWluX01kU3YpKSkgKyAKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQsIGxpbmV3aWR0aCA9IDEuNSkgKyAKICBsYWJzKHRpdGxlID0gIkRlbnNpdHkgUGxvdCBvZiBDVFEgVG90YWwgYnkgUFJFIFBhaW4iLAogICAgICAgeCA9ICJDVFEgU2NvcmUiLAogICAgICAgeSA9ICJEZW5zaXR5IikgKyAKICB0aGVtZV9saWdodCgpICsKICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiaG90cGluayIsInNreWJsdWUiKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjc1KSkgKyBnZ2hpc3RvCgpwNCA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gQ1RRX1RyaWFkLCBmaWxsID0gRURfR2VuZGVyQmlydGhDZXJ0KSkgKyAKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQsIGxpbmV3aWR0aD0xLjUpICsgCiAgbGFicyh0aXRsZSA9ICJEZW5zaXR5IFBsb3Qgb2YgQ1RRIFRyaWFkIGJ5IFNleCIsCiAgICAgICB4ID0gIkNUUSBUcmlhZFNjb3JlIiwKICAgICAgIHkgPSAiRGVuc2l0eSIpICsgdGhlbWVfbGlnaHQoKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJob3RwaW5rIiwic2t5Ymx1ZSIpKSArCiAgZ2doaXN0byArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjc1KSkKCmdyaWQuYXJyYW5nZShwMSwgcDIsIHAzLCBwNCwgbmNvbCA9IDIpIApgYGAKCiMjIyBNb2RlbHMKCiMjIyMgTW9kZWwgMTogQmFzZSBNb2RlbAoKTWFpbiBtdWx0aS1ub21pbmFsIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBDVFEgYXMgYSBwcmVkaWN0b3IgdmFyaWFibGUsIGluY2x1ZGluZyBvdXIgc3RhbmRhcmQgY292YXJpYXRlcyAoc2FtZSBpbiBsaW5lYXIgbW9kZWxzKSwgYW5kIGxhdGVudCBwYWluIHRyYWplY3RvcmllcyBhcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlcy4gTW9kZWwgMiBpcyB0aGlzIHdpdGggZXh0cmEgZmVhdHVyZXMuIGV4dHJhY3QgbWFyZ2luYWwgbWVhbnMgZnJvbSBiYXNlIG1vZGVsIGZvciBtYWtpbmcgZ3JhcGhzCgpgYGB7cn0KI3BhaW4gdHJhamVjdG9yeSB+IGFnZSArIHNleCArIHJhY2UgKyBzaXRlICsgQ1RRCm0xIDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgQ1RRX1RvdGFsLCBkYXRhID0gZGYpCgojdmlldyBvdXRwdXQKdGlkeShtMSwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSkgCiNleGFtaW5lIHZhcmlhbmNlIGluZmxhdGlvbiBmYWN0b3IgdG8gYXNzZXNzIGNvbGxpbmVhcml0eQp2aWYobTEpCmBgYAoKVmFyaWFuY2UgSW5mbGF0aW9uIEZhY3RvciAoVklGKSBpcyB1c2VkIHRvIGRldGVjdCBtdWx0aWNvbGxpbmVhcml0eS4gVklGIFw+IDEwOiBJbmRpY2F0ZXMgaGlnaCBtdWx0aWNvbGxpbmVhcml0eSB0aGF0IG1pZ2h0IGJlIHByb2JsZW1hdGljLiBWSUYgYmV0d2VlbiA1IGFuZCAxMDogTW9kZXJhdGUgbXVsdGljb2xsaW5lYXJpdHkgdGhhdCBtaWdodCBuZWVkIGFkZHJlc3NpbmcuIFZJRiBcPCA1OiBHZW5lcmFsbHkgY29uc2lkZXJlZCBhY2NlcHRhYmxlLgoKPGJyPgoKUmVwZWF0IHRoaXMgYnV0IHdpdGggdGhlIHogdHJhbnNmb3JtZWQgZGF0YQoKYGBge3IsIGVjaG89RkFMU0V9CiNiYXNlIG1vZGVsCiN0cmFqZWN0b3J5IH4gYWdlICsgc2V4ICsgcmFjZSArIHNpdGUgKyBDVFEKbXogPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBDVFFfVG90YWwsIGRhdGEgPSBkZl90cmFqKQoKdGlkeShteiwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSkKYGBgCgojIyMjIE1vZGVsIDI6IEFkZGl0aW9uYWwgRmVhdHVyZXMKCmBgYHtyfQptMiA8LSBtdWx0aW5vbShQYWluX0NsYXNzIH4gRURfQWdlICsgU2l0ZV9OZXcgKyBFRF9SYWNlRXRoQ29kZSArIEVEX0dlbmRlckJpcnRoQ2VydCArIENUUV9Ub3RhbCArIEJNSSArIFBSRV9QYWluX01kU3YgKyBFRF9NYXJpdGFsICsgQURJX05hdFJhbmsgKyBFRF9FdmVudF9Ccm9hZENsYXNzICsgRURfUERJX1JTLCBkYXRhID0gZGYpCgp0aWR5KG0yLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQoKdmlmKG0yKQpgYGAKCgojIyMjIEludmVzdGlnYXRlIENvbGxpbmVhdG9yIGJldHdlZW4gY2F0ZWdvcmljYWwgdmFyaWFibGVzCmBgYHtyfQojIENyZWF0ZSBhIGxpc3Qgb2YgY2F0ZWdvcmljYWwgdmFyaWFibGVzIHRvIHRlc3QKY2F0ZWdvcmljYWxfdmFycyA8LSBjKCJFRF9HZW5kZXJCaXJ0aENlcnQiLCAiRURfTWFyaXRhbCIsICJFRF9SYWNlRXRoQ29kZSIsICJFRF9FdmVudF9Ccm9hZENsYXNzIiwgIlBhaW5fQ2xhc3MiKQoKIyBHZW5lcmF0ZSBhbGwgY29tYmluYXRpb25zIG9mIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwpjb21iaW5hdGlvbnMgPC0gY29tYm4oY2F0ZWdvcmljYWxfdmFycywgMiwgc2ltcGxpZnkgPSBGQUxTRSkKCiMgRnVuY3Rpb24gdG8gcGVyZm9ybSBjaGktc3F1YXJlIHRlc3QgYW5kIHJldHVybiByZXN1bHRzCnBlcmZvcm1fY2hpc3FfdGVzdCA8LSBmdW5jdGlvbih2YXIxLCB2YXIyLCBkYXRhKSB7CiAgdGFibGVfZGF0YSA8LSB0YWJsZShkYXRhW1t2YXIxXV0sIGRhdGFbW3ZhcjJdXSkKICB0ZXN0X3Jlc3VsdCA8LSBjaGlzcS50ZXN0KHRhYmxlX2RhdGEpCiAgcmVzdWx0IDwtIGxpc3QoCiAgICB2YXJpYWJsZXMgPSBwYXN0ZSh2YXIxLCAidnMiLCB2YXIyKSwKICAgIGNoaTIgPSB0ZXN0X3Jlc3VsdCRzdGF0aXN0aWMsCiAgICBwX3ZhbHVlID0gdGVzdF9yZXN1bHQkcC52YWx1ZQogICkKICByZXR1cm4ocmVzdWx0KQp9CgojIFBlcmZvcm0gY2hpLXNxdWFyZSB0ZXN0cyBvbiBhbGwgY29tYmluYXRpb25zCnJlc3VsdHMgPC0gbGFwcGx5KGNvbWJpbmF0aW9ucywgZnVuY3Rpb24odmFycykgcGVyZm9ybV9jaGlzcV90ZXN0KHZhcnNbMV0sIHZhcnNbMl0sIGRmKSkKCiMgUHJpbnQgcmVzdWx0cwpmb3IgKHJlc3VsdCBpbiByZXN1bHRzKSB7CiAgY2F0KCJDaGktU3F1YXJlIFRlc3QgZm9yIiwgcmVzdWx0JHZhcmlhYmxlcywgIlxuIikKICBjYXQoIkNoaS1TcXVhcmUgU3RhdGlzdGljOiIsIHJlc3VsdCRjaGkyLCAiXG4iKQogIGNhdCgiUC1WYWx1ZToiLCByZXN1bHQkcF92YWx1ZSwgIlxuXG4iKQp9CgpsaWJyYXJ5KGNoaXNxLnBvc3Rob2MudGVzdCkKY2hpc3EucG9zdGhvYy50ZXN0KHRhYmxlKGRmJEVEX1JhY2VFdGhDb2RlLCBkZiRFRF9HZW5kZXJCaXJ0aENlcnQpLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpCmBgYAoKIyMjIyBFeHBsb3JlIGludGVyYWN0aW9ucyBiZXR3ZWVuIHJhY2UgYW5kIG90aGVyIGNhdGVnb3JpZXMKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChkZiAlPiUgZHJvcF9uYShFRF9SYWNlRXRoQ29kZSwgRURfTWFyaXRhbCksIGFlcyh4ID0gRURfUmFjZUV0aENvZGUsIGZpbGwgPSBFRF9SYWNlRXRoQ29kZSkpICsKICBnZW9tX2JhcigpICsgZmFjZXRfd3JhcCh+IEVEX01hcml0YWwpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIjEiID0gIkhpc3BhbmljIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyIiA9ICJOSCBXaGl0ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMyIgPSAiTkggQmxhY2siLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjQiID0gIk90aGVyIikpKwogIGxhYnModGl0bGUgPSAiQ291bnRzIG9mIFJhY2UgRXRobmljaXR5IGJ5IE1hcml0YWwgU3RhdHVzIiwKICAgICAgIHggPSAiUmFjZSBFdGhuaWNpdHkiLCB5ID0gIkNvdW50IiwgZmlsbCA9ICJSYWNlIEV0aG5pY2l0eSIpICsgZ2doaXN0bwoKZ2dwbG90KGRmICU+JSBkcm9wX25hKEVEX1JhY2VFdGhDb2RlLCBFRF9HZW5kZXJCaXJ0aENlcnQpLCBhZXMoeCA9IEVEX1JhY2VFdGhDb2RlLCBmaWxsID0gRURfUmFjZUV0aENvZGUpKSArCiAgZ2VvbV9iYXIoKSArIGZhY2V0X3dyYXAofiBFRF9HZW5kZXJCaXJ0aENlcnQpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIjEiID0gIkhpc3BhbmljIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyIiA9ICJOSCBXaGl0ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMyIgPSAiTkggQmxhY2siLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjQiID0gIk90aGVyIikpKwogIGxhYnModGl0bGUgPSAiQ291bnRzIG9mIFJhY2UgRXRobmljaXR5IGJ5IFNleCIsCiAgICAgICB4ID0gIlJhY2UgRXRobmljaXR5IiwgeSA9ICJDb3VudCIsIGZpbGwgPSAiUmFjZSBFdGhuaWNpdHkiKSArIGdnaGlzdG8KCmdncGxvdChkZiAlPiUgZHJvcF9uYShFRF9SYWNlRXRoQ29kZSwgRURfaGlnaGVzdGdyYWRlKSwgYWVzKHggPSBFRF9SYWNlRXRoQ29kZSwgZmlsbCA9IEVEX1JhY2VFdGhDb2RlKSkgKwogIGdlb21fYmFyKCkgKyBmYWNldF93cmFwKH4gRURfaGlnaGVzdGdyYWRlKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCIxIiA9ICJIaXNwYW5pYyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSAiTkggV2hpdGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjMiID0gIk5IIEJsYWNrIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI0IiA9ICJPdGhlciIpKSsKICBsYWJzKHRpdGxlID0gIkNvdW50cyBvZiBSYWNlIEV0aG5pY2l0eSBieSBFZHVjYXRpb24iLAogICAgICAgeCA9ICJSYWNlIEV0aG5pY2l0eSIsIHkgPSAiQ291bnQiLCBmaWxsID0gIlJhY2UgRXRobmljaXR5IikgKyBnZ2hpc3RvCmBgYAoKIyMjIyBNb2RlbCAzOiBTZXgqQ1RRIGludGVyYWN0aW9uCgpgYGB7cn0KIzNyZCBtb2RlbCBpcyBzYW1lIGFzIE0yIGJ1dCB3aXRoIHNleCpDVFEgaW50ZXJhY3Rpb24KbTMgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBDVFFfVG90YWwgKyBCTUkgKyBQUkVfUGFpbl9NZFN2ICsgRURfQ29uY3Vzc2lvbiArIEVEX1BESV9SUyArIEVEX0dlbmRlckJpcnRoQ2VydCpDVFFfVG90YWwsIGRhdGEgPSBkZl90cmFqKQoKdGlkeShtMywgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSkKYGBgCgojIyMjIE1vZGVscyA0LTg6IENUUSBzdWJ0eXBlcwoKYGBge3J9CiM0dGggbW9kZWwgaXMgc2FtZSBhcyBtMCBidXQgb25seSB3ZWVrIDIgZW1vdGlvbmFsIGFidXNlIHNjYWxlCm00IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX0Vtb0FidV9SUywgZGF0YSA9IGRmX3RyYWopCgp0aWR5KG00LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCmBgYHtyfQojNXRoIG1vZGVsIGlzIHBoeXNpY2FsIGFidXNlCm01IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX1BoeUFidV9SUywgZGF0YSA9IGRmX3RyYWopCgp0aWR5KG01LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSU+JSAKICBmaWx0ZXIodGVybSA9PSAiQ1RRX1RvdGFsIikKCiNwaHlzaWNhbCBhYnVzZSpzZXggaW50ZXJhY3Rpb24gdGVybSBhZGRlZAptNWIgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBXSzJfQ1RRU0ZfUGh5QWJ1X1JTICsgV0syX0NUUVNGX1BoeUFidV9SUypFRF9HZW5kZXJCaXJ0aENlcnQsIGRhdGEgPSBkZl90cmFqKQoKdGlkeShtNWIsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpCmBgYAoKYGBge3J9CiM2dGggbW9kZWwgaXMgc2V4dWFsIGFidXNlCm02IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX1NleEFidV9SUywgZGF0YSA9IGRmX3RyYWopCgp0aWR5KG02LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCmBgYHtyfQojN3RoIG1vZGVsIGlzIGVtb3Rpb25hbCBuZWdsZWN0Cm03IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX0Vtb05lZ19SUywgZGF0YSA9IGRmX3RyYWopCgp0aWR5KG03LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCmBgYHtyfQojOHRoIG1vZGVsIGlzIHBoeXNpY2FsIG5lZ2xlY3QKbTggPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBXSzJfQ1RRU0ZfUGh5TmVnX1JTLCBkYXRhID0gZGZfdHJhaikKCnRpZHkobTgsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpCmBgYAoKIyMjIyBNb2RlbCA5OiBQaHlzaWNhbCBhbmQgZW1vdGlvbmFsIGFidXNlIGludGVyYWN0aW9uICArIGZ1bGwgbTIgbW9kZWwKYGBge3J9Cm05IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX0Vtb0FidV9SUypXSzJfQ1RRU0ZfUGh5QWJ1X1JTICsgQk1JICsgUFJFX1BhaW5fTWRTdiArIEVEX01hcml0YWwgKyBBRElfTmF0UmFuayArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMsIGRhdGEgPSBkZikKYGBgCgoKIyMjIyBNb2RlbCAxMDogQmFzZSBtb2RlbCArIEJ1bGx5aW5nCgpgYGB7cn0KIzEwdGggbW9kZWwgaXMgYnVsbHlpbmcKbTEwIDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0J1bGx5aW5nX1RvdGFsLCBkYXRhID0gZGZfdHJhaikKCnRpZHkobTEwLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCiMjIyMgTW9kZWwgMTE6IEJhc2UgTW9kZWwgKyBCdWxseWluZyArIFBoeXNpY2FsIEFidXNlICsgRW1vdGlvbmFsIEFidXNlCgpgYGB7cn0KbTExIDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX0Vtb0FidV9SUyArIFdLMl9CdWxseWluZ19Ub3RhbCArIFdLMl9DVFFTRl9QaHlBYnVfUlMgLCBkYXRhID0gZGYpCgp0aWR5KG0xMSwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSkKYGBgCgojIyMjIE1vZGVsIDEyOiBCYXNlIE1vZGVsICsgQ1RRX1RyaWFkCgpgYGB7cn0KbTEyIDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgQ1RRX1RyaWFkLCBkYXRhID0gZGYpCgp0aWR5KG0xMiwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSkKCnZpZihtMTIpCmBgYAoKIyMjIyBNb2RlbCAxMzogTTIgKyBDVFFfVHJpYWQKCmBgYHtyfQptMTMgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBDVFFfVHJpYWQgKyBCTUkgKyBQUkVfUGFpbl9NZFN2ICsgRURfQ29uY3Vzc2lvbiArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMgKyBBRElfTmF0UmFuaywgZGF0YSA9IGRmKQoKdGlkeShtMTMsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpCmBgYAoKIyMjIyBNb2RlbCAxNDogTTIgKyBDVFEqcmFjZSBpbnRlcmFjdGlvbgoKYGBge3J9Cm0xNCA8LSBtdWx0aW5vbShQYWluX0NsYXNzIH4gRURfQWdlICsgU2l0ZV9OZXcgKyBFRF9SYWNlRXRoQ29kZSArIEVEX0dlbmRlckJpcnRoQ2VydCArIENUUV9Ub3RhbCArIEJNSSArIFBSRV9QYWluX01kU3YgKyBFRF9NYXJpdGFsICsgQURJX05hdFJhbmsgKyBFRF9FdmVudF9Ccm9hZENsYXNzICsgRURfUERJX1JTICsgQ1RRX1RvdGFsKkVEX1JhY2VFdGhDb2RlLCBkYXRhID0gZGYpCgp0aWR5KG0xNCwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSkKYGBgCgojIyMjIE1vZGVsIDE1OiBNMiArIENUUSpTZXggaW50ZXJhY3Rpb24KCmBgYHtyfQptMTUgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBDVFFfVG90YWwgKyBCTUkgKyBQUkVfUGFpbl9NZFN2ICsgRURfTWFyaXRhbCArIEFESV9OYXRSYW5rICsgRURfRXZlbnRfQnJvYWRDbGFzcyArIEVEX1BESV9SUyArIENUUV9Ub3RhbCpFRF9HZW5kZXJCaXJ0aENlcnQsIGRhdGEgPSBkZikKCnRpZHkobTE1LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCiMjIyMgTW9kZWxzIDE2LTIxOiBNMiArIGVhY2ggQ1RRIHN1YnR5cGUgKyBidWxseWluZwoKYGBge3J9CiNwaHlzaWNhbCBhYnVzZSBtMTYKbTE2IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX1BoeUFidV9SUyArIEJNSSArIFBSRV9QYWluX01kU3YgKyBFRF9NYXJpdGFsICsgQURJX05hdFJhbmsgKyBFRF9FdmVudF9Ccm9hZENsYXNzICsgRURfUERJX1JTLCBkYXRhID0gZGYpCgojcGh5c2ljYWwgbmVnbGVjdCBtMTcKbTE3IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX1BoeU5lZ19SUyArIEJNSSArIFBSRV9QYWluX01kU3YgKyBFRF9NYXJpdGFsICsgQURJX05hdFJhbmsgKyBFRF9FdmVudF9Ccm9hZENsYXNzICsgRURfUERJX1JTLCBkYXRhID0gZGYpCgojZW1vdGlvbmFsIGFidXNlIG0xOAptMTggPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBXSzJfQ1RRU0ZfRW1vQWJ1X1JTICsgQk1JICsgUFJFX1BhaW5fTWRTdiArIEVEX01hcml0YWwgKyBBRElfTmF0UmFuayArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMsIGRhdGEgPSBkZikKCiNlbW90aW9uYWwgbmVnbGVjdCBtMTkKbTE5IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0NUUVNGX0Vtb05lZ19SUyArIEJNSSArIFBSRV9QYWluX01kU3YgKyBFRF9NYXJpdGFsICsgQURJX05hdFJhbmsgKyBFRF9FdmVudF9Ccm9hZENsYXNzICsgRURfUERJX1JTLCBkYXRhID0gZGYpCgojc2V4dWFsIGFidXNlIG0yMAptMjAgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBXSzJfQ1RRU0ZfU2V4QWJ1X1JTICsgQk1JICsgUFJFX1BhaW5fTWRTdiArIEVEX01hcml0YWwgKyBBRElfTmF0UmFuayArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMsIGRhdGEgPSBkZikKCiNidWxseWluZyBtMjEKbTIxIDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgV0syX0J1bGx5aW5nX1RvdGFsICsgQk1JICsgUFJFX1BhaW5fTWRTdiArIEVEX01hcml0YWwgKyBBRElfTmF0UmFuayArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMsIGRhdGEgPSBkZikKCnRpZHkobTE2LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAKCnRpZHkobTE3LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAKCnRpZHkobTE4LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAKCnRpZHkobTE5LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAKCnRpZHkobTIwLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAKCnRpZHkobTIxLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAKYGBgCgojIyMjIE1vZGVsIDIyOiBtMSArIFNleCpDVFEKYGBge3J9Cm0yMiA8LSBtdWx0aW5vbShQYWluX0NsYXNzIH4gRURfQWdlICsgU2l0ZV9OZXcgKyBFRF9SYWNlRXRoQ29kZSArIEVEX0dlbmRlckJpcnRoQ2VydCArIENUUV9Ub3RhbCArIEVEX0dlbmRlckJpcnRoQ2VydCpDVFFfVG90YWwsIGRhdGEgPSBkZikKCnRpZHkobTIyLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCiMjIyMgTW9kZWwgMjM6IG0xICsgUmFjZSpDVFEKYGBge3J9Cm0yMyA8LSBtdWx0aW5vbShQYWluX0NsYXNzIH4gRURfQWdlICsgU2l0ZV9OZXcgKyBFRF9SYWNlRXRoQ29kZSArIEVEX0dlbmRlckJpcnRoQ2VydCArIENUUV9Ub3RhbCArIEVEX1JhY2VFdGhDb2RlKkNUUV9Ub3RhbCwgZGF0YSA9IGRmKQoKdGlkeShtMjMsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpCmBgYAoKIyMjIyBNb2RlbCAyNDogbTIgZmVtYWxlIG9ubHkKYGBge3J9CgpkZl9mZW0gPC0gZGYgJT4lIGZpbHRlcihFRF9HZW5kZXJCaXJ0aENlcnQgPT0gIkZlbWFsZSIpCgptMjQgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBDVFFfVG90YWwgKyBCTUkgKyBQUkVfUGFpbl9NZFN2ICsgRURfTWFyaXRhbCArIEFESV9OYXRSYW5rICsgRURfRXZlbnRfQnJvYWRDbGFzcyArIEVEX1BESV9SUywgZGF0YT1kZl9mZW0pCgp0aWR5KG0yNCwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSkKYGBgCgojIyMjIE1vZGVsIDI1OiBtMiBtYWxlIG9ubHkKYGBge3J9CmRmX21hbGUgPC0gZGYgJT4lIGZpbHRlcihFRF9HZW5kZXJCaXJ0aENlcnQgPT0gIk1hbGUiKQoKbTI1IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgQ1RRX1RvdGFsICsgQk1JICsgUFJFX1BhaW5fTWRTdiArIEVEX01hcml0YWwgKyBBRElfTmF0UmFuayArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMsIGRhdGE9ZGZfbWFsZSkKCnRpZHkobTI1LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCiMjIyMgTW9kZWxzIDI2LTMxOiBNMiArIEJJTkFSWSBJTkRJQ0FUT1JTCgoKCgojIyMjIE0yNjogTTIgKyBQaHlBYnUgQU5ZCgpgYGB7cn0KI01vZGVsIDIgYnV0IGluc3RlYWQgb2YgcGh5c2ljYWwgYWJ1c2Ugc2NvcmUsIGl0cyBhIGJpbmFyeSBzY29yZSBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgcHQgaGFkIGFueSBwaHlzaWNhbCBhYnVzZQoKbTI2IDwtIG11bHRpbm9tKFBhaW5fQ2xhc3MgfiBFRF9BZ2UgKyBTaXRlX05ldyArIEVEX1JhY2VFdGhDb2RlICsgRURfR2VuZGVyQmlydGhDZXJ0ICsgUGh5QWJ1X0FueSArIEJNSSArIFBSRV9QYWluX01kU3YgKyBFRF9NYXJpdGFsICsgQURJX05hdFJhbmsgKyBFRF9FdmVudF9Ccm9hZENsYXNzICsgRURfUERJX1JTLCBkYXRhID0gZGYpCgp0aWR5KG0yNiwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKSAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIDUpKSklPiUKICBtdXRhdGUocF9hZGpfYmggPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSkKYGBgCgpNb2RlbCAyNzogTTIgKyBFbW9fQWJ1c2UgQU5ZCmBgYHtyfQojTW9kZWwgMiBidXQgaW5zdGVhZCBvZiBlbW90aW9uYWwgYWJ1c2Ugc2NvcmUsIGl0cyBhIGJpbmFyeSBzY29yZSBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgcHQgaGFkIGFueSBlbW90aW9uYWwgYWJ1c2UKCm0yNyA8LSBtdWx0aW5vbShQYWluX0NsYXNzIH4gRURfQWdlICsgU2l0ZV9OZXcgKyBFRF9SYWNlRXRoQ29kZSArIEVEX0dlbmRlckJpcnRoQ2VydCArIEVtb0FidV9BbnkgKyBCTUkgKyBQUkVfUGFpbl9NZFN2ICsgRURfTWFyaXRhbCArIEFESV9OYXRSYW5rICsgRURfRXZlbnRfQnJvYWRDbGFzcyArIEVEX1BESV9SUywgZGF0YSA9IGRmKQoKdGlkeShtMjcsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpCmBgYAoKTW9kZWwgMjg6IE0yICsgRW1vX05lZ2xlY3QgQU5ZCmBgYHtyfQojTW9kZWwgMiBidXQgaW5zdGVhZCBvZiBlbW90aW9uYWwgbmVnbGVjdCBzY29yZSwgaXRzIGEgYmluYXJ5IHNjb3JlIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBwdCBoYWQgYW55IGVtb3Rpb25hbCBuZWdsZWN0CgptMjggPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBFbW9OZWdfQW55ICsgQk1JICsgUFJFX1BhaW5fTWRTdiArIEVEX01hcml0YWwgKyBBRElfTmF0UmFuayArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMsIGRhdGEgPSBkZikKCnRpZHkobTI4LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCk1vZGVsIDI5OiBNMiArIFBoeV9OZWdsZWN0IEFOWQpgYGB7cn0KI01vZGVsIDIgYnV0IGluc3RlYWQgb2YgcGh5c2ljYWwgbmVnbGVjdCBzY29yZSwgaXRzIGEgYmluYXJ5IHNjb3JlIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBwdCBoYWQgYW55IHBoeXNpY2FsIG5lZ2xlY3QKCm0yOSA8LSBtdWx0aW5vbShQYWluX0NsYXNzIH4gRURfQWdlICsgU2l0ZV9OZXcgKyBFRF9SYWNlRXRoQ29kZSArIEVEX0dlbmRlckJpcnRoQ2VydCArIFBoeU5lZ19BbnkgKyBCTUkgKyBQUkVfUGFpbl9NZFN2ICsgRURfTWFyaXRhbCArIEFESV9OYXRSYW5rICsgRURfRXZlbnRfQnJvYWRDbGFzcyArIEVEX1BESV9SUywgZGF0YSA9IGRmKQoKdGlkeShtMjksIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpCmBgYAoKTW9kZWwgMzA6IE0yICsgU2V4dWFsIEFidXNlIEFOWQpgYGB7cn0KI01vZGVsIDIgYnV0IGluc3RlYWQgb2Ygc2V4dWFsIGFidXNlIHNjb3JlLCBpdHMgYSBiaW5hcnkgc2NvcmUgb2Ygd2hldGhlciBvciBub3QgdGhlIHB0IGhhZCBhbnkgc2V4dWFsIGFidXNlCgptMzAgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBTZXhBYnVfQW55ICsgQk1JICsgUFJFX1BhaW5fTWRTdiArIEVEX01hcml0YWwgKyBBRElfTmF0UmFuayArIEVEX0V2ZW50X0Jyb2FkQ2xhc3MgKyBFRF9QRElfUlMsIGRhdGEgPSBkZikKCnRpZHkobTMwLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKQpgYGAKCiMjIyMgTW9kZWwgMzE6IE0yICsgQnVsbHlpbmcgQU5ZCmBgYHtyfQojTW9kZWwgMiBidXQgaW5zdGVhZCBvZiBidWxseWluZyBzY29yZSwgaXRzIGEgYmluYXJ5IHNjb3JlIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBwdCBoYWQgYW55IGJ1bGx5aW5nCgptMzEgPC0gbXVsdGlub20oUGFpbl9DbGFzcyB+IEVEX0FnZSArIFNpdGVfTmV3ICsgRURfUmFjZUV0aENvZGUgKyBFRF9HZW5kZXJCaXJ0aENlcnQgKyBCdWxseWluZ19BbnkgKyBCTUkgKyBQUkVfUGFpbl9NZFN2ICsgRURfTWFyaXRhbCArIEFESV9OYXRSYW5rICsgRURfRXZlbnRfQnJvYWRDbGFzcyArIEVEX1BESV9SUywgZGF0YSA9IGRmKQoKdGlkeShtMzEsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpCmBgYAoKIyMjIyBNb2RlbCAzMjogU3RlcHdpc2UgU2VsZWN0aW9uCmBgYHtyfQojd3JpdGUgYSBtb2RlbCB0aGF0IGRvZXMgbXVsdGlub21pYWwgc3RlcHdpc2Ugc2VsZWN0aW9uIHRvIHByZWRpY3QgcGFpbl9jbGFzcyBmcm9tICB0aGUgYmVzdCBmZWF0dXJlcyBmcm9tIGRmCgojcmV3cml0ZSBzdGVwd2lzZSBjb2RlIHRvIHJlbW92ZSBtaXNzaW5nIHZhbHVlcwoKaW52aXNpYmxlKGNhcHR1cmUub3V0cHV0KApzdGVwd2lzZV9zZWxlY3Rpb24gPC0gc3RlcEFJQygKICBtdWx0aW5vbShQYWluX0NsYXNzIH4gLiwgZGF0YSA9IGRyb3BfbmEoZGYpKSwKICBkaXJlY3Rpb24gPSAiYm90aCIsCiAgdHJhY2UgPSAwKQopKQoKCiMgSW5pdGlhbCBmZWF0dXJlcyAoZXhjbHVkaW5nIHRoZSByZXNwb25zZSB2YXJpYWJsZSAnUGFpbl9DbGFzcycpCmluaXRpYWxfZmVhdHVyZXMgPC0gbmFtZXMoZGYpW25hbWVzKGRmKSAhPSAiUGFpbl9DbGFzcyJdCmluY2x1ZGVkX2ZlYXR1cmVzIDwtIG5hbWVzKGNvZWYoc3RlcHdpc2Vfc2VsZWN0aW9uKSkKZXhjbHVkZWRfZmVhdHVyZXMgPC0gc2V0ZGlmZihpbml0aWFsX2ZlYXR1cmVzLCBpbmNsdWRlZF9mZWF0dXJlcykKCiMgUHJpbnQgaW5jbHVkZWQgYW5kIGV4Y2x1ZGVkIGZlYXR1cmVzCmNhdCgiSW5jbHVkZWQgZmVhdHVyZXM6XG4iKQpwcmludChpbmNsdWRlZF9mZWF0dXJlcykKCmNhdCgiXG5FeGNsdWRlZCBmZWF0dXJlczpcbiIpCnByaW50KGV4Y2x1ZGVkX2ZlYXR1cmVzKQpgYGAKCiMjIyMgTW9kZWwgMzMtMzQgUHJlLXBhaW4gbG9naXN0aWMgcmVncmVzc2lvbgojIyMjIEVtYWlsIGZyb20gTGF1cmVuIDMtQXVnLTI0CldlIHdhbnRlZCB0byBtYWtlIHN1cmUgdG8gaW5jbHVkZSBhbiBhbmFseXNpcyB0aGF0IGNsb3NlbHkgbWlycm9ycyBvdXIgZmlyc3QgYW5pbWFsIGZpZ3VyZSAocHJpb3IgdG8gU1BTL1RTRSBleHBvc3VyZSwgYW5pbWFscyB3aXRoIEVMQSBoYXZlIGluY3JlYXNlIHBhaW4tbGlrZSBiZWhhdmlvcikuIEkgZG8gbm90IHRoaW5rIHdlIGhhdmUgZG9uZSBhbnl0aGluZyBsaWtlIHRoaXMgeWV0LiBDYW4geW91IHJ1biBhbiBhbmFseXNpcyB0byB0ZXN0IHdoZXRoZXIgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGluIFByZVBhaW4gcmF0ZXMvb2RkcyBiYXNlZCBvbiBFTEE/CiAKSSB0aGluayB0aGlzIHdvdWxkIGVpdGhlciBiZSBhIGxvZ2lzdGljIHJlZ3Jlc3Npb24gdXNpbmcgdGhlIENUUSBjb21wb3NpdGUgYW5kIChzZXBhcmF0ZWx5KSB0aGUgQnVsbHlpbmcgY29tcG9zaXRlLCBvciBhIGNoaS1zcXVhcmUvei1wcm9wb3J0aW9uIHRlc3QgYW5kIHdlIGNvdWxkIGdyb3VwIENUUSBhbmQgQnVsbHlpbmcgaW50byBoaWdoIGFuZCBsb3cgYmFzZWQgb24gdGhlaXIgbWVkaWFuIHNjb3JlIChDVFE+NiBhbmQgQnVsbHlpbmc+Mykgb3IganVzdCB1c2UgdGhlIOKAnGFueSBDVFHigJ0gYW5kIOKAnGFueSBCdWxseWluZyB2YXJpYWJsZXPigJ0uIApgYGB7cn0KIyBDcmVhdGUgYmluYXJ5IHZhcmlhYmxlcyBmb3IgaGlnaC9sb3cgQ1RRIGFuZCBCdWxseWluZwpkZiA8LSBkZiAlPiUKICBtdXRhdGUoCiAgICBDVFFfSGlnaExvdyA9IGlmZWxzZShDVFFfVG90YWwgPiA2LCAiSGlnaCIsICJMb3ciKSwKICAgIEJ1bGx5aW5nX0hpZ2hMb3cgPSBpZmVsc2UoV0syX0J1bGx5aW5nX1RvdGFsID4gMywgIkhpZ2giLCAiTG93IikpCgojIENyZWF0ZSBiaW5hcnkgdmFyaWFibGUgZm9yIFBSRV9QYWluX01kU3YKZGYkUFJFX1BhaW5fTWRTdjIgPC0gaWZlbHNlKGRmJFBSRV9QYWluX01kU3YgPT0gIlllcyIsIDEsIDApCgojIE0zMyBMb2dpc3RpYyByZWdyZXNzaW9uIHVzaW5nIENUUSBjb21wb3NpdGUKbTMzIDwtIGdsbShQUkVfUGFpbl9NZFN2MiB+IENUUV9Ub3RhbCwgZGF0YSA9IGRmLCBmYW1pbHkgPSAiYmlub21pYWwiKQoKdGlkeShtMzMsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSkpCgojIE0zNCBMb2dpc3RpYyByZWdyZXNzaW9uIHVzaW5nIEJ1bGx5aW5nIGNvbXBvc2l0ZQptMzQgPC0gZ2xtKFBSRV9QYWluX01kU3YyIH4gV0syX0J1bGx5aW5nX1RvdGFsLCBkYXRhID0gZGYsIGZhbWlseSA9ICJiaW5vbWlhbCIpCnRpZHkobTM0LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYykpKQoKIyBDaGktc3F1YXJlIHRlc3QgZm9yIENUUV9IaWdoTG93CmNoaXNxLnRlc3QodGFibGUoZGYkQ1RRX0hpZ2hMb3csIGRmJFBSRV9QYWluX01kU3YpKQoKIyBDaGktc3F1YXJlIHRlc3QgZm9yIEJ1bGx5aW5nX0hpZ2hMb3cKY2hpc3EudGVzdCh0YWJsZShkZiRCdWxseWluZ19IaWdoTG93LCBkZiRQUkVfUGFpbl9NZFN2KSkKCiMgY2hpLXNxdWFyZSB0ZXN0IGZvciBhbnkgQ1RRCmNoaXNxLnRlc3QodGFibGUoZGYkQ1RRX0FueSwgZGYkUFJFX1BhaW5fTWRTdikpCgojIGNoaS1zcXVhcmUgdGVzdCBmb3IgYW55IGJ1bGx5aW5nCmNoaXNxLnRlc3QodGFibGUoZGYkQnVsbHlpbmdfQW55LCBkZiRQUkVfUGFpbl9NZFN2KSkKYGBgCgoKIyMjIEFOT1ZBIGZvciByYWNlIHggQ1RRCgpgYGB7cn0KI0FOT1ZBIG9uIHJhY2UgdnMgQ1RRCiNBTk9WQSBvbiBFRF9SYWNlRXRoQ29kZSB2ZXJzdXMgQ1RRCgphbm92YV9yZXN1bHQgPC0gYW92KENUUV9Ub3RhbCB+IEVEX1JhY2VFdGhDb2RlLCBkYXRhID0gZGYpCnN1bW1hcnkoYW5vdmFfcmVzdWx0KQpUdWtleUhTRChhbm92YV9yZXN1bHQpCmBgYAoKYGBge3J9CiNBTk9WQSBvbiBwYWluIHRyYWplY3RvcnkgYnkgQ1RRCnJlc3VsdCA8LSBhb3YoQ1RRX1RvdGFsIH4gUGFpbl9DbGFzcywgZGF0YSA9IGRmKQpzdW1tYXJ5KHJlc3VsdCkKVHVrZXlIU0QocmVzdWx0KQpgYGAKCjxicj4KCiMjIyBNb2RlbCBDb21wYXJpc29uCgptMSAjYmFzZSBtb2RlbCBtMiAjYmFzZSBtb2RlbCArIGFkZGl0aW9uYWwgZmVhdHVyZXMgbTEyICNiYXNlIG1vZGVsICsgQ1RRX1RyaWFkIG0xMyAjbTIgKyBDVFFfVAoKbTE2ICNtMiArIHBoeXNpY2FsIGFidXNlIG0xNyAjbTIgKyBwaHlzaWNhbCBuZWdsZWN0IG0xOCAjbTIgKyBlbW90aW9uYWwgYWJ1c2UgbTE5ICNtMiArIGVtb3Rpb25hbCBuZWdsZWN0IG0yMCAjbTIgKyBzZXh1YWwgYWJ1c2UgbTIxICNtMiArIGJ1bGx5aW5nCgpgYGB7cn0KIyBMaXN0IG9mIGFsbCBtb2RlbHMKbW9kZWxfbmFtZXMgPC0gcGFzdGUwKCJtIiwgMTozMSkKbW9kZWxzIDwtIGxhcHBseShtb2RlbF9uYW1lcywgZ2V0KQoKI3JlbW92ZSBtMjUgZnJvbSBsaXN0IG9mIG1vZGVscwptb2RlbF9uYW1lczIgPC0gbW9kZWxfbmFtZXNbLTI1XQptb2RlbHMyIDwtIGxhcHBseShtb2RlbF9uYW1lczIsIGdldCkKYGBgCgo8YnI+CgojIyMjIFN0ZXB3aXNlIHNlbGVjdGlvbiBvZiBiZXN0IG1vZGVsCmBgYHtyfQpgYGAKCgoKPGJyPgoKIyMjIyBDb21wYXJlIEFJQy9CSUMKCmBgYHtyfQojIEZ1bmN0aW9uIHRvIGdldCBBSUMgYW5kIEJJQwpnZXRfYWljX2JpYyA8LSBmdW5jdGlvbihtb2RlbCkgYyhBSUMgPSBBSUMobW9kZWwpLCBCSUMgPSBCSUMobW9kZWwpKQoKIyBBcHBseSB0aGUgZnVuY3Rpb24gdG8gYWxsIG1vZGVscywgc29ydCByZXN1bHRzCmNvbXBhcmVkX20gPC0gYXMuZGF0YS5mcmFtZSh0KHNhcHBseShtb2RlbHMsIGdldF9haWNfYmljKSkpCmNvbXBhcmVkX20gPC0gY2JpbmQobW9kZWwgPSBtb2RlbF9uYW1lcywgY29tcGFyZWRfbSkKY29tcGFyZWRfbSA8LSBjb21wYXJlZF9tW29yZGVyKGNvbXBhcmVkX20kQklDKSwgXQoKIyBQcmludCB0aGUgcmVzdWx0cwpwcmludChjb21wYXJlZF9tKQoKI20xOCBpcyBtMiArIGVtb3Rpb25hbCBhYnVzZQojbTEzIGlzIG0yICsgdHJpYWQKI20xNiBpcyBtMiArIHBoeXNpY2FsIGFidXNlCiNtMjEgaXMgbTIgKyBidWxseWluZwojbTIgaXMgb3VyIG1haW4gbW9kZWwKI20yMCBpcyBtMiArIHNleHVhbCBhYnVzZQojbTE5IGlzIG0yICsgZW1vdGlvbmFsIG5lZ2xlY3QKYGBgCgojIyMjIFVzZSBtdWx0aS1jbGFzcyBST0MgY3VydmVzCgpUcnlpbmcgdGhpcyB3aXRoIG0xLCBiYXNlIG1vZGVsCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBMb2FkIHJlcXVpcmVkIGxpYnJhcnkKbGlicmFyeShwUk9DKQoKIyBQcmVkaWN0IHByb2JhYmlsaXRpZXMgZm9yIG0yNQpwcm9iczEgPC0gcHJlZGljdChtMjUsIGRmLCB0eXBlID0gInByb2JzIikKCiMgQ3JlYXRlIG9uZS12cy1yZXN0IFJPQyBjdXJ2ZXMKcm9jX2xpc3QgPC0gbGlzdCgpCmF1cm9jX3ZhbHVlcyA8LSBudW1lcmljKGxlbmd0aChjb2xuYW1lcyhwcm9iczEpKSkgICMgSW5pdGlhbGl6ZSB2ZWN0b3IgZm9yIEFVUk9DIHZhbHVlcwoKZm9yIChjbGFzcyBpbiBjb2xuYW1lcyhwcm9iczEpKSB7CiAgcm9jX2xpc3RbW2NsYXNzXV0gPC0gcm9jKGFzLm51bWVyaWMoZGYkUGFpbl9DbGFzcyA9PSBjbGFzcyksIHByb2JzMVssY2xhc3NdKQogIGF1cm9jX3ZhbHVlc1tjbGFzc10gPC0gYXVjKHJvY19saXN0W1tjbGFzc11dKSAgIyBDYWxjdWxhdGUgQVVST0MKfQoKIyBQbG90IFJPQyBjdXJ2ZXMKcGxvdChyb2NfbGlzdFtbMV1dLCBtYWluID0gIlJPQyBDdXJ2ZXMgZm9yIEVhY2ggQ2xhc3MiLCBjb2wgPSAxLCBsd2QgPSAyKQpmb3IgKGkgaW4gMjpsZW5ndGgocm9jX2xpc3QpKSB7CiAgcGxvdChyb2NfbGlzdFtbaV1dLCBhZGQgPSBUUlVFLCBjb2wgPSBpLCBsd2QgPSAyKQp9CgojIEFkZCBBVVJPQyB2YWx1ZXMgYXMgdGV4dCBkaXJlY3RseSBvbiB0aGUgcGxvdAojIFVzZSBhIGZpeGVkIHBvc2l0aW9uIG9yIGFkanVzdCBhcyBuZWVkZWQKdGV4dF9wb3NpdGlvbnMgPC0gYygwLjgsIDAuNywgMC42LCAwLjUsIDAuNCwgMC4zKSAgIyBBZGp1c3QgYXMgbmVjZXNzYXJ5IGZvciB5b3VyIHBsb3QKCmZvciAoaSBpbiAxOmxlbmd0aChyb2NfbGlzdCkpIHsKICB0ZXh0KHggPSAwLjYsIHkgPSB0ZXh0X3Bvc2l0aW9uc1tpXSwgCiAgICAgICBsYWJlbHMgPSBwYXN0ZTAobmFtZXMocm9jX2xpc3QpW2ldLCAiOiBBVVJPQyA9ICIsIHJvdW5kKGF1cm9jX3ZhbHVlc1tpXSwgMykpLAogICAgICAgcG9zID0gNCwgY2V4ID0gMC44LCBjb2wgPSBpKQp9CgojIEFkZCBsZWdlbmQgdG8gdGhlIHBsb3QKbGVnZW5kKCJib3R0b21yaWdodCIsIGxlZ2VuZCA9IG5hbWVzKHJvY19saXN0KSwgY29sID0gMTpsZW5ndGgocm9jX2xpc3QpLCBsd2QgPSAyLCBidHkgPSAibiIpCmBgYAoKCiMjIyMgRXhhbWluZSBjb25mdXNpb24gbWF0cml4CgpgYGB7cn0KbGlicmFyeShjYXJldCkKCiMgRnVuY3Rpb24gdG8gY29tcHV0ZSBjb25mdXNpb24gbWF0cml4IHdpdGggbW9kZWwgbmFtZXMKZ2V0X2NvbmZ1c2lvbl9tYXRyaXggPC0gZnVuY3Rpb24obW9kZWwsIGRhdGEsIG1vZGVsX25hbWUpIHsKICBwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KG1vZGVsLCBuZXdkYXRhID0gZGF0YSwgdHlwZSA9ICJjbGFzcyIpCiAgY20gPC0gY29uZnVzaW9uTWF0cml4KHByZWRpY3Rpb25zLCBkYXRhJFBhaW5fQ2xhc3MpCiAgcmV0dXJuKGxpc3QobW9kZWwgPSBtb2RlbF9uYW1lLCBjb25mdXNpb25fbWF0cml4ID0gY20pKX0KCiMgQ29tcHV0ZSBjb25mdXNpb24gbWF0cmljZXMgd2l0aCBtb2RlbCBuYW1lcwptb2RlbF9uYW1lcyA8LSBjKCJtMiIsICJtMjUiKQptb2RlbHMgPC0gbGFwcGx5KG1vZGVsX25hbWVzLCBnZXQpCgpjb25mX21hdHJpY2VzIDwtIG1hcHBseShnZXRfY29uZnVzaW9uX21hdHJpeCwgbW9kZWxzLCBNb3JlQXJncyA9IGxpc3QoZGF0YSA9IGRmKSwgbW9kZWxfbmFtZSA9IG1vZGVsX25hbWVzLCBTSU1QTElGWSA9IEZBTFNFKQoKIyBQcmludCB0aGUgY29uZnVzaW9uIG1hdHJpY2VzIHdpdGggbW9kZWwgbmFtZXMKZm9yIChjbSBpbiBjb25mX21hdHJpY2VzKSB7CiAgY2F0KCJNb2RlbDoiLCBjbSRtb2RlbCwgIlxuIikKICBwcmludChjbSRjb25mdXNpb25fbWF0cml4KQogIGNhdCgiXG4iKX0KYGBgCjxicj4KCiMjIyBDb3JyZWN0aW9ucyB0ZXN0aW5nCiBmb3IgbTEsIG0yLCBtMiArIGVhY2ggc3VidHlwZSwgbTIgKyBlYWNoIHN1YnR5cGUgQU5ZIApsaWtlbGlob29kIHJhdGlvIHRlc3QgbTEgdnMgbTIKCiMjIyMgQkggRnVuY3Rpb24KYGBge3J9CmFwcGx5X2JoX2NvcnJlY3Rpb24gPC0gZnVuY3Rpb24obW9kZWxzLCBtb2RlbF9uYW1lcykgewogIGNvcnJlY3RfbW9kZWwgPC0gZnVuY3Rpb24obW9kZWwpIHsKICAgIG1vZGVsX3Jlc3VsdHMgPC0gdGlkeShtb2RlbCwgZXhwb25lbnRpYXRlID0gVFJVRSkgJT4lCiAgICAgIGZpbHRlcih0ZXJtICE9ICIoSW50ZXJjZXB0KSIpICU+JQogICAgICBzZWxlY3QoeS5sZXZlbCx0ZXJtLCBlc3RpbWF0ZSwgcC52YWx1ZSkKICAgIAogICAgbW9kZWxfcmVzdWx0cyA8LSBtb2RlbF9yZXN1bHRzICU+JQogICAgICBtdXRhdGUocF9hZGpfYmggPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSkgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBwLnZhbHVlID0gcm91bmQocC52YWx1ZSwgZGlnaXRzID0gNiksCiAgICAgICAgcF9hZGpfYmggPSByb3VuZChwX2Fkal9iaCwgZGlnaXRzID0gNikKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIHAudmFsdWUgPSBmb3JtYXQocC52YWx1ZSwgc2NpZW50aWZpYyA9IEZBTFNFKSwKICAgICAgICBwX2Fkal9iaCA9IGZvcm1hdChwX2Fkal9iaCwgc2NpZW50aWZpYyA9IEZBTFNFKQogICAgICApCiAgICByZXR1cm4obW9kZWxfcmVzdWx0cykKICB9CiAgCiAgY29ycmVjdGVkX21vZGVscyA8LSBsYXBwbHkobW9kZWxzLCBjb3JyZWN0X21vZGVsKQogIG5hbWVzKGNvcnJlY3RlZF9tb2RlbHMpIDwtIG1vZGVsX25hbWVzCiAgCiAgcmV0dXJuKGNvcnJlY3RlZF9tb2RlbHMpCn0KYGBgCgojIyMjIEJIIENvcnJlY3RlZCBNMS1NMgoKYGBge3J9Cm1vZGVsc19saXN0X2Jhc2VzIDwtIGxpc3QobTEsbTIpCm1vZGVsX25hbWVzIDwtIGMoIm0xIiwgIm0yIikKYWRqdXN0ZWRfbW9kZWxzIDwtIGFwcGx5X2JoX2NvcnJlY3Rpb24obW9kZWxzX2xpc3RfYmFzZXMsIG1vZGVsX25hbWVzKQoKY2F0KCJNT0RFTCAxIEJIIENPUlJFQ1RFRCIpCnRpZHkobTEsIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguLCA1KSkpICAlPiUKICAgICAgICBmaWx0ZXIodGVybSAhPSAiKEludGVyY2VwdCkiKSAlPiUKICAgICAgc2VsZWN0KHkubGV2ZWwsdGVybSwgZXN0aW1hdGUsIHAudmFsdWUpJT4lCiAgICAgIG11dGF0ZShwX2Fkal9iaCA9IHAuYWRqdXN0KHAudmFsdWUsIG1ldGhvZCA9ICJCSCIpKQoKY2F0KCJcbiBcbiBNT0RFTCAyIEJIIENPUlJFQ1RFRCIpCgp0aWR5KG0yLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAgJT4lCiAgICAgICAgZmlsdGVyKHRlcm0gIT0gIihJbnRlcmNlcHQpIikgJT4lCiAgICAgIHNlbGVjdCh5LmxldmVsLHRlcm0sIGVzdGltYXRlLCBwLnZhbHVlKSU+JQogICAgICBtdXRhdGUocF9hZGpfYmggPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSkKYGBgCgojIyMjIEJIIENvcnJlY3RlZCBNMTMgVHJpYWQKV2l0aGluCmBgYHtyfQpjYXQoIk1PREVMIDEzIEJIIENPUlJFQ1RFRCIpCnRpZHkobTEzLCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgNSkpKSAgJT4lCiAgICAgICAgZmlsdGVyKHRlcm0gIT0gIihJbnRlcmNlcHQpIikgJT4lCiAgICAgIHNlbGVjdCh5LmxldmVsLHRlcm0sIGVzdGltYXRlLCBwLnZhbHVlKSU+JQogICAgICBtdXRhdGUocF9hZGpfYmggPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSkKYGBgCgoKIyMjIyBFeHRyYWN0IEFkaiBwLXZhbApgYGB7cn0KI2Z1bmN0aW9uIHRvIGdldCBhZGp1c3RlZCBwIHZhbHVlcyBmcm9tIGxpc3Qgb2YgbW9kZWxzCmV4dHJhY3RfcF92YWx1ZXMgPC0gZnVuY3Rpb24obW9kZWxfZGYsIG1vZGVsX25hbWUpIHsKICBtb2RlbF9kZiAlPiUKICAgIG11dGF0ZShtb2RlbCA9IG1vZGVsX25hbWUpICU+JQogICAgc2VsZWN0KHkubGV2ZWwsIHRlcm0sIHAudmFsdWUscF9hZGpfYmgsIG1vZGVsKX0KYGBgCgoKIyMjIyBCSCBBY3Jvc3MgTTE2LU0yMQoKcGVyZm9ybSBCSCBjb3JyZWN0aW9ucyBvbiB0aGUgdmFsdWVzIGluIGNvbWJpbmVkX3BfdmFsdWVzX20xNl9tMjEKYGBge3J9CiNCSCBjb3JyZWN0aW9ucyBmb3IgbW9kZWxzIHdpdGggc3VidHlwZXMgbTE2LW0yMQoKI21ha2UgZmlyc3Qgc2V0IG9mIGFkanVzdGVkIHdpdGhpbiBwIHZhbHMKbW9kZWxzX2xpc3Rfc3VidHlwZXMgPC0gbGlzdChtMTYsIG0xNywgbTE4LCBtMTksIG0yMCwgbTIxKQptb2RlbF9uYW1lczIgPC0gYygibTE2IiwgIm0xNyIsICJtMTgiLCAibTE5IiwgIm0yMCIsICJtMjEiKQphZGp1c3RlZF9tb2RlbHMyIDwtIGFwcGx5X2JoX2NvcnJlY3Rpb24obW9kZWxzX2xpc3Rfc3VidHlwZXMsIG1vZGVsX25hbWVzMikKCmNvbWJpbmVkX3BfdmFsdWVzX20xNl9tMjEgPC0gbWFwMl9kZnIoYWRqdXN0ZWRfbW9kZWxzMiwgcGFzdGUwKCJtIiwgMTY6MjEpLCBleHRyYWN0X3BfdmFsdWVzKQoKZG91YmxlX2NvcnJlY3RlZF9wX3ZhbHVlc18xNl9tMjEgPC0gY29tYmluZWRfcF92YWx1ZXNfbTE2X20yMSAlPiUKICBtdXRhdGUocF9hZGpfYmhfMiA9IHAuYWRqdXN0KGFzLm51bWVyaWMocF9hZGpfYmgpLCBtZXRob2QgPSAiQkgiKSkgJT4lCiAgbXV0YXRlKAogICAgcF9hZGpfYmhfMiA9IHJvdW5kKHBfYWRqX2JoXzIsIGRpZ2l0cyA9IDYpLAogICAgcF9hZGpfYmhfMiA9IGZvcm1hdChwX2Fkal9iaF8yLCBzY2llbnRpZmljID0gRkFMU0UpICApCgpkb3VibGVfY29ycmVjdGVkX3BfdmFsdWVzXzE2X20yMQpgYGAKCiMjIyMgQkggQWNyb3NzIE0yNi1NMzEKCmBgYHtyfQojQkggQkVUV0VFTiBDb3JyZWN0aW9ucyBmb3IgbW9kZWxzIHdpdGggYmluYXJ5IGluZGljYXRvcnMgbTI2LW0zMQoKbW9kZWxzX2xpc3RfQU5ZIDwtIGxpc3QobTI2LCBtMjcsIG0yOCwgbTI5LCBtMzAsIG0zMSkKbW9kZWxfbmFtZXMzIDwtIGMoIm0yNiIsICJtMjciLCAibTI4IiwgIm0yOSIsICJtMzAiLCAibTMxIikKYWRqdXN0ZWRfbW9kZWxzMyA8LSBhcHBseV9iaF9jb3JyZWN0aW9uKG1vZGVsc19saXN0X0FOWSwgbW9kZWxfbmFtZXMzKQoKZG91YmxlX2NvcnJlY3RlZF9wX3ZhbHVlc19tMjZfbTMxIDwtIG1hcDJfZGZyKGFkanVzdGVkX21vZGVsczMsIHBhc3RlMCgibSIsIDI2OjMxKSwgZXh0cmFjdF9wX3ZhbHVlcykKCiNwZXJmb3JtIEJIIGNvcnJlY3Rpb25zIG9uIHRoZSB2YWx1ZXMgaW4gZG91YmxlX2NvcnJlY3RlZF9wX3ZhbHVlc19tMjZfbTMxCmRvdWJsZV9jb3JyZWN0ZWRfcF92YWx1ZXNfbTI2X20zMSA8LSBkb3VibGVfY29ycmVjdGVkX3BfdmFsdWVzX20yNl9tMzEgJT4lCiAgbXV0YXRlKHBfYWRqX2JoXzIgPSBwLmFkanVzdChhcy5udW1lcmljKHBfYWRqX2JoKSwgbWV0aG9kID0gIkJIIikpICU+JQogIG11dGF0ZSgKICAgIHBfYWRqX2JoXzIgPSByb3VuZChwX2Fkal9iaF8yLCBkaWdpdHMgPSA2KSwKICAgIHBfYWRqX2JoXzIgPSBmb3JtYXQocF9hZGpfYmhfMiwgc2NpZW50aWZpYyA9IEZBTFNFKSAgKQoKZG91YmxlX2NvcnJlY3RlZF9wX3ZhbHVlc19tMjZfbTMxCmBgYAoKCgoKIyMjIFRhYmxlcyBmb3IgTWFudXNjcmlwdAoKIyMjIyBUYWJsZSAxLiBHZW5lcmFsCgpUYWJsZSAxYTogU29jaW8tZGVtb2dyYXBoaWMgdmFyaWFibGVzCmBgYHtyfQp0YWJsZTFhX2ZlYXR1cmVzIDwtIGMoIkVEX0dlbmRlckJpcnRoQ2VydCIsICJFRF9BZ2UiLCAiRURfUmFjZUV0aENvZGUiLCJCTUkiLCAiQURJX05hdFJhbmsiKQoKc3VwcHJlc3NNZXNzYWdlcyhzdXBwcmVzc1dhcm5pbmdzKAogIGRmICU+JQogICAgc2VsZWN0KGFsbF9vZih0YWJsZTFhX2ZlYXR1cmVzKSkgJT4lCiAgICB0Ymxfc3VtbWFyeShzdGF0aXN0aWMgPSBhbGxfY29udGludW91cygpIH4gInttZWFufSAoe3NkfSkiLCAKICAgICAgZGlnaXRzID0gYWxsX2NvbnRpbnVvdXMoKSB+IDIpKSkKYGBgCgo8YnI+CgoKVGFibGUgMWI6IEVEL1RyYXVtYS1yZWxhdGVkIHZhcmlhYmxlLm5hbWVzCmBgYHtyfQp0YWJsZTFiX2ZlYXR1cmVzIDwtIGMoIlNpdGVfTmV3IiwgIkVEX0V2ZW50X0Jyb2FkQ2xhc3MiLCAiRURfUERJX1JTIikKCnN1cHByZXNzTWVzc2FnZXMoc3VwcHJlc3NXYXJuaW5ncygKZGYgJT4lCiAgICBzZWxlY3QoYWxsX29mKHRhYmxlMWJfZmVhdHVyZXMpKSAlPiUKICAgIHRibF9zdW1tYXJ5KHN0YXRpc3RpYyA9IGFsbF9jb250aW51b3VzKCkgfiAie21lYW59ICh7c2R9KSIsIAogICAgICBkaWdpdHMgPSBhbGxfY29udGludW91cygpIH4gMikpKQpgYGAKCjxicj4KClRhYmxlIDFjOiBQYXN0IHBhaW4vc3RyZXNzIHZhcmlhYmxlcwpgYGB7cn0KdGFibGUxY19mZWF0dXJlcyA8LSBjKCJQUkVfUGFpbl9NZFN2IiwgIkNUUV9BbnkiLCJDVFFfVG90YWwiLCJQaHlBYnVfQW55IiwgIldLMl9DVFFTRl9QaHlBYnVfUlMiLCAiRW1vQWJ1X0FueSIsIldLMl9DVFFTRl9FbW9BYnVfUlMiLCAiU2V4QWJ1X0FueSIsICJXSzJfQ1RRU0ZfU2V4QWJ1X1JTIiwgIlBoeU5lZ19BbnkiLCAiV0syX0NUUVNGX1BoeU5lZ19SUyIsICJFbW9OZWdfQW55IiwgIldLMl9DVFFTRl9FbW9OZWdfUlMiLCAiQnVsbHlpbmdfQW55IiwgIldLMl9CdWxseWluZ19Ub3RhbCIpCgojIENyZWF0ZSBhIG5hbWVkIGxpc3QgdG8gc3BlY2lmeSB0aGUgdHlwZSBvZiBlYWNoIHZhcmlhYmxlCnR5cGVfbGlzdCA8LSBsaXN0KAogIFdLMl9DVFFTRl9QaHlBYnVfUlMgPSAiY29udGludW91cyIsCiAgV0syX0NUUVNGX0Vtb0FidV9SUyA9ICJjb250aW51b3VzIiwKICBXSzJfQ1RRU0ZfU2V4QWJ1X1JTID0gImNvbnRpbnVvdXMiLAogIFdLMl9DVFFTRl9QaHlOZWdfUlMgPSAiY29udGludW91cyIsCiAgV0syX0NUUVNGX0Vtb05lZ19SUyA9ICJjb250aW51b3VzIiwKICBXSzJfQnVsbHlpbmdfVG90YWwgPSAiY29udGludW91cyIpCgojIEdlbmVyYXRlIHRoZSBzdW1tYXJ5IHRhYmxlCnN1cHByZXNzTWVzc2FnZXMoc3VwcHJlc3NXYXJuaW5ncygKICBkZiAlPiUKICAgIHNlbGVjdChhbGxfb2YodGFibGUxY19mZWF0dXJlcykpICU+JQogICAgdGJsX3N1bW1hcnkoCiAgICAgIHN0YXRpc3RpYyA9IGFsbF9jb250aW51b3VzKCkgfiAie21lYW59ICh7c2R9KSIsCiAgICAgIGRpZ2l0cyA9IGFsbF9jb250aW51b3VzKCkgfiAyLAogICAgICB0eXBlID0gdHlwZV9saXN0KSkpCmBgYAoKPGJyPgoKIyMjIyBUYWJsZSAxLiBDb21wYXJlZCBQYWluIENsYXNzZXMKCmBgYHtyfQp0YWJsZTFfY2xhc3NfZmVhdHVyZXMgPC0gYygiUGFpbl9DbGFzcyIsIkVEX0dlbmRlckJpcnRoQ2VydCIsICJFRF9BZ2UiLCAiRURfUmFjZUV0aENvZGUiLCJCTUkiLCAiQURJX05hdFJhbmsiLCJTaXRlX05ldyIsICJFRF9FdmVudF9Ccm9hZENsYXNzIiwgIkVEX1BESV9SUyIsIlBSRV9QYWluX01kU3YiLCAiQ1RRX0FueSIsIkNUUV9Ub3RhbCIsIlBoeUFidV9BbnkiLCAiV0syX0NUUVNGX1BoeUFidV9SUyIsICJFbW9BYnVfQW55IiwiV0syX0NUUVNGX0Vtb0FidV9SUyIsICJTZXhBYnVfQW55IiwgIldLMl9DVFFTRl9TZXhBYnVfUlMiLCAiUGh5TmVnX0FueSIsICJXSzJfQ1RRU0ZfUGh5TmVnX1JTIiwgIkVtb05lZ19BbnkiLCAiV0syX0NUUVNGX0Vtb05lZ19SUyIsICJCdWxseWluZ19BbnkiLCAiV0syX0J1bGx5aW5nX1RvdGFsIikKCiMgQ3JlYXRlIGEgbmFtZWQgbGlzdCB0byBzcGVjaWZ5IHRoZSB0eXBlIG9mIGVhY2ggdmFyaWFibGUKdHlwZV9saXN0IDwtIGxpc3QoCiAgV0syX0NUUVNGX1BoeUFidV9SUyA9ICJjb250aW51b3VzIiwKICBXSzJfQ1RRU0ZfRW1vQWJ1X1JTID0gImNvbnRpbnVvdXMiLAogIFdLMl9DVFFTRl9TZXhBYnVfUlMgPSAiY29udGludW91cyIsCiAgV0syX0NUUVNGX1BoeU5lZ19SUyA9ICJjb250aW51b3VzIiwKICBXSzJfQ1RRU0ZfRW1vTmVnX1JTID0gImNvbnRpbnVvdXMiLAogIFdLMl9CdWxseWluZ19Ub3RhbCA9ICJjb250aW51b3VzIikKCiMgR2VuZXJhdGUgdGhlIHN1bW1hcnkgdGFibGUgYW5kIGNvbXBhcmUgYWNyb3NzIGNsYXNzIGFuZCBhZGQgcAoKc3VwcHJlc3NNZXNzYWdlcyhzdXBwcmVzc1dhcm5pbmdzKAogIGRmICU+JQogICAgc2VsZWN0KGFsbF9vZih0YWJsZTFfY2xhc3NfZmVhdHVyZXMpKSAlPiUKICAgIHRibF9zdW1tYXJ5KAogICAgICBieSA9IFBhaW5fQ2xhc3MsCiAgICAgIHN0YXRpc3RpYyA9IGFsbF9jb250aW51b3VzKCkgfiAie21lYW59ICh7c2R9KSIsCiAgICAgIGRpZ2l0cyA9IGFsbF9jb250aW51b3VzKCkgfiAyLAogICAgICB0eXBlID0gdHlwZV9saXN0KSAlPiUgYWRkX3ApKSAKYGBgCgojIyMjIFdoYXQgJSB3ZXJlIGJ1bGxpZWQ/CmBgYHtyfQojIFdoYXQgJSB3ZXJlIGJ1bGxpZWQ/CmRmICU+JQogIHN1bW1hcml6ZSgKICAgIE4gPSBuKCksCiAgICBCdWxseWluZ19BbnkgPSBzdW0oQnVsbHlpbmdfQW55ID09IDEpLAogICAgUGVyY2VudF9CdWxsaWVkID0gcm91bmQoQnVsbHlpbmdfQW55IC8gTiAqIDEwMCwgMikpCgojYm94cGxvdCBvZiBlYWNoIGN0cSB0eXBlIApkZiAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gc3RhcnRzX3dpdGgoIldLMl9DVFFTRiIpLAogICAgbmFtZXNfdG8gPSAiQ1RRX1R5cGUiLAogICAgdmFsdWVzX3RvID0gIlNjb3JlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gQ1RRX1R5cGUsIHkgPSBTY29yZSkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKCmBgYAoKCgojIyMjIEtXIGZ1bmN0aW9uCgpgYGB7cn0Ka3J1c2thbF93YWxsaXNfcmVzdWx0cyA8LSBmdW5jdGlvbihkZiwgZmVhdHVyZXMsIGdyb3VwX3ZhcikgewogIHRlc3RfZmVhdHVyZSA8LSBmdW5jdGlvbihmZWF0dXJlKSB7CiAgICBpZiAoIWZlYXR1cmUgJWluJSBuYW1lcyhkZikpIHsKICAgICAgcmV0dXJuKGRhdGEuZnJhbWUoCiAgICAgICAgRmVhdHVyZSA9IGZlYXR1cmUsCiAgICAgICAgQ2hpX1NxdWFyZSA9IE5BLAogICAgICAgIFBfVmFsdWUgPSBOQQogICAgICApKX0KICAgIGt3X3Rlc3QgPC0gdHJ5Q2F0Y2goCiAgICAgIGtydXNrYWwudGVzdChkZltbZmVhdHVyZV1dIH4gZGZbW2dyb3VwX3Zhcl1dKSwKICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgICAgICAgcmV0dXJuKGxpc3Qoc3RhdGlzdGljID0gTkEsIHAudmFsdWUgPSBOQSkpCiAgICAgIH0pCiAgICBjaGlfc3F1YXJlZCA8LSBrd190ZXN0JHN0YXRpc3RpYwogICAgcF92YWx1ZSA8LSBrd190ZXN0JHAudmFsdWUKICAgIAogICAgcmV0dXJuKGRhdGEuZnJhbWUoCiAgICAgIEZlYXR1cmUgPSBmZWF0dXJlLAogICAgICBDaGlfU3F1YXJlID0gY2hpX3NxdWFyZWQsCiAgICAgIFBfVmFsdWUgPSBwX3ZhbHVlCiAgICApKX0KICAKICByZXN1bHRzIDwtIG1hcF9kZnIoZmVhdHVyZXMsIHRlc3RfZmVhdHVyZSkKICByZXR1cm4ocmVzdWx0cykKfQoKY29udGludW91c19mZWF0dXJlcyA8LSBjKCJXSzJfQ1RRU0ZfUGh5QWJ1X1JTIiwgIldLMl9DVFFTRl9FbW9BYnVfUlMiLCAiV0syX0NUUVNGX1NleEFidV9SUyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIldLMl9DVFFTRl9QaHlOZWdfUlMiLCAiV0syX0NUUVNGX0Vtb05lZ19SUyIsICJXSzJfQnVsbHlpbmdfVG90YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICJFRF9BZ2UiLCAiQk1JIiwgIkFESV9OYXRSYW5rIiwgIkVEX1BESV9SUyIpCgprd190YWJsZSA8LSBrcnVza2FsX3dhbGxpc19yZXN1bHRzKGRmLCBjb250aW51b3VzX2ZlYXR1cmVzLCAiUGFpbl9DbGFzcyIpCgprd190YWJsZQojc2F2ZSBrdyB0YWJsZSBhcyBjc3YKd3JpdGUuY3N2KGt3X3RhYmxlLCAia3dfdGFibGUuY3N2IikKYGBgCgojIyMjIGNoaSBzcSBmdW5jdGlvbgpgYGB7cn0KI3J1biBjaGkgc3F1YXJlIHRlc3QgZm9yIGFsbCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKY2hpX3NxX3Jlc3VsdHMgPC0gZnVuY3Rpb24oZGYsIGZlYXR1cmVzLCBncm91cF92YXIpIHsKICB0ZXN0X2ZlYXR1cmUgPC0gZnVuY3Rpb24oZmVhdHVyZSkgewogICAgaWYgKCFmZWF0dXJlICVpbiUgbmFtZXMoZGYpKSB7CiAgICAgIHJldHVybihkYXRhLmZyYW1lKAogICAgICAgIEZlYXR1cmUgPSBmZWF0dXJlLAogICAgICAgIENoaV9TcXVhcmUgPSBOQSwKICAgICAgICBQX1ZhbHVlID0gTkEKICAgICAgKSl9CiAgICBjaGlfc3FfdGVzdCA8LSB0cnlDYXRjaCgKICAgICAgY2hpc3EudGVzdCh0YWJsZShkZltbZmVhdHVyZV1dLCBkZltbZ3JvdXBfdmFyXV0pKSwKICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgICAgICAgcmV0dXJuKGxpc3Qoc3RhdGlzdGljID0gTkEsIHAudmFsdWUgPSBOQSkpCiAgICAgIH0pCiAgICBjaGlfc3F1YXJlZCA8LSBjaGlfc3FfdGVzdCRzdGF0aXN0aWMKICAgIHBfdmFsdWUgPC0gY2hpX3NxX3Rlc3QkcC52YWx1ZQogICAgCiAgICByZXR1cm4oZGF0YS5mcmFtZSgKICAgICAgRmVhdHVyZSA9IGZlYXR1cmUsCiAgICAgIENoaV9TcXVhcmUgPSBjaGlfc3F1YXJlZCwKICAgICAgUF9WYWx1ZSA9IHBfdmFsdWUKICAgICkpfQogIAogIHJlc3VsdHMgPC0gbWFwX2RmcihmZWF0dXJlcywgdGVzdF9mZWF0dXJlKQogIHJldHVybihyZXN1bHRzKQp9CgpjYXRlZ29yaWNhbF9mZWF0dXJlcyA8LSBjKCJFRF9HZW5kZXJCaXJ0aENlcnQiLCAiRURfUmFjZUV0aENvZGUiLCAiU2l0ZV9OZXciLCAiRURfRXZlbnRfQnJvYWRDbGFzcyIsICJQUkVfUGFpbl9NZFN2IiwgIkNUUV9BbnkiLCAiUGh5QWJ1X0FueSIsICJFbW9BYnVfQW55IiwgIlNleEFidV9BbnkiLCAiUGh5TmVnX0FueSIsICJFbW9OZWdfQW55IiwgIkJ1bGx5aW5nX0FueSIpCgpjaGkuc3FfdGFibGUgPC0gY2hpX3NxX3Jlc3VsdHMoZGYsIGNhdGVnb3JpY2FsX2ZlYXR1cmVzLCAiUGFpbl9DbGFzcyIpCgpjaGkuc3FfdGFibGUKCiNzYXZlIGNoaSBzcSB0YWJsZSBhcyBjc3YKd3JpdGUuY3N2KGNoaS5zcV90YWJsZSwgImNoaV9zcV90YWJsZS5jc3YiKQpgYGAKCgojIyMjIGV4YW1pbmUgYWdlIGJ5IFBhaW4gQ2xhc3MKCmBgYHtyfQpkZiAlPiUKICBncm91cF9ieShQYWluX0NsYXNzKSAlPiUKICBzdW1tYXJpemUoCiAgICBNZWFuX0FnZSA9IG1lYW4oRURfQWdlLCBuYS5ybSA9IFRSVUUpLAogICAgU0RfQWdlID0gc2QoRURfQWdlLCBuYS5ybSA9IFRSVUUpLAogICAgTWVkaWFuX0FnZSA9IG1lZGlhbihFRF9BZ2UsIG5hLnJtID0gVFJVRSksCiAgICBJUVJfQWdlID0gSVFSKEVEX0FnZSwgbmEucm0gPSBUUlVFKSwKICAgIE4gPSBuKCkpCmBgYAoKIyMjIyBFTEEgKyBwcmV2aW91cyBwYWluIHJlbGF0aW9uc2hpcApgYGB7cn0KCiNwcmludCBudW1iZXIgb2YgcGVvcGxlIHdobyBoYWQgbW9kZXJhdGUgb3Igc2V2ZXJlIHBhaW4Kc3VtbWFyeV9kZiA8LSBkYXRhLmZyYW1lKAogIE4gPSBucm93KGRmKSwKICBQUkVfUGFpbl9NZFN2ID0gc3VtKGRmJFBSRV9QYWluX01kU3YgPT0gIlllcyIpLAogIFBlcmNlbnRfUGFpbiA9IHJvdW5kKHN1bShkZiRQUkVfUGFpbl9NZFN2ID09ICJZZXMiKSAvIG5yb3coZGYpICogMTAwLCAyKSkKCnQgPC0gdGFibGUoZGYkUFJFX1BhaW5fTWRTdikKCiNtYWtlIHRoZSB0YWJsZSBgdGAgcGVyY2VudGFnZXMgCnQKcHJvcC50YWJsZSh0KSAqIDEwMAoKZGYkUFJFX1BhaW5fTWRTdiA8LSBhcy5mYWN0b3IoZGYkUFJFX1BhaW5fTWRTdikKZGYkQ1RRX0FueSA8LSBhcy5mYWN0b3IoZGYkQ1RRX0FueSkKZGYkQnVsbHlpbmdfQW55IDwtIGFzLmZhY3RvcihkZiRCdWxseWluZ19BbnkpCgpjaGlzcS50ZXN0KHRhYmxlKGRmJFBSRV9QYWluX01kU3YsIGRmJEJ1bGx5aW5nX0FueSkpCmNoaXNxLnRlc3QodGFibGUoZGYkUFJFX1BhaW5fTWRTdiwgZGYkQ1RRX0FueSkpCgptMzUgPC0gZ2xtKFBSRV9QYWluX01kU3YgfiBDVFFfVG90YWwsIGRhdGEgPSBkZiwgZmFtaWx5ID0gYmlub21pYWwpCnRpZHkobTM1LCBleHBvbmVudGlhdGUgPSBUUlVFLCBjb25mLmludCA9IFRSVUUpIAoKbTM2IDwtIGdsbShQUkVfUGFpbl9NZFN2IH4gV0syX0J1bGx5aW5nX1RvdGFsLCBkYXRhID0gZGYsIGZhbWlseSA9IGJpbm9taWFsKQp0aWR5KG0zNiwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKQpgYGAKCjxicj4KCkVMQSArIHByZXZpb3VzIHBhaW4geiBzY29yZSBub3JtYWxpemVkCgpgYGB7cn0KZGYkQ1RRX1RvdGFsX3ogPC0gc2NhbGUoZGYkQ1RRX1RvdGFsKQpkZiRXSzJfQnVsbHlpbmdfVG90YWxfeiA8LSBzY2FsZShkZiRXSzJfQnVsbHlpbmdfVG90YWwpCgptb2RlbF9jdHFfeiA8LSBnbG0oUFJFX1BhaW5fTWRTdiB+IENUUV9Ub3RhbF96LCBkYXRhID0gZGYsIGZhbWlseSA9ICJiaW5vbWlhbCIpCnRpZHkobW9kZWxfY3RxX3osIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkKCm1vZGVsX2J1bGx5aW5nX3ogPC0gZ2xtKFBSRV9QYWluX01kU3YgfiBXSzJfQnVsbHlpbmdfVG90YWxfeiwgZGF0YSA9IGRmLCBmYW1pbHkgPSAiYmlub21pYWwiKQp0aWR5KG1vZGVsX2J1bGx5aW5nX3osIGV4cG9uZW50aWF0ZSA9IFRSVUUsIGNvbmYuaW50ID0gVFJVRSkKYGBgCgoKCgojIyMgU3Vic2V0IGZvciBMYXVyZW4KYGBge3J9CiNtYWtlIGEgY3N2IHRoYXQgY29udGFpbnMgUElELCBQYWluX0NsYXNzLCBDVFFfVG90YWwsIGFuZCBCdWxseWluZyBzY29yZQpkZl9MYXVyZW4gPC0gZGZfdHJhaiAlPiUgc2VsZWN0KFBJRCwgUGFpbl9DbGFzcywgQ1RRX1RvdGFsLCBXSzJfQnVsbHlpbmdfVG90YWwpCgojcmVtb3ZlIE5BIHZhbHVlcyBmcm9tIGRmX2xhdXJlbgpkZl9MYXVyZW4gPC0gZGZfTGF1cmVuICU+JSBkcm9wX25hKCkKCndyaXRlLmNzdihkZl9MYXVyZW4sICJkZl8yNDgwX0ZyZWV6ZTRfZGF0YV9MYXVyZW4uY3N2IikKYGBgCgoKIyMjIE5vdGVzCgojIyMjIFRPIENPTVBMRVRFIEpVTFkgMjk6CgpjaGVjayBhbmQgY2xlYW4gZWFjaCBmZWF0dXJlIGRhdGEgKOKckykgcmUtY29kZSB0cmF1bWEgdHlwZXNcfiAo4pyTKSBydW4gbXVsdGljb2xsaW5lYXJpdHkgdGVzdCAoMykgZm9yIGVhY2ggY3RxIHN1YnR5cGVzLCB0dGVzdCBhbmQgcGxvdCBmb3IgZ2VuZGVyICjinJMpIGZvciBlYWNoIGN0cSBzdWJ0eXBlLCB0dGVzZXQgYW5kIHBsb3QgZm9yIHJhY2UgKOKckykgQU5PVkEgb24gcmFjZSB2cyBDVFEgKOKckykgbmV3IENUUSBjb21ibyB2YXJpYWJsZSBtb2RlbCAo4pyTKSBydW4gbXVsdGljb2xsaW5lYXJpdHkgb24gbmV3bHkgYWRkZWQgZmVhdHVyZXMgKOKckykgYWRkIGluY29tZSBhbmQgcmUtY2F0IGVkdWNhdGlvbiB0byBtMiAo4pyTKSBiYXNlIG1vZGVsICsgQ1RRXCpyYWNlICjinJMpCgojIyMjIG5vdGVzIGp1bHkgMzB0aAoKMS4gIGFkZCBtYXJpdGFsIHN0YXR1cyA0IHRvIGRpdm9yY2UgY2F0ZWdvcnkgKOKckykKMi4gIGNoZWNrIGZyZXF1ZW5jaWVzIG9mIGFsbCBjYXRlZ29yaWVzIGluIGFsbCB2YXJpYWJsZXMgKOKckykKMy4gIG1hcml0YWwgc3RhdHVzIDEtbWFycmllZCAyLXNlcGFyYXRlZCAzLWRpdm9yY2VkIDQtYW5udWxsZWQgNS13aWRvd2VkIDYtc2luZ2xlICjinJMpCjQuICBtYXJyaWFnZSAtIGNvbWJpbmUgMiszKzQrNSBhcyBhIHNpbmdsZSBjYXRlZ29yeSAo4pyTKQo1LiAgZWR1Y2F0aW9uIC0gYWxsIG5lZ2F0aXZlcyBhcmUgbWlzc2luZyBmb3IgZGlmZmVyZW50IHJlYXNvbnMgPSBOQSAo4pyTKQo2LiAgTGF1cmVuIHdpbGwgZW1haWwgQWxpY2UgdGhlIGVkdWNhdGlvbiBjYXRlZ29yeSBpbmZvICjinJMpCjcuICAxLSBkaWQgbm90IGZpbmlzaCBIUyAoY29kZXMgMC0xMikgMi0gSFMgZ3JhZCArIHNvbWUgY29sbGVnZSAoY29kZXMgMTMtMTUpIDMtIGNvbGxlZ2UgZ3JhZCAoQmFjaGVsb3JzIG9yIEFzc29jaWF0ZXMpIChjb2RlcyAxNi0xOCkgNC0gcG9zdCBncmFkIGNvZGVzKDE5LTIxKSAo4pyTKQo4LiAgVXNlIEFESSBpbnN0ZWFkIG9mIGluY29tZSAo4pyTKQoKIyMjIyBqdWx5IDMwdGggcnVuIHRoZXNlIGFuZCBzZW5kIHJlc3VsdHMgdG9kYXkKCjguICBydW4gTTIgd2l0aCBhIENUUTo6cmFjZSBpbnRlcmFjdGlvbiBhbmQgYSBzZXBhcmF0ZSBtb2RlbCB3aXRoIENUUTo6U2V4IGludGVyYWN0aW9uICjinJMpCjkuICBSdW4gTTIgd2l0aCBlYWNoIENUUSBzdWJ0eXBlIGFuZCBidWxseWluZyAo4pyTKQoxMC4gc2NhbGUgbm9ybWFsaXplIGVhY2ggZmVhdHVyZSBzbyB0aGV5IGNhbiBiZSBjb21wYXJlZCBhY3Jvc3Mgb25lIGFub3RoZXIgLyBjYW4gY2xhaW0gd2hpY2ggYXJlIG1vcmUgb3IgbGVzcyBhc3NvY2lhdGVkIHdpdGggcG9zdCB0cmF1bWEgcGFpbiAo4pyTKQoxMS4gY29tcGFyZSB0cmlhZCBiYXNlZCBtb2RlbCB2cyBjb21wbGV0ZWQgY3RxIG1vZGVsLCB1c2UgQUlDL0JJQyBhbmQgb3RoZXIgbWVhc3VyZW1lbnRzIG9mIGZpdCB0byBzaG93ICJiZXR0ZXIiIG1vZGVsICjinJMpCjEyLiByZWRvIEFOT1ZBcyBhcyBLVyBhbmQgc2hvdyBwYWlyd2lzZSBjb21wYXJpc29uIHBvc3Rob2MuIGZvciByYWNlICjinJMpCjEzLiBtYWtlIGEgZGVtb2dyYXBoaWNzIHRhYmxlIHdpdGggc2lnbmlmaWNhbmNlIGJ5IHBhaW4gdHJhamVjdG9yeSAo4pyTKQoxNC4gYW5lc3RoZXNpYSByZXNlYXJjaCBhYnN0cmFjdAoKIyMjIyBKdWx5IDMxc3Qgbm90ZXMKMC4gcmVkbyBhbmFseXNpcyB3aXRoIHRoZSBvcmlnaW5hbCBkZiBpIHdhcyB1c2luZy8gdGhlIEZSRUVaRSA0IGRmICjinJMpCjEuIG9uZSBvdXQgcHV0IG9mIHR3byBncmFwaHM6IG9uZSBncmFwaCB3aXRoIENUUSB0b3RhbCBieSBzZXgsIGFuZCBvdGhlciBncmFwaCBpcyBDVFEgdG90YWwgYnkgcmFjZS4gYW5kIGFkZCBzdGFycy9zaWduaWZpY2FuY2Ugbm90YXRpb24gZm9yIHNleCwgbnMgZm9yIHJhY2UKMi4gbWFrZSBncmFwaHMgb2Ygc3VidHlwZXMgKGluY2wgYnVsbHlpbmcgaW5zdGVhZCBvZiBjdHEgdG90YWwpIHNvIHdlIGhhdmUgMngzIHRhYmxlIGFuZCBpbmNsdWRlIGFzdGVyaXNrcyBmb3Igc2lnCgojIyMjIEp1bHkgMzEgcmVxdWVzdCBmcm9tIExhdXJlbgoxLiBUYWJsZSAxOiBzYW1wbGUgY2hhcmFjdGVyaXN0aWNzIGZvciBmdWxsIGNvaG9ydAoyLiBTdXBwbGVtZW50YXJ5IFRhYmxlIDI6IHNhbXBsZSBjaGFyYWN0ZXJpc3RpY3Mgc3BsaXQgYnkgcGFpbiB0cmFqZWN0b3JpZXMKMy4gU3VwcGxlbWVudGFyeSBUYWJsZSAzOiBFTEEgc3VidHlwZSBjb3JyZWxhdGlvbiBoZWF0bWFwL3RhYmxlCgoK