図の右上のshowボタンを押すとRのコードが表示されます。

2.1 数量と図形の大きさを紐づける

2.1.1 図形の大きさと数量を紐づける

library(conflicted)
library(tidyverse)
library(ggpubr)

label <- c("支持する", "支持しない", "どちらとも\nいえない", "無回答")
data.frame(
  label=factor(label, levels = rev(label)),
  data=c(40, 32, 25, 3)
  ) |>
  ggdonutchart(
    x = "data",
    label = "label",
    fill = "label",
    palette = c("darkgray", "lightgray", "red", "blue")
    ) +
  theme(legend.position = "none")

2.1.2 ワードクラウドを用いた「頻度と見た目の大きさ」の紐づけ

ストップワードが違うようで、全く一緒にはならないです。

library(conflicted)
library(tidyverse)
library(tidytext)
library(wordcloud2)

# テキストデータ
df <- data.frame(
  text = "Clustering coefficients for correlation networks, Energy landscape analysis of neuroimaging data, Simulation of space acquisition process of pedestrians using proxemic floor field model, Pedestrian flow through multiple bottlenecks, Closer to critical resting-state neural dynamics in individuals with higher fluid intelligence, Reinforcement learning explains conditional cooperation and its moody cousin, Jam-absorption driving with a car-following model, Age‐related changes in the ease of dynamical transitions in human brain activity, Potential global jamming transition in aviation networks, Methodology and theoretical basis of forward genetic screening for sleep/wakefulness in mice, Jamming transitions in force-based models for pedestrian dynamics, Inflow process of pedestrians to a confined space, Exact solution of a heterogeneous multilane asymmetric simple exclusion process, Exact stationary distribution of an asymmetric simple exclusion process with Langmuir kinetics and memory reservoirs, Taming macroscopic jamming in transportation networks, A demonstration experiment of a theory of jam-absorption driving, A balance network for the asymmetric simple exclusion process, Reinforcement learning account of network reciprocity, Towards understanding network topology and robustness of logistics systems, Inflow process: A counterpart of evacuation, Analysis on a single segment of evacuation network, Dynamics of assembly production flow, Presynaptic inhibition of dopamine neurons controls optimistic bias, Bridging the micro-macro gap between single-molecular behavior and bulk hydrolysis properties of cellulase, Cluster size distribution in 1D-CA traffic models, Modelling state‐transition dynamics in resting‐state brain signals by the hidden Markov and Gaussian mixture models, Positive congestion effect on a totally asymmetric simple exclusion process with an adsorption lane, Metastability in pedestrian evacuation, Constructing quantum dark solitons with stable scattering properties, The Autonomous Sensory Meridian Response Activates the Parasympathetic Nervous System, Trait, staging, and state markers of psychosis based on functional alteration of salience-related networks in the high-risk, first episode, and chronic stages, Critical brain dynamics and human intelligence, Influence of velocity variance of a single particle on cellular automaton models, Collective motion of oscillatory walkers, Reinforcing critical links for robust network logistics: A centrality measure for substitutability, Dynamic transitions between brain states predict auditory attentional fluctuations, Associations of conservatism/jumping to conclusions biases with aberrant salience and default mode network, Model retraining and information sharing in a supply chain with long-term fluctuating demands, Functional alterations of salience-related networks are associated with traits, staging, and the state of psychosis."
)

df |>
  unnest_tokens(word, text) |>
  count(word, sort = TRUE, name = "freq") |>
  anti_join(stop_words, by = join_by(word)) |>
  wordcloud2(shape = "square", shuffle = FALSE)

2.1.3 ツリーマップによるグループ情報の付与

library(conflicted)
library(tidyverse)
library(treemapify)
library(gapminder)
library(viridis)

# gapminderデータセットから2007年のデータを抽出
df <- gapminder |>
  dplyr::filter(year == 2007)

df |>
  ggplot(aes(area = pop, fill = lifeExp, label = country, subgroup = continent)) +
  geom_treemap() +
  geom_treemap_text(colour = "black", place = "topleft", reflow = TRUE) +
  geom_treemap_subgroup_border() +
  geom_treemap_subgroup_text(
    place = "centre", grow = TRUE, alpha = 0.6, colour = "black",
    fontface = "italic", min.size = 0
    ) +
  scale_fill_viridis(option = "turbo", direction = -1) +
#  scale_fill_gradient2(
#    low  = "red", mid  = "white", high = "blue", midpoint = mean(df$lifeExp)
#    ) +
  theme(aspect.ratio = 1/2)

2.2 大きさを比較する

2.2.1 棒グラフの例

library(conflicted)
library(tidyverse)
library(patchwork)

#データの定義
week <- c("月曜", "火曜", "水曜", "木曜", "金曜", "土曜", "日曜")
data <- data.frame(
  week = factor(week, levels = week),
  sales = c(30, 25, 35, 28, 22, 34, 35),
  card_member = c(20, 13, 20, 14, 14, 20, 25),
  non_member = c(10, 12, 15, 14, 8, 14, 10)
)

#基本的な棒グラフの作成
p1 <- data |>
  ggplot(aes(x = week, y = sales)) + 
  geom_col(fill = "blue") + 
  theme(axis.title.x = element_blank(), legend.position = "none") +
  labs(title = "基本的な棒グラフ",  x= "", y = "売上 [万円]")

#積み上げ棒グラフの作成
data_long <- data |>
  select(!sales) |>
  pivot_longer(!week, names_to = "membership", values_to = "sales")

p2 <- data_long |>
  ggplot(aes(x=week, y=sales, fill=membership)) +
  geom_col(position = "stack") + 
  theme(
    axis.title.x = element_blank(),
    legend.position = "none"
    ) +
  labs(y = "売上 [万円]", title = "積み上げ棒グラフ")

#水平棒グラフの作成
p3 <- data_long |>
  ggplot(aes(x=week, y=sales, fill=membership)) +
  geom_col(position = "dodge") + 
  coord_flip() + 
  theme(
    legend.title = element_blank(),
    legend.position = c(0.9, 0.2)
      ) +
  labs(y = "売上 [万円]", x = "", title = "水平棒グラフ/集団棒グラフ") +
  scale_fill_hue(name = "カード会員", labels = c(card_member = "カード会員", non_member ="非会員") )

#プロットの並べ方設定
(p1 + p2) / p3

2.2.2 折れ線グラフの例

library(conflicted)
library(tidyverse)
library(patchwork)

week <- c("月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日")
set.seed(0)
data.frame(
  曜日 = factor(week, levels = week),
  Aさん = rnorm(7, 36, 0.2),
  Bさん = rnorm(7, 36, 0.2)
  ) |>
  pivot_longer(!曜日) |>
  ggplot(aes(x=曜日, y = value, group = name, color = name, linetype = name, shape = name)) + 
  geom_line() +
  geom_point() + 
  theme(
    legend.title = element_blank(),
    legend.position = c(0.9, 0.8)
    ) +
    labs(y = "体温[℃]", title="折れ線グラフ") + 
  theme(aspect.ratio = 1/2)

2.2.3 見やすさのための折れ線グラフ

library(conflicted)
library(tidyverse)
library(patchwork)

people <- LETTERS[1:7]
set.seed(0)
df <- data.frame(
= c(people, people),
  temp = rnorm(14, mean = 36.0, sd = 0.2),
  time_of_day = c(rep("夕方", 7), rep("早朝", 7))
  )

# マーカーのみの折れ線グラフをプロット
p1 <- df |>
  ggplot(aes(
    x = 人, y = temp, group = time_of_day, shape = time_of_day,
    color = time_of_day, linetype = time_of_day)) +
  geom_point() +
  labs(title = "マーカーのみプロット", x = "", y = "体温 [℃]" ) +
  theme(
    aspect.ratio = 1,
    legend.title = element_blank(),
    legend.position = c(0.8, 0.8)
    )

p2 <- p1 +
  geom_line() +
  labs(title = "見やすさのための補助の折れ線を追加")

p1 + p2

2.3 標本を視えるようにする

2.3.1 平均値の棒グラフの危険性

library(conflicted)
library(tidyverse)
library(patchwork)

p1 <- data.frame(
  x = c("商品1","商品2"),
  avg = c(100, 80)
  ) |>
  ggplot(aes(x = x, y = avg)) +
  geom_col(fill = c("blue","orange")) +
  theme(axis.title.x = element_blank()) +
  labs(y = "日別販売数(平均)", title = "平均値のみ比較") +
  coord_cartesian(ylim = c(0, 130))

# データの生成
n_small <- 30
n_large <- 4
set.seed(0)
df_small_var <- bind_rows(
  data.frame(
    商品 = rep("商品1", n_small),
    日別販売数 = rnorm(n_small, 100, 5) # 平均100、標準偏差5の正規分布に従う乱数を30個生成
    ), 
  data.frame(
    商品 = rep("商品2", n_small),
    日別販売数 = rnorm(n_small, 80, 5) # 平均80、標準偏差5の正規分布に従う乱数を30個生成
    )
  ) 

p2 <- df_small_var |>
  ggplot(aes(x=商品, y=日別販売数, color = 商品)) + 
  geom_jitter(width = 0.1, height = 0) +
  theme(
    axis.title.x = element_blank(),
    legend.position = "none"
    )+
  labs(title = "サンプルサイズ大\nばらつき小") +
  coord_cartesian(ylim = c(0, 130))

set.seed(1)
df_large_var <- bind_rows(
  data.frame(
    商品 = rep("商品1", n_large),
    日別販売数 = rnorm(n_large, 100, 20) # 平均100、標準偏差20の正規分布に従う乱数を4個生成
  ),
  data.frame(
    商品 = rep("商品2", n_large),
    日別販売数 = rnorm(n_large, 80, 20) # 平均80、標準偏差20の正規分布に従う乱数を4個生成
  )
)

p3 <- df_large_var |>
  ggplot(aes(x=商品, y=日別販売数, color = 商品)) + 
  geom_jitter(width = 0.1, height = 0) +
  theme(
    axis.title.x = element_blank(),
    legend.position = "none"
  )+
  labs(title = "サンプルサイズ小\nばらつき大") +
  coord_cartesian(ylim = c(0, 130))

p1 + p2 + p3

2.3.2 様々な標本の可視化

library(conflicted)
library(tidyverse)
library(ggbeeswarm)
library(patchwork)

num_samples <- 100 # サンプルサイズ
set.seed(0)
data <- data.frame(
  Value = c(
    rnorm(num_samples, 100, 10), # 平均100、標準偏差10の正規分布
    rnorm(num_samples, 80, 20)   # 平均80、標準偏差20の正規分布
    ),
  Category = c(
    rep("商品3", num_samples), 
    rep("商品4", num_samples)
    )
  )

# ggplot2の基本設定
plt <- data |>
  ggplot(aes(x=Category, y=Value)) +
  theme(
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    legend.position = "none"
  )

# ストリッププロット (Dodge position)
p1 <- plt +
  geom_jitter(aes(color = Category), height = 0, width = 0.1)+
  scale_y_continuous(limits = c(0, 140)) +
  labs(title = "ストリッププロット")

# スウォームプロット
p2 <- plt +
  geom_beeswarm(aes(color = Category),cex = 3) +
  labs(title = "スウォームプロット")

# ヒストグラム
p3 <- data |>
  ggplot(aes(y=Value, fill=Category)) +
  geom_histogram(alpha=0.5, position='identity') +
  labs(title = "ヒストグラム") +
  theme(
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    legend.title = element_blank(),
    legend.position = c(0.8, 0.8)
  )

# バイオリンプロット
p4 <- plt + 
  geom_violin(aes(fill = Category), trim=FALSE) +
  geom_boxplot(width = .1, fill = "gray", color="black")+
  stat_summary(fun = mean, geom = "point", 
               shape =16, size = 2, color = "red", alpha = 0.5)+
  scale_y_continuous(limits = c(0, 140))+
  labs(title = "バイオリンプロット")

# エラーバー付き棒グラフ
p5 <- plt +
  stat_summary(aes(fill = Category),fun = "mean", geom = "bar") +
  stat_summary(geom = "errorbar",
               fun.data = "mean_sdl",
               width = 0.1, color = "black") +
  scale_y_continuous(limits = c(0, 140))+
  labs(title = "エラーバー付き棒グラフ")

# 箱ひげ図
p6 <- plt +
  geom_boxplot(aes(fill = Category)) +
  scale_y_continuous(limits = c(0, 140))+
  labs(title = "箱ひげ図")

(p1 + p2 + p3) / (p4 + p5 + p6)

2.3.3 箱髭図の構成要素

library(conflicted)
library(tidyverse)
library(ggbeeswarm)

set.seed(0)
data.frame(
  Value = rnorm(100, mean=80, sd=20),
  Category = "商品4"
  ) |>
  ggplot(aes(x=Category, y=Value)) +
  geom_boxplot(fill = "orange", width = 0.5) +
  geom_beeswarm(shape = 21, cex = 3, fill = "orange", alpha=0.6) +
  coord_cartesian(ylim = c(0,140)) +
  labs(title = "箱髭図で表現されるデータの特徴") +
  theme(
    legend.position="none", 
    axis.title.x=element_blank(), 
    axis.title.y=element_blank()
    )

第2章はここまで。

LS0tCnRpdGxlOiAi56ysMueroCDmlbDph4/jgpLmiormj6HjgZnjgovjg4fjg7zjgr/lj6/oppbljJYiCmF1dGhvcjogIk9zYW11LCBNT1JJTU9UTyIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICB0aGVtZTogdW5pdGVkICAgIAogICAgbWRfZXh0ZW5zaW9uczogIi1hc2NpaV9pZGVudGlmaWVycyIKICAgIHRvY19mbG9hdDogeWVzCiAgICBmaWdfd2lkdGg6IDcuNQogICAgZmlnX2hlaWdodDogNS42MjUKICAgIGRldjogcmFnZ19wbmcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgrlm7Pjga7lj7PkuIrjga5gc2hvd2Djg5zjgr/jg7PjgpLmirzjgZnjgahS44Gu44Kz44O844OJ44GM6KGo56S644GV44KM44G+44GZ44CCCgojIyAyLjEg5pWw6YeP44Go5Zuz5b2i44Gu5aSn44GN44GV44KS57SQ44Gl44GR44KLCgojIyMgMi4xLjEg5Zuz5b2i44Gu5aSn44GN44GV44Go5pWw6YeP44KS57SQ44Gl44GR44KLCgpgYGB7ciBmaWcuaGVpZ2h0PTcuNSwgZmlnLndpZHRoPTcuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShjb25mbGljdGVkKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3B1YnIpCgpsYWJlbCA8LSBjKCLmlK/mjIHjgZnjgosiLCAi5pSv5oyB44GX44Gq44GEIiwgIuOBqeOBoeOCieOBqOOCglxu44GE44GI44Gq44GEIiwgIueEoeWbnuetlCIpCmRhdGEuZnJhbWUoCiAgbGFiZWw9ZmFjdG9yKGxhYmVsLCBsZXZlbHMgPSByZXYobGFiZWwpKSwKICBkYXRhPWMoNDAsIDMyLCAyNSwgMykKICApIHw+CiAgZ2dkb251dGNoYXJ0KAogICAgeCA9ICJkYXRhIiwKICAgIGxhYmVsID0gImxhYmVsIiwKICAgIGZpbGwgPSAibGFiZWwiLAogICAgcGFsZXR0ZSA9IGMoImRhcmtncmF5IiwgImxpZ2h0Z3JheSIsICJyZWQiLCAiYmx1ZSIpCiAgICApICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKIyMjIDIuMS4yIOODr+ODvOODieOCr+ODqeOCpuODieOCkueUqOOBhOOBn+OAjOmgu+W6puOBqOimi+OBn+ebruOBruWkp+OBjeOBleOAjeOBrue0kOOBpeOBkQoK44K544OI44OD44OX44Ov44O844OJ44GM6YGV44GG44KI44GG44Gn44CB5YWo44GP5LiA57eS44Gr44Gv44Gq44KJ44Gq44GE44Gn44GZ44CCCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KHdvcmRjbG91ZDIpCgojIOODhuOCreOCueODiOODh+ODvOOCvwpkZiA8LSBkYXRhLmZyYW1lKAogIHRleHQgPSAiQ2x1c3RlcmluZyBjb2VmZmljaWVudHMgZm9yIGNvcnJlbGF0aW9uIG5ldHdvcmtzLCBFbmVyZ3kgbGFuZHNjYXBlIGFuYWx5c2lzIG9mIG5ldXJvaW1hZ2luZyBkYXRhLCBTaW11bGF0aW9uIG9mIHNwYWNlIGFjcXVpc2l0aW9uIHByb2Nlc3Mgb2YgcGVkZXN0cmlhbnMgdXNpbmcgcHJveGVtaWMgZmxvb3IgZmllbGQgbW9kZWwsIFBlZGVzdHJpYW4gZmxvdyB0aHJvdWdoIG11bHRpcGxlIGJvdHRsZW5lY2tzLCBDbG9zZXIgdG8gY3JpdGljYWwgcmVzdGluZy1zdGF0ZSBuZXVyYWwgZHluYW1pY3MgaW4gaW5kaXZpZHVhbHMgd2l0aCBoaWdoZXIgZmx1aWQgaW50ZWxsaWdlbmNlLCBSZWluZm9yY2VtZW50IGxlYXJuaW5nIGV4cGxhaW5zIGNvbmRpdGlvbmFsIGNvb3BlcmF0aW9uIGFuZCBpdHMgbW9vZHkgY291c2luLCBKYW0tYWJzb3JwdGlvbiBkcml2aW5nIHdpdGggYSBjYXItZm9sbG93aW5nIG1vZGVsLCBBZ2XigJByZWxhdGVkIGNoYW5nZXMgaW4gdGhlIGVhc2Ugb2YgZHluYW1pY2FsIHRyYW5zaXRpb25zIGluIGh1bWFuIGJyYWluIGFjdGl2aXR5LCBQb3RlbnRpYWwgZ2xvYmFsIGphbW1pbmcgdHJhbnNpdGlvbiBpbiBhdmlhdGlvbiBuZXR3b3JrcywgTWV0aG9kb2xvZ3kgYW5kIHRoZW9yZXRpY2FsIGJhc2lzIG9mIGZvcndhcmQgZ2VuZXRpYyBzY3JlZW5pbmcgZm9yIHNsZWVwL3dha2VmdWxuZXNzIGluIG1pY2UsIEphbW1pbmcgdHJhbnNpdGlvbnMgaW4gZm9yY2UtYmFzZWQgbW9kZWxzIGZvciBwZWRlc3RyaWFuIGR5bmFtaWNzLCBJbmZsb3cgcHJvY2VzcyBvZiBwZWRlc3RyaWFucyB0byBhIGNvbmZpbmVkIHNwYWNlLCBFeGFjdCBzb2x1dGlvbiBvZiBhIGhldGVyb2dlbmVvdXMgbXVsdGlsYW5lIGFzeW1tZXRyaWMgc2ltcGxlIGV4Y2x1c2lvbiBwcm9jZXNzLCBFeGFjdCBzdGF0aW9uYXJ5IGRpc3RyaWJ1dGlvbiBvZiBhbiBhc3ltbWV0cmljIHNpbXBsZSBleGNsdXNpb24gcHJvY2VzcyB3aXRoIExhbmdtdWlyIGtpbmV0aWNzIGFuZCBtZW1vcnkgcmVzZXJ2b2lycywgVGFtaW5nIG1hY3Jvc2NvcGljIGphbW1pbmcgaW4gdHJhbnNwb3J0YXRpb24gbmV0d29ya3MsIEEgZGVtb25zdHJhdGlvbiBleHBlcmltZW50IG9mIGEgdGhlb3J5IG9mIGphbS1hYnNvcnB0aW9uIGRyaXZpbmcsIEEgYmFsYW5jZSBuZXR3b3JrIGZvciB0aGUgYXN5bW1ldHJpYyBzaW1wbGUgZXhjbHVzaW9uIHByb2Nlc3MsIFJlaW5mb3JjZW1lbnQgbGVhcm5pbmcgYWNjb3VudCBvZiBuZXR3b3JrIHJlY2lwcm9jaXR5LCBUb3dhcmRzIHVuZGVyc3RhbmRpbmcgbmV0d29yayB0b3BvbG9neSBhbmQgcm9idXN0bmVzcyBvZiBsb2dpc3RpY3Mgc3lzdGVtcywgSW5mbG93IHByb2Nlc3M6IEEgY291bnRlcnBhcnQgb2YgZXZhY3VhdGlvbiwgQW5hbHlzaXMgb24gYSBzaW5nbGUgc2VnbWVudCBvZiBldmFjdWF0aW9uIG5ldHdvcmssIER5bmFtaWNzIG9mIGFzc2VtYmx5IHByb2R1Y3Rpb24gZmxvdywgUHJlc3luYXB0aWMgaW5oaWJpdGlvbiBvZiBkb3BhbWluZSBuZXVyb25zIGNvbnRyb2xzIG9wdGltaXN0aWMgYmlhcywgQnJpZGdpbmcgdGhlIG1pY3JvLW1hY3JvIGdhcCBiZXR3ZWVuIHNpbmdsZS1tb2xlY3VsYXIgYmVoYXZpb3IgYW5kIGJ1bGsgaHlkcm9seXNpcyBwcm9wZXJ0aWVzIG9mIGNlbGx1bGFzZSwgQ2x1c3RlciBzaXplIGRpc3RyaWJ1dGlvbiBpbiAxRC1DQSB0cmFmZmljIG1vZGVscywgTW9kZWxsaW5nIHN0YXRl4oCQdHJhbnNpdGlvbiBkeW5hbWljcyBpbiByZXN0aW5n4oCQc3RhdGUgYnJhaW4gc2lnbmFscyBieSB0aGUgaGlkZGVuIE1hcmtvdiBhbmQgR2F1c3NpYW4gbWl4dHVyZSBtb2RlbHMsIFBvc2l0aXZlIGNvbmdlc3Rpb24gZWZmZWN0IG9uIGEgdG90YWxseSBhc3ltbWV0cmljIHNpbXBsZSBleGNsdXNpb24gcHJvY2VzcyB3aXRoIGFuIGFkc29ycHRpb24gbGFuZSwgTWV0YXN0YWJpbGl0eSBpbiBwZWRlc3RyaWFuIGV2YWN1YXRpb24sIENvbnN0cnVjdGluZyBxdWFudHVtIGRhcmsgc29saXRvbnMgd2l0aCBzdGFibGUgc2NhdHRlcmluZyBwcm9wZXJ0aWVzLCBUaGUgQXV0b25vbW91cyBTZW5zb3J5IE1lcmlkaWFuIFJlc3BvbnNlIEFjdGl2YXRlcyB0aGUgUGFyYXN5bXBhdGhldGljIE5lcnZvdXMgU3lzdGVtLCBUcmFpdCwgc3RhZ2luZywgYW5kIHN0YXRlIG1hcmtlcnMgb2YgcHN5Y2hvc2lzIGJhc2VkIG9uIGZ1bmN0aW9uYWwgYWx0ZXJhdGlvbiBvZiBzYWxpZW5jZS1yZWxhdGVkIG5ldHdvcmtzIGluIHRoZSBoaWdoLXJpc2ssIGZpcnN0IGVwaXNvZGUsIGFuZCBjaHJvbmljIHN0YWdlcywgQ3JpdGljYWwgYnJhaW4gZHluYW1pY3MgYW5kIGh1bWFuIGludGVsbGlnZW5jZSwgSW5mbHVlbmNlIG9mIHZlbG9jaXR5IHZhcmlhbmNlIG9mIGEgc2luZ2xlIHBhcnRpY2xlIG9uIGNlbGx1bGFyIGF1dG9tYXRvbiBtb2RlbHMsIENvbGxlY3RpdmUgbW90aW9uIG9mIG9zY2lsbGF0b3J5IHdhbGtlcnMsIFJlaW5mb3JjaW5nIGNyaXRpY2FsIGxpbmtzIGZvciByb2J1c3QgbmV0d29yayBsb2dpc3RpY3M6IEEgY2VudHJhbGl0eSBtZWFzdXJlIGZvciBzdWJzdGl0dXRhYmlsaXR5LCBEeW5hbWljIHRyYW5zaXRpb25zIGJldHdlZW4gYnJhaW4gc3RhdGVzIHByZWRpY3QgYXVkaXRvcnkgYXR0ZW50aW9uYWwgZmx1Y3R1YXRpb25zLCBBc3NvY2lhdGlvbnMgb2YgY29uc2VydmF0aXNtL2p1bXBpbmcgdG8gY29uY2x1c2lvbnMgYmlhc2VzIHdpdGggYWJlcnJhbnQgc2FsaWVuY2UgYW5kIGRlZmF1bHQgbW9kZSBuZXR3b3JrLCBNb2RlbCByZXRyYWluaW5nIGFuZCBpbmZvcm1hdGlvbiBzaGFyaW5nIGluIGEgc3VwcGx5IGNoYWluIHdpdGggbG9uZy10ZXJtIGZsdWN0dWF0aW5nIGRlbWFuZHMsIEZ1bmN0aW9uYWwgYWx0ZXJhdGlvbnMgb2Ygc2FsaWVuY2UtcmVsYXRlZCBuZXR3b3JrcyBhcmUgYXNzb2NpYXRlZCB3aXRoIHRyYWl0cywgc3RhZ2luZywgYW5kIHRoZSBzdGF0ZSBvZiBwc3ljaG9zaXMuIgopCgpkZiB8PgogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCkgfD4KICBjb3VudCh3b3JkLCBzb3J0ID0gVFJVRSwgbmFtZSA9ICJmcmVxIikgfD4KICBhbnRpX2pvaW4oc3RvcF93b3JkcywgYnkgPSBqb2luX2J5KHdvcmQpKSB8PgogIHdvcmRjbG91ZDIoc2hhcGUgPSAic3F1YXJlIiwgc2h1ZmZsZSA9IEZBTFNFKQpgYGAKCiMjIyAyLjEuMyDjg4Tjg6rjg7zjg57jg4Pjg5fjgavjgojjgovjgrDjg6vjg7zjg5fmg4XloLHjga7ku5jkuI4KCmBgYHtyIGZpZy5oZWlnaHQ9NS42MjUsIGZpZy53aWR0aD03LjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodHJlZW1hcGlmeSkKbGlicmFyeShnYXBtaW5kZXIpCmxpYnJhcnkodmlyaWRpcykKCiMgZ2FwbWluZGVy44OH44O844K/44K744OD44OI44GL44KJMjAwN+W5tOOBruODh+ODvOOCv+OCkuaKveWHugpkZiA8LSBnYXBtaW5kZXIgfD4KICBkcGx5cjo6ZmlsdGVyKHllYXIgPT0gMjAwNykKCmRmIHw+CiAgZ2dwbG90KGFlcyhhcmVhID0gcG9wLCBmaWxsID0gbGlmZUV4cCwgbGFiZWwgPSBjb3VudHJ5LCBzdWJncm91cCA9IGNvbnRpbmVudCkpICsKICBnZW9tX3RyZWVtYXAoKSArCiAgZ2VvbV90cmVlbWFwX3RleHQoY29sb3VyID0gImJsYWNrIiwgcGxhY2UgPSAidG9wbGVmdCIsIHJlZmxvdyA9IFRSVUUpICsKICBnZW9tX3RyZWVtYXBfc3ViZ3JvdXBfYm9yZGVyKCkgKwogIGdlb21fdHJlZW1hcF9zdWJncm91cF90ZXh0KAogICAgcGxhY2UgPSAiY2VudHJlIiwgZ3JvdyA9IFRSVUUsIGFscGhhID0gMC42LCBjb2xvdXIgPSAiYmxhY2siLAogICAgZm9udGZhY2UgPSAiaXRhbGljIiwgbWluLnNpemUgPSAwCiAgICApICsKICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uID0gInR1cmJvIiwgZGlyZWN0aW9uID0gLTEpICsKIyAgc2NhbGVfZmlsbF9ncmFkaWVudDIoCiMgICAgbG93ICA9ICJyZWQiLCBtaWQgID0gIndoaXRlIiwgaGlnaCA9ICJibHVlIiwgbWlkcG9pbnQgPSBtZWFuKGRmJGxpZmVFeHApCiMgICAgKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMS8yKQpgYGAKCiMjIDIuMiDlpKfjgY3jgZXjgpLmr5TovIPjgZnjgosKCiMjIyAyLjIuMSDmo5LjgrDjg6njg5Xjga7kvosKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTcuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShjb25mbGljdGVkKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShwYXRjaHdvcmspCgoj44OH44O844K/44Gu5a6a576pCndlZWsgPC0gYygi5pyI5pucIiwgIueBq+abnCIsICLmsLTmm5wiLCAi5pyo5pucIiwgIumHkeabnCIsICLlnJ/mm5wiLCAi5pel5pucIikKZGF0YSA8LSBkYXRhLmZyYW1lKAogIHdlZWsgPSBmYWN0b3Iod2VlaywgbGV2ZWxzID0gd2VlayksCiAgc2FsZXMgPSBjKDMwLCAyNSwgMzUsIDI4LCAyMiwgMzQsIDM1KSwKICBjYXJkX21lbWJlciA9IGMoMjAsIDEzLCAyMCwgMTQsIDE0LCAyMCwgMjUpLAogIG5vbl9tZW1iZXIgPSBjKDEwLCAxMiwgMTUsIDE0LCA4LCAxNCwgMTApCikKCiPln7rmnKznmoTjgarmo5LjgrDjg6njg5Xjga7kvZzmiJAKcDEgPC0gZGF0YSB8PgogIGdncGxvdChhZXMoeCA9IHdlZWssIHkgPSBzYWxlcykpICsgCiAgZ2VvbV9jb2woZmlsbCA9ICJibHVlIikgKyAKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnModGl0bGUgPSAi5Z+65pys55qE44Gq5qOS44Kw44Op44OVIiwgIHg9ICIiLCB5ID0gIuWjsuS4iiBb5LiH5YaGXSIpCgoj56mN44G/5LiK44GS5qOS44Kw44Op44OV44Gu5L2c5oiQCmRhdGFfbG9uZyA8LSBkYXRhIHw+CiAgc2VsZWN0KCFzYWxlcykgfD4KICBwaXZvdF9sb25nZXIoIXdlZWssIG5hbWVzX3RvID0gIm1lbWJlcnNoaXAiLCB2YWx1ZXNfdG8gPSAic2FsZXMiKQoKcDIgPC0gZGF0YV9sb25nIHw+CiAgZ2dwbG90KGFlcyh4PXdlZWssIHk9c2FsZXMsIGZpbGw9bWVtYmVyc2hpcCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJzdGFjayIpICsgCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICAgICkgKwogIGxhYnMoeSA9ICLlo7LkuIogW+S4h+WGhl0iLCB0aXRsZSA9ICLnqY3jgb/kuIrjgZLmo5LjgrDjg6njg5UiKQoKI+awtOW5s+ajkuOCsOODqeODleOBruS9nOaIkApwMyA8LSBkYXRhX2xvbmcgfD4KICBnZ3Bsb3QoYWVzKHg9d2VlaywgeT1zYWxlcywgZmlsbD1tZW1iZXJzaGlwKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBjb29yZF9mbGlwKCkgKyAKICB0aGVtZSgKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45LCAwLjIpCiAgICAgICkgKwogIGxhYnMoeSA9ICLlo7LkuIogW+S4h+WGhl0iLCB4ID0gIiIsIHRpdGxlID0gIuawtOW5s+ajkuOCsOODqeODle+8j+mbhuWbo+ajkuOCsOODqeODlSIpICsKICBzY2FsZV9maWxsX2h1ZShuYW1lID0gIuOCq+ODvOODieS8muWToSIsIGxhYmVscyA9IGMoY2FyZF9tZW1iZXIgPSAi44Kr44O844OJ5Lya5ZOhIiwgbm9uX21lbWJlciA9IumdnuS8muWToSIpICkKCiPjg5fjg63jg4Pjg4jjga7kuKbjgbnmlrnoqK3lrpoKKHAxICsgcDIpIC8gcDMKYGBgCgojIyMgMi4yLjIg5oqY44KM57ea44Kw44Op44OV44Gu5L6LCgpgYGB7ciBmaWcuaGVpZ2h0PTMuNzUsIGZpZy53aWR0aD03LjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGF0Y2h3b3JrKQoKd2VlayA8LSBjKCLmnIjmm5zml6UiLCAi54Gr5puc5pelIiwgIuawtOabnOaXpSIsICLmnKjmm5zml6UiLCAi6YeR5puc5pelIiwgIuWcn+abnOaXpSIsICLml6Xmm5zml6UiKQpzZXQuc2VlZCgwKQpkYXRhLmZyYW1lKAogIOabnOaXpSA9IGZhY3Rvcih3ZWVrLCBsZXZlbHMgPSB3ZWVrKSwKICBB44GV44KTID0gcm5vcm0oNywgMzYsIDAuMiksCiAgQuOBleOCkyA9IHJub3JtKDcsIDM2LCAwLjIpCiAgKSB8PgogIHBpdm90X2xvbmdlcigh5puc5pelKSB8PgogIGdncGxvdChhZXMoeD3mm5zml6UsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBuYW1lLCBjb2xvciA9IG5hbWUsIGxpbmV0eXBlID0gbmFtZSwgc2hhcGUgPSBuYW1lKSkgKyAKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgdGhlbWUoCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuOSwgMC44KQogICAgKSArCiAgICBsYWJzKHkgPSAi5L2T5ripW+KEg10iLCB0aXRsZT0i5oqY44KM57ea44Kw44Op44OVIikgKyAKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxLzIpCmBgYAoKIyMjIDIuMi4zIOimi+OChOOBmeOBleOBruOBn+OCgeOBruaKmOOCjOe3muOCsOODqeODlQoKYGBge3IgZmlnLmhlaWdodD0zLjc1LCBmaWcud2lkdGg9Ny41LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBhdGNod29yaykKCnBlb3BsZSA8LSBMRVRURVJTWzE6N10Kc2V0LnNlZWQoMCkKZGYgPC0gZGF0YS5mcmFtZSgKICDkurogPSBjKHBlb3BsZSwgcGVvcGxlKSwKICB0ZW1wID0gcm5vcm0oMTQsIG1lYW4gPSAzNi4wLCBzZCA9IDAuMiksCiAgdGltZV9vZl9kYXkgPSBjKHJlcCgi5aSV5pa5IiwgNyksIHJlcCgi5pep5pydIiwgNykpCiAgKQoKIyDjg57jg7zjgqvjg7zjga7jgb/jga7mipjjgoznt5rjgrDjg6njg5XjgpLjg5fjg63jg4Pjg4gKcDEgPC0gZGYgfD4KICBnZ3Bsb3QoYWVzKAogICAgeCA9IOS6uiwgeSA9IHRlbXAsIGdyb3VwID0gdGltZV9vZl9kYXksIHNoYXBlID0gdGltZV9vZl9kYXksCiAgICBjb2xvciA9IHRpbWVfb2ZfZGF5LCBsaW5ldHlwZSA9IHRpbWVfb2ZfZGF5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh0aXRsZSA9ICLjg57jg7zjgqvjg7zjga7jgb/jg5fjg63jg4Pjg4giLCB4ID0gIiIsIHkgPSAi5L2T5ripIFvihINdIiApICsKICB0aGVtZSgKICAgIGFzcGVjdC5yYXRpbyA9IDEsCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuOCwgMC44KQogICAgKQoKcDIgPC0gcDEgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIuimi+OChOOBmeOBleOBruOBn+OCgeOBruijnOWKqeOBruaKmOOCjOe3muOCkui/veWKoCIpCgpwMSArIHAyCmBgYAoKIyMgMi4zIOaomeacrOOCkuimluOBiOOCi+OCiOOBhuOBq+OBmeOCiwoKIyMjIDIuMy4xIOW5s+Wdh+WApOOBruajkuOCsOODqeODleOBruWNsemZuuaApwoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9Ny41LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBhdGNod29yaykKCnAxIDwtIGRhdGEuZnJhbWUoCiAgeCA9IGMoIuWVhuWTgTEiLCLllYblk4EyIiksCiAgYXZnID0gYygxMDAsIDgwKQogICkgfD4KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0gYXZnKSkgKwogIGdlb21fY29sKGZpbGwgPSBjKCJibHVlIiwib3JhbmdlIikpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKHkgPSAi5pel5Yil6LKp5aOy5pWw77yI5bmz5Z2H77yJIiwgdGl0bGUgPSAi5bmz5Z2H5YCk44Gu44G/5q+U6LyDIikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMzApKQoKIyDjg4fjg7zjgr/jga7nlJ/miJAKbl9zbWFsbCA8LSAzMApuX2xhcmdlIDwtIDQKc2V0LnNlZWQoMCkKZGZfc21hbGxfdmFyIDwtIGJpbmRfcm93cygKICBkYXRhLmZyYW1lKAogICAg5ZWG5ZOBID0gcmVwKCLllYblk4ExIiwgbl9zbWFsbCksCiAgICDml6XliKXosqnlo7LmlbAgPSBybm9ybShuX3NtYWxsLCAxMDAsIDUpICMg5bmz5Z2HMTAw44CB5qiZ5rqW5YGP5beuNeOBruato+imj+WIhuW4g+OBq+W+k+OBhuS5seaVsOOCkjMw5YCL55Sf5oiQCiAgICApLCAKICBkYXRhLmZyYW1lKAogICAg5ZWG5ZOBID0gcmVwKCLllYblk4EyIiwgbl9zbWFsbCksCiAgICDml6XliKXosqnlo7LmlbAgPSBybm9ybShuX3NtYWxsLCA4MCwgNSkgIyDlubPlnYc4MOOAgeaomea6luWBj+W3rjXjga7mraPopo/liIbluIPjgavlvpPjgYbkubHmlbDjgpIzMOWAi+eUn+aIkAogICAgKQogICkgCgpwMiA8LSBkZl9zbWFsbF92YXIgfD4KICBnZ3Bsb3QoYWVzKHg95ZWG5ZOBLCB5PeaXpeWIpeiyqeWjsuaVsCwgY29sb3IgPSDllYblk4EpKSArIAogIGdlb21faml0dGVyKHdpZHRoID0gMC4xLCBoZWlnaHQgPSAwKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICAgICkrCiAgbGFicyh0aXRsZSA9ICLjgrXjg7Pjg5fjg6vjgrXjgqTjgrrlpKdcbuOBsOOCieOBpOOBjeWwjyIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTMwKSkKCnNldC5zZWVkKDEpCmRmX2xhcmdlX3ZhciA8LSBiaW5kX3Jvd3MoCiAgZGF0YS5mcmFtZSgKICAgIOWVhuWTgSA9IHJlcCgi5ZWG5ZOBMSIsIG5fbGFyZ2UpLAogICAg5pel5Yil6LKp5aOy5pWwID0gcm5vcm0obl9sYXJnZSwgMTAwLCAyMCkgIyDlubPlnYcxMDDjgIHmqJnmupblgY/lt64yMOOBruato+imj+WIhuW4g+OBq+W+k+OBhuS5seaVsOOCkjTlgIvnlJ/miJAKICApLAogIGRhdGEuZnJhbWUoCiAgICDllYblk4EgPSByZXAoIuWVhuWTgTIiLCBuX2xhcmdlKSwKICAgIOaXpeWIpeiyqeWjsuaVsCA9IHJub3JtKG5fbGFyZ2UsIDgwLCAyMCkgIyDlubPlnYc4MOOAgeaomea6luWBj+W3rjIw44Gu5q2j6KaP5YiG5biD44Gr5b6T44GG5Lmx5pWw44KSNOWAi+eUn+aIkAogICkKKQoKcDMgPC0gZGZfbGFyZ2VfdmFyIHw+CiAgZ2dwbG90KGFlcyh4PeWVhuWTgSwgeT3ml6XliKXosqnlo7LmlbAsIGNvbG9yID0g5ZWG5ZOBKSkgKyAKICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMSwgaGVpZ2h0ID0gMCkgKwogIHRoZW1lKAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiCiAgKSsKICBsYWJzKHRpdGxlID0gIuOCteODs+ODl+ODq+OCteOCpOOCuuWwj1xu44Gw44KJ44Gk44GN5aSnIikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMzApKQoKcDEgKyBwMiArIHAzCmBgYAoKIyMjIDIuMy4yIOanmOOAheOBquaomeacrOOBruWPr+imluWMlgoKYGBge3IgZmlnLmhlaWdodD03LjUsIGZpZy53aWR0aD03LjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2diZWVzd2FybSkKbGlicmFyeShwYXRjaHdvcmspCgpudW1fc2FtcGxlcyA8LSAxMDAgIyDjgrXjg7Pjg5fjg6vjgrXjgqTjgroKc2V0LnNlZWQoMCkKZGF0YSA8LSBkYXRhLmZyYW1lKAogIFZhbHVlID0gYygKICAgIHJub3JtKG51bV9zYW1wbGVzLCAxMDAsIDEwKSwgIyDlubPlnYcxMDDjgIHmqJnmupblgY/lt64xMOOBruato+imj+WIhuW4gwogICAgcm5vcm0obnVtX3NhbXBsZXMsIDgwLCAyMCkgICAjIOW5s+Wdhzgw44CB5qiZ5rqW5YGP5beuMjDjga7mraPopo/liIbluIMKICAgICksCiAgQ2F0ZWdvcnkgPSBjKAogICAgcmVwKCLllYblk4EzIiwgbnVtX3NhbXBsZXMpLCAKICAgIHJlcCgi5ZWG5ZOBNCIsIG51bV9zYW1wbGVzKQogICAgKQogICkKCiMgZ2dwbG90MuOBruWfuuacrOioreWumgpwbHQgPC0gZGF0YSB8PgogIGdncGxvdChhZXMoeD1DYXRlZ29yeSwgeT1WYWx1ZSkpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICkKCiMg44K544OI44Oq44OD44OX44OX44Ot44OD44OIIChEb2RnZSBwb3NpdGlvbikKcDEgPC0gcGx0ICsKICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBDYXRlZ29yeSksIGhlaWdodCA9IDAsIHdpZHRoID0gMC4xKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNDApKSArCiAgbGFicyh0aXRsZSA9ICLjgrnjg4jjg6rjg4Pjg5fjg5fjg63jg4Pjg4giKQoKIyDjgrnjgqbjgqnjg7zjg6Djg5fjg63jg4Pjg4gKcDIgPC0gcGx0ICsKICBnZW9tX2JlZXN3YXJtKGFlcyhjb2xvciA9IENhdGVnb3J5KSxjZXggPSAzKSArCiAgbGFicyh0aXRsZSA9ICLjgrnjgqbjgqnjg7zjg6Djg5fjg63jg4Pjg4giKQoKIyDjg5Ljgrnjg4jjgrDjg6njg6AKcDMgPC0gZGF0YSB8PgogIGdncGxvdChhZXMoeT1WYWx1ZSwgZmlsbD1DYXRlZ29yeSkpICsKICBnZW9tX2hpc3RvZ3JhbShhbHBoYT0wLjUsIHBvc2l0aW9uPSdpZGVudGl0eScpICsKICBsYWJzKHRpdGxlID0gIuODkuOCueODiOOCsOODqeODoCIpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjgpCiAgKQoKIyDjg5DjgqTjgqrjg6rjg7Pjg5fjg63jg4Pjg4gKcDQgPC0gcGx0ICsgCiAgZ2VvbV92aW9saW4oYWVzKGZpbGwgPSBDYXRlZ29yeSksIHRyaW09RkFMU0UpICsKICBnZW9tX2JveHBsb3Qod2lkdGggPSAuMSwgZmlsbCA9ICJncmF5IiwgY29sb3I9ImJsYWNrIikrCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCAKICAgICAgICAgICAgICAgc2hhcGUgPTE2LCBzaXplID0gMiwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDE0MCkpKwogIGxhYnModGl0bGUgPSAi44OQ44Kk44Kq44Oq44Oz44OX44Ot44OD44OIIikKCiMg44Ko44Op44O844OQ44O85LuY44GN5qOS44Kw44Op44OVCnA1IDwtIHBsdCArCiAgc3RhdF9zdW1tYXJ5KGFlcyhmaWxsID0gQ2F0ZWdvcnkpLGZ1biA9ICJtZWFuIiwgZ2VvbSA9ICJiYXIiKSArCiAgc3RhdF9zdW1tYXJ5KGdlb20gPSAiZXJyb3JiYXIiLAogICAgICAgICAgICAgICBmdW4uZGF0YSA9ICJtZWFuX3NkbCIsCiAgICAgICAgICAgICAgIHdpZHRoID0gMC4xLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNDApKSsKICBsYWJzKHRpdGxlID0gIuOCqOODqeODvOODkOODvOS7mOOBjeajkuOCsOODqeODlSIpCgojIOeuseOBsuOBkuWbswpwNiA8LSBwbHQgKwogIGdlb21fYm94cGxvdChhZXMoZmlsbCA9IENhdGVnb3J5KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDE0MCkpKwogIGxhYnModGl0bGUgPSAi566x44Gy44GS5ZuzIikKCihwMSArIHAyICsgcDMpIC8gKHA0ICsgcDUgKyBwNikKCmBgYAoKIyMjIDIuMy4zIOeusemrreWbs+OBruani+aIkOimgee0oAoKYGBge3IgZmlnLmhlaWdodD03LjUsIGZpZy53aWR0aD0zLjc1LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdnYmVlc3dhcm0pCgpzZXQuc2VlZCgwKQpkYXRhLmZyYW1lKAogIFZhbHVlID0gcm5vcm0oMTAwLCBtZWFuPTgwLCBzZD0yMCksCiAgQ2F0ZWdvcnkgPSAi5ZWG5ZOBNCIKICApIHw+CiAgZ2dwbG90KGFlcyh4PUNhdGVnb3J5LCB5PVZhbHVlKSkgKwogIGdlb21fYm94cGxvdChmaWxsID0gIm9yYW5nZSIsIHdpZHRoID0gMC41KSArCiAgZ2VvbV9iZWVzd2FybShzaGFwZSA9IDIxLCBjZXggPSAzLCBmaWxsID0gIm9yYW5nZSIsIGFscGhhPTAuNikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDE0MCkpICsKICBsYWJzKHRpdGxlID0gIueusemrreWbs+OBp+ihqOePvuOBleOCjOOCi+ODh+ODvOOCv+OBrueJueW+tCIpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsIAogICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwgCiAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpCiAgICApCmBgYAoK56ysMueroOOBr+OBk+OBk+OBvuOBp+OAggo=