A ideia dessa analise é trazer o que as pessoas estavam falando sobre o programa Fantástico, que é transmitido todos os domingo na tv Globo. Nessa análise eu utilizei algumas técnicas de mineração de texto e clusterização para extrair o máximo de informações do twitter sobre o programa. Essa análise foi feita no dia 07/06 e foram analisados mais de 8mil tweets com a hashtag fantástico

Pacotes utilizados

library(SnowballC)
library(rtweet)
library(wordcloud)
library(tm)
library(RColorBrewer)
library(cluster)   
library(fpc)
library(twitteR)

Conexão com o Twitter

Feita conexão com o Twitter através das API’s, a idéia foi trazer as palavras através da #Fantástico

setup_twitter_oauth(api_key, api_secret, access_token, access_token_secret)
[1] "Using direct authentication"

Captura dos tweets da rede social

fantastico_tweets <- search_tweets(
  "#fantastico", n = 15000, include_rts = FALSE,lang = "pt", charset="utf-8")

Selecionando a variável de trabalho

Como o objetivo da analise é trabalhar com os comentarios, vamos trazer o que as pessoas estão falando sobre o programa, então vamos trabalhar com a variavel text do banco

fantastico_text <- fantastico_tweets$text

Primeira visualização

Conseguimos obsevar que durante a semana a hashtag teve uma baixa frequência, mas durante e após o programa conseguimos ver um pico.

Limpeza dos textos

Assim como tratamos com dados numéricos, os dados em forma de texto também precisam de um tratamento para que sejam organizados.
Com o VCorpus, conseguimos remover as palavras irrelevantes, pontuações e fazer uma série de tratamentos

Nuvem de palavras

Nessa primeira nuvem conseguimos observar as palavras que foram mensionadas quando a Hashtag foi utilizada.
Em seguida farei alguns outros tratamentos e no quase no final uma outra nuvem de palavras.

formatacao <- brewer.pal(8,"Dark2")
wordcloud(fantastico_text_corpus,min.freq=2,max.words=100, random.order=T, colors=formatacao)

Criando uma matriz e tratando os termos

Nessa etapa eu transformei o Corpus em uma matriz e ajustei as palavras pela frequência. Conseguimos observar que temos 8983 documentos e 17169 termos distintos (Palavras), com isso conseguimos separar pela frequência, e podemos usar para um modelo de previsão utilizando textos se necessário. Conseguimos ver também a matriz separada por termos, essa seria uma organização inicial das palavras, essas palavras serão removidas na próxima linha de código

fantastico_dtm<- DocumentTermMatrix(fantastico_text_corpus)   
fantastico_dtm
<<DocumentTermMatrix (documents: 8983, terms: 17169)>>
Non-/sparse entries: 95448/154133679
Sparsity           : 100%
Maximal term length: 244
Weighting          : term frequency (tf)
fantastico_frequencia <- colSums(as.matrix(fantastico_dtm))   
length(fantastico_frequencia) 
[1] 17169
tail(fantastico_frequencia,10)
   zoeira      zoio     zomba    zombar      zona zoológico     zotto     zuada    zueira     zzzzz 
        1         1         1         1         2         1        13         1         1         1 

Nessa etapa, removi os termos que tinham frequência muito baixa e atrapalhavam a análise. Conseguimos observar que o Maximal term length era 244 e foi reduzido para 18

fantastico_dtms <- removeSparseTerms(fantastico_dtm, 0.98) 
fantastico_dtms
<<DocumentTermMatrix (documents: 8983, terms: 36)>>
Non-/sparse entries: 19489/303899
Sparsity           : 94%
Maximal term length: 18
Weighting          : term frequency (tf)

Na sequência eu recriei a frequência com os termos tratados com a quantidade de 36.

fantastico_frequencia <- colSums(as.matrix(fantastico_dtms))   
length(fantastico_frequencia) 
[1] 36
fantastico_frequencia <- sort(colSums(as.matrix(fantastico_frequencia)), decreasing=TRUE) 
fantastico_frequencia
[1] 20360

Matriz e Data.Frame

Convertendo a matriz em um data.frame

fantastico_plot <- data.frame(word=names(fantastico_frequencia), freq=fantastico_frequencia)  

Visualização

Nessa etapa, vamos plotar alguns gráficos e continuar a limpeza das palavras. Selecionei que a palavra tivesse uma frequência de maior que 200 para aparecer no gráfico

Conseguimos observar que ainda existem muitas palavras que são irrelevantes para a análise, a seguir vamos fazer o tratamento dessas palavras

grafico   

Último tratamento

Removendo as palavras que sujam a analise e também as palavras que são óbvias

fantastico_text_corpus <- tm_map(fantastico_text_corpus, removeWords,c("contra","aqui","falar","fazer", "sobre", "ainda","bem","tudo","falar", "fantastico","fantástico","pra","ser","vai", "globo","agora","ter", "nada","domingoespetacular","be","ver","sobre","cara","ainda","bem","tudo","desse"))
fantastico_dtms <- removeSparseTerms(DocumentTermMatrix(fantastico_text_corpus) , 0.98) 
fantastico_dtms
<<DocumentTermMatrix (documents: 8983, terms: 16)>>
Non-/sparse entries: 4346/139382
Sparsity           : 97%
Maximal term length: 13
Weighting          : term frequency (tf)


Retornando para matriz

fantastico_frequencia <- colSums(as.matrix(fantastico_dtms))   
length(fantastico_frequencia) 
[1] 16

Visualizando a frenquência das palavras.

fantastico_frequencia <- sort(colSums(as.matrix(fantastico_dtms)), decreasing=TRUE) 
fantastico_frequencia
        gente    showdavida        brasil    reportagem       matéria           pai       pessoas 
          516           487           434           368           340           321           285 
        tadeu manifestações          deus       caboclo       polícia          hoje      encrenca 
          234           225           222           207           206           205           198 
       médico      programa 
          193           185 

Convertendo a matriz de frequência em dataframe e mostrando em formato de tabela.

fantastico_plot <- data.frame(word=names(fantastico_frequencia), freq=fantastico_frequencia)  
fantastico_plot

Ultimas Visualizações

No gráfico abaixo, organizei as palavras com maior frequência depois de aplicado o tratamento de retirar as palavras irrelevantes. Conseguimos observar a diferença entre os dois gráficos de barra

grafico <- ggplot(subset(fantastico_plot, fantastico_frequencia>10), aes(x = reorder(word, -freq), y = freq)) +
  geom_bar(stat = "identity") + 
  theme(axis.text.x=element_text(angle=45, hjust=1)) +
  ggtitle("Grafico de barras com os termos mais frequentes") +
  labs(y="Frequencia", x = "Termos")
grafico   

Nuvem de palavras

Depois de todos os tratamentos, a nuvem de palavra fica muito mais limpa, e assim conseguimos ter uma melhore visualização dos termos mais frequentes.

wordcloud(names(fantastico_frequencia),fantastico_frequencia,min.freq=2,max.words=150, random.order=T, colors=formatacao)

Clustering - Dendograma

Aplicando removeSparseTerms para trazer um cluster mais limpo que fique de uma forma mais facil de visualizar.

fantastico_dtms2 <- removeSparseTerms(fantastico_dtms, 0.98)
fantastico_dtms2
<<DocumentTermMatrix (documents: 8983, terms: 16)>>
Non-/sparse entries: 4346/139382
Sparsity           : 97%
Maximal term length: 13
Weighting          : term frequency (tf)

A idéia do dendograma é trazer em qual cluster estão as palavras e qual a força de relacionamento entre elas
Ex:é a palavra principal é Gente, quais clusters derivam dessa palavra?

distancia <- dist(t(fantastico_dtms2), method="euclidian")   
dendograma <- hclust(d=distancia, method="complete")
plot(dendograma, hang=-1,main = "Dendograma Tweets",
     xlab = "Distancia",
     ylab = "Altura")
groups <- cutree(dendograma, k=4)
rect.hclust(dendograma, k=4, border="red")



Conclusão

Técnicas de análise de textos podem ser utilizadas de muitas formas, nessa análise eu separei apenas alguns tratamentos que podem ser feitos e como analisar o comportamento das pessoas. É de extrema importância estarmos monitorando as redes para definir quais estratégias devem ser tomadas e qual momento que se deve falar mais de determinado assunto. Muitas vezes temos a impressão de que as redes sociais estão dizendo uma coisa, mas elas podem estar dizendo outra completamente diferente, essa visão pode ser devido as nossas redes já estarem enviesadas e só conseguimos ver dentro da nossa bolha de relacionamento. Olhar as redes sociais de uma forma “Macro” e não micro ou segmentada, traz uma visão mais técnica e objetiva e uma ferramenta poderosa nas estratégias de uma empresa.
Agora me diz, o quão importante seria essa técnica na estratégia de marketing e vendas da sua empresa?


Blog: https://diascodes.medium.com/
Linkedin: https://www.linkedin.com/in/gabrieldiasdeoliveira/

LS0tDQp0aXRsZTogIlRleHQgTWluaW5nIC0gTWluZXJhw6fDo28gZGUgdGV4dG8gdXRpbGl6YW5kbyBkYWRvcyBkbyBUd2l0dGVyIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQphdXRob3I6ICJBdXRvcjogR2FicmllbCBEaWFzIg0KLS0tDQo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCipBIGlkZWlhIGRlc3NhIGFuYWxpc2Ugw6kgdHJhemVyIG8gcXVlIGFzIHBlc3NvYXMgZXN0YXZhbSBmYWxhbmRvIHNvYnJlIG8gcHJvZ3JhbWEgRmFudMOhc3RpY28sIHF1ZSDDqSB0cmFuc21pdGlkbyB0b2RvcyBvcyBkb21pbmdvIG5hIHR2IEdsb2JvLiBOZXNzYSBhbsOhbGlzZSBldSB1dGlsaXplaSBhbGd1bWFzIHTDqWNuaWNhcyBkZSBtaW5lcmHDp8OjbyBkZSB0ZXh0byBlIGNsdXN0ZXJpemHDp8OjbyBwYXJhIGV4dHJhaXIgbyBtw6F4aW1vIGRlIGluZm9ybWHDp8O1ZXMgZG8gdHdpdHRlciBzb2JyZSBvIHByb2dyYW1hLioNCipFc3NhIGFuw6FsaXNlIGZvaSBmZWl0YSBubyBkaWEgMDcvMDYgZSBmb3JhbSBhbmFsaXNhZG9zIG1haXMgZGUgOG1pbCB0d2VldHMgY29tIGEgaGFzaHRhZyBmYW50w6FzdGljbyoNCg0KIyMjIFBhY290ZXMgdXRpbGl6YWRvcw0KYGBge3J9DQpsaWJyYXJ5KFNub3diYWxsQykNCmxpYnJhcnkocnR3ZWV0KQ0KbGlicmFyeSh3b3JkY2xvdWQpDQpsaWJyYXJ5KHRtKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KGNsdXN0ZXIpICAgDQpsaWJyYXJ5KGZwYykNCmxpYnJhcnkodHdpdHRlUikNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmFwaV9rZXkgPSAiejdaS3JvYUJ3Y1RjbHJLYzZvTFBsaFhaViINCmFwaV9zZWNyZXQgPSAiZzlzeVJ0ZTllSXo1WTFGbXl5TzBUWmFOM1dWRmZ1cjBOWmRuV0NFTU1OR2xVYjE0ajUiDQphY2Nlc3NfdG9rZW4gPSAiMTM4NjQ5OTg0MDY5MjEzNzk4NC1XRjJVZEFvNHpOYmViZlR2RmZRQ2hJNUlCendlUWsiDQphY2Nlc3NfdG9rZW5fc2VjcmV0ID0gIjlvWHFWSGZEOFBTZ3BMWndKeERTVHdvdmJKRnZhMzE0dVdhNXJiWnk3Szg3SyINCmBgYA0KDQojIyMgQ29uZXjDo28gY29tIG8gVHdpdHRlcg0KKkZlaXRhIGNvbmV4w6NvIGNvbSBvIFR3aXR0ZXIgYXRyYXbDqXMgZGFzIEFQSSdzLCBhIGlkw6lpYSBmb2kgdHJhemVyIGFzIHBhbGF2cmFzIGF0cmF2w6lzIGRhICNGYW50w6FzdGljbyogDQoNCmBgYHtyfQ0Kc2V0dXBfdHdpdHRlcl9vYXV0aChhcGlfa2V5LCBhcGlfc2VjcmV0LCBhY2Nlc3NfdG9rZW4sIGFjY2Vzc190b2tlbl9zZWNyZXQpDQpgYGANCipDYXB0dXJhIGRvcyB0d2VldHMgZGEgcmVkZSBzb2NpYWwqDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmZhbnRhc3RpY29fdHdlZXRzIDwtIHNlYXJjaF90d2VldHMoDQogICIjZmFudGFzdGljbyIsIG4gPSAxNTAwMCwgaW5jbHVkZV9ydHMgPSBGQUxTRSxsYW5nID0gInB0IiwgY2hhcnNldD0idXRmLTgiKQ0KYGBgDQoNCiMjIyBTZWxlY2lvbmFuZG8gYSB2YXJpw6F2ZWwgZGUgdHJhYmFsaG8NCipDb21vIG8gb2JqZXRpdm8gZGEgYW5hbGlzZSDDqSB0cmFiYWxoYXIgY29tIG9zIGNvbWVudGFyaW9zLCB2YW1vcyB0cmF6ZXIgbyBxdWUgYXMgcGVzc29hcyBlc3TDo28gZmFsYW5kbyBzb2JyZSBvIHByb2dyYW1hLCBlbnTDo28gdmFtb3MgdHJhYmFsaGFyIGNvbSBhIHZhcmlhdmVsIHRleHQgZG8gYmFuY28qDQpgYGB7cn0NCmZhbnRhc3RpY29fdGV4dCA8LSBmYW50YXN0aWNvX3R3ZWV0cyR0ZXh0DQpgYGANCg0KIyMjIFByaW1laXJhIHZpc3VhbGl6YcOnw6NvDQoqQ29uc2VndWltb3Mgb2JzZXZhciBxdWUgZHVyYW50ZSBhIHNlbWFuYSBhIGhhc2h0YWcgdGV2ZSB1bWEgYmFpeGEgZnJlcXXDqm5jaWEsIG1hcyBkdXJhbnRlIGUgYXDDs3MgbyBwcm9ncmFtYSBjb25zZWd1aW1vcyB2ZXIgdW0gcGljby4qIA0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCmZhbnRhc3RpY29fdHdlZXRzICU+JQ0KICB0c19wbG90KCIxIGhvdXJzIikgKw0KICBnZ3Bsb3QyOjp0aGVtZV9taW5pbWFsKCkgKw0KICBnZ3Bsb3QyOjp0aGVtZShwbG90LnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSArDQogIGdncGxvdDI6OmxhYnMoDQogICAgeCA9IE5VTEwsIHkgPSBOVUxMLA0KICAgIHRpdGxlID0gIkZyZXF1ZW5jaWEgZGUgI0ZhbnRhc3RpY28gVHdpdHRlciBwb3N0cyIsDQogICAgc3VidGl0bGUgPSAiVHdlZXRzIGEgY2FkYSAxIGhvcmEiLA0KICAgIGNhcHRpb24gPSAiXG5Tb3VyY2U6IERhZG9zIGNvbGV0YWRvcyBkYSBUd2l0dGVyJ3MgUkVTVCBBUEkgdmlhIHJ0d2VldCINCiAgKQ0KYGBgDQojIyMgTGltcGV6YSBkb3MgdGV4dG9zDQoqQXNzaW0gY29tbyB0cmF0YW1vcyBjb20gZGFkb3MgbnVtw6lyaWNvcywgb3MgZGFkb3MgZW0gZm9ybWEgZGUgdGV4dG8gdGFtYsOpbSBwcmVjaXNhbSBkZSB1bSB0cmF0YW1lbnRvIHBhcmEgcXVlIHNlamFtIG9yZ2FuaXphZG9zLio8YnI+KkNvbSBvIFZDb3JwdXMsIGNvbnNlZ3VpbW9zIHJlbW92ZXIgYXMgcGFsYXZyYXMgaXJyZWxldmFudGVzLCBwb250dWHDp8O1ZXMgZSBmYXplciB1bWEgc8OpcmllIGRlIHRyYXRhbWVudG9zKg0KYGBge3IsZWNobz1GQUxTRX0NCmZhbnRhc3RpY29fdGV4dF9jb3JwdXMgPC0gVkNvcnB1cyhWZWN0b3JTb3VyY2UoZmFudGFzdGljb190ZXh0KSkNCmZhbnRhc3RpY29fdGV4dF9jb3JwdXMgPC0gdG1fbWFwKGZhbnRhc3RpY29fdGV4dF9jb3JwdXMsIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpDQpmYW50YXN0aWNvX3RleHRfY29ycHVzIDwtIHRtX21hcChmYW50YXN0aWNvX3RleHRfY29ycHVzLCByZW1vdmVQdW5jdHVhdGlvbikNCmZhbnRhc3RpY29fdGV4dF9jb3JwdXMgPC0gdG1fbWFwKGZhbnRhc3RpY29fdGV4dF9jb3JwdXMscmVtb3ZlV29yZHMsIHN0b3B3b3JkcygicHQiKSkNCmBgYA0KDQojIyMgTnV2ZW0gZGUgcGFsYXZyYXMNCipOZXNzYSBwcmltZWlyYSBudXZlbSBjb25zZWd1aW1vcyBvYnNlcnZhciBhcyBwYWxhdnJhcyBxdWUgZm9yYW0gbWVuc2lvbmFkYXMgcXVhbmRvIGEgSGFzaHRhZyBmb2kgdXRpbGl6YWRhLiogPGJyPiAqRW0gc2VndWlkYSBmYXJlaSBhbGd1bnMgb3V0cm9zIHRyYXRhbWVudG9zIGUgbm8gcXVhc2Ugbm8gZmluYWwgdW1hIG91dHJhIG51dmVtIGRlIHBhbGF2cmFzLioNCmBgYHtyfQ0KZm9ybWF0YWNhbyA8LSBicmV3ZXIucGFsKDgsIkRhcmsyIikNCndvcmRjbG91ZChmYW50YXN0aWNvX3RleHRfY29ycHVzLG1pbi5mcmVxPTIsbWF4LndvcmRzPTEwMCwgcmFuZG9tLm9yZGVyPVQsIGNvbG9ycz1mb3JtYXRhY2FvKQ0KYGBgDQoNCiMjIyBDcmlhbmRvIHVtYSBtYXRyaXogZSB0cmF0YW5kbyBvcyB0ZXJtb3MNCipOZXNzYSBldGFwYSBldSB0cmFuc2Zvcm1laSBvIENvcnB1cyBlbSB1bWEgbWF0cml6IGUgYWp1c3RlaSBhcyBwYWxhdnJhcyBwZWxhIGZyZXF1w6puY2lhLiAqDQoqQ29uc2VndWltb3Mgb2JzZXJ2YXIgcXVlIHRlbW9zIDg5ODMgZG9jdW1lbnRvcyBlIDE3MTY5IHRlcm1vcyBkaXN0aW50b3MgKFBhbGF2cmFzKSwgY29tIGlzc28gY29uc2VndWltb3Mgc2VwYXJhciBwZWxhIGZyZXF1w6puY2lhLCBlIHBvZGVtb3MgdXNhciBwYXJhIHVtIG1vZGVsbyBkZSBwcmV2aXPDo28gdXRpbGl6YW5kbyB0ZXh0b3Mgc2UgbmVjZXNzw6FyaW8uICoNCipDb25zZWd1aW1vcyB2ZXIgdGFtYsOpbSBhIG1hdHJpeiBzZXBhcmFkYSBwb3IgdGVybW9zLCBlc3NhIHNlcmlhIHVtYSBvcmdhbml6YcOnw6NvIGluaWNpYWwgZGFzIHBhbGF2cmFzLCBlc3NhcyBwYWxhdnJhcyBzZXLDo28gcmVtb3ZpZGFzIG5hIHByw7N4aW1hIGxpbmhhIGRlIGPDs2RpZ28qDQoNCmBgYHtyfQ0KZmFudGFzdGljb19kdG08LSBEb2N1bWVudFRlcm1NYXRyaXgoZmFudGFzdGljb190ZXh0X2NvcnB1cykgICANCmZhbnRhc3RpY29fZHRtDQpgYGANCmBgYHtyfQ0KZmFudGFzdGljb19mcmVxdWVuY2lhIDwtIGNvbFN1bXMoYXMubWF0cml4KGZhbnRhc3RpY29fZHRtKSkgICANCmxlbmd0aChmYW50YXN0aWNvX2ZyZXF1ZW5jaWEpIA0KdGFpbChmYW50YXN0aWNvX2ZyZXF1ZW5jaWEsMTApDQpgYGANCipOZXNzYSBldGFwYSwgcmVtb3ZpIG9zIHRlcm1vcyBxdWUgdGluaGFtIGZyZXF1w6puY2lhIG11aXRvIGJhaXhhIGUgYXRyYXBhbGhhdmFtIGEgYW7DoWxpc2UuKiANCipDb25zZWd1aW1vcyBvYnNlcnZhciBxdWUgbyogYE1heGltYWwgdGVybSBsZW5ndGggZXJhIDI0NCBlIGZvaSByZWR1emlkbyBwYXJhIDE4YCANCmBgYHtyfQ0KZmFudGFzdGljb19kdG1zIDwtIHJlbW92ZVNwYXJzZVRlcm1zKGZhbnRhc3RpY29fZHRtLCAwLjk4KSANCmZhbnRhc3RpY29fZHRtcw0KYGBgDQoqTmEgc2VxdcOqbmNpYSBldSByZWNyaWVpIGEgZnJlcXXDqm5jaWEgY29tIG9zIHRlcm1vcyB0cmF0YWRvcyBjb20gYSBxdWFudGlkYWRlIGRlIDM2LiAgKg0KYGBge3J9DQpmYW50YXN0aWNvX2ZyZXF1ZW5jaWEgPC0gY29sU3Vtcyhhcy5tYXRyaXgoZmFudGFzdGljb19kdG1zKSkgICANCmxlbmd0aChmYW50YXN0aWNvX2ZyZXF1ZW5jaWEpIA0KDQpmYW50YXN0aWNvX2ZyZXF1ZW5jaWEgPC0gc29ydChjb2xTdW1zKGFzLm1hdHJpeChmYW50YXN0aWNvX2ZyZXF1ZW5jaWEpKSwgZGVjcmVhc2luZz1UUlVFKSANCmZhbnRhc3RpY29fZnJlcXVlbmNpYQ0KYGBgDQojIyMgTWF0cml6IGUgRGF0YS5GcmFtZQ0KKkNvbnZlcnRlbmRvIGEgbWF0cml6IGVtIHVtIGRhdGEuZnJhbWUqDQpgYGB7cn0NCmZhbnRhc3RpY29fcGxvdCA8LSBkYXRhLmZyYW1lKHdvcmQ9bmFtZXMoZmFudGFzdGljb19mcmVxdWVuY2lhKSwgZnJlcT1mYW50YXN0aWNvX2ZyZXF1ZW5jaWEpICANCmBgYA0KIyMjIFZpc3VhbGl6YcOnw6NvIA0KKk5lc3NhIGV0YXBhLCB2YW1vcyBwbG90YXIgYWxndW5zIGdyw6FmaWNvcyBlIGNvbnRpbnVhciBhIGxpbXBlemEgZGFzIHBhbGF2cmFzLioNCipTZWxlY2lvbmVpIHF1ZSBhIHBhbGF2cmEgdGl2ZXNzZSB1bWEgZnJlcXXDqm5jaWEgZGUgbWFpb3IgcXVlIDIwMCBwYXJhIGFwYXJlY2VyIG5vIGdyw6FmaWNvKg0KDQpgYGB7ciwgaW5jbHVkZSA9IEZBTFNFfQ0KZ3JhZmljbyA8LSBnZ3Bsb3Qoc3Vic2V0KGZhbnRhc3RpY29fcGxvdCAsIGZhbnRhc3RpY29fZnJlcXVlbmNpYT4yMDApLCBhZXMoeCA9IHJlb3JkZXIod29yZCwgLWZyZXEpLCB5ID0gZnJlcSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsgDQogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSkpICsNCiAgZ2d0aXRsZSgiR3JhZmljbyBkZSBiYXJyYXMgY29tIG9zIHRlcm1vcyBtYWlzIGZyZXF1ZW50ZXMiKSArDQogIGxhYnMoeT0iRnJlcXVlbmNpYSIsIHggPSAiVGVybW9zIikNCmBgYA0KYENvbnNlZ3VpbW9zIG9ic2VydmFyIHF1ZSBhaW5kYSBleGlzdGVtIG11aXRhcyBwYWxhdnJhcyBxdWUgc8OjbyBpcnJlbGV2YW50ZXMgcGFyYSBhIGFuw6FsaXNlLGANCmBhIHNlZ3VpciB2YW1vcyBmYXplciBvIHRyYXRhbWVudG8gZGVzc2FzIHBhbGF2cmFzYA0KYGBge3J9DQpncmFmaWNvICAgDQpgYGANCg0KDQojIyMgw5psdGltbyB0cmF0YW1lbnRvIA0KKlJlbW92ZW5kbyBhcyBwYWxhdnJhcyBxdWUgc3VqYW0gYSBhbmFsaXNlIGUgdGFtYsOpbSBhcyBwYWxhdnJhcyBxdWUgc8OjbyDDs2J2aWFzKg0KYGBge3IsIH0NCmZhbnRhc3RpY29fdGV4dF9jb3JwdXMgPC0gdG1fbWFwKGZhbnRhc3RpY29fdGV4dF9jb3JwdXMsIHJlbW92ZVdvcmRzLGMoImNvbnRyYSIsImFxdWkiLCJmYWxhciIsImZhemVyIiwgInNvYnJlIiwgImFpbmRhIiwiYmVtIiwidHVkbyIsImZhbGFyIiwgImZhbnRhc3RpY28iLCJmYW50w6FzdGljbyIsInByYSIsInNlciIsInZhaSIsICJnbG9ibyIsImFnb3JhIiwidGVyIiwgIm5hZGEiLCJkb21pbmdvZXNwZXRhY3VsYXIiLCJiZSIsInZlciIsInNvYnJlIiwiY2FyYSIsImFpbmRhIiwiYmVtIiwidHVkbyIsImRlc3NlIikpDQpmYW50YXN0aWNvX2R0bXMgPC0gcmVtb3ZlU3BhcnNlVGVybXMoRG9jdW1lbnRUZXJtTWF0cml4KGZhbnRhc3RpY29fdGV4dF9jb3JwdXMpICwgMC45OCkgDQpmYW50YXN0aWNvX2R0bXMNCmBgYA0KPGJyPg0KKlJldG9ybmFuZG8gcGFyYSBtYXRyaXoqDQpgYGB7cn0NCmZhbnRhc3RpY29fZnJlcXVlbmNpYSA8LSBjb2xTdW1zKGFzLm1hdHJpeChmYW50YXN0aWNvX2R0bXMpKSAgIA0KbGVuZ3RoKGZhbnRhc3RpY29fZnJlcXVlbmNpYSkgDQpgYGANCg0KKlZpc3VhbGl6YW5kbyBhIGZyZW5xdcOqbmNpYSBkYXMgcGFsYXZyYXMuKg0KYGBge3J9DQpmYW50YXN0aWNvX2ZyZXF1ZW5jaWEgPC0gc29ydChjb2xTdW1zKGFzLm1hdHJpeChmYW50YXN0aWNvX2R0bXMpKSwgZGVjcmVhc2luZz1UUlVFKSANCmZhbnRhc3RpY29fZnJlcXVlbmNpYQ0KYGBgDQoNCipDb252ZXJ0ZW5kbyBhIG1hdHJpeiBkZSBmcmVxdcOqbmNpYSBlbSBkYXRhZnJhbWUgZSBtb3N0cmFuZG8gZW0gZm9ybWF0byBkZSB0YWJlbGEuKg0KYGBge3J9IA0KZmFudGFzdGljb19wbG90IDwtIGRhdGEuZnJhbWUod29yZD1uYW1lcyhmYW50YXN0aWNvX2ZyZXF1ZW5jaWEpLCBmcmVxPWZhbnRhc3RpY29fZnJlcXVlbmNpYSkgIA0KZmFudGFzdGljb19wbG90DQpgYGANCg0KIyMjIFVsdGltYXMgVmlzdWFsaXphw6fDtWVzIA0KKk5vIGdyw6FmaWNvIGFiYWl4bywgb3JnYW5pemVpIGFzIHBhbGF2cmFzIGNvbSBtYWlvciBmcmVxdcOqbmNpYSBkZXBvaXMgZGUgYXBsaWNhZG8gbyB0cmF0YW1lbnRvIGRlIHJldGlyYXIgYXMgcGFsYXZyYXMgaXJyZWxldmFudGVzLiBDb25zZWd1aW1vcyBvYnNlcnZhciBhIGRpZmVyZW7Dp2EgZW50cmUgb3MgZG9pcyBncsOhZmljb3MgZGUgYmFycmEqDQpgYGB7cn0NCmdyYWZpY28gPC0gZ2dwbG90KHN1YnNldChmYW50YXN0aWNvX3Bsb3QsIGZhbnRhc3RpY29fZnJlcXVlbmNpYT4xMCksIGFlcyh4ID0gcmVvcmRlcih3b3JkLCAtZnJlcSksIHkgPSBmcmVxKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyANCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSkgKw0KICBnZ3RpdGxlKCJHcmFmaWNvIGRlIGJhcnJhcyBjb20gb3MgdGVybW9zIG1haXMgZnJlcXVlbnRlcyIpICsNCiAgbGFicyh5PSJGcmVxdWVuY2lhIiwgeCA9ICJUZXJtb3MiKQ0KZ3JhZmljbyAgIA0KYGBgDQojIyMgTnV2ZW0gZGUgcGFsYXZyYXMNCg0KKkRlcG9pcyBkZSB0b2RvcyBvcyB0cmF0YW1lbnRvcywgYSBudXZlbSBkZSBwYWxhdnJhIGZpY2EgbXVpdG8gbWFpcyBsaW1wYSwgZSBhc3NpbSBjb25zZWd1aW1vcyB0ZXIgdW1hIG1lbGhvcmUgdmlzdWFsaXphw6fDo28gZG9zIHRlcm1vcyBtYWlzIGZyZXF1ZW50ZXMuKiAgIA0KYGBge3J9DQp3b3JkY2xvdWQobmFtZXMoZmFudGFzdGljb19mcmVxdWVuY2lhKSxmYW50YXN0aWNvX2ZyZXF1ZW5jaWEsbWluLmZyZXE9MixtYXgud29yZHM9MTUwLCByYW5kb20ub3JkZXI9VCwgY29sb3JzPWZvcm1hdGFjYW8pDQpgYGANCg0KIyMjIENsdXN0ZXJpbmcgLSBEZW5kb2dyYW1hDQoqQXBsaWNhbmRvKiBgcmVtb3ZlU3BhcnNlVGVybXNgICpwYXJhIHRyYXplciB1bSBjbHVzdGVyIG1haXMgbGltcG8gcXVlIGZpcXVlIGRlIHVtYSBmb3JtYSBtYWlzIGZhY2lsIGRlIHZpc3VhbGl6YXIuKiANCmBgYHtyfQ0KZmFudGFzdGljb19kdG1zMiA8LSByZW1vdmVTcGFyc2VUZXJtcyhmYW50YXN0aWNvX2R0bXMsIDAuOTgpDQpmYW50YXN0aWNvX2R0bXMyDQpgYGANCg0KDQoqQSBpZMOpaWEgZG8gZGVuZG9ncmFtYSDDqSB0cmF6ZXIgZW0gcXVhbCBjbHVzdGVyIGVzdMOjbyBhcyBwYWxhdnJhcyBlIHF1YWwgYSBmb3LDp2EgZGUgcmVsYWNpb25hbWVudG8gZW50cmUgZWxhcyo8YnI+DQoqRXg6w6kgYSBwYWxhdnJhIHByaW5jaXBhbCDDqSBHZW50ZSwgcXVhaXMgY2x1c3RlcnMgZGVyaXZhbSBkZXNzYSBwYWxhdnJhPyogDQoNCmBgYHtyfSANCmRpc3RhbmNpYSA8LSBkaXN0KHQoZmFudGFzdGljb19kdG1zMiksIG1ldGhvZD0iZXVjbGlkaWFuIikgICANCmRlbmRvZ3JhbWEgPC0gaGNsdXN0KGQ9ZGlzdGFuY2lhLCBtZXRob2Q9ImNvbXBsZXRlIikNCnBsb3QoZGVuZG9ncmFtYSwgaGFuZz0tMSxtYWluID0gIkRlbmRvZ3JhbWEgVHdlZXRzIiwNCiAgICAgeGxhYiA9ICJEaXN0YW5jaWEiLA0KICAgICB5bGFiID0gIkFsdHVyYSIpDQpncm91cHMgPC0gY3V0cmVlKGRlbmRvZ3JhbWEsIGs9NCkNCnJlY3QuaGNsdXN0KGRlbmRvZ3JhbWEsIGs9NCwgYm9yZGVyPSJyZWQiKQ0KDQpgYGANCg0KPGJyPjxicj4NCg0KIyMjIENvbmNsdXPDo28NCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGp1c3RpZnkiPg0KKlTDqWNuaWNhcyBkZSBhbsOhbGlzZSBkZSB0ZXh0b3MgcG9kZW0gc2VyIHV0aWxpemFkYXMgZGUgbXVpdGFzIGZvcm1hcywgbmVzc2EgYW7DoWxpc2UgZXUgc2VwYXJlaSBhcGVuYXMgYWxndW5zIHRyYXRhbWVudG9zIHF1ZSBwb2RlbSBzZXIgZmVpdG9zIGUgY29tbyBhbmFsaXNhciBvIGNvbXBvcnRhbWVudG8gZGFzIHBlc3NvYXMuIMOJIGRlIGV4dHJlbWEgaW1wb3J0w6JuY2lhIGVzdGFybW9zIG1vbml0b3JhbmRvIGFzIHJlZGVzIHBhcmEgZGVmaW5pciBxdWFpcyBlc3RyYXTDqWdpYXMgZGV2ZW0gc2VyIHRvbWFkYXMgZSBxdWFsIG1vbWVudG8gcXVlIHNlIGRldmUgZmFsYXIgbWFpcyBkZSBkZXRlcm1pbmFkbyBhc3N1bnRvLiBNdWl0YXMgdmV6ZXMgdGVtb3MgYSBpbXByZXNzw6NvIGRlIHF1ZSBhcyByZWRlcyBzb2NpYWlzIGVzdMOjbyBkaXplbmRvIHVtYSBjb2lzYSwgbWFzIGVsYXMgcG9kZW0gZXN0YXIgZGl6ZW5kbyBvdXRyYSBjb21wbGV0YW1lbnRlIGRpZmVyZW50ZSwgZXNzYSB2aXPDo28gcG9kZSBzZXIgZGV2aWRvIGFzIG5vc3NhcyByZWRlcyBqw6EgZXN0YXJlbSBlbnZpZXNhZGFzIGUgc8OzIGNvbnNlZ3VpbW9zIHZlciBkZW50cm8gZGEgbm9zc2EgYm9saGEgZGUgcmVsYWNpb25hbWVudG8uIE9saGFyIGFzIHJlZGVzIHNvY2lhaXMgZGUgdW1hIGZvcm1hICJNYWNybyIgZSBuw6NvIG1pY3JvIG91IHNlZ21lbnRhZGEsIHRyYXogdW1hIHZpc8OjbyBtYWlzIHTDqWNuaWNhIGUgb2JqZXRpdmEgZSB1bWEgZmVycmFtZW50YSBwb2Rlcm9zYSBuYXMgZXN0cmF0w6lnaWFzIGRlIHVtYSBlbXByZXNhLio8YnI+DQoqQWdvcmEgbWUgZGl6LCBvIHF1w6NvIGltcG9ydGFudGUgc2VyaWEgZXNzYSB0w6ljbmljYSBuYSBlc3RyYXTDqWdpYSBkZSBtYXJrZXRpbmcgZSB2ZW5kYXMgZGEgc3VhIGVtcHJlc2E/ICoNCg0KPGJyPg0KKkJsb2c6IGh0dHBzOi8vZGlhc2NvZGVzLm1lZGl1bS5jb20vKiA8YnI+DQoqTGlua2VkaW46IGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9pbi9nYWJyaWVsZGlhc2Rlb2xpdmVpcmEvKjxicj4NCg==