1. RStudio Scripts Cp y Fallas

Considerando el documento RStudio_Scripts_Cp y Fallas (que se encuentra en la plataforma Classroom del curso en la sección Lenguaje R y RStudio) que contiene Scripts y ejemplos de manejo de datos, replicar los siguientes Scripts:

a. Análisis en R

Análisis estadístico básico en R, interpretando el diagrama boxplot (¿Qué representa cada uno de sus componentes?).

E1
summary(E1)
       X       
 Min.   :2045  
 1st Qu.:2684  
 Median :3456  
 Mean   :3615  
 3rd Qu.:4454  
 Max.   :5890  
boxplot(E1, main="Boxplot de E1", ylab="Valor",
        col="lightblue")

Caja (IQR): del primer al tercer cuartil.

Línea central: mediana.

Bigotes: llegan hasta 1.5·IQR; puntos fuera son atípicos.

b. Capacidad de proceso

library(qcc)

# Datos de diámetros (reemplaza con tus datos de clase)
CP <- c(31.6, 33.4, 35.0, 32.2, 33.8,
       38.4, 31.6, 36.8, 35.0, 34.0,
       29.8, 34.0, 33.0, 34.8, 35.6,
       30.8, 33.0, 31.6, 33.8, 33.8)

# Índice para cada dato
Muestra <- 1:length(CP)

# Histograma
hist(CP, main="Histograma de Diámetros", xlab="Diámetro (mm)", col="lightgreen")


D_groups <- qcc.groups(CP,Muestra)

# Grupos para qcc (aunque no hay grupos reales, usamos los datos tal cual)
q <- qcc(D_groups, type = "xbar", nsigmas = 3, plot = FALSE)

# Capacidad de proceso
process.capability(q, spec.limits = c(30, 38))

Process Capability Analysis

Call:
process.capability(object = q, spec.limits = c(30, 38))

Number of obs = 20           Target = 34
       Center = 33.6            LSL = 30
       StdDev = 2.303           USL = 38

Capability indices:

       Value    2.5%   97.5%
Cp    0.5791  0.3965  0.7614
Cp_l  0.5212  0.3358  0.7066
Cp_u  0.6370  0.4274  0.8465
Cp_k  0.5212  0.3003  0.7421
Cpm   0.5705  0.3926  0.7482

Exp<LSL 5.9%     Obs<LSL 5%
Exp>USL 2.8%     Obs>USL 5%

El proceso tiene una baja capacidad para cumplir consistentemente con las especificaciones establecidas. Esto sugiere que una proporción importante de piezas puede estar fuera de tolerancia, especialmente por debajo del límite inferior.

El índice de capacidad Cp fue de 0.5791, lo que indica que el proceso no es suficientemente capaz, ya que este valor es menor a 1. Además, los índices Cp_l y Cp_u, de 0.5212 y 0.6370 respectivamente, evidencian que el proceso está descentrado respecto a las especificaciones, con una mayor proporción de piezas que tienden a caer fuera del límite inferior (5% de observaciones reales bajo el LSL y 2.8% por encima del USL). Estos resultados indican que el proceso necesita ajustes para mejorar su estabilidad y precisión, que se puede lograr reduciendo la variabilidad.

c. Análisis de fallas en máquinas

Análisis de fallas en máquinas, analizando la condición del equipo considerado.

Horas <- c(2045, 3456, 4567, 3421, 2678, 3789, 4321, 5890, 2367, 4398,
           2690, 4532, 3190, 2367, 4509)

# 3. Análisis estadístico
summary(Horas)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   2045    2684    3456    3615    4454    5890 
hist(Horas, main="Histograma de fallas (horas)", xlab="Horas", col="orange", border="white")


# 4. Ajuste a distribución de Weibull
ajuste_weibull <- fitdist(Horas, "weibull")
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
Warning :Se han producido NaNs
plot(ajuste_weibull)


# 5. Resumen del ajuste
summary(ajuste_weibull)
Fitting of the distribution ' weibull ' by maximum likelihood 
Parameters : 
Loglikelihood:  -125.5636   AIC:  255.1272   BIC:  256.5433 
Correlation matrix:
          shape     scale
shape 1.0000000 0.3266744
scale 0.3266744 1.0000000

El valor de β indica que el equipo se encuentra en la fase de desgaste, lo que significa que la probabilidad de falla aumenta a medida que transcurre el tiempo de operación. Con esta información, en un entorno real se podría plantear la implementación de planes de mantenimiento preventivo enfocadas al sostenimiento del equipo.

Además, el valor de \(\alpha\)(escala) proporciona una referencia sobre el tiempo promedio en el que se espera la ocurrencia de fallas, lo que permite programar mantenimientos alrededor de las 3000 a 3500 horas, considerando un margen de seguridad para minimizar riesgos de paros no programados

d. Aplicación

Aplicar el script de R con los datos tomados en clase (20 datos) sobre la fabricación del componente mecánico cuyo diámetro fue especificado en \(16,90 \pm 0,08\) mm, Tolerancia \([16,82 – 16,98]\). Analizar la información de los resultados generados y plantear una estrategia de mejoramiento de proceso para lograr la especificación.

# 1. Datos de diámetros
Diametro <- c(16.88, 16.81, 16.92, 16.92, 16.81, 16.93, 16.96, 16.96,
              16.94, 16.95, 16.95, 16.96, 16.92, 16.97, 16.94, 16.94,
              16.93, 16.93, 16.82, 16.93)

# 2. Análisis estadístico
summary(Diametro)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  16.81   16.92   16.93   16.92   16.95   16.97 
boxplot(Diametro, main="Boxplot de Diámetros", col="lightblue", ylab="Diámetro (mm)")


# 3. Histograma
hist(Diametro, main="Histograma de Diámetros", xlab="Diámetro (mm)", col="lightgreen", border="white")


# 4. Capacidad de proceso (usando qcc)
if (!require(qcc)) install.packages("qcc"); library(qcc)

# Control de calidad para valores individuales
q <- qcc(Diametro, type = "xbar.one", nsigmas = 3, labels = 1:20,
         xlab = "Muestra", ylab = "Diámetro (mm)", title = "Carta X-bar de valores individuales")


# Capacidad de proceso (tolerancia 16.82 a 16.98)
process.capability(q, spec.limits = c(16.82, 16.98))

Process Capability Analysis

Call:
process.capability(object = q, spec.limits = c(16.82, 16.98))

Number of obs = 20           Target = 16.9
       Center = 16.92           LSL = 16.82
       StdDev = 0.03873         USL = 16.98

Capability indices:

       Value    2.5%   97.5%
Cp    0.6886  0.4714  0.9054
Cp_l  0.8478  0.5905  1.1051
Cp_u  0.5293  0.3423  0.7164
Cp_k  0.5293  0.3065  0.7522
Cpm   0.6213  0.4137  0.8288

Exp<LSL 0.55%    Obs<LSL 10%
Exp>USL 5.6%     Obs>USL 0%

El resumen estadístico muestra una media cercana a 16,92 mm, lo cual es positivo, pero también resalta la presencia de valores mínimos en 16,81 mm, justo en el límite inferior, y máximos en 16,97 mm, muy cercanos al límite superior. De manera general, se aprecia una buena precisión en el proceso.

Después de realizar los análisis anteriores, se concluye que la capacidad de proceso en algunos casos es baja y el proceso de fabricación puede presentar desviaciones respecto a las especificaciones. Para mejorar, es necesario implementar acciones como la reducción de la variabilidad del proceso, optimización de los parámetros de máquina, ajuste de herramientas, establecimiento de un programa de mantenimiento preventivo, y capacitación del personal en temas de control de calidad

2. Análisis de fallas

A continuación se muestran los datos de tiempo entre fallas TBF, en horas, para un equipo de fabricación.

tbf_horas <- TBF$`TBF (horas)`
cat("TBF (h): ",tbf_horas, "\n")
TBF (h):  14 11 11 17 14 19 16 15 13 15 15 15 13 14 14 15 17 14 14 15 

A partir de estos datos encontrar la función de distribución de Weibull que modela la probabilidad de falla \(F(t)\) y la confiabilidad \(R(t)\).

tbf_fit_weibull <- invisible(rriskFitdist.cont(tbf_horas, "weibull"))
tbf_beta <- invisible(tbf_fit_weibull$estimate["shape"])
tbf_alfa <- invisible(tbf_fit_weibull$estimate["scale"])
tbf_fit_weibull <- invisible(rriskFitdist.cont(tbf_horas, "weibull"))
G2;H2;Warningh in rriskFitdist.cont(tbf_horas, "weibull") :
  Kolmogorov-Smirnov and Anderson-Darling statistics may not be correct with tiesg
tbf_beta <- invisible(tbf_fit_weibull$estimate["shape"])
tbf_alfa <- invisible(tbf_fit_weibull$estimate["scale"])
cat("Escala (alfa):", scale_est, "\nForma (beta):", shape_est, "\n")
Escala (alfa): 15.01125 
Forma (beta): 6.589119 
tbf_dweibull <- invisible(dweibull(tbf_horas, tbf_beta, tbf_alfa))
plot(tbf_horas, tbf_dweibull, col="blue")

Función de densidad de probabilidad

tbf_dens_weibull <- function(x, tbf_beta, tbf_alfa) {
  (tbf_beta / tbf_alfa) * (x / tbf_alfa)^(tbf_beta - 1) * exp(-(x / tbf_alfa)^tbf_beta)
}

A partir de la definición de la función, se procede a graficar para apreciar su comportamiento.

curve(tbf_dens_weibull(x, tbf_beta, tbf_alfa), xlim=c(min(tbf_horas)-0.5,max(tbf_horas)+0.5),xlab="Tiempo entre fallas TBF", ylab="Densidad de Probabilidad", col="red")

¿Cuál será el valor de probabilidad de falla y confiabilidad al cabo de 15 horas de operación? ¿Es adecuado el valor de confiabilidad para la operación del equipo?


Probabilidad de falla

tbf_pweibull <- invisible(pweibull(tbf_horas, tbf_beta, tbf_alfa))

plot(tbf_horas, tbf_pweibull, xlab="Tiempo entre fallas TBF",
     ylab="Probabilidad de falla", col="blue")

Se tiene la distribución acumulada de Weibull que dicta la probabilidad de falla:

tbf_acum_weibull <- function(x,tbf_beta,tbf_alfa){
  1 - exp(-(x/tbf_alfa)^tbf_beta)
}

tbf_acum_weibull
function(x,tbf_beta,tbf_alfa){
  1 - exp(-(x/tbf_alfa)^tbf_beta)
}
curve(tbf_acum_weibull(x,tbf_beta,tbf_alfa), xlim=c(min(tbf_horas)-0.5,max(tbf_horas)+0.5))

Dada la curva, si se desea obtener el valor de la función de probabilidad de falla para 15 horas:

prob_falla <- pweibull(15, shape = shape_est, scale = scale_est)

cat("Probabilidad de falla: ",prob_falla*100, "%")
Probabilidad de falla:  63.03032 %

Confiabilidad

Dada la probabilidad de falla para 15 horas de operación, la confiabilidad se puede definir como:

confiabilidad <- 1 - prob_falla
cat("Confiabilidad: ",confiabilidad*100, "%")
Confiabilidad:  36.96968 %

Un valor significativamente bajo de confiabilidad como el obtenido indica que el equipo no tiene una capacidad adecuada para desempeñar sus funciones de manera satisfactoria, en la medida que es más propenso a fallar que lo contrario.

Función de tasa de fallas

Expresar matemáticamente la función de tasa de fallas \(\lambda(t)\) y a partir de ésta determinar el valor de la tasa de fallas para 15 horas de operación.`

Recordando que \(\beta =6.59\) y \(\alpha=15.01\), la función lambda de tasa de fallas se presenta entonces como:

\(\lambda(t)=0.53*\left(\frac{t}{15.01}\right)^{5.59}\)


tbf_lambda <- function(x,tbf_alfa,tbf_beta){
  (tbf_beta/tbf_alfa)*(x/tbf_alfa)^(tbf_beta-1)
}

cat("Tasa de fallas para 15 horas", tbf_lambda(15,tbf_alfa,tbf_beta)," fallas/hora")
Tasa de fallas para 15 horas 0.4469101  fallas/hora

Curva de bañera

¿En qué zona de la curva de la bañera se encuentra el equipo? El factor de forma es mayor a 1, por lo que se puede entender que el equipo se encuentra en etapa de envejecimiento. En ese sentido, el equipo se enfrenta a falla por desgaste.

Conclusión

¿Bajo esta condición se consideraría un reemplazo en el corto plazo del equipo?

Entendiendo que

3. Tiempo de reparación (TT)

A continuación, se muestran los datos de los tiempos para reparación o mantenimiento TTR (TTM por algunos autores) para el mismo equipo de la tabla anterior.

ttr_horas <- TTR$`TTR (horas)`
cat("TTR (h): ", ttr_horas,"\n")
TTR (h):  1.7 1.8 4.4 3.3 4.3 3 2.1 2 2.1 1.9 2 1.9 2 2.1 2.1 2.1 1.8 2.2 2.2 2 

Disponibilidad

Determinar la disponibilidad \(A\) (Availability) considerando que el sistema es reparable. ¿Es este valor adecuado para la operación del equipo en la línea de producción?

Se define la disponibilidad, en un sistema reparable, como: \(A=\frac{MTBF}{MTBF+MTTM}\). A continuación se definen estas variables para los conjuntos de datos

MTBF <- mean(tbf_horas)
MTTM <- mean(ttr_horas)

cat("MTBF = ",MTBF," h\nMTTM = ",MTTM," h")
MTBF =  14.55  h
MTTM =  2.35  h

En consecuencia, la disponibilidad A es:

A <- MTBF/(MTBF+MTTM)
cat("A = ",A*100,"%")
A =  86.09467 %

Mantenibilidad

Expresar matemáticamente la función de mantenibilidad para el equipo y determinarla para un TTR de 3 horas.

Asumiendo mantenibilidad con TTM exponencial, se aplicará la ecuación correspondiente:

\(M(t)=1-e^{-\mu t}\)

De donde:

mu <- 1/MTTM
cat("\u03BC = ",mu)
μ =  0.4255319

En consecuencia, la función matemática será:

\(M(t)=1-e^{-0.425t}\)

Y la mantenibilidad M para 3 horas de operación será:

mantenibilidad <- function(x){1-exp(-mu*x)}
cat("M(13) = ", mantenibilidad(3))
M(13) =  0.7210146
curve(mantenibilidad(x), xlim=c(min(ttr_horas)-0.5,max(ttr_horas)+0.5))

Conclusiones

¿Qué se puede concluir sobre la mantenibilidad del equipo?

En cuanto a la mantenibilidad del equipo a partir de los datos planteados se puede apreciar un comportamiento favorable que, aunado a la relativamente alta disponibilidad que dispone, permite un proceso óptimo en tiempos de reparación.

LS0tDQp0aXRsZTogIlRhbGxlciAyOiBSU3R1ZGlvIHkgYW7DoWxpc2lzIGRlIGZhbGxhIg0Kc3VidGl0bGU6ICJDaHJpc3RpYW4gVmFyZ2FzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyAxLiBSU3R1ZGlvIFNjcmlwdHMgQ3AgeSBGYWxsYXMNCg0KQ29uc2lkZXJhbmRvIGVsIGRvY3VtZW50byBSU3R1ZGlvXF9TY3JpcHRzXF9DcCB5IEZhbGxhcyAocXVlIHNlIGVuY3VlbnRyYSBlbiBsYSBwbGF0YWZvcm1hIENsYXNzcm9vbSBkZWwgY3Vyc28gZW4gbGEgc2VjY2nDs24gTGVuZ3VhamUgUiB5IFJTdHVkaW8pIHF1ZSBjb250aWVuZSBTY3JpcHRzIHkgZWplbXBsb3MgZGUgbWFuZWpvIGRlIGRhdG9zLCByZXBsaWNhciBsb3Mgc2lndWllbnRlcyBTY3JpcHRzOg0KDQojIyMgYS4gQW7DoWxpc2lzIGVuIFINCg0KQW7DoWxpc2lzIGVzdGFkw61zdGljbyBiw6FzaWNvIGVuIFIsIGludGVycHJldGFuZG8gZWwgZGlhZ3JhbWEgYm94cGxvdCAowr9RdcOpIHJlcHJlc2VudGEgY2FkYSB1bm8gZGUgc3VzIGNvbXBvbmVudGVzPykuDQoNCmBgYHtyfQ0KRTENCnN1bW1hcnkoRTEpDQpib3hwbG90KEUxLCBtYWluPSJCb3hwbG90IGRlIEUxIiwgeWxhYj0iVmFsb3IiLA0KICAgICAgICBjb2w9ImxpZ2h0Ymx1ZSIpDQpgYGANCkNhamEgKElRUik6IGRlbCBwcmltZXIgYWwgdGVyY2VyIGN1YXJ0aWwuDQoNCkzDrW5lYSBjZW50cmFsOiBtZWRpYW5hLg0KDQpCaWdvdGVzOiBsbGVnYW4gaGFzdGEgMS41wrdJUVI7IHB1bnRvcyBmdWVyYSBzb24gYXTDrXBpY29zLg0KDQoNCiMjIyBiLiBDYXBhY2lkYWQgZGUgcHJvY2Vzbw0KDQpgYGB7cn0NCmxpYnJhcnkocWNjKQ0KDQojIERhdG9zIGRlIGRpw6FtZXRyb3MgKHJlZW1wbGF6YSBjb24gdHVzIGRhdG9zIGRlIGNsYXNlKQ0KQ1AgPC0gYygzMS42LCAzMy40LCAzNS4wLCAzMi4yLCAzMy44LA0KICAgICAgIDM4LjQsIDMxLjYsIDM2LjgsIDM1LjAsIDM0LjAsDQogICAgICAgMjkuOCwgMzQuMCwgMzMuMCwgMzQuOCwgMzUuNiwNCiAgICAgICAzMC44LCAzMy4wLCAzMS42LCAzMy44LCAzMy44KQ0KDQojIMONbmRpY2UgcGFyYSBjYWRhIGRhdG8NCk11ZXN0cmEgPC0gMTpsZW5ndGgoQ1ApDQoNCiMgSGlzdG9ncmFtYQ0KaGlzdChDUCwgbWFpbj0iSGlzdG9ncmFtYSBkZSBEacOhbWV0cm9zIiwgeGxhYj0iRGnDoW1ldHJvIChtbSkiLCBjb2w9ImxpZ2h0Z3JlZW4iKQ0KDQpEX2dyb3VwcyA8LSBxY2MuZ3JvdXBzKENQLE11ZXN0cmEpDQoNCiMgR3J1cG9zIHBhcmEgcWNjIChhdW5xdWUgbm8gaGF5IGdydXBvcyByZWFsZXMsIHVzYW1vcyBsb3MgZGF0b3MgdGFsIGN1YWwpDQpxIDwtIHFjYyhEX2dyb3VwcywgdHlwZSA9ICJ4YmFyIiwgbnNpZ21hcyA9IDMsIHBsb3QgPSBGQUxTRSkNCg0KIyBDYXBhY2lkYWQgZGUgcHJvY2Vzbw0KcHJvY2Vzcy5jYXBhYmlsaXR5KHEsIHNwZWMubGltaXRzID0gYygzMCwgMzgpKQ0KDQpgYGANCkVsIHByb2Nlc28gdGllbmUgdW5hIGJhamEgY2FwYWNpZGFkIHBhcmEgY3VtcGxpciBjb25zaXN0ZW50ZW1lbnRlIGNvbiBsYXMgZXNwZWNpZmljYWNpb25lcyBlc3RhYmxlY2lkYXMuIEVzdG8gc3VnaWVyZSBxdWUgdW5hIHByb3BvcmNpw7NuIGltcG9ydGFudGUgZGUgcGllemFzIHB1ZWRlIGVzdGFyIGZ1ZXJhIGRlIHRvbGVyYW5jaWEsIGVzcGVjaWFsbWVudGUgcG9yIGRlYmFqbyBkZWwgbMOtbWl0ZSBpbmZlcmlvci4NCg0KRWwgw61uZGljZSBkZSBjYXBhY2lkYWQgQ3AgZnVlIGRlIDAuNTc5MSwgbG8gcXVlIGluZGljYSBxdWUgZWwgcHJvY2VzbyBubyBlcyBzdWZpY2llbnRlbWVudGUgY2FwYXosIHlhIHF1ZSBlc3RlIHZhbG9yIGVzIG1lbm9yIGEgMS4gQWRlbcOhcywgbG9zIMOtbmRpY2VzIENwX2wgeSBDcF91LCBkZSAwLjUyMTIgeSAwLjYzNzAgcmVzcGVjdGl2YW1lbnRlLCBldmlkZW5jaWFuIHF1ZSBlbCBwcm9jZXNvIGVzdMOhIGRlc2NlbnRyYWRvIHJlc3BlY3RvIGEgbGFzIGVzcGVjaWZpY2FjaW9uZXMsIGNvbiB1bmEgbWF5b3IgcHJvcG9yY2nDs24gZGUgcGllemFzIHF1ZSB0aWVuZGVuIGEgY2FlciBmdWVyYSBkZWwgbMOtbWl0ZSBpbmZlcmlvciAoNSUgZGUgb2JzZXJ2YWNpb25lcyByZWFsZXMgYmFqbyBlbCBMU0wgeSAyLjglIHBvciBlbmNpbWEgZGVsIFVTTCkuIEVzdG9zIHJlc3VsdGFkb3MgaW5kaWNhbiBxdWUgZWwgcHJvY2VzbyBuZWNlc2l0YSBhanVzdGVzIHBhcmEgbWVqb3JhciBzdSBlc3RhYmlsaWRhZCB5IHByZWNpc2nDs24sIHF1ZSBzZSBwdWVkZSBsb2dyYXIgcmVkdWNpZW5kbyBsYSB2YXJpYWJpbGlkYWQuDQoNCg0KIyMjIGMuIEFuw6FsaXNpcyBkZSBmYWxsYXMgZW4gbcOhcXVpbmFzDQoNCkFuw6FsaXNpcyBkZSBmYWxsYXMgZW4gbcOhcXVpbmFzLCBhbmFsaXphbmRvIGxhIGNvbmRpY2nDs24gZGVsIGVxdWlwbyBjb25zaWRlcmFkby4NCg0KYGBge3J9DQpIb3JhcyA8LSBjKDIwNDUsIDM0NTYsIDQ1NjcsIDM0MjEsIDI2NzgsIDM3ODksIDQzMjEsIDU4OTAsIDIzNjcsIDQzOTgsDQogICAgICAgICAgIDI2OTAsIDQ1MzIsIDMxOTAsIDIzNjcsIDQ1MDkpDQoNCiMgMy4gQW7DoWxpc2lzIGVzdGFkw61zdGljbw0Kc3VtbWFyeShIb3JhcykNCmhpc3QoSG9yYXMsIG1haW49Ikhpc3RvZ3JhbWEgZGUgZmFsbGFzIChob3JhcykiLCB4bGFiPSJIb3JhcyIsIGNvbD0ib3JhbmdlIiwgYm9yZGVyPSJ3aGl0ZSIpDQoNCiMgNC4gQWp1c3RlIGEgZGlzdHJpYnVjacOzbiBkZSBXZWlidWxsDQphanVzdGVfd2VpYnVsbCA8LSBmaXRkaXN0KEhvcmFzLCAid2VpYnVsbCIpDQpwbG90KGFqdXN0ZV93ZWlidWxsKQ0KDQojIDUuIFJlc3VtZW4gZGVsIGFqdXN0ZQ0Kc3VtbWFyeShhanVzdGVfd2VpYnVsbCkNCg0KYGBgDQpFbCB2YWxvciBkZSDOsiBpbmRpY2EgcXVlIGVsIGVxdWlwbyBzZSBlbmN1ZW50cmEgZW4gbGEgZmFzZSBkZSBkZXNnYXN0ZSwgbG8gcXVlIHNpZ25pZmljYSBxdWUgbGEgcHJvYmFiaWxpZGFkIGRlIGZhbGxhIGF1bWVudGEgYSBtZWRpZGEgcXVlIHRyYW5zY3VycmUgZWwgdGllbXBvIGRlIG9wZXJhY2nDs24uIENvbiBlc3RhIGluZm9ybWFjacOzbiwgZW4gdW4gZW50b3JubyByZWFsIHNlIHBvZHLDrWEgcGxhbnRlYXIgbGEgaW1wbGVtZW50YWNpw7NuIGRlIHBsYW5lcyBkZSBtYW50ZW5pbWllbnRvIHByZXZlbnRpdm8gZW5mb2NhZGFzIGFsIHNvc3RlbmltaWVudG8gZGVsIGVxdWlwby4NCg0KQWRlbcOhcywgZWwgdmFsb3IgZGUgJFxhbHBoYSQoZXNjYWxhKSBwcm9wb3JjaW9uYSB1bmEgcmVmZXJlbmNpYSBzb2JyZSBlbCB0aWVtcG8gcHJvbWVkaW8gZW4gZWwgcXVlIHNlIGVzcGVyYSBsYSBvY3VycmVuY2lhIGRlIGZhbGxhcywgbG8gcXVlIHBlcm1pdGUgcHJvZ3JhbWFyIG1hbnRlbmltaWVudG9zIGFscmVkZWRvciBkZSBsYXMgMzAwMCBhIDM1MDAgaG9yYXMsIGNvbnNpZGVyYW5kbyB1biBtYXJnZW4gZGUgc2VndXJpZGFkIHBhcmEgbWluaW1pemFyIHJpZXNnb3MgZGUgcGFyb3Mgbm8gcHJvZ3JhbWFkb3MNCg0KIyMjIGQuIEFwbGljYWNpw7NuDQoNCkFwbGljYXIgZWwgc2NyaXB0IGRlIFIgY29uIGxvcyBkYXRvcyB0b21hZG9zIGVuIGNsYXNlICgyMCBkYXRvcykgc29icmUgbGEgZmFicmljYWNpw7NuIGRlbCBjb21wb25lbnRlIG1lY8OhbmljbyBjdXlvIGRpw6FtZXRybyBmdWUgZXNwZWNpZmljYWRvIGVuICQxNiw5MCBccG0gMCwwOCQgbW0sIFRvbGVyYW5jaWEgJFsxNiw4MiDigJMgMTYsOThdJC4gQW5hbGl6YXIgbGEgaW5mb3JtYWNpw7NuIGRlIGxvcyByZXN1bHRhZG9zIGdlbmVyYWRvcyB5IHBsYW50ZWFyIHVuYSBlc3RyYXRlZ2lhIGRlIG1lam9yYW1pZW50byBkZSBwcm9jZXNvIHBhcmEgbG9ncmFyIGxhIGVzcGVjaWZpY2FjacOzbi4NCg0KYGBge3J9DQojIDEuIERhdG9zIGRlIGRpw6FtZXRyb3MNCkRpYW1ldHJvIDwtIGMoMTYuODgsIDE2LjgxLCAxNi45MiwgMTYuOTIsIDE2LjgxLCAxNi45MywgMTYuOTYsIDE2Ljk2LA0KICAgICAgICAgICAgICAxNi45NCwgMTYuOTUsIDE2Ljk1LCAxNi45NiwgMTYuOTIsIDE2Ljk3LCAxNi45NCwgMTYuOTQsDQogICAgICAgICAgICAgIDE2LjkzLCAxNi45MywgMTYuODIsIDE2LjkzKQ0KDQojIDIuIEFuw6FsaXNpcyBlc3RhZMOtc3RpY28NCnN1bW1hcnkoRGlhbWV0cm8pDQpib3hwbG90KERpYW1ldHJvLCBtYWluPSJCb3hwbG90IGRlIERpw6FtZXRyb3MiLCBjb2w9ImxpZ2h0Ymx1ZSIsIHlsYWI9IkRpw6FtZXRybyAobW0pIikNCg0KIyAzLiBIaXN0b2dyYW1hDQpoaXN0KERpYW1ldHJvLCBtYWluPSJIaXN0b2dyYW1hIGRlIERpw6FtZXRyb3MiLCB4bGFiPSJEacOhbWV0cm8gKG1tKSIsIGNvbD0ibGlnaHRncmVlbiIsIGJvcmRlcj0id2hpdGUiKQ0KDQojIDQuIENhcGFjaWRhZCBkZSBwcm9jZXNvICh1c2FuZG8gcWNjKQ0KaWYgKCFyZXF1aXJlKHFjYykpIGluc3RhbGwucGFja2FnZXMoInFjYyIpOyBsaWJyYXJ5KHFjYykNCg0KIyBDb250cm9sIGRlIGNhbGlkYWQgcGFyYSB2YWxvcmVzIGluZGl2aWR1YWxlcw0KcSA8LSBxY2MoRGlhbWV0cm8sIHR5cGUgPSAieGJhci5vbmUiLCBuc2lnbWFzID0gMywgbGFiZWxzID0gMToyMCwNCiAgICAgICAgIHhsYWIgPSAiTXVlc3RyYSIsIHlsYWIgPSAiRGnDoW1ldHJvIChtbSkiLCB0aXRsZSA9ICJDYXJ0YSBYLWJhciBkZSB2YWxvcmVzIGluZGl2aWR1YWxlcyIpDQoNCiMgQ2FwYWNpZGFkIGRlIHByb2Nlc28gKHRvbGVyYW5jaWEgMTYuODIgYSAxNi45OCkNCnByb2Nlc3MuY2FwYWJpbGl0eShxLCBzcGVjLmxpbWl0cyA9IGMoMTYuODIsIDE2Ljk4KSkNCg0KYGBgDQpFbCByZXN1bWVuIGVzdGFkw61zdGljbyBtdWVzdHJhIHVuYSBtZWRpYSBjZXJjYW5hIGEgMTYsOTIgbW0sIGxvIGN1YWwgZXMgcG9zaXRpdm8sIHBlcm8gdGFtYmnDqW4gcmVzYWx0YSBsYSBwcmVzZW5jaWEgZGUgdmFsb3JlcyBtw61uaW1vcyBlbiAxNiw4MSBtbSwganVzdG8gZW4gZWwgbMOtbWl0ZSBpbmZlcmlvciwgeSBtw6F4aW1vcyBlbiAxNiw5NyBtbSwgbXV5IGNlcmNhbm9zIGFsIGzDrW1pdGUgc3VwZXJpb3IuIERlIG1hbmVyYSBnZW5lcmFsLCBzZSBhcHJlY2lhIHVuYSBidWVuYSBwcmVjaXNpw7NuIGVuIGVsIHByb2Nlc28uDQoNCg0KRGVzcHXDqXMgZGUgcmVhbGl6YXIgbG9zIGFuw6FsaXNpcyBhbnRlcmlvcmVzLCBzZSBjb25jbHV5ZSBxdWUgbGEgY2FwYWNpZGFkIGRlIHByb2Nlc28gZW4gYWxndW5vcyBjYXNvcyBlcyBiYWphIHkgZWwgcHJvY2VzbyBkZSBmYWJyaWNhY2nDs24gcHVlZGUgcHJlc2VudGFyIGRlc3ZpYWNpb25lcyByZXNwZWN0byBhIGxhcyBlc3BlY2lmaWNhY2lvbmVzLiBQYXJhIG1lam9yYXIsIGVzIG5lY2VzYXJpbyBpbXBsZW1lbnRhciBhY2Npb25lcyBjb21vIGxhIHJlZHVjY2nDs24gZGUgbGEgdmFyaWFiaWxpZGFkIGRlbCBwcm9jZXNvLCBvcHRpbWl6YWNpw7NuIGRlIGxvcyBwYXLDoW1ldHJvcyBkZSBtw6FxdWluYSwgYWp1c3RlIGRlIGhlcnJhbWllbnRhcywgZXN0YWJsZWNpbWllbnRvIGRlIHVuIHByb2dyYW1hIGRlIG1hbnRlbmltaWVudG8gcHJldmVudGl2bywgeSBjYXBhY2l0YWNpw7NuIGRlbCBwZXJzb25hbCBlbiB0ZW1hcyBkZSBjb250cm9sIGRlIGNhbGlkYWQNCg0KIyAyLiBBbsOhbGlzaXMgZGUgZmFsbGFzDQoNCkEgY29udGludWFjacOzbiBzZSBtdWVzdHJhbiBsb3MgZGF0b3MgZGUgdGllbXBvIGVudHJlIGZhbGxhcyBUQkYsIGVuIGhvcmFzLCBwYXJhIHVuIGVxdWlwbyBkZSBmYWJyaWNhY2nDs24uDQoNCmBgYHtyfQ0KdGJmX2hvcmFzIDwtIFRCRiRgVEJGIChob3JhcylgDQpjYXQoIlRCRiAoaCk6ICIsdGJmX2hvcmFzLCAiXG4iKQ0KYGBgDQoNCkEgcGFydGlyIGRlIGVzdG9zIGRhdG9zIGVuY29udHJhciBsYSBmdW5jacOzbiBkZSBkaXN0cmlidWNpw7NuIGRlIFdlaWJ1bGwgcXVlIG1vZGVsYSBsYSBwcm9iYWJpbGlkYWQgZGUgZmFsbGEgJEYodCkkIHkgbGEgY29uZmlhYmlsaWRhZCAkUih0KSQuIA0KDQpgYGANCnRiZl9maXRfd2VpYnVsbCA8LSBpbnZpc2libGUocnJpc2tGaXRkaXN0LmNvbnQodGJmX2hvcmFzLCAid2VpYnVsbCIpKQ0KdGJmX2JldGEgPC0gaW52aXNpYmxlKHRiZl9maXRfd2VpYnVsbCRlc3RpbWF0ZVsic2hhcGUiXSkNCnRiZl9hbGZhIDwtIGludmlzaWJsZSh0YmZfZml0X3dlaWJ1bGwkZXN0aW1hdGVbInNjYWxlIl0pDQpgYGANCg0KYGBge3J9DQp0YmZfZml0X3dlaWJ1bGwgPC0gaW52aXNpYmxlKHJyaXNrRml0ZGlzdC5jb250KHRiZl9ob3JhcywgIndlaWJ1bGwiKSkNCnRiZl9iZXRhIDwtIGludmlzaWJsZSh0YmZfZml0X3dlaWJ1bGwkZXN0aW1hdGVbInNoYXBlIl0pDQp0YmZfYWxmYSA8LSBpbnZpc2libGUodGJmX2ZpdF93ZWlidWxsJGVzdGltYXRlWyJzY2FsZSJdKQ0KYGBgDQoNCmBgYHtyfQ0KY2F0KCJFc2NhbGEgKGFsZmEpOiIsIHNjYWxlX2VzdCwgIlxuRm9ybWEgKGJldGEpOiIsIHNoYXBlX2VzdCwgIlxuIikNCmBgYA0KDQpgYGB7cn0NCnRiZl9kd2VpYnVsbCA8LSBpbnZpc2libGUoZHdlaWJ1bGwodGJmX2hvcmFzLCB0YmZfYmV0YSwgdGJmX2FsZmEpKQ0KcGxvdCh0YmZfaG9yYXMsIHRiZl9kd2VpYnVsbCwgY29sPSJibHVlIikNCmBgYA0KDQoNCiMjIyBGdW5jacOzbiBkZSBkZW5zaWRhZCBkZSBwcm9iYWJpbGlkYWQNCg0KYGBge3J9DQp0YmZfZGVuc193ZWlidWxsIDwtIGZ1bmN0aW9uKHgsIHRiZl9iZXRhLCB0YmZfYWxmYSkgew0KICAodGJmX2JldGEgLyB0YmZfYWxmYSkgKiAoeCAvIHRiZl9hbGZhKV4odGJmX2JldGEgLSAxKSAqIGV4cCgtKHggLyB0YmZfYWxmYSledGJmX2JldGEpDQp9DQpgYGANCg0KQSBwYXJ0aXIgZGUgbGEgZGVmaW5pY2nDs24gZGUgbGEgZnVuY2nDs24sIHNlIHByb2NlZGUgYSBncmFmaWNhciBwYXJhIGFwcmVjaWFyIHN1IGNvbXBvcnRhbWllbnRvLg0KDQpgYGB7cn0NCmN1cnZlKHRiZl9kZW5zX3dlaWJ1bGwoeCwgdGJmX2JldGEsIHRiZl9hbGZhKSwgeGxpbT1jKG1pbih0YmZfaG9yYXMpLTAuNSxtYXgodGJmX2hvcmFzKSswLjUpLHhsYWI9IlRpZW1wbyBlbnRyZSBmYWxsYXMgVEJGIiwgeWxhYj0iRGVuc2lkYWQgZGUgUHJvYmFiaWxpZGFkIiwgY29sPSJyZWQiKQ0KDQpgYGANCg0Kwr9DdcOhbCBzZXLDoSBlbCB2YWxvciBkZSBwcm9iYWJpbGlkYWQgZGUgZmFsbGEgeSBjb25maWFiaWxpZGFkIGFsIGNhYm8gZGUgMTUgaG9yYXMgZGUgb3BlcmFjacOzbj8gwr9FcyBhZGVjdWFkbyBlbCB2YWxvciBkZSBjb25maWFiaWxpZGFkIHBhcmEgbGEgb3BlcmFjacOzbiBkZWwgZXF1aXBvPyANCg0KX19fXw0KDQojIyBQcm9iYWJpbGlkYWQgZGUgZmFsbGENCg0KDQpgYGB7cn0NCnRiZl9wd2VpYnVsbCA8LSBpbnZpc2libGUocHdlaWJ1bGwodGJmX2hvcmFzLCB0YmZfYmV0YSwgdGJmX2FsZmEpKQ0KDQpwbG90KHRiZl9ob3JhcywgdGJmX3B3ZWlidWxsLCB4bGFiPSJUaWVtcG8gZW50cmUgZmFsbGFzIFRCRiIsDQogICAgIHlsYWI9IlByb2JhYmlsaWRhZCBkZSBmYWxsYSIsIGNvbD0iYmx1ZSIpDQpgYGANCg0KU2UgdGllbmUgbGEgZGlzdHJpYnVjacOzbiBhY3VtdWxhZGEgZGUgV2VpYnVsbCBxdWUgZGljdGEgbGEgcHJvYmFiaWxpZGFkIGRlIGZhbGxhOg0KDQpgYGB7cn0NCnRiZl9hY3VtX3dlaWJ1bGwgPC0gZnVuY3Rpb24oeCx0YmZfYmV0YSx0YmZfYWxmYSl7DQogIDEgLSBleHAoLSh4L3RiZl9hbGZhKV50YmZfYmV0YSkNCn0NCg0KdGJmX2FjdW1fd2VpYnVsbA0KDQpjdXJ2ZSh0YmZfYWN1bV93ZWlidWxsKHgsdGJmX2JldGEsdGJmX2FsZmEpLCB4bGltPWMobWluKHRiZl9ob3JhcyktMC41LG1heCh0YmZfaG9yYXMpKzAuNSkpDQoNCmBgYCANCg0KRGFkYSBsYSBjdXJ2YSwgc2kgc2UgZGVzZWEgb2J0ZW5lciBlbCB2YWxvciBkZSBsYSBmdW5jacOzbiBkZSBwcm9iYWJpbGlkYWQgZGUgZmFsbGEgcGFyYSAxNSBob3JhczoNCg0KYGBge3J9DQpwcm9iX2ZhbGxhIDwtIHB3ZWlidWxsKDE1LCBzaGFwZSA9IHNoYXBlX2VzdCwgc2NhbGUgPSBzY2FsZV9lc3QpDQoNCmNhdCgiUHJvYmFiaWxpZGFkIGRlIGZhbGxhOiAiLHByb2JfZmFsbGEqMTAwLCAiJSIpDQoNCmBgYA0KDQpfX19fX18NCg0KIyMgQ29uZmlhYmlsaWRhZA0KDQpEYWRhIGxhIHByb2JhYmlsaWRhZCBkZSBmYWxsYSBwYXJhIDE1IGhvcmFzIGRlIG9wZXJhY2nDs24sIGxhIGNvbmZpYWJpbGlkYWQgc2UgcHVlZGUgZGVmaW5pciBjb21vOg0KYGBge3J9DQpjb25maWFiaWxpZGFkIDwtIDEgLSBwcm9iX2ZhbGxhDQpjYXQoIkNvbmZpYWJpbGlkYWQ6ICIsY29uZmlhYmlsaWRhZCoxMDAsICIlIikNCmBgYA0KVW4gdmFsb3Igc2lnbmlmaWNhdGl2YW1lbnRlIGJham8gZGUgY29uZmlhYmlsaWRhZCBjb21vIGVsIG9idGVuaWRvIGluZGljYSBxdWUgZWwgZXF1aXBvIG5vIHRpZW5lIHVuYSBjYXBhY2lkYWQgYWRlY3VhZGEgcGFyYSBkZXNlbXBlw7FhciBzdXMgZnVuY2lvbmVzIGRlIG1hbmVyYSBzYXRpc2ZhY3RvcmlhLCBlbiBsYSBtZWRpZGEgcXVlIGVzIG3DoXMgcHJvcGVuc28gYSBmYWxsYXIgcXVlIGxvIGNvbnRyYXJpby4NCg0KIyMgRnVuY2nDs24gZGUgdGFzYSBkZSBmYWxsYXMNCg0KRXhwcmVzYXIgbWF0ZW3DoXRpY2FtZW50ZSBsYSBmdW5jacOzbiBkZSB0YXNhIGRlIGZhbGxhcyAkXGxhbWJkYSh0KSQgeSBhIHBhcnRpciBkZSDDqXN0YSBkZXRlcm1pbmFyIGVsIHZhbG9yIGRlIGxhIHRhc2EgZGUgZmFsbGFzIHBhcmEgMTUgaG9yYXMgZGUgb3BlcmFjacOzbi5gDQoNClJlY29yZGFuZG8gcXVlICRcYmV0YSA9Ni41OSQgeSAkXGFscGhhPTE1LjAxJCwgbGEgZnVuY2nDs24gbGFtYmRhIGRlIHRhc2EgZGUgZmFsbGFzIHNlIHByZXNlbnRhIGVudG9uY2VzIGNvbW86DQoNCiRcbGFtYmRhKHQpPTAuNTMqXGxlZnQoXGZyYWN7dH17MTUuMDF9XHJpZ2h0KV57NS41OX0kDQoNCmBgYHtyfQ0KDQp0YmZfbGFtYmRhIDwtIGZ1bmN0aW9uKHgsdGJmX2FsZmEsdGJmX2JldGEpew0KICAodGJmX2JldGEvdGJmX2FsZmEpKih4L3RiZl9hbGZhKV4odGJmX2JldGEtMSkNCn0NCg0KY2F0KCJUYXNhIGRlIGZhbGxhcyBwYXJhIDE1IGhvcmFzIiwgdGJmX2xhbWJkYSgxNSx0YmZfYWxmYSx0YmZfYmV0YSksIiBmYWxsYXMvaG9yYSIpDQoNCmBgYA0KDQojIyBDdXJ2YSBkZSBiYcOxZXJhDQoNCsK/RW4gcXXDqSB6b25hIGRlIGxhIGN1cnZhIGRlIGxhIGJhw7FlcmEgc2UgZW5jdWVudHJhIGVsIGVxdWlwbz8gDQpFbCBmYWN0b3IgZGUgZm9ybWEgZXMgbWF5b3IgYSAxLCBwb3IgbG8gcXVlIHNlIHB1ZWRlIGVudGVuZGVyIHF1ZSBlbCBlcXVpcG8gc2UgZW5jdWVudHJhIGVuIGV0YXBhIGRlIGVudmVqZWNpbWllbnRvLiBFbiBlc2Ugc2VudGlkbywgZWwgZXF1aXBvIHNlIGVuZnJlbnRhIGEgZmFsbGEgcG9yIGRlc2dhc3RlLg0KDQojIyBDb25jbHVzacOzbg0Kwr9CYWpvIGVzdGEgY29uZGljacOzbiBzZSBjb25zaWRlcmFyw61hIHVuIHJlZW1wbGF6byBlbiBlbCBjb3J0byBwbGF6byBkZWwgZXF1aXBvPw0KDQpFbnRlbmRpZW5kbyBxdWUgDQoNCiMgMy4gVGllbXBvIGRlIHJlcGFyYWNpw7NuIChUVCkNCg0KQSBjb250aW51YWNpw7NuLCBzZSBtdWVzdHJhbiBsb3MgZGF0b3MgZGUgbG9zIHRpZW1wb3MgcGFyYSByZXBhcmFjacOzbiBvIG1hbnRlbmltaWVudG8gVFRSIChUVE0gcG9yIGFsZ3Vub3MgYXV0b3JlcykgcGFyYSBlbCBtaXNtbyBlcXVpcG8gZGUgbGEgdGFibGEgYW50ZXJpb3IuDQoNCg0KYGBge3J9DQp0dHJfaG9yYXMgPC0gVFRSJGBUVFIgKGhvcmFzKWANCmNhdCgiVFRSIChoKTogIiwgdHRyX2hvcmFzLCJcbiIpDQpgYGANCiMjIERpc3BvbmliaWxpZGFkDQoNCkRldGVybWluYXIgbGEgZGlzcG9uaWJpbGlkYWQgJEEkIChBdmFpbGFiaWxpdHkpIGNvbnNpZGVyYW5kbyBxdWUgZWwgc2lzdGVtYSBlcyByZXBhcmFibGUuIMK/RXMgZXN0ZSB2YWxvciBhZGVjdWFkbyBwYXJhIGxhIG9wZXJhY2nDs24gZGVsIGVxdWlwbyBlbiBsYSBsw61uZWEgZGUgcHJvZHVjY2nDs24/DQoNClNlIGRlZmluZSBsYSBkaXNwb25pYmlsaWRhZCwgZW4gdW4gc2lzdGVtYSByZXBhcmFibGUsIGNvbW86ICRBPVxmcmFje01UQkZ9e01UQkYrTVRUTX0kLiBBIGNvbnRpbnVhY2nDs24gc2UgZGVmaW5lbiBlc3RhcyB2YXJpYWJsZXMgcGFyYSBsb3MgY29uanVudG9zIGRlIGRhdG9zIA0KDQpgYGB7cn0NCk1UQkYgPC0gbWVhbih0YmZfaG9yYXMpDQpNVFRNIDwtIG1lYW4odHRyX2hvcmFzKQ0KDQpjYXQoIk1UQkYgPSAiLE1UQkYsIiBoXG5NVFRNID0gIixNVFRNLCIgaCIpDQpgYGANCkVuIGNvbnNlY3VlbmNpYSwgbGEgZGlzcG9uaWJpbGlkYWQgQSBlczoNCg0KYGBge3J9DQpBIDwtIE1UQkYvKE1UQkYrTVRUTSkNCmNhdCgiQSA9ICIsQSoxMDAsIiUiKQ0KYGBgDQoNCg0KDQojIyBNYW50ZW5pYmlsaWRhZA0KRXhwcmVzYXIgbWF0ZW3DoXRpY2FtZW50ZSBsYSBmdW5jacOzbiBkZSBtYW50ZW5pYmlsaWRhZCBwYXJhIGVsIGVxdWlwbyB5IGRldGVybWluYXJsYSBwYXJhIHVuIFRUUiBkZSAzIGhvcmFzLg0KDQpBc3VtaWVuZG8gbWFudGVuaWJpbGlkYWQgY29uIFRUTSBleHBvbmVuY2lhbCwgc2UgYXBsaWNhcsOhIGxhIGVjdWFjacOzbiBjb3JyZXNwb25kaWVudGU6DQoNCiRNKHQpPTEtZV57LVxtdSB0fSQNCg0KRGUgZG9uZGU6DQpgYGB7cn0NCm11IDwtIDEvTVRUTQ0KY2F0KCJcdTAzQkMgPSAiLG11KQ0KYGBgDQoNCkVuIGNvbnNlY3VlbmNpYSwgbGEgZnVuY2nDs24gbWF0ZW3DoXRpY2Egc2Vyw6E6DQoNCiRNKHQpPTEtZV57LTAuNDI1dH0kDQoNClkgbGEgbWFudGVuaWJpbGlkYWQgTSBwYXJhIDMgaG9yYXMgZGUgb3BlcmFjacOzbiBzZXLDoToNCg0KYGBge3J9DQptYW50ZW5pYmlsaWRhZCA8LSBmdW5jdGlvbih4KXsxLWV4cCgtbXUqeCl9DQpjYXQoIk0oMTMpID0gIiwgbWFudGVuaWJpbGlkYWQoMykpDQoNCmN1cnZlKG1hbnRlbmliaWxpZGFkKHgpLCB4bGltPWMobWluKHR0cl9ob3JhcyktMC41LG1heCh0dHJfaG9yYXMpKzAuNSkpDQoNCmBgYA0KDQoNCg0KIyMgQ29uY2x1c2lvbmVzDQrCv1F1w6kgc2UgcHVlZGUgY29uY2x1aXIgc29icmUgbGEgbWFudGVuaWJpbGlkYWQgZGVsIGVxdWlwbz8NCg0KRW4gY3VhbnRvIGEgbGEgbWFudGVuaWJpbGlkYWQgZGVsIGVxdWlwbyBhIHBhcnRpciBkZSBsb3MgZGF0b3MgcGxhbnRlYWRvcyBzZSBwdWVkZSBhcHJlY2lhciB1biBjb21wb3J0YW1pZW50byBmYXZvcmFibGUgcXVlLCBhdW5hZG8gYSBsYSByZWxhdGl2YW1lbnRlIGFsdGEgZGlzcG9uaWJpbGlkYWQgcXVlIGRpc3BvbmUsIHBlcm1pdGUgdW4gcHJvY2VzbyDDs3B0aW1vIGVuIHRpZW1wb3MgZGUgcmVwYXJhY2nDs24u