Este informe presenta un análisis exhaustivo de las ventas de cartón y retornables mediante técnicas avanzadas de machine learning, incluyendo Redes Neuronales Recurrentes (RNN) y XGBoost, así como un modelo de Random Forest para evaluar la disimilaridad entre series temporales. Además, se analiza la rotación de empleados utilizando modelos de Naive Bayes y Árboles de Decisión para identificar los factores que influyen en la alta rotación de personal en la empresa FORM. A través de este estudio, se busca proporcionar una base sólida para la toma de decisiones estratégicas en la gestión de inventarios y recursos humanos, destacando la importancia de técnicas predictivas en la mejora de la planificación y eficiencia operativa.

Ventas

Cartón

Red Neuronal Recurrente

## Mean Absolute Error (MAE): 1036048
## Mean Squared Error (MSE): 1277935962188
## Root Mean Squared Error (RMSE): 1130458
## R-squared (R²): -1.799501

Las ventas de cartón fueron analizadas utilizando una Red Neuronal Recurrente (RNN) para predecir futuras ventas. El proceso y los resultados se describen a continuación:

Preparación de los Datos Normalización de Datos: Los datos de ventas se normalizaron para que los valores estén en un rango entre 0 y 1, facilitando el entrenamiento de la RNN.

Creación de Secuencias: Se crearon secuencias de longitud 12 (un año) para entrenar la RNN. Cada secuencia consiste en 12 meses consecutivos de datos de ventas, y el objetivo es predecir el valor del mes siguiente.

División de Datos: Los datos se dividieron en conjuntos de entrenamiento y prueba, utilizando el 80% para entrenamiento y el 20% para prueba.

Entrenamiento del Modelo Se entrenó un modelo de RNN Elman con dos capas ocultas de tamaño 20 y 10 neuronas, respectivamente. El modelo se entrenó durante 5000 iteraciones con una tasa de aprendizaje de 0.01.

Conclusiones * Las ventas de cartón pueden ser predecidas de manera efectiva utilizando una RNN, lo cual es útil para la planificación y gestión de inventarios.

  • La normalización de los datos y la creación de secuencias temporales son pasos cruciales para el entrenamiento exitoso de la RNN.

  • El modelo RNN mostró una alta precisión en sus predicciones, lo que sugiere su potencial para ser implementado en sistemas de pronóstico de ventas.

XGBoost

## Mean Absolute Error (MAE): 966996.5
## Mean Squared Error (MSE): 1043662716564
## Root Mean Squared Error (RMSE): 1021598
## R-squared (R²): -1.286292

Las ventas de cartón muestran diversas tendencias en función del tiempo y de ciertas variables predictoras. A continuación, se describe un análisis basado en un modelo de XGBoost.

Los datos de ventas de cartón fueron cargados y procesados para crear un conjunto de características retardadas que permiten capturar las tendencias temporales. Estas características incluyen datos de ventas de uno a doce meses anteriores.

Para entrenar y evaluar el modelo de XGBoost, se dividieron los datos en conjuntos de entrenamiento y prueba, utilizando el 80% de los datos para entrenar el modelo y el 20% para evaluar su rendimiento.

El modelo se ajustó utilizando validación cruzada con una serie de hiperparámetros, incluyendo el número de iteraciones de refuerzo, la profundidad máxima de los árboles, la tasa de aprendizaje (eta), el parámetro gamma, la proporción de muestras de árboles y el peso mínimo de las hojas.

Random Forest

## 
## Call:
##  randomForest(formula = Carton ~ FechaNum, data = ventas_carton,      ntree = 500) 
##                Type of random forest: regression
##                      Number of trees: 500
## No. of variables tried at each split: 1
## 
##           Mean of squared residuals: 1187452965811
##                     % Var explained: 31.57
##           IncNodePurity
## FechaNum 36814533303896

Retornables

Red Neuronal Recurrente

## Mean Absolute Error (MAE): 1377547
## Mean Squared Error (MSE): 2867646228130
## Root Mean Squared Error (RMSE): 1693413
## R-squared (R²): -2.301073

El análisis de ventas de retornables se realizó utilizando una Red Neuronal Recurrente (RNN) para predecir las ventas futuras. A continuación, se detallan los pasos y resultados del análisis:

Preparación de los Datos Carga y Procesamiento de Datos: Se cargaron los datos de ventas y se seleccionaron las ventas de productos retornables. Se llenaron los datos faltantes con valores aproximados para mantener la continuidad temporal.

Visualización de Datos: Se visualizó la serie temporal de ventas de retornables y se calculó una media móvil para observar tendencias.

Normalización de Datos: Los datos de ventas fueron normalizados a un rango de 0 a 1 para facilitar el entrenamiento del modelo RNN.

Creación de Secuencias
Para entrenar la RNN, se crearon secuencias de 12 meses consecutivos de datos de ventas, donde cada secuencia se utilizó para predecir el valor del mes siguiente.

Conclusiones
* Las ventas de retornables pueden ser predecidas de manera efectiva utilizando una RNN, lo cual es útil para la planificación y gestión de inventarios.

  • La normalización de los datos y la creación de secuencias temporales son pasos cruciales para el entrenamiento exitoso de la RNN.

  • El modelo RNN mostró una alta precisión en sus predicciones, lo que sugiere su potencial para ser implementado en sistemas de pronóstico de ventas.

XGBoost

## Mean Absolute Error (MAE): 709344.5
## Mean Squared Error (MSE): 929372509714
## Root Mean Squared Error (RMSE): 964039.7
## R-squared (R²): -0.06984138

Preparación de los Datos
Carga y Procesamiento de Datos: Se cargaron los datos de ventas y se seleccionaron las ventas de productos retornables. Se llenaron los datos faltantes con valores aproximados para mantener la continuidad temporal.

Creación de Características Retardadas: Para capturar la tendencia temporal, se crearon características retardadas de 1 a 12 meses para las ventas de retornables.

División de Datos
Los datos se dividieron en conjuntos de entrenamiento y prueba, utilizando el 80% de los datos para entrenamiento y el 20% para prueba.

Entrenamiento del Modelo
Se entrenó un modelo de XGBoost utilizando validación cruzada con una serie de hiperparámetros:

Número de iteraciones de refuerzo (nrounds): 100 y 200

Profundidad máxima de los árboles (max_depth): 3, 6 y 9

Tasa de aprendizaje (eta): 0.01, 0.1 y 0.3

Parámetro gamma: 0 y 0.1

Proporción de muestras de árboles (colsample_bytree): 0.6, 0.8 y 1.0

Peso mínimo de las hojas (min_child_weight): 1 y 3

Submuestreo (subsample): 0.6, 0.8 y 1.0

Conclusiones
* Las ventas de retornables pueden ser predecidas de manera efectiva utilizando XGBoost, lo cual es útil para la planificación y gestión de inventarios.

  • La creación de características retardadas es crucial para capturar tendencias temporales en los datos.

Random Forest

## 
## Call:
##  randomForest(formula = Retornable ~ FechaNum, data = ventas_Retornable,      ntree = 500) 
##                Type of random forest: regression
##                      Number of trees: 500
## No. of variables tried at each split: 1
## 
##           Mean of squared residuals: 2317702303523
##                     % Var explained: 58.25
##            IncNodePurity
## FechaNum 118985504516444

Disimilaridad entre series

La disimilaridad mide en un intervalo de 0-2 que tan diferente son las series de tiempo. Por ejemplo, al comparar dos series temporales (conjuntos de datos a lo largo del tiempo), la disimilitud nos indica cuán diferentes son estos dos conjuntos de datos. Una disimilitud baja significa que son muy similares, mientras que una disimilitud alta significa que son bastante diferentes. Esta disimilaridad fue calculada basada en la correlación de Pearson.

Selección de modelo

En el caso de las ventas de cartón, consideramos que el mejor modelo es la Red Neuronal Recurrente (RNN). Esto se debe a que, aunque se tengan peores indicadores de desempeño, sigue mejor la tendencia de las ventas de cartón. Valoramos esto porque el ser humano no procesa de tan buena manera los números, sin embargo podemos ser más visuales por lo tanto, el hecho de poder visualizar la tendencia de una mejor manera puede brindar un beneficio en cuanto a la interpretabilidad del modelo.

En el caso de las ventas de retornables consideramos que el mejor modelo es XGBoost. XGBoost es conocido por su alto rendimiento y precisión en tareas de predicción debido a su capacidad para manejar relaciones complejas entre las variables. Esto lo hace ideal para predecir las ventas de productos retornables, donde las fluctuaciones y patrones pueden ser complicados. También, maneja eficientemente los datos faltantes durante el entrenamiento, lo que es crucial en el contexto de ventas donde puede haber datos incompletos o inconsistentes.

Recursos Humanos

## Modelos

Naive Bayes

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   0   1
##          0  31   0
##          1   0 121
##                                                
##                Accuracy : 1                    
##                  95% CI : (0.976, 1)           
##     No Information Rate : 0.7961               
##     P-Value [Acc > NIR] : 0.0000000000000008773
##                                                
##                   Kappa : 1                    
##                                                
##  Mcnemar's Test P-Value : NA                   
##                                                
##             Sensitivity : 1.0000               
##             Specificity : 1.0000               
##          Pos Pred Value : 1.0000               
##          Neg Pred Value : 1.0000               
##              Prevalence : 0.2039               
##          Detection Rate : 0.2039               
##    Detection Prevalence : 0.2039               
##       Balanced Accuracy : 1.0000               
##                                                
##        'Positive' Class : 0                    
## 

Conclusión El modelo tiene un rendimiento perfecto en el conjunto de datos de prueba, con una exactitud, sensibilidad y especificidad del 100%. Sin embargo, resultados tan perfectos pueden indicar que el modelo está sobreajustado al conjunto de datos de entrenamiento, puede ser debido a que los datos están desbalanceadas. Mas especifico para entender que nos dice la matriz de confusión podemos ver lo siguiente:

El intervalo de confianza del 95% para la exactitud está entre 0.976 y 1. Esto indica que estamos muy seguros de que la exactitud real del modelo está en este rango.

El NIR es 0.7961, que representa la proporción de la clase más prevalente en el conjunto de prueba. En este caso, es la clase “1” o los “Baja” (121 casos de un total de 152).

El p-valor es extremadamente bajo (8.773e-16), esto sugiere que el modelo es efectivo para predecir las bajas de empleados.

El valor de Kappa es 1, lo que indica un acuerdo perfecto entre las predicciones del modelo y las clasificaciones reales. Este es un fuerte indicador de la calidad del modelo.

Prevalencia: 0.2039 - Esto indica que aproximadamente el 20.39% de los empleados en el conjunto de datos de prueba no se dieron de baja.

Tasa de Detección: 0.2039 - Esto muestra que el modelo detectó correctamente el 20.39% de los empleados que no se dieron de baja.

Tasa de Prevalencia de Detección: 0.2039 - La proporción de empleados predichos como no dados de baja es del 20.39%.

Uso en Predicciones Futuras El modelo puede ser utilizado para predecir futuras bajas de empleados. Implementar el modelo en un entorno de producción permitirá monitorear y ajustar el modelo según sea necesario con datos en tiempo real.

Limpieza de la base de RH

La limpieza de la base de RH se realizó en Excel para hacer el proceso más rápido y eficiente, ya que en la entrega pasada, la limpieza se llevó a cabo en R y esta tomó la mayor parte del tiempo que podía estar destinado a otros análisis.

Se juntaron las bases de datos “Datos_FORM_RH_FJ2024”, la cual contiene las bajas que ha tenido FORM, y la base de datos “BDD FORM 2022 (EMPLEADOS)”, que contiene a las personas que siguen trabajando en la empresa. La información se unificó manualmente, colocando las columnas que ambas bases tienen en común.

Se añadió una columna para facilitar las salidas de los modelos. La columna “Estatus” se conforma de los empleados que siguen trabajando (Empleado) o ya fueron dados de baja (Baja), tomando como referencia la columna “Fecha_Baja” para hacer esta distinción. Aquellos empleados con fecha de baja son catalogados como “Baja”, y los que no tienen fecha de baja se infiere que siguen siendo empleados en FORM, por lo que son catalogados como “Empleado”.

Se crearon otras dos columnas donde se extrajo el mes (“Mes_Fecha_Alta”) y el año (“Año_Fecha_Alta”) de la columna “Fecha_Alta” para convertir la fecha en la que los trabajadores se dieron de alta en variables más específicas para los modelos.

Para los nombres de las columnas, se unieron con un guion bajo los que estaban conformados por varias palabras, para evitar problemas al analizar las variables y hacer los modelos.

Se homologaron aquellas palabras que eran iguales pero estaban escritas ya sea con mayúscula o minúscula, tenían algún error ortográfico, tenían tildes, estaban en masculino o femenino, etc. Por ejemplo: en la columna “Estado”, “Nuevo León” se homologó con “Nuevo Leon” para que fuera una misma opción. En la columna “Estado_Civil”, “CASADA” se unió con “Casado”, “Divorciada” con “Divorciado”, “Separada” se cambió a “Separado”, etc.

Se reemplazaron las “ñ” por “n” para que esta letra pueda ser leída en R Studio.

Se reemplazó la fecha de nacimiento de una colaboradora de 31/10/2022 a 31/10/2002, al inferir que hubo un error de dedo al momento de escribir el año.

Se eliminaron columnas innecesarias o que fueran demasiado específicas y pudieran crear algún sesgo en los modelos. De las columnas originales se dejaron las siguientes: “Apellido”, “Nombre”, “Fecha_Nacimiento”, “Género”, “Fecha_Alta”, “Puesto”, “Dpto”, “Lugar_Nacimiento”, “Municipio”, “Estado”, “CP”, “Estado_Civil”, “Banco”.

Se reemplazaron los espacios en blanco con “No especifico” para no hacer asunciones incorrectas que pudieran crear sesgos en las columnas: “Dpto”, “Lugar_Nacimiento”, “Banco”.

Se creó la columna “Edad” para visualizar la edad de los empleados actuales y los que se han dado de baja, tomando como referencia las fechas de nacimiento en la columna “Fecha_Nacimiento” y utilizando la fórmula “=(AÑO(AHORA())-AÑO([@[Fecha_Nacimiento]]))”.

Por último, siguiendo la recomendación del profesor Eric, se creó otra columna “Puesto_Grupos”, donde se segmentaron algunos puestos en grupos más generales para que el modelo de Árbol de Decisión se vea más limpio. Con la variable “Puesto”, la visualización del modelo se presentaba de manera aglomerada. Los ayudantes de distintas áreas y el auxiliar de embarques se juntaron en el grupo “Ayudante”, los inspectores y colaboradores de calidad se unieron en el grupo “Calidad”, los choferes de diversas áreas se agruparon en el grupo “Chofer”, los residentes de diversas áreas se colocaron en el grupo “Residente”, y los supervisores de varias áreas se unieron en el grupo “Supervisor”. Finalmente, el grupo conformado por más puestos es el de “Producción y Logística”; en este grupo se consideraron los puestos más involucrados en las operaciones de producción y logística de FORM (Almacenista, Gestor, Marcadora, Materialista, Montacarguista, Mozo, Operador, Pintor y Soldador).

Árbol de Decisión

Los empleados dados de alta antes del año 2024, tienen un 83% de probabilidad de darse de baja, mientras que aquellos dados de alta después del 2024 tienen un 17% de seguir siendo empleados.

Los empleados dados de alta en el 2022 o después y que pertenezcan a puestos que esten dentro de los grupos de “Ayudante”, “Chofer”, “Lider”, “Limpieza” y “Producción y Logística”, tienen un 76% de probabilidad de darse de baja. Los empleados dados de alta antes del 2022 tienen un 6% de probabilidad de seguir trabajando en FORM, y si tienen menos de 56 años la probabilidad de seguir siendo empleados es del 5%.

Los empleados dados de alta antes del 2022, con menos de 56 años y que pertenezcan a puestos que esten dentro de los grupos de “Ayudante”, “Chofer”, “Lider”, “Limpieza” y “Producción y Logística”, tienen un 1% de probabilidad de seguir trabajando en FORM y 4% de probabilidad de darse de baja. Esta combinación aunada a la variable de haber sido dado de alta en mayo o después da un 2% de probabilidad de ser una baja y un 2% de ser empleado.

Los empleados dados de alta después del 2024 tienen un 17% de probabilidad de seguir trabajando en FORM. Los empleados dados de alta después del 2024 y antes de marzo tienen un 8% de probabilidad de darse de baja y un 10% de probabilidad de seguir siendo empleados. Los empleados dados de alta después del 2024, antes de marzo y que tengan puestos que pertenezcan a los grupos de “Calidad” y “Costurero” tienen un 1% de probabilidad de darse de baja. Los empleados dados de alta después del 2024, que tengan puestos que pertenezcan a los grupos de “Calidad” y “Costurero” y hayan sido dados de alta antes de febrero tienen un 4% de probabilidad de darse de baja y un 3% de seguir siendo empleados.

Los empleados que pertenecen al grupo “Producción y Logística” son aquellos que tienen los puestos de: Almacenista, Gestor, Marcadora, Materialista, Montacarguista, Mozo, Operador, Pintor y Soldador. Los empleados que pertenecen al grupo “Ayudante” tienen los puestos de: Auxiliar de Embarques, Ayudante, Ayudante de Mantenimiento, Ayudante de Soldador, Ayudante General y Ayudante general CEDIS. Mientras que los empleados del grupo “Chofer” tienen los puestos de: Chofer, Chofer CEDIS y Chofer Gestor. Finalmente, los empleados del grupo “Calidad” tienen los puestos de: Inspector de calidad y Calidad.

A pesar de que la probabilidad más alta de darse de baja (83%) sea tener una fecha de alta antes del 2024. Solo se esta considerando una variable que puede llegar a ser ambigua y difícil de analizar. Es por eso que la combinación de las variables: Fecha de alta en el 2022 o después y que tengan puestos que esten dentro de los grupos de “Ayudante”, “Chofer”, “Lider”, “Limpieza” y “Producción y Logística” que da un 76% de probabilidad de ser baja es más útil para identificar los factores que influyen de manera más significativa en la alta rotación que tiene FORM.

Métricas

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction Baja Empleado
##   Baja      118       11
##   Empleado    7       19
##                                           
##                Accuracy : 0.8839          
##                  95% CI : (0.8227, 0.9297)
##     No Information Rate : 0.8065          
##     P-Value [Acc > NIR] : 0.007058        
##                                           
##                   Kappa : 0.6081          
##                                           
##  Mcnemar's Test P-Value : 0.479500        
##                                           
##             Sensitivity : 0.9440          
##             Specificity : 0.6333          
##          Pos Pred Value : 0.9147          
##          Neg Pred Value : 0.7308          
##              Prevalence : 0.8065          
##          Detection Rate : 0.7613          
##    Detection Prevalence : 0.8323          
##       Balanced Accuracy : 0.7887          
##                                           
##        'Positive' Class : Baja            
## 

Conclusión

Considerando que el objetivo es identificar los factores que hacen que los empleados se den de baja en FORM, el modelo de Árbol de Decisión es un buen modelo. La sensibilidad del 0.9440 indica que el modelo tiene una capacidad alta para identificar correctamente a los empleados que se dan de baja. Esto es crucial ya que el objetivo es entender por qué los empleados se van de la empresa.

Aunque la especificidad es algo baja (0.6333), lo que indica que el modelo tiene dificultades para identificar correctamente a los empleados que permanecen en la empresa, esto no afecta significativamente, ya que, el objetivo principal es detectar los factores de baja.

Además, el modelo cuenta con una buena precisión (0.8839), lo que indica que cuando predice que un empleado se da de baja, en el 88.39% de los casos, esta predicción es correcta. Esto sugiere que las decisiones tomadas basadas en estas predicciones serán, en su mayoría, acertadas.

Selección de modelo RRHH

Decidimos que para el caso de RRHH el modelo de Árbol de Decisión pueda ser el más apropiado para nuestro cliente. Principalmente porque tiene una gran capacidad de capturar interacciones. Los Árboles de Decisión pueden capturar interacciones complejas entre variables. En el contexto de la rotación de empleados, es probable que factores como la antigüedad y el puesto interactúen de maneras no obvias que el modelo puede detectar. Tembién queremos que los modelos tengan una mayor interpretabilidad visual. Los Árboles de Decisión son fácilmente interpretables y visualizables. Esto permite a los responsables de recursos humanos entender claramente qué factores están contribuyendo a la rotación y cómo.

CHATBOT

Este es un ejemplo de lo que el equipo ha logrado implementar con el ChatBot. Esperamos que este bot pueda ayudar a los prospectos a tener información de inmediato y que pueda agilizar el proceso de prospección y selección de candidatos.

LS0tDQp0aXRsZTogIkV2aWRlbmNpYSAyIg0KYXV0aG9yOiAiRXF1aXBvIDYiDQpkYXRlOiAiMjAyNC0wNS0yMyINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiANCiAgICAgIHZlcnNpb246IDQNCiAgICAgIGJvb3Rzd2F0Y2g6IGZsYXRseQ0KICAgICAgcHJpbWFyeTogIiNmZjdmMGUiICMgT3JhbmdlIGNvbG9yDQogICAgICBiZzogIiNmZmZmZmYiDQogICAgICBmZzogIiMwMDAwMDAiDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmcgPSBGQUxTRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpDQoNCg0KYGBgDQoNCiFbXShDOlxcVXNlcnNcXGthdGhpXFxPbmVEcml2ZVxcRXNjcml0b3Jpb1xcRVZJREVOQ0lBMl9JQVxccG9ydGFkYS5wbmcpICANCg0KRXN0ZSBpbmZvcm1lIHByZXNlbnRhIHVuIGFuw6FsaXNpcyBleGhhdXN0aXZvIGRlIGxhcyB2ZW50YXMgZGUgY2FydMOzbiB5IHJldG9ybmFibGVzIG1lZGlhbnRlIHTDqWNuaWNhcyBhdmFuemFkYXMgZGUgbWFjaGluZSBsZWFybmluZywgaW5jbHV5ZW5kbyBSZWRlcyBOZXVyb25hbGVzIFJlY3VycmVudGVzIChSTk4pIHkgWEdCb29zdCwgYXPDrSBjb21vIHVuIG1vZGVsbyBkZSBSYW5kb20gRm9yZXN0IHBhcmEgZXZhbHVhciBsYSBkaXNpbWlsYXJpZGFkIGVudHJlIHNlcmllcyB0ZW1wb3JhbGVzLiBBZGVtw6FzLCBzZSBhbmFsaXphIGxhIHJvdGFjacOzbiBkZSBlbXBsZWFkb3MgdXRpbGl6YW5kbyBtb2RlbG9zIGRlIE5haXZlIEJheWVzIHkgw4FyYm9sZXMgZGUgRGVjaXNpw7NuIHBhcmEgaWRlbnRpZmljYXIgbG9zIGZhY3RvcmVzIHF1ZSBpbmZsdXllbiBlbiBsYSBhbHRhIHJvdGFjacOzbiBkZSBwZXJzb25hbCBlbiBsYSBlbXByZXNhIEZPUk0uIEEgdHJhdsOpcyBkZSBlc3RlIGVzdHVkaW8sIHNlIGJ1c2NhIHByb3BvcmNpb25hciB1bmEgYmFzZSBzw7NsaWRhIHBhcmEgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGVzdHJhdMOpZ2ljYXMgZW4gbGEgZ2VzdGnDs24gZGUgaW52ZW50YXJpb3MgeSByZWN1cnNvcyBodW1hbm9zLCBkZXN0YWNhbmRvIGxhIGltcG9ydGFuY2lhIGRlIHTDqWNuaWNhcyBwcmVkaWN0aXZhcyBlbiBsYSBtZWpvcmEgZGUgbGEgcGxhbmlmaWNhY2nDs24geSBlZmljaWVuY2lhIG9wZXJhdGl2YS4NCg0KDQojIFZlbnRhcw0KDQohW10oQzpcXFVzZXJzXFxrYXRoaVxcT25lRHJpdmVcXEVzY3JpdG9yaW9cXEVWSURFTkNJQTJfSUFcXHZlbnRhcy5wbmcpDQoNCiMjIENhcnTDs24NCg0KIyMjIFJlZCBOZXVyb25hbCBSZWN1cnJlbnRlDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzDQpsaWJyYXJ5KFRTY2x1c3QpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGd0KQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KERhdGFFeHBsb3JlcikNCmxpYnJhcnkoem9vKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShncmlkKQ0KbGlicmFyeShkdHdjbHVzdCkNCmxpYnJhcnkoUlNOTlMpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShSU05OUykNCm9wdGlvbnMoc2NpcGVuID0gOTk5OSkNCg0KIyBMb2FkIGRhdGENCnZlbnRhcyA8LSByZWFkeGw6OnJlYWRfZXhjZWwoIlZlbnRhcyBlMi54bHN4IikNCg0KdmVudGFzIDwtIHZlbnRhcyAlPiUNCiAgbXV0YXRlKEZlY2hhID0gYXMuRGF0ZShGZWNoYSwgZm9ybWF0ID0gIiVZLSVtLSVkIikpDQoNCnZlbnRhc19jYXJ0b24gPC0gdmVudGFzICU+JQ0KICBzZWxlY3QoRmVjaGEsIENhcnRvbikgJT4lDQogIGZpbHRlcighaXMubmEoQ2FydG9uKSkNCg0KIyBGaWxsIG1pc3NpbmcgZGF0YQ0KbWlzc2luZ19kYXRhIDwtIGRhdGEuZnJhbWUoDQogIEZlY2hhID0gYXMuRGF0ZShjKCIyMDIyLTEwLTAxIiwgIjIwMjItMTEtMDEiLCAiMjAyMi0xMi0wMSIpKSwNCiAgQ2FydG9uID0gYyg3Nzc2NzcxLCA2Mjk1MTcyLCA4ODczMjk2KSAgIyBSZXBsYWNlIE5BIHdpdGggYWN0dWFsIG9yIGFwcHJveGltYXRlIHZhbHVlcw0KKQ0KDQp2ZW50YXNfY2FydG9uIDwtIGJpbmRfcm93cyh2ZW50YXNfY2FydG9uLCBtaXNzaW5nX2RhdGEpICU+JQ0KICBhcnJhbmdlKEZlY2hhKQ0KDQpjYXJ0b25fdHMgPC0gdHModmVudGFzX2NhcnRvbiRDYXJ0b24sIHN0YXJ0ID0gYygyMDIxLCAxKSwgZnJlcXVlbmN5ID0gMTIpDQoNCiMgUGxvdCBkYXRhDQpwbG90KGNhcnRvbl90cywgdHlwZT0ibCIsIGNvbD0iYmx1ZSIsIGx3ZD0yLCB4bGFiPSJGZWNoYSIsIHlsYWI9IlZlbnRhIFRvdGFsIGRlIENhcnRvbiIsIG1haW49IlZlbnRhcyBkZSBDYXJ0b24iKQ0KDQoNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KbGlicmFyeSh6b28pDQoNCnZlbnRhc19jYXJ0b24gPC0gdmVudGFzX2NhcnRvbiAlPiUNCiAgbXV0YXRlKE1vdmluZ0F2ZyA9IHJvbGxtZWFuKENhcnRvbiwgMywgZmlsbCA9IE5BLCBhbGlnbiA9ICJyaWdodCIpKQ0KDQp2ZW50YXNfY2FydG9uX2ZpbHRlcmVkIDwtIHZlbnRhc19jYXJ0b24gJT4lDQogIGZpbHRlcighaXMubmEoTW92aW5nQXZnKSkNCg0KZ2dwbG90KHZlbnRhc19jYXJ0b25fZmlsdGVyZWQsIGFlcyh4ID0gRmVjaGEpKSArDQogIGdlb21fbGluZShhZXMoeSA9IENhcnRvbiksIGNvbG9yID0gImJsdWUiLCBsaW5ld2lkdGggPSAxKSArDQogIGdlb21fbGluZShhZXMoeSA9IE1vdmluZ0F2ZyksIGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJWZW50YXMgZGUgQ2FydG9uIGNvbiBNZWRpYSBNb3ZpbCIsIA0KICAgICAgIHggPSAiRmVjaGEiLCANCiAgICAgICB5ID0gIlZlbnRhIFRvdGFsIGRlIENhcnTDs24iKSArDQogIHRoZW1lX2NsYXNzaWMoKQ0KDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgTm9ybWFsaXplIGRhdGENCm5vcm1hbGl6ZSA8LSBmdW5jdGlvbih4KSB7DQogIHJldHVybiAoKHggLSBtaW4oeCkpIC8gKG1heCh4KSAtIG1pbih4KSkpDQp9DQoNCnZlbnRhc19jYXJ0b24kQ2FydG9uIDwtIG5vcm1hbGl6ZSh2ZW50YXNfY2FydG9uJENhcnRvbikNCg0KIyBQcmVwYXJlIGRhdGEgZm9yIFJOTg0KZGYgPC0gdmVudGFzX2NhcnRvbiAlPiUNCiAgbXV0YXRlKE1vbnRoID0gYXMubnVtZXJpYyhmb3JtYXQoRmVjaGEsICIlbSIpKSwNCiAgICAgICAgIFllYXIgPSBhcy5udW1lcmljKGZvcm1hdChGZWNoYSwgIiVZIikpKSAlPiUNCiAgYXJyYW5nZShGZWNoYSkNCg0KIyBFbnN1cmUgdGhlICdDYXJ0b24nIGNvbHVtbiBpcyBudW1lcmljDQpkZiRDYXJ0b24gPC0gYXMubnVtZXJpYyhkZiRDYXJ0b24pDQoNCiMgQ3JlYXRlIHNlcXVlbmNlcyBmb3IgUk5ODQpjcmVhdGVfc2VxdWVuY2VzIDwtIGZ1bmN0aW9uKGRhdGEsIHNlcV9sZW5ndGgpIHsNCiAgWCA8LSBtYXRyaXgobnJvdyA9IDAsIG5jb2wgPSBzZXFfbGVuZ3RoKQ0KICB5IDwtIG51bWVyaWMoKQ0KICBmb3IgKGkgaW4gMToobnJvdyhkYXRhKSAtIHNlcV9sZW5ndGgpKSB7DQogICAgWCA8LSByYmluZChYLCBhcy5udW1lcmljKGRhdGEkQ2FydG9uW2k6KGkgKyBzZXFfbGVuZ3RoIC0gMSldKSkNCiAgICB5IDwtIGMoeSwgYXMubnVtZXJpYyhkYXRhJENhcnRvbltpICsgc2VxX2xlbmd0aF0pKQ0KICB9DQogIGxpc3QoWCA9IFgsIHkgPSB5KQ0KfQ0KDQpzZXFfbGVuZ3RoIDwtIDEyDQpzZXF1ZW5jZXMgPC0gY3JlYXRlX3NlcXVlbmNlcyhkZiwgc2VxX2xlbmd0aCkNCg0KIyBDb252ZXJ0IHRvIFJTTk5TIGZvcm1hdA0KaW5wdXRzIDwtIGFzLmRhdGEuZnJhbWUoc2VxdWVuY2VzJFgpDQp0YXJnZXRzIDwtIGFzLmRhdGEuZnJhbWUoc2VxdWVuY2VzJHkpDQoNCiMgU3BsaXQgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMNCnNldC5zZWVkKDEyMykNCnRyYWluX2luZGljZXMgPC0gc2FtcGxlKDE6bnJvdyhpbnB1dHMpLCAwLjggKiBucm93KGlucHV0cykpDQppbnB1dHNfdHJhaW4gPC0gaW5wdXRzW3RyYWluX2luZGljZXMsIF0NCnRhcmdldHNfdHJhaW4gPC0gdGFyZ2V0c1t0cmFpbl9pbmRpY2VzLCBdDQppbnB1dHNfdGVzdCA8LSBpbnB1dHNbLXRyYWluX2luZGljZXMsIF0NCnRhcmdldHNfdGVzdCA8LSB0YXJnZXRzWy10cmFpbl9pbmRpY2VzLCBdDQoNCiMgVHJhaW4gdGhlIFJOTiBtb2RlbCB3aXRoIGluY3JlYXNlZCBjb21wbGV4aXR5DQptb2RlbCA8LSBlbG1hbihpbnB1dHNfdHJhaW4sIHRhcmdldHNfdHJhaW4sIHNpemUgPSBjKDIwLCAxMCksIGxlYXJuRnVuY1BhcmFtcyA9IGMoMC4wMSksIG1heGl0ID0gNTAwMCkNCg0KIyBNYWtlIHByZWRpY3Rpb25zDQpwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KG1vZGVsLCBpbnB1dHNfdGVzdCkNCg0KIyBEZW5vcm1hbGl6ZSB0aGUgZGF0YQ0KZGVub3JtYWxpemUgPC0gZnVuY3Rpb24oeCwgb3JpZ2luYWwpIHsNCiAgcmV0dXJuICh4ICogKG1heChvcmlnaW5hbCkgLSBtaW4ob3JpZ2luYWwpKSArIG1pbihvcmlnaW5hbCkpDQp9DQoNCmFjdHVhbCA8LSBkZW5vcm1hbGl6ZShhcy52ZWN0b3IodGFyZ2V0c190ZXN0KSwgY2FydG9uX3RzKQ0KcHJlZGljdGVkIDwtIGRlbm9ybWFsaXplKGFzLnZlY3RvcihwcmVkaWN0aW9ucyksIGNhcnRvbl90cykNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KIyBQbG90IGFjdHVhbCB2cyBwcmVkaWN0ZWQgdmFsdWVzDQpwbG90KGFjdHVhbCwgdHlwZSA9ICdsJywgY29sID0gJ2JsdWUnLCBtYWluID0gIkFjdHVhbCB2cyBQcmVkaWN0ZWQiLCB5bGFiID0gIlZhbHVlIiwgeGxhYiA9ICJUaW1lIiwgeWxpbSA9IGMobWluKGFjdHVhbCwgcHJlZGljdGVkKSwgbWF4KGFjdHVhbCwgcHJlZGljdGVkKSkpDQpsaW5lcyhwcmVkaWN0ZWQsIGNvbCA9ICdyZWQnKQ0KbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IGMoIkFjdHVhbCIsICJQcmVkaWN0ZWQiKSwgY29sID0gYygiYmx1ZSIsICJyZWQiKSwgbHR5ID0gMSkNCg0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0V9DQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcw0KbGlicmFyeShNZXRyaWNzKQ0KDQojIENhbGN1bGF0ZSBldmFsdWF0aW9uIG1ldHJpY3MNCm1hZV92YWx1ZSA8LSBtYWUoYWN0dWFsLCBwcmVkaWN0ZWQpDQptc2VfdmFsdWUgPC0gbXNlKGFjdHVhbCwgcHJlZGljdGVkKQ0Kcm1zZV92YWx1ZSA8LSBybXNlKGFjdHVhbCwgcHJlZGljdGVkKQ0KcjJfdmFsdWUgPC0gMSAtIChzdW0oKGFjdHVhbCAtIHByZWRpY3RlZCleMikgLyBzdW0oKGFjdHVhbCAtIG1lYW4oYWN0dWFsKSleMikpDQoNCiMgUHJpbnQgbWV0cmljcw0KY2F0KCJNZWFuIEFic29sdXRlIEVycm9yIChNQUUpOiIsIG1hZV92YWx1ZSwgIlxuIikNCmNhdCgiTWVhbiBTcXVhcmVkIEVycm9yIChNU0UpOiIsIG1zZV92YWx1ZSwgIlxuIikNCmNhdCgiUm9vdCBNZWFuIFNxdWFyZWQgRXJyb3IgKFJNU0UpOiIsIHJtc2VfdmFsdWUsICJcbiIpDQpjYXQoIlItc3F1YXJlZCAoUsKyKToiLCByMl92YWx1ZSwgIlxuIikNCmBgYA0KDQpMYXMgdmVudGFzIGRlIGNhcnTDs24gZnVlcm9uIGFuYWxpemFkYXMgdXRpbGl6YW5kbyB1bmEgUmVkIE5ldXJvbmFsIFJlY3VycmVudGUgKFJOTikgcGFyYSBwcmVkZWNpciBmdXR1cmFzIHZlbnRhcy4gRWwgcHJvY2VzbyB5IGxvcyByZXN1bHRhZG9zIHNlIGRlc2NyaWJlbiBhIGNvbnRpbnVhY2nDs246DQoNClByZXBhcmFjacOzbiBkZSBsb3MgRGF0b3MNCk5vcm1hbGl6YWNpw7NuIGRlIERhdG9zOiBMb3MgZGF0b3MgZGUgdmVudGFzIHNlIG5vcm1hbGl6YXJvbiBwYXJhIHF1ZSBsb3MgdmFsb3JlcyBlc3TDqW4gZW4gdW4gcmFuZ28gZW50cmUgMCB5IDEsIGZhY2lsaXRhbmRvIGVsIGVudHJlbmFtaWVudG8gZGUgbGEgUk5OLg0KDQpDcmVhY2nDs24gZGUgU2VjdWVuY2lhczogU2UgY3JlYXJvbiBzZWN1ZW5jaWFzIGRlIGxvbmdpdHVkIDEyICh1biBhw7FvKSBwYXJhIGVudHJlbmFyIGxhIFJOTi4gQ2FkYSBzZWN1ZW5jaWEgY29uc2lzdGUgZW4gMTIgbWVzZXMgY29uc2VjdXRpdm9zIGRlIGRhdG9zIGRlIHZlbnRhcywgeSBlbCBvYmpldGl2byBlcyBwcmVkZWNpciBlbCB2YWxvciBkZWwgbWVzIHNpZ3VpZW50ZS4NCg0KRGl2aXNpw7NuIGRlIERhdG9zOiBMb3MgZGF0b3Mgc2UgZGl2aWRpZXJvbiBlbiBjb25qdW50b3MgZGUgZW50cmVuYW1pZW50byB5IHBydWViYSwgdXRpbGl6YW5kbyBlbCA4MCUgcGFyYSBlbnRyZW5hbWllbnRvIHkgZWwgMjAlIHBhcmEgcHJ1ZWJhLg0KDQpFbnRyZW5hbWllbnRvIGRlbCBNb2RlbG8NClNlIGVudHJlbsOzIHVuIG1vZGVsbyBkZSBSTk4gRWxtYW4gY29uIGRvcyBjYXBhcyBvY3VsdGFzIGRlIHRhbWHDsW8gMjAgeSAxMCBuZXVyb25hcywgcmVzcGVjdGl2YW1lbnRlLiBFbCBtb2RlbG8gc2UgZW50cmVuw7MgZHVyYW50ZSA1MDAwIGl0ZXJhY2lvbmVzIGNvbiB1bmEgdGFzYSBkZSBhcHJlbmRpemFqZSBkZSAwLjAxLg0KDQoqKkNvbmNsdXNpb25lcyoqDQoqIExhcyB2ZW50YXMgZGUgY2FydMOzbiBwdWVkZW4gc2VyIHByZWRlY2lkYXMgZGUgbWFuZXJhIGVmZWN0aXZhIHV0aWxpemFuZG8gdW5hIFJOTiwgbG8gY3VhbCBlcyDDunRpbCBwYXJhIGxhIHBsYW5pZmljYWNpw7NuIHkgZ2VzdGnDs24gZGUgaW52ZW50YXJpb3MuICANCg0KKiBMYSBub3JtYWxpemFjacOzbiBkZSBsb3MgZGF0b3MgeSBsYSBjcmVhY2nDs24gZGUgc2VjdWVuY2lhcyB0ZW1wb3JhbGVzIHNvbiBwYXNvcyBjcnVjaWFsZXMgcGFyYSBlbCBlbnRyZW5hbWllbnRvIGV4aXRvc28gZGUgbGEgUk5OLiAgDQoNCiogRWwgbW9kZWxvIFJOTiBtb3N0csOzIHVuYSBhbHRhIHByZWNpc2nDs24gZW4gc3VzIHByZWRpY2Npb25lcywgbG8gcXVlIHN1Z2llcmUgc3UgcG90ZW5jaWFsIHBhcmEgc2VyIGltcGxlbWVudGFkbyBlbiBzaXN0ZW1hcyBkZSBwcm9uw7NzdGljbyBkZSB2ZW50YXMuICANCg0KDQojIyMgWEdCb29zdA0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkoeGdib29zdCkNCm9wdGlvbnMoc2NpcGVuID0gOTk5OSkNCg0KIyBMb2FkIGRhdGENCnZlbnRhcyA8LSByZWFkeGw6OnJlYWRfZXhjZWwoIlZlbnRhcyBlMi54bHN4IikNCg0KdmVudGFzIDwtIHZlbnRhcyAlPiUNCiAgbXV0YXRlKEZlY2hhID0gYXMuRGF0ZShGZWNoYSwgZm9ybWF0ID0gIiVZLSVtLSVkIikpDQoNCnZlbnRhc19jYXJ0b24gPC0gdmVudGFzICU+JQ0KICBzZWxlY3QoRmVjaGEsIENhcnRvbikgJT4lDQogIGZpbHRlcighaXMubmEoQ2FydG9uKSkNCg0KIyBGaWxsIG1pc3NpbmcgZGF0YQ0KbWlzc2luZ19kYXRhIDwtIGRhdGEuZnJhbWUoDQogIEZlY2hhID0gYXMuRGF0ZShjKCIyMDIyLTEwLTAxIiwgIjIwMjItMTEtMDEiLCAiMjAyMi0xMi0wMSIpKSwNCiAgQ2FydG9uID0gYyg2Mjk1MTcyLCA3Nzc2NzcxLCA4ODczMjk2KSAgIyBSZXBsYWNlIE5BIHdpdGggYWN0dWFsIG9yIGFwcHJveGltYXRlIHZhbHVlcw0KKQ0KDQp2ZW50YXNfY2FydG9uIDwtIGJpbmRfcm93cyh2ZW50YXNfY2FydG9uLCBtaXNzaW5nX2RhdGEpICU+JQ0KICBhcnJhbmdlKEZlY2hhKQ0KDQojIENyZWF0ZSBsYWdnZWQgZmVhdHVyZXMNCnZlbnRhc19jYXJ0b24gPC0gdmVudGFzX2NhcnRvbiAlPiUNCiAgbXV0YXRlKA0KICAgIExhZzEgPSBsYWcoQ2FydG9uLCAxKSwNCiAgICBMYWcyID0gbGFnKENhcnRvbiwgMiksDQogICAgTGFnMyA9IGxhZyhDYXJ0b24sIDMpLA0KICAgIExhZzQgPSBsYWcoQ2FydG9uLCA0KSwNCiAgICBMYWc1ID0gbGFnKENhcnRvbiwgNSksDQogICAgTGFnNiA9IGxhZyhDYXJ0b24sIDYpLA0KICAgIExhZzcgPSBsYWcoQ2FydG9uLCA3KSwNCiAgICBMYWc4ID0gbGFnKENhcnRvbiwgOCksDQogICAgTGFnOSA9IGxhZyhDYXJ0b24sIDkpLA0KICAgIExhZzEwID0gbGFnKENhcnRvbiwgMTApLA0KICAgIExhZzExID0gbGFnKENhcnRvbiwgMTEpLA0KICAgIExhZzEyID0gbGFnKENhcnRvbiwgMTIpDQogICkgJT4lDQogIGRyb3BfbmEoKQ0KDQojIFNwbGl0IGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzDQpzZXQuc2VlZCgxMjMpDQp0cmFpbl9pbmRpY2VzIDwtIHNhbXBsZSgxOm5yb3codmVudGFzX2NhcnRvbiksIDAuOCAqIG5yb3codmVudGFzX2NhcnRvbikpDQp0cmFpbl9kYXRhIDwtIHZlbnRhc19jYXJ0b25bdHJhaW5faW5kaWNlcywgXQ0KdGVzdF9kYXRhIDwtIHZlbnRhc19jYXJ0b25bLXRyYWluX2luZGljZXMsIF0NCg0KIyBEZWZpbmUgY29udHJvbCBmdW5jdGlvbiBmb3IgY3Jvc3MtdmFsaWRhdGlvbg0KY29udHJvbCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IiwgbnVtYmVyID0gMTApDQoNCiMgRGVmaW5lIGdyaWQgZm9yIGh5cGVycGFyYW1ldGVyIHR1bmluZw0KdHVuZWdyaWQgPC0gZXhwYW5kLmdyaWQoDQogIG5yb3VuZHMgPSBjKDEwMCwgMjAwKSwgICMgTnVtYmVyIG9mIGJvb3N0aW5nIGl0ZXJhdGlvbnMNCiAgbWF4X2RlcHRoID0gYygzLCA2LCA5KSwNCiAgZXRhID0gYygwLjAxLCAwLjEsIDAuMyksDQogIGdhbW1hID0gYygwLCAwLjEpLA0KICBjb2xzYW1wbGVfYnl0cmVlID0gYygwLjYsIDAuOCwgMS4wKSwNCiAgbWluX2NoaWxkX3dlaWdodCA9IGMoMSwgMyksDQogIHN1YnNhbXBsZSA9IGMoMC42LCAwLjgsIDEuMCkNCikNCg0KIyBUcmFpbiB0aGUgWEdCb29zdCBtb2RlbCB3aXRoIGNyb3NzLXZhbGlkYXRpb24NCnhnYl9tb2RlbCA8LSB0cmFpbigNCiAgQ2FydG9uIH4gLiwgZGF0YSA9IHRyYWluX2RhdGEsIG1ldGhvZCA9ICJ4Z2JUcmVlIiwgDQogIHRyQ29udHJvbCA9IGNvbnRyb2wsIHR1bmVHcmlkID0gdHVuZWdyaWQsIHZlcmJvc2UgPSBGQUxTRQ0KKQ0KDQojIFByaW50IGJlc3QgbW9kZWwNCnByaW50KHhnYl9tb2RlbCRiZXN0VHVuZSkNCg0KIyBNYWtlIHByZWRpY3Rpb25zDQpwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KHhnYl9tb2RlbCwgdGVzdF9kYXRhKQ0KDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCnBsb3QoYWN0dWFsLCB0eXBlID0gJ2wnLCBjb2wgPSAnYmx1ZScsIG1haW4gPSAiQWN0dWFsIHZzIFByZWRpY3RlZCIsIHlsYWIgPSAiVmFsdWUiLCB4bGFiID0gIlRpbWUiKQ0KbGluZXMocHJlZGljdGlvbnMsIGNvbCA9ICdyZWQnKQ0KbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IGMoIkFjdHVhbCIsICJQcmVkaWN0ZWQiKSwgY29sID0gYygiYmx1ZSIsICJyZWQiKSwgbHR5ID0gMSkNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KYWN0dWFsIDwtIHRlc3RfZGF0YSRDYXJ0b24NCm1hZV92YWx1ZSA8LSBtYWUoYWN0dWFsLCBwcmVkaWN0aW9ucykNCm1zZV92YWx1ZSA8LSBtc2UoYWN0dWFsLCBwcmVkaWN0aW9ucykNCnJtc2VfdmFsdWUgPC0gcm1zZShhY3R1YWwsIHByZWRpY3Rpb25zKQ0KcjJfdmFsdWUgPC0gMSAtIChzdW0oKGFjdHVhbCAtIHByZWRpY3Rpb25zKV4yKSAvIHN1bSgoYWN0dWFsIC0gbWVhbihhY3R1YWwpKV4yKSkNCg0KY2F0KCJNZWFuIEFic29sdXRlIEVycm9yIChNQUUpOiIsIG1hZV92YWx1ZSwgIlxuIikNCmNhdCgiTWVhbiBTcXVhcmVkIEVycm9yIChNU0UpOiIsIG1zZV92YWx1ZSwgIlxuIikNCmNhdCgiUm9vdCBNZWFuIFNxdWFyZWQgRXJyb3IgKFJNU0UpOiIsIHJtc2VfdmFsdWUsICJcbiIpDQpjYXQoIlItc3F1YXJlZCAoUsKyKToiLCByMl92YWx1ZSwgIlxuIikNCmBgYA0KDQpMYXMgdmVudGFzIGRlIGNhcnTDs24gbXVlc3RyYW4gZGl2ZXJzYXMgdGVuZGVuY2lhcyBlbiBmdW5jacOzbiBkZWwgdGllbXBvIHkgZGUgY2llcnRhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMuIEEgY29udGludWFjacOzbiwgc2UgZGVzY3JpYmUgdW4gYW7DoWxpc2lzIGJhc2FkbyBlbiB1biBtb2RlbG8gZGUgWEdCb29zdC4NCg0KTG9zIGRhdG9zIGRlIHZlbnRhcyBkZSBjYXJ0w7NuIGZ1ZXJvbiBjYXJnYWRvcyB5IHByb2Nlc2Fkb3MgcGFyYSBjcmVhciB1biBjb25qdW50byBkZSBjYXJhY3RlcsOtc3RpY2FzIHJldGFyZGFkYXMgcXVlIHBlcm1pdGVuIGNhcHR1cmFyIGxhcyB0ZW5kZW5jaWFzIHRlbXBvcmFsZXMuIEVzdGFzIGNhcmFjdGVyw61zdGljYXMgaW5jbHV5ZW4gZGF0b3MgZGUgdmVudGFzIGRlIHVubyBhIGRvY2UgbWVzZXMgYW50ZXJpb3Jlcy4NCg0KUGFyYSBlbnRyZW5hciB5IGV2YWx1YXIgZWwgbW9kZWxvIGRlIFhHQm9vc3QsIHNlIGRpdmlkaWVyb24gbG9zIGRhdG9zIGVuIGNvbmp1bnRvcyBkZSBlbnRyZW5hbWllbnRvIHkgcHJ1ZWJhLCB1dGlsaXphbmRvIGVsIDgwJSBkZSBsb3MgZGF0b3MgcGFyYSBlbnRyZW5hciBlbCBtb2RlbG8geSBlbCAyMCUgcGFyYSBldmFsdWFyIHN1IHJlbmRpbWllbnRvLg0KDQpFbCBtb2RlbG8gc2UgYWp1c3TDsyB1dGlsaXphbmRvIHZhbGlkYWNpw7NuIGNydXphZGEgY29uIHVuYSBzZXJpZSBkZSBoaXBlcnBhcsOhbWV0cm9zLCBpbmNsdXllbmRvIGVsIG7Dum1lcm8gZGUgaXRlcmFjaW9uZXMgZGUgcmVmdWVyem8sIGxhIHByb2Z1bmRpZGFkIG3DoXhpbWEgZGUgbG9zIMOhcmJvbGVzLCBsYSB0YXNhIGRlIGFwcmVuZGl6YWplIChldGEpLCBlbCBwYXLDoW1ldHJvIGdhbW1hLCBsYSBwcm9wb3JjacOzbiBkZSBtdWVzdHJhcyBkZSDDoXJib2xlcyB5IGVsIHBlc28gbcOtbmltbyBkZSBsYXMgaG9qYXMuDQoNCg0KIyMjIFJhbmRvbSBGb3Jlc3QNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIENhcmdhciBsYXMgYmlibGlvdGVjYXMgbmVjZXNhcmlhcw0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQoNCiMgTGVlciBsb3MgZGF0b3MNCnZlbnRhcyA8LSByZWFkX3hsc3goIlZlbnRhcyBlMi54bHN4IikNCg0KIyBDb252ZXJ0aXIgZmVjaGFzIHkgbGltcGlhciBjb2x1bW5hIENhcnRvbg0KdmVudGFzIDwtIHZlbnRhcyAlPiUNCiAgbXV0YXRlKA0KICAgIEZlY2hhID0gYXMuRGF0ZShGZWNoYSwgZm9ybWF0ID0gIiVkLyVtLyVZIiksICAjIEFzZWfDunJhdGUgZGUgcXVlIGVsIGZvcm1hdG8gZGUgZmVjaGEgY29pbmNpZGUgY29uIHR1cyBkYXRvcw0KICAgIENhcnRvbiA9IGFzLm51bWVyaWMoZ3N1YigiW14wLTkuXSIsICIiLCBDYXJ0b24pKSAgIyBFbGltaW5hIHRvZG8gbG8gcXVlIG5vIHNlYSBuw7ptZXJvcyBvIHB1bnRvcw0KICApDQoNCiMgRmlsdHJhciBwYXJhIGVsaW1pbmFyIE5BIGVuIENhcnRvbiBzaSBhw7puIGV4aXN0ZW4NCnZlbnRhc19jYXJ0b24gPC0gdmVudGFzICU+JQ0KICBzZWxlY3QoRmVjaGEsIENhcnRvbikgJT4lDQogIGZpbHRlcighaXMubmEoQ2FydG9uKSkNCg0KIyBEYXRvcyBwYXJhIGxsZW5hciB2YWxvcmVzIGZhbHRhbnRlcw0KbWlzc2luZ19kYXRhIDwtIGRhdGEuZnJhbWUoDQogIEZlY2hhID0gYXMuRGF0ZShjKCIyMDIyLTEwLTAxIiwgIjIwMjItMTEtMDEiLCAiMjAyMi0xMi0wMSIpKSwNCiAgQ2FydG9uID0gYyg3Nzc2NzcxLCA2Mjk1MTcyLCA4ODczMjk2KSAgIyBWYWxvcmVzIG51bcOpcmljb3MNCikNCg0KIyBDb21iaW5hciBsb3MgZGF0b3MgY29ycmlnaWVuZG8gZWwgdGlwbyBkZSBkYXRvcw0KdmVudGFzX2NhcnRvbiA8LSBiaW5kX3Jvd3ModmVudGFzX2NhcnRvbiwgbWlzc2luZ19kYXRhKSAlPiUNCiAgYXJyYW5nZShGZWNoYSkNCg0KIyBWZXJpZmljYXIgbG9zIGRhdG9zDQpwcmludCh2ZW50YXNfY2FydG9uKQ0KDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCiMgSW5zdGFsYXIgeSBjYXJnYXIgbGEgYmlibGlvdGVjYSByYW5kb21Gb3Jlc3Qgc2kgYcO6biBubyBlc3TDoSBjYXJnYWRhDQppZiAoIXJlcXVpcmUoInJhbmRvbUZvcmVzdCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInJhbmRvbUZvcmVzdCIpDQogIGxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KfQ0KDQojIFN1cG9uaWVuZG8gcXVlIHRpZW5lcyBvdHJhcyBjb2x1bW5hcyBxdWUgcHVlZGFzIHVzYXIgY29tbyBwcmVkaWN0b3JlcywgYXF1w60gdXNvIHPDs2xvIGxhIGZlY2hhDQojIENvbnZlcnRpciBsYSBmZWNoYSBlbiB1biBwcmVkaWN0b3IgbnVtw6lyaWNvIChjb21vIGVsIG7Dum1lcm8gZGUgZMOtYXMgZGVzZGUgdW5hIGZlY2hhIGJhc2UpDQp2ZW50YXNfY2FydG9uJEZlY2hhTnVtID0gYXMubnVtZXJpYyh2ZW50YXNfY2FydG9uJEZlY2hhIC0gbWluKHZlbnRhc19jYXJ0b24kRmVjaGEpKQ0KDQojIEFqdXN0YXIgZWwgbW9kZWxvIGRlIFJhbmRvbSBGb3Jlc3QNCnJmX21vZGVsIDwtIHJhbmRvbUZvcmVzdChDYXJ0b24gfiBGZWNoYU51bSwgZGF0YSA9IHZlbnRhc19jYXJ0b24sIG50cmVlPTUwMCkNCg0KIyBNb3N0cmFyIGVsIHJlc3VtZW4gZGVsIG1vZGVsbw0KcHJpbnQocmZfbW9kZWwpDQoNCiMgSW1wb3J0YW5jaWEgZGUgbGFzIHZhcmlhYmxlcw0KaW1wb3J0YW5jZShyZl9tb2RlbCkNCg0KIyBIYWNlciBwcmVkaWNjaW9uZXMgKG9wY2lvbmFsKQ0KcHJlZGljdGlvbnMgPC0gcHJlZGljdChyZl9tb2RlbCwgdmVudGFzX2NhcnRvbikNCg0KIyBHcmFmaWNhciB2YWxvcmVzIHJlYWxlcyB2cy4gcHJlZGljY2lvbmVzIChvcGNpb25hbCkNCnBsb3QodmVudGFzX2NhcnRvbiRGZWNoYSwgdmVudGFzX2NhcnRvbiRDYXJ0b24sIHR5cGUgPSAnbCcsIGNvbCA9ICdibHVlJywgeGxhYiA9ICJGZWNoYSIsIHlsYWIgPSAiQ2FydG9uIiwgbWFpbiA9ICJSZWFsIHZzIFByZWRpY2Npw7NuIikNCmxpbmVzKHZlbnRhc19jYXJ0b24kRmVjaGEsIHByZWRpY3Rpb25zLCBjb2wgPSAncmVkJykNCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCJSZWFsIiwgIlByZWRpY2Npw7NuIiksIGNvbCA9IGMoImJsdWUiLCAicmVkIiksIGx0eSA9IDEpDQoNCmBgYA0KDQojIyBSZXRvcm5hYmxlcw0KDQojIyMgUmVkIE5ldXJvbmFsIFJlY3VycmVudGUNCmBgYHtyIGVjaG89RkFMU0V9DQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcw0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoUlNOTlMpDQpvcHRpb25zKHNjaXBlbiA9IDk5OTkpDQoNCiMgTG9hZCBkYXRhDQp2ZW50YXMgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCJWZW50YXMgZTIueGxzeCIpDQoNCnZlbnRhcyA8LSB2ZW50YXMgJT4lDQogIG11dGF0ZShGZWNoYSA9IGFzLkRhdGUoRmVjaGEsIGZvcm1hdCA9ICIlWS0lbS0lZCIpKQ0KDQp2ZW50YXNfcmV0b3JuYWJsZSA8LSB2ZW50YXMgJT4lDQogIHNlbGVjdChGZWNoYSwgUmV0b3JuYWJsZSkgJT4lDQogIGZpbHRlcighaXMubmEoUmV0b3JuYWJsZSkpDQoNCiMgRmlsbCBtaXNzaW5nIGRhdGENCm1pc3NpbmdfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBGZWNoYSA9IGFzLkRhdGUoYygiMjAyMi0xMC0wMSIsICIyMDIyLTExLTAxIiwgIjIwMjItMTItMDEiKSksDQogIFJldG9ybmFibGUgPSBjKDEwNzA3NTIsIDE5OTMyODksIDM1MzM4MzIpICAjIFJlcGxhY2UgTkEgd2l0aCBhY3R1YWwgb3IgYXBwcm94aW1hdGUgdmFsdWVzDQopDQoNCnZlbnRhc19yZXRvcm5hYmxlIDwtIGJpbmRfcm93cyh2ZW50YXNfcmV0b3JuYWJsZSwgbWlzc2luZ19kYXRhKSAlPiUNCiAgYXJyYW5nZShGZWNoYSkNCg0KcmV0b3JuYWJsZV90cyA8LSB0cyh2ZW50YXNfcmV0b3JuYWJsZSRSZXRvcm5hYmxlLCBzdGFydCA9IGMoMjAyMSwgMSksIGZyZXF1ZW5jeSA9IDEyKQ0KDQojIFBsb3QgZGF0YQ0KcGxvdChyZXRvcm5hYmxlX3RzLCB0eXBlPSJsIiwgY29sPSJibHVlIiwgbHdkPTIsIHhsYWI9IkZlY2hhIiwgeWxhYj0iVmVudGEgVG90YWwgZGUgUmV0b3JuYWJsZXMiLCBtYWluPSJWZW50YXMgZGUgUmV0b3JuYWJsZXMiKQ0KDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCmxpYnJhcnkoem9vKQ0KDQp2ZW50YXNfcmV0b3JuYWJsZSA8LSB2ZW50YXNfcmV0b3JuYWJsZSAlPiUNCiAgbXV0YXRlKE1vdmluZ0F2ZyA9IHJvbGxtZWFuKFJldG9ybmFibGUsIDMsIGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSkNCg0KdmVudGFzX3JldG9ybmFibGVfZmlsdGVyZWQgPC0gdmVudGFzX3JldG9ybmFibGUgJT4lDQogIGZpbHRlcighaXMubmEoTW92aW5nQXZnKSkNCg0KZ2dwbG90KHZlbnRhc19yZXRvcm5hYmxlX2ZpbHRlcmVkLCBhZXMoeCA9IEZlY2hhKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBSZXRvcm5hYmxlKSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV3aWR0aCA9IDEpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gTW92aW5nQXZnKSwgY29sb3IgPSAicmVkIiwgbGluZXdpZHRoID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBsYWJzKHRpdGxlID0gIlZlbnRhcyBkZSBSZXRvcm5hYmxlIGNvbiBNZWRpYSBNb3ZpbCIsIA0KICAgICAgIHggPSAiRmVjaGEiLCANCiAgICAgICB5ID0gIlZlbnRhIFRvdGFsIGRlIFJldG9ybmFibGUiKSArDQogIHRoZW1lX2NsYXNzaWMoKQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0V9DQojIE5vcm1hbGl6ZSBmdW5jdGlvbg0Kbm9ybWFsaXplIDwtIGZ1bmN0aW9uKHgpIHsNCiAgcmV0dXJuICgoeCAtIG1pbih4KSkgLyAobWF4KHgpIC0gbWluKHgpKSkNCn0NCg0KIyBOb3JtYWxpemUgdGhlICdSZXRvcm5hYmxlJyBjb2x1bW4NCnZlbnRhc19yZXRvcm5hYmxlJFJldG9ybmFibGUgPC0gbm9ybWFsaXplKHZlbnRhc19yZXRvcm5hYmxlJFJldG9ybmFibGUpDQoNCiMgUHJlcGFyZSBkYXRhIGZvciBSTk4NCmRmX3JldG9ybmFibGUgPC0gdmVudGFzX3JldG9ybmFibGUgJT4lDQogIG11dGF0ZShNb250aCA9IGFzLm51bWVyaWMoZm9ybWF0KEZlY2hhLCAiJW0iKSksDQogICAgICAgICBZZWFyID0gYXMubnVtZXJpYyhmb3JtYXQoRmVjaGEsICIlWSIpKSkgJT4lDQogIGFycmFuZ2UoRmVjaGEpDQoNCiMgRW5zdXJlIHRoZSAnUmV0b3JuYWJsZScgY29sdW1uIGlzIG51bWVyaWMNCmRmX3JldG9ybmFibGUkUmV0b3JuYWJsZSA8LSBhcy5udW1lcmljKGRmX3JldG9ybmFibGUkUmV0b3JuYWJsZSkNCg0KIyBDcmVhdGUgc2VxdWVuY2VzIGZvciBSTk4NCmNyZWF0ZV9zZXF1ZW5jZXNfcmV0b3JuYWJsZSA8LSBmdW5jdGlvbihkYXRhLCBzZXFfbGVuZ3RoKSB7DQogIFggPC0gbWF0cml4KG5yb3cgPSAwLCBuY29sID0gc2VxX2xlbmd0aCkNCiAgeSA8LSBudW1lcmljKCkNCiAgZm9yIChpIGluIDE6KG5yb3coZGF0YSkgLSBzZXFfbGVuZ3RoKSkgew0KICAgIFggPC0gcmJpbmQoWCwgYXMubnVtZXJpYyhkYXRhJFJldG9ybmFibGVbaTooaSArIHNlcV9sZW5ndGggLSAxKV0pKQ0KICAgIHkgPC0gYyh5LCBhcy5udW1lcmljKGRhdGEkUmV0b3JuYWJsZVtpICsgc2VxX2xlbmd0aF0pKQ0KICB9DQogIGxpc3QoWCA9IFgsIHkgPSB5KQ0KfQ0KDQpzZXFfbGVuZ3RoIDwtIDEyDQpzZXF1ZW5jZXNfcmV0b3JuYWJsZSA8LSBjcmVhdGVfc2VxdWVuY2VzX3JldG9ybmFibGUoZGZfcmV0b3JuYWJsZSwgc2VxX2xlbmd0aCkNCg0KIyBDb252ZXJ0IHRvIFJTTk5TIGZvcm1hdA0KaW5wdXRzX3JldG9ybmFibGUgPC0gYXMuZGF0YS5mcmFtZShzZXF1ZW5jZXNfcmV0b3JuYWJsZSRYKQ0KdGFyZ2V0c19yZXRvcm5hYmxlIDwtIGFzLmRhdGEuZnJhbWUoc2VxdWVuY2VzX3JldG9ybmFibGUkeSkNCg0KIyBTcGxpdCBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cw0Kc2V0LnNlZWQoMTIzKQ0KdHJhaW5faW5kaWNlc19yZXRvcm5hYmxlIDwtIHNhbXBsZSgxOm5yb3coaW5wdXRzX3JldG9ybmFibGUpLCAwLjggKiBucm93KGlucHV0c19yZXRvcm5hYmxlKSkNCmlucHV0c190cmFpbl9yZXRvcm5hYmxlIDwtIGlucHV0c19yZXRvcm5hYmxlW3RyYWluX2luZGljZXNfcmV0b3JuYWJsZSwgXQ0KdGFyZ2V0c190cmFpbl9yZXRvcm5hYmxlIDwtIHRhcmdldHNfcmV0b3JuYWJsZVt0cmFpbl9pbmRpY2VzX3JldG9ybmFibGUsIF0NCmlucHV0c190ZXN0X3JldG9ybmFibGUgPC0gaW5wdXRzX3JldG9ybmFibGVbLXRyYWluX2luZGljZXNfcmV0b3JuYWJsZSwgXQ0KdGFyZ2V0c190ZXN0X3JldG9ybmFibGUgPC0gdGFyZ2V0c19yZXRvcm5hYmxlWy10cmFpbl9pbmRpY2VzX3JldG9ybmFibGUsIF0NCg0KIyBUcmFpbiB0aGUgUk5OIG1vZGVsIHdpdGggaW5jcmVhc2VkIGNvbXBsZXhpdHkNCm1vZGVsX3JldG9ybmFibGUgPC0gZWxtYW4oaW5wdXRzX3RyYWluX3JldG9ybmFibGUsIHRhcmdldHNfdHJhaW5fcmV0b3JuYWJsZSwgc2l6ZSA9IGMoMjAsIDEwKSwgbGVhcm5GdW5jUGFyYW1zID0gYygwLjAxKSwgbWF4aXQgPSA1MDAwKQ0KDQojIE1ha2UgcHJlZGljdGlvbnMNCnByZWRpY3Rpb25zX3JldG9ybmFibGUgPC0gcHJlZGljdChtb2RlbF9yZXRvcm5hYmxlLCBpbnB1dHNfdGVzdF9yZXRvcm5hYmxlKQ0KDQojIERlbm9ybWFsaXplIHRoZSBkYXRhDQpkZW5vcm1hbGl6ZSA8LSBmdW5jdGlvbih4LCBvcmlnaW5hbCkgew0KICByZXR1cm4gKHggKiAobWF4KG9yaWdpbmFsKSAtIG1pbihvcmlnaW5hbCkpICsgbWluKG9yaWdpbmFsKSkNCn0NCg0KYWN0dWFsX3JldG9ybmFibGUgPC0gZGVub3JtYWxpemUoYXMudmVjdG9yKHRhcmdldHNfdGVzdF9yZXRvcm5hYmxlKSwgcmV0b3JuYWJsZV90cykNCnByZWRpY3RlZF9yZXRvcm5hYmxlIDwtIGRlbm9ybWFsaXplKGFzLnZlY3RvcihwcmVkaWN0aW9uc19yZXRvcm5hYmxlKSwgcmV0b3JuYWJsZV90cykNCg0KIyBQbG90IGFjdHVhbCB2cyBwcmVkaWN0ZWQgdmFsdWVzDQpwbG90KGFjdHVhbF9yZXRvcm5hYmxlLCB0eXBlID0gJ2wnLCBjb2wgPSAnYmx1ZScsIG1haW4gPSAiQWN0dWFsIHZzIFByZWRpY3RlZCAoUmV0b3JuYWJsZSkiLCB5bGFiID0gIlZhbHVlIiwgeGxhYiA9ICJUaW1lIiwgeWxpbSA9IGMobWluKGFjdHVhbF9yZXRvcm5hYmxlLCBwcmVkaWN0ZWRfcmV0b3JuYWJsZSksIG1heChhY3R1YWxfcmV0b3JuYWJsZSwgcHJlZGljdGVkX3JldG9ybmFibGUpKSkNCmxpbmVzKHByZWRpY3RlZF9yZXRvcm5hYmxlLCBjb2wgPSAncmVkJykNCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCJBY3R1YWwiLCAiUHJlZGljdGVkIiksIGNvbCA9IGMoImJsdWUiLCAicmVkIiksIGx0eSA9IDEpDQoNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMNCmxpYnJhcnkoTWV0cmljcykNCg0KIyBDYWxjdWxhdGUgZXZhbHVhdGlvbiBtZXRyaWNzDQptYWVfdmFsdWUgPC0gbWFlKGFjdHVhbF9yZXRvcm5hYmxlLCBwcmVkaWN0ZWRfcmV0b3JuYWJsZSkNCm1zZV92YWx1ZSA8LSBtc2UoYWN0dWFsX3JldG9ybmFibGUsIHByZWRpY3RlZF9yZXRvcm5hYmxlKQ0Kcm1zZV92YWx1ZSA8LSBybXNlKGFjdHVhbF9yZXRvcm5hYmxlLCBwcmVkaWN0ZWRfcmV0b3JuYWJsZSkNCnIyX3ZhbHVlIDwtIDEgLSAoc3VtKChhY3R1YWxfcmV0b3JuYWJsZSAtIHByZWRpY3RlZF9yZXRvcm5hYmxlKV4yKSAvIHN1bSgoYWN0dWFsX3JldG9ybmFibGUgLSBtZWFuKGFjdHVhbF9yZXRvcm5hYmxlKSleMikpDQoNCiMgUHJpbnQgbWV0cmljcw0KY2F0KCJNZWFuIEFic29sdXRlIEVycm9yIChNQUUpOiIsIG1hZV92YWx1ZSwgIlxuIikNCmNhdCgiTWVhbiBTcXVhcmVkIEVycm9yIChNU0UpOiIsIG1zZV92YWx1ZSwgIlxuIikNCmNhdCgiUm9vdCBNZWFuIFNxdWFyZWQgRXJyb3IgKFJNU0UpOiIsIHJtc2VfdmFsdWUsICJcbiIpDQpjYXQoIlItc3F1YXJlZCAoUsKyKToiLCByMl92YWx1ZSwgIlxuIikNCmBgYA0KDQpFbCBhbsOhbGlzaXMgZGUgdmVudGFzIGRlIHJldG9ybmFibGVzIHNlIHJlYWxpesOzIHV0aWxpemFuZG8gdW5hIFJlZCBOZXVyb25hbCBSZWN1cnJlbnRlIChSTk4pIHBhcmEgcHJlZGVjaXIgbGFzIHZlbnRhcyBmdXR1cmFzLiBBIGNvbnRpbnVhY2nDs24sIHNlIGRldGFsbGFuIGxvcyBwYXNvcyB5IHJlc3VsdGFkb3MgZGVsIGFuw6FsaXNpczoNCg0KUHJlcGFyYWNpw7NuIGRlIGxvcyBEYXRvcw0KQ2FyZ2EgeSBQcm9jZXNhbWllbnRvIGRlIERhdG9zOiBTZSBjYXJnYXJvbiBsb3MgZGF0b3MgZGUgdmVudGFzIHkgc2Ugc2VsZWNjaW9uYXJvbiBsYXMgdmVudGFzIGRlIHByb2R1Y3RvcyByZXRvcm5hYmxlcy4gU2UgbGxlbmFyb24gbG9zIGRhdG9zIGZhbHRhbnRlcyBjb24gdmFsb3JlcyBhcHJveGltYWRvcyBwYXJhIG1hbnRlbmVyIGxhIGNvbnRpbnVpZGFkIHRlbXBvcmFsLg0KDQpWaXN1YWxpemFjacOzbiBkZSBEYXRvczogU2UgdmlzdWFsaXrDsyBsYSBzZXJpZSB0ZW1wb3JhbCBkZSB2ZW50YXMgZGUgcmV0b3JuYWJsZXMgeSBzZSBjYWxjdWzDsyB1bmEgbWVkaWEgbcOzdmlsIHBhcmEgb2JzZXJ2YXIgdGVuZGVuY2lhcy4gIA0KDQpOb3JtYWxpemFjacOzbiBkZSBEYXRvczogTG9zIGRhdG9zIGRlIHZlbnRhcyBmdWVyb24gbm9ybWFsaXphZG9zIGEgdW4gcmFuZ28gZGUgMCBhIDEgcGFyYSBmYWNpbGl0YXIgZWwgZW50cmVuYW1pZW50byBkZWwgbW9kZWxvIFJOTi4gIA0KDQpDcmVhY2nDs24gZGUgU2VjdWVuY2lhcyAgDQpQYXJhIGVudHJlbmFyIGxhIFJOTiwgc2UgY3JlYXJvbiBzZWN1ZW5jaWFzIGRlIDEyIG1lc2VzIGNvbnNlY3V0aXZvcyBkZSBkYXRvcyBkZSB2ZW50YXMsIGRvbmRlIGNhZGEgc2VjdWVuY2lhIHNlIHV0aWxpesOzIHBhcmEgcHJlZGVjaXIgZWwgdmFsb3IgZGVsIG1lcyBzaWd1aWVudGUuICANCg0KKipDb25jbHVzaW9uZXMqKiAgDQoqIExhcyB2ZW50YXMgZGUgcmV0b3JuYWJsZXMgcHVlZGVuIHNlciBwcmVkZWNpZGFzIGRlIG1hbmVyYSBlZmVjdGl2YSB1dGlsaXphbmRvIHVuYSBSTk4sIGxvIGN1YWwgZXMgw7p0aWwgcGFyYSBsYSBwbGFuaWZpY2FjacOzbiB5IGdlc3Rpw7NuIGRlIGludmVudGFyaW9zLiAgDQoNCiogTGEgbm9ybWFsaXphY2nDs24gZGUgbG9zIGRhdG9zIHkgbGEgY3JlYWNpw7NuIGRlIHNlY3VlbmNpYXMgdGVtcG9yYWxlcyBzb24gcGFzb3MgY3J1Y2lhbGVzIHBhcmEgZWwgZW50cmVuYW1pZW50byBleGl0b3NvIGRlIGxhIFJOTi4gIA0KDQoqIEVsIG1vZGVsbyBSTk4gbW9zdHLDsyB1bmEgYWx0YSBwcmVjaXNpw7NuIGVuIHN1cyBwcmVkaWNjaW9uZXMsIGxvIHF1ZSBzdWdpZXJlIHN1IHBvdGVuY2lhbCBwYXJhIHNlciBpbXBsZW1lbnRhZG8gZW4gc2lzdGVtYXMgZGUgcHJvbsOzc3RpY28gZGUgdmVudGFzLiAgDQoNCiMjIyBYR0Jvb3N0DQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KHhnYm9vc3QpDQpvcHRpb25zKHNjaXBlbiA9IDk5OTkpDQoNCiMgTG9hZCBkYXRhDQp2ZW50YXMgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCJWZW50YXMgZTIueGxzeCIpDQoNCnZlbnRhcyA8LSB2ZW50YXMgJT4lDQogIG11dGF0ZShGZWNoYSA9IGFzLkRhdGUoRmVjaGEsIGZvcm1hdCA9ICIlWS0lbS0lZCIpKQ0KDQp2ZW50YXNfcmV0b3JuYWJsZSA8LSB2ZW50YXMgJT4lDQogIHNlbGVjdChGZWNoYSwgUmV0b3JuYWJsZSkgJT4lDQogIGZpbHRlcighaXMubmEoUmV0b3JuYWJsZSkpDQoNCiMgRmlsbCBtaXNzaW5nIGRhdGENCm1pc3NpbmdfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBGZWNoYSA9IGFzLkRhdGUoYygiMjAyMi0xMC0wMSIsICIyMDIyLTExLTAxIiwgIjIwMjItMTItMDEiKSksDQogIFJldG9ybmFibGUgPSBjKDEwNzA3NTIsIDE5OTMyODksIDM1MzM4MzIpICAjIFJlcGxhY2UgTkEgd2l0aCBhY3R1YWwgb3IgYXBwcm94aW1hdGUgdmFsdWVzDQopDQoNCnZlbnRhc19yZXRvcm5hYmxlIDwtIGJpbmRfcm93cyh2ZW50YXNfcmV0b3JuYWJsZSwgbWlzc2luZ19kYXRhKSAlPiUNCiAgYXJyYW5nZShGZWNoYSkNCg0KIyBDcmVhdGUgbGFnZ2VkIGZlYXR1cmVzDQp2ZW50YXNfcmV0b3JuYWJsZSA8LSB2ZW50YXNfcmV0b3JuYWJsZSAlPiUNCiAgbXV0YXRlKA0KICAgIExhZzEgPSBsYWcoUmV0b3JuYWJsZSwgMSksDQogICAgTGFnMiA9IGxhZyhSZXRvcm5hYmxlLCAyKSwNCiAgICBMYWczID0gbGFnKFJldG9ybmFibGUsIDMpLA0KICAgIExhZzQgPSBsYWcoUmV0b3JuYWJsZSwgNCksDQogICAgTGFnNSA9IGxhZyhSZXRvcm5hYmxlLCA1KSwNCiAgICBMYWc2ID0gbGFnKFJldG9ybmFibGUsIDYpLA0KICAgIExhZzcgPSBsYWcoUmV0b3JuYWJsZSwgNyksDQogICAgTGFnOCA9IGxhZyhSZXRvcm5hYmxlLCA4KSwNCiAgICBMYWc5ID0gbGFnKFJldG9ybmFibGUsIDkpLA0KICAgIExhZzEwID0gbGFnKFJldG9ybmFibGUsIDEwKSwNCiAgICBMYWcxMSA9IGxhZyhSZXRvcm5hYmxlLCAxMSksDQogICAgTGFnMTIgPSBsYWcoUmV0b3JuYWJsZSwgMTIpDQogICkgJT4lDQogIGRyb3BfbmEoKQ0KDQojIFNwbGl0IGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzDQpzZXQuc2VlZCgxMjMpDQp0cmFpbl9pbmRpY2VzX3JldG9ybmFibGUgPC0gc2FtcGxlKDE6bnJvdyh2ZW50YXNfcmV0b3JuYWJsZSksIDAuOCAqIG5yb3codmVudGFzX3JldG9ybmFibGUpKQ0KdHJhaW5fZGF0YV9yZXRvcm5hYmxlIDwtIHZlbnRhc19yZXRvcm5hYmxlW3RyYWluX2luZGljZXNfcmV0b3JuYWJsZSwgXQ0KdGVzdF9kYXRhX3JldG9ybmFibGUgPC0gdmVudGFzX3JldG9ybmFibGVbLXRyYWluX2luZGljZXNfcmV0b3JuYWJsZSwgXQ0KDQojIERlZmluZSBjb250cm9sIGZ1bmN0aW9uIGZvciBjcm9zcy12YWxpZGF0aW9uDQpjb250cm9sX3JldG9ybmFibGUgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsIG51bWJlciA9IDEwKQ0KDQojIERlZmluZSBncmlkIGZvciBoeXBlcnBhcmFtZXRlciB0dW5pbmcNCnR1bmVncmlkX3JldG9ybmFibGUgPC0gZXhwYW5kLmdyaWQoDQogIG5yb3VuZHMgPSBjKDEwMCwgMjAwKSwgICMgTnVtYmVyIG9mIGJvb3N0aW5nIGl0ZXJhdGlvbnMNCiAgbWF4X2RlcHRoID0gYygzLCA2LCA5KSwNCiAgZXRhID0gYygwLjAxLCAwLjEsIDAuMyksDQogIGdhbW1hID0gYygwLCAwLjEpLA0KICBjb2xzYW1wbGVfYnl0cmVlID0gYygwLjYsIDAuOCwgMS4wKSwNCiAgbWluX2NoaWxkX3dlaWdodCA9IGMoMSwgMyksDQogIHN1YnNhbXBsZSA9IGMoMC42LCAwLjgsIDEuMCkNCikNCg0KIyBUcmFpbiB0aGUgWEdCb29zdCBtb2RlbCB3aXRoIGNyb3NzLXZhbGlkYXRpb24NCnhnYl9tb2RlbF9yZXRvcm5hYmxlIDwtIHRyYWluKA0KICBSZXRvcm5hYmxlIH4gLiwgZGF0YSA9IHRyYWluX2RhdGFfcmV0b3JuYWJsZSwgbWV0aG9kID0gInhnYlRyZWUiLCANCiAgdHJDb250cm9sID0gY29udHJvbF9yZXRvcm5hYmxlLCB0dW5lR3JpZCA9IHR1bmVncmlkX3JldG9ybmFibGUsIHZlcmJvc2UgPSBGQUxTRQ0KKQ0KDQojIFByaW50IGJlc3QgbW9kZWwNCnByaW50KHhnYl9tb2RlbF9yZXRvcm5hYmxlJGJlc3RUdW5lKQ0KDQojIE1ha2UgcHJlZGljdGlvbnMNCnByZWRpY3Rpb25zX3JldG9ybmFibGUgPC0gcHJlZGljdCh4Z2JfbW9kZWxfcmV0b3JuYWJsZSwgdGVzdF9kYXRhX3JldG9ybmFibGUpDQoNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcGxvdChhY3R1YWxfcmV0b3JuYWJsZSwgdHlwZSA9ICdsJywgY29sID0gJ2JsdWUnLCBtYWluID0gIkFjdHVhbCB2cyBQcmVkaWN0ZWQgKFJldG9ybmFibGUpIiwgeWxhYiA9ICJWYWx1ZSIsIHhsYWIgPSAiVGltZSIpDQpsaW5lcyhwcmVkaWN0aW9uc19yZXRvcm5hYmxlLCBjb2wgPSAncmVkJykNCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCJBY3R1YWwiLCAiUHJlZGljdGVkIiksIGNvbCA9IGMoImJsdWUiLCAicmVkIiksIGx0eSA9IDEpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCmFjdHVhbF9yZXRvcm5hYmxlIDwtIHRlc3RfZGF0YV9yZXRvcm5hYmxlJFJldG9ybmFibGUNCm1hZV92YWx1ZV9yZXRvcm5hYmxlIDwtIG1hZShhY3R1YWxfcmV0b3JuYWJsZSwgcHJlZGljdGlvbnNfcmV0b3JuYWJsZSkNCm1zZV92YWx1ZV9yZXRvcm5hYmxlIDwtIG1zZShhY3R1YWxfcmV0b3JuYWJsZSwgcHJlZGljdGlvbnNfcmV0b3JuYWJsZSkNCnJtc2VfdmFsdWVfcmV0b3JuYWJsZSA8LSBybXNlKGFjdHVhbF9yZXRvcm5hYmxlLCBwcmVkaWN0aW9uc19yZXRvcm5hYmxlKQ0KcjJfdmFsdWVfcmV0b3JuYWJsZSA8LSAxIC0gKHN1bSgoYWN0dWFsX3JldG9ybmFibGUgLSBwcmVkaWN0aW9uc19yZXRvcm5hYmxlKV4yKSAvIHN1bSgoYWN0dWFsX3JldG9ybmFibGUgLSBtZWFuKGFjdHVhbF9yZXRvcm5hYmxlKSleMikpDQoNCmNhdCgiTWVhbiBBYnNvbHV0ZSBFcnJvciAoTUFFKToiLCBtYWVfdmFsdWVfcmV0b3JuYWJsZSwgIlxuIikNCmNhdCgiTWVhbiBTcXVhcmVkIEVycm9yIChNU0UpOiIsIG1zZV92YWx1ZV9yZXRvcm5hYmxlLCAiXG4iKQ0KY2F0KCJSb290IE1lYW4gU3F1YXJlZCBFcnJvciAoUk1TRSk6Iiwgcm1zZV92YWx1ZV9yZXRvcm5hYmxlLCAiXG4iKQ0KY2F0KCJSLXNxdWFyZWQgKFLCsik6IiwgcjJfdmFsdWVfcmV0b3JuYWJsZSwgIlxuIikNCmBgYA0KDQpQcmVwYXJhY2nDs24gZGUgbG9zIERhdG9zICANCkNhcmdhIHkgUHJvY2VzYW1pZW50byBkZSBEYXRvczogU2UgY2FyZ2Fyb24gbG9zIGRhdG9zIGRlIHZlbnRhcyB5IHNlIHNlbGVjY2lvbmFyb24gbGFzIHZlbnRhcyBkZSBwcm9kdWN0b3MgcmV0b3JuYWJsZXMuIFNlIGxsZW5hcm9uIGxvcyBkYXRvcyBmYWx0YW50ZXMgY29uIHZhbG9yZXMgYXByb3hpbWFkb3MgcGFyYSBtYW50ZW5lciBsYSBjb250aW51aWRhZCB0ZW1wb3JhbC4NCg0KQ3JlYWNpw7NuIGRlIENhcmFjdGVyw61zdGljYXMgUmV0YXJkYWRhczogUGFyYSBjYXB0dXJhciBsYSB0ZW5kZW5jaWEgdGVtcG9yYWwsIHNlIGNyZWFyb24gY2FyYWN0ZXLDrXN0aWNhcyByZXRhcmRhZGFzIGRlIDEgYSAxMiBtZXNlcyBwYXJhIGxhcyB2ZW50YXMgZGUgcmV0b3JuYWJsZXMuDQoNCkRpdmlzacOzbiBkZSBEYXRvcyAgDQpMb3MgZGF0b3Mgc2UgZGl2aWRpZXJvbiBlbiBjb25qdW50b3MgZGUgZW50cmVuYW1pZW50byB5IHBydWViYSwgdXRpbGl6YW5kbyBlbCA4MCUgZGUgbG9zIGRhdG9zIHBhcmEgZW50cmVuYW1pZW50byB5IGVsIDIwJSBwYXJhIHBydWViYS4NCg0KRW50cmVuYW1pZW50byBkZWwgTW9kZWxvICANClNlIGVudHJlbsOzIHVuIG1vZGVsbyBkZSBYR0Jvb3N0IHV0aWxpemFuZG8gdmFsaWRhY2nDs24gY3J1emFkYSBjb24gdW5hIHNlcmllIGRlIGhpcGVycGFyw6FtZXRyb3M6DQoNCk7Dum1lcm8gZGUgaXRlcmFjaW9uZXMgZGUgcmVmdWVyem8gKG5yb3VuZHMpOiAxMDAgeSAyMDAgIA0KDQpQcm9mdW5kaWRhZCBtw6F4aW1hIGRlIGxvcyDDoXJib2xlcyAobWF4X2RlcHRoKTogMywgNiB5IDkgIA0KDQpUYXNhIGRlIGFwcmVuZGl6YWplIChldGEpOiAwLjAxLCAwLjEgeSAwLjMgIA0KDQpQYXLDoW1ldHJvIGdhbW1hOiAwIHkgMC4xICANCg0KUHJvcG9yY2nDs24gZGUgbXVlc3RyYXMgZGUgw6FyYm9sZXMgKGNvbHNhbXBsZV9ieXRyZWUpOiAwLjYsIDAuOCB5IDEuMCAgDQoNClBlc28gbcOtbmltbyBkZSBsYXMgaG9qYXMgKG1pbl9jaGlsZF93ZWlnaHQpOiAxIHkgMyAgDQoNClN1Ym11ZXN0cmVvIChzdWJzYW1wbGUpOiAwLjYsIDAuOCB5IDEuMCAgDQoNCioqQ29uY2x1c2lvbmVzKiogIA0KKiBMYXMgdmVudGFzIGRlIHJldG9ybmFibGVzIHB1ZWRlbiBzZXIgcHJlZGVjaWRhcyBkZSBtYW5lcmEgZWZlY3RpdmEgdXRpbGl6YW5kbyBYR0Jvb3N0LCBsbyBjdWFsIGVzIMO6dGlsIHBhcmEgbGEgcGxhbmlmaWNhY2nDs24geSBnZXN0acOzbiBkZSBpbnZlbnRhcmlvcy4gIA0KDQoqIExhIGNyZWFjacOzbiBkZSBjYXJhY3RlcsOtc3RpY2FzIHJldGFyZGFkYXMgZXMgY3J1Y2lhbCBwYXJhIGNhcHR1cmFyIHRlbmRlbmNpYXMgdGVtcG9yYWxlcyBlbiBsb3MgZGF0b3MuICANCg0KDQojIyMgUmFuZG9tIEZvcmVzdA0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgQ2FyZ2FyIGxhcyBiaWJsaW90ZWNhcyBuZWNlc2FyaWFzDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCg0KIyBMZWVyIGxvcyBkYXRvcw0KdmVudGFzIDwtIHJlYWRfeGxzeCgiVmVudGFzIGUyLnhsc3giKQ0KDQojIENvbnZlcnRpciBmZWNoYXMgeSBsaW1waWFyIGNvbHVtbmEgQ2FydG9uDQp2ZW50YXMgPC0gdmVudGFzICU+JQ0KICBtdXRhdGUoDQogICAgRmVjaGEgPSBhcy5EYXRlKEZlY2hhLCBmb3JtYXQgPSAiJWQvJW0vJVkiKSwgICMgQXNlZ8O6cmF0ZSBkZSBxdWUgZWwgZm9ybWF0byBkZSBmZWNoYSBjb2luY2lkZSBjb24gdHVzIGRhdG9zDQogICAgUmV0b3JuYWJsZSA9IGFzLm51bWVyaWMoZ3N1YigiW14wLTkuXSIsICIiLCBSZXRvcm5hYmxlKSkgICMgRWxpbWluYSB0b2RvIGxvIHF1ZSBubyBzZWEgbsO6bWVyb3MgbyBwdW50b3MNCiAgKQ0KDQojIEZpbHRyYXIgcGFyYSBlbGltaW5hciBOQSBlbiBDYXJ0b24gc2kgYcO6biBleGlzdGVuDQp2ZW50YXNfUmV0b3JuYWJsZSA8LSB2ZW50YXMgJT4lDQogIHNlbGVjdChGZWNoYSwgUmV0b3JuYWJsZSkgJT4lDQogIGZpbHRlcighaXMubmEoUmV0b3JuYWJsZSkpDQoNCiMgRGF0b3MgcGFyYSBsbGVuYXIgdmFsb3JlcyBmYWx0YW50ZXMNCm1pc3NpbmdfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBGZWNoYSA9IGFzLkRhdGUoYygiMjAyMi0xMC0wMSIsICIyMDIyLTExLTAxIiwgIjIwMjItMTItMDEiKSksDQogIFJldG9ybmFibGUgPSBjKDc3NzY3NzEsIDYyOTUxNzIsIDg4NzMyOTYpICAjIFZhbG9yZXMgbnVtw6lyaWNvcw0KKQ0KDQojIENvbWJpbmFyIGxvcyBkYXRvcyBjb3JyaWdpZW5kbyBlbCB0aXBvIGRlIGRhdG9zDQp2ZW50YXNfUmV0b3JuYWJsZSA8LSBiaW5kX3Jvd3ModmVudGFzX1JldG9ybmFibGUsIG1pc3NpbmdfZGF0YSkgJT4lDQogIGFycmFuZ2UoRmVjaGEpDQoNCiMgVmVyaWZpY2FyIGxvcyBkYXRvcw0KcHJpbnQodmVudGFzX1JldG9ybmFibGUpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCiMgSW5zdGFsYXIgeSBjYXJnYXIgbGEgYmlibGlvdGVjYSByYW5kb21Gb3Jlc3Qgc2kgYcO6biBubyBlc3TDoSBjYXJnYWRhDQppZiAoIXJlcXVpcmUoInJhbmRvbUZvcmVzdCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInJhbmRvbUZvcmVzdCIpDQogIGxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KfQ0KDQojIFN1cG9uaWVuZG8gcXVlIHRpZW5lcyBvdHJhcyBjb2x1bW5hcyBxdWUgcHVlZGFzIHVzYXIgY29tbyBwcmVkaWN0b3JlcywgYXF1w60gdXNvIHPDs2xvIGxhIGZlY2hhDQojIENvbnZlcnRpciBsYSBmZWNoYSBlbiB1biBwcmVkaWN0b3IgbnVtw6lyaWNvIChjb21vIGVsIG7Dum1lcm8gZGUgZMOtYXMgZGVzZGUgdW5hIGZlY2hhIGJhc2UpDQp2ZW50YXNfUmV0b3JuYWJsZSRGZWNoYU51bSA9IGFzLm51bWVyaWModmVudGFzX1JldG9ybmFibGUkRmVjaGEgLSBtaW4odmVudGFzX1JldG9ybmFibGUkRmVjaGEpKQ0KDQojIEFqdXN0YXIgZWwgbW9kZWxvIGRlIFJhbmRvbSBGb3Jlc3QNCnJmX21vZGVsIDwtIHJhbmRvbUZvcmVzdChSZXRvcm5hYmxlIH4gRmVjaGFOdW0sIGRhdGEgPSB2ZW50YXNfUmV0b3JuYWJsZSwgbnRyZWU9NTAwKQ0KDQojIE1vc3RyYXIgZWwgcmVzdW1lbiBkZWwgbW9kZWxvDQpwcmludChyZl9tb2RlbCkNCg0KIyBJbXBvcnRhbmNpYSBkZSBsYXMgdmFyaWFibGVzDQppbXBvcnRhbmNlKHJmX21vZGVsKQ0KDQojIEhhY2VyIHByZWRpY2Npb25lcyAob3BjaW9uYWwpDQpwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KHJmX21vZGVsLCB2ZW50YXNfUmV0b3JuYWJsZSkNCg0KIyBHcmFmaWNhciB2YWxvcmVzIHJlYWxlcyB2cy4gcHJlZGljY2lvbmVzIChvcGNpb25hbCkNCnBsb3QodmVudGFzX1JldG9ybmFibGUkRmVjaGEsIHZlbnRhc19SZXRvcm5hYmxlJFJldG9ybmFibGUsIHR5cGUgPSAnbCcsIGNvbCA9ICdibHVlJywgeGxhYiA9ICJGZWNoYSIsIHlsYWIgPSAiUmV0b3JuYWJsZSIsIG1haW4gPSAiUmVhbCB2cyBQcmVkaWNjacOzbiIpDQpsaW5lcyh2ZW50YXNfUmV0b3JuYWJsZSRGZWNoYSwgcHJlZGljdGlvbnMsIGNvbCA9ICdyZWQnKQ0KbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IGMoIlJlYWwiLCAiUHJlZGljY2nDs24iKSwgY29sID0gYygiYmx1ZSIsICJyZWQiKSwgbHR5ID0gMSkNCg0KDQpgYGANCg0KDQojIyBEaXNpbWlsYXJpZGFkIGVudHJlIHNlcmllcyANCg0KTGEgZGlzaW1pbGFyaWRhZCBtaWRlIGVuIHVuIGludGVydmFsbyBkZSAqMC0yKiBxdWUgdGFuIGRpZmVyZW50ZSBzb24gbGFzIHNlcmllcyBkZSB0aWVtcG8uIFBvciBlamVtcGxvLCBhbCBjb21wYXJhciBkb3Mgc2VyaWVzIHRlbXBvcmFsZXMgKGNvbmp1bnRvcyBkZSBkYXRvcyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8pLCBsYSBkaXNpbWlsaXR1ZCBub3MgaW5kaWNhIGN1w6FuIGRpZmVyZW50ZXMgc29uIGVzdG9zIGRvcyBjb25qdW50b3MgZGUgZGF0b3MuIFVuYSBkaXNpbWlsaXR1ZCBiYWphIHNpZ25pZmljYSBxdWUgc29uIG11eSBzaW1pbGFyZXMsIG1pZW50cmFzIHF1ZSB1bmEgZGlzaW1pbGl0dWQgYWx0YSBzaWduaWZpY2EgcXVlIHNvbiBiYXN0YW50ZSBkaWZlcmVudGVzLiBFc3RhIGRpc2ltaWxhcmlkYWQgZnVlIGNhbGN1bGFkYSBiYXNhZGEgZW4gbGEgY29ycmVsYWNpw7NuIGRlIFBlYXJzb24uICANCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KbnVtYmVyIDwtIFRTY2x1c3Q6OmRpc3MuQ09SKGNhcnRvbl90cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0b3JuYWJsZV90cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV0YSA9IE5VTEwpDQoNCiMgUGxvdA0KcGxvdCgxLCB0eXBlID0gIm4iLCB4bGFiID0gIiIsIHlsYWIgPSAiIiwgYXhlcyA9IEZBTFNFKQ0KdGV4dCgxLCAxLCBudW1iZXIsIGNleCA9IDMpDQp0aXRsZShtYWluID0gIkRpc2ltaWxhcmlkYWQgZGUgUGVhcnNvbiIpDQoNCg0KYGBgDQoNCiMjIFNlbGVjY2nDs24gZGUgbW9kZWxvDQoNCkVuIGVsIGNhc28gZGUgbGFzIHZlbnRhcyBkZSBjYXJ0w7NuLCBjb25zaWRlcmFtb3MgcXVlIGVsIG1lam9yIG1vZGVsbyBlcyBsYSBSZWQgTmV1cm9uYWwgUmVjdXJyZW50ZSAoUk5OKS4gRXN0byBzZSBkZWJlIGEgcXVlLCBhdW5xdWUgc2UgdGVuZ2FuIHBlb3JlcyBpbmRpY2Fkb3JlcyBkZSBkZXNlbXBlw7FvLCBzaWd1ZSBtZWpvciBsYSB0ZW5kZW5jaWEgZGUgbGFzIHZlbnRhcyBkZSBjYXJ0w7NuLiBWYWxvcmFtb3MgZXN0byBwb3JxdWUgZWwgc2VyIGh1bWFubyBubyBwcm9jZXNhIGRlIHRhbiBidWVuYSBtYW5lcmEgbG9zIG7Dum1lcm9zLCBzaW4gZW1iYXJnbyBwb2RlbW9zIHNlciBtw6FzIHZpc3VhbGVzIHBvciBsbyB0YW50bywgZWwgaGVjaG8gZGUgcG9kZXIgdmlzdWFsaXphciBsYSB0ZW5kZW5jaWEgZGUgdW5hIG1lam9yIG1hbmVyYSBwdWVkZSBicmluZGFyIHVuIGJlbmVmaWNpbyBlbiBjdWFudG8gYSBsYSBpbnRlcnByZXRhYmlsaWRhZCBkZWwgbW9kZWxvLiAgDQoNCkVuIGVsIGNhc28gZGUgbGFzIHZlbnRhcyBkZSByZXRvcm5hYmxlcyBjb25zaWRlcmFtb3MgcXVlIGVsIG1lam9yIG1vZGVsbyBlcyBYR0Jvb3N0LiBYR0Jvb3N0IGVzIGNvbm9jaWRvIHBvciBzdSBhbHRvIHJlbmRpbWllbnRvIHkgcHJlY2lzacOzbiBlbiB0YXJlYXMgZGUgcHJlZGljY2nDs24gZGViaWRvIGEgc3UgY2FwYWNpZGFkIHBhcmEgbWFuZWphciByZWxhY2lvbmVzIGNvbXBsZWphcyBlbnRyZSBsYXMgdmFyaWFibGVzLiBFc3RvIGxvIGhhY2UgaWRlYWwgcGFyYSBwcmVkZWNpciBsYXMgdmVudGFzIGRlIHByb2R1Y3RvcyByZXRvcm5hYmxlcywgZG9uZGUgbGFzIGZsdWN0dWFjaW9uZXMgeSBwYXRyb25lcyBwdWVkZW4gc2VyIGNvbXBsaWNhZG9zLiBUYW1iacOpbiwgbWFuZWphIGVmaWNpZW50ZW1lbnRlIGxvcyBkYXRvcyBmYWx0YW50ZXMgZHVyYW50ZSBlbCBlbnRyZW5hbWllbnRvLCBsbyBxdWUgZXMgY3J1Y2lhbCBlbiBlbCBjb250ZXh0byBkZSB2ZW50YXMgZG9uZGUgcHVlZGUgaGFiZXIgZGF0b3MgaW5jb21wbGV0b3MgbyBpbmNvbnNpc3RlbnRlcy4NCg0KIyBSZWN1cnNvcyBIdW1hbm9zDQoNCiFbXShDOlxcVXNlcnNcXGthdGhpXFxPbmVEcml2ZVxcRXNjcml0b3Jpb1xcRVZJREVOQ0lBMl9JQVxcUlJISC5wbmcpDQojIyBNb2RlbG9zIA0KDQojIyMgTmFpdmUgQmF5ZXMNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgSW5zdGFsYXIgeSBjYXJnYXIgbG9zIHBhcXVldGVzIG5lY2VzYXJpb3MNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShlMTA3MSkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBMZWVyIGVsIGFyY2hpdm8gRXhjZWwNCmRhdGEgPC0gcmVhZF9leGNlbCgiQmFzZV9KdW50YV9SSCAoMSkueGxzeCIpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgSW5zcGVjY2lvbmFyIGxhcyBwcmltZXJhcyBmaWxhcyBkZWwgZGF0YXNldCBwYXJhIGVudGVuZGVyIHN1IGVzdHJ1Y3R1cmENCmhlYWQoZGF0YSkNCg0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIFZlcmlmaWNhciBsb3MgdGlwb3MgZGUgZGF0b3MNCnN0cihkYXRhKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIEZ1bmNpw7NuIG1lam9yYWRhIHBhcmEgbGltcGlhciB5IGNvbnZlcnRpciBmZWNoYXMNCmNvbnZlcnRpcl9hX2ZlY2hhIDwtIGZ1bmN0aW9uKGNvbHVtbmEpIHsNCiAgIyBDb252ZXJ0aXIgYSBuw7ptZXJvIHNpIG5vIGxvIGVzDQogIGNvbHVtbmEgPC0gYXMubnVtZXJpYyhjb2x1bW5hKQ0KICAjIENvbnZlcnRpciBhIGZlY2hhIHVzYW5kbyBsYSBmZWNoYSBkZSBvcmlnZW4gZGUgRXhjZWwNCiAgYXMuRGF0ZShjb2x1bW5hLCBvcmlnaW4gPSAiMTg5OS0xMi0zMCIpDQp9DQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBNb3N0cmFyIGxhIGVzdHJ1Y3R1cmEgZGVsIGRhdGFmcmFtZSBhbnRlcyBkZSBsYSBjb252ZXJzacOzbg0Kc3RyKGRhdGEpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgQ29udmVydGlyIGxhcyBjb2x1bW5hcyByZWxldmFudGVzIGEgZmVjaGFzDQpkYXRhIDwtIGRhdGEgJT4lDQogIG11dGF0ZSgNCiAgICBGZWNoYV9OYWNpbWllbnRvID0gYXMuUE9TSVhjdChGZWNoYV9OYWNpbWllbnRvLCBmb3JtYXQgPSAiJVktJW0tJWQiKSwNCiAgICBGZWNoYV9BbHRhID0gYXMuUE9TSVhjdChGZWNoYV9BbHRhLCBmb3JtYXQgPSAiJVktJW0tJWQiKSwNCiAgICBQcmltZXJfTWVzID0gY29udmVydGlyX2FfZmVjaGEoUHJpbWVyX01lcyksDQogICAgQ3VhcnRvX01lcyA9IGNvbnZlcnRpcl9hX2ZlY2hhKEN1YXJ0b19NZXMpLA0KICAgIEZlY2hhX0JhamEgPSBjb252ZXJ0aXJfYV9mZWNoYShGZWNoYV9CYWphKQ0KICApDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgTW9zdHJhciBsYSBlc3RydWN0dXJhIGRlbCBkYXRhZnJhbWUgZGVzcHXDqXMgZGUgbGEgY29udmVyc2nDs24NCnN0cihkYXRhKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIFZlcmlmaWNhciBsb3MgdmFsb3JlcyBOQSBpbnRyb2R1Y2lkb3MgZHVyYW50ZSBsYSBjb252ZXJzacOzbg0KdmFsb3Jlc19uYSA8LSBzYXBwbHkoZGF0YSwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkNCnZhbG9yZXNfbmENCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KICMgQ29kaWZpY2FyIHZhcmlhYmxlcyBjYXRlZ8OzcmljYXMNCmRhdGEkR2VuZXJvIDwtIGFzLmZhY3RvcihkYXRhJEdlbmVybykNCmRhdGEkRXN0YWRvX0NpdmlsIDwtIGFzLmZhY3RvcihkYXRhJEVzdGFkb19DaXZpbCkNCmRhdGEkUHVlc3RvIDwtIGFzLmZhY3RvcihkYXRhJFB1ZXN0bykNCmRhdGEkRHB0byA8LSBhcy5mYWN0b3IoZGF0YSREcHRvKQ0KZGF0YSRTdGF0dXMgPC0gYXMuZmFjdG9yKGRhdGEkU3RhdHVzKQ0KZGF0YSRTdGF0dXNfTnVtIDwtIGFzLmZhY3RvcihkYXRhJFN0YXR1c19OdW0pDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBEaXZpc2nDs24gZGUgbG9zIGRhdG9zIGVuIGVudHJlbmFtaWVudG8geSBwcnVlYmENCnNldC5zZWVkKDEyMykNCnRyYWluSW5kZXggPC0gY3JlYXRlRGF0YVBhcnRpdGlvbihkYXRhJFN0YXR1c19OdW0sIHAgPSAuOCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdCA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpDQpkYXRhVHJhaW4gPC0gZGF0YVt0cmFpbkluZGV4LCBdDQpkYXRhVGVzdCAgPC0gZGF0YVstdHJhaW5JbmRleCwgXQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIEFzZWd1cmFyc2UgZGUgcXVlIGxvcyBuaXZlbGVzIGRlIGZhY3RvciBkZSBTdGF0dXNfTnVtIHNlYW4gY29uc2lzdGVudGVzDQpsZXZlbHMoZGF0YVRyYWluJFN0YXR1c19OdW0pIDwtIGxldmVscyhkYXRhJFN0YXR1c19OdW0pDQpsZXZlbHMoZGF0YVRlc3QkU3RhdHVzX051bSkgPC0gbGV2ZWxzKGRhdGEkU3RhdHVzX051bSkNCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBFbnRyZW5hciB1biBtb2RlbG8gTmFpdmUgQmF5ZXMNCm5iX21vZGVsIDwtIG5haXZlQmF5ZXMoU3RhdHVzX051bSB+IC4sIGRhdGEgPSBkYXRhVHJhaW4pDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgSGFjZXIgcHJlZGljY2lvbmVzDQpwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KG5iX21vZGVsLCBuZXdkYXRhID0gZGF0YVRlc3QpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCiMgQ29udmVydGlyIGxhcyBwcmVkaWNjaW9uZXMgYSBmYWN0b3IgeSBhc2VndXJhcnNlIGRlIHF1ZSB0aWVuZW4gbG9zIG1pc21vcyBuaXZlbGVzIHF1ZSBTdGF0dXNfTnVtDQpwcmVkaWN0aW9ucyA8LSBmYWN0b3IocHJlZGljdGlvbnMsIGxldmVscyA9IGxldmVscyhkYXRhJFN0YXR1c19OdW0pKQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0V9DQojIEV2YWx1YXIgZWwgbW9kZWxvDQpjb25mdXNpb24gPC0gY29uZnVzaW9uTWF0cml4KHByZWRpY3Rpb25zLCBkYXRhVGVzdCRTdGF0dXNfTnVtKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIEltcHJpbWlyIGVsIHJlc3VtZW4gZGVsIG1vZGVsbw0KcHJpbnQobmJfbW9kZWwpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCiMgSW1wcmltaXIgbGEgbWF0cml6IGRlIGNvbmZ1c2nDs24NCnByaW50KGNvbmZ1c2lvbikNCmBgYA0KDQoqQ29uY2x1c2nDs24qDQpFbCBtb2RlbG8gdGllbmUgdW4gcmVuZGltaWVudG8gcGVyZmVjdG8gZW4gZWwgY29uanVudG8gZGUgZGF0b3MgZGUgcHJ1ZWJhLCBjb24gdW5hIGV4YWN0aXR1ZCwgc2Vuc2liaWxpZGFkIHkgZXNwZWNpZmljaWRhZCBkZWwgMTAwJS4gU2luIGVtYmFyZ28sIHJlc3VsdGFkb3MgdGFuIHBlcmZlY3RvcyBwdWVkZW4gaW5kaWNhciBxdWUgZWwgbW9kZWxvIGVzdMOhIHNvYnJlYWp1c3RhZG8gYWwgY29uanVudG8gZGUgZGF0b3MgZGUgZW50cmVuYW1pZW50bywgcHVlZGUgc2VyIGRlYmlkbyBhIHF1ZSBsb3MgZGF0b3MgZXN0w6FuIGRlc2JhbGFuY2VhZGFzLiBNYXMgZXNwZWNpZmljbyBwYXJhIGVudGVuZGVyIHF1ZSBub3MgZGljZSBsYSBtYXRyaXogZGUgY29uZnVzacOzbiBwb2RlbW9zIHZlciBsbyBzaWd1aWVudGU6IA0KDQpFbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlbCA5NSUgcGFyYSBsYSBleGFjdGl0dWQgZXN0w6EgZW50cmUgMC45NzYgeSAxLiBFc3RvIGluZGljYSBxdWUgZXN0YW1vcyBtdXkgc2VndXJvcyBkZSBxdWUgbGEgZXhhY3RpdHVkIHJlYWwgZGVsIG1vZGVsbyBlc3TDoSBlbiBlc3RlIHJhbmdvLiANCg0KRWwgTklSIGVzIDAuNzk2MSwgcXVlIHJlcHJlc2VudGEgbGEgcHJvcG9yY2nDs24gZGUgbGEgY2xhc2UgbcOhcyBwcmV2YWxlbnRlIGVuIGVsIGNvbmp1bnRvIGRlIHBydWViYS4gRW4gZXN0ZSBjYXNvLCBlcyBsYSBjbGFzZSAiMSIgbyBsb3MgIkJhamEiICgxMjEgY2Fzb3MgZGUgdW4gdG90YWwgZGUgMTUyKS4gDQoNCkVsIHAtdmFsb3IgZXMgZXh0cmVtYWRhbWVudGUgYmFqbyAoOC43NzNlLTE2KSwgZXN0byBzdWdpZXJlIHF1ZSBlbCBtb2RlbG8gZXMgZWZlY3Rpdm8gcGFyYSBwcmVkZWNpciBsYXMgYmFqYXMgZGUgZW1wbGVhZG9zLiANCg0KRWwgdmFsb3IgZGUgS2FwcGEgZXMgMSwgbG8gcXVlIGluZGljYSB1biBhY3VlcmRvIHBlcmZlY3RvIGVudHJlIGxhcyBwcmVkaWNjaW9uZXMgZGVsIG1vZGVsbyB5IGxhcyBjbGFzaWZpY2FjaW9uZXMgcmVhbGVzLiBFc3RlIGVzIHVuIGZ1ZXJ0ZSBpbmRpY2Fkb3IgZGUgbGEgY2FsaWRhZCBkZWwgbW9kZWxvLg0KDQpQcmV2YWxlbmNpYTogMC4yMDM5IC0gRXN0byBpbmRpY2EgcXVlIGFwcm94aW1hZGFtZW50ZSBlbCAyMC4zOSUgZGUgbG9zIGVtcGxlYWRvcyBlbiBlbCBjb25qdW50byBkZSBkYXRvcyBkZSBwcnVlYmEgbm8gc2UgZGllcm9uIGRlIGJhamEuDQoNClRhc2EgZGUgRGV0ZWNjacOzbjogMC4yMDM5IC0gRXN0byBtdWVzdHJhIHF1ZSBlbCBtb2RlbG8gZGV0ZWN0w7MgY29ycmVjdGFtZW50ZSBlbCAyMC4zOSUgZGUgbG9zIGVtcGxlYWRvcyBxdWUgbm8gc2UgZGllcm9uIGRlIGJhamEuDQoNClRhc2EgZGUgUHJldmFsZW5jaWEgZGUgRGV0ZWNjacOzbjogMC4yMDM5IC0gTGEgcHJvcG9yY2nDs24gZGUgZW1wbGVhZG9zIHByZWRpY2hvcyBjb21vIG5vIGRhZG9zIGRlIGJhamEgZXMgZGVsIDIwLjM5JS4NCg0KDQoqVXNvIGVuIFByZWRpY2Npb25lcyBGdXR1cmFzKg0KRWwgbW9kZWxvIHB1ZWRlIHNlciB1dGlsaXphZG8gcGFyYSBwcmVkZWNpciBmdXR1cmFzIGJhamFzIGRlIGVtcGxlYWRvcy4gSW1wbGVtZW50YXIgZWwgbW9kZWxvIGVuIHVuIGVudG9ybm8gZGUgcHJvZHVjY2nDs24gcGVybWl0aXLDoSBtb25pdG9yZWFyIHkgYWp1c3RhciBlbCBtb2RlbG8gc2Vnw7puIHNlYSBuZWNlc2FyaW8gY29uIGRhdG9zIGVuIHRpZW1wbyByZWFsLg0KDQoNCiMjIyBMaW1waWV6YSBkZSBsYSBiYXNlIGRlIFJIICANCg0KTGEgbGltcGllemEgZGUgbGEgYmFzZSBkZSBSSCBzZSByZWFsaXrDsyBlbiBFeGNlbCBwYXJhIGhhY2VyIGVsIHByb2Nlc28gbcOhcyByw6FwaWRvIHkgZWZpY2llbnRlLCB5YSBxdWUgZW4gbGEgZW50cmVnYSBwYXNhZGEsIGxhIGxpbXBpZXphIHNlIGxsZXbDsyBhIGNhYm8gZW4gUiB5IGVzdGEgdG9tw7MgbGEgbWF5b3IgcGFydGUgZGVsIHRpZW1wbyBxdWUgcG9kw61hIGVzdGFyIGRlc3RpbmFkbyBhIG90cm9zIGFuw6FsaXNpcy4gIA0KDQpTZSBqdW50YXJvbiBsYXMgYmFzZXMgZGUgZGF0b3Mg4oCcRGF0b3NfRk9STV9SSF9GSjIwMjTigJ0sIGxhIGN1YWwgY29udGllbmUgbGFzIGJhamFzIHF1ZSBoYSB0ZW5pZG8gRk9STSwgeSBsYSBiYXNlIGRlIGRhdG9zIOKAnEJERCBGT1JNIDIwMjIgKEVNUExFQURPUynigJ0sIHF1ZSBjb250aWVuZSBhIGxhcyBwZXJzb25hcyBxdWUgc2lndWVuIHRyYWJhamFuZG8gZW4gbGEgZW1wcmVzYS4gTGEgaW5mb3JtYWNpw7NuIHNlIHVuaWZpY8OzIG1hbnVhbG1lbnRlLCBjb2xvY2FuZG8gbGFzIGNvbHVtbmFzIHF1ZSBhbWJhcyBiYXNlcyB0aWVuZW4gZW4gY29tw7puLiAgDQoNClNlIGHDsWFkacOzIHVuYSBjb2x1bW5hIHBhcmEgZmFjaWxpdGFyIGxhcyBzYWxpZGFzIGRlIGxvcyBtb2RlbG9zLiBMYSBjb2x1bW5hIOKAnEVzdGF0dXPigJ0gc2UgY29uZm9ybWEgZGUgbG9zIGVtcGxlYWRvcyBxdWUgc2lndWVuIHRyYWJhamFuZG8gKEVtcGxlYWRvKSBvIHlhIGZ1ZXJvbiBkYWRvcyBkZSBiYWphIChCYWphKSwgdG9tYW5kbyBjb21vIHJlZmVyZW5jaWEgbGEgY29sdW1uYSDigJxGZWNoYV9CYWph4oCdIHBhcmEgaGFjZXIgZXN0YSBkaXN0aW5jacOzbi4gQXF1ZWxsb3MgZW1wbGVhZG9zIGNvbiBmZWNoYSBkZSBiYWphIHNvbiBjYXRhbG9nYWRvcyBjb21vIOKAnEJhamHigJ0sIHkgbG9zIHF1ZSBubyB0aWVuZW4gZmVjaGEgZGUgYmFqYSBzZSBpbmZpZXJlIHF1ZSBzaWd1ZW4gc2llbmRvIGVtcGxlYWRvcyBlbiBGT1JNLCBwb3IgbG8gcXVlIHNvbiBjYXRhbG9nYWRvcyBjb21vIOKAnEVtcGxlYWRv4oCdLiAgDQoNClNlIGNyZWFyb24gb3RyYXMgZG9zIGNvbHVtbmFzIGRvbmRlIHNlIGV4dHJham8gZWwgbWVzICjigJxNZXNfRmVjaGFfQWx0YeKAnSkgeSBlbCBhw7FvICjigJxBw7FvX0ZlY2hhX0FsdGHigJ0pIGRlIGxhIGNvbHVtbmEg4oCcRmVjaGFfQWx0YSIgcGFyYSBjb252ZXJ0aXIgbGEgZmVjaGEgZW4gbGEgcXVlIGxvcyB0cmFiYWphZG9yZXMgc2UgZGllcm9uIGRlIGFsdGEgZW4gdmFyaWFibGVzIG3DoXMgZXNwZWPDrWZpY2FzIHBhcmEgbG9zIG1vZGVsb3MuICANCg0KUGFyYSBsb3Mgbm9tYnJlcyBkZSBsYXMgY29sdW1uYXMsIHNlIHVuaWVyb24gY29uIHVuIGd1aW9uIGJham8gbG9zIHF1ZSBlc3RhYmFuIGNvbmZvcm1hZG9zIHBvciB2YXJpYXMgcGFsYWJyYXMsIHBhcmEgZXZpdGFyIHByb2JsZW1hcyBhbCBhbmFsaXphciBsYXMgdmFyaWFibGVzIHkgaGFjZXIgbG9zIG1vZGVsb3MuICANCg0KU2UgaG9tb2xvZ2Fyb24gYXF1ZWxsYXMgcGFsYWJyYXMgcXVlIGVyYW4gaWd1YWxlcyBwZXJvIGVzdGFiYW4gZXNjcml0YXMgeWEgc2VhIGNvbiBtYXnDunNjdWxhIG8gbWluw7pzY3VsYSwgdGVuw61hbiBhbGfDum4gZXJyb3Igb3J0b2dyw6FmaWNvLCB0ZW7DrWFuIHRpbGRlcywgZXN0YWJhbiBlbiBtYXNjdWxpbm8gbyBmZW1lbmlubywgZXRjLiBQb3IgZWplbXBsbzogZW4gbGEgY29sdW1uYSDigJxFc3RhZG/igJ0sIOKAnE51ZXZvIExlw7Nu4oCdIHNlIGhvbW9sb2fDsyBjb24g4oCcTnVldm8gTGVvbuKAnSBwYXJhIHF1ZSBmdWVyYSB1bmEgbWlzbWEgb3BjacOzbi4gRW4gbGEgY29sdW1uYSDigJxFc3RhZG9fQ2l2aWzigJ0sIOKAnENBU0FEQeKAnSBzZSB1bmnDsyBjb24g4oCcQ2FzYWRv4oCdLCDigJxEaXZvcmNpYWRh4oCdIGNvbiDigJxEaXZvcmNpYWRv4oCdLCDigJxTZXBhcmFkYeKAnSBzZSBjYW1iacOzIGEg4oCcU2VwYXJhZG/igJ0sIGV0Yy4gIA0KDQpTZSByZWVtcGxhemFyb24gbGFzICLDsSIgcG9yICJuIiBwYXJhIHF1ZSBlc3RhIGxldHJhIHB1ZWRhIHNlciBsZcOtZGEgZW4gUiBTdHVkaW8uICANCg0KU2UgcmVlbXBsYXrDsyBsYSBmZWNoYSBkZSBuYWNpbWllbnRvIGRlIHVuYSBjb2xhYm9yYWRvcmEgZGUgMzEvMTAvMjAyMiBhIDMxLzEwLzIwMDIsIGFsIGluZmVyaXIgcXVlIGh1Ym8gdW4gZXJyb3IgZGUgZGVkbyBhbCBtb21lbnRvIGRlIGVzY3JpYmlyIGVsIGHDsW8uICAgIA0KDQoNClNlIGVsaW1pbmFyb24gY29sdW1uYXMgaW5uZWNlc2FyaWFzIG8gcXVlIGZ1ZXJhbiBkZW1hc2lhZG8gZXNwZWPDrWZpY2FzIHkgcHVkaWVyYW4gY3JlYXIgYWxnw7puIHNlc2dvIGVuIGxvcyBtb2RlbG9zLiBEZSBsYXMgY29sdW1uYXMgb3JpZ2luYWxlcyBzZSBkZWphcm9uIGxhcyBzaWd1aWVudGVzOiDigJxBcGVsbGlkb+KAnSwg4oCcTm9tYnJl4oCdLCDigJxGZWNoYV9OYWNpbWllbnRv4oCdLCDigJxHw6luZXJv4oCdLCDigJxGZWNoYV9BbHRh4oCdLCDigJxQdWVzdG/igJ0sIOKAnERwdG/igJ0sIOKAnEx1Z2FyX05hY2ltaWVudG/igJ0sIOKAnE11bmljaXBpb+KAnSwg4oCcRXN0YWRv4oCdLCDigJxDUOKAnSwg4oCcRXN0YWRvX0Npdmls4oCdLCDigJxCYW5jb+KAnS4gIA0KDQpTZSByZWVtcGxhemFyb24gbG9zIGVzcGFjaW9zIGVuIGJsYW5jbyBjb24g4oCcTm8gZXNwZWNpZmljb+KAnSBwYXJhIG5vIGhhY2VyIGFzdW5jaW9uZXMgaW5jb3JyZWN0YXMgcXVlIHB1ZGllcmFuIGNyZWFyIHNlc2dvcyBlbiBsYXMgY29sdW1uYXM6IOKAnERwdG/igJ0sIOKAnEx1Z2FyX05hY2ltaWVudG/igJ0sIOKAnEJhbmNv4oCdLiAgDQoNClNlIGNyZcOzIGxhIGNvbHVtbmEg4oCcRWRhZOKAnSBwYXJhIHZpc3VhbGl6YXIgbGEgZWRhZCBkZSBsb3MgZW1wbGVhZG9zIGFjdHVhbGVzIHkgbG9zIHF1ZSBzZSBoYW4gZGFkbyBkZSBiYWphLCB0b21hbmRvIGNvbW8gcmVmZXJlbmNpYSBsYXMgZmVjaGFzIGRlIG5hY2ltaWVudG8gZW4gbGEgY29sdW1uYSDigJxGZWNoYV9OYWNpbWllbnRv4oCdIHkgdXRpbGl6YW5kbyBsYSBmw7NybXVsYSDigJw9KEHDkU8oQUhPUkEoKSktQcORTyhbQFtGZWNoYV9OYWNpbWllbnRvXV0pKeKAnS4gIA0KDQpQb3Igw7psdGltbywgc2lndWllbmRvIGxhIHJlY29tZW5kYWNpw7NuIGRlbCBwcm9mZXNvciBFcmljLCBzZSBjcmXDsyBvdHJhIGNvbHVtbmEg4oCcUHVlc3RvX0dydXBvc+KAnSwgZG9uZGUgc2Ugc2VnbWVudGFyb24gYWxndW5vcyBwdWVzdG9zIGVuIGdydXBvcyBtw6FzIGdlbmVyYWxlcyBwYXJhIHF1ZSBlbCBtb2RlbG8gZGUgw4FyYm9sIGRlIERlY2lzacOzbiBzZSB2ZWEgbcOhcyBsaW1waW8uIENvbiBsYSB2YXJpYWJsZSDigJxQdWVzdG/igJ0sIGxhIHZpc3VhbGl6YWNpw7NuIGRlbCBtb2RlbG8gc2UgcHJlc2VudGFiYSBkZSBtYW5lcmEgYWdsb21lcmFkYS4gTG9zIGF5dWRhbnRlcyBkZSBkaXN0aW50YXMgw6FyZWFzIHkgZWwgYXV4aWxpYXIgZGUgZW1iYXJxdWVzIHNlIGp1bnRhcm9uIGVuIGVsIGdydXBvIOKAnEF5dWRhbnRl4oCdLCBsb3MgaW5zcGVjdG9yZXMgeSBjb2xhYm9yYWRvcmVzIGRlIGNhbGlkYWQgc2UgdW5pZXJvbiBlbiBlbCBncnVwbyDigJxDYWxpZGFk4oCdLCBsb3MgY2hvZmVyZXMgZGUgZGl2ZXJzYXMgw6FyZWFzIHNlIGFncnVwYXJvbiBlbiBlbCBncnVwbyDigJxDaG9mZXLigJ0sIGxvcyByZXNpZGVudGVzIGRlIGRpdmVyc2FzIMOhcmVhcyBzZSBjb2xvY2Fyb24gZW4gZWwgZ3J1cG8g4oCcUmVzaWRlbnRl4oCdLCB5IGxvcyBzdXBlcnZpc29yZXMgZGUgdmFyaWFzIMOhcmVhcyBzZSB1bmllcm9uIGVuIGVsIGdydXBvIOKAnFN1cGVydmlzb3LigJ0uIEZpbmFsbWVudGUsIGVsIGdydXBvIGNvbmZvcm1hZG8gcG9yIG3DoXMgcHVlc3RvcyBlcyBlbCBkZSDigJxQcm9kdWNjacOzbiB5IExvZ8Otc3RpY2HigJ07IGVuIGVzdGUgZ3J1cG8gc2UgY29uc2lkZXJhcm9uIGxvcyBwdWVzdG9zIG3DoXMgaW52b2x1Y3JhZG9zIGVuIGxhcyBvcGVyYWNpb25lcyBkZSBwcm9kdWNjacOzbiB5IGxvZ8Otc3RpY2EgZGUgRk9STSAoQWxtYWNlbmlzdGEsIEdlc3RvciwgTWFyY2Fkb3JhLCBNYXRlcmlhbGlzdGEsIE1vbnRhY2FyZ3Vpc3RhLCBNb3pvLCBPcGVyYWRvciwgUGludG9yIHkgU29sZGFkb3IpLiAgDQoNCg0KIyMjIMOBcmJvbCBkZSBEZWNpc2nDs24NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgQ2FyZ2EgZGUgbGlicmVyaWFzDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShNZXRyaWNzKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShycGFydC5wbG90KQ0KYGBgDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgQmFzZSBkZSBkYXRvcyBSSA0KREZfUkggPC0gcmVhZF9leGNlbCgiQmFzZV9KdW50YV9SSF9hY3R1YWwueGxzeCIpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBWZXIgbGEgZXN0cnVjdHVyYSBkZSBsYSBiYXNlDQpzdHIoREZfUkgpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBJZGVudGlmaWNhciBOQXMNCnN1bShpcy5uYShERl9SSCkpICMgTm8gaGF5IE5BcyBlbiBsYSBiYXNlLiANCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBDYW1iaWFyICJFc3RhdHVzIiBhIGZvcm1hdG8gZmFjdG9yIGFsIHNlciBsYSB2YXJpYWJsZSBkZSBzYWxpZGENCkRGX1JIJEVzdGF0dXMgPC0gYXMuZmFjdG9yKERGX1JIJEVzdGF0dXMpDQoNCiMgQ2FtYmlhciAiQ1AiLCAiRWRhZCIsICJNZXNfRmVjaGFfQWx0YSIgeSAiQcOxb19GZWNoYV9BbHRhIiBhIGZvcm1hdG8gbsO6bWVybw0KREZfUkgkQ1AgPC0gYXMubnVtZXJpYyhERl9SSCRDUCkNCkRGX1JIJEVkYWQgPC0gYXMubnVtZXJpYyhERl9SSCRFZGFkKQ0KREZfUkgkTWVzX0ZlY2hhX0FsdGEgPC0gYXMubnVtZXJpYyhERl9SSCRNZXNfRmVjaGFfQWx0YSkNCkRGX1JIJEHDsW9fRmVjaGFfQWx0YSA8LSBhcy5udW1lcmljKERGX1JIJEHDsW9fRmVjaGFfQWx0YSkNCmBgYA0KDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIERpdmlkaXIgbG9zIGRhdG9zIGVuIGNvbmp1bnRvcyBkZSBlbnRyZW5hbWllbnRvIHkgcHJ1ZWJhDQpzZXQuc2VlZCgxMjMpDQpzYW1wbGVfREZfUkggPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBucm93KERGX1JIKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuOCwwLjIpKQ0KdHJhaW5fREZfUkggIDwtIERGX1JIW3NhbXBsZV9ERl9SSCwgXQ0KdGVzdF9ERl9SSCAgIDwtIERGX1JIWyFzYW1wbGVfREZfUkgsIF0NCmBgYA0KDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIEFqdXN0YXIgZWwgbW9kZWxvIGNvbiBkaWZlcmVudGVzIHZhbG9yZXMgZGUgY3ANCmNwX3ZhbHVlcyA8LSBjKDAuMDEsIDAuMDMsIDAuMDUsIDAuMSkNCmZvciAoY3AgaW4gY3BfdmFsdWVzKSB7DQogIERlY2lzaW9uVHJlZV9tb2RlbF9wcnVlYmEgPC0gcnBhcnQoRXN0YXR1cyB+IEVkYWQgKyBHZW5lcm8gKyBNZXNfRmVjaGFfQWx0YSArIEHDsW9fRmVjaGFfQWx0YSArIFB1ZXN0b19HcnVwb3MgKyBFc3RhZG8gKyBFc3RhZG9fQ2l2aWwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHRyYWluX0RGX1JILCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJjbGFzcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gcnBhcnQuY29udHJvbChjcCA9IGNwKSkNCiAgcnBhcnQucGxvdChEZWNpc2lvblRyZWVfbW9kZWxfcHJ1ZWJhLCBtYWluID0gcGFzdGUoIlRyZWUgd2l0aCBjcCA9IiwgY3ApKQ0KfQ0KYGBgDQoNCg0KYGBge3IgZWNobz1GQUxTRX0NCiMgTW9kZWxvIGRlIMOBcmJvbCBkZSBEZWNpc2nDs24NCkRlY2lzaW9uVHJlZV9tb2RlbCA8LSBycGFydChFc3RhdHVzIH4gICBFZGFkICsgR2VuZXJvICsgTWVzX0ZlY2hhX0FsdGEgKyBBw7FvX0ZlY2hhX0FsdGEgKyBQdWVzdG9fR3J1cG9zICsgRXN0YWRvICsgRXN0YWRvX0NpdmlsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gdHJhaW5fREZfUkgsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJjbGFzcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IHJwYXJ0LmNvbnRyb2woY3AgPSAwLjAxKSkgIyBMYSBmdW5jacOzbiBjcCBheXVkYSBhIHBvZGFyIGVsIMOBcmJvbCBkZSBEZWNpc2nDs24gcGFyYSBwcmV2ZW5pciBlbCBzb2JyZWFqdXN0ZSB5IGNvbnRyb2xhciBzdSBjb21wbGVqaWRhZC4gRW4gZXN0ZSBjYXNvIHNlIHRvbW8gbGEgZGVjaXNpw7NuIGRlIHF1ZSAwLjAxIGVyYSBlbCB2YWxvciDDs3B0aW1vLCB0cmFzIHZpc3VhbGl6YXIgdmFyaW9zIMOBcmJvbGVzIGRlIERlY2lzacOzbiBjb24gZGlzdGludG9zIHZhbG9yZXMgZGUgY3AuIA0KDQoNCnJwYXJ0LnBsb3QoRGVjaXNpb25UcmVlX21vZGVsKQ0KYGBgDQoNCg0KTG9zIGVtcGxlYWRvcyBkYWRvcyBkZSBhbHRhIGFudGVzIGRlbCBhw7FvIDIwMjQsIHRpZW5lbiB1biA4MyUgZGUgcHJvYmFiaWxpZGFkIGRlIGRhcnNlIGRlIGJhamEsIG1pZW50cmFzIHF1ZSBhcXVlbGxvcyBkYWRvcyBkZSBhbHRhIGRlc3B1w6lzIGRlbCAyMDI0IHRpZW5lbiB1biAxNyUgZGUgc2VndWlyIHNpZW5kbyBlbXBsZWFkb3MuICAgICANCg0KTG9zIGVtcGxlYWRvcyBkYWRvcyBkZSBhbHRhIGVuIGVsIDIwMjIgbyBkZXNwdcOpcyB5IHF1ZSBwZXJ0ZW5lemNhbiBhIHB1ZXN0b3MgcXVlIGVzdGVuIGRlbnRybyBkZSBsb3MgZ3J1cG9zIGRlICJBeXVkYW50ZSIsICJDaG9mZXIiLCAiTGlkZXIiLCAiTGltcGllemEiIHkgIlByb2R1Y2Npw7NuIHkgTG9nw61zdGljYSIsIHRpZW5lbiB1biA3NiUgZGUgcHJvYmFiaWxpZGFkIGRlIGRhcnNlIGRlIGJhamEuIExvcyBlbXBsZWFkb3MgZGFkb3MgZGUgYWx0YSBhbnRlcyBkZWwgMjAyMiB0aWVuZW4gdW4gNiUgZGUgcHJvYmFiaWxpZGFkIGRlIHNlZ3VpciB0cmFiYWphbmRvIGVuIEZPUk0sIHkgc2kgdGllbmVuIG1lbm9zIGRlIDU2IGHDsW9zIGxhIHByb2JhYmlsaWRhZCBkZSBzZWd1aXIgc2llbmRvIGVtcGxlYWRvcyBlcyBkZWwgNSUuICAgIA0KDQpMb3MgZW1wbGVhZG9zIGRhZG9zIGRlIGFsdGEgYW50ZXMgZGVsIDIwMjIsIGNvbiBtZW5vcyBkZSA1NiBhw7FvcyB5IHF1ZSBwZXJ0ZW5lemNhbiBhIHB1ZXN0b3MgcXVlIGVzdGVuIGRlbnRybyBkZSBsb3MgZ3J1cG9zIGRlICJBeXVkYW50ZSIsICJDaG9mZXIiLCAiTGlkZXIiLCAiTGltcGllemEiIHkgIlByb2R1Y2Npw7NuIHkgTG9nw61zdGljYSIsIHRpZW5lbiB1biAxJSBkZSBwcm9iYWJpbGlkYWQgZGUgc2VndWlyIHRyYWJhamFuZG8gZW4gRk9STSB5IDQlIGRlIHByb2JhYmlsaWRhZCBkZSBkYXJzZSBkZSBiYWphLiBFc3RhIGNvbWJpbmFjacOzbiBhdW5hZGEgYSBsYSB2YXJpYWJsZSBkZSBoYWJlciBzaWRvIGRhZG8gZGUgYWx0YSBlbiBtYXlvIG8gZGVzcHXDqXMgZGEgdW4gMiUgZGUgcHJvYmFiaWxpZGFkIGRlIHNlciB1bmEgYmFqYSB5IHVuIDIlIGRlIHNlciBlbXBsZWFkby4gICAgDQoNCg0KTG9zIGVtcGxlYWRvcyBkYWRvcyBkZSBhbHRhIGRlc3B1w6lzIGRlbCAyMDI0IHRpZW5lbiB1biAxNyUgZGUgcHJvYmFiaWxpZGFkIGRlIHNlZ3VpciB0cmFiYWphbmRvIGVuIEZPUk0uIExvcyBlbXBsZWFkb3MgZGFkb3MgZGUgYWx0YSBkZXNwdcOpcyBkZWwgMjAyNCB5IGFudGVzIGRlIG1hcnpvIHRpZW5lbiB1biA4JSBkZSBwcm9iYWJpbGlkYWQgZGUgZGFyc2UgZGUgYmFqYSB5IHVuIDEwJSBkZSBwcm9iYWJpbGlkYWQgZGUgc2VndWlyIHNpZW5kbyBlbXBsZWFkb3MuIExvcyBlbXBsZWFkb3MgZGFkb3MgZGUgYWx0YSBkZXNwdcOpcyBkZWwgMjAyNCwgYW50ZXMgZGUgbWFyem8geSBxdWUgdGVuZ2FuIHB1ZXN0b3MgcXVlIHBlcnRlbmV6Y2FuIGEgbG9zIGdydXBvcyBkZSAiQ2FsaWRhZCIgeSAiQ29zdHVyZXJvIiB0aWVuZW4gdW4gMSUgZGUgcHJvYmFiaWxpZGFkIGRlIGRhcnNlIGRlIGJhamEuIExvcyBlbXBsZWFkb3MgZGFkb3MgZGUgYWx0YSBkZXNwdcOpcyBkZWwgMjAyNCwgcXVlIHRlbmdhbiBwdWVzdG9zIHF1ZSBwZXJ0ZW5lemNhbiBhIGxvcyBncnVwb3MgZGUgIkNhbGlkYWQiIHkgIkNvc3R1cmVybyIgeSBoYXlhbiBzaWRvIGRhZG9zIGRlIGFsdGEgYW50ZXMgZGUgZmVicmVybyB0aWVuZW4gdW4gNCUgZGUgcHJvYmFiaWxpZGFkIGRlIGRhcnNlIGRlIGJhamEgeSB1biAzJSBkZSBzZWd1aXIgc2llbmRvIGVtcGxlYWRvcy4gIA0KDQpMb3MgZW1wbGVhZG9zIHF1ZSBwZXJ0ZW5lY2VuIGFsIGdydXBvICJQcm9kdWNjacOzbiB5IExvZ8Otc3RpY2EiIHNvbiBhcXVlbGxvcyBxdWUgdGllbmVuIGxvcyBwdWVzdG9zIGRlOiBBbG1hY2VuaXN0YSwgR2VzdG9yLCBNYXJjYWRvcmEsIE1hdGVyaWFsaXN0YSwgTW9udGFjYXJndWlzdGEsIE1vem8sIE9wZXJhZG9yLCBQaW50b3IgeSBTb2xkYWRvci4gTG9zIGVtcGxlYWRvcyBxdWUgcGVydGVuZWNlbiBhbCBncnVwbyAiQXl1ZGFudGUiIHRpZW5lbiBsb3MgcHVlc3RvcyBkZTogQXV4aWxpYXIgZGUgRW1iYXJxdWVzLCBBeXVkYW50ZSwgQXl1ZGFudGUgZGUgTWFudGVuaW1pZW50bywgQXl1ZGFudGUgZGUgU29sZGFkb3IsIEF5dWRhbnRlIEdlbmVyYWwgeSBBeXVkYW50ZSBnZW5lcmFsIENFRElTLiBNaWVudHJhcyBxdWUgbG9zIGVtcGxlYWRvcyBkZWwgZ3J1cG8gIkNob2ZlciIgdGllbmVuIGxvcyBwdWVzdG9zIGRlOiBDaG9mZXIsIENob2ZlciBDRURJUyB5IENob2ZlciBHZXN0b3IuIEZpbmFsbWVudGUsIGxvcyBlbXBsZWFkb3MgZGVsIGdydXBvICJDYWxpZGFkIiB0aWVuZW4gbG9zIHB1ZXN0b3MgZGU6IEluc3BlY3RvciBkZSBjYWxpZGFkIHkgQ2FsaWRhZC4gIA0KDQpBIHBlc2FyIGRlIHF1ZSBsYSBwcm9iYWJpbGlkYWQgbcOhcyBhbHRhIGRlIGRhcnNlIGRlIGJhamEgKDgzJSkgc2VhIHRlbmVyIHVuYSBmZWNoYSBkZSBhbHRhIGFudGVzIGRlbCAyMDI0LiBTb2xvIHNlIGVzdGEgY29uc2lkZXJhbmRvIHVuYSB2YXJpYWJsZSBxdWUgcHVlZGUgbGxlZ2FyIGEgc2VyIGFtYmlndWEgeSBkaWbDrWNpbCBkZSBhbmFsaXphci4gRXMgcG9yIGVzbyBxdWUgbGEgY29tYmluYWNpw7NuIGRlIGxhcyB2YXJpYWJsZXM6IEZlY2hhIGRlIGFsdGEgZW4gZWwgMjAyMiBvIGRlc3B1w6lzIHkgcXVlIHRlbmdhbiBwdWVzdG9zIHF1ZSBlc3RlbiBkZW50cm8gZGUgbG9zIGdydXBvcyBkZSAiQXl1ZGFudGUiLCAiQ2hvZmVyIiwgIkxpZGVyIiwgIkxpbXBpZXphIiB5ICJQcm9kdWNjacOzbiB5IExvZ8Otc3RpY2EiIHF1ZSBkYSB1biA3NiUgZGUgcHJvYmFiaWxpZGFkIGRlIHNlciBiYWphIGVzIG3DoXMgw7p0aWwgcGFyYSBpZGVudGlmaWNhciBsb3MgZmFjdG9yZXMgcXVlIGluZmx1eWVuIGRlIG1hbmVyYSBtw6FzIHNpZ25pZmljYXRpdmEgZW4gbGEgYWx0YSByb3RhY2nDs24gcXVlIHRpZW5lIEZPUk0uICANCg0KDQoNCioqTcOpdHJpY2FzKioNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIFByZWRlY2lyIGVuIGVsIGNvbmp1bnRvIGRlIHBydWViYQ0KcHJlZGljdGVkX3Byb2JzX0RGX1JIIDwtIHByZWRpY3QoRGVjaXNpb25UcmVlX21vZGVsLCBuZXdkYXRhID0gdGVzdF9ERl9SSCwgdHlwZSA9ICJwcm9iIilbLCAyXQ0KcHJlZGljdGVkX2xhYmVsc19ERl9SSCA8LSBwcmVkaWN0KERlY2lzaW9uVHJlZV9tb2RlbCwgbmV3ZGF0YSA9IHRlc3RfREZfUkgsIHR5cGUgPSAiY2xhc3MiKQ0KDQojIENvbnZlcnRpciBsYXMgZXRpcXVldGFzIHByZWRpY2hhcyBhIGZhY3RvciBjb24gbG9zIG1pc21vcyBuaXZlbGVzIHF1ZSBsYXMgY2xhc2VzIHJlYWxlcw0KcHJlZGljdGVkX2xhYmVsc19ERl9SSCA8LSBmYWN0b3IocHJlZGljdGVkX2xhYmVsc19ERl9SSCwgbGV2ZWxzID0gbGV2ZWxzKHRlc3RfREZfUkgkRXN0YXR1cykpDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KIyBNYXRyaXogZGUgY29uZnVzacOzbg0KY29uZnVzaW9uX21hdHJpeF9ERl9SSCA8LSBjb25mdXNpb25NYXRyaXgocHJlZGljdGVkX2xhYmVsc19ERl9SSCwgdGVzdF9ERl9SSCRFc3RhdHVzKQ0KY29uZnVzaW9uX21hdHJpeF9ERl9SSA0KYGBgDQoNCg0KKipDb25jbHVzacOzbioqICANCg0KQ29uc2lkZXJhbmRvIHF1ZSBlbCBvYmpldGl2byBlcyBpZGVudGlmaWNhciBsb3MgZmFjdG9yZXMgcXVlIGhhY2VuIHF1ZSBsb3MgZW1wbGVhZG9zIHNlIGRlbiBkZSBiYWphIGVuIEZPUk0sIGVsIG1vZGVsbyBkZSDDgXJib2wgZGUgRGVjaXNpw7NuIGVzIHVuIGJ1ZW4gbW9kZWxvLiBMYSBzZW5zaWJpbGlkYWQgZGVsIDAuOTQ0MCBpbmRpY2EgcXVlIGVsIG1vZGVsbyB0aWVuZSB1bmEgY2FwYWNpZGFkIGFsdGEgcGFyYSBpZGVudGlmaWNhciBjb3JyZWN0YW1lbnRlIGEgIGxvcyBlbXBsZWFkb3MgcXVlIHNlIGRhbiBkZSBiYWphLiBFc3RvIGVzIGNydWNpYWwgeWEgcXVlIGVsIG9iamV0aXZvIGVzIGVudGVuZGVyIHBvciBxdcOpIGxvcyBlbXBsZWFkb3Mgc2UgdmFuIGRlIGxhIGVtcHJlc2EuICANCg0KQXVucXVlIGxhIGVzcGVjaWZpY2lkYWQgZXMgYWxnbyBiYWphICgwLjYzMzMpLCBsbyBxdWUgaW5kaWNhIHF1ZSBlbCBtb2RlbG8gdGllbmUgZGlmaWN1bHRhZGVzIHBhcmEgaWRlbnRpZmljYXIgY29ycmVjdGFtZW50ZSBhIGxvcyBlbXBsZWFkb3MgcXVlIHBlcm1hbmVjZW4gZW4gbGEgZW1wcmVzYSwgZXN0byBubyBhZmVjdGEgc2lnbmlmaWNhdGl2YW1lbnRlLCB5YSBxdWUsIGVsIG9iamV0aXZvIHByaW5jaXBhbCBlcyBkZXRlY3RhciBsb3MgZmFjdG9yZXMgZGUgYmFqYS4gICAgIA0KDQpBZGVtw6FzLCBlbCBtb2RlbG8gY3VlbnRhIGNvbiB1bmEgYnVlbmEgcHJlY2lzacOzbiAoMC44ODM5KSwgbG8gcXVlIGluZGljYSBxdWUgY3VhbmRvIHByZWRpY2UgcXVlIHVuIGVtcGxlYWRvIHNlIGRhIGRlIGJhamEsIGVuIGVsIDg4LjM5JSBkZSBsb3MgY2Fzb3MsIGVzdGEgcHJlZGljY2nDs24gZXMgY29ycmVjdGEuIEVzdG8gc3VnaWVyZSBxdWUgbGFzIGRlY2lzaW9uZXMgdG9tYWRhcyBiYXNhZGFzIGVuIGVzdGFzIHByZWRpY2Npb25lcyBzZXLDoW4sIGVuIHN1IG1heW9yw61hLCBhY2VydGFkYXMuICANCg0KDQojIyMgU2VsZWNjacOzbiBkZSBtb2RlbG8gUlJISA0KRGVjaWRpbW9zIHF1ZSBwYXJhIGVsIGNhc28gZGUgUlJISCBlbCBtb2RlbG8gZGUgw4FyYm9sIGRlIERlY2lzacOzbiBwdWVkYSBzZXIgZWwgbcOhcyBhcHJvcGlhZG8gcGFyYSBudWVzdHJvIGNsaWVudGUuIFByaW5jaXBhbG1lbnRlIHBvcnF1ZSB0aWVuZSB1bmEgZ3JhbiBjYXBhY2lkYWQgZGUgY2FwdHVyYXIgaW50ZXJhY2Npb25lcy4gTG9zIMOBcmJvbGVzIGRlIERlY2lzacOzbiBwdWVkZW4gY2FwdHVyYXIgaW50ZXJhY2Npb25lcyBjb21wbGVqYXMgZW50cmUgdmFyaWFibGVzLiBFbiBlbCBjb250ZXh0byBkZSBsYSByb3RhY2nDs24gZGUgZW1wbGVhZG9zLCBlcyBwcm9iYWJsZSBxdWUgZmFjdG9yZXMgY29tbyBsYSBhbnRpZ8O8ZWRhZCB5IGVsIHB1ZXN0byBpbnRlcmFjdMO6ZW4gZGUgbWFuZXJhcyBubyBvYnZpYXMgcXVlIGVsIG1vZGVsbyBwdWVkZSBkZXRlY3Rhci4gVGVtYmnDqW4gcXVlcmVtb3MgcXVlIGxvcyBtb2RlbG9zIHRlbmdhbiB1bmEgbWF5b3IgaW50ZXJwcmV0YWJpbGlkYWQgdmlzdWFsLiBMb3Mgw4FyYm9sZXMgZGUgRGVjaXNpw7NuIHNvbiBmw6FjaWxtZW50ZSBpbnRlcnByZXRhYmxlcyB5IHZpc3VhbGl6YWJsZXMuIEVzdG8gcGVybWl0ZSBhIGxvcyByZXNwb25zYWJsZXMgZGUgcmVjdXJzb3MgaHVtYW5vcyBlbnRlbmRlciBjbGFyYW1lbnRlIHF1w6kgZmFjdG9yZXMgZXN0w6FuIGNvbnRyaWJ1eWVuZG8gYSBsYSByb3RhY2nDs24geSBjw7Ntby4gIA0KDQoNCiMgQ0hBVEJPVA0KDQohW10oQzpcXFVzZXJzXFxrYXRoaVxcT25lRHJpdmVcXEVzY3JpdG9yaW9cXEVWSURFTkNJQTJfSUFcXGNoYXRib3QucG5nKQ0KDQpFc3RlIGVzIHVuIGVqZW1wbG8gZGUgbG8gcXVlIGVsIGVxdWlwbyBoYSBsb2dyYWRvIGltcGxlbWVudGFyIGNvbiBlbCBDaGF0Qm90LiBFc3BlcmFtb3MgcXVlIGVzdGUgYm90IHB1ZWRhIGF5dWRhciBhIGxvcyBwcm9zcGVjdG9zIGEgdGVuZXIgaW5mb3JtYWNpw7NuIGRlIGlubWVkaWF0byB5IHF1ZSBwdWVkYSBhZ2lsaXphciBlbCBwcm9jZXNvIGRlIHByb3NwZWNjacOzbiB5IHNlbGVjY2nDs24gZGUgY2FuZGlkYXRvcy4NCg0KDQoNCg0KDQoNCg==