library(dplyr)
library(ggplot2)
Shiny app a los problemas
Problema 1:
Usted intenta determinar el rango de valores que puede tomar una variable aleatoria sobre la cual tiene poca experiencia. Para subsanar su falta de experiencia, ha decidido consultar a tres expertos en el tema: El experto A estima que la variable puede tomar un valor m´ınimo de 45, un valor m´as probable de 45 y un valor m´aximo de 70. El experto B estima valores de 50, 65 y 90 para los mismos par´ametros. El experto C considera que los valores de esos par´ametros debieran ser 50, 65 y 80. Sobre la base de la reputaci´on de cada experto, Usted asigna una ponderaci´on a cada opini´on. En su ponderaci´on le da un peso del 50 % a la opini´on del experto A, y un 25 % a cada uno de los otros expertos. Responda lo siguiente: 1. ¿Cu´al es la distribuci´on que va a emplear para definir la aleatoreidad de esta variable? 2. ¿Cu´al es el valor esperado de esta variable aleatoria?
Definimos nuestra vector de personas
get_montecarloest <- function(experto){
vmin<-experto[1]
vmax<-experto[3]
vest<-experto[2]
mn <- (vmin + 4*vest + vmax)/6
s <- abs((vmax - vmin)/6)
valmontecarlo <- rnorm(1, mean=mn,s)
return(valmontecarlo)
}
experto_a <-c(45,46,70)
experto_b <-c(50,65,90)
experto_c <-c(50,65,80)
definimos nuestra función de blend de expertos
get_opinion_experto<-function(idx){
ret<-get_montecarloest(experto_a)*.5+get_montecarloest(experto_b)*.25+get_montecarloest(experto_c)*.25
return(ret)
}
get_opinion_experto(0)
[1] 58.34753
Generamos nuestra simulacion
simulacion<-10000
sim<-sapply(1:simulacion, get_opinion_experto)
hist(sim)
abline(v=mean(sim),col="blue",lwd=2)
abline(v=median(sim),col="red",lwd=2)

hist(sim, prob=TRUE, col="gray",
main="Simulador (densidad)",
xlab="valor predicho",
ylim=c(0.0,0.7))
curve(dnorm(x, mean=mean(sim), sd=sd(sim)), add=TRUE, col="purple")

Respuestas 1.1
es una distribución normal
REspuesata 1.2
c(" Valor esperado ", mean(sim))
[1] " Valor esperado " "57.7694065142762"
Problema 2:
Usted es gerente de una empresa distribuidora de libros y debe tomar una decisi´on respecto al volumen de pedido de un libro para el pr´oximo trimestre, cada libro cuesta $7.5 y se vende por $10. Si al cabo del trimestre quedan libros sin vender, se pueden devolver a la editorial los ejemplares sobrantes obteniendo un reembolso de $2.50 por libro. El personal de ventas de la empresa estima que la demanda para ese libro para el pr´oximo trimestre se ajusta a la siguiente distribuci´on de probabilidad:
| 30% |
100-150 |
| 35% |
151-200 |
| 25% |
201-250 |
| 10% |
251-300 |
Determine el volumen de pedido con el objetivo de maximizar el resultado esperado
valor_costo<-7.5
valor_venta<-10
valor_reembolso<-2.5
tipo_demanda <-c("Excelente", "Bueno","Regular", "Malo")
probabilidad_demanda<- c(.10,.25,.35,.30)
rango_excelente<-251:300
rango_bueno<-201:250
rango_regular<-151:200
rango_malo<-100:150
rango_selected<-c()
simulaciones<-1000
tipodemanda<-numeric(simulaciones)
demanda_real<-numeric(simulaciones)
sobrante_real<-numeric(simulaciones)
result<-NULL
Resultado_Final<-NULL
for (d in 1:simulaciones) {
# calculamos un sample basado en la probabilidad del tipo de demanda
tipodemanda[d]<- sample(tipo_demanda, size=1, replace = TRUE, prob=probabilidad_demanda)
idx<-1
#verificamos el tipo de pedido
if(tipodemanda[d]=="Excelente")
{
rango_selected<-rango_excelente
idx<-1
}
if(tipodemanda[d]=="Bueno")
{
rango_selected<-rango_bueno
idx<-2
}
if(tipodemanda[d]=="Regular")
{
rango_selected<-rango_regular
idx=3
}
if(tipodemanda[d]=="Malo")
{
rango_selected<-rango_malo
idx<-4
}
demanda_real[d] <- sample(rango_selected, size=1, replace = TRUE )
sobrante_real[d]<-max(rango_selected)
venta<-demanda_real[d]*valor_venta
costo<-demanda_real[d]*valor_costo
sobrante<-sobrante_real[d]-demanda_real[d]
costo_sobrante<-sobrante*valor_costo
valor_sobrante<-sobrante*valor_reembolso
utilidad<-venta+valor_sobrante-costo-costo_sobrante
nuevo <- data.frame (iter=d,
tipo_demanda=tipodemanda[d],
demandareal=demanda_real[d],
compra= sobrante_real[d],
sobrante=sobrante,
Ganancia=utilidad,
ventas_reales=venta,
costos_reales=costo,
costo_sobrante=costo_sobrante,
valor_reembolso=valor_sobrante
)
result <- rbind(result, nuevo)
}
respuestas
result
c(" Valor esperado de la demanda es", mean(result$demandareal))
[1] " Valor esperado de la demanda es" "183.027"
pedido<-result$demandareal
hist(pedido)
abline(v=mean(pedido),col="blue",lwd=2)
abline(v=median(pedido),col="red",lwd=2)

Problema 3:
Usted es un inversor a quien un ingeniero agr´onomo de su confianza le present´o una propuesta para arrendar una superficie de 1.000 hect´areas para sembrar ma´ız. Las pautas sobre las que Usted va a basar su decisi´on de inversi´on son las siguientes: El duenio del campo pide 180 $/hect´area arrendada. El campo tiene buen potencial maicero. El agr´onomo estima que el rendimiento m´as probable ser´a de 7 ton/ha., aunque seg´un condiciones clim´aticas bajo un escenario pesimista el rendimiento podr´ıa caer a 4.5 ton/ha y bajo un escenario optimista podr´ıa ser tan alto como 9 ton/ha. El siguiente cuadro refleja la variabilidad esperada de rendimiento:
| probalidad |
15% |
25% |
35% |
25% |
| rendimiento |
4.5 a 5.5 |
5.5 a 6.5 |
6.5 a 7.5 |
7.5 a 9 |
Sus expectativas de precio en puerto a cosecha se resumen en un precio m´as probable de 90 $/ton, un precio pesimista de 85 $/ton y un precio optimista de 95 $/ton. Los gastos de cultivo presupuestados ascienden a 143 $/ha. El gasto de cosecha se presupuesta como un 8.5 % del ingreso bruto (precio en puerto por rendimiento). Los gastos de comercializaci´on incluyen gastos de fletes y acondicionamiento por 27 $/ton y comisiones e impuestos de 3 % del ingreso bruto. Los gastos de administraci´on presupuestados suman 22 $/ha.
Sobre la base de esta informaci´on, Usted debe estimar: 1. Saldo de caja neto esperado. 2. Probabilidad de perder dinero efectuando el negocio. 3. Probabilidad de lograr un saldo de caja neto mayor a $48.000.
costo_x_hectarea<- 180
tipo_rendimiento <-c("malo", "regular","bueno", "muy bueno")
probabilidad_rendimiento<- c(.15,.25,.35,.25)
intervalos_rendimiento_malo<- c(4.5,5.5)
intervalos_rendimiento_regular<- c(5.5,6.5)
intervalos_rendimiento_bueno<- c(6.5,7.5)
intervalos_rendimiento_muybueno<- c(7.5,9)
precio_tonelada<- c(85,90,95)
get_distest <- function(experto){
vmin<-experto[1]
vmax<-experto[2]
vest<-(vmax+vmin)/2
mn <- (vmin + 4*vest + vmax)/6
ret <- rnorm(1, mean=mn,3)
return(ret)
}
get_pricetonelada <- function(experto){
vmin<-experto[1]
vmax<-experto[3]
vest<- experto[2]
mn <- (vmin + 4*vest + vmax)/6
s <- abs((vmax - vmin)/6)
ret <- rnorm(1, mean=mn,s)
return(ret)
}
get_distest(intervalos_rendimiento_malo)
[1] 2.286751
simulaciones<-10000
tipodemanda<-numeric(simulaciones)
rendimiento_esperado<-numeric(simulaciones)
sobrante_real<-numeric(simulaciones)
result<-NULL
Resultado_Final<-NULL
for (d in 1:simulaciones) {
tipodemanda[d]<- sample(tipo_rendimiento, size=1, replace = TRUE, prob=probabilidad_rendimiento)
if(tipodemanda[d]=="malo")
{
rango_selected<-intervalos_rendimiento_malo
idx<-1
}
if(tipodemanda[d]=="regular")
{
rango_selected<-intervalos_rendimiento_regular
idx<-2
}
if(tipodemanda[d]=="bueno")
{
rango_selected<-intervalos_rendimiento_bueno
idx=3
}
if(tipodemanda[d]=="muy bueno")
{
rango_selected<-intervalos_rendimiento_muybueno
idx<-4
}
rendimiento_esperado[d] <- get_distest(rango_selected)
precio_acobrar <- get_pricetonelada(c(85,90,95))
toneladas<-rendimiento_esperado[d]
venta<-toneladas*precio_acobrar*1000
costo_hectaria<-costo_x_hectarea*1000
gasto_cultivo<-143*1000
gatos_cosecha<-1000*toneladas*precio_acobrar*(8.5/100 )
gasto_admin<-22*1000
gastos_comercializacion<-27*1000+precio_acobrar*(3/100 )
utilidad<-venta-gasto_cultivo-costo_hectaria-gatos_cosecha-gasto_admin-gastos_comercializacion
nuevo <- data.frame (iter=d,
tipo_rendimiento=tipodemanda[d],
precio_acobrar=precio_acobrar,
ganancia=utilidad,
rendimiento=toneladas,
venta_real=venta,
precio_ton=precio_acobrar,
costo_hectaria=costo_hectaria,
gatos_cosecha=gatos_cosecha,
gasto_admin=gasto_admin,
gasto_com<-gastos_comercializacion
)
result <- rbind(result, nuevo)
}
respuestas
result
hist(result$ganancia)
abline(v=mean(result$ganancia),col="blue",lwd=2)
abline(v=median(result$ganancia),col="red",lwd=2)

paste0("Saldo de caja esperado:", mean(result$ganancia), " probabilidad de perder dinero: ", 100*length(result$ganancia[result$ganancia<0])/ length(result$ganancia), "% probabilidad de tener utilizades mayores a 48k:",
100*length(result$ganancia[result$ganancia>48000])/ length(result$ganancia),"%"
)
[1] "Saldo de caja esperado:186729.629211717 probabilidad de perder dinero: 23.58% probabilidad de tener utilizades mayores a 48k:70.31%"
Problema 4:
Problema 5:
Usted est´a evaluando invertir en un proyecto con una duraci´on esperada de 5 anios. El monto de la inversi´on inicial es de $600,000. Se estima que al cabo de los 8 anios los activos del proyecto tendr´an un valor residual de $18,000. Las ventas estimadas oscilan en un rango entre un valor pesimista de 70,000 unidades, un valor m´as probable de 100,000 unidades, y un valor optimista de 130,000 unidades por anio. Para los efectos pr´acticos, se estima que este rango cubre un 95 % de los valores que pueda tomar la demanda. El precio del producto puede oscilar en un rango entre 8 $/unidad como valor pesimista, 9 $/unidad como valor m´as probable, y 10 $/unidad como valor optimista. El gasto variable puede variar entre 5.85 $/unidad como valor optimista, 6.3 $/unidad como valor m´as probable y 6.75 $/unidad como valor pesimista. Los gastos fijos se estima ascender´an a 160,000 $/anio. El costo de oportunidad del capital es de 10 % anual. Realice lo siguiente: 1. Estime el valor esperado y la variabilidad del VAN y la TIR del proyecto. 2. ¿Cu´al es la probabilidad de que el proyecto supere el costo de oportunidad del capital invertido? 3. ¿Cambiar´ıan sus estimaciones si las ventas de un anio guardaran relaci´on con las ventas del anio anterior?
inversion_inicial<-600000
valor_residual<-18000
ventas_estimada<-c(70000,100000,130000)
demanda<-.95
precio_producto<-c(8,9,10)
gatso_varaible<-c(5.85,6.3,6.75)
gastos_fijos<-160000
costo_oportunidad<-.10
simulaciones<-100
get_ventas <- function(venta){
vmin<-venta[1]
vmax<-venta[3]
vest<- venta[2]
mn <- (vmin + 4*vest + vmax)/6
s <- abs((vmax - vmin)/6)
ret <- rnorm(1, mean=mn,s)
return(ret)
}
ventas<-numeric(simulaciones)
rendimiento_esperado<-numeric(simulaciones)
sobrante_real<-numeric(simulaciones)
result<-NULL
Resultado_Final<-NULL
for( a in 1:5){
for (d in 1:simulaciones) {
ventasim <-get_ventas(ventas_estimada)
preciosim<-get_ventas(precio_producto)
gastovarsim<-get_ventas(gatso_varaible)
gastosfij<-gastos_fijos
revenue<-ventasim*preciosim
if(a==5){
revenue<-revenue+valor_residual
}
flujo<-revenue-gastovarsim-gastosfij
year=a
nuevo <- data.frame (iter=d,
anno<-year,
flujo<-flujo,
ventas<-ventasim,
preciosim<-preciosim,
gastovarsim<-gastovarsim,
gastosfij<-gastosfij,
revenue<-revenue
)
result <- rbind(result, nuevo)
}
tempflujo<-result$flujo[result$anno==a]
medianvalue<- median(tempflujo)
meanvalue<- mean(tempflujo)
nuevo <- data.frame (
anno<-a,
flujo_median<-medianvalue,
flujo_mean<-meanvalue
)
Resultado_Final <- rbind(Resultado_Final, nuevo)
}
Resultado_Final
library(FinancialMath)
result
hist(result$flujo)
abline(v=mean(result$flujo),col="blue",lwd=2)
abline(v=median(result$flujo),col="red",lwd=2)

van<-NPV(cf0=inversion_inicial,cf=Resultado_Final$flujo_mean....meanvalue,times=c(1,1,1,1,1),i=.1)
tir<-IRR(cf0=inversion_inicial,cf=Resultado_Final$flujo_mean....meanvalue,times=c(1,1,1,1,1))
paste0("van:", van," y tir:",tir)
[1] "van:2733522.05770734 y tir:5.1114571057968"
LS0tDQp0aXRsZTogIlBhcmNpYWwiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQpbU2hpbnkgYXBwICBhIGxvcyBwcm9ibGVtYXNdKGh0dHBzOi8vZWxncmFuYnlyLnNoaW55YXBwcy5pby9wYXJjaWFsLykNCg0KDQoNCiMgUHJvYmxlbWEgMToNCg0KVXN0ZWQgaW50ZW50YSBkZXRlcm1pbmFyIGVsIHJhbmdvIGRlIHZhbG9yZXMgcXVlIHB1ZWRlIHRvbWFyIHVuYSB2YXJpYWJsZSBhbGVhdG9yaWEgc29icmUgbGEgY3VhbA0KdGllbmUgcG9jYSBleHBlcmllbmNpYS4gUGFyYSBzdWJzYW5hciBzdSBmYWx0YSBkZSBleHBlcmllbmNpYSwgaGEgZGVjaWRpZG8gY29uc3VsdGFyIGEgdHJlcyBleHBlcnRvcw0KZW4gZWwgdGVtYToNCkVsIGV4cGVydG8gQSBlc3RpbWEgcXVlIGxhIHZhcmlhYmxlIHB1ZWRlIHRvbWFyIHVuIHZhbG9yIG3CtMSxbmltbyBkZSA0NSwgdW4gdmFsb3IgbcK0YXMgcHJvYmFibGUNCmRlIDQ1IHkgdW4gdmFsb3IgbcK0YXhpbW8gZGUgNzAuDQpFbCBleHBlcnRvIEIgZXN0aW1hIHZhbG9yZXMgZGUgNTAsIDY1IHkgOTAgcGFyYSBsb3MgbWlzbW9zIHBhcsK0YW1ldHJvcy4NCkVsIGV4cGVydG8gQyBjb25zaWRlcmEgcXVlIGxvcyB2YWxvcmVzIGRlIGVzb3MgcGFywrRhbWV0cm9zIGRlYmllcmFuIHNlciA1MCwgNjUgeSA4MC4NClNvYnJlIGxhIGJhc2UgZGUgbGEgcmVwdXRhY2nCtG9uIGRlIGNhZGEgZXhwZXJ0bywgVXN0ZWQgYXNpZ25hIHVuYSBwb25kZXJhY2nCtG9uIGEgY2FkYSBvcGluacK0b24uDQpFbiBzdSBwb25kZXJhY2nCtG9uIGxlIGRhIHVuIHBlc28gZGVsIDUwICUgYSBsYSBvcGluacK0b24gZGVsIGV4cGVydG8gQSwgeSB1biAyNSAlIGEgY2FkYSB1bm8NCmRlIGxvcyBvdHJvcyBleHBlcnRvcy4NClJlc3BvbmRhIGxvIHNpZ3VpZW50ZToNCjEuIMK/Q3XCtGFsIGVzIGxhIGRpc3RyaWJ1Y2nCtG9uIHF1ZSB2YSBhIGVtcGxlYXIgcGFyYSBkZWZpbmlyIGxhIGFsZWF0b3JlaWRhZCBkZSBlc3RhIHZhcmlhYmxlPw0KMi4gwr9DdcK0YWwgZXMgZWwgdmFsb3IgZXNwZXJhZG8gZGUgZXN0YSB2YXJpYWJsZSBhbGVhdG9yaWE/IA0KDQpEZWZpbmltb3MgbnVlc3RyYSB2ZWN0b3IgZGUgcGVyc29uYXMNCg0KYGBge3J9DQpnZXRfbW9udGVjYXJsb2VzdCA8LSBmdW5jdGlvbihleHBlcnRvKXsNCiAgdm1pbjwtZXhwZXJ0b1sxXQ0KICB2bWF4PC1leHBlcnRvWzNdDQogIHZlc3Q8LWV4cGVydG9bMl0NCiAgbW4gPC0gKHZtaW4gKyA0KnZlc3QgKyB2bWF4KS82DQogIHMgPC0gYWJzKCh2bWF4IC0gdm1pbikvNikNCiAgdmFsbW9udGVjYXJsbyA8LSBybm9ybSgxLCBtZWFuPW1uLHMpDQogIA0KICByZXR1cm4odmFsbW9udGVjYXJsbykNCn0NCg0KYGBgDQoNCg0KDQpgYGB7cn0NCmV4cGVydG9fYSA8LWMoNDUsNDYsNzApDQpleHBlcnRvX2IgPC1jKDUwLDY1LDkwKQ0KZXhwZXJ0b19jIDwtYyg1MCw2NSw4MCkNCg0KYGBgDQoNCmRlZmluaW1vcyBudWVzdHJhIGZ1bmNpw7NuIGRlIGJsZW5kIGRlIGV4cGVydG9zDQpgYGB7cn0NCmdldF9vcGluaW9uX2V4cGVydG88LWZ1bmN0aW9uKGlkeCl7DQpyZXQ8LWdldF9tb250ZWNhcmxvZXN0KGV4cGVydG9fYSkqLjUrZ2V0X21vbnRlY2FybG9lc3QoZXhwZXJ0b19iKSouMjUrZ2V0X21vbnRlY2FybG9lc3QoZXhwZXJ0b19jKSouMjUNCnJldHVybihyZXQpDQp9DQpnZXRfb3Bpbmlvbl9leHBlcnRvKDApDQpgYGANCkdlbmVyYW1vcyBudWVzdHJhIHNpbXVsYWNpb24NCmBgYHtyfQ0Kc2ltdWxhY2lvbjwtMTAwMDANCnNpbTwtc2FwcGx5KDE6c2ltdWxhY2lvbiwgZ2V0X29waW5pb25fZXhwZXJ0bykNCg0KaGlzdChzaW0pDQphYmxpbmUodj1tZWFuKHNpbSksY29sPSJibHVlIixsd2Q9MikNCmFibGluZSh2PW1lZGlhbihzaW0pLGNvbD0icmVkIixsd2Q9MikNCg0KYGBgDQoNCg0KYGBge3J9DQpoaXN0KHNpbSwgcHJvYj1UUlVFLCBjb2w9ImdyYXkiLCANCiAgICAgbWFpbj0iU2ltdWxhZG9yIChkZW5zaWRhZCkiLA0KICAgICB4bGFiPSJ2YWxvciBwcmVkaWNobyIsDQogICAgIHlsaW09YygwLjAsMC43KSkNCmN1cnZlKGRub3JtKHgsIG1lYW49bWVhbihzaW0pLCBzZD1zZChzaW0pKSwgYWRkPVRSVUUsIGNvbD0icHVycGxlIikNCmBgYA0KDQojIyMgUmVzcHVlc3RhcyAxLjENCmVzIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbA0KDQojIyMgUkVzcHVlc2F0YSAxLjINCg0KYGBge3J9DQpjKCIgVmFsb3IgZXNwZXJhZG8gIiwgbWVhbihzaW0pKQ0KYGBgDQoNCiMgUHJvYmxlbWEgMjoNCg0KVXN0ZWQgZXMgZ2VyZW50ZSBkZSB1bmEgZW1wcmVzYSBkaXN0cmlidWlkb3JhIGRlIGxpYnJvcyB5IGRlYmUgdG9tYXIgdW5hIGRlY2lzacK0b24gcmVzcGVjdG8gYWwNCnZvbHVtZW4gZGUgcGVkaWRvIGRlIHVuIGxpYnJvIHBhcmEgZWwgcHLCtG94aW1vIHRyaW1lc3RyZSwgY2FkYSBsaWJybyBjdWVzdGEgJDcuNSB5IHNlIHZlbmRlIHBvciAkMTAuDQpTaSBhbCBjYWJvIGRlbCB0cmltZXN0cmUgcXVlZGFuIGxpYnJvcyBzaW4gdmVuZGVyLCBzZSBwdWVkZW4gZGV2b2x2ZXIgYSBsYSBlZGl0b3JpYWwgbG9zIGVqZW1wbGFyZXMNCnNvYnJhbnRlcyBvYnRlbmllbmRvIHVuIHJlZW1ib2xzbyBkZSAkMi41MCBwb3IgbGlicm8uIEVsIHBlcnNvbmFsIGRlIHZlbnRhcyBkZSBsYSBlbXByZXNhIGVzdGltYQ0KcXVlIGxhIGRlbWFuZGEgcGFyYSBlc2UgbGlicm8gcGFyYSBlbCBwcsK0b3hpbW8gdHJpbWVzdHJlIHNlIGFqdXN0YSBhIGxhIHNpZ3VpZW50ZSBkaXN0cmlidWNpwrRvbiBkZQ0KcHJvYmFiaWxpZGFkOg0KDQp8IHByb2JhbGlkYWQgIHwgZGVtYW5kYSB8DQp8IC0tLS0tIHwgLS0tLS0tLS0tLS0gfA0KfCAzMCUgIHwgMTAwLTE1MCAgfA0KfCAzNSUgIHwgMTUxLTIwMCAgfA0KfCAyNSUgIHwgMjAxLTI1MCAgfA0KfCAxMCUgfCAyNTEtMzAwICB8DQoNCkRldGVybWluZSBlbCB2b2x1bWVuIGRlIHBlZGlkbyBjb24gZWwgb2JqZXRpdm8gZGUgbWF4aW1pemFyIGVsIHJlc3VsdGFkbyBlc3BlcmFkbw0KDQoNCmBgYHtyfQ0KdmFsb3JfY29zdG88LTcuNQ0KdmFsb3JfdmVudGE8LTEwDQp2YWxvcl9yZWVtYm9sc288LTIuNQ0KdGlwb19kZW1hbmRhIDwtYygiRXhjZWxlbnRlIiwgIkJ1ZW5vIiwiUmVndWxhciIsICJNYWxvIikNCnByb2JhYmlsaWRhZF9kZW1hbmRhPC0gYyguMTAsLjI1LC4zNSwuMzApDQpyYW5nb19leGNlbGVudGU8LTI1MTozMDANCnJhbmdvX2J1ZW5vPC0yMDE6MjUwDQpyYW5nb19yZWd1bGFyPC0xNTE6MjAwDQpyYW5nb19tYWxvPC0xMDA6MTUwDQpyYW5nb19zZWxlY3RlZDwtYygpDQpzaW11bGFjaW9uZXM8LTEwMDANCnRpcG9kZW1hbmRhPC1udW1lcmljKHNpbXVsYWNpb25lcykNCmRlbWFuZGFfcmVhbDwtbnVtZXJpYyhzaW11bGFjaW9uZXMpDQpzb2JyYW50ZV9yZWFsPC1udW1lcmljKHNpbXVsYWNpb25lcykNCnJlc3VsdDwtTlVMTA0KUmVzdWx0YWRvX0ZpbmFsPC1OVUxMDQoNCg0KIGZvciAoZCBpbiAxOnNpbXVsYWNpb25lcykgew0KICAgICMgY2FsY3VsYW1vcyB1biBzYW1wbGUgYmFzYWRvIGVuIGxhIHByb2JhYmlsaWRhZCBkZWwgdGlwbyBkZSBkZW1hbmRhDQogICAgdGlwb2RlbWFuZGFbZF08LSBzYW1wbGUodGlwb19kZW1hbmRhLCBzaXplPTEsIHJlcGxhY2UgPSBUUlVFLCBwcm9iPXByb2JhYmlsaWRhZF9kZW1hbmRhKSANCiAgICBpZHg8LTENCiAgICAjdmVyaWZpY2Ftb3MgZWwgdGlwbyBkZSBwZWRpZG8NCiAgICBpZih0aXBvZGVtYW5kYVtkXT09IkV4Y2VsZW50ZSIpDQogICAgew0KICAgICAgcmFuZ29fc2VsZWN0ZWQ8LXJhbmdvX2V4Y2VsZW50ZQ0KICAgICAgaWR4PC0xDQogICAgICANCiAgICB9DQogICAgaWYodGlwb2RlbWFuZGFbZF09PSJCdWVubyIpDQogICAgew0KICAgICAgcmFuZ29fc2VsZWN0ZWQ8LXJhbmdvX2J1ZW5vDQogICAgICBpZHg8LTINCiAgICB9DQogICAgDQogICAgDQogICAgaWYodGlwb2RlbWFuZGFbZF09PSJSZWd1bGFyIikNCiAgICB7DQogICAgICByYW5nb19zZWxlY3RlZDwtcmFuZ29fcmVndWxhcg0KICAgICAgaWR4PTMNCiAgICB9DQogICAgDQogICAgaWYodGlwb2RlbWFuZGFbZF09PSJNYWxvIikNCiAgICB7DQogICAgICByYW5nb19zZWxlY3RlZDwtcmFuZ29fbWFsbw0KICAgICAgaWR4PC00DQogICAgICANCiAgICB9DQogICAgZGVtYW5kYV9yZWFsW2RdIDwtIHNhbXBsZShyYW5nb19zZWxlY3RlZCwgc2l6ZT0xLCByZXBsYWNlID0gVFJVRSApDQogICAgc29icmFudGVfcmVhbFtkXTwtbWF4KHJhbmdvX3NlbGVjdGVkKQ0KICAgIA0KICAgIA0KICAgIHZlbnRhPC1kZW1hbmRhX3JlYWxbZF0qdmFsb3JfdmVudGENCiAgICBjb3N0bzwtZGVtYW5kYV9yZWFsW2RdKnZhbG9yX2Nvc3RvDQogICAgc29icmFudGU8LXNvYnJhbnRlX3JlYWxbZF0tZGVtYW5kYV9yZWFsW2RdDQogICAgY29zdG9fc29icmFudGU8LXNvYnJhbnRlKnZhbG9yX2Nvc3RvDQogICAgdmFsb3Jfc29icmFudGU8LXNvYnJhbnRlKnZhbG9yX3JlZW1ib2xzbw0KICAgIHV0aWxpZGFkPC12ZW50YSt2YWxvcl9zb2JyYW50ZS1jb3N0by1jb3N0b19zb2JyYW50ZQ0KICAgIG51ZXZvIDwtIGRhdGEuZnJhbWUgKGl0ZXI9ZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgdGlwb19kZW1hbmRhPXRpcG9kZW1hbmRhW2RdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBkZW1hbmRhcmVhbD1kZW1hbmRhX3JlYWxbZF0sDQogICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJhPSBzb2JyYW50ZV9yZWFsW2RdLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNvYnJhbnRlPXNvYnJhbnRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgIEdhbmFuY2lhPXV0aWxpZGFkLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHZlbnRhc19yZWFsZXM9dmVudGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgY29zdG9zX3JlYWxlcz1jb3N0bywNCiAgICAgICAgICAgICAgICAgICAgICAgICBjb3N0b19zb2JyYW50ZT1jb3N0b19zb2JyYW50ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICB2YWxvcl9yZWVtYm9sc289dmFsb3Jfc29icmFudGUNCiAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgcmVzdWx0IDwtIHJiaW5kKHJlc3VsdCwgbnVldm8pIA0KICAgIA0KIH0NCg0KYGBgDQoNCiMjIyByZXNwdWVzdGFzDQoNCmBgYHtyfQ0KcmVzdWx0DQoNCg0KYygiIFZhbG9yIGVzcGVyYWRvIGRlIGxhIGRlbWFuZGEgZXMiLCBtZWFuKHJlc3VsdCRkZW1hbmRhcmVhbCkpDQoNCnBlZGlkbzwtcmVzdWx0JGRlbWFuZGFyZWFsDQoNCmhpc3QocGVkaWRvKQ0KYWJsaW5lKHY9bWVhbihwZWRpZG8pLGNvbD0iYmx1ZSIsbHdkPTIpDQphYmxpbmUodj1tZWRpYW4ocGVkaWRvKSxjb2w9InJlZCIsbHdkPTIpDQoNCmBgYA0KDQoNCiMgUHJvYmxlbWEgMzoNCg0KVXN0ZWQgZXMgdW4gaW52ZXJzb3IgYSBxdWllbiB1biBpbmdlbmllcm8gYWdywrRvbm9tbyBkZSBzdSBjb25maWFuemEgbGUgcHJlc2VudMK0byB1bmEgcHJvcHVlc3RhIHBhcmENCmFycmVuZGFyIHVuYSBzdXBlcmZpY2llIGRlIDEuMDAwIGhlY3TCtGFyZWFzIHBhcmEgc2VtYnJhciBtYcK0xLF6LiBMYXMgcGF1dGFzIHNvYnJlIGxhcyBxdWUgVXN0ZWQgdmEgYQ0KYmFzYXIgc3UgZGVjaXNpwrRvbiBkZSBpbnZlcnNpwrRvbiBzb24gbGFzIHNpZ3VpZW50ZXM6DQpFbCBkdWVuaW8gZGVsIGNhbXBvIHBpZGUgMTgwICQvaGVjdMK0YXJlYSBhcnJlbmRhZGEuDQpFbCBjYW1wbyB0aWVuZSBidWVuIHBvdGVuY2lhbCBtYWljZXJvLiBFbCBhZ3LCtG9ub21vIGVzdGltYSBxdWUgZWwgcmVuZGltaWVudG8gbcK0YXMgcHJvYmFibGUNCnNlcsK0YSBkZSA3IHRvbi9oYS4sIGF1bnF1ZSBzZWfCtHVuIGNvbmRpY2lvbmVzIGNsaW3CtGF0aWNhcyBiYWpvIHVuIGVzY2VuYXJpbyBwZXNpbWlzdGEgZWwgcmVuZGltaWVudG8gcG9kcsK0xLFhIGNhZXIgYSA0LjUgdG9uL2hhIHkgYmFqbyB1biBlc2NlbmFyaW8gb3B0aW1pc3RhIHBvZHLCtMSxYSBzZXIgdGFuIGFsdG8gY29tbyA5DQp0b24vaGEuIEVsIHNpZ3VpZW50ZSBjdWFkcm8gcmVmbGVqYSBsYSB2YXJpYWJpbGlkYWQgZXNwZXJhZGEgZGUgcmVuZGltaWVudG86DQoNCnwgICB8IG1hbG8gfCAgcmVndWxhciB8ICBidWVubyB8IG11eSBidWVub3wNCnwgLS0tLS0gfCAtLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tIHwtLS0tLS0tLS0tLSB8DQp8IHByb2JhbGlkYWQgIHwgMTUlICB8ICAyNSUgIHwgIDM1JSAgfCAyNSUNCnwgcmVuZGltaWVudG98IDQuNSBhIDUuNSAgfCA1LjUgYSA2LjUgIHwgNi41IGEgNy41ICB8IDcuNSBhIDkNCg0KDQpTdXMgZXhwZWN0YXRpdmFzIGRlIHByZWNpbyBlbiBwdWVydG8gYSBjb3NlY2hhIHNlIHJlc3VtZW4gZW4gdW4gcHJlY2lvIG3CtGFzIHByb2JhYmxlIGRlIDkwDQokL3RvbiwgdW4gcHJlY2lvIHBlc2ltaXN0YSBkZSA4NSAkL3RvbiB5IHVuIHByZWNpbyBvcHRpbWlzdGEgZGUgOTUgJC90b24uDQpMb3MgZ2FzdG9zIGRlIGN1bHRpdm8gcHJlc3VwdWVzdGFkb3MgYXNjaWVuZGVuIGEgMTQzICQvaGEuDQpFbCBnYXN0byBkZSBjb3NlY2hhIHNlIHByZXN1cHVlc3RhIGNvbW8gdW4gOC41ICUgZGVsIGluZ3Jlc28gYnJ1dG8gKHByZWNpbyBlbiBwdWVydG8gcG9yDQpyZW5kaW1pZW50bykuDQpMb3MgZ2FzdG9zIGRlIGNvbWVyY2lhbGl6YWNpwrRvbiBpbmNsdXllbiBnYXN0b3MgZGUgZmxldGVzIHkgYWNvbmRpY2lvbmFtaWVudG8gcG9yIDI3ICQvdG9uIHkNCmNvbWlzaW9uZXMgZSBpbXB1ZXN0b3MgZGUgMyAlIGRlbCBpbmdyZXNvIGJydXRvLg0KTG9zIGdhc3RvcyBkZSBhZG1pbmlzdHJhY2nCtG9uIHByZXN1cHVlc3RhZG9zIHN1bWFuIDIyICQvaGEuDQoNClNvYnJlIGxhIGJhc2UgZGUgZXN0YSBpbmZvcm1hY2nCtG9uLCBVc3RlZCBkZWJlIGVzdGltYXI6DQoxLiBTYWxkbyBkZSBjYWphIG5ldG8gZXNwZXJhZG8uDQoyLiBQcm9iYWJpbGlkYWQgZGUgcGVyZGVyIGRpbmVybyBlZmVjdHVhbmRvIGVsIG5lZ29jaW8uDQozLiBQcm9iYWJpbGlkYWQgZGUgbG9ncmFyIHVuIHNhbGRvIGRlIGNhamEgbmV0byBtYXlvciBhICQ0OC4wMDAuDQoNCg0KYGBge3J9DQpjb3N0b194X2hlY3RhcmVhPC0gMTgwDQp0aXBvX3JlbmRpbWllbnRvIDwtYygibWFsbyIsICJyZWd1bGFyIiwiYnVlbm8iLCAibXV5IGJ1ZW5vIikNCnByb2JhYmlsaWRhZF9yZW5kaW1pZW50bzwtIGMoLjE1LC4yNSwuMzUsLjI1KQ0KaW50ZXJ2YWxvc19yZW5kaW1pZW50b19tYWxvPC0gYyg0LjUsNS41KQ0KaW50ZXJ2YWxvc19yZW5kaW1pZW50b19yZWd1bGFyPC0gYyg1LjUsNi41KQ0KaW50ZXJ2YWxvc19yZW5kaW1pZW50b19idWVubzwtIGMoNi41LDcuNSkNCmludGVydmFsb3NfcmVuZGltaWVudG9fbXV5YnVlbm88LSBjKDcuNSw5KQ0KcHJlY2lvX3RvbmVsYWRhPC0gYyg4NSw5MCw5NSkNCg0KZ2V0X2Rpc3Rlc3QgPC0gZnVuY3Rpb24oZXhwZXJ0byl7DQogIHZtaW48LWV4cGVydG9bMV0NCiAgdm1heDwtZXhwZXJ0b1syXQ0KICB2ZXN0PC0odm1heCt2bWluKS8yDQogIG1uIDwtICh2bWluICsgNCp2ZXN0ICsgdm1heCkvNg0KICByZXQgPC0gcm5vcm0oMSwgbWVhbj1tbiwzKQ0KICByZXR1cm4ocmV0KQ0KfQ0KDQpnZXRfcHJpY2V0b25lbGFkYSA8LSBmdW5jdGlvbihleHBlcnRvKXsNCiAgdm1pbjwtZXhwZXJ0b1sxXQ0KICB2bWF4PC1leHBlcnRvWzNdDQogIHZlc3Q8LSBleHBlcnRvWzJdDQogIG1uIDwtICh2bWluICsgNCp2ZXN0ICsgdm1heCkvNg0KICBzIDwtIGFicygodm1heCAtIHZtaW4pLzYpDQogIHJldCA8LSBybm9ybSgxLCBtZWFuPW1uLHMpDQogIHJldHVybihyZXQpDQp9DQoNCmdldF9kaXN0ZXN0KGludGVydmFsb3NfcmVuZGltaWVudG9fbWFsbykNCg0KDQpzaW11bGFjaW9uZXM8LTEwMDAwDQp0aXBvZGVtYW5kYTwtbnVtZXJpYyhzaW11bGFjaW9uZXMpDQpyZW5kaW1pZW50b19lc3BlcmFkbzwtbnVtZXJpYyhzaW11bGFjaW9uZXMpDQpzb2JyYW50ZV9yZWFsPC1udW1lcmljKHNpbXVsYWNpb25lcykNCnJlc3VsdDwtTlVMTA0KUmVzdWx0YWRvX0ZpbmFsPC1OVUxMDQoNCg0KZm9yIChkIGluIDE6c2ltdWxhY2lvbmVzKSB7DQogIHRpcG9kZW1hbmRhW2RdPC0gc2FtcGxlKHRpcG9fcmVuZGltaWVudG8sIHNpemU9MSwgcmVwbGFjZSA9IFRSVUUsIHByb2I9cHJvYmFiaWxpZGFkX3JlbmRpbWllbnRvKSANCiAgIGlmKHRpcG9kZW1hbmRhW2RdPT0ibWFsbyIpDQogICAgew0KICAgICAgcmFuZ29fc2VsZWN0ZWQ8LWludGVydmFsb3NfcmVuZGltaWVudG9fbWFsbw0KICAgICAgaWR4PC0xDQogICAgICANCiAgICB9DQogICAgaWYodGlwb2RlbWFuZGFbZF09PSJyZWd1bGFyIikNCiAgICB7DQogICAgICByYW5nb19zZWxlY3RlZDwtaW50ZXJ2YWxvc19yZW5kaW1pZW50b19yZWd1bGFyDQogICAgICBpZHg8LTINCiAgICB9DQogICAgDQogICAgDQogICAgaWYodGlwb2RlbWFuZGFbZF09PSJidWVubyIpDQogICAgew0KICAgICAgDQogICAgICByYW5nb19zZWxlY3RlZDwtaW50ZXJ2YWxvc19yZW5kaW1pZW50b19idWVubw0KICAgICAgaWR4PTMNCiAgICB9DQogICAgDQogICAgaWYodGlwb2RlbWFuZGFbZF09PSJtdXkgYnVlbm8iKQ0KICAgIHsNCiAgICAgIHJhbmdvX3NlbGVjdGVkPC1pbnRlcnZhbG9zX3JlbmRpbWllbnRvX211eWJ1ZW5vDQogICAgICBpZHg8LTQNCiAgICAgIA0KICAgIH0NCiAgDQogICAgcmVuZGltaWVudG9fZXNwZXJhZG9bZF0gPC0gZ2V0X2Rpc3Rlc3QocmFuZ29fc2VsZWN0ZWQpDQogIA0KICAgIHByZWNpb19hY29icmFyIDwtIGdldF9wcmljZXRvbmVsYWRhKGMoODUsOTAsOTUpKQ0KICAgIHRvbmVsYWRhczwtcmVuZGltaWVudG9fZXNwZXJhZG9bZF0NCiAgICB2ZW50YTwtdG9uZWxhZGFzKnByZWNpb19hY29icmFyKjEwMDANCiAgICBjb3N0b19oZWN0YXJpYTwtY29zdG9feF9oZWN0YXJlYSoxMDAwDQogICAgDQogICAgZ2FzdG9fY3VsdGl2bzwtMTQzKjEwMDANCiAgICBnYXRvc19jb3NlY2hhPC0xMDAwKnRvbmVsYWRhcypwcmVjaW9fYWNvYnJhciooOC41LzEwMCApDQogICAgZ2FzdG9fYWRtaW48LTIyKjEwMDANCiAgICBnYXN0b3NfY29tZXJjaWFsaXphY2lvbjwtMjcqMTAwMCtwcmVjaW9fYWNvYnJhciooMy8xMDAgKQ0KICAgIHV0aWxpZGFkPC12ZW50YS1nYXN0b19jdWx0aXZvLWNvc3RvX2hlY3RhcmlhLWdhdG9zX2Nvc2VjaGEtZ2FzdG9fYWRtaW4tZ2FzdG9zX2NvbWVyY2lhbGl6YWNpb24NCiAgICANCiAgICBudWV2byA8LSBkYXRhLmZyYW1lIChpdGVyPWQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRpcG9fcmVuZGltaWVudG89dGlwb2RlbWFuZGFbZF0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHByZWNpb19hY29icmFyPXByZWNpb19hY29icmFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGdhbmFuY2lhPXV0aWxpZGFkLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRpbWllbnRvPXRvbmVsYWRhcywNCiAgICAgICAgICAgICAgICAgICAgICAgICB2ZW50YV9yZWFsPXZlbnRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHByZWNpb190b249cHJlY2lvX2Fjb2JyYXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgY29zdG9faGVjdGFyaWE9Y29zdG9faGVjdGFyaWEsDQogICAgICAgICAgICAgICAgICAgICAgICAgZ2F0b3NfY29zZWNoYT1nYXRvc19jb3NlY2hhLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGdhc3RvX2FkbWluPWdhc3RvX2FkbWluLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGdhc3RvX2NvbTwtZ2FzdG9zX2NvbWVyY2lhbGl6YWNpb24NCiAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgcmVzdWx0IDwtIHJiaW5kKHJlc3VsdCwgbnVldm8pIA0KICAgIA0KICAgIA0KfQ0KDQoNCg0KDQpgYGANCg0KIyMjIHJlc3B1ZXN0YXMNCg0KYGBge3J9DQoNCnJlc3VsdA0KDQpoaXN0KHJlc3VsdCRnYW5hbmNpYSkNCmFibGluZSh2PW1lYW4ocmVzdWx0JGdhbmFuY2lhKSxjb2w9ImJsdWUiLGx3ZD0yKQ0KYWJsaW5lKHY9bWVkaWFuKHJlc3VsdCRnYW5hbmNpYSksY29sPSJyZWQiLGx3ZD0yKQ0KDQoNCg0KcGFzdGUwKCJTYWxkbyBkZSBjYWphIGVzcGVyYWRvOiIsIG1lYW4ocmVzdWx0JGdhbmFuY2lhKSwgIiBwcm9iYWJpbGlkYWQgZGUgcGVyZGVyIGRpbmVybzogIiwgMTAwKmxlbmd0aChyZXN1bHQkZ2FuYW5jaWFbcmVzdWx0JGdhbmFuY2lhPDBdKS8gbGVuZ3RoKHJlc3VsdCRnYW5hbmNpYSksICIlIHByb2JhYmlsaWRhZCBkZSB0ZW5lciB1dGlsaXphZGVzIG1heW9yZXMgYSA0OGs6IiwNCg0KMTAwKmxlbmd0aChyZXN1bHQkZ2FuYW5jaWFbcmVzdWx0JGdhbmFuY2lhPjQ4MDAwXSkvIGxlbmd0aChyZXN1bHQkZ2FuYW5jaWEpLCIlIg0KKQ0KYGBgDQoNCg0KIyBQcm9ibGVtYSA0Og0KDQojIFByb2JsZW1hIDU6DQoNClVzdGVkIGVzdMK0YSBldmFsdWFuZG8gaW52ZXJ0aXIgZW4gdW4gcHJveWVjdG8gY29uIHVuYSBkdXJhY2nCtG9uIGVzcGVyYWRhIGRlIDUgYW5pb3MuIEVsIG1vbnRvIGRlIGxhDQppbnZlcnNpwrRvbiBpbmljaWFsIGVzIGRlICQ2MDAsMDAwLiBTZSBlc3RpbWEgcXVlIGFsIGNhYm8gZGUgbG9zIDggYW5pb3MgbG9zIGFjdGl2b3MgZGVsIHByb3llY3RvIHRlbmRywrRhbg0KdW4gdmFsb3IgcmVzaWR1YWwgZGUgJDE4LDAwMC4gTGFzIHZlbnRhcyBlc3RpbWFkYXMgb3NjaWxhbiBlbiB1biByYW5nbyBlbnRyZSB1biB2YWxvciBwZXNpbWlzdGENCmRlIDcwLDAwMCB1bmlkYWRlcywgdW4gdmFsb3IgbcK0YXMgcHJvYmFibGUgZGUgMTAwLDAwMCB1bmlkYWRlcywgeSB1biB2YWxvciBvcHRpbWlzdGEgZGUgMTMwLDAwMA0KdW5pZGFkZXMgcG9yIGFuaW8uIFBhcmEgbG9zIGVmZWN0b3MgcHLCtGFjdGljb3MsIHNlIGVzdGltYSBxdWUgZXN0ZSByYW5nbyBjdWJyZSB1biA5NSAlIGRlIGxvcyB2YWxvcmVzDQpxdWUgcHVlZGEgdG9tYXIgbGEgZGVtYW5kYS4gRWwgcHJlY2lvIGRlbCBwcm9kdWN0byBwdWVkZSBvc2NpbGFyIGVuIHVuIHJhbmdvIGVudHJlIDggJC91bmlkYWQNCmNvbW8gdmFsb3IgcGVzaW1pc3RhLCA5ICQvdW5pZGFkIGNvbW8gdmFsb3IgbcK0YXMgcHJvYmFibGUsIHkgMTAgJC91bmlkYWQgY29tbyB2YWxvciBvcHRpbWlzdGEuDQpFbCBnYXN0byB2YXJpYWJsZSBwdWVkZSB2YXJpYXIgZW50cmUgNS44NSAkL3VuaWRhZCBjb21vIHZhbG9yIG9wdGltaXN0YSwgNi4zICQvdW5pZGFkIGNvbW8gdmFsb3INCm3CtGFzIHByb2JhYmxlIHkgNi43NSAkL3VuaWRhZCBjb21vIHZhbG9yIHBlc2ltaXN0YS4gTG9zIGdhc3RvcyBmaWpvcyBzZSBlc3RpbWEgYXNjZW5kZXLCtGFuIGEgMTYwLDAwMA0KJC9hbmlvLiBFbCBjb3N0byBkZSBvcG9ydHVuaWRhZCBkZWwgY2FwaXRhbCBlcyBkZSAxMCAlIGFudWFsLg0KUmVhbGljZSBsbyBzaWd1aWVudGU6DQoxLiBFc3RpbWUgZWwgdmFsb3IgZXNwZXJhZG8geSBsYSB2YXJpYWJpbGlkYWQgZGVsIFZBTiB5IGxhIFRJUiBkZWwgcHJveWVjdG8uDQoyLiDCv0N1wrRhbCBlcyBsYSBwcm9iYWJpbGlkYWQgZGUgcXVlIGVsIHByb3llY3RvIHN1cGVyZSBlbCBjb3N0byBkZSBvcG9ydHVuaWRhZCBkZWwgY2FwaXRhbCBpbnZlcnRpZG8/DQozLiDCv0NhbWJpYXLCtMSxYW4gc3VzIGVzdGltYWNpb25lcyBzaSBsYXMgdmVudGFzIGRlIHVuIGFuaW8gZ3VhcmRhcmFuIHJlbGFjacK0b24gY29uIGxhcyB2ZW50YXMgZGVsDQphbmlvIGFudGVyaW9yPw0KDQpgYGB7cn0NCmludmVyc2lvbl9pbmljaWFsPC02MDAwMDANCnZhbG9yX3Jlc2lkdWFsPC0xODAwMA0KdmVudGFzX2VzdGltYWRhPC1jKDcwMDAwLDEwMDAwMCwxMzAwMDApDQpkZW1hbmRhPC0uOTUNCnByZWNpb19wcm9kdWN0bzwtYyg4LDksMTApDQpnYXRzb192YXJhaWJsZTwtYyg1Ljg1LDYuMyw2Ljc1KQ0KZ2FzdG9zX2Zpam9zPC0xNjAwMDANCmNvc3RvX29wb3J0dW5pZGFkPC0uMTANCnNpbXVsYWNpb25lczwtMTAwDQpnZXRfdmVudGFzIDwtIGZ1bmN0aW9uKHZlbnRhKXsNCiAgdm1pbjwtdmVudGFbMV0NCiAgdm1heDwtdmVudGFbM10NCiAgdmVzdDwtIHZlbnRhWzJdDQogIG1uIDwtICh2bWluICsgNCp2ZXN0ICsgdm1heCkvNg0KICBzIDwtIGFicygodm1heCAtIHZtaW4pLzYpDQogIHJldCA8LSBybm9ybSgxLCBtZWFuPW1uLHMpDQogIHJldHVybihyZXQpDQp9DQoNCnZlbnRhczwtbnVtZXJpYyhzaW11bGFjaW9uZXMpDQpyZW5kaW1pZW50b19lc3BlcmFkbzwtbnVtZXJpYyhzaW11bGFjaW9uZXMpDQpzb2JyYW50ZV9yZWFsPC1udW1lcmljKHNpbXVsYWNpb25lcykNCnJlc3VsdDwtTlVMTA0KUmVzdWx0YWRvX0ZpbmFsPC1OVUxMDQoNCg0KZm9yKCBhIGluIDE6NSl7DQpmb3IgKGQgaW4gMTpzaW11bGFjaW9uZXMpIHsNCiAgDQogIHZlbnRhc2ltICA8LWdldF92ZW50YXModmVudGFzX2VzdGltYWRhKQ0KICBwcmVjaW9zaW08LWdldF92ZW50YXMocHJlY2lvX3Byb2R1Y3RvKQ0KICBnYXN0b3ZhcnNpbTwtZ2V0X3ZlbnRhcyhnYXRzb192YXJhaWJsZSkNCiAgZ2FzdG9zZmlqPC1nYXN0b3NfZmlqb3MNCiAgcmV2ZW51ZTwtdmVudGFzaW0qcHJlY2lvc2ltDQogIGlmKGE9PTUpew0KICAgIHJldmVudWU8LXJldmVudWUrdmFsb3JfcmVzaWR1YWwNCiAgfQ0KICBmbHVqbzwtcmV2ZW51ZS1nYXN0b3ZhcnNpbS1nYXN0b3NmaWoNCiAgeWVhcj1hDQogICAgICBudWV2byA8LSBkYXRhLmZyYW1lIChpdGVyPWQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vPC15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmx1am88LWZsdWpvLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHZlbnRhczwtdmVudGFzaW0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHByZWNpb3NpbTwtcHJlY2lvc2ltLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGdhc3RvdmFyc2ltPC1nYXN0b3ZhcnNpbSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBnYXN0b3NmaWo8LWdhc3Rvc2ZpaiwNCiAgICAgICAgICAgICAgICAgICAgICAgICByZXZlbnVlPC1yZXZlbnVlDQogICAgICAgICAgICAgICAgICAgICAgICAgKQ0KICAgIHJlc3VsdCA8LSByYmluZChyZXN1bHQsIG51ZXZvKSANCiAgDQogICAgDQp9DQogIHRlbXBmbHVqbzwtcmVzdWx0JGZsdWpvW3Jlc3VsdCRhbm5vPT1hXQ0KICBtZWRpYW52YWx1ZTwtICBtZWRpYW4odGVtcGZsdWpvKQ0KICBtZWFudmFsdWU8LSAgbWVhbih0ZW1wZmx1am8pDQoNCiAgbnVldm8gPC0gZGF0YS5mcmFtZSAoDQogICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vPC1hLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmx1am9fbWVkaWFuPC1tZWRpYW52YWx1ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBmbHVqb19tZWFuPC1tZWFudmFsdWUNCiAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgUmVzdWx0YWRvX0ZpbmFsIDwtIHJiaW5kKFJlc3VsdGFkb19GaW5hbCwgbnVldm8pIA0KICAgIA0KICANCn0NCg0KUmVzdWx0YWRvX0ZpbmFsDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KEZpbmFuY2lhbE1hdGgpDQpyZXN1bHQNCg0KaGlzdChyZXN1bHQkZmx1am8pDQphYmxpbmUodj1tZWFuKHJlc3VsdCRmbHVqbyksY29sPSJibHVlIixsd2Q9MikNCmFibGluZSh2PW1lZGlhbihyZXN1bHQkZmx1am8pLGNvbD0icmVkIixsd2Q9MikNCg0KdmFuPC1OUFYoY2YwPWludmVyc2lvbl9pbmljaWFsLGNmPVJlc3VsdGFkb19GaW5hbCRmbHVqb19tZWFuLi4uLm1lYW52YWx1ZSx0aW1lcz1jKDEsMSwxLDEsMSksaT0uMSkNCnRpcjwtSVJSKGNmMD1pbnZlcnNpb25faW5pY2lhbCxjZj1SZXN1bHRhZG9fRmluYWwkZmx1am9fbWVhbi4uLi5tZWFudmFsdWUsdGltZXM9YygxLDEsMSwxLDEpKQ0KcGFzdGUwKCJ2YW46IiwgdmFuLCIgeSB0aXI6Iix0aXIpIA0KDQoNCg0KYGBg