Comparación de Métodos de Optimización de Portafolios
En este documento, comparamos tres métodos de optimización de
portafolios: el Modelo de Markowitz, el Enfoque de Black-Litterman y el
Modelo de Optimización de Paridad de Riesgo.
Modelo de Markowitz (Teoría Moderna de Portafolios)(1)
Ventajas
- Fundamentación Teórica: Marco teórico sólido basado
en la diversificación y la relación riesgo-retorno.
- Frontera Eficiente: Identificación de la
combinación óptima de activos.
Desventajas
- Sensibilidad a las Entradas: Alta sensibilidad a
estimaciones de retorno y riesgo.
- Requiere Gran Cantidad de Datos: Necesidad de datos
históricos extensos.
Enfoque de Black-Litterman (2)
Ventajas
- Incorporación de Vistas del Inversionista:
Integración de expectativas específicas del inversionista.
- Estabilidad en las Estimaciones: Reduce la
sensibilidad a las estimaciones de entrada.
Desventajas
- Complejidad: Mayor complejidad en su
implementación.
- Dependencia de un Modelo de Mercado: Necesidad de
un modelo de mercado de referencia.
Modelo de Optimización de Paridad de Riesgo (3)
Ventajas
- Diversificación de Riesgo: Enfoque en igualar el
riesgo aportado por cada activo.
- Resiliencia en Mercados Volátiles: Mejor desempeño
en mercados volátiles.
Desventajas
- Puede Ignorar la Relación Riesgo-Retorno: No se
enfoca directamente en la maximización del retorno.
- Subestimación de Oportunidades de Rendimiento:
Posible subestimación de activos con mayor potencial.
Justificación para usar el Modelo de Markowitz
El modelo de Markowitz sigue siendo ampliamente utilizado por su
equilibrio entre riesgo y retorno, su base intuitiva y fundamentada, y
su adaptabilidad a diversos perfiles de inversión.
Pasos del Análisis
1. Cargar los Datos Históricos Este paso implica
recopilar datos históricos de los activos que se están considerando para
la inversión, como acciones, bonos o fondos. Estos datos suelen incluir
precios de cierre diarios, rendimientos, y cualquier otra información
relevante. Estos datos históricos son esenciales para realizar análisis
y proyecciones futuras.
2. Cálculo de Retornos Esperados y Varianza Aquí se
calculan dos aspectos críticos: los retornos esperados,
que es la ganancia o pérdida que se espera obtener de una inversión. Se
calcula a partir del promedio de los rendimientos históricos de un
activo; y el segundo es la varianza, la cual mide la
dispersión de los retornos de un activo en relación a su media, lo que
ayuda a entender el riesgo involucrado. Una mayor varianza indica una
mayor incertidumbre y riesgo.
3. Construcción de Portafolios En este paso, se
combinan diferentes activos para formar un portafolio. La selección de
activos y su proporción en el portafolio dependerá de los objetivos de
inversión, la tolerancia al riesgo y el horizonte temporal del inversor.
El objetivo es crear un portafolio equilibrado que optimice los retornos
mientras se gestiona el riesgo.
4. Análisis de Portafolios Aquí se evalúa el
rendimiento del portafolio, analizando aspectos como el retorno total,
el riesgo (volatilidad), y la correlación entre los activos del
portafolio. Este análisis ayuda a entender si el portafolio está
alineado con los objetivos y preferencias de riesgo del inversor.
5. Identificación de la Frontera Eficiente La
frontera eficiente es un concepto clave en la teoría de Markowitz.
Representa el conjunto de portafolios que ofrecen el máximo retorno
esperado para un nivel de riesgo dado o el mínimo riesgo para un nivel
de retorno dado. En este paso, se identifican estos portafolios mediante
técnicas de optimización.
6. Selección del Portafolio Eficiente Finalmente, se
selecciona el portafolio más adecuado de entre aquellos en la frontera
eficiente. Esta selección se basa en las preferencias personales del
inversor, su tolerancia al riesgo, y sus objetivos de inversión. El
resultado es un portafolio que busca maximizar los retornos ajustados al
riesgo según las necesidades específicas del inversor.
Conceptos Clave
Para el ejercicio práctico que se incluye en este documento, es
importante tener en cuenta los siguientes conceptos:
Riesgo y Retorno: Según Markowitz, el riesgo de un
portafolio se mide por la variabilidad de sus retornos, y los inversores
buscan maximizar los retornos minimizando el riesgo.
Diversificación: La diversificación de las
inversiones en diferentes activos reduce el riesgo del portafolio, ya
que los movimientos de precio no están perfectamente
correlacionados.
Frontera Eficiente: Es el conjunto de portafolios
que ofrecen el máximo retorno para un nivel de riesgo dado o el mínimo
riesgo para un nivel de retorno dado.
Selección de Portafolio: Los inversores seleccionan
portafolios sobre la frontera eficiente basados en sus preferencias de
riesgo y retorno.
Stocks (Acciones): Definición: Las acciones son
instrumentos financieros que representan una participación de propiedad
en una empresa. Al comprar acciones, el inversor se convierte en
accionista y, por tanto, en propietario de una parte de esa empresa.
Esto le da derecho a una parte de las ganancias de la empresa
(dividendos) y, en algunos casos, a voto en las juntas de
accionistas.
Ejemplo: Al comprar acciones de la empresa Apple Inc. se obtiene una
pequeña parte de propiedad de Apple. Si la empresa tiene éxito y sus
ganancias aumentan, el valor de las acciones puede subir, y también se
podría recibir dividendos.
Bonds (Bonos): Definición: Los bonos son
instrumentos de deuda utilizados tanto por entidades gubernamentales
como por corporaciones para recaudar fondos. Cuando se compra un bono,
se esta prestando dinero al emisor del bono a cambio de pagos de
intereses regulares durante la vida del bono y el reembolso del
principal (el monto original prestado) al vencimiento del bono.
Ejemplo: Se compran un bono del gobierno de Estados Unidos con un
valor nominal de $1,000, una tasa de interés anual del 2% y un
vencimiento de 10 años. Cada año, se recibirá $20 (2% de $1,000) y, al
final de los 10 años, recibirás de vuelta tus $1,000.
MM (Money Market / Mercado de Dinero): Definición:
El mercado de dinero es un segmento del mercado financiero donde se
negocian instrumentos de deuda a corto plazo, generalmente con
vencimientos de menos de un año. Los productos del mercado de dinero son
conocidos por su baja volatilidad y alta liquidez, lo que los hace
atractivos para inversionistas que buscan un lugar seguro para sus
inversiones a corto plazo.
Ejemplo: Los fondos del mercado de dinero son un ejemplo común. Se
invierte en un fondo de mercado de dinero que compra letras del Tesoro,
certificados de depósito y papel comercial. Este fondo ofrece seguridad
y liquidez, permitiéndote acceder al dinero rápidamente si se necesita,
aunque los rendimientos suelen ser más bajos en comparación con acciones
o bonos a largo plazo.
Código en R:
1. Cargar los Datos Históricos Primero, cargaremos
los datos históricos en R.
data <- data.frame(
year = 1960:2003,
stocks = c(17.21, 14.14, 14.54, 21.98, -4.8, 17.57, 20.94, -0.22, 9.81, -8.56, 5.27, 17.56, 9.14, 2.49, 11.52, 16.69, -4.34, -6.32, 35.74, 9.35, 32.06, 10.95, -2.79, -25.34, 14.85, -3.65, 16.95, 14.12, 20.71, -8.31, 16.98, 39.14, 16.2, 10.84, -4.7, 8.24, 30.77, -15.39, 14.46, -3.86, -14.87, -0.23, 20.32, 22.16),
bonds = c(17.11, 1.84, -2.67, 17.19, 5.17, 5.77, 9.92, 13.64, -2.34, 7.21, 7.01, 6.25, 13.66, 7.18, 9.13, 17.46, 12.97, 3.85, 8.27, 14.27, 4.76, 16.61, 12.21, 7.72, 2.2, 14.97, 13.46, 11.47, 0.75, 8.73, 16.05, 12.62, 12.88, 13.43, 13.76, 10.58, 11.31, 4.68, 10.39, 3.57, 7.57, 7.21, 7.28, 16.42),
mm = c(7.82, 9.77, 7.66, 10.35, 1.68, 8.34, 6.06, 4.91, 4.07, 7.88, 9.39, 9.87, 2.9, 4.9, 4.4, 7.69, 6.54, 3.27, 6.04, 8.09, 9.44, 4.3, 7.95, 9.18, 7.48, 4.23, 8.99, 7.67, 4.78, 3.81, 14.95, 8.6, 2.41, 4, 7.85, 3.43, 5.83, 4.88, 4.75, 9.38, 10.37, 7.57, 6.83, 7.79)
)
2. Cálculo de Retornos Esperados y Varianza
Calcularemos el retorno esperado, la varianza y la covarianza de los
activos.
library(PerformanceAnalytics)
# Asumiendo que los datos ya están en formato porcentual
returns <- data[, -1]
# Retorno esperado (media) y varianza
expected_returns <- colMeans(returns)
covariance_matrix <- cov(returns)
3. Construcción de Portafolios Generaremos
portafolios con diferentes combinaciones de los activos.
library(PortfolioAnalytics)
portfolio <- portfolio.spec(assets = colnames(returns))
portfolio <- add.constraint(portfolio, type = "full_investment")
portfolio <- add.constraint(portfolio, type = "box", min = 0, max = 1)
portfolio <- add.objective(portfolio, type = "return", name = "mean")
portfolio <- add.objective(portfolio, type = "risk", name = "StdDev")
4. Análisis de Portafolios y 5. Frontera
Eficiente
library(DEoptim)
library(xts)
library(PortfolioAnalytics)
# Transformar 'data' en objeto xts
data$year <- as.Date(as.character(data$year), format = "%Y")
returns_xts <- xts(data[, -1], order.by = data$year)
# Calcular retornos
returns <- diff(log(returns_xts))[-1, ]
Warning: Se han producido NaNs
# Optimización del portafolio
optimized_portfolio <- optimize.portfolio(returns, portfolio, optimize_method = "DEoptim", trace = TRUE)
Leverage constraint min_sum and max_sum are restrictive,
consider relaxing. e.g. 'full_investment' constraint should be min_sum=0.99 and max_sum=1.01
Iteration: 1 bestvalit: 0.471388 bestmemit: 0.333333 0.333333 0.333333
Iteration: 2 bestvalit: 0.467996 bestmemit: 0.274000 0.256000 0.470000
Iteration: 3 bestvalit: 0.467996 bestmemit: 0.274000 0.256000 0.470000
Iteration: 4 bestvalit: 0.467996 bestmemit: 0.274000 0.256000 0.470000
Iteration: 5 bestvalit: 0.467996 bestmemit: 0.274000 0.256000 0.470000
Iteration: 6 bestvalit: 0.467996 bestmemit: 0.274000 0.256000 0.470000
Iteration: 7 bestvalit: 0.467996 bestmemit: 0.274000 0.256000 0.470000
[1] 0.274 0.256 0.470
6. Selección del Portafolio Eficiente
Seleccionaremos el portafolio eficiente según los objetivos de
inversión.
efficient_portfolio <- extractWeights(optimized_portfolio)
LS0tDQp0aXRsZTogIlByb3llY3RvIEZpbmFsIFTDs3BpY29zIFNlbGVjdG9zIGRlIEZpbmFuemFzIg0KYXV0aG9yOiAiTUEgRGFuaWVsIEzDs3BleiINCmRhdGU6ICJaYXBvcGFuLCBEaWNpZW1icmUgMjAyMyAtIMOabHRpbWEgYWN0dWFsaXphY2nDs246IDE4LjEyLjIwMjMiICANCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIFByZXBhcmFkbyBwYXJhDQpwaGQgUGFibG8gTMOzcGV6DQoNCiMjIEludHJvZHVjY2nDs24NCiMjIENvbXBhcmFjacOzbiBkZSBNw6l0b2RvcyBkZSBPcHRpbWl6YWNpw7NuIGRlIFBvcnRhZm9saW9zDQoNCkVuIGVzdGUgZG9jdW1lbnRvLCBjb21wYXJhbW9zIHRyZXMgbcOpdG9kb3MgZGUgb3B0aW1pemFjacOzbiBkZSBwb3J0YWZvbGlvczogZWwgTW9kZWxvIGRlIE1hcmtvd2l0eiwgZWwgRW5mb3F1ZSBkZSBCbGFjay1MaXR0ZXJtYW4geSBlbCBNb2RlbG8gZGUgT3B0aW1pemFjacOzbiBkZSBQYXJpZGFkIGRlIFJpZXNnby4NCg0KIyMjIE1vZGVsbyBkZSBNYXJrb3dpdHogKFRlb3LDrWEgTW9kZXJuYSBkZSBQb3J0YWZvbGlvcykoMSkNCg0KIyMjIyBWZW50YWphcw0KDQotICoqRnVuZGFtZW50YWNpw7NuIFRlw7NyaWNhOioqIE1hcmNvIHRlw7NyaWNvIHPDs2xpZG8gYmFzYWRvIGVuIGxhIGRpdmVyc2lmaWNhY2nDs24geSBsYSByZWxhY2nDs24gcmllc2dvLXJldG9ybm8uDQotICoqRnJvbnRlcmEgRWZpY2llbnRlOioqIElkZW50aWZpY2FjacOzbiBkZSBsYSBjb21iaW5hY2nDs24gw7NwdGltYSBkZSBhY3Rpdm9zLg0KDQojIyMjIERlc3ZlbnRhamFzDQoNCi0gKipTZW5zaWJpbGlkYWQgYSBsYXMgRW50cmFkYXM6KiogQWx0YSBzZW5zaWJpbGlkYWQgYSBlc3RpbWFjaW9uZXMgZGUgcmV0b3JubyB5IHJpZXNnby4NCi0gKipSZXF1aWVyZSBHcmFuIENhbnRpZGFkIGRlIERhdG9zOioqIE5lY2VzaWRhZCBkZSBkYXRvcyBoaXN0w7NyaWNvcyBleHRlbnNvcy4NCg0KIyMjIEVuZm9xdWUgZGUgQmxhY2stTGl0dGVybWFuICgyKQ0KDQojIyMjIFZlbnRhamFzDQoNCi0gKipJbmNvcnBvcmFjacOzbiBkZSBWaXN0YXMgZGVsIEludmVyc2lvbmlzdGE6KiogSW50ZWdyYWNpw7NuIGRlIGV4cGVjdGF0aXZhcyBlc3BlY8OtZmljYXMgZGVsIGludmVyc2lvbmlzdGEuDQotICoqRXN0YWJpbGlkYWQgZW4gbGFzIEVzdGltYWNpb25lczoqKiBSZWR1Y2UgbGEgc2Vuc2liaWxpZGFkIGEgbGFzIGVzdGltYWNpb25lcyBkZSBlbnRyYWRhLg0KDQojIyMjIERlc3ZlbnRhamFzDQoNCi0gKipDb21wbGVqaWRhZDoqKiBNYXlvciBjb21wbGVqaWRhZCBlbiBzdSBpbXBsZW1lbnRhY2nDs24uDQotICoqRGVwZW5kZW5jaWEgZGUgdW4gTW9kZWxvIGRlIE1lcmNhZG86KiogTmVjZXNpZGFkIGRlIHVuIG1vZGVsbyBkZSBtZXJjYWRvIGRlIHJlZmVyZW5jaWEuDQoNCiMjIyBNb2RlbG8gZGUgT3B0aW1pemFjacOzbiBkZSBQYXJpZGFkIGRlIFJpZXNnbyAoMykNCg0KIyMjIyBWZW50YWphcw0KDQotICoqRGl2ZXJzaWZpY2FjacOzbiBkZSBSaWVzZ286KiogRW5mb3F1ZSBlbiBpZ3VhbGFyIGVsIHJpZXNnbyBhcG9ydGFkbyBwb3IgY2FkYSBhY3Rpdm8uDQotICoqUmVzaWxpZW5jaWEgZW4gTWVyY2Fkb3MgVm9sw6F0aWxlczoqKiBNZWpvciBkZXNlbXBlw7FvIGVuIG1lcmNhZG9zIHZvbMOhdGlsZXMuDQoNCiMjIyMgRGVzdmVudGFqYXMNCg0KLSAqKlB1ZWRlIElnbm9yYXIgbGEgUmVsYWNpw7NuIFJpZXNnby1SZXRvcm5vOioqIE5vIHNlIGVuZm9jYSBkaXJlY3RhbWVudGUgZW4gbGEgbWF4aW1pemFjacOzbiBkZWwgcmV0b3Juby4NCi0gKipTdWJlc3RpbWFjacOzbiBkZSBPcG9ydHVuaWRhZGVzIGRlIFJlbmRpbWllbnRvOioqIFBvc2libGUgc3ViZXN0aW1hY2nDs24gZGUgYWN0aXZvcyBjb24gbWF5b3IgcG90ZW5jaWFsLg0KDQojIyMgSnVzdGlmaWNhY2nDs24gcGFyYSB1c2FyIGVsIE1vZGVsbyBkZSBNYXJrb3dpdHoNCg0KRWwgbW9kZWxvIGRlIE1hcmtvd2l0eiBzaWd1ZSBzaWVuZG8gYW1wbGlhbWVudGUgdXRpbGl6YWRvIHBvciBzdSBlcXVpbGlicmlvIGVudHJlIHJpZXNnbyB5IHJldG9ybm8sIHN1IGJhc2UgaW50dWl0aXZhIHkgZnVuZGFtZW50YWRhLCB5IHN1IGFkYXB0YWJpbGlkYWQgYSBkaXZlcnNvcyBwZXJmaWxlcyBkZSBpbnZlcnNpw7NuLg0KDQoNCiMjIyBQYXNvcyBkZWwgQW7DoWxpc2lzDQoNCioqMS4gQ2FyZ2FyIGxvcyBEYXRvcyBIaXN0w7NyaWNvcyoqDQpFc3RlIHBhc28gaW1wbGljYSByZWNvcGlsYXIgZGF0b3MgaGlzdMOzcmljb3MgZGUgbG9zIGFjdGl2b3MgcXVlIHNlIGVzdMOhbiBjb25zaWRlcmFuZG8gcGFyYSBsYSBpbnZlcnNpw7NuLCBjb21vIGFjY2lvbmVzLCBib25vcyBvIGZvbmRvcy4gRXN0b3MgZGF0b3Mgc3VlbGVuIGluY2x1aXIgcHJlY2lvcyBkZSBjaWVycmUgZGlhcmlvcywgcmVuZGltaWVudG9zLCB5IGN1YWxxdWllciBvdHJhIGluZm9ybWFjacOzbiByZWxldmFudGUuIEVzdG9zIGRhdG9zIGhpc3TDs3JpY29zIHNvbiBlc2VuY2lhbGVzIHBhcmEgcmVhbGl6YXIgYW7DoWxpc2lzIHkgcHJveWVjY2lvbmVzIGZ1dHVyYXMuDQoNCioqMi4gQ8OhbGN1bG8gZGUgUmV0b3Jub3MgRXNwZXJhZG9zIHkgVmFyaWFuemEqKg0KQXF1w60gc2UgY2FsY3VsYW4gZG9zIGFzcGVjdG9zIGNyw610aWNvczogbG9zICoqcmV0b3Jub3MgZXNwZXJhZG9zKiosIHF1ZSBlcyBsYSBnYW5hbmNpYSBvIHDDqXJkaWRhIHF1ZSBzZSBlc3BlcmEgb2J0ZW5lciBkZSB1bmEgaW52ZXJzacOzbi4gU2UgY2FsY3VsYSBhIHBhcnRpciBkZWwgcHJvbWVkaW8gZGUgbG9zIHJlbmRpbWllbnRvcyBoaXN0w7NyaWNvcyBkZSB1biBhY3Rpdm87IHkgZWwgc2VndW5kbyBlcyBsYSAqKnZhcmlhbnphKiosIGxhIGN1YWwgbWlkZSBsYSBkaXNwZXJzacOzbiBkZSBsb3MgcmV0b3Jub3MgZGUgdW4gYWN0aXZvIGVuIHJlbGFjacOzbiBhIHN1IG1lZGlhLCBsbyBxdWUgYXl1ZGEgYSBlbnRlbmRlciBlbCByaWVzZ28gaW52b2x1Y3JhZG8uIFVuYSBtYXlvciB2YXJpYW56YSBpbmRpY2EgdW5hIG1heW9yIGluY2VydGlkdW1icmUgeSByaWVzZ28uDQoNCioqMy4gQ29uc3RydWNjacOzbiBkZSBQb3J0YWZvbGlvcyoqDQpFbiBlc3RlIHBhc28sIHNlIGNvbWJpbmFuIGRpZmVyZW50ZXMgYWN0aXZvcyBwYXJhIGZvcm1hciB1biBwb3J0YWZvbGlvLiBMYSBzZWxlY2Npw7NuIGRlIGFjdGl2b3MgeSBzdSBwcm9wb3JjacOzbiBlbiBlbCBwb3J0YWZvbGlvIGRlcGVuZGVyw6EgZGUgbG9zIG9iamV0aXZvcyBkZSBpbnZlcnNpw7NuLCBsYSB0b2xlcmFuY2lhIGFsIHJpZXNnbyB5IGVsIGhvcml6b250ZSB0ZW1wb3JhbCBkZWwgaW52ZXJzb3IuIEVsIG9iamV0aXZvIGVzIGNyZWFyIHVuIHBvcnRhZm9saW8gZXF1aWxpYnJhZG8gcXVlIG9wdGltaWNlIGxvcyByZXRvcm5vcyBtaWVudHJhcyBzZSBnZXN0aW9uYSBlbCByaWVzZ28uDQoNCioqNC4gQW7DoWxpc2lzIGRlIFBvcnRhZm9saW9zKioNCkFxdcOtIHNlIGV2YWzDumEgZWwgcmVuZGltaWVudG8gZGVsIHBvcnRhZm9saW8sIGFuYWxpemFuZG8gYXNwZWN0b3MgY29tbyBlbCByZXRvcm5vIHRvdGFsLCBlbCByaWVzZ28gKHZvbGF0aWxpZGFkKSwgeSBsYSBjb3JyZWxhY2nDs24gZW50cmUgbG9zIGFjdGl2b3MgZGVsIHBvcnRhZm9saW8uIEVzdGUgYW7DoWxpc2lzIGF5dWRhIGEgZW50ZW5kZXIgc2kgZWwgcG9ydGFmb2xpbyBlc3TDoSBhbGluZWFkbyBjb24gbG9zIG9iamV0aXZvcyB5IHByZWZlcmVuY2lhcyBkZSByaWVzZ28gZGVsIGludmVyc29yLg0KDQoqKjUuIElkZW50aWZpY2FjacOzbiBkZSBsYSBGcm9udGVyYSBFZmljaWVudGUqKg0KTGEgZnJvbnRlcmEgZWZpY2llbnRlIGVzIHVuIGNvbmNlcHRvIGNsYXZlIGVuIGxhIHRlb3LDrWEgZGUgTWFya293aXR6LiBSZXByZXNlbnRhIGVsIGNvbmp1bnRvIGRlIHBvcnRhZm9saW9zIHF1ZSBvZnJlY2VuIGVsIG3DoXhpbW8gcmV0b3JubyBlc3BlcmFkbyBwYXJhIHVuIG5pdmVsIGRlIHJpZXNnbyBkYWRvIG8gZWwgbcOtbmltbyByaWVzZ28gcGFyYSB1biBuaXZlbCBkZSByZXRvcm5vIGRhZG8uIEVuIGVzdGUgcGFzbywgc2UgaWRlbnRpZmljYW4gZXN0b3MgcG9ydGFmb2xpb3MgbWVkaWFudGUgdMOpY25pY2FzIGRlIG9wdGltaXphY2nDs24uDQoNCioqNi4gU2VsZWNjacOzbiBkZWwgUG9ydGFmb2xpbyBFZmljaWVudGUqKg0KRmluYWxtZW50ZSwgc2Ugc2VsZWNjaW9uYSBlbCBwb3J0YWZvbGlvIG3DoXMgYWRlY3VhZG8gZGUgZW50cmUgYXF1ZWxsb3MgZW4gbGEgZnJvbnRlcmEgZWZpY2llbnRlLiBFc3RhIHNlbGVjY2nDs24gc2UgYmFzYSBlbiBsYXMgcHJlZmVyZW5jaWFzIHBlcnNvbmFsZXMgZGVsIGludmVyc29yLCBzdSB0b2xlcmFuY2lhIGFsIHJpZXNnbywgeSBzdXMgb2JqZXRpdm9zIGRlIGludmVyc2nDs24uIEVsIHJlc3VsdGFkbyBlcyB1biBwb3J0YWZvbGlvIHF1ZSBidXNjYSBtYXhpbWl6YXIgbG9zIHJldG9ybm9zIGFqdXN0YWRvcyBhbCByaWVzZ28gc2Vnw7puIGxhcyBuZWNlc2lkYWRlcyBlc3BlY8OtZmljYXMgZGVsIGludmVyc29yLg0KDQojIyMgQ29uY2VwdG9zIENsYXZlDQpQYXJhIGVsIGVqZXJjaWNpbyBwcsOhY3RpY28gcXVlIHNlIGluY2x1eWUgZW4gZXN0ZSBkb2N1bWVudG8sIGVzIGltcG9ydGFudGUgdGVuZXIgZW4gY3VlbnRhIGxvcyBzaWd1aWVudGVzIGNvbmNlcHRvczoNCg0KKipSaWVzZ28geSBSZXRvcm5vOioqIFNlZ8O6biBNYXJrb3dpdHosIGVsIHJpZXNnbyBkZSB1biBwb3J0YWZvbGlvIHNlIG1pZGUgcG9yIGxhIHZhcmlhYmlsaWRhZCBkZSBzdXMgcmV0b3Jub3MsIHkgbG9zIGludmVyc29yZXMgYnVzY2FuIG1heGltaXphciBsb3MgcmV0b3Jub3MgbWluaW1pemFuZG8gZWwgcmllc2dvLg0KDQoqKkRpdmVyc2lmaWNhY2nDs246KiogTGEgZGl2ZXJzaWZpY2FjacOzbiBkZSBsYXMgaW52ZXJzaW9uZXMgZW4gZGlmZXJlbnRlcyBhY3Rpdm9zIHJlZHVjZSBlbCByaWVzZ28gZGVsIHBvcnRhZm9saW8sIHlhIHF1ZSBsb3MgbW92aW1pZW50b3MgZGUgcHJlY2lvIG5vIGVzdMOhbiBwZXJmZWN0YW1lbnRlIGNvcnJlbGFjaW9uYWRvcy4NCg0KKipGcm9udGVyYSBFZmljaWVudGU6KiogRXMgZWwgY29uanVudG8gZGUgcG9ydGFmb2xpb3MgcXVlIG9mcmVjZW4gZWwgbcOheGltbyByZXRvcm5vIHBhcmEgdW4gbml2ZWwgZGUgcmllc2dvIGRhZG8gbyBlbCBtw61uaW1vIHJpZXNnbyBwYXJhIHVuIG5pdmVsIGRlIHJldG9ybm8gZGFkby4NCg0KKipTZWxlY2Npw7NuIGRlIFBvcnRhZm9saW86KiogTG9zIGludmVyc29yZXMgc2VsZWNjaW9uYW4gcG9ydGFmb2xpb3Mgc29icmUgbGEgZnJvbnRlcmEgZWZpY2llbnRlIGJhc2Fkb3MgZW4gc3VzIHByZWZlcmVuY2lhcyBkZSByaWVzZ28geSByZXRvcm5vLg0KDQoqKlN0b2NrcyAoQWNjaW9uZXMpOioqDQpEZWZpbmljacOzbjoNCkxhcyBhY2Npb25lcyBzb24gaW5zdHJ1bWVudG9zIGZpbmFuY2llcm9zIHF1ZSByZXByZXNlbnRhbiB1bmEgcGFydGljaXBhY2nDs24gZGUgcHJvcGllZGFkIGVuIHVuYSBlbXByZXNhLiBBbCBjb21wcmFyIGFjY2lvbmVzLCBlbCBpbnZlcnNvciBzZSBjb252aWVydGUgZW4gYWNjaW9uaXN0YSB5LCBwb3IgdGFudG8sIGVuIHByb3BpZXRhcmlvIGRlIHVuYSBwYXJ0ZSBkZSBlc2EgZW1wcmVzYS4gRXN0byBsZSBkYSBkZXJlY2hvIGEgdW5hIHBhcnRlIGRlIGxhcyBnYW5hbmNpYXMgZGUgbGEgZW1wcmVzYSAoZGl2aWRlbmRvcykgeSwgZW4gYWxndW5vcyBjYXNvcywgYSB2b3RvIGVuIGxhcyBqdW50YXMgZGUgYWNjaW9uaXN0YXMuDQoNCkVqZW1wbG86DQpBbCBjb21wcmFyIGFjY2lvbmVzIGRlIGxhIGVtcHJlc2EgQXBwbGUgSW5jLiBzZSBvYnRpZW5lIHVuYSBwZXF1ZcOxYSBwYXJ0ZSBkZSBwcm9waWVkYWQgZGUgQXBwbGUuIFNpIGxhIGVtcHJlc2EgdGllbmUgw6l4aXRvIHkgc3VzIGdhbmFuY2lhcyBhdW1lbnRhbiwgZWwgdmFsb3IgZGUgbGFzIGFjY2lvbmVzIHB1ZWRlIHN1YmlyLCB5IHRhbWJpw6luIHNlIHBvZHLDrWEgcmVjaWJpciBkaXZpZGVuZG9zLg0KDQoqKkJvbmRzIChCb25vcyk6KioNCkRlZmluaWNpw7NuOg0KTG9zIGJvbm9zIHNvbiBpbnN0cnVtZW50b3MgZGUgZGV1ZGEgdXRpbGl6YWRvcyB0YW50byBwb3IgZW50aWRhZGVzIGd1YmVybmFtZW50YWxlcyBjb21vIHBvciBjb3Jwb3JhY2lvbmVzIHBhcmEgcmVjYXVkYXIgZm9uZG9zLiBDdWFuZG8gc2UgY29tcHJhIHVuIGJvbm8sIHNlIGVzdGEgcHJlc3RhbmRvIGRpbmVybyBhbCBlbWlzb3IgZGVsIGJvbm8gYSBjYW1iaW8gZGUgcGFnb3MgZGUgaW50ZXJlc2VzIHJlZ3VsYXJlcyBkdXJhbnRlIGxhIHZpZGEgZGVsIGJvbm8geSBlbCByZWVtYm9sc28gZGVsIHByaW5jaXBhbCAoZWwgbW9udG8gb3JpZ2luYWwgcHJlc3RhZG8pIGFsIHZlbmNpbWllbnRvIGRlbCBib25vLg0KDQpFamVtcGxvOg0KU2UgY29tcHJhbiB1biBib25vIGRlbCBnb2JpZXJubyBkZSBFc3RhZG9zIFVuaWRvcyBjb24gdW4gdmFsb3Igbm9taW5hbCBkZSAkMSwwMDAsIHVuYSB0YXNhIGRlIGludGVyw6lzIGFudWFsIGRlbCAyJSB5IHVuIHZlbmNpbWllbnRvIGRlIDEwIGHDsW9zLiBDYWRhIGHDsW8sIHNlIHJlY2liaXLDoSAkMjAgKDIlIGRlICQxLDAwMCkgeSwgYWwgZmluYWwgZGUgbG9zIDEwIGHDsW9zLCByZWNpYmlyw6FzIGRlIHZ1ZWx0YSB0dXMgJDEsMDAwLg0KDQoqKk1NIChNb25leSBNYXJrZXQgLyBNZXJjYWRvIGRlIERpbmVybyk6KioNCkRlZmluaWNpw7NuOg0KRWwgbWVyY2FkbyBkZSBkaW5lcm8gZXMgdW4gc2VnbWVudG8gZGVsIG1lcmNhZG8gZmluYW5jaWVybyBkb25kZSBzZSBuZWdvY2lhbiBpbnN0cnVtZW50b3MgZGUgZGV1ZGEgYSBjb3J0byBwbGF6bywgZ2VuZXJhbG1lbnRlIGNvbiB2ZW5jaW1pZW50b3MgZGUgbWVub3MgZGUgdW4gYcOxby4gTG9zIHByb2R1Y3RvcyBkZWwgbWVyY2FkbyBkZSBkaW5lcm8gc29uIGNvbm9jaWRvcyBwb3Igc3UgYmFqYSB2b2xhdGlsaWRhZCB5IGFsdGEgbGlxdWlkZXosIGxvIHF1ZSBsb3MgaGFjZSBhdHJhY3Rpdm9zIHBhcmEgaW52ZXJzaW9uaXN0YXMgcXVlIGJ1c2NhbiB1biBsdWdhciBzZWd1cm8gcGFyYSBzdXMgaW52ZXJzaW9uZXMgYSBjb3J0byBwbGF6by4NCg0KRWplbXBsbzoNCkxvcyBmb25kb3MgZGVsIG1lcmNhZG8gZGUgZGluZXJvIHNvbiB1biBlamVtcGxvIGNvbcO6bi4gU2UgaW52aWVydGUgZW4gdW4gZm9uZG8gZGUgbWVyY2FkbyBkZSBkaW5lcm8gcXVlIGNvbXByYSBsZXRyYXMgZGVsIFRlc29ybywgY2VydGlmaWNhZG9zIGRlIGRlcMOzc2l0byB5IHBhcGVsIGNvbWVyY2lhbC4gRXN0ZSBmb25kbyBvZnJlY2Ugc2VndXJpZGFkIHkgbGlxdWlkZXosIHBlcm1pdGnDqW5kb3RlIGFjY2VkZXIgYWwgZGluZXJvIHLDoXBpZGFtZW50ZSBzaSBzZSBuZWNlc2l0YSwgYXVucXVlIGxvcyByZW5kaW1pZW50b3Mgc3VlbGVuIHNlciBtw6FzIGJham9zIGVuIGNvbXBhcmFjacOzbiBjb24gYWNjaW9uZXMgbyBib25vcyBhIGxhcmdvIHBsYXpvLg0KDQojIyBBbsOhbGlzaXMgZGUgUG9ydGFmb2xpb3MgZW4gUjogRnVuY2lvbmVzIENsYXZlKDQpDQoNCkVuIGVzdGUgZG9jdW1lbnRvLCBleHBsb3JhbW9zIGN1YXRybyBmdW5jaW9uZXMgaW1wb3J0YW50ZXMgcGFyYSBlbCBhbsOhbGlzaXMgZGUgcG9ydGFmb2xpb3MgZW4gUiwgaW5jbHV5ZW5kbyBgREVvcHRpbWAgcGFyYSBsYSBvcHRpbWl6YWNpw7NuIGJhc2FkYSBlbiBsYSB0ZW9yw61hIGRlIE1hcmtvd2l0ei4NCg0KIyMjIEZ1bmNpb25lcyBkZSBBbsOhbGlzaXMgZGUgUG9ydGFmb2xpb3MNCg0KQSBjb250aW51YWNpw7NuLCBwcmVzZW50YW1vcyB1bmEgdGFibGEgcXVlIHJlc3VtZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBjdWF0cm8gZnVuY2lvbmVzIGNsYXZlOg0KDQp8IEZ1bmNpw7NuIHwgUGFxdWV0ZSB8IERlc2NyaXBjacOzbiB8IENhcmFjdGVyw61zdGljYXMgfA0KfC0tLS0tLS0tLXwtLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLXwNCnwgYHBvcnRmb2xpby5vcHRpbWAgfCBgdHNlcmllc2AgfCBPcHRpbWl6YSBwb3J0YWZvbGlvcyBiYXNhZG8gZW4gZWwgcmV0b3JubyB5IHJpZXNnby4gfCBVdGlsaXphIGxhIG1lZGlhLXZhcmlhbnphIHBhcmEgbGEgb3B0aW1pemFjacOzbi4gfA0KfCBgb3B0aW1pemUucG9ydGZvbGlvYCB8IGBQb3J0Zm9saW9BbmFseXRpY3NgIHwgUHJvcG9yY2lvbmEgdW4gbWFyY28gZmxleGlibGUgcGFyYSBsYSBjb25zdHJ1Y2Npw7NuIGRlIHBvcnRhZm9saW9zLiB8IEFkbWl0ZSByZXN0cmljY2lvbmVzIHBlcnNvbmFsaXphZGFzIHkgb2JqZXRpdm9zIG3Dumx0aXBsZXMuIHwNCnwgYFJldHVybi5wb3J0Zm9saW9gIHwgYFBlcmZvcm1hbmNlQW5hbHl0aWNzYCB8IENhbGN1bGEgZWwgcmV0b3JubyB0b3RhbCBkZSB1biBwb3J0YWZvbGlvLiB8IMOadGlsIHBhcmEgZWwgYW7DoWxpc2lzIHBvc3RlcmlvciBhIGxhIG9wdGltaXphY2nDs24uIHwNCnwgYERFb3B0aW1gIHwgYERFb3B0aW1gIHwgUmVhbGl6YSBsYSBvcHRpbWl6YWNpw7NuIGdsb2JhbCBiYXNhZGEgZW4gZWwgYWxnb3JpdG1vIGRlIGV2b2x1Y2nDs24gZGlmZXJlbmNpYWwuIHwgRWZpY2F6IHBhcmEgcHJvYmxlbWFzIGNvbXBsZWpvcyB5IG5vIGxpbmVhbGVzLiB8DQoNCiMjIyBKdXN0aWZpY2FjacOzbiBwYXJhIGxhIEVsZWNjacOzbiBkZSBgREVvcHRpbWANCg0KYERFb3B0aW1gIGVzIHVuYSBleGNlbGVudGUgZWxlY2Npw7NuIHBhcmEgbGEgb3B0aW1pemFjacOzbiBkZSBwb3J0YWZvbGlvcyBiYXNhZGEgZW4gbGEgdGVvcsOtYSBkZSBNYXJrb3dpdHogcG9yIHZhcmlhcyByYXpvbmVzOg0KDQoxLiAqKkZsZXhpYmlsaWRhZCBlbiBsYSBPcHRpbWl6YWNpw7NuOioqIGBERW9wdGltYCBlcyBlZmljYXogcGFyYSBtYW5lamFyIHByb2JsZW1hcyBkZSBvcHRpbWl6YWNpw7NuIGNvbXBsZWpvcyB5IG5vIGxpbmVhbGVzLCBsbyBxdWUgZXMgY29tw7puIGVuIGxhIG9wdGltaXphY2nDs24gZGUgcG9ydGFmb2xpb3MuDQoyLiAqKkNhcGFjaWRhZCBkZSBFdml0YXIgTcOtbmltb3MgTG9jYWxlczoqKiBBIGRpZmVyZW5jaWEgZGUgbG9zIG3DqXRvZG9zIGRlIG9wdGltaXphY2nDs24gdHJhZGljaW9uYWxlcyBxdWUgcHVlZGVuIHF1ZWRhciBhdHJhcGFkb3MgZW4gbcOtbmltb3MgbG9jYWxlcywgYERFb3B0aW1gIHV0aWxpemEgdW4gYWxnb3JpdG1vIGRlIGV2b2x1Y2nDs24gZGlmZXJlbmNpYWwgcXVlIGV4cGxvcmEgZGUgbWFuZXJhIG3DoXMgZWZlY3RpdmEgZWwgZXNwYWNpbyBkZSBzb2x1Y2lvbmVzLg0KMy4gKipBZGFwdGFiaWxpZGFkOioqIFB1ZWRlIG1hbmVqYXIgZGl2ZXJzYXMgcmVzdHJpY2Npb25lcyB5IG1vZGVsb3MsIGxvIHF1ZSBlcyBjcnVjaWFsIGN1YW5kbyBzZSB0cmFiYWphIGNvbiBsb3MgZGlmZXJlbnRlcyBlc2NlbmFyaW9zIHkgcHJlZmVyZW5jaWFzIGRlIGludmVyc2nDs24gcXVlIGNvbnRlbXBsYSBsYSB0ZW9yw61hIGRlIE1hcmtvd2l0ei4NCg0KRW4gcmVzdW1lbiwgYERFb3B0aW1gIHByb3BvcmNpb25hIHVuIGVuZm9xdWUgcm9idXN0byB5IGZsZXhpYmxlIHBhcmEgZW5jb250cmFyIGxhIGZyb250ZXJhIGVmaWNpZW50ZSBlbiBsYSBvcHRpbWl6YWNpw7NuIGRlIHBvcnRhZm9saW9zLCBhbGluZcOhbmRvc2UgYmllbiBjb24gbG9zIHByaW5jaXBpb3MgZGUgTWFya293aXR6IHNvYnJlIGRpdmVyc2lmaWNhY2nDs24geSBiYWxhbmNlIGVudHJlIHJpZXNnbyB5IHJldG9ybm8uDQoNCkEgY29udGludWFjacOzbiwgc2UgcHJvY2VkZSBjb24gZWwgZWplcmNpY2lvIHByw6FjdGljby4NCg0KIyMgQ8OzZGlnbyBlbiBSOg0KDQoqKjEuIENhcmdhciBsb3MgRGF0b3MgSGlzdMOzcmljb3MqKg0KUHJpbWVybywgY2FyZ2FyZW1vcyBsb3MgZGF0b3MgaGlzdMOzcmljb3MgZW4gUi4NCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKA0KICB5ZWFyID0gMTk2MDoyMDAzLA0KICBzdG9ja3MgPSBjKDE3LjIxLCAxNC4xNCwgMTQuNTQsIDIxLjk4LCAtNC44LCAxNy41NywgMjAuOTQsIC0wLjIyLCA5LjgxLCAtOC41NiwgNS4yNywgMTcuNTYsIDkuMTQsIDIuNDksIDExLjUyLCAxNi42OSwgLTQuMzQsIC02LjMyLCAzNS43NCwgOS4zNSwgMzIuMDYsIDEwLjk1LCAtMi43OSwgLTI1LjM0LCAxNC44NSwgLTMuNjUsIDE2Ljk1LCAxNC4xMiwgMjAuNzEsIC04LjMxLCAxNi45OCwgMzkuMTQsIDE2LjIsIDEwLjg0LCAtNC43LCA4LjI0LCAzMC43NywgLTE1LjM5LCAxNC40NiwgLTMuODYsIC0xNC44NywgLTAuMjMsIDIwLjMyLCAyMi4xNiksDQogIGJvbmRzID0gYygxNy4xMSwgMS44NCwgLTIuNjcsIDE3LjE5LCA1LjE3LCA1Ljc3LCA5LjkyLCAxMy42NCwgLTIuMzQsIDcuMjEsIDcuMDEsIDYuMjUsIDEzLjY2LCA3LjE4LCA5LjEzLCAxNy40NiwgMTIuOTcsIDMuODUsIDguMjcsIDE0LjI3LCA0Ljc2LCAxNi42MSwgMTIuMjEsIDcuNzIsIDIuMiwgMTQuOTcsIDEzLjQ2LCAxMS40NywgMC43NSwgOC43MywgMTYuMDUsIDEyLjYyLCAxMi44OCwgMTMuNDMsIDEzLjc2LCAxMC41OCwgMTEuMzEsIDQuNjgsIDEwLjM5LCAzLjU3LCA3LjU3LCA3LjIxLCA3LjI4LCAxNi40MiksDQogIG1tID0gYyg3LjgyLCA5Ljc3LCA3LjY2LCAxMC4zNSwgMS42OCwgOC4zNCwgNi4wNiwgNC45MSwgNC4wNywgNy44OCwgOS4zOSwgOS44NywgMi45LCA0LjksIDQuNCwgNy42OSwgNi41NCwgMy4yNywgNi4wNCwgOC4wOSwgOS40NCwgNC4zLCA3Ljk1LCA5LjE4LCA3LjQ4LCA0LjIzLCA4Ljk5LCA3LjY3LCA0Ljc4LCAzLjgxLCAxNC45NSwgOC42LCAyLjQxLCA0LCA3Ljg1LCAzLjQzLCA1LjgzLCA0Ljg4LCA0Ljc1LCA5LjM4LCAxMC4zNywgNy41NywgNi44MywgNy43OSkNCikNCg0KYGBgDQoqKjIuIEPDoWxjdWxvIGRlIFJldG9ybm9zIEVzcGVyYWRvcyB5IFZhcmlhbnphKioNCkNhbGN1bGFyZW1vcyBlbCByZXRvcm5vIGVzcGVyYWRvLCBsYSB2YXJpYW56YSB5IGxhIGNvdmFyaWFuemEgZGUgbG9zIGFjdGl2b3MuDQpgYGB7cn0NCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQojIEFzdW1pZW5kbyBxdWUgbG9zIGRhdG9zIHlhIGVzdMOhbiBlbiBmb3JtYXRvIHBvcmNlbnR1YWwNCnJldHVybnMgPC0gZGF0YVssIC0xXQ0KDQojIFJldG9ybm8gZXNwZXJhZG8gKG1lZGlhKSB5IHZhcmlhbnphDQpleHBlY3RlZF9yZXR1cm5zIDwtIGNvbE1lYW5zKHJldHVybnMpDQpjb3ZhcmlhbmNlX21hdHJpeCA8LSBjb3YocmV0dXJucykNCg0KYGBgDQoqKjMuIENvbnN0cnVjY2nDs24gZGUgUG9ydGFmb2xpb3MqKg0KR2VuZXJhcmVtb3MgcG9ydGFmb2xpb3MgY29uIGRpZmVyZW50ZXMgY29tYmluYWNpb25lcyBkZSBsb3MgYWN0aXZvcy4NCmBgYHtyfQ0KbGlicmFyeShQb3J0Zm9saW9BbmFseXRpY3MpDQpwb3J0Zm9saW8gPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzID0gY29sbmFtZXMocmV0dXJucykpDQpwb3J0Zm9saW8gPC0gYWRkLmNvbnN0cmFpbnQocG9ydGZvbGlvLCB0eXBlID0gImZ1bGxfaW52ZXN0bWVudCIpDQpwb3J0Zm9saW8gPC0gYWRkLmNvbnN0cmFpbnQocG9ydGZvbGlvLCB0eXBlID0gImJveCIsIG1pbiA9IDAsIG1heCA9IDEpDQpwb3J0Zm9saW8gPC0gYWRkLm9iamVjdGl2ZShwb3J0Zm9saW8sIHR5cGUgPSAicmV0dXJuIiwgbmFtZSA9ICJtZWFuIikNCnBvcnRmb2xpbyA8LSBhZGQub2JqZWN0aXZlKHBvcnRmb2xpbywgdHlwZSA9ICJyaXNrIiwgbmFtZSA9ICJTdGREZXYiKQ0KDQpgYGANCioqNC4gQW7DoWxpc2lzIGRlIFBvcnRhZm9saW9zIHkgNS4gRnJvbnRlcmEgRWZpY2llbnRlKioNCmBgYHtyfQ0KbGlicmFyeShERW9wdGltKQ0KbGlicmFyeSh4dHMpDQpsaWJyYXJ5KFBvcnRmb2xpb0FuYWx5dGljcykNCg0KIyBUcmFuc2Zvcm1hciAnZGF0YScgZW4gb2JqZXRvIHh0cw0KZGF0YSR5ZWFyIDwtIGFzLkRhdGUoYXMuY2hhcmFjdGVyKGRhdGEkeWVhciksIGZvcm1hdCA9ICIlWSIpDQpyZXR1cm5zX3h0cyA8LSB4dHMoZGF0YVssIC0xXSwgb3JkZXIuYnkgPSBkYXRhJHllYXIpDQoNCiMgQ2FsY3VsYXIgcmV0b3Jub3MNCnJldHVybnMgPC0gZGlmZihsb2cocmV0dXJuc194dHMpKVstMSwgXQ0KDQojIE9wdGltaXphY2nDs24gZGVsIHBvcnRhZm9saW8NCm9wdGltaXplZF9wb3J0Zm9saW8gPC0gb3B0aW1pemUucG9ydGZvbGlvKHJldHVybnMsIHBvcnRmb2xpbywgb3B0aW1pemVfbWV0aG9kID0gIkRFb3B0aW0iLCB0cmFjZSA9IFRSVUUpDQoNCmBgYA0KKio2LiBTZWxlY2Npw7NuIGRlbCBQb3J0YWZvbGlvIEVmaWNpZW50ZSoqDQpTZWxlY2Npb25hcmVtb3MgZWwgcG9ydGFmb2xpbyBlZmljaWVudGUgc2Vnw7puIGxvcyBvYmpldGl2b3MgZGUgaW52ZXJzacOzbi4NCmBgYHtyfQ0KZWZmaWNpZW50X3BvcnRmb2xpbyA8LSBleHRyYWN0V2VpZ2h0cyhvcHRpbWl6ZWRfcG9ydGZvbGlvKQ0KDQpgYGANCiMjIFJlc3VtZW5lcyB5IGdyw6FmaWNvcw0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoY29ycnBsb3QpDQoNCiMgMS4gUmVzdW1lbiBkZSBsb3MgRGF0b3MNCnByaW50KHN1bW1hcnkoZGF0YSkpDQoNCiMgMi4gR3LDoWZpY28gZGUgU2VyaWVzIFRlbXBvcmFsZXMgZGUgbG9zIFJldG9ybm9zDQpkYXRhX2xvbmcgPC0gZGF0YSAlPiUgDQogIHBpdm90X2xvbmdlcigteWVhciwgbmFtZXNfdG8gPSAiYXNzZXQiLCB2YWx1ZXNfdG8gPSAicmV0dXJucyIpDQoNCmdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0geWVhciwgeSA9IHJldHVybnMsIGNvbG9yID0gYXNzZXQpKSArDQogIGdlb21fbGluZSgpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJTZXJpZXMgVGVtcG9yYWxlcyBkZSBSZXRvcm5vcyIsIHggPSAiQcOxbyIsIHkgPSAiUmV0b3JubyIsIGNvbG9yID0gIkFjdGl2byIpDQpgYGANCiMjIyBBbsOhbGlzaXMgZGUgU2VyaWVzIFRlbXBvcmFsZXMgZGUgUmV0b3Jub3MgZGUgSW52ZXJzaW9uZXMNCg0KRXN0ZSBkb2N1bWVudG8gcHJlc2VudGEgdW4gYW7DoWxpc2lzIHZpc3VhbCBkZSBsb3MgcmV0b3Jub3MgZGUgZGlmZXJlbnRlcyB0aXBvcyBkZSBpbnZlcnNpb25lcyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8uDQoNCiMjIyMgRGVzY3JpcGNpw7NuIGRlbCBHcsOhZmljbyBkZSBTZXJpZXMgVGVtcG9yYWxlcw0KDQpFbCBncsOhZmljbyBpbHVzdHJhIGPDs21vIGhhbiBmbHVjdHVhZG8gbG9zIHJldG9ybm9zIGRlIGFjY2lvbmVzLCBib25vcyB5IGVsIG1lcmNhZG8gbW9uZXRhcmlvIGRlc2RlIDE5NjAgaGFzdGEgcHJpbmNpcGlvcyBkZWwgMjAwMC4NCg0KIyMjIyBDb21wb25lbnRlcyBkZWwgR3LDoWZpY28NCi0gKipMw61uZWFzIGRlbCBHcsOhZmljbzoqKiANCiAgLSBMYSBsw61uZWEgYXp1bCByZXByZXNlbnRhIGxhcyBhY2Npb25lcyAoYHN0b2Nrc2ApLg0KICAtIExhIGzDrW5lYSByb2phIHJlcHJlc2VudGEgbG9zIGJvbm9zIChgYm9uZHNgKS4NCiAgLSBMYSBsw61uZWEgdmVyZGUgcmVwcmVzZW50YSBlbCBtZXJjYWRvIG1vbmV0YXJpbyAoYG1tYCkuDQoNCi0gKipFamUgVmVydGljYWwgLSBSZXRvcm5vOioqIA0KICAtIEluZGljYSBlbCByZXRvcm5vIGRlIGxhcyBpbnZlcnNpb25lcyBlbiBwb3JjZW50YWplLg0KICAtIFVuIHZhbG9yIG3DoXMgYWx0byBzaWduaWZpY2EgdW4gbWF5b3IgcmV0b3JubyBlbiBlc2UgYcOxby4NCg0KLSAqKkVqZSBIb3Jpem9udGFsIC0gQcOxbzoqKiANCiAgLSBNdWVzdHJhIGxhIGzDrW5lYSBkZSB0aWVtcG8gZGVzZGUgMTk2MCBoYXN0YSBlbCAyMDAwLg0KDQojIyMjIEludGVycHJldGFjacOzbiBkZSBsb3MgRGF0b3MNCg0KIyMjIyMgVm9sYXRpbGlkYWQNCi0gTGEgdm9sYXRpbGlkYWQgZGUgbGFzIGFjY2lvbmVzIHNlIHJlZmxlamEgZW4gbGEgYW1wbGl0dWQgZGUgbG9zIHBpY29zIChhenVsZXMpLCBsbyBxdWUgaW5kaWNhIHBvdGVuY2lhbCB0YW50byBwYXJhIGFsdG9zIHJldG9ybm9zIGNvbW8gcGFyYSBjYcOtZGFzIHNpZ25pZmljYXRpdmFzLg0KDQojIyMjIyBFc3RhYmlsaWRhZA0KLSBMb3MgYm9ub3MsIHJlcHJlc2VudGFkb3MgcG9yIGxhIGzDrW5lYSByb2phLCBtdWVzdHJhbiBtZW5vcyB2b2xhdGlsaWRhZCwgc3VnaXJpZW5kbyBxdWUgc29uIG1lbm9zIHJpZXNnb3NvcyB5IG9mcmVjZW4gcmV0b3Jub3MgbcOhcyBwcmVkZWNpYmxlcy4NCg0KIyMjIyMgQ29uc2VydmFkdXJpc21vDQotIExhIGzDrW5lYSB2ZXJkZSBkZWwgbWVyY2FkbyBtb25ldGFyaW8gbXVlc3RyYSBsYSBtYXlvciBlc3RhYmlsaWRhZCBlbnRyZSBsb3MgdHJlcywgaW5kaWNhbmRvIHVuYSBvcGNpw7NuIGRlIGludmVyc2nDs24gY29uc2VydmFkb3JhIGNvbiBtZW5vcmVzIHJldG9ybm9zIHBlcm8gdGFtYmnDqW4gbWVub3Igcmllc2dvLg0KDQojIyMjIEVzdHJhdGVnaWFzIGRlIEludmVyc2nDs24NCg0KIyMjIyMgRGl2ZXJzaWZpY2FjacOzbg0KLSBDb21iaW5hciBlc3RvcyB0aXBvcyBkZSBhY3Rpdm9zIHB1ZWRlIGJhbGFuY2VhciBlbCByaWVzZ28geSBlbCByZXRvcm5vLCBheXVkYW5kbyBhIG1pdGlnYXIgbG9zIGVmZWN0b3MgZGUgdW4gbWFsIGHDsW8gcGFyYSB1biBhY3Rpdm8gZXNwZWPDrWZpY28uDQoNCiMjIyMjIFBlcmZpbCBkZSBSaWVzZ28NCi0gTGEgc2VsZWNjacOzbiBlbnRyZSBhY2Npb25lcyB5IGJvbm9zIHB1ZWRlIGRlcGVuZGVyIGRlIGxhIHRvbGVyYW5jaWEgYWwgcmllc2dvIGRlbCBpbnZlcnNvciwgY29uIGJvbm9zIHByZWZlcmlkb3MgcGFyYSBlc3RhYmlsaWRhZCB5IGFjY2lvbmVzIHBhcmEgYXF1ZWxsb3MgcXVlIGJ1c2NhbiBtYXlvcmVzIHJldG9ybm9zIGFzdW1pZW5kbyBtw6FzIHJpZXNnby4NCg0KIyMjIyBQbGFuaWZpY2FjacOzbiBhIExhcmdvIFBsYXpvDQotIExhcyB0ZW5kZW5jaWFzIGEgbGFyZ28gcGxhem8gc29uIGNydWNpYWxlcyBwYXJhIGludmVyc29yZXMgYSBsYXJnbyBwbGF6bywgbcOhcyBhbGzDoSBkZSBsYXMgZmx1Y3R1YWNpb25lcyBhIGNvcnRvIHBsYXpvLg0KDQpMYSBjb21wcmVuc2nDs24gZGUgZXN0b3MgcHJpbmNpcGlvcyBlcyBlc2VuY2lhbCBwYXJhIGxvcyBlamVjdXRpdm9zIGFsIHRvbWFyIGRlY2lzaW9uZXMgZXN0cmF0w6lnaWNhcyBkZSBpbnZlcnNpw7NuLg0KDQoNCmBgYHtyfQ0KIyAzLiBNYXRyaXogZGUgQ29ycmVsYWNpb25lcw0KY29ycmVsYXRpb25fbWF0cml4IDwtIGNvcihkYXRhWywtMV0pDQojIEVzdGFibGVjZXIgcGFyw6FtZXRyb3MgZ3LDoWZpY29zIHBhcmEgcmVkdWNpciBlbCB0YW1hw7FvIGRlbCB0w610dWxvIHkgbGFzIGV0aXF1ZXRhcw0KcGFyKG9tYSA9IGMoNSwgNywgMSwgMSkpICMgQWp1c3RhIGxvcyBtw6FyZ2VuZXMgZXh0ZXJpb3JlcyBzaSBlcyBuZWNlc2FyaW8NCnBhcihtZ3AgPSBjKDIsIDEsIDApKSAgICAjIEFqdXN0YSBsYSBsw61uZWEgZW4gbGEgcXVlIHNlIGRpYnVqYW4gbGFzIGV0aXF1ZXRhcyBkZWwgZWplIChlamUsIGV0aXF1ZXRhLCB0w610dWxvKQ0KcGFyKGNleC5tYWluID0gMC43KSAgICAgICAjIFJlZHVjZSBlbCB0YW1hw7FvIGRlbCB0w610dWxvDQpwYXIoY2V4LmxhYiA9IDAuNykgICAgICAgICMgUmVkdWNlIGVsIHRhbWHDsW8gZGUgbGFzIGV0aXF1ZXRhcyBkZSBsb3MgZWplcw0KDQojIEdlbmVyYSBlbCBncsOhZmljbyBkZSBsYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBjb24gdGFtYcOxb3MgZGUgdGV4dG8gcmVkdWNpZG9zDQpjb3JycGxvdChjb3JyZWxhdGlvbl9tYXRyaXgsIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLA0KICAgICAgICAgdGwuY29sID0gImJsYWNrIiwgdGwuc3J0ID0gNDUsIHRsLmNleCA9IDAuNywgY2wuY2V4ID0gMC43LCAjIEFqdXN0YSBlbCB0YW1hw7FvIGRlIGxhcyBldGlxdWV0YXMgeSBsYSBsZXllbmRhDQogICAgICAgICB0aXRsZSA9ICJNYXRyaXogZGUgQ29ycmVsYWNpb25lcyIpDQoNCiMgUmVzdGF1cmEgbGEgY29uZmlndXJhY2nDs24gZ3LDoWZpY2EgcHJlZGV0ZXJtaW5hZGEgZGVzcHXDqXMgZGVsIGdyw6FmaWNvDQpwYXIoY2V4Lm1haW4gPSAxLCBjZXgubGFiID0gMSwgb21hID0gYygwLCAwLCAwLCAwKSwgbWdwID0gYygzLCAxLCAwKSkNCmBgYA0KIyMjIEV4cGxpY2FjacOzbiBkZSBsYSBNYXRyaXogZGUgQ29ycmVsYWNpb25lcw0KDQpMYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBlcyB1bmEgaGVycmFtaWVudGEgcXVlIG5vcyBtdWVzdHJhIGPDs21vIGRpZmVyZW50ZXMgdGlwb3MgZGUgaW52ZXJzaW9uZXMgc2UgbXVldmVuIGVuIHJlbGFjacOzbiBlbnRyZSBzw60uIEVuIHVuIHBvcnRhZm9saW8sIHRlbmVyIGFjdGl2b3MgcXVlIG5vIHNlIG11ZXZlbiBlbiBsYSBtaXNtYSBkaXJlY2Npw7NuIHB1ZWRlIGF5dWRhciBhIHJlZHVjaXIgZWwgcmllc2dvLg0KDQojIyMjIEludGVycHJldGFjacOzbiBkZSBsYSBNYXRyaXoNCg0KLSBDYWRhIGN1YWRyYWRvIGVuIGxhIG1hdHJpeiByZXByZXNlbnRhIGxhIHJlbGFjacOzbiBlbnRyZSBkb3MgdGlwb3MgZGUgYWN0aXZvcy4NCi0gTG9zIGNvbG9yZXMgbcOhcyBvc2N1cm9zIHkgdmFsb3JlcyBjZXJjYW5vcyBhIDEgbyAtMSBpbmRpY2FuIHVuYSByZWxhY2nDs24gZnVlcnRlLg0KLSBWYWxvcmVzIGNlcmNhbm9zIGEgMCBpbmRpY2FuIHVuYSByZWxhY2nDs24gZMOpYmlsIG8gaW5leGlzdGVudGUuDQoNCiMjIyMgRGV0YWxsZXMgZGUgbGEgTWF0cml6DQoNCi0gKipBY2Npb25lcyB2cy4gQm9ub3M6KiogTGEgY29ycmVsYWNpw7NuIGVudHJlIGFjY2lvbmVzIHkgYm9ub3MgZXMgZ2VuZXJhbG1lbnRlIGJhamEsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBubyBzZSBtdWV2ZW4gZW4gcGVyZmVjdGEgYXJtb27DrWEuIEVzdG8gZXMgYmVuZWZpY2lvc28gcGFyYSBsYSBkaXZlcnNpZmljYWNpw7NuIGRlbCBwb3J0YWZvbGlvLCB5YSBxdWUgbGEgbWV6Y2xhIGRlIGFjdGl2b3MgcHVlZGUgcmVkdWNpciBlbCByaWVzZ28gZ2VuZXJhbC4NCg0KLSAqKkFjY2lvbmVzIHZzLiBNZXJjYWRvIE1vbmV0YXJpbzoqKiBMYSBjb3JyZWxhY2nDs24gZW50cmUgYWNjaW9uZXMgeSBlbCBtZXJjYWRvIG1vbmV0YXJpbyB0YW1iacOpbiB0aWVuZGUgYSBzZXIgYmFqYSwgcmVmb3J6YW5kbyBlbCBiZW5lZmljaW8gZGUgZGl2ZXJzaWZpY2FyIGFsIGluY2x1aXIgZGlmZXJlbnRlcyB0aXBvcyBkZSBhY3Rpdm9zLg0KDQotICoqQm9ub3MgdnMuIE1lcmNhZG8gTW9uZXRhcmlvOioqIEVzdG9zIGRvcyBhY3Rpdm9zIHB1ZWRlbiBtb3N0cmFyIHVuYSBjb3JyZWxhY2nDs24gbcOhcyBmdWVydGUsIHlhIHF1ZSBhbWJvcyBzb24gY29uc2lkZXJhZG9zIGludmVyc2lvbmVzIG3DoXMgc2VndXJhcyBlbiBjb21wYXJhY2nDs24gY29uIGxhcyBhY2Npb25lcy4gU2luIGVtYmFyZ28sIHVuYSBjb3JyZWxhY2nDs24gbm8gcGVyZmVjdGFtZW50ZSBwb3NpdGl2YSBzaWd1ZSBvZnJlY2llbmRvIGJlbmVmaWNpb3MgZGUgZGl2ZXJzaWZpY2FjacOzbi4NCg0KIyMjIyBSZWxldmFuY2lhIHBhcmEgbGEgRXN0cmF0ZWdpYSBkZSBJbnZlcnNpw7NuDQoNClBhcmEgdW4gZWplY3V0aXZvLCBlbnRlbmRlciBlc3RhIG1hdHJpeiBlcyBjcnVjaWFsIHBhcmEgbGEgZGl2ZXJzaWZpY2FjacOzbiBkZWwgcG9ydGFmb2xpbzoNCg0KLSAqKkRpdmVyc2lmaWNhY2nDs246KiogQnVzY2Ftb3MgY29tYmluYXIgYWN0aXZvcyBxdWUgbm8gc2UgbXVldmVuIGV4YWN0YW1lbnRlIGlndWFsIHBhcmEgcHJvdGVnZXIgZWwgcG9ydGFmb2xpbyBjb250cmEgbW92aW1pZW50b3MgaW5lc3BlcmFkb3MgZGVsIG1lcmNhZG8uDQotICoqQmFsYW5jZSBkZSBSaWVzZ286KiogU2kgdG9kb3MgbnVlc3Ryb3MgYWN0aXZvcyBzZSBtdWV2ZW4ganVudG9zLCB1biBtYWwgZXZlbnRvIHB1ZWRlIGFmZWN0YXIgYSB0b2RvIGVsIHBvcnRhZm9saW8uIERpdmVyc2lmaWNhciBheXVkYSBhIG1pdGlnYXIgZXN0ZSByaWVzZ28uDQotICoqUGxhbmlmaWNhY2nDs24gRXN0cmF0w6lnaWNhOioqIENvbXByZW5kZXIgZXN0YXMgcmVsYWNpb25lcyBub3MgYXl1ZGEgYSBwbGFuaWZpY2FyIHBhcmEgZGlmZXJlbnRlcyBlc2NlbmFyaW9zIGVjb27Ds21pY29zIHkgYXNlZ3VyYXIgcXVlIGVsIHBvcnRhZm9saW8gZXN0w6kgcHJlcGFyYWRvIHBhcmEgZW5mcmVudGFyIGxhIHZvbGF0aWxpZGFkIGRlbCBtZXJjYWRvLg0KDQpSZWNvcmRhciBxdWUgZWwgb2JqZXRpdm8gZXMgbWFudGVuZXIgdW4gZXF1aWxpYnJpbyBxdWUgYWxpbmVlIGNvbiBsb3Mgb2JqZXRpdm9zIGRlIGludmVyc2nDs24geSBlbCBhcGV0aXRvIGRlIHJpZXNnbyBkZSBsYSBjb21wYcOxw61hLg0KDQpgYGB7cn0NCiMgNC4gUG9ydGFmb2xpbyBPcHRpbWl6YWRvDQpwcmludChlZmZpY2llbnRfcG9ydGZvbGlvKQ0KDQojIDUuIEdyw6FmaWNvIGRlbCBQb3J0YWZvbGlvIE9wdGltaXphZG8NCm9wdGltaXplZF93ZWlnaHRzIDwtIGRhdGEuZnJhbWUoDQogIGFzc2V0ID0gY29sbmFtZXMocmV0dXJucyksDQogIHdlaWdodHMgPSBlZmZpY2llbnRfcG9ydGZvbGlvDQopDQoNCmdncGxvdChvcHRpbWl6ZWRfd2VpZ2h0cywgYWVzKHggPSBhc3NldCwgeSA9IHdlaWdodHMsIGZpbGwgPSBhc3NldCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlbCBQb3J0YWZvbGlvIE9wdGltaXphZG8iLCB4ID0gIlRpcG8gZGUgQWN0aXZvIiwgeSA9ICJQZXNvIikNCmBgYA0KIyMjIyBFeHBsaWNhY2nDs24gZGUgbGEgRGlzdHJpYnVjacOzbiBkZWwgUG9ydGFmb2xpbyBPcHRpbWl6YWRvDQoNCkVsIGdyw6FmaWNvIG11ZXN0cmEgbGEgZGlzdHJpYnVjacOzbiBkZSB1biBwb3J0YWZvbGlvIGRlIGludmVyc2nDs24gb3B0aW1pemFkbywgaWx1c3RyYW5kbyBjw7NtbyBzZSBoYSBhc2lnbmFkbyBlbCBjYXBpdGFsIGVudHJlIGRpZmVyZW50ZXMgdGlwb3MgZGUgYWN0aXZvcy4NCg0KLSAqKkJvbm9zIChgYm9uZHNgKToqKiBMYSBiYXJyYSByb2phIGluZGljYSBsYSBwcm9wb3JjacOzbiBkZWwgcG9ydGFmb2xpbyBhc2lnbmFkYSBhIGJvbm9zLCBxdWUgZXMgbGlnZXJhbWVudGUgbcOhcyBkZWwgMjAlLiBMb3MgYm9ub3Mgc3VlbGVuIGNvbnNpZGVyYXJzZSBjb21vIGludmVyc2lvbmVzIG3DoXMgc2VndXJhcyBlbiBjb21wYXJhY2nDs24gY29uIGxhcyBhY2Npb25lcy4NCg0KLSAqKk1lcmNhZG8gTW9uZXRhcmlvIChgbW1gKToqKiBMYSBiYXJyYSB2ZXJkZSBtdWVzdHJhIGxhIHByb3BvcmNpw7NuIGFzaWduYWRhIGFsIG1lcmNhZG8gbW9uZXRhcmlvLCBxdWUgcmVwcmVzZW50YSBsYSBtYXlvciBwYXJ0ZSBkZWwgcG9ydGFmb2xpbyBjb24gYXByb3hpbWFkYW1lbnRlIHVuIDM1JS4gSW52ZXJzaW9uZXMgZW4gZWwgbWVyY2FkbyBtb25ldGFyaW8gc3VlbGVuIHNlciBtdXkgbMOtcXVpZGFzIHkgZGUgYmFqbyByaWVzZ28uDQoNCi0gKipBY2Npb25lcyAoYHN0b2Nrc2ApOioqIExhIGJhcnJhIGF6dWwgcmVmbGVqYSBsYSBpbnZlcnNpw7NuIGVuIGFjY2lvbmVzLCBjb24gdW4gcGVzbyBzaW1pbGFyIGFsIGRlbCBtZXJjYWRvIG1vbmV0YXJpby4gTGFzIGFjY2lvbmVzIHNvbiBnZW5lcmFsbWVudGUgbcOhcyB2b2zDoXRpbGVzIHkgcHVlZGVuIG9mcmVjZXIgdW4gbWF5b3IgcG90ZW5jaWFsIGRlIGNyZWNpbWllbnRvIGNvbXBhcmFkbyBjb24gYm9ub3MgeSBtZXJjYWRvIG1vbmV0YXJpby4NCg0KRXN0ZSBwb3J0YWZvbGlvIHBhcmVjZSBlc3RhciBkaXZlcnNpZmljYWRvLCBkaXN0cmlidXllbmRvIGVsIHJpZXNnbyB5IHBvdGVuY2lhbG1lbnRlIGVxdWlsaWJyYW5kbyBlbCBjcmVjaW1pZW50byB5IGxhIHNlZ3VyaWRhZC4NCg0KDQoNCiMjIFJlZmVyZW5jaWFzIGJpYmxpb2dyw6FmaWNhczoNCigxKSAgQXJyaWFnYSBOYXZhcnJldGUsIFIuLCBDYXN0cm8gT2xpdmFyZXMsIEouIEUuLCAmIFNvc2EgQ2FzdHJvLCBNLiAoMjAxOSkuIEFuw6FsaXNpcyBkZSBlc3RyYXRlZ2lhcyBkZSBpbnZlcnNpw7NuIGRlIGRpdmVyc2lmaWNhY2nDs24gaW50ZXJuYWNpb25hbDogcG9ydGFmb2xpb3MgdHJhZGljaW9uYWxlcyB2cyBFVEZTLiBBbsOhbGlzaXMgZWNvbsOzbWljbywgMzQoODcpLCA0MS03MC4gRXB1YiAxMyBkZSBub3ZpZW1icmUgZGUgMjAyMC4gUmVjdXBlcmFkbyBlbCAxOCBkZSBkaWNpZW1icmUgZGUgMjAyMywgZGUgaHR0cDovL3d3dy5zY2llbG8ub3JnLm14L3NjaWVsby5waHA/c2NyaXB0PXNjaV9hcnR0ZXh0JnBpZD1TMjQ0OC02NjU1MjAxOTAwMDMwMDA0MSZsbmc9ZXMmdGxuZz1lcy4NCg0KKDIpICBCdXJpdGljw6EtTWVqw61hLCBKLiBBLiAoMjAyMSkuIE1vZGVsbyBCbGFjay1MaXR0ZXJtYW4gY29uIFN1cHBvcnQgVmVjdG9yIFJlZ3Jlc3Npb246IHVuYSBhbHRlcm5hdGl2YSBwYXJhIGxvcyBmb25kb3MgZGUgcGVuc2lvbmVzIG9ibGlnYXRvcmlvcyBjb2xvbWJpYW5vcy4gT0RFT04sICgxOCksIDIwNeKAkzI1Ny4gaHR0cHM6Ly9kb2kub3JnLzEwLjE4NjAxLzE3OTQxMTEzLm4xOC4wNi4NCg0KKDMpICBBcmFnw7NuIFVycmVnbywgRC4gKDIwMjIpLiBQYXJpZGFkIGRlIHJpZXNnbyBqZXLDoXJxdWljbzogYXByb3hpbWFjacOzbiBhbCBtw6l0b2RvIHkgYXBsaWNhY2nDs24gcGFyYSBlbCBtZXJjYWRvIGVzdGFkb3VuaWRlbnNlLiBPREVPTiwgKDIxKSwgMTA14oCTMTI0LiBodHRwczovL2RvaS5vcmcvMTAuMTg2MDEvMTc5NDExMTMubjIxLjA2Lg0KDQooNCkgIE1hdGVyaWFsIEN1cnNvIDEuIChzLiBmLikuIFByw6FjdGljYSA2OiBBbsOhbGlzaXMgeSBzZWxlY2Npw7NuIGRlIHBvcnRhZm9saW9zLiBSZWN1cGVyYWRvIGRlIGh0dHBzOi8vbmF0YWxpYXByaW5zLmdpdGh1Yi5pby9jdXJzb3MvU2VsZWNjaSVDMyVCM24lMjBkZSUyMENhcnRlcmFzL1NlbGVjY2lvbiUyMGRlJTIwcG9ydGFmb2xpb3MvQW4lQzMlQTFsaXNpcyUyMHklMjBTZWxlY2NpJUMzJUIzbiUyMGRlJTIwUG9ydGFmb2xpb3MuaHRtbA0KDQoNCg0K