I. Analyse descriptive
Justification
L’analyse descriptive permet de comprendre la distribution et les
caractéristiques générales des données, offrant ainsi un aperçu
préliminaire des tendances et des associations potentielles entre les
variables étudiées.
fastggplot <- function(data, x_var, title, x_label, y_label) {
# Calcul des fréquences
freq_data <- data %>%
count(.data[[x_var]]) %>%
mutate(percentage = n / sum(n) * 100) # Calcul des pourcentages
ggplot(data, aes(x = factor(.data[[x_var]]), fill = factor(.data[[x_var]]))) +
geom_bar(color = "black", alpha = 0.8) +
geom_label(data = freq_data, aes(x = factor(.data[[x_var]]), y = n + 1, label = paste0(round(percentage, 1), "%")),
position = position_dodge(width = 0.8), size = 5, color = "black", fontface = "bold", fill = "white", label.padding = unit(0.2, "lines")) +
labs(title = title, x = x_label, y = y_label, fill = x_var) +
theme_minimal() +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"))
}
a. Répartion des étudiants en fonction de la bourse
Boursier <- fastggplot(data, "Boursier", "Répartition en fonction de la bourse", "", "Nombre d'occurence")
Boursier

b. Répartion des étudiants en fonction du sexe
Sexe <- fastggplot(data, "Sexe", "Répartition homme femme", "", "Nombre de cas")
Sexe <- Sexe + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Sexe

c. Répartion des étudiants en fonction de la catégorie
socio-professionnele du parent 1
PCS_Parent1 <- fastggplot(data, "PCS_Parent1", "Catégorie socio-professionnelle du parent 1", "", "Nombre d'occurence")
PCS_Parent1 <- PCS_Parent1 + theme(axis.text.x = element_text(angle = 45, hjust = 1))
PCS_Parent1

d. Répartion des étudiants en fonction de la bourse
PCS_Parent2 = fastggplot(data, "PCS_Parent2", "Catégorie socio-professionnelle du parent 2", "", "Nombre d'occurence")
PCS_Parent2 <- PCS_Parent2 + theme(axis.text.x = element_text(angle = 45, hjust = 1))
PCS_Parent2

e.Répartion des étudiants en fonction du bac
Bac = fastggplot(data, "Bac_Groupe", "Bac", "", "Nombre d'occurence")
Bac <- Bac + theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7))
Bac

f. Répartion de la mention des étudiants au Bac
Bac_Mention = fastggplot(data, "Bac_Mention", "Mention au Bac", "", "Nombre d'occurence")
Bac_Mention <- Bac_Mention + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Bac_Mention

g. Intitulé d’étude en 2023-2024
note2023 = fastggplot(data, "2023", "Intitulé d'étude en 2023-2024", "", "Nombre d'occurence")
note2023 <- note2023 +theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7))
note2023

h. Résultat des étudiants en 2023-2024
Resultat2023 = fastggplot(data, "Resultat", "Résultat 2023", "", "Nombre d'occurence")
Resultat2023 <- Resultat2023 + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Resultat2023

j. Moyenne générale des étudiants en 2023-2024
# Histogramme amélioré pour la variable Note
library(ggplot2)
noted = ggplot(data, aes(x = Note)) +
geom_histogram(binwidth = 1, fill = "#69b3a2", color = "white", alpha = 0.8) +
labs(
title = "Distribution des Notes",
x = "Note",
y = "Fréquence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 18, face = "bold", color = "#2a3d3f"),
axis.title = element_text(size = 14, face = "bold", color = "#2a3d3f"),
axis.text = element_text(size = 12, color = "#2a3d3f"),
panel.grid.major = element_line(color = "#d3d3d3"),
panel.grid.minor = element_blank()
)
noted

II. Analyse inférentielle
L’analyse inférentielle entre les notes et les autres variables vise
à déterminer si des facteurs comme le statut de boursier, le sexe, la
catégorie socioprofessionnelle des parents, ou les mentions au bac
influencent les résultats académiques.
a. Sexe et notes
# Effectuer le test t de Student entre Sexe et Note
t_test_result10 <- t.test(Note ~ Sexe, data = data, var.equal = TRUE)
# Extraire la p-value du test
p_value10 <- t_test_result10$p.value
# Créer un boxplot et ajouter la p-value sur le graphique
library(ggplot2)
ggplot(data, aes(x = Sexe, y = Note, fill = Sexe)) +
geom_boxplot(color = "black", alpha = 0.6) +
labs(title = "Comparaison des notes selon le sexe",
x = "Sexe", y = "Note") +
theme_minimal() +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold")) +
# Ajouter la p-value sur le graphique
annotate("text", x = 1.5, y = max(data$Note, na.rm = TRUE),
label = paste("p-value =", round(p_value10, 4)),
size = 5, color = "red", fontface = "bold")

b. Bourse et notes
# Effectuer le test t de Student entre Boursier et Note
t_test_result1 <- t.test(Note ~ Boursier, data = data)
# Extraire la p-value du test
p_value1 <- t_test_result1$p.value
# Créer un boxplot et ajouter la p-value sur le graphique
library(ggplot2)
ggplot(data, aes(x = Boursier, y = Note, fill = Boursier)) +
geom_boxplot(color = "black", alpha = 0.6) +
labs(title = "Comparaison des notes entre boursiers et non-boursiers",
x = "Statut Boursier", y = "Note") +
theme_minimal() +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold")) +
# Ajouter la p-value sur le graphique
annotate("text", x = 1.5, y = max(data$Note, na.rm = TRUE),
label = paste("p-value =", round(p_value1, 4)),
size = 5, color = "red", fontface = "bold")

c. Notes et catégorie socio-professionnelle du parent 1
# Effectuer une ANOVA entre PCS_Parent1 et Note
anova_result1 <- aov(Note ~ PCS_Parent1, data = data)
# Extraire la p-value de l'ANOVA
anova_p_value2 <- summary(anova_result1)[[1]][["Pr(>F)"]][1]
# Créer un boxplot avec p-value et ajuster l'apparence des noms des variables
ggplot(data, aes(x = PCS_Parent1, y = Note, fill = PCS_Parent1)) +
geom_boxplot(color = "black", alpha = 0.6) +
labs(
title = "Comparaison des notes selon la PCS du parent 1",
x = "PCS Parent 1",
y = "Note"
) +
theme_minimal() +
theme(
axis.text.x = element_text(size = 10, angle = 45, hjust = 1), # Taille réduite et rotation des noms
axis.text.y = element_text(size = 12), # Taille des étiquettes de l'axe Y
axis.title = element_text(size = 14, face = "bold"), # Taille et style des titres des axes
plot.title = element_text(size = 16, face = "bold") # Taille et style du titre principal
) +
# Ajouter la p-value en bas à droite
annotate(
"text",
x = length(unique(data$PCS_Parent1)), # Position x (dernière catégorie)
y = min(data$Note, na.rm = TRUE) - 1, # Position y légèrement sous le minimum des notes
label = paste("p-value =", round(anova_p_value2, 4)),
size = 5,
color = "red",
fontface = "bold",
hjust = 1 # Alignement à droite
)

NA
NA
d. Notes et catégorie-professionnelle du parent 2
# Effectuer une ANOVA entre PCS_Parent1 et Note
anova_result2 <- aov(Note ~ PCS_Parent2, data = data)
# Extraire la p-value de l'ANOVA
anova_p_value3 <- summary(anova_result2)[[1]][["Pr(>F)"]][1]
# Créer un boxplot avec p-value et ajuster l'apparence des noms des variables
ggplot(data, aes(x = PCS_Parent2, y = Note, fill = PCS_Parent2)) +
geom_boxplot(color = "black", alpha = 0.6) +
labs(
title = "Comparaison des notes selon la PCS du parent 2",
x = "PCS Parent 2",
y = "Note"
) +
theme_minimal() +
theme(
axis.text.x = element_text(size = 10, angle = 45, hjust = 1), # Taille réduite et rotation des noms
axis.text.y = element_text(size = 12), # Taille des étiquettes de l'axe Y
axis.title = element_text(size = 14, face = "bold"), # Taille et style des titres des axes
plot.title = element_text(size = 16, face = "bold") # Taille et style du titre principal
) +
# Ajouter la p-value en bas à droite
annotate(
"text",
x = length(unique(data$PCS_Parent1)), # Position x (dernière catégorie)
y = min(data$Note, na.rm = TRUE) - 1, # Position y légèrement sous le minimum des notes
label = paste("p-value =", round(anova_p_value3, 4)),
size = 5,
color = "red",
fontface = "bold",
hjust = 1 # Alignement à droite
)

e. Notes et mention au bac
anova_result3 <- aov(Note ~ Bac_Mention, data = data)
# Extraire la p-value de l'ANOVA
anova_p_value4 <- summary(anova_result3)[[1]][["Pr(>F)"]][1]
# Créer un boxplot avec p-value et ajuster l'apparence des noms des variables
ggplot(data, aes(x = Bac_Mention, y = Note, fill = Bac_Mention)) +
geom_boxplot(color = "black", alpha = 0.6) +
labs(
title = "Comparaison des notes selon la mention au bac",
x = "Mention au Bac",
y = "Note"
) +
theme_minimal() +
theme(
axis.text.x = element_text(size = 10, angle = 45, hjust = 1), # Taille réduite et rotation des noms
axis.text.y = element_text(size = 12), # Taille des étiquettes de l'axe Y
axis.title = element_text(size = 14, face = "bold"), # Taille et style des titres des axes
plot.title = element_text(size = 16, face = "bold") # Taille et style du titre principal
) +
# Ajouter la p-value en bas à droite
annotate(
"text",
x = length(unique(data$Bac_Mention)), # Position x (dernière catégorie)
y = min(data$Note, na.rm = TRUE) - 1, # Position y légèrement sous le minimum des notes
label = paste("p-value =", round(anova_p_value4, 4)),
size = 5,
color = "green",
fontface = "bold",
hjust = 1 # Alignement à droite
)

BUT
setwd("C:/Users/Valen/Desktop/BDIP")
data <- read.csv("Données_BUTClean.csv", stringsAsFactors = FALSE)
data = data[,-2]
data <- data.frame(lapply(data, as.factor))
data$bourse_type <- as.factor(ifelse(is.na(data$bourse_type), "Pas de bourse", as.character(data$bourse_type)))
data$bourse_eche <- as.factor(ifelse(data$bourse_type == "Pas de bourse", "Pas de bourse", as.character(data$bourse_eche)))
data$bourse_eche <- as.factor(ifelse(data$bourse_eche == 10, "Echelon 1",
ifelse(data$bourse_eche == 20, "Echelon 2",
ifelse(data$bourse_eche == 30, "Echelon 3",
ifelse(data$bourse_eche == 40, "Echelon 4",
ifelse(data$bourse_eche == 50 | data$bourse_eche == 5, "Echelon 5",
ifelse(data$bourse_eche == 60, "Echelon 6",
ifelse(data$bourse_eche == 70, "Echelon 7",
as.character(data$bourse_eche)))))))))
data$bourse_eche <- as.character(data$bourse_eche)
data$bourse_eche[is.na(data$bourse_eche) & !is.na(data$boursier)] <- "échelon non connu"
data$bourse_eche[data$boursier == "N"] <- "Pas de bourse"
data$bourse_eche <- ifelse(data$bourse_eche %in% c("Echelon 1", "Echelon 2"), "Bourse faible",
ifelse(data$bourse_eche %in% c("Echelon 3", "Echelon 4", "Echelon 5"), "Bourse moyenne",
ifelse(data$bourse_eche %in% c("Echelon 6", "Echelon 7"), "Bourse élevée",
as.character(data$bourse_eche))))
data = data[,-c(9)]
data$logement <- factor(data$logement,
levels = c("chambr etu", "log perso", "parents", "résid uni"),
labels = c("Chambre étudiante", "Logement personnel", "Parents", "Résidence universitaire"))
data$bac_mention <- ifelse(data$bac_mention == "Passable", "Sans mention", as.character(data$bac_mention))
I. Analyse descriptive
L’analyse descriptive permet de comprendre la distribution et les
caractéristiques générales des données, offrant ainsi un aperçu
préliminaire des tendances et des associations potentielles entre les
variables étudiées.
a. Répartition des étudiants en fonction du sexe
fastggplot <- function(data, x_var, title, x_label, y_label) {
# Calcul des fréquences
freq_data <- data %>%
count(.data[[x_var]]) %>%
mutate(percentage = n / sum(n) * 100) # Calcul des pourcentages
ggplot(data, aes(x = factor(.data[[x_var]]), fill = factor(.data[[x_var]]))) +
geom_bar(color = "black", alpha = 0.8) +
geom_label(data = freq_data, aes(x = factor(.data[[x_var]]), y = n + 1, label = paste0(round(percentage, 1), "%")),
position = position_dodge(width = 0.8), size = 5, color = "black", fontface = "bold", fill = "white", label.padding = unit(0.2, "lines")) +
labs(title = title, x = x_label, y = y_label, fill = x_var) +
theme_minimal() +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"))
}
data$PCS_parent1_categorized <- NA
# Cadres et professions supérieures
data$PCS_parent1_categorized[data$PCS_parent1 %in% c("Chef entpr", "Conduc eng", "ingénieur", "prof lib", "professeur", "Cadre Retr", "Retr")] <- "Cadres et professions supérieures"
# Professions intermédiaires
data$PCS_parent1_categorized[data$PCS_parent1 %in% c("emp adm en", "emp commer", "Artisans", "Pr Int ad", "int ad f p", "technicien", "cadr admin", "cadr f pub", "Administra", "Ag maitris", "Agri M Exp", "policier")] <- "Professions intermédiaires"
# Ouvriers
data$PCS_parent1_categorized[data$PCS_parent1 %in% c("Ouvr Ind", "Ouvr N Art", "SS prof -", "int ad com", "int san so", "Retr Pr In")] <- "Ouvriers"
# Inconnus ou autres
data$PCS_parent1_categorized[data$PCS_parent1 %in% c("inconnu", "retrait ar", "Retr Cadre")] <- "Inconnus ou autres"
data$dip_mention <- gsub("GENIE ELECTRIQUE ET INFORMATIQUE INDUSTRIELLE", "GENIE ELECTRIQUE", data$dip_mention)
data <- data[data$res_det != "Attente de note (sportif de haut niveau)", ]
data_filtered <- data %>%
filter(res_det != "Attente de note (sportif de haut niveau)")
colnames(data)[colnames(data) == "PCS_parent1_categorized"] <- "PCS_du_parent1"
data <- data %>%
mutate(res_det = case_when(
res_det == "Ajourné mais accès autorisé à étape sup." ~ "Ajourné",
res_det == "Non admis - Autorisé à redoubler" ~ "Ajourné",
res_det == "Réorienté" ~ "Défaillant",
TRUE ~ res_det # Garde les autres catégories inchangées
))
Sexe <- fastggplot(data, "sexe", "Répartition en fonction du sexe", "", "Nombre d'occurence")
Sexe

b. Répartition des étudiants en fonction du type de logement
Logement <- fastggplot(data, "logement", "Répartition en fonction du type de logement", "", "Nombre d'occurence")
Logement <- Logement + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Logement

c. Répartition en fonction de l’obtention de la bourse
Bourse <- fastggplot(data, "boursier", "Répartition de l'obtention de la bourse", "", "Nombre d'occurence")
Bourse <- Bourse + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Bourse

d. Répartition en fonction du type de bourse
Bourse2 <- fastggplot(data, "bourse_eche", "Répartition en fonction du type de bourse", "", "Nombre d'occurence")
Bourse2 <- Bourse2 + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Bourse2

e. Répartition en fonction du type de bac
Bac <- fastggplot(data, "bac_filiere", "Répartition en fonction du type de bac", "", "Nombre d'occurence")
Bac <- Bac + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Bac

f. Répartition en fonction de la mention au bac
Bac <- fastggplot(data, "bac_mention", "Répartition en fonction de la mention au bac", "", "Nombre d'occurence")
Bac

g. Catégorie socio-professionnelle du parent 1
ee <- fastggplot(data, "PCS_du_parent1", "Catégorie socio-professionnelle du parent 1", "", "Nombre d'occurence")
ee = ee + theme(axis.text.x = element_text(angle = 45, hjust = 1))
ee

h.Mention du diplôme préparé
mentiondip <- fastggplot(data, "dip_mention", "Mention du diplôme préparé", "", "Nombre d'occurence")
dip = mentiondip
dip

i. Résultat à l’année
result <- fastggplot(data, "res_det", "Résultat à l'année", "", "Nombre d'occurence")
result = result + theme(axis.text.x = element_text(angle = 45, hjust = 1))
result

II. Analyse inférentielle
a. Résultat et sexe
# Filtrer les données pour retirer "Attente de note"
data_filtered <- data %>%
filter(res_det != "Attente de note (sportif de haut niveau)")
# Créer un tableau de contingence entre sexe et res_det
table_contingence <- table(data_filtered$sexe, data_filtered$res_det)
# Effectuer un test du Chi² ou Fisher selon les effectifs
chisq_test <- chisq.test(table_contingence)
# Vérifier si des effectifs théoriques sont < 5
if(any(chisq_test$expected < 5)) {
test_result <- fisher.test(table_contingence)
test_type <- "Test exact de Fisher"
} else {
test_result <- chisq_test
test_type <- "Test du Chi²"
}
# Extraire la p-value
p_value <- test_result$p.value
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = sexe, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon le sexe",
x = "Sexe", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 5, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "red", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

NA
NA
b. Résultat et catégorie socio-professionnelle du parent 1
# Filtrer les données pour retirer "Attente de note"
data_filtered <- data %>%
filter(res_det != "Attente de note (sportif de haut niveau)")
# Créer un tableau de contingence entre res_det et PCS_du_parent1
table_contingence <- table(data_filtered$res_det, data_filtered$PCS_du_parent1)
# Extraire la p-value
p_value <- 0.214
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = PCS_du_parent1, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon la catégorie socio-professionnelle du parent 1",
x = "PCS du parent 1", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 4, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "red", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

c. Logement et résultat
# Créer un tableau de contingence entre res_det et logement
table_contingence <- table(data_filtered$res_det, data_filtered$logement)
# Extraire la p-value
p_value <- 0.1352
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = logement, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon le type de logement",
x = "Type de logement", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text = element_text(size = 12),
axis.title = element_text(size = 12, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 4, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "red", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

d. Résultat et type de bac
# Créer le tableau de contingence
table_contingence <- table(data_filtered$res_det, data_filtered$bac_filiere)
# Effectuer le test exact de Fisher
test_result <- fisher.test(table_contingence)
# Extraire la p-value
p_value <- 0.07
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = bac_filiere, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon le type de bac",
x = "Type de bac", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 4, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "green", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

e. Résultat et mention au bac
# Créer un tableau de contingence entre res_det et bac_mention
table_contingence <- table(data_filtered$res_det, data_filtered$bac_mention)
# Effectuer un test exact de Fisher si possible
test_type <- "Test exact de Fisher"
test_result <- tryCatch(
{
fisher.test(table_contingence)
},
error = function(e) {
cat("Fisher impossible, passage au Chi² avec simulation Monte Carlo\n")
test_type <<- "Test du Chi² avec simulation Monte Carlo"
chisq.test(table_contingence, simulate.p.value = TRUE, B = 10000)
}
)
# Extraire la p-value
p_value <- test_result$p.value
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = bac_mention, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon la mention au bac",
x = "Mention au bac", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 4, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "green", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

NA
NA
f. Résultat et bourse
# Créer un tableau de contingence entre res_det et boursier
table_contingence <- table(data_filtered$res_det, data_filtered$boursier)
# Effectuer un test exact de Fisher si possible
test_type <- "Test exact de Fisher"
test_result <- tryCatch(
{
fisher.test(table_contingence)
},
error = function(e) {
cat("Fisher impossible, passage au Chi² avec simulation Monte Carlo\n")
test_type <<- "Test du Chi² avec simulation Monte Carlo"
chisq.test(table_contingence, simulate.p.value = TRUE, B = 10000)
}
)
# Extraire la p-value
p_value <- test_result$p.value
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = boursier, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon le statut de boursier",
x = "Boursier", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 4, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "green", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

NA
NA
g. Résultat et type de bourse
# Créer un tableau de contingence entre res_det et bourse_eche
table_contingence <- table(data_filtered$res_det, data_filtered$bourse_eche)
# Effectuer un test exact de Fisher si possible
test_type <- "Test exact de Fisher"
test_result <- tryCatch(
{
fisher.test(table_contingence)
},
error = function(e) {
cat("Fisher impossible, passage au Chi² avec simulation Monte Carlo\n")
test_type <<- "Test du Chi² avec simulation Monte Carlo"
chisq.test(table_contingence, simulate.p.value = TRUE, B = 10000)
}
)
# Extraire la p-value
p_value <- test_result$p.value
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = bourse_eche, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon le type de bourse",
x = "Type de bourse", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 4, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "green", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

# Créer un tableau de contingence entre res_det et dip_mention
table_contingence <- table(data_filtered$res_det, data_filtered$dip_mention)
# Effectuer un test exact de Fisher si possible
test_type <- "Test exact de Fisher"
test_result <- tryCatch(
{
fisher.test(table_contingence)
},
error = function(e) {
cat("Fisher impossible, passage au Chi² avec simulation Monte Carlo\n")
test_type <<- "Test du Chi² avec simulation Monte Carlo"
chisq.test(table_contingence, simulate.p.value = TRUE, B = 10000)
}
)
# Extraire la p-value
p_value <- 0.004
# Créer le barplot principal
barplot <- ggplot(data_filtered, aes(x = dip_mention, fill = res_det)) +
geom_bar(position = "stack", color = "black") +
labs(title = "Répartition des résultats selon la mention du diplôme préparé",
x = "Mention du diplôme", y = "Effectif", fill = "Résultat déterminé") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text = element_text(size = 12),
axis.title = element_text(size = 14, face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
legend.position = "right") + # Légende à droite
geom_text(stat = "count", aes(label = ..count..),
position = position_stack(vjust = 0.5), size = 4, color = "white")
# Créer un texte contenant la p-value (à afficher sous la légende)
p_value_text <- ggdraw() +
draw_text(paste(test_type, "\np-value =", round(p_value, 4)),
size = 14, color = "green", hjust = 0.5)
# Combiner le graphique principal avec la p-value sous la légende
plot_grid(barplot, p_value_text, ncol = 1, rel_heights = c(4, 0.5))

LS0tDQp0aXRsZTogIkdyYXBoaXF1ZSBTVEFQUyINCmF1dGhvcjogIkJFQ0sgVmFsZW50aW4iDQpvdXRwdXQ6DQogIA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHRoZW1lOiBqb3VybmFsDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgc291cmNlOiBlbWJlZA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCmBgYHs9aHRtbH0NCjxzdHlsZT4NCmJvZHkgew0KICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KfQ0KDQoubmF2LWJhciB7DQogIHBvc2l0aW9uOiBzdGlja3k7DQogIHRvcDogMDsNCiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjsNCiAgcGFkZGluZzogMTBweDsNCiAgZGlzcGxheTogZmxleDsNCiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1hcm91bmQ7DQogIHotaW5kZXg6IDEwMDsNCiAgYm9yZGVyLWJvdHRvbTogMnB4IHNvbGlkICNkZGQ7DQogIGJveC1zaGFkb3c6IDBweCA0cHggNnB4IHJnYmEoMCwgMCwgMCwgMC4xKTsNCn0NCg0KLm5hdi1iYXIgYSB7DQogIGJhY2tncm91bmQtY29sb3I6ICMyOGE3NDU7DQogIGJvcmRlcjogbm9uZTsNCiAgY29sb3I6IHdoaXRlOw0KICBwYWRkaW5nOiAxMHB4IDIwcHg7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOw0KICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7DQogIGZvbnQtc2l6ZTogMTZweDsNCiAgbWFyZ2luOiA0cHggMnB4Ow0KICBjdXJzb3I6IHBvaW50ZXI7DQogIGJvcmRlci1yYWRpdXM6IDVweDsNCiAgdHJhbnNpdGlvbjogYmFja2dyb3VuZC1jb2xvciAwLjNzLCB0cmFuc2Zvcm0gMC4yczsNCn0NCg0KLm5hdi1iYXIgYTpob3ZlciB7DQogIGJhY2tncm91bmQtY29sb3I6ICMyMTg4Mzg7DQogIHRyYW5zZm9ybTogc2NhbGUoMS4wNSk7DQp9DQo8L3N0eWxlPg0KDQo8ZGl2IGNsYXNzPSJuYXYtYmFyIj4NCiAgPGEgaHJlZj0iI1NUQVBTIj5TVEFQUzwvYT4gDQogIDxhIGhyZWY9IiNCVVQiPkJVVDwvYT4NCjwvZGl2Pg0KDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgU1RBUFMNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpvcHRpb25zKHJlcG9zID0gYyhDUkFOID0gImh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnIikpDQoNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCg0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh2Y2QpDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShycGFydC5wbG90KQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShwUk9DKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoRmFjdG9NaW5lUikNCmluc3RhbGwucGFja2FnZXMoImFybSIpDQpsaWJyYXJ5KGFybSkNCmluc3RhbGwucGFja2FnZXMoInJlYWR4bCIpDQpsaWJyYXJ5KHJlYWR4bCkNCg0Kc2V0d2QoIkM6L1VzZXJzL1ZhbGVuL0Rlc2t0b3AvTWFjaGluZSBsZWFybmluZy8iKQ0KDQoNCiAgZGF0YSA9IHJlYWRfZXhjZWwoJ1NUQVBTLnhsc3gnKQ0KICBkYXRhID0gZGF0YVstMTMzLF0NCiAgDQogIGRhdGEgPC0gZGF0YVssIC1jKDEsIDIsMywgNCwgNyAsIDgpXSAgDQogIA0KDQoNCg0KY29sbmFtZXMoZGF0YSkgPC0gYygNCiJCb3Vyc2llciIsICJTZXhlIiwgDQogICJQQ1NfUGFyZW50MiIsICJQQ1NfUGFyZW50MSIsICJCYWNfR3JvdXBlIiwgIkJhY19NZW50aW9uIiwgDQogICIyMDIzIiwgIk5vdGUiLCAiUmVzdWx0YXQiLCAiMjAyNCINCikNCg0KDQoNCiMgVHJhbnNmb3JtZXIgbGVzIGNvbG9ubmVzIGRlIHR5cGUgImNociIgZW4gImZhY3RvciINCmRhdGEgPC0gZGF0YSAlPiUNCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5jaGFyYWN0ZXIpLCBhcy5mYWN0b3IpKQ0KDQoNCg0KIyBDcsOpYXRpb24gZCd1biB2ZWN0ZXVyIGRlIHJlZ3JvdXBlbWVudA0KY2F0ZWdvcmllcyA8LSBjKA0KICAiMTEiID0gIkFncmljdWx0ZXVycyIsDQogICIxMiIgPSAiQWdyaWN1bHRldXJzIiwNCiAgIjIxIiA9ICJBZ3JpY3VsdGV1cnMiLA0KICAiMjIiID0gIkFydGlzYW5zIGV0IGNvbW1lcsOnYW50cyIsDQogICIzMSIgPSAiQXJ0aXNhbnMgZXQgY29tbWVyw6dhbnRzIiwNCiAgIjMzIiA9ICJDYWRyZXMiLA0KICAiMzQiID0gIkNhZHJlcyIsDQogICIzNyIgPSAiUHJvZmVzc2lvbnMgaW50ZXJtw6lkaWFpcmVzIiwNCiAgIjM4IiA9ICJQcm9mZXNzaW9ucyBpbnRlcm3DqWRpYWlyZXMiLA0KICAiNDIiID0gIkVtcGxvecOpcyIsDQogICI0MyIgPSAiRW1wbG95w6lzIiwNCiAgIjQ1IiA9ICJFbXBsb3nDqXMiLA0KICAiNDYiID0gIk91dnJpZXJzIiwNCiAgIjQ3IiA9ICJPdXZyaWVycyIsDQogICI0OCIgPSAiT3V2cmllcnMiLA0KICAiNTIiID0gIlJldHJhaXTDqXMiLA0KICAiNTMiID0gIlJldHJhaXTDqXMiLA0KICAiNTQiID0gIlJldHJhaXTDqXMiLA0KICAiNTUiID0gIlJldHJhaXTDqXMiLA0KICAiNTYiID0gIlJldHJhaXTDqXMiLA0KICAiNzQiID0gIkF1dHJlcyBpbmFjdGlmcyIsDQogICI3NyIgPSAiQXV0cmVzIGluYWN0aWZzIiwNCiAgIjc4IiA9ICJBdXRyZXMgaW5hY3RpZnMiLA0KICAiODUiID0gIkF1dHJlcyBpbmFjdGlmcyIsDQogICI5OSIgPSAiQXV0cmVzIGluYWN0aWZzIg0KKQ0KDQojIFJlbXBsYWNlbWVudCBkYW5zIGxhIGNvbG9ubmUgUENTX1BhcmVudDENCmRhdGEkUENTX1BhcmVudDEgPC0gYXMuY2hhcmFjdGVyKGRhdGEkUENTX1BhcmVudDEpICAjIFMnYXNzdXJlciBxdWUgbGEgY29sb25uZSBlc3QgZW4gY2FyYWN0w6hyZXMNCmRhdGEkUENTX1BhcmVudDEgPC0gY2F0ZWdvcmllc1tkYXRhJFBDU19QYXJlbnQxXSAgICMgUmVtcGxhY2VyIGxlcyBjb2RlcyBwYXIgbGVzIG5vbXMNCg0KIyBSZW1wbGFjZW1lbnQgZGFucyBsYSBjb2xvbm5lIFBDU19QYXJlbnQyDQpkYXRhJFBDU19QYXJlbnQyIDwtIGFzLmNoYXJhY3RlcihkYXRhJFBDU19QYXJlbnQyKSAgIyBTJ2Fzc3VyZXIgcXVlIGxhIGNvbG9ubmUgZXN0IGVuIGNhcmFjdMOocmVzDQpkYXRhJFBDU19QYXJlbnQyIDwtIGNhdGVnb3JpZXNbZGF0YSRQQ1NfUGFyZW50Ml0gICAjIFJlbXBsYWNlciBsZXMgY29kZXMgcGFyIGxlcyBub21zDQoNCg0KDQpvcHRpb25zKHdhcm4gPSAtMSkNCg0KYGBgDQoNCg0KYGBgez1odG1sfQ0KPGRpdiBpZD0iU1RBUFMiIHN0eWxlPSJwYWRkaW5nLXRvcDogNDNweDttYXJnaW4tdG9wOiAtNDNweDtkaXNwbGF5OiBpbmxpbmUtYmxvY2s7Ij48L2Rpdj4NCmBgYA0KDQojIEkuIEFuYWx5c2UgZGVzY3JpcHRpdmUgDQoNCg0KIyMgSnVzdGlmaWNhdGlvbg0KDQpMJ2FuYWx5c2UgZGVzY3JpcHRpdmUgcGVybWV0IGRlIGNvbXByZW5kcmUgbGEgZGlzdHJpYnV0aW9uIGV0IGxlcyBjYXJhY3TDqXJpc3RpcXVlcyBnw6luw6lyYWxlcyBkZXMgZG9ubsOpZXMsIG9mZnJhbnQgYWluc2kgdW4gYXBlcsOndSBwcsOpbGltaW5haXJlIGRlcyB0ZW5kYW5jZXMgZXQgZGVzIGFzc29jaWF0aW9ucyBwb3RlbnRpZWxsZXMgZW50cmUgbGVzIHZhcmlhYmxlcyDDqXR1ZGnDqWVzLg0KDQoNCmBgYHtyIGNhcnN9DQpmYXN0Z2dwbG90IDwtIGZ1bmN0aW9uKGRhdGEsIHhfdmFyLCB0aXRsZSwgeF9sYWJlbCwgeV9sYWJlbCkgew0KICAjIENhbGN1bCBkZXMgZnLDqXF1ZW5jZXMNCiAgZnJlcV9kYXRhIDwtIGRhdGEgJT4lDQogICAgY291bnQoLmRhdGFbW3hfdmFyXV0pICU+JQ0KICAgIG11dGF0ZShwZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCkgICMgQ2FsY3VsIGRlcyBwb3VyY2VudGFnZXMNCiAgDQogIGdncGxvdChkYXRhLCBhZXMoeCA9IGZhY3RvciguZGF0YVtbeF92YXJdXSksIGZpbGwgPSBmYWN0b3IoLmRhdGFbW3hfdmFyXV0pKSkgKw0KICAgIGdlb21fYmFyKGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjgpICsNCiAgICBnZW9tX2xhYmVsKGRhdGEgPSBmcmVxX2RhdGEsIGFlcyh4ID0gZmFjdG9yKC5kYXRhW1t4X3Zhcl1dKSwgeSA9IG4gKyAxLCBsYWJlbCA9IHBhc3RlMChyb3VuZChwZXJjZW50YWdlLCAxKSwgIiUiKSksIA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHNpemUgPSA1LCBjb2xvciA9ICJibGFjayIsIGZvbnRmYWNlID0gImJvbGQiLCBmaWxsID0gIndoaXRlIiwgbGFiZWwucGFkZGluZyA9IHVuaXQoMC4yLCAibGluZXMiKSkgKw0KICAgIGxhYnModGl0bGUgPSB0aXRsZSwgeCA9IHhfbGFiZWwsIHkgPSB5X2xhYmVsLCBmaWxsID0geF92YXIpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIikpDQp9DQoNCg0KYGBgDQoNCiMjIGEuIFLDqXBhcnRpb24gZGVzIMOpdHVkaWFudHMgZW4gZm9uY3Rpb24gZGUgbGEgYm91cnNlDQoNCmBgYHtyfQ0KQm91cnNpZXIgPC0gZmFzdGdncGxvdChkYXRhLCAiQm91cnNpZXIiLCAiUsOpcGFydGl0aW9uIGVuIGZvbmN0aW9uIGRlIGxhIGJvdXJzZSIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNCkJvdXJzaWVyDQpgYGANCg0KDQojIyBiLiBSw6lwYXJ0aW9uIGRlcyDDqXR1ZGlhbnRzIGVuIGZvbmN0aW9uIGR1IHNleGUNCg0KYGBge3J9DQpTZXhlIDwtIGZhc3RnZ3Bsb3QoZGF0YSwgIlNleGUiLCAiUsOpcGFydGl0aW9uIGhvbW1lIGZlbW1lIiwgIiIsICJOb21icmUgZGUgY2FzIikNClNleGUgPC0gU2V4ZSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpTZXhlDQpgYGANCiMjIGMuIFLDqXBhcnRpb24gZGVzIMOpdHVkaWFudHMgZW4gZm9uY3Rpb24gZGUgbGEgY2F0w6lnb3JpZSBzb2Npby1wcm9mZXNzaW9ubmVsZSBkdSBwYXJlbnQgMQ0KDQoNCmBgYHtyfQ0KUENTX1BhcmVudDEgPC0gZmFzdGdncGxvdChkYXRhLCAiUENTX1BhcmVudDEiLCAiQ2F0w6lnb3JpZSBzb2Npby1wcm9mZXNzaW9ubmVsbGUgZHUgcGFyZW50IDEiLCAiIiwgIk5vbWJyZSBkJ29jY3VyZW5jZSIpDQpQQ1NfUGFyZW50MSA8LSBQQ1NfUGFyZW50MSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpQQ1NfUGFyZW50MQ0KYGBgDQojIyBkLiBSw6lwYXJ0aW9uIGRlcyDDqXR1ZGlhbnRzIGVuIGZvbmN0aW9uIGRlIGxhIGJvdXJzZQ0KDQpgYGB7cn0NClBDU19QYXJlbnQyID0gZmFzdGdncGxvdChkYXRhLCAiUENTX1BhcmVudDIiLCAiQ2F0w6lnb3JpZSBzb2Npby1wcm9mZXNzaW9ubmVsbGUgZHUgcGFyZW50IDIiLCAiIiwgIk5vbWJyZSBkJ29jY3VyZW5jZSIpDQpQQ1NfUGFyZW50MiA8LSBQQ1NfUGFyZW50MiArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpQQ1NfUGFyZW50Mg0KYGBgDQoNCiMjIGUuUsOpcGFydGlvbiBkZXMgw6l0dWRpYW50cyBlbiBmb25jdGlvbiBkdSBiYWMNCg0KYGBge3J9DQpCYWMgPSBmYXN0Z2dwbG90KGRhdGEsICJCYWNfR3JvdXBlIiwgIkJhYyIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNCkJhYyA8LSBCYWMgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA3KSkNCkJhYw0KYGBgDQojIyBmLiBSw6lwYXJ0aW9uIGRlIGxhIG1lbnRpb24gZGVzIMOpdHVkaWFudHMgYXUgQmFjDQoNCmBgYHtyfQ0KDQpCYWNfTWVudGlvbiA9IGZhc3RnZ3Bsb3QoZGF0YSwgIkJhY19NZW50aW9uIiwgIk1lbnRpb24gYXUgQmFjIiwgIiIsICJOb21icmUgZCdvY2N1cmVuY2UiKQ0KQmFjX01lbnRpb24gPC0gQmFjX01lbnRpb24gKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KQmFjX01lbnRpb24gDQpgYGANCiMjIGcuIEludGl0dWzDqSBkJ8OpdHVkZSBlbiAyMDIzLTIwMjQNCg0KYGBge3J9DQpub3RlMjAyMyA9IGZhc3RnZ3Bsb3QoZGF0YSwgIjIwMjMiLCAiSW50aXR1bMOpIGQnw6l0dWRlIGVuIDIwMjMtMjAyNCIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNCm5vdGUyMDIzIDwtIG5vdGUyMDIzICt0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA3KSkNCm5vdGUyMDIzDQpgYGANCiMjIGguIFLDqXN1bHRhdCBkZXMgw6l0dWRpYW50cyBlbiAyMDIzLTIwMjQNCg0KYGBge3J9DQpSZXN1bHRhdDIwMjMgPSBmYXN0Z2dwbG90KGRhdGEsICJSZXN1bHRhdCIsICJSw6lzdWx0YXQgMjAyMyIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNClJlc3VsdGF0MjAyMyA8LSBSZXN1bHRhdDIwMjMgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KUmVzdWx0YXQyMDIzDQpgYGANCg0KIyMgaS4gSW50aXR1bMOpIGRlIGZvcm1hdGlvbiBlbiAyMDI0LTIwMjUNCg0KDQpgYGB7cn0NCg0KRm9ybWF0aW9uMjAyNCA9IGZhc3RnZ3Bsb3QoZGF0YSwgIjIwMjQiLCAiRm9ybWF0aW9uIDIwMjQtMjAyNSIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNCkZvcm1hdGlvbjIwMjQgPC0gRm9ybWF0aW9uMjAyNCArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpGb3JtYXRpb24yMDI0DQpgYGANCiMjIGouIE1veWVubmUgZ8OpbsOpcmFsZSBkZXMgw6l0dWRpYW50cyBlbiAyMDIzLTIwMjQNCg0KYGBge3J9DQojIEhpc3RvZ3JhbW1lIGFtw6lsaW9yw6kgcG91ciBsYSB2YXJpYWJsZSBOb3RlDQpsaWJyYXJ5KGdncGxvdDIpDQoNCm5vdGVkID0gZ2dwbG90KGRhdGEsIGFlcyh4ID0gTm90ZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gIiM2OWIzYTIiLCBjb2xvciA9ICJ3aGl0ZSIsIGFscGhhID0gMC44KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIGRlcyBOb3RlcyIsDQogICAgeCA9ICJOb3RlIiwNCiAgICB5ID0gIkZyw6lxdWVuY2UiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiIzJhM2QzZiIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiLCBjb2xvciA9ICIjMmEzZDNmIiksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiIzJhM2QzZiIpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiI2QzZDNkMyIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkNCiAgKQ0Kbm90ZWQNCmBgYA0KDQojIElJLiBBbmFseXNlIGluZsOpcmVudGllbGxlDQoNCkwnYW5hbHlzZSBpbmbDqXJlbnRpZWxsZSBlbnRyZSBsZXMgbm90ZXMgZXQgbGVzIGF1dHJlcyB2YXJpYWJsZXMgdmlzZSDDoCBkw6l0ZXJtaW5lciBzaSBkZXMgZmFjdGV1cnMgY29tbWUgbGUgc3RhdHV0IGRlIGJvdXJzaWVyLCBsZSBzZXhlLCBsYSBjYXTDqWdvcmllIHNvY2lvcHJvZmVzc2lvbm5lbGxlIGRlcyBwYXJlbnRzLCBvdSBsZXMgbWVudGlvbnMgYXUgYmFjIGluZmx1ZW5jZW50IGxlcyByw6lzdWx0YXRzIGFjYWTDqW1pcXVlcy4NCg0KDQojIyBhLiBTZXhlIGV0IG5vdGVzDQoNCmBgYHtyfQ0KDQojIEVmZmVjdHVlciBsZSB0ZXN0IHQgZGUgU3R1ZGVudCBlbnRyZSBTZXhlIGV0IE5vdGUNCnRfdGVzdF9yZXN1bHQxMCA8LSB0LnRlc3QoTm90ZSB+IFNleGUsIGRhdGEgPSBkYXRhLCB2YXIuZXF1YWwgPSBUUlVFKQ0KDQojIEV4dHJhaXJlIGxhIHAtdmFsdWUgZHUgdGVzdA0KcF92YWx1ZTEwIDwtIHRfdGVzdF9yZXN1bHQxMCRwLnZhbHVlDQoNCiMgQ3LDqWVyIHVuIGJveHBsb3QgZXQgYWpvdXRlciBsYSBwLXZhbHVlIHN1ciBsZSBncmFwaGlxdWUNCmxpYnJhcnkoZ2dwbG90MikNCg0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gU2V4ZSwgeSA9IE5vdGUsIGZpbGwgPSBTZXhlKSkgKw0KICBnZW9tX2JveHBsb3QoY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNikgKw0KICBsYWJzKHRpdGxlID0gIkNvbXBhcmFpc29uIGRlcyBub3RlcyBzZWxvbiBsZSBzZXhlIiwNCiAgICAgICB4ID0gIlNleGUiLCB5ID0gIk5vdGUiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSkgKw0KICAjIEFqb3V0ZXIgbGEgcC12YWx1ZSBzdXIgbGUgZ3JhcGhpcXVlDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEuNSwgeSA9IG1heChkYXRhJE5vdGUsIG5hLnJtID0gVFJVRSksIA0KICAgICAgICAgICBsYWJlbCA9IHBhc3RlKCJwLXZhbHVlID0iLCByb3VuZChwX3ZhbHVlMTAsIDQpKSwgDQogICAgICAgICAgIHNpemUgPSA1LCBjb2xvciA9ICJyZWQiLCBmb250ZmFjZSA9ICJib2xkIikNCmBgYA0KDQojIyBiLiBCb3Vyc2UgZXQgbm90ZXMNCg0KYGBge3J9DQoNCiMgRWZmZWN0dWVyIGxlIHRlc3QgdCBkZSBTdHVkZW50IGVudHJlIEJvdXJzaWVyIGV0IE5vdGUNCnRfdGVzdF9yZXN1bHQxIDwtIHQudGVzdChOb3RlIH4gQm91cnNpZXIsIGRhdGEgPSBkYXRhKQ0KDQojIEV4dHJhaXJlIGxhIHAtdmFsdWUgZHUgdGVzdA0KcF92YWx1ZTEgPC0gdF90ZXN0X3Jlc3VsdDEkcC52YWx1ZQ0KDQojIENyw6llciB1biBib3hwbG90IGV0IGFqb3V0ZXIgbGEgcC12YWx1ZSBzdXIgbGUgZ3JhcGhpcXVlDQpsaWJyYXJ5KGdncGxvdDIpDQoNCmdncGxvdChkYXRhLCBhZXMoeCA9IEJvdXJzaWVyLCB5ID0gTm90ZSwgZmlsbCA9IEJvdXJzaWVyKSkgKw0KICBnZW9tX2JveHBsb3QoY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNikgKw0KICBsYWJzKHRpdGxlID0gIkNvbXBhcmFpc29uIGRlcyBub3RlcyBlbnRyZSBib3Vyc2llcnMgZXQgbm9uLWJvdXJzaWVycyIsDQogICAgICAgeCA9ICJTdGF0dXQgQm91cnNpZXIiLCB5ID0gIk5vdGUiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSkgKw0KICAjIEFqb3V0ZXIgbGEgcC12YWx1ZSBzdXIgbGUgZ3JhcGhpcXVlDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEuNSwgeSA9IG1heChkYXRhJE5vdGUsIG5hLnJtID0gVFJVRSksIA0KICAgICAgICAgICBsYWJlbCA9IHBhc3RlKCJwLXZhbHVlID0iLCByb3VuZChwX3ZhbHVlMSwgNCkpLCANCiAgICAgICAgICAgc2l6ZSA9IDUsIGNvbG9yID0gInJlZCIsIGZvbnRmYWNlID0gImJvbGQiKQ0KDQpgYGANCiMjIGMuIE5vdGVzIGV0IGNhdMOpZ29yaWUgc29jaW8tcHJvZmVzc2lvbm5lbGxlIGR1IHBhcmVudCAxDQoNCg0KYGBge3J9DQoNCiMgRWZmZWN0dWVyIHVuZSBBTk9WQSBlbnRyZSBQQ1NfUGFyZW50MSBldCBOb3RlDQphbm92YV9yZXN1bHQxIDwtIGFvdihOb3RlIH4gUENTX1BhcmVudDEsIGRhdGEgPSBkYXRhKQ0KDQojIEV4dHJhaXJlIGxhIHAtdmFsdWUgZGUgbCdBTk9WQQ0KYW5vdmFfcF92YWx1ZTIgPC0gc3VtbWFyeShhbm92YV9yZXN1bHQxKVtbMV1dW1siUHIoPkYpIl1dWzFdDQoNCiMgQ3LDqWVyIHVuIGJveHBsb3QgYXZlYyBwLXZhbHVlIGV0IGFqdXN0ZXIgbCdhcHBhcmVuY2UgZGVzIG5vbXMgZGVzIHZhcmlhYmxlcw0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gUENTX1BhcmVudDEsIHkgPSBOb3RlLCBmaWxsID0gUENTX1BhcmVudDEpKSArDQogIGdlb21fYm94cGxvdChjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC42KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29tcGFyYWlzb24gZGVzIG5vdGVzIHNlbG9uIGxhIFBDUyBkdSBwYXJlbnQgMSIsDQogICAgeCA9ICJQQ1MgUGFyZW50IDEiLCANCiAgICB5ID0gIk5vdGUiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAjIFRhaWxsZSByw6lkdWl0ZSBldCByb3RhdGlvbiBkZXMgbm9tcw0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksICAgICAgICAgICAgICAgICAgICAgICAgICMgVGFpbGxlIGRlcyDDqXRpcXVldHRlcyBkZSBsJ2F4ZSBZDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLCAgICAgICAgICAgIyBUYWlsbGUgZXQgc3R5bGUgZGVzIHRpdHJlcyBkZXMgYXhlcw0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSAgICAgICAgICAgICMgVGFpbGxlIGV0IHN0eWxlIGR1IHRpdHJlIHByaW5jaXBhbA0KICApICsNCiAgIyBBam91dGVyIGxhIHAtdmFsdWUgZW4gYmFzIMOgIGRyb2l0ZQ0KICBhbm5vdGF0ZSgNCiAgICAidGV4dCIsIA0KICAgIHggPSBsZW5ndGgodW5pcXVlKGRhdGEkUENTX1BhcmVudDEpKSwgICMgUG9zaXRpb24geCAoZGVybmnDqHJlIGNhdMOpZ29yaWUpDQogICAgeSA9IG1pbihkYXRhJE5vdGUsIG5hLnJtID0gVFJVRSkgLSAxLCAgIyBQb3NpdGlvbiB5IGzDqWfDqHJlbWVudCBzb3VzIGxlIG1pbmltdW0gZGVzIG5vdGVzDQogICAgbGFiZWwgPSBwYXN0ZSgicC12YWx1ZSA9Iiwgcm91bmQoYW5vdmFfcF92YWx1ZTIsIDQpKSwgDQogICAgc2l6ZSA9IDUsIA0KICAgIGNvbG9yID0gInJlZCIsIA0KICAgIGZvbnRmYWNlID0gImJvbGQiLA0KICAgIGhqdXN0ID0gMSAgIyBBbGlnbmVtZW50IMOgIGRyb2l0ZQ0KICApDQoNCg0KYGBgDQojIyBkLiBOb3RlcyBldCBjYXTDqWdvcmllLXByb2Zlc3Npb25uZWxsZSBkdSBwYXJlbnQgMg0KDQpgYGB7cn0NCg0KIyBFZmZlY3R1ZXIgdW5lIEFOT1ZBIGVudHJlIFBDU19QYXJlbnQxIGV0IE5vdGUNCmFub3ZhX3Jlc3VsdDIgPC0gYW92KE5vdGUgfiBQQ1NfUGFyZW50MiwgZGF0YSA9IGRhdGEpDQoNCiMgRXh0cmFpcmUgbGEgcC12YWx1ZSBkZSBsJ0FOT1ZBDQphbm92YV9wX3ZhbHVlMyA8LSBzdW1tYXJ5KGFub3ZhX3Jlc3VsdDIpW1sxXV1bWyJQcig+RikiXV1bMV0NCg0KIyBDcsOpZXIgdW4gYm94cGxvdCBhdmVjIHAtdmFsdWUgZXQgYWp1c3RlciBsJ2FwcGFyZW5jZSBkZXMgbm9tcyBkZXMgdmFyaWFibGVzDQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBQQ1NfUGFyZW50MiwgeSA9IE5vdGUsIGZpbGwgPSBQQ1NfUGFyZW50MikpICsNCiAgZ2VvbV9ib3hwbG90KGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjYpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDb21wYXJhaXNvbiBkZXMgbm90ZXMgc2Vsb24gbGEgUENTIGR1IHBhcmVudCAyIiwNCiAgICB4ID0gIlBDUyBQYXJlbnQgMiIsIA0KICAgIHkgPSAiTm90ZSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwgICMgVGFpbGxlIHLDqWR1aXRlIGV0IHJvdGF0aW9uIGRlcyBub21zDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwgICAgICAgICAgICAgICAgICAgICAgICAgIyBUYWlsbGUgZGVzIMOpdGlxdWV0dGVzIGRlIGwnYXhlIFkNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksICAgICAgICAgICAjIFRhaWxsZSBldCBzdHlsZSBkZXMgdGl0cmVzIGRlcyBheGVzDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpICAgICAgICAgICAgIyBUYWlsbGUgZXQgc3R5bGUgZHUgdGl0cmUgcHJpbmNpcGFsDQogICkgKw0KICAjIEFqb3V0ZXIgbGEgcC12YWx1ZSBlbiBiYXMgw6AgZHJvaXRlDQogIGFubm90YXRlKA0KICAgICJ0ZXh0IiwgDQogICAgeCA9IGxlbmd0aCh1bmlxdWUoZGF0YSRQQ1NfUGFyZW50MSkpLCAgIyBQb3NpdGlvbiB4IChkZXJuacOocmUgY2F0w6lnb3JpZSkNCiAgICB5ID0gbWluKGRhdGEkTm90ZSwgbmEucm0gPSBUUlVFKSAtIDEsICAjIFBvc2l0aW9uIHkgbMOpZ8OocmVtZW50IHNvdXMgbGUgbWluaW11bSBkZXMgbm90ZXMNCiAgICBsYWJlbCA9IHBhc3RlKCJwLXZhbHVlID0iLCByb3VuZChhbm92YV9wX3ZhbHVlMywgNCkpLCANCiAgICBzaXplID0gNSwgDQogICAgY29sb3IgPSAicmVkIiwgDQogICAgZm9udGZhY2UgPSAiYm9sZCIsDQogICAgaGp1c3QgPSAxICAjIEFsaWduZW1lbnQgw6AgZHJvaXRlDQogICkNCmBgYA0KIyMgZS4gTm90ZXMgZXQgbWVudGlvbiBhdSBiYWMNCg0KYGBge3J9DQphbm92YV9yZXN1bHQzIDwtIGFvdihOb3RlIH4gQmFjX01lbnRpb24sIGRhdGEgPSBkYXRhKQ0KDQojIEV4dHJhaXJlIGxhIHAtdmFsdWUgZGUgbCdBTk9WQQ0KYW5vdmFfcF92YWx1ZTQgPC0gc3VtbWFyeShhbm92YV9yZXN1bHQzKVtbMV1dW1siUHIoPkYpIl1dWzFdDQoNCiMgQ3LDqWVyIHVuIGJveHBsb3QgYXZlYyBwLXZhbHVlIGV0IGFqdXN0ZXIgbCdhcHBhcmVuY2UgZGVzIG5vbXMgZGVzIHZhcmlhYmxlcw0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gQmFjX01lbnRpb24sIHkgPSBOb3RlLCBmaWxsID0gQmFjX01lbnRpb24pKSArDQogIGdlb21fYm94cGxvdChjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC42KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29tcGFyYWlzb24gZGVzIG5vdGVzIHNlbG9uIGxhIG1lbnRpb24gYXUgYmFjIiwNCiAgICB4ID0gIk1lbnRpb24gYXUgQmFjIiwgDQogICAgeSA9ICJOb3RlIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLCAgIyBUYWlsbGUgcsOpZHVpdGUgZXQgcm90YXRpb24gZGVzIG5vbXMNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCAgICAgICAgICAgICAgICAgICAgICAgICAjIFRhaWxsZSBkZXMgw6l0aXF1ZXR0ZXMgZGUgbCdheGUgWQ0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgICAgICAgICAgICMgVGFpbGxlIGV0IHN0eWxlIGRlcyB0aXRyZXMgZGVzIGF4ZXMNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIikgICAgICAgICAgICAjIFRhaWxsZSBldCBzdHlsZSBkdSB0aXRyZSBwcmluY2lwYWwNCiAgKSArDQogICMgQWpvdXRlciBsYSBwLXZhbHVlIGVuIGJhcyDDoCBkcm9pdGUNCiAgYW5ub3RhdGUoDQogICAgInRleHQiLCANCiAgICB4ID0gbGVuZ3RoKHVuaXF1ZShkYXRhJEJhY19NZW50aW9uKSksICAjIFBvc2l0aW9uIHggKGRlcm5pw6hyZSBjYXTDqWdvcmllKQ0KICAgIHkgPSBtaW4oZGF0YSROb3RlLCBuYS5ybSA9IFRSVUUpIC0gMSwgICMgUG9zaXRpb24geSBsw6lnw6hyZW1lbnQgc291cyBsZSBtaW5pbXVtIGRlcyBub3Rlcw0KICAgIGxhYmVsID0gcGFzdGUoInAtdmFsdWUgPSIsIHJvdW5kKGFub3ZhX3BfdmFsdWU0LCA0KSksIA0KICAgIHNpemUgPSA1LCANCiAgICBjb2xvciA9ICJncmVlbiIsIA0KICAgIGZvbnRmYWNlID0gImJvbGQiLA0KICAgIGhqdXN0ID0gMSAgIyBBbGlnbmVtZW50IMOgIGRyb2l0ZQ0KICApDQpgYGANCiMgSUlJLiBNb2TDqGxlIHByZW5hbnQgdG91dGVzIGxlcyB2YXJpYWJsZXMgZW5zZW1ibGUNCg0KYGBge3J9DQoNCiMgQ3LDqWF0aW9uIGR1IGdyYXBoaXF1ZSBhdmVjIGdncGxvdDINCmdncGxvdChpbXBvcnRhbmNlX2RhdGEsIGFlcyh4ID0gcmVvcmRlcihWYXJpYWJsZSwgSW1wb3J0YW5jZSksIHkgPSBJbXBvcnRhbmNlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJza3libHVlIiwgY29sb3IgPSAiYmxhY2siKSArICAjIEJhcnJlcyBhdmVjIGNvdWxldXIgZXQgYm9yZHVyZQ0KICBjb29yZF9mbGlwKCkgKyAgIyBJbnZlcnNlciBsZXMgYXhlcyBwb3VyIHVuZSBtZWlsbGV1cmUgbGlzaWJpbGl0w6kNCiAgbGFicyh0aXRsZSA9ICJWYXJpYWJsZXMgc2lnbmlmaWNhdGl2ZXMgYXZlYyBpbXBvcnRhbmNlID4gc2V1aWwgOTUlIiwNCiAgICAgICB4ID0gIlZhcmlhYmxlcyIsIHkgPSAiSW1wb3J0YW5jZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgICMgVGjDqG1lIG1pbmltYWxpc3RlDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwgICMgUm90YXRpb24gZGVzIG5vbXMgZGVzIHZhcmlhYmxlcw0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkgICMgVGFpbGxlIGRlcyBub21zIGRlcyB2YXJpYWJsZXMNCiAgKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHNldWlsX2ltcG9ydGFuY2UsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIsIHNpemUgPSAxLjUpICAjIEFqb3V0ZXIgbGUgc2V1aWwNCg0KDQpgYGANCg0KIyBCVVQgDQoNCmBgYHs9aHRtbH0NCjxkaXYgaWQ9IkJVVCIgc3R5bGU9InBhZGRpbmctdG9wOiA0M3B4O21hcmdpbi10b3A6IC00M3B4O2Rpc3BsYXk6IGlubGluZS1ibG9jazsiPjwvZGl2Pg0KYGBgDQoNCg0KYGBge3J9DQpzZXR3ZCgiQzovVXNlcnMvVmFsZW4vRGVza3RvcC9CRElQIikNCg0KZGF0YSA8LSByZWFkLmNzdigiRG9ubsOpZXNfQlVUQ2xlYW4uY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KDQpkYXRhID0gZGF0YVssLTJdDQoNCmRhdGEgPC0gZGF0YS5mcmFtZShsYXBwbHkoZGF0YSwgYXMuZmFjdG9yKSkNCg0KDQpkYXRhJGJvdXJzZV90eXBlIDwtIGFzLmZhY3RvcihpZmVsc2UoaXMubmEoZGF0YSRib3Vyc2VfdHlwZSksICJQYXMgZGUgYm91cnNlIiwgYXMuY2hhcmFjdGVyKGRhdGEkYm91cnNlX3R5cGUpKSkNCg0KZGF0YSRib3Vyc2VfZWNoZSA8LSBhcy5mYWN0b3IoaWZlbHNlKGRhdGEkYm91cnNlX3R5cGUgPT0gIlBhcyBkZSBib3Vyc2UiLCAiUGFzIGRlIGJvdXJzZSIsIGFzLmNoYXJhY3RlcihkYXRhJGJvdXJzZV9lY2hlKSkpDQoNCmRhdGEkYm91cnNlX2VjaGUgPC0gYXMuZmFjdG9yKGlmZWxzZShkYXRhJGJvdXJzZV9lY2hlID09IDEwLCAiRWNoZWxvbiAxIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZGF0YSRib3Vyc2VfZWNoZSA9PSAyMCwgIkVjaGVsb24gMiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkYXRhJGJvdXJzZV9lY2hlID09IDMwLCAiRWNoZWxvbiAzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkYXRhJGJvdXJzZV9lY2hlID09IDQwLCAiRWNoZWxvbiA0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZGF0YSRib3Vyc2VfZWNoZSA9PSA1MCB8IGRhdGEkYm91cnNlX2VjaGUgPT0gNSwgIkVjaGVsb24gNSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZGF0YSRib3Vyc2VfZWNoZSA9PSA2MCwgIkVjaGVsb24gNiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZGF0YSRib3Vyc2VfZWNoZSA9PSA3MCwgIkVjaGVsb24gNyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKGRhdGEkYm91cnNlX2VjaGUpKSkpKSkpKSkNCg0KDQoNCg0KZGF0YSRib3Vyc2VfZWNoZSA8LSBhcy5jaGFyYWN0ZXIoZGF0YSRib3Vyc2VfZWNoZSkNCg0KZGF0YSRib3Vyc2VfZWNoZVtpcy5uYShkYXRhJGJvdXJzZV9lY2hlKSAmICFpcy5uYShkYXRhJGJvdXJzaWVyKV0gPC0gIsOpY2hlbG9uIG5vbiBjb25udSINCg0KZGF0YSRib3Vyc2VfZWNoZVtkYXRhJGJvdXJzaWVyID09ICJOIl0gPC0gIlBhcyBkZSBib3Vyc2UiDQoNCmRhdGEkYm91cnNlX2VjaGUgPC0gaWZlbHNlKGRhdGEkYm91cnNlX2VjaGUgJWluJSBjKCJFY2hlbG9uIDEiLCAiRWNoZWxvbiAyIiksICJCb3Vyc2UgZmFpYmxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkYXRhJGJvdXJzZV9lY2hlICVpbiUgYygiRWNoZWxvbiAzIiwgIkVjaGVsb24gNCIsICJFY2hlbG9uIDUiKSwgIkJvdXJzZSBtb3llbm5lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZGF0YSRib3Vyc2VfZWNoZSAlaW4lIGMoIkVjaGVsb24gNiIsICJFY2hlbG9uIDciKSwgIkJvdXJzZSDDqWxldsOpZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcihkYXRhJGJvdXJzZV9lY2hlKSkpKQ0KDQpkYXRhID0gZGF0YVssLWMoOSldDQoNCg0KDQpkYXRhJGxvZ2VtZW50IDwtIGZhY3RvcihkYXRhJGxvZ2VtZW50LCANCiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNoYW1iciBldHUiLCAibG9nIHBlcnNvIiwgInBhcmVudHMiLCAicsOpc2lkIHVuaSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNoYW1icmUgw6l0dWRpYW50ZSIsICJMb2dlbWVudCBwZXJzb25uZWwiLCAiUGFyZW50cyIsICJSw6lzaWRlbmNlIHVuaXZlcnNpdGFpcmUiKSkNCg0KZGF0YSRiYWNfbWVudGlvbiA8LSBpZmVsc2UoZGF0YSRiYWNfbWVudGlvbiA9PSAiUGFzc2FibGUiLCAiU2FucyBtZW50aW9uIiwgYXMuY2hhcmFjdGVyKGRhdGEkYmFjX21lbnRpb24pKQ0KDQoNCmBgYA0KIyBJLiBBbmFseXNlIGRlc2NyaXB0aXZlDQoNCkzigJlhbmFseXNlIGRlc2NyaXB0aXZlIHBlcm1ldCBkZSBjb21wcmVuZHJlIGxhIGRpc3RyaWJ1dGlvbiBldCBsZXMgY2FyYWN0w6lyaXN0aXF1ZXMgZ8OpbsOpcmFsZXMgZGVzIGRvbm7DqWVzLCBvZmZyYW50IGFpbnNpIHVuIGFwZXLDp3UgcHLDqWxpbWluYWlyZSBkZXMgdGVuZGFuY2VzIGV0IGRlcyBhc3NvY2lhdGlvbnMgcG90ZW50aWVsbGVzIGVudHJlIGxlcyB2YXJpYWJsZXMgw6l0dWRpw6llcy4NCg0KIyMgYS4gUsOpcGFydGl0aW9uIGRlcyDDqXR1ZGlhbnRzIGVuIGZvbmN0aW9uIGR1IHNleGUNCg0KYGBge3J9DQpmYXN0Z2dwbG90IDwtIGZ1bmN0aW9uKGRhdGEsIHhfdmFyLCB0aXRsZSwgeF9sYWJlbCwgeV9sYWJlbCkgew0KICAjIENhbGN1bCBkZXMgZnLDqXF1ZW5jZXMNCiAgZnJlcV9kYXRhIDwtIGRhdGEgJT4lDQogICAgY291bnQoLmRhdGFbW3hfdmFyXV0pICU+JQ0KICAgIG11dGF0ZShwZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCkgICMgQ2FsY3VsIGRlcyBwb3VyY2VudGFnZXMNCiAgDQogIGdncGxvdChkYXRhLCBhZXMoeCA9IGZhY3RvciguZGF0YVtbeF92YXJdXSksIGZpbGwgPSBmYWN0b3IoLmRhdGFbW3hfdmFyXV0pKSkgKw0KICAgIGdlb21fYmFyKGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjgpICsNCiAgICBnZW9tX2xhYmVsKGRhdGEgPSBmcmVxX2RhdGEsIGFlcyh4ID0gZmFjdG9yKC5kYXRhW1t4X3Zhcl1dKSwgeSA9IG4gKyAxLCBsYWJlbCA9IHBhc3RlMChyb3VuZChwZXJjZW50YWdlLCAxKSwgIiUiKSksIA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHNpemUgPSA1LCBjb2xvciA9ICJibGFjayIsIGZvbnRmYWNlID0gImJvbGQiLCBmaWxsID0gIndoaXRlIiwgbGFiZWwucGFkZGluZyA9IHVuaXQoMC4yLCAibGluZXMiKSkgKw0KICAgIGxhYnModGl0bGUgPSB0aXRsZSwgeCA9IHhfbGFiZWwsIHkgPSB5X2xhYmVsLCBmaWxsID0geF92YXIpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIikpDQp9DQoNCg0KDQpkYXRhJFBDU19wYXJlbnQxX2NhdGVnb3JpemVkIDwtIE5BDQoNCg0KDQojIENhZHJlcyBldCBwcm9mZXNzaW9ucyBzdXDDqXJpZXVyZXMNCmRhdGEkUENTX3BhcmVudDFfY2F0ZWdvcml6ZWRbZGF0YSRQQ1NfcGFyZW50MSAlaW4lIGMoIkNoZWYgZW50cHIiLCAiQ29uZHVjIGVuZyIsICJpbmfDqW5pZXVyIiwgInByb2YgbGliIiwgInByb2Zlc3NldXIiLCAiQ2FkcmUgUmV0ciIsICJSZXRyIildIDwtICJDYWRyZXMgZXQgcHJvZmVzc2lvbnMgc3Vww6lyaWV1cmVzIg0KDQojIFByb2Zlc3Npb25zIGludGVybcOpZGlhaXJlcw0KZGF0YSRQQ1NfcGFyZW50MV9jYXRlZ29yaXplZFtkYXRhJFBDU19wYXJlbnQxICVpbiUgYygiZW1wIGFkbSBlbiIsICJlbXAgY29tbWVyIiwgIkFydGlzYW5zIiwgIlByIEludCBhZCIsICJpbnQgYWQgZiBwIiwgInRlY2huaWNpZW4iLCAiY2FkciBhZG1pbiIsICJjYWRyIGYgcHViIiwgIkFkbWluaXN0cmEiLCAiQWcgbWFpdHJpcyIsICJBZ3JpIE0gRXhwIiwgInBvbGljaWVyIildIDwtICJQcm9mZXNzaW9ucyBpbnRlcm3DqWRpYWlyZXMiDQoNCiMgT3V2cmllcnMNCmRhdGEkUENTX3BhcmVudDFfY2F0ZWdvcml6ZWRbZGF0YSRQQ1NfcGFyZW50MSAlaW4lIGMoIk91dnIgSW5kIiwgIk91dnIgTiBBcnQiLCAiU1MgcHJvZiAtIiwgImludCBhZCBjb20iLCAiaW50IHNhbiBzbyIsICJSZXRyIFByIEluIildIDwtICJPdXZyaWVycyINCg0KIyBJbmNvbm51cyBvdSBhdXRyZXMNCmRhdGEkUENTX3BhcmVudDFfY2F0ZWdvcml6ZWRbZGF0YSRQQ1NfcGFyZW50MSAlaW4lIGMoImluY29ubnUiLCAicmV0cmFpdCBhciIsICJSZXRyIENhZHJlIildIDwtICJJbmNvbm51cyBvdSBhdXRyZXMiDQoNCg0KZGF0YSRkaXBfbWVudGlvbiA8LSBnc3ViKCJHRU5JRSBFTEVDVFJJUVVFIEVUIElORk9STUFUSVFVRSBJTkRVU1RSSUVMTEUiLCAiR0VOSUUgRUxFQ1RSSVFVRSIsIGRhdGEkZGlwX21lbnRpb24pDQoNCmRhdGEgPC0gZGF0YVtkYXRhJHJlc19kZXQgIT0gIkF0dGVudGUgZGUgbm90ZSAoc3BvcnRpZiBkZSBoYXV0IG5pdmVhdSkiLCBdDQoNCmRhdGFfZmlsdGVyZWQgPC0gZGF0YSAlPiUNCiAgZmlsdGVyKHJlc19kZXQgIT0gIkF0dGVudGUgZGUgbm90ZSAoc3BvcnRpZiBkZSBoYXV0IG5pdmVhdSkiKQ0KDQpjb2xuYW1lcyhkYXRhKVtjb2xuYW1lcyhkYXRhKSA9PSAiUENTX3BhcmVudDFfY2F0ZWdvcml6ZWQiXSA8LSAiUENTX2R1X3BhcmVudDEiDQoNCg0KDQpkYXRhIDwtIGRhdGEgJT4lDQogIG11dGF0ZShyZXNfZGV0ID0gY2FzZV93aGVuKA0KICAgIHJlc19kZXQgPT0gIkFqb3VybsOpIG1haXMgYWNjw6hzIGF1dG9yaXPDqSDDoCDDqXRhcGUgc3VwLiIgfiAiQWpvdXJuw6kiLA0KICAgIHJlc19kZXQgPT0gIk5vbiBhZG1pcyAtIEF1dG9yaXPDqSDDoCByZWRvdWJsZXIiIH4gIkFqb3VybsOpIiwNCiAgICByZXNfZGV0ID09ICJSw6lvcmllbnTDqSIgfiAiRMOpZmFpbGxhbnQiLA0KICAgIFRSVUUgfiByZXNfZGV0ICAjIEdhcmRlIGxlcyBhdXRyZXMgY2F0w6lnb3JpZXMgaW5jaGFuZ8OpZXMNCiAgKSkNCg0KYGBgDQoNCg0KYGBge3J9DQpTZXhlIDwtIGZhc3RnZ3Bsb3QoZGF0YSwgInNleGUiLCAiUsOpcGFydGl0aW9uIGVuIGZvbmN0aW9uIGR1IHNleGUiLCAiIiwgIk5vbWJyZSBkJ29jY3VyZW5jZSIpDQpTZXhlDQpgYGANCg0KIyMgYi4gUsOpcGFydGl0aW9uIGRlcyDDqXR1ZGlhbnRzIGVuIGZvbmN0aW9uIGR1IHR5cGUgZGUgbG9nZW1lbnQNCg0KYGBge3J9DQpMb2dlbWVudCA8LSBmYXN0Z2dwbG90KGRhdGEsICJsb2dlbWVudCIsICJSw6lwYXJ0aXRpb24gZW4gZm9uY3Rpb24gZHUgdHlwZSBkZSBsb2dlbWVudCIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNCkxvZ2VtZW50IDwtIExvZ2VtZW50ICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCkxvZ2VtZW50DQpgYGANCg0KIyMgYy4gUsOpcGFydGl0aW9uIGVuIGZvbmN0aW9uIGRlIGwnb2J0ZW50aW9uIGRlIGxhIGJvdXJzZQ0KDQpgYGB7cn0NCkJvdXJzZSA8LSBmYXN0Z2dwbG90KGRhdGEsICJib3Vyc2llciIsICJSw6lwYXJ0aXRpb24gZGUgbCdvYnRlbnRpb24gZGUgbGEgYm91cnNlIiwgIiIsICJOb21icmUgZCdvY2N1cmVuY2UiKQ0KQm91cnNlIDwtIEJvdXJzZSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpCb3Vyc2UNCmBgYA0KIyMgZC4gUsOpcGFydGl0aW9uIGVuIGZvbmN0aW9uIGR1IHR5cGUgZGUgYm91cnNlDQoNCmBgYHtyfQ0KQm91cnNlMiA8LSBmYXN0Z2dwbG90KGRhdGEsICJib3Vyc2VfZWNoZSIsICJSw6lwYXJ0aXRpb24gZW4gZm9uY3Rpb24gZHUgdHlwZSBkZSBib3Vyc2UiLCAiIiwgIk5vbWJyZSBkJ29jY3VyZW5jZSIpDQpCb3Vyc2UyIDwtIEJvdXJzZTIgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KQm91cnNlMg0KYGBgDQojIyBlLiBSw6lwYXJ0aXRpb24gZW4gZm9uY3Rpb24gZHUgdHlwZSBkZSBiYWMNCg0KYGBge3J9DQpCYWMgPC0gZmFzdGdncGxvdChkYXRhLCAiYmFjX2ZpbGllcmUiLCAiUsOpcGFydGl0aW9uIGVuIGZvbmN0aW9uIGR1IHR5cGUgZGUgYmFjIiwgIiIsICJOb21icmUgZCdvY2N1cmVuY2UiKQ0KQmFjIDwtIEJhYyArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpCYWMNCmBgYA0KIyMgZi4gUsOpcGFydGl0aW9uIGVuIGZvbmN0aW9uIGRlIGxhIG1lbnRpb24gYXUgYmFjDQoNCmBgYHtyfQ0KQmFjIDwtIGZhc3RnZ3Bsb3QoZGF0YSwgImJhY19tZW50aW9uIiwgIlLDqXBhcnRpdGlvbiBlbiBmb25jdGlvbiBkZSBsYSBtZW50aW9uIGF1IGJhYyIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNCkJhYw0KYGBgDQojIyBnLiBDYXTDqWdvcmllIHNvY2lvLXByb2Zlc3Npb25uZWxsZSBkdSBwYXJlbnQgMQ0KDQpgYGB7cn0NCmVlIDwtIGZhc3RnZ3Bsb3QoZGF0YSwgIlBDU19kdV9wYXJlbnQxIiwgIkNhdMOpZ29yaWUgc29jaW8tcHJvZmVzc2lvbm5lbGxlIGR1IHBhcmVudCAxIiwgIiIsICJOb21icmUgZCdvY2N1cmVuY2UiKQ0KZWUgPSBlZSAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KZWUNCmBgYA0KDQojIyBoLk1lbnRpb24gZHUgZGlwbMO0bWUgcHLDqXBhcsOpDQoNCmBgYHtyfQ0KbWVudGlvbmRpcCA8LSBmYXN0Z2dwbG90KGRhdGEsICJkaXBfbWVudGlvbiIsICJNZW50aW9uIGR1IGRpcGzDtG1lIHByw6lwYXLDqSIsICIiLCAiTm9tYnJlIGQnb2NjdXJlbmNlIikNCmRpcCA9IG1lbnRpb25kaXAgDQpkaXANCmBgYA0KDQojIyBpLiBSw6lzdWx0YXQgw6AgbCdhbm7DqWUNCg0KYGBge3J9DQpyZXN1bHQgPC0gZmFzdGdncGxvdChkYXRhLCAicmVzX2RldCIsICJSw6lzdWx0YXQgw6AgbCdhbm7DqWUiLCAiIiwgIk5vbWJyZSBkJ29jY3VyZW5jZSIpDQpyZXN1bHQgPSByZXN1bHQgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KcmVzdWx0DQpgYGANCg0KIyBJSS4gQW5hbHlzZSBpbmbDqXJlbnRpZWxsZQ0KDQojIyBhLiBSw6lzdWx0YXQgZXQgc2V4ZQ0KDQpgYGB7cn0NCiMgRmlsdHJlciBsZXMgZG9ubsOpZXMgcG91ciByZXRpcmVyICJBdHRlbnRlIGRlIG5vdGUiDQpkYXRhX2ZpbHRlcmVkIDwtIGRhdGEgJT4lDQogIGZpbHRlcihyZXNfZGV0ICE9ICJBdHRlbnRlIGRlIG5vdGUgKHNwb3J0aWYgZGUgaGF1dCBuaXZlYXUpIikNCg0KIyBDcsOpZXIgdW4gdGFibGVhdSBkZSBjb250aW5nZW5jZSBlbnRyZSBzZXhlIGV0IHJlc19kZXQNCnRhYmxlX2NvbnRpbmdlbmNlIDwtIHRhYmxlKGRhdGFfZmlsdGVyZWQkc2V4ZSwgZGF0YV9maWx0ZXJlZCRyZXNfZGV0KQ0KDQojIEVmZmVjdHVlciB1biB0ZXN0IGR1IENoacKyIG91IEZpc2hlciBzZWxvbiBsZXMgZWZmZWN0aWZzDQpjaGlzcV90ZXN0IDwtIGNoaXNxLnRlc3QodGFibGVfY29udGluZ2VuY2UpDQoNCiMgVsOpcmlmaWVyIHNpIGRlcyBlZmZlY3RpZnMgdGjDqW9yaXF1ZXMgc29udCA8IDUNCmlmKGFueShjaGlzcV90ZXN0JGV4cGVjdGVkIDwgNSkpIHsNCiAgdGVzdF9yZXN1bHQgPC0gZmlzaGVyLnRlc3QodGFibGVfY29udGluZ2VuY2UpDQogIHRlc3RfdHlwZSA8LSAiVGVzdCBleGFjdCBkZSBGaXNoZXIiDQp9IGVsc2Ugew0KICB0ZXN0X3Jlc3VsdCA8LSBjaGlzcV90ZXN0DQogIHRlc3RfdHlwZSA8LSAiVGVzdCBkdSBDaGnCsiINCn0NCg0KIyBFeHRyYWlyZSBsYSBwLXZhbHVlDQpwX3ZhbHVlIDwtIHRlc3RfcmVzdWx0JHAudmFsdWUNCg0KIyBDcsOpZXIgbGUgYmFycGxvdCBwcmluY2lwYWwNCmJhcnBsb3QgPC0gZ2dwbG90KGRhdGFfZmlsdGVyZWQsIGFlcyh4ID0gc2V4ZSwgZmlsbCA9IHJlc19kZXQpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnModGl0bGUgPSAiUsOpcGFydGl0aW9uIGRlcyByw6lzdWx0YXRzIHNlbG9uIGxlIHNleGUiLA0KICAgICAgIHggPSAiU2V4ZSIsIHkgPSAiRWZmZWN0aWYiLCBmaWxsID0gIlLDqXN1bHRhdCBkw6l0ZXJtaW7DqSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSArICAjIEzDqWdlbmRlIMOgIGRyb2l0ZQ0KICBnZW9tX3RleHQoc3RhdCA9ICJjb3VudCIsIGFlcyhsYWJlbCA9IC4uY291bnQuLiksIA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA1LCBjb2xvciA9ICJ3aGl0ZSIpDQoNCiMgQ3LDqWVyIHVuIHRleHRlIGNvbnRlbmFudCBsYSBwLXZhbHVlICjDoCBhZmZpY2hlciBzb3VzIGxhIGzDqWdlbmRlKQ0KcF92YWx1ZV90ZXh0IDwtIGdnZHJhdygpICsgDQogIGRyYXdfdGV4dChwYXN0ZSh0ZXN0X3R5cGUsICJcbnAtdmFsdWUgPSIsIHJvdW5kKHBfdmFsdWUsIDQpKSwgDQogICAgICAgICAgICBzaXplID0gMTQsIGNvbG9yID0gInJlZCIsIGhqdXN0ID0gMC41KQ0KDQojIENvbWJpbmVyIGxlIGdyYXBoaXF1ZSBwcmluY2lwYWwgYXZlYyBsYSBwLXZhbHVlIHNvdXMgbGEgbMOpZ2VuZGUNCnBsb3RfZ3JpZChiYXJwbG90LCBwX3ZhbHVlX3RleHQsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoNCwgMC41KSkNCg0KDQpgYGANCg0KIyMgYi4gUsOpc3VsdGF0IGV0IGNhdMOpZ29yaWUgc29jaW8tcHJvZmVzc2lvbm5lbGxlIGR1IHBhcmVudCAxDQoNCmBgYHtyfQ0KIyBGaWx0cmVyIGxlcyBkb25uw6llcyBwb3VyIHJldGlyZXIgIkF0dGVudGUgZGUgbm90ZSINCmRhdGFfZmlsdGVyZWQgPC0gZGF0YSAlPiUNCiAgZmlsdGVyKHJlc19kZXQgIT0gIkF0dGVudGUgZGUgbm90ZSAoc3BvcnRpZiBkZSBoYXV0IG5pdmVhdSkiKQ0KDQojIENyw6llciB1biB0YWJsZWF1IGRlIGNvbnRpbmdlbmNlIGVudHJlIHJlc19kZXQgZXQgUENTX2R1X3BhcmVudDENCnRhYmxlX2NvbnRpbmdlbmNlIDwtIHRhYmxlKGRhdGFfZmlsdGVyZWQkcmVzX2RldCwgZGF0YV9maWx0ZXJlZCRQQ1NfZHVfcGFyZW50MSkNCg0KIyBFeHRyYWlyZSBsYSBwLXZhbHVlDQpwX3ZhbHVlIDwtIDAuMjE0DQoNCiMgQ3LDqWVyIGxlIGJhcnBsb3QgcHJpbmNpcGFsDQpiYXJwbG90IDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkLCBhZXMoeCA9IFBDU19kdV9wYXJlbnQxLCBmaWxsID0gcmVzX2RldCkpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJSw6lwYXJ0aXRpb24gZGVzIHLDqXN1bHRhdHMgc2Vsb24gbGEgY2F0w6lnb3JpZSBzb2Npby1wcm9mZXNzaW9ubmVsbGUgZHUgcGFyZW50IDEiLA0KICAgICAgIHggPSAiUENTIGR1IHBhcmVudCAxIiwgeSA9ICJFZmZlY3RpZiIsIGZpbGwgPSAiUsOpc3VsdGF0IGTDqXRlcm1pbsOpIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMCksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikgKyAgIyBMw6lnZW5kZSDDoCBkcm9pdGUNCiAgZ2VvbV90ZXh0KHN0YXQgPSAiY291bnQiLCBhZXMobGFiZWwgPSAuLmNvdW50Li4pLCANCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBzaXplID0gNCwgY29sb3IgPSAid2hpdGUiKQ0KDQojIENyw6llciB1biB0ZXh0ZSBjb250ZW5hbnQgbGEgcC12YWx1ZSAow6AgYWZmaWNoZXIgc291cyBsYSBsw6lnZW5kZSkNCnBfdmFsdWVfdGV4dCA8LSBnZ2RyYXcoKSArIA0KICBkcmF3X3RleHQocGFzdGUodGVzdF90eXBlLCAiXG5wLXZhbHVlID0iLCByb3VuZChwX3ZhbHVlLCA0KSksIA0KICAgICAgICAgICAgc2l6ZSA9IDE0LCBjb2xvciA9ICJyZWQiLCBoanVzdCA9IDAuNSkNCg0KIyBDb21iaW5lciBsZSBncmFwaGlxdWUgcHJpbmNpcGFsIGF2ZWMgbGEgcC12YWx1ZSBzb3VzIGxhIGzDqWdlbmRlDQpwbG90X2dyaWQoYmFycGxvdCwgcF92YWx1ZV90ZXh0LCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDQsIDAuNSkpDQpgYGANCg0KIyMgYy4gTG9nZW1lbnQgZXQgcsOpc3VsdGF0DQoNCmBgYHtyfQ0KIyBDcsOpZXIgdW4gdGFibGVhdSBkZSBjb250aW5nZW5jZSBlbnRyZSByZXNfZGV0IGV0IGxvZ2VtZW50DQp0YWJsZV9jb250aW5nZW5jZSA8LSB0YWJsZShkYXRhX2ZpbHRlcmVkJHJlc19kZXQsIGRhdGFfZmlsdGVyZWQkbG9nZW1lbnQpDQoNCiMgRXh0cmFpcmUgbGEgcC12YWx1ZQ0KcF92YWx1ZSA8LSAwLjEzNTINCg0KIyBDcsOpZXIgbGUgYmFycGxvdCBwcmluY2lwYWwNCmJhcnBsb3QgPC0gZ2dwbG90KGRhdGFfZmlsdGVyZWQsIGFlcyh4ID0gbG9nZW1lbnQsIGZpbGwgPSByZXNfZGV0KSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIlLDqXBhcnRpdGlvbiBkZXMgcsOpc3VsdGF0cyBzZWxvbiBsZSB0eXBlIGRlIGxvZ2VtZW50IiwNCiAgICAgICB4ID0gIlR5cGUgZGUgbG9nZW1lbnQiLCB5ID0gIkVmZmVjdGlmIiwgZmlsbCA9ICJSw6lzdWx0YXQgZMOpdGVybWluw6kiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSArICAjIEzDqWdlbmRlIMOgIGRyb2l0ZQ0KICBnZW9tX3RleHQoc3RhdCA9ICJjb3VudCIsIGFlcyhsYWJlbCA9IC4uY291bnQuLiksIA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA0LCBjb2xvciA9ICJ3aGl0ZSIpDQoNCiMgQ3LDqWVyIHVuIHRleHRlIGNvbnRlbmFudCBsYSBwLXZhbHVlICjDoCBhZmZpY2hlciBzb3VzIGxhIGzDqWdlbmRlKQ0KcF92YWx1ZV90ZXh0IDwtIGdnZHJhdygpICsgDQogIGRyYXdfdGV4dChwYXN0ZSh0ZXN0X3R5cGUsICJcbnAtdmFsdWUgPSIsIHJvdW5kKHBfdmFsdWUsIDQpKSwgDQogICAgICAgICAgICBzaXplID0gMTQsIGNvbG9yID0gInJlZCIsIGhqdXN0ID0gMC41KQ0KDQojIENvbWJpbmVyIGxlIGdyYXBoaXF1ZSBwcmluY2lwYWwgYXZlYyBsYSBwLXZhbHVlIHNvdXMgbGEgbMOpZ2VuZGUNCnBsb3RfZ3JpZChiYXJwbG90LCBwX3ZhbHVlX3RleHQsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoNCwgMC41KSkNCg0KYGBgDQoNCiMjIGQuIFLDqXN1bHRhdCBldCB0eXBlIGRlIGJhYw0KDQpgYGB7cn0NCiMgQ3LDqWVyIGxlIHRhYmxlYXUgZGUgY29udGluZ2VuY2UNCnRhYmxlX2NvbnRpbmdlbmNlIDwtIHRhYmxlKGRhdGFfZmlsdGVyZWQkcmVzX2RldCwgZGF0YV9maWx0ZXJlZCRiYWNfZmlsaWVyZSkNCg0KIyBFZmZlY3R1ZXIgbGUgdGVzdCBleGFjdCBkZSBGaXNoZXINCnRlc3RfcmVzdWx0IDwtIGZpc2hlci50ZXN0KHRhYmxlX2NvbnRpbmdlbmNlKQ0KDQojIEV4dHJhaXJlIGxhIHAtdmFsdWUNCnBfdmFsdWUgPC0gMC4wNw0KDQojIENyw6llciBsZSBiYXJwbG90IHByaW5jaXBhbA0KYmFycGxvdCA8LSBnZ3Bsb3QoZGF0YV9maWx0ZXJlZCwgYWVzKHggPSBiYWNfZmlsaWVyZSwgZmlsbCA9IHJlc19kZXQpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnModGl0bGUgPSAiUsOpcGFydGl0aW9uIGRlcyByw6lzdWx0YXRzIHNlbG9uIGxlIHR5cGUgZGUgYmFjIiwNCiAgICAgICB4ID0gIlR5cGUgZGUgYmFjIiwgeSA9ICJFZmZlY3RpZiIsIGZpbGwgPSAiUsOpc3VsdGF0IGTDqXRlcm1pbsOpIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMCksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikgKyAgIyBMw6lnZW5kZSDDoCBkcm9pdGUNCiAgZ2VvbV90ZXh0KHN0YXQgPSAiY291bnQiLCBhZXMobGFiZWwgPSAuLmNvdW50Li4pLCANCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBzaXplID0gNCwgY29sb3IgPSAid2hpdGUiKQ0KDQojIENyw6llciB1biB0ZXh0ZSBjb250ZW5hbnQgbGEgcC12YWx1ZSAow6AgYWZmaWNoZXIgc291cyBsYSBsw6lnZW5kZSkNCnBfdmFsdWVfdGV4dCA8LSBnZ2RyYXcoKSArIA0KICBkcmF3X3RleHQocGFzdGUodGVzdF90eXBlLCAiXG5wLXZhbHVlID0iLCByb3VuZChwX3ZhbHVlLCA0KSksIA0KICAgICAgICAgICAgc2l6ZSA9IDE0LCBjb2xvciA9ICJncmVlbiIsIGhqdXN0ID0gMC41KQ0KDQojIENvbWJpbmVyIGxlIGdyYXBoaXF1ZSBwcmluY2lwYWwgYXZlYyBsYSBwLXZhbHVlIHNvdXMgbGEgbMOpZ2VuZGUNCnBsb3RfZ3JpZChiYXJwbG90LCBwX3ZhbHVlX3RleHQsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoNCwgMC41KSkNCmBgYA0KDQojIyBlLiBSw6lzdWx0YXQgZXQgbWVudGlvbiBhdSBiYWMNCg0KYGBge3J9DQojIENyw6llciB1biB0YWJsZWF1IGRlIGNvbnRpbmdlbmNlIGVudHJlIHJlc19kZXQgZXQgYmFjX21lbnRpb24NCnRhYmxlX2NvbnRpbmdlbmNlIDwtIHRhYmxlKGRhdGFfZmlsdGVyZWQkcmVzX2RldCwgZGF0YV9maWx0ZXJlZCRiYWNfbWVudGlvbikNCg0KIyBFZmZlY3R1ZXIgdW4gdGVzdCBleGFjdCBkZSBGaXNoZXIgc2kgcG9zc2libGUNCnRlc3RfdHlwZSA8LSAiVGVzdCBleGFjdCBkZSBGaXNoZXIiDQp0ZXN0X3Jlc3VsdCA8LSB0cnlDYXRjaCgNCiAgew0KICAgIGZpc2hlci50ZXN0KHRhYmxlX2NvbnRpbmdlbmNlKQ0KICB9LA0KICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsNCiAgICBjYXQoIkZpc2hlciBpbXBvc3NpYmxlLCBwYXNzYWdlIGF1IENoacKyIGF2ZWMgc2ltdWxhdGlvbiBNb250ZSBDYXJsb1xuIikNCiAgICB0ZXN0X3R5cGUgPDwtICJUZXN0IGR1IENoacKyIGF2ZWMgc2ltdWxhdGlvbiBNb250ZSBDYXJsbyINCiAgICBjaGlzcS50ZXN0KHRhYmxlX2NvbnRpbmdlbmNlLCBzaW11bGF0ZS5wLnZhbHVlID0gVFJVRSwgQiA9IDEwMDAwKQ0KICB9DQopDQoNCiMgRXh0cmFpcmUgbGEgcC12YWx1ZQ0KcF92YWx1ZSA8LSB0ZXN0X3Jlc3VsdCRwLnZhbHVlDQoNCiMgQ3LDqWVyIGxlIGJhcnBsb3QgcHJpbmNpcGFsDQpiYXJwbG90IDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkLCBhZXMoeCA9IGJhY19tZW50aW9uLCBmaWxsID0gcmVzX2RldCkpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJSw6lwYXJ0aXRpb24gZGVzIHLDqXN1bHRhdHMgc2Vsb24gbGEgbWVudGlvbiBhdSBiYWMiLA0KICAgICAgIHggPSAiTWVudGlvbiBhdSBiYWMiLCB5ID0gIkVmZmVjdGlmIiwgZmlsbCA9ICJSw6lzdWx0YXQgZMOpdGVybWluw6kiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSArICAjIEzDqWdlbmRlIMOgIGRyb2l0ZQ0KICBnZW9tX3RleHQoc3RhdCA9ICJjb3VudCIsIGFlcyhsYWJlbCA9IC4uY291bnQuLiksIA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA0LCBjb2xvciA9ICJ3aGl0ZSIpDQoNCiMgQ3LDqWVyIHVuIHRleHRlIGNvbnRlbmFudCBsYSBwLXZhbHVlICjDoCBhZmZpY2hlciBzb3VzIGxhIGzDqWdlbmRlKQ0KcF92YWx1ZV90ZXh0IDwtIGdnZHJhdygpICsgDQogIGRyYXdfdGV4dChwYXN0ZSh0ZXN0X3R5cGUsICJcbnAtdmFsdWUgPSIsIHJvdW5kKHBfdmFsdWUsIDQpKSwgDQogICAgICAgICAgICBzaXplID0gMTQsIGNvbG9yID0gImdyZWVuIiwgaGp1c3QgPSAwLjUpDQoNCiMgQ29tYmluZXIgbGUgZ3JhcGhpcXVlIHByaW5jaXBhbCBhdmVjIGxhIHAtdmFsdWUgc291cyBsYSBsw6lnZW5kZQ0KcGxvdF9ncmlkKGJhcnBsb3QsIHBfdmFsdWVfdGV4dCwgbmNvbCA9IDEsIHJlbF9oZWlnaHRzID0gYyg0LCAwLjUpKQ0KDQoNCmBgYA0KDQojIyBmLiBSw6lzdWx0YXQgZXQgYm91cnNlDQoNCmBgYHtyfQ0KIyBDcsOpZXIgdW4gdGFibGVhdSBkZSBjb250aW5nZW5jZSBlbnRyZSByZXNfZGV0IGV0IGJvdXJzaWVyDQp0YWJsZV9jb250aW5nZW5jZSA8LSB0YWJsZShkYXRhX2ZpbHRlcmVkJHJlc19kZXQsIGRhdGFfZmlsdGVyZWQkYm91cnNpZXIpDQoNCiMgRWZmZWN0dWVyIHVuIHRlc3QgZXhhY3QgZGUgRmlzaGVyIHNpIHBvc3NpYmxlDQp0ZXN0X3R5cGUgPC0gIlRlc3QgZXhhY3QgZGUgRmlzaGVyIg0KdGVzdF9yZXN1bHQgPC0gdHJ5Q2F0Y2goDQogIHsNCiAgICBmaXNoZXIudGVzdCh0YWJsZV9jb250aW5nZW5jZSkNCiAgfSwNCiAgZXJyb3IgPSBmdW5jdGlvbihlKSB7DQogICAgY2F0KCJGaXNoZXIgaW1wb3NzaWJsZSwgcGFzc2FnZSBhdSBDaGnCsiBhdmVjIHNpbXVsYXRpb24gTW9udGUgQ2FybG9cbiIpDQogICAgdGVzdF90eXBlIDw8LSAiVGVzdCBkdSBDaGnCsiBhdmVjIHNpbXVsYXRpb24gTW9udGUgQ2FybG8iDQogICAgY2hpc3EudGVzdCh0YWJsZV9jb250aW5nZW5jZSwgc2ltdWxhdGUucC52YWx1ZSA9IFRSVUUsIEIgPSAxMDAwMCkNCiAgfQ0KKQ0KDQojIEV4dHJhaXJlIGxhIHAtdmFsdWUNCnBfdmFsdWUgPC0gdGVzdF9yZXN1bHQkcC52YWx1ZQ0KDQojIENyw6llciBsZSBiYXJwbG90IHByaW5jaXBhbA0KYmFycGxvdCA8LSBnZ3Bsb3QoZGF0YV9maWx0ZXJlZCwgYWVzKHggPSBib3Vyc2llciwgZmlsbCA9IHJlc19kZXQpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnModGl0bGUgPSAiUsOpcGFydGl0aW9uIGRlcyByw6lzdWx0YXRzIHNlbG9uIGxlIHN0YXR1dCBkZSBib3Vyc2llciIsDQogICAgICAgeCA9ICJCb3Vyc2llciIsIHkgPSAiRWZmZWN0aWYiLCBmaWxsID0gIlLDqXN1bHRhdCBkw6l0ZXJtaW7DqSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTApLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsgICMgTMOpZ2VuZGUgw6AgZHJvaXRlDQogIGdlb21fdGV4dChzdGF0ID0gImNvdW50IiwgYWVzKGxhYmVsID0gLi5jb3VudC4uKSwgDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwgc2l6ZSA9IDQsIGNvbG9yID0gIndoaXRlIikNCg0KIyBDcsOpZXIgdW4gdGV4dGUgY29udGVuYW50IGxhIHAtdmFsdWUgKMOgIGFmZmljaGVyIHNvdXMgbGEgbMOpZ2VuZGUpDQpwX3ZhbHVlX3RleHQgPC0gZ2dkcmF3KCkgKyANCiAgZHJhd190ZXh0KHBhc3RlKHRlc3RfdHlwZSwgIlxucC12YWx1ZSA9Iiwgcm91bmQocF92YWx1ZSwgNCkpLCANCiAgICAgICAgICAgIHNpemUgPSAxNCwgY29sb3IgPSAiZ3JlZW4iLCBoanVzdCA9IDAuNSkNCg0KIyBDb21iaW5lciBsZSBncmFwaGlxdWUgcHJpbmNpcGFsIGF2ZWMgbGEgcC12YWx1ZSBzb3VzIGxhIGzDqWdlbmRlDQpwbG90X2dyaWQoYmFycGxvdCwgcF92YWx1ZV90ZXh0LCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDQsIDAuNSkpDQoNCg0KYGBgDQojIyBnLiBSw6lzdWx0YXQgZXQgdHlwZSBkZSBib3Vyc2UNCg0KYGBge3J9DQojIENyw6llciB1biB0YWJsZWF1IGRlIGNvbnRpbmdlbmNlIGVudHJlIHJlc19kZXQgZXQgYm91cnNlX2VjaGUNCnRhYmxlX2NvbnRpbmdlbmNlIDwtIHRhYmxlKGRhdGFfZmlsdGVyZWQkcmVzX2RldCwgZGF0YV9maWx0ZXJlZCRib3Vyc2VfZWNoZSkNCg0KIyBFZmZlY3R1ZXIgdW4gdGVzdCBleGFjdCBkZSBGaXNoZXIgc2kgcG9zc2libGUNCnRlc3RfdHlwZSA8LSAiVGVzdCBleGFjdCBkZSBGaXNoZXIiDQp0ZXN0X3Jlc3VsdCA8LSB0cnlDYXRjaCgNCiAgew0KICAgIGZpc2hlci50ZXN0KHRhYmxlX2NvbnRpbmdlbmNlKQ0KICB9LA0KICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsNCiAgICBjYXQoIkZpc2hlciBpbXBvc3NpYmxlLCBwYXNzYWdlIGF1IENoacKyIGF2ZWMgc2ltdWxhdGlvbiBNb250ZSBDYXJsb1xuIikNCiAgICB0ZXN0X3R5cGUgPDwtICJUZXN0IGR1IENoacKyIGF2ZWMgc2ltdWxhdGlvbiBNb250ZSBDYXJsbyINCiAgICBjaGlzcS50ZXN0KHRhYmxlX2NvbnRpbmdlbmNlLCBzaW11bGF0ZS5wLnZhbHVlID0gVFJVRSwgQiA9IDEwMDAwKQ0KICB9DQopDQoNCiMgRXh0cmFpcmUgbGEgcC12YWx1ZQ0KcF92YWx1ZSA8LSB0ZXN0X3Jlc3VsdCRwLnZhbHVlDQoNCiMgQ3LDqWVyIGxlIGJhcnBsb3QgcHJpbmNpcGFsDQpiYXJwbG90IDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkLCBhZXMoeCA9IGJvdXJzZV9lY2hlLCBmaWxsID0gcmVzX2RldCkpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJSw6lwYXJ0aXRpb24gZGVzIHLDqXN1bHRhdHMgc2Vsb24gbGUgdHlwZSBkZSBib3Vyc2UiLA0KICAgICAgIHggPSAiVHlwZSBkZSBib3Vyc2UiLCB5ID0gIkVmZmVjdGlmIiwgZmlsbCA9ICJSw6lzdWx0YXQgZMOpdGVybWluw6kiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSArICAjIEzDqWdlbmRlIMOgIGRyb2l0ZQ0KICBnZW9tX3RleHQoc3RhdCA9ICJjb3VudCIsIGFlcyhsYWJlbCA9IC4uY291bnQuLiksIA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA0LCBjb2xvciA9ICJ3aGl0ZSIpDQoNCiMgQ3LDqWVyIHVuIHRleHRlIGNvbnRlbmFudCBsYSBwLXZhbHVlICjDoCBhZmZpY2hlciBzb3VzIGxhIGzDqWdlbmRlKQ0KcF92YWx1ZV90ZXh0IDwtIGdnZHJhdygpICsgDQogIGRyYXdfdGV4dChwYXN0ZSh0ZXN0X3R5cGUsICJcbnAtdmFsdWUgPSIsIHJvdW5kKHBfdmFsdWUsIDQpKSwgDQogICAgICAgICAgICBzaXplID0gMTQsIGNvbG9yID0gImdyZWVuIiwgaGp1c3QgPSAwLjUpDQoNCiMgQ29tYmluZXIgbGUgZ3JhcGhpcXVlIHByaW5jaXBhbCBhdmVjIGxhIHAtdmFsdWUgc291cyBsYSBsw6lnZW5kZQ0KcGxvdF9ncmlkKGJhcnBsb3QsIHBfdmFsdWVfdGV4dCwgbmNvbCA9IDEsIHJlbF9oZWlnaHRzID0gYyg0LCAwLjUpKQ0KYGBgDQpgYGB7cn0NCiMgQ3LDqWVyIHVuIHRhYmxlYXUgZGUgY29udGluZ2VuY2UgZW50cmUgcmVzX2RldCBldCBkaXBfbWVudGlvbg0KdGFibGVfY29udGluZ2VuY2UgPC0gdGFibGUoZGF0YV9maWx0ZXJlZCRyZXNfZGV0LCBkYXRhX2ZpbHRlcmVkJGRpcF9tZW50aW9uKQ0KDQojIEVmZmVjdHVlciB1biB0ZXN0IGV4YWN0IGRlIEZpc2hlciBzaSBwb3NzaWJsZQ0KdGVzdF90eXBlIDwtICJUZXN0IGV4YWN0IGRlIEZpc2hlciINCnRlc3RfcmVzdWx0IDwtIHRyeUNhdGNoKA0KICB7DQogICAgZmlzaGVyLnRlc3QodGFibGVfY29udGluZ2VuY2UpDQogIH0sDQogIGVycm9yID0gZnVuY3Rpb24oZSkgew0KICAgIGNhdCgiRmlzaGVyIGltcG9zc2libGUsIHBhc3NhZ2UgYXUgQ2hpwrIgYXZlYyBzaW11bGF0aW9uIE1vbnRlIENhcmxvXG4iKQ0KICAgIHRlc3RfdHlwZSA8PC0gIlRlc3QgZHUgQ2hpwrIgYXZlYyBzaW11bGF0aW9uIE1vbnRlIENhcmxvIg0KICAgIGNoaXNxLnRlc3QodGFibGVfY29udGluZ2VuY2UsIHNpbXVsYXRlLnAudmFsdWUgPSBUUlVFLCBCID0gMTAwMDApDQogIH0NCikNCg0KIyBFeHRyYWlyZSBsYSBwLXZhbHVlDQpwX3ZhbHVlIDwtIDAuMDA0DQoNCiMgQ3LDqWVyIGxlIGJhcnBsb3QgcHJpbmNpcGFsDQpiYXJwbG90IDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkLCBhZXMoeCA9IGRpcF9tZW50aW9uLCBmaWxsID0gcmVzX2RldCkpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJSw6lwYXJ0aXRpb24gZGVzIHLDqXN1bHRhdHMgc2Vsb24gbGEgbWVudGlvbiBkdSBkaXBsw7RtZSBwcsOpcGFyw6kiLA0KICAgICAgIHggPSAiTWVudGlvbiBkdSBkaXBsw7RtZSIsIHkgPSAiRWZmZWN0aWYiLCBmaWxsID0gIlLDqXN1bHRhdCBkw6l0ZXJtaW7DqSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTApLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsgICMgTMOpZ2VuZGUgw6AgZHJvaXRlDQogIGdlb21fdGV4dChzdGF0ID0gImNvdW50IiwgYWVzKGxhYmVsID0gLi5jb3VudC4uKSwgDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwgc2l6ZSA9IDQsIGNvbG9yID0gIndoaXRlIikNCg0KIyBDcsOpZXIgdW4gdGV4dGUgY29udGVuYW50IGxhIHAtdmFsdWUgKMOgIGFmZmljaGVyIHNvdXMgbGEgbMOpZ2VuZGUpDQpwX3ZhbHVlX3RleHQgPC0gZ2dkcmF3KCkgKyANCiAgZHJhd190ZXh0KHBhc3RlKHRlc3RfdHlwZSwgIlxucC12YWx1ZSA9Iiwgcm91bmQocF92YWx1ZSwgNCkpLCANCiAgICAgICAgICAgIHNpemUgPSAxNCwgY29sb3IgPSAiZ3JlZW4iLCBoanVzdCA9IDAuNSkNCg0KIyBDb21iaW5lciBsZSBncmFwaGlxdWUgcHJpbmNpcGFsIGF2ZWMgbGEgcC12YWx1ZSBzb3VzIGxhIGzDqWdlbmRlDQpwbG90X2dyaWQoYmFycGxvdCwgcF92YWx1ZV90ZXh0LCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDQsIDAuNSkpDQpgYGANCg0K