Lecture07: Shiny

感情分析の補足:

ライブラリの読み込み

library(syuzhet)

Sentiment analysis of an Aljazeera article

  • テキストファイルの1行ずつ読み込み
text1_Lines <- readLines("G7/Aljazeera.txt")
text1_Lines[1]
[1] "Top diplomats from the Group of Seven (G7) have called for “humanitarian pauses” in Israel’s bombardment in order to deliver aid to desperate Palestinian civilians in the Gaza Strip."
  • トークン化
(text1_1_words <- get_tokens(text1_Lines[1]))
 [1] "top"          "diplomats"    "from"         "the"         
 [5] "group"        "of"           "seven"        "g7"          
 [9] "have"         "called"       "for"          "humanitarian"
[13] "pauses"       "in"           "israel"       "s"           
[17] "bombardment"  "in"           "order"        "to"          
[21] "deliver"      "aid"          "to"           "desperate"   
[25] "palestinian"  "civilians"    "in"           "the"         
[29] "gaza"         "strip"       
  • 感情得点の取得
text1_1_sentiment_scores <- get_nrc_sentiment(text1_1_words)
  • 行名のインデックスを出現単語に変更
row.names(text1_1_sentiment_scores)
 [1] "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10" "11" "12" "13" "14"
[15] "15" "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28"
[29] "29" "30"
row.names(text1_1_sentiment_scores)<-NULL
row.names(text1_1_sentiment_scores)<-make.unique(text1_1_words)
  • 感情得点の相対頻度の算出(総数1)
View(prop.table(text1_1_sentiment_scores[, 1:8]))

“top”のsentiment_score

(tmp<-text1_1_sentiment_scores[1,1:8])
text1_1_sentiment_scores[, 1:8]
sum(text1_1_sentiment_scores[, 1:8])
[1] 9
tmp/sum(text1_1_sentiment_scores[, 1:8])

全テキスト感情得点の取得

text1_string <- get_text_as_string("G7/Aljazeera.txt")
text1_words <- get_tokens(text1_string)
text1_sentiment_scores <- get_nrc_sentiment(text1_words)

感情カテゴリ別集計

SentTotal<-colSums(prop.table(text1_sentiment_scores[, 1:8]))
sort(SentTotal,decreasing=TRUE)
       trust         fear anticipation          joy      sadness 
  0.28571429   0.20000000   0.15714286   0.10000000   0.10000000 
       anger     surprise      disgust 
  0.08571429   0.05714286   0.01428571 

感情カテゴリ内単語情報:trust

id<-which(text1_sentiment_scores$trust>0)
sort(table(text1_words[id]),decreasing=TRUE)

        food humanitarian         bank      medical    statement 
           3            3            2            2            2 
      agreed    committed     continue      leading        peace 
           1            1            1            1            1 
     shelter          top       united 
           1            1            1 

感情カテゴリ内単語情報:fear

id<-which(text1_sentiment_scores$fear>0)
sort(table(text1_words[id]),decreasing=TRUE)

         war  bombardment      medical        broke condemnation 
           3            2            2            1            1 
   displaced         fire     military       urgent     violence 
           1            1            1            1            1 

視覚化: Rader chart

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

install.packages("fmsb")

ライブラリの読み込み

library("fmsb")

radarchart関数で描画

参考サイトのコードを土台に作成

#最大、最小データの準備
index<-1:8
SentimentLabels <- names(text1_sentiment_scores)
maxmin <- data.frame(
  lapply(index,function(i) assign(SentimentLabels[i], c(0.3,0), envir = globalenv()) )
)
names(maxmin)<-SentimentLabels[index]

scores <-colSums(prop.table(text1_sentiment_scores[, 1:8]))
dat <- data.frame(
  lapply(index,function(i) assign(sentiments[i], scores[i], envir = globalenv()) )
  )
names(dat)<-SentimentLabels[index]
dat <- rbind(maxmin, dat) #データの結合

####radarchartの設定##### 
#centerzero = TRUEで中心が0
#axistype:軸基準設定,0:無し, 1:割合, 2:実数, 3:割合,実数, 4:最大を1, 5:最大を1,実数
#seg:分割数
#plty:線の種類
#vlcex:ラベルの大きさ
radarchart(dat, axistype = 2, seg = 8, plty = 1, pcol="blue", vlcex = 1.,
           centerzero = TRUE, vlabels = colnames(dat),cglcol ="gray",
           title = "NRC Emotions in AL JAZEERA Text (8 Nov 2023)")

# default: pcol=1:8 (1:black, 2:red, 3:green, 4:blue, 5:cyan, 6:magenta, 7:yellow, 8:gray)

Sentiment analysis of an BBC articleの感情得点

text2_string <- get_text_as_string("G7/BBC.txt")
text2_words <- get_tokens(text2_string)
text2_sentiment_scores <- get_nrc_sentiment(text2_words)

radarchart関数で描画

#最大、最小データの準備
index<-1:8
SentimentLabels <- names(text1_sentiment_scores)
maxmin <- data.frame(
  lapply(index,function(i) assign(SentimentLabels[i], c(0.3,0), envir = globalenv()) )
)
names(maxmin)<-SentimentLabels[index]

scores1<-colSums(prop.table(text1_sentiment_scores[, 1:8]))
scores2<-colSums(prop.table(text2_sentiment_scores[, 1:8]))
scores <-mapply(c,scores1,scores2)

RNGkind("Mersenne-Twister")
dat <- data.frame(
  lapply(index,function(i) assign(sentiments[i], scores[,i], envir = globalenv()) )
  )
names(dat)<-SentimentLabels[index]
dat <- rbind(maxmin, dat)

radarchart(dat, axistype = 2, seg = 8, plty = 1, vlcex = 1., pcol=c(2,3),
           centerzero = TRUE, vlabels = colnames(dat), cglcol ="gray",
           title = "NRC Emotions in AL JAZEERA & BBC (8 Nov 2023)")

shiny

Shiny apps Demo

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

install.packages("shiny", dependencies = TRUE)

shinyパッケージのロード

library(shiny)

Shiny app作成手順

  1. Shiny appのフォルダを作成
  2. ui.R, server.R, (global.R)のスクリプトファイルを作成
  3. runApp(フォルダ名)で実行

app_hoge

  • server.R
  • ui.R ### Shinyアプリケーション”app_hoge”の実行
runApp("app_hoge")

app_hoge2

  • server.R
  • ui.R
  • global.R

Shinyアプリケーション”app_hoge2”の実行

runApp("app_hoge2")

プロットマーカーのアプリケーション1”app_pch1”の実行

runApp("app_pch1")

プロットマーカーのアプリケーション2”app_pch2”の実行

runApp("app_pch2")

Shinyでアプリケーションを作成する際の注意点

  • UI(外観)部分から作り始める
  • 少しずつコードを書いて、こまめに動作確認
LS0tCnRpdGxlOiAiTGVjMDc6IFNoaW55IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCiMgTGVjdHVyZTA3OiBTaGlueQoKIyMg5oSf5oOF5YiG5p6Q44Gu6KOc6Laz77yaCiMjIyA8YSBocmVmPSJodHRwczovL3NhaWZtb2hhbW1hZC5jb20vV2ViUGFnZXMvTlJDLUVtb3Rpb24tTGV4aWNvbi5odG0iPk5SQyBXb3JkLUVtb3Rpb24gQXNzb2NpYXRpb24gTGV4aWNvbjwvYT4KCiMjIyDjg6njgqTjg5bjg6njg6rjga7oqq3jgb/ovrzjgb8KYGBge3J9CmxpYnJhcnkoc3l1emhldCkKYGBgCgojIyMgU2VudGltZW50IGFuYWx5c2lzIG9mIGFuIEFsamF6ZWVyYSBhcnRpY2xlCi0g44OG44Kt44K544OI44OV44Kh44Kk44Or44GuMeihjOOBmuOBpOiqreOBv+i+vOOBvwpgYGB7cn0KdGV4dDFfTGluZXMgPC0gcmVhZExpbmVzKCJHNy9BbGphemVlcmEudHh0IikKdGV4dDFfTGluZXNbMV0KYGBgCi0g44OI44O844Kv44Oz5YyWCmBgYHtyfQoodGV4dDFfMV93b3JkcyA8LSBnZXRfdG9rZW5zKHRleHQxX0xpbmVzWzFdKSkKYGBgCi0g5oSf5oOF5b6X54K544Gu5Y+W5b6XCmBgYHtyfQp0ZXh0MV8xX3NlbnRpbWVudF9zY29yZXMgPC0gZ2V0X25yY19zZW50aW1lbnQodGV4dDFfMV93b3JkcykKYGBgCgotIOihjOWQjeOBruOCpOODs+ODh+ODg+OCr+OCueOCkuWHuuePvuWNmOiqnuOBq+WkieabtApgYGB7cn0Kcm93Lm5hbWVzKHRleHQxXzFfc2VudGltZW50X3Njb3JlcykKcm93Lm5hbWVzKHRleHQxXzFfc2VudGltZW50X3Njb3Jlcyk8LU5VTEwKcm93Lm5hbWVzKHRleHQxXzFfc2VudGltZW50X3Njb3Jlcyk8LW1ha2UudW5pcXVlKHRleHQxXzFfd29yZHMpCmBgYAotIOaEn+aDheW+l+eCueOBruebuOWvvumgu+W6puOBrueul+WHuu+8iOe3j+aVsO+8ke+8iQpgYGB7cn0KVmlldyhwcm9wLnRhYmxlKHRleHQxXzFfc2VudGltZW50X3Njb3Jlc1ssIDE6OF0pKQpgYGAKCiMjIyMgInRvcCLjga5zZW50aW1lbnRfc2NvcmUKYGBge3J9Cih0bXA8LXRleHQxXzFfc2VudGltZW50X3Njb3Jlc1sxLDE6OF0pCnRleHQxXzFfc2VudGltZW50X3Njb3Jlc1ssIDE6OF0Kc3VtKHRleHQxXzFfc2VudGltZW50X3Njb3Jlc1ssIDE6OF0pCnRtcC9zdW0odGV4dDFfMV9zZW50aW1lbnRfc2NvcmVzWywgMTo4XSkKYGBgCgojIyMg5YWo44OG44Kt44K544OI5oSf5oOF5b6X54K544Gu5Y+W5b6XCmBgYHtyfQp0ZXh0MV9zdHJpbmcgPC0gZ2V0X3RleHRfYXNfc3RyaW5nKCJHNy9BbGphemVlcmEudHh0IikKdGV4dDFfd29yZHMgPC0gZ2V0X3Rva2Vucyh0ZXh0MV9zdHJpbmcpCnRleHQxX3NlbnRpbWVudF9zY29yZXMgPC0gZ2V0X25yY19zZW50aW1lbnQodGV4dDFfd29yZHMpCmBgYAoKIyMjIyDmhJ/mg4Xjgqvjg4bjgrTjg6rliKXpm4boqIgKYGBge3J9ClNlbnRUb3RhbDwtY29sU3Vtcyhwcm9wLnRhYmxlKHRleHQxX3NlbnRpbWVudF9zY29yZXNbLCAxOjhdKSkKc29ydChTZW50VG90YWwsZGVjcmVhc2luZz1UUlVFKQpgYGAKIyMjIyDmhJ/mg4Xjgqvjg4bjgrTjg6rlhoXljZjoqp7mg4XloLE6dHJ1c3QKYGBge3J9CmlkPC13aGljaCh0ZXh0MV9zZW50aW1lbnRfc2NvcmVzJHRydXN0PjApCnNvcnQodGFibGUodGV4dDFfd29yZHNbaWRdKSxkZWNyZWFzaW5nPVRSVUUpCmBgYAojIyMjIOaEn+aDheOCq+ODhuOCtOODquWGheWNmOiqnuaDheWgsTpmZWFyCmBgYHtyfQppZDwtd2hpY2godGV4dDFfc2VudGltZW50X3Njb3JlcyRmZWFyPjApCnNvcnQodGFibGUodGV4dDFfd29yZHNbaWRdKSxkZWNyZWFzaW5nPVRSVUUpCmBgYAojIyMg6KaW6Kaa5YyWOiBSYWRlciBjaGFydAojIyMgPGEgaHJlZj0iaHR0cHM6Ly9taW5hdG8uc2lwMjFjLm9yZy9tc2IvbWFuL2luZGV4Lmh0bWwiIHRhcmdldD0iX2JsYW5rIj5mbXNi44OR44OD44Kx44O844K4PC9hPuOBruOCpOODs+OCueODiOODvOODqwpgYGB7ciwgZXZhbD1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygiZm1zYiIpCmBgYAoKIyMjIOODqeOCpOODluODqeODquOBruiqreOBv+i+vOOBvwpgYGB7cn0KbGlicmFyeSgiZm1zYiIpCmBgYAoKIyMjIDxhIGhyZWY9Imh0dHBzOi8vbWluYXRvLnNpcDIxYy5vcmcvbXNiL21hbi9yYWRhcmNoYXJ0Lmh0bWwiIHRhcmdldD0iX2JsYW5rIj5yYWRhcmNoYXJ06Zai5pWwPC9hPuOBp+aPj+eUuwojIyMjIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmthcmFkYS1nb29kLm5ldC9hbmFseXRpY3NyL3ItMjEvIiB0YXJnZXQ9Il9ibGFuayI+5Y+C6ICD44K144Kk44OIPC9hPuOBruOCs+ODvOODieOCkuWcn+WPsOOBq+S9nOaIkApgYGB7cn0KI+acgOWkp+OAgeacgOWwj+ODh+ODvOOCv+OBrua6luWCmQppbmRleDwtMTo4ClNlbnRpbWVudExhYmVscyA8LSBuYW1lcyh0ZXh0MV9zZW50aW1lbnRfc2NvcmVzKQptYXhtaW4gPC0gZGF0YS5mcmFtZSgKICBsYXBwbHkoaW5kZXgsZnVuY3Rpb24oaSkgYXNzaWduKFNlbnRpbWVudExhYmVsc1tpXSwgYygwLjMsMCksIGVudmlyID0gZ2xvYmFsZW52KCkpICkKKQpuYW1lcyhtYXhtaW4pPC1TZW50aW1lbnRMYWJlbHNbaW5kZXhdCgpzY29yZXMgPC1jb2xTdW1zKHByb3AudGFibGUodGV4dDFfc2VudGltZW50X3Njb3Jlc1ssIDE6OF0pKQpkYXQgPC0gZGF0YS5mcmFtZSgKICBsYXBwbHkoaW5kZXgsZnVuY3Rpb24oaSkgYXNzaWduKHNlbnRpbWVudHNbaV0sIHNjb3Jlc1tpXSwgZW52aXIgPSBnbG9iYWxlbnYoKSkgKQogICkKbmFtZXMoZGF0KTwtU2VudGltZW50TGFiZWxzW2luZGV4XQpkYXQgPC0gcmJpbmQobWF4bWluLCBkYXQpICPjg4fjg7zjgr/jga7ntZDlkIgKCiMjIyNyYWRhcmNoYXJ044Gu6Kit5a6aIyMjIyMgCiNjZW50ZXJ6ZXJvID0gVFJVReOBp+S4reW/g+OBjDAKI2F4aXN0eXBlOui7uOWfuua6luioreWumiwwOueEoeOBlywgMTrlibLlkIgsIDI65a6f5pWwLCAzOuWJsuWQiCzlrp/mlbAsIDQ65pyA5aSn44KSMSwgNTrmnIDlpKfjgpIxLOWun+aVsAojc2VnOuWIhuWJsuaVsAojcGx0eTrnt5rjga7nqK7poZ4KI3ZsY2V4OuODqeODmeODq+OBruWkp+OBjeOBlQpyYWRhcmNoYXJ0KGRhdCwgYXhpc3R5cGUgPSAyLCBzZWcgPSA4LCBwbHR5ID0gMSwgcGNvbD0iYmx1ZSIsIHZsY2V4ID0gMS4sCiAgICAgICAgICAgY2VudGVyemVybyA9IFRSVUUsIHZsYWJlbHMgPSBjb2xuYW1lcyhkYXQpLGNnbGNvbCA9ImdyYXkiLAogICAgICAgICAgIHRpdGxlID0gIk5SQyBFbW90aW9ucyBpbiBBTCBKQVpFRVJBIFRleHQgKDggTm92IDIwMjMpIikKIyBkZWZhdWx0OiBwY29sPTE6OCAoMTpibGFjaywgMjpyZWQsIDM6Z3JlZW4sIDQ6Ymx1ZSwgNTpjeWFuLCA2Om1hZ2VudGEsIDc6eWVsbG93LCA4OmdyYXkpCmBgYAoKIyMjIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmJiYy5jb20vbmV3cy93b3JsZC1ldXJvcGUtNjczNTU0MjMiIHRhcmdldD0iX2JsYW5rIj5TZW50aW1lbnQgYW5hbHlzaXMgb2YgYW4gQkJDIGFydGljbGU8L2E+44Gu5oSf5oOF5b6X54K5CmBgYHtyfQp0ZXh0Ml9zdHJpbmcgPC0gZ2V0X3RleHRfYXNfc3RyaW5nKCJHNy9CQkMudHh0IikKdGV4dDJfd29yZHMgPC0gZ2V0X3Rva2Vucyh0ZXh0Ml9zdHJpbmcpCnRleHQyX3NlbnRpbWVudF9zY29yZXMgPC0gZ2V0X25yY19zZW50aW1lbnQodGV4dDJfd29yZHMpCmBgYAojIyMgPGEgaHJlZj0iaHR0cHM6Ly9taW5hdG8uc2lwMjFjLm9yZy9tc2IvbWFuL3JhZGFyY2hhcnQuaHRtbCIgdGFyZ2V0PSJfYmxhbmsiPnJhZGFyY2hhcnTplqLmlbA8L2E+44Gn5o+P55S7CmBgYHtyfQoj5pyA5aSn44CB5pyA5bCP44OH44O844K/44Gu5rqW5YKZCmluZGV4PC0xOjgKU2VudGltZW50TGFiZWxzIDwtIG5hbWVzKHRleHQxX3NlbnRpbWVudF9zY29yZXMpCm1heG1pbiA8LSBkYXRhLmZyYW1lKAogIGxhcHBseShpbmRleCxmdW5jdGlvbihpKSBhc3NpZ24oU2VudGltZW50TGFiZWxzW2ldLCBjKDAuMywwKSwgZW52aXIgPSBnbG9iYWxlbnYoKSkgKQopCm5hbWVzKG1heG1pbik8LVNlbnRpbWVudExhYmVsc1tpbmRleF0KCnNjb3JlczE8LWNvbFN1bXMocHJvcC50YWJsZSh0ZXh0MV9zZW50aW1lbnRfc2NvcmVzWywgMTo4XSkpCnNjb3JlczI8LWNvbFN1bXMocHJvcC50YWJsZSh0ZXh0Ml9zZW50aW1lbnRfc2NvcmVzWywgMTo4XSkpCnNjb3JlcyA8LW1hcHBseShjLHNjb3JlczEsc2NvcmVzMikKClJOR2tpbmQoIk1lcnNlbm5lLVR3aXN0ZXIiKQpkYXQgPC0gZGF0YS5mcmFtZSgKICBsYXBwbHkoaW5kZXgsZnVuY3Rpb24oaSkgYXNzaWduKHNlbnRpbWVudHNbaV0sIHNjb3Jlc1ssaV0sIGVudmlyID0gZ2xvYmFsZW52KCkpICkKICApCm5hbWVzKGRhdCk8LVNlbnRpbWVudExhYmVsc1tpbmRleF0KZGF0IDwtIHJiaW5kKG1heG1pbiwgZGF0KQoKcmFkYXJjaGFydChkYXQsIGF4aXN0eXBlID0gMiwgc2VnID0gOCwgcGx0eSA9IDEsIHZsY2V4ID0gMS4sIHBjb2w9YygyLDMpLAogICAgICAgICAgIGNlbnRlcnplcm8gPSBUUlVFLCB2bGFiZWxzID0gY29sbmFtZXMoZGF0KSwgY2dsY29sID0iZ3JheSIsCiAgICAgICAgICAgdGl0bGUgPSAiTlJDIEVtb3Rpb25zIGluIEFMIEpBWkVFUkEgJiBCQkMgKDggTm92IDIwMjMpIikKYGBgCiMjIHNoaW55CjxhIGhyZWY9Imh0dHBzOi8vc2hpbnkucnN0dWRpby5jb20vZ2FsbGVyeS8iIHRhcmdldD0iX2JsYW5rIj5TaGlueSBhcHBzIERlbW88L2E+CgojIyMgc2hpbnnjg5Hjg4PjgrHjg7zjgrjjga7jgqTjg7Pjgrnjg4jjg7zjg6sKYGBge3IsIGV2YWw9RkFMU0V9Cmluc3RhbGwucGFja2FnZXMoInNoaW55IiwgZGVwZW5kZW5jaWVzID0gVFJVRSkKYGBgCgojIyMgc2hpbnnjg5Hjg4PjgrHjg7zjgrjjga7jg63jg7zjg4kKYGBge3J9CmxpYnJhcnkoc2hpbnkpCmBgYAoKIyMjIFNoaW55IGFwcOS9nOaIkOaJi+mghgoxLiBTaGlueSBhcHDjga7jg5Xjgqnjg6vjg4DjgpLkvZzmiJAKMi4gdWkuUiwgc2VydmVyLlIsIChnbG9iYWwuUinjga7jgrnjgq/jg6rjg5fjg4jjg5XjgqHjgqTjg6vjgpLkvZzmiJAKMy4gcnVuQXBwKOODleOCqeODq+ODgOWQjSnjgaflrp/ooYwKCiogPGEgaHJlZj0iaHR0cHM6Ly9zaGlueS5yc3R1ZGlvLmNvbS90dXRvcmlhbC93cml0dGVuLXR1dG9yaWFsL2xlc3NvbjEvIiB0YXJnZXQ9Il9ibGFuayI+VHV0b3JpYWw8L2E+CgojIyMgYXBwX2hvZ2UKKiBzZXJ2ZXIuUgoqIHVpLlIKIyMjIFNoaW5544Ki44OX44Oq44Kx44O844K344On44OzImFwcF9ob2dlIuOBruWun+ihjApgYGB7ciwgZXZhbD1GQUxTRX0KcnVuQXBwKCJhcHBfaG9nZSIpCmBgYAoKIyMjIGFwcF9ob2dlMgoqIHNlcnZlci5SCiogdWkuUgoqIGdsb2JhbC5SCgojIyMgU2hpbnnjgqLjg5fjg6rjgrHjg7zjgrfjg6fjg7MiYXBwX2hvZ2UyIuOBruWun+ihjApgYGB7ciwgZXZhbD1GQUxTRX0KcnVuQXBwKCJhcHBfaG9nZTIiKQpgYGAKCiMjIyDjg5fjg63jg4Pjg4jjg57jg7zjgqvjg7zjga7jgqLjg5fjg6rjgrHjg7zjgrfjg6fjg7MxImFwcF9wY2gxIuOBruWun+ihjAoqIDxhIGhyZWY9Imh0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS9yLXBsb3QtcGNoLXN5bWJvbHMtdGhlLWRpZmZlcmVudC1wb2ludC1zaGFwZXMtYXZhaWxhYmxlLWluLXIiIHRhcmdldD0iX2JsYW5rIj5QQ0ggU3ltYm9sczwvYT4KYGBge3IsIGV2YWw9RkFMU0V9CnJ1bkFwcCgiYXBwX3BjaDEiKQpgYGAKCiMjIyDjg5fjg63jg4Pjg4jjg57jg7zjgqvjg7zjga7jgqLjg5fjg6rjgrHjg7zjgrfjg6fjg7MyImFwcF9wY2gyIuOBruWun+ihjApgYGB7ciwgZXZhbD1GQUxTRX0KcnVuQXBwKCJhcHBfcGNoMiIpCmBgYAoKIyMjIFNoaW5544Gn44Ki44OX44Oq44Kx44O844K344On44Oz44KS5L2c5oiQ44GZ44KL6Zqb44Gu5rOo5oSP54K5CiogVUnvvIjlpJboprPvvInpg6jliIbjgYvjgonkvZzjgorlp4vjgoHjgosKKiDlsJHjgZfjgZrjgaTjgrPjg7zjg4njgpLmm7jjgYTjgabjgIHjgZPjgb7jgoHjgavli5XkvZznorroqo0KCg==