Start Date: 23 August 2025

Report Date: 31 August 2025

Source: Psi Chi R

knitr::opts_chunk$set(echo = T,message = F,warning = F)

#setwd("C:/Users/alanh/Documents/R/Psi_Chi_R")

rm(list=ls())

setwd("~/R/Psi_Chi_R")

library(tidyverse)

#commenting out code but not for text
if (FALSE) {

}

#total for bottom row

sum_rows = function(x) {
  x = as.data.frame(x) # Ensure x is a data frame
  sums = sapply(x,function(col) if (is.numeric(col)) sum(col, na.rm = T) else NA)
  sums = as.data.frame(t(sums)) # Convert to data frame
  names(sums) = names(x) # Retain column names
  rbind(x, sums) # Bind the sum row to the original data frame
}

# right column for total
sum_cols = function(x) {
  x$Total = rowSums(x[sapply(x, is.numeric)], na.rm = T)
  x
}

options(scipen=999) # disable scientific notation

#dollar format function
dollars = function(x) {
  paste0("$",format(x,big.mark= ",",scientific=F))
}

desc_stats = function(x){
  c(min = min(x,na.rm=T),
    median = median(x,na.rm=T),
    max = max(x,na.rm=T),
    mean = mean(x,na.rm=T),
    sd = sd(x,na.rm=T))
}

Clean and EDA

data=read_csv('data.csv',show_col_types = F)

# data = readxl::read_excel('C:/Users/alanh/Downloads/2025Apr_data.xlsx')

names(data) = make.names(colnames(data))

#SmartEDA::ExpData(data,type=2) %>% arrange(desc(Per_of_Missing))

#skimr::skim(data)

Data set:

Level 1: Preparing the data

Remove participants who are missing values for ‘Age’; Remove participants who are missing values for ‘Hoursdad’

Test your skills: Remove participants with missing values for ‘Age’ and ‘Hoursdad’

data1 = data |> 
  filter(!is.na(Age),!is.na(Hoursdad)) |> 
  arrange(Progress) |> 
  mutate(Progress = as.character(Progress))

if (FALSE) {
hist(data1$Age,prob=T,col='steelblue')
lines(density(data1$Age),lwd=2,col='darkred')

data1 |>
  ggplot(aes(x=Age))+
  geom_density()+
  theme_bw()
}

Level 2: Data Prep. and inspection

Create a variable called ‘PsyContF’ by summing together the following variables: DyadF1+ DyadF2+ DyadF3+ DyadF4+ DyadF5+ DyadF6+ DyadF7

dyad_df = data1 |> 
  mutate(Progress = as.character(Progress)) |> 
  select(Progress,DyadF1, DyadF2,DyadF3, DyadF4, DyadF5,DyadF6, DyadF7) |> 
  sum_cols() |> 
  rename(PsyContF = Total) |> 
  select(PsyContF,P1=Progress)

data2 = data1 |> 
  cbind(dyad_df) |> 
  select(PsyContF,everything())

sum(is.na(data2$PsyContF))
## [1] 0

Test your skills: Visualize outlier values for ‘PsyContF’.

boxplot(data2$PsyContF,main='PsyContF')

data2 |> 
  ggplot(aes(x=PsyContF))+
  geom_boxplot()

summary(data2$PsyContF)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00    7.00    9.00   11.57   15.00   35.00
#hist(data2$PsyContF)

Test your skills: If outliers are present, remove them.

data3 = data2 |> 
  filter(PsyContF < 25)

boxplot(data3$PsyContF)

Create a variable called FACEcomm (Family Communication) by adding together the following items FACES43 + FACES44 + FACES45 + FACES46 + FACES47 + FACES48 + FACES49 + FACES50 + FACES51 + FACES52.

face_df = data3 |> 
  select(FACES43, FACES44, FACES45, FACES46 ,FACES47 , FACES48 , FACES49 ,FACES50, FACES51 ,FACES52,Progress) |> 
  sum_cols() |> 
  rename(FACEcomm = Total) |> 
  select(FACEcomm,P2=Progress)

data4 = data3 |> 
  #left_join(face_df,by=join_by(Progress==P2)) |> 
  cbind(face_df) |> 
  select(FACEcomm,PsyContF,P1,P2,everything()) |> 
  filter(FACEcomm >= 22)

sum(is.na(data4$FACEcomm))
## [1] 0
summary(data4$FACEcomm)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   23.00   33.00   38.00   37.86   42.00   50.00
boxplot(data4$FACEcomm)

Test your skills: Visualize the distribution of the FACEcomm

hist(data4$FACEcomm,probability = T,col='steelblue',main='Distro of Family Communication',xlab = 'FACEcomm')
lines(density(data4$FACEcomm),lwd=2,col='red')

Level 3: Descriptives

Find the mean, standard deviation, median, and range of ‘PsyContF’ and ‘FACEcomm’.

Test your skills: Find the mean, standard deviation, median, and range of ‘PsyContF’ and ‘FACEcomm’ in one step

level3_list = c('FACEcomm','PsyContF')

for (i in level3_list){
  x=desc_stats(data4[[i]])
  print(paste("Descriptives for",i))
  print(x)
}
## [1] "Descriptives for FACEcomm"
##       min    median       max      mean        sd 
## 23.000000 38.000000 50.000000 37.855556  6.549726 
## [1] "Descriptives for PsyContF"
##       min    median       max      mean        sd 
##  0.000000  9.000000 24.000000 10.915556  4.714285
for (i in level3_list){
  x=range(data4[[i]])
  print(paste('Range for',i))
  print(x)
}
## [1] "Range for FACEcomm"
## [1] 23 50
## [1] "Range for PsyContF"
## [1]  0 24

Level 4: Inferential + Other Statistics

Is there a correlation between ‘PsyContF’ and ‘FACEcomm?’ Note any relevant statistics.

Normality test and plot

for (i in level3_list){
  x=shapiro.test(data4[[i]])
  print(i)
  print(x)
}
## [1] "FACEcomm"
## 
##  Shapiro-Wilk normality test
## 
## data:  data4[[i]]
## W = 0.97644, p-value = 0.00000115
## 
## [1] "PsyContF"
## 
##  Shapiro-Wilk normality test
## 
## data:  data4[[i]]
## W = 0.86865, p-value < 0.00000000000000022
for (i in level3_list){
  hist(data4[[i]],main=i,xlab=i,probability = T,col='steelblue')
  lines(density(data4[[i]]),lwd=2,col='red')
}

#not normally distributed

Correlation

cor.test(data4$PsyContF,data4$FACEcomm,method = 'k')
## 
##  Kendall's rank correlation tau
## 
## data:  data4$PsyContF and data4$FACEcomm
## z = -5.2321, p-value = 0.0000001676
## alternative hypothesis: true tau is not equal to 0
## sample estimates:
##        tau 
## -0.1790498
if (FALSE) {
method_list = list('k','s','p')

for (i in method_list){
  x=cor.test(data4$PsyContF,data4$FACEcomm, method = i)
  print(x)
}
}

#according to Kendall's tau, there is a statistically significant weak negative correlation of -0.17 between FACEcomm and PsyContF.

Plot

data4 |> 
  ggplot(aes(x=PsyContF,y=FACEcomm))+
  geom_point()+
  theme_bw()+
  geom_smooth(method = 'lm')+
  labs(title='What in the Family Communication and PsyContF is Happening Here?')+
  theme(plot.title = element_text(hjust = .5))

LS0tDQp0aXRsZTogIlBzaSBDaGkgUiAtIEF1ZyAyMDI1Ig0KI2RhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGFsd2F5c19hbGxvd19odG1sOiB5ZXMNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIGFuY2hvcl9zZWN0aW9uczogVFJVRQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQpTdGFydCBEYXRlOiAyMyBBdWd1c3QgMjAyNQ0KDQpSZXBvcnQgRGF0ZTogYHIgZm9ybWF0KFN5cy5EYXRlKCksICclZCAlQiAlWScpYA0KDQpbU291cmNlOiBQc2kgQ2hpIFJdKGh0dHBzOi8vb3NmLmlvL2dyNTZzL3dpa2kvaG9tZS8pDQoNCmBgYHtyIHdhcm5pbmc9RixtZXNzYWdlPUZ9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFQsbWVzc2FnZSA9IEYsd2FybmluZyA9IEYpDQoNCiNzZXR3ZCgiQzovVXNlcnMvYWxhbmgvRG9jdW1lbnRzL1IvUHNpX0NoaV9SIikNCg0Kcm0obGlzdD1scygpKQ0KDQpzZXR3ZCgifi9SL1BzaV9DaGlfUiIpDQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQojY29tbWVudGluZyBvdXQgY29kZSBidXQgbm90IGZvciB0ZXh0DQppZiAoRkFMU0UpIHsNCg0KfQ0KDQojdG90YWwgZm9yIGJvdHRvbSByb3cNCg0Kc3VtX3Jvd3MgPSBmdW5jdGlvbih4KSB7DQogIHggPSBhcy5kYXRhLmZyYW1lKHgpICMgRW5zdXJlIHggaXMgYSBkYXRhIGZyYW1lDQogIHN1bXMgPSBzYXBwbHkoeCxmdW5jdGlvbihjb2wpIGlmIChpcy5udW1lcmljKGNvbCkpIHN1bShjb2wsIG5hLnJtID0gVCkgZWxzZSBOQSkNCiAgc3VtcyA9IGFzLmRhdGEuZnJhbWUodChzdW1zKSkgIyBDb252ZXJ0IHRvIGRhdGEgZnJhbWUNCiAgbmFtZXMoc3VtcykgPSBuYW1lcyh4KSAjIFJldGFpbiBjb2x1bW4gbmFtZXMNCiAgcmJpbmQoeCwgc3VtcykgIyBCaW5kIHRoZSBzdW0gcm93IHRvIHRoZSBvcmlnaW5hbCBkYXRhIGZyYW1lDQp9DQoNCiMgcmlnaHQgY29sdW1uIGZvciB0b3RhbA0Kc3VtX2NvbHMgPSBmdW5jdGlvbih4KSB7DQogIHgkVG90YWwgPSByb3dTdW1zKHhbc2FwcGx5KHgsIGlzLm51bWVyaWMpXSwgbmEucm0gPSBUKQ0KICB4DQp9DQoNCm9wdGlvbnMoc2NpcGVuPTk5OSkgIyBkaXNhYmxlIHNjaWVudGlmaWMgbm90YXRpb24NCg0KI2RvbGxhciBmb3JtYXQgZnVuY3Rpb24NCmRvbGxhcnMgPSBmdW5jdGlvbih4KSB7DQogIHBhc3RlMCgiJCIsZm9ybWF0KHgsYmlnLm1hcms9ICIsIixzY2llbnRpZmljPUYpKQ0KfQ0KDQpkZXNjX3N0YXRzID0gZnVuY3Rpb24oeCl7DQogIGMobWluID0gbWluKHgsbmEucm09VCksDQogICAgbWVkaWFuID0gbWVkaWFuKHgsbmEucm09VCksDQogICAgbWF4ID0gbWF4KHgsbmEucm09VCksDQogICAgbWVhbiA9IG1lYW4oeCxuYS5ybT1UKSwNCiAgICBzZCA9IHNkKHgsbmEucm09VCkpDQp9DQpgYGANCg0KIyMgQ2xlYW4gYW5kIEVEQQ0KDQpgYGB7cn0NCmRhdGE9cmVhZF9jc3YoJ2RhdGEuY3N2JyxzaG93X2NvbF90eXBlcyA9IEYpDQoNCiMgZGF0YSA9IHJlYWR4bDo6cmVhZF9leGNlbCgnQzovVXNlcnMvYWxhbmgvRG93bmxvYWRzLzIwMjVBcHJfZGF0YS54bHN4JykNCg0KbmFtZXMoZGF0YSkgPSBtYWtlLm5hbWVzKGNvbG5hbWVzKGRhdGEpKQ0KDQojU21hcnRFREE6OkV4cERhdGEoZGF0YSx0eXBlPTIpICU+JSBhcnJhbmdlKGRlc2MoUGVyX29mX01pc3NpbmcpKQ0KDQojc2tpbXI6OnNraW0oZGF0YSkNCmBgYA0KDQojIyMgRGF0YSBzZXQ6DQoNCmBgYHtyIGVjaG89Rn0NCmRvd25sb2FkdGhpczo6ZG93bmxvYWRfdGhpcyhkYXRhLG91dHB1dF9uYW1lID0gJ2RhdGFzZXQnLG91dHB1dF9leHRlbnNpb24gPSAnLnhsc3gnKQ0KYGBgDQoNCiMjIExldmVsIDE6IFByZXBhcmluZyB0aGUgZGF0YQ0KDQojIyMgUmVtb3ZlIHBhcnRpY2lwYW50cyB3aG8gYXJlIG1pc3NpbmcgdmFsdWVzIGZvciDigJhBZ2XigJk7IFJlbW92ZSBwYXJ0aWNpcGFudHMgd2hvIGFyZSBtaXNzaW5nIHZhbHVlcyBmb3Ig4oCYSG91cnNkYWTigJkNCg0KIyMjIFRlc3QgeW91ciBza2lsbHM6IFJlbW92ZSBwYXJ0aWNpcGFudHMgd2l0aCBtaXNzaW5nIHZhbHVlcyBmb3Ig4oCYQWdl4oCZIGFuZCDigJhIb3Vyc2RhZOKAmQ0KDQpgYGB7cn0NCmRhdGExID0gZGF0YSB8PiANCiAgZmlsdGVyKCFpcy5uYShBZ2UpLCFpcy5uYShIb3Vyc2RhZCkpIHw+IA0KICBhcnJhbmdlKFByb2dyZXNzKSB8PiANCiAgbXV0YXRlKFByb2dyZXNzID0gYXMuY2hhcmFjdGVyKFByb2dyZXNzKSkNCg0KaWYgKEZBTFNFKSB7DQpoaXN0KGRhdGExJEFnZSxwcm9iPVQsY29sPSdzdGVlbGJsdWUnKQ0KbGluZXMoZGVuc2l0eShkYXRhMSRBZ2UpLGx3ZD0yLGNvbD0nZGFya3JlZCcpDQoNCmRhdGExIHw+DQogIGdncGxvdChhZXMoeD1BZ2UpKSsNCiAgZ2VvbV9kZW5zaXR5KCkrDQogIHRoZW1lX2J3KCkNCn0NCmBgYA0KDQojIyBMZXZlbCAyOiBEYXRhIFByZXAuIGFuZCBpbnNwZWN0aW9uDQoNCiMjIyBDcmVhdGUgYSB2YXJpYWJsZSBjYWxsZWQg4oCYUHN5Q29udEbigJkgYnkgc3VtbWluZyB0b2dldGhlciB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczogRHlhZEYxKyBEeWFkRjIrIER5YWRGMysgRHlhZEY0KyBEeWFkRjUrIER5YWRGNisgRHlhZEY3DQoNCmBgYHtyfQ0KZHlhZF9kZiA9IGRhdGExIHw+IA0KICBtdXRhdGUoUHJvZ3Jlc3MgPSBhcy5jaGFyYWN0ZXIoUHJvZ3Jlc3MpKSB8PiANCiAgc2VsZWN0KFByb2dyZXNzLER5YWRGMSwgRHlhZEYyLER5YWRGMywgRHlhZEY0LCBEeWFkRjUsRHlhZEY2LCBEeWFkRjcpIHw+IA0KICBzdW1fY29scygpIHw+IA0KICByZW5hbWUoUHN5Q29udEYgPSBUb3RhbCkgfD4gDQogIHNlbGVjdChQc3lDb250RixQMT1Qcm9ncmVzcykNCg0KZGF0YTIgPSBkYXRhMSB8PiANCiAgY2JpbmQoZHlhZF9kZikgfD4gDQogIHNlbGVjdChQc3lDb250RixldmVyeXRoaW5nKCkpDQoNCnN1bShpcy5uYShkYXRhMiRQc3lDb250RikpDQpgYGANCg0KIyMjIFRlc3QgeW91ciBza2lsbHM6IFZpc3VhbGl6ZSBvdXRsaWVyIHZhbHVlcyBmb3Ig4oCYUHN5Q29udEbigJkuDQoNCmBgYHtyfQ0KYm94cGxvdChkYXRhMiRQc3lDb250RixtYWluPSdQc3lDb250RicpDQoNCmRhdGEyIHw+IA0KICBnZ3Bsb3QoYWVzKHg9UHN5Q29udEYpKSsNCiAgZ2VvbV9ib3hwbG90KCkNCg0Kc3VtbWFyeShkYXRhMiRQc3lDb250RikNCg0KI2hpc3QoZGF0YTIkUHN5Q29udEYpDQpgYGANCg0KIyMjIFRlc3QgeW91ciBza2lsbHM6IElmIG91dGxpZXJzIGFyZSBwcmVzZW50LCByZW1vdmUgdGhlbS4NCg0KYGBge3J9DQpkYXRhMyA9IGRhdGEyIHw+IA0KICBmaWx0ZXIoUHN5Q29udEYgPCAyNSkNCg0KYm94cGxvdChkYXRhMyRQc3lDb250RikNCmBgYA0KDQojIyMgQ3JlYXRlIGEgdmFyaWFibGUgY2FsbGVkIEZBQ0Vjb21tIChGYW1pbHkgQ29tbXVuaWNhdGlvbikgYnkgYWRkaW5nIHRvZ2V0aGVyIHRoZSBmb2xsb3dpbmcgaXRlbXMgRkFDRVM0MyArIEZBQ0VTNDQgKyBGQUNFUzQ1ICsgRkFDRVM0NiArIEZBQ0VTNDcgKyBGQUNFUzQ4ICsgRkFDRVM0OSArIEZBQ0VTNTAgKyBGQUNFUzUxICsgRkFDRVM1Mi4NCg0KYGBge3J9DQpmYWNlX2RmID0gZGF0YTMgfD4gDQogIHNlbGVjdChGQUNFUzQzLCBGQUNFUzQ0LCBGQUNFUzQ1LCBGQUNFUzQ2ICxGQUNFUzQ3ICwgRkFDRVM0OCAsIEZBQ0VTNDkgLEZBQ0VTNTAsIEZBQ0VTNTEgLEZBQ0VTNTIsUHJvZ3Jlc3MpIHw+IA0KICBzdW1fY29scygpIHw+IA0KICByZW5hbWUoRkFDRWNvbW0gPSBUb3RhbCkgfD4gDQogIHNlbGVjdChGQUNFY29tbSxQMj1Qcm9ncmVzcykNCg0KZGF0YTQgPSBkYXRhMyB8PiANCiAgI2xlZnRfam9pbihmYWNlX2RmLGJ5PWpvaW5fYnkoUHJvZ3Jlc3M9PVAyKSkgfD4gDQogIGNiaW5kKGZhY2VfZGYpIHw+IA0KICBzZWxlY3QoRkFDRWNvbW0sUHN5Q29udEYsUDEsUDIsZXZlcnl0aGluZygpKSB8PiANCiAgZmlsdGVyKEZBQ0Vjb21tID49IDIyKQ0KDQpzdW0oaXMubmEoZGF0YTQkRkFDRWNvbW0pKQ0KDQpzdW1tYXJ5KGRhdGE0JEZBQ0Vjb21tKQ0KDQpib3hwbG90KGRhdGE0JEZBQ0Vjb21tKQ0KYGBgDQoNClRlc3QgeW91ciBza2lsbHM6IFZpc3VhbGl6ZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBGQUNFY29tbQ0KDQpgYGB7cn0NCmhpc3QoZGF0YTQkRkFDRWNvbW0scHJvYmFiaWxpdHkgPSBULGNvbD0nc3RlZWxibHVlJyxtYWluPSdEaXN0cm8gb2YgRmFtaWx5IENvbW11bmljYXRpb24nLHhsYWIgPSAnRkFDRWNvbW0nKQ0KbGluZXMoZGVuc2l0eShkYXRhNCRGQUNFY29tbSksbHdkPTIsY29sPSdyZWQnKQ0KYGBgDQoNCiMjIExldmVsIDM6IERlc2NyaXB0aXZlcw0KDQojIyMgRmluZCB0aGUgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uLCBtZWRpYW4sIGFuZCByYW5nZSBvZiDigJhQc3lDb250RuKAmSBhbmQg4oCYRkFDRWNvbW3igJkuDQoNCiMjIyBUZXN0IHlvdXIgc2tpbGxzOiBGaW5kIHRoZSBtZWFuLCBzdGFuZGFyZCBkZXZpYXRpb24sIG1lZGlhbiwgYW5kIHJhbmdlIG9mIOKAmFBzeUNvbnRG4oCZIGFuZCDigJhGQUNFY29tbeKAmSBpbiBvbmUgc3RlcA0KDQpgYGB7cn0NCmxldmVsM19saXN0ID0gYygnRkFDRWNvbW0nLCdQc3lDb250RicpDQoNCmZvciAoaSBpbiBsZXZlbDNfbGlzdCl7DQogIHg9ZGVzY19zdGF0cyhkYXRhNFtbaV1dKQ0KICBwcmludChwYXN0ZSgiRGVzY3JpcHRpdmVzIGZvciIsaSkpDQogIHByaW50KHgpDQp9DQoNCmZvciAoaSBpbiBsZXZlbDNfbGlzdCl7DQogIHg9cmFuZ2UoZGF0YTRbW2ldXSkNCiAgcHJpbnQocGFzdGUoJ1JhbmdlIGZvcicsaSkpDQogIHByaW50KHgpDQp9DQoNCmBgYA0KDQojIyBMZXZlbCA0OiBJbmZlcmVudGlhbCArIE90aGVyIFN0YXRpc3RpY3MNCg0KIyMjIElzIHRoZXJlIGEgY29ycmVsYXRpb24gYmV0d2VlbiDigJhQc3lDb250RuKAmSBhbmQg4oCYRkFDRWNvbW0/4oCZIE5vdGUgYW55IHJlbGV2YW50IHN0YXRpc3RpY3MuDQoNCiMjIyMgTm9ybWFsaXR5IHRlc3QgYW5kIHBsb3QNCg0KYGBge3J9DQpmb3IgKGkgaW4gbGV2ZWwzX2xpc3Qpew0KICB4PXNoYXBpcm8udGVzdChkYXRhNFtbaV1dKQ0KICBwcmludChpKQ0KICBwcmludCh4KQ0KfQ0KDQpmb3IgKGkgaW4gbGV2ZWwzX2xpc3Qpew0KICBoaXN0KGRhdGE0W1tpXV0sbWFpbj1pLHhsYWI9aSxwcm9iYWJpbGl0eSA9IFQsY29sPSdzdGVlbGJsdWUnKQ0KICBsaW5lcyhkZW5zaXR5KGRhdGE0W1tpXV0pLGx3ZD0yLGNvbD0ncmVkJykNCn0NCg0KI25vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KYGBgDQoNCiMjIyMgQ29ycmVsYXRpb24NCg0KYGBge3J9DQpjb3IudGVzdChkYXRhNCRQc3lDb250RixkYXRhNCRGQUNFY29tbSxtZXRob2QgPSAnaycpDQoNCmlmIChGQUxTRSkgew0KbWV0aG9kX2xpc3QgPSBsaXN0KCdrJywncycsJ3AnKQ0KDQpmb3IgKGkgaW4gbWV0aG9kX2xpc3Qpew0KICB4PWNvci50ZXN0KGRhdGE0JFBzeUNvbnRGLGRhdGE0JEZBQ0Vjb21tLCBtZXRob2QgPSBpKQ0KICBwcmludCh4KQ0KfQ0KfQ0KDQojYWNjb3JkaW5nIHRvIEtlbmRhbGwncyB0YXUsIHRoZXJlIGlzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCB3ZWFrIG5lZ2F0aXZlIGNvcnJlbGF0aW9uIG9mIC0wLjE3IGJldHdlZW4gRkFDRWNvbW0gYW5kIFBzeUNvbnRGLg0KYGBgDQoNCiMjIyMgUGxvdA0KDQpgYGB7cn0NCmRhdGE0IHw+IA0KICBnZ3Bsb3QoYWVzKHg9UHN5Q29udEYseT1GQUNFY29tbSkpKw0KICBnZW9tX3BvaW50KCkrDQogIHRoZW1lX2J3KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpKw0KICBsYWJzKHRpdGxlPSdXaGF0IGluIHRoZSBGYW1pbHkgQ29tbXVuaWNhdGlvbiBhbmQgUHN5Q29udEYgaXMgSGFwcGVuaW5nIEhlcmU/JykrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAuNSkpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZ9DQojYmVlcCB3aGVuIGRvbmUNCmlmIChyZXF1aXJlKCJiZWVwciIpKQ0KICBiZWVwcjo6YmVlcCgyKQ0KYGBg