Packages

library("dplyr")
library("ggplot2")
library("tidyr")
library("readr")
library("car") # para sp

Datasets

Dataset 1

df <- read.csv("mediciones.csv", header = T, sep = ",")
str(df)
'data.frame':   108 obs. of  7 variables:
 $ Tipo     : Factor w/ 2 levels "Lesion","Sellante": 1 1 1 2 2 2 1 1 1 2 ...
 $ Muestra  : Factor w/ 18 levels "A1","A2","A3",..: 1 1 1 1 1 1 2 2 2 2 ...
 $ Muestra.2: int  1 1 1 1 1 1 2 2 2 2 ...
 $ Grupo    : Factor w/ 3 levels "A","B","C": 1 1 1 1 1 1 1 1 1 1 ...
 $ N        : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Angulo   : num  90 17.4 18.4 21.8 18.4 ...
 $ LD       : num  0.097 0.102 0.077 0.019 0.019 0.022 0.546 0.228 0.134 0.023 ...
df$Muestra.2 <- as.factor(df$Muestra.2)
df$N <- as.factor(df$N)
levels(df$Grupo)[levels(df$Grupo)=="A"] <- "H3PO4"
levels(df$Grupo)[levels(df$Grupo)=="B"] <- "H3PO4 + NaOCL"
levels(df$Grupo)[levels(df$Grupo)=="C"] <- "NaOCL + H3PO4"
df$LD <- df$LD*1000 # convierto a micrones

Dataset 2

df2 <- read.csv("mediciones_2.csv", header = T, sep = ",", encoding = "UTF-8")
df2$Lesión <- df2$Lesión*100
df2$Sellante <- df2$Sellante*100
tbl_df(df2)

Dataset 3

df3 <- read.csv("mediciones_3.csv", header = T, sep = ";")
str(df3)
'data.frame':   67 obs. of  9 variables:
 $ Tipo          : Factor w/ 2 levels "","Lesion": 2 2 2 2 2 2 2 2 2 2 ...
 $ Muestra       : Factor w/ 19 levels "","A1","A2","A3",..: 2 2 2 3 3 3 4 4 4 5 ...
 $ Muestra.2     : int  1 1 1 2 2 2 3 3 3 4 ...
 $ Grupo         : Factor w/ 4 levels "","A","B","C": 2 2 2 2 2 2 2 2 2 2 ...
 $ N             : int  3 1 2 7 8 9 13 14 15 19 ...
 $ AnguloLesion  : num  18.4 90 17.4 -20.8 -13.1 ...
 $ Lesion        : num  0.077 0.097 0.102 0.546 0.228 0.134 0.827 0.126 0.122 0.591 ...
 $ AnguloSellante: num  18.43 21.8 18.43 -7.12 -3.81 ...
 $ Sellante      : num  0.022 0.019 0.019 0.047 0.037 0.023 0.032 0.032 0.018 0.095 ...
df3$Lesion <- df3$Lesion*100
df3$Sellante <- df3$Sellante*100
df3$Muestra.2 <- as.factor(df3$Muestra.2)
df3 <- na.omit(df3) #omito los NA
df3 <- df3 %>%  
        mutate(Porcentaje.Penetracion = (Sellante/Lesion)*100)
levels(df3$Grupo)[levels(df3$Grupo)=="A"] <- "H3PO4"
levels(df3$Grupo)[levels(df3$Grupo)=="B"] <- "H3PO4 + NaOCL"
levels(df3$Grupo)[levels(df3$Grupo)=="C"] <- "NaOCL + H3PO4"
df3 <- df3 %>% 
        filter(Lesion <60)

Descriptive stats

df %>% 
        group_by(Grupo) %>% 
        summarise( n= n(), "Promedio lesión um" = mean(LD), DE = sd(LD)) %>% 
        ungroup()
df %>% 
        group_by(Tipo) %>% 
        summarise( n= n(), "Promedio um" = mean(LD), DE = sd(LD)) %>% 
        ungroup()

Gráficos

Sellante

df %>% 
        filter(Tipo == "Sellante") %>% 
        ggplot(aes(x=Grupo, y=LD)) + geom_boxplot() + 
        ggtitle("Profundidad penetración sellante por grupo") +
        labs(x="Grupo", y= "Profundidad " * mu ~ "m" ) + 
        ylim(0,350) + 
        theme_minimal()

Lesion

df %>% 
        filter(Tipo == "Lesion") %>% 
        ggplot(aes(x=Grupo, y=LD)) + geom_boxplot() +
        ggtitle("Profundidad lesión grupo") +
        labs(x="Grupo", y= "Profundidad " * mu ~ "m" ) + 
        ylim(0,350) + 
        theme_minimal()

Comparación profundidad lesión y penetración del sellante

ggplot(aes(y = LD, x = Grupo, fill = Tipo), data = df) +
        geom_boxplot() +
        ggtitle("Profundidad de lesiones y penetracion de sellante por grupo") +
        labs(x="Grupo",y= "Profundidad en (" * mu ~ "m)" ) + 
        theme_minimal()
df3 %>% 
        group_by(Grupo) %>% 
        summarise(
                n = n(), 
                Promedio.Lesion=mean(Lesion), SD.Lesion=sd(Lesion), 
                Promedio.Sellante=mean(Sellante), SD.Sellante=sd(Sellante), 
                Promedio.Penetracion=mean(Porcentaje.Penetracion), SD.Penetracion=sd(Porcentaje.Penetracion)
        )
anova.lesion <- aov(df3$Lesion~df3$Grupo)
anova.lesion
summary(anova.lesion)
            Df Sum Sq Mean Sq F value Pr(>F)  
df3$Grupo    2   1218   609.1   3.969 0.0251 *
Residuals   50   7674   153.5                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
TukeyHSD(anova.lesion, conf.level = 0.95)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = df3$Lesion ~ df3$Grupo)

$`df3$Grupo`
                                 diff         lwr        upr     p adj
H3PO4 + NaOCL-H3PO4         -9.873529 -19.9935623  0.2465035 0.0572316
NaOCL + H3PO4-H3PO4          0.470915  -9.6491179 10.5909479 0.9930604
NaOCL + H3PO4-H3PO4 + NaOCL 10.344444   0.3700311 20.3188578 0.0405094
anova.sellante <- aov(df3$Sellante~df3$Grupo)
anova.sellante
Call:
   aov(formula = df3$Sellante ~ df3$Grupo)

Terms:
                df3$Grupo Residuals
Sum of Squares    77.7382 1157.3629
Deg. of Freedom         2        50

Residual standard error: 4.81116
Estimated effects may be unbalanced
summary(anova.sellante)
            Df Sum Sq Mean Sq F value Pr(>F)
df3$Grupo    2   77.7   38.87   1.679  0.197
Residuals   50 1157.4   23.15               

Porcentaje penetración

ggplot(aes(y = Porcentaje.Penetracion, x = Grupo), data = df2) +
        geom_boxplot() +
        ggtitle("Porcentaje de penetración del sellante en lesión por grupo") +
        labs(x="Grupo",y= "Porcentaje de penetración" ) + 
        ylim(0,100) +
        theme_minimal()

ggplot(aes(y = Porcentaje.Penetracion, x = Grupo), data = df3) +
        geom_boxplot() +
        ggtitle("Porcentaje de penetración del sellante en lesión por grupo") +
        labs(x="Grupo",y= "Porcentaje de penetración" ) + 
        ylim(0,100) +
        theme_minimal()

Análisis inferenciales

supuestos

acido <- df2 %>% 
        filter(Grupo == "H3PO4")
acido.desprot <-  df2 %>% 
        filter(Grupo == "H3PO4 + NaOCL")
desprot.acido <- df2 %>% 
wilcox.test(acido$Porcentaje.Penetracion)

    Wilcoxon signed rank test

data:  acido$Porcentaje.Penetracion
V = 21, p-value = 0.03125
alternative hypothesis: true location is not equal to 0
wilcox.test(acido.desprot$Porcentaje.Penetracion)

    Wilcoxon signed rank test

data:  acido.desprot$Porcentaje.Penetracion
V = 21, p-value = 0.03125
alternative hypothesis: true location is not equal to 0
wilcox.test(desprot.acido$Porcentaje.Penetracion)

    Wilcoxon signed rank test

data:  desprot.acido$Porcentaje.Penetracion
V = 21, p-value = 0.03125
alternative hypothesis: true location is not equal to 0

ANOVA

m1 <- aov(df2$Porcentaje.Penetracion~df2$Grupo)
summary(m1)
            Df Sum Sq Mean Sq F value Pr(>F)
df2$Grupo    2    129    64.4   0.113  0.894
Residuals   15   8547   569.8               
m1
Call:
   aov(formula = df2$Porcentaje.Penetracion ~ df2$Grupo)

Terms:
                df2$Grupo Residuals
Sum of Squares    128.897  8546.594
Deg. of Freedom         2        15

Residual standard error: 23.86992
Estimated effects may be unbalanced
ggplot(df2, aes(Sellante, Lesión, color=Grupo, shape = Grupo)) +
        geom_point(size = 3) + 
        xlab("Profundidad penetración sellante en um") + ylab("Profundidad lesión en um") +
        labs(title = "Relación entre profundidad de la lesión y penetración del sellante") + 
        ylim(0, 120) + xlim(0, 75) + 
        geom_smooth(method="lm", fill=NA) +
        theme_minimal()

layout(matrix(c(1,2,3,4),2,2)) 
plot(m1) 

Correlation analysis

Primero, son las lesiones similares?

m2 <- aov(df3$Lesion ~ df3$Grupo)
m2
Call:
   aov(formula = df3$Lesion ~ df3$Grupo)

Terms:
                df3$Grupo Residuals
Sum of Squares   1218.287  7673.645
Deg. of Freedom         2        50

Residual standard error: 12.38842
Estimated effects may be unbalanced
summary(m3)
            Df Sum Sq Mean Sq F value Pr(>F)
df3$Grupo    2   77.7   38.87   1.679  0.197
Residuals   50 1157.4   23.15               

Y penetran los sellantes iguales?

m3 <- aov(df3$Sellante ~ df3$Grupo)
m3
Call:
   aov(formula = df3$Sellante ~ df3$Grupo)

Terms:
                df3$Grupo Residuals
Sum of Squares    77.7382 1157.3629
Deg. of Freedom         2        50

Residual standard error: 4.81116
Estimated effects may be unbalanced
summary(m3)
            Df Sum Sq Mean Sq F value Pr(>F)
df3$Grupo    2   77.7   38.87   1.679  0.197
Residuals   50 1157.4   23.15               

DF3

Comparación entre grupos

m4 <- lm(Porcentaje.Penetracion~Grupo, data = df3)
m4

Call:
lm(formula = Porcentaje.Penetracion ~ Grupo, data = df3)

Coefficients:
       (Intercept)  GrupoH3PO4 + NaOCL  GrupoNaOCL + H3PO4  
            33.318               1.238              -1.715  
summary(m4)

Call:
lm(formula = Porcentaje.Penetracion ~ Grupo, data = df3)

Residuals:
    Min      1Q  Median      3Q     Max 
-26.284 -17.933  -7.921  14.128  74.310 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)          33.318      5.915   5.632 8.11e-07 ***
GrupoH3PO4 + NaOCL    1.238      8.249   0.150    0.881    
GrupoNaOCL + H3PO4   -1.715      8.249  -0.208    0.836    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.39 on 50 degrees of freedom
Multiple R-squared:  0.002654,  Adjusted R-squared:  -0.03724 
F-statistic: 0.06652 on 2 and 50 DF,  p-value: 0.9357
anova(m4)
Analysis of Variance Table

Response: Porcentaje.Penetracion
          Df  Sum Sq Mean Sq F value Pr(>F)
Grupo      2    79.1   39.57  0.0665 0.9357
Residuals 50 29743.7  594.87               

Chequeo normalidad

shapiro.test(residuals(m4)) 

    Shapiro-Wilk normality test

data:  residuals(m4)
W = 0.86277, p-value = 2.168e-05

Normalidad

do.call("rbind", with(df3, tapply(Porcentaje.Penetracion, Grupo, 
   function(x) unlist(shapiro.test(x)[c("statistic", "p.value")]))))
              statistic.W      p.value
H3PO4           0.7127640 0.0001618666
H3PO4 + NaOCL   0.8650695 0.0147722784
NaOCL + H3PO4   0.9135844 0.0995283649

Scatterplot

ggplot(df3, aes(Sellante, Lesion, color=Grupo, shape = Grupo)) +
        geom_point(size = 3) + 
        xlab("Profundidad penetración sellante en um") + ylab("Profundidad lesión en um") +
        labs(title = "Relación entre profundidad de la lesión y penetración del sellante") + 
        ylim(0, 60) + xlim(0, 35) + 
        geom_smooth(method="lm", fill=NA) +
        theme_minimal()

Tabla

df3 %>% 
        group_by(Grupo) %>% 
        summarise( n = n(), 
                   "Promedio profundidad lesión en um" = mean(Lesion), "Desviación estándar lesión (um)" = sd(Lesion), 
                   "Promedio penetración sellante en um" = mean(Sellante), "Desviación estándar sellante (um)" = sd(Sellante), 
                   "Promedio % penetración sellante" = mean(Porcentaje.Penetracion), "Desviación estándar % penetración sellante" = sd(Porcentaje.Penetracion)) %>% 
        ungroup()
m4 <- lm(df3$Porcentaje.Penetracion~df3$Grupo)
m4

Call:
lm(formula = df3$Porcentaje.Penetracion ~ df3$Grupo)

Coefficients:
           (Intercept)  df3$GrupoH3PO4 + NaOCL  df3$GrupoNaOCL + H3PO4  
                33.318                   1.238                  -1.715  
summary(m4)

Call:
lm(formula = df3$Porcentaje.Penetracion ~ df3$Grupo)

Residuals:
    Min      1Q  Median      3Q     Max 
-26.284 -17.933  -7.921  14.128  74.310 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)    
(Intercept)              33.318      5.915   5.632 8.11e-07 ***
df3$GrupoH3PO4 + NaOCL    1.238      8.249   0.150    0.881    
df3$GrupoNaOCL + H3PO4   -1.715      8.249  -0.208    0.836    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.39 on 50 degrees of freedom
Multiple R-squared:  0.002654,  Adjusted R-squared:  -0.03724 
F-statistic: 0.06652 on 2 and 50 DF,  p-value: 0.9357
layout(matrix(c(1,2,3,4),2,2)) 
plot(m1)

LS0tDQp0aXRsZTogRWZlY3RvIGRlbCBwcmV0cmF0YW1pZW50byB5IHByb3RvY29sbyBkZSBhcGxpY2FjacOzbiBkZSBOYU9DbCBlbiBsYSBwZW5ldHJhY2nDs24NCiAgZGVsIHNlbGxhbnRlIGVuIGVzbWFsdGUgY29uIGxlc2lvbmVzIG5hdHVyYWxlcw0KYXV0aG9yOiAiVXJpYmUgU0UsIEhlcm5hbmRleiBNUCwgSmFyYSBJLCBHb21leiBTUyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQoNCiMgUGFja2FnZXMNCmBgYHtyIHBhY2thZ2VzfQ0KbGlicmFyeSgiZHBseXIiKQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpsaWJyYXJ5KCJ0aWR5ciIpDQpsaWJyYXJ5KCJyZWFkciIpDQpsaWJyYXJ5KCJjYXIiKSAjIHBhcmEgc3ANCmBgYA0KDQojIERhdGFzZXRzDQojIyBEYXRhc2V0IDENCmBgYHtyIERhdGFzZXR9DQpkZiA8LSByZWFkLmNzdigibWVkaWNpb25lcy5jc3YiLCBoZWFkZXIgPSBULCBzZXAgPSAiLCIpDQpzdHIoZGYpDQpkZiRNdWVzdHJhLjIgPC0gYXMuZmFjdG9yKGRmJE11ZXN0cmEuMikNCmRmJE4gPC0gYXMuZmFjdG9yKGRmJE4pDQpsZXZlbHMoZGYkR3J1cG8pW2xldmVscyhkZiRHcnVwbyk9PSJBIl0gPC0gIkgzUE80Ig0KbGV2ZWxzKGRmJEdydXBvKVtsZXZlbHMoZGYkR3J1cG8pPT0iQiJdIDwtICJIM1BPNCArIE5hT0NMIg0KbGV2ZWxzKGRmJEdydXBvKVtsZXZlbHMoZGYkR3J1cG8pPT0iQyJdIDwtICJOYU9DTCArIEgzUE80Ig0KDQpkZiRMRCA8LSBkZiRMRCoxMDAwICMgY29udmllcnRvIGEgbWljcm9uZXMNCg0KYGBgDQoNCiMjIERhdGFzZXQgMg0KYGBge3IgZGYyfQ0KZGYyIDwtIHJlYWQuY3N2KCJtZWRpY2lvbmVzXzIuY3N2IiwgaGVhZGVyID0gVCwgc2VwID0gIiwiLCBlbmNvZGluZyA9ICJVVEYtOCIpDQpkZjIkTGVzacOzbiA8LSBkZjIkTGVzacOzbioxMDANCmRmMiRTZWxsYW50ZSA8LSBkZjIkU2VsbGFudGUqMTAwDQoNCnRibF9kZihkZjIpDQpgYGANCg0KDQojIyBEYXRhc2V0IDMNCg0KYGBge3IgZGF0YXNldCAzfQ0KZGYzIDwtIHJlYWQuY3N2KCJtZWRpY2lvbmVzXzMuY3N2IiwgaGVhZGVyID0gVCwgc2VwID0gIjsiKQ0Kc3RyKGRmMykNCmRmMyRMZXNpb24gPC0gZGYzJExlc2lvbioxMDANCmRmMyRTZWxsYW50ZSA8LSBkZjMkU2VsbGFudGUqMTAwDQpkZjMkTXVlc3RyYS4yIDwtIGFzLmZhY3RvcihkZjMkTXVlc3RyYS4yKQ0KZGYzIDwtIG5hLm9taXQoZGYzKSAjb21pdG8gbG9zIE5BDQpkZjMgPC0gZGYzICU+JSAgDQogICAgICAgIG11dGF0ZShQb3JjZW50YWplLlBlbmV0cmFjaW9uID0gKFNlbGxhbnRlL0xlc2lvbikqMTAwKQ0KbGV2ZWxzKGRmMyRHcnVwbylbbGV2ZWxzKGRmMyRHcnVwbyk9PSJBIl0gPC0gIkgzUE80Ig0KbGV2ZWxzKGRmMyRHcnVwbylbbGV2ZWxzKGRmMyRHcnVwbyk9PSJCIl0gPC0gIkgzUE80ICsgTmFPQ0wiDQpsZXZlbHMoZGYzJEdydXBvKVtsZXZlbHMoZGYzJEdydXBvKT09IkMiXSA8LSAiTmFPQ0wgKyBIM1BPNCINCg0KZGYzIDwtIGRmMyAlPiUgDQogICAgICAgIGZpbHRlcihMZXNpb24gPDYwKQ0KDQoNCmBgYA0KDQojIERlc2NyaXB0aXZlIHN0YXRzDQpgYGB7ciBwb3IgZ3J1cG99DQpkZiAlPiUgDQogICAgICAgIGdyb3VwX2J5KEdydXBvKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZSggbj0gbigpLCAiUHJvbWVkaW8gbGVzacOzbiB1bSIgPSBtZWFuKExEKSwgREUgPSBzZChMRCkpICU+JSANCiAgICAgICAgdW5ncm91cCgpDQoNCmBgYA0KDQpgYGB7ciBwb3IgdGlwb30NCg0KZGYgJT4lIA0KICAgICAgICBncm91cF9ieShUaXBvKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZSggbj0gbigpLCAiUHJvbWVkaW8gdW0iID0gbWVhbihMRCksIERFID0gc2QoTEQpKSAlPiUgDQogICAgICAgIHVuZ3JvdXAoKQ0KDQpgYGANCiMjIEdyw6FmaWNvcw0KDQojIyMgU2VsbGFudGUNCmBgYHtyIEdyYXBoIFNlbGxhbnRlfQ0KZGYgJT4lIA0KICAgICAgICBmaWx0ZXIoVGlwbyA9PSAiU2VsbGFudGUiKSAlPiUgDQogICAgICAgIGdncGxvdChhZXMoeD1HcnVwbywgeT1MRCkpICsgZ2VvbV9ib3hwbG90KCkgKyANCiAgICAgICAgZ2d0aXRsZSgiUHJvZnVuZGlkYWQgcGVuZXRyYWNpw7NuIHNlbGxhbnRlIHBvciBncnVwbyIpICsNCiAgICAgICAgbGFicyh4PSJHcnVwbyIsIHk9ICJQcm9mdW5kaWRhZCAiICogbXUgfiAibSIgKSArIA0KICAgICAgICB5bGltKDAsMzUwKSArIA0KICAgICAgICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCiMjIExlc2lvbg0KYGBge3IgR3JhcGggTGVzaW9ufQ0KZGYgJT4lIA0KICAgICAgICBmaWx0ZXIoVGlwbyA9PSAiTGVzaW9uIikgJT4lIA0KICAgICAgICBnZ3Bsb3QoYWVzKHg9R3J1cG8sIHk9TEQpKSArIGdlb21fYm94cGxvdCgpICsNCiAgICAgICAgZ2d0aXRsZSgiUHJvZnVuZGlkYWQgbGVzacOzbiBncnVwbyIpICsNCiAgICAgICAgbGFicyh4PSJHcnVwbyIsIHk9ICJQcm9mdW5kaWRhZCAiICogbXUgfiAibSIgKSArIA0KICAgICAgICB5bGltKDAsMzUwKSArIA0KICAgICAgICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMjIENvbXBhcmFjacOzbiBwcm9mdW5kaWRhZCBsZXNpw7NuIHkgcGVuZXRyYWNpw7NuIGRlbCBzZWxsYW50ZQ0KYGBge3IgQ29tcGFyYWNpw7NuIGVudHJlIGdydXBvc30NCmdncGxvdChhZXMoeSA9IExELCB4ID0gR3J1cG8sIGZpbGwgPSBUaXBvKSwgZGF0YSA9IGRmKSArDQogICAgICAgIGdlb21fYm94cGxvdCgpICsNCiAgICAgICAgZ2d0aXRsZSgiUHJvZnVuZGlkYWQgZGUgbGVzaW9uZXMgeSBwZW5ldHJhY2lvbiBkZSBzZWxsYW50ZSBwb3IgZ3J1cG8iKSArDQogICAgICAgIGxhYnMoeD0iR3J1cG8iLHk9ICJQcm9mdW5kaWRhZCBlbiAoIiAqIG11IH4gIm0pIiApICsgDQogICAgICAgIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCmBgYHtyIFRhYmxhIGNvbiBkZjN9DQpkZjMgJT4lIA0KICAgICAgICBncm91cF9ieShHcnVwbykgJT4lIA0KICAgICAgICBzdW1tYXJpc2UoDQogICAgICAgICAgICAgICAgbiA9IG4oKSwgDQogICAgICAgICAgICAgICAgUHJvbWVkaW8uTGVzaW9uPW1lYW4oTGVzaW9uKSwgU0QuTGVzaW9uPXNkKExlc2lvbiksIA0KICAgICAgICAgICAgICAgIFByb21lZGlvLlNlbGxhbnRlPW1lYW4oU2VsbGFudGUpLCBTRC5TZWxsYW50ZT1zZChTZWxsYW50ZSksIA0KICAgICAgICAgICAgICAgIFByb21lZGlvLlBlbmV0cmFjaW9uPW1lYW4oUG9yY2VudGFqZS5QZW5ldHJhY2lvbiksIFNELlBlbmV0cmFjaW9uPXNkKFBvcmNlbnRhamUuUGVuZXRyYWNpb24pDQogICAgICAgICkNCmBgYA0KDQpgYGB7ciBBbm92YSBwYXJhIGxlc2nDs259DQphbm92YS5sZXNpb24gPC0gYW92KGRmMyRMZXNpb25+ZGYzJEdydXBvKQ0KYW5vdmEubGVzaW9uDQpgYGANCmBgYHtyIEFOb3ZhIHBhcmEgbGVzaW9uIHJlc3VtZW59DQpzdW1tYXJ5KGFub3ZhLmxlc2lvbikNCmBgYA0KDQpgYGB7ciBBbm92YSBwb3IgbGVzaW9uIHBvc3Rob2N9DQoNClR1a2V5SFNEKGFub3ZhLmxlc2lvbiwgY29uZi5sZXZlbCA9IDAuOTUpDQpgYGANCg0KYGBge3IgQU5vdmEgcGFyYSBzZWxsYW50ZX0NCmFub3ZhLnNlbGxhbnRlIDwtIGFvdihkZjMkU2VsbGFudGV+ZGYzJEdydXBvKQ0KYW5vdmEuc2VsbGFudGUNCmBgYA0KDQpgYGB7ciBBbm92YSBwYXJhIHNlbGxhbnRlcyByZXN1bWVufQ0Kc3VtbWFyeShhbm92YS5zZWxsYW50ZSkNCmBgYA0KDQoNCiMjIyBQb3JjZW50YWplIHBlbmV0cmFjacOzbg0KYGBge3IgR3JhcGggcG9yY2VudGFqZSBwZW5ldHJhY2lvbn0NCmdncGxvdChhZXMoeSA9IFBvcmNlbnRhamUuUGVuZXRyYWNpb24sIHggPSBHcnVwbyksIGRhdGEgPSBkZjIpICsNCiAgICAgICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgICAgICBnZ3RpdGxlKCJQb3JjZW50YWplIGRlIHBlbmV0cmFjacOzbiBkZWwgc2VsbGFudGUgZW4gbGVzacOzbiBwb3IgZ3J1cG8iKSArDQogICAgICAgIGxhYnMoeD0iR3J1cG8iLHk9ICJQb3JjZW50YWplIGRlIHBlbmV0cmFjacOzbiIgKSArIA0KICAgICAgICB5bGltKDAsMTAwKSArDQogICAgICAgIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KYGBge3IgR3JhcGggJSBwZW5ldHJhY2nDs24gZGYzfQ0KZ2dwbG90KGFlcyh5ID0gUG9yY2VudGFqZS5QZW5ldHJhY2lvbiwgeCA9IEdydXBvKSwgZGF0YSA9IGRmMykgKw0KICAgICAgICBnZW9tX2JveHBsb3QoKSArDQogICAgICAgIGdndGl0bGUoIlBvcmNlbnRhamUgZGUgcGVuZXRyYWNpw7NuIGRlbCBzZWxsYW50ZSBlbiBsZXNpw7NuIHBvciBncnVwbyIpICsNCiAgICAgICAgbGFicyh4PSJHcnVwbyIseT0gIlBvcmNlbnRhamUgZGUgcGVuZXRyYWNpw7NuIiApICsgDQogICAgICAgIHlsaW0oMCwxMDApICsNCiAgICAgICAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIEFuw6FsaXNpcyBpbmZlcmVuY2lhbGVzDQpgYGB7ciBUYWJsYSBwYXJhIGFuYWxpc2lzIGluZmVyZW5jaWFsfQ0KZGYyICU+JSANCiAgICAgICAgZ3JvdXBfYnkoR3J1cG8pICU+JSANCiAgICAgICAgc3VtbWFyaXNlKCANCiAgICAgICAgICAgICAgICBQcm9tZWRpby5QZW5ldHJhY2lvbiA9IG1lYW4oUG9yY2VudGFqZS5QZW5ldHJhY2lvbiksIA0KICAgICAgICAgICAgICAgU0QuUGVuZXRyYWNpb24gPSBzZChQb3JjZW50YWplLlBlbmV0cmFjaW9uKSkgDQogICAgICAgIHVuZ3JvdXAoKQ0KYGBgDQoNCg0KIyMgc3VwdWVzdG9zDQpgYGB7ciBncnVwb3N9DQphY2lkbyA8LSBkZjIgJT4lIA0KICAgICAgICBmaWx0ZXIoR3J1cG8gPT0gIkgzUE80IikNCmFjaWRvLmRlc3Byb3QgPC0gIGRmMiAlPiUgDQogICAgICAgIGZpbHRlcihHcnVwbyA9PSAiSDNQTzQgKyBOYU9DTCIpDQpkZXNwcm90LmFjaWRvIDwtIGRmMiAlPiUgDQogICAgICAgIGZpbHRlcihHcnVwbyA9PSAiTmFPQ0wgKyBIM1BPNCIpDQpgYGANCg0KYGBge3Igbm9ybWFsaWRhZCBBfQ0Kd2lsY294LnRlc3QoYWNpZG8kUG9yY2VudGFqZS5QZW5ldHJhY2lvbikNCmBgYA0KDQpgYGB7ciBub3JtYWxpZGFkIEJ9DQp3aWxjb3gudGVzdChhY2lkby5kZXNwcm90JFBvcmNlbnRhamUuUGVuZXRyYWNpb24pDQpgYGANCg0KYGBge3Igbm9ybWFsaWRhZCBDfQ0Kd2lsY294LnRlc3QoZGVzcHJvdC5hY2lkbyRQb3JjZW50YWplLlBlbmV0cmFjaW9uKQ0KYGBgDQoNCg0KIyMgQU5PVkENCmBgYHtyIEFOT1ZBIENvbXBsZXRlbHkgUmFuZG9taXplZCBEZXNpZ259DQptMSA8LSBhb3YoZGYyJFBvcmNlbnRhamUuUGVuZXRyYWNpb25+ZGYyJEdydXBvKQ0Kc3VtbWFyeShtMSkNCmBgYA0KYGBge3IgQU5PVkEgQ29tcGxldGVseSBSYW5kb21pemVkIERlc2lnbiAyfQ0KbTENCmBgYA0KDQoNCmBgYHtyIHNjYXR0ZXJwbG90IGVuIGdncGxvdCBjb24gZGYyfQ0KZ2dwbG90KGRmMiwgYWVzKFNlbGxhbnRlLCBMZXNpw7NuLCBjb2xvcj1HcnVwbywgc2hhcGUgPSBHcnVwbykpICsNCiAgICAgICAgZ2VvbV9wb2ludChzaXplID0gMykgKyANCiAgICAgICAgeGxhYigiUHJvZnVuZGlkYWQgcGVuZXRyYWNpw7NuIHNlbGxhbnRlIGVuIHVtIikgKyB5bGFiKCJQcm9mdW5kaWRhZCBsZXNpw7NuIGVuIHVtIikgKw0KICAgICAgICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBwcm9mdW5kaWRhZCBkZSBsYSBsZXNpw7NuIHkgcGVuZXRyYWNpw7NuIGRlbCBzZWxsYW50ZSIpICsgDQogICAgICAgIHlsaW0oMCwgMTIwKSArIHhsaW0oMCwgNzUpICsgDQogICAgICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBmaWxsPU5BKSArDQogICAgICAgIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KYGBge3IgQU5PVkEgQ29tcGxldGVseSBSYW5kb21pemVkIERlc2lnbiBwbG90c30NCmxheW91dChtYXRyaXgoYygxLDIsMyw0KSwyLDIpKSANCnBsb3QobTEpIA0KDQpgYGANCg0KIyMgQ29ycmVsYXRpb24gYW5hbHlzaXMNCg0KIyMjIFByaW1lcm8sIHNvbiBsYXMgbGVzaW9uZXMgc2ltaWxhcmVzPw0KYGBge3IgcmVncmVzc2lvbiBsZXNpb259DQptMiA8LSBhb3YoZGYzJExlc2lvbiB+IGRmMyRHcnVwbykNCm0yDQpgYGANCmBgYHtyIG0yIHJlc3VtZW59DQpzdW1tYXJ5KG0yKQ0KYGBgDQoNCg0KDQojIyMgWSBwZW5ldHJhbiBsb3Mgc2VsbGFudGVzIGlndWFsZXM/DQpgYGB7ciByZWdyZXNpb24gc2VsbGFudGV9DQptMyA8LSBhb3YoZGYzJFNlbGxhbnRlIH4gZGYzJEdydXBvKQ0KbTMNCmBgYA0KYGBge3IgbTMgSX0NCnN1bW1hcnkobTMpDQoNCmBgYA0KDQoNCiMgREYzDQoNCiMjIENvbXBhcmFjacOzbiBlbnRyZSBncnVwb3MNCg0KDQpgYGB7ciBBbm92YSBtNH0NCm00IDwtIGxtKFBvcmNlbnRhamUuUGVuZXRyYWNpb25+R3J1cG8sIGRhdGEgPSBkZjMpDQpgYGANCmBgYHtyIG00IDF9DQptNA0KYGBgDQoNCmBgYHtyIHN1bW1hcnkgbTR9DQpzdW1tYXJ5KG00KQ0KYGBgDQoNCmBgYHtyIEFOT1ZBIG00IDJ9DQphbm92YShtNCkNCmBgYA0KDQpDaGVxdWVvIG5vcm1hbGlkYWQNCmBgYHtyIG5vcm1hbGlkYWQgZGYzfQ0Kc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtNCkpIA0KYGBgDQojIyMgTm9ybWFsaWRhZA0KYGBge3Igbm9ybWFsaWRhZCBkZjMgSUl9DQpkby5jYWxsKCJyYmluZCIsIHdpdGgoZGYzLCB0YXBwbHkoUG9yY2VudGFqZS5QZW5ldHJhY2lvbiwgR3J1cG8sIA0KICAgZnVuY3Rpb24oeCkgdW5saXN0KHNoYXBpcm8udGVzdCh4KVtjKCJzdGF0aXN0aWMiLCAicC52YWx1ZSIpXSkpKSkNCmBgYA0KDQojIyMgU2NhdHRlcnBsb3QNCmBgYHtyIHNjYXR0ZXJwbG90ICUgcGVuZXRyYWNpw7NuIGRmM30NCmdncGxvdChkZjMsIGFlcyhTZWxsYW50ZSwgTGVzaW9uLCBjb2xvcj1HcnVwbywgc2hhcGUgPSBHcnVwbykpICsNCiAgICAgICAgZ2VvbV9wb2ludChzaXplID0gMykgKyANCiAgICAgICAgeGxhYigiUHJvZnVuZGlkYWQgcGVuZXRyYWNpw7NuIHNlbGxhbnRlIGVuIHVtIikgKyB5bGFiKCJQcm9mdW5kaWRhZCBsZXNpw7NuIGVuIHVtIikgKw0KICAgICAgICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBwcm9mdW5kaWRhZCBkZSBsYSBsZXNpw7NuIHkgcGVuZXRyYWNpw7NuIGRlbCBzZWxsYW50ZSIpICsgDQogICAgICAgIHlsaW0oMCwgNjApICsgeGxpbSgwLCAzNSkgKyANCiAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIGZpbGw9TkEpICsNCiAgICAgICAgdGhlbWVfbWluaW1hbCgpDQpgYGANCiMjIyBUYWJsYQ0KYGBge3IgVGFibGEgZGVzY3JpcHRpdmEgZGYzfQ0KZGYzICU+JSANCiAgICAgICAgZ3JvdXBfYnkoR3J1cG8pICU+JSANCiAgICAgICAgc3VtbWFyaXNlKCBuID0gbigpLCANCiAgICAgICAgICAgICAgICAgICAiUHJvbWVkaW8gcHJvZnVuZGlkYWQgbGVzacOzbiBlbiB1bSIgPSBtZWFuKExlc2lvbiksICJEZXN2aWFjacOzbiBlc3TDoW5kYXIgbGVzacOzbiAodW0pIiA9IHNkKExlc2lvbiksIA0KICAgICAgICAgICAgICAgICAgICJQcm9tZWRpbyBwZW5ldHJhY2nDs24gc2VsbGFudGUgZW4gdW0iID0gbWVhbihTZWxsYW50ZSksICJEZXN2aWFjacOzbiBlc3TDoW5kYXIgc2VsbGFudGUgKHVtKSIgPSBzZChTZWxsYW50ZSksIA0KICAgICAgICAgICAgICAgICAgICJQcm9tZWRpbyAlIHBlbmV0cmFjacOzbiBzZWxsYW50ZSIgPSBtZWFuKFBvcmNlbnRhamUuUGVuZXRyYWNpb24pLCAiRGVzdmlhY2nDs24gZXN0w6FuZGFyICUgcGVuZXRyYWNpw7NuIHNlbGxhbnRlIiA9IHNkKFBvcmNlbnRhamUuUGVuZXRyYWNpb24pKSAlPiUgDQogICAgICAgIHVuZ3JvdXAoKQ0KYGBgDQoNCg0KYGBge3IgbTQgQU5PVkEgZmluYWx9DQptNCA8LSBsbShkZjMkUG9yY2VudGFqZS5QZW5ldHJhY2lvbn5kZjMkR3J1cG8pDQptNA0KYGBgDQpgYGB7ciBtNCAyfQ0Kc3VtbWFyeShtNCkNCmBgYA0KYGBge3IgbTQgcGxvdHN9DQpsYXlvdXQobWF0cml4KGMoMSwyLDMsNCksMiwyKSkgDQpwbG90KG0xKQ0KYGBgDQoNCg0KDQoNCg==