Climate change timeline
# Instalación de paquetes necesarios (descomenta si no los tienes)
# install.packages("ggplot2")
# install.packages("dplyr")
# install.packages("ggtext")
options(warn = -1)
library(ggplot2)
suppressPackageStartupMessages(library(dplyr))
suppressWarnings(library(ggtext))
# Datos de las Conferencias COP
cop_data <- data.frame(
year = c(1997, 2005, 2007, 2009, 2011, 2012, 2015, 2021, 2024, 2025),
event = c("COP3", "COP11/MOP1", "COP13", "COP15", "COP17", "COP18", "COP21", "COP26", "COP29", "COP30"),
title = c(
"Protocolo de Kioto",
"Entrada en vigor de Kioto",
"Plan de Acción de Bali",
"Acuerdo de Copenhague",
"Plataforma de Durban",
"Enmienda de Doha",
"Acuerdo de París",
"Pacto de Glasgow",
"COP29",
"COP30"
),
location = c(
"Kioto, Japón",
"Montreal, Canadá",
"Bali, Indonesia",
"Copenhague, Dinamarca",
"Durban, Sudáfrica",
"Doha, Catar",
"París, Francia",
"Glasgow, Reino Unido",
"Bakú, Azerbaiyán",
"Belém, Brasil"
),
description = c(
"Metas vinculantes de reducción de\nemisiones 6-8% vs 1990",
"Primera reunión de las Partes\ndel protocolo. +10,000 delegados",
"Cronograma para el marco post-2012.\nGrupo de acción cooperativa",
"192 países. Compromiso de\n$30 mil millones 2010-2012",
"Negociaciones para acuerdo vinculante.\nFondo Verde $100 mil millones",
"Segundo período de compromiso\nKioto 2013-2020",
"Mantener calentamiento <2°C.\nParticipación universal",
"Primer balance global del\nAcuerdo de París. +40,000 participantes",
"Acuerdo de $300,000 millones\nanuales para países en desarrollo",
"Prevista para noviembre 2025.\nNuevas NDCs 3.0"
),
highlight = c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE),
side = c("left", "right", "left", "right", "left", "right", "left", "right", "left", "right")
)
# Crear el gráfico
p <- ggplot(cop_data, aes(x = year, y = 0)) +
# Línea de tiempo central
geom_segment(aes(x = min(year), xend = max(year), y = 0, yend = 0),
color = "#667eea", size = 1.5, lineend = "round") +
# Puntos en la línea de tiempo
geom_point(aes(color = highlight), size = 8, show.legend = FALSE) +
scale_color_manual(values = c("TRUE" = "#e74c3c", "FALSE" = "#667eea")) +
# Líneas conectoras a las cajas de texto
geom_segment(data = cop_data %>% filter(side == "left"),
aes(x = year, xend = year, y = 0, yend = 0.3),
color = "#667eea", size = 0.8, linetype = "solid") +
geom_segment(data = cop_data %>% filter(side == "right"),
aes(x = year, xend = year, y = 0, yend = -0.3),
color = "#667eea", size = 0.8, linetype = "solid") +
# Cajas de eventos (lado izquierdo/arriba)
geom_label(data = cop_data %>% filter(side == "left"),
aes(x = year, y = 0.35,
label = paste0("**", year, " - ", title, "**\n",
"📍 ", location, "\n\n",
description),
fill = highlight),
hjust = 0.5, vjust = 0, size = 3.5,
lineheight = 0.9, label.padding = unit(0.5, "lines"),
label.size = 0.5, show.legend = FALSE) +
# Cajas de eventos (lado derecho/abajo)
geom_label(data = cop_data %>% filter(side == "right"),
aes(x = year, y = -0.35,
label = paste0("**", year, " - ", title, "**\n",
"📍 ", location, "\n\n",
description),
fill = highlight),
hjust = 0.5, vjust = 1, size = 3.5,
lineheight = 0.9, label.padding = unit(0.5, "lines"),
label.size = 0.5, show.legend = FALSE) +
scale_fill_manual(values = c("TRUE" = "#667eea", "FALSE" = "#ecf0f1")) +
# Etiquetas de años en la línea
geom_text(aes(label = year), y = -0.05, vjust = 1.5,
size = 3, fontface = "bold", color = "#2c3e50") +
# Configuración de escalas y tema
scale_x_continuous(breaks = cop_data$year, limits = c(1995, 2027)) +
scale_y_continuous(limits = c(-0.8, 0.8)) +
labs(
title = "🌍 Conferencias de la ONU sobre Cambio Climático",
subtitle = "Del Protocolo de Kioto (1997) a la COP30 (2025)",
caption = "Fuente: UNFCCC | Eventos destacados: Kioto, París y COP30"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 20, face = "bold", hjust = 0.5,
color = "#2c3e50", margin = margin(b = 5)),
plot.subtitle = element_text(size = 14, hjust = 0.5,
color = "#7f8c8d", margin = margin(b = 20)),
plot.caption = element_text(size = 10, color = "#95a5a6", hjust = 0.5,
margin = margin(t = 20)),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.title = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank(),
plot.background = element_rect(fill = "#f8f9fa", color = NA),
panel.background = element_rect(fill = "#f8f9fa", color = NA),
plot.margin = margin(30, 30, 30, 30)
)
# Mostrar el gráfico
print(p)

# Guardar el gráfico (opcional)
# ggsave("timeline_cop_conferencias.png", plot = p,
# width = 16, height = 10, dpi = 300, bg = "#f8f9fa")
suppressPackageStartupMessages(library(kableExtra))
# kable(cop_data[ ,1:5], format = "html")
cop_data[ ,1:5] %>%
kbl() %>%
kable_material(c("striped", "hover"))
|
year
|
event
|
title
|
location
|
description
|
|
1997
|
COP3
|
Protocolo de Kioto
|
Kioto, Japón
|
Metas vinculantes de reducción de emisiones 6-8% vs 1990
|
|
2005
|
COP11/MOP1
|
Entrada en vigor de Kioto
|
Montreal, Canadá
|
Primera reunión de las Partes del protocolo. +10,000 delegados
|
|
2007
|
COP13
|
Plan de Acción de Bali
|
Bali, Indonesia
|
Cronograma para el marco post-2012. Grupo de acción cooperativa
|
|
2009
|
COP15
|
Acuerdo de Copenhague
|
Copenhague, Dinamarca
|
192 países. Compromiso de $30 mil millones 2010-2012
|
|
2011
|
COP17
|
Plataforma de Durban
|
Durban, Sudáfrica
|
Negociaciones para acuerdo vinculante. Fondo Verde $100 mil millones
|
|
2012
|
COP18
|
Enmienda de Doha
|
Doha, Catar
|
Segundo período de compromiso Kioto 2013-2020
|
|
2015
|
COP21
|
Acuerdo de París
|
París, Francia
|
Mantener calentamiento <2°C. Participación universal
|
|
2021
|
COP26
|
Pacto de Glasgow
|
Glasgow, Reino Unido
|
Primer balance global del Acuerdo de París. +40,000 participantes
|
|
2024
|
COP29
|
COP29
|
Bakú, Azerbaiyán
|
Acuerdo de $300,000 millones anuales para países en desarrollo
|
|
2025
|
COP30
|
COP30
|
Belém, Brasil
|
Prevista para noviembre 2025. Nuevas NDCs 3.0
|
Metrics of the globalization
Those are the so-called “end of globalization” metrics.

Offshoring
Offshoring is the practice of relocating a business
process, manufacturing, or service to a distant foreign country,
typically to take advantage of lower labor costs or other economic
benefits (environmental).
Location: A country far from the company’s home
country (e.g., a U.S. company moving manufacturing to China or a
European company moving IT support to India).
Primary Motivation: Significant cost savings,
access to specialized skills, and global market expansion.
Trade-offs: Potential for long supply chains,
significant time zone differences, cultural/language barriers, and
reduced supply chain visibility/control.
Re-shoring (also called Onshoring)
Re-shoring is the process of bringing business
operations, production, or services back to the company’s original home
country after they were previously moved overseas (offshored).
Location: The company’s home country.
Primary Motivation: Increasing supply chain
resilience and control, reducing lead times, improving product quality
oversight, avoiding geopolitical risks, and leveraging the “Made in
[Home Country]” appeal.
Trade-offs: Generally involves higher labor and
operational costs compared to offshore locations.
Near-shoring
Near-shoring involves relocating business operations
or services to a nearby foreign country, typically one that is
geographically proximate, often sharing a border or being within a close
time zone.
Location: A neighboring or geographically close
country (e.g., a U.S. company moving production to Mexico or a French
company moving IT to Romania).
Primary Motivation: Seeking a balance between
cost savings (lower costs than the home country) and the benefits of
proximity, such as shorter shipping times, fewer time zone issues, and
easier communication and travel for oversight.
Trade-offs: Costs are typically lower than
re-shoring but potentially higher than far-off offshoring. The goal is
to mitigate the complexity and risk associated with long-distance
offshoring while still achieving some cost advantages
One man is One man everywhere
* A US citizen emits seven times more than a European citizen. China proposes reducing emissions based on quotas per country.
* A Chinese citizen emits 15 times less than a European, but uses coal. Furthermore, they have a huge population. The US proposes reducing China's emissions and quality without altering its own emition rate. (MAGA)
* India has lowered its energy intensity (TOE vs. GDP), proposing that one man equals one man. Developed countries have already "burned" their share of fuel. Then their need to reduce his emissions and allow developing countries to close the inequality gap.
What decisions and paths to take
The Institute of Industrial Engineering and Di³ are working on the
following lines of research that use artificial intelligence and
language models to investigate ways to optimize critical infrastructure,
which appears to be the focus of attacks and cyberattacks to reduce
competitiveness in these end-of-globalization environments.
We firmly believe that universities cannot silence their voices
and must work toward a culture of peace.
Playing war games, as many leaders are doing, is more dangerous
than playing Russian roulette with nuclear bullets.
As academics, our duty is to research, discover, and put on the
agenda of governments and companies what our models tell us should be
the right thing to do.
Use CI as intelligently as possible
It is very clear that the governments of Western democracies will no
longer have the capacity to invest in infrastructure in the way they did
in the first half of the 20th century.
The infrastructure we inherited will soon be overwhelmed by
exponential population growth.
New environmental restrictions force us to become more efficient or
endure increasingly intense and adverse weather events.
A Clever Decisión
USE ARTIFICIAL INTELLIGENCE TO GET THE MAXUMUN OF YOUR CRITICAL INFRASTRUCTURE
EXAMPLE 1 - Wine Supply Chain Case


China and Australia Wine Routing
China’s shares of the volume of world wine:
| 2014 |
4.0 |
5.6 |
3.6 |
| 2015 |
4.0 |
6.7 |
5.2 |
| 2016 |
4.0 |
6.8 |
6.0 |
| 2017 |
3.7 |
6.7 |
7.0 |
| 2018 |
2.1 |
5.4 |
6.5 |
| 2019 |
1.6 |
4.3 |
5.8 |
| 2020 |
1.2 |
3.1 |
4.1 |
| 2021 |
1.0 |
2.9 |
4.0 |
| 2022 |
0.7 |
2.2 |
3.2 |
| 2023 |
0.6 |
2.4 |
3.5 |
| 2024 |
0.3 |
2.9 |
3.1 |
shares_volume <- c(2014 , 4.0, 5.6, 3.6 ,
2015 , 4.0, 6.7, 5.2 ,
2016 , 4.0, 6.8, 6.0 ,
2017 , 3.7, 6.7, 7.0 ,
2018 , 2.1, 5.4, 6.5 ,
2019 , 1.6, 4.3, 5.8 ,
2020 , 1.2, 3.1, 4.1 ,
2021 , 1.0, 2.9, 4.0 ,
2022 , 0.7, 2.2, 3.2 ,
2023 , 1.6, 2.4, 3.5 ,
2024 , 3, 1.3, 1.5 )
shares_volume <- matrix(shares_volume,ncol = 4, byrow = TRUE)
colnames(shares_volume) <- c("Year", "Consumption", "Consumption", "Imports")
# shares_volume
suppressPackageStartupMessages(library(ggplot2))
suppressPackageStartupMessages(library(plotly))
suppressPackageStartupMessages(library(tidyr))
# Crear el vector y la matriz
shares_volume_vec <- c(2014, 4.0, 5.6, 3.6,
2015, 4.0, 6.7, 5.2,
2016, 4.0, 6.8, 6.0,
2017, 3.7, 6.7, 7.0,
2018, 2.1, 5.4, 6.5,
2019, 1.6, 4.3, 5.8,
2020, 1.2, 3.1, 4.1,
2021, 1.0, 2.9, 4.0,
2022, 0.7, 2.2, 3.2,
2023, 1.6, 2.4, 3.5,
2024, 3, 1.3, 1.5)
shares_volume <- matrix(shares_volume_vec, ncol = 4, byrow = TRUE)
colnames(shares_volume) <- c("Year", "Production", "Consumption", "Imports")
# Convertir a data frame
df <- as.data.frame(shares_volume)
# Transformar de formato ancho a largo para ggplot2
df_long <- pivot_longer(df,
cols = c("Production", "Consumption", "Imports"),
names_to = "Variable",
values_to = "Value")
# Crear gráfico con ggplot2
p <- ggplot(df_long, aes(x = Year, y = Value, color = Variable, group = Variable)) +
geom_line(size = 1.2) +
geom_point(size = 3) +
labs(title = "Shares Volume: Production, Consumption & Imports",
x = "Year",
y = "Value",
color = "Variable") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
legend.position = "right")
# Convertir a plotly para interactividad
interactive_plot <- ggplotly(p, tooltip = c("x", "y", "colour"))
# Mostrar el gráfico interactivo
interactive_plot
China vs Australia vs Chile
Index of intensity of wine exports to China from Australia, Chile and
France,a and share of Australia’s wine exports going to China, by value,
2014 to 2022
| % Export Au to Ch |
1.9 |
2.8 |
3.7 |
5 |
5.1 |
6 |
0.5 |
0.3 |
6 |
| Australia Index |
2.8 |
2.8 |
3 |
4 |
4.6 |
5.5 |
6.5 |
0.3 |
0.1 |
| Chile Index |
1.95 |
1.9 |
1.8 |
2 |
2.3 |
2.6 |
2.5 |
4.1 |
4.4 |
| France Index |
1.3 |
1.1 |
1.0 |
1.1 |
0.9 |
0.8 |
0.95 |
1.3 |
1.35 |
export_index <- c(
1.9 , 2.8 , 3.7 , 5 , 5.1, 6 , 0.5 , 0.3 , 6 ,
2.8 , 2.8 , 3 , 4 , 4.6 , 5.5 , 6.5 , 0.3 , 0.1 ,
1.95 , 1.9 , 1.8 , 2 , 2.3 , 2.6 , 2.5 , 4.1 , 4.4 ,
1.3 , 1.1 , 1.0 , 1.1, 0.9 , 0.8 , 0.95, 1.3 , 1.35 )
export_index <- matrix(export_index, ncol= 9 , byrow = "TRUE")
colnames(export_index) <- c( "2014", "2015", "2016","2017","2018","2019" ,"2020" ,"2021","2022")
rownames( export_index) <- c("Bult wine export Australy to China", "Australia Index", "Chile Index","France Index")
# export_index
# library(ggplot2)
# library(plotly)
suppressPackageStartupMessages(library(tidyr))
suppressPackageStartupMessages(library(dplyr))
# Crear la matriz
export_index <- c(
1.9, 2.8, 3.7, 5, 5.1, 6, 0.5, 0.3, 0.2,
2.8, 2.8, 3, 4, 4.6, 5.5, 6.5, 0.3, 0.1,
1.95, 1.9, 1.8, 2, 2.3, 2.6, 2.5, 4.1, 4.4,
1.3, 1.1, 1.0, 1.1, 0.9, 0.8, 0.95, 1.3, 1.35
)
export_index <- matrix(export_index, ncol = 9, byrow = TRUE)
colnames(export_index) <- c("2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022")
rownames(export_index) <- c("Bulk wine export Australia to China", "Australia Index", "Chile Index", "France Index")
# Convertir a data frame largo
df <- as.data.frame(export_index)
df$Category <- rownames(export_index)
df_long <- df %>%
pivot_longer(cols = -Category, names_to = "Year", values_to = "Value") %>%
mutate(
Type = ifelse(Category == "Bulk wine export Australia to China", "Bar", "Line"),
Year = factor(Year, levels = colnames(export_index))
)
# Crear el gráfico con ggplot2
p <- ggplot(df_long, aes(x = Year, y = Value, color = Category, group = Category)) +
# Líneas para los índices
geom_line(data = filter(df_long, Type == "Line"), linewidth = 1) +
geom_point(data = filter(df_long, Type == "Line"), size = 2.5) +
# Barras para exportaciones de vino
geom_col(data = filter(df_long, Type == "Bar"),
aes(fill = Category), alpha = 0.7, color = NA) +
scale_color_manual(values = c(
"Bulk wine export Australia to China" = "#8B0000",
"Australia Index" = "#FF6B6B",
"Chile Index" = "#FFFF00",
"France Index" = "#45B7FF"
)) +
scale_fill_manual(values = c("Bulk wine export Australia to China" = "#00f200")) +
labs(
title = "Export Index: Wine and Country Indices (2014-2022)",
x = "Year",
y = "Index Value",
color = "Category",
fill = "Category"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "right"
)
# Convertir a plotly para interactividad
fig <- ggplotly(p, tooltip = c("x", "y", "colour"))
# Mostrar el gráfico
fig
Example 2 - AI and Logistics for Water Management



The model initially built in LOGO was implemented in R-Cran. CLAUDE
was then used to generate a dynamic model that would improve the
reliability of water distribution and conservation strategies for human,
agricultural, and industrial consumption, minimizing last-mile logistics
costs.
Example 3 - Quality of Data for Operational Excellence

In this research, the quality documentation systems of 50 companies
in the retail and automotive sectors were used as training material for
a language model (using Llama 3 and Deep Seek on low-cost local
servers). By using the PRISMA methodology for systematic literature
review, the agent was improved, enabling it to generate recommendations
for SMEs that lead to operational excellence.
LS0tCnRpdGxlOiBJcyBpdCB0aGUgZW5kIG9mIGdsb2JhbGl6YXRpb24/IE9yIGlzIGEgY29tbWl0bWVudCB0byBjcml0aWNhbCBpbmZyYXN0cnVjdHVyZSAgIHN1cHBseSBjaGFpbnM/CmF1dGhvcjoKLSBuYW1lOiBSaWNhcmRvIFIuIFBhbG1hIDxyaWNhcmRvLnBhbG1hQGluZ2VuaWVyaWEudW5jdXlvLmVkdS5hcj4KICBhZmZpbGlhdGlvbjogJ0luc3RpdHV0byBkZSBJbmdlbmllcsOtYSBJbmR1c3RyaWFsLCAgVW5pdmVyc2lkYWQgTmFjaW9uYWwgZGUgQ3V5bywKICAgIE1lbmRvemEsIEFyZ2VudGluYSAnCi0gbmFtZTogRW1pbGlhbm8gVG9iYXJlcyA8ZW1pbGlhbm8udG9iYXJlc0BpbmdlbmllcmlhLnVuY3V5by5lZHUuYXI+CiAgYWZmaWxpYXRpb246ICdEacKzIERvY3RvcmFkbyBlbiAgSW5nZW5pZXLDrWEgSW5kdXN0cmlhbCwgIFVuaXZlcnNpZGFkIE5hY2lvbmFsIGRlCiAgICBDdXlvLCBNZW5kb3phLCBBcmdlbnRpbmEgJwotIG5hbWU6IE1hdXJvIEJlbmV0dGkgPG1hdXJvLmJlbmV0dGlAZ21haWwuY29tPgogIGFmZmlsaWF0aW9uOiAnRGnCsyBEb2N0b3JhZG8gZW4gIEluZ2VuaWVyw61hIEluZHVzdHJpYWwsICBVbml2ZXJzaWRhZCBOYWNpb25hbCBkZQogICAgQ3V5bywgTWVuZG96YSwgQXJnZW50aW5hICcgICAgCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKY3NsOiBhcGEuY3NsCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIEFnZW5kYQoKLSAgIENsaW1hdGUgY2hhbmdlIGFuZCBtYW51ZmFjdHVyaW5nCi0gICBVbml0ZWQgTmF0aW9ucyBUaW1lbGluZQotICAgTWV0cmljcyBvZiB0aGUgZ2xvYmFsaXphdGlvbgotICAgT25lIG1hbiBpcyBPbmUgbWFuCi0gICBUaGUgcm9sZSBvZiBoZWdlbW9uaWMgcG93ZXJzCi0gICBXaGF0IGEgY3JpdGljYWwgaW5mcmFzdHJ1Y3R1cmUgaXM/Ci0gICBQb3N0LUNPVklEIGFuZCBDSSBwcm90ZWN0aW9uCi0gICBXaW5lIFN1cHBseSBDaGFpbiBDYXNlCi0gICBBSSBhbmQgTG9naXN0aWNzIGZvciBXYXRlciBNYW5hZ2VtZW50Ci0gICBDb25jbHVzaW9uCgohW0NvbmZlcmVuY2UgUGFwZXJdKGltYWdlbi9Mb2dDb2xhYi5wbmcpCgojIyBEaXNjbGFpbWVyCgotICAgVGhpcyBwcmVzZW50YXRpb24gaGFkIGJlZW4gZGV2ZWxvcGVkIGZvbGxvd2luZyB0aGUgKipPcGVuIFNjaWVuY2UqKiBwYXJhZGlnbS4KCi0gICBGdXJ0aGVybW9yZSwgd2UgaGF2ZSBjaG9zZW4gdG8gdXBob2xkIHRoZSBwcmluY2lwbGVzIG9mIGEgaGlnaCBncmFkaWVudCBvZiByZXByb2R1Y2liaWxpdHkuCgohW10oaW1hZ2VuL2dyYWRpZW50ZS5wbmcpCgpZb3UgY2FuIGRvd25sb2FkIGNvZGUsIGRhdGFzZXRzIGFuZCBuZXcgdmVyc2lvbiBvZiB0aGlzIGRvY3VtZW50IGZyb20gOiA8aHR0cHM6Ly9ycHVicy5jb20vcmljYXJkb3JwYWxtYS8xMzUxNDc1PgoKKipET0kqKiAxMC41MjgxL3plbm9kby4xNzI2MjYxNQoKPGh0dHBzOi8vemVub2RvLm9yZy9yZWNvcmRzLzE3MjYyNjE1PgoKIyBDbGltYXRlIGNoYW5nZSB0aW1lbGluZQoKYGBge3IgfQojIEluc3RhbGFjacOzbiBkZSBwYXF1ZXRlcyBuZWNlc2FyaW9zIChkZXNjb21lbnRhIHNpIG5vIGxvcyB0aWVuZXMpCiMgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCiMgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQojIGluc3RhbGwucGFja2FnZXMoImdndGV4dCIpCm9wdGlvbnMod2FybiA9IC0xKQpsaWJyYXJ5KGdncGxvdDIpCgpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShkcGx5cikpCgpzdXBwcmVzc1dhcm5pbmdzKGxpYnJhcnkoZ2d0ZXh0KSkKCiMgRGF0b3MgZGUgbGFzIENvbmZlcmVuY2lhcyBDT1AKY29wX2RhdGEgPC0gZGF0YS5mcmFtZSgKICB5ZWFyID0gYygxOTk3LCAyMDA1LCAyMDA3LCAyMDA5LCAyMDExLCAyMDEyLCAyMDE1LCAyMDIxLCAyMDI0LCAyMDI1KSwKICBldmVudCA9IGMoIkNPUDMiLCAiQ09QMTEvTU9QMSIsICJDT1AxMyIsICJDT1AxNSIsICJDT1AxNyIsICJDT1AxOCIsICJDT1AyMSIsICJDT1AyNiIsICJDT1AyOSIsICJDT1AzMCIpLAogIHRpdGxlID0gYygKICAgICJQcm90b2NvbG8gZGUgS2lvdG8iLAogICAgIkVudHJhZGEgZW4gdmlnb3IgZGUgS2lvdG8iLAogICAgIlBsYW4gZGUgQWNjacOzbiBkZSBCYWxpIiwKICAgICJBY3VlcmRvIGRlIENvcGVuaGFndWUiLAogICAgIlBsYXRhZm9ybWEgZGUgRHVyYmFuIiwKICAgICJFbm1pZW5kYSBkZSBEb2hhIiwKICAgICJBY3VlcmRvIGRlIFBhcsOtcyIsCiAgICAiUGFjdG8gZGUgR2xhc2dvdyIsCiAgICAiQ09QMjkiLAogICAgIkNPUDMwIgogICksCiAgbG9jYXRpb24gPSBjKAogICAgIktpb3RvLCBKYXDDs24iLAogICAgIk1vbnRyZWFsLCBDYW5hZMOhIiwKICAgICJCYWxpLCBJbmRvbmVzaWEiLAogICAgIkNvcGVuaGFndWUsIERpbmFtYXJjYSIsCiAgICAiRHVyYmFuLCBTdWTDoWZyaWNhIiwKICAgICJEb2hhLCBDYXRhciIsCiAgICAiUGFyw61zLCBGcmFuY2lhIiwKICAgICJHbGFzZ293LCBSZWlubyBVbmlkbyIsCiAgICAiQmFrw7osIEF6ZXJiYWl5w6FuIiwKICAgICJCZWzDqW0sIEJyYXNpbCIKICApLAogIGRlc2NyaXB0aW9uID0gYygKICAgICJNZXRhcyB2aW5jdWxhbnRlcyBkZSByZWR1Y2Npw7NuIGRlXG5lbWlzaW9uZXMgNi04JSB2cyAxOTkwIiwKICAgICJQcmltZXJhIHJldW5pw7NuIGRlIGxhcyBQYXJ0ZXNcbmRlbCBwcm90b2NvbG8uICsxMCwwMDAgZGVsZWdhZG9zIiwKICAgICJDcm9ub2dyYW1hIHBhcmEgZWwgbWFyY28gcG9zdC0yMDEyLlxuR3J1cG8gZGUgYWNjacOzbiBjb29wZXJhdGl2YSIsCiAgICAiMTkyIHBhw61zZXMuIENvbXByb21pc28gZGVcbiQzMCBtaWwgbWlsbG9uZXMgMjAxMC0yMDEyIiwKICAgICJOZWdvY2lhY2lvbmVzIHBhcmEgYWN1ZXJkbyB2aW5jdWxhbnRlLlxuRm9uZG8gVmVyZGUgJDEwMCBtaWwgbWlsbG9uZXMiLAogICAgIlNlZ3VuZG8gcGVyw61vZG8gZGUgY29tcHJvbWlzb1xuS2lvdG8gMjAxMy0yMDIwIiwKICAgICJNYW50ZW5lciBjYWxlbnRhbWllbnRvIDwywrBDLlxuUGFydGljaXBhY2nDs24gdW5pdmVyc2FsIiwKICAgICJQcmltZXIgYmFsYW5jZSBnbG9iYWwgZGVsXG5BY3VlcmRvIGRlIFBhcsOtcy4gKzQwLDAwMCBwYXJ0aWNpcGFudGVzIiwKICAgICJBY3VlcmRvIGRlICQzMDAsMDAwIG1pbGxvbmVzXG5hbnVhbGVzIHBhcmEgcGHDrXNlcyBlbiBkZXNhcnJvbGxvIiwKICAgICJQcmV2aXN0YSBwYXJhIG5vdmllbWJyZSAyMDI1LlxuTnVldmFzIE5EQ3MgMy4wIgogICksCiAgaGlnaGxpZ2h0ID0gYyhUUlVFLCBGQUxTRSwgRkFMU0UsIEZBTFNFLCBGQUxTRSwgRkFMU0UsIFRSVUUsIEZBTFNFLCBGQUxTRSwgVFJVRSksCiAgc2lkZSA9IGMoImxlZnQiLCAicmlnaHQiLCAibGVmdCIsICJyaWdodCIsICJsZWZ0IiwgInJpZ2h0IiwgImxlZnQiLCAicmlnaHQiLCAibGVmdCIsICJyaWdodCIpCikKCiMgQ3JlYXIgZWwgZ3LDoWZpY28KcCA8LSBnZ3Bsb3QoY29wX2RhdGEsIGFlcyh4ID0geWVhciwgeSA9IDApKSArCiAgCiAgIyBMw61uZWEgZGUgdGllbXBvIGNlbnRyYWwKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBtaW4oeWVhciksIHhlbmQgPSBtYXgoeWVhciksIHkgPSAwLCB5ZW5kID0gMCksCiAgICAgICAgICAgICAgIGNvbG9yID0gIiM2NjdlZWEiLCBzaXplID0gMS41LCBsaW5lZW5kID0gInJvdW5kIikgKwogIAogICMgUHVudG9zIGVuIGxhIGzDrW5lYSBkZSB0aWVtcG8KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGhpZ2hsaWdodCksIHNpemUgPSA4LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlRSVUUiID0gIiNlNzRjM2MiLCAiRkFMU0UiID0gIiM2NjdlZWEiKSkgKwogIAogICMgTMOtbmVhcyBjb25lY3RvcmFzIGEgbGFzIGNhamFzIGRlIHRleHRvCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBjb3BfZGF0YSAlPiUgZmlsdGVyKHNpZGUgPT0gImxlZnQiKSwKICAgICAgICAgICAgICAgYWVzKHggPSB5ZWFyLCB4ZW5kID0geWVhciwgeSA9IDAsIHllbmQgPSAwLjMpLAogICAgICAgICAgICAgICBjb2xvciA9ICIjNjY3ZWVhIiwgc2l6ZSA9IDAuOCwgbGluZXR5cGUgPSAic29saWQiKSArCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBjb3BfZGF0YSAlPiUgZmlsdGVyKHNpZGUgPT0gInJpZ2h0IiksCiAgICAgICAgICAgICAgIGFlcyh4ID0geWVhciwgeGVuZCA9IHllYXIsIHkgPSAwLCB5ZW5kID0gLTAuMyksCiAgICAgICAgICAgICAgIGNvbG9yID0gIiM2NjdlZWEiLCBzaXplID0gMC44LCBsaW5ldHlwZSA9ICJzb2xpZCIpICsKICAKICAjIENhamFzIGRlIGV2ZW50b3MgKGxhZG8gaXpxdWllcmRvL2FycmliYSkKICBnZW9tX2xhYmVsKGRhdGEgPSBjb3BfZGF0YSAlPiUgZmlsdGVyKHNpZGUgPT0gImxlZnQiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwgeSA9IDAuMzUsIAogICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCIqKiIsIHllYXIsICIgLSAiLCB0aXRsZSwgIioqXG4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIvCfk40gIiwgbG9jYXRpb24sICJcblxuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uKSwKICAgICAgICAgICAgICAgICBmaWxsID0gaGlnaGxpZ2h0KSwKICAgICAgICAgICAgIGhqdXN0ID0gMC41LCB2anVzdCA9IDAsIHNpemUgPSAzLjUsCiAgICAgICAgICAgICBsaW5laGVpZ2h0ID0gMC45LCBsYWJlbC5wYWRkaW5nID0gdW5pdCgwLjUsICJsaW5lcyIpLAogICAgICAgICAgICAgbGFiZWwuc2l6ZSA9IDAuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIAogICMgQ2FqYXMgZGUgZXZlbnRvcyAobGFkbyBkZXJlY2hvL2FiYWpvKQogIGdlb21fbGFiZWwoZGF0YSA9IGNvcF9kYXRhICU+JSBmaWx0ZXIoc2lkZSA9PSAicmlnaHQiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwgeSA9IC0wLjM1LCAKICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiKioiLCB5ZWFyLCAiIC0gIiwgdGl0bGUsICIqKlxuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLwn5ONICIsIGxvY2F0aW9uLCAiXG5cbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiksCiAgICAgICAgICAgICAgICAgZmlsbCA9IGhpZ2hsaWdodCksCiAgICAgICAgICAgICBoanVzdCA9IDAuNSwgdmp1c3QgPSAxLCBzaXplID0gMy41LAogICAgICAgICAgICAgbGluZWhlaWdodCA9IDAuOSwgbGFiZWwucGFkZGluZyA9IHVuaXQoMC41LCAibGluZXMiKSwKICAgICAgICAgICAgIGxhYmVsLnNpemUgPSAwLjUsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJUUlVFIiA9ICIjNjY3ZWVhIiwgIkZBTFNFIiA9ICIjZWNmMGYxIikpICsKICAKICAjIEV0aXF1ZXRhcyBkZSBhw7FvcyBlbiBsYSBsw61uZWEKICBnZW9tX3RleHQoYWVzKGxhYmVsID0geWVhciksIHkgPSAtMC4wNSwgdmp1c3QgPSAxLjUsIAogICAgICAgICAgICBzaXplID0gMywgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gIiMyYzNlNTAiKSArCiAgCiAgIyBDb25maWd1cmFjacOzbiBkZSBlc2NhbGFzIHkgdGVtYQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjb3BfZGF0YSR5ZWFyLCBsaW1pdHMgPSBjKDE5OTUsIDIwMjcpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTAuOCwgMC44KSkgKwogIAogIGxhYnMoCiAgICB0aXRsZSA9ICLwn4yNIENvbmZlcmVuY2lhcyBkZSBsYSBPTlUgc29icmUgQ2FtYmlvIENsaW3DoXRpY28iLAogICAgc3VidGl0bGUgPSAiRGVsIFByb3RvY29sbyBkZSBLaW90byAoMTk5NykgYSBsYSBDT1AzMCAoMjAyNSkiLAogICAgY2FwdGlvbiA9ICJGdWVudGU6IFVORkNDQyB8IEV2ZW50b3MgZGVzdGFjYWRvczogS2lvdG8sIFBhcsOtcyB5IENPUDMwIgogICkgKwogIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMmMzZTUwIiwgbWFyZ2luID0gbWFyZ2luKGIgPSA1KSksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgaGp1c3QgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjN2Y4YzhkIiwgbWFyZ2luID0gbWFyZ2luKGIgPSAyMCkpLAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiIzk1YTVhNiIsIGhqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gbWFyZ2luKHQgPSAyMCkpLAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNmOGY5ZmEiLCBjb2xvciA9IE5BKSwKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjZjhmOWZhIiwgY29sb3IgPSBOQSksCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigzMCwgMzAsIDMwLCAzMCkKICApCgojIE1vc3RyYXIgZWwgZ3LDoWZpY28KcHJpbnQocCkKCiMgR3VhcmRhciBlbCBncsOhZmljbyAob3BjaW9uYWwpCiMgZ2dzYXZlKCJ0aW1lbGluZV9jb3BfY29uZmVyZW5jaWFzLnBuZyIsIHBsb3QgPSBwLCAKIyAgICAgICAgd2lkdGggPSAxNiwgaGVpZ2h0ID0gMTAsIGRwaSA9IDMwMCwgYmcgPSAiI2Y4ZjlmYSIpCmBgYAoKYGBge3J9CnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KGthYmxlRXh0cmEpKQojIGthYmxlKGNvcF9kYXRhWyAsMTo1XSwgZm9ybWF0ID0gImh0bWwiKQpjb3BfZGF0YVsgLDE6NV0gJT4lCiAga2JsKCkgJT4lCiAga2FibGVfbWF0ZXJpYWwoYygic3RyaXBlZCIsICJob3ZlciIpKQoKYGBgCgojIyBNZXRyaWNzIG9mIHRoZSBnbG9iYWxpemF0aW9uCgpUaG9zZSBhcmUgdGhlIHNvLWNhbGxlZCAiZW5kIG9mIGdsb2JhbGl6YXRpb24iIG1ldHJpY3MuCgohW10oaW1hZ2VuL3Jlc2hvcmluZy5wbmcpCgo8aHI+CgojIyMgT2Zmc2hvcmluZwoKKipPZmZzaG9yaW5nKiogaXMgdGhlIHByYWN0aWNlIG9mIHJlbG9jYXRpbmcgYSBidXNpbmVzcyBwcm9jZXNzLCBtYW51ZmFjdHVyaW5nLCBvciBzZXJ2aWNlIHRvIGEgZGlzdGFudCBmb3JlaWduIGNvdW50cnksIHR5cGljYWxseSB0byB0YWtlIGFkdmFudGFnZSBvZiBsb3dlciBsYWJvciBjb3N0cyBvciBvdGhlciBlY29ub21pYyBiZW5lZml0cyAoZW52aXJvbm1lbnRhbCkuCgotICAgKipMb2NhdGlvbjoqKiBBIGNvdW50cnkgZmFyIGZyb20gdGhlIGNvbXBhbnkncyBob21lIGNvdW50cnkgKGUuZy4sIGEgVS5TLiBjb21wYW55IG1vdmluZyBtYW51ZmFjdHVyaW5nIHRvIENoaW5hIG9yIGEgRXVyb3BlYW4gY29tcGFueSBtb3ZpbmcgSVQgc3VwcG9ydCB0byBJbmRpYSkuCgotICAgKipQcmltYXJ5IE1vdGl2YXRpb246KiogU2lnbmlmaWNhbnQgY29zdCBzYXZpbmdzLCBhY2Nlc3MgdG8gc3BlY2lhbGl6ZWQgc2tpbGxzLCBhbmQgZ2xvYmFsIG1hcmtldCBleHBhbnNpb24uCgotICAgKipUcmFkZS1vZmZzOioqIFBvdGVudGlhbCBmb3IgbG9uZyBzdXBwbHkgY2hhaW5zLCBzaWduaWZpY2FudCB0aW1lIHpvbmUgZGlmZmVyZW5jZXMsIGN1bHR1cmFsL2xhbmd1YWdlIGJhcnJpZXJzLCBhbmQgcmVkdWNlZCBzdXBwbHkgY2hhaW4gdmlzaWJpbGl0eS9jb250cm9sLgoKPGhyPgoKIyMjIFJlLXNob3JpbmcgKGFsc28gY2FsbGVkIE9uc2hvcmluZykKCioqUmUtc2hvcmluZyoqIGlzIHRoZSBwcm9jZXNzIG9mIGJyaW5naW5nIGJ1c2luZXNzIG9wZXJhdGlvbnMsIHByb2R1Y3Rpb24sIG9yIHNlcnZpY2VzIGJhY2sgdG8gdGhlIGNvbXBhbnkncyBvcmlnaW5hbCBob21lIGNvdW50cnkgYWZ0ZXIgdGhleSB3ZXJlIHByZXZpb3VzbHkgbW92ZWQgb3ZlcnNlYXMgKG9mZnNob3JlZCkuCgotICAgKipMb2NhdGlvbjoqKiBUaGUgY29tcGFueSdzIGhvbWUgY291bnRyeS4KCi0gICAqKlByaW1hcnkgTW90aXZhdGlvbjoqKiBJbmNyZWFzaW5nIHN1cHBseSBjaGFpbiByZXNpbGllbmNlIGFuZCBjb250cm9sLCByZWR1Y2luZyBsZWFkIHRpbWVzLCBpbXByb3ZpbmcgcHJvZHVjdCBxdWFsaXR5IG92ZXJzaWdodCwgYXZvaWRpbmcgZ2VvcG9saXRpY2FsIHJpc2tzLCBhbmQgbGV2ZXJhZ2luZyB0aGUgIk1hZGUgaW4gW0hvbWUgQ291bnRyeV0iIGFwcGVhbC4KCi0gICAqKlRyYWRlLW9mZnM6KiogR2VuZXJhbGx5IGludm9sdmVzIGhpZ2hlciBsYWJvciBhbmQgb3BlcmF0aW9uYWwgY29zdHMgY29tcGFyZWQgdG8gb2Zmc2hvcmUgbG9jYXRpb25zLgoKPGhyPgoKIyMjIE5lYXItc2hvcmluZwoKKipOZWFyLXNob3JpbmcqKiBpbnZvbHZlcyByZWxvY2F0aW5nIGJ1c2luZXNzIG9wZXJhdGlvbnMgb3Igc2VydmljZXMgdG8gYSBuZWFyYnkgZm9yZWlnbiBjb3VudHJ5LCB0eXBpY2FsbHkgb25lIHRoYXQgaXMgZ2VvZ3JhcGhpY2FsbHkgcHJveGltYXRlLCBvZnRlbiBzaGFyaW5nIGEgYm9yZGVyIG9yIGJlaW5nIHdpdGhpbiBhIGNsb3NlIHRpbWUgem9uZS4KCi0gICAqKkxvY2F0aW9uOioqIEEgbmVpZ2hib3Jpbmcgb3IgZ2VvZ3JhcGhpY2FsbHkgY2xvc2UgY291bnRyeSAoZS5nLiwgYSBVLlMuIGNvbXBhbnkgbW92aW5nIHByb2R1Y3Rpb24gdG8gTWV4aWNvIG9yIGEgRnJlbmNoIGNvbXBhbnkgbW92aW5nIElUIHRvIFJvbWFuaWEpLgoKLSAgICoqUHJpbWFyeSBNb3RpdmF0aW9uOioqIFNlZWtpbmcgYSBiYWxhbmNlIGJldHdlZW4gY29zdCBzYXZpbmdzIChsb3dlciBjb3N0cyB0aGFuIHRoZSBob21lIGNvdW50cnkpIGFuZCB0aGUgYmVuZWZpdHMgb2YgcHJveGltaXR5LCBzdWNoIGFzIHNob3J0ZXIgc2hpcHBpbmcgdGltZXMsIGZld2VyIHRpbWUgem9uZSBpc3N1ZXMsIGFuZCBlYXNpZXIgY29tbXVuaWNhdGlvbiBhbmQgdHJhdmVsIGZvciBvdmVyc2lnaHQuCgotICAgKipUcmFkZS1vZmZzOioqIENvc3RzIGFyZSB0eXBpY2FsbHkgbG93ZXIgdGhhbiByZS1zaG9yaW5nIGJ1dCBwb3RlbnRpYWxseSBoaWdoZXIgdGhhbiBmYXItb2ZmIG9mZnNob3JpbmcuIFRoZSBnb2FsIGlzIHRvIG1pdGlnYXRlIHRoZSBjb21wbGV4aXR5IGFuZCByaXNrIGFzc29jaWF0ZWQgd2l0aCBsb25nLWRpc3RhbmNlIG9mZnNob3Jpbmcgd2hpbGUgc3RpbGwgYWNoaWV2aW5nIHNvbWUgY29zdCBhZHZhbnRhZ2VzCgojIyBPbmUgbWFuIGlzIE9uZSBtYW4gZXZlcnl3aGVyZQoKYGBgICAgICAgICAgCiogQSBVUyBjaXRpemVuIGVtaXRzIHNldmVuIHRpbWVzIG1vcmUgdGhhbiBhIEV1cm9wZWFuIGNpdGl6ZW4uIENoaW5hIHByb3Bvc2VzIHJlZHVjaW5nIGVtaXNzaW9ucyBiYXNlZCBvbiBxdW90YXMgcGVyIGNvdW50cnkuCgoKKiBBIENoaW5lc2UgY2l0aXplbiBlbWl0cyAxNSB0aW1lcyBsZXNzIHRoYW4gYSBFdXJvcGVhbiwgYnV0IHVzZXMgY29hbC4gRnVydGhlcm1vcmUsIHRoZXkgaGF2ZSBhIGh1Z2UgcG9wdWxhdGlvbi4gVGhlIFVTIHByb3Bvc2VzIHJlZHVjaW5nIENoaW5hJ3MgZW1pc3Npb25zIGFuZCBxdWFsaXR5IHdpdGhvdXQgYWx0ZXJpbmcgaXRzIG93biBlbWl0aW9uIHJhdGUuIChNQUdBKQoKCiogSW5kaWEgaGFzIGxvd2VyZWQgaXRzIGVuZXJneSBpbnRlbnNpdHkgKFRPRSB2cy4gR0RQKSwgcHJvcG9zaW5nIHRoYXQgb25lIG1hbiBlcXVhbHMgb25lIG1hbi4gRGV2ZWxvcGVkIGNvdW50cmllcyBoYXZlIGFscmVhZHkgImJ1cm5lZCIgdGhlaXIgc2hhcmUgb2YgZnVlbC4gVGhlbiB0aGVpciBuZWVkIHRvIHJlZHVjZSBoaXMgZW1pc3Npb25zIGFuZCBhbGxvdyBkZXZlbG9waW5nIGNvdW50cmllcyB0byBjbG9zZSB0aGUgaW5lcXVhbGl0eSBnYXAuCmBgYAoKIyBUaGUgcm9sZSBvZiBoZWdlbW9uaWMgcG93ZXJzCgpgYGAgICAgICAgICAKVGhlcmUgYXJlIGh1bmRyZWRzIG9mIGV4YW1wbGVzIHRocm91Z2hvdXQgaGlzdG9yeSBvZiB3aGF0IGhhcHBlbnMgd2hlbiBhIGhlZ2Vtb25pYyBwb3dlciBkaXNhcHBlYXJzICh0aGUgUm9tYW4gRW1waXJlKS4gVGhlcmUgaXMgYSB0cmFuc2l0aW9uIHBlcmlvZCB3aXRoIHdhcnMgYW5kIGEgZHJhbWF0aWMgcmVkdWN0aW9uIGluICJpbnRlcm5hdGlvbmFsIiB0cmFkZS4KYGBgCgpgYGAgICAgICAgICAKSXQgaXMgYSBwYWluZnVsIHByb2Nlc3MgdGhhdCByZXF1aXJlcyBhIGNoYW5nZSBpbiAqKmN1bHR1cmUqKiB1bnRpbCB0aGUgbmV3IHBvd2VyIG1hbmFnZXMgdG8gZXN0YWJsaXNoIGl0c2VsZi4gVGhlIGhlZ2Vtb25pYyBwb3dlciB0aGF0IHRlbmRzIHRvIGRpc2FwcGVhciB1c2VzIGEgKipjb3B5IG9mIHRoZSBzdHJhdGVnaWVzKiogdGhhdCBhbGxvd2VkIHRoZSBlbWVyZ2luZyBwb3dlciB0byBncm93LioqVHJ1c3QqKiBpcyBhbHNvIGxvc3QgYmV0d2VlbiBzdHJhdGVnaWMgcGFydG5lcnMuCmBgYAoKYGBgICAgICAgICAgClRoZSBVUyBpcyBicmVha2luZyB0aWVzIHdpdGggRXVyb3BlLiBJdCB3YW50cyB0byBiZWNvbWUgZ3JlYXQgYWdhaW4gYnkgaW1pdGF0aW5nIHRoZSBlY29ub21pYyBwcm9jZXNzZXMgb2YgSW5kdXN0cnkgMi4wLiBJdCdzIGNsb3NpbmcgaXRzIGRvb3JzIHRvIGJyYWlucy4gSXQgZG9lc24ndCBzdXBwb3J0IGVsZWN0cmljIGNhcnMgb3IgNUcuCmBgYAoKYGBgICAgICAgICAgCkl0IGNyZWF0ZSBJbmR1c3RyeSA1LjAgaW4gU2lsaWNvbiBWYWxsZXkgYW5kIG9wZXJhdGUgb25seSB3aXRoIHRhcmlmZnMgdGhhdCBpbXBhY3QgdGhlIGdsb2JhbCBzdXBwbHkgY2hhaW5zLgpgYGAKCiMjIFRoZSBlbmQgb2YgZ2xvYmFsaXphdGlvbgoKVGhlICoqImVuZCBvZiBnbG9iYWxpemF0aW9uIioqIGlzIGEgd2lkZWx5IGRpc2N1c3NlZCBjb25jZXB0IHN1Z2dlc3RpbmcgdGhhdCB0aGUgZGVlcCwgZmFzdCwgYW5kIGV4dGVuc2l2ZSBpbnRlZ3JhdGlvbiBvZiB0aGUgd29ybGQncyBlY29ub21pZXMsIGN1bHR1cmVzLCBhbmQgcG9saXRpY3PigJRhIHByb2Nlc3Mga25vd24gYXMgZ2xvYmFsaXphdGlvbuKAlGlzIHNsb3dpbmcgZG93biwgc3RhZ25hdGluZywgb3IgZXZlbiByZXZlcnNpbmcuCgoxLSBSaXNlIG9mIEVjb25vbWljIE5hdGlvbmFsaXNtIGFuZCBQcm90ZWN0aW9uaXNtCgoyLSBUcmFkZSBXYXJzIGFuZCBUYXJpZmZzCgozLSBQb3B1bGlzdCBCYWNrbGFzaAoKNC0gR3Jvd2luZyBlcm9zaW9uIG9mIGluc3RpdHV0aW9uYWxpc20gKGluY2x1ZGluZyBXZXN0ZXJuIGRlbW9jcmFjaWVzKQoKNS0gU3VwcGx5IENoYWluIFZ1bG5lcmFiaWxpdHkKCjYtIFNob2NrcyBhbmQgRGlzcnVwdGlvbnM6IE1ham9yIGV2ZW50cyBsaWtlIHRoZSAyMDA4IGZpbmFuY2lhbCBjcmlzaXMsIHRoZSBDT1ZJRC0xOSBwYW5kZW1pYywgYW5kIHRoZSBSdXNzaWEtVWtyYWluZSB3YXIgZXhwb3NlZCB0aGUgZnJhZ2lsaXR5IG9mIGhpZ2hseSBvcHRpbWl6ZWQsIGp1c3QtaW4tdGltZSBnbG9iYWwgc3VwcGx5IGNoYWlucy4KCjctIEZvY3VzIG9uIFJlc2lsaWVuY2UKCiMgV2hhdCBhIGNyaXRpY2FsIGluZnJhc3RydWN0dXJlIGlzPwoKSW5mcmFzdHJ1Y3R1cmUgaXMgbm8gbG9uZ2VyIGp1c3QgYnJpZGdlcywgcm9hZHMsIGFuZCB0aGUgbGlrZeKAlGl0IG5vdyBpbmNsdWRlcyBlbGVtZW50cyByYW5naW5nIGZyb20gZGlnaXRhbCBuZXR3b3JrcyB0byBjbGVhbi1lbmVyZ3kgc3lzdGVtcyB0byBlbGVjdHJpYy12ZWhpY2xlIGNoYXJnaW5nIGNvcnJpZG9ycy4KClRvIG1lZXQgdGhlIGdyb3dpbmcgZGVtYW5kIGZvciBpbmZyYXN0cnVjdHVyZSwgTWNLaW5zZXkgZXN0aW1hdGVzIHRoYXQgYSBjdW11bGF0aXZlIFwkMTA2IHRyaWxsaW9uIGluIGludmVzdG1lbnQgd2lsbCBiZSBuZWNlc3NhcnkgdGhyb3VnaCAyMDQwLiBBc2lhIGlzIGV4cGVjdGVkIHRvIHJlY2VpdmUgbW9yZSB0aGFuIGhhbGYgb2YgdGhlIHRvdGFsIGluZnJhc3RydWN0dXJlIGludmVzdG1lbnQgdGhyb3VnaCAyMDQwLCBkcml2ZW4gYnkgcmFwaWQgdXJiYW5pemF0aW9uLCBwb3B1bGF0aW9uIGdyb3d0aCwgYW5kIGNvbnRpbnVlZCBpbmR1c3RyaWFsIGV4cGFuc2lvbi4KCiMjIEluZnJhbm9taWNzCgpJbnRyb2R1Y2luZyBJbmZyYW5vbWljcywgYXMgYSBjcnVjaWFsIGRpc2NpcGxpbmUgZm9yIHRoaXMgY2VudHVyeS4gTmVpdGhlciBhdXRob3JpdGllcywgbm9yIGluZHVzdHJpYWwgb3IgYWNhZGVtaWMgYm9kaWVzIGNvdWxkIGFmZm9yZCB0byBpZ25vcmUgdGhlIGFkdmVudCBvZiB0aGUgY29udm9sdXRpb24gb2Ygb3Bwb3J0dW5pdGllcyBhbmQgcmlza3MgYWNjb21wYW55aW5nIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgbmV3IGdlbmVyYXRpb24gb2YgaW5mcmFzdHJ1Y3R1cmVzLiBUaGUgc2hhcGUgb2Ygb3VyIHNvY2lldHkgd2lsbCBiZSBkZXRlcm1pbmVkIGJ5IHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2YsIGFuZCB0aGUgc2VydmljZXMgZGVsaXZlcmVkIHRocm91Z2gsIHRob3NlIGluZnJhc3RydWN0dXJlcy4gSXQgaXMgYXJndWVkIHRoYXQgSW5mcmFub21pY3MgaXMgdGhlIGJvZHkgb2YgZGlzY2lwbGluZXMgc3VwcG9ydGluZyB0aGUgYW5hbHlzaXMgYW5kIGRlY2lzaW9uLW1ha2luZyByZWdhcmRpbmcgdGhlIG1ldGFzeXN0ZW0KCkludHJvZHVjaW5nIEluZnJhbm9taWNzLCBhcyBhIGNydWNpYWwgZGlzY2lwbGluZSBmb3IgdGhpcyBjZW50dXJ5LiBOZWl0aGVyIGF1dGhvcml0aWVzLCBub3IgaW5kdXN0cmlhbCBvciBhY2FkZW1pYyBib2RpZXMgY291bGQgYWZmb3JkIHRvIGlnbm9yZSB0aGUgYWR2ZW50IG9mIHRoZSBjb252b2x1dGlvbiBvZiBvcHBvcnR1bml0aWVzIGFuZCByaXNrcyBhY2NvbXBhbnlpbmcgdGhlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBuZXcgZ2VuZXJhdGlvbiBvZiBpbmZyYXN0cnVjdHVyZXMuIFRoZSBzaGFwZSBvZiBvdXIgc29jaWV0eSB3aWxsIGJlIGRldGVybWluZWQgYnkgdGhlIGNoYXJhY3RlcmlzdGljcyBvZiwgYW5kIHRoZSBzZXJ2aWNlcyBkZWxpdmVyZWQgdGhyb3VnaCwgdGhvc2UgaW5mcmFzdHJ1Y3R1cmVzLiBJdCBpcyBhcmd1ZWQgdGhhdCBJbmZyYW5vbWljcyBpcyB0aGUgYm9keSBvZiBkaXNjaXBsaW5lcyBzdXBwb3J0aW5nIHRoZSBhbmFseXNpcyBhbmQgZGVjaXNpb24tbWFraW5nIHJlZ2FyZGluZyB0aGUgbWV0YXN5c3RlbSAhW10oaW1hZ2VuL2luZnJhbm9taWNzLnBuZyl7d2lkdGg9IjEyY20ifQoKIyMgUG9zdC1DT1ZJRCBhbmQgQ0kgcHJvdGVjdGlvbgoKPGh0dHBzOi8vcmljYXJkb3JwYWxtYS5naXRodWIuaW8vSUNfU0NNLz4KCiFbXShpbWFnZW4vY292ZXJNWkEucG5nKQoKIyBXaGF0IGRlY2lzaW9ucyBhbmQgcGF0aHMgdG8gdGFrZQoKVGhlIEluc3RpdHV0ZSBvZiBJbmR1c3RyaWFsIEVuZ2luZWVyaW5nIGFuZCBEacKzIGFyZSB3b3JraW5nIG9uIHRoZSBmb2xsb3dpbmcgbGluZXMgb2YgcmVzZWFyY2ggdGhhdCB1c2UgYXJ0aWZpY2lhbCBpbnRlbGxpZ2VuY2UgYW5kIGxhbmd1YWdlIG1vZGVscyB0byBpbnZlc3RpZ2F0ZSB3YXlzIHRvIG9wdGltaXplIGNyaXRpY2FsIGluZnJhc3RydWN0dXJlLCB3aGljaCBhcHBlYXJzIHRvIGJlIHRoZSBmb2N1cyBvZiBhdHRhY2tzIGFuZCBjeWJlcmF0dGFja3MgdG8gcmVkdWNlIGNvbXBldGl0aXZlbmVzcyBpbiB0aGVzZSBlbmQtb2YtZ2xvYmFsaXphdGlvbiBlbnZpcm9ubWVudHMuCgotICAgV2UgZmlybWx5IGJlbGlldmUgdGhhdCB1bml2ZXJzaXRpZXMgY2Fubm90IHNpbGVuY2UgdGhlaXIgdm9pY2VzIGFuZCBtdXN0IHdvcmsgdG93YXJkIGEgY3VsdHVyZSBvZiBwZWFjZS4KCi0gICBQbGF5aW5nIHdhciBnYW1lcywgYXMgbWFueSBsZWFkZXJzIGFyZSBkb2luZywgaXMgbW9yZSBkYW5nZXJvdXMgdGhhbiBwbGF5aW5nIFJ1c3NpYW4gcm91bGV0dGUgd2l0aCBudWNsZWFyIGJ1bGxldHMuCgotICAgQXMgYWNhZGVtaWNzLCBvdXIgZHV0eSBpcyB0byByZXNlYXJjaCwgZGlzY292ZXIsIGFuZCBwdXQgb24gdGhlIGFnZW5kYSBvZiBnb3Zlcm5tZW50cyBhbmQgY29tcGFuaWVzIHdoYXQgb3VyIG1vZGVscyB0ZWxsIHVzIHNob3VsZCBiZSB0aGUgcmlnaHQgdGhpbmcgdG8gZG8uCgojIyBVc2UgQ0kgYXMgaW50ZWxsaWdlbnRseSBhcyBwb3NzaWJsZQoKSXQgaXMgdmVyeSBjbGVhciB0aGF0IHRoZSBnb3Zlcm5tZW50cyBvZiBXZXN0ZXJuIGRlbW9jcmFjaWVzIHdpbGwgbm8gbG9uZ2VyIGhhdmUgdGhlIGNhcGFjaXR5IHRvIGludmVzdCBpbiBpbmZyYXN0cnVjdHVyZSBpbiB0aGUgd2F5IHRoZXkgZGlkIGluIHRoZSBmaXJzdCBoYWxmIG9mIHRoZSAyMHRoIGNlbnR1cnkuCgpUaGUgaW5mcmFzdHJ1Y3R1cmUgd2UgaW5oZXJpdGVkIHdpbGwgc29vbiBiZSBvdmVyd2hlbG1lZCBieSBleHBvbmVudGlhbCBwb3B1bGF0aW9uIGdyb3d0aC4KCk5ldyBlbnZpcm9ubWVudGFsIHJlc3RyaWN0aW9ucyBmb3JjZSB1cyB0byBiZWNvbWUgbW9yZSBlZmZpY2llbnQgb3IgZW5kdXJlIGluY3JlYXNpbmdseSBpbnRlbnNlIGFuZCBhZHZlcnNlIHdlYXRoZXIgZXZlbnRzLgoKIyMjIEEgQ2xldmVyIERlY2lzacOzbgoKYGBgICAgICAgICAgCiAgVVNFIEFSVElGSUNJQUwgSU5URUxMSUdFTkNFIFRPIEdFVCBUSEUgTUFYVU1VTiBPRiBZT1VSIENSSVRJQ0FMIElORlJBU1RSVUNUVVJFCmBgYAoKIyMgRVhBTVBMRSAxIC0gV2luZSBTdXBwbHkgQ2hhaW4gQ2FzZQoKIVtdKGltYWdlbi9md3NjY18yNC5wbmcpe3dpZHRoPSI1MCUifQoKIVtdKGltYWdlbi9wYXBlcl8xLnBuZykKCiMjIENoaW5hIGFuZCBBdXN0cmFsaWEgV2luZSBSb3V0aW5nCgp8IFl1dmFsIEhhcmFyaSBhbmQgdGhlIEZhaXQgfCBHb3Zlcm1lbnQgYW5kIFdpbmUgfCBDaGluZXNlIFdpbmU/IHwKfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8ICFbXShpbWFnZW4vcGFwZXJfZmUucG5nKSB8ICFbXShpbWFnZW4vcGFwZXJfZ29iaWVybm8ucG5nKSB8ICFbXShpbWFnZW4vd2luZV9jaGluYS5wbmcpIHwKCiMjIyBDaGluYSdzIHNoYXJlcyBvZiB0aGUgdm9sdW1lIG9mIHdvcmxkIHdpbmU6Cgp8IFllYXIgfCBQcm9kdWN0aW9uIHwgQ29uc3VtcHRpb24gfCBJbXBvcnRzIHwKfC0tLS0tLXwtLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwtLS0tLS0tLS18CnwgMjAxNCB8IDQuMCAgICAgICAgfCA1LjYgICAgICAgICB8IDMuNiAgICAgfAp8IDIwMTUgfCA0LjAgICAgICAgIHwgNi43ICAgICAgICAgfCA1LjIgICAgIHwKfCAyMDE2IHwgNC4wICAgICAgICB8IDYuOCAgICAgICAgIHwgNi4wICAgICB8CnwgMjAxNyB8IDMuNyAgICAgICAgfCA2LjcgICAgICAgICB8IDcuMCAgICAgfAp8IDIwMTggfCAyLjEgICAgICAgIHwgNS40ICAgICAgICAgfCA2LjUgICAgIHwKfCAyMDE5IHwgMS42ICAgICAgICB8IDQuMyAgICAgICAgIHwgNS44ICAgICB8CnwgMjAyMCB8IDEuMiAgICAgICAgfCAzLjEgICAgICAgICB8IDQuMSAgICAgfAp8IDIwMjEgfCAxLjAgICAgICAgIHwgMi45ICAgICAgICAgfCA0LjAgICAgIHwKfCAyMDIyIHwgMC43ICAgICAgICB8IDIuMiAgICAgICAgIHwgMy4yICAgICB8CnwgMjAyMyB8IDAuNiAgICAgICAgfCAyLjQgICAgICAgICB8IDMuNSAgICAgfAp8IDIwMjQgfCAwLjMgICAgICAgIHwgMi45ICAgICAgICAgfCAzLjEgICAgIHwKCmBgYHtyfQpzaGFyZXNfdm9sdW1lIDwtIGMoMjAxNCAsIDQuMCwgNS42LCAzLjYgLAoyMDE1ICwgNC4wLCA2LjcsIDUuMiAsCjIwMTYgLCA0LjAsIDYuOCwgNi4wICwKMjAxNyAsIDMuNywgNi43LCA3LjAgLAoyMDE4ICwgMi4xLCA1LjQsIDYuNSAsCjIwMTkgLCAxLjYsIDQuMywgNS44ICwKMjAyMCAsIDEuMiwgMy4xLCA0LjEgLAoyMDIxICwgMS4wLCAyLjksIDQuMCAsICAKMjAyMiAsIDAuNywgMi4yLCAzLjIgLAoyMDIzICwgMS42LCAyLjQsIDMuNSAsCjIwMjQgLCAgMywgMS4zLCAxLjUgKQoKc2hhcmVzX3ZvbHVtZSA8LSBtYXRyaXgoc2hhcmVzX3ZvbHVtZSxuY29sID0gNCwgYnlyb3cgPSBUUlVFKQpjb2xuYW1lcyhzaGFyZXNfdm9sdW1lKSA8LSBjKCJZZWFyIiwgIkNvbnN1bXB0aW9uIiwgIkNvbnN1bXB0aW9uIiwgIkltcG9ydHMiKQojIHNoYXJlc192b2x1bWUKYGBgCgpgYGB7cn0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoZ2dwbG90MikpCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KHBsb3RseSkpCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KHRpZHlyKSkKCiMgQ3JlYXIgZWwgdmVjdG9yIHkgbGEgbWF0cml6CnNoYXJlc192b2x1bWVfdmVjIDwtIGMoMjAxNCwgNC4wLCA1LjYsIDMuNiwKICAgICAgICAgICAgICAgICAgICAgICAyMDE1LCA0LjAsIDYuNywgNS4yLAogICAgICAgICAgICAgICAgICAgICAgIDIwMTYsIDQuMCwgNi44LCA2LjAsCiAgICAgICAgICAgICAgICAgICAgICAgMjAxNywgMy43LCA2LjcsIDcuMCwKICAgICAgICAgICAgICAgICAgICAgICAyMDE4LCAyLjEsIDUuNCwgNi41LAogICAgICAgICAgICAgICAgICAgICAgIDIwMTksIDEuNiwgNC4zLCA1LjgsCiAgICAgICAgICAgICAgICAgICAgICAgMjAyMCwgMS4yLCAzLjEsIDQuMSwKICAgICAgICAgICAgICAgICAgICAgICAyMDIxLCAxLjAsIDIuOSwgNC4wLAogICAgICAgICAgICAgICAgICAgICAgIDIwMjIsIDAuNywgMi4yLCAzLjIsCiAgICAgICAgICAgICAgICAgICAgICAgMjAyMywgMS42LCAyLjQsIDMuNSwKICAgICAgICAgICAgICAgICAgICAgICAyMDI0LCAzLCAxLjMsIDEuNSkKCnNoYXJlc192b2x1bWUgPC0gbWF0cml4KHNoYXJlc192b2x1bWVfdmVjLCBuY29sID0gNCwgYnlyb3cgPSBUUlVFKQpjb2xuYW1lcyhzaGFyZXNfdm9sdW1lKSA8LSBjKCJZZWFyIiwgIlByb2R1Y3Rpb24iLCAiQ29uc3VtcHRpb24iLCAiSW1wb3J0cyIpCgojIENvbnZlcnRpciBhIGRhdGEgZnJhbWUKZGYgPC0gYXMuZGF0YS5mcmFtZShzaGFyZXNfdm9sdW1lKQoKIyBUcmFuc2Zvcm1hciBkZSBmb3JtYXRvIGFuY2hvIGEgbGFyZ28gcGFyYSBnZ3Bsb3QyCmRmX2xvbmcgPC0gcGl2b3RfbG9uZ2VyKGRmLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29scyA9IGMoIlByb2R1Y3Rpb24iLCAiQ29uc3VtcHRpb24iLCAiSW1wb3J0cyIpLAogICAgICAgICAgICAgICAgICAgICAgICBuYW1lc190byA9ICJWYXJpYWJsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJWYWx1ZSIpCgojIENyZWFyIGdyw6FmaWNvIGNvbiBnZ3Bsb3QyCnAgPC0gZ2dwbG90KGRmX2xvbmcsIGFlcyh4ID0gWWVhciwgeSA9IFZhbHVlLCBjb2xvciA9IFZhcmlhYmxlLCBncm91cCA9IFZhcmlhYmxlKSkgKwogIGdlb21fbGluZShzaXplID0gMS4yKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIGxhYnModGl0bGUgPSAiU2hhcmVzIFZvbHVtZTogUHJvZHVjdGlvbiwgQ29uc3VtcHRpb24gJiBJbXBvcnRzIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIlZhbHVlIiwKICAgICAgIGNvbG9yID0gIlZhcmlhYmxlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKIyBDb252ZXJ0aXIgYSBwbG90bHkgcGFyYSBpbnRlcmFjdGl2aWRhZAppbnRlcmFjdGl2ZV9wbG90IDwtIGdncGxvdGx5KHAsIHRvb2x0aXAgPSBjKCJ4IiwgInkiLCAiY29sb3VyIikpCgojIE1vc3RyYXIgZWwgZ3LDoWZpY28gaW50ZXJhY3Rpdm8KaW50ZXJhY3RpdmVfcGxvdAoKYGBgCgojIyBDaGluYSB2cyBBdXN0cmFsaWEgdnMgQ2hpbGUKCkluZGV4IG9mIGludGVuc2l0eSBvZiB3aW5lIGV4cG9ydHMgdG8gQ2hpbmEgZnJvbSBBdXN0cmFsaWEsIENoaWxlIGFuZCBGcmFuY2UsYSBhbmQgc2hhcmUgb2YgQXVzdHJhbGlh4oCZcyB3aW5lIGV4cG9ydHMgZ29pbmcgdG8gQ2hpbmEsIGJ5IHZhbHVlLCAyMDE0IHRvIDIwMjIKCnwgQ291bnRyeSAgICAgICAgICAgIHwgMjAxNCB8IDIwMTUgfCAyMDE2IHwgMjAxNyB8IDIwMTggfCAyMDE5IHwgMjAyMCB8IDIwMjEgfCAyMDIyIHwKfC0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLXwtLS0tLS18LS0tLS0tfC0tLS0tLXwtLS0tLS18LS0tLS0tfC0tLS0tLXwtLS0tLS18LS0tLS0tfAp8IFwlIEV4cG9ydCBBdSB0byBDaCB8IDEuOSAgfCAyLjggIHwgMy43ICB8IDUgICAgfCA1LjEgIHwgNiAgICB8IDAuNSAgfCAwLjMgIHwgNiAgICB8CnwgQXVzdHJhbGlhIEluZGV4ICAgIHwgMi44ICB8IDIuOCAgfCAzICAgIHwgNCAgICB8IDQuNiAgfCA1LjUgIHwgNi41ICB8IDAuMyAgfCAwLjEgIHwKfCBDaGlsZSBJbmRleCAgICAgICAgfCAxLjk1IHwgMS45ICB8IDEuOCAgfCAyICAgIHwgMi4zICB8IDIuNiAgfCAyLjUgIHwgNC4xICB8IDQuNCAgfAp8IEZyYW5jZSBJbmRleCAgICAgICB8IDEuMyAgfCAxLjEgIHwgMS4wICB8IDEuMSAgfCAwLjkgIHwgMC44ICB8IDAuOTUgfCAxLjMgIHwgMS4zNSB8CgpgYGB7cn0KZXhwb3J0X2luZGV4IDwtIGMoCiAxLjkgICwgMi44ICAsIDMuNyAgLCA1ICAsICA1LjEsIDYgICAsIDAuNSAsIDAuMyAgLCA2ICAgLAogMi44ICAsIDIuOCAgLCAzICAgICwgNCAgLCA0LjYgLCA1LjUgLCA2LjUgLCAwLjMgICwgMC4xICwKIDEuOTUgLCAxLjkgICwgMS44ICAsIDIgICwgMi4zICwgMi42ICwgMi41ICwgNC4xICAsIDQuNCAsCiAxLjMgICwgMS4xICAsIDEuMCAgLCAxLjEsIDAuOSAsIDAuOCAsIDAuOTUsIDEuMyAgLCAxLjM1ICkKCmV4cG9ydF9pbmRleCA8LSBtYXRyaXgoZXhwb3J0X2luZGV4LCBuY29sPSA5ICwgYnlyb3cgPSAiVFJVRSIpCgpjb2xuYW1lcyhleHBvcnRfaW5kZXgpIDwtIGMoICIyMDE0IiwgIjIwMTUiLCAiMjAxNiIsIjIwMTciLCIyMDE4IiwiMjAxOSIgLCIyMDIwIiAsIjIwMjEiLCIyMDIyIikKCnJvd25hbWVzKCBleHBvcnRfaW5kZXgpIDwtICBjKCJCdWx0IHdpbmUgZXhwb3J0IEF1c3RyYWx5IHRvIENoaW5hIiwgIkF1c3RyYWxpYSBJbmRleCIsICJDaGlsZSBJbmRleCIsIkZyYW5jZSBJbmRleCIpIAogIAojIGV4cG9ydF9pbmRleAoKCgpgYGAKCmBgYHtyfQojIGxpYnJhcnkoZ2dwbG90MikKIyBsaWJyYXJ5KHBsb3RseSkKc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkodGlkeXIpKQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShkcGx5cikpCgojIENyZWFyIGxhIG1hdHJpegpleHBvcnRfaW5kZXggPC0gYygKICAxLjksIDIuOCwgMy43LCA1LCA1LjEsIDYsIDAuNSwgMC4zLCAwLjIsCiAgMi44LCAyLjgsIDMsIDQsIDQuNiwgNS41LCA2LjUsIDAuMywgMC4xLAogIDEuOTUsIDEuOSwgMS44LCAyLCAyLjMsIDIuNiwgMi41LCA0LjEsIDQuNCwKICAxLjMsIDEuMSwgMS4wLCAxLjEsIDAuOSwgMC44LCAwLjk1LCAxLjMsIDEuMzUKKQoKZXhwb3J0X2luZGV4IDwtIG1hdHJpeChleHBvcnRfaW5kZXgsIG5jb2wgPSA5LCBieXJvdyA9IFRSVUUpCmNvbG5hbWVzKGV4cG9ydF9pbmRleCkgPC0gYygiMjAxNCIsICIyMDE1IiwgIjIwMTYiLCAiMjAxNyIsICIyMDE4IiwgIjIwMTkiLCAiMjAyMCIsICIyMDIxIiwgIjIwMjIiKQpyb3duYW1lcyhleHBvcnRfaW5kZXgpIDwtIGMoIkJ1bGsgd2luZSBleHBvcnQgQXVzdHJhbGlhIHRvIENoaW5hIiwgIkF1c3RyYWxpYSBJbmRleCIsICJDaGlsZSBJbmRleCIsICJGcmFuY2UgSW5kZXgiKQoKIyBDb252ZXJ0aXIgYSBkYXRhIGZyYW1lIGxhcmdvCmRmIDwtIGFzLmRhdGEuZnJhbWUoZXhwb3J0X2luZGV4KQpkZiRDYXRlZ29yeSA8LSByb3duYW1lcyhleHBvcnRfaW5kZXgpCgpkZl9sb25nIDwtIGRmICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gLUNhdGVnb3J5LCBuYW1lc190byA9ICJZZWFyIiwgdmFsdWVzX3RvID0gIlZhbHVlIikgJT4lCiAgbXV0YXRlKAogICAgVHlwZSA9IGlmZWxzZShDYXRlZ29yeSA9PSAiQnVsayB3aW5lIGV4cG9ydCBBdXN0cmFsaWEgdG8gQ2hpbmEiLCAiQmFyIiwgIkxpbmUiKSwKICAgIFllYXIgPSBmYWN0b3IoWWVhciwgbGV2ZWxzID0gY29sbmFtZXMoZXhwb3J0X2luZGV4KSkKICApCgojIENyZWFyIGVsIGdyw6FmaWNvIGNvbiBnZ3Bsb3QyCnAgPC0gZ2dwbG90KGRmX2xvbmcsIGFlcyh4ID0gWWVhciwgeSA9IFZhbHVlLCBjb2xvciA9IENhdGVnb3J5LCBncm91cCA9IENhdGVnb3J5KSkgKwogICMgTMOtbmVhcyBwYXJhIGxvcyDDrW5kaWNlcwogIGdlb21fbGluZShkYXRhID0gZmlsdGVyKGRmX2xvbmcsIFR5cGUgPT0gIkxpbmUiKSwgbGluZXdpZHRoID0gMSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpbHRlcihkZl9sb25nLCBUeXBlID09ICJMaW5lIiksIHNpemUgPSAyLjUpICsKICAjIEJhcnJhcyBwYXJhIGV4cG9ydGFjaW9uZXMgZGUgdmlubwogIGdlb21fY29sKGRhdGEgPSBmaWx0ZXIoZGZfbG9uZywgVHlwZSA9PSAiQmFyIiksIAogICAgICAgICAgIGFlcyhmaWxsID0gQ2F0ZWdvcnkpLCBhbHBoYSA9IDAuNywgY29sb3IgPSBOQSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKAogICAgIkJ1bGsgd2luZSBleHBvcnQgQXVzdHJhbGlhIHRvIENoaW5hIiA9ICIjOEIwMDAwIiwKICAgICJBdXN0cmFsaWEgSW5kZXgiID0gIiNGRjZCNkIiLAogICAgIkNoaWxlIEluZGV4IiA9ICIjRkZGRjAwIiwKICAgICJGcmFuY2UgSW5kZXgiID0gIiM0NUI3RkYiCiAgKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkJ1bGsgd2luZSBleHBvcnQgQXVzdHJhbGlhIHRvIENoaW5hIiA9ICIjMDBmMjAwIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRXhwb3J0IEluZGV4OiBXaW5lIGFuZCBDb3VudHJ5IEluZGljZXMgKDIwMTQtMjAyMikiLAogICAgeCA9ICJZZWFyIiwKICAgIHkgPSAiSW5kZXggVmFsdWUiLAogICAgY29sb3IgPSAiQ2F0ZWdvcnkiLAogICAgZmlsbCA9ICJDYXRlZ29yeSIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiCiAgKQoKIyBDb252ZXJ0aXIgYSBwbG90bHkgcGFyYSBpbnRlcmFjdGl2aWRhZApmaWcgPC0gZ2dwbG90bHkocCwgdG9vbHRpcCA9IGMoIngiLCAieSIsICJjb2xvdXIiKSkKCiMgTW9zdHJhciBlbCBncsOhZmljbwpmaWcKYGBgCgojIyBFeGFtcGxlIDIgLSBBSSBhbmQgTG9naXN0aWNzIGZvciBXYXRlciBNYW5hZ2VtZW50CgohW10oaW1hZ2VuL0RJMy5wbmcpCgohW10oaW1hZ2VuL1RFU0lTXzEucG5nKQoKIVtdKGltYWdlbi9UZXNpcyUyMDFfYi5wbmcpCgpUaGUgbW9kZWwgaW5pdGlhbGx5IGJ1aWx0IGluIExPR08gd2FzIGltcGxlbWVudGVkIGluIFItQ3Jhbi4gQ0xBVURFIHdhcyB0aGVuIHVzZWQgdG8gZ2VuZXJhdGUgYSBkeW5hbWljIG1vZGVsIHRoYXQgd291bGQgaW1wcm92ZSB0aGUgcmVsaWFiaWxpdHkgb2Ygd2F0ZXIgZGlzdHJpYnV0aW9uIGFuZCBjb25zZXJ2YXRpb24gc3RyYXRlZ2llcyBmb3IgaHVtYW4sIGFncmljdWx0dXJhbCwgYW5kIGluZHVzdHJpYWwgY29uc3VtcHRpb24sIG1pbmltaXppbmcgbGFzdC1taWxlIGxvZ2lzdGljcyBjb3N0cy4KCiMjIEV4YW1wbGUgMyAtIFF1YWxpdHkgb2YgRGF0YSBmb3IgT3BlcmF0aW9uYWwgRXhjZWxsZW5jZQoKIVtdKGltYWdlbi9wYXBlcjIucG5nKQoKSW4gdGhpcyByZXNlYXJjaCwgdGhlIHF1YWxpdHkgZG9jdW1lbnRhdGlvbiBzeXN0ZW1zIG9mIDUwIGNvbXBhbmllcyBpbiB0aGUgcmV0YWlsIGFuZCBhdXRvbW90aXZlIHNlY3RvcnMgd2VyZSB1c2VkIGFzIHRyYWluaW5nIG1hdGVyaWFsIGZvciBhIGxhbmd1YWdlIG1vZGVsICh1c2luZyBMbGFtYSAzIGFuZCBEZWVwIFNlZWsgb24gbG93LWNvc3QgbG9jYWwgc2VydmVycykuIEJ5IHVzaW5nIHRoZSBQUklTTUEgbWV0aG9kb2xvZ3kgZm9yIHN5c3RlbWF0aWMgbGl0ZXJhdHVyZSByZXZpZXcsIHRoZSBhZ2VudCB3YXMgaW1wcm92ZWQsIGVuYWJsaW5nIGl0IHRvIGdlbmVyYXRlIHJlY29tbWVuZGF0aW9ucyBmb3IgU01FcyB0aGF0IGxlYWQgdG8gb3BlcmF0aW9uYWwgZXhjZWxsZW5jZS4KCiMgQ29uY2x1c2lvbgoKIyMgQ2xpbWF0ZSBwcm9ibGVtCgpBY2hpZXZpbmcgdGhlIFN1c3RhaW5hYmxlIERldmVsb3BtZW50IEdvYWxzIChTREdzKSBieSAyMDMwIGhhcyBiZWNvbWUgZXh0cmVtZWx5IGRpZmZpY3VsdCwgYXMgbW9zdCBjb3VudHJpZXMgYXJlIGxhZ2dpbmcgYmVoaW5kIGFuZCBwcm9ncmVzcyBpcyBlaXRoZXIgbnVsbCBvciByZWdyZXNzaXZlLCBhZ2dyYXZhdGVkIGJ5IGdsb2JhbCBjcmlzZXMuIERlc3BpdGUgdGhpcywgaXQgaXMgc3RpbGwgcG9zc2libGUgdGhyb3VnaCBhIGRlY2FkZUZJVkUgWUVBUlMgb2YgYW1iaXRpb3VzIGFjdGlvbiBhbmQgcG9saWN5IGNoYW5nZXMsIHdpdGgga2V5IGludmVzdG1lbnRzIGluIGNyaXRpY2FsIGFuZCBub3QgKipjcml0aWNhbCBpbmZyYXN0cnVjdHVyZSoqLCBzdXBwb3J0IGZvciB0aGUgbW9zdCB2dWxuZXJhYmxlLCBhbmQgYWN0aXZlIHBhcnRpY2lwYXRpb24gZnJvbSBhbGwgc2VjdG9ycyBvZiBzb2NpZXR5LgoKIyMgV2hhdCBhYm91dCBIZWdlbW9uaWMgUG93ZXJzCgotICAgTW9zdCBtYWpvciBlY29ub21pZXMgKGV4Y2VwdCBKYXBhbikgaGF2ZSBwb3N0cG9uZWQgdGhlIFN1c3RhaW5hYmxlIERldmVsb3BtZW50IEdvYWxzIHVudGlsIDIwNTAuCgotICAgVW5saWtlIHdoYXQgaGFwcGVuZWQgaW4gdGhlIEZpcnN0IGFuZCBTZWNvbmQgV29ybGQgV2FycywgaW5mcmFzdHJ1Y3R1cmVzIGhhdmUgYmVjb21lIHRoZSB0YXJnZXRzIG9mIGF0dGFjayBpbiBldmVyeSB3YXIgdGhhdCBoYXMgYXBwZWFyZWQuCgotICAgVGhpcyByZWR1Y2VzIHRoZSBwb3NzaWJpbGl0eSBvZiBudWNsZWFyIGNvbmZsaWN0cyBhbmQgb3BlbnMgdXAgdGhlIHBvc3NpYmlsaXR5IGZvciBhY2FkZW1pYSB0byBjb25kdWN0IFImRCBpbiBpbmZyYXN0cnVjdHVyZSBhdCBib3JkZXJzLCBhcyBhIG1lYW5zIG9mIGNvbm5lY3RpbmcgcmF0aGVyIHRoYW4gZGl2aWRpbmcuIFBvcnRzLCByb2FkcywgYWlyd2F5cywgd2F0ZXIsIGRpc2FzdGVyIG1pdGlnYXRpb24sIGFuZCBmYXJtcyBmb3IgZm9vZCBpbmRlcGVuZGVuY2UgYXBwZWFyIGFzIGtleSB0b3BpY3MgZm9yIGFwcGx5aW5nIEFJIG1vZGVscywgYW5kIGFsbCBvZiB0aGVtIGludm9sdmUgbGFzdC1taWxlIGxvZ2lzdGljcy4KCiMjIExlc3NvbnMgbGVhcm5lZCBmcm9tIGV4YW1wbGVzIDEsMiBhbmQgMwoKLSAgIExhc3QtbWlsZSBsb2dpc3RpY3MgaXNuJ3QgbGltaXRlZCBzb2xlbHkgdG8gdXJiYW4gdHJhZmZpYyBvciBkcm9uZSBkZWxpdmVyeSBpc3N1ZXMuCgotICAgQ2hpbmEgaGFzIGluY3JlYXNlZCBpdHMgdmluZXlhcmQgcHJvZHVjdGlvbiB1c2luZyBzbWFydCByb2xsaW5nIHZlaGljbGVzIHRoYXQgdHJhdmVsIHRocm91Z2ggc21hbGwgdmluZXlhcmRzLiBUaGV5IGhhdmVuJ3QgdXNlZCBkcm9uZXMsIGFuZCB0aGVzZSB2ZWhpY2xlcyBkb24ndCBoYXZlIGRyaXZlcnMgb3IgcmVtb3RlIHBpbG90cy4KCi0gICBUaGUgY2FzZSBvZiBpcnJpZ2F0aW9uIHdhdGVyIGRpc3RyaWJ1dGlvbiBpcyBhbm90aGVyIGV4YW1wbGUgb2YgbGFzdC1taWxlIGxvZ2lzdGljcyB0byB3aGljaCB3ZSBpbnRlbmQgdG8gYXBwbHkgdGhlIGFyc2VuYWwgb2YgbWV0aG9kcyB0aGF0IEFJIG9mZmVycy4KCi0gICBGaW5hbGx5LCB0aGUgY2FzZSBvZiBsYW5ndWFnZSBtb2RlbHMgaXMgY2xvc2VseSBsaW5rZWQgdG8gdGhlIEphcGFuZXNlIHByb3Bvc2FsIHdlIHJlZmVycmVkIHRvIGluIHRoZSBwcmV2aW91cyBwYXJhZ3JhcGhzLiBBcyB3aXRoIHRoZSBxdWFsaXR5IHBhcmFkaWdtLCB3aGljaCBoYXMgYmVlbiBhIGN1bHR1cmFsIGNvbnN0cnVjdCBpbiBKYXBhbiB3aXRoIGFuIGVjdW1lbmljYWwgY2hhcmFjdGVyLCB0aGV5IHByb3Bvc2Ugb3BlcmF0aW9uYWwgZXhjZWxsZW5jZSBhcyBhbiBhbHRlcm5hdGl2ZSB0byBJbmR1c3RyeSA0LjAgYW5kIDUuMC4KCiMjIFRoZSBlbmQgb2YgZ2xvYmFsaXphdGlvbj8KCi0gICBPaywgSSBjYW4gZ3JhbnQgeW91IHRoYXQgdGhpcyBtYXkgbm90IGJlIHRoZSBlbmQgb2YgZ2xvYmFsaXphdGlvbiwgYnV0IGxldCdzIGF0IGxlYXN0IGFncmVlIHRoYXQgaXQncyBhIEhVR0UgY2hhbmdlLgoKLSAgIFRoaXMgb3BlcmF0aW9uYWwgZXhjZWxsZW5jZSBpcyBwYXJ0IG9mIHdoYXQgdGhleSBoYXZlIGNhbGxlZCBTT0NJRVRZIDUuMC4gV2hvIGtub3dzPyBQZXJoYXBzIHRoaXMgaXMgdGhlIG1vc3QgcGxhdXNpYmxlIGFuc3dlciB3ZSBoYXZlIGZvdW5kIHRvIGFsbCB0aGVzZSBxdWVzdGlvbnMuCg==