Detección de exoplanetas y sus características

El problema

Durante casi tres décadas de investigación, la NASA ha confirmado la existencia de mÔs de 5,600 exoplanetas en 4,151 sistemas planetarios. Estos mundos, conocidos como exoplanetas o planetas extrasolares, orbitan estrellas distintas al Sol. Aunque los astrónomos los imaginaron durante milenios, no fue hasta mediados de la década de 1990 cuando comenzaron a aparecer en los registros científicos.

Aproximadamente dos tercios de los exoplanetas descubiertos hasta ahora provienen del telescopio espacial Kepler, mientras que cientos mÔs han sido identificados gracias a la misión TESS y otros observatorios terrestres. Estas misiones han generado una enorme cantidad de datos, con cerca de 10,000 posibles exoplanetas aún pendientes de confirmación. Un número impresionante si consideramos que hasta principios de los años noventa no se conocía ninguno, pero diminuto en comparación con los cientos de miles de millones que podrían existir solo en la Vía LÔctea.

Para detectar estos mundos, los astrónomos emplean diversas técnicas, muchas de ellas llevadas al límite de la tecnología disponible en los observatorios espaciales (Nardi, Luca, n.d.): astrometría o detección a través del movimiento estelar (Wu, Dong-Hong, n.d.), velocidades radiales o detección a través del efecto Doppler (Marín, Daniel, n.d.b), método del trÔnsito o detección a través de la sombra planetaria (Alonso Sobrino, Roi, n.d.), microlente gravitacional o detección a través de la curvatura del espacio-tiempo (Marín, Daniel, n.d.a), observación directa o fotografía en medio del brillo estelar (NASA, Equipo de redacción de Ciencia, n.d.) y detección por cómo afectan la rotación de púlsares (Wolszczan, Aleksander & Frail, D. A., n.d.).

El anÔlisis de exoplanetas presenta varios desafíos en la modelización de datos. La multicolinealidad es un problema común, ya que muchas variables orbitales, estelares y planetarias estÔn altamente correlacionadas debido a su origen físico común, como la relación entre el período orbital y el semieje mayor, descrita por la Ley de Kepler. AdemÔs, el ruido y la variabilidad en los datos pueden afectar la precisión de las predicciones, ya que las mediciones suelen presentar incertidumbre, especialmente en la estimación de masas y radios planetarios, lo que refleja la diversidad natural de los sistemas estelares. Otro aspecto clave es la no linealidad en las relaciones entre propiedades estelares, orbitales y planetarias, como la dependencia cúbica entre el semieje mayor y el período orbital según la Ley de Kepler. Finalmente, la alta dimensionalidad de los datos, generada por la gran cantidad de sensores y metodologías para detectar exoplanetas, puede introducir variables irrelevantes o redundantes, aumentando innecesariamente la complejidad del modelo, por lo que es fundamental aplicar técnicas de selección de variables para mejorar la eficiencia del anÔlisis.

Antecedentes

La detección de exoplanetas es un campo de investigación en constante evolución, con nuevos descubrimientos y técnicas emergentes que amplían nuestro conocimiento del universo. La ciencia de datos juega un papel fundamental en este proceso, permitiendo a los astrónomos analizar grandes volúmenes de datos y extraer información relevante sobre los exoplanetas y sus características.

Incluso NASA anima a la detección amateur de exoplanetas a través de su sitio Exoplanet Watch donde ofrece una guía detallada sobre cómo analizar observaciones de trÔnsitos de exoplanetas para generar curvas de luz, que representan las variaciones en el brillo de una estrella cuando un planeta pasa frente a ella (brachman-2024?)

Trabajos relacionados

Hay varios antecedentes del uso de aprendizaje automÔtico y métodos estadísticos para la detección de exoplanetas.

En (Malik, A., Moster, B. P., & Obermeier, C., n.d.) se presenta una nueva técnica basada en machine learning para detectar exoplanetas mediante el método de trÔnsito. Se empleó la biblioteca TSFresh para extraer 789 características de curvas de luz y entrenar un clasificador de gradient boosting con LightGBM.

En (Hadrien Cambazard, Nicolas Catusse, Antoine Chomez, Anne-Marie Lagrange, n.d.) se trata la problemÔtica de detección de imagen directa de exoplanetas y cómo separar el ruido de fondo de las señales planetarias. Los métodos estadísticos recientes evitan la auto sustracción de señales de interés, a diferencia del enfoque inicial basado en imÔgenes diferenciales angulares (ADI). Sin embargo, estos métodos pueden generar muchos falsos positivos si no se establecen umbrales conservadores, lo que a su vez puede hacer que se pierdan exoplanetas débiles. Este estudio extiende un marco estadístico incorporando una regresión logística para filtrar candidatos, utilizando características ópticas en dos longitudes de onda. Se aplica detección de bordes y algoritmos de clustering para procesar sub-imÔgenes.

En (Cardenas, Christian & Lozano, David & Marquez, Cristian & Torres, Edilberto & Delgado-Correal, Camilo, n.d.) se desarrolla un ensamblado de software autónomo para detectar trÔnsitos planetarios en curvas de luz estelares, utilizando un clasificador de lógica difusa y evitando la búsqueda manual de trÔnsitos en grandes volúmenes de datos.

En (venkata-2023?) se presenta una técnica para detectar exoplanetas usando el método de trÔnsito. El objetivo es mejorar las técnicas tradicionales en astronomía con el uso de algoritmos de aprendizaje automÔtico. Para ello, utilizan seis modelos diferentes de aprendizaje automÔtico: Random Forest, Decision Tree, Support Vector Classifier, K-Nearest Neighbor y Multi-Layer Perceptron. Al comparar las precisiones concluye que combinando cuatro de esos modelos (Support Vector Classifier, K-Nearest Neighbor, Random Forest y Multi-Layer Perceptron) usando bagging, se lograba una mayor precisión.

En (Pimentel, J., Amorim, J. & Rudzicz, F., n.d.) se centra en detectar posibles planetas utilizando el método de trÔnsito con un enfoque novedoso al clasificar estrellas mediante un conjunto de características extraídas de series temporales en tres dominios: temporal, estadístico y espectral. Estas características se utilizan para entrenar y evaluar modelos con datos del telescopio Kepler, y los resultados superan algunos enfoques existentes. AdemÔs, el proceso de validación cruzada se emplea para eliminar sesgos y evaluar mejor los modelos.

InspirÔndose en estos antecedentes, este trabajo busca utilizar la regresión parÔmetros faltantes de los exoplanetas así como predecir su habitabilidad.

#AnƔlisis Exploratorio

En (tuckey-1977?) se explica que el anÔlisis exploratorio de datos (EDA) se enfoca en descubrir patrones, anomalías y relaciones dentro de los datos, utilizando métodos visuales y estadísticos. En su base, implica abordar la incertidumbre y la diversidad de estructuras posibles en los datos, evitando asumir un único modelo probabilístico como absoluto. El EDA enfatiza la exploración sobre la inferencia estricta, buscando métodos robustos y flexibles que funcionen en diversas circunstancias, con el objetivo de proporcionar una comprensión preliminar y preparar el terreno para anÔlisis mÔs profundos.

El dataset de expolanetas detectados con el telescopio espacial Kepler

El Archivo de Exoplanetas de la NASA es un catÔlogo astronómico en línea y un servicio de datos que recopila, correlaciona y organiza información sobre exoplanetas y sus estrellas anfitrionas. AdemÔs, proporciona herramientas para trabajar con estos datos. Este archivo estÔ dedicado a la recopilación y difusión de conjuntos de datos públicos claves utilizados en la búsqueda y caracterización de planetas extrasolares y sus estrellas (IPAC, n.d.a).

Este archivo estÔ dedicado a la recopilación y difusión de conjuntos de datos públicos clave utilizados en la búsqueda y caracterización de planetas extrasolares y sus estrellas (IPAC, n.d.b). Entre los datos disponibles se incluyen:

  • ParĆ”metros estelares: posiciones, magnitudes y temperaturas de las estrellas anfitrionas.
  • ParĆ”metros de exoplanetas: masas, caracterĆ­sticas orbitales y otros datos fundamentales.
  • Datos de descubrimiento y caracterización: curvas de velocidad radial publicadas, curvas de luz fotomĆ©tricas, imĆ”genes y espectros.

Esta base de datos es una herramienta esencial para la investigación en el campo de la astronomía de exoplanetas y ha sido utilizada en numerosos estudios científicos y proyectos de investigación. Se encuentra disponible en línea y es de libre acceso para la comunidad científica y el público en general en el sitio del IPAC del Caltech. El IPAC (Infrared Processing and Analysis Center) es un centro de investigación y procesamiento de datos astronómicos ubicado en el Instituto de Tecnología de California (Caltech). Se especializa en la gestión y anÔlisis de datos de misiones espaciales y telescopios astronómicos, en colaboración con agencias como la NASA, la Fundación Nacional de Ciencias (NSF) y el Laboratorio de Propulsión a Chorro (JPL) (IPAC, n.d.c).

Al momento de la extracción (14 de enero de 2025) el dataset de exoplanetas contiene información sobre 28.217 exoplanetas (entre confirmados, propuestos y en estudio) y sus características. La base de datos de IPAC contiene información sobre los exoplanetas detectados por la misión Kepler y otros telescopios, pero para este trabajo se utilizarÔ solo la información de los exoplanetas detectados por la misión Kepler (Cermak, A. & Cermak, A., n.d.).

Se cargarÔn los datos, se filtrarÔn las filas de los explonetas confirmados, las columnas relevantes, se eliminarÔn los valores faltantes y se realizarÔ un anÔlisis exploratorio de los datos para luego realizar la regresión lineal y logística.

Preprocesamiento de datos

Se cargan los datos del dataset de exoplanetas de la misión Kepler del archivo keplerexoplanets.csv. El mismo se obtuvo de la pÔgina del IPAC del Caltech (IPAC, n.d.a). La consulta usada para producir el dataset fue la siguiente:

# This file was produced by the NASA Exoplanet Archive  http://exoplanetarchive.ipac.caltech.edu
# Tue Jan 14 15:20:53 2025
#
# User preference: *
#
# CONSTRAINT:  where (disc_facility like '%Kepler%')
#
# COLUMN pl_name:        Planet Name
# COLUMN hostname:       Host Name
# COLUMN pl_letter:      Planet Letter
# COLUMN hd_name:        HD ID
# COLUMN hip_name:       HIP ID
# COLUMN tic_id:         TIC ID
# COLUMN gaia_id:        GAIA ID
# COLUMN default_flag:   Default Parameter Set
# COLUMN sy_snum:        Number of Stars
# COLUMN sy_pnum:        Number of Planets
# COLUMN sy_mnum:        Number of Moons
# COLUMN cb_flag:        Circumbinary Flag
# COLUMN discoverymethod: Discovery Method
# COLUMN disc_year:      Discovery Year
# COLUMN disc_refname:   Discovery Reference
# COLUMN disc_pubdate:   Discovery Publication Date
# COLUMN disc_locale:    Discovery Locale
# COLUMN disc_facility:  Discovery Facility
# COLUMN disc_telescope: Discovery Telescope
# COLUMN disc_instrument: Discovery Instrument
# COLUMN rv_flag:        Detected by Radial Velocity Variations
# COLUMN pul_flag:       Detected by Pulsar Timing Variations
# COLUMN ptv_flag:       Detected by Pulsation Timing Variations
# COLUMN tran_flag:      Detected by Transits
# COLUMN ast_flag:       Detected by Astrometric Variations
# COLUMN obm_flag:       Detected by Orbital Brightness Modulations
# COLUMN micro_flag:     Detected by Microlensing
# COLUMN etv_flag:       Detected by Eclipse Timing Variations
# COLUMN ima_flag:       Detected by Imaging
# COLUMN dkin_flag:      Detected by Disk Kinematics
# COLUMN soltype:        Solution Type
# COLUMN pl_controv_flag: Controversial Flag
# COLUMN pl_refname:     Planetary Parameter Reference
# COLUMN pl_orbper:      Orbital Period [days]
# COLUMN pl_orbsmax:     Orbit Semi-Major Axis [au]
# COLUMN pl_rade:        Planet Radius [Earth Radius]
# COLUMN pl_radj:        Planet Radius [Jupiter Radius]
# COLUMN pl_masse:       Planet Mass [Earth Mass]
# COLUMN pl_massj:       Planet Mass [Jupiter Mass]
# COLUMN pl_msinie:      Planet Mass*sin(i) [Earth Mass]
# COLUMN pl_msinij:      Planet Mass*sin(i) [Jupiter Mass]
# COLUMN pl_cmasse:      Planet Mass*sin(i)/sin(i) [Earth Mass]
# COLUMN pl_cmassj:      Planet Mass*sin(i)/sin(i) [Jupiter Mass]
# COLUMN pl_bmasse:      Planet Mass or Mass*sin(i) [Earth Mass]
# COLUMN pl_bmassj:      Planet Mass or Mass*sin(i) [Jupiter Mass]
# COLUMN pl_bmassprov:   Planet Mass or Mass*sin(i) Provenance
# COLUMN pl_dens:        Planet Density [g/cm**3]
# COLUMN pl_orbeccen:    Eccentricity
# COLUMN pl_insol:       Insolation Flux [Earth Flux]
# COLUMN pl_eqt:         Equilibrium Temperature [K]
# COLUMN pl_orbincl:     Inclination [deg]
# COLUMN pl_tranmid:     Transit Midpoint [days]
# COLUMN pl_tsystemref:  Time Reference Frame and Standard
# COLUMN ttv_flag:       Data show Transit Timing Variations
# COLUMN pl_imppar:      Impact Parameter
# COLUMN pl_trandep:     Transit Depth [%]
# COLUMN pl_trandur:     Transit Duration [hours]
# COLUMN pl_ratdor:      Ratio of Semi-Major Axis to Stellar Radius
# COLUMN pl_ratror:      Ratio of Planet to Stellar Radius
# COLUMN pl_occdep:      Occultation Depth [%]
# COLUMN pl_orbtper:     Epoch of Periastron [days]
# COLUMN pl_orblper:     Argument of Periastron [deg]
# COLUMN pl_rvamp:       Radial Velocity Amplitude [m/s]
# COLUMN pl_projobliq:   Projected Obliquity [deg]
# COLUMN pl_trueobliq:   True Obliquity [deg]
# COLUMN st_refname:     Stellar Parameter Reference
# COLUMN st_spectype:    Spectral Type
# COLUMN st_teff:        Stellar Effective Temperature [K]
# COLUMN st_rad:         Stellar Radius [Solar Radius]
# COLUMN st_mass:        Stellar Mass [Solar mass]
# COLUMN st_met:         Stellar Metallicity [dex]
# COLUMN st_metratio:    Stellar Metallicity Ratio
# COLUMN st_lum:         Stellar Luminosity [log(Solar)]
# COLUMN st_logg:        Stellar Surface Gravity [log10(cm/s**2)]
# COLUMN st_age:         Stellar Age [Gyr]
# COLUMN st_dens:        Stellar Density [g/cm**3]
# COLUMN st_vsin:        Stellar Rotational Velocity [km/s]
# COLUMN st_rotp:        Stellar Rotational Period [days]
# COLUMN st_radv:        Systemic Radial Velocity [km/s]
# COLUMN sy_refname:     System Parameter Reference
# COLUMN rastr:          RA [sexagesimal]
# COLUMN ra:             RA [deg]
# COLUMN decstr:         Dec [sexagesimal]
# COLUMN dec:            Dec [deg]
# COLUMN glat:           Galactic Latitude [deg]
# COLUMN glon:           Galactic Longitude [deg]
# COLUMN elat:           Ecliptic Latitude [deg]
# COLUMN elon:           Ecliptic Longitude [deg]
# COLUMN sy_pm:          Total Proper Motion [mas/yr]
# COLUMN sy_pmra:        Proper Motion (RA) [mas/yr]
# COLUMN sy_pmdec:       Proper Motion (Dec) [mas/yr]
# COLUMN sy_dist:        Distance [pc]
# COLUMN sy_plx:         Parallax [mas]
# COLUMN sy_bmag:        B (Johnson) Magnitude
# COLUMN sy_vmag:        V (Johnson) Magnitude
# COLUMN sy_jmag:        J (2MASS) Magnitude
# COLUMN sy_hmag:        H (2MASS) Magnitude
# COLUMN sy_kmag:        Ks (2MASS) Magnitude
# COLUMN sy_umag:        u (Sloan) Magnitude
# COLUMN sy_gmag:        g (Sloan) Magnitude
# COLUMN sy_rmag:        r (Sloan) Magnitude
# COLUMN sy_imag:        i (Sloan) Magnitude
# COLUMN sy_zmag:        z (Sloan) Magnitude
# COLUMN sy_w1mag:       W1 (WISE) Magnitude
# COLUMN sy_w2mag:       W2 (WISE) Magnitude
# COLUMN sy_w3mag:       W3 (WISE) Magnitude
# COLUMN sy_w4mag:       W4 (WISE) Magnitude
# COLUMN sy_gaiamag:     Gaia Magnitude
# COLUMN sy_icmag:       I (Cousins) Magnitude
# COLUMN sy_tmag:        TESS Magnitude
# COLUMN sy_kepmag:      Kepler Magnitude
# COLUMN rowupdate:      Date of Last Update
# COLUMN pl_pubdate:     Planetary Parameter Reference Publication Date
# COLUMN releasedate:    Release Date
# COLUMN pl_nnotes:      Number of Notes
# COLUMN st_nphot:       Number of Photometry Time Series
# COLUMN st_nrvc:        Number of Radial Velocity Time Series
# COLUMN st_nspec:       Number of Stellar Spectra Measurements
# COLUMN pl_nespec:      Number of Eclipse Spectra
# COLUMN pl_ntranspec:   Number of Transmission Spectra
# COLUMN pl_ndispec:     Number of Direct Imaging Spectra
#

El encabezado mÔs arriba estaba incluído en el archivo .CSV generado y se incluye aquí para reproducir la consulta. El dataset contiene información sobre los sistemas exoplanetarios detectados por la misión Kepler y el diccionario de datos se encuentra en línea (IPAC, n.d.d) explicando en mÔs profundidad la semÔntica de las variables.

Todos los archivos necesarios para este trabajo se encuentran en el repositorio de GitHub del autor (Nicolau, Jorge, n.d.) y se pueden descargar desde allí para reproducir este anÔlisis, incluyendo el dataset keplerexoplanets.csv que a continuación se carga.

library(readr)

# Cargar los datos del archivo CSV
kepler_data <- read_csv("keplerexoplanets.csv")

Estructura de los Datos

library(knitr)

# Capturar la salida de str() como texto
str_output <- capture.output(str(kepler_data, list.len = Inf, give.attr=FALSE))

# Convertir la salida en un data frame para formatearla como tabla
str_df <- data.frame(
  Details = str_output,
  stringsAsFactors = FALSE
)

# Mostrar la salida en formato de tabla con kable
kable(str_df, col.names = c("Tipo de datos y previsualización"), align = "l")
Tipo de datos y previsualización
spc_tbl_ [28,217 Ɨ 121] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ pl_name : chr [1:28217] ā€œ2MASS J19383260+4603591 bā€ ā€œ2MASS J19383260+4603591 bā€ ā€œKIC 10001893 bā€ ā€œKIC 10001893 cā€ …
$ hostname : chr [1:28217] ā€œ2MASS J19383260+4603591ā€ ā€œ2MASS J19383260+4603591ā€ ā€œKIC 10001893ā€ ā€œKIC 10001893ā€ …
$ pl_letter : chr [1:28217] ā€œbā€ ā€œbā€ ā€œbā€ ā€œcā€ …
$ hd_name : logi [1:28217] NA NA NA NA NA NA …
$ hip_name : chr [1:28217] NA NA NA NA …
$ tic_id : chr [1:28217] ā€œTIC 271164763ā€ ā€œTIC 271164763ā€ ā€œTIC 158488181ā€ ā€œTIC 158488181ā€ …
$ gaia_id : chr [1:28217] ā€œGaia DR2 2080063931448749824ā€ ā€œGaia DR2 2080063931448749824ā€ ā€œGaia DR2 2130473176626619136ā€ ā€œGaia DR2 2130473176626619136ā€ …
$ default_flag : num [1:28217] 1 0 1 1 1 1 1 1 0 0 …
$ sy_snum : num [1:28217] 2 2 1 1 1 1 1 1 1 1 …
$ sy_pnum : num [1:28217] 3 3 3 3 3 1 1 1 2 2 …
$ sy_mnum : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ cb_flag : num [1:28217] 1 1 0 0 0 0 0 0 0 0 …
$ discoverymethod: chr [1:28217] ā€œEclipse Timing Variationsā€ ā€œEclipse Timing Variationsā€ ā€œOrbital Brightness Modulationā€ ā€œOrbital Brightness Modulationā€ …
$ disc_year : num [1:28217] 2015 2015 2014 2014 2014 …
$ disc_refname : chr [1:28217] ā€œBaraā€| truncated ā€œBaraā€| truncated ā€œSā€| truncated ā€œSā€| truncated …
$ disc_pubdate : chr [1:28217] ā€œ2015-05ā€ ā€œ2015-05ā€ ā€œ2014-10ā€ ā€œ2014-10ā€ …
$ disc_locale : chr [1:28217] ā€œSpaceā€ ā€œSpaceā€ ā€œSpaceā€ ā€œSpaceā€ …
$ disc_facility : chr [1:28217] ā€œKeplerā€ ā€œKeplerā€ ā€œKeplerā€ ā€œKeplerā€ …
$ disc_telescope : chr [1:28217] ā€œ0.95 m Kepler Telescopeā€ ā€œ0.95 m Kepler Telescopeā€ ā€œ0.95 m Kepler Telescopeā€ ā€œ0.95 m Kepler Telescopeā€ …
$ disc_instrument: chr [1:28217] ā€œKepler CCD Arrayā€ ā€œKepler CCD Arrayā€ ā€œKepler CCD Arrayā€ ā€œKepler CCD Arrayā€ …
$ rv_flag : num [1:28217] 0 0 0 0 0 1 0 0 0 0 …
$ pul_flag : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ ptv_flag : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ tran_flag : num [1:28217] 0 0 0 0 0 0 1 1 1 1 …
$ ast_flag : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ obm_flag : num [1:28217] 0 0 1 1 1 1 0 0 0 0 …
$ micro_flag : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ etv_flag : num [1:28217] 1 1 0 0 0 0 0 0 0 0 …
$ ima_flag : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ dkin_flag : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ soltype : chr [1:28217] ā€œPublished Confirmedā€ ā€œPublished Confirmedā€ ā€œPublished Confirmedā€ ā€œPublished Confirmedā€ …
$ pl_controv_flag: num [1:28217] 0 0 1 1 1 0 0 0 0 0 …
$ pl_refname : chr [1:28217] ā€œEsmeā€| truncated ā€œBaraā€| truncated ā€œSā€| truncated ā€œSā€| truncated …
$ pl_orbper : num [1:28217] 406 416 0.22 0.325 0.812 …
$ pl_orbsmax : num [1:28217] NA 0.92 NA NA NA …
$ pl_rade : num [1:28217] NA NA NA NA NA NA 5.5 6.9 7.23 6.7 …
$ pl_radj : num [1:28217] NA NA NA NA NA NA 0.491 0.616 0.645 0.598 …
$ pl_masse : num [1:28217] NA 604 NA NA NA …
$ pl_massj : num [1:28217] NA 1.9 NA NA NA NA NA NA NA NA …
$ pl_msinie : num [1:28217] 591 NA NA NA NA …
$ pl_msinij : num [1:28217] 1.86 NA NA NA NA 2 NA NA NA NA …
$ pl_cmasse : logi [1:28217] NA NA NA NA NA NA …
$ pl_cmassj : logi [1:28217] NA NA NA NA NA NA …
$ pl_bmasse : num [1:28217] 591 604 NA NA NA …
$ pl_bmassj : num [1:28217] 1.86 1.9 NA NA NA 2 NA NA NA NA …
$ pl_bmassprov : chr [1:28217] ā€œMsiniā€ ā€œMassā€ NA NA …
$ pl_dens : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ pl_orbeccen : num [1:28217] 0.33 NA NA NA NA NA NA NA 0 0 …
$ pl_insol : num [1:28217] NA NA NA NA NA NA NA NA 2.14 2.14 …
$ pl_eqt : num [1:28217] NA NA NA NA NA NA NA NA 308 308 …
$ pl_orbincl : num [1:28217] NA NA NA NA NA …
$ pl_tranmid : num [1:28217] NA NA NA NA NA …
$ pl_tsystemref : chr [1:28217] ā€œBJD-TDBā€ NA NA NA …
$ ttv_flag : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ pl_imppar : num [1:28217] NA NA NA NA NA NA NA NA 0.424 0.212 …
$ pl_trandep : num [1:28217] NA NA NA NA NA …
$ pl_trandur : num [1:28217] NA NA NA NA NA …
$ pl_ratdor : num [1:28217] NA NA NA NA NA …
$ pl_ratror : num [1:28217] NA NA NA NA NA …
$ pl_occdep : logi [1:28217] NA NA NA NA NA NA …
$ pl_orbtper : num [1:28217] 2455131 NA NA NA NA …
$ pl_orblper : num [1:28217] 302 NA NA NA NA NA NA NA NA NA …
$ pl_rvamp : num [1:28217] NA NA NA NA NA …
$ pl_projobliq : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ pl_trueobliq : logi [1:28217] NA NA NA NA NA NA …
$ st_refname : chr [1:28217] ā€œEsmeā€| truncated ā€œBaraā€| truncated ā€œSā€| truncated ā€œSā€| truncated …
$ st_spectype : chr [1:28217] NA NA NA NA …
$ st_teff : num [1:28217] 29564 NA 27500 27500 27500 …
$ st_rad : num [1:28217] 0.2 NA NA NA NA 1.57 1.01 1.01 1.39 1.39 …
$ st_mass : num [1:28217] 0.48 0.48 NA NA NA 1.22 1.01 0.98 1.03 1.03 …
$ st_met : num [1:28217] NA NA NA NA NA 0.01 -0.04 -0.42 -0.38 -0.38 …
$ st_metratio : chr [1:28217] NA NA NA NA …
$ st_lum : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ st_logg : num [1:28217] 5.51 NA 5.35 5.35 5.35 4.09 4.42 4.44 4.16 4.16 …
$ st_age : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ st_dens : num [1:28217] NA NA NA NA NA …
$ st_vsin : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ st_rotp : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ st_radv : num [1:28217] NA NA 25 25 25 NA NA NA NA NA …
$ sy_refname : chr [1:28217] ā€œTICv8ā€ ā€œTICv8ā€ ā€œTICv8ā€ ā€œTICv8ā€ …
$ rastr : chr [1:28217] ā€œ19h38m32.62sā€ ā€œ19h38m32.62sā€ ā€œ19h09m33.42sā€ ā€œ19h09m33.42sā€ …
$ ra : num [1:28217] 295 295 287 287 287 …
$ decstr : chr [1:28217] ā€œ+46d03m59.07sā€ ā€œ+46d03m59.07sā€ ā€œ+46d59m04.02sā€ ā€œ+46d59m04.02sā€ …
$ dec : num [1:28217] 46.1 46.1 47 47 47 …
$ glat : num [1:28217] 11.7 11.7 16.6 16.6 16.6 …
$ glon : num [1:28217] 79 79 77.7 77.7 77.7 …
$ elat : num [1:28217] 65.7 65.7 68.4 68.4 68.4 …
$ elon : num [1:28217] 315 315 304 304 304 …
$ sy_pm : num [1:28217] 6.97 6.97 6.01 6.01 6.01 …
$ sy_pmra : num [1:28217] 5.2 5.2 1.32 1.32 1.32 …
$ sy_pmdec : num [1:28217] -4.64 -4.64 -5.86 -5.86 -5.86 …
$ sy_dist : num [1:28217] 396 396 1673 1673 1673 …
$ sy_plx : num [1:28217] 2.495 2.495 0.569 0.569 0.569 …
$ sy_bmag : num [1:28217] 12.1 12.1 15.1 15.1 15.1 …
$ sy_vmag : num [1:28217] 12.7 12.7 15.8 15.8 15.8 …
$ sy_jmag : num [1:28217] 12.8 12.8 16.4 16.4 16.4 …
$ sy_hmag : num [1:28217] 12.9 12.9 15.7 15.7 15.7 …
$ sy_kmag : num [1:28217] 13 13 16.6 16.6 16.6 …
$ sy_umag : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ sy_gmag : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ sy_rmag : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ sy_imag : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ sy_zmag : num [1:28217] NA NA NA NA NA NA NA NA NA NA …
$ sy_w1mag : num [1:28217] 12.9 12.9 NA NA NA …
$ sy_w2mag : num [1:28217] 12.9 12.9 NA NA NA …
$ sy_w3mag : num [1:28217] 12.7 12.7 NA NA NA …
$ sy_w4mag : num [1:28217] 9.2 9.2 NA NA NA …
$ sy_gaiamag : num [1:28217] 12.1 12.1 15.7 15.7 15.7 …
$ sy_icmag : logi [1:28217] NA NA NA NA NA NA …
$ sy_tmag : num [1:28217] 12.5 12.5 16 16 16 …
$ sy_kepmag : num [1:28217] 12.3 12.3 15.8 15.8 15.8 …
$ rowupdate : Date[1:28217], format: ā€œ2022-04-19ā€ ā€œ2015-06-04ā€ …
$ pl_pubdate : chr [1:28217] ā€œ2022-04ā€ ā€œ2015-05ā€ ā€œ2014-10ā€ ā€œ2014-10ā€ …
$ releasedate : Date[1:28217], format: ā€œ2022-04-19ā€ ā€œ2015-06-04ā€ …
$ pl_nnotes : num [1:28217] 1 1 1 1 1 1 2 1 2 2 …
$ st_nphot : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ st_nrvc : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ st_nspec : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ pl_nespec : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ pl_ntranspec : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …
$ pl_ndispec : num [1:28217] 0 0 0 0 0 0 0 0 0 0 …

Para el anƔlisis se considerarƔn solo los exoplanetas confirmados y se eliminarƔn las columnas no relevantes para el anƔlisis.

Para reducir la dimensionalidad del problema, a continuación se eliminan las columnas con referencias a sitios web no relevantes para el anÔlisis. También se eliminan los datos de referencia de los planetas, estrellas y sistemas no relevantes para el anÔlisis tales como referencias a catÔlogos externos de estrellas y sistemas, información de publicación del descubrimiento, información de detección, información de fotometría, banderas de organización interna del dataset, información del sistema planetario y detalles técnicos de la detección.

Para reducir la cantidad de registros del dataset y como se busca predecir la habitabilidad de los exoplanetas en sistemas similares al Solar, se filtran los sistemas con estrellas de tamaƱo similar al Sol (0.9 a 1.1 radios solares). Hay muchas entradas con valores faltantes en las columnas de tipo espectral de las estrellas (la mayorĆ­a) que serĆ­a un mejor indicador para determinarl la zona habitable, por eso se toma como criterio de filtro el tamaƱo de las estrellas. AdemĆ”s se consideraran para la muesta solo los exoplanetas publicados en la literatura cientĆ­fica, por lo que se filtra por ā€œPublished Confirmedā€ en la columna soltype.

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# PARTE 1 - FILTRO DE DATOS
# Seleccionar los sistemas con estrellas de tamaƱo
# similar al Sol (0.9 a 1.1 radios solares)
kepler_data <- filter(kepler_data, st_rad >= 0.9 & st_rad <= 1.1)

# Seleccionar solo los exoplanetas publicados en la literatura cientĆ­fica
kepler_data <- filter(kepler_data, soltype == "Published Confirmed")

# PARTE 2 - REDUCCION DE LA DIMENSIONALIDAD
# Eliminar columnas de referencias a sitios web
kepler_data <- subset(kepler_data, select = c(-disc_refname, -pl_refname, -st_refname, -sy_refname))

# Eliminar columnas de id de catalogos externos de estrellas y sistemas
kepler_data <- subset(kepler_data, select = c(-tic_id, -gaia_id))

# Eliminar información referente a la publicación del descubrimiento
# así como la información del instrumento utilizado, para todos es Kepler
kepler_data <- subset(kepler_data, select = c(-disc_year, -disc_pubdate, -disc_locale, -disc_facility, -disc_telescope, -disc_instrument, -rowupdate, -pl_pubdate, -releasedate))

# Eliminar columnas con información referente a la detección
kepler_data <- subset(kepler_data, select = c(-rv_flag, -pul_flag, -ptv_flag, -tran_flag, -ast_flag, -obm_flag, -micro_flag, -etv_flag, -ima_flag, -dkin_flag))

# Eliminar columnas con información de fotometria
kepler_data <- subset(kepler_data, select = c(-sy_bmag, -sy_vmag, -sy_jmag, -sy_hmag, -sy_kmag, -sy_umag, -sy_gmag, -sy_rmag, -sy_imag, -sy_zmag, -sy_w1mag, -sy_w2mag, -sy_w3mag, -sy_w4mag, -sy_gaiamag, -sy_icmag, -sy_tmag, -sy_kepmag))

# Eliminar banderas de organización interna del dataset
kepler_data <- subset(kepler_data, select = c(-pl_nnotes, -pl_controv_flag, -default_flag))

# Eliminar columnas con información del sistema planetario
# y detalles técnicos de la detección
kepler_data <- subset(kepler_data, select = c(-sy_mnum, -pl_ndispec))

# Eliminar columnas con información adicional de fotometria
kepler_data <- subset( kepler_data, select = c(-st_nphot, -st_nrvc, -st_nspec, -pl_nespec, -pl_ntranspec))

El dataset resultante se guarda en un archivo CSV llamado keplerfiltered.csv. El dataset resultante contiene 2547 registros y 68 columnas.

Las columnas en el dataset filtrado, y su descripción extraída del diccionario de datos (IPAC, n.d.d), son las siguientes:

library(dplyr)
library(knitr)

# Ordenar las columnas alfabƩticamente
kepler_data <- kepler_data[, order(names(kepler_data))]

# Copiar el nombre de las columnas a un data frame
column_names <- data.frame(
  Column = names(kepler_data),
  stringsAsFactors = FALSE
)

# Agregar una columna con la descripción de la variable
# Fuente: https://exoplanetarchive.ipac.caltech.edu/docs/API_PS_columns.html
column_names <- column_names %>%
  mutate(Description = c(
    "cb_flag: Flag de circumbinario (el planeta orbita un sistema binario)",
    "dec: Declinación de la estrella (en grados decimales)",
    "decstr: Declinación de la estrella (en grados sexagesimales)",
    "discoverymethod: MƩtodo de descubrimiento del planeta",
    "elat: Latitud eclĆ­ptica de la estrella (en grados decimales)",
    "elon: Longitud eclĆ­ptica de la estrella (en grados decimales)",
    "glat: Latitud galƔctica de la estrella (en grados decimales)",
    "glon: Longitud galƔctica de la estrella (en grados decimales)",
    "hd_name: Nombre del sistema estelar en el catƔlogo Henry Draper",
    "hip_name: Nombre del sistema estelar en el catƔlogo Hipparcos",
    "hostname: Nombre del sistema estelar utilizado en la literatura",
    "pl_bmasse: Mejor estimación de la masa del planeta (en masas terrestres)",
    "pl_bmassj: Mejor estimación de la masa del planeta (en masas jovianas)",
    "pl_bmassprov: Proveedor de la mejor estimación de la masa del planeta (mínima o proyectada)",
    "pl_cmasse: Masa mĆ­nima proyectada (en masas terrestres)",
    "pl_cmassj: Masa mĆ­nima proyectada (en masas jovianas)",
    "pl_dens: Densidad del planeta (en g/cm³)",
    "pl_eqt: Temperatura de equilibrio del planeta considero como un cuerpo oscur (en grados K)",
    "pl_imppar: ParƔmetro de impacto del planeta como distancia proyectada del centro del planeta al centro de la estrella (en radios estelares)",
    "pl_insol: Insolación del planeta en terminos la insolación de la tierra (en W/m²)",
    "pl_letter: Letra del planeta en el sistema (primer planeta es b)",
    "pl_masse: Masa del planeta (en masas terrestres)",
    "pl_massj: Masa del planeta (en masas jovianas)",
    "pl_msinie: Mƭnimo de masa medida por el mƩtodo de velocidad radial (en masas terrestres)",
    "pl_msinij: Mƭnimo de masa medida por el mƩtodo de velocidad radial (en masas jovianas)",
    "pl_occdep: Profundidad del eclipse del planeta en terminos de el flujo relativo decreciente frente a su estrella (en %)",
    "pl_orbeccen: Excentricidad orbital del planeta",
    "pl_orbincl: Inclinación orbital del planeta respecto de la línea de visión desde la Tierra (en grados)",
    "pl_orblper: El argumento del periastro del planeta (en grados)",
    "pl_orbper: Periodo orbital del planeta (en dĆ­as)",
    "pl_orbsmax: Distancia orbital semieje mayor (en UA)",
    "pl_orbtper: El momento del paso del planeta por el periastro (en grados)",
    "pl_projobliq: Inclinación proyectada del planeta respecto de la línea de visión desde la Tierra (en grados)",
    "pl_rade: Radio del planeta (en radios terrestres)",
    "pl_radj: Radio del planeta (en radios jovianos)",
    "pl_ratdor: cociente del semieje orbital mayor sobre el radio estelar",
    "pl_ratror: cociente del radio del planeta sobre el radio estelar",
    "pl_rvamp: Amplitud de la velocidad radial del planeta (en m/s)",
    "pl_trandep: Profundidad del trƔnsito del planeta en terminos de el flujo relativo decreciente frente a su estrella (en %)",
    "pl_trandur: Duración del trÔnsito del planeta (en horas)",
    "pl_tranmid: Tiempo de trƔnsito medio del planeta respecto de su estrella (en dƭas)",
    "pl_trueobliq: Inclinación verdadera del planeta respecto de la línea de visión desde la Tierra (en grados)",
    "pl_tsystemref: Sistema de Tiempo de Referencia del sistema planetario",
    "ra: Ascensión recta de la estrella (en grados decimales)",
    "rastr: Ascensión recta de la estrella (en grados sexagesimales)",
    "soltype: Disposición del planeta según el conjunto de parÔmetros planetarios dado",
    "st_age: Edad de la estrella (en Ga, gigaaƱos, o miles de millones de aƱos)",
    "st_dens: Densidad de la estrella (en g/cm³)",
    "st_logg: Gravedad superficial de la estrella (en logaritmo en base 10 de cm/s²)",
    "st_lum: Luminosidad de la estrella (en logartima en base 10 de unidades solares)",
    "st_mass: Masa de la estrella (en masas solares)",
    "st_met: Medición del contenido de metales en la fotosfera de la estrella en comparación con el contenido de hidrógeno",
    "st_metratio: Relación de metalicidad de la estrella",
    "st_rad: Radio de la estrella (en radios solares)",
    "st_radv: Velocidad radial de la estrella (en km/s)",
    "st_rotp: Periodo de rotación de la estrella (en días)",
    "st_spectype: Tipo espectral de la estrella segĆŗn el sistema Morgan-Keenan",
    "st_teff: Temperatura efectiva de la estrella (en grados K)",
    "st_vsin: Velocidad de rotación de la estrella (en km/s)",
    "sy_dist: Distancia del sistema (en parsecs)",
    "sy_plx: Paralaje del sistema (en miliarcosegundos)",
    "sy_pm: Movimiento propio del sistema (en miliarcosegundos/aƱo)",
    "sy_pmdec: Movimiento propio del sistema en declinación (en miliarcosegundos/año)",
    "sy_pmra: Movimiento propio del sistema en ascensión recta (en miliarcosegundos/año)",
    "sy_pnum: NĆŗmero de planetas en el sistema",
    "sy_snum: NĆŗmero de estrellas en el sistema",
    "ttv_flag: Flag de trƔnsito de tiempo variante",
    "pl_name: Nombre del planeta"))

# Eliminar de la columna Description el prefijo de la variable
column_names$Description <- gsub("^.*: ", "", column_names$Description)

# Elimina la columna con el numero de fila
rownames(column_names) <- NULL

kable(column_names, col.names = c("Variable", "Descripción"), align = "l")
Variable Descripción
cb_flag Flag de circumbinario (el planeta orbita un sistema binario)
dec Declinación de la estrella (en grados decimales)
decstr Declinación de la estrella (en grados sexagesimales)
discoverymethod MƩtodo de descubrimiento del planeta
elat Latitud eclĆ­ptica de la estrella (en grados decimales)
elon Longitud eclĆ­ptica de la estrella (en grados decimales)
glat Latitud galƔctica de la estrella (en grados decimales)
glon Longitud galƔctica de la estrella (en grados decimales)
hd_name Nombre del sistema estelar en el catƔlogo Henry Draper
hip_name Nombre del sistema estelar en el catƔlogo Hipparcos
hostname Nombre del sistema estelar utilizado en la literatura
pl_bmasse Mejor estimación de la masa del planeta (en masas terrestres)
pl_bmassj Mejor estimación de la masa del planeta (en masas jovianas)
pl_bmassprov Proveedor de la mejor estimación de la masa del planeta (mínima o proyectada)
pl_cmasse Masa mĆ­nima proyectada (en masas terrestres)
pl_cmassj Masa mĆ­nima proyectada (en masas jovianas)
pl_dens Densidad del planeta (en g/cm³)
pl_eqt Temperatura de equilibrio del planeta considero como un cuerpo oscur (en grados K)
pl_imppar ParƔmetro de impacto del planeta como distancia proyectada del centro del planeta al centro de la estrella (en radios estelares)
pl_insol Insolación del planeta en terminos la insolación de la tierra (en W/m²)
pl_letter Letra del planeta en el sistema (primer planeta es b)
pl_masse Masa del planeta (en masas terrestres)
pl_massj Masa del planeta (en masas jovianas)
pl_msinie Mƭnimo de masa medida por el mƩtodo de velocidad radial (en masas terrestres)
pl_msinij Mƭnimo de masa medida por el mƩtodo de velocidad radial (en masas jovianas)
pl_name Profundidad del eclipse del planeta en terminos de el flujo relativo decreciente frente a su estrella (en %)
pl_occdep Excentricidad orbital del planeta
pl_orbeccen Inclinación orbital del planeta respecto de la línea de visión desde la Tierra (en grados)
pl_orbincl El argumento del periastro del planeta (en grados)
pl_orblper Periodo orbital del planeta (en dĆ­as)
pl_orbper Distancia orbital semieje mayor (en UA)
pl_orbsmax El momento del paso del planeta por el periastro (en grados)
pl_orbtper Inclinación proyectada del planeta respecto de la línea de visión desde la Tierra (en grados)
pl_projobliq Radio del planeta (en radios terrestres)
pl_rade Radio del planeta (en radios jovianos)
pl_radj cociente del semieje orbital mayor sobre el radio estelar
pl_ratdor cociente del radio del planeta sobre el radio estelar
pl_ratror Amplitud de la velocidad radial del planeta (en m/s)
pl_rvamp Profundidad del trƔnsito del planeta en terminos de el flujo relativo decreciente frente a su estrella (en %)
pl_trandep Duración del trÔnsito del planeta (en horas)
pl_trandur Tiempo de trƔnsito medio del planeta respecto de su estrella (en dƭas)
pl_tranmid Inclinación verdadera del planeta respecto de la línea de visión desde la Tierra (en grados)
pl_trueobliq Sistema de Tiempo de Referencia del sistema planetario
pl_tsystemref Ascensión recta de la estrella (en grados decimales)
ra Ascensión recta de la estrella (en grados sexagesimales)
rastr Disposición del planeta según el conjunto de parÔmetros planetarios dado
soltype Edad de la estrella (en Ga, gigaaƱos, o miles de millones de aƱos)
st_age Densidad de la estrella (en g/cm³)
st_dens Gravedad superficial de la estrella (en logaritmo en base 10 de cm/s²)
st_logg Luminosidad de la estrella (en logartima en base 10 de unidades solares)
st_lum Masa de la estrella (en masas solares)
st_mass Medición del contenido de metales en la fotosfera de la estrella en comparación con el contenido de hidrógeno
st_met Relación de metalicidad de la estrella
st_metratio Radio de la estrella (en radios solares)
st_rad Velocidad radial de la estrella (en km/s)
st_radv Periodo de rotación de la estrella (en días)
st_rotp Tipo espectral de la estrella segĆŗn el sistema Morgan-Keenan
st_spectype Temperatura efectiva de la estrella (en grados K)
st_teff Velocidad de rotación de la estrella (en km/s)
st_vsin Distancia del sistema (en parsecs)
sy_dist Paralaje del sistema (en miliarcosegundos)
sy_plx Movimiento propio del sistema (en miliarcosegundos/aƱo)
sy_pm Movimiento propio del sistema en declinación (en miliarcosegundos/año)
sy_pmdec Movimiento propio del sistema en ascensión recta (en miliarcosegundos/año)
sy_pmra NĆŗmero de planetas en el sistema
sy_pnum NĆŗmero de estrellas en el sistema
sy_snum Flag de trƔnsito de tiempo variante
ttv_flag Nombre del planeta
# Guardar los datos filtrados en un archivo CSV
write_csv(kepler_data, "keplerfiltered.csv")

# Guardar la estructura de las columnas en un archivo CSV
write_csv(column_names, "keplerdatadictionary.csv")

AnƔlisis exploratorio de datos

Para realizar un anƔlisis exploratorio de los datos, se cargan el nuevo dataset (puede comenzarse el anƔlisis en este punto porque el dataset preprocesado estƔ almacenado en el archivo keplerfiltered.csv) y se realizan algunas visualizaciones y cƔlculos descriptivos.

library(ggplot2)
library(dplyr)
library(readr)
library(skimr)
library(knitr)

# Leer los datos completos
kepler_data <- read_csv("keplerfiltered.csv")

# Resumen de los datos con skimr solo variables numƩricas
kepler_data_num <- kepler_data %>%
  select_if(is.numeric)

# Generar resumen con skimr 
resumen <- skim(kepler_data_num) 

# Ordenar por nombre de variable
resumen <- resumen[order(resumen$skim_variable), ]

# Filtrar columnas relevantes
resumen <- subset(resumen, select = c(
    skim_variable, numeric.mean, numeric.sd, numeric.p0, numeric.p25, 
    numeric.p50, numeric.p75, numeric.p100, numeric.hist))

# Mostrar tabla formateada
kable(resumen, format = "markdown", digits = 4,
      col.names = c("Variable", "Media", "Des.Est.", "Mƭn.", "P25", "Mediana", "P75", "MƔx.","Hist.")
      )
Variable Media Des.Est. Mƭn. P25 Mediana P75 MƔx. Hist.
cb_flag 0.0024 0.0485 0.0000 0.0000 0.0000 0.0000 1.0000 ▇▁▁▁▁
dec 44.2366 3.6695 36.5773 41.3738 44.3155 47.1127 52.1491 ā–…ā–‡ā–‡ā–‡ā–ƒ
elat 64.7746 3.6360 57.6374 61.8480 64.7690 67.5246 72.4913 ā–…ā–‡ā–‡ā–†ā–ƒ
elon 307.9950 8.0410 288.7515 302.3200 308.2267 314.3187 323.9048 ā–‚ā–…ā–‡ā–‡ā–ƒ
glat 12.9778 3.4193 5.9607 10.4051 12.6586 15.7959 21.1430 ā–ƒā–‡ā–‡ā–…ā–‚
glon 76.3718 3.6938 68.2330 73.3769 76.4011 79.3326 84.3822 ā–ƒā–‡ā–‡ā–‡ā–ƒ
pl_bmasse 328.4638 1965.7298 0.7600 6.0133 18.4000 95.1000 25426.4000 ▇▁▁▁▁
pl_bmassj 1.0335 6.1849 0.0024 0.0190 0.0580 0.2992 80.0000 ▇▁▁▁▁
pl_dens 4.2419 8.2500 0.0300 0.6950 2.1300 5.5250 77.7000 ▇▁▁▁▁
pl_eqt 938.0333 564.4973 251.0000 438.7500 861.5000 1146.5000 2188.0000 ā–‡ā–†ā–ƒā–‚ā–‚
pl_imppar 0.3940 0.2883 0.0000 0.1500 0.3300 0.6200 1.4830 ā–‡ā–…ā–ƒā–ā–
pl_insol 299.3455 598.0846 0.5900 26.9900 96.9450 304.9000 4849.2600 ▇▁▁▁▁
pl_masse 328.4638 1965.7298 0.7600 6.0133 18.4000 95.1000 25426.4000 ▇▁▁▁▁
pl_massj 1.0335 6.1849 0.0024 0.0190 0.0580 0.2992 80.0000 ▇▁▁▁▁
pl_msinie 47.8000 NA 47.8000 47.8000 47.8000 47.8000 47.8000 ▁▁▇▁▁
pl_msinij 0.1500 NA 0.1500 0.1500 0.1500 0.1500 0.1500 ▁▁▇▁▁
pl_orbeccen 0.1177 0.1778 0.0000 0.0105 0.0420 0.1350 0.8380 ▇▁▁▁▁
pl_orbincl 88.6474 1.7458 82.2140 87.8060 89.1855 89.7905 93.1500 ā–ā–ā–ƒā–‡ā–
pl_orblper 146.9116 142.8866 -163.0000 49.2755 154.7000 261.6000 357.0300 ▂▅▆▅▇
pl_orbper 31.4997 62.6948 0.5383 5.6992 13.0314 33.6013 1322.3000 ▇▁▁▁▁
pl_orbsmax 0.1834 0.2236 0.0168 0.0655 0.1091 0.2170 2.4200 ▇▁▁▁▁
pl_orbtper 2455003.7584 106.5838 2454935.8000 2454950.2605 2454958.2168 2455011.7148 2455162.8000 ▇▁▁▁▂
pl_projobliq -35.1429 60.4109 -135.0000 -61.5000 0.0000 4.0000 4.0000 ā–ƒā–ā–ā–ā–‡
pl_rade 2.9323 2.4308 0.4000 1.6230 2.3700 3.0240 30.8000 ▇▁▁▁▁
pl_radj 0.2616 0.2169 0.0360 0.1450 0.2110 0.2700 2.7480 ▇▁▁▁▁
pl_ratdor 60.9640 83.9114 3.1000 11.5600 30.3000 78.3000 576.7000 ▇▁▁▁▁
pl_ratror 0.0288 0.0263 0.0056 0.0147 0.0213 0.0286 0.2873 ▇▁▁▁▁
pl_rvamp 47.4204 88.2590 0.2800 2.1000 3.7200 71.9000 419.5000 ▇▂▁▁▁
pl_trandep 0.1813 0.3624 0.0060 0.0481 0.0705 0.1063 2.2620 ▇▁▁▁▁
pl_trandur 4.3811 2.2576 0.8244 2.8100 3.8212 5.4291 18.8860 ▇▅▁▁▁
pl_tranmid 2455003.7508 121.7668 2454832.9010 2454967.1167 2454973.9640 2455004.6853 2457959.9661 ▇▁▁▁▁
ra 291.3112 4.6829 280.2066 287.6980 291.4314 295.0027 301.5430 ▂▆▇▇▂
st_age 4.5799 1.7720 0.1050 3.8000 4.2700 4.7900 11.9000 ▁▇▂▁▁
st_dens 1.6002 1.3618 0.0044 1.2072 1.4497 1.6696 19.9316 ▇▁▁▁▁
st_logg 4.4442 0.0556 4.2100 4.4100 4.4500 4.4800 5.0000 ▁▇▁▁▁
st_lum -0.0616 0.1126 -0.4090 -0.1360 -0.0630 0.0280 0.2200 ā–ā–ƒā–‡ā–†ā–‚
st_mass 0.9901 0.0642 0.6900 0.9500 0.9900 1.0300 1.2500 ā–ā–ā–‡ā–ƒā–
st_met 0.0199 0.1570 -0.8160 -0.0400 0.0200 0.1000 0.4800 ā–ā–ā–ƒā–‡ā–
st_rad 0.9922 0.0619 0.9000 0.9400 0.9900 1.0500 1.1000 ▇▅▅▅▅
st_radv -34.3600 29.8608 -98.9300 -57.1600 -24.7600 -20.9300 9.9600 ā–‚ā–ƒā–‚ā–‡ā–ƒ
st_rotp 12.2225 5.6116 4.6900 10.1775 11.8900 14.3225 22.0500 ā–ƒā–ā–‡ā–‚ā–‚
st_teff 5684.9878 236.0809 4388.3900 5549.5000 5688.0000 5833.5000 6484.0000 ▁▁▆▇▁
st_vsin 2.2671 1.9863 0.3000 0.5000 2.0000 3.0000 10.4000 ā–‡ā–ƒā–ā–ā–
sy_dist 875.6348 389.0261 68.1730 625.3390 860.3910 1101.1000 2879.8300 ā–ƒā–‡ā–‚ā–ā–
sy_plx 1.4880 1.2326 0.3269 0.8774 1.1298 1.5694 14.6396 ▇▁▁▁▁
sy_pm 10.9292 9.0598 0.1586 4.5898 8.4847 14.5826 77.6183 ▇▂▁▁▁
sy_pmdec -3.2419 11.7992 -66.6869 -9.1002 -3.1269 2.5670 48.3025 ā–ā–ā–‡ā–ƒā–
sy_pmra -0.3364 7.1920 -49.3144 -3.5431 -0.4287 3.0154 32.8344 ▁▁▇▇▁
sy_pnum 2.0628 1.2462 1.0000 1.0000 2.0000 3.0000 6.0000 ▇▂▁▁▁
sy_snum 1.0271 0.1624 1.0000 1.0000 1.0000 1.0000 2.0000 ▇▁▁▁▁
ttv_flag 0.1496 0.3567 0.0000 0.0000 0.0000 0.0000 1.0000 ▇▁▁▁▂

AnƔlisis los parƔmetros numƩricos del dataset

En este anƔlisis preliminar se observan varias caracterƭsticas en los parƔmetros del conjunto de datos.

Las variables cb_flag y ttv_flag son binarias y presentan valores mayoritariamente en 0, ya que su media es baja (~0.0024 y ~0.1496, respectivamente). Esto indica un fuerte desbalance en los datos. AdemƔs, la variable sy_snum casi siempre toma el valor de 1, lo que sugiere que la mayorƭa de los sistemas tienen una sola estrella.

En cuanto a los parÔmetros de coordenadas celestes, las variables dec y ra (declinación y ascensión recta), así como elat, elon, glat y glon (latitudes y longitudes eclípticas y galÔcticas), muestran distribuciones relativamente centradas. elon tiene un rango amplio (288-323), mientras que glat y glon presentan valores bien concentrados en torno a la media, lo que sugiere la observación de un cúmulo estelar. La longitud eclíptica elon (288° a 324°) corresponde a la región de las constelaciones de Capricornio y Acuario, extendiéndose hacia Piscis, mientras que la latitud eclíptica elat (57° a 72°) es alta, indicando que estos objetos estÔn lejos del plano de la eclíptica y ubicados en el hemisferio norte eclíptico.

Dado que elat presenta valores elevados (muy por encima del plano de la eclíptica), esto indica que los objetos en el conjunto de datos no estÔn alineados con el disco principal del Sistema Solar, sino que se encuentran en una región mÔs inclinada del cielo. Esta Ôrea corresponde en parte a la región del Polo Norte Eclíptico, en la dirección de la constelación del Dragón (Draco).

Las variables pl_bmasse y pl_masse (masa en unidades terrestres), así como pl_bmassj y pl_massj (masa en unidades jovianas), muestran distribuciones sesgadas a la derecha, con valores mÔximos extremadamente grandes (hasta 25,426 masas terrestres). Hay una gran cantidad de valores pequeños y algunos valores atípicos muy altos. De manera similar, pl_rade (radio en radios terrestres) y pl_radj (radio en radios jovianos) presentan una distribución sesgada, con pocos valores grandes. La mediana de pl_rade es 2.37, lo que indica que la mayoría de los exoplanetas en el conjunto tienen mÔs del doble del tamaño de la Tierra.

En cuanto a la excentricidad orbital, pl_orbeccen es mayoritariamente cercana a 0, lo que sugiere que la mayoría de los exoplanetas tienen órbitas casi circulares. La inclinación orbital, representada por pl_orbincl, muestra una alta concentración en valores cercanos a 90°, lo que indica que la mayoría de los planetas tienen órbitas casi perpendiculares a la línea de visión. Esto es consistente con el método de detección predominante, el método de trÔnsito, que es mÔs efectivo para planetas que pasan frente a su estrella.

El período orbital (pl_orbper) presenta una mediana de ~13 días, aunque existen valores extremos de hasta 1,322 días, lo que indica una gran variabilidad en la duración de las órbitas. Por otro lado, la temperatura planetaria de equilibrio (pl_eqt) tiene una media de 938 K, con una distribución amplia (mínimo: 251 K, mÔximo: 2,188 K), lo que sugiere una mezcla de planetas fríos y extremadamente calientes.

Respecto a la densidad planetaria (pl_dens), la mediana es 2.13 g/cm³, con una gran variabilidad, lo que refleja una diversidad en la composición de los exoplanetas.

En cuanto a las características estelares, las variables st_mass y st_rad muestran que la mayoría de las estrellas en el conjunto tienen masas y radios similares al Sol (~1.0), lo que es coherente con el filtro aplicado en el preprocesamiento. La temperatura estelar efectiva (st_teff) tiene una media de 5,685 K, lo que es consistente con estrellas tipo G (similares al Sol). Si bien esto puede deberse al filtro aplicado, también estÔ relacionado con la composición y edad de las estrellas.

La variable st_logg (logaritmo en base 10 de la gravedad estelar superficial) se concentra en valores cercanos a 4.45, lo que es característico de estrellas en la secuencia principal dentro del ciclo de vida estelar. Por su parte, la luminosidad estelar (st_lum) tiene una distribución centrada alrededor de 0 en escala logarítmica, lo que indica que muchas de estas estrellas tienen luminosidades similares a la del Sol.

El parƔmetro sy_dist (distancia en parsecs del sistema estelar) varƭa considerablemente, con valores entre 68 pc y 2,879 pc. La mediana es ~860 pc, lo que indica que la mayorƭa de estos sistemas estƔn relativamente lejos (mƔs de 2,804 aƱos luz).

En cuanto al movimiento propio de las estrellas, las variables sy_pm, sy_pmra y sy_pmdec (movimiento propio del sistema estelar en milisegundos de arco por aƱo) estƔn centradas en 0, aunque algunas estrellas presentan movimientos mƔs rƔpidos.

El nĆŗmero de planetas por sistema (sy_pnum) tiene una mediana de 2, aunque algunos sistemas alcanzan hasta 6 planetas detectados.

Las variables pl_trandep y pl_trandur (profundidad y duración del trÔnsito) muestran una distribución sesgada, con la mayoría de los valores en el extremo inferior. Esto es esperable, ya que la mayoría de los trÔnsitos son poco profundos y de corta duración.

Por otro lado, la oblicuidad del eje de rotación del planeta (pl_projobliq) tiene una mediana en 0° (indicando que la mayoría de los planetas tienen un eje de rotación perpendicular a la eclíptica de su sistema), aunque se observan valores extremos de hasta -135°.

En general, muchas distribuciones en el conjunto de datos estƔn sesgadas, con valores extremos que podrƭan representar atƭpicos (outliers) o simplemente reflejar la diversidad de los exoplanetas. Los datos sobre masa y radio indican que la mayorƭa de los exoplanetas son relativamente pequeƱos, aunque existen algunos extremadamente grandes. La temperatura de los planetas varƭa ampliamente, lo que sugiere una gran diversidad en los tipos de exoplanetas.

Por Ćŗltimo, en cuanto a las estrellas, la mayorĆ­a son similares al Sol, aunque presentan algunas diferencias en edad y metalicidad, lo cual es esperable debido al filtro aplicado en el preprocesamiento.

Detención de valores faltantes

Se analiza la cantidad de valores faltantes en el dataset para identificar posibles problemas de calidad de datos.

library(tidyr)

# Calcular la cantidad de valores faltantes por columna
missing_values <- kepler_data %>%
  summarise_all(~sum(is.na(.))) %>%
  gather() %>%
  arrange(desc(value))

# Eliminar las columnas sin valores faltantes
missing_values <- missing_values %>%
  filter(value > 0)

# Total de columnas
total_rows <- nrow(missing_values)

# Calcular el punto medio
midpoint <- ceiling(total_rows / 2)

Valores Faltantes por Columna

ggplot(missing_values[1:midpoint,], aes(x = reorder(key, value), y = value)) +
  geom_bar(stat = "identity", fill = "skyblue", color = "darkblue", width = 0.5) + # Reducir ancho de las barras
  geom_text(aes(label = value), hjust = -0.2, size = 3) + # AƱadir valores al final de las barras
  coord_flip() +
  scale_y_continuous(expand = expansion(mult = c(0.01, 0.1))) + # AƱadir margen extra en el eje y
  labs(title = "",
       x = "Columna",
       y = "") +
  theme_minimal() +
  theme(
    axis.text.y = element_text(size = 10),   # Ajustar tamaƱo de texto en eje Y
    plot.title = element_text(hjust = 0.5)  # Centrar el tĆ­tulo
  )

# Crear un grƔfico de barras con los valores faltantes que no sean cero
# con la segunda mitad de las filas
ggplot(missing_values[(midpoint+1):total_rows,], aes(x = reorder(key, value), y = value)) +
  geom_bar(stat = "identity", fill = "skyblue", color = "darkblue", width = 0.5) + # Reducir ancho de las barras
  geom_text(aes(label = value), hjust = -0.2, size = 3) + # AƱadir valores al final de las barras
  coord_flip() +
  scale_y_continuous(expand = expansion(mult = c(0.01, 0.1))) + # AƱadir margen extra en el eje y
  labs(title = "",
       x = "",
       y = "Cantidad de Valores Faltantes") +
  theme_minimal() +
  theme(
    axis.text.y = element_text(size = 10),   # Ajustar tamaƱo de texto en eje Y
    plot.title = element_text(hjust = 0.5)  # Centrar el tĆ­tulo
  )

En el anÔlisis del dataset, se detectó una gran cantidad de valores faltantes en varias columnas, lo que probablemente se deba a la falta de estimaciones o mediciones para ciertos exoplanetas. Según los prefijos utilizados en las columnas del dataset, las variables pueden clasificarse en tres categorías principales: parÔmetros del planeta (con prefijo pl_), parÔmetros de la estrella (con prefijo st_) y parÔmetros del sistema (prefijo sy_).

Como parte del proceso, se analizarÔn las variables conocidas de los exoplanetas para identificar aquellas que puedan actuar como predictoras de las variables con valores faltantes. Por ejemplo, en el caso del radio del exoplaneta (representado por pl_radj en radios jovianos y pl_rade en radios terrestres), que presenta 886 valores faltantes, es posible estimarlo utilizando otras variables disponibles en el dataset. Algunas de estas incluyen el período orbital en días (pl_orbper, con 450 valores faltantes), el tiempo de conjunción (pl_tranmid, con 675 valores faltantes) y el logaritmo en base 10 de la gravedad superficial de la estrella del sistema planetario (st_logg, con 554 valores faltantes).

Para determinar cuÔles de estas variables tienen un mayor potencial como predictoras, se utilizarÔ la matriz de correlación, que permitirÔ identificar las relaciones mÔs significativas entre las variables numéricas del dataset. De esta manera, se seleccionarÔn aquellas que presenten una correlación positiva o negativa mÔs fuerte con la variable faltante, lo que facilitarÔ su estimación con un mayor grado de precisión.

Buscando correlaciones

Para elegir la mejor variable para realizar una regresión lineal se utiliza la correlación lineal simple (Pearson) para medir la relación lineal entre cada variable independiente y la dependiente. Se utilizar porque es posible que entre los parÔmetros planetarios haya una relación lineal simple. La limitación con esta metodología es que ignora la multicolinealidad y no considera relaciones no lineales. Se analiza la correlación entre las variables numéricas del dataset para identificar posibles relaciones entre ellas utilizando los métodos de Pearson (detección de correlaciones lineales). A través de esta matriz, se pueden detectar tanto correlaciones positivas (cuando un aumento en una variable estÔ asociado con un aumento en otra) como correlaciones negativas (cuando un aumento en una variable estÔ relacionado con una disminución en otra). Estas relaciones pueden ser útiles para entender patrones en los datos y seleccionar las mejores variables predictoras para modelos de estimación.

library(corrplot)
## corrplot 0.92 loaded
# Calcular la matriz de correlación
correlation_matrix_pearson <- cor(kepler_data_num, use="pairwise.complete.obs" , method = "pearson")
## Warning in cor(kepler_data_num, use = "pairwise.complete.obs", method =
## "pearson"): the standard deviation is zero
# Ordenar la matriz por nombre de columnas
correlation_matrix_pearson <- correlation_matrix_pearson[order(rownames(correlation_matrix_pearson)), order(colnames(correlation_matrix_pearson))]

# NĆŗmero de variables
n_vars <- ncol(correlation_matrix_pearson)
half <- ceiling(n_vars / 2)

Matriz de Correlación 1/3 (Pearson Cuadrante Superior)

# Parte 1: Primera mitad (diagonal superior)
correlation_matrix_pearson_sup <- correlation_matrix_pearson[1:half, 1:half]
corrplot(
  correlation_matrix_pearson_sup,
  method = "color",
  type = "upper",
  addCoef.col = "black",
  number.cex = 0.4,
  tl.cex = 0.5,
  tl.col = "black",
  col = colorRampPalette(c("indianred", "white", "steelblue"))(20),
  title = ""
)

Matriz de Correlación 2/3 (Pearson Cruce)

# Parte 2: Cruce entre la primera y segunda mitad
correlation_matrix_pearson_cross <- correlation_matrix_pearson[1:half, (half + 1):n_vars]
corrplot(
  correlation_matrix_pearson_cross,
  method = "color",
  type = "full",  # Mostrar todas las correlaciones en esta sección
  addCoef.col = "black",
  number.cex = 0.4,
  tl.cex = 0.5,
  tl.col = "black",
  col = colorRampPalette(c("indianred", "white", "steelblue"))(20),
  title = ""
)

Matriz de Correlación 3/3 (Pearson Cuadrante Inferior)

# Parte 3: Segunda mitad (diagonal inferior)
correlation_matrix_pearson_inf <- correlation_matrix_pearson[(half + 1):n_vars, (half + 1):n_vars]
corrplot(
  correlation_matrix_pearson_inf,
  method = "color",
  type = "upper",
  addCoef.col = "black",
  number.cex = 0.4,
  tl.cex = 0.5,
  tl.col = "black",
  col = colorRampPalette(c("indianred", "white", "steelblue"))(20),
  title = ""
)

La matriz de correlación es una herramienta fundamental en el anÔlisis de datos, ya que permite identificar relaciones lineales entre las variables numéricas del dataset. A través de esta matriz, se pueden detectar tanto correlaciones positivas (cuando un aumento en una variable estÔ asociado con un aumento en otra) como correlaciones negativas (cuando un aumento en una variable estÔ relacionado con una disminución en otra). Estas relaciones pueden ser útiles para entender patrones en los datos y seleccionar las mejores variables predictoras para modelos de estimación.

Un ejemplo de estas correlaciones se observa en la relación entre el cociente del semieje orbital mayor y el período orbital (pl_ratdor), el cual muestra una correlación positiva con el período orbital (pl_orbper). Esto sugiere que a medida que el período orbital aumenta, también lo hace este cociente. En contraste, pl_ratdor presenta una correlación negativa con la temperatura de equilibrio del exoplaneta (pl_eqt), lo que indica que los exoplanetas con períodos orbitales largos tienden a tener temperaturas mÔs bajas, lo cual es esperable, ya que suelen estar mÔs alejados de su estrella anfitriona.

En cuanto a la variable que se seleccionó como variable objetivo en el anÔlisis previo, el radio del exoplaneta (pl_radj), se observan relaciones significativas con otras variables. Específicamente, tiene una correlación positiva con la profundidad del trÔnsito (pl_trandep), lo que indica que los exoplanetas mÔs grandes generan una mayor disminución en el brillo de su estrella al pasar frente a ella. Por otro lado, pl_radj muestra una correlación negativa con la gravedad superficial de la estrella anfitriona (st_logg), lo que sugiere que los exoplanetas mÔs grandes tienden a encontrarse en sistemas con estrellas de menor gravedad superficial, posiblemente porque estos sistemas albergan planetas de mayor tamaño.

Para visualizar mejor estas relaciones y seleccionar las mejores variables predictoras, se realiza un pair plot con las variables que presentan una correlación significativa, estableciendo un umbral del 50% en valor absoluto. Este grÔfico permite examinar cómo se distribuyen los datos y cómo se relacionan las variables entre sí, facilitando la identificación de tendencias y posibles patrones útiles para la estimación de valores faltantes y la construcción de modelos de predicción.

# Seleccionar de la matriz de correlación las variables con correlacion mayor o
# igual a 0.3 en valor absoluto con la variable faltante
correlated_vars <- names(which(abs(correlation_matrix_pearson["pl_radj", ]) >= 0.5))

# Se genera un dataframe con la correlacion entre las variables seleccionadas
# en correlated_vars y la variable faltante tomando de la matriz de correlacion
# solo las filas y columnas correspondientes a las variables seleccionadas
correlation_df <- data.frame(
  Variable = names(correlation_matrix_pearson[correlated_vars, "pl_radj"]),
  Correlacion = correlation_matrix_pearson[correlated_vars, "pl_radj"]
)

# Agregar una columna con la cantidad de valores faltantes
correlation_df$Faltantes <- sapply(correlation_df$Variable, function(x) sum(is.na(kepler_data[[x]])))

# Escribo a correlated_vars las variables seleccionadas
correlated_vars <- correlation_df$Variable

# Ordenar el dataframe por cantidad de faltantes ascendente
# y por valor absoluto de correlación descendente
correlation_df <- correlation_df[order(correlation_df$Faltantes, -abs(correlation_df$Correlacion)), ]

# Eliminar la columna de indice
rownames(correlation_df) <- NULL

# Mostrar tabla formateada
kable(correlation_df, columns = c("Variable","Correlación","Faltantes"), align = "l")
Variable Correlacion Faltantes
pl_radj 1.0000000 886
pl_rade 0.9999990 886
pl_ratror 0.9962260 1740
pl_trandep 0.9696465 2078
pl_rvamp 0.7326113 2474
st_rotp 0.5860330 2539
panel.hist <- function(x, ...) {
  usr <- par("usr"); on.exit(par(usr))
  par(usr = c(usr[1:2], 0, 1.5)) 
  hist(x, col = "indianred", border = "white", probability = TRUE, add = TRUE)
}

pairs(kepler_data_num[, correlated_vars], 
      diag.panel = panel.hist,     # Histogramas en la diagonal
      col = "steelblue", pch = 19, cex = 1.2)

MĆ”s allĆ” de la relación lineal evidente entre las medidas del radio del exoplaneta en diferentes unidades —es decir, radios jovianos y radios terrestres—, el anĆ”lisis de correlación revela la presencia de otras relaciones lineales significativas entre el radio del exoplaneta y otras variables del conjunto de datos. Estas relaciones se ordenan en función de su fuerza de correlación en orden descendente, destacando tres principales variables:

La primera variable con una fuerte correlación es el cociente del radio del planeta sobre el radio de su estrella anfitriona (pl_ratror). Esta relación tiene sentido desde un punto de vista físico, ya que el tamaño relativo del exoplaneta respecto a su estrella afecta directamente la observación de fenómenos como el trÔnsito. Cuanto mayor sea este cociente, mayor serÔ el tamaño aparente del exoplaneta durante el trÔnsito.

La segunda variable con alta correlación es la profundidad del trÔnsito (pl_trandep). Este valor mide la disminución en el brillo de la estrella cuando el planeta pasa frente a ella. Dado que planetas mÔs grandes bloquean una mayor parte de la luz estelar durante un trÔnsito, es lógico que exista una relación lineal positiva entre el radio del planeta y la profundidad del trÔnsito observado.

La tercera variable significativa es la amplitud de la velocidad radial del planeta (pl_rvamp). Esta mide el desplazamiento de la estrella debido al tirón gravitacional del exoplaneta en su órbita. Los exoplanetas de mayor tamaño tienden a ejercer una fuerza gravitacional mÔs intensa sobre la estrella, generando mayores variaciones en la velocidad radial detectada mediante el efecto Doppler, lo que explica esta relación.

Con base en estos resultados, se seleccionan estas tres variables como variables predictoras para el radio del exoplaneta, ya que presentan una alta correlación lineal, positiva o negativa, con la variable faltante. Estas relaciones proporcionan información clave para realizar estimaciones mÔs precisas del radio del exoplaneta mediante técnicas de regresión, basÔndose en patrones consistentes en los datos.

Detección de valores atípicos (outliers) en las predictoras

Para las variables predictoras seleccionadas (pl_ratdor,pl_trandep,pl_rvamp), se detectan valores atípicos en el dataset que puedan afectar el anÔlisis y la predicción de la variable faltante (pl_radj).

# Seleccionar las variables predictoras
predictor_vars <- c("pl_ratdor", "pl_trandep", "pl_rvamp")

# Crear un data frame con las variables predictoras
predictor_data <- kepler_data_num[predictor_vars]

# Normalizar los datos
predictor_data <- scale(predictor_data)

library(ggplot2)
library(tidyr)

predictor_data <- as.data.frame(predictor_data)

# Convertir a formato largo para ggplot2
data_long <- pivot_longer(predictor_data, cols = everything(), names_to = "Variable", values_to = "Valores")


# Graficar los valores atĆ­picos con un boxplot horizontal
# Se muestra el numero total de valores atĆ­picos
ggplot(data_long, aes(x = Valores, y = Variable)) +
  geom_boxplot(fill = "skyblue", color = "darkblue") +
  geom_jitter(aes(color = abs(Valores) > 3), width = 0.1) +
  scale_color_manual(values = c("black", "red")) +
  labs(title = "Detección de Valores Atípicos en Variables Predictoras",
       x = "Valores Normalizados",
       y = "Variable") +
  theme_minimal()

El boxplot revela la presencia de valores atípicos en las variables predictoras seleccionadas, lo que puede influir significativamente en el anÔlisis y en la precisión de la estimación de la variable faltante. Estos outliers pueden sesgar los resultados y reducir la eficacia de los modelos de predicción, especialmente si se utilizan técnicas sensibles a valores extremos, como la regresión lineal estÔndar.

Llama particularmente la atención la dispersión y la presencia de valores extremos en la variable pl_trandep, que representa la profundidad del trÔnsito del planeta, es decir, qué tanto disminuye el flujo de luz de la estrella cuando el planeta pasa por delante de ella. BÔsicamente, cuÔnta luz bloquea el planeta durante el trÔnsito, en porcentaje. La dispersión de valore nos da algunas pistas. En primer lugar los valores cercanos a cero (la gran mayoría): indican que el planeta bloquea muy poca luz durante el trÔnsito. Esto es normal para planetas pequeños o lejanos. Por otra parte la columna larga de puntos a la derecha (outliers en rojo): esos son casos donde la disminución del flujo es mucho mayor, indicando que el planeta: o es muy grande en comparación con su estrella, o la estrella es pequeña, así que cualquier planeta genera un gran bloqueo de luz pero también posiblemente que haya problemas en la medición o errores sistemÔticos.

La gran cantidad de valores extremos en pl_trandep puede sugerir una distribución naturalmente sesgada; es decir esta variable puede seguir una distribución fuertemente asimétrica dado quye la mayoría de los planetas apenas bloquean luz pero unos pocos bloquean bastante (ej: Júpiteres calientes frente a enanas rojas). Es común en astronomía: pocos eventos extremos, muchos valores pequeños. Pero también puede significar errores o ruido instrumental: algunos outliers podrían ser artefactos de medición, donde el modelo de trÔnsito interpretó mal la curva de luz. Por último no debe descartarse que puede haber errores de reducción de datos en el telescopio Kepler. Si no es un problema del telescopio, puede ser un sistema mal clasificado: Algunos objetos pueden no ser planetas, sino estrellas binarias eclipsantes, que generan una bajada de flujo mucho mayor al de un planeta.

Para abordar este problema, es recomendable emplear métodos de regresión robustos, diseñados para minimizar el impacto de valores atípicos en el ajuste del modelo. Un ejemplo de este enfoque es la regresión de Huber, que combina las ventajas de la regresión lineal y la regresión por mínimos cuadrados, pero con un mecanismo que reduce la influencia de outliers al asignarles un menor peso en el cÔlculo de los coeficientes.

Otra alternativa es utilizar técnicas como la regresión de Tukey biweight o la regresión de cuantiles, que modelan la relación entre variables sin verse afectadas por la distribución de los datos extremos. Adicionalmente, se pueden aplicar métodos de detección y tratamiento de outliers, como el recorte de datos (trimming), que elimina valores extremos por encima o por debajo de un umbral específico, o la transformación de variables, como el uso de logaritmos o escalado robusto, para reducir el impacto de valores extremos en el anÔlisis.

Analisis de regresión

Para explorar la relación entre las características conocidas de los exoplanetas, se lleva a cabo un anÔlisis de regresión lineal. El objetivo es predecir el radio del exoplaneta (pl_radj) utilizando tres variables que podrían estar estrechamente relacionadas con su tamaño:

  • pl_ratdor: el cociente entre el radio del exoplaneta y el radio de su estrella, que proporciona una medida relativa del tamaƱo del planeta.
  • pl_trandep: la profundidad del trĆ”nsito, que indica cuĆ”nto disminuye el brillo de la estrella cuando el exoplaneta pasa frente a ella, lo que estĆ” directamente relacionado con su radio.
  • pl_rvamp: la amplitud de la velocidad radial del planeta, que refleja su efecto gravitacional sobre la estrella y puede aportar información sobre su masa y, en combinación con otras variables, su tamaƱo.

A través de este anÔlisis, se busca comprender mejor cómo estas variables influyen en el tamaño de los exoplanetas y determinar cuÔl de ellas tiene un mayor impacto en la predicción de pl_radj.

Regresión lineal univariada

Las variablies de características de los sistemas exoplanetarios tales como periodo orbital, radio planetario, temperatura de la estrella central del sistema y masa del planeta pueden inferirse indirectamente a partir de otras variables como excentricidad orbital, distancia a la estrella, caracteristicas de la estrella y otras. Se explorar un anÔlisis de regresión lineal univariada con varias variables independientes evaluando la capacidad de predicción de cada modelo planteado.

Se realiza un anÔlisis de regresión lineal univariada para predecir el radio del exoplaneta (pl_radj) consecutivamente a partir de las variables independientes seleccionadas.

Regresión lineal: radio del exoplaneta según ratio del radio sobre el radio estelar (pl_ratdor)

# Regresion de pl_radj con pl_ratdor
model_pl_ratdor <- lm(pl_radj ~ pl_ratdor, data = kepler_data_num)

model_pl_ratdor_summary <- summary(model_pl_ratdor)

model_pl_ratdor_summary
## 
## Call:
## lm(formula = pl_radj ~ pl_ratdor, data = kepler_data_num)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.3749 -0.2695 -0.2125  0.3126  1.2264 
## 
## Coefficients:
##              Estimate Std. Error t value        Pr(>|t|)    
## (Intercept) 0.4086542  0.0535610   7.630 0.0000000000489 ***
## pl_ratdor   0.0007341  0.0005069   1.448           0.152    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3872 on 78 degrees of freedom
##   (2467 observations deleted due to missingness)
## Multiple R-squared:  0.02618,    Adjusted R-squared:  0.0137 
## F-statistic: 2.097 on 1 and 78 DF,  p-value: 0.1516
# Scatter plot de pl_radj vs pl_ratdor con la recta de regresión en rojo
# y los margenes de confianza en gris
ggplot(kepler_data_num, aes(x = pl_ratdor, y = pl_radj)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Regresión Lineal: Radio del Exoplaneta segun Ratio sobre el Radio Estelar",
       x = "Ratio sobre Radio Estelar",
       y = "Radio del Exoplaneta (JĆŗpiter)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

Para el modelo de regresión planteado:

\[ pl\_radj = \beta_0 + \beta_1 \cdot pl\_ratdor + \varepsilon \]

El anÔlisis de regresión sugiere que la variable pl_ratdor no es un buen predictor del radio del exoplaneta (pl_radj). Según los resultados, por cada aumento de 1 unidad en pl_ratdor, se espera un incremento de apenas 0.0007341 en pl_radj. Sin embargo, el valor p asociado a esta relación (Pr(>|t|) = 0.152) es mayor que 0.05, lo que significa que no hay suficiente evidencia estadística para afirmar que pl_ratdor influye significativamente en pl_radj. Esto sugiere que el modelo planteado no es el mÔs adecuado para estimar el radio del exoplaneta en función del cociente entre su radio y el radio de su estrella.

Este resultado se refuerza al revisar las estadísticas de ajuste del modelo. El Error EstÔndar Residual (0.3872) indica que los valores predichos se desvían bastante de los valores reales, lo que evidencia un ajuste impreciso. AdemÔs, el R² múltiple (0.02618) muestra que solo el 2.6% de la variabilidad en pl_radj es explicada por pl_ratdor, lo que indica un modelo con muy poca capacidad predictiva. De manera similar, el R² ajustado (0.0137), que corrige por el número de predictores, sigue siendo muy bajo, reforzando la idea de que pl_ratdor no contribuye significativamente a la predicción del radio del exoplaneta.

Por otro lado, el F-statistic (2.097) y su valor p (0.1516) confirman que el modelo, en su conjunto, no es estadísticamente significativo, lo que significa que no es capaz de explicar de manera fiable la relación entre estas variables.

A pesar de estos resultados, se realiza un anÔlisis de los residuos del modelo para verificar si cumplen con los supuestos de la regresión lineal, con el objetivo de entender mejor las limitaciones del modelo y explorar posibles ajustes o alternativas.

# Obtener los residuos y valores ajustados
res_pl_ratdor <- residuals(model_pl_ratdor)

# Estimar los valores ajustados
fit_val_pl_ratdor <- fitted(model_pl_ratdor)

# Crear un data frame con los residuos y valores ajustados
res_pl_ratdor_df <- data.frame(Fitted_Values = fit_val_pl_ratdor, Residuals = res_pl_ratdor)

# Scatter plot de residuos vs valores ajustados
ggplot(res_pl_ratdor_df, aes(x = Fitted_Values, y = Residuals)) +
  geom_point(color = "steelblue") +
  geom_hline(yintercept = 0, color = "indianred", linetype = "dashed") +
  labs(title = "Residuos vs Valores Ajustados",
       x = "Valores Ajustados",
       y = "Residuos") +
  theme_minimal()

El anÔlisis de los residuos muestra que estos tienden a concentrarse en los valores ajustados mÔs bajos, aproximadamente entre 0.4 y 0.5. A medida que los valores ajustados aumentan, la dispersión de los residuos también parece incrementar ligeramente. Sin embargo, no se observa un patrón claro en forma de parÔbola o curva, lo que sugiere que la relación entre la variable independiente (pl_ratdor) y la dependiente (pl_radj) podría ser aproximadamente lineal.

En general, la mayorĆ­a de los residuos se encuentran relativamente cerca de 0, aunque hay algunos valores positivos elevados (mayores a 0.5), lo que indica que el modelo tiende a subestimar ciertos valores de pl_radj. Por otro lado, hay pocos residuos negativos extremos, lo que sugiere que el modelo no estĆ” sobreestimando significativamente los valores del radio del exoplaneta.

Se detecta una leve heterocedasticidad, ya que la dispersión de los residuos parece mayor en los valores ajustados mÔs altos. Esto implica que el error no es completamente uniforme a lo largo de la distribución de valores ajustados, lo que podría afectar la confiabilidad de las predicciones. En un modelo ideal que cumpliera con la suposición de homocedasticidad (es decir, varianza constante de los errores), los residuos deberían distribuirse de manera mÔs uniforme alrededor de la línea de referencia (residuo = 0).

Dado que el modelo tiene un R² muy bajo (~2.6%), era esperable encontrar una dispersión alta en los residuos, lo que confirma que pl_ratdor no es un buen predictor de pl_radj. AdemÔs, la presencia de residuos elevados sugiere que existen otras variables no consideradas que podrían explicar mejor la variabilidad en el radio del exoplaneta.

# Crear un grƔfico Q-Q de los residuos
qqnorm(res_pl_ratdor, main = "GrƔfico Q-Q de los Residuos", col = "indianred")

Para que los residuos sigan una distribución normal, los puntos en la grÔfica deberían alinearse con una línea diagonal imaginaria. Sin embargo, se observan desviaciones en los extremos, es decir, en los cuantiles mÔs bajos y mÔs altos, donde los puntos se alejan de la línea teórica. Esto indica la presencia de colas mÔs pesadas de lo esperado en una distribución normal, lo que sugiere que existen valores atípicos o que los residuos no siguen completamente una distribución normal.

AdemÔs, se nota una ligera curvatura en la parte central del grÔfico. Aunque la mayoría de los puntos se alinean con la línea teórica en esta región, la curvatura sugiere que los residuos no son perfectamente normales, lo que podría afectar la validez de algunas inferencias estadísticas.

La regresión lineal asume que los residuos deben seguir una distribución normal para garantizar la validez de los intervalos de confianza y de los valores p. En este caso, la curvatura y las colas pesadas plantean dudas sobre el cumplimiento de esta suposición. Si los residuos no son normales, la inferencia estadística del modelo podría verse afectada, aunque la estimación de los coeficientes seguiría siendo vÔlida.

Para abordar este problema, una posible solución es aplicar transformaciones en la variable dependiente (pl_radj), como logaritmos o raíces cuadradas, para mejorar la normalidad de los residuos. Para confirmar estas observaciones, se realizan pruebas de normalidad y homocedasticidad, con el fin de evaluar si los residuos siguen efectivamente una distribución normal y si la varianza de los errores se mantiene constante a lo largo de los valores ajustados.

# Prueba de normalidad de Shapiro-Wilk
shapiro_test_pl_ratdor <- shapiro.test(res_pl_ratdor)

shapiro_test_pl_ratdor
## 
##  Shapiro-Wilk normality test
## 
## data:  res_pl_ratdor
## W = 0.81534, p-value = 0.00000001313

La prueba de Shapiro-Wilk es una herramienta estadística utilizada para determinar si un conjunto de datos sigue una distribución normal. En este anÔlisis, se aplicó a los residuos del modelo para evaluar si cumplen con esta suposición fundamental en la regresión lineal.

Esta prueba parte de la hipótesis nula (Hā‚€), que establece que los residuos siguen una distribución normal. Si el resultado muestra un p-valor muy bajo, se rechaza esta hipótesis, indicando que los datos no se ajustan a una distribución normal.

El resultado de la prueba arrojó un estadístico W de 0.81534, lo que sugiere una desviación considerable de la normalidad, ya que un valor cercano a 1 indicaría que los datos se distribuyen de manera normal. AdemÔs, el p-valor obtenido fue aproximadamente 0.00000001313, lo que es significativamente menor a 0.05. Esto proporciona suficiente evidencia para rechazar la hipótesis nula con un alto nivel de confianza, confirmando que los residuos no siguen una distribución normal.

Este resultado es relevante porque la falta de normalidad en los residuos puede afectar la validez de los intervalos de confianza y los valores p en la regresión. Para corregir este problema, podría ser necesario aplicar transformaciones a los datos o considerar el uso de métodos estadísticos mÔs robustos que no dependan estrictamente de la normalidad de los residuos.

# Prueba de homocedasticidad de Breusch-Pagan
library(lmtest)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
# Prueba de Breusch-Pagan
bp_test_pl_ratdor <- bptest(model_pl_ratdor)

bp_test_pl_ratdor
## 
##  studentized Breusch-Pagan test
## 
## data:  model_pl_ratdor
## BP = 1.1306, df = 1, p-value = 0.2876

El test de Breusch-Pagan es una prueba estadística utilizada para evaluar si los residuos del modelo presentan homocedasticidad (varianza constante) o heterocedasticidad (varianza no constante). La prueba parte de la hipótesis nula, que asume que los residuos tienen una varianza constante. Si se encuentra suficiente evidencia para rechazar esta hipótesis, se concluye que existe heterocedasticidad en el modelo.

En este anÔlisis, el estadístico de la prueba (BP) obtuvo un valor de 1.1306, el cual es relativamente bajo. Un valor alto de este estadístico indicaría la presencia de heterocedasticidad, pero en este caso no se observa una señal clara de ello. Dado que solo se utiliza un predictor, la prueba se basa en un grado de libertad (df = 1). AdemÔs, el p-valor obtenido fue de 0.2876, lo que es superior al umbral de 0.05. Esto significa que no hay suficiente evidencia estadística para rechazar la hipótesis nula, lo que sugiere que no se detecta heterocedasticidad significativa en los residuos.

A pesar de esto, el modelo no parece ajustarse bien a los datos, ya que se observa una gran dispersión en los residuos y la posible presencia de heterocedasticidad en ciertos rangos de los valores ajustados. Para mejorar el modelo, se exploran posibles transformaciones en la variable dependiente, como la aplicación de logaritmos. AdemÔs, se analiza si una transformación logarítmica en las variables predictoras podría mejorar la capacidad predictiva del modelo, utilizando para ello la prueba de Box-Cox, que permite determinar la mejor transformación para estabilizar la varianza y mejorar el ajuste del modelo.

# Prueba de Box-Cox para transformar la variable st_rad
library(MASS)
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
# Prueba de Box-Cox
boxcox_pl_ratdor <- boxcox(model_pl_ratdor, lambda = seq(-2, 2, by = 0.1))

La transformación de Box-Cox es una técnica utilizada en modelos de regresión para encontrar la mejor manera de transformar la variable dependiente, con el fin de mejorar la normalidad de los residuos y garantizar una varianza constante (homocedasticidad).

La grÔfica generada en este anÔlisis muestra cómo varía la log-verosimilitud en función del parÔmetro lambda, el cual determina la forma de la transformación aplicada a la variable dependiente Y. Dependiendo del valor de lambda, la transformación puede ser una raíz cuadrada, un logaritmo, una inversa, entre otras, ayudando a estabilizar la varianza y mejorar el ajuste del modelo.

\[ Y' = \begin{cases} \frac{Y^\lambda - 1}{\lambda}, & \lambda \neq 0 \\ \log(Y), & \lambda = 0 \end{cases} \]

# Obtener el lambda óptimo
lambda_optimal <- boxcox_pl_ratdor$x[which.max(boxcox_pl_ratdor$y)]

lambda_optimal
## [1] -0.02020202

El valor óptimo del parÔmetro lambda obtenido en la transformación de Box-Cox es -0.0202, lo que indica que la mejor transformación para la variable pl_ratdor es cercana a 0. Dado que un lambda de 0 corresponde a una transformación logarítmica, aplicar el logaritmo a esta variable podría mejorar la capacidad predictiva del modelo de regresión lineal.

Para verificar si esta transformación realmente mejora el ajuste del modelo, se lleva a cabo una nueva regresión lineal utilizando la variable transformada. Luego, se evalúa el desempeño del modelo actualizado, analizando métricas como el R², los residuos y la significancia de los coeficientes para determinar si la predicción de pl_radj mejora con la nueva transformación.

# Regresión de pl_radj con log(pl_ratdor) 
model_pl_ratdor_log <- lm(pl_radj ~ log(pl_ratdor), data = kepler_data_num)

model_pl_ratdor_log_summary <- summary(model_pl_ratdor_log)

model_pl_ratdor_log_summary
## 
## Call:
## lm(formula = pl_radj ~ log(pl_ratdor), data = kepler_data_num)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.3776 -0.2720 -0.2215  0.2916  1.2130 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)  
## (Intercept)     0.29440    0.12286   2.396    0.019 *
## log(pl_ratdor)  0.04726    0.03397   1.391    0.168  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3876 on 78 degrees of freedom
##   (2467 observations deleted due to missingness)
## Multiple R-squared:  0.02421,    Adjusted R-squared:  0.0117 
## F-statistic: 1.935 on 1 and 78 DF,  p-value: 0.1681
# Scatter plot de pl_radj vs log(pl_ratdor) con la recta de regresión en rojo
# y los margenes de confianza en gris
ggplot(kepler_data_num, aes(x = log(pl_ratdor), y = pl_radj)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Regresión Lineal: Radio del Exoplaneta segun Logaritmo del Ratio sobre el Radio Estelar",
       x = "Logaritmo del Ratio sobre Radio Estelar",
       y = "Radio del Exoplaneta (JĆŗpiter)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

El modelo ajustado con la transformación logarítmica de pl_ratdor muestra resultados muy similares al modelo original, lo que indica que la transformación no mejoró significativamente la capacidad predictiva. El error estÔndar de los residuos es 0.3876, prÔcticamente idéntico al del modelo sin transformación (0.3872), lo que sugiere que la variabilidad de los residuos sigue siendo la misma.

El coeficiente de determinación R² múltiple es 0.02421 (2.4%), lo que significa que solo un 2.4% de la variabilidad de pl_radj es explicada por log(pl_ratdor), un valor extremadamente bajo. Incluso al ajustar por el número de predictores, el R² ajustado apenas mejora, quedando en 1.2%, lo que refuerza la idea de que el modelo sigue sin capturar bien la relación entre las variables.

El estadístico F, con un valor de 1.935 y un p-valor de 0.1681, indica que no hay suficiente evidencia estadística para afirmar que la transformación logarítmica de pl_ratdor mejora significativamente el modelo.

En conclusión, el modelo sigue sin ser adecuado para predecir pl_radj a partir de pl_ratdor, incluso después de aplicar la transformación logarítmica. Ante estos resultados, se procede a probar con otras variables predictoras o combinaciones de variables para mejorar la capacidad de ajuste del modelo.

Regresión lineal: radio del exoplaneta según la profundidad del trÔnsito (pl_trandep)

# Regresion del radio del exploplaneta (pl_radj) 
# con la profundidad del trƔnsito del planeta (pl_trandep)
# como predictor
model_pl_trandep <- lm(pl_radj ~ pl_trandep, data = kepler_data_num)

model_pl_trandep_summary <- summary(model_pl_trandep)

model_pl_trandep_summary
## 
## Call:
## lm(formula = pl_radj ~ pl_trandep, data = kepler_data_num)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.203530 -0.056704  0.002386  0.056979  0.150580 
## 
## Coefficients:
##             Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)  0.22308    0.01590   14.03 <0.0000000000000002 ***
## pl_trandep   0.61058    0.02434   25.08 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.08315 on 40 degrees of freedom
##   (2505 observations deleted due to missingness)
## Multiple R-squared:  0.9402, Adjusted R-squared:  0.9387 
## F-statistic: 629.1 on 1 and 40 DF,  p-value: < 0.00000000000000022
# Scatter plot de pl_radj vs pl_trandep con la recta de regresión en rojo
# y los margenes de confianza en gris
ggplot(kepler_data_num, aes(x = pl_trandep, y = pl_radj)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Regresión Lineal: Radio del Exoplaneta vs Profundidad del TrÔnsito",
       x = "Profundidad del TrƔnsito (%)",
       y = "Radio del Exoplaneta (JĆŗpiter)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

En el modelo:

\[ pl\_radj = \beta_0 + \beta_1 \cdot pl\_trandep + \varepsilon \]

Cada aumento unitario en pl_trandep se asocia con un incremento de 0.61058 en pl_radj. AdemĆ”s es altamente significativo (con p-value < 0.00000000000000022), lo que indica una fuerte relación entre pl_trandep y pl_radj. AdemĆ”s: El modelo de regresión planteado para predecir pl_radj en función de pl_trandep muestra una relación clara y significativa entre ambas variables. En este caso, por cada aumento unitario en pl_trandep, se observa un incremento de 0.61058 en pl_radj. AdemĆ”s, esta relación es altamente significativa, con un p-valor extremadamente bajo (< 2.2 Ɨ 10⁻¹⁶), lo que indica que hay una fuerte conexión entre ambas variables.

El modelo presenta un error estÔndar de los residuos de 0.08315, lo que sugiere que la variabilidad en las predicciones es muy baja y, por lo tanto, el ajuste del modelo es bastante preciso. AdemÔs, el coeficiente de determinación R² alcanza un 94.02%, lo que significa que el modelo explica casi toda la variabilidad de pl_radj. Incluso el R² ajustado, que corrige por el número de predictores, sigue siendo muy alto (93.87%), lo que confirma la solidez del ajuste.

La prueba de significancia global del modelo, evaluada con el estadístico F, arroja un valor de 629.1 con un p-valor extremadamente bajo, lo que refuerza la validez del modelo y su capacidad para explicar la relación entre las variables.

En comparación con los modelos anteriores (pl_radj ~ pl_ratdor y pl_radj ~ log(pl_ratdor)), este nuevo modelo muestra una mejora drÔstica en el ajuste, con una capacidad explicativa mucho mayor. La relación entre pl_trandep y pl_radj no solo es fuerte, sino que también es estadísticamente muy significativa, lo que indica que pl_trandep es un excelente predictor del radio del exoplaneta.

# Obtener los residuos y valores ajustados
res_pl_trandep <- residuals(model_pl_trandep)

# Calcular los valores ajustados
fit_val_pl_trandep <- fitted(model_pl_trandep)

# Crear un data frame con los residuos y valores ajustados
res_pl_trandep_df <- data.frame(
  Residuals = res_pl_trandep,
  Fitted_Values = fit_val_pl_trandep
)

# Scatter plot de residuos vs valores ajustados
ggplot(res_pl_trandep_df, aes(x = Fitted_Values, y = Residuals)) +
  geom_point(color = "steelblue") +
  geom_hline(yintercept = 0, color = "indianred", linetype = "dashed") +
  labs(title = "Residuos vs Valores Ajustados",
       x = "Valores Ajustados",
       y = "Residuos") +
  theme_minimal()

El grÔfico de residuos vs valores ajustados revela un patrón en la dispersión de los residuos. Para valores ajustados bajos, los residuos tienden a agruparse cerca de 0, lo que indica una menor variabilidad en esta región. Sin embargo, a medida que los valores ajustados aumentan, los residuos se dispersan mÔs, sugiriendo que el error del modelo no es uniforme en todo el rango de predicciones.

Este comportamiento sugiere la presencia de heterocedasticidad, ya que la dispersión de los residuos parece seguir un patrón de parÔbola invertida, con una mayor variabilidad en los valores ajustados mÔs altos. La heterocedasticidad ocurre cuando la varianza de los errores no es constante, lo que puede afectar la fiabilidad de las inferencias estadísticas del modelo. Para confirmar si este problema estÔ presente, se puede realizar el test de Breusch-Pagan, que evalúa si la varianza de los residuos cambia sistemÔticamente con los valores ajustados.

En un modelo bien especificado, los residuos deberían distribuirse de manera aleatoria alrededor de la línea de referencia (y=0), sin mostrar patrones claros. Sin embargo, en este caso, se observa una mayor concentración de puntos en la parte izquierda del grÔfico, lo que sugiere que el modelo podría no estar captando completamente la relación entre pl_radj y pl_trandep. Este comportamiento indica que el modelo podría beneficiarse de una revisión, como la inclusión de nuevas variables explicativas o la aplicación de transformaciones para mejorar la estabilidad de la varianza de los errores.

# Crear un grƔfico Q-Q de los residuos
qqnorm(res_pl_trandep, main = "GrƔfico Q-Q de los Residuos", col="indianred")

El grÔfico Q-Q (Quantile-Quantile) de los residuos permite evaluar si estos siguen una distribución normal comparando sus cuantiles con los de una distribución normal teórica. En este caso, los puntos del grÔfico se alinean bastante bien con la línea diagonal, lo que indica que, en general, los residuos siguen un comportamiento cercano a la normalidad.

Sin embargo, se observan pequeñas desviaciones en los extremos, tanto en los valores mÔs negativos como en los mÔs positivos. Esto sugiere la presencia de colas mÔs pesadas en la distribución de los residuos o la existencia de algunos valores atípicos leves. A pesar de estas desviaciones, no parecen ser lo suficientemente grandes como para indicar una violación grave de la normalidad.

Para complementar este anÔlisis y confirmar si los residuos cumplen con los supuestos de normalidad y homocedasticidad, se realizan pruebas estadísticas específicas. Estas pruebas permiten verificar con mayor precisión si los residuos siguen efectivamente una distribución normal y si la varianza de los errores es constante en todo el rango de valores ajustados. Si se detectan problemas significativos, podrían ser necesarias transformaciones en los datos o el uso de modelos mÔs robustos para mejorar la validez del anÔlisis.

# Prueba de normalidad de Shapiro-Wilk
shapiro_test_pl_trandep <- shapiro.test(res_pl_trandep)

shapiro_test_pl_trandep
## 
##  Shapiro-Wilk normality test
## 
## data:  res_pl_trandep
## W = 0.98715, p-value = 0.9115

La prueba de Shapiro-Wilk se utilizó para evaluar si los residuos del modelo siguen una distribución normal. El resultado arrojó un estadístico W de 0.98715, un valor cercano a 1, lo que indica que los datos se ajustan bien a una distribución normal. AdemÔs, el p-valor obtenido fue de 0.9115, lo que, al ser mayor que 0.05, significa que no hay suficiente evidencia estadística para rechazar la hipótesis nula. En otras palabras, los residuos no presentan desviaciones significativas de la normalidad.

Este resultado confirma que el supuesto de normalidad de los residuos se cumple, lo que hace que el modelo sea estadísticamente vÔlido para realizar inferencias. AdemÔs, es coherente con la observación del grÔfico Q-Q, que ya sugería una buena alineación de los residuos con la distribución normal. Esto refuerza la confianza en la fiabilidad del modelo y en la precisión de sus estimaciones.

# Prueba de homocedasticidad de Breusch-Pagan
library(lmtest)

# Prueba de Breusch-Pagan
bp_test_pl_trandep <- bptest(model_pl_trandep)

bp_test_pl_trandep
## 
##  studentized Breusch-Pagan test
## 
## data:  model_pl_trandep
## BP = 6.2822, df = 1, p-value = 0.0122

El test de homocedasticidad de Breusch-Pagan se utilizó para evaluar si la varianza de los errores en el modelo es constante. Los resultados muestran un estadístico BP de 6.2822, lo que sugiere una mayor evidencia de heterocedasticidad. Dado que solo se incluye un predictor en el modelo, la prueba se basa en un grado de libertad. AdemÔs, el p-valor obtenido fue de 0.0122, lo que, al ser menor que 0.05, indica que se debe rechazar la hipótesis nula y concluir que los residuos presentan heterocedasticidad significativa. En otras palabras, la varianza de los errores no es constante en todo el rango de valores ajustados.

Esta violación de la suposición de homocedasticidad puede afectar la precisión de las estimaciones y pruebas de hipótesis, haciendo que los intervalos de confianza y valores p sean menos confiables debido a la variabilidad desigual en los errores del modelo.

Dado que esta condición puede comprometer la validez de los resultados, es importante considerar estrategias para corregir la heterocedasticidad. Una opción es aplicar una transformación en la variable dependiente, como el logaritmo (log(Y)) o la raíz cuadrada (sqrt(Y)), para estabilizar la varianza de los errores. Otra alternativa es utilizar una regresión robusta con errores estÔndar de White, que ajusta los errores para hacerlos menos sensibles a la heterocedasticidad. También puede aplicarse una regresión ponderada (WLS, Weighted Least Squares), en la que se asignan pesos a las observaciones para compensar la variabilidad desigual en los errores, especialmente si la heterocedasticidad estÔ relacionada con una variable específica.

Como primer intento de corrección, se aplicarÔ una transformación a la variable dependiente pl_radj, con el objetivo de reducir la heterocedasticidad y mejorar la estabilidad del modelo.

# Prueba de Box-Cox para transformar la variable pl_trandep
library(MASS)

# Prueba de Box-Cox
boxcox_pl_trandep <- boxcox(model_pl_trandep, lambda = seq(-2, 2, by = 0.1))

El anĆ”lisis de la transformación de Box-Cox muestra que el pico de la curva ocurre aproximadamente en lambda ā‰ˆ 2, lo que indica que la mejor transformación para la variable dependiente se encuentra en esa región. Como este valor estĆ” dentro del intervalo de confianza, se considera una opción adecuada para transformar los datos y mejorar el ajuste del modelo.

Dado que el valor óptimo de lambda es cercano a 2, la transformación sugerida para la variable dependiente es elevarla al cuadrado (Y²). Este tipo de transformación puede ayudar a estabilizar la varianza de los residuos y mejorar la linealidad de la relación entre las variables.

Por otro lado, no se recomienda utilizar una transformación logarítmica (log(Y)) correspondiente a lambda = 0, ni la raíz cuadrada (sqrt(Y)), que correspondería a lambda = 0.5. Ambas opciones quedan fuera del intervalo óptimo definido por la prueba y, por lo tanto, no ofrecerían una mejora significativa en la normalidad de los residuos ni en la homocedasticidad del modelo.

# Regresión de pl_radj^2 con pl_trandep
model_pl_trandep_square <- lm(I(pl_radj^2) ~ pl_trandep, data = kepler_data_num)

model_pl_trandep_square_summary <- summary(model_pl_trandep_square)

model_pl_trandep_square_summary
## 
## Call:
## lm(formula = I(pl_radj^2) ~ pl_trandep, data = kepler_data_num)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.108946 -0.015184 -0.004665  0.010102  0.134871 
## 
## Coefficients:
##             Estimate Std. Error t value            Pr(>|t|)    
## (Intercept) 0.010364   0.007744   1.338               0.188    
## pl_trandep  0.803698   0.011855  67.795 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.04049 on 40 degrees of freedom
##   (2505 observations deleted due to missingness)
## Multiple R-squared:  0.9914, Adjusted R-squared:  0.9912 
## F-statistic:  4596 on 1 and 40 DF,  p-value: < 0.00000000000000022
# Scatter plot de pl_radj^2 vs pl_trandep con la recta de regresión en rojo
# y los margenes de confianza en gris
ggplot(kepler_data_num, aes(x = pl_trandep, y = I(pl_radj^2)))+
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Regresión Lineal: Radio del Exoplaneta al Cuadrado segun Profundidad del TrÔnsito",
       x = "Profundidad del TrƔnsito (%)",
       y = "Radio del Exoplaneta al Cuadrado (JĆŗpiter^2)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 2505 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 2505 rows containing missing values or values outside the scale range
## (`geom_point()`).

\[ pl\_radj^2 = \beta_0 + \beta_1 \cdot pl\_trandep + \varepsilon \]

El anÔlisis del modelo después de aplicar la transformación cuadrÔtica muestra una mejora significativa en su precisión y capacidad predictiva. El error estÔndar de los residuos se redujo a 0.04049, un valor menor en comparación con el modelo sin transformación, lo que indica una mayor precisión en las predicciones.

El modelo ahora explica el 99.14% de la variabilidad en pl_radj², con un R² de 0.9914, lo que refleja un ajuste excepcional. Incluso al corregir por el número de predictores, el R² ajustado sigue siendo extremadamente alto, con un valor de 0.9912, lo que confirma que la relación entre las variables es muy sólida.

AdemĆ”s, el estadĆ­stico F, con un valor de 4,596 y un p-valor extremadamente bajo (< 2.2 Ɨ 10⁻¹⁶), demuestra que el modelo es altamente significativo.

En general, la transformación cuadrÔtica mejoró notablemente el ajuste en comparación con el modelo original. La relación entre pl_trandep y pl_radj² no solo es fuerte, sino también estadísticamente significativa, lo que sugiere que este modelo es una representación mÔs precisa de la relación entre las variables.

# Obtener los residuos y valores ajustados
res_pl_trandep_square <- residuals(model_pl_trandep_square)

# Calcular los valores ajustados
fit_val_pl_trandep_square <- fitted(model_pl_trandep_square)

# Crear un data frame con los residuos y valores ajustados
res_pl_trandep_square_df <- data.frame(
  Residuals = res_pl_trandep_square,
  Fitted_Values = fit_val_pl_trandep_square
)

# Scatter plot de residuos vs valores ajustados
ggplot(res_pl_trandep_square_df, aes(x = Fitted_Values, y = Residuals)) +
  geom_point(color = "steelblue") +
  geom_hline(yintercept = 0, color = "indianred", linetype = "dashed") +
  labs(title = "Residuos vs Valores Ajustados",
       x = "Valores Ajustados",
       y = "Residuos") +
  theme_minimal()

Los residuos tienen menor dispersión, lo que confirma que la heterocedasticidad detectada anteriormente fue reducida con la transformación.

# Crear un grƔfico Q-Q de los residuos
qqnorm(res_pl_trandep_square, main = "GrƔfico Q-Q de los Residuos", col="indianred")

En el grÔfico Q-Q de los residuos, los puntos se alinean bastante bien con la línea diagonal, lo que sugiere que los residuos siguen una distribución normal. Aunque hay una pequeña desviación en los extremos (valores muy negativos y positivos), la desviación no es severa.

# Prueba de normalidad de Shapiro-Wilk
shapiro_test_pl_trandep_square <- shapiro.test(res_pl_trandep_square)

shapiro_test_pl_trandep_square
## 
##  Shapiro-Wilk normality test
## 
## data:  res_pl_trandep_square
## W = 0.8507, p-value = 0.00006504

El test de normalidad de Shapiro-Wilk arroja un estadístico W de 0.8507 y un p-valor de 0.00006504, lo que indica que los residuos no siguen una distribución normal. A pesar de que en el grÔfico Q-Q los puntos parecían alinearse de manera razonable con la línea diagonal, la prueba estadística proporciona evidencia suficiente para rechazar la hipótesis de normalidad.

library(lmtest)
# Prueba de homocedasticidad de Breusch-Pagan
bp_test_pl_trandep_square <- bptest(model_pl_trandep_square)

bp_test_pl_trandep_square
## 
##  studentized Breusch-Pagan test
## 
## data:  model_pl_trandep_square
## BP = 14.87, df = 1, p-value = 0.0001152

El test de Breusch-Pagan arroja un estadĆ­stico BP de 14.87, con 1 grado de libertad y un p-valor de 0.0001152, lo que indica que los residuos presentan heterocedasticidad significativa. Esto significa que la varianza de los errores no es constante en todo el modelo, lo que puede afectar la fiabilidad de las inferencias estadĆ­sticas.

Aunque la transformación cuadrÔtica aplicada a la variable dependiente ayudó a reducir la heterocedasticidad, los resultados muestran que aún persiste en cierta medida. Esto sugiere que, aunque el modelo ha mejorado, puede ser necesario aplicar otras estrategias, como regresión ponderada o el uso de errores estÔndar robustos, para garantizar una estimación mÔs estable y confiable.

Regresión lineal robusta de Huber: radio del exoplaneta según la profundidad del trÔnsito (pl_trandep)

Cabe recordar, según lo expuesto en el anÔlisis de outliers, la gran cantidad de datos extremos en la variable pl_trandep, por lo que probablemente sea adecuada la utilización de un modelo mÔs robusto para evitar que estos datos afecten la calidad del modelo, como por ejemplo la regresión de Huber.

# Regresión de Huber
library(MASS)

# Ajuste del modelo de regresión de Huber
model_pl_trandep_huber <- rlm(pl_radj ~ pl_trandep, data = kepler_data_num)

model_pl_trandep_huber_summary <- summary(model_pl_trandep_huber)

model_pl_trandep_huber_summary
## 
## Call: rlm(formula = pl_radj ~ pl_trandep, data = kepler_data_num)
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.237990 -0.058563  0.003357  0.053174  0.146508 
## 
## Coefficients:
##             Value   Std. Error t value
## (Intercept)  0.2199  0.0163    13.5180
## pl_trandep   0.6289  0.0249    25.2548
## 
## Residual standard error: 0.08627 on 40 degrees of freedom
##   (2505 observations deleted due to missingness)
# Scatter plot de pl_radj vs pl_trandep con la recta de regresión en rojo
# y los margenes de confianza en gris
ggplot(kepler_data_num, aes(x = pl_trandep, y = pl_radj)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "rlm", color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Regresión de Huber: Radio del Exoplaneta segun Profundidad del TrÔnsito",
       x = "Profundidad del TrƔnsito (%)",
       y = "Radio del Exoplaneta (JĆŗpiter)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

formular de la regresión de Huber:

\[ pl\_radj = 0.2199 + 0.6289 \cdot pl\_trandep + 0.08627 \]

El modelo de regresión de Huber muestra una relación significativa entre pl_trandep y pl_radj, con un coeficiente de 0.6289. Cada aumento unitario en pl_trandep se asocia con un incremento de 0.6289 en pl_radj. AdemÔs, el modelo tiene un error estÔndar de los residuos de 0.3876, lo que indica una variabilidad moderada en las predicciones.

Ambos coeficientes son altamente significativos (t > 2 por mucho), lo que sugiere que hay una relación clara y fuerte entre la profundidad del trÔnsito y el radio del planeta. Sin embargo, de los datos originales, solo 41 observaciones fueron usadas y 2505 observaciones fueron descartadas. Eso puede pasar si faltan datos en pl_radj o pl_trandep o se perdieron en el preprocesamiento (posiblemente el tratamiento del método robusto) los dejó fuera.

Regresión lineal: radio del exoplaneta según la amplitud de la velocidad radial (pl_rvamp)

# Regresion del radio del exoplaneta (pl_radj) 
# utilizando la amplitude de la velocidad radial del planeta (pl_rvamp)
# como predictor
model_pl_rvamp <- lm(pl_radj ~ pl_rvamp, data = kepler_data_num)

model_pl_rvamp_summary <- summary(model_pl_rvamp)

model_pl_rvamp_summary
## 
## Call:
## lm(formula = pl_radj ~ pl_rvamp, data = kepler_data_num)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.5172 -0.2119 -0.1206  0.2644  0.8116 
## 
## Coefficients:
##             Estimate Std. Error t value         Pr(>|t|)    
## (Intercept) 0.337785   0.041804   8.080 0.00000000001903 ***
## pl_rvamp    0.003550   0.000406   8.744 0.00000000000124 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3026 on 66 degrees of freedom
##   (2479 observations deleted due to missingness)
## Multiple R-squared:  0.5367, Adjusted R-squared:  0.5297 
## F-statistic: 76.46 on 1 and 66 DF,  p-value: 0.000000000001239
# Scatter plot de pl_radj vs pl_rvamp con la recta de regresión en rojo
# y los margenes de confianza en gris
ggplot(kepler_data_num, aes(x = pl_rvamp, y = pl_radj)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Regresión Lineal: Radio del Exoplaneta segun Amplitud de la Velocidad Radial",
       x = "Amplitud de la Velocidad Radial (ma/s)",
       y = "Radio del Exoplaneta (JĆŗpiter)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

Para el modelo de regresión planteado:

\[ pl\_radj = \beta_0 + \beta_1 \cdot pl\_rvamp + \varepsilon \]

Las estadĆ­sticas del modelo muestran que:

El modelo presenta un R² de 0.5367, lo que indica que explica el 53.67% de la variabilidad en pl_radj. Esto sugiere una relación moderada a fuerte entre las variables, aunque todavía queda un 46.33% de variabilidad sin explicar, lo que implica que otros factores podrían estar influyendo en la variable dependiente.

El R² ajustado es 0.5297, lo que significa que, incluso al corregir por el número de predictores, el modelo sigue manteniendo un buen nivel de ajuste. AdemÔs, el estadístico F tiene un valor de 76.46, con un p-valor extremadamente bajo, lo que confirma que el modelo es altamente significativo y que la relación entre las variables no es producto del azar.

A pesar de que el modelo tiene un ajuste razonable, no es tan preciso como el obtenido en la regresión de pl_radj ~ pl_trandep. Sin embargo, la relación entre pl_rvamp y pl_radj sigue siendo estadísticamente significativa y muestra un nivel de asociación importante, lo que sugiere que pl_rvamp es un predictor relevante, aunque no el mÔs fuerte disponible.

# Obtener los residuos y valores ajustados
res_pl_rvamp <- residuals(model_pl_rvamp)

# Calcular los valores ajustados
fit_val_pl_rvamp <- fitted(model_pl_rvamp)

# Crear un data frame con los residuos y valores ajustados
res_pl_rvamp_df <- data.frame(
  Residuals = res_pl_rvamp,
  Fitted_Values = fit_val_pl_rvamp
)

# Scatter plot de residuos vs valores ajustados
ggplot(res_pl_rvamp_df, aes(x = Fitted_Values, y = Residuals)) +
  geom_point(color = "steelblue") +
  geom_hline(yintercept = 0, color = "indianred", linetype = "dashed") +
  labs(title = "Residuos vs Valores Ajustados",
       x = "Valores Ajustados",
       y = "Residuos") +
  theme_minimal()

El anÔlisis de los residuos revela que su dispersión no es constante a lo largo de los valores ajustados, lo que sugiere la posible presencia de heterocedasticidad. En los valores ajustados mÔs pequeños (menores a 0.5), los residuos estÔn muy concentrados, lo que indica una menor variabilidad en esta región. Sin embargo, a medida que los valores ajustados aumentan (mayores a 1.0), los residuos muestran una dispersión mucho mayor, lo que sugiere que la varianza de los errores no es constante en todo el modelo.

La presencia de heterocedasticidad puede indicar que el modelo no estÔ capturando adecuadamente la variabilidad de los datos, lo que podría afectar la precisión de sus predicciones. Para corregir este problema, se pueden aplicar transformaciones en las variables, como el uso de logaritmos o raíces cuadradas, o utilizar métodos de regresión robustos que ajusten los errores estÔndar para hacerlos menos sensibles a la variabilidad desigual.

AdemÔs, si los residuos muestran una tendencia curva o patrones de agrupación, esto podría ser una señal de que el modelo lineal no es la mejor opción. En estos casos, podría ser necesario recurrir a un modelo no lineal o incluir términos polinomiales en la regresión para capturar mejor la relación entre las variables y mejorar la precisión del ajuste.

# Crear un grƔfico Q-Q de los residuos
qqnorm(res_pl_rvamp, main = "GrƔfico Q-Q de los Residuos", col="indianred")

El anÔlisis del grÔfico Q-Q de los residuos muestra desviaciones significativas en los extremos, especialmente en los cuantiles mÔs bajos y mÔs altos. Esto sugiere que la distribución de los residuos no sigue completamente una distribución normal y que las colas de la distribución son mÔs pesadas de lo esperado. En otras palabras, hay mÔs valores extremos en los residuos de lo que se esperaría en una distribución normal ideal.

Los residuos mÔs alejados de la media, tanto en la dirección negativa como positiva, se desvían notablemente de la línea teórica, lo que indica la presencia de valores atípicos que podrían estar afectando el modelo. A pesar de esto, la mayor parte de los puntos en la zona central del grÔfico parecen alinearse mejor con la distribución normal, aunque los extremos muestran una curvatura evidente.

La falta de normalidad en los residuos pone en duda la validez de los intervalos de confianza y las pruebas de hipótesis del modelo, ya que muchos procedimientos estadísticos dependen de esta suposición. La presencia de valores extremos también sugiere que outliers o una distribución sesgada podrían estar influyendo en el comportamiento del modelo. Para abordar este problema, se pueden considerar transformaciones de las variables, la eliminación de valores atípicos o el uso de modelos mÔs robustos que no dependan estrictamente de la normalidad de los errores.

# Prueba de normalidad de Shapiro-Wilk
shapiro_test_pl_rvamp <- shapiro.test(res_pl_rvamp)

shapiro_test_pl_rvamp
## 
##  Shapiro-Wilk normality test
## 
## data:  res_pl_rvamp
## W = 0.86708, p-value = 0.000003207

El resultado de la prueba de normalidad de Shapiro-Wilk indica que los residuos no siguen una distribución normal, con un estadístico W de 0.86708 y un p-valor de 0.000003207. Dado que este p-valor es extremadamente bajo, hay suficiente evidencia para rechazar la hipótesis de normalidad.

Aunque en el grÔfico Q-Q los residuos parecían alinearse en cierta medida con la línea diagonal, la prueba estadística confirma que existen desviaciones significativas. Esto sugiere que los residuos podrían estar influenciados por la presencia de valores atípicos o que su distribución tiene características diferentes a las de una normal ideal.

La falta de normalidad en los residuos podría afectar la validez de los intervalos de confianza y las pruebas de hipótesis, lo que hace necesario considerar posibles soluciones, como aplicar transformaciones a los datos, eliminar valores extremos o utilizar métodos estadísticos mÔs robustos que no dependan estrictamente de la normalidad de los errores.

# Prueba de homocedasticidad de Breusch-Pagan
library(lmtest)

# Prueba de Breusch-Pagan
bp_test_pl_rvamp <- bptest(model_pl_rvamp)

bp_test_pl_rvamp
## 
##  studentized Breusch-Pagan test
## 
## data:  model_pl_rvamp
## BP = 10.096, df = 1, p-value = 0.001486

El resultado del test de Breusch-Pagan indica la presencia de heterocedasticidad significativa, con un estadístico BP de 10.096 y un p-valor de 0.001486. Esto significa que la varianza de los errores no es constante, lo que puede comprometer la precisión de las estimaciones del modelo y las pruebas de hipótesis.

Dado que el modelo no cumple con la suposición de homocedasticidad y, ademÔs, los residuos no siguen una distribución normal, se busca corregir la heterocedasticidad mediante una transformación de la variable dependiente. Para determinar cuÔl es la mejor transformación, se lleva a cabo una prueba de Box-Cox, que permite identificar la forma mÔs adecuada para estabilizar la varianza de los errores y mejorar el ajuste del modelo.

# Prueba de Box-Cox para transformar la variable pl_rvamp
library(MASS)

# Prueba de Box-Cox
boxcox_pl_rvamp <- boxcox(model_pl_rvamp, lambda = seq(-2, 2, by = 0.1))

El pico de la curva en la prueba de Box-Cox se encuentra cerca de lambda = 0, lo que indica que la mejor transformación para la variable dependiente se encuentra en esa zona. En términos prÔcticos, cuando el valor óptimo de lambda (λ) es 0, la transformación recomendada es el logaritmo natural de la variable dependiente.

Dado que λ = 0 estÔ dentro del intervalo de confianza, esto confirma que aplicar una transformación logarítmica (log(Y)) es la opción mÔs adecuada. Este tipo de transformación es útil porque puede reducir la heterocedasticidad, mejorar la normalidad de los residuos y hacer que la relación entre las variables sea mÔs lineal, lo que permite que el modelo de regresión tenga un mejor ajuste y sea mÔs preciso en sus estimaciones.

# Regresión de log(pl_radj) con logpl_rvamp
model_pl_rvamp_log <- lm(log(pl_radj) ~ log(pl_rvamp), data = kepler_data_num)

model_pl_rvamp_log_summary <- summary(model_pl_rvamp_log)

model_pl_rvamp_log_summary
## 
## Call:
## lm(formula = log(pl_radj) ~ log(pl_rvamp), data = kepler_data_num)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.09181 -0.30754  0.04893  0.21513  0.98300 
## 
## Coefficients:
##               Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)   -2.06303    0.06935  -29.75 <0.0000000000000002 ***
## log(pl_rvamp)  0.44267    0.02356   18.79 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3753 on 66 degrees of freedom
##   (2479 observations deleted due to missingness)
## Multiple R-squared:  0.8425, Adjusted R-squared:  0.8401 
## F-statistic:   353 on 1 and 66 DF,  p-value: < 0.00000000000000022
# Scatter plot de log(pl_radj) vs pl_rvamp con la recta de regresión en rojo
# y los margenes de confianza en gris
ggplot(kepler_data_num, aes(x = pl_rvamp, y = log(pl_radj))) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Regresión Lineal: Logaritmo del Radio del Exoplaneta segun Logaritmo de la Amplitud de la Velocidad Radial",
       x = "Logaritmo de la Amplitud de la Velocidad Radial",
       y = "Logaritmo del Radio del Exoplaneta (JĆŗpiter)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

Para el modelo de regresión planteado:

\[ log(pl\_radj) = \beta_0 + \beta_1 \cdot pl\_rvamp + \varepsilon \]

El anÔlisis del modelo después de aplicar la transformación logarítmica muestra una mejora significativa en su capacidad predictiva. El R² obtenido es de 84.25%, lo que indica que el modelo explica una gran parte de la variabilidad en log(pl_radj), representando un ajuste excelente. Este resultado es considerablemente mejor que el del modelo sin transformación, donde el R² era aproximadamente 53.67%.

Incluso al corregir por el nĆŗmero de predictores, el R² ajustado sigue siendo alto, con un valor de 84.01%, lo que confirma que el modelo mantiene su solidez y no se ve afectado por un exceso de predictores innecesarios. AdemĆ”s, el estadĆ­stico F, con un valor de 353 y un p-valor extremadamente bajo (< 2.2 Ɨ 10⁻¹⁶), confirma que el modelo es altamente significativo y que la relación entre las variables no es producto del azar.

En conclusión, la transformación logarítmica ha mejorado significativamente el ajuste del modelo en comparación con el modelo sin transformación. La relación entre pl_rvamp y log(pl_radj) es fuerte y altamente significativa, lo que sugiere que este modelo es mucho mÔs adecuado para describir la relación entre estas variables y ofrece estimaciones mÔs precisas.

# Obtener los residuos y valores ajustados
res_pl_rvamp_log <- residuals(model_pl_rvamp_log)

# Calcular los valores ajustados
fit_val_pl_rvamp_log <- fitted(model_pl_rvamp_log)

# Crear un data frame con los residuos y valores ajustados
res_pl_rvamp_log_df <- data.frame(
  Residuals = res_pl_rvamp_log,
  Fitted_Values = fit_val_pl_rvamp_log
)

# Scatter plot de residuos vs valores ajustados
ggplot(res_pl_rvamp_log_df, aes(x = Fitted_Values, y = Residuals)) +
  geom_point(color = "steelblue") +
  geom_hline(yintercept = 0, color = "indianred", linetype = "dashed") +
  labs(title = "Residuos vs Valores Ajustados",
       x = "Valores Ajustados",
       y = "Residuos") +
  theme_minimal()

Después de aplicar la transformación, se observa una reducción en la dispersión de los residuos, lo que indica que la heterocedasticidad detectada previamente ha disminuido considerablemente. Esto significa que la varianza de los errores es ahora mÔs constante a lo largo de los valores ajustados, cumpliendo mejor con la suposición de homocedasticidad en la regresión lineal.

La disminución en la variabilidad de los residuos sugiere que el modelo ha logrado un ajuste mÔs estable y confiable. Esto no solo mejora la precisión de las estimaciones, sino que también aumenta la validez de los intervalos de confianza y las pruebas de hipótesis, ya que las predicciones del modelo son menos sensibles a valores extremos o patrones no deseados en los errores.

# Crear un grƔfico Q-Q de los residuos
qqnorm(res_pl_rvamp_log, main = "GrƔfico Q-Q de los Residuos", col="indianred")

La alineación de los puntos con la línea diagonal en el grÔfico sugiere que los residuos siguen aproximadamente una distribución normal. La mayor parte de los puntos se ajusta bien a la línea teórica, lo que indica que el supuesto de normalidad en los residuos se cumple en gran medida.

Sin embargo, en los extremos del grÔfico, correspondientes a los valores mÔs negativos y mÔs positivos de los residuos, se observa una ligera desviación. Esto sugiere que la distribución de los residuos tiene colas ligeramente mÔs pesadas, lo que implica la posible presencia de algunos valores atípicos o extremos.

A pesar de esta leve desviación en los valores extremos, el patrón general indica que los residuos siguen una distribución normal de manera aceptable. Esto significa que el modelo sigue siendo estadísticamente vÔlido para realizar inferencias, aunque la presencia de valores extremos podría justificar un anÔlisis mÔs detallado si se requiere mayor precisión en las estimaciones.

# Prueba de normalidad de Shapiro-Wilk
shapiro_test_pl_rvamp_log <- shapiro.test(res_pl_rvamp_log)

shapiro_test_pl_rvamp_log
## 
##  Shapiro-Wilk normality test
## 
## data:  res_pl_rvamp_log
## W = 0.97622, p-value = 0.2188

El test de normalidad de Shapiro-Wilk arroja un estadístico W de 0.97622 y un p-valor de 0.2188, lo que indica que no hay evidencia suficiente para rechazar la hipótesis de normalidad. Esto significa que los residuos siguen una distribución normal, cumpliendo con una de las principales suposiciones del modelo.

Si bien el grÔfico Q-Q ya mostraba una buena alineación de los puntos con la línea diagonal, la prueba estadística confirma de manera mÔs rigurosa que los residuos no presentan desviaciones significativas respecto a una distribución normal. Esto refuerza la validez del modelo y la fiabilidad de sus estimaciones.

# Prueba de homocedasticidad de Breusch-Pagan
library(lmtest)

# Prueba de Breusch-Pagan
bp_test_pl_rvamp_log <- bptest(model_pl_rvamp_log)

bp_test_pl_rvamp_log
## 
##  studentized Breusch-Pagan test
## 
## data:  model_pl_rvamp_log
## BP = 0.48865, df = 1, p-value = 0.4845

El test de homocedasticidad de Breusch-Pagan muestra un estadístico BP de 0.48865 y un p-valor de 0.4845, lo que indica que no hay evidencia de heterocedasticidad significativa en el modelo. Esto significa que la varianza de los errores es constante, cumpliendo con una de las suposiciones clave de la regresión lineal. Dado que los modelos anteriores presentaban problemas de heterocedasticidad, estos resultados confirman que la transformación logarítmica aplicada a la variable dependiente corrigió eficazmente este problema.

Tras evaluar los tres modelos de regresión lineal univariada, se concluye que el modelo pl_radj ~ pl_rvamp con transformación logarítmica es el que ofrece el mejor ajuste.

\[ log(pl\_radj) = \beta_0 + \beta_1 \cdot pl\_rvamp + \varepsilon \]

Este modelo explica el 84.25% de la variabilidad en log(pl_radj), lo que indica una capacidad predictiva excelente. AdemÔs, la relación entre pl_rvamp y log(pl_radj) es fuerte y altamente significativa, con residuos que siguen una distribución normal y no presentan heterocedasticidad significativa.

Conclusión sobre los modelos lineales univariados planteados

A lo largo del anÔlisis, se probaron diferentes enfoques para ajustar la relación entre las variables, considerando tanto modelos sin transformación como con transformaciones matemÔticas para mejorar su estabilidad. Inicialmente, los modelos sin transformación mostraron problemas de heterocedasticidad y normalidad en los residuos, lo que afectaba la validez de sus inferencias. Sin embargo, la aplicación de una transformación logarítmica a la variable dependiente (pl_radj) permitió corregir estos problemas, logrando un modelo mÔs estable y confiable.

# Resumen de los modelos de regresión lineal univariada
model_summaries <- list(
  model_pl_ratdor_summary,
  model_pl_trandep_summary,
  model_pl_trandep_square_summary,
  model_pl_rvamp_summary,
  model_pl_rvamp_log_summary
)

model_summaries
## [[1]]
## 
## Call:
## lm(formula = pl_radj ~ pl_ratdor, data = kepler_data_num)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.3749 -0.2695 -0.2125  0.3126  1.2264 
## 
## Coefficients:
##              Estimate Std. Error t value        Pr(>|t|)    
## (Intercept) 0.4086542  0.0535610   7.630 0.0000000000489 ***
## pl_ratdor   0.0007341  0.0005069   1.448           0.152    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3872 on 78 degrees of freedom
##   (2467 observations deleted due to missingness)
## Multiple R-squared:  0.02618,    Adjusted R-squared:  0.0137 
## F-statistic: 2.097 on 1 and 78 DF,  p-value: 0.1516
## 
## 
## [[2]]
## 
## Call:
## lm(formula = pl_radj ~ pl_trandep, data = kepler_data_num)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.203530 -0.056704  0.002386  0.056979  0.150580 
## 
## Coefficients:
##             Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)  0.22308    0.01590   14.03 <0.0000000000000002 ***
## pl_trandep   0.61058    0.02434   25.08 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.08315 on 40 degrees of freedom
##   (2505 observations deleted due to missingness)
## Multiple R-squared:  0.9402, Adjusted R-squared:  0.9387 
## F-statistic: 629.1 on 1 and 40 DF,  p-value: < 0.00000000000000022
## 
## 
## [[3]]
## 
## Call:
## lm(formula = I(pl_radj^2) ~ pl_trandep, data = kepler_data_num)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.108946 -0.015184 -0.004665  0.010102  0.134871 
## 
## Coefficients:
##             Estimate Std. Error t value            Pr(>|t|)    
## (Intercept) 0.010364   0.007744   1.338               0.188    
## pl_trandep  0.803698   0.011855  67.795 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.04049 on 40 degrees of freedom
##   (2505 observations deleted due to missingness)
## Multiple R-squared:  0.9914, Adjusted R-squared:  0.9912 
## F-statistic:  4596 on 1 and 40 DF,  p-value: < 0.00000000000000022
## 
## 
## [[4]]
## 
## Call:
## lm(formula = pl_radj ~ pl_rvamp, data = kepler_data_num)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.5172 -0.2119 -0.1206  0.2644  0.8116 
## 
## Coefficients:
##             Estimate Std. Error t value         Pr(>|t|)    
## (Intercept) 0.337785   0.041804   8.080 0.00000000001903 ***
## pl_rvamp    0.003550   0.000406   8.744 0.00000000000124 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3026 on 66 degrees of freedom
##   (2479 observations deleted due to missingness)
## Multiple R-squared:  0.5367, Adjusted R-squared:  0.5297 
## F-statistic: 76.46 on 1 and 66 DF,  p-value: 0.000000000001239
## 
## 
## [[5]]
## 
## Call:
## lm(formula = log(pl_radj) ~ log(pl_rvamp), data = kepler_data_num)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.09181 -0.30754  0.04893  0.21513  0.98300 
## 
## Coefficients:
##               Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)   -2.06303    0.06935  -29.75 <0.0000000000000002 ***
## log(pl_rvamp)  0.44267    0.02356   18.79 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3753 on 66 degrees of freedom
##   (2479 observations deleted due to missingness)
## Multiple R-squared:  0.8425, Adjusted R-squared:  0.8401 
## F-statistic:   353 on 1 and 66 DF,  p-value: < 0.00000000000000022

El modelo final con transformación logarítmica no solo ofrece un mejor ajuste y mayor capacidad explicativa, sino que también cumple con los supuestos clave de la regresión lineal, lo que lo convierte en la mejor opción para modelar la relación entre pl_radj y pl_rvamp. Este resultado subraya la importancia de evaluar la calidad del ajuste y de realizar transformaciones adecuadas cuando se detectan desviaciones en los supuestos del modelo, garantizando así estimaciones mÔs precisas y robustas.

Regresión lineal multivariada

Para mejorar la precisión en la predicción del radio del exoplaneta (pl_radj), se lleva a cabo un anÔlisis de regresión lineal multivariada. En este enfoque, se consideran simultÔneamente tres variables explicativas que podrían influir en el radio del exoplaneta:

  1. El cociente del radio planetario sobre el radio estelar (pl_ratdor), que representa el tamaño relativo del exoplaneta en comparación con su estrella.
  2. La profundidad del trÔnsito (pl_trandep), que mide la disminución en el brillo de la estrella cuando el exoplaneta pasa frente a ella, lo que estÔ directamente relacionado con su tamaño.
  3. La amplitud de la velocidad radial del planeta (pl_rvamp), que refleja el impacto gravitacional del exoplaneta sobre su estrella y puede proporcionar información sobre su masa y, en combinación con otras variables, su radio.

Este modelo de regresión multivariada permite analizar cómo estas tres variables influyen en conjunto en la predicción del radio del exoplaneta, en lugar de evaluar cada una por separado. Al considerar múltiples factores al mismo tiempo, se espera obtener un modelo mÔs preciso y robusto, capaz de capturar mejor la variabilidad en los datos y proporcionar estimaciones mÔs confiables del tamaño de los exoplanetas.

# Regresion de pl_radj con pl_ratdor, pl_trandep y pl_rvamp
model_multivar <- lm(pl_radj ~ pl_ratdor + pl_trandep + pl_rvamp, data = kepler_data_num)

model_multivar_summary <- summary(model_multivar)

model_multivar_summary
## 
## Call:
## lm(formula = pl_radj ~ pl_ratdor + pl_trandep + pl_rvamp, data = kepler_data_num)
## 
## Residuals:
##      611     1785     1822     1946     1947     2251     2465     2541 
##  0.00903 -0.07158 -0.03219  0.08415 -0.01535  0.09444 -0.08736  0.01885 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.2110174  0.0531204   3.972 0.016505 *  
## pl_ratdor    0.0001583  0.0004277   0.370 0.730111    
## pl_trandep   0.7120088  0.0781077   9.116 0.000803 ***
## pl_rvamp    -0.0008151  0.0006926  -1.177 0.304472    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.08727 on 4 degrees of freedom
##   (2539 observations deleted due to missingness)
## Multiple R-squared:  0.9731, Adjusted R-squared:  0.953 
## F-statistic: 48.28 on 3 and 4 DF,  p-value: 0.001342

El modelo de regresión planteado:

\[ pl\_radj = \beta_0 + \beta_1 \cdot pl\_ratdor + \beta_2 \cdot pl\_trandep + \beta_3 \cdot pl\_rvamp + \varepsilon \] Presenta buenas estadĆ­sticas por cuanto:

El modelo de regresión muestra un excelente ajuste, explicando el 97.31% de la variabilidad en pl_radj. Incluso después de ajustar por el número de predictores, el R² ajustado sigue siendo alto, con un 95.3%, lo que indica que el modelo generaliza bien y mantiene una fuerte capacidad predictiva. AdemÔs, el estadístico F de 48.28 y un p-valor de 0.0013 confirman que el modelo en su conjunto es altamente significativo, lo que sugiere que al menos una de las variables predictoras tiene un impacto relevante en la estimación de pl_radj.

Sin embargo, existen algunas limitaciones importantes. Después de eliminar los datos con valores faltantes, solo quedan 4 observaciones efectivas, lo que es extremadamente bajo para un modelo con tres predictores. Esta reducción drÔstica en la cantidad de datos puede hacer que el modelo sea poco confiable y que las estimaciones de los coeficientes sean inestables, ya que se basan en una muestra demasiado pequeña.

AdemÔs, se han descartado 2,539 observaciones debido a valores faltantes, lo que plantea la necesidad de revisar la estructura del dataset. Evaluar si se pueden recuperar mÔs observaciones permitiría mejorar la estabilidad del modelo y evitar conclusiones basadas en un número tan reducido de datos.

Dado que la variable pl_trandep es la mÔs significativa dentro del modelo, una posible alternativa sería simplificar la regresión eliminando pl_ratdor y pl_rvamp, dejando solo pl_trandep como predictor. Esto llevaría al segundo modelo evaluado, que podría ofrecer un ajuste igualmente bueno pero con una estructura mÔs sencilla y posiblemente mÔs robusta frente a la escasez de datos.

Regresión logística

Para predecir la habitabilidad de los exoplanetas, se realiza un anÔlisis de regresión logística utilizando las variables conocidas de los exoplanetas y las estrellas del sistema. Se seleccionan las variables conocidas de los exoplanetas y las estrellas como variables independientes y la habitabilidad como variable dependiente.

Existen varios indicadores de habitabilidad de los exoplanetas. Considerando que estamos estudiando estrellas con radios similiares al solar (+/- 10%) los parÔmetros planetarios mÔs relevantes se describen a continuación.

La temperatura de equilibrio (pl_eqt) planetaria es una variable fundamental en la definición de la zona habitable, ya que estÔ directamente relacionada con la posibilidad de agua líquida en la superficie de un planeta. En (Kopparapu, R. K., Ramirez, R., Kasting, J. F., Eymet, V., Robinson, T. D., Mahadevan, S., Terrien, R. C., Domagal-Goldman, S., Meadows, V., & Deshpande, R., n.d.) se analizan factores para ajustar los límites de la zona habitable y define los rangos ideales de temperatura para habitabilidad. - La insolación (pl_insol), esto es flujo de radiación recibido por el planeta en comparación con la Tierra, es otro predictor clave, ya que determina el balance energético del planeta. En (Shields, Aomawa L., Ballard, Sarah, & Johnson, John Asher, n.d.) se estudian los efectos del flujo de radiación en la zona habitable y su impacto en la capacidad de un planeta para retener agua. - El semieje mayor orbital (pl_orbsmax) es otro indicador importante, ya que determina la distancia del planeta a su estrella anfitriona y, por lo tanto, su temperatura superficial. En (Kane, Stephen R. & Gelino, Dawn M., n.d.) se demuestra cómo la distancia orbital y la luminosidad de la estrella afectan la habitabilidad.

La determinación de la habitabilidad de un exoplaneta es un tema complejo y multifactorial que depende de varios indicadores fĆ­sicos y quĆ­micos. Si bien no existe una fórmula Ćŗnica universalmente aceptada para calcular la ā€œhabitabilidadā€, se pueden combinar los indicadores antes mencionados para aproximar el potencial de habitabilidad de un exoplaneta. Una de las aproximaciones mĆ”s comunes es usar una combinación ponderada de las condiciones adecuadas para la presencia de agua lĆ­quida, ya que esta es fundamental para la vida tal como la conocemos. El uso de una combinación lineal ponderada de variables tales como las consideradas es una tĆ©cnica vĆ”lida en la modelización de habitabilidad planetaria. En (MĆ©ndez, Abel, Rivera-Valentin, Edgard, Schulze-Makuch, Dirk, Filiberto, Justin, Ramirez, Ramses, Wood, Tana, DĆ”vila, Alfonso, McKay, Chris, Ceballos, Kevin, Jusino-Maldonado, Marcos, Torres-Santiago, Nicole, Gomez, Guillermo Nery, Heller, RenĆ©, Byrne, Paul, Malaska, Michael, Nathan, Erica, SimƵes, Marta, Antunes, AndrĆ©, MartĆ­nez-FrĆ­as, JesĆŗs, & Haqq-Misra, Jacob., n.d.) se propone el Earth Similarity Index (ESI), que usa una fórmula normalizada combinando temperatura, flujo estelar y parĆ”metros orbitales.

AsĆ­ con los indicadores seleccionados definimos un ƍndice de Habitabilidad Planetaria (PHI - Planetary Habitability Index) como una función normalizada que combine los indicadores clave:

\[ \text{PHI} = w_1 \cdot f_1(\text{pl_eqt}) + w_2 \cdot f_2(\text{pl_insol}) + w_3 \cdot f_3(\text{pl_orbsmax}) \]

Donde:

  • \(w_i\) son los pesos normalizados asociados a cada indicador sumando 1.
  • \(f_i(x)\) son funciones de transformación o normalización que convierten las medidas en valores entre 0 y 1, segĆŗn el rango de habitabilidad conocido.

Estas variables se consideran como posibles predictores de la habitabilidad de los exoplanetas cuando estƔn en determinados rangos.

Temperatura de equilibrio (pl_eqt)

Idealmente la temperatua de equilibrio debe estar en un rango compatible con agua líquida, aproximadamente entre 0°C y 100°C. Así la normalización resultan en:

\[ f_i(\text{pl_eqt}) = \max\left(0, \min\left(1, \frac{\text{pl_eqt} - T_{\text{min}}}{T_{\text{max}} - T_{\text{min}}}\right)\right) \]

Donde \(T_{\text{min}}\) y \(T_{\text{max}}\) son los límites inferiores y superiores. El agua líquida, esencial para la vida, puede existir en un rango de temperaturas superficiales de aproximadamente 273K (0 °C) a 373K (100 °C). Sin embargo, debido a factores atmosféricos y de presión, este rango puede extenderse ligeramente: \(T_{\text{min}}=200K\) puede ser el umbral inferior, considerando atmósferas densas como la de Marte y \(T_{\text{max}}=400K\) puede considerarse el umbral superior, considerando atmósferas con alta presión como la de Venus.

Según la literatura especializada el peso de la temperatura de equilibrio en el índice de habitabilidad es de \(w_1=0.40\) cuando se considera la temperatura de equilibrio como un indicador preponderante de habitabilidad y no se tienen muchos mÔs datos del planeta.

La insolación (pl_insol)

La insolación es la cantidad de energía recibida por el planeta y es un indicador importante de la habitabilidad. La insolación se mide en unidades de flujo de energía recibida por unidad de Ôrea y se puede normalizar en un rango de 0 a 1. La insolación ideal para la vida es aquella que permite la presencia de agua líquida en la superficie del planeta (generalmente valores cercanos a la Tierra son ideales). La insolación se puede normalizar considerando que La Tierra tiene una insolación de 1S (donde \(S\) es la insolación solar a la distancia de la Tierra) y se puede considerar que la vida puede existir en un rango de insolación de \(I_{min}=0.3S\) (aproximadamente el límite interior de la zona habitable para una estrella como el Sol, mÔs allÔ de este valor el agua podría congelarse) a \(I_{max}=1,7S\) (aproximadamente el límite exterior de la zona habitable, mÔs allÔ de este valor el agua podría evaporarse). Así la normalización resulta en:

\[ f_2(\text{pl_insol}) = \max\left(0, \min\left(1, \frac{\text{pl_insol} - I_{\text{min}}}{I_{\text{max}} - I_{\text{min}}}\right)\right) \]

La insolación es un factor crítico para mantener agua líquida en la superficie del planeta, pero su impacto depende de otros factores como la atmósfera y el albedo, según la literatura especializada el peso de la insolación en el índice de habitabilidad es de \(w_2=0.30\). Es importante destacar que El rango de \(I_{min}\) e \(I_{max}\) puede variar según la luminosidad de la estrella, ya que la zona habitable cambia en función del tipo estelar por lo que esta estimación sirve para estrellas similares al Sol.

La distancia orbital del semieje mayor (pl_orbsmax)

La distancia orbital semieje mayor es un indicador de la zona habitable de un sistema planetario. La distancia orbital semieje mayor se mide en unidades astronómicas (UA) y se puede normalizar en un rango de 0 a 1. La distancia orbital semieje mayor ideal para la vida es aquella que permite la presencia de agua líquida en la superficie del planeta. La distancia orbital semieje mayor se puede normalizar considerando que La Tierra tiene una distancia orbital semieje mayor de 1 UA y se puede considerar que la vida puede existir en un rango de distancias de \(D_{\text{min}}=0,5\) UA (aproximadamente el límite interior de la zona habitable para una estrella como el Sol, mÔs allÔ de este valor el agua podría congelarse) a \(D_{\text{max}}=2\) UA (aproximadamente el límite exterior de la zona habitable, mÔs allÔ de este valor el agua podría evaporarse). Estos rangos pueden variar según el tipo de estrella. Así la normalización resulta en:

\[ f_3(\text{pl_orbsmax}) = \max\left(0, \min\left(1, \frac{\text{pl_orbsmax} - D_{\text{min}}}{D_{\text{max}} - D_{\text{min}}}\right)\right) \]

En la mayoría de los modelos, el peso para el valor normalizado de pl_orbsmax oscila entre 15% y 25%. Esto se debe a que pl_orbsmax complementa indicadores mÔs directos como pl_eqt (temperatura de equilibrio) y pl_insol (insolación). Se tomarÔ un peso de \(w_3=0.30\).

ƍndice de habitabilidad planetaria (PHI)

Por lo expuesto anteriormente, el ƍndice de Habitabilidad Planetaria (PHI) se calcula utilizando variables normalizadas y sus respectivos pesos, lo que permite evaluar la habitabilidad de un exoplaneta de manera mĆ”s equilibrada y comparable entre diferentes sistemas.

La fórmula para calcular el PHI que se utilizarÔ en el modelo de regresión logística es:

\[ \text{PHI} = 0.4 \cdot f_1(\text{pl_eqt}) + 0.3 \cdot f_2(\text{pl_insol}) + 0,3 \cdot f_3(\text{pl_orbsmax}) \]

library(dplyr)

# Normalizar las variables
kepler_data <- kepler_data %>%
  mutate(
    pl_eqt_normalized = pmin(1, pmax(0, (pl_eqt - 200) / (400 - 200))),
    pl_insol_normalized = pmin(1, pmax(0, (pl_insol - 0.3) / (1.7 - 0.3))),
    pl_orbsmax_normalized = pmin(1, pmax(0, (pl_orbsmax - 0.05) / (2 - 1.05)))
  )

# Calcular el Ć­ndice de habitabilidad planetaria (PHI)
kepler_data <- kepler_data %>%
  mutate(
    phi = 0.4 * pl_eqt_normalized + 0.3 * pl_insol_normalized + 0.3 * pl_orbsmax_normalized 
  )
# Crear un modelo de regresión logística
model_logistic <- glm(phi ~ pl_eqt_normalized + pl_insol_normalized + pl_orbsmax_normalized , data = kepler_data, family = binomial)
## Warning in eval(family$initialize): non-integer #successes in a binomial glm!
model_logistic_summary <- summary(model_logistic)

model_logistic_summary
## 
## Call:
## glm(formula = phi ~ pl_eqt_normalized + pl_insol_normalized + 
##     pl_orbsmax_normalized, family = binomial, data = kepler_data)
## 
## Coefficients:
##                       Estimate Std. Error z value Pr(>|z|)
## (Intercept)             -2.488      7.878  -0.316    0.752
## pl_eqt_normalized        2.228     11.813   0.189    0.850
## pl_insol_normalized      1.105      6.760   0.163    0.870
## pl_orbsmax_normalized    1.569      6.123   0.256    0.798
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 0.45354364  on 16  degrees of freedom
## Residual deviance: 0.00063461  on 13  degrees of freedom
##   (2530 observations deleted due to missingness)
## AIC: 19.641
## 
## Number of Fisher Scoring iterations: 4
# Graficar la curva logistica del modelo
# Crear un data frame con los valores de PHI y las probabilidades predichas
# de habitabilidad. Seleccionar solo los registros donde se conoce la habitabilidad
phi_prob <- predict(model_logistic, type = "response")

# Filtrar los registros donde se conoce la habitabilidad
kepler_data_phi <- kepler_data %>%
  filter(!is.na(phi))

phi_prob_df <- data.frame(PHI = kepler_data_phi$phi, Probabilidad = phi_prob)

# Scatter plot de PHI vs Probabilidad
ggplot(phi_prob_df, aes(x = PHI, y = Probabilidad)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "glm", method.args = list(family = "binomial"), color = "indianred", fill = "grey", alpha = 0.2) +
  labs(title = "Curva Logística del Modelo de Regresión",
       x = "PHI",
       y = "Probabilidad") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

El modelo de regresión logística obtenido no es particularmente sólido debido a la escasez de datos disponibles para calcular el PHI (Planetary Habitability Index). En este caso, la cantidad de exoplanetas con información completa sobre los factores clave para la predicción, como temperatura de equilibrio, insolación y semieje mayor orbital, es muy limitada, con solo 17 observaciones disponibles.

La baja cantidad de datos afecta significativamente la precisión y confiabilidad del modelo, ya que un tamaño de muestra tan reducido limita la capacidad de generalización y hace que los coeficientes del modelo sean menos estables. Para obtener un modelo mÔs robusto y representativo, sería necesario contar con un mayor número de exoplanetas con datos completos, lo que permitiría entrenar la regresión con mÔs información y mejorar la validez de las predicciones sobre habitabilidad.

El modelo de regresión logística planteado presenta varias limitaciones que afectan su utilidad y confiabilidad.

\[ \log \left( \frac{P(\phi = 1)}{1 - P(\phi = 1)} \right) = -2.488 + 2.228 \cdot \text{pl_eqt_normalized} + 1.105 \cdot \text{pl_insol_normalized} + 1.569 \cdot \text{pl_orbsmax_normalized} \]

Uno de los principales problemas es la drÔstica reducción en la deviance residual, que pasó de 0.4535 (sin predictores) a 0.0006 (con predictores). Si bien una reducción en la deviance suele indicar una mejora en el modelo, en este caso el valor extremadamente bajo sugiere un sobreajuste, lo que significa que el modelo estÔ ajustÔndose demasiado a los pocos datos disponibles y podría no generalizar bien a nuevas observaciones.

El criterio de información de Akaike (AIC), con un valor de 19.641, indica que el modelo penaliza adecuadamente la complejidad, pero la falta de significancia en los coeficientes sugiere que no es útil para la predicción, ya que no logra establecer una relación clara entre las variables.

Otro problema grave es la eliminación de datos faltantes, que dejó solo 17 observaciones disponibles después de descartar 2,530 registros incompletos. Con tan pocos datos, los grados de libertad (df=13) son extremadamente bajos, lo que afecta la estabilidad del modelo y hace que las estimaciones sean poco confiables.

En su estado actual, el modelo no es útil, ya que no cuenta con variables predictoras significativas y enfrenta una pérdida masiva de datos, lo que limita su capacidad para hacer inferencias vÔlidas. Antes de sacar conclusiones sobre la relación entre PHI y las variables predictoras, sería recomendable limpiar los datos y probar un modelo mÔs simple. Sin embargo, dada la escasez de observaciones, es posible que no sea factible construir un modelo confiable para la predicción de habitabilidad en estas condiciones.

Predicción de PHI con datos faltantes

Dado que el índice de habitabilidad planetaria (PHI) sólo pudo calcularse para 17 planetas, y que el resto del conjunto, 2530 observaciones, presenta datos faltantes en variables clave, la aplicación directa de un modelo supervisado como la regresión logística no resulta viable sin recurrir a imputaciones extensas y potencialmente sesgadas. En lugar de ello, se intenta un enfoque semi-supervisado combinando clustering con LightGBM. Primero, se aplica el algoritmo de agrupamiento K-means a la totalidad del conjunto de datos (sin utilizar las etiquetas), con el fin de identificar estructuras latentes en el espacio de variables. Luego, se analizan los 17 planetas con PHI calculado para verificar si se concentran en uno o mÔs de estos clústeres. Finalmente, se utilizan los clusters como etiquetas débiles para entrenar un modelo con LightGBM, lo que permite aprovechar la información estructural del conjunto completo y facilitar la generalización en contextos donde las etiquetas son escasas, como es común en astronomía y otros campos científicos.

En contextos donde la disponibilidad de datos etiquetados es extremadamente limitada, los métodos de aprendizaje semi-supervisado ofrecen una alternativa eficaz para aprovechar la estructura latente de los datos no etiquetados. Una estrategia ampliamente utilizada es el pseudo-etiquetado, que consiste en asignar etiquetas estimadas a ejemplos no etiquetados y utilizarlas en conjunto con las etiquetas reales para entrenar modelos supervisados. Este enfoque fue formalizado por (Lee, D.-H., n.d.), quien demostró que el uso iterativo de pseudo-etiquetas puede mejorar significativamente el rendimiento de los modelos, incluso con cantidades mínimas de datos anotados. Por otro lado, (Zhou, D., Bousquet, O., Lal, T. N., Weston, J., & Schölkopf, B., n.d.) introdujeron el concepto de propagación de etiquetas sobre grafos construidos a partir de la similitud entre ejemplos, lo que respalda el uso de algoritmos de agrupamiento como K-means para difundir información de las etiquetas escasas a través de la estructura del conjunto de datos. En combinación, estos enfoques permiten construir modelos robustos a partir de datos predominantemente no etiquetados, como en el caso de la estimación del índice de habitabilidad planetaria (PHI), donde menos del 1% de los registros disponibles incluyen una etiqueta confiable.

Primero se aplica el algoritmo de agrupamiento K-means a la totalidad del conjunto de datos (sin utilizar las etiquetas), con el fin de identificar estructuras latentes en el espacio de variables. Para ello, se imputa NA con la mediana por columna y se eliminan columnas con valores no finitos.

library(dplyr)
library(lightgbm)
library(Matrix)
## 
## Attaching package: 'Matrix'
## The following objects are masked from 'package:tidyr':
## 
##     expand, pack, unpack
# asignar un id numerico Ćŗnico a cada fila
kepler_data <- kepler_data %>%
  mutate(id = row_number())

# Separar PHI y features
# Filtrar columnas numƩricas **con solo valores finitos**
features <- kepler_data %>%
  dplyr::select(where(is.numeric)) %>%
  dplyr::select(where(~ all(is.finite(.))))
phi <- kepler_data$phi

# Se imputa NA con la mediana por columna
# La imputacion es sólo para aplicar k-means, no para entrenar LightGBM
features_imputed <- features %>%
  mutate(across(where(is.numeric), ~ ifelse(is.na(.), median(., na.rm = TRUE), .)))

# Aplicar K-means con k = 17
set.seed(random_seed)
kmeans_result <- kmeans(scale(features_imputed), centers = 17, nstart = 25)
clusters <- kmeans_result$cluster

Dada la alta dimensionalidad de los datos, se utiliza PCA para visualizar los clústeres. En este caso, se seleccionan los dos primeros componentes principales para la visualización en 2D. AdemÔs se muestran los 17 planetas con PHI conocido.

library(ggplot2)

# 1. Asegurarse de que features estÔ estandarizado (como se usó en K-means)
features_scaled <- scale(features)

# 2. Ejecutar PCA
pca_result <- prcomp(features_scaled)
pca_data <- as.data.frame(pca_result$x[, 1:2])  # Tomamos solo PC1 y PC2

# 3. Agregar cluster y si tiene PHI
pca_data$cluster <- as.factor(clusters)
pca_data$has_phi <- !is.na(kepler_data$phi)

# 4. Graficar
ggplot(pca_data, aes(x = PC1, y = PC2, color = cluster)) +
  geom_point(alpha = 0.6, size = 2) +
  geom_point(data = subset(pca_data, has_phi), 
             aes(x = PC1, y = PC2), 
             shape = 17, size = 3.5, color = "black") +
  labs(
    title = "Clusters de K-means visualizados con PCA",
    subtitle = "Los triƔngulos negros indican planetas con PHI conocido",
    x = "Componente Principal 1",
    y = "Componente Principal 2"
  ) +
  theme_minimal()

Segundo se analiza si los 17 planetas con PHI calculado se concentran en uno o mÔs de estos clústeres. Para ello, se propagan etiquetas débiles a través de los clústeres, asignando el valor promedio de PHI a los planetas no etiquetados dentro de cada clúster. Si un clúster no tiene etiquetas, se asigna el promedio del clúster mÔs cercano.

# Propagar PHI promedio dentro de cada cluster
pseudo_phi <- numeric(length(phi))
for (cluster_id in unique(clusters)) {
  in_cluster <- clusters == cluster_id
  labeled <- !is.na(phi) & in_cluster
  unlabeled <- is.na(phi) & in_cluster

  if (sum(labeled) > 0) {
    phi_mean <- mean(phi[labeled])
    pseudo_phi[unlabeled] <- phi_mean
    pseudo_phi[labeled] <- phi[labeled]  # mantener valores reales
  } else {
    # buscar cluster mƔs cercano con PHI
    centroids <- kmeans_result$centers
    dists <- apply(centroids, 1, function(c) sum((centroids[cluster_id, ] - c)^2))
    dists[cluster_id] <- Inf
    nearest_cluster <- which.min(dists)
    phi_mean <- mean(phi[clusters == nearest_cluster & !is.na(phi)])
    pseudo_phi[unlabeled] <- phi_mean
  }
}

# Crear pesos: mƔs alto para muestras reales
weights <- ifelse(is.na(phi), 1, 10)

Tercero se entrena el modelo LightGBM utilizando los clusters como etiquetas dƩbiles y los pesos para ajustar la importancia de las muestras reales frente a las no etiquetadas.

# Antes de entrenar el modelo, se eliminan los PHI
kepler_data <- kepler_data %>%
  mutate(phi = NULL)
# Entrenar modelo LightGBM
# Convertir a matriz de LightGBM
X_matrix <- as.matrix(features)
dtrain <- lgb.Dataset(data = X_matrix, label = pseudo_phi, weight = weights)

params <- list(
  objective = "regression",
  metric = "l2",
  learning_rate = 0.05,
  num_leaves = 31
)

lgbm_model <- lgb.train(
  params = params,
  data = dtrain,
  nrounds = 100
)
## [LightGBM] [Info] Auto-choosing row-wise multi-threading, the overhead of testing was 0.003168 seconds.
## You can set `force_row_wise=true` to remove the overhead.
## And if memory is not enough, you can set `force_col_wise=true`.
## [LightGBM] [Info] Total Bins 1806
## [LightGBM] [Info] Number of data points in the train set: 2547, number of used features: 11
## [LightGBM] [Info] Start training from score 0.600569
# Predecir PHI estimado
phi_pred <- predict(lgbm_model, X_matrix)
kepler_data$phi_estimated <- phi_pred

# Asignar los valores predichos a la columna phi_estimated
# en data original siguiendo la correspondencia de id
kepler_data <- kepler_data %>%
  mutate(phi_estimated = phi_pred[match(id, kepler_data$id)])

# Guardar el dataset con los valores predichos
# en el archivo CSV "kepler_data_with_phi.csv"
write.csv(kepler_data, "keplerdataestimated.csv", row.names = FALSE)

Interpretación del modelo LightGBM: importancia de las variables

# Importancia de las variables
lgb.importance(lgbm_model) %>%
  lgb.plot.importance(top_n = 20, measure = "Gain")

Con 17 centroides, el Ôrbol estimado muestra que las variables con mayor importancia no relacionadas con las caracterísiticas del sistema estelar son ttv_flag (indicador de trÔnsito variable), sy_pnum (cantidad de planetas en el sistema) y st_rad (radio de la estrella central del sistema) son la que se esperaría que tenga un impacto significativo en la habitabilidad, ya que estÔn relacionadas con características físicas del sistema estelar. No es razonable que el modelo haya aprendido a predecir el PHI a partir de la latitud y longitud de los planetas en el firmamento, ya que no deberían influir en la habitabilidad. Sin embargo, es posible que el modelo haya capturado patrones relacionados con la ubicación de los planetas en el espacio de características, lo que podría ser útil para identificar grupos de planetas con características similares.

Histograma de PHI estimado

# Histograma de PHI estimado
ggplot(kepler_data, aes(x = phi_estimated)) +
  geom_histogram(binwidth = 0.05, fill = "steelblue", color = "black", alpha = 0.7) +
  stat_bin(binwidth = 0.05, geom = "text", aes(label = after_stat(count)),
           vjust = -0.5, color = "black", size = 3) +
  scale_x_continuous(breaks = seq(0, 1, by = 0.05)) +
  labs(title = "Histograma de PHI Estimado",
       x = "PHI Estimado",
       y = "Frecuencia") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))

El histograma de PHI estimado muestra una distribución sesgada hacia la derecha con picos en 0, 0.55, 0.65, 0.70 y 0.75, lo que sugiere que el modelo ha aprendido a predecir un valor de PHI relativamente alto para la mayoría de los planetas. Esto puede ser un indicativo de que el modelo ha capturado patrones en los datos, pero también puede reflejar la influencia de las etiquetas débiles y la falta de datos reales.`

# Contar la cantidad de planetas con phi_estimated > 0.70
habitable_planets <- sum(kepler_data$phi_estimated > 0.70, na.rm = TRUE)

# Contar la cantidad total de planetas
total_planets <- nrow(kepler_data)

# Calcular el porcentaje de planetas habitables
percentage_habitable <- (habitable_planets / total_planets) * 100

# Mostrar resultados
cat("Porcentaje de planetas habitables:", percentage_habitable, "%\n")
## Porcentaje de planetas habitables: 58.57872 %

Si bien hemos con seguido un enfoque semi-supervisado para estimar el PHI, es importante tener en cuenta que la calidad de las predicciones dependerÔ en gran medida de la calidad de los datos y de la capacidad del modelo para generalizar a partir de las etiquetas débiles. La interpretación de los resultados debe hacerse con cautela, ya que el modelo puede haber aprendido patrones espurios o no representativos. Poniendo un umbral de 0.70 para considerar un planeta habitable, sería esperable que la cantidad de planetas habitables sea minoritarioa; sin embargo la predicción de PHI estimado muestra que mÔs del 68% de los planetas tienen un PHI estimado superior a 0.70, lo que sugiere que el modelo puede haber aprendido patrones espurios o no representativos.

Comparativa de los modelos de clasificación

La regresión logística, entrenada únicamente sobre los 17 planetas con PHI conocido, puede ofrecer un buen ajuste local sobre ese conjunto reducido, pero carece completamente de capacidad para generalizar al resto del dataset. Su utilidad prÔctica es muy limitada, ya que no permite estimar el índice de habitabilidad para los miles de planetas no etiquetados. AdemÔs, al trabajar con tan pocos datos, es extremadamente sensible al ruido y propensa al sobreajuste.

En contraste, el modelo semi-supervisado basado en K-means y LightGBM utiliza la estructura global de los datos para propagar etiquetas y entrenar un modelo que predice PHI para todo el conjunto. Aunque puede ser menos preciso en los pocos casos conocidos, gana ampliamente en cobertura, robustez y aplicabilidad. Su capacidad de generalizar y generar hipótesis a partir de un conjunto de datos mayor lo convierte en una herramienta mucho mÔs útil en contextos donde la escasez de etiquetas es la norma.

Posibles mejoras para futuros anƔlisis

Para mejorar el modelo de regresión logística, es fundamental aplicar técnicas de regularización (como L1 o L2) para mitigar el sobreajuste derivado del escaso número de observaciones. También se recomienda una selección de variables cuidadosa, priorizando aquellas con fuerte correlación con PHI o justificación física. La inclusión de transformaciones no lineales e interacciones puede capturar relaciones mÔs complejas, y el uso de validación cruzada tipo leave-one-out (LOOCV) maximiza el aprovechamiento del conjunto limitado de datos. Alternativamente, una regresión logística bayesiana permitiría incorporar incertidumbre y conocimiento previo sobre los factores que influyen en la habitabilidad.

Para el modelo semi-supervisado, las mejoras se enfocan en refinar la generación de pseudo-etiquetas y aprovechar mejor la estructura del conjunto de datos. Una opción es utilizar pseudo-labeling iterativo, donde el modelo actualiza sus predicciones en ciclos sucesivos. También puede explorarse un ajuste dinÔmico del número de clusters o el uso de algoritmos de clustering mÔs flexibles. Incorporar embeddings generados por autoencoders o técnicas no supervisadas permitiría representar mejor las relaciones latentes entre planetas. AdemÔs, asignar pesos variables a las pseudo-etiquetas según su confiabilidad y validar únicamente sobre los casos con PHI real mejora la robustez y la capacidad de generalización del modelo. En conclusión, aunque la regresión lineal de las variables faltantes puede ayudar a recuperar observaciones y mejorar la estabilidad del modelo logístico, es importante ser consciente de los errores de predicción acumulados y del impacto que pueden tener en la validez de las estimaciones. Evaluar cuidadosamente estos aspectos garantizarÔ que el modelo final sea mÔs confiable y que sus conclusiones sean interpretadas con la debida cautela.

Conclusiones

El anÔlisis realizado permitió evaluar diferentes modelos de regresión para predecir el radio de los exoplanetas y explorar la relación entre sus características físicas. Se probaron modelos de regresión lineal y logística, incluyendo transformaciones para mejorar la normalidad de los residuos y corregir problemas de heterocedasticidad. Los resultados indicaron que el modelo pl_radj ~ pl_rvamp con transformación logarítmica fue el mÔs efectivo, explicando el 84.25% de la variabilidad en el radio del exoplaneta y cumpliendo con los principales supuestos estadísticos. Sin embargo, el modelo de regresión logística para predecir la habitabilidad planetaria presentó limitaciones debido a la escasez de datos completos, lo que afectó su estabilidad y capacidad predictiva.

Para mejorar la calidad de los modelos, es fundamental abordar el problema de los valores faltantes, ya sea mediante imputación de datos o la recolección de mÔs observaciones. AdemÔs, al utilizar variables estimadas en modelos posteriores, se debe considerar el impacto de los errores de predicción acumulados en los resultados finales. Si bien las transformaciones de datos ayudaron a mejorar la precisión de algunos modelos, la falta de datos sigue siendo una limitación clave para la predicción de la habitabilidad planetaria. Futuras investigaciones deberían centrarse en ampliar el conjunto de datos y explorar enfoques mÔs robustos, como modelos de aprendizaje automÔtico, que podrían mejorar la capacidad predictiva de estos anÔlisis.

Referencias

Alonso Sobrino, Roi. n.d. ā€œDetección y Caracterización de Exoplanetas Mediante El MĆ©todo de Los TrĆ”nsitos.ā€ Instituto de AstrofĆ­sica de Canarias (IAC). https://www.iac.es/es/ciencia-y-tecnologia/publicaciones/deteccion-y-caracterizacion-de-exoplanetas-mediante-el-metodo-de-los-transitos.
Cardenas, Christian & Lozano, David & Marquez, Cristian & Torres, Edilberto & Delgado-Correal, Camilo. n.d. ā€œOptimización de Un Sistema Difuso Para La Detección AutomĆ”tica de TrĆ”nsitos Planetarios En Curvas de Luz de Estrellas Individuales.ā€ http://dx.doi.org/10.19053/01217488.v1.n2E.2022.15136.
Cermak, A. & Cermak, A. n.d. ā€œKepler / K2 - NASA Science.ā€ NASA Science. https://science.nasa.gov/mission/kepler/.
Hadrien Cambazard, Nicolas Catusse, Antoine Chomez, Anne-Marie Lagrange. n.d. ā€œLogistic Regression to Boost Exoplanet Detection Performances.ā€ https://doi.org/10.1093/mnras/stae2657.
IPAC. n.d.a. ā€œNASA Exoplanet Archive.ā€ NASA Exoplanet Science Institute. https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TblView/nph-tblView?app=ExoTbls&config=PS.
———. n.d.b. ā€œNASA Exoplanet Archive Overview and Holdings.ā€ https://exoplanetarchive.ipac.caltech.edu/docs/intro.html.
———. n.d.c. ā€œOur Mission.ā€ https://www.ipac.caltech.edu/page/mission.
———. n.d.d. ā€œPlanetary Systems and Planetary Systems Composite Parameters Data Column Definitions.ā€ https://exoplanetarchive.ipac.caltech.edu/docs/API_PS_columns.html.
Kane, Stephen R. & Gelino, Dawn M. n.d. ā€œThe Habitable Zone and Extreme Planetary Orbits.ā€ https://doi.org/10.1089/ast.2011.0798.
Kopparapu, R. K., Ramirez, R., Kasting, J. F., Eymet, V., Robinson, T. D., Mahadevan, S., Terrien, R. C., Domagal-Goldman, S., Meadows, V., & Deshpande, R. n.d. ā€œHabitable Zones Around Main-Sequence Stars: New Estimates.ā€ https://doi.org/10.1088/0004-637x/765/2/131.
Lee, D.-H. n.d. ā€œPseudo-Label: The Simple and Efficient Semi-Supervised Learning Method for Deep Neural Networks.ā€ https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=798d9840d2439a0e5d47bcf5d164aa46d5e7dc26.
Malik, A., Moster, B. P., & Obermeier, C. n.d. ā€œExoplanet Detection Using Machine Learning.ā€ https://doi.org/10.1093/mnras/stab3692.
MarĆ­n, Daniel. n.d.a. ā€œDetectando Planetas Desde El Espacio Gracias a Einstein - Eureka.ā€ Eureka. https://danielmarin.naukas.com/2011/05/23/detectando-planetas-desde-el-espacio-gracias-a-einstein/.
———. n.d.b. ā€œEarthFinder: Un Telescopio Espacial Para Buscar Exotierras Por El MĆ©todo de La Velocidad Radial - Eureka.ā€ https://danielmarin.naukas.com/2018/03/14/earthfinder/.
MĆ©ndez, Abel, Rivera-Valentin, Edgard, Schulze-Makuch, Dirk, Filiberto, Justin, Ramirez, Ramses, Wood, Tana, DĆ”vila, Alfonso, McKay, Chris, Ceballos, Kevin, Jusino-Maldonado, Marcos, Torres-Santiago, Nicole, Gomez, Guillermo Nery, Heller, RenĆ©, Byrne, Paul, Malaska, Michael, Nathan, Erica, SimƵes, Marta, Antunes, AndrĆ©, MartĆ­nez-FrĆ­as, JesĆŗs, & Haqq-Misra, Jacob. n.d. ā€œHabitability Models for Astrobiology.ā€ https://doi.org/10.1089/ast.2020.2342.
Nardi, Luca. n.d. ā€œĀæCuĆ”les Son Las TĆ©cnicas Utilizadas Para Descubrir Exoplanetas?ā€ WIRED. https://es.wired.com/articulos/cuales-son-las-tecnicas-utilizadas-para-descubrir-exoplanetas.
NASA, Equipo de redacción de Ciencia. n.d. ā€œWebb de La NASA Obtiene Su Primera Imagen Directa de Un Mundo Distante.ā€ NASA Ciencia. https://ciencia.nasa.gov/universo/webb-de-la-nasa-obtiene-su-primera-imagen-directa-de-un-mundo-distante/.
Nicolau, Jorge. n.d. ā€œGitHub - Georgsmeinung/Ra-Tp-Final.ā€ GitHub. https://github.com/georgsmeinung/ra-tp-final/.
Pimentel, J., Amorim, J. & Rudzicz, F. n.d. ā€œFeature Extraction for Exoplanet Detection.ā€ https://doi.org/10.1007/s41060-024-00552-7.
Shields, Aomawa L., Ballard, Sarah, & Johnson, John Asher. n.d. ā€œThe Habitability of Planets Orbiting M-Dwarf Stars.ā€ https://doi.org/10.1016/j.physrep.2016.10.003.
Wolszczan, Aleksander & Frail, D. A. n.d. ā€œA Planetary System Around the Millisecond Pulsar PSR1257 + 12.ā€ https://doi.org/10.1038/355145a0.
Wu, Dong-Hong. n.d. ā€œThe Possibility of Detecting Our Solar System Through Astrometry.ā€ https://arxiv.org/abs/2309.11729.
Zhou, D., Bousquet, O., Lal, T. N., Weston, J., & Schƶlkopf, B. n.d. ā€œLearning with Local and Global Consistency.ā€ https://proceedings.neurips.cc/paper_files/paper/2003/file/87682805257e619d49b8e0dfdc14affa-Paper.pdf.
LS0tDQp0aXRsZTogIlJlZ3Jlc2nDs24gQXZhbnphZGEgMjAyNCAtIFRQIEZpbmFsIg0KYXV0aG9yOiAiSm9yZ2UgTmljb2xhdSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICB0b2NfZmxvYXQ6IGZhbHNlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgdGhlbWU6IHVuaXRlZA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0b2NfZGVwdGg6IDINCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6ICcyJw0KcmVmZXJlbmNlczoNCiAgLSBpZDogYWxvbnNvLXNvYnJpbm8tMjAwNg0KICAgIGF1dGhvcjogIkFsb25zbyBTb2JyaW5vLCBSb2kiDQogICAgdGl0bGU6ICJEZXRlY2Npw7NuIHkgY2FyYWN0ZXJpemFjacOzbiBkZSBleG9wbGFuZXRhcyBtZWRpYW50ZSBlbCBtw6l0b2RvIGRlIGxvcyB0csOhbnNpdG9zIg0KICAgIHllYXI6IDIwMDYNCiAgICBwdWJsaXNoZXI6ICJJbnN0aXR1dG8gZGUgQXN0cm9mw61zaWNhIGRlIENhbmFyaWFzIChJQUMpIg0KICAgIHVybDogImh0dHBzOi8vd3d3LmlhYy5lcy9lcy9jaWVuY2lhLXktdGVjbm9sb2dpYS9wdWJsaWNhY2lvbmVzL2RldGVjY2lvbi15LWNhcmFjdGVyaXphY2lvbi1kZS1leG9wbGFuZXRhcy1tZWRpYW50ZS1lbC1tZXRvZG8tZGUtbG9zLXRyYW5zaXRvcyINCiAgLSBpZDogYnJhY2htYW4tbm8tZGF0ZQ0KICAgIGF1dGhvcjogIkJyYWNobWFuLCBSLiBaLiINCiAgICB0aXRsZTogIkhvdyB0byBBbmFseXplIFlvdXIgRGF0YSB8IEhvdyB0byBHZXQgU3RhcnRlZCDigJMgRXhvcGxhbmV0IEV4cGxvcmF0aW9uOiBQbGFuZXRzIEJleW9uZCBvdXIgU29sYXIgU3lzdGVtIg0KICAgIHB1Ymxpc2hlcjogIkV4b3BsYW5ldCBFeHBsb3JhdGlvbjogUGxhbmV0cyBCZXlvbmQgT3VyIFNvbGFyIFN5c3RlbSINCiAgICB1cmw6ICJodHRwczovL2V4b3BsYW5ldHMubmFzYS5nb3YvZXhvcGxhbmV0LXdhdGNoL2hvdy10by1jb250cmlidXRlL2hvdy10by1hbmFseXplLXlvdXItZGF0YS8iDQogIC0gaWQ6IGNhcmRlbmFzLTIwMjINCiAgICBhdXRob3I6ICJDYXJkZW5hcywgQ2hyaXN0aWFuICYgTG96YW5vLCBEYXZpZCAmIE1hcnF1ZXosIENyaXN0aWFuICYgVG9ycmVzLCBFZGlsYmVydG8gJiBEZWxnYWRvLUNvcnJlYWwsIENhbWlsbyIgDQogICAgdGl0bGU6ICJPcHRpbWl6YWNpw7NuIGRlIHVuIHNpc3RlbWEgZGlmdXNvIHBhcmEgbGEgZGV0ZWNjacOzbiBhdXRvbcOhdGljYSBkZSB0csOhbnNpdG9zIHBsYW5ldGFyaW9zIGVuIGN1cnZhcyBkZSBsdXogZGUgZXN0cmVsbGFzIGluZGl2aWR1YWxlcyINCiAgICBqb3VybmFsOiAiQ2llbmNpYSBlbiBEZXNhcnJvbGxvIg0KICAgIHllYXI6IDIwMjIgDQogICAgdm9sdW1lOiAxDQogICAgbnVtYmVyOiAxMA0KICAgIHBhZ2VzOiAiMTktMzUiIA0KICAgIHVybDogImh0dHA6Ly9keC5kb2kub3JnLzEwLjE5MDUzLzAxMjE3NDg4LnYxLm4yRS4yMDIyLjE1MTM2Ig0KICAtIGlkOiBjZXJtYWstMjAyNA0KICAgIGF1dGhvcjogIkNlcm1haywgQS4gJiBDZXJtYWssIEEuIg0KICAgIHRpdGxlOiAiS2VwbGVyIC8gSzIgLSBOQVNBIFNjaWVuY2UiDQogICAgcHVibGlzaGVyOiAiTkFTQSBTY2llbmNlIg0KICAgIHllYXI6IDIwMjQNCiAgICBtb250aDogIlNlcHRlbWJlciAzIg0KICAgIHVybDogImh0dHBzOi8vc2NpZW5jZS5uYXNhLmdvdi9taXNzaW9uL2tlcGxlci8iDQogIC0gaWQ6IGhhZHJpZW4tMjAyNQ0KICAgIGF1dGhvcjogIkhhZHJpZW4gQ2FtYmF6YXJkLCBOaWNvbGFzIENhdHVzc2UsIEFudG9pbmUgQ2hvbWV6LCBBbm5lLU1hcmllIExhZ3JhbmdlIg0KICAgIHRpdGxlOiAiTG9naXN0aWMgcmVncmVzc2lvbiB0byBib29zdCBleG9wbGFuZXQgZGV0ZWN0aW9uIHBlcmZvcm1hbmNlcyINCiAgICBqb3VybmFsOiAiTW9udGhseSBOb3RpY2VzIG9mIHRoZSBSb3lhbCBBc3Ryb25vbWljYWwgU29jaWV0eSINCiAgICB5ZWFyOiAyMDI1DQogICAgdm9sdW1lOiA1MzYNCiAgICBudW1iZXI6IDINCiAgICBwYWdlczogIjE2MTDigJMxNjI0Ig0KICAgIHVybDogImh0dHBzOi8vZG9pLm9yZy8xMC4xMDkzL21ucmFzL3N0YWUyNjU3Ig0KICAtIGlkOiBpcGFjLWV4b3BsYW5ldC1zY2llbmNlLW5vLWRhdGUNCiAgICBhdXRob3I6ICJJUEFDIg0KICAgIHRpdGxlOiAiTkFTQSBFeG9wbGFuZXQgQXJjaGl2ZSINCiAgICBwdWJsaXNoZXI6ICJOQVNBIEV4b3BsYW5ldCBTY2llbmNlIEluc3RpdHV0ZSINCiAgICB1cmw6ICJodHRwczovL2V4b3BsYW5ldGFyY2hpdmUuaXBhYy5jYWx0ZWNoLmVkdS9jZ2ktYmluL1RibFZpZXcvbnBoLXRibFZpZXc/YXBwPUV4b1RibHMmY29uZmlnPVBTIg0KICAtIGlkOiBpcGFjLWV4b3BsYW5ldC1hcmNoaXZlLW5vLWRhdGUNCiAgICBhdXRob3I6ICJJUEFDIg0KICAgIHRpdGxlOiAiTkFTQSBFeG9wbGFuZXQgQXJjaGl2ZSBvdmVydmlldyBhbmQgaG9sZGluZ3MiDQogICAgdXJsOiAiaHR0cHM6Ly9leG9wbGFuZXRhcmNoaXZlLmlwYWMuY2FsdGVjaC5lZHUvZG9jcy9pbnRyby5odG1sIg0KICAtIGlkOiBpcGFjLW5vLWRhdGUNCiAgICBhdXRob3I6ICJJUEFDIg0KICAgIHRpdGxlOiAiT3VyIG1pc3Npb24iDQogICAgdXJsOiAiaHR0cHM6Ly93d3cuaXBhYy5jYWx0ZWNoLmVkdS9wYWdlL21pc3Npb24iDQogIC0gaWQ6IGlwYWMtcGxhbmV0YXJ5LWRhdGEtbm8tZGF0ZQ0KICAgIGF1dGhvcjogIklQQUMiDQogICAgdGl0bGU6ICJQbGFuZXRhcnkgU3lzdGVtcyBhbmQgUGxhbmV0YXJ5IFN5c3RlbXMgQ29tcG9zaXRlIFBhcmFtZXRlcnMgRGF0YSBDb2x1bW4gRGVmaW5pdGlvbnMiDQogICAgdXJsOiAiaHR0cHM6Ly9leG9wbGFuZXRhcmNoaXZlLmlwYWMuY2FsdGVjaC5lZHUvZG9jcy9BUElfUFNfY29sdW1ucy5odG1sIg0KICAtIGlkOiBrYW5lLWdlbGluby0yMDEyDQogICAgYXV0aG9yOiAiS2FuZSwgU3RlcGhlbiBSLiAmIEdlbGlubywgRGF3biBNLiINCiAgICB0aXRsZTogIlRoZSBoYWJpdGFibGUgem9uZSBhbmQgZXh0cmVtZSBwbGFuZXRhcnkgb3JiaXRzIg0KICAgIGpvdXJuYWw6ICJBc3Ryb2Jpb2xvZ3kiDQogICAgeWVhcjogMjAxMg0KICAgIHZvbHVtZTogMTINCiAgICBudW1iZXI6IDEwDQogICAgcGFnZXM6ICI5NDAtOTQ1Ig0KICAgIGRvaTogIjEwLjEwODkvYXN0LjIwMTEuMDc5OCINCiAgICB1cmw6ICJodHRwczovL2RvaS5vcmcvMTAuMTA4OS9hc3QuMjAxMS4wNzk4Ig0KICAtIGlkOiBrb3BwYXJhcHUtcmFtaXJlei0yMDEzDQogICAgYXV0aG9yOiAiS29wcGFyYXB1LCBSLiBLLiwgUmFtaXJleiwgUi4sIEthc3RpbmcsIEouIEYuLCBFeW1ldCwgVi4sIFJvYmluc29uLCBULiBELiwgTWFoYWRldmFuLCBTLiwgVGVycmllbiwgUi4gQy4sIERvbWFnYWwtR29sZG1hbiwgUy4sIE1lYWRvd3MsIFYuLCAmIERlc2hwYW5kZSwgUi4iDQogICAgdGl0bGU6ICJIYWJpdGFibGUgem9uZXMgYXJvdW5kIG1haW4tc2VxdWVuY2Ugc3RhcnM6IG5ldyBlc3RpbWF0ZXMiDQogICAgam91cm5hbDogIlRoZSBBc3Ryb3BoeXNpY2FsIEpvdXJuYWwiDQogICAgeWVhcjogMjAxMw0KICAgIHZvbHVtZTogNzY1DQogICAgbnVtYmVyOiAyDQogICAgcGFnZXM6ICIxMzEiDQogICAgZG9pOiAiMTAuMTA4OC8wMDA0LTYzN3gvNzY1LzIvMTMxIg0KICAgIHVybDogImh0dHBzOi8vZG9pLm9yZy8xMC4xMDg4LzAwMDQtNjM3eC83NjUvMi8xMzEiDQogIC0gaWQ6IGxlZS0yMDEzDQogICAgYXV0aG9yOiAiTGVlLCBELi1ILiINCiAgICB0aXRsZTogIlBzZXVkby1sYWJlbDogVGhlIHNpbXBsZSBhbmQgZWZmaWNpZW50IHNlbWktc3VwZXJ2aXNlZCBsZWFybmluZyBtZXRob2QgZm9yIGRlZXAgbmV1cmFsIG5ldHdvcmtzIg0KICAgIHVybDogImh0dHBzOi8vY2l0ZXNlZXJ4LmlzdC5wc3UuZWR1L2RvY3VtZW50P3JlcGlkPXJlcDEmdHlwZT1wZGYmZG9pPTc5OGQ5ODQwZDI0MzlhMGU1ZDQ3YmNmNWQxNjRhYTQ2ZDVlN2RjMjYiDQogIC0gaWQ6IG1hbGlrLTIwMjENCiAgICBhdXRob3I6ICJNYWxpaywgQS4sIE1vc3RlciwgQi4gUC4sICYgT2Jlcm1laWVyLCBDLiINCiAgICB0aXRsZTogIkV4b3BsYW5ldCBkZXRlY3Rpb24gdXNpbmcgbWFjaGluZSBsZWFybmluZyINCiAgICBqb3VybmFsOiAiTW9udGhseSBOb3RpY2VzIG9mIHRoZSBSb3lhbCBBc3Ryb25vbWljYWwgU29jaWV0eSINCiAgICB5ZWFyOiAyMDIxDQogICAgdXJsOiAiaHR0cHM6Ly9kb2kub3JnLzEwLjEwOTMvbW5yYXMvc3RhYjM2OTIiDQogIC0gaWQ6IG1hcmluLTIwMTENCiAgICBhdXRob3I6ICJNYXLDrW4sIERhbmllbCINCiAgICB0aXRsZTogIkRldGVjdGFuZG8gcGxhbmV0YXMgZGVzZGUgZWwgZXNwYWNpbyBncmFjaWFzIGEgRWluc3RlaW4gLSBFdXJla2EiDQogICAgcHVibGlzaGVyOiAiRXVyZWthIg0KICAgIHllYXI6IDIwMTENCiAgICB1cmw6ICJodHRwczovL2RhbmllbG1hcmluLm5hdWthcy5jb20vMjAxMS8wNS8yMy9kZXRlY3RhbmRvLXBsYW5ldGFzLWRlc2RlLWVsLWVzcGFjaW8tZ3JhY2lhcy1hLWVpbnN0ZWluLyINCiAgLSBpZDogbWFyaW4tMjAxOA0KICAgIGF1dGhvcjogIk1hcsOtbiwgRGFuaWVsIg0KICAgIHRpdGxlOiAiRWFydGhGaW5kZXI6IHVuIHRlbGVzY29waW8gZXNwYWNpYWwgcGFyYSBidXNjYXIgZXhvdGllcnJhcyBwb3IgZWwgbcOpdG9kbyBkZSBsYSB2ZWxvY2lkYWQgcmFkaWFsIC0gRXVyZWthIg0KICAgIHllYXI6IDIwMTgNCiAgICBtb250aDogIk1hcmNoIg0KICAgIHVybDogImh0dHBzOi8vZGFuaWVsbWFyaW4ubmF1a2FzLmNvbS8yMDE4LzAzLzE0L2VhcnRoZmluZGVyLyINCiAgLSBpZDogbWVuZGV6LXJpdmVyYS0yMDIxDQogICAgYXV0aG9yOiAiTcOpbmRleiwgQWJlbCwgUml2ZXJhLVZhbGVudGluLCBFZGdhcmQsIFNjaHVsemUtTWFrdWNoLCBEaXJrLCBGaWxpYmVydG8sIEp1c3RpbiwgUmFtaXJleiwgUmFtc2VzLCBXb29kLCBUYW5hLCBEw6F2aWxhLCBBbGZvbnNvLCBNY0theSwgQ2hyaXMsIENlYmFsbG9zLCBLZXZpbiwgSnVzaW5vLU1hbGRvbmFkbywgTWFyY29zLCBUb3JyZXMtU2FudGlhZ28sIE5pY29sZSwgR29tZXosIEd1aWxsZXJtbyBOZXJ5LCBIZWxsZXIsIFJlbsOpLCBCeXJuZSwgUGF1bCwgTWFsYXNrYSwgTWljaGFlbCwgTmF0aGFuLCBFcmljYSwgU2ltw7VlcywgTWFydGEsIEFudHVuZXMsIEFuZHLDqSwgTWFydMOtbmV6LUZyw61hcywgSmVzw7pzLCAmIEhhcXEtTWlzcmEsIEphY29iLiINCiAgICB0aXRsZTogIkhhYml0YWJpbGl0eSBNb2RlbHMgZm9yIEFzdHJvYmlvbG9neSINCiAgICBqb3VybmFsOiAiQXN0cm9iaW9sb2d5Ig0KICAgIHllYXI6IDIwMjENCiAgICBkb2k6ICIxMC4xMDg5L2FzdC4yMDIwLjIzNDIiDQogICAgdXJsOiAiaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9wdWJsaWNhdGlvbi8zNTM4NjE0NDJfSGFiaXRhYmlsaXR5X01vZGVsc19mb3JfQXN0cm9iaW9sb2d5Ig0KICAtIGlkOiBuYXJkaS0yMDI0DQogICAgYXV0aG9yOiAiTmFyZGksIEx1Y2EiDQogICAgdGl0bGU6ICLCv0N1w6FsZXMgc29uIGxhcyB0w6ljbmljYXMgdXRpbGl6YWRhcyBwYXJhIGRlc2N1YnJpciBleG9wbGFuZXRhcz8iDQogICAgcHVibGlzaGVyOiAiV0lSRUQiDQogICAgeWVhcjogMjAyNA0KICAgIG1vbnRoOiAiQXVndXN0IDI2Ig0KICAgIHVybDogImh0dHBzOi8vZXMud2lyZWQuY29tL2FydGljdWxvcy9jdWFsZXMtc29uLWxhcy10ZWNuaWNhcy11dGlsaXphZGFzLXBhcmEtZGVzY3VicmlyLWV4b3BsYW5ldGFzIg0KICAtIGlkOiBuYXNhLTIwMjINCiAgICBhdXRob3I6ICJOQVNBLCBFcXVpcG8gZGUgcmVkYWNjacOzbiBkZSBDaWVuY2lhIg0KICAgIHRpdGxlOiAiV2ViYiBkZSBsYSBOQVNBIG9idGllbmUgc3UgcHJpbWVyYSBpbWFnZW4gZGlyZWN0YSBkZSB1biBtdW5kbyBkaXN0YW50ZSINCiAgICB5ZWFyOiAyMDIyDQogICAgcHVibGlzaGVyOiAiTkFTQSBDaWVuY2lhIg0KICAgIHVybDogImh0dHBzOi8vY2llbmNpYS5uYXNhLmdvdi91bml2ZXJzby93ZWJiLWRlLWxhLW5hc2Etb2J0aWVuZS1zdS1wcmltZXJhLWltYWdlbi1kaXJlY3RhLWRlLXVuLW11bmRvLWRpc3RhbnRlLyINCiAgLSBpZDogbmljb2xhdS0yMDI1DQogICAgYXV0aG9yOiAiTmljb2xhdSwgSm9yZ2UiDQogICAgdGl0bGU6ICJHaXRIdWIgLSBnZW9yZ3NtZWludW5nL3JhLXRwLWZpbmFsIg0KICAgIHB1Ymxpc2hlcjogIkdpdEh1YiINCiAgICB5ZWFyOiAyMDI1DQogICAgdXJsOiAiaHR0cHM6Ly9naXRodWIuY29tL2dlb3Jnc21laW51bmcvcmEtdHAtZmluYWwvIg0KICAtIGlkOiBwaW1lbnRlbC0yMDI0DQogICAgYXV0aG9yOiAiUGltZW50ZWwsIEouLCBBbW9yaW0sIEouICYgUnVkemljeiwgRi4iDQogICAgdGl0bGU6ICJGZWF0dXJlIGV4dHJhY3Rpb24gZm9yIGV4b3BsYW5ldCBkZXRlY3Rpb24iDQogICAgam91cm5hbDogIkludCBKIERhdGEgU2NpIEFuYWwiDQogICAgeWVhcjogMjAyNA0KICAgIHVybDogImh0dHBzOi8vZG9pLm9yZy8xMC4xMDA3L3M0MTA2MC0wMjQtMDA1NTItNyINCiAgLSBpZDogc2hpZWxkcy1iYWxsYXJkLTIwMTYNCiAgICBhdXRob3I6ICJTaGllbGRzLCBBb21hd2EgTC4sIEJhbGxhcmQsIFNhcmFoLCAmIEpvaG5zb24sIEpvaG4gQXNoZXIiDQogICAgdGl0bGU6ICJUaGUgaGFiaXRhYmlsaXR5IG9mIHBsYW5ldHMgb3JiaXRpbmcgTS1kd2FyZiBzdGFycyINCiAgICBqb3VybmFsOiAiUGh5c2ljcyBSZXBvcnRzIg0KICAgIHllYXI6IDIwMTYNCiAgICB2b2x1bWU6IDY2Mw0KICAgIHBhZ2VzOiAiMS0zOCINCiAgICBkb2k6ICIxMC4xMDE2L2oucGh5c3JlcC4yMDE2LjEwLjAwMyINCiAgICB1cmw6ICJodHRwczovL2RvaS5vcmcvMTAuMTAxNi9qLnBoeXNyZXAuMjAxNi4xMC4wMDMiDQogIC0gaWQ6IHNoaWVsZHMtMjAxNg0KICAgIGF1dGhvcjogIlNoaWVsZHMsIEFvbWF3YSBMLiwgQmFsbGFyZCwgU2FyYWgsICYgSm9obnNvbiwgSm9obiBBc2hlciINCiAgICB0aXRsZTogIlRoZSBIYWJpdGFiaWxpdHkgb2YgUGxhbmV0cyBPcmJpdGluZyBNLUR3YXJmIFN0YXJzIg0KICAgIHllYXI6IDIwMTYNCiAgICB1cmw6ICJodHRwczovL2RvaS5vcmcvMTAuMTAxNi9qLnBoeXNyZXAuMjAxNi4xMC4wMDMiDQogIC0gaWQ6IHR1a2V5LTE5NzcNCiAgICBhdXRob3I6ICJUdWtleSwgSi4gVy4iDQogICAgdGl0bGU6ICJFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIg0KICAgIHB1Ymxpc2hlcjogIkFkZGlzb24tV2VzbGV5IFB1Ymxpc2hpbmcgQ29tcGFueSINCiAgICB5ZWFyOiAxOTc3DQogICAgdm9sdW1lOiAyDQogIC0gaWQ6IHZlbnRha2EtMjAyMw0KICAgIGF1dGhvcjogIlZlbmthdGEsIEcgJiBKYWhuYXZpLCBNICYgQ2gsIFZlbmthdGEgJiBTdW5lZXRoYSwgTXV2dmEiDQogICAgdGl0bGU6ICJFeG9wbGFuZXQgRGV0ZWN0aW9uIFVzaW5nIEZlYXR1cmUgRW5naW5lZXJpbmcgd2l0aCBFbnNlbWJsZSBMZWFybmluZyINCiAgICB5ZWFyOiAyMDIzDQogICAgdXJsOiAiaHR0cDovL2R4LmRvaS5vcmcvMTAuMTEwOS9JQ1BDU041ODgyNy4yMDIzLjAwMDI1Ig0KICAtIGlkOiB3b2xzemN6YW4tZnJhaWwtMTk5Mg0KICAgIGF1dGhvcjogIldvbHN6Y3phbiwgQWxla3NhbmRlciAmIEZyYWlsLCBELiBBLiINCiAgICB0aXRsZTogIkEgcGxhbmV0YXJ5IHN5c3RlbSBhcm91bmQgdGhlIG1pbGxpc2Vjb25kIHB1bHNhciBQU1IxMjU3ICsgMTIiDQogICAgam91cm5hbDogIk5hdHVyZSINCiAgICB5ZWFyOiAxOTkyDQogICAgdm9sdW1lOiAzNTUNCiAgICBudW1iZXI6IDYzNTYNCiAgICBwYWdlczogIjE0NS0xNDciDQogICAgZG9pOiAiMTAuMTAzOC8zNTUxNDVhMCINCiAgICB1cmw6ICJodHRwczovL2RvaS5vcmcvMTAuMTAzOC8zNTUxNDVhMCINCiAgLSBpZDogd3UtMjAyMw0KICAgIGF1dGhvcjogIld1LCBEb25nLUhvbmciDQogICAgdGl0bGU6ICJUaGUgcG9zc2liaWxpdHkgb2YgZGV0ZWN0aW5nIG91ciBzb2xhciBzeXN0ZW0gdGhyb3VnaCBhc3Ryb21ldHJ5Ig0KICAgIHllYXI6IDIwMjMNCiAgICB1cmw6ICJodHRwczovL2FyeGl2Lm9yZy9hYnMvMjMwOS4xMTcyOSINCiAgLSBpZDogemhvdS0yMDA0DQogICAgYXV0aG9yOiAiWmhvdSwgRC4sIEJvdXNxdWV0LCBPLiwgTGFsLCBULiBOLiwgV2VzdG9uLCBKLiwgJiBTY2jDtmxrb3BmLCBCLiINCiAgICB0aXRsZTogIkxlYXJuaW5nIHdpdGggbG9jYWwgYW5kIGdsb2JhbCBjb25zaXN0ZW5jeSINCiAgICBqb3VybmFsOiAiQWR2YW5jZXMgaW4gTmV1cmFsIEluZm9ybWF0aW9uIFByb2Nlc3NpbmcgU3lzdGVtcyINCiAgICB5ZWFyOiAyMDA0DQogICAgdm9sdW1lOiAxNg0KICAgIHBhZ2VzOiAiMzIx4oCTMzI4Ig0KICAgIHVybDogImh0dHBzOi8vcHJvY2VlZGluZ3MubmV1cmlwcy5jYy9wYXBlcl9maWxlcy9wYXBlci8yMDAzL2ZpbGUvODc2ODI4MDUyNTdlNjE5ZDQ5YjhlMGRmZGMxNGFmZmEtUGFwZXIucGRmIg0KZWRpdG9yX29wdGlvbnM6DQogIG1hcmtkb3duOg0KICAgIHdyYXA6IG5vbmUNCi0tLQ0KDQo6Ojoge3N0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7In0NCiFbXShsb2dvLWF1c3RyYWwucG5nKXt3aWR0aD0iMjAwcHgifQ0KOjo6DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KIyBCbG9xdWUgZGUgY29uZmlndXJhY2nDs24gZGUgUiBNYXJrZG93bg0KIyBMaW1waWV6YSBkZWwgV29ya3NwYWNlDQpybShsaXN0ID0gbHMoKSkNCg0KIyBEZXRlcm1pbmFyIGVsIGRpcmVjdG9yaW8gZGVsIHNjcmlwdCBhY3R1YWwNCiMgeSBjYW1iaWFyIGVsIHdvcmtpbmcgZGlyZWN0b3J5IGFsIGRpcmVjdG9yaW8gZGVsIHNjcmlwdCBhY3R1YWwNCmxpYnJhcnkocnN0dWRpb2FwaSkNCnNjcmlwdF9mdWxsX3BhdGggPC0gcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGgNCnNjcmlwdF9wYXRoIDwtIGZpbGUucGF0aChkaXJuYW1lKHNjcmlwdF9mdWxsX3BhdGgpLCAiIikNCnNldHdkKHNjcmlwdF9wYXRoKQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQojIERlc2hhYmlsaXRhIGxhIGltcHJlc2nDs24gZGUgdHVzIHJlc3VsdGFkb3MgZW4gbm90YWNpw7NuIGNpZW50w61maWNhDQpvcHRpb25zKHNjaXBlbj05OTkpDQoNCiMgU2VtaWxsYSBnbG9iYWwgcGFyYSByZXByb2R1Y2liaWxpZGFkDQpyYW5kb21fc2VlZCA8LSAyMzUzMzcNCnNldC5zZWVkKHJhbmRvbV9zZWVkKQ0KYGBgDQoNCiMgRGV0ZWNjacOzbiBkZSBleG9wbGFuZXRhcyB5IHN1cyBjYXJhY3RlcsOtc3RpY2FzDQoNCiMjIEVsIHByb2JsZW1hIA0KDQpEdXJhbnRlIGNhc2kgdHJlcyBkw6ljYWRhcyBkZSBpbnZlc3RpZ2FjacOzbiwgbGEgTkFTQSBoYSBjb25maXJtYWRvIGxhIGV4aXN0ZW5jaWEgZGUgbcOhcyBkZSA1LDYwMCBleG9wbGFuZXRhcyBlbiA0LDE1MSBzaXN0ZW1hcyBwbGFuZXRhcmlvcy4gRXN0b3MgbXVuZG9zLCBjb25vY2lkb3MgY29tbyBleG9wbGFuZXRhcyBvIHBsYW5ldGFzIGV4dHJhc29sYXJlcywgb3JiaXRhbiBlc3RyZWxsYXMgZGlzdGludGFzIGFsIFNvbC4gQXVucXVlIGxvcyBhc3Ryw7Nub21vcyBsb3MgaW1hZ2luYXJvbiBkdXJhbnRlIG1pbGVuaW9zLCBubyBmdWUgaGFzdGEgbWVkaWFkb3MgZGUgbGEgZMOpY2FkYSBkZSAxOTkwIGN1YW5kbyBjb21lbnphcm9uIGEgYXBhcmVjZXIgZW4gbG9zIHJlZ2lzdHJvcyBjaWVudMOtZmljb3MuDQoNCkFwcm94aW1hZGFtZW50ZSBkb3MgdGVyY2lvcyBkZSBsb3MgZXhvcGxhbmV0YXMgZGVzY3ViaWVydG9zIGhhc3RhIGFob3JhIHByb3ZpZW5lbiBkZWwgdGVsZXNjb3BpbyBlc3BhY2lhbCBLZXBsZXIsIG1pZW50cmFzIHF1ZSBjaWVudG9zIG3DoXMgaGFuIHNpZG8gaWRlbnRpZmljYWRvcyBncmFjaWFzIGEgbGEgbWlzacOzbiBURVNTIHkgb3Ryb3Mgb2JzZXJ2YXRvcmlvcyB0ZXJyZXN0cmVzLiBFc3RhcyBtaXNpb25lcyBoYW4gZ2VuZXJhZG8gdW5hIGVub3JtZSBjYW50aWRhZCBkZSBkYXRvcywgY29uIGNlcmNhIGRlIDEwLDAwMCBwb3NpYmxlcyBleG9wbGFuZXRhcyBhw7puIHBlbmRpZW50ZXMgZGUgY29uZmlybWFjacOzbi4gVW4gbsO6bWVybyBpbXByZXNpb25hbnRlIHNpIGNvbnNpZGVyYW1vcyBxdWUgaGFzdGEgcHJpbmNpcGlvcyBkZSBsb3MgYcOxb3Mgbm92ZW50YSBubyBzZSBjb25vY8OtYSBuaW5ndW5vLCBwZXJvIGRpbWludXRvIGVuIGNvbXBhcmFjacOzbiBjb24gbG9zIGNpZW50b3MgZGUgbWlsZXMgZGUgbWlsbG9uZXMgcXVlIHBvZHLDrWFuIGV4aXN0aXIgc29sbyBlbiBsYSBWw61hIEzDoWN0ZWEuDQoNClBhcmEgZGV0ZWN0YXIgZXN0b3MgbXVuZG9zLCBsb3MgYXN0csOzbm9tb3MgZW1wbGVhbiBkaXZlcnNhcyB0w6ljbmljYXMsIG11Y2hhcyBkZSBlbGxhcyBsbGV2YWRhcyBhbCBsw61taXRlIGRlIGxhIHRlY25vbG9nw61hIGRpc3BvbmlibGUgZW4gbG9zIG9ic2VydmF0b3Jpb3MgZXNwYWNpYWxlcyBbQG5hcmRpLTIwMjRdOiBhc3Ryb21ldHLDrWEgbyBkZXRlY2Npw7NuIGEgdHJhdsOpcyBkZWwgbW92aW1pZW50byBlc3RlbGFyIFtAd3UtMjAyM10sIHZlbG9jaWRhZGVzIHJhZGlhbGVzIG8gZGV0ZWNjacOzbiBhIHRyYXbDqXMgZGVsIGVmZWN0byBEb3BwbGVyIFtAbWFyaW4tMjAxOF0sIG3DqXRvZG8gZGVsIHRyw6Fuc2l0byBvIGRldGVjY2nDs24gYSB0cmF2w6lzIGRlIGxhIHNvbWJyYSBwbGFuZXRhcmlhIFtAYWxvbnNvLXNvYnJpbm8tMjAwNl0sIG1pY3JvbGVudGUgZ3Jhdml0YWNpb25hbCBvIGRldGVjY2nDs24gYSB0cmF2w6lzIGRlIGxhIGN1cnZhdHVyYSBkZWwgZXNwYWNpby10aWVtcG8gW0BtYXJpbi0yMDExXSwgb2JzZXJ2YWNpw7NuIGRpcmVjdGEgbyBmb3RvZ3JhZsOtYSBlbiBtZWRpbyBkZWwgYnJpbGxvIGVzdGVsYXIgW0BuYXNhLTIwMjJdIHkgZGV0ZWNjacOzbiBwb3IgY8OzbW8gYWZlY3RhbiBsYSByb3RhY2nDs24gZGUgcMO6bHNhcmVzIFtAd29sc3pjemFuLWZyYWlsLTE5OTJdLg0KDQpFbCBhbsOhbGlzaXMgZGUgZXhvcGxhbmV0YXMgcHJlc2VudGEgdmFyaW9zIGRlc2Fmw61vcyBlbiBsYSBtb2RlbGl6YWNpw7NuIGRlIGRhdG9zLiBMYSBtdWx0aWNvbGluZWFsaWRhZCBlcyB1biBwcm9ibGVtYSBjb23Dum4sIHlhIHF1ZSBtdWNoYXMgdmFyaWFibGVzIG9yYml0YWxlcywgZXN0ZWxhcmVzIHkgcGxhbmV0YXJpYXMgZXN0w6FuIGFsdGFtZW50ZSBjb3JyZWxhY2lvbmFkYXMgZGViaWRvIGEgc3Ugb3JpZ2VuIGbDrXNpY28gY29tw7puLCBjb21vIGxhIHJlbGFjacOzbiBlbnRyZSBlbCBwZXLDrW9kbyBvcmJpdGFsIHkgZWwgc2VtaWVqZSBtYXlvciwgZGVzY3JpdGEgcG9yIGxhIExleSBkZSBLZXBsZXIuIEFkZW3DoXMsIGVsIHJ1aWRvIHkgbGEgdmFyaWFiaWxpZGFkIGVuIGxvcyBkYXRvcyBwdWVkZW4gYWZlY3RhciBsYSBwcmVjaXNpw7NuIGRlIGxhcyBwcmVkaWNjaW9uZXMsIHlhIHF1ZSBsYXMgbWVkaWNpb25lcyBzdWVsZW4gcHJlc2VudGFyIGluY2VydGlkdW1icmUsIGVzcGVjaWFsbWVudGUgZW4gbGEgZXN0aW1hY2nDs24gZGUgbWFzYXMgeSByYWRpb3MgcGxhbmV0YXJpb3MsIGxvIHF1ZSByZWZsZWphIGxhIGRpdmVyc2lkYWQgbmF0dXJhbCBkZSBsb3Mgc2lzdGVtYXMgZXN0ZWxhcmVzLiBPdHJvIGFzcGVjdG8gY2xhdmUgZXMgbGEgbm8gbGluZWFsaWRhZCBlbiBsYXMgcmVsYWNpb25lcyBlbnRyZSBwcm9waWVkYWRlcyBlc3RlbGFyZXMsIG9yYml0YWxlcyB5IHBsYW5ldGFyaWFzLCBjb21vIGxhIGRlcGVuZGVuY2lhIGPDumJpY2EgZW50cmUgZWwgc2VtaWVqZSBtYXlvciB5IGVsIHBlcsOtb2RvIG9yYml0YWwgc2Vnw7puIGxhIExleSBkZSBLZXBsZXIuIEZpbmFsbWVudGUsIGxhIGFsdGEgZGltZW5zaW9uYWxpZGFkIGRlIGxvcyBkYXRvcywgZ2VuZXJhZGEgcG9yIGxhIGdyYW4gY2FudGlkYWQgZGUgc2Vuc29yZXMgeSBtZXRvZG9sb2fDrWFzIHBhcmEgZGV0ZWN0YXIgZXhvcGxhbmV0YXMsIHB1ZWRlIGludHJvZHVjaXIgdmFyaWFibGVzIGlycmVsZXZhbnRlcyBvIHJlZHVuZGFudGVzLCBhdW1lbnRhbmRvIGlubmVjZXNhcmlhbWVudGUgbGEgY29tcGxlamlkYWQgZGVsIG1vZGVsbywgcG9yIGxvIHF1ZSBlcyBmdW5kYW1lbnRhbCBhcGxpY2FyIHTDqWNuaWNhcyBkZSBzZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyBwYXJhIG1lam9yYXIgbGEgZWZpY2llbmNpYSBkZWwgYW7DoWxpc2lzLg0KDQojIyBBbnRlY2VkZW50ZXMNCg0KTGEgZGV0ZWNjacOzbiBkZSBleG9wbGFuZXRhcyBlcyB1biBjYW1wbyBkZSBpbnZlc3RpZ2FjacOzbiBlbiBjb25zdGFudGUgZXZvbHVjacOzbiwgY29uIG51ZXZvcyBkZXNjdWJyaW1pZW50b3MgeSB0w6ljbmljYXMgZW1lcmdlbnRlcyBxdWUgYW1wbMOtYW4gbnVlc3RybyBjb25vY2ltaWVudG8gZGVsIHVuaXZlcnNvLiBMYSBjaWVuY2lhIGRlIGRhdG9zIGp1ZWdhIHVuIHBhcGVsIGZ1bmRhbWVudGFsIGVuIGVzdGUgcHJvY2VzbywgcGVybWl0aWVuZG8gYSBsb3MgYXN0csOzbm9tb3MgYW5hbGl6YXIgZ3JhbmRlcyB2b2zDum1lbmVzIGRlIGRhdG9zIHkgZXh0cmFlciBpbmZvcm1hY2nDs24gcmVsZXZhbnRlIHNvYnJlIGxvcyBleG9wbGFuZXRhcyB5IHN1cyBjYXJhY3RlcsOtc3RpY2FzLg0KDQpJbmNsdXNvIE5BU0EgYW5pbWEgYSBsYSBkZXRlY2Npw7NuIGFtYXRldXIgZGUgZXhvcGxhbmV0YXMgYSB0cmF2w6lzIGRlIHN1IHNpdGlvIEV4b3BsYW5ldCBXYXRjaCBkb25kZSBvZnJlY2UgdW5hIGd1w61hIGRldGFsbGFkYSBzb2JyZSBjw7NtbyBhbmFsaXphciBvYnNlcnZhY2lvbmVzIGRlIHRyw6Fuc2l0b3MgZGUgZXhvcGxhbmV0YXMgcGFyYSBnZW5lcmFyIGN1cnZhcyBkZSBsdXosIHF1ZSByZXByZXNlbnRhbiBsYXMgdmFyaWFjaW9uZXMgZW4gZWwgYnJpbGxvIGRlIHVuYSBlc3RyZWxsYSBjdWFuZG8gdW4gcGxhbmV0YSBwYXNhIGZyZW50ZSBhIGVsbGEgW0BicmFjaG1hbi0yMDI0XQ0KDQojI1RyYWJham9zIHJlbGFjaW9uYWRvcw0KDQpIYXkgdmFyaW9zIGFudGVjZWRlbnRlcyBkZWwgdXNvIGRlIGFwcmVuZGl6YWplIGF1dG9tw6F0aWNvIHkgbcOpdG9kb3MgZXN0YWTDrXN0aWNvcyBwYXJhIGxhIGRldGVjY2nDs24gZGUgZXhvcGxhbmV0YXMuDQoNCkVuIFtAbWFsaWstMjAyMV0gc2UgcHJlc2VudGEgdW5hIG51ZXZhIHTDqWNuaWNhIGJhc2FkYSBlbiBtYWNoaW5lIGxlYXJuaW5nIHBhcmEgZGV0ZWN0YXIgZXhvcGxhbmV0YXMgbWVkaWFudGUgZWwgbcOpdG9kbyBkZSB0csOhbnNpdG8uIFNlIGVtcGxlw7MgbGEgYmlibGlvdGVjYSBUU0ZyZXNoIHBhcmEgZXh0cmFlciA3ODkgY2FyYWN0ZXLDrXN0aWNhcyBkZSBjdXJ2YXMgZGUgbHV6IHkgZW50cmVuYXIgdW4gY2xhc2lmaWNhZG9yIGRlIGdyYWRpZW50IGJvb3N0aW5nIGNvbiBMaWdodEdCTS4NCg0KRW4gW0BoYWRyaWVuLTIwMjVdIHNlIHRyYXRhIGxhIHByb2JsZW3DoXRpY2EgZGUgZGV0ZWNjacOzbiBkZSBpbWFnZW4gZGlyZWN0YSBkZSBleG9wbGFuZXRhcyB5IGPDs21vIHNlcGFyYXIgZWwgcnVpZG8gZGUgZm9uZG8gZGUgbGFzIHNlw7FhbGVzIHBsYW5ldGFyaWFzLiBMb3MgbcOpdG9kb3MgZXN0YWTDrXN0aWNvcyByZWNpZW50ZXMgZXZpdGFuIGxhIGF1dG8gc3VzdHJhY2Npw7NuIGRlIHNlw7FhbGVzIGRlIGludGVyw6lzLCBhIGRpZmVyZW5jaWEgZGVsIGVuZm9xdWUgaW5pY2lhbCBiYXNhZG8gZW4gaW3DoWdlbmVzIGRpZmVyZW5jaWFsZXMgYW5ndWxhcmVzIChBREkpLiBTaW4gZW1iYXJnbywgZXN0b3MgbcOpdG9kb3MgcHVlZGVuIGdlbmVyYXIgbXVjaG9zIGZhbHNvcyBwb3NpdGl2b3Mgc2kgbm8gc2UgZXN0YWJsZWNlbiB1bWJyYWxlcyBjb25zZXJ2YWRvcmVzLCBsbyBxdWUgYSBzdSB2ZXogcHVlZGUgaGFjZXIgcXVlIHNlIHBpZXJkYW4gZXhvcGxhbmV0YXMgZMOpYmlsZXMuIEVzdGUgZXN0dWRpbyBleHRpZW5kZSB1biBtYXJjbyBlc3RhZMOtc3RpY28gaW5jb3Jwb3JhbmRvIHVuYSByZWdyZXNpw7NuIGxvZ8Otc3RpY2EgcGFyYSBmaWx0cmFyIGNhbmRpZGF0b3MsIHV0aWxpemFuZG8gY2FyYWN0ZXLDrXN0aWNhcyDDs3B0aWNhcyBlbiBkb3MgbG9uZ2l0dWRlcyBkZSBvbmRhLiBTZSBhcGxpY2EgZGV0ZWNjacOzbiBkZSBib3JkZXMgeSBhbGdvcml0bW9zIGRlIGNsdXN0ZXJpbmcgcGFyYSBwcm9jZXNhciBzdWItaW3DoWdlbmVzLiANCg0KRW4gW0BjYXJkZW5hcy0yMDIyXSBzZSBkZXNhcnJvbGxhIHVuIGVuc2FtYmxhZG8gZGUgc29mdHdhcmUgYXV0w7Nub21vIHBhcmEgZGV0ZWN0YXIgdHLDoW5zaXRvcyBwbGFuZXRhcmlvcyBlbiBjdXJ2YXMgZGUgbHV6IGVzdGVsYXJlcywgdXRpbGl6YW5kbyB1biBjbGFzaWZpY2Fkb3IgZGUgbMOzZ2ljYSBkaWZ1c2EgeSBldml0YW5kbyBsYSBiw7pzcXVlZGEgbWFudWFsIGRlIHRyw6Fuc2l0b3MgZW4gZ3JhbmRlcyB2b2zDum1lbmVzIGRlIGRhdG9zLiANCg0KRW4gW0B2ZW5rYXRhLTIwMjNdIHNlIHByZXNlbnRhIHVuYSB0w6ljbmljYSBwYXJhIGRldGVjdGFyIGV4b3BsYW5ldGFzIHVzYW5kbyBlbCBtw6l0b2RvIGRlIHRyw6Fuc2l0by4gRWwgb2JqZXRpdm8gZXMgbWVqb3JhciBsYXMgdMOpY25pY2FzIHRyYWRpY2lvbmFsZXMgZW4gYXN0cm9ub23DrWEgY29uIGVsIHVzbyBkZSBhbGdvcml0bW9zIGRlIGFwcmVuZGl6YWplIGF1dG9tw6F0aWNvLiBQYXJhIGVsbG8sIHV0aWxpemFuIHNlaXMgbW9kZWxvcyBkaWZlcmVudGVzIGRlIGFwcmVuZGl6YWplIGF1dG9tw6F0aWNvOiBSYW5kb20gRm9yZXN0LCBEZWNpc2lvbiBUcmVlLCBTdXBwb3J0IFZlY3RvciBDbGFzc2lmaWVyLCBLLU5lYXJlc3QgTmVpZ2hib3IgeSBNdWx0aS1MYXllciBQZXJjZXB0cm9uLiBBbCBjb21wYXJhciBsYXMgcHJlY2lzaW9uZXMgY29uY2x1eWUgcXVlIGNvbWJpbmFuZG8gY3VhdHJvIGRlIGVzb3MgbW9kZWxvcyAoU3VwcG9ydCBWZWN0b3IgQ2xhc3NpZmllciwgSy1OZWFyZXN0IE5laWdoYm9yLCBSYW5kb20gRm9yZXN0IHkgTXVsdGktTGF5ZXIgUGVyY2VwdHJvbikgdXNhbmRvIGJhZ2dpbmcsIHNlIGxvZ3JhYmEgdW5hIG1heW9yIHByZWNpc2nDs24uDQoNCkVuIFtAcGltZW50ZWwtMjAyNF0gc2UgY2VudHJhIGVuIGRldGVjdGFyIHBvc2libGVzIHBsYW5ldGFzIHV0aWxpemFuZG8gZWwgbcOpdG9kbyBkZSB0csOhbnNpdG8gY29uIHVuIGVuZm9xdWUgbm92ZWRvc28gYWwgY2xhc2lmaWNhciBlc3RyZWxsYXMgbWVkaWFudGUgdW4gY29uanVudG8gZGUgY2FyYWN0ZXLDrXN0aWNhcyBleHRyYcOtZGFzIGRlIHNlcmllcyB0ZW1wb3JhbGVzIGVuIHRyZXMgZG9taW5pb3M6IHRlbXBvcmFsLCBlc3RhZMOtc3RpY28geSBlc3BlY3RyYWwuIEVzdGFzIGNhcmFjdGVyw61zdGljYXMgc2UgdXRpbGl6YW4gcGFyYSBlbnRyZW5hciB5IGV2YWx1YXIgbW9kZWxvcyBjb24gZGF0b3MgZGVsIHRlbGVzY29waW8gS2VwbGVyLCB5IGxvcyByZXN1bHRhZG9zIHN1cGVyYW4gYWxndW5vcyBlbmZvcXVlcyBleGlzdGVudGVzLiBBZGVtw6FzLCBlbCBwcm9jZXNvIGRlIHZhbGlkYWNpw7NuIGNydXphZGEgc2UgZW1wbGVhIHBhcmEgZWxpbWluYXIgc2VzZ29zIHkgZXZhbHVhciBtZWpvciBsb3MgbW9kZWxvcy4gDQoNCkluc3BpcsOhbmRvc2UgZW4gZXN0b3MgYW50ZWNlZGVudGVzLCBlc3RlIHRyYWJham8gYnVzY2EgdXRpbGl6YXIgbGEgcmVncmVzacOzbiBwYXLDoW1ldHJvcyBmYWx0YW50ZXMgZGUgbG9zIGV4b3BsYW5ldGFzIGFzw60gY29tbyBwcmVkZWNpciBzdSBoYWJpdGFiaWxpZGFkLg0KDQojQW7DoWxpc2lzIEV4cGxvcmF0b3Jpbw0KDQpFbiBbQHR1Y2tleS0xOTc3XSBzZSBleHBsaWNhIHF1ZSBlbCBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGRhdG9zIChFREEpIHNlIGVuZm9jYSBlbiBkZXNjdWJyaXIgcGF0cm9uZXMsIGFub21hbMOtYXMgeSByZWxhY2lvbmVzIGRlbnRybyBkZSBsb3MgZGF0b3MsIHV0aWxpemFuZG8gbcOpdG9kb3MgdmlzdWFsZXMgeSBlc3RhZMOtc3RpY29zLiBFbiBzdSBiYXNlLCBpbXBsaWNhIGFib3JkYXIgbGEgaW5jZXJ0aWR1bWJyZSB5IGxhIGRpdmVyc2lkYWQgZGUgZXN0cnVjdHVyYXMgcG9zaWJsZXMgZW4gbG9zIGRhdG9zLCBldml0YW5kbyBhc3VtaXIgdW4gw7puaWNvIG1vZGVsbyBwcm9iYWJpbMOtc3RpY28gY29tbyBhYnNvbHV0by4gRWwgRURBIGVuZmF0aXphIGxhIGV4cGxvcmFjacOzbiBzb2JyZSBsYSBpbmZlcmVuY2lhIGVzdHJpY3RhLCBidXNjYW5kbyBtw6l0b2RvcyByb2J1c3RvcyB5IGZsZXhpYmxlcyBxdWUgZnVuY2lvbmVuIGVuIGRpdmVyc2FzIGNpcmN1bnN0YW5jaWFzLCBjb24gZWwgb2JqZXRpdm8gZGUgcHJvcG9yY2lvbmFyIHVuYSBjb21wcmVuc2nDs24gcHJlbGltaW5hciB5IHByZXBhcmFyIGVsIHRlcnJlbm8gcGFyYSBhbsOhbGlzaXMgbcOhcyBwcm9mdW5kb3MuDQoNCiMjIEVsIGRhdGFzZXQgZGUgZXhwb2xhbmV0YXMgZGV0ZWN0YWRvcyBjb24gZWwgdGVsZXNjb3BpbyBlc3BhY2lhbCBLZXBsZXINCg0KRWwgKipBcmNoaXZvIGRlIEV4b3BsYW5ldGFzIGRlIGxhIE5BU0EqKiBlcyB1biBjYXTDoWxvZ28gYXN0cm9uw7NtaWNvIGVuIGzDrW5lYSB5IHVuIHNlcnZpY2lvIGRlIGRhdG9zIHF1ZSByZWNvcGlsYSwgY29ycmVsYWNpb25hIHkgb3JnYW5pemEgaW5mb3JtYWNpw7NuIHNvYnJlIGV4b3BsYW5ldGFzIHkgc3VzIGVzdHJlbGxhcyBhbmZpdHJpb25hcy4gQWRlbcOhcywgcHJvcG9yY2lvbmEgaGVycmFtaWVudGFzIHBhcmEgdHJhYmFqYXIgY29uIGVzdG9zIGRhdG9zLiBFc3RlIGFyY2hpdm8gZXN0w6EgZGVkaWNhZG8gYSBsYSByZWNvcGlsYWNpw7NuIHkgZGlmdXNpw7NuIGRlIGNvbmp1bnRvcyBkZSBkYXRvcyBww7pibGljb3MgY2xhdmVzIHV0aWxpemFkb3MgZW4gbGEgYsO6c3F1ZWRhIHkgY2FyYWN0ZXJpemFjacOzbiBkZSBwbGFuZXRhcyBleHRyYXNvbGFyZXMgeSBzdXMgZXN0cmVsbGFzIFtAaXBhYy1leG9wbGFuZXQtc2NpZW5jZS1uby1kYXRlXS4gDQoNCkVzdGUgYXJjaGl2byBlc3TDoSBkZWRpY2FkbyBhIGxhIHJlY29waWxhY2nDs24geSBkaWZ1c2nDs24gZGUgKipjb25qdW50b3MgZGUgZGF0b3MgcMO6YmxpY29zIGNsYXZlKiogdXRpbGl6YWRvcyBlbiBsYSBiw7pzcXVlZGEgeSBjYXJhY3Rlcml6YWNpw7NuIGRlIHBsYW5ldGFzIGV4dHJhc29sYXJlcyB5IHN1cyBlc3RyZWxsYXMgW0BpcGFjLWV4b3BsYW5ldC1hcmNoaXZlLW5vLWRhdGVdLiBFbnRyZSBsb3MgZGF0b3MgZGlzcG9uaWJsZXMgc2UgaW5jbHV5ZW46DQoNCi0gICAqKlBhcsOhbWV0cm9zIGVzdGVsYXJlcyoqOiBwb3NpY2lvbmVzLCBtYWduaXR1ZGVzIHkgdGVtcGVyYXR1cmFzIGRlIGxhcyBlc3RyZWxsYXMgYW5maXRyaW9uYXMuXA0KLSAgICoqUGFyw6FtZXRyb3MgZGUgZXhvcGxhbmV0YXMqKjogbWFzYXMsIGNhcmFjdGVyw61zdGljYXMgb3JiaXRhbGVzIHkgb3Ryb3MgZGF0b3MgZnVuZGFtZW50YWxlcy5cDQotICAgKipEYXRvcyBkZSBkZXNjdWJyaW1pZW50byB5IGNhcmFjdGVyaXphY2nDs24qKjogY3VydmFzIGRlIHZlbG9jaWRhZCByYWRpYWwgcHVibGljYWRhcywgY3VydmFzIGRlIGx1eiBmb3RvbcOpdHJpY2FzLCBpbcOhZ2VuZXMgeSBlc3BlY3Ryb3MuDQoNCkVzdGEgYmFzZSBkZSBkYXRvcyBlcyB1bmEgaGVycmFtaWVudGEgZXNlbmNpYWwgcGFyYSBsYSBpbnZlc3RpZ2FjacOzbiBlbiBlbCBjYW1wbyBkZSBsYSAqKmFzdHJvbm9tw61hIGRlIGV4b3BsYW5ldGFzKiogeSBoYSBzaWRvIHV0aWxpemFkYSBlbiBudW1lcm9zb3MgZXN0dWRpb3MgY2llbnTDrWZpY29zIHkgcHJveWVjdG9zIGRlIGludmVzdGlnYWNpw7NuLiBTZSBlbmN1ZW50cmEgZGlzcG9uaWJsZSBlbiBsw61uZWEgeSBlcyBkZSBsaWJyZSBhY2Nlc28gcGFyYSBsYSBjb211bmlkYWQgY2llbnTDrWZpY2EgeSBlbCBww7pibGljbyBlbiBnZW5lcmFsIGVuIGVsIHNpdGlvIGRlbCBJUEFDIGRlbCBDYWx0ZWNoLiBFbCAqKklQQUMgKEluZnJhcmVkIFByb2Nlc3NpbmcgYW5kIEFuYWx5c2lzIENlbnRlcikqKiBlcyB1biBjZW50cm8gZGUgaW52ZXN0aWdhY2nDs24geSBwcm9jZXNhbWllbnRvIGRlIGRhdG9zIGFzdHJvbsOzbWljb3MgdWJpY2FkbyBlbiBlbCAqKkluc3RpdHV0byBkZSBUZWNub2xvZ8OtYSBkZSBDYWxpZm9ybmlhIChDYWx0ZWNoKSoqLiBTZSBlc3BlY2lhbGl6YSBlbiBsYSBnZXN0acOzbiB5IGFuw6FsaXNpcyBkZSBkYXRvcyBkZSBtaXNpb25lcyBlc3BhY2lhbGVzIHkgdGVsZXNjb3Bpb3MgYXN0cm9uw7NtaWNvcywgZW4gY29sYWJvcmFjacOzbiBjb24gYWdlbmNpYXMgY29tbyBsYSAqKk5BU0EsIGxhIEZ1bmRhY2nDs24gTmFjaW9uYWwgZGUgQ2llbmNpYXMgKE5TRikgeSBlbCBMYWJvcmF0b3JpbyBkZSBQcm9wdWxzacOzbiBhIENob3JybyAoSlBMKSoqIFtAaXBhYy1uby1kYXRlXS4NCg0KQWwgbW9tZW50byBkZSBsYSBleHRyYWNjacOzbiAoMTQgZGUgZW5lcm8gZGUgMjAyNSkgZWwgZGF0YXNldCBkZSBleG9wbGFuZXRhcyBjb250aWVuZSBpbmZvcm1hY2nDs24gc29icmUgMjguMjE3IGV4b3BsYW5ldGFzIChlbnRyZSBjb25maXJtYWRvcywgcHJvcHVlc3RvcyB5IGVuIGVzdHVkaW8pIHkgc3VzIGNhcmFjdGVyw61zdGljYXMuIExhIGJhc2UgZGUgZGF0b3MgZGUgSVBBQyBjb250aWVuZSBpbmZvcm1hY2nDs24gc29icmUgbG9zIGV4b3BsYW5ldGFzIGRldGVjdGFkb3MgcG9yIGxhIG1pc2nDs24gS2VwbGVyIHkgb3Ryb3MgdGVsZXNjb3Bpb3MsIHBlcm8gcGFyYSBlc3RlIHRyYWJham8gc2UgdXRpbGl6YXLDoSBzb2xvIGxhIGluZm9ybWFjacOzbiBkZSBsb3MgZXhvcGxhbmV0YXMgZGV0ZWN0YWRvcyBwb3IgbGEgbWlzacOzbiBLZXBsZXIgW0BjZXJtYWstMjAyNF0uDQoNClNlIGNhcmdhcsOhbiBsb3MgZGF0b3MsIHNlIGZpbHRyYXLDoW4gbGFzIGZpbGFzIGRlIGxvcyBleHBsb25ldGFzIGNvbmZpcm1hZG9zLCBsYXMgY29sdW1uYXMgcmVsZXZhbnRlcywgc2UgZWxpbWluYXLDoW4gbG9zIHZhbG9yZXMgZmFsdGFudGVzIHkgc2UgcmVhbGl6YXLDoSB1biBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGxvcyBkYXRvcyBwYXJhIGx1ZWdvIHJlYWxpemFyIGxhIHJlZ3Jlc2nDs24gbGluZWFsIHkgbG9nw61zdGljYS4NCg0KIyMgUHJlcHJvY2VzYW1pZW50byBkZSBkYXRvcw0KDQpTZSBjYXJnYW4gbG9zIGRhdG9zIGRlbCBkYXRhc2V0IGRlIGV4b3BsYW5ldGFzIGRlIGxhIG1pc2nDs24gS2VwbGVyIGRlbCBhcmNoaXZvICoqYGtlcGxlcmV4b3BsYW5ldHMuY3N2YCoqLiBFbCBtaXNtbyBzZSBvYnR1dm8gZGUgbGEgcMOhZ2luYSBkZWwgSVBBQyBkZWwgQ2FsdGVjaCBbQGlwYWMtZXhvcGxhbmV0LXNjaWVuY2Utbm8tZGF0ZV0uIExhIGNvbnN1bHRhIHVzYWRhIHBhcmEgcHJvZHVjaXIgZWwgZGF0YXNldCBmdWUgbGEgc2lndWllbnRlOg0KDQpgYGAgICAgICAgICANCiMgVGhpcyBmaWxlIHdhcyBwcm9kdWNlZCBieSB0aGUgTkFTQSBFeG9wbGFuZXQgQXJjaGl2ZSAgaHR0cDovL2V4b3BsYW5ldGFyY2hpdmUuaXBhYy5jYWx0ZWNoLmVkdQ0KIyBUdWUgSmFuIDE0IDE1OjIwOjUzIDIwMjUNCiMNCiMgVXNlciBwcmVmZXJlbmNlOiAqDQojDQojIENPTlNUUkFJTlQ6ICB3aGVyZSAoZGlzY19mYWNpbGl0eSBsaWtlICclS2VwbGVyJScpDQojDQojIENPTFVNTiBwbF9uYW1lOiAgICAgICAgUGxhbmV0IE5hbWUNCiMgQ09MVU1OIGhvc3RuYW1lOiAgICAgICBIb3N0IE5hbWUNCiMgQ09MVU1OIHBsX2xldHRlcjogICAgICBQbGFuZXQgTGV0dGVyDQojIENPTFVNTiBoZF9uYW1lOiAgICAgICAgSEQgSUQNCiMgQ09MVU1OIGhpcF9uYW1lOiAgICAgICBISVAgSUQNCiMgQ09MVU1OIHRpY19pZDogICAgICAgICBUSUMgSUQNCiMgQ09MVU1OIGdhaWFfaWQ6ICAgICAgICBHQUlBIElEDQojIENPTFVNTiBkZWZhdWx0X2ZsYWc6ICAgRGVmYXVsdCBQYXJhbWV0ZXIgU2V0DQojIENPTFVNTiBzeV9zbnVtOiAgICAgICAgTnVtYmVyIG9mIFN0YXJzDQojIENPTFVNTiBzeV9wbnVtOiAgICAgICAgTnVtYmVyIG9mIFBsYW5ldHMNCiMgQ09MVU1OIHN5X21udW06ICAgICAgICBOdW1iZXIgb2YgTW9vbnMNCiMgQ09MVU1OIGNiX2ZsYWc6ICAgICAgICBDaXJjdW1iaW5hcnkgRmxhZw0KIyBDT0xVTU4gZGlzY292ZXJ5bWV0aG9kOiBEaXNjb3ZlcnkgTWV0aG9kDQojIENPTFVNTiBkaXNjX3llYXI6ICAgICAgRGlzY292ZXJ5IFllYXINCiMgQ09MVU1OIGRpc2NfcmVmbmFtZTogICBEaXNjb3ZlcnkgUmVmZXJlbmNlDQojIENPTFVNTiBkaXNjX3B1YmRhdGU6ICAgRGlzY292ZXJ5IFB1YmxpY2F0aW9uIERhdGUNCiMgQ09MVU1OIGRpc2NfbG9jYWxlOiAgICBEaXNjb3ZlcnkgTG9jYWxlDQojIENPTFVNTiBkaXNjX2ZhY2lsaXR5OiAgRGlzY292ZXJ5IEZhY2lsaXR5DQojIENPTFVNTiBkaXNjX3RlbGVzY29wZTogRGlzY292ZXJ5IFRlbGVzY29wZQ0KIyBDT0xVTU4gZGlzY19pbnN0cnVtZW50OiBEaXNjb3ZlcnkgSW5zdHJ1bWVudA0KIyBDT0xVTU4gcnZfZmxhZzogICAgICAgIERldGVjdGVkIGJ5IFJhZGlhbCBWZWxvY2l0eSBWYXJpYXRpb25zDQojIENPTFVNTiBwdWxfZmxhZzogICAgICAgRGV0ZWN0ZWQgYnkgUHVsc2FyIFRpbWluZyBWYXJpYXRpb25zDQojIENPTFVNTiBwdHZfZmxhZzogICAgICAgRGV0ZWN0ZWQgYnkgUHVsc2F0aW9uIFRpbWluZyBWYXJpYXRpb25zDQojIENPTFVNTiB0cmFuX2ZsYWc6ICAgICAgRGV0ZWN0ZWQgYnkgVHJhbnNpdHMNCiMgQ09MVU1OIGFzdF9mbGFnOiAgICAgICBEZXRlY3RlZCBieSBBc3Ryb21ldHJpYyBWYXJpYXRpb25zDQojIENPTFVNTiBvYm1fZmxhZzogICAgICAgRGV0ZWN0ZWQgYnkgT3JiaXRhbCBCcmlnaHRuZXNzIE1vZHVsYXRpb25zDQojIENPTFVNTiBtaWNyb19mbGFnOiAgICAgRGV0ZWN0ZWQgYnkgTWljcm9sZW5zaW5nDQojIENPTFVNTiBldHZfZmxhZzogICAgICAgRGV0ZWN0ZWQgYnkgRWNsaXBzZSBUaW1pbmcgVmFyaWF0aW9ucw0KIyBDT0xVTU4gaW1hX2ZsYWc6ICAgICAgIERldGVjdGVkIGJ5IEltYWdpbmcNCiMgQ09MVU1OIGRraW5fZmxhZzogICAgICBEZXRlY3RlZCBieSBEaXNrIEtpbmVtYXRpY3MNCiMgQ09MVU1OIHNvbHR5cGU6ICAgICAgICBTb2x1dGlvbiBUeXBlDQojIENPTFVNTiBwbF9jb250cm92X2ZsYWc6IENvbnRyb3ZlcnNpYWwgRmxhZw0KIyBDT0xVTU4gcGxfcmVmbmFtZTogICAgIFBsYW5ldGFyeSBQYXJhbWV0ZXIgUmVmZXJlbmNlDQojIENPTFVNTiBwbF9vcmJwZXI6ICAgICAgT3JiaXRhbCBQZXJpb2QgW2RheXNdDQojIENPTFVNTiBwbF9vcmJzbWF4OiAgICAgT3JiaXQgU2VtaS1NYWpvciBBeGlzIFthdV0NCiMgQ09MVU1OIHBsX3JhZGU6ICAgICAgICBQbGFuZXQgUmFkaXVzIFtFYXJ0aCBSYWRpdXNdDQojIENPTFVNTiBwbF9yYWRqOiAgICAgICAgUGxhbmV0IFJhZGl1cyBbSnVwaXRlciBSYWRpdXNdDQojIENPTFVNTiBwbF9tYXNzZTogICAgICAgUGxhbmV0IE1hc3MgW0VhcnRoIE1hc3NdDQojIENPTFVNTiBwbF9tYXNzajogICAgICAgUGxhbmV0IE1hc3MgW0p1cGl0ZXIgTWFzc10NCiMgQ09MVU1OIHBsX21zaW5pZTogICAgICBQbGFuZXQgTWFzcypzaW4oaSkgW0VhcnRoIE1hc3NdDQojIENPTFVNTiBwbF9tc2luaWo6ICAgICAgUGxhbmV0IE1hc3Mqc2luKGkpIFtKdXBpdGVyIE1hc3NdDQojIENPTFVNTiBwbF9jbWFzc2U6ICAgICAgUGxhbmV0IE1hc3Mqc2luKGkpL3NpbihpKSBbRWFydGggTWFzc10NCiMgQ09MVU1OIHBsX2NtYXNzajogICAgICBQbGFuZXQgTWFzcypzaW4oaSkvc2luKGkpIFtKdXBpdGVyIE1hc3NdDQojIENPTFVNTiBwbF9ibWFzc2U6ICAgICAgUGxhbmV0IE1hc3Mgb3IgTWFzcypzaW4oaSkgW0VhcnRoIE1hc3NdDQojIENPTFVNTiBwbF9ibWFzc2o6ICAgICAgUGxhbmV0IE1hc3Mgb3IgTWFzcypzaW4oaSkgW0p1cGl0ZXIgTWFzc10NCiMgQ09MVU1OIHBsX2JtYXNzcHJvdjogICBQbGFuZXQgTWFzcyBvciBNYXNzKnNpbihpKSBQcm92ZW5hbmNlDQojIENPTFVNTiBwbF9kZW5zOiAgICAgICAgUGxhbmV0IERlbnNpdHkgW2cvY20qKjNdDQojIENPTFVNTiBwbF9vcmJlY2NlbjogICAgRWNjZW50cmljaXR5DQojIENPTFVNTiBwbF9pbnNvbDogICAgICAgSW5zb2xhdGlvbiBGbHV4IFtFYXJ0aCBGbHV4XQ0KIyBDT0xVTU4gcGxfZXF0OiAgICAgICAgIEVxdWlsaWJyaXVtIFRlbXBlcmF0dXJlIFtLXQ0KIyBDT0xVTU4gcGxfb3JiaW5jbDogICAgIEluY2xpbmF0aW9uIFtkZWddDQojIENPTFVNTiBwbF90cmFubWlkOiAgICAgVHJhbnNpdCBNaWRwb2ludCBbZGF5c10NCiMgQ09MVU1OIHBsX3RzeXN0ZW1yZWY6ICBUaW1lIFJlZmVyZW5jZSBGcmFtZSBhbmQgU3RhbmRhcmQNCiMgQ09MVU1OIHR0dl9mbGFnOiAgICAgICBEYXRhIHNob3cgVHJhbnNpdCBUaW1pbmcgVmFyaWF0aW9ucw0KIyBDT0xVTU4gcGxfaW1wcGFyOiAgICAgIEltcGFjdCBQYXJhbWV0ZXINCiMgQ09MVU1OIHBsX3RyYW5kZXA6ICAgICBUcmFuc2l0IERlcHRoIFslXQ0KIyBDT0xVTU4gcGxfdHJhbmR1cjogICAgIFRyYW5zaXQgRHVyYXRpb24gW2hvdXJzXQ0KIyBDT0xVTU4gcGxfcmF0ZG9yOiAgICAgIFJhdGlvIG9mIFNlbWktTWFqb3IgQXhpcyB0byBTdGVsbGFyIFJhZGl1cw0KIyBDT0xVTU4gcGxfcmF0cm9yOiAgICAgIFJhdGlvIG9mIFBsYW5ldCB0byBTdGVsbGFyIFJhZGl1cw0KIyBDT0xVTU4gcGxfb2NjZGVwOiAgICAgIE9jY3VsdGF0aW9uIERlcHRoIFslXQ0KIyBDT0xVTU4gcGxfb3JidHBlcjogICAgIEVwb2NoIG9mIFBlcmlhc3Ryb24gW2RheXNdDQojIENPTFVNTiBwbF9vcmJscGVyOiAgICAgQXJndW1lbnQgb2YgUGVyaWFzdHJvbiBbZGVnXQ0KIyBDT0xVTU4gcGxfcnZhbXA6ICAgICAgIFJhZGlhbCBWZWxvY2l0eSBBbXBsaXR1ZGUgW20vc10NCiMgQ09MVU1OIHBsX3Byb2pvYmxpcTogICBQcm9qZWN0ZWQgT2JsaXF1aXR5IFtkZWddDQojIENPTFVNTiBwbF90cnVlb2JsaXE6ICAgVHJ1ZSBPYmxpcXVpdHkgW2RlZ10NCiMgQ09MVU1OIHN0X3JlZm5hbWU6ICAgICBTdGVsbGFyIFBhcmFtZXRlciBSZWZlcmVuY2UNCiMgQ09MVU1OIHN0X3NwZWN0eXBlOiAgICBTcGVjdHJhbCBUeXBlDQojIENPTFVNTiBzdF90ZWZmOiAgICAgICAgU3RlbGxhciBFZmZlY3RpdmUgVGVtcGVyYXR1cmUgW0tdDQojIENPTFVNTiBzdF9yYWQ6ICAgICAgICAgU3RlbGxhciBSYWRpdXMgW1NvbGFyIFJhZGl1c10NCiMgQ09MVU1OIHN0X21hc3M6ICAgICAgICBTdGVsbGFyIE1hc3MgW1NvbGFyIG1hc3NdDQojIENPTFVNTiBzdF9tZXQ6ICAgICAgICAgU3RlbGxhciBNZXRhbGxpY2l0eSBbZGV4XQ0KIyBDT0xVTU4gc3RfbWV0cmF0aW86ICAgIFN0ZWxsYXIgTWV0YWxsaWNpdHkgUmF0aW8NCiMgQ09MVU1OIHN0X2x1bTogICAgICAgICBTdGVsbGFyIEx1bWlub3NpdHkgW2xvZyhTb2xhcildDQojIENPTFVNTiBzdF9sb2dnOiAgICAgICAgU3RlbGxhciBTdXJmYWNlIEdyYXZpdHkgW2xvZzEwKGNtL3MqKjIpXQ0KIyBDT0xVTU4gc3RfYWdlOiAgICAgICAgIFN0ZWxsYXIgQWdlIFtHeXJdDQojIENPTFVNTiBzdF9kZW5zOiAgICAgICAgU3RlbGxhciBEZW5zaXR5IFtnL2NtKiozXQ0KIyBDT0xVTU4gc3RfdnNpbjogICAgICAgIFN0ZWxsYXIgUm90YXRpb25hbCBWZWxvY2l0eSBba20vc10NCiMgQ09MVU1OIHN0X3JvdHA6ICAgICAgICBTdGVsbGFyIFJvdGF0aW9uYWwgUGVyaW9kIFtkYXlzXQ0KIyBDT0xVTU4gc3RfcmFkdjogICAgICAgIFN5c3RlbWljIFJhZGlhbCBWZWxvY2l0eSBba20vc10NCiMgQ09MVU1OIHN5X3JlZm5hbWU6ICAgICBTeXN0ZW0gUGFyYW1ldGVyIFJlZmVyZW5jZQ0KIyBDT0xVTU4gcmFzdHI6ICAgICAgICAgIFJBIFtzZXhhZ2VzaW1hbF0NCiMgQ09MVU1OIHJhOiAgICAgICAgICAgICBSQSBbZGVnXQ0KIyBDT0xVTU4gZGVjc3RyOiAgICAgICAgIERlYyBbc2V4YWdlc2ltYWxdDQojIENPTFVNTiBkZWM6ICAgICAgICAgICAgRGVjIFtkZWddDQojIENPTFVNTiBnbGF0OiAgICAgICAgICAgR2FsYWN0aWMgTGF0aXR1ZGUgW2RlZ10NCiMgQ09MVU1OIGdsb246ICAgICAgICAgICBHYWxhY3RpYyBMb25naXR1ZGUgW2RlZ10NCiMgQ09MVU1OIGVsYXQ6ICAgICAgICAgICBFY2xpcHRpYyBMYXRpdHVkZSBbZGVnXQ0KIyBDT0xVTU4gZWxvbjogICAgICAgICAgIEVjbGlwdGljIExvbmdpdHVkZSBbZGVnXQ0KIyBDT0xVTU4gc3lfcG06ICAgICAgICAgIFRvdGFsIFByb3BlciBNb3Rpb24gW21hcy95cl0NCiMgQ09MVU1OIHN5X3BtcmE6ICAgICAgICBQcm9wZXIgTW90aW9uIChSQSkgW21hcy95cl0NCiMgQ09MVU1OIHN5X3BtZGVjOiAgICAgICBQcm9wZXIgTW90aW9uIChEZWMpIFttYXMveXJdDQojIENPTFVNTiBzeV9kaXN0OiAgICAgICAgRGlzdGFuY2UgW3BjXQ0KIyBDT0xVTU4gc3lfcGx4OiAgICAgICAgIFBhcmFsbGF4IFttYXNdDQojIENPTFVNTiBzeV9ibWFnOiAgICAgICAgQiAoSm9obnNvbikgTWFnbml0dWRlDQojIENPTFVNTiBzeV92bWFnOiAgICAgICAgViAoSm9obnNvbikgTWFnbml0dWRlDQojIENPTFVNTiBzeV9qbWFnOiAgICAgICAgSiAoMk1BU1MpIE1hZ25pdHVkZQ0KIyBDT0xVTU4gc3lfaG1hZzogICAgICAgIEggKDJNQVNTKSBNYWduaXR1ZGUNCiMgQ09MVU1OIHN5X2ttYWc6ICAgICAgICBLcyAoMk1BU1MpIE1hZ25pdHVkZQ0KIyBDT0xVTU4gc3lfdW1hZzogICAgICAgIHUgKFNsb2FuKSBNYWduaXR1ZGUNCiMgQ09MVU1OIHN5X2dtYWc6ICAgICAgICBnIChTbG9hbikgTWFnbml0dWRlDQojIENPTFVNTiBzeV9ybWFnOiAgICAgICAgciAoU2xvYW4pIE1hZ25pdHVkZQ0KIyBDT0xVTU4gc3lfaW1hZzogICAgICAgIGkgKFNsb2FuKSBNYWduaXR1ZGUNCiMgQ09MVU1OIHN5X3ptYWc6ICAgICAgICB6IChTbG9hbikgTWFnbml0dWRlDQojIENPTFVNTiBzeV93MW1hZzogICAgICAgVzEgKFdJU0UpIE1hZ25pdHVkZQ0KIyBDT0xVTU4gc3lfdzJtYWc6ICAgICAgIFcyIChXSVNFKSBNYWduaXR1ZGUNCiMgQ09MVU1OIHN5X3czbWFnOiAgICAgICBXMyAoV0lTRSkgTWFnbml0dWRlDQojIENPTFVNTiBzeV93NG1hZzogICAgICAgVzQgKFdJU0UpIE1hZ25pdHVkZQ0KIyBDT0xVTU4gc3lfZ2FpYW1hZzogICAgIEdhaWEgTWFnbml0dWRlDQojIENPTFVNTiBzeV9pY21hZzogICAgICAgSSAoQ291c2lucykgTWFnbml0dWRlDQojIENPTFVNTiBzeV90bWFnOiAgICAgICAgVEVTUyBNYWduaXR1ZGUNCiMgQ09MVU1OIHN5X2tlcG1hZzogICAgICBLZXBsZXIgTWFnbml0dWRlDQojIENPTFVNTiByb3d1cGRhdGU6ICAgICAgRGF0ZSBvZiBMYXN0IFVwZGF0ZQ0KIyBDT0xVTU4gcGxfcHViZGF0ZTogICAgIFBsYW5ldGFyeSBQYXJhbWV0ZXIgUmVmZXJlbmNlIFB1YmxpY2F0aW9uIERhdGUNCiMgQ09MVU1OIHJlbGVhc2VkYXRlOiAgICBSZWxlYXNlIERhdGUNCiMgQ09MVU1OIHBsX25ub3RlczogICAgICBOdW1iZXIgb2YgTm90ZXMNCiMgQ09MVU1OIHN0X25waG90OiAgICAgICBOdW1iZXIgb2YgUGhvdG9tZXRyeSBUaW1lIFNlcmllcw0KIyBDT0xVTU4gc3RfbnJ2YzogICAgICAgIE51bWJlciBvZiBSYWRpYWwgVmVsb2NpdHkgVGltZSBTZXJpZXMNCiMgQ09MVU1OIHN0X25zcGVjOiAgICAgICBOdW1iZXIgb2YgU3RlbGxhciBTcGVjdHJhIE1lYXN1cmVtZW50cw0KIyBDT0xVTU4gcGxfbmVzcGVjOiAgICAgIE51bWJlciBvZiBFY2xpcHNlIFNwZWN0cmENCiMgQ09MVU1OIHBsX250cmFuc3BlYzogICBOdW1iZXIgb2YgVHJhbnNtaXNzaW9uIFNwZWN0cmENCiMgQ09MVU1OIHBsX25kaXNwZWM6ICAgICBOdW1iZXIgb2YgRGlyZWN0IEltYWdpbmcgU3BlY3RyYQ0KIw0KYGBgDQoNCkVsIGVuY2FiZXphZG8gbcOhcyBhcnJpYmEgZXN0YWJhIGluY2x1w61kbyBlbiBlbCBhcmNoaXZvIC5DU1YgZ2VuZXJhZG8geSBzZSBpbmNsdXllIGFxdcOtIHBhcmEgcmVwcm9kdWNpciBsYSBjb25zdWx0YS4gRWwgZGF0YXNldCBjb250aWVuZSBpbmZvcm1hY2nDs24gc29icmUgbG9zIHNpc3RlbWFzIGV4b3BsYW5ldGFyaW9zIGRldGVjdGFkb3MgcG9yIGxhIG1pc2nDs24gS2VwbGVyIHkgZWwgZGljY2lvbmFyaW8gZGUgZGF0b3Mgc2UgZW5jdWVudHJhIGVuIGzDrW5lYSBbQGlwYWMtcGxhbmV0YXJ5LWRhdGEtbm8tZGF0ZV0gZXhwbGljYW5kbyBlbiBtw6FzIHByb2Z1bmRpZGFkIGxhIHNlbcOhbnRpY2EgZGUgbGFzIHZhcmlhYmxlcy4NCg0KVG9kb3MgbG9zIGFyY2hpdm9zIG5lY2VzYXJpb3MgcGFyYSBlc3RlIHRyYWJham8gc2UgZW5jdWVudHJhbiBlbiBlbCByZXBvc2l0b3JpbyBkZSBHaXRIdWIgZGVsIGF1dG9yIFtAbmljb2xhdS0yMDI1XSB5IHNlIHB1ZWRlbiBkZXNjYXJnYXIgZGVzZGUgYWxsw60gcGFyYSByZXByb2R1Y2lyIGVzdGUgYW7DoWxpc2lzLCBpbmNsdXllbmRvIGVsIGRhdGFzZXQgKipga2VwbGVyZXhvcGxhbmV0cy5jc3ZgKiogcXVlIGEgY29udGludWFjacOzbiBzZSBjYXJnYS4NCg0KYGBge3IgbG9hZF9kYXRhLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShyZWFkcikNCg0KIyBDYXJnYXIgbG9zIGRhdG9zIGRlbCBhcmNoaXZvIENTVg0Ka2VwbGVyX2RhdGEgPC0gcmVhZF9jc3YoImtlcGxlcmV4b3BsYW5ldHMuY3N2IikNCmBgYA0KDQoqKkVzdHJ1Y3R1cmEgZGUgbG9zIERhdG9zKioNCg0KYGBge3Igc2hvd19kYXRhX3N0cn0NCg0KbGlicmFyeShrbml0cikNCg0KIyBDYXB0dXJhciBsYSBzYWxpZGEgZGUgc3RyKCkgY29tbyB0ZXh0bw0Kc3RyX291dHB1dCA8LSBjYXB0dXJlLm91dHB1dChzdHIoa2VwbGVyX2RhdGEsIGxpc3QubGVuID0gSW5mLCBnaXZlLmF0dHI9RkFMU0UpKQ0KDQojIENvbnZlcnRpciBsYSBzYWxpZGEgZW4gdW4gZGF0YSBmcmFtZSBwYXJhIGZvcm1hdGVhcmxhIGNvbW8gdGFibGENCnN0cl9kZiA8LSBkYXRhLmZyYW1lKA0KICBEZXRhaWxzID0gc3RyX291dHB1dCwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgTW9zdHJhciBsYSBzYWxpZGEgZW4gZm9ybWF0byBkZSB0YWJsYSBjb24ga2FibGUNCmthYmxlKHN0cl9kZiwgY29sLm5hbWVzID0gYygiVGlwbyBkZSBkYXRvcyB5IHByZXZpc3VhbGl6YWNpw7NuIiksIGFsaWduID0gImwiKQ0KDQpgYGANCg0KUGFyYSBlbCBhbsOhbGlzaXMgc2UgY29uc2lkZXJhcsOhbiBzb2xvIGxvcyBleG9wbGFuZXRhcyBjb25maXJtYWRvcyB5IHNlIGVsaW1pbmFyw6FuIGxhcyBjb2x1bW5hcyBubyByZWxldmFudGVzIHBhcmEgZWwgYW7DoWxpc2lzLg0KDQpQYXJhIHJlZHVjaXIgbGEgZGltZW5zaW9uYWxpZGFkIGRlbCBwcm9ibGVtYSwgYSBjb250aW51YWNpw7NuIHNlIGVsaW1pbmFuIGxhcyBjb2x1bW5hcyBjb24gcmVmZXJlbmNpYXMgYSBzaXRpb3Mgd2ViIG5vIHJlbGV2YW50ZXMgcGFyYSBlbCBhbsOhbGlzaXMuIFRhbWJpw6luIHNlIGVsaW1pbmFuIGxvcyBkYXRvcyBkZSByZWZlcmVuY2lhIGRlIGxvcyBwbGFuZXRhcywgZXN0cmVsbGFzIHkgc2lzdGVtYXMgbm8gcmVsZXZhbnRlcyBwYXJhIGVsIGFuw6FsaXNpcyB0YWxlcyBjb21vIHJlZmVyZW5jaWFzIGEgY2F0w6Fsb2dvcyBleHRlcm5vcyBkZSBlc3RyZWxsYXMgeSBzaXN0ZW1hcywgaW5mb3JtYWNpw7NuIGRlIHB1YmxpY2FjacOzbiBkZWwgZGVzY3VicmltaWVudG8sIGluZm9ybWFjacOzbiBkZSBkZXRlY2Npw7NuLCBpbmZvcm1hY2nDs24gZGUgZm90b21ldHLDrWEsIGJhbmRlcmFzIGRlIG9yZ2FuaXphY2nDs24gaW50ZXJuYSBkZWwgZGF0YXNldCwgaW5mb3JtYWNpw7NuIGRlbCBzaXN0ZW1hIHBsYW5ldGFyaW8geSBkZXRhbGxlcyB0w6ljbmljb3MgZGUgbGEgZGV0ZWNjacOzbi4NCg0KUGFyYSByZWR1Y2lyIGxhIGNhbnRpZGFkIGRlIHJlZ2lzdHJvcyBkZWwgZGF0YXNldCB5IGNvbW8gc2UgYnVzY2EgcHJlZGVjaXIgbGEgaGFiaXRhYmlsaWRhZCBkZSBsb3MgZXhvcGxhbmV0YXMgZW4gc2lzdGVtYXMgc2ltaWxhcmVzIGFsIFNvbGFyLCBzZSBmaWx0cmFuIGxvcyBzaXN0ZW1hcyBjb24gZXN0cmVsbGFzIGRlIHRhbWHDsW8gc2ltaWxhciBhbCBTb2wgKDAuOSBhIDEuMSByYWRpb3Mgc29sYXJlcykuIEhheSBtdWNoYXMgZW50cmFkYXMgY29uIHZhbG9yZXMgZmFsdGFudGVzIGVuIGxhcyBjb2x1bW5hcyBkZSB0aXBvIGVzcGVjdHJhbCBkZSBsYXMgZXN0cmVsbGFzIChsYSBtYXlvcsOtYSkgcXVlIHNlcsOtYSB1biBtZWpvciBpbmRpY2Fkb3IgcGFyYSBkZXRlcm1pbmFybCBsYSB6b25hIGhhYml0YWJsZSwgcG9yIGVzbyBzZSB0b21hIGNvbW8gY3JpdGVyaW8gZGUgZmlsdHJvIGVsIHRhbWHDsW8gZGUgbGFzIGVzdHJlbGxhcy4gQWRlbcOhcyBzZSBjb25zaWRlcmFyYW4gcGFyYSBsYSBtdWVzdGEgc29sbyBsb3MgZXhvcGxhbmV0YXMgcHVibGljYWRvcyBlbiBsYSBsaXRlcmF0dXJhIGNpZW50w61maWNhLCBwb3IgbG8gcXVlIHNlIGZpbHRyYSBwb3IgIlB1Ymxpc2hlZCBDb25maXJtZWQiIGVuIGxhIGNvbHVtbmEgKipgc29sdHlwZWAqKi4NCg0KYGBge3IgZmlsdGVyX2RhdGEsIHdhcm5pbmc9RkFMU0V9DQoNCmxpYnJhcnkoZHBseXIpDQoNCiMgUEFSVEUgMSAtIEZJTFRSTyBERSBEQVRPUw0KIyBTZWxlY2Npb25hciBsb3Mgc2lzdGVtYXMgY29uIGVzdHJlbGxhcyBkZSB0YW1hw7FvDQojIHNpbWlsYXIgYWwgU29sICgwLjkgYSAxLjEgcmFkaW9zIHNvbGFyZXMpDQprZXBsZXJfZGF0YSA8LSBmaWx0ZXIoa2VwbGVyX2RhdGEsIHN0X3JhZCA+PSAwLjkgJiBzdF9yYWQgPD0gMS4xKQ0KDQojIFNlbGVjY2lvbmFyIHNvbG8gbG9zIGV4b3BsYW5ldGFzIHB1YmxpY2Fkb3MgZW4gbGEgbGl0ZXJhdHVyYSBjaWVudMOtZmljYQ0Ka2VwbGVyX2RhdGEgPC0gZmlsdGVyKGtlcGxlcl9kYXRhLCBzb2x0eXBlID09ICJQdWJsaXNoZWQgQ29uZmlybWVkIikNCg0KIyBQQVJURSAyIC0gUkVEVUNDSU9OIERFIExBIERJTUVOU0lPTkFMSURBRA0KIyBFbGltaW5hciBjb2x1bW5hcyBkZSByZWZlcmVuY2lhcyBhIHNpdGlvcyB3ZWINCmtlcGxlcl9kYXRhIDwtIHN1YnNldChrZXBsZXJfZGF0YSwgc2VsZWN0ID0gYygtZGlzY19yZWZuYW1lLCAtcGxfcmVmbmFtZSwgLXN0X3JlZm5hbWUsIC1zeV9yZWZuYW1lKSkNCg0KIyBFbGltaW5hciBjb2x1bW5hcyBkZSBpZCBkZSBjYXRhbG9nb3MgZXh0ZXJub3MgZGUgZXN0cmVsbGFzIHkgc2lzdGVtYXMNCmtlcGxlcl9kYXRhIDwtIHN1YnNldChrZXBsZXJfZGF0YSwgc2VsZWN0ID0gYygtdGljX2lkLCAtZ2FpYV9pZCkpDQoNCiMgRWxpbWluYXIgaW5mb3JtYWNpw7NuIHJlZmVyZW50ZSBhIGxhIHB1YmxpY2FjacOzbiBkZWwgZGVzY3VicmltaWVudG8NCiMgYXPDrSBjb21vIGxhIGluZm9ybWFjacOzbiBkZWwgaW5zdHJ1bWVudG8gdXRpbGl6YWRvLCBwYXJhIHRvZG9zIGVzIEtlcGxlcg0Ka2VwbGVyX2RhdGEgPC0gc3Vic2V0KGtlcGxlcl9kYXRhLCBzZWxlY3QgPSBjKC1kaXNjX3llYXIsIC1kaXNjX3B1YmRhdGUsIC1kaXNjX2xvY2FsZSwgLWRpc2NfZmFjaWxpdHksIC1kaXNjX3RlbGVzY29wZSwgLWRpc2NfaW5zdHJ1bWVudCwgLXJvd3VwZGF0ZSwgLXBsX3B1YmRhdGUsIC1yZWxlYXNlZGF0ZSkpDQoNCiMgRWxpbWluYXIgY29sdW1uYXMgY29uIGluZm9ybWFjacOzbiByZWZlcmVudGUgYSBsYSBkZXRlY2Npw7NuDQprZXBsZXJfZGF0YSA8LSBzdWJzZXQoa2VwbGVyX2RhdGEsIHNlbGVjdCA9IGMoLXJ2X2ZsYWcsIC1wdWxfZmxhZywgLXB0dl9mbGFnLCAtdHJhbl9mbGFnLCAtYXN0X2ZsYWcsIC1vYm1fZmxhZywgLW1pY3JvX2ZsYWcsIC1ldHZfZmxhZywgLWltYV9mbGFnLCAtZGtpbl9mbGFnKSkNCg0KIyBFbGltaW5hciBjb2x1bW5hcyBjb24gaW5mb3JtYWNpw7NuIGRlIGZvdG9tZXRyaWENCmtlcGxlcl9kYXRhIDwtIHN1YnNldChrZXBsZXJfZGF0YSwgc2VsZWN0ID0gYygtc3lfYm1hZywgLXN5X3ZtYWcsIC1zeV9qbWFnLCAtc3lfaG1hZywgLXN5X2ttYWcsIC1zeV91bWFnLCAtc3lfZ21hZywgLXN5X3JtYWcsIC1zeV9pbWFnLCAtc3lfem1hZywgLXN5X3cxbWFnLCAtc3lfdzJtYWcsIC1zeV93M21hZywgLXN5X3c0bWFnLCAtc3lfZ2FpYW1hZywgLXN5X2ljbWFnLCAtc3lfdG1hZywgLXN5X2tlcG1hZykpDQoNCiMgRWxpbWluYXIgYmFuZGVyYXMgZGUgb3JnYW5pemFjacOzbiBpbnRlcm5hIGRlbCBkYXRhc2V0DQprZXBsZXJfZGF0YSA8LSBzdWJzZXQoa2VwbGVyX2RhdGEsIHNlbGVjdCA9IGMoLXBsX25ub3RlcywgLXBsX2NvbnRyb3ZfZmxhZywgLWRlZmF1bHRfZmxhZykpDQoNCiMgRWxpbWluYXIgY29sdW1uYXMgY29uIGluZm9ybWFjacOzbiBkZWwgc2lzdGVtYSBwbGFuZXRhcmlvDQojIHkgZGV0YWxsZXMgdMOpY25pY29zIGRlIGxhIGRldGVjY2nDs24NCmtlcGxlcl9kYXRhIDwtIHN1YnNldChrZXBsZXJfZGF0YSwgc2VsZWN0ID0gYygtc3lfbW51bSwgLXBsX25kaXNwZWMpKQ0KDQojIEVsaW1pbmFyIGNvbHVtbmFzIGNvbiBpbmZvcm1hY2nDs24gYWRpY2lvbmFsIGRlIGZvdG9tZXRyaWENCmtlcGxlcl9kYXRhIDwtIHN1YnNldCgga2VwbGVyX2RhdGEsIHNlbGVjdCA9IGMoLXN0X25waG90LCAtc3RfbnJ2YywgLXN0X25zcGVjLCAtcGxfbmVzcGVjLCAtcGxfbnRyYW5zcGVjKSkNCg0KYGBgDQoNCkVsIGRhdGFzZXQgcmVzdWx0YW50ZSBzZSBndWFyZGEgZW4gdW4gYXJjaGl2byBDU1YgbGxhbWFkbyAqKmBrZXBsZXJmaWx0ZXJlZC5jc3ZgKiouIEVsIGRhdGFzZXQgcmVzdWx0YW50ZSBjb250aWVuZSAyNTQ3IHJlZ2lzdHJvcyB5IDY4IGNvbHVtbmFzLg0KDQpMYXMgY29sdW1uYXMgZW4gZWwgZGF0YXNldCBmaWx0cmFkbywgeSBzdSBkZXNjcmlwY2nDs24gZXh0cmHDrWRhIGRlbCBkaWNjaW9uYXJpbyBkZSBkYXRvcyBbQGlwYWMtcGxhbmV0YXJ5LWRhdGEtbm8tZGF0ZV0sIHNvbiBsYXMgc2lndWllbnRlczoNCg0KYGBge3Igc2hvd19maWx0ZXJlZF9kYXRhX3N0cnVjdHVyZX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIE9yZGVuYXIgbGFzIGNvbHVtbmFzIGFsZmFiw6l0aWNhbWVudGUNCmtlcGxlcl9kYXRhIDwtIGtlcGxlcl9kYXRhWywgb3JkZXIobmFtZXMoa2VwbGVyX2RhdGEpKV0NCg0KIyBDb3BpYXIgZWwgbm9tYnJlIGRlIGxhcyBjb2x1bW5hcyBhIHVuIGRhdGEgZnJhbWUNCmNvbHVtbl9uYW1lcyA8LSBkYXRhLmZyYW1lKA0KICBDb2x1bW4gPSBuYW1lcyhrZXBsZXJfZGF0YSksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQojIEFncmVnYXIgdW5hIGNvbHVtbmEgY29uIGxhIGRlc2NyaXBjacOzbiBkZSBsYSB2YXJpYWJsZQ0KIyBGdWVudGU6IGh0dHBzOi8vZXhvcGxhbmV0YXJjaGl2ZS5pcGFjLmNhbHRlY2guZWR1L2RvY3MvQVBJX1BTX2NvbHVtbnMuaHRtbA0KY29sdW1uX25hbWVzIDwtIGNvbHVtbl9uYW1lcyAlPiUNCiAgbXV0YXRlKERlc2NyaXB0aW9uID0gYygNCiAgICAiY2JfZmxhZzogRmxhZyBkZSBjaXJjdW1iaW5hcmlvIChlbCBwbGFuZXRhIG9yYml0YSB1biBzaXN0ZW1hIGJpbmFyaW8pIiwNCiAgICAiZGVjOiBEZWNsaW5hY2nDs24gZGUgbGEgZXN0cmVsbGEgKGVuIGdyYWRvcyBkZWNpbWFsZXMpIiwNCiAgICAiZGVjc3RyOiBEZWNsaW5hY2nDs24gZGUgbGEgZXN0cmVsbGEgKGVuIGdyYWRvcyBzZXhhZ2VzaW1hbGVzKSIsDQogICAgImRpc2NvdmVyeW1ldGhvZDogTcOpdG9kbyBkZSBkZXNjdWJyaW1pZW50byBkZWwgcGxhbmV0YSIsDQogICAgImVsYXQ6IExhdGl0dWQgZWNsw61wdGljYSBkZSBsYSBlc3RyZWxsYSAoZW4gZ3JhZG9zIGRlY2ltYWxlcykiLA0KICAgICJlbG9uOiBMb25naXR1ZCBlY2zDrXB0aWNhIGRlIGxhIGVzdHJlbGxhIChlbiBncmFkb3MgZGVjaW1hbGVzKSIsDQogICAgImdsYXQ6IExhdGl0dWQgZ2Fsw6FjdGljYSBkZSBsYSBlc3RyZWxsYSAoZW4gZ3JhZG9zIGRlY2ltYWxlcykiLA0KICAgICJnbG9uOiBMb25naXR1ZCBnYWzDoWN0aWNhIGRlIGxhIGVzdHJlbGxhIChlbiBncmFkb3MgZGVjaW1hbGVzKSIsDQogICAgImhkX25hbWU6IE5vbWJyZSBkZWwgc2lzdGVtYSBlc3RlbGFyIGVuIGVsIGNhdMOhbG9nbyBIZW5yeSBEcmFwZXIiLA0KICAgICJoaXBfbmFtZTogTm9tYnJlIGRlbCBzaXN0ZW1hIGVzdGVsYXIgZW4gZWwgY2F0w6Fsb2dvIEhpcHBhcmNvcyIsDQogICAgImhvc3RuYW1lOiBOb21icmUgZGVsIHNpc3RlbWEgZXN0ZWxhciB1dGlsaXphZG8gZW4gbGEgbGl0ZXJhdHVyYSIsDQogICAgInBsX2JtYXNzZTogTWVqb3IgZXN0aW1hY2nDs24gZGUgbGEgbWFzYSBkZWwgcGxhbmV0YSAoZW4gbWFzYXMgdGVycmVzdHJlcykiLA0KICAgICJwbF9ibWFzc2o6IE1lam9yIGVzdGltYWNpw7NuIGRlIGxhIG1hc2EgZGVsIHBsYW5ldGEgKGVuIG1hc2FzIGpvdmlhbmFzKSIsDQogICAgInBsX2JtYXNzcHJvdjogUHJvdmVlZG9yIGRlIGxhIG1lam9yIGVzdGltYWNpw7NuIGRlIGxhIG1hc2EgZGVsIHBsYW5ldGEgKG3DrW5pbWEgbyBwcm95ZWN0YWRhKSIsDQogICAgInBsX2NtYXNzZTogTWFzYSBtw61uaW1hIHByb3llY3RhZGEgKGVuIG1hc2FzIHRlcnJlc3RyZXMpIiwNCiAgICAicGxfY21hc3NqOiBNYXNhIG3DrW5pbWEgcHJveWVjdGFkYSAoZW4gbWFzYXMgam92aWFuYXMpIiwNCiAgICAicGxfZGVuczogRGVuc2lkYWQgZGVsIHBsYW5ldGEgKGVuIGcvY23CsykiLA0KICAgICJwbF9lcXQ6IFRlbXBlcmF0dXJhIGRlIGVxdWlsaWJyaW8gZGVsIHBsYW5ldGEgY29uc2lkZXJvIGNvbW8gdW4gY3VlcnBvIG9zY3VyIChlbiBncmFkb3MgSykiLA0KICAgICJwbF9pbXBwYXI6IFBhcsOhbWV0cm8gZGUgaW1wYWN0byBkZWwgcGxhbmV0YSBjb21vIGRpc3RhbmNpYSBwcm95ZWN0YWRhIGRlbCBjZW50cm8gZGVsIHBsYW5ldGEgYWwgY2VudHJvIGRlIGxhIGVzdHJlbGxhIChlbiByYWRpb3MgZXN0ZWxhcmVzKSIsDQogICAgInBsX2luc29sOiBJbnNvbGFjacOzbiBkZWwgcGxhbmV0YSBlbiB0ZXJtaW5vcyBsYSBpbnNvbGFjacOzbiBkZSBsYSB0aWVycmEgKGVuIFcvbcKyKSIsDQogICAgInBsX2xldHRlcjogTGV0cmEgZGVsIHBsYW5ldGEgZW4gZWwgc2lzdGVtYSAocHJpbWVyIHBsYW5ldGEgZXMgYikiLA0KICAgICJwbF9tYXNzZTogTWFzYSBkZWwgcGxhbmV0YSAoZW4gbWFzYXMgdGVycmVzdHJlcykiLA0KICAgICJwbF9tYXNzajogTWFzYSBkZWwgcGxhbmV0YSAoZW4gbWFzYXMgam92aWFuYXMpIiwNCiAgICAicGxfbXNpbmllOiBNw61uaW1vIGRlIG1hc2EgbWVkaWRhIHBvciBlbCBtw6l0b2RvIGRlIHZlbG9jaWRhZCByYWRpYWwgKGVuIG1hc2FzIHRlcnJlc3RyZXMpIiwNCiAgICAicGxfbXNpbmlqOiBNw61uaW1vIGRlIG1hc2EgbWVkaWRhIHBvciBlbCBtw6l0b2RvIGRlIHZlbG9jaWRhZCByYWRpYWwgKGVuIG1hc2FzIGpvdmlhbmFzKSIsDQogICAgInBsX29jY2RlcDogUHJvZnVuZGlkYWQgZGVsIGVjbGlwc2UgZGVsIHBsYW5ldGEgZW4gdGVybWlub3MgZGUgZWwgZmx1am8gcmVsYXRpdm8gZGVjcmVjaWVudGUgZnJlbnRlIGEgc3UgZXN0cmVsbGEgKGVuICUpIiwNCiAgICAicGxfb3JiZWNjZW46IEV4Y2VudHJpY2lkYWQgb3JiaXRhbCBkZWwgcGxhbmV0YSIsDQogICAgInBsX29yYmluY2w6IEluY2xpbmFjacOzbiBvcmJpdGFsIGRlbCBwbGFuZXRhIHJlc3BlY3RvIGRlIGxhIGzDrW5lYSBkZSB2aXNpw7NuIGRlc2RlIGxhIFRpZXJyYSAoZW4gZ3JhZG9zKSIsDQogICAgInBsX29yYmxwZXI6IEVsIGFyZ3VtZW50byBkZWwgcGVyaWFzdHJvIGRlbCBwbGFuZXRhIChlbiBncmFkb3MpIiwNCiAgICAicGxfb3JicGVyOiBQZXJpb2RvIG9yYml0YWwgZGVsIHBsYW5ldGEgKGVuIGTDrWFzKSIsDQogICAgInBsX29yYnNtYXg6IERpc3RhbmNpYSBvcmJpdGFsIHNlbWllamUgbWF5b3IgKGVuIFVBKSIsDQogICAgInBsX29yYnRwZXI6IEVsIG1vbWVudG8gZGVsIHBhc28gZGVsIHBsYW5ldGEgcG9yIGVsIHBlcmlhc3RybyAoZW4gZ3JhZG9zKSIsDQogICAgInBsX3Byb2pvYmxpcTogSW5jbGluYWNpw7NuIHByb3llY3RhZGEgZGVsIHBsYW5ldGEgcmVzcGVjdG8gZGUgbGEgbMOtbmVhIGRlIHZpc2nDs24gZGVzZGUgbGEgVGllcnJhIChlbiBncmFkb3MpIiwNCiAgICAicGxfcmFkZTogUmFkaW8gZGVsIHBsYW5ldGEgKGVuIHJhZGlvcyB0ZXJyZXN0cmVzKSIsDQogICAgInBsX3JhZGo6IFJhZGlvIGRlbCBwbGFuZXRhIChlbiByYWRpb3Mgam92aWFub3MpIiwNCiAgICAicGxfcmF0ZG9yOiBjb2NpZW50ZSBkZWwgc2VtaWVqZSBvcmJpdGFsIG1heW9yIHNvYnJlIGVsIHJhZGlvIGVzdGVsYXIiLA0KICAgICJwbF9yYXRyb3I6IGNvY2llbnRlIGRlbCByYWRpbyBkZWwgcGxhbmV0YSBzb2JyZSBlbCByYWRpbyBlc3RlbGFyIiwNCiAgICAicGxfcnZhbXA6IEFtcGxpdHVkIGRlIGxhIHZlbG9jaWRhZCByYWRpYWwgZGVsIHBsYW5ldGEgKGVuIG0vcykiLA0KICAgICJwbF90cmFuZGVwOiBQcm9mdW5kaWRhZCBkZWwgdHLDoW5zaXRvIGRlbCBwbGFuZXRhIGVuIHRlcm1pbm9zIGRlIGVsIGZsdWpvIHJlbGF0aXZvIGRlY3JlY2llbnRlIGZyZW50ZSBhIHN1IGVzdHJlbGxhIChlbiAlKSIsDQogICAgInBsX3RyYW5kdXI6IER1cmFjacOzbiBkZWwgdHLDoW5zaXRvIGRlbCBwbGFuZXRhIChlbiBob3JhcykiLA0KICAgICJwbF90cmFubWlkOiBUaWVtcG8gZGUgdHLDoW5zaXRvIG1lZGlvIGRlbCBwbGFuZXRhIHJlc3BlY3RvIGRlIHN1IGVzdHJlbGxhIChlbiBkw61hcykiLA0KICAgICJwbF90cnVlb2JsaXE6IEluY2xpbmFjacOzbiB2ZXJkYWRlcmEgZGVsIHBsYW5ldGEgcmVzcGVjdG8gZGUgbGEgbMOtbmVhIGRlIHZpc2nDs24gZGVzZGUgbGEgVGllcnJhIChlbiBncmFkb3MpIiwNCiAgICAicGxfdHN5c3RlbXJlZjogU2lzdGVtYSBkZSBUaWVtcG8gZGUgUmVmZXJlbmNpYSBkZWwgc2lzdGVtYSBwbGFuZXRhcmlvIiwNCiAgICAicmE6IEFzY2Vuc2nDs24gcmVjdGEgZGUgbGEgZXN0cmVsbGEgKGVuIGdyYWRvcyBkZWNpbWFsZXMpIiwNCiAgICAicmFzdHI6IEFzY2Vuc2nDs24gcmVjdGEgZGUgbGEgZXN0cmVsbGEgKGVuIGdyYWRvcyBzZXhhZ2VzaW1hbGVzKSIsDQogICAgInNvbHR5cGU6IERpc3Bvc2ljacOzbiBkZWwgcGxhbmV0YSBzZWfDum4gZWwgY29uanVudG8gZGUgcGFyw6FtZXRyb3MgcGxhbmV0YXJpb3MgZGFkbyIsDQogICAgInN0X2FnZTogRWRhZCBkZSBsYSBlc3RyZWxsYSAoZW4gR2EsIGdpZ2Fhw7FvcywgbyBtaWxlcyBkZSBtaWxsb25lcyBkZSBhw7FvcykiLA0KICAgICJzdF9kZW5zOiBEZW5zaWRhZCBkZSBsYSBlc3RyZWxsYSAoZW4gZy9jbcKzKSIsDQogICAgInN0X2xvZ2c6IEdyYXZlZGFkIHN1cGVyZmljaWFsIGRlIGxhIGVzdHJlbGxhIChlbiBsb2dhcml0bW8gZW4gYmFzZSAxMCBkZSBjbS9zwrIpIiwNCiAgICAic3RfbHVtOiBMdW1pbm9zaWRhZCBkZSBsYSBlc3RyZWxsYSAoZW4gbG9nYXJ0aW1hIGVuIGJhc2UgMTAgZGUgdW5pZGFkZXMgc29sYXJlcykiLA0KICAgICJzdF9tYXNzOiBNYXNhIGRlIGxhIGVzdHJlbGxhIChlbiBtYXNhcyBzb2xhcmVzKSIsDQogICAgInN0X21ldDogTWVkaWNpw7NuIGRlbCBjb250ZW5pZG8gZGUgbWV0YWxlcyBlbiBsYSBmb3Rvc2ZlcmEgZGUgbGEgZXN0cmVsbGEgZW4gY29tcGFyYWNpw7NuIGNvbiBlbCBjb250ZW5pZG8gZGUgaGlkcsOzZ2VubyIsDQogICAgInN0X21ldHJhdGlvOiBSZWxhY2nDs24gZGUgbWV0YWxpY2lkYWQgZGUgbGEgZXN0cmVsbGEiLA0KICAgICJzdF9yYWQ6IFJhZGlvIGRlIGxhIGVzdHJlbGxhIChlbiByYWRpb3Mgc29sYXJlcykiLA0KICAgICJzdF9yYWR2OiBWZWxvY2lkYWQgcmFkaWFsIGRlIGxhIGVzdHJlbGxhIChlbiBrbS9zKSIsDQogICAgInN0X3JvdHA6IFBlcmlvZG8gZGUgcm90YWNpw7NuIGRlIGxhIGVzdHJlbGxhIChlbiBkw61hcykiLA0KICAgICJzdF9zcGVjdHlwZTogVGlwbyBlc3BlY3RyYWwgZGUgbGEgZXN0cmVsbGEgc2Vnw7puIGVsIHNpc3RlbWEgTW9yZ2FuLUtlZW5hbiIsDQogICAgInN0X3RlZmY6IFRlbXBlcmF0dXJhIGVmZWN0aXZhIGRlIGxhIGVzdHJlbGxhIChlbiBncmFkb3MgSykiLA0KICAgICJzdF92c2luOiBWZWxvY2lkYWQgZGUgcm90YWNpw7NuIGRlIGxhIGVzdHJlbGxhIChlbiBrbS9zKSIsDQogICAgInN5X2Rpc3Q6IERpc3RhbmNpYSBkZWwgc2lzdGVtYSAoZW4gcGFyc2VjcykiLA0KICAgICJzeV9wbHg6IFBhcmFsYWplIGRlbCBzaXN0ZW1hIChlbiBtaWxpYXJjb3NlZ3VuZG9zKSIsDQogICAgInN5X3BtOiBNb3ZpbWllbnRvIHByb3BpbyBkZWwgc2lzdGVtYSAoZW4gbWlsaWFyY29zZWd1bmRvcy9hw7FvKSIsDQogICAgInN5X3BtZGVjOiBNb3ZpbWllbnRvIHByb3BpbyBkZWwgc2lzdGVtYSBlbiBkZWNsaW5hY2nDs24gKGVuIG1pbGlhcmNvc2VndW5kb3MvYcOxbykiLA0KICAgICJzeV9wbXJhOiBNb3ZpbWllbnRvIHByb3BpbyBkZWwgc2lzdGVtYSBlbiBhc2NlbnNpw7NuIHJlY3RhIChlbiBtaWxpYXJjb3NlZ3VuZG9zL2HDsW8pIiwNCiAgICAic3lfcG51bTogTsO6bWVybyBkZSBwbGFuZXRhcyBlbiBlbCBzaXN0ZW1hIiwNCiAgICAic3lfc251bTogTsO6bWVybyBkZSBlc3RyZWxsYXMgZW4gZWwgc2lzdGVtYSIsDQogICAgInR0dl9mbGFnOiBGbGFnIGRlIHRyw6Fuc2l0byBkZSB0aWVtcG8gdmFyaWFudGUiLA0KICAgICJwbF9uYW1lOiBOb21icmUgZGVsIHBsYW5ldGEiKSkNCg0KIyBFbGltaW5hciBkZSBsYSBjb2x1bW5hIERlc2NyaXB0aW9uIGVsIHByZWZpam8gZGUgbGEgdmFyaWFibGUNCmNvbHVtbl9uYW1lcyREZXNjcmlwdGlvbiA8LSBnc3ViKCJeLio6ICIsICIiLCBjb2x1bW5fbmFtZXMkRGVzY3JpcHRpb24pDQoNCiMgRWxpbWluYSBsYSBjb2x1bW5hIGNvbiBlbCBudW1lcm8gZGUgZmlsYQ0Kcm93bmFtZXMoY29sdW1uX25hbWVzKSA8LSBOVUxMDQoNCmthYmxlKGNvbHVtbl9uYW1lcywgY29sLm5hbWVzID0gYygiVmFyaWFibGUiLCAiRGVzY3JpcGNpw7NuIiksIGFsaWduID0gImwiKQ0KDQpgYGANCg0KYGBge3Igc2F2ZV9maWx0ZXJlZF9kYXRhc2V0fQ0KIyBHdWFyZGFyIGxvcyBkYXRvcyBmaWx0cmFkb3MgZW4gdW4gYXJjaGl2byBDU1YNCndyaXRlX2NzdihrZXBsZXJfZGF0YSwgImtlcGxlcmZpbHRlcmVkLmNzdiIpDQoNCiMgR3VhcmRhciBsYSBlc3RydWN0dXJhIGRlIGxhcyBjb2x1bW5hcyBlbiB1biBhcmNoaXZvIENTVg0Kd3JpdGVfY3N2KGNvbHVtbl9uYW1lcywgImtlcGxlcmRhdGFkaWN0aW9uYXJ5LmNzdiIpDQpgYGANCg0KIyMgQW7DoWxpc2lzIGV4cGxvcmF0b3JpbyBkZSBkYXRvcw0KDQpQYXJhIHJlYWxpemFyIHVuIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8gZGUgbG9zIGRhdG9zLCBzZSBjYXJnYW4gZWwgbnVldm8gZGF0YXNldCAocHVlZGUgY29tZW56YXJzZSBlbCBhbsOhbGlzaXMgZW4gZXN0ZSBwdW50byBwb3JxdWUgZWwgZGF0YXNldCBwcmVwcm9jZXNhZG8gZXN0w6EgYWxtYWNlbmFkbyBlbiBlbCBhcmNoaXZvICoqYGtlcGxlcmZpbHRlcmVkLmNzdmAqKikgeSBzZSByZWFsaXphbiBhbGd1bmFzIHZpc3VhbGl6YWNpb25lcyB5IGPDoWxjdWxvcyBkZXNjcmlwdGl2b3MuDQoNCmBgYHtyIGVkYV9maWx0ZXJlZF9kYXRhLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoc2tpbXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIExlZXIgbG9zIGRhdG9zIGNvbXBsZXRvcw0Ka2VwbGVyX2RhdGEgPC0gcmVhZF9jc3YoImtlcGxlcmZpbHRlcmVkLmNzdiIpDQoNCiMgUmVzdW1lbiBkZSBsb3MgZGF0b3MgY29uIHNraW1yIHNvbG8gdmFyaWFibGVzIG51bcOpcmljYXMNCmtlcGxlcl9kYXRhX251bSA8LSBrZXBsZXJfZGF0YSAlPiUNCiAgc2VsZWN0X2lmKGlzLm51bWVyaWMpDQoNCiMgR2VuZXJhciByZXN1bWVuIGNvbiBza2ltciANCnJlc3VtZW4gPC0gc2tpbShrZXBsZXJfZGF0YV9udW0pIA0KDQojIE9yZGVuYXIgcG9yIG5vbWJyZSBkZSB2YXJpYWJsZQ0KcmVzdW1lbiA8LSByZXN1bWVuW29yZGVyKHJlc3VtZW4kc2tpbV92YXJpYWJsZSksIF0NCg0KIyBGaWx0cmFyIGNvbHVtbmFzIHJlbGV2YW50ZXMNCnJlc3VtZW4gPC0gc3Vic2V0KHJlc3VtZW4sIHNlbGVjdCA9IGMoDQogICAgc2tpbV92YXJpYWJsZSwgbnVtZXJpYy5tZWFuLCBudW1lcmljLnNkLCBudW1lcmljLnAwLCBudW1lcmljLnAyNSwgDQogICAgbnVtZXJpYy5wNTAsIG51bWVyaWMucDc1LCBudW1lcmljLnAxMDAsIG51bWVyaWMuaGlzdCkpDQoNCiMgTW9zdHJhciB0YWJsYSBmb3JtYXRlYWRhDQprYWJsZShyZXN1bWVuLCBmb3JtYXQgPSAibWFya2Rvd24iLCBkaWdpdHMgPSA0LA0KICAgICAgY29sLm5hbWVzID0gYygiVmFyaWFibGUiLCAiTWVkaWEiLCAiRGVzLkVzdC4iLCAiTcOtbi4iLCAiUDI1IiwgIk1lZGlhbmEiLCAiUDc1IiwgIk3DoXguIiwiSGlzdC4iKQ0KICAgICAgKQ0KDQpgYGANCg0KIyMgQW7DoWxpc2lzIGxvcyBwYXLDoW1ldHJvcyBudW3DqXJpY29zIGRlbCBkYXRhc2V0DQoNCkVuIGVzdGUgYW7DoWxpc2lzIHByZWxpbWluYXIgc2Ugb2JzZXJ2YW4gdmFyaWFzIGNhcmFjdGVyw61zdGljYXMgZW4gbG9zIHBhcsOhbWV0cm9zIGRlbCBjb25qdW50byBkZSBkYXRvcy4NCg0KTGFzIHZhcmlhYmxlcyAqKmBjYl9mbGFnYCoqIHkgKipgdHR2X2ZsYWdgKiogc29uIGJpbmFyaWFzIHkgcHJlc2VudGFuIHZhbG9yZXMgbWF5b3JpdGFyaWFtZW50ZSBlbiAqKjAqKiwgeWEgcXVlIHN1IG1lZGlhIGVzIGJhamEgKFx+MC4wMDI0IHkgXH4wLjE0OTYsIHJlc3BlY3RpdmFtZW50ZSkuIEVzdG8gaW5kaWNhIHVuIGZ1ZXJ0ZSAqKmRlc2JhbGFuY2UgZW4gbG9zIGRhdG9zKiouIEFkZW3DoXMsIGxhIHZhcmlhYmxlICoqYHN5X3NudW1gKiogY2FzaSBzaWVtcHJlIHRvbWEgZWwgdmFsb3IgZGUgKioxKiosIGxvIHF1ZSBzdWdpZXJlIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3Mgc2lzdGVtYXMgdGllbmVuIHVuYSBzb2xhIGVzdHJlbGxhLg0KDQpFbiBjdWFudG8gYSBsb3MgcGFyw6FtZXRyb3MgZGUgY29vcmRlbmFkYXMgY2VsZXN0ZXMsIGxhcyB2YXJpYWJsZXMgKipgZGVjYCoqIHkgKipgcmFgKiogKGRlY2xpbmFjacOzbiB5IGFzY2Vuc2nDs24gcmVjdGEpLCBhc8OtIGNvbW8gKipgZWxhdCwgZWxvbiwgZ2xhdGAqKiB5ICoqYGdsb25gKiogKGxhdGl0dWRlcyB5IGxvbmdpdHVkZXMgZWNsw61wdGljYXMgeSBnYWzDoWN0aWNhcyksIG11ZXN0cmFuIGRpc3RyaWJ1Y2lvbmVzIHJlbGF0aXZhbWVudGUgY2VudHJhZGFzLiAqKmBlbG9uYCoqIHRpZW5lIHVuIHJhbmdvIGFtcGxpbyAoMjg4LTMyMyksIG1pZW50cmFzIHF1ZSAqKmBnbGF0YCoqIHkgKipgZ2xvbmAqKiBwcmVzZW50YW4gdmFsb3JlcyBiaWVuIGNvbmNlbnRyYWRvcyBlbiB0b3JubyBhIGxhIG1lZGlhLCBsbyBxdWUgc3VnaWVyZSBsYSBvYnNlcnZhY2nDs24gZGUgdW4gY8O6bXVsbyBlc3RlbGFyLiBMYSBsb25naXR1ZCBlY2zDrXB0aWNhICoqYGVsb25gKiogKDI4OMKwIGEgMzI0wrApIGNvcnJlc3BvbmRlIGEgbGEgcmVnacOzbiBkZSBsYXMgY29uc3RlbGFjaW9uZXMgZGUgKipDYXByaWNvcm5pbyB5IEFjdWFyaW8qKiwgZXh0ZW5kacOpbmRvc2UgaGFjaWEgKipQaXNjaXMqKiwgbWllbnRyYXMgcXVlIGxhIGxhdGl0dWQgZWNsw61wdGljYSAqKmBlbGF0YCoqICg1N8KwIGEgNzLCsCkgZXMgYWx0YSwgaW5kaWNhbmRvIHF1ZSBlc3RvcyBvYmpldG9zIGVzdMOhbiBsZWpvcyBkZWwgcGxhbm8gZGUgbGEgZWNsw61wdGljYSB5IHViaWNhZG9zIGVuIGVsICoqaGVtaXNmZXJpbyBub3J0ZSBlY2zDrXB0aWNvKiouDQoNCkRhZG8gcXVlICoqYGVsYXRgKiogcHJlc2VudGEgdmFsb3JlcyBlbGV2YWRvcyAobXV5IHBvciBlbmNpbWEgZGVsIHBsYW5vIGRlIGxhIGVjbMOtcHRpY2EpLCBlc3RvIGluZGljYSBxdWUgbG9zIG9iamV0b3MgZW4gZWwgY29uanVudG8gZGUgZGF0b3MgKipubyBlc3TDoW4gYWxpbmVhZG9zIGNvbiBlbCBkaXNjbyBwcmluY2lwYWwgZGVsIFNpc3RlbWEgU29sYXIqKiwgc2lubyBxdWUgc2UgZW5jdWVudHJhbiBlbiB1bmEgcmVnacOzbiBtw6FzIGluY2xpbmFkYSBkZWwgY2llbG8uIEVzdGEgw6FyZWEgY29ycmVzcG9uZGUgZW4gcGFydGUgYSBsYSByZWdpw7NuIGRlbCAqKlBvbG8gTm9ydGUgRWNsw61wdGljbyoqLCBlbiBsYSBkaXJlY2Npw7NuIGRlIGxhIGNvbnN0ZWxhY2nDs24gZGVsICoqRHJhZ8OzbiAoRHJhY28pKiouDQoNCkxhcyB2YXJpYWJsZXMgKipgcGxfYm1hc3NlYCoqIHkgKipgcGxfbWFzc2VgKiogKG1hc2EgZW4gdW5pZGFkZXMgdGVycmVzdHJlcyksIGFzw60gY29tbyAqKmBwbF9ibWFzc2pgKiogeSAqKmBwbF9tYXNzamAqKiAobWFzYSBlbiB1bmlkYWRlcyBqb3ZpYW5hcyksIG11ZXN0cmFuIGRpc3RyaWJ1Y2lvbmVzICoqc2VzZ2FkYXMgYSBsYSBkZXJlY2hhKiosIGNvbiB2YWxvcmVzIG3DoXhpbW9zIGV4dHJlbWFkYW1lbnRlIGdyYW5kZXMgKGhhc3RhICoqMjUsNDI2IG1hc2FzIHRlcnJlc3RyZXMqKikuIEhheSB1bmEgZ3JhbiBjYW50aWRhZCBkZSB2YWxvcmVzIHBlcXVlw7FvcyB5IGFsZ3Vub3MgdmFsb3JlcyBhdMOtcGljb3MgbXV5IGFsdG9zLiBEZSBtYW5lcmEgc2ltaWxhciwgYHBsX3JhZGVgIChyYWRpbyBlbiByYWRpb3MgdGVycmVzdHJlcykgeSAqKmBwbF9yYWRqYCoqIChyYWRpbyBlbiByYWRpb3Mgam92aWFub3MpIHByZXNlbnRhbiB1bmEgKipkaXN0cmlidWNpw7NuIHNlc2dhZGEqKiwgY29uIHBvY29zIHZhbG9yZXMgZ3JhbmRlcy4gTGEgbWVkaWFuYSBkZSAqKmBwbF9yYWRlYCoqIGVzICoqMi4zNyoqLCBsbyBxdWUgaW5kaWNhIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgZXhvcGxhbmV0YXMgZW4gZWwgY29uanVudG8gdGllbmVuICoqbcOhcyBkZWwgZG9ibGUgZGVsIHRhbWHDsW8gZGUgbGEgVGllcnJhKiouDQoNCkVuIGN1YW50byBhIGxhIGV4Y2VudHJpY2lkYWQgb3JiaXRhbCwgKipgcGxfb3JiZWNjZW5gKiogZXMgbWF5b3JpdGFyaWFtZW50ZSBjZXJjYW5hIGEgKiowKiosIGxvIHF1ZSBzdWdpZXJlIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgZXhvcGxhbmV0YXMgdGllbmVuICoqw7NyYml0YXMgY2FzaSBjaXJjdWxhcmVzKiouIExhIGluY2xpbmFjacOzbiBvcmJpdGFsLCByZXByZXNlbnRhZGEgcG9yICoqYHBsX29yYmluY2xgKiosIG11ZXN0cmEgdW5hIGFsdGEgY29uY2VudHJhY2nDs24gZW4gdmFsb3JlcyBjZXJjYW5vcyBhICoqOTDCsCoqLCBsbyBxdWUgaW5kaWNhIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgcGxhbmV0YXMgdGllbmVuICoqw7NyYml0YXMgY2FzaSBwZXJwZW5kaWN1bGFyZXMgYSBsYSBsw61uZWEgZGUgdmlzacOzbioqLiBFc3RvIGVzIGNvbnNpc3RlbnRlIGNvbiBlbCBtw6l0b2RvIGRlIGRldGVjY2nDs24gcHJlZG9taW5hbnRlLCBlbCAqKm3DqXRvZG8gZGUgdHLDoW5zaXRvKiosIHF1ZSBlcyBtw6FzIGVmZWN0aXZvIHBhcmEgcGxhbmV0YXMgcXVlIHBhc2FuIGZyZW50ZSBhIHN1IGVzdHJlbGxhLg0KDQpFbCAqKnBlcsOtb2RvIG9yYml0YWwqKiAoKipgcGxfb3JicGVyYCoqKSBwcmVzZW50YSB1bmEgbWVkaWFuYSBkZSAqKlx+MTMgZMOtYXMqKiwgYXVucXVlIGV4aXN0ZW4gdmFsb3JlcyBleHRyZW1vcyBkZSBoYXN0YSAqKjEsMzIyIGTDrWFzKiosIGxvIHF1ZSBpbmRpY2EgdW5hIGdyYW4gdmFyaWFiaWxpZGFkIGVuIGxhIGR1cmFjacOzbiBkZSBsYXMgw7NyYml0YXMuIFBvciBvdHJvIGxhZG8sIGxhICoqdGVtcGVyYXR1cmEgcGxhbmV0YXJpYSBkZSBlcXVpbGlicmlvKiogKCoqYHBsX2VxdGAqKikgdGllbmUgdW5hIG1lZGlhIGRlICoqOTM4IEsqKiwgY29uIHVuYSBkaXN0cmlidWNpw7NuIGFtcGxpYSAobcOtbmltbzogKioyNTEgSyoqLCBtw6F4aW1vOiAqKjIsMTg4IEsqKiksIGxvIHF1ZSBzdWdpZXJlIHVuYSBtZXpjbGEgZGUgKipwbGFuZXRhcyBmcsOtb3MgeSBleHRyZW1hZGFtZW50ZSBjYWxpZW50ZXMqKi4NCg0KUmVzcGVjdG8gYSBsYSAqKmRlbnNpZGFkIHBsYW5ldGFyaWEqKiAoKipgcGxfZGVuc2AqKiksIGxhIG1lZGlhbmEgZXMgKioyLjEzIGcvY23CsyoqLCBjb24gdW5hIGdyYW4gdmFyaWFiaWxpZGFkLCBsbyBxdWUgcmVmbGVqYSB1bmEgZGl2ZXJzaWRhZCBlbiBsYSAqKmNvbXBvc2ljacOzbiBkZSBsb3MgZXhvcGxhbmV0YXMqKi4NCg0KRW4gY3VhbnRvIGEgbGFzIGNhcmFjdGVyw61zdGljYXMgZXN0ZWxhcmVzLCBsYXMgdmFyaWFibGVzICoqYHN0X21hc3NgKiogeSAqKmBzdF9yYWRgKiogbXVlc3RyYW4gcXVlIGxhIG1heW9yw61hIGRlIGxhcyBlc3RyZWxsYXMgZW4gZWwgY29uanVudG8gdGllbmVuICoqbWFzYXMgeSByYWRpb3Mgc2ltaWxhcmVzIGFsIFNvbCAoXH4xLjApKiosIGxvIHF1ZSBlcyBjb2hlcmVudGUgY29uIGVsIGZpbHRybyBhcGxpY2FkbyBlbiBlbCBwcmVwcm9jZXNhbWllbnRvLiBMYSAqKnRlbXBlcmF0dXJhIGVzdGVsYXIgZWZlY3RpdmEqKiAoKipgc3RfdGVmZmAqKikgdGllbmUgdW5hIG1lZGlhIGRlICoqNSw2ODUgSyoqLCBsbyBxdWUgZXMgY29uc2lzdGVudGUgY29uICoqZXN0cmVsbGFzIHRpcG8gRyAoc2ltaWxhcmVzIGFsIFNvbCkqKi4gU2kgYmllbiBlc3RvIHB1ZWRlIGRlYmVyc2UgYWwgZmlsdHJvIGFwbGljYWRvLCB0YW1iacOpbiBlc3TDoSByZWxhY2lvbmFkbyBjb24gbGEgY29tcG9zaWNpw7NuIHkgZWRhZCBkZSBsYXMgZXN0cmVsbGFzLg0KDQpMYSB2YXJpYWJsZSAqKmBzdF9sb2dnYCoqIChsb2dhcml0bW8gZW4gYmFzZSAxMCBkZSBsYSBncmF2ZWRhZCBlc3RlbGFyIHN1cGVyZmljaWFsKSBzZSBjb25jZW50cmEgZW4gdmFsb3JlcyBjZXJjYW5vcyBhICoqNC40NSoqLCBsbyBxdWUgZXMgY2FyYWN0ZXLDrXN0aWNvIGRlICoqZXN0cmVsbGFzIGVuIGxhIHNlY3VlbmNpYSBwcmluY2lwYWwqKiBkZW50cm8gZGVsIGNpY2xvIGRlIHZpZGEgZXN0ZWxhci4gUG9yIHN1IHBhcnRlLCBsYSAqKmx1bWlub3NpZGFkIGVzdGVsYXIqKiAoKipgc3RfbHVtYCoqKSB0aWVuZSB1bmEgZGlzdHJpYnVjacOzbiBjZW50cmFkYSBhbHJlZGVkb3IgZGUgKiowKiogZW4gZXNjYWxhIGxvZ2Fyw610bWljYSwgbG8gcXVlIGluZGljYSBxdWUgbXVjaGFzIGRlIGVzdGFzIGVzdHJlbGxhcyB0aWVuZW4gKipsdW1pbm9zaWRhZGVzIHNpbWlsYXJlcyBhIGxhIGRlbCBTb2wqKi4NCg0KRWwgcGFyw6FtZXRybyAqKmBzeV9kaXN0YCoqIChkaXN0YW5jaWEgZW4gcGFyc2VjcyBkZWwgc2lzdGVtYSBlc3RlbGFyKSB2YXLDrWEgY29uc2lkZXJhYmxlbWVudGUsIGNvbiB2YWxvcmVzIGVudHJlICoqNjggcGMgeSAyLDg3OSBwYyoqLiBMYSBtZWRpYW5hIGVzICoqXH44NjAgcGMqKiwgbG8gcXVlIGluZGljYSBxdWUgKipsYSBtYXlvcsOtYSBkZSBlc3RvcyBzaXN0ZW1hcyBlc3TDoW4gcmVsYXRpdmFtZW50ZSBsZWpvcyAobcOhcyBkZSAyLDgwNCBhw7FvcyBsdXopKiouDQoNCkVuIGN1YW50byBhbCBtb3ZpbWllbnRvIHByb3BpbyBkZSBsYXMgZXN0cmVsbGFzLCBsYXMgdmFyaWFibGVzICoqYHN5X3BtLCBzeV9wbXJhYCoqIHkgKipgc3lfcG1kZWNgKiogKG1vdmltaWVudG8gcHJvcGlvIGRlbCBzaXN0ZW1hIGVzdGVsYXIgZW4gbWlsaXNlZ3VuZG9zIGRlIGFyY28gcG9yIGHDsW8pIGVzdMOhbiAqKmNlbnRyYWRhcyBlbiAwKiosIGF1bnF1ZSBhbGd1bmFzIGVzdHJlbGxhcyBwcmVzZW50YW4gKiptb3ZpbWllbnRvcyBtw6FzIHLDoXBpZG9zKiouDQoNCkVsICoqbsO6bWVybyBkZSBwbGFuZXRhcyBwb3Igc2lzdGVtYSoqICgqKmBzeV9wbnVtYCoqKSB0aWVuZSB1bmEgbWVkaWFuYSBkZSAqKjIqKiwgYXVucXVlIGFsZ3Vub3Mgc2lzdGVtYXMgYWxjYW56YW4gKipoYXN0YSA2IHBsYW5ldGFzIGRldGVjdGFkb3MqKi4NCg0KTGFzIHZhcmlhYmxlcyAqKmBwbF90cmFuZGVwYCoqIHkgKipgcGxfdHJhbmR1cmAqKiAocHJvZnVuZGlkYWQgeSBkdXJhY2nDs24gZGVsIHRyw6Fuc2l0bykgbXVlc3RyYW4gdW5hIGRpc3RyaWJ1Y2nDs24gKipzZXNnYWRhKiosIGNvbiBsYSBtYXlvcsOtYSBkZSBsb3MgdmFsb3JlcyBlbiBlbCBleHRyZW1vIGluZmVyaW9yLiBFc3RvIGVzIGVzcGVyYWJsZSwgeWEgcXVlIGxhIG1heW9yw61hIGRlIGxvcyAqKnRyw6Fuc2l0b3Mgc29uIHBvY28gcHJvZnVuZG9zIHkgZGUgY29ydGEgZHVyYWNpw7NuKiouDQoNClBvciBvdHJvIGxhZG8sIGxhICoqb2JsaWN1aWRhZCBkZWwgZWplIGRlIHJvdGFjacOzbiBkZWwgcGxhbmV0YSoqICgqKmBwbF9wcm9qb2JsaXFgKiopIHRpZW5lIHVuYSBtZWRpYW5hIGVuICoqMMKwKiogKGluZGljYW5kbyBxdWUgbGEgbWF5b3LDrWEgZGUgbG9zIHBsYW5ldGFzIHRpZW5lbiB1biBlamUgZGUgcm90YWNpw7NuIHBlcnBlbmRpY3VsYXIgYSBsYSBlY2zDrXB0aWNhIGRlIHN1IHNpc3RlbWEpLCBhdW5xdWUgc2Ugb2JzZXJ2YW4gdmFsb3JlcyBleHRyZW1vcyBkZSBoYXN0YSAqKi0xMzXCsCoqLg0KDQpFbiBnZW5lcmFsLCBtdWNoYXMgZGlzdHJpYnVjaW9uZXMgZW4gZWwgY29uanVudG8gZGUgZGF0b3MgZXN0w6FuICoqc2VzZ2FkYXMqKiwgY29uIHZhbG9yZXMgZXh0cmVtb3MgcXVlIHBvZHLDrWFuIHJlcHJlc2VudGFyICoqYXTDrXBpY29zIChvdXRsaWVycykgbyBzaW1wbGVtZW50ZSByZWZsZWphciBsYSBkaXZlcnNpZGFkIGRlIGxvcyBleG9wbGFuZXRhcyoqLiBMb3MgZGF0b3Mgc29icmUgKiptYXNhIHkgcmFkaW8qKiBpbmRpY2FuIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgZXhvcGxhbmV0YXMgc29uICoqcmVsYXRpdmFtZW50ZSBwZXF1ZcOxb3MqKiwgYXVucXVlIGV4aXN0ZW4gYWxndW5vcyBleHRyZW1hZGFtZW50ZSBncmFuZGVzLiBMYSAqKnRlbXBlcmF0dXJhKiogZGUgbG9zIHBsYW5ldGFzIHZhcsOtYSBhbXBsaWFtZW50ZSwgbG8gcXVlIHN1Z2llcmUgdW5hIGdyYW4gZGl2ZXJzaWRhZCBlbiBsb3MgdGlwb3MgZGUgZXhvcGxhbmV0YXMuDQoNClBvciDDumx0aW1vLCBlbiBjdWFudG8gYSBsYXMgZXN0cmVsbGFzLCBsYSBtYXlvcsOtYSBzb24gKipzaW1pbGFyZXMgYWwgU29sKiosIGF1bnF1ZSBwcmVzZW50YW4gYWxndW5hcyBkaWZlcmVuY2lhcyBlbiAqKmVkYWQgeSBtZXRhbGljaWRhZCoqLCBsbyBjdWFsIGVzIGVzcGVyYWJsZSBkZWJpZG8gYWwgKipmaWx0cm8gYXBsaWNhZG8gZW4gZWwgcHJlcHJvY2VzYW1pZW50byoqLg0KDQojIyBEZXRlbmNpw7NuIGRlIHZhbG9yZXMgZmFsdGFudGVzDQoNClNlIGFuYWxpemEgbGEgY2FudGlkYWQgZGUgdmFsb3JlcyBmYWx0YW50ZXMgZW4gZWwgZGF0YXNldCBwYXJhIGlkZW50aWZpY2FyIHBvc2libGVzIHByb2JsZW1hcyBkZSBjYWxpZGFkIGRlIGRhdG9zLg0KDQpgYGB7ciBtaXNzaW5nX3ZhbHVlc19jYWxjfQ0KDQpsaWJyYXJ5KHRpZHlyKQ0KDQojIENhbGN1bGFyIGxhIGNhbnRpZGFkIGRlIHZhbG9yZXMgZmFsdGFudGVzIHBvciBjb2x1bW5hDQptaXNzaW5nX3ZhbHVlcyA8LSBrZXBsZXJfZGF0YSAlPiUNCiAgc3VtbWFyaXNlX2FsbCh+c3VtKGlzLm5hKC4pKSkgJT4lDQogIGdhdGhlcigpICU+JQ0KICBhcnJhbmdlKGRlc2ModmFsdWUpKQ0KDQojIEVsaW1pbmFyIGxhcyBjb2x1bW5hcyBzaW4gdmFsb3JlcyBmYWx0YW50ZXMNCm1pc3NpbmdfdmFsdWVzIDwtIG1pc3NpbmdfdmFsdWVzICU+JQ0KICBmaWx0ZXIodmFsdWUgPiAwKQ0KDQojIFRvdGFsIGRlIGNvbHVtbmFzDQp0b3RhbF9yb3dzIDwtIG5yb3cobWlzc2luZ192YWx1ZXMpDQoNCiMgQ2FsY3VsYXIgZWwgcHVudG8gbWVkaW8NCm1pZHBvaW50IDwtIGNlaWxpbmcodG90YWxfcm93cyAvIDIpDQoNCmBgYA0KDQoqKlZhbG9yZXMgRmFsdGFudGVzIHBvciBDb2x1bW5hKioNCg0KYGBge3IgbWlzc2luZ192YWx1ZXNfZ3JhcGgxLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpnZ3Bsb3QobWlzc2luZ192YWx1ZXNbMTptaWRwb2ludCxdLCBhZXMoeCA9IHJlb3JkZXIoa2V5LCB2YWx1ZSksIHkgPSB2YWx1ZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIsIGNvbG9yID0gImRhcmtibHVlIiwgd2lkdGggPSAwLjUpICsgIyBSZWR1Y2lyIGFuY2hvIGRlIGxhcyBiYXJyYXMNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHZhbHVlKSwgaGp1c3QgPSAtMC4yLCBzaXplID0gMykgKyAjIEHDsWFkaXIgdmFsb3JlcyBhbCBmaW5hbCBkZSBsYXMgYmFycmFzDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wMSwgMC4xKSkpICsgIyBBw7FhZGlyIG1hcmdlbiBleHRyYSBlbiBlbCBlamUgeQ0KICBsYWJzKHRpdGxlID0gIiIsDQogICAgICAgeCA9ICJDb2x1bW5hIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgICAjIEFqdXN0YXIgdGFtYcOxbyBkZSB0ZXh0byBlbiBlamUgWQ0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpICAjIENlbnRyYXIgZWwgdMOtdHVsbw0KICApDQoNCmBgYA0KDQpgYGB7ciBtaXNzaW5nX3ZhbHVlc19ncmFwaDIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgQ3JlYXIgdW4gZ3LDoWZpY28gZGUgYmFycmFzIGNvbiBsb3MgdmFsb3JlcyBmYWx0YW50ZXMgcXVlIG5vIHNlYW4gY2Vybw0KIyBjb24gbGEgc2VndW5kYSBtaXRhZCBkZSBsYXMgZmlsYXMNCmdncGxvdChtaXNzaW5nX3ZhbHVlc1sobWlkcG9pbnQrMSk6dG90YWxfcm93cyxdLCBhZXMoeCA9IHJlb3JkZXIoa2V5LCB2YWx1ZSksIHkgPSB2YWx1ZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIsIGNvbG9yID0gImRhcmtibHVlIiwgd2lkdGggPSAwLjUpICsgIyBSZWR1Y2lyIGFuY2hvIGRlIGxhcyBiYXJyYXMNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHZhbHVlKSwgaGp1c3QgPSAtMC4yLCBzaXplID0gMykgKyAjIEHDsWFkaXIgdmFsb3JlcyBhbCBmaW5hbCBkZSBsYXMgYmFycmFzDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wMSwgMC4xKSkpICsgIyBBw7FhZGlyIG1hcmdlbiBleHRyYSBlbiBlbCBlamUgeQ0KICBsYWJzKHRpdGxlID0gIiIsDQogICAgICAgeCA9ICIiLA0KICAgICAgIHkgPSAiQ2FudGlkYWQgZGUgVmFsb3JlcyBGYWx0YW50ZXMiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksICAgIyBBanVzdGFyIHRhbWHDsW8gZGUgdGV4dG8gZW4gZWplIFkNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSAgIyBDZW50cmFyIGVsIHTDrXR1bG8NCiAgKQ0KDQpgYGANCg0KRW4gZWwgYW7DoWxpc2lzIGRlbCBkYXRhc2V0LCBzZSBkZXRlY3TDsyB1bmEgZ3JhbiBjYW50aWRhZCBkZSAqKnZhbG9yZXMgZmFsdGFudGVzKiogZW4gdmFyaWFzIGNvbHVtbmFzLCBsbyBxdWUgcHJvYmFibGVtZW50ZSBzZSBkZWJhIGEgbGEgZmFsdGEgZGUgZXN0aW1hY2lvbmVzIG8gbWVkaWNpb25lcyBwYXJhIGNpZXJ0b3MgZXhvcGxhbmV0YXMuIFNlZ8O6biBsb3MgcHJlZmlqb3MgdXRpbGl6YWRvcyBlbiBsYXMgY29sdW1uYXMgZGVsIGRhdGFzZXQsIGxhcyB2YXJpYWJsZXMgcHVlZGVuIGNsYXNpZmljYXJzZSBlbiB0cmVzIGNhdGVnb3LDrWFzIHByaW5jaXBhbGVzOiAqKnBhcsOhbWV0cm9zIGRlbCBwbGFuZXRhIChjb24gcHJlZmlqbyBwbFxfKSoqLCAqKnBhcsOhbWV0cm9zIGRlIGxhIGVzdHJlbGxhIChjb24gcHJlZmlqbyBzdFxfKSoqIHkgKipwYXLDoW1ldHJvcyBkZWwgc2lzdGVtYSAocHJlZmlqbyBzeVxfKSoqLg0KDQpDb21vIHBhcnRlIGRlbCBwcm9jZXNvLCBzZSBhbmFsaXphcsOhbiBsYXMgKip2YXJpYWJsZXMgY29ub2NpZGFzIGRlIGxvcyBleG9wbGFuZXRhcyoqIHBhcmEgaWRlbnRpZmljYXIgYXF1ZWxsYXMgcXVlIHB1ZWRhbiBhY3R1YXIgY29tbyAqKnByZWRpY3RvcmFzKiogZGUgbGFzIHZhcmlhYmxlcyBjb24gdmFsb3JlcyBmYWx0YW50ZXMuIFBvciBlamVtcGxvLCBlbiBlbCBjYXNvIGRlbCAqKnJhZGlvIGRlbCBleG9wbGFuZXRhKiogKHJlcHJlc2VudGFkbyBwb3IgKipgcGxfcmFkamAqKiBlbiByYWRpb3Mgam92aWFub3MgeSAqKmBwbF9yYWRlYCoqIGVuIHJhZGlvcyB0ZXJyZXN0cmVzKSwgcXVlIHByZXNlbnRhICoqODg2IHZhbG9yZXMgZmFsdGFudGVzKiosIGVzIHBvc2libGUgZXN0aW1hcmxvIHV0aWxpemFuZG8gb3RyYXMgdmFyaWFibGVzIGRpc3BvbmlibGVzIGVuIGVsIGRhdGFzZXQuIEFsZ3VuYXMgZGUgZXN0YXMgaW5jbHV5ZW4gZWwgKipwZXLDrW9kbyBvcmJpdGFsIGVuIGTDrWFzKiogKCoqYHBsX29yYnBlcmAqKiwgY29uICoqNDUwIHZhbG9yZXMgZmFsdGFudGVzKiopLCBlbCAqKnRpZW1wbyBkZSBjb25qdW5jacOzbioqICgqKmBwbF90cmFubWlkYCoqLCBjb24gKio2NzUgdmFsb3JlcyBmYWx0YW50ZXMqKikgeSBlbCAqKmxvZ2FyaXRtbyBlbiBiYXNlIDEwIGRlIGxhIGdyYXZlZGFkIHN1cGVyZmljaWFsIGRlIGxhIGVzdHJlbGxhIGRlbCBzaXN0ZW1hIHBsYW5ldGFyaW8qKiAoKipgc3RfbG9nZ2AqKiwgY29uICoqNTU0IHZhbG9yZXMgZmFsdGFudGVzKiopLg0KDQpQYXJhIGRldGVybWluYXIgY3XDoWxlcyBkZSBlc3RhcyB2YXJpYWJsZXMgdGllbmVuIHVuIG1heW9yIHBvdGVuY2lhbCBjb21vICoqcHJlZGljdG9yYXMqKiwgc2UgdXRpbGl6YXLDoSBsYSAqKm1hdHJpeiBkZSBjb3JyZWxhY2nDs24qKiwgcXVlIHBlcm1pdGlyw6EgaWRlbnRpZmljYXIgbGFzIHJlbGFjaW9uZXMgbcOhcyBzaWduaWZpY2F0aXZhcyBlbnRyZSBsYXMgdmFyaWFibGVzIG51bcOpcmljYXMgZGVsIGRhdGFzZXQuIERlIGVzdGEgbWFuZXJhLCBzZSBzZWxlY2Npb25hcsOhbiBhcXVlbGxhcyBxdWUgcHJlc2VudGVuIHVuYSAqKmNvcnJlbGFjacOzbiBwb3NpdGl2YSBvIG5lZ2F0aXZhIG3DoXMgZnVlcnRlKiogY29uIGxhIHZhcmlhYmxlIGZhbHRhbnRlLCBsbyBxdWUgZmFjaWxpdGFyw6Egc3UgZXN0aW1hY2nDs24gY29uIHVuIG1heW9yIGdyYWRvIGRlIHByZWNpc2nDs24uDQoNCiMjIEJ1c2NhbmRvIGNvcnJlbGFjaW9uZXMNCg0KUGFyYSBlbGVnaXIgbGEgbWVqb3IgdmFyaWFibGUgcGFyYSByZWFsaXphciB1bmEgcmVncmVzacOzbiBsaW5lYWwgc2UgdXRpbGl6YSBsYSBjb3JyZWxhY2nDs24gbGluZWFsIHNpbXBsZSAoUGVhcnNvbikgcGFyYSBtZWRpciBsYSByZWxhY2nDs24gbGluZWFsIGVudHJlIGNhZGEgdmFyaWFibGUgaW5kZXBlbmRpZW50ZSB5IGxhIGRlcGVuZGllbnRlLiBTZSB1dGlsaXphciBwb3JxdWUgZXMgcG9zaWJsZSBxdWUgZW50cmUgbG9zIHBhcsOhbWV0cm9zIHBsYW5ldGFyaW9zIGhheWEgdW5hIHJlbGFjacOzbiBsaW5lYWwgc2ltcGxlLiBMYSBsaW1pdGFjacOzbiBjb24gZXN0YSBtZXRvZG9sb2fDrWEgZXMgcXVlIGlnbm9yYSBsYSBtdWx0aWNvbGluZWFsaWRhZCB5IG5vIGNvbnNpZGVyYSByZWxhY2lvbmVzIG5vIGxpbmVhbGVzLg0KU2UgYW5hbGl6YSBsYSBjb3JyZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBudW3DqXJpY2FzIGRlbCBkYXRhc2V0IHBhcmEgaWRlbnRpZmljYXIgcG9zaWJsZXMgcmVsYWNpb25lcyBlbnRyZSBlbGxhcyB1dGlsaXphbmRvIGxvcyBtw6l0b2RvcyBkZSBQZWFyc29uIChkZXRlY2Npw7NuIGRlIGNvcnJlbGFjaW9uZXMgbGluZWFsZXMpLiBBIHRyYXbDqXMgZGUgZXN0YSBtYXRyaXosIHNlIHB1ZWRlbiBkZXRlY3RhciB0YW50byBjb3JyZWxhY2lvbmVzIHBvc2l0aXZhcyAoY3VhbmRvIHVuIGF1bWVudG8gZW4gdW5hIHZhcmlhYmxlIGVzdMOhIGFzb2NpYWRvIGNvbiB1biBhdW1lbnRvIGVuIG90cmEpIGNvbW8gY29ycmVsYWNpb25lcyBuZWdhdGl2YXMgKGN1YW5kbyB1biBhdW1lbnRvIGVuIHVuYSB2YXJpYWJsZSBlc3TDoSByZWxhY2lvbmFkbyBjb24gdW5hIGRpc21pbnVjacOzbiBlbiBvdHJhKS4gRXN0YXMgcmVsYWNpb25lcyBwdWVkZW4gc2VyIMO6dGlsZXMgcGFyYSBlbnRlbmRlciBwYXRyb25lcyBlbiBsb3MgZGF0b3MgeSBzZWxlY2Npb25hciBsYXMgbWVqb3JlcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgcGFyYSBtb2RlbG9zIGRlIGVzdGltYWNpw7NuLg0KDQoNCmBgYHtyIGNvcnJlbGF0aW9uX21hdHJpeF9wZWFyc29ufQ0KDQpsaWJyYXJ5KGNvcnJwbG90KQ0KDQojIENhbGN1bGFyIGxhIG1hdHJpeiBkZSBjb3JyZWxhY2nDs24NCmNvcnJlbGF0aW9uX21hdHJpeF9wZWFyc29uIDwtIGNvcihrZXBsZXJfZGF0YV9udW0sIHVzZT0icGFpcndpc2UuY29tcGxldGUub2JzIiAsIG1ldGhvZCA9ICJwZWFyc29uIikNCg0KIyBPcmRlbmFyIGxhIG1hdHJpeiBwb3Igbm9tYnJlIGRlIGNvbHVtbmFzDQpjb3JyZWxhdGlvbl9tYXRyaXhfcGVhcnNvbiA8LSBjb3JyZWxhdGlvbl9tYXRyaXhfcGVhcnNvbltvcmRlcihyb3duYW1lcyhjb3JyZWxhdGlvbl9tYXRyaXhfcGVhcnNvbikpLCBvcmRlcihjb2xuYW1lcyhjb3JyZWxhdGlvbl9tYXRyaXhfcGVhcnNvbikpXQ0KDQojIE7Dum1lcm8gZGUgdmFyaWFibGVzDQpuX3ZhcnMgPC0gbmNvbChjb3JyZWxhdGlvbl9tYXRyaXhfcGVhcnNvbikNCmhhbGYgPC0gY2VpbGluZyhuX3ZhcnMgLyAyKQ0KDQpgYGANCg0KKipNYXRyaXogZGUgQ29ycmVsYWNpw7NuIDEvMyAoUGVhcnNvbiBDdWFkcmFudGUgU3VwZXJpb3IpKioNCg0KYGBge3IgcGxvdF9jb3JyZWxhdGlvbl9wZWFyc29uX3VwcGVyX3F1YWRyYW50LCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02LCBkcGk9MTUwfQ0KDQojIFBhcnRlIDE6IFByaW1lcmEgbWl0YWQgKGRpYWdvbmFsIHN1cGVyaW9yKQ0KY29ycmVsYXRpb25fbWF0cml4X3BlYXJzb25fc3VwIDwtIGNvcnJlbGF0aW9uX21hdHJpeF9wZWFyc29uWzE6aGFsZiwgMTpoYWxmXQ0KY29ycnBsb3QoDQogIGNvcnJlbGF0aW9uX21hdHJpeF9wZWFyc29uX3N1cCwNCiAgbWV0aG9kID0gImNvbG9yIiwNCiAgdHlwZSA9ICJ1cHBlciIsDQogIGFkZENvZWYuY29sID0gImJsYWNrIiwNCiAgbnVtYmVyLmNleCA9IDAuNCwNCiAgdGwuY2V4ID0gMC41LA0KICB0bC5jb2wgPSAiYmxhY2siLA0KICBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGMoImluZGlhbnJlZCIsICJ3aGl0ZSIsICJzdGVlbGJsdWUiKSkoMjApLA0KICB0aXRsZSA9ICIiDQopDQoNCmBgYA0KDQoqKk1hdHJpeiBkZSBDb3JyZWxhY2nDs24gMi8zIChQZWFyc29uIENydWNlKSoqDQoNCmBgYHtyIHBsb3RfY29ycmVsYXRpb25fcGVhcnNvbl9jcm9zcywgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NiwgZHBpPTE1MH0NCg0KIyBQYXJ0ZSAyOiBDcnVjZSBlbnRyZSBsYSBwcmltZXJhIHkgc2VndW5kYSBtaXRhZA0KY29ycmVsYXRpb25fbWF0cml4X3BlYXJzb25fY3Jvc3MgPC0gY29ycmVsYXRpb25fbWF0cml4X3BlYXJzb25bMTpoYWxmLCAoaGFsZiArIDEpOm5fdmFyc10NCmNvcnJwbG90KA0KICBjb3JyZWxhdGlvbl9tYXRyaXhfcGVhcnNvbl9jcm9zcywNCiAgbWV0aG9kID0gImNvbG9yIiwNCiAgdHlwZSA9ICJmdWxsIiwgICMgTW9zdHJhciB0b2RhcyBsYXMgY29ycmVsYWNpb25lcyBlbiBlc3RhIHNlY2Npw7NuDQogIGFkZENvZWYuY29sID0gImJsYWNrIiwNCiAgbnVtYmVyLmNleCA9IDAuNCwNCiAgdGwuY2V4ID0gMC41LA0KICB0bC5jb2wgPSAiYmxhY2siLA0KICBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGMoImluZGlhbnJlZCIsICJ3aGl0ZSIsICJzdGVlbGJsdWUiKSkoMjApLA0KICB0aXRsZSA9ICIiDQopDQoNCmBgYA0KDQoqKk1hdHJpeiBkZSBDb3JyZWxhY2nDs24gMy8zIChQZWFyc29uIEN1YWRyYW50ZSBJbmZlcmlvcikqKg0KDQpgYGB7ciBwbG90X2NvcnJlbGF0aW9uX3BlYXJzb25fbG93ZXJfcXVhZHJhbnQsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTYsIGRwaT0xNTB9DQoNCiMgUGFydGUgMzogU2VndW5kYSBtaXRhZCAoZGlhZ29uYWwgaW5mZXJpb3IpDQpjb3JyZWxhdGlvbl9tYXRyaXhfcGVhcnNvbl9pbmYgPC0gY29ycmVsYXRpb25fbWF0cml4X3BlYXJzb25bKGhhbGYgKyAxKTpuX3ZhcnMsIChoYWxmICsgMSk6bl92YXJzXQ0KY29ycnBsb3QoDQogIGNvcnJlbGF0aW9uX21hdHJpeF9wZWFyc29uX2luZiwNCiAgbWV0aG9kID0gImNvbG9yIiwNCiAgdHlwZSA9ICJ1cHBlciIsDQogIGFkZENvZWYuY29sID0gImJsYWNrIiwNCiAgbnVtYmVyLmNleCA9IDAuNCwNCiAgdGwuY2V4ID0gMC41LA0KICB0bC5jb2wgPSAiYmxhY2siLA0KICBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGMoImluZGlhbnJlZCIsICJ3aGl0ZSIsICJzdGVlbGJsdWUiKSkoMjApLA0KICB0aXRsZSA9ICIiDQopDQoNCmBgYA0KDQpMYSAqKm1hdHJpeiBkZSBjb3JyZWxhY2nDs24qKiBlcyB1bmEgaGVycmFtaWVudGEgZnVuZGFtZW50YWwgZW4gZWwgYW7DoWxpc2lzIGRlIGRhdG9zLCB5YSBxdWUgcGVybWl0ZSBpZGVudGlmaWNhciByZWxhY2lvbmVzICoqbGluZWFsZXMqKiBlbnRyZSBsYXMgdmFyaWFibGVzIG51bcOpcmljYXMgZGVsIGRhdGFzZXQuIEEgdHJhdsOpcyBkZSBlc3RhIG1hdHJpeiwgc2UgcHVlZGVuIGRldGVjdGFyIHRhbnRvICoqY29ycmVsYWNpb25lcyBwb3NpdGl2YXMqKiAoY3VhbmRvIHVuIGF1bWVudG8gZW4gdW5hIHZhcmlhYmxlIGVzdMOhIGFzb2NpYWRvIGNvbiB1biBhdW1lbnRvIGVuIG90cmEpIGNvbW8gKipjb3JyZWxhY2lvbmVzIG5lZ2F0aXZhcyoqIChjdWFuZG8gdW4gYXVtZW50byBlbiB1bmEgdmFyaWFibGUgZXN0w6EgcmVsYWNpb25hZG8gY29uIHVuYSBkaXNtaW51Y2nDs24gZW4gb3RyYSkuIEVzdGFzIHJlbGFjaW9uZXMgcHVlZGVuIHNlciDDunRpbGVzIHBhcmEgZW50ZW5kZXIgcGF0cm9uZXMgZW4gbG9zIGRhdG9zIHkgc2VsZWNjaW9uYXIgbGFzIG1lam9yZXMgdmFyaWFibGVzIHByZWRpY3RvcmFzIHBhcmEgbW9kZWxvcyBkZSBlc3RpbWFjacOzbi4NCg0KVW4gZWplbXBsbyBkZSBlc3RhcyBjb3JyZWxhY2lvbmVzIHNlIG9ic2VydmEgZW4gbGEgcmVsYWNpw7NuIGVudHJlIGVsICoqY29jaWVudGUgZGVsIHNlbWllamUgb3JiaXRhbCBtYXlvciB5IGVsIHBlcsOtb2RvIG9yYml0YWwqKiAoKipgcGxfcmF0ZG9yYCoqKSwgZWwgY3VhbCBtdWVzdHJhIHVuYSAqKmNvcnJlbGFjacOzbiBwb3NpdGl2YSoqIGNvbiBlbCAqKnBlcsOtb2RvIG9yYml0YWwqKiAoKipgcGxfb3JicGVyYCoqKS4gRXN0byBzdWdpZXJlIHF1ZSBhIG1lZGlkYSBxdWUgZWwgcGVyw61vZG8gb3JiaXRhbCBhdW1lbnRhLCB0YW1iacOpbiBsbyBoYWNlIGVzdGUgY29jaWVudGUuIEVuIGNvbnRyYXN0ZSwgKipgcGxfcmF0ZG9yYCoqIHByZXNlbnRhIHVuYSAqKmNvcnJlbGFjacOzbiBuZWdhdGl2YSoqIGNvbiBsYSAqKnRlbXBlcmF0dXJhIGRlIGVxdWlsaWJyaW8gZGVsIGV4b3BsYW5ldGEqKiAoKipgcGxfZXF0YCoqKSwgbG8gcXVlIGluZGljYSBxdWUgbG9zIGV4b3BsYW5ldGFzIGNvbiBwZXLDrW9kb3Mgb3JiaXRhbGVzIGxhcmdvcyB0aWVuZGVuIGEgdGVuZXIgdGVtcGVyYXR1cmFzIG3DoXMgYmFqYXMsIGxvIGN1YWwgZXMgZXNwZXJhYmxlLCB5YSBxdWUgc3VlbGVuIGVzdGFyIG3DoXMgYWxlamFkb3MgZGUgc3UgZXN0cmVsbGEgYW5maXRyaW9uYS4NCg0KRW4gY3VhbnRvIGEgbGEgdmFyaWFibGUgcXVlIHNlIHNlbGVjY2lvbsOzIGNvbW8gKip2YXJpYWJsZSBvYmpldGl2byoqIGVuIGVsIGFuw6FsaXNpcyBwcmV2aW8sIGVsICoqcmFkaW8gZGVsIGV4b3BsYW5ldGEqKiAoKipgcGxfcmFkamAqKiksIHNlIG9ic2VydmFuIHJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMgY29uIG90cmFzIHZhcmlhYmxlcy4gRXNwZWPDrWZpY2FtZW50ZSwgdGllbmUgdW5hICoqY29ycmVsYWNpw7NuIHBvc2l0aXZhKiogY29uIGxhICoqcHJvZnVuZGlkYWQgZGVsIHRyw6Fuc2l0byoqICgqKmBwbF90cmFuZGVwYCoqKSwgbG8gcXVlIGluZGljYSBxdWUgbG9zIGV4b3BsYW5ldGFzIG3DoXMgZ3JhbmRlcyBnZW5lcmFuIHVuYSBtYXlvciBkaXNtaW51Y2nDs24gZW4gZWwgYnJpbGxvIGRlIHN1IGVzdHJlbGxhIGFsIHBhc2FyIGZyZW50ZSBhIGVsbGEuIFBvciBvdHJvIGxhZG8sICoqYHBsX3JhZGpgKiogbXVlc3RyYSB1bmEgKipjb3JyZWxhY2nDs24gbmVnYXRpdmEqKiBjb24gbGEgKipncmF2ZWRhZCBzdXBlcmZpY2lhbCBkZSBsYSBlc3RyZWxsYSBhbmZpdHJpb25hKiogKCoqYHN0X2xvZ2dgKiopLCBsbyBxdWUgc3VnaWVyZSBxdWUgbG9zIGV4b3BsYW5ldGFzIG3DoXMgZ3JhbmRlcyB0aWVuZGVuIGEgZW5jb250cmFyc2UgZW4gc2lzdGVtYXMgY29uIGVzdHJlbGxhcyBkZSBtZW5vciBncmF2ZWRhZCBzdXBlcmZpY2lhbCwgcG9zaWJsZW1lbnRlIHBvcnF1ZSBlc3RvcyBzaXN0ZW1hcyBhbGJlcmdhbiBwbGFuZXRhcyBkZSBtYXlvciB0YW1hw7FvLg0KDQpQYXJhIHZpc3VhbGl6YXIgbWVqb3IgZXN0YXMgcmVsYWNpb25lcyB5IHNlbGVjY2lvbmFyIGxhcyBtZWpvcmVzICoqdmFyaWFibGVzIHByZWRpY3RvcmFzKiosIHNlIHJlYWxpemEgdW4gKipwYWlyIHBsb3QqKiBjb24gbGFzIHZhcmlhYmxlcyBxdWUgcHJlc2VudGFuIHVuYSBjb3JyZWxhY2nDs24gc2lnbmlmaWNhdGl2YSwgZXN0YWJsZWNpZW5kbyB1biAqKnVtYnJhbCBkZWwgNTAlIGVuIHZhbG9yIGFic29sdXRvKiouIEVzdGUgZ3LDoWZpY28gcGVybWl0ZSBleGFtaW5hciBjw7NtbyBzZSBkaXN0cmlidXllbiBsb3MgZGF0b3MgeSBjw7NtbyBzZSByZWxhY2lvbmFuIGxhcyB2YXJpYWJsZXMgZW50cmUgc8OtLCBmYWNpbGl0YW5kbyBsYSBpZGVudGlmaWNhY2nDs24gZGUgdGVuZGVuY2lhcyB5IHBvc2libGVzIHBhdHJvbmVzIMO6dGlsZXMgcGFyYSBsYSBlc3RpbWFjacOzbiBkZSB2YWxvcmVzIGZhbHRhbnRlcyB5IGxhIGNvbnN0cnVjY2nDs24gZGUgbW9kZWxvcyBkZSBwcmVkaWNjacOzbi4NCg0KYGBge3IgbW9zdF9jb3JyZWxhdGVkX3ZhcmlhYmxlc30NCg0KIyBTZWxlY2Npb25hciBkZSBsYSBtYXRyaXogZGUgY29ycmVsYWNpw7NuIGxhcyB2YXJpYWJsZXMgY29uIGNvcnJlbGFjaW9uIG1heW9yIG8NCiMgaWd1YWwgYSAwLjMgZW4gdmFsb3IgYWJzb2x1dG8gY29uIGxhIHZhcmlhYmxlIGZhbHRhbnRlDQpjb3JyZWxhdGVkX3ZhcnMgPC0gbmFtZXMod2hpY2goYWJzKGNvcnJlbGF0aW9uX21hdHJpeF9wZWFyc29uWyJwbF9yYWRqIiwgXSkgPj0gMC41KSkNCg0KIyBTZSBnZW5lcmEgdW4gZGF0YWZyYW1lIGNvbiBsYSBjb3JyZWxhY2lvbiBlbnRyZSBsYXMgdmFyaWFibGVzIHNlbGVjY2lvbmFkYXMNCiMgZW4gY29ycmVsYXRlZF92YXJzIHkgbGEgdmFyaWFibGUgZmFsdGFudGUgdG9tYW5kbyBkZSBsYSBtYXRyaXogZGUgY29ycmVsYWNpb24NCiMgc29sbyBsYXMgZmlsYXMgeSBjb2x1bW5hcyBjb3JyZXNwb25kaWVudGVzIGEgbGFzIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzDQpjb3JyZWxhdGlvbl9kZiA8LSBkYXRhLmZyYW1lKA0KICBWYXJpYWJsZSA9IG5hbWVzKGNvcnJlbGF0aW9uX21hdHJpeF9wZWFyc29uW2NvcnJlbGF0ZWRfdmFycywgInBsX3JhZGoiXSksDQogIENvcnJlbGFjaW9uID0gY29ycmVsYXRpb25fbWF0cml4X3BlYXJzb25bY29ycmVsYXRlZF92YXJzLCAicGxfcmFkaiJdDQopDQoNCiMgQWdyZWdhciB1bmEgY29sdW1uYSBjb24gbGEgY2FudGlkYWQgZGUgdmFsb3JlcyBmYWx0YW50ZXMNCmNvcnJlbGF0aW9uX2RmJEZhbHRhbnRlcyA8LSBzYXBwbHkoY29ycmVsYXRpb25fZGYkVmFyaWFibGUsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYShrZXBsZXJfZGF0YVtbeF1dKSkpDQoNCiMgRXNjcmlibyBhIGNvcnJlbGF0ZWRfdmFycyBsYXMgdmFyaWFibGVzIHNlbGVjY2lvbmFkYXMNCmNvcnJlbGF0ZWRfdmFycyA8LSBjb3JyZWxhdGlvbl9kZiRWYXJpYWJsZQ0KDQojIE9yZGVuYXIgZWwgZGF0YWZyYW1lIHBvciBjYW50aWRhZCBkZSBmYWx0YW50ZXMgYXNjZW5kZW50ZQ0KIyB5IHBvciB2YWxvciBhYnNvbHV0byBkZSBjb3JyZWxhY2nDs24gZGVzY2VuZGVudGUNCmNvcnJlbGF0aW9uX2RmIDwtIGNvcnJlbGF0aW9uX2RmW29yZGVyKGNvcnJlbGF0aW9uX2RmJEZhbHRhbnRlcywgLWFicyhjb3JyZWxhdGlvbl9kZiRDb3JyZWxhY2lvbikpLCBdDQoNCiMgRWxpbWluYXIgbGEgY29sdW1uYSBkZSBpbmRpY2UNCnJvd25hbWVzKGNvcnJlbGF0aW9uX2RmKSA8LSBOVUxMDQoNCiMgTW9zdHJhciB0YWJsYSBmb3JtYXRlYWRhDQprYWJsZShjb3JyZWxhdGlvbl9kZiwgY29sdW1ucyA9IGMoIlZhcmlhYmxlIiwiQ29ycmVsYWNpw7NuIiwiRmFsdGFudGVzIiksIGFsaWduID0gImwiKQ0KDQpgYGANCg0KYGBge3IgcGFpcl9wbG90X2NvcnJlbGF0ZWRfdmFyaWFibGVzLCB3YXJuaW5nPUZBTFNFfQ0KDQpwYW5lbC5oaXN0IDwtIGZ1bmN0aW9uKHgsIC4uLikgew0KICB1c3IgPC0gcGFyKCJ1c3IiKTsgb24uZXhpdChwYXIodXNyKSkNCiAgcGFyKHVzciA9IGModXNyWzE6Ml0sIDAsIDEuNSkpIA0KICBoaXN0KHgsIGNvbCA9ICJpbmRpYW5yZWQiLCBib3JkZXIgPSAid2hpdGUiLCBwcm9iYWJpbGl0eSA9IFRSVUUsIGFkZCA9IFRSVUUpDQp9DQoNCnBhaXJzKGtlcGxlcl9kYXRhX251bVssIGNvcnJlbGF0ZWRfdmFyc10sIA0KICAgICAgZGlhZy5wYW5lbCA9IHBhbmVsLmhpc3QsICAgICAjIEhpc3RvZ3JhbWFzIGVuIGxhIGRpYWdvbmFsDQogICAgICBjb2wgPSAic3RlZWxibHVlIiwgcGNoID0gMTksIGNleCA9IDEuMikNCg0KYGBgDQoNCk3DoXMgYWxsw6EgZGUgbGEgcmVsYWNpw7NuIGxpbmVhbCBldmlkZW50ZSBlbnRyZSBsYXMgbWVkaWRhcyBkZWwgKipyYWRpbyBkZWwgZXhvcGxhbmV0YSBlbiBkaWZlcmVudGVzIHVuaWRhZGVzKiog4oCUZXMgZGVjaXIsICoqcmFkaW9zIGpvdmlhbm9zKiogeSAqKnJhZGlvcyB0ZXJyZXN0cmVzKirigJQsIGVsIGFuw6FsaXNpcyBkZSBjb3JyZWxhY2nDs24gcmV2ZWxhIGxhIHByZXNlbmNpYSBkZSBvdHJhcyByZWxhY2lvbmVzIGxpbmVhbGVzIHNpZ25pZmljYXRpdmFzIGVudHJlIGVsIHJhZGlvIGRlbCBleG9wbGFuZXRhIHkgb3RyYXMgdmFyaWFibGVzIGRlbCBjb25qdW50byBkZSBkYXRvcy4gRXN0YXMgcmVsYWNpb25lcyBzZSBvcmRlbmFuIGVuIGZ1bmNpw7NuIGRlIHN1ICoqZnVlcnphIGRlIGNvcnJlbGFjacOzbioqIGVuIG9yZGVuIGRlc2NlbmRlbnRlLCBkZXN0YWNhbmRvIHRyZXMgcHJpbmNpcGFsZXMgdmFyaWFibGVzOg0KDQpMYSBwcmltZXJhIHZhcmlhYmxlIGNvbiB1bmEgZnVlcnRlIGNvcnJlbGFjacOzbiBlcyBlbCAqKmNvY2llbnRlIGRlbCByYWRpbyBkZWwgcGxhbmV0YSBzb2JyZSBlbCByYWRpbyBkZSBzdSBlc3RyZWxsYSBhbmZpdHJpb25hKiogKCoqYHBsX3JhdHJvcmAqKikuIEVzdGEgcmVsYWNpw7NuIHRpZW5lIHNlbnRpZG8gZGVzZGUgdW4gcHVudG8gZGUgdmlzdGEgZsOtc2ljbywgeWEgcXVlIGVsIHRhbWHDsW8gcmVsYXRpdm8gZGVsIGV4b3BsYW5ldGEgcmVzcGVjdG8gYSBzdSBlc3RyZWxsYSBhZmVjdGEgZGlyZWN0YW1lbnRlIGxhIG9ic2VydmFjacOzbiBkZSBmZW7Ds21lbm9zIGNvbW8gZWwgdHLDoW5zaXRvLiBDdWFudG8gbWF5b3Igc2VhIGVzdGUgY29jaWVudGUsIG1heW9yIHNlcsOhIGVsIHRhbWHDsW8gYXBhcmVudGUgZGVsIGV4b3BsYW5ldGEgZHVyYW50ZSBlbCB0csOhbnNpdG8uDQoNCkxhIHNlZ3VuZGEgdmFyaWFibGUgY29uIGFsdGEgY29ycmVsYWNpw7NuIGVzIGxhICoqcHJvZnVuZGlkYWQgZGVsIHRyw6Fuc2l0byoqICgqKmBwbF90cmFuZGVwYCoqKS4gRXN0ZSB2YWxvciBtaWRlIGxhIGRpc21pbnVjacOzbiBlbiBlbCBicmlsbG8gZGUgbGEgZXN0cmVsbGEgY3VhbmRvIGVsIHBsYW5ldGEgcGFzYSBmcmVudGUgYSBlbGxhLiBEYWRvIHF1ZSBwbGFuZXRhcyBtw6FzIGdyYW5kZXMgYmxvcXVlYW4gdW5hIG1heW9yIHBhcnRlIGRlIGxhIGx1eiBlc3RlbGFyIGR1cmFudGUgdW4gdHLDoW5zaXRvLCBlcyBsw7NnaWNvIHF1ZSBleGlzdGEgdW5hIHJlbGFjacOzbiBsaW5lYWwgcG9zaXRpdmEgZW50cmUgZWwgcmFkaW8gZGVsIHBsYW5ldGEgeSBsYSBwcm9mdW5kaWRhZCBkZWwgdHLDoW5zaXRvIG9ic2VydmFkby4NCg0KTGEgdGVyY2VyYSB2YXJpYWJsZSBzaWduaWZpY2F0aXZhIGVzIGxhICoqYW1wbGl0dWQgZGUgbGEgdmVsb2NpZGFkIHJhZGlhbCBkZWwgcGxhbmV0YSoqICgqKmBwbF9ydmFtcGAqKikuIEVzdGEgbWlkZSBlbCBkZXNwbGF6YW1pZW50byBkZSBsYSBlc3RyZWxsYSBkZWJpZG8gYWwgdGlyw7NuIGdyYXZpdGFjaW9uYWwgZGVsIGV4b3BsYW5ldGEgZW4gc3Ugw7NyYml0YS4gTG9zIGV4b3BsYW5ldGFzIGRlIG1heW9yIHRhbWHDsW8gdGllbmRlbiBhIGVqZXJjZXIgdW5hIGZ1ZXJ6YSBncmF2aXRhY2lvbmFsIG3DoXMgaW50ZW5zYSBzb2JyZSBsYSBlc3RyZWxsYSwgZ2VuZXJhbmRvIG1heW9yZXMgdmFyaWFjaW9uZXMgZW4gbGEgdmVsb2NpZGFkIHJhZGlhbCBkZXRlY3RhZGEgbWVkaWFudGUgZWwgZWZlY3RvIERvcHBsZXIsIGxvIHF1ZSBleHBsaWNhIGVzdGEgcmVsYWNpw7NuLg0KDQpDb24gYmFzZSBlbiBlc3RvcyByZXN1bHRhZG9zLCBzZSBzZWxlY2Npb25hbiBlc3RhcyB0cmVzIHZhcmlhYmxlcyBjb21vICoqdmFyaWFibGVzIHByZWRpY3RvcmFzKiogcGFyYSBlbCByYWRpbyBkZWwgZXhvcGxhbmV0YSwgeWEgcXVlIHByZXNlbnRhbiB1bmEgKiphbHRhIGNvcnJlbGFjacOzbiBsaW5lYWwqKiwgcG9zaXRpdmEgbyBuZWdhdGl2YSwgY29uIGxhIHZhcmlhYmxlIGZhbHRhbnRlLiBFc3RhcyByZWxhY2lvbmVzIHByb3BvcmNpb25hbiBpbmZvcm1hY2nDs24gY2xhdmUgcGFyYSByZWFsaXphciBlc3RpbWFjaW9uZXMgbcOhcyBwcmVjaXNhcyBkZWwgcmFkaW8gZGVsIGV4b3BsYW5ldGEgbWVkaWFudGUgdMOpY25pY2FzIGRlIHJlZ3Jlc2nDs24sIGJhc8OhbmRvc2UgZW4gcGF0cm9uZXMgY29uc2lzdGVudGVzIGVuIGxvcyBkYXRvcy4NCg0KIyMgRGV0ZWNjacOzbiBkZSB2YWxvcmVzIGF0w61waWNvcyAob3V0bGllcnMpIGVuIGxhcyBwcmVkaWN0b3Jhcw0KDQpQYXJhIGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgc2VsZWNjaW9uYWRhcyAoKipgcGxfcmF0ZG9yYCoqLCoqYHBsX3RyYW5kZXBgKiosKipgcGxfcnZhbXBgKiopLCBzZSBkZXRlY3RhbiB2YWxvcmVzIGF0w61waWNvcyBlbiBlbCBkYXRhc2V0IHF1ZSBwdWVkYW4gYWZlY3RhciBlbCBhbsOhbGlzaXMgeSBsYSBwcmVkaWNjacOzbiBkZSBsYSB2YXJpYWJsZSBmYWx0YW50ZSAoKipgcGxfcmFkamAqKikuDQoNCmBgYHtyIG91dGxpZXJzX2RldGVjdGlvbiwgd2FybmluZz1GQUxTRX0NCg0KIyBTZWxlY2Npb25hciBsYXMgdmFyaWFibGVzIHByZWRpY3RvcmFzDQpwcmVkaWN0b3JfdmFycyA8LSBjKCJwbF9yYXRkb3IiLCAicGxfdHJhbmRlcCIsICJwbF9ydmFtcCIpDQoNCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZSBjb24gbGFzIHZhcmlhYmxlcyBwcmVkaWN0b3Jhcw0KcHJlZGljdG9yX2RhdGEgPC0ga2VwbGVyX2RhdGFfbnVtW3ByZWRpY3Rvcl92YXJzXQ0KDQojIE5vcm1hbGl6YXIgbG9zIGRhdG9zDQpwcmVkaWN0b3JfZGF0YSA8LSBzY2FsZShwcmVkaWN0b3JfZGF0YSkNCg0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCg0KcHJlZGljdG9yX2RhdGEgPC0gYXMuZGF0YS5mcmFtZShwcmVkaWN0b3JfZGF0YSkNCg0KIyBDb252ZXJ0aXIgYSBmb3JtYXRvIGxhcmdvIHBhcmEgZ2dwbG90Mg0KZGF0YV9sb25nIDwtIHBpdm90X2xvbmdlcihwcmVkaWN0b3JfZGF0YSwgY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsb3JlcyIpDQoNCg0KIyBHcmFmaWNhciBsb3MgdmFsb3JlcyBhdMOtcGljb3MgY29uIHVuIGJveHBsb3QgaG9yaXpvbnRhbA0KIyBTZSBtdWVzdHJhIGVsIG51bWVybyB0b3RhbCBkZSB2YWxvcmVzIGF0w61waWNvcw0KZ2dwbG90KGRhdGFfbG9uZywgYWVzKHggPSBWYWxvcmVzLCB5ID0gVmFyaWFibGUpKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJkYXJrYmx1ZSIpICsNCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gYWJzKFZhbG9yZXMpID4gMyksIHdpZHRoID0gMC4xKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsICJyZWQiKSkgKw0KICBsYWJzKHRpdGxlID0gIkRldGVjY2nDs24gZGUgVmFsb3JlcyBBdMOtcGljb3MgZW4gVmFyaWFibGVzIFByZWRpY3RvcmFzIiwNCiAgICAgICB4ID0gIlZhbG9yZXMgTm9ybWFsaXphZG9zIiwNCiAgICAgICB5ID0gIlZhcmlhYmxlIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KDQoNCmBgYA0KDQpFbCAqKmJveHBsb3QqKiByZXZlbGEgbGEgcHJlc2VuY2lhIGRlICoqdmFsb3JlcyBhdMOtcGljb3MqKiBlbiBsYXMgdmFyaWFibGVzIHByZWRpY3RvcmFzIHNlbGVjY2lvbmFkYXMsIGxvIHF1ZSBwdWVkZSBpbmZsdWlyIHNpZ25pZmljYXRpdmFtZW50ZSBlbiBlbCBhbsOhbGlzaXMgeSBlbiBsYSBwcmVjaXNpw7NuIGRlIGxhIGVzdGltYWNpw7NuIGRlIGxhIHZhcmlhYmxlIGZhbHRhbnRlLiBFc3RvcyAqKm91dGxpZXJzKiogcHVlZGVuIHNlc2dhciBsb3MgcmVzdWx0YWRvcyB5IHJlZHVjaXIgbGEgZWZpY2FjaWEgZGUgbG9zIG1vZGVsb3MgZGUgcHJlZGljY2nDs24sIGVzcGVjaWFsbWVudGUgc2kgc2UgdXRpbGl6YW4gdMOpY25pY2FzIHNlbnNpYmxlcyBhIHZhbG9yZXMgZXh0cmVtb3MsIGNvbW8gbGEgcmVncmVzacOzbiBsaW5lYWwgZXN0w6FuZGFyLg0KDQpMbGFtYSBwYXJ0aWN1bGFybWVudGUgbGEgYXRlbmNpw7NuIGxhIGRpc3BlcnNpw7NuIHkgbGEgcHJlc2VuY2lhIGRlICoqdmFsb3JlcyBleHRyZW1vcyoqIGVuIGxhIHZhcmlhYmxlICoqYHBsX3RyYW5kZXBgKiosIHF1ZSByZXByZXNlbnRhIGxhIHByb2Z1bmRpZGFkIGRlbCB0csOhbnNpdG8gZGVsIHBsYW5ldGEsIGVzIGRlY2lyLCBxdcOpIHRhbnRvIGRpc21pbnV5ZSBlbCBmbHVqbyBkZSBsdXogZGUgbGEgZXN0cmVsbGEgY3VhbmRvIGVsIHBsYW5ldGEgcGFzYSBwb3IgZGVsYW50ZSBkZSBlbGxhLiBCw6FzaWNhbWVudGUsIGN1w6FudGEgbHV6IGJsb3F1ZWEgZWwgcGxhbmV0YSBkdXJhbnRlIGVsIHRyw6Fuc2l0bywgZW4gcG9yY2VudGFqZS4gTGEgZGlzcGVyc2nDs24gZGUgdmFsb3JlIG5vcyBkYSBhbGd1bmFzIHBpc3Rhcy4gRW4gcHJpbWVyIGx1Z2FyIGxvcyB2YWxvcmVzIGNlcmNhbm9zIGEgY2VybyAobGEgZ3JhbiBtYXlvcsOtYSk6IGluZGljYW4gcXVlIGVsIHBsYW5ldGEgYmxvcXVlYSBtdXkgcG9jYSBsdXogZHVyYW50ZSBlbCB0csOhbnNpdG8uIEVzdG8gZXMgbm9ybWFsIHBhcmEgcGxhbmV0YXMgcGVxdWXDsW9zIG8gbGVqYW5vcy4gUG9yIG90cmEgcGFydGUgbGEgY29sdW1uYSBsYXJnYSBkZSBwdW50b3MgYSBsYSBkZXJlY2hhIChvdXRsaWVycyBlbiByb2pvKTogZXNvcyBzb24gY2Fzb3MgZG9uZGUgbGEgZGlzbWludWNpw7NuIGRlbCBmbHVqbyBlcyBtdWNobyBtYXlvciwgaW5kaWNhbmRvIHF1ZSBlbCBwbGFuZXRhOiBvIGVzIG11eSBncmFuZGUgZW4gY29tcGFyYWNpw7NuIGNvbiBzdSBlc3RyZWxsYSwgbyBsYSBlc3RyZWxsYSBlcyBwZXF1ZcOxYSwgYXPDrSBxdWUgY3VhbHF1aWVyIHBsYW5ldGEgZ2VuZXJhIHVuIGdyYW4gYmxvcXVlbyBkZSBsdXogcGVybyB0YW1iacOpbiBwb3NpYmxlbWVudGUgcXVlIGhheWEgcHJvYmxlbWFzIGVuIGxhIG1lZGljacOzbiBvIGVycm9yZXMgc2lzdGVtw6F0aWNvcy4NCg0KTGEgZ3JhbiBjYW50aWRhZCBkZSAqKnZhbG9yZXMgZXh0cmVtb3MqKiBlbiAqKmBwbF90cmFuZGVwYCoqIHB1ZWRlIHN1Z2VyaXIgdW5hIGRpc3RyaWJ1Y2nDs24gbmF0dXJhbG1lbnRlIHNlc2dhZGE7IGVzIGRlY2lyIGVzdGEgdmFyaWFibGUgcHVlZGUgc2VndWlyIHVuYSBkaXN0cmlidWNpw7NuIGZ1ZXJ0ZW1lbnRlIGFzaW3DqXRyaWNhIGRhZG8gcXV5ZSBsYSBtYXlvcsOtYSBkZSBsb3MgcGxhbmV0YXMgYXBlbmFzIGJsb3F1ZWFuIGx1eiBwZXJvIHVub3MgcG9jb3MgYmxvcXVlYW4gYmFzdGFudGUgKGVqOiBKw7pwaXRlcmVzIGNhbGllbnRlcyBmcmVudGUgYSBlbmFuYXMgcm9qYXMpLiBFcyBjb23Dum4gZW4gYXN0cm9ub23DrWE6IHBvY29zIGV2ZW50b3MgZXh0cmVtb3MsIG11Y2hvcyB2YWxvcmVzIHBlcXVlw7Fvcy4gUGVybyB0YW1iacOpbiBwdWVkZSBzaWduaWZpY2FyIGVycm9yZXMgbyBydWlkbyBpbnN0cnVtZW50YWw6IGFsZ3Vub3Mgb3V0bGllcnMgcG9kcsOtYW4gc2VyIGFydGVmYWN0b3MgZGUgbWVkaWNpw7NuLCBkb25kZSBlbCBtb2RlbG8gZGUgdHLDoW5zaXRvIGludGVycHJldMOzIG1hbCBsYSBjdXJ2YSBkZSBsdXouIFBvciDDumx0aW1vIG5vIGRlYmUgZGVzY2FydGFyc2UgcXVlICBwdWVkZSBoYWJlciBlcnJvcmVzIGRlIHJlZHVjY2nDs24gZGUgZGF0b3MgZW4gZWwgdGVsZXNjb3BpbyBLZXBsZXIuIFNpIG5vIGVzIHVuIHByb2JsZW1hIGRlbCB0ZWxlc2NvcGlvLCBwdWVkZSBzZXIgdW4gc2lzdGVtYSBtYWwgY2xhc2lmaWNhZG86IEFsZ3Vub3Mgb2JqZXRvcyBwdWVkZW4gbm8gc2VyIHBsYW5ldGFzLCBzaW5vIGVzdHJlbGxhcyBiaW5hcmlhcyBlY2xpcHNhbnRlcywgcXVlIGdlbmVyYW4gdW5hIGJhamFkYSBkZSBmbHVqbyBtdWNobyBtYXlvciBhbCBkZSB1biBwbGFuZXRhLg0KDQpQYXJhIGFib3JkYXIgZXN0ZSBwcm9ibGVtYSwgZXMgcmVjb21lbmRhYmxlIGVtcGxlYXIgKiptw6l0b2RvcyBkZSByZWdyZXNpw7NuIHJvYnVzdG9zKiosIGRpc2XDsWFkb3MgcGFyYSBtaW5pbWl6YXIgZWwgaW1wYWN0byBkZSB2YWxvcmVzIGF0w61waWNvcyBlbiBlbCBhanVzdGUgZGVsIG1vZGVsby4gVW4gZWplbXBsbyBkZSBlc3RlIGVuZm9xdWUgZXMgbGEgKipyZWdyZXNpw7NuIGRlIEh1YmVyKiosIHF1ZSBjb21iaW5hIGxhcyB2ZW50YWphcyBkZSBsYSByZWdyZXNpw7NuIGxpbmVhbCB5IGxhIHJlZ3Jlc2nDs24gcG9yIG3DrW5pbW9zIGN1YWRyYWRvcywgcGVybyBjb24gdW4gbWVjYW5pc21vIHF1ZSByZWR1Y2UgbGEgaW5mbHVlbmNpYSBkZSBvdXRsaWVycyBhbCBhc2lnbmFybGVzIHVuIG1lbm9yIHBlc28gZW4gZWwgY8OhbGN1bG8gZGUgbG9zIGNvZWZpY2llbnRlcy4NCg0KT3RyYSBhbHRlcm5hdGl2YSBlcyB1dGlsaXphciB0w6ljbmljYXMgY29tbyBsYSAqKnJlZ3Jlc2nDs24gZGUgVHVrZXkgYml3ZWlnaHQqKiBvIGxhICoqcmVncmVzacOzbiBkZSBjdWFudGlsZXMqKiwgcXVlIG1vZGVsYW4gbGEgcmVsYWNpw7NuIGVudHJlIHZhcmlhYmxlcyBzaW4gdmVyc2UgYWZlY3RhZGFzIHBvciBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBkYXRvcyBleHRyZW1vcy4gQWRpY2lvbmFsbWVudGUsIHNlIHB1ZWRlbiBhcGxpY2FyICoqbcOpdG9kb3MgZGUgZGV0ZWNjacOzbiB5IHRyYXRhbWllbnRvIGRlIG91dGxpZXJzKiosIGNvbW8gZWwgKipyZWNvcnRlIGRlIGRhdG9zICh0cmltbWluZykqKiwgcXVlIGVsaW1pbmEgdmFsb3JlcyBleHRyZW1vcyBwb3IgZW5jaW1hIG8gcG9yIGRlYmFqbyBkZSB1biB1bWJyYWwgZXNwZWPDrWZpY28sIG8gbGEgKip0cmFuc2Zvcm1hY2nDs24gZGUgdmFyaWFibGVzKiosIGNvbW8gZWwgdXNvIGRlIGxvZ2FyaXRtb3MgbyBlc2NhbGFkbyByb2J1c3RvLCBwYXJhIHJlZHVjaXIgZWwgaW1wYWN0byBkZSB2YWxvcmVzIGV4dHJlbW9zIGVuIGVsIGFuw6FsaXNpcy4NCg0KIyBBbmFsaXNpcyBkZSByZWdyZXNpw7NuDQoNClBhcmEgZXhwbG9yYXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYXJhY3RlcsOtc3RpY2FzIGNvbm9jaWRhcyBkZSBsb3MgZXhvcGxhbmV0YXMsIHNlIGxsZXZhIGEgY2FibyB1biAqKmFuw6FsaXNpcyBkZSByZWdyZXNpw7NuIGxpbmVhbCoqLiBFbCBvYmpldGl2byBlcyBwcmVkZWNpciBlbCAqKnJhZGlvIGRlbCBleG9wbGFuZXRhIChgcGxfcmFkamApKiogdXRpbGl6YW5kbyB0cmVzIHZhcmlhYmxlcyBxdWUgcG9kcsOtYW4gZXN0YXIgZXN0cmVjaGFtZW50ZSByZWxhY2lvbmFkYXMgY29uIHN1IHRhbWHDsW86DQoNCi0gICAqKmBwbF9yYXRkb3JgKio6IGVsIGNvY2llbnRlIGVudHJlIGVsIHJhZGlvIGRlbCBleG9wbGFuZXRhIHkgZWwgcmFkaW8gZGUgc3UgZXN0cmVsbGEsIHF1ZSBwcm9wb3JjaW9uYSB1bmEgbWVkaWRhIHJlbGF0aXZhIGRlbCB0YW1hw7FvIGRlbCBwbGFuZXRhLlwNCi0gICAqKmBwbF90cmFuZGVwYCoqOiBsYSBwcm9mdW5kaWRhZCBkZWwgdHLDoW5zaXRvLCBxdWUgaW5kaWNhIGN1w6FudG8gZGlzbWludXllIGVsIGJyaWxsbyBkZSBsYSBlc3RyZWxsYSBjdWFuZG8gZWwgZXhvcGxhbmV0YSBwYXNhIGZyZW50ZSBhIGVsbGEsIGxvIHF1ZSBlc3TDoSBkaXJlY3RhbWVudGUgcmVsYWNpb25hZG8gY29uIHN1IHJhZGlvLlwNCi0gICAqKmBwbF9ydmFtcGAqKjogbGEgYW1wbGl0dWQgZGUgbGEgdmVsb2NpZGFkIHJhZGlhbCBkZWwgcGxhbmV0YSwgcXVlIHJlZmxlamEgc3UgZWZlY3RvIGdyYXZpdGFjaW9uYWwgc29icmUgbGEgZXN0cmVsbGEgeSBwdWVkZSBhcG9ydGFyIGluZm9ybWFjacOzbiBzb2JyZSBzdSBtYXNhIHksIGVuIGNvbWJpbmFjacOzbiBjb24gb3RyYXMgdmFyaWFibGVzLCBzdSB0YW1hw7FvLg0KDQpBIHRyYXbDqXMgZGUgZXN0ZSBhbsOhbGlzaXMsIHNlIGJ1c2NhIGNvbXByZW5kZXIgbWVqb3IgY8OzbW8gZXN0YXMgdmFyaWFibGVzIGluZmx1eWVuIGVuIGVsIHRhbWHDsW8gZGUgbG9zIGV4b3BsYW5ldGFzIHkgZGV0ZXJtaW5hciBjdcOhbCBkZSBlbGxhcyB0aWVuZSB1biBtYXlvciBpbXBhY3RvIGVuIGxhIHByZWRpY2Npw7NuIGRlICoqYHBsX3JhZGpgKiouDQoNCiMjIFJlZ3Jlc2nDs24gbGluZWFsIHVuaXZhcmlhZGENCg0KTGFzIHZhcmlhYmxpZXMgZGUgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsb3Mgc2lzdGVtYXMgZXhvcGxhbmV0YXJpb3MgdGFsZXMgY29tbyBwZXJpb2RvIG9yYml0YWwsIHJhZGlvIHBsYW5ldGFyaW8sIHRlbXBlcmF0dXJhIGRlIGxhIGVzdHJlbGxhIGNlbnRyYWwgZGVsIHNpc3RlbWEgeSBtYXNhIGRlbCBwbGFuZXRhIHB1ZWRlbiBpbmZlcmlyc2UgaW5kaXJlY3RhbWVudGUgYSBwYXJ0aXIgZGUgb3RyYXMgdmFyaWFibGVzIGNvbW8gZXhjZW50cmljaWRhZCBvcmJpdGFsLCBkaXN0YW5jaWEgYSBsYSBlc3RyZWxsYSwgY2FyYWN0ZXJpc3RpY2FzIGRlIGxhIGVzdHJlbGxhIHkgb3RyYXMuIFNlIGV4cGxvcmFyIHVuIGFuw6FsaXNpcyBkZSByZWdyZXNpw7NuIGxpbmVhbCB1bml2YXJpYWRhIGNvbiB2YXJpYXMgdmFyaWFibGVzIGluZGVwZW5kaWVudGVzIGV2YWx1YW5kbyBsYSBjYXBhY2lkYWQgZGUgcHJlZGljY2nDs24gZGUgY2FkYSBtb2RlbG8gcGxhbnRlYWRvLg0KDQpTZSByZWFsaXphIHVuIGFuw6FsaXNpcyBkZSByZWdyZXNpw7NuIGxpbmVhbCB1bml2YXJpYWRhIHBhcmEgcHJlZGVjaXIgZWwgcmFkaW8gZGVsIGV4b3BsYW5ldGEgKCoqYHBsX3JhZGpgKiopIGNvbnNlY3V0aXZhbWVudGUgYSBwYXJ0aXIgZGUgbGFzIHZhcmlhYmxlcyBpbmRlcGVuZGllbnRlcyBzZWxlY2Npb25hZGFzLg0KDQojIyMgUmVncmVzacOzbiBsaW5lYWw6IHJhZGlvIGRlbCBleG9wbGFuZXRhIHNlZ8O6biByYXRpbyBkZWwgcmFkaW8gc29icmUgZWwgcmFkaW8gZXN0ZWxhciAoYHBsX3JhdGRvcmApDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcmF0ZG9yfQ0KDQojIFJlZ3Jlc2lvbiBkZSBwbF9yYWRqIGNvbiBwbF9yYXRkb3INCm1vZGVsX3BsX3JhdGRvciA8LSBsbShwbF9yYWRqIH4gcGxfcmF0ZG9yLCBkYXRhID0ga2VwbGVyX2RhdGFfbnVtKQ0KDQptb2RlbF9wbF9yYXRkb3Jfc3VtbWFyeSA8LSBzdW1tYXJ5KG1vZGVsX3BsX3JhdGRvcikNCg0KbW9kZWxfcGxfcmF0ZG9yX3N1bW1hcnkNCmBgYA0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3JhdGRvcl9wbG90LCB3YXJuaW5nPUZBTFNFfQ0KDQojIFNjYXR0ZXIgcGxvdCBkZSBwbF9yYWRqIHZzIHBsX3JhdGRvciBjb24gbGEgcmVjdGEgZGUgcmVncmVzacOzbiBlbiByb2pvDQojIHkgbG9zIG1hcmdlbmVzIGRlIGNvbmZpYW56YSBlbiBncmlzDQpnZ3Bsb3Qoa2VwbGVyX2RhdGFfbnVtLCBhZXMoeCA9IHBsX3JhdGRvciwgeSA9IHBsX3JhZGopKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJpbmRpYW5yZWQiLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMikgKw0KICBsYWJzKHRpdGxlID0gIlJlZ3Jlc2nDs24gTGluZWFsOiBSYWRpbyBkZWwgRXhvcGxhbmV0YSBzZWd1biBSYXRpbyBzb2JyZSBlbCBSYWRpbyBFc3RlbGFyIiwNCiAgICAgICB4ID0gIlJhdGlvIHNvYnJlIFJhZGlvIEVzdGVsYXIiLA0KICAgICAgIHkgPSAiUmFkaW8gZGVsIEV4b3BsYW5ldGEgKErDunBpdGVyKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpQYXJhIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIHBsYW50ZWFkbzoNCg0KJCQNCnBsXF9yYWRqID0gXGJldGFfMCArIFxiZXRhXzEgXGNkb3QgcGxcX3JhdGRvciArIFx2YXJlcHNpbG9uDQokJA0KDQpFbCBhbsOhbGlzaXMgZGUgcmVncmVzacOzbiBzdWdpZXJlIHF1ZSBsYSB2YXJpYWJsZSAqKmBwbF9yYXRkb3JgKiogbm8gZXMgdW4gYnVlbiBwcmVkaWN0b3IgZGVsIHJhZGlvIGRlbCBleG9wbGFuZXRhICgqKmBwbF9yYWRqYCoqKS4gU2Vnw7puIGxvcyByZXN1bHRhZG9zLCBwb3IgY2FkYSBhdW1lbnRvIGRlIDEgdW5pZGFkIGVuICoqYHBsX3JhdGRvcmAqKiwgc2UgZXNwZXJhIHVuIGluY3JlbWVudG8gZGUgYXBlbmFzICoqMC4wMDA3MzQxKiogZW4gKipgcGxfcmFkamAqKi4gU2luIGVtYmFyZ28sIGVsIHZhbG9yIHAgYXNvY2lhZG8gYSBlc3RhIHJlbGFjacOzbiAoKipQcihcPlx8dFx8KSA9IDAuMTUyKiopIGVzIG1heW9yIHF1ZSAqKjAuMDUqKiwgbG8gcXVlIHNpZ25pZmljYSBxdWUgKipubyBoYXkgc3VmaWNpZW50ZSBldmlkZW5jaWEgZXN0YWTDrXN0aWNhKiogcGFyYSBhZmlybWFyIHF1ZSAqKmBwbF9yYXRkb3JgKiogaW5mbHV5ZSBzaWduaWZpY2F0aXZhbWVudGUgZW4gKipgcGxfcmFkamAqKi4gRXN0byBzdWdpZXJlIHF1ZSBlbCBtb2RlbG8gcGxhbnRlYWRvIG5vIGVzIGVsIG3DoXMgYWRlY3VhZG8gcGFyYSBlc3RpbWFyIGVsIHJhZGlvIGRlbCBleG9wbGFuZXRhIGVuIGZ1bmNpw7NuIGRlbCBjb2NpZW50ZSBlbnRyZSBzdSByYWRpbyB5IGVsIHJhZGlvIGRlIHN1IGVzdHJlbGxhLg0KDQpFc3RlIHJlc3VsdGFkbyBzZSByZWZ1ZXJ6YSBhbCByZXZpc2FyIGxhcyBlc3RhZMOtc3RpY2FzIGRlIGFqdXN0ZSBkZWwgbW9kZWxvLiBFbCAqKkVycm9yIEVzdMOhbmRhciBSZXNpZHVhbCoqICgqKjAuMzg3MioqKSBpbmRpY2EgcXVlIGxvcyB2YWxvcmVzIHByZWRpY2hvcyBzZSBkZXN2w61hbiBiYXN0YW50ZSBkZSBsb3MgdmFsb3JlcyByZWFsZXMsIGxvIHF1ZSBldmlkZW5jaWEgdW4gYWp1c3RlIGltcHJlY2lzby4gQWRlbcOhcywgZWwgKipSwrIgbcO6bHRpcGxlKiogKCoqMC4wMjYxOCoqKSBtdWVzdHJhIHF1ZSBzb2xvICoqZWwgMi42JSBkZSBsYSB2YXJpYWJpbGlkYWQgZW4gYHBsX3JhZGpgKiogZXMgZXhwbGljYWRhIHBvciAqKmBwbF9yYXRkb3JgKiosIGxvIHF1ZSBpbmRpY2EgdW4gbW9kZWxvIGNvbiBtdXkgcG9jYSBjYXBhY2lkYWQgcHJlZGljdGl2YS4gRGUgbWFuZXJhIHNpbWlsYXIsIGVsICoqUsKyIGFqdXN0YWRvKiogKCoqMC4wMTM3KiopLCBxdWUgY29ycmlnZSBwb3IgZWwgbsO6bWVybyBkZSBwcmVkaWN0b3Jlcywgc2lndWUgc2llbmRvIG11eSBiYWpvLCByZWZvcnphbmRvIGxhIGlkZWEgZGUgcXVlICoqYHBsX3JhdGRvcmAqKiBubyBjb250cmlidXllIHNpZ25pZmljYXRpdmFtZW50ZSBhIGxhIHByZWRpY2Npw7NuIGRlbCByYWRpbyBkZWwgZXhvcGxhbmV0YS4NCg0KUG9yIG90cm8gbGFkbywgZWwgKipGLXN0YXRpc3RpYyoqICgyLjA5NykgeSBzdSB2YWxvciBwICgqKjAuMTUxNioqKSBjb25maXJtYW4gcXVlIGVsIG1vZGVsbywgZW4gc3UgY29uanVudG8sICoqbm8gZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2byoqLCBsbyBxdWUgc2lnbmlmaWNhIHF1ZSBubyBlcyBjYXBheiBkZSBleHBsaWNhciBkZSBtYW5lcmEgZmlhYmxlIGxhIHJlbGFjacOzbiBlbnRyZSBlc3RhcyB2YXJpYWJsZXMuDQoNCkEgcGVzYXIgZGUgZXN0b3MgcmVzdWx0YWRvcywgc2UgcmVhbGl6YSB1biBhbsOhbGlzaXMgZGUgbG9zICoqcmVzaWR1b3MgZGVsIG1vZGVsbyoqIHBhcmEgdmVyaWZpY2FyIHNpIGN1bXBsZW4gY29uIGxvcyBzdXB1ZXN0b3MgZGUgbGEgcmVncmVzacOzbiBsaW5lYWwsIGNvbiBlbCBvYmpldGl2byBkZSBlbnRlbmRlciBtZWpvciBsYXMgbGltaXRhY2lvbmVzIGRlbCBtb2RlbG8geSBleHBsb3JhciBwb3NpYmxlcyBhanVzdGVzIG8gYWx0ZXJuYXRpdmFzLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3JhdGRvcl9yZXNfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBPYnRlbmVyIGxvcyByZXNpZHVvcyB5IHZhbG9yZXMgYWp1c3RhZG9zDQpyZXNfcGxfcmF0ZG9yIDwtIHJlc2lkdWFscyhtb2RlbF9wbF9yYXRkb3IpDQoNCiMgRXN0aW1hciBsb3MgdmFsb3JlcyBhanVzdGFkb3MNCmZpdF92YWxfcGxfcmF0ZG9yIDwtIGZpdHRlZChtb2RlbF9wbF9yYXRkb3IpDQoNCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZSBjb24gbG9zIHJlc2lkdW9zIHkgdmFsb3JlcyBhanVzdGFkb3MNCnJlc19wbF9yYXRkb3JfZGYgPC0gZGF0YS5mcmFtZShGaXR0ZWRfVmFsdWVzID0gZml0X3ZhbF9wbF9yYXRkb3IsIFJlc2lkdWFscyA9IHJlc19wbF9yYXRkb3IpDQoNCiMgU2NhdHRlciBwbG90IGRlIHJlc2lkdW9zIHZzIHZhbG9yZXMgYWp1c3RhZG9zDQpnZ3Bsb3QocmVzX3BsX3JhdGRvcl9kZiwgYWVzKHggPSBGaXR0ZWRfVmFsdWVzLCB5ID0gUmVzaWR1YWxzKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAiaW5kaWFucmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBsYWJzKHRpdGxlID0gIlJlc2lkdW9zIHZzIFZhbG9yZXMgQWp1c3RhZG9zIiwNCiAgICAgICB4ID0gIlZhbG9yZXMgQWp1c3RhZG9zIiwNCiAgICAgICB5ID0gIlJlc2lkdW9zIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCkVsIGFuw6FsaXNpcyBkZSBsb3MgcmVzaWR1b3MgbXVlc3RyYSBxdWUgZXN0b3MgdGllbmRlbiBhIGNvbmNlbnRyYXJzZSBlbiBsb3MgdmFsb3JlcyBhanVzdGFkb3MgbcOhcyBiYWpvcywgYXByb3hpbWFkYW1lbnRlIGVudHJlICoqMC40IHkgMC41KiouIEEgbWVkaWRhIHF1ZSBsb3MgdmFsb3JlcyBhanVzdGFkb3MgYXVtZW50YW4sIGxhIGRpc3BlcnNpw7NuIGRlIGxvcyByZXNpZHVvcyB0YW1iacOpbiBwYXJlY2UgKippbmNyZW1lbnRhciBsaWdlcmFtZW50ZSoqLiBTaW4gZW1iYXJnbywgbm8gc2Ugb2JzZXJ2YSB1biBwYXRyw7NuIGNsYXJvIGVuIGZvcm1hIGRlIHBhcsOhYm9sYSBvIGN1cnZhLCBsbyBxdWUgc3VnaWVyZSBxdWUgbGEgcmVsYWNpw7NuIGVudHJlIGxhIHZhcmlhYmxlIGluZGVwZW5kaWVudGUgKCoqYHBsX3JhdGRvcmAqKikgeSBsYSBkZXBlbmRpZW50ZSAoKipgcGxfcmFkamAqKikgcG9kcsOtYSBzZXIgKiphcHJveGltYWRhbWVudGUgbGluZWFsKiouDQoNCkVuIGdlbmVyYWwsIGxhIG1heW9yw61hIGRlIGxvcyByZXNpZHVvcyBzZSBlbmN1ZW50cmFuIHJlbGF0aXZhbWVudGUgKipjZXJjYSBkZSAwKiosIGF1bnF1ZSBoYXkgYWxndW5vcyB2YWxvcmVzIHBvc2l0aXZvcyBlbGV2YWRvcyAoKiptYXlvcmVzIGEgMC41KiopLCBsbyBxdWUgaW5kaWNhIHF1ZSBlbCBtb2RlbG8gdGllbmRlIGEgKipzdWJlc3RpbWFyIGNpZXJ0b3MgdmFsb3JlcyoqIGRlICoqYHBsX3JhZGpgKiouIFBvciBvdHJvIGxhZG8sIGhheSBwb2NvcyByZXNpZHVvcyBuZWdhdGl2b3MgZXh0cmVtb3MsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBlbCBtb2RlbG8gKipubyBlc3TDoSBzb2JyZWVzdGltYW5kbyBzaWduaWZpY2F0aXZhbWVudGUqKiBsb3MgdmFsb3JlcyBkZWwgcmFkaW8gZGVsIGV4b3BsYW5ldGEuDQoNClNlIGRldGVjdGEgdW5hIGxldmUgKipoZXRlcm9jZWRhc3RpY2lkYWQqKiwgeWEgcXVlIGxhIGRpc3BlcnNpw7NuIGRlIGxvcyByZXNpZHVvcyBwYXJlY2UgKiptYXlvciBlbiBsb3MgdmFsb3JlcyBhanVzdGFkb3MgbcOhcyBhbHRvcyoqLiBFc3RvIGltcGxpY2EgcXVlIGVsIGVycm9yIG5vIGVzIGNvbXBsZXRhbWVudGUgdW5pZm9ybWUgYSBsbyBsYXJnbyBkZSBsYSBkaXN0cmlidWNpw7NuIGRlIHZhbG9yZXMgYWp1c3RhZG9zLCBsbyBxdWUgcG9kcsOtYSBhZmVjdGFyIGxhICoqY29uZmlhYmlsaWRhZCBkZSBsYXMgcHJlZGljY2lvbmVzKiouIEVuIHVuIG1vZGVsbyBpZGVhbCBxdWUgY3VtcGxpZXJhIGNvbiBsYSBzdXBvc2ljacOzbiBkZSAqKmhvbW9jZWRhc3RpY2lkYWQqKiAoZXMgZGVjaXIsIHZhcmlhbnphIGNvbnN0YW50ZSBkZSBsb3MgZXJyb3JlcyksIGxvcyByZXNpZHVvcyBkZWJlcsOtYW4gZGlzdHJpYnVpcnNlIGRlIG1hbmVyYSBtw6FzIHVuaWZvcm1lIGFscmVkZWRvciBkZSBsYSBsw61uZWEgZGUgcmVmZXJlbmNpYSAqKihyZXNpZHVvID0gMCkqKi4NCg0KRGFkbyBxdWUgZWwgbW9kZWxvIHRpZW5lIHVuICoqUsKyIG11eSBiYWpvIChcfjIuNiUpKiosIGVyYSBlc3BlcmFibGUgZW5jb250cmFyIHVuYSBkaXNwZXJzacOzbiBhbHRhIGVuIGxvcyByZXNpZHVvcywgbG8gcXVlIGNvbmZpcm1hIHF1ZSAqKmBwbF9yYXRkb3JgIG5vIGVzIHVuIGJ1ZW4gcHJlZGljdG9yIGRlIGBwbF9yYWRqYCoqLiBBZGVtw6FzLCBsYSBwcmVzZW5jaWEgZGUgcmVzaWR1b3MgZWxldmFkb3Mgc3VnaWVyZSBxdWUgZXhpc3RlbiAqKm90cmFzIHZhcmlhYmxlcyBubyBjb25zaWRlcmFkYXMqKiBxdWUgcG9kcsOtYW4gZXhwbGljYXIgbWVqb3IgbGEgdmFyaWFiaWxpZGFkIGVuIGVsIHJhZGlvIGRlbCBleG9wbGFuZXRhLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3JhdGRvcl9xcV9wbG90LCB3YXJuaW5nPUZBTFNFfQ0KDQojIENyZWFyIHVuIGdyw6FmaWNvIFEtUSBkZSBsb3MgcmVzaWR1b3MNCnFxbm9ybShyZXNfcGxfcmF0ZG9yLCBtYWluID0gIkdyw6FmaWNvIFEtUSBkZSBsb3MgUmVzaWR1b3MiLCBjb2wgPSAiaW5kaWFucmVkIikNCg0KYGBgDQoNClBhcmEgcXVlIGxvcyByZXNpZHVvcyBzaWdhbiB1bmEgKipkaXN0cmlidWNpw7NuIG5vcm1hbCoqLCBsb3MgcHVudG9zIGVuIGxhIGdyw6FmaWNhIGRlYmVyw61hbiBhbGluZWFyc2UgY29uIHVuYSAqKmzDrW5lYSBkaWFnb25hbCBpbWFnaW5hcmlhKiouIFNpbiBlbWJhcmdvLCBzZSBvYnNlcnZhbiAqKmRlc3ZpYWNpb25lcyoqIGVuIGxvcyBleHRyZW1vcywgZXMgZGVjaXIsIGVuIGxvcyBjdWFudGlsZXMgbcOhcyBiYWpvcyB5IG3DoXMgYWx0b3MsIGRvbmRlIGxvcyBwdW50b3Mgc2UgYWxlamFuIGRlIGxhIGzDrW5lYSB0ZcOzcmljYS4gRXN0byBpbmRpY2EgbGEgcHJlc2VuY2lhIGRlICoqY29sYXMgbcOhcyBwZXNhZGFzKiogZGUgbG8gZXNwZXJhZG8gZW4gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLCBsbyBxdWUgc3VnaWVyZSBxdWUgZXhpc3RlbiAqKnZhbG9yZXMgYXTDrXBpY29zIG8gcXVlIGxvcyByZXNpZHVvcyBubyBzaWd1ZW4gY29tcGxldGFtZW50ZSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwqKi4NCg0KQWRlbcOhcywgc2Ugbm90YSB1bmEgKipsaWdlcmEgY3VydmF0dXJhIGVuIGxhIHBhcnRlIGNlbnRyYWwgZGVsIGdyw6FmaWNvKiouIEF1bnF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgcHVudG9zIHNlIGFsaW5lYW4gY29uIGxhIGzDrW5lYSB0ZcOzcmljYSBlbiBlc3RhIHJlZ2nDs24sIGxhIGN1cnZhdHVyYSBzdWdpZXJlIHF1ZSBsb3MgcmVzaWR1b3Mgbm8gc29uICoqcGVyZmVjdGFtZW50ZSBub3JtYWxlcyoqLCBsbyBxdWUgcG9kcsOtYSBhZmVjdGFyIGxhIHZhbGlkZXogZGUgYWxndW5hcyBpbmZlcmVuY2lhcyBlc3RhZMOtc3RpY2FzLg0KDQpMYSAqKnJlZ3Jlc2nDs24gbGluZWFsKiogYXN1bWUgcXVlIGxvcyByZXNpZHVvcyBkZWJlbiBzZWd1aXIgdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsIHBhcmEgZ2FyYW50aXphciBsYSAqKnZhbGlkZXogZGUgbG9zIGludGVydmFsb3MgZGUgY29uZmlhbnphIHkgZGUgbG9zIHZhbG9yZXMgcCoqLiBFbiBlc3RlIGNhc28sIGxhIGN1cnZhdHVyYSB5IGxhcyBjb2xhcyBwZXNhZGFzIHBsYW50ZWFuIGR1ZGFzIHNvYnJlIGVsIGN1bXBsaW1pZW50byBkZSBlc3RhIHN1cG9zaWNpw7NuLiBTaSBsb3MgcmVzaWR1b3Mgbm8gc29uIG5vcm1hbGVzLCBsYSBpbmZlcmVuY2lhIGVzdGFkw61zdGljYSBkZWwgbW9kZWxvIHBvZHLDrWEgdmVyc2UgYWZlY3RhZGEsIGF1bnF1ZSBsYSBlc3RpbWFjacOzbiBkZSBsb3MgY29lZmljaWVudGVzIHNlZ3VpcsOtYSBzaWVuZG8gdsOhbGlkYS4NCg0KUGFyYSBhYm9yZGFyIGVzdGUgcHJvYmxlbWEsIHVuYSBwb3NpYmxlIHNvbHVjacOzbiBlcyBhcGxpY2FyICoqdHJhbnNmb3JtYWNpb25lcyBlbiBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSoqICgqKmBwbF9yYWRqYCoqKSwgY29tbyAqKmxvZ2FyaXRtb3MgbyByYcOtY2VzIGN1YWRyYWRhcyoqLCBwYXJhIG1lam9yYXIgbGEgbm9ybWFsaWRhZCBkZSBsb3MgcmVzaWR1b3MuIFBhcmEgY29uZmlybWFyIGVzdGFzIG9ic2VydmFjaW9uZXMsIHNlIHJlYWxpemFuICoqcHJ1ZWJhcyBkZSBub3JtYWxpZGFkIHkgaG9tb2NlZGFzdGljaWRhZCoqLCBjb24gZWwgZmluIGRlIGV2YWx1YXIgc2kgbG9zIHJlc2lkdW9zIHNpZ3VlbiBlZmVjdGl2YW1lbnRlIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbCB5IHNpIGxhICoqdmFyaWFuemEgZGUgbG9zIGVycm9yZXMgc2UgbWFudGllbmUgY29uc3RhbnRlKiogYSBsbyBsYXJnbyBkZSBsb3MgdmFsb3JlcyBhanVzdGFkb3MuDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcmF0ZG9yX3NoYXBpcm9fdGVzdH0NCg0KIyBQcnVlYmEgZGUgbm9ybWFsaWRhZCBkZSBTaGFwaXJvLVdpbGsNCnNoYXBpcm9fdGVzdF9wbF9yYXRkb3IgPC0gc2hhcGlyby50ZXN0KHJlc19wbF9yYXRkb3IpDQoNCnNoYXBpcm9fdGVzdF9wbF9yYXRkb3INCg0KYGBgDQoNCkxhICoqcHJ1ZWJhIGRlIFNoYXBpcm8tV2lsayoqIGVzIHVuYSBoZXJyYW1pZW50YSBlc3RhZMOtc3RpY2EgdXRpbGl6YWRhIHBhcmEgZGV0ZXJtaW5hciBzaSB1biBjb25qdW50byBkZSBkYXRvcyBzaWd1ZSB1bmEgKipkaXN0cmlidWNpw7NuIG5vcm1hbCoqLiBFbiBlc3RlIGFuw6FsaXNpcywgc2UgYXBsaWPDsyBhIGxvcyByZXNpZHVvcyBkZWwgbW9kZWxvIHBhcmEgZXZhbHVhciBzaSBjdW1wbGVuIGNvbiBlc3RhIHN1cG9zaWNpw7NuIGZ1bmRhbWVudGFsIGVuIGxhIHJlZ3Jlc2nDs24gbGluZWFsLg0KDQpFc3RhIHBydWViYSBwYXJ0ZSBkZSBsYSAqKmhpcMOzdGVzaXMgbnVsYSAoSOKCgCkqKiwgcXVlIGVzdGFibGVjZSBxdWUgbG9zIHJlc2lkdW9zIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuIFNpIGVsIHJlc3VsdGFkbyBtdWVzdHJhIHVuICoqcC12YWxvciBtdXkgYmFqbyoqLCBzZSByZWNoYXphIGVzdGEgaGlww7N0ZXNpcywgaW5kaWNhbmRvIHF1ZSBsb3MgZGF0b3Mgbm8gc2UgYWp1c3RhbiBhIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbC4NCg0KRWwgcmVzdWx0YWRvIGRlIGxhIHBydWViYSBhcnJvasOzIHVuICoqZXN0YWTDrXN0aWNvIFcgZGUgMC44MTUzNCoqLCBsbyBxdWUgc3VnaWVyZSB1bmEgZGVzdmlhY2nDs24gY29uc2lkZXJhYmxlIGRlIGxhIG5vcm1hbGlkYWQsIHlhIHF1ZSB1biB2YWxvciBjZXJjYW5vIGEgKioxKiogaW5kaWNhcsOtYSBxdWUgbG9zIGRhdG9zIHNlIGRpc3RyaWJ1eWVuIGRlIG1hbmVyYSBub3JtYWwuIEFkZW3DoXMsIGVsICoqcC12YWxvciBvYnRlbmlkbyBmdWUgYXByb3hpbWFkYW1lbnRlIDAuMDAwMDAwMDEzMTMqKiwgbG8gcXVlIGVzIHNpZ25pZmljYXRpdmFtZW50ZSBtZW5vciBhICoqMC4wNSoqLiBFc3RvIHByb3BvcmNpb25hIHN1ZmljaWVudGUgZXZpZGVuY2lhIHBhcmEgcmVjaGF6YXIgbGEgaGlww7N0ZXNpcyBudWxhIGNvbiB1biBhbHRvIG5pdmVsIGRlIGNvbmZpYW56YSwgY29uZmlybWFuZG8gcXVlIGxvcyByZXNpZHVvcyAqKm5vIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwqKi4NCg0KRXN0ZSByZXN1bHRhZG8gZXMgcmVsZXZhbnRlIHBvcnF1ZSBsYSBmYWx0YSBkZSBub3JtYWxpZGFkIGVuIGxvcyByZXNpZHVvcyBwdWVkZSBhZmVjdGFyIGxhIHZhbGlkZXogZGUgbG9zICoqaW50ZXJ2YWxvcyBkZSBjb25maWFuemEqKiB5IGxvcyAqKnZhbG9yZXMgcCoqIGVuIGxhIHJlZ3Jlc2nDs24uIFBhcmEgY29ycmVnaXIgZXN0ZSBwcm9ibGVtYSwgcG9kcsOtYSBzZXIgbmVjZXNhcmlvIGFwbGljYXIgdHJhbnNmb3JtYWNpb25lcyBhIGxvcyBkYXRvcyBvIGNvbnNpZGVyYXIgZWwgdXNvIGRlIG3DqXRvZG9zIGVzdGFkw61zdGljb3MgbcOhcyByb2J1c3RvcyBxdWUgbm8gZGVwZW5kYW4gZXN0cmljdGFtZW50ZSBkZSBsYSBub3JtYWxpZGFkIGRlIGxvcyByZXNpZHVvcy4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF9yYXRkb3JfYnBfdGVzdH0NCg0KIyBQcnVlYmEgZGUgaG9tb2NlZGFzdGljaWRhZCBkZSBCcmV1c2NoLVBhZ2FuDQpsaWJyYXJ5KGxtdGVzdCkNCg0KIyBQcnVlYmEgZGUgQnJldXNjaC1QYWdhbg0KYnBfdGVzdF9wbF9yYXRkb3IgPC0gYnB0ZXN0KG1vZGVsX3BsX3JhdGRvcikNCg0KYnBfdGVzdF9wbF9yYXRkb3INCg0KYGBgDQoNCkVsICoqdGVzdCBkZSBCcmV1c2NoLVBhZ2FuKiogZXMgdW5hIHBydWViYSBlc3RhZMOtc3RpY2EgdXRpbGl6YWRhIHBhcmEgZXZhbHVhciBzaSBsb3MgcmVzaWR1b3MgZGVsIG1vZGVsbyBwcmVzZW50YW4gKipob21vY2VkYXN0aWNpZGFkKiogKHZhcmlhbnphIGNvbnN0YW50ZSkgbyAqKmhldGVyb2NlZGFzdGljaWRhZCoqICh2YXJpYW56YSBubyBjb25zdGFudGUpLiBMYSBwcnVlYmEgcGFydGUgZGUgbGEgKipoaXDDs3Rlc2lzIG51bGEqKiwgcXVlIGFzdW1lIHF1ZSBsb3MgcmVzaWR1b3MgdGllbmVuIHVuYSB2YXJpYW56YSBjb25zdGFudGUuIFNpIHNlIGVuY3VlbnRyYSBzdWZpY2llbnRlIGV2aWRlbmNpYSBwYXJhIHJlY2hhemFyIGVzdGEgaGlww7N0ZXNpcywgc2UgY29uY2x1eWUgcXVlIGV4aXN0ZSBoZXRlcm9jZWRhc3RpY2lkYWQgZW4gZWwgbW9kZWxvLg0KDQpFbiBlc3RlIGFuw6FsaXNpcywgZWwgKiplc3RhZMOtc3RpY28gZGUgbGEgcHJ1ZWJhIChCUCkqKiBvYnR1dm8gdW4gdmFsb3IgZGUgKioxLjEzMDYqKiwgZWwgY3VhbCBlcyByZWxhdGl2YW1lbnRlIGJham8uIFVuIHZhbG9yIGFsdG8gZGUgZXN0ZSBlc3RhZMOtc3RpY28gaW5kaWNhcsOtYSBsYSBwcmVzZW5jaWEgZGUgaGV0ZXJvY2VkYXN0aWNpZGFkLCBwZXJvIGVuIGVzdGUgY2FzbyBubyBzZSBvYnNlcnZhIHVuYSBzZcOxYWwgY2xhcmEgZGUgZWxsby4gRGFkbyBxdWUgc29sbyBzZSB1dGlsaXphIHVuIHByZWRpY3RvciwgbGEgcHJ1ZWJhIHNlIGJhc2EgZW4gKip1biBncmFkbyBkZSBsaWJlcnRhZCAoZGYgPSAxKSoqLiBBZGVtw6FzLCBlbCAqKnAtdmFsb3Igb2J0ZW5pZG8gZnVlIGRlIDAuMjg3NioqLCBsbyBxdWUgZXMgc3VwZXJpb3IgYWwgdW1icmFsIGRlICoqMC4wNSoqLiBFc3RvIHNpZ25pZmljYSBxdWUgbm8gaGF5IHN1ZmljaWVudGUgZXZpZGVuY2lhIGVzdGFkw61zdGljYSBwYXJhIHJlY2hhemFyIGxhIGhpcMOzdGVzaXMgbnVsYSwgbG8gcXVlIHN1Z2llcmUgcXVlICoqbm8gc2UgZGV0ZWN0YSBoZXRlcm9jZWRhc3RpY2lkYWQgc2lnbmlmaWNhdGl2YSBlbiBsb3MgcmVzaWR1b3MqKi4NCg0KQSBwZXNhciBkZSBlc3RvLCBlbCBtb2RlbG8gbm8gcGFyZWNlIGFqdXN0YXJzZSBiaWVuIGEgbG9zIGRhdG9zLCB5YSBxdWUgc2Ugb2JzZXJ2YSB1bmEgZ3JhbiBkaXNwZXJzacOzbiBlbiBsb3MgcmVzaWR1b3MgeSBsYSBwb3NpYmxlIHByZXNlbmNpYSBkZSBoZXRlcm9jZWRhc3RpY2lkYWQgZW4gY2llcnRvcyByYW5nb3MgZGUgbG9zIHZhbG9yZXMgYWp1c3RhZG9zLiBQYXJhIG1lam9yYXIgZWwgbW9kZWxvLCBzZSBleHBsb3JhbiBwb3NpYmxlcyAqKnRyYW5zZm9ybWFjaW9uZXMgZW4gbGEgdmFyaWFibGUgZGVwZW5kaWVudGUqKiwgY29tbyBsYSBhcGxpY2FjacOzbiBkZSBsb2dhcml0bW9zLiBBZGVtw6FzLCBzZSBhbmFsaXphIHNpIHVuYSAqKnRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EgZW4gbGFzIHZhcmlhYmxlcyBwcmVkaWN0b3JhcyoqIHBvZHLDrWEgbWVqb3JhciBsYSBjYXBhY2lkYWQgcHJlZGljdGl2YSBkZWwgbW9kZWxvLCB1dGlsaXphbmRvIHBhcmEgZWxsbyBsYSAqKnBydWViYSBkZSBCb3gtQ294KiosIHF1ZSBwZXJtaXRlIGRldGVybWluYXIgbGEgbWVqb3IgdHJhbnNmb3JtYWNpw7NuIHBhcmEgZXN0YWJpbGl6YXIgbGEgdmFyaWFuemEgeSBtZWpvcmFyIGVsIGFqdXN0ZSBkZWwgbW9kZWxvLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3JhdGRvcl9ib3hjb3gsIHdhcm5pbmc9RkFMU0V9DQoNCiMgUHJ1ZWJhIGRlIEJveC1Db3ggcGFyYSB0cmFuc2Zvcm1hciBsYSB2YXJpYWJsZSBzdF9yYWQNCmxpYnJhcnkoTUFTUykNCg0KIyBQcnVlYmEgZGUgQm94LUNveA0KYm94Y294X3BsX3JhdGRvciA8LSBib3hjb3gobW9kZWxfcGxfcmF0ZG9yLCBsYW1iZGEgPSBzZXEoLTIsIDIsIGJ5ID0gMC4xKSkNCg0KYGBgDQoNCkxhICoqdHJhbnNmb3JtYWNpw7NuIGRlIEJveC1Db3gqKiBlcyB1bmEgdMOpY25pY2EgdXRpbGl6YWRhIGVuIG1vZGVsb3MgZGUgcmVncmVzacOzbiBwYXJhIGVuY29udHJhciBsYSBtZWpvciBtYW5lcmEgZGUgdHJhbnNmb3JtYXIgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUsIGNvbiBlbCBmaW4gZGUgbWVqb3JhciBsYSAqKm5vcm1hbGlkYWQgZGUgbG9zIHJlc2lkdW9zKiogeSBnYXJhbnRpemFyIHVuYSAqKnZhcmlhbnphIGNvbnN0YW50ZSoqIChob21vY2VkYXN0aWNpZGFkKS4NCg0KTGEgZ3LDoWZpY2EgZ2VuZXJhZGEgZW4gZXN0ZSBhbsOhbGlzaXMgbXVlc3RyYSBjw7NtbyB2YXLDrWEgbGEgKipsb2ctdmVyb3NpbWlsaXR1ZCoqIGVuIGZ1bmNpw7NuIGRlbCAqKnBhcsOhbWV0cm8gbGFtYmRhKiosIGVsIGN1YWwgZGV0ZXJtaW5hIGxhIGZvcm1hIGRlIGxhIHRyYW5zZm9ybWFjacOzbiBhcGxpY2FkYSBhIGxhIHZhcmlhYmxlIGRlcGVuZGllbnRlICoqWSoqLiBEZXBlbmRpZW5kbyBkZWwgdmFsb3IgZGUgKipsYW1iZGEqKiwgbGEgdHJhbnNmb3JtYWNpw7NuIHB1ZWRlIHNlciB1bmEgcmHDrXogY3VhZHJhZGEsIHVuIGxvZ2FyaXRtbywgdW5hIGludmVyc2EsIGVudHJlIG90cmFzLCBheXVkYW5kbyBhIGVzdGFiaWxpemFyIGxhIHZhcmlhbnphIHkgbWVqb3JhciBlbCBhanVzdGUgZGVsIG1vZGVsby4NCg0KJCQNClknID0gDQpcYmVnaW57Y2FzZXN9DQpcZnJhY3tZXlxsYW1iZGEgLSAxfXtcbGFtYmRhfSwgJiBcbGFtYmRhIFxuZXEgMCBcXA0KXGxvZyhZKSwgJiBcbGFtYmRhID0gMA0KXGVuZHtjYXNlc30NCiQkDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcmF0ZG9yX2JveGNveF9vcHRpbWFsX2xhbWJkYSwgd2FybmluZz1GQUxTRX0NCg0KIyBPYnRlbmVyIGVsIGxhbWJkYSDDs3B0aW1vDQpsYW1iZGFfb3B0aW1hbCA8LSBib3hjb3hfcGxfcmF0ZG9yJHhbd2hpY2gubWF4KGJveGNveF9wbF9yYXRkb3IkeSldDQoNCmxhbWJkYV9vcHRpbWFsDQoNCmBgYA0KDQpFbCB2YWxvciDDs3B0aW1vIGRlbCBwYXLDoW1ldHJvICoqbGFtYmRhKiogb2J0ZW5pZG8gZW4gbGEgdHJhbnNmb3JtYWNpw7NuIGRlICoqQm94LUNveCoqIGVzICoqLTAuMDIwMioqLCBsbyBxdWUgaW5kaWNhIHF1ZSBsYSBtZWpvciB0cmFuc2Zvcm1hY2nDs24gcGFyYSBsYSB2YXJpYWJsZSAqKmBwbF9yYXRkb3JgKiogZXMgY2VyY2FuYSBhICoqMCoqLiBEYWRvIHF1ZSB1biAqKmxhbWJkYSBkZSAwKiogY29ycmVzcG9uZGUgYSB1bmEgKip0cmFuc2Zvcm1hY2nDs24gbG9nYXLDrXRtaWNhKiosIGFwbGljYXIgZWwgbG9nYXJpdG1vIGEgZXN0YSB2YXJpYWJsZSBwb2Ryw61hIG1lam9yYXIgbGEgY2FwYWNpZGFkIHByZWRpY3RpdmEgZGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCg0KUGFyYSB2ZXJpZmljYXIgc2kgZXN0YSB0cmFuc2Zvcm1hY2nDs24gcmVhbG1lbnRlIG1lam9yYSBlbCBhanVzdGUgZGVsIG1vZGVsbywgc2UgbGxldmEgYSBjYWJvIHVuYSBudWV2YSAqKnJlZ3Jlc2nDs24gbGluZWFsIHV0aWxpemFuZG8gbGEgdmFyaWFibGUgdHJhbnNmb3JtYWRhKiouIEx1ZWdvLCBzZSBldmFsw7phIGVsIGRlc2VtcGXDsW8gZGVsIG1vZGVsbyBhY3R1YWxpemFkbywgYW5hbGl6YW5kbyBtw6l0cmljYXMgY29tbyBlbCAqKlLCsioqLCBsb3MgKipyZXNpZHVvcyoqIHkgbGEgKipzaWduaWZpY2FuY2lhIGRlIGxvcyBjb2VmaWNpZW50ZXMqKiBwYXJhIGRldGVybWluYXIgc2kgbGEgcHJlZGljY2nDs24gZGUgKipgcGxfcmFkamAqKiBtZWpvcmEgY29uIGxhIG51ZXZhIHRyYW5zZm9ybWFjacOzbi4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF9yYXRkb3JfbG9nLCB3YXJuaW5nPUZBTFNFfQ0KDQojIFJlZ3Jlc2nDs24gZGUgcGxfcmFkaiBjb24gbG9nKHBsX3JhdGRvcikgDQptb2RlbF9wbF9yYXRkb3JfbG9nIDwtIGxtKHBsX3JhZGogfiBsb2cocGxfcmF0ZG9yKSwgZGF0YSA9IGtlcGxlcl9kYXRhX251bSkNCg0KbW9kZWxfcGxfcmF0ZG9yX2xvZ19zdW1tYXJ5IDwtIHN1bW1hcnkobW9kZWxfcGxfcmF0ZG9yX2xvZykNCg0KbW9kZWxfcGxfcmF0ZG9yX2xvZ19zdW1tYXJ5DQoNCmBgYA0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3JhdGRvcl9sb2dfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBTY2F0dGVyIHBsb3QgZGUgcGxfcmFkaiB2cyBsb2cocGxfcmF0ZG9yKSBjb24gbGEgcmVjdGEgZGUgcmVncmVzacOzbiBlbiByb2pvDQojIHkgbG9zIG1hcmdlbmVzIGRlIGNvbmZpYW56YSBlbiBncmlzDQpnZ3Bsb3Qoa2VwbGVyX2RhdGFfbnVtLCBhZXMoeCA9IGxvZyhwbF9yYXRkb3IpLCB5ID0gcGxfcmFkaikpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gImluZGlhbnJlZCIsIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC4yKSArDQogIGxhYnModGl0bGUgPSAiUmVncmVzacOzbiBMaW5lYWw6IFJhZGlvIGRlbCBFeG9wbGFuZXRhIHNlZ3VuIExvZ2FyaXRtbyBkZWwgUmF0aW8gc29icmUgZWwgUmFkaW8gRXN0ZWxhciIsDQogICAgICAgeCA9ICJMb2dhcml0bW8gZGVsIFJhdGlvIHNvYnJlIFJhZGlvIEVzdGVsYXIiLA0KICAgICAgIHkgPSAiUmFkaW8gZGVsIEV4b3BsYW5ldGEgKErDunBpdGVyKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpFbCBtb2RlbG8gYWp1c3RhZG8gY29uIGxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EgZGUgKipgcGxfcmF0ZG9yYCoqIG11ZXN0cmEgcmVzdWx0YWRvcyBtdXkgc2ltaWxhcmVzIGFsIG1vZGVsbyBvcmlnaW5hbCwgbG8gcXVlIGluZGljYSBxdWUgbGEgdHJhbnNmb3JtYWNpw7NuICoqbm8gbWVqb3LDsyBzaWduaWZpY2F0aXZhbWVudGUgbGEgY2FwYWNpZGFkIHByZWRpY3RpdmEqKi4gRWwgKiplcnJvciBlc3TDoW5kYXIgZGUgbG9zIHJlc2lkdW9zKiogZXMgKiowLjM4NzYqKiwgcHLDoWN0aWNhbWVudGUgaWTDqW50aWNvIGFsIGRlbCBtb2RlbG8gc2luIHRyYW5zZm9ybWFjacOzbiAoKiowLjM4NzIqKiksIGxvIHF1ZSBzdWdpZXJlIHF1ZSBsYSB2YXJpYWJpbGlkYWQgZGUgbG9zIHJlc2lkdW9zIHNpZ3VlIHNpZW5kbyBsYSBtaXNtYS4NCg0KRWwgY29lZmljaWVudGUgZGUgZGV0ZXJtaW5hY2nDs24gKipSwrIgbcO6bHRpcGxlKiogZXMgKiowLjAyNDIxICgyLjQlKSoqLCBsbyBxdWUgc2lnbmlmaWNhIHF1ZSBzb2xvIHVuICoqMi40JSBkZSBsYSB2YXJpYWJpbGlkYWQgZGUgYHBsX3JhZGpgKiogZXMgZXhwbGljYWRhIHBvciAqKmBsb2cocGxfcmF0ZG9yKWAqKiwgdW4gdmFsb3IgZXh0cmVtYWRhbWVudGUgYmFqby4gSW5jbHVzbyBhbCBhanVzdGFyIHBvciBlbCBuw7ptZXJvIGRlIHByZWRpY3RvcmVzLCBlbCAqKlLCsiBhanVzdGFkbyoqIGFwZW5hcyBtZWpvcmEsIHF1ZWRhbmRvIGVuICoqMS4yJSoqLCBsbyBxdWUgcmVmdWVyemEgbGEgaWRlYSBkZSBxdWUgZWwgbW9kZWxvIHNpZ3VlIHNpbiBjYXB0dXJhciBiaWVuIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzLg0KDQpFbCAqKmVzdGFkw61zdGljbyBGKiosIGNvbiB1biB2YWxvciBkZSAqKjEuOTM1KiogeSB1biAqKnAtdmFsb3IgZGUgMC4xNjgxKiosIGluZGljYSBxdWUgbm8gaGF5IHN1ZmljaWVudGUgZXZpZGVuY2lhIGVzdGFkw61zdGljYSBwYXJhIGFmaXJtYXIgcXVlIGxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EgZGUgKipgcGxfcmF0ZG9yYCoqIG1lam9yYSBzaWduaWZpY2F0aXZhbWVudGUgZWwgbW9kZWxvLg0KDQpFbiBjb25jbHVzacOzbiwgZWwgbW9kZWxvIHNpZ3VlIHNpbiBzZXIgYWRlY3VhZG8gcGFyYSBwcmVkZWNpciAqKmBwbF9yYWRqYCoqIGEgcGFydGlyIGRlICoqYHBsX3JhdGRvcmAqKiwgaW5jbHVzbyBkZXNwdcOpcyBkZSBhcGxpY2FyIGxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EuIEFudGUgZXN0b3MgcmVzdWx0YWRvcywgc2UgcHJvY2VkZSBhIHByb2JhciBjb24gKipvdHJhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgbyBjb21iaW5hY2lvbmVzIGRlIHZhcmlhYmxlcyoqIHBhcmEgbWVqb3JhciBsYSBjYXBhY2lkYWQgZGUgYWp1c3RlIGRlbCBtb2RlbG8uDQoNCiMjIyBSZWdyZXNpw7NuIGxpbmVhbDogcmFkaW8gZGVsIGV4b3BsYW5ldGEgc2Vnw7puIGxhIHByb2Z1bmRpZGFkIGRlbCB0csOhbnNpdG8gKGBwbF90cmFuZGVwYCkNCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwfQ0KDQojIFJlZ3Jlc2lvbiBkZWwgcmFkaW8gZGVsIGV4cGxvcGxhbmV0YSAocGxfcmFkaikgDQojIGNvbiBsYSBwcm9mdW5kaWRhZCBkZWwgdHLDoW5zaXRvIGRlbCBwbGFuZXRhIChwbF90cmFuZGVwKQ0KIyBjb21vIHByZWRpY3Rvcg0KbW9kZWxfcGxfdHJhbmRlcCA8LSBsbShwbF9yYWRqIH4gcGxfdHJhbmRlcCwgZGF0YSA9IGtlcGxlcl9kYXRhX251bSkNCg0KbW9kZWxfcGxfdHJhbmRlcF9zdW1tYXJ5IDwtIHN1bW1hcnkobW9kZWxfcGxfdHJhbmRlcCkNCg0KbW9kZWxfcGxfdHJhbmRlcF9zdW1tYXJ5DQoNCmBgYA0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3RyYW5kZXBfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBTY2F0dGVyIHBsb3QgZGUgcGxfcmFkaiB2cyBwbF90cmFuZGVwIGNvbiBsYSByZWN0YSBkZSByZWdyZXNpw7NuIGVuIHJvam8NCiMgeSBsb3MgbWFyZ2VuZXMgZGUgY29uZmlhbnphIGVuIGdyaXMNCmdncGxvdChrZXBsZXJfZGF0YV9udW0sIGFlcyh4ID0gcGxfdHJhbmRlcCwgeSA9IHBsX3JhZGopKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJpbmRpYW5yZWQiLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMikgKw0KICBsYWJzKHRpdGxlID0gIlJlZ3Jlc2nDs24gTGluZWFsOiBSYWRpbyBkZWwgRXhvcGxhbmV0YSB2cyBQcm9mdW5kaWRhZCBkZWwgVHLDoW5zaXRvIiwNCiAgICAgICB4ID0gIlByb2Z1bmRpZGFkIGRlbCBUcsOhbnNpdG8gKCUpIiwNCiAgICAgICB5ID0gIlJhZGlvIGRlbCBFeG9wbGFuZXRhIChKw7pwaXRlcikiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KRW4gZWwgbW9kZWxvOg0KDQokJA0KcGxcX3JhZGogPSBcYmV0YV8wICsgXGJldGFfMSBcY2RvdCBwbFxfdHJhbmRlcCArIFx2YXJlcHNpbG9uDQokJA0KDQpDYWRhIGF1bWVudG8gdW5pdGFyaW8gZW4gKipgcGxfdHJhbmRlcGAqKiBzZSBhc29jaWEgY29uIHVuIGluY3JlbWVudG8gZGUgMC42MTA1OCBlbiAqKmBwbF9yYWRqYCoqLiBBZGVtw6FzIGVzIGFsdGFtZW50ZSBzaWduaWZpY2F0aXZvIChjb24gcC12YWx1ZSBcPCAwLjAwMDAwMDAwMDAwMDAwMDIyKSwgbG8gcXVlIGluZGljYSB1bmEgZnVlcnRlIHJlbGFjacOzbiBlbnRyZSAqKmBwbF90cmFuZGVwYCoqIHkgKipgcGxfcmFkamAqKi4gQWRlbcOhczogRWwgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gcGxhbnRlYWRvIHBhcmEgcHJlZGVjaXIgKipgcGxfcmFkamAqKiBlbiBmdW5jacOzbiBkZSAqKmBwbF90cmFuZGVwYCoqIG11ZXN0cmEgdW5hIHJlbGFjacOzbiBjbGFyYSB5IHNpZ25pZmljYXRpdmEgZW50cmUgYW1iYXMgdmFyaWFibGVzLiBFbiBlc3RlIGNhc28sICoqcG9yIGNhZGEgYXVtZW50byB1bml0YXJpbyBlbiBgcGxfdHJhbmRlcGAqKiwgc2Ugb2JzZXJ2YSB1biAqKmluY3JlbWVudG8gZGUgMC42MTA1OCBlbiBgcGxfcmFkamAqKi4gQWRlbcOhcywgZXN0YSByZWxhY2nDs24gZXMgYWx0YW1lbnRlIHNpZ25pZmljYXRpdmEsIGNvbiB1biAqKnAtdmFsb3IgZXh0cmVtYWRhbWVudGUgYmFqbyoqIChcPCAyLjIgw5cgMTDigbvCueKBtiksIGxvIHF1ZSBpbmRpY2EgcXVlIGhheSB1bmEgZnVlcnRlIGNvbmV4acOzbiBlbnRyZSBhbWJhcyB2YXJpYWJsZXMuDQoNCkVsIG1vZGVsbyBwcmVzZW50YSB1biAqKmVycm9yIGVzdMOhbmRhciBkZSBsb3MgcmVzaWR1b3MgZGUgMC4wODMxNSoqLCBsbyBxdWUgc3VnaWVyZSBxdWUgbGEgdmFyaWFiaWxpZGFkIGVuIGxhcyBwcmVkaWNjaW9uZXMgZXMgbXV5IGJhamEgeSwgcG9yIGxvIHRhbnRvLCBlbCBhanVzdGUgZGVsIG1vZGVsbyBlcyBiYXN0YW50ZSBwcmVjaXNvLiBBZGVtw6FzLCBlbCAqKmNvZWZpY2llbnRlIGRlIGRldGVybWluYWNpw7NuIFLCsioqIGFsY2FuemEgdW4gKio5NC4wMiUqKiwgbG8gcXVlIHNpZ25pZmljYSBxdWUgZWwgbW9kZWxvIGV4cGxpY2EgKipjYXNpIHRvZGEgbGEgdmFyaWFiaWxpZGFkKiogZGUgKipgcGxfcmFkamAqKi4gSW5jbHVzbyBlbCAqKlLCsiBhanVzdGFkbyoqLCBxdWUgY29ycmlnZSBwb3IgZWwgbsO6bWVybyBkZSBwcmVkaWN0b3Jlcywgc2lndWUgc2llbmRvICoqbXV5IGFsdG8gKDkzLjg3JSkqKiwgbG8gcXVlIGNvbmZpcm1hIGxhIHNvbGlkZXogZGVsIGFqdXN0ZS4NCg0KTGEgcHJ1ZWJhIGRlICoqc2lnbmlmaWNhbmNpYSBnbG9iYWwgZGVsIG1vZGVsbyoqLCBldmFsdWFkYSBjb24gZWwgKiplc3RhZMOtc3RpY28gRioqLCBhcnJvamEgdW4gdmFsb3IgZGUgKio2MjkuMSoqIGNvbiB1biAqKnAtdmFsb3IgZXh0cmVtYWRhbWVudGUgYmFqbyoqLCBsbyBxdWUgcmVmdWVyemEgbGEgdmFsaWRleiBkZWwgbW9kZWxvIHkgc3UgY2FwYWNpZGFkIHBhcmEgZXhwbGljYXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyB2YXJpYWJsZXMuDQoNCkVuIGNvbXBhcmFjacOzbiBjb24gbG9zIG1vZGVsb3MgYW50ZXJpb3JlcyAoKipgcGxfcmFkaiB+IHBsX3JhdGRvcmAqKiB5ICoqYHBsX3JhZGogfiBsb2cocGxfcmF0ZG9yKWAqKiksIGVzdGUgbnVldm8gbW9kZWxvIG11ZXN0cmEgdW5hIG1lam9yYSAqKmRyw6FzdGljYSoqIGVuIGVsIGFqdXN0ZSwgY29uIHVuYSBjYXBhY2lkYWQgZXhwbGljYXRpdmEgbXVjaG8gbWF5b3IuIExhIHJlbGFjacOzbiBlbnRyZSAqKmBwbF90cmFuZGVwYCoqIHkgKipgcGxfcmFkamAqKiBubyBzb2xvIGVzIGZ1ZXJ0ZSwgc2lubyBxdWUgdGFtYmnDqW4gZXMgZXN0YWTDrXN0aWNhbWVudGUgKiptdXkgc2lnbmlmaWNhdGl2YSoqLCBsbyBxdWUgaW5kaWNhIHF1ZSAqKmBwbF90cmFuZGVwYCoqIGVzIHVuIGV4Y2VsZW50ZSBwcmVkaWN0b3IgZGVsIHJhZGlvIGRlbCBleG9wbGFuZXRhLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3RyYW5kZXBfcmVzX3Bsb3QsIHdhcm5pbmc9RkFMU0V9DQoNCiMgT2J0ZW5lciBsb3MgcmVzaWR1b3MgeSB2YWxvcmVzIGFqdXN0YWRvcw0KcmVzX3BsX3RyYW5kZXAgPC0gcmVzaWR1YWxzKG1vZGVsX3BsX3RyYW5kZXApDQoNCiMgQ2FsY3VsYXIgbG9zIHZhbG9yZXMgYWp1c3RhZG9zDQpmaXRfdmFsX3BsX3RyYW5kZXAgPC0gZml0dGVkKG1vZGVsX3BsX3RyYW5kZXApDQoNCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZSBjb24gbG9zIHJlc2lkdW9zIHkgdmFsb3JlcyBhanVzdGFkb3MNCnJlc19wbF90cmFuZGVwX2RmIDwtIGRhdGEuZnJhbWUoDQogIFJlc2lkdWFscyA9IHJlc19wbF90cmFuZGVwLA0KICBGaXR0ZWRfVmFsdWVzID0gZml0X3ZhbF9wbF90cmFuZGVwDQopDQoNCiMgU2NhdHRlciBwbG90IGRlIHJlc2lkdW9zIHZzIHZhbG9yZXMgYWp1c3RhZG9zDQpnZ3Bsb3QocmVzX3BsX3RyYW5kZXBfZGYsIGFlcyh4ID0gRml0dGVkX1ZhbHVlcywgeSA9IFJlc2lkdWFscykpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gImluZGlhbnJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJSZXNpZHVvcyB2cyBWYWxvcmVzIEFqdXN0YWRvcyIsDQogICAgICAgeCA9ICJWYWxvcmVzIEFqdXN0YWRvcyIsDQogICAgICAgeSA9ICJSZXNpZHVvcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpFbCBncsOhZmljbyBkZSAqKnJlc2lkdW9zIHZzIHZhbG9yZXMgYWp1c3RhZG9zKiogcmV2ZWxhIHVuIHBhdHLDs24gZW4gbGEgZGlzcGVyc2nDs24gZGUgbG9zIHJlc2lkdW9zLiBQYXJhIHZhbG9yZXMgYWp1c3RhZG9zIGJham9zLCBsb3MgcmVzaWR1b3MgdGllbmRlbiBhIGFncnVwYXJzZSBjZXJjYSBkZSAqKjAqKiwgbG8gcXVlIGluZGljYSB1bmEgbWVub3IgdmFyaWFiaWxpZGFkIGVuIGVzdGEgcmVnacOzbi4gU2luIGVtYmFyZ28sIGEgbWVkaWRhIHF1ZSBsb3MgdmFsb3JlcyBhanVzdGFkb3MgYXVtZW50YW4sIGxvcyByZXNpZHVvcyBzZSBkaXNwZXJzYW4gbcOhcywgc3VnaXJpZW5kbyBxdWUgZWwgZXJyb3IgZGVsIG1vZGVsbyBubyBlcyB1bmlmb3JtZSBlbiB0b2RvIGVsIHJhbmdvIGRlIHByZWRpY2Npb25lcy4NCg0KRXN0ZSBjb21wb3J0YW1pZW50byBzdWdpZXJlIGxhIHByZXNlbmNpYSBkZSAqKmhldGVyb2NlZGFzdGljaWRhZCoqLCB5YSBxdWUgbGEgZGlzcGVyc2nDs24gZGUgbG9zIHJlc2lkdW9zIHBhcmVjZSBzZWd1aXIgdW4gKipwYXRyw7NuIGRlIHBhcsOhYm9sYSBpbnZlcnRpZGEqKiwgY29uIHVuYSBtYXlvciB2YXJpYWJpbGlkYWQgZW4gbG9zIHZhbG9yZXMgYWp1c3RhZG9zIG3DoXMgYWx0b3MuIExhICoqaGV0ZXJvY2VkYXN0aWNpZGFkKiogb2N1cnJlIGN1YW5kbyBsYSB2YXJpYW56YSBkZSBsb3MgZXJyb3JlcyBubyBlcyBjb25zdGFudGUsIGxvIHF1ZSBwdWVkZSBhZmVjdGFyIGxhIGZpYWJpbGlkYWQgZGUgbGFzIGluZmVyZW5jaWFzIGVzdGFkw61zdGljYXMgZGVsIG1vZGVsby4gUGFyYSBjb25maXJtYXIgc2kgZXN0ZSBwcm9ibGVtYSBlc3TDoSBwcmVzZW50ZSwgc2UgcHVlZGUgcmVhbGl6YXIgZWwgKip0ZXN0IGRlIEJyZXVzY2gtUGFnYW4qKiwgcXVlIGV2YWzDumEgc2kgbGEgdmFyaWFuemEgZGUgbG9zIHJlc2lkdW9zIGNhbWJpYSBzaXN0ZW3DoXRpY2FtZW50ZSBjb24gbG9zIHZhbG9yZXMgYWp1c3RhZG9zLg0KDQpFbiB1biBtb2RlbG8gYmllbiBlc3BlY2lmaWNhZG8sIGxvcyByZXNpZHVvcyBkZWJlcsOtYW4gZGlzdHJpYnVpcnNlICoqZGUgbWFuZXJhIGFsZWF0b3JpYSoqIGFscmVkZWRvciBkZSBsYSBsw61uZWEgZGUgcmVmZXJlbmNpYSAqKih5PTApKiosIHNpbiBtb3N0cmFyIHBhdHJvbmVzIGNsYXJvcy4gU2luIGVtYmFyZ28sIGVuIGVzdGUgY2Fzbywgc2Ugb2JzZXJ2YSB1bmEgbWF5b3IgY29uY2VudHJhY2nDs24gZGUgcHVudG9zIGVuIGxhIHBhcnRlIGl6cXVpZXJkYSBkZWwgZ3LDoWZpY28sIGxvIHF1ZSBzdWdpZXJlIHF1ZSBlbCBtb2RlbG8gcG9kcsOtYSBubyBlc3RhciBjYXB0YW5kbyBjb21wbGV0YW1lbnRlIGxhIHJlbGFjacOzbiBlbnRyZSAqKmBwbF9yYWRqYCoqIHkgKipgcGxfdHJhbmRlcGAqKi4gRXN0ZSBjb21wb3J0YW1pZW50byBpbmRpY2EgcXVlIGVsIG1vZGVsbyBwb2Ryw61hIGJlbmVmaWNpYXJzZSBkZSB1bmEgcmV2aXNpw7NuLCBjb21vIGxhIGluY2x1c2nDs24gZGUgbnVldmFzIHZhcmlhYmxlcyBleHBsaWNhdGl2YXMgbyBsYSBhcGxpY2FjacOzbiBkZSB0cmFuc2Zvcm1hY2lvbmVzIHBhcmEgbWVqb3JhciBsYSBlc3RhYmlsaWRhZCBkZSBsYSB2YXJpYW56YSBkZSBsb3MgZXJyb3Jlcy4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwX3FxX3Bsb3QsIHdhcm5pbmc9RkFMU0V9DQoNCiMgQ3JlYXIgdW4gZ3LDoWZpY28gUS1RIGRlIGxvcyByZXNpZHVvcw0KcXFub3JtKHJlc19wbF90cmFuZGVwLCBtYWluID0gIkdyw6FmaWNvIFEtUSBkZSBsb3MgUmVzaWR1b3MiLCBjb2w9ImluZGlhbnJlZCIpDQoNCmBgYA0KDQpFbCAqKmdyw6FmaWNvIFEtUSAoUXVhbnRpbGUtUXVhbnRpbGUpKiogZGUgbG9zIHJlc2lkdW9zIHBlcm1pdGUgZXZhbHVhciBzaSBlc3RvcyBzaWd1ZW4gdW5hICoqZGlzdHJpYnVjacOzbiBub3JtYWwqKiBjb21wYXJhbmRvIHN1cyBjdWFudGlsZXMgY29uIGxvcyBkZSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwgdGXDs3JpY2EuIEVuIGVzdGUgY2FzbywgbG9zIHB1bnRvcyBkZWwgZ3LDoWZpY28gc2UgYWxpbmVhbiBiYXN0YW50ZSBiaWVuIGNvbiBsYSAqKmzDrW5lYSBkaWFnb25hbCoqLCBsbyBxdWUgaW5kaWNhIHF1ZSwgZW4gZ2VuZXJhbCwgbG9zIHJlc2lkdW9zIHNpZ3VlbiB1biAqKmNvbXBvcnRhbWllbnRvIGNlcmNhbm8gYSBsYSBub3JtYWxpZGFkKiouDQoNClNpbiBlbWJhcmdvLCBzZSBvYnNlcnZhbiAqKnBlcXVlw7FhcyBkZXN2aWFjaW9uZXMgZW4gbG9zIGV4dHJlbW9zKiosIHRhbnRvIGVuIGxvcyB2YWxvcmVzIG3DoXMgbmVnYXRpdm9zIGNvbW8gZW4gbG9zIG3DoXMgcG9zaXRpdm9zLiBFc3RvIHN1Z2llcmUgbGEgcHJlc2VuY2lhIGRlICoqY29sYXMgbcOhcyBwZXNhZGFzKiogZW4gbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgcmVzaWR1b3MgbyBsYSBleGlzdGVuY2lhIGRlIGFsZ3Vub3MgKip2YWxvcmVzIGF0w61waWNvcyBsZXZlcyoqLiBBIHBlc2FyIGRlIGVzdGFzIGRlc3ZpYWNpb25lcywgbm8gcGFyZWNlbiBzZXIgbG8gc3VmaWNpZW50ZW1lbnRlIGdyYW5kZXMgY29tbyBwYXJhIGluZGljYXIgdW5hICoqdmlvbGFjacOzbiBncmF2ZSBkZSBsYSBub3JtYWxpZGFkKiouDQoNClBhcmEgY29tcGxlbWVudGFyIGVzdGUgYW7DoWxpc2lzIHkgY29uZmlybWFyIHNpIGxvcyByZXNpZHVvcyBjdW1wbGVuIGNvbiBsb3MgKipzdXB1ZXN0b3MgZGUgbm9ybWFsaWRhZCB5IGhvbW9jZWRhc3RpY2lkYWQqKiwgc2UgcmVhbGl6YW4gcHJ1ZWJhcyBlc3RhZMOtc3RpY2FzIGVzcGVjw61maWNhcy4gRXN0YXMgcHJ1ZWJhcyBwZXJtaXRlbiB2ZXJpZmljYXIgY29uIG1heW9yIHByZWNpc2nDs24gc2kgbG9zIHJlc2lkdW9zIHNpZ3VlbiBlZmVjdGl2YW1lbnRlIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbCB5IHNpIGxhICoqdmFyaWFuemEgZGUgbG9zIGVycm9yZXMgZXMgY29uc3RhbnRlKiogZW4gdG9kbyBlbCByYW5nbyBkZSB2YWxvcmVzIGFqdXN0YWRvcy4gU2kgc2UgZGV0ZWN0YW4gcHJvYmxlbWFzIHNpZ25pZmljYXRpdm9zLCBwb2Ryw61hbiBzZXIgbmVjZXNhcmlhcyB0cmFuc2Zvcm1hY2lvbmVzIGVuIGxvcyBkYXRvcyBvIGVsIHVzbyBkZSBtb2RlbG9zIG3DoXMgcm9idXN0b3MgcGFyYSBtZWpvcmFyIGxhIHZhbGlkZXogZGVsIGFuw6FsaXNpcy4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwX3NoYXBpcm9fdGVzdH0NCg0KIyBQcnVlYmEgZGUgbm9ybWFsaWRhZCBkZSBTaGFwaXJvLVdpbGsNCnNoYXBpcm9fdGVzdF9wbF90cmFuZGVwIDwtIHNoYXBpcm8udGVzdChyZXNfcGxfdHJhbmRlcCkNCg0Kc2hhcGlyb190ZXN0X3BsX3RyYW5kZXANCg0KYGBgDQoNCkxhICoqcHJ1ZWJhIGRlIFNoYXBpcm8tV2lsayoqIHNlIHV0aWxpesOzIHBhcmEgZXZhbHVhciBzaSBsb3MgcmVzaWR1b3MgZGVsIG1vZGVsbyBzaWd1ZW4gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLiBFbCByZXN1bHRhZG8gYXJyb2rDsyB1biAqKmVzdGFkw61zdGljbyBXIGRlIDAuOTg3MTUqKiwgdW4gdmFsb3IgY2VyY2FubyBhICoqMSoqLCBsbyBxdWUgaW5kaWNhIHF1ZSBsb3MgZGF0b3Mgc2UgYWp1c3RhbiBiaWVuIGEgdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLiBBZGVtw6FzLCBlbCAqKnAtdmFsb3Igb2J0ZW5pZG8gZnVlIGRlIDAuOTExNSoqLCBsbyBxdWUsIGFsIHNlciBtYXlvciBxdWUgKiowLjA1KiosIHNpZ25pZmljYSBxdWUgbm8gaGF5IHN1ZmljaWVudGUgZXZpZGVuY2lhIGVzdGFkw61zdGljYSBwYXJhIHJlY2hhemFyIGxhICoqaGlww7N0ZXNpcyBudWxhKiouIEVuIG90cmFzIHBhbGFicmFzLCBsb3MgcmVzaWR1b3MgKipubyBwcmVzZW50YW4gZGVzdmlhY2lvbmVzIHNpZ25pZmljYXRpdmFzIGRlIGxhIG5vcm1hbGlkYWQqKi4NCg0KRXN0ZSByZXN1bHRhZG8gY29uZmlybWEgcXVlIGVsICoqc3VwdWVzdG8gZGUgbm9ybWFsaWRhZCBkZSBsb3MgcmVzaWR1b3Mgc2UgY3VtcGxlKiosIGxvIHF1ZSBoYWNlIHF1ZSBlbCBtb2RlbG8gc2VhICoqZXN0YWTDrXN0aWNhbWVudGUgdsOhbGlkbyBwYXJhIHJlYWxpemFyIGluZmVyZW5jaWFzKiouIEFkZW3DoXMsIGVzIGNvaGVyZW50ZSBjb24gbGEgb2JzZXJ2YWNpw7NuIGRlbCAqKmdyw6FmaWNvIFEtUSoqLCBxdWUgeWEgc3VnZXLDrWEgdW5hIGJ1ZW5hIGFsaW5lYWNpw7NuIGRlIGxvcyByZXNpZHVvcyBjb24gbGEgZGlzdHJpYnVjacOzbiBub3JtYWwuIEVzdG8gcmVmdWVyemEgbGEgY29uZmlhbnphIGVuIGxhIGZpYWJpbGlkYWQgZGVsIG1vZGVsbyB5IGVuIGxhIHByZWNpc2nDs24gZGUgc3VzIGVzdGltYWNpb25lcy4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwX2JwX3Rlc3R9DQoNCiMgUHJ1ZWJhIGRlIGhvbW9jZWRhc3RpY2lkYWQgZGUgQnJldXNjaC1QYWdhbg0KbGlicmFyeShsbXRlc3QpDQoNCiMgUHJ1ZWJhIGRlIEJyZXVzY2gtUGFnYW4NCmJwX3Rlc3RfcGxfdHJhbmRlcCA8LSBicHRlc3QobW9kZWxfcGxfdHJhbmRlcCkNCg0KYnBfdGVzdF9wbF90cmFuZGVwDQoNCmBgYA0KDQpFbCAqKnRlc3QgZGUgaG9tb2NlZGFzdGljaWRhZCBkZSBCcmV1c2NoLVBhZ2FuKiogc2UgdXRpbGl6w7MgcGFyYSBldmFsdWFyIHNpIGxhIHZhcmlhbnphIGRlIGxvcyBlcnJvcmVzIGVuIGVsIG1vZGVsbyBlcyBjb25zdGFudGUuIExvcyByZXN1bHRhZG9zIG11ZXN0cmFuIHVuICoqZXN0YWTDrXN0aWNvIEJQIGRlIDYuMjgyMioqLCBsbyBxdWUgc3VnaWVyZSB1bmEgbWF5b3IgZXZpZGVuY2lhIGRlICoqaGV0ZXJvY2VkYXN0aWNpZGFkKiouIERhZG8gcXVlIHNvbG8gc2UgaW5jbHV5ZSB1biBwcmVkaWN0b3IgZW4gZWwgbW9kZWxvLCBsYSBwcnVlYmEgc2UgYmFzYSBlbiAqKnVuIGdyYWRvIGRlIGxpYmVydGFkKiouIEFkZW3DoXMsIGVsICoqcC12YWxvciBvYnRlbmlkbyBmdWUgZGUgMC4wMTIyKiosIGxvIHF1ZSwgYWwgc2VyIG1lbm9yIHF1ZSAqKjAuMDUqKiwgaW5kaWNhIHF1ZSBzZSBkZWJlICoqcmVjaGF6YXIgbGEgaGlww7N0ZXNpcyBudWxhKiogeSBjb25jbHVpciBxdWUgbG9zIHJlc2lkdW9zIHByZXNlbnRhbiAqKmhldGVyb2NlZGFzdGljaWRhZCBzaWduaWZpY2F0aXZhKiouIEVuIG90cmFzIHBhbGFicmFzLCBsYSB2YXJpYW56YSBkZSBsb3MgZXJyb3JlcyBubyBlcyBjb25zdGFudGUgZW4gdG9kbyBlbCByYW5nbyBkZSB2YWxvcmVzIGFqdXN0YWRvcy4NCg0KRXN0YSB2aW9sYWNpw7NuIGRlIGxhIHN1cG9zaWNpw7NuIGRlICoqaG9tb2NlZGFzdGljaWRhZCoqIHB1ZWRlIGFmZWN0YXIgbGEgKipwcmVjaXNpw7NuIGRlIGxhcyBlc3RpbWFjaW9uZXMgeSBwcnVlYmFzIGRlIGhpcMOzdGVzaXMqKiwgaGFjaWVuZG8gcXVlIGxvcyAqKmludGVydmFsb3MgZGUgY29uZmlhbnphIHkgdmFsb3JlcyBwIHNlYW4gbWVub3MgY29uZmlhYmxlcyoqIGRlYmlkbyBhIGxhIHZhcmlhYmlsaWRhZCBkZXNpZ3VhbCBlbiBsb3MgZXJyb3JlcyBkZWwgbW9kZWxvLg0KDQpEYWRvIHF1ZSBlc3RhIGNvbmRpY2nDs24gcHVlZGUgY29tcHJvbWV0ZXIgbGEgdmFsaWRleiBkZSBsb3MgcmVzdWx0YWRvcywgZXMgaW1wb3J0YW50ZSBjb25zaWRlcmFyIGVzdHJhdGVnaWFzIHBhcmEgY29ycmVnaXIgbGEgaGV0ZXJvY2VkYXN0aWNpZGFkLiBVbmEgb3BjacOzbiBlcyBhcGxpY2FyIHVuYSAqKnRyYW5zZm9ybWFjacOzbiBlbiBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSoqLCBjb21vIGVsICoqbG9nYXJpdG1vIChgbG9nKFkpYCkgbyBsYSByYcOteiBjdWFkcmFkYSAoYHNxcnQoWSlgKSoqLCBwYXJhIGVzdGFiaWxpemFyIGxhIHZhcmlhbnphIGRlIGxvcyBlcnJvcmVzLiBPdHJhIGFsdGVybmF0aXZhIGVzIHV0aWxpemFyIHVuYSAqKnJlZ3Jlc2nDs24gcm9idXN0YSBjb24gZXJyb3JlcyBlc3TDoW5kYXIgZGUgV2hpdGUqKiwgcXVlIGFqdXN0YSBsb3MgZXJyb3JlcyBwYXJhIGhhY2VybG9zIG1lbm9zIHNlbnNpYmxlcyBhIGxhIGhldGVyb2NlZGFzdGljaWRhZC4gVGFtYmnDqW4gcHVlZGUgYXBsaWNhcnNlIHVuYSAqKnJlZ3Jlc2nDs24gcG9uZGVyYWRhIChXTFMsIFdlaWdodGVkIExlYXN0IFNxdWFyZXMpKiosIGVuIGxhIHF1ZSBzZSBhc2lnbmFuIHBlc29zIGEgbGFzIG9ic2VydmFjaW9uZXMgcGFyYSBjb21wZW5zYXIgbGEgdmFyaWFiaWxpZGFkIGRlc2lndWFsIGVuIGxvcyBlcnJvcmVzLCBlc3BlY2lhbG1lbnRlIHNpIGxhIGhldGVyb2NlZGFzdGljaWRhZCBlc3TDoSByZWxhY2lvbmFkYSBjb24gdW5hIHZhcmlhYmxlIGVzcGVjw61maWNhLg0KDQpDb21vIHByaW1lciBpbnRlbnRvIGRlIGNvcnJlY2Npw7NuLCBzZSBhcGxpY2Fyw6EgdW5hICoqdHJhbnNmb3JtYWNpw7NuIGEgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUgYHBsX3JhZGpgKiosIGNvbiBlbCBvYmpldGl2byBkZSByZWR1Y2lyIGxhIGhldGVyb2NlZGFzdGljaWRhZCB5IG1lam9yYXIgbGEgZXN0YWJpbGlkYWQgZGVsIG1vZGVsby4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwX2JveGNveCwgd2FybmluZz1GQUxTRX0NCg0KIyBQcnVlYmEgZGUgQm94LUNveCBwYXJhIHRyYW5zZm9ybWFyIGxhIHZhcmlhYmxlIHBsX3RyYW5kZXANCmxpYnJhcnkoTUFTUykNCg0KIyBQcnVlYmEgZGUgQm94LUNveA0KYm94Y294X3BsX3RyYW5kZXAgPC0gYm94Y294KG1vZGVsX3BsX3RyYW5kZXAsIGxhbWJkYSA9IHNlcSgtMiwgMiwgYnkgPSAwLjEpKQ0KDQpgYGANCg0KRWwgYW7DoWxpc2lzIGRlIGxhICoqdHJhbnNmb3JtYWNpw7NuIGRlIEJveC1Db3gqKiBtdWVzdHJhIHF1ZSBlbCAqKnBpY28gZGUgbGEgY3VydmEqKiBvY3VycmUgYXByb3hpbWFkYW1lbnRlIGVuICoqbGFtYmRhIOKJiCAyKiosIGxvIHF1ZSBpbmRpY2EgcXVlIGxhIG1lam9yIHRyYW5zZm9ybWFjacOzbiBwYXJhIGxhIHZhcmlhYmxlIGRlcGVuZGllbnRlIHNlIGVuY3VlbnRyYSBlbiBlc2EgcmVnacOzbi4gQ29tbyBlc3RlIHZhbG9yIGVzdMOhIGRlbnRybyBkZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSwgc2UgY29uc2lkZXJhIHVuYSBvcGNpw7NuIGFkZWN1YWRhIHBhcmEgdHJhbnNmb3JtYXIgbG9zIGRhdG9zIHkgbWVqb3JhciBlbCBhanVzdGUgZGVsIG1vZGVsby4NCg0KRGFkbyBxdWUgZWwgdmFsb3Igw7NwdGltbyBkZSBsYW1iZGEgZXMgY2VyY2FubyBhICoqMioqLCBsYSB0cmFuc2Zvcm1hY2nDs24gc3VnZXJpZGEgcGFyYSBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSBlcyAqKmVsZXZhcmxhIGFsIGN1YWRyYWRvIChgWcKyYCkqKi4gRXN0ZSB0aXBvIGRlIHRyYW5zZm9ybWFjacOzbiBwdWVkZSBheXVkYXIgYSBlc3RhYmlsaXphciBsYSB2YXJpYW56YSBkZSBsb3MgcmVzaWR1b3MgeSBtZWpvcmFyIGxhIGxpbmVhbGlkYWQgZGUgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyB2YXJpYWJsZXMuDQoNClBvciBvdHJvIGxhZG8sIG5vIHNlIHJlY29taWVuZGEgdXRpbGl6YXIgdW5hICoqdHJhbnNmb3JtYWNpw7NuIGxvZ2Fyw610bWljYSAoYGxvZyhZKWApKiogY29ycmVzcG9uZGllbnRlIGEgKipsYW1iZGEgPSAwKiosIG5pIGxhICoqcmHDrXogY3VhZHJhZGEgKGBzcXJ0KFkpYCkqKiwgcXVlIGNvcnJlc3BvbmRlcsOtYSBhICoqbGFtYmRhID0gMC41KiouIEFtYmFzIG9wY2lvbmVzIHF1ZWRhbiBmdWVyYSBkZWwgaW50ZXJ2YWxvIMOzcHRpbW8gZGVmaW5pZG8gcG9yIGxhIHBydWViYSB5LCBwb3IgbG8gdGFudG8sIG5vIG9mcmVjZXLDrWFuIHVuYSBtZWpvcmEgc2lnbmlmaWNhdGl2YSBlbiBsYSBub3JtYWxpZGFkIGRlIGxvcyByZXNpZHVvcyBuaSBlbiBsYSBob21vY2VkYXN0aWNpZGFkIGRlbCBtb2RlbG8uDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfdHJhbmRlcF9zcXVhcmVfdHJhbnNmfQ0KDQojIFJlZ3Jlc2nDs24gZGUgcGxfcmFkal4yIGNvbiBwbF90cmFuZGVwDQptb2RlbF9wbF90cmFuZGVwX3NxdWFyZSA8LSBsbShJKHBsX3JhZGpeMikgfiBwbF90cmFuZGVwLCBkYXRhID0ga2VwbGVyX2RhdGFfbnVtKQ0KDQptb2RlbF9wbF90cmFuZGVwX3NxdWFyZV9zdW1tYXJ5IDwtIHN1bW1hcnkobW9kZWxfcGxfdHJhbmRlcF9zcXVhcmUpDQoNCm1vZGVsX3BsX3RyYW5kZXBfc3F1YXJlX3N1bW1hcnkNCg0KYGBgDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfdHJhbmRlcF9zcXVhcmVfdHJhbnNmX3NjYXRfcGxvdH0NCg0KIyBTY2F0dGVyIHBsb3QgZGUgcGxfcmFkal4yIHZzIHBsX3RyYW5kZXAgY29uIGxhIHJlY3RhIGRlIHJlZ3Jlc2nDs24gZW4gcm9qbw0KIyB5IGxvcyBtYXJnZW5lcyBkZSBjb25maWFuemEgZW4gZ3Jpcw0KZ2dwbG90KGtlcGxlcl9kYXRhX251bSwgYWVzKHggPSBwbF90cmFuZGVwLCB5ID0gSShwbF9yYWRqXjIpKSkrDQogIGdlb21fcG9pbnQoY29sb3IgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJpbmRpYW5yZWQiLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMikgKw0KICBsYWJzKHRpdGxlID0gIlJlZ3Jlc2nDs24gTGluZWFsOiBSYWRpbyBkZWwgRXhvcGxhbmV0YSBhbCBDdWFkcmFkbyBzZWd1biBQcm9mdW5kaWRhZCBkZWwgVHLDoW5zaXRvIiwNCiAgICAgICB4ID0gIlByb2Z1bmRpZGFkIGRlbCBUcsOhbnNpdG8gKCUpIiwNCiAgICAgICB5ID0gIlJhZGlvIGRlbCBFeG9wbGFuZXRhIGFsIEN1YWRyYWRvIChKw7pwaXRlcl4yKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQokJA0KcGxcX3JhZGpeMiA9IFxiZXRhXzAgKyBcYmV0YV8xIFxjZG90IHBsXF90cmFuZGVwICsgXHZhcmVwc2lsb24NCiQkDQoNCkVsIGFuw6FsaXNpcyBkZWwgbW9kZWxvIGRlc3B1w6lzIGRlIGFwbGljYXIgbGEgdHJhbnNmb3JtYWNpw7NuIGN1YWRyw6F0aWNhIG11ZXN0cmEgdW5hIG1lam9yYSBzaWduaWZpY2F0aXZhIGVuIHN1IHByZWNpc2nDs24geSBjYXBhY2lkYWQgcHJlZGljdGl2YS4gRWwgKiplcnJvciBlc3TDoW5kYXIgZGUgbG9zIHJlc2lkdW9zKiogc2UgcmVkdWpvIGEgKiowLjA0MDQ5KiosIHVuIHZhbG9yIG1lbm9yIGVuIGNvbXBhcmFjacOzbiBjb24gZWwgbW9kZWxvIHNpbiB0cmFuc2Zvcm1hY2nDs24sIGxvIHF1ZSBpbmRpY2EgdW5hIG1heW9yIHByZWNpc2nDs24gZW4gbGFzIHByZWRpY2Npb25lcy4NCg0KRWwgbW9kZWxvIGFob3JhIGV4cGxpY2EgKiplbCA5OS4xNCUgZGUgbGEgdmFyaWFiaWxpZGFkIGVuIGBwbF9yYWRqwrJgKiosIGNvbiB1biAqKlLCsiBkZSAwLjk5MTQqKiwgbG8gcXVlIHJlZmxlamEgdW4gYWp1c3RlIGV4Y2VwY2lvbmFsLiBJbmNsdXNvIGFsIGNvcnJlZ2lyIHBvciBlbCBuw7ptZXJvIGRlIHByZWRpY3RvcmVzLCBlbCAqKlLCsiBhanVzdGFkbyoqIHNpZ3VlIHNpZW5kbyBleHRyZW1hZGFtZW50ZSBhbHRvLCBjb24gdW4gdmFsb3IgZGUgKiowLjk5MTIqKiwgbG8gcXVlIGNvbmZpcm1hIHF1ZSBsYSByZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBlcyBtdXkgc8OzbGlkYS4NCg0KQWRlbcOhcywgZWwgKiplc3RhZMOtc3RpY28gRioqLCBjb24gdW4gdmFsb3IgZGUgKio0LDU5NioqIHkgdW4gKipwLXZhbG9yIGV4dHJlbWFkYW1lbnRlIGJham8gKFw8IDIuMiDDlyAxMOKBu8K54oG2KSoqLCBkZW11ZXN0cmEgcXVlIGVsIG1vZGVsbyBlcyBhbHRhbWVudGUgc2lnbmlmaWNhdGl2by4NCg0KRW4gZ2VuZXJhbCwgbGEgdHJhbnNmb3JtYWNpw7NuIGN1YWRyw6F0aWNhIG1lam9yw7Mgbm90YWJsZW1lbnRlIGVsIGFqdXN0ZSBlbiBjb21wYXJhY2nDs24gY29uIGVsIG1vZGVsbyBvcmlnaW5hbC4gTGEgcmVsYWNpw7NuIGVudHJlICoqYHBsX3RyYW5kZXBgKiogeSAqKmBwbF9yYWRqwrJgKiogbm8gc29sbyBlcyBmdWVydGUsIHNpbm8gdGFtYmnDqW4gZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YSwgbG8gcXVlIHN1Z2llcmUgcXVlIGVzdGUgbW9kZWxvIGVzIHVuYSByZXByZXNlbnRhY2nDs24gbcOhcyBwcmVjaXNhIGRlIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3RyYW5kZXBfc3F1YXJlX3RyYW5zZl9yZXNfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBPYnRlbmVyIGxvcyByZXNpZHVvcyB5IHZhbG9yZXMgYWp1c3RhZG9zDQpyZXNfcGxfdHJhbmRlcF9zcXVhcmUgPC0gcmVzaWR1YWxzKG1vZGVsX3BsX3RyYW5kZXBfc3F1YXJlKQ0KDQojIENhbGN1bGFyIGxvcyB2YWxvcmVzIGFqdXN0YWRvcw0KZml0X3ZhbF9wbF90cmFuZGVwX3NxdWFyZSA8LSBmaXR0ZWQobW9kZWxfcGxfdHJhbmRlcF9zcXVhcmUpDQoNCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZSBjb24gbG9zIHJlc2lkdW9zIHkgdmFsb3JlcyBhanVzdGFkb3MNCnJlc19wbF90cmFuZGVwX3NxdWFyZV9kZiA8LSBkYXRhLmZyYW1lKA0KICBSZXNpZHVhbHMgPSByZXNfcGxfdHJhbmRlcF9zcXVhcmUsDQogIEZpdHRlZF9WYWx1ZXMgPSBmaXRfdmFsX3BsX3RyYW5kZXBfc3F1YXJlDQopDQoNCiMgU2NhdHRlciBwbG90IGRlIHJlc2lkdW9zIHZzIHZhbG9yZXMgYWp1c3RhZG9zDQpnZ3Bsb3QocmVzX3BsX3RyYW5kZXBfc3F1YXJlX2RmLCBhZXMoeCA9IEZpdHRlZF9WYWx1ZXMsIHkgPSBSZXNpZHVhbHMpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICJpbmRpYW5yZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGxhYnModGl0bGUgPSAiUmVzaWR1b3MgdnMgVmFsb3JlcyBBanVzdGFkb3MiLA0KICAgICAgIHggPSAiVmFsb3JlcyBBanVzdGFkb3MiLA0KICAgICAgIHkgPSAiUmVzaWR1b3MiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KTG9zIHJlc2lkdW9zIHRpZW5lbiBtZW5vciBkaXNwZXJzacOzbiwgbG8gcXVlIGNvbmZpcm1hIHF1ZSBsYSBoZXRlcm9jZWRhc3RpY2lkYWQgZGV0ZWN0YWRhIGFudGVyaW9ybWVudGUgZnVlIHJlZHVjaWRhIGNvbiBsYSB0cmFuc2Zvcm1hY2nDs24uDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfdHJhbmRlcF9zcXVhcmVfdHJhbnNmX3FxX3Bsb3QsIHdhcm5pbmc9RkFMU0V9DQoNCiMgQ3JlYXIgdW4gZ3LDoWZpY28gUS1RIGRlIGxvcyByZXNpZHVvcw0KcXFub3JtKHJlc19wbF90cmFuZGVwX3NxdWFyZSwgbWFpbiA9ICJHcsOhZmljbyBRLVEgZGUgbG9zIFJlc2lkdW9zIiwgY29sPSJpbmRpYW5yZWQiKQ0KDQpgYGANCg0KRW4gZWwgZ3LDoWZpY28gUS1RIGRlIGxvcyByZXNpZHVvcywgbG9zIHB1bnRvcyBzZSBhbGluZWFuIGJhc3RhbnRlIGJpZW4gY29uIGxhIGzDrW5lYSBkaWFnb25hbCwgbG8gcXVlIHN1Z2llcmUgcXVlIGxvcyByZXNpZHVvcyBzaWd1ZW4gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLiBBdW5xdWUgaGF5IHVuYSBwZXF1ZcOxYSBkZXN2aWFjacOzbiBlbiBsb3MgZXh0cmVtb3MgKHZhbG9yZXMgbXV5IG5lZ2F0aXZvcyB5IHBvc2l0aXZvcyksIGxhIGRlc3ZpYWNpw7NuIG5vIGVzIHNldmVyYS4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwX3NxdWFyZV90cmFuc2Zfc2hhcGlyb190ZXN0fQ0KDQojIFBydWViYSBkZSBub3JtYWxpZGFkIGRlIFNoYXBpcm8tV2lsaw0Kc2hhcGlyb190ZXN0X3BsX3RyYW5kZXBfc3F1YXJlIDwtIHNoYXBpcm8udGVzdChyZXNfcGxfdHJhbmRlcF9zcXVhcmUpDQoNCnNoYXBpcm9fdGVzdF9wbF90cmFuZGVwX3NxdWFyZQ0KDQpgYGANCg0KRWwgKip0ZXN0IGRlIG5vcm1hbGlkYWQgZGUgU2hhcGlyby1XaWxrKiogYXJyb2phIHVuICoqZXN0YWTDrXN0aWNvIFcgZGUgMC44NTA3KiogeSB1biAqKnAtdmFsb3IgZGUgMC4wMDAwNjUwNCoqLCBsbyBxdWUgaW5kaWNhIHF1ZSBsb3MgcmVzaWR1b3MgKipubyBzaWd1ZW4gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsKiouIEEgcGVzYXIgZGUgcXVlIGVuIGVsICoqZ3LDoWZpY28gUS1RKiogbG9zIHB1bnRvcyBwYXJlY8OtYW4gYWxpbmVhcnNlIGRlIG1hbmVyYSByYXpvbmFibGUgY29uIGxhIGzDrW5lYSBkaWFnb25hbCwgbGEgcHJ1ZWJhIGVzdGFkw61zdGljYSBwcm9wb3JjaW9uYSBldmlkZW5jaWEgc3VmaWNpZW50ZSBwYXJhIHJlY2hhemFyIGxhIGhpcMOzdGVzaXMgZGUgbm9ybWFsaWRhZC4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwX3NxdWFyZV90cmFuc2ZfYnBfdGVzdH0NCg0KbGlicmFyeShsbXRlc3QpDQojIFBydWViYSBkZSBob21vY2VkYXN0aWNpZGFkIGRlIEJyZXVzY2gtUGFnYW4NCmJwX3Rlc3RfcGxfdHJhbmRlcF9zcXVhcmUgPC0gYnB0ZXN0KG1vZGVsX3BsX3RyYW5kZXBfc3F1YXJlKQ0KDQpicF90ZXN0X3BsX3RyYW5kZXBfc3F1YXJlDQoNCmBgYA0KDQpFbCAqKnRlc3QgZGUgQnJldXNjaC1QYWdhbioqIGFycm9qYSB1biAqKmVzdGFkw61zdGljbyBCUCBkZSAxNC44NyoqLCBjb24gKioxIGdyYWRvIGRlIGxpYmVydGFkKiogeSB1biAqKnAtdmFsb3IgZGUgMC4wMDAxMTUyKiosIGxvIHF1ZSBpbmRpY2EgcXVlIGxvcyByZXNpZHVvcyBwcmVzZW50YW4gKipoZXRlcm9jZWRhc3RpY2lkYWQgc2lnbmlmaWNhdGl2YSoqLiBFc3RvIHNpZ25pZmljYSBxdWUgbGEgdmFyaWFuemEgZGUgbG9zIGVycm9yZXMgbm8gZXMgY29uc3RhbnRlIGVuIHRvZG8gZWwgbW9kZWxvLCBsbyBxdWUgcHVlZGUgYWZlY3RhciBsYSBmaWFiaWxpZGFkIGRlIGxhcyBpbmZlcmVuY2lhcyBlc3RhZMOtc3RpY2FzLg0KDQpBdW5xdWUgbGEgKip0cmFuc2Zvcm1hY2nDs24gY3VhZHLDoXRpY2EqKiBhcGxpY2FkYSBhIGxhIHZhcmlhYmxlIGRlcGVuZGllbnRlIGF5dWTDsyBhICoqcmVkdWNpciBsYSBoZXRlcm9jZWRhc3RpY2lkYWQqKiwgbG9zIHJlc3VsdGFkb3MgbXVlc3RyYW4gcXVlIGHDum4gcGVyc2lzdGUgZW4gY2llcnRhIG1lZGlkYS4gRXN0byBzdWdpZXJlIHF1ZSwgYXVucXVlIGVsIG1vZGVsbyBoYSBtZWpvcmFkbywgcHVlZGUgc2VyIG5lY2VzYXJpbyBhcGxpY2FyICoqb3RyYXMgZXN0cmF0ZWdpYXMqKiwgY29tbyByZWdyZXNpw7NuIHBvbmRlcmFkYSBvIGVsIHVzbyBkZSBlcnJvcmVzIGVzdMOhbmRhciByb2J1c3RvcywgcGFyYSBnYXJhbnRpemFyIHVuYSBlc3RpbWFjacOzbiBtw6FzIGVzdGFibGUgeSBjb25maWFibGUuDQoNCiMjIyBSZWdyZXNpw7NuIGxpbmVhbCByb2J1c3RhIGRlIEh1YmVyOiByYWRpbyBkZWwgZXhvcGxhbmV0YSBzZWfDum4gbGEgcHJvZnVuZGlkYWQgZGVsIHRyw6Fuc2l0byAoYHBsX3RyYW5kZXBgKQ0KDQpDYWJlIHJlY29yZGFyLCBzZWfDum4gbG8gZXhwdWVzdG8gZW4gZWwgYW7DoWxpc2lzIGRlIG91dGxpZXJzLCBsYSBncmFuIGNhbnRpZGFkIGRlIGRhdG9zIGV4dHJlbW9zIGVuIGxhIHZhcmlhYmxlIGBwbF90cmFuZGVwYCwgcG9yIGxvIHF1ZSBwcm9iYWJsZW1lbnRlIHNlYSBhZGVjdWFkYSBsYSB1dGlsaXphY2nDs24gZGUgdW4gbW9kZWxvIG3DoXMgcm9idXN0byBwYXJhIGV2aXRhciBxdWUgZXN0b3MgZGF0b3MgYWZlY3RlbiBsYSBjYWxpZGFkIGRlbCBtb2RlbG8sIGNvbW8gcG9yIGVqZW1wbG8gKipsYSByZWdyZXNpw7NuIGRlIEh1YmVyKiouDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfdHJhbmRlcF9odWJlcn0NCg0KIyBSZWdyZXNpw7NuIGRlIEh1YmVyDQpsaWJyYXJ5KE1BU1MpDQoNCiMgQWp1c3RlIGRlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBkZSBIdWJlcg0KbW9kZWxfcGxfdHJhbmRlcF9odWJlciA8LSBybG0ocGxfcmFkaiB+IHBsX3RyYW5kZXAsIGRhdGEgPSBrZXBsZXJfZGF0YV9udW0pDQoNCm1vZGVsX3BsX3RyYW5kZXBfaHViZXJfc3VtbWFyeSA8LSBzdW1tYXJ5KG1vZGVsX3BsX3RyYW5kZXBfaHViZXIpDQoNCm1vZGVsX3BsX3RyYW5kZXBfaHViZXJfc3VtbWFyeQ0KDQpgYGANCg0KYGBge3IgdW5pdmFyX3JlZ19wbF90cmFuZGVwX2h1YmVyX3Bsb3QsIHdhcm5pbmc9RkFMU0V9DQoNCiMgU2NhdHRlciBwbG90IGRlIHBsX3JhZGogdnMgcGxfdHJhbmRlcCBjb24gbGEgcmVjdGEgZGUgcmVncmVzacOzbiBlbiByb2pvDQojIHkgbG9zIG1hcmdlbmVzIGRlIGNvbmZpYW56YSBlbiBncmlzDQpnZ3Bsb3Qoa2VwbGVyX2RhdGFfbnVtLCBhZXMoeCA9IHBsX3RyYW5kZXAsIHkgPSBwbF9yYWRqKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gInJsbSIsIGNvbG9yID0gImluZGlhbnJlZCIsIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC4yKSArDQogIGxhYnModGl0bGUgPSAiUmVncmVzacOzbiBkZSBIdWJlcjogUmFkaW8gZGVsIEV4b3BsYW5ldGEgc2VndW4gUHJvZnVuZGlkYWQgZGVsIFRyw6Fuc2l0byIsDQogICAgICAgeCA9ICJQcm9mdW5kaWRhZCBkZWwgVHLDoW5zaXRvICglKSIsDQogICAgICAgeSA9ICJSYWRpbyBkZWwgRXhvcGxhbmV0YSAoSsO6cGl0ZXIpIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCmZvcm11bGFyIGRlIGxhIHJlZ3Jlc2nDs24gZGUgSHViZXI6DQoNCiQkDQpwbFxfcmFkaiA9IDAuMjE5OSArIDAuNjI4OSBcY2RvdCBwbFxfdHJhbmRlcCArIDAuMDg2MjcNCiQkDQoNCkVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGRlIEh1YmVyIG11ZXN0cmEgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlICoqYHBsX3RyYW5kZXBgKiogeSAqKmBwbF9yYWRqYCoqLCBjb24gdW4gY29lZmljaWVudGUgZGUgKiowLjYyODkqKi4gQ2FkYSBhdW1lbnRvIHVuaXRhcmlvIGVuICoqYHBsX3RyYW5kZXBgKiogc2UgYXNvY2lhIGNvbiB1biBpbmNyZW1lbnRvIGRlICoqMC42Mjg5IGVuIGBwbF9yYWRqYCoqLiBBZGVtw6FzLCBlbCBtb2RlbG8gdGllbmUgdW4gKiplcnJvciBlc3TDoW5kYXIgZGUgbG9zIHJlc2lkdW9zIGRlIDAuMzg3NioqLCBsbyBxdWUgaW5kaWNhIHVuYSB2YXJpYWJpbGlkYWQgbW9kZXJhZGEgZW4gbGFzIHByZWRpY2Npb25lcy4NCg0KQW1ib3MgY29lZmljaWVudGVzIHNvbiBhbHRhbWVudGUgc2lnbmlmaWNhdGl2b3MgKHQgPiAyIHBvciBtdWNobyksIGxvIHF1ZSBzdWdpZXJlIHF1ZSBoYXkgdW5hIHJlbGFjacOzbiBjbGFyYSB5IGZ1ZXJ0ZSBlbnRyZSBsYSBwcm9mdW5kaWRhZCBkZWwgdHLDoW5zaXRvIHkgZWwgcmFkaW8gZGVsIHBsYW5ldGEuIFNpbiBlbWJhcmdvLCBkZSBsb3MgZGF0b3Mgb3JpZ2luYWxlcywgc29sbyA0MSBvYnNlcnZhY2lvbmVzIGZ1ZXJvbiB1c2FkYXMgeSAyNTA1IG9ic2VydmFjaW9uZXMgZnVlcm9uIGRlc2NhcnRhZGFzLiBFc28gcHVlZGUgcGFzYXIgc2kgZmFsdGFuIGRhdG9zIGVuICoqYHBsX3JhZGpgKiogbyAqKmBwbF90cmFuZGVwYCoqIG8gc2UgcGVyZGllcm9uIGVuIGVsIHByZXByb2Nlc2FtaWVudG8gKHBvc2libGVtZW50ZSBlbCB0cmF0YW1pZW50byBkZWwgbcOpdG9kbyByb2J1c3RvKSBsb3MgZGVqw7MgZnVlcmEuDQoNCiMjIyBSZWdyZXNpw7NuIGxpbmVhbDogcmFkaW8gZGVsIGV4b3BsYW5ldGEgc2Vnw7puIGxhIGFtcGxpdHVkIGRlIGxhIHZlbG9jaWRhZCByYWRpYWwgKGBwbF9ydmFtcGApDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcnZhbXB9DQoNCiMgUmVncmVzaW9uIGRlbCByYWRpbyBkZWwgZXhvcGxhbmV0YSAocGxfcmFkaikgDQojIHV0aWxpemFuZG8gbGEgYW1wbGl0dWRlIGRlIGxhIHZlbG9jaWRhZCByYWRpYWwgZGVsIHBsYW5ldGEgKHBsX3J2YW1wKQ0KIyBjb21vIHByZWRpY3Rvcg0KbW9kZWxfcGxfcnZhbXAgPC0gbG0ocGxfcmFkaiB+IHBsX3J2YW1wLCBkYXRhID0ga2VwbGVyX2RhdGFfbnVtKQ0KDQptb2RlbF9wbF9ydmFtcF9zdW1tYXJ5IDwtIHN1bW1hcnkobW9kZWxfcGxfcnZhbXApDQoNCm1vZGVsX3BsX3J2YW1wX3N1bW1hcnkNCg0KYGBgDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcnZhbXBfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBTY2F0dGVyIHBsb3QgZGUgcGxfcmFkaiB2cyBwbF9ydmFtcCBjb24gbGEgcmVjdGEgZGUgcmVncmVzacOzbiBlbiByb2pvDQojIHkgbG9zIG1hcmdlbmVzIGRlIGNvbmZpYW56YSBlbiBncmlzDQpnZ3Bsb3Qoa2VwbGVyX2RhdGFfbnVtLCBhZXMoeCA9IHBsX3J2YW1wLCB5ID0gcGxfcmFkaikpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gImluZGlhbnJlZCIsIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC4yKSArDQogIGxhYnModGl0bGUgPSAiUmVncmVzacOzbiBMaW5lYWw6IFJhZGlvIGRlbCBFeG9wbGFuZXRhIHNlZ3VuIEFtcGxpdHVkIGRlIGxhIFZlbG9jaWRhZCBSYWRpYWwiLA0KICAgICAgIHggPSAiQW1wbGl0dWQgZGUgbGEgVmVsb2NpZGFkIFJhZGlhbCAobWEvcykiLA0KICAgICAgIHkgPSAiUmFkaW8gZGVsIEV4b3BsYW5ldGEgKErDunBpdGVyKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpQYXJhIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIHBsYW50ZWFkbzoNCg0KJCQNCnBsXF9yYWRqID0gXGJldGFfMCArIFxiZXRhXzEgXGNkb3QgcGxcX3J2YW1wICsgXHZhcmVwc2lsb24NCiQkDQoNCkxhcyBlc3RhZMOtc3RpY2FzIGRlbCBtb2RlbG8gbXVlc3RyYW4gcXVlOg0KDQpFbCBtb2RlbG8gcHJlc2VudGEgdW4gKipSwrIgZGUgMC41MzY3KiosIGxvIHF1ZSBpbmRpY2EgcXVlICoqZXhwbGljYSBlbCA1My42NyUgZGUgbGEgdmFyaWFiaWxpZGFkIGVuIGBwbF9yYWRqYCoqLiBFc3RvIHN1Z2llcmUgdW5hIHJlbGFjacOzbiAqKm1vZGVyYWRhIGEgZnVlcnRlKiogZW50cmUgbGFzIHZhcmlhYmxlcywgYXVucXVlIHRvZGF2w61hIHF1ZWRhIHVuICoqNDYuMzMlIGRlIHZhcmlhYmlsaWRhZCBzaW4gZXhwbGljYXIqKiwgbG8gcXVlIGltcGxpY2EgcXVlIG90cm9zIGZhY3RvcmVzIHBvZHLDrWFuIGVzdGFyIGluZmx1eWVuZG8gZW4gbGEgdmFyaWFibGUgZGVwZW5kaWVudGUuDQoNCkVsICoqUsKyIGFqdXN0YWRvKiogZXMgKiowLjUyOTcqKiwgbG8gcXVlIHNpZ25pZmljYSBxdWUsIGluY2x1c28gYWwgY29ycmVnaXIgcG9yIGVsIG7Dum1lcm8gZGUgcHJlZGljdG9yZXMsIGVsIG1vZGVsbyBzaWd1ZSBtYW50ZW5pZW5kbyB1biAqKmJ1ZW4gbml2ZWwgZGUgYWp1c3RlKiouIEFkZW3DoXMsIGVsICoqZXN0YWTDrXN0aWNvIEYqKiB0aWVuZSB1biB2YWxvciBkZSAqKjc2LjQ2KiosIGNvbiB1biAqKnAtdmFsb3IgZXh0cmVtYWRhbWVudGUgYmFqbyoqLCBsbyBxdWUgY29uZmlybWEgcXVlIGVsIG1vZGVsbyBlcyAqKmFsdGFtZW50ZSBzaWduaWZpY2F0aXZvKiogeSBxdWUgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyB2YXJpYWJsZXMgbm8gZXMgcHJvZHVjdG8gZGVsIGF6YXIuDQoNCkEgcGVzYXIgZGUgcXVlIGVsIG1vZGVsbyB0aWVuZSB1biBhanVzdGUgcmF6b25hYmxlLCBubyBlcyB0YW4gcHJlY2lzbyBjb21vIGVsIG9idGVuaWRvIGVuIGxhIHJlZ3Jlc2nDs24gZGUgKipgcGxfcmFkaiB+IHBsX3RyYW5kZXBgKiouIFNpbiBlbWJhcmdvLCBsYSByZWxhY2nDs24gZW50cmUgKipgcGxfcnZhbXBgIHkgYHBsX3JhZGpgKiogc2lndWUgc2llbmRvICoqZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YSoqIHkgbXVlc3RyYSB1biBuaXZlbCBkZSBhc29jaWFjacOzbiBpbXBvcnRhbnRlLCBsbyBxdWUgc3VnaWVyZSBxdWUgYHBsX3J2YW1wYCBlcyB1biBwcmVkaWN0b3IgcmVsZXZhbnRlLCBhdW5xdWUgbm8gZWwgbcOhcyBmdWVydGUgZGlzcG9uaWJsZS4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF9ydmFtcF9yZXNfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBPYnRlbmVyIGxvcyByZXNpZHVvcyB5IHZhbG9yZXMgYWp1c3RhZG9zDQpyZXNfcGxfcnZhbXAgPC0gcmVzaWR1YWxzKG1vZGVsX3BsX3J2YW1wKQ0KDQojIENhbGN1bGFyIGxvcyB2YWxvcmVzIGFqdXN0YWRvcw0KZml0X3ZhbF9wbF9ydmFtcCA8LSBmaXR0ZWQobW9kZWxfcGxfcnZhbXApDQoNCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZSBjb24gbG9zIHJlc2lkdW9zIHkgdmFsb3JlcyBhanVzdGFkb3MNCnJlc19wbF9ydmFtcF9kZiA8LSBkYXRhLmZyYW1lKA0KICBSZXNpZHVhbHMgPSByZXNfcGxfcnZhbXAsDQogIEZpdHRlZF9WYWx1ZXMgPSBmaXRfdmFsX3BsX3J2YW1wDQopDQoNCiMgU2NhdHRlciBwbG90IGRlIHJlc2lkdW9zIHZzIHZhbG9yZXMgYWp1c3RhZG9zDQpnZ3Bsb3QocmVzX3BsX3J2YW1wX2RmLCBhZXMoeCA9IEZpdHRlZF9WYWx1ZXMsIHkgPSBSZXNpZHVhbHMpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICJpbmRpYW5yZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGxhYnModGl0bGUgPSAiUmVzaWR1b3MgdnMgVmFsb3JlcyBBanVzdGFkb3MiLA0KICAgICAgIHggPSAiVmFsb3JlcyBBanVzdGFkb3MiLA0KICAgICAgIHkgPSAiUmVzaWR1b3MiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KRWwgYW7DoWxpc2lzIGRlIGxvcyByZXNpZHVvcyByZXZlbGEgcXVlIHN1ICoqZGlzcGVyc2nDs24gbm8gZXMgY29uc3RhbnRlKiogYSBsbyBsYXJnbyBkZSBsb3MgdmFsb3JlcyBhanVzdGFkb3MsIGxvIHF1ZSBzdWdpZXJlIGxhIHBvc2libGUgcHJlc2VuY2lhIGRlICoqaGV0ZXJvY2VkYXN0aWNpZGFkKiouIEVuIGxvcyB2YWxvcmVzIGFqdXN0YWRvcyBtw6FzIHBlcXVlw7FvcyAoKiptZW5vcmVzIGEgMC41KiopLCBsb3MgcmVzaWR1b3MgZXN0w6FuICoqbXV5IGNvbmNlbnRyYWRvcyoqLCBsbyBxdWUgaW5kaWNhIHVuYSBtZW5vciB2YXJpYWJpbGlkYWQgZW4gZXN0YSByZWdpw7NuLiBTaW4gZW1iYXJnbywgYSBtZWRpZGEgcXVlIGxvcyB2YWxvcmVzIGFqdXN0YWRvcyBhdW1lbnRhbiAoKiptYXlvcmVzIGEgMS4wKiopLCBsb3MgcmVzaWR1b3MgbXVlc3RyYW4gdW5hIGRpc3BlcnNpw7NuIG11Y2hvIG1heW9yLCBsbyBxdWUgc3VnaWVyZSBxdWUgbGEgKip2YXJpYW56YSBkZSBsb3MgZXJyb3JlcyBubyBlcyBjb25zdGFudGUgZW4gdG9kbyBlbCBtb2RlbG8qKi4NCg0KTGEgcHJlc2VuY2lhIGRlICoqaGV0ZXJvY2VkYXN0aWNpZGFkKiogcHVlZGUgaW5kaWNhciBxdWUgZWwgbW9kZWxvICoqbm8gZXN0w6EgY2FwdHVyYW5kbyBhZGVjdWFkYW1lbnRlIGxhIHZhcmlhYmlsaWRhZCBkZSBsb3MgZGF0b3MqKiwgbG8gcXVlIHBvZHLDrWEgYWZlY3RhciBsYSBwcmVjaXNpw7NuIGRlIHN1cyBwcmVkaWNjaW9uZXMuIFBhcmEgY29ycmVnaXIgZXN0ZSBwcm9ibGVtYSwgc2UgcHVlZGVuIGFwbGljYXIgKip0cmFuc2Zvcm1hY2lvbmVzIGVuIGxhcyB2YXJpYWJsZXMqKiwgY29tbyBlbCB1c28gZGUgbG9nYXJpdG1vcyBvIHJhw61jZXMgY3VhZHJhZGFzLCBvIHV0aWxpemFyICoqbcOpdG9kb3MgZGUgcmVncmVzacOzbiByb2J1c3RvcyoqIHF1ZSBhanVzdGVuIGxvcyBlcnJvcmVzIGVzdMOhbmRhciBwYXJhIGhhY2VybG9zIG1lbm9zIHNlbnNpYmxlcyBhIGxhIHZhcmlhYmlsaWRhZCBkZXNpZ3VhbC4NCg0KQWRlbcOhcywgc2kgbG9zIHJlc2lkdW9zIG11ZXN0cmFuIHVuYSAqKnRlbmRlbmNpYSBjdXJ2YSBvIHBhdHJvbmVzIGRlIGFncnVwYWNpw7NuKiosIGVzdG8gcG9kcsOtYSBzZXIgdW5hIHNlw7FhbCBkZSBxdWUgZWwgKiptb2RlbG8gbGluZWFsIG5vIGVzIGxhIG1lam9yIG9wY2nDs24qKi4gRW4gZXN0b3MgY2Fzb3MsIHBvZHLDrWEgc2VyIG5lY2VzYXJpbyByZWN1cnJpciBhIHVuICoqbW9kZWxvIG5vIGxpbmVhbCoqIG8gaW5jbHVpciAqKnTDqXJtaW5vcyBwb2xpbm9taWFsZXMqKiBlbiBsYSByZWdyZXNpw7NuIHBhcmEgY2FwdHVyYXIgbWVqb3IgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyB2YXJpYWJsZXMgeSBtZWpvcmFyIGxhIHByZWNpc2nDs24gZGVsIGFqdXN0ZS4NCg0KYGBge3IgdW5pdmFyX3BsX3J2YW1wX2VxdF9xcV9wbG90LCB3YXJuaW5nPUZBTFNFfQ0KDQojIENyZWFyIHVuIGdyw6FmaWNvIFEtUSBkZSBsb3MgcmVzaWR1b3MNCnFxbm9ybShyZXNfcGxfcnZhbXAsIG1haW4gPSAiR3LDoWZpY28gUS1RIGRlIGxvcyBSZXNpZHVvcyIsIGNvbD0iaW5kaWFucmVkIikNCg0KYGBgDQoNCkVsIGFuw6FsaXNpcyBkZWwgKipncsOhZmljbyBRLVEgZGUgbG9zIHJlc2lkdW9zKiogbXVlc3RyYSAqKmRlc3ZpYWNpb25lcyBzaWduaWZpY2F0aXZhcyBlbiBsb3MgZXh0cmVtb3MqKiwgZXNwZWNpYWxtZW50ZSBlbiBsb3MgY3VhbnRpbGVzIG3DoXMgYmFqb3MgeSBtw6FzIGFsdG9zLiBFc3RvIHN1Z2llcmUgcXVlIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIHJlc2lkdW9zICoqbm8gc2lndWUgY29tcGxldGFtZW50ZSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwqKiB5IHF1ZSAqKmxhcyBjb2xhcyBkZSBsYSBkaXN0cmlidWNpw7NuIHNvbiBtw6FzIHBlc2FkYXMgZGUgbG8gZXNwZXJhZG8qKi4gRW4gb3RyYXMgcGFsYWJyYXMsIGhheSBtw6FzIHZhbG9yZXMgZXh0cmVtb3MgZW4gbG9zIHJlc2lkdW9zIGRlIGxvIHF1ZSBzZSBlc3BlcmFyw61hIGVuIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbCBpZGVhbC4NCg0KTG9zIHJlc2lkdW9zIG3DoXMgYWxlamFkb3MgZGUgbGEgbWVkaWEsIHRhbnRvIGVuIGxhIGRpcmVjY2nDs24gKipuZWdhdGl2YSBjb21vIHBvc2l0aXZhKiosIHNlIGRlc3bDrWFuIG5vdGFibGVtZW50ZSBkZSBsYSAqKmzDrW5lYSB0ZcOzcmljYSoqLCBsbyBxdWUgaW5kaWNhIGxhIHByZXNlbmNpYSBkZSB2YWxvcmVzIGF0w61waWNvcyBxdWUgcG9kcsOtYW4gZXN0YXIgYWZlY3RhbmRvIGVsIG1vZGVsby4gQSBwZXNhciBkZSBlc3RvLCBsYSBtYXlvciBwYXJ0ZSBkZSBsb3MgcHVudG9zIGVuIGxhICoqem9uYSBjZW50cmFsKiogZGVsIGdyw6FmaWNvIHBhcmVjZW4gYWxpbmVhcnNlIG1lam9yIGNvbiBsYSBkaXN0cmlidWNpw7NuIG5vcm1hbCwgYXVucXVlIGxvcyBleHRyZW1vcyBtdWVzdHJhbiB1bmEgY3VydmF0dXJhIGV2aWRlbnRlLg0KDQpMYSBmYWx0YSBkZSBub3JtYWxpZGFkIGVuIGxvcyByZXNpZHVvcyBwb25lIGVuIGR1ZGEgbGEgKip2YWxpZGV6IGRlIGxvcyBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YSB5IGxhcyBwcnVlYmFzIGRlIGhpcMOzdGVzaXMgZGVsIG1vZGVsbyoqLCB5YSBxdWUgbXVjaG9zIHByb2NlZGltaWVudG9zIGVzdGFkw61zdGljb3MgZGVwZW5kZW4gZGUgZXN0YSBzdXBvc2ljacOzbi4gTGEgcHJlc2VuY2lhIGRlIHZhbG9yZXMgZXh0cmVtb3MgdGFtYmnDqW4gc3VnaWVyZSBxdWUgKipvdXRsaWVycyBvIHVuYSBkaXN0cmlidWNpw7NuIHNlc2dhZGEqKiBwb2Ryw61hbiBlc3RhciBpbmZsdXllbmRvIGVuIGVsIGNvbXBvcnRhbWllbnRvIGRlbCBtb2RlbG8uIFBhcmEgYWJvcmRhciBlc3RlIHByb2JsZW1hLCBzZSBwdWVkZW4gY29uc2lkZXJhciAqKnRyYW5zZm9ybWFjaW9uZXMgZGUgbGFzIHZhcmlhYmxlcywgbGEgZWxpbWluYWNpw7NuIGRlIHZhbG9yZXMgYXTDrXBpY29zKiogbyBlbCB1c28gZGUgKiptb2RlbG9zIG3DoXMgcm9idXN0b3MqKiBxdWUgbm8gZGVwZW5kYW4gZXN0cmljdGFtZW50ZSBkZSBsYSBub3JtYWxpZGFkIGRlIGxvcyBlcnJvcmVzLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3J2YW1wX3NoYXBpcm9fdGVzdH0NCg0KIyBQcnVlYmEgZGUgbm9ybWFsaWRhZCBkZSBTaGFwaXJvLVdpbGsNCnNoYXBpcm9fdGVzdF9wbF9ydmFtcCA8LSBzaGFwaXJvLnRlc3QocmVzX3BsX3J2YW1wKQ0KDQpzaGFwaXJvX3Rlc3RfcGxfcnZhbXANCg0KYGBgDQoNCkVsIHJlc3VsdGFkbyBkZSBsYSAqKnBydWViYSBkZSBub3JtYWxpZGFkIGRlIFNoYXBpcm8tV2lsayoqIGluZGljYSBxdWUgbG9zIHJlc2lkdW9zICoqbm8gc2lndWVuIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbCoqLCBjb24gdW4gKiplc3RhZMOtc3RpY28gVyBkZSAwLjg2NzA4KiogeSB1biAqKnAtdmFsb3IgZGUgMC4wMDAwMDMyMDcqKi4gRGFkbyBxdWUgZXN0ZSBwLXZhbG9yIGVzIGV4dHJlbWFkYW1lbnRlIGJham8sIGhheSBzdWZpY2llbnRlIGV2aWRlbmNpYSBwYXJhIHJlY2hhemFyIGxhIGhpcMOzdGVzaXMgZGUgbm9ybWFsaWRhZC4NCg0KQXVucXVlIGVuIGVsICoqZ3LDoWZpY28gUS1RKiogbG9zIHJlc2lkdW9zIHBhcmVjw61hbiBhbGluZWFyc2UgZW4gY2llcnRhIG1lZGlkYSBjb24gbGEgbMOtbmVhIGRpYWdvbmFsLCBsYSBwcnVlYmEgZXN0YWTDrXN0aWNhIGNvbmZpcm1hIHF1ZSAqKmV4aXN0ZW4gZGVzdmlhY2lvbmVzIHNpZ25pZmljYXRpdmFzKiouIEVzdG8gc3VnaWVyZSBxdWUgbG9zIHJlc2lkdW9zIHBvZHLDrWFuIGVzdGFyIGluZmx1ZW5jaWFkb3MgcG9yIGxhICoqcHJlc2VuY2lhIGRlIHZhbG9yZXMgYXTDrXBpY29zKiogbyBxdWUgc3UgZGlzdHJpYnVjacOzbiB0aWVuZSBjYXJhY3RlcsOtc3RpY2FzIGRpZmVyZW50ZXMgYSBsYXMgZGUgdW5hIG5vcm1hbCBpZGVhbC4NCg0KTGEgZmFsdGEgZGUgbm9ybWFsaWRhZCBlbiBsb3MgcmVzaWR1b3MgcG9kcsOtYSBhZmVjdGFyIGxhICoqdmFsaWRleiBkZSBsb3MgaW50ZXJ2YWxvcyBkZSBjb25maWFuemEgeSBsYXMgcHJ1ZWJhcyBkZSBoaXDDs3Rlc2lzKiosIGxvIHF1ZSBoYWNlIG5lY2VzYXJpbyBjb25zaWRlcmFyIHBvc2libGVzIHNvbHVjaW9uZXMsIGNvbW8gYXBsaWNhciAqKnRyYW5zZm9ybWFjaW9uZXMgYSBsb3MgZGF0b3MqKiwgZWxpbWluYXIgdmFsb3JlcyBleHRyZW1vcyBvIHV0aWxpemFyICoqbcOpdG9kb3MgZXN0YWTDrXN0aWNvcyBtw6FzIHJvYnVzdG9zKiogcXVlIG5vIGRlcGVuZGFuIGVzdHJpY3RhbWVudGUgZGUgbGEgbm9ybWFsaWRhZCBkZSBsb3MgZXJyb3Jlcy4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF9ydmFtcF9ydmFtcF9icF90ZXN0fQ0KDQojIFBydWViYSBkZSBob21vY2VkYXN0aWNpZGFkIGRlIEJyZXVzY2gtUGFnYW4NCmxpYnJhcnkobG10ZXN0KQ0KDQojIFBydWViYSBkZSBCcmV1c2NoLVBhZ2FuDQpicF90ZXN0X3BsX3J2YW1wIDwtIGJwdGVzdChtb2RlbF9wbF9ydmFtcCkNCg0KYnBfdGVzdF9wbF9ydmFtcA0KDQpgYGANCg0KRWwgcmVzdWx0YWRvIGRlbCAqKnRlc3QgZGUgQnJldXNjaC1QYWdhbioqIGluZGljYSBsYSBwcmVzZW5jaWEgZGUgKipoZXRlcm9jZWRhc3RpY2lkYWQgc2lnbmlmaWNhdGl2YSoqLCBjb24gdW4gKiplc3RhZMOtc3RpY28gQlAgZGUgMTAuMDk2KiogeSB1biAqKnAtdmFsb3IgZGUgMC4wMDE0ODYqKi4gRXN0byBzaWduaWZpY2EgcXVlIGxhICoqdmFyaWFuemEgZGUgbG9zIGVycm9yZXMgbm8gZXMgY29uc3RhbnRlKiosIGxvIHF1ZSBwdWVkZSBjb21wcm9tZXRlciBsYSBwcmVjaXNpw7NuIGRlIGxhcyAqKmVzdGltYWNpb25lcyBkZWwgbW9kZWxvIHkgbGFzIHBydWViYXMgZGUgaGlww7N0ZXNpcyoqLg0KDQpEYWRvIHF1ZSBlbCBtb2RlbG8gbm8gY3VtcGxlIGNvbiBsYSAqKnN1cG9zaWNpw7NuIGRlIGhvbW9jZWRhc3RpY2lkYWQqKiB5LCBhZGVtw6FzLCBsb3MgcmVzaWR1b3MgKipubyBzaWd1ZW4gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsKiosIHNlIGJ1c2NhIGNvcnJlZ2lyIGxhIGhldGVyb2NlZGFzdGljaWRhZCBtZWRpYW50ZSB1bmEgKip0cmFuc2Zvcm1hY2nDs24gZGUgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUqKi4gUGFyYSBkZXRlcm1pbmFyIGN1w6FsIGVzIGxhIG1lam9yIHRyYW5zZm9ybWFjacOzbiwgc2UgbGxldmEgYSBjYWJvIHVuYSAqKnBydWViYSBkZSBCb3gtQ294KiosIHF1ZSBwZXJtaXRlIGlkZW50aWZpY2FyIGxhIGZvcm1hIG3DoXMgYWRlY3VhZGEgcGFyYSBlc3RhYmlsaXphciBsYSB2YXJpYW56YSBkZSBsb3MgZXJyb3JlcyB5IG1lam9yYXIgZWwgYWp1c3RlIGRlbCBtb2RlbG8uDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcnZhbXBfYm94Y294LCB3YXJuaW5nPUZBTFNFfQ0KDQojIFBydWViYSBkZSBCb3gtQ294IHBhcmEgdHJhbnNmb3JtYXIgbGEgdmFyaWFibGUgcGxfcnZhbXANCmxpYnJhcnkoTUFTUykNCg0KIyBQcnVlYmEgZGUgQm94LUNveA0KYm94Y294X3BsX3J2YW1wIDwtIGJveGNveChtb2RlbF9wbF9ydmFtcCwgbGFtYmRhID0gc2VxKC0yLCAyLCBieSA9IDAuMSkpDQoNCmBgYA0KDQpFbCAqKnBpY28gZGUgbGEgY3VydmEqKiBlbiBsYSBwcnVlYmEgZGUgKipCb3gtQ294Kiogc2UgZW5jdWVudHJhIGNlcmNhIGRlICoqbGFtYmRhID0gMCoqLCBsbyBxdWUgaW5kaWNhIHF1ZSBsYSBtZWpvciB0cmFuc2Zvcm1hY2nDs24gcGFyYSBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSBzZSBlbmN1ZW50cmEgZW4gZXNhIHpvbmEuIEVuIHTDqXJtaW5vcyBwcsOhY3RpY29zLCBjdWFuZG8gZWwgdmFsb3Igw7NwdGltbyBkZSAqKmxhbWJkYSAozrspKiogZXMgKiowKiosIGxhIHRyYW5zZm9ybWFjacOzbiByZWNvbWVuZGFkYSBlcyBlbCAqKmxvZ2FyaXRtbyBuYXR1cmFsKiogZGUgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUuDQoNCkRhZG8gcXVlICoqzrsgPSAwIGVzdMOhIGRlbnRybyBkZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSoqLCBlc3RvIGNvbmZpcm1hIHF1ZSBhcGxpY2FyIHVuYSAqKnRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EgKGBsb2coWSlgKSoqIGVzIGxhIG9wY2nDs24gbcOhcyBhZGVjdWFkYS4gRXN0ZSB0aXBvIGRlIHRyYW5zZm9ybWFjacOzbiBlcyDDunRpbCBwb3JxdWUgcHVlZGUgKipyZWR1Y2lyIGxhIGhldGVyb2NlZGFzdGljaWRhZCoqLCBtZWpvcmFyIGxhICoqbm9ybWFsaWRhZCBkZSBsb3MgcmVzaWR1b3MqKiB5IGhhY2VyIHF1ZSBsYSByZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBzZWEgKiptw6FzIGxpbmVhbCoqLCBsbyBxdWUgcGVybWl0ZSBxdWUgZWwgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gdGVuZ2EgdW4gbWVqb3IgYWp1c3RlIHkgc2VhIG3DoXMgcHJlY2lzbyBlbiBzdXMgZXN0aW1hY2lvbmVzLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3J2YW1wX2xvZ190cmFuc2Z9DQoNCiMgUmVncmVzacOzbiBkZSBsb2cocGxfcmFkaikgY29uIGxvZ3BsX3J2YW1wDQptb2RlbF9wbF9ydmFtcF9sb2cgPC0gbG0obG9nKHBsX3JhZGopIH4gbG9nKHBsX3J2YW1wKSwgZGF0YSA9IGtlcGxlcl9kYXRhX251bSkNCg0KbW9kZWxfcGxfcnZhbXBfbG9nX3N1bW1hcnkgPC0gc3VtbWFyeShtb2RlbF9wbF9ydmFtcF9sb2cpDQoNCm1vZGVsX3BsX3J2YW1wX2xvZ19zdW1tYXJ5DQoNCmBgYA0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3J2YW1wX2xvZ190cmFuc2ZfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBTY2F0dGVyIHBsb3QgZGUgbG9nKHBsX3JhZGopIHZzIHBsX3J2YW1wIGNvbiBsYSByZWN0YSBkZSByZWdyZXNpw7NuIGVuIHJvam8NCiMgeSBsb3MgbWFyZ2VuZXMgZGUgY29uZmlhbnphIGVuIGdyaXMNCmdncGxvdChrZXBsZXJfZGF0YV9udW0sIGFlcyh4ID0gcGxfcnZhbXAsIHkgPSBsb2cocGxfcmFkaikpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJpbmRpYW5yZWQiLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMikgKw0KICBsYWJzKHRpdGxlID0gIlJlZ3Jlc2nDs24gTGluZWFsOiBMb2dhcml0bW8gZGVsIFJhZGlvIGRlbCBFeG9wbGFuZXRhIHNlZ3VuIExvZ2FyaXRtbyBkZSBsYSBBbXBsaXR1ZCBkZSBsYSBWZWxvY2lkYWQgUmFkaWFsIiwNCiAgICAgICB4ID0gIkxvZ2FyaXRtbyBkZSBsYSBBbXBsaXR1ZCBkZSBsYSBWZWxvY2lkYWQgUmFkaWFsIiwNCiAgICAgICB5ID0gIkxvZ2FyaXRtbyBkZWwgUmFkaW8gZGVsIEV4b3BsYW5ldGEgKErDunBpdGVyKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpQYXJhIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIHBsYW50ZWFkbzoNCg0KJCQNCmxvZyhwbFxfcmFkaikgPSBcYmV0YV8wICsgXGJldGFfMSBcY2RvdCBwbFxfcnZhbXAgKyBcdmFyZXBzaWxvbg0KJCQNCg0KRWwgYW7DoWxpc2lzIGRlbCBtb2RlbG8gZGVzcHXDqXMgZGUgYXBsaWNhciBsYSAqKnRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EqKiBtdWVzdHJhIHVuYSBtZWpvcmEgc2lnbmlmaWNhdGl2YSBlbiBzdSBjYXBhY2lkYWQgcHJlZGljdGl2YS4gRWwgKipSwrIgb2J0ZW5pZG8gZXMgZGUgODQuMjUlKiosIGxvIHF1ZSBpbmRpY2EgcXVlIGVsIG1vZGVsbyBleHBsaWNhIHVuYSBncmFuIHBhcnRlIGRlIGxhIHZhcmlhYmlsaWRhZCBlbiAqKmxvZyhgcGxfcmFkamApKiosIHJlcHJlc2VudGFuZG8gdW4gYWp1c3RlIGV4Y2VsZW50ZS4gRXN0ZSByZXN1bHRhZG8gZXMgY29uc2lkZXJhYmxlbWVudGUgbWVqb3IgcXVlIGVsIGRlbCBtb2RlbG8gc2luIHRyYW5zZm9ybWFjacOzbiwgZG9uZGUgZWwgKipSwrIgZXJhIGFwcm94aW1hZGFtZW50ZSA1My42NyUqKi4NCg0KSW5jbHVzbyBhbCBjb3JyZWdpciBwb3IgZWwgbsO6bWVybyBkZSBwcmVkaWN0b3JlcywgZWwgKipSwrIgYWp1c3RhZG8qKiBzaWd1ZSBzaWVuZG8gYWx0bywgY29uIHVuIHZhbG9yIGRlICoqODQuMDElKiosIGxvIHF1ZSBjb25maXJtYSBxdWUgZWwgbW9kZWxvIG1hbnRpZW5lIHN1IHNvbGlkZXogeSBubyBzZSB2ZSBhZmVjdGFkbyBwb3IgdW4gZXhjZXNvIGRlIHByZWRpY3RvcmVzIGlubmVjZXNhcmlvcy4gQWRlbcOhcywgZWwgKiplc3RhZMOtc3RpY28gRioqLCBjb24gdW4gdmFsb3IgZGUgKiozNTMqKiB5IHVuICoqcC12YWxvciBleHRyZW1hZGFtZW50ZSBiYWpvIChcPCAyLjIgw5cgMTDigbvCueKBtikqKiwgY29uZmlybWEgcXVlIGVsIG1vZGVsbyBlcyBhbHRhbWVudGUgc2lnbmlmaWNhdGl2byB5IHF1ZSBsYSByZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBubyBlcyBwcm9kdWN0byBkZWwgYXphci4NCg0KRW4gY29uY2x1c2nDs24sIGxhICoqdHJhbnNmb3JtYWNpw7NuIGxvZ2Fyw610bWljYSBoYSBtZWpvcmFkbyBzaWduaWZpY2F0aXZhbWVudGUgZWwgYWp1c3RlIGRlbCBtb2RlbG8qKiBlbiBjb21wYXJhY2nDs24gY29uIGVsIG1vZGVsbyBzaW4gdHJhbnNmb3JtYWNpw7NuLiBMYSByZWxhY2nDs24gZW50cmUgKipgcGxfcnZhbXBgIHkgYGxvZyhwbF9yYWRqYCkqKiBlcyBmdWVydGUgeSBhbHRhbWVudGUgc2lnbmlmaWNhdGl2YSwgbG8gcXVlIHN1Z2llcmUgcXVlIGVzdGUgbW9kZWxvIGVzIG11Y2hvIG3DoXMgYWRlY3VhZG8gcGFyYSBkZXNjcmliaXIgbGEgcmVsYWNpw7NuIGVudHJlIGVzdGFzIHZhcmlhYmxlcyB5IG9mcmVjZSBlc3RpbWFjaW9uZXMgbcOhcyBwcmVjaXNhcy4NCg0KYGBge3IgdW5pdmFyX3JlZ19wbF9ydmFtcF9sb2dfdHJhbnNmX3Jlc19wbG90LCB3YXJuaW5nPUZBTFNFfQ0KDQojIE9idGVuZXIgbG9zIHJlc2lkdW9zIHkgdmFsb3JlcyBhanVzdGFkb3MNCnJlc19wbF9ydmFtcF9sb2cgPC0gcmVzaWR1YWxzKG1vZGVsX3BsX3J2YW1wX2xvZykNCg0KIyBDYWxjdWxhciBsb3MgdmFsb3JlcyBhanVzdGFkb3MNCmZpdF92YWxfcGxfcnZhbXBfbG9nIDwtIGZpdHRlZChtb2RlbF9wbF9ydmFtcF9sb2cpDQoNCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZSBjb24gbG9zIHJlc2lkdW9zIHkgdmFsb3JlcyBhanVzdGFkb3MNCnJlc19wbF9ydmFtcF9sb2dfZGYgPC0gZGF0YS5mcmFtZSgNCiAgUmVzaWR1YWxzID0gcmVzX3BsX3J2YW1wX2xvZywNCiAgRml0dGVkX1ZhbHVlcyA9IGZpdF92YWxfcGxfcnZhbXBfbG9nDQopDQoNCiMgU2NhdHRlciBwbG90IGRlIHJlc2lkdW9zIHZzIHZhbG9yZXMgYWp1c3RhZG9zDQpnZ3Bsb3QocmVzX3BsX3J2YW1wX2xvZ19kZiwgYWVzKHggPSBGaXR0ZWRfVmFsdWVzLCB5ID0gUmVzaWR1YWxzKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAiaW5kaWFucmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBsYWJzKHRpdGxlID0gIlJlc2lkdW9zIHZzIFZhbG9yZXMgQWp1c3RhZG9zIiwNCiAgICAgICB4ID0gIlZhbG9yZXMgQWp1c3RhZG9zIiwNCiAgICAgICB5ID0gIlJlc2lkdW9zIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCkRlc3B1w6lzIGRlIGFwbGljYXIgbGEgdHJhbnNmb3JtYWNpw7NuLCBzZSBvYnNlcnZhIHVuYSAqKnJlZHVjY2nDs24gZW4gbGEgZGlzcGVyc2nDs24gZGUgbG9zIHJlc2lkdW9zKiosIGxvIHF1ZSBpbmRpY2EgcXVlIGxhICoqaGV0ZXJvY2VkYXN0aWNpZGFkIGRldGVjdGFkYSBwcmV2aWFtZW50ZSBoYSBkaXNtaW51aWRvIGNvbnNpZGVyYWJsZW1lbnRlKiouIEVzdG8gc2lnbmlmaWNhIHF1ZSBsYSAqKnZhcmlhbnphIGRlIGxvcyBlcnJvcmVzIGVzIGFob3JhIG3DoXMgY29uc3RhbnRlKiogYSBsbyBsYXJnbyBkZSBsb3MgdmFsb3JlcyBhanVzdGFkb3MsIGN1bXBsaWVuZG8gbWVqb3IgY29uIGxhIHN1cG9zaWNpw7NuIGRlICoqaG9tb2NlZGFzdGljaWRhZCoqIGVuIGxhIHJlZ3Jlc2nDs24gbGluZWFsLg0KDQpMYSBkaXNtaW51Y2nDs24gZW4gbGEgdmFyaWFiaWxpZGFkIGRlIGxvcyByZXNpZHVvcyBzdWdpZXJlIHF1ZSBlbCBtb2RlbG8gaGEgbG9ncmFkbyB1biBhanVzdGUgbcOhcyBlc3RhYmxlIHkgY29uZmlhYmxlLiBFc3RvIG5vIHNvbG8gbWVqb3JhIGxhICoqcHJlY2lzacOzbiBkZSBsYXMgZXN0aW1hY2lvbmVzKiosIHNpbm8gcXVlIHRhbWJpw6luIGF1bWVudGEgbGEgKip2YWxpZGV6IGRlIGxvcyBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YSB5IGxhcyBwcnVlYmFzIGRlIGhpcMOzdGVzaXMqKiwgeWEgcXVlIGxhcyBwcmVkaWNjaW9uZXMgZGVsIG1vZGVsbyBzb24gbWVub3Mgc2Vuc2libGVzIGEgdmFsb3JlcyBleHRyZW1vcyBvIHBhdHJvbmVzIG5vIGRlc2VhZG9zIGVuIGxvcyBlcnJvcmVzLg0KDQpgYGB7ciB1bml2YXJfcmVnX3BsX3J2YW1wX2xvZ190cmFuc2ZfcXFfcGxvdCwgd2FybmluZz1GQUxTRX0NCg0KIyBDcmVhciB1biBncsOhZmljbyBRLVEgZGUgbG9zIHJlc2lkdW9zDQpxcW5vcm0ocmVzX3BsX3J2YW1wX2xvZywgbWFpbiA9ICJHcsOhZmljbyBRLVEgZGUgbG9zIFJlc2lkdW9zIiwgY29sPSJpbmRpYW5yZWQiKQ0KDQpgYGANCg0KTGEgKiphbGluZWFjacOzbiBkZSBsb3MgcHVudG9zIGNvbiBsYSBsw61uZWEgZGlhZ29uYWwqKiBlbiBlbCBncsOhZmljbyBzdWdpZXJlIHF1ZSBsb3MgcmVzaWR1b3Mgc2lndWVuICoqYXByb3hpbWFkYW1lbnRlIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbCoqLiBMYSBtYXlvciBwYXJ0ZSBkZSBsb3MgcHVudG9zIHNlIGFqdXN0YSBiaWVuIGEgbGEgbMOtbmVhIHRlw7NyaWNhLCBsbyBxdWUgaW5kaWNhIHF1ZSBlbCBzdXB1ZXN0byBkZSBub3JtYWxpZGFkIGVuIGxvcyByZXNpZHVvcyBzZSBjdW1wbGUgZW4gZ3JhbiBtZWRpZGEuDQoNClNpbiBlbWJhcmdvLCBlbiBsb3MgKipleHRyZW1vcyBkZWwgZ3LDoWZpY28qKiwgY29ycmVzcG9uZGllbnRlcyBhIGxvcyB2YWxvcmVzIG3DoXMgbmVnYXRpdm9zIHkgbcOhcyBwb3NpdGl2b3MgZGUgbG9zIHJlc2lkdW9zLCBzZSBvYnNlcnZhIHVuYSAqKmxpZ2VyYSBkZXN2aWFjacOzbioqLiBFc3RvIHN1Z2llcmUgcXVlIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIHJlc2lkdW9zIHRpZW5lICoqY29sYXMgbGlnZXJhbWVudGUgbcOhcyBwZXNhZGFzKiosIGxvIHF1ZSBpbXBsaWNhIGxhIHBvc2libGUgcHJlc2VuY2lhIGRlIGFsZ3Vub3MgdmFsb3JlcyBhdMOtcGljb3MgbyBleHRyZW1vcy4NCg0KQSBwZXNhciBkZSBlc3RhIGxldmUgZGVzdmlhY2nDs24gZW4gbG9zIHZhbG9yZXMgZXh0cmVtb3MsIGVsIHBhdHLDs24gZ2VuZXJhbCBpbmRpY2EgcXVlICoqbG9zIHJlc2lkdW9zIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwgZGUgbWFuZXJhIGFjZXB0YWJsZSoqLiBFc3RvIHNpZ25pZmljYSBxdWUgZWwgbW9kZWxvIHNpZ3VlIHNpZW5kbyAqKmVzdGFkw61zdGljYW1lbnRlIHbDoWxpZG8qKiBwYXJhIHJlYWxpemFyIGluZmVyZW5jaWFzLCBhdW5xdWUgbGEgcHJlc2VuY2lhIGRlIHZhbG9yZXMgZXh0cmVtb3MgcG9kcsOtYSBqdXN0aWZpY2FyIHVuIGFuw6FsaXNpcyBtw6FzIGRldGFsbGFkbyBzaSBzZSByZXF1aWVyZSBtYXlvciBwcmVjaXNpw7NuIGVuIGxhcyBlc3RpbWFjaW9uZXMuDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcnZhbXBfbG9nX3RyYW5zZl9zaGFwaXJvX3Rlc3R9DQoNCiMgUHJ1ZWJhIGRlIG5vcm1hbGlkYWQgZGUgU2hhcGlyby1XaWxrDQpzaGFwaXJvX3Rlc3RfcGxfcnZhbXBfbG9nIDwtIHNoYXBpcm8udGVzdChyZXNfcGxfcnZhbXBfbG9nKQ0KDQpzaGFwaXJvX3Rlc3RfcGxfcnZhbXBfbG9nDQoNCmBgYA0KDQpFbCAqKnRlc3QgZGUgbm9ybWFsaWRhZCBkZSBTaGFwaXJvLVdpbGsqKiBhcnJvamEgdW4gKiplc3RhZMOtc3RpY28gVyBkZSAwLjk3NjIyKiogeSB1biAqKnAtdmFsb3IgZGUgMC4yMTg4KiosIGxvIHF1ZSBpbmRpY2EgcXVlIG5vIGhheSBldmlkZW5jaWEgc3VmaWNpZW50ZSBwYXJhIHJlY2hhemFyIGxhIGhpcMOzdGVzaXMgZGUgbm9ybWFsaWRhZC4gRXN0byBzaWduaWZpY2EgcXVlIGxvcyAqKnJlc2lkdW9zIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwqKiwgY3VtcGxpZW5kbyBjb24gdW5hIGRlIGxhcyBwcmluY2lwYWxlcyBzdXBvc2ljaW9uZXMgZGVsIG1vZGVsby4NCg0KU2kgYmllbiBlbCAqKmdyw6FmaWNvIFEtUSoqIHlhIG1vc3RyYWJhIHVuYSBidWVuYSBhbGluZWFjacOzbiBkZSBsb3MgcHVudG9zIGNvbiBsYSBsw61uZWEgZGlhZ29uYWwsIGxhIHBydWViYSBlc3RhZMOtc3RpY2EgKipjb25maXJtYSBkZSBtYW5lcmEgbcOhcyByaWd1cm9zYSoqIHF1ZSBsb3MgcmVzaWR1b3Mgbm8gcHJlc2VudGFuIGRlc3ZpYWNpb25lcyBzaWduaWZpY2F0aXZhcyByZXNwZWN0byBhIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbC4gRXN0byByZWZ1ZXJ6YSBsYSB2YWxpZGV6IGRlbCBtb2RlbG8geSBsYSBmaWFiaWxpZGFkIGRlIHN1cyBlc3RpbWFjaW9uZXMuDQoNCmBgYHtyIHVuaXZhcl9yZWdfcGxfcnZhbXBfbG9nX3RyYW5zZl9icF90ZXN0fQ0KDQojIFBydWViYSBkZSBob21vY2VkYXN0aWNpZGFkIGRlIEJyZXVzY2gtUGFnYW4NCmxpYnJhcnkobG10ZXN0KQ0KDQojIFBydWViYSBkZSBCcmV1c2NoLVBhZ2FuDQpicF90ZXN0X3BsX3J2YW1wX2xvZyA8LSBicHRlc3QobW9kZWxfcGxfcnZhbXBfbG9nKQ0KDQpicF90ZXN0X3BsX3J2YW1wX2xvZw0KDQpgYGANCg0KRWwgKip0ZXN0IGRlIGhvbW9jZWRhc3RpY2lkYWQgZGUgQnJldXNjaC1QYWdhbioqIG11ZXN0cmEgdW4gKiplc3RhZMOtc3RpY28gQlAgZGUgMC40ODg2NSoqIHkgdW4gKipwLXZhbG9yIGRlIDAuNDg0NSoqLCBsbyBxdWUgaW5kaWNhIHF1ZSBubyBoYXkgZXZpZGVuY2lhIGRlICoqaGV0ZXJvY2VkYXN0aWNpZGFkIHNpZ25pZmljYXRpdmEqKiBlbiBlbCBtb2RlbG8uIEVzdG8gc2lnbmlmaWNhIHF1ZSBsYSAqKnZhcmlhbnphIGRlIGxvcyBlcnJvcmVzIGVzIGNvbnN0YW50ZSoqLCBjdW1wbGllbmRvIGNvbiB1bmEgZGUgbGFzIHN1cG9zaWNpb25lcyBjbGF2ZSBkZSBsYSByZWdyZXNpw7NuIGxpbmVhbC4gRGFkbyBxdWUgbG9zIG1vZGVsb3MgYW50ZXJpb3JlcyBwcmVzZW50YWJhbiBwcm9ibGVtYXMgZGUgaGV0ZXJvY2VkYXN0aWNpZGFkLCBlc3RvcyByZXN1bHRhZG9zIGNvbmZpcm1hbiBxdWUgKipsYSB0cmFuc2Zvcm1hY2nDs24gbG9nYXLDrXRtaWNhIGFwbGljYWRhIGEgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUgY29ycmlnacOzIGVmaWNhem1lbnRlIGVzdGUgcHJvYmxlbWEqKi4NCg0KVHJhcyBldmFsdWFyIGxvcyAqKnRyZXMgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbCB1bml2YXJpYWRhKiosIHNlIGNvbmNsdXllIHF1ZSBlbCBtb2RlbG8gKipgcGxfcmFkaiB+IHBsX3J2YW1wYCBjb24gdHJhbnNmb3JtYWNpw7NuIGxvZ2Fyw610bWljYSoqIGVzIGVsIHF1ZSBvZnJlY2UgZWwgKiptZWpvciBhanVzdGUqKi4NCg0KJCQNCmxvZyhwbFxfcmFkaikgPSBcYmV0YV8wICsgXGJldGFfMSBcY2RvdCBwbFxfcnZhbXAgKyBcdmFyZXBzaWxvbg0KJCQNCg0KRXN0ZSBtb2RlbG8gZXhwbGljYSBlbCAqKjg0LjI1JSBkZSBsYSB2YXJpYWJpbGlkYWQgZW4gYGxvZyhwbF9yYWRqKWAqKiwgbG8gcXVlIGluZGljYSB1bmEgY2FwYWNpZGFkIHByZWRpY3RpdmEgZXhjZWxlbnRlLiBBZGVtw6FzLCBsYSByZWxhY2nDs24gZW50cmUgKipgcGxfcnZhbXBgIHkgYGxvZyhwbF9yYWRqKWAqKiBlcyAqKmZ1ZXJ0ZSB5IGFsdGFtZW50ZSBzaWduaWZpY2F0aXZhKiosIGNvbiByZXNpZHVvcyBxdWUgc2lndWVuIHVuYSAqKmRpc3RyaWJ1Y2nDs24gbm9ybWFsKiogeSAqKm5vIHByZXNlbnRhbiBoZXRlcm9jZWRhc3RpY2lkYWQgc2lnbmlmaWNhdGl2YSoqLg0KDQojIyMgQ29uY2x1c2nDs24gc29icmUgbG9zIG1vZGVsb3MgbGluZWFsZXMgdW5pdmFyaWFkb3MgcGxhbnRlYWRvcw0KDQpBIGxvIGxhcmdvIGRlbCBhbsOhbGlzaXMsIHNlIHByb2Jhcm9uIGRpZmVyZW50ZXMgZW5mb3F1ZXMgcGFyYSBhanVzdGFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzLCBjb25zaWRlcmFuZG8gdGFudG8gbW9kZWxvcyBzaW4gdHJhbnNmb3JtYWNpw7NuIGNvbW8gY29uIHRyYW5zZm9ybWFjaW9uZXMgbWF0ZW3DoXRpY2FzIHBhcmEgbWVqb3JhciBzdSBlc3RhYmlsaWRhZC4gSW5pY2lhbG1lbnRlLCBsb3MgbW9kZWxvcyBzaW4gdHJhbnNmb3JtYWNpw7NuIG1vc3RyYXJvbiAqKnByb2JsZW1hcyBkZSBoZXRlcm9jZWRhc3RpY2lkYWQgeSBub3JtYWxpZGFkIGVuIGxvcyByZXNpZHVvcyoqLCBsbyBxdWUgYWZlY3RhYmEgbGEgdmFsaWRleiBkZSBzdXMgaW5mZXJlbmNpYXMuIFNpbiBlbWJhcmdvLCBsYSAqKmFwbGljYWNpw7NuIGRlIHVuYSB0cmFuc2Zvcm1hY2nDs24gbG9nYXLDrXRtaWNhIGEgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUgKGBwbF9yYWRqYCkgcGVybWl0acOzIGNvcnJlZ2lyIGVzdG9zIHByb2JsZW1hcyoqLCBsb2dyYW5kbyB1biBtb2RlbG8gbcOhcyBlc3RhYmxlIHkgY29uZmlhYmxlLg0KDQpgYGB7ciB1bml2YXJfcmVnX3N1bW1hcnl9DQoNCiMgUmVzdW1lbiBkZSBsb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbCB1bml2YXJpYWRhDQptb2RlbF9zdW1tYXJpZXMgPC0gbGlzdCgNCiAgbW9kZWxfcGxfcmF0ZG9yX3N1bW1hcnksDQogIG1vZGVsX3BsX3RyYW5kZXBfc3VtbWFyeSwNCiAgbW9kZWxfcGxfdHJhbmRlcF9zcXVhcmVfc3VtbWFyeSwNCiAgbW9kZWxfcGxfcnZhbXBfc3VtbWFyeSwNCiAgbW9kZWxfcGxfcnZhbXBfbG9nX3N1bW1hcnkNCikNCg0KbW9kZWxfc3VtbWFyaWVzDQoNCmBgYA0KDQpFbCAqKm1vZGVsbyBmaW5hbCBjb24gdHJhbnNmb3JtYWNpw7NuIGxvZ2Fyw610bWljYSoqIG5vIHNvbG8gb2ZyZWNlIHVuIG1lam9yIGFqdXN0ZSB5IG1heW9yIGNhcGFjaWRhZCBleHBsaWNhdGl2YSwgc2lubyBxdWUgdGFtYmnDqW4gY3VtcGxlIGNvbiBsb3MgKipzdXB1ZXN0b3MgY2xhdmUgZGUgbGEgcmVncmVzacOzbiBsaW5lYWwqKiwgbG8gcXVlIGxvIGNvbnZpZXJ0ZSBlbiBsYSBtZWpvciBvcGNpw7NuIHBhcmEgbW9kZWxhciBsYSByZWxhY2nDs24gZW50cmUgKipgcGxfcmFkamAqKiB5ICoqYHBsX3J2YW1wYCoqLiBFc3RlIHJlc3VsdGFkbyBzdWJyYXlhIGxhIGltcG9ydGFuY2lhIGRlIGV2YWx1YXIgbGEgY2FsaWRhZCBkZWwgYWp1c3RlIHkgZGUgcmVhbGl6YXIgKip0cmFuc2Zvcm1hY2lvbmVzIGFkZWN1YWRhcyoqIGN1YW5kbyBzZSBkZXRlY3RhbiBkZXN2aWFjaW9uZXMgZW4gbG9zIHN1cHVlc3RvcyBkZWwgbW9kZWxvLCBnYXJhbnRpemFuZG8gYXPDrSBlc3RpbWFjaW9uZXMgbcOhcyBwcmVjaXNhcyB5IHJvYnVzdGFzLg0KDQojIyBSZWdyZXNpw7NuIGxpbmVhbCBtdWx0aXZhcmlhZGENCg0KUGFyYSBtZWpvcmFyIGxhIHByZWNpc2nDs24gZW4gbGEgcHJlZGljY2nDs24gZGVsICoqcmFkaW8gZGVsIGV4b3BsYW5ldGEgKGBwbF9yYWRqYCkqKiwgc2UgbGxldmEgYSBjYWJvIHVuICoqYW7DoWxpc2lzIGRlIHJlZ3Jlc2nDs24gbGluZWFsIG11bHRpdmFyaWFkYSoqLiBFbiBlc3RlIGVuZm9xdWUsIHNlIGNvbnNpZGVyYW4gc2ltdWx0w6FuZWFtZW50ZSB0cmVzIHZhcmlhYmxlcyBleHBsaWNhdGl2YXMgcXVlIHBvZHLDrWFuIGluZmx1aXIgZW4gZWwgcmFkaW8gZGVsIGV4b3BsYW5ldGE6DQoNCjEuICAqKkVsIGNvY2llbnRlIGRlbCByYWRpbyBwbGFuZXRhcmlvIHNvYnJlIGVsIHJhZGlvIGVzdGVsYXIgKGBwbF9yYXRkb3JgKSoqLCBxdWUgcmVwcmVzZW50YSBlbCB0YW1hw7FvIHJlbGF0aXZvIGRlbCBleG9wbGFuZXRhIGVuIGNvbXBhcmFjacOzbiBjb24gc3UgZXN0cmVsbGEuXA0KMi4gICoqTGEgcHJvZnVuZGlkYWQgZGVsIHRyw6Fuc2l0byAoYHBsX3RyYW5kZXBgKSoqLCBxdWUgbWlkZSBsYSBkaXNtaW51Y2nDs24gZW4gZWwgYnJpbGxvIGRlIGxhIGVzdHJlbGxhIGN1YW5kbyBlbCBleG9wbGFuZXRhIHBhc2EgZnJlbnRlIGEgZWxsYSwgbG8gcXVlIGVzdMOhIGRpcmVjdGFtZW50ZSByZWxhY2lvbmFkbyBjb24gc3UgdGFtYcOxby5cDQozLiAgKipMYSBhbXBsaXR1ZCBkZSBsYSB2ZWxvY2lkYWQgcmFkaWFsIGRlbCBwbGFuZXRhIChgcGxfcnZhbXBgKSoqLCBxdWUgcmVmbGVqYSBlbCBpbXBhY3RvIGdyYXZpdGFjaW9uYWwgZGVsIGV4b3BsYW5ldGEgc29icmUgc3UgZXN0cmVsbGEgeSBwdWVkZSBwcm9wb3JjaW9uYXIgaW5mb3JtYWNpw7NuIHNvYnJlIHN1IG1hc2EgeSwgZW4gY29tYmluYWNpw7NuIGNvbiBvdHJhcyB2YXJpYWJsZXMsIHN1IHJhZGlvLg0KDQpFc3RlIG1vZGVsbyBkZSByZWdyZXNpw7NuIG11bHRpdmFyaWFkYSBwZXJtaXRlIGFuYWxpemFyICoqY8OzbW8gZXN0YXMgdHJlcyB2YXJpYWJsZXMgaW5mbHV5ZW4gZW4gY29uanVudG8qKiBlbiBsYSBwcmVkaWNjacOzbiBkZWwgcmFkaW8gZGVsIGV4b3BsYW5ldGEsIGVuIGx1Z2FyIGRlIGV2YWx1YXIgY2FkYSB1bmEgcG9yIHNlcGFyYWRvLiBBbCBjb25zaWRlcmFyIG3Dumx0aXBsZXMgZmFjdG9yZXMgYWwgbWlzbW8gdGllbXBvLCBzZSBlc3BlcmEgb2J0ZW5lciB1biAqKm1vZGVsbyBtw6FzIHByZWNpc28geSByb2J1c3RvKiosIGNhcGF6IGRlIGNhcHR1cmFyIG1lam9yIGxhIHZhcmlhYmlsaWRhZCBlbiBsb3MgZGF0b3MgeSBwcm9wb3JjaW9uYXIgZXN0aW1hY2lvbmVzIG3DoXMgY29uZmlhYmxlcyBkZWwgdGFtYcOxbyBkZSBsb3MgZXhvcGxhbmV0YXMuDQoNCmBgYHtyIG11bHRpdmFyX3JlZ30NCg0KIyBSZWdyZXNpb24gZGUgcGxfcmFkaiBjb24gcGxfcmF0ZG9yLCBwbF90cmFuZGVwIHkgcGxfcnZhbXANCm1vZGVsX211bHRpdmFyIDwtIGxtKHBsX3JhZGogfiBwbF9yYXRkb3IgKyBwbF90cmFuZGVwICsgcGxfcnZhbXAsIGRhdGEgPSBrZXBsZXJfZGF0YV9udW0pDQoNCm1vZGVsX211bHRpdmFyX3N1bW1hcnkgPC0gc3VtbWFyeShtb2RlbF9tdWx0aXZhcikNCg0KbW9kZWxfbXVsdGl2YXJfc3VtbWFyeQ0KDQpgYGANCg0KRWwgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gcGxhbnRlYWRvOg0KDQokJA0KcGxcX3JhZGogPSBcYmV0YV8wICsgXGJldGFfMSBcY2RvdCBwbFxfcmF0ZG9yICsgXGJldGFfMiBcY2RvdCBwbFxfdHJhbmRlcCArIFxiZXRhXzMgXGNkb3QgcGxcX3J2YW1wICsgXHZhcmVwc2lsb24NCiQkIFByZXNlbnRhIGJ1ZW5hcyBlc3RhZMOtc3RpY2FzIHBvciBjdWFudG86DQoNCkVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIG11ZXN0cmEgdW4gKipleGNlbGVudGUgYWp1c3RlKiosIGV4cGxpY2FuZG8gZWwgKio5Ny4zMSUgZGUgbGEgdmFyaWFiaWxpZGFkIGVuIGBwbF9yYWRqYCoqLiBJbmNsdXNvIGRlc3B1w6lzIGRlIGFqdXN0YXIgcG9yIGVsIG7Dum1lcm8gZGUgcHJlZGljdG9yZXMsIGVsICoqUsKyIGFqdXN0YWRvIHNpZ3VlIHNpZW5kbyBhbHRvLCBjb24gdW4gOTUuMyUqKiwgbG8gcXVlIGluZGljYSBxdWUgZWwgbW9kZWxvIGdlbmVyYWxpemEgYmllbiB5IG1hbnRpZW5lIHVuYSBmdWVydGUgY2FwYWNpZGFkIHByZWRpY3RpdmEuIEFkZW3DoXMsIGVsICoqZXN0YWTDrXN0aWNvIEYgZGUgNDguMjgqKiB5IHVuICoqcC12YWxvciBkZSAwLjAwMTMqKiBjb25maXJtYW4gcXVlIGVsIG1vZGVsbyBlbiBzdSBjb25qdW50byBlcyAqKmFsdGFtZW50ZSBzaWduaWZpY2F0aXZvKiosIGxvIHF1ZSBzdWdpZXJlIHF1ZSBhbCBtZW5vcyB1bmEgZGUgbGFzIHZhcmlhYmxlcyBwcmVkaWN0b3JhcyB0aWVuZSB1biBpbXBhY3RvIHJlbGV2YW50ZSBlbiBsYSBlc3RpbWFjacOzbiBkZSAqKmBwbF9yYWRqYCoqLg0KDQpTaW4gZW1iYXJnbywgZXhpc3RlbiBhbGd1bmFzIGxpbWl0YWNpb25lcyBpbXBvcnRhbnRlcy4gRGVzcHXDqXMgZGUgZWxpbWluYXIgbG9zIGRhdG9zIGNvbiB2YWxvcmVzIGZhbHRhbnRlcywgKipzb2xvIHF1ZWRhbiA0IG9ic2VydmFjaW9uZXMgZWZlY3RpdmFzKiosIGxvIHF1ZSBlcyAqKmV4dHJlbWFkYW1lbnRlIGJham8qKiBwYXJhIHVuIG1vZGVsbyBjb24gdHJlcyBwcmVkaWN0b3Jlcy4gRXN0YSByZWR1Y2Npw7NuIGRyw6FzdGljYSBlbiBsYSBjYW50aWRhZCBkZSBkYXRvcyBwdWVkZSBoYWNlciBxdWUgZWwgbW9kZWxvIHNlYSBwb2NvIGNvbmZpYWJsZSB5IHF1ZSBsYXMgZXN0aW1hY2lvbmVzIGRlIGxvcyBjb2VmaWNpZW50ZXMgc2VhbiAqKmluZXN0YWJsZXMqKiwgeWEgcXVlIHNlIGJhc2FuIGVuIHVuYSBtdWVzdHJhIGRlbWFzaWFkbyBwZXF1ZcOxYS4NCg0KQWRlbcOhcywgc2UgaGFuIGRlc2NhcnRhZG8gKioyLDUzOSBvYnNlcnZhY2lvbmVzKiogZGViaWRvIGEgdmFsb3JlcyBmYWx0YW50ZXMsIGxvIHF1ZSBwbGFudGVhIGxhIG5lY2VzaWRhZCBkZSByZXZpc2FyIGxhIGVzdHJ1Y3R1cmEgZGVsIGRhdGFzZXQuIEV2YWx1YXIgc2kgc2UgcHVlZGVuIHJlY3VwZXJhciBtw6FzIG9ic2VydmFjaW9uZXMgcGVybWl0aXLDrWEgbWVqb3JhciBsYSBlc3RhYmlsaWRhZCBkZWwgbW9kZWxvIHkgZXZpdGFyIGNvbmNsdXNpb25lcyBiYXNhZGFzIGVuIHVuIG7Dum1lcm8gdGFuIHJlZHVjaWRvIGRlIGRhdG9zLg0KDQpEYWRvIHF1ZSBsYSB2YXJpYWJsZSAqKmBwbF90cmFuZGVwYCoqIGVzIGxhIG3DoXMgc2lnbmlmaWNhdGl2YSBkZW50cm8gZGVsIG1vZGVsbywgdW5hIHBvc2libGUgYWx0ZXJuYXRpdmEgc2Vyw61hICoqc2ltcGxpZmljYXIgbGEgcmVncmVzacOzbiBlbGltaW5hbmRvIGBwbF9yYXRkb3JgIHkgYHBsX3J2YW1wYCoqLCBkZWphbmRvIHNvbG8gKipgcGxfdHJhbmRlcGAqKiBjb21vIHByZWRpY3Rvci4gRXN0byBsbGV2YXLDrWEgYWwgc2VndW5kbyBtb2RlbG8gZXZhbHVhZG8sIHF1ZSBwb2Ryw61hIG9mcmVjZXIgdW4gYWp1c3RlIGlndWFsbWVudGUgYnVlbm8gcGVybyBjb24gdW5hIGVzdHJ1Y3R1cmEgbcOhcyBzZW5jaWxsYSB5IHBvc2libGVtZW50ZSBtw6FzIHJvYnVzdGEgZnJlbnRlIGEgbGEgZXNjYXNleiBkZSBkYXRvcy4NCg0KIyMgUmVncmVzacOzbiBsb2fDrXN0aWNhDQoNClBhcmEgcHJlZGVjaXIgbGEgaGFiaXRhYmlsaWRhZCBkZSBsb3MgZXhvcGxhbmV0YXMsIHNlIHJlYWxpemEgdW4gYW7DoWxpc2lzIGRlIHJlZ3Jlc2nDs24gbG9nw61zdGljYSB1dGlsaXphbmRvIGxhcyB2YXJpYWJsZXMgY29ub2NpZGFzIGRlIGxvcyBleG9wbGFuZXRhcyB5IGxhcyBlc3RyZWxsYXMgZGVsIHNpc3RlbWEuIFNlIHNlbGVjY2lvbmFuIGxhcyB2YXJpYWJsZXMgY29ub2NpZGFzIGRlIGxvcyBleG9wbGFuZXRhcyB5IGxhcyBlc3RyZWxsYXMgY29tbyB2YXJpYWJsZXMgaW5kZXBlbmRpZW50ZXMgeSBsYSBoYWJpdGFiaWxpZGFkIGNvbW8gdmFyaWFibGUgZGVwZW5kaWVudGUuDQoNCkV4aXN0ZW4gdmFyaW9zIGluZGljYWRvcmVzIGRlIGhhYml0YWJpbGlkYWQgZGUgbG9zIGV4b3BsYW5ldGFzLiBDb25zaWRlcmFuZG8gcXVlIGVzdGFtb3MgZXN0dWRpYW5kbyBlc3RyZWxsYXMgY29uIHJhZGlvcyBzaW1pbGlhcmVzIGFsIHNvbGFyICgrLy0gMTAlKSBsb3MgcGFyw6FtZXRyb3MgcGxhbmV0YXJpb3MgbcOhcyByZWxldmFudGVzIHNlIGRlc2NyaWJlbiBhIGNvbnRpbnVhY2nDs24uDQoNCkxhIHRlbXBlcmF0dXJhIGRlIGVxdWlsaWJyaW8gKCoqYHBsX2VxdGAqKikgcGxhbmV0YXJpYSBlcyB1bmEgdmFyaWFibGUgZnVuZGFtZW50YWwgZW4gbGEgZGVmaW5pY2nDs24gZGUgbGEgem9uYSBoYWJpdGFibGUsIHlhIHF1ZSBlc3TDoSBkaXJlY3RhbWVudGUgcmVsYWNpb25hZGEgY29uIGxhIHBvc2liaWxpZGFkIGRlIGFndWEgbMOtcXVpZGEgZW4gbGEgc3VwZXJmaWNpZSBkZSB1biBwbGFuZXRhLiBFbiBbQGtvcHBhcmFwdS1yYW1pcmV6LTIwMTNdIHNlIGFuYWxpemFuIGZhY3RvcmVzIHBhcmEgYWp1c3RhciBsb3MgbMOtbWl0ZXMgZGUgbGEgem9uYSBoYWJpdGFibGUgeSBkZWZpbmUgbG9zIHJhbmdvcyBpZGVhbGVzIGRlIHRlbXBlcmF0dXJhIHBhcmEgaGFiaXRhYmlsaWRhZC4gLSBMYSBpbnNvbGFjacOzbiAoKipgcGxfaW5zb2xgKiopLCBlc3RvIGVzIGZsdWpvIGRlIHJhZGlhY2nDs24gcmVjaWJpZG8gcG9yIGVsIHBsYW5ldGEgZW4gY29tcGFyYWNpw7NuIGNvbiBsYSBUaWVycmEsIGVzIG90cm8gcHJlZGljdG9yIGNsYXZlLCB5YSBxdWUgZGV0ZXJtaW5hIGVsIGJhbGFuY2UgZW5lcmfDqXRpY28gZGVsIHBsYW5ldGEuIEVuIFtAc2hpZWxkcy1iYWxsYXJkLTIwMTZdIHNlIGVzdHVkaWFuIGxvcyBlZmVjdG9zIGRlbCBmbHVqbyBkZSByYWRpYWNpw7NuIGVuIGxhIHpvbmEgaGFiaXRhYmxlIHkgc3UgaW1wYWN0byBlbiBsYSBjYXBhY2lkYWQgZGUgdW4gcGxhbmV0YSBwYXJhIHJldGVuZXIgYWd1YS4gLSBFbCBzZW1pZWplIG1heW9yIG9yYml0YWwgKGBwbF9vcmJzbWF4YCkgZXMgb3RybyBpbmRpY2Fkb3IgaW1wb3J0YW50ZSwgeWEgcXVlIGRldGVybWluYSBsYSBkaXN0YW5jaWEgZGVsIHBsYW5ldGEgYSBzdSBlc3RyZWxsYSBhbmZpdHJpb25hIHksIHBvciBsbyB0YW50bywgc3UgdGVtcGVyYXR1cmEgc3VwZXJmaWNpYWwuIEVuIFtAa2FuZS1nZWxpbm8tMjAxMl0gc2UgZGVtdWVzdHJhIGPDs21vIGxhIGRpc3RhbmNpYSBvcmJpdGFsIHkgbGEgbHVtaW5vc2lkYWQgZGUgbGEgZXN0cmVsbGEgYWZlY3RhbiBsYSBoYWJpdGFiaWxpZGFkLg0KDQpMYSBkZXRlcm1pbmFjacOzbiBkZSBsYSBoYWJpdGFiaWxpZGFkIGRlIHVuIGV4b3BsYW5ldGEgZXMgdW4gdGVtYSBjb21wbGVqbyB5IG11bHRpZmFjdG9yaWFsIHF1ZSBkZXBlbmRlIGRlIHZhcmlvcyBpbmRpY2Fkb3JlcyBmw61zaWNvcyB5IHF1w61taWNvcy4gU2kgYmllbiBubyBleGlzdGUgdW5hIGbDs3JtdWxhIMO6bmljYSB1bml2ZXJzYWxtZW50ZSBhY2VwdGFkYSBwYXJhIGNhbGN1bGFyIGxhICJoYWJpdGFiaWxpZGFkIiwgc2UgcHVlZGVuIGNvbWJpbmFyIGxvcyBpbmRpY2Fkb3JlcyBhbnRlcyBtZW5jaW9uYWRvcyBwYXJhIGFwcm94aW1hciBlbCBwb3RlbmNpYWwgZGUgaGFiaXRhYmlsaWRhZCBkZSB1biBleG9wbGFuZXRhLiBVbmEgZGUgbGFzIGFwcm94aW1hY2lvbmVzIG3DoXMgY29tdW5lcyBlcyB1c2FyIHVuYSBjb21iaW5hY2nDs24gcG9uZGVyYWRhIGRlIGxhcyBjb25kaWNpb25lcyBhZGVjdWFkYXMgcGFyYSBsYSBwcmVzZW5jaWEgZGUgYWd1YSBsw61xdWlkYSwgeWEgcXVlIGVzdGEgZXMgZnVuZGFtZW50YWwgcGFyYSBsYSB2aWRhIHRhbCBjb21vIGxhIGNvbm9jZW1vcy4gRWwgdXNvIGRlIHVuYSBjb21iaW5hY2nDs24gbGluZWFsIHBvbmRlcmFkYSBkZSB2YXJpYWJsZXMgdGFsZXMgY29tbyBsYXMgY29uc2lkZXJhZGFzIGVzIHVuYSB0w6ljbmljYSB2w6FsaWRhIGVuIGxhIG1vZGVsaXphY2nDs24gZGUgaGFiaXRhYmlsaWRhZCBwbGFuZXRhcmlhLiBFbiBbQG1lbmRlei1yaXZlcmEtMjAyMV0gc2UgcHJvcG9uZSBlbCBFYXJ0aCBTaW1pbGFyaXR5IEluZGV4IChFU0kpLCBxdWUgdXNhIHVuYSBmw7NybXVsYSBub3JtYWxpemFkYSBjb21iaW5hbmRvIHRlbXBlcmF0dXJhLCBmbHVqbyBlc3RlbGFyIHkgcGFyw6FtZXRyb3Mgb3JiaXRhbGVzLg0KDQpBc8OtIGNvbiBsb3MgaW5kaWNhZG9yZXMgc2VsZWNjaW9uYWRvcyBkZWZpbmltb3MgdW4gw41uZGljZSBkZSBIYWJpdGFiaWxpZGFkIFBsYW5ldGFyaWEgKFBISSAtIFBsYW5ldGFyeSBIYWJpdGFiaWxpdHkgSW5kZXgpIGNvbW8gdW5hIGZ1bmNpw7NuIG5vcm1hbGl6YWRhIHF1ZSBjb21iaW5lIGxvcyBpbmRpY2Fkb3JlcyBjbGF2ZToNCg0KJCQNClx0ZXh0e1BISX0gPSB3XzEgXGNkb3QgZl8xKFx0ZXh0e3BsX2VxdH0pICsgd18yIFxjZG90IGZfMihcdGV4dHtwbF9pbnNvbH0pICsgd18zIFxjZG90IGZfMyhcdGV4dHtwbF9vcmJzbWF4fSkgDQokJA0KDQpEb25kZToNCg0KLSAgICR3X2kkIHNvbiBsb3MgcGVzb3Mgbm9ybWFsaXphZG9zIGFzb2NpYWRvcyBhIGNhZGEgaW5kaWNhZG9yIHN1bWFuZG8gMS4NCi0gICAkZl9pKHgpJCBzb24gZnVuY2lvbmVzIGRlIHRyYW5zZm9ybWFjacOzbiBvIG5vcm1hbGl6YWNpw7NuIHF1ZSBjb252aWVydGVuIGxhcyBtZWRpZGFzIGVuIHZhbG9yZXMgZW50cmUgMCB5IDEsIHNlZ8O6biBlbCByYW5nbyBkZSBoYWJpdGFiaWxpZGFkIGNvbm9jaWRvLg0KDQpFc3RhcyB2YXJpYWJsZXMgc2UgY29uc2lkZXJhbiBjb21vIHBvc2libGVzIHByZWRpY3RvcmVzIGRlIGxhIGhhYml0YWJpbGlkYWQgZGUgbG9zIGV4b3BsYW5ldGFzIGN1YW5kbyBlc3TDoW4gZW4gZGV0ZXJtaW5hZG9zIHJhbmdvcy4NCg0KIyMjIFRlbXBlcmF0dXJhIGRlIGVxdWlsaWJyaW8gKGBwbF9lcXRgKQ0KDQpJZGVhbG1lbnRlIGxhIHRlbXBlcmF0dWEgZGUgZXF1aWxpYnJpbyBkZWJlIGVzdGFyIGVuIHVuIHJhbmdvIGNvbXBhdGlibGUgY29uIGFndWEgbMOtcXVpZGEsIGFwcm94aW1hZGFtZW50ZSBlbnRyZSAwwrBDIHkgMTAwwrBDLiBBc8OtIGxhIG5vcm1hbGl6YWNpw7NuIHJlc3VsdGFuIGVuOg0KDQokJA0KZl9pKFx0ZXh0e3BsX2VxdH0pID0gXG1heFxsZWZ0KDAsIFxtaW5cbGVmdCgxLCBcZnJhY3tcdGV4dHtwbF9lcXR9IC0gVF97XHRleHR7bWlufX19e1Rfe1x0ZXh0e21heH19IC0gVF97XHRleHR7bWlufX19XHJpZ2h0KVxyaWdodCkNCiQkDQoNCkRvbmRlICRUX3tcdGV4dHttaW59fSQgeSAkVF97XHRleHR7bWF4fX0kIHNvbiBsb3MgbMOtbWl0ZXMgaW5mZXJpb3JlcyB5IHN1cGVyaW9yZXMuIEVsIGFndWEgbMOtcXVpZGEsIGVzZW5jaWFsIHBhcmEgbGEgdmlkYSwgcHVlZGUgZXhpc3RpciBlbiB1biByYW5nbyBkZSB0ZW1wZXJhdHVyYXMgc3VwZXJmaWNpYWxlcyBkZSBhcHJveGltYWRhbWVudGUgMjczSyAoMCDCsEMpIGEgMzczSyAoMTAwIMKwQykuIFNpbiBlbWJhcmdvLCBkZWJpZG8gYSBmYWN0b3JlcyBhdG1vc2bDqXJpY29zIHkgZGUgcHJlc2nDs24sIGVzdGUgcmFuZ28gcHVlZGUgZXh0ZW5kZXJzZSBsaWdlcmFtZW50ZTogJFRfe1x0ZXh0e21pbn19PTIwMEskIHB1ZWRlIHNlciBlbCB1bWJyYWwgaW5mZXJpb3IsIGNvbnNpZGVyYW5kbyBhdG3Ds3NmZXJhcyBkZW5zYXMgY29tbyBsYSBkZSBNYXJ0ZSB5ICRUX3tcdGV4dHttYXh9fT00MDBLJCBwdWVkZSBjb25zaWRlcmFyc2UgZWwgdW1icmFsIHN1cGVyaW9yLCBjb25zaWRlcmFuZG8gYXRtw7NzZmVyYXMgY29uIGFsdGEgcHJlc2nDs24gY29tbyBsYSBkZSBWZW51cy4NCg0KU2Vnw7puIGxhIGxpdGVyYXR1cmEgZXNwZWNpYWxpemFkYSBlbCBwZXNvIGRlIGxhIHRlbXBlcmF0dXJhIGRlIGVxdWlsaWJyaW8gZW4gZWwgw61uZGljZSBkZSBoYWJpdGFiaWxpZGFkIGVzIGRlICR3XzE9MC40MCQgY3VhbmRvIHNlIGNvbnNpZGVyYSBsYSB0ZW1wZXJhdHVyYSBkZSBlcXVpbGlicmlvIGNvbW8gdW4gaW5kaWNhZG9yIHByZXBvbmRlcmFudGUgZGUgaGFiaXRhYmlsaWRhZCB5IG5vIHNlIHRpZW5lbiBtdWNob3MgbcOhcyBkYXRvcyBkZWwgcGxhbmV0YS4NCg0KIyMjIExhIGluc29sYWNpw7NuIChgcGxfaW5zb2xgKQ0KDQpMYSBpbnNvbGFjacOzbiBlcyBsYSBjYW50aWRhZCBkZSBlbmVyZ8OtYSByZWNpYmlkYSBwb3IgZWwgcGxhbmV0YSB5IGVzIHVuIGluZGljYWRvciBpbXBvcnRhbnRlIGRlIGxhIGhhYml0YWJpbGlkYWQuIExhIGluc29sYWNpw7NuIHNlIG1pZGUgZW4gdW5pZGFkZXMgZGUgZmx1am8gZGUgZW5lcmfDrWEgcmVjaWJpZGEgcG9yIHVuaWRhZCBkZSDDoXJlYSB5IHNlIHB1ZWRlIG5vcm1hbGl6YXIgZW4gdW4gcmFuZ28gZGUgMCBhIDEuIExhIGluc29sYWNpw7NuIGlkZWFsIHBhcmEgbGEgdmlkYSBlcyBhcXVlbGxhIHF1ZSBwZXJtaXRlIGxhIHByZXNlbmNpYSBkZSBhZ3VhIGzDrXF1aWRhIGVuIGxhIHN1cGVyZmljaWUgZGVsIHBsYW5ldGEgKGdlbmVyYWxtZW50ZSB2YWxvcmVzIGNlcmNhbm9zIGEgbGEgVGllcnJhIHNvbiBpZGVhbGVzKS4gTGEgaW5zb2xhY2nDs24gc2UgcHVlZGUgbm9ybWFsaXphciBjb25zaWRlcmFuZG8gcXVlIExhIFRpZXJyYSB0aWVuZSB1bmEgaW5zb2xhY2nDs24gZGUgMVMgKGRvbmRlICRTJCBlcyBsYSBpbnNvbGFjacOzbiBzb2xhciBhIGxhIGRpc3RhbmNpYSBkZSBsYSBUaWVycmEpIHkgc2UgcHVlZGUgY29uc2lkZXJhciBxdWUgbGEgdmlkYSBwdWVkZSBleGlzdGlyIGVuIHVuIHJhbmdvIGRlIGluc29sYWNpw7NuIGRlICRJX3ttaW59PTAuM1MkIChhcHJveGltYWRhbWVudGUgZWwgbMOtbWl0ZSBpbnRlcmlvciBkZSBsYSB6b25hIGhhYml0YWJsZSBwYXJhIHVuYSBlc3RyZWxsYSBjb21vIGVsIFNvbCwgbcOhcyBhbGzDoSBkZSBlc3RlIHZhbG9yIGVsIGFndWEgcG9kcsOtYSBjb25nZWxhcnNlKSBhICRJX3ttYXh9PTEsN1MkIChhcHJveGltYWRhbWVudGUgZWwgbMOtbWl0ZSBleHRlcmlvciBkZSBsYSB6b25hIGhhYml0YWJsZSwgbcOhcyBhbGzDoSBkZSBlc3RlIHZhbG9yIGVsIGFndWEgcG9kcsOtYSBldmFwb3JhcnNlKS4gQXPDrSBsYSBub3JtYWxpemFjacOzbiByZXN1bHRhIGVuOg0KDQokJA0KZl8yKFx0ZXh0e3BsX2luc29sfSkgPSBcbWF4XGxlZnQoMCwgXG1pblxsZWZ0KDEsIFxmcmFje1x0ZXh0e3BsX2luc29sfSAtIElfe1x0ZXh0e21pbn19fXtJX3tcdGV4dHttYXh9fSAtIElfe1x0ZXh0e21pbn19fVxyaWdodClccmlnaHQpDQokJA0KDQpMYSBpbnNvbGFjacOzbiBlcyB1biBmYWN0b3IgY3LDrXRpY28gcGFyYSBtYW50ZW5lciBhZ3VhIGzDrXF1aWRhIGVuIGxhIHN1cGVyZmljaWUgZGVsIHBsYW5ldGEsIHBlcm8gc3UgaW1wYWN0byBkZXBlbmRlIGRlIG90cm9zIGZhY3RvcmVzIGNvbW8gbGEgYXRtw7NzZmVyYSB5IGVsIGFsYmVkbywgc2Vnw7puIGxhIGxpdGVyYXR1cmEgZXNwZWNpYWxpemFkYSBlbCBwZXNvIGRlIGxhIGluc29sYWNpw7NuIGVuIGVsIMOtbmRpY2UgZGUgaGFiaXRhYmlsaWRhZCBlcyBkZSAkd18yPTAuMzAkLiBFcyBpbXBvcnRhbnRlIGRlc3RhY2FyIHF1ZSBFbCByYW5nbyBkZSAkSV97bWlufSQgZSAkSV97bWF4fSQgcHVlZGUgdmFyaWFyIHNlZ8O6biBsYSBsdW1pbm9zaWRhZCBkZSBsYSBlc3RyZWxsYSwgeWEgcXVlIGxhIHpvbmEgaGFiaXRhYmxlIGNhbWJpYSBlbiBmdW5jacOzbiBkZWwgdGlwbyBlc3RlbGFyIHBvciBsbyBxdWUgZXN0YSBlc3RpbWFjacOzbiBzaXJ2ZSBwYXJhIGVzdHJlbGxhcyBzaW1pbGFyZXMgYWwgU29sLg0KDQojIyMgTGEgZGlzdGFuY2lhIG9yYml0YWwgZGVsIHNlbWllamUgbWF5b3IgKGBwbF9vcmJzbWF4YCkNCg0KTGEgZGlzdGFuY2lhIG9yYml0YWwgc2VtaWVqZSBtYXlvciBlcyB1biBpbmRpY2Fkb3IgZGUgbGEgem9uYSBoYWJpdGFibGUgZGUgdW4gc2lzdGVtYSBwbGFuZXRhcmlvLiBMYSBkaXN0YW5jaWEgb3JiaXRhbCBzZW1pZWplIG1heW9yIHNlIG1pZGUgZW4gdW5pZGFkZXMgYXN0cm9uw7NtaWNhcyAoVUEpIHkgc2UgcHVlZGUgbm9ybWFsaXphciBlbiB1biByYW5nbyBkZSAwIGEgMS4gTGEgZGlzdGFuY2lhIG9yYml0YWwgc2VtaWVqZSBtYXlvciBpZGVhbCBwYXJhIGxhIHZpZGEgZXMgYXF1ZWxsYSBxdWUgcGVybWl0ZSBsYSBwcmVzZW5jaWEgZGUgYWd1YSBsw61xdWlkYSBlbiBsYSBzdXBlcmZpY2llIGRlbCBwbGFuZXRhLiBMYSBkaXN0YW5jaWEgb3JiaXRhbCBzZW1pZWplIG1heW9yIHNlIHB1ZWRlIG5vcm1hbGl6YXIgY29uc2lkZXJhbmRvIHF1ZSBMYSBUaWVycmEgdGllbmUgdW5hIGRpc3RhbmNpYSBvcmJpdGFsIHNlbWllamUgbWF5b3IgZGUgMSBVQSB5IHNlIHB1ZWRlIGNvbnNpZGVyYXIgcXVlIGxhIHZpZGEgcHVlZGUgZXhpc3RpciBlbiB1biByYW5nbyBkZSBkaXN0YW5jaWFzIGRlICREX3tcdGV4dHttaW59fT0wLDUkIFVBIChhcHJveGltYWRhbWVudGUgZWwgbMOtbWl0ZSBpbnRlcmlvciBkZSBsYSB6b25hIGhhYml0YWJsZSBwYXJhIHVuYSBlc3RyZWxsYSBjb21vIGVsIFNvbCwgbcOhcyBhbGzDoSBkZSBlc3RlIHZhbG9yIGVsIGFndWEgcG9kcsOtYSBjb25nZWxhcnNlKSBhICREX3tcdGV4dHttYXh9fT0yJCBVQSAoYXByb3hpbWFkYW1lbnRlIGVsIGzDrW1pdGUgZXh0ZXJpb3IgZGUgbGEgem9uYSBoYWJpdGFibGUsIG3DoXMgYWxsw6EgZGUgZXN0ZSB2YWxvciBlbCBhZ3VhIHBvZHLDrWEgZXZhcG9yYXJzZSkuIEVzdG9zIHJhbmdvcyBwdWVkZW4gdmFyaWFyIHNlZ8O6biBlbCB0aXBvIGRlIGVzdHJlbGxhLiBBc8OtIGxhIG5vcm1hbGl6YWNpw7NuIHJlc3VsdGEgZW46DQoNCiQkDQpmXzMoXHRleHR7cGxfb3Jic21heH0pID0gXG1heFxsZWZ0KDAsIFxtaW5cbGVmdCgxLCBcZnJhY3tcdGV4dHtwbF9vcmJzbWF4fSAtIERfe1x0ZXh0e21pbn19fXtEX3tcdGV4dHttYXh9fSAtIERfe1x0ZXh0e21pbn19fVxyaWdodClccmlnaHQpDQokJA0KDQpFbiBsYSBtYXlvcsOtYSBkZSBsb3MgbW9kZWxvcywgZWwgcGVzbyBwYXJhIGVsIHZhbG9yIG5vcm1hbGl6YWRvIGRlICoqYHBsX29yYnNtYXhgKiogb3NjaWxhIGVudHJlIDE1JSB5IDI1JS4gRXN0byBzZSBkZWJlIGEgcXVlICoqYHBsX29yYnNtYXhgKiogY29tcGxlbWVudGEgaW5kaWNhZG9yZXMgbcOhcyBkaXJlY3RvcyBjb21vICoqYHBsX2VxdGAqKiAodGVtcGVyYXR1cmEgZGUgZXF1aWxpYnJpbykgeSAqKmBwbF9pbnNvbGAqKiAoaW5zb2xhY2nDs24pLiBTZSB0b21hcsOhIHVuIHBlc28gZGUgJHdfMz0wLjMwJC4NCg0KIyMjIMONbmRpY2UgZGUgaGFiaXRhYmlsaWRhZCBwbGFuZXRhcmlhIChgUEhJYCkNCg0KUG9yIGxvIGV4cHVlc3RvIGFudGVyaW9ybWVudGUsIGVsICoqw41uZGljZSBkZSBIYWJpdGFiaWxpZGFkIFBsYW5ldGFyaWEgKFBISSkqKiBzZSBjYWxjdWxhIHV0aWxpemFuZG8gKip2YXJpYWJsZXMgbm9ybWFsaXphZGFzKiogeSBzdXMgcmVzcGVjdGl2b3MgKipwZXNvcyoqLCBsbyBxdWUgcGVybWl0ZSBldmFsdWFyIGxhIGhhYml0YWJpbGlkYWQgZGUgdW4gZXhvcGxhbmV0YSBkZSBtYW5lcmEgbcOhcyBlcXVpbGlicmFkYSB5IGNvbXBhcmFibGUgZW50cmUgZGlmZXJlbnRlcyBzaXN0ZW1hcy4NCg0KTGEgZsOzcm11bGEgcGFyYSBjYWxjdWxhciBlbCAqKlBISSoqIHF1ZSBzZSB1dGlsaXphcsOhIGVuIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxvZ8Otc3RpY2EgZXM6DQoNCiQkDQpcdGV4dHtQSEl9ID0gMC40IFxjZG90IGZfMShcdGV4dHtwbF9lcXR9KSArIDAuMyBcY2RvdCBmXzIoXHRleHR7cGxfaW5zb2x9KSArIDAsMyBcY2RvdCBmXzMoXHRleHR7cGxfb3Jic21heH0pIA0KJCQNCg0KYGBge3IgbG9nX3JlZ19waGlfY2FsY3VsYXRpb259DQoNCmxpYnJhcnkoZHBseXIpDQoNCiMgTm9ybWFsaXphciBsYXMgdmFyaWFibGVzDQprZXBsZXJfZGF0YSA8LSBrZXBsZXJfZGF0YSAlPiUNCiAgbXV0YXRlKA0KICAgIHBsX2VxdF9ub3JtYWxpemVkID0gcG1pbigxLCBwbWF4KDAsIChwbF9lcXQgLSAyMDApIC8gKDQwMCAtIDIwMCkpKSwNCiAgICBwbF9pbnNvbF9ub3JtYWxpemVkID0gcG1pbigxLCBwbWF4KDAsIChwbF9pbnNvbCAtIDAuMykgLyAoMS43IC0gMC4zKSkpLA0KICAgIHBsX29yYnNtYXhfbm9ybWFsaXplZCA9IHBtaW4oMSwgcG1heCgwLCAocGxfb3Jic21heCAtIDAuMDUpIC8gKDIgLSAxLjA1KSkpDQogICkNCg0KIyBDYWxjdWxhciBlbCDDrW5kaWNlIGRlIGhhYml0YWJpbGlkYWQgcGxhbmV0YXJpYSAoUEhJKQ0Ka2VwbGVyX2RhdGEgPC0ga2VwbGVyX2RhdGEgJT4lDQogIG11dGF0ZSgNCiAgICBwaGkgPSAwLjQgKiBwbF9lcXRfbm9ybWFsaXplZCArIDAuMyAqIHBsX2luc29sX25vcm1hbGl6ZWQgKyAwLjMgKiBwbF9vcmJzbWF4X25vcm1hbGl6ZWQgDQogICkNCg0KYGBgDQoNCmBgYHtyIGxvZ19yZWd9DQoNCiMgQ3JlYXIgdW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbG9nw61zdGljYQ0KbW9kZWxfbG9naXN0aWMgPC0gZ2xtKHBoaSB+IHBsX2VxdF9ub3JtYWxpemVkICsgcGxfaW5zb2xfbm9ybWFsaXplZCArIHBsX29yYnNtYXhfbm9ybWFsaXplZCAsIGRhdGEgPSBrZXBsZXJfZGF0YSwgZmFtaWx5ID0gYmlub21pYWwpDQoNCm1vZGVsX2xvZ2lzdGljX3N1bW1hcnkgPC0gc3VtbWFyeShtb2RlbF9sb2dpc3RpYykNCg0KbW9kZWxfbG9naXN0aWNfc3VtbWFyeQ0KDQpgYGANCg0KYGBge3IgbG9nX3JlZ19wbG90LCB3YXJuaW5nPUZBTFNFfQ0KDQojIEdyYWZpY2FyIGxhIGN1cnZhIGxvZ2lzdGljYSBkZWwgbW9kZWxvDQojIENyZWFyIHVuIGRhdGEgZnJhbWUgY29uIGxvcyB2YWxvcmVzIGRlIFBISSB5IGxhcyBwcm9iYWJpbGlkYWRlcyBwcmVkaWNoYXMNCiMgZGUgaGFiaXRhYmlsaWRhZC4gU2VsZWNjaW9uYXIgc29sbyBsb3MgcmVnaXN0cm9zIGRvbmRlIHNlIGNvbm9jZSBsYSBoYWJpdGFiaWxpZGFkDQpwaGlfcHJvYiA8LSBwcmVkaWN0KG1vZGVsX2xvZ2lzdGljLCB0eXBlID0gInJlc3BvbnNlIikNCg0KIyBGaWx0cmFyIGxvcyByZWdpc3Ryb3MgZG9uZGUgc2UgY29ub2NlIGxhIGhhYml0YWJpbGlkYWQNCmtlcGxlcl9kYXRhX3BoaSA8LSBrZXBsZXJfZGF0YSAlPiUNCiAgZmlsdGVyKCFpcy5uYShwaGkpKQ0KDQpwaGlfcHJvYl9kZiA8LSBkYXRhLmZyYW1lKFBISSA9IGtlcGxlcl9kYXRhX3BoaSRwaGksIFByb2JhYmlsaWRhZCA9IHBoaV9wcm9iKQ0KDQojIFNjYXR0ZXIgcGxvdCBkZSBQSEkgdnMgUHJvYmFiaWxpZGFkDQpnZ3Bsb3QocGhpX3Byb2JfZGYsIGFlcyh4ID0gUEhJLCB5ID0gUHJvYmFiaWxpZGFkKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImdsbSIsIG1ldGhvZC5hcmdzID0gbGlzdChmYW1pbHkgPSAiYmlub21pYWwiKSwgY29sb3IgPSAiaW5kaWFucmVkIiwgZmlsbCA9ICJncmV5IiwgYWxwaGEgPSAwLjIpICsNCiAgbGFicyh0aXRsZSA9ICJDdXJ2YSBMb2fDrXN0aWNhIGRlbCBNb2RlbG8gZGUgUmVncmVzacOzbiIsDQogICAgICAgeCA9ICJQSEkiLA0KICAgICAgIHkgPSAiUHJvYmFiaWxpZGFkIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCkVsICoqbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbG9nw61zdGljYSoqIG9idGVuaWRvIG5vIGVzIHBhcnRpY3VsYXJtZW50ZSBzw7NsaWRvIGRlYmlkbyBhIGxhICoqZXNjYXNleiBkZSBkYXRvcyBkaXNwb25pYmxlcyoqIHBhcmEgY2FsY3VsYXIgZWwgKipQSEkgKFBsYW5ldGFyeSBIYWJpdGFiaWxpdHkgSW5kZXgpKiouIEVuIGVzdGUgY2FzbywgbGEgY2FudGlkYWQgZGUgKipleG9wbGFuZXRhcyBjb24gaW5mb3JtYWNpw7NuIGNvbXBsZXRhKiogc29icmUgbG9zIGZhY3RvcmVzIGNsYXZlIHBhcmEgbGEgcHJlZGljY2nDs24sIGNvbW8gKip0ZW1wZXJhdHVyYSBkZSBlcXVpbGlicmlvLCBpbnNvbGFjacOzbiB5IHNlbWllamUgbWF5b3Igb3JiaXRhbCoqLCBlcyAqKm11eSBsaW1pdGFkYSoqLCBjb24gc29sbyAqKjE3IG9ic2VydmFjaW9uZXMqKiBkaXNwb25pYmxlcy4NCg0KTGEgYmFqYSBjYW50aWRhZCBkZSBkYXRvcyBhZmVjdGEgc2lnbmlmaWNhdGl2YW1lbnRlIGxhICoqcHJlY2lzacOzbiB5IGNvbmZpYWJpbGlkYWQqKiBkZWwgbW9kZWxvLCB5YSBxdWUgdW4gdGFtYcOxbyBkZSBtdWVzdHJhIHRhbiByZWR1Y2lkbyAqKmxpbWl0YSBsYSBjYXBhY2lkYWQgZGUgZ2VuZXJhbGl6YWNpw7NuKiogeSBoYWNlIHF1ZSBsb3MgY29lZmljaWVudGVzIGRlbCBtb2RlbG8gc2VhbiAqKm1lbm9zIGVzdGFibGVzKiouIFBhcmEgb2J0ZW5lciB1biBtb2RlbG8gbcOhcyByb2J1c3RvIHkgcmVwcmVzZW50YXRpdm8sIHNlcsOtYSBuZWNlc2FyaW8gY29udGFyIGNvbiAqKnVuIG1heW9yIG7Dum1lcm8gZGUgZXhvcGxhbmV0YXMgY29uIGRhdG9zIGNvbXBsZXRvcyoqLCBsbyBxdWUgcGVybWl0aXLDrWEgZW50cmVuYXIgbGEgcmVncmVzacOzbiBjb24gbcOhcyBpbmZvcm1hY2nDs24geSBtZWpvcmFyIGxhIHZhbGlkZXogZGUgbGFzIHByZWRpY2Npb25lcyBzb2JyZSBoYWJpdGFiaWxpZGFkLg0KDQpFbCAqKm1vZGVsbyBkZSByZWdyZXNpw7NuIGxvZ8Otc3RpY2EqKiBwbGFudGVhZG8gcHJlc2VudGEgdmFyaWFzIGxpbWl0YWNpb25lcyBxdWUgYWZlY3RhbiBzdSB1dGlsaWRhZCB5IGNvbmZpYWJpbGlkYWQuDQoNCiQkDQpcbG9nIFxsZWZ0KCBcZnJhY3tQKFxwaGkgPSAxKX17MSAtIFAoXHBoaSA9IDEpfSBccmlnaHQpID0gLTIuNDg4ICsgMi4yMjggXGNkb3QgXHRleHR7cGxfZXF0X25vcm1hbGl6ZWR9ICsgMS4xMDUgXGNkb3QgXHRleHR7cGxfaW5zb2xfbm9ybWFsaXplZH0gKyAxLjU2OSBcY2RvdCBcdGV4dHtwbF9vcmJzbWF4X25vcm1hbGl6ZWR9DQokJA0KDQpVbm8gZGUgbG9zIHByaW5jaXBhbGVzIHByb2JsZW1hcyBlcyBsYSAqKmRyw6FzdGljYSByZWR1Y2Npw7NuIGVuIGxhIGRldmlhbmNlIHJlc2lkdWFsKiosIHF1ZSBwYXPDsyBkZSAqKjAuNDUzNSoqIChzaW4gcHJlZGljdG9yZXMpIGEgKiowLjAwMDYqKiAoY29uIHByZWRpY3RvcmVzKS4gU2kgYmllbiB1bmEgcmVkdWNjacOzbiBlbiBsYSBkZXZpYW5jZSBzdWVsZSBpbmRpY2FyIHVuYSBtZWpvcmEgZW4gZWwgbW9kZWxvLCBlbiBlc3RlIGNhc28gZWwgdmFsb3IgKipleHRyZW1hZGFtZW50ZSBiYWpvKiogc3VnaWVyZSB1biAqKnNvYnJlYWp1c3RlKiosIGxvIHF1ZSBzaWduaWZpY2EgcXVlIGVsIG1vZGVsbyBlc3TDoSBhanVzdMOhbmRvc2UgZGVtYXNpYWRvIGEgbG9zIHBvY29zIGRhdG9zIGRpc3BvbmlibGVzIHkgcG9kcsOtYSBubyBnZW5lcmFsaXphciBiaWVuIGEgbnVldmFzIG9ic2VydmFjaW9uZXMuDQoNCkVsICoqY3JpdGVyaW8gZGUgaW5mb3JtYWNpw7NuIGRlIEFrYWlrZSAoQUlDKSoqLCBjb24gdW4gdmFsb3IgZGUgKioxOS42NDEqKiwgaW5kaWNhIHF1ZSBlbCBtb2RlbG8gcGVuYWxpemEgYWRlY3VhZGFtZW50ZSBsYSBjb21wbGVqaWRhZCwgcGVybyBsYSAqKmZhbHRhIGRlIHNpZ25pZmljYW5jaWEgZW4gbG9zIGNvZWZpY2llbnRlcyoqIHN1Z2llcmUgcXVlICoqbm8gZXMgw7p0aWwgcGFyYSBsYSBwcmVkaWNjacOzbioqLCB5YSBxdWUgbm8gbG9ncmEgZXN0YWJsZWNlciB1bmEgcmVsYWNpw7NuIGNsYXJhIGVudHJlIGxhcyB2YXJpYWJsZXMuDQoNCk90cm8gcHJvYmxlbWEgZ3JhdmUgZXMgbGEgKiplbGltaW5hY2nDs24gZGUgZGF0b3MgZmFsdGFudGVzKiosIHF1ZSBkZWrDsyAqKnNvbG8gMTcgb2JzZXJ2YWNpb25lcyBkaXNwb25pYmxlcyoqIGRlc3B1w6lzIGRlIGRlc2NhcnRhciAqKjIsNTMwIHJlZ2lzdHJvcyBpbmNvbXBsZXRvcyoqLiBDb24gdGFuIHBvY29zIGRhdG9zLCBsb3MgKipncmFkb3MgZGUgbGliZXJ0YWQgKGRmPTEzKSBzb24gZXh0cmVtYWRhbWVudGUgYmFqb3MqKiwgbG8gcXVlICoqYWZlY3RhIGxhIGVzdGFiaWxpZGFkIGRlbCBtb2RlbG8qKiB5IGhhY2UgcXVlIGxhcyBlc3RpbWFjaW9uZXMgc2VhbiBwb2NvIGNvbmZpYWJsZXMuDQoNCkVuIHN1IGVzdGFkbyBhY3R1YWwsIGVsIG1vZGVsbyBubyBlcyDDunRpbCwgeWEgcXVlICoqbm8gY3VlbnRhIGNvbiB2YXJpYWJsZXMgcHJlZGljdG9yYXMgc2lnbmlmaWNhdGl2YXMqKiB5IGVuZnJlbnRhICoqdW5hIHDDqXJkaWRhIG1hc2l2YSBkZSBkYXRvcyoqLCBsbyBxdWUgbGltaXRhIHN1IGNhcGFjaWRhZCBwYXJhIGhhY2VyIGluZmVyZW5jaWFzIHbDoWxpZGFzLiBBbnRlcyBkZSBzYWNhciBjb25jbHVzaW9uZXMgc29icmUgbGEgcmVsYWNpw7NuIGVudHJlICoqUEhJKiogeSBsYXMgdmFyaWFibGVzIHByZWRpY3RvcmFzLCBzZXLDrWEgcmVjb21lbmRhYmxlICoqbGltcGlhciBsb3MgZGF0b3MgeSBwcm9iYXIgdW4gbW9kZWxvIG3DoXMgc2ltcGxlKiouIFNpbiBlbWJhcmdvLCBkYWRhIGxhICoqZXNjYXNleiBkZSBvYnNlcnZhY2lvbmVzKiosIGVzIHBvc2libGUgcXVlIG5vIHNlYSBmYWN0aWJsZSBjb25zdHJ1aXIgdW4gbW9kZWxvIGNvbmZpYWJsZSBwYXJhIGxhICoqcHJlZGljY2nDs24gZGUgaGFiaXRhYmlsaWRhZCoqIGVuIGVzdGFzIGNvbmRpY2lvbmVzLg0KDQojIyBQcmVkaWNjacOzbiBkZSBQSEkgY29uIGRhdG9zIGZhbHRhbnRlcw0KDQpEYWRvIHF1ZSBlbCDDrW5kaWNlIGRlIGhhYml0YWJpbGlkYWQgcGxhbmV0YXJpYSAoUEhJKSAqKnPDs2xvIHB1ZG8gY2FsY3VsYXJzZSBwYXJhIDE3IHBsYW5ldGFzKiosIHkgcXVlIGVsIHJlc3RvIGRlbCBjb25qdW50bywgKioyNTMwIG9ic2VydmFjaW9uZXMsIHByZXNlbnRhIGRhdG9zIGZhbHRhbnRlcyBlbiB2YXJpYWJsZXMgY2xhdmUqKiwgbGEgYXBsaWNhY2nDs24gZGlyZWN0YSBkZSB1biBtb2RlbG8gc3VwZXJ2aXNhZG8gY29tbyAqKmxhIHJlZ3Jlc2nDs24gbG9nw61zdGljYSBubyByZXN1bHRhIHZpYWJsZSBzaW4gcmVjdXJyaXIgYSBpbXB1dGFjaW9uZXMgZXh0ZW5zYXMgeSBwb3RlbmNpYWxtZW50ZSBzZXNnYWRhcyoqLiBFbiBsdWdhciBkZSBlbGxvLCBzZSBpbnRlbnRhICoqdW4gZW5mb3F1ZSBzZW1pLXN1cGVydmlzYWRvIGNvbWJpbmFuZG8gY2x1c3RlcmluZyBjb24gTGlnaHRHQk0qKi4gUHJpbWVybywgc2UgYXBsaWNhIGVsIGFsZ29yaXRtbyBkZSBhZ3J1cGFtaWVudG8gKipLLW1lYW5zKiogYSBsYSB0b3RhbGlkYWQgZGVsIGNvbmp1bnRvIGRlIGRhdG9zIChzaW4gdXRpbGl6YXIgbGFzIGV0aXF1ZXRhcyksIGNvbiBlbCBmaW4gZGUgaWRlbnRpZmljYXIgZXN0cnVjdHVyYXMgbGF0ZW50ZXMgZW4gZWwgZXNwYWNpbyBkZSB2YXJpYWJsZXMuIEx1ZWdvLCBzZSBhbmFsaXphbiBsb3MgMTcgcGxhbmV0YXMgY29uIFBISSBjYWxjdWxhZG8gcGFyYSB2ZXJpZmljYXIgc2kgc2UgY29uY2VudHJhbiBlbiB1bm8gbyBtw6FzIGRlIGVzdG9zIGNsw7pzdGVyZXMuIEZpbmFsbWVudGUsICoqc2UgdXRpbGl6YW4gbG9zIGNsdXN0ZXJzIGNvbW8gZXRpcXVldGFzIGTDqWJpbGVzIHBhcmEgZW50cmVuYXIgdW4gbW9kZWxvIGNvbiBMaWdodEdCTSoqLCBsbyBxdWUgcGVybWl0ZSBhcHJvdmVjaGFyIGxhIGluZm9ybWFjacOzbiBlc3RydWN0dXJhbCBkZWwgY29uanVudG8gY29tcGxldG8geSBmYWNpbGl0YXIgbGEgZ2VuZXJhbGl6YWNpw7NuIGVuIGNvbnRleHRvcyBkb25kZSBsYXMgZXRpcXVldGFzIHNvbiBlc2Nhc2FzLCBjb21vIGVzIGNvbcO6biBlbiBhc3Ryb25vbcOtYSB5IG90cm9zIGNhbXBvcyBjaWVudMOtZmljb3MuDQoNCkVuIGNvbnRleHRvcyBkb25kZSBsYSBkaXNwb25pYmlsaWRhZCBkZSBkYXRvcyBldGlxdWV0YWRvcyBlcyBleHRyZW1hZGFtZW50ZSBsaW1pdGFkYSwgKipsb3MgbcOpdG9kb3MgZGUgYXByZW5kaXphamUgc2VtaS1zdXBlcnZpc2FkbyBvZnJlY2VuIHVuYSBhbHRlcm5hdGl2YSBlZmljYXogcGFyYSBhcHJvdmVjaGFyIGxhIGVzdHJ1Y3R1cmEgbGF0ZW50ZSBkZSBsb3MgZGF0b3Mgbm8gZXRpcXVldGFkb3MqKi4gVW5hIGVzdHJhdGVnaWEgYW1wbGlhbWVudGUgdXRpbGl6YWRhIGVzIGVsIHBzZXVkby1ldGlxdWV0YWRvLCBxdWUgY29uc2lzdGUgZW4gYXNpZ25hciBldGlxdWV0YXMgZXN0aW1hZGFzIGEgZWplbXBsb3Mgbm8gZXRpcXVldGFkb3MgeSB1dGlsaXphcmxhcyBlbiBjb25qdW50byBjb24gbGFzIGV0aXF1ZXRhcyByZWFsZXMgcGFyYSBlbnRyZW5hciBtb2RlbG9zIHN1cGVydmlzYWRvcy4gRXN0ZSBlbmZvcXVlIGZ1ZSBmb3JtYWxpemFkbyBwb3IgW0BsZWUtMjAxM10sICoqcXVpZW4gZGVtb3N0csOzIHF1ZSBlbCB1c28gaXRlcmF0aXZvIGRlIHBzZXVkby1ldGlxdWV0YXMgcHVlZGUgbWVqb3JhciBzaWduaWZpY2F0aXZhbWVudGUgZWwgcmVuZGltaWVudG8gZGUgbG9zIG1vZGVsb3MqKiwgaW5jbHVzbyBjb24gY2FudGlkYWRlcyBtw61uaW1hcyBkZSBkYXRvcyBhbm90YWRvcy4gUG9yIG90cm8gbGFkbywgW0B6aG91LTIwMDRdICoqaW50cm9kdWplcm9uIGVsIGNvbmNlcHRvIGRlIHByb3BhZ2FjacOzbiBkZSBldGlxdWV0YXMgc29icmUgZ3JhZm9zIGNvbnN0cnVpZG9zIGEgcGFydGlyIGRlIGxhIHNpbWlsaXR1ZCBlbnRyZSBlamVtcGxvcyoqLCBsbyBxdWUgcmVzcGFsZGEgZWwgdXNvIGRlIGFsZ29yaXRtb3MgZGUgYWdydXBhbWllbnRvIGNvbW8gSy1tZWFucyBwYXJhIGRpZnVuZGlyIGluZm9ybWFjacOzbiBkZSBsYXMgZXRpcXVldGFzIGVzY2FzYXMgYSB0cmF2w6lzIGRlIGxhIGVzdHJ1Y3R1cmEgZGVsIGNvbmp1bnRvIGRlIGRhdG9zLiBFbiBjb21iaW5hY2nDs24sICoqZXN0b3MgZW5mb3F1ZXMgcGVybWl0ZW4gY29uc3RydWlyIG1vZGVsb3Mgcm9idXN0b3MgYSBwYXJ0aXIgZGUgZGF0b3MgcHJlZG9taW5hbnRlbWVudGUgbm8gZXRpcXVldGFkb3MqKiwgY29tbyBlbiBlbCBjYXNvIGRlIGxhIGVzdGltYWNpw7NuIGRlbCDDrW5kaWNlIGRlIGhhYml0YWJpbGlkYWQgcGxhbmV0YXJpYSAoUEhJKSwgZG9uZGUgbWVub3MgZGVsIDElIGRlIGxvcyByZWdpc3Ryb3MgZGlzcG9uaWJsZXMgaW5jbHV5ZW4gdW5hIGV0aXF1ZXRhIGNvbmZpYWJsZS4NCg0KUHJpbWVybyBzZSBhcGxpY2EgZWwgYWxnb3JpdG1vIGRlIGFncnVwYW1pZW50byAqKkstbWVhbnMqKiBhIGxhIHRvdGFsaWRhZCBkZWwgY29uanVudG8gZGUgZGF0b3MgKHNpbiB1dGlsaXphciBsYXMgZXRpcXVldGFzKSwgY29uIGVsIGZpbiBkZSBpZGVudGlmaWNhciBlc3RydWN0dXJhcyBsYXRlbnRlcyBlbiBlbCBlc3BhY2lvIGRlIHZhcmlhYmxlcy4gUGFyYSBlbGxvLCBzZSBpbXB1dGEgTkEgY29uIGxhIG1lZGlhbmEgcG9yIGNvbHVtbmEgeSBzZSBlbGltaW5hbiBjb2x1bW5hcyBjb24gdmFsb3JlcyBubyBmaW5pdG9zLg0KDQpgYGB7ciBzZW1pX3N1cGVydmlzZWRfa21lYW5zfQ0KDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShsaWdodGdibSkNCmxpYnJhcnkoTWF0cml4KQ0KDQojIGFzaWduYXIgdW4gaWQgbnVtZXJpY28gw7puaWNvIGEgY2FkYSBmaWxhDQprZXBsZXJfZGF0YSA8LSBrZXBsZXJfZGF0YSAlPiUNCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKQ0KDQojIFNlcGFyYXIgUEhJIHkgZmVhdHVyZXMNCiMgRmlsdHJhciBjb2x1bW5hcyBudW3DqXJpY2FzICoqY29uIHNvbG8gdmFsb3JlcyBmaW5pdG9zKioNCmZlYXR1cmVzIDwtIGtlcGxlcl9kYXRhICU+JQ0KICBkcGx5cjo6c2VsZWN0KHdoZXJlKGlzLm51bWVyaWMpKSAlPiUNCiAgZHBseXI6OnNlbGVjdCh3aGVyZSh+IGFsbChpcy5maW5pdGUoLikpKSkNCnBoaSA8LSBrZXBsZXJfZGF0YSRwaGkNCg0KIyBTZSBpbXB1dGEgTkEgY29uIGxhIG1lZGlhbmEgcG9yIGNvbHVtbmENCiMgTGEgaW1wdXRhY2lvbiBlcyBzw7NsbyBwYXJhIGFwbGljYXIgay1tZWFucywgbm8gcGFyYSBlbnRyZW5hciBMaWdodEdCTQ0KZmVhdHVyZXNfaW1wdXRlZCA8LSBmZWF0dXJlcyAlPiUNCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBpZmVsc2UoaXMubmEoLiksIG1lZGlhbiguLCBuYS5ybSA9IFRSVUUpLCAuKSkpDQoNCiMgQXBsaWNhciBLLW1lYW5zIGNvbiBrID0gMTcNCnNldC5zZWVkKHJhbmRvbV9zZWVkKQ0Ka21lYW5zX3Jlc3VsdCA8LSBrbWVhbnMoc2NhbGUoZmVhdHVyZXNfaW1wdXRlZCksIGNlbnRlcnMgPSAxNywgbnN0YXJ0ID0gMjUpDQpjbHVzdGVycyA8LSBrbWVhbnNfcmVzdWx0JGNsdXN0ZXINCg0KYGBgDQoNCkRhZGEgbGEgYWx0YSBkaW1lbnNpb25hbGlkYWQgZGUgbG9zIGRhdG9zLCBzZSB1dGlsaXphIFBDQSBwYXJhIHZpc3VhbGl6YXIgbG9zIGNsw7pzdGVyZXMuIEVuIGVzdGUgY2Fzbywgc2Ugc2VsZWNjaW9uYW4gbG9zIGRvcyBwcmltZXJvcyBjb21wb25lbnRlcyBwcmluY2lwYWxlcyBwYXJhIGxhIHZpc3VhbGl6YWNpw7NuIGVuIDJELiBBZGVtw6FzIHNlIG11ZXN0cmFuIGxvcyAxNyBwbGFuZXRhcyBjb24gUEhJIGNvbm9jaWRvLg0KDQpgYGB7ciBzZW1pX3N1cGVydmlzZWRfa21lYW5zX3BjYV9wbG90fQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgMS4gQXNlZ3VyYXJzZSBkZSBxdWUgZmVhdHVyZXMgZXN0w6EgZXN0YW5kYXJpemFkbyAoY29tbyBzZSB1c8OzIGVuIEstbWVhbnMpDQpmZWF0dXJlc19zY2FsZWQgPC0gc2NhbGUoZmVhdHVyZXMpDQoNCiMgMi4gRWplY3V0YXIgUENBDQpwY2FfcmVzdWx0IDwtIHByY29tcChmZWF0dXJlc19zY2FsZWQpDQpwY2FfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKHBjYV9yZXN1bHQkeFssIDE6Ml0pICAjIFRvbWFtb3Mgc29sbyBQQzEgeSBQQzINCg0KIyAzLiBBZ3JlZ2FyIGNsdXN0ZXIgeSBzaSB0aWVuZSBQSEkNCnBjYV9kYXRhJGNsdXN0ZXIgPC0gYXMuZmFjdG9yKGNsdXN0ZXJzKQ0KcGNhX2RhdGEkaGFzX3BoaSA8LSAhaXMubmEoa2VwbGVyX2RhdGEkcGhpKQ0KDQojIDQuIEdyYWZpY2FyDQpnZ3Bsb3QocGNhX2RhdGEsIGFlcyh4ID0gUEMxLCB5ID0gUEMyLCBjb2xvciA9IGNsdXN0ZXIpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYsIHNpemUgPSAyKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IHN1YnNldChwY2FfZGF0YSwgaGFzX3BoaSksIA0KICAgICAgICAgICAgIGFlcyh4ID0gUEMxLCB5ID0gUEMyKSwgDQogICAgICAgICAgICAgc2hhcGUgPSAxNywgc2l6ZSA9IDMuNSwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ2x1c3RlcnMgZGUgSy1tZWFucyB2aXN1YWxpemFkb3MgY29uIFBDQSIsDQogICAgc3VidGl0bGUgPSAiTG9zIHRyacOhbmd1bG9zIG5lZ3JvcyBpbmRpY2FuIHBsYW5ldGFzIGNvbiBQSEkgY29ub2NpZG8iLA0KICAgIHggPSAiQ29tcG9uZW50ZSBQcmluY2lwYWwgMSIsDQogICAgeSA9ICJDb21wb25lbnRlIFByaW5jaXBhbCAyIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCg0KYGBgDQoNClNlZ3VuZG8gc2UgYW5hbGl6YSBzaSBsb3MgMTcgcGxhbmV0YXMgY29uIFBISSBjYWxjdWxhZG8gc2UgY29uY2VudHJhbiBlbiB1bm8gbyBtw6FzIGRlIGVzdG9zIGNsw7pzdGVyZXMuIFBhcmEgZWxsbywgc2UgcHJvcGFnYW4gZXRpcXVldGFzIGTDqWJpbGVzIGEgdHJhdsOpcyBkZSBsb3MgY2zDunN0ZXJlcywgYXNpZ25hbmRvIGVsIHZhbG9yIHByb21lZGlvIGRlIFBISSBhIGxvcyBwbGFuZXRhcyBubyBldGlxdWV0YWRvcyBkZW50cm8gZGUgY2FkYSBjbMO6c3Rlci4gU2kgdW4gY2zDunN0ZXIgbm8gdGllbmUgZXRpcXVldGFzLCBzZSBhc2lnbmEgZWwgcHJvbWVkaW8gZGVsIGNsw7pzdGVyIG3DoXMgY2VyY2Fuby4NCg0KYGBge3Igc2VtaV9zdXBlcnZpc2VkX3dlYWtfbGFiZWxzfQ0KDQojIFByb3BhZ2FyIFBISSBwcm9tZWRpbyBkZW50cm8gZGUgY2FkYSBjbHVzdGVyDQpwc2V1ZG9fcGhpIDwtIG51bWVyaWMobGVuZ3RoKHBoaSkpDQpmb3IgKGNsdXN0ZXJfaWQgaW4gdW5pcXVlKGNsdXN0ZXJzKSkgew0KICBpbl9jbHVzdGVyIDwtIGNsdXN0ZXJzID09IGNsdXN0ZXJfaWQNCiAgbGFiZWxlZCA8LSAhaXMubmEocGhpKSAmIGluX2NsdXN0ZXINCiAgdW5sYWJlbGVkIDwtIGlzLm5hKHBoaSkgJiBpbl9jbHVzdGVyDQoNCiAgaWYgKHN1bShsYWJlbGVkKSA+IDApIHsNCiAgICBwaGlfbWVhbiA8LSBtZWFuKHBoaVtsYWJlbGVkXSkNCiAgICBwc2V1ZG9fcGhpW3VubGFiZWxlZF0gPC0gcGhpX21lYW4NCiAgICBwc2V1ZG9fcGhpW2xhYmVsZWRdIDwtIHBoaVtsYWJlbGVkXSAgIyBtYW50ZW5lciB2YWxvcmVzIHJlYWxlcw0KICB9IGVsc2Ugew0KICAgICMgYnVzY2FyIGNsdXN0ZXIgbcOhcyBjZXJjYW5vIGNvbiBQSEkNCiAgICBjZW50cm9pZHMgPC0ga21lYW5zX3Jlc3VsdCRjZW50ZXJzDQogICAgZGlzdHMgPC0gYXBwbHkoY2VudHJvaWRzLCAxLCBmdW5jdGlvbihjKSBzdW0oKGNlbnRyb2lkc1tjbHVzdGVyX2lkLCBdIC0gYyleMikpDQogICAgZGlzdHNbY2x1c3Rlcl9pZF0gPC0gSW5mDQogICAgbmVhcmVzdF9jbHVzdGVyIDwtIHdoaWNoLm1pbihkaXN0cykNCiAgICBwaGlfbWVhbiA8LSBtZWFuKHBoaVtjbHVzdGVycyA9PSBuZWFyZXN0X2NsdXN0ZXIgJiAhaXMubmEocGhpKV0pDQogICAgcHNldWRvX3BoaVt1bmxhYmVsZWRdIDwtIHBoaV9tZWFuDQogIH0NCn0NCg0KIyBDcmVhciBwZXNvczogbcOhcyBhbHRvIHBhcmEgbXVlc3RyYXMgcmVhbGVzDQp3ZWlnaHRzIDwtIGlmZWxzZShpcy5uYShwaGkpLCAxLCAxMCkNCg0KYGBgDQoNClRlcmNlcm8gc2UgZW50cmVuYSBlbCBtb2RlbG8gTGlnaHRHQk0gdXRpbGl6YW5kbyBsb3MgY2x1c3RlcnMgY29tbyBldGlxdWV0YXMgZMOpYmlsZXMgeSBsb3MgcGVzb3MgcGFyYSBhanVzdGFyIGxhIGltcG9ydGFuY2lhIGRlIGxhcyBtdWVzdHJhcyByZWFsZXMgZnJlbnRlIGEgbGFzIG5vIGV0aXF1ZXRhZGFzLg0KDQpgYGB7ciBzZW1pX3N1cGVydmlzZWRfbGlnaHRnYm19ICAgIA0KDQojIEFudGVzIGRlIGVudHJlbmFyIGVsIG1vZGVsbywgc2UgZWxpbWluYW4gbG9zIFBISQ0Ka2VwbGVyX2RhdGEgPC0ga2VwbGVyX2RhdGEgJT4lDQogIG11dGF0ZShwaGkgPSBOVUxMKQ0KIyBFbnRyZW5hciBtb2RlbG8gTGlnaHRHQk0NCiMgQ29udmVydGlyIGEgbWF0cml6IGRlIExpZ2h0R0JNDQpYX21hdHJpeCA8LSBhcy5tYXRyaXgoZmVhdHVyZXMpDQpkdHJhaW4gPC0gbGdiLkRhdGFzZXQoZGF0YSA9IFhfbWF0cml4LCBsYWJlbCA9IHBzZXVkb19waGksIHdlaWdodCA9IHdlaWdodHMpDQoNCnBhcmFtcyA8LSBsaXN0KA0KICBvYmplY3RpdmUgPSAicmVncmVzc2lvbiIsDQogIG1ldHJpYyA9ICJsMiIsDQogIGxlYXJuaW5nX3JhdGUgPSAwLjA1LA0KICBudW1fbGVhdmVzID0gMzENCikNCg0KbGdibV9tb2RlbCA8LSBsZ2IudHJhaW4oDQogIHBhcmFtcyA9IHBhcmFtcywNCiAgZGF0YSA9IGR0cmFpbiwNCiAgbnJvdW5kcyA9IDEwMA0KKQ0KDQojIFByZWRlY2lyIFBISSBlc3RpbWFkbw0KcGhpX3ByZWQgPC0gcHJlZGljdChsZ2JtX21vZGVsLCBYX21hdHJpeCkNCmtlcGxlcl9kYXRhJHBoaV9lc3RpbWF0ZWQgPC0gcGhpX3ByZWQNCg0KIyBBc2lnbmFyIGxvcyB2YWxvcmVzIHByZWRpY2hvcyBhIGxhIGNvbHVtbmEgcGhpX2VzdGltYXRlZA0KIyBlbiBkYXRhIG9yaWdpbmFsIHNpZ3VpZW5kbyBsYSBjb3JyZXNwb25kZW5jaWEgZGUgaWQNCmtlcGxlcl9kYXRhIDwtIGtlcGxlcl9kYXRhICU+JQ0KICBtdXRhdGUocGhpX2VzdGltYXRlZCA9IHBoaV9wcmVkW21hdGNoKGlkLCBrZXBsZXJfZGF0YSRpZCldKQ0KDQojIEd1YXJkYXIgZWwgZGF0YXNldCBjb24gbG9zIHZhbG9yZXMgcHJlZGljaG9zDQojIGVuIGVsIGFyY2hpdm8gQ1NWICJrZXBsZXJfZGF0YV93aXRoX3BoaS5jc3YiDQp3cml0ZS5jc3Yoa2VwbGVyX2RhdGEsICJrZXBsZXJkYXRhZXN0aW1hdGVkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQpgYGANCg0KSW50ZXJwcmV0YWNpw7NuIGRlbCBtb2RlbG8gTGlnaHRHQk06IGltcG9ydGFuY2lhIGRlIGxhcyB2YXJpYWJsZXMNCg0KYGBge3Igc2VtaV9zdXBlcnZpc2VkX2xpZ2h0Z2JtX2ltcG9ydGFuY2V9DQojIEltcG9ydGFuY2lhIGRlIGxhcyB2YXJpYWJsZXMNCmxnYi5pbXBvcnRhbmNlKGxnYm1fbW9kZWwpICU+JQ0KICBsZ2IucGxvdC5pbXBvcnRhbmNlKHRvcF9uID0gMjAsIG1lYXN1cmUgPSAiR2FpbiIpDQoNCmBgYA0KDQpDb24gMTcgY2VudHJvaWRlcywgZWwgw6FyYm9sIGVzdGltYWRvIG11ZXN0cmEgcXVlIGxhcyB2YXJpYWJsZXMgY29uIG1heW9yIGltcG9ydGFuY2lhIG5vIHJlbGFjaW9uYWRhcyBjb24gbGFzIGNhcmFjdGVyw61zaXRpY2FzIGRlbCBzaXN0ZW1hIGVzdGVsYXIgc29uICoqdHR2X2ZsYWcqKiAoaW5kaWNhZG9yIGRlIHRyw6Fuc2l0byB2YXJpYWJsZSksICoqc3lfcG51bSoqIChjYW50aWRhZCBkZSBwbGFuZXRhcyBlbiBlbCBzaXN0ZW1hKSB5ICoqc3RfcmFkKiogKHJhZGlvIGRlIGxhIGVzdHJlbGxhIGNlbnRyYWwgZGVsIHNpc3RlbWEpIHNvbiBsYSBxdWUgc2UgZXNwZXJhcsOtYSBxdWUgdGVuZ2EgdW4gaW1wYWN0byBzaWduaWZpY2F0aXZvIGVuIGxhIGhhYml0YWJpbGlkYWQsIHlhIHF1ZSBlc3TDoW4gcmVsYWNpb25hZGFzIGNvbiBjYXJhY3RlcsOtc3RpY2FzIGbDrXNpY2FzIGRlbCBzaXN0ZW1hIGVzdGVsYXIuIE5vIGVzIHJhem9uYWJsZSBxdWUgZWwgbW9kZWxvIGhheWEgYXByZW5kaWRvIGEgcHJlZGVjaXIgZWwgUEhJIGEgcGFydGlyIGRlIGxhIGxhdGl0dWQgeSBsb25naXR1ZCBkZSBsb3MgcGxhbmV0YXMgZW4gZWwgZmlybWFtZW50bywgeWEgcXVlIG5vIGRlYmVyw61hbiBpbmZsdWlyIGVuIGxhIGhhYml0YWJpbGlkYWQuIFNpbiBlbWJhcmdvLCBlcyBwb3NpYmxlIHF1ZSBlbCBtb2RlbG8gaGF5YSBjYXB0dXJhZG8gcGF0cm9uZXMgcmVsYWNpb25hZG9zIGNvbiBsYSB1YmljYWNpw7NuIGRlIGxvcyBwbGFuZXRhcyBlbiBlbCBlc3BhY2lvIGRlIGNhcmFjdGVyw61zdGljYXMsIGxvIHF1ZSBwb2Ryw61hIHNlciDDunRpbCBwYXJhIGlkZW50aWZpY2FyIGdydXBvcyBkZSBwbGFuZXRhcyBjb24gY2FyYWN0ZXLDrXN0aWNhcyBzaW1pbGFyZXMuICANCg0KSGlzdG9ncmFtYSBkZSBQSEkgZXN0aW1hZG8NCg0KYGBge3Igc2VtaV9zdXBlcnZpc2VkX2xpZ2h0Z2JtX2hpc3RvZ3JhbX0NCg0KIyBIaXN0b2dyYW1hIGRlIFBISSBlc3RpbWFkbw0KZ2dwbG90KGtlcGxlcl9kYXRhLCBhZXMoeCA9IHBoaV9lc3RpbWF0ZWQpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wNSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC43KSArDQogIHN0YXRfYmluKGJpbndpZHRoID0gMC4wNSwgZ2VvbSA9ICJ0ZXh0IiwgYWVzKGxhYmVsID0gYWZ0ZXJfc3RhdChjb3VudCkpLA0KICAgICAgICAgICB2anVzdCA9IC0wLjUsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMDUpKSArDQogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtYSBkZSBQSEkgRXN0aW1hZG8iLA0KICAgICAgIHggPSAiUEhJIEVzdGltYWRvIiwNCiAgICAgICB5ID0gIkZyZWN1ZW5jaWEiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdCA9IDEpKQ0KDQpgYGANCg0KRWwgaGlzdG9ncmFtYSBkZSAqKlBISSBlc3RpbWFkbyoqIG11ZXN0cmEgdW5hIGRpc3RyaWJ1Y2nDs24gc2VzZ2FkYSBoYWNpYSBsYSBkZXJlY2hhIGNvbiBwaWNvcyBlbiAwLCAwLjU1LCAwLjY1LCAwLjcwIHkgMC43NSwgbG8gcXVlIHN1Z2llcmUgcXVlIGVsIG1vZGVsbyBoYSBhcHJlbmRpZG8gYSBwcmVkZWNpciB1biB2YWxvciBkZSBQSEkgcmVsYXRpdmFtZW50ZSBhbHRvIHBhcmEgbGEgbWF5b3LDrWEgZGUgbG9zIHBsYW5ldGFzLiAqKkVzdG8gcHVlZGUgc2VyIHVuIGluZGljYXRpdm8gZGUgcXVlIGVsIG1vZGVsbyBoYSBjYXB0dXJhZG8gcGF0cm9uZXMgZW4gbG9zIGRhdG9zKiosIHBlcm8gdGFtYmnDqW4gcHVlZGUgcmVmbGVqYXIgbGEgaW5mbHVlbmNpYSBkZSBsYXMgZXRpcXVldGFzIGTDqWJpbGVzIHkgbGEgZmFsdGEgZGUgZGF0b3MgcmVhbGVzLmANCg0KYGBge3Igc2VtaV9zdXBlcnZpc2VkX2hhYml0YWJsZV9wbGFuZXRzfX0NCg0KIyBDb250YXIgbGEgY2FudGlkYWQgZGUgcGxhbmV0YXMgY29uIHBoaV9lc3RpbWF0ZWQgPiAwLjcwDQpoYWJpdGFibGVfcGxhbmV0cyA8LSBzdW0oa2VwbGVyX2RhdGEkcGhpX2VzdGltYXRlZCA+IDAuNzAsIG5hLnJtID0gVFJVRSkNCg0KIyBDb250YXIgbGEgY2FudGlkYWQgdG90YWwgZGUgcGxhbmV0YXMNCnRvdGFsX3BsYW5ldHMgPC0gbnJvdyhrZXBsZXJfZGF0YSkNCg0KIyBDYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIHBsYW5ldGFzIGhhYml0YWJsZXMNCnBlcmNlbnRhZ2VfaGFiaXRhYmxlIDwtIChoYWJpdGFibGVfcGxhbmV0cyAvIHRvdGFsX3BsYW5ldHMpICogMTAwDQoNCiMgTW9zdHJhciByZXN1bHRhZG9zDQpjYXQoIlBvcmNlbnRhamUgZGUgcGxhbmV0YXMgaGFiaXRhYmxlczoiLCBwZXJjZW50YWdlX2hhYml0YWJsZSwgIiVcbiIpDQoNCmBgYA0KDQpTaSBiaWVuIGhlbW9zIGNvbiBzZWd1aWRvIHVuIGVuZm9xdWUgc2VtaS1zdXBlcnZpc2FkbyBwYXJhIGVzdGltYXIgZWwgUEhJLCBlcyBpbXBvcnRhbnRlIHRlbmVyIGVuIGN1ZW50YSBxdWUgbGEgY2FsaWRhZCBkZSBsYXMgcHJlZGljY2lvbmVzIGRlcGVuZGVyw6EgZW4gZ3JhbiBtZWRpZGEgZGUgbGEgY2FsaWRhZCBkZSBsb3MgZGF0b3MgeSBkZSBsYSBjYXBhY2lkYWQgZGVsIG1vZGVsbyBwYXJhIGdlbmVyYWxpemFyIGEgcGFydGlyIGRlIGxhcyBldGlxdWV0YXMgZMOpYmlsZXMuIExhIGludGVycHJldGFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcyBkZWJlIGhhY2Vyc2UgY29uIGNhdXRlbGEsIHlhIHF1ZSBlbCBtb2RlbG8gcHVlZGUgaGFiZXIgYXByZW5kaWRvIHBhdHJvbmVzIGVzcHVyaW9zIG8gbm8gcmVwcmVzZW50YXRpdm9zLiBQb25pZW5kbyB1biB1bWJyYWwgZGUgMC43MCBwYXJhIGNvbnNpZGVyYXIgdW4gcGxhbmV0YSBoYWJpdGFibGUsIHNlcsOtYSBlc3BlcmFibGUgcXVlIGxhIGNhbnRpZGFkIGRlIHBsYW5ldGFzIGhhYml0YWJsZXMgc2VhIG1pbm9yaXRhcmlvYTsgc2luIGVtYmFyZ28gbGEgcHJlZGljY2nDs24gZGUgUEhJIGVzdGltYWRvIG11ZXN0cmEgcXVlIG3DoXMgZGVsIDY4JSBkZSBsb3MgcGxhbmV0YXMgdGllbmVuIHVuIFBISSBlc3RpbWFkbyBzdXBlcmlvciBhIDAuNzAsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBlbCBtb2RlbG8gcHVlZGUgaGFiZXIgYXByZW5kaWRvIHBhdHJvbmVzIGVzcHVyaW9zIG8gbm8gcmVwcmVzZW50YXRpdm9zLg0KDQojIyBDb21wYXJhdGl2YSBkZSBsb3MgbW9kZWxvcyBkZSBjbGFzaWZpY2FjacOzbg0KDQpMYSByZWdyZXNpw7NuIGxvZ8Otc3RpY2EsIGVudHJlbmFkYSDDum5pY2FtZW50ZSBzb2JyZSBsb3MgMTcgcGxhbmV0YXMgY29uIFBISSBjb25vY2lkbywgKipwdWVkZSBvZnJlY2VyIHVuIGJ1ZW4gYWp1c3RlIGxvY2FsIHNvYnJlIGVzZSBjb25qdW50byByZWR1Y2lkbywgcGVybyBjYXJlY2UgY29tcGxldGFtZW50ZSBkZSBjYXBhY2lkYWQgcGFyYSBnZW5lcmFsaXphciBhbCByZXN0byBkZWwgZGF0YXNldCoqLiBTdSB1dGlsaWRhZCBwcsOhY3RpY2EgZXMgbXV5IGxpbWl0YWRhLCB5YSBxdWUgbm8gcGVybWl0ZSBlc3RpbWFyIGVsIMOtbmRpY2UgZGUgaGFiaXRhYmlsaWRhZCBwYXJhIGxvcyBtaWxlcyBkZSBwbGFuZXRhcyBubyBldGlxdWV0YWRvcy4gQWRlbcOhcywgYWwgdHJhYmFqYXIgY29uIHRhbiBwb2NvcyBkYXRvcywgZXMgZXh0cmVtYWRhbWVudGUgc2Vuc2libGUgYWwgcnVpZG8geSBwcm9wZW5zYSBhbCBzb2JyZWFqdXN0ZS4NCg0KRW4gY29udHJhc3RlLCBlbCBtb2RlbG8gc2VtaS1zdXBlcnZpc2FkbyBiYXNhZG8gZW4gSy1tZWFucyB5IExpZ2h0R0JNICoqdXRpbGl6YSBsYSBlc3RydWN0dXJhIGdsb2JhbCBkZSBsb3MgZGF0b3MgcGFyYSBwcm9wYWdhciBldGlxdWV0YXMgeSBlbnRyZW5hciB1biBtb2RlbG8gcXVlIHByZWRpY2UgUEhJIHBhcmEgdG9kbyBlbCBjb25qdW50byoqLiBBdW5xdWUgcHVlZGUgc2VyIG1lbm9zIHByZWNpc28gZW4gbG9zIHBvY29zIGNhc29zIGNvbm9jaWRvcywgZ2FuYSBhbXBsaWFtZW50ZSBlbiBjb2JlcnR1cmEsIHJvYnVzdGV6IHkgYXBsaWNhYmlsaWRhZC4gU3UgY2FwYWNpZGFkIGRlIGdlbmVyYWxpemFyIHkgZ2VuZXJhciBoaXDDs3Rlc2lzIGEgcGFydGlyIGRlIHVuIGNvbmp1bnRvIGRlIGRhdG9zIG1heW9yIGxvIGNvbnZpZXJ0ZSBlbiB1bmEgaGVycmFtaWVudGEgbXVjaG8gbcOhcyDDunRpbCBlbiBjb250ZXh0b3MgZG9uZGUgbGEgZXNjYXNleiBkZSBldGlxdWV0YXMgZXMgbGEgbm9ybWEuDQoNCiMgUG9zaWJsZXMgbWVqb3JhcyBwYXJhIGZ1dHVyb3MgYW7DoWxpc2lzDQoNClBhcmEgbWVqb3JhciBlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsb2fDrXN0aWNhLCBlcyBmdW5kYW1lbnRhbCBhcGxpY2FyIHTDqWNuaWNhcyBkZSByZWd1bGFyaXphY2nDs24gKGNvbW8gTDEgbyBMMikgcGFyYSBtaXRpZ2FyIGVsIHNvYnJlYWp1c3RlIGRlcml2YWRvIGRlbCBlc2Nhc28gbsO6bWVybyBkZSBvYnNlcnZhY2lvbmVzLiBUYW1iacOpbiBzZSByZWNvbWllbmRhIHVuYSBzZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyBjdWlkYWRvc2EsIHByaW9yaXphbmRvIGFxdWVsbGFzIGNvbiBmdWVydGUgY29ycmVsYWNpw7NuIGNvbiBQSEkgbyBqdXN0aWZpY2FjacOzbiBmw61zaWNhLiBMYSBpbmNsdXNpw7NuIGRlIHRyYW5zZm9ybWFjaW9uZXMgbm8gbGluZWFsZXMgZSBpbnRlcmFjY2lvbmVzIHB1ZWRlIGNhcHR1cmFyIHJlbGFjaW9uZXMgbcOhcyBjb21wbGVqYXMsIHkgZWwgdXNvIGRlIHZhbGlkYWNpw7NuIGNydXphZGEgdGlwbyBsZWF2ZS1vbmUtb3V0IChMT09DVikgbWF4aW1pemEgZWwgYXByb3ZlY2hhbWllbnRvIGRlbCBjb25qdW50byBsaW1pdGFkbyBkZSBkYXRvcy4gQWx0ZXJuYXRpdmFtZW50ZSwgdW5hIHJlZ3Jlc2nDs24gbG9nw61zdGljYSBiYXllc2lhbmEgcGVybWl0aXLDrWEgaW5jb3Jwb3JhciBpbmNlcnRpZHVtYnJlIHkgY29ub2NpbWllbnRvIHByZXZpbyBzb2JyZSBsb3MgZmFjdG9yZXMgcXVlIGluZmx1eWVuIGVuIGxhIGhhYml0YWJpbGlkYWQuDQoNClBhcmEgZWwgbW9kZWxvIHNlbWktc3VwZXJ2aXNhZG8sIGxhcyBtZWpvcmFzIHNlIGVuZm9jYW4gZW4gcmVmaW5hciBsYSBnZW5lcmFjacOzbiBkZSBwc2V1ZG8tZXRpcXVldGFzIHkgYXByb3ZlY2hhciBtZWpvciBsYSBlc3RydWN0dXJhIGRlbCBjb25qdW50byBkZSBkYXRvcy4gVW5hIG9wY2nDs24gZXMgdXRpbGl6YXIgcHNldWRvLWxhYmVsaW5nIGl0ZXJhdGl2bywgZG9uZGUgZWwgbW9kZWxvIGFjdHVhbGl6YSBzdXMgcHJlZGljY2lvbmVzIGVuIGNpY2xvcyBzdWNlc2l2b3MuIFRhbWJpw6luIHB1ZWRlIGV4cGxvcmFyc2UgdW4gYWp1c3RlIGRpbsOhbWljbyBkZWwgbsO6bWVybyBkZSBjbHVzdGVycyBvIGVsIHVzbyBkZSBhbGdvcml0bW9zIGRlIGNsdXN0ZXJpbmcgbcOhcyBmbGV4aWJsZXMuIEluY29ycG9yYXIgZW1iZWRkaW5ncyBnZW5lcmFkb3MgcG9yIGF1dG9lbmNvZGVycyBvIHTDqWNuaWNhcyBubyBzdXBlcnZpc2FkYXMgcGVybWl0aXLDrWEgcmVwcmVzZW50YXIgbWVqb3IgbGFzIHJlbGFjaW9uZXMgbGF0ZW50ZXMgZW50cmUgcGxhbmV0YXMuIEFkZW3DoXMsIGFzaWduYXIgcGVzb3MgdmFyaWFibGVzIGEgbGFzIHBzZXVkby1ldGlxdWV0YXMgc2Vnw7puIHN1IGNvbmZpYWJpbGlkYWQgeSB2YWxpZGFyIMO6bmljYW1lbnRlIHNvYnJlIGxvcyBjYXNvcyBjb24gUEhJIHJlYWwgbWVqb3JhIGxhIHJvYnVzdGV6IHkgbGEgY2FwYWNpZGFkIGRlIGdlbmVyYWxpemFjacOzbiBkZWwgbW9kZWxvLg0KRW4gY29uY2x1c2nDs24sIGF1bnF1ZSBsYSByZWdyZXNpw7NuIGxpbmVhbCBkZSBsYXMgdmFyaWFibGVzIGZhbHRhbnRlcyBwdWVkZSBheXVkYXIgYSByZWN1cGVyYXIgb2JzZXJ2YWNpb25lcyB5IG1lam9yYXIgbGEgZXN0YWJpbGlkYWQgZGVsIG1vZGVsbyBsb2fDrXN0aWNvLCBlcyBpbXBvcnRhbnRlIHNlciBjb25zY2llbnRlIGRlIGxvcyAqKmVycm9yZXMgZGUgcHJlZGljY2nDs24gYWN1bXVsYWRvcyoqIHkgZGVsIGltcGFjdG8gcXVlIHB1ZWRlbiB0ZW5lciBlbiBsYSB2YWxpZGV6IGRlIGxhcyBlc3RpbWFjaW9uZXMuIEV2YWx1YXIgY3VpZGFkb3NhbWVudGUgZXN0b3MgYXNwZWN0b3MgZ2FyYW50aXphcsOhIHF1ZSBlbCBtb2RlbG8gZmluYWwgc2VhIG3DoXMgY29uZmlhYmxlIHkgcXVlIHN1cyBjb25jbHVzaW9uZXMgc2VhbiBpbnRlcnByZXRhZGFzIGNvbiBsYSBkZWJpZGEgY2F1dGVsYS4NCg0KIyBDb25jbHVzaW9uZXMNCg0KRWwgYW7DoWxpc2lzIHJlYWxpemFkbyBwZXJtaXRpw7MgZXZhbHVhciBkaWZlcmVudGVzIG1vZGVsb3MgZGUgcmVncmVzacOzbiBwYXJhIHByZWRlY2lyIGVsIHJhZGlvIGRlIGxvcyBleG9wbGFuZXRhcyB5IGV4cGxvcmFyIGxhIHJlbGFjacOzbiBlbnRyZSBzdXMgY2FyYWN0ZXLDrXN0aWNhcyBmw61zaWNhcy4gU2UgcHJvYmFyb24gbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbCB5IGxvZ8Otc3RpY2EsIGluY2x1eWVuZG8gdHJhbnNmb3JtYWNpb25lcyBwYXJhIG1lam9yYXIgbGEgbm9ybWFsaWRhZCBkZSBsb3MgcmVzaWR1b3MgeSBjb3JyZWdpciBwcm9ibGVtYXMgZGUgaGV0ZXJvY2VkYXN0aWNpZGFkLiBMb3MgcmVzdWx0YWRvcyBpbmRpY2Fyb24gcXVlIGVsIG1vZGVsbyAqKmBwbF9yYWRqIH4gcGxfcnZhbXBgIGNvbiB0cmFuc2Zvcm1hY2nDs24gbG9nYXLDrXRtaWNhKiogZnVlIGVsIG3DoXMgZWZlY3Rpdm8sIGV4cGxpY2FuZG8gZWwgKio4NC4yNSUgZGUgbGEgdmFyaWFiaWxpZGFkKiogZW4gZWwgcmFkaW8gZGVsIGV4b3BsYW5ldGEgeSBjdW1wbGllbmRvIGNvbiBsb3MgcHJpbmNpcGFsZXMgc3VwdWVzdG9zIGVzdGFkw61zdGljb3MuIFNpbiBlbWJhcmdvLCBlbCBtb2RlbG8gZGUgKipyZWdyZXNpw7NuIGxvZ8Otc3RpY2EqKiBwYXJhIHByZWRlY2lyIGxhIGhhYml0YWJpbGlkYWQgcGxhbmV0YXJpYSBwcmVzZW50w7MgbGltaXRhY2lvbmVzIGRlYmlkbyBhIGxhIGVzY2FzZXogZGUgZGF0b3MgY29tcGxldG9zLCBsbyBxdWUgYWZlY3TDsyBzdSBlc3RhYmlsaWRhZCB5IGNhcGFjaWRhZCBwcmVkaWN0aXZhLg0KDQpQYXJhIG1lam9yYXIgbGEgY2FsaWRhZCBkZSBsb3MgbW9kZWxvcywgZXMgZnVuZGFtZW50YWwgYWJvcmRhciBlbCBwcm9ibGVtYSBkZSBsb3MgdmFsb3JlcyBmYWx0YW50ZXMsIHlhIHNlYSBtZWRpYW50ZSAqKmltcHV0YWNpw7NuIGRlIGRhdG9zKiogbyBsYSByZWNvbGVjY2nDs24gZGUgbcOhcyBvYnNlcnZhY2lvbmVzLiBBZGVtw6FzLCBhbCB1dGlsaXphciB2YXJpYWJsZXMgZXN0aW1hZGFzIGVuIG1vZGVsb3MgcG9zdGVyaW9yZXMsIHNlIGRlYmUgY29uc2lkZXJhciBlbCBpbXBhY3RvIGRlIGxvcyAqKmVycm9yZXMgZGUgcHJlZGljY2nDs24gYWN1bXVsYWRvcyoqIGVuIGxvcyByZXN1bHRhZG9zIGZpbmFsZXMuIFNpIGJpZW4gbGFzIHRyYW5zZm9ybWFjaW9uZXMgZGUgZGF0b3MgYXl1ZGFyb24gYSBtZWpvcmFyIGxhIHByZWNpc2nDs24gZGUgYWxndW5vcyBtb2RlbG9zLCBsYSBmYWx0YSBkZSBkYXRvcyBzaWd1ZSBzaWVuZG8gdW5hIGxpbWl0YWNpw7NuIGNsYXZlIHBhcmEgbGEgcHJlZGljY2nDs24gZGUgbGEgKipoYWJpdGFiaWxpZGFkIHBsYW5ldGFyaWEqKi4gRnV0dXJhcyBpbnZlc3RpZ2FjaW9uZXMgZGViZXLDrWFuIGNlbnRyYXJzZSBlbiBhbXBsaWFyIGVsIGNvbmp1bnRvIGRlIGRhdG9zIHkgZXhwbG9yYXIgZW5mb3F1ZXMgbcOhcyByb2J1c3RvcywgY29tbyBtb2RlbG9zIGRlIGFwcmVuZGl6YWplIGF1dG9tw6F0aWNvLCBxdWUgcG9kcsOtYW4gbWVqb3JhciBsYSBjYXBhY2lkYWQgcHJlZGljdGl2YSBkZSBlc3RvcyBhbsOhbGlzaXMuDQoNCiMgUmVmZXJlbmNpYXMNCg==