This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

plot(cars)

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

install.packages("FSA")
library(readxl)
library(tidyverse)
library(psych)
library(ggplot2)
library(effects)
library(viridis)
library(car)
library(stats)
library(FSA)
library(scales)
#uploading dataset
library(readxl)
dataAssignment2 <- read_excel("~/Library/Mobile Documents/com~apple~CloudDocs/UNI/courses/year two/quan/QRMSEMINARS/assignemnt 2/dataAssignment2.xlsx")
View(dataAssignment2)
#rename dataset
data <- dataAssignment2
# check structure of dataset
str(data)
#correct variable types
#correct types of variables
data$laName <- as.factor(data$laName)
data$timePeriod <- as.factor(data$timePeriod)
data$regionName <- as.factor(data$regionName)
data$sex <- as.factor(data$sex)
data$ethnicityMajor <- as.factor(data$ethnicityMajor)
data$ethnicityMinor <- as.factor(data$ethnicityMinor)
data$fsmStatus <- as.factor(data$fsmStatus)
data$yearGroup <- as.factor(data$yearGroup)
data$percentTarget <- as.numeric(data$percentTarget)
data$percentFSM <- as.numeric(data$percentFSM)
#part 1: overall England

#1) average percent of students that met phonics attainment target
mean(data$percentTarget, na.rm=TRUE) 
[1] 77.55901
#2)
median(data$percentTarget, na.rm = TRUE)
[1] 80
#3)
summary(data$percentTarget)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
   0.00   70.00   80.00   77.56   87.00  100.00    3428 
#5) creating boxplot: by region
 pal_fill <- c("East Midlands"="#A24BEA", "East of England"="#1F78B4", "London"="#FF69B4", "North East"="#FFFF00", "North West"="#008000", "South East"="#ADD8E6", "South West" = "#FFA500", "West Midlands" = "#FF0000", "Yorkshire and The Humber"="#964B00") 
 
boxplot_regs <- ggplot(data, aes(x= regionName, y = percentTarget, fill= regionName)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.9,               
               color = "black",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "England's Phonics Attainment by Region",
       x = "Region",
       y= "Phonics Attainment") +
  theme_minimal(base_size = 6)

print(boxplot_regs)

# Part 1: 6) histogram: local authorities' medians of phonics attainment

#6.1 robust single number per LA: median percentTarget
LA_att <- data %>%  
  group_by(laName) %>%  
  summarise(LA_median_percentTarget = median(percentTarget, na.rm = TRUE),    
            .groups = "drop")

#6.2 National central tendency and spread across LAs
national_median <- median(LA_att$LA_median_percentTarget, na.rm = TRUE)   # vertical reference line
LA_q25 <- quantile(LA_att$LA_median_percentTarget, probs = 0.25, na.rm = TRUE)  # IQR lowerbound
LA_q75 <- quantile(LA_att$LA_median_percentTarget, probs = 0.75, na.rm = TRUE)  # IQR upper bound

#6.3 Histogram with vertical median line and shaded IQR band 
histogram <- ggplot(LA_att, aes(x = LA_median_percentTarget)) +
  geom_histogram(bins = 20, fill = "#A24BEA", color = "white", alpha = 0.85) +
  # Shaded IQR band
  annotate("rect",
           xmin = as.numeric(LA_q25), xmax = as.numeric(LA_q75),
           ymin = -Inf, ymax = Inf,
           fill = "#FFFF00", alpha = 0.5) +
  # National median line + label
  geom_vline(xintercept = national_median, color = "#E45756", linewidth = 1.2) +
  annotate("label",
           x = national_median, y = Inf, vjust = 1.5,
           label = paste0("National median = ", round(national_median, 1), "%"),
           fill = "#1F78B4", color = "white", size = 3.5) +
  # Labels & theme
    labs(    
      title = "Distribution of LA-level phonics attainment (medians)",    
      x = "medians",
      y = "Count of LAs"  ) +  
     scale_x_continuous(labels = label_percent(scale = 1)) + 
  scale_y_continuous( 
    breaks = scales::breaks_width(2),  
    expand = expansion(mult = c(0, 0.05))
  )+
  theme_minimal(base_size = 12) +
  theme(    
    plot.title = element_text(face = "bold"),    
    panel.grid.minor = element_blank()  
    )
#printed histogram
print(histogram)

#part 1: 7->dotplot of local authorities

# 7.1) Compute medians at LA, region, and nation

#a) One robust number per LA: median of percentTarget across its rows
la_med <- data %>%
  group_by(laName, regionName) %>%
  summarise(la_median = median(percentTarget, na.rm = TRUE), .groups = "drop")

#b) Region medians (across LAs)
region_med <- la_med %>%
  group_by(regionName) %>%
  summarise(region_median = median(la_median, na.rm = TRUE), .groups = "drop")

#c) National median (across LAs)
national_median <- median(la_med$la_median, na.rm = TRUE)

#7.2) Sort LAs from lowest to highest and build x positions
la_sorted <- la_med %>%
  arrange(la_median, laName) %>%                  # tie-break by name for stability
  mutate(x_idx = row_number())                    # x position after sorting

# For faint region reference lines
region_spans <- la_sorted %>%
  group_by(regionName) %>%
  summarise(
    x_min = min(x_idx),
    x_max = max(x_idx),
    region_median = median(la_median, na.rm = TRUE),
    .groups = "drop"
  )
# part 1: 8-> Dot plot (“caterpillar”) figure

dotplot<- ggplot(la_sorted, aes(x = x_idx, y = la_median)) +
  # National median (bold line across entire panel)
  geom_hline(yintercept = national_median, color = "#E45756", linewidth = 0.9) +

  # Dots for each LA, colored by region (optional)
  geom_point(aes(color = regionName), size = 2.2, alpha = 0.9) +

  # Axes & labels
  scale_x_continuous(
    breaks = NULL,                      # hide tick labels (too many LAs)
    expand = expansion(mult = c(0.01, 0.01))
  ) +
  scale_y_continuous(
    limits = c(0, 100),
    breaks = seq(30, 100, by = 10)
  ) +
  labs(
    title = "Local Authority phonics attainment (LA medians, sorted low → high)",
    subtitle = "Dots = LA medians; red line = national median",
    x = "Local Authorities (sorted)",
    y = "LA median % at expected standard",
    color = "Region"
  ) +
  theme_minimal(base_size = 10) +
  theme(
    plot.title = element_text(face = "bold"),
    panel.grid.minor = element_blank()
  )

print(dotplot)

#Part 1: 9-> boxplot showing sex across regions

# One panel with regions on the x-axis; side-by-side boxes for Girls/Boys.
boxplot_regions <- ggplot(data , aes(x = regionName, y = percentTarget, fill = sex)) +
  geom_boxplot(outlier.alpha = 0.25, width = 0.7, position = position_dodge(width = 0.75)) +
  scale_fill_manual(values = c("Girls" = "#A24BEA", "Boys" = "#1F78B4")) +
  labs(
    title = "Phonics attainment by sex across regions",
    x = "Region",
    y = "% at expected standard",
    fill = "Sex"
  ) +
  scale_y_continuous(labels = percent_format(scale = 1), limits = c(0, 100)) +
  theme_minimal(base_size = 11) +
  theme(
    plot.title = element_text(face = "bold"),
    panel.grid.minor = element_blank(),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )
print(boxplot_regions)

#Part 1:10-> heatmap: sex x FSM -> by region
region_map <- data %>%
  group_by(regionName, sex, fsmStatus) %>%
  summarise(median_attain = median(percentTarget, na.rm = TRUE), .groups = "drop")

heatmap <- ggplot(region_map, aes(x = sex, y = fsmStatus, fill = median_attain)) +
  geom_tile(color = "white", linewidth = 0.6) +
  geom_text(aes(label = paste0(round(median_attain, 1), "%")), color = "black", size = 3.2) +
  facet_wrap(~ regionName, ncol = 4) +
  scale_fill_gradient(low = "#FDE725", high = "#2C7FB8", limits = c(0, 100), name = "Median %") +
  labs(
    title = "Sex × FSM heatmap by region (median % at expected standard)",
    x = "Sex",
    y = "FSM status"
  ) +
  theme_minimal(base_size = 8) +
  theme(
    plot.title = element_text(face = "bold"),
    panel.grid = element_blank(),
    strip.text = element_text(face = "bold")
  )

# Display:
print(heatmap)

#part 1a: overview of phonics attainment by sex

#1) filtering for sex
sex_data <- data %>%
  filter(timePeriod == "202425") %>%
  select(sex, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) checkin sample size for assumptions
table(sex_data$sex)

 Boys Girls 
 4135  4110 
#3) assumption one: Shapiro-Wilk (normality/normal distribution) -> violated
by(sex_data$percentTarget, sex_data$sex, shapiro.test)
sex_data$sex: Boys

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.9608, p-value < 2.2e-16

---------------------------------------------------------------------------------------------- 
sex_data$sex: Girls

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.93387, p-value < 2.2e-16
#4) assumption two: Levene's Test (homogenity of varience) -> violated
leveneTest(percentTarget ~ sex, data = sex_data)
Levene's Test for Homogeneity of Variance (center = median)
        Df F value    Pr(>F)    
group    1  110.63 < 2.2e-16 ***
      8243                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#5) double checking labels in "sex" 
levels(factor(sex_data$sex))
[1] "Boys"  "Girls"
#Kruskal-Wallis (any statistically significant differences?) -> yes
kruskal.test(percentTarget ~ sex, data = sex_data)

    Kruskal-Wallis rank sum test

data:  percentTarget by sex
Kruskal-Wallis chi-squared = 985.76, df = 1, p-value < 2.2e-16
#Post-hoc Dunn's test
dunnTest(percentTarget ~ sex, data = sex_data, method = "bonferroni")

#8) colors for boxplot
pal_fill <- c("Girls" = "#A24BEA", "Boys" = "#1F78B4")  #fill colors for boxes

#9) creating boxplot
ggplot(sex_data, aes(x= sex, y = percentTarget, fill= sex)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.8,               
               color = "white",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "England: Phonics Attainment by Sex",
       subtitle = "p value < 2.2e-16",
       x = "Sex",
       y= "Phonics Attainment") +
  theme_minimal()



#medians for boys and girls
med_by_sex <- tapply(sex_data$percentTarget, sex_data$sex, median, na.rm = TRUE)
med_by_sex
 Boys Girls 
   75    84 
#part 1b: overview phonics attainment by FSM-Status

#1) filtering for FSMStatus
fsm_data <- data %>%
  filter(timePeriod == "202425") %>%
  select(fsmStatus, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) checking levels
levels(fsm_data$fsmStatus)
[1] "FSM eligible"                 "Not known to be FSM eligible"
#3) assumption one: Shapiro-Wilk (normality/normal distribution) -> violated
by(fsm_data$percentTarget, fsm_data$fsmStatus, shapiro.test)
fsm_data$fsmStatus: FSM eligible

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.98263, p-value < 2.2e-16

---------------------------------------------------------------------------------------------- 
fsm_data$fsmStatus: Not known to be FSM eligible

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.93218, p-value < 2.2e-16
#4) assumption two: Levene's Test (homogenity of varience) -> violated
leveneTest(percentTarget ~ fsmStatus, data = fsm_data)
Levene's Test for Homogeneity of Variance (center = median)
        Df F value    Pr(>F)    
group    1  413.11 < 2.2e-16 ***
      8243                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#Kruskal-Wallis (any statistically significant differences?) -> yes
kruskal.test(percentTarget ~ fsmStatus, data = fsm_data)

    Kruskal-Wallis rank sum test

data:  percentTarget by fsmStatus
Kruskal-Wallis chi-squared = 1940.4, df = 1, p-value < 2.2e-16
#Post-hoc Dunn's test (where is the difference?) -> 
dunnTest(percentTarget ~ fsmStatus, data = fsm_data, method = "bonferroni")
#3) colors for boxplot
pal_fill <- c("FSM eligible" = "#A24BEA", "Not known to be FSM eligible" = "#1F78B4")  

#8) creating boxplot
ggplot(fsm_data, aes(x= fsmStatus, y = percentTarget, fill= fsmStatus)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.8,               
               color = "white",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "England: Phonics Attainment by FSM-Status",
       subtitle = "p value < 2.2e-16",
       x = "FSM-Status",
       y= "Phonics Attainment") +
  theme_minimal()

#part 1c: correlation between percentFSM and phonics attainment

#1) correlation testing (person's r)
cor.test(data$percentTarget, data$percentFSM, method = "pearson")

    Pearson's product-moment correlation

data:  data$percentTarget and data$percentFSM
t = 3.8415, df = 8243, p-value = 0.0001232
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.02070673 0.06380083
sample estimates:
       cor 
0.04227344 
cor(data$percentTarget, data$percentFSM, use = "complete.obs")
[1] 0.04227344
#-> revealed: statistically significant but negligable relationship and percentFSM is not a meaningful predicator

#scatterplot:
ggplot(data, aes(x = percentFSM, y = percentTarget)) +
  geom_point(alpha = 0.4) +
  geom_smooth(method = "lm", se = TRUE) +
  labs(
    x = "Percentage of pupils eligible for FSM",
    y = "Percentage meeting phonics target",
    title = "Correlation between FSM eligibility and phonics attainment"
  )

#part 1d: overview phonics attainment by ethnicity major

#1) filtering for ethnicity major
eth_data_ma <- data %>%
  filter(timePeriod == "202425") %>%
  select(ethnicityMajor, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) checking levels
levels(eth_data_ma$ethnicityMajor)
[1] "Asian / Asian British"                       "Black / African / Caribbean / Black British"
[3] "Mixed / Multiple ethnic groups"              "Other ethnic group"                         
[5] "White"                                      
#3) colors for boxplot
pal_fill <- c("Asian / Asian British" = "#A24BEA", "Black / African / Caribbean / Black British" = "#1F78B4", "White" = "#FF69B4", "Mixed / Multiple ethnic groups" = "#FFFF00", "Other ethnic group" = "#008000" )

#4) creating boxplot
ggplot(eth_data_ma, aes(x= ethnicityMajor, y = percentTarget, fill= ethnicityMajor)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.8,               
               color = "black",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "England: Phonics Attainment by major ethnicities",
       x = "Major Ethnicity",
       y= "Phonics Attainment") +
theme_minimal(base_size = 5.5)


#table of medians

eth_data_ma %>%
  group_by(ethnicityMajor) %>%
  summarise(median_value = median(percentTarget))
NA
#part 1e: overview phonics attainment by ethnicity (minor)

#1) filtering for minor ethnicites
eth_data_mi <- data %>%
  filter(timePeriod == "202425") %>%
  select(ethnicityMinor, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) checking levels
levels(eth_data_mi$ethnicityMinor)
#part 1e.1: overview phonics attainment by minor Asian ethnicities

#1) filtering for all asians
asian_categories <- c( "Bangladeshi", "Chinese", "Pakistani", "Gypsy", "Any other Asian background", "Indian", "White and Asian")

asian_minor <- eth_data_mi %>%
  filter(ethnicityMinor %in% asian_categories)

#2) colors for boxplot
pal_fill <- c("Bangladeshi" = "#A24BEA", "Chinese" = "#1F78B4", "Pakistani" = "#FF69B4", "Indian" = "#FFFF00", "Gypsy" = "#008000", "Any other Asian background" = "#FF0000", "White and Asian" = "#964B00" )

#4) creating boxplot
ggplot(asian_minor, aes(x= ethnicityMinor, y = percentTarget, fill= ethnicityMinor)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.8,               
               color = "black",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "England: Phonics Attainment by minor Asian ethnicities",
       x = "Minor Asian Ethnicity",
       y= "Phonics Attainment") +
theme_minimal(base_size = 7)

#part 1e.2: overview phonics attainment by minor White ethnicities

#1) filtering for all whites
white_categories <- c("English / Welsh / Scottish / Northern Irish / British", "Irish", "Irish Traveller", "Any other White Background")

white_minor <- eth_data_mi %>%
  filter(ethnicityMinor %in% white_categories)

#2) colors for boxplot
pal_fill <- c("Irish" = "#A24BEA", "Irish Traveller" = "#1F78B4", "Any other White Background" = "#FF69B4", "English / Welsh / Scottish / Northern Irish / British" = "#FFFF00" )

#4) creating boxplot
ggplot(white_minor, aes(x= ethnicityMinor, y = percentTarget, fill= ethnicityMinor)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.8,               
               color = "black",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "England: Phonics Attainment by minor White ethnicities",
       x = "Minor White Ethnicity",
       y= "Phonics Attainment") +
theme_minimal(base_size = 7)

#part 1e.3: overview phonics attainment by minor Black ethnicities

#1) filtering for all blacks
black_categories <- c("Caribbean", "African", "White and Black African", "Any other Black / African / Caribbean background", "White and Black Caribbean")

black_minor <- eth_data_mi %>%
  filter(ethnicityMinor %in% black_categories)

#2) colors for boxplot
pal_fill <- c("Caribbean" = "#A24BEA", "African" = "#1F78B4", "White and Black African" = "#FF69B4", "White and Black Caribbean" = "#FFFF00", "Any other Black / African / Caribbean background" = "#FF0000")

#4) creating boxplot
ggplot(black_minor, aes(x= ethnicityMinor, y = percentTarget, fill= ethnicityMinor)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill ="white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",
               aes(label = round(..y.., 1)),               
               vjust = +1.8,               
               color = "black",
               fontface = "bold",
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "England: Phonics Attainment by minor Black ethnicities",
       x = "Minor Black Ethnicity",
       y= "Phonics Attainment") +
theme_minimal(base_size = 6)

#part 2a: local authorities

#filter for only those 3
dat3 <- data %>%
  filter(laName %in% c("Richmond upon Thames", "West Sussex", "Lewisham"))

#filtering for only phonics attainment score (percentTarget)
dat3 <- dat3 %>%
  select(laName, percentTarget) %>%
  filter(! is.na(percentTarget))

#how many rows for each authority?
table(dat3$laName)

               Barking and Dagenham                              Barnet                            Barnsley 
                                  0                                   0                                   0 
       Bath and North East Somerset                             Bedford                              Bexley 
                                  0                                   0                                   0 
                         Birmingham               Blackburn with Darwen                           Blackpool 
                                  0                                   0                                   0 
                             Bolton Bournemouth, Christchurch and Poole                    Bracknell Forest 
                                  0                                   0                                   0 
                           Bradford                               Brent                   Brighton and Hove 
                                  0                                   0                                   0 
                   Bristol, City of                             Bromley                     Buckinghamshire 
                                  0                                   0                                   0 
                               Bury                          Calderdale                      Cambridgeshire 
                                  0                                   0                                   0 
                             Camden                Central Bedfordshire                       Cheshire East 
                                  0                                   0                                   0 
          Cheshire West and Chester                      City of London                            Cornwall 
                                  0                                   0                                   0 
                      County Durham                            Coventry                             Croydon 
                                  0                                   0                                   0 
                         Cumberland                          Darlington                               Derby 
                                  0                                   0                                   0 
                         Derbyshire                               Devon                           Doncaster 
                                  0                                   0                                   0 
                             Dorset                              Dudley                              Ealing 
                                  0                                   0                                   0 
           East Riding of Yorkshire                         East Sussex                             Enfield 
                                  0                                   0                                   0 
                              Essex                           Gateshead                     Gloucestershire 
                                  0                                   0                                   0 
                          Greenwich                             Hackney                              Halton 
                                  0                                   0                                   0 
             Hammersmith and Fulham                           Hampshire                            Haringey 
                                  0                                   0                                   0 
                             Harrow                          Hartlepool                            Havering 
                                  0                                   0                                   0 
           Herefordshire, County of                       Hertfordshire                          Hillingdon 
                                  0                                   0                                   0 
                           Hounslow                       Isle of Wight                     Isles of Scilly 
                                  0                                   0                                   0 
                          Islington              Kensington and Chelsea                                Kent 
                                  0                                   0                                   0 
        Kingston upon Hull, City of                Kingston upon Thames                            Kirklees 
                                  0                                   0                                   0 
                           Knowsley                             Lambeth                          Lancashire 
                                  0                                   0                                   0 
                              Leeds                           Leicester                      Leicestershire 
                                  0                                   0                                   0 
                           Lewisham                        Lincolnshire                           Liverpool 
                                 67                                   0                                   0 
                              Luton                          Manchester                              Medway 
                                  0                                   0                                   0 
                             Merton                       Middlesbrough                       Milton Keynes 
                                  0                                   0                                   0 
                Newcastle upon Tyne                              Newham                             Norfolk 
                                  0                                   0                                   0 
            North East Lincolnshire                  North Lincolnshire              North Northamptonshire 
                                  0                                   0                                   0 
                     North Somerset                      North Tyneside                     North Yorkshire 
                                  0                                   0                                   0 
                     Northumberland                          Nottingham                     Nottinghamshire 
                                  0                                   0                                   0 
                             Oldham                         Oxfordshire                        Peterborough 
                                  0                                   0                                   0 
                           Plymouth                          Portsmouth                             Reading 
                                  0                                   0                                   0 
                          Redbridge                Redcar and Cleveland                Richmond upon Thames 
                                  0                                   0                                  49 
                           Rochdale                           Rotherham                             Rutland 
                                  0                                   0                                   0 
                            Salford                            Sandwell                              Sefton 
                                  0                                   0                                   0 
                          Sheffield                          Shropshire                              Slough 
                                  0                                   0                                   0 
                           Solihull                            Somerset               South Gloucestershire 
                                  0                                   0                                   0 
                     South Tyneside                         Southampton                     Southend-on-Sea 
                                  0                                   0                                   0 
                          Southwark                          St. Helens                       Staffordshire 
                                  0                                   0                                   0 
                          Stockport                    Stockton-on-Tees                      Stoke-on-Trent 
                                  0                                   0                                   0 
                            Suffolk                          Sunderland                              Surrey 
                                  0                                   0                                   0 
                             Sutton                             Swindon                            Tameside 
                                  0                                   0                                   0 
                 Telford and Wrekin                            Thurrock                              Torbay 
                                  0                                   0                                   0 
                      Tower Hamlets                            Trafford                           Wakefield 
                                  0                                   0                                   0 
                            Walsall                      Waltham Forest                          Wandsworth 
                                  0                                   0                                   0 
                         Warrington                        Warwickshire                      West Berkshire 
                                  0                                   0                                   0 
              West Northamptonshire                         West Sussex                         Westminster 
                                  0                                  71                                   0 
            Westmorland and Furness                               Wigan                           Wiltshire 
                                  0                                   0                                   0 
             Windsor and Maidenhead                              Wirral                           Wokingham 
                                  0                                   0                                   0 
                      Wolverhampton                      Worcestershire                                York 
                                  0                                   0                                   0 
#checking assumptions: Shapiro-Wilk (normal distribution) -> violated (Lew & Rich: p<0.05)
by(dat3$percentTarget, dat3$laName, shapiro.test)
dat3$laName: Barking and Dagenham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Barnet
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Barnsley
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bath and North East Somerset
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bedford
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bexley
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Birmingham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Blackburn with Darwen
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Blackpool
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bolton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bournemouth, Christchurch and Poole
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bracknell Forest
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bradford
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Brent
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Brighton and Hove
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bristol, City of
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bromley
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Buckinghamshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Bury
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Calderdale
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Cambridgeshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Camden
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Central Bedfordshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Cheshire East
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Cheshire West and Chester
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: City of London
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Cornwall
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: County Durham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Coventry
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Croydon
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Cumberland
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Darlington
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Derby
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Derbyshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Devon
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Doncaster
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Dorset
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Dudley
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Ealing
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: East Riding of Yorkshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: East Sussex
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Enfield
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Essex
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Gateshead
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Gloucestershire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Greenwich
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Hackney
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Halton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Hammersmith and Fulham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Hampshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Haringey
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Harrow
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Hartlepool
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Havering
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Herefordshire, County of
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Hertfordshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Hillingdon
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Hounslow
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Isle of Wight
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Isles of Scilly
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Islington
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Kensington and Chelsea
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Kent
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Kingston upon Hull, City of
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Kingston upon Thames
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Kirklees
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Knowsley
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Lambeth
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Lancashire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Leeds
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Leicester
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Leicestershire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Lewisham

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.96219, p-value = 0.03959

---------------------------------------------------------------------------------------------- 
dat3$laName: Lincolnshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Liverpool
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Luton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Manchester
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Medway
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Merton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Middlesbrough
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Milton Keynes
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Newcastle upon Tyne
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Newham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Norfolk
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: North East Lincolnshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: North Lincolnshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: North Northamptonshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: North Somerset
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: North Tyneside
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: North Yorkshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Northumberland
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Nottingham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Nottinghamshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Oldham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Oxfordshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Peterborough
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Plymouth
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Portsmouth
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Reading
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Redbridge
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Redcar and Cleveland
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Richmond upon Thames

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.90716, p-value = 0.0009496

---------------------------------------------------------------------------------------------- 
dat3$laName: Rochdale
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Rotherham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Rutland
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Salford
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Sandwell
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Sefton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Sheffield
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Shropshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Slough
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Solihull
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Somerset
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: South Gloucestershire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: South Tyneside
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Southampton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Southend-on-Sea
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Southwark
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: St. Helens
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Staffordshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Stockport
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Stockton-on-Tees
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Stoke-on-Trent
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Suffolk
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Sunderland
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Surrey
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Sutton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Swindon
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Tameside
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Telford and Wrekin
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Thurrock
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Torbay
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Tower Hamlets
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Trafford
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Wakefield
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Walsall
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Waltham Forest
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Wandsworth
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Warrington
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Warwickshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: West Berkshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: West Northamptonshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: West Sussex

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.96824, p-value = 0.06892

---------------------------------------------------------------------------------------------- 
dat3$laName: Westminster
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Westmorland and Furness
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Wigan
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Wiltshire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Windsor and Maidenhead
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Wirral
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Wokingham
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Wolverhampton
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: Worcestershire
NULL
---------------------------------------------------------------------------------------------- 
dat3$laName: York
NULL
#checking assumptions: Levene's test (homogenity of variance) -> violated 
leveneTest(percentTarget ~ laName, data = dat3, center = median)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value  Pr(>F)  
group   2  3.5192 0.03163 *
      184                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#Kruskal-Wallis (any statistically significant differences?) -> yes, p<0.05
kruskal.test(percentTarget ~ laName, data = dat3)

    Kruskal-Wallis rank sum test

data:  percentTarget by laName
Kruskal-Wallis chi-squared = 38.49, df = 2, p-value = 4.386e-09
#Post-hoc Dunn's test (where is the difference?) -> 
dunnTest(percentTarget ~ laName, data = dat3, method = "bonferroni")
#part 2b: lowest ranking local authority

#identifying (calculating mean) -> WEST SUSSEX
dat3 %>%
  group_by(laName) %>%
  summarise(mean_percent = mean(percentTarget, na.rm = TRUE)) %>%
  arrange(mean_percent)
#part 2b.1: analysis of the factor sex

#1) filtering for WS
ws_data <- data %>%
  filter(laName == "West Sussex") %>%
  select(sex, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) checkin sample size for assumptions
table(ws_data$sex)

 Boys Girls 
   35    36 
#3) assumption one: Shapiro-Wilk (normality/normal distribution) -> confirmed
by(ws_data$percentTarget, ws_data$sex, shapiro.test)
ws_data$sex: Boys

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.9561, p-value = 0.1742

---------------------------------------------------------------------------------------------- 
ws_data$sex: Girls

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.96213, p-value = 0.2499
#4) assumption two: Levene's Test (homogenity of varience)
leveneTest(percentTarget ~ sex, data = ws_data)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  1  0.8376 0.3633
      69               
#5) double checking labels in "sex" for independent T test
levels(factor(ws_data$sex))
[1] "Boys"  "Girls"
#6) running independent t test
tt_ws <- t.test(percentTarget ~ sex, data = ws_data, var.equal = TRUE)

#7) printing results
tt_ws

    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 
#9) colors for boxplot
pal_fill <- c("Girls" = "#A24BEA", "Boys" = "#1F78B4")  #fill colors for boxes
pal_point <- c("Girls" = "#7A1FD2", "Boys" = "#0E5D91")  #colors for jitter 

#8) creating boxplot
ggplot(ws_data, aes(x= sex, y = percentTarget, fill= sex)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  geom_jitter(aes(color = sex), width = 0.15, alpha = 0.6, size = 2)+
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.7,               
               color = "white",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  scale_color_manual(values = pal_point) +
  labs(title = "West Sussex: Phonics Attainment by Sex",
       subtitle = "*white diamond marker = mean; p = 0.04",
       x = "Sex",
       y= "Phonics Attainment") +
  theme_minimal()


#9) heatmap fsm x sex in West Sussex

ws_sex_fsm_map <- data %>%
  filter(laName == "West Sussex") %>%
  group_by(laName, sex, fsmStatus) %>%
  summarise(median_attain = median(percentTarget, na.rm = TRUE), .groups = "drop")

ggplot(ws_sex_fsm_map, aes(x = sex, y = fsmStatus, fill = median_attain)) +
  geom_tile(color = "white", linewidth = 0.6) +
  geom_text(aes(label = paste0(round(median_attain, 1), "%")), color = "black", size = 3.2) +
  scale_fill_gradient(low = "#FDE725", high = "#2C7FB8", limits = c(0, 100), name = "Median %") +
  labs(
    title = "West Sussex: Sex × FSM heatmap (median % at expected standard)",
    x = "Sex",
    y = "FSM status"
  ) +
  theme_minimal(base_size = 8) +
  theme(
    plot.title = element_text(face = "bold"),
    panel.grid = element_blank(),
    strip.text = element_text(face = "bold")
  )

#Part 2b.2: Analysis of the factor FSM Status

#1) filtering for fsm-Status in WS
ws_data_fsm <- data %>%
  filter(laName == "West Sussex") %>%
  select(fsmStatus, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) checkin sample size for assumptions
table(ws_data_fsm$fsmStatus)

                FSM eligible Not known to be FSM eligible 
                          29                           42 
#3) assumption one: Shapiro-Wilk (normality/normal distribution) -> violated
by(ws_data_fsm$percentTarget, ws_data_fsm$fsmStatus, shapiro.test)
ws_data_fsm$fsmStatus: FSM eligible

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.95083, p-value = 0.1923

---------------------------------------------------------------------------------------------- 
ws_data_fsm$fsmStatus: Not known to be FSM eligible

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.89505, p-value = 0.001027
#4) assumption two: Levene's Test (homogenity of varience) -> upheld
leveneTest(percentTarget ~ fsmStatus, data = ws_data_fsm)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  1  0.7892 0.3774
      69               
#5) Mann-Whitney U Test (since assumptions violated)
wilcox.test(percentTarget ~ fsmStatus, data = ws_data_fsm, exact = FALSE)

    Wilcoxon rank sum test with continuity correction

data:  percentTarget by fsmStatus
W = 209, p-value = 2.897e-06
alternative hypothesis: true location shift is not equal to 0
#9) colors for boxplot
pal_fill <- c("FSM eligible" = "#A24BEA", "Not known to be FSM eligible" = "#1F78B4")  #fill colors for boxes
pal_point <- c("FSM eligible" = "#7A1FD2", "Not known to be FSM eligible" = "#0E5D91")  #colors for jitter 

#8) creating boxplot
ggplot(ws_data_fsm, aes(x= fsmStatus, y = percentTarget, fill= fsmStatus)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  geom_jitter(aes(color = fsmStatus), width = 0.15, alpha = 0.6, size = 2)+
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.7,               
               color = "white",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  scale_color_manual(values = pal_point) +
  labs(title = "West Sussex: Phonics Attainment by FSM Status",
       subtitle = "*white diamond marker = mean; p = 2.897e-06 ",
       x = "FSM Status",
       y= "Phonics Attainment") +
 theme_minimal(base_size = 8)

#Part 2b.2: Analysis of the factor ethnicity (major) in WS

#1) filtering for ethnicity (major) in WS
ws_data_eth <- data %>%
  filter(laName == "West Sussex") %>%
  select(ethnicityMajor, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) double checking levels
levels(ws_data_eth$ethnicityMajor)
[1] "Asian / Asian British"                       "Black / African / Caribbean / Black British"
[3] "Mixed / Multiple ethnic groups"              "Other ethnic group"                         
[5] "White"                                      
#3) checking number of rows
table(ws_data_eth$ethnicityMajor)

                      Asian / Asian British Black / African / Caribbean / Black British 
                                         18                                          12 
             Mixed / Multiple ethnic groups                          Other ethnic group 
                                         19                                           4 
                                      White 
                                         18 
#checking assumptions: Shapiro-Wilk (normal distribution) -> violated (Mixed p<0.05)
by(ws_data_eth$percentTarget, ws_data_eth$ethnicityMajor, shapiro.test)
ws_data_eth$ethnicityMajor: Asian / Asian British

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.94075, p-value = 0.2984

---------------------------------------------------------------------------------------------- 
ws_data_eth$ethnicityMajor: Black / African / Caribbean / Black British

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.91427, p-value = 0.2419

---------------------------------------------------------------------------------------------- 
ws_data_eth$ethnicityMajor: Mixed / Multiple ethnic groups

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.89373, p-value = 0.03752

---------------------------------------------------------------------------------------------- 
ws_data_eth$ethnicityMajor: Other ethnic group

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.87842, p-value = 0.3319

---------------------------------------------------------------------------------------------- 
ws_data_eth$ethnicityMajor: White

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.92169, p-value = 0.1385
#checking assumptions: Levene's test (homogenity of variance) -> upheld
leveneTest(percentTarget ~ ethnicityMajor, data = ws_data_eth, center = median)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  4   1.749 0.1498
      66               
#Kruskal-Wallis (any statistically significant differnces?) -> p>0.05; not significant
kruskal.test(percentTarget ~ ethnicityMajor, data = ws_data_eth)

    Kruskal-Wallis rank sum test

data:  percentTarget by ethnicityMajor
Kruskal-Wallis chi-squared = 7.1045, df = 4, p-value = 0.1305
pal_fill <- c("Asian / Asian British" = "#A24BEA", "Black / African / Caribbean / Black British" = "#1F78B4", "White" = "#FF69B4", "Mixed / Multiple ethnic groups" = "#FFFF00", "Other ethnic group" = "#008000" )

#4) creating boxplot
ggplot(ws_data_eth, aes(x= ethnicityMajor, y = percentTarget, fill= ethnicityMajor)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.6,               
               color = "black",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "West Sussex: Phonics Attainment by Major Ethnicities",
       x = "Major Ethnicity",
       y= "Phonics Attainment") +
theme_minimal(base_size = 5.5)


#table of medians

ws_data_eth %>%
  group_by(ethnicityMajor) %>%
  summarise(median_value = median(percentTarget))
#part 2b.3: overview phonics attainment by minor White ethnicities

#1) filtering for ethnicity (minor) in WS
ws_data_eth_min <- data %>%
  filter(laName == "West Sussex") %>%
  select(ethnicityMinor, percentTarget) %>%
  filter(! is.na(percentTarget))

#2) filtering for all whites
white_categories <- c("English / Welsh / Scottish / Northern Irish / British", "Irish", "Irish Traveller", "Any other White Background")

white_minor_WS <- ws_data_eth_min %>%
  filter(ethnicityMinor %in% white_categories)

#3) colors for boxplot
pal_fill <- c("Irish" = "#A24BEA", "Irish Traveller" = "#1F78B4", "Any other White Background" = "#FF69B4", "English / Welsh / Scottish / Northern Irish / British" = "#FFFF00" )

#4) creating boxplot
ggplot(white_minor_WS, aes(x= ethnicityMinor, y = percentTarget, fill= ethnicityMinor)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +1.8,               
               color = "black",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "West Sussex: Phonics Attainment by Minor White Ethnicities",
       x = "Minor White Ethnicity",
       y= "Phonics Attainment") +
theme_minimal(base_size = 7)

#part 2b.4: overview phonics attainment by minor Asian ethnicities

#1) filtering for all asians
asian_categories <- c( "Bangladeshi", "Chinese", "Pakistani", "Gypsy", "Any other Asian background", "Indian", "White and Asian")

asian_minor_WS <- ws_data_eth_min %>%
  filter(ethnicityMinor %in% asian_categories)

#2) colors for boxplot
pal_fill <- c("Bangladeshi" = "#A24BEA", "Chinese" = "#1F78B4", "Pakistani" = "#FF69B4", "Indian" = "#FFFF00", "Gypsy" = "#008000", "Any other Asian background" = "#FF0000", "White and Asian" = "#964B00" )

#4) creating boxplot
ggplot(asian_minor_WS, aes(x= ethnicityMinor, y = percentTarget, fill= ethnicityMinor)) +
  geom_boxplot(outlier.shape = NA, alpha = 0.7) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", color = "black")+
  stat_summary(fun = mean,               
               geom = "text",               
               aes(label = round(..y.., 1)),               
               vjust = +2,               
               color = "black",               
               fontface = "bold",               
               size = 3) +
  scale_fill_manual(values = pal_fill) +  
  labs(title = "West Sussex: Phonics Attainment by Minor Asian Ethnicities",
       x = "Minor Asian Ethnicity",
       y= "Phonics Attainment") +
theme_minimal(base_size = 7)

LS0tCnRpdGxlOiAiYXNzaW5nbWVudCAyIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiAKClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDbWQrU2hpZnQrRW50ZXIqLiAKCmBgYHtyfQpwbG90KGNhcnMpCmBgYAoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLiAKClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4KCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJGU0EiKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocHN5Y2gpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShlZmZlY3RzKQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KHN0YXRzKQpsaWJyYXJ5KEZTQSkKbGlicmFyeShzY2FsZXMpCmBgYAoKCmBgYHtyfQojdXBsb2FkaW5nIGRhdGFzZXQKbGlicmFyeShyZWFkeGwpCmRhdGFBc3NpZ25tZW50MiA8LSByZWFkX2V4Y2VsKCJ+L0xpYnJhcnkvTW9iaWxlIERvY3VtZW50cy9jb21+YXBwbGV+Q2xvdWREb2NzL1VOSS9jb3Vyc2VzL3llYXIgdHdvL3F1YW4vUVJNU0VNSU5BUlMvYXNzaWduZW1udCAyL2RhdGFBc3NpZ25tZW50Mi54bHN4IikKVmlldyhkYXRhQXNzaWdubWVudDIpCmBgYAoKYGBge3J9CiNyZW5hbWUgZGF0YXNldApkYXRhIDwtIGRhdGFBc3NpZ25tZW50MgpgYGAKCmBgYHtyfQojIGNoZWNrIHN0cnVjdHVyZSBvZiBkYXRhc2V0CnN0cihkYXRhKQpgYGAKCmBgYHtyfQojY29ycmVjdCB2YXJpYWJsZSB0eXBlcwojY29ycmVjdCB0eXBlcyBvZiB2YXJpYWJsZXMKZGF0YSRsYU5hbWUgPC0gYXMuZmFjdG9yKGRhdGEkbGFOYW1lKQpkYXRhJHRpbWVQZXJpb2QgPC0gYXMuZmFjdG9yKGRhdGEkdGltZVBlcmlvZCkKZGF0YSRyZWdpb25OYW1lIDwtIGFzLmZhY3RvcihkYXRhJHJlZ2lvbk5hbWUpCmRhdGEkc2V4IDwtIGFzLmZhY3RvcihkYXRhJHNleCkKZGF0YSRldGhuaWNpdHlNYWpvciA8LSBhcy5mYWN0b3IoZGF0YSRldGhuaWNpdHlNYWpvcikKZGF0YSRldGhuaWNpdHlNaW5vciA8LSBhcy5mYWN0b3IoZGF0YSRldGhuaWNpdHlNaW5vcikKZGF0YSRmc21TdGF0dXMgPC0gYXMuZmFjdG9yKGRhdGEkZnNtU3RhdHVzKQpkYXRhJHllYXJHcm91cCA8LSBhcy5mYWN0b3IoZGF0YSR5ZWFyR3JvdXApCmRhdGEkcGVyY2VudFRhcmdldCA8LSBhcy5udW1lcmljKGRhdGEkcGVyY2VudFRhcmdldCkKZGF0YSRwZXJjZW50RlNNIDwtIGFzLm51bWVyaWMoZGF0YSRwZXJjZW50RlNNKQpgYGAKCmBgYHtyfQojcGFydCAxOiBvdmVyYWxsIEVuZ2xhbmQKCiMxKSBhdmVyYWdlIHBlcmNlbnQgb2Ygc3R1ZGVudHMgdGhhdCBtZXQgcGhvbmljcyBhdHRhaW5tZW50IHRhcmdldAptZWFuKGRhdGEkcGVyY2VudFRhcmdldCwgbmEucm09VFJVRSkgCgojMikKbWVkaWFuKGRhdGEkcGVyY2VudFRhcmdldCwgbmEucm0gPSBUUlVFKQoKIzMpCnN1bW1hcnkoZGF0YSRwZXJjZW50VGFyZ2V0KQoKCiM1KSBjcmVhdGluZyBib3hwbG90OiBieSByZWdpb24KIHBhbF9maWxsIDwtIGMoIkVhc3QgTWlkbGFuZHMiPSIjQTI0QkVBIiwgIkVhc3Qgb2YgRW5nbGFuZCI9IiMxRjc4QjQiLCAiTG9uZG9uIj0iI0ZGNjlCNCIsICJOb3J0aCBFYXN0Ij0iI0ZGRkYwMCIsICJOb3J0aCBXZXN0Ij0iIzAwODAwMCIsICJTb3V0aCBFYXN0Ij0iI0FERDhFNiIsICJTb3V0aCBXZXN0IiA9ICIjRkZBNTAwIiwgIldlc3QgTWlkbGFuZHMiID0gIiNGRjAwMDAiLCAiWW9ya3NoaXJlIGFuZCBUaGUgSHVtYmVyIj0iIzk2NEIwMCIpIAogCmJveHBsb3RfcmVncyA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHg9IHJlZ2lvbk5hbWUsIHkgPSBwZXJjZW50VGFyZ2V0LCBmaWxsPSByZWdpb25OYW1lKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gMC43KSArCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBzaGFwZSA9IDIzLCBzaXplID0gMywgZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGdlb20gPSAidGV4dCIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHJvdW5kKC4ueS4uLCAxKSksICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHZqdXN0ID0gKzEuOSwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxfZmlsbCkgKyAgCiAgbGFicyh0aXRsZSA9ICJFbmdsYW5kJ3MgUGhvbmljcyBBdHRhaW5tZW50IGJ5IFJlZ2lvbiIsCiAgICAgICB4ID0gIlJlZ2lvbiIsCiAgICAgICB5PSAiUGhvbmljcyBBdHRhaW5tZW50IikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gNikKCnByaW50KGJveHBsb3RfcmVncykKYGBgCgoKYGBge3J9CiMgUGFydCAxOiA2KSBoaXN0b2dyYW06IGxvY2FsIGF1dGhvcml0aWVzJyBtZWRpYW5zIG9mIHBob25pY3MgYXR0YWlubWVudAoKIzYuMSByb2J1c3Qgc2luZ2xlIG51bWJlciBwZXIgTEE6IG1lZGlhbiBwZXJjZW50VGFyZ2V0CkxBX2F0dCA8LSBkYXRhICU+JSAgCiAgZ3JvdXBfYnkobGFOYW1lKSAlPiUgIAogIHN1bW1hcmlzZShMQV9tZWRpYW5fcGVyY2VudFRhcmdldCA9IG1lZGlhbihwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpLCAgICAKICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIikKCiM2LjIgTmF0aW9uYWwgY2VudHJhbCB0ZW5kZW5jeSBhbmQgc3ByZWFkIGFjcm9zcyBMQXMKbmF0aW9uYWxfbWVkaWFuIDwtIG1lZGlhbihMQV9hdHQkTEFfbWVkaWFuX3BlcmNlbnRUYXJnZXQsIG5hLnJtID0gVFJVRSkgICAjIHZlcnRpY2FsIHJlZmVyZW5jZSBsaW5lCkxBX3EyNSA8LSBxdWFudGlsZShMQV9hdHQkTEFfbWVkaWFuX3BlcmNlbnRUYXJnZXQsIHByb2JzID0gMC4yNSwgbmEucm0gPSBUUlVFKSAgIyBJUVIgbG93ZXJib3VuZApMQV9xNzUgPC0gcXVhbnRpbGUoTEFfYXR0JExBX21lZGlhbl9wZXJjZW50VGFyZ2V0LCBwcm9icyA9IDAuNzUsIG5hLnJtID0gVFJVRSkgICMgSVFSIHVwcGVyIGJvdW5kCgojNi4zIEhpc3RvZ3JhbSB3aXRoIHZlcnRpY2FsIG1lZGlhbiBsaW5lIGFuZCBzaGFkZWQgSVFSIGJhbmQgCmhpc3RvZ3JhbSA8LSBnZ3Bsb3QoTEFfYXR0LCBhZXMoeCA9IExBX21lZGlhbl9wZXJjZW50VGFyZ2V0KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAyMCwgZmlsbCA9ICIjQTI0QkVBIiwgY29sb3IgPSAid2hpdGUiLCBhbHBoYSA9IDAuODUpICsKICAjIFNoYWRlZCBJUVIgYmFuZAogIGFubm90YXRlKCJyZWN0IiwKICAgICAgICAgICB4bWluID0gYXMubnVtZXJpYyhMQV9xMjUpLCB4bWF4ID0gYXMubnVtZXJpYyhMQV9xNzUpLAogICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLAogICAgICAgICAgIGZpbGwgPSAiI0ZGRkYwMCIsIGFscGhhID0gMC41KSArCiAgIyBOYXRpb25hbCBtZWRpYW4gbGluZSArIGxhYmVsCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbmF0aW9uYWxfbWVkaWFuLCBjb2xvciA9ICIjRTQ1NzU2IiwgbGluZXdpZHRoID0gMS4yKSArCiAgYW5ub3RhdGUoImxhYmVsIiwKICAgICAgICAgICB4ID0gbmF0aW9uYWxfbWVkaWFuLCB5ID0gSW5mLCB2anVzdCA9IDEuNSwKICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiTmF0aW9uYWwgbWVkaWFuID0gIiwgcm91bmQobmF0aW9uYWxfbWVkaWFuLCAxKSwgIiUiKSwKICAgICAgICAgICBmaWxsID0gIiMxRjc4QjQiLCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzLjUpICsKICAjIExhYmVscyAmIHRoZW1lCiAgICBsYWJzKCAgICAKICAgICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIExBLWxldmVsIHBob25pY3MgYXR0YWlubWVudCAobWVkaWFucykiLCAgICAKICAgICAgeCA9ICJtZWRpYW5zIiwKICAgICAgeSA9ICJDb3VudCBvZiBMQXMiICApICsgIAogICAgIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9wZXJjZW50KHNjYWxlID0gMSkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKCAKICAgIGJyZWFrcyA9IHNjYWxlczo6YnJlYWtzX3dpZHRoKDIpLCAgCiAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4wNSkpCiAgKSsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKSArCiAgdGhlbWUoICAgIAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwgICAgCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpICAKICAgICkKI3ByaW50ZWQgaGlzdG9ncmFtCnByaW50KGhpc3RvZ3JhbSkKYGBgCgoKYGBge3J9CiNwYXJ0IDE6IDctPmRvdHBsb3Qgb2YgbG9jYWwgYXV0aG9yaXRpZXMKCiMgNy4xKSBDb21wdXRlIG1lZGlhbnMgYXQgTEEsIHJlZ2lvbiwgYW5kIG5hdGlvbgoKI2EpIE9uZSByb2J1c3QgbnVtYmVyIHBlciBMQTogbWVkaWFuIG9mIHBlcmNlbnRUYXJnZXQgYWNyb3NzIGl0cyByb3dzCmxhX21lZCA8LSBkYXRhICU+JQogIGdyb3VwX2J5KGxhTmFtZSwgcmVnaW9uTmFtZSkgJT4lCiAgc3VtbWFyaXNlKGxhX21lZGlhbiA9IG1lZGlhbihwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKI2IpIFJlZ2lvbiBtZWRpYW5zIChhY3Jvc3MgTEFzKQpyZWdpb25fbWVkIDwtIGxhX21lZCAlPiUKICBncm91cF9ieShyZWdpb25OYW1lKSAlPiUKICBzdW1tYXJpc2UocmVnaW9uX21lZGlhbiA9IG1lZGlhbihsYV9tZWRpYW4sIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgojYykgTmF0aW9uYWwgbWVkaWFuIChhY3Jvc3MgTEFzKQpuYXRpb25hbF9tZWRpYW4gPC0gbWVkaWFuKGxhX21lZCRsYV9tZWRpYW4sIG5hLnJtID0gVFJVRSkKCiM3LjIpIFNvcnQgTEFzIGZyb20gbG93ZXN0IHRvIGhpZ2hlc3QgYW5kIGJ1aWxkIHggcG9zaXRpb25zCmxhX3NvcnRlZCA8LSBsYV9tZWQgJT4lCiAgYXJyYW5nZShsYV9tZWRpYW4sIGxhTmFtZSkgJT4lICAgICAgICAgICAgICAgICAgIyB0aWUtYnJlYWsgYnkgbmFtZSBmb3Igc3RhYmlsaXR5CiAgbXV0YXRlKHhfaWR4ID0gcm93X251bWJlcigpKSAgICAgICAgICAgICAgICAgICAgIyB4IHBvc2l0aW9uIGFmdGVyIHNvcnRpbmcKCiMgRm9yIGZhaW50IHJlZ2lvbiByZWZlcmVuY2UgbGluZXMKcmVnaW9uX3NwYW5zIDwtIGxhX3NvcnRlZCAlPiUKICBncm91cF9ieShyZWdpb25OYW1lKSAlPiUKICBzdW1tYXJpc2UoCiAgICB4X21pbiA9IG1pbih4X2lkeCksCiAgICB4X21heCA9IG1heCh4X2lkeCksCiAgICByZWdpb25fbWVkaWFuID0gbWVkaWFuKGxhX21lZGlhbiwgbmEucm0gPSBUUlVFKSwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApCmBgYAoKCmBgYHtyfQojIHBhcnQgMTogOC0+IERvdCBwbG90ICjigJxjYXRlcnBpbGxhcuKAnSkgZmlndXJlIChub3QgdXNlZCBpbiByZXBvcnQpCgpkb3RwbG90PC0gZ2dwbG90KGxhX3NvcnRlZCwgYWVzKHggPSB4X2lkeCwgeSA9IGxhX21lZGlhbikpICsKICAjIE5hdGlvbmFsIG1lZGlhbiAoYm9sZCBsaW5lIGFjcm9zcyBlbnRpcmUgcGFuZWwpCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbmF0aW9uYWxfbWVkaWFuLCBjb2xvciA9ICIjRTQ1NzU2IiwgbGluZXdpZHRoID0gMC45KSArCgogICMgRG90cyBmb3IgZWFjaCBMQSwgY29sb3JlZCBieSByZWdpb24gKG9wdGlvbmFsKQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcmVnaW9uTmFtZSksIHNpemUgPSAyLjIsIGFscGhhID0gMC45KSArCgogICMgQXhlcyAmIGxhYmVscwogIHNjYWxlX3hfY29udGludW91cygKICAgIGJyZWFrcyA9IE5VTEwsICAgICAgICAgICAgICAgICAgICAgICMgaGlkZSB0aWNrIGxhYmVscyAodG9vIG1hbnkgTEFzKQogICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMDEsIDAuMDEpKQogICkgKwogIHNjYWxlX3lfY29udGludW91cygKICAgIGxpbWl0cyA9IGMoMCwgMTAwKSwKICAgIGJyZWFrcyA9IHNlcSgzMCwgMTAwLCBieSA9IDEwKQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJMb2NhbCBBdXRob3JpdHkgcGhvbmljcyBhdHRhaW5tZW50IChMQSBtZWRpYW5zLCBzb3J0ZWQgbG93IOKGkiBoaWdoKSIsCiAgICBzdWJ0aXRsZSA9ICJEb3RzID0gTEEgbWVkaWFuczsgcmVkIGxpbmUgPSBuYXRpb25hbCBtZWRpYW4iLAogICAgeCA9ICJMb2NhbCBBdXRob3JpdGllcyAoc29ydGVkKSIsCiAgICB5ID0gIkxBIG1lZGlhbiAlIGF0IGV4cGVjdGVkIHN0YW5kYXJkIiwKICAgIGNvbG9yID0gIlJlZ2lvbiIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCnByaW50KGRvdHBsb3QpCmBgYAoKYGBge3J9CiNQYXJ0IDE6IDktPiBib3hwbG90IHNob3dpbmcgc2V4IGFjcm9zcyByZWdpb25zCgojIE9uZSBwYW5lbCB3aXRoIHJlZ2lvbnMgb24gdGhlIHgtYXhpczsgc2lkZS1ieS1zaWRlIGJveGVzIGZvciBHaXJscy9Cb3lzLgpib3hwbG90X3JlZ2lvbnMgPC0gZ2dwbG90KGRhdGEgLCBhZXMoeCA9IHJlZ2lvbk5hbWUsIHkgPSBwZXJjZW50VGFyZ2V0LCBmaWxsID0gc2V4KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLmFscGhhID0gMC4yNSwgd2lkdGggPSAwLjcsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjc1KSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkdpcmxzIiA9ICIjQTI0QkVBIiwgIkJveXMiID0gIiMxRjc4QjQiKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQaG9uaWNzIGF0dGFpbm1lbnQgYnkgc2V4IGFjcm9zcyByZWdpb25zIiwKICAgIHggPSAiUmVnaW9uIiwKICAgIHkgPSAiJSBhdCBleHBlY3RlZCBzdGFuZGFyZCIsCiAgICBmaWxsID0gIlNleCIKICApICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoc2NhbGUgPSAxKSwgbGltaXRzID0gYygwLCAxMDApKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMSkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpCiAgKQpwcmludChib3hwbG90X3JlZ2lvbnMpCmBgYAoKCgpgYGB7cn0KI1BhcnQgMToxMC0+IGhlYXRtYXA6IHNleCB4IEZTTSAtPiBieSByZWdpb24KcmVnaW9uX21hcCA8LSBkYXRhICU+JQogIGdyb3VwX2J5KHJlZ2lvbk5hbWUsIHNleCwgZnNtU3RhdHVzKSAlPiUKICBzdW1tYXJpc2UobWVkaWFuX2F0dGFpbiA9IG1lZGlhbihwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKaGVhdG1hcCA8LSBnZ3Bsb3QocmVnaW9uX21hcCwgYWVzKHggPSBzZXgsIHkgPSBmc21TdGF0dXMsIGZpbGwgPSBtZWRpYW5fYXR0YWluKSkgKwogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIsIGxpbmV3aWR0aCA9IDAuNikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQobWVkaWFuX2F0dGFpbiwgMSksICIlIikpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLjIpICsKICBmYWNldF93cmFwKH4gcmVnaW9uTmFtZSwgbmNvbCA9IDQpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICIjRkRFNzI1IiwgaGlnaCA9ICIjMkM3RkI4IiwgbGltaXRzID0gYygwLCAxMDApLCBuYW1lID0gIk1lZGlhbiAlIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJTZXggw5cgRlNNIGhlYXRtYXAgYnkgcmVnaW9uIChtZWRpYW4gJSBhdCBleHBlY3RlZCBzdGFuZGFyZCkiLAogICAgeCA9ICJTZXgiLAogICAgeSA9ICJGU00gc3RhdHVzIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gOCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpCiAgKQoKIyBEaXNwbGF5OgpwcmludChoZWF0bWFwKQpgYGAKCmBgYHtyfQojcGFydCAxYTogb3ZlcnZpZXcgb2YgcGhvbmljcyBhdHRhaW5tZW50IGJ5IHNleAoKIzEpIGZpbHRlcmluZyBmb3Igc2V4CnNleF9kYXRhIDwtIGRhdGEgJT4lCiAgZmlsdGVyKHRpbWVQZXJpb2QgPT0gIjIwMjQyNSIpICU+JQogIHNlbGVjdChzZXgsIHBlcmNlbnRUYXJnZXQpICU+JQogIGZpbHRlcighIGlzLm5hKHBlcmNlbnRUYXJnZXQpKQoKIzIpIGNoZWNraW4gc2FtcGxlIHNpemUgZm9yIGFzc3VtcHRpb25zCnRhYmxlKHNleF9kYXRhJHNleCkKCiMzKSBhc3N1bXB0aW9uIG9uZTogU2hhcGlyby1XaWxrIChub3JtYWxpdHkvbm9ybWFsIGRpc3RyaWJ1dGlvbikgLT4gdmlvbGF0ZWQKYnkoc2V4X2RhdGEkcGVyY2VudFRhcmdldCwgc2V4X2RhdGEkc2V4LCBzaGFwaXJvLnRlc3QpCgojNCkgYXNzdW1wdGlvbiB0d286IExldmVuZSdzIFRlc3QgKGhvbW9nZW5pdHkgb2YgdmFyaWVuY2UpIC0+IHZpb2xhdGVkCmxldmVuZVRlc3QocGVyY2VudFRhcmdldCB+IHNleCwgZGF0YSA9IHNleF9kYXRhKQoKIzUpIGRvdWJsZSBjaGVja2luZyBsYWJlbHMgaW4gInNleCIgCmxldmVscyhmYWN0b3Ioc2V4X2RhdGEkc2V4KSkKCiNLcnVza2FsLVdhbGxpcyAoYW55IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXM/KSAtPiB5ZXMKa3J1c2thbC50ZXN0KHBlcmNlbnRUYXJnZXQgfiBzZXgsIGRhdGEgPSBzZXhfZGF0YSkKCiNQb3N0LWhvYyBEdW5uJ3MgdGVzdApkdW5uVGVzdChwZXJjZW50VGFyZ2V0IH4gc2V4LCBkYXRhID0gc2V4X2RhdGEsIG1ldGhvZCA9ICJib25mZXJyb25pIikKCiM4KSBjb2xvcnMgZm9yIGJveHBsb3QKcGFsX2ZpbGwgPC0gYygiR2lybHMiID0gIiNBMjRCRUEiLCAiQm95cyIgPSAiIzFGNzhCNCIpICAjZmlsbCBjb2xvcnMgZm9yIGJveGVzCgojOSkgY3JlYXRpbmcgYm94cGxvdApnZ3Bsb3Qoc2V4X2RhdGEsIGFlcyh4PSBzZXgsIHkgPSBwZXJjZW50VGFyZ2V0LCBmaWxsPSBzZXgpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgYWxwaGEgPSAwLjcpICsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIHNoYXBlID0gMjMsIHNpemUgPSAzLCBmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gcm91bmQoLi55Li4sIDEpKSwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgdmp1c3QgPSArMS44LCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbF9maWxsKSArICAKICBsYWJzKHRpdGxlID0gIkVuZ2xhbmQ6IFBob25pY3MgQXR0YWlubWVudCBieSBTZXgiLAogICAgICAgc3VidGl0bGUgPSAicCB2YWx1ZSA8IDIuMmUtMTYiLAogICAgICAgeCA9ICJTZXgiLAogICAgICAgeT0gIlBob25pY3MgQXR0YWlubWVudCIpICsKICB0aGVtZV9taW5pbWFsKCkKCgojbWVkaWFucyBmb3IgYm95cyBhbmQgZ2lybHMKbWVkX2J5X3NleCA8LSB0YXBwbHkoc2V4X2RhdGEkcGVyY2VudFRhcmdldCwgc2V4X2RhdGEkc2V4LCBtZWRpYW4sIG5hLnJtID0gVFJVRSkKbWVkX2J5X3NleAoKYGBgCgpgYGB7cn0KI3BhcnQgMWI6IG92ZXJ2aWV3IHBob25pY3MgYXR0YWlubWVudCBieSBGU00tU3RhdHVzCgojMSkgZmlsdGVyaW5nIGZvciBGU01TdGF0dXMKZnNtX2RhdGEgPC0gZGF0YSAlPiUKICBmaWx0ZXIodGltZVBlcmlvZCA9PSAiMjAyNDI1IikgJT4lCiAgc2VsZWN0KGZzbVN0YXR1cywgcGVyY2VudFRhcmdldCkgJT4lCiAgZmlsdGVyKCEgaXMubmEocGVyY2VudFRhcmdldCkpCgojMikgY2hlY2tpbmcgbGV2ZWxzCmxldmVscyhmc21fZGF0YSRmc21TdGF0dXMpCgojMykgYXNzdW1wdGlvbiBvbmU6IFNoYXBpcm8tV2lsayAobm9ybWFsaXR5L25vcm1hbCBkaXN0cmlidXRpb24pIC0+IHZpb2xhdGVkCmJ5KGZzbV9kYXRhJHBlcmNlbnRUYXJnZXQsIGZzbV9kYXRhJGZzbVN0YXR1cywgc2hhcGlyby50ZXN0KQoKIzQpIGFzc3VtcHRpb24gdHdvOiBMZXZlbmUncyBUZXN0IChob21vZ2VuaXR5IG9mIHZhcmllbmNlKSAtPiB2aW9sYXRlZApsZXZlbmVUZXN0KHBlcmNlbnRUYXJnZXQgfiBmc21TdGF0dXMsIGRhdGEgPSBmc21fZGF0YSkKCiNLcnVza2FsLVdhbGxpcyAoYW55IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXM/KSAtPiB5ZXMKa3J1c2thbC50ZXN0KHBlcmNlbnRUYXJnZXQgfiBmc21TdGF0dXMsIGRhdGEgPSBmc21fZGF0YSkKCiNQb3N0LWhvYyBEdW5uJ3MgdGVzdCAod2hlcmUgaXMgdGhlIGRpZmZlcmVuY2U/KSAtPiAKZHVublRlc3QocGVyY2VudFRhcmdldCB+IGZzbVN0YXR1cywgZGF0YSA9IGZzbV9kYXRhLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpCiMzKSBjb2xvcnMgZm9yIGJveHBsb3QKcGFsX2ZpbGwgPC0gYygiRlNNIGVsaWdpYmxlIiA9ICIjQTI0QkVBIiwgIk5vdCBrbm93biB0byBiZSBGU00gZWxpZ2libGUiID0gIiMxRjc4QjQiKSAgCgojOCkgY3JlYXRpbmcgYm94cGxvdApnZ3Bsb3QoZnNtX2RhdGEsIGFlcyh4PSBmc21TdGF0dXMsIHkgPSBwZXJjZW50VGFyZ2V0LCBmaWxsPSBmc21TdGF0dXMpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgYWxwaGEgPSAwLjcpICsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIHNoYXBlID0gMjMsIHNpemUgPSAzLCBmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gcm91bmQoLi55Li4sIDEpKSwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgdmp1c3QgPSArMS44LCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbF9maWxsKSArICAKICBsYWJzKHRpdGxlID0gIkVuZ2xhbmQ6IFBob25pY3MgQXR0YWlubWVudCBieSBGU00tU3RhdHVzIiwKICAgICAgIHN1YnRpdGxlID0gInAgdmFsdWUgPCAyLjJlLTE2IiwKICAgICAgIHggPSAiRlNNLVN0YXR1cyIsCiAgICAgICB5PSAiUGhvbmljcyBBdHRhaW5tZW50IikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCmBgYHtyfQojcGFydCAxYzogY29ycmVsYXRpb24gYmV0d2VlbiBwZXJjZW50RlNNIGFuZCBwaG9uaWNzIGF0dGFpbm1lbnQKCiMxKSBjb3JyZWxhdGlvbiB0ZXN0aW5nIChwZXJzb24ncyByKQpjb3IudGVzdChkYXRhJHBlcmNlbnRUYXJnZXQsIGRhdGEkcGVyY2VudEZTTSwgbWV0aG9kID0gInBlYXJzb24iKQpjb3IoZGF0YSRwZXJjZW50VGFyZ2V0LCBkYXRhJHBlcmNlbnRGU00sIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQojLT4gcmV2ZWFsZWQ6IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYnV0IG5lZ2xpZ2FibGUgcmVsYXRpb25zaGlwIGFuZCBwZXJjZW50RlNNIGlzIG5vdCBhIG1lYW5pbmdmdWwgcHJlZGljYXRvcgoKI3NjYXR0ZXJwbG90OgpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBwZXJjZW50RlNNLCB5ID0gcGVyY2VudFRhcmdldCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC40KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFKSArCiAgbGFicygKICAgIHggPSAiUGVyY2VudGFnZSBvZiBwdXBpbHMgZWxpZ2libGUgZm9yIEZTTSIsCiAgICB5ID0gIlBlcmNlbnRhZ2UgbWVldGluZyBwaG9uaWNzIHRhcmdldCIsCiAgICB0aXRsZSA9ICJDb3JyZWxhdGlvbiBiZXR3ZWVuIEZTTSBlbGlnaWJpbGl0eSBhbmQgcGhvbmljcyBhdHRhaW5tZW50IgogICkKYGBgCgoKYGBge3J9CiNwYXJ0IDFkOiBvdmVydmlldyBwaG9uaWNzIGF0dGFpbm1lbnQgYnkgZXRobmljaXR5IG1ham9yCgojMSkgZmlsdGVyaW5nIGZvciBldGhuaWNpdHkgbWFqb3IKZXRoX2RhdGFfbWEgPC0gZGF0YSAlPiUKICBmaWx0ZXIodGltZVBlcmlvZCA9PSAiMjAyNDI1IikgJT4lCiAgc2VsZWN0KGV0aG5pY2l0eU1ham9yLCBwZXJjZW50VGFyZ2V0KSAlPiUKICBmaWx0ZXIoISBpcy5uYShwZXJjZW50VGFyZ2V0KSkKCiMyKSBjaGVja2luZyBsZXZlbHMKbGV2ZWxzKGV0aF9kYXRhX21hJGV0aG5pY2l0eU1ham9yKQoKIzMpIGNvbG9ycyBmb3IgYm94cGxvdApwYWxfZmlsbCA8LSBjKCJBc2lhbiAvIEFzaWFuIEJyaXRpc2giID0gIiNBMjRCRUEiLCAiQmxhY2sgLyBBZnJpY2FuIC8gQ2FyaWJiZWFuIC8gQmxhY2sgQnJpdGlzaCIgPSAiIzFGNzhCNCIsICJXaGl0ZSIgPSAiI0ZGNjlCNCIsICJNaXhlZCAvIE11bHRpcGxlIGV0aG5pYyBncm91cHMiID0gIiNGRkZGMDAiLCAiT3RoZXIgZXRobmljIGdyb3VwIiA9ICIjMDA4MDAwIiApCgojNCkgY3JlYXRpbmcgYm94cGxvdApnZ3Bsb3QoZXRoX2RhdGFfbWEsIGFlcyh4PSBldGhuaWNpdHlNYWpvciwgeSA9IHBlcmNlbnRUYXJnZXQsIGZpbGw9IGV0aG5pY2l0eU1ham9yKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gMC43KSArCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBzaGFwZSA9IDIzLCBzaXplID0gMywgZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGdlb20gPSAidGV4dCIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHJvdW5kKC4ueS4uLCAxKSksICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHZqdXN0ID0gKzEuOCwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxfZmlsbCkgKyAgCiAgbGFicyh0aXRsZSA9ICJFbmdsYW5kOiBQaG9uaWNzIEF0dGFpbm1lbnQgYnkgbWFqb3IgZXRobmljaXRpZXMiLAogICAgICAgeCA9ICJNYWpvciBFdGhuaWNpdHkiLAogICAgICAgeT0gIlBob25pY3MgQXR0YWlubWVudCIpICsKdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSA1LjUpCgojdGFibGUgb2YgbWVkaWFucwoKZXRoX2RhdGFfbWEgJT4lCiAgZ3JvdXBfYnkoZXRobmljaXR5TWFqb3IpICU+JQogIHN1bW1hcmlzZShtZWRpYW5fdmFsdWUgPSBtZWRpYW4ocGVyY2VudFRhcmdldCkpCgpgYGAKCmBgYHtyfQojcGFydCAxZTogb3ZlcnZpZXcgcGhvbmljcyBhdHRhaW5tZW50IGJ5IGV0aG5pY2l0eSAobWlub3IpCgojMSkgZmlsdGVyaW5nIGZvciBtaW5vciBldGhuaWNpdGVzCmV0aF9kYXRhX21pIDwtIGRhdGEgJT4lCiAgZmlsdGVyKHRpbWVQZXJpb2QgPT0gIjIwMjQyNSIpICU+JQogIHNlbGVjdChldGhuaWNpdHlNaW5vciwgcGVyY2VudFRhcmdldCkgJT4lCiAgZmlsdGVyKCEgaXMubmEocGVyY2VudFRhcmdldCkpCgojMikgY2hlY2tpbmcgbGV2ZWxzCmxldmVscyhldGhfZGF0YV9taSRldGhuaWNpdHlNaW5vcikKCmBgYAoKCmBgYHtyfQojcGFydCAxZS4xOiBvdmVydmlldyBwaG9uaWNzIGF0dGFpbm1lbnQgYnkgbWlub3IgQXNpYW4gZXRobmljaXRpZXMKCiMxKSBmaWx0ZXJpbmcgZm9yIGFsbCBhc2lhbnMKYXNpYW5fY2F0ZWdvcmllcyA8LSBjKCAiQmFuZ2xhZGVzaGkiLCAiQ2hpbmVzZSIsICJQYWtpc3RhbmkiLCAiR3lwc3kiLCAiQW55IG90aGVyIEFzaWFuIGJhY2tncm91bmQiLCAiSW5kaWFuIiwgIldoaXRlIGFuZCBBc2lhbiIpCgphc2lhbl9taW5vciA8LSBldGhfZGF0YV9taSAlPiUKICBmaWx0ZXIoZXRobmljaXR5TWlub3IgJWluJSBhc2lhbl9jYXRlZ29yaWVzKQoKIzIpIGNvbG9ycyBmb3IgYm94cGxvdApwYWxfZmlsbCA8LSBjKCJCYW5nbGFkZXNoaSIgPSAiI0EyNEJFQSIsICJDaGluZXNlIiA9ICIjMUY3OEI0IiwgIlBha2lzdGFuaSIgPSAiI0ZGNjlCNCIsICJJbmRpYW4iID0gIiNGRkZGMDAiLCAiR3lwc3kiID0gIiMwMDgwMDAiLCAiQW55IG90aGVyIEFzaWFuIGJhY2tncm91bmQiID0gIiNGRjAwMDAiLCAiV2hpdGUgYW5kIEFzaWFuIiA9ICIjOTY0QjAwIiApCgojNCkgY3JlYXRpbmcgYm94cGxvdApnZ3Bsb3QoYXNpYW5fbWlub3IsIGFlcyh4PSBldGhuaWNpdHlNaW5vciwgeSA9IHBlcmNlbnRUYXJnZXQsIGZpbGw9IGV0aG5pY2l0eU1pbm9yKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gMC43KSArCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBzaGFwZSA9IDIzLCBzaXplID0gMywgZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGdlb20gPSAidGV4dCIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHJvdW5kKC4ueS4uLCAxKSksICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHZqdXN0ID0gKzEuOCwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxfZmlsbCkgKyAgCiAgbGFicyh0aXRsZSA9ICJFbmdsYW5kOiBQaG9uaWNzIEF0dGFpbm1lbnQgYnkgbWlub3IgQXNpYW4gZXRobmljaXRpZXMiLAogICAgICAgeCA9ICJNaW5vciBBc2lhbiBFdGhuaWNpdHkiLAogICAgICAgeT0gIlBob25pY3MgQXR0YWlubWVudCIpICsKdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSA3KQoKYGBgCgpgYGB7cn0KI3BhcnQgMWUuMjogb3ZlcnZpZXcgcGhvbmljcyBhdHRhaW5tZW50IGJ5IG1pbm9yIFdoaXRlIGV0aG5pY2l0aWVzCgojMSkgZmlsdGVyaW5nIGZvciBhbGwgd2hpdGVzCndoaXRlX2NhdGVnb3JpZXMgPC0gYygiRW5nbGlzaCAvIFdlbHNoIC8gU2NvdHRpc2ggLyBOb3J0aGVybiBJcmlzaCAvIEJyaXRpc2giLCAiSXJpc2giLCAiSXJpc2ggVHJhdmVsbGVyIiwgIkFueSBvdGhlciBXaGl0ZSBCYWNrZ3JvdW5kIikKCndoaXRlX21pbm9yIDwtIGV0aF9kYXRhX21pICU+JQogIGZpbHRlcihldGhuaWNpdHlNaW5vciAlaW4lIHdoaXRlX2NhdGVnb3JpZXMpCgojMikgY29sb3JzIGZvciBib3hwbG90CnBhbF9maWxsIDwtIGMoIklyaXNoIiA9ICIjQTI0QkVBIiwgIklyaXNoIFRyYXZlbGxlciIgPSAiIzFGNzhCNCIsICJBbnkgb3RoZXIgV2hpdGUgQmFja2dyb3VuZCIgPSAiI0ZGNjlCNCIsICJFbmdsaXNoIC8gV2Vsc2ggLyBTY290dGlzaCAvIE5vcnRoZXJuIElyaXNoIC8gQnJpdGlzaCIgPSAiI0ZGRkYwMCIgKQoKIzQpIGNyZWF0aW5nIGJveHBsb3QKZ2dwbG90KHdoaXRlX21pbm9yLCBhZXMoeD0gZXRobmljaXR5TWlub3IsIHkgPSBwZXJjZW50VGFyZ2V0LCBmaWxsPSBldGhuaWNpdHlNaW5vcikpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBhbHBoYSA9IDAuNykgKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCBnZW9tID0gInBvaW50Iiwgc2hhcGUgPSAyMywgc2l6ZSA9IDMsIGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBnZW9tID0gInRleHQiLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBhZXMobGFiZWwgPSByb3VuZCguLnkuLiwgMSkpLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICB2anVzdCA9ICsxLjgsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsX2ZpbGwpICsgIAogIGxhYnModGl0bGUgPSAiRW5nbGFuZDogUGhvbmljcyBBdHRhaW5tZW50IGJ5IG1pbm9yIFdoaXRlIGV0aG5pY2l0aWVzIiwKICAgICAgIHggPSAiTWlub3IgV2hpdGUgRXRobmljaXR5IiwKICAgICAgIHk9ICJQaG9uaWNzIEF0dGFpbm1lbnQiKSArCnRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gNykKYGBgCgpgYGB7cn0KI3BhcnQgMWUuMzogb3ZlcnZpZXcgcGhvbmljcyBhdHRhaW5tZW50IGJ5IG1pbm9yIEJsYWNrIGV0aG5pY2l0aWVzCgojMSkgZmlsdGVyaW5nIGZvciBhbGwgYmxhY2tzCmJsYWNrX2NhdGVnb3JpZXMgPC0gYygiQ2FyaWJiZWFuIiwgIkFmcmljYW4iLCAiV2hpdGUgYW5kIEJsYWNrIEFmcmljYW4iLCAiQW55IG90aGVyIEJsYWNrIC8gQWZyaWNhbiAvIENhcmliYmVhbiBiYWNrZ3JvdW5kIiwgIldoaXRlIGFuZCBCbGFjayBDYXJpYmJlYW4iKQoKYmxhY2tfbWlub3IgPC0gZXRoX2RhdGFfbWkgJT4lCiAgZmlsdGVyKGV0aG5pY2l0eU1pbm9yICVpbiUgYmxhY2tfY2F0ZWdvcmllcykKCiMyKSBjb2xvcnMgZm9yIGJveHBsb3QKcGFsX2ZpbGwgPC0gYygiQ2FyaWJiZWFuIiA9ICIjQTI0QkVBIiwgIkFmcmljYW4iID0gIiMxRjc4QjQiLCAiV2hpdGUgYW5kIEJsYWNrIEFmcmljYW4iID0gIiNGRjY5QjQiLCAiV2hpdGUgYW5kIEJsYWNrIENhcmliYmVhbiIgPSAiI0ZGRkYwMCIsICJBbnkgb3RoZXIgQmxhY2sgLyBBZnJpY2FuIC8gQ2FyaWJiZWFuIGJhY2tncm91bmQiID0gIiNGRjAwMDAiKQoKIzQpIGNyZWF0aW5nIGJveHBsb3QKZ2dwbG90KGJsYWNrX21pbm9yLCBhZXMoeD0gZXRobmljaXR5TWlub3IsIHkgPSBwZXJjZW50VGFyZ2V0LCBmaWxsPSBldGhuaWNpdHlNaW5vcikpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBhbHBoYSA9IDAuNykgKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCBnZW9tID0gInBvaW50Iiwgc2hhcGUgPSAyMywgc2l6ZSA9IDMsIGZpbGwgPSJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHJvdW5kKC4ueS4uLCAxKSksICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHZqdXN0ID0gKzEuOCwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxfZmlsbCkgKyAgCiAgbGFicyh0aXRsZSA9ICJFbmdsYW5kOiBQaG9uaWNzIEF0dGFpbm1lbnQgYnkgbWlub3IgQmxhY2sgZXRobmljaXRpZXMiLAogICAgICAgeCA9ICJNaW5vciBCbGFjayBFdGhuaWNpdHkiLAogICAgICAgeT0gIlBob25pY3MgQXR0YWlubWVudCIpICsKdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSA2KQpgYGAKCmBgYHtyfQojcGFydCAyYTogbG9jYWwgYXV0aG9yaXRpZXMKCiNmaWx0ZXIgZm9yIG9ubHkgdGhvc2UgMwpkYXQzIDwtIGRhdGEgJT4lCiAgZmlsdGVyKGxhTmFtZSAlaW4lIGMoIlJpY2htb25kIHVwb24gVGhhbWVzIiwgIldlc3QgU3Vzc2V4IiwgIkxld2lzaGFtIikpCgojZmlsdGVyaW5nIGZvciBvbmx5IHBob25pY3MgYXR0YWlubWVudCBzY29yZSAocGVyY2VudFRhcmdldCkKZGF0MyA8LSBkYXQzICU+JQogIHNlbGVjdChsYU5hbWUsIHBlcmNlbnRUYXJnZXQpICU+JQogIGZpbHRlcighIGlzLm5hKHBlcmNlbnRUYXJnZXQpKQoKI2hvdyBtYW55IHJvd3MgZm9yIGVhY2ggYXV0aG9yaXR5Pwp0YWJsZShkYXQzJGxhTmFtZSkKCiNjaGVja2luZyBhc3N1bXB0aW9uczogU2hhcGlyby1XaWxrIChub3JtYWwgZGlzdHJpYnV0aW9uKSAtPiB2aW9sYXRlZCAoTGV3ICYgUmljaDogcDwwLjA1KQpieShkYXQzJHBlcmNlbnRUYXJnZXQsIGRhdDMkbGFOYW1lLCBzaGFwaXJvLnRlc3QpCgojY2hlY2tpbmcgYXNzdW1wdGlvbnM6IExldmVuZSdzIHRlc3QgKGhvbW9nZW5pdHkgb2YgdmFyaWFuY2UpIC0+IHZpb2xhdGVkIApsZXZlbmVUZXN0KHBlcmNlbnRUYXJnZXQgfiBsYU5hbWUsIGRhdGEgPSBkYXQzLCBjZW50ZXIgPSBtZWRpYW4pCgojS3J1c2thbC1XYWxsaXMgKGFueSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzPykgLT4geWVzLCBwPDAuMDUKa3J1c2thbC50ZXN0KHBlcmNlbnRUYXJnZXQgfiBsYU5hbWUsIGRhdGEgPSBkYXQzKQoKI1Bvc3QtaG9jIER1bm4ncyB0ZXN0ICh3aGVyZSBpcyB0aGUgZGlmZmVyZW5jZT8pIC0+IApkdW5uVGVzdChwZXJjZW50VGFyZ2V0IH4gbGFOYW1lLCBkYXRhID0gZGF0MywgbWV0aG9kID0gImJvbmZlcnJvbmkiKQpgYGAKCmBgYHtyfQojcGFydCAyYjogbG93ZXN0IHJhbmtpbmcgbG9jYWwgYXV0aG9yaXR5CgojaWRlbnRpZnlpbmcgKGNhbGN1bGF0aW5nIG1lYW4pIC0+IFdFU1QgU1VTU0VYCmRhdDMgJT4lCiAgZ3JvdXBfYnkobGFOYW1lKSAlPiUKICBzdW1tYXJpc2UobWVhbl9wZXJjZW50ID0gbWVhbihwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKG1lYW5fcGVyY2VudCkKYGBgCgoKYGBge3J9CiNwYXJ0IDJiLjE6IGFuYWx5c2lzIG9mIHRoZSBmYWN0b3Igc2V4CgojMSkgZmlsdGVyaW5nIGZvciBXUwp3c19kYXRhIDwtIGRhdGEgJT4lCiAgZmlsdGVyKGxhTmFtZSA9PSAiV2VzdCBTdXNzZXgiKSAlPiUKICBzZWxlY3Qoc2V4LCBwZXJjZW50VGFyZ2V0KSAlPiUKICBmaWx0ZXIoISBpcy5uYShwZXJjZW50VGFyZ2V0KSkKCiMyKSBjaGVja2luIHNhbXBsZSBzaXplIGZvciBhc3N1bXB0aW9ucwp0YWJsZSh3c19kYXRhJHNleCkKCiMzKSBhc3N1bXB0aW9uIG9uZTogU2hhcGlyby1XaWxrIChub3JtYWxpdHkvbm9ybWFsIGRpc3RyaWJ1dGlvbikgLT4gY29uZmlybWVkCmJ5KHdzX2RhdGEkcGVyY2VudFRhcmdldCwgd3NfZGF0YSRzZXgsIHNoYXBpcm8udGVzdCkKCiM0KSBhc3N1bXB0aW9uIHR3bzogTGV2ZW5lJ3MgVGVzdCAoaG9tb2dlbml0eSBvZiB2YXJpZW5jZSkKbGV2ZW5lVGVzdChwZXJjZW50VGFyZ2V0IH4gc2V4LCBkYXRhID0gd3NfZGF0YSkKCiM1KSBkb3VibGUgY2hlY2tpbmcgbGFiZWxzIGluICJzZXgiIGZvciBpbmRlcGVuZGVudCBUIHRlc3QKbGV2ZWxzKGZhY3Rvcih3c19kYXRhJHNleCkpCgojNikgcnVubmluZyBpbmRlcGVuZGVudCB0IHRlc3QKdHRfd3MgPC0gdC50ZXN0KHBlcmNlbnRUYXJnZXQgfiBzZXgsIGRhdGEgPSB3c19kYXRhLCB2YXIuZXF1YWwgPSBUUlVFKQoKIzcpIHByaW50aW5nIHJlc3VsdHMKdHRfd3MKCiM5KSBjb2xvcnMgZm9yIGJveHBsb3QKcGFsX2ZpbGwgPC0gYygiR2lybHMiID0gIiNBMjRCRUEiLCAiQm95cyIgPSAiIzFGNzhCNCIpICAjZmlsbCBjb2xvcnMgZm9yIGJveGVzCnBhbF9wb2ludCA8LSBjKCJHaXJscyIgPSAiIzdBMUZEMiIsICJCb3lzIiA9ICIjMEU1RDkxIikgICNjb2xvcnMgZm9yIGppdHRlciAKCiM4KSBjcmVhdGluZyBib3hwbG90CmdncGxvdCh3c19kYXRhLCBhZXMoeD0gc2V4LCB5ID0gcGVyY2VudFRhcmdldCwgZmlsbD0gc2V4KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gMC43KSArCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gc2V4KSwgd2lkdGggPSAwLjE1LCBhbHBoYSA9IDAuNiwgc2l6ZSA9IDIpKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCBnZW9tID0gInBvaW50Iiwgc2hhcGUgPSAyMywgc2l6ZSA9IDMsIGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBnZW9tID0gInRleHQiLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBhZXMobGFiZWwgPSByb3VuZCguLnkuLiwgMSkpLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICB2anVzdCA9ICsxLjcsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsX2ZpbGwpICsgIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWxfcG9pbnQpICsKICBsYWJzKHRpdGxlID0gIldlc3QgU3Vzc2V4OiBQaG9uaWNzIEF0dGFpbm1lbnQgYnkgU2V4IiwKICAgICAgIHN1YnRpdGxlID0gIip3aGl0ZSBkaWFtb25kIG1hcmtlciA9IG1lYW47IHAgPSAwLjA0IiwKICAgICAgIHggPSAiU2V4IiwKICAgICAgIHk9ICJQaG9uaWNzIEF0dGFpbm1lbnQiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojOSkgaGVhdG1hcCBmc20geCBzZXggaW4gV2VzdCBTdXNzZXgKCndzX3NleF9mc21fbWFwIDwtIGRhdGEgJT4lCiAgZmlsdGVyKGxhTmFtZSA9PSAiV2VzdCBTdXNzZXgiKSAlPiUKICBncm91cF9ieShsYU5hbWUsIHNleCwgZnNtU3RhdHVzKSAlPiUKICBzdW1tYXJpc2UobWVkaWFuX2F0dGFpbiA9IG1lZGlhbihwZXJjZW50VGFyZ2V0LCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKZ2dwbG90KHdzX3NleF9mc21fbWFwLCBhZXMoeCA9IHNleCwgeSA9IGZzbVN0YXR1cywgZmlsbCA9IG1lZGlhbl9hdHRhaW4pKSArCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIiwgbGluZXdpZHRoID0gMC42KSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChtZWRpYW5fYXR0YWluLCAxKSwgIiUiKSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMuMikgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIiNGREU3MjUiLCBoaWdoID0gIiMyQzdGQjgiLCBsaW1pdHMgPSBjKDAsIDEwMCksIG5hbWUgPSAiTWVkaWFuICUiKSArCiAgbGFicygKICAgIHRpdGxlID0gIldlc3QgU3Vzc2V4OiBTZXggw5cgRlNNIGhlYXRtYXAgKG1lZGlhbiAlIGF0IGV4cGVjdGVkIHN0YW5kYXJkKSIsCiAgICB4ID0gIlNleCIsCiAgICB5ID0gIkZTTSBzdGF0dXMiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSA4KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikKICApCgpgYGAKCmBgYHtyfQojUGFydCAyYi4yOiBBbmFseXNpcyBvZiB0aGUgZmFjdG9yIEZTTSBTdGF0dXMKCiMxKSBmaWx0ZXJpbmcgZm9yIGZzbS1TdGF0dXMgaW4gV1MKd3NfZGF0YV9mc20gPC0gZGF0YSAlPiUKICBmaWx0ZXIobGFOYW1lID09ICJXZXN0IFN1c3NleCIpICU+JQogIHNlbGVjdChmc21TdGF0dXMsIHBlcmNlbnRUYXJnZXQpICU+JQogIGZpbHRlcighIGlzLm5hKHBlcmNlbnRUYXJnZXQpKQoKIzIpIGNoZWNraW4gc2FtcGxlIHNpemUgZm9yIGFzc3VtcHRpb25zCnRhYmxlKHdzX2RhdGFfZnNtJGZzbVN0YXR1cykKCiMzKSBhc3N1bXB0aW9uIG9uZTogU2hhcGlyby1XaWxrIChub3JtYWxpdHkvbm9ybWFsIGRpc3RyaWJ1dGlvbikgLT4gdmlvbGF0ZWQKYnkod3NfZGF0YV9mc20kcGVyY2VudFRhcmdldCwgd3NfZGF0YV9mc20kZnNtU3RhdHVzLCBzaGFwaXJvLnRlc3QpCgojNCkgYXNzdW1wdGlvbiB0d286IExldmVuZSdzIFRlc3QgKGhvbW9nZW5pdHkgb2YgdmFyaWVuY2UpIC0+IHVwaGVsZApsZXZlbmVUZXN0KHBlcmNlbnRUYXJnZXQgfiBmc21TdGF0dXMsIGRhdGEgPSB3c19kYXRhX2ZzbSkKCiM1KSBNYW5uLVdoaXRuZXkgVSBUZXN0IChzaW5jZSBhc3N1bXB0aW9ucyB2aW9sYXRlZCkKd2lsY294LnRlc3QocGVyY2VudFRhcmdldCB+IGZzbVN0YXR1cywgZGF0YSA9IHdzX2RhdGFfZnNtLCBleGFjdCA9IEZBTFNFKQoKIzkpIGNvbG9ycyBmb3IgYm94cGxvdApwYWxfZmlsbCA8LSBjKCJGU00gZWxpZ2libGUiID0gIiNBMjRCRUEiLCAiTm90IGtub3duIHRvIGJlIEZTTSBlbGlnaWJsZSIgPSAiIzFGNzhCNCIpICAjZmlsbCBjb2xvcnMgZm9yIGJveGVzCnBhbF9wb2ludCA8LSBjKCJGU00gZWxpZ2libGUiID0gIiM3QTFGRDIiLCAiTm90IGtub3duIHRvIGJlIEZTTSBlbGlnaWJsZSIgPSAiIzBFNUQ5MSIpICAjY29sb3JzIGZvciBqaXR0ZXIgCgojOCkgY3JlYXRpbmcgYm94cGxvdApnZ3Bsb3Qod3NfZGF0YV9mc20sIGFlcyh4PSBmc21TdGF0dXMsIHkgPSBwZXJjZW50VGFyZ2V0LCBmaWxsPSBmc21TdGF0dXMpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgYWxwaGEgPSAwLjcpICsKICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBmc21TdGF0dXMpLCB3aWR0aCA9IDAuMTUsIGFscGhhID0gMC42LCBzaXplID0gMikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBzaGFwZSA9IDIzLCBzaXplID0gMywgZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGdlb20gPSAidGV4dCIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHJvdW5kKC4ueS4uLCAxKSksICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHZqdXN0ID0gKzEuNywgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxfZmlsbCkgKyAgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbF9wb2ludCkgKwogIGxhYnModGl0bGUgPSAiV2VzdCBTdXNzZXg6IFBob25pY3MgQXR0YWlubWVudCBieSBGU00gU3RhdHVzIiwKICAgICAgIHN1YnRpdGxlID0gIip3aGl0ZSBkaWFtb25kIG1hcmtlciA9IG1lYW47IHAgPSAyLjg5N2UtMDYgIiwKICAgICAgIHggPSAiRlNNIFN0YXR1cyIsCiAgICAgICB5PSAiUGhvbmljcyBBdHRhaW5tZW50IikgKwogdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSA4KQoKYGBgCgpgYGB7cn0KI1BhcnQgMmIuMjogQW5hbHlzaXMgb2YgdGhlIGZhY3RvciBldGhuaWNpdHkgKG1ham9yKSBpbiBXUwoKIzEpIGZpbHRlcmluZyBmb3IgZXRobmljaXR5IChtYWpvcikgaW4gV1MKd3NfZGF0YV9ldGggPC0gZGF0YSAlPiUKICBmaWx0ZXIobGFOYW1lID09ICJXZXN0IFN1c3NleCIpICU+JQogIHNlbGVjdChldGhuaWNpdHlNYWpvciwgcGVyY2VudFRhcmdldCkgJT4lCiAgZmlsdGVyKCEgaXMubmEocGVyY2VudFRhcmdldCkpCgojMikgZG91YmxlIGNoZWNraW5nIGxldmVscwpsZXZlbHMod3NfZGF0YV9ldGgkZXRobmljaXR5TWFqb3IpCgojMykgY2hlY2tpbmcgbnVtYmVyIG9mIHJvd3MKdGFibGUod3NfZGF0YV9ldGgkZXRobmljaXR5TWFqb3IpCgojY2hlY2tpbmcgYXNzdW1wdGlvbnM6IFNoYXBpcm8tV2lsayAobm9ybWFsIGRpc3RyaWJ1dGlvbikgLT4gdmlvbGF0ZWQgKE1peGVkIHA8MC4wNSkKYnkod3NfZGF0YV9ldGgkcGVyY2VudFRhcmdldCwgd3NfZGF0YV9ldGgkZXRobmljaXR5TWFqb3IsIHNoYXBpcm8udGVzdCkKCiNjaGVja2luZyBhc3N1bXB0aW9uczogTGV2ZW5lJ3MgdGVzdCAoaG9tb2dlbml0eSBvZiB2YXJpYW5jZSkgLT4gdXBoZWxkCmxldmVuZVRlc3QocGVyY2VudFRhcmdldCB+IGV0aG5pY2l0eU1ham9yLCBkYXRhID0gd3NfZGF0YV9ldGgsIGNlbnRlciA9IG1lZGlhbikKCiNLcnVza2FsLVdhbGxpcyAoYW55IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVybmNlcz8pIC0+IHA+MC4wNTsgbm90IHNpZ25pZmljYW50CmtydXNrYWwudGVzdChwZXJjZW50VGFyZ2V0IH4gZXRobmljaXR5TWFqb3IsIGRhdGEgPSB3c19kYXRhX2V0aCkKCnBhbF9maWxsIDwtIGMoIkFzaWFuIC8gQXNpYW4gQnJpdGlzaCIgPSAiI0EyNEJFQSIsICJCbGFjayAvIEFmcmljYW4gLyBDYXJpYmJlYW4gLyBCbGFjayBCcml0aXNoIiA9ICIjMUY3OEI0IiwgIldoaXRlIiA9ICIjRkY2OUI0IiwgIk1peGVkIC8gTXVsdGlwbGUgZXRobmljIGdyb3VwcyIgPSAiI0ZGRkYwMCIsICJPdGhlciBldGhuaWMgZ3JvdXAiID0gIiMwMDgwMDAiICkKCiM0KSBjcmVhdGluZyBib3hwbG90CmdncGxvdCh3c19kYXRhX2V0aCwgYWVzKHg9IGV0aG5pY2l0eU1ham9yLCB5ID0gcGVyY2VudFRhcmdldCwgZmlsbD0gZXRobmljaXR5TWFqb3IpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgYWxwaGEgPSAwLjcpICsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIHNoYXBlID0gMjMsIHNpemUgPSAzLCBmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gcm91bmQoLi55Li4sIDEpKSwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgdmp1c3QgPSArMS42LCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbF9maWxsKSArICAKICBsYWJzKHRpdGxlID0gIldlc3QgU3Vzc2V4OiBQaG9uaWNzIEF0dGFpbm1lbnQgYnkgTWFqb3IgRXRobmljaXRpZXMiLAogICAgICAgeCA9ICJNYWpvciBFdGhuaWNpdHkiLAogICAgICAgeT0gIlBob25pY3MgQXR0YWlubWVudCIpICsKdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSA1LjUpCgojdGFibGUgb2YgbWVkaWFucwoKd3NfZGF0YV9ldGggJT4lCiAgZ3JvdXBfYnkoZXRobmljaXR5TWFqb3IpICU+JQogIHN1bW1hcmlzZShtZWRpYW5fdmFsdWUgPSBtZWRpYW4ocGVyY2VudFRhcmdldCkpCmBgYAoKYGBge3J9CiNwYXJ0IDJiLjM6IG92ZXJ2aWV3IHBob25pY3MgYXR0YWlubWVudCBieSBtaW5vciBXaGl0ZSBldGhuaWNpdGllcwoKIzEpIGZpbHRlcmluZyBmb3IgZXRobmljaXR5IChtaW5vcikgaW4gV1MKd3NfZGF0YV9ldGhfbWluIDwtIGRhdGEgJT4lCiAgZmlsdGVyKGxhTmFtZSA9PSAiV2VzdCBTdXNzZXgiKSAlPiUKICBzZWxlY3QoZXRobmljaXR5TWlub3IsIHBlcmNlbnRUYXJnZXQpICU+JQogIGZpbHRlcighIGlzLm5hKHBlcmNlbnRUYXJnZXQpKQoKIzIpIGZpbHRlcmluZyBmb3IgYWxsIHdoaXRlcwp3aGl0ZV9jYXRlZ29yaWVzIDwtIGMoIkVuZ2xpc2ggLyBXZWxzaCAvIFNjb3R0aXNoIC8gTm9ydGhlcm4gSXJpc2ggLyBCcml0aXNoIiwgIklyaXNoIiwgIklyaXNoIFRyYXZlbGxlciIsICJBbnkgb3RoZXIgV2hpdGUgQmFja2dyb3VuZCIpCgp3aGl0ZV9taW5vcl9XUyA8LSB3c19kYXRhX2V0aF9taW4gJT4lCiAgZmlsdGVyKGV0aG5pY2l0eU1pbm9yICVpbiUgd2hpdGVfY2F0ZWdvcmllcykKCiMzKSBjb2xvcnMgZm9yIGJveHBsb3QKcGFsX2ZpbGwgPC0gYygiSXJpc2giID0gIiNBMjRCRUEiLCAiSXJpc2ggVHJhdmVsbGVyIiA9ICIjMUY3OEI0IiwgIkFueSBvdGhlciBXaGl0ZSBCYWNrZ3JvdW5kIiA9ICIjRkY2OUI0IiwgIkVuZ2xpc2ggLyBXZWxzaCAvIFNjb3R0aXNoIC8gTm9ydGhlcm4gSXJpc2ggLyBCcml0aXNoIiA9ICIjRkZGRjAwIiApCgojNCkgY3JlYXRpbmcgYm94cGxvdApnZ3Bsb3Qod2hpdGVfbWlub3JfV1MsIGFlcyh4PSBldGhuaWNpdHlNaW5vciwgeSA9IHBlcmNlbnRUYXJnZXQsIGZpbGw9IGV0aG5pY2l0eU1pbm9yKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gMC43KSArCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBzaGFwZSA9IDIzLCBzaXplID0gMywgZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGdlb20gPSAidGV4dCIsICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHJvdW5kKC4ueS4uLCAxKSksICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHZqdXN0ID0gKzEuOCwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxfZmlsbCkgKyAgCiAgbGFicyh0aXRsZSA9ICJXZXN0IFN1c3NleDogUGhvbmljcyBBdHRhaW5tZW50IGJ5IE1pbm9yIFdoaXRlIEV0aG5pY2l0aWVzIiwKICAgICAgIHggPSAiTWlub3IgV2hpdGUgRXRobmljaXR5IiwKICAgICAgIHk9ICJQaG9uaWNzIEF0dGFpbm1lbnQiKSArCnRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gNykKYGBgCgpgYGB7cn0KI3BhcnQgMmIuNDogb3ZlcnZpZXcgcGhvbmljcyBhdHRhaW5tZW50IGJ5IG1pbm9yIEFzaWFuIGV0aG5pY2l0aWVzCgojMSkgZmlsdGVyaW5nIGZvciBhbGwgYXNpYW5zCmFzaWFuX2NhdGVnb3JpZXMgPC0gYyggIkJhbmdsYWRlc2hpIiwgIkNoaW5lc2UiLCAiUGFraXN0YW5pIiwgIkd5cHN5IiwgIkFueSBvdGhlciBBc2lhbiBiYWNrZ3JvdW5kIiwgIkluZGlhbiIsICJXaGl0ZSBhbmQgQXNpYW4iKQoKYXNpYW5fbWlub3JfV1MgPC0gd3NfZGF0YV9ldGhfbWluICU+JQogIGZpbHRlcihldGhuaWNpdHlNaW5vciAlaW4lIGFzaWFuX2NhdGVnb3JpZXMpCgojMikgY29sb3JzIGZvciBib3hwbG90CnBhbF9maWxsIDwtIGMoIkJhbmdsYWRlc2hpIiA9ICIjQTI0QkVBIiwgIkNoaW5lc2UiID0gIiMxRjc4QjQiLCAiUGFraXN0YW5pIiA9ICIjRkY2OUI0IiwgIkluZGlhbiIgPSAiI0ZGRkYwMCIsICJHeXBzeSIgPSAiIzAwODAwMCIsICJBbnkgb3RoZXIgQXNpYW4gYmFja2dyb3VuZCIgPSAiI0ZGMDAwMCIsICJXaGl0ZSBhbmQgQXNpYW4iID0gIiM5NjRCMDAiICkKCiM0KSBjcmVhdGluZyBib3hwbG90CmdncGxvdChhc2lhbl9taW5vcl9XUywgYWVzKHg9IGV0aG5pY2l0eU1pbm9yLCB5ID0gcGVyY2VudFRhcmdldCwgZmlsbD0gZXRobmljaXR5TWlub3IpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgYWxwaGEgPSAwLjcpICsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIHNoYXBlID0gMjMsIHNpemUgPSAzLCBmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSsKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gcm91bmQoLi55Li4sIDEpKSwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgdmp1c3QgPSArMiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxfZmlsbCkgKyAgCiAgbGFicyh0aXRsZSA9ICJXZXN0IFN1c3NleDogUGhvbmljcyBBdHRhaW5tZW50IGJ5IE1pbm9yIEFzaWFuIEV0aG5pY2l0aWVzIiwKICAgICAgIHggPSAiTWlub3IgQXNpYW4gRXRobmljaXR5IiwKICAgICAgIHk9ICJQaG9uaWNzIEF0dGFpbm1lbnQiKSArCnRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gNykKCmBgYAoK