主題

分析PTT八卦版對台灣513停電事件的文字資料和社會網絡資料

一、動機與分析目的

  • 背景與動機
    • 五月初臺灣疫情受到華航機師與諾福特酒店事件影響,疫情開始蔓延,加上久旱未雨,各地區面臨了缺水的窘況,就在這疫情與旱象夾擊下的臺灣,5月13日受興達電廠跳機的影響造成全台分區停電、限電的事件。針對這個事件網路媒體是如何看待、是意外事件還是能源政策造成的?
  • 研究目的
    1. 台灣513停電的討論重點有哪些? 主要分為哪幾種風向?。
    2. 目前風向最偏哪邊?
    3. 討論513停電的社群網路如何分布?
    4. 513停電的意見領袖有誰?網友的推噓狀態如何?

1.資料集描述

  • 資料來源:中山大學管理學院文字分析平台收集PTT八卦版文章取得之原始csv檔案。
  • 資料集:PPT八卦版。
  • 資料日期區間:2021.05.13~2021.05.18。
  • 資料的關鍵字:檢索「停電」、「缺電」、「興達」、「電廠」、「興達電廠」五個關鍵字,共搜尋出1113篇文章。

二、前置作業

Sys.setlocale(category = "LC_ALL", locale = "zh_TW.UTF-8") # 避免中文亂碼
[1] ""

安裝需要的packages

packages = c("readr", "dplyr", "jiebaR", "tidyr", "tidytext", "igraph", "topicmodels", "ggplot2", "stringr","text2vec")
existing = as.character(installed.packages()[,1])
for(pkg in packages[!(packages %in% existing)]) install.packages(pkg)

將require及library載入

library(readr)
library(dplyr)
library(jiebaR)
library(tidyr)
library(tidytext)
library(igraph)
library(topicmodels)
library(stringr)
library(ggplot2)
library(reshape2)
library(wordcloud2)
require(text2vec)

載入自平台下載下來的資料

posts <- read_csv("0612-1_articleMetaData.csv") 
reviews <- read_csv("0612-1_articleReviews.csv") 
rd <- read_csv("0612-1_artWordPOSFreq.csv")

資料處理

data <- rd %>% 
  dplyr::select(artDate, artUrl) %>% 
  distinct()
article_count_by_date <- data %>% 
  group_by(artDate) %>% 
  summarise(count = n())
head(article_count_by_date, 20)

文章斷句

# # 文章斷句("\n\n"取代成"。")
mask_meta <- posts %>%
               mutate(sentence=gsub("[\n]{2,}", "。", sentence))
# 
# # 以全形或半形 驚歎號、問號、分號 以及 全形句號 爲依據進行斷句
mask_sentences <- strsplit(mask_meta$sentence,"[。!;?!?;]")
# 
# # 將每句句子,與他所屬的文章連結配對起來,整理成一個dataframe
mask_sentences <- data.frame(
                        artUrl = rep(mask_meta$artUrl, sapply(mask_sentences, length)),
                        sentence = unlist(mask_sentences)
                       ) %>%
                       filter(!str_detect(sentence, regex("^(\t|\n| )*$")))
                       # 如果有\t或\n就去掉
 
mask_sentences$sentence <- as.character(mask_sentences$sentence)
mask_sentences

文章斷詞

# 加入自定義的字典
jieba_tokenizer <- worker(user="user_dict.txt", stop_word = "stop_words.txt")

# 設定斷詞function
chi_tokenizer <- function(t) {
  lapply(t, function(x) {
    if(nchar(x)>1){
      tokens <- segment(x, jieba_tokenizer)
      # 去掉字串長度爲1的詞彙
      tokens <- tokens[nchar(tokens)>1]
      return(tokens)
    }
  })
}

rd_tokens_all <- posts %>%
  unnest_tokens(word, sentence, token=chi_tokenizer) %>% 
  select(-artTime)

# # 用剛剛初始化的斷詞器把sentence斷開
tokens <- mask_sentences %>%
     mutate(sentence = gsub("[[:punct:]]", "",sentence)) %>%
     mutate(sentence = gsub("[0-9a-zA-Z]", "",sentence)) %>%
     unnest_tokens(word, sentence, token=chi_tokenizer) %>%
   count(artUrl, word) %>% # 計算每篇文章出現的字頻
   rename(count=n)
tokens
# save.image(file = "../data/token_result.rdata")

清理斷詞結果

freq = 3
# 依據字頻挑字
reserved_word <- tokens %>% 
  group_by(word) %>% 
  count() %>% 
  filter(n > freq) %>% 
  unlist()

mask_removed <- tokens %>% 
  filter(word %in% reserved_word)

#mask_dtm 裡面 nrow:幾篇文章 ; ncol:幾個字
mask_dtm <- mask_removed %>% cast_dtm(artUrl, word, count) 

三、折線圖

1.台灣大停電事件在PTT八卦5/13~5/18各時段的文章討論數量變化

posts %>% 
  mutate(artDate = as.Date(artDate)) %>%
  group_by(artDate) %>%
  summarise(count = n())%>%
  ggplot(aes(artDate,count))+
    geom_line(color="red")+
    geom_point()

四、文字雲

data <- rd %>% 
  group_by(word) %>% 
  summarise(sum = sum(count), .groups = 'drop') %>% 
  arrange(desc(sum))

data %>% filter(sum > 50) %>% wordcloud2()

五、LDA 主題分類

1.LDA 主題分析

嘗試2、4、6、10、15個主題數,將結果存起來,再做進一步分析。

ldas = c()
topics = c(2,4,6,10,15)
for(topic in topics){
start_time <- Sys.time()
lda <- LDA(mask_dtm, k = topic, control = list(seed = 2021))
ldas =c(ldas,lda)
print(paste(topic ,paste("topic(s) and use time is ", Sys.time() -start_time)))
save(ldas,file = "ldas_result.rdata") # 將模型輸出成檔案
}
[1] "2 topic(s) and use time is  2.0354688167572"
[1] "4 topic(s) and use time is  7.28165197372437"
[1] "6 topic(s) and use time is  16.9567279815674"
[1] "10 topic(s) and use time is  27.2636518478394"
[1] "15 topic(s) and use time is  51.1909809112549"

透過perplexity找到最佳主題數

library(purrr)

Attaching package: 愼㸱愼㸵purrr愼㸱愼㸶

The following objects are masked from 愼㸱愼㸵package:igraph愼㸱愼㸶:

    compose, simplify
topics = c(2,4,6,10,15)
data_frame(k = topics, perplex = map_dbl(ldas, topicmodels::perplexity)) %>%
  ggplot(aes(k, perplex)) +
  geom_point() +
  geom_line() +
  labs(title = "Evaluating LDA topic models",
       subtitle = "Optimal number of topics (smaller is better)",
       x = "Number of topics",
       y = "Perplexity")
`data_frame()` was deprecated in tibble 1.1.0.
Please use `tibble()` instead.

  • 主題數越多,複雜度越低,內容的純度越高。
  • 可以挑選下降幅度減緩的點。

2.LDAvis 六個主題

library(udpipe)
dtf <- document_term_frequencies(tokens, document = "artUrl", term = "word")
dtm <- document_term_matrix(x = dtf)
dtm_clean <- dtm_remove_lowfreq(dtm, minfreq = 30)
dim(dtm_clean)
set.seed(5432)

topic_n = 6

lda_model =text2vec::LDA$new(n_topics = topic_n,doc_topic_prior = 0.1, topic_word_prior = 0.001)
doc_topic_distr =lda_model$fit_transform(dtm_clean, n_iter = 1000, convergence_tol = 1e-5,check_convergence_every_n = 100)
lda_model$get_top_words(n = 10, lambda = 0.5)
lda_model$plot()
lda_model$plot(out.dir ="lda_result", open.browser = TRUE)

將剛處理好的dtm放入LDA函式分析

# LDA分成6個主題
mask_lda <- LDA(mask_dtm, k = 6, control = list(seed = 12345))
#  mask_lda <- LDA(mask_dtm, k = 6, control = list(seed = 12345))

取出代表字詞(term)

removed_word = c("一下","不是","停電","有沒有","電廠") 
# 看各群的常用詞彙
tidy(mask_lda, matrix = "beta") %>% # 取出topic term beta值
  filter(! term %in% removed_word) %>% 
  group_by(topic) %>%
  top_n(13, beta) %>% # beta值前10的字
  ungroup() %>%
  mutate(topic = as.factor(topic),
         term = reorder_within(term, beta, topic)) %>%
  ggplot(aes(term, beta, fill = topic)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ topic, scales = "free") +
  coord_flip() +
  scale_x_reordered()

可以歸納出
topic 1 = “討論為何停電”
topic 2 = “各家新聞報導內容”
topic 3 = “抱怨停電”
topic 4 = “討論政府針對缺水、疫情、缺電的政策”
topic 5 = “討論政府的能源政策”
topic 6 = “討論分區停電”
以下我們挑出第1個主題、第3個主題和第4個主題來做比較。

取出代表主題(topic)

# 在tidy function中使用參數"gamma"來取得 theta矩陣
mask_topics <- tidy(mask_lda, matrix="gamma") %>% # document topic gamma
                  group_by(document) %>%
                  top_n(1, wt=gamma)
mask_topics

3.資料內容探索

posts_topic <- merge(x = posts, y = mask_topics, by.x = "artUrl", by.y="document")

# 看一下各主題在說甚麼
set.seed(12345)
posts_topic %>% # 主題一
  filter(topic==1) %>%
  select(artTitle) %>%
  unique() %>%
  sample_n(12)
posts_topic %>% # 主題二
  filter(topic==2) %>%
  select(artTitle) %>%
  unique() %>%
  sample_n(12)
posts_topic %>% # 主題三
  filter(topic==3) %>%
  select(artTitle) %>%
  unique() %>%
  sample_n(12)
posts_topic %>% # 主題四
  filter(topic==4) %>%
  select(artTitle) %>%
  unique() %>%
  sample_n(12)
posts_topic %>% # 主題五
  filter(topic==5) %>%
  select(artTitle) %>%
  unique() %>%
  sample_n(12)
posts_topic %>% # 主題六
  filter(topic==6) %>%
  select(artTitle) %>%
  unique() %>%
  sample_n(12)

4.日期主題分布

posts_topic %>%
  mutate(artDate = as.Date(artDate)) %>% 
  group_by(artDate,topic) %>%
  summarise(sum =sum(topic)) %>%
  ggplot(aes(x= artDate,y=sum,fill=as.factor(topic))) +
  geom_col(position="fill") 
`summarise()` has grouped output by 'artDate'. You can override using the `.groups` argument.

posts_topic %>%
  group_by(artCat,topic) %>%
  summarise(sum = n())  %>%
  ggplot(aes(x= artCat,y=sum,fill=as.factor(topic))) +
  geom_col(position="dodge") 
`summarise()` has grouped output by 'artCat'. You can override using the `.groups` argument.

topic 1 = “討論為何停電”
topic 2 = “各家新聞報導內容”
topic 3 = “抱怨停電”
topic 4 = “討論政府針對缺水、疫情、缺電的政策”
topic 5 = “討論政府的能源政策”
topic 6 = “討論分區停電”

六、社群網路圖

資料合併

# 文章和留言
reviews <- reviews %>%
      select(artUrl, cmtPoster, cmtStatus, cmtContent)
posts_Reviews <- merge(x = posts, y = reviews, by = "artUrl")

# 把文章和topic
posts_Reviews <- merge(x = posts_Reviews, y = mask_topics, by.x = "artUrl", by.y="document")
head(posts_Reviews,3)

取出 cmtPoster(回覆者)、artPoster(發文者)、artUrl(文章連結) 三個欄位

link <- posts_Reviews %>% select(cmtPoster, artPoster, artUrl)
head(link,3)

1.基本網路圖

建立網路關係

reviewNetwork <- graph_from_data_frame(d=link, directed=T)
reviewNetwork
IGRAPH 342d22d DN-- 165 184 -- 
+ attr: name (v/c), artUrl (e/c), cmtStatus (e/c)
+ edges from 342d22d (vertex names):
 [1] Annis812    ->thelittleone pttyu       ->GoogleTaiwan a0952864901 ->lolic        onejune     ->lolic        w1230319    ->lolic        bangjia     ->lolic       
 [7] garyyang36  ->lolic        Annis812    ->lolic        garyyang36  ->lolic        Paulsic     ->lolic        shidaeun    ->lolic        Aonian      ->lolic       
[13] catvsdog    ->lolic        catvsdog    ->lolic        zanarland   ->lolic        Aonian      ->lolic        S0031104    ->lolic        S0031104    ->lolic       
[19] aiam        ->dark45662    aiam        ->dark45662    lml99       ->Gunbuster    ffruecek    ->Gunbuster    aikensh     ->Gunbuster    baboosh     ->Gunbuster   
[25] rainbow321  ->Gunbuster    lml99       ->Gunbuster    baboosh     ->Gunbuster    nicky51     ->Gunbuster    HGT7473     ->Gunbuster    baseken     ->Gunbuster   
[31] LukeSkywaker->Minegun      TZUYIC      ->Minegun      howerd11    ->Minegun      howerd11    ->Minegun      other9343   ->Minegun      CruiseTom   ->Minegun     
[37] tokuchi2013 ->Minegun      tokuchi2013 ->Minegun      danwhei     ->kenbo        Senga41     ->kenbo        lml99       ->kenbo        ray88076    ->kenbo       
[43] a8330028    ->kenbo        Senga41     ->kenbo        a8330028    ->kenbo        GhostFather ->currykukuo   mi324       ->currykukuo   EdenEden    ->Aliensoul   
+ ... omitted several edges

2.文章留言數

# 看一下留言數大概都多少(方便後面篩選)
posts %>%
  #filter(commentNum<200) %>%
  ggplot(aes(x=commentNum)) + geom_histogram()

依據發文數或回覆數篩選post和review

## 帳號發文篇數
post_count = posts %>%
  group_by(artPoster) %>%
  summarise(count = n()) %>%
  arrange(desc(count)) 
post_count

## 帳號回覆總數
review_count = reviews %>%
  group_by(cmtPoster) %>%
  summarise(count = n()) %>%
  arrange(desc(count)) 
review_count

## 發文者
poster_select <- post_count %>% filter(count >= 2)
posts <- posts %>%  filter(posts$artPoster %in% poster_select$artPoster)

## 回覆者
reviewer_select <- review_count %>%  filter(count >= 5)
reviews <- reviews %>%  filter(reviews$cmtPoster %in% reviewer_select$cmtPoster)
# 檢視參與人數
length(unique(posts_Reviews$artPoster)) # 發文者數量 911
[1] 911
length(unique(posts_Reviews$cmtPoster)) # 回覆者數量 15224
[1] 15224
allPoster <- c(posts_Reviews$artPoster, posts_Reviews$cmtPoster) # 總參與人數 15641
length(unique(allPoster))
[1] 15641

標記所有出現過得使用者

  • poster:只發過文、發過文+留過言
  • replyer:只留過言
userList <- data.frame(user=unique(allPoster)) %>%
              mutate(type=ifelse(user%in%posts$artPoster, "poster", "replyer"))
head(userList,3)

3.以日期篩選社群

link <- posts_Reviews %>%
      group_by(cmtPoster, artUrl) %>% 
      filter(n()>3) %>% 
      filter(commentNum > 200) %>%
      filter(artCat=="Gossiping") %>% 
      filter(artDate == as.Date('2021-05-13')) %>%
      select(cmtPoster, artPoster, artUrl) %>% 
      unique()
link

篩選在link裡面有出現的使用者

filtered_user <- userList %>%
          filter(user%in%link$cmtPoster | user%in%link$artPoster) %>%
          arrange(desc(type))
head(filtered_user,3)

因爲圖片箭頭有點礙眼,所以這裏我們先把關係的方向性拿掉,減少圖片中的不必要的資訊 set.seed 因為igraph呈現的方向是隨機的

set.seed(12345)
# v=filtered_user
reviewNetwork = degree(reviewNetwork) > 2
reviewNetwork <- graph_from_data_frame(d=link, v=filtered_user, directed=F)
plot(reviewNetwork, vertex.size=3, edge.arrow.size=0.3,vertex.label=NA)

加上nodes的顯示資訊 用使用者的身份來區分點的顏色

  • poster:gold(有發文)
  • replyer:lightblue(只有回覆文章)
set.seed(12345)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")
plot(reviewNetwork, vertex.size=3, edge.arrow.size=0.3,vertex.label=NA)

可以稍微看出圖中的點(人)之間有一定的關聯,不過目前只有單純圖形我們無法分析其中的內容。
因此以下我們將資料集中的資訊加到我們的圖片中。

為點加上帳號名字,用degree篩選要顯示出的使用者,以免圖形被密密麻麻的文字覆蓋

filter_degree = 5
set.seed(12345)
# 設定 node 的 label/ color
labels <- degree(reviewNetwork) # 算出每個點的degree
V(reviewNetwork)$label <- names(labels)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")
plot(
  reviewNetwork, 
  vertex.size=3, 
  edge.width=3, 
  vertex.label.dist=1,
  vertex.label=ifelse(degree(reviewNetwork) > filter_degree, V(reviewNetwork)$label, NA),vertex.label.font=2)

我們可以看到基本的使用者關係,但是我們希望能夠將更進階的資訊視覺化。
例如:使用者經常參與的文章種類,或是使用者在該社群網路中是否受到歡迎。

4.以主題篩選社群

  • 抓link

挑選出2021-05-13當天的文章, 篩選一篇文章回覆3次以上者,且文章留言數多餘60則, 文章主題歸類為1、3與4者, 欄位只取:cmtPoster(評論者), artPoster(發文者), artUrl(文章連結), topic(主題)

link <- posts_Reviews %>%
      group_by(cmtPoster, artUrl) %>% 
      filter(n()>3) %>% 
      filter(commentNum > 60) %>%
      filter(artCat=="Gossiping") %>% #HatePolitics / Gossiping
      filter(artDate == as.Date('2021-05-13')) %>%
      filter( topic == 1 | topic == 3 | topic == 4) %>% 
      dplyr::select(cmtPoster, artPoster, artUrl, topic) %>% 
      unique()
link

+抓nodes 在所有的使用者裡面,篩選link中有出現的使用者

filtered_user <- userList %>%
          filter(user%in%link$cmtPoster | user%in%link$artPoster) %>%
          arrange(desc(type))
head(filtered_user,3)

5.使用者經常參與的文章種類

filter_degree = 2

# 建立網路關係
reviewNetwork <- graph_from_data_frame(d=link, v=filtered_user, directed=F)

# 依據使用者身份對點進行上色
labels <- degree(reviewNetwork)
V(reviewNetwork)$label <- names(labels)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")

# 依據回覆發生的文章所對應的主題,對他們的關聯線進行上色
E(reviewNetwork)$color <- ifelse(E(reviewNetwork)$topic == "1", "palevioletred",ifelse((E(reviewNetwork)$topic =="3"),"lightgreen","deepskyblue" ))

# 畫出社群網路圖
set.seed(12345)
plot(reviewNetwork, vertex.size=3, edge.width=3, vertex.label.dist=1,
     vertex.label=ifelse(degree(reviewNetwork) > filter_degree, V(reviewNetwork)$label, NA),vertex.label.font=2)

# 加入標示
legend("bottomright", c("發文者","回文者"), pch=21,
  col="#777777", pt.bg=c("gold","lightblue"), pt.cex=1, cex=1)
legend("topleft", c("討論為何停電","抱怨停電","討論政府對缺水、疫情、缺電的政策"),
  col=c("palevioletred", "lightgreen","deepskyblue"), lty=1, cex=1)

6.使用者是否受到歡迎

PTT的回覆有三種,推文、噓文、箭頭,我們只要看推噓就好,因此把箭頭清掉,這樣資料筆數較少,所以我們把篩選的條件放寬一些。

filter_degree = 1 # 使用者degree

# 過濾留言者對發文者的推噓程度
link <- posts_Reviews %>%
      filter(artCat=="Gossiping") %>% 
      filter(commentNum > 40) %>%
      filter(cmtStatus!="→") %>%
      group_by(cmtPoster, artUrl) %>%
      filter( n() > 2) %>%
      ungroup() %>% 
      dplyr::select(cmtPoster, artPoster, artUrl, cmtStatus) %>% 
      unique()

# 接下來把網路圖畫出來,跟前面做的事都一樣,因此不再細述
# 篩選link中有出現的使用者
filtered_user <- userList %>%
          filter(user%in%link$cmtPoster | user%in%link$artPoster) %>%
          arrange(desc(type))

# 建立網路關係
reviewNetwork <- graph_from_data_frame(d=link, v=filtered_user, directed=F)

# 依據使用者身份對點進行上色
labels <- degree(reviewNetwork)
V(reviewNetwork)$label <- names(labels)
V(reviewNetwork)$color <- ifelse(V(reviewNetwork)$type=="poster", "gold", "lightblue")


# 依據回覆發生的文章所對應的主題,對他們的關聯線進行上色
E(reviewNetwork)$color <- ifelse(E(reviewNetwork)$cmtStatus == "推", "lightgreen", "palevioletred")

# 畫出社群網路圖
set.seed(12345)
plot(reviewNetwork, vertex.size=2, edge.width=3, vertex.label.dist=1,
     vertex.label=ifelse(degree(reviewNetwork) > filter_degree, V(reviewNetwork)$label, NA),vertex.label.font=2)

# 加入標示
legend("bottomright", c("發文者","回文者"), pch=21,
  col="#777777", pt.bg=c("gold","lightblue"), pt.cex=1, cex=1)
legend("topleft", c("推","噓"), 
       col=c("lightgreen","palevioletred"), lty=1, cex=1)

可以發現本次的討論中幾乎都是推文、噓文較少

七、總結

1.513停電事件的討論重點有哪些? 主要分為哪幾種風向?
對於2021-05-13 ~ 2021-05-18收集的文章,大概可以分成討論政府的討論為何停電、抱怨停電和討論政府針對缺水、疫情、缺電的政策這三個主題,其他還有各家新聞報導內容、討論政府的能源政策以及討論分區停電等三個主題。

2.目前風向最偏哪邊?
針對停電事件PTT上主要以討論為何停電與抱怨停電的文章居多。

3.討論513停電事件的社群網路如何分布?
以社群文章數來看,討論為何停電的網友較多。

4.513停電事件的意見領袖有誰?網友的推噓狀態如何?
因為資料選取的時間較短,只要幾篇回覆量高的貼文,就有機會成為社群中心,在八卦版上,以報導討論為主的意見領袖有:
- 討論為何停電的意見領袖為logyin,大多都是正面推文。
- 抱怨停電的意見領袖lolic ,推文多、噓文少。
- 討論政府針對缺水、疫情、缺電的政策的意見領袖computerqqq,也是推文多、噓文少。

LS0tDQp0aXRsZTogIuekvue+pOWqkumrlOWIhuaekOacn+acq+WgseWRiuesrOWNgeS5nee1hC3mjqLoqI5wdHTlhavljabmnb/lsI3lj7DngaPlgZzpm7vkuovku7bnmoTnnIvms5UiDQphdXRob3I6ICJOMDk0MDIwMDE3IOael+elkOaWsCwgTjA5NDAyMDAzNCDolKHoirjlubMsIE4wOTQwMjAwMzIg6YSS5bKx5L2RLCBOMDk0MDIwMDAxIOWui+aYjuavhSINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGhpZ2hsaWdodDogcHlnbWVudHMNCiAgICB0aGVtZTogZmxhdGx5DQogICAgY3NzOiBzdHlsZS5jc3MNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCiMjIOS4u+mhjA0KPiDliIbmnpBQVFTlhavljabniYjlsI3lj7DngaM1MTPlgZzpm7vkuovku7bnmoTmloflrZfos4fmlpnlkoznpL7mnIPntrLntaHos4fmlpkNCg0KIyDkuIDjgIHli5XmqZ/oiIfliIbmnpDnm67nmoQNCi0g6IOM5pmv6IiH5YuV5qmfDQogICsg5LqU5pyI5Yid6Ie654Gj55ar5oOF5Y+X5Yiw6I+v6Iiq5qmf5bir6IiH6Ku+56aP54m56YWS5bqX5LqL5Lu25b2x6Z+/77yM55ar5oOF6ZaL5aeL6JST5bu277yM5Yqg5LiK5LmF5pex5pyq6Zuo77yM5ZCE5Zyw5Y2A6Z2i6Ieo5LqG57y65rC055qE56qY5rOB77yM5bCx5Zyo6YCZ55ar5oOF6IiH5pex6LGh5aS+5pOK5LiL55qE6Ie654Gj77yMNeaciDEz5pel5Y+X6IiI6YGU6Zu75bug6Lez5qmf55qE5b2x6Z+/6YCg5oiQ5YWo5Y+w5YiG5Y2A5YGc6Zu744CB6ZmQ6Zu755qE5LqL5Lu244CC6Yed5bCN6YCZ5YCL5LqL5Lu257ay6Lev5aqS6auU5piv5aaC5L2V55yL5b6F44CB5piv5oSP5aSW5LqL5Lu26YKE5piv6IO95rqQ5pS/562W6YCg5oiQ55qE77yfDQoNCisg56CU56m255uu55qEDQogICAxLiDlj7DngaM1MTPlgZzpm7vnmoToqI7oq5bph43pu57mnInlk6rkups/IOS4u+imgeWIhueCuuWTquW5vueorumiqOWQkT/jgII8L2JyPg0KICAgMi4g55uu5YmN6aKo5ZCR5pyA5YGP5ZOq6YKKPzwvYnI+DQogICAzLiDoqI7oq5Y1MTPlgZzpm7vnmoTnpL7nvqTntrLot6/lpoLkvZXliIbluIM/PC9icj4NCiAgIDMuIDUxM+WBnOmbu+eahOaEj+imi+mgmOiiluacieiqsD/ntrLlj4vnmoTmjqjlmZPni4DmhYvlpoLkvZU/PC9icj4NCg0KIyMgMS7os4fmlpnpm4bmj4/ov7ANCisg6LOH5paZ5L6G5rqQ77ya5Lit5bGx5aSn5a24566h55CG5a246Zmi5paH5a2X5YiG5p6Q5bmz5Y+w5pS26ZuGUFRU5YWr5Y2m54mI5paH56ug5Y+W5b6X5LmL5Y6f5aeLY3N25qqU5qGI44CCDQorIOizh+aWmembhu+8mlBQVOWFq+WNpueJiOOAgg0KKyDos4fmlpnml6XmnJ/ljYDplpPvvJoyMDIxLjA1LjEzfjIwMjEuMDUuMTjjgIINCisg6LOH5paZ55qE6Zec6Y215a2XOuaqoue0ouOAjOWBnOmbu+OAjeOAgeOAjOe8uumbu+OAjeOAgeOAjOiIiOmBlOOAjeOAgeOAjOmbu+W7oOOAjeOAgeOAjOiIiOmBlOmbu+W7oOOAjeS6lOWAi+mXnOmNteWtl++8jOWFseaQnOWwi+WHujExMTPnr4fmlofnq6DjgIINCg0KDQojIOS6jOOAgeWJjee9ruS9nOalrQ0KYGBge3Isd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFfQ0KU3lzLnNldGxvY2FsZShjYXRlZ29yeSA9ICJMQ19BTEwiLCBsb2NhbGUgPSAiemhfVFcuVVRGLTgiKSAjIOmBv+WFjeS4reaWh+S6gueivA0KYGBgDQoNCuWuieijnemcgOimgeeahHBhY2thZ2VzDQpgYGB7ciB3YXJuaW5nPUZBTFNFfQ0KcGFja2FnZXMgPSBjKCJyZWFkciIsICJkcGx5ciIsICJqaWViYVIiLCAidGlkeXIiLCAidGlkeXRleHQiLCAiaWdyYXBoIiwgInRvcGljbW9kZWxzIiwgImdncGxvdDIiLCAic3RyaW5nciIsInRleHQydmVjIikNCmV4aXN0aW5nID0gYXMuY2hhcmFjdGVyKGluc3RhbGxlZC5wYWNrYWdlcygpWywxXSkNCmZvcihwa2cgaW4gcGFja2FnZXNbIShwYWNrYWdlcyAlaW4lIGV4aXN0aW5nKV0pIGluc3RhbGwucGFja2FnZXMocGtnKQ0KYGBgDQoNCuWwh3JlcXVpcmXlj4psaWJyYXJ56LyJ5YWlDQpgYGB7cix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoamllYmFSKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkodGlkeXRleHQpDQpsaWJyYXJ5KGlncmFwaCkNCmxpYnJhcnkodG9waWNtb2RlbHMpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeSh3b3JkY2xvdWQyKQ0KcmVxdWlyZSh0ZXh0MnZlYykNCmBgYA0KDQoNCui8ieWFpeiHquW5s+WPsOS4i+i8ieS4i+S+hueahOizh+aWmQ0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCnBvc3RzIDwtIHJlYWRfY3N2KCIwNjEyLTFfYXJ0aWNsZU1ldGFEYXRhLmNzdiIpIA0KcmV2aWV3cyA8LSByZWFkX2NzdigiMDYxMi0xX2FydGljbGVSZXZpZXdzLmNzdiIpIA0KcmQgPC0gcmVhZF9jc3YoIjA2MTItMV9hcnRXb3JkUE9TRnJlcS5jc3YiKQ0KYGBgDQoNCuizh+aWmeiZleeQhg0KYGBge3J9DQpkYXRhIDwtIHJkICU+JSANCiAgZHBseXI6OnNlbGVjdChhcnREYXRlLCBhcnRVcmwpICU+JSANCiAgZGlzdGluY3QoKQ0KYXJ0aWNsZV9jb3VudF9ieV9kYXRlIDwtIGRhdGEgJT4lIA0KICBncm91cF9ieShhcnREYXRlKSAlPiUgDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkNCmhlYWQoYXJ0aWNsZV9jb3VudF9ieV9kYXRlLCAyMCkNCmBgYA0KDQrmlofnq6Dmlrflj6UNCmBgYHtyfQ0KIyAjIOaWh+eroOaWt+WPpSgiXG5cbiLlj5bku6PmiJAi44CCIikNCm1hc2tfbWV0YSA8LSBwb3N0cyAlPiUNCiAgICAgICAgICAgICAgIG11dGF0ZShzZW50ZW5jZT1nc3ViKCJbXG5dezIsfSIsICLjgIIiLCBzZW50ZW5jZSkpDQojIA0KIyAjIOS7peWFqOW9ouaIluWNiuW9oiDpqZrmrY7omZ/jgIHllY/omZ/jgIHliIbomZ8g5Lul5Y+KIOWFqOW9ouWPpeiZnyDniLLkvp3mk5rpgLLooYzmlrflj6UNCm1hc2tfc2VudGVuY2VzIDwtIHN0cnNwbGl0KG1hc2tfbWV0YSRzZW50ZW5jZSwiW+OAgu+8ge+8m++8nyE/O10iKQ0KIyANCiMgIyDlsIfmr4/lj6Xlj6XlrZDvvIzoiIfku5bmiYDlsaznmoTmlofnq6DpgKPntZDphY3lsI3otbfkvobvvIzmlbTnkIbmiJDkuIDlgItkYXRhZnJhbWUNCm1hc2tfc2VudGVuY2VzIDwtIGRhdGEuZnJhbWUoDQogICAgICAgICAgICAgICAgICAgICAgICBhcnRVcmwgPSByZXAobWFza19tZXRhJGFydFVybCwgc2FwcGx5KG1hc2tfc2VudGVuY2VzLCBsZW5ndGgpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlID0gdW5saXN0KG1hc2tfc2VudGVuY2VzKQ0KICAgICAgICAgICAgICAgICAgICAgICApICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoIXN0cl9kZXRlY3Qoc2VudGVuY2UsIHJlZ2V4KCJeKFx0fFxufCApKiQiKSkpDQogICAgICAgICAgICAgICAgICAgICAgICMg5aaC5p6c5pyJXHTmiJZcbuWwseWOu+aOiQ0KIA0KbWFza19zZW50ZW5jZXMkc2VudGVuY2UgPC0gYXMuY2hhcmFjdGVyKG1hc2tfc2VudGVuY2VzJHNlbnRlbmNlKQ0KbWFza19zZW50ZW5jZXMNCmBgYA0KDQoNCuaWh+eroOaWt+ipng0KYGBge3J9DQojIOWKoOWFpeiHquWumue+qeeahOWtl+WFuA0KamllYmFfdG9rZW5pemVyIDwtIHdvcmtlcih1c2VyPSJ1c2VyX2RpY3QudHh0Iiwgc3RvcF93b3JkID0gInN0b3Bfd29yZHMudHh0IikNCg0KIyDoqK3lrprmlrfoqZ5mdW5jdGlvbg0KY2hpX3Rva2VuaXplciA8LSBmdW5jdGlvbih0KSB7DQogIGxhcHBseSh0LCBmdW5jdGlvbih4KSB7DQogICAgaWYobmNoYXIoeCk+MSl7DQogICAgICB0b2tlbnMgPC0gc2VnbWVudCh4LCBqaWViYV90b2tlbml6ZXIpDQogICAgICAjIOWOu+aOieWtl+S4sumVt+W6pueIsjHnmoToqZ7lvZkNCiAgICAgIHRva2VucyA8LSB0b2tlbnNbbmNoYXIodG9rZW5zKT4xXQ0KICAgICAgcmV0dXJuKHRva2VucykNCiAgICB9DQogIH0pDQp9DQoNCnJkX3Rva2Vuc19hbGwgPC0gcG9zdHMgJT4lDQogIHVubmVzdF90b2tlbnMod29yZCwgc2VudGVuY2UsIHRva2VuPWNoaV90b2tlbml6ZXIpICU+JSANCiAgc2VsZWN0KC1hcnRUaW1lKQ0KDQojICMg55So5Ymb5Ymb5Yid5aeL5YyW55qE5pa36Kme5Zmo5oqKc2VudGVuY2XmlrfplosNCnRva2VucyA8LSBtYXNrX3NlbnRlbmNlcyAlPiUNCiAgICAgbXV0YXRlKHNlbnRlbmNlID0gZ3N1YigiW1s6cHVuY3Q6XV0iLCAiIixzZW50ZW5jZSkpICU+JQ0KICAgICBtdXRhdGUoc2VudGVuY2UgPSBnc3ViKCJbMC05YS16QS1aXSIsICIiLHNlbnRlbmNlKSkgJT4lDQogICAgIHVubmVzdF90b2tlbnMod29yZCwgc2VudGVuY2UsIHRva2VuPWNoaV90b2tlbml6ZXIpICU+JQ0KICAgY291bnQoYXJ0VXJsLCB3b3JkKSAlPiUgIyDoqIjnrpfmr4/nr4fmlofnq6Dlh7rnj77nmoTlrZfpoLsNCiAgIHJlbmFtZShjb3VudD1uKQ0KdG9rZW5zDQojIHNhdmUuaW1hZ2UoZmlsZSA9ICIuLi9kYXRhL3Rva2VuX3Jlc3VsdC5yZGF0YSIpDQpgYGANCg0K5riF55CG5pa36Kme57WQ5p6cDQpgYGB7cn0NCmZyZXEgPSAzDQojIOS+neaTmuWtl+mgu+aMkeWtlw0KcmVzZXJ2ZWRfd29yZCA8LSB0b2tlbnMgJT4lIA0KICBncm91cF9ieSh3b3JkKSAlPiUgDQogIGNvdW50KCkgJT4lIA0KICBmaWx0ZXIobiA+IGZyZXEpICU+JSANCiAgdW5saXN0KCkNCg0KbWFza19yZW1vdmVkIDwtIHRva2VucyAlPiUgDQogIGZpbHRlcih3b3JkICVpbiUgcmVzZXJ2ZWRfd29yZCkNCg0KI21hc2tfZHRtIOijoemdoiBucm93OuW5vuevh+aWh+eroCA7IG5jb2w65bm+5YCL5a2XDQptYXNrX2R0bSA8LSBtYXNrX3JlbW92ZWQgJT4lIGNhc3RfZHRtKGFydFVybCwgd29yZCwgY291bnQpIA0KYGBgDQoNCiMg5LiJ44CB5oqY57ea5ZyWDQoNCiMjIDEu5Y+w54Gj5aSn5YGc6Zu75LqL5Lu25ZyoUFRU5YWr5Y2mNS8xM341LzE45ZCE5pmC5q6155qE5paH56ug6KiO6KuW5pW46YeP6K6K5YyWDQpgYGB7cn0NCnBvc3RzICU+JSANCiAgbXV0YXRlKGFydERhdGUgPSBhcy5EYXRlKGFydERhdGUpKSAlPiUNCiAgZ3JvdXBfYnkoYXJ0RGF0ZSkgJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSklPiUNCiAgZ2dwbG90KGFlcyhhcnREYXRlLGNvdW50KSkrDQogICAgZ2VvbV9saW5lKGNvbG9yPSJyZWQiKSsNCiAgICBnZW9tX3BvaW50KCkNCmBgYA0KDQojIOWbm+OAgeaWh+Wtl+mbsg0KYGBge3J9DQpkYXRhIDwtIHJkICU+JSANCiAgZ3JvdXBfYnkod29yZCkgJT4lIA0KICBzdW1tYXJpc2Uoc3VtID0gc3VtKGNvdW50KSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lIA0KICBhcnJhbmdlKGRlc2Moc3VtKSkNCg0KZGF0YSAlPiUgZmlsdGVyKHN1bSA+IDUwKSAlPiUgd29yZGNsb3VkMigpDQpgYGANCg0KDQojIOS6lOOAgUxEQSDkuLvpoYzliIbpoZ4NCg0KIyMgMS5MREEg5Li76aGM5YiG5p6QDQoNCuWYl+ippjLjgIE044CBNuOAgTEw44CBMTXlgIvkuLvpoYzmlbjvvIzlsIfntZDmnpzlrZjotbfkvobvvIzlho3lgZrpgLLkuIDmraXliIbmnpDjgIINCmBgYHtyfQ0KbGRhcyA9IGMoKQ0KdG9waWNzID0gYygyLDQsNiwxMCwxNSkNCmZvcih0b3BpYyBpbiB0b3BpY3Mpew0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQpsZGEgPC0gTERBKG1hc2tfZHRtLCBrID0gdG9waWMsIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSAyMDIxKSkNCmxkYXMgPWMobGRhcyxsZGEpDQpwcmludChwYXN0ZSh0b3BpYyAscGFzdGUoInRvcGljKHMpIGFuZCB1c2UgdGltZSBpcyAiLCBTeXMudGltZSgpIC1zdGFydF90aW1lKSkpDQpzYXZlKGxkYXMsZmlsZSA9ICJsZGFzX3Jlc3VsdC5yZGF0YSIpICMg5bCH5qih5Z6L6Ly45Ye65oiQ5qqU5qGIDQp9DQpgYGANCumAj+mBjnBlcnBsZXhpdHnmib7liLDmnIDkvbPkuLvpoYzmlbgNCmBgYHtyfQ0KbGlicmFyeShwdXJycikNCnRvcGljcyA9IGMoMiw0LDYsMTAsMTUpDQpkYXRhX2ZyYW1lKGsgPSB0b3BpY3MsIHBlcnBsZXggPSBtYXBfZGJsKGxkYXMsIHRvcGljbW9kZWxzOjpwZXJwbGV4aXR5KSkgJT4lDQogIGdncGxvdChhZXMoaywgcGVycGxleCkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHRpdGxlID0gIkV2YWx1YXRpbmcgTERBIHRvcGljIG1vZGVscyIsDQogICAgICAgc3VidGl0bGUgPSAiT3B0aW1hbCBudW1iZXIgb2YgdG9waWNzIChzbWFsbGVyIGlzIGJldHRlcikiLA0KICAgICAgIHggPSAiTnVtYmVyIG9mIHRvcGljcyIsDQogICAgICAgeSA9ICJQZXJwbGV4aXR5IikNCmBgYA0KICArIOS4u+mhjOaVuOi2iuWkmu+8jOikh+mbnOW6pui2iuS9ju+8jOWFp+WuueeahOe0lOW6pui2iumrmOOAgg0KICArIOWPr+S7peaMkemBuOS4i+mZjeW5heW6pua4m+e3qeeahOm7nuOAgg0KICANCiAgDQojIyAyLkxEQXZpcyDlha3lgIvkuLvpoYwNCmBgYHtyfQ0KbGlicmFyeSh1ZHBpcGUpDQpkdGYgPC0gZG9jdW1lbnRfdGVybV9mcmVxdWVuY2llcyh0b2tlbnMsIGRvY3VtZW50ID0gImFydFVybCIsIHRlcm0gPSAid29yZCIpDQpkdG0gPC0gZG9jdW1lbnRfdGVybV9tYXRyaXgoeCA9IGR0ZikNCmR0bV9jbGVhbiA8LSBkdG1fcmVtb3ZlX2xvd2ZyZXEoZHRtLCBtaW5mcmVxID0gMzApDQpkaW0oZHRtX2NsZWFuKQ0Kc2V0LnNlZWQoNTQzMikNCg0KdG9waWNfbiA9IDYNCg0KbGRhX21vZGVsID10ZXh0MnZlYzo6TERBJG5ldyhuX3RvcGljcyA9IHRvcGljX24sZG9jX3RvcGljX3ByaW9yID0gMC4xLCB0b3BpY193b3JkX3ByaW9yID0gMC4wMDEpDQpkb2NfdG9waWNfZGlzdHIgPWxkYV9tb2RlbCRmaXRfdHJhbnNmb3JtKGR0bV9jbGVhbiwgbl9pdGVyID0gMTAwMCwgY29udmVyZ2VuY2VfdG9sID0gMWUtNSxjaGVja19jb252ZXJnZW5jZV9ldmVyeV9uID0gMTAwKQ0KbGRhX21vZGVsJGdldF90b3Bfd29yZHMobiA9IDEwLCBsYW1iZGEgPSAwLjUpDQpsZGFfbW9kZWwkcGxvdCgpDQpsZGFfbW9kZWwkcGxvdChvdXQuZGlyID0ibGRhX3Jlc3VsdCIsIG9wZW4uYnJvd3NlciA9IFRSVUUpDQoNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuY2FwPSJMREF2aXMiLCBvdXQud2lkdGggPSAnMzAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIxLnBuZyIpDQpgYGANCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5jYXA9IkxEQXZpcyIsIG91dC53aWR0aCA9ICczMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIjIucG5nIikNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuY2FwPSJMREF2aXMiLCBvdXQud2lkdGggPSAnMzAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIzLnBuZyIpDQpgYGANCg0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5jYXA9IkxEQXZpcyIsIG91dC53aWR0aCA9ICczMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIjQucG5nIikNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5jYXA9IkxEQXZpcyIsIG91dC53aWR0aCA9ICczMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIjUucG5nIikNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5jYXA9IkxEQXZpcyIsIG91dC53aWR0aCA9ICczMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIjYucG5nIikNCmBgYA0KDQrlsIfliZvomZXnkIblpb3nmoRkdG3mlL7lhaVMREHlh73lvI/liIbmnpANCmBgYHtyfQ0KIyBMREHliIbmiJA25YCL5Li76aGMDQptYXNrX2xkYSA8LSBMREEobWFza19kdG0sIGsgPSA2LCBjb250cm9sID0gbGlzdChzZWVkID0gMTIzNDUpKQ0KIyAgbWFza19sZGEgPC0gTERBKG1hc2tfZHRtLCBrID0gNiwgY29udHJvbCA9IGxpc3Qoc2VlZCA9IDEyMzQ1KSkNCmBgYA0KDQoNCuWPluWHuuS7o+ihqOWtl+ipnih0ZXJtKQ0KYGBge3J9DQpyZW1vdmVkX3dvcmQgPSBjKCLkuIDkuIsiLCLkuI3mmK8iLCLlgZzpm7siLCLmnInmspLmnIkiLCLpm7vlu6AiKSANCiMg55yL5ZCE576k55qE5bi455So6Kme5b2ZDQp0aWR5KG1hc2tfbGRhLCBtYXRyaXggPSAiYmV0YSIpICU+JSAjIOWPluWHunRvcGljIHRlcm0gYmV0YeWAvA0KICBmaWx0ZXIoISB0ZXJtICVpbiUgcmVtb3ZlZF93b3JkKSAlPiUgDQogIGdyb3VwX2J5KHRvcGljKSAlPiUNCiAgdG9wX24oMTMsIGJldGEpICU+JSAjIGJldGHlgLzliY0xMOeahOWtlw0KICB1bmdyb3VwKCkgJT4lDQogIG11dGF0ZSh0b3BpYyA9IGFzLmZhY3Rvcih0b3BpYyksDQogICAgICAgICB0ZXJtID0gcmVvcmRlcl93aXRoaW4odGVybSwgYmV0YSwgdG9waWMpKSAlPiUNCiAgZ2dwbG90KGFlcyh0ZXJtLCBiZXRhLCBmaWxsID0gdG9waWMpKSArDQogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCh+IHRvcGljLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfeF9yZW9yZGVyZWQoKQ0KYGBgDQoNCg0KPuWPr+S7peatuOe0jeWHuiA8YnI+DQo+dG9waWMgMSA9IOKAnOiojuirlueCuuS9leWBnOmbu+KAnSA8YnI+DQo+dG9waWMgMiA9IOKAnOWQhOWutuaWsOiBnuWgseWwjuWFp+WuueKAnSA8YnI+DQo+dG9waWMgMyA9IOKAnOaKseaAqOWBnOmbu+KAnSA8YnI+DQo+dG9waWMgNCA9IOKAnOiojuirluaUv+W6nOmHneWwjee8uuawtOOAgeeWq+aDheOAgee8uumbu+eahOaUv+etluKAnSA8YnI+DQo+dG9waWMgNSA9IOKAnOiojuirluaUv+W6nOeahOiDvea6kOaUv+etluKAnSA8YnI+DQo+dG9waWMgNiA9IOKAnOiojuirluWIhuWNgOWBnOmbu+KAnSA8YnI+DQo+5Lul5LiL5oiR5YCR5oyR5Ye656ysMeWAi+S4u+mhjOOAgeesrDPlgIvkuLvpoYzlkoznrKw05YCL5Li76aGM5L6G5YGa5q+U6LyD44CCDQoNCg0KDQrlj5blh7rku6PooajkuLvpoYwodG9waWMpDQpgYGB7cn0NCiMg5ZyodGlkeSBmdW5jdGlvbuS4reS9v+eUqOWPg+aVuCJnYW1tYSLkvoblj5blvpcgdGhldGHnn6npmaMNCm1hc2tfdG9waWNzIDwtIHRpZHkobWFza19sZGEsIG1hdHJpeD0iZ2FtbWEiKSAlPiUgIyBkb2N1bWVudCB0b3BpYyBnYW1tYQ0KICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoZG9jdW1lbnQpICU+JQ0KICAgICAgICAgICAgICAgICAgdG9wX24oMSwgd3Q9Z2FtbWEpDQptYXNrX3RvcGljcw0KYGBgDQoNCiMjIDMu6LOH5paZ5YWn5a655o6i57SiDQpgYGB7cn0NCnBvc3RzX3RvcGljIDwtIG1lcmdlKHggPSBwb3N0cywgeSA9IG1hc2tfdG9waWNzLCBieS54ID0gImFydFVybCIsIGJ5Lnk9ImRvY3VtZW50IikNCg0KIyDnnIvkuIDkuIvlkITkuLvpoYzlnKjoqqrnlJrpurwNCnNldC5zZWVkKDEyMzQ1KQ0KcG9zdHNfdG9waWMgJT4lICMg5Li76aGM5LiADQogIGZpbHRlcih0b3BpYz09MSkgJT4lDQogIHNlbGVjdChhcnRUaXRsZSkgJT4lDQogIHVuaXF1ZSgpICU+JQ0KICBzYW1wbGVfbigxMikNCnBvc3RzX3RvcGljICU+JSAjIOS4u+mhjOS6jA0KICBmaWx0ZXIodG9waWM9PTIpICU+JQ0KICBzZWxlY3QoYXJ0VGl0bGUpICU+JQ0KICB1bmlxdWUoKSAlPiUNCiAgc2FtcGxlX24oMTIpDQpwb3N0c190b3BpYyAlPiUgIyDkuLvpoYzkuIkNCiAgZmlsdGVyKHRvcGljPT0zKSAlPiUNCiAgc2VsZWN0KGFydFRpdGxlKSAlPiUNCiAgdW5pcXVlKCkgJT4lDQogIHNhbXBsZV9uKDEyKQ0KcG9zdHNfdG9waWMgJT4lICMg5Li76aGM5ZubDQogIGZpbHRlcih0b3BpYz09NCkgJT4lDQogIHNlbGVjdChhcnRUaXRsZSkgJT4lDQogIHVuaXF1ZSgpICU+JQ0KICBzYW1wbGVfbigxMikNCnBvc3RzX3RvcGljICU+JSAjIOS4u+mhjOS6lA0KICBmaWx0ZXIodG9waWM9PTUpICU+JQ0KICBzZWxlY3QoYXJ0VGl0bGUpICU+JQ0KICB1bmlxdWUoKSAlPiUNCiAgc2FtcGxlX24oMTIpDQpwb3N0c190b3BpYyAlPiUgIyDkuLvpoYzlha0NCiAgZmlsdGVyKHRvcGljPT02KSAlPiUNCiAgc2VsZWN0KGFydFRpdGxlKSAlPiUNCiAgdW5pcXVlKCkgJT4lDQogIHNhbXBsZV9uKDEyKQ0KYGBgDQoNCiMjIDQu5pel5pyf5Li76aGM5YiG5biDDQpgYGB7cn0NCnBvc3RzX3RvcGljICU+JQ0KICBtdXRhdGUoYXJ0RGF0ZSA9IGFzLkRhdGUoYXJ0RGF0ZSkpICU+JSANCiAgZ3JvdXBfYnkoYXJ0RGF0ZSx0b3BpYykgJT4lDQogIHN1bW1hcmlzZShzdW0gPXN1bSh0b3BpYykpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9IGFydERhdGUseT1zdW0sZmlsbD1hcy5mYWN0b3IodG9waWMpKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbj0iZmlsbCIpIA0KDQpgYGANCg0KYGBge3J9DQpwb3N0c190b3BpYyAlPiUNCiAgZ3JvdXBfYnkoYXJ0Q2F0LHRvcGljKSAlPiUNCiAgc3VtbWFyaXNlKHN1bSA9IG4oKSkgICU+JQ0KICBnZ3Bsb3QoYWVzKHg9IGFydENhdCx5PXN1bSxmaWxsPWFzLmZhY3Rvcih0b3BpYykpKSArDQogIGdlb21fY29sKHBvc2l0aW9uPSJkb2RnZSIpIA0KDQpgYGANCg0KPnRvcGljIDEgPSDigJzoqI7oq5bngrrkvZXlgZzpm7vigJ0gPGJyPg0KPnRvcGljIDIgPSDigJzlkITlrrbmlrDogZ7loLHlsI7lhaflrrnigJ0gPGJyPg0KPnRvcGljIDMgPSDigJzmirHmgKjlgZzpm7vigJ0gPGJyPg0KPnRvcGljIDQgPSDigJzoqI7oq5bmlL/lupzph53lsI3nvLrmsLTjgIHnlqvmg4XjgIHnvLrpm7vnmoTmlL/nrZbigJ0gPGJyPg0KPnRvcGljIDUgPSDigJzoqI7oq5bmlL/lupznmoTog73mupDmlL/nrZbigJ0gPGJyPg0KPnRvcGljIDYgPSDigJzoqI7oq5bliIbljYDlgZzpm7vigJ0gPGJyPg0KDQoNCg0KIyDlha3jgIHnpL7nvqTntrLot6/lnJYNCg0K6LOH5paZ5ZCI5L21DQpgYGB7cn0NCiMg5paH56ug5ZKM55WZ6KiADQpyZXZpZXdzIDwtIHJldmlld3MgJT4lDQogICAgICBzZWxlY3QoYXJ0VXJsLCBjbXRQb3N0ZXIsIGNtdFN0YXR1cywgY210Q29udGVudCkNCnBvc3RzX1Jldmlld3MgPC0gbWVyZ2UoeCA9IHBvc3RzLCB5ID0gcmV2aWV3cywgYnkgPSAiYXJ0VXJsIikNCg0KIyDmiormlofnq6Dlkox0b3BpYw0KcG9zdHNfUmV2aWV3cyA8LSBtZXJnZSh4ID0gcG9zdHNfUmV2aWV3cywgeSA9IG1hc2tfdG9waWNzLCBieS54ID0gImFydFVybCIsIGJ5Lnk9ImRvY3VtZW50IikNCmhlYWQocG9zdHNfUmV2aWV3cywzKQ0KYGBgDQrlj5blh7ogY210UG9zdGVyKOWbnuimhuiAhSnjgIFhcnRQb3N0ZXIo55m85paH6ICFKeOAgWFydFVybCjmlofnq6DpgKPntZApIOS4ieWAi+ashOS9jQ0KYGBge3J9DQpsaW5rIDwtIHBvc3RzX1Jldmlld3MgJT4lIHNlbGVjdChjbXRQb3N0ZXIsIGFydFBvc3RlciwgYXJ0VXJsKQ0KaGVhZChsaW5rLDMpDQpgYGANCg0KIyMgMS7ln7rmnKzntrLot6/lnJYNCg0K5bu656uL57ay6Lev6Zec5L+CDQpgYGB7cn0NCnJldmlld05ldHdvcmsgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGQ9bGluaywgZGlyZWN0ZWQ9VCkNCnJldmlld05ldHdvcmsNCmBgYA0KDQojIyAyLuaWh+eroOeVmeiogOaVuA0KYGBge3J9DQojIOeci+S4gOS4i+eVmeiogOaVuOWkp+amgumDveWkmuWwkSjmlrnkvr/lvozpnaLnr6npgbgpDQpwb3N0cyAlPiUNCiAgI2ZpbHRlcihjb21tZW50TnVtPDIwMCkgJT4lDQogIGdncGxvdChhZXMoeD1jb21tZW50TnVtKSkgKyBnZW9tX2hpc3RvZ3JhbSgpDQpgYGANCg0K5L6d5pOa55m85paH5pW45oiW5Zue6KaG5pW456+p6YG4cG9zdOWSjHJldmlldw0KYGBge3J9DQojIyDluLPomZ/nmbzmlofnr4fmlbgNCnBvc3RfY291bnQgPSBwb3N0cyAlPiUNCiAgZ3JvdXBfYnkoYXJ0UG9zdGVyKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUNCiAgYXJyYW5nZShkZXNjKGNvdW50KSkgDQpwb3N0X2NvdW50DQoNCiMjIOW4s+iZn+Wbnuimhue4veaVuA0KcmV2aWV3X2NvdW50ID0gcmV2aWV3cyAlPiUNCiAgZ3JvdXBfYnkoY210UG9zdGVyKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUNCiAgYXJyYW5nZShkZXNjKGNvdW50KSkgDQpyZXZpZXdfY291bnQNCg0KIyMg55m85paH6ICFDQpwb3N0ZXJfc2VsZWN0IDwtIHBvc3RfY291bnQgJT4lIGZpbHRlcihjb3VudCA+PSAyKQ0KcG9zdHMgPC0gcG9zdHMgJT4lICBmaWx0ZXIocG9zdHMkYXJ0UG9zdGVyICVpbiUgcG9zdGVyX3NlbGVjdCRhcnRQb3N0ZXIpDQoNCiMjIOWbnuimhuiAhQ0KcmV2aWV3ZXJfc2VsZWN0IDwtIHJldmlld19jb3VudCAlPiUgIGZpbHRlcihjb3VudCA+PSA1KQ0KcmV2aWV3cyA8LSByZXZpZXdzICU+JSAgZmlsdGVyKHJldmlld3MkY210UG9zdGVyICVpbiUgcmV2aWV3ZXJfc2VsZWN0JGNtdFBvc3RlcikNCmBgYA0KDQpgYGB7cn0NCiMg5qqi6KaW5Y+D6IiH5Lq65pW4DQpsZW5ndGgodW5pcXVlKHBvc3RzX1Jldmlld3MkYXJ0UG9zdGVyKSkgIyDnmbzmlofogIXmlbjph48gOTExDQpsZW5ndGgodW5pcXVlKHBvc3RzX1Jldmlld3MkY210UG9zdGVyKSkgIyDlm57opobogIXmlbjph48gMTUyMjQNCmFsbFBvc3RlciA8LSBjKHBvc3RzX1Jldmlld3MkYXJ0UG9zdGVyLCBwb3N0c19SZXZpZXdzJGNtdFBvc3RlcikgIyDnuL3lj4PoiIfkurrmlbggMTU2NDENCmxlbmd0aCh1bmlxdWUoYWxsUG9zdGVyKSkNCmBgYA0KDQrmqJnoqJjmiYDmnInlh7rnj77pgY7lvpfkvb/nlKjogIUNCg0KICArIHBvc3Rlcu+8muWPqueZvOmBjuaWh+OAgeeZvOmBjuaWhyvnlZnpgY7oqIANCiAgKyByZXBseWVy77ya5Y+q55WZ6YGO6KiADQpgYGB7cn0NCnVzZXJMaXN0IDwtIGRhdGEuZnJhbWUodXNlcj11bmlxdWUoYWxsUG9zdGVyKSkgJT4lDQogICAgICAgICAgICAgIG11dGF0ZSh0eXBlPWlmZWxzZSh1c2VyJWluJXBvc3RzJGFydFBvc3RlciwgInBvc3RlciIsICJyZXBseWVyIikpDQpoZWFkKHVzZXJMaXN0LDMpDQpgYGANCg0KIyMgMy7ku6Xml6XmnJ/nr6npgbjnpL7nvqQNCmBgYHtyfQ0KbGluayA8LSBwb3N0c19SZXZpZXdzICU+JQ0KICAgICAgZ3JvdXBfYnkoY210UG9zdGVyLCBhcnRVcmwpICU+JSANCiAgICAgIGZpbHRlcihuKCk+MykgJT4lIA0KICAgICAgZmlsdGVyKGNvbW1lbnROdW0gPiAyMDApICU+JQ0KICAgICAgZmlsdGVyKGFydENhdD09Ikdvc3NpcGluZyIpICU+JSANCiAgICAgIGZpbHRlcihhcnREYXRlID09IGFzLkRhdGUoJzIwMjEtMDUtMTMnKSkgJT4lDQogICAgICBzZWxlY3QoY210UG9zdGVyLCBhcnRQb3N0ZXIsIGFydFVybCkgJT4lIA0KICAgICAgdW5pcXVlKCkNCmxpbmsNCmBgYA0KDQrnr6npgbjlnKhsaW5r6KOh6Z2i5pyJ5Ye654++55qE5L2/55So6ICFDQpgYGB7cn0NCmZpbHRlcmVkX3VzZXIgPC0gdXNlckxpc3QgJT4lDQogICAgICAgICAgZmlsdGVyKHVzZXIlaW4lbGluayRjbXRQb3N0ZXIgfCB1c2VyJWluJWxpbmskYXJ0UG9zdGVyKSAlPiUNCiAgICAgICAgICBhcnJhbmdlKGRlc2ModHlwZSkpDQpoZWFkKGZpbHRlcmVkX3VzZXIsMykNCmBgYA0KDQrlm6DniLLlnJbniYfnrq3poK3mnInpu57npJnnnLzvvIzmiYDku6XpgJnoo4/miJHlgJHlhYjmiorpl5zkv4LnmoTmlrnlkJHmgKfmi7/mjonvvIzmuJvlsJHlnJbniYfkuK3nmoTkuI3lv4XopoHnmoTos4foqIogc2V0LnNlZWQg5Zug54K6aWdyYXBo5ZGI54++55qE5pa55ZCR5piv6Zqo5qmf55qEDQpgYGB7cn0NCnNldC5zZWVkKDEyMzQ1KQ0KIyB2PWZpbHRlcmVkX3VzZXINCnJldmlld05ldHdvcmsgPSBkZWdyZWUocmV2aWV3TmV0d29yaykgPiAyDQpyZXZpZXdOZXR3b3JrIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShkPWxpbmssIHY9ZmlsdGVyZWRfdXNlciwgZGlyZWN0ZWQ9RikNCnBsb3QocmV2aWV3TmV0d29yaywgdmVydGV4LnNpemU9MywgZWRnZS5hcnJvdy5zaXplPTAuMyx2ZXJ0ZXgubGFiZWw9TkEpDQpgYGANCg0K5Yqg5LiKbm9kZXPnmoTpoa/npLros4foqIoNCueUqOS9v+eUqOiAheeahOi6q+S7veS+huWNgOWIhum7nueahOmhj+iJsg0KDQogICsgcG9zdGVyOmdvbGQo5pyJ55m85paHKQ0KICArIHJlcGx5ZXI6bGlnaHRibHVlKOWPquacieWbnuimhuaWh+eroCkNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzNDUpDQpWKHJldmlld05ldHdvcmspJGNvbG9yIDwtIGlmZWxzZShWKHJldmlld05ldHdvcmspJHR5cGU9PSJwb3N0ZXIiLCAiZ29sZCIsICJsaWdodGJsdWUiKQ0KcGxvdChyZXZpZXdOZXR3b3JrLCB2ZXJ0ZXguc2l6ZT0zLCBlZGdlLmFycm93LnNpemU9MC4zLHZlcnRleC5sYWJlbD1OQSkNCmBgYA0KDQo+IOWPr+S7peeojeW+rueci+WHuuWcluS4reeahOm7nijkurop5LmL6ZaT5pyJ5LiA5a6a55qE6Zec6IGv77yM5LiN6YGO55uu5YmN5Y+q5pyJ5Zau57SU5ZyW5b2i5oiR5YCR54Sh5rOV5YiG5p6Q5YW25Lit55qE5YWn5a6544CCPGJyPg0K5Zug5q2k5Lul5LiL5oiR5YCR5bCH6LOH5paZ6ZuG5Lit55qE6LOH6KiK5Yqg5Yiw5oiR5YCR55qE5ZyW54mH5Lit44CCDQoNCueCuum7nuWKoOS4iuW4s+iZn+WQjeWtl++8jOeUqGRlZ3JlZeevqemBuOimgemhr+ekuuWHuueahOS9v+eUqOiAhe+8jOS7peWFjeWcluW9ouiiq+WvhuWvhum6u+m6u+eahOaWh+Wtl+imhuiTiw0KYGBge3J9DQpmaWx0ZXJfZGVncmVlID0gNQ0Kc2V0LnNlZWQoMTIzNDUpDQojIOioreWumiBub2RlIOeahCBsYWJlbC8gY29sb3INCmxhYmVscyA8LSBkZWdyZWUocmV2aWV3TmV0d29yaykgIyDnrpflh7rmr4/lgIvpu57nmoRkZWdyZWUNClYocmV2aWV3TmV0d29yaykkbGFiZWwgPC0gbmFtZXMobGFiZWxzKQ0KVihyZXZpZXdOZXR3b3JrKSRjb2xvciA8LSBpZmVsc2UoVihyZXZpZXdOZXR3b3JrKSR0eXBlPT0icG9zdGVyIiwgImdvbGQiLCAibGlnaHRibHVlIikNCnBsb3QoDQogIHJldmlld05ldHdvcmssIA0KICB2ZXJ0ZXguc2l6ZT0zLCANCiAgZWRnZS53aWR0aD0zLCANCiAgdmVydGV4LmxhYmVsLmRpc3Q9MSwNCiAgdmVydGV4LmxhYmVsPWlmZWxzZShkZWdyZWUocmV2aWV3TmV0d29yaykgPiBmaWx0ZXJfZGVncmVlLCBWKHJldmlld05ldHdvcmspJGxhYmVsLCBOQSksdmVydGV4LmxhYmVsLmZvbnQ9MikNCmBgYA0KPiDmiJHlgJHlj6/ku6XnnIvliLDln7rmnKznmoTkvb/nlKjogIXpl5zkv4LvvIzkvYbmmK/miJHlgJHluIzmnJvog73lpKDlsIfmm7TpgLLpmo7nmoTos4foqIroppboprrljJbjgII8YnI+DQrkvovlpoLvvJrkvb/nlKjogIXntpPluLjlj4PoiIfnmoTmlofnq6DnqK7poZ7vvIzmiJbmmK/kvb/nlKjogIXlnKjoqbLnpL7nvqTntrLot6/kuK3mmK/lkKblj5fliLDmraHov47jgIINCg0KDQoNCiMjIDQu5Lul5Li76aGM56+p6YG456S+576kDQoNCisg5oqTbGluaw0KDQrmjJHpgbjlh7oyMDIxLTA1LTEz55W25aSp55qE5paH56ug77yMDQrnr6npgbjkuIDnr4fmlofnq6Dlm57opoYz5qyh5Lul5LiK6ICF77yM5LiU5paH56ug55WZ6KiA5pW45aSa6aSYNjDliYfvvIwNCuaWh+eroOS4u+mhjOatuOmhnueCujHjgIEz6IiHNOiAhe+8jA0K5qyE5L2N5Y+q5Y+W77yaY210UG9zdGVyKOipleirluiAhSksIGFydFBvc3RlcijnmbzmlofogIUpLCBhcnRVcmwo5paH56ug6YCj57WQKSwgdG9waWMo5Li76aGMKQ0KYGBge3J9DQpsaW5rIDwtIHBvc3RzX1Jldmlld3MgJT4lDQogICAgICBncm91cF9ieShjbXRQb3N0ZXIsIGFydFVybCkgJT4lIA0KICAgICAgZmlsdGVyKG4oKT4zKSAlPiUgDQogICAgICBmaWx0ZXIoY29tbWVudE51bSA+IDYwKSAlPiUNCiAgICAgIGZpbHRlcihhcnRDYXQ9PSJHb3NzaXBpbmciKSAlPiUgI0hhdGVQb2xpdGljcyAvIEdvc3NpcGluZw0KICAgICAgZmlsdGVyKGFydERhdGUgPT0gYXMuRGF0ZSgnMjAyMS0wNS0xMycpKSAlPiUNCiAgICAgIGZpbHRlciggdG9waWMgPT0gMSB8IHRvcGljID09IDMgfCB0b3BpYyA9PSA0KSAlPiUgDQogICAgICBkcGx5cjo6c2VsZWN0KGNtdFBvc3RlciwgYXJ0UG9zdGVyLCBhcnRVcmwsIHRvcGljKSAlPiUgDQogICAgICB1bmlxdWUoKQ0KbGluaw0KYGBgDQor5oqTbm9kZXMNCuWcqOaJgOacieeahOS9v+eUqOiAheijoemdou+8jOevqemBuGxpbmvkuK3mnInlh7rnj77nmoTkvb/nlKjogIUNCmBgYHtyfQ0KZmlsdGVyZWRfdXNlciA8LSB1c2VyTGlzdCAlPiUNCiAgICAgICAgICBmaWx0ZXIodXNlciVpbiVsaW5rJGNtdFBvc3RlciB8IHVzZXIlaW4lbGluayRhcnRQb3N0ZXIpICU+JQ0KICAgICAgICAgIGFycmFuZ2UoZGVzYyh0eXBlKSkNCmhlYWQoZmlsdGVyZWRfdXNlciwzKQ0KYGBgDQoNCiMjIDUu5L2/55So6ICF57aT5bi45Y+D6IiH55qE5paH56ug56iu6aGeDQpgYGB7cn0NCmZpbHRlcl9kZWdyZWUgPSAyDQoNCiMg5bu656uL57ay6Lev6Zec5L+CDQpyZXZpZXdOZXR3b3JrIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShkPWxpbmssIHY9ZmlsdGVyZWRfdXNlciwgZGlyZWN0ZWQ9RikNCg0KIyDkvp3mk5rkvb/nlKjogIXouqvku73lsI3pu57pgLLooYzkuIroibINCmxhYmVscyA8LSBkZWdyZWUocmV2aWV3TmV0d29yaykNClYocmV2aWV3TmV0d29yaykkbGFiZWwgPC0gbmFtZXMobGFiZWxzKQ0KVihyZXZpZXdOZXR3b3JrKSRjb2xvciA8LSBpZmVsc2UoVihyZXZpZXdOZXR3b3JrKSR0eXBlPT0icG9zdGVyIiwgImdvbGQiLCAibGlnaHRibHVlIikNCg0KIyDkvp3mk5rlm57opobnmbznlJ/nmoTmlofnq6DmiYDlsI3mh4nnmoTkuLvpoYzvvIzlsI3ku5blgJHnmoTpl5zoga/nt5rpgLLooYzkuIroibINCkUocmV2aWV3TmV0d29yaykkY29sb3IgPC0gaWZlbHNlKEUocmV2aWV3TmV0d29yaykkdG9waWMgPT0gIjEiLCAicGFsZXZpb2xldHJlZCIsaWZlbHNlKChFKHJldmlld05ldHdvcmspJHRvcGljID09IjMiKSwibGlnaHRncmVlbiIsImRlZXBza3libHVlIiApKQ0KDQojIOeVq+WHuuekvue+pOe2sui3r+Wclg0Kc2V0LnNlZWQoMTIzNDUpDQpwbG90KHJldmlld05ldHdvcmssIHZlcnRleC5zaXplPTMsIGVkZ2Uud2lkdGg9MywgdmVydGV4LmxhYmVsLmRpc3Q9MSwNCiAgICAgdmVydGV4LmxhYmVsPWlmZWxzZShkZWdyZWUocmV2aWV3TmV0d29yaykgPiBmaWx0ZXJfZGVncmVlLCBWKHJldmlld05ldHdvcmspJGxhYmVsLCBOQSksdmVydGV4LmxhYmVsLmZvbnQ9MikNCg0KIyDliqDlhaXmqJnnpLoNCmxlZ2VuZCgiYm90dG9tcmlnaHQiLCBjKCLnmbzmlofogIUiLCLlm57mlofogIUiKSwgcGNoPTIxLA0KICBjb2w9IiM3Nzc3NzciLCBwdC5iZz1jKCJnb2xkIiwibGlnaHRibHVlIiksIHB0LmNleD0xLCBjZXg9MSkNCmxlZ2VuZCgidG9wbGVmdCIsIGMoIuiojuirlueCuuS9leWBnOmbuyIsIuaKseaAqOWBnOmbuyIsIuiojuirluaUv+W6nOWwjee8uuawtOOAgeeWq+aDheOAgee8uumbu+eahOaUv+etliIpLA0KICBjb2w9YygicGFsZXZpb2xldHJlZCIsICJsaWdodGdyZWVuIiwiZGVlcHNreWJsdWUiKSwgbHR5PTEsIGNleD0xKQ0KYGBgDQoNCiMjIDYu5L2/55So6ICF5piv5ZCm5Y+X5Yiw5q2h6L+ODQoNClBUVOeahOWbnuimhuacieS4ieeoru+8jOaOqOaWh+OAgeWZk+aWh+OAgeeuremgre+8jOaIkeWAkeWPquimgeeci+aOqOWZk+WwseWlve+8jOWboOatpOaKiueuremgrea4heaOie+8jOmAmeaoo+izh+aWmeethuaVuOi8g+Wwke+8jOaJgOS7peaIkeWAkeaKiuevqemBuOeahOaineS7tuaUvuWvrOS4gOS6m+OAgg0KYGBge3J9DQpmaWx0ZXJfZGVncmVlID0gMSAjIOS9v+eUqOiAhWRlZ3JlZQ0KDQojIOmBjua/vueVmeiogOiAheWwjeeZvOaWh+iAheeahOaOqOWZk+eoi+W6pg0KbGluayA8LSBwb3N0c19SZXZpZXdzICU+JQ0KICAgICAgZmlsdGVyKGFydENhdD09Ikdvc3NpcGluZyIpICU+JSANCiAgICAgIGZpbHRlcihjb21tZW50TnVtID4gNDApICU+JQ0KICAgICAgZmlsdGVyKGNtdFN0YXR1cyE9IuKGkiIpICU+JQ0KICAgICAgZ3JvdXBfYnkoY210UG9zdGVyLCBhcnRVcmwpICU+JQ0KICAgICAgZmlsdGVyKCBuKCkgPiAyKSAlPiUNCiAgICAgIHVuZ3JvdXAoKSAlPiUgDQogICAgICBkcGx5cjo6c2VsZWN0KGNtdFBvc3RlciwgYXJ0UG9zdGVyLCBhcnRVcmwsIGNtdFN0YXR1cykgJT4lIA0KICAgICAgdW5pcXVlKCkNCg0KIyDmjqXkuIvkvobmiorntrLot6/lnJbnlavlh7rkvobvvIzot5/liY3pnaLlgZrnmoTkuovpg73kuIDmqKPvvIzlm6DmraTkuI3lho3ntLDov7ANCiMg56+p6YG4bGlua+S4reacieWHuuePvueahOS9v+eUqOiAhQ0KZmlsdGVyZWRfdXNlciA8LSB1c2VyTGlzdCAlPiUNCiAgICAgICAgICBmaWx0ZXIodXNlciVpbiVsaW5rJGNtdFBvc3RlciB8IHVzZXIlaW4lbGluayRhcnRQb3N0ZXIpICU+JQ0KICAgICAgICAgIGFycmFuZ2UoZGVzYyh0eXBlKSkNCg0KIyDlu7rnq4vntrLot6/pl5zkv4INCnJldmlld05ldHdvcmsgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGQ9bGluaywgdj1maWx0ZXJlZF91c2VyLCBkaXJlY3RlZD1GKQ0KDQojIOS+neaTmuS9v+eUqOiAhei6q+S7veWwjem7numAsuihjOS4iuiJsg0KbGFiZWxzIDwtIGRlZ3JlZShyZXZpZXdOZXR3b3JrKQ0KVihyZXZpZXdOZXR3b3JrKSRsYWJlbCA8LSBuYW1lcyhsYWJlbHMpDQpWKHJldmlld05ldHdvcmspJGNvbG9yIDwtIGlmZWxzZShWKHJldmlld05ldHdvcmspJHR5cGU9PSJwb3N0ZXIiLCAiZ29sZCIsICJsaWdodGJsdWUiKQ0KDQoNCiMg5L6d5pOa5Zue6KaG55m855Sf55qE5paH56ug5omA5bCN5oeJ55qE5Li76aGM77yM5bCN5LuW5YCR55qE6Zec6IGv57ea6YCy6KGM5LiK6ImyDQpFKHJldmlld05ldHdvcmspJGNvbG9yIDwtIGlmZWxzZShFKHJldmlld05ldHdvcmspJGNtdFN0YXR1cyA9PSAi5o6oIiwgImxpZ2h0Z3JlZW4iLCAicGFsZXZpb2xldHJlZCIpDQoNCiMg55Wr5Ye656S+576k57ay6Lev5ZyWDQpzZXQuc2VlZCgxMjM0NSkNCnBsb3QocmV2aWV3TmV0d29yaywgdmVydGV4LnNpemU9MiwgZWRnZS53aWR0aD0zLCB2ZXJ0ZXgubGFiZWwuZGlzdD0xLA0KICAgICB2ZXJ0ZXgubGFiZWw9aWZlbHNlKGRlZ3JlZShyZXZpZXdOZXR3b3JrKSA+IGZpbHRlcl9kZWdyZWUsIFYocmV2aWV3TmV0d29yaykkbGFiZWwsIE5BKSx2ZXJ0ZXgubGFiZWwuZm9udD0yKQ0KDQojIOWKoOWFpeaomeekug0KbGVnZW5kKCJib3R0b21yaWdodCIsIGMoIueZvOaWh+iAhSIsIuWbnuaWh+iAhSIpLCBwY2g9MjEsDQogIGNvbD0iIzc3Nzc3NyIsIHB0LmJnPWMoImdvbGQiLCJsaWdodGJsdWUiKSwgcHQuY2V4PTEsIGNleD0xKQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgYygi5o6oIiwi5ZmTIiksIA0KICAgICAgIGNvbD1jKCJsaWdodGdyZWVuIiwicGFsZXZpb2xldHJlZCIpLCBsdHk9MSwgY2V4PTEpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmNhcD0iTERBdmlzIiwgb3V0LndpZHRoID0gJzMwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiRmluYWwucG5nIikNCmBgYA0KDQoNCuWPr+S7peeZvOePvuacrOasoeeahOiojuirluS4reW5vuS5jumDveaYr+aOqOaWh+OAgeWZk+aWh+i8g+WwkQ0KDQoNCiMg5LiD44CB57i957WQDQoNCjEuNTEz5YGc6Zu75LqL5Lu255qE6KiO6KuW6YeN6bue5pyJ5ZOq5LqbPyDkuLvopoHliIbngrrlk6rlub7nqK7poqjlkJE/PC9icj4NCuWwjeaWvDIwMjEtMDUtMTMgfiAyMDIxLTA1LTE45pS26ZuG55qE5paH56ug77yM5aSn5qaC5Y+v5Lul5YiG5oiQ6KiO6KuW5pS/5bqc55qE6KiO6KuW54K65L2V5YGc6Zu744CB5oqx5oCo5YGc6Zu75ZKM6KiO6KuW5pS/5bqc6Yed5bCN57y65rC044CB55ar5oOF44CB57y66Zu755qE5pS/562W6YCZ5LiJ5YCL5Li76aGM77yM5YW25LuW6YKE5pyJ5ZCE5a625paw6IGe5aCx5bCO5YWn5a6544CB6KiO6KuW5pS/5bqc55qE6IO95rqQ5pS/562W5Lul5Y+K6KiO6KuW5YiG5Y2A5YGc6Zu7562J5LiJ5YCL5Li76aGM44CCDQoNCjIu55uu5YmN6aKo5ZCR5pyA5YGP5ZOq6YKKPzwvYnI+DQrph53lsI3lgZzpm7vkuovku7ZQVFTkuIrkuLvopoHku6XoqI7oq5bngrrkvZXlgZzpm7voiIfmirHmgKjlgZzpm7vnmoTmlofnq6DlsYXlpJrjgIINCg0KMy7oqI7oq5Y1MTPlgZzpm7vkuovku7bnmoTnpL7nvqTntrLot6/lpoLkvZXliIbluIM/PC9icj4NCuS7peekvue+pOaWh+eroOaVuOS+hueci++8jOiojuirlueCuuS9leWBnOmbu+eahOe2suWPi+i8g+WkmuOAgg0KDQo0LjUxM+WBnOmbu+S6i+S7tueahOaEj+imi+mgmOiiluacieiqsD/ntrLlj4vnmoTmjqjlmZPni4DmhYvlpoLkvZU/PC9icj4NCuWboOeCuuizh+aWmemBuOWPlueahOaZgumWk+i8g+efre+8jOWPquimgeW5vuevh+WbnuimhumHj+mrmOeahOiyvOaWh++8jOWwseacieapn+acg+aIkOeCuuekvue+pOS4reW/g++8jOWcqOWFq+WNpueJiOS4iu+8jOS7peWgseWwjuiojuirlueCuuS4u+eahOaEj+imi+mgmOiiluaciToNCiA8YnI+LSDoqI7oq5bngrrkvZXlgZzpm7vnmoTmhI/opovpoJjoopbngrpsb2d5aW7vvIzlpKflpJrpg73mmK/mraPpnaLmjqjmlofjgIINCiA8YnI+LSDmirHmgKjlgZzpm7vnmoTmhI/opovpoJjoopZsb2xpYyDvvIzmjqjmloflpJrjgIHlmZPmloflsJHjgIINCiA8YnI+LSDoqI7oq5bmlL/lupzph53lsI3nvLrmsLTjgIHnlqvmg4XjgIHnvLrpm7vnmoTmlL/nrZbnmoTmhI/opovpoJjoopZjb21wdXRlcnFxce+8jOS5n+aYr+aOqOaWh+WkmuOAgeWZk+aWh+WwkeOAgg0KDQoNCg0KDQo=