library(readxl)
library(tidyverse)
library(psych)
library(ggplot2)
library(car)
library(stats)
library(viridis)
options(scipen = 999)
rm(list = ls())
library(readxl)
dataset_dfe <- read_excel("~/Desktop/QRMSEMINARS/vi. assignment2/dataAssignment2.xlsx")
View(dataset_dfe)
class(dataset_dfe)
[1] "tbl_df"     "tbl"        "data.frame"
str(dataset_dfe)
tibble [11,673 × 10] (S3: tbl_df/tbl/data.frame)
 $ laName        : chr [1:11673] "Barking and Dagenham" "Barking and Dagenham" "Barking and Dagenham" "Barking and Dagenham" ...
 $ timePeriod    : num [1:11673] 202425 202425 202425 202425 202425 ...
 $ regionName    : chr [1:11673] "London" "London" "London" "London" ...
 $ sex           : chr [1:11673] "Girls" "Boys" "Boys" "Boys" ...
 $ ethnicityMajor: chr [1:11673] "Mixed / Multiple ethnic groups" "Black / African / Caribbean / Black British" "White" "Asian / Asian British" ...
 $ ethnicityMinor: chr [1:11673] "White and Asian" "Caribbean" "Any other White background" "Any other Asian background" ...
 $ fsmStatus     : chr [1:11673] "FSM eligible" "Not known to be FSM eligible" "FSM eligible" "Not known to be FSM eligible" ...
 $ yearGroup     : chr [1:11673] "Year 1" "Year 1" "Year 1" "Year 1" ...
 $ percentTarget : num [1:11673] 100 85 72 76 82 79 NA 100 NA 68 ...
 $ percentFSM    : num [1:11673] 23.3 23.3 23.3 23.3 23.3 ...
dataset_dfe$laName <- as.factor(dataset_dfe$laName)
dataset_dfe$timePeriod <- as.factor(dataset_dfe$timePeriod)
dataset_dfe$regionName <- as.factor(dataset_dfe$regionName)
dataset_dfe$sex <- as.factor(dataset_dfe$sex)
dataset_dfe$ethnicityMajor <- as.factor(dataset_dfe$ethnicityMajor)
dataset_dfe$ethnicityMinor <- as.factor(dataset_dfe$ethnicityMinor)
dataset_dfe$fsmStatus <- as.factor(dataset_dfe$fsmStatus)
dataset_dfe$yearGroup <- as.factor(dataset_dfe$yearGroup)
str(dataset_dfe)
tibble [11,673 × 10] (S3: tbl_df/tbl/data.frame)
 $ laName        : Factor w/ 153 levels "Barking and Dagenham",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ timePeriod    : Factor w/ 1 level "202425": 1 1 1 1 1 1 1 1 1 1 ...
 $ regionName    : Factor w/ 9 levels "East Midlands",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ sex           : Factor w/ 2 levels "Boys","Girls": 2 1 1 1 2 1 1 2 2 1 ...
 $ ethnicityMajor: Factor w/ 5 levels "Asian / Asian British",..: 3 2 5 1 2 1 1 3 5 2 ...
 $ ethnicityMinor: Factor w/ 22 levels "African","All Asian / Asian British",..: 20 12 10 6 1 2 13 20 18 1 ...
 $ fsmStatus     : Factor w/ 2 levels "FSM eligible",..: 1 2 1 2 1 2 1 2 1 1 ...
 $ yearGroup     : Factor w/ 1 level "Year 1": 1 1 1 1 1 1 1 1 1 1 ...
 $ percentTarget : num [1:11673] 100 85 72 76 82 79 NA 100 NA 68 ...
 $ percentFSM    : num [1:11673] 23.3 23.3 23.3 23.3 23.3 ...
#Part 1 - Task 1
data_dfe <- dataset_dfe %>%
  filter(!is.na(percentTarget))

overall_stats <- data_dfe %>%
  summarise(
    Median = median(percentTarget),
    Mean = mean(percentTarget),
    SD = sd(percentTarget),
  )

print(overall_stats)
library(ggplot2)

mean_val <- mean(data_dfe$percentTarget, na.rm = TRUE)
median_val <- median(data_dfe$percentTarget, na.rm = TRUE)

ggplot(data_dfe, aes(x = percentTarget)) +
  geom_density(fill = "#56B4E9", alpha = 0.8, color = "black") +
  geom_vline(aes(xintercept = mean_val), color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = median_val), color = "black", linetype = "solid", size = 1) +
  annotate("text", x = mean_val - 5, y = 0.01, 
           label = paste("Mean:", round(mean_val, 1)), color = "red", angle = 0, vjust = 1) +
  annotate("text", x = median_val + 5, y = 0.01, 
           label = paste("Median:", round(median_val, 1)), color = "black", angle = 0, vjust = -0.5) +
  
 theme_minimal() +
  labs(
    title = "Distribution of Phonics Attainment Scores in England",
    x = "percentTarget",
    y = "Density"
  ) 

#Part 1 - Task 2
sex_stats <- data_dfe %>%
  group_by(sex) %>%
  summarise(
    Median = median(percentTarget),
    Mean = mean(percentTarget),
    SD = sd(percentTarget)
  )

print(sex_stats)
boxplot_sex <- ggplot(data_dfe, aes(x = sex, y = percentTarget, fill = sex)) +
  geom_boxplot(alpha = 0.7, outlier.colour = "red", outlier.shape = 1) +

  theme_minimal() +
  labs(
    title = "Phonics Attainment by Sex",
    x = "Sex",
    y = "percentTarget"
  )

print(boxplot_sex)

library(tidyverse)
library(car)

#DV needs to be numeric
is.numeric(data_dfe$percentTarget)
[1] TRUE
boys_dfe <- data_dfe$percentTarget[data_dfe$sex == "Boys"]

print("Shapiro-Wilk Test: Boys")
[1] "Shapiro-Wilk Test: Boys"
if (length(boys_dfe) > 5000) {
  shapiro.test(sample(boys_dfe, 5000))
} else {
  shapiro.test(boys_dfe)
}

    Shapiro-Wilk normality test

data:  boys_dfe
W = 0.9608, p-value < 0.00000000000000022
girls_dfe <- data_dfe$percentTarget[data_dfe$sex == "Girls"]

print("Shapiro-Wilk Text: Girls")
[1] "Shapiro-Wilk Text: Girls"
if (length(girls_dfe) > 5000) {
  shapiro.test(sample(girls_dfe, 5000))
} else {
  shapiro.test(girls_dfe)
}

    Shapiro-Wilk normality test

data:  girls_dfe
W = 0.93387, p-value < 0.00000000000000022
leveneTest(percentTarget ~ sex, data = data_dfe)
Levene's Test for Homogeneity of Variance (center = median)
        Df F value                Pr(>F)    
group    1  110.63 < 0.00000000000000022 ***
      8243                                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
wilcox_result_sex <- wilcox.test(data_dfe$percentTarget ~ data_dfe$sex, alternative = "two.sided")
print(wilcox_result_sex)

    Wilcoxon rank sum test with continuity correction

data:  data_dfe$percentTarget by data_dfe$sex
W = 5105979, p-value < 0.00000000000000022
alternative hypothesis: true location shift is not equal to 0
#Part 1 Task 3
fsm_stats <- data_dfe %>%
  group_by(fsmStatus) %>%
  summarise(
    Median = median(percentTarget),
    Mean = mean(percentTarget),
    SD = sd(percentTarget)
  )

print(fsm_stats)
boxplot_fsm <- ggplot(data_dfe, aes(x = fsmStatus, y = percentTarget, fill = fsmStatus)) +
  geom_boxplot(alpha = 0.7, outlier.colour = "red", outlier.shape = 1) +

  theme_minimal() +
  labs(
    title = "Phonics Attainment by FSM Status",
    x = "FSM Status",
    y = "percentTarget"
  )

print(boxplot_fsm)

fsm_eligible <- data_dfe$percentTarget[data_dfe$fsmStatus == "FSM eligible"]

print("Shapiro-Wilk Test: FSM eligible")
[1] "Shapiro-Wilk Test: FSM eligible"
if (length(fsm_eligible) > 5000) {
  shapiro.test(sample(fsm_eligible, 5000))
} else {
  shapiro.test(fsm_eligible)
}

    Shapiro-Wilk normality test

data:  fsm_eligible
W = 0.98263, p-value < 0.00000000000000022
fsm_notKnown <- data_dfe$percentTarget[data_dfe$fsmStatus == "Not known to be FSM eligible"]

print("Shapiro-Wilk Text: Not known to be FSM eligible")
[1] "Shapiro-Wilk Text: Not known to be FSM eligible"
if (length(fsm_notKnown) > 5000) {
  shapiro.test(sample(fsm_notKnown, 5000))
} else {
  shapiro.test(fsm_notKnown)
}

    Shapiro-Wilk normality test

data:  fsm_notKnown
W = 0.93218, p-value < 0.00000000000000022
leveneTest(percentTarget ~ fsmStatus, data = data_dfe)
Levene's Test for Homogeneity of Variance (center = median)
        Df F value                Pr(>F)    
group    1  413.11 < 0.00000000000000022 ***
      8243                                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
wilcox_result_fsm <- wilcox.test(data_dfe$percentTarget ~ data_dfe$fsmStatus, alternative = "two.sided")
print(wilcox_result_fsm)

    Wilcoxon rank sum test with continuity correction

data:  data_dfe$percentTarget by data_dfe$fsmStatus
W = 3500711, p-value < 0.00000000000000022
alternative hypothesis: true location shift is not equal to 0
#Part 1 - Task 4
region_stats <- data_dfe %>%
  group_by(regionName) %>%
  summarise(
    Median = median(percentTarget),
    Mean = mean(percentTarget),
    SD = sd(percentTarget),
  ) %>%
arrange(desc(Median))
print(region_stats)
scatterplot <- ggplot(data = data_dfe, 
                      aes(x = percentFSM, y = percentTarget)) +
  geom_point(color = "#56B4E9") + 
  geom_smooth(method = lm, color = "red") +    
  ylim(0, 100) +
  theme_minimal() +
  labs(
    x = "percentFSM",
    y = "percentTarget"
  )

print(scatterplot)

model <- lm(percentTarget ~ percentFSM, data = data_dfe)
summary(model)

Call:
lm(formula = percentTarget ~ percentFSM, data = data_dfe)

Residuals:
    Min      1Q  Median      3Q     Max 
-77.685  -7.696   2.353   9.647  23.626 

Coefficients:
            Estimate Std. Error t value             Pr(>|t|)    
(Intercept) 75.75804    0.49200 153.978 < 0.0000000000000002 ***
percentFSM   0.08403    0.02187   3.841             0.000123 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 13.55 on 8243 degrees of freedom
Multiple R-squared:  0.001787,  Adjusted R-squared:  0.001666 
F-statistic: 14.76 on 1 and 8243 DF,  p-value: 0.0001232
plot(model, which = 2)

#Part 2 - Task 1 

# the three Local Authorities are: Richmond Upon Thames, West Sussex, and Manchester 
la_summary <- data_dfe %>%
  group_by(laName) %>%
  summarise(
    Median_FSM = median(percentFSM, na.rm = TRUE )
    ) %>%
  arrange(Median_FSM)

print(la_summary)
library(dplyr)

fsm_rankings <- data_dfe %>%
  group_by(laName) %>%
  summarise(
    Median_FSM = median(percentFSM, na.rm = TRUE)) %>%
  arrange(desc(Median_FSM)) 

print(head(fsm_rankings, 5))
threeLas_comparison <- data_dfe %>%
  filter(laName %in% c("Richmond upon Thames", "West Sussex", "Manchester")) %>%
  group_by(laName) %>%
  summarise(
    Median_FSM = median(percentFSM, na.rm = TRUE),      
    Median_Score = median(percentTarget, na.rm = TRUE)
  )

print(threeLas_comparison)
#Part 2 - Task 2
library(tidyverse)
library(car)

three_las <- c("Richmond upon Thames", "West Sussex", "Manchester")
data_three_las <- data_dfe %>% 
  filter(laName %in% three_las)

data_three_las %>%
  group_by(laName) %>%
  summarise(p_value = shapiro.test(percentTarget)$p.value) %>%
  print()
leveneTest(percentTarget ~ laName, data = data_three_las)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value   Pr(>F)   
group   2  4.9269 0.008167 **
      197                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
kruskal_result <- kruskal.test(percentTarget ~ laName, data = data_three_las)
print(kruskal_result)

    Kruskal-Wallis rank sum test

data:  percentTarget by laName
Kruskal-Wallis chi-squared = 44.369, df = 2, p-value = 0.0000000002319
library(FSA)

dunn_result <- dunnTest(percentTarget ~ laName, 
                        data = data_three_las, 
                        method = "bonferroni")

print(dunn_result)
#Part 2 - 3 
library(dplyr)

data_three_las %>%
  group_by(laName) %>%
  summarise(
    Median_Score = median(percentTarget, na.rm = TRUE), 
    Mean_Score = mean(percentTarget, na.rm = TRUE)
  ) %>%
  arrange(Median_Score) 
NA
ggplot(data_three_las, aes(x = reorder (laName, percentTarget, median),
                           y = percentTarget,
                           fill = laName)) + 
         geom_boxplot(alpha = 0.7, show.legend = FALSE) + 
         theme_minimal() +
         labs(title = "Comparison of Three LAs",
              x = "Local Authority",
              y = "Phonics Attainment (%)") 

#part 2 - 4
data_WS <- data_dfe %>% 
  filter(laName == "West Sussex")

sex_stats_ws <- data_WS %>% 
  group_by(sex) %>% 
  summarise(Median = median(percentTarget, na.rm=TRUE), Count = n())
print(sex_stats_ws)
data_WS %>%
  group_by(sex) %>%
  summarise(p_value = shapiro.test(percentTarget)$p.value) %>%
  print()

leveneTest(percentTarget ~ sex, data = data_WS)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  1  0.8376 0.3633
      69               
result_sex <- t.test(percentTarget ~ sex, data = data_WS, var.equal = TRUE)
print(result_sex)

    Two Sample t-test

data:  percentTarget by sex
t = -2.136, df = 69, p-value = 0.03623
alternative hypothesis: true difference in means between group Boys and group Girls is not equal to 0
95 percent confidence interval:
 -13.5009383  -0.4609665
sample estimates:
 mean in group Boys mean in group Girls 
           66.68571            73.66667 
fsm_stats_ws <- data_WS %>% 
  group_by(fsmStatus) %>% 
  summarise(Median = median(percentTarget, na.rm=TRUE), Count = n())
print(fsm_stats_ws)
data_WS %>%
  group_by(fsmStatus) %>%
  summarise(p_value = shapiro.test(percentTarget)$p.value) %>%
  print()

leveneTest(percentTarget ~ fsmStatus, data = data_WS)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  1  0.7892 0.3774
      69               
print(wilcox.test(percentTarget ~ fsmStatus, data = data_WS))

    Wilcoxon rank sum test with continuity correction

data:  percentTarget by fsmStatus
W = 209, p-value = 0.000002897
alternative hypothesis: true location shift is not equal to 0
ethnicity_stats_ws <- data_WS %>% 
  group_by(ethnicityMajor) %>% 
  summarise(Median = median(percentTarget, na.rm=TRUE), Count = n()) %>% 
  arrange(desc(Median))
print(ethnicity_stats_ws)
data_WS %>%
  group_by(ethnicityMajor) %>%
  summarise(p_value = shapiro.test(percentTarget)$p.value) %>%
  print()
library(car)
leveneTest(percentTarget ~ ethnicityMajor, data = data_WS)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  4   1.749 0.1498
      66               
print(kruskal.test(percentTarget ~ ethnicityMajor, data = data_WS))

    Kruskal-Wallis rank sum test

data:  percentTarget by ethnicityMajor
Kruskal-Wallis chi-squared = 7.1045, df = 4, p-value = 0.1305
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KbGlicmFyeShyZWFkeGwpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KHN0YXRzKQpsaWJyYXJ5KHZpcmlkaXMpCmBgYAoKYGBge3J9Cm9wdGlvbnMoc2NpcGVuID0gOTk5KQpybShsaXN0ID0gbHMoKSkKYGBgCgpgYGB7cn0KbGlicmFyeShyZWFkeGwpCmRhdGFzZXRfZGZlIDwtIHJlYWRfZXhjZWwoIn4vRGVza3RvcC9RUk1TRU1JTkFSUy92aS4gYXNzaWdubWVudDIvZGF0YUFzc2lnbm1lbnQyLnhsc3giKQpWaWV3KGRhdGFzZXRfZGZlKQpgYGAKCmBgYHtyfQpjbGFzcyhkYXRhc2V0X2RmZSkKc3RyKGRhdGFzZXRfZGZlKQpgYGAKCmBgYHtyfQpkYXRhc2V0X2RmZSRsYU5hbWUgPC0gYXMuZmFjdG9yKGRhdGFzZXRfZGZlJGxhTmFtZSkKZGF0YXNldF9kZmUkdGltZVBlcmlvZCA8LSBhcy5mYWN0b3IoZGF0YXNldF9kZmUkdGltZVBlcmlvZCkKZGF0YXNldF9kZmUkcmVnaW9uTmFtZSA8LSBhcy5mYWN0b3IoZGF0YXNldF9kZmUkcmVnaW9uTmFtZSkKZGF0YXNldF9kZmUkc2V4IDwtIGFzLmZhY3RvcihkYXRhc2V0X2RmZSRzZXgpCmRhdGFzZXRfZGZlJGV0aG5pY2l0eU1ham9yIDwtIGFzLmZhY3RvcihkYXRhc2V0X2RmZSRldGhuaWNpdHlNYWpvcikKZGF0YXNldF9kZmUkZXRobmljaXR5TWlub3IgPC0gYXMuZmFjdG9yKGRhdGFzZXRfZGZlJGV0aG5pY2l0eU1pbm9yKQpkYXRhc2V0X2RmZSRmc21TdGF0dXMgPC0gYXMuZmFjdG9yKGRhdGFzZXRfZGZlJGZzbVN0YXR1cykKZGF0YXNldF9kZmUkeWVhckdyb3VwIDwtIGFzLmZhY3RvcihkYXRhc2V0X2RmZSR5ZWFyR3JvdXApCmBgYAoKYGBge3J9CnN0cihkYXRhc2V0X2RmZSkKYGBgCmBgYHtyfQojUGFydCAxIC0gIDEKYGBgCgpgYGB7cn0KZGF0YV9kZmUgPC0gZGF0YXNldF9kZmUgJT4lCiAgZmlsdGVyKCFpcy5uYShwZXJjZW50VGFyZ2V0KSkKCm92ZXJhbGxfc3RhdHMgPC0gZGF0YV9kZmUgJT4lCiAgc3VtbWFyaXNlKAogICAgTWVkaWFuID0gbWVkaWFuKHBlcmNlbnRUYXJnZXQpLAogICAgTWVhbiA9IG1lYW4ocGVyY2VudFRhcmdldCksCiAgICBTRCA9IHNkKHBlcmNlbnRUYXJnZXQpLAogICkKCnByaW50KG92ZXJhbGxfc3RhdHMpCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCm1lYW5fdmFsIDwtIG1lYW4oZGF0YV9kZmUkcGVyY2VudFRhcmdldCwgbmEucm0gPSBUUlVFKQptZWRpYW5fdmFsIDwtIG1lZGlhbihkYXRhX2RmZSRwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpCgpnZ3Bsb3QoZGF0YV9kZmUsIGFlcyh4ID0gcGVyY2VudFRhcmdldCkpICsKICBnZW9tX2RlbnNpdHkoZmlsbCA9ICIjNTZCNEU5IiwgYWxwaGEgPSAwLjgsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuX3ZhbCksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbl92YWwpLCBjb2xvciA9ICJibGFjayIsIGxpbmV0eXBlID0gInNvbGlkIiwgc2l6ZSA9IDEpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSBtZWFuX3ZhbCAtIDUsIHkgPSAwLjAxLCAKICAgICAgICAgICBsYWJlbCA9IHBhc3RlKCJNZWFuOiIsIHJvdW5kKG1lYW5fdmFsLCAxKSksIGNvbG9yID0gInJlZCIsIGFuZ2xlID0gMCwgdmp1c3QgPSAxKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gbWVkaWFuX3ZhbCArIDUsIHkgPSAwLjAxLCAKICAgICAgICAgICBsYWJlbCA9IHBhc3RlKCJNZWRpYW46Iiwgcm91bmQobWVkaWFuX3ZhbCwgMSkpLCBjb2xvciA9ICJibGFjayIsIGFuZ2xlID0gMCwgdmp1c3QgPSAtMC41KSArCiAgCiB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUGhvbmljcyBBdHRhaW5tZW50IFNjb3JlcyBpbiBFbmdsYW5kIiwKICAgIHggPSAicGVyY2VudFRhcmdldCIsCiAgICB5ID0gIkRlbnNpdHkiCiAgKSAKYGBgCmBgYHtyfQojUGFydCAxIC0gIDIKYGBgCgpgYGB7cn0Kc2V4X3N0YXRzIDwtIGRhdGFfZGZlICU+JQogIGdyb3VwX2J5KHNleCkgJT4lCiAgc3VtbWFyaXNlKAogICAgTWVkaWFuID0gbWVkaWFuKHBlcmNlbnRUYXJnZXQpLAogICAgTWVhbiA9IG1lYW4ocGVyY2VudFRhcmdldCksCiAgICBTRCA9IHNkKHBlcmNlbnRUYXJnZXQpCiAgKQoKcHJpbnQoc2V4X3N0YXRzKQpgYGAKCmBgYHtyfQpib3hwbG90X3NleCA8LSBnZ3Bsb3QoZGF0YV9kZmUsIGFlcyh4ID0gc2V4LCB5ID0gcGVyY2VudFRhcmdldCwgZmlsbCA9IHNleCkpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjcsIG91dGxpZXIuY29sb3VyID0gInJlZCIsIG91dGxpZXIuc2hhcGUgPSAxKSArCgogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlBob25pY3MgQXR0YWlubWVudCBieSBTZXgiLAogICAgeCA9ICJTZXgiLAogICAgeSA9ICJwZXJjZW50VGFyZ2V0IgogICkKCnByaW50KGJveHBsb3Rfc2V4KQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjYXIpCgppcy5udW1lcmljKGRhdGFfZGZlJHBlcmNlbnRUYXJnZXQpCmBgYAoKYGBge3J9CmJveXNfZGZlIDwtIGRhdGFfZGZlJHBlcmNlbnRUYXJnZXRbZGF0YV9kZmUkc2V4ID09ICJCb3lzIl0KCnByaW50KCJTaGFwaXJvLVdpbGsgVGVzdDogQm95cyIpCmlmIChsZW5ndGgoYm95c19kZmUpID4gNTAwMCkgewogIHNoYXBpcm8udGVzdChzYW1wbGUoYm95c19kZmUsIDUwMDApKQp9IGVsc2UgewogIHNoYXBpcm8udGVzdChib3lzX2RmZSkKfQoKZ2lybHNfZGZlIDwtIGRhdGFfZGZlJHBlcmNlbnRUYXJnZXRbZGF0YV9kZmUkc2V4ID09ICJHaXJscyJdCgpwcmludCgiU2hhcGlyby1XaWxrIFRleHQ6IEdpcmxzIikKaWYgKGxlbmd0aChnaXJsc19kZmUpID4gNTAwMCkgewogIHNoYXBpcm8udGVzdChzYW1wbGUoZ2lybHNfZGZlLCA1MDAwKSkKfSBlbHNlIHsKICBzaGFwaXJvLnRlc3QoZ2lybHNfZGZlKQp9CgpgYGAKCgpgYGB7cn0KbGV2ZW5lVGVzdChwZXJjZW50VGFyZ2V0IH4gc2V4LCBkYXRhID0gZGF0YV9kZmUpCmBgYAoKYGBge3J9CndpbGNveF9yZXN1bHRfc2V4IDwtIHdpbGNveC50ZXN0KGRhdGFfZGZlJHBlcmNlbnRUYXJnZXQgfiBkYXRhX2RmZSRzZXgsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpCnByaW50KHdpbGNveF9yZXN1bHRfc2V4KQpgYGAKCgpgYGB7cn0KI1BhcnQgMSAtIDMKYGBgCgoKYGBge3J9CmZzbV9zdGF0cyA8LSBkYXRhX2RmZSAlPiUKICBncm91cF9ieShmc21TdGF0dXMpICU+JQogIHN1bW1hcmlzZSgKICAgIE1lZGlhbiA9IG1lZGlhbihwZXJjZW50VGFyZ2V0KSwKICAgIE1lYW4gPSBtZWFuKHBlcmNlbnRUYXJnZXQpLAogICAgU0QgPSBzZChwZXJjZW50VGFyZ2V0KQogICkKCnByaW50KGZzbV9zdGF0cykKYGBgCmBgYHtyfQpib3hwbG90X2ZzbSA8LSBnZ3Bsb3QoZGF0YV9kZmUsIGFlcyh4ID0gZnNtU3RhdHVzLCB5ID0gcGVyY2VudFRhcmdldCwgZmlsbCA9IGZzbVN0YXR1cykpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjcsIG91dGxpZXIuY29sb3VyID0gInJlZCIsIG91dGxpZXIuc2hhcGUgPSAxKSArCgogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlBob25pY3MgQXR0YWlubWVudCBieSBGU00gU3RhdHVzIiwKICAgIHggPSAiRlNNIFN0YXR1cyIsCiAgICB5ID0gInBlcmNlbnRUYXJnZXQiCiAgKQoKcHJpbnQoYm94cGxvdF9mc20pCmBgYAoKYGBge3J9CmZzbV9lbGlnaWJsZSA8LSBkYXRhX2RmZSRwZXJjZW50VGFyZ2V0W2RhdGFfZGZlJGZzbVN0YXR1cyA9PSAiRlNNIGVsaWdpYmxlIl0KCnByaW50KCJTaGFwaXJvLVdpbGsgVGVzdDogRlNNIGVsaWdpYmxlIikKaWYgKGxlbmd0aChmc21fZWxpZ2libGUpID4gNTAwMCkgewogIHNoYXBpcm8udGVzdChzYW1wbGUoZnNtX2VsaWdpYmxlLCA1MDAwKSkKfSBlbHNlIHsKICBzaGFwaXJvLnRlc3QoZnNtX2VsaWdpYmxlKQp9Cgpmc21fbm90S25vd24gPC0gZGF0YV9kZmUkcGVyY2VudFRhcmdldFtkYXRhX2RmZSRmc21TdGF0dXMgPT0gIk5vdCBrbm93biB0byBiZSBGU00gZWxpZ2libGUiXQoKcHJpbnQoIlNoYXBpcm8tV2lsayBUZXh0OiBOb3Qga25vd24gdG8gYmUgRlNNIGVsaWdpYmxlIikKaWYgKGxlbmd0aChmc21fbm90S25vd24pID4gNTAwMCkgewogIHNoYXBpcm8udGVzdChzYW1wbGUoZnNtX25vdEtub3duLCA1MDAwKSkKfSBlbHNlIHsKICBzaGFwaXJvLnRlc3QoZnNtX25vdEtub3duKQp9CgpgYGAKYGBge3J9CmxldmVuZVRlc3QocGVyY2VudFRhcmdldCB+IGZzbVN0YXR1cywgZGF0YSA9IGRhdGFfZGZlKQpgYGAKCmBgYHtyfQp3aWxjb3hfcmVzdWx0X2ZzbSA8LSB3aWxjb3gudGVzdChkYXRhX2RmZSRwZXJjZW50VGFyZ2V0IH4gZGF0YV9kZmUkZnNtU3RhdHVzLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQpwcmludCh3aWxjb3hfcmVzdWx0X2ZzbSkKYGBgCgpgYGB7cn0KI1BhcnQgMSAtIDQKYGBgCgpgYGB7cn0KcmVnaW9uX3N0YXRzIDwtIGRhdGFfZGZlICU+JQogIGdyb3VwX2J5KHJlZ2lvbk5hbWUpICU+JQogIHN1bW1hcmlzZSgKICAgIE1lZGlhbiA9IG1lZGlhbihwZXJjZW50VGFyZ2V0KSwKICAgIE1lYW4gPSBtZWFuKHBlcmNlbnRUYXJnZXQpLAogICAgU0QgPSBzZChwZXJjZW50VGFyZ2V0KSwKICApICU+JQphcnJhbmdlKGRlc2MoTWVkaWFuKSkKcHJpbnQocmVnaW9uX3N0YXRzKQpgYGAKCmBgYHtyfQpzY2F0dGVycGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGFfZGZlLCAKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcGVyY2VudEZTTSwgeSA9IHBlcmNlbnRUYXJnZXQpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICIjNTZCNEU5IikgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSwgY29sb3IgPSAicmVkIikgKyAgICAKICB5bGltKDAsIDEwMCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHggPSAicGVyY2VudEZTTSIsCiAgICB5ID0gInBlcmNlbnRUYXJnZXQiCiAgKQoKcHJpbnQoc2NhdHRlcnBsb3QpCmBgYAoKYGBge3J9Cm1vZGVsIDwtIGxtKHBlcmNlbnRUYXJnZXQgfiBwZXJjZW50RlNNLCBkYXRhID0gZGF0YV9kZmUpCnN1bW1hcnkobW9kZWwpCmBgYApgYGB7cn0KcGxvdChtb2RlbCwgd2hpY2ggPSAyKQpgYGAKCgpgYGB7cn0KI1BhcnQgMiAtIDEgCmBgYAoKYGBge3J9CmxhX3N1bW1hcnkgPC0gZGF0YV9kZmUgJT4lCiAgZ3JvdXBfYnkobGFOYW1lKSAlPiUKICBzdW1tYXJpc2UoCiAgICBNZWRpYW5fRlNNID0gbWVkaWFuKHBlcmNlbnRGU00sIG5hLnJtID0gVFJVRSApCiAgICApICU+JQogIGFycmFuZ2UoTWVkaWFuX0ZTTSkKCnByaW50KGxhX3N1bW1hcnkpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQoKZnNtX3JhbmtpbmdzIDwtIGRhdGFfZGZlICU+JQogIGdyb3VwX2J5KGxhTmFtZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgTWVkaWFuX0ZTTSA9IG1lZGlhbihwZXJjZW50RlNNLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKGRlc2MoTWVkaWFuX0ZTTSkpIAoKcHJpbnQoaGVhZChmc21fcmFua2luZ3MsIDUpKQpgYGAKCgpgYGB7cn0KdGhyZWVMYXNfY29tcGFyaXNvbiA8LSBkYXRhX2RmZSAlPiUKICBmaWx0ZXIobGFOYW1lICVpbiUgYygiUmljaG1vbmQgdXBvbiBUaGFtZXMiLCAiV2VzdCBTdXNzZXgiLCAiTWFuY2hlc3RlciIpKSAlPiUKICBncm91cF9ieShsYU5hbWUpICU+JQogIHN1bW1hcmlzZSgKICAgIE1lZGlhbl9GU00gPSBtZWRpYW4ocGVyY2VudEZTTSwgbmEucm0gPSBUUlVFKSwgICAgICAKICAgIE1lZGlhbl9TY29yZSA9IG1lZGlhbihwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpCiAgKQoKcHJpbnQodGhyZWVMYXNfY29tcGFyaXNvbikKYGBgCgoKYGBge3J9CiNQYXJ0IDIgLSAyCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGNhcikKCnRocmVlX2xhcyA8LSBjKCJSaWNobW9uZCB1cG9uIFRoYW1lcyIsICJXZXN0IFN1c3NleCIsICJNYW5jaGVzdGVyIikKZGF0YV90aHJlZV9sYXMgPC0gZGF0YV9kZmUgJT4lIAogIGZpbHRlcihsYU5hbWUgJWluJSB0aHJlZV9sYXMpCgpkYXRhX3RocmVlX2xhcyAlPiUKICBncm91cF9ieShsYU5hbWUpICU+JQogIHN1bW1hcmlzZShwX3ZhbHVlID0gc2hhcGlyby50ZXN0KHBlcmNlbnRUYXJnZXQpJHAudmFsdWUpICU+JQogIHByaW50KCkKYGBgCgpgYGB7cn0KbGV2ZW5lVGVzdChwZXJjZW50VGFyZ2V0IH4gbGFOYW1lLCBkYXRhID0gZGF0YV90aHJlZV9sYXMpCmBgYAoKYGBge3J9CmtydXNrYWxfcmVzdWx0IDwtIGtydXNrYWwudGVzdChwZXJjZW50VGFyZ2V0IH4gbGFOYW1lLCBkYXRhID0gZGF0YV90aHJlZV9sYXMpCnByaW50KGtydXNrYWxfcmVzdWx0KQpgYGAKCmBgYHtyfQpsaWJyYXJ5KEZTQSkKCmR1bm5fcmVzdWx0IDwtIGR1bm5UZXN0KHBlcmNlbnRUYXJnZXQgfiBsYU5hbWUsIAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV90aHJlZV9sYXMsIAogICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiYm9uZmVycm9uaSIpCgpwcmludChkdW5uX3Jlc3VsdCkKYGBgCgoKYGBge3J9CiNQYXJ0IDIgLSAzIApgYGAKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQoKZGF0YV90aHJlZV9sYXMgJT4lCiAgZ3JvdXBfYnkobGFOYW1lKSAlPiUKICBzdW1tYXJpc2UoCiAgICBNZWRpYW5fU2NvcmUgPSBtZWRpYW4ocGVyY2VudFRhcmdldCwgbmEucm0gPSBUUlVFKSwgCiAgICBNZWFuX1Njb3JlID0gbWVhbihwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpCiAgKSAlPiUKICBhcnJhbmdlKE1lZGlhbl9TY29yZSkgCgpgYGAKCgpgYGB7cn0KZ2dwbG90KGRhdGFfdGhyZWVfbGFzLCBhZXMoeCA9IHJlb3JkZXIgKGxhTmFtZSwgcGVyY2VudFRhcmdldCwgbWVkaWFuKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHBlcmNlbnRUYXJnZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBsYU5hbWUpKSArIAogICAgICAgICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjcsIHNob3cubGVnZW5kID0gRkFMU0UpICsgCiAgICAgICAgIHRoZW1lX21pbmltYWwoKSArCiAgICAgICAgIGxhYnModGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBUaHJlZSBMQXMiLAogICAgICAgICAgICAgIHggPSAiTG9jYWwgQXV0aG9yaXR5IiwKICAgICAgICAgICAgICB5ID0gIlBob25pY3MgQXR0YWlubWVudCAoJSkiKSAKYGBgCgpgYGB7cn0KI3BhcnQgMiAtIDQKYGBgCgoKYGBge3J9CmRhdGFfV1MgPC0gZGF0YV9kZmUgJT4lIAogIGZpbHRlcihsYU5hbWUgPT0gIldlc3QgU3Vzc2V4IikKCnNleF9zdGF0c193cyA8LSBkYXRhX1dTICU+JSAKICBncm91cF9ieShzZXgpICU+JSAKICBzdW1tYXJpc2UoTWVkaWFuID0gbWVkaWFuKHBlcmNlbnRUYXJnZXQsIG5hLnJtPVRSVUUpLCBDb3VudCA9IG4oKSkKcHJpbnQoc2V4X3N0YXRzX3dzKQpgYGAKCmBgYHtyfQpkYXRhX1dTICU+JQogIGdyb3VwX2J5KHNleCkgJT4lCiAgc3VtbWFyaXNlKHBfdmFsdWUgPSBzaGFwaXJvLnRlc3QocGVyY2VudFRhcmdldCkkcC52YWx1ZSkgJT4lCiAgcHJpbnQoKQoKbGV2ZW5lVGVzdChwZXJjZW50VGFyZ2V0IH4gc2V4LCBkYXRhID0gZGF0YV9XUykKYGBgCgpgYGB7cn0KcmVzdWx0X3NleCA8LSB0LnRlc3QocGVyY2VudFRhcmdldCB+IHNleCwgZGF0YSA9IGRhdGFfV1MsIHZhci5lcXVhbCA9IFRSVUUpCnByaW50KHJlc3VsdF9zZXgpCmBgYAoKYGBge3J9CmZzbV9zdGF0c193cyA8LSBkYXRhX1dTICU+JSAKICBncm91cF9ieShmc21TdGF0dXMpICU+JSAKICBzdW1tYXJpc2UoTWVkaWFuID0gbWVkaWFuKHBlcmNlbnRUYXJnZXQsIG5hLnJtPVRSVUUpLCBDb3VudCA9IG4oKSkKcHJpbnQoZnNtX3N0YXRzX3dzKQpgYGAKYGBge3J9CmRhdGFfV1MgJT4lCiAgZ3JvdXBfYnkoZnNtU3RhdHVzKSAlPiUKICBzdW1tYXJpc2UocF92YWx1ZSA9IHNoYXBpcm8udGVzdChwZXJjZW50VGFyZ2V0KSRwLnZhbHVlKSAlPiUKICBwcmludCgpCgpsZXZlbmVUZXN0KHBlcmNlbnRUYXJnZXQgfiBmc21TdGF0dXMsIGRhdGEgPSBkYXRhX1dTKQpgYGAKCmBgYHtyfQpwcmludCh3aWxjb3gudGVzdChwZXJjZW50VGFyZ2V0IH4gZnNtU3RhdHVzLCBkYXRhID0gZGF0YV9XUykpCmBgYAoKYGBge3J9CmV0aG5pY2l0eV9zdGF0c193cyA8LSBkYXRhX1dTICU+JSAKICBncm91cF9ieShldGhuaWNpdHlNYWpvcikgJT4lIAogIHN1bW1hcmlzZShNZWRpYW4gPSBtZWRpYW4ocGVyY2VudFRhcmdldCwgbmEucm09VFJVRSksIENvdW50ID0gbigpKSAlPiUgCiAgYXJyYW5nZShkZXNjKE1lZGlhbikpCnByaW50KGV0aG5pY2l0eV9zdGF0c193cykKYGBgCgpgYGB7cn0KZGF0YV9XUyAlPiUKICBncm91cF9ieShldGhuaWNpdHlNYWpvcikgJT4lCiAgc3VtbWFyaXNlKHBfdmFsdWUgPSBzaGFwaXJvLnRlc3QocGVyY2VudFRhcmdldCkkcC52YWx1ZSkgJT4lCiAgcHJpbnQoKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGNhcikKbGV2ZW5lVGVzdChwZXJjZW50VGFyZ2V0IH4gZXRobmljaXR5TWFqb3IsIGRhdGEgPSBkYXRhX1dTKQpgYGAKCmBgYHtyfQpwcmludChrcnVza2FsLnRlc3QocGVyY2VudFRhcmdldCB+IGV0aG5pY2l0eU1ham9yLCBkYXRhID0gZGF0YV9XUykpCmBgYAoK