Como leer este
documento
Los cuatro ejercicios comparten una sola pregunta: cuando dos
modelos compiten, quien decide? La respuesta que sostengo es
que los indices de ajuste son una condicion necesaria pero nunca
suficiente, y que un modelo con mejor ajuste puede ser peor modelo. Los
ejercicios 1 a 3 construyen la evidencia con datos; el ejercicio 4 la
confronta con un caso publicado donde los autores rechazaron su propio
modelo mejor ajustado.
Todos los modelos se estiman con lavaan. Los criterios
de ajuste que uso a lo largo del documento son los convencionales en la
literatura (Hu y Bentler, 1999):
Criterios de ajuste usados en todo el documento
| Chi-cuadrada |
Distancia absoluta entre la matriz observada y la
implicada |
no significativa (sensible a N) |
| CFI / TLI |
Ajuste comparativo contra el modelo nulo |
>= .95 (aceptable >= .90) |
| RMSEA |
Error de aproximacion por grado de libertad (penaliza
falta de parsimonia) |
<= .06 (aceptable <= .08) |
| SRMR |
Residual estandarizado promedio |
<= .08 |
# indices que reporto en cada modelo
IDX <- c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "srmr")
# tabla de ajuste de uno o varios modelos, para comparar en el mismo renglon
tabla_ajuste <- function(..., etiquetas = NULL) {
modelos <- list(...)
if (is.null(etiquetas)) etiquetas <- paste("Modelo", seq_along(modelos))
out <- do.call(rbind, lapply(modelos, function(m) {
fm <- fitMeasures(m, IDX)
data.frame(chisq = round(fm[["chisq"]], 2), gl = fm[["df"]],
p = round(fm[["pvalue"]], 3), CFI = round(fm[["cfi"]], 3),
TLI = round(fm[["tli"]], 3), RMSEA = round(fm[["rmsea"]], 3),
SRMR = round(fm[["srmr"]], 3))
}))
# post.check avisa de soluciones inadmisibles (varianzas negativas, cargas > 1)
out$admisible <- sapply(modelos, function(m) lavInspect(m, "post.check"))
rownames(out) <- etiquetas
out
}
# prueba de diferencia de chi-cuadrada entre dos modelos anidados, como tabla con titulo
# (las salidas sin titulo se desalinean de su rotulo al compilar a PDF)
comparar <- function(modelo_a, modelo_b, etiquetas, caption) {
gl <- c(fitMeasures(modelo_a, "df"), fitMeasures(modelo_b, "df"))
a <- suppressWarnings(lavTestLRT(modelo_a, modelo_b))
# lavTestLRT devuelve los modelos ordenados por grados de libertad, no en el orden
# en que se pasan: hay que reordenar las etiquetas igual o quedan cruzadas
out <- data.frame(Modelo = etiquetas[match(a$Df, gl)],
gl = a$Df, AIC = round(a$AIC, 1), BIC = round(a$BIC, 1),
chisq = round(a$Chisq, 2),
dif_chisq = round(a$"Chisq diff", 3),
dif_gl = a$"Df diff",
p = round(a$"Pr(>Chisq)", 4))
kable(out, row.names = FALSE,
col.names = c("Modelo","gl","AIC","BIC","chisq","dif. chisq","dif. gl","p"),
caption = caption)
}
# cargas estandarizadas ordenadas de menor a mayor
cargas <- function(fit) {
s <- subset(standardizedSolution(fit), op == "=~")
s <- s[order(s$est.std), c("lhs", "rhs", "est.std", "pvalue")]
names(s) <- c("Factor", "Item", "Carga_estandarizada", "p")
rownames(s) <- NULL
s
}
Ejercicio 1: Holzinger
y Swineford (1939)
El modelo teorico de
tres factores ajusta mal, y el problema tiene nombre: x9
La base clasica de Holzinger y Swineford registra nueve pruebas
mentales aplicadas a 301 estudiantes de dos escuelas. La teoria propone
tres habilidades latentes: visual (x1–x3),
verbal (x4–x6) y velocidad
(x7–x9).
mod_hs <- ' visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 '
fit_hs <- cfa(mod_hs, data = HolzingerSwineford1939)
kable(tabla_ajuste(fit_hs, etiquetas = "3 factores (teorico)"),
caption = "El modelo teorico se queda corto: CFI por debajo de .95 y RMSEA arriba de .06")
El modelo teorico se queda corto: CFI por debajo de .95 y RMSEA
arriba de .06
| 3 factores (teorico) |
85.31 |
24 |
0 |
0.931 |
0.896 |
0.092 |
0.065 |
TRUE |
El CFI de 0.931 y el RMSEA de 0.092 son aceptables pero no buenos.
Antes de tocar nada, conviene ver donde falla:
x2 (.42) y x3 (.58) sostienen mal al factor visual
| visual |
x2 |
0.424 |
0 |
| speed |
x7 |
0.570 |
0 |
| visual |
x3 |
0.581 |
0 |
| speed |
x9 |
0.665 |
0 |
| speed |
x8 |
0.723 |
0 |
| visual |
x1 |
0.772 |
0 |
| textual |
x6 |
0.838 |
0 |
| textual |
x4 |
0.852 |
0 |
| textual |
x5 |
0.855 |
0 |
mi_hs <- modindices(fit_hs, sort. = TRUE)
kable(head(mi_hs[, c("lhs","op","rhs","mi","epc","sepc.all")], 6), row.names = FALSE,
digits = 3, caption = "Indices de modificacion: x9 quiere cargar tambien en visual")
Indices de modificacion: x9 quiere cargar tambien en
visual
| visual |
=~ |
x9 |
36.411 |
0.577 |
0.515 |
| x7 |
|
x8 |
34.145 |
0.536 |
0.859 |
| visual |
=~ |
x7 |
18.631 |
-0.422 |
-0.349 |
| x8 |
|
x9 |
14.946 |
-0.423 |
-0.805 |
| textual |
=~ |
x3 |
9.151 |
-0.272 |
-0.238 |
| x2 |
|
x7 |
8.918 |
-0.183 |
-0.192 |
El indice mas grande no es un error residual cualquiera: es
visual =~ x9, con un MI de 36.4. Eso tiene lectura
sustantiva. La prueba x9 mide velocidad para contar puntos en
figuras: es una tarea de rapidez, si, pero el estimulo es
visual. No es raro que comparta varianza con el factor
visual.
Depuracion: un solo
parametro, elegido por teoria y no por el indice mas alto
mod_hs2 <- ' visual =~ x1 + x2 + x3 + x9
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 '
fit_hs2 <- cfa(mod_hs2, data = HolzingerSwineford1939)
# alternativa que el MI tambien sugiere, pero sin lectura sustantiva clara
mod_hs3 <- paste(mod_hs, "\n x7 ~~ x9")
fit_hs3 <- cfa(mod_hs3, data = HolzingerSwineford1939)
kable(tabla_ajuste(fit_hs, fit_hs2, fit_hs3,
etiquetas = c("3 factores (teorico)", "x9 carga tambien en visual",
"covarianza residual x7 ~~ x9")),
caption = "Solo la carga cruzada de x9 mueve el ajuste a territorio bueno")
Solo la carga cruzada de x9 mueve el ajuste a territorio
bueno
| 3 factores (teorico) |
85.31 |
24 |
0 |
0.931 |
0.896 |
0.092 |
0.065 |
TRUE |
| x9 carga tambien en visual |
52.38 |
23 |
0 |
0.967 |
0.948 |
0.065 |
0.045 |
TRUE |
| covarianza residual x7 x9 |
79.80 |
23 |
0 |
0.936 |
0.899 |
0.091 |
0.062 |
TRUE |
comparar(fit_hs, fit_hs2,
c("3 factores (teorico)", "x9 carga tambien en visual"),
"Liberar un solo parametro mejora el ajuste de forma significativa")
Liberar un solo parametro mejora el ajuste de forma
significativa
| x9 carga tambien en visual |
23 |
7487 |
7568 |
52.38 |
NA |
NA |
NA |
| 3 factores (teorico) |
24 |
7518 |
7595 |
85.31 |
32.92 |
1 |
0 |
La diferencia de chi-cuadrada es significativa con un solo grado de
libertad: liberar visual =~ x9 mejora el ajuste de forma
real, no marginal. La covarianza residual x7 ~~ x9, en
cambio, casi no mueve nada (CFI 0.936), lo cual confirma que el problema
no es ruido compartido entre dos pruebas de velocidad sino que
x9 mide dos cosas a la vez.
Honestidad sobre la
depuracion: validarla en una muestra que no la sugirio
Aqui esta el riesgo del que casi nunca se habla. Un indice de
modificacion se calcula sobre los mismos datos que se
van a usar para juzgar el modelo mejorado. Seguirlo es, en el limite,
ajustarle el modelo al ruido de esta muestra. La unica defensa real es
verificar que el hallazgo se repite en datos que no participaron en la
decision.
La base trae dos escuelas. Uso una para descubrir y la otra para
confirmar:
val <- do.call(rbind, lapply(levels(HolzingerSwineford1939$school), function(esc) {
sub <- HolzingerSwineford1939[HolzingerSwineford1939$school == esc, ]
a <- cfa(mod_hs, data = sub)
b <- cfa(mod_hs2, data = sub)
data.frame(Escuela = esc, n = nrow(sub),
CFI_base = round(fitMeasures(a, "cfi"), 3),
CFI_depurado = round(fitMeasures(b, "cfi"), 3),
RMSEA_base = round(fitMeasures(a, "rmsea"), 3),
RMSEA_depurado = round(fitMeasures(b, "rmsea"), 3),
carga_x9_visual = round(subset(standardizedSolution(b),
lhs == "visual" & rhs == "x9")$est.std, 3))
}))
kable(val, row.names = FALSE, caption = "La carga cruzada de x9 aparece en las dos escuelas, pero no con la misma fuerza")
La carga cruzada de x9 aparece en las dos escuelas, pero no con
la misma fuerza
| Grant-White |
145 |
0.941 |
0.989 |
0.089 |
0.040 |
0.447 |
| Pasteur |
156 |
0.903 |
0.927 |
0.104 |
0.092 |
0.310 |
El resultado se repite en ambas escuelas, asi que no es un artefacto:
x9 carga en visual en las dos. Pero la magnitud cae de 0.447 en
Grant-White a 0.31 en Pasteur, y en Pasteur el modelo depurado
sigue sin alcanzar el criterio (CFI 0.927, RMSEA
0.092). Es decir: la correccion es real, pero el modelo depurado que
reporto arriba se ve mejor de lo que es porque se estimo en la muestra
completa, incluyendo la escuela donde el efecto es fuerte.
Conclusiones del
ejercicio 1
- El modelo teorico de tres factores es defendible pero
incompleto: ajusta de forma aceptable (CFI 0.931) y no
buena.
- La causa es una variable que mide dos constructos.
x9 pertenece a velocidad por su formato y a visual por su contenido. Es
un problema de diseno del instrumento, no de estimacion.
- Depurar guiado por indices de modificacion funciona, pero el
ajuste que resulta esta inflado por haber usado los mismos
datos para descubrir y para evaluar. La validacion entre escuelas lo
demuestra.
- Regla que me llevo: solo libero un parametro si puedo explicarlo
antes de verlo en la tabla de MI.
visual =~ x9 pasa esa
prueba; x7 ~~ x9 no, y ademas no servia.
Ejercicio 2: democracia
politica e industrializacion (Bollen)
El modelo obvio
ajusta mal, y la razon es que ignora que son las mismas preguntas dos
veces
La base de Bollen sigue a 75 paises en desarrollo. ind60
es industrializacion en 1960 (x1–x3); dem60 y
dem65 son democracia politica en 1960 y 1965, medidas con
los mismos cuatro indicadores (y1–y4 y y5–y8
respectivamente). La hipotesis es que la industrializacion impulsa la
democracia, en parte de forma directa y en parte a traves de la
democracia previa.
mod_pd <- '
ind60 =~ x1 + x2 + x3
dem60 =~ y1 + y2 + y3 + y4
dem65 =~ y5 + y6 + y7 + y8
dem60 ~ ind60
dem65 ~ ind60 + dem60 '
fit_pd <- cfa(mod_pd, data = PoliticalDemocracy)
kable(tabla_ajuste(fit_pd, etiquetas = "sin errores correlacionados"),
caption = "RMSEA de .101: el modelo deja algo importante fuera")
RMSEA de .101: el modelo deja algo importante fuera
| sin errores correlacionados |
72.46 |
41 |
0.002 |
0.953 |
0.938 |
0.101 |
0.055 |
TRUE |
Todos los indices altos son covarianzas entre errores de
y
| y2 |
|
y6 |
9.279 |
2.129 |
| y6 |
|
y8 |
8.668 |
1.513 |
| y1 |
|
y5 |
8.183 |
0.884 |
| y3 |
|
y6 |
6.574 |
-1.590 |
| y1 |
|
y3 |
5.204 |
1.024 |
| y2 |
|
y4 |
4.911 |
1.432 |
Los seis indices mas grandes son covarianzas entre residuales
de los indicadores y, y ninguno involucra a las x. Eso no es
casualidad. El indicador y1 (libertad de prensa en 1960) y el y5
(libertad de prensa en 1965) son la misma pregunta aplicada cinco
anios despues: comparten no solo el constructo democracia, sino la
fuente, el sesgo del codificador y la idiosincrasia del pais. Esa
varianza compartida es metodo, no constructo, y si no
se modela se acumula en el residual del sistema.
El modelo correcto:
dejar que los errores del mismo indicador se correlacionen en el
tiempo
mod_pd2 <- '
ind60 =~ x1 + x2 + x3
dem60 =~ y1 + y2 + y3 + y4
dem65 =~ y5 + y6 + y7 + y8
dem60 ~ a*ind60
dem65 ~ c*ind60 + b*dem60
# errores autocorrelacionados: mismo indicador medido en 1960 y en 1965
y1 ~~ y5
y2 ~~ y4 + y6
y3 ~~ y7
y4 ~~ y8
y6 ~~ y8
# descomposicion del efecto de la industrializacion sobre la democracia de 1965
indirecto := a*b
total := c + a*b '
fit_pd2 <- sem(mod_pd2, data = PoliticalDemocracy)
kable(tabla_ajuste(fit_pd, fit_pd2,
etiquetas = c("sin errores correlacionados", "con errores correlacionados")),
caption = "El ajuste pasa de dudoso a muy bueno con seis parametros que la teoria de medicion exige")
El ajuste pasa de dudoso a muy bueno con seis parametros que la
teoria de medicion exige
| sin errores correlacionados |
72.46 |
41 |
0.002 |
0.953 |
0.938 |
0.101 |
0.055 |
TRUE |
| con errores correlacionados |
38.13 |
35 |
0.329 |
0.995 |
0.993 |
0.035 |
0.044 |
TRUE |
comparar(fit_pd, fit_pd2,
c("sin errores correlacionados", "con errores correlacionados"),
"Los seis errores correlacionados no son opcionales: su omision es rechazada")
Los seis errores correlacionados no son opcionales: su omision
es rechazada
| con errores correlacionados |
35 |
3158 |
3229 |
38.13 |
NA |
NA |
NA |
| sin errores correlacionados |
41 |
3180 |
3238 |
72.46 |
34.34 |
6 |
0 |
Efectos directo,
indirecto y total
ef <- parameterEstimates(fit_pd2, standardized = TRUE)
ef <- subset(ef, op %in% c("~", ":="))[, c("lhs","rhs","label","est","se","pvalue","std.all")]
names(ef) <- c("Destino","Origen","Etiqueta","Estimado","EE","p","Estandarizado")
kable(ef, row.names = FALSE, digits = 3,
caption = "El grueso del efecto de la industrializacion sobre la democracia de 1965 es indirecto")
El grueso del efecto de la industrializacion sobre la
democracia de 1965 es indirecto
| dem60 |
ind60 |
a |
1.483 |
0.399 |
0.00 |
0.447 |
| dem65 |
ind60 |
c |
0.572 |
0.221 |
0.01 |
0.182 |
| dem65 |
dem60 |
b |
0.837 |
0.098 |
0.00 |
0.885 |
| indirecto |
a*b |
indirecto |
1.242 |
0.355 |
0.00 |
0.395 |
| total |
c+a*b |
total |
1.814 |
0.374 |
0.00 |
0.578 |
La lectura sustantiva: de un efecto total estandarizado de 0.578, la
parte indirecta (0.395) es 68% del total. La
industrializacion de 1960 no produce democracia en 1965 por si sola: la
produce sobre todo porque ya habia producido democracia en 1960, y la
democracia es altamente persistente (b estandarizado =
0.885, casi un techo).
Conclusiones del
ejercicio 2
- El mal ajuste inicial no era del modelo
estructural, era del modelo de medicion. Las flechas entre
latentes estaban bien; lo que faltaba era reconocer que el mismo
indicador medido dos veces arrastra su propio error.
- Los seis parametros que agregue no se justifican por su MI sino por
el diseno del estudio: son datos longitudinales con
indicadores repetidos. Ese es el caso donde liberar covarianzas
residuales es obligatorio, no oportunista.
- La descomposicion directo / indirecto cambia la conclusion de
politica publica: industrializar hoy tiene efecto sobre la democracia
futura principalmente a traves de la democracia
presente, es decir, hay dependencia de la trayectoria.
Ejercicio 3: bienestar
de los colaboradores
d <- read.csv("datos/datos_sem.csv")
c(observaciones = nrow(d), variables = ncol(d), valores_faltantes = sum(is.na(d)))
## observaciones variables valores_faltantes
## 223 51 0
La base tiene 223 colaboradores, sin valores faltantes. Las escalas
de recuperacion y energia van de 1 a 7 y la de engagement de 0 a 7.
Nota de verificacion. La descripcion de instrumentos
nombra los items de energia recuperada como REG01–REG10 y marca REG01,
REG09 y REG10 como eliminados; la base los trae como EN01–EN08 sin EN03.
La correspondencia exacta entre las dos numeraciones no esta
documentada, asi que trabajo con los siete items tal como vienen y
no asumo que EN0k sea REG0k. Igual conviene confirmarlo
con el profesor. La misma hoja indica que la escala de engagement es
“Nunca = 0, Casi nunca = 2, …” (sin el 1), pero la base si contiene
unos; lo trato como escala continua de 0 a 7.
Parte 1: analisis
factorial confirmatorio de segundo orden de las experiencias de
recuperacion
El modelo de primer
orden con los 31 items no pasa
Las experiencias de recuperacion se miden con cuatro dominios:
desapego psicologico, relajacion, maestria y control sobre el tiempo
libre.
items_rec <- list(
DESAPEGO = grep("^RPD", names(d), value = TRUE),
RELAJACION = grep("^RRE", names(d), value = TRUE),
MAESTRIA = grep("^RMA", names(d), value = TRUE),
CONTROL = grep("^RCO", names(d), value = TRUE))
sapply(items_rec, length)
## DESAPEGO RELAJACION MAESTRIA CONTROL
## 9 7 9 6
# arma la sintaxis de lavaan a partir de la lista de items
sintaxis <- function(lista) {
paste(mapply(function(nombre, its) paste0(nombre, " =~ ", paste(its, collapse = " + ")),
names(lista), lista), collapse = "\n")
}
fit_r1 <- cfa(sintaxis(items_rec), data = d, estimator = "MLR")
kable(tabla_ajuste(fit_r1, etiquetas = "4 factores, 31 items"),
caption = "Ningun criterio se cumple: hay que depurar")
Ningun criterio se cumple: hay que depurar
| 4 factores, 31 items |
1215 |
428 |
0 |
0.888 |
0.879 |
0.091 |
0.071 |
TRUE |
El diagnostico: items casi identicos entre si y un item que
carga en el factor equivocado
| RPD06 |
|
RPD08 |
109.27 |
1.232 |
0.758 |
| RPD09 |
|
RPD10 |
96.96 |
0.840 |
0.813 |
| RMA02 |
|
RMA03 |
47.44 |
0.812 |
0.504 |
| CONTROL |
=~ |
RMA06 |
44.90 |
0.437 |
0.455 |
| RPD02 |
|
RPD07 |
41.02 |
0.544 |
0.500 |
| RRE02 |
|
RRE03 |
33.78 |
0.298 |
0.468 |
| RELAJACION |
=~ |
RMA06 |
32.24 |
0.479 |
0.389 |
| RRE04 |
|
RRE05 |
30.91 |
0.216 |
0.511 |
El diagnostico es claro y tiene sentido leyendo los reactivos:
RPD06 ~~ RPD08 (MI = 109): “A proposito no hice, ni
revise nada de mi trabajo” y “Con toda intencion no hice nada sobre mi
trabajo” son la misma frase.
RPD09 ~~ RPD10: “Logre desligarme de mis
responsabilidades laborales” y “Me deslinde de mis actividades
laborales”, igual.
CONTROL =~ RMA06: “Utilice mi tiempo en actividades
diferentes” habla de como dispongo de mi tiempo, no de
retarme a aprender. Esta en el factor equivocado.
Esto no es ruido estadistico: es redundancia de
redaccion en el instrumento. Dos items que dicen lo mismo
comparten varianza que ningun factor comun puede explicar, y el modelo
lo registra como desajuste.
Una regla de
depuracion explicita, con piso de tres items por factor
Depurar a ojo es donde se cuela el sesgo. Escribo la regla como
funcion para que sea auditable y para que el orden de eliminacion no
dependa de mi criterio del momento:
# Regla, en este orden de prioridad:
# 1. carga estandarizada < .70 -> el item no mide el factor
# 2. carga cruzada con MI > 20 -> el item mide otro factor
# 3. residuales correlacionados con MI>20 -> redundancia: cae el de menor carga
# Restriccion dura: ningun factor puede quedar con menos de 3 items, porque
# un factor de 2 indicadores no se identifica por si solo y el constructo se vacia.
factor_de <- function(lista, item) names(lista)[sapply(lista, function(v) item %in% v)][1]
protegido <- function(lista, item, min_items) length(lista[[factor_de(lista, item)]]) <= min_items
depurar <- function(lista, datos, max_iter = 15, min_items = 3,
corte = c(cfi = .95, rmsea = .06, srmr = .08)) {
traza <- NULL
for (k in 0:max_iter) {
fit <- cfa(sintaxis(lista), data = datos, estimator = "MLR")
fm <- fitMeasures(fit, IDX)
fila <- data.frame(paso = k, items = sum(lengths(lista)),
chisq = round(fm[["chisq"]], 1), gl = fm[["df"]],
CFI = round(fm[["cfi"]], 3), TLI = round(fm[["tli"]], 3),
RMSEA = round(fm[["rmsea"]], 3), SRMR = round(fm[["srmr"]], 3),
eliminado = NA_character_, motivo = NA_character_)
if (fm[["cfi"]] >= corte["cfi"] && fm[["rmsea"]] <= corte["rmsea"] &&
fm[["srmr"]] <= corte["srmr"]) { traza <- rbind(traza, fila); break }
ld <- subset(standardizedSolution(fit), op == "=~")
mi <- modindices(fit)
cand <- NA_character_; motivo <- NA_character_
baja <- ld[order(ld$est.std), ]
baja <- baja[baja$est.std < .70 & !sapply(baja$rhs, protegido, lista = lista,
min_items = min_items), ]
if (nrow(baja) > 0) {
cand <- baja$rhs[1]; motivo <- sprintf("carga %.2f < .70", baja$est.std[1])
}
if (is.na(cand)) {
cc <- subset(mi, op == "=~" & mi > 20); cc <- cc[order(-cc$mi), ]
cc <- cc[!sapply(cc$rhs, protegido, lista = lista, min_items = min_items), ]
if (nrow(cc) > 0) {
cand <- cc$rhs[1]; motivo <- sprintf("carga cruzada en %s (MI=%.0f)", cc$lhs[1], cc$mi[1])
}
}
if (is.na(cand)) {
rr <- subset(mi, op == "~~" & lhs != rhs & mi > 20); rr <- rr[order(-rr$mi), ]
for (i in seq_len(nrow(rr))) {
par <- c(rr$lhs[i], rr$rhs[i])
par <- par[order(ld$est.std[match(par, ld$rhs)])] # primero el de menor carga
libre <- par[!sapply(par, protegido, lista = lista, min_items = min_items)]
if (length(libre) > 0) {
cand <- libre[1]
motivo <- sprintf("redundante con %s (MI=%.0f)", setdiff(par, cand), rr$mi[i])
break
}
}
}
if (is.na(cand)) {
fila$motivo <- "sin candidatos elegibles: se detiene"
traza <- rbind(traza, fila); break
}
fila$eliminado <- cand; fila$motivo <- motivo
traza <- rbind(traza, fila)
lista[[factor_de(lista, cand)]] <- setdiff(lista[[factor_de(lista, cand)]], cand)
}
list(items = lista, traza = traza, fit = fit)
}
dep_rec <- depurar(items_rec, d)
kable(dep_rec$traza, row.names = FALSE,
caption = "Traza completa de la depuracion: que se elimino, en que paso y por que")
Traza completa de la depuracion: que se elimino, en que paso y
por que
| 0 |
31 |
1215.4 |
428 |
0.888 |
0.879 |
0.091 |
0.071 |
RMA06 |
carga 0.58 < .70 |
| 1 |
30 |
1117.6 |
399 |
0.896 |
0.887 |
0.090 |
0.057 |
RRE10 |
carga 0.70 < .70 |
| 2 |
29 |
1074.0 |
371 |
0.896 |
0.886 |
0.092 |
0.057 |
RPD06 |
redundante con RPD08 (MI=109) |
| 3 |
28 |
910.7 |
344 |
0.912 |
0.903 |
0.086 |
0.056 |
RPD09 |
redundante con RPD10 (MI=102) |
| 4 |
27 |
781.3 |
318 |
0.924 |
0.916 |
0.081 |
0.057 |
RMA02 |
redundante con RMA03 (MI=46) |
| 5 |
26 |
695.5 |
293 |
0.931 |
0.924 |
0.078 |
0.056 |
RRE02 |
redundante con RRE03 (MI=34) |
| 6 |
25 |
645.6 |
269 |
0.932 |
0.925 |
0.079 |
0.055 |
RRE04 |
carga cruzada en MAESTRIA (MI=23) |
| 7 |
24 |
552.3 |
246 |
0.941 |
0.934 |
0.075 |
0.050 |
RRE03 |
redundante con RRE05 (MI=25) |
| 8 |
23 |
474.5 |
224 |
0.949 |
0.943 |
0.071 |
0.050 |
RPD07 |
redundante con RPD02 (MI=23) |
| 9 |
22 |
426.0 |
203 |
0.952 |
0.945 |
0.070 |
0.049 |
RMA03 |
redundante con RMA05 (MI=20) |
| 10 |
21 |
361.6 |
183 |
0.959 |
0.953 |
0.066 |
0.047 |
NA |
sin candidatos elegibles: se detiene |
Instrumento depurado
| DESAPEGO |
6 |
RPD01, RPD02, RPD03, RPD05, RPD08, RPD10 |
| RELAJACION |
3 |
RRE05, RRE06, RRE07 |
| MAESTRIA |
6 |
RMA04, RMA05, RMA07, RMA08, RMA09, RMA10 |
| CONTROL |
6 |
RCO02, RCO03, RCO04, RCO05, RCO06, RCO07 |
De 31 items quedan 21. Se eliminaron: RPD06, RPD07, RPD09, RRE02,
RRE03, RRE04, RRE10, RMA02, RMA03, RMA06.
La depuracion
redescubre lo que los autores del instrumento ya sabian
Este es el control de calidad que le da credibilidad al
procedimiento. La hoja de instrumentos marca como (eliminated)
varios items que sin embargo siguen en la base: RPD01,
RPD06, RMA02 y RMA06. Si mi regla es buena, deberia volver a
encontrarlos sin haberlos visto:
Coincidencia entre la depuracion ciega y las eliminaciones
documentadas
| RPD01 |
eliminado |
lo conserva |
| RPD06 |
eliminado |
tambien lo elimina |
| RMA02 |
eliminado |
tambien lo elimina |
| RMA06 |
eliminado |
tambien lo elimina |
Tres de cuatro coinciden. El unico que conservo es RPD01 (“Me olvide
del trabajo”), que en esta muestra carga 0.811 y no viola ningun
criterio. Que una regla mecanica reproduzca decisiones que se tomaron
por juicio de expertos es la mejor evidencia de que no estoy solo
persiguiendo indices.
El modelo de
segundo orden: los cuatro dominios son facetas de un mismo
constructo
Hasta aqui tengo cuatro factores correlacionados. La pregunta del
ejercicio es si existe un factor superior, experiencias de
recuperacion, que explique por que esos cuatro
correlacionan. Es una hipotesis mas fuerte y por lo tanto mas facil de
refutar: el modelo de segundo orden reproduce las seis correlaciones
entre dominios con solo cuatro cargas, asi que gasta dos grados de
libertad menos.
mod_seg <- paste(sintaxis(dep_rec$items),
"\n RECUPERACION =~ DESAPEGO + RELAJACION + MAESTRIA + CONTROL")
fit_seg <- cfa(mod_seg, data = d, estimator = "MLR")
kable(tabla_ajuste(dep_rec$fit, fit_seg,
etiquetas = c("1er orden: 4 factores correlacionados", "2o orden: RECUPERACION")),
caption = "El factor de segundo orden no cuesta ajuste")
El factor de segundo orden no cuesta ajuste
| 1er orden: 4 factores correlacionados |
361.6 |
183 |
0 |
0.959 |
0.953 |
0.066 |
0.047 |
TRUE |
| 2o orden: RECUPERACION |
368.0 |
185 |
0 |
0.958 |
0.953 |
0.067 |
0.055 |
TRUE |
comparar(dep_rec$fit, fit_seg,
c("1er orden: 4 factores correlacionados", "2o orden: RECUPERACION"),
"La estructura jerarquica no empeora el modelo de forma detectable")
La estructura jerarquica no empeora el modelo de forma
detectable
| 1er orden: 4 factores correlacionados |
183 |
14529 |
14692 |
361.6 |
NA |
NA |
NA |
| 2o orden: RECUPERACION |
185 |
14531 |
14688 |
368.0 |
5.712 |
2 |
0.0575 |
Cargas de segundo orden: los cuatro dominios pertenecen al
mismo constructo
| DESAPEGO |
0.664 |
0.045 |
0 |
| RELAJACION |
0.915 |
0.039 |
0 |
| MAESTRIA |
0.632 |
0.059 |
0 |
| CONTROL |
0.836 |
0.043 |
0 |
La diferencia de chi-cuadrada con 2 grados de libertad no es
significativa (p = 0.057): imponer la estructura jerarquica no
empeora el modelo de forma detectable. Las cuatro cargas son
significativas, pero desiguales: relajacion (0.915) y control (0.836)
son casi sinonimos del constructo general, mientras desapego (0.664) y
maestria (0.632) conservan bastante identidad propia. Traducido: quien
se recupera bien casi siempre se relaja y controla su tiempo, pero
desconectarse mentalmente y buscar retos son cosas que algunas
personas hacen y otras no, con relativa independencia de su
nivel general de recuperacion.
Parte 2: analisis
factorial confirmatorio del constructo de energia recuperada
items_en <- grep("^EN0", names(d), value = TRUE)
fit_en <- cfa(paste0("ENERGIA =~ ", paste(items_en, collapse = " + ")),
data = d, estimator = "MLR")
kable(tabla_ajuste(fit_en, etiquetas = "ENERGIA unidimensional, 7 items"),
caption = "CFI, TLI y SRMR excelentes; RMSEA fuera de criterio")
CFI, TLI y SRMR excelentes; RMSEA fuera de criterio
| ENERGIA unidimensional, 7 items |
47.22 |
14 |
0 |
0.986 |
0.978 |
0.103 |
0.012 |
TRUE |
kable(cargas(fit_en), row.names = FALSE, digits = 3,
caption = "Las siete cargas por arriba de .89")
Las siete cargas por arriba de .89
| ENERGIA |
EN01 |
0.893 |
0 |
| ENERGIA |
EN04 |
0.924 |
0 |
| ENERGIA |
EN07 |
0.928 |
0 |
| ENERGIA |
EN02 |
0.933 |
0 |
| ENERGIA |
EN05 |
0.939 |
0 |
| ENERGIA |
EN06 |
0.940 |
0 |
| ENERGIA |
EN08 |
0.946 |
0 |
Los siete items se agrupan en una sola dimension, y
de forma contundente: la carga mas baja es 0.893 y el SRMR es 0.012,
practicamente cero. La respuesta a la pregunta del ejercicio es si.
El RMSEA de 0.103 parece contradecirlo. No lo hace, y vale la pena
entender por que en lugar de “arreglarlo”:
dep_en <- depurar(list(ENERGIA = items_en), d)
kable(dep_en$traza, row.names = FALSE,
caption = "La regla de depuracion no encuentra un solo item que eliminar")
La regla de depuracion no encuentra un solo item que
eliminar
| 0 |
7 |
47.2 |
14 |
0.986 |
0.978 |
0.103 |
0.012 |
NA |
sin candidatos elegibles: se detiene |
Ningun item tiene carga baja, ninguno carga en otro factor, y el
residual correlacionado mas grande tiene MI de 12, por debajo del
umbral. No hay nada que depurar. El RMSEA alto es
consecuencia de su formula: penaliza por grado de libertad, y con solo
14 grados de libertad y cargas tan altas, cualquier discrepancia minima
se amplifica. Es el problema conocido de RMSEA en modelos pequenios
(Kenny, Kaniskan y McCoach, 2015). Forzar la mejora eliminando items
buenos seria maquillar el indice a costa del constructo.
Lo que si me preocupa es lo contrario: cargas de .89
a .95 entre siete reactivos sugieren que el instrumento pregunta lo
mismo siete veces (“me siento renovado”, “me siento como nuevo”,
“recupere mi energia”). Mide bien, pero es ineficiente: tres items
probablemente darian la misma informacion.
Parte 3: analisis de
senderos con la energia recuperada como mediadora
Construccion de los
compuestos
for (nm in names(dep_rec$items)) d[[nm]] <- rowMeans(d[, dep_rec$items[[nm]]])
d$RECUP <- rowMeans(d[, names(dep_rec$items)]) # promedio de los 4 dominios
d$ENER <- rowMeans(d[, items_en])
items_eng <- c("EVI01","EVI02","EVI03","EDE01","EDE02","EDE03","EAB01","EAB02","EAB03")
d$ENGA <- rowMeans(d[, items_eng])
kable(round(cor(d[, c("DESAPEGO","RELAJACION","MAESTRIA","CONTROL","RECUP","ENER","ENGA")]), 2),
caption = "Matriz de correlaciones de los compuestos")
Matriz de correlaciones de los compuestos
| DESAPEGO |
1.00 |
0.58 |
0.31 |
0.56 |
0.77 |
0.58 |
0.40 |
| RELAJACION |
0.58 |
1.00 |
0.56 |
0.70 |
0.88 |
0.65 |
0.43 |
| MAESTRIA |
0.31 |
0.56 |
1.00 |
0.51 |
0.74 |
0.55 |
0.39 |
| CONTROL |
0.56 |
0.70 |
0.51 |
1.00 |
0.85 |
0.71 |
0.48 |
| RECUP |
0.77 |
0.88 |
0.74 |
0.85 |
1.00 |
0.77 |
0.53 |
| ENER |
0.58 |
0.65 |
0.55 |
0.71 |
0.77 |
1.00 |
0.60 |
| ENGA |
0.40 |
0.43 |
0.39 |
0.48 |
0.53 |
0.60 |
1.00 |
Cada dominio pesa igual en RECUP (promedio de promedios,
no promedio de items), para que desapego con seis items no domine a
relajacion con tres.
Camino 2: abrir la
recuperacion en sus cuatro dominios
mod_dom <- ' ENER ~ a1*DESAPEGO + a2*RELAJACION + a3*MAESTRIA + a4*CONTROL
ENGA ~ b*ENER
i_desapego := a1*b
i_relajacion := a2*b
i_maestria := a3*b
i_control := a4*b '
fit_dom <- sem(mod_dom, data = d, se = "bootstrap", bootstrap = 1000)
mod_dom_p <- ' ENER ~ a1*DESAPEGO + a2*RELAJACION + a3*MAESTRIA + a4*CONTROL
ENGA ~ b*ENER + c1*DESAPEGO + c2*RELAJACION + c3*MAESTRIA + c4*CONTROL '
fit_dom_p <- sem(mod_dom_p, data = d)
kable(tabla_ajuste(fit_dom, fit_dom_p,
etiquetas = c("mediacion completa (gl=4)", "mediacion parcial (saturado)")),
caption = "El modelo de mediacion completa ajusta casi perfecto con 4 grados de libertad")
El modelo de mediacion completa ajusta casi perfecto con 4
grados de libertad
| mediacion completa (gl=4) |
4.33 |
4 |
0.363 |
0.999 |
0.998 |
0.019 |
0.023 |
TRUE |
| mediacion parcial (saturado) |
0.00 |
0 |
NA |
1.000 |
1.000 |
0.000 |
0.000 |
TRUE |
comparar(fit_dom, fit_dom_p,
c("mediacion completa", "mediacion parcial"),
"Quitar los cuatro caminos directos no empeora el modelo")
Quitar los cuatro caminos directos no empeora el
modelo
| mediacion parcial |
0 |
1392 |
1430 |
0.00 |
NA |
NA |
NA |
| mediacion completa |
4 |
1389 |
1412 |
4.33 |
4.33 |
4 |
0.3632 |
La chi-cuadrada de 4.33 con 4 grados de libertad no es
significativa (p = 0.363). Eliminar los cuatro caminos directos
no empeora el modelo. Y el modelo saturado explica por que:
Ninguno de los cuatro caminos directos hacia engagement es
significativo
| ENGA |
ENER |
0.410 |
0.072 |
0.000 |
0.477 |
| ENGA |
DESAPEGO |
0.055 |
0.060 |
0.365 |
0.063 |
| ENGA |
RELAJACION |
-0.016 |
0.081 |
0.842 |
-0.017 |
| ENGA |
MAESTRIA |
0.077 |
0.062 |
0.215 |
0.084 |
| ENGA |
CONTROL |
0.080 |
0.086 |
0.354 |
0.079 |
Ninguno de los cuatro dominios llega al engagement por su cuenta.
Toda la relacion pasa por la energia recuperada.
Efectos indirectos,
con intervalos bootstrap
ef3 <- parameterEstimates(fit_dom, boot.ci.type = "perc", standardized = TRUE)
ef3 <- subset(ef3, op %in% c("~", ":="))[, c("lhs","rhs","label","est","se",
"pvalue","ci.lower","ci.upper","std.all")]
kable(ef3, row.names = FALSE, digits = 3,
col.names = c("Destino","Origen","Etiqueta","Est","EE","p","IC 2.5%","IC 97.5%","Estand."),
caption = "Efectos del modelo de mediacion completa (1000 remuestreos bootstrap)")
Efectos del modelo de mediacion completa (1000 remuestreos
bootstrap)
| ENER |
DESAPEGO |
a1 |
0.216 |
0.060 |
0.000 |
0.108 |
0.347 |
0.215 |
| ENER |
RELAJACION |
a2 |
0.164 |
0.080 |
0.040 |
-0.006 |
0.310 |
0.148 |
| ENER |
MAESTRIA |
a3 |
0.216 |
0.067 |
0.001 |
0.102 |
0.357 |
0.202 |
| ENER |
CONTROL |
a4 |
0.452 |
0.086 |
0.000 |
0.280 |
0.605 |
0.383 |
| ENGA |
ENER |
b |
0.519 |
0.065 |
0.000 |
0.397 |
0.651 |
0.603 |
| i_desapego |
a1*b |
i_desapego |
0.112 |
0.033 |
0.001 |
0.056 |
0.190 |
0.130 |
| i_relajacion |
a2*b |
i_relajacion |
0.085 |
0.043 |
0.046 |
-0.003 |
0.167 |
0.089 |
| i_maestria |
a3*b |
i_maestria |
0.112 |
0.038 |
0.003 |
0.049 |
0.192 |
0.122 |
| i_control |
a4*b |
i_control |
0.235 |
0.057 |
0.000 |
0.128 |
0.349 |
0.231 |
r2 <- inspect(fit_dom, "r2")
kable(data.frame(Variable = names(r2), R2 = round(as.numeric(r2), 3)),
row.names = FALSE, caption = "Varianza explicada")
Varianza explicada
| ENER |
0.602 |
| ENGA |
0.364 |
El producto de coeficientes no se distribuye normal, por eso el
intervalo bootstrap y no el error estandar de Wald. Y la diferencia
importa: relajacion tiene p = 0.046 por Wald pero su
intervalo bootstrap (-0.003 a 0.167) incluye el cero.
Con el criterio mas exigente, que es el correcto aqui, su efecto no esta
demostrado.
Orden de importancia por efecto indirecto estandarizado:
Control sobre el tiempo libre es, por mucho, el dominio que mas
rinde
| i_control |
0.231 |
0.128 |
0.349 |
efecto sostenido |
| i_desapego |
0.130 |
0.056 |
0.190 |
efecto sostenido |
| i_maestria |
0.122 |
0.049 |
0.192 |
efecto sostenido |
| i_relajacion |
0.089 |
-0.003 |
0.167 |
no distinguible de cero |
Lectura para la
organizacion
El resultado tiene una implicacion practica concreta y algo incomoda
para las areas de recursos humanos: el engagement no se compra
con actividades de bienestar. Ninguna de las cuatro
experiencias de recuperacion mueve el engagement directamente. Lo mueven
solo en la medida en que el colaborador efectivamente recupera
energia. Un programa de yoga al que la gente asiste sin
desconectarse no cambia nada.
Y entre los cuatro dominios, el que mas rinde es control
sobre el tiempo libre (0.231), que no cuesta presupuesto:
cuesta politica de la empresa. Es la diferencia entre organizar
actividades para la gente y dejar que la gente decida como usa su
tiempo.
Parte 4: el modelo de
medicion
El modelo de senderos de la Parte 3 supone algo fuerte y falso: que
los compuestos miden sin error. Un promedio de items no es el
constructo. El modelo de medicion levanta ese supuesto poniendo cada
variable latente con sus indicadores.
kable(round(cor(d[, items_eng]), 2),
caption = "Los items de engagement: correlaciones que decaen segun la distancia en el cuestionario")
Los items de engagement: correlaciones que decaen segun la
distancia en el cuestionario
| EVI01 |
1.00 |
0.94 |
0.80 |
0.82 |
0.74 |
0.61 |
0.70 |
0.53 |
0.44 |
| EVI02 |
0.94 |
1.00 |
0.78 |
0.82 |
0.73 |
0.62 |
0.70 |
0.55 |
0.44 |
| EVI03 |
0.80 |
0.78 |
1.00 |
0.87 |
0.78 |
0.60 |
0.73 |
0.53 |
0.44 |
| EDE01 |
0.82 |
0.82 |
0.87 |
1.00 |
0.89 |
0.67 |
0.80 |
0.58 |
0.49 |
| EDE02 |
0.74 |
0.73 |
0.78 |
0.89 |
1.00 |
0.74 |
0.79 |
0.59 |
0.53 |
| EDE03 |
0.61 |
0.62 |
0.60 |
0.67 |
0.74 |
1.00 |
0.73 |
0.72 |
0.58 |
| EAB01 |
0.70 |
0.70 |
0.73 |
0.80 |
0.79 |
0.73 |
1.00 |
0.66 |
0.58 |
| EAB02 |
0.53 |
0.55 |
0.53 |
0.58 |
0.59 |
0.72 |
0.66 |
1.00 |
0.73 |
| EAB03 |
0.44 |
0.44 |
0.44 |
0.49 |
0.53 |
0.58 |
0.58 |
0.73 |
1.00 |
Antes de estimar hay que ver el problema. La matriz
no tiene la estructura de bloques que predice la teoria
de tres factores (vigor, dedicacion, absorcion). Tiene un
gradiente: cada item correlaciona mas con el que esta a
su lado en el cuestionario (EVI01–EVI02 = .94, EDE01–EDE02 = .89) y
menos conforme se aleja (EVI01–EAB03 = .44). EDE01 correlaciona mas con
EVI03 (.87), que es de otro factor, que con EDE03 (.67), que es del
suyo. Eso es un efecto de proximidad en el instrumento,
no la estructura del constructo.
mod_eng3 <- ' VIGOR =~ EVI01 + EVI02 + EVI03
DEDICACION =~ EDE01 + EDE02 + EDE03
ABSORCION =~ EAB01 + EAB02 + EAB03 '
fit_eng3 <- cfa(mod_eng3, data = d, estimator = "MLR")
fit_eng2 <- cfa(paste(mod_eng3, "\n ENGAGEMENT =~ VIGOR + DEDICACION + ABSORCION"),
data = d, estimator = "MLR")
kable(tabla_ajuste(fit_eng3, fit_eng2,
etiquetas = c("3 factores correlacionados", "2o orden: ENGAGEMENT")),
caption = "El modelo de segundo orden entrega una solucion INADMISIBLE")
El modelo de segundo orden entrega una solucion
INADMISIBLE
| 3 factores correlacionados |
271.2 |
24 |
0 |
0.889 |
0.833 |
0.215 |
0.07 |
TRUE |
| 2o orden: ENGAGEMENT |
271.2 |
24 |
0 |
0.889 |
0.833 |
0.215 |
0.07 |
FALSE |
Una carga estandarizada mayor que 1: caso Heywood
| Carga DEDICACION en ENGAGEMENT |
1.013 |
| Correlacion DEDICACION–ABSORCION |
0.913 |
| Correlacion VIGOR–DEDICACION |
0.881 |
Aqui esta el punto central de toda la actividad, y aparece
antes de mirar ningun indice de ajuste: la carga
estandarizada de dedicacion sobre engagement es mayor que
1, lo que implica una varianza de error negativa. Es un
caso Heywood: un resultado imposible. Los indices de
ajuste del modelo de segundo orden son identicos a los del de tres
factores, asi que si me hubiera guiado solo por CFI y RMSEA no habria
notado nada. Un modelo con una estimacion inadmisible se
descarta, sin importar como ajuste.
La causa es visible en la tabla: dedicacion y absorcion correlacionan
.91 y vigor con dedicacion .88. A ese nivel los tres factores no son
distinguibles, y el factor de segundo orden intenta explicar mas
covarianza de la que existe.
mod_medicion <- '
DESAPEGO =~ RPD01 + RPD02 + RPD03 + RPD05 + RPD08 + RPD10
RELAJACION =~ RRE05 + RRE06 + RRE07
MAESTRIA =~ RMA04 + RMA05 + RMA07 + RMA08 + RMA09 + RMA10
CONTROL =~ RCO02 + RCO03 + RCO04 + RCO05 + RCO06 + RCO07
ENERGIA =~ EN01 + EN02 + EN04 + EN05 + EN06 + EN07 + EN08
ENGAGEMENT =~ EVI01 + EVI02 + EVI03 + EDE01 + EDE02 + EDE03 + EAB01 + EAB02 + EAB03
RECUPERACION =~ DESAPEGO + RELAJACION + MAESTRIA + CONTROL
# los dos pares casi identicos que detecto el diagnostico de proximidad
EVI01 ~~ EVI02
EAB02 ~~ EAB03
RECUPERACION ~~ ENERGIA + ENGAGEMENT
ENERGIA ~~ ENGAGEMENT '
fit_med <- cfa(mod_medicion, data = d, estimator = "MLR")
kable(tabla_ajuste(fit_med, etiquetas = "modelo de medicion completo"),
caption = "Ajuste aceptable y solucion admisible")
Ajuste aceptable y solucion admisible
| modelo de medicion completo |
1290 |
620 |
0 |
0.93 |
0.925 |
0.07 |
0.059 |
TRUE |
El modelo de medicion completo estima 83 parametros con 223
observaciones. Ajusta de forma aceptable pero no buena
(CFI 0.93, RMSEA 0.07), y el desajuste esta concentrado en el bloque de
engagement:
Los residuales mas grandes siguen siendo de los items de
engagement
| EDE03 |
|
EAB02 |
31.35 |
0.342 |
| EDE01 |
|
EDE03 |
25.83 |
-0.253 |
| EDE03 |
|
EAB01 |
21.32 |
0.294 |
| RCO03 |
|
RCO06 |
20.77 |
-0.194 |
| DESAPEGO |
=~ |
RRE05 |
20.16 |
0.265 |
| DESAPEGO |
=~ |
EN01 |
19.36 |
0.232 |
El modelo
estructural latente confirma la conclusion de la Parte 3
base_med <- sub("RECUPERACION ~~ ENERGIA \\+ ENGAGEMENT\n ENERGIA ~~ ENGAGEMENT", "",
mod_medicion)
fit_lat_c <- sem(paste(base_med, "
ENERGIA ~ a*RECUPERACION
ENGAGEMENT ~ b*ENERGIA
indirecto := a*b "), data = d, estimator = "MLR")
fit_lat_p <- sem(paste(base_med, "
ENERGIA ~ a*RECUPERACION
ENGAGEMENT ~ b*ENERGIA + cp*RECUPERACION
indirecto := a*b
total := cp + a*b "), data = d, estimator = "MLR")
kable(tabla_ajuste(fit_lat_c, fit_lat_p,
etiquetas = c("latente: mediacion completa", "latente: mediacion parcial")),
caption = "Mismo resultado que con compuestos: el camino directo no hace falta")
Mismo resultado que con compuestos: el camino directo no hace
falta
| latente: mediacion completa |
1294 |
621 |
0 |
0.929 |
0.924 |
0.07 |
0.063 |
TRUE |
| latente: mediacion parcial |
1290 |
620 |
0 |
0.930 |
0.925 |
0.07 |
0.059 |
TRUE |
comparar(fit_lat_c, fit_lat_p,
c("latente: mediacion completa", "latente: mediacion parcial"),
"Con variables latentes la conclusion no cambia")
Con variables latentes la conclusion no cambia
| latente: mediacion parcial |
620 |
24164 |
24447 |
1290 |
NA |
NA |
NA |
| latente: mediacion completa |
621 |
24166 |
24445 |
1294 |
2.205 |
1 |
0.1375 |
Efectos con variables latentes (mediacion parcial)
| ENERGIA |
RECUPERACION |
a |
1.433 |
0.144 |
0.000 |
0.835 |
| ENGAGEMENT |
ENERGIA |
b |
0.379 |
0.129 |
0.003 |
0.428 |
| ENGAGEMENT |
RECUPERACION |
cp |
0.353 |
0.228 |
0.121 |
0.233 |
| indirecto |
a*b |
indirecto |
0.543 |
0.195 |
0.005 |
0.357 |
| total |
cp+a*b |
total |
0.897 |
0.132 |
0.000 |
0.590 |
La conclusion sustantiva no depende de como se mida: es
robusta
| Compuestos (Parte 3) |
0.158 |
0.110 |
0.374 |
| Latente (Parte 4) |
0.233 |
0.121 |
0.403 |
Corregir por error de medicion sube la magnitud de
los efectos, como se espera (las correlaciones atenuadas por falta de
fiabilidad se desatenuan), pero no cambia la conclusion: el camino
directo sigue sin ser significativo y la varianza explicada del
engagement es practicamente la misma. La mediacion completa se sostiene
con las dos especificaciones.
Conclusiones del
ejercicio 3
- El instrumento de recuperacion tenia grasa. De 31
items quedaron
- Lo que se elimino no fueron items malos sino items
repetidos: pares que dicen lo mismo con otras palabras.
La regla de depuracion redescubrio tres de las cuatro eliminaciones que
ya habian documentado los autores.
- El constructo de segundo orden se sostiene. Los
cuatro dominios son facetas de una sola capacidad de recuperacion, y
renunciar a las seis correlaciones libres a cambio de cuatro cargas no
cuesta ajuste (p = 0.057).
- La energia recuperada es unidimensional, con cargas
de .89 a .95. El RMSEA alto es un artefacto de tener pocos grados de
libertad, no evidencia de mala estructura, y no se corrige tirando
items.
- La mediacion es completa. Las experiencias de
recuperacion no tocan el engagement por su cuenta: lo tocan solo a
traves de la energia efectivamente recuperada (p = 0.363 para la
restriccion de mediacion completa, y ningun camino directo
significativo).
- Control sobre el tiempo libre es la palanca. Efecto
indirecto estandarizado de 0.231, casi el doble del siguiente.
Relajacion, en cambio, no sobrevive al intervalo bootstrap.
- La escala de engagement no replica su estructura teorica en
esta muestra. El modelo de segundo orden produce un caso
Heywood, y el patron de correlaciones apunta a un efecto de proximidad
en el cuestionario. Este es el hallazgo que conecta directamente con el
ejercicio 4.
Ejercicio 4: Behson,
Eddy y Lorenzet (2000)
Los dos modelos que
compiten
Behson, Eddy y Lorenzet (2000) juntan 13 estudios sobre el Modelo de
Caracteristicas del Puesto de Hackman y Oldham en un meta-analisis,
arman con el una matriz de correlaciones y estiman sobre ella dos
modelos rivales:
Los dos modelos del articulo
| Modelo 1: JCM original (3 etapas) |
5 caracteristicas del puesto -> 3 estados
psicologicos criticos -> 3 resultados |
14 |
mediacion completa por los estados psicologicos |
| Modelo 2: JCM como se prueba (2 etapas) |
5 caracteristicas del puesto -> 3 resultados (los
estados se omiten) |
15 |
efecto directo, sin mecanismo intermedio |
El Modelo 1 es la teoria original: las caracteristicas del puesto
(variedad, significado, identidad, autonomia, retroalimentacion)
producen tres estados psicologicos criticos
(significado experimentado, responsabilidad experimentada, conocimiento
de resultados) y son estos los que producen satisfaccion, satisfaccion
de crecimiento y motivacion interna. El Modelo 2 es como casi toda la
literatura posterior lo ha probado: brincandose los estados
psicologicos.
Lo que reporta el
articulo
Tabla 4 del articulo. El Modelo 2 gana en GFI, CFI, AIC y
CAIC
| Chi-cuadrada (gl) |
124.25 (25) |
12.09 (3) |
| RMSEA |
.14 |
.16 |
| GFI |
.91 |
.99 |
| CFI |
.89 |
.98 |
| Caminos significativos |
12 de 14 |
7 de 15 |
| R2 satisfaccion |
.42 |
.37 |
| R2 crecimiento |
.42 |
.43 |
| R2 motivacion |
.38 |
.32 |
| AIC |
294.48 |
80.09 |
| CAIC |
446.29 |
227.56 |
Los autores lo dicen sin rodeos: el AIC y el CAIC, que son los unicos
estadisticos que usan para comparar formalmente los dos modelos,
favorecen al Modelo 2. Y aun asi eligen el Modelo
1.
Replicacion: la
matriz del articulo esta publicada, asi que se puede verificar
La Tabla 2 del articulo publica la matriz de correlaciones
meta-analitica completa y las desviaciones estandar normativas de
Oldham, Hackman y Stepina (1979). Con eso se puede reconstruir la matriz
de covarianzas y volver a estimar los dos modelos.
v <- c("VAR","SIG","IDE","AUT","FBK","MEA","RES","KNO","SAT","GRO","MOT")
sdv <- c(1.57, 1.25, 1.44, 1.39, 1.34, 1.14, 0.96, 1.14, 1.07, 1.15, 0.77)
R <- diag(11); dimnames(R) <- list(v, v)
tri <- list(c(.41), c(.22,.20), c(.43,.32,.32), c(.35,.34,.26,.39),
c(.46,.45,.24,.42,.38), c(.34,.33,.27,.39,.34,.59),
c(.16,.23,.28,.29,.49,.40,.34), c(.35,.29,.22,.42,.36,.65,.49,.42),
c(.50,.38,.26,.54,.44,.65,.51,.40,.69),
c(.35,.33,.17,.30,.42,.57,.59,.25,.43,.50))
for (i in 2:11) { R[i, 1:(i-1)] <- tri[[i-1]]; R[1:(i-1), i] <- tri[[i-1]] }
S <- diag(sdv) %*% R %*% diag(sdv); dimnames(S) <- dimnames(R)
N <- 208 # los autores usan la mediana del tamanio de muestra, no la suma
mod_b1 <- '
MEA ~ VAR + SIG + IDE
RES ~ AUT
KNO ~ FBK
SAT ~ MEA + RES + KNO
GRO ~ MEA + RES + KNO
MOT ~ MEA + RES + KNO
MEA ~~ RES + KNO
RES ~~ KNO
SAT ~~ GRO + MOT
GRO ~~ MOT '
fit_b1 <- sem(mod_b1, sample.cov = S, sample.nobs = N, fixed.x = FALSE)
round(fitMeasures(fit_b1, c("chisq","df","cfi","rmsea","gfi")), 3)
## chisq df cfi rmsea gfi
## 106.967 25.000 0.884 0.126 0.943
round(inspect(fit_b1, "r2"), 3)
## MEA RES KNO SAT GRO MOT
## 0.205 0.082 0.187 0.419 0.418 0.382
El Modelo 1 se reproduce casi exactamente
| Grados de libertad |
25 |
25 |
| Caminos significativos |
12 de 14 |
12 de 14 |
| R2 satisfaccion |
.42 |
0.419 |
| R2 crecimiento |
.42 |
0.418 |
| R2 motivacion |
.38 |
0.382 |
La replicacion del Modelo 1 es practicamente exacta: mismos grados de
libertad, mismos 12 de 14 caminos significativos y las tres R2 coinciden
al segundo decimal. Eso valida que la matriz esta bien reconstruida y
que entendi la especificacion.
o8 <- c("VAR","SIG","IDE","AUT","FBK","SAT","GRO","MOT")
mod_b2 <- '
SAT ~ VAR + SIG + IDE + AUT + FBK
GRO ~ VAR + SIG + IDE + AUT + FBK
MOT ~ VAR + SIG + IDE + AUT + FBK '
# auto.cov.y = FALSE reproduce los 3 grados de libertad que reporta el articulo
fit_b2 <- sem(mod_b2, sample.cov = S[o8, o8], sample.nobs = N,
fixed.x = FALSE, auto.cov.y = FALSE)
round(fitMeasures(fit_b2, c("chisq","df","cfi","rmsea","gfi")), 3)
## chisq df cfi rmsea gfi
## 100.258 3.000 0.692 0.395 0.897
Nota de verificacion. Los grados de libertad
coinciden (3), pero la chi-cuadrada que obtengo es 100.26 contra los
12.09 publicados, y el CFI me da 0.692 contra .98. La razon es
identificable: con 3 grados de libertad las tres covarianzas entre los
residuales de los resultados estan fijas en cero, y satisfaccion con
crecimiento correlacionan .69 en la matriz publicada, asi que esa
restriccion tiene que producir un desajuste enorme. Si
se liberan esas tres covarianzas el modelo queda saturado (gl = 0,
ajuste perfecto). No existe una especificacion que de al mismo tiempo gl
= 3 y chi-cuadrada = 12.09 con la matriz que ellos publican. Dado que el
Modelo 1 si se reproduce, la inconsistencia esta en el reporte del
Modelo 2, no en mi reconstruccion. Conviene contrastarlo con el
profesor.
La comparacion por
AIC del articulo no es valida, y eso refuerza su propia decision
Independientemente del punto anterior, hay un problema mas grave con
el argumento cuantitativo del articulo. El AIC y el CAIC son el
unico criterio formal que usan para declarar superior al Modelo
2. Pero comparan dos modelos ajustados a conjuntos distintos de
variables observadas: el Modelo 1 usa 11 variables (66
momentos) y el Modelo 2 usa 8 (36 momentos). La verosimilitud de ambos
no esta en la misma escala.
# dos modelos de ajuste PERFECTO, uno con 11 variables y otro con 8
sat11 <- paste(apply(t(combn(v, 2)), 1, function(p) paste(p[1], "~~", p[2])), collapse = "\n")
fit_s11 <- sem(sat11, sample.cov = S, sample.nobs = N)
fit_s8 <- sem(paste(mod_b2, "\n SAT ~~ GRO + MOT \n GRO ~~ MOT"),
sample.cov = S[o8, o8], sample.nobs = N, fixed.x = FALSE)
kable(data.frame(
Modelo = c("Saturado, 11 variables (ajuste perfecto)",
"Saturado, 8 variables (ajuste perfecto)"),
chisq = c(0, 0), gl = c(0, 0),
AIC = round(c(fitMeasures(fit_s11, "aic"), fitMeasures(fit_s8, "aic")), 0)),
row.names = FALSE,
caption = "Dos modelos con ajuste identicamente perfecto y AIC separados por mas de mil puntos")
Dos modelos con ajuste identicamente perfecto y AIC separados
por mas de mil puntos
| Saturado, 11 variables (ajuste perfecto) |
0 |
0 |
6455 |
| Saturado, 8 variables (ajuste perfecto) |
0 |
0 |
4952 |
Los dos modelos de la tabla ajustan perfecto, y aun
asi sus AIC difieren en 1503 puntos. La diferencia no mide calidad de
ajuste: mide cuantas variables entraron al modelo. Un
modelo con menos variables siempre va a tener menor AIC, aunque sea peor
teoria. Por lo tanto el argumento “el AIC y el CAIC favorecen al Modelo
2” no sostiene lo que se le pide sostener.
Por que eligieron el
Modelo 1: la respuesta del articulo
Los autores no invocan el argumento anterior. Su razon es distinta y,
en mi lectura, mas fuerte todavia. La formulan asi: comparar modelos
rivales exige mas que comparar razones de ajuste, porque la
razonabilidad de los valores del modelo y su correspondencia con la
teoria son igual o mas importantes.
El hecho concreto que los decide esta en los coeficientes:
pb2 <- subset(parameterEstimates(fit_b2, standardized = TRUE), op == "~")
tres <- pb2[pb2$rhs %in% c("VAR","SIG","IDE"), ]
kable(tres[, c("lhs","rhs","est","se","pvalue","std.all")], row.names = FALSE, digits = 3,
col.names = c("Resultado","Caracteristica","Estimado","EE","p","Estandarizado"),
caption = "Modelo 2: los caminos desde variedad, significado e identidad hacia los resultados")
Modelo 2: los caminos desde variedad, significado e identidad
hacia los resultados
| SAT |
VAR |
0.093 |
0.048 |
0.056 |
0.136 |
| SAT |
SIG |
0.073 |
0.058 |
0.210 |
0.086 |
| SAT |
IDE |
0.035 |
0.048 |
0.460 |
0.048 |
| GRO |
VAR |
0.182 |
0.046 |
0.000 |
0.248 |
| GRO |
SIG |
0.099 |
0.055 |
0.071 |
0.108 |
| GRO |
IDE |
0.028 |
0.045 |
0.535 |
0.035 |
| MOT |
VAR |
0.078 |
0.035 |
0.026 |
0.159 |
| MOT |
SIG |
0.088 |
0.042 |
0.036 |
0.143 |
| MOT |
IDE |
0.005 |
0.035 |
0.885 |
0.009 |
En el Modelo 2, 6 de los 9 caminos que van de variedad de
habilidades, significado de la tarea e identidad de la tarea hacia los
resultados no son significativos. El articulo reporta 8
de 9; yo obtengo 6 de 9, con dos casos al filo. La conclusion es la
misma: si el Modelo 2 fuera cierto, enriquecer un puesto dandole
variedad y significado no serviria de nada. Eso contradice dos
decadas de investigacion sobre rediseno del trabajo.
El Modelo 1 resuelve la paradoja:
mod_b1_ind <- '
MEA ~ v*VAR + s*SIG + i*IDE
RES ~ AUT
KNO ~ FBK
SAT ~ m1*MEA + RES + KNO
GRO ~ m2*MEA + RES + KNO
MOT ~ m3*MEA + RES + KNO
MEA ~~ RES + KNO
RES ~~ KNO
SAT ~~ GRO + MOT
GRO ~~ MOT
variedad_sat := v*m1
variedad_crec := v*m2
significado_sat := s*m1
significado_crec := s*m2 '
fit_b1i <- sem(mod_b1_ind, sample.cov = S, sample.nobs = N, fixed.x = FALSE)
kable(subset(parameterEstimates(fit_b1i, standardized = TRUE), op == ":=")[
, c("lhs","est","se","pvalue","std.all")], row.names = FALSE, digits = 3,
col.names = c("Efecto indirecto","Estimado","EE","p","Estandarizado"),
caption = "En el Modelo 1 esos mismos caminos SI existen, pero pasan por el significado experimentado")
En el Modelo 1 esos mismos caminos SI existen, pero pasan por
el significado experimentado
| variedad_sat |
0.094 |
0.023 |
0 |
0.144 |
| variedad_crec |
0.099 |
0.024 |
0 |
0.142 |
| significado_sat |
0.095 |
0.027 |
0 |
0.116 |
| significado_crec |
0.101 |
0.028 |
0 |
0.114 |
Variedad y significado si afectan la satisfaccion y
el crecimiento, pero lo hacen a traves del significado
experimentado. Al borrar los estados psicologicos, el Modelo 2
no elimina un rodeo innecesario: elimina el mecanismo, y con el
desaparece el efecto.
Los autores eligen el Modelo 1, entonces, por cuatro razones
acumuladas:
- Los coeficientes del Modelo 2 contradicen la teoria
establecida. Un modelo cuyos parametros no tienen sentido
sustantivo no es utilizable, ajuste lo que ajuste.
- El Modelo 1 explica mas varianza en dos de los tres
resultados y tiene mejor proporcion de caminos significativos (12 de 14
contra 7 de 15).
- El mejor ajuste del Modelo 2 es en buena medida
mecanico. Con 3 grados de libertad esta a un paso de estar
saturado, y un modelo casi saturado casi no puede desajustar. Los 25
grados de libertad del Modelo 1 son una hipotesis mucho mas expuesta a
refutacion. De hecho el RMSEA, que es el unico indice de la tabla que
penaliza la falta de parsimonia, es peor en el Modelo 2
(.16 contra .14).
- El proposito del modelo es explicar, no solo
describir. Los estados psicologicos son lo unico sobre lo que
un gerente puede actuar con criterio: le dicen por que funciona
el rediseno del puesto y cuando no va a funcionar.
Conclusiones del
ejercicio 4: la leccion
Un indice de ajuste mide si el modelo reproduce la matriz de
covarianzas. No mide si el modelo es verdadero, ni si es util, ni
siquiera si es posible. Elegir modelo por CFI es como elegir un
pronostico por su R2 dentro de muestra.
Las tres verificaciones que este articulo me deja como rutina, en
este orden:
- Admisibilidad primero. Antes de leer un solo
indice, revisar que no haya varianzas negativas ni cargas estandarizadas
mayores que 1. En el ejercicio 3 esto descarto el modelo de engagement
de segundo orden antes de que su ajuste identico al de
tres factores me hiciera pasarlo por alto.
- Signo y magnitud de los coeficientes contra la
teoria. Un modelo que ajusta mejor pero dice que dar variedad
al trabajo no sirve, esta diciendo algo falso.
- Comparabilidad de la comparacion. Chi-cuadrada solo
entre modelos anidados; AIC solo entre modelos sobre las mismas
variables. En el ejercicio 3 esto me obligo a fijar el camino directo en
cero para poder contrastar algo, en vez de celebrar el CFI = 1 de un
modelo saturado.
Y la leccion de fondo, que es la que conecta los cuatro ejercicios:
borrar el mediador mejora el ajuste y destruye la
explicacion. El Modelo 2 de Behson ajusta mejor porque pide
menos; mi modelo de mediacion parcial de la Parte 3 ajustaba perfecto
porque no pedia nada. En los dos casos, el modelo que vale es el que se
atreve a afirmar el mecanismo y sobrevive a la prueba.
LS0tCnRpdGxlOiAiRWN1YWNpb25lcyBlc3RydWN0dXJhbGVzOiBlbCBhanVzdGUgbm8gZWxpZ2UgZWwgbW9kZWxvLCBsbyBlbGlnZSBsYSB0ZW9yaWEiCnN1YnRpdGxlOiAiQWN0aXZpZGFkIDMsIFBhcnRlIDEgLS0tIE1vZHVsbyAxIC0tLSBHZW5lcmFjaW9uIGRlIGVzY2VuYXJpb3MgZnV0dXJvcyBjb24KICBhbmFsaXRpY2EgKENELTMwMDFCKSIKYXV0aG9yOiAiUGF0cmljaW8gSGVybW9zaWxsbyAtLS0gQTAxNTY3MDM2IgpkYXRlOiAiMjYgZGUgYWdvc3RvIGRlIDIwMjYiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0aGVtZTogdW5pdGVkCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleAogICAgZGZfcHJpbnQ6IGthYmxlCmZvbnRzaXplOiAxMXB0Cmdlb21ldHJ5OiBtYXJnaW49Mi41Y20KaGVhZGVyLWluY2x1ZGVzOiB8CiAgXHVzZXBhY2thZ2V7ZmxvYXR9CiAgXGZsb2F0cGxhY2VtZW50e3RhYmxlfXtIfQogIFxmbG9hdHBsYWNlbWVudHtmaWd1cmV9e0h9Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIiwgZmlnLndpZHRoID0gNi41LCBmaWcuaGVpZ2h0ID0gNCwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5wb3MgPSAiSCIsIG91dC5leHRyYSA9ICIiKQpvcHRpb25zKHNjaXBlbiA9IDk5OSwgZGlnaXRzID0gNCkKbGlicmFyeShsYXZhYW4pCmxpYnJhcnkoa25pdHIpCnNldC5zZWVkKDIwMjYpCmBgYAoKIyBDb21vIGxlZXIgZXN0ZSBkb2N1bWVudG8KCkxvcyBjdWF0cm8gZWplcmNpY2lvcyBjb21wYXJ0ZW4gdW5hIHNvbGEgcHJlZ3VudGE6ICoqY3VhbmRvIGRvcyBtb2RlbG9zIGNvbXBpdGVuLCBxdWllbgpkZWNpZGU/KiogTGEgcmVzcHVlc3RhIHF1ZSBzb3N0ZW5nbyBlcyBxdWUgbG9zIGluZGljZXMgZGUgYWp1c3RlIHNvbiB1bmEgY29uZGljaW9uCm5lY2VzYXJpYSBwZXJvIG51bmNhIHN1ZmljaWVudGUsIHkgcXVlIHVuIG1vZGVsbyBjb24gbWVqb3IgYWp1c3RlIHB1ZWRlIHNlciBwZW9yIG1vZGVsby4KTG9zIGVqZXJjaWNpb3MgMSBhIDMgY29uc3RydXllbiBsYSBldmlkZW5jaWEgY29uIGRhdG9zOyBlbCBlamVyY2ljaW8gNCBsYSBjb25mcm9udGEgY29uCnVuIGNhc28gcHVibGljYWRvIGRvbmRlIGxvcyBhdXRvcmVzIHJlY2hhemFyb24gc3UgcHJvcGlvIG1vZGVsbyBtZWpvciBhanVzdGFkby4KClRvZG9zIGxvcyBtb2RlbG9zIHNlIGVzdGltYW4gY29uIGBsYXZhYW5gLiBMb3MgY3JpdGVyaW9zIGRlIGFqdXN0ZSBxdWUgdXNvIGEgbG8gbGFyZ28gZGVsCmRvY3VtZW50byBzb24gbG9zIGNvbnZlbmNpb25hbGVzIGVuIGxhIGxpdGVyYXR1cmEgKEh1IHkgQmVudGxlciwgMTk5OSk6CgpgYGB7ciBjcml0ZXJpb3MsIGVjaG89RkFMU0V9CmthYmxlKGRhdGEuZnJhbWUoCiAgSW5kaWNlID0gYygiQ2hpLWN1YWRyYWRhIiwgIkNGSSAvIFRMSSIsICJSTVNFQSIsICJTUk1SIiksCiAgUXVlX21pZGUgPSBjKCJEaXN0YW5jaWEgYWJzb2x1dGEgZW50cmUgbGEgbWF0cml6IG9ic2VydmFkYSB5IGxhIGltcGxpY2FkYSIsCiAgICAgICAgICAgICAgICJBanVzdGUgY29tcGFyYXRpdm8gY29udHJhIGVsIG1vZGVsbyBudWxvIiwKICAgICAgICAgICAgICAgIkVycm9yIGRlIGFwcm94aW1hY2lvbiBwb3IgZ3JhZG8gZGUgbGliZXJ0YWQgKHBlbmFsaXphIGZhbHRhIGRlIHBhcnNpbW9uaWEpIiwKICAgICAgICAgICAgICAgIlJlc2lkdWFsIGVzdGFuZGFyaXphZG8gcHJvbWVkaW8iKSwKICBDcml0ZXJpbyA9IGMoIm5vIHNpZ25pZmljYXRpdmEgKHNlbnNpYmxlIGEgTikiLCAiPj0gLjk1IChhY2VwdGFibGUgPj0gLjkwKSIsCiAgICAgICAgICAgICAgICI8PSAuMDYgKGFjZXB0YWJsZSA8PSAuMDgpIiwgIjw9IC4wOCIpKSwKICBjYXB0aW9uID0gIkNyaXRlcmlvcyBkZSBhanVzdGUgdXNhZG9zIGVuIHRvZG8gZWwgZG9jdW1lbnRvIikKYGBgCgpgYGB7ciBoZWxwZXJzfQojIGluZGljZXMgcXVlIHJlcG9ydG8gZW4gY2FkYSBtb2RlbG8KSURYIDwtIGMoImNoaXNxIiwgImRmIiwgInB2YWx1ZSIsICJjZmkiLCAidGxpIiwgInJtc2VhIiwgInNybXIiKQoKIyB0YWJsYSBkZSBhanVzdGUgZGUgdW5vIG8gdmFyaW9zIG1vZGVsb3MsIHBhcmEgY29tcGFyYXIgZW4gZWwgbWlzbW8gcmVuZ2xvbgp0YWJsYV9hanVzdGUgPC0gZnVuY3Rpb24oLi4uLCBldGlxdWV0YXMgPSBOVUxMKSB7CiAgbW9kZWxvcyA8LSBsaXN0KC4uLikKICBpZiAoaXMubnVsbChldGlxdWV0YXMpKSBldGlxdWV0YXMgPC0gcGFzdGUoIk1vZGVsbyIsIHNlcV9hbG9uZyhtb2RlbG9zKSkKICBvdXQgPC0gZG8uY2FsbChyYmluZCwgbGFwcGx5KG1vZGVsb3MsIGZ1bmN0aW9uKG0pIHsKICAgIGZtIDwtIGZpdE1lYXN1cmVzKG0sIElEWCkKICAgIGRhdGEuZnJhbWUoY2hpc3EgPSByb3VuZChmbVtbImNoaXNxIl1dLCAyKSwgZ2wgPSBmbVtbImRmIl1dLAogICAgICAgICAgICAgICBwID0gcm91bmQoZm1bWyJwdmFsdWUiXV0sIDMpLCBDRkkgPSByb3VuZChmbVtbImNmaSJdXSwgMyksCiAgICAgICAgICAgICAgIFRMSSA9IHJvdW5kKGZtW1sidGxpIl1dLCAzKSwgUk1TRUEgPSByb3VuZChmbVtbInJtc2VhIl1dLCAzKSwKICAgICAgICAgICAgICAgU1JNUiA9IHJvdW5kKGZtW1sic3JtciJdXSwgMykpCiAgfSkpCiAgIyBwb3N0LmNoZWNrIGF2aXNhIGRlIHNvbHVjaW9uZXMgaW5hZG1pc2libGVzICh2YXJpYW56YXMgbmVnYXRpdmFzLCBjYXJnYXMgPiAxKQogIG91dCRhZG1pc2libGUgPC0gc2FwcGx5KG1vZGVsb3MsIGZ1bmN0aW9uKG0pIGxhdkluc3BlY3QobSwgInBvc3QuY2hlY2siKSkKICByb3duYW1lcyhvdXQpIDwtIGV0aXF1ZXRhcwogIG91dAp9CgojIHBydWViYSBkZSBkaWZlcmVuY2lhIGRlIGNoaS1jdWFkcmFkYSBlbnRyZSBkb3MgbW9kZWxvcyBhbmlkYWRvcywgY29tbyB0YWJsYSBjb24gdGl0dWxvCiMgKGxhcyBzYWxpZGFzIHNpbiB0aXR1bG8gc2UgZGVzYWxpbmVhbiBkZSBzdSByb3R1bG8gYWwgY29tcGlsYXIgYSBQREYpCmNvbXBhcmFyIDwtIGZ1bmN0aW9uKG1vZGVsb19hLCBtb2RlbG9fYiwgZXRpcXVldGFzLCBjYXB0aW9uKSB7CiAgZ2wgPC0gYyhmaXRNZWFzdXJlcyhtb2RlbG9fYSwgImRmIiksIGZpdE1lYXN1cmVzKG1vZGVsb19iLCAiZGYiKSkKICBhICA8LSBzdXBwcmVzc1dhcm5pbmdzKGxhdlRlc3RMUlQobW9kZWxvX2EsIG1vZGVsb19iKSkKICAjIGxhdlRlc3RMUlQgZGV2dWVsdmUgbG9zIG1vZGVsb3Mgb3JkZW5hZG9zIHBvciBncmFkb3MgZGUgbGliZXJ0YWQsIG5vIGVuIGVsIG9yZGVuCiAgIyBlbiBxdWUgc2UgcGFzYW46IGhheSBxdWUgcmVvcmRlbmFyIGxhcyBldGlxdWV0YXMgaWd1YWwgbyBxdWVkYW4gY3J1emFkYXMKICBvdXQgPC0gZGF0YS5mcmFtZShNb2RlbG8gPSBldGlxdWV0YXNbbWF0Y2goYSREZiwgZ2wpXSwKICAgICAgICAgICAgICAgICAgICBnbCA9IGEkRGYsIEFJQyA9IHJvdW5kKGEkQUlDLCAxKSwgQklDID0gcm91bmQoYSRCSUMsIDEpLAogICAgICAgICAgICAgICAgICAgIGNoaXNxID0gcm91bmQoYSRDaGlzcSwgMiksCiAgICAgICAgICAgICAgICAgICAgZGlmX2NoaXNxID0gcm91bmQoYSQiQ2hpc3EgZGlmZiIsIDMpLAogICAgICAgICAgICAgICAgICAgIGRpZl9nbCA9IGEkIkRmIGRpZmYiLAogICAgICAgICAgICAgICAgICAgIHAgPSByb3VuZChhJCJQcig+Q2hpc3EpIiwgNCkpCiAga2FibGUob3V0LCByb3cubmFtZXMgPSBGQUxTRSwKICAgICAgICBjb2wubmFtZXMgPSBjKCJNb2RlbG8iLCJnbCIsIkFJQyIsIkJJQyIsImNoaXNxIiwiZGlmLiBjaGlzcSIsImRpZi4gZ2wiLCJwIiksCiAgICAgICAgY2FwdGlvbiA9IGNhcHRpb24pCn0KCiMgY2FyZ2FzIGVzdGFuZGFyaXphZGFzIG9yZGVuYWRhcyBkZSBtZW5vciBhIG1heW9yCmNhcmdhcyA8LSBmdW5jdGlvbihmaXQpIHsKICBzIDwtIHN1YnNldChzdGFuZGFyZGl6ZWRTb2x1dGlvbihmaXQpLCBvcCA9PSAiPX4iKQogIHMgPC0gc1tvcmRlcihzJGVzdC5zdGQpLCBjKCJsaHMiLCAicmhzIiwgImVzdC5zdGQiLCAicHZhbHVlIildCiAgbmFtZXMocykgPC0gYygiRmFjdG9yIiwgIkl0ZW0iLCAiQ2FyZ2FfZXN0YW5kYXJpemFkYSIsICJwIikKICByb3duYW1lcyhzKSA8LSBOVUxMCiAgcwp9CmBgYAoKIyBFamVyY2ljaW8gMTogSG9semluZ2VyIHkgU3dpbmVmb3JkICgxOTM5KQoKIyMgRWwgbW9kZWxvIHRlb3JpY28gZGUgdHJlcyBmYWN0b3JlcyBhanVzdGEgbWFsLCB5IGVsIHByb2JsZW1hIHRpZW5lIG5vbWJyZTogeDkKCkxhIGJhc2UgY2xhc2ljYSBkZSBIb2x6aW5nZXIgeSBTd2luZWZvcmQgcmVnaXN0cmEgbnVldmUgcHJ1ZWJhcyBtZW50YWxlcyBhcGxpY2FkYXMgYQpgciBucm93KEhvbHppbmdlclN3aW5lZm9yZDE5MzkpYCBlc3R1ZGlhbnRlcyBkZSBkb3MgZXNjdWVsYXMuIExhIHRlb3JpYSBwcm9wb25lIHRyZXMKaGFiaWxpZGFkZXMgbGF0ZW50ZXM6ICoqdmlzdWFsKiogKHgxLS14MyksICoqdmVyYmFsKiogKHg0LS14NikgeSAqKnZlbG9jaWRhZCoqICh4Ny0teDkpLgoKYGBge3IgZWoxLWJhc2V9Cm1vZF9ocyA8LSAnIHZpc3VhbCAgPX4geDEgKyB4MiArIHgzCiAgICAgICAgICAgIHRleHR1YWwgPX4geDQgKyB4NSArIHg2CiAgICAgICAgICAgIHNwZWVkICAgPX4geDcgKyB4OCArIHg5ICcKZml0X2hzIDwtIGNmYShtb2RfaHMsIGRhdGEgPSBIb2x6aW5nZXJTd2luZWZvcmQxOTM5KQprYWJsZSh0YWJsYV9hanVzdGUoZml0X2hzLCBldGlxdWV0YXMgPSAiMyBmYWN0b3JlcyAodGVvcmljbykiKSwKICAgICAgY2FwdGlvbiA9ICJFbCBtb2RlbG8gdGVvcmljbyBzZSBxdWVkYSBjb3J0bzogQ0ZJIHBvciBkZWJham8gZGUgLjk1IHkgUk1TRUEgYXJyaWJhIGRlIC4wNiIpCmBgYAoKRWwgQ0ZJIGRlIGByIHJvdW5kKGZpdE1lYXN1cmVzKGZpdF9ocywiY2ZpIiksMylgIHkgZWwgUk1TRUEgZGUKYHIgcm91bmQoZml0TWVhc3VyZXMoZml0X2hzLCJybXNlYSIpLDMpYCBzb24gYWNlcHRhYmxlcyBwZXJvIG5vIGJ1ZW5vcy4gQW50ZXMgZGUgdG9jYXIKbmFkYSwgY29udmllbmUgdmVyICoqZG9uZGUqKiBmYWxsYToKCmBgYHtyIGVqMS1jYXJnYXMsIGVjaG89RkFMU0V9CmthYmxlKGNhcmdhcyhmaXRfaHMpLCByb3cubmFtZXMgPSBGQUxTRSwgZGlnaXRzID0gMywKICAgICAgY2FwdGlvbiA9ICJ4MiAoLjQyKSB5IHgzICguNTgpIHNvc3RpZW5lbiBtYWwgYWwgZmFjdG9yIHZpc3VhbCIpCmBgYAoKYGBge3IgZWoxLW1pfQptaV9ocyA8LSBtb2RpbmRpY2VzKGZpdF9ocywgc29ydC4gPSBUUlVFKQprYWJsZShoZWFkKG1pX2hzWywgYygibGhzIiwib3AiLCJyaHMiLCJtaSIsImVwYyIsInNlcGMuYWxsIildLCA2KSwgcm93Lm5hbWVzID0gRkFMU0UsCiAgICAgIGRpZ2l0cyA9IDMsIGNhcHRpb24gPSAiSW5kaWNlcyBkZSBtb2RpZmljYWNpb246IHg5IHF1aWVyZSBjYXJnYXIgdGFtYmllbiBlbiB2aXN1YWwiKQpgYGAKCkVsIGluZGljZSBtYXMgZ3JhbmRlIG5vIGVzIHVuIGVycm9yIHJlc2lkdWFsIGN1YWxxdWllcmE6IGVzIGB2aXN1YWwgPX4geDlgLCBjb24gdW4gTUkgZGUKYHIgcm91bmQobWlfaHMkbWlbMV0sMSlgLiBFc28gdGllbmUgbGVjdHVyYSBzdXN0YW50aXZhLiBMYSBwcnVlYmEgeDkgbWlkZSAqdmVsb2NpZGFkIHBhcmEKY29udGFyIHB1bnRvcyBlbiBmaWd1cmFzKjogZXMgdW5hIHRhcmVhIGRlIHJhcGlkZXosIHNpLCBwZXJvICoqZWwgZXN0aW11bG8gZXMgdmlzdWFsKiouCk5vIGVzIHJhcm8gcXVlIGNvbXBhcnRhIHZhcmlhbnphIGNvbiBlbCBmYWN0b3IgdmlzdWFsLgoKIyMgRGVwdXJhY2lvbjogdW4gc29sbyBwYXJhbWV0cm8sIGVsZWdpZG8gcG9yIHRlb3JpYSB5IG5vIHBvciBlbCBpbmRpY2UgbWFzIGFsdG8KCmBgYHtyIGVqMS1kZXB9Cm1vZF9oczIgPC0gJyB2aXN1YWwgID1+IHgxICsgeDIgKyB4MyArIHg5CiAgICAgICAgICAgICB0ZXh0dWFsID1+IHg0ICsgeDUgKyB4NgogICAgICAgICAgICAgc3BlZWQgICA9fiB4NyArIHg4ICsgeDkgJwpmaXRfaHMyIDwtIGNmYShtb2RfaHMyLCBkYXRhID0gSG9semluZ2VyU3dpbmVmb3JkMTkzOSkKCiMgYWx0ZXJuYXRpdmEgcXVlIGVsIE1JIHRhbWJpZW4gc3VnaWVyZSwgcGVybyBzaW4gbGVjdHVyYSBzdXN0YW50aXZhIGNsYXJhCm1vZF9oczMgPC0gcGFzdGUobW9kX2hzLCAiXG4geDcgfn4geDkiKQpmaXRfaHMzIDwtIGNmYShtb2RfaHMzLCBkYXRhID0gSG9semluZ2VyU3dpbmVmb3JkMTkzOSkKCmthYmxlKHRhYmxhX2FqdXN0ZShmaXRfaHMsIGZpdF9oczIsIGZpdF9oczMsCiAgICAgIGV0aXF1ZXRhcyA9IGMoIjMgZmFjdG9yZXMgKHRlb3JpY28pIiwgIng5IGNhcmdhIHRhbWJpZW4gZW4gdmlzdWFsIiwKICAgICAgICAgICAgICAgICAgICAiY292YXJpYW56YSByZXNpZHVhbCB4NyB+fiB4OSIpKSwKICAgICAgY2FwdGlvbiA9ICJTb2xvIGxhIGNhcmdhIGNydXphZGEgZGUgeDkgbXVldmUgZWwgYWp1c3RlIGEgdGVycml0b3JpbyBidWVubyIpCmBgYAoKYGBge3IgZWoxLWFub3ZhfQpjb21wYXJhcihmaXRfaHMsIGZpdF9oczIsCiAgICAgICAgIGMoIjMgZmFjdG9yZXMgKHRlb3JpY28pIiwgIng5IGNhcmdhIHRhbWJpZW4gZW4gdmlzdWFsIiksCiAgICAgICAgICJMaWJlcmFyIHVuIHNvbG8gcGFyYW1ldHJvIG1lam9yYSBlbCBhanVzdGUgZGUgZm9ybWEgc2lnbmlmaWNhdGl2YSIpCmBgYAoKTGEgZGlmZXJlbmNpYSBkZSBjaGktY3VhZHJhZGEgZXMgc2lnbmlmaWNhdGl2YSBjb24gdW4gc29sbyBncmFkbyBkZSBsaWJlcnRhZDogbGliZXJhcgpgdmlzdWFsID1+IHg5YCBtZWpvcmEgZWwgYWp1c3RlIGRlIGZvcm1hIHJlYWwsIG5vIG1hcmdpbmFsLiBMYSBjb3ZhcmlhbnphIHJlc2lkdWFsCmB4NyB+fiB4OWAsIGVuIGNhbWJpbywgY2FzaSBubyBtdWV2ZSBuYWRhIChDRkkgYHIgcm91bmQoZml0TWVhc3VyZXMoZml0X2hzMywiY2ZpIiksMylgKSwKbG8gY3VhbCBjb25maXJtYSBxdWUgZWwgcHJvYmxlbWEgbm8gZXMgcnVpZG8gY29tcGFydGlkbyBlbnRyZSBkb3MgcHJ1ZWJhcyBkZSB2ZWxvY2lkYWQKc2lubyBxdWUgKip4OSBtaWRlIGRvcyBjb3NhcyBhIGxhIHZleioqLgoKIyMgSG9uZXN0aWRhZCBzb2JyZSBsYSBkZXB1cmFjaW9uOiB2YWxpZGFybGEgZW4gdW5hIG11ZXN0cmEgcXVlIG5vIGxhIHN1Z2lyaW8KCkFxdWkgZXN0YSBlbCByaWVzZ28gZGVsIHF1ZSBjYXNpIG51bmNhIHNlIGhhYmxhLiBVbiBpbmRpY2UgZGUgbW9kaWZpY2FjaW9uIHNlIGNhbGN1bGEKKipzb2JyZSBsb3MgbWlzbW9zIGRhdG9zKiogcXVlIHNlIHZhbiBhIHVzYXIgcGFyYSBqdXpnYXIgZWwgbW9kZWxvIG1lam9yYWRvLiBTZWd1aXJsbyBlcywKZW4gZWwgbGltaXRlLCBhanVzdGFybGUgZWwgbW9kZWxvIGFsIHJ1aWRvIGRlIGVzdGEgbXVlc3RyYS4gTGEgdW5pY2EgZGVmZW5zYSByZWFsIGVzCnZlcmlmaWNhciBxdWUgZWwgaGFsbGF6Z28gc2UgcmVwaXRlIGVuIGRhdG9zIHF1ZSBubyBwYXJ0aWNpcGFyb24gZW4gbGEgZGVjaXNpb24uCgpMYSBiYXNlIHRyYWUgZG9zIGVzY3VlbGFzLiBVc28gdW5hIHBhcmEgZGVzY3VicmlyIHkgbGEgb3RyYSBwYXJhIGNvbmZpcm1hcjoKCmBgYHtyIGVqMS1jdn0KdmFsIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShsZXZlbHMoSG9semluZ2VyU3dpbmVmb3JkMTkzOSRzY2hvb2wpLCBmdW5jdGlvbihlc2MpIHsKICBzdWIgPC0gSG9semluZ2VyU3dpbmVmb3JkMTkzOVtIb2x6aW5nZXJTd2luZWZvcmQxOTM5JHNjaG9vbCA9PSBlc2MsIF0KICBhIDwtIGNmYShtb2RfaHMsICBkYXRhID0gc3ViKQogIGIgPC0gY2ZhKG1vZF9oczIsIGRhdGEgPSBzdWIpCiAgZGF0YS5mcmFtZShFc2N1ZWxhID0gZXNjLCBuID0gbnJvdyhzdWIpLAogICAgICAgICAgICAgQ0ZJX2Jhc2UgPSByb3VuZChmaXRNZWFzdXJlcyhhLCAiY2ZpIiksIDMpLAogICAgICAgICAgICAgQ0ZJX2RlcHVyYWRvID0gcm91bmQoZml0TWVhc3VyZXMoYiwgImNmaSIpLCAzKSwKICAgICAgICAgICAgIFJNU0VBX2Jhc2UgPSByb3VuZChmaXRNZWFzdXJlcyhhLCAicm1zZWEiKSwgMyksCiAgICAgICAgICAgICBSTVNFQV9kZXB1cmFkbyA9IHJvdW5kKGZpdE1lYXN1cmVzKGIsICJybXNlYSIpLCAzKSwKICAgICAgICAgICAgIGNhcmdhX3g5X3Zpc3VhbCA9IHJvdW5kKHN1YnNldChzdGFuZGFyZGl6ZWRTb2x1dGlvbihiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxocyA9PSAidmlzdWFsIiAmIHJocyA9PSAieDkiKSRlc3Quc3RkLCAzKSkKfSkpCmthYmxlKHZhbCwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiTGEgY2FyZ2EgY3J1emFkYSBkZSB4OSBhcGFyZWNlIGVuIGxhcyBkb3MgZXNjdWVsYXMsIHBlcm8gbm8gY29uIGxhIG1pc21hIGZ1ZXJ6YSIpCmBgYAoKRWwgcmVzdWx0YWRvIHNlIHJlcGl0ZSBlbiBhbWJhcyBlc2N1ZWxhcywgYXNpIHF1ZSBubyBlcyB1biBhcnRlZmFjdG86IHg5IGNhcmdhIGVuIHZpc3VhbAplbiBsYXMgZG9zLiBQZXJvIGxhIG1hZ25pdHVkIGNhZSBkZSBgciB2YWwkY2FyZ2FfeDlfdmlzdWFsWzFdYCBlbiBHcmFudC1XaGl0ZSBhCmByIHZhbCRjYXJnYV94OV92aXN1YWxbMl1gIGVuIFBhc3RldXIsIHkgZW4gUGFzdGV1ciBlbCBtb2RlbG8gZGVwdXJhZG8gKipzaWd1ZSBzaW4KYWxjYW56YXIqKiBlbCBjcml0ZXJpbyAoQ0ZJIGByIHZhbCRDRklfZGVwdXJhZG9bMl1gLCBSTVNFQSBgciB2YWwkUk1TRUFfZGVwdXJhZG9bMl1gKS4KRXMgZGVjaXI6IGxhIGNvcnJlY2Npb24gZXMgcmVhbCwgcGVybyBlbCBtb2RlbG8gZGVwdXJhZG8gcXVlIHJlcG9ydG8gYXJyaWJhIHNlIHZlIG1lam9yCmRlIGxvIHF1ZSBlcyBwb3JxdWUgc2UgZXN0aW1vIGVuIGxhIG11ZXN0cmEgY29tcGxldGEsIGluY2x1eWVuZG8gbGEgZXNjdWVsYSBkb25kZSBlbAplZmVjdG8gZXMgZnVlcnRlLgoKIyMgQ29uY2x1c2lvbmVzIGRlbCBlamVyY2ljaW8gMQoKMS4gRWwgbW9kZWxvIHRlb3JpY28gZGUgdHJlcyBmYWN0b3JlcyBlcyAqKmRlZmVuZGlibGUgcGVybyBpbmNvbXBsZXRvKio6IGFqdXN0YSBkZSBmb3JtYQogICBhY2VwdGFibGUgKENGSSBgciByb3VuZChmaXRNZWFzdXJlcyhmaXRfaHMsImNmaSIpLDMpYCkgeSBubyBidWVuYS4KMi4gTGEgY2F1c2EgZXMgdW5hICoqdmFyaWFibGUgcXVlIG1pZGUgZG9zIGNvbnN0cnVjdG9zKiouIHg5IHBlcnRlbmVjZSBhIHZlbG9jaWRhZCBwb3Igc3UKICAgZm9ybWF0byB5IGEgdmlzdWFsIHBvciBzdSBjb250ZW5pZG8uIEVzIHVuIHByb2JsZW1hIGRlIGRpc2VubyBkZWwgaW5zdHJ1bWVudG8sIG5vIGRlCiAgIGVzdGltYWNpb24uCjMuIERlcHVyYXIgZ3VpYWRvIHBvciBpbmRpY2VzIGRlIG1vZGlmaWNhY2lvbiBmdW5jaW9uYSwgcGVybyAqKmVsIGFqdXN0ZSBxdWUgcmVzdWx0YSBlc3RhCiAgIGluZmxhZG8qKiBwb3IgaGFiZXIgdXNhZG8gbG9zIG1pc21vcyBkYXRvcyBwYXJhIGRlc2N1YnJpciB5IHBhcmEgZXZhbHVhci4gTGEgdmFsaWRhY2lvbgogICBlbnRyZSBlc2N1ZWxhcyBsbyBkZW11ZXN0cmEuCjQuIFJlZ2xhIHF1ZSBtZSBsbGV2bzogc29sbyBsaWJlcm8gdW4gcGFyYW1ldHJvIHNpIHB1ZWRvIGV4cGxpY2FybG8gYW50ZXMgZGUgdmVybG8gZW4gbGEKICAgdGFibGEgZGUgTUkuIGB2aXN1YWwgPX4geDlgIHBhc2EgZXNhIHBydWViYTsgYHg3IH5+IHg5YCBubywgeSBhZGVtYXMgbm8gc2VydmlhLgoKIyBFamVyY2ljaW8gMjogZGVtb2NyYWNpYSBwb2xpdGljYSBlIGluZHVzdHJpYWxpemFjaW9uIChCb2xsZW4pCgojIyBFbCBtb2RlbG8gb2J2aW8gYWp1c3RhIG1hbCwgeSBsYSByYXpvbiBlcyBxdWUgaWdub3JhIHF1ZSBzb24gbGFzIG1pc21hcyBwcmVndW50YXMgZG9zIHZlY2VzCgpMYSBiYXNlIGRlIEJvbGxlbiBzaWd1ZSBhIDc1IHBhaXNlcyBlbiBkZXNhcnJvbGxvLiBgaW5kNjBgIGVzIGluZHVzdHJpYWxpemFjaW9uIGVuIDE5NjAKKHgxLS14Myk7IGBkZW02MGAgeSBgZGVtNjVgIHNvbiBkZW1vY3JhY2lhIHBvbGl0aWNhIGVuIDE5NjAgeSAxOTY1LCBtZWRpZGFzIGNvbiAqKmxvcwptaXNtb3MgY3VhdHJvIGluZGljYWRvcmVzKiogKHkxLS15NCB5IHk1LS15OCByZXNwZWN0aXZhbWVudGUpLiBMYSBoaXBvdGVzaXMgZXMgcXVlIGxhCmluZHVzdHJpYWxpemFjaW9uIGltcHVsc2EgbGEgZGVtb2NyYWNpYSwgZW4gcGFydGUgZGUgZm9ybWEgZGlyZWN0YSB5IGVuIHBhcnRlIGEgdHJhdmVzIGRlCmxhIGRlbW9jcmFjaWEgcHJldmlhLgoKYGBge3IgZWoyLWJhc2V9Cm1vZF9wZCA8LSAnCiAgaW5kNjAgPX4geDEgKyB4MiArIHgzCiAgZGVtNjAgPX4geTEgKyB5MiArIHkzICsgeTQKICBkZW02NSA9fiB5NSArIHk2ICsgeTcgKyB5OAogIGRlbTYwIH4gaW5kNjAKICBkZW02NSB+IGluZDYwICsgZGVtNjAgJwpmaXRfcGQgPC0gY2ZhKG1vZF9wZCwgZGF0YSA9IFBvbGl0aWNhbERlbW9jcmFjeSkKa2FibGUodGFibGFfYWp1c3RlKGZpdF9wZCwgZXRpcXVldGFzID0gInNpbiBlcnJvcmVzIGNvcnJlbGFjaW9uYWRvcyIpLAogICAgICBjYXB0aW9uID0gIlJNU0VBIGRlIC4xMDE6IGVsIG1vZGVsbyBkZWphIGFsZ28gaW1wb3J0YW50ZSBmdWVyYSIpCmBgYAoKYGBge3IgZWoyLW1pLCBlY2hvPUZBTFNFfQprYWJsZShoZWFkKG1vZGluZGljZXMoZml0X3BkLCBzb3J0LiA9IFRSVUUpWywgYygibGhzIiwib3AiLCJyaHMiLCJtaSIsImVwYyIpXSwgNiksCiAgICAgIHJvdy5uYW1lcyA9IEZBTFNFLCBkaWdpdHMgPSAzLAogICAgICBjYXB0aW9uID0gIlRvZG9zIGxvcyBpbmRpY2VzIGFsdG9zIHNvbiBjb3ZhcmlhbnphcyBlbnRyZSBlcnJvcmVzIGRlIHkiKQpgYGAKCkxvcyBzZWlzIGluZGljZXMgbWFzIGdyYW5kZXMgc29uICoqY292YXJpYW56YXMgZW50cmUgcmVzaWR1YWxlcyBkZSBsb3MgaW5kaWNhZG9yZXMgeSoqLCB5Cm5pbmd1bm8gaW52b2x1Y3JhIGEgbGFzIHguIEVzbyBubyBlcyBjYXN1YWxpZGFkLiBFbCBpbmRpY2Fkb3IgeTEgKGxpYmVydGFkIGRlIHByZW5zYSBlbgoxOTYwKSB5IGVsIHk1IChsaWJlcnRhZCBkZSBwcmVuc2EgZW4gMTk2NSkgc29uICpsYSBtaXNtYSBwcmVndW50YSBhcGxpY2FkYSBjaW5jbyBhbmlvcwpkZXNwdWVzKjogY29tcGFydGVuIG5vIHNvbG8gZWwgY29uc3RydWN0byBkZW1vY3JhY2lhLCBzaW5vIGxhIGZ1ZW50ZSwgZWwgc2VzZ28gZGVsCmNvZGlmaWNhZG9yIHkgbGEgaWRpb3NpbmNyYXNpYSBkZWwgcGFpcy4gRXNhIHZhcmlhbnphIGNvbXBhcnRpZGEgZXMgKiptZXRvZG8qKiwgbm8KY29uc3RydWN0bywgeSBzaSBubyBzZSBtb2RlbGEgc2UgYWN1bXVsYSBlbiBlbCByZXNpZHVhbCBkZWwgc2lzdGVtYS4KCiMjIEVsIG1vZGVsbyBjb3JyZWN0bzogZGVqYXIgcXVlIGxvcyBlcnJvcmVzIGRlbCBtaXNtbyBpbmRpY2Fkb3Igc2UgY29ycmVsYWNpb25lbiBlbiBlbCB0aWVtcG8KCmBgYHtyIGVqMi1jb3JyfQptb2RfcGQyIDwtICcKICBpbmQ2MCA9fiB4MSArIHgyICsgeDMKICBkZW02MCA9fiB5MSArIHkyICsgeTMgKyB5NAogIGRlbTY1ID1+IHk1ICsgeTYgKyB5NyArIHk4CiAgZGVtNjAgfiBhKmluZDYwCiAgZGVtNjUgfiBjKmluZDYwICsgYipkZW02MAogICMgZXJyb3JlcyBhdXRvY29ycmVsYWNpb25hZG9zOiBtaXNtbyBpbmRpY2Fkb3IgbWVkaWRvIGVuIDE5NjAgeSBlbiAxOTY1CiAgeTEgfn4geTUKICB5MiB+fiB5NCArIHk2CiAgeTMgfn4geTcKICB5NCB+fiB5OAogIHk2IH5+IHk4CiAgIyBkZXNjb21wb3NpY2lvbiBkZWwgZWZlY3RvIGRlIGxhIGluZHVzdHJpYWxpemFjaW9uIHNvYnJlIGxhIGRlbW9jcmFjaWEgZGUgMTk2NQogIGluZGlyZWN0byA6PSBhKmIKICB0b3RhbCAgICAgOj0gYyArIGEqYiAnCmZpdF9wZDIgPC0gc2VtKG1vZF9wZDIsIGRhdGEgPSBQb2xpdGljYWxEZW1vY3JhY3kpCmthYmxlKHRhYmxhX2FqdXN0ZShmaXRfcGQsIGZpdF9wZDIsCiAgICAgIGV0aXF1ZXRhcyA9IGMoInNpbiBlcnJvcmVzIGNvcnJlbGFjaW9uYWRvcyIsICJjb24gZXJyb3JlcyBjb3JyZWxhY2lvbmFkb3MiKSksCiAgICAgIGNhcHRpb24gPSAiRWwgYWp1c3RlIHBhc2EgZGUgZHVkb3NvIGEgbXV5IGJ1ZW5vIGNvbiBzZWlzIHBhcmFtZXRyb3MgcXVlIGxhIHRlb3JpYSBkZSBtZWRpY2lvbiBleGlnZSIpCmBgYAoKYGBge3IgZWoyLWFub3ZhfQpjb21wYXJhcihmaXRfcGQsIGZpdF9wZDIsCiAgICAgICAgIGMoInNpbiBlcnJvcmVzIGNvcnJlbGFjaW9uYWRvcyIsICJjb24gZXJyb3JlcyBjb3JyZWxhY2lvbmFkb3MiKSwKICAgICAgICAgIkxvcyBzZWlzIGVycm9yZXMgY29ycmVsYWNpb25hZG9zIG5vIHNvbiBvcGNpb25hbGVzOiBzdSBvbWlzaW9uIGVzIHJlY2hhemFkYSIpCmBgYAoKIyMgRWZlY3RvcyBkaXJlY3RvLCBpbmRpcmVjdG8geSB0b3RhbAoKYGBge3IgZWoyLWVmZWN0b3N9CmVmIDwtIHBhcmFtZXRlckVzdGltYXRlcyhmaXRfcGQyLCBzdGFuZGFyZGl6ZWQgPSBUUlVFKQplZiA8LSBzdWJzZXQoZWYsIG9wICVpbiUgYygifiIsICI6PSIpKVssIGMoImxocyIsInJocyIsImxhYmVsIiwiZXN0Iiwic2UiLCJwdmFsdWUiLCJzdGQuYWxsIildCm5hbWVzKGVmKSA8LSBjKCJEZXN0aW5vIiwiT3JpZ2VuIiwiRXRpcXVldGEiLCJFc3RpbWFkbyIsIkVFIiwicCIsIkVzdGFuZGFyaXphZG8iKQprYWJsZShlZiwgcm93Lm5hbWVzID0gRkFMU0UsIGRpZ2l0cyA9IDMsCiAgICAgIGNhcHRpb24gPSAiRWwgZ3J1ZXNvIGRlbCBlZmVjdG8gZGUgbGEgaW5kdXN0cmlhbGl6YWNpb24gc29icmUgbGEgZGVtb2NyYWNpYSBkZSAxOTY1IGVzIGluZGlyZWN0byIpCmBgYAoKYGBge3IgZWoyLWxlY3R1cmEsIGVjaG89RkFMU0V9CmUgPC0gZnVuY3Rpb24obCkgZWYkRXN0YW5kYXJpemFkb1ttYXRjaChsLCBlZiRFdGlxdWV0YSldCmBgYAoKTGEgbGVjdHVyYSBzdXN0YW50aXZhOiBkZSB1biBlZmVjdG8gdG90YWwgZXN0YW5kYXJpemFkbyBkZSBgciByb3VuZChlKCJ0b3RhbCIpLDMpYCwKbGEgcGFydGUgaW5kaXJlY3RhIChgciByb3VuZChlKCJpbmRpcmVjdG8iKSwzKWApIGVzICoqYHIgcm91bmQoMTAwKmUoImluZGlyZWN0byIpL2UoInRvdGFsIikpYCUqKgpkZWwgdG90YWwuIExhIGluZHVzdHJpYWxpemFjaW9uIGRlIDE5NjAgbm8gcHJvZHVjZSBkZW1vY3JhY2lhIGVuIDE5NjUgcG9yIHNpIHNvbGE6IGxhCnByb2R1Y2Ugc29icmUgdG9kbyBwb3JxdWUgeWEgaGFiaWEgcHJvZHVjaWRvIGRlbW9jcmFjaWEgZW4gMTk2MCwgeSBsYSBkZW1vY3JhY2lhIGVzCmFsdGFtZW50ZSBwZXJzaXN0ZW50ZSAoYGJgIGVzdGFuZGFyaXphZG8gPSBgciByb3VuZChlKCJiIiksMylgLCBjYXNpIHVuIHRlY2hvKS4KCiMjIENvbmNsdXNpb25lcyBkZWwgZWplcmNpY2lvIDIKCjEuIEVsIG1hbCBhanVzdGUgaW5pY2lhbCAqKm5vIGVyYSBkZWwgbW9kZWxvIGVzdHJ1Y3R1cmFsKiosIGVyYSBkZWwgbW9kZWxvIGRlIG1lZGljaW9uLgogICBMYXMgZmxlY2hhcyBlbnRyZSBsYXRlbnRlcyBlc3RhYmFuIGJpZW47IGxvIHF1ZSBmYWx0YWJhIGVyYSByZWNvbm9jZXIgcXVlIGVsIG1pc21vCiAgIGluZGljYWRvciBtZWRpZG8gZG9zIHZlY2VzIGFycmFzdHJhIHN1IHByb3BpbyBlcnJvci4KMi4gTG9zIHNlaXMgcGFyYW1ldHJvcyBxdWUgYWdyZWd1ZSBubyBzZSBqdXN0aWZpY2FuIHBvciBzdSBNSSBzaW5vIHBvciAqKmVsIGRpc2VubyBkZWwKICAgZXN0dWRpbyoqOiBzb24gZGF0b3MgbG9uZ2l0dWRpbmFsZXMgY29uIGluZGljYWRvcmVzIHJlcGV0aWRvcy4gRXNlIGVzIGVsIGNhc28gZG9uZGUKICAgbGliZXJhciBjb3ZhcmlhbnphcyByZXNpZHVhbGVzIGVzIG9ibGlnYXRvcmlvLCBubyBvcG9ydHVuaXN0YS4KMy4gTGEgZGVzY29tcG9zaWNpb24gZGlyZWN0byAvIGluZGlyZWN0byBjYW1iaWEgbGEgY29uY2x1c2lvbiBkZSBwb2xpdGljYSBwdWJsaWNhOgogICBpbmR1c3RyaWFsaXphciBob3kgdGllbmUgZWZlY3RvIHNvYnJlIGxhIGRlbW9jcmFjaWEgZnV0dXJhIHByaW5jaXBhbG1lbnRlICoqYSB0cmF2ZXMKICAgZGUgbGEgZGVtb2NyYWNpYSBwcmVzZW50ZSoqLCBlcyBkZWNpciwgaGF5IGRlcGVuZGVuY2lhIGRlIGxhIHRyYXllY3RvcmlhLgoKIyBFamVyY2ljaW8gMzogYmllbmVzdGFyIGRlIGxvcyBjb2xhYm9yYWRvcmVzCgpgYGB7ciBlajMtZGF0b3N9CmQgPC0gcmVhZC5jc3YoImRhdG9zL2RhdG9zX3NlbS5jc3YiKQpjKG9ic2VydmFjaW9uZXMgPSBucm93KGQpLCB2YXJpYWJsZXMgPSBuY29sKGQpLCB2YWxvcmVzX2ZhbHRhbnRlcyA9IHN1bShpcy5uYShkKSkpCmBgYAoKTGEgYmFzZSB0aWVuZSBgciBucm93KGQpYCBjb2xhYm9yYWRvcmVzLCBzaW4gdmFsb3JlcyBmYWx0YW50ZXMuIExhcyBlc2NhbGFzIGRlCnJlY3VwZXJhY2lvbiB5IGVuZXJnaWEgdmFuIGRlIDEgYSA3IHkgbGEgZGUgZW5nYWdlbWVudCBkZSAwIGEgNy4KCioqTm90YSBkZSB2ZXJpZmljYWNpb24uKiogTGEgZGVzY3JpcGNpb24gZGUgaW5zdHJ1bWVudG9zIG5vbWJyYSBsb3MgaXRlbXMgZGUgZW5lcmdpYQpyZWN1cGVyYWRhIGNvbW8gUkVHMDEtLVJFRzEwIHkgbWFyY2EgUkVHMDEsIFJFRzA5IHkgUkVHMTAgY29tbyBlbGltaW5hZG9zOyBsYSBiYXNlIGxvcwp0cmFlIGNvbW8gRU4wMS0tRU4wOCBzaW4gRU4wMy4gTGEgY29ycmVzcG9uZGVuY2lhIGV4YWN0YSBlbnRyZSBsYXMgZG9zIG51bWVyYWNpb25lcyBubwplc3RhIGRvY3VtZW50YWRhLCBhc2kgcXVlIHRyYWJham8gY29uIGxvcyBzaWV0ZSBpdGVtcyB0YWwgY29tbyB2aWVuZW4geSAqKm5vIGFzdW1vKiogcXVlCkVOMGsgc2VhIFJFRzBrLiBJZ3VhbCBjb252aWVuZSBjb25maXJtYXJsbyBjb24gZWwgcHJvZmVzb3IuIExhIG1pc21hIGhvamEgaW5kaWNhIHF1ZSBsYQplc2NhbGEgZGUgZW5nYWdlbWVudCBlcyAiTnVuY2EgPSAwLCBDYXNpIG51bmNhID0gMiwgLi4uIiAoc2luIGVsIDEpLCBwZXJvIGxhIGJhc2Ugc2kKY29udGllbmUgdW5vczsgbG8gdHJhdG8gY29tbyBlc2NhbGEgY29udGludWEgZGUgMCBhIDcuCgojIyBQYXJ0ZSAxOiBhbmFsaXNpcyBmYWN0b3JpYWwgY29uZmlybWF0b3JpbyBkZSBzZWd1bmRvIG9yZGVuIGRlIGxhcyBleHBlcmllbmNpYXMgZGUgcmVjdXBlcmFjaW9uCgojIyMgRWwgbW9kZWxvIGRlIHByaW1lciBvcmRlbiBjb24gbG9zIDMxIGl0ZW1zIG5vIHBhc2EKCkxhcyBleHBlcmllbmNpYXMgZGUgcmVjdXBlcmFjaW9uIHNlIG1pZGVuIGNvbiBjdWF0cm8gZG9taW5pb3M6IGRlc2FwZWdvIHBzaWNvbG9naWNvLApyZWxhamFjaW9uLCBtYWVzdHJpYSB5IGNvbnRyb2wgc29icmUgZWwgdGllbXBvIGxpYnJlLgoKYGBge3IgZWozLXAxLWl0ZW1zfQppdGVtc19yZWMgPC0gbGlzdCgKICBERVNBUEVHTyAgID0gZ3JlcCgiXlJQRCIsIG5hbWVzKGQpLCB2YWx1ZSA9IFRSVUUpLAogIFJFTEFKQUNJT04gPSBncmVwKCJeUlJFIiwgbmFtZXMoZCksIHZhbHVlID0gVFJVRSksCiAgTUFFU1RSSUEgICA9IGdyZXAoIl5STUEiLCBuYW1lcyhkKSwgdmFsdWUgPSBUUlVFKSwKICBDT05UUk9MICAgID0gZ3JlcCgiXlJDTyIsIG5hbWVzKGQpLCB2YWx1ZSA9IFRSVUUpKQpzYXBwbHkoaXRlbXNfcmVjLCBsZW5ndGgpCgojIGFybWEgbGEgc2ludGF4aXMgZGUgbGF2YWFuIGEgcGFydGlyIGRlIGxhIGxpc3RhIGRlIGl0ZW1zCnNpbnRheGlzIDwtIGZ1bmN0aW9uKGxpc3RhKSB7CiAgcGFzdGUobWFwcGx5KGZ1bmN0aW9uKG5vbWJyZSwgaXRzKSBwYXN0ZTAobm9tYnJlLCAiID1+ICIsIHBhc3RlKGl0cywgY29sbGFwc2UgPSAiICsgIikpLAogICAgICAgICAgICAgICBuYW1lcyhsaXN0YSksIGxpc3RhKSwgY29sbGFwc2UgPSAiXG4iKQp9CmZpdF9yMSA8LSBjZmEoc2ludGF4aXMoaXRlbXNfcmVjKSwgZGF0YSA9IGQsIGVzdGltYXRvciA9ICJNTFIiKQprYWJsZSh0YWJsYV9hanVzdGUoZml0X3IxLCBldGlxdWV0YXMgPSAiNCBmYWN0b3JlcywgMzEgaXRlbXMiKSwKICAgICAgY2FwdGlvbiA9ICJOaW5ndW4gY3JpdGVyaW8gc2UgY3VtcGxlOiBoYXkgcXVlIGRlcHVyYXIiKQpgYGAKCmBgYHtyIGVqMy1wMS1kaWFnLCBlY2hvPUZBTFNFfQptaV9yIDwtIG1vZGluZGljZXMoZml0X3IxLCBzb3J0LiA9IFRSVUUpCmthYmxlKGhlYWQobWlfclssIGMoImxocyIsIm9wIiwicmhzIiwibWkiLCJlcGMiLCJzZXBjLmFsbCIpXSwgOCksIHJvdy5uYW1lcyA9IEZBTFNFLAogICAgICBkaWdpdHMgPSAzLCBjYXB0aW9uID0gIkVsIGRpYWdub3N0aWNvOiBpdGVtcyBjYXNpIGlkZW50aWNvcyBlbnRyZSBzaSB5IHVuIGl0ZW0gcXVlIGNhcmdhIGVuIGVsIGZhY3RvciBlcXVpdm9jYWRvIikKYGBgCgpFbCBkaWFnbm9zdGljbyBlcyBjbGFybyB5IHRpZW5lIHNlbnRpZG8gbGV5ZW5kbyBsb3MgcmVhY3Rpdm9zOgoKLSBgUlBEMDYgfn4gUlBEMDhgIChNSSA9IGByIHJvdW5kKG1pX3IkbWlbMV0pYCk6ICJBIHByb3Bvc2l0byBubyBoaWNlLCBuaSByZXZpc2UgbmFkYSBkZQogIG1pIHRyYWJham8iIHkgIkNvbiB0b2RhIGludGVuY2lvbiBubyBoaWNlIG5hZGEgc29icmUgbWkgdHJhYmFqbyIgc29uICoqbGEgbWlzbWEgZnJhc2UqKi4KLSBgUlBEMDkgfn4gUlBEMTBgOiAiTG9ncmUgZGVzbGlnYXJtZSBkZSBtaXMgcmVzcG9uc2FiaWxpZGFkZXMgbGFib3JhbGVzIiB5ICJNZSBkZXNsaW5kZQogIGRlIG1pcyBhY3RpdmlkYWRlcyBsYWJvcmFsZXMiLCBpZ3VhbC4KLSBgQ09OVFJPTCA9fiBSTUEwNmA6ICJVdGlsaWNlIG1pIHRpZW1wbyBlbiBhY3RpdmlkYWRlcyBkaWZlcmVudGVzIiBoYWJsYSBkZSAqKmNvbW8KICBkaXNwb25nbyBkZSBtaSB0aWVtcG8qKiwgbm8gZGUgcmV0YXJtZSBhIGFwcmVuZGVyLiBFc3RhIGVuIGVsIGZhY3RvciBlcXVpdm9jYWRvLgoKRXN0byBubyBlcyBydWlkbyBlc3RhZGlzdGljbzogZXMgKipyZWR1bmRhbmNpYSBkZSByZWRhY2Npb24qKiBlbiBlbCBpbnN0cnVtZW50by4gRG9zIGl0ZW1zCnF1ZSBkaWNlbiBsbyBtaXNtbyBjb21wYXJ0ZW4gdmFyaWFuemEgcXVlIG5pbmd1biBmYWN0b3IgY29tdW4gcHVlZGUgZXhwbGljYXIsIHkgZWwgbW9kZWxvCmxvIHJlZ2lzdHJhIGNvbW8gZGVzYWp1c3RlLgoKIyMjIFVuYSByZWdsYSBkZSBkZXB1cmFjaW9uIGV4cGxpY2l0YSwgY29uIHBpc28gZGUgdHJlcyBpdGVtcyBwb3IgZmFjdG9yCgpEZXB1cmFyIGEgb2pvIGVzIGRvbmRlIHNlIGN1ZWxhIGVsIHNlc2dvLiBFc2NyaWJvIGxhIHJlZ2xhIGNvbW8gZnVuY2lvbiBwYXJhIHF1ZSBzZWEKYXVkaXRhYmxlIHkgcGFyYSBxdWUgZWwgb3JkZW4gZGUgZWxpbWluYWNpb24gbm8gZGVwZW5kYSBkZSBtaSBjcml0ZXJpbyBkZWwgbW9tZW50bzoKCmBgYHtyIGVqMy1wMS1yZWdsYX0KIyBSZWdsYSwgZW4gZXN0ZSBvcmRlbiBkZSBwcmlvcmlkYWQ6CiMgICAxLiBjYXJnYSBlc3RhbmRhcml6YWRhIDwgLjcwICAgICAgICAgICAgLT4gZWwgaXRlbSBubyBtaWRlIGVsIGZhY3RvcgojICAgMi4gY2FyZ2EgY3J1emFkYSBjb24gTUkgPiAyMCAgICAgICAgICAgIC0+IGVsIGl0ZW0gbWlkZSBvdHJvIGZhY3RvcgojICAgMy4gcmVzaWR1YWxlcyBjb3JyZWxhY2lvbmFkb3MgY29uIE1JPjIwIC0+IHJlZHVuZGFuY2lhOiBjYWUgZWwgZGUgbWVub3IgY2FyZ2EKIyBSZXN0cmljY2lvbiBkdXJhOiBuaW5ndW4gZmFjdG9yIHB1ZWRlIHF1ZWRhciBjb24gbWVub3MgZGUgMyBpdGVtcywgcG9ycXVlCiMgdW4gZmFjdG9yIGRlIDIgaW5kaWNhZG9yZXMgbm8gc2UgaWRlbnRpZmljYSBwb3Igc2kgc29sbyB5IGVsIGNvbnN0cnVjdG8gc2UgdmFjaWEuCmZhY3Rvcl9kZSA8LSBmdW5jdGlvbihsaXN0YSwgaXRlbSkgbmFtZXMobGlzdGEpW3NhcHBseShsaXN0YSwgZnVuY3Rpb24odikgaXRlbSAlaW4lIHYpXVsxXQpwcm90ZWdpZG8gPC0gZnVuY3Rpb24obGlzdGEsIGl0ZW0sIG1pbl9pdGVtcykgbGVuZ3RoKGxpc3RhW1tmYWN0b3JfZGUobGlzdGEsIGl0ZW0pXV0pIDw9IG1pbl9pdGVtcwoKZGVwdXJhciA8LSBmdW5jdGlvbihsaXN0YSwgZGF0b3MsIG1heF9pdGVyID0gMTUsIG1pbl9pdGVtcyA9IDMsCiAgICAgICAgICAgICAgICAgICAgY29ydGUgPSBjKGNmaSA9IC45NSwgcm1zZWEgPSAuMDYsIHNybXIgPSAuMDgpKSB7CiAgdHJhemEgPC0gTlVMTAogIGZvciAoayBpbiAwOm1heF9pdGVyKSB7CiAgICBmaXQgPC0gY2ZhKHNpbnRheGlzKGxpc3RhKSwgZGF0YSA9IGRhdG9zLCBlc3RpbWF0b3IgPSAiTUxSIikKICAgIGZtICA8LSBmaXRNZWFzdXJlcyhmaXQsIElEWCkKICAgIGZpbGEgPC0gZGF0YS5mcmFtZShwYXNvID0gaywgaXRlbXMgPSBzdW0obGVuZ3RocyhsaXN0YSkpLAogICAgICAgICAgICAgICAgICAgICAgIGNoaXNxID0gcm91bmQoZm1bWyJjaGlzcSJdXSwgMSksIGdsID0gZm1bWyJkZiJdXSwKICAgICAgICAgICAgICAgICAgICAgICBDRkkgPSByb3VuZChmbVtbImNmaSJdXSwgMyksIFRMSSA9IHJvdW5kKGZtW1sidGxpIl1dLCAzKSwKICAgICAgICAgICAgICAgICAgICAgICBSTVNFQSA9IHJvdW5kKGZtW1sicm1zZWEiXV0sIDMpLCBTUk1SID0gcm91bmQoZm1bWyJzcm1yIl1dLCAzKSwKICAgICAgICAgICAgICAgICAgICAgICBlbGltaW5hZG8gPSBOQV9jaGFyYWN0ZXJfLCBtb3Rpdm8gPSBOQV9jaGFyYWN0ZXJfKQogICAgaWYgKGZtW1siY2ZpIl1dID49IGNvcnRlWyJjZmkiXSAmJiBmbVtbInJtc2VhIl1dIDw9IGNvcnRlWyJybXNlYSJdICYmCiAgICAgICAgZm1bWyJzcm1yIl1dIDw9IGNvcnRlWyJzcm1yIl0pIHsgdHJhemEgPC0gcmJpbmQodHJhemEsIGZpbGEpOyBicmVhayB9CgogICAgbGQgPC0gc3Vic2V0KHN0YW5kYXJkaXplZFNvbHV0aW9uKGZpdCksIG9wID09ICI9fiIpCiAgICBtaSA8LSBtb2RpbmRpY2VzKGZpdCkKICAgIGNhbmQgPC0gTkFfY2hhcmFjdGVyXzsgbW90aXZvIDwtIE5BX2NoYXJhY3Rlcl8KCiAgICBiYWphIDwtIGxkW29yZGVyKGxkJGVzdC5zdGQpLCBdCiAgICBiYWphIDwtIGJhamFbYmFqYSRlc3Quc3RkIDwgLjcwICYgIXNhcHBseShiYWphJHJocywgcHJvdGVnaWRvLCBsaXN0YSA9IGxpc3RhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluX2l0ZW1zID0gbWluX2l0ZW1zKSwgXQogICAgaWYgKG5yb3coYmFqYSkgPiAwKSB7CiAgICAgIGNhbmQgPC0gYmFqYSRyaHNbMV07IG1vdGl2byA8LSBzcHJpbnRmKCJjYXJnYSAlLjJmIDwgLjcwIiwgYmFqYSRlc3Quc3RkWzFdKQogICAgfQogICAgaWYgKGlzLm5hKGNhbmQpKSB7CiAgICAgIGNjIDwtIHN1YnNldChtaSwgb3AgPT0gIj1+IiAmIG1pID4gMjApOyBjYyA8LSBjY1tvcmRlcigtY2MkbWkpLCBdCiAgICAgIGNjIDwtIGNjWyFzYXBwbHkoY2MkcmhzLCBwcm90ZWdpZG8sIGxpc3RhID0gbGlzdGEsIG1pbl9pdGVtcyA9IG1pbl9pdGVtcyksIF0KICAgICAgaWYgKG5yb3coY2MpID4gMCkgewogICAgICAgIGNhbmQgPC0gY2MkcmhzWzFdOyBtb3Rpdm8gPC0gc3ByaW50ZigiY2FyZ2EgY3J1emFkYSBlbiAlcyAoTUk9JS4wZikiLCBjYyRsaHNbMV0sIGNjJG1pWzFdKQogICAgICB9CiAgICB9CiAgICBpZiAoaXMubmEoY2FuZCkpIHsKICAgICAgcnIgPC0gc3Vic2V0KG1pLCBvcCA9PSAifn4iICYgbGhzICE9IHJocyAmIG1pID4gMjApOyByciA8LSBycltvcmRlcigtcnIkbWkpLCBdCiAgICAgIGZvciAoaSBpbiBzZXFfbGVuKG5yb3cocnIpKSkgewogICAgICAgIHBhciA8LSBjKHJyJGxoc1tpXSwgcnIkcmhzW2ldKQogICAgICAgIHBhciA8LSBwYXJbb3JkZXIobGQkZXN0LnN0ZFttYXRjaChwYXIsIGxkJHJocyldKV0gICAjIHByaW1lcm8gZWwgZGUgbWVub3IgY2FyZ2EKICAgICAgICBsaWJyZSA8LSBwYXJbIXNhcHBseShwYXIsIHByb3RlZ2lkbywgbGlzdGEgPSBsaXN0YSwgbWluX2l0ZW1zID0gbWluX2l0ZW1zKV0KICAgICAgICBpZiAobGVuZ3RoKGxpYnJlKSA+IDApIHsKICAgICAgICAgIGNhbmQgPC0gbGlicmVbMV0KICAgICAgICAgIG1vdGl2byA8LSBzcHJpbnRmKCJyZWR1bmRhbnRlIGNvbiAlcyAoTUk9JS4wZikiLCBzZXRkaWZmKHBhciwgY2FuZCksIHJyJG1pW2ldKQogICAgICAgICAgYnJlYWsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChpcy5uYShjYW5kKSkgewogICAgICBmaWxhJG1vdGl2byA8LSAic2luIGNhbmRpZGF0b3MgZWxlZ2libGVzOiBzZSBkZXRpZW5lIgogICAgICB0cmF6YSA8LSByYmluZCh0cmF6YSwgZmlsYSk7IGJyZWFrCiAgICB9CiAgICBmaWxhJGVsaW1pbmFkbyA8LSBjYW5kOyBmaWxhJG1vdGl2byA8LSBtb3Rpdm8KICAgIHRyYXphIDwtIHJiaW5kKHRyYXphLCBmaWxhKQogICAgbGlzdGFbW2ZhY3Rvcl9kZShsaXN0YSwgY2FuZCldXSA8LSBzZXRkaWZmKGxpc3RhW1tmYWN0b3JfZGUobGlzdGEsIGNhbmQpXV0sIGNhbmQpCiAgfQogIGxpc3QoaXRlbXMgPSBsaXN0YSwgdHJhemEgPSB0cmF6YSwgZml0ID0gZml0KQp9CmBgYAoKYGBge3IgZWozLXAxLWRlcH0KZGVwX3JlYyA8LSBkZXB1cmFyKGl0ZW1zX3JlYywgZCkKa2FibGUoZGVwX3JlYyR0cmF6YSwgcm93Lm5hbWVzID0gRkFMU0UsCiAgICAgIGNhcHRpb24gPSAiVHJhemEgY29tcGxldGEgZGUgbGEgZGVwdXJhY2lvbjogcXVlIHNlIGVsaW1pbm8sIGVuIHF1ZSBwYXNvIHkgcG9yIHF1ZSIpCmBgYAoKYGBge3IgZWozLXAxLWZpbmFsLCBlY2hvPUZBTFNFfQplbGltaW5hZG9zIDwtIHNldGRpZmYodW5saXN0KGl0ZW1zX3JlYyksIHVubGlzdChkZXBfcmVjJGl0ZW1zKSkKa2FibGUoZGF0YS5mcmFtZShGYWN0b3IgPSBuYW1lcyhkZXBfcmVjJGl0ZW1zKSwKICAgICAgICAgICAgICAgICBJdGVtc19maW5hbGVzID0gc2FwcGx5KGRlcF9yZWMkaXRlbXMsIGxlbmd0aCksCiAgICAgICAgICAgICAgICAgQ3VhbGVzID0gc2FwcGx5KGRlcF9yZWMkaXRlbXMsIHBhc3RlLCBjb2xsYXBzZSA9ICIsICIpKSwKICAgICAgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiSW5zdHJ1bWVudG8gZGVwdXJhZG8iKQpgYGAKCkRlIGByIHN1bShsZW5ndGhzKGl0ZW1zX3JlYykpYCBpdGVtcyBxdWVkYW4gYHIgc3VtKGxlbmd0aHMoZGVwX3JlYyRpdGVtcykpYC4gU2UgZWxpbWluYXJvbjoKYHIgcGFzdGUoZWxpbWluYWRvcywgY29sbGFwc2UgPSAiLCAiKWAuCgojIyMgTGEgZGVwdXJhY2lvbiByZWRlc2N1YnJlIGxvIHF1ZSBsb3MgYXV0b3JlcyBkZWwgaW5zdHJ1bWVudG8geWEgc2FiaWFuCgpFc3RlIGVzIGVsIGNvbnRyb2wgZGUgY2FsaWRhZCBxdWUgbGUgZGEgY3JlZGliaWxpZGFkIGFsIHByb2NlZGltaWVudG8uIExhIGhvamEgZGUKaW5zdHJ1bWVudG9zIG1hcmNhIGNvbW8gKihlbGltaW5hdGVkKSogdmFyaW9zIGl0ZW1zIHF1ZSAqKnNpbiBlbWJhcmdvIHNpZ3VlbiBlbiBsYSBiYXNlKio6ClJQRDAxLCBSUEQwNiwgUk1BMDIgeSBSTUEwNi4gU2kgbWkgcmVnbGEgZXMgYnVlbmEsIGRlYmVyaWEgdm9sdmVyIGEgZW5jb250cmFybG9zIHNpbgpoYWJlcmxvcyB2aXN0bzoKCmBgYHtyIGVqMy1wMS1jb250cm9sLCBlY2hvPUZBTFNFfQptYXJjYWRvcyA8LSBjKCJSUEQwMSIsIlJQRDA2IiwiUk1BMDIiLCJSTUEwNiIpCmthYmxlKGRhdGEuZnJhbWUoSXRlbSA9IG1hcmNhZG9zLAogICAgICAgICAgICAgICAgIE1hcmNhZG9fcG9yX2xvc19hdXRvcmVzID0gImVsaW1pbmFkbyIsCiAgICAgICAgICAgICAgICAgTWlfcmVnbGEgPSBpZmVsc2UobWFyY2Fkb3MgJWluJSBlbGltaW5hZG9zLCAidGFtYmllbiBsbyBlbGltaW5hIiwgImxvIGNvbnNlcnZhIikpLAogICAgICByb3cubmFtZXMgPSBGQUxTRSwKICAgICAgY2FwdGlvbiA9ICJDb2luY2lkZW5jaWEgZW50cmUgbGEgZGVwdXJhY2lvbiBjaWVnYSB5IGxhcyBlbGltaW5hY2lvbmVzIGRvY3VtZW50YWRhcyIpCmBgYAoKVHJlcyBkZSBjdWF0cm8gY29pbmNpZGVuLiBFbCB1bmljbyBxdWUgY29uc2Vydm8gZXMgUlBEMDEgKCJNZSBvbHZpZGUgZGVsIHRyYWJham8iKSwgcXVlIGVuCmVzdGEgbXVlc3RyYSBjYXJnYQpgciByb3VuZChzdWJzZXQoc3RhbmRhcmRpemVkU29sdXRpb24oZGVwX3JlYyRmaXQpLCByaHM9PSJSUEQwMSIpJGVzdC5zdGRbMV0sIDMpYAp5IG5vIHZpb2xhIG5pbmd1biBjcml0ZXJpby4gUXVlIHVuYSByZWdsYSBtZWNhbmljYSByZXByb2R1emNhIGRlY2lzaW9uZXMgcXVlIHNlIHRvbWFyb24KcG9yIGp1aWNpbyBkZSBleHBlcnRvcyBlcyBsYSBtZWpvciBldmlkZW5jaWEgZGUgcXVlIG5vIGVzdG95IHNvbG8gcGVyc2lndWllbmRvIGluZGljZXMuCgojIyMgRWwgbW9kZWxvIGRlIHNlZ3VuZG8gb3JkZW46IGxvcyBjdWF0cm8gZG9taW5pb3Mgc29uIGZhY2V0YXMgZGUgdW4gbWlzbW8gY29uc3RydWN0bwoKSGFzdGEgYXF1aSB0ZW5nbyBjdWF0cm8gZmFjdG9yZXMgY29ycmVsYWNpb25hZG9zLiBMYSBwcmVndW50YSBkZWwgZWplcmNpY2lvIGVzIHNpIGV4aXN0ZQp1biBmYWN0b3Igc3VwZXJpb3IsICoqZXhwZXJpZW5jaWFzIGRlIHJlY3VwZXJhY2lvbioqLCBxdWUgZXhwbGlxdWUgKnBvciBxdWUqIGVzb3MgY3VhdHJvCmNvcnJlbGFjaW9uYW4uIEVzIHVuYSBoaXBvdGVzaXMgbWFzIGZ1ZXJ0ZSB5IHBvciBsbyB0YW50byBtYXMgZmFjaWwgZGUgcmVmdXRhcjogZWwgbW9kZWxvCmRlIHNlZ3VuZG8gb3JkZW4gcmVwcm9kdWNlIGxhcyBzZWlzIGNvcnJlbGFjaW9uZXMgZW50cmUgZG9taW5pb3MgY29uIHNvbG8gY3VhdHJvIGNhcmdhcywKYXNpIHF1ZSBnYXN0YSBkb3MgZ3JhZG9zIGRlIGxpYmVydGFkIG1lbm9zLgoKYGBge3IgZWozLXAxLXNlZ30KbW9kX3NlZyA8LSBwYXN0ZShzaW50YXhpcyhkZXBfcmVjJGl0ZW1zKSwKICAgICAgICAgICAgICAgICAiXG4gUkVDVVBFUkFDSU9OID1+IERFU0FQRUdPICsgUkVMQUpBQ0lPTiArIE1BRVNUUklBICsgQ09OVFJPTCIpCmZpdF9zZWcgPC0gY2ZhKG1vZF9zZWcsIGRhdGEgPSBkLCBlc3RpbWF0b3IgPSAiTUxSIikKa2FibGUodGFibGFfYWp1c3RlKGRlcF9yZWMkZml0LCBmaXRfc2VnLAogICAgICBldGlxdWV0YXMgPSBjKCIxZXIgb3JkZW46IDQgZmFjdG9yZXMgY29ycmVsYWNpb25hZG9zIiwgIjJvIG9yZGVuOiBSRUNVUEVSQUNJT04iKSksCiAgICAgIGNhcHRpb24gPSAiRWwgZmFjdG9yIGRlIHNlZ3VuZG8gb3JkZW4gbm8gY3Vlc3RhIGFqdXN0ZSIpCmBgYAoKYGBge3IgZWozLXAxLWFub3ZhfQpjb21wYXJhcihkZXBfcmVjJGZpdCwgZml0X3NlZywKICAgICAgICAgYygiMWVyIG9yZGVuOiA0IGZhY3RvcmVzIGNvcnJlbGFjaW9uYWRvcyIsICIybyBvcmRlbjogUkVDVVBFUkFDSU9OIiksCiAgICAgICAgICJMYSBlc3RydWN0dXJhIGplcmFycXVpY2Egbm8gZW1wZW9yYSBlbCBtb2RlbG8gZGUgZm9ybWEgZGV0ZWN0YWJsZSIpCmBgYAoKYGBge3IgZWozLXAxLWNhcmdhczIsIGVjaG89RkFMU0V9CmMyIDwtIHN1YnNldChzdGFuZGFyZGl6ZWRTb2x1dGlvbihmaXRfc2VnKSwgbGhzID09ICJSRUNVUEVSQUNJT04iICYgb3AgPT0gIj1+IikKa2FibGUoYzJbLCBjKCJyaHMiLCJlc3Quc3RkIiwic2UiLCJwdmFsdWUiKV0sIHJvdy5uYW1lcyA9IEZBTFNFLCBkaWdpdHMgPSAzLAogICAgICBjb2wubmFtZXMgPSBjKCJEb21pbmlvIiwiQ2FyZ2EgZXN0YW5kYXJpemFkYSIsIkVFIiwicCIpLAogICAgICBjYXB0aW9uID0gIkNhcmdhcyBkZSBzZWd1bmRvIG9yZGVuOiBsb3MgY3VhdHJvIGRvbWluaW9zIHBlcnRlbmVjZW4gYWwgbWlzbW8gY29uc3RydWN0byIpCmBgYAoKTGEgZGlmZXJlbmNpYSBkZSBjaGktY3VhZHJhZGEgY29uIDIgZ3JhZG9zIGRlIGxpYmVydGFkICoqbm8gZXMgc2lnbmlmaWNhdGl2YSoqCihwID0gYHIgcm91bmQoc3VwcHJlc3NXYXJuaW5ncyhsYXZUZXN0TFJUKGZpdF9zZWcsIGRlcF9yZWMkZml0KSlbMiwiUHIoPkNoaXNxKSJdLCAzKWApOiBpbXBvbmVyIGxhIGVzdHJ1Y3R1cmEKamVyYXJxdWljYSBubyBlbXBlb3JhIGVsIG1vZGVsbyBkZSBmb3JtYSBkZXRlY3RhYmxlLiBMYXMgY3VhdHJvIGNhcmdhcyBzb24gc2lnbmlmaWNhdGl2YXMsCnBlcm8gZGVzaWd1YWxlczogcmVsYWphY2lvbiAoYHIgcm91bmQoYzIkZXN0LnN0ZFsyXSwzKWApIHkgY29udHJvbAooYHIgcm91bmQoYzIkZXN0LnN0ZFs0XSwzKWApIHNvbiBjYXNpIHNpbm9uaW1vcyBkZWwgY29uc3RydWN0byBnZW5lcmFsLCBtaWVudHJhcyBkZXNhcGVnbwooYHIgcm91bmQoYzIkZXN0LnN0ZFsxXSwzKWApIHkgbWFlc3RyaWEgKGByIHJvdW5kKGMyJGVzdC5zdGRbM10sMylgKSBjb25zZXJ2YW4gYmFzdGFudGUKaWRlbnRpZGFkIHByb3BpYS4gVHJhZHVjaWRvOiBxdWllbiBzZSByZWN1cGVyYSBiaWVuIGNhc2kgc2llbXByZSBzZSByZWxhamEgeSBjb250cm9sYSBzdQp0aWVtcG8sIHBlcm8gZGVzY29uZWN0YXJzZSBtZW50YWxtZW50ZSB5IGJ1c2NhciByZXRvcyBzb24gY29zYXMgcXVlICoqYWxndW5hcyBwZXJzb25hcwpoYWNlbiB5IG90cmFzIG5vKiosIGNvbiByZWxhdGl2YSBpbmRlcGVuZGVuY2lhIGRlIHN1IG5pdmVsIGdlbmVyYWwgZGUgcmVjdXBlcmFjaW9uLgoKIyMgUGFydGUgMjogYW5hbGlzaXMgZmFjdG9yaWFsIGNvbmZpcm1hdG9yaW8gZGVsIGNvbnN0cnVjdG8gZGUgZW5lcmdpYSByZWN1cGVyYWRhCgpgYGB7ciBlajMtcDJ9Cml0ZW1zX2VuIDwtIGdyZXAoIl5FTjAiLCBuYW1lcyhkKSwgdmFsdWUgPSBUUlVFKQpmaXRfZW4gPC0gY2ZhKHBhc3RlMCgiRU5FUkdJQSA9fiAiLCBwYXN0ZShpdGVtc19lbiwgY29sbGFwc2UgPSAiICsgIikpLAogICAgICAgICAgICAgIGRhdGEgPSBkLCBlc3RpbWF0b3IgPSAiTUxSIikKa2FibGUodGFibGFfYWp1c3RlKGZpdF9lbiwgZXRpcXVldGFzID0gIkVORVJHSUEgdW5pZGltZW5zaW9uYWwsIDcgaXRlbXMiKSwKICAgICAgY2FwdGlvbiA9ICJDRkksIFRMSSB5IFNSTVIgZXhjZWxlbnRlczsgUk1TRUEgZnVlcmEgZGUgY3JpdGVyaW8iKQprYWJsZShjYXJnYXMoZml0X2VuKSwgcm93Lm5hbWVzID0gRkFMU0UsIGRpZ2l0cyA9IDMsCiAgICAgIGNhcHRpb24gPSAiTGFzIHNpZXRlIGNhcmdhcyBwb3IgYXJyaWJhIGRlIC44OSIpCmBgYAoKTG9zIHNpZXRlIGl0ZW1zIHNlIGFncnVwYW4gZW4gKip1bmEgc29sYSBkaW1lbnNpb24qKiwgeSBkZSBmb3JtYSBjb250dW5kZW50ZTogbGEgY2FyZ2EgbWFzCmJhamEgZXMgYHIgcm91bmQobWluKGNhcmdhcyhmaXRfZW4pJENhcmdhX2VzdGFuZGFyaXphZGEpLDMpYCB5IGVsIFNSTVIgZXMKYHIgcm91bmQoZml0TWVhc3VyZXMoZml0X2VuLCJzcm1yIiksMylgLCBwcmFjdGljYW1lbnRlIGNlcm8uIExhIHJlc3B1ZXN0YSBhIGxhIHByZWd1bnRhCmRlbCBlamVyY2ljaW8gZXMgc2kuCgpFbCBSTVNFQSBkZSBgciByb3VuZChmaXRNZWFzdXJlcyhmaXRfZW4sInJtc2VhIiksMylgIHBhcmVjZSBjb250cmFkZWNpcmxvLiBObyBsbyBoYWNlLCB5CnZhbGUgbGEgcGVuYSBlbnRlbmRlciBwb3IgcXVlIGVuIGx1Z2FyIGRlICJhcnJlZ2xhcmxvIjoKCmBgYHtyIGVqMy1wMi1kZXB9CmRlcF9lbiA8LSBkZXB1cmFyKGxpc3QoRU5FUkdJQSA9IGl0ZW1zX2VuKSwgZCkKa2FibGUoZGVwX2VuJHRyYXphLCByb3cubmFtZXMgPSBGQUxTRSwKICAgICAgY2FwdGlvbiA9ICJMYSByZWdsYSBkZSBkZXB1cmFjaW9uIG5vIGVuY3VlbnRyYSB1biBzb2xvIGl0ZW0gcXVlIGVsaW1pbmFyIikKYGBgCgpOaW5ndW4gaXRlbSB0aWVuZSBjYXJnYSBiYWphLCBuaW5ndW5vIGNhcmdhIGVuIG90cm8gZmFjdG9yLCB5IGVsIHJlc2lkdWFsIGNvcnJlbGFjaW9uYWRvCm1hcyBncmFuZGUgdGllbmUgTUkgZGUKYHIgcm91bmQobWF4KHN1YnNldChtb2RpbmRpY2VzKGZpdF9lbiksIG9wPT0ifn4iICYgbGhzIT1yaHMpJG1pKSwxKWAsIHBvciBkZWJham8gZGVsIHVtYnJhbC4KKipObyBoYXkgbmFkYSBxdWUgZGVwdXJhci4qKiBFbCBSTVNFQSBhbHRvIGVzIGNvbnNlY3VlbmNpYSBkZSBzdSBmb3JtdWxhOiBwZW5hbGl6YSBwb3IKZ3JhZG8gZGUgbGliZXJ0YWQsIHkgY29uIHNvbG8gYHIgZml0TWVhc3VyZXMoZml0X2VuLCJkZiIpYCBncmFkb3MgZGUgbGliZXJ0YWQgeSBjYXJnYXMgdGFuCmFsdGFzLCBjdWFscXVpZXIgZGlzY3JlcGFuY2lhIG1pbmltYSBzZSBhbXBsaWZpY2EuIEVzIGVsIHByb2JsZW1hIGNvbm9jaWRvIGRlIFJNU0VBIGVuCm1vZGVsb3MgcGVxdWVuaW9zIChLZW5ueSwgS2FuaXNrYW4geSBNY0NvYWNoLCAyMDE1KS4gRm9yemFyIGxhIG1lam9yYSBlbGltaW5hbmRvIGl0ZW1zCmJ1ZW5vcyBzZXJpYSBtYXF1aWxsYXIgZWwgaW5kaWNlIGEgY29zdGEgZGVsIGNvbnN0cnVjdG8uCgoqKkxvIHF1ZSBzaSBtZSBwcmVvY3VwYSoqIGVzIGxvIGNvbnRyYXJpbzogY2FyZ2FzIGRlIC44OSBhIC45NSBlbnRyZSBzaWV0ZSByZWFjdGl2b3MKc3VnaWVyZW4gcXVlIGVsIGluc3RydW1lbnRvIHByZWd1bnRhIGxvIG1pc21vIHNpZXRlIHZlY2VzICgibWUgc2llbnRvIHJlbm92YWRvIiwKIm1lIHNpZW50byBjb21vIG51ZXZvIiwgInJlY3VwZXJlIG1pIGVuZXJnaWEiKS4gTWlkZSBiaWVuLCBwZXJvIGVzIGluZWZpY2llbnRlOiB0cmVzIGl0ZW1zCnByb2JhYmxlbWVudGUgZGFyaWFuIGxhIG1pc21hIGluZm9ybWFjaW9uLgoKIyMgUGFydGUgMzogYW5hbGlzaXMgZGUgc2VuZGVyb3MgY29uIGxhIGVuZXJnaWEgcmVjdXBlcmFkYSBjb21vIG1lZGlhZG9yYQoKIyMjIENvbnN0cnVjY2lvbiBkZSBsb3MgY29tcHVlc3RvcwoKYGBge3IgZWozLXAzLWNvbXB9CmZvciAobm0gaW4gbmFtZXMoZGVwX3JlYyRpdGVtcykpIGRbW25tXV0gPC0gcm93TWVhbnMoZFssIGRlcF9yZWMkaXRlbXNbW25tXV1dKQpkJFJFQ1VQIDwtIHJvd01lYW5zKGRbLCBuYW1lcyhkZXBfcmVjJGl0ZW1zKV0pICAgIyBwcm9tZWRpbyBkZSBsb3MgNCBkb21pbmlvcwpkJEVORVIgIDwtIHJvd01lYW5zKGRbLCBpdGVtc19lbl0pCml0ZW1zX2VuZyA8LSBjKCJFVkkwMSIsIkVWSTAyIiwiRVZJMDMiLCJFREUwMSIsIkVERTAyIiwiRURFMDMiLCJFQUIwMSIsIkVBQjAyIiwiRUFCMDMiKQpkJEVOR0EgIDwtIHJvd01lYW5zKGRbLCBpdGVtc19lbmddKQprYWJsZShyb3VuZChjb3IoZFssIGMoIkRFU0FQRUdPIiwiUkVMQUpBQ0lPTiIsIk1BRVNUUklBIiwiQ09OVFJPTCIsIlJFQ1VQIiwiRU5FUiIsIkVOR0EiKV0pLCAyKSwKICAgICAgY2FwdGlvbiA9ICJNYXRyaXogZGUgY29ycmVsYWNpb25lcyBkZSBsb3MgY29tcHVlc3RvcyIpCmBgYAoKQ2FkYSBkb21pbmlvIHBlc2EgaWd1YWwgZW4gYFJFQ1VQYCAocHJvbWVkaW8gZGUgcHJvbWVkaW9zLCBubyBwcm9tZWRpbyBkZSBpdGVtcyksIHBhcmEgcXVlCmRlc2FwZWdvIGNvbiBzZWlzIGl0ZW1zIG5vIGRvbWluZSBhIHJlbGFqYWNpb24gY29uIHRyZXMuCgojIyMgUG9yIHF1ZSBlbCBtb2RlbG8gZGUgbWVkaWFjaW9uIHNpbXBsZSBubyBzZSBwdWVkZSBldmFsdWFyIHBvciBhanVzdGUKCmBgYHtyIGVqMy1wMy1zYXR9Cm1vZF9zYXQgPC0gJyBFTkVSIH4gYSpSRUNVUAogICAgICAgICAgICAgRU5HQSB+IGNwKlJFQ1VQICsgYipFTkVSCiAgICAgICAgICAgICBpbmRpcmVjdG8gOj0gYSpiCiAgICAgICAgICAgICB0b3RhbCAgICAgOj0gY3AgKyBhKmIgJwpmaXRfc2F0IDwtIHNlbShtb2Rfc2F0LCBkYXRhID0gZCwgc2UgPSAiYm9vdHN0cmFwIiwgYm9vdHN0cmFwID0gMTAwMCkKa2FibGUodGFibGFfYWp1c3RlKGZpdF9zYXQsIGV0aXF1ZXRhcyA9ICJtZWRpYWNpb24gcGFyY2lhbCAoMyB2YXJpYWJsZXMpIiksCiAgICAgIGNhcHRpb24gPSAiQWp1c3RlIHBlcmZlY3RvIHkgdmFjaW86IGVsIG1vZGVsbyBlc3RhIHNhdHVyYWRvIikKYGBgCgpFbCBlamVyY2ljaW8gcGlkZSByZXZpc2FyIGxvcyBpbmRpY2VzIGRlIGFqdXN0ZSwgeSBhcXVpIGxhIHJlc3B1ZXN0YSBjb3JyZWN0YSBlcyBxdWUKKipubyBkaWNlbiBuYWRhKiouIENvbiB0cmVzIHZhcmlhYmxlcyBvYnNlcnZhZGFzIGhheSA2IG1vbWVudG9zIHkgZWwgbW9kZWxvIGVzdGltYSA2CnBhcmFtZXRyb3M6IGNlcm8gZ3JhZG9zIGRlIGxpYmVydGFkLiBDRkkgPSAxIHkgUk1TRUEgPSAwIHNvbiBhcml0bWV0aWNhLCBubyBldmlkZW5jaWEuClVuIG1vZGVsbyBzYXR1cmFkbyByZXByb2R1Y2UgY3VhbHF1aWVyIG1hdHJpeiBkZSBjb3ZhcmlhbnphcywgaW5jbHVpZGEgdW5hIGdlbmVyYWRhIGFsCmF6YXIuCgpQYXJhIHF1ZSBlbCBhanVzdGUgc2lnbmlmaXF1ZSBhbGdvIGhheSBxdWUgKippbXBvbmVyIHVuYSByZXN0cmljY2lvbiBmYWxzYWJsZSoqLiBEb3MKY2FtaW5vcywgeSB0b21vIGxvcyBkb3MuCgojIyMgQ2FtaW5vIDE6IGxhIG1lZGlhY2lvbiBjb21wbGV0YSBjb21vIGhpcG90ZXNpcyBjb250cmFzdGFibGUKCmBgYHtyIGVqMy1wMy1jb21wMn0KbW9kX2Z1bGwgPC0gJyBFTkVSIH4gYSpSRUNVUAogICAgICAgICAgICAgIEVOR0EgfiBiKkVORVIKICAgICAgICAgICAgICBpbmRpcmVjdG8gOj0gYSpiICcKZml0X2Z1bGwgPC0gc2VtKG1vZF9mdWxsLCBkYXRhID0gZCkKa2FibGUodGFibGFfYWp1c3RlKGZpdF9mdWxsLCBmaXRfc2F0LAogICAgICBldGlxdWV0YXMgPSBjKCJtZWRpYWNpb24gY29tcGxldGEgKGdsPTEpIiwgIm1lZGlhY2lvbiBwYXJjaWFsIChnbD0wKSIpKSwKICAgICAgY2FwdGlvbiA9ICJBbCBmaWphciBlbCBjYW1pbm8gZGlyZWN0byBlbiBjZXJvLCBlbCBtb2RlbG8gcG9yIGZpbiBzZSBwdWVkZSByZWZ1dGFyIikKY29tcGFyYXIoZml0X2Z1bGwsIGZpdF9zYXQsCiAgICAgICAgIGMoIm1lZGlhY2lvbiBjb21wbGV0YSIsICJtZWRpYWNpb24gcGFyY2lhbCIpLAogICAgICAgICAiUHJ1ZWJhIGRlIGxhIHJlc3RyaWNjaW9uIGRlIG1lZGlhY2lvbiBjb21wbGV0YSAobWVkaWFjaW9uIHNpbXBsZSkiKQpgYGAKCiMjIyBDYW1pbm8gMjogYWJyaXIgbGEgcmVjdXBlcmFjaW9uIGVuIHN1cyBjdWF0cm8gZG9taW5pb3MKCmBgYHtyIGVqMy1wMy1kb219Cm1vZF9kb20gPC0gJyBFTkVSIH4gYTEqREVTQVBFR08gKyBhMipSRUxBSkFDSU9OICsgYTMqTUFFU1RSSUEgKyBhNCpDT05UUk9MCiAgICAgICAgICAgICBFTkdBIH4gYipFTkVSCiAgICAgICAgICAgICBpX2Rlc2FwZWdvICAgOj0gYTEqYgogICAgICAgICAgICAgaV9yZWxhamFjaW9uIDo9IGEyKmIKICAgICAgICAgICAgIGlfbWFlc3RyaWEgICA6PSBhMypiCiAgICAgICAgICAgICBpX2NvbnRyb2wgICAgOj0gYTQqYiAnCmZpdF9kb20gPC0gc2VtKG1vZF9kb20sIGRhdGEgPSBkLCBzZSA9ICJib290c3RyYXAiLCBib290c3RyYXAgPSAxMDAwKQoKbW9kX2RvbV9wIDwtICcgRU5FUiB+IGExKkRFU0FQRUdPICsgYTIqUkVMQUpBQ0lPTiArIGEzKk1BRVNUUklBICsgYTQqQ09OVFJPTAogICAgICAgICAgICAgICBFTkdBIH4gYipFTkVSICsgYzEqREVTQVBFR08gKyBjMipSRUxBSkFDSU9OICsgYzMqTUFFU1RSSUEgKyBjNCpDT05UUk9MICcKZml0X2RvbV9wIDwtIHNlbShtb2RfZG9tX3AsIGRhdGEgPSBkKQoKa2FibGUodGFibGFfYWp1c3RlKGZpdF9kb20sIGZpdF9kb21fcCwKICAgICAgZXRpcXVldGFzID0gYygibWVkaWFjaW9uIGNvbXBsZXRhIChnbD00KSIsICJtZWRpYWNpb24gcGFyY2lhbCAoc2F0dXJhZG8pIikpLAogICAgICBjYXB0aW9uID0gIkVsIG1vZGVsbyBkZSBtZWRpYWNpb24gY29tcGxldGEgYWp1c3RhIGNhc2kgcGVyZmVjdG8gY29uIDQgZ3JhZG9zIGRlIGxpYmVydGFkIikKY29tcGFyYXIoZml0X2RvbSwgZml0X2RvbV9wLAogICAgICAgICBjKCJtZWRpYWNpb24gY29tcGxldGEiLCAibWVkaWFjaW9uIHBhcmNpYWwiKSwKICAgICAgICAgIlF1aXRhciBsb3MgY3VhdHJvIGNhbWlub3MgZGlyZWN0b3Mgbm8gZW1wZW9yYSBlbCBtb2RlbG8iKQpgYGAKCkxhIGNoaS1jdWFkcmFkYSBkZSBgciByb3VuZChmaXRNZWFzdXJlcyhmaXRfZG9tLCJjaGlzcSIpLDIpYCBjb24gNCBncmFkb3MgZGUgbGliZXJ0YWQKKipubyBlcyBzaWduaWZpY2F0aXZhKiogKHAgPSBgciByb3VuZChmaXRNZWFzdXJlcyhmaXRfZG9tLCJwdmFsdWUiKSwzKWApLiBFbGltaW5hciBsb3MKY3VhdHJvIGNhbWlub3MgZGlyZWN0b3Mgbm8gZW1wZW9yYSBlbCBtb2RlbG8uIFkgZWwgbW9kZWxvIHNhdHVyYWRvIGV4cGxpY2EgcG9yIHF1ZToKCmBgYHtyIGVqMy1wMy1kaXJlY3RvcywgZWNobz1GQUxTRX0KcGQgPC0gc3Vic2V0KHBhcmFtZXRlckVzdGltYXRlcyhmaXRfZG9tX3AsIHN0YW5kYXJkaXplZCA9IFRSVUUpLCBvcCA9PSAifiIgJiBsaHMgPT0gIkVOR0EiKQprYWJsZShwZFssIGMoImxocyIsInJocyIsImVzdCIsInNlIiwicHZhbHVlIiwic3RkLmFsbCIpXSwgcm93Lm5hbWVzID0gRkFMU0UsIGRpZ2l0cyA9IDMsCiAgICAgIGNvbC5uYW1lcyA9IGMoIkRlc3Rpbm8iLCJPcmlnZW4iLCJFc3RpbWFkbyIsIkVFIiwicCIsIkVzdGFuZGFyaXphZG8iKSwKICAgICAgY2FwdGlvbiA9ICJOaW5ndW5vIGRlIGxvcyBjdWF0cm8gY2FtaW5vcyBkaXJlY3RvcyBoYWNpYSBlbmdhZ2VtZW50IGVzIHNpZ25pZmljYXRpdm8iKQpgYGAKCk5pbmd1bm8gZGUgbG9zIGN1YXRybyBkb21pbmlvcyBsbGVnYSBhbCBlbmdhZ2VtZW50IHBvciBzdSBjdWVudGEuICoqVG9kYSoqIGxhIHJlbGFjaW9uCnBhc2EgcG9yIGxhIGVuZXJnaWEgcmVjdXBlcmFkYS4KCiMjIyBFZmVjdG9zIGluZGlyZWN0b3MsIGNvbiBpbnRlcnZhbG9zIGJvb3RzdHJhcAoKYGBge3IgZWozLXAzLWVmZWN0b3N9CmVmMyA8LSBwYXJhbWV0ZXJFc3RpbWF0ZXMoZml0X2RvbSwgYm9vdC5jaS50eXBlID0gInBlcmMiLCBzdGFuZGFyZGl6ZWQgPSBUUlVFKQplZjMgPC0gc3Vic2V0KGVmMywgb3AgJWluJSBjKCJ+IiwgIjo9IikpWywgYygibGhzIiwicmhzIiwibGFiZWwiLCJlc3QiLCJzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwdmFsdWUiLCJjaS5sb3dlciIsImNpLnVwcGVyIiwic3RkLmFsbCIpXQprYWJsZShlZjMsIHJvdy5uYW1lcyA9IEZBTFNFLCBkaWdpdHMgPSAzLAogICAgICBjb2wubmFtZXMgPSBjKCJEZXN0aW5vIiwiT3JpZ2VuIiwiRXRpcXVldGEiLCJFc3QiLCJFRSIsInAiLCJJQyAyLjUlIiwiSUMgOTcuNSUiLCJFc3RhbmQuIiksCiAgICAgIGNhcHRpb24gPSAiRWZlY3RvcyBkZWwgbW9kZWxvIGRlIG1lZGlhY2lvbiBjb21wbGV0YSAoMTAwMCByZW11ZXN0cmVvcyBib290c3RyYXApIikKcjIgPC0gaW5zcGVjdChmaXRfZG9tLCAicjIiKQprYWJsZShkYXRhLmZyYW1lKFZhcmlhYmxlID0gbmFtZXMocjIpLCBSMiA9IHJvdW5kKGFzLm51bWVyaWMocjIpLCAzKSksCiAgICAgIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIlZhcmlhbnphIGV4cGxpY2FkYSIpCmBgYAoKRWwgcHJvZHVjdG8gZGUgY29lZmljaWVudGVzIG5vIHNlIGRpc3RyaWJ1eWUgbm9ybWFsLCBwb3IgZXNvIGVsIGludGVydmFsbyBib290c3RyYXAgeSBubwplbCBlcnJvciBlc3RhbmRhciBkZSBXYWxkLiBZIGxhIGRpZmVyZW5jaWEgaW1wb3J0YTogKipyZWxhamFjaW9uKiogdGllbmUgcCA9CmByIHJvdW5kKGVmMyRwdmFsdWVbZWYzJGxhYmVsPT0iaV9yZWxhamFjaW9uIl0sMylgIHBvciBXYWxkIHBlcm8gc3UgaW50ZXJ2YWxvIGJvb3RzdHJhcAooYHIgcm91bmQoZWYzJGNpLmxvd2VyW2VmMyRsYWJlbD09ImlfcmVsYWphY2lvbiJdLDMpYCBhCmByIHJvdW5kKGVmMyRjaS51cHBlcltlZjMkbGFiZWw9PSJpX3JlbGFqYWNpb24iXSwzKWApICoqaW5jbHV5ZSBlbCBjZXJvKiouIENvbiBlbApjcml0ZXJpbyBtYXMgZXhpZ2VudGUsIHF1ZSBlcyBlbCBjb3JyZWN0byBhcXVpLCBzdSBlZmVjdG8gbm8gZXN0YSBkZW1vc3RyYWRvLgoKT3JkZW4gZGUgaW1wb3J0YW5jaWEgcG9yIGVmZWN0byBpbmRpcmVjdG8gZXN0YW5kYXJpemFkbzoKCmBgYHtyIGVqMy1wMy1vcmRlbiwgZWNobz1GQUxTRX0KaW5kIDwtIGVmM1tzdGFydHNXaXRoKGVmMyRsYWJlbCwgImlfIiksIF0KaW5kIDwtIGluZFtvcmRlcigtaW5kJHN0ZC5hbGwpLCBjKCJsYWJlbCIsInN0ZC5hbGwiLCJjaS5sb3dlciIsImNpLnVwcGVyIildCmluZCRjb25jbHVzaW9uIDwtIGlmZWxzZShpbmQkY2kubG93ZXIgPiAwLCAiZWZlY3RvIHNvc3RlbmlkbyIsICJubyBkaXN0aW5ndWlibGUgZGUgY2VybyIpCmthYmxlKGluZCwgcm93Lm5hbWVzID0gRkFMU0UsIGRpZ2l0cyA9IDMsCiAgICAgIGNvbC5uYW1lcyA9IGMoIkRvbWluaW8iLCJFZmVjdG8gaW5kaXJlY3RvIGVzdGFuZC4iLCJJQyAyLjUlIiwiSUMgOTcuNSUiLCJDb25jbHVzaW9uIiksCiAgICAgIGNhcHRpb24gPSAiQ29udHJvbCBzb2JyZSBlbCB0aWVtcG8gbGlicmUgZXMsIHBvciBtdWNobywgZWwgZG9taW5pbyBxdWUgbWFzIHJpbmRlIikKYGBgCgojIyMgTGVjdHVyYSBwYXJhIGxhIG9yZ2FuaXphY2lvbgoKRWwgcmVzdWx0YWRvIHRpZW5lIHVuYSBpbXBsaWNhY2lvbiBwcmFjdGljYSBjb25jcmV0YSB5IGFsZ28gaW5jb21vZGEgcGFyYSBsYXMgYXJlYXMgZGUKcmVjdXJzb3MgaHVtYW5vczogKiplbCBlbmdhZ2VtZW50IG5vIHNlIGNvbXByYSBjb24gYWN0aXZpZGFkZXMgZGUgYmllbmVzdGFyKiouIE5pbmd1bmEgZGUKbGFzIGN1YXRybyBleHBlcmllbmNpYXMgZGUgcmVjdXBlcmFjaW9uIG11ZXZlIGVsIGVuZ2FnZW1lbnQgZGlyZWN0YW1lbnRlLiBMbyBtdWV2ZW4gc29sbwplbiBsYSBtZWRpZGEgZW4gcXVlIGVsIGNvbGFib3JhZG9yIGVmZWN0aXZhbWVudGUgKipyZWN1cGVyYSBlbmVyZ2lhKiouIFVuIHByb2dyYW1hIGRlIHlvZ2EKYWwgcXVlIGxhIGdlbnRlIGFzaXN0ZSBzaW4gZGVzY29uZWN0YXJzZSBubyBjYW1iaWEgbmFkYS4KClkgZW50cmUgbG9zIGN1YXRybyBkb21pbmlvcywgZWwgcXVlIG1hcyByaW5kZSBlcyAqKmNvbnRyb2wgc29icmUgZWwgdGllbXBvIGxpYnJlKioKKGByIHJvdW5kKGluZCRzdGQuYWxsWzFdLDMpYCksIHF1ZSBubyBjdWVzdGEgcHJlc3VwdWVzdG86IGN1ZXN0YSBwb2xpdGljYSBkZSBsYSBlbXByZXNhLgpFcyBsYSBkaWZlcmVuY2lhIGVudHJlIG9yZ2FuaXphciBhY3RpdmlkYWRlcyBwYXJhIGxhIGdlbnRlIHkgZGVqYXIgcXVlIGxhIGdlbnRlIGRlY2lkYQpjb21vIHVzYSBzdSB0aWVtcG8uCgojIyBQYXJ0ZSA0OiBlbCBtb2RlbG8gZGUgbWVkaWNpb24KCkVsIG1vZGVsbyBkZSBzZW5kZXJvcyBkZSBsYSBQYXJ0ZSAzIHN1cG9uZSBhbGdvIGZ1ZXJ0ZSB5IGZhbHNvOiBxdWUgbG9zIGNvbXB1ZXN0b3MgbWlkZW4Kc2luIGVycm9yLiBVbiBwcm9tZWRpbyBkZSBpdGVtcyBubyBlcyBlbCBjb25zdHJ1Y3RvLiBFbCBtb2RlbG8gZGUgbWVkaWNpb24gbGV2YW50YSBlc2UKc3VwdWVzdG8gcG9uaWVuZG8gY2FkYSB2YXJpYWJsZSBsYXRlbnRlIGNvbiBzdXMgaW5kaWNhZG9yZXMuCgpgYGB7ciBlajMtcDQtZGlhZ30Ka2FibGUocm91bmQoY29yKGRbLCBpdGVtc19lbmddKSwgMiksCiAgICAgIGNhcHRpb24gPSAiTG9zIGl0ZW1zIGRlIGVuZ2FnZW1lbnQ6IGNvcnJlbGFjaW9uZXMgcXVlIGRlY2FlbiBzZWd1biBsYSBkaXN0YW5jaWEgZW4gZWwgY3Vlc3Rpb25hcmlvIikKYGBgCgpBbnRlcyBkZSBlc3RpbWFyIGhheSBxdWUgdmVyIGVsIHByb2JsZW1hLiBMYSBtYXRyaXogKipubyoqIHRpZW5lIGxhIGVzdHJ1Y3R1cmEgZGUgYmxvcXVlcwpxdWUgcHJlZGljZSBsYSB0ZW9yaWEgZGUgdHJlcyBmYWN0b3JlcyAodmlnb3IsIGRlZGljYWNpb24sIGFic29yY2lvbikuIFRpZW5lIHVuCioqZ3JhZGllbnRlKio6IGNhZGEgaXRlbSBjb3JyZWxhY2lvbmEgbWFzIGNvbiBlbCBxdWUgZXN0YSBhIHN1IGxhZG8gZW4gZWwgY3Vlc3Rpb25hcmlvCihFVkkwMS0tRVZJMDIgPSAuOTQsIEVERTAxLS1FREUwMiA9IC44OSkgeSBtZW5vcyBjb25mb3JtZSBzZSBhbGVqYSAoRVZJMDEtLUVBQjAzID0gLjQ0KS4KRURFMDEgY29ycmVsYWNpb25hIG1hcyBjb24gRVZJMDMgKC44NyksIHF1ZSBlcyBkZSBvdHJvIGZhY3RvciwgcXVlIGNvbiBFREUwMyAoLjY3KSwgcXVlIGVzCmRlbCBzdXlvLiBFc28gZXMgdW4gKiplZmVjdG8gZGUgcHJveGltaWRhZCBlbiBlbCBpbnN0cnVtZW50byoqLCBubyBsYSBlc3RydWN0dXJhIGRlbApjb25zdHJ1Y3RvLgoKYGBge3IgZWozLXA0LWVuZ30KbW9kX2VuZzMgPC0gJyBWSUdPUiAgICAgID1+IEVWSTAxICsgRVZJMDIgKyBFVkkwMwogICAgICAgICAgICAgIERFRElDQUNJT04gPX4gRURFMDEgKyBFREUwMiArIEVERTAzCiAgICAgICAgICAgICAgQUJTT1JDSU9OICA9fiBFQUIwMSArIEVBQjAyICsgRUFCMDMgJwpmaXRfZW5nMyA8LSBjZmEobW9kX2VuZzMsIGRhdGEgPSBkLCBlc3RpbWF0b3IgPSAiTUxSIikKZml0X2VuZzIgPC0gY2ZhKHBhc3RlKG1vZF9lbmczLCAiXG4gRU5HQUdFTUVOVCA9fiBWSUdPUiArIERFRElDQUNJT04gKyBBQlNPUkNJT04iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBkLCBlc3RpbWF0b3IgPSAiTUxSIikKa2FibGUodGFibGFfYWp1c3RlKGZpdF9lbmczLCBmaXRfZW5nMiwKICAgICAgZXRpcXVldGFzID0gYygiMyBmYWN0b3JlcyBjb3JyZWxhY2lvbmFkb3MiLCAiMm8gb3JkZW46IEVOR0FHRU1FTlQiKSksCiAgICAgIGNhcHRpb24gPSAiRWwgbW9kZWxvIGRlIHNlZ3VuZG8gb3JkZW4gZW50cmVnYSB1bmEgc29sdWNpb24gSU5BRE1JU0lCTEUiKQpgYGAKCmBgYHtyIGVqMy1wNC1oZXl3b29kLCBlY2hvPUZBTFNFfQprYWJsZShkYXRhLmZyYW1lKFBhcmFtZXRybyA9IGMoIkNhcmdhIERFRElDQUNJT04gZW4gRU5HQUdFTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29ycmVsYWNpb24gREVESUNBQ0lPTi0tQUJTT1JDSU9OIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb3JyZWxhY2lvbiBWSUdPUi0tREVESUNBQ0lPTiIpLAogICAgICAgICAgICAgICAgIFZhbG9yID0gYyhyb3VuZChzdWJzZXQoc3RhbmRhcmRpemVkU29sdXRpb24oZml0X2VuZzIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaHM9PSJFTkdBR0VNRU5UIiAmIHJocz09IkRFRElDQUNJT04iKSRlc3Quc3RkLCAzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoc3Vic2V0KHN0YW5kYXJkaXplZFNvbHV0aW9uKGZpdF9lbmczKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGhzPT0iREVESUNBQ0lPTiIgJiByaHM9PSJBQlNPUkNJT04iICYgb3A9PSJ+fiIpJGVzdC5zdGQsIDMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChzdWJzZXQoc3RhbmRhcmRpemVkU29sdXRpb24oZml0X2VuZzMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaHM9PSJWSUdPUiIgJiByaHM9PSJERURJQ0FDSU9OIiAmIG9wPT0ifn4iKSRlc3Quc3RkLCAzKSkpLAogICAgICByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICJVbmEgY2FyZ2EgZXN0YW5kYXJpemFkYSBtYXlvciBxdWUgMTogY2FzbyBIZXl3b29kIikKYGBgCgpBcXVpIGVzdGEgZWwgcHVudG8gY2VudHJhbCBkZSB0b2RhIGxhIGFjdGl2aWRhZCwgeSBhcGFyZWNlICoqYW50ZXMqKiBkZSBtaXJhciBuaW5ndW4KaW5kaWNlIGRlIGFqdXN0ZTogbGEgY2FyZ2EgZXN0YW5kYXJpemFkYSBkZSBkZWRpY2FjaW9uIHNvYnJlIGVuZ2FnZW1lbnQgZXMgKiptYXlvciBxdWUgMSoqLApsbyBxdWUgaW1wbGljYSB1bmEgdmFyaWFuemEgZGUgZXJyb3IgbmVnYXRpdmEuIEVzIHVuICoqY2FzbyBIZXl3b29kKio6IHVuIHJlc3VsdGFkbwppbXBvc2libGUuIExvcyBpbmRpY2VzIGRlIGFqdXN0ZSBkZWwgbW9kZWxvIGRlIHNlZ3VuZG8gb3JkZW4gc29uIGlkZW50aWNvcyBhIGxvcyBkZWwgZGUKdHJlcyBmYWN0b3JlcywgYXNpIHF1ZSBzaSBtZSBodWJpZXJhIGd1aWFkbyBzb2xvIHBvciBDRkkgeSBSTVNFQSBubyBoYWJyaWEgbm90YWRvIG5hZGEuClVuIG1vZGVsbyBjb24gdW5hIGVzdGltYWNpb24gaW5hZG1pc2libGUgKipzZSBkZXNjYXJ0YSwgc2luIGltcG9ydGFyIGNvbW8gYWp1c3RlKiouCgpMYSBjYXVzYSBlcyB2aXNpYmxlIGVuIGxhIHRhYmxhOiBkZWRpY2FjaW9uIHkgYWJzb3JjaW9uIGNvcnJlbGFjaW9uYW4gLjkxIHkgdmlnb3IgY29uCmRlZGljYWNpb24gLjg4LiBBIGVzZSBuaXZlbCBsb3MgdHJlcyBmYWN0b3JlcyBubyBzb24gZGlzdGluZ3VpYmxlcywgeSBlbCBmYWN0b3IgZGUgc2VndW5kbwpvcmRlbiBpbnRlbnRhIGV4cGxpY2FyIG1hcyBjb3ZhcmlhbnphIGRlIGxhIHF1ZSBleGlzdGUuCgpgYGB7ciBlajMtcDQtbWVkaWNpb259Cm1vZF9tZWRpY2lvbiA8LSAnCiAgREVTQVBFR08gICA9fiBSUEQwMSArIFJQRDAyICsgUlBEMDMgKyBSUEQwNSArIFJQRDA4ICsgUlBEMTAKICBSRUxBSkFDSU9OID1+IFJSRTA1ICsgUlJFMDYgKyBSUkUwNwogIE1BRVNUUklBICAgPX4gUk1BMDQgKyBSTUEwNSArIFJNQTA3ICsgUk1BMDggKyBSTUEwOSArIFJNQTEwCiAgQ09OVFJPTCAgICA9fiBSQ08wMiArIFJDTzAzICsgUkNPMDQgKyBSQ08wNSArIFJDTzA2ICsgUkNPMDcKICBFTkVSR0lBICAgID1+IEVOMDEgKyBFTjAyICsgRU4wNCArIEVOMDUgKyBFTjA2ICsgRU4wNyArIEVOMDgKICBFTkdBR0VNRU5UID1+IEVWSTAxICsgRVZJMDIgKyBFVkkwMyArIEVERTAxICsgRURFMDIgKyBFREUwMyArIEVBQjAxICsgRUFCMDIgKyBFQUIwMwogIFJFQ1VQRVJBQ0lPTiA9fiBERVNBUEVHTyArIFJFTEFKQUNJT04gKyBNQUVTVFJJQSArIENPTlRST0wKICAjIGxvcyBkb3MgcGFyZXMgY2FzaSBpZGVudGljb3MgcXVlIGRldGVjdG8gZWwgZGlhZ25vc3RpY28gZGUgcHJveGltaWRhZAogIEVWSTAxIH5+IEVWSTAyCiAgRUFCMDIgfn4gRUFCMDMKICBSRUNVUEVSQUNJT04gfn4gRU5FUkdJQSArIEVOR0FHRU1FTlQKICBFTkVSR0lBIH5+IEVOR0FHRU1FTlQgJwpmaXRfbWVkIDwtIGNmYShtb2RfbWVkaWNpb24sIGRhdGEgPSBkLCBlc3RpbWF0b3IgPSAiTUxSIikKa2FibGUodGFibGFfYWp1c3RlKGZpdF9tZWQsIGV0aXF1ZXRhcyA9ICJtb2RlbG8gZGUgbWVkaWNpb24gY29tcGxldG8iKSwKICAgICAgY2FwdGlvbiA9ICJBanVzdGUgYWNlcHRhYmxlIHkgc29sdWNpb24gYWRtaXNpYmxlIikKYGBgCgpFbCBtb2RlbG8gZGUgbWVkaWNpb24gY29tcGxldG8gZXN0aW1hCmByIGZpdE1lYXN1cmVzKGZpdF9tZWQsIm5wYXIiKWAgcGFyYW1ldHJvcyBjb24gYHIgbnJvdyhkKWAgb2JzZXJ2YWNpb25lcy4gQWp1c3RhIGRlIGZvcm1hCioqYWNlcHRhYmxlIHBlcm8gbm8gYnVlbmEqKiAoQ0ZJIGByIHJvdW5kKGZpdE1lYXN1cmVzKGZpdF9tZWQsImNmaSIpLDMpYCwgUk1TRUEKYHIgcm91bmQoZml0TWVhc3VyZXMoZml0X21lZCwicm1zZWEiKSwzKWApLCB5IGVsIGRlc2FqdXN0ZSBlc3RhIGNvbmNlbnRyYWRvIGVuIGVsIGJsb3F1ZSBkZQplbmdhZ2VtZW50OgoKYGBge3IgZWozLXA0LW1pLCBlY2hvPUZBTFNFfQprYWJsZShoZWFkKG1vZGluZGljZXMoZml0X21lZCwgc29ydC4gPSBUUlVFKVssIGMoImxocyIsIm9wIiwicmhzIiwibWkiLCJlcGMiKV0sIDYpLAogICAgICByb3cubmFtZXMgPSBGQUxTRSwgZGlnaXRzID0gMywKICAgICAgY2FwdGlvbiA9ICJMb3MgcmVzaWR1YWxlcyBtYXMgZ3JhbmRlcyBzaWd1ZW4gc2llbmRvIGRlIGxvcyBpdGVtcyBkZSBlbmdhZ2VtZW50IikKYGBgCgojIyMgRWwgbW9kZWxvIGVzdHJ1Y3R1cmFsIGxhdGVudGUgY29uZmlybWEgbGEgY29uY2x1c2lvbiBkZSBsYSBQYXJ0ZSAzCgpgYGB7ciBlajMtcDQtZXN0cnVjdHVyYWx9CmJhc2VfbWVkIDwtIHN1YigiUkVDVVBFUkFDSU9OIH5+IEVORVJHSUEgXFwrIEVOR0FHRU1FTlRcbiAgRU5FUkdJQSB+fiBFTkdBR0VNRU5UIiwgIiIsCiAgICAgICAgICAgICAgICBtb2RfbWVkaWNpb24pCmZpdF9sYXRfYyA8LSBzZW0ocGFzdGUoYmFzZV9tZWQsICIKICBFTkVSR0lBICAgIH4gYSpSRUNVUEVSQUNJT04KICBFTkdBR0VNRU5UIH4gYipFTkVSR0lBCiAgaW5kaXJlY3RvIDo9IGEqYiAiKSwgZGF0YSA9IGQsIGVzdGltYXRvciA9ICJNTFIiKQpmaXRfbGF0X3AgPC0gc2VtKHBhc3RlKGJhc2VfbWVkLCAiCiAgRU5FUkdJQSAgICB+IGEqUkVDVVBFUkFDSU9OCiAgRU5HQUdFTUVOVCB+IGIqRU5FUkdJQSArIGNwKlJFQ1VQRVJBQ0lPTgogIGluZGlyZWN0byA6PSBhKmIKICB0b3RhbCAgICAgOj0gY3AgKyBhKmIgIiksIGRhdGEgPSBkLCBlc3RpbWF0b3IgPSAiTUxSIikKa2FibGUodGFibGFfYWp1c3RlKGZpdF9sYXRfYywgZml0X2xhdF9wLAogICAgICBldGlxdWV0YXMgPSBjKCJsYXRlbnRlOiBtZWRpYWNpb24gY29tcGxldGEiLCAibGF0ZW50ZTogbWVkaWFjaW9uIHBhcmNpYWwiKSksCiAgICAgIGNhcHRpb24gPSAiTWlzbW8gcmVzdWx0YWRvIHF1ZSBjb24gY29tcHVlc3RvczogZWwgY2FtaW5vIGRpcmVjdG8gbm8gaGFjZSBmYWx0YSIpCmNvbXBhcmFyKGZpdF9sYXRfYywgZml0X2xhdF9wLAogICAgICAgICBjKCJsYXRlbnRlOiBtZWRpYWNpb24gY29tcGxldGEiLCAibGF0ZW50ZTogbWVkaWFjaW9uIHBhcmNpYWwiKSwKICAgICAgICAgIkNvbiB2YXJpYWJsZXMgbGF0ZW50ZXMgbGEgY29uY2x1c2lvbiBubyBjYW1iaWEiKQpgYGAKCmBgYHtyIGVqMy1wNC1jb21wLCBlY2hvPUZBTFNFfQplZl9sYXQgPC0gc3Vic2V0KHBhcmFtZXRlckVzdGltYXRlcyhmaXRfbGF0X3AsIHN0YW5kYXJkaXplZCA9IFRSVUUpLCBvcCAlaW4lIGMoIn4iLCAiOj0iKSkKa2FibGUoZWZfbGF0WywgYygibGhzIiwicmhzIiwibGFiZWwiLCJlc3QiLCJzZSIsInB2YWx1ZSIsInN0ZC5hbGwiKV0sIHJvdy5uYW1lcyA9IEZBTFNFLAogICAgICBkaWdpdHMgPSAzLCBjb2wubmFtZXMgPSBjKCJEZXN0aW5vIiwiT3JpZ2VuIiwiRXRpcXVldGEiLCJFc3QiLCJFRSIsInAiLCJFc3RhbmQuIiksCiAgICAgIGNhcHRpb24gPSAiRWZlY3RvcyBjb24gdmFyaWFibGVzIGxhdGVudGVzIChtZWRpYWNpb24gcGFyY2lhbCkiKQoKY29tcCA8LSBkYXRhLmZyYW1lKAogIEVzcGVjaWZpY2FjaW9uID0gYygiQ29tcHVlc3RvcyAoUGFydGUgMykiLCAiTGF0ZW50ZSAoUGFydGUgNCkiKSwKICBDYW1pbm9fZGlyZWN0b19lc3RhbmQgPSBjKAogICAgcm91bmQoc3Vic2V0KHBhcmFtZXRlckVzdGltYXRlcyhmaXRfc2F0LCBzdGFuZGFyZGl6ZWQ9VFJVRSksIGxhYmVsPT0iY3AiKSRzdGQuYWxsLCAzKSwKICAgIHJvdW5kKHN1YnNldChwYXJhbWV0ZXJFc3RpbWF0ZXMoZml0X2xhdF9wLCBzdGFuZGFyZGl6ZWQ9VFJVRSksIGxhYmVsPT0iY3AiKSRzdGQuYWxsLCAzKSksCiAgcF9kZWxfZGlyZWN0byA9IGMoCiAgICByb3VuZChzdWJzZXQocGFyYW1ldGVyRXN0aW1hdGVzKGZpdF9zYXQpLCBsYWJlbD09ImNwIikkcHZhbHVlLCAzKSwKICAgIHJvdW5kKHN1YnNldChwYXJhbWV0ZXJFc3RpbWF0ZXMoZml0X2xhdF9wKSwgbGFiZWw9PSJjcCIpJHB2YWx1ZSwgMykpLAogIFIyX2VuZ2FnZW1lbnQgPSBjKHJvdW5kKGluc3BlY3QoZml0X3NhdCwicjIiKVtbIkVOR0EiXV0sIDMpLAogICAgICAgICAgICAgICAgICAgIHJvdW5kKGluc3BlY3QoZml0X2xhdF9wLCJyMiIpW1siRU5HQUdFTUVOVCJdXSwgMykpKQprYWJsZShjb21wLCByb3cubmFtZXMgPSBGQUxTRSwKICAgICAgY29sLm5hbWVzID0gYygiRXNwZWNpZmljYWNpb24iLCAiQ2FtaW5vIGRpcmVjdG8gZXN0YW5kLiIsICJwIGRlbCBkaXJlY3RvIiwKICAgICAgICAgICAgICAgICAgICAiUjIgZGUgZW5nYWdlbWVudCIpLAogICAgICBjYXB0aW9uID0gIkxhIGNvbmNsdXNpb24gc3VzdGFudGl2YSBubyBkZXBlbmRlIGRlIGNvbW8gc2UgbWlkYTogZXMgcm9idXN0YSIpCmBgYAoKQ29ycmVnaXIgcG9yIGVycm9yIGRlIG1lZGljaW9uICoqc3ViZSoqIGxhIG1hZ25pdHVkIGRlIGxvcyBlZmVjdG9zLCBjb21vIHNlIGVzcGVyYSAobGFzCmNvcnJlbGFjaW9uZXMgYXRlbnVhZGFzIHBvciBmYWx0YSBkZSBmaWFiaWxpZGFkIHNlIGRlc2F0ZW51YW4pLCBwZXJvIG5vIGNhbWJpYSBsYQpjb25jbHVzaW9uOiBlbCBjYW1pbm8gZGlyZWN0byBzaWd1ZSBzaW4gc2VyIHNpZ25pZmljYXRpdm8geSBsYSB2YXJpYW56YSBleHBsaWNhZGEgZGVsCmVuZ2FnZW1lbnQgZXMgcHJhY3RpY2FtZW50ZSBsYSBtaXNtYS4gTGEgbWVkaWFjaW9uIGNvbXBsZXRhIHNlIHNvc3RpZW5lIGNvbiBsYXMgZG9zCmVzcGVjaWZpY2FjaW9uZXMuCgojIyBDb25jbHVzaW9uZXMgZGVsIGVqZXJjaWNpbyAzCgoxLiAqKkVsIGluc3RydW1lbnRvIGRlIHJlY3VwZXJhY2lvbiB0ZW5pYSBncmFzYS4qKiBEZSAzMSBpdGVtcyBxdWVkYXJvbgogICBgciBzdW0obGVuZ3RocyhkZXBfcmVjJGl0ZW1zKSlgLiBMbyBxdWUgc2UgZWxpbWlubyBubyBmdWVyb24gaXRlbXMgbWFsb3Mgc2lubyBpdGVtcwogICAqKnJlcGV0aWRvcyoqOiBwYXJlcyBxdWUgZGljZW4gbG8gbWlzbW8gY29uIG90cmFzIHBhbGFicmFzLiBMYSByZWdsYSBkZSBkZXB1cmFjaW9uCiAgIHJlZGVzY3VicmlvIHRyZXMgZGUgbGFzIGN1YXRybyBlbGltaW5hY2lvbmVzIHF1ZSB5YSBoYWJpYW4gZG9jdW1lbnRhZG8gbG9zIGF1dG9yZXMuCjIuICoqRWwgY29uc3RydWN0byBkZSBzZWd1bmRvIG9yZGVuIHNlIHNvc3RpZW5lLioqIExvcyBjdWF0cm8gZG9taW5pb3Mgc29uIGZhY2V0YXMgZGUgdW5hCiAgIHNvbGEgY2FwYWNpZGFkIGRlIHJlY3VwZXJhY2lvbiwgeSByZW51bmNpYXIgYSBsYXMgc2VpcyBjb3JyZWxhY2lvbmVzIGxpYnJlcyBhIGNhbWJpbyBkZQogICBjdWF0cm8gY2FyZ2FzIG5vIGN1ZXN0YSBhanVzdGUgKHAgPSBgciByb3VuZChzdXBwcmVzc1dhcm5pbmdzKGxhdlRlc3RMUlQoZml0X3NlZywgZGVwX3JlYyRmaXQpKVsyLCJQcig+Q2hpc3EpIl0sMylgKS4KMy4gKipMYSBlbmVyZ2lhIHJlY3VwZXJhZGEgZXMgdW5pZGltZW5zaW9uYWwqKiwgY29uIGNhcmdhcyBkZSAuODkgYSAuOTUuIEVsIFJNU0VBIGFsdG8gZXMKICAgdW4gYXJ0ZWZhY3RvIGRlIHRlbmVyIHBvY29zIGdyYWRvcyBkZSBsaWJlcnRhZCwgbm8gZXZpZGVuY2lhIGRlIG1hbGEgZXN0cnVjdHVyYSwgeSBubwogICBzZSBjb3JyaWdlIHRpcmFuZG8gaXRlbXMuCjQuICoqTGEgbWVkaWFjaW9uIGVzIGNvbXBsZXRhLioqIExhcyBleHBlcmllbmNpYXMgZGUgcmVjdXBlcmFjaW9uIG5vIHRvY2FuIGVsIGVuZ2FnZW1lbnQKICAgcG9yIHN1IGN1ZW50YTogbG8gdG9jYW4gc29sbyBhIHRyYXZlcyBkZSBsYSBlbmVyZ2lhIGVmZWN0aXZhbWVudGUgcmVjdXBlcmFkYQogICAocCA9IGByIHJvdW5kKGZpdE1lYXN1cmVzKGZpdF9kb20sInB2YWx1ZSIpLDMpYCBwYXJhIGxhIHJlc3RyaWNjaW9uIGRlIG1lZGlhY2lvbgogICBjb21wbGV0YSwgeSBuaW5ndW4gY2FtaW5vIGRpcmVjdG8gc2lnbmlmaWNhdGl2bykuCjUuICoqQ29udHJvbCBzb2JyZSBlbCB0aWVtcG8gbGlicmUgZXMgbGEgcGFsYW5jYS4qKiBFZmVjdG8gaW5kaXJlY3RvIGVzdGFuZGFyaXphZG8gZGUKICAgYHIgcm91bmQoaW5kJHN0ZC5hbGxbMV0sMylgLCBjYXNpIGVsIGRvYmxlIGRlbCBzaWd1aWVudGUuIFJlbGFqYWNpb24sIGVuIGNhbWJpbywgbm8KICAgc29icmV2aXZlIGFsIGludGVydmFsbyBib290c3RyYXAuCjYuICoqTGEgZXNjYWxhIGRlIGVuZ2FnZW1lbnQgbm8gcmVwbGljYSBzdSBlc3RydWN0dXJhIHRlb3JpY2EgZW4gZXN0YSBtdWVzdHJhLioqIEVsIG1vZGVsbwogICBkZSBzZWd1bmRvIG9yZGVuIHByb2R1Y2UgdW4gY2FzbyBIZXl3b29kLCB5IGVsIHBhdHJvbiBkZSBjb3JyZWxhY2lvbmVzIGFwdW50YSBhIHVuCiAgIGVmZWN0byBkZSBwcm94aW1pZGFkIGVuIGVsIGN1ZXN0aW9uYXJpby4gRXN0ZSBlcyBlbCBoYWxsYXpnbyBxdWUgY29uZWN0YSBkaXJlY3RhbWVudGUKICAgY29uIGVsIGVqZXJjaWNpbyA0LgoKIyBFamVyY2ljaW8gNDogQmVoc29uLCBFZGR5IHkgTG9yZW56ZXQgKDIwMDApCgojIyBMb3MgZG9zIG1vZGVsb3MgcXVlIGNvbXBpdGVuCgpCZWhzb24sIEVkZHkgeSBMb3JlbnpldCAoMjAwMCkganVudGFuIDEzIGVzdHVkaW9zIHNvYnJlIGVsIE1vZGVsbyBkZSBDYXJhY3RlcmlzdGljYXMgZGVsClB1ZXN0byBkZSBIYWNrbWFuIHkgT2xkaGFtIGVuIHVuIG1ldGEtYW5hbGlzaXMsIGFybWFuIGNvbiBlbCB1bmEgbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMKeSBlc3RpbWFuIHNvYnJlIGVsbGEgZG9zIG1vZGVsb3Mgcml2YWxlczoKCmBgYHtyIGVqNC1tb2RlbG9zLCBlY2hvPUZBTFNFfQprYWJsZShkYXRhLmZyYW1lKAogIE1vZGVsbyA9IGMoIk1vZGVsbyAxOiBKQ00gb3JpZ2luYWwgKDMgZXRhcGFzKSIsICJNb2RlbG8gMjogSkNNIGNvbW8gc2UgcHJ1ZWJhICgyIGV0YXBhcykiKSwKICBFc3RydWN0dXJhID0gYygiNSBjYXJhY3RlcmlzdGljYXMgZGVsIHB1ZXN0byAtPiAzIGVzdGFkb3MgcHNpY29sb2dpY29zIGNyaXRpY29zIC0+IDMgcmVzdWx0YWRvcyIsCiAgICAgICAgICAgICAgICAgIjUgY2FyYWN0ZXJpc3RpY2FzIGRlbCBwdWVzdG8gLT4gMyByZXN1bHRhZG9zIChsb3MgZXN0YWRvcyBzZSBvbWl0ZW4pIiksCiAgQ2FtaW5vcyA9IGMoIjE0IiwgIjE1IiksCiAgU3VwdWVzdG8gPSBjKCJtZWRpYWNpb24gY29tcGxldGEgcG9yIGxvcyBlc3RhZG9zIHBzaWNvbG9naWNvcyIsCiAgICAgICAgICAgICAgICJlZmVjdG8gZGlyZWN0bywgc2luIG1lY2FuaXNtbyBpbnRlcm1lZGlvIikpLAogIGNhcHRpb24gPSAiTG9zIGRvcyBtb2RlbG9zIGRlbCBhcnRpY3VsbyIpCmBgYAoKRWwgTW9kZWxvIDEgZXMgbGEgdGVvcmlhIG9yaWdpbmFsOiBsYXMgY2FyYWN0ZXJpc3RpY2FzIGRlbCBwdWVzdG8gKHZhcmllZGFkLCBzaWduaWZpY2FkbywKaWRlbnRpZGFkLCBhdXRvbm9taWEsIHJldHJvYWxpbWVudGFjaW9uKSBwcm9kdWNlbiB0cmVzICoqZXN0YWRvcyBwc2ljb2xvZ2ljb3MgY3JpdGljb3MqKgooc2lnbmlmaWNhZG8gZXhwZXJpbWVudGFkbywgcmVzcG9uc2FiaWxpZGFkIGV4cGVyaW1lbnRhZGEsIGNvbm9jaW1pZW50byBkZSByZXN1bHRhZG9zKSB5CnNvbiBlc3RvcyBsb3MgcXVlIHByb2R1Y2VuIHNhdGlzZmFjY2lvbiwgc2F0aXNmYWNjaW9uIGRlIGNyZWNpbWllbnRvIHkgbW90aXZhY2lvbiBpbnRlcm5hLgpFbCBNb2RlbG8gMiBlcyBjb21vIGNhc2kgdG9kYSBsYSBsaXRlcmF0dXJhIHBvc3RlcmlvciBsbyBoYSBwcm9iYWRvOiBicmluY2FuZG9zZSBsb3MKZXN0YWRvcyBwc2ljb2xvZ2ljb3MuCgojIyBMbyBxdWUgcmVwb3J0YSBlbCBhcnRpY3VsbwoKYGBge3IgZWo0LXJlcG9ydGUsIGVjaG89RkFMU0V9CmthYmxlKGRhdGEuZnJhbWUoCiAgRXN0YWRpc3RpY28gPSBjKCJDaGktY3VhZHJhZGEgKGdsKSIsICJSTVNFQSIsICJHRkkiLCAiQ0ZJIiwKICAgICAgICAgICAgICAgICAgIkNhbWlub3Mgc2lnbmlmaWNhdGl2b3MiLCAiUjIgc2F0aXNmYWNjaW9uIiwgIlIyIGNyZWNpbWllbnRvIiwKICAgICAgICAgICAgICAgICAgIlIyIG1vdGl2YWNpb24iLCAiQUlDIiwgIkNBSUMiKSwKICBNb2RlbG9fMSA9IGMoIjEyNC4yNSAoMjUpIiwgIi4xNCIsICIuOTEiLCAiLjg5IiwgIjEyIGRlIDE0IiwgIi40MiIsICIuNDIiLCAiLjM4IiwKICAgICAgICAgICAgICAgIjI5NC40OCIsICI0NDYuMjkiKSwKICBNb2RlbG9fMiA9IGMoIjEyLjA5ICgzKSIsICIuMTYiLCAiLjk5IiwgIi45OCIsICI3IGRlIDE1IiwgIi4zNyIsICIuNDMiLCAiLjMyIiwKICAgICAgICAgICAgICAgIjgwLjA5IiwgIjIyNy41NiIpKSwKICBjYXB0aW9uID0gIlRhYmxhIDQgZGVsIGFydGljdWxvLiBFbCBNb2RlbG8gMiBnYW5hIGVuIEdGSSwgQ0ZJLCBBSUMgeSBDQUlDIikKYGBgCgpMb3MgYXV0b3JlcyBsbyBkaWNlbiBzaW4gcm9kZW9zOiBlbCBBSUMgeSBlbCBDQUlDLCBxdWUgc29uIGxvcyB1bmljb3MgZXN0YWRpc3RpY29zIHF1ZQp1c2FuIHBhcmEgY29tcGFyYXIgZm9ybWFsbWVudGUgbG9zIGRvcyBtb2RlbG9zLCAqKmZhdm9yZWNlbiBhbCBNb2RlbG8gMioqLiBZIGF1biBhc2kKZWxpZ2VuIGVsIE1vZGVsbyAxLgoKIyMgUmVwbGljYWNpb246IGxhIG1hdHJpeiBkZWwgYXJ0aWN1bG8gZXN0YSBwdWJsaWNhZGEsIGFzaSBxdWUgc2UgcHVlZGUgdmVyaWZpY2FyCgpMYSBUYWJsYSAyIGRlbCBhcnRpY3VsbyBwdWJsaWNhIGxhIG1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIG1ldGEtYW5hbGl0aWNhIGNvbXBsZXRhIHkgbGFzCmRlc3ZpYWNpb25lcyBlc3RhbmRhciBub3JtYXRpdmFzIGRlIE9sZGhhbSwgSGFja21hbiB5IFN0ZXBpbmEgKDE5NzkpLiBDb24gZXNvIHNlIHB1ZWRlCnJlY29uc3RydWlyIGxhIG1hdHJpeiBkZSBjb3ZhcmlhbnphcyB5IHZvbHZlciBhIGVzdGltYXIgbG9zIGRvcyBtb2RlbG9zLgoKYGBge3IgZWo0LW1hdHJpen0KdiAgIDwtIGMoIlZBUiIsIlNJRyIsIklERSIsIkFVVCIsIkZCSyIsIk1FQSIsIlJFUyIsIktOTyIsIlNBVCIsIkdSTyIsIk1PVCIpCnNkdiA8LSBjKDEuNTcsIDEuMjUsIDEuNDQsIDEuMzksIDEuMzQsIDEuMTQsIDAuOTYsIDEuMTQsIDEuMDcsIDEuMTUsIDAuNzcpClIgPC0gZGlhZygxMSk7IGRpbW5hbWVzKFIpIDwtIGxpc3QodiwgdikKdHJpIDwtIGxpc3QoYyguNDEpLCBjKC4yMiwuMjApLCBjKC40MywuMzIsLjMyKSwgYyguMzUsLjM0LC4yNiwuMzkpLAogICAgICAgICAgICBjKC40NiwuNDUsLjI0LC40MiwuMzgpLCBjKC4zNCwuMzMsLjI3LC4zOSwuMzQsLjU5KSwKICAgICAgICAgICAgYyguMTYsLjIzLC4yOCwuMjksLjQ5LC40MCwuMzQpLCBjKC4zNSwuMjksLjIyLC40MiwuMzYsLjY1LC40OSwuNDIpLAogICAgICAgICAgICBjKC41MCwuMzgsLjI2LC41NCwuNDQsLjY1LC41MSwuNDAsLjY5KSwKICAgICAgICAgICAgYyguMzUsLjMzLC4xNywuMzAsLjQyLC41NywuNTksLjI1LC40MywuNTApKQpmb3IgKGkgaW4gMjoxMSkgeyBSW2ksIDE6KGktMSldIDwtIHRyaVtbaS0xXV07IFJbMTooaS0xKSwgaV0gPC0gdHJpW1tpLTFdXSB9ClMgPC0gZGlhZyhzZHYpICUqJSBSICUqJSBkaWFnKHNkdik7IGRpbW5hbWVzKFMpIDwtIGRpbW5hbWVzKFIpCk4gPC0gMjA4ICAgIyBsb3MgYXV0b3JlcyB1c2FuIGxhIG1lZGlhbmEgZGVsIHRhbWFuaW8gZGUgbXVlc3RyYSwgbm8gbGEgc3VtYQpgYGAKCmBgYHtyIGVqNC1tMX0KbW9kX2IxIDwtICcKICBNRUEgfiBWQVIgKyBTSUcgKyBJREUKICBSRVMgfiBBVVQKICBLTk8gfiBGQksKICBTQVQgfiBNRUEgKyBSRVMgKyBLTk8KICBHUk8gfiBNRUEgKyBSRVMgKyBLTk8KICBNT1QgfiBNRUEgKyBSRVMgKyBLTk8KICBNRUEgfn4gUkVTICsgS05PCiAgUkVTIH5+IEtOTwogIFNBVCB+fiBHUk8gKyBNT1QKICBHUk8gfn4gTU9UICcKZml0X2IxIDwtIHNlbShtb2RfYjEsIHNhbXBsZS5jb3YgPSBTLCBzYW1wbGUubm9icyA9IE4sIGZpeGVkLnggPSBGQUxTRSkKcm91bmQoZml0TWVhc3VyZXMoZml0X2IxLCBjKCJjaGlzcSIsImRmIiwiY2ZpIiwicm1zZWEiLCJnZmkiKSksIDMpCnJvdW5kKGluc3BlY3QoZml0X2IxLCAicjIiKSwgMykKYGBgCgpgYGB7ciBlajQtbTEtY2FtaW5vcywgZWNobz1GQUxTRX0KcGIxIDwtIHN1YnNldChwYXJhbWV0ZXJFc3RpbWF0ZXMoZml0X2IxLCBzdGFuZGFyZGl6ZWQgPSBUUlVFKSwgb3AgPT0gIn4iKQprYWJsZShkYXRhLmZyYW1lKAogIENhbnRpZGFkID0gYygiR3JhZG9zIGRlIGxpYmVydGFkIiwgIkNhbWlub3Mgc2lnbmlmaWNhdGl2b3MiLCAiUjIgc2F0aXNmYWNjaW9uIiwKICAgICAgICAgICAgICAgIlIyIGNyZWNpbWllbnRvIiwgIlIyIG1vdGl2YWNpb24iKSwKICBBcnRpY3VsbyA9IGMoIjI1IiwgIjEyIGRlIDE0IiwgIi40MiIsICIuNDIiLCAiLjM4IiksCiAgUmVwbGljYWNpb24gPSBjKGZpdE1lYXN1cmVzKGZpdF9iMSwiZGYiKSwKICAgICAgICAgICAgICAgICAgcGFzdGUoc3VtKHBiMSRwdmFsdWUgPCAuMDUpLCAiZGUiLCBucm93KHBiMSkpLAogICAgICAgICAgICAgICAgICByb3VuZChpbnNwZWN0KGZpdF9iMSwicjIiKVtbIlNBVCJdXSwgMyksCiAgICAgICAgICAgICAgICAgIHJvdW5kKGluc3BlY3QoZml0X2IxLCJyMiIpW1siR1JPIl1dLCAzKSwKICAgICAgICAgICAgICAgICAgcm91bmQoaW5zcGVjdChmaXRfYjEsInIyIilbWyJNT1QiXV0sIDMpKSksCiAgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiRWwgTW9kZWxvIDEgc2UgcmVwcm9kdWNlIGNhc2kgZXhhY3RhbWVudGUiKQpgYGAKCkxhIHJlcGxpY2FjaW9uIGRlbCBNb2RlbG8gMSBlcyBwcmFjdGljYW1lbnRlIGV4YWN0YTogbWlzbW9zIGdyYWRvcyBkZSBsaWJlcnRhZCwgbWlzbW9zCjEyIGRlIDE0IGNhbWlub3Mgc2lnbmlmaWNhdGl2b3MgeSBsYXMgdHJlcyBSMiBjb2luY2lkZW4gYWwgc2VndW5kbyBkZWNpbWFsLiBFc28gdmFsaWRhIHF1ZQpsYSBtYXRyaXogZXN0YSBiaWVuIHJlY29uc3RydWlkYSB5IHF1ZSBlbnRlbmRpIGxhIGVzcGVjaWZpY2FjaW9uLgoKYGBge3IgZWo0LW0yfQpvOCA8LSBjKCJWQVIiLCJTSUciLCJJREUiLCJBVVQiLCJGQksiLCJTQVQiLCJHUk8iLCJNT1QiKQptb2RfYjIgPC0gJwogIFNBVCB+IFZBUiArIFNJRyArIElERSArIEFVVCArIEZCSwogIEdSTyB+IFZBUiArIFNJRyArIElERSArIEFVVCArIEZCSwogIE1PVCB+IFZBUiArIFNJRyArIElERSArIEFVVCArIEZCSyAnCiMgYXV0by5jb3YueSA9IEZBTFNFIHJlcHJvZHVjZSBsb3MgMyBncmFkb3MgZGUgbGliZXJ0YWQgcXVlIHJlcG9ydGEgZWwgYXJ0aWN1bG8KZml0X2IyIDwtIHNlbShtb2RfYjIsIHNhbXBsZS5jb3YgPSBTW284LCBvOF0sIHNhbXBsZS5ub2JzID0gTiwKICAgICAgICAgICAgICBmaXhlZC54ID0gRkFMU0UsIGF1dG8uY292LnkgPSBGQUxTRSkKcm91bmQoZml0TWVhc3VyZXMoZml0X2IyLCBjKCJjaGlzcSIsImRmIiwiY2ZpIiwicm1zZWEiLCJnZmkiKSksIDMpCmBgYAoKKipOb3RhIGRlIHZlcmlmaWNhY2lvbi4qKiBMb3MgZ3JhZG9zIGRlIGxpYmVydGFkIGNvaW5jaWRlbiAoMyksIHBlcm8gbGEgY2hpLWN1YWRyYWRhIHF1ZQpvYnRlbmdvIGVzIGByIHJvdW5kKGZpdE1lYXN1cmVzKGZpdF9iMiwiY2hpc3EiKSwyKWAgY29udHJhIGxvcyAxMi4wOSBwdWJsaWNhZG9zLCB5IGVsIENGSQptZSBkYSBgciByb3VuZChmaXRNZWFzdXJlcyhmaXRfYjIsImNmaSIpLDMpYCBjb250cmEgLjk4LiBMYSByYXpvbiBlcyBpZGVudGlmaWNhYmxlOiBjb24gMwpncmFkb3MgZGUgbGliZXJ0YWQgbGFzIHRyZXMgY292YXJpYW56YXMgZW50cmUgbG9zIHJlc2lkdWFsZXMgZGUgbG9zIHJlc3VsdGFkb3MgZXN0YW4gZmlqYXMKZW4gY2VybywgeSBzYXRpc2ZhY2Npb24gY29uIGNyZWNpbWllbnRvIGNvcnJlbGFjaW9uYW4gLjY5IGVuIGxhIG1hdHJpeiBwdWJsaWNhZGEsIGFzaSBxdWUKZXNhIHJlc3RyaWNjaW9uICoqdGllbmUqKiBxdWUgcHJvZHVjaXIgdW4gZGVzYWp1c3RlIGVub3JtZS4gU2kgc2UgbGliZXJhbiBlc2FzIHRyZXMKY292YXJpYW56YXMgZWwgbW9kZWxvIHF1ZWRhIHNhdHVyYWRvIChnbCA9IDAsIGFqdXN0ZSBwZXJmZWN0bykuIE5vIGV4aXN0ZSB1bmEKZXNwZWNpZmljYWNpb24gcXVlIGRlIGFsIG1pc21vIHRpZW1wbyBnbCA9IDMgeSBjaGktY3VhZHJhZGEgPSAxMi4wOSBjb24gbGEgbWF0cml6IHF1ZSBlbGxvcwpwdWJsaWNhbi4gRGFkbyBxdWUgZWwgTW9kZWxvIDEgc2kgc2UgcmVwcm9kdWNlLCBsYSBpbmNvbnNpc3RlbmNpYSBlc3RhIGVuIGVsIHJlcG9ydGUgZGVsCk1vZGVsbyAyLCBubyBlbiBtaSByZWNvbnN0cnVjY2lvbi4gQ29udmllbmUgY29udHJhc3RhcmxvIGNvbiBlbCBwcm9mZXNvci4KCiMjIExhIGNvbXBhcmFjaW9uIHBvciBBSUMgZGVsIGFydGljdWxvIG5vIGVzIHZhbGlkYSwgeSBlc28gcmVmdWVyemEgc3UgcHJvcGlhIGRlY2lzaW9uCgpJbmRlcGVuZGllbnRlbWVudGUgZGVsIHB1bnRvIGFudGVyaW9yLCBoYXkgdW4gcHJvYmxlbWEgbWFzIGdyYXZlIGNvbiBlbCBhcmd1bWVudG8KY3VhbnRpdGF0aXZvIGRlbCBhcnRpY3Vsby4gRWwgQUlDIHkgZWwgQ0FJQyBzb24gKiplbCB1bmljbyBjcml0ZXJpbyBmb3JtYWwqKiBxdWUgdXNhbiBwYXJhCmRlY2xhcmFyIHN1cGVyaW9yIGFsIE1vZGVsbyAyLiBQZXJvIGNvbXBhcmFuIGRvcyBtb2RlbG9zIGFqdXN0YWRvcyBhICoqY29uanVudG9zIGRpc3RpbnRvcwpkZSB2YXJpYWJsZXMgb2JzZXJ2YWRhcyoqOiBlbCBNb2RlbG8gMSB1c2EgMTEgdmFyaWFibGVzICg2NiBtb21lbnRvcykgeSBlbCBNb2RlbG8gMiB1c2EgOAooMzYgbW9tZW50b3MpLiBMYSB2ZXJvc2ltaWxpdHVkIGRlIGFtYm9zIG5vIGVzdGEgZW4gbGEgbWlzbWEgZXNjYWxhLgoKYGBge3IgZWo0LWFpY30KIyBkb3MgbW9kZWxvcyBkZSBhanVzdGUgUEVSRkVDVE8sIHVubyBjb24gMTEgdmFyaWFibGVzIHkgb3RybyBjb24gOApzYXQxMSA8LSBwYXN0ZShhcHBseSh0KGNvbWJuKHYsIDIpKSwgMSwgZnVuY3Rpb24ocCkgcGFzdGUocFsxXSwgIn5+IiwgcFsyXSkpLCBjb2xsYXBzZSA9ICJcbiIpCmZpdF9zMTEgPC0gc2VtKHNhdDExLCBzYW1wbGUuY292ID0gUywgc2FtcGxlLm5vYnMgPSBOKQpmaXRfczggIDwtIHNlbShwYXN0ZShtb2RfYjIsICJcbiBTQVQgfn4gR1JPICsgTU9UIFxuIEdSTyB+fiBNT1QiKSwKICAgICAgICAgICAgICAgc2FtcGxlLmNvdiA9IFNbbzgsIG84XSwgc2FtcGxlLm5vYnMgPSBOLCBmaXhlZC54ID0gRkFMU0UpCmthYmxlKGRhdGEuZnJhbWUoCiAgTW9kZWxvID0gYygiU2F0dXJhZG8sIDExIHZhcmlhYmxlcyAoYWp1c3RlIHBlcmZlY3RvKSIsCiAgICAgICAgICAgICAiU2F0dXJhZG8sIDggdmFyaWFibGVzIChhanVzdGUgcGVyZmVjdG8pIiksCiAgY2hpc3EgPSBjKDAsIDApLCBnbCA9IGMoMCwgMCksCiAgQUlDID0gcm91bmQoYyhmaXRNZWFzdXJlcyhmaXRfczExLCAiYWljIiksIGZpdE1lYXN1cmVzKGZpdF9zOCwgImFpYyIpKSwgMCkpLAogIHJvdy5uYW1lcyA9IEZBTFNFLAogIGNhcHRpb24gPSAiRG9zIG1vZGVsb3MgY29uIGFqdXN0ZSBpZGVudGljYW1lbnRlIHBlcmZlY3RvIHkgQUlDIHNlcGFyYWRvcyBwb3IgbWFzIGRlIG1pbCBwdW50b3MiKQpgYGAKCkxvcyBkb3MgbW9kZWxvcyBkZSBsYSB0YWJsYSBhanVzdGFuICoqcGVyZmVjdG8qKiwgeSBhdW4gYXNpIHN1cyBBSUMgZGlmaWVyZW4gZW4KYHIgcm91bmQoZml0TWVhc3VyZXMoZml0X3MxMSwiYWljIikgLSBmaXRNZWFzdXJlcyhmaXRfczgsImFpYyIpKWAgcHVudG9zLiBMYSBkaWZlcmVuY2lhIG5vCm1pZGUgY2FsaWRhZCBkZSBhanVzdGU6IG1pZGUgKipjdWFudGFzIHZhcmlhYmxlcyBlbnRyYXJvbiBhbCBtb2RlbG8qKi4gVW4gbW9kZWxvIGNvbiBtZW5vcwp2YXJpYWJsZXMgc2llbXByZSB2YSBhIHRlbmVyIG1lbm9yIEFJQywgYXVucXVlIHNlYSBwZW9yIHRlb3JpYS4gUG9yIGxvIHRhbnRvIGVsIGFyZ3VtZW50bwoiZWwgQUlDIHkgZWwgQ0FJQyBmYXZvcmVjZW4gYWwgTW9kZWxvIDIiIG5vIHNvc3RpZW5lIGxvIHF1ZSBzZSBsZSBwaWRlIHNvc3RlbmVyLgoKIyMgUG9yIHF1ZSBlbGlnaWVyb24gZWwgTW9kZWxvIDE6IGxhIHJlc3B1ZXN0YSBkZWwgYXJ0aWN1bG8KCkxvcyBhdXRvcmVzIG5vIGludm9jYW4gZWwgYXJndW1lbnRvIGFudGVyaW9yLiBTdSByYXpvbiBlcyBkaXN0aW50YSB5LCBlbiBtaSBsZWN0dXJhLCBtYXMKZnVlcnRlIHRvZGF2aWEuIExhIGZvcm11bGFuIGFzaTogY29tcGFyYXIgbW9kZWxvcyByaXZhbGVzIGV4aWdlIG1hcyBxdWUgY29tcGFyYXIgcmF6b25lcwpkZSBhanVzdGUsIHBvcnF1ZSAqKmxhIHJhem9uYWJpbGlkYWQgZGUgbG9zIHZhbG9yZXMgZGVsIG1vZGVsbyB5IHN1IGNvcnJlc3BvbmRlbmNpYSBjb24gbGEKdGVvcmlhIHNvbiBpZ3VhbCBvIG1hcyBpbXBvcnRhbnRlcyoqLgoKRWwgaGVjaG8gY29uY3JldG8gcXVlIGxvcyBkZWNpZGUgZXN0YSBlbiBsb3MgY29lZmljaWVudGVzOgoKYGBge3IgZWo0LWNvZWZ9CnBiMiA8LSBzdWJzZXQocGFyYW1ldGVyRXN0aW1hdGVzKGZpdF9iMiwgc3RhbmRhcmRpemVkID0gVFJVRSksIG9wID09ICJ+IikKdHJlcyA8LSBwYjJbcGIyJHJocyAlaW4lIGMoIlZBUiIsIlNJRyIsIklERSIpLCBdCmthYmxlKHRyZXNbLCBjKCJsaHMiLCJyaHMiLCJlc3QiLCJzZSIsInB2YWx1ZSIsInN0ZC5hbGwiKV0sIHJvdy5uYW1lcyA9IEZBTFNFLCBkaWdpdHMgPSAzLAogICAgICBjb2wubmFtZXMgPSBjKCJSZXN1bHRhZG8iLCJDYXJhY3RlcmlzdGljYSIsIkVzdGltYWRvIiwiRUUiLCJwIiwiRXN0YW5kYXJpemFkbyIpLAogICAgICBjYXB0aW9uID0gIk1vZGVsbyAyOiBsb3MgY2FtaW5vcyBkZXNkZSB2YXJpZWRhZCwgc2lnbmlmaWNhZG8gZSBpZGVudGlkYWQgaGFjaWEgbG9zIHJlc3VsdGFkb3MiKQpgYGAKCkVuIGVsIE1vZGVsbyAyLCBgciBzdW0odHJlcyRwdmFsdWUgPj0gLjA1KWAgZGUgbG9zIGByIG5yb3codHJlcylgIGNhbWlub3MgcXVlIHZhbiBkZQp2YXJpZWRhZCBkZSBoYWJpbGlkYWRlcywgc2lnbmlmaWNhZG8gZGUgbGEgdGFyZWEgZSBpZGVudGlkYWQgZGUgbGEgdGFyZWEgaGFjaWEgbG9zCnJlc3VsdGFkb3MgKipubyBzb24gc2lnbmlmaWNhdGl2b3MqKi4gRWwgYXJ0aWN1bG8gcmVwb3J0YSA4IGRlIDk7IHlvIG9idGVuZ28KYHIgc3VtKHRyZXMkcHZhbHVlID49IC4wNSlgIGRlIGByIG5yb3codHJlcylgLCBjb24gZG9zIGNhc29zIGFsIGZpbG8uIExhIGNvbmNsdXNpb24gZXMgbGEKbWlzbWE6ICoqc2kgZWwgTW9kZWxvIDIgZnVlcmEgY2llcnRvLCBlbnJpcXVlY2VyIHVuIHB1ZXN0byBkYW5kb2xlIHZhcmllZGFkIHkgc2lnbmlmaWNhZG8Kbm8gc2VydmlyaWEgZGUgbmFkYS4qKiBFc28gY29udHJhZGljZSBkb3MgZGVjYWRhcyBkZSBpbnZlc3RpZ2FjaW9uIHNvYnJlIHJlZGlzZW5vIGRlbAp0cmFiYWpvLgoKRWwgTW9kZWxvIDEgcmVzdWVsdmUgbGEgcGFyYWRvamE6CgpgYGB7ciBlajQtaW5kaXJlY3Rvc30KbW9kX2IxX2luZCA8LSAnCiAgTUVBIH4gdipWQVIgKyBzKlNJRyArIGkqSURFCiAgUkVTIH4gQVVUCiAgS05PIH4gRkJLCiAgU0FUIH4gbTEqTUVBICsgUkVTICsgS05PCiAgR1JPIH4gbTIqTUVBICsgUkVTICsgS05PCiAgTU9UIH4gbTMqTUVBICsgUkVTICsgS05PCiAgTUVBIH5+IFJFUyArIEtOTwogIFJFUyB+fiBLTk8KICBTQVQgfn4gR1JPICsgTU9UCiAgR1JPIH5+IE1PVAogIHZhcmllZGFkX3NhdCAgICAgICAgOj0gdiptMQogIHZhcmllZGFkX2NyZWMgICAgICAgOj0gdiptMgogIHNpZ25pZmljYWRvX3NhdCAgICAgOj0gcyptMQogIHNpZ25pZmljYWRvX2NyZWMgICAgOj0gcyptMiAnCmZpdF9iMWkgPC0gc2VtKG1vZF9iMV9pbmQsIHNhbXBsZS5jb3YgPSBTLCBzYW1wbGUubm9icyA9IE4sIGZpeGVkLnggPSBGQUxTRSkKa2FibGUoc3Vic2V0KHBhcmFtZXRlckVzdGltYXRlcyhmaXRfYjFpLCBzdGFuZGFyZGl6ZWQgPSBUUlVFKSwgb3AgPT0gIjo9IilbCiAgICAgICAgLCBjKCJsaHMiLCJlc3QiLCJzZSIsInB2YWx1ZSIsInN0ZC5hbGwiKV0sIHJvdy5uYW1lcyA9IEZBTFNFLCBkaWdpdHMgPSAzLAogICAgICBjb2wubmFtZXMgPSBjKCJFZmVjdG8gaW5kaXJlY3RvIiwiRXN0aW1hZG8iLCJFRSIsInAiLCJFc3RhbmRhcml6YWRvIiksCiAgICAgIGNhcHRpb24gPSAiRW4gZWwgTW9kZWxvIDEgZXNvcyBtaXNtb3MgY2FtaW5vcyBTSSBleGlzdGVuLCBwZXJvIHBhc2FuIHBvciBlbCBzaWduaWZpY2FkbyBleHBlcmltZW50YWRvIikKYGBgCgpWYXJpZWRhZCB5IHNpZ25pZmljYWRvICoqc2kqKiBhZmVjdGFuIGxhIHNhdGlzZmFjY2lvbiB5IGVsIGNyZWNpbWllbnRvLCBwZXJvIGxvIGhhY2VuCioqYSB0cmF2ZXMgZGVsIHNpZ25pZmljYWRvIGV4cGVyaW1lbnRhZG8qKi4gQWwgYm9ycmFyIGxvcyBlc3RhZG9zIHBzaWNvbG9naWNvcywgZWwgTW9kZWxvIDIKbm8gZWxpbWluYSB1biByb2RlbyBpbm5lY2VzYXJpbzogZWxpbWluYSBlbCBtZWNhbmlzbW8sIHkgY29uIGVsIGRlc2FwYXJlY2UgZWwgZWZlY3RvLgoKTG9zIGF1dG9yZXMgZWxpZ2VuIGVsIE1vZGVsbyAxLCBlbnRvbmNlcywgcG9yIGN1YXRybyByYXpvbmVzIGFjdW11bGFkYXM6CgoxLiAqKkxvcyBjb2VmaWNpZW50ZXMgZGVsIE1vZGVsbyAyIGNvbnRyYWRpY2VuIGxhIHRlb3JpYSBlc3RhYmxlY2lkYS4qKiBVbiBtb2RlbG8gY3V5b3MKICAgcGFyYW1ldHJvcyBubyB0aWVuZW4gc2VudGlkbyBzdXN0YW50aXZvIG5vIGVzIHV0aWxpemFibGUsIGFqdXN0ZSBsbyBxdWUgYWp1c3RlLgoyLiAqKkVsIE1vZGVsbyAxIGV4cGxpY2EgbWFzIHZhcmlhbnphKiogZW4gZG9zIGRlIGxvcyB0cmVzIHJlc3VsdGFkb3MgeSB0aWVuZSBtZWpvcgogICBwcm9wb3JjaW9uIGRlIGNhbWlub3Mgc2lnbmlmaWNhdGl2b3MgKDEyIGRlIDE0IGNvbnRyYSA3IGRlIDE1KS4KMy4gKipFbCBtZWpvciBhanVzdGUgZGVsIE1vZGVsbyAyIGVzIGVuIGJ1ZW5hIG1lZGlkYSBtZWNhbmljby4qKiBDb24gMyBncmFkb3MgZGUgbGliZXJ0YWQKICAgZXN0YSBhIHVuIHBhc28gZGUgZXN0YXIgc2F0dXJhZG8sIHkgdW4gbW9kZWxvIGNhc2kgc2F0dXJhZG8gY2FzaSBubyBwdWVkZSBkZXNhanVzdGFyLgogICBMb3MgMjUgZ3JhZG9zIGRlIGxpYmVydGFkIGRlbCBNb2RlbG8gMSBzb24gdW5hIGhpcG90ZXNpcyBtdWNobyBtYXMgZXhwdWVzdGEgYQogICByZWZ1dGFjaW9uLiBEZSBoZWNobyBlbCBSTVNFQSwgcXVlIGVzIGVsIHVuaWNvIGluZGljZSBkZSBsYSB0YWJsYSBxdWUgcGVuYWxpemEgbGEgZmFsdGEKICAgZGUgcGFyc2ltb25pYSwgZXMgKipwZW9yKiogZW4gZWwgTW9kZWxvIDIgKC4xNiBjb250cmEgLjE0KS4KNC4gKipFbCBwcm9wb3NpdG8gZGVsIG1vZGVsbyBlcyBleHBsaWNhciwgbm8gc29sbyBkZXNjcmliaXIuKiogTG9zIGVzdGFkb3MgcHNpY29sb2dpY29zIHNvbgogICBsbyB1bmljbyBzb2JyZSBsbyBxdWUgdW4gZ2VyZW50ZSBwdWVkZSBhY3R1YXIgY29uIGNyaXRlcmlvOiBsZSBkaWNlbiAqcG9yIHF1ZSogZnVuY2lvbmEKICAgZWwgcmVkaXNlbm8gZGVsIHB1ZXN0byB5IGN1YW5kbyBubyB2YSBhIGZ1bmNpb25hci4KCiMjIENvbmNsdXNpb25lcyBkZWwgZWplcmNpY2lvIDQ6IGxhIGxlY2Npb24KCioqVW4gaW5kaWNlIGRlIGFqdXN0ZSBtaWRlIHNpIGVsIG1vZGVsbyByZXByb2R1Y2UgbGEgbWF0cml6IGRlIGNvdmFyaWFuemFzLiBObyBtaWRlIHNpIGVsCm1vZGVsbyBlcyB2ZXJkYWRlcm8sIG5pIHNpIGVzIHV0aWwsIG5pIHNpcXVpZXJhIHNpIGVzIHBvc2libGUuKiogRWxlZ2lyIG1vZGVsbyBwb3IgQ0ZJIGVzCmNvbW8gZWxlZ2lyIHVuIHByb25vc3RpY28gcG9yIHN1IFIyIGRlbnRybyBkZSBtdWVzdHJhLgoKTGFzIHRyZXMgdmVyaWZpY2FjaW9uZXMgcXVlIGVzdGUgYXJ0aWN1bG8gbWUgZGVqYSBjb21vIHJ1dGluYSwgZW4gZXN0ZSBvcmRlbjoKCjEuICoqQWRtaXNpYmlsaWRhZCBwcmltZXJvLioqIEFudGVzIGRlIGxlZXIgdW4gc29sbyBpbmRpY2UsIHJldmlzYXIgcXVlIG5vIGhheWEgdmFyaWFuemFzCiAgIG5lZ2F0aXZhcyBuaSBjYXJnYXMgZXN0YW5kYXJpemFkYXMgbWF5b3JlcyBxdWUgMS4gRW4gZWwgZWplcmNpY2lvIDMgZXN0byBkZXNjYXJ0byBlbAogICBtb2RlbG8gZGUgZW5nYWdlbWVudCBkZSBzZWd1bmRvIG9yZGVuICoqYW50ZXMqKiBkZSBxdWUgc3UgYWp1c3RlIGlkZW50aWNvIGFsIGRlIHRyZXMKICAgZmFjdG9yZXMgbWUgaGljaWVyYSBwYXNhcmxvIHBvciBhbHRvLgoyLiAqKlNpZ25vIHkgbWFnbml0dWQgZGUgbG9zIGNvZWZpY2llbnRlcyBjb250cmEgbGEgdGVvcmlhLioqIFVuIG1vZGVsbyBxdWUgYWp1c3RhIG1lam9yCiAgIHBlcm8gZGljZSBxdWUgZGFyIHZhcmllZGFkIGFsIHRyYWJham8gbm8gc2lydmUsIGVzdGEgZGljaWVuZG8gYWxnbyBmYWxzby4KMy4gKipDb21wYXJhYmlsaWRhZCBkZSBsYSBjb21wYXJhY2lvbi4qKiBDaGktY3VhZHJhZGEgc29sbyBlbnRyZSBtb2RlbG9zIGFuaWRhZG9zOyBBSUMgc29sbwogICBlbnRyZSBtb2RlbG9zIHNvYnJlIGxhcyBtaXNtYXMgdmFyaWFibGVzLiBFbiBlbCBlamVyY2ljaW8gMyBlc3RvIG1lIG9ibGlnbyBhIGZpamFyIGVsCiAgIGNhbWlubyBkaXJlY3RvIGVuIGNlcm8gcGFyYSBwb2RlciBjb250cmFzdGFyIGFsZ28sIGVuIHZleiBkZSBjZWxlYnJhciBlbCBDRkkgPSAxIGRlIHVuCiAgIG1vZGVsbyBzYXR1cmFkby4KClkgbGEgbGVjY2lvbiBkZSBmb25kbywgcXVlIGVzIGxhIHF1ZSBjb25lY3RhIGxvcyBjdWF0cm8gZWplcmNpY2lvczogKipib3JyYXIgZWwgbWVkaWFkb3IKbWVqb3JhIGVsIGFqdXN0ZSB5IGRlc3RydXllIGxhIGV4cGxpY2FjaW9uLioqIEVsIE1vZGVsbyAyIGRlIEJlaHNvbiBhanVzdGEgbWVqb3IgcG9ycXVlCnBpZGUgbWVub3M7IG1pIG1vZGVsbyBkZSBtZWRpYWNpb24gcGFyY2lhbCBkZSBsYSBQYXJ0ZSAzIGFqdXN0YWJhIHBlcmZlY3RvIHBvcnF1ZSBubyBwZWRpYQpuYWRhLiBFbiBsb3MgZG9zIGNhc29zLCBlbCBtb2RlbG8gcXVlIHZhbGUgZXMgZWwgcXVlIHNlIGF0cmV2ZSBhIGFmaXJtYXIgZWwgbWVjYW5pc21vIHkKc29icmV2aXZlIGEgbGEgcHJ1ZWJhLgoKIyBMaW1pdGFjaW9uZXMKCjEuICoqTG9zIGRhdG9zIGRlbCBlamVyY2ljaW8gMyBzb24gdHJhbnN2ZXJzYWxlcy4qKiBUb2RvIGVsIGxlbmd1YWplIGNhdXNhbCAoImxhcwogICBleHBlcmllbmNpYXMgZGUgcmVjdXBlcmFjaW9uIHByb2R1Y2VuIGVuZXJnaWEsIHF1ZSBwcm9kdWNlIGVuZ2FnZW1lbnQiKSBkZXNjcmliZSBsYQogICBlc3RydWN0dXJhIGRlbCBtb2RlbG8sIG5vIHVuYSBjYXVzYWxpZGFkIGRlbW9zdHJhZGEuIENvbiB1bmEgc29sYSBtZWRpY2lvbiwgZWwgbW9kZWxvCiAgIGludmVyc28gKGNvbGFib3JhZG9yZXMgY29tcHJvbWV0aWRvcyBzZSByZWN1cGVyYW4gbWVqb3IpIGFqdXN0YSBpZ3VhbCBkZSBiaWVuLiBQYXJhCiAgIGRpc3Rpbmd1aXJsb3MgaGFjZSBmYWx0YSBtZWRpY2lvbiByZXBldGlkYSwgY29tbyBlbiBlbCBlamVyY2ljaW8gMi4KMi4gKipWYXJpYW56YSBkZSBtZXRvZG8gY29tdW4uKiogUmVjdXBlcmFjaW9uLCBlbmVyZ2lhIHkgZW5nYWdlbWVudCBzZSBtaWRpZXJvbiBlbiBlbCBtaXNtbwogICBjdWVzdGlvbmFyaW8sIGNvbiBsYSBtaXNtYSBwZXJzb25hIHkgZW4gZWwgbWlzbW8gbW9tZW50by4gUGFydGUgZGUgbGFzIGNvcnJlbGFjaW9uZXMKICAgb2JzZXJ2YWRhcyBlcyBkZWwgaW5zdHJ1bWVudG8sIG5vIGRlIGxvcyBjb25zdHJ1Y3Rvcy4gRWwgZ3JhZGllbnRlIGRlIHByb3hpbWlkYWQgZW4gbG9zCiAgIGl0ZW1zIGRlIGVuZ2FnZW1lbnQgZXMgZXZpZGVuY2lhIGRpcmVjdGEgZGUgcXVlIGVzZSBlZmVjdG8gZXhpc3RlIGVuIGVzdGEgYmFzZS4KMy4gKipMYSBkZXB1cmFjaW9uIHNlIHZhbGlkbyBkZW50cm8gZGUgbGEgbWlzbWEgbXVlc3RyYS4qKiBFbiBlbCBlamVyY2ljaW8gMSBwdWRlIHVzYXIgbGFzCiAgIGRvcyBlc2N1ZWxhcyBjb21vIG11ZXN0cmFzIGRlIGRlc2N1YnJpbWllbnRvIHkgY29uZmlybWFjaW9uOyBlbiBlbCBlamVyY2ljaW8gMywgY29uCiAgIGByIG5yb3coZClgIGNhc29zLCBwYXJ0aXIgbGEgbXVlc3RyYSBoYWJyaWEgZGVqYWRvIHN1Ym11ZXN0cmFzIGRlbWFzaWFkbyBjaGljYXMgcGFyYSAyMQogICBpdGVtcy4gTG9zIGluZGljZXMgZGUgYWp1c3RlIGRlbCBtb2RlbG8gZGVwdXJhZG8gZXN0YW4gcG9yIGxvIHRhbnRvICoqb3B0aW1pc3RhcyoqLgo0LiAqKkxhIGVzY2FsYSBkZSBlbmdhZ2VtZW50IG5vIHNlIGRlcHVybyoqIHBvcnF1ZSBlbCBlbnVuY2lhZG8gbGEgZGEgcG9yIGRlcHVyYWRhLiBFcyBsYQogICBmdWVudGUgcHJpbmNpcGFsIGRlbCBkZXNhanVzdGUgZGVsIG1vZGVsbyBkZSBtZWRpY2lvbiwgeSBzdSBlc3RydWN0dXJhIHRlb3JpY2Egbm8gc2UKICAgc29zdGllbmUgZW4gZXN0YSBtdWVzdHJhLgo1LiAqKkxhIHJlcGxpY2FjaW9uIGRlbCBlamVyY2ljaW8gNCBwYXJ0ZSBkZSB1bmEgbWF0cml6IHB1YmxpY2FkYSoqLCBubyBkZSBsb3MgZGF0b3MKICAgb3JpZ2luYWxlcy4gTGFzIGRpZmVyZW5jaWFzIGNvbiBsbyByZXBvcnRhZG8gcHVlZGVuIGRlYmVyc2UgYSBkZWNpc2lvbmVzIGRlCiAgIGVzcGVjaWZpY2FjaW9uIGVuIExJU1JFTCBxdWUgZWwgYXJ0aWN1bG8gbm8gZG9jdW1lbnRhLgoKIyBSZWZlcmVuY2lhcwoKLSBCZWhzb24sIFMuIEouLCBFZGR5LCBFLiBSLiwgeSBMb3JlbnpldCwgUy4gSi4gKDIwMDApLiBUaGUgaW1wb3J0YW5jZSBvZiB0aGUgY3JpdGljYWwKICBwc3ljaG9sb2dpY2FsIHN0YXRlcyBpbiB0aGUgam9iIGNoYXJhY3RlcmlzdGljcyBtb2RlbDogQSBtZXRhLWFuYWx5dGljIGFuZCBzdHJ1Y3R1cmFsCiAgZXF1YXRpb25zIG1vZGVsaW5nIGV4YW1pbmF0aW9uLiAqQ3VycmVudCBSZXNlYXJjaCBpbiBTb2NpYWwgUHN5Y2hvbG9neSwgNSooMTIpLCAxNzAtLTE4OS4KLSBCb2xsZW4sIEsuIEEuICgxOTg5KS4gKlN0cnVjdHVyYWwgZXF1YXRpb25zIHdpdGggbGF0ZW50IHZhcmlhYmxlcyouIFdpbGV5LgotIEhhY2ttYW4sIEouIFIuLCB5IE9sZGhhbSwgRy4gUi4gKDE5NzYpLiBNb3RpdmF0aW9uIHRocm91Z2ggdGhlIGRlc2lnbiBvZiB3b3JrOiBUZXN0IG9mIGEKICB0aGVvcnkuICpPcmdhbml6YXRpb25hbCBCZWhhdmlvciBhbmQgSHVtYW4gUGVyZm9ybWFuY2UsIDE2KigyKSwgMjUwLS0yNzkuCi0gSG9semluZ2VyLCBLLiBKLiwgeSBTd2luZWZvcmQsIEYuICgxOTM5KS4gKkEgc3R1ZHkgaW4gZmFjdG9yIGFuYWx5c2lzOiBUaGUgc3RhYmlsaXR5IG9mIGEKICBiaS1mYWN0b3Igc29sdXRpb24qLiBVbml2ZXJzaXR5IG9mIENoaWNhZ28uCi0gSHUsIEwuLCB5IEJlbnRsZXIsIFAuIE0uICgxOTk5KS4gQ3V0b2ZmIGNyaXRlcmlhIGZvciBmaXQgaW5kZXhlcyBpbiBjb3ZhcmlhbmNlIHN0cnVjdHVyZQogIGFuYWx5c2lzLiAqU3RydWN0dXJhbCBFcXVhdGlvbiBNb2RlbGluZywgNiooMSksIDEtLTU1LgotIEtlbm55LCBELiBBLiwgS2FuaXNrYW4sIEIuLCB5IE1jQ29hY2gsIEQuIEIuICgyMDE1KS4gVGhlIHBlcmZvcm1hbmNlIG9mIFJNU0VBIGluIG1vZGVscwogIHdpdGggc21hbGwgZGVncmVlcyBvZiBmcmVlZG9tLiAqU29jaW9sb2dpY2FsIE1ldGhvZHMgYW5kIFJlc2VhcmNoLCA0NCooMyksIDQ4Ni0tNTA3LgotIFJvc3NlZWwsIFkuICgyMDEyKS4gbGF2YWFuOiBBbiBSIHBhY2thZ2UgZm9yIHN0cnVjdHVyYWwgZXF1YXRpb24gbW9kZWxpbmcuCiAgKkpvdXJuYWwgb2YgU3RhdGlzdGljYWwgU29mdHdhcmUsIDQ4KigyKSwgMS0tMzYuCi0gU2NoYXVmZWxpLCBXLiBCLiwgeSBCYWtrZXIsIEEuIEIuICgyMDAzKS4gKlVXRVM6IFV0cmVjaHQgV29yayBFbmdhZ2VtZW50IFNjYWxlKi4KICBPY2N1cGF0aW9uYWwgSGVhbHRoIFBzeWNob2xvZ3kgVW5pdCwgVXRyZWNodCBVbml2ZXJzaXR5LgoKYGBge3Igc2VzaW9uLCBlY2hvPUZBTFNFfQprYWJsZShkYXRhLmZyYW1lKENvbXBvbmVudGUgPSBjKCJSIiwgImxhdmFhbiIsICJTZW1pbGxhIiwgIk9ic2VydmFjaW9uZXMiKSwKICAgICAgICAgICAgICAgICBWYWxvciA9IGMoUi52ZXJzaW9uLnN0cmluZywgYXMuY2hhcmFjdGVyKHBhY2thZ2VWZXJzaW9uKCJsYXZhYW4iKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDI2IiwgbnJvdyhkKSkpLAogICAgICBjYXB0aW9uID0gIkVudG9ybm8gZGUgZWplY3VjaW9uIikKYGBgCg==