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/爬蟲資料/Google/GoogleMapReview.csv")
Parsed with column specification:
cols(
  city = col_character(),
  artTitle = col_character(),
  rating = col_double(),
  user_ratings_total = col_double(),
  artContent = col_character()
)
colnames(P)
[1] "city"               "artTitle"           "rating"             "user_ratings_total"
[5] "artContent"        
# [1] "city"               "artTitle"           "rating"             "user_ratings_total"
# [5] "artContent"         "text"         
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","輸入","傳統","中繼站","信義","子","不收",
           "有時候","是從","小東西","NA","一位","and","the","十分","they",
           "謝謝","具","包","墊","掉","好好","真","were","樓","超過")
於 '/Volumes/GoogleDrive/Team Drives/THESIS/案例構思/巨力搬家/Data Collection/爬蟲資料/dict/stop_words.txt' 找到不完整的最後一列



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))
Error in simple_triplet_matrix(ii, as.integer(jj), vv, dimnames = list(as.character(1:length(P$text)),  : 
  'dimnames' component invalid length or type



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 72.145980 
iter   5 value 40.909806
iter  10 value 38.938357
iter  15 value 38.074441
final  value 37.818707 
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 
27 53 10 34  9  8  9  9  7 13 15  2 
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)



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



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 = 6)) +
  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+w54Gj5pCs5a6255Si5qWt5paH5a2X5YiG5p6Q77yIR29vZ2xl6KmV6KuW77yJLyBUZXh0IE1pbmluZyBvZiBNb3ZpbmcgSW5kdXN0cnkgaW4gVGFpd2FuIChHb29nbGUgTWFwIFJldmlldykiCmF1dGhvcjogIkthcmVuIFlhbmcg5qWK5Yex5YCrIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgo8YnI+Cjxicj4KCisgQ29ycHVzIFR5cGU6IEdvb2dsZSBNYXAgUmV2aWV3CisgTnVtYmVyIG9mIGNvcnB1czogNzQ5Cgo8YnI+Cjxicj4KCiMjIyMjIEVuY29kaW5nIHRvIFVURi04CmBgYHtyfQpTeXMuc2V0bG9jYWxlKGNhdGVnb3J5ID0gIkxDX0FMTCIsIGxvY2FsZSA9ICJ6aF9UVy5VVEYtOCIpCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBJbnN0YWxsIGVzc2VudGlhbCBwYWNrYWdlCmBgYHtyfQpwYWNrYWdlcyA9IGMoImRwbHlyIiwgInRpZHl0ZXh0IiwgInN0cmluZ3IiLCAid29yZGNsb3VkMiIsICJnZ3Bsb3QyIiwncmVhZHInLCdkYXRhLnRhYmxlJywncmVzaGFwZTInLCd3b3JkY2xvdWQnLCd0aWR5cicsJ3NjYWxlcycsJ3J2ZXN0JywnbWFncml0dHInLCdSQ3VybCcsJ1hNTCcsJ3NsYW0nKQpleGlzdGluZyA9IGFzLmNoYXJhY3RlcihpbnN0YWxsZWQucGFja2FnZXMoKVssMV0pCmZvcihwa2cgaW4gcGFja2FnZXNbIShwYWNrYWdlcyAlaW4lIGV4aXN0aW5nKV0pIGluc3RhbGwucGFja2FnZXMocGtnKQpgYGAKCjxicj4KPGJyPgoKIyMjIyMgTG9hZGluZyBsaWJyYXJ5CmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkod29yZGNsb3VkKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShyZWFkcikKbGlicmFyeShqaWViYVIpCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBMb2FkaW5nIGRhdGEgKG1vYmlsZTAxKQpgYGB7cn0KUCA8LSByZWFkX2NzdigiL1ZvbHVtZXMvR29vZ2xlRHJpdmUvVGVhbVwgRHJpdmVzL1RIRVNJUy/moYjkvovmp4vmgJ0v5beo5Yqb5pCs5a62L0RhdGFcIENvbGxlY3Rpb24v54is6J+y6LOH5paZL0dvb2dsZS9Hb29nbGVNYXBSZXZpZXcuY3N2IikKY29sbmFtZXMoUCkKIyBbMV0gImNpdHkiICAgICAgICAgICAgICAgImFydFRpdGxlIiAgICAgICAgICAgInJhdGluZyIgICAgICAgICAgICAgInVzZXJfcmF0aW5nc190b3RhbCIKIyBbNV0gImFydENvbnRlbnQiICAgICAgICAgInRleHQiICAgICAgICAgClAkdGV4dCA9IFAkYXJ0Q29udGVudApgYGAKCgoKIyMjIyMgTG9hZGluZyBKaWViYVIgcGFja2FnZSBhbmQgc2V0dXAgc3RvcCB3b3JkcyBkaWN0aW9uYXJ5CmBgYHtyfQpsaWJyYXJ5KGppZWJhUikKdXNlcndkID0gYygi5pCs5a625YWs5Y+4Iiwi5bSU5aq95aq9Iiwi5bq356aPIiwi5beo5YqbIiwi5aSn5ZCJ5pe6Iiwi5pCs5a62Iiwi5LmZ5LmF5YipIiwi5bq356aP5pCs5a62Iiwi5beo5Yqb5pCs5a62Iiwi5bSU5aq95aq95Z+66YeR5pyDIiwi5LiN5Yqg5YO5Iiwi5LiN5LqC5Yqg5YO5Iiwi5bSU5aq95aq957ay56uZIiwi6IiK5YKi5L+xIiwi6L6y5rCR5puGIiwi6aKo5rC0Iiwi5pmC6L6wIiwi5YKi5L+xIiwi5YKi5YW3IikKY2MgPSB3b3JrZXIoKQpuZXdfdXNlcl93b3JkKGNjLHVzZXJ3ZCx0YWdzPXJlcCgnbicsbGVuZ3RoKHVzZXJ3ZCkpKQoKc3RvcHdkID0gYyhyZWFkTGluZXMoIi9Wb2x1bWVzL0dvb2dsZURyaXZlL1RlYW1cIERyaXZlcy9USEVTSVMv5qGI5L6L5qeL5oCdL+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/mnbHopb8iLCJOQSIsIuS4gOS9jSIsImFuZCIsInRoZSIsIuWNgeWIhiIsInRoZXkiLAogICAgICAgICAgICLorJ3orJ0iLCLlhbciLCLljIUiLCLloooiLCLmjokiLCLlpb3lpb0iLCLnnJ8iLCJ3ZXJlIiwi5qiTIiwi6LaF6YGOIikKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIEJhcnBsb3QgKG51bSBvZiB3b3JkcykKYGBge3J9CmxpYnJhcnkoc2xhbSk7IGxpYnJhcnkodG0pOyBsaWJyYXJ5KHRtY24pOyBsaWJyYXJ5KHJKYXZhKTsgbGlicmFyeShTbm93YmFsbEMpOyBsaWJyYXJ5KGppZWJhUikKCmlpID0gamogPSB2diA9TlVMTApmb3IoaSBpbiAxOmxlbmd0aChQJHRleHQpKSB7CiAgeCA9IHNlZ21lbnQoUCR0ZXh0W2ldLCBjYykKICB4ID0geFshIGdyZXBsKCJbMC05XSsiLHgpXQogIHggPSB0YWJsZSh4WyEgeCAlaW4lIHN0b3B3ZF0pCiAgaWkgPSBjKGlpLCByZXAoaSxsZW5ndGgoeCkpKQogIGpqID0gYyhqaiwgbmFtZXMoeCkpCiAgdnYgPSBjKHZ2LCBhcy52ZWN0b3IoeCkpCn0KamogPSBhcy5mYWN0b3IoamopCgpsID0gbGV2ZWxzKGpqKQpkdG0gPSBzaW1wbGVfdHJpcGxldF9tYXRyaXgoaWksYXMuaW50ZWdlcihqaiksdnYsCiAgICAgICAgICAgICBkaW1uYW1lcz1saXN0KGFzLmNoYXJhY3RlcigxOmxlbmd0aChQJHRleHQpKSxsKSkKZGltKGR0bSkKc2F2ZShkdG0sIGZpbGU9Ik1IbWIwMS5yZGF0YSIpCmR0bSA9IGR0bVssIG9yZGVyKGNvbF9zdW1zKGR0bSksIGRlY3JlYXNpbmc9VCldCmNvbF9zdW1zKGR0bSlbMTo0MF0gJT4lIGJhcnBsb3QobGFzPTIsIGZhbWlseSA9ICJIZWl0aSBUQyBMaWdodCIpCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBIaWVyYXJjaGljYWwgQ2x1c3RlcnMgKGJpbmFyeSBkaXN0YW5jZSkKYGBge3J9CmxpYnJhcnkoTUFTUykKbGlicmFyeSh3b3JkY2xvdWQpCmNvbG9ycyA9IGMoJ2dvbGQnLCdwdXJwbGUnLCdjeWFuJywncmVkJywnb3JhbmdlMycsJ2dyYXknLAogICAgICAgICAgICdwaW5rJywnZ3JlZW4nLCdkYXJrZ3JlZW4nLCdibHVlJywnYnJvd24nLCdtYWdlbnRhJywnZGVlcHNreWJsdWUzJykKCm4gPSAyMDA7IGEgPSA1CmJkID0gZGlzdCh0KGR0bVssYTpuXSksbWV0aG9kPSJiaW5hcnkiKQojIGJkID0gZGlzdCh0KGR0bVssYTpuXSkpCm1kcyA9ICBpc29NRFMoYmQgKyAxMF4oLTYpKQpoYyA9IGhjbHVzdChiZCxtZXRob2Q9IndhcmQuRDIiKQpwbG90KGhjLCBmYW1pbHkgPSAiSGVpdGkgVEMgTGlnaHQiKSAKCms9MTIKcGxvdChoYyxjZXg9MC43LG1haW49IkhpZXJhcmNoaWNhbCBDbHVzdGVycyAoQmluYXJ5IERpc3RhbmNlKSIsCiAgICAgc3ViPSIiLHlsYWI9IiIseGxhYj0iSmFjY2FyZCAoQmluYXJ5KSBEaXN0YW5jZSIsCiAgICAgY2V4LmF4aXM9MC42LGNleC5sYWI9MC44LGNleC5tYWluPTEsIGZhbWlseSA9ICJIZWl0aSBUQyBMaWdodCIpCnJlY3QuaGNsdXN0KGhjLCBrPWssIGJvcmRlcj0icGluayIpCmBgYAoKPGJyPgo8YnI+CgojIyMjIyBXb3JkIENsb3VkCmBgYHtyfQpncCA9IGN1dHJlZShoYywgaz1rKTsgdGFibGUoZ3ApCndjID0gY29sX3N1bXMoZHRtWyxhOm5dKQpwMCA9IHBhcihtYXI9YygxLDEsMSwxKSkKdGV4dHBsb3QobWRzJHBvaW50c1ssMV0sbWRzJHBvaW50c1ssMl0sY29sbmFtZXMoZHRtKVthOm5dLAogICAgICAgICBzaG93PUYsIGNvbD1jb2xvcnNbZ3BdLGNleD0xLjUqc3FydCh3Yy9tZWFuKHdjKSksCiAgICAgICAgIGZvbnQ9MixheGVzPUYsIGZhbWlseSA9ICJNaWNyb3NvZnQgSmhlbmdIZWkiKTsgcGFyKHAwKQpgYGAKCjxicj4KPGJyPgojIyMgU2VudGltZW50IEFuYWx5c2lzCgojIyMjIyBMb2FkaW5nIENoaW5lc2UgVGV4dGluZyBuZWVkZWQgcGFja2FnZXMKYGBge3J9CiMgaW5zdGFsbC5wYWNrYWdlcygnY2hpbmVzZS5taXNjJykKbGlicmFyeShjaGluZXNlLm1pc2MpCmxpYnJhcnkodG0pCmxpYnJhcnkoamllYmFSKQpsaWJyYXJ5KE1hdHJpeCkKbGlicmFyeShyZWFkcikKbGlicmFyeSh0aWR5dGV4dCkKbGlicmFyeSh0aWR5cikKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIENoYW5nZSB0aGUgZm9ybWF0IG9mIHRoZSBkYXRhc2V0IApgYGB7cn0KUCRhcnRDb250ZW50ID0gYXMuY2hhcmFjdGVyKFAkYXJ0Q29udGVudCkKUCR0ZXh0ID0gYXMuY2hhcmFjdGVyKFAkdGV4dCkKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIExvYWRpbmcgY3VzdG9taXplIGRpY3QgaW4gSmllYmEKYGBge3J9CmppZWJhX3Rva2VuaXplciA8LSB3b3JrZXIodXNlcj0iZGljdC9NSF93b3Jkcy5kaWN0IikKYGBgCgo8YnI+Cjxicj4KIyMjIyMgU2VnbWVudGF0aW9uCmBgYHtyfQojIFNldHVwIHNlZ21lbnQgZnVuY3Rpb24KTUhfdG9rZW5pemVyIDwtIGZ1bmN0aW9uKHQpIHsKICBsYXBwbHkodCwgZnVuY3Rpb24oeCkgewogICAgdG9rZW5zIDwtIHNlZ21lbnQoeCwgamllYmFfdG9rZW5pemVyKQogICAgcmV0dXJuKHRva2VucykKICB9KQp9Cgp0b2tlbnMgPSBQICU+JSAKICB1bm5lc3RfdG9rZW5zKHdvcmQsIGFydENvbnRlbnQsIHRva2VuID0gTUhfdG9rZW5pemVyKQpgYGAKCjxicj4KPGJyPgoKIyBDb3VudCBmb3IgdGhlIGFtb3VudCBvZiB3b3JkcyBpbiBjb3JwdXMKYGBge3J9CnRva2VucyA9IHRva2VucyAlPiUKICBtdXRhdGUoY291bnQgPSBuKCkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBkaXN0aW5jdCgpICMg5bex57aT57Wx6KiI6YGO5pW46YeP77yb5Y676Zmk6YeN6KSH6LOH5paZCgp0b2tlbnMKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIExJV0MgZGljdCAocG9zaXRpdmUsIG5lZ2F0aXZlKQpgYGB7cn0KcCA8LSByZWFkX2ZpbGUoIi9Wb2x1bWVzL0dvb2dsZURyaXZlL1RlYW1cIERyaXZlcy9USEVTSVMv5qGI5L6L5qeL5oCdL+W3qOWKm+aQrOWuti9EYXRhXCBDb2xsZWN0aW9uL+eIrOifsuizh+aWmS9kaWN0L01IX3Bvc2l0aXZlLnR4dCIpCm4gPC0gcmVhZF9maWxlKCIvVm9sdW1lcy9Hb29nbGVEcml2ZS9UZWFtXCBEcml2ZXMvVEhFU0lTL+ahiOS+i+ani+aAnS/lt6jlipvmkKzlrrYvRGF0YVwgQ29sbGVjdGlvbi/niKzon7Los4fmlpkvZGljdC9NSF9uZWdhdGl2ZS50eHQiKQpwb3NpdGl2ZSA8LSBzdHJzcGxpdChwLCAiWyxdIilbWzFdXQpuZWdhdGl2ZSA8LSBzdHJzcGxpdChuLCAiWyxdIilbWzFdXQpwb3NpdGl2ZSA8LSBkYXRhLmZyYW1lKHdvcmQgPSBwb3NpdGl2ZSwgc2VudGltZW50cyA9ICJwb3NpdGl2ZSIpCm5lZ2F0aXZlIDwtIGRhdGEuZnJhbWUod29yZCA9IG5lZ2F0aXZlLCBzZW50aWVtdG5zID0gIm5lZ2F0aXZlIikKY29sbmFtZXMobmVnYXRpdmUpID0gYygid29yZCIsInNlbnRpbWVudCIpCmNvbG5hbWVzKHBvc2l0aXZlKSA9IGMoIndvcmQiLCJzZW50aW1lbnQiKQpMSVdDX2NoIDwtIHJiaW5kKHBvc2l0aXZlLCBuZWdhdGl2ZSkgJT4lIGRpc3RpbmN0KCkKCkxJV0NfY2gKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIEpvaW4gY29ycHVzIHdpdGggTElXQyAob3QgbWFrZSBzdXJlIHRoZSB3b3JkIGlzIGJlbG9uZ3MgdG8gcG9zaXRpdmUgb3IgbmVnYXRpdmUpCmBgYHtyfQpzZW50aV90b2tlbnMgPSB0b2tlbnMgJT4lIGlubmVyX2pvaW4oTElXQ19jaCkgCmhlYWQoc2VudGlfdG9rZW5zKSAKYGBgCgo8YnI+Cjxicj4KCiMjIyMjIENvbW1vbiBzZW50aW1lbnQgd29yZHMgaW4gTElXQyBkaWN0IChwb3NpdGl2ZSwgbmVnYXRpdmUpCgpgYGB7cn0KdG9rZW5zICU+JSAKICBpbm5lcl9qb2luKExJV0NfY2gpICU+JSAKICBncm91cF9ieShzZW50aW1lbnQpICU+JQogIGNvdW50KHdvcmQpICU+JQogIGdncGxvdChhZXMod29yZCwgbiwgZmlsbCA9IHNlbnRpbWVudCkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+IHNlbnRpbWVudCwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHkgPSAiQ29udHJpYnV0aW9uIHRvIHNlbnRpbWVudCIsCiAgICAgICB4ID0gTlVMTCkgKwogIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemUgPSA2KSkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkhlaXRpIFRDIExpZ2h0IikpIApgYGAKCjxicj4KPGJyPgoKPHN0eWxlPgouY2FwdGlvbiB7CiAgbWFyZ2luLXRvcDogMTBweDsKfQpwIGNvZGUgewogIHdoaXRlLXNwYWNlOiBpbmhlcml0Owp9CnByZSB7CiAgd29yZC1icmVhazogbm9ybWFsOwogIHdvcmQtd3JhcDogbm9ybWFsOwogIGxpbmUtaGVpZ2h0OiAxOwp9CnByZSBjb2RlIHsKICB3aGl0ZS1zcGFjZTogaW5oZXJpdDsKfQpwLGxpIHsKICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsKfQoKLnJ7CiAgbGluZS1oZWlnaHQ6IDEuMjsKfQoKYm9keXsKICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsKfQoKaDEsaDIsaDMsaDQsaDV7CiAgY29sb3I6ICM0NDQ0NDQ7CiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7Cn0KCmgzewogIGNvbG9yOiAjNDY4Mjg0OwogIGJhY2tncm91bmQ6ICNmZmUwYjM7CiAgbGluZS1oZWlnaHQ6IDI7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KCmg1ewogIGNvbG9yOiAjNDY4Mjg0OwogIGJhY2tncm91bmQ6ICNmZmZmZTA7CiAgbGluZS1oZWlnaHQ6IDI7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KCmVtewogIGNvbG9yOiAjNDY4Mjg0OwogIH0KCjwvc3R5bGU+