Packages

library("dplyr")
library("ggplot2")
library("tidyr")

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*1000
df2$Sellante <- df2$Sellante*1000
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*1000
df3$Sellante <- df3$Sellante*1000
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) %>% 
        filter(Tipo == "Lesion" & LD <600) %>% 
        summarise( n= n(), "Promedio lesión um" = mean(LD), DE = sd(LD)) %>% 
        ungroup()
df %>% 
        group_by(Grupo) %>% 
        filter(Tipo == "Sellante"& LD <600) %>% 
        summarise( n= n(), "Promedio Sellante 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
B-H3PO4             -9.873529 -19.9935623  0.2465035 0.0572316
NaOCL + H3PO4-H3PO4  0.470915  -9.6491179 10.5909479 0.9930604
NaOCL + H3PO4-B     10.344444   0.3700311 20.3188578 0.0405094
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 %>% 
        filter(Grupo == "NaOCL + H3PO4")
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

Correlation analysis

Primero, son las lesiones similares?

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(m2)
            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

Y penetran los sellantes iguales?

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)
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
  contrasts can be applied only to factors with 2 or more levels
m4

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

Coefficients:
           (Intercept)              df3$GrupoB  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$GrupoB                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
anova(m4)
Analysis of Variance Table

Response: df3$Porcentaje.Penetracion
          Df  Sum Sq Mean Sq F value Pr(>F)
df3$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")]))))
Error in shapiro.test(x) : sample size must be between 3 and 5000

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

m4

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

Coefficients:
           (Intercept)              df3$GrupoB  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$GrupoB                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

COmparación con estudio de Gómez

prop.test(convencional, total)

    2-sample test for equality of proportions with continuity correction

data:  convencional out of total
X-squared = 40.516, df = 1, p-value = 1.95e-10
alternative hypothesis: two.sided
95 percent confidence interval:
 0.3269742 0.5930258
sample estimates:
prop 1 prop 2 
  0.74   0.28 
prop.test(desprot, total)

    2-sample test for equality of proportions with continuity correction

data:  desprot out of total
X-squared = 73.458, df = 1, p-value < 2.2e-16
alternative hypothesis: two.sided
95 percent confidence interval:
 0.4755687 0.7044313
sample estimates:
prop 1 prop 2 
  0.94   0.35 
prop.test(gomez, total)

    2-sample test for equality of proportions with continuity correction

data:  gomez out of total
X-squared = 13.676, df = 1, p-value = 0.0002172
alternative hypothesis: two.sided
95 percent confidence interval:
 -0.30832065 -0.09367935
sample estimates:
prop 1 prop 2 
 0.741  0.942 
prop.test(nosotros, total)

    2-sample test for equality of proportions with continuity correction

data:  nosotros out of total
X-squared = 0.33936, df = 1, p-value = 0.5602
alternative hypothesis: two.sided
95 percent confidence interval:
 -0.18567627  0.08967627
sample estimates:
prop 1 prop 2 
 0.283  0.331 
LS0tDQp0aXRsZTogRWZlY3RvIGRlbCBwcmV0cmF0YW1pZW50byB5IHByb3RvY29sbyBkZSBhcGxpY2FjacOzbiBkZSBOYU9DbCBlbiBsYSBwZW5ldHJhY2nDs24NCiAgZGVsIHNlbGxhbnRlIGVuIGVzbWFsdGUgY29uIGxlc2lvbmVzIG5hdHVyYWxlcw0KYXV0aG9yOiAiVXJpYmUgU0UsIEhlcm5hbmRleiBNUCwgSmFyYSBJLCBHb21leiBTUyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQoNCiMgUGFja2FnZXMNCmBgYHtyIHBhY2thZ2VzfQ0KbGlicmFyeSgiZHBseXIiKQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpsaWJyYXJ5KCJ0aWR5ciIpDQpgYGANCg0KIyBEYXRhc2V0cw0KIyMgRGF0YXNldCAxDQpgYGB7ciBEYXRhc2V0IE1lZGljaW9uZXN9DQpkZiA8LSByZWFkLmNzdigibWVkaWNpb25lcy5jc3YiLCBoZWFkZXIgPSBULCBzZXAgPSAiLCIpDQpzdHIoZGYpDQpkZiRNdWVzdHJhLjIgPC0gYXMuZmFjdG9yKGRmJE11ZXN0cmEuMikNCmRmJE4gPC0gYXMuZmFjdG9yKGRmJE4pDQpsZXZlbHMoZGYkR3J1cG8pW2xldmVscyhkZiRHcnVwbyk9PSJBIl0gPC0gIkgzUE80Ig0KbGV2ZWxzKGRmJEdydXBvKVtsZXZlbHMoZGYkR3J1cG8pPT0iQiJdIDwtICJIM1BPNCArIE5hT0NMIg0KbGV2ZWxzKGRmJEdydXBvKVtsZXZlbHMoZGYkR3J1cG8pPT0iQyJdIDwtICJOYU9DTCArIEgzUE80Ig0KDQpkZiRMRCA8LSBkZiRMRCoxMDAwICMgY29udmllcnRvIGEgbWljcm9uZXMNCg0KYGBgDQoNCiMjIERhdGFzZXQgMg0KYGBge3IgZGYyIE1lZGljaW9uZXMgMn0NCmRmMiA8LSByZWFkLmNzdigibWVkaWNpb25lc18yLmNzdiIsIGhlYWRlciA9IFQsIHNlcCA9ICIsIiwgZW5jb2RpbmcgPSAiVVRGLTgiKQ0KZGYyJExlc2nDs24gPC0gZGYyJExlc2nDs24qMTAwMA0KZGYyJFNlbGxhbnRlIDwtIGRmMiRTZWxsYW50ZSoxMDAwDQoNCnRibF9kZihkZjIpDQpgYGANCg0KDQojIyBEYXRhc2V0IDMNCg0KYGBge3IgZGF0YXNldCAzIE1lZGljaW9uZXMgM30NCmRmMyA8LSByZWFkLmNzdigibWVkaWNpb25lc18zLmNzdiIsIGhlYWRlciA9IFQsIHNlcCA9ICI7IikNCnN0cihkZjMpDQpkZjMkTGVzaW9uIDwtIGRmMyRMZXNpb24qMTAwMA0KZGYzJFNlbGxhbnRlIDwtIGRmMyRTZWxsYW50ZSoxMDAwDQpkZjMkTXVlc3RyYS4yIDwtIGFzLmZhY3RvcihkZjMkTXVlc3RyYS4yKQ0KZGYzIDwtIG5hLm9taXQoZGYzKSAjb21pdG8gbG9zIE5BDQpkZjMgPC0gZGYzICU+JSAgDQogICAgICAgIG11dGF0ZShQb3JjZW50YWplLlBlbmV0cmFjaW9uID0gKFNlbGxhbnRlL0xlc2lvbikqMTAwKQ0KbGV2ZWxzKGRmMyRHcnVwbylbbGV2ZWxzKGRmMyRHcnVwbyk9PSJBIl0gPC0gIkgzUE80Ig0KbGV2ZWxzKGRmMyRHcnVwbylbbGV2ZWxzKGRmMyRHcnVwbyk9PSJCIl0gPC0gIkgzUE80ICsgTmFPQ0wiDQpsZXZlbHMoZGYzJEdydXBvKVtsZXZlbHMoZGYzJEdydXBvKT09IkMiXSA8LSAiTmFPQ0wgKyBIM1BPNCINCg0KZGYzIDwtIGRmMyAlPiUgDQogICAgICAgIGZpbHRlcihMZXNpb24gPDYwKQ0KDQoNCmBgYA0KDQojIERlc2NyaXB0aXZlIHN0YXRzDQpgYGB7ciBwb3IgZ3J1cG8gbGVzacOzbn0NCmRmICU+JSANCiAgICAgICAgZ3JvdXBfYnkoR3J1cG8pICU+JSANCiAgICAgICAgZmlsdGVyKFRpcG8gPT0gIkxlc2lvbiIgJiBMRCA8NjAwKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZSggbj0gbigpLCAiUHJvbWVkaW8gbGVzacOzbiB1bSIgPSBtZWFuKExEKSwgREUgPSBzZChMRCkpICU+JSANCiAgICAgICAgdW5ncm91cCgpDQoNCmBgYA0KDQpgYGB7ciBwb3IgZ3J1cG8gc2VsbGFudGV9DQpkZiAlPiUgDQogICAgICAgIGdyb3VwX2J5KEdydXBvKSAlPiUgDQogICAgICAgIGZpbHRlcihUaXBvID09ICJTZWxsYW50ZSImIExEIDw2MDApICU+JSANCiAgICAgICAgc3VtbWFyaXNlKCBuPSBuKCksICJQcm9tZWRpbyBTZWxsYW50ZSB1bSIgPSBtZWFuKExEKSwgREUgPSBzZChMRCkpICU+JSANCiAgICAgICAgdW5ncm91cCgpDQpgYGANCg0KYGBge3IgcG9yIHRpcG99DQoNCmRmICU+JSANCiAgICAgICAgZ3JvdXBfYnkoVGlwbykgJT4lIA0KICAgICAgICBzdW1tYXJpc2UoIG49IG4oKSwgIlByb21lZGlvIHVtIiA9IG1lYW4oTEQpLCBERSA9IHNkKExEKSkgJT4lIA0KICAgICAgICB1bmdyb3VwKCkNCg0KYGBgDQojIyBHcsOhZmljb3MNCg0KIyMjIFNlbGxhbnRlDQpgYGB7ciBHcmFwaCBTZWxsYW50ZX0NCmRmICU+JSANCiAgICAgICAgZmlsdGVyKFRpcG8gPT0gIlNlbGxhbnRlIikgJT4lIA0KICAgICAgICBnZ3Bsb3QoYWVzKHg9R3J1cG8sIHk9TEQpKSArIGdlb21fYm94cGxvdCgpICsgDQogICAgICAgIGdndGl0bGUoIlByb2Z1bmRpZGFkIHBlbmV0cmFjacOzbiBzZWxsYW50ZSBwb3IgZ3J1cG8iKSArDQogICAgICAgIGxhYnMoeD0iR3J1cG8iLCB5PSAiUHJvZnVuZGlkYWQgIiAqIG11IH4gIm0iICkgKyANCiAgICAgICAgeWxpbSgwLDM1MCkgKyANCiAgICAgICAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIyBMZXNpb24NCmBgYHtyIEdyYXBoIExlc2lvbn0NCmRmICU+JSANCiAgICAgICAgZmlsdGVyKFRpcG8gPT0gIkxlc2lvbiIpICU+JSANCiAgICAgICAgZ2dwbG90KGFlcyh4PUdydXBvLCB5PUxEKSkgKyBnZW9tX2JveHBsb3QoKSArDQogICAgICAgIGdndGl0bGUoIlByb2Z1bmRpZGFkIGxlc2nDs24gZ3J1cG8iKSArDQogICAgICAgIGxhYnMoeD0iR3J1cG8iLCB5PSAiUHJvZnVuZGlkYWQgIiAqIG11IH4gIm0iICkgKyANCiAgICAgICAgeWxpbSgwLDM1MCkgKyANCiAgICAgICAgdGhlbWVfbWluaW1hbCgpDQpgYGANCiMjIyBDb21wYXJhY2nDs24gcHJvZnVuZGlkYWQgbGVzacOzbiB5IHBlbmV0cmFjacOzbiBkZWwgc2VsbGFudGUNCmBgYHtyIENvbXBhcmFjacOzbiBlbnRyZSBncnVwb3N9DQpnZ3Bsb3QoYWVzKHkgPSBMRCwgeCA9IEdydXBvLCBmaWxsID0gVGlwbyksIGRhdGEgPSBkZikgKw0KICAgICAgICBnZW9tX2JveHBsb3QoKSArDQogICAgICAgIGdndGl0bGUoIlByb2Z1bmRpZGFkIGRlIGxlc2lvbmVzIHkgcGVuZXRyYWNpb24gZGUgc2VsbGFudGUgcG9yIGdydXBvIikgKw0KICAgICAgICBsYWJzKHg9IkdydXBvIix5PSAiUHJvZnVuZGlkYWQgZW4gKCIgKiBtdSB+ICJtKSIgKSArIA0KICAgICAgICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7ciBUYWJsYSBjb24gZGYzfQ0KZGYzICU+JSANCiAgICAgICAgZ3JvdXBfYnkoR3J1cG8pICU+JSANCiAgICAgICAgc3VtbWFyaXNlKA0KICAgICAgICAgICAgICAgIG4gPSBuKCksIA0KICAgICAgICAgICAgICAgIFByb21lZGlvLkxlc2lvbj1tZWFuKExlc2lvbiksIFNELkxlc2lvbj1zZChMZXNpb24pLCANCiAgICAgICAgICAgICAgICBQcm9tZWRpby5TZWxsYW50ZT1tZWFuKFNlbGxhbnRlKSwgU0QuU2VsbGFudGU9c2QoU2VsbGFudGUpLCANCiAgICAgICAgICAgICAgICBQcm9tZWRpby5QZW5ldHJhY2lvbj1tZWFuKFBvcmNlbnRhamUuUGVuZXRyYWNpb24pLCBTRC5QZW5ldHJhY2lvbj1zZChQb3JjZW50YWplLlBlbmV0cmFjaW9uKQ0KICAgICAgICApDQpgYGANCg0KYGBge3IgQW5vdmEgcGFyYSBsZXNpw7NufQ0KYW5vdmEubGVzaW9uIDwtIGFvdihkZjMkTGVzaW9ufmRmMyRHcnVwbykNCmFub3ZhLmxlc2lvbg0KYGBgDQpgYGB7ciBBTm92YSBwYXJhIGxlc2lvbiByZXN1bWVufQ0Kc3VtbWFyeShhbm92YS5sZXNpb24pDQpgYGANCg0KYGBge3IgQW5vdmEgcG9yIGxlc2lvbiBwb3N0aG9jfQ0KDQpUdWtleUhTRChhbm92YS5sZXNpb24sIGNvbmYubGV2ZWwgPSAwLjk1KQ0KYGBgDQoNCmBgYHtyIEFOb3ZhIHBhcmEgc2VsbGFudGV9DQphbm92YS5zZWxsYW50ZQ0KYGBgDQoNCmBgYHtyIEFub3ZhIHBhcmEgc2VsbGFudGVzIHJlc3VtZW59DQpzdW1tYXJ5KGFub3ZhLnNlbGxhbnRlKQ0KYGBgDQoNCg0KIyMjIFBvcmNlbnRhamUgcGVuZXRyYWNpw7NuDQpgYGB7ciBHcmFwaCBwb3JjZW50YWplIHBlbmV0cmFjaW9ufQ0KZ2dwbG90KGFlcyh5ID0gUG9yY2VudGFqZS5QZW5ldHJhY2lvbiwgeCA9IEdydXBvKSwgZGF0YSA9IGRmMikgKw0KICAgICAgICBnZW9tX2JveHBsb3QoKSArDQogICAgICAgIGdndGl0bGUoIlBvcmNlbnRhamUgZGUgcGVuZXRyYWNpw7NuIGRlbCBzZWxsYW50ZSBlbiBsZXNpw7NuIHBvciBncnVwbyIpICsNCiAgICAgICAgbGFicyh4PSJHcnVwbyIseT0gIlBvcmNlbnRhamUgZGUgcGVuZXRyYWNpw7NuIiApICsgDQogICAgICAgIHlsaW0oMCwxMDApICsNCiAgICAgICAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpgYGB7ciBHcmFwaCAlIHBlbmV0cmFjaW9uIGRmM30NCmdncGxvdChhZXMoeSA9IFBvcmNlbnRhamUuUGVuZXRyYWNpb24sIHggPSBHcnVwbyksIGRhdGEgPSBkZjMpICsNCiAgICAgICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgICAgICBnZ3RpdGxlKCJQb3JjZW50YWplIGRlIHBlbmV0cmFjacOzbiBkZWwgc2VsbGFudGUgZW4gbGVzacOzbiBwb3IgZ3J1cG8iKSArDQogICAgICAgIGxhYnMoeD0iR3J1cG8iLHk9ICJQb3JjZW50YWplIGRlIHBlbmV0cmFjacOzbiIgKSArIA0KICAgICAgICB5bGltKDAsMTAwKSArDQogICAgICAgIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KIyBBbsOhbGlzaXMgaW5mZXJlbmNpYWxlcw0KYGBge3IgVGFibGEgcGFyYSBhbmFsaXNpcyBpbmZlcmVuY2lhbH0NCmRmMiAlPiUgDQogICAgICAgIGdyb3VwX2J5KEdydXBvKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZSggDQogICAgICAgICAgICAgICAgUHJvbWVkaW8uUG9yY2VudGFqZS5QZW5ldHJhY2lvbiA9IG1lYW4oUG9yY2VudGFqZS5QZW5ldHJhY2lvbiksIA0KICAgICAgICAgICAgICAgU0QuUGVuZXRyYWNpb24gPSBzZChQb3JjZW50YWplLlBlbmV0cmFjaW9uKSkgDQogICAgICAgIHVuZ3JvdXAoKQ0KYGBgDQoNCg0KIyMgc3VwdWVzdG9zDQpgYGB7ciBncnVwb3N9DQphY2lkbyA8LSBkZjIgJT4lIA0KICAgICAgICBmaWx0ZXIoR3J1cG8gPT0gIkgzUE80IikNCmFjaWRvLmRlc3Byb3QgPC0gIGRmMiAlPiUgDQogICAgICAgIGZpbHRlcihHcnVwbyA9PSAiSDNQTzQgKyBOYU9DTCIpDQpkZXNwcm90LmFjaWRvIDwtIGRmMiAlPiUgDQogICAgICAgIGZpbHRlcihHcnVwbyA9PSAiTmFPQ0wgKyBIM1BPNCIpDQpgYGANCg0KYGBge3Igbm9ybWFsaWRhZCBBfQ0Kd2lsY294LnRlc3QoYWNpZG8kUG9yY2VudGFqZS5QZW5ldHJhY2lvbikNCmBgYA0KDQpgYGB7ciBub3JtYWxpZGFkIEJ9DQp3aWxjb3gudGVzdChhY2lkby5kZXNwcm90JFBvcmNlbnRhamUuUGVuZXRyYWNpb24pDQpgYGANCg0KYGBge3Igbm9ybWFsaWRhZCBDfQ0Kd2lsY294LnRlc3QoZGVzcHJvdC5hY2lkbyRQb3JjZW50YWplLlBlbmV0cmFjaW9uKQ0KYGBgDQoNCg0KIyMgQU5PVkENCmBgYHtyIEFOT1ZBIENvbXBsZXRlbHkgUmFuZG9taXplZCBEZXNpZ259DQptMSA8LSBhb3YoZGYyJFBvcmNlbnRhamUuUGVuZXRyYWNpb25+ZGYyJEdydXBvKQ0Kc3VtbWFyeShtMSkNCmBgYA0KYGBge3IgQU5PVkEgQ29tcGxldGVseSBSYW5kb21pemVkIERlc2lnbiAyfQ0KbTENCmBgYA0KDQoNCmBgYHtyIHNjYXR0ZXJwbG90IGVuIGdncGxvdCBjb24gZGYyfQ0KZ2dwbG90KGRmMiwgYWVzKFNlbGxhbnRlLCBMZXNpw7NuLCBjb2xvcj1HcnVwbywgc2hhcGUgPSBHcnVwbykpICsNCiAgICAgICAgZ2VvbV9wb2ludChzaXplID0gMykgKyANCiAgICAgICAgeGxhYigiUHJvZnVuZGlkYWQgcGVuZXRyYWNpw7NuIHNlbGxhbnRlIGVuIHVtIikgKyB5bGFiKCJQcm9mdW5kaWRhZCBsZXNpw7NuIGVuIHVtIikgKw0KICAgICAgICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBwcm9mdW5kaWRhZCBkZSBsYSBsZXNpw7NuIHkgcGVuZXRyYWNpw7NuIGRlbCBzZWxsYW50ZSIpICsgDQogICAgICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBmaWxsPU5BKSArDQogICAgICAgIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KYGBge3IgQU5PVkEgQ29tcGxldGVseSBSYW5kb21pemVkIERlc2lnbiBwbG90c30NCmxheW91dChtYXRyaXgoYygxLDIsMyw0KSwyLDIpKSANCnBsb3QobTEpIA0KDQpgYGANCg0KIyMgQ29ycmVsYXRpb24gYW5hbHlzaXMNCg0KIyMjIFByaW1lcm8sIHNvbiBsYXMgbGVzaW9uZXMgc2ltaWxhcmVzPw0KYGBge3IgcmVncmVzc2lvbiBsZXNpb259DQptMiA8LSBhb3YoZGYzJExlc2lvbiB+IGRmMyRHcnVwbykNCm0yDQpgYGANCmBgYHtyIG0yIHJlc3VtZW59DQpzdW1tYXJ5KG0yKQ0KYGBgDQoNCg0KDQojIyMgWSBwZW5ldHJhbiBsb3Mgc2VsbGFudGVzIGlndWFsZXM/DQpgYGB7ciByZWdyZXNpb24gc2VsbGFudGV9DQptMyA8LSBhb3YoZGYzJFNlbGxhbnRlIH4gZGYzJEdydXBvKQ0KbTMNCmBgYA0KYGBge3IgbTMgSX0NCnN1bW1hcnkobTMpDQoNCmBgYA0KDQoNCiMgREYzDQoNCiMjIENvbXBhcmFjacOzbiBlbnRyZSBncnVwb3MNCg0KDQpgYGB7ciBBbm92YSBtNH0NCm00IDwtIGxtKFBvcmNlbnRhamUuUGVuZXRyYWNpb25+R3J1cG8sIGRhdGEgPSBkZjMpDQpgYGANCmBgYHtyIG00IDF9DQptNA0KYGBgDQoNCmBgYHtyIHN1bW1hcnkgbTR9DQpzdW1tYXJ5KG00KQ0KYGBgDQoNCmBgYHtyIEFOT1ZBIG00IDJ9DQphbm92YShtNCkNCmBgYA0KDQpDaGVxdWVvIG5vcm1hbGlkYWQNCmBgYHtyIG5vcm1hbGlkYWQgZGYzfQ0Kc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtNCkpIA0KYGBgDQojIyMgTm9ybWFsaWRhZA0KYGBge3Igbm9ybWFsaWRhZCBkZjMgSUl9DQpkby5jYWxsKCJyYmluZCIsIHdpdGgoZGYzLCB0YXBwbHkoUG9yY2VudGFqZS5QZW5ldHJhY2lvbiwgR3J1cG8sIA0KICAgZnVuY3Rpb24oeCkgdW5saXN0KHNoYXBpcm8udGVzdCh4KVtjKCJzdGF0aXN0aWMiLCAicC52YWx1ZSIpXSkpKSkNCmBgYA0KDQojIyMgU2NhdHRlcnBsb3QNCmBgYHtyIHNjYXR0ZXJwbG90ICUgcGVuZXRyYWNpw7NuIGRmM30NCmdncGxvdChkZjMsIGFlcyhTZWxsYW50ZSwgTGVzaW9uLCBjb2xvcj1HcnVwbywgc2hhcGUgPSBHcnVwbykpICsNCiAgICAgICAgZ2VvbV9wb2ludChzaXplID0gMykgKyANCiAgICAgICAgeGxhYigiUHJvZnVuZGlkYWQgcGVuZXRyYWNpw7NuIHNlbGxhbnRlIGVuIHVtIikgKyB5bGFiKCJQcm9mdW5kaWRhZCBsZXNpw7NuIGVuIHVtIikgKw0KICAgICAgICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBwcm9mdW5kaWRhZCBkZSBsYSBsZXNpw7NuIHkgcGVuZXRyYWNpw7NuIGRlbCBzZWxsYW50ZSIpICsgDQogICAgICAgIHlsaW0oMCwgNjApICsgeGxpbSgwLCAzNSkgKyANCiAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIGZpbGw9TkEpICsNCiAgICAgICAgdGhlbWVfbWluaW1hbCgpDQpgYGANCiMjIyBUYWJsYQ0KYGBge3IgVGFibGEgZGVzY3JpcHRpdmEgZGYzfQ0KZGYzICU+JSANCiAgICAgICAgZ3JvdXBfYnkoR3J1cG8pICU+JSANCiAgICAgICAgc3VtbWFyaXNlKCBuID0gbigpLCANCiAgICAgICAgICAgICAgICAgICAiUHJvbWVkaW8gcHJvZnVuZGlkYWQgbGVzacOzbiBlbiB1bSIgPSBtZWFuKExlc2lvbiksICJEZXN2aWFjacOzbiBlc3TDoW5kYXIgbGVzacOzbiAodW0pIiA9IHNkKExlc2lvbiksIA0KICAgICAgICAgICAgICAgICAgICJQcm9tZWRpbyBwZW5ldHJhY2nDs24gc2VsbGFudGUgZW4gdW0iID0gbWVhbihTZWxsYW50ZSksICJEZXN2aWFjacOzbiBlc3TDoW5kYXIgc2VsbGFudGUgKHVtKSIgPSBzZChTZWxsYW50ZSksIA0KICAgICAgICAgICAgICAgICAgICJQcm9tZWRpbyAlIHBlbmV0cmFjacOzbiBzZWxsYW50ZSIgPSBtZWFuKFBvcmNlbnRhamUuUGVuZXRyYWNpb24pLCAiRGVzdmlhY2nDs24gZXN0w6FuZGFyICUgcGVuZXRyYWNpw7NuIHNlbGxhbnRlIiA9IHNkKFBvcmNlbnRhamUuUGVuZXRyYWNpb24pKSAlPiUgDQogICAgICAgIHVuZ3JvdXAoKQ0KYGBgDQoNCg0KYGBge3IgbTQgQU5PVkEgZmluYWx9DQptNCA8LSBsbShkZjMkUG9yY2VudGFqZS5QZW5ldHJhY2lvbn5kZjMkR3J1cG8pDQptNA0KYGBgDQpgYGB7ciBtNCAyfQ0Kc3VtbWFyeShtNCkNCmBgYA0KYGBge3IgbTQgcGxvdHN9DQpsYXlvdXQobWF0cml4KGMoMSwyLDMsNCksMiwyKSkgDQpwbG90KG0xKQ0KYGBgDQojIyBDT21wYXJhY2nDs24gY29uIGVzdHVkaW8gZGUgR8OzbWV6DQpgYGB7ciBEYXRvcyBnb21leiB2cyBhaG9yYX0NCmNvbnZlbmNpb25hbCA8LSBjKDc0LCAyOCkNCmRlc3Byb3QgPC0gYyg5NCwgMzUpDQp0b3RhbCA8LSBjKDEwMCwgMTAwKQ0KYGBgDQoNCmBgYHtyIGNvbnZlbmNpb25hbH0NCnByb3AudGVzdChjb252ZW5jaW9uYWwsIHRvdGFsKQ0KYGBgDQoNCmBgYHtyIGRlcHJvdH0NCnByb3AudGVzdChkZXNwcm90LCB0b3RhbCkNCmBgYA0KDQpgYGB7ciBvdHJvIDF9DQpnb21leiA8LSBjKDc0LjEsIDk0LjIpDQpwcm9wLnRlc3QoZ29tZXosIHRvdGFsKQ0KYGBgDQoNCmBgYHtyIG5vc290cm9zfQ0Kbm9zb3Ryb3MgPC0gYygyOC4zLCAzMy4xKQ0KcHJvcC50ZXN0KG5vc290cm9zLCB0b3RhbCkNCmBgYA0KDQo=