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)
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==