Lecture6: Manipulate関数, Sentiment Analysis

manipulate (インタラクティブなプロット)

manipulate関数の書き方

  • 単一実行スクリプトの場合
manipulate(
  実行スクリプト,
  picker, sliderの情報(複数の場合はカンマで結合)
)
  • 複数実行スクリプトの場合
manipulate(
  {
  複数の実行スクリプト
  },
  picker, sliderの情報(複数の場合はカンマで結合)
)

注意:manipulate関数は、配布Notebookファイルではなく、拡張子”.R”のファイル上で確認すること

ライブラリの読み込み

library(manipulate)

色の選択

title="PCH Symbols"
xlabel="x"
ylabel="y"
plot(0,0,pch=8,cex=5,col="blue", main=title, xlab=xlabel, ylab=ylabel)

  • picker()関数
manipulate(plot(0,0,pch=8,cex=5,col=myColors), myColors=picker("red", "violet", "pink", "orange", "yellow", "green", "blue", "cyan") )
  • picker()関数 & List
colors = c("red", "violet", "pink", "orange", "yellow", "green", "blue", "cyan")
manipulate(plot(0,0,pch=8,cex=5,col=myColors), myColors=picker(colors) )

プロットマーカーの選択

manipulate(
  plot(0,0,pch=myMarkers,cex=5,col=myColors), myColors=picker("red", "violet", "pink", "orange", "yellow", "green", "blue", "cyan",initial="violet"),
  myMarkers=picker(1,2,3,4,5,6,7,8,initial="5")
)

picker + List

colPalets = c("red", "violet", "pink", "orange", "yellow", "green", "blue", "cyan")
manipulate(
  plot(0,0,pch=myMarkers,cex=5,col=myColors, main=title, xlab=xlabel, ylab=ylabel),
  myColors=picker(as.list(colPalets),initial=colPalets[2]),
  myMarkers=picker(as.list(seq(1,8)),initial="5")
)

プロットサイズの選択

  • slider()関数
manipulate(
  plot(0,0,pch=8,cex=mySize,col="blue"),
  mySize=slider(1,10,initial=5,step=2)
)

getWordFreq関数

  • getWordLst

単語頻度表

wdLst.BBC <- getWordFreq("G7/BBC.txt")
head(wdLst.BBC)
wordLst
    the      in      of      to       a ukraine 
     24      15      13      10       9       7 

色付き棒グラフ

color8 = c("red", "violet", "pink", "orange", "yellow", "green", "blue", "cyan")
barplot(wdLst.BBC, las=3,col=color8,ylab="Frequency")

length(wdLst.BBC)
[1] 239
barplot(wdLst.BBC[1:length(wdLst.BBC)], las=3,col=color8,ylab="Frequency")

las: label style

las = 0 : XYの両軸とも目盛り文字は軸方向(デフォルト)
las = 1 : XYの両軸とも目盛り文字は水平方向
las = 2 : XYの両軸とも目盛り文字は軸方向と直角
las = 3 : XYの両軸とも目盛り文字は垂直方向
max.Index<-10
barplot(wdLst.BBC[1:max.Index], las=3,col=color8,ylab="Frequency")

練習1:manipulate関数で、wdLst.BBC単語頻度棒グラフの以下の2点をインタラクティブに変更できるようにしてください。

-軸ラベルの向き -wdLst.BBCの単語最大表示数(最小値=5,最大値=全出現数(Types),Step=20)

  • 実行結果例は、配布資料の動画を参照

RColorBrewer Package

ライブラリの読み込み

library(wordcloud)

パレット情報

binfo<-brewer.pal.info[]
head(binfo)

パレットの抽出

palets <-rownames(binfo[binfo$maxcolors>10,])
palets
 [1] "BrBG"     "PiYG"     "PRGn"     "PuOr"     "RdBu"     "RdGy"     "RdYlBu"  
 [8] "RdYlGn"   "Spectral" "Paired"   "Set3"    

using a brewer.palet

palets[10]#"Paired"
[1] "Paired"
max.Index<-20
barplot(wdLst.BBC[1:max.Index], las=3,col=brewer.pal(10,palets[1]),ylab="Frequency")

Sentiment Analysis

syuzhetパッケージのインストール

install.packages("syuzhet")

ライブラリの読み込み

library(syuzhet)

Sentiment analysis of an Aljazeera article

テキストファイルの読み込み

text1_string <- get_text_as_string("G7/Aljazeera.txt")

トークン化

text1_words <- get_tokens(text1_string)
head(text1_words)
[1] "top"       "diplomats" "from"      "the"       "group"     "of"       

Tokens

length(text1_words)
[1] 402

感情得点の取得

text1_sentiment_scores <- get_nrc_sentiment(text1_words)

視覚化

barplot(
  colSums(prop.table(text1_sentiment_scores[, 1:8])),
  space = 0.1,
  horiz = TRUE,
  las = 1,
  cex.names = 0.7,
  col = brewer.pal(n = 8, name = "Set3"),
  main = "Aljazeera, 8 Nov 2023",
  sub = "AL JAZEERA AND NEWS AGENCIES",
  xlab="emotions", ylab = NULL)

Sentiment analysis of an BBC article

テキストファイルの読み込み&トークン化

text2_string <- get_text_as_string("G7/BBC.txt")
text2_words <- get_tokens(text2_string)
head(text2_words)
[1] "at"      "a"       "g7"      "meeting" "in"      "japan"  

感情得点の取得

text2_sentiment_scores <- get_nrc_sentiment(text2_words)

視覚化

barplot(
  colSums(prop.table(text2_sentiment_scores[, 1:8])),
  space = 0.1,
  horiz = TRUE,
  las = 1,
  cex.names = 0.8,
  col = brewer.pal(n = 8, name = "Set3"),
  main = "BBC, 8 Nov 2023",
  sub = "By Ido Vock BBC News",
  xlab="emotions", ylab = NULL)

2つのデータを列結合

sentiData<-cbind(colSums(prop.table(text1_sentiment_scores[, 1:8])),colSums(prop.table(text2_sentiment_scores[, 1:8])))
sentiData
                   [,1]       [,2]
anger        0.08571429 0.20588235
anticipation 0.15714286 0.10294118
disgust      0.01428571 0.05882353
fear         0.20000000 0.27941176
joy          0.10000000 0.04411765
sadness      0.10000000 0.08823529
surprise     0.05714286 0.02941176
trust        0.28571429 0.19117647
colnames(sentiData) <- c("ALJAZEERA","BBC")

2つのデータを並べて表示

barplot(sentiData,
        space = 0.1,
        horiz = TRUE,
        las = 1,
        cex.names = 0.8,
        col = brewer.pal(n = 8, name = "Set3"),
        legend.text = rownames(sentiData),
        xlab = "Sentiment Score Ratio", 
        ylab = "Article",
        main = "")

LS0tCnRpdGxlOiAiTGVjMDY6IE1hbmlwdWxhdGUiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgTGVjdHVyZTY6IE1hbmlwdWxhdGXplqLmlbAsIFNlbnRpbWVudCBBbmFseXNpcwoKIyMgbWFuaXB1bGF0ZSAo44Kk44Oz44K/44Op44Kv44OG44Kj44OW44Gq44OX44Ot44OD44OIKQojIyMgbWFuaXB1bGF0ZemWouaVsOOBruabuOOBjeaWuQoqIOWNmOS4gOWun+ihjOOCueOCr+ODquODl+ODiOOBruWgtOWQiApgYGAKbWFuaXB1bGF0ZSgKICDlrp/ooYzjgrnjgq/jg6rjg5fjg4gsCiAgcGlja2VyLCBzbGlkZXLjga7mg4XloLHvvIjopIfmlbDjga7loLTlkIjjga/jgqvjg7Pjg57jgafntZDlkIjvvIkKKQpgYGAKCiog6KSH5pWw5a6f6KGM44K544Kv44Oq44OX44OI44Gu5aC05ZCICmBgYAptYW5pcHVsYXRlKAogIHsKICDopIfmlbDjga7lrp/ooYzjgrnjgq/jg6rjg5fjg4gKICB9LAogIHBpY2tlciwgc2xpZGVy44Gu5oOF5aCx77yI6KSH5pWw44Gu5aC05ZCI44Gv44Kr44Oz44Oe44Gn57WQ5ZCI77yJCikKYGBgCgojIyMg5rOo5oSP77yabWFuaXB1bGF0ZemWouaVsOOBr+OAgemFjeW4g05vdGVib29r44OV44Kh44Kk44Or44Gn44Gv44Gq44GP44CB5ouh5by15a2Q4oCdLlLigJ3jga7jg5XjgqHjgqTjg6vkuIrjgafnorroqo3jgZnjgovjgZPjgagKCiMjIyDjg6njgqTjg5bjg6njg6rjga7oqq3jgb/ovrzjgb8KYGBge3J9CmxpYnJhcnkobWFuaXB1bGF0ZSkKYGBgCgojIyMgPGEgaHJlZj0iaHR0cHM6Ly9odHN1ZGEubmV0L3N0YXRzL3Bsb3QuaHRtbCIgdGFyZ2V0PSJfYmxhbmsiPnBjaDogcGxvdCBjaGFyYWN0ZXI8L2E+CgojIyMg6Imy44Gu6YG45oqeCmBgYHtyfQp0aXRsZT0iUENIIFN5bWJvbHMiCnhsYWJlbD0ieCIKeWxhYmVsPSJ5IgpwbG90KDAsMCxwY2g9OCxjZXg9NSxjb2w9ImJsdWUiLCBtYWluPXRpdGxlLCB4bGFiPXhsYWJlbCwgeWxhYj15bGFiZWwpCmBgYAoKKiBwaWNrZXIoKemWouaVsApgYGB7cixlcnJvcj1GQUxTRSxldmFsPUZBTFNFfQptYW5pcHVsYXRlKHBsb3QoMCwwLHBjaD04LGNleD01LGNvbD1teUNvbG9ycyksIG15Q29sb3JzPXBpY2tlcigicmVkIiwgInZpb2xldCIsICJwaW5rIiwgIm9yYW5nZSIsICJ5ZWxsb3ciLCAiZ3JlZW4iLCAiYmx1ZSIsICJjeWFuIikgKQpgYGAKKiBwaWNrZXIoKemWouaVsCAmIExpc3QKYGBge3IsZXJyb3I9RkFMU0UsZXZhbD1GQUxTRX0KY29sb3JzID0gYygicmVkIiwgInZpb2xldCIsICJwaW5rIiwgIm9yYW5nZSIsICJ5ZWxsb3ciLCAiZ3JlZW4iLCAiYmx1ZSIsICJjeWFuIikKbWFuaXB1bGF0ZShwbG90KDAsMCxwY2g9OCxjZXg9NSxjb2w9bXlDb2xvcnMpLCBteUNvbG9ycz1waWNrZXIoY29sb3JzKSApCmBgYAoKIyMjIOODl+ODreODg+ODiOODnuODvOOCq+ODvOOBrumBuOaKngoqIDxhIGhyZWY9Imh0dHA6Ly9jc2UubmFyby5hZmZyYy5nby5qcC90YWtlemF3YS9yLXRpcHMvci81My5odG1sIiB0YXJnZXQ9Il9ibGFuayI+44Oe44O844Kr44O8PC9hPgoqIHBpY2tlcigp6Zai5pWwCmBgYHtyLGVycm9yPUZBTFNFLGV2YWw9RkFMU0V9Cm1hbmlwdWxhdGUoCiAgcGxvdCgwLDAscGNoPW15TWFya2VycyxjZXg9NSxjb2w9bXlDb2xvcnMpLCBteUNvbG9ycz1waWNrZXIoInJlZCIsICJ2aW9sZXQiLCAicGluayIsICJvcmFuZ2UiLCAieWVsbG93IiwgImdyZWVuIiwgImJsdWUiLCAiY3lhbiIsaW5pdGlhbD0idmlvbGV0IiksCiAgbXlNYXJrZXJzPXBpY2tlcigxLDIsMyw0LDUsNiw3LDgsaW5pdGlhbD0iNSIpCikKYGBgCgojIyMgcGlja2VyICsgTGlzdApgYGB7cixlcnJvcj1GQUxTRSxldmFsPUZBTFNFfQpjb2xQYWxldHMgPSBjKCJyZWQiLCAidmlvbGV0IiwgInBpbmsiLCAib3JhbmdlIiwgInllbGxvdyIsICJncmVlbiIsICJibHVlIiwgImN5YW4iKQptYW5pcHVsYXRlKAogIHBsb3QoMCwwLHBjaD1teU1hcmtlcnMsY2V4PTUsY29sPW15Q29sb3JzLCBtYWluPXRpdGxlLCB4bGFiPXhsYWJlbCwgeWxhYj15bGFiZWwpLAogIG15Q29sb3JzPXBpY2tlcihhcy5saXN0KGNvbFBhbGV0cyksaW5pdGlhbD1jb2xQYWxldHNbMl0pLAogIG15TWFya2Vycz1waWNrZXIoYXMubGlzdChzZXEoMSw4KSksaW5pdGlhbD0iNSIpCikKYGBgCgojIyMg44OX44Ot44OD44OI44K144Kk44K644Gu6YG45oqeCiogc2xpZGVyKCnplqLmlbAKYGBge3IsZXJyb3I9RkFMU0UsZXZhbD1GQUxTRX0KbWFuaXB1bGF0ZSgKICBwbG90KDAsMCxwY2g9OCxjZXg9bXlTaXplLGNvbD0iYmx1ZSIpLAogIG15U2l6ZT1zbGlkZXIoMSwxMCxpbml0aWFsPTUsc3RlcD0yKQopCmBgYAoKIyMgZ2V0V29yZEZyZXHplqLmlbAKLSBnZXRXb3JkTHN0CmBgYHtyLCBlY2hvPUZBTFNFfQpnZXRXb3JkRnJlcTwtIGZ1bmN0aW9uKGZuYW1lKSB7CiAgICB0eHQ8LXJlYWRMaW5lcyhmbmFtZSkKICAgIHdvcmRMc3Q8LXN0cnNwbGl0KHR4dCwiXFxzfFxcVyIpCiAgICB3b3JkTHN0PC11bmxpc3Qod29yZExzdCkKICAgIHdvcmRMc3Q8LXRvbG93ZXIod29yZExzdCkKICAgIHdvcmRMc3Q8LSB3b3JkTHN0W3dvcmRMc3QgIT0gIiJdCiAgICB3b3JkRnJlcTwtc29ydCh0YWJsZSh3b3JkTHN0KSxkZWNyZWFzaW5nPVRSVUUpCiAgICByZXR1cm4od29yZEZyZXEpCn0KYGBgCgojIyDljZjoqp7poLvluqbooagKYGBge3J9CndkTHN0LkJCQyA8LSBnZXRXb3JkRnJlcSgiRzcvQkJDLnR4dCIpCmhlYWQod2RMc3QuQkJDKQpgYGAKCgojIyDoibLku5jjgY3mo5LjgrDjg6njg5UKYGBge3J9CmNvbG9yOCA9IGMoInJlZCIsICJ2aW9sZXQiLCAicGluayIsICJvcmFuZ2UiLCAieWVsbG93IiwgImdyZWVuIiwgImJsdWUiLCAiY3lhbiIpCmJhcnBsb3Qod2RMc3QuQkJDLCBsYXM9Myxjb2w9Y29sb3I4LHlsYWI9IkZyZXF1ZW5jeSIpCmBgYAoKYGBge3J9Cmxlbmd0aCh3ZExzdC5CQkMpCmJhcnBsb3Qod2RMc3QuQkJDWzE6bGVuZ3RoKHdkTHN0LkJCQyldLCBsYXM9Myxjb2w9Y29sb3I4LHlsYWI9IkZyZXF1ZW5jeSIpCmBgYAoKIyMjIDxhIGhyZWY9Imh0dHBzOi8vaHRzdWRhLm5ldC9zdGF0cy9wbG90Lmh0bWwiIHRhcmdldD0iX2JsYW5rIj5sYXM6IGxhYmVsIHN0eWxlPC9hPgpgYGAKbGFzID0gMCA6IFhZ44Gu5Lih6Lu444Go44KC55uu55ub44KK5paH5a2X44Gv6Lu45pa55ZCR77yI44OH44OV44Kp44Or44OI77yJCmxhcyA9IDEgOiBYWeOBruS4oei7uOOBqOOCguebruebm+OCiuaWh+Wtl+OBr+awtOW5s+aWueWQkQpsYXMgPSAyIDogWFnjga7kuKHou7jjgajjgoLnm67nm5vjgormloflrZfjga/ou7jmlrnlkJHjgajnm7Top5IKbGFzID0gMyA6IFhZ44Gu5Lih6Lu444Go44KC55uu55ub44KK5paH5a2X44Gv5Z6C55u05pa55ZCRCmBgYApgYGB7cn0KbWF4LkluZGV4PC0xMApiYXJwbG90KHdkTHN0LkJCQ1sxOm1heC5JbmRleF0sIGxhcz0zLGNvbD1jb2xvcjgseWxhYj0iRnJlcXVlbmN5IikKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7ICI+57e057+SMTwvc3Bhbj46bWFuaXB1bGF0ZemWouaVsOOBp+OAgXdkTHN0LkJCQ+WNmOiqnumgu+W6puajkuOCsOODqeODleOBruS7peS4i+OBrjLngrnjgpLjgqTjg7Pjgr/jg6njgq/jg4bjgqPjg5bjgavlpInmm7TjgafjgY3jgovjgojjgYbjgavjgZfjgabjgY/jgaDjgZXjgYTjgIIKCi3ou7jjg6njg5njg6vjga7lkJHjgY0KLXdkTHN0LkJCQ+OBruWNmOiqnuacgOWkp+ihqOekuuaVsO+8iOacgOWwj+WApD01LOacgOWkp+WApD3lhajlh7rnj77mlbDvvIhUeXBlc++8iSxTdGVwPTIw77yJCgoqIOWun+ihjOe1kOaenOS+i+OBr+OAgemFjeW4g+izh+aWmeOBruWLleeUu+OCkuWPgueFpwoKIyMgPGEgaHJlZj0iaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL1JDb2xvckJyZXdlci9SQ29sb3JCcmV3ZXIucGRmIiB0YXJnZXQ9Il9ibGFuayI+UkNvbG9yQnJld2VyIFBhY2thZ2U8L2E+CiMjIyDjg6njgqTjg5bjg6njg6rjga7oqq3jgb/ovrzjgb8KYGBge3J9CmxpYnJhcnkod29yZGNsb3VkKQpgYGAKCiMjIyDjg5Hjg6zjg4Pjg4jmg4XloLEKYGBge3J9CmJpbmZvPC1icmV3ZXIucGFsLmluZm9bXQpoZWFkKGJpbmZvKQpgYGAKCiMjIyDjg5Hjg6zjg4Pjg4jjga7mir3lh7oKYGBge3J9CnBhbGV0cyA8LXJvd25hbWVzKGJpbmZvW2JpbmZvJG1heGNvbG9ycz4xMCxdKQpwYWxldHMKYGBgCgojIyMgdXNpbmcgYSBicmV3ZXIucGFsZXQKYGBge3J9CnBhbGV0c1sxMF0jIlBhaXJlZCIKbWF4LkluZGV4PC0yMApiYXJwbG90KHdkTHN0LkJCQ1sxOm1heC5JbmRleF0sIGxhcz0zLGNvbD1icmV3ZXIucGFsKDEwLHBhbGV0c1sxXSkseWxhYj0iRnJlcXVlbmN5IikKYGBgCiMjIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmNhbWJyaWRnZS5vcmcvY29yZS9ib29rcy9hYnMvc2VudGltZW50LWFuYWx5c2lzL2ludHJvZHVjdGlvbi8yRkY0RDJFNTNGRjJEQUI1NDQyMTFBRDdBNzNGQ0RCRSIgdGFyZ2V0PSJfYmxhbmsiPlNlbnRpbWVudCBBbmFseXNpczwvYT4KIyMjICDlj4LogIPjgrXjgqTjg4gKLSA8YSBocmVmPSJodHRwczovL3Byb2dyYW1taW5naGlzdG9yaWFuLm9yZy9lbi9sZXNzb25zL3NlbnRpbWVudC1hbmFseXNpcy1zeXV6aGV0IiB0YXJnZXQ9Il9ibGFuayI+U2VudGltZW50IEFuYWx5c2lzIHdpdGggJ3N5dXpoZXQnIHVzaW5nIFI8L2E+Ci0gPGEgaHJlZj0iaHR0cHM6Ly93d3cudGlkeXRleHRtaW5pbmcuY29tL3NlbnRpbWVudCIgdGFyZ2V0PSJfYmxhbmsiPlNlbnRpbWVudCBhbmFseXNpcyB3aXRoIHRpZHkgZGF0YTwvYT4KCiMjIyBzeXV6aGV044OR44OD44Kx44O844K444Gu44Kk44Oz44K544OI44O844OrCmBgYHtyLCBldmFsPUZBTFNFfQppbnN0YWxsLnBhY2thZ2VzKCJzeXV6aGV0IikKYGBgCgojIyMg44Op44Kk44OW44Op44Oq44Gu6Kqt44G/6L6844G/CmBgYHtyfQpsaWJyYXJ5KHN5dXpoZXQpCmBgYAoKIyMjIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmFsamF6ZWVyYS5jb20vbmV3cy8yMDIzLzExLzgvZzctbmF0aW9ucy11bmFuaW1vdXNseS1jYWxsLWZvci1odW1hbml0YXJpYW4tcGF1c2VzLWluLWlzcmFlbC1nYXphLXdhciIgdGFyZ2V0PSJfYmxhbmsiPlNlbnRpbWVudCBhbmFseXNpcyBvZiBhbiBBbGphemVlcmEgYXJ0aWNsZTwvYT4KCiMjIyDjg4bjgq3jgrnjg4jjg5XjgqHjgqTjg6vjga7oqq3jgb/ovrzjgb8KYGBge3J9CnRleHQxX3N0cmluZyA8LSBnZXRfdGV4dF9hc19zdHJpbmcoIkc3L0FsamF6ZWVyYS50eHQiKQpgYGAKIyMjIOODiOODvOOCr+ODs+WMlgpgYGB7cn0KdGV4dDFfd29yZHMgPC0gZ2V0X3Rva2Vucyh0ZXh0MV9zdHJpbmcpCmhlYWQodGV4dDFfd29yZHMpCmBgYAojIyMgVG9rZW5zCmBgYHtyfQpsZW5ndGgodGV4dDFfd29yZHMpCmBgYAojIyMg5oSf5oOF5b6X54K544Gu5Y+W5b6XCmBgYHtyfQp0ZXh0MV9zZW50aW1lbnRfc2NvcmVzIDwtIGdldF9ucmNfc2VudGltZW50KHRleHQxX3dvcmRzKQpgYGAKIyMjIOimluimmuWMlgpgYGB7cn0KYmFycGxvdCgKICBjb2xTdW1zKHByb3AudGFibGUodGV4dDFfc2VudGltZW50X3Njb3Jlc1ssIDE6OF0pKSwKICBzcGFjZSA9IDAuMSwKICBob3JpeiA9IFRSVUUsCiAgbGFzID0gMSwKICBjZXgubmFtZXMgPSAwLjcsCiAgY29sID0gYnJld2VyLnBhbChuID0gOCwgbmFtZSA9ICJTZXQzIiksCiAgbWFpbiA9ICJBbGphemVlcmEsIDggTm92IDIwMjMiLAogIHN1YiA9ICJBTCBKQVpFRVJBIEFORCBORVdTIEFHRU5DSUVTIiwKICB4bGFiPSJlbW90aW9ucyIsIHlsYWIgPSBOVUxMKQpgYGAKCiMjIyA8YSBocmVmPSJodHRwczovL3d3dy5iYmMuY29tL25ld3Mvd29ybGQtZXVyb3BlLTY3MzU1NDIzIiB0YXJnZXQ9Il9ibGFuayI+U2VudGltZW50IGFuYWx5c2lzIG9mIGFuIEJCQyBhcnRpY2xlPC9hPgojIyMg44OG44Kt44K544OI44OV44Kh44Kk44Or44Gu6Kqt44G/6L6844G/77yG44OI44O844Kv44Oz5YyWCmBgYHtyfQp0ZXh0Ml9zdHJpbmcgPC0gZ2V0X3RleHRfYXNfc3RyaW5nKCJHNy9CQkMudHh0IikKdGV4dDJfd29yZHMgPC0gZ2V0X3Rva2Vucyh0ZXh0Ml9zdHJpbmcpCmhlYWQodGV4dDJfd29yZHMpCmBgYAojIyMg5oSf5oOF5b6X54K544Gu5Y+W5b6XCmBgYHtyfQp0ZXh0Ml9zZW50aW1lbnRfc2NvcmVzIDwtIGdldF9ucmNfc2VudGltZW50KHRleHQyX3dvcmRzKQpgYGAKIyMjIOimluimmuWMlgpgYGB7cn0KYmFycGxvdCgKICBjb2xTdW1zKHByb3AudGFibGUodGV4dDJfc2VudGltZW50X3Njb3Jlc1ssIDE6OF0pKSwKICBzcGFjZSA9IDAuMSwKICBob3JpeiA9IFRSVUUsCiAgbGFzID0gMSwKICBjZXgubmFtZXMgPSAwLjgsCiAgY29sID0gYnJld2VyLnBhbChuID0gOCwgbmFtZSA9ICJTZXQzIiksCiAgbWFpbiA9ICJCQkMsIDggTm92IDIwMjMiLAogIHN1YiA9ICJCeSBJZG8gVm9jayBCQkMgTmV3cyIsCiAgeGxhYj0iZW1vdGlvbnMiLCB5bGFiID0gTlVMTCkKYGBgCiMjIyAy44Gk44Gu44OH44O844K/44KS5YiX57WQ5ZCICmBgYHtyfQpzZW50aURhdGE8LWNiaW5kKGNvbFN1bXMocHJvcC50YWJsZSh0ZXh0MV9zZW50aW1lbnRfc2NvcmVzWywgMTo4XSkpLGNvbFN1bXMocHJvcC50YWJsZSh0ZXh0Ml9zZW50aW1lbnRfc2NvcmVzWywgMTo4XSkpKQpzZW50aURhdGEKY29sbmFtZXMoc2VudGlEYXRhKSA8LSBjKCJBTEpBWkVFUkEiLCJCQkMiKQpgYGAKIyMjIDLjgaTjga7jg4fjg7zjgr/jgpLkuKbjgbnjgabooajnpLoKYGBge3J9CmJhcnBsb3Qoc2VudGlEYXRhLAogICAgICAgIHNwYWNlID0gMC4xLAogICAgICAgIGhvcml6ID0gVFJVRSwKICAgICAgICBsYXMgPSAxLAogICAgICAgIGNleC5uYW1lcyA9IDAuOCwKICAgICAgICBjb2wgPSBicmV3ZXIucGFsKG4gPSA4LCBuYW1lID0gIlNldDMiKSwKICAgICAgICBsZWdlbmQudGV4dCA9IHJvd25hbWVzKHNlbnRpRGF0YSksCiAgICAgICAgeGxhYiA9ICJTZW50aW1lbnQgU2NvcmUgUmF0aW8iLCAKICAgICAgICB5bGFiID0gIkFydGljbGUiLAogICAgICAgIG1haW4gPSAiIikKYGBgCg==