Encoding to UTF-8
Sys.setlocale(category = "LC_ALL", locale = "zh_TW.UTF-8")
[1] "zh_TW.UTF-8/zh_TW.UTF-8/zh_TW.UTF-8/C/zh_TW.UTF-8/zh_TW.UTF-8"



Install essential package
packages = c("dplyr", "tidytext", "stringr", "wordcloud2", "ggplot2",'readr','data.table','reshape2','wordcloud','tidyr','scales','rvest','magrittr','RCurl','XML','slam')
existing = as.character(installed.packages()[,1])
for(pkg in packages[!(packages %in% existing)]) install.packages(pkg)



Loading library
library(dplyr)
library(magrittr)
library(ggplot2)
library(wordcloud)
library(scales)
library(readr)
library(jiebaR)



Loading data (mobile01)
P <- read_csv("/Volumes/GoogleDrive/Team\ Drives/THESIS/案例構思/巨力搬家/Data\ Collection/爬蟲資料/interview/MHinterview.csv")
Parsed with column specification:
cols(
  artTitle = col_character(),
  artDate = col_date(format = ""),
  artTime = col_time(format = ""),
  artUrl = col_character(),
  artContent = col_character()
)
P$text = P$artContent
Loading JiebaR package and setup stop words dictionary
library(jiebaR)
userwd = c("搬家公司","崔媽媽","康福","巨力","大吉旺","搬家","乙久利","康福搬家","巨力搬家","崔媽媽基金會","不加價","不亂加價","崔媽媽網站","舊傢俱","農民曆","風水","時辰")
cc = worker()
new_user_word(cc,userwd,tags=rep('n',length(userwd)))
[1] TRUE
stopwd = c(readLines("/Volumes/GoogleDrive/Team\ Drives/THESIS/案例構思/巨力搬家/Data\ Collection/爬蟲資料/dict/stop_words.txt",encoding="UTF-8"),
           "真的","com","XD","imgur","jpg","www","http","i",
           "html","bbs","請問","https","po","ptt","cc","Contacts",
           "文章","謝謝","之前","網址","想說","知道","問題",
           "一下","現在","後","再","人","喔","分享","有點","最近",
           "推薦","好像","應該","太","放","已經","看看",
           "看到","  一直","發現","推","這款","耶","今天","之後",
           "超","一點","小","原","有沒有","建議","一個","找",
           "戴","買","好","比較","覺得","說","想","真的","可能",
           "就是","因為","所以","如果","也是","一個","真的","後來",
           "時","完","幫","先","搬","請","一車","參考","一次","一台",
           "一些","一家","一趟","兩次","一定","這是","這家","至少",
           "寫","所有","搬過","本來","是否","前","噸","一直","約","元",
           "月","台北","台南","這次","中","台","算","吋","次","公",
           "最","家","高","當時","免","問","囉","無","找過","記得",
           "辦法","順利","部分","那種","感謝","幾次","送","整個",
           "新竹","有人","只能","只","做","不知","OK","台中","我家",
           "不到","還要","開","走","點","府","估","真是","這種",
           "不用","直接","還會","公司","錢","車","原本","載","舊",
           "當初","當天","最後","下","已","一人","一間","事情","地方",
           "台南","搬運","搬到","需要","無法","改","以上","兩個","X",
           "最好","要求","一起","老闆","幾個","放在","給我","去年",
           "感覺","事","卻","找到","以後","希望","重點","給你","還好",
           "遇到","通常","這間","上次","家裡","回頭","剩下","桃園",
           "縣市","高雄","完全","阿姨","選擇","像是","不錯","方面","裡面",
           "第五次","主要","住","歲","花","B","算是","收","就要","兩三個",
           "能夠","再來","相關","不想","男朋友","寄","男","感到","認為","崁",
           "年","一天","用到","過去","想要","今年","很大","這裡","繼續","箱",
           "之外","求","整體而言","進行","原先","一個月","南","左右","回去",
           "我要","板橋","説","第一次","家樂福","挑","一塊","最大","搬出去",
           "上面","透過","巨力搬家","巨力","原因","來說","打開","有太多","過來",
           "妹妹","智慧","box","輸入","傳統","中繼站","信義","子","不收",
           "有時候","是從","小東西")
於 '/Volumes/GoogleDrive/Team Drives/THESIS/案例構思/巨力搬家/Data Collection/爬蟲資料/dict/stop_words.txt' 找到不完整的最後一列



Descriptive Statistics



Select artDate and change format
P$artDate= P$artDate %>% as.Date("%Y/%m/%d")
data$artDate= data$artDate %>% as.Date("%Y/%m/%d")
data = P %>% dplyr::select(artDate)



Grouping date
data <- data %>% 
  group_by(artDate) %>% 
  summarise(count = n())



Line graph of articles
plot_date <- data %>% ggplot(aes(x = artDate, y = count)) +
  geom_line(color = "#00AFBB", size = 1) + 
  scale_x_date(labels = date_format("%Y/%m/%d")) +
  ggtitle("搬家-討論文章數(Mobile01)") + 
  xlab("Date") + 
  ylab("Count") + 
  theme(text = element_text(family = "Heiti TC Light")) 

plot_date



Barplot (num of words)
library(slam); library(tm); library(tmcn); library(rJava); library(SnowballC); library(jiebaR)

ii = jj = vv =NULL
for(i in 1:length(P$text)) {
  x = segment(P$text[i], cc)
  x = x[! grepl("[0-9]+",x)]
  x = table(x[! x %in% stopwd])
  ii = c(ii, rep(i,length(x)))
  jj = c(jj, names(x))
  vv = c(vv, as.vector(x))
}
jj = as.factor(jj)

l = levels(jj)
dtm = simple_triplet_matrix(ii,as.integer(jj),vv,
             dimnames=list(as.character(1:length(P$text)),l))
dim(dtm)
[1]    9 1265
save(dtm, file="MHmb01.rdata")
dtm = dtm[, order(col_sums(dtm), decreasing=T)]
col_sums(dtm)[1:40] %>% barplot(las=2, family = "Heiti TC Light")



Hierarchical Clusters (binary distance)
library(MASS)
library(wordcloud)
colors = c('gold','purple','cyan','red','orange3','gray',
           'pink','green','darkgreen','blue','brown','magenta','deepskyblue3')

n = 200; a = 5
bd = dist(t(dtm[,a:n]),method="binary")
# bd = dist(t(dtm[,a:n]))
mds =  isoMDS(bd + 10^(-6))
initial  value 35.255153 
final  value 35.255153 
converged
hc = hclust(bd,method="ward.D2")
plot(hc, family = "Heiti TC Light") 


k=12
plot(hc,cex=0.7,main="Hierarchical Clusters (Binary Distance)",
     sub="",ylab="",xlab="Jaccard (Binary) Distance",
     cex.axis=0.6,cex.lab=0.8,cex.main=1, family = "Heiti TC Light")
rect.hclust(hc, k=k, border="pink")



Word Cloud
gp = cutree(hc, k=k); table(gp)
gp
 1  2  3  4  5  6  7  8  9 10 11 12 
24 12 15 17 24 18 19 21 14 12 10 10 
wc = col_sums(dtm[,a:n])
p0 = par(mar=c(1,1,1,1))
textplot(mds$points[,1],mds$points[,2],colnames(dtm)[a:n],
         show=F, col=colors[gp],cex=1.5*sqrt(wc/mean(wc)),
         font=2,axes=F, family = "Microsoft JhengHei"); par(p0)



### Sentiment Analysis

Loading Chinese Texting needed packages
# install.packages('chinese.misc')
library(chinese.misc)
library(tm)
library(jiebaR)
library(Matrix)
library(readr)
library(tidytext)
library(tidyr)



Change the format of the dataset
P$artContent = as.character(P$artContent)
P$text = as.character(P$text)
P$artDate = as.Date(P$artDate)



Loading customize dict in Jieba
jieba_tokenizer <- worker(user="dict/MH_words.dict")



##### Segmentation

# Setup segment function
MH_tokenizer <- function(t) {
  lapply(t, function(x) {
    tokens <- segment(x, jieba_tokenizer)
    return(tokens)
  })
}

tokens = P %>% 
  unnest_tokens(word, artContent, token = MH_tokenizer)



Count for the amount of words in corpus

tokens = tokens %>%
  dplyr::select(artDate, word) %>%
  group_by(artDate, word) %>%
  mutate(count = n()) %>%
  ungroup() %>%
  distinct() # 己經統計過數量;去除重複資料

tokens



LIWC dict (positive, negative)
p <- read_file("/Volumes/GoogleDrive/Team\ Drives/THESIS/案例構思/巨力搬家/Data\ Collection/爬蟲資料/dict/MH_positive.txt")
n <- read_file("/Volumes/GoogleDrive/Team\ Drives/THESIS/案例構思/巨力搬家/Data\ Collection/爬蟲資料/dict/MH_negative.txt")
positive <- strsplit(p, "[,]")[[1]]
negative <- strsplit(n, "[,]")[[1]]
positive <- data.frame(word = positive, sentiments = "positive")
negative <- data.frame(word = negative, sentiemtns = "negative")
colnames(negative) = c("word","sentiment")
colnames(positive) = c("word","sentiment")
LIWC_ch <- rbind(positive, negative) %>% distinct()

LIWC_ch



Join corpus with LIWC (ot make sure the word is belongs to positive or negative)
senti_tokens = tokens %>% inner_join(LIWC_ch) 
Joining, by = "word"
Column `word` joining character vector and factor, coercing into character vector
head(senti_tokens) 



Find out all date in time period
all_dates <- 
  expand.grid(seq(as.Date(min(data$artDate)), as.Date(max(data$artDate)), by="day"), c("positive", "negative"))
head(all_dates)



Line chart of sentiment (positive, negative)

senti_tokens$artDate = as.Date(senti_tokens$artDate)
# head(senti_tokens)        artTitle, artDate, artTime, artUrl, text, word, sentiment
# head(LIWC_ch)             word, sentiment
plot_table <- senti_tokens %>%
  inner_join(LIWC_ch) %>% 
  group_by(artDate,sentiment) %>%
  summarise(count = n())
Joining, by = c("word", "sentiment")
Column `word` joining character vector and factor, coercing into character vector
plot_table %>%
  ggplot() +
  geom_line(aes(x = artDate, y = count, colour = sentiment)) +
  scale_x_date(labels = date_format("%Y/%m/%d")) +
  xlab("Date") + ylab("Count")



Common sentiment words in LIWC dict (positive, negative)
tokens %>% 
  inner_join(LIWC_ch) %>% 
  group_by(sentiment) %>%
  count(word) %>%
  ggplot(aes(word, n, fill = sentiment)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ sentiment, scales = "free_y") +
  labs(y = "Contribution to sentiment",
       x = NULL) +
  theme(text=element_text(size=11)) +
  coord_flip() + 
  theme(text = element_text(family = "Heiti TC Light")) 
Joining, by = "word"
Column `word` joining character vector and factor, coercing into character vector



LS0tCnRpdGxlOiAi5Y+w54Gj5pCs5a6255Si5qWt5paH5a2X5YiG5p6Q77yI5rex5bqm6Kiq6KuH77yJLyBUZXh0IE1pbmluZyBvZiBNb3ZpbmcgSW5kdXN0cnkgaW4gVGFpd2FuIChJbnRlcnZpZXcpIgphdXRob3I6ICJLYXJlbiBZYW5nIOaliuWHseWAqyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKPGJyPgo8YnI+CgorIENvcnB1cyBUeXBlOiBJbnRlcnZpZXcgKHNvbWVvbmUgd2hvIGhhcyBleHBlcmllbmNlIGluIG1vdmluZyBob21lKQorIFRpbWUgUGVyaW9kOiAyMDE5LzA0LzI3IC0gMjAxOS8wNi8wMgorIE51bWJlciBvZiBjb3JwdXM6IDkKCjxicj4KPGJyPgoKIyMjIyMgRW5jb2RpbmcgdG8gVVRGLTgKYGBge3J9ClN5cy5zZXRsb2NhbGUoY2F0ZWdvcnkgPSAiTENfQUxMIiwgbG9jYWxlID0gInpoX1RXLlVURi04IikKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIEluc3RhbGwgZXNzZW50aWFsIHBhY2thZ2UKYGBge3J9CnBhY2thZ2VzID0gYygiZHBseXIiLCAidGlkeXRleHQiLCAic3RyaW5nciIsICJ3b3JkY2xvdWQyIiwgImdncGxvdDIiLCdyZWFkcicsJ2RhdGEudGFibGUnLCdyZXNoYXBlMicsJ3dvcmRjbG91ZCcsJ3RpZHlyJywnc2NhbGVzJywncnZlc3QnLCdtYWdyaXR0cicsJ1JDdXJsJywnWE1MJywnc2xhbScpCmV4aXN0aW5nID0gYXMuY2hhcmFjdGVyKGluc3RhbGxlZC5wYWNrYWdlcygpWywxXSkKZm9yKHBrZyBpbiBwYWNrYWdlc1shKHBhY2thZ2VzICVpbiUgZXhpc3RpbmcpXSkgaW5zdGFsbC5wYWNrYWdlcyhwa2cpCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBMb2FkaW5nIGxpYnJhcnkKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh3b3JkY2xvdWQpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGppZWJhUikKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIExvYWRpbmcgZGF0YSAobW9iaWxlMDEpCmBgYHtyfQpQIDwtIHJlYWRfY3N2KCIvVm9sdW1lcy9Hb29nbGVEcml2ZS9UZWFtXCBEcml2ZXMvVEhFU0lTL+ahiOS+i+ani+aAnS/lt6jlipvmkKzlrrYvRGF0YVwgQ29sbGVjdGlvbi/niKzon7Los4fmlpkvaW50ZXJ2aWV3L01IaW50ZXJ2aWV3LmNzdiIpClAkdGV4dCA9IFAkYXJ0Q29udGVudApgYGAKCgoKIyMjIyMgTG9hZGluZyBKaWViYVIgcGFja2FnZSBhbmQgc2V0dXAgc3RvcCB3b3JkcyBkaWN0aW9uYXJ5CmBgYHtyfQpsaWJyYXJ5KGppZWJhUikKdXNlcndkID0gYygi5pCs5a625YWs5Y+4Iiwi5bSU5aq95aq9Iiwi5bq356aPIiwi5beo5YqbIiwi5aSn5ZCJ5pe6Iiwi5pCs5a62Iiwi5LmZ5LmF5YipIiwi5bq356aP5pCs5a62Iiwi5beo5Yqb5pCs5a62Iiwi5bSU5aq95aq95Z+66YeR5pyDIiwi5LiN5Yqg5YO5Iiwi5LiN5LqC5Yqg5YO5Iiwi5bSU5aq95aq957ay56uZIiwi6IiK5YKi5L+xIiwi6L6y5rCR5puGIiwi6aKo5rC0Iiwi5pmC6L6wIikKY2MgPSB3b3JrZXIoKQpuZXdfdXNlcl93b3JkKGNjLHVzZXJ3ZCx0YWdzPXJlcCgnbicsbGVuZ3RoKHVzZXJ3ZCkpKQoKc3RvcHdkID0gYyhyZWFkTGluZXMoIi9Wb2x1bWVzL0dvb2dsZURyaXZlL1RlYW1cIERyaXZlcy9USEVTSVMv5qGI5L6L5qeL5oCdL+W3qOWKm+aQrOWuti9EYXRhXCBDb2xsZWN0aW9uL+eIrOifsuizh+aWmS9kaWN0L3N0b3Bfd29yZHMudHh0IixlbmNvZGluZz0iVVRGLTgiKSwKICAgICAgICAgICAi55yf55qEIiwiY29tIiwiWEQiLCJpbWd1ciIsImpwZyIsInd3dyIsImh0dHAiLCJpIiwKICAgICAgICAgICAiaHRtbCIsImJicyIsIuiri+WVjyIsImh0dHBzIiwicG8iLCJwdHQiLCJjYyIsIkNvbnRhY3RzIiwKICAgICAgICAgICAi5paH56ugIiwi6Kyd6KydIiwi5LmL5YmNIiwi57ay5Z2AIiwi5oOz6KqqIiwi55+l6YGTIiwi5ZWP6aGMIiwKICAgICAgICAgICAi5LiA5LiLIiwi54++5ZyoIiwi5b6MIiwi5YaNIiwi5Lq6Iiwi5ZaUIiwi5YiG5LqrIiwi5pyJ6bueIiwi5pyA6L+RIiwKICAgICAgICAgICAi5o6o6JamIiwi5aW95YOPIiwi5oeJ6KmyIiwi5aSqIiwi5pS+Iiwi5bey57aTIiwi55yL55yLIiwKICAgICAgICAgICAi55yL5YiwIiwiICDkuIDnm7QiLCLnmbznj74iLCLmjqgiLCLpgJnmrL4iLCLogLYiLCLku4rlpKkiLCLkuYvlvowiLAogICAgICAgICAgICLotoUiLCLkuIDpu54iLCLlsI8iLCLljp8iLCLmnInmspLmnIkiLCLlu7rorbAiLCLkuIDlgIsiLCLmib4iLAogICAgICAgICAgICLmiLQiLCLosrciLCLlpb0iLCLmr5TovIMiLCLoprrlvpciLCLoqqoiLCLmg7MiLCLnnJ/nmoQiLCLlj6/og70iLAogICAgICAgICAgICLlsLHmmK8iLCLlm6DngroiLCLmiYDku6UiLCLlpoLmnpwiLCLkuZ/mmK8iLCLkuIDlgIsiLCLnnJ/nmoQiLCLlvozkvoYiLAogICAgICAgICAgICLmmYIiLCLlrowiLCLluasiLCLlhYgiLCLmkKwiLCLoq4siLCLkuIDou4oiLCLlj4PogIMiLCLkuIDmrKEiLCLkuIDlj7AiLAogICAgICAgICAgICLkuIDkupsiLCLkuIDlrrYiLCLkuIDotp8iLCLlhanmrKEiLCLkuIDlrpoiLCLpgJnmmK8iLCLpgJnlrrYiLCLoh7PlsJEiLAogICAgICAgICAgICLlr6siLCLmiYDmnIkiLCLmkKzpgY4iLCLmnKzkvoYiLCLmmK/lkKYiLCLliY0iLCLlmbgiLCLkuIDnm7QiLCLntIQiLCLlhYMiLAogICAgICAgICAgICLmnIgiLCLlj7DljJciLCLlj7DljZciLCLpgJnmrKEiLCLkuK0iLCLlj7AiLCLnrpciLCLlkIsiLCLmrKEiLCLlhawiLAogICAgICAgICAgICLmnIAiLCLlrrYiLCLpq5giLCLnlbbmmYIiLCLlhY0iLCLllY8iLCLlm4kiLCLnhKEiLCLmib7pgY4iLCLoqJjlvpciLAogICAgICAgICAgICLovqbms5UiLCLpoIbliKkiLCLpg6jliIYiLCLpgqPnqK4iLCLmhJ/orJ0iLCLlub7mrKEiLCLpgIEiLCLmlbTlgIsiLAogICAgICAgICAgICLmlrDnq7kiLCLmnInkuroiLCLlj6rog70iLCLlj6oiLCLlgZoiLCLkuI3nn6UiLCJPSyIsIuWPsOS4rSIsIuaIkeWutiIsCiAgICAgICAgICAgIuS4jeWIsCIsIumChOimgSIsIumWiyIsIui1sCIsIum7niIsIuW6nCIsIuS8sCIsIuecn+aYryIsIumAmeeoriIsCiAgICAgICAgICAgIuS4jeeUqCIsIuebtOaOpSIsIumChOacgyIsIuWFrOWPuCIsIumMoiIsIui7iiIsIuWOn+acrCIsIui8iSIsIuiIiiIsCiAgICAgICAgICAgIueVtuWInSIsIueVtuWkqSIsIuacgOW+jCIsIuS4iyIsIuW3siIsIuS4gOS6uiIsIuS4gOmWkyIsIuS6i+aDhSIsIuWcsOaWuSIsCiAgICAgICAgICAgIuWPsOWNlyIsIuaQrOmBiyIsIuaQrOWIsCIsIumcgOimgSIsIueEoeazlSIsIuaUuSIsIuS7peS4iiIsIuWFqeWAiyIsIu+8uCIsCiAgICAgICAgICAgIuacgOWlvSIsIuimgeaxgiIsIuS4gOi1tyIsIuiAgemXhiIsIuW5vuWAiyIsIuaUvuWcqCIsIue1puaIkSIsIuWOu+W5tCIsCiAgICAgICAgICAgIuaEn+imuiIsIuS6iyIsIuWNuyIsIuaJvuWIsCIsIuS7peW+jCIsIuW4jOacmyIsIumHjem7niIsIue1puS9oCIsIumChOWlvSIsCiAgICAgICAgICAgIumBh+WIsCIsIumAmuW4uCIsIumAmemWkyIsIuS4iuasoSIsIuWutuijoSIsIuWbnumgrSIsIuWJqeS4iyIsIuahg+WckiIsCiAgICAgICAgICAgIue4o+W4giIsIumrmOmbhCIsIuWujOWFqCIsIumYv+WnqCIsIumBuOaThyIsIuWDj+aYryIsIuS4jemMryIsIuaWuemdoiIsIuijoemdoiIsCiAgICAgICAgICAgIuesrOS6lOasoSIsIuS4u+imgSIsIuS9jyIsIuatsiIsIuiKsSIsIkIiLCLnrpfmmK8iLCLmlLYiLCLlsLHopoEiLCLlhankuInlgIsiLAogICAgICAgICAgICLog73lpKAiLCLlho3kvoYiLCLnm7jpl5wiLCLkuI3mg7MiLCLnlLfmnIvlj4siLCLlr4QiLCLnlLciLCLmhJ/liLAiLCLoqo3ngroiLCLltIEiLAogICAgICAgICAgICLlubQiLCLkuIDlpKkiLCLnlKjliLAiLCLpgY7ljrsiLCLmg7PopoEiLCLku4rlubQiLCLlvojlpKciLCLpgJnoo6EiLCLnubznuowiLCLnrrEiLAogICAgICAgICAgICLkuYvlpJYiLCLmsYIiLCLmlbTpq5TogIzoqIAiLCLpgLLooYwiLCLljp/lhYgiLCLkuIDlgIvmnIgiLCLljZciLCLlt6blj7MiLCLlm57ljrsiLAogICAgICAgICAgICLmiJHopoEiLCLmnb/mqYsiLCLoqqwiLCLnrKzkuIDmrKEiLCLlrrbmqILnpo8iLCLmjJEiLCLkuIDloYoiLCLmnIDlpKciLCLmkKzlh7rljrsiLAogICAgICAgICAgICLkuIrpnaIiLCLpgI/pgY4iLCLlt6jlipvmkKzlrrYiLCLlt6jlipsiLCLljp/lm6AiLCLkvoboqqoiLCLmiZPplosiLCLmnInlpKrlpJoiLCLpgY7kvoYiLAogICAgICAgICAgICLlprnlprkiLCLmmbrmhaciLCJib3giLCLovLjlhaUiLCLlgrPntbEiLCLkuK3nubznq5kiLCLkv6HnvqkiLCLlrZAiLCLkuI3mlLYiLAogICAgICAgICAgICLmnInmmYLlgJkiLCLmmK/lvp4iLCLlsI/mnbHopb8iKQpgYGAKCgo8YnI+Cjxicj4KCgojIyMgRGVzY3JpcHRpdmUgU3RhdGlzdGljcwoKPGJyPgo8YnI+CgojIyMjIyBTZWxlY3QgYXJ0RGF0ZSBhbmQgY2hhbmdlIGZvcm1hdApgYGB7cn0KUCRhcnREYXRlPSBQJGFydERhdGUgJT4lIGFzLkRhdGUoIiVZLyVtLyVkIikKZGF0YSRhcnREYXRlPSBkYXRhJGFydERhdGUgJT4lIGFzLkRhdGUoIiVZLyVtLyVkIikKZGF0YSA9IFAgJT4lIGRwbHlyOjpzZWxlY3QoYXJ0RGF0ZSkKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIEdyb3VwaW5nIGRhdGUKYGBge3J9CmRhdGEgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkoYXJ0RGF0ZSkgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIExpbmUgZ3JhcGggb2YgYXJ0aWNsZXMKYGBge3J9CnBsb3RfZGF0ZSA8LSBkYXRhICU+JSBnZ3Bsb3QoYWVzKHggPSBhcnREYXRlLCB5ID0gY291bnQpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gIiMwMEFGQkIiLCBzaXplID0gMSkgKyAKICBzY2FsZV94X2RhdGUobGFiZWxzID0gZGF0ZV9mb3JtYXQoIiVZLyVtLyVkIikpICsKICBnZ3RpdGxlKCLmkKzlrrbvvI3oqI7oq5bmlofnq6DmlbjvvIhNb2JpbGUwMe+8iSIpICsgCiAgeGxhYigiRGF0ZSIpICsgCiAgeWxhYigiQ291bnQiKSArIAogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkhlaXRpIFRDIExpZ2h0IikpIAoKcGxvdF9kYXRlCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBCYXJwbG90IChudW0gb2Ygd29yZHMpCmBgYHtyfQpsaWJyYXJ5KHNsYW0pOyBsaWJyYXJ5KHRtKTsgbGlicmFyeSh0bWNuKTsgbGlicmFyeShySmF2YSk7IGxpYnJhcnkoU25vd2JhbGxDKTsgbGlicmFyeShqaWViYVIpCgppaSA9IGpqID0gdnYgPU5VTEwKZm9yKGkgaW4gMTpsZW5ndGgoUCR0ZXh0KSkgewogIHggPSBzZWdtZW50KFAkdGV4dFtpXSwgY2MpCiAgeCA9IHhbISBncmVwbCgiWzAtOV0rIix4KV0KICB4ID0gdGFibGUoeFshIHggJWluJSBzdG9wd2RdKQogIGlpID0gYyhpaSwgcmVwKGksbGVuZ3RoKHgpKSkKICBqaiA9IGMoamosIG5hbWVzKHgpKQogIHZ2ID0gYyh2diwgYXMudmVjdG9yKHgpKQp9CmpqID0gYXMuZmFjdG9yKGpqKQoKbCA9IGxldmVscyhqaikKZHRtID0gc2ltcGxlX3RyaXBsZXRfbWF0cml4KGlpLGFzLmludGVnZXIoamopLHZ2LAogICAgICAgICAgICAgZGltbmFtZXM9bGlzdChhcy5jaGFyYWN0ZXIoMTpsZW5ndGgoUCR0ZXh0KSksbCkpCmRpbShkdG0pCnNhdmUoZHRtLCBmaWxlPSJNSG1iMDEucmRhdGEiKQpkdG0gPSBkdG1bLCBvcmRlcihjb2xfc3VtcyhkdG0pLCBkZWNyZWFzaW5nPVQpXQpjb2xfc3VtcyhkdG0pWzE6NDBdICU+JSBiYXJwbG90KGxhcz0yLCBmYW1pbHkgPSAiSGVpdGkgVEMgTGlnaHQiKQpgYGAKCjxicj4KPGJyPgoKIyMjIyMgSGllcmFyY2hpY2FsIENsdXN0ZXJzIChiaW5hcnkgZGlzdGFuY2UpCmBgYHtyfQpsaWJyYXJ5KE1BU1MpCmxpYnJhcnkod29yZGNsb3VkKQpjb2xvcnMgPSBjKCdnb2xkJywncHVycGxlJywnY3lhbicsJ3JlZCcsJ29yYW5nZTMnLCdncmF5JywKICAgICAgICAgICAncGluaycsJ2dyZWVuJywnZGFya2dyZWVuJywnYmx1ZScsJ2Jyb3duJywnbWFnZW50YScsJ2RlZXBza3libHVlMycpCgpuID0gMjAwOyBhID0gNQpiZCA9IGRpc3QodChkdG1bLGE6bl0pLG1ldGhvZD0iYmluYXJ5IikKIyBiZCA9IGRpc3QodChkdG1bLGE6bl0pKQptZHMgPSAgaXNvTURTKGJkICsgMTBeKC02KSkKaGMgPSBoY2x1c3QoYmQsbWV0aG9kPSJ3YXJkLkQyIikKcGxvdChoYywgZmFtaWx5ID0gIkhlaXRpIFRDIExpZ2h0IikgCgprPTEyCnBsb3QoaGMsY2V4PTAuNyxtYWluPSJIaWVyYXJjaGljYWwgQ2x1c3RlcnMgKEJpbmFyeSBEaXN0YW5jZSkiLAogICAgIHN1Yj0iIix5bGFiPSIiLHhsYWI9IkphY2NhcmQgKEJpbmFyeSkgRGlzdGFuY2UiLAogICAgIGNleC5heGlzPTAuNixjZXgubGFiPTAuOCxjZXgubWFpbj0xLCBmYW1pbHkgPSAiSGVpdGkgVEMgTGlnaHQiKQpyZWN0LmhjbHVzdChoYywgaz1rLCBib3JkZXI9InBpbmsiKQpgYGAKCjxicj4KPGJyPgoKIyMjIyMgV29yZCBDbG91ZApgYGB7cn0KZ3AgPSBjdXRyZWUoaGMsIGs9ayk7IHRhYmxlKGdwKQp3YyA9IGNvbF9zdW1zKGR0bVssYTpuXSkKcDAgPSBwYXIobWFyPWMoMSwxLDEsMSkpCnRleHRwbG90KG1kcyRwb2ludHNbLDFdLG1kcyRwb2ludHNbLDJdLGNvbG5hbWVzKGR0bSlbYTpuXSwKICAgICAgICAgc2hvdz1GLCBjb2w9Y29sb3JzW2dwXSxjZXg9MS41KnNxcnQod2MvbWVhbih3YykpLAogICAgICAgICBmb250PTIsYXhlcz1GLCBmYW1pbHkgPSAiTWljcm9zb2Z0IEpoZW5nSGVpIik7IHBhcihwMCkKYGBgCgo8YnI+Cjxicj4KIyMjIFNlbnRpbWVudCBBbmFseXNpcwoKIyMjIyMgTG9hZGluZyBDaGluZXNlIFRleHRpbmcgbmVlZGVkIHBhY2thZ2VzCmBgYHtyfQojIGluc3RhbGwucGFja2FnZXMoJ2NoaW5lc2UubWlzYycpCmxpYnJhcnkoY2hpbmVzZS5taXNjKQpsaWJyYXJ5KHRtKQpsaWJyYXJ5KGppZWJhUikKbGlicmFyeShNYXRyaXgpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkodGlkeXRleHQpCmxpYnJhcnkodGlkeXIpCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBDaGFuZ2UgdGhlIGZvcm1hdCBvZiB0aGUgZGF0YXNldCAKYGBge3J9ClAkYXJ0Q29udGVudCA9IGFzLmNoYXJhY3RlcihQJGFydENvbnRlbnQpClAkdGV4dCA9IGFzLmNoYXJhY3RlcihQJHRleHQpClAkYXJ0RGF0ZSA9IGFzLkRhdGUoUCRhcnREYXRlKQpgYGAKCjxicj4KPGJyPgoKIyMjIyMgTG9hZGluZyBjdXN0b21pemUgZGljdCBpbiBKaWViYQpgYGB7cn0KamllYmFfdG9rZW5pemVyIDwtIHdvcmtlcih1c2VyPSJkaWN0L01IX3dvcmRzLmRpY3QiKQpgYGAKCjxicj4KPGJyPgojIyMjIyBTZWdtZW50YXRpb24KYGBge3J9CiMgU2V0dXAgc2VnbWVudCBmdW5jdGlvbgpNSF90b2tlbml6ZXIgPC0gZnVuY3Rpb24odCkgewogIGxhcHBseSh0LCBmdW5jdGlvbih4KSB7CiAgICB0b2tlbnMgPC0gc2VnbWVudCh4LCBqaWViYV90b2tlbml6ZXIpCiAgICByZXR1cm4odG9rZW5zKQogIH0pCn0KCnRva2VucyA9IFAgJT4lIAogIHVubmVzdF90b2tlbnMod29yZCwgYXJ0Q29udGVudCwgdG9rZW4gPSBNSF90b2tlbml6ZXIpCmBgYAoKPGJyPgo8YnI+CgojIENvdW50IGZvciB0aGUgYW1vdW50IG9mIHdvcmRzIGluIGNvcnB1cwpgYGB7cn0KdG9rZW5zID0gdG9rZW5zICU+JQogIGRwbHlyOjpzZWxlY3QoYXJ0RGF0ZSwgd29yZCkgJT4lCiAgZ3JvdXBfYnkoYXJ0RGF0ZSwgd29yZCkgJT4lCiAgbXV0YXRlKGNvdW50ID0gbigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZGlzdGluY3QoKSAjIOW3see2k+e1seioiOmBjuaVuOmHj++8m+WOu+mZpOmHjeikh+izh+aWmQoKdG9rZW5zCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBMSVdDIGRpY3QgKHBvc2l0aXZlLCBuZWdhdGl2ZSkKYGBge3J9CnAgPC0gcmVhZF9maWxlKCIvVm9sdW1lcy9Hb29nbGVEcml2ZS9UZWFtXCBEcml2ZXMvVEhFU0lTL+ahiOS+i+ani+aAnS/lt6jlipvmkKzlrrYvRGF0YVwgQ29sbGVjdGlvbi/niKzon7Los4fmlpkvZGljdC9NSF9wb3NpdGl2ZS50eHQiKQpuIDwtIHJlYWRfZmlsZSgiL1ZvbHVtZXMvR29vZ2xlRHJpdmUvVGVhbVwgRHJpdmVzL1RIRVNJUy/moYjkvovmp4vmgJ0v5beo5Yqb5pCs5a62L0RhdGFcIENvbGxlY3Rpb24v54is6J+y6LOH5paZL2RpY3QvTUhfbmVnYXRpdmUudHh0IikKcG9zaXRpdmUgPC0gc3Ryc3BsaXQocCwgIlssXSIpW1sxXV0KbmVnYXRpdmUgPC0gc3Ryc3BsaXQobiwgIlssXSIpW1sxXV0KcG9zaXRpdmUgPC0gZGF0YS5mcmFtZSh3b3JkID0gcG9zaXRpdmUsIHNlbnRpbWVudHMgPSAicG9zaXRpdmUiKQpuZWdhdGl2ZSA8LSBkYXRhLmZyYW1lKHdvcmQgPSBuZWdhdGl2ZSwgc2VudGllbXRucyA9ICJuZWdhdGl2ZSIpCmNvbG5hbWVzKG5lZ2F0aXZlKSA9IGMoIndvcmQiLCJzZW50aW1lbnQiKQpjb2xuYW1lcyhwb3NpdGl2ZSkgPSBjKCJ3b3JkIiwic2VudGltZW50IikKTElXQ19jaCA8LSByYmluZChwb3NpdGl2ZSwgbmVnYXRpdmUpICU+JSBkaXN0aW5jdCgpCgpMSVdDX2NoCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBKb2luIGNvcnB1cyB3aXRoIExJV0MgKG90IG1ha2Ugc3VyZSB0aGUgd29yZCBpcyBiZWxvbmdzIHRvIHBvc2l0aXZlIG9yIG5lZ2F0aXZlKQpgYGB7cn0Kc2VudGlfdG9rZW5zID0gdG9rZW5zICU+JSBpbm5lcl9qb2luKExJV0NfY2gpIApoZWFkKHNlbnRpX3Rva2VucykgCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBGaW5kIG91dCBhbGwgZGF0ZSBpbiB0aW1lIHBlcmlvZApgYGB7cn0KYWxsX2RhdGVzIDwtIAogIGV4cGFuZC5ncmlkKHNlcShhcy5EYXRlKG1pbihkYXRhJGFydERhdGUpKSwgYXMuRGF0ZShtYXgoZGF0YSRhcnREYXRlKSksIGJ5PSJkYXkiKSwgYygicG9zaXRpdmUiLCAibmVnYXRpdmUiKSkKaGVhZChhbGxfZGF0ZXMpCmBgYAoKPGJyPgo8YnI+CgojIExpbmUgY2hhcnQgb2Ygc2VudGltZW50IChwb3NpdGl2ZSwgbmVnYXRpdmUpCmBgYHtyfQpzZW50aV90b2tlbnMkYXJ0RGF0ZSA9IGFzLkRhdGUoc2VudGlfdG9rZW5zJGFydERhdGUpCiMgaGVhZChzZW50aV90b2tlbnMpICAgICAgICBhcnRUaXRsZSwgYXJ0RGF0ZSwgYXJ0VGltZSwgYXJ0VXJsLCB0ZXh0LCB3b3JkLCBzZW50aW1lbnQKIyBoZWFkKExJV0NfY2gpICAgICAgICAgICAgIHdvcmQsIHNlbnRpbWVudApwbG90X3RhYmxlIDwtIHNlbnRpX3Rva2VucyAlPiUKICBpbm5lcl9qb2luKExJV0NfY2gpICU+JSAKICBncm91cF9ieShhcnREYXRlLHNlbnRpbWVudCkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQoKcGxvdF90YWJsZSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gYXJ0RGF0ZSwgeSA9IGNvdW50LCBjb2xvdXIgPSBzZW50aW1lbnQpKSArCiAgc2NhbGVfeF9kYXRlKGxhYmVscyA9IGRhdGVfZm9ybWF0KCIlWS8lbS8lZCIpKSArCiAgeGxhYigiRGF0ZSIpICsgeWxhYigiQ291bnQiKQpgYGAKCjxicj4KPGJyPgoKIyMjIyMgQ29tbW9uIHNlbnRpbWVudCB3b3JkcyBpbiBMSVdDIGRpY3QgKHBvc2l0aXZlLCBuZWdhdGl2ZSkKCmBgYHtyfQp0b2tlbnMgJT4lIAogIGlubmVyX2pvaW4oTElXQ19jaCkgJT4lIAogIGdyb3VwX2J5KHNlbnRpbWVudCkgJT4lCiAgY291bnQod29yZCkgJT4lCiAgZ2dwbG90KGFlcyh3b3JkLCBuLCBmaWxsID0gc2VudGltZW50KSkgKwogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF93cmFwKH4gc2VudGltZW50LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeSA9ICJDb250cmlidXRpb24gdG8gc2VudGltZW50IiwKICAgICAgIHggPSBOVUxMKSArCiAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMSkpICsKICBjb29yZF9mbGlwKCkgKyAKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJIZWl0aSBUQyBMaWdodCIpKSAKYGBgCgo8YnI+Cjxicj4KCjxzdHlsZT4KLmNhcHRpb24gewogIG1hcmdpbi10b3A6IDEwcHg7Cn0KcCBjb2RlIHsKICB3aGl0ZS1zcGFjZTogaW5oZXJpdDsKfQpwcmUgewogIHdvcmQtYnJlYWs6IG5vcm1hbDsKICB3b3JkLXdyYXA6IG5vcm1hbDsKICBsaW5lLWhlaWdodDogMTsKfQpwcmUgY29kZSB7CiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7Cn0KcCxsaSB7CiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7Cn0KCi5yewogIGxpbmUtaGVpZ2h0OiAxLjI7Cn0KCmJvZHl7CiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7Cn0KCmgxLGgyLGgzLGg0LGg1ewogIGNvbG9yOiAjNDQ0NDQ0OwogIGZvbnQtZmFtaWx5OiAiVHJlYnVjaGV0IE1TIiwgIuW+rui7n+ato+m7kemrlCIsICJNaWNyb3NvZnQgSmhlbmdIZWkiOwp9CgpoM3sKICBjb2xvcjogIzQ2ODI4NDsKICBiYWNrZ3JvdW5kOiAjZmZlMGIzOwogIGxpbmUtaGVpZ2h0OiAyOwogIGZvbnQtd2VpZ2h0OiBib2xkOwp9CgpoNXsKICBjb2xvcjogIzQ2ODI4NDsKICBiYWNrZ3JvdW5kOiAjZmZmZmUwOwogIGxpbmUtaGVpZ2h0OiAyOwogIGZvbnQtd2VpZ2h0OiBib2xkOwp9CgplbXsKICBjb2xvcjogIzQ2ODI4NDsKICB9Cgo8L3N0eWxlPg==