1. Introducción
Este informe tiene como objetivo principal realizar un análisis
exploratorio de los datos sobre un conjunto de datos sobre personas con
enfermedades del corazón, con sus características de forma anónima para
poder generar visualizaciones informativas sobre la relación que tienen
las variables entre sí, para poder comprender los datos de una mejor
manera, buscando patrones, identificando anomalías, etc.
2. Descripción del problema
Los problemas de corazón son cada vez más comunes en las sociedades
modernas, esto debido a muchos factores que afectan la salud física de
las personas, como la falta de actividad física, el consumo de comidas
que perjudican el estado del corazón y el resto del cuerpo, el consumo
de drogas, padecimientos previos como presión alta, diabetes, tiempos de
sueño irregulares, altos niveles de estrés. Estas y otras razones son
fuentes de problemas en el corazón en personas de todo el mundo.
Es por esto por lo que muchos especialistas en el tema recolectan
datos de las personas que pueden ayudar a confirmar si se tiene o no
algún padecimiento del corazón, o al menos se pueda utilizar como guía
para poder identificarlos temprano, como el conjunto de datos que se
utilizara en el presente análisis exploratorio de los datos.
3. Definición de fuentes de datos
El conjunto de datos que es usado para este análisis fue realizado
por Oktay Ördekci llamado Heart
Diseaseel cual contiene 21 indicadores de riesgo relacionados a los
problemas de salud. Como la edad, genero, presión en sangre, etc. Estos
datos fueron recolectados para analizar las posibilidades de riesgo en
padecimientos del control y ayudar a la investigación en temas de salud.
La siguiente tabla muestra todos los indicadores que contiene el
conjunto de datos, una breve descripcion de cada uno y los valores que
puede tomar.
Diccionario de variables
| Age |
La edad de cada individuo |
Numérico entero |
| Gender |
El género del individuo |
Male o Famale |
| Blood Preassure |
La presión en sangre del individuo |
Numérico entero |
| Cholesterol Level |
El nivel de colesterol de cada individuo |
Numérico entero |
| Exercise Habits |
Nivel de ejercicio del individuo |
Low(bajo), Medium(medio), High(alto) |
| Smoking |
Si el individuo fuma o no |
Yes o No |
| Family Heart Disease |
Si alguien en la familia tiene padecimientos en el
corazón |
Yes o No |
| Diabetes |
Si la persona padece de diabetes o no |
Yes o No |
| BMI |
Índice de masa corporal del individuo |
Numérico decimal |
| High Blood Pressure |
Si el individuo tiene presión de sangre alta |
Yes o No |
| Low HDL Cholesterol |
Si el individuo tiene bajo nivel de colesterol HDL |
Yes o No |
| High LDL Cholesterol |
Si el individuo tiene alto nivel de colesterol LDL |
Yes o No |
| Alcohol Consumption |
Cuanto alcohol consume el individuo |
None(nada), Low(poco), Medium(medio), High(alto) |
| Stress Level |
Nivel de estrés del individuo |
Low(bajo), Medium(medio), High(alto) |
| Sleep Hours |
Cantidad de horas de sueño del individuo |
Numérico decimal |
| Sugar Consumption |
Consumo de azúcar del individuo |
Low(bajo), Medium(medio), High(alto) |
| Triglyceride Level |
Nivel de triglicéridos del individuo |
Numérico entero |
| Fasting Blood Sugar |
Nivel de azúcar en sangre del individuo |
Numérico entero |
| CRP Level |
Nivel de la proteína C reactiva |
Numérico decimal |
| Homocysteine Level |
Nivel de homocisteína del individuo |
Numérico decimal |
| Heart Disease Status |
Si el individuo tiene o no problemas del corazón |
Yes o No |
Definiciones importantes
Colesterol: es una sustancia cerosa y grasa que
el cuerpo necesita para formar células saludables, hormonas y vitamina
D, es producido por el hígado y viaja por la sangre.
Diabetes: es una enfermedad crónica que se
caracteriza por altos niveles de glucosa en sangre, aparece cuando el
páncreas no produce suficiente insulina o el cuerpo no es capaz de
usarla.
Índice de Masa Corporal (BMI): es una medida que
usa el peso y la estatura para estimar la grasa corporal y evaluar el
riesgo de la salud en adultos, es decir si tiene sobrepeso u obesidad,
se calcula mediante la siguiente formula: \[BMI = \frac{Peso (kg)}{Altura
(m^2)}\]
HDL Colesterol: lipoproteína de alta densidad es
conocido como el colesterol “bueno”, porque transporta el colesterol del
cuerpo al hígado para ser destruido, reduciendo el riesgo de
enfermedades cardiacas.
LDL Colesterol: lipoproteína de baja densidad es
conocido como el colesterol “malo”, porque transporta colesterol a las
células, pero cuando sus niveles son altos estos se acumulan en las
paredes de las arterias, estrechándolas y provocando su endurecimiento,
lo que aumenta el riesgo de ataques cardiacos.
Triglicéridos: es el tipo más común de grasa
(lípido) en el cuerpo, el cual es esencial para proporcionar energía,
cuando hay niveles altos en sangre, por encima de 200mg/dl aumentan los
riesgos de enfermedades cardiacas.
CRP level: mide la inflamación en el cuerpo, es
producida por el hígado y sus niveles aumentan cuando hay infecciones,
lesiones o enfermedades crónicas, mientras mayor nivel indica que hay
alta inflación del cuerpo.
Homocisteína: es un aminoácido presente en la
sangre que se produce al descomponer proteínas. En niveles altos daña
las arterias y aumentan el riesgo de enfermedades
cardiovasculares.
4. Descripción detallada y explicación de las gráficas
Gráficas unidimencionales
- Gráfica 1 Distribución de individuos por edad.
La gráfica de burbujas anterior demuestra mediante una serie de
burbujas la distribución de la edad de los individuos del conjunto de
datos, donde las burbujas más pequeñas representan que tienen menos
individuos en esa edad, mientras las más grandes representan que hay
mayor cantidad de individuos, la posición de izquierda a derecha indica
la edad, siendo la izquierda la menor y la derecha la mayor. Observar
esta visualización nos permite ver que hay una distribución bastante
pareja de los datos, ya que la mayoria de las burbujas rondan un tamaño
similar, lo que representa que en promedio por cada edad hay de 150 a
160 individuos, así mismo, podemos identificar ciertos extremos muy
facilmente como es el caso de la edad 48, que es la que posee menor
cantidad de individuos relacionados.
- Gráfica 2 Distribución de individuos por
género.
La gráfica de pastel anterior permite ver la distribucion de
individos “Male”, “Female” o “Nulos”, donde los nulos son los datos que
estan vacios, con 0 o en blanco. Se puede ver que hay una distribucion
casi 50-50 entre los géneros masculino y femenino, sin embargo, hay un
0.02% mas de individuos masulinos que femeninos. El conjunto de datos
posee datos de 5003 individuos masculinos y
4978 individuos femeninos y 19
individuos que no estan registrados. Esto nos permite comprender que el
conjunto de datos esta balanceado entre masculinos y femeninos.
- Gráfica 3 Distribución de individuos con antecedentes
familiares de enfermedades del corazón.
La gráfica de barras anterior muestra la distribución de las
respuestas de los individuos sobre si possen antecedentes de problemas
en el corazón, lo que nos deja la siguiente información relevante,
5004 individuos no tienen atecedentes familiares hay
21 individuos que respondieron en blanco, mientras que,
4975 individuos si lo posee, lo que indica que podria
haber un poco de probabilidad de que esos individuos. Lo que, al igual
que las graficas anteriores demuestra que los datos están practicamente
balanceados
Gráficas bidimencionales
- Gráfica 1: Consumo de Azúcar vs Niveles de Glucosa en
Ayunas
Esta gráfica permite evaluar como un hábito de consumo afecta un
indicador clínico. Al hacer uso de los notch en las cajas, permite
identificar de forma interactiva si las medias e glucosa varían
significativamente según el nuvel de azúcar ingerido. Si se quisiera
indagar más, esto ayudaría a validar si la dieta es un factor
determinante en los niveles de azúcar en sangre de los pacientes.
- Gráfica 2: Concentración de Colesterol según Nivel de Estrés
Se hace uso de un gráfico de violín interactivo para observar la
densidad de los niveles de colesterol según el estrés del paciente. Al
analizar la forma de la distribución, el EDA revela un patrón
interesante: los datos se distribuyen de manera casi uniforme en todos
los niveles. Esto nos indica estadísticamente que, en este conjunto de
datos específico, el nivel de estrés no altera significativamente la
concentración de colesterol
Gráficas multidimencionales
- Gráfica 1 Distribución de individuos por habitos
individuales, ejercicio, nivel de estres, horas de sueño, consumo de
azucar y problemas del corazón.
La matriz de dispersión en escalera permite ver una comparatica de 5
dimensiones, horas de sueño redondeadas, consumo de azucar, nivel de
estrés, si es fumador y la cantidad de ejercicio que se realiza
comparando cada una con las demás, donde cada gráfica representa la
comparación de dos variables, mediante mapas de calor interactivos, la
intensidad del color azul funciona como un indicador de densidad
demográfica, lo que permite ver a simple vista la cantidad de personas
que cumplen con dichas caracteristicas. Para poder ver los datos, solo
se pasa por encima el mouse para ver los datos.
Gráfica de facetas
- Gráfica 1: Relación de Edad y BMI dividida por
Tabaquismo
Para esta visualización se hace uso de la técnica de facetas que
permite integrar 4 variables simultáneamente: Edad en el eje X, BMI en
el eje Y, Estado Cardíaco representado con el Color y Tabaquismo en los
Paneles separados. Al dividir la población entre fumadores y no
fumadores, se puede explorar de manera interactiva si los puntos rojos,
es decir, pacientes con enfermedad, tienden a concentrarse en zonas de
mayor edad o mayor peso dependiendo de su hábito de fumar.
Gráfica compuesta
- Gráfica 1: Dashboard Integrado de Factores
Clínicos
Esta imagen compuesta integra las dos gráficas bidimensionales
generadas anteriormente en un solo dashboard. La ventaja es que permite
comparar múltiples factores de riesgo biológico y de comportamiento en
una sola pantalla, e igual se mantinenen las capacidades de
interacción.
5. Conclusiones
Tras realizar el EDA sobre este conjunto del total de registros, el
proceso de storytelling visual nos ha permitido transformar datos crudos
en hallazgos clave sobre los factores de riesgo en enfermedades
cardíacas:
Balance y calidad de la muestra: El análisis
unidimensional reveló que el conjunto de datos está excepcionalmente
balanceado en términos demográficos. La distribución casi simétrica
entre los géneros (5003 masculinos y 4978 femeninos) y la proporción
equitativa de antecedentes familiares, garantizan que los patrones
descubiertos no estén sesgados hacia un grupo poblacional
específico.
Desmitificación de variables aisladas: Una de
las revelaciones más valiosas surgió en el análisis bidimensional.
Contrario a la creencia popular de que el estrés dispara automáticamente
el colesterol, las gráficas de violín demostraron una distribución
uniforme; es decir, en esta población particular, el nivel de estrés por
sí solo no altera de forma estadísticamente significativa la
concentración de colesterol. Esto indica que no se debe diagnosticar el
riesgo basándose en un solo factor aislado.
El poder de los factores combinados: El
verdadero valor predictivo se observó al cruzar múltiples dimensiones.
Gracias a las gráficas de facetas y la matriz de calor multidimensional,
quedó en evidencia que las enfermedades del corazón no dependen de un
solo mal hábito, sino de la acumulación de estos. La interacción
simultánea entre una mayor edad, un BMI elevado y el Smoking agrupa
visualmente a los pacientes con estado cardíaco positivo encHeart
Disease Status.
Accionabilidad: A nivel médico y preventivo,
este análisis sugiere que las campañas de salud no deben enfocarse
únicamente en reducir el estrés o el consumo de azúcar de forma aislada.
Deben diseñarse intervenciones integrales dirigidas a los “perfiles
combinados” de alto riesgo (por ejemplo: pacientes de edad avanzada, con
alto BMI y fumadores activos).
Para finalizar, el desarrollo de este EDA demuestra la importancia
del storytelling con los datos. Al transformar registros complejos en
gráficas interactivas y narrativas claras, se facilita por mucho la
comprensión de la información. Gracias a la limpieza, estructuración y
ausencia de sesgos demográficos comprobados, este conjunto de datos
resulta ser un candidato ideal para el diseño de dashboards médicos.
Estas herramientas visuales permitirían a los profesionales de la salud
explorar tendencias, aislar variables interactivamente y comunicar
riesgos a los pacientes de forma transparente y efectiva, cumpliendo así
con el objetivo fundamental de la visualización de la información.
LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBFeHBsb3JhdG9yaW8gZGUgRGF0b3M6IEVuZmVybWVkYWRlcyBkZWwgQ29yYXrDs24iDQphdXRob3I6ICJSYWZhZWwgQXJheWEgeSBPdHRvIFNlZ3VyYSINCmRhdGU6ICIxMiBkZSBhYnJpbCwgMjAyNiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIDEuIEludHJvZHVjY2nDs24NCkVzdGUgaW5mb3JtZSB0aWVuZSBjb21vIG9iamV0aXZvIHByaW5jaXBhbCByZWFsaXphciB1biBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGxvcyBkYXRvcyBzb2JyZSB1biBjb25qdW50byBkZSBkYXRvcyBzb2JyZSBwZXJzb25hcyBjb24gZW5mZXJtZWRhZGVzIGRlbCBjb3JhesOzbiwgY29uIHN1cyBjYXJhY3RlcsOtc3RpY2FzIGRlIGZvcm1hIGFuw7NuaW1hIHBhcmEgcG9kZXIgZ2VuZXJhciB2aXN1YWxpemFjaW9uZXMgaW5mb3JtYXRpdmFzIHNvYnJlIGxhIHJlbGFjacOzbiBxdWUgdGllbmVuIGxhcyB2YXJpYWJsZXMgZW50cmUgc8OtLCBwYXJhIHBvZGVyIGNvbXByZW5kZXIgbG9zIGRhdG9zIGRlIHVuYSBtZWpvciBtYW5lcmEsIGJ1c2NhbmRvIHBhdHJvbmVzLCBpZGVudGlmaWNhbmRvIGFub21hbMOtYXMsIGV0Yy4gDQoNCi0tLQ0KDQojIyAyLiBEZXNjcmlwY2nDs24gZGVsIHByb2JsZW1hDQpMb3MgcHJvYmxlbWFzIGRlIGNvcmF6w7NuIHNvbiBjYWRhIHZleiBtw6FzIGNvbXVuZXMgZW4gbGFzIHNvY2llZGFkZXMgbW9kZXJuYXMsIGVzdG8gZGViaWRvIGEgbXVjaG9zIGZhY3RvcmVzIHF1ZSBhZmVjdGFuIGxhIHNhbHVkIGbDrXNpY2EgZGUgbGFzIHBlcnNvbmFzLCBjb21vIGxhIGZhbHRhIGRlIGFjdGl2aWRhZCBmw61zaWNhLCBlbCBjb25zdW1vIGRlIGNvbWlkYXMgcXVlIHBlcmp1ZGljYW4gZWwgZXN0YWRvIGRlbCBjb3JhesOzbiB5IGVsIHJlc3RvIGRlbCBjdWVycG8sIGVsIGNvbnN1bW8gZGUgZHJvZ2FzLCBwYWRlY2ltaWVudG9zIHByZXZpb3MgY29tbyBwcmVzacOzbiBhbHRhLCBkaWFiZXRlcywgdGllbXBvcyBkZSBzdWXDsW8gaXJyZWd1bGFyZXMsIGFsdG9zIG5pdmVsZXMgZGUgZXN0csOpcy4gRXN0YXMgeSBvdHJhcyByYXpvbmVzIHNvbiBmdWVudGVzIGRlIHByb2JsZW1hcyBlbiBlbCBjb3JhesOzbiBlbiBwZXJzb25hcyBkZSB0b2RvIGVsIG11bmRvLg0KDQpFcyBwb3IgZXN0byBwb3IgbG8gcXVlIG11Y2hvcyBlc3BlY2lhbGlzdGFzIGVuIGVsIHRlbWEgcmVjb2xlY3RhbiBkYXRvcyBkZSBsYXMgcGVyc29uYXMgcXVlIHB1ZWRlbiBheXVkYXIgYSBjb25maXJtYXIgc2kgc2UgdGllbmUgbyBubyBhbGfDum4gcGFkZWNpbWllbnRvIGRlbCBjb3JhesOzbiwgbyBhbCBtZW5vcyBzZSBwdWVkYSB1dGlsaXphciBjb21vIGd1w61hIHBhcmEgcG9kZXIgaWRlbnRpZmljYXJsb3MgdGVtcHJhbm8sIGNvbW8gZWwgY29uanVudG8gZGUgZGF0b3MgcXVlIHNlIHV0aWxpemFyYSBlbiBlbCBwcmVzZW50ZSBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGxvcyBkYXRvcy4NCg0KDQotLS0NCg0KIyMgMy4gRGVmaW5pY2nDs24gZGUgZnVlbnRlcyBkZSBkYXRvcw0KRWwgY29uanVudG8gZGUgZGF0b3MgcXVlIGVzIHVzYWRvIHBhcmEgZXN0ZSBhbsOhbGlzaXMgZnVlIHJlYWxpemFkbyBwb3IgT2t0YXkgw5ZyZGVrY2kgbGxhbWFkbyBbSGVhcnQgRGlzZWFzZV0oIGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvb2t0YXlyZGVraS9oZWFydC1kaXNlYXNlICllbCBjdWFsIGNvbnRpZW5lIDIxIGluZGljYWRvcmVzIGRlIHJpZXNnbyByZWxhY2lvbmFkb3MgYSBsb3MgcHJvYmxlbWFzIGRlIHNhbHVkLiBDb21vIGxhIGVkYWQsIGdlbmVybywgcHJlc2nDs24gZW4gc2FuZ3JlLCBldGMuIEVzdG9zIGRhdG9zIGZ1ZXJvbiByZWNvbGVjdGFkb3MgcGFyYSBhbmFsaXphciBsYXMgcG9zaWJpbGlkYWRlcyBkZSByaWVzZ28gZW4gcGFkZWNpbWllbnRvcyBkZWwgY29udHJvbCB5IGF5dWRhciBhIGxhIGludmVzdGlnYWNpw7NuIGVuIHRlbWFzIGRlIHNhbHVkLiBMYSBzaWd1aWVudGUgdGFibGEgbXVlc3RyYSB0b2RvcyBsb3MgaW5kaWNhZG9yZXMgcXVlIGNvbnRpZW5lIGVsIGNvbmp1bnRvIGRlIGRhdG9zLCB1bmEgYnJldmUgZGVzY3JpcGNpb24gZGUgY2FkYSB1bm8geSBsb3MgdmFsb3JlcyBxdWUgcHVlZGUgdG9tYXIuIA0KDQojIyMgRGljY2lvbmFyaW8gZGUgdmFyaWFibGVzDQp8IEluZGljYWRvciB8IERlc2NyaXBjacOzbiB8IFZhbG9yZXMgfA0KfCA6LS0tIHwgOi0tLSB8IDotLS0gfA0KfCAqKkFnZSoqIHwgTGEgZWRhZCBkZSBjYWRhIGluZGl2aWR1byB8IE51bcOpcmljbyBlbnRlcm8gfA0KfCAqKkdlbmRlcioqIHwgRWwgZ8OpbmVybyBkZWwgaW5kaXZpZHVvIHwgTWFsZSBvIEZhbWFsZSB8DQp8ICoqQmxvb2QgUHJlYXNzdXJlKiogfCBMYSBwcmVzacOzbiBlbiBzYW5ncmUgZGVsIGluZGl2aWR1byB8IE51bcOpcmljbyBlbnRlcm8gfA0KfCAqKkNob2xlc3Rlcm9sIExldmVsKiogfCBFbCBuaXZlbCBkZSBjb2xlc3Rlcm9sIGRlIGNhZGEgaW5kaXZpZHVvIHwgTnVtw6lyaWNvIGVudGVybyB8DQp8ICoqRXhlcmNpc2UgSGFiaXRzKiogfCBOaXZlbCBkZSBlamVyY2ljaW8gZGVsIGluZGl2aWR1byB8IExvdyhiYWpvKSwgTWVkaXVtKG1lZGlvKSwgSGlnaChhbHRvKSB8DQp8ICoqU21va2luZyoqIHwgU2kgZWwgaW5kaXZpZHVvIGZ1bWEgbyBubyB8IFllcyBvIE5vIHwNCnwgKipGYW1pbHkgSGVhcnQgRGlzZWFzZSoqIHwgU2kgYWxndWllbiBlbiBsYSBmYW1pbGlhIHRpZW5lIHBhZGVjaW1pZW50b3MgZW4gZWwgY29yYXrDs24gfCBZZXMgbyBObyB8DQp8ICoqRGlhYmV0ZXMqKiB8IFNpIGxhIHBlcnNvbmEgcGFkZWNlIGRlIGRpYWJldGVzIG8gbm8gfCBZZXMgbyBObyB8DQp8ICoqQk1JKiogfCDDjW5kaWNlIGRlIG1hc2EgY29ycG9yYWwgZGVsIGluZGl2aWR1byB8IE51bcOpcmljbyBkZWNpbWFsIHwNCnwgKipIaWdoIEJsb29kIFByZXNzdXJlKiogfCBTaSBlbCBpbmRpdmlkdW8gdGllbmUgcHJlc2nDs24gZGUgc2FuZ3JlIGFsdGEgfCBZZXMgbyBObyB8DQp8ICoqTG93IEhETCBDaG9sZXN0ZXJvbCoqIHwgU2kgZWwgaW5kaXZpZHVvIHRpZW5lIGJham8gbml2ZWwgZGUgY29sZXN0ZXJvbCBIREwgfCBZZXMgbyBObyB8DQp8ICoqSGlnaCBMREwgQ2hvbGVzdGVyb2wqKiB8IFNpIGVsIGluZGl2aWR1byB0aWVuZSBhbHRvIG5pdmVsIGRlIGNvbGVzdGVyb2wgTERMIHwgWWVzIG8gTm8gfA0KfCAqKkFsY29ob2wgQ29uc3VtcHRpb24qKiB8IEN1YW50byBhbGNvaG9sIGNvbnN1bWUgZWwgaW5kaXZpZHVvIHwgTm9uZShuYWRhKSwgTG93KHBvY28pLCBNZWRpdW0obWVkaW8pLCBIaWdoKGFsdG8pIHwNCnwgKipTdHJlc3MgTGV2ZWwqKiB8IE5pdmVsIGRlIGVzdHLDqXMgZGVsIGluZGl2aWR1byB8IExvdyhiYWpvKSwgTWVkaXVtKG1lZGlvKSwgSGlnaChhbHRvKSB8DQp8ICoqU2xlZXAgSG91cnMqKiB8IENhbnRpZGFkIGRlIGhvcmFzIGRlIHN1ZcOxbyBkZWwgaW5kaXZpZHVvIHwgTnVtw6lyaWNvIGRlY2ltYWwgfA0KfCAqKlN1Z2FyIENvbnN1bXB0aW9uKiogfCBDb25zdW1vIGRlIGF6w7pjYXIgZGVsIGluZGl2aWR1byB8IExvdyhiYWpvKSwgTWVkaXVtKG1lZGlvKSwgSGlnaChhbHRvKSB8DQp8ICoqVHJpZ2x5Y2VyaWRlIExldmVsKiogfCBOaXZlbCBkZSB0cmlnbGljw6lyaWRvcyBkZWwgaW5kaXZpZHVvIHwgTnVtw6lyaWNvIGVudGVybyB8DQp8ICoqRmFzdGluZyBCbG9vZCBTdWdhcioqIHwgTml2ZWwgZGUgYXrDumNhciBlbiBzYW5ncmUgZGVsIGluZGl2aWR1byB8IE51bcOpcmljbyBlbnRlcm8gfA0KfCAqKkNSUCBMZXZlbCoqIHwgTml2ZWwgZGUgbGEgcHJvdGXDrW5hIEMgcmVhY3RpdmEgfCBOdW3DqXJpY28gZGVjaW1hbCB8DQp8ICoqSG9tb2N5c3RlaW5lIExldmVsKiogfCBOaXZlbCBkZSBob21vY2lzdGXDrW5hIGRlbCBpbmRpdmlkdW8gfCBOdW3DqXJpY28gZGVjaW1hbCB8DQp8ICoqSGVhcnQgRGlzZWFzZSBTdGF0dXMqKiB8IFNpIGVsIGluZGl2aWR1byB0aWVuZSBvIG5vIHByb2JsZW1hcyBkZWwgY29yYXrDs24gfCBZZXMgbyBObyB8DQoNCiMjIyBEZWZpbmljaW9uZXMgaW1wb3J0YW50ZXMNCiogKipDb2xlc3Rlcm9sKio6IGVzIHVuYSBzdXN0YW5jaWEgY2Vyb3NhIHkgZ3Jhc2EgcXVlIGVsIGN1ZXJwbyBuZWNlc2l0YSBwYXJhIGZvcm1hciBjw6lsdWxhcyBzYWx1ZGFibGVzLCBob3Jtb25hcyB5IHZpdGFtaW5hIEQsIGVzIHByb2R1Y2lkbyBwb3IgZWwgaMOtZ2FkbyB5IHZpYWphIHBvciBsYSBzYW5ncmUuIA0KKiAqKkRpYWJldGVzKio6IGVzIHVuYSBlbmZlcm1lZGFkIGNyw7NuaWNhIHF1ZSBzZSBjYXJhY3Rlcml6YSBwb3IgYWx0b3Mgbml2ZWxlcyBkZSBnbHVjb3NhIGVuIHNhbmdyZSwgYXBhcmVjZSBjdWFuZG8gZWwgcMOhbmNyZWFzIG5vIHByb2R1Y2Ugc3VmaWNpZW50ZSBpbnN1bGluYSBvIGVsIGN1ZXJwbyBubyBlcyBjYXBheiBkZSB1c2FybGEuIA0KDQoqICoqw41uZGljZSBkZSBNYXNhIENvcnBvcmFsIChCTUkpOioqIGVzIHVuYSBtZWRpZGEgcXVlIHVzYSBlbCBwZXNvIHkgbGEgZXN0YXR1cmEgcGFyYSBlc3RpbWFyIGxhIGdyYXNhIGNvcnBvcmFsIHkgZXZhbHVhciBlbCByaWVzZ28gZGUgbGEgc2FsdWQgZW4gYWR1bHRvcywgZXMgZGVjaXIgc2kgdGllbmUgc29icmVwZXNvIHUgb2Jlc2lkYWQsIHNlIGNhbGN1bGEgbWVkaWFudGUgbGEgc2lndWllbnRlIGZvcm11bGE6DQokJEJNSSA9IFxmcmFje1Blc28gKGtnKX17QWx0dXJhIChtXjIpfSQkDQoqICoqSERMIENvbGVzdGVyb2wqKjogbGlwb3Byb3Rlw61uYSBkZSBhbHRhIGRlbnNpZGFkIGVzIGNvbm9jaWRvIGNvbW8gZWwgY29sZXN0ZXJvbCDigJxidWVub+KAnSwgcG9ycXVlIHRyYW5zcG9ydGEgZWwgY29sZXN0ZXJvbCBkZWwgY3VlcnBvIGFsIGjDrWdhZG8gcGFyYSBzZXIgZGVzdHJ1aWRvLCByZWR1Y2llbmRvIGVsIHJpZXNnbyBkZSBlbmZlcm1lZGFkZXMgY2FyZGlhY2FzLiANCiogKipMREwgQ29sZXN0ZXJvbCoqOiBsaXBvcHJvdGXDrW5hIGRlIGJhamEgZGVuc2lkYWQgZXMgY29ub2NpZG8gY29tbyBlbCBjb2xlc3Rlcm9sIOKAnG1hbG/igJ0sIHBvcnF1ZSB0cmFuc3BvcnRhIGNvbGVzdGVyb2wgYSBsYXMgY8OpbHVsYXMsIHBlcm8gY3VhbmRvIHN1cyBuaXZlbGVzIHNvbiBhbHRvcyBlc3RvcyBzZSBhY3VtdWxhbiBlbiBsYXMgcGFyZWRlcyBkZSBsYXMgYXJ0ZXJpYXMsIGVzdHJlY2jDoW5kb2xhcyB5IHByb3ZvY2FuZG8gc3UgZW5kdXJlY2ltaWVudG8sIGxvIHF1ZSBhdW1lbnRhIGVsIHJpZXNnbyBkZSBhdGFxdWVzIGNhcmRpYWNvcy4gDQoqICoqVHJpZ2xpY8Opcmlkb3MqKjogZXMgZWwgdGlwbyBtw6FzIGNvbcO6biBkZSBncmFzYSAobMOtcGlkbykgZW4gZWwgY3VlcnBvLCBlbCBjdWFsIGVzIGVzZW5jaWFsIHBhcmEgcHJvcG9yY2lvbmFyIGVuZXJnw61hLCBjdWFuZG8gaGF5IG5pdmVsZXMgYWx0b3MgZW4gc2FuZ3JlLCBwb3IgZW5jaW1hIGRlIDIwMG1nL2RsIGF1bWVudGFuIGxvcyByaWVzZ29zIGRlIGVuZmVybWVkYWRlcyBjYXJkaWFjYXMuIA0KKiAqKkNSUCBsZXZlbCoqOiBtaWRlIGxhIGluZmxhbWFjacOzbiBlbiBlbCBjdWVycG8sIGVzIHByb2R1Y2lkYSBwb3IgZWwgaMOtZ2FkbyB5IHN1cyBuaXZlbGVzIGF1bWVudGFuIGN1YW5kbyBoYXkgaW5mZWNjaW9uZXMsIGxlc2lvbmVzIG8gZW5mZXJtZWRhZGVzIGNyw7NuaWNhcywgbWllbnRyYXMgbWF5b3Igbml2ZWwgaW5kaWNhIHF1ZSBoYXkgYWx0YSBpbmZsYWNpw7NuIGRlbCBjdWVycG8uIA0KKiAqKkhvbW9jaXN0ZcOtbmEqKjogZXMgdW4gYW1pbm/DoWNpZG8gcHJlc2VudGUgZW4gbGEgc2FuZ3JlIHF1ZSBzZSBwcm9kdWNlIGFsIGRlc2NvbXBvbmVyIHByb3Rlw61uYXMuIEVuIG5pdmVsZXMgYWx0b3MgZGHDsWEgbGFzIGFydGVyaWFzIHkgYXVtZW50YW4gZWwgcmllc2dvIGRlIGVuZmVybWVkYWRlcyBjYXJkaW92YXNjdWxhcmVzLiANCg0KDQotLS0NCg0KIyMgNC4gRGVzY3JpcGNpw7NuIGRldGFsbGFkYSB5IGV4cGxpY2FjacOzbiBkZSBsYXMgZ3LDoWZpY2FzDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQojaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCiNpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQojaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQojaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikNCmRhdGEgPC0gcmVhZC5jc3YoImRhdGEvaGVhcnRfZGlzZWFzZS5jc3YiKQ0KYGBgDQoNCiMjIyAqKkdyw6FmaWNhcyB1bmlkaW1lbmNpb25hbGVzKioNCg0KKiAqKkdyw6FmaWNhIDEgRGlzdHJpYnVjacOzbiBkZSBpbmRpdmlkdW9zIHBvciBlZGFkLioqDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCmRhdGEgPC0gcmVhZC5jc3YoImRhdGEvaGVhcnRfZGlzZWFzZS5jc3YiKQ0KDQpkYXRhX2J1cmJ1amFzIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KEFnZSkgJT4lDQogIHN1bW1hcmlzZShDYW50aWRhZCA9IG4oKSkNCg0KZmlnIDwtIHBsb3RfbHkoZGF0YV9idXJidWphcywgeCA9IH5BZ2UsIHkgPSB+Q2FudGlkYWQsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbWFya2Vycycsc2l6ZSA9IH5DYW50aWRhZCwgY29sb3IgPSB+YXMuZmFjdG9yKEFnZSksbWFya2VyID0gbGlzdChzaXplbW9kZSA9ICdkaWFtZXRlcicsIG9wYWNpdHkgPSAwLjcsIGxpbmUgPSBsaXN0KHdpZHRoID0gMSwgY29sb3IgPSAnI0ZGRkZGRicpKSkNCg0KZmlnIDwtIGZpZyAlPiUgbGF5b3V0KA0KICAgIHRpdGxlID0gJ0Rpc3RyaWJ1Y2nDs24gZGUgaW5kaXZpZHVvcyBwb3IgZWRhZCcsDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0VkYWQnLCBzaG93Z3JpZCA9IEZBTFNFKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnQ2FudGlkYWQgZGUgaW5kaXZpZHVvcycsIHNob3dncmlkID0gRkFMU0UpLA0KICAgIHNob3dsZWdlbmQgPSBGQUxTRQ0KICApDQoNCmZpZw0KDQpgYGANCg0KTGEgZ3LDoWZpY2EgZGUgYnVyYnVqYXMgYW50ZXJpb3IgZGVtdWVzdHJhIG1lZGlhbnRlIHVuYSBzZXJpZSBkZSBidXJidWphcyBsYSBkaXN0cmlidWNpw7NuIGRlIGxhIGVkYWQgZGUgbG9zIGluZGl2aWR1b3MgZGVsIGNvbmp1bnRvIGRlIGRhdG9zLCBkb25kZSBsYXMgYnVyYnVqYXMgbcOhcyBwZXF1ZcOxYXMgcmVwcmVzZW50YW4gcXVlIHRpZW5lbiBtZW5vcyBpbmRpdmlkdW9zIGVuIGVzYSBlZGFkLCBtaWVudHJhcyBsYXMgbcOhcyBncmFuZGVzIHJlcHJlc2VudGFuIHF1ZSBoYXkgbWF5b3IgY2FudGlkYWQgZGUgaW5kaXZpZHVvcywgbGEgcG9zaWNpw7NuIGRlIGl6cXVpZXJkYSBhIGRlcmVjaGEgaW5kaWNhIGxhIGVkYWQsIHNpZW5kbyBsYSBpenF1aWVyZGEgbGEgbWVub3IgeSBsYSBkZXJlY2hhIGxhIG1heW9yLiBPYnNlcnZhciBlc3RhIHZpc3VhbGl6YWNpw7NuIG5vcyBwZXJtaXRlIHZlciBxdWUgaGF5IHVuYSBkaXN0cmlidWNpw7NuIGJhc3RhbnRlIHBhcmVqYSBkZSBsb3MgZGF0b3MsIHlhIHF1ZSBsYSBtYXlvcmlhIGRlIGxhcyBidXJidWphcyByb25kYW4gdW4gdGFtYcOxbyBzaW1pbGFyLCBsbyBxdWUgcmVwcmVzZW50YSBxdWUgZW4gcHJvbWVkaW8gcG9yIGNhZGEgZWRhZCBoYXkgZGUgMTUwIGEgMTYwIGluZGl2aWR1b3MsIGFzw60gbWlzbW8sIHBvZGVtb3MgaWRlbnRpZmljYXIgY2llcnRvcyBleHRyZW1vcyBtdXkgZmFjaWxtZW50ZSBjb21vIGVzIGVsIGNhc28gZGUgbGEgZWRhZCA0OCwgcXVlIGVzIGxhIHF1ZSBwb3NlZSBtZW5vciBjYW50aWRhZCBkZSBpbmRpdmlkdW9zIHJlbGFjaW9uYWRvcy4gDQoNCiogKipHcsOhZmljYSAyIERpc3RyaWJ1Y2nDs24gZGUgaW5kaXZpZHVvcyBwb3IgZ8OpbmVyby4qKg0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KDQpkYXRhIDwtIHJlYWQuY3N2KCJkYXRhL2hlYXJ0X2Rpc2Vhc2UuY3N2IikNCg0KZGF0YV9nZW4gPC0gZGF0YSAlPiUNCiAgbXV0YXRlKEdlbmRlciA9IGNhc2Vfd2hlbihHZW5kZXIgPT0gIk1hbGUiIH4gIk1hc2N1bGlubyIsR2VuZGVyID09ICJGZW1hbGUiIH4gIkZlbWVuaW5vIixUUlVFIH4gIk51bG9zIg0KICApKSAlPiUNCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUNCiAgc3VtbWFyaXNlKENhbnRpZGFkID0gbigpKQ0KDQoNCmZpZyA8LSBwbG90X2x5KGRhdGFfZ2VuLCBsYWJlbHMgPSB+R2VuZGVyLCB2YWx1ZXMgPSB+Q2FudGlkYWQsIHR5cGUgPSAncGllJywgbWFya2VyID0gbGlzdChjb2xvcnMgPSBjKCcjRjA2MjkyJywgJyMxRTg4RTUnLCAnI0JEQzNDNycpKSkgDQoNCmZpZyA8LSBmaWcgJT4lIGxheW91dCh0aXRsZSA9ICdEaXN0cmlidWNpw7NuIGRlIGluZGl2aWR1b3MgcG9yIGfDqW5lcm8nLCB4YXhpcyA9IGxpc3Qoc2hvd2dyaWQgPSBGQUxTRSwgemVyb2xpbmUgPSBGQUxTRSwgc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSksIHlheGlzID0gbGlzdChzaG93Z3JpZCA9IEZBTFNFLCB6ZXJvbGluZSA9IEZBTFNFLCBzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCmZpZw0KYGBgDQpMYSBncsOhZmljYSBkZSBwYXN0ZWwgYW50ZXJpb3IgcGVybWl0ZSB2ZXIgbGEgZGlzdHJpYnVjaW9uIGRlIGluZGl2aWRvcyAiTWFsZSIsICJGZW1hbGUiIG8gIk51bG9zIiwgZG9uZGUgbG9zIG51bG9zIHNvbiBsb3MgZGF0b3MgcXVlIGVzdGFuIHZhY2lvcywgY29uIDAgbyBlbiBibGFuY28uIFNlIHB1ZWRlIHZlciBxdWUgaGF5IHVuYSBkaXN0cmlidWNpb24gY2FzaSA1MC01MCBlbnRyZSBsb3MgZ8OpbmVyb3MgbWFzY3VsaW5vIHkgZmVtZW5pbm8sIHNpbiBlbWJhcmdvLCBoYXkgdW4gMC4wMiUgbWFzIGRlIGluZGl2aWR1b3MgbWFzdWxpbm9zIHF1ZSBmZW1lbmlub3MuIEVsIGNvbmp1bnRvIGRlIGRhdG9zIHBvc2VlIGRhdG9zIGRlICoqNTAwMyoqIGluZGl2aWR1b3MgbWFzY3VsaW5vcyB5ICoqNDk3OCoqIGluZGl2aWR1b3MgZmVtZW5pbm9zIHkgKioxOSoqIGluZGl2aWR1b3MgcXVlIG5vIGVzdGFuIHJlZ2lzdHJhZG9zLiBFc3RvIG5vcyBwZXJtaXRlIGNvbXByZW5kZXIgcXVlIGVsIGNvbmp1bnRvIGRlIGRhdG9zIGVzdGEgYmFsYW5jZWFkbyBlbnRyZSBtYXNjdWxpbm9zIHkgZmVtZW5pbm9zLiANCg0KKiAqKkdyw6FmaWNhIDMgRGlzdHJpYnVjacOzbiBkZSBpbmRpdmlkdW9zIGNvbiBhbnRlY2VkZW50ZXMgZmFtaWxpYXJlcyBkZSBlbmZlcm1lZGFkZXMgZGVsIGNvcmF6w7NuLioqDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCmRhdGEgPC0gcmVhZC5jc3YoImRhdGEvaGVhcnRfZGlzZWFzZS5jc3YiKQ0KDQpkYXRhX2ZhbSA8LSBkYXRhICU+JQ0KICBtdXRhdGUoRmFtaWx5LkhlYXJ0LkRpc2Vhc2UgPSBjYXNlX3doZW4oIGlzLm5hKEZhbWlseS5IZWFydC5EaXNlYXNlKSB8IEZhbWlseS5IZWFydC5EaXNlYXNlID09ICIiIH4gIkVuIGJsYW5jbyIsIEZhbWlseS5IZWFydC5EaXNlYXNlID09ICJZZXMiIH4gIlPDrSIsIEZhbWlseS5IZWFydC5EaXNlYXNlID09ICJObyIgfiAiTm8iLCBUUlVFIH4gYXMuY2hhcmFjdGVyKEZhbWlseS5IZWFydC5EaXNlYXNlKSApKSAlPiUgZ3JvdXBfYnkoRmFtaWx5LkhlYXJ0LkRpc2Vhc2UpICU+JSBzdW1tYXJpc2UoQ2FudGlkYWQgPSBuKCkpDQoNCmZpZyA8LSBwbG90X2x5KGRhdGFfZmFtLCB4ID0gfkZhbWlseS5IZWFydC5EaXNlYXNlLCB5ID0gfkNhbnRpZGFkLCB0eXBlID0gImJhciIsIG1hcmtlciA9IGxpc3QoY29sb3IgPSBjKCAnI0JEQzNDNycsICcjMzQ5OERCJywgICcjRTc0QzNDJykpKSANCg0KZmlnIDwtIGZpZyAlPiUgbGF5b3V0KHRpdGxlID0gJ0FudGVjZWRlbnRlcyBmYW1pbGlhcmVzIGRlIGVuZmVybWVkYWRlcyBkZWwgY29yYXrDs24nLA0KICAgICAgICAgICAgICAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICLCv1Bvc2VlIGFudGVjZWRlbnRlcz8iKSwNCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQ2FudGlkYWQgZGUgUGVyc29uYXMiKSkNCg0KZmlnDQoNCmBgYA0KTGEgZ3LDoWZpY2EgZGUgYmFycmFzIGFudGVyaW9yIG11ZXN0cmEgbGEgZGlzdHJpYnVjacOzbiBkZSBsYXMgcmVzcHVlc3RhcyBkZSBsb3MgaW5kaXZpZHVvcyBzb2JyZSBzaSBwb3NzZW4gYW50ZWNlZGVudGVzIGRlIHByb2JsZW1hcyBlbiBlbCBjb3JhesOzbiwgbG8gcXVlIG5vcyBkZWphIGxhIHNpZ3VpZW50ZSBpbmZvcm1hY2nDs24gcmVsZXZhbnRlLCAqKjUwMDQqKiBpbmRpdmlkdW9zIG5vIHRpZW5lbiBhdGVjZWRlbnRlcyBmYW1pbGlhcmVzIGhheSAqKjIxKiogaW5kaXZpZHVvcyBxdWUgcmVzcG9uZGllcm9uIGVuIGJsYW5jbywgbWllbnRyYXMgcXVlLCAqKjQ5NzUqKiBpbmRpdmlkdW9zIHNpIGxvIHBvc2VlLCAgbG8gcXVlIGluZGljYSBxdWUgcG9kcmlhIGhhYmVyIHVuIHBvY28gZGUgcHJvYmFiaWxpZGFkIGRlIHF1ZSBlc29zIGluZGl2aWR1b3MuIExvIHF1ZSwgYWwgaWd1YWwgcXVlIGxhcyBncmFmaWNhcyBhbnRlcmlvcmVzIGRlbXVlc3RyYSBxdWUgbG9zIGRhdG9zIGVzdMOhbiBwcmFjdGljYW1lbnRlICBiYWxhbmNlYWRvcw0KDQoNCg0KIyMjICoqR3LDoWZpY2FzIGJpZGltZW5jaW9uYWxlcyoqDQoNCiogKipHcsOhZmljYSAxOiBDb25zdW1vIGRlIEF6w7pjYXIgdnMgTml2ZWxlcyBkZSBHbHVjb3NhIGVuIEF5dW5hcyoqDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCmRhdGFfYmkxIDwtIGRhdGEgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKFN1Z2FyLkNvbnN1bXB0aW9uKSwgIWlzLm5hKEZhc3RpbmcuQmxvb2QuU3VnYXIpLCBTdWdhci5Db25zdW1wdGlvbiAhPSAiIikNCg0KcDEgPC0gZ2dwbG90KGRhdGFfYmkxLCBhZXMoeCA9IFN1Z2FyLkNvbnN1bXB0aW9uLCB5ID0gRmFzdGluZy5CbG9vZC5TdWdhciwgZmlsbCA9IFN1Z2FyLkNvbnN1bXB0aW9uKSkgKw0KICBnZW9tX2JveHBsb3Qobm90Y2ggPSBUUlVFLCBhbHBoYSA9IDAuNykgKyANCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgRGlldGEgeSBHbHVjb3NhIiwgDQogICAgICAgeCA9ICJOaXZlbCBkZSBDb25zdW1vIGRlIEF6w7pjYXIiLCANCiAgICAgICB5ID0gIkdsdWNvc2EgZW4gQXl1bmFzIChtZy9kTCkiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkxvdyIgPSAibGlnaHRncmVlbiIsICJNZWRpdW0iID0gImdyZWVuIiwgIkhpZ2giID0gImRhcmtncmVlbiIpKQ0KDQpncmFmaWNhXzJkXzEgPC0gZ2dwbG90bHkocDEpDQpncmFmaWNhXzJkXzENCmBgYA0KRXN0YSBncsOhZmljYSBwZXJtaXRlIGV2YWx1YXIgY29tbyB1biBow6FiaXRvIGRlIGNvbnN1bW8gYWZlY3RhIHVuIGluZGljYWRvciBjbMOtbmljby4gQWwgaGFjZXIgdXNvIGRlIGxvcyBub3RjaCBlbiBsYXMgY2FqYXMsIHBlcm1pdGUgaWRlbnRpZmljYXIgZGUgZm9ybWEgaW50ZXJhY3RpdmEgc2kgbGFzIG1lZGlhcyBlIGdsdWNvc2EgdmFyw61hbiBzaWduaWZpY2F0aXZhbWVudGUgc2Vnw7puIGVsIG51dmVsIGRlIGF6w7pjYXIgaW5nZXJpZG8uIFNpIHNlIHF1aXNpZXJhIGluZGFnYXIgbcOhcywgZXN0byBheXVkYXLDrWEgYSB2YWxpZGFyIHNpIGxhIGRpZXRhIGVzIHVuIGZhY3RvciBkZXRlcm1pbmFudGUgZW4gbG9zIG5pdmVsZXMgZGUgYXrDumNhciBlbiBzYW5ncmUgZGUgbG9zIHBhY2llbnRlcy4gDQoNCiogKipHcsOhZmljYSAyOiBDb25jZW50cmFjacOzbiBkZSBDb2xlc3Rlcm9sIHNlZ8O6biBOaXZlbCBkZSBFc3Ryw6lzICoqDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCmRhdGFfYmkyIDwtIGRhdGEgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKFN0cmVzcy5MZXZlbCksICFpcy5uYShDaG9sZXN0ZXJvbC5MZXZlbCksIFN0cmVzcy5MZXZlbCAhPSAiIikNCg0KcDIgPC0gZ2dwbG90KGRhdGFfYmkyLCBhZXMoeCA9IFN0cmVzcy5MZXZlbCwgeSA9IENob2xlc3Rlcm9sLkxldmVsLCBmaWxsID0gU3RyZXNzLkxldmVsKSkgKw0KICBnZW9tX3Zpb2xpbih0cmltID0gRkFMU0UsIGFscGhhID0gMC43KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBDb2xlc3Rlcm9sIHBvciBOaXZlbCBkZSBFc3Ryw6lzIiwgDQogICAgICAgeCA9ICJOaXZlbCBkZSBFc3Ryw6lzIiwgDQogICAgICAgeSA9ICJOaXZlbCBkZSBDb2xlc3Rlcm9sIikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJMb3ciID0gImdyZWVuIiwgIk1lZGl1bSIgPSAieWVsbG93IiwgIkhpZ2giID0gInJlZCIpKQ0KDQpncmFmaWNhXzJkXzIgPC0gZ2dwbG90bHkocDIpDQpncmFmaWNhXzJkXzINCmBgYA0KU2UgaGFjZSB1c28gZGUgdW4gZ3LDoWZpY28gZGUgdmlvbMOtbiBpbnRlcmFjdGl2byBwYXJhIG9ic2VydmFyIGxhIGRlbnNpZGFkIGRlIGxvcyBuaXZlbGVzIGRlIGNvbGVzdGVyb2wgc2Vnw7puIGVsIGVzdHLDqXMgZGVsIHBhY2llbnRlLiBBbCBhbmFsaXphciBsYSBmb3JtYSBkZSBsYSBkaXN0cmlidWNpw7NuLCBlbCBFREEgcmV2ZWxhIHVuIHBhdHLDs24gaW50ZXJlc2FudGU6IGxvcyBkYXRvcyBzZSBkaXN0cmlidXllbiBkZSBtYW5lcmEgY2FzaSB1bmlmb3JtZSBlbiB0b2RvcyBsb3Mgbml2ZWxlcy4gRXN0byBub3MgaW5kaWNhIGVzdGFkw61zdGljYW1lbnRlIHF1ZSwgZW4gZXN0ZSBjb25qdW50byBkZSBkYXRvcyBlc3BlY8OtZmljbywgZWwgbml2ZWwgZGUgZXN0csOpcyBubyBhbHRlcmEgc2lnbmlmaWNhdGl2YW1lbnRlIGxhIGNvbmNlbnRyYWNpw7NuIGRlIGNvbGVzdGVyb2wNCg0KIyMjICoqR3LDoWZpY2FzIG11bHRpZGltZW5jaW9uYWxlcyoqDQoNCiogKipHcsOhZmljYSAxIERpc3RyaWJ1Y2nDs24gZGUgaW5kaXZpZHVvcyBwb3IgaGFiaXRvcyBpbmRpdmlkdWFsZXMsIGVqZXJjaWNpbywgbml2ZWwgZGUgZXN0cmVzLCBob3JhcyBkZSBzdWXDsW8sIGNvbnN1bW8gZGUgYXp1Y2FyIHkgcHJvYmxlbWFzIGRlbCBjb3JhesOzbi4qKg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGRwbHlyKQ0KDQoNCmRhdGFfbGltcGlhIDwtIGRhdGEgJT4lDQogIG11dGF0ZShhY3Jvc3MoYyhFeGVyY2lzZS5IYWJpdHMsIFNsZWVwLkhvdXJzLCBTdWdhci5Db25zdW1wdGlvbiwgU21va2luZywgU3RyZXNzLkxldmVsKSwgDQogICAgICAgICAgICAgICAgfmFzLmNoYXJhY3RlcihpZihpcy5udW1lcmljKC4pKSByb3VuZCguKSBlbHNlIC4pKSkgJT4lIA0KICBzZWxlY3QoRWplcmNpY2lvID0gRXhlcmNpc2UuSGFiaXRzLCBTdWXDsW8gPSBTbGVlcC5Ib3VycywgDQogICAgICAgICBBesO6Y2FyID0gU3VnYXIuQ29uc3VtcHRpb24sIEZ1bWFkb3IgPSBTbW9raW5nLCBFc3Ryw6lzID0gU3RyZXNzLkxldmVsKQ0KDQp2YXJzIDwtIG5hbWVzKGRhdGFfbGltcGlhKQ0Kbl92YXJzIDwtIGxlbmd0aCh2YXJzKQ0KDQoNCmNyZWFyX2NlbGRhX2VzY2FsZXJhIDwtIGZ1bmN0aW9uKGNvbF9pZHgsIHJvd19pZHgpIHsNCiAgdjEgPC0gdmFyc1tjb2xfaWR4XSANCiAgdjIgPC0gdmFyc1tyb3dfaWR4XQ0KICANCiAgaWYgKGNvbF9pZHggPCByb3dfaWR4KSB7IA0KICAgIGRmX2NvdW50IDwtIGRhdGFfbGltcGlhICU+JSBjb3VudCguZGF0YVtbdjFdXSwgLmRhdGFbW3YyXV0pDQogICAgDQogICAgcGxvdF9seShkYXRhID0gZGZfY291bnQsIHggPSB+LmRhdGFbW3YxXV0sIHkgPSB+LmRhdGFbW3YyXV0sIHogPSB+biwgDQogICAgICAgICAgICB0eXBlID0gImhlYXRtYXAiLCBjb2xvcnNjYWxlID0gIkJsdWVzIiwgc2hvd3NjYWxlID0gRkFMU0UsIA0KICAgICAgICAgICAgaG92ZXJpbmZvID0gInRleHQiLCANCiAgICAgICAgICAgIHRleHQgPSB+cGFzdGUwKCI8Yj4iLCB2MSwgIjwvYj4gdnMgPGI+IiwgdjIsICI8L2I+PGJyPiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLmRhdGFbW3YxXV0sICIgLyAiLCAuZGF0YVtbdjJdXSwgIjxicj4iLCAiVG90YWw6ICIsIG4sICIgcGVyc29uYXMiKSkgJT4lDQogICAgICBsYXlvdXQoDQogICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9IGlmKHJvd19pZHggPT0gbl92YXJzKSB2MSBlbHNlICIiLCB0aWNrYW5nbGUgPSA0NSksDQogICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9IGlmKGNvbF9pZHggPT0gMSkgdjIgZWxzZSAiIikNCiAgICAgICkNCiAgfSBlbHNlIHsNCiAgICANCiAgICBwbG90X2x5KHR5cGUgPSAic2NhdHRlciIsIG1vZGUgPSAibWFya2VycyIpICU+JSANCiAgICAgIGxheW91dCh4YXhpcyA9IGxpc3QodmlzaWJsZSA9IEZBTFNFKSwgeWF4aXMgPSBsaXN0KHZpc2libGUgPSBGQUxTRSkpDQogIH0NCn0NCg0KDQpsaXN0YV9wbG90cyA8LSBsaXN0KCkNCmZvciAoaSBpbiAxOm5fdmFycykgeyAgIA0KICBmb3IgKGogaW4gMTpuX3ZhcnMpIHsgIA0KICAgIGxpc3RhX3Bsb3RzW1tsZW5ndGgobGlzdGFfcGxvdHMpICsgMV1dIDwtIGNyZWFyX2NlbGRhX2VzY2FsZXJhKGosIGkpDQogIH0NCn0NCg0KZmlnIDwtIHN1YnBsb3QobGlzdGFfcGxvdHMsIG5yb3dzID0gbl92YXJzLCBtYXJnaW4gPSAwLjAyLCANCiAgICAgICAgICAgICAgIHRpdGxlWCA9IFRSVUUsIHRpdGxlWSA9IFRSVUUsIHNoYXJlWCA9IEZBTFNFLCBzaGFyZVkgPSBGQUxTRSkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9ICJDb21wYXJhdGl2YSBkZSBow6FiaXRvcyIsDQogICAgbWFyZ2luID0gbGlzdChsID0gMTAwLCBiID0gMTAwLCB0ID0gODAsIHIgPSAyMCkNCiAgKQ0KDQpmaWckd2lkdGggPC0gODUwDQpmaWckaGVpZ2h0IDwtIDg1MA0KDQpmaWcNCmBgYA0KDQoNCg0KTGEgbWF0cml6IGRlIGRpc3BlcnNpw7NuIGVuIGVzY2FsZXJhIHBlcm1pdGUgdmVyIHVuYSBjb21wYXJhdGljYSBkZSA1IGRpbWVuc2lvbmVzLCBob3JhcyBkZSBzdWXDsW8gcmVkb25kZWFkYXMsIGNvbnN1bW8gZGUgYXp1Y2FyLCBuaXZlbCBkZSBlc3Ryw6lzLCBzaSBlcyBmdW1hZG9yIHkgbGEgY2FudGlkYWQgZGUgZWplcmNpY2lvIHF1ZSBzZSByZWFsaXphIGNvbXBhcmFuZG8gY2FkYSB1bmEgY29uIGxhcyBkZW3DoXMsIGRvbmRlIGNhZGEgZ3LDoWZpY2EgcmVwcmVzZW50YSBsYSBjb21wYXJhY2nDs24gZGUgZG9zIHZhcmlhYmxlcywgbWVkaWFudGUgbWFwYXMgZGUgY2Fsb3IgaW50ZXJhY3Rpdm9zLCBsYSBpbnRlbnNpZGFkIGRlbCBjb2xvciBhenVsIGZ1bmNpb25hIGNvbW8gdW4gaW5kaWNhZG9yIGRlIGRlbnNpZGFkIGRlbW9ncsOhZmljYSwgbG8gcXVlIHBlcm1pdGUgdmVyIGEgc2ltcGxlIHZpc3RhIGxhIGNhbnRpZGFkIGRlIHBlcnNvbmFzIHF1ZSBjdW1wbGVuIGNvbiBkaWNoYXMgY2FyYWN0ZXJpc3RpY2FzLiBQYXJhIHBvZGVyIHZlciBsb3MgZGF0b3MsIHNvbG8gc2UgcGFzYSBwb3IgZW5jaW1hIGVsIG1vdXNlIHBhcmEgdmVyIGxvcyBkYXRvcy4NCg0KDQoqKkdyw6FmaWNhIGRlIGZhY2V0YXMqKg0KDQoqICoqR3LDoWZpY2EgMTogUmVsYWNpw7NuIGRlIEVkYWQgeSBCTUkgZGl2aWRpZGEgcG9yIFRhYmFxdWlzbW8qKg0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCmRhdGFfZmFjZXRhcyA8LSBkYXRhICU+JSANCiAgZmlsdGVyKCFpcy5uYShBZ2UpLCAhaXMubmEoQk1JKSwgU21va2luZyAlaW4lIGMoIlllcyIsICJObyIpLCAhaXMubmEoSGVhcnQuRGlzZWFzZS5TdGF0dXMpKQ0KDQpwMyA8LSBnZ3Bsb3QoZGF0YV9mYWNldGFzLCBhZXMoeCA9IEFnZSwgeSA9IEJNSSwgY29sb3IgPSBIZWFydC5EaXNlYXNlLlN0YXR1cykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICBmYWNldF93cmFwKH4gU21va2luZykgKyAjIEFxdcOtIGNyZWFtb3MgbG9zIHBhbmVsZXMgc2VwYXJhZG9zDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiRWRhZCB2cyBCTUkgKFBhbmVsZXMgcG9yIFRhYmFxdWlzbW8pIiwgDQogICAgICAgeCA9ICJFZGFkIChhw7FvcykiLCANCiAgICAgICB5ID0gIsONbmRpY2UgZGUgTWFzYSBDb3Jwb3JhbCAoQk1JKSIpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk5vIiA9ICJsaWdodGJsdWUiLCAiWWVzIiA9ICJyZWQiKSkNCg0KZ3JhZmljYV9mYWNldGFzIDwtIGdncGxvdGx5KHAzKQ0KZ3JhZmljYV9mYWNldGFzDQoNCmBgYA0KDQpQYXJhIGVzdGEgdmlzdWFsaXphY2nDs24gc2UgaGFjZSB1c28gZGUgbGEgdMOpY25pY2EgZGUgZmFjZXRhcyBxdWUgcGVybWl0ZSBpbnRlZ3JhciA0IHZhcmlhYmxlcyBzaW11bHTDoW5lYW1lbnRlOiBFZGFkIGVuIGVsIGVqZSBYLCBCTUkgZW4gZWwgZWplIFksIEVzdGFkbyBDYXJkw61hY28gcmVwcmVzZW50YWRvIGNvbiBlbCBDb2xvciB5IFRhYmFxdWlzbW8gZW4gbG9zIFBhbmVsZXMgc2VwYXJhZG9zLiBBbCBkaXZpZGlyIGxhIHBvYmxhY2nDs24gZW50cmUgZnVtYWRvcmVzIHkgbm8gZnVtYWRvcmVzLCBzZSBwdWVkZSBleHBsb3JhciBkZSBtYW5lcmEgaW50ZXJhY3RpdmEgc2kgbG9zIHB1bnRvcyByb2pvcywgZXMgZGVjaXIsIHBhY2llbnRlcyBjb24gZW5mZXJtZWRhZCwgdGllbmRlbiBhIGNvbmNlbnRyYXJzZSBlbiB6b25hcyBkZSBtYXlvciBlZGFkIG8gbWF5b3IgcGVzbyBkZXBlbmRpZW5kbyBkZSBzdSBow6FiaXRvIGRlIGZ1bWFyLg0KDQotLS0NCg0KIyMjICoqR3LDoWZpY2EgY29tcHVlc3RhKioNCg0KLS0tDQoNCiogKipHcsOhZmljYSAxOiBEYXNoYm9hcmQgSW50ZWdyYWRvIGRlIEZhY3RvcmVzIENsw61uaWNvcyoqDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCmdyYWZpY2FfY29tcHVlc3RhIDwtIHN1YnBsb3QgKGdyYWZpY2FfMmRfMSwgZ3JhZmljYV8yZF8yLCBucm93cyA9IDEsIG1hcmdpbiA9IDAuMDUsIHRpdGxlWCA9IFRSVUUsIHRpdGxlWSA9IFRSVUUpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiRGFzaGJvYXJkOiBBbsOhbGlzaXMgZGUgRXN0csOpcyB5IERpZXRhIiwgc2hvd2xlZ2VuZCA9IEZBTFNFKQ0KDQpncmFmaWNhX2NvbXB1ZXN0YQ0KYGBgDQpFc3RhIGltYWdlbiBjb21wdWVzdGEgaW50ZWdyYSBsYXMgZG9zIGdyw6FmaWNhcyBiaWRpbWVuc2lvbmFsZXMgZ2VuZXJhZGFzIGFudGVyaW9ybWVudGUgZW4gdW4gc29sbyBkYXNoYm9hcmQuIExhIHZlbnRhamEgZXMgcXVlIHBlcm1pdGUgY29tcGFyYXIgbcO6bHRpcGxlcyBmYWN0b3JlcyBkZSByaWVzZ28gYmlvbMOzZ2ljbyB5IGRlIGNvbXBvcnRhbWllbnRvIGVuIHVuYSBzb2xhIHBhbnRhbGxhLCBlIGlndWFsIHNlIG1hbnRpbmVuZW4gbGFzIGNhcGFjaWRhZGVzIGRlIGludGVyYWNjacOzbi4gDQoNCiMjIDUuIENvbmNsdXNpb25lcw0KDQpUcmFzIHJlYWxpemFyIGVsIEVEQSBzb2JyZSBlc3RlIGNvbmp1bnRvIGRlbCB0b3RhbCBkZSByZWdpc3Ryb3MsIGVsIHByb2Nlc28gZGUgc3Rvcnl0ZWxsaW5nIHZpc3VhbCBub3MgaGEgcGVybWl0aWRvIHRyYW5zZm9ybWFyIGRhdG9zIGNydWRvcyBlbiBoYWxsYXpnb3MgY2xhdmUgc29icmUgbG9zIGZhY3RvcmVzIGRlIHJpZXNnbyBlbiBlbmZlcm1lZGFkZXMgY2FyZMOtYWNhczoNCg0KKiAqKkJhbGFuY2UgeSBjYWxpZGFkIGRlIGxhIG11ZXN0cmE6KiogRWwgYW7DoWxpc2lzIHVuaWRpbWVuc2lvbmFsIHJldmVsw7MgcXVlIGVsIGNvbmp1bnRvIGRlIGRhdG9zIGVzdMOhIGV4Y2VwY2lvbmFsbWVudGUgYmFsYW5jZWFkbyBlbiB0w6lybWlub3MgZGVtb2dyw6FmaWNvcy4gTGEgZGlzdHJpYnVjacOzbiBjYXNpIHNpbcOpdHJpY2EgZW50cmUgbG9zIGfDqW5lcm9zICg1MDAzIG1hc2N1bGlub3MgeSA0OTc4IGZlbWVuaW5vcykgeSBsYSBwcm9wb3JjacOzbiBlcXVpdGF0aXZhIGRlIGFudGVjZWRlbnRlcyBmYW1pbGlhcmVzLCBnYXJhbnRpemFuIHF1ZSBsb3MgcGF0cm9uZXMgZGVzY3ViaWVydG9zIG5vIGVzdMOpbiBzZXNnYWRvcyBoYWNpYSB1biBncnVwbyBwb2JsYWNpb25hbCBlc3BlY8OtZmljby4NCg0KKiAqKkRlc21pdGlmaWNhY2nDs24gZGUgdmFyaWFibGVzIGFpc2xhZGFzOioqIFVuYSBkZSBsYXMgcmV2ZWxhY2lvbmVzIG3DoXMgdmFsaW9zYXMgc3VyZ2nDsyBlbiBlbCBhbsOhbGlzaXMgYmlkaW1lbnNpb25hbC4gQ29udHJhcmlvIGEgbGEgY3JlZW5jaWEgcG9wdWxhciBkZSBxdWUgZWwgZXN0csOpcyBkaXNwYXJhIGF1dG9tw6F0aWNhbWVudGUgZWwgY29sZXN0ZXJvbCwgbGFzIGdyw6FmaWNhcyBkZSB2aW9sw61uIGRlbW9zdHJhcm9uIHVuYSBkaXN0cmlidWNpw7NuIHVuaWZvcm1lOyBlcyBkZWNpciwgZW4gZXN0YSBwb2JsYWNpw7NuIHBhcnRpY3VsYXIsIGVsIG5pdmVsIGRlIGVzdHLDqXMgcG9yIHPDrSBzb2xvIG5vIGFsdGVyYSBkZSBmb3JtYSBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhIGxhIGNvbmNlbnRyYWNpw7NuIGRlIGNvbGVzdGVyb2wuIEVzdG8gaW5kaWNhIHF1ZSBubyBzZSBkZWJlIGRpYWdub3N0aWNhciBlbCByaWVzZ28gYmFzw6FuZG9zZSBlbiB1biBzb2xvIGZhY3RvciBhaXNsYWRvLg0KDQoqICoqRWwgcG9kZXIgZGUgbG9zIGZhY3RvcmVzIGNvbWJpbmFkb3M6KiogRWwgdmVyZGFkZXJvIHZhbG9yIHByZWRpY3Rpdm8gc2Ugb2JzZXJ2w7MgYWwgY3J1emFyIG3Dumx0aXBsZXMgZGltZW5zaW9uZXMuIEdyYWNpYXMgYSBsYXMgZ3LDoWZpY2FzIGRlIGZhY2V0YXMgeSBsYSBtYXRyaXogZGUgY2Fsb3IgbXVsdGlkaW1lbnNpb25hbCwgcXVlZMOzIGVuIGV2aWRlbmNpYSBxdWUgbGFzIGVuZmVybWVkYWRlcyBkZWwgY29yYXrDs24gbm8gZGVwZW5kZW4gZGUgdW4gc29sbyBtYWwgaMOhYml0bywgc2lubyBkZSBsYSBhY3VtdWxhY2nDs24gZGUgZXN0b3MuIExhIGludGVyYWNjacOzbiBzaW11bHTDoW5lYSBlbnRyZSB1bmEgbWF5b3IgZWRhZCwgdW4gQk1JIGVsZXZhZG8geSBlbCBTbW9raW5nIGFncnVwYSB2aXN1YWxtZW50ZSBhIGxvcyBwYWNpZW50ZXMgY29uIGVzdGFkbyBjYXJkw61hY28gcG9zaXRpdm8gZW5jSGVhcnQgRGlzZWFzZSBTdGF0dXMuDQoNCiogKipBY2Npb25hYmlsaWRhZDoqKg0KQSBuaXZlbCBtw6lkaWNvIHkgcHJldmVudGl2bywgZXN0ZSBhbsOhbGlzaXMgc3VnaWVyZSBxdWUgbGFzIGNhbXBhw7FhcyBkZSBzYWx1ZCBubyBkZWJlbiBlbmZvY2Fyc2Ugw7puaWNhbWVudGUgZW4gcmVkdWNpciBlbCBlc3Ryw6lzIG8gZWwgY29uc3VtbyBkZSBhesO6Y2FyIGRlIGZvcm1hIGFpc2xhZGEuIERlYmVuIGRpc2XDsWFyc2UgaW50ZXJ2ZW5jaW9uZXMgaW50ZWdyYWxlcyBkaXJpZ2lkYXMgYSBsb3MgInBlcmZpbGVzIGNvbWJpbmFkb3MiIGRlIGFsdG8gcmllc2dvIChwb3IgZWplbXBsbzogcGFjaWVudGVzIGRlIGVkYWQgYXZhbnphZGEsIGNvbiBhbHRvIEJNSSB5IGZ1bWFkb3JlcyBhY3Rpdm9zKS4gDQoNClBhcmEgZmluYWxpemFyLCBlbCBkZXNhcnJvbGxvIGRlIGVzdGUgRURBIGRlbXVlc3RyYSBsYSBpbXBvcnRhbmNpYSBkZWwgc3Rvcnl0ZWxsaW5nIGNvbiBsb3MgZGF0b3MuIEFsIHRyYW5zZm9ybWFyIHJlZ2lzdHJvcyBjb21wbGVqb3MgZW4gZ3LDoWZpY2FzIGludGVyYWN0aXZhcyB5IG5hcnJhdGl2YXMgY2xhcmFzLCBzZSBmYWNpbGl0YSBwb3IgbXVjaG8gbGEgY29tcHJlbnNpw7NuIGRlIGxhIGluZm9ybWFjacOzbi4gR3JhY2lhcyBhIGxhIGxpbXBpZXphLCBlc3RydWN0dXJhY2nDs24geSBhdXNlbmNpYSBkZSBzZXNnb3MgZGVtb2dyw6FmaWNvcyBjb21wcm9iYWRvcywgZXN0ZSBjb25qdW50byBkZSBkYXRvcyByZXN1bHRhIHNlciB1biBjYW5kaWRhdG8gaWRlYWwgcGFyYSBlbCBkaXNlw7FvIGRlIGRhc2hib2FyZHMgbcOpZGljb3MuIEVzdGFzIGhlcnJhbWllbnRhcyB2aXN1YWxlcyBwZXJtaXRpcsOtYW4gYSBsb3MgcHJvZmVzaW9uYWxlcyBkZSBsYSBzYWx1ZCBleHBsb3JhciB0ZW5kZW5jaWFzLCBhaXNsYXIgdmFyaWFibGVzIGludGVyYWN0aXZhbWVudGUgeSBjb211bmljYXIgcmllc2dvcyBhIGxvcyBwYWNpZW50ZXMgZGUgZm9ybWEgdHJhbnNwYXJlbnRlIHkgZWZlY3RpdmEsIGN1bXBsaWVuZG8gYXPDrSBjb24gZWwgb2JqZXRpdm8gZnVuZGFtZW50YWwgZGUgbGEgdmlzdWFsaXphY2nDs24gZGUgbGEgaW5mb3JtYWNpw7NuLg0K