Description:

The effect of intelligence on success has been debated - some argue that it’s overstated (e.g. Gladwell, Taleb); others say it has a decent impact, but that other factors must have a large effect based on the fact that IQ only explains so much variance (10-20%) in most outcomes (this is the position of most mainstream intelligence researchers). I’ve only seen AR Jensen emphasize the importance of accurate measurement – it seems his instincts were in the right place.

In this piece I show that it is the third perspective that is correct, and the association between IQ and socioeconomic status is deflated by the fact there is no perfect indicator of SES. Using a composite of education, occupation, assets, and income earned over 20 years, I find that about 40% of the permanent variation in socioeconomic status can be accounted for by intelligence, and this reduces by about 20% when the non-causal variation is parsed out.

Note that all of the causal explanatory variables of SES must add up to 100% - if intelligence only explains 10-20% of the variation in socioeconomic status, then 80-90% of the variation remains. Most of the research I have seen on “inherited unfair advantages” (e.g. attractiveness, height, voice tone, skin color) is that these may have a small causal effect, but that they explain very little variance in success – say 5%. This still leaves 75-85% of the variation explained – which must be some kind of random luck or personality traits. I don’t deny that these are valuable, but given the findings from twin studies, I find it hard to believe that these factors can account fully for the 80%.

DATA CLEANING

Preliminary data cleaning:

#loading data
setwd('~')
Warning: The working directory was changed to /home/asuka inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
setwd('Documents/rstuff/predsucc')
new_data <- read.csv('new_data.csv')

#demographics
new_data$Female <- new_data$R0536300-1
new_data$race <- 'Other'
new_data$race[new_data$R0538700==1] <- 'White'
new_data$race[new_data$R0538600==1] <- 'Hispanic'
new_data$race[new_data$R0538700==4] <- 'Asian'
new_data$race[new_data$R0538700==2] <- 'Black'

#iq data
subtestlist <- c('GS', 'AR', 'WK', 'PC', 'NO', 'CS', 'AI', 'SI', 'MK', 'MC', 'EI', 'AO')
new_data$GS = NA
new_data$AR = NA
new_data$WK = NA
new_data$PC = NA
new_data$NO = NA
new_data$CS = NA
new_data$AI = NA
new_data$SI = NA
new_data$MK = NA
new_data$MC = NA
new_data$EI = NA
new_data$AO = NA

new_data$testday = new_data$R9708601*1/12+new_data$R9708602

new_data$testday[is.na(new_data$testday)] <- 1997.661

new_data$bdate = new_data$R0536402 + new_data$R0536401*1/12

new_data$ageat = new_data$testday-new_data$bdate
cor.test(new_data$R9705300, new_data$ageat)

    Pearson's product-moment correlation

data:  new_data$R9705300 and new_data$ageat
t = 7.3547, df = 2380, p-value = 2.62e-13
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.1095651 0.1881073
sample estimates:
      cor 
0.1490713 
j = 0
for(stest in subtestlist) {
  posstring = paste("R", 9705200+j*100, sep="")
  negstring = paste("R", 9706400+j*100, sep="")
  stcolumnindex = getcolindex(stest, new_data)
  negcolumnindex = getcolindex(negstring, new_data)
  poscolumnindex = getcolindex(posstring, new_data)
  new_data[, stcolumnindex] = as.numeric(pmax(new_data[, negcolumnindex]*-1, new_data[, poscolumnindex], na.rm=TRUE))
  new_data[, stcolumnindex] = normalise(new_data[, stcolumnindex])
  new_data[, stcolumnindex][!is.na(new_data[, stcolumnindex])] <- agecorrect(stest, agevectorname='ageat', datafr = new_data, normalizeit=T, splinex = 6)
  j = j+1
}
cor.test(new_data$GS, new_data$ageat)

    Pearson's product-moment correlation

data:  new_data$GS and new_data$ageat
t = 2.3196e-14, df = 7125, p-value = 1
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.02321711  0.02321711
sample estimates:
         cor 
2.748013e-16 
iq <- subset(new_data, select = c(GS, AR, WK, PC, NO, CS, AI, SI, MK, MC, EI, AO))
new_data$g2 = getpc(iq, normalizeit=T, fillmissing=F, dofa=F)
new_data$IQ <- new_data$g2*15+100
new_data$age = 2021 - new_data$bdate

Parental SES data cleaning (assets + family income + father/mother education). Severe outliers (+5SD above the mean) were removed.

poldat <- subset(new_data, select = c(R1204500, R1204700, R1302600, R1302700))
new_data$pses = getpc(poldat, normalizeit=T, fillmissing=T, dofa=F)
new_data$pses[new_data$pses > 5] <- NA

pcalol <- pca(poldat, nfactors=1, rotate="none", missing=TRUE)
print(pcalol)
Principal Components Analysis
Call: principal(r = r, nfactors = nfactors, residuals = residuals, 
    rotate = rotate, n.obs = n.obs, covar = covar, scores = scores, 
    missing = missing, impute = impute, oblique.scores = oblique.scores, 
    method = method, use = use, cor = cor, correct = 0.5, weight = NULL)
Standardized loadings (pattern matrix) based upon correlation matrix

                PC1
SS loadings    2.30
Proportion Var 0.57

Mean item complexity =  1
Test of the hypothesis that 1 component is sufficient.

The root mean square of the residuals (RMSR) is  0.19 
 with the empirical chi square  3797.21  with prob <  0 

Fit based upon off diagonal values = 0.83

Child income, net worth and education data cleaning – pre-2000 data is not considered. For a few children, net worth at 20 would have been measured in 1999 – I judge this as a nonfactor, so I included this variable.

column_mappings <- c("inc2000", R6827500 = "inc2001", S1055800 = "inc2002", 
                     S3134600 = "inc2003", S4799600 = "inc2004", S6501000 = "inc2005", 
                     S8496500 = "inc2006", T0889800 = "inc2007", T3003000 = "inc2008", 
                     T4406000 = "inc2009", T6055500 = "inc2010", T7545600 = "inc2011", 
                     T8976700 = "inc2013", U0956900 = "inc2015", U2857200 = "inc2017", 
                     U4282300 = "inc2019", U5753500 = "inc2021")

names_to_change <- names(new_data) %in% names(column_mappings)  
names(new_data)[names_to_change] <- column_mappings[names(new_data)[names_to_change]]
##############
degree_mappings <- c(
  S2261100 = "deg2003", S4032600 = "deg2004", S5613000 = "deg2005",
  S7683300 = "deg2006", T0149600 = "deg2007", T2120000 = "deg2008",
  T3731100 = "deg2009", T5322200 = "deg2010", T6767100 = "deg2011",
  T8241400 = "deg2013", U0137100 = "deg2015", U1990700 = "deg2017",
  U3572700 = "deg2019", U5072600 = "deg2021"
)

names_to_change <- names(new_data) %in% names(degree_mappings)  
names(new_data)[names_to_change] <- degree_mappings[names(new_data)[names_to_change]] 

new_data <- data.frame(new_data)
deg_columns <- c("deg2003", "deg2004", "deg2005", 
                    "deg2006", "deg2007", "deg2008", "deg2009", "deg2010", "deg2011", 
                    "deg2013", "deg2015", "deg2017", "deg2019", "deg2021")
existing_deg_columns <- deg_columns[deg_columns %in% names(new_data)]
yearly_averages <- sapply(new_data[, existing_deg_columns], mean, na.rm = TRUE)

net_worth_mappings <- c(
  Z9048900 = "nwage20", 
  Z9049000 = "nwage25", 
  Z9121900 = "nwage30",
  Z9141400 = "nwage35",
  Z9164500 = "nwage40"
)

names_to_change <- names(new_data) %in% names(net_worth_mappings)  
names(new_data)[names_to_change] <- net_worth_mappings[names(new_data)[names_to_change]] 

income_columns <- c("inc2000", "inc2001", "inc2002", "inc2003", "inc2004", "inc2005", 
                    "inc2006", "inc2007", "inc2008", "inc2009", "inc2010", "inc2011", 
                    "inc2013", "inc2015", "inc2017", "inc2019", "inc2021")

existing_income_columns <- income_columns[income_columns %in% names(new_data)]
yearly_averages <- sapply(new_data[, existing_income_columns], mean, na.rm = TRUE)

new_data$weighted_mean_income <- apply(new_data[, existing_income_columns], 1, function(row) {
  non_missing_indices <- !is.na(row)
  total_income <- sum(row[non_missing_indices], na.rm = TRUE)
  total_average <- sum(yearly_averages[non_missing_indices], na.rm = TRUE)
  weighted_mean <- ifelse(total_average > 0, total_income / total_average, NA)
  return(weighted_mean)
})

Occupation data cleaning – placed separately, as the occupation data was more complex than the other data. Occupation rank was assigned based on the average income of the job. ‘job2000_01’ refers to the respondent’s first job in 2000, ‘job2007_03’ refers to the respondent’s third job in 2007.

occupation_mappings <- c(
  S3713000 = "job2000_01", S3713100 = "job2000_02", S3713200 = "job2000_03", S3713300 = "job2000_04",
  S3729000 = "job2001_01", S3729100 = "job2001_02", S3729200 = "job2001_03", S3729300 = "job2001_04",
  S3757000 = "job2003_01", S3757100 = "job2003_02", S3757200 = "job2003_03", S3757300 = "job2003_04",
  S5041700 = "job2004_01", S5041800 = "job2004_02", S5041900 = "job2004_03", S5042000 = "job2004_04",
  S8689700 = "job2006_01", S8689800 = "job2006_02", S8689900 = "job2006_03", S8690000 = "job2006_04",
  T1109400 = "job2007_01", T1109500 = "job2007_02", T1109600 = "job2007_03", T1109700 = "job2007_04",
  T3186900 = "job2008_01", T3187000 = "job2008_02", T3187100 = "job2008_03", T3187200 = "job2008_04",
  T4597800 = "job2009_01", T4597900 = "job2009_02", T4598000 = "job2009_03", T4598100 = "job2009_04",
  T6231000 = "job2010_01", T6231100 = "job2010_02", T6231200 = "job2010_03", T6231300 = "job2010_04",
  T7732100 = "job2011_01", T7732200 = "job2011_02", T7732300 = "job2011_03", T7732400 = "job2011_04",
  T9133500 = "job2013_01", T9133600 = "job2013_02", T9133700 = "job2013_03", T9133800 = "job2013_04",
  U1127100 = "job2015_01", U1127200 = "job2015_02", U1127300 = "job2015_03", U1127400 = "job2015_04",
  U1719400 = "job2017_01", U1719500 = "job2017_02", U1719600 = "job2017_03", U1719700 = "job2017_04",
  U3315700 = "job2019_01", U3315800 = "job2019_02", U3315900 = "job2019_03", U3316000 = "job2019_04",
  U4820200 = "job2021_01", U4820300 = "job2021_02", U4820400 = "job2021_03", U4820500 = "job2021_04"
)

names(new_data) <- ifelse(names(new_data) %in% names(occupation_mappings),
                          occupation_mappings[names(new_data)],
                          names(new_data))

###################
new_data$temp <- normalise(new_data$weighted_mean_income)
job_columns <- grep("job", names(new_data), value = TRUE)
rankings <- list()

#ranking the variables by income
for (job in job_columns) {
  new_data$temp2 <- new_data[[job]]
  rankings[[job]] <- new_data %>% group_by(temp2) %>% summarise(status = mean(temp, na.rm=T))
}
#converting this to a list
average_status_by_temp2 <- list()
for (job_name in names(rankings)) {
  average_status_by_temp2[[job_name]] <- aggregate(status ~ temp2, data = rankings[[job_name]], mean)
}

#combining years to reduce unreliability in ranking
combined_averages <- Reduce(function(x, y) merge(x, y, by = "temp2", all = TRUE), average_status_by_temp2)
combined_averages$sum <- rowMeans(combined_averages[, 2:61], na.rm=T)
pol <- combined_averages %>% select(sum, temp2)

Then, weighed averages were made from the years between 2000-2021 based on the data. Because SES measured later in life is higher on average, the years must be weighed based on this bias. This makes the scale a bit uninterpretable, but it has a more accurate rank order. For occupation, the highest status job an individual held in a given year was used as the main variable within years.

#####income data cleaning
income_columns <- c("inc2000", "inc2001", "inc2002", "inc2003", "inc2004", "inc2005", 
                    "inc2006", "inc2007", "inc2008", "inc2009", "inc2010", "inc2011", 
                    "inc2013", "inc2015", "inc2017", "inc2019", "inc2021")

existing_income_columns <- income_columns[income_columns %in% names(new_data)]
yearly_averages <- sapply(new_data[, existing_income_columns], mean, na.rm = TRUE)

new_data$weighted_mean_income <- apply(new_data[, existing_income_columns], 1, function(row) {
  non_missing_indices <- !is.na(row)
  total_income <- sum(row[non_missing_indices], na.rm = TRUE)
  total_average <- sum(yearly_averages[non_missing_indices], na.rm = TRUE)
  weighted_mean <- ifelse(total_average > 0, total_income / total_average, NA)
  return(weighted_mean)
})

#####education data cleaning
new_data <- data.frame(new_data)
deg_columns <- c("deg2003", "deg2004", "deg2005", 
                    "deg2006", "deg2007", "deg2008", "deg2009", "deg2010", "deg2011", 
                    "deg2013", "deg2015", "deg2017", "deg2019", "deg2021")
existing_deg_columns <- deg_columns[deg_columns %in% names(new_data)]
yearly_averages <- sapply(new_data[, existing_deg_columns], mean, na.rm = TRUE)
new_data$weighted_degree <- apply(new_data[, existing_deg_columns], 1, function(row) {
  non_missing_indices <- !is.na(row)
  total_deg <- sum(row[non_missing_indices], na.rm = TRUE)
  total_average <- sum(yearly_averages[non_missing_indices], na.rm = TRUE)
  weighted_mean <- ifelse(total_deg > 0, total_deg / total_average, NA)
  return(weighted_mean)
})

#########occupation data cleaning
for (jobcol in job_columns) {
  temp <- paste0(jobcol, '_rank')
  new_data$temp_key <- new_data[[jobcol]]
  new_data <- new_data %>%
    left_join(pol, by = c("temp_key" = "temp2")) %>%
    mutate(!!temp := sum) %>%
    select(-sum)
  new_or.new_datadata <- select(new_data, -temp_key)
}

years <- seq(2000, 2021, by = 1) 

for (year in years) {
  rank_cols <- grep(paste0("job", year, "_\\d{2}_rank"), names(new_data), value = TRUE)

  if (length(rank_cols) == 4) {
    new_data <- new_data %>%
      mutate(!!paste0("highest_rank_job_", year) := pmax(!!!rlang::syms(rank_cols), na.rm = TRUE))
  } else {
    warning(paste("Expected 4 job rank columns for year", year, "but found", length(rank_cols)))
  }
}
Warning: Expected 4 job rank columns for year 2002 but found 0Warning: Expected 4 job rank columns for year 2005 but found 0Warning: Expected 4 job rank columns for year 2012 but found 0Warning: Expected 4 job rank columns for year 2014 but found 0Warning: Expected 4 job rank columns for year 2016 but found 0Warning: Expected 4 job rank columns for year 2018 but found 0Warning: Expected 4 job rank columns for year 2020 but found 0
new_data <- data.frame(new_data)

for(col in occ_columns) {
  new_data[[col]] <- new_data[[col]] - min(new_data[[col]], na.rm=T)
}

occ_columns <- grep(paste0("highest"), names(new_data), value = TRUE)
existing_occ_columns <- occ_columns[occ_columns %in% names(new_data)]
yearly_averages <- sapply(new_data[, existing_occ_columns], mean, na.rm = TRUE)

new_data$weighted_occ <- apply(new_data[, existing_occ_columns], 1, function(row) {
  non_missing_indices <- !is.na(row)
  total_occ <- sum(row[non_missing_indices], na.rm = TRUE)
  total_average <- sum(yearly_averages[non_missing_indices], na.rm = TRUE)
  weighted_mean <- ifelse(total_occ > 0, total_occ / total_average, NA)
  return(weighted_mean)
})

new_data <- data.frame(new_data)

for(col in occ_columns) {
  new_data[[col]] <- new_data[[col]] - min(new_data[[col]], na.rm=T)
}

#net worth data cleaning
nw_columns <- net_worth_mappings <- c("nwage20", "nwage25", "nwage30","nwage35","nwage40")
existing_nw_columns <- nw_columns[nw_columns %in% names(new_data)]
yearly_averages <- sapply(new_data[, existing_nw_columns], mean, na.rm = TRUE)

new_data$weighted_nw <- apply(new_data[, existing_nw_columns], 1, function(row) {
  non_missing_indices <- !is.na(row)
  total_occ <- sum(row[non_missing_indices], na.rm = TRUE)
  total_average <- sum(yearly_averages[non_missing_indices], na.rm = TRUE)
  weighted_mean <- ifelse(total_occ > 0, total_occ / total_average, NA)
  return(weighted_mean)
})

Age adjustments were made, as not everybody was of the same age.

new_data$weighted_occ[!is.na(new_data$weighted_occ)] <- agecorrect('weighted_occ', agevectorname='age', datafr = new_data, normalizeit=T, splinex = 6)

new_data$weighted_mean_income[!is.na(new_data$weighted_mean_income)] <- agecorrect('weighted_mean_income', agevectorname='age', datafr = new_data, normalizeit=T, splinex = 6)

new_data$weighted_degree[!is.na(new_data$weighted_degree)] <- agecorrect('weighted_degree', agevectorname='age', datafr = new_data, normalizeit=T, splinex = 6)

new_data$weighted_nw[!is.na(new_data$weighted_nw)] <- agecorrect('weighted_nw', agevectorname='age', datafr = new_data, normalizeit=T, splinex = 6)

Finally, the holy grail: ses – a composite of semi-permanent assets, education, income, and occupational status.

new_data$ses <- getpc(new_data %>% select(weighted_occ, weighted_mean_income, weighted_degree, weighted_nw), normalizeit = T, fillmissing=F, dofa=F)

RESULTS:

The correlation matrix of the main indicators: parental socioeconomic status (pses), child socioeconomic status (ses), child IQ (IQ), semi-permanent occupational status (weighted_occ), semi-permanent income (weighted_mean_income), semi-permanent education (weighted_degree), and semi-permanent assets (weighted_nw).

correlation_matrix(new_data %>% select(weighted_occ, weighted_mean_income, weighted_degree, weighted_nw, ses, pses, IQ))
                     weighted_occ weighted_mean_income weighted_degree weighted_nw ses         pses        IQ         
weighted_occ         "NA"         "0.626 ***"          "0.451 ***"     "0.35 ***"  "0.823 ***" "0.298 ***" "0.449 ***"
weighted_mean_income "0.626 ***"  "NA"                 "0.395 ***"     "0.433 ***" "0.836 ***" "0.25 ***"  "0.364 ***"
weighted_degree      "0.451 ***"  "0.395 ***"          "NA"            "0.328 ***" "0.702 ***" "0.444 ***" "0.557 ***"
weighted_nw          "0.35 ***"   "0.433 ***"          "0.328 ***"     "NA"        "0.67 ***"  "0.29 ***"  "0.275 ***"
ses                  "0.823 ***"  "0.836 ***"          "0.702 ***"     "0.67 ***"  "NA"        "0.43 ***"  "0.557 ***"
pses                 "0.298 ***"  "0.25 ***"           "0.444 ***"     "0.29 ***"  "0.43 ***"  "NA"        "0.458 ***"
IQ                   "0.449 ***"  "0.364 ***"          "0.557 ***"     "0.275 ***" "0.557 ***" "0.458 ***" "NA"       

The scatterplots for the semi-permanent variables. Note the linear association between IQ and every variable with the exception of parental SES.

GG_scatter(new_data, 'IQ', 'ses') + geom_smooth()

GG_scatter(new_data, 'pses', 'IQ') + geom_smooth()

GG_scatter(new_data, 'IQ', 'weighted_occ') + geom_smooth()

GG_scatter(new_data, 'IQ', 'weighted_mean_income') + geom_smooth()

GG_scatter(new_data, 'IQ', 'weighted_degree') + geom_smooth()

GG_scatter(new_data, 'IQ', 'weighted_nw') + geom_smooth()

Compare this to the ones generated for just the year 2010:

new_data$ses2010 <- getpc(new_data %>% select(highest_rank_job_2010, inc2010, deg2010, nwage30))

GG_scatter(new_data, 'IQ', 'ses2010') + geom_smooth()

GG_scatter(new_data, 'IQ', 'highest_rank_job_2010') + geom_smooth()

GG_scatter(new_data, 'IQ', 'inc2010') + geom_smooth()

GG_scatter(new_data, 'IQ', 'deg2010') + geom_smooth()

GG_scatter(new_data, 'IQ', 'nwage30') + geom_smooth()

There are several ways to estimate the true correlation between IQ and SES: - Jensen vector method - Latent correlation - Adjusting for observed unreliability.

Jensen vector method estimates the correlation between g and SES to be .56:

p <- pca(new_data %>% select(subtestlist), rotate='none', nfactors=1)

debi <- data.frame(v = rep('', length(subtestlist)), r = rep(0, length(subtestlist)))
debi$v <- NA
i = 1
for(vec in subtestlist) {
  debi$v[i] <- vec
  debi$r[i] <- cor.test(new_data[[vec]], new_data$ses)$estimate
  i = i + 1
}
debi$v
 [1] "GS" "AR" "WK" "PC" "NO" "CS" "AI" "SI" "MK" "MC" "EI" "AO"
debi$l <- p$loadings
GG_scatter(df=debi, x_var='l', y_var='r', case_names = 'v')


lr <- lm(data=debi, r ~ l)
lr

Call:
lm(formula = r ~ l, data = debi)

Coefficients:
(Intercept)            l  
   -0.01948      0.58374  

Latent correlation is .64

lat0 <- "
  #LATENTS
  S =~ weighted_occ + weighted_mean_income + weighted_degree + weighted_nw
  G =~ GS+AR+WK+PC+NO+CS+AI+SI+MK+MC+EI+AO

  S ~~ G
"
latfit1 <- sem(model = lat0, data=new_data)
summary(latfit1, fit.measures=T, standardize=T)
lavaan 0.6.17 ended normally after 29 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                        33

                                                  Used       Total
  Number of observations                          5685        8984

Model Test User Model:
                                                      
  Test statistic                              9278.057
  Degrees of freedom                               103
  P-value (Chi-square)                           0.000

Model Test Baseline Model:

  Test statistic                             62419.878
  Degrees of freedom                               120
  P-value                                        0.000

User Model versus Baseline Model:

  Comparative Fit Index (CFI)                    0.853
  Tucker-Lewis Index (TLI)                       0.828

Loglikelihood and Information Criteria:

  Loglikelihood user model (H0)            -103149.265
  Loglikelihood unrestricted model (H1)     -98510.237
                                                      
  Akaike (AIC)                              206364.531
  Bayesian (BIC)                            206583.835
  Sample-size adjusted Bayesian (SABIC)     206478.971

Root Mean Square Error of Approximation:

  RMSEA                                          0.125
  90 Percent confidence interval - lower         0.123
  90 Percent confidence interval - upper         0.127
  P-value H_0: RMSEA <= 0.050                    0.000
  P-value H_0: RMSEA >= 0.080                    1.000

Standardized Root Mean Square Residual:

  SRMR                                           0.077

Parameter Estimates:

  Standard errors                             Standard
  Information                                 Expected
  Information saturated (h1) model          Structured

Latent Variables:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
  S =~                                                                  
    weighted_occ      1.000                               0.789    0.776
    weightd_mn_ncm    0.953    0.019   49.047    0.000    0.752    0.744
    weighted_degre    0.785    0.018   42.848    0.000    0.619    0.632
    weighted_nw       0.655    0.019   34.318    0.000    0.517    0.503
  G =~                                                                  
    GS                1.000                               0.877    0.873
    AR                0.995    0.011   90.555    0.000    0.873    0.865
    WK                0.980    0.011   89.462    0.000    0.860    0.860
    PC                0.971    0.011   87.402    0.000    0.852    0.850
    NO                0.703    0.013   52.490    0.000    0.617    0.615
    CS                0.632    0.014   45.925    0.000    0.555    0.555
    AI                0.650    0.014   46.617    0.000    0.571    0.561
    SI                0.723    0.013   53.846    0.000    0.634    0.626
    MK                0.970    0.011   86.013    0.000    0.851    0.843
    MC                0.927    0.012   79.430    0.000    0.814    0.807
    EI                0.911    0.012   76.292    0.000    0.799    0.789
    AO                0.797    0.013   62.835    0.000    0.699    0.698

Covariances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
  S ~~                                                                  
    G                 0.442    0.013   33.163    0.000    0.638    0.638

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .weighted_occ      0.412    0.012   33.984    0.000    0.412    0.398
   .weightd_mn_ncm    0.456    0.012   37.322    0.000    0.456    0.447
   .weighted_degre    0.577    0.013   44.982    0.000    0.577    0.601
   .weighted_nw       0.787    0.016   49.129    0.000    0.787    0.747
   .GS                0.241    0.005   45.201    0.000    0.241    0.239
   .AR                0.256    0.006   45.751    0.000    0.256    0.252
   .WK                0.261    0.006   46.104    0.000    0.261    0.261
   .PC                0.280    0.006   46.717    0.000    0.280    0.278
   .NO                0.626    0.012   51.780    0.000    0.626    0.622
   .CS                0.693    0.013   52.192    0.000    0.693    0.692
   .AI                0.708    0.014   52.153    0.000    0.708    0.685
   .SI                0.623    0.012   51.683    0.000    0.623    0.608
   .MK                0.296    0.006   47.094    0.000    0.296    0.290
   .MC                0.354    0.007   48.578    0.000    0.354    0.349
   .EI                0.388    0.008   49.145    0.000    0.388    0.378
   .AO                0.514    0.010   50.907    0.000    0.514    0.512
    S                 0.622    0.020   30.957    0.000    1.000    1.000
    G                 0.770    0.019   41.310    0.000    1.000    1.000

Adjusting for the observed unreliability (omega total), a correlation of .64 is obtained.

reliability(new_data %>% select(weighted_occ, weighted_mean_income, weighted_degree, weighted_nw))
keys not specified, all items will be scored
Measures of reliability 
reliability(keys = new_data %>% select(weighted_occ, weighted_mean_income, 
    weighted_degree, weighted_nw))
          omega_h alpha omega.tot  Uni  tau cong max.split min.split mean.r med.r n.items  CFI  ECV
All_items    0.56  0.75      0.81 0.95 0.95 0.99       0.8      0.71   0.43  0.41       4 0.97 0.87
reliability(new_data %>% select(subtestlist))
keys not specified, all items will be scored
Measures of reliability 
reliability(keys = new_data %>% select(subtestlist))
          omega_h alpha omega.tot  Uni  tau cong max.split min.split mean.r med.r n.items  CFI  ECV
All_items    0.71  0.94      0.95 0.92 0.93 0.98      0.96      0.85   0.55  0.56      12 0.86 0.85
corrforatt(new_data, r1=0.95, r2=0.81, 'IQ', 'ses')
[1] "Corrected corr: 0.635085625039677"
[1] "Upper lim: 0.655230749020211"
[1] "Lower lim: 0.614348432898653"

Given the correlation between IQ and SES is so high, for the relationship to be noncausal, the confounders in the relationship must have extremely strong relationships with intelligence to bias it. The most obvious one is parental SES - adjusting for it does decrease the observed relationship, but only by about 80%.

#zero order IQ ~ SES (g2 = IQ standardized to mean = 0 and SD = 1)
lr <- lm(data=new_data, ses ~ g2)
summary(lr)

Call:
lm(formula = ses ~ g2, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.2999 -0.5506 -0.1043  0.4225  6.5533 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.05145    0.01102   4.668 3.12e-06 ***
g2           0.55089    0.01089  50.573  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8311 on 5683 degrees of freedom
  (3299 observations deleted due to missingness)
Multiple R-squared:  0.3104,    Adjusted R-squared:  0.3102 
F-statistic:  2558 on 1 and 5683 DF,  p-value: < 2.2e-16
#zero order parental SES ~ SES
lr <- lm(data=new_data, ses ~ pses)
summary(lr)

Call:
lm(formula = ses ~ pses, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.9023 -0.6180 -0.1263  0.4488  6.3260 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.0004859  0.0106215   0.046    0.964    
pses        0.4379165  0.0108104  40.509   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9031 on 7228 degrees of freedom
  (1754 observations deleted due to missingness)
Multiple R-squared:  0.185, Adjusted R-squared:  0.1849 
F-statistic:  1641 on 1 and 7228 DF,  p-value: < 2.2e-16
#parental SES + IQ
lr <- lm(data=new_data, ses ~ pses + g2)
summary(lr)

Call:
lm(formula = ses ~ pses + g2, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.1434 -0.5340 -0.0971  0.4054  6.3898 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.03589    0.01075    3.34 0.000844 ***
pses         0.22793    0.01226   18.59  < 2e-16 ***
g2           0.44642    0.01199   37.23  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8074 on 5676 degrees of freedom
  (3305 observations deleted due to missingness)
Multiple R-squared:  0.3499,    Adjusted R-squared:  0.3496 
F-statistic:  1527 on 2 and 5676 DF,  p-value: < 2.2e-16
#parental SES + IQ + demographics (reference race is Asian)
lr <- lm(data=new_data, ses ~ g2 + race + Female + pses)
summary(lr)

Call:
lm(formula = ses ~ g2 + race + Female + pses, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.2751 -0.5131 -0.0918  0.4045  6.1967 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   0.63595    0.07943   8.006 1.43e-15 ***
g2            0.42177    0.01283  32.862  < 2e-16 ***
raceBlack    -0.59841    0.08277  -7.230 5.46e-13 ***
raceHispanic -0.41654    0.08334  -4.998 5.96e-07 ***
raceOther    -0.52113    0.11130  -4.682 2.91e-06 ***
raceWhite    -0.49289    0.07974  -6.181 6.81e-10 ***
Female       -0.22103    0.02116 -10.444  < 2e-16 ***
pses          0.23175    0.01260  18.395  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7951 on 5671 degrees of freedom
  (3305 observations deleted due to missingness)
Multiple R-squared:   0.37, Adjusted R-squared:  0.3692 
F-statistic: 475.8 on 7 and 5671 DF,  p-value: < 2.2e-16

Causality can also be tested with kin controls – using NLSYlinks. I find roughly the same association (B = .40)

library(NlsyLinks)
nl <- NlsyLinks::Links97PairExpanded
ndreduced <- new_data %>% select('X', 'IQ', 'ses')
temp <- full_join(ndreduced, nl, by = c("X" = "SubjectID_S2"))
temp2 <- temp %>% select('X', 'IQ', 'ses', 'R', 'SubjectID_S1')
temp2$SubjectID_S2 <- temp2$X
kin <- full_join(new_data, temp2, by = c("X" = "SubjectID_S1")) %>% filter(!is.na(SubjectID_S2)) %>% select('IQ.x', 'ses.x', 'IQ.y', 'ses.y', 'R', 'SubjectID_S2', 'X')

kin$sesdiff[!is.na(kin$ses.x) & !is.na(kin$ses.y)] <- kin$ses.y[!is.na(kin$ses.x) & !is.na(kin$ses.y)] - kin$ses.x[!is.na(kin$ses.x) & !is.na(kin$ses.y)]
kin$iqdiff[!is.na(kin$IQ.x) & !is.na(kin$IQ.y)] <- kin$IQ.y[!is.na(kin$IQ.x) & !is.na(kin$IQ.y)] - kin$IQ.x[!is.na(kin$IQ.x) & !is.na(kin$IQ.y)]

lr <- lm(data=kin, normalise(sesdiff) ~ normalise(iqdiff))
summary(lr)

Call:
lm(formula = normalise(sesdiff) ~ normalise(iqdiff), data = kin)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.6883 -0.5006 -0.0007  0.5050  3.8940 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -0.01181    0.02687  -0.439     0.66    
normalise(iqdiff)  0.40229    0.02653  15.165   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.901 on 1123 degrees of freedom
  (8221 observations deleted due to missingness)
Multiple R-squared:   0.17, Adjusted R-squared:  0.1692 
F-statistic:   230 on 1 and 1123 DF,  p-value: < 2.2e-16

Random notes:

correlation_matrix(subset(new_data, select = c(GS, AR, WK, PC, NO, CS, AI, SI, MK, MC, EI, AO)))
   GS          AR          WK          PC          NO          CS          AI          SI          MK          MC          EI          AO         
GS "NA"        "0.717 ***" "0.81 ***"  "0.732 ***" "0.465 ***" "0.42 ***"  "0.524 ***" "0.597 ***" "0.699 ***" "0.707 ***" "0.73 ***"  "0.562 ***"
AR "0.717 ***" "NA"        "0.717 ***" "0.741 ***" "0.606 ***" "0.504 ***" "0.445 ***" "0.488 ***" "0.803 ***" "0.682 ***" "0.637 ***" "0.631 ***"
WK "0.81 ***"  "0.717 ***" "NA"        "0.766 ***" "0.505 ***" "0.445 ***" "0.477 ***" "0.544 ***" "0.696 ***" "0.663 ***" "0.7 ***"   "0.536 ***"
PC "0.732 ***" "0.741 ***" "0.766 ***" "NA"        "0.543 ***" "0.522 ***" "0.414 ***" "0.436 ***" "0.732 ***" "0.661 ***" "0.648 ***" "0.616 ***"
NO "0.465 ***" "0.606 ***" "0.505 ***" "0.543 ***" "NA"        "0.571 ***" "0.216 ***" "0.213 ***" "0.665 ***" "0.403 ***" "0.4 ***"   "0.407 ***"
CS "0.42 ***"  "0.504 ***" "0.445 ***" "0.522 ***" "0.571 ***" "NA"        "0.191 ***" "0.206 ***" "0.554 ***" "0.397 ***" "0.361 ***" "0.462 ***"
AI "0.524 ***" "0.445 ***" "0.477 ***" "0.414 ***" "0.216 ***" "0.191 ***" "NA"        "0.589 ***" "0.363 ***" "0.535 ***" "0.566 ***" "0.335 ***"
SI "0.597 ***" "0.488 ***" "0.544 ***" "0.436 ***" "0.213 ***" "0.206 ***" "0.589 ***" "NA"        "0.404 ***" "0.611 ***" "0.619 ***" "0.398 ***"
MK "0.699 ***" "0.803 ***" "0.696 ***" "0.732 ***" "0.665 ***" "0.554 ***" "0.363 ***" "0.404 ***" "NA"        "0.64 ***"  "0.596 ***" "0.632 ***"
MC "0.707 ***" "0.682 ***" "0.663 ***" "0.661 ***" "0.403 ***" "0.397 ***" "0.535 ***" "0.611 ***" "0.64 ***"  "NA"        "0.683 ***" "0.632 ***"
EI "0.73 ***"  "0.637 ***" "0.7 ***"   "0.648 ***" "0.4 ***"   "0.361 ***" "0.566 ***" "0.619 ***" "0.596 ***" "0.683 ***" "NA"        "0.513 ***"
AO "0.562 ***" "0.631 ***" "0.536 ***" "0.616 ***" "0.407 ***" "0.462 ***" "0.335 ***" "0.398 ***" "0.632 ***" "0.632 ***" "0.513 ***" "NA"       
GG_denhist(new_data, 'ses')
Warning: Removed 1747 rows containing non-finite outside the scale range (`stat_bin()`).Warning: Removed 1747 rows containing non-finite outside the scale range (`stat_density()`).

lr <- lm(data=new_data, ses ~ rcs(IQ, 6))
lr2 <- lm(data=new_data, ses ~ IQ)
summary(lr)

Call:
lm(formula = ses ~ rcs(IQ, 6), data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.3844 -0.5415 -0.1028  0.4213  6.5849 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)      -2.918271   0.322454  -9.050  < 2e-16 ***
rcs(IQ, 6)IQ      0.028206   0.004135   6.821 9.99e-12 ***
rcs(IQ, 6)IQ'     0.022039   0.027666   0.797    0.426    
rcs(IQ, 6)IQ''   -0.089581   0.159116  -0.563    0.573    
rcs(IQ, 6)IQ'''   0.262472   0.375416   0.699    0.484    
rcs(IQ, 6)IQ'''' -0.399247   0.423308  -0.943    0.346    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8301 on 5679 degrees of freedom
  (3299 observations deleted due to missingness)
Multiple R-squared:  0.3126,    Adjusted R-squared:  0.312 
F-statistic: 516.6 on 5 and 5679 DF,  p-value: < 2.2e-16
summary(lr2)

Call:
lm(formula = ses ~ IQ, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.2999 -0.5506 -0.1043  0.4225  6.5533 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -3.6211743  0.0734583  -49.30   <2e-16 ***
IQ           0.0367263  0.0007262   50.57   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8311 on 5683 degrees of freedom
  (3299 observations deleted due to missingness)
Multiple R-squared:  0.3104,    Adjusted R-squared:  0.3102 
F-statistic:  2558 on 1 and 5683 DF,  p-value: < 2.2e-16
anova(lr, lr2)
Analysis of Variance Table

Model 1: ses ~ rcs(IQ, 6)
Model 2: ses ~ IQ
  Res.Df    RSS Df Sum of Sq      F    Pr(>F)    
1   5679 3912.8                                  
2   5683 3925.7 -4   -12.906 4.6829 0.0008985 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
lr <- lm(data=new_data, weighted_occ ~ rcs(IQ, 6))
lr2 <- lm(data=new_data, weighted_occ ~ IQ)
summary(lr)

Call:
lm(formula = weighted_occ ~ rcs(IQ, 6), data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.6554 -0.5686 -0.1272  0.4037 11.6442 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)      -2.333661   0.325612  -7.167 8.47e-13 ***
rcs(IQ, 6)IQ      0.022597   0.004169   5.421 6.14e-08 ***
rcs(IQ, 6)IQ'     0.008587   0.027403   0.313    0.754    
rcs(IQ, 6)IQ''   -0.012960   0.156218  -0.083    0.934    
rcs(IQ, 6)IQ'''   0.023765   0.367076   0.065    0.948    
rcs(IQ, 6)IQ''''  0.035494   0.414546   0.086    0.932    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8937 on 6867 degrees of freedom
  (2111 observations deleted due to missingness)
Multiple R-squared:  0.2063,    Adjusted R-squared:  0.2058 
F-statistic: 357.1 on 5 and 6867 DF,  p-value: < 2.2e-16
summary(lr2)

Call:
lm(formula = weighted_occ ~ IQ, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.4591 -0.5728 -0.1365  0.3972 11.6179 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -2.9819070  0.0732491  -40.71   <2e-16 ***
IQ           0.0301350  0.0007238   41.63   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8962 on 6871 degrees of freedom
  (2111 observations deleted due to missingness)
Multiple R-squared:  0.2014,    Adjusted R-squared:  0.2013 
F-statistic:  1733 on 1 and 6871 DF,  p-value: < 2.2e-16
anova(lr, lr2)
Analysis of Variance Table

Model 1: weighted_occ ~ rcs(IQ, 6)
Model 2: weighted_occ ~ IQ
  Res.Df    RSS Df Sum of Sq      F    Pr(>F)    
1   6867 5484.6                                  
2   6871 5518.4 -4   -33.817 10.585 1.504e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
lr <- lm(data=new_data, weighted_mean_income ~ rcs(IQ, 6))
lr2 <- lm(data=new_data, weighted_mean_income ~ IQ)
summary(lr)

Call:
lm(formula = weighted_mean_income ~ rcs(IQ, 6), data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.3353 -0.5749 -0.1548  0.3632  7.3451 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)      -2.776596   0.345574  -8.035  1.1e-15 ***
rcs(IQ, 6)IQ      0.029233   0.004422   6.611  4.1e-11 ***
rcs(IQ, 6)IQ'    -0.034379   0.028976  -1.186    0.235    
rcs(IQ, 6)IQ''    0.138421   0.164896   0.839    0.401    
rcs(IQ, 6)IQ'''  -0.164734   0.386764  -0.426    0.670    
rcs(IQ, 6)IQ''''  0.088057   0.436068   0.202    0.840    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9313 on 6720 degrees of freedom
  (2258 observations deleted due to missingness)
Multiple R-squared:  0.1336,    Adjusted R-squared:  0.133 
F-statistic: 207.2 on 5 and 6720 DF,  p-value: < 2.2e-16
summary(lr2)

Call:
lm(formula = weighted_mean_income ~ IQ, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.2069 -0.5738 -0.1542  0.3694  7.3192 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -2.4283238  0.0773067  -31.41   <2e-16 ***
IQ           0.0244714  0.0007626   32.09   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9314 on 6724 degrees of freedom
  (2258 observations deleted due to missingness)
Multiple R-squared:  0.1328,    Adjusted R-squared:  0.1327 
F-statistic:  1030 on 1 and 6724 DF,  p-value: < 2.2e-16
anova(lr, lr2)
Analysis of Variance Table

Model 1: weighted_mean_income ~ rcs(IQ, 6)
Model 2: weighted_mean_income ~ IQ
  Res.Df    RSS Df Sum of Sq      F Pr(>F)
1   6720 5828.0                           
2   6724 5833.4 -4   -5.3466 1.5412 0.1873
lr <- lm(data=new_data, weighted_degree ~ rcs(IQ, 6))
lr2 <- lm(data=new_data, weighted_degree ~ IQ)
summary(lr)

Call:
lm(formula = weighted_degree ~ rcs(IQ, 6), data = new_data)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.90593 -0.56529  0.00559  0.57516  2.83367 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)      -2.798243   0.293098  -9.547  < 2e-16 ***
rcs(IQ, 6)IQ      0.026233   0.003756   6.984 3.15e-12 ***
rcs(IQ, 6)IQ'     0.062558   0.024935   2.509   0.0121 *  
rcs(IQ, 6)IQ''   -0.307091   0.142919  -2.149   0.0317 *  
rcs(IQ, 6)IQ'''   0.648306   0.337196   1.923   0.0546 .  
rcs(IQ, 6)IQ'''' -0.745258   0.381496  -1.954   0.0508 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8191 on 6825 degrees of freedom
  (2153 observations deleted due to missingness)
Multiple R-squared:  0.3117,    Adjusted R-squared:  0.3112 
F-statistic: 618.2 on 5 and 6825 DF,  p-value: < 2.2e-16
summary(lr2)

Call:
lm(formula = weighted_degree ~ IQ, data = new_data)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.97677 -0.56357 -0.01213  0.58718  2.93416 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -3.5935964  0.0667844  -53.81   <2e-16 ***
IQ           0.0366114  0.0006607   55.41   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8197 on 6829 degrees of freedom
  (2153 observations deleted due to missingness)
Multiple R-squared:  0.3102,    Adjusted R-squared:  0.3101 
F-statistic:  3070 on 1 and 6829 DF,  p-value: < 2.2e-16
anova(lr, lr2)
Analysis of Variance Table

Model 1: weighted_degree ~ rcs(IQ, 6)
Model 2: weighted_degree ~ IQ
  Res.Df    RSS Df Sum of Sq      F   Pr(>F)   
1   6825 4578.6                                
2   6829 4588.8 -4   -10.249 3.8194 0.004187 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
lr <- lm(data=new_data, weighted_nw ~ rcs(IQ, 6))
lr2 <- lm(data=new_data, weighted_nw ~ IQ)
summary(lr)

Call:
lm(formula = weighted_nw ~ rcs(IQ, 6), data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.3100 -0.5217 -0.2644  0.2234 21.6795 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)   
(Intercept)      -1.044175   0.366523  -2.849   0.0044 **
rcs(IQ, 6)IQ      0.008985   0.004709   1.908   0.0564 . 
rcs(IQ, 6)IQ'     0.018696   0.031903   0.586   0.5579   
rcs(IQ, 6)IQ''    0.014569   0.184709   0.079   0.9371   
rcs(IQ, 6)IQ'''  -0.110611   0.438322  -0.252   0.8008   
rcs(IQ, 6)IQ'''' -0.017266   0.496242  -0.035   0.9722   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9852 on 5857 degrees of freedom
  (3121 observations deleted due to missingness)
Multiple R-squared:  0.07801,   Adjusted R-squared:  0.07722 
F-statistic: 99.11 on 5 and 5857 DF,  p-value: < 2.2e-16
summary(lr2)

Call:
lm(formula = weighted_nw ~ IQ, data = new_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.3886 -0.5493 -0.2566  0.2162 21.6864 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -1.8110157  0.0850398  -21.30   <2e-16 ***
IQ           0.0184757  0.0008432   21.91   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9861 on 5861 degrees of freedom
  (3121 observations deleted due to missingness)
Multiple R-squared:  0.07571,   Adjusted R-squared:  0.07555 
F-statistic: 480.1 on 1 and 5861 DF,  p-value: < 2.2e-16
anova(lr, lr2)
Analysis of Variance Table

Model 1: weighted_nw ~ rcs(IQ, 6)
Model 2: weighted_nw ~ IQ
  Res.Df    RSS Df Sum of Sq      F   Pr(>F)   
1   5857 5684.8                                
2   5861 5699.0 -4   -14.189 3.6547 0.005599 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
kin %>% group_by(R) %>% summarise(rses = cor.test(ses.x, ses.y)$estimate/0.81, cor.test(ses.x, ses.y)$parameter+2)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCkRlc2NyaXB0aW9uOgoKVGhlIGVmZmVjdCBvZiBpbnRlbGxpZ2VuY2Ugb24gc3VjY2VzcyBoYXMgYmVlbiBkZWJhdGVkIC0gc29tZSBhcmd1ZSB0aGF0IGl0J3MKb3ZlcnN0YXRlZCAoZS5nLiBHbGFkd2VsbCwgVGFsZWIpOyBvdGhlcnMgc2F5IGl0IGhhcyBhIGRlY2VudCBpbXBhY3QsIGJ1dCB0aGF0IG90aGVyIGZhY3RvcnMKbXVzdCBoYXZlIGEgbGFyZ2UgZWZmZWN0IGJhc2VkIG9uIHRoZSBmYWN0IHRoYXQgSVEgb25seSBleHBsYWlucyBzbyBtdWNoIHZhcmlhbmNlICgxMC0yMCUpIGluIAptb3N0IG91dGNvbWVzICh0aGlzIGlzIHRoZSBwb3NpdGlvbiBvZiBtb3N0IG1haW5zdHJlYW0gaW50ZWxsaWdlbmNlIHJlc2VhcmNoZXJzKS4gSSd2ZSBvbmx5IApzZWVuIEFSIEplbnNlbiBlbXBoYXNpemUgdGhlIGltcG9ydGFuY2Ugb2YgYWNjdXJhdGUgbWVhc3VyZW1lbnQgLS0gaXQgc2VlbXMgaGlzIGluc3RpbmN0cyAKd2VyZSBpbiB0aGUgcmlnaHQgcGxhY2UuCgpJbiB0aGlzIHBpZWNlIEkgc2hvdyB0aGF0IGl0IGlzIHRoZSB0aGlyZCBwZXJzcGVjdGl2ZSB0aGF0IGlzIGNvcnJlY3QsIGFuZCB0aGUgYXNzb2NpYXRpb24KYmV0d2VlbiBJUSBhbmQgc29jaW9lY29ub21pYyBzdGF0dXMgaXMgZGVmbGF0ZWQgYnkgdGhlIGZhY3QgdGhlcmUgaXMgbm8gcGVyZmVjdCBpbmRpY2F0b3IKb2YgU0VTLiBVc2luZyBhIGNvbXBvc2l0ZSBvZiBlZHVjYXRpb24sIG9jY3VwYXRpb24sIGFzc2V0cywgYW5kIGluY29tZSBlYXJuZWQgb3ZlciAyMCB5ZWFycywgSQpmaW5kIHRoYXQgYWJvdXQgNDAlIG9mIHRoZSBwZXJtYW5lbnQgdmFyaWF0aW9uIGluIHNvY2lvZWNvbm9taWMgc3RhdHVzIGNhbiBiZSBhY2NvdW50ZWQgZm9yCmJ5IGludGVsbGlnZW5jZSwgYW5kIHRoaXMgcmVkdWNlcyBieSBhYm91dCAyMCUgd2hlbiB0aGUgbm9uLWNhdXNhbCB2YXJpYXRpb24gaXMgcGFyc2VkIG91dC4KCk5vdGUgdGhhdCBhbGwgb2YgdGhlIGNhdXNhbCBleHBsYW5hdG9yeSB2YXJpYWJsZXMgb2YgU0VTIG11c3QgYWRkIHVwIHRvIDEwMCUgLSBpZiBpbnRlbGxpZ2VuY2Ugb25seQpleHBsYWlucyAxMC0yMCUgb2YgdGhlIHZhcmlhdGlvbiBpbiBzb2Npb2Vjb25vbWljIHN0YXR1cywgdGhlbiA4MC05MCUgb2YgdGhlIHZhcmlhdGlvbiByZW1haW5zLgpNb3N0IG9mIHRoZSByZXNlYXJjaCBJIGhhdmUgc2VlbiBvbiAiaW5oZXJpdGVkIHVuZmFpciBhZHZhbnRhZ2VzIiAoZS5nLiBhdHRyYWN0aXZlbmVzcywgaGVpZ2h0LAp2b2ljZSB0b25lLCBza2luIGNvbG9yKSBpcyB0aGF0IHRoZXNlIG1heSBoYXZlIGEgc21hbGwgY2F1c2FsIGVmZmVjdCwgYnV0IHRoYXQgdGhleSBleHBsYWluCnZlcnkgbGl0dGxlIHZhcmlhbmNlIGluIHN1Y2Nlc3MgLS0gc2F5IDUlLiBUaGlzIHN0aWxsIGxlYXZlcyA3NS04NSUgb2YgdGhlIHZhcmlhdGlvbiBleHBsYWluZWQgLS0gCndoaWNoIG11c3QgYmUgc29tZSBraW5kIG9mIHJhbmRvbSBsdWNrIG9yIHBlcnNvbmFsaXR5IHRyYWl0cy4gSSBkb24ndCBkZW55IHRoYXQgdGhlc2UgYXJlIHZhbHVhYmxlLApidXQgZ2l2ZW4gdGhlIGZpbmRpbmdzIGZyb20gdHdpbiBzdHVkaWVzLCBJIGZpbmQgaXQgaGFyZCB0byBiZWxpZXZlIHRoYXQgdGhlc2UgZmFjdG9ycyBjYW4gYWNjb3VudCAKZnVsbHkgZm9yIHRoZSA4MCUuCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMKREFUQSBDTEVBTklORwoKUHJlbGltaW5hcnkgZGF0YSBjbGVhbmluZzoKYGBge3J9CiNsb2FkaW5nIGRhdGEKc2V0d2QoJ34nKQpzZXR3ZCgnRG9jdW1lbnRzL3JzdHVmZi9wcmVkc3VjYycpCm5ld19kYXRhIDwtIHJlYWQuY3N2KCduZXdfZGF0YS5jc3YnKQoKI2RlbW9ncmFwaGljcwpuZXdfZGF0YSRGZW1hbGUgPC0gbmV3X2RhdGEkUjA1MzYzMDAtMQpuZXdfZGF0YSRyYWNlIDwtICdPdGhlcicKbmV3X2RhdGEkcmFjZVtuZXdfZGF0YSRSMDUzODcwMD09MV0gPC0gJ1doaXRlJwpuZXdfZGF0YSRyYWNlW25ld19kYXRhJFIwNTM4NjAwPT0xXSA8LSAnSGlzcGFuaWMnCm5ld19kYXRhJHJhY2VbbmV3X2RhdGEkUjA1Mzg3MDA9PTRdIDwtICdBc2lhbicKbmV3X2RhdGEkcmFjZVtuZXdfZGF0YSRSMDUzODcwMD09Ml0gPC0gJ0JsYWNrJwoKI2lxIGRhdGEKc3VidGVzdGxpc3QgPC0gYygnR1MnLCAnQVInLCAnV0snLCAnUEMnLCAnTk8nLCAnQ1MnLCAnQUknLCAnU0knLCAnTUsnLCAnTUMnLCAnRUknLCAnQU8nKQpuZXdfZGF0YSRHUyA9IE5BCm5ld19kYXRhJEFSID0gTkEKbmV3X2RhdGEkV0sgPSBOQQpuZXdfZGF0YSRQQyA9IE5BCm5ld19kYXRhJE5PID0gTkEKbmV3X2RhdGEkQ1MgPSBOQQpuZXdfZGF0YSRBSSA9IE5BCm5ld19kYXRhJFNJID0gTkEKbmV3X2RhdGEkTUsgPSBOQQpuZXdfZGF0YSRNQyA9IE5BCm5ld19kYXRhJEVJID0gTkEKbmV3X2RhdGEkQU8gPSBOQQoKbmV3X2RhdGEkdGVzdGRheSA9IG5ld19kYXRhJFI5NzA4NjAxKjEvMTIrbmV3X2RhdGEkUjk3MDg2MDIKCm5ld19kYXRhJHRlc3RkYXlbaXMubmEobmV3X2RhdGEkdGVzdGRheSldIDwtIDE5OTcuNjYxCgpuZXdfZGF0YSRiZGF0ZSA9IG5ld19kYXRhJFIwNTM2NDAyICsgbmV3X2RhdGEkUjA1MzY0MDEqMS8xMgoKbmV3X2RhdGEkYWdlYXQgPSBuZXdfZGF0YSR0ZXN0ZGF5LW5ld19kYXRhJGJkYXRlCmNvci50ZXN0KG5ld19kYXRhJFI5NzA1MzAwLCBuZXdfZGF0YSRhZ2VhdCkKaiA9IDAKZm9yKHN0ZXN0IGluIHN1YnRlc3RsaXN0KSB7CiAgcG9zc3RyaW5nID0gcGFzdGUoIlIiLCA5NzA1MjAwK2oqMTAwLCBzZXA9IiIpCiAgbmVnc3RyaW5nID0gcGFzdGUoIlIiLCA5NzA2NDAwK2oqMTAwLCBzZXA9IiIpCiAgc3Rjb2x1bW5pbmRleCA9IGdldGNvbGluZGV4KHN0ZXN0LCBuZXdfZGF0YSkKICBuZWdjb2x1bW5pbmRleCA9IGdldGNvbGluZGV4KG5lZ3N0cmluZywgbmV3X2RhdGEpCiAgcG9zY29sdW1uaW5kZXggPSBnZXRjb2xpbmRleChwb3NzdHJpbmcsIG5ld19kYXRhKQogIG5ld19kYXRhWywgc3Rjb2x1bW5pbmRleF0gPSBhcy5udW1lcmljKHBtYXgobmV3X2RhdGFbLCBuZWdjb2x1bW5pbmRleF0qLTEsIG5ld19kYXRhWywgcG9zY29sdW1uaW5kZXhdLCBuYS5ybT1UUlVFKSkKICBuZXdfZGF0YVssIHN0Y29sdW1uaW5kZXhdID0gbm9ybWFsaXNlKG5ld19kYXRhWywgc3Rjb2x1bW5pbmRleF0pCiAgbmV3X2RhdGFbLCBzdGNvbHVtbmluZGV4XVshaXMubmEobmV3X2RhdGFbLCBzdGNvbHVtbmluZGV4XSldIDwtIGFnZWNvcnJlY3Qoc3Rlc3QsIGFnZXZlY3Rvcm5hbWU9J2FnZWF0JywgZGF0YWZyID0gbmV3X2RhdGEsIG5vcm1hbGl6ZWl0PVQsIHNwbGluZXggPSA2KQogIGogPSBqKzEKfQpjb3IudGVzdChuZXdfZGF0YSRHUywgbmV3X2RhdGEkYWdlYXQpCmlxIDwtIHN1YnNldChuZXdfZGF0YSwgc2VsZWN0ID0gYyhHUywgQVIsIFdLLCBQQywgTk8sIENTLCBBSSwgU0ksIE1LLCBNQywgRUksIEFPKSkKbmV3X2RhdGEkZzIgPSBnZXRwYyhpcSwgbm9ybWFsaXplaXQ9VCwgZmlsbG1pc3Npbmc9RiwgZG9mYT1GKQpuZXdfZGF0YSRJUSA8LSBuZXdfZGF0YSRnMioxNSsxMDAKbmV3X2RhdGEkYWdlID0gMjAyMSAtIG5ld19kYXRhJGJkYXRlCmBgYAoKUGFyZW50YWwgU0VTIGRhdGEgY2xlYW5pbmcgKGFzc2V0cyArIGZhbWlseSBpbmNvbWUgKyBmYXRoZXIvbW90aGVyIGVkdWNhdGlvbikuClNldmVyZSBvdXRsaWVycyAoKzVTRCBhYm92ZSB0aGUgbWVhbikgd2VyZSByZW1vdmVkLgpgYGB7cn0KcG9sZGF0IDwtIHN1YnNldChuZXdfZGF0YSwgc2VsZWN0ID0gYyhSMTIwNDUwMCwgUjEyMDQ3MDAsIFIxMzAyNjAwLCBSMTMwMjcwMCkpCm5ld19kYXRhJHBzZXMgPSBnZXRwYyhwb2xkYXQsIG5vcm1hbGl6ZWl0PVQsIGZpbGxtaXNzaW5nPVQsIGRvZmE9RikKbmV3X2RhdGEkcHNlc1tuZXdfZGF0YSRwc2VzID4gNV0gPC0gTkEKCnBjYWxvbCA8LSBwY2EocG9sZGF0LCBuZmFjdG9ycz0xLCByb3RhdGU9Im5vbmUiLCBtaXNzaW5nPVRSVUUpCnByaW50KHBjYWxvbCkKCmBgYApDaGlsZCBpbmNvbWUsIG5ldCB3b3J0aCBhbmQgZWR1Y2F0aW9uIGRhdGEgY2xlYW5pbmcgLS0gcHJlLTIwMDAgZGF0YSBpcyBub3QgY29uc2lkZXJlZC4KRm9yIGEgZmV3IGNoaWxkcmVuLCBuZXQgd29ydGggYXQgMjAgd291bGQgaGF2ZSBiZWVuIG1lYXN1cmVkIGluIDE5OTkgLS0gSSBqdWRnZSB0aGlzIAphcyBhIG5vbmZhY3Rvciwgc28gSSBpbmNsdWRlZCB0aGlzIHZhcmlhYmxlLgpgYGB7cn0KY29sdW1uX21hcHBpbmdzIDwtIGMoImluYzIwMDAiLCBSNjgyNzUwMCA9ICJpbmMyMDAxIiwgUzEwNTU4MDAgPSAiaW5jMjAwMiIsIAogICAgICAgICAgICAgICAgICAgICBTMzEzNDYwMCA9ICJpbmMyMDAzIiwgUzQ3OTk2MDAgPSAiaW5jMjAwNCIsIFM2NTAxMDAwID0gImluYzIwMDUiLCAKICAgICAgICAgICAgICAgICAgICAgUzg0OTY1MDAgPSAiaW5jMjAwNiIsIFQwODg5ODAwID0gImluYzIwMDciLCBUMzAwMzAwMCA9ICJpbmMyMDA4IiwgCiAgICAgICAgICAgICAgICAgICAgIFQ0NDA2MDAwID0gImluYzIwMDkiLCBUNjA1NTUwMCA9ICJpbmMyMDEwIiwgVDc1NDU2MDAgPSAiaW5jMjAxMSIsIAogICAgICAgICAgICAgICAgICAgICBUODk3NjcwMCA9ICJpbmMyMDEzIiwgVTA5NTY5MDAgPSAiaW5jMjAxNSIsIFUyODU3MjAwID0gImluYzIwMTciLCAKICAgICAgICAgICAgICAgICAgICAgVTQyODIzMDAgPSAiaW5jMjAxOSIsIFU1NzUzNTAwID0gImluYzIwMjEiKQoKbmFtZXNfdG9fY2hhbmdlIDwtIG5hbWVzKG5ld19kYXRhKSAlaW4lIG5hbWVzKGNvbHVtbl9tYXBwaW5ncykgIApuYW1lcyhuZXdfZGF0YSlbbmFtZXNfdG9fY2hhbmdlXSA8LSBjb2x1bW5fbWFwcGluZ3NbbmFtZXMobmV3X2RhdGEpW25hbWVzX3RvX2NoYW5nZV1dCiMjIyMjIyMjIyMjIyMjCmRlZ3JlZV9tYXBwaW5ncyA8LSBjKAogIFMyMjYxMTAwID0gImRlZzIwMDMiLCBTNDAzMjYwMCA9ICJkZWcyMDA0IiwgUzU2MTMwMDAgPSAiZGVnMjAwNSIsCiAgUzc2ODMzMDAgPSAiZGVnMjAwNiIsIFQwMTQ5NjAwID0gImRlZzIwMDciLCBUMjEyMDAwMCA9ICJkZWcyMDA4IiwKICBUMzczMTEwMCA9ICJkZWcyMDA5IiwgVDUzMjIyMDAgPSAiZGVnMjAxMCIsIFQ2NzY3MTAwID0gImRlZzIwMTEiLAogIFQ4MjQxNDAwID0gImRlZzIwMTMiLCBVMDEzNzEwMCA9ICJkZWcyMDE1IiwgVTE5OTA3MDAgPSAiZGVnMjAxNyIsCiAgVTM1NzI3MDAgPSAiZGVnMjAxOSIsIFU1MDcyNjAwID0gImRlZzIwMjEiCikKCm5hbWVzX3RvX2NoYW5nZSA8LSBuYW1lcyhuZXdfZGF0YSkgJWluJSBuYW1lcyhkZWdyZWVfbWFwcGluZ3MpICAKbmFtZXMobmV3X2RhdGEpW25hbWVzX3RvX2NoYW5nZV0gPC0gZGVncmVlX21hcHBpbmdzW25hbWVzKG5ld19kYXRhKVtuYW1lc190b19jaGFuZ2VdXSAKCm5ld19kYXRhIDwtIGRhdGEuZnJhbWUobmV3X2RhdGEpCmRlZ19jb2x1bW5zIDwtIGMoImRlZzIwMDMiLCAiZGVnMjAwNCIsICJkZWcyMDA1IiwgCiAgICAgICAgICAgICAgICAgICAgImRlZzIwMDYiLCAiZGVnMjAwNyIsICJkZWcyMDA4IiwgImRlZzIwMDkiLCAiZGVnMjAxMCIsICJkZWcyMDExIiwgCiAgICAgICAgICAgICAgICAgICAgImRlZzIwMTMiLCAiZGVnMjAxNSIsICJkZWcyMDE3IiwgImRlZzIwMTkiLCAiZGVnMjAyMSIpCmV4aXN0aW5nX2RlZ19jb2x1bW5zIDwtIGRlZ19jb2x1bW5zW2RlZ19jb2x1bW5zICVpbiUgbmFtZXMobmV3X2RhdGEpXQp5ZWFybHlfYXZlcmFnZXMgPC0gc2FwcGx5KG5ld19kYXRhWywgZXhpc3RpbmdfZGVnX2NvbHVtbnNdLCBtZWFuLCBuYS5ybSA9IFRSVUUpCgpuZXRfd29ydGhfbWFwcGluZ3MgPC0gYygKICBaOTA0ODkwMCA9ICJud2FnZTIwIiwgCiAgWjkwNDkwMDAgPSAibndhZ2UyNSIsIAogIFo5MTIxOTAwID0gIm53YWdlMzAiLAogIFo5MTQxNDAwID0gIm53YWdlMzUiLAogIFo5MTY0NTAwID0gIm53YWdlNDAiCikKCm5hbWVzX3RvX2NoYW5nZSA8LSBuYW1lcyhuZXdfZGF0YSkgJWluJSBuYW1lcyhuZXRfd29ydGhfbWFwcGluZ3MpICAKbmFtZXMobmV3X2RhdGEpW25hbWVzX3RvX2NoYW5nZV0gPC0gbmV0X3dvcnRoX21hcHBpbmdzW25hbWVzKG5ld19kYXRhKVtuYW1lc190b19jaGFuZ2VdXSAKCmluY29tZV9jb2x1bW5zIDwtIGMoImluYzIwMDAiLCAiaW5jMjAwMSIsICJpbmMyMDAyIiwgImluYzIwMDMiLCAiaW5jMjAwNCIsICJpbmMyMDA1IiwgCiAgICAgICAgICAgICAgICAgICAgImluYzIwMDYiLCAiaW5jMjAwNyIsICJpbmMyMDA4IiwgImluYzIwMDkiLCAiaW5jMjAxMCIsICJpbmMyMDExIiwgCiAgICAgICAgICAgICAgICAgICAgImluYzIwMTMiLCAiaW5jMjAxNSIsICJpbmMyMDE3IiwgImluYzIwMTkiLCAiaW5jMjAyMSIpCgpleGlzdGluZ19pbmNvbWVfY29sdW1ucyA8LSBpbmNvbWVfY29sdW1uc1tpbmNvbWVfY29sdW1ucyAlaW4lIG5hbWVzKG5ld19kYXRhKV0KeWVhcmx5X2F2ZXJhZ2VzIDwtIHNhcHBseShuZXdfZGF0YVssIGV4aXN0aW5nX2luY29tZV9jb2x1bW5zXSwgbWVhbiwgbmEucm0gPSBUUlVFKQoKbmV3X2RhdGEkd2VpZ2h0ZWRfbWVhbl9pbmNvbWUgPC0gYXBwbHkobmV3X2RhdGFbLCBleGlzdGluZ19pbmNvbWVfY29sdW1uc10sIDEsIGZ1bmN0aW9uKHJvdykgewogIG5vbl9taXNzaW5nX2luZGljZXMgPC0gIWlzLm5hKHJvdykKICB0b3RhbF9pbmNvbWUgPC0gc3VtKHJvd1tub25fbWlzc2luZ19pbmRpY2VzXSwgbmEucm0gPSBUUlVFKQogIHRvdGFsX2F2ZXJhZ2UgPC0gc3VtKHllYXJseV9hdmVyYWdlc1tub25fbWlzc2luZ19pbmRpY2VzXSwgbmEucm0gPSBUUlVFKQogIHdlaWdodGVkX21lYW4gPC0gaWZlbHNlKHRvdGFsX2F2ZXJhZ2UgPiAwLCB0b3RhbF9pbmNvbWUgLyB0b3RhbF9hdmVyYWdlLCBOQSkKICByZXR1cm4od2VpZ2h0ZWRfbWVhbikKfSkKCmBgYAoKT2NjdXBhdGlvbiBkYXRhIGNsZWFuaW5nIC0tIHBsYWNlZCBzZXBhcmF0ZWx5LCBhcyB0aGUgb2NjdXBhdGlvbiBkYXRhIHdhcwptb3JlIGNvbXBsZXggdGhhbiB0aGUgb3RoZXIgZGF0YS4gT2NjdXBhdGlvbiByYW5rIHdhcyBhc3NpZ25lZCBiYXNlZCBvbiB0aGUgYXZlcmFnZSBpbmNvbWUKb2YgdGhlIGpvYi4gJ2pvYjIwMDBfMDEnIHJlZmVycyB0byB0aGUgcmVzcG9uZGVudCdzIGZpcnN0IGpvYiBpbiAyMDAwLCAnam9iMjAwN18wMycKcmVmZXJzIHRvIHRoZSByZXNwb25kZW50J3MgdGhpcmQgam9iIGluIDIwMDcuIApgYGB7cn0Kb2NjdXBhdGlvbl9tYXBwaW5ncyA8LSBjKAogIFMzNzEzMDAwID0gImpvYjIwMDBfMDEiLCBTMzcxMzEwMCA9ICJqb2IyMDAwXzAyIiwgUzM3MTMyMDAgPSAiam9iMjAwMF8wMyIsIFMzNzEzMzAwID0gImpvYjIwMDBfMDQiLAogIFMzNzI5MDAwID0gImpvYjIwMDFfMDEiLCBTMzcyOTEwMCA9ICJqb2IyMDAxXzAyIiwgUzM3MjkyMDAgPSAiam9iMjAwMV8wMyIsIFMzNzI5MzAwID0gImpvYjIwMDFfMDQiLAogIFMzNzU3MDAwID0gImpvYjIwMDNfMDEiLCBTMzc1NzEwMCA9ICJqb2IyMDAzXzAyIiwgUzM3NTcyMDAgPSAiam9iMjAwM18wMyIsIFMzNzU3MzAwID0gImpvYjIwMDNfMDQiLAogIFM1MDQxNzAwID0gImpvYjIwMDRfMDEiLCBTNTA0MTgwMCA9ICJqb2IyMDA0XzAyIiwgUzUwNDE5MDAgPSAiam9iMjAwNF8wMyIsIFM1MDQyMDAwID0gImpvYjIwMDRfMDQiLAogIFM4Njg5NzAwID0gImpvYjIwMDZfMDEiLCBTODY4OTgwMCA9ICJqb2IyMDA2XzAyIiwgUzg2ODk5MDAgPSAiam9iMjAwNl8wMyIsIFM4NjkwMDAwID0gImpvYjIwMDZfMDQiLAogIFQxMTA5NDAwID0gImpvYjIwMDdfMDEiLCBUMTEwOTUwMCA9ICJqb2IyMDA3XzAyIiwgVDExMDk2MDAgPSAiam9iMjAwN18wMyIsIFQxMTA5NzAwID0gImpvYjIwMDdfMDQiLAogIFQzMTg2OTAwID0gImpvYjIwMDhfMDEiLCBUMzE4NzAwMCA9ICJqb2IyMDA4XzAyIiwgVDMxODcxMDAgPSAiam9iMjAwOF8wMyIsIFQzMTg3MjAwID0gImpvYjIwMDhfMDQiLAogIFQ0NTk3ODAwID0gImpvYjIwMDlfMDEiLCBUNDU5NzkwMCA9ICJqb2IyMDA5XzAyIiwgVDQ1OTgwMDAgPSAiam9iMjAwOV8wMyIsIFQ0NTk4MTAwID0gImpvYjIwMDlfMDQiLAogIFQ2MjMxMDAwID0gImpvYjIwMTBfMDEiLCBUNjIzMTEwMCA9ICJqb2IyMDEwXzAyIiwgVDYyMzEyMDAgPSAiam9iMjAxMF8wMyIsIFQ2MjMxMzAwID0gImpvYjIwMTBfMDQiLAogIFQ3NzMyMTAwID0gImpvYjIwMTFfMDEiLCBUNzczMjIwMCA9ICJqb2IyMDExXzAyIiwgVDc3MzIzMDAgPSAiam9iMjAxMV8wMyIsIFQ3NzMyNDAwID0gImpvYjIwMTFfMDQiLAogIFQ5MTMzNTAwID0gImpvYjIwMTNfMDEiLCBUOTEzMzYwMCA9ICJqb2IyMDEzXzAyIiwgVDkxMzM3MDAgPSAiam9iMjAxM18wMyIsIFQ5MTMzODAwID0gImpvYjIwMTNfMDQiLAogIFUxMTI3MTAwID0gImpvYjIwMTVfMDEiLCBVMTEyNzIwMCA9ICJqb2IyMDE1XzAyIiwgVTExMjczMDAgPSAiam9iMjAxNV8wMyIsIFUxMTI3NDAwID0gImpvYjIwMTVfMDQiLAogIFUxNzE5NDAwID0gImpvYjIwMTdfMDEiLCBVMTcxOTUwMCA9ICJqb2IyMDE3XzAyIiwgVTE3MTk2MDAgPSAiam9iMjAxN18wMyIsIFUxNzE5NzAwID0gImpvYjIwMTdfMDQiLAogIFUzMzE1NzAwID0gImpvYjIwMTlfMDEiLCBVMzMxNTgwMCA9ICJqb2IyMDE5XzAyIiwgVTMzMTU5MDAgPSAiam9iMjAxOV8wMyIsIFUzMzE2MDAwID0gImpvYjIwMTlfMDQiLAogIFU0ODIwMjAwID0gImpvYjIwMjFfMDEiLCBVNDgyMDMwMCA9ICJqb2IyMDIxXzAyIiwgVTQ4MjA0MDAgPSAiam9iMjAyMV8wMyIsIFU0ODIwNTAwID0gImpvYjIwMjFfMDQiCikKCm5hbWVzKG5ld19kYXRhKSA8LSBpZmVsc2UobmFtZXMobmV3X2RhdGEpICVpbiUgbmFtZXMob2NjdXBhdGlvbl9tYXBwaW5ncyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgb2NjdXBhdGlvbl9tYXBwaW5nc1tuYW1lcyhuZXdfZGF0YSldLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzKG5ld19kYXRhKSkKCiMjIyMjIyMjIyMjIyMjIyMjIyMKbmV3X2RhdGEkdGVtcCA8LSBub3JtYWxpc2UobmV3X2RhdGEkd2VpZ2h0ZWRfbWVhbl9pbmNvbWUpCmpvYl9jb2x1bW5zIDwtIGdyZXAoImpvYiIsIG5hbWVzKG5ld19kYXRhKSwgdmFsdWUgPSBUUlVFKQpyYW5raW5ncyA8LSBsaXN0KCkKCiNyYW5raW5nIHRoZSB2YXJpYWJsZXMgYnkgaW5jb21lCmZvciAoam9iIGluIGpvYl9jb2x1bW5zKSB7CiAgbmV3X2RhdGEkdGVtcDIgPC0gbmV3X2RhdGFbW2pvYl1dCiAgcmFua2luZ3NbW2pvYl1dIDwtIG5ld19kYXRhICU+JSBncm91cF9ieSh0ZW1wMikgJT4lIHN1bW1hcmlzZShzdGF0dXMgPSBtZWFuKHRlbXAsIG5hLnJtPVQpKQp9CiNjb252ZXJ0aW5nIHRoaXMgdG8gYSBsaXN0CmF2ZXJhZ2Vfc3RhdHVzX2J5X3RlbXAyIDwtIGxpc3QoKQpmb3IgKGpvYl9uYW1lIGluIG5hbWVzKHJhbmtpbmdzKSkgewogIGF2ZXJhZ2Vfc3RhdHVzX2J5X3RlbXAyW1tqb2JfbmFtZV1dIDwtIGFnZ3JlZ2F0ZShzdGF0dXMgfiB0ZW1wMiwgZGF0YSA9IHJhbmtpbmdzW1tqb2JfbmFtZV1dLCBtZWFuKQp9CgojY29tYmluaW5nIHllYXJzIHRvIHJlZHVjZSB1bnJlbGlhYmlsaXR5IGluIHJhbmtpbmcKY29tYmluZWRfYXZlcmFnZXMgPC0gUmVkdWNlKGZ1bmN0aW9uKHgsIHkpIG1lcmdlKHgsIHksIGJ5ID0gInRlbXAyIiwgYWxsID0gVFJVRSksIGF2ZXJhZ2Vfc3RhdHVzX2J5X3RlbXAyKQpjb21iaW5lZF9hdmVyYWdlcyRzdW0gPC0gcm93TWVhbnMoY29tYmluZWRfYXZlcmFnZXNbLCAyOjYxXSwgbmEucm09VCkKcG9sIDwtIGNvbWJpbmVkX2F2ZXJhZ2VzICU+JSBzZWxlY3Qoc3VtLCB0ZW1wMikKCmBgYAoKVGhlbiwgd2VpZ2hlZCBhdmVyYWdlcyB3ZXJlIG1hZGUgZnJvbSB0aGUgeWVhcnMgYmV0d2VlbiAyMDAwLTIwMjEgYmFzZWQgb24gdGhlIGRhdGEuCkJlY2F1c2UgU0VTIG1lYXN1cmVkIGxhdGVyIGluIGxpZmUgaXMgaGlnaGVyIG9uIGF2ZXJhZ2UsIHRoZSB5ZWFycyBtdXN0IGJlIHdlaWdoZWQKYmFzZWQgb24gdGhpcyBiaWFzLiBUaGlzIG1ha2VzIHRoZSBzY2FsZSBhIGJpdCB1bmludGVycHJldGFibGUsIGJ1dCBpdCBoYXMgYQptb3JlIGFjY3VyYXRlIHJhbmsgb3JkZXIuIEZvciBvY2N1cGF0aW9uLCB0aGUgaGlnaGVzdCBzdGF0dXMKam9iIGFuIGluZGl2aWR1YWwgaGVsZCBpbiBhIGdpdmVuIHllYXIgd2FzIHVzZWQgYXMgdGhlIG1haW4gdmFyaWFibGUgd2l0aGluIHllYXJzLgpgYGB7cn0KIyMjIyNpbmNvbWUgZGF0YSBjbGVhbmluZwppbmNvbWVfY29sdW1ucyA8LSBjKCJpbmMyMDAwIiwgImluYzIwMDEiLCAiaW5jMjAwMiIsICJpbmMyMDAzIiwgImluYzIwMDQiLCAiaW5jMjAwNSIsIAogICAgICAgICAgICAgICAgICAgICJpbmMyMDA2IiwgImluYzIwMDciLCAiaW5jMjAwOCIsICJpbmMyMDA5IiwgImluYzIwMTAiLCAiaW5jMjAxMSIsIAogICAgICAgICAgICAgICAgICAgICJpbmMyMDEzIiwgImluYzIwMTUiLCAiaW5jMjAxNyIsICJpbmMyMDE5IiwgImluYzIwMjEiKQoKZXhpc3RpbmdfaW5jb21lX2NvbHVtbnMgPC0gaW5jb21lX2NvbHVtbnNbaW5jb21lX2NvbHVtbnMgJWluJSBuYW1lcyhuZXdfZGF0YSldCnllYXJseV9hdmVyYWdlcyA8LSBzYXBwbHkobmV3X2RhdGFbLCBleGlzdGluZ19pbmNvbWVfY29sdW1uc10sIG1lYW4sIG5hLnJtID0gVFJVRSkKCm5ld19kYXRhJHdlaWdodGVkX21lYW5faW5jb21lIDwtIGFwcGx5KG5ld19kYXRhWywgZXhpc3RpbmdfaW5jb21lX2NvbHVtbnNdLCAxLCBmdW5jdGlvbihyb3cpIHsKICBub25fbWlzc2luZ19pbmRpY2VzIDwtICFpcy5uYShyb3cpCiAgdG90YWxfaW5jb21lIDwtIHN1bShyb3dbbm9uX21pc3NpbmdfaW5kaWNlc10sIG5hLnJtID0gVFJVRSkKICB0b3RhbF9hdmVyYWdlIDwtIHN1bSh5ZWFybHlfYXZlcmFnZXNbbm9uX21pc3NpbmdfaW5kaWNlc10sIG5hLnJtID0gVFJVRSkKICB3ZWlnaHRlZF9tZWFuIDwtIGlmZWxzZSh0b3RhbF9hdmVyYWdlID4gMCwgdG90YWxfaW5jb21lIC8gdG90YWxfYXZlcmFnZSwgTkEpCiAgcmV0dXJuKHdlaWdodGVkX21lYW4pCn0pCgojIyMjI2VkdWNhdGlvbiBkYXRhIGNsZWFuaW5nCm5ld19kYXRhIDwtIGRhdGEuZnJhbWUobmV3X2RhdGEpCmRlZ19jb2x1bW5zIDwtIGMoImRlZzIwMDMiLCAiZGVnMjAwNCIsICJkZWcyMDA1IiwgCiAgICAgICAgICAgICAgICAgICAgImRlZzIwMDYiLCAiZGVnMjAwNyIsICJkZWcyMDA4IiwgImRlZzIwMDkiLCAiZGVnMjAxMCIsICJkZWcyMDExIiwgCiAgICAgICAgICAgICAgICAgICAgImRlZzIwMTMiLCAiZGVnMjAxNSIsICJkZWcyMDE3IiwgImRlZzIwMTkiLCAiZGVnMjAyMSIpCmV4aXN0aW5nX2RlZ19jb2x1bW5zIDwtIGRlZ19jb2x1bW5zW2RlZ19jb2x1bW5zICVpbiUgbmFtZXMobmV3X2RhdGEpXQp5ZWFybHlfYXZlcmFnZXMgPC0gc2FwcGx5KG5ld19kYXRhWywgZXhpc3RpbmdfZGVnX2NvbHVtbnNdLCBtZWFuLCBuYS5ybSA9IFRSVUUpCm5ld19kYXRhJHdlaWdodGVkX2RlZ3JlZSA8LSBhcHBseShuZXdfZGF0YVssIGV4aXN0aW5nX2RlZ19jb2x1bW5zXSwgMSwgZnVuY3Rpb24ocm93KSB7CiAgbm9uX21pc3NpbmdfaW5kaWNlcyA8LSAhaXMubmEocm93KQogIHRvdGFsX2RlZyA8LSBzdW0ocm93W25vbl9taXNzaW5nX2luZGljZXNdLCBuYS5ybSA9IFRSVUUpCiAgdG90YWxfYXZlcmFnZSA8LSBzdW0oeWVhcmx5X2F2ZXJhZ2VzW25vbl9taXNzaW5nX2luZGljZXNdLCBuYS5ybSA9IFRSVUUpCiAgd2VpZ2h0ZWRfbWVhbiA8LSBpZmVsc2UodG90YWxfZGVnID4gMCwgdG90YWxfZGVnIC8gdG90YWxfYXZlcmFnZSwgTkEpCiAgcmV0dXJuKHdlaWdodGVkX21lYW4pCn0pCgojIyMjIyMjIyNvY2N1cGF0aW9uIGRhdGEgY2xlYW5pbmcKZm9yIChqb2Jjb2wgaW4gam9iX2NvbHVtbnMpIHsKICB0ZW1wIDwtIHBhc3RlMChqb2Jjb2wsICdfcmFuaycpCiAgbmV3X2RhdGEkdGVtcF9rZXkgPC0gbmV3X2RhdGFbW2pvYmNvbF1dCiAgbmV3X2RhdGEgPC0gbmV3X2RhdGEgJT4lCiAgICBsZWZ0X2pvaW4ocG9sLCBieSA9IGMoInRlbXBfa2V5IiA9ICJ0ZW1wMiIpKSAlPiUKICAgIG11dGF0ZSghIXRlbXAgOj0gc3VtKSAlPiUKICAgIHNlbGVjdCgtc3VtKQogIG5ld19vci5uZXdfZGF0YWRhdGEgPC0gc2VsZWN0KG5ld19kYXRhLCAtdGVtcF9rZXkpCn0KCnllYXJzIDwtIHNlcSgyMDAwLCAyMDIxLCBieSA9IDEpIAoKZm9yICh5ZWFyIGluIHllYXJzKSB7CiAgcmFua19jb2xzIDwtIGdyZXAocGFzdGUwKCJqb2IiLCB5ZWFyLCAiX1xcZHsyfV9yYW5rIiksIG5hbWVzKG5ld19kYXRhKSwgdmFsdWUgPSBUUlVFKQoKICBpZiAobGVuZ3RoKHJhbmtfY29scykgPT0gNCkgewogICAgbmV3X2RhdGEgPC0gbmV3X2RhdGEgJT4lCiAgICAgIG11dGF0ZSghIXBhc3RlMCgiaGlnaGVzdF9yYW5rX2pvYl8iLCB5ZWFyKSA6PSBwbWF4KCEhIXJsYW5nOjpzeW1zKHJhbmtfY29scyksIG5hLnJtID0gVFJVRSkpCiAgfSBlbHNlIHsKICAgIHdhcm5pbmcocGFzdGUoIkV4cGVjdGVkIDQgam9iIHJhbmsgY29sdW1ucyBmb3IgeWVhciIsIHllYXIsICJidXQgZm91bmQiLCBsZW5ndGgocmFua19jb2xzKSkpCiAgfQp9CgpuZXdfZGF0YSA8LSBkYXRhLmZyYW1lKG5ld19kYXRhKQoKZm9yKGNvbCBpbiBvY2NfY29sdW1ucykgewogIG5ld19kYXRhW1tjb2xdXSA8LSBuZXdfZGF0YVtbY29sXV0gLSBtaW4obmV3X2RhdGFbW2NvbF1dLCBuYS5ybT1UKQp9CgpvY2NfY29sdW1ucyA8LSBncmVwKHBhc3RlMCgiaGlnaGVzdCIpLCBuYW1lcyhuZXdfZGF0YSksIHZhbHVlID0gVFJVRSkKZXhpc3Rpbmdfb2NjX2NvbHVtbnMgPC0gb2NjX2NvbHVtbnNbb2NjX2NvbHVtbnMgJWluJSBuYW1lcyhuZXdfZGF0YSldCnllYXJseV9hdmVyYWdlcyA8LSBzYXBwbHkobmV3X2RhdGFbLCBleGlzdGluZ19vY2NfY29sdW1uc10sIG1lYW4sIG5hLnJtID0gVFJVRSkKCm5ld19kYXRhJHdlaWdodGVkX29jYyA8LSBhcHBseShuZXdfZGF0YVssIGV4aXN0aW5nX29jY19jb2x1bW5zXSwgMSwgZnVuY3Rpb24ocm93KSB7CiAgbm9uX21pc3NpbmdfaW5kaWNlcyA8LSAhaXMubmEocm93KQogIHRvdGFsX29jYyA8LSBzdW0ocm93W25vbl9taXNzaW5nX2luZGljZXNdLCBuYS5ybSA9IFRSVUUpCiAgdG90YWxfYXZlcmFnZSA8LSBzdW0oeWVhcmx5X2F2ZXJhZ2VzW25vbl9taXNzaW5nX2luZGljZXNdLCBuYS5ybSA9IFRSVUUpCiAgd2VpZ2h0ZWRfbWVhbiA8LSBpZmVsc2UodG90YWxfb2NjID4gMCwgdG90YWxfb2NjIC8gdG90YWxfYXZlcmFnZSwgTkEpCiAgcmV0dXJuKHdlaWdodGVkX21lYW4pCn0pCgpuZXdfZGF0YSA8LSBkYXRhLmZyYW1lKG5ld19kYXRhKQoKZm9yKGNvbCBpbiBvY2NfY29sdW1ucykgewogIG5ld19kYXRhW1tjb2xdXSA8LSBuZXdfZGF0YVtbY29sXV0gLSBtaW4obmV3X2RhdGFbW2NvbF1dLCBuYS5ybT1UKQp9CgojbmV0IHdvcnRoIGRhdGEgY2xlYW5pbmcKbndfY29sdW1ucyA8LSBuZXRfd29ydGhfbWFwcGluZ3MgPC0gYygibndhZ2UyMCIsICJud2FnZTI1IiwgIm53YWdlMzAiLCJud2FnZTM1IiwibndhZ2U0MCIpCmV4aXN0aW5nX253X2NvbHVtbnMgPC0gbndfY29sdW1uc1tud19jb2x1bW5zICVpbiUgbmFtZXMobmV3X2RhdGEpXQp5ZWFybHlfYXZlcmFnZXMgPC0gc2FwcGx5KG5ld19kYXRhWywgZXhpc3RpbmdfbndfY29sdW1uc10sIG1lYW4sIG5hLnJtID0gVFJVRSkKCm5ld19kYXRhJHdlaWdodGVkX253IDwtIGFwcGx5KG5ld19kYXRhWywgZXhpc3RpbmdfbndfY29sdW1uc10sIDEsIGZ1bmN0aW9uKHJvdykgewogIG5vbl9taXNzaW5nX2luZGljZXMgPC0gIWlzLm5hKHJvdykKICB0b3RhbF9vY2MgPC0gc3VtKHJvd1tub25fbWlzc2luZ19pbmRpY2VzXSwgbmEucm0gPSBUUlVFKQogIHRvdGFsX2F2ZXJhZ2UgPC0gc3VtKHllYXJseV9hdmVyYWdlc1tub25fbWlzc2luZ19pbmRpY2VzXSwgbmEucm0gPSBUUlVFKQogIHdlaWdodGVkX21lYW4gPC0gaWZlbHNlKHRvdGFsX29jYyA+IDAsIHRvdGFsX29jYyAvIHRvdGFsX2F2ZXJhZ2UsIE5BKQogIHJldHVybih3ZWlnaHRlZF9tZWFuKQp9KQpgYGAKCkFnZSBhZGp1c3RtZW50cyB3ZXJlIG1hZGUsIGFzIG5vdCBldmVyeWJvZHkgd2FzIG9mIHRoZSBzYW1lIGFnZS4KYGBge3J9Cm5ld19kYXRhJHdlaWdodGVkX29jY1shaXMubmEobmV3X2RhdGEkd2VpZ2h0ZWRfb2NjKV0gPC0gYWdlY29ycmVjdCgnd2VpZ2h0ZWRfb2NjJywgYWdldmVjdG9ybmFtZT0nYWdlJywgZGF0YWZyID0gbmV3X2RhdGEsIG5vcm1hbGl6ZWl0PVQsIHNwbGluZXggPSA2KQoKbmV3X2RhdGEkd2VpZ2h0ZWRfbWVhbl9pbmNvbWVbIWlzLm5hKG5ld19kYXRhJHdlaWdodGVkX21lYW5faW5jb21lKV0gPC0gYWdlY29ycmVjdCgnd2VpZ2h0ZWRfbWVhbl9pbmNvbWUnLCBhZ2V2ZWN0b3JuYW1lPSdhZ2UnLCBkYXRhZnIgPSBuZXdfZGF0YSwgbm9ybWFsaXplaXQ9VCwgc3BsaW5leCA9IDYpCgpuZXdfZGF0YSR3ZWlnaHRlZF9kZWdyZWVbIWlzLm5hKG5ld19kYXRhJHdlaWdodGVkX2RlZ3JlZSldIDwtIGFnZWNvcnJlY3QoJ3dlaWdodGVkX2RlZ3JlZScsIGFnZXZlY3Rvcm5hbWU9J2FnZScsIGRhdGFmciA9IG5ld19kYXRhLCBub3JtYWxpemVpdD1ULCBzcGxpbmV4ID0gNikKCm5ld19kYXRhJHdlaWdodGVkX253WyFpcy5uYShuZXdfZGF0YSR3ZWlnaHRlZF9udyldIDwtIGFnZWNvcnJlY3QoJ3dlaWdodGVkX253JywgYWdldmVjdG9ybmFtZT0nYWdlJywgZGF0YWZyID0gbmV3X2RhdGEsIG5vcm1hbGl6ZWl0PVQsIHNwbGluZXggPSA2KQoKYGBgCgpGaW5hbGx5LCB0aGUgaG9seSBncmFpbDogc2VzIC0tIGEgY29tcG9zaXRlIG9mIHNlbWktcGVybWFuZW50IGFzc2V0cywgZWR1Y2F0aW9uLCBpbmNvbWUsIGFuZCBvY2N1cGF0aW9uYWwgc3RhdHVzLgpgYGB7cn0KbmV3X2RhdGEkc2VzIDwtIGdldHBjKG5ld19kYXRhICU+JSBzZWxlY3Qod2VpZ2h0ZWRfb2NjLCB3ZWlnaHRlZF9tZWFuX2luY29tZSwgd2VpZ2h0ZWRfZGVncmVlLCB3ZWlnaHRlZF9udyksIG5vcm1hbGl6ZWl0ID0gVCwgZmlsbG1pc3Npbmc9RiwgZG9mYT1GKQpgYGAKCiMjIyMjIyMjIyMjIyMjIyMjClJFU1VMVFM6CgpUaGUgY29ycmVsYXRpb24gbWF0cml4IG9mIHRoZSBtYWluIGluZGljYXRvcnM6IHBhcmVudGFsIHNvY2lvZWNvbm9taWMgc3RhdHVzIChwc2VzKSwgY2hpbGQgCnNvY2lvZWNvbm9taWMgc3RhdHVzIChzZXMpLCBjaGlsZCBJUSAoSVEpLCBzZW1pLXBlcm1hbmVudCBvY2N1cGF0aW9uYWwgc3RhdHVzICh3ZWlnaHRlZF9vY2MpLApzZW1pLXBlcm1hbmVudCBpbmNvbWUgKHdlaWdodGVkX21lYW5faW5jb21lKSwgc2VtaS1wZXJtYW5lbnQgZWR1Y2F0aW9uICh3ZWlnaHRlZF9kZWdyZWUpLAphbmQgc2VtaS1wZXJtYW5lbnQgYXNzZXRzICh3ZWlnaHRlZF9udykuCmBgYHtyfQpjb3JyZWxhdGlvbl9tYXRyaXgobmV3X2RhdGEgJT4lIHNlbGVjdCh3ZWlnaHRlZF9vY2MsIHdlaWdodGVkX21lYW5faW5jb21lLCB3ZWlnaHRlZF9kZWdyZWUsIHdlaWdodGVkX253LCBzZXMsIHBzZXMsIElRKSkKYGBgCgpUaGUgc2NhdHRlcnBsb3RzIGZvciB0aGUgc2VtaS1wZXJtYW5lbnQgdmFyaWFibGVzLgpOb3RlIHRoZSBsaW5lYXIgYXNzb2NpYXRpb24gYmV0d2VlbiBJUSBhbmQgZXZlcnkgdmFyaWFibGUgd2l0aCAKdGhlIGV4Y2VwdGlvbiBvZiBwYXJlbnRhbCBTRVMuCmBgYHtyfQpHR19zY2F0dGVyKG5ld19kYXRhLCAnSVEnLCAnc2VzJykgKyBnZW9tX3Ntb290aCgpCkdHX3NjYXR0ZXIobmV3X2RhdGEsICdwc2VzJywgJ0lRJykgKyBnZW9tX3Ntb290aCgpCkdHX3NjYXR0ZXIobmV3X2RhdGEsICdJUScsICd3ZWlnaHRlZF9vY2MnKSArIGdlb21fc21vb3RoKCkKR0dfc2NhdHRlcihuZXdfZGF0YSwgJ0lRJywgJ3dlaWdodGVkX21lYW5faW5jb21lJykgKyBnZW9tX3Ntb290aCgpCkdHX3NjYXR0ZXIobmV3X2RhdGEsICdJUScsICd3ZWlnaHRlZF9kZWdyZWUnKSArIGdlb21fc21vb3RoKCkKR0dfc2NhdHRlcihuZXdfZGF0YSwgJ0lRJywgJ3dlaWdodGVkX253JykgKyBnZW9tX3Ntb290aCgpCmBgYAoKQ29tcGFyZSB0aGlzIHRvIHRoZSBvbmVzIGdlbmVyYXRlZCBmb3IganVzdCB0aGUgeWVhciAyMDEwOgpgYGB7cn0KbmV3X2RhdGEkc2VzMjAxMCA8LSBnZXRwYyhuZXdfZGF0YSAlPiUgc2VsZWN0KGhpZ2hlc3RfcmFua19qb2JfMjAxMCwgaW5jMjAxMCwgZGVnMjAxMCwgbndhZ2UzMCkpCgpHR19zY2F0dGVyKG5ld19kYXRhLCAnSVEnLCAnc2VzMjAxMCcpICsgZ2VvbV9zbW9vdGgoKQpHR19zY2F0dGVyKG5ld19kYXRhLCAnSVEnLCAnaGlnaGVzdF9yYW5rX2pvYl8yMDEwJykgKyBnZW9tX3Ntb290aCgpCkdHX3NjYXR0ZXIobmV3X2RhdGEsICdJUScsICdpbmMyMDEwJykgKyBnZW9tX3Ntb290aCgpCkdHX3NjYXR0ZXIobmV3X2RhdGEsICdJUScsICdkZWcyMDEwJykgKyBnZW9tX3Ntb290aCgpCkdHX3NjYXR0ZXIobmV3X2RhdGEsICdJUScsICdud2FnZTMwJykgKyBnZW9tX3Ntb290aCgpCmBgYAoKVGhlcmUgYXJlIHNldmVyYWwgd2F5cyB0byBlc3RpbWF0ZSB0aGUgdHJ1ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIElRIGFuZCBTRVM6Ci0gSmVuc2VuIHZlY3RvciBtZXRob2QKLSBMYXRlbnQgY29ycmVsYXRpb24KLSBBZGp1c3RpbmcgZm9yIG9ic2VydmVkIHVucmVsaWFiaWxpdHkuCgpKZW5zZW4gdmVjdG9yIG1ldGhvZCBlc3RpbWF0ZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gZyBhbmQgU0VTIHRvIGJlIC41NjoKYGBge3J9CnAgPC0gcGNhKG5ld19kYXRhICU+JSBzZWxlY3Qoc3VidGVzdGxpc3QpLCByb3RhdGU9J25vbmUnLCBuZmFjdG9ycz0xKQoKZGViaSA8LSBkYXRhLmZyYW1lKHYgPSByZXAoJycsIGxlbmd0aChzdWJ0ZXN0bGlzdCkpLCByID0gcmVwKDAsIGxlbmd0aChzdWJ0ZXN0bGlzdCkpKQpkZWJpJHYgPC0gTkEKaSA9IDEKZm9yKHZlYyBpbiBzdWJ0ZXN0bGlzdCkgewogIGRlYmkkdltpXSA8LSB2ZWMKICBkZWJpJHJbaV0gPC0gY29yLnRlc3QobmV3X2RhdGFbW3ZlY11dLCBuZXdfZGF0YSRzZXMpJGVzdGltYXRlCiAgaSA9IGkgKyAxCn0KZGViaSR2CmRlYmkkbCA8LSBwJGxvYWRpbmdzCkdHX3NjYXR0ZXIoZGY9ZGViaSwgeF92YXI9J2wnLCB5X3Zhcj0ncicsIGNhc2VfbmFtZXMgPSAndicpCgpsciA8LSBsbShkYXRhPWRlYmksIHIgfiBsKQpscgpgYGAKCkxhdGVudCBjb3JyZWxhdGlvbiBpcyAuNjQKYGBge3J9CmxhdDAgPC0gIgogICNMQVRFTlRTCiAgUyA9fiB3ZWlnaHRlZF9vY2MgKyB3ZWlnaHRlZF9tZWFuX2luY29tZSArIHdlaWdodGVkX2RlZ3JlZSArIHdlaWdodGVkX253CiAgRyA9fiBHUytBUitXSytQQytOTytDUytBSStTSStNSytNQytFSStBTwoKICBTIH5+IEcKIgpsYXRmaXQxIDwtIHNlbShtb2RlbCA9IGxhdDAsIGRhdGE9bmV3X2RhdGEpCnN1bW1hcnkobGF0Zml0MSwgZml0Lm1lYXN1cmVzPVQsIHN0YW5kYXJkaXplPVQpCgpgYGAKCkFkanVzdGluZyBmb3IgdGhlIG9ic2VydmVkIHVucmVsaWFiaWxpdHkgKG9tZWdhIHRvdGFsKSwgYSBjb3JyZWxhdGlvbiBvZiAuNjQgaXMgb2J0YWluZWQuCmBgYHtyfQpyZWxpYWJpbGl0eShuZXdfZGF0YSAlPiUgc2VsZWN0KHdlaWdodGVkX29jYywgd2VpZ2h0ZWRfbWVhbl9pbmNvbWUsIHdlaWdodGVkX2RlZ3JlZSwgd2VpZ2h0ZWRfbncpKQpyZWxpYWJpbGl0eShuZXdfZGF0YSAlPiUgc2VsZWN0KHN1YnRlc3RsaXN0KSkKCmNvcnJmb3JhdHQobmV3X2RhdGEsIHIxPTAuOTUsIHIyPTAuODEsICdJUScsICdzZXMnKQpgYGAKCkdpdmVuIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIElRIGFuZCBTRVMgaXMgc28gaGlnaCwgZm9yIHRoZSByZWxhdGlvbnNoaXAgdG8gYmUgbm9uY2F1c2FsLCAKdGhlIGNvbmZvdW5kZXJzIGluIHRoZSByZWxhdGlvbnNoaXAgbXVzdCBoYXZlIGV4dHJlbWVseSBzdHJvbmcgcmVsYXRpb25zaGlwcyB3aXRoIGludGVsbGlnZW5jZQp0byBiaWFzIGl0LiBUaGUgbW9zdCBvYnZpb3VzIG9uZSBpcyBwYXJlbnRhbCBTRVMgLSBhZGp1c3RpbmcgZm9yIGl0IGRvZXMgZGVjcmVhc2UgdGhlIG9ic2VydmVkCnJlbGF0aW9uc2hpcCwgYnV0IG9ubHkgYnkgYWJvdXQgODAlLgoKYGBge3J9CiN6ZXJvIG9yZGVyIElRIH4gU0VTIChnMiA9IElRIHN0YW5kYXJkaXplZCB0byBtZWFuID0gMCBhbmQgU0QgPSAxKQpsciA8LSBsbShkYXRhPW5ld19kYXRhLCBzZXMgfiBnMikKc3VtbWFyeShscikKCiN6ZXJvIG9yZGVyIHBhcmVudGFsIFNFUyB+IFNFUwpsciA8LSBsbShkYXRhPW5ld19kYXRhLCBzZXMgfiBwc2VzKQpzdW1tYXJ5KGxyKQoKI3BhcmVudGFsIFNFUyArIElRCmxyIDwtIGxtKGRhdGE9bmV3X2RhdGEsIHNlcyB+IHBzZXMgKyBnMikKc3VtbWFyeShscikKCiNwYXJlbnRhbCBTRVMgKyBJUSArIGRlbW9ncmFwaGljcyAocmVmZXJlbmNlIHJhY2UgaXMgQXNpYW4pCmxyIDwtIGxtKGRhdGE9bmV3X2RhdGEsIHNlcyB+IGcyICsgcmFjZSArIEZlbWFsZSArIHBzZXMpCnN1bW1hcnkobHIpCmBgYAoKQ2F1c2FsaXR5IGNhbiBhbHNvIGJlIHRlc3RlZCB3aXRoIGtpbiBjb250cm9scyAtLSB1c2luZyBOTFNZbGlua3MuIEkgZmluZCByb3VnaGx5IAp0aGUgc2FtZSBhc3NvY2lhdGlvbiAoQiA9IC40MCkKYGBge3J9CmxpYnJhcnkoTmxzeUxpbmtzKQpubCA8LSBObHN5TGlua3M6OkxpbmtzOTdQYWlyRXhwYW5kZWQKbmRyZWR1Y2VkIDwtIG5ld19kYXRhICU+JSBzZWxlY3QoJ1gnLCAnSVEnLCAnc2VzJykKdGVtcCA8LSBmdWxsX2pvaW4obmRyZWR1Y2VkLCBubCwgYnkgPSBjKCJYIiA9ICJTdWJqZWN0SURfUzIiKSkKdGVtcDIgPC0gdGVtcCAlPiUgc2VsZWN0KCdYJywgJ0lRJywgJ3NlcycsICdSJywgJ1N1YmplY3RJRF9TMScpCnRlbXAyJFN1YmplY3RJRF9TMiA8LSB0ZW1wMiRYCmtpbiA8LSBmdWxsX2pvaW4obmV3X2RhdGEsIHRlbXAyLCBieSA9IGMoIlgiID0gIlN1YmplY3RJRF9TMSIpKSAlPiUgZmlsdGVyKCFpcy5uYShTdWJqZWN0SURfUzIpKSAlPiUgc2VsZWN0KCdJUS54JywgJ3Nlcy54JywgJ0lRLnknLCAnc2VzLnknLCAnUicsICdTdWJqZWN0SURfUzInLCAnWCcpCgpraW4kc2VzZGlmZlshaXMubmEoa2luJHNlcy54KSAmICFpcy5uYShraW4kc2VzLnkpXSA8LSBraW4kc2VzLnlbIWlzLm5hKGtpbiRzZXMueCkgJiAhaXMubmEoa2luJHNlcy55KV0gLSBraW4kc2VzLnhbIWlzLm5hKGtpbiRzZXMueCkgJiAhaXMubmEoa2luJHNlcy55KV0Ka2luJGlxZGlmZlshaXMubmEoa2luJElRLngpICYgIWlzLm5hKGtpbiRJUS55KV0gPC0ga2luJElRLnlbIWlzLm5hKGtpbiRJUS54KSAmICFpcy5uYShraW4kSVEueSldIC0ga2luJElRLnhbIWlzLm5hKGtpbiRJUS54KSAmICFpcy5uYShraW4kSVEueSldCgpsciA8LSBsbShkYXRhPWtpbiwgbm9ybWFsaXNlKHNlc2RpZmYpIH4gbm9ybWFsaXNlKGlxZGlmZikpCnN1bW1hcnkobHIpCgoKYGBgCgpSYW5kb20gbm90ZXM6CmBgYHtyfQpjb3JyZWxhdGlvbl9tYXRyaXgoc3Vic2V0KG5ld19kYXRhLCBzZWxlY3QgPSBjKEdTLCBBUiwgV0ssIFBDLCBOTywgQ1MsIEFJLCBTSSwgTUssIE1DLCBFSSwgQU8pKSkKYGBgCgpgYGB7cn0KR0dfZGVuaGlzdChuZXdfZGF0YSwgJ3NlcycpCmBgYAoKYGBge3J9CmxyIDwtIGxtKGRhdGE9bmV3X2RhdGEsIHNlcyB+IHJjcyhJUSwgNikpCmxyMiA8LSBsbShkYXRhPW5ld19kYXRhLCBzZXMgfiBJUSkKc3VtbWFyeShscikKc3VtbWFyeShscjIpCmFub3ZhKGxyLCBscjIpCgpsciA8LSBsbShkYXRhPW5ld19kYXRhLCB3ZWlnaHRlZF9vY2MgfiByY3MoSVEsIDYpKQpscjIgPC0gbG0oZGF0YT1uZXdfZGF0YSwgd2VpZ2h0ZWRfb2NjIH4gSVEpCnN1bW1hcnkobHIpCnN1bW1hcnkobHIyKQphbm92YShsciwgbHIyKQoKbHIgPC0gbG0oZGF0YT1uZXdfZGF0YSwgd2VpZ2h0ZWRfbWVhbl9pbmNvbWUgfiByY3MoSVEsIDYpKQpscjIgPC0gbG0oZGF0YT1uZXdfZGF0YSwgd2VpZ2h0ZWRfbWVhbl9pbmNvbWUgfiBJUSkKc3VtbWFyeShscikKc3VtbWFyeShscjIpCmFub3ZhKGxyLCBscjIpCgpsciA8LSBsbShkYXRhPW5ld19kYXRhLCB3ZWlnaHRlZF9kZWdyZWUgfiByY3MoSVEsIDYpKQpscjIgPC0gbG0oZGF0YT1uZXdfZGF0YSwgd2VpZ2h0ZWRfZGVncmVlIH4gSVEpCnN1bW1hcnkobHIpCnN1bW1hcnkobHIyKQphbm92YShsciwgbHIyKQoKbHIgPC0gbG0oZGF0YT1uZXdfZGF0YSwgd2VpZ2h0ZWRfbncgfiByY3MoSVEsIDYpKQpscjIgPC0gbG0oZGF0YT1uZXdfZGF0YSwgd2VpZ2h0ZWRfbncgfiBJUSkKc3VtbWFyeShscikKc3VtbWFyeShscjIpCmFub3ZhKGxyLCBscjIpCmBgYAoKYGBge3J9CmtpbiAlPiUgZ3JvdXBfYnkoUikgJT4lIHN1bW1hcmlzZShyc2VzID0gY29yLnRlc3Qoc2VzLngsIHNlcy55KSRlc3RpbWF0ZS8wLjgxLCBjb3IudGVzdChzZXMueCwgc2VzLnkpJHBhcmFtZXRlcisyKQpgYGA=