1. Defining malnutrition

1.1. Prerequisites

library(tidyverse)
library(zscorer)
library(readr)
library(dplyr)
library (lubridate)
library (ggplot2)
library (rmarkdown)
library(openxlsx)
PSFI_df_malnutrition <- read_csv("Ben_cut_4_27.csv")
  PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(
    date_present = as.POSIXct(date_present, format = "%d%b%Y:%H:%M:%S", tz = "UTC"),
    dob = mdy(dob),
    age_days_exact = as.numeric(difftime(date_present, dob, units = "days"))
  )
  
  
summary(PSFI_df_malnutrition$age_days_exact)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  32.03  289.19  604.61 1124.44 1461.64 5452.40 
View(PSFI_df_malnutrition)

1.2. Anthroprometric analysis

PSFI_df_malnutrition %>%
  filter(case_control == 1) %>%
  select(ht, wt, age_years, muac) %>%
  summary()
Error in `select()`:
! Can't select columns that don't exist.
✖ Column `age_years` doesn't exist.
Run `]8;;x-r-run:rlang::last_trace()rlang::last_trace()]8;;` to see where the error occurred.
# Layout to split the screen
layout(mat = matrix(c(1,2),2,1, byrow=TRUE),  height = c(1,8))
 
# Draw the boxplot and the histogram 
par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(PSFI_df_malnutrition$ht[PSFI_df_malnutrition$case_control == 1] , horizontal=TRUE , ylim=c(0,200), xaxt="n" , col=rgb(0.8,0.8,0,0.5) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(PSFI_df_malnutrition$ht[PSFI_df_malnutrition$case_control == 1]
     , breaks=40 , col=rgb(1,0.8,0.8,1) , border=F , main="" , xlab="Height (cm)", xlim=c(0,200))

layout(mat = matrix(c(1,2),2,1, byrow=TRUE),  height = c(1,8))
 par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(PSFI_df_malnutrition$wt[PSFI_df_malnutrition$case_control == 1] , horizontal=TRUE , ylim=c(0,80), xaxt="n" , col=rgb(0.8,0.8,0,0.5) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(PSFI_df_malnutrition$wt[PSFI_df_malnutrition$case_control == 1]
     , breaks=40 , col=rgb(1,0.8,0.8,1) , border=F , main="" , xlab="Weight (kg)", xlim=c(0,80))

layout(mat = matrix(c(1,2),2,1, byrow=TRUE),  height = c(1,8))
par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(PSFI_df_malnutrition$muac[PSFI_df_malnutrition$case_control == 1] , horizontal=TRUE , ylim=c(5,30), xaxt="n" , col=rgb(0.8,0.8,0,0.5) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(PSFI_df_malnutrition$muac[PSFI_df_malnutrition$case_control == 1]
     , breaks=20 , col=rgb(1,0.8,0.8,1) , border=F , main="" , xlab="Mid-upper arm circumference (cm)", xlim=c(5,30))
abline(v = 11.5, col = "red", lwd = 2, lty = 2)   # severe
abline(v = 12.5, col = "blue", lwd = 2, lty = 2)  # moderate

PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(age_years = age_days_exact / 365.25)

summary(PSFI_df_malnutrition$age_years)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
 0.08768  0.79176  1.65535  3.07854  4.00176 14.92786 
layout(mat = matrix(c(1,2),2,1, byrow=TRUE),  height = c(1,8))
 par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(PSFI_df_malnutrition$age_years[PSFI_df_malnutrition$case_control == 1] , horizontal=TRUE , ylim=c(0,15), xaxt="n" , col=rgb(0.8,0.8,0,0.5) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(PSFI_df_malnutrition$age_years[PSFI_df_malnutrition$case_control == 1]
     , breaks=40 , col=rgb(1,0.8,0.8,1) , border=F , main="" , xlab="Age (years)", xlim=c(0,15))

1.3. Z-scorer

PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(sex_who = if_else(sex == 1, 1, 2))

summary(PSFI_df_malnutrition$sex_who)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   1.000   1.427   2.000   2.000 
PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(
    age_group = case_when(
      age_days_exact < 5 * 365.25 ~ 0L,
      age_days_exact >= 5 * 365.25 ~ 1L,
      TRUE ~ NA_integer_
    )
  )
PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(
    wflz = addWGSR(
      data = .,
      sex = "sex_who",
      firstPart = "wt",
      secondPart = "ht",
      index = "wfl"
    )$wflz,
    
    wfhz = addWGSR(
      data = .,
      sex = "sex_who",
      firstPart = "wt",
      secondPart = "ht",
      index = "wfh"
    )$wfhz,
    
    baz = addWGSR(
      data = .,
      sex = "sex_who",
      firstPart = "wt",
      secondPart = "ht",
      thirdPart = "age_days_exact",
      index = "bfa"
    )$bfaz,
  )
==============================================================================================
==============================================================================================
==============================================================================================
PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(
    muacz = case_when(
      muac >= 12.5 ~ 0,
      muac >= 11.5 & muac < 12.5 ~ -2.5,
      muac < 11.5 ~ -4,
      TRUE ~ NA_real_
    )
  )
PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(
    zscore_unified = case_when(
      age_group == 0 & ht >= 45 & ht < 65 ~ wflz,
      age_group == 0 & ht >= 65 & ht < 120 ~ wfhz,
      age_group == 0 & (ht < 45 | ht >= 120 | is.na(ht)) ~ muacz,
      age_group == 1 ~ baz,
      TRUE ~ NA_real_
    )
  )
PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(
    malnutrition = case_when(
  is.na(zscore_unified) ~ NA_integer_,
  zscore_unified < -3 ~ 2L,
  zscore_unified >= -3 & zscore_unified < -2 ~ 1L,
  TRUE ~ 0L
    )
  )
PSFI_df_malnutrition <- PSFI_df_malnutrition %>%
  mutate(
    malnutrition_source = case_when(
      age_group == 0 & ht >= 45 & ht < 65  ~ "WFL",
      age_group == 0 & ht >= 65 & ht < 120 ~ "WFH",
      age_group == 0 & (ht < 45 | ht >= 120 | is.na(ht)) ~ "MUAC",
      age_group == 1 ~ "BFA",
      TRUE ~ NA_character_
    )
  )

1.4 Z score check

PSFI_df_malnutrition %>%
  filter(age_group == 1 & case_control == 1) %>%
  pull(baz) %>%
  summary()
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-11.0000  -2.1325  -0.4700  -0.2723   1.1300  32.6700 
PSFI_df_malnutrition %>%
  filter(age_group == 0 & ht >= 45 & ht < 65 & case_control == 1) %>%
  pull(wflz) %>%
  summary()
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-4.9000 -1.0075  0.8800  0.9719  2.4400 13.7700 
PSFI_df_malnutrition %>%
  filter(age_group == 0 & ht >= 65 & ht < 120 & case_control == 1) %>%
  pull(wfhz) %>%
  summary()
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-10.5900  -2.4175  -0.8900  -0.9841   0.7500  12.8800 
layout(mat = matrix(c(1,2),2,1, byrow=TRUE),  height = c(1,8))
 par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(PSFI_df_malnutrition$baz[PSFI_df_malnutrition$age_group == 1 & PSFI_df_malnutrition$case_control == 1] , horizontal=TRUE , ylim=c(-10,10), xaxt="n" , col=rgb(0.8,0.8,0,0.5) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(PSFI_df_malnutrition$baz[PSFI_df_malnutrition$age_group == 1 & PSFI_df_malnutrition$case_control == 1]
     , breaks=50 , col=rgb(1,0.8,0.8,1) , border=F , main="" , xlab="BMI for age (z-score)", xlim=c(-10,10))

layout(mat = matrix(c(1,2),2,1, byrow=TRUE),  height = c(1,8))
 par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(PSFI_df_malnutrition$wfhz[PSFI_df_malnutrition$age_group == 0 & PSFI_df_malnutrition$ht >= 65 & PSFI_df_malnutrition$ht < 120 & PSFI_df_malnutrition$case_control == 1] , horizontal=TRUE , ylim=c(-10,10), xaxt="n" , col=rgb(0.8,0.8,0,0.5) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(PSFI_df_malnutrition$wfhz[PSFI_df_malnutrition$age_group == 0 & PSFI_df_malnutrition$ht >= 65 & PSFI_df_malnutrition$ht < 120 & PSFI_df_malnutrition$case_control == 1]
     , breaks=50 , col=rgb(1,0.8,0.8,1) , border=F , main="" , xlab="Weight-for-height (z-score)", xlim=c(-10,10))

layout(mat = matrix(c(1,2),2,1, byrow=TRUE),  height = c(1,8))
 par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(PSFI_df_malnutrition$wflz[PSFI_df_malnutrition$age_group == 0 & PSFI_df_malnutrition$ht >= 45 & PSFI_df_malnutrition$ht < 65 & PSFI_df_malnutrition$case_control == 1] , horizontal=TRUE , ylim=c(-10,10), xaxt="n" , col=rgb(0.8,0.8,0,0.5) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(PSFI_df_malnutrition$wflz[PSFI_df_malnutrition$age_group == 0 & PSFI_df_malnutrition$ht >= 45 & PSFI_df_malnutrition$ht < 65 & PSFI_df_malnutrition$case_control == 1]
     , breaks=50 , col=rgb(1,0.8,0.8,1) , border=F , main="" , xlab="Weight for length (z-score)", xlim=c(-10,10))

## muac is not based on z-score, but rather if it is <115mm, between 115-125 or >125mm
PSFI_df_malnutrition %>%
  filter(case_control == 1) %>%
  drop_na(muacz) %>%
  mutate(
    malnutrition_status = case_when(
      muacz < -3 ~ "Severe malnutrition",
      muacz >= -3 & muacz < -2 ~ "Moderate malnutrition",
      muacz >= -2 ~ "No malnutrition",
      TRUE ~ NA_character_
    )
  ) %>%
  ggplot(aes(x = malnutrition_status)) +
  geom_bar() +
  labs(
    x = "Malnutrition status based on MUAC",
    y = "N"
  )

1.5 Data check

PSFI_df_malnutrition%>%
  group_by(malnutrition) %>%
  summarize(
    malnutrition_missing = sum(is.na(malnutrition)),
    mort_inhosp_missing = sum(is.na(mort_inhosp)), #103 mort_inhosp_miissing  = controls
  )
PSFI_df_malnutrition %>%
  filter (case_control == 1) %>%
  group_by(malnutrition_source) %>%
  summarize(
    count_malnut = n()
  )

# NA due to child with height of 20 cm (under WHO curve for wfh/wfl) and 38 days old (too young for MUAC)
PSFI_df_malnutrition %>%
  filter (case_control == 1) %>%
  group_by(malnutrition) %>%
  summarize(
    count_malnut = n()
  )
PSFI_df_malnutrition %>%
  drop_na(malnutrition, mort_inhosp) %>%
  ggplot(aes(x = factor(malnutrition))) +
  geom_bar() +
  labs(
    x = "Malnutrition",
    y = "N"
  )

PSFI_df_malnutrition%>%
  filter (case_control == 1) %>%
  count(malnutrition, mort_inhosp) %>%
  group_by(malnutrition) %>%
  mutate(prop = n / sum(n))
PSFI_df_malnutrition %>%
  drop_na(mort_inhosp, malnutrition) %>% #only cases & minus the one previously mentioned NA
  ggplot +
  (aes(x = factor(malnutrition), fill = factor(mort_inhosp))) +
  geom_bar(stat = "count", position = "fill") +
  labs(
    x = "Malnutrition",
    y = "Proportion",
    fill = "Mortality"
  )

PSFI_df_malnutrition %>%
  drop_na(malnutrition) %>%
  ggplot +
  (aes(x = factor(malnutrition), fill = factor(case_control))) +
  geom_bar(stat = "count", position = "fill") +
  labs(
    x = "Malnutrition",
    y = "Proportion",
    fill = "Case/Control"
  )

write.xlsx(PSFI_df_malnutrition, file = "PSFI_final_malnutrition.xlsx")
LS0tCnRpdGxlOiAiVGhlIERvdWJsZSBCdXJkZW4gb2YgTWFsbnV0cml0aW9uIGFuZCBQZWRpYXRyaWMgU2Vwc2lzIGluIFRhbnphbmlhIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKIyAxLiBEZWZpbmluZyBtYWxudXRyaXRpb24KCiMjIDEuMS4gUHJlcmVxdWlzaXRlcwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHpzY29yZXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkgKGx1YnJpZGF0ZSkKbGlicmFyeSAoZ2dwbG90MikKbGlicmFyeSAocm1hcmtkb3duKQpsaWJyYXJ5KG9wZW54bHN4KQpgYGAKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiA8LSByZWFkX2NzdigiQmVuX2N1dF80XzI3LmNzdiIpCmBgYAoKYGBge3J9CiAgUFNGSV9kZl9tYWxudXRyaXRpb24gPC0gUFNGSV9kZl9tYWxudXRyaXRpb24gJT4lCiAgbXV0YXRlKAogICAgZGF0ZV9wcmVzZW50ID0gYXMuUE9TSVhjdChkYXRlX3ByZXNlbnQsIGZvcm1hdCA9ICIlZCViJVk6JUg6JU06JVMiLCB0eiA9ICJVVEMiKSwKICAgIGRvYiA9IG1keShkb2IpLAogICAgYWdlX2RheXNfZXhhY3QgPSBhcy5udW1lcmljKGRpZmZ0aW1lKGRhdGVfcHJlc2VudCwgZG9iLCB1bml0cyA9ICJkYXlzIikpCiAgKQogIAogIApzdW1tYXJ5KFBTRklfZGZfbWFsbnV0cml0aW9uJGFnZV9kYXlzX2V4YWN0KQpgYGAKCmBgYHtyfQpWaWV3KFBTRklfZGZfbWFsbnV0cml0aW9uKQoKYGBgCgojIyAxLjIuIEFudGhyb3Byb21ldHJpYyBhbmFseXNpcwoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIGZpbHRlcihjYXNlX2NvbnRyb2wgPT0gMSkgJT4lCiAgc2VsZWN0KGh0LCB3dCwgYWdlX3llYXJzLCBtdWFjKSAlPiUKICBzdW1tYXJ5KCkKYGBgCgpgYGB7cn0KIyBMYXlvdXQgdG8gc3BsaXQgdGhlIHNjcmVlbgpsYXlvdXQobWF0ID0gbWF0cml4KGMoMSwyKSwyLDEsIGJ5cm93PVRSVUUpLCAgaGVpZ2h0ID0gYygxLDgpKQogCiMgRHJhdyB0aGUgYm94cGxvdCBhbmQgdGhlIGhpc3RvZ3JhbSAKcGFyKG1hcj1jKDAsIDMuMSwgMS4xLCAyLjEpKQpib3hwbG90KFBTRklfZGZfbWFsbnV0cml0aW9uJGh0W1BTRklfZGZfbWFsbnV0cml0aW9uJGNhc2VfY29udHJvbCA9PSAxXSAsIGhvcml6b250YWw9VFJVRSAsIHlsaW09YygwLDIwMCksIHhheHQ9Im4iICwgY29sPXJnYigwLjgsMC44LDAsMC41KSAsIGZyYW1lPUYpCnBhcihtYXI9Yyg0LCAzLjEsIDEuMSwgMi4xKSkKaGlzdChQU0ZJX2RmX21hbG51dHJpdGlvbiRodFtQU0ZJX2RmX21hbG51dHJpdGlvbiRjYXNlX2NvbnRyb2wgPT0gMV0KICAgICAsIGJyZWFrcz00MCAsIGNvbD1yZ2IoMSwwLjgsMC44LDEpICwgYm9yZGVyPUYgLCBtYWluPSIiICwgeGxhYj0iSGVpZ2h0IChjbSkiLCB4bGltPWMoMCwyMDApKQpgYGAKCmBgYHtyfQpsYXlvdXQobWF0ID0gbWF0cml4KGMoMSwyKSwyLDEsIGJ5cm93PVRSVUUpLCAgaGVpZ2h0ID0gYygxLDgpKQogcGFyKG1hcj1jKDAsIDMuMSwgMS4xLCAyLjEpKQpib3hwbG90KFBTRklfZGZfbWFsbnV0cml0aW9uJHd0W1BTRklfZGZfbWFsbnV0cml0aW9uJGNhc2VfY29udHJvbCA9PSAxXSAsIGhvcml6b250YWw9VFJVRSAsIHlsaW09YygwLDgwKSwgeGF4dD0ibiIgLCBjb2w9cmdiKDAuOCwwLjgsMCwwLjUpICwgZnJhbWU9RikKcGFyKG1hcj1jKDQsIDMuMSwgMS4xLCAyLjEpKQpoaXN0KFBTRklfZGZfbWFsbnV0cml0aW9uJHd0W1BTRklfZGZfbWFsbnV0cml0aW9uJGNhc2VfY29udHJvbCA9PSAxXQogICAgICwgYnJlYWtzPTQwICwgY29sPXJnYigxLDAuOCwwLjgsMSkgLCBib3JkZXI9RiAsIG1haW49IiIgLCB4bGFiPSJXZWlnaHQgKGtnKSIsIHhsaW09YygwLDgwKSkKYGBgCgpgYGB7cn0KbGF5b3V0KG1hdCA9IG1hdHJpeChjKDEsMiksMiwxLCBieXJvdz1UUlVFKSwgIGhlaWdodCA9IGMoMSw4KSkKcGFyKG1hcj1jKDAsIDMuMSwgMS4xLCAyLjEpKQpib3hwbG90KFBTRklfZGZfbWFsbnV0cml0aW9uJG11YWNbUFNGSV9kZl9tYWxudXRyaXRpb24kY2FzZV9jb250cm9sID09IDFdICwgaG9yaXpvbnRhbD1UUlVFICwgeWxpbT1jKDUsMzApLCB4YXh0PSJuIiAsIGNvbD1yZ2IoMC44LDAuOCwwLDAuNSkgLCBmcmFtZT1GKQpwYXIobWFyPWMoNCwgMy4xLCAxLjEsIDIuMSkpCmhpc3QoUFNGSV9kZl9tYWxudXRyaXRpb24kbXVhY1tQU0ZJX2RmX21hbG51dHJpdGlvbiRjYXNlX2NvbnRyb2wgPT0gMV0KICAgICAsIGJyZWFrcz0yMCAsIGNvbD1yZ2IoMSwwLjgsMC44LDEpICwgYm9yZGVyPUYgLCBtYWluPSIiICwgeGxhYj0iTWlkLXVwcGVyIGFybSBjaXJjdW1mZXJlbmNlIChjbSkiLCB4bGltPWMoNSwzMCkpCmFibGluZSh2ID0gMTEuNSwgY29sID0gInJlZCIsIGx3ZCA9IDIsIGx0eSA9IDIpICAgIyBzZXZlcmUKYWJsaW5lKHYgPSAxMi41LCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIsIGx0eSA9IDIpICAjIG1vZGVyYXRlCmBgYAoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uIDwtIFBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIG11dGF0ZShhZ2VfeWVhcnMgPSBhZ2VfZGF5c19leGFjdCAvIDM2NS4yNSkKCnN1bW1hcnkoUFNGSV9kZl9tYWxudXRyaXRpb24kYWdlX3llYXJzKQpgYGAKCmBgYHtyfQpsYXlvdXQobWF0ID0gbWF0cml4KGMoMSwyKSwyLDEsIGJ5cm93PVRSVUUpLCAgaGVpZ2h0ID0gYygxLDgpKQogcGFyKG1hcj1jKDAsIDMuMSwgMS4xLCAyLjEpKQpib3hwbG90KFBTRklfZGZfbWFsbnV0cml0aW9uJGFnZV95ZWFyc1tQU0ZJX2RmX21hbG51dHJpdGlvbiRjYXNlX2NvbnRyb2wgPT0gMV0gLCBob3Jpem9udGFsPVRSVUUgLCB5bGltPWMoMCwxNSksIHhheHQ9Im4iICwgY29sPXJnYigwLjgsMC44LDAsMC41KSAsIGZyYW1lPUYpCnBhcihtYXI9Yyg0LCAzLjEsIDEuMSwgMi4xKSkKaGlzdChQU0ZJX2RmX21hbG51dHJpdGlvbiRhZ2VfeWVhcnNbUFNGSV9kZl9tYWxudXRyaXRpb24kY2FzZV9jb250cm9sID09IDFdCiAgICAgLCBicmVha3M9NDAgLCBjb2w9cmdiKDEsMC44LDAuOCwxKSAsIGJvcmRlcj1GICwgbWFpbj0iIiAsIHhsYWI9IkFnZSAoeWVhcnMpIiwgeGxpbT1jKDAsMTUpKQpgYGAKCiMjIDEuMy4gWi1zY29yZXIKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiA8LSBQU0ZJX2RmX21hbG51dHJpdGlvbiAlPiUKICBtdXRhdGUoc2V4X3dobyA9IGlmX2Vsc2Uoc2V4ID09IDEsIDEsIDIpKQoKc3VtbWFyeShQU0ZJX2RmX21hbG51dHJpdGlvbiRzZXhfd2hvKQpgYGAKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiA8LSBQU0ZJX2RmX21hbG51dHJpdGlvbiAlPiUKICBtdXRhdGUoCiAgICBhZ2VfZ3JvdXAgPSBjYXNlX3doZW4oCiAgICAgIGFnZV9kYXlzX2V4YWN0IDwgNSAqIDM2NS4yNSB+IDBMLAogICAgICBhZ2VfZGF5c19leGFjdCA+PSA1ICogMzY1LjI1IH4gMUwsCiAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXwogICAgKQogICkKCmBgYAoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uIDwtIFBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIG11dGF0ZSgKICAgIHdmbHogPSBhZGRXR1NSKAogICAgICBkYXRhID0gLiwKICAgICAgc2V4ID0gInNleF93aG8iLAogICAgICBmaXJzdFBhcnQgPSAid3QiLAogICAgICBzZWNvbmRQYXJ0ID0gImh0IiwKICAgICAgaW5kZXggPSAid2ZsIgogICAgKSR3Zmx6LAogICAgCiAgICB3Zmh6ID0gYWRkV0dTUigKICAgICAgZGF0YSA9IC4sCiAgICAgIHNleCA9ICJzZXhfd2hvIiwKICAgICAgZmlyc3RQYXJ0ID0gInd0IiwKICAgICAgc2Vjb25kUGFydCA9ICJodCIsCiAgICAgIGluZGV4ID0gIndmaCIKICAgICkkd2ZoeiwKICAgIAogICAgYmF6ID0gYWRkV0dTUigKICAgICAgZGF0YSA9IC4sCiAgICAgIHNleCA9ICJzZXhfd2hvIiwKICAgICAgZmlyc3RQYXJ0ID0gInd0IiwKICAgICAgc2Vjb25kUGFydCA9ICJodCIsCiAgICAgIHRoaXJkUGFydCA9ICJhZ2VfZGF5c19leGFjdCIsCiAgICAgIGluZGV4ID0gImJmYSIKICAgICkkYmZheiwKICApCgpgYGAKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiA8LSBQU0ZJX2RmX21hbG51dHJpdGlvbiAlPiUKICBtdXRhdGUoCiAgICBtdWFjeiA9IGNhc2Vfd2hlbigKICAgICAgbXVhYyA+PSAxMi41IH4gMCwKICAgICAgbXVhYyA+PSAxMS41ICYgbXVhYyA8IDEyLjUgfiAtMi41LAogICAgICBtdWFjIDwgMTEuNSB+IC00LAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICkKICApCmBgYAoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uIDwtIFBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIG11dGF0ZSgKICAgIHpzY29yZV91bmlmaWVkID0gY2FzZV93aGVuKAogICAgICBhZ2VfZ3JvdXAgPT0gMCAmIGh0ID49IDQ1ICYgaHQgPCA2NSB+IHdmbHosCiAgICAgIGFnZV9ncm91cCA9PSAwICYgaHQgPj0gNjUgJiBodCA8IDEyMCB+IHdmaHosCiAgICAgIGFnZV9ncm91cCA9PSAwICYgKGh0IDwgNDUgfCBodCA+PSAxMjAgfCBpcy5uYShodCkpIH4gbXVhY3osCiAgICAgIGFnZV9ncm91cCA9PSAxIH4gYmF6LAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICkKICApCmBgYAoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uIDwtIFBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIG11dGF0ZSgKICAgIG1hbG51dHJpdGlvbiA9IGNhc2Vfd2hlbigKICBpcy5uYSh6c2NvcmVfdW5pZmllZCkgfiBOQV9pbnRlZ2VyXywKICB6c2NvcmVfdW5pZmllZCA8IC0zIH4gMkwsCiAgenNjb3JlX3VuaWZpZWQgPj0gLTMgJiB6c2NvcmVfdW5pZmllZCA8IC0yIH4gMUwsCiAgVFJVRSB+IDBMCiAgICApCiAgKQpgYGAKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiA8LSBQU0ZJX2RmX21hbG51dHJpdGlvbiAlPiUKICBtdXRhdGUoCiAgICBtYWxudXRyaXRpb25fc291cmNlID0gY2FzZV93aGVuKAogICAgICBhZ2VfZ3JvdXAgPT0gMCAmIGh0ID49IDQ1ICYgaHQgPCA2NSAgfiAiV0ZMIiwKICAgICAgYWdlX2dyb3VwID09IDAgJiBodCA+PSA2NSAmIGh0IDwgMTIwIH4gIldGSCIsCiAgICAgIGFnZV9ncm91cCA9PSAwICYgKGh0IDwgNDUgfCBodCA+PSAxMjAgfCBpcy5uYShodCkpIH4gIk1VQUMiLAogICAgICBhZ2VfZ3JvdXAgPT0gMSB+ICJCRkEiLAogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXwogICAgKQogICkKYGBgCgojIyAxLjQgWiBzY29yZSBjaGVjawoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIGZpbHRlcihhZ2VfZ3JvdXAgPT0gMSAmIGNhc2VfY29udHJvbCA9PSAxKSAlPiUKICBwdWxsKGJheikgJT4lCiAgc3VtbWFyeSgpCgpgYGAKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiAlPiUKICBmaWx0ZXIoYWdlX2dyb3VwID09IDAgJiBodCA+PSA0NSAmIGh0IDwgNjUgJiBjYXNlX2NvbnRyb2wgPT0gMSkgJT4lCiAgcHVsbCh3Zmx6KSAlPiUKICBzdW1tYXJ5KCkKYGBgCgpgYGB7cn0KUFNGSV9kZl9tYWxudXRyaXRpb24gJT4lCiAgZmlsdGVyKGFnZV9ncm91cCA9PSAwICYgaHQgPj0gNjUgJiBodCA8IDEyMCAmIGNhc2VfY29udHJvbCA9PSAxKSAlPiUKICBwdWxsKHdmaHopICU+JQogIHN1bW1hcnkoKQpgYGAKCgpgYGB7cn0KbGF5b3V0KG1hdCA9IG1hdHJpeChjKDEsMiksMiwxLCBieXJvdz1UUlVFKSwgIGhlaWdodCA9IGMoMSw4KSkKIHBhcihtYXI9YygwLCAzLjEsIDEuMSwgMi4xKSkKYm94cGxvdChQU0ZJX2RmX21hbG51dHJpdGlvbiRiYXpbUFNGSV9kZl9tYWxudXRyaXRpb24kYWdlX2dyb3VwID09IDEgJiBQU0ZJX2RmX21hbG51dHJpdGlvbiRjYXNlX2NvbnRyb2wgPT0gMV0gLCBob3Jpem9udGFsPVRSVUUgLCB5bGltPWMoLTEwLDEwKSwgeGF4dD0ibiIgLCBjb2w9cmdiKDAuOCwwLjgsMCwwLjUpICwgZnJhbWU9RikKcGFyKG1hcj1jKDQsIDMuMSwgMS4xLCAyLjEpKQpoaXN0KFBTRklfZGZfbWFsbnV0cml0aW9uJGJheltQU0ZJX2RmX21hbG51dHJpdGlvbiRhZ2VfZ3JvdXAgPT0gMSAmIFBTRklfZGZfbWFsbnV0cml0aW9uJGNhc2VfY29udHJvbCA9PSAxXQogICAgICwgYnJlYWtzPTUwICwgY29sPXJnYigxLDAuOCwwLjgsMSkgLCBib3JkZXI9RiAsIG1haW49IiIgLCB4bGFiPSJCTUkgZm9yIGFnZSAoei1zY29yZSkiLCB4bGltPWMoLTEwLDEwKSkKYGBgCgpgYGB7cn0KbGF5b3V0KG1hdCA9IG1hdHJpeChjKDEsMiksMiwxLCBieXJvdz1UUlVFKSwgIGhlaWdodCA9IGMoMSw4KSkKIHBhcihtYXI9YygwLCAzLjEsIDEuMSwgMi4xKSkKYm94cGxvdChQU0ZJX2RmX21hbG51dHJpdGlvbiR3Zmh6W1BTRklfZGZfbWFsbnV0cml0aW9uJGFnZV9ncm91cCA9PSAwICYgUFNGSV9kZl9tYWxudXRyaXRpb24kaHQgPj0gNjUgJiBQU0ZJX2RmX21hbG51dHJpdGlvbiRodCA8IDEyMCAmIFBTRklfZGZfbWFsbnV0cml0aW9uJGNhc2VfY29udHJvbCA9PSAxXSAsIGhvcml6b250YWw9VFJVRSAsIHlsaW09YygtMTAsMTApLCB4YXh0PSJuIiAsIGNvbD1yZ2IoMC44LDAuOCwwLDAuNSkgLCBmcmFtZT1GKQpwYXIobWFyPWMoNCwgMy4xLCAxLjEsIDIuMSkpCmhpc3QoUFNGSV9kZl9tYWxudXRyaXRpb24kd2ZoeltQU0ZJX2RmX21hbG51dHJpdGlvbiRhZ2VfZ3JvdXAgPT0gMCAmIFBTRklfZGZfbWFsbnV0cml0aW9uJGh0ID49IDY1ICYgUFNGSV9kZl9tYWxudXRyaXRpb24kaHQgPCAxMjAgJiBQU0ZJX2RmX21hbG51dHJpdGlvbiRjYXNlX2NvbnRyb2wgPT0gMV0KICAgICAsIGJyZWFrcz01MCAsIGNvbD1yZ2IoMSwwLjgsMC44LDEpICwgYm9yZGVyPUYgLCBtYWluPSIiICwgeGxhYj0iV2VpZ2h0LWZvci1oZWlnaHQgKHotc2NvcmUpIiwgeGxpbT1jKC0xMCwxMCkpCmBgYAoKYGBge3J9CmxheW91dChtYXQgPSBtYXRyaXgoYygxLDIpLDIsMSwgYnlyb3c9VFJVRSksICBoZWlnaHQgPSBjKDEsOCkpCiBwYXIobWFyPWMoMCwgMy4xLCAxLjEsIDIuMSkpCmJveHBsb3QoUFNGSV9kZl9tYWxudXRyaXRpb24kd2ZseltQU0ZJX2RmX21hbG51dHJpdGlvbiRhZ2VfZ3JvdXAgPT0gMCAmIFBTRklfZGZfbWFsbnV0cml0aW9uJGh0ID49IDQ1ICYgUFNGSV9kZl9tYWxudXRyaXRpb24kaHQgPCA2NSAmIFBTRklfZGZfbWFsbnV0cml0aW9uJGNhc2VfY29udHJvbCA9PSAxXSAsIGhvcml6b250YWw9VFJVRSAsIHlsaW09YygtMTAsMTApLCB4YXh0PSJuIiAsIGNvbD1yZ2IoMC44LDAuOCwwLDAuNSkgLCBmcmFtZT1GKQpwYXIobWFyPWMoNCwgMy4xLCAxLjEsIDIuMSkpCmhpc3QoUFNGSV9kZl9tYWxudXRyaXRpb24kd2ZseltQU0ZJX2RmX21hbG51dHJpdGlvbiRhZ2VfZ3JvdXAgPT0gMCAmIFBTRklfZGZfbWFsbnV0cml0aW9uJGh0ID49IDQ1ICYgUFNGSV9kZl9tYWxudXRyaXRpb24kaHQgPCA2NSAmIFBTRklfZGZfbWFsbnV0cml0aW9uJGNhc2VfY29udHJvbCA9PSAxXQogICAgICwgYnJlYWtzPTUwICwgY29sPXJnYigxLDAuOCwwLjgsMSkgLCBib3JkZXI9RiAsIG1haW49IiIgLCB4bGFiPSJXZWlnaHQgZm9yIGxlbmd0aCAoei1zY29yZSkiLCB4bGltPWMoLTEwLDEwKSkKYGBgCmBgYHtyfQojIyBtdWFjIGlzIG5vdCBiYXNlZCBvbiB6LXNjb3JlLCBidXQgcmF0aGVyIGlmIGl0IGlzIDwxMTVtbSwgYmV0d2VlbiAxMTUtMTI1IG9yID4xMjVtbQpQU0ZJX2RmX21hbG51dHJpdGlvbiAlPiUKICBmaWx0ZXIoY2FzZV9jb250cm9sID09IDEpICU+JQogIGRyb3BfbmEobXVhY3opICU+JQogIG11dGF0ZSgKICAgIG1hbG51dHJpdGlvbl9zdGF0dXMgPSBjYXNlX3doZW4oCiAgICAgIG11YWN6IDwgLTMgfiAiU2V2ZXJlIG1hbG51dHJpdGlvbiIsCiAgICAgIG11YWN6ID49IC0zICYgbXVhY3ogPCAtMiB+ICJNb2RlcmF0ZSBtYWxudXRyaXRpb24iLAogICAgICBtdWFjeiA+PSAtMiB+ICJObyBtYWxudXRyaXRpb24iLAogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXwogICAgKQogICkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbWFsbnV0cml0aW9uX3N0YXR1cykpICsKICBnZW9tX2JhcigpICsKICBsYWJzKAogICAgeCA9ICJNYWxudXRyaXRpb24gc3RhdHVzIGJhc2VkIG9uIE1VQUMiLAogICAgeSA9ICJOIgogICkKYGBgCgoKIyMgMS41IERhdGEgY2hlY2sKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiU+JQogIGdyb3VwX2J5KG1hbG51dHJpdGlvbikgJT4lCiAgc3VtbWFyaXplKAogICAgbWFsbnV0cml0aW9uX21pc3NpbmcgPSBzdW0oaXMubmEobWFsbnV0cml0aW9uKSksCiAgICBtb3J0X2luaG9zcF9taXNzaW5nID0gc3VtKGlzLm5hKG1vcnRfaW5ob3NwKSksICMxMDMgbW9ydF9pbmhvc3BfbWlpc3NpbmcgID0gY29udHJvbHMKICApCmBgYAoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIGZpbHRlciAoY2FzZV9jb250cm9sID09IDEpICU+JQogIGdyb3VwX2J5KG1hbG51dHJpdGlvbl9zb3VyY2UpICU+JQogIHN1bW1hcml6ZSgKICAgIGNvdW50X21hbG51dCA9IG4oKQogICkKCiMgTkEgZHVlIHRvIGNoaWxkIHdpdGggaGVpZ2h0IG9mIDIwIGNtICh1bmRlciBXSE8gY3VydmUgZm9yIHdmaC93ZmwpIGFuZCAzOCBkYXlzIG9sZCAodG9vIHlvdW5nIGZvciBNVUFDKQpgYGAKCmBgYHtyfQpQU0ZJX2RmX21hbG51dHJpdGlvbiAlPiUKICBmaWx0ZXIgKGNhc2VfY29udHJvbCA9PSAxKSAlPiUKICBncm91cF9ieShtYWxudXRyaXRpb24pICU+JQogIHN1bW1hcml6ZSgKICAgIGNvdW50X21hbG51dCA9IG4oKQogICkKYGBgCgpgYGB7cn0KUFNGSV9kZl9tYWxudXRyaXRpb24gJT4lCiAgZHJvcF9uYShtYWxudXRyaXRpb24sIG1vcnRfaW5ob3NwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IobWFsbnV0cml0aW9uKSkpICsKICBnZW9tX2JhcigpICsKICBsYWJzKAogICAgeCA9ICJNYWxudXRyaXRpb24iLAogICAgeSA9ICJOIgogICkKYGBgCgpgYGB7cn0KUFNGSV9kZl9tYWxudXRyaXRpb24lPiUKICBmaWx0ZXIgKGNhc2VfY29udHJvbCA9PSAxKSAlPiUKICBjb3VudChtYWxudXRyaXRpb24sIG1vcnRfaW5ob3NwKSAlPiUKICBncm91cF9ieShtYWxudXRyaXRpb24pICU+JQogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSkKYGBgCgpgYGB7cn0KUFNGSV9kZl9tYWxudXRyaXRpb24gJT4lCiAgZHJvcF9uYShtb3J0X2luaG9zcCwgbWFsbnV0cml0aW9uKSAlPiUgI29ubHkgY2FzZXMgJiBtaW51cyB0aGUgb25lIHByZXZpb3VzbHkgbWVudGlvbmVkIE5BCiAgZ2dwbG90ICsKICAoYWVzKHggPSBmYWN0b3IobWFsbnV0cml0aW9uKSwgZmlsbCA9IGZhY3Rvcihtb3J0X2luaG9zcCkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJjb3VudCIsIHBvc2l0aW9uID0gImZpbGwiKSArCiAgbGFicygKICAgIHggPSAiTWFsbnV0cml0aW9uIiwKICAgIHkgPSAiUHJvcG9ydGlvbiIsCiAgICBmaWxsID0gIk1vcnRhbGl0eSIKICApCmBgYAoKYGBge3J9ClBTRklfZGZfbWFsbnV0cml0aW9uICU+JQogIGNvdW50KG1hbG51dHJpdGlvbiwgY2FzZV9jb250cm9sKSAlPiUKICBncm91cF9ieShtYWxudXRyaXRpb24pICU+JQogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSkKYGBgCgpgYGB7cn0KUFNGSV9kZl9tYWxudXRyaXRpb24gJT4lCiAgZHJvcF9uYShtYWxudXRyaXRpb24pICU+JQogIGdncGxvdCArCiAgKGFlcyh4ID0gZmFjdG9yKG1hbG51dHJpdGlvbiksIGZpbGwgPSBmYWN0b3IoY2FzZV9jb250cm9sKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImNvdW50IiwgcG9zaXRpb24gPSAiZmlsbCIpICsKICBsYWJzKAogICAgeCA9ICJNYWxudXRyaXRpb24iLAogICAgeSA9ICJQcm9wb3J0aW9uIiwKICAgIGZpbGwgPSAiQ2FzZS9Db250cm9sIgogICkKYGBgCgpgYGB7cn0Kd3JpdGUueGxzeChQU0ZJX2RmX21hbG51dHJpdGlvbiwgZmlsZSA9ICJQU0ZJX2ZpbmFsX21hbG51dHJpdGlvbi54bHN4IikKYGBgCg==