Preparado para

phd Pablo López

Introducción

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.

Análisis de Portafolios en R: Funciones Clave(4)

En este documento, exploramos cuatro funciones importantes para el análisis de portafolios en R, incluyendo DEoptim para la optimización basada en la teoría de Markowitz.

Funciones de Análisis de Portafolios

A continuación, presentamos una tabla que resume las características de cuatro funciones clave:

Función Paquete Descripción Características
portfolio.optim tseries Optimiza portafolios basado en el retorno y riesgo. Utiliza la media-varianza para la optimización.
optimize.portfolio PortfolioAnalytics Proporciona un marco flexible para la construcción de portafolios. Admite restricciones personalizadas y objetivos múltiples.
Return.portfolio PerformanceAnalytics Calcula el retorno total de un portafolio. Útil para el análisis posterior a la optimización.
DEoptim DEoptim Realiza la optimización global basada en el algoritmo de evolución diferencial. Eficaz para problemas complejos y no lineales.

Justificación para la Elección de DEoptim

DEoptim es una excelente elección para la optimización de portafolios basada en la teoría de Markowitz por varias razones:

  1. Flexibilidad en la Optimización: DEoptim es eficaz para manejar problemas de optimización complejos y no lineales, lo que es común en la optimización de portafolios.
  2. Capacidad de Evitar Mínimos Locales: A diferencia de los métodos de optimización tradicionales que pueden quedar atrapados en mínimos locales, DEoptim utiliza un algoritmo de evolución diferencial que explora de manera más efectiva el espacio de soluciones.
  3. Adaptabilidad: Puede manejar diversas restricciones y modelos, lo que es crucial cuando se trabaja con los diferentes escenarios y preferencias de inversión que contempla la teoría de Markowitz.

En resumen, DEoptim proporciona un enfoque robusto y flexible para encontrar la frontera eficiente en la optimización de portafolios, alineándose bien con los principios de Markowitz sobre diversificación y balance entre riesgo y retorno.

A continuación, se procede con el ejercicio práctico.

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)

Resumenes y gráficos

library(ggplot2)
library(dplyr)
library(tidyr)
library(corrplot)

# 1. Resumen de los Datos
print(summary(data))
      year                stocks            bonds              mm        
 Min.   :1960-12-15   Min.   :-25.340   Min.   :-2.670   Min.   : 1.680  
 1st Qu.:1971-09-14   1st Qu.: -3.005   1st Qu.: 6.130   1st Qu.: 4.662  
 Median :1982-06-15   Median : 11.235   Median : 9.525   Median : 7.525  
 Mean   :1982-06-15   Mean   :  9.303   Mean   : 9.398   Mean   : 6.775  
 3rd Qu.:1993-03-16   3rd Qu.: 17.297   3rd Qu.:13.505   3rd Qu.: 8.405  
 Max.   :2003-12-15   Max.   : 39.140   Max.   :17.460   Max.   :14.950  
# 2. Gráfico de Series Temporales de los Retornos
data_long <- data %>% 
  pivot_longer(-year, names_to = "asset", values_to = "returns")

ggplot(data_long, aes(x = year, y = returns, color = asset)) +
  geom_line() +
  theme_minimal() +
  labs(title = "Series Temporales de Retornos", x = "Año", y = "Retorno", color = "Activo")

Análisis de Series Temporales de Retornos de Inversiones

Este documento presenta un análisis visual de los retornos de diferentes tipos de inversiones a lo largo del tiempo.

Descripción del Gráfico de Series Temporales

El gráfico ilustra cómo han fluctuado los retornos de acciones, bonos y el mercado monetario desde 1960 hasta principios del 2000.

Componentes del Gráfico

  • Líneas del Gráfico:
    • La línea azul representa las acciones (stocks).
    • La línea roja representa los bonos (bonds).
    • La línea verde representa el mercado monetario (mm).
  • Eje Vertical - Retorno:
    • Indica el retorno de las inversiones en porcentaje.
    • Un valor más alto significa un mayor retorno en ese año.
  • Eje Horizontal - Año:
    • Muestra la línea de tiempo desde 1960 hasta el 2000.

Interpretación de los Datos

Volatilidad
  • La volatilidad de las acciones se refleja en la amplitud de los picos (azules), lo que indica potencial tanto para altos retornos como para caídas significativas.
Estabilidad
  • Los bonos, representados por la línea roja, muestran menos volatilidad, sugiriendo que son menos riesgosos y ofrecen retornos más predecibles.
Conservadurismo
  • La línea verde del mercado monetario muestra la mayor estabilidad entre los tres, indicando una opción de inversión conservadora con menores retornos pero también menor riesgo.

Estrategias de Inversión

Diversificación
  • Combinar estos tipos de activos puede balancear el riesgo y el retorno, ayudando a mitigar los efectos de un mal año para un activo específico.
Perfil de Riesgo
  • La selección entre acciones y bonos puede depender de la tolerancia al riesgo del inversor, con bonos preferidos para estabilidad y acciones para aquellos que buscan mayores retornos asumiendo más riesgo.

Planificación a Largo Plazo

  • Las tendencias a largo plazo son cruciales para inversores a largo plazo, más allá de las fluctuaciones a corto plazo.

La comprensión de estos principios es esencial para los ejecutivos al tomar decisiones estratégicas de inversión.

# 3. Matriz de Correlaciones
correlation_matrix <- cor(data[,-1])
# Establecer parámetros gráficos para reducir el tamaño del título y las etiquetas
par(oma = c(5, 7, 1, 1)) # Ajusta los márgenes exteriores si es necesario
par(mgp = c(2, 1, 0))    # Ajusta la línea en la que se dibujan las etiquetas del eje (eje, etiqueta, título)
par(cex.main = 0.7)       # Reduce el tamaño del título
par(cex.lab = 0.7)        # Reduce el tamaño de las etiquetas de los ejes

# Genera el gráfico de la matriz de correlaciones con tamaños de texto reducidos
corrplot(correlation_matrix, method = "color", type = "upper",
         tl.col = "black", tl.srt = 45, tl.cex = 0.7, cl.cex = 0.7, # Ajusta el tamaño de las etiquetas y la leyenda
         title = "Matriz de Correlaciones")

# Restaura la configuración gráfica predeterminada después del gráfico
par(cex.main = 1, cex.lab = 1, oma = c(0, 0, 0, 0), mgp = c(3, 1, 0))

Explicación de la Matriz de Correlaciones

La matriz de correlaciones es una herramienta que nos muestra cómo diferentes tipos de inversiones se mueven en relación entre sí. En un portafolio, tener activos que no se mueven en la misma dirección puede ayudar a reducir el riesgo.

Interpretación de la Matriz

  • Cada cuadrado en la matriz representa la relación entre dos tipos de activos.
  • Los colores más oscuros y valores cercanos a 1 o -1 indican una relación fuerte.
  • Valores cercanos a 0 indican una relación débil o inexistente.

Detalles de la Matriz

  • Acciones vs. Bonos: La correlación entre acciones y bonos es generalmente baja, lo que sugiere que no se mueven en perfecta armonía. Esto es beneficioso para la diversificación del portafolio, ya que la mezcla de activos puede reducir el riesgo general.

  • Acciones vs. Mercado Monetario: La correlación entre acciones y el mercado monetario también tiende a ser baja, reforzando el beneficio de diversificar al incluir diferentes tipos de activos.

  • Bonos vs. Mercado Monetario: Estos dos activos pueden mostrar una correlación más fuerte, ya que ambos son considerados inversiones más seguras en comparación con las acciones. Sin embargo, una correlación no perfectamente positiva sigue ofreciendo beneficios de diversificación.

Relevancia para la Estrategia de Inversión

Para un ejecutivo, entender esta matriz es crucial para la diversificación del portafolio:

  • Diversificación: Buscamos combinar activos que no se mueven exactamente igual para proteger el portafolio contra movimientos inesperados del mercado.
  • Balance de Riesgo: Si todos nuestros activos se mueven juntos, un mal evento puede afectar a todo el portafolio. Diversificar ayuda a mitigar este riesgo.
  • Planificación Estratégica: Comprender estas relaciones nos ayuda a planificar para diferentes escenarios económicos y asegurar que el portafolio esté preparado para enfrentar la volatilidad del mercado.

Recordar que el objetivo es mantener un equilibrio que alinee con los objetivos de inversión y el apetito de riesgo de la compañía.

# 4. Portafolio Optimizado
print(efficient_portfolio)
stocks  bonds     mm 
 0.274  0.256  0.470 
# 5. Gráfico del Portafolio Optimizado
optimized_weights <- data.frame(
  asset = colnames(returns),
  weights = efficient_portfolio
)

ggplot(optimized_weights, aes(x = asset, y = weights, fill = asset)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  labs(title = "Distribución del Portafolio Optimizado", x = "Tipo de Activo", y = "Peso")

Explicación de la Distribución del Portafolio Optimizado

El gráfico muestra la distribución de un portafolio de inversión optimizado, ilustrando cómo se ha asignado el capital entre diferentes tipos de activos.

  • Bonos (bonds): La barra roja indica la proporción del portafolio asignada a bonos, que es ligeramente más del 20%. Los bonos suelen considerarse como inversiones más seguras en comparación con las acciones.

  • Mercado Monetario (mm): La barra verde muestra la proporción asignada al mercado monetario, que representa la mayor parte del portafolio con aproximadamente un 35%. Inversiones en el mercado monetario suelen ser muy líquidas y de bajo riesgo.

  • Acciones (stocks): La barra azul refleja la inversión en acciones, con un peso similar al del mercado monetario. Las acciones son generalmente más volátiles y pueden ofrecer un mayor potencial de crecimiento comparado con bonos y mercado monetario.

Este portafolio parece estar diversificado, distribuyendo el riesgo y potencialmente equilibrando el crecimiento y la seguridad.

Referencias bibliográficas:

  1. Arriaga Navarrete, R., Castro Olivares, J. E., & Sosa Castro, M. (2019). Análisis de estrategias de inversión de diversificación internacional: portafolios tradicionales vs ETFS. Análisis económico, 34(87), 41-70. Epub 13 de noviembre de 2020. Recuperado el 18 de diciembre de 2023, de http://www.scielo.org.mx/scielo.php?script=sci_arttext&pid=S2448-66552019000300041&lng=es&tlng=es.

  2. Buriticá-Mejía, J. A. (2021). Modelo Black-Litterman con Support Vector Regression: una alternativa para los fondos de pensiones obligatorios colombianos. ODEON, (18), 205–257. https://doi.org/10.18601/17941113.n18.06.

  3. Aragón Urrego, D. (2022). Paridad de riesgo jerárquico: aproximación al método y aplicación para el mercado estadounidense. ODEON, (21), 105–124. https://doi.org/10.18601/17941113.n21.06.

  4. Material Curso 1. (s. f.). Práctica 6: Análisis y selección de portafolios. Recuperado de https://nataliaprins.github.io/cursos/Selecci%C3%B3n%20de%20Carteras/Seleccion%20de%20portafolios/An%C3%A1lisis%20y%20Selecci%C3%B3n%20de%20Portafolios.html

LS0tDQp0aXRsZTogIlByb3llY3RvIEZpbmFsIFTDs3BpY29zIFNlbGVjdG9zIGRlIEZpbmFuemFzIg0KYXV0aG9yOiAiTUEgRGFuaWVsIEzDs3BleiINCmRhdGU6ICJaYXBvcGFuLCBEaWNpZW1icmUgMjAyMyAtIMOabHRpbWEgYWN0dWFsaXphY2nDs246IDE4LjEyLjIwMjMiICANCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIFByZXBhcmFkbyBwYXJhDQpwaGQgUGFibG8gTMOzcGV6DQoNCiMjIEludHJvZHVjY2nDs24NCiMjIENvbXBhcmFjacOzbiBkZSBNw6l0b2RvcyBkZSBPcHRpbWl6YWNpw7NuIGRlIFBvcnRhZm9saW9zDQoNCkVuIGVzdGUgZG9jdW1lbnRvLCBjb21wYXJhbW9zIHRyZXMgbcOpdG9kb3MgZGUgb3B0aW1pemFjacOzbiBkZSBwb3J0YWZvbGlvczogZWwgTW9kZWxvIGRlIE1hcmtvd2l0eiwgZWwgRW5mb3F1ZSBkZSBCbGFjay1MaXR0ZXJtYW4geSBlbCBNb2RlbG8gZGUgT3B0aW1pemFjacOzbiBkZSBQYXJpZGFkIGRlIFJpZXNnby4NCg0KIyMjIE1vZGVsbyBkZSBNYXJrb3dpdHogKFRlb3LDrWEgTW9kZXJuYSBkZSBQb3J0YWZvbGlvcykoMSkNCg0KIyMjIyBWZW50YWphcw0KDQotICoqRnVuZGFtZW50YWNpw7NuIFRlw7NyaWNhOioqIE1hcmNvIHRlw7NyaWNvIHPDs2xpZG8gYmFzYWRvIGVuIGxhIGRpdmVyc2lmaWNhY2nDs24geSBsYSByZWxhY2nDs24gcmllc2dvLXJldG9ybm8uDQotICoqRnJvbnRlcmEgRWZpY2llbnRlOioqIElkZW50aWZpY2FjacOzbiBkZSBsYSBjb21iaW5hY2nDs24gw7NwdGltYSBkZSBhY3Rpdm9zLg0KDQojIyMjIERlc3ZlbnRhamFzDQoNCi0gKipTZW5zaWJpbGlkYWQgYSBsYXMgRW50cmFkYXM6KiogQWx0YSBzZW5zaWJpbGlkYWQgYSBlc3RpbWFjaW9uZXMgZGUgcmV0b3JubyB5IHJpZXNnby4NCi0gKipSZXF1aWVyZSBHcmFuIENhbnRpZGFkIGRlIERhdG9zOioqIE5lY2VzaWRhZCBkZSBkYXRvcyBoaXN0w7NyaWNvcyBleHRlbnNvcy4NCg0KIyMjIEVuZm9xdWUgZGUgQmxhY2stTGl0dGVybWFuICgyKQ0KDQojIyMjIFZlbnRhamFzDQoNCi0gKipJbmNvcnBvcmFjacOzbiBkZSBWaXN0YXMgZGVsIEludmVyc2lvbmlzdGE6KiogSW50ZWdyYWNpw7NuIGRlIGV4cGVjdGF0aXZhcyBlc3BlY8OtZmljYXMgZGVsIGludmVyc2lvbmlzdGEuDQotICoqRXN0YWJpbGlkYWQgZW4gbGFzIEVzdGltYWNpb25lczoqKiBSZWR1Y2UgbGEgc2Vuc2liaWxpZGFkIGEgbGFzIGVzdGltYWNpb25lcyBkZSBlbnRyYWRhLg0KDQojIyMjIERlc3ZlbnRhamFzDQoNCi0gKipDb21wbGVqaWRhZDoqKiBNYXlvciBjb21wbGVqaWRhZCBlbiBzdSBpbXBsZW1lbnRhY2nDs24uDQotICoqRGVwZW5kZW5jaWEgZGUgdW4gTW9kZWxvIGRlIE1lcmNhZG86KiogTmVjZXNpZGFkIGRlIHVuIG1vZGVsbyBkZSBtZXJjYWRvIGRlIHJlZmVyZW5jaWEuDQoNCiMjIyBNb2RlbG8gZGUgT3B0aW1pemFjacOzbiBkZSBQYXJpZGFkIGRlIFJpZXNnbyAoMykNCg0KIyMjIyBWZW50YWphcw0KDQotICoqRGl2ZXJzaWZpY2FjacOzbiBkZSBSaWVzZ286KiogRW5mb3F1ZSBlbiBpZ3VhbGFyIGVsIHJpZXNnbyBhcG9ydGFkbyBwb3IgY2FkYSBhY3Rpdm8uDQotICoqUmVzaWxpZW5jaWEgZW4gTWVyY2Fkb3MgVm9sw6F0aWxlczoqKiBNZWpvciBkZXNlbXBlw7FvIGVuIG1lcmNhZG9zIHZvbMOhdGlsZXMuDQoNCiMjIyMgRGVzdmVudGFqYXMNCg0KLSAqKlB1ZWRlIElnbm9yYXIgbGEgUmVsYWNpw7NuIFJpZXNnby1SZXRvcm5vOioqIE5vIHNlIGVuZm9jYSBkaXJlY3RhbWVudGUgZW4gbGEgbWF4aW1pemFjacOzbiBkZWwgcmV0b3Juby4NCi0gKipTdWJlc3RpbWFjacOzbiBkZSBPcG9ydHVuaWRhZGVzIGRlIFJlbmRpbWllbnRvOioqIFBvc2libGUgc3ViZXN0aW1hY2nDs24gZGUgYWN0aXZvcyBjb24gbWF5b3IgcG90ZW5jaWFsLg0KDQojIyMgSnVzdGlmaWNhY2nDs24gcGFyYSB1c2FyIGVsIE1vZGVsbyBkZSBNYXJrb3dpdHoNCg0KRWwgbW9kZWxvIGRlIE1hcmtvd2l0eiBzaWd1ZSBzaWVuZG8gYW1wbGlhbWVudGUgdXRpbGl6YWRvIHBvciBzdSBlcXVpbGlicmlvIGVudHJlIHJpZXNnbyB5IHJldG9ybm8sIHN1IGJhc2UgaW50dWl0aXZhIHkgZnVuZGFtZW50YWRhLCB5IHN1IGFkYXB0YWJpbGlkYWQgYSBkaXZlcnNvcyBwZXJmaWxlcyBkZSBpbnZlcnNpw7NuLg0KDQoNCiMjIyBQYXNvcyBkZWwgQW7DoWxpc2lzDQoNCioqMS4gQ2FyZ2FyIGxvcyBEYXRvcyBIaXN0w7NyaWNvcyoqDQpFc3RlIHBhc28gaW1wbGljYSByZWNvcGlsYXIgZGF0b3MgaGlzdMOzcmljb3MgZGUgbG9zIGFjdGl2b3MgcXVlIHNlIGVzdMOhbiBjb25zaWRlcmFuZG8gcGFyYSBsYSBpbnZlcnNpw7NuLCBjb21vIGFjY2lvbmVzLCBib25vcyBvIGZvbmRvcy4gRXN0b3MgZGF0b3Mgc3VlbGVuIGluY2x1aXIgcHJlY2lvcyBkZSBjaWVycmUgZGlhcmlvcywgcmVuZGltaWVudG9zLCB5IGN1YWxxdWllciBvdHJhIGluZm9ybWFjacOzbiByZWxldmFudGUuIEVzdG9zIGRhdG9zIGhpc3TDs3JpY29zIHNvbiBlc2VuY2lhbGVzIHBhcmEgcmVhbGl6YXIgYW7DoWxpc2lzIHkgcHJveWVjY2lvbmVzIGZ1dHVyYXMuDQoNCioqMi4gQ8OhbGN1bG8gZGUgUmV0b3Jub3MgRXNwZXJhZG9zIHkgVmFyaWFuemEqKg0KQXF1w60gc2UgY2FsY3VsYW4gZG9zIGFzcGVjdG9zIGNyw610aWNvczogbG9zICoqcmV0b3Jub3MgZXNwZXJhZG9zKiosIHF1ZSBlcyBsYSBnYW5hbmNpYSBvIHDDqXJkaWRhIHF1ZSBzZSBlc3BlcmEgb2J0ZW5lciBkZSB1bmEgaW52ZXJzacOzbi4gU2UgY2FsY3VsYSBhIHBhcnRpciBkZWwgcHJvbWVkaW8gZGUgbG9zIHJlbmRpbWllbnRvcyBoaXN0w7NyaWNvcyBkZSB1biBhY3Rpdm87IHkgZWwgc2VndW5kbyBlcyBsYSAqKnZhcmlhbnphKiosIGxhIGN1YWwgbWlkZSBsYSBkaXNwZXJzacOzbiBkZSBsb3MgcmV0b3Jub3MgZGUgdW4gYWN0aXZvIGVuIHJlbGFjacOzbiBhIHN1IG1lZGlhLCBsbyBxdWUgYXl1ZGEgYSBlbnRlbmRlciBlbCByaWVzZ28gaW52b2x1Y3JhZG8uIFVuYSBtYXlvciB2YXJpYW56YSBpbmRpY2EgdW5hIG1heW9yIGluY2VydGlkdW1icmUgeSByaWVzZ28uDQoNCioqMy4gQ29uc3RydWNjacOzbiBkZSBQb3J0YWZvbGlvcyoqDQpFbiBlc3RlIHBhc28sIHNlIGNvbWJpbmFuIGRpZmVyZW50ZXMgYWN0aXZvcyBwYXJhIGZvcm1hciB1biBwb3J0YWZvbGlvLiBMYSBzZWxlY2Npw7NuIGRlIGFjdGl2b3MgeSBzdSBwcm9wb3JjacOzbiBlbiBlbCBwb3J0YWZvbGlvIGRlcGVuZGVyw6EgZGUgbG9zIG9iamV0aXZvcyBkZSBpbnZlcnNpw7NuLCBsYSB0b2xlcmFuY2lhIGFsIHJpZXNnbyB5IGVsIGhvcml6b250ZSB0ZW1wb3JhbCBkZWwgaW52ZXJzb3IuIEVsIG9iamV0aXZvIGVzIGNyZWFyIHVuIHBvcnRhZm9saW8gZXF1aWxpYnJhZG8gcXVlIG9wdGltaWNlIGxvcyByZXRvcm5vcyBtaWVudHJhcyBzZSBnZXN0aW9uYSBlbCByaWVzZ28uDQoNCioqNC4gQW7DoWxpc2lzIGRlIFBvcnRhZm9saW9zKioNCkFxdcOtIHNlIGV2YWzDumEgZWwgcmVuZGltaWVudG8gZGVsIHBvcnRhZm9saW8sIGFuYWxpemFuZG8gYXNwZWN0b3MgY29tbyBlbCByZXRvcm5vIHRvdGFsLCBlbCByaWVzZ28gKHZvbGF0aWxpZGFkKSwgeSBsYSBjb3JyZWxhY2nDs24gZW50cmUgbG9zIGFjdGl2b3MgZGVsIHBvcnRhZm9saW8uIEVzdGUgYW7DoWxpc2lzIGF5dWRhIGEgZW50ZW5kZXIgc2kgZWwgcG9ydGFmb2xpbyBlc3TDoSBhbGluZWFkbyBjb24gbG9zIG9iamV0aXZvcyB5IHByZWZlcmVuY2lhcyBkZSByaWVzZ28gZGVsIGludmVyc29yLg0KDQoqKjUuIElkZW50aWZpY2FjacOzbiBkZSBsYSBGcm9udGVyYSBFZmljaWVudGUqKg0KTGEgZnJvbnRlcmEgZWZpY2llbnRlIGVzIHVuIGNvbmNlcHRvIGNsYXZlIGVuIGxhIHRlb3LDrWEgZGUgTWFya293aXR6LiBSZXByZXNlbnRhIGVsIGNvbmp1bnRvIGRlIHBvcnRhZm9saW9zIHF1ZSBvZnJlY2VuIGVsIG3DoXhpbW8gcmV0b3JubyBlc3BlcmFkbyBwYXJhIHVuIG5pdmVsIGRlIHJpZXNnbyBkYWRvIG8gZWwgbcOtbmltbyByaWVzZ28gcGFyYSB1biBuaXZlbCBkZSByZXRvcm5vIGRhZG8uIEVuIGVzdGUgcGFzbywgc2UgaWRlbnRpZmljYW4gZXN0b3MgcG9ydGFmb2xpb3MgbWVkaWFudGUgdMOpY25pY2FzIGRlIG9wdGltaXphY2nDs24uDQoNCioqNi4gU2VsZWNjacOzbiBkZWwgUG9ydGFmb2xpbyBFZmljaWVudGUqKg0KRmluYWxtZW50ZSwgc2Ugc2VsZWNjaW9uYSBlbCBwb3J0YWZvbGlvIG3DoXMgYWRlY3VhZG8gZGUgZW50cmUgYXF1ZWxsb3MgZW4gbGEgZnJvbnRlcmEgZWZpY2llbnRlLiBFc3RhIHNlbGVjY2nDs24gc2UgYmFzYSBlbiBsYXMgcHJlZmVyZW5jaWFzIHBlcnNvbmFsZXMgZGVsIGludmVyc29yLCBzdSB0b2xlcmFuY2lhIGFsIHJpZXNnbywgeSBzdXMgb2JqZXRpdm9zIGRlIGludmVyc2nDs24uIEVsIHJlc3VsdGFkbyBlcyB1biBwb3J0YWZvbGlvIHF1ZSBidXNjYSBtYXhpbWl6YXIgbG9zIHJldG9ybm9zIGFqdXN0YWRvcyBhbCByaWVzZ28gc2Vnw7puIGxhcyBuZWNlc2lkYWRlcyBlc3BlY8OtZmljYXMgZGVsIGludmVyc29yLg0KDQojIyMgQ29uY2VwdG9zIENsYXZlDQpQYXJhIGVsIGVqZXJjaWNpbyBwcsOhY3RpY28gcXVlIHNlIGluY2x1eWUgZW4gZXN0ZSBkb2N1bWVudG8sIGVzIGltcG9ydGFudGUgdGVuZXIgZW4gY3VlbnRhIGxvcyBzaWd1aWVudGVzIGNvbmNlcHRvczoNCg0KKipSaWVzZ28geSBSZXRvcm5vOioqIFNlZ8O6biBNYXJrb3dpdHosIGVsIHJpZXNnbyBkZSB1biBwb3J0YWZvbGlvIHNlIG1pZGUgcG9yIGxhIHZhcmlhYmlsaWRhZCBkZSBzdXMgcmV0b3Jub3MsIHkgbG9zIGludmVyc29yZXMgYnVzY2FuIG1heGltaXphciBsb3MgcmV0b3Jub3MgbWluaW1pemFuZG8gZWwgcmllc2dvLg0KDQoqKkRpdmVyc2lmaWNhY2nDs246KiogTGEgZGl2ZXJzaWZpY2FjacOzbiBkZSBsYXMgaW52ZXJzaW9uZXMgZW4gZGlmZXJlbnRlcyBhY3Rpdm9zIHJlZHVjZSBlbCByaWVzZ28gZGVsIHBvcnRhZm9saW8sIHlhIHF1ZSBsb3MgbW92aW1pZW50b3MgZGUgcHJlY2lvIG5vIGVzdMOhbiBwZXJmZWN0YW1lbnRlIGNvcnJlbGFjaW9uYWRvcy4NCg0KKipGcm9udGVyYSBFZmljaWVudGU6KiogRXMgZWwgY29uanVudG8gZGUgcG9ydGFmb2xpb3MgcXVlIG9mcmVjZW4gZWwgbcOheGltbyByZXRvcm5vIHBhcmEgdW4gbml2ZWwgZGUgcmllc2dvIGRhZG8gbyBlbCBtw61uaW1vIHJpZXNnbyBwYXJhIHVuIG5pdmVsIGRlIHJldG9ybm8gZGFkby4NCg0KKipTZWxlY2Npw7NuIGRlIFBvcnRhZm9saW86KiogTG9zIGludmVyc29yZXMgc2VsZWNjaW9uYW4gcG9ydGFmb2xpb3Mgc29icmUgbGEgZnJvbnRlcmEgZWZpY2llbnRlIGJhc2Fkb3MgZW4gc3VzIHByZWZlcmVuY2lhcyBkZSByaWVzZ28geSByZXRvcm5vLg0KDQoqKlN0b2NrcyAoQWNjaW9uZXMpOioqDQpEZWZpbmljacOzbjoNCkxhcyBhY2Npb25lcyBzb24gaW5zdHJ1bWVudG9zIGZpbmFuY2llcm9zIHF1ZSByZXByZXNlbnRhbiB1bmEgcGFydGljaXBhY2nDs24gZGUgcHJvcGllZGFkIGVuIHVuYSBlbXByZXNhLiBBbCBjb21wcmFyIGFjY2lvbmVzLCBlbCBpbnZlcnNvciBzZSBjb252aWVydGUgZW4gYWNjaW9uaXN0YSB5LCBwb3IgdGFudG8sIGVuIHByb3BpZXRhcmlvIGRlIHVuYSBwYXJ0ZSBkZSBlc2EgZW1wcmVzYS4gRXN0byBsZSBkYSBkZXJlY2hvIGEgdW5hIHBhcnRlIGRlIGxhcyBnYW5hbmNpYXMgZGUgbGEgZW1wcmVzYSAoZGl2aWRlbmRvcykgeSwgZW4gYWxndW5vcyBjYXNvcywgYSB2b3RvIGVuIGxhcyBqdW50YXMgZGUgYWNjaW9uaXN0YXMuDQoNCkVqZW1wbG86DQpBbCBjb21wcmFyIGFjY2lvbmVzIGRlIGxhIGVtcHJlc2EgQXBwbGUgSW5jLiBzZSBvYnRpZW5lIHVuYSBwZXF1ZcOxYSBwYXJ0ZSBkZSBwcm9waWVkYWQgZGUgQXBwbGUuIFNpIGxhIGVtcHJlc2EgdGllbmUgw6l4aXRvIHkgc3VzIGdhbmFuY2lhcyBhdW1lbnRhbiwgZWwgdmFsb3IgZGUgbGFzIGFjY2lvbmVzIHB1ZWRlIHN1YmlyLCB5IHRhbWJpw6luIHNlIHBvZHLDrWEgcmVjaWJpciBkaXZpZGVuZG9zLg0KDQoqKkJvbmRzIChCb25vcyk6KioNCkRlZmluaWNpw7NuOg0KTG9zIGJvbm9zIHNvbiBpbnN0cnVtZW50b3MgZGUgZGV1ZGEgdXRpbGl6YWRvcyB0YW50byBwb3IgZW50aWRhZGVzIGd1YmVybmFtZW50YWxlcyBjb21vIHBvciBjb3Jwb3JhY2lvbmVzIHBhcmEgcmVjYXVkYXIgZm9uZG9zLiBDdWFuZG8gc2UgY29tcHJhIHVuIGJvbm8sIHNlIGVzdGEgcHJlc3RhbmRvIGRpbmVybyBhbCBlbWlzb3IgZGVsIGJvbm8gYSBjYW1iaW8gZGUgcGFnb3MgZGUgaW50ZXJlc2VzIHJlZ3VsYXJlcyBkdXJhbnRlIGxhIHZpZGEgZGVsIGJvbm8geSBlbCByZWVtYm9sc28gZGVsIHByaW5jaXBhbCAoZWwgbW9udG8gb3JpZ2luYWwgcHJlc3RhZG8pIGFsIHZlbmNpbWllbnRvIGRlbCBib25vLg0KDQpFamVtcGxvOg0KU2UgY29tcHJhbiB1biBib25vIGRlbCBnb2JpZXJubyBkZSBFc3RhZG9zIFVuaWRvcyBjb24gdW4gdmFsb3Igbm9taW5hbCBkZSAkMSwwMDAsIHVuYSB0YXNhIGRlIGludGVyw6lzIGFudWFsIGRlbCAyJSB5IHVuIHZlbmNpbWllbnRvIGRlIDEwIGHDsW9zLiBDYWRhIGHDsW8sIHNlIHJlY2liaXLDoSAkMjAgKDIlIGRlICQxLDAwMCkgeSwgYWwgZmluYWwgZGUgbG9zIDEwIGHDsW9zLCByZWNpYmlyw6FzIGRlIHZ1ZWx0YSB0dXMgJDEsMDAwLg0KDQoqKk1NIChNb25leSBNYXJrZXQgLyBNZXJjYWRvIGRlIERpbmVybyk6KioNCkRlZmluaWNpw7NuOg0KRWwgbWVyY2FkbyBkZSBkaW5lcm8gZXMgdW4gc2VnbWVudG8gZGVsIG1lcmNhZG8gZmluYW5jaWVybyBkb25kZSBzZSBuZWdvY2lhbiBpbnN0cnVtZW50b3MgZGUgZGV1ZGEgYSBjb3J0byBwbGF6bywgZ2VuZXJhbG1lbnRlIGNvbiB2ZW5jaW1pZW50b3MgZGUgbWVub3MgZGUgdW4gYcOxby4gTG9zIHByb2R1Y3RvcyBkZWwgbWVyY2FkbyBkZSBkaW5lcm8gc29uIGNvbm9jaWRvcyBwb3Igc3UgYmFqYSB2b2xhdGlsaWRhZCB5IGFsdGEgbGlxdWlkZXosIGxvIHF1ZSBsb3MgaGFjZSBhdHJhY3Rpdm9zIHBhcmEgaW52ZXJzaW9uaXN0YXMgcXVlIGJ1c2NhbiB1biBsdWdhciBzZWd1cm8gcGFyYSBzdXMgaW52ZXJzaW9uZXMgYSBjb3J0byBwbGF6by4NCg0KRWplbXBsbzoNCkxvcyBmb25kb3MgZGVsIG1lcmNhZG8gZGUgZGluZXJvIHNvbiB1biBlamVtcGxvIGNvbcO6bi4gU2UgaW52aWVydGUgZW4gdW4gZm9uZG8gZGUgbWVyY2FkbyBkZSBkaW5lcm8gcXVlIGNvbXByYSBsZXRyYXMgZGVsIFRlc29ybywgY2VydGlmaWNhZG9zIGRlIGRlcMOzc2l0byB5IHBhcGVsIGNvbWVyY2lhbC4gRXN0ZSBmb25kbyBvZnJlY2Ugc2VndXJpZGFkIHkgbGlxdWlkZXosIHBlcm1pdGnDqW5kb3RlIGFjY2VkZXIgYWwgZGluZXJvIHLDoXBpZGFtZW50ZSBzaSBzZSBuZWNlc2l0YSwgYXVucXVlIGxvcyByZW5kaW1pZW50b3Mgc3VlbGVuIHNlciBtw6FzIGJham9zIGVuIGNvbXBhcmFjacOzbiBjb24gYWNjaW9uZXMgbyBib25vcyBhIGxhcmdvIHBsYXpvLg0KDQojIyBBbsOhbGlzaXMgZGUgUG9ydGFmb2xpb3MgZW4gUjogRnVuY2lvbmVzIENsYXZlKDQpDQoNCkVuIGVzdGUgZG9jdW1lbnRvLCBleHBsb3JhbW9zIGN1YXRybyBmdW5jaW9uZXMgaW1wb3J0YW50ZXMgcGFyYSBlbCBhbsOhbGlzaXMgZGUgcG9ydGFmb2xpb3MgZW4gUiwgaW5jbHV5ZW5kbyBgREVvcHRpbWAgcGFyYSBsYSBvcHRpbWl6YWNpw7NuIGJhc2FkYSBlbiBsYSB0ZW9yw61hIGRlIE1hcmtvd2l0ei4NCg0KIyMjIEZ1bmNpb25lcyBkZSBBbsOhbGlzaXMgZGUgUG9ydGFmb2xpb3MNCg0KQSBjb250aW51YWNpw7NuLCBwcmVzZW50YW1vcyB1bmEgdGFibGEgcXVlIHJlc3VtZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBjdWF0cm8gZnVuY2lvbmVzIGNsYXZlOg0KDQp8IEZ1bmNpw7NuIHwgUGFxdWV0ZSB8IERlc2NyaXBjacOzbiB8IENhcmFjdGVyw61zdGljYXMgfA0KfC0tLS0tLS0tLXwtLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLXwNCnwgYHBvcnRmb2xpby5vcHRpbWAgfCBgdHNlcmllc2AgfCBPcHRpbWl6YSBwb3J0YWZvbGlvcyBiYXNhZG8gZW4gZWwgcmV0b3JubyB5IHJpZXNnby4gfCBVdGlsaXphIGxhIG1lZGlhLXZhcmlhbnphIHBhcmEgbGEgb3B0aW1pemFjacOzbi4gfA0KfCBgb3B0aW1pemUucG9ydGZvbGlvYCB8IGBQb3J0Zm9saW9BbmFseXRpY3NgIHwgUHJvcG9yY2lvbmEgdW4gbWFyY28gZmxleGlibGUgcGFyYSBsYSBjb25zdHJ1Y2Npw7NuIGRlIHBvcnRhZm9saW9zLiB8IEFkbWl0ZSByZXN0cmljY2lvbmVzIHBlcnNvbmFsaXphZGFzIHkgb2JqZXRpdm9zIG3Dumx0aXBsZXMuIHwNCnwgYFJldHVybi5wb3J0Zm9saW9gIHwgYFBlcmZvcm1hbmNlQW5hbHl0aWNzYCB8IENhbGN1bGEgZWwgcmV0b3JubyB0b3RhbCBkZSB1biBwb3J0YWZvbGlvLiB8IMOadGlsIHBhcmEgZWwgYW7DoWxpc2lzIHBvc3RlcmlvciBhIGxhIG9wdGltaXphY2nDs24uIHwNCnwgYERFb3B0aW1gIHwgYERFb3B0aW1gIHwgUmVhbGl6YSBsYSBvcHRpbWl6YWNpw7NuIGdsb2JhbCBiYXNhZGEgZW4gZWwgYWxnb3JpdG1vIGRlIGV2b2x1Y2nDs24gZGlmZXJlbmNpYWwuIHwgRWZpY2F6IHBhcmEgcHJvYmxlbWFzIGNvbXBsZWpvcyB5IG5vIGxpbmVhbGVzLiB8DQoNCiMjIyBKdXN0aWZpY2FjacOzbiBwYXJhIGxhIEVsZWNjacOzbiBkZSBgREVvcHRpbWANCg0KYERFb3B0aW1gIGVzIHVuYSBleGNlbGVudGUgZWxlY2Npw7NuIHBhcmEgbGEgb3B0aW1pemFjacOzbiBkZSBwb3J0YWZvbGlvcyBiYXNhZGEgZW4gbGEgdGVvcsOtYSBkZSBNYXJrb3dpdHogcG9yIHZhcmlhcyByYXpvbmVzOg0KDQoxLiAqKkZsZXhpYmlsaWRhZCBlbiBsYSBPcHRpbWl6YWNpw7NuOioqIGBERW9wdGltYCBlcyBlZmljYXogcGFyYSBtYW5lamFyIHByb2JsZW1hcyBkZSBvcHRpbWl6YWNpw7NuIGNvbXBsZWpvcyB5IG5vIGxpbmVhbGVzLCBsbyBxdWUgZXMgY29tw7puIGVuIGxhIG9wdGltaXphY2nDs24gZGUgcG9ydGFmb2xpb3MuDQoyLiAqKkNhcGFjaWRhZCBkZSBFdml0YXIgTcOtbmltb3MgTG9jYWxlczoqKiBBIGRpZmVyZW5jaWEgZGUgbG9zIG3DqXRvZG9zIGRlIG9wdGltaXphY2nDs24gdHJhZGljaW9uYWxlcyBxdWUgcHVlZGVuIHF1ZWRhciBhdHJhcGFkb3MgZW4gbcOtbmltb3MgbG9jYWxlcywgYERFb3B0aW1gIHV0aWxpemEgdW4gYWxnb3JpdG1vIGRlIGV2b2x1Y2nDs24gZGlmZXJlbmNpYWwgcXVlIGV4cGxvcmEgZGUgbWFuZXJhIG3DoXMgZWZlY3RpdmEgZWwgZXNwYWNpbyBkZSBzb2x1Y2lvbmVzLg0KMy4gKipBZGFwdGFiaWxpZGFkOioqIFB1ZWRlIG1hbmVqYXIgZGl2ZXJzYXMgcmVzdHJpY2Npb25lcyB5IG1vZGVsb3MsIGxvIHF1ZSBlcyBjcnVjaWFsIGN1YW5kbyBzZSB0cmFiYWphIGNvbiBsb3MgZGlmZXJlbnRlcyBlc2NlbmFyaW9zIHkgcHJlZmVyZW5jaWFzIGRlIGludmVyc2nDs24gcXVlIGNvbnRlbXBsYSBsYSB0ZW9yw61hIGRlIE1hcmtvd2l0ei4NCg0KRW4gcmVzdW1lbiwgYERFb3B0aW1gIHByb3BvcmNpb25hIHVuIGVuZm9xdWUgcm9idXN0byB5IGZsZXhpYmxlIHBhcmEgZW5jb250cmFyIGxhIGZyb250ZXJhIGVmaWNpZW50ZSBlbiBsYSBvcHRpbWl6YWNpw7NuIGRlIHBvcnRhZm9saW9zLCBhbGluZcOhbmRvc2UgYmllbiBjb24gbG9zIHByaW5jaXBpb3MgZGUgTWFya293aXR6IHNvYnJlIGRpdmVyc2lmaWNhY2nDs24geSBiYWxhbmNlIGVudHJlIHJpZXNnbyB5IHJldG9ybm8uDQoNCkEgY29udGludWFjacOzbiwgc2UgcHJvY2VkZSBjb24gZWwgZWplcmNpY2lvIHByw6FjdGljby4NCg0KIyMgQ8OzZGlnbyBlbiBSOg0KDQoqKjEuIENhcmdhciBsb3MgRGF0b3MgSGlzdMOzcmljb3MqKg0KUHJpbWVybywgY2FyZ2FyZW1vcyBsb3MgZGF0b3MgaGlzdMOzcmljb3MgZW4gUi4NCmBgYHtyfQ0KZGF0YSA8LSBkYXRhLmZyYW1lKA0KICB5ZWFyID0gMTk2MDoyMDAzLA0KICBzdG9ja3MgPSBjKDE3LjIxLCAxNC4xNCwgMTQuNTQsIDIxLjk4LCAtNC44LCAxNy41NywgMjAuOTQsIC0wLjIyLCA5LjgxLCAtOC41NiwgNS4yNywgMTcuNTYsIDkuMTQsIDIuNDksIDExLjUyLCAxNi42OSwgLTQuMzQsIC02LjMyLCAzNS43NCwgOS4zNSwgMzIuMDYsIDEwLjk1LCAtMi43OSwgLTI1LjM0LCAxNC44NSwgLTMuNjUsIDE2Ljk1LCAxNC4xMiwgMjAuNzEsIC04LjMxLCAxNi45OCwgMzkuMTQsIDE2LjIsIDEwLjg0LCAtNC43LCA4LjI0LCAzMC43NywgLTE1LjM5LCAxNC40NiwgLTMuODYsIC0xNC44NywgLTAuMjMsIDIwLjMyLCAyMi4xNiksDQogIGJvbmRzID0gYygxNy4xMSwgMS44NCwgLTIuNjcsIDE3LjE5LCA1LjE3LCA1Ljc3LCA5LjkyLCAxMy42NCwgLTIuMzQsIDcuMjEsIDcuMDEsIDYuMjUsIDEzLjY2LCA3LjE4LCA5LjEzLCAxNy40NiwgMTIuOTcsIDMuODUsIDguMjcsIDE0LjI3LCA0Ljc2LCAxNi42MSwgMTIuMjEsIDcuNzIsIDIuMiwgMTQuOTcsIDEzLjQ2LCAxMS40NywgMC43NSwgOC43MywgMTYuMDUsIDEyLjYyLCAxMi44OCwgMTMuNDMsIDEzLjc2LCAxMC41OCwgMTEuMzEsIDQuNjgsIDEwLjM5LCAzLjU3LCA3LjU3LCA3LjIxLCA3LjI4LCAxNi40MiksDQogIG1tID0gYyg3LjgyLCA5Ljc3LCA3LjY2LCAxMC4zNSwgMS42OCwgOC4zNCwgNi4wNiwgNC45MSwgNC4wNywgNy44OCwgOS4zOSwgOS44NywgMi45LCA0LjksIDQuNCwgNy42OSwgNi41NCwgMy4yNywgNi4wNCwgOC4wOSwgOS40NCwgNC4zLCA3Ljk1LCA5LjE4LCA3LjQ4LCA0LjIzLCA4Ljk5LCA3LjY3LCA0Ljc4LCAzLjgxLCAxNC45NSwgOC42LCAyLjQxLCA0LCA3Ljg1LCAzLjQzLCA1LjgzLCA0Ljg4LCA0Ljc1LCA5LjM4LCAxMC4zNywgNy41NywgNi44MywgNy43OSkNCikNCg0KYGBgDQoqKjIuIEPDoWxjdWxvIGRlIFJldG9ybm9zIEVzcGVyYWRvcyB5IFZhcmlhbnphKioNCkNhbGN1bGFyZW1vcyBlbCByZXRvcm5vIGVzcGVyYWRvLCBsYSB2YXJpYW56YSB5IGxhIGNvdmFyaWFuemEgZGUgbG9zIGFjdGl2b3MuDQpgYGB7cn0NCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQojIEFzdW1pZW5kbyBxdWUgbG9zIGRhdG9zIHlhIGVzdMOhbiBlbiBmb3JtYXRvIHBvcmNlbnR1YWwNCnJldHVybnMgPC0gZGF0YVssIC0xXQ0KDQojIFJldG9ybm8gZXNwZXJhZG8gKG1lZGlhKSB5IHZhcmlhbnphDQpleHBlY3RlZF9yZXR1cm5zIDwtIGNvbE1lYW5zKHJldHVybnMpDQpjb3ZhcmlhbmNlX21hdHJpeCA8LSBjb3YocmV0dXJucykNCg0KYGBgDQoqKjMuIENvbnN0cnVjY2nDs24gZGUgUG9ydGFmb2xpb3MqKg0KR2VuZXJhcmVtb3MgcG9ydGFmb2xpb3MgY29uIGRpZmVyZW50ZXMgY29tYmluYWNpb25lcyBkZSBsb3MgYWN0aXZvcy4NCmBgYHtyfQ0KbGlicmFyeShQb3J0Zm9saW9BbmFseXRpY3MpDQpwb3J0Zm9saW8gPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzID0gY29sbmFtZXMocmV0dXJucykpDQpwb3J0Zm9saW8gPC0gYWRkLmNvbnN0cmFpbnQocG9ydGZvbGlvLCB0eXBlID0gImZ1bGxfaW52ZXN0bWVudCIpDQpwb3J0Zm9saW8gPC0gYWRkLmNvbnN0cmFpbnQocG9ydGZvbGlvLCB0eXBlID0gImJveCIsIG1pbiA9IDAsIG1heCA9IDEpDQpwb3J0Zm9saW8gPC0gYWRkLm9iamVjdGl2ZShwb3J0Zm9saW8sIHR5cGUgPSAicmV0dXJuIiwgbmFtZSA9ICJtZWFuIikNCnBvcnRmb2xpbyA8LSBhZGQub2JqZWN0aXZlKHBvcnRmb2xpbywgdHlwZSA9ICJyaXNrIiwgbmFtZSA9ICJTdGREZXYiKQ0KDQpgYGANCioqNC4gQW7DoWxpc2lzIGRlIFBvcnRhZm9saW9zIHkgNS4gRnJvbnRlcmEgRWZpY2llbnRlKioNCmBgYHtyfQ0KbGlicmFyeShERW9wdGltKQ0KbGlicmFyeSh4dHMpDQpsaWJyYXJ5KFBvcnRmb2xpb0FuYWx5dGljcykNCg0KIyBUcmFuc2Zvcm1hciAnZGF0YScgZW4gb2JqZXRvIHh0cw0KZGF0YSR5ZWFyIDwtIGFzLkRhdGUoYXMuY2hhcmFjdGVyKGRhdGEkeWVhciksIGZvcm1hdCA9ICIlWSIpDQpyZXR1cm5zX3h0cyA8LSB4dHMoZGF0YVssIC0xXSwgb3JkZXIuYnkgPSBkYXRhJHllYXIpDQoNCiMgQ2FsY3VsYXIgcmV0b3Jub3MNCnJldHVybnMgPC0gZGlmZihsb2cocmV0dXJuc194dHMpKVstMSwgXQ0KDQojIE9wdGltaXphY2nDs24gZGVsIHBvcnRhZm9saW8NCm9wdGltaXplZF9wb3J0Zm9saW8gPC0gb3B0aW1pemUucG9ydGZvbGlvKHJldHVybnMsIHBvcnRmb2xpbywgb3B0aW1pemVfbWV0aG9kID0gIkRFb3B0aW0iLCB0cmFjZSA9IFRSVUUpDQoNCmBgYA0KKio2LiBTZWxlY2Npw7NuIGRlbCBQb3J0YWZvbGlvIEVmaWNpZW50ZSoqDQpTZWxlY2Npb25hcmVtb3MgZWwgcG9ydGFmb2xpbyBlZmljaWVudGUgc2Vnw7puIGxvcyBvYmpldGl2b3MgZGUgaW52ZXJzacOzbi4NCmBgYHtyfQ0KZWZmaWNpZW50X3BvcnRmb2xpbyA8LSBleHRyYWN0V2VpZ2h0cyhvcHRpbWl6ZWRfcG9ydGZvbGlvKQ0KDQpgYGANCiMjIFJlc3VtZW5lcyB5IGdyw6FmaWNvcw0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoY29ycnBsb3QpDQoNCiMgMS4gUmVzdW1lbiBkZSBsb3MgRGF0b3MNCnByaW50KHN1bW1hcnkoZGF0YSkpDQoNCiMgMi4gR3LDoWZpY28gZGUgU2VyaWVzIFRlbXBvcmFsZXMgZGUgbG9zIFJldG9ybm9zDQpkYXRhX2xvbmcgPC0gZGF0YSAlPiUgDQogIHBpdm90X2xvbmdlcigteWVhciwgbmFtZXNfdG8gPSAiYXNzZXQiLCB2YWx1ZXNfdG8gPSAicmV0dXJucyIpDQoNCmdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0geWVhciwgeSA9IHJldHVybnMsIGNvbG9yID0gYXNzZXQpKSArDQogIGdlb21fbGluZSgpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJTZXJpZXMgVGVtcG9yYWxlcyBkZSBSZXRvcm5vcyIsIHggPSAiQcOxbyIsIHkgPSAiUmV0b3JubyIsIGNvbG9yID0gIkFjdGl2byIpDQpgYGANCiMjIyBBbsOhbGlzaXMgZGUgU2VyaWVzIFRlbXBvcmFsZXMgZGUgUmV0b3Jub3MgZGUgSW52ZXJzaW9uZXMNCg0KRXN0ZSBkb2N1bWVudG8gcHJlc2VudGEgdW4gYW7DoWxpc2lzIHZpc3VhbCBkZSBsb3MgcmV0b3Jub3MgZGUgZGlmZXJlbnRlcyB0aXBvcyBkZSBpbnZlcnNpb25lcyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8uDQoNCiMjIyMgRGVzY3JpcGNpw7NuIGRlbCBHcsOhZmljbyBkZSBTZXJpZXMgVGVtcG9yYWxlcw0KDQpFbCBncsOhZmljbyBpbHVzdHJhIGPDs21vIGhhbiBmbHVjdHVhZG8gbG9zIHJldG9ybm9zIGRlIGFjY2lvbmVzLCBib25vcyB5IGVsIG1lcmNhZG8gbW9uZXRhcmlvIGRlc2RlIDE5NjAgaGFzdGEgcHJpbmNpcGlvcyBkZWwgMjAwMC4NCg0KIyMjIyBDb21wb25lbnRlcyBkZWwgR3LDoWZpY28NCi0gKipMw61uZWFzIGRlbCBHcsOhZmljbzoqKiANCiAgLSBMYSBsw61uZWEgYXp1bCByZXByZXNlbnRhIGxhcyBhY2Npb25lcyAoYHN0b2Nrc2ApLg0KICAtIExhIGzDrW5lYSByb2phIHJlcHJlc2VudGEgbG9zIGJvbm9zIChgYm9uZHNgKS4NCiAgLSBMYSBsw61uZWEgdmVyZGUgcmVwcmVzZW50YSBlbCBtZXJjYWRvIG1vbmV0YXJpbyAoYG1tYCkuDQoNCi0gKipFamUgVmVydGljYWwgLSBSZXRvcm5vOioqIA0KICAtIEluZGljYSBlbCByZXRvcm5vIGRlIGxhcyBpbnZlcnNpb25lcyBlbiBwb3JjZW50YWplLg0KICAtIFVuIHZhbG9yIG3DoXMgYWx0byBzaWduaWZpY2EgdW4gbWF5b3IgcmV0b3JubyBlbiBlc2UgYcOxby4NCg0KLSAqKkVqZSBIb3Jpem9udGFsIC0gQcOxbzoqKiANCiAgLSBNdWVzdHJhIGxhIGzDrW5lYSBkZSB0aWVtcG8gZGVzZGUgMTk2MCBoYXN0YSBlbCAyMDAwLg0KDQojIyMjIEludGVycHJldGFjacOzbiBkZSBsb3MgRGF0b3MNCg0KIyMjIyMgVm9sYXRpbGlkYWQNCi0gTGEgdm9sYXRpbGlkYWQgZGUgbGFzIGFjY2lvbmVzIHNlIHJlZmxlamEgZW4gbGEgYW1wbGl0dWQgZGUgbG9zIHBpY29zIChhenVsZXMpLCBsbyBxdWUgaW5kaWNhIHBvdGVuY2lhbCB0YW50byBwYXJhIGFsdG9zIHJldG9ybm9zIGNvbW8gcGFyYSBjYcOtZGFzIHNpZ25pZmljYXRpdmFzLg0KDQojIyMjIyBFc3RhYmlsaWRhZA0KLSBMb3MgYm9ub3MsIHJlcHJlc2VudGFkb3MgcG9yIGxhIGzDrW5lYSByb2phLCBtdWVzdHJhbiBtZW5vcyB2b2xhdGlsaWRhZCwgc3VnaXJpZW5kbyBxdWUgc29uIG1lbm9zIHJpZXNnb3NvcyB5IG9mcmVjZW4gcmV0b3Jub3MgbcOhcyBwcmVkZWNpYmxlcy4NCg0KIyMjIyMgQ29uc2VydmFkdXJpc21vDQotIExhIGzDrW5lYSB2ZXJkZSBkZWwgbWVyY2FkbyBtb25ldGFyaW8gbXVlc3RyYSBsYSBtYXlvciBlc3RhYmlsaWRhZCBlbnRyZSBsb3MgdHJlcywgaW5kaWNhbmRvIHVuYSBvcGNpw7NuIGRlIGludmVyc2nDs24gY29uc2VydmFkb3JhIGNvbiBtZW5vcmVzIHJldG9ybm9zIHBlcm8gdGFtYmnDqW4gbWVub3Igcmllc2dvLg0KDQojIyMjIEVzdHJhdGVnaWFzIGRlIEludmVyc2nDs24NCg0KIyMjIyMgRGl2ZXJzaWZpY2FjacOzbg0KLSBDb21iaW5hciBlc3RvcyB0aXBvcyBkZSBhY3Rpdm9zIHB1ZWRlIGJhbGFuY2VhciBlbCByaWVzZ28geSBlbCByZXRvcm5vLCBheXVkYW5kbyBhIG1pdGlnYXIgbG9zIGVmZWN0b3MgZGUgdW4gbWFsIGHDsW8gcGFyYSB1biBhY3Rpdm8gZXNwZWPDrWZpY28uDQoNCiMjIyMjIFBlcmZpbCBkZSBSaWVzZ28NCi0gTGEgc2VsZWNjacOzbiBlbnRyZSBhY2Npb25lcyB5IGJvbm9zIHB1ZWRlIGRlcGVuZGVyIGRlIGxhIHRvbGVyYW5jaWEgYWwgcmllc2dvIGRlbCBpbnZlcnNvciwgY29uIGJvbm9zIHByZWZlcmlkb3MgcGFyYSBlc3RhYmlsaWRhZCB5IGFjY2lvbmVzIHBhcmEgYXF1ZWxsb3MgcXVlIGJ1c2NhbiBtYXlvcmVzIHJldG9ybm9zIGFzdW1pZW5kbyBtw6FzIHJpZXNnby4NCg0KIyMjIyBQbGFuaWZpY2FjacOzbiBhIExhcmdvIFBsYXpvDQotIExhcyB0ZW5kZW5jaWFzIGEgbGFyZ28gcGxhem8gc29uIGNydWNpYWxlcyBwYXJhIGludmVyc29yZXMgYSBsYXJnbyBwbGF6bywgbcOhcyBhbGzDoSBkZSBsYXMgZmx1Y3R1YWNpb25lcyBhIGNvcnRvIHBsYXpvLg0KDQpMYSBjb21wcmVuc2nDs24gZGUgZXN0b3MgcHJpbmNpcGlvcyBlcyBlc2VuY2lhbCBwYXJhIGxvcyBlamVjdXRpdm9zIGFsIHRvbWFyIGRlY2lzaW9uZXMgZXN0cmF0w6lnaWNhcyBkZSBpbnZlcnNpw7NuLg0KDQoNCmBgYHtyfQ0KIyAzLiBNYXRyaXogZGUgQ29ycmVsYWNpb25lcw0KY29ycmVsYXRpb25fbWF0cml4IDwtIGNvcihkYXRhWywtMV0pDQojIEVzdGFibGVjZXIgcGFyw6FtZXRyb3MgZ3LDoWZpY29zIHBhcmEgcmVkdWNpciBlbCB0YW1hw7FvIGRlbCB0w610dWxvIHkgbGFzIGV0aXF1ZXRhcw0KcGFyKG9tYSA9IGMoNSwgNywgMSwgMSkpICMgQWp1c3RhIGxvcyBtw6FyZ2VuZXMgZXh0ZXJpb3JlcyBzaSBlcyBuZWNlc2FyaW8NCnBhcihtZ3AgPSBjKDIsIDEsIDApKSAgICAjIEFqdXN0YSBsYSBsw61uZWEgZW4gbGEgcXVlIHNlIGRpYnVqYW4gbGFzIGV0aXF1ZXRhcyBkZWwgZWplIChlamUsIGV0aXF1ZXRhLCB0w610dWxvKQ0KcGFyKGNleC5tYWluID0gMC43KSAgICAgICAjIFJlZHVjZSBlbCB0YW1hw7FvIGRlbCB0w610dWxvDQpwYXIoY2V4LmxhYiA9IDAuNykgICAgICAgICMgUmVkdWNlIGVsIHRhbWHDsW8gZGUgbGFzIGV0aXF1ZXRhcyBkZSBsb3MgZWplcw0KDQojIEdlbmVyYSBlbCBncsOhZmljbyBkZSBsYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBjb24gdGFtYcOxb3MgZGUgdGV4dG8gcmVkdWNpZG9zDQpjb3JycGxvdChjb3JyZWxhdGlvbl9tYXRyaXgsIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLA0KICAgICAgICAgdGwuY29sID0gImJsYWNrIiwgdGwuc3J0ID0gNDUsIHRsLmNleCA9IDAuNywgY2wuY2V4ID0gMC43LCAjIEFqdXN0YSBlbCB0YW1hw7FvIGRlIGxhcyBldGlxdWV0YXMgeSBsYSBsZXllbmRhDQogICAgICAgICB0aXRsZSA9ICJNYXRyaXogZGUgQ29ycmVsYWNpb25lcyIpDQoNCiMgUmVzdGF1cmEgbGEgY29uZmlndXJhY2nDs24gZ3LDoWZpY2EgcHJlZGV0ZXJtaW5hZGEgZGVzcHXDqXMgZGVsIGdyw6FmaWNvDQpwYXIoY2V4Lm1haW4gPSAxLCBjZXgubGFiID0gMSwgb21hID0gYygwLCAwLCAwLCAwKSwgbWdwID0gYygzLCAxLCAwKSkNCmBgYA0KIyMjIEV4cGxpY2FjacOzbiBkZSBsYSBNYXRyaXogZGUgQ29ycmVsYWNpb25lcw0KDQpMYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBlcyB1bmEgaGVycmFtaWVudGEgcXVlIG5vcyBtdWVzdHJhIGPDs21vIGRpZmVyZW50ZXMgdGlwb3MgZGUgaW52ZXJzaW9uZXMgc2UgbXVldmVuIGVuIHJlbGFjacOzbiBlbnRyZSBzw60uIEVuIHVuIHBvcnRhZm9saW8sIHRlbmVyIGFjdGl2b3MgcXVlIG5vIHNlIG11ZXZlbiBlbiBsYSBtaXNtYSBkaXJlY2Npw7NuIHB1ZWRlIGF5dWRhciBhIHJlZHVjaXIgZWwgcmllc2dvLg0KDQojIyMjIEludGVycHJldGFjacOzbiBkZSBsYSBNYXRyaXoNCg0KLSBDYWRhIGN1YWRyYWRvIGVuIGxhIG1hdHJpeiByZXByZXNlbnRhIGxhIHJlbGFjacOzbiBlbnRyZSBkb3MgdGlwb3MgZGUgYWN0aXZvcy4NCi0gTG9zIGNvbG9yZXMgbcOhcyBvc2N1cm9zIHkgdmFsb3JlcyBjZXJjYW5vcyBhIDEgbyAtMSBpbmRpY2FuIHVuYSByZWxhY2nDs24gZnVlcnRlLg0KLSBWYWxvcmVzIGNlcmNhbm9zIGEgMCBpbmRpY2FuIHVuYSByZWxhY2nDs24gZMOpYmlsIG8gaW5leGlzdGVudGUuDQoNCiMjIyMgRGV0YWxsZXMgZGUgbGEgTWF0cml6DQoNCi0gKipBY2Npb25lcyB2cy4gQm9ub3M6KiogTGEgY29ycmVsYWNpw7NuIGVudHJlIGFjY2lvbmVzIHkgYm9ub3MgZXMgZ2VuZXJhbG1lbnRlIGJhamEsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBubyBzZSBtdWV2ZW4gZW4gcGVyZmVjdGEgYXJtb27DrWEuIEVzdG8gZXMgYmVuZWZpY2lvc28gcGFyYSBsYSBkaXZlcnNpZmljYWNpw7NuIGRlbCBwb3J0YWZvbGlvLCB5YSBxdWUgbGEgbWV6Y2xhIGRlIGFjdGl2b3MgcHVlZGUgcmVkdWNpciBlbCByaWVzZ28gZ2VuZXJhbC4NCg0KLSAqKkFjY2lvbmVzIHZzLiBNZXJjYWRvIE1vbmV0YXJpbzoqKiBMYSBjb3JyZWxhY2nDs24gZW50cmUgYWNjaW9uZXMgeSBlbCBtZXJjYWRvIG1vbmV0YXJpbyB0YW1iacOpbiB0aWVuZGUgYSBzZXIgYmFqYSwgcmVmb3J6YW5kbyBlbCBiZW5lZmljaW8gZGUgZGl2ZXJzaWZpY2FyIGFsIGluY2x1aXIgZGlmZXJlbnRlcyB0aXBvcyBkZSBhY3Rpdm9zLg0KDQotICoqQm9ub3MgdnMuIE1lcmNhZG8gTW9uZXRhcmlvOioqIEVzdG9zIGRvcyBhY3Rpdm9zIHB1ZWRlbiBtb3N0cmFyIHVuYSBjb3JyZWxhY2nDs24gbcOhcyBmdWVydGUsIHlhIHF1ZSBhbWJvcyBzb24gY29uc2lkZXJhZG9zIGludmVyc2lvbmVzIG3DoXMgc2VndXJhcyBlbiBjb21wYXJhY2nDs24gY29uIGxhcyBhY2Npb25lcy4gU2luIGVtYmFyZ28sIHVuYSBjb3JyZWxhY2nDs24gbm8gcGVyZmVjdGFtZW50ZSBwb3NpdGl2YSBzaWd1ZSBvZnJlY2llbmRvIGJlbmVmaWNpb3MgZGUgZGl2ZXJzaWZpY2FjacOzbi4NCg0KIyMjIyBSZWxldmFuY2lhIHBhcmEgbGEgRXN0cmF0ZWdpYSBkZSBJbnZlcnNpw7NuDQoNClBhcmEgdW4gZWplY3V0aXZvLCBlbnRlbmRlciBlc3RhIG1hdHJpeiBlcyBjcnVjaWFsIHBhcmEgbGEgZGl2ZXJzaWZpY2FjacOzbiBkZWwgcG9ydGFmb2xpbzoNCg0KLSAqKkRpdmVyc2lmaWNhY2nDs246KiogQnVzY2Ftb3MgY29tYmluYXIgYWN0aXZvcyBxdWUgbm8gc2UgbXVldmVuIGV4YWN0YW1lbnRlIGlndWFsIHBhcmEgcHJvdGVnZXIgZWwgcG9ydGFmb2xpbyBjb250cmEgbW92aW1pZW50b3MgaW5lc3BlcmFkb3MgZGVsIG1lcmNhZG8uDQotICoqQmFsYW5jZSBkZSBSaWVzZ286KiogU2kgdG9kb3MgbnVlc3Ryb3MgYWN0aXZvcyBzZSBtdWV2ZW4ganVudG9zLCB1biBtYWwgZXZlbnRvIHB1ZWRlIGFmZWN0YXIgYSB0b2RvIGVsIHBvcnRhZm9saW8uIERpdmVyc2lmaWNhciBheXVkYSBhIG1pdGlnYXIgZXN0ZSByaWVzZ28uDQotICoqUGxhbmlmaWNhY2nDs24gRXN0cmF0w6lnaWNhOioqIENvbXByZW5kZXIgZXN0YXMgcmVsYWNpb25lcyBub3MgYXl1ZGEgYSBwbGFuaWZpY2FyIHBhcmEgZGlmZXJlbnRlcyBlc2NlbmFyaW9zIGVjb27Ds21pY29zIHkgYXNlZ3VyYXIgcXVlIGVsIHBvcnRhZm9saW8gZXN0w6kgcHJlcGFyYWRvIHBhcmEgZW5mcmVudGFyIGxhIHZvbGF0aWxpZGFkIGRlbCBtZXJjYWRvLg0KDQpSZWNvcmRhciBxdWUgZWwgb2JqZXRpdm8gZXMgbWFudGVuZXIgdW4gZXF1aWxpYnJpbyBxdWUgYWxpbmVlIGNvbiBsb3Mgb2JqZXRpdm9zIGRlIGludmVyc2nDs24geSBlbCBhcGV0aXRvIGRlIHJpZXNnbyBkZSBsYSBjb21wYcOxw61hLg0KDQpgYGB7cn0NCiMgNC4gUG9ydGFmb2xpbyBPcHRpbWl6YWRvDQpwcmludChlZmZpY2llbnRfcG9ydGZvbGlvKQ0KDQojIDUuIEdyw6FmaWNvIGRlbCBQb3J0YWZvbGlvIE9wdGltaXphZG8NCm9wdGltaXplZF93ZWlnaHRzIDwtIGRhdGEuZnJhbWUoDQogIGFzc2V0ID0gY29sbmFtZXMocmV0dXJucyksDQogIHdlaWdodHMgPSBlZmZpY2llbnRfcG9ydGZvbGlvDQopDQoNCmdncGxvdChvcHRpbWl6ZWRfd2VpZ2h0cywgYWVzKHggPSBhc3NldCwgeSA9IHdlaWdodHMsIGZpbGwgPSBhc3NldCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlbCBQb3J0YWZvbGlvIE9wdGltaXphZG8iLCB4ID0gIlRpcG8gZGUgQWN0aXZvIiwgeSA9ICJQZXNvIikNCmBgYA0KIyMjIyBFeHBsaWNhY2nDs24gZGUgbGEgRGlzdHJpYnVjacOzbiBkZWwgUG9ydGFmb2xpbyBPcHRpbWl6YWRvDQoNCkVsIGdyw6FmaWNvIG11ZXN0cmEgbGEgZGlzdHJpYnVjacOzbiBkZSB1biBwb3J0YWZvbGlvIGRlIGludmVyc2nDs24gb3B0aW1pemFkbywgaWx1c3RyYW5kbyBjw7NtbyBzZSBoYSBhc2lnbmFkbyBlbCBjYXBpdGFsIGVudHJlIGRpZmVyZW50ZXMgdGlwb3MgZGUgYWN0aXZvcy4NCg0KLSAqKkJvbm9zIChgYm9uZHNgKToqKiBMYSBiYXJyYSByb2phIGluZGljYSBsYSBwcm9wb3JjacOzbiBkZWwgcG9ydGFmb2xpbyBhc2lnbmFkYSBhIGJvbm9zLCBxdWUgZXMgbGlnZXJhbWVudGUgbcOhcyBkZWwgMjAlLiBMb3MgYm9ub3Mgc3VlbGVuIGNvbnNpZGVyYXJzZSBjb21vIGludmVyc2lvbmVzIG3DoXMgc2VndXJhcyBlbiBjb21wYXJhY2nDs24gY29uIGxhcyBhY2Npb25lcy4NCg0KLSAqKk1lcmNhZG8gTW9uZXRhcmlvIChgbW1gKToqKiBMYSBiYXJyYSB2ZXJkZSBtdWVzdHJhIGxhIHByb3BvcmNpw7NuIGFzaWduYWRhIGFsIG1lcmNhZG8gbW9uZXRhcmlvLCBxdWUgcmVwcmVzZW50YSBsYSBtYXlvciBwYXJ0ZSBkZWwgcG9ydGFmb2xpbyBjb24gYXByb3hpbWFkYW1lbnRlIHVuIDM1JS4gSW52ZXJzaW9uZXMgZW4gZWwgbWVyY2FkbyBtb25ldGFyaW8gc3VlbGVuIHNlciBtdXkgbMOtcXVpZGFzIHkgZGUgYmFqbyByaWVzZ28uDQoNCi0gKipBY2Npb25lcyAoYHN0b2Nrc2ApOioqIExhIGJhcnJhIGF6dWwgcmVmbGVqYSBsYSBpbnZlcnNpw7NuIGVuIGFjY2lvbmVzLCBjb24gdW4gcGVzbyBzaW1pbGFyIGFsIGRlbCBtZXJjYWRvIG1vbmV0YXJpby4gTGFzIGFjY2lvbmVzIHNvbiBnZW5lcmFsbWVudGUgbcOhcyB2b2zDoXRpbGVzIHkgcHVlZGVuIG9mcmVjZXIgdW4gbWF5b3IgcG90ZW5jaWFsIGRlIGNyZWNpbWllbnRvIGNvbXBhcmFkbyBjb24gYm9ub3MgeSBtZXJjYWRvIG1vbmV0YXJpby4NCg0KRXN0ZSBwb3J0YWZvbGlvIHBhcmVjZSBlc3RhciBkaXZlcnNpZmljYWRvLCBkaXN0cmlidXllbmRvIGVsIHJpZXNnbyB5IHBvdGVuY2lhbG1lbnRlIGVxdWlsaWJyYW5kbyBlbCBjcmVjaW1pZW50byB5IGxhIHNlZ3VyaWRhZC4NCg0KDQoNCiMjIFJlZmVyZW5jaWFzIGJpYmxpb2dyw6FmaWNhczoNCigxKSAgQXJyaWFnYSBOYXZhcnJldGUsIFIuLCBDYXN0cm8gT2xpdmFyZXMsIEouIEUuLCAmIFNvc2EgQ2FzdHJvLCBNLiAoMjAxOSkuIEFuw6FsaXNpcyBkZSBlc3RyYXRlZ2lhcyBkZSBpbnZlcnNpw7NuIGRlIGRpdmVyc2lmaWNhY2nDs24gaW50ZXJuYWNpb25hbDogcG9ydGFmb2xpb3MgdHJhZGljaW9uYWxlcyB2cyBFVEZTLiBBbsOhbGlzaXMgZWNvbsOzbWljbywgMzQoODcpLCA0MS03MC4gRXB1YiAxMyBkZSBub3ZpZW1icmUgZGUgMjAyMC4gUmVjdXBlcmFkbyBlbCAxOCBkZSBkaWNpZW1icmUgZGUgMjAyMywgZGUgaHR0cDovL3d3dy5zY2llbG8ub3JnLm14L3NjaWVsby5waHA/c2NyaXB0PXNjaV9hcnR0ZXh0JnBpZD1TMjQ0OC02NjU1MjAxOTAwMDMwMDA0MSZsbmc9ZXMmdGxuZz1lcy4NCg0KKDIpICBCdXJpdGljw6EtTWVqw61hLCBKLiBBLiAoMjAyMSkuIE1vZGVsbyBCbGFjay1MaXR0ZXJtYW4gY29uIFN1cHBvcnQgVmVjdG9yIFJlZ3Jlc3Npb246IHVuYSBhbHRlcm5hdGl2YSBwYXJhIGxvcyBmb25kb3MgZGUgcGVuc2lvbmVzIG9ibGlnYXRvcmlvcyBjb2xvbWJpYW5vcy4gT0RFT04sICgxOCksIDIwNeKAkzI1Ny4gaHR0cHM6Ly9kb2kub3JnLzEwLjE4NjAxLzE3OTQxMTEzLm4xOC4wNi4NCg0KKDMpICBBcmFnw7NuIFVycmVnbywgRC4gKDIwMjIpLiBQYXJpZGFkIGRlIHJpZXNnbyBqZXLDoXJxdWljbzogYXByb3hpbWFjacOzbiBhbCBtw6l0b2RvIHkgYXBsaWNhY2nDs24gcGFyYSBlbCBtZXJjYWRvIGVzdGFkb3VuaWRlbnNlLiBPREVPTiwgKDIxKSwgMTA14oCTMTI0LiBodHRwczovL2RvaS5vcmcvMTAuMTg2MDEvMTc5NDExMTMubjIxLjA2Lg0KDQooNCkgIE1hdGVyaWFsIEN1cnNvIDEuIChzLiBmLikuIFByw6FjdGljYSA2OiBBbsOhbGlzaXMgeSBzZWxlY2Npw7NuIGRlIHBvcnRhZm9saW9zLiBSZWN1cGVyYWRvIGRlIGh0dHBzOi8vbmF0YWxpYXByaW5zLmdpdGh1Yi5pby9jdXJzb3MvU2VsZWNjaSVDMyVCM24lMjBkZSUyMENhcnRlcmFzL1NlbGVjY2lvbiUyMGRlJTIwcG9ydGFmb2xpb3MvQW4lQzMlQTFsaXNpcyUyMHklMjBTZWxlY2NpJUMzJUIzbiUyMGRlJTIwUG9ydGFmb2xpb3MuaHRtbA0KDQoNCg0K