STAPS

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

i. Intitulé de formation en 2024-2025


Formation2024 = fastggplot(data, "2024", "Formation 2024-2025", "", "Nombre d'occurence")
Formation2024 <- Formation2024 + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Formation2024

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
  )

III. Modèle prenant toutes les variables ensemble


# Création du graphique avec ggplot2
ggplot(importance_data, aes(x = reorder(Variable, Importance), y = Importance)) +
  geom_bar(stat = "identity", fill = "skyblue", color = "black") +  # Barres avec couleur et bordure
  coord_flip() +  # Inverser les axes pour une meilleure lisibilité
  labs(title = "Variables significatives avec importance > seuil 95%",
       x = "Variables", y = "Importance") +
  theme_minimal() +  # Thème minimaliste
  theme(
    axis.text.x = element_text(size = 10, angle = 45, hjust = 1),  # Rotation des noms des variables
    axis.text.y = element_text(size = 10)  # Taille des noms des variables
  ) +
  geom_hline(yintercept = seuil_importance, linetype = "dashed", color = "red", size = 1.5)  # Ajouter le seuil

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