Load CSVs

steel_1018_data <- read.csv("M12_A_1018.csv", header = TRUE)
steel_1045_data <- read.csv("M12_A_1045.csv", header = TRUE)
al_7075_data    <- read.csv("M12_A_7075.csv", header = TRUE)
pmma_data       <- read.csv("M12_A_PMMA.csv", header = TRUE)

Extract data and Geometry

# Steel 1018
dis_1018 <- as.numeric(steel_1018_data$Displacement)
F_1018   <- as.numeric(steel_1018_data$Force)
eps_1018 <- as.numeric(steel_1018_data$Composite.strain)
l_1018 <- 64.92; d_1018 <- 19.05; A_1018 <- pi/4 * d_1018^2
sigma_eng_1018 <- F_1018 / A_1018 * 1000
sigma_true_1018 <- sigma_eng_1018 * (1 + eps_1018)
eps_true_1018 <- log(1 + eps_1018)
ultimate_1018<- max(sigma_eng_1018, na.rm = TRUE)
fracture_1018 <- length(sigma_eng_1018)

# Steel 1045
dis_1045 <- as.numeric(steel_1045_data$Displacement)
F_1045   <- as.numeric(steel_1045_data$Force)
eps_1045 <- as.numeric(steel_1045_data$Composite.strain)
l_1045 <- 39.8;  d_1045 <- 12.55; A_1045 <- pi/4 * d_1045^2
sigma_eng_1045 <- F_1045 / A_1045 * 1000
sigma_true_1045 <- sigma_eng_1045 * (1 + eps_1045)
eps_true_1045 <- log(1 + eps_1045)
ultimate_1045<- max(sigma_eng_1045, na.rm = TRUE)
fracture_1045 <- length(sigma_eng_1045)


# Aluminum 7075
dis_7075 <- as.numeric(al_7075_data$Displacement)
F_7075   <- as.numeric(al_7075_data$Force)
eps_7075 <- as.numeric(al_7075_data$Composite.strain)
l_7075 <- 39.93; d_7075 <- 12.84; A_7075 <- pi/4 * d_7075^2
sigma_eng_7075 <- F_7075 / A_7075 * 1000
sigma_true_7075 <- sigma_eng_7075 * (1 + eps_7075)
eps_true_7075 <- log(1 + eps_7075)
ultimate_7075 <- max(sigma_eng_7075, na.rm = TRUE)
fracture_7075 <- length(sigma_eng_7075)

# Plastic PMMA
dis_PMMA <- as.numeric(pmma_data$Displacement)
F_PMMA   <- as.numeric(pmma_data$Force)
eps_PMMA <- as.numeric(pmma_data$Compressive.strain)
l_PMMA <- 65.02; d_PMMA <- 19.01; A_PMMA <- pi/4 * d_PMMA^2
sigma_eng_PMMA <- F_PMMA / A_PMMA * 1000
sigma_true_PMMA <- sigma_eng_PMMA * (1 + eps_PMMA)
eps_true_PMMA <- log(1 + eps_PMMA)
fracture_PMMA <- length(sigma_eng_PMMA)
ultimate_PMMA <- max(sigma_eng_PMMA, na.rm = TRUE)

Plot All Engineering Curves in one graph

colors <- c("firebrick", "darkorange", "steelblue", "black")
labels <- c("1045 Steel", "7075 Aluminum", "1018 Steel", "PMMA")
xmax <- max(c(eps_1045, eps_7075, eps_1018, eps_PMMA), na.rm = TRUE)
ymax <- max(c(sigma_eng_1045, sigma_eng_7075, sigma_eng_1018, sigma_eng_PMMA), na.rm = TRUE)
par(mfrow = c(1, 1))
plot(eps_1045, sigma_eng_1045, type = "l", col = colors[1], lwd = 2,
     xlim = c(0, xmax), ylim = c(0, ymax),
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "Stress vs. Strain Curves (All Materials)")
lines(eps_7075, sigma_eng_7075, col = colors[2], lwd = 2)
lines(eps_1018, sigma_eng_1018, col = colors[3], lwd = 2)
lines(eps_PMMA, sigma_eng_PMMA, col = colors[4], lwd = 2)
legend("topright", legend = labels, col = colors, lwd = 2, bty = "n")
grid()

Aluminum 7075 Engineering vs. True

plot(eps_7075, sigma_eng_7075, type = "n",
     xlab = "Strain (mm/mm)", ylab = "Stress (MPa)",
     main = "7075 Aluminum: Engineering vs True")
grid()
points(eps_7075, sigma_eng_7075, col = "royalblue", pch = 16)
points(eps_true_7075, sigma_true_7075, col = "darkorange", pch = 16)
legend("bottomright",
       legend = c("Engineering σ–ε", "True σ–ε"),
       col = c("royalblue", "darkorange"),
       pch = 16, bty = "n")

Four Material Stress-Strain Curve Comparsion

par(mfrow = c(2, 2)) 
# 1045 Steel
plot(eps_1045, eng_stress_1045,
     type = "l", col = "firebrick", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "1045 Steel")
points(eps_1045, eng_stress_1045, col = "firebrick", pch = 16)
points(eps_1045[ultimate_1045], eng_stress_1045[ultimate_1045], col = "purple", pch = 17, cex = 1.5)
legend("bottomright", legend = c("Ultimate Stress"), pch = 17, col = "purple", bty = "n")
grid()

# 7075 Aluminum
plot(eps_7075, eng_stress_7075,
     type = "l", col = "darkorange", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "7075 Aluminum")
points(eps_7075, eng_stress_7075, col = "darkorange", pch = 16)
points(eps_7075[ultimate_7075], eng_stress_7075[ultimate_7075], col = "purple", pch = 17, cex = 1.5)
legend("bottomright", legend = c("Ultimate Stress"), pch = 17, col = "purple", bty = "n")
grid()

# 1018 Steel
plot(eps_1018, eng_stress_1018,
     type = "l", col = "steelblue", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "1018 Steel")
points(eps_1018, eng_stress_1018, col = "steelblue", pch = 16)
points(eps_1018[ultimate_1018], eng_stress_1018[ultimate_1018], col = "purple", pch = 17, cex = 1.5)
legend("bottomright", legend = c("Ultimate Stress"), pch = 17, col = "purple", bty = "n")
grid()

# PMMA
plot(eps_PMMA, eng_stress_PMMA,
     type = "l", col = "black", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "PMMA")
points(eps_PMMA, eng_stress_PMMA, col = "black", pch = 10)
points(eps_PMMA[ultimate_PMMA], eng_stress_PMMA[ultimate_PMMA], col = "purple", pch = 17, cex = 1.5)
legend("bottomright", legend = c("Ultimate Stress"), pch = 17, col = "purple", bty = "n")
grid()

# Eye-balling ultimate stress (will adjust based on the best fit line)
eps_yield_1045 = 0.0033
eps_yield_7075 = 0.004
eps_yield_1018 = 0.0026
eps_yield_PMMA = 0.07
E_1045  <- coef(lm(eng_stress_1045[eps_1045 <= eps_yield_1045] ~ 0 + eps_1045[eps_1045 <= eps_yield_1045]))[1]
E_7075  <- coef(lm(eng_stress_7075[eps_7075 <= eps_yield_7075] ~ 0 + eps_7075[eps_7075 <= eps_yield_7075]))[1]
E_1018  <- coef(lm(eng_stress_1018[eps_1018 <= eps_yield_1018] ~ 0 + eps_1018[eps_1018 <= eps_yield_1018]))[1]
E_PMMA  <- coef(lm(eng_stress_PMMA[eps_PMMA <= eps_yield_PMMA] ~ 0 + eps_PMMA[eps_PMMA <= eps_yield_PMMA]))[1]

cat("E_1045  =", E_1045, "MPa\n")
E_1045  = 195069.4 MPa
cat("E_7075  =", E_7075, "MPa\n")
E_7075  = 71655.21 MPa
cat("E_1018  =", E_1018, "MPa\n")
E_1018  = 104377.6 MPa
cat("E_PMMA  =", E_PMMA, "MPa\n")
E_PMMA  = 1958.495 MPa

1045 Steel

# --- 1045 Steel ---
E_1045 <- coef(fit_1045)[1]
sigma_offset_1045 <- E_1045 * (eps_1045 - 0.002)
diff_1045 <- eng_stress_1045 - sigma_offset_1045
i_1045 <- which(diff(sign(diff_1045)) != 0)[1]
yield_stress_1045 <- eng_stress_1045[i_1045]
yield_strain_1045 <- eps_1045[i_1045]

plot(eps_1045, eng_stress_1045,
     type = "l", col = "firebrick", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "1045 Steel")
points(eps_1045, eng_stress_1045, col = "firebrick", pch = 16)
abline(a = 0, b = coef(fit_1045), col = "purple", lwd = 2, lty = 2)
abline(a = -coef(fit_1045) * 0.002, b = coef(fit_1045), col = "darkgreen", lwd = 2, lty = 3)
points(yield_strain_1045, yield_stress_1045, pch = 19, col = "red")
text(x = yield_strain_1045,
     y = yield_stress_1045,
     labels = paste0(round(yield_stress_1045, 1), " MPa"),
     pos = 3, col = "red", cex = 1.5)


cat("\n--- 1045 Steel ---\n")

--- 1045 Steel ---
cat("E =", round(E_1045, 2), "MPa\n")
E = 195069.4 MPa
cat("0.2% Offset Yield Strain =", round(yield_strain_1045, 5), "\n")
0.2% Offset Yield Strain = 0.00405 
cat("0.2% Offset Yield Stress =", round(yield_stress_1045, 2), "MPa\n")
0.2% Offset Yield Stress = 452.54 MPa

7075 Aluminium

# --- 0.2% Offset Yield Calculation ---
E_7075 <- coef(fit_7075)[1]
sigma_offset_7075 <- E_7075 * (eps_7075 - 0.002)
diff_7075 <- eng_stress_7075 - sigma_offset_7075
i_7075 <- which(diff(sign(diff_7075)) != 0)[1]
yield_stress_7075 <- eng_stress_7075[i_7075]
yield_strain_7075 <- eps_7075[i_7075]

# --- Plot ---
plot(eps_7075, eng_stress_7075,
     type = "l", col = "darkorange", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "7075 Aluminum")
points(eps_7075, eng_stress_7075, col = "darkorange", pch = 16)

# Elastic best-fit and offset lines
fit_7075 <- lm(eng_stress_7075[eps_7075 <= eps_yield_7075] ~ 0 + eps_7075[eps_7075 <= eps_yield_7075])
abline(a = 0, b = coef(fit_7075), col = "purple", lwd = 2, lty = 2)
abline(a = -coef(fit_7075) * 0.002, b = coef(fit_7075), col = "darkgreen", lwd = 2, lty = 3)

# Yield point marker
points(yield_strain_7075, yield_stress_7075, pch = 19, col = "red")

# Annotate yield point
text(x = yield_strain_7075,
     y = yield_stress_7075,
     labels = paste0(round(yield_stress_7075, 1), " MPa"),
     pos = 3, col = "red", cex = 1.5)


cat("\n--- 7075 Aluminum ---\n")

--- 7075 Aluminum ---
cat("E =", round(E_7075, 2), "MPa\n")
E = 71655.21 MPa
cat("0.2% Offset Yield Strain =", round(yield_strain_7075, 5), "\n")
0.2% Offset Yield Strain = 0.00551 
cat("0.2% Offset Yield Stress =", round(yield_stress_7075, 2), "MPa\n")
0.2% Offset Yield Stress = 270.38 MPa

1018 Steel

# --- 0.2% Offset Yield Calculation ---
E_1018 <- coef(fit_1018)[1]
sigma_offset_1018 <- E_1018 * (eps_1018 - 0.002)
diff_1018 <- eng_stress_1018 - sigma_offset_1018
i_1018 <- which(diff(sign(diff_1018)) != 0)[1]
yield_stress_1018 <- eng_stress_1018[i_1018]
yield_strain_1018 <- eps_1018[i_1018]

# --- Plot ---
plot(eps_1018, eng_stress_1018,
     type = "l", col = "steelblue", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "1018 Steel",
     xlim = c(0, 0.005),       # expand x-axis a bit
     ylim = c(0, 310))         # expand y-axis to make space for red text

points(eps_1018, eng_stress_1018, col = "steelblue", pch = 16)

# Elastic best-fit and offset lines
fit_1018 <- lm(eng_stress_1018[eps_1018 <= eps_yield_1018] ~ 0 + eps_1018[eps_1018 <= eps_yield_1018])
abline(a = 0, b = coef(fit_1018), col = "purple", lwd = 2, lty = 2)
abline(a = -coef(fit_1018) * 0.002, b = coef(fit_1018), col = "darkgreen", lwd = 2, lty = 3)

# Yield point marker
points(yield_strain_1018, yield_stress_1018, pch = 19, col = "red")

# Annotate yield point
text(x = yield_strain_1018,
     y = yield_stress_1018,
     labels = paste0(round(yield_stress_1018, 1), " MPa"),
     pos = 3, col = "red", cex = 2)


cat("\n--- 1018 Steel ---\n")

--- 1018 Steel ---
cat("E =", round(E_1018, 2), "MPa\n")
E = 104377.6 MPa
cat("0.2% Offset Yield Strain =", round(yield_strain_1018, 5), "\n")
0.2% Offset Yield Strain = 0.00445 
cat("0.2% Offset Yield Stress =", round(yield_stress_1018, 2), "MPa\n")
0.2% Offset Yield Stress = 272.79 MPa

EMMA Plastic

# --- 0.2% Offset Yield Calculation ---
E_PMMA <- coef(fit_PMMA)[1]
sigma_offset_PMMA <- E_PMMA * (eps_PMMA - 0.002)
diff_PMMA <- eng_stress_PMMA - sigma_offset_PMMA
i_PMMA <- which(diff(sign(diff_PMMA)) != 0)[1]
yield_stress_PMMA <- eng_stress_PMMA[i_PMMA]
yield_strain_PMMA <- eps_PMMA[i_PMMA]

# --- Plot  ---
plot(eps_PMMA, eng_stress_PMMA,
     type = "l", col = "black", lwd = 2,
     xlab = "Strain (-)", ylab = "Stress (MPa)",
     main = "PMMA (Compressive Test)")
points(eps_PMMA, eng_stress_PMMA, col = "black", pch = 10)

# Elastic best-fit and offset lines
fit_PMMA <- lm(eng_stress_PMMA[eps_PMMA <= eps_yield_PMMA] ~ 0 + eps_PMMA[eps_PMMA <= eps_yield_PMMA])
abline(a = 0, b = coef(fit_PMMA), col = "purple", lwd = 2, lty = 2)
abline(a = -coef(fit_PMMA) * 0.002, b = coef(fit_PMMA), col = "darkgreen", lwd = 2, lty = 3)

# Yield point marker
points(yield_strain_PMMA, yield_stress_PMMA, pch = 19, col = "red")

# Annotate yield point with stress label
text(x = yield_strain_PMMA,
     y = yield_stress_PMMA,
     labels = paste0(round(yield_stress_PMMA, 1), " MPa"),
     pos = 3, col = "red", cex = 1.5)


cat("\n--- PMMA ---\n")

--- PMMA ---
cat("E =", round(E_PMMA, 2), "MPa\n")
E = 1958.5 MPa
cat("0.2% Offset Yield Strain =", round(yield_strain_PMMA, 5), "\n")
0.2% Offset Yield Strain = 0.05505 
cat("0.2% Offset Yield Stress =", round(yield_stress_PMMA, 2), "MPa\n")
0.2% Offset Yield Stress = 104.36 MPa
# Load package
library(knitr)



# Use your stored variables
youngs_modulus <- c(E_1018, E_1045, E_7075, E_PMMA)
yield_stress_0p2 <- c(yield_stress_1018, yield_stress_1045, yield_stress_7075, yield_stress_PMMA)
ultimate_strength <- c(ultimate_1018, ultimate_1045, ultimate_7075, ultimate_PMMA)

# Build data frame
table_data <- data.frame(
  row.names = c("Young’s Modulus", "0.2% Offset Yield Stress", "Ultimate Strength"),
  `1018 Steel` = round(c(youngs_modulus[1], yield_stress_0p2[1], ultimate_strength[1]), 2),
  `1045 Steel` = round(c(youngs_modulus[2], yield_stress_0p2[2], ultimate_strength[2]), 2),
  `7075 Aluminum Alloy` = round(c(youngs_modulus[3], yield_stress_0p2[3], ultimate_strength[3]), 2),
  `PMMA` = round(c(youngs_modulus[4], yield_stress_0p2[4], ultimate_strength[4]), 2)
)

# Print the table
kable(table_data, caption = "Table 4. Young’s Modulus, 0.2% Offset Yield Stress, and Ultimate Strength of Listed Materials")
Table 4. Young’s Modulus, 0.2% Offset Yield Stress, and Ultimate Strength of Listed Materials
X1018.Steel X1045.Steel X7075.Aluminum.Alloy PMMA
Young’s Modulus 104377.61 195069.43 71655.21 1958.50
0.2% Offset Yield Stress 272.79 452.54 270.38 104.36
Ultimate Strength 274.78 586.81 424.68 114.33

# Message
cat("Table generated successfully!\n")
Table generated successfully!
LS0tCnRpdGxlOiAiTUUzMzAgTGFiIDE6IENvbXByZXNzaW9uICYgSGFyZG5lc3MiCm91dHB1dDogaHRtbF9ub3RlYm9vawphdXRob3I6IEpvc2h1YSBaaGFuZwotLS0KCiMjIyBMb2FkIENTVnMKYGBge3J9CnN0ZWVsXzEwMThfZGF0YSA8LSByZWFkLmNzdigiTTEyX0FfMTAxOC5jc3YiLCBoZWFkZXIgPSBUUlVFKQpzdGVlbF8xMDQ1X2RhdGEgPC0gcmVhZC5jc3YoIk0xMl9BXzEwNDUuY3N2IiwgaGVhZGVyID0gVFJVRSkKYWxfNzA3NV9kYXRhICAgIDwtIHJlYWQuY3N2KCJNMTJfQV83MDc1LmNzdiIsIGhlYWRlciA9IFRSVUUpCnBtbWFfZGF0YSAgICAgICA8LSByZWFkLmNzdigiTTEyX0FfUE1NQS5jc3YiLCBoZWFkZXIgPSBUUlVFKQpgYGAKCiMjIyBFeHRyYWN0IGRhdGEgYW5kIEdlb21ldHJ5CmBgYHtyLHdhcm5pbmc9RkFMU0V9CiMgU3RlZWwgMTAxOApkaXNfMTAxOCA8LSBhcy5udW1lcmljKHN0ZWVsXzEwMThfZGF0YSREaXNwbGFjZW1lbnQpCkZfMTAxOCAgIDwtIGFzLm51bWVyaWMoc3RlZWxfMTAxOF9kYXRhJEZvcmNlKQplcHNfMTAxOCA8LSBhcy5udW1lcmljKHN0ZWVsXzEwMThfZGF0YSRDb21wb3NpdGUuc3RyYWluKQpsXzEwMTggPC0gNjQuOTI7IGRfMTAxOCA8LSAxOS4wNTsgQV8xMDE4IDwtIHBpLzQgKiBkXzEwMTheMgpzaWdtYV9lbmdfMTAxOCA8LSBGXzEwMTggLyBBXzEwMTggKiAxMDAwCnNpZ21hX3RydWVfMTAxOCA8LSBzaWdtYV9lbmdfMTAxOCAqICgxICsgZXBzXzEwMTgpCmVwc190cnVlXzEwMTggPC0gbG9nKDEgKyBlcHNfMTAxOCkKdWx0aW1hdGVfMTAxODwtIG1heChzaWdtYV9lbmdfMTAxOCwgbmEucm0gPSBUUlVFKQpmcmFjdHVyZV8xMDE4IDwtIGxlbmd0aChzaWdtYV9lbmdfMTAxOCkKCiMgU3RlZWwgMTA0NQpkaXNfMTA0NSA8LSBhcy5udW1lcmljKHN0ZWVsXzEwNDVfZGF0YSREaXNwbGFjZW1lbnQpCkZfMTA0NSAgIDwtIGFzLm51bWVyaWMoc3RlZWxfMTA0NV9kYXRhJEZvcmNlKQplcHNfMTA0NSA8LSBhcy5udW1lcmljKHN0ZWVsXzEwNDVfZGF0YSRDb21wb3NpdGUuc3RyYWluKQpsXzEwNDUgPC0gMzkuODsgIGRfMTA0NSA8LSAxMi41NTsgQV8xMDQ1IDwtIHBpLzQgKiBkXzEwNDVeMgpzaWdtYV9lbmdfMTA0NSA8LSBGXzEwNDUgLyBBXzEwNDUgKiAxMDAwCnNpZ21hX3RydWVfMTA0NSA8LSBzaWdtYV9lbmdfMTA0NSAqICgxICsgZXBzXzEwNDUpCmVwc190cnVlXzEwNDUgPC0gbG9nKDEgKyBlcHNfMTA0NSkKdWx0aW1hdGVfMTA0NTwtIG1heChzaWdtYV9lbmdfMTA0NSwgbmEucm0gPSBUUlVFKQpmcmFjdHVyZV8xMDQ1IDwtIGxlbmd0aChzaWdtYV9lbmdfMTA0NSkKCgojIEFsdW1pbnVtIDcwNzUKZGlzXzcwNzUgPC0gYXMubnVtZXJpYyhhbF83MDc1X2RhdGEkRGlzcGxhY2VtZW50KQpGXzcwNzUgICA8LSBhcy5udW1lcmljKGFsXzcwNzVfZGF0YSRGb3JjZSkKZXBzXzcwNzUgPC0gYXMubnVtZXJpYyhhbF83MDc1X2RhdGEkQ29tcG9zaXRlLnN0cmFpbikKbF83MDc1IDwtIDM5LjkzOyBkXzcwNzUgPC0gMTIuODQ7IEFfNzA3NSA8LSBwaS80ICogZF83MDc1XjIKc2lnbWFfZW5nXzcwNzUgPC0gRl83MDc1IC8gQV83MDc1ICogMTAwMApzaWdtYV90cnVlXzcwNzUgPC0gc2lnbWFfZW5nXzcwNzUgKiAoMSArIGVwc183MDc1KQplcHNfdHJ1ZV83MDc1IDwtIGxvZygxICsgZXBzXzcwNzUpCnVsdGltYXRlXzcwNzUgPC0gbWF4KHNpZ21hX2VuZ183MDc1LCBuYS5ybSA9IFRSVUUpCmZyYWN0dXJlXzcwNzUgPC0gbGVuZ3RoKHNpZ21hX2VuZ183MDc1KQoKIyBQbGFzdGljIFBNTUEKZGlzX1BNTUEgPC0gYXMubnVtZXJpYyhwbW1hX2RhdGEkRGlzcGxhY2VtZW50KQpGX1BNTUEgICA8LSBhcy5udW1lcmljKHBtbWFfZGF0YSRGb3JjZSkKZXBzX1BNTUEgPC0gYXMubnVtZXJpYyhwbW1hX2RhdGEkQ29tcHJlc3NpdmUuc3RyYWluKQpsX1BNTUEgPC0gNjUuMDI7IGRfUE1NQSA8LSAxOS4wMTsgQV9QTU1BIDwtIHBpLzQgKiBkX1BNTUFeMgpzaWdtYV9lbmdfUE1NQSA8LSBGX1BNTUEgLyBBX1BNTUEgKiAxMDAwCnNpZ21hX3RydWVfUE1NQSA8LSBzaWdtYV9lbmdfUE1NQSAqICgxICsgZXBzX1BNTUEpCmVwc190cnVlX1BNTUEgPC0gbG9nKDEgKyBlcHNfUE1NQSkKZnJhY3R1cmVfUE1NQSA8LSBsZW5ndGgoc2lnbWFfZW5nX1BNTUEpCnVsdGltYXRlX1BNTUEgPC0gbWF4KHNpZ21hX2VuZ19QTU1BLCBuYS5ybSA9IFRSVUUpCgpgYGAKCgoKIyMjIFBsb3QgQWxsIEVuZ2luZWVyaW5nIEN1cnZlcyBpbiBvbmUgZ3JhcGgKYGBge3J9CmNvbG9ycyA8LSBjKCJmaXJlYnJpY2siLCAiZGFya29yYW5nZSIsICJzdGVlbGJsdWUiLCAiYmxhY2siKQpsYWJlbHMgPC0gYygiMTA0NSBTdGVlbCIsICI3MDc1IEFsdW1pbnVtIiwgIjEwMTggU3RlZWwiLCAiUE1NQSIpCnhtYXggPC0gbWF4KGMoZXBzXzEwNDUsIGVwc183MDc1LCBlcHNfMTAxOCwgZXBzX1BNTUEpLCBuYS5ybSA9IFRSVUUpCnltYXggPC0gbWF4KGMoc2lnbWFfZW5nXzEwNDUsIHNpZ21hX2VuZ183MDc1LCBzaWdtYV9lbmdfMTAxOCwgc2lnbWFfZW5nX1BNTUEpLCBuYS5ybSA9IFRSVUUpCnBhcihtZnJvdyA9IGMoMSwgMSkpCnBsb3QoZXBzXzEwNDUsIHNpZ21hX2VuZ18xMDQ1LCB0eXBlID0gImwiLCBjb2wgPSBjb2xvcnNbMV0sIGx3ZCA9IDIsCiAgICAgeGxpbSA9IGMoMCwgeG1heCksIHlsaW0gPSBjKDAsIHltYXgpLAogICAgIHhsYWIgPSAiU3RyYWluICgtKSIsIHlsYWIgPSAiU3RyZXNzIChNUGEpIiwKICAgICBtYWluID0gIlN0cmVzcyB2cy4gU3RyYWluIEN1cnZlcyAoQWxsIE1hdGVyaWFscykiKQpsaW5lcyhlcHNfNzA3NSwgc2lnbWFfZW5nXzcwNzUsIGNvbCA9IGNvbG9yc1syXSwgbHdkID0gMikKbGluZXMoZXBzXzEwMTgsIHNpZ21hX2VuZ18xMDE4LCBjb2wgPSBjb2xvcnNbM10sIGx3ZCA9IDIpCmxpbmVzKGVwc19QTU1BLCBzaWdtYV9lbmdfUE1NQSwgY29sID0gY29sb3JzWzRdLCBsd2QgPSAyKQpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kID0gbGFiZWxzLCBjb2wgPSBjb2xvcnMsIGx3ZCA9IDIsIGJ0eSA9ICJuIikKZ3JpZCgpCmBgYAojIyMgQWx1bWludW0gNzA3NSBFbmdpbmVlcmluZyB2cy4gVHJ1ZQpgYGB7cn0KcGxvdChlcHNfNzA3NSwgc2lnbWFfZW5nXzcwNzUsIHR5cGUgPSAibiIsCiAgICAgeGxhYiA9ICJTdHJhaW4gKG1tL21tKSIsIHlsYWIgPSAiU3RyZXNzIChNUGEpIiwKICAgICBtYWluID0gIjcwNzUgQWx1bWludW06IEVuZ2luZWVyaW5nIHZzIFRydWUiKQpncmlkKCkKcG9pbnRzKGVwc183MDc1LCBzaWdtYV9lbmdfNzA3NSwgY29sID0gInJveWFsYmx1ZSIsIHBjaCA9IDE2KQpwb2ludHMoZXBzX3RydWVfNzA3NSwgc2lnbWFfdHJ1ZV83MDc1LCBjb2wgPSAiZGFya29yYW5nZSIsIHBjaCA9IDE2KQpsZWdlbmQoImJvdHRvbXJpZ2h0IiwKICAgICAgIGxlZ2VuZCA9IGMoIkVuZ2luZWVyaW5nIM+D4oCTzrUiLCAiVHJ1ZSDPg+KAk861IiksCiAgICAgICBjb2wgPSBjKCJyb3lhbGJsdWUiLCAiZGFya29yYW5nZSIpLAogICAgICAgcGNoID0gMTYsIGJ0eSA9ICJuIikKYGBgCiMjIyBGb3VyIE1hdGVyaWFsIFN0cmVzcy1TdHJhaW4gQ3VydmUgQ29tcGFyc2lvbgpgYGB7cn0KcGFyKG1mcm93ID0gYygyLCAyKSkgCiMgMTA0NSBTdGVlbApwbG90KGVwc18xMDQ1LCBlbmdfc3RyZXNzXzEwNDUsCiAgICAgdHlwZSA9ICJsIiwgY29sID0gImZpcmVicmljayIsIGx3ZCA9IDIsCiAgICAgeGxhYiA9ICJTdHJhaW4gKC0pIiwgeWxhYiA9ICJTdHJlc3MgKE1QYSkiLAogICAgIG1haW4gPSAiMTA0NSBTdGVlbCIpCnBvaW50cyhlcHNfMTA0NSwgZW5nX3N0cmVzc18xMDQ1LCBjb2wgPSAiZmlyZWJyaWNrIiwgcGNoID0gMTYpCnBvaW50cyhlcHNfMTA0NVt1bHRpbWF0ZV8xMDQ1XSwgZW5nX3N0cmVzc18xMDQ1W3VsdGltYXRlXzEwNDVdLCBjb2wgPSAicHVycGxlIiwgcGNoID0gMTcsIGNleCA9IDEuNSkKbGVnZW5kKCJib3R0b21yaWdodCIsIGxlZ2VuZCA9IGMoIlVsdGltYXRlIFN0cmVzcyIpLCBwY2ggPSAxNywgY29sID0gInB1cnBsZSIsIGJ0eSA9ICJuIikKZ3JpZCgpCgojIDcwNzUgQWx1bWludW0KcGxvdChlcHNfNzA3NSwgZW5nX3N0cmVzc183MDc1LAogICAgIHR5cGUgPSAibCIsIGNvbCA9ICJkYXJrb3JhbmdlIiwgbHdkID0gMiwKICAgICB4bGFiID0gIlN0cmFpbiAoLSkiLCB5bGFiID0gIlN0cmVzcyAoTVBhKSIsCiAgICAgbWFpbiA9ICI3MDc1IEFsdW1pbnVtIikKcG9pbnRzKGVwc183MDc1LCBlbmdfc3RyZXNzXzcwNzUsIGNvbCA9ICJkYXJrb3JhbmdlIiwgcGNoID0gMTYpCnBvaW50cyhlcHNfNzA3NVt1bHRpbWF0ZV83MDc1XSwgZW5nX3N0cmVzc183MDc1W3VsdGltYXRlXzcwNzVdLCBjb2wgPSAicHVycGxlIiwgcGNoID0gMTcsIGNleCA9IDEuNSkKbGVnZW5kKCJib3R0b21yaWdodCIsIGxlZ2VuZCA9IGMoIlVsdGltYXRlIFN0cmVzcyIpLCBwY2ggPSAxNywgY29sID0gInB1cnBsZSIsIGJ0eSA9ICJuIikKZ3JpZCgpCgojIDEwMTggU3RlZWwKcGxvdChlcHNfMTAxOCwgZW5nX3N0cmVzc18xMDE4LAogICAgIHR5cGUgPSAibCIsIGNvbCA9ICJzdGVlbGJsdWUiLCBsd2QgPSAyLAogICAgIHhsYWIgPSAiU3RyYWluICgtKSIsIHlsYWIgPSAiU3RyZXNzIChNUGEpIiwKICAgICBtYWluID0gIjEwMTggU3RlZWwiKQpwb2ludHMoZXBzXzEwMTgsIGVuZ19zdHJlc3NfMTAxOCwgY29sID0gInN0ZWVsYmx1ZSIsIHBjaCA9IDE2KQpwb2ludHMoZXBzXzEwMThbdWx0aW1hdGVfMTAxOF0sIGVuZ19zdHJlc3NfMTAxOFt1bHRpbWF0ZV8xMDE4XSwgY29sID0gInB1cnBsZSIsIHBjaCA9IDE3LCBjZXggPSAxLjUpCmxlZ2VuZCgiYm90dG9tcmlnaHQiLCBsZWdlbmQgPSBjKCJVbHRpbWF0ZSBTdHJlc3MiKSwgcGNoID0gMTcsIGNvbCA9ICJwdXJwbGUiLCBidHkgPSAibiIpCmdyaWQoKQoKIyBQTU1BCnBsb3QoZXBzX1BNTUEsIGVuZ19zdHJlc3NfUE1NQSwKICAgICB0eXBlID0gImwiLCBjb2wgPSAiYmxhY2siLCBsd2QgPSAyLAogICAgIHhsYWIgPSAiU3RyYWluICgtKSIsIHlsYWIgPSAiU3RyZXNzIChNUGEpIiwKICAgICBtYWluID0gIlBNTUEiKQpwb2ludHMoZXBzX1BNTUEsIGVuZ19zdHJlc3NfUE1NQSwgY29sID0gImJsYWNrIiwgcGNoID0gMTApCnBvaW50cyhlcHNfUE1NQVt1bHRpbWF0ZV9QTU1BXSwgZW5nX3N0cmVzc19QTU1BW3VsdGltYXRlX1BNTUFdLCBjb2wgPSAicHVycGxlIiwgcGNoID0gMTcsIGNleCA9IDEuNSkKbGVnZW5kKCJib3R0b21yaWdodCIsIGxlZ2VuZCA9IGMoIlVsdGltYXRlIFN0cmVzcyIpLCBwY2ggPSAxNywgY29sID0gInB1cnBsZSIsIGJ0eSA9ICJuIikKZ3JpZCgpCmBgYApgYGB7cn0KIyBFeWUtYmFsbGluZyB1bHRpbWF0ZSBzdHJlc3MgKHdpbGwgYWRqdXN0IGJhc2VkIG9uIHRoZSBiZXN0IGZpdCBsaW5lKQplcHNfeWllbGRfMTA0NSA9IDAuMDAzMwplcHNfeWllbGRfNzA3NSA9IDAuMDA0CmVwc195aWVsZF8xMDE4ID0gMC4wMDI2CmVwc195aWVsZF9QTU1BID0gMC4wNwpgYGAKCmBgYHtyfQpFXzEwNDUgIDwtIGNvZWYobG0oZW5nX3N0cmVzc18xMDQ1W2Vwc18xMDQ1IDw9IGVwc195aWVsZF8xMDQ1XSB+IDAgKyBlcHNfMTA0NVtlcHNfMTA0NSA8PSBlcHNfeWllbGRfMTA0NV0pKVsxXQpFXzcwNzUgIDwtIGNvZWYobG0oZW5nX3N0cmVzc183MDc1W2Vwc183MDc1IDw9IGVwc195aWVsZF83MDc1XSB+IDAgKyBlcHNfNzA3NVtlcHNfNzA3NSA8PSBlcHNfeWllbGRfNzA3NV0pKVsxXQpFXzEwMTggIDwtIGNvZWYobG0oZW5nX3N0cmVzc18xMDE4W2Vwc18xMDE4IDw9IGVwc195aWVsZF8xMDE4XSB+IDAgKyBlcHNfMTAxOFtlcHNfMTAxOCA8PSBlcHNfeWllbGRfMTAxOF0pKVsxXQpFX1BNTUEgIDwtIGNvZWYobG0oZW5nX3N0cmVzc19QTU1BW2Vwc19QTU1BIDw9IGVwc195aWVsZF9QTU1BXSB+IDAgKyBlcHNfUE1NQVtlcHNfUE1NQSA8PSBlcHNfeWllbGRfUE1NQV0pKVsxXQoKY2F0KCJFXzEwNDUgID0iLCBFXzEwNDUsICJNUGFcbiIpCmNhdCgiRV83MDc1ICA9IiwgRV83MDc1LCAiTVBhXG4iKQpjYXQoIkVfMTAxOCAgPSIsIEVfMTAxOCwgIk1QYVxuIikKY2F0KCJFX1BNTUEgID0iLCBFX1BNTUEsICJNUGFcbiIpCmBgYAojIyMgMTA0NSBTdGVlbCAKYGBge3J9CiMgLS0tIDEwNDUgU3RlZWwgLS0tCkVfMTA0NSA8LSBjb2VmKGZpdF8xMDQ1KVsxXQpzaWdtYV9vZmZzZXRfMTA0NSA8LSBFXzEwNDUgKiAoZXBzXzEwNDUgLSAwLjAwMikKZGlmZl8xMDQ1IDwtIGVuZ19zdHJlc3NfMTA0NSAtIHNpZ21hX29mZnNldF8xMDQ1CmlfMTA0NSA8LSB3aGljaChkaWZmKHNpZ24oZGlmZl8xMDQ1KSkgIT0gMClbMV0KeWllbGRfc3RyZXNzXzEwNDUgPC0gZW5nX3N0cmVzc18xMDQ1W2lfMTA0NV0KeWllbGRfc3RyYWluXzEwNDUgPC0gZXBzXzEwNDVbaV8xMDQ1XQoKcGxvdChlcHNfMTA0NSwgZW5nX3N0cmVzc18xMDQ1LAogICAgIHR5cGUgPSAibCIsIGNvbCA9ICJmaXJlYnJpY2siLCBsd2QgPSAyLAogICAgIHhsYWIgPSAiU3RyYWluICgtKSIsIHlsYWIgPSAiU3RyZXNzIChNUGEpIiwKICAgICBtYWluID0gIjEwNDUgU3RlZWwiKQpwb2ludHMoZXBzXzEwNDUsIGVuZ19zdHJlc3NfMTA0NSwgY29sID0gImZpcmVicmljayIsIHBjaCA9IDE2KQphYmxpbmUoYSA9IDAsIGIgPSBjb2VmKGZpdF8xMDQ1KSwgY29sID0gInB1cnBsZSIsIGx3ZCA9IDIsIGx0eSA9IDIpCmFibGluZShhID0gLWNvZWYoZml0XzEwNDUpICogMC4wMDIsIGIgPSBjb2VmKGZpdF8xMDQ1KSwgY29sID0gImRhcmtncmVlbiIsIGx3ZCA9IDIsIGx0eSA9IDMpCnBvaW50cyh5aWVsZF9zdHJhaW5fMTA0NSwgeWllbGRfc3RyZXNzXzEwNDUsIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKdGV4dCh4ID0geWllbGRfc3RyYWluXzEwNDUsCiAgICAgeSA9IHlpZWxkX3N0cmVzc18xMDQ1LAogICAgIGxhYmVscyA9IHBhc3RlMChyb3VuZCh5aWVsZF9zdHJlc3NfMTA0NSwgMSksICIgTVBhIiksCiAgICAgcG9zID0gMywgY29sID0gInJlZCIsIGNleCA9IDEuNSkKCmNhdCgiXG4tLS0gMTA0NSBTdGVlbCAtLS1cbiIpCmNhdCgiRSA9Iiwgcm91bmQoRV8xMDQ1LCAyKSwgIk1QYVxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJhaW4gPSIsIHJvdW5kKHlpZWxkX3N0cmFpbl8xMDQ1LCA1KSwgIlxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJlc3MgPSIsIHJvdW5kKHlpZWxkX3N0cmVzc18xMDQ1LCAyKSwgIk1QYVxuIikKYGBgCgoKCiMjIyA3MDc1IEFsdW1pbml1bSAKYGBge3J9CiMgLS0tIDAuMiUgT2Zmc2V0IFlpZWxkIENhbGN1bGF0aW9uIC0tLQpFXzcwNzUgPC0gY29lZihmaXRfNzA3NSlbMV0Kc2lnbWFfb2Zmc2V0XzcwNzUgPC0gRV83MDc1ICogKGVwc183MDc1IC0gMC4wMDIpCmRpZmZfNzA3NSA8LSBlbmdfc3RyZXNzXzcwNzUgLSBzaWdtYV9vZmZzZXRfNzA3NQppXzcwNzUgPC0gd2hpY2goZGlmZihzaWduKGRpZmZfNzA3NSkpICE9IDApWzFdCnlpZWxkX3N0cmVzc183MDc1IDwtIGVuZ19zdHJlc3NfNzA3NVtpXzcwNzVdCnlpZWxkX3N0cmFpbl83MDc1IDwtIGVwc183MDc1W2lfNzA3NV0KCiMgLS0tIFBsb3QgLS0tCnBsb3QoZXBzXzcwNzUsIGVuZ19zdHJlc3NfNzA3NSwKICAgICB0eXBlID0gImwiLCBjb2wgPSAiZGFya29yYW5nZSIsIGx3ZCA9IDIsCiAgICAgeGxhYiA9ICJTdHJhaW4gKC0pIiwgeWxhYiA9ICJTdHJlc3MgKE1QYSkiLAogICAgIG1haW4gPSAiNzA3NSBBbHVtaW51bSIpCnBvaW50cyhlcHNfNzA3NSwgZW5nX3N0cmVzc183MDc1LCBjb2wgPSAiZGFya29yYW5nZSIsIHBjaCA9IDE2KQoKIyBFbGFzdGljIGJlc3QtZml0IGFuZCBvZmZzZXQgbGluZXMKZml0XzcwNzUgPC0gbG0oZW5nX3N0cmVzc183MDc1W2Vwc183MDc1IDw9IGVwc195aWVsZF83MDc1XSB+IDAgKyBlcHNfNzA3NVtlcHNfNzA3NSA8PSBlcHNfeWllbGRfNzA3NV0pCmFibGluZShhID0gMCwgYiA9IGNvZWYoZml0XzcwNzUpLCBjb2wgPSAicHVycGxlIiwgbHdkID0gMiwgbHR5ID0gMikKYWJsaW5lKGEgPSAtY29lZihmaXRfNzA3NSkgKiAwLjAwMiwgYiA9IGNvZWYoZml0XzcwNzUpLCBjb2wgPSAiZGFya2dyZWVuIiwgbHdkID0gMiwgbHR5ID0gMykKCiMgWWllbGQgcG9pbnQgbWFya2VyCnBvaW50cyh5aWVsZF9zdHJhaW5fNzA3NSwgeWllbGRfc3RyZXNzXzcwNzUsIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKCiMgQW5ub3RhdGUgeWllbGQgcG9pbnQKdGV4dCh4ID0geWllbGRfc3RyYWluXzcwNzUsCiAgICAgeSA9IHlpZWxkX3N0cmVzc183MDc1LAogICAgIGxhYmVscyA9IHBhc3RlMChyb3VuZCh5aWVsZF9zdHJlc3NfNzA3NSwgMSksICIgTVBhIiksCiAgICAgcG9zID0gMywgY29sID0gInJlZCIsIGNleCA9IDEuNSkKCmNhdCgiXG4tLS0gNzA3NSBBbHVtaW51bSAtLS1cbiIpCmNhdCgiRSA9Iiwgcm91bmQoRV83MDc1LCAyKSwgIk1QYVxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJhaW4gPSIsIHJvdW5kKHlpZWxkX3N0cmFpbl83MDc1LCA1KSwgIlxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJlc3MgPSIsIHJvdW5kKHlpZWxkX3N0cmVzc183MDc1LCAyKSwgIk1QYVxuIikKCmBgYAoKIyMgMTAxOCBTdGVlbApgYGB7cn0KIyAtLS0gMC4yJSBPZmZzZXQgWWllbGQgQ2FsY3VsYXRpb24gLS0tCkVfMTAxOCA8LSBjb2VmKGZpdF8xMDE4KVsxXQpzaWdtYV9vZmZzZXRfMTAxOCA8LSBFXzEwMTggKiAoZXBzXzEwMTggLSAwLjAwMikKZGlmZl8xMDE4IDwtIGVuZ19zdHJlc3NfMTAxOCAtIHNpZ21hX29mZnNldF8xMDE4CmlfMTAxOCA8LSB3aGljaChkaWZmKHNpZ24oZGlmZl8xMDE4KSkgIT0gMClbMV0KeWllbGRfc3RyZXNzXzEwMTggPC0gZW5nX3N0cmVzc18xMDE4W2lfMTAxOF0KeWllbGRfc3RyYWluXzEwMTggPC0gZXBzXzEwMThbaV8xMDE4XQoKIyAtLS0gUGxvdCAtLS0KcGxvdChlcHNfMTAxOCwgZW5nX3N0cmVzc18xMDE4LAogICAgIHR5cGUgPSAibCIsIGNvbCA9ICJzdGVlbGJsdWUiLCBsd2QgPSAyLAogICAgIHhsYWIgPSAiU3RyYWluICgtKSIsIHlsYWIgPSAiU3RyZXNzIChNUGEpIiwKICAgICBtYWluID0gIjEwMTggU3RlZWwiLAogICAgIHhsaW0gPSBjKDAsIDAuMDA1KSwgICAgICAgIyBleHBhbmQgeC1heGlzIGEgYml0CiAgICAgeWxpbSA9IGMoMCwgMzEwKSkgICAgICAgICAjIGV4cGFuZCB5LWF4aXMgdG8gbWFrZSBzcGFjZSBmb3IgcmVkIHRleHQKCnBvaW50cyhlcHNfMTAxOCwgZW5nX3N0cmVzc18xMDE4LCBjb2wgPSAic3RlZWxibHVlIiwgcGNoID0gMTYpCgojIEVsYXN0aWMgYmVzdC1maXQgYW5kIG9mZnNldCBsaW5lcwpmaXRfMTAxOCA8LSBsbShlbmdfc3RyZXNzXzEwMThbZXBzXzEwMTggPD0gZXBzX3lpZWxkXzEwMThdIH4gMCArIGVwc18xMDE4W2Vwc18xMDE4IDw9IGVwc195aWVsZF8xMDE4XSkKYWJsaW5lKGEgPSAwLCBiID0gY29lZihmaXRfMTAxOCksIGNvbCA9ICJwdXJwbGUiLCBsd2QgPSAyLCBsdHkgPSAyKQphYmxpbmUoYSA9IC1jb2VmKGZpdF8xMDE4KSAqIDAuMDAyLCBiID0gY29lZihmaXRfMTAxOCksIGNvbCA9ICJkYXJrZ3JlZW4iLCBsd2QgPSAyLCBsdHkgPSAzKQoKIyBZaWVsZCBwb2ludCBtYXJrZXIKcG9pbnRzKHlpZWxkX3N0cmFpbl8xMDE4LCB5aWVsZF9zdHJlc3NfMTAxOCwgcGNoID0gMTksIGNvbCA9ICJyZWQiKQoKIyBBbm5vdGF0ZSB5aWVsZCBwb2ludAp0ZXh0KHggPSB5aWVsZF9zdHJhaW5fMTAxOCwKICAgICB5ID0geWllbGRfc3RyZXNzXzEwMTgsCiAgICAgbGFiZWxzID0gcGFzdGUwKHJvdW5kKHlpZWxkX3N0cmVzc18xMDE4LCAxKSwgIiBNUGEiKSwKICAgICBwb3MgPSAzLCBjb2wgPSAicmVkIiwgY2V4ID0gMikKCmNhdCgiXG4tLS0gMTAxOCBTdGVlbCAtLS1cbiIpCmNhdCgiRSA9Iiwgcm91bmQoRV8xMDE4LCAyKSwgIk1QYVxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJhaW4gPSIsIHJvdW5kKHlpZWxkX3N0cmFpbl8xMDE4LCA1KSwgIlxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJlc3MgPSIsIHJvdW5kKHlpZWxkX3N0cmVzc18xMDE4LCAyKSwgIk1QYVxuIikKCmBgYAoKIyMjIEVNTUEgUGxhc3RpYwpgYGB7cn0KIyAtLS0gMC4yJSBPZmZzZXQgWWllbGQgQ2FsY3VsYXRpb24gLS0tCkVfUE1NQSA8LSBjb2VmKGZpdF9QTU1BKVsxXQpzaWdtYV9vZmZzZXRfUE1NQSA8LSBFX1BNTUEgKiAoZXBzX1BNTUEgLSAwLjAwMikKZGlmZl9QTU1BIDwtIGVuZ19zdHJlc3NfUE1NQSAtIHNpZ21hX29mZnNldF9QTU1BCmlfUE1NQSA8LSB3aGljaChkaWZmKHNpZ24oZGlmZl9QTU1BKSkgIT0gMClbMV0KeWllbGRfc3RyZXNzX1BNTUEgPC0gZW5nX3N0cmVzc19QTU1BW2lfUE1NQV0KeWllbGRfc3RyYWluX1BNTUEgPC0gZXBzX1BNTUFbaV9QTU1BXQoKIyAtLS0gUGxvdCAgLS0tCnBsb3QoZXBzX1BNTUEsIGVuZ19zdHJlc3NfUE1NQSwKICAgICB0eXBlID0gImwiLCBjb2wgPSAiYmxhY2siLCBsd2QgPSAyLAogICAgIHhsYWIgPSAiU3RyYWluICgtKSIsIHlsYWIgPSAiU3RyZXNzIChNUGEpIiwKICAgICBtYWluID0gIlBNTUEgKENvbXByZXNzaXZlIFRlc3QpIikKcG9pbnRzKGVwc19QTU1BLCBlbmdfc3RyZXNzX1BNTUEsIGNvbCA9ICJibGFjayIsIHBjaCA9IDEwKQoKIyBFbGFzdGljIGJlc3QtZml0IGFuZCBvZmZzZXQgbGluZXMKZml0X1BNTUEgPC0gbG0oZW5nX3N0cmVzc19QTU1BW2Vwc19QTU1BIDw9IGVwc195aWVsZF9QTU1BXSB+IDAgKyBlcHNfUE1NQVtlcHNfUE1NQSA8PSBlcHNfeWllbGRfUE1NQV0pCmFibGluZShhID0gMCwgYiA9IGNvZWYoZml0X1BNTUEpLCBjb2wgPSAicHVycGxlIiwgbHdkID0gMiwgbHR5ID0gMikKYWJsaW5lKGEgPSAtY29lZihmaXRfUE1NQSkgKiAwLjAwMiwgYiA9IGNvZWYoZml0X1BNTUEpLCBjb2wgPSAiZGFya2dyZWVuIiwgbHdkID0gMiwgbHR5ID0gMykKCiMgWWllbGQgcG9pbnQgbWFya2VyCnBvaW50cyh5aWVsZF9zdHJhaW5fUE1NQSwgeWllbGRfc3RyZXNzX1BNTUEsIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKCiMgQW5ub3RhdGUgeWllbGQgcG9pbnQgd2l0aCBzdHJlc3MgbGFiZWwKdGV4dCh4ID0geWllbGRfc3RyYWluX1BNTUEsCiAgICAgeSA9IHlpZWxkX3N0cmVzc19QTU1BLAogICAgIGxhYmVscyA9IHBhc3RlMChyb3VuZCh5aWVsZF9zdHJlc3NfUE1NQSwgMSksICIgTVBhIiksCiAgICAgcG9zID0gMywgY29sID0gInJlZCIsIGNleCA9IDEuNSkKCmNhdCgiXG4tLS0gUE1NQSAtLS1cbiIpCmNhdCgiRSA9Iiwgcm91bmQoRV9QTU1BLCAyKSwgIk1QYVxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJhaW4gPSIsIHJvdW5kKHlpZWxkX3N0cmFpbl9QTU1BLCA1KSwgIlxuIikKY2F0KCIwLjIlIE9mZnNldCBZaWVsZCBTdHJlc3MgPSIsIHJvdW5kKHlpZWxkX3N0cmVzc19QTU1BLCAyKSwgIk1QYVxuIikKCmBgYAoKYGBge3J9CiMgTG9hZCBwYWNrYWdlCmxpYnJhcnkoa25pdHIpCgoKIyBVc2UgeW91ciBzdG9yZWQgdmFyaWFibGVzCnlvdW5nc19tb2R1bHVzIDwtIGMoRV8xMDE4LCBFXzEwNDUsIEVfNzA3NSwgRV9QTU1BKQp5aWVsZF9zdHJlc3NfMHAyIDwtIGMoeWllbGRfc3RyZXNzXzEwMTgsIHlpZWxkX3N0cmVzc18xMDQ1LCB5aWVsZF9zdHJlc3NfNzA3NSwgeWllbGRfc3RyZXNzX1BNTUEpCnVsdGltYXRlX3N0cmVuZ3RoIDwtIGModWx0aW1hdGVfMTAxOCwgdWx0aW1hdGVfMTA0NSwgdWx0aW1hdGVfNzA3NSwgdWx0aW1hdGVfUE1NQSkKCiMgQnVpbGQgZGF0YSBmcmFtZQp0YWJsZV9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgcm93Lm5hbWVzID0gYygiWW91bmfigJlzIE1vZHVsdXMiLCAiMC4yJSBPZmZzZXQgWWllbGQgU3RyZXNzIiwgIlVsdGltYXRlIFN0cmVuZ3RoIiksCiAgYDEwMTggU3RlZWxgID0gcm91bmQoYyh5b3VuZ3NfbW9kdWx1c1sxXSwgeWllbGRfc3RyZXNzXzBwMlsxXSwgdWx0aW1hdGVfc3RyZW5ndGhbMV0pLCAyKSwKICBgMTA0NSBTdGVlbGAgPSByb3VuZChjKHlvdW5nc19tb2R1bHVzWzJdLCB5aWVsZF9zdHJlc3NfMHAyWzJdLCB1bHRpbWF0ZV9zdHJlbmd0aFsyXSksIDIpLAogIGA3MDc1IEFsdW1pbnVtIEFsbG95YCA9IHJvdW5kKGMoeW91bmdzX21vZHVsdXNbM10sIHlpZWxkX3N0cmVzc18wcDJbM10sIHVsdGltYXRlX3N0cmVuZ3RoWzNdKSwgMiksCiAgYFBNTUFgID0gcm91bmQoYyh5b3VuZ3NfbW9kdWx1c1s0XSwgeWllbGRfc3RyZXNzXzBwMls0XSwgdWx0aW1hdGVfc3RyZW5ndGhbNF0pLCAyKQopCgprYWJsZSh0YWJsZV9kYXRhLCBjYXB0aW9uID0gIllvdW5n4oCZcyBNb2R1bHVzLCAwLjIlIE9mZnNldCBZaWVsZCBTdHJlc3MsIGFuZCBVbHRpbWF0ZSBTdHJlbmd0aCBvZiBMaXN0ZWQgTWF0ZXJpYWxzIikKCmBgYAoKCgoKCg==