Politician analysis
1- Download tweets
I create a list of accounts from which I am going to download their tweets, and also an assignment to know to which political party each account.
The original idea is to have 4 members from each of the two main parties, the last 4 candidates in the 2019 elections and also the 4 party accounts on Twitter.
- Frente de todos: Alberto Fernández, Cristina Kirchner, Gines González García y Axel Kicillof
- PRO: Mauricio Macri, Horacio Rodríguez Larreta, Fernán Quiroz y Patricia Bullrich
- Otros candidatos: José Luis Espert, Roberto Lavagna, Juan José Gómez Centurión y Nicolas del Caño
- Partidarias: Frente de Todos, PRO, GEN y Unión Cívica Radical
print("Muestra")
[1] "Muestra"
print(Tweets_DF %>%
select(text)%>%
head(5))
2-ETL process
We are going to clean up certain elements that can complicate the analysis of the text, such as links, numbers, graphics and turn everything to lowercase.
In addition, we create several fields for what the date is, disaggregating the field into several different ones, which will be used in the future, and the time is also updated to the time zone where the tweet (Argentina) was made.
Finally we filter by date, the idea is to have only tweets from the period 1/3/2020 until the publication date (Sep / 2020)
Tweets_DF <-
Tweets_DF %>%
##Todo el texto a minuscula##
mutate(text = tolower(text)) %>%
##Sin graficos##
mutate(text = gsub("[^[:graph:]]", " ", text)) %>%
##Sin links##
mutate(text = gsub("http//S", " ", text)) %>%
##Sin numeros##
mutate(text = gsub("[[:digit:]]", " ", text)) %>%
##Sin numeros##
mutate(text = chartr('áéíóúñ','aeioun',text)) %>%
##Cambiamos a la zona horaria correspondiente##
mutate(created_at = with_tz(created_at, "America/Argentina/Buenos_Aires"))%>%
##Separamos en dia y hora el campo created_at##
separate(created_at, into = c("date", "hour"), sep = " ")%>%
##Separamos la hora en hora,minutos y segundos##
separate(hour, into = c("hour", "minutes","seconds"), sep = ":")%>%
##Cambiamos la columna con el nombre del politico##
rename(Politico = screen_name) %>%
##Creamos una columna con el numero de año, mes, dia, nombre de dia y de mes.##
mutate(periodo = year(date),
mes = month(date, label = F, abbr = F),
dia = as.numeric(day(date)),
dia_sem = wday(date, label = T, abbr = F, week_start = 1),
dia_per = yday(date),
date = as.Date(date)
) %>%
##Solo vamos a utilizar info de marzo 2020 en adelante##
filter(periodo == 2020 & mes > 2)
print("Muestra")
[1] "Muestra"
print(Tweets_DF %>%
select(Politico, status_id, periodo, mes, dia)%>%
head(10))
NA
3-Normalization
We normalize some fields, to help the analysis and also the visualization.
We add the match to each of those analyzed, and also change their name from the @ we see on Twitter, to a name easy for everyone to understand
Tweets_DF <-
Tweets_DF %>%
mutate (Partido = ifelse (Politico == "alferdez", "Peronismo",
ifelse (Politico == "CFKArgentina", "Peronismo",
ifelse (Politico == "ginesggarcia", "Peronismo",
ifelse (Politico == "Kicillofok", "Peronismo",
ifelse (Politico == "UCRNacional", "cuenta partidaria",
ifelse (Politico == "FrenteDeTodos", "cuenta partidaria",
ifelse (Politico == "proargentina", "cuenta partidaria",
ifelse (Politico == "PartidoGEN", "cuenta partidaria",
ifelse (Politico == "mauriciomacri", "PRO",
ifelse (Politico == "PatoBullrich", "PRO",
ifelse (Politico == "horaciorlarreta", "PRO",
ifelse (Politico == "FernanQuirosBA", "PRO",
"otros candidatos")))))))))))))
Tweets_DF <-
Tweets_DF %>%
mutate (Politico = ifelse (Politico == "alferdez", "A.Fernandez",
ifelse (Politico == "CFKArgentina", "C.Kirchner",
ifelse (Politico == "ginesggarcia", "Gines.GG",
ifelse (Politico == "Kicillofok", "A.Kicillof",
ifelse (Politico == "UCRNacional", "UCR",
ifelse (Politico == "FrenteDeTodos", "TODOS",
ifelse (Politico == "proargentina", "PRO",
ifelse (Politico == "PartidoGEN", "GEN",
ifelse (Politico == "mauriciomacri", "M.Macri",
ifelse (Politico == "PatoBullrich", "P.Bullrich",
ifelse (Politico == "horaciorlarreta", "H.Larreta",
ifelse (Politico == "FernanQuirosBA", "F.Quiros",
ifelse (Politico == "NicolasdelCano", "N.DelCaño",
ifelse (Politico == "jlespert", "J.Espert",
ifelse (Politico == "RLavagna", "R.Lavagna",
"GomezCenturion"
))))))))))))))))
print("Muestra")
[1] "Muestra"
print(Tweets_DF %>%
select(Politico, Partido, source)%>%
tail(10))
4-Number of tweets
The first approximation that we are going to have is the number of times each tweeted from March 2020 to the date of publication of the report.
There are considerable differences between all, you should normalize or use proportions more than once
- Macri and Lavagna have fewer tweets than the rest
- Cristina Kirchner is also of little participation
- The accounts of Frente de Todos, Espert, Del Caño and the UCR are the most used
Cantidad_tweets = Tweets_DF %>%
group_by(Politico, Partido) %>%
count(Politico)
Cantidad_tweets%>%
ggplot()+
aes(x=reorder(Politico, n), y= n, fill= Politico) +
geom_col() +
facet_wrap("Partido", scales = "free_y") +
coord_flip() +
labs(title = "Cantidad total de tweets", x = "tweets", y = "Cantidad") +
tema1

5-Date of tweets
We see when each of the analyzed tweets have been published, in order to show when they had more or less action.
- In the case of the Frente de todos account, as it had more than 3,200 tweets, the analysis starts from the first days of April
Tweets_DF %>%
filter(Partido == "PRO") %>%
ggplot(aes(x = as.Date(date), fill = Politico)) +
geom_histogram(position = "identity", bins = 20, show.legend = FALSE) +
scale_x_date(date_labels = "%d-%m", date_breaks = "1 month") +
labs(x = "fecha de publicación", y = "número de tweets") +
facet_wrap(~ Politico, ncol = 1) +
tema2 +
theme(axis.text.x = element_text(angle = 90))

Tweets_DF %>%
filter(Partido == "Peronismo") %>%
ggplot(aes(x = as.Date(date), fill = Politico)) +
geom_histogram(position = "identity", bins = 20, show.legend = FALSE) +
scale_x_date(date_labels = "%d-%m", date_breaks = "1 month") +
labs(x = "fecha de publicación", y = "número de tweets") +
facet_wrap(~ Politico, ncol = 1) +
tema1 +
theme(axis.text.x = element_text(angle = 90))

Tweets_DF %>%
filter(Partido == "otros candidatos") %>%
ggplot(aes(x = as.Date(date), fill = Politico)) +
geom_histogram(position = "identity", bins = 20, show.legend = FALSE) +
scale_x_date(date_labels = "%d-%m", date_breaks = "1 month") +
labs(x = "fecha de publicación", y = "número de tweets") +
facet_wrap(~ Politico, ncol = 1) +
tema1 +
theme(axis.text.x = element_text(angle = 90))

Tweets_DF %>%
filter(Partido == "cuenta partidaria") %>%
ggplot(aes(x = as.Date(date), fill = Politico)) +
geom_histogram(position = "identity", bins = 20, show.legend = FALSE) +
scale_x_date(date_labels = "%d-%m", date_breaks = "1 month") +
labs(x = "fecha de publicación", y = "número de tweets") +
facet_wrap(~ Politico, ncol = 1) +
tema2 +
theme(axis.text.x = element_text(angle = 90))

6-Number of tweets about COVID
The most important topic of the year is the coronavirus, the idea is to see what percentage of the tweets made these months deal with the coronavirus, for that they will look for keywords that determine that the tweet is about the pandemic.
Clearly the ministers are the ones who spoke the most about the Coronavirus, with 75% of their tweets.
Governors Kiciloff and Larreta continue, who discussed the evolution of the pandemic in their districts.
To a lesser extent the leaders of the two main parties spoke.
Del Caño is the one who spoke the most among the other candidates, followed by Espert, while Lavagna and Gómez Centurión spoke very little.
Party accounts, except those of the UCR, were not widely used to talk about the Coronavirus
#We look for tweets with the word covid
Palabras_covid <- "covid|covid-19|covid19|coronavirus|#covid|#covid-19|#covid19|#coronavirus|test|testeo|testeos|pcr|serologico|hisopado|antibioticos|aplanar|curva|cuarentena|contagio|enfermedad|epidemia|pandemia|alarma|gel|cuidados|incubacion|jabon|barbijo|barbijos|mascarilla|mascarillas|mers|sars|vacuna|wuhan|oxford|astra|zeneca|transmision|exponencial|casos|duplicacion|distanciamiento|colapso|salud|letalidad|mortalidad|ventilador|icu|uci|uti|inmunidad|serologica|distanciamiento|virus|asintomatico|caso sospechoso|olfato|gusto|terapia|saturacion|clinica|positividad|positivios|rebaño|inmunidad|hospital|hospitales|aspo|aislamiento"
Tweets_DF$Covid <- grepl(Palabras_covid, Tweets_DF$text, ignore.case ="True")
Tweets_DF %>%
count(Politico, Partido,Covid) %>%
group_by(Politico) %>%
mutate(Proporcion = n / sum(n)) %>%
mutate(Covid = ifelse(Covid == T, "Sobre COVID", "Otro tema"))%>%
ggplot() +
aes(Politico, Proporcion, fill = Covid) +
geom_col() +
scale_y_continuous(labels = percent_format()) +
facet_wrap("Partido", scales = "free") +
theme(legend.position = "top")

7- Wordcloud
The idea of the word cloud is to know which are the 200 words that were used the most by those analyzed these months, as expected they stand out “coronavirus”, “covid”, “pandemia” or “cuarentena”
tuits_tokens <-
Tweets_DF %>%
unnest_tokens(input = text, output = Palabra, token = "words") %>%
select(Politico, Palabra, status_id, periodo, mes, hour, Partido) %>%
mutate(status_id = gsub("<(.*)>+?", "", status_id)) %>%
filter(!Palabra %in% stopwords("es")) %>%
filter(!Palabra %in% c("t.co", "https", "vÃa", "youtube", "amp"))
Palabras_sinhoymas = tuits_tokens %>%
filter(Palabra != "mas" & Palabra != "hoy")
wordcloud(words = Palabras_sinhoymas$Palabra,
scale=c(2,.2),
max.words=200, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"),
)
transformation drops documentstransformation drops documents

8-Download a dictionary
We download a dictionary that has the words in Spanish, and assigns it a value between -5 to 5, showing the positivity or negativity of the word.
We eliminate the word “No” that takes it as negative, when in Spanish it is a connector sometimes, and the word “Negro” (Nigga) that takes it with the maximum negative value
download.file("https://raw.githubusercontent.com/jboscomendoza/rpubs/master/sentimientos_afinn/lexico_afinn.en.es.csv",
"lexico_afinn.en.es.csv")
probando la URL 'https://raw.githubusercontent.com/jboscomendoza/rpubs/master/sentimientos_afinn/lexico_afinn.en.es.csv'
Content type 'text/plain; charset=utf-8' length 51625 bytes (50 KB)
downloaded 50 KB
afinn <- read.csv("lexico_afinn.en.es.csv", stringsAsFactors = F, fileEncoding = "latin1") %>%
tbl_df()
`tbl_df()` is deprecated as of dplyr 1.0.0.
Please use `tibble::as_tibble()` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
afinn$Puntuacion <- ifelse(afinn$Palabra == "no", 0, afinn$Puntuacion)
afinn$Puntuacion <- ifelse(afinn$Palabra == "negro", 0, afinn$Puntuacion)
print("Muestra")
[1] "Muestra"
afinn %>%
select(Palabra, Puntuacion) %>%
arrange(Puntuacion) %>%
print(head(10))
afinn %>%
select(Palabra, Puntuacion) %>%
arrange(-Puntuacion) %>%
print(tail(10))
9- Word separation
We separated the different words that each of the politicians used in their tweets, and we eliminated some of Twitter’s own words and the so-called stopwords that are the most frequent words in the Spanish language.
print ("Muestra")
[1] "Muestra"
print (tuits_tokens %>%
select(Politico, Palabra) %>%
head (10))
10- We value words
We join the scoring dictionary with the words that each of those analyzed used, so that each word has a value, and it helps us to analyze what each politician wrote.
The words will be:
If they have a value greater than 0 Positive
If they are less than 0 Negative
In case the word does not have a load of feelings Neutral
tuits_tokens_emociones <-
tuits_tokens %>%
inner_join(afinn, ., by = "Palabra") %>%
mutate(Calificacion = ifelse(Puntuacion > 0, "Positiva",
ifelse(Puntuacion == 0, "Neutral",
"Negativa")
)
)
print ("Muestra")
[1] "Muestra"
print (tuits_tokens_emociones %>%
select(Politico, Palabra, Puntuacion, Calificacion) %>%
tail (10))
11- Who uses most characters?
The idea is to find what is the average length (number of characters) of the tweets made by each of those analyzed.
The further to the right the box is, the longer the tweets they write, in that aspect they stand out:
Lavagna, Patricia Bullrich, Larreta and Fernán Quirós are the ones who write the longest tweets.
Those related to the PRO are to write longer tweets
Tweets_DF %>%
ggplot()+
aes(x= Politico, y= display_text_width, color= Politico) +
geom_boxplot () +
labs(title = "Largo promedio del tweet", x = "Politico", y = "Cantidad caracteres") +
coord_flip() +
tema1

12- Who uses most words?
The idea is to analyze who is the one who used the most different words on average during this time, in this case we are going to divide by the number of tweets he made, so it is normalized for all those analyzed.
Common connectors such as “on”, “to”, “from”, etc. are not counted
- Espert is below 15 words per tweet, it is the least used.
- The rest is in a similar amount of between 15 and 20 words.
Cantidad_palabras= tuits_tokens%>%
group_by(Politico, Partido)%>%
count(Politico)%>%
inner_join(Cantidad_tweets, ., by = "Politico")%>%
mutate(cantidad_promedio = n.y / n.x)
Cantidad_palabras%>% ggplot()+
aes(x=reorder(Politico, -cantidad_promedio), y= cantidad_promedio, fill= Politico) +
geom_col() +
facet_wrap("Partido.x", scales = "free_y") +
labs(title = "Uso de palabras", x = "tweets", y = "Cantidad") +
coord_flip() +
tema1

NA
NA
13- Who uses the different words?
We seek to see the distinctive lexicon that is in each of the accounts, counting their unique words and it shows:
Differences between Lavagna, Macri, Cristina with the rest of those who write
Espert that is the one with the least varied lexicon
tuits_tokens%>%
group_by(Politico, Partido)%>%
distinct(Palabra)%>%
count(Politico)%>%
inner_join(Cantidad_tweets, ., by = "Politico") %>%
mutate(cantidad_promedio = n.y / n.x) %>%
ggplot()+
aes(x=reorder(Politico, cantidad_promedio), y= cantidad_promedio, fill= Politico) +
geom_col() +
facet_wrap("Partido.x", scales = "free_y") +
labs(title = "Palabras distintas", x = "tweets", y = "Cantidad") +
coord_flip() +
tema1

NA
14- Most used words
Now that we know with what variety of words, we can analyze which ones they used the most
In this case, each graph has a different scale so that it is not lost due to the number of tweets made.
The most used words were:
- “avoid”
- “debt”
- “Justice”
- “freedom” mainly used by Espert.
tuits_tokens_emociones %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "PRO") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras más usadas") +
tema1

tuits_tokens_emociones %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "Peronismo") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras más usadas") +
tema1

tuits_tokens_emociones %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "otros candidatos") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras más usadas") +
tema1

tuits_tokens_emociones %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "cuenta partidaria") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras más usadas") +
tema1

15- Most used positive words
By having a score for each word given by the lexicon dictionary, we can also look for the positive words that each of the politicians use the most.
In this case:
Note the use of the words “freedom” and “justice” which are considered positive
The use of the word “thank you” appears quite a lot, mainly from those accounts related to health (Gines González García and Fernán Quirós)
tuits_tokens_emociones %>%
filter(Calificacion == "Positiva") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "PRO") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Positivas más usadas")

tuits_tokens_emociones %>%
filter(Calificacion == "Positiva") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "Peronismo") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Positivas más usadas")

tuits_tokens_emociones %>%
filter(Calificacion == "Positiva") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "otros candidatos") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Positivas más usadas")

tuits_tokens_emociones %>%
filter(Calificacion == "Positiva") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "cuenta partidaria") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Positivas más usadas")

16- Most used negative words
By having a score for each word given by the lexicon dictionary, we can also look for the negative words that each of the politicians use the most.
Avoid, Emergency or Problem are the words that appear the most, within the main topic of speech, which is the pandemic.
Debt is another widely used word, a difficult subject to avoid this year.
tuits_tokens_emociones %>%
filter(Calificacion == "Negativa") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "PRO") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Negativas más usadas")

tuits_tokens_emociones %>%
filter(Calificacion == "Negativa") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "Peronismo") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Negativas más usadas")

tuits_tokens_emociones %>%
filter(Calificacion == "Negativa") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "otros candidatos") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Negativas más usadas")

tuits_tokens_emociones %>%
filter(Calificacion == "Negativa") %>%
group_by(Partido, Politico) %>%
count(Palabra, sort = T) %>%
slice_max(order_by = n, n= 10) %>%
filter(Partido == "cuenta partidaria") %>%
ggplot() +
aes(Palabra, n, fill = Politico) +
geom_col() +
facet_wrap("Politico", scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = "Palabras Negativas más usadas")

17- Feelings in the tweet
Using the afinn dictionary punctuation again, we rejoin the words to the tweets and averaged the points of all the words, moving from the unit word value to a unit value for each tweet posted.
Most tweets were neutral.
The most positive in this course were M. Macri, A. Fernandez and R. Lavagna.
The most negative were N. Del Caño and the official PRO account.
Tweets_DF <-
tuits_tokens_emociones %>%
group_by(status_id) %>%
summarise(Puntuacion_tweet.x = mean(Puntuacion)) %>%
left_join(Tweets_DF, ., by = "status_id")
`summarise()` ungrouping output (override with `.groups` argument)
Tweets_DF <- Tweets_DF %>%
mutate(Puntuacion_tweet.x_letra = ifelse(is.na(Puntuacion_tweet.x), "Neutral",
ifelse(Puntuacion_tweet.x > 0, "Positiva",
ifelse(Puntuacion_tweet.x == 0, "Neutral",
"Negativa")
)
)
)
Tweets_DF %>%
count(Politico, Partido, Puntuacion_tweet.x_letra) %>%
group_by(Politico) %>%
mutate(Proporcion = n / sum(n)) %>%
ggplot() +
aes(Politico, Proporcion, fill = Puntuacion_tweet.x_letra) +
geom_col() +
scale_y_continuous(labels = percent_format()) +
facet_wrap("Partido", scales = "free") +
theme(legend.position = "top")

NA
NA
18- Feelings in the PRO vs Peronismo tweet
We take the 4 members that we have already analyzed from each of the parties (PRO and TODOS), and we unite it in a single graph per party, we see that the distribution is something similar, although Peronism had a little more positive tweets and fewer negative tweets, but not at significant levels.
Tweets_DF %>%
count(Partido, Puntuacion_tweet.x_letra) %>%
group_by(Partido) %>%
filter(Partido == "PRO" |Partido == "Peronismo")%>%
mutate(Proporcion = n / sum(n)) %>%
ggplot() +
aes(Partido, Proporcion, fill = Puntuacion_tweet.x_letra) +
geom_col() +
scale_y_continuous(labels = percent_format()) +
theme(legend.position = "top")

19- Feeling month by month
The idea is to analyze if there are fluctuations in what they have been tweeting over time and their feelings.
In the PRO there were no big changes, the last tweets of Bullrich are more positive.
Among the other candidates Nicolas Del Caño is always negative, but has been less negative lately.
Among the Frente de Todos there is a lot of fluctuation, the President seems to be on a path towards negativity.
Tweets_DF$Puntuacion_tweet.x = ifelse(is.na(Tweets_DF$Puntuacion_tweet.x), 0, Tweets_DF$Puntuacion_tweet.x)
Tweets_DF %>%
group_by(Politico, Partido, mes) %>%
filter(Partido == "PRO")%>%
summarise(sentimiento = mean(Puntuacion_tweet.x)) %>%
ggplot() +
aes(mes, sentimiento, color = Politico) +
geom_hline(yintercept = 0, alpha = .35) +
geom_line() +
facet_grid(Politico~.) +
tema1 +
theme(legend.position = "none")
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

Tweets_DF %>%
group_by(Politico, Partido, mes) %>%
filter(Partido == "otros candidatos")%>%
summarise(sentimiento = mean(Puntuacion_tweet.x)) %>%
ggplot() +
aes(mes, sentimiento, color = Politico) +
geom_hline(yintercept = 0, alpha = .35) +
geom_line() +
facet_grid(Politico~.) +
tema1 +
theme(legend.position = "none")
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

Tweets_DF %>%
group_by(Politico, Partido, mes) %>%
filter(Partido == "Peronismo")%>%
summarise(sentimiento = mean(Puntuacion_tweet.x)) %>%
ggplot() +
aes(mes, sentimiento, color = Politico) +
geom_hline(yintercept = 0, alpha = .35) +
geom_line() +
facet_grid(Politico~.) +
tema1 +
theme(legend.position = "none")
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

Tweets_DF %>%
group_by(Politico, Partido, mes) %>%
filter(Partido == "cuenta partidaria")%>%
summarise(sentimiento = mean(Puntuacion_tweet.x)) %>%
ggplot() +
aes(mes, sentimiento, color = Politico) +
geom_hline(yintercept = 0, alpha = .35) +
geom_line() +
facet_grid(Politico~.) +
tema1 +
theme(legend.position = "none")
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

20- Feeling Boxplot
The distribution of feelings among all the tweets, those that are enclosed in the boxes are the normal ones, while the loose points are isolated tweets to what they usually write.
- Espert does not present any kind of pattern of feelings
Tweets_DF %>%
ggplot() +
aes(Politico, Puntuacion_tweet.x, fill = Politico) +
geom_boxplot() +
coord_flip() +
labs(y= "Sentimiento") +
tema1

21- Correlation between PRO vs Peronismo tweeted
It is searched through the words that they used what is the correlation between the different politicians and their tweets, and several observations can be made:
Quirós and Larreta are the ones with the highest correlation, demonstrating good management of Buenos Aires communication, where both continue in the same direction.
Macri is the one with the lowest correlation with the rest of the participants, but it also makes sense that his highest level of relationship is with Bullrich.
Between Kiciloff and Gines, there is an important relationship, as well as the two of them with their similar porteños (Quirós and Larreta).
Cristina Kirchner is another who does not have a high level of relationship in her tweets with other politicians.
It is surprising that one of the highest levels of relationship in terms of what is communicated is between Alberto Fernández and Patricia Bullrich.
tweets_spread2 <- tuits_tokens %>%
filter(Partido == "PRO" | Partido == "Peronismo")%>%
group_by(Politico, Palabra) %>%
count(Palabra) %>%
spread(key = Politico, value = n, fill = NA, drop = TRUE)
tweets_spread2[is.na(tweets_spread2)] <- 0
names(tweets_spread2) <- c("Palabra", "A.Fernandez", "A.Kicillof",
"C.Kirchner", "F.Quiros", "Gines.GG","H.Larreta", "M.Macri", "P.Bullrich" )
method <- "pearson"
m_cor <- matrix(nrow = 8, ncol = 8)
for (i in 1:dim(m_cor)[1]) {
for (j in 1:dim(m_cor)[2]) {
form <- as.formula(paste("~", names(tweets_spread2)[i+1],
"+", names(tweets_spread2)[j+1]))
if(i!=j){
m_cor[i,j] <- cor.test(form, method = method,
data = tweets_spread2)$estimate
}
if(i==j){m_cor[i,j] <- 1}
}
}
colnames(m_cor) <- names(tweets_spread2)[2:9]
rownames(m_cor) <- names(tweets_spread2)[2:9]
corrplot(m_cor, method="color", type="upper", order="hclust",
addCoef.col = "black", tl.col="black", tl.srt=45,
sig.level = 0.01, insig = "blank", diag=FALSE)

22- Correlation between the tweeted candidates for president.
The relationship between what the candidates write has a cluster that stands out above the rest, which is the relationship between Espert, Gómez Centurión and Alberto Fernández.
Nicolas Del Caño has a high level of relationship with Gómez Centurión, and to a medium extent with Alberto Fernández and Espert.
Lavagna and Macri do not present a great correlation with the rest of the politicians.
tweets_spread2 <- tuits_tokens %>%
filter(Partido == "otros candidatos" | Politico == "A.Fernandez"| Politico == "M.Macri")%>%
group_by(Politico, Palabra) %>%
count(Palabra) %>%
spread(key = Politico, value = n, fill = NA, drop = TRUE)
tweets_spread2[is.na(tweets_spread2)] <- 0
names(tweets_spread2) <- c("Palabra", "A.Fernandez", "J.Espert",
"GomezCenturion", "M.Macri", "N.DelCaño","R.Lavagna")
method <- "pearson"
m_cor <- matrix(nrow = 6, ncol = 6)
for (i in 1:dim(m_cor)[1]) {
for (j in 1:dim(m_cor)[2]) {
form <- as.formula(paste("~", names(tweets_spread2)[i+1],
"+", names(tweets_spread2)[j+1]))
if(i!=j){
m_cor[i,j] <- cor.test(form, method = method,
data = tweets_spread2)$estimate
}
if(i==j){m_cor[i,j] <- 1}
}
}
colnames(m_cor) <- names(tweets_spread2)[2:7]
rownames(m_cor) <- names(tweets_spread2)[2:7]
corrplot(m_cor, method="color", type="upper", order="hclust",
addCoef.col = "black", tl.col="black", tl.srt=45,
sig.level = 0.01, insig = "blank", diag=FALSE)

23- Correlation between what was tweeted between party accounts
This can be an interesting analysis, since the number of tweets is significant for everyone.
Surprisingly, the maximum level of relationship occurs between the UCR and TODOS, two parties that today are presented as opposite
The high relationship between the PRO and the UCR makes more sense.
The GEN seems to be the party that writes more differently from the rest.
However, we can note that, unlike the individual accounts, the supporters have more relationship, due to their more neutral language and organic communication.
tweets_spread2 <- tuits_tokens %>%
filter(Partido == "cuenta partidaria")%>%
group_by(Politico, Palabra) %>%
count(Palabra) %>%
spread(key = Politico, value = n, fill = NA, drop = TRUE)
tweets_spread2[is.na(tweets_spread2)] <- 0
names(tweets_spread2) <- c("Palabra", "GEN", "PRO",
"TODOS", "UCR")
method <- "pearson"
m_cor <- matrix(nrow = 4, ncol = 4)
for (i in 1:dim(m_cor)[1]) {
for (j in 1:dim(m_cor)[2]) {
form <- as.formula(paste("~", names(tweets_spread2)[i+1],
"+", names(tweets_spread2)[j+1]))
if(i!=j){
m_cor[i,j] <- cor.test(form, method = method,
data = tweets_spread2)$estimate
}
if(i==j){m_cor[i,j] <- 1}
}
}
colnames(m_cor) <- names(tweets_spread2)[2:5]
rownames(m_cor) <- names(tweets_spread2)[2:5]
corrplot(m_cor, method="color", type="upper", order="hclust",
addCoef.col = "black", tl.col="black", tl.srt=45,
sig.level = 0.01, insig = "blank", diag=FALSE)

24- Macri vs Fernandez word use comparison
The idea of this graph is to show which words are the most different in their use, in this case between Mauricio Macri and Alberto Fernández
# Pivotaje y despivotaje
tweets_unpivot <- tuits_tokens %>% group_by(Politico, Palabra) %>%
count(Palabra) %>%
spread(key = Politico, value = n, fill = 0, drop = TRUE) %>%
gather(key = "Politico", value = "n", -Palabra)
# Selección de los autores
tweets_unpivot2 <- tweets_unpivot %>%
filter(Politico %in% c("M.Macri", "A.Fernandez"))
# Se añade el total de palabras de cada autor
tweets_unpivot2 <- tweets_unpivot2 %>%
left_join(Tweets_DF %>% group_by(Politico) %>%
summarise(N = n()), by = "Politico")
`summarise()` ungrouping output (override with `.groups` argument)
# Cálculo de odds y log of odds de cada palabra
tweets_logOdds <- tweets_unpivot2 %>%
mutate(odds = (n + 1) / (N + 1)) %>%
select(Politico, Palabra, odds) %>%
spread(key = Politico, value = odds)
tweets_logOdds[,4] <- log(tweets_logOdds[,2]/tweets_logOdds[,3])
names(tweets_logOdds)[4] <- "log_odds"
tweets_logOdds[,5] <- abs(tweets_logOdds$log_odds)
names(tweets_logOdds)[5] <- "abs_log_odds"
tweets_logOdds <- tweets_logOdds %>%
mutate(autor_frecuente = if_else(log_odds > 0,
names(tweets_logOdds)[2],
names(tweets_logOdds)[3]))
Diferencia_AF <- tweets_logOdds %>%
arrange(-abs_log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "A.Fernandez")%>%
head(15)
Diferencia_MM <- tweets_logOdds %>%
arrange(log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "M.Macri")%>%
head(15)
Diferencia_AF_MM <- rbind(Diferencia_AF,Diferencia_MM)
Diferencia_AF_MM%>%
ggplot(aes(x = reorder(Palabra, log_odds), y= log_odds, fill = autor_frecuente)) +
geom_col() +
labs(x = "-palabra", y = "Uso", title = "Fernandez vs Macri") +
coord_flip() +
tema2

25- Larreta vs Kicillof word use comparison
The idea of this graph is to show which words are the most different in their use, in this case between Horacio Larreta and Axel Kicillof
# Pivotaje y despivotaje
tweets_unpivot <- tuits_tokens %>% group_by(Politico, Palabra) %>%
count(Palabra) %>%
spread(key = Politico, value = n, fill = 0, drop = TRUE) %>%
gather(key = "Politico", value = "n", -Palabra)
# Selección de los autores
tweets_unpivot2 <- tweets_unpivot %>%
filter(Politico %in% c("H.Larreta", "A.Kicillof"))
# Se añade el total de palabras de cada autor
tweets_unpivot2 <- tweets_unpivot2 %>%
left_join(Tweets_DF %>% group_by(Politico) %>%
summarise(N = n()), by = "Politico")
`summarise()` ungrouping output (override with `.groups` argument)
# Cálculo de odds y log of odds de cada palabra
tweets_logOdds <- tweets_unpivot2 %>%
mutate(odds = (n + 1) / (N + 1)) %>%
select(Politico, Palabra, odds) %>%
spread(key = Politico, value = odds)
tweets_logOdds[,4] <- log(tweets_logOdds[,2]/tweets_logOdds[,3])
names(tweets_logOdds)[4] <- "log_odds"
tweets_logOdds[,5] <- abs(tweets_logOdds$log_odds)
names(tweets_logOdds)[5] <- "abs_log_odds"
tweets_logOdds <- tweets_logOdds %>%
mutate(autor_frecuente = if_else(log_odds > 0,
names(tweets_logOdds)[2],
names(tweets_logOdds)[3]))
Diferencia_AK <- tweets_logOdds %>%
arrange(-log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "A.Kicillof")%>%
head(15)
Diferencia_HL <- tweets_logOdds %>%
arrange(abs_log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "H.Larreta")%>%
tail(15)
Diferencia_AK_HL <- rbind(Diferencia_AK,Diferencia_HL)
Diferencia_AK_HL%>%
ggplot(aes(x = reorder(Palabra, log_odds), y= log_odds, fill = autor_frecuente)) +
geom_col() +
labs(x = "-palabra", y = "Uso", title = "Kicillof vs Larreta") +
coord_flip() +
tema2

26-Gines vs Quirós word use comparison
The idea of this graph is to show which words are the most different in their use, in this case between Gines Gonzalez and Fernán Quirós
tweets_unpivot <- tuits_tokens %>% group_by(Politico, Palabra) %>%
count(Palabra) %>%
spread(key = Politico, value = n, fill = 0, drop = TRUE) %>%
gather(key = "Politico", value = "n", -Palabra)
# Selección de los autores
tweets_unpivot2 <- tweets_unpivot %>%
filter(Politico %in% c("Gines.GG", "F.Quiros"))
# Se añade el total de palabras de cada autor
tweets_unpivot2 <- tweets_unpivot2 %>%
left_join(Tweets_DF %>% group_by(Politico) %>%
summarise(N = n()), by = "Politico")
`summarise()` ungrouping output (override with `.groups` argument)
# Cálculo de odds y log of odds de cada palabra
tweets_logOdds <- tweets_unpivot2 %>%
mutate(odds = (n + 1) / (N + 1)) %>%
select(Politico, Palabra, odds) %>%
spread(key = Politico, value = odds)
tweets_logOdds[,4] <- log(tweets_logOdds[,2]/tweets_logOdds[,3])
names(tweets_logOdds)[4] <- "log_odds"
tweets_logOdds[,5] <- abs(tweets_logOdds$log_odds)
names(tweets_logOdds)[5] <- "abs_log_odds"
tweets_logOdds <- tweets_logOdds %>%
mutate(autor_frecuente = if_else(log_odds > 0,
names(tweets_logOdds)[2],
names(tweets_logOdds)[3]))
Diferencia_GG <- tweets_logOdds %>%
arrange(-log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "Gines.GG")%>%
tail(15)
Diferencia_FQ <- tweets_logOdds %>%
arrange(-abs_log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "F.Quiros")%>%
head(15)
Diferencia_GG_FQ <- rbind(Diferencia_GG,Diferencia_FQ)
Diferencia_GG_FQ%>%
ggplot(aes(x = reorder(Palabra, log_odds), y= log_odds, fill = autor_frecuente)) +
geom_col() +
labs(x = "-palabra", y = "Uso", title = "Quirós vs Gines") +
coord_flip() +
tema2

27- Bullrich vs Cristina word use comparison
The idea of this graph is to show which words are the most different in their use, in this case between Cristina Kirchner and Patricia Bullrich
tweets_unpivot <- tuits_tokens %>% group_by(Politico, Palabra) %>%
count(Palabra) %>%
spread(key = Politico, value = n, fill = 0, drop = TRUE) %>%
gather(key = "Politico", value = "n", -Palabra)
# Selección de los autores
tweets_unpivot2 <- tweets_unpivot %>%
filter(Politico %in% c("P.Bullrich", "C.Kirchner"))
# Se añade el total de palabras de cada autor
tweets_unpivot2 <- tweets_unpivot2 %>%
left_join(Tweets_DF %>% group_by(Politico) %>%
summarise(N = n()), by = "Politico")
`summarise()` ungrouping output (override with `.groups` argument)
# Cálculo de odds y log of odds de cada palabra
tweets_logOdds <- tweets_unpivot2 %>%
mutate(odds = (n + 1) / (N + 1)) %>%
select(Politico, Palabra, odds) %>%
spread(key = Politico, value = odds)
tweets_logOdds[,4] <- log(tweets_logOdds[,2]/tweets_logOdds[,3])
names(tweets_logOdds)[4] <- "log_odds"
tweets_logOdds[,5] <- abs(tweets_logOdds$log_odds)
names(tweets_logOdds)[5] <- "abs_log_odds"
tweets_logOdds <- tweets_logOdds %>%
mutate(autor_frecuente = if_else(log_odds > 0,
names(tweets_logOdds)[2],
names(tweets_logOdds)[3]))
Diferencia_PB <- tweets_logOdds %>%
arrange(-log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "P.Bullrich")%>%
tail(15)
Diferencia_CFK <- tweets_logOdds %>%
arrange(-abs_log_odds, bygroup = FALSE)%>%
filter(autor_frecuente == "C.Kirchner")%>%
head(15)
Diferencia_PB_CFK <- rbind(Diferencia_PB,Diferencia_CFK)
Diferencia_PB_CFK%>%
ggplot(aes(x = reorder(Palabra, log_odds), y= log_odds, fill = autor_frecuente)) +
geom_col() +
labs(x = "-palabra", y = "Uso", title = "Cristina vs Bullrich") +
coord_flip() +
tema2

28- Emotions in tweets
Now we analyze a broader field of emotions that were used by the different politicians among all the tweets that have been published in this period.
Among the members of PRO and Peronism, trust stands out as the main sentiment expressed
In accounts like Espert or Del Caño what their tweets show the most is fear.
The PRO and Peronism accounts, mainly by the ministers and heads of governments, seek a feeling of * anticipation *
Other accounts are higher tone anguish over time.
Sadness is a general feeling that is incorporated in all tweets, and is understood by the complex situation that a pandemic means.
gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, sentiment) %>%
filter(Partido == "cuenta partidaria")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(Politico, Proporcion, fill = sentiment) +
geom_col(position = "stack", color = "black") +
coord_flip() +
scale_y_continuous(expand = c(0,0)) +
labs(y = "Palabras") +
theme_minimal()
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, sentiment) %>%
filter(Partido == "PRO")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(Politico, Proporcion, fill = sentiment) +
geom_col(position = "stack", color = "black") +
coord_flip() +
scale_y_continuous(expand = c(0,0)) +
labs(y = "Palabras") +
theme_minimal()
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, sentiment) %>%
filter(Partido == "Peronismo")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(Politico, Proporcion, fill = sentiment) +
geom_col(position = "stack", color = "black") +
coord_flip() +
scale_y_continuous(expand = c(0,0)) +
labs(y = "Palabras") +
theme_minimal()
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, sentiment) %>%
filter(Partido == "otros candidatos")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(Politico, Proporcion, fill = sentiment) +
geom_col(position = "stack", color = "black") +
coord_flip() +
scale_y_continuous(expand = c(0,0)) +
labs(y = "Palabras") +
theme_minimal()
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

29- Emotions month by month
Although there are no major changes when it comes to doing sentiment analysis from month to month, there are some details:
Health ministers transmit more and more confidence.
The so-called other candidates is declining the transmission of confidence.
Larreta although it has low in the feeling of confidence, continues to expose one of * anticipation *.
Kicillof has an increasing message of anguish.
gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, mes, sentiment) %>%
filter(Partido == "cuenta partidaria")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(x = mes, y =Proporcion, color = sentiment) +
geom_point() +
geom_line(aes(group = sentiment)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .4),
text = element_text(family = "serif")) +
tema2 +
facet_wrap(~ Politico) +
labs(title = "Cambio de los sentimientos en el tiempo",
x = "Mes", y = "Porporción", color = "Sentimiento")
`summarise()` regrouping output by 'Politico', 'Partido', 'mes' (override with `.groups` argument)

gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, mes, sentiment) %>%
filter(Partido == "otros candidatos")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(x = mes, y =Proporcion, color = sentiment) +
geom_point() +
geom_line(aes(group = sentiment)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .4),
text = element_text(family = "serif")) +
tema2 +
facet_wrap(~ Politico) +
labs(title = "Cambio de los sentimientos en el tiempo",
x = "Mes", y = "Porporción", color = "Sentimiento")
`summarise()` regrouping output by 'Politico', 'Partido', 'mes' (override with `.groups` argument)

gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, mes, sentiment) %>%
filter(Partido == "Peronismo")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(x = mes, y =Proporcion, color = sentiment) +
geom_point() +
geom_line(aes(group = sentiment)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .4),
text = element_text(family = "serif")) +
tema2 +
facet_wrap(~ Politico) +
labs(title = "Cambio de los sentimientos en el tiempo",
x = "Mes", y = "Porporción", color = "Sentimiento")
`summarise()` regrouping output by 'Politico', 'Partido', 'mes' (override with `.groups` argument)

gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, mes, sentiment) %>%
filter(Partido == "PRO")%>%
filter(sentiment != "negative" & sentiment !="positive")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(x = mes, y =Proporcion, color = sentiment) +
geom_point() +
geom_line(aes(group = sentiment)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .4),
text = element_text(family = "serif")) +
tema2 +
facet_wrap(~ Politico) +
labs(title = "Cambio de los sentimientos en el tiempo",
x = "Mes", y = "Porporción", color = "Sentimiento")
`summarise()` regrouping output by 'Politico', 'Partido', 'mes' (override with `.groups` argument)

30- Comparison of emotions
The idea of comparing everyone’s emotions on a graph helps for a general visualization (eliminating party accounts):
Although the number of tweets from Macri are few, it is the one that transmits the most confidence.
Those who have elected power are the ones who most trust seek in their tweets.
Candidates who have lost have mixed feelings, with a high level of fear and anguish in their writing.
Feelings that represent less than 10% of tweets are discarded.
gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, sentiment) %>%
filter(sentiment != "negative" & sentiment !="positive" & Partido != "cuenta partidaria")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(Politico, Proporcion, color = sentiment, alpha = Proporcion) +
geom_point(fill = "white", stroke = 1, shape = 21) +
geom_text(aes(label = sentiment), vjust = -.9, family = "serif") +
scale_y_continuous(labels = percent_format ()) +
tema1 +
theme(legend.position = "none",
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
text = element_text(family = "serif")) +
coord_flip() +
labs(title = "Sentimientos totales comparativo",
x = "Politico",
y = "Proporción del sentimiento")
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

gather(Tweets_DF_sentimiento, "sentiment", "values", 103:112) %>%
group_by(Politico, Partido, sentiment) %>%
filter(sentiment != "positive" & sentiment !="negative" & sentiment !="joy" & sentiment !="surprise" & Partido != "cuenta partidaria")%>%
summarise(Total = sum(values)) %>%
mutate(Proporcion = Total / sum(Total)) %>%
ggplot() +
aes(sentiment, Proporcion, color = sentiment) +
geom_point() +
geom_text(aes(label = Politico) ,vjust = -.3, size = 3) +
scale_y_continuous(limits = c(0.15, 0.47)) +
labs(title = "Sentimientos totales comparativo",
x = "Politico",
y = "Proporción del sentimiento") +
theme_minimal() +
theme(legend.position = "none")
`summarise()` regrouping output by 'Politico', 'Partido' (override with `.groups` argument)

LS0tDQp0aXRsZTogIkFuYWxpc2lzIGRlIHR3aXR0ZXI6IFBvbMOtdGljb3MgZW4gY3VhcmVudGVuYSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KYWJzdHJhY3Q6IFRoZSBpZGVhIG9mIHRoaXMgZG9jdW1lbnQgaXMgdG8gc2VlIGhvdyBzb21lIHBvbGl0aWNpYW5zIGludGVyYWN0ZWQgb24gVHdpdHRlcg0KICBmcm9tIHRoZSBiZWdpbm5pbmcgb2YgdGhlIHBhbmRlbWljIHVudGlsIFNlcHRlbWJlciAxMC4gRm9yDQogIGRvd25sb2FkIHRoZSB0d2VldHMgdXNpbmcgdGhlIFR3aXR0ZXIgQVBJIGFuZCB0aGUgcnR3ZWV0IGxpYnJhcnkNCi0tLQ0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMDIxODJCOyI+IDxoMj4gUG9saXRpY2lhbiBhbmFseXNpcyA8L2gyPiA8L3NwYW4+IDwvY2VudGVyPg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAxLSBEb3dubG9hZCB0d2VldHMgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KSSBjcmVhdGUgYSBsaXN0IG9mIGFjY291bnRzIGZyb20gd2hpY2ggSSBhbSBnb2luZyB0byBkb3dubG9hZCB0aGVpciB0d2VldHMsIGFuZCBhbHNvIGFuIGFzc2lnbm1lbnQgdG8ga25vdyB0byB3aGljaCBwb2xpdGljYWwgcGFydHkgZWFjaCBhY2NvdW50Lg0KDQpUaGUgb3JpZ2luYWwgaWRlYSBpcyB0byBoYXZlIDQgbWVtYmVycyBmcm9tIGVhY2ggb2YgdGhlIHR3byBtYWluIHBhcnRpZXMsIHRoZSBsYXN0IDQgY2FuZGlkYXRlcyBpbiB0aGUgMjAxOSBlbGVjdGlvbnMgYW5kIGFsc28gdGhlIDQgcGFydHkgYWNjb3VudHMgb24gVHdpdHRlci4NCg0KICAtICAqKkZyZW50ZSBkZSB0b2RvcyoqOiAqQWxiZXJ0byBGZXJuw6FuZGV6LCBDcmlzdGluYSBLaXJjaG5lciwgR2luZXMgR29uesOhbGV6IEdhcmPDrWEgeSBBeGVsIEtpY2lsbG9mKg0KICAtICAqKlBSTyoqOiAqTWF1cmljaW8gTWFjcmksIEhvcmFjaW8gUm9kcsOtZ3VleiBMYXJyZXRhLCBGZXJuw6FuIFF1aXJveiB5IFBhdHJpY2lhIEJ1bGxyaWNoKg0KICAtICAqKk90cm9zIGNhbmRpZGF0b3MqKjogKkpvc8OpIEx1aXMgRXNwZXJ0LCBSb2JlcnRvIExhdmFnbmEsIEp1YW4gSm9zw6kgR8OzbWV6IENlbnR1cmnDs24geSBOaWNvbGFzIGRlbCBDYcOxbyoNCiAgLSAgKipQYXJ0aWRhcmlhcyoqOiAqRnJlbnRlIGRlIFRvZG9zLCBQUk8sIEdFTiB5IFVuacOzbiBDw612aWNhIFJhZGljYWwqDQoNCmBgYHtyfQ0KY2FuZGlkYXRvcyA8LSBsaXN0KCJhbGZlcmRleiIsIA0KICAgICAgICAgICAgICAgICAgICJDRktBcmdlbnRpbmEiLCANCiAgICAgICAgICAgICAgICAgICAiZ2luZXNnZ2FyY2lhIiwNCiAgICAgICAgICAgICAgICAgICAiS2ljaWxsb2ZvayIsDQogICAgICAgICAgICAgICAgICAgIlBhcnRpZG9HRU4iLCANCiAgICAgICAgICAgICAgICAgICAiRnJlbnRlRGVUb2RvcyIsDQogICAgICAgICAgICAgICAgICAgICJtYXVyaWNpb21hY3JpIiwNCiAgICAgICAgICAgICAgICAgICAiUGF0b0J1bGxyaWNoIiwNCiAgICAgICAgICAgICAgICAgICAiaG9yYWNpb3JsYXJyZXRhIiwNCiAgICAgICAgICAgICAgICAgICAiRmVybmFuUXVpcm9zQkEiLA0KICAgICAgICAgICAgICAgICAgICJwcm9hcmdlbnRpbmEiLA0KICAgICAgICAgICAgICAgICAgICJVQ1JOYWNpb25hbCIsDQogICAgICAgICAgICAgICAgICAgImpsZXNwZXJ0IiwNCiAgICAgICAgICAgICAgICAgICAiTmljb2xhc2RlbENhbm8iLA0KICAgICAgICAgICAgICAgICAgICJSTGF2YWduYSIsDQogICAgICAgICAgICAgICAgICAgImp1YW5qb21hbHZpbmFzIikNCg0KdGlwb2N1ZW50YSA8LSBsaXN0ICgiUGVyb25pc21vIiwiY3VlbnRhIHBhcnRpZGFyaWEiLCAiUFJPIiwib3Ryb3MgY2FuZGlkYXRvcyIgKQ0KDQogVHdlZXRzPC1tYXAoY2FuZGlkYXRvcywgZnVuY3Rpb24oeCl7DQogICAgZ2V0X3RpbWVsaW5lKHVzZXIgPSB4LCBuID0gMzIwMCwgaW5jbHVkZVJ0cyA9IEYsIGV4Y2x1ZGVSZXBsaWVzID0gRikNCiAgICAgfSApDQogDQpUd2VldHNfREY8LSBkb19jYWxsX3JiaW5kKFR3ZWV0cykNCg0KcHJpbnQoIk11ZXN0cmEiKQ0KcHJpbnQoVHdlZXRzX0RGICU+JSANCiAgc2VsZWN0KHRleHQpJT4lIA0KICAgIGhlYWQoNSkpDQoNCmBgYA0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+IDItRVRMIHByb2Nlc3MgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KDQpXZSBhcmUgZ29pbmcgdG8gY2xlYW4gdXAgY2VydGFpbiBlbGVtZW50cyB0aGF0IGNhbiBjb21wbGljYXRlIHRoZSBhbmFseXNpcyBvZiB0aGUgdGV4dCwgc3VjaCBhcyBsaW5rcywgbnVtYmVycywgZ3JhcGhpY3MgYW5kIHR1cm4gZXZlcnl0aGluZyB0byBsb3dlcmNhc2UuDQoNCkluIGFkZGl0aW9uLCB3ZSBjcmVhdGUgc2V2ZXJhbCBmaWVsZHMgZm9yIHdoYXQgdGhlIGRhdGUgaXMsIGRpc2FnZ3JlZ2F0aW5nIHRoZSBmaWVsZCBpbnRvIHNldmVyYWwgZGlmZmVyZW50IG9uZXMsIHdoaWNoIHdpbGwgYmUgdXNlZCBpbiB0aGUgZnV0dXJlLCBhbmQgdGhlIHRpbWUgaXMgYWxzbyB1cGRhdGVkIHRvIHRoZSB0aW1lIHpvbmUgd2hlcmUgdGhlIHR3ZWV0ICooQXJnZW50aW5hKSogd2FzIG1hZGUuDQoNCkZpbmFsbHkgd2UgZmlsdGVyIGJ5IGRhdGUsIHRoZSBpZGVhIGlzIHRvIGhhdmUgb25seSB0d2VldHMgZnJvbSB0aGUgcGVyaW9kIDEvMy8yMDIwIHVudGlsIHRoZSBwdWJsaWNhdGlvbiBkYXRlICooU2VwIC8gMjAyMCkqDQoNCmBgYHtyfQ0KVHdlZXRzX0RGIDwtDQogIFR3ZWV0c19ERiAlPiUNCiAgIyNBbGwgdGV4dCBpbiBsb3dlcmNhc2UjIw0KICBtdXRhdGUodGV4dCA9IHRvbG93ZXIodGV4dCkpICU+JSANCiAgIyNObyBncmFwaHMjIw0KICBtdXRhdGUodGV4dCA9IGdzdWIoIlteWzpncmFwaDpdXSIsICIgIiwgdGV4dCkpICU+JSANCiAgIyNObyBsaW5rcyMjDQogIG11dGF0ZSh0ZXh0ID0gZ3N1YigiaHR0cC8vUyIsICIgIiwgdGV4dCkpICU+JSANCiAgIyNObyBudW1iZXJzIyMNCiAgbXV0YXRlKHRleHQgPSBnc3ViKCJbWzpkaWdpdDpdXSIsICIgIiwgdGV4dCkpICU+JSANCiAgIyNObyBhY2NlbnQgbWFyayMjDQogIG11dGF0ZSh0ZXh0ID0gY2hhcnRyKCfDocOpw63Ds8O6w7EnLCdhZWlvdW4nLHRleHQpKSAlPiUNCiAgIyNXZSBjaGFuZ2UgdG8gdGhlIGNvcnJlc3BvbmRpbmcgdGltZSB6b25lIyMNCiAgbXV0YXRlKGNyZWF0ZWRfYXQgPSB3aXRoX3R6KGNyZWF0ZWRfYXQsICJBbWVyaWNhL0FyZ2VudGluYS9CdWVub3NfQWlyZXMiKSklPiUgDQogICMjV2Ugc2VwYXJhdGUgdGhlIGNyZWF0ZWRfYSBmaWVsZCBpbnRvIGRheSBhbmQgdGltZXQjIw0KICBzZXBhcmF0ZShjcmVhdGVkX2F0LCBpbnRvID0gYygiZGF0ZSIsICJob3VyIiksIHNlcCA9ICIgIiklPiUgDQogICMjV2Ugc2VwYXJhdGUgdGhlIHRpbWUgaW50byBob3VycywgbWludXRlcyBhbmQgc2Vjb25kcyMjDQogICAgc2VwYXJhdGUoaG91ciwgaW50byA9IGMoImhvdXIiLCAibWludXRlcyIsInNlY29uZHMiKSwgc2VwID0gIjoiKSU+JSANCiAgIyNXZSBjaGFuZ2UgdGhlIGNvbHVtbiB3aXRoIHRoZSBuYW1lIG9mIHRoZSBwb2xpdGljaWFuIyMNCiAgIHJlbmFtZShQb2xpdGljbyA9IHNjcmVlbl9uYW1lKSAlPiUgDQogICMjV2UgY3JlYXRlIGEgY29sdW1uIHdpdGggdGhlIG51bWJlciBvZiB5ZWFyLCBtb250aCwgZGF5LCBuYW1lIG9mIGRheSBhbmQgbW9udGguIyMNCm11dGF0ZShwZXJpb2RvID0geWVhcihkYXRlKSwgDQogICAgICAgICBtZXMgPSBtb250aChkYXRlLCBsYWJlbCA9IEYsIGFiYnIgPSBGKSwNCiAgICAgICAgIGRpYSA9IGFzLm51bWVyaWMoZGF5KGRhdGUpKSwNCiAgICAgICAgIGRpYV9zZW0gPSB3ZGF5KGRhdGUsIGxhYmVsID0gVCwgYWJiciA9IEYsIHdlZWtfc3RhcnQgPSAxKSwNCiAgICAgICAgIGRpYV9wZXIgPSB5ZGF5KGRhdGUpLA0KICAgICAgICAgZGF0ZSA9IGFzLkRhdGUoZGF0ZSkgDQogICkgJT4lDQogICMjV2Ugd2lsbCBvbmx5IHVzZSBpbmZvIGZyb20gTWFyY2ggMjAyMCBvbndhcmRzIyMNCiAgZmlsdGVyKHBlcmlvZG8gPT0gMjAyMCAmIG1lcyA+IDIpIA0KDQpwcmludCgiTXVlc3RyYSIpDQpwcmludChUd2VldHNfREYgJT4lIA0KICBzZWxlY3QoUG9saXRpY28sIHN0YXR1c19pZCwgcGVyaW9kbywgbWVzLCBkaWEpJT4lIA0KICAgIGhlYWQoMTApKQ0KDQpgYGANCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gMy1Ob3JtYWxpemF0aW9uIDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KV2Ugbm9ybWFsaXplIHNvbWUgZmllbGRzLCB0byBoZWxwIHRoZSBhbmFseXNpcyBhbmQgYWxzbyB0aGUgdmlzdWFsaXphdGlvbi4NCg0KV2UgYWRkIHRoZSBtYXRjaCB0byBlYWNoIG9mIHRob3NlIGFuYWx5emVkLCBhbmQgYWxzbyBjaGFuZ2UgdGhlaXIgbmFtZSBmcm9tIHRoZSBAIHdlIHNlZSBvbiBUd2l0dGVyLCB0byBhIG5hbWUgZWFzeSBmb3IgZXZlcnlvbmUgdG8gdW5kZXJzdGFuZA0KDQoNCmBgYHtyfQ0KVHdlZXRzX0RGIDwtDQogIFR3ZWV0c19ERiAlPiUNCiAgbXV0YXRlIChQYXJ0aWRvID0gaWZlbHNlIChQb2xpdGljbyA9PSAiYWxmZXJkZXoiLCAiUGVyb25pc21vIiwNCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiQ0ZLQXJnZW50aW5hIiwgIlBlcm9uaXNtbyIsDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gImdpbmVzZ2dhcmNpYSIsICJQZXJvbmlzbW8iLCANCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiS2ljaWxsb2ZvayIsICJQZXJvbmlzbW8iLA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJVQ1JOYWNpb25hbCIsICJjdWVudGEgcGFydGlkYXJpYSIsICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiRnJlbnRlRGVUb2RvcyIsICJjdWVudGEgcGFydGlkYXJpYSIsIA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJwcm9hcmdlbnRpbmEiLCAiY3VlbnRhIHBhcnRpZGFyaWEiLA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJQYXJ0aWRvR0VOIiwgImN1ZW50YSBwYXJ0aWRhcmlhIiwNCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAibWF1cmljaW9tYWNyaSIsICJQUk8iLA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJQYXRvQnVsbHJpY2giLCAiUFJPIiwNCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiaG9yYWNpb3JsYXJyZXRhIiwgIlBSTyIsDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gIkZlcm5hblF1aXJvc0JBIiwgIlBSTyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvdHJvcyBjYW5kaWRhdG9zIikpKSkpKSkpKSkpKSkNCg0KVHdlZXRzX0RGIDwtDQogIFR3ZWV0c19ERiAlPiUNCiAgbXV0YXRlIChQb2xpdGljbyA9IGlmZWxzZSAoUG9saXRpY28gPT0gImFsZmVyZGV6IiwgIkEuRmVybmFuZGV6IiwNCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiQ0ZLQXJnZW50aW5hIiwgIkMuS2lyY2huZXIiLA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJnaW5lc2dnYXJjaWEiLCAiR2luZXMuR0ciLCANCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiS2ljaWxsb2ZvayIsICJBLktpY2lsbG9mIiwNCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiVUNSTmFjaW9uYWwiLCAiVUNSIiwgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJGcmVudGVEZVRvZG9zIiwgIlRPRE9TIiwgDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gInByb2FyZ2VudGluYSIsICJQUk8iLA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJQYXJ0aWRvR0VOIiwgIkdFTiIsDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gIm1hdXJpY2lvbWFjcmkiLCAiTS5NYWNyaSIsDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gIlBhdG9CdWxscmljaCIsICJQLkJ1bGxyaWNoIiwNCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlIChQb2xpdGljbyA9PSAiaG9yYWNpb3JsYXJyZXRhIiwgIkguTGFycmV0YSIsDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gIkZlcm5hblF1aXJvc0JBIiwgIkYuUXVpcm9zIiwgDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gIk5pY29sYXNkZWxDYW5vIiwgIk4uRGVsQ2HDsW8iLA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKFBvbGl0aWNvID09ICJqbGVzcGVydCIsICJKLkVzcGVydCIsDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoUG9saXRpY28gPT0gIlJMYXZhZ25hIiwgIlIuTGF2YWduYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdvbWV6Q2VudHVyaW9uIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKSkpKSkpKSkpKSkpKSkNCg0KcHJpbnQoIk11ZXN0cmEiKQ0KcHJpbnQoVHdlZXRzX0RGICU+JSANCiAgc2VsZWN0KFBvbGl0aWNvLCBQYXJ0aWRvLCBzb3VyY2UpJT4lIA0KICAgIHRhaWwoMTApKQ0KYGBgDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gNC1OdW1iZXIgb2YgdHdlZXRzIDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KVGhlIGZpcnN0IGFwcHJveGltYXRpb24gdGhhdCB3ZSBhcmUgZ29pbmcgdG8gaGF2ZSBpcyB0aGUgbnVtYmVyIG9mIHRpbWVzIGVhY2ggdHdlZXRlZCBmcm9tIE1hcmNoIDIwMjAgdG8gdGhlIGRhdGUgb2YgcHVibGljYXRpb24gb2YgdGhlIHJlcG9ydC4NCg0KVGhlcmUgYXJlIGNvbnNpZGVyYWJsZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGFsbCwgeW91IHNob3VsZCBub3JtYWxpemUgb3IgdXNlIHByb3BvcnRpb25zIG1vcmUgdGhhbiBvbmNlDQoNCiAgLSAqTWFjcmkgYW5kIExhdmFnbmEgaGF2ZSBmZXdlciB0d2VldHMgdGhhbiB0aGUgcmVzdCoNCiAgLSAqQ3Jpc3RpbmEgS2lyY2huZXIgaXMgYWxzbyBvZiBsaXR0bGUgcGFydGljaXBhdGlvbioNCiAgLSAqVGhlIGFjY291bnRzIG9mIEZyZW50ZSBkZSBUb2RvcywgRXNwZXJ0LCBEZWwgQ2HDsW8gYW5kIHRoZSBVQ1IgYXJlIHRoZSBtb3N0IHVzZWQqDQoNCg0KICANCmBgYHtyfQ0KQ2FudGlkYWRfdHdlZXRzID0gVHdlZXRzX0RGICU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbykgJT4lDQogIGNvdW50KFBvbGl0aWNvKQ0KICANCkNhbnRpZGFkX3R3ZWV0cyU+JSAgDQogIGdncGxvdCgpKw0KICBhZXMoeD1yZW9yZGVyKFBvbGl0aWNvLCBuKSwgeT0gbiwgZmlsbD0gUG9saXRpY28pICsNCiAgZ2VvbV9jb2woKSArDQogIGZhY2V0X3dyYXAoIlBhcnRpZG8iLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHRpdGxlID0gIkNhbnRpZGFkIHRvdGFsIGRlIHR3ZWV0cyIsIHggPSAidHdlZXRzIiwgeSA9ICJDYW50aWRhZCIpICsNCiAgICB0ZW1hMQ0KYGBgDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gNS1EYXRlIG9mIHR3ZWV0cyA8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQoNCldlIHNlZSB3aGVuIGVhY2ggb2YgdGhlIGFuYWx5emVkIHR3ZWV0cyBoYXZlIGJlZW4gcHVibGlzaGVkLCBpbiBvcmRlciB0byBzaG93IHdoZW4gdGhleSBoYWQgbW9yZSBvciBsZXNzIGFjdGlvbi4NCg0KICAtICpJbiB0aGUgY2FzZSBvZiB0aGUgRnJlbnRlIGRlIHRvZG9zIGFjY291bnQsIGFzIGl0IGhhZCBtb3JlIHRoYW4gMywyMDAgdHdlZXRzLCB0aGUgYW5hbHlzaXMgc3RhcnRzIGZyb20gdGhlIGZpcnN0IGRheXMgb2YgQXByaWwqDQoNCmBgYHtyfQ0KVHdlZXRzX0RGICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAiUFJPIikgJT4lDQogIGdncGxvdChhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIGZpbGwgPSBQb2xpdGljbykpICsNCiAgICAgIGdlb21faGlzdG9ncmFtKHBvc2l0aW9uID0gImlkZW50aXR5IiwgYmlucyA9IDIwLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJWQtJW0iLCBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIikgKw0KICAgICAgbGFicyh4ID0gImZlY2hhIGRlIHB1YmxpY2FjacOzbiIsIHkgPSAibsO6bWVybyBkZSB0d2VldHMiKSArDQogICAgICBmYWNldF93cmFwKH4gUG9saXRpY28sIG5jb2wgPSAxKSArDQogICAgICB0ZW1hMiArDQogICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkNCg0KVHdlZXRzX0RGICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAiUGVyb25pc21vIikgJT4lDQogIGdncGxvdChhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIGZpbGwgPSBQb2xpdGljbykpICsNCiAgICAgIGdlb21faGlzdG9ncmFtKHBvc2l0aW9uID0gImlkZW50aXR5IiwgYmlucyA9IDIwLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJWQtJW0iLCBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIikgKw0KICAgICAgbGFicyh4ID0gImZlY2hhIGRlIHB1YmxpY2FjacOzbiIsIHkgPSAibsO6bWVybyBkZSB0d2VldHMiKSArDQogICAgICBmYWNldF93cmFwKH4gUG9saXRpY28sIG5jb2wgPSAxKSArDQogICAgICB0ZW1hMSArDQogICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkNCg0KVHdlZXRzX0RGICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAib3Ryb3MgY2FuZGlkYXRvcyIpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBhcy5EYXRlKGRhdGUpLCBmaWxsID0gUG9saXRpY28pKSArDQogICAgICBnZW9tX2hpc3RvZ3JhbShwb3NpdGlvbiA9ICJpZGVudGl0eSIsIGJpbnMgPSAyMCwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVkLSVtIiwgZGF0ZV9icmVha3MgPSAiMSBtb250aCIpICsNCiAgICAgIGxhYnMoeCA9ICJmZWNoYSBkZSBwdWJsaWNhY2nDs24iLCB5ID0gIm7Dum1lcm8gZGUgdHdlZXRzIikgKw0KICAgICAgZmFjZXRfd3JhcCh+IFBvbGl0aWNvLCBuY29sID0gMSkgKw0KICAgICAgdGVtYTEgKw0KICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpDQoNClR3ZWV0c19ERiAlPiUNCiAgZmlsdGVyKFBhcnRpZG8gPT0gImN1ZW50YSBwYXJ0aWRhcmlhIikgJT4lDQogIGdncGxvdChhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIGZpbGwgPSBQb2xpdGljbykpICsNCiAgICAgIGdlb21faGlzdG9ncmFtKHBvc2l0aW9uID0gImlkZW50aXR5IiwgYmlucyA9IDIwLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJWQtJW0iLCBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIikgKw0KICAgICAgbGFicyh4ID0gImZlY2hhIGRlIHB1YmxpY2FjacOzbiIsIHkgPSAibsO6bWVybyBkZSB0d2VldHMiKSArDQogICAgICBmYWNldF93cmFwKH4gUG9saXRpY28sIG5jb2wgPSAxKSArDQogICAgICB0ZW1hMiAgKw0KICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpDQpgYGANCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+IDYtTnVtYmVyIG9mIHR3ZWV0cyBhYm91dCBDT1ZJRCA8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQoNClRoZSBtb3N0IGltcG9ydGFudCB0b3BpYyBvZiB0aGUgeWVhciBpcyB0aGUgY29yb25hdmlydXMsIHRoZSBpZGVhIGlzIHRvIHNlZSB3aGF0IHBlcmNlbnRhZ2Ugb2YgdGhlIHR3ZWV0cyBtYWRlIHRoZXNlIG1vbnRocyBkZWFsIHdpdGggdGhlIGNvcm9uYXZpcnVzLCBmb3IgdGhhdCB0aGV5IHdpbGwgbG9vayBmb3Iga2V5d29yZHMgdGhhdCBkZXRlcm1pbmUgdGhhdCB0aGUgdHdlZXQgaXMgYWJvdXQgdGhlIHBhbmRlbWljLg0KDQogIC0gKkNsZWFybHkgdGhlIG1pbmlzdGVycyBhcmUgdGhlIG9uZXMgd2hvIHNwb2tlIHRoZSBtb3N0IGFib3V0IHRoZSBDb3JvbmF2aXJ1cywgd2l0aCA3NSUgb2YgdGhlaXIgdHdlZXRzLioNCiAgDQogIC0gKkdvdmVybm9ycyBLaWNpbG9mZiBhbmQgTGFycmV0YSBjb250aW51ZSwgd2hvIGRpc2N1c3NlZCB0aGUgZXZvbHV0aW9uIG9mIHRoZSBwYW5kZW1pYyBpbiB0aGVpciBkaXN0cmljdHMuKg0KDQogIC0gKlRvIGEgbGVzc2VyIGV4dGVudCB0aGUgbGVhZGVycyBvZiB0aGUgdHdvIG1haW4gcGFydGllcyBzcG9rZS4qDQoNCiAgLSAqRGVsIENhw7FvIGlzIHRoZSBvbmUgd2hvIHNwb2tlIHRoZSBtb3N0IGFtb25nIHRoZSBvdGhlciBjYW5kaWRhdGVzLCBmb2xsb3dlZCBieSBFc3BlcnQsIHdoaWxlIExhdmFnbmEgYW5kIEfDs21leiBDZW50dXJpw7NuIHNwb2tlIHZlcnkgbGl0dGxlLioNCg0KICAtICpQYXJ0eSBhY2NvdW50cywgZXhjZXB0IHRob3NlIG9mIHRoZSBVQ1IsIHdlcmUgbm90IHdpZGVseSB1c2VkIHRvIHRhbGsgYWJvdXQgdGhlIENvcm9uYXZpcnVzKg0KDQoNCg0KYGBge3J9DQojV2UgbG9vayBmb3IgdHdlZXRzIHdpdGggdGhlIHdvcmQgY292aWQNClBhbGFicmFzX2NvdmlkIDwtICJjb3ZpZHxjb3ZpZC0xOXxjb3ZpZDE5fGNvcm9uYXZpcnVzfCNjb3ZpZHwjY292aWQtMTl8I2NvdmlkMTl8I2Nvcm9uYXZpcnVzfHRlc3R8dGVzdGVvfHRlc3Rlb3N8cGNyfHNlcm9sb2dpY298aGlzb3BhZG98YW50aWJpb3RpY29zfGFwbGFuYXJ8Y3VydmF8Y3VhcmVudGVuYXxjb250YWdpb3xlbmZlcm1lZGFkfGVwaWRlbWlhfHBhbmRlbWlhfGFsYXJtYXxnZWx8Y3VpZGFkb3N8aW5jdWJhY2lvbnxqYWJvbnxiYXJiaWpvfGJhcmJpam9zfG1hc2NhcmlsbGF8bWFzY2FyaWxsYXN8bWVyc3xzYXJzfHZhY3VuYXx3dWhhbnxveGZvcmR8YXN0cmF8emVuZWNhfHRyYW5zbWlzaW9ufGV4cG9uZW5jaWFsfGNhc29zfGR1cGxpY2FjaW9ufGRpc3RhbmNpYW1pZW50b3xjb2xhcHNvfHNhbHVkfGxldGFsaWRhZHxtb3J0YWxpZGFkfHZlbnRpbGFkb3J8aWN1fHVjaXx1dGl8aW5tdW5pZGFkfHNlcm9sb2dpY2F8ZGlzdGFuY2lhbWllbnRvfHZpcnVzfGFzaW50b21hdGljb3xjYXNvIHNvc3BlY2hvc298b2xmYXRvfGd1c3RvfHRlcmFwaWF8c2F0dXJhY2lvbnxjbGluaWNhfHBvc2l0aXZpZGFkfHBvc2l0aXZpb3N8cmViYcOxb3xpbm11bmlkYWR8aG9zcGl0YWx8aG9zcGl0YWxlc3xhc3BvfGFpc2xhbWllbnRvIg0KVHdlZXRzX0RGJENvdmlkIDwtIGdyZXBsKFBhbGFicmFzX2NvdmlkLCBUd2VldHNfREYkdGV4dCwgaWdub3JlLmNhc2UgPSJUcnVlIikNCg0KVHdlZXRzX0RGICU+JSANCmNvdW50KFBvbGl0aWNvLCBQYXJ0aWRvLENvdmlkKSAlPiUNCiAgZ3JvdXBfYnkoUG9saXRpY28pICU+JQ0KICBtdXRhdGUoUHJvcG9yY2lvbiA9IG4gLyBzdW0obikpICU+JQ0KICBtdXRhdGUoQ292aWQgPSBpZmVsc2UoQ292aWQgPT0gVCwgIlNvYnJlIENPVklEIiwgIk90cm8gdGVtYSIpKSU+JQ0KZ2dwbG90KCkgKw0KICBhZXMoUG9saXRpY28sIFByb3BvcmNpb24sIGZpbGwgPSBDb3ZpZCkgKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCkpICsNCiAgICAgIGZhY2V0X3dyYXAoIlBhcnRpZG8iLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpDQpgYGANCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+ICA3LSBXb3JkY2xvdWQgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KDQpUaGUgaWRlYSBvZiDigIvigIt0aGUgd29yZCBjbG91ZCBpcyB0byBrbm93IHdoaWNoIGFyZSB0aGUgMjAwIHdvcmRzIHRoYXQgd2VyZSB1c2VkIHRoZSBtb3N0IGJ5IHRob3NlIGFuYWx5emVkIHRoZXNlIG1vbnRocywgYXMgZXhwZWN0ZWQgdGhleSBzdGFuZCBvdXQgKioiY29yb25hdmlydXMiKiosICoqImNvdmlkIioqLCAqKiJwYW5kZW1pYSIqKiBvciAqKiJjdWFyZW50ZW5hIioqDQoNCg0KYGBge3J9DQp0dWl0c190b2tlbnMgPC0NCiAgVHdlZXRzX0RGICU+JQ0KICB1bm5lc3RfdG9rZW5zKGlucHV0ID0gdGV4dCwgb3V0cHV0ID0gUGFsYWJyYSwgdG9rZW4gPSAid29yZHMiKSAlPiUNCiAgc2VsZWN0KFBvbGl0aWNvLCBQYWxhYnJhLCBzdGF0dXNfaWQsIHBlcmlvZG8sIG1lcywgaG91ciwgUGFydGlkbykgJT4lDQogIG11dGF0ZShzdGF0dXNfaWQgPSBnc3ViKCI8KC4qKT4rPyIsICIiLCBzdGF0dXNfaWQpKSAlPiUNCiAgZmlsdGVyKCFQYWxhYnJhICVpbiUgc3RvcHdvcmRzKCJlcyIpKSAlPiUNCiAgZmlsdGVyKCFQYWxhYnJhICVpbiUgYygidC5jbyIsICJodHRwcyIsICJ2w4PCrWEiLCAieW91dHViZSIsICJhbXAiKSkNCg0KUGFsYWJyYXNfc2luaG95bWFzID0gdHVpdHNfdG9rZW5zICAlPiUNCiAgZmlsdGVyKFBhbGFicmEgIT0gIm1hcyIgJiBQYWxhYnJhICE9ICJob3kiKSANCg0Kd29yZGNsb3VkKHdvcmRzID0gUGFsYWJyYXNfc2luaG95bWFzJFBhbGFicmEsIA0KICAgICAgICAgIHNjYWxlPWMoMiwuMiksIA0KICAgICAgICAgIG1heC53b3Jkcz0yMDAsIHJhbmRvbS5vcmRlcj1GQUxTRSwgcm90LnBlcj0wLjM1LCANCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiRGFyazIiKSwNCiAgICAgICAgICApDQoNCg0KYGBgDQoNCg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiA4LURvd25sb2FkIGEgZGljdGlvbmFyeSA8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQoNCldlIGRvd25sb2FkIGEgZGljdGlvbmFyeSB0aGF0IGhhcyB0aGUgd29yZHMgaW4gU3BhbmlzaCwgYW5kIGFzc2lnbnMgaXQgYSB2YWx1ZSBiZXR3ZWVuIC01IHRvIDUsIHNob3dpbmcgdGhlIHBvc2l0aXZpdHkgb3IgbmVnYXRpdml0eSBvZiB0aGUgd29yZC4NCg0KV2UgZWxpbWluYXRlIHRoZSB3b3JkICoiTm8iKiB0aGF0IHRha2VzIGl0IGFzIG5lZ2F0aXZlLCB3aGVuIGluIFNwYW5pc2ggaXQgaXMgYSBjb25uZWN0b3Igc29tZXRpbWVzLCBhbmQgdGhlIHdvcmQgKuKAnE5lZ3Jv4oCdKiAoTmlnZ2EpIHRoYXQgdGFrZXMgaXQgd2l0aCB0aGUgbWF4aW11bSBuZWdhdGl2ZSB2YWx1ZQ0KDQoNCmBgYHtyfQ0KZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pib3Njb21lbmRvemEvcnB1YnMvbWFzdGVyL3NlbnRpbWllbnRvc19hZmlubi9sZXhpY29fYWZpbm4uZW4uZXMuY3N2IiwNCiAgICAgICAgICAgICAgImxleGljb19hZmlubi5lbi5lcy5jc3YiKQ0KDQphZmlubiA8LSByZWFkLmNzdigibGV4aWNvX2FmaW5uLmVuLmVzLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGLCBmaWxlRW5jb2RpbmcgPSAibGF0aW4xIikgJT4lIA0KICB0YmxfZGYoKQ0KDQphZmlubiRQdW50dWFjaW9uIDwtIGlmZWxzZShhZmlubiRQYWxhYnJhID09ICJubyIsIDAsIGFmaW5uJFB1bnR1YWNpb24pDQphZmlubiRQdW50dWFjaW9uIDwtIGlmZWxzZShhZmlubiRQYWxhYnJhID09ICJuZWdybyIsIDAsIGFmaW5uJFB1bnR1YWNpb24pDQoNCnByaW50KCJNdWVzdHJhIikNCmFmaW5uICU+JQ0KICBzZWxlY3QoUGFsYWJyYSwgUHVudHVhY2lvbikgJT4lDQogICAgYXJyYW5nZShQdW50dWFjaW9uKSAlPiUNCiAgcHJpbnQoaGVhZCgxMCkpDQoNCmFmaW5uICU+JQ0KICBzZWxlY3QoUGFsYWJyYSwgUHVudHVhY2lvbikgJT4lDQogICAgYXJyYW5nZSgtUHVudHVhY2lvbikgJT4lDQogIHByaW50KHRhaWwoMTApKQ0KYGBgDQoNCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+IDktIFdvcmQgc2VwYXJhdGlvbiA8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQoNCldlIHNlcGFyYXRlZCB0aGUgZGlmZmVyZW50IHdvcmRzIHRoYXQgZWFjaCBvZiB0aGUgcG9saXRpY2lhbnMgdXNlZCBpbiB0aGVpciB0d2VldHMsIGFuZCB3ZSBlbGltaW5hdGVkIHNvbWUgb2YgVHdpdHRlcidzIG93biB3b3JkcyBhbmQgdGhlIHNvLWNhbGxlZCBzdG9wd29yZHMgdGhhdCBhcmUgdGhlIG1vc3QgZnJlcXVlbnQgd29yZHMgaW4gdGhlIFNwYW5pc2ggbGFuZ3VhZ2UuDQoNCg0KYGBge3J9DQpwcmludCAoIk11ZXN0cmEiKQ0KcHJpbnQgKHR1aXRzX3Rva2VucyAlPiUNCiAgICBzZWxlY3QoUG9saXRpY28sIFBhbGFicmEpICU+JSAgICANCiAgICAgICAgIGhlYWQgKDEwKSkNCmBgYA0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAxMC0gV2UgdmFsdWUgd29yZHMgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KDQpXZSBqb2luIHRoZSBzY29yaW5nIGRpY3Rpb25hcnkgd2l0aCB0aGUgd29yZHMgdGhhdCBlYWNoIG9mIHRob3NlIGFuYWx5emVkIHVzZWQsIHNvIHRoYXQgZWFjaCB3b3JkIGhhcyBhIHZhbHVlLCBhbmQgaXQgaGVscHMgdXMgdG8gYW5hbHl6ZSB3aGF0IGVhY2ggcG9saXRpY2lhbiB3cm90ZS4NCg0KVGhlIHdvcmRzIHdpbGwgYmU6DQoNCiAgLSBJZiB0aGV5IGhhdmUgYSB2YWx1ZSBncmVhdGVyIHRoYW4gMCAqKlBvc2l0aXZlKioNCiAgDQogIC0gSWYgdGhleSBhcmUgbGVzcyB0aGFuIDAgKipOZWdhdGl2ZSoqDQogIA0KICAtIEluIGNhc2UgdGhlIHdvcmQgZG9lcyBub3QgaGF2ZSBhIGxvYWQgb2YgZmVlbGluZ3MgKipOZXV0cmFsKioNCg0KDQpgYGB7cn0NCnR1aXRzX3Rva2Vuc19lbW9jaW9uZXMgPC0gICANCiB0dWl0c190b2tlbnMgJT4lDQppbm5lcl9qb2luKGFmaW5uLCAuLCBieSA9ICJQYWxhYnJhIikgJT4lDQogIG11dGF0ZShDYWxpZmljYWNpb24gPSBpZmVsc2UoUHVudHVhY2lvbiA+IDAsICJQb3NpdGl2YSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFB1bnR1YWNpb24gPT0gMCwgIk5ldXRyYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5lZ2F0aXZhIikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICkgICAgICANCg0KcHJpbnQgKCJNdWVzdHJhIikNCnByaW50ICh0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIHNlbGVjdChQb2xpdGljbywgUGFsYWJyYSwgUHVudHVhY2lvbiwgQ2FsaWZpY2FjaW9uKSAlPiUgICAgDQogICAgICAgICB0YWlsICgxMCkpDQpgYGANCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+IDExLSBXaG8gdXNlcyBtb3N0IGNoYXJhY3RlcnM/IDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KVGhlIGlkZWEgaXMgdG8gZmluZCB3aGF0IGlzIHRoZSBhdmVyYWdlIGxlbmd0aCAobnVtYmVyIG9mIGNoYXJhY3RlcnMpIG9mIHRoZSB0d2VldHMgbWFkZSBieSBlYWNoIG9mIHRob3NlIGFuYWx5emVkLg0KDQpUaGUgZnVydGhlciB0byB0aGUgcmlnaHQgdGhlIGJveCBpcywgdGhlIGxvbmdlciB0aGUgdHdlZXRzIHRoZXkgd3JpdGUsIGluIHRoYXQgYXNwZWN0IHRoZXkgc3RhbmQgb3V0Og0KDQogIC0gKkxhdmFnbmEsIFBhdHJpY2lhIEJ1bGxyaWNoLCBMYXJyZXRhIGFuZCBGZXJuw6FuIFF1aXLDs3MgYXJlIHRoZSBvbmVzIHdobyB3cml0ZSB0aGUgbG9uZ2VzdCB0d2VldHMuKg0KICANCiAgLSAqVGhvc2UgcmVsYXRlZCB0byB0aGUgUFJPIGFyZSB0byB3cml0ZSBsb25nZXIgdHdlZXRzKg0KDQoNCmBgYHtyfQ0KVHdlZXRzX0RGICU+JSANCmdncGxvdCgpKw0KICBhZXMoeD0gUG9saXRpY28sIHk9IGRpc3BsYXlfdGV4dF93aWR0aCwgY29sb3I9IFBvbGl0aWNvKSArDQogIGdlb21fYm94cGxvdCAoKSArDQogICAgbGFicyh0aXRsZSA9ICJMYXJnbyBwcm9tZWRpbyBkZWwgdHdlZXQiLCB4ID0gIlBvbGl0aWNvIiwgeSA9ICJDYW50aWRhZCBjYXJhY3RlcmVzIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICAgIHRlbWExDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gMTItIFdobyB1c2VzIG1vc3Qgd29yZHM/IDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KVGhlIGlkZWEgaXMgdG8gYW5hbHl6ZSB3aG8gaXMgdGhlIG9uZSB3aG8gdXNlZCB0aGUgbW9zdCBkaWZmZXJlbnQgd29yZHMgb24gYXZlcmFnZSBkdXJpbmcgdGhpcyB0aW1lLCBpbiB0aGlzIGNhc2Ugd2UgYXJlIGdvaW5nIHRvIGRpdmlkZSBieSB0aGUgbnVtYmVyIG9mIHR3ZWV0cyBoZSBtYWRlLCBzbyBpdCBpcyBub3JtYWxpemVkIGZvciBhbGwgdGhvc2UgYW5hbHl6ZWQuDQoNCipDb21tb24gY29ubmVjdG9ycyBzdWNoIGFzICJvbiIsICJ0byIsICJmcm9tIiwgZXRjLiBhcmUgbm90IGNvdW50ZWQqDQoNCiAgLSAqRXNwZXJ0IGlzIGJlbG93IDE1IHdvcmRzIHBlciB0d2VldCwgaXQgaXMgdGhlIGxlYXN0IHVzZWQuKg0KICAtICpUaGUgcmVzdCBpcyBpbiBhIHNpbWlsYXIgYW1vdW50IG9mIGJldHdlZW4gMTUgYW5kIDIwIHdvcmRzLioNCg0KDQoNCmBgYHtyfQ0KQ2FudGlkYWRfcGFsYWJyYXM9IHR1aXRzX3Rva2VucyU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbyklPiUNCiAgY291bnQoUG9saXRpY28pJT4lDQppbm5lcl9qb2luKENhbnRpZGFkX3R3ZWV0cywgLiwgYnkgPSAiUG9saXRpY28iKSU+JQ0KICBtdXRhdGUoY2FudGlkYWRfcHJvbWVkaW8gPSBuLnkgLyBuLngpDQoNCg0KQ2FudGlkYWRfcGFsYWJyYXMlPiUgZ2dwbG90KCkrDQogIGFlcyh4PXJlb3JkZXIoUG9saXRpY28sIC1jYW50aWRhZF9wcm9tZWRpbyksIHk9IGNhbnRpZGFkX3Byb21lZGlvLCBmaWxsPSBQb2xpdGljbykgKw0KICBnZW9tX2NvbCgpICsNCiAgZmFjZXRfd3JhcCgiUGFydGlkby54Iiwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicyh0aXRsZSA9ICJVc28gZGUgcGFsYWJyYXMiLCB4ID0gInR3ZWV0cyIsIHkgPSAiQ2FudGlkYWQiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogICAgdGVtYTENCg0KDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gIDEzLSBXaG8gdXNlcyB0aGUgZGlmZmVyZW50IHdvcmRzPyA8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQpXZSBzZWVrIHRvIHNlZSB0aGUgZGlzdGluY3RpdmUgbGV4aWNvbiB0aGF0IGlzIGluIGVhY2ggb2YgdGhlIGFjY291bnRzLCBjb3VudGluZyB0aGVpciB1bmlxdWUgd29yZHMgYW5kIGl0IHNob3dzOg0KDQotICpEaWZmZXJlbmNlcyBiZXR3ZWVuIExhdmFnbmEsIE1hY3JpLCBDcmlzdGluYSB3aXRoIHRoZSByZXN0IG9mIHRob3NlIHdobyB3cml0ZSoNCg0KLSAqRXNwZXJ0IHRoYXQgaXMgdGhlIG9uZSB3aXRoIHRoZSBsZWFzdCB2YXJpZWQgbGV4aWNvbioNCg0KDQpgYGB7cn0NCnR1aXRzX3Rva2VucyU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbyklPiUNCiAgZGlzdGluY3QoUGFsYWJyYSklPiUNCiAgY291bnQoUG9saXRpY28pJT4lDQppbm5lcl9qb2luKENhbnRpZGFkX3R3ZWV0cywgLiwgYnkgPSAiUG9saXRpY28iKSAgJT4lDQogIG11dGF0ZShjYW50aWRhZF9wcm9tZWRpbyA9IG4ueSAvIG4ueCkgJT4lIA0KICBnZ3Bsb3QoKSsNCiAgYWVzKHg9cmVvcmRlcihQb2xpdGljbywgY2FudGlkYWRfcHJvbWVkaW8pLCB5PSBjYW50aWRhZF9wcm9tZWRpbywgZmlsbD0gUG9saXRpY28pICsNCiAgZ2VvbV9jb2woKSArDQogIGZhY2V0X3dyYXAoIlBhcnRpZG8ueCIsIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnModGl0bGUgPSAiUGFsYWJyYXMgZGlzdGludGFzIiwgeCA9ICJ0d2VldHMiLCB5ID0gIkNhbnRpZGFkIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICAgIHRlbWExDQogIA0KYGBgDQoNCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+IDE0LSBNb3N0IHVzZWQgd29yZHMgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KTm93IHRoYXQgd2Uga25vdyB3aXRoIHdoYXQgdmFyaWV0eSBvZiB3b3Jkcywgd2UgY2FuIGFuYWx5emUgd2hpY2ggb25lcyB0aGV5IHVzZWQgdGhlIG1vc3QNCg0KSW4gdGhpcyBjYXNlLCBlYWNoIGdyYXBoIGhhcyBhIGRpZmZlcmVudCBzY2FsZSBzbyB0aGF0IGl0IGlzIG5vdCBsb3N0IGR1ZSB0byB0aGUgbnVtYmVyIG9mIHR3ZWV0cyBtYWRlLg0KDQpUaGUgbW9zdCB1c2VkIHdvcmRzIHdlcmU6DQoNCi0gIiphdm9pZCoiDQotICIqZGVidCoiDQotICIqSnVzdGljZSoiDQotICIqZnJlZWRvbSoiIG1haW5seSB1c2VkIGJ5IEVzcGVydC4NCg0KDQpgYGB7cn0NCnR1aXRzX3Rva2Vuc19lbW9jaW9uZXMgJT4lDQogICAgZ3JvdXBfYnkoUGFydGlkbywgUG9saXRpY28pICU+JQ0KICAgIGNvdW50KFBhbGFicmEsIHNvcnQgPSBUKSAlPiUNCiAgICAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gbiwgbj0gMTApICU+JQ0KICAgICAgZmlsdGVyKFBhcnRpZG8gPT0gICJQUk8iKSAlPiUNCiAgICBnZ3Bsb3QoKSArDQogICAgYWVzKFBhbGFicmEsIG4sIGZpbGwgPSBQb2xpdGljbykgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGZhY2V0X3dyYXAoIlBvbGl0aWNvIiwgc2NhbGVzID0gImZyZWUiKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGxhYnModGl0bGUgPSAiUGFsYWJyYXMgbcOhcyB1c2FkYXMiKSArDQogICAgIHRlbWExDQoNCiB0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIGdyb3VwX2J5KFBhcnRpZG8sIFBvbGl0aWNvKSAlPiUNCiAgICBjb3VudChQYWxhYnJhLCBzb3J0ID0gVCkgJT4lDQogICAgIHNsaWNlX21heChvcmRlcl9ieSA9IG4sIG49IDEwKSAlPiUNCiAgICAgIGZpbHRlcihQYXJ0aWRvID09ICAiUGVyb25pc21vIikgJT4lDQogICAgZ2dwbG90KCkgKw0KICAgIGFlcyhQYWxhYnJhLCBuLCBmaWxsID0gUG9saXRpY28pICsNCiAgICBnZW9tX2NvbCgpICsNCiAgICBmYWNldF93cmFwKCJQb2xpdGljbyIsIHNjYWxlcyA9ICJmcmVlIikgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBsYWJzKHRpdGxlID0gIlBhbGFicmFzIG3DoXMgdXNhZGFzIikgKw0KICAgICB0ZW1hMQ0KIA0KICB0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIGdyb3VwX2J5KFBhcnRpZG8sIFBvbGl0aWNvKSAlPiUNCiAgICBjb3VudChQYWxhYnJhLCBzb3J0ID0gVCkgJT4lDQogICAgIHNsaWNlX21heChvcmRlcl9ieSA9IG4sIG49IDEwKSAlPiUNCiAgICAgIGZpbHRlcihQYXJ0aWRvID09ICAib3Ryb3MgY2FuZGlkYXRvcyIpICU+JQ0KICAgIGdncGxvdCgpICsNCiAgICBhZXMoUGFsYWJyYSwgbiwgZmlsbCA9IFBvbGl0aWNvKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgZmFjZXRfd3JhcCgiUG9saXRpY28iLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicyh0aXRsZSA9ICJQYWxhYnJhcyBtw6FzIHVzYWRhcyIpICsNCiAgICAgdGVtYTENCiAgDQogICB0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIGdyb3VwX2J5KFBhcnRpZG8sIFBvbGl0aWNvKSAlPiUNCiAgICBjb3VudChQYWxhYnJhLCBzb3J0ID0gVCkgJT4lDQogICAgIHNsaWNlX21heChvcmRlcl9ieSA9IG4sIG49IDEwKSAlPiUNCiAgICAgIGZpbHRlcihQYXJ0aWRvID09ICAiY3VlbnRhIHBhcnRpZGFyaWEiKSAlPiUNCiAgICBnZ3Bsb3QoKSArDQogICAgYWVzKFBhbGFicmEsIG4sIGZpbGwgPSBQb2xpdGljbykgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGZhY2V0X3dyYXAoIlBvbGl0aWNvIiwgc2NhbGVzID0gImZyZWUiKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGxhYnModGl0bGUgPSAiUGFsYWJyYXMgbcOhcyB1c2FkYXMiKSArDQogICAgIHRlbWExDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gMTUtIE1vc3QgdXNlZCBwb3NpdGl2ZSB3b3JkcyA8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQpCeSBoYXZpbmcgYSBzY29yZSBmb3IgZWFjaCB3b3JkIGdpdmVuIGJ5IHRoZSBsZXhpY29uIGRpY3Rpb25hcnksIHdlIGNhbiBhbHNvIGxvb2sgZm9yIHRoZSBwb3NpdGl2ZSB3b3JkcyB0aGF0IGVhY2ggb2YgdGhlIHBvbGl0aWNpYW5zIHVzZSB0aGUgbW9zdC4NCg0KSW4gdGhpcyBjYXNlOg0KDQotIE5vdGUgdGhlIHVzZSBvZiB0aGUgd29yZHMgKioiZnJlZWRvbSIqKiBhbmQgKioianVzdGljZSIqKiB3aGljaCBhcmUgY29uc2lkZXJlZCBwb3NpdGl2ZQ0KDQotIFRoZSB1c2Ugb2YgdGhlIHdvcmQgKioidGhhbmsgeW91IioqIGFwcGVhcnMgcXVpdGUgYSBsb3QsIG1haW5seSBmcm9tIHRob3NlIGFjY291bnRzIHJlbGF0ZWQgdG8gaGVhbHRoICoqKEdpbmVzIEdvbnrDoWxleiBHYXJjw61hIGFuZCBGZXJuw6FuIFF1aXLDs3MpKioNCg0KDQpgYGB7cn0NCiB0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIGZpbHRlcihDYWxpZmljYWNpb24gPT0gICJQb3NpdGl2YSIpICU+JQ0KICAgIGdyb3VwX2J5KFBhcnRpZG8sIFBvbGl0aWNvKSAlPiUNCiAgICBjb3VudChQYWxhYnJhLCBzb3J0ID0gVCkgJT4lDQogICAgIHNsaWNlX21heChvcmRlcl9ieSA9IG4sIG49IDEwKSAlPiUNCiAgICAgIGZpbHRlcihQYXJ0aWRvID09ICAiUFJPIikgJT4lDQogICAgZ2dwbG90KCkgKw0KICAgIGFlcyhQYWxhYnJhLCBuLCBmaWxsID0gUG9saXRpY28pICsNCiAgICBnZW9tX2NvbCgpICsNCiAgICBmYWNldF93cmFwKCJQb2xpdGljbyIsIHNjYWxlcyA9ICJmcmVlIikgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBsYWJzKHRpdGxlID0gIlBhbGFicmFzIFBvc2l0aXZhcyBtw6FzIHVzYWRhcyIpIA0KDQogdHVpdHNfdG9rZW5zX2Vtb2Npb25lcyAlPiUNCiAgICBmaWx0ZXIoQ2FsaWZpY2FjaW9uID09ICAiUG9zaXRpdmEiKSAlPiUNCiAgICBncm91cF9ieShQYXJ0aWRvLCBQb2xpdGljbykgJT4lDQogICAgY291bnQoUGFsYWJyYSwgc29ydCA9IFQpICU+JQ0KICAgICBzbGljZV9tYXgob3JkZXJfYnkgPSBuLCBuPSAxMCkgJT4lDQogICAgICBmaWx0ZXIoUGFydGlkbyA9PSAgIlBlcm9uaXNtbyIpICU+JQ0KICAgIGdncGxvdCgpICsNCiAgICBhZXMoUGFsYWJyYSwgbiwgZmlsbCA9IFBvbGl0aWNvKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgZmFjZXRfd3JhcCgiUG9saXRpY28iLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicyh0aXRsZSA9ICJQYWxhYnJhcyBQb3NpdGl2YXMgbcOhcyB1c2FkYXMiKSANCiANCiAgdHVpdHNfdG9rZW5zX2Vtb2Npb25lcyAlPiUNCiAgICBmaWx0ZXIoQ2FsaWZpY2FjaW9uID09ICAiUG9zaXRpdmEiKSAlPiUNCiAgICBncm91cF9ieShQYXJ0aWRvLCBQb2xpdGljbykgJT4lDQogICAgY291bnQoUGFsYWJyYSwgc29ydCA9IFQpICU+JQ0KICAgICBzbGljZV9tYXgob3JkZXJfYnkgPSBuLCBuPSAxMCkgJT4lDQogICAgICBmaWx0ZXIoUGFydGlkbyA9PSAgIm90cm9zIGNhbmRpZGF0b3MiKSAlPiUNCiAgICBnZ3Bsb3QoKSArDQogICAgYWVzKFBhbGFicmEsIG4sIGZpbGwgPSBQb2xpdGljbykgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGZhY2V0X3dyYXAoIlBvbGl0aWNvIiwgc2NhbGVzID0gImZyZWUiKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGxhYnModGl0bGUgPSAiUGFsYWJyYXMgUG9zaXRpdmFzIG3DoXMgdXNhZGFzIikgDQogIA0KICAgdHVpdHNfdG9rZW5zX2Vtb2Npb25lcyAlPiUNCiAgICBmaWx0ZXIoQ2FsaWZpY2FjaW9uID09ICAiUG9zaXRpdmEiKSAlPiUNCiAgICBncm91cF9ieShQYXJ0aWRvLCBQb2xpdGljbykgJT4lDQogICAgY291bnQoUGFsYWJyYSwgc29ydCA9IFQpICU+JQ0KICAgICBzbGljZV9tYXgob3JkZXJfYnkgPSBuLCBuPSAxMCkgJT4lDQogICAgICBmaWx0ZXIoUGFydGlkbyA9PSAgImN1ZW50YSBwYXJ0aWRhcmlhIikgJT4lDQogICAgZ2dwbG90KCkgKw0KICAgIGFlcyhQYWxhYnJhLCBuLCBmaWxsID0gUG9saXRpY28pICsNCiAgICBnZW9tX2NvbCgpICsNCiAgICBmYWNldF93cmFwKCJQb2xpdGljbyIsIHNjYWxlcyA9ICJmcmVlIikgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBsYWJzKHRpdGxlID0gIlBhbGFicmFzIFBvc2l0aXZhcyBtw6FzIHVzYWRhcyIpIA0KYGBgDQoNCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+IDE2LSBNb3N0IHVzZWQgbmVnYXRpdmUgd29yZHMgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KDQpCeSBoYXZpbmcgYSBzY29yZSBmb3IgZWFjaCB3b3JkIGdpdmVuIGJ5IHRoZSBsZXhpY29uIGRpY3Rpb25hcnksIHdlIGNhbiBhbHNvIGxvb2sgZm9yIHRoZSBuZWdhdGl2ZSB3b3JkcyB0aGF0IGVhY2ggb2YgdGhlIHBvbGl0aWNpYW5zIHVzZSB0aGUgbW9zdC4NCg0KICAtICpBdm9pZCosICpFbWVyZ2VuY3kqIG9yICpQcm9ibGVtKiBhcmUgdGhlIHdvcmRzIHRoYXQgYXBwZWFyIHRoZSBtb3N0LCB3aXRoaW4gdGhlIG1haW4gdG9waWMgb2Ygc3BlZWNoLCB3aGljaCBpcyB0aGUgcGFuZGVtaWMuDQoNCiAgLSAqRGVidCogaXMgYW5vdGhlciB3aWRlbHkgdXNlZCB3b3JkLCBhIGRpZmZpY3VsdCBzdWJqZWN0IHRvIGF2b2lkIHRoaXMgeWVhci4NCg0KDQoNCmBgYHtyfQ0KIHR1aXRzX3Rva2Vuc19lbW9jaW9uZXMgJT4lDQogICAgZmlsdGVyKENhbGlmaWNhY2lvbiA9PSAgIk5lZ2F0aXZhIikgJT4lDQogICAgZ3JvdXBfYnkoUGFydGlkbywgUG9saXRpY28pICU+JQ0KICAgIGNvdW50KFBhbGFicmEsIHNvcnQgPSBUKSAlPiUNCiAgICAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gbiwgbj0gMTApICU+JQ0KICAgICAgZmlsdGVyKFBhcnRpZG8gPT0gICJQUk8iKSAlPiUNCiAgICBnZ3Bsb3QoKSArDQogICAgYWVzKFBhbGFicmEsIG4sIGZpbGwgPSBQb2xpdGljbykgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGZhY2V0X3dyYXAoIlBvbGl0aWNvIiwgc2NhbGVzID0gImZyZWUiKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGxhYnModGl0bGUgPSAiUGFsYWJyYXMgTmVnYXRpdmFzIG3DoXMgdXNhZGFzIikgDQoNCiB0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIGZpbHRlcihDYWxpZmljYWNpb24gPT0gICJOZWdhdGl2YSIpICU+JQ0KICAgIGdyb3VwX2J5KFBhcnRpZG8sIFBvbGl0aWNvKSAlPiUNCiAgICBjb3VudChQYWxhYnJhLCBzb3J0ID0gVCkgJT4lDQogICAgIHNsaWNlX21heChvcmRlcl9ieSA9IG4sIG49IDEwKSAlPiUNCiAgICAgIGZpbHRlcihQYXJ0aWRvID09ICAiUGVyb25pc21vIikgJT4lDQogICAgZ2dwbG90KCkgKw0KICAgIGFlcyhQYWxhYnJhLCBuLCBmaWxsID0gUG9saXRpY28pICsNCiAgICBnZW9tX2NvbCgpICsNCiAgICBmYWNldF93cmFwKCJQb2xpdGljbyIsIHNjYWxlcyA9ICJmcmVlIikgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBsYWJzKHRpdGxlID0gIlBhbGFicmFzIE5lZ2F0aXZhcyBtw6FzIHVzYWRhcyIpIA0KIA0KICB0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIGZpbHRlcihDYWxpZmljYWNpb24gPT0gICJOZWdhdGl2YSIpICU+JQ0KICAgIGdyb3VwX2J5KFBhcnRpZG8sIFBvbGl0aWNvKSAlPiUNCiAgICBjb3VudChQYWxhYnJhLCBzb3J0ID0gVCkgJT4lDQogICAgIHNsaWNlX21heChvcmRlcl9ieSA9IG4sIG49IDEwKSAlPiUNCiAgICAgIGZpbHRlcihQYXJ0aWRvID09ICAib3Ryb3MgY2FuZGlkYXRvcyIpICU+JQ0KICAgIGdncGxvdCgpICsNCiAgICBhZXMoUGFsYWJyYSwgbiwgZmlsbCA9IFBvbGl0aWNvKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgZmFjZXRfd3JhcCgiUG9saXRpY28iLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicyh0aXRsZSA9ICJQYWxhYnJhcyBOZWdhdGl2YXMgbcOhcyB1c2FkYXMiKSANCiAgDQogICB0dWl0c190b2tlbnNfZW1vY2lvbmVzICU+JQ0KICAgIGZpbHRlcihDYWxpZmljYWNpb24gPT0gICJOZWdhdGl2YSIpICU+JQ0KICAgIGdyb3VwX2J5KFBhcnRpZG8sIFBvbGl0aWNvKSAlPiUNCiAgICBjb3VudChQYWxhYnJhLCBzb3J0ID0gVCkgJT4lDQogICAgIHNsaWNlX21heChvcmRlcl9ieSA9IG4sIG49IDEwKSAlPiUNCiAgICAgIGZpbHRlcihQYXJ0aWRvID09ICAiY3VlbnRhIHBhcnRpZGFyaWEiKSAlPiUNCiAgICBnZ3Bsb3QoKSArDQogICAgYWVzKFBhbGFicmEsIG4sIGZpbGwgPSBQb2xpdGljbykgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGZhY2V0X3dyYXAoIlBvbGl0aWNvIiwgc2NhbGVzID0gImZyZWUiKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGxhYnModGl0bGUgPSAiUGFsYWJyYXMgTmVnYXRpdmFzIG3DoXMgdXNhZGFzIikgDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gIDE3LSBGZWVsaW5ncyBpbiB0aGUgdHdlZXQgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KDQpVc2luZyB0aGUgYWZpbm4gZGljdGlvbmFyeSBwdW5jdHVhdGlvbiBhZ2Fpbiwgd2UgcmVqb2luIHRoZSB3b3JkcyB0byB0aGUgdHdlZXRzIGFuZCBhdmVyYWdlZCB0aGUgcG9pbnRzIG9mIGFsbCB0aGUgd29yZHMsIG1vdmluZyBmcm9tIHRoZSB1bml0IHdvcmQgdmFsdWUgdG8gYSB1bml0IHZhbHVlIGZvciBlYWNoIHR3ZWV0IHBvc3RlZC4NCg0KICAtICpNb3N0IHR3ZWV0cyB3ZXJlIG5ldXRyYWwuKg0KICANCiAgLSAqVGhlIG1vc3QgcG9zaXRpdmUgaW4gdGhpcyBjb3Vyc2Ugd2VyZSBNLiBNYWNyaSwgQS4gRmVybmFuZGV6IGFuZCBSLiBMYXZhZ25hLioNCiAgDQogIC0gKlRoZSBtb3N0IG5lZ2F0aXZlIHdlcmUgTi4gRGVsIENhw7FvIGFuZCB0aGUgb2ZmaWNpYWwgUFJPIGFjY291bnQuKg0KDQoNCmBgYHtyfQ0KVHdlZXRzX0RGIDwtDQogIHR1aXRzX3Rva2Vuc19lbW9jaW9uZXMgJT4lDQogIGdyb3VwX2J5KHN0YXR1c19pZCkgJT4lDQogIHN1bW1hcmlzZShQdW50dWFjaW9uX3R3ZWV0LnggPSBtZWFuKFB1bnR1YWNpb24pKSAlPiUNCiAgbGVmdF9qb2luKFR3ZWV0c19ERiwgLiwgYnkgPSAic3RhdHVzX2lkIikNCg0KDQpUd2VldHNfREYgPC0gIFR3ZWV0c19ERiAlPiUNCiAgbXV0YXRlKFB1bnR1YWNpb25fdHdlZXQueF9sZXRyYSA9IGlmZWxzZShpcy5uYShQdW50dWFjaW9uX3R3ZWV0LngpLCAiTmV1dHJhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShQdW50dWFjaW9uX3R3ZWV0LnggPiAwLCAiUG9zaXRpdmEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShQdW50dWFjaW9uX3R3ZWV0LnggPT0gMCwgIk5ldXRyYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5lZ2F0aXZhIikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICkgICAgICANCikNCg0KVHdlZXRzX0RGICU+JQ0KICBjb3VudChQb2xpdGljbywgUGFydGlkbywgUHVudHVhY2lvbl90d2VldC54X2xldHJhKSAlPiUNCiAgZ3JvdXBfYnkoUG9saXRpY28pICU+JQ0KICBtdXRhdGUoUHJvcG9yY2lvbiA9IG4gLyBzdW0obikpICU+JQ0KZ2dwbG90KCkgKw0KICBhZXMoUG9saXRpY28sIFByb3BvcmNpb24sIGZpbGwgPSBQdW50dWFjaW9uX3R3ZWV0LnhfbGV0cmEpICsNCiAgZ2VvbV9jb2woKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdCgpKSArDQogICAgICBmYWNldF93cmFwKCJQYXJ0aWRvIiwgc2NhbGVzID0gImZyZWUiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQ0KDQoNCmBgYA0KDQoNCg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAxOC0gRmVlbGluZ3MgaW4gdGhlIFBSTyB2cyBQZXJvbmlzbW8gdHdlZXQgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KDQpXZSB0YWtlIHRoZSA0IG1lbWJlcnMgdGhhdCB3ZSBoYXZlIGFscmVhZHkgYW5hbHl6ZWQgZnJvbSBlYWNoIG9mIHRoZSBwYXJ0aWVzICooUFJPIGFuZCBUT0RPUykqLCBhbmQgd2UgdW5pdGUgaXQgaW4gYSBzaW5nbGUgZ3JhcGggcGVyIHBhcnR5LCB3ZSBzZWUgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIGlzIHNvbWV0aGluZyBzaW1pbGFyLCBhbHRob3VnaCBQZXJvbmlzbSBoYWQgYSBsaXR0bGUgbW9yZSBwb3NpdGl2ZSB0d2VldHMgYW5kIGZld2VyIG5lZ2F0aXZlIHR3ZWV0cywgYnV0IG5vdCBhdCBzaWduaWZpY2FudCBsZXZlbHMuDQoNCg0KDQpgYGB7cn0NClR3ZWV0c19ERiAlPiUNCiAgY291bnQoUGFydGlkbywgUHVudHVhY2lvbl90d2VldC54X2xldHJhKSAlPiUNCiAgZ3JvdXBfYnkoUGFydGlkbykgJT4lDQogIGZpbHRlcihQYXJ0aWRvID09ICJQUk8iIHxQYXJ0aWRvID09ICJQZXJvbmlzbW8iKSU+JQ0KICBtdXRhdGUoUHJvcG9yY2lvbiA9IG4gLyBzdW0obikpICU+JQ0KZ2dwbG90KCkgKw0KICBhZXMoUGFydGlkbywgUHJvcG9yY2lvbiwgZmlsbCA9IFB1bnR1YWNpb25fdHdlZXQueF9sZXRyYSkgKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCkpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gIDE5LSBGZWVsaW5nIG1vbnRoIGJ5IG1vbnRoIDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KVGhlIGlkZWEgaXMgdG8gYW5hbHl6ZSBpZiB0aGVyZSBhcmUgZmx1Y3R1YXRpb25zIGluIHdoYXQgdGhleSBoYXZlIGJlZW4gdHdlZXRpbmcgb3ZlciB0aW1lIGFuZCB0aGVpciBmZWVsaW5ncy4NCg0KICAtIEluIHRoZSAqKlBSTyoqIHRoZXJlIHdlcmUgbm8gYmlnIGNoYW5nZXMsIHRoZSBsYXN0IHR3ZWV0cyBvZiBCdWxscmljaCBhcmUgbW9yZSBwb3NpdGl2ZS4NCiAgDQogIC0gQW1vbmcgdGhlIG90aGVyIGNhbmRpZGF0ZXMgKipOaWNvbGFzIERlbCBDYcOxbyoqIGlzIGFsd2F5cyBuZWdhdGl2ZSwgYnV0IGhhcyBiZWVuIGxlc3MgbmVnYXRpdmUgbGF0ZWx5Lg0KICANCiAgLSBBbW9uZyB0aGUgKipGcmVudGUgZGUgVG9kb3MqKiB0aGVyZSBpcyBhIGxvdCBvZiBmbHVjdHVhdGlvbiwgdGhlIFByZXNpZGVudCBzZWVtcyB0byBiZSBvbiBhIHBhdGggdG93YXJkcyBuZWdhdGl2aXR5Lg0KICANCg0KYGBge3J9DQpUd2VldHNfREYkUHVudHVhY2lvbl90d2VldC54ID0gaWZlbHNlKGlzLm5hKFR3ZWV0c19ERiRQdW50dWFjaW9uX3R3ZWV0LngpLCAwLCBUd2VldHNfREYkUHVudHVhY2lvbl90d2VldC54KQ0KDQpUd2VldHNfREYgJT4lDQpncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgbWVzKSAlPiUNCiAgZmlsdGVyKFBhcnRpZG8gPT0gIlBSTyIpJT4lDQogIHN1bW1hcmlzZShzZW50aW1pZW50byA9IG1lYW4oUHVudHVhY2lvbl90d2VldC54KSkgJT4lDQpnZ3Bsb3QoKSArDQogIGFlcyhtZXMsIHNlbnRpbWllbnRvLCBjb2xvciA9IFBvbGl0aWNvKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGFscGhhID0gLjM1KSArDQogIGdlb21fbGluZSgpICsNCiAgZmFjZXRfZ3JpZChQb2xpdGljb34uKSArDQogIHRlbWExICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQpUd2VldHNfREYgJT4lDQpncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgbWVzKSAlPiUNCiAgZmlsdGVyKFBhcnRpZG8gPT0gIm90cm9zIGNhbmRpZGF0b3MiKSU+JQ0KICBzdW1tYXJpc2Uoc2VudGltaWVudG8gPSBtZWFuKFB1bnR1YWNpb25fdHdlZXQueCkpICU+JQ0KZ2dwbG90KCkgKw0KICBhZXMobWVzLCBzZW50aW1pZW50bywgY29sb3IgPSBQb2xpdGljbykgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBhbHBoYSA9IC4zNSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGZhY2V0X2dyaWQoUG9saXRpY29+LikgKw0KICB0ZW1hMSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KVHdlZXRzX0RGICU+JQ0KZ3JvdXBfYnkoUG9saXRpY28sIFBhcnRpZG8sIG1lcykgJT4lDQogIGZpbHRlcihQYXJ0aWRvID09ICJQZXJvbmlzbW8iKSU+JQ0KICBzdW1tYXJpc2Uoc2VudGltaWVudG8gPSBtZWFuKFB1bnR1YWNpb25fdHdlZXQueCkpICU+JQ0KZ2dwbG90KCkgKw0KICBhZXMobWVzLCBzZW50aW1pZW50bywgY29sb3IgPSBQb2xpdGljbykgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBhbHBoYSA9IC4zNSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGZhY2V0X2dyaWQoUG9saXRpY29+LikgKw0KICB0ZW1hMSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KVHdlZXRzX0RGICU+JQ0KZ3JvdXBfYnkoUG9saXRpY28sIFBhcnRpZG8sIG1lcykgJT4lDQogIGZpbHRlcihQYXJ0aWRvID09ICJjdWVudGEgcGFydGlkYXJpYSIpJT4lDQogIHN1bW1hcmlzZShzZW50aW1pZW50byA9IG1lYW4oUHVudHVhY2lvbl90d2VldC54KSkgJT4lDQpnZ3Bsb3QoKSArDQogIGFlcyhtZXMsIHNlbnRpbWllbnRvLCBjb2xvciA9IFBvbGl0aWNvKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGFscGhhID0gLjM1KSArDQogIGdlb21fbGluZSgpICsNCiAgZmFjZXRfZ3JpZChQb2xpdGljb34uKSArDQogIHRlbWExICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+ICAyMC0gRmVlbGluZyBCb3hwbG90IDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KDQpUaGUgZGlzdHJpYnV0aW9uIG9mIGZlZWxpbmdzIGFtb25nIGFsbCB0aGUgdHdlZXRzLCB0aG9zZSB0aGF0IGFyZSBlbmNsb3NlZCBpbiB0aGUgYm94ZXMgYXJlIHRoZSBub3JtYWwgb25lcywgd2hpbGUgdGhlIGxvb3NlIHBvaW50cyBhcmUgaXNvbGF0ZWQgdHdlZXRzIHRvIHdoYXQgdGhleSB1c3VhbGx5IHdyaXRlLg0KDQogIC0gKkVzcGVydCBkb2VzIG5vdCBwcmVzZW50IGFueSBraW5kIG9mIHBhdHRlcm4gb2YgZmVlbGluZ3MqDQoNCg0KYGBge3J9DQpUd2VldHNfREYgJT4lDQogIGdncGxvdCgpICsNCiAgYWVzKFBvbGl0aWNvLCBQdW50dWFjaW9uX3R3ZWV0LngsIGZpbGwgPSBQb2xpdGljbykgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGNvb3JkX2ZsaXAoKSArIA0KICBsYWJzKHk9ICJTZW50aW1pZW50byIpICsNCiAgdGVtYTENCmBgYA0KDQoNCg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAyMS0gQ29ycmVsYXRpb24gYmV0d2VlbiBQUk8gdnMgUGVyb25pc21vIHR3ZWV0ZWQ8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQpJdCBpcyBzZWFyY2hlZCB0aHJvdWdoIHRoZSB3b3JkcyB0aGF0IHRoZXkgdXNlZCB3aGF0IGlzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBkaWZmZXJlbnQgcG9saXRpY2lhbnMgYW5kIHRoZWlyIHR3ZWV0cywgYW5kIHNldmVyYWwgb2JzZXJ2YXRpb25zIGNhbiBiZSBtYWRlOg0KDQogIC0gKlF1aXLDs3MgYW5kIExhcnJldGEgYXJlIHRoZSBvbmVzIHdpdGggdGhlIGhpZ2hlc3QgY29ycmVsYXRpb24sIGRlbW9uc3RyYXRpbmcgZ29vZCBtYW5hZ2VtZW50IG9mIEJ1ZW5vcyBBaXJlcyBjb21tdW5pY2F0aW9uLCB3aGVyZSBib3RoIGNvbnRpbnVlIGluIHRoZSBzYW1lIGRpcmVjdGlvbi4gKg0KDQogIC0gKk1hY3JpIGlzIHRoZSBvbmUgd2l0aCB0aGUgbG93ZXN0IGNvcnJlbGF0aW9uIHdpdGggdGhlIHJlc3Qgb2YgdGhlIHBhcnRpY2lwYW50cywgYnV0IGl0IGFsc28gbWFrZXMgc2Vuc2UgdGhhdCBoaXMgaGlnaGVzdCBsZXZlbCBvZiByZWxhdGlvbnNoaXAgaXMgd2l0aCBCdWxscmljaC4gKg0KDQogIC0gKkJldHdlZW4gS2ljaWxvZmYgYW5kIEdpbmVzLCB0aGVyZSBpcyBhbiBpbXBvcnRhbnQgcmVsYXRpb25zaGlwLCBhcyB3ZWxsIGFzIHRoZSB0d28gb2YgdGhlbSB3aXRoIHRoZWlyIHNpbWlsYXIgcG9ydGXDsW9zIChRdWlyw7NzIGFuZCBMYXJyZXRhKS4gKg0KDQogIC0gKkNyaXN0aW5hIEtpcmNobmVyIGlzIGFub3RoZXIgd2hvIGRvZXMgbm90IGhhdmUgYSBoaWdoIGxldmVsIG9mIHJlbGF0aW9uc2hpcCBpbiBoZXIgdHdlZXRzIHdpdGggb3RoZXIgcG9saXRpY2lhbnMuICoNCg0KICAtICpJdCBpcyBzdXJwcmlzaW5nIHRoYXQgb25lIG9mIHRoZSBoaWdoZXN0IGxldmVscyBvZiByZWxhdGlvbnNoaXAgaW4gdGVybXMgb2Ygd2hhdCBpcyBjb21tdW5pY2F0ZWQgaXMgYmV0d2VlbiBBbGJlcnRvIEZlcm7DoW5kZXogYW5kIFBhdHJpY2lhIEJ1bGxyaWNoLiAqDQoNCg0KDQpgYGB7cn0NCnR3ZWV0c19zcHJlYWQyIDwtIHR1aXRzX3Rva2VucyAlPiUgDQogZmlsdGVyKFBhcnRpZG8gPT0gICJQUk8iIHwgUGFydGlkbyA9PSAiUGVyb25pc21vIiklPiUgDQogIGdyb3VwX2J5KFBvbGl0aWNvLCBQYWxhYnJhKSAlPiUgDQogIGNvdW50KFBhbGFicmEpICU+JQ0KICAgICAgc3ByZWFkKGtleSA9IFBvbGl0aWNvLCB2YWx1ZSA9IG4sIGZpbGwgPSBOQSwgZHJvcCA9IFRSVUUpDQp0d2VldHNfc3ByZWFkMltpcy5uYSh0d2VldHNfc3ByZWFkMildIDwtIDANCg0KbmFtZXModHdlZXRzX3NwcmVhZDIpIDwtIGMoIlBhbGFicmEiLCAiQS5GZXJuYW5kZXoiLCAiQS5LaWNpbGxvZiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiQy5LaXJjaG5lciIsICJGLlF1aXJvcyIsICJHaW5lcy5HRyIsIkguTGFycmV0YSIsICJNLk1hY3JpIiwgIlAuQnVsbHJpY2giICkNCg0KbWV0aG9kIDwtICJwZWFyc29uIg0KbV9jb3IgPC0gbWF0cml4KG5yb3cgPSA4LCBuY29sID0gOCkNCmZvciAoaSBpbiAxOmRpbShtX2NvcilbMV0pIHsNCiAgICAgIGZvciAoaiBpbiAxOmRpbShtX2NvcilbMl0pIHsNCiAgICAgICAgICAgIGZvcm0gPC0gYXMuZm9ybXVsYShwYXN0ZSgifiIsIG5hbWVzKHR3ZWV0c19zcHJlYWQyKVtpKzFdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIisiLCBuYW1lcyh0d2VldHNfc3ByZWFkMilbaisxXSkpDQogICAgICAgICAgICBpZihpIT1qKXsNCiAgICAgICAgICAgICAgICAgIG1fY29yW2ksal0gPC0gY29yLnRlc3QoZm9ybSwgbWV0aG9kID0gbWV0aG9kLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHR3ZWV0c19zcHJlYWQyKSRlc3RpbWF0ZQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYoaT09ail7bV9jb3JbaSxqXSA8LSAxfQ0KICAgICAgfQ0KfQ0KY29sbmFtZXMobV9jb3IpIDwtIG5hbWVzKHR3ZWV0c19zcHJlYWQyKVsyOjldDQpyb3duYW1lcyhtX2NvcikgPC0gbmFtZXModHdlZXRzX3NwcmVhZDIpWzI6OV0NCmNvcnJwbG90KG1fY29yLCBtZXRob2Q9ImNvbG9yIiwgdHlwZT0idXBwZXIiLCBvcmRlcj0iaGNsdXN0IiwgDQogICAgICAgICBhZGRDb2VmLmNvbCA9ICJibGFjayIsIHRsLmNvbD0iYmxhY2siLCB0bC5zcnQ9NDUsDQogICAgICAgICBzaWcubGV2ZWwgPSAwLjAxLCBpbnNpZyA9ICJibGFuayIsIGRpYWc9RkFMU0UpDQoNCmBgYA0KDQoNCg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAyMi0gQ29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdHdlZXRlZCBjYW5kaWRhdGVzIGZvciBwcmVzaWRlbnQuIDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KLSBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gd2hhdCB0aGUgY2FuZGlkYXRlcyB3cml0ZSBoYXMgYSBjbHVzdGVyIHRoYXQgc3RhbmRzIG91dCBhYm92ZSB0aGUgcmVzdCwgd2hpY2ggaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEVzcGVydCwgR8OzbWV6IENlbnR1cmnDs24gYW5kIEFsYmVydG8gRmVybsOhbmRlei4NCg0KLSBOaWNvbGFzIERlbCBDYcOxbyBoYXMgYSBoaWdoIGxldmVsIG9mIHJlbGF0aW9uc2hpcCB3aXRoIEfDs21leiBDZW50dXJpw7NuLCBhbmQgdG8gYSBtZWRpdW0gZXh0ZW50IHdpdGggQWxiZXJ0byBGZXJuw6FuZGV6IGFuZCBFc3BlcnQuDQoNCi0gTGF2YWduYSBhbmQgTWFjcmkgZG8gbm90IHByZXNlbnQgYSBncmVhdCBjb3JyZWxhdGlvbiB3aXRoIHRoZSByZXN0IG9mIHRoZSBwb2xpdGljaWFucy4NCg0KDQpgYGB7cn0NCnR3ZWV0c19zcHJlYWQyIDwtIHR1aXRzX3Rva2VucyAlPiUgDQogIGZpbHRlcihQYXJ0aWRvID09ICAib3Ryb3MgY2FuZGlkYXRvcyIgfCBQb2xpdGljbyA9PSAiQS5GZXJuYW5kZXoifCBQb2xpdGljbyA9PSAiTS5NYWNyaSIpJT4lIA0KICBncm91cF9ieShQb2xpdGljbywgUGFsYWJyYSkgJT4lIA0KICBjb3VudChQYWxhYnJhKSAlPiUNCiAgICAgIHNwcmVhZChrZXkgPSBQb2xpdGljbywgdmFsdWUgPSBuLCBmaWxsID0gTkEsIGRyb3AgPSBUUlVFKQ0KdHdlZXRzX3NwcmVhZDJbaXMubmEodHdlZXRzX3NwcmVhZDIpXSA8LSAwDQoNCm5hbWVzKHR3ZWV0c19zcHJlYWQyKSA8LSBjKCJQYWxhYnJhIiwgIkEuRmVybmFuZGV6IiwgIkouRXNwZXJ0IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICJHb21lekNlbnR1cmlvbiIsICJNLk1hY3JpIiwgIk4uRGVsQ2HDsW8iLCJSLkxhdmFnbmEiKQ0KDQptZXRob2QgPC0gInBlYXJzb24iDQptX2NvciA8LSBtYXRyaXgobnJvdyA9IDYsIG5jb2wgPSA2KQ0KZm9yIChpIGluIDE6ZGltKG1fY29yKVsxXSkgew0KICAgICAgZm9yIChqIGluIDE6ZGltKG1fY29yKVsyXSkgew0KICAgICAgICAgICAgZm9ybSA8LSBhcy5mb3JtdWxhKHBhc3RlKCJ+IiwgbmFtZXModHdlZXRzX3NwcmVhZDIpW2krMV0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiKyIsIG5hbWVzKHR3ZWV0c19zcHJlYWQyKVtqKzFdKSkNCiAgICAgICAgICAgIGlmKGkhPWopew0KICAgICAgICAgICAgICAgICAgbV9jb3JbaSxqXSA8LSBjb3IudGVzdChmb3JtLCBtZXRob2QgPSBtZXRob2QsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gdHdlZXRzX3NwcmVhZDIpJGVzdGltYXRlDQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZihpPT1qKXttX2NvcltpLGpdIDwtIDF9DQogICAgICB9DQp9DQpjb2xuYW1lcyhtX2NvcikgPC0gbmFtZXModHdlZXRzX3NwcmVhZDIpWzI6N10NCnJvd25hbWVzKG1fY29yKSA8LSBuYW1lcyh0d2VldHNfc3ByZWFkMilbMjo3XQ0KY29ycnBsb3QobV9jb3IsIG1ldGhvZD0iY29sb3IiLCB0eXBlPSJ1cHBlciIsIG9yZGVyPSJoY2x1c3QiLCANCiAgICAgICAgIGFkZENvZWYuY29sID0gImJsYWNrIiwgdGwuY29sPSJibGFjayIsIHRsLnNydD00NSwNCiAgICAgICAgIHNpZy5sZXZlbCA9IDAuMDEsIGluc2lnID0gImJsYW5rIiwgZGlhZz1GQUxTRSkNCmBgYA0KDQoNCg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAyMy0gQ29ycmVsYXRpb24gYmV0d2VlbiB3aGF0IHdhcyB0d2VldGVkIGJldHdlZW4gcGFydHkgYWNjb3VudHM8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQoNClRoaXMgY2FuIGJlIGFuIGludGVyZXN0aW5nIGFuYWx5c2lzLCBzaW5jZSB0aGUgbnVtYmVyIG9mIHR3ZWV0cyBpcyBzaWduaWZpY2FudCBmb3IgZXZlcnlvbmUuDQoNCi0gU3VycHJpc2luZ2x5LCB0aGUgbWF4aW11bSBsZXZlbCBvZiByZWxhdGlvbnNoaXAgb2NjdXJzIGJldHdlZW4gdGhlIFVDUiBhbmQgVE9ET1MsIHR3byBwYXJ0aWVzIHRoYXQgdG9kYXkgYXJlIHByZXNlbnRlZCBhcyBvcHBvc2l0ZQ0KDQotIFRoZSBoaWdoIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBQUk8gYW5kIHRoZSBVQ1IgbWFrZXMgbW9yZSBzZW5zZS4NCg0KLSBUaGUgR0VOIHNlZW1zIHRvIGJlIHRoZSBwYXJ0eSB0aGF0IHdyaXRlcyBtb3JlIGRpZmZlcmVudGx5IGZyb20gdGhlIHJlc3QuDQoNCi0gSG93ZXZlciwgd2UgY2FuIG5vdGUgdGhhdCwgdW5saWtlIHRoZSBpbmRpdmlkdWFsIGFjY291bnRzLCB0aGUgc3VwcG9ydGVycyBoYXZlIG1vcmUgcmVsYXRpb25zaGlwLCBkdWUgdG8gdGhlaXIgbW9yZSBuZXV0cmFsIGxhbmd1YWdlIGFuZCBvcmdhbmljIGNvbW11bmljYXRpb24uDQoNCg0KYGBge3J9DQp0d2VldHNfc3ByZWFkMiA8LSB0dWl0c190b2tlbnMgJT4lIA0KICBmaWx0ZXIoUGFydGlkbyA9PSAgImN1ZW50YSBwYXJ0aWRhcmlhIiklPiUgDQogIGdyb3VwX2J5KFBvbGl0aWNvLCBQYWxhYnJhKSAlPiUgDQogIGNvdW50KFBhbGFicmEpICU+JQ0KICAgICAgc3ByZWFkKGtleSA9IFBvbGl0aWNvLCB2YWx1ZSA9IG4sIGZpbGwgPSBOQSwgZHJvcCA9IFRSVUUpDQp0d2VldHNfc3ByZWFkMltpcy5uYSh0d2VldHNfc3ByZWFkMildIDwtIDANCg0KbmFtZXModHdlZXRzX3NwcmVhZDIpIDwtIGMoIlBhbGFicmEiLCAiR0VOIiwgIlBSTyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVE9ET1MiLCAiVUNSIikNCg0KbWV0aG9kIDwtICJwZWFyc29uIg0KbV9jb3IgPC0gbWF0cml4KG5yb3cgPSA0LCBuY29sID0gNCkNCmZvciAoaSBpbiAxOmRpbShtX2NvcilbMV0pIHsNCiAgICAgIGZvciAoaiBpbiAxOmRpbShtX2NvcilbMl0pIHsNCiAgICAgICAgICAgIGZvcm0gPC0gYXMuZm9ybXVsYShwYXN0ZSgifiIsIG5hbWVzKHR3ZWV0c19zcHJlYWQyKVtpKzFdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIisiLCBuYW1lcyh0d2VldHNfc3ByZWFkMilbaisxXSkpDQogICAgICAgICAgICBpZihpIT1qKXsNCiAgICAgICAgICAgICAgICAgIG1fY29yW2ksal0gPC0gY29yLnRlc3QoZm9ybSwgbWV0aG9kID0gbWV0aG9kLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHR3ZWV0c19zcHJlYWQyKSRlc3RpbWF0ZQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYoaT09ail7bV9jb3JbaSxqXSA8LSAxfQ0KICAgICAgfQ0KfQ0KY29sbmFtZXMobV9jb3IpIDwtIG5hbWVzKHR3ZWV0c19zcHJlYWQyKVsyOjVdDQpyb3duYW1lcyhtX2NvcikgPC0gbmFtZXModHdlZXRzX3NwcmVhZDIpWzI6NV0NCmNvcnJwbG90KG1fY29yLCBtZXRob2Q9ImNvbG9yIiwgdHlwZT0idXBwZXIiLCBvcmRlcj0iaGNsdXN0IiwgDQogICAgICAgICBhZGRDb2VmLmNvbCA9ICJibGFjayIsIHRsLmNvbD0iYmxhY2siLCB0bC5zcnQ9NDUsDQogICAgICAgICBzaWcubGV2ZWwgPSAwLjAxLCBpbnNpZyA9ICJibGFuayIsIGRpYWc9RkFMU0UpDQpgYGANCg0KDQoNCg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAyNC0gTWFjcmkgdnMgRmVybmFuZGV6IHdvcmQgdXNlIGNvbXBhcmlzb24gPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KDQpUaGUgaWRlYSBvZiB0aGlzIGdyYXBoIGlzIHRvIHNob3cgd2hpY2ggd29yZHMgYXJlIHRoZSBtb3N0IGRpZmZlcmVudCBpbiB0aGVpciB1c2UsIGluIHRoaXMgY2FzZSBiZXR3ZWVuICpNYXVyaWNpbyBNYWNyaSogYW5kICpBbGJlcnRvIEZlcm7DoW5kZXoqDQoNCg0KDQpgYGB7cn0NCg0KIyBQaXZvdGFqZSB5IGRlc3Bpdm90YWplDQp0d2VldHNfdW5waXZvdCA8LSB0dWl0c190b2tlbnMgJT4lIGdyb3VwX2J5KFBvbGl0aWNvLCBQYWxhYnJhKSAlPiUNCiAgICAgIGNvdW50KFBhbGFicmEpICU+JQ0KICAgICAgc3ByZWFkKGtleSA9IFBvbGl0aWNvLCB2YWx1ZSA9IG4sIGZpbGwgPSAwLCBkcm9wID0gVFJVRSkgJT4lIA0KICAgICAgZ2F0aGVyKGtleSA9ICJQb2xpdGljbyIsIHZhbHVlID0gIm4iLCAtUGFsYWJyYSkNCg0KDQogICAgICAgICAgICAgICAgICAjIFNlbGVjY2nDs24gZGUgbG9zIGF1dG9yZXMNCiAgICAgICAgICAgICAgICAgIHR3ZWV0c191bnBpdm90MiA8LSB0d2VldHNfdW5waXZvdCAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoUG9saXRpY28gJWluJSBjKCJNLk1hY3JpIiwgIkEuRmVybmFuZGV6IikpDQogICAgICAgICAgICAgICAgICAjIFNlIGHDsWFkZSBlbCB0b3RhbCBkZSBwYWxhYnJhcyBkZSBjYWRhIGF1dG9yDQogICAgICAgICAgICAgICAgICB0d2VldHNfdW5waXZvdDIgPC0gdHdlZXRzX3VucGl2b3QyICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgbGVmdF9qb2luKFR3ZWV0c19ERiAlPiUgZ3JvdXBfYnkoUG9saXRpY28pICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShOID0gbigpKSwgYnkgPSAiUG9saXRpY28iKQ0KICAgICAgICAgICAgICAgICAgIyBDw6FsY3VsbyBkZSBvZGRzIHkgbG9nIG9mIG9kZHMgZGUgY2FkYSBwYWxhYnJhDQogICAgICAgICAgICAgICAgICB0d2VldHNfbG9nT2RkcyA8LSB0d2VldHNfdW5waXZvdDIgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKG9kZHMgPSAobiArIDEpIC8gKE4gKyAxKSkgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoUG9saXRpY28sIFBhbGFicmEsIG9kZHMpICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgIHNwcmVhZChrZXkgPSBQb2xpdGljbywgdmFsdWUgPSBvZGRzKQ0KICAgICAgICAgICAgICAgICAgdHdlZXRzX2xvZ09kZHNbLDRdIDwtIGxvZyh0d2VldHNfbG9nT2Rkc1ssMl0vdHdlZXRzX2xvZ09kZHNbLDNdKQ0KICAgICAgICAgICAgICAgICAgbmFtZXModHdlZXRzX2xvZ09kZHMpWzRdIDwtICJsb2dfb2RkcyINCiAgICAgICAgICAgICAgICAgIHR3ZWV0c19sb2dPZGRzWyw1XSA8LSBhYnModHdlZXRzX2xvZ09kZHMkbG9nX29kZHMpDQogICAgICAgICAgICAgICAgICBuYW1lcyh0d2VldHNfbG9nT2RkcylbNV0gPC0gImFic19sb2dfb2RkcyINCiAgICAgICAgICAgICAgICAgIHR3ZWV0c19sb2dPZGRzIDwtIHR3ZWV0c19sb2dPZGRzICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGF1dG9yX2ZyZWN1ZW50ZSA9IGlmX2Vsc2UobG9nX29kZHMgPiAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXModHdlZXRzX2xvZ09kZHMpWzJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXModHdlZXRzX2xvZ09kZHMpWzNdKSkNCg0KRGlmZXJlbmNpYV9BRiA8LSB0d2VldHNfbG9nT2RkcyAlPiUgDQogIGFycmFuZ2UoLWFic19sb2dfb2RkcywgYnlncm91cCA9IEZBTFNFKSU+JSANCiAgZmlsdGVyKGF1dG9yX2ZyZWN1ZW50ZSA9PSAiQS5GZXJuYW5kZXoiKSU+JSANCiAgaGVhZCgxNSkNCg0KRGlmZXJlbmNpYV9NTSA8LSB0d2VldHNfbG9nT2RkcyAlPiUgDQogIGFycmFuZ2UobG9nX29kZHMsIGJ5Z3JvdXAgPSBGQUxTRSklPiUgDQogIGZpbHRlcihhdXRvcl9mcmVjdWVudGUgPT0gIk0uTWFjcmkiKSU+JSANCiAgaGVhZCgxNSkNCg0KRGlmZXJlbmNpYV9BRl9NTSA8LSByYmluZChEaWZlcmVuY2lhX0FGLERpZmVyZW5jaWFfTU0pDQoNCkRpZmVyZW5jaWFfQUZfTU0lPiUgDQogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihQYWxhYnJhLCBsb2dfb2RkcyksIHk9IGxvZ19vZGRzLCBmaWxsID0gYXV0b3JfZnJlY3VlbnRlKSkgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGxhYnMoeCA9ICItcGFsYWJyYSIsIHkgPSAiVXNvIiwgdGl0bGUgPSAiRmVybmFuZGV6IHZzIE1hY3JpIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICB0ZW1hMg0KDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gMjUtIExhcnJldGEgdnMgS2ljaWxsb2Ygd29yZCB1c2UgY29tcGFyaXNvbjwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KVGhlIGlkZWEgb2YgdGhpcyBncmFwaCBpcyB0byBzaG93IHdoaWNoIHdvcmRzIGFyZSB0aGUgbW9zdCBkaWZmZXJlbnQgaW4gdGhlaXIgdXNlLCBpbiB0aGlzIGNhc2UgYmV0d2VlbiAqSG9yYWNpbyBMYXJyZXRhKiBhbmQgKkF4ZWwgS2ljaWxsb2YqDQoNCg0KDQpgYGB7cn0NCg0KDQojIFBpdm90YWplIHkgZGVzcGl2b3RhamUNCnR3ZWV0c191bnBpdm90IDwtIHR1aXRzX3Rva2VucyAlPiUgZ3JvdXBfYnkoUG9saXRpY28sIFBhbGFicmEpICU+JQ0KICAgICAgY291bnQoUGFsYWJyYSkgJT4lDQogICAgICBzcHJlYWQoa2V5ID0gUG9saXRpY28sIHZhbHVlID0gbiwgZmlsbCA9IDAsIGRyb3AgPSBUUlVFKSAlPiUgDQogICAgICBnYXRoZXIoa2V5ID0gIlBvbGl0aWNvIiwgdmFsdWUgPSAibiIsIC1QYWxhYnJhKQ0KDQoNCiAgICAgICAgICAgICAgICAgICMgU2VsZWNjacOzbiBkZSBsb3MgYXV0b3Jlcw0KICAgICAgICAgICAgICAgICAgdHdlZXRzX3VucGl2b3QyIDwtIHR3ZWV0c191bnBpdm90ICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihQb2xpdGljbyAlaW4lIGMoIkguTGFycmV0YSIsICJBLktpY2lsbG9mIikpDQogICAgICAgICAgICAgICAgICAjIFNlIGHDsWFkZSBlbCB0b3RhbCBkZSBwYWxhYnJhcyBkZSBjYWRhIGF1dG9yDQogICAgICAgICAgICAgICAgICB0d2VldHNfdW5waXZvdDIgPC0gdHdlZXRzX3VucGl2b3QyICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgbGVmdF9qb2luKFR3ZWV0c19ERiAlPiUgZ3JvdXBfYnkoUG9saXRpY28pICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShOID0gbigpKSwgYnkgPSAiUG9saXRpY28iKQ0KICAgICAgICAgICAgICAgICAgIyBDw6FsY3VsbyBkZSBvZGRzIHkgbG9nIG9mIG9kZHMgZGUgY2FkYSBwYWxhYnJhDQogICAgICAgICAgICAgICAgICB0d2VldHNfbG9nT2RkcyA8LSB0d2VldHNfdW5waXZvdDIgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKG9kZHMgPSAobiArIDEpIC8gKE4gKyAxKSkgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoUG9saXRpY28sIFBhbGFicmEsIG9kZHMpICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgIHNwcmVhZChrZXkgPSBQb2xpdGljbywgdmFsdWUgPSBvZGRzKSANCiAgICAgICAgICAgICAgICAgIHR3ZWV0c19sb2dPZGRzWyw0XSA8LSBsb2codHdlZXRzX2xvZ09kZHNbLDJdL3R3ZWV0c19sb2dPZGRzWywzXSkNCiAgICAgICAgICAgICAgICAgIG5hbWVzKHR3ZWV0c19sb2dPZGRzKVs0XSA8LSAibG9nX29kZHMiDQogICAgICAgICAgICAgICAgICB0d2VldHNfbG9nT2Rkc1ssNV0gPC0gYWJzKHR3ZWV0c19sb2dPZGRzJGxvZ19vZGRzKQ0KICAgICAgICAgICAgICAgICAgbmFtZXModHdlZXRzX2xvZ09kZHMpWzVdIDwtICJhYnNfbG9nX29kZHMiDQogICAgICAgICAgICAgICAgICB0d2VldHNfbG9nT2RkcyA8LSB0d2VldHNfbG9nT2RkcyAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShhdXRvcl9mcmVjdWVudGUgPSBpZl9lbHNlKGxvZ19vZGRzID4gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzKHR3ZWV0c19sb2dPZGRzKVsyXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzKHR3ZWV0c19sb2dPZGRzKVszXSkpDQoNCkRpZmVyZW5jaWFfQUsgPC0gdHdlZXRzX2xvZ09kZHMgJT4lIA0KICBhcnJhbmdlKC1sb2dfb2RkcywgYnlncm91cCA9IEZBTFNFKSU+JSANCiAgZmlsdGVyKGF1dG9yX2ZyZWN1ZW50ZSA9PSAiQS5LaWNpbGxvZiIpJT4lIA0KICBoZWFkKDE1KQ0KDQpEaWZlcmVuY2lhX0hMIDwtIHR3ZWV0c19sb2dPZGRzICU+JSANCiAgYXJyYW5nZShhYnNfbG9nX29kZHMsIGJ5Z3JvdXAgPSBGQUxTRSklPiUgDQogIGZpbHRlcihhdXRvcl9mcmVjdWVudGUgPT0gIkguTGFycmV0YSIpJT4lIA0KICB0YWlsKDE1KQ0KDQpEaWZlcmVuY2lhX0FLX0hMIDwtIHJiaW5kKERpZmVyZW5jaWFfQUssRGlmZXJlbmNpYV9ITCkNCg0KRGlmZXJlbmNpYV9BS19ITCU+JSANCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFBhbGFicmEsIGxvZ19vZGRzKSwgeT0gbG9nX29kZHMsIGZpbGwgPSBhdXRvcl9mcmVjdWVudGUpKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgbGFicyh4ID0gIi1wYWxhYnJhIiwgeSA9ICJVc28iLCB0aXRsZSA9ICJLaWNpbGxvZiB2cyBMYXJyZXRhIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICB0ZW1hMg0KDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gMjYtR2luZXMgdnMgUXVpcsOzcyB3b3JkIHVzZSBjb21wYXJpc29uIDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KVGhlIGlkZWEgb2YgdGhpcyBncmFwaCBpcyB0byBzaG93IHdoaWNoIHdvcmRzIGFyZSB0aGUgbW9zdCBkaWZmZXJlbnQgaW4gdGhlaXIgdXNlLCBpbiB0aGlzIGNhc2UgYmV0d2VlbiAqR2luZXMgR29uemFsZXoqIGFuZCAqRmVybsOhbiBRdWlyw7NzKg0KDQoNCmBgYHtyfQ0KdHdlZXRzX3VucGl2b3QgPC0gdHVpdHNfdG9rZW5zICU+JSBncm91cF9ieShQb2xpdGljbywgUGFsYWJyYSkgJT4lDQogICAgICBjb3VudChQYWxhYnJhKSAlPiUNCiAgICAgIHNwcmVhZChrZXkgPSBQb2xpdGljbywgdmFsdWUgPSBuLCBmaWxsID0gMCwgZHJvcCA9IFRSVUUpICU+JSANCiAgICAgIGdhdGhlcihrZXkgPSAiUG9saXRpY28iLCB2YWx1ZSA9ICJuIiwgLVBhbGFicmEpDQoNCg0KICAgICAgICAgICAgICAgICAgIyBTZWxlY2Npw7NuIGRlIGxvcyBhdXRvcmVzDQogICAgICAgICAgICAgICAgICB0d2VldHNfdW5waXZvdDIgPC0gdHdlZXRzX3VucGl2b3QgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKFBvbGl0aWNvICVpbiUgYygiR2luZXMuR0ciLCAiRi5RdWlyb3MiKSkNCiAgICAgICAgICAgICAgICAgICMgU2UgYcOxYWRlIGVsIHRvdGFsIGRlIHBhbGFicmFzIGRlIGNhZGEgYXV0b3INCiAgICAgICAgICAgICAgICAgIHR3ZWV0c191bnBpdm90MiA8LSB0d2VldHNfdW5waXZvdDIgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICBsZWZ0X2pvaW4oVHdlZXRzX0RGICU+JSBncm91cF9ieShQb2xpdGljbykgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKE4gPSBuKCkpLCBieSA9ICJQb2xpdGljbyIpDQogICAgICAgICAgICAgICAgICAjIEPDoWxjdWxvIGRlIG9kZHMgeSBsb2cgb2Ygb2RkcyBkZSBjYWRhIHBhbGFicmENCiAgICAgICAgICAgICAgICAgIHR3ZWV0c19sb2dPZGRzIDwtIHR3ZWV0c191bnBpdm90MiAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUob2RkcyA9IChuICsgMSkgLyAoTiArIDEpKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChQb2xpdGljbywgUGFsYWJyYSwgb2RkcykgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgc3ByZWFkKGtleSA9IFBvbGl0aWNvLCB2YWx1ZSA9IG9kZHMpIA0KICAgICAgICAgICAgICAgICAgdHdlZXRzX2xvZ09kZHNbLDRdIDwtIGxvZyh0d2VldHNfbG9nT2Rkc1ssMl0vdHdlZXRzX2xvZ09kZHNbLDNdKQ0KICAgICAgICAgICAgICAgICAgbmFtZXModHdlZXRzX2xvZ09kZHMpWzRdIDwtICJsb2dfb2RkcyINCiAgICAgICAgICAgICAgICAgIHR3ZWV0c19sb2dPZGRzWyw1XSA8LSBhYnModHdlZXRzX2xvZ09kZHMkbG9nX29kZHMpDQogICAgICAgICAgICAgICAgICBuYW1lcyh0d2VldHNfbG9nT2RkcylbNV0gPC0gImFic19sb2dfb2RkcyINCiAgICAgICAgICAgICAgICAgIHR3ZWV0c19sb2dPZGRzIDwtIHR3ZWV0c19sb2dPZGRzICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGF1dG9yX2ZyZWN1ZW50ZSA9IGlmX2Vsc2UobG9nX29kZHMgPiAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXModHdlZXRzX2xvZ09kZHMpWzJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXModHdlZXRzX2xvZ09kZHMpWzNdKSkNCg0KRGlmZXJlbmNpYV9HRyA8LSB0d2VldHNfbG9nT2RkcyAlPiUgDQogIGFycmFuZ2UoLWxvZ19vZGRzLCBieWdyb3VwID0gRkFMU0UpJT4lIA0KICBmaWx0ZXIoYXV0b3JfZnJlY3VlbnRlID09ICJHaW5lcy5HRyIpJT4lIA0KICB0YWlsKDE1KQ0KDQpEaWZlcmVuY2lhX0ZRIDwtIHR3ZWV0c19sb2dPZGRzICU+JSANCiAgYXJyYW5nZSgtYWJzX2xvZ19vZGRzLCBieWdyb3VwID0gRkFMU0UpJT4lIA0KICBmaWx0ZXIoYXV0b3JfZnJlY3VlbnRlID09ICJGLlF1aXJvcyIpJT4lIA0KICBoZWFkKDE1KQ0KDQpEaWZlcmVuY2lhX0dHX0ZRIDwtIHJiaW5kKERpZmVyZW5jaWFfR0csRGlmZXJlbmNpYV9GUSkNCg0KRGlmZXJlbmNpYV9HR19GUSU+JSANCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFBhbGFicmEsIGxvZ19vZGRzKSwgeT0gbG9nX29kZHMsIGZpbGwgPSBhdXRvcl9mcmVjdWVudGUpKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgbGFicyh4ID0gIi1wYWxhYnJhIiwgeSA9ICJVc28iLCB0aXRsZSA9ICJRdWlyw7NzIHZzIEdpbmVzIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICB0ZW1hMg0KYGBgDQoNCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+IDI3LSBCdWxscmljaCB2cyBDcmlzdGluYSB3b3JkIHVzZSBjb21wYXJpc29uIDwvaDM+IDwvc3Bhbj4gPC9jZW50ZXI+DQoNCg0KVGhlIGlkZWEgb2YgdGhpcyBncmFwaCBpcyB0byBzaG93IHdoaWNoIHdvcmRzIGFyZSB0aGUgbW9zdCBkaWZmZXJlbnQgaW4gdGhlaXIgdXNlLCBpbiB0aGlzIGNhc2UgYmV0d2Vlbg0KICpDcmlzdGluYSBLaXJjaG5lciogYW5kICpQYXRyaWNpYSBCdWxscmljaCoNCg0KDQpgYGB7cn0NCnR3ZWV0c191bnBpdm90IDwtIHR1aXRzX3Rva2VucyAlPiUgZ3JvdXBfYnkoUG9saXRpY28sIFBhbGFicmEpICU+JQ0KICAgICAgY291bnQoUGFsYWJyYSkgJT4lDQogICAgICBzcHJlYWQoa2V5ID0gUG9saXRpY28sIHZhbHVlID0gbiwgZmlsbCA9IDAsIGRyb3AgPSBUUlVFKSAlPiUgDQogICAgICBnYXRoZXIoa2V5ID0gIlBvbGl0aWNvIiwgdmFsdWUgPSAibiIsIC1QYWxhYnJhKQ0KDQoNCiAgICAgICAgICAgICAgICAgICMgU2VsZWNjacOzbiBkZSBsb3MgYXV0b3Jlcw0KICAgICAgICAgICAgICAgICAgdHdlZXRzX3VucGl2b3QyIDwtIHR3ZWV0c191bnBpdm90ICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihQb2xpdGljbyAlaW4lIGMoIlAuQnVsbHJpY2giLCAiQy5LaXJjaG5lciIpKQ0KICAgICAgICAgICAgICAgICAgIyBTZSBhw7FhZGUgZWwgdG90YWwgZGUgcGFsYWJyYXMgZGUgY2FkYSBhdXRvcg0KICAgICAgICAgICAgICAgICAgdHdlZXRzX3VucGl2b3QyIDwtIHR3ZWV0c191bnBpdm90MiAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRfam9pbihUd2VldHNfREYgJT4lIGdyb3VwX2J5KFBvbGl0aWNvKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoTiA9IG4oKSksIGJ5ID0gIlBvbGl0aWNvIikNCiAgICAgICAgICAgICAgICAgICMgQ8OhbGN1bG8gZGUgb2RkcyB5IGxvZyBvZiBvZGRzIGRlIGNhZGEgcGFsYWJyYQ0KICAgICAgICAgICAgICAgICAgdHdlZXRzX2xvZ09kZHMgPC0gdHdlZXRzX3VucGl2b3QyICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShvZGRzID0gKG4gKyAxKSAvIChOICsgMSkpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KFBvbGl0aWNvLCBQYWxhYnJhLCBvZGRzKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICBzcHJlYWQoa2V5ID0gUG9saXRpY28sIHZhbHVlID0gb2RkcykgDQogICAgICAgICAgICAgICAgICB0d2VldHNfbG9nT2Rkc1ssNF0gPC0gbG9nKHR3ZWV0c19sb2dPZGRzWywyXS90d2VldHNfbG9nT2Rkc1ssM10pDQogICAgICAgICAgICAgICAgICBuYW1lcyh0d2VldHNfbG9nT2RkcylbNF0gPC0gImxvZ19vZGRzIg0KICAgICAgICAgICAgICAgICAgdHdlZXRzX2xvZ09kZHNbLDVdIDwtIGFicyh0d2VldHNfbG9nT2RkcyRsb2dfb2RkcykNCiAgICAgICAgICAgICAgICAgIG5hbWVzKHR3ZWV0c19sb2dPZGRzKVs1XSA8LSAiYWJzX2xvZ19vZGRzIg0KICAgICAgICAgICAgICAgICAgdHdlZXRzX2xvZ09kZHMgPC0gdHdlZXRzX2xvZ09kZHMgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoYXV0b3JfZnJlY3VlbnRlID0gaWZfZWxzZShsb2dfb2RkcyA+IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lcyh0d2VldHNfbG9nT2RkcylbMl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lcyh0d2VldHNfbG9nT2RkcylbM10pKQ0KDQpEaWZlcmVuY2lhX1BCIDwtIHR3ZWV0c19sb2dPZGRzICU+JSANCiAgYXJyYW5nZSgtbG9nX29kZHMsIGJ5Z3JvdXAgPSBGQUxTRSklPiUgDQogIGZpbHRlcihhdXRvcl9mcmVjdWVudGUgPT0gIlAuQnVsbHJpY2giKSU+JSANCiAgdGFpbCgxNSkNCg0KRGlmZXJlbmNpYV9DRksgPC0gdHdlZXRzX2xvZ09kZHMgJT4lIA0KICBhcnJhbmdlKC1hYnNfbG9nX29kZHMsIGJ5Z3JvdXAgPSBGQUxTRSklPiUgDQogIGZpbHRlcihhdXRvcl9mcmVjdWVudGUgPT0gIkMuS2lyY2huZXIiKSU+JSANCiAgaGVhZCgxNSkNCg0KRGlmZXJlbmNpYV9QQl9DRksgPC0gcmJpbmQoRGlmZXJlbmNpYV9QQixEaWZlcmVuY2lhX0NGSykNCg0KRGlmZXJlbmNpYV9QQl9DRkslPiUgDQogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihQYWxhYnJhLCBsb2dfb2RkcyksIHk9IGxvZ19vZGRzLCBmaWxsID0gYXV0b3JfZnJlY3VlbnRlKSkgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGxhYnMoeCA9ICItcGFsYWJyYSIsIHkgPSAiVXNvIiwgdGl0bGUgPSAiQ3Jpc3RpbmEgdnMgQnVsbHJpY2giKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRlbWEyDQpgYGANCg0KDQoNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMjgyRjQ0OyI+IDxoMz4gIDI4LSBFbW90aW9ucyBpbiB0d2VldHMgPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KTm93IHdlIGFuYWx5emUgYSBicm9hZGVyIGZpZWxkIG9mIGVtb3Rpb25zIHRoYXQgd2VyZSB1c2VkIGJ5IHRoZSBkaWZmZXJlbnQgcG9saXRpY2lhbnMgYW1vbmcgYWxsIHRoZSB0d2VldHMgdGhhdCBoYXZlIGJlZW4gcHVibGlzaGVkIGluIHRoaXMgcGVyaW9kLg0KDQogIC0gQW1vbmcgdGhlIG1lbWJlcnMgb2YgKipQUk8qKiBhbmQgKipQZXJvbmlzbSoqLCAqdHJ1c3QqIHN0YW5kcyBvdXQgYXMgdGhlIG1haW4gc2VudGltZW50IGV4cHJlc3NlZA0KDQogIC0gSW4gYWNjb3VudHMgbGlrZSAqKkVzcGVydCoqIG9yICoqRGVsIENhw7FvKiogd2hhdCB0aGVpciB0d2VldHMgc2hvdyB0aGUgbW9zdCBpcyAqZmVhciouDQoNCiAgLSBUaGUgKipQUk8qKiBhbmQgKipQZXJvbmlzbSoqIGFjY291bnRzLCBtYWlubHkgYnkgdGhlIG1pbmlzdGVycyBhbmQgaGVhZHMgb2YgZ292ZXJubWVudHMsIHNlZWsgYSBmZWVsaW5nIG9mICogYW50aWNpcGF0aW9uICoNCg0KICAtIE90aGVyIGFjY291bnRzIGFyZSBoaWdoZXIgdG9uZSAqYW5ndWlzaCogb3ZlciB0aW1lLg0KDQogIC0gKlNhZG5lc3MqIGlzIGEgZ2VuZXJhbCBmZWVsaW5nIHRoYXQgaXMgaW5jb3Jwb3JhdGVkIGluIGFsbCB0d2VldHMsIGFuZCBpcyB1bmRlcnN0b29kIGJ5IHRoZSBjb21wbGV4IHNpdHVhdGlvbiB0aGF0IGEgcGFuZGVtaWMgbWVhbnMuDQoNCg0KDQoNCmBgYHtyfQ0KVGV4dFNlbnRpbWVudCA8LSBnZXRfbnJjX3NlbnRpbWVudChUd2VldHNfREYkdGV4dCkNCg0KDQpUd2VldHNfREZfc2VudGltaWVudG8gPC0gY2JpbmQoVHdlZXRzX0RGLCBUZXh0U2VudGltZW50KQ0KDQoNCmdhdGhlcihUd2VldHNfREZfc2VudGltaWVudG8sICJzZW50aW1lbnQiLCAidmFsdWVzIiwgMTAzOjExMikgJT4lDQogIGdyb3VwX2J5KFBvbGl0aWNvLCBQYXJ0aWRvLCBzZW50aW1lbnQpICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAgImN1ZW50YSBwYXJ0aWRhcmlhIiklPiUNCiAgZmlsdGVyKHNlbnRpbWVudCAhPSAibmVnYXRpdmUiICYgc2VudGltZW50ICE9InBvc2l0aXZlIiklPiUNCiAgICBzdW1tYXJpc2UoVG90YWwgPSBzdW0odmFsdWVzKSkgJT4lDQogICAgICBtdXRhdGUoUHJvcG9yY2lvbiA9IFRvdGFsIC8gc3VtKFRvdGFsKSkgJT4lDQpnZ3Bsb3QoKSArDQogIGFlcyhQb2xpdGljbywgUHJvcG9yY2lvbiwgZmlsbCA9IHNlbnRpbWVudCkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICJzdGFjayIsIGNvbG9yID0gImJsYWNrIikgKw0KICBjb29yZF9mbGlwKCkgICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwwKSkgKw0KICBsYWJzKHkgPSAiUGFsYWJyYXMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpnYXRoZXIoVHdlZXRzX0RGX3NlbnRpbWllbnRvLCAic2VudGltZW50IiwgInZhbHVlcyIsIDEwMzoxMTIpICU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgc2VudGltZW50KSAlPiUNCiAgZmlsdGVyKFBhcnRpZG8gPT0gICJQUk8iKSU+JQ0KICAgIGZpbHRlcihzZW50aW1lbnQgIT0gIm5lZ2F0aXZlIiAmIHNlbnRpbWVudCAhPSJwb3NpdGl2ZSIpJT4lDQogICAgc3VtbWFyaXNlKFRvdGFsID0gc3VtKHZhbHVlcykpICU+JQ0KICAgICAgbXV0YXRlKFByb3BvcmNpb24gPSBUb3RhbCAvIHN1bShUb3RhbCkpICU+JQ0KZ2dwbG90KCkgKw0KICBhZXMoUG9saXRpY28sIFByb3BvcmNpb24sIGZpbGwgPSBzZW50aW1lbnQpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJibGFjayIpICsNCiAgY29vcmRfZmxpcCgpICArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsMCkpICsNCiAgbGFicyh5ID0gIlBhbGFicmFzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KZ2F0aGVyKFR3ZWV0c19ERl9zZW50aW1pZW50bywgInNlbnRpbWVudCIsICJ2YWx1ZXMiLCAxMDM6MTEyKSAlPiUNCiAgZ3JvdXBfYnkoUG9saXRpY28sIFBhcnRpZG8sIHNlbnRpbWVudCkgJT4lDQogIGZpbHRlcihQYXJ0aWRvID09ICAiUGVyb25pc21vIiklPiUNCiAgICBmaWx0ZXIoc2VudGltZW50ICE9ICJuZWdhdGl2ZSIgJiBzZW50aW1lbnQgIT0icG9zaXRpdmUiKSU+JQ0KICAgIHN1bW1hcmlzZShUb3RhbCA9IHN1bSh2YWx1ZXMpKSAlPiUNCiAgICAgIG11dGF0ZShQcm9wb3JjaW9uID0gVG90YWwgLyBzdW0oVG90YWwpKSAlPiUNCmdncGxvdCgpICsNCiAgYWVzKFBvbGl0aWNvLCBQcm9wb3JjaW9uLCBmaWxsID0gc2VudGltZW50KSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGNvb3JkX2ZsaXAoKSAgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApKSArDQogIGxhYnMoeSA9ICJQYWxhYnJhcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmdhdGhlcihUd2VldHNfREZfc2VudGltaWVudG8sICJzZW50aW1lbnQiLCAidmFsdWVzIiwgMTAzOjExMikgJT4lDQogIGdyb3VwX2J5KFBvbGl0aWNvLCBQYXJ0aWRvLCBzZW50aW1lbnQpICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAgIm90cm9zIGNhbmRpZGF0b3MiKSU+JQ0KICAgZmlsdGVyKHNlbnRpbWVudCAhPSAibmVnYXRpdmUiICYgc2VudGltZW50ICE9InBvc2l0aXZlIiklPiUNCiAgICBzdW1tYXJpc2UoVG90YWwgPSBzdW0odmFsdWVzKSkgJT4lDQogICAgICBtdXRhdGUoUHJvcG9yY2lvbiA9IFRvdGFsIC8gc3VtKFRvdGFsKSkgJT4lDQpnZ3Bsb3QoKSArDQogIGFlcyhQb2xpdGljbywgUHJvcG9yY2lvbiwgZmlsbCA9IHNlbnRpbWVudCkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICJzdGFjayIsIGNvbG9yID0gImJsYWNrIikgKw0KICBjb29yZF9mbGlwKCkgICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwwKSkgKw0KICBsYWJzKHkgPSAiUGFsYWJyYXMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjogIzI4MkY0NDsiPiA8aDM+ICAyOS0gRW1vdGlvbnMgbW9udGggYnkgbW9udGggPC9oMz4gPC9zcGFuPiA8L2NlbnRlcj4NCg0KQWx0aG91Z2ggdGhlcmUgYXJlIG5vIG1ham9yIGNoYW5nZXMgd2hlbiBpdCBjb21lcyB0byBkb2luZyBzZW50aW1lbnQgYW5hbHlzaXMgZnJvbSBtb250aCB0byBtb250aCwgdGhlcmUgYXJlIHNvbWUgZGV0YWlsczoNCg0KLSBIZWFsdGggbWluaXN0ZXJzIHRyYW5zbWl0IG1vcmUgYW5kIG1vcmUgKmNvbmZpZGVuY2UqLg0KDQotIFRoZSBzby1jYWxsZWQgb3RoZXIgY2FuZGlkYXRlcyBpcyBkZWNsaW5pbmcgdGhlIHRyYW5zbWlzc2lvbiBvZiAqY29uZmlkZW5jZSouDQoNCi0gKipMYXJyZXRhKiogYWx0aG91Z2ggaXQgaGFzIGxvdyBpbiB0aGUgZmVlbGluZyBvZiAqY29uZmlkZW5jZSosIGNvbnRpbnVlcyB0byBleHBvc2Ugb25lIG9mICogYW50aWNpcGF0aW9uICouDQoNCi0gKipLaWNpbGxvZioqIGhhcyBhbiBpbmNyZWFzaW5nIG1lc3NhZ2Ugb2YgKmFuZ3Vpc2gqLg0KDQoNCg0KYGBge3J9DQpnYXRoZXIoVHdlZXRzX0RGX3NlbnRpbWllbnRvLCAic2VudGltZW50IiwgInZhbHVlcyIsIDEwMzoxMTIpICU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgbWVzLCBzZW50aW1lbnQpICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAgImN1ZW50YSBwYXJ0aWRhcmlhIiklPiUNCiAgZmlsdGVyKHNlbnRpbWVudCAhPSAibmVnYXRpdmUiICYgc2VudGltZW50ICE9InBvc2l0aXZlIiklPiUNCiAgICBzdW1tYXJpc2UoVG90YWwgPSBzdW0odmFsdWVzKSkgJT4lDQogICAgICBtdXRhdGUoUHJvcG9yY2lvbiA9IFRvdGFsIC8gc3VtKFRvdGFsKSkgJT4lDQpnZ3Bsb3QoKSArDQphZXMoeCA9IG1lcywgeSA9UHJvcG9yY2lvbiwgY29sb3IgPSBzZW50aW1lbnQpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNlbnRpbWVudCkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IC40KSwgDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNlcmlmIikpICsNCiAgdGVtYTIgKw0KICBmYWNldF93cmFwKH4gUG9saXRpY28pICsNCiAgbGFicyh0aXRsZSA9ICJDYW1iaW8gZGUgbG9zIHNlbnRpbWllbnRvcyBlbiBlbCB0aWVtcG8iLCANCiAgICAgICB4ID0gIk1lcyIsIHkgPSAiUG9ycG9yY2nDs24iLCBjb2xvciA9ICJTZW50aW1pZW50byIpIA0KDQpnYXRoZXIoVHdlZXRzX0RGX3NlbnRpbWllbnRvLCAic2VudGltZW50IiwgInZhbHVlcyIsIDEwMzoxMTIpICU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgbWVzLCBzZW50aW1lbnQpICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAgIm90cm9zIGNhbmRpZGF0b3MiKSU+JQ0KICAgZmlsdGVyKHNlbnRpbWVudCAhPSAibmVnYXRpdmUiICYgc2VudGltZW50ICE9InBvc2l0aXZlIiklPiUNCiAgICBzdW1tYXJpc2UoVG90YWwgPSBzdW0odmFsdWVzKSkgJT4lDQogICAgICBtdXRhdGUoUHJvcG9yY2lvbiA9IFRvdGFsIC8gc3VtKFRvdGFsKSkgJT4lDQpnZ3Bsb3QoKSArDQphZXMoeCA9IG1lcywgeSA9UHJvcG9yY2lvbiwgY29sb3IgPSBzZW50aW1lbnQpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNlbnRpbWVudCkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IC40KSwgDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNlcmlmIikpICsNCiAgdGVtYTIgKw0KICBmYWNldF93cmFwKH4gUG9saXRpY28pICsNCiAgbGFicyh0aXRsZSA9ICJDYW1iaW8gZGUgbG9zIHNlbnRpbWllbnRvcyBlbiBlbCB0aWVtcG8iLCANCiAgICAgICB4ID0gIk1lcyIsIHkgPSAiUG9ycG9yY2nDs24iLCBjb2xvciA9ICJTZW50aW1pZW50byIpIA0KDQoNCmdhdGhlcihUd2VldHNfREZfc2VudGltaWVudG8sICJzZW50aW1lbnQiLCAidmFsdWVzIiwgMTAzOjExMikgJT4lDQogIGdyb3VwX2J5KFBvbGl0aWNvLCBQYXJ0aWRvLCBtZXMsIHNlbnRpbWVudCkgJT4lDQogIGZpbHRlcihQYXJ0aWRvID09ICAiUGVyb25pc21vIiklPiUNCiAgZmlsdGVyKHNlbnRpbWVudCAhPSAibmVnYXRpdmUiICYgc2VudGltZW50ICE9InBvc2l0aXZlIiklPiUNCiAgICBzdW1tYXJpc2UoVG90YWwgPSBzdW0odmFsdWVzKSkgJT4lDQogICAgICBtdXRhdGUoUHJvcG9yY2lvbiA9IFRvdGFsIC8gc3VtKFRvdGFsKSkgJT4lDQpnZ3Bsb3QoKSArDQphZXMoeCA9IG1lcywgeSA9UHJvcG9yY2lvbiwgY29sb3IgPSBzZW50aW1lbnQpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNlbnRpbWVudCkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IC40KSwgDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNlcmlmIikpICsNCiAgdGVtYTIgKw0KICBmYWNldF93cmFwKH4gUG9saXRpY28pICsNCiAgbGFicyh0aXRsZSA9ICJDYW1iaW8gZGUgbG9zIHNlbnRpbWllbnRvcyBlbiBlbCB0aWVtcG8iLCANCiAgICAgICB4ID0gIk1lcyIsIHkgPSAiUG9ycG9yY2nDs24iLCBjb2xvciA9ICJTZW50aW1pZW50byIpIA0KDQpnYXRoZXIoVHdlZXRzX0RGX3NlbnRpbWllbnRvLCAic2VudGltZW50IiwgInZhbHVlcyIsIDEwMzoxMTIpICU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgbWVzLCBzZW50aW1lbnQpICU+JQ0KICBmaWx0ZXIoUGFydGlkbyA9PSAgIlBSTyIpJT4lDQogIGZpbHRlcihzZW50aW1lbnQgIT0gIm5lZ2F0aXZlIiAmIHNlbnRpbWVudCAhPSJwb3NpdGl2ZSIpJT4lDQogICAgc3VtbWFyaXNlKFRvdGFsID0gc3VtKHZhbHVlcykpICU+JQ0KICAgICAgbXV0YXRlKFByb3BvcmNpb24gPSBUb3RhbCAvIHN1bShUb3RhbCkpICU+JQ0KZ2dwbG90KCkgKw0KYWVzKHggPSBtZXMsIHkgPVByb3BvcmNpb24sIGNvbG9yID0gc2VudGltZW50KSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBzZW50aW1lbnQpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAuNCksIA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJzZXJpZiIpKSArDQogIHRlbWEyICsNCiAgZmFjZXRfd3JhcCh+IFBvbGl0aWNvKSArDQogIGxhYnModGl0bGUgPSAiQ2FtYmlvIGRlIGxvcyBzZW50aW1pZW50b3MgZW4gZWwgdGllbXBvIiwgDQogICAgICAgeCA9ICJNZXMiLCB5ID0gIlBvcnBvcmNpw7NuIiwgY29sb3IgPSAiU2VudGltaWVudG8iKSANCmBgYA0KDQoNCg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6ICMyODJGNDQ7Ij4gPGgzPiAzMC0gQ29tcGFyaXNvbiBvZiBlbW90aW9ucyA8L2gzPiA8L3NwYW4+IDwvY2VudGVyPg0KDQoNClRoZSBpZGVhIG9mIOKAi+KAi2NvbXBhcmluZyBldmVyeW9uZSdzIGVtb3Rpb25zIG9uIGEgZ3JhcGggaGVscHMgZm9yIGEgZ2VuZXJhbCB2aXN1YWxpemF0aW9uIChlbGltaW5hdGluZyBwYXJ0eSBhY2NvdW50cyk6DQoNCi0gQWx0aG91Z2ggdGhlIG51bWJlciBvZiB0d2VldHMgZnJvbSAqKk1hY3JpKiogYXJlIGZldywgaXQgaXMgdGhlIG9uZSB0aGF0IHRyYW5zbWl0cyB0aGUgbW9zdCAqY29uZmlkZW5jZSouDQoNCi0gVGhvc2Ugd2hvIGhhdmUgZWxlY3RlZCBwb3dlciBhcmUgdGhlIG9uZXMgd2hvIG1vc3QgKnRydXN0KiBzZWVrIGluIHRoZWlyIHR3ZWV0cy4NCg0KLSBDYW5kaWRhdGVzIHdobyBoYXZlIGxvc3QgaGF2ZSBtaXhlZCBmZWVsaW5ncywgd2l0aCBhIGhpZ2ggbGV2ZWwgb2YgKmZlYXIqIGFuZCAqYW5ndWlzaCogaW4gdGhlaXIgd3JpdGluZy4NCg0KLSAqRmVlbGluZ3MgdGhhdCByZXByZXNlbnQgbGVzcyB0aGFuIDEwJSBvZiB0d2VldHMgYXJlIGRpc2NhcmRlZC4qDQoNCg0KDQoNCg0KYGBge3J9DQpnYXRoZXIoVHdlZXRzX0RGX3NlbnRpbWllbnRvLCAic2VudGltZW50IiwgInZhbHVlcyIsIDEwMzoxMTIpICU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgc2VudGltZW50KSAlPiUNCiAgZmlsdGVyKHNlbnRpbWVudCAhPSAibmVnYXRpdmUiICYgc2VudGltZW50ICE9InBvc2l0aXZlIiAmIFBhcnRpZG8gIT0gImN1ZW50YSBwYXJ0aWRhcmlhIiklPiUNCiAgICBzdW1tYXJpc2UoVG90YWwgPSBzdW0odmFsdWVzKSkgJT4lDQogICAgICBtdXRhdGUoUHJvcG9yY2lvbiA9IFRvdGFsIC8gc3VtKFRvdGFsKSkgJT4lDQogICAgZ2dwbG90KCkgKw0KICBhZXMoUG9saXRpY28sIFByb3BvcmNpb24sIGNvbG9yID0gc2VudGltZW50LCBhbHBoYSA9IFByb3BvcmNpb24pICsNCiAgZ2VvbV9wb2ludChmaWxsID0gIndoaXRlIiwgc3Ryb2tlID0gMSwgc2hhcGUgPSAyMSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc2VudGltZW50KSwgdmp1c3QgPSAtLjksIGZhbWlseSA9ICJzZXJpZiIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0ICgpKSArDQogIHRlbWExICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgdGV4dCA9ICBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNlcmlmIikpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgbGFicyh0aXRsZSA9ICJTZW50aW1pZW50b3MgdG90YWxlcyBjb21wYXJhdGl2byIsDQogICAgICAgeCA9ICJQb2xpdGljbyIsDQogICAgICAgeSA9ICJQcm9wb3JjacOzbiBkZWwgc2VudGltaWVudG8iKQ0KDQpnYXRoZXIoVHdlZXRzX0RGX3NlbnRpbWllbnRvLCAic2VudGltZW50IiwgInZhbHVlcyIsIDEwMzoxMTIpICU+JQ0KICBncm91cF9ieShQb2xpdGljbywgUGFydGlkbywgc2VudGltZW50KSAlPiUNCiAgZmlsdGVyKHNlbnRpbWVudCAhPSAicG9zaXRpdmUiICYgc2VudGltZW50ICE9Im5lZ2F0aXZlIiAmIHNlbnRpbWVudCAhPSJqb3kiICYgc2VudGltZW50ICE9InN1cnByaXNlIiAmIFBhcnRpZG8gIT0gImN1ZW50YSBwYXJ0aWRhcmlhIiklPiUNCiAgICBzdW1tYXJpc2UoVG90YWwgPSBzdW0odmFsdWVzKSkgJT4lDQogICAgICBtdXRhdGUoUHJvcG9yY2lvbiA9IFRvdGFsIC8gc3VtKFRvdGFsKSkgJT4lDQogIGdncGxvdCgpICsNCiAgYWVzKHNlbnRpbWVudCwgUHJvcG9yY2lvbiwgY29sb3IgPSBzZW50aW1lbnQpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBvbGl0aWNvKSAsdmp1c3QgPSAtLjMsIHNpemUgPSAzKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMTUsIDAuNDcpKSArDQogICBsYWJzKHRpdGxlID0gIlNlbnRpbWllbnRvcyB0b3RhbGVzIGNvbXBhcmF0aXZvIiwNCiAgICAgICB4ID0gIlBvbGl0aWNvIiwNCiAgICAgICB5ID0gIlByb3BvcmNpw7NuIGRlbCBzZW50aW1pZW50byIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCmBgYA0K