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

8.1 効果的な可視化のテクニック

8.1.1 見づらい図と見やすい図

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

base_plot <- tibble(
  x = seq(0, 10, length.out = 100),
  y1 = sin(x),
  y2 = cos(x),
  y3 = y1 + y2
  ) |>
  pivot_longer(!x, names_to = "y") |>
  ggplot(aes(x = x, y = value, color = y, linetype = y)) +
  coord_cartesian(xlim = c(0 ,10), ylim = c(-3, 3)) +
  scale_color_hue(name = "", labels = c(y1 = "y = sin(x)", y2 ="y = cos(x)", y3 ="y = sin(x) + cos(x)")) +
  scale_linetype_discrete(name = "", labels = c(y1 = "y = sin(x)", y2 ="y = cos(x)", y3 ="y = sin(x) + cos(x)")) +
  theme(
    legend.title = element_blank(),
    legend.position = c(0.75, 0.85),
    aspect.ratio = 1
    )

# 見づらい図
p1 <- base_plot + 
  geom_line(linewidth = 0.2) +
  scale_x_continuous(breaks = seq(0, 10, by = 0.5)) +
  scale_y_continuous(breaks = seq(-3, 3, by = 0.2)) +
  labs(x = "x-axis label, x", y = "y-axis label, y", title = "見づらいグラフ") +
  theme(
    axis.title = element_text(size = 6, family = "Times New Roman"),
    axis.text = element_text(size = 6, family = "Times New Roman"),
    legend.text = element_text(size = 8, family = "Times New Roman")
    )

# 見やすい図
p2 <- base_plot + 
  geom_line(linewidth = 1) +
  scale_x_continuous(breaks = seq(0, 10, by = 2)) +
  scale_y_continuous(breaks = seq(-3, 3, by = 1)) +
  labs(x = "x-axis label, x", y = "y-axis label, y", title = "見やすいグラフ") +
  theme(
    axis.title = element_text(size = 14, family = "Arial"),
    axis.text = element_text(size = 14, family = "Arial"),
    legend.text = element_text(size = 12, family = "Arial")
  )
  
p1 + p2

8.1.2 グラフの縦横比と軸の範囲

library(conflicted)
library(tidyverse)

# データの定義
df <- data.frame(
  x = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
  y1 = c(11, 11.2, 11.5, 12, 12.2, 13, 14.2, 14.5, 15, 15.6, 16),
  y2 = c(11.1, 11.3, 11.4, 11.9, 12.1, 12.8, 14.0, 14.2, 14.7, 15.0, 15.5)
  ) |>
  pivot_longer(!x, names_to = "y")

# グラフ
p1 <- df |>
  ggplot(aes(x = x, y = value, color = y, shape = y)) +
  geom_line() +
  geom_point() +
  labs(x = "x", y = "y", title = "基準とする描画例") +
  theme(legend.title = element_blank(), legend.position = c(0.1, 0.8))

p2 <- df |>
  ggplot(aes(x = x, y = value, color = y, shape = y)) +
  geom_line() +
  geom_point() +
  labs(x = "x", y = "y", title = "縦軸範囲広げすぎ?") +
  coord_cartesian(ylim = c(0, 30)) +
  theme(legend.title = element_blank(), legend.position = c(0.1, 0.8))

p3 <- df |>
  ggplot(aes(x = x, y = value, color = y, shape = y)) +
  geom_line() +
  geom_point() +
  labs(x = "x", y = "y", title = "縦軸方向を強調") +
  theme(legend.title = element_blank(), legend.position = c(0.2, 0.9))

p4 <- df |>
  ggplot(aes(x = x, y = value, color = y, shape = y)) +
  geom_line() +
  geom_point() +
  labs(x = "x", y = "y", title = "横軸方向を強調") +
  theme(legend.title = element_blank(), legend.position = c(0.1, 0.8))

design <- "
  113
  223
  444
"

p1 + p2 + p3 + p4 + plot_layout(design = design)

8.1.3 片対数グラフを利用する

library(conflicted)
library(tidyverse)
library(zoo)
library(scales)

# 加工前のデータはこちらにあります。
# https://covid19.who.int/WHO-COVID-19-global-data.csv

# ファイルを読み込む
# 日本、アメリカ、中国のデータを抜き出す
# Date_reportedは日付型に
# 14日間の移動平均を計算
df <- read_csv("https://raw.githubusercontent.com/tkEzaki/data_visualization/main/8%E7%AB%A0/data/covid_data_dummy.csv") |>
  dplyr::filter(Country %in% c("Japan", "United States of America", "China")) |>
  mutate(
    Date_reported = as.Date(Date_reported),
    `14_day_avg` = rollmean(New_cases, 14, fill = NA),
    .by = Country
    ) |>
  mutate(Country = factor(Country, levels = c("Japan", "United States of America", "China")))


# 通常の縦軸
p1 <- df |>
  ggplot(aes(x = Date_reported)) +
  geom_line(aes(y = New_cases, color = Country)) +
  scale_y_continuous(labels = label_comma()) +
  theme(axis.text.x = element_text(angle = 30, hjust = 1)) +
  labs(x = "", y = "新規感染者数", title = "縦軸をそのままプロットしたもの") +
  theme(legend.title = element_blank(), legend.position = c(0.2, 0.8), aspect.ratio = 1/2)

# 対数縦軸
p2 <- df |>
  ggplot(aes(x = Date_reported)) +
  geom_line(aes(y = New_cases, color = Country)) +
  scale_y_continuous(trans = "log10", labels = label_comma()) +
  theme(axis.text.x = element_text(angle = 30, hjust = 1)) +
  labs(x = "", y = "新規感染者数", title = "縦軸を対数でプロットしたもの") +
  theme(legend.title = element_blank(), legend.position = "bottom", aspect.ratio = 1/2)

p1 / p2

8.1.4 凡例を近くに置く

コメントは「普段の平日より1.5倍の来客」となっているがコードは1.4倍?

原点がゼロになっていないが、ゼロにした

library(conflicted)
library(tidyverse)
library(ggrepel)
library(geomtextpath)
library(patchwork)

# データフレームを作成
# 月曜日から日曜日までの7日間, 各時刻
df_base <- expand_grid(
  days_of_week = c("月", "火", "水", "木", "金", "土", "日"),
  hours_of_day = 10:20
  ) 

n <- nrow(df_base)

# 水曜日は12時と17時以外の時間に、普段の平日より1.5倍の来客
# 休日は11:00 - 17:00 までまんべんなく多い
# 平日は12時と17時が多い
set.seed(0)
df_visitor_count <- tibble(
  days_of_week = factor(df_base$days_of_week, levels = c("月", "火", "水", "木", "金", "土", "日")),
  hours_of_day = df_base$hours_of_day,
  visitor_count = case_when(
    days_of_week == "水" & !(hours_of_day %in% c(12, 17)) ~ sample(50:80, 77, replace = TRUE), 
    days_of_week == "水" & hours_of_day %in% c(12, 17) ~ sample(20:50, 77, replace = TRUE) * 1.5,
    days_of_week %in% c("土", "日") & hours_of_day %in% 11:17 ~ sample(70:100, 77, replace = TRUE),
    days_of_week %in% c("土", "日") & !(hours_of_day %in% 11:17) ~ sample(30:60, 77, replace = TRUE),
    !(days_of_week %in% c("水", "土", "日")) & hours_of_day %in% c(12, 17) ~ sample(50:80, 77, replace = TRUE),
    !(days_of_week %in% c("水", "土", "日")) & !(hours_of_day %in% c(12, 17)) ~ sample(20:50, 77, replace = TRUE)
  )
)

# 折れ線グラフを描画
p1 <- df_visitor_count |>
  ggplot(aes(x=hours_of_day, y=visitor_count, group=days_of_week, color=days_of_week)) +
  scale_x_continuous(breaks = seq(10, 20, 1)) +
  coord_cartesian(ylim = c(0, 100)) +
  geom_line() +
  geom_point() +
  labs(x="時刻", y="来客数", color = "曜日", title = "凡例をまとめて表示した例") +
  theme(aspect.ratio = 1/2)

# 凡例を近くに表示した例(1) ggrepelの例(個別に位置設定)
p2 <- df_visitor_count |>
  ggplot(aes(x=hours_of_day, y=visitor_count, group=days_of_week, color=days_of_week)) +
  scale_x_continuous(breaks = seq(10, 20, 1)) +
  coord_cartesian(ylim = c(0, 100)) +
  geom_line() +
  geom_point() +
  geom_text_repel(
    data = data.frame(
      days_of_week =  c("月", "火", "水", "木", "金", "土", "日"),
      hours_of_day =  c(  14,   14,   20,   10.5,   14.1,   13,   16),
      visitor_count = c(  37.5,   48,   79,   50,   21,  91,   96)
    ),
    aes(label = days_of_week), size = 5
  ) +
  theme(legend.position = "none", aspect.ratio = 1/2) +
  labs(x="時刻", y="来客数", color = "曜日", title = "凡例を近くに表示した例(1)", subtitle = "ggrepel1")


# 凡例を近くに表示した例(2) ggrepelの例(終点に配置)
p3 <- df_visitor_count |>
  ggplot(aes(x=hours_of_day, y=visitor_count, group=days_of_week, color=days_of_week)) +
  scale_x_continuous(breaks = seq(10, 20, 1)) +
  coord_cartesian(ylim = c(0, 100)) +
  geom_line() +
  geom_point() +
  geom_text_repel(
    data = df_visitor_count |> slice_max(hours_of_day, n = 1),
    aes(label = days_of_week),
    nudge_x = 1,
    segment.alpha = 0.3,
    size = 5
  ) +
  theme(legend.position = "none", aspect.ratio = 1/2) +
  labs(x="時刻", y="来客数", color = "曜日", title = "凡例を近くに表示した例(2)", subtitle = "ggrepel2")


# 凡例を近くに表示した例(2) geomtextpathの例 おしゃれだが日本語が通らない
p4 <- df_visitor_count |>
  mutate(
    days_of_week_en = case_when(
      days_of_week == "月" ~ "Mon.",
      days_of_week == "火" ~ "Tue.",
      days_of_week == "水" ~ "Wed.",
      days_of_week == "木" ~ "Thu.",
      days_of_week == "金" ~ "Fri.",
      days_of_week == "土" ~ "Sat.",
      days_of_week == "日" ~ "Sun."
      )
    ) |>
  ggplot(aes(x=hours_of_day, y=visitor_count, group=days_of_week, color=days_of_week, label = days_of_week_en)) +
  geom_textline(size = 4, vjust = -0.5) +
  scale_x_continuous(breaks = seq(10, 20, 1)) +
  coord_cartesian(ylim = c(0, 100)) +
  geom_point() +
  theme(legend.position = "none", aspect.ratio = 1/2) +
  labs(x="時刻", y="来客数", color = "曜日", title = "凡例を近くに表示した例(3)", subtitle = "geomtextpath")

p1/p2/p3/p4

8.1.5 色を抑えて強調

library(conflicted)
library(tidyverse)

# データフレームを作成
# 月曜日から日曜日までの7日間, 各時刻
df_base <- expand_grid(
  days_of_week = c("月", "火", "水", "木", "金", "土", "日"),
  hours_of_day = 10:20
) 

n <- nrow(df_base)

# 水曜日は12時と17時以外の時間に、普段の平日より1.5倍の来客
# 休日は11:00 - 17:00 までまんべんなく多い
# 平日は12時と17時が多い
set.seed(0)
df_visitor_count <- tibble(
  days_of_week = factor(df_base$days_of_week, levels = c("月", "火", "水", "木", "金", "土", "日")),
  hours_of_day = df_base$hours_of_day,
  visitor_count = case_when(
    days_of_week == "水" & !(hours_of_day %in% c(12, 17)) ~ sample(50:80, 77, replace = TRUE),
    days_of_week == "水" & hours_of_day %in% c(12, 17) ~ sample(20:50, 77, replace = TRUE) * 1.5,
    days_of_week %in% c("土", "日") & hours_of_day %in% 11:17 ~ sample(70:100, 77, replace = TRUE),
    days_of_week %in% c("土", "日") & !(hours_of_day %in% 11:17) ~ sample(30:60, 77, replace = TRUE),
    !(days_of_week %in% c("水", "土", "日")) & hours_of_day %in% c(12, 17) ~ sample(50:80, 77, replace = TRUE),
    !(days_of_week %in% c("水", "土", "日")) & !(hours_of_day %in% c(12, 17)) ~ sample(20:50, 77, replace = TRUE)
  )
)

# 折れ線グラフを描画
days_of_week <- c("月", "火", "水", "木", "金", "土", "日")
df_visitor_count |>
  ggplot(aes(x = hours_of_day, y = visitor_count, group = days_of_week, color = days_of_week, linetype = days_of_week)) +
  geom_line() +
  geom_point() +
  scale_x_continuous(breaks = seq(10, 20, 1)) +
  coord_cartesian(ylim = c(0, 100)) +
  scale_color_manual(
    values = c(rep("black", 2), "#F8766D", rep("black", 4)),
    breaks = days_of_week
    ) +
  scale_linetype_manual(
    values = c(rep("solid", 5), rep("dashed", 2)),
    breaks = days_of_week
  ) +
  annotate("text", x = 13, y = 95, label="土日", size = 5, color = "black") +
  annotate("text", x = 20, y = 85, label="水", size = 5, color = "#F8766D") +
  annotate("text", x = 15, y = 15, label="その他の平日", size = 5, color = "black") +
  labs(x = "時刻", y = "来客数", title = "注目しているデータだけハイライト") +
  theme(legend.position = "none", aspect.ratio = 1/2)

8.1.6 図内に値を直接記入する

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

set.seed(5)

# 10変数、各時系列の長さはL=20でランダムデータを生成(正の値のみ)
# 乱数は0から1の範囲で生成されるため、それに50を(掛けて)足して負にならないようにする
df <- as.data.frame(
  matrix(runif(20 * 6) * 50, ncol = 6),
  make.names = FALSE
  )
names(df) <- LETTERS[1:6]

# 相関係数を計算
correlation_matrix <- df |>
  cor() |>
  as.data.frame() |>
  rownames_to_column()|>
  pivot_longer(!rowname)

# データフレームを準備
df_plot <- df |>
  pivot_longer(everything()) |>
  mutate(name = factor(name, levels =LETTERS[6:1]))

# 棒グラフを描画
p1 <- df_plot |>
  dplyr::filter(name == "A") |>
  ggplot(aes(y = value, x=1:20, label = round(value, 2))) +
  geom_col() +
  coord_cartesian(xlim = c(1, 10)) +
  theme(
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    aspect.ratio = 1
    )

# ヒートマップを描画
p2 <- correlation_matrix |>
  ggplot(aes(x = rowname, y = name, fill = value, label = round(value, 2))) +
  scale_fill_viridis_c(option = "turbo") + 
  geom_tile() +
  theme_minimal() +
  theme(
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    legend.title = element_blank(),
    aspect.ratio = 1
  )

# 数値入れる
p3 <- p1 +
  geom_text(nudge_y = 1, size = 2.5)

p4 <- p2 +
  geom_text(size = 3, aes(color = (value > 0.75 | value < -0.5))) +
  scale_color_manual(values = c("black", "white")) +
  guides(color = "none")

{p1 | p2} / {p3 | p4}

8.1.7 軸ラベルを説明的にする

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

data(iris)

base_p <- iris |>
  ggplot(aes(x = Petal.Length, y = Petal.Width, color = Species)) +
  geom_point() +
  theme(aspect.ratio = 1)

p1 <- base_p + labs(
    x = expression(paste(italic("L")[italic("p")])),
    y = expression(paste(italic("W")[italic("p")]))
    ) +
  theme(legend.position = "none") +
  labs(title = "軸ラベルがわかりにくい図")

p2 <- base_p +
  labs(
    x = expression(paste("花弁の長さ [cm], ", italic("L")[italic("p")])),
    y = expression(paste("花弁の幅 [cm], ", italic("W")[italic("p")]))
    ) +
  scale_color_hue(labels = c("setosa" = "セトサ", "versicolor" ="バージカラー", "virginica" ="バージニカ")) +
  theme(
    legend.position = c(0.2, 0.8),
    legend.title = element_blank()
    ) +
  labs(title = "軸ラベルをわかりやすくした図")

p1 + p2

8.1.8 パネルのレイアウトを考える

8.1.8.1 わかりにくいレイアウト

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

data(iris)

p1 <- iris |>
  dplyr::filter(Species == "setosa") |>
  ggplot(aes(x = Petal.Length, y = Petal.Width)) +
  geom_point() +
  labs(x = "花弁の長さ [cm]", y = "花弁の幅 [cm]", title = "セトサ (花弁長 vs 花弁幅)") +
  theme(aspect.ratio = 1)

p2 <- iris |>
  dplyr::filter(Species == "setosa") |>
  ggplot(aes(x = Sepal.Length, y = Petal.Length)) +
  geom_point() +
  labs(x = "がく片の長さ [cm]", y = "花弁の長さ [cm]", title = "セトサ (がく片長さ vs 花弁長)") +
  theme(aspect.ratio = 1)

p3 <- iris |>
  dplyr::filter(Species == "versicolor") |>
  ggplot(aes(x = Petal.Length, y = Petal.Width)) +
  geom_point() +
  labs(x = "花弁の長さ [cm]", y = "花弁の幅 [cm]", title = "バージカラー (花弁長 vs 花弁幅)") +
  theme(aspect.ratio = 1)

p4 <-  iris |>
  dplyr::filter(Species == "versicolor") |>
  ggplot(aes(x = Sepal.Length, y = Petal.Length)) +
  geom_point() +
  labs(x = "がく片の長さ [cm]", y = "花弁の長さ [cm]", title = "バージカラー (がく片長さ vs 花弁長)") +
  theme(aspect.ratio = 1)

p5 <- iris |>
  dplyr::filter(Species == "virginica") |>
  ggplot(aes(x = Petal.Length, y = Petal.Width)) +
  geom_point() +
  labs(x = "花弁の長さ [cm]", y = "花弁の幅 [cm]", title = "バージニカ (花弁長 vs 花弁幅)") +
  theme(aspect.ratio = 1)

p6 <-  iris |>
  dplyr::filter(Species == "virginica") |>
  ggplot(aes(x = Sepal.Length, y = Petal.Length)) +
  geom_point() +
  labs(x = "がく片の長さ [cm]", y = "花弁の長さ [cm]", title = "バージニカ (がく片長さ vs 花弁長)") +
  theme(aspect.ratio = 1)

{p1 | p2 | p3} / {p4 | p5 | p6}

8.1.8.2 わかりやすいレイアウト

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

data(iris)

plot_iris <- iris |>
  mutate(
    Species = case_when(
      Species == "setosa" ~ "セトサ",
      Species == "versicolor" ~ "バージカラー",
      Species == "virginica" ~ "バージニカ"
      )
    )

p1 <- plot_iris |>
  ggplot(aes(x = Petal.Length, y = Petal.Width, color = Species)) +
  geom_point() +
  labs(x = "花弁の長さ [cm]", y = "花弁の幅 [cm]") +
  theme(legend.position = "none", aspect.ratio = 1) +
  facet_wrap(vars(Species), scales = "free")
p2 <- plot_iris |>
  ggplot(aes(x = Petal.Length, y = Sepal.Length, color = Species)) +
  geom_point() +
  labs(x = "花弁の長さ [cm]", y = "がく片の長さ [cm]") +
  theme(legend.position = "none", aspect.ratio = 1) +
  facet_wrap(vars(Species), scales = "free")


p1 / p2

これについては、スケールを揃えたほうが誤解が無いと思う。

こんな風に。

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

data(iris)

plot_iris <- iris |>
  mutate(
    Species = case_when(
      Species == "setosa" ~ "セトサ",
      Species == "versicolor" ~ "バージカラー",
      Species == "virginica" ~ "バージニカ"
    )
  )

p1 <- plot_iris |>
  ggplot(aes(x = Petal.Length, y = Petal.Width, color = Species)) +
  geom_point() +
  labs(x = "花弁の長さ [cm]", y = "花弁の幅 [cm]") +
  theme(legend.position = "none", aspect.ratio = 1) +
  facet_wrap(vars(Species))
p2 <- plot_iris |>
  ggplot(aes(x = Petal.Length, y = Sepal.Length, color = Species)) +
  geom_point() +
  labs(x = "花弁の長さ [cm]", y = "がく片の長さ [cm]") +
  theme(legend.position = "none", aspect.ratio = 1) +
  facet_wrap(vars(Species))


p1 / p2

8.2 指標化から可視化の戦略を考える

8.2.4 外れ値・異常値を指標化してしまうと……

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

n <- 20
set.seed(0)
samples <- purrr::map2(
  c(10, 15, 12, 20), #mean
  c(5, 5, 5, 5),     #sd
  \(x, y) rnorm(n, x, y)
  )

# サンプルAに外れ値を追加
samples[[1]][1] <- 100

names(samples) <- LETTERS[1:4]

# データフレームを作成
df <- samples |>
  as.data.frame() |>
  pivot_longer(everything())

# スウォームプロット
p1 <- df |>
  ggplot(aes(x = name, y = value, color = name)) +
  geom_quasirandom() +
  theme(
    legend.position = "none",
    axis.title = element_blank(),
    aspect.ratio = 1
  ) + 
  labs(title = "元となるデータ")

# 棒グラフ(平均値)
p2 <- df |>
  summarise(mean = mean(value), .by = name) |>
  ggplot(aes(x = name, y = mean, fill = name)) +
  geom_col() +
  theme(
    legend.position = "none",
    axis.title = element_blank(),
    aspect.ratio = 1
  ) + 
  labs(title = "指標化したもの(平均)")


p1 + p2

8.3.2 ばらつき度合いと特徴の強さ

タイトルの斜体や下付き文字とオブジェクトが同居できない

教えていただいてできました!

library(conflicted)
library(tidyverse)
library(ggbeeswarm)
library(broom)
library(scales) #muted()
library(patchwork)

# データの生成
set.seed(2)
samples <- purrr::pmap(
  list(
    n = c(20, 20, 400, 400),
    mean = c(6, 6, 6, 5.75),
    sd = c(2, 2, 2, 2)
  ),
  \(n, mean, sd) rnorm(n, mean, sd)
)

names(samples) <- c("v11", "v12", "v21", "v22")

# t検定
t_test1 <- tidy(t.test(samples$v11, samples$v12))
t_test2 <- tidy(t.test(samples$v21, samples$v22))

# データの整形
data1 <- data.frame(
  Group = rep(c("Group 1", "Group 2"), each = 20),
  Value = c(samples$v11, samples$v12)
  )
data1_mean <- data1 |>
  summarise(mean = mean(Value), .by = Group)

data2 <- data.frame(
  Group = rep(c("Group 1", "Group 2"), each = 400),
  Value = c(samples$v21, samples$v22)
  )

data2_mean <- data2 |>
  summarise(mean = mean(Value), .by = Group)

p1 <- ggplot() +
  geom_col(data = data1_mean, aes(x = Group, y = mean, fill = Group )) +
  geom_quasirandom(data = data1, aes(x = Group, y = Value, color = Group)) +
  scale_fill_manual(values = c("#CAB2D6", "#B2DF8A")) +
  scale_color_manual(values = c("#6A3D9A", "#33A02C")) + 
  coord_cartesian(ylim = c(0, 12)) +
  labs(
    title = "標本平均の差は大きいが……?", 
    subtitle = bquote(italic(t)[20] == .(round(t_test1$statistic, 2)) ~ ", p-value = " ~ .(round(t_test1$p.value, 4)))
 #   subtitle = expression(paste({italic(t)[20]}, " = ", round(t_test1$statistic, 2), ", p-value = ", round(t_test1$p.value, 4)))
#    subtitle = paste("t20 = ", round(t_test1$statistic, 2), ", p-value = ", round(t_test1$p.value, 4))

    ) +
  theme(legend.position = "none", axis.title = element_blank()) 

test <- expression({italic(t)[400]})
p2 <- ggplot() +
  geom_col(data = data2_mean, aes(x = Group, y = mean, fill = Group )) +
  geom_quasirandom(data = data2, aes(x = Group, y = Value, color = Group)) +
  scale_fill_manual(values = c("#CAB2D6", "#B2DF8A")) +
  scale_color_manual(values = c("#6A3D9A", "#33A02C")) +
  coord_cartesian(ylim = c(0, 12)) +
  labs(
    title = "標本平均の差は小さいが……?",
    subtitle = bquote(italic(t)[400] == .(round(t_test1$statistic, 2)) ~ ", p-value = " ~ .(round(t_test2$p.value, 4)))
  #  subtitle = paste("t400 = ", round(t_test2$statistic, 2), ", p-value = ", round(t_test2$p.value, 4))
    ) +
  theme(legend.position = "none", axis.title = element_blank()) 

p1 + p2

第8章ここまで

LS0tCnRpdGxlOiAi56ysOOeroCDjg4fjg7zjgr/mjIfmqJnljJbjg7vlj6/oppbljJbjga7jg5fjg63jgrvjgrkiCmF1dGhvcjogIk9zYW11LCBNT1JJTU9UTyIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICB0aGVtZTogdW5pdGVkICAgIAogICAgbWRfZXh0ZW5zaW9uczogIi1hc2NpaV9pZGVudGlmaWVycyIKICAgIHRvY19mbG9hdDogeWVzCiAgICBmaWdfd2lkdGg6IDcuNQogICAgZmlnX2hlaWdodDogNS42MjUKICAgIGRldjogcmFnZ19wbmcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgrlm7Pjga7lj7PkuIrjga5gc2hvd2Djg5zjgr/jg7PjgpLmirzjgZnjgahS44Gu44Kz44O844OJ44GM6KGo56S644GV44KM44G+44GZ44CCCgojIyA4LjEg5Yq55p6c55qE44Gq5Y+v6KaW5YyW44Gu44OG44Kv44OL44OD44KvCgojIyMgOC4xLjEg6KaL44Gl44KJ44GE5Zuz44Go6KaL44KE44GZ44GE5ZuzCgpgYGB7ciBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGF0Y2h3b3JrKQoKYmFzZV9wbG90IDwtIHRpYmJsZSgKICB4ID0gc2VxKDAsIDEwLCBsZW5ndGgub3V0ID0gMTAwKSwKICB5MSA9IHNpbih4KSwKICB5MiA9IGNvcyh4KSwKICB5MyA9IHkxICsgeTIKICApIHw+CiAgcGl2b3RfbG9uZ2VyKCF4LCBuYW1lc190byA9ICJ5IikgfD4KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0gdmFsdWUsIGNvbG9yID0geSwgbGluZXR5cGUgPSB5KSkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwICwxMCksIHlsaW0gPSBjKC0zLCAzKSkgKwogIHNjYWxlX2NvbG9yX2h1ZShuYW1lID0gIiIsIGxhYmVscyA9IGMoeTEgPSAieSA9IHNpbih4KSIsIHkyID0ieSA9IGNvcyh4KSIsIHkzID0ieSA9IHNpbih4KSArIGNvcyh4KSIpKSArCiAgc2NhbGVfbGluZXR5cGVfZGlzY3JldGUobmFtZSA9ICIiLCBsYWJlbHMgPSBjKHkxID0gInkgPSBzaW4oeCkiLCB5MiA9InkgPSBjb3MoeCkiLCB5MyA9InkgPSBzaW4oeCkgKyBjb3MoeCkiKSkgKwogIHRoZW1lKAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjc1LCAwLjg1KSwKICAgIGFzcGVjdC5yYXRpbyA9IDEKICAgICkKCiMg6KaL44Gl44KJ44GE5ZuzCnAxIDwtIGJhc2VfcGxvdCArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAwLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwLCBieSA9IDAuNSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0zLCAzLCBieSA9IDAuMikpICsKICBsYWJzKHggPSAieC1heGlzIGxhYmVsLCB4IiwgeSA9ICJ5LWF4aXMgbGFiZWwsIHkiLCB0aXRsZSA9ICLopovjgaXjgonjgYTjgrDjg6njg5UiKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA2LCBmYW1pbHkgPSAiVGltZXMgTmV3IFJvbWFuIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYsIGZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LCBmYW1pbHkgPSAiVGltZXMgTmV3IFJvbWFuIikKICAgICkKCiMg6KaL44KE44GZ44GE5ZuzCnAyIDwtIGJhc2VfcGxvdCArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAxKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMCwgYnkgPSAyKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTMsIDMsIGJ5ID0gMSkpICsKICBsYWJzKHggPSAieC1heGlzIGxhYmVsLCB4IiwgeSA9ICJ5LWF4aXMgbGFiZWwsIHkiLCB0aXRsZSA9ICLopovjgoTjgZnjgYTjgrDjg6njg5UiKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIkFyaWFsIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYW1pbHkgPSAiQXJpYWwiKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFtaWx5ID0gIkFyaWFsIikKICApCiAgCnAxICsgcDIKYGBgCgoKIyMjIyA4LjEuMiDjgrDjg6njg5Xjga7nuKbmqKrmr5Tjgajou7jjga7nr4Tlm7IKCmBgYHtyIGZpZy5oZWlnaHQ9MTAuNSwgZmlnLndpZHRoPTcuNX0KbGlicmFyeShjb25mbGljdGVkKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCiMg44OH44O844K/44Gu5a6a576pCmRmIDwtIGRhdGEuZnJhbWUoCiAgeCA9IGMoMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTApLAogIHkxID0gYygxMSwgMTEuMiwgMTEuNSwgMTIsIDEyLjIsIDEzLCAxNC4yLCAxNC41LCAxNSwgMTUuNiwgMTYpLAogIHkyID0gYygxMS4xLCAxMS4zLCAxMS40LCAxMS45LCAxMi4xLCAxMi44LCAxNC4wLCAxNC4yLCAxNC43LCAxNS4wLCAxNS41KQogICkgfD4KICBwaXZvdF9sb25nZXIoIXgsIG5hbWVzX3RvID0gInkiKQoKIyDjgrDjg6njg5UKcDEgPC0gZGYgfD4KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0gdmFsdWUsIGNvbG9yID0geSwgc2hhcGUgPSB5KSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeCA9ICJ4IiwgeSA9ICJ5IiwgdGl0bGUgPSAi5Z+65rqW44Go44GZ44KL5o+P55S75L6LIikgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjEsIDAuOCkpCgpwMiA8LSBkZiB8PgogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB2YWx1ZSwgY29sb3IgPSB5LCBzaGFwZSA9IHkpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4ID0gIngiLCB5ID0gInkiLCB0aXRsZSA9ICLnuKbou7jnr4Tlm7LluoPjgZLjgZnjgY7vvJ8iKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIDMwKSkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjEsIDAuOCkpCgpwMyA8LSBkZiB8PgogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB2YWx1ZSwgY29sb3IgPSB5LCBzaGFwZSA9IHkpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4ID0gIngiLCB5ID0gInkiLCB0aXRsZSA9ICLnuKbou7jmlrnlkJHjgpLlvLfoqr8iKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMiwgMC45KSkKCnA0IDwtIGRmIHw+CiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHZhbHVlLCBjb2xvciA9IHksIHNoYXBlID0geSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAieCIsIHkgPSAieSIsIHRpdGxlID0gIuaoqui7uOaWueWQkeOCkuW8t+iqvyIpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4xLCAwLjgpKQoKZGVzaWduIDwtICIKICAxMTMKICAyMjMKICA0NDQKIgoKcDEgKyBwMiArIHAzICsgcDQgKyBwbG90X2xheW91dChkZXNpZ24gPSBkZXNpZ24pCmBgYAoKCiMjIyA4LjEuMyDniYflr77mlbDjgrDjg6njg5XjgpLliKnnlKjjgZnjgosKCmBgYHtyIGZpZy5oZWlnaHQ9Ny41LCBmaWcud2lkdGg9Ny41LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHpvbykKbGlicmFyeShzY2FsZXMpCgojIOWKoOW3peWJjeOBruODh+ODvOOCv+OBr+OBk+OBoeOCieOBq+OBguOCiuOBvuOBmeOAggojIGh0dHBzOi8vY292aWQxOS53aG8uaW50L1dITy1DT1ZJRC0xOS1nbG9iYWwtZGF0YS5jc3YKCiMg44OV44Kh44Kk44Or44KS6Kqt44G/6L6844KACiMg5pel5pys44CB44Ki44Oh44Oq44Kr44CB5Lit5Zu944Gu44OH44O844K/44KS5oqc44GN5Ye644GZCiMgRGF0ZV9yZXBvcnRlZOOBr+aXpeS7mOWei+OBqwojIDE05pel6ZaT44Gu56e75YuV5bmz5Z2H44KS6KiI566XCmRmIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vdGtFemFraS9kYXRhX3Zpc3VhbGl6YXRpb24vbWFpbi84JUU3JUFCJUEwL2RhdGEvY292aWRfZGF0YV9kdW1teS5jc3YiKSB8PgogIGRwbHlyOjpmaWx0ZXIoQ291bnRyeSAlaW4lIGMoIkphcGFuIiwgIlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSIsICJDaGluYSIpKSB8PgogIG11dGF0ZSgKICAgIERhdGVfcmVwb3J0ZWQgPSBhcy5EYXRlKERhdGVfcmVwb3J0ZWQpLAogICAgYDE0X2RheV9hdmdgID0gcm9sbG1lYW4oTmV3X2Nhc2VzLCAxNCwgZmlsbCA9IE5BKSwKICAgIC5ieSA9IENvdW50cnkKICAgICkgfD4KICBtdXRhdGUoQ291bnRyeSA9IGZhY3RvcihDb3VudHJ5LCBsZXZlbHMgPSBjKCJKYXBhbiIsICJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiLCAiQ2hpbmEiKSkpCgoKIyDpgJrluLjjga7nuKbou7gKcDEgPC0gZGYgfD4KICBnZ3Bsb3QoYWVzKHggPSBEYXRlX3JlcG9ydGVkKSkgKwogIGdlb21fbGluZShhZXMoeSA9IE5ld19jYXNlcywgY29sb3IgPSBDb3VudHJ5KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9jb21tYSgpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgaGp1c3QgPSAxKSkgKwogIGxhYnMoeCA9ICIiLCB5ID0gIuaWsOimj+aEn+afk+iAheaVsCIsIHRpdGxlID0gIue4pui7uOOCkuOBneOBruOBvuOBvuODl+ODreODg+ODiOOBl+OBn+OCguOBriIpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yLCAwLjgpLCBhc3BlY3QucmF0aW8gPSAxLzIpCgojIOWvvuaVsOe4pui7uApwMiA8LSBkZiB8PgogIGdncGxvdChhZXMoeCA9IERhdGVfcmVwb3J0ZWQpKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gTmV3X2Nhc2VzLCBjb2xvciA9IENvdW50cnkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbGFiZWxzID0gbGFiZWxfY29tbWEoKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0gMSkpICsKICBsYWJzKHggPSAiIiwgeSA9ICLmlrDopo/mhJ/mn5PogIXmlbAiLCB0aXRsZSA9ICLnuKbou7jjgpLlr77mlbDjgafjg5fjg63jg4Pjg4jjgZfjgZ/jgoLjga4iKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgYXNwZWN0LnJhdGlvID0gMS8yKQoKcDEgLyBwMgoKYGBgCgoKIyMjIDguMS40IOWHoeS+i+OCkui/keOBj+OBq+e9ruOBjwoK44Kz44Oh44Oz44OI44Gv44CM5pmu5q6144Gu5bmz5pel44KI44KKMS415YCN44Gu5p2l5a6i44CN44Go44Gq44Gj44Gm44GE44KL44GM44Kz44O844OJ44GvMS405YCN77yfCgrljp/ngrnjgYzjgrzjg63jgavjgarjgaPjgabjgYTjgarjgYTjgYzjgIHjgrzjg63jgavjgZfjgZ8KCmBgYHtyIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD03LjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShnZW9tdGV4dHBhdGgpCmxpYnJhcnkocGF0Y2h3b3JrKQoKIyDjg4fjg7zjgr/jg5Xjg6zjg7zjg6DjgpLkvZzmiJAKIyDmnIjmm5zml6XjgYvjgonml6Xmm5zml6Xjgb7jgafjga435pel6ZaTLCDlkITmmYLliLsKZGZfYmFzZSA8LSBleHBhbmRfZ3JpZCgKICBkYXlzX29mX3dlZWsgPSBjKCLmnIgiLCAi54GrIiwgIuawtCIsICLmnKgiLCAi6YeRIiwgIuWcnyIsICLml6UiKSwKICBob3Vyc19vZl9kYXkgPSAxMDoyMAogICkgCgpuIDwtIG5yb3coZGZfYmFzZSkKCiMg5rC05puc5pel44GvMTLmmYLjgagxN+aZguS7peWkluOBruaZgumWk+OBq+OAgeaZruauteOBruW5s+aXpeOCiOOCijEuNeWAjeOBruadpeWuogojIOS8keaXpeOBrzExOjAwIC0gMTc6MDAg44G+44Gn44G+44KT44G544KT44Gq44GP5aSa44GECiMg5bmz5pel44GvMTLmmYLjgagxN+aZguOBjOWkmuOBhApzZXQuc2VlZCgwKQpkZl92aXNpdG9yX2NvdW50IDwtIHRpYmJsZSgKICBkYXlzX29mX3dlZWsgPSBmYWN0b3IoZGZfYmFzZSRkYXlzX29mX3dlZWssIGxldmVscyA9IGMoIuaciCIsICLngasiLCAi5rC0IiwgIuacqCIsICLph5EiLCAi5ZyfIiwgIuaXpSIpKSwKICBob3Vyc19vZl9kYXkgPSBkZl9iYXNlJGhvdXJzX29mX2RheSwKICB2aXNpdG9yX2NvdW50ID0gY2FzZV93aGVuKAogICAgZGF5c19vZl93ZWVrID09ICLmsLQiICYgIShob3Vyc19vZl9kYXkgJWluJSBjKDEyLCAxNykpIH4gc2FtcGxlKDUwOjgwLCA3NywgcmVwbGFjZSA9IFRSVUUpLCAKICAgIGRheXNfb2Zfd2VlayA9PSAi5rC0IiAmIGhvdXJzX29mX2RheSAlaW4lIGMoMTIsIDE3KSB+IHNhbXBsZSgyMDo1MCwgNzcsIHJlcGxhY2UgPSBUUlVFKSAqIDEuNSwKICAgIGRheXNfb2Zfd2VlayAlaW4lIGMoIuWcnyIsICLml6UiKSAmIGhvdXJzX29mX2RheSAlaW4lIDExOjE3IH4gc2FtcGxlKDcwOjEwMCwgNzcsIHJlcGxhY2UgPSBUUlVFKSwKICAgIGRheXNfb2Zfd2VlayAlaW4lIGMoIuWcnyIsICLml6UiKSAmICEoaG91cnNfb2ZfZGF5ICVpbiUgMTE6MTcpIH4gc2FtcGxlKDMwOjYwLCA3NywgcmVwbGFjZSA9IFRSVUUpLAogICAgIShkYXlzX29mX3dlZWsgJWluJSBjKCLmsLQiLCAi5ZyfIiwgIuaXpSIpKSAmIGhvdXJzX29mX2RheSAlaW4lIGMoMTIsIDE3KSB+IHNhbXBsZSg1MDo4MCwgNzcsIHJlcGxhY2UgPSBUUlVFKSwKICAgICEoZGF5c19vZl93ZWVrICVpbiUgYygi5rC0IiwgIuWcnyIsICLml6UiKSkgJiAhKGhvdXJzX29mX2RheSAlaW4lIGMoMTIsIDE3KSkgfiBzYW1wbGUoMjA6NTAsIDc3LCByZXBsYWNlID0gVFJVRSkKICApCikKCiMg5oqY44KM57ea44Kw44Op44OV44KS5o+P55S7CnAxIDwtIGRmX3Zpc2l0b3JfY291bnQgfD4KICBnZ3Bsb3QoYWVzKHg9aG91cnNfb2ZfZGF5LCB5PXZpc2l0b3JfY291bnQsIGdyb3VwPWRheXNfb2Zfd2VlaywgY29sb3I9ZGF5c19vZl93ZWVrKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAsIDIwLCAxKSkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMDApKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSLmmYLliLsiLCB5PSLmnaXlrqLmlbAiLCBjb2xvciA9ICLmm5zml6UiLCB0aXRsZSA9ICLlh6HkvovjgpLjgb7jgajjgoHjgabooajnpLrjgZfjgZ/kvosiKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMS8yKQoKIyDlh6HkvovjgpLov5HjgY/jgavooajnpLrjgZfjgZ/kvosoMSkgZ2dyZXBlbOOBruS+i++8iOWAi+WIpeOBq+S9jee9ruioreWumu+8iQpwMiA8LSBkZl92aXNpdG9yX2NvdW50IHw+CiAgZ2dwbG90KGFlcyh4PWhvdXJzX29mX2RheSwgeT12aXNpdG9yX2NvdW50LCBncm91cD1kYXlzX29mX3dlZWssIGNvbG9yPWRheXNfb2Zfd2VlaykpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwLCAyMCwgMSkpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTAwKSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdGV4dF9yZXBlbCgKICAgIGRhdGEgPSBkYXRhLmZyYW1lKAogICAgICBkYXlzX29mX3dlZWsgPSAgYygi5pyIIiwgIueBqyIsICLmsLQiLCAi5pyoIiwgIumHkSIsICLlnJ8iLCAi5pelIiksCiAgICAgIGhvdXJzX29mX2RheSA9ICBjKCAgMTQsICAgMTQsICAgMjAsICAgMTAuNSwgICAxNC4xLCAgIDEzLCAgIDE2KSwKICAgICAgdmlzaXRvcl9jb3VudCA9IGMoICAzNy41LCAgIDQ4LCAgIDc5LCAgIDUwLCAgIDIxLCAgOTEsICAgOTYpCiAgICApLAogICAgYWVzKGxhYmVsID0gZGF5c19vZl93ZWVrKSwgc2l6ZSA9IDUKICApICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGFzcGVjdC5yYXRpbyA9IDEvMikgKwogIGxhYnMoeD0i5pmC5Yi7IiwgeT0i5p2l5a6i5pWwIiwgY29sb3IgPSAi5puc5pelIiwgdGl0bGUgPSAi5Yeh5L6L44KS6L+R44GP44Gr6KGo56S644GX44Gf5L6LKDEpIiwgc3VidGl0bGUgPSAiZ2dyZXBlbDEiKQoKCiMg5Yeh5L6L44KS6L+R44GP44Gr6KGo56S644GX44Gf5L6LKDIpIGdncmVwZWzjga7kvovvvIjntYLngrnjgavphY3nva7vvIkKcDMgPC0gZGZfdmlzaXRvcl9jb3VudCB8PgogIGdncGxvdChhZXMoeD1ob3Vyc19vZl9kYXksIHk9dmlzaXRvcl9jb3VudCwgZ3JvdXA9ZGF5c19vZl93ZWVrLCBjb2xvcj1kYXlzX29mX3dlZWspKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMCwgMjAsIDEpKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIDEwMCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3RleHRfcmVwZWwoCiAgICBkYXRhID0gZGZfdmlzaXRvcl9jb3VudCB8PiBzbGljZV9tYXgoaG91cnNfb2ZfZGF5LCBuID0gMSksCiAgICBhZXMobGFiZWwgPSBkYXlzX29mX3dlZWspLAogICAgbnVkZ2VfeCA9IDEsCiAgICBzZWdtZW50LmFscGhhID0gMC4zLAogICAgc2l6ZSA9IDUKICApICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGFzcGVjdC5yYXRpbyA9IDEvMikgKwogIGxhYnMoeD0i5pmC5Yi7IiwgeT0i5p2l5a6i5pWwIiwgY29sb3IgPSAi5puc5pelIiwgdGl0bGUgPSAi5Yeh5L6L44KS6L+R44GP44Gr6KGo56S644GX44Gf5L6LKDIpIiwgc3VidGl0bGUgPSAiZ2dyZXBlbDIiKQoKCiMg5Yeh5L6L44KS6L+R44GP44Gr6KGo56S644GX44Gf5L6LKDIpIGdlb210ZXh0cGF0aOOBruS+iyDjgYrjgZfjgoPjgozjgaDjgYzml6XmnKzoqp7jgYzpgJrjgonjgarjgYQKcDQgPC0gZGZfdmlzaXRvcl9jb3VudCB8PgogIG11dGF0ZSgKICAgIGRheXNfb2Zfd2Vla19lbiA9IGNhc2Vfd2hlbigKICAgICAgZGF5c19vZl93ZWVrID09ICLmnIgiIH4gIk1vbi4iLAogICAgICBkYXlzX29mX3dlZWsgPT0gIueBqyIgfiAiVHVlLiIsCiAgICAgIGRheXNfb2Zfd2VlayA9PSAi5rC0IiB+ICJXZWQuIiwKICAgICAgZGF5c19vZl93ZWVrID09ICLmnKgiIH4gIlRodS4iLAogICAgICBkYXlzX29mX3dlZWsgPT0gIumHkSIgfiAiRnJpLiIsCiAgICAgIGRheXNfb2Zfd2VlayA9PSAi5ZyfIiB+ICJTYXQuIiwKICAgICAgZGF5c19vZl93ZWVrID09ICLml6UiIH4gIlN1bi4iCiAgICAgICkKICAgICkgfD4KICBnZ3Bsb3QoYWVzKHg9aG91cnNfb2ZfZGF5LCB5PXZpc2l0b3JfY291bnQsIGdyb3VwPWRheXNfb2Zfd2VlaywgY29sb3I9ZGF5c19vZl93ZWVrLCBsYWJlbCA9IGRheXNfb2Zfd2Vla19lbikpICsKICBnZW9tX3RleHRsaW5lKHNpemUgPSA0LCB2anVzdCA9IC0wLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwLCAyMCwgMSkpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTAwKSkgKwogIGdlb21fcG9pbnQoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBhc3BlY3QucmF0aW8gPSAxLzIpICsKICBsYWJzKHg9IuaZguWIuyIsIHk9IuadpeWuouaVsCIsIGNvbG9yID0gIuabnOaXpSIsIHRpdGxlID0gIuWHoeS+i+OCkui/keOBj+OBq+ihqOekuuOBl+OBn+S+iygzKSIsIHN1YnRpdGxlID0gImdlb210ZXh0cGF0aCIpCgpwMS9wMi9wMy9wNApgYGAKCgojIyMgOC4xLjUg6Imy44KS5oqR44GI44Gm5by36Kq/CgpgYGB7cn0KbGlicmFyeShjb25mbGljdGVkKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCiMg44OH44O844K/44OV44Os44O844Og44KS5L2c5oiQCiMg5pyI5puc5pel44GL44KJ5pel5puc5pel44G+44Gn44GuN+aXpemWkywg5ZCE5pmC5Yi7CmRmX2Jhc2UgPC0gZXhwYW5kX2dyaWQoCiAgZGF5c19vZl93ZWVrID0gYygi5pyIIiwgIueBqyIsICLmsLQiLCAi5pyoIiwgIumHkSIsICLlnJ8iLCAi5pelIiksCiAgaG91cnNfb2ZfZGF5ID0gMTA6MjAKKSAKCm4gPC0gbnJvdyhkZl9iYXNlKQoKIyDmsLTmm5zml6Xjga8xMuaZguOBqDE35pmC5Lul5aSW44Gu5pmC6ZaT44Gr44CB5pmu5q6144Gu5bmz5pel44KI44KKMS415YCN44Gu5p2l5a6iCiMg5LyR5pel44GvMTE6MDAgLSAxNzowMCDjgb7jgafjgb7jgpPjgbnjgpPjgarjgY/lpJrjgYQKIyDlubPml6Xjga8xMuaZguOBqDE35pmC44GM5aSa44GECnNldC5zZWVkKDApCmRmX3Zpc2l0b3JfY291bnQgPC0gdGliYmxlKAogIGRheXNfb2Zfd2VlayA9IGZhY3RvcihkZl9iYXNlJGRheXNfb2Zfd2VlaywgbGV2ZWxzID0gYygi5pyIIiwgIueBqyIsICLmsLQiLCAi5pyoIiwgIumHkSIsICLlnJ8iLCAi5pelIikpLAogIGhvdXJzX29mX2RheSA9IGRmX2Jhc2UkaG91cnNfb2ZfZGF5LAogIHZpc2l0b3JfY291bnQgPSBjYXNlX3doZW4oCiAgICBkYXlzX29mX3dlZWsgPT0gIuawtCIgJiAhKGhvdXJzX29mX2RheSAlaW4lIGMoMTIsIDE3KSkgfiBzYW1wbGUoNTA6ODAsIDc3LCByZXBsYWNlID0gVFJVRSksCiAgICBkYXlzX29mX3dlZWsgPT0gIuawtCIgJiBob3Vyc19vZl9kYXkgJWluJSBjKDEyLCAxNykgfiBzYW1wbGUoMjA6NTAsIDc3LCByZXBsYWNlID0gVFJVRSkgKiAxLjUsCiAgICBkYXlzX29mX3dlZWsgJWluJSBjKCLlnJ8iLCAi5pelIikgJiBob3Vyc19vZl9kYXkgJWluJSAxMToxNyB+IHNhbXBsZSg3MDoxMDAsIDc3LCByZXBsYWNlID0gVFJVRSksCiAgICBkYXlzX29mX3dlZWsgJWluJSBjKCLlnJ8iLCAi5pelIikgJiAhKGhvdXJzX29mX2RheSAlaW4lIDExOjE3KSB+IHNhbXBsZSgzMDo2MCwgNzcsIHJlcGxhY2UgPSBUUlVFKSwKICAgICEoZGF5c19vZl93ZWVrICVpbiUgYygi5rC0IiwgIuWcnyIsICLml6UiKSkgJiBob3Vyc19vZl9kYXkgJWluJSBjKDEyLCAxNykgfiBzYW1wbGUoNTA6ODAsIDc3LCByZXBsYWNlID0gVFJVRSksCiAgICAhKGRheXNfb2Zfd2VlayAlaW4lIGMoIuawtCIsICLlnJ8iLCAi5pelIikpICYgIShob3Vyc19vZl9kYXkgJWluJSBjKDEyLCAxNykpIH4gc2FtcGxlKDIwOjUwLCA3NywgcmVwbGFjZSA9IFRSVUUpCiAgKQopCgojIOaKmOOCjOe3muOCsOODqeODleOCkuaPj+eUuwpkYXlzX29mX3dlZWsgPC0gYygi5pyIIiwgIueBqyIsICLmsLQiLCAi5pyoIiwgIumHkSIsICLlnJ8iLCAi5pelIikKZGZfdmlzaXRvcl9jb3VudCB8PgogIGdncGxvdChhZXMoeCA9IGhvdXJzX29mX2RheSwgeSA9IHZpc2l0b3JfY291bnQsIGdyb3VwID0gZGF5c19vZl93ZWVrLCBjb2xvciA9IGRheXNfb2Zfd2VlaywgbGluZXR5cGUgPSBkYXlzX29mX3dlZWspKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMCwgMjAsIDEpKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIDEwMCkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKHJlcCgiYmxhY2siLCAyKSwgIiNGODc2NkQiLCByZXAoImJsYWNrIiwgNCkpLAogICAgYnJlYWtzID0gZGF5c19vZl93ZWVrCiAgICApICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKHJlcCgic29saWQiLCA1KSwgcmVwKCJkYXNoZWQiLCAyKSksCiAgICBicmVha3MgPSBkYXlzX29mX3dlZWsKICApICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxMywgeSA9IDk1LCBsYWJlbD0i5Zyf5pelIiwgc2l6ZSA9IDUsIGNvbG9yID0gImJsYWNrIikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIwLCB5ID0gODUsIGxhYmVsPSLmsLQiLCBzaXplID0gNSwgY29sb3IgPSAiI0Y4NzY2RCIpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxNSwgeSA9IDE1LCBsYWJlbD0i44Gd44Gu5LuW44Gu5bmz5pelIiwgc2l6ZSA9IDUsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnMoeCA9ICLmmYLliLsiLCB5ID0gIuadpeWuouaVsCIsIHRpdGxlID0gIuazqOebruOBl+OBpuOBhOOCi+ODh+ODvOOCv+OBoOOBkeODj+OCpOODqeOCpOODiCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGFzcGVjdC5yYXRpbyA9IDEvMikKYGBgCgoKIyMjIDguMS42IOWbs+WGheOBq+WApOOCkuebtOaOpeiomOWFpeOBmeOCiwoKYGBge3IgZmlnLndpZHRoPTcuNX0KbGlicmFyeShjb25mbGljdGVkKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShwYXRjaHdvcmspCgpzZXQuc2VlZCg1KQoKIyAxMOWkieaVsOOAgeWQhOaZguezu+WIl+OBrumVt+OBleOBr0w9MjDjgafjg6njg7Pjg4Djg6Djg4fjg7zjgr/jgpLnlJ/miJDvvIjmraPjga7lgKTjga7jgb/vvIkKIyDkubHmlbDjga8w44GL44KJMeOBruevhOWbsuOBp+eUn+aIkOOBleOCjOOCi+OBn+OCgeOAgeOBneOCjOOBqzUw44KS77yI5o6b44GR44Gm77yJ6Laz44GX44Gm6LKg44Gr44Gq44KJ44Gq44GE44KI44GG44Gr44GZ44KLCmRmIDwtIGFzLmRhdGEuZnJhbWUoCiAgbWF0cml4KHJ1bmlmKDIwICogNikgKiA1MCwgbmNvbCA9IDYpLAogIG1ha2UubmFtZXMgPSBGQUxTRQogICkKbmFtZXMoZGYpIDwtIExFVFRFUlNbMTo2XQoKIyDnm7jplqLkv4LmlbDjgpLoqIjnrpcKY29ycmVsYXRpb25fbWF0cml4IDwtIGRmIHw+CiAgY29yKCkgfD4KICBhcy5kYXRhLmZyYW1lKCkgfD4KICByb3duYW1lc190b19jb2x1bW4oKXw+CiAgcGl2b3RfbG9uZ2VyKCFyb3duYW1lKQoKIyDjg4fjg7zjgr/jg5Xjg6zjg7zjg6DjgpLmupblgpkKZGZfcGxvdCA8LSBkZiB8PgogIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKCkpIHw+CiAgbXV0YXRlKG5hbWUgPSBmYWN0b3IobmFtZSwgbGV2ZWxzID1MRVRURVJTWzY6MV0pKQoKIyDmo5LjgrDjg6njg5XjgpLmj4/nlLsKcDEgPC0gZGZfcGxvdCB8PgogIGRwbHlyOjpmaWx0ZXIobmFtZSA9PSAiQSIpIHw+CiAgZ2dwbG90KGFlcyh5ID0gdmFsdWUsIHg9MToyMCwgbGFiZWwgPSByb3VuZCh2YWx1ZSwgMikpKSArCiAgZ2VvbV9jb2woKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDEsIDEwKSkgKwogIHRoZW1lKAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXNwZWN0LnJhdGlvID0gMQogICAgKQoKIyDjg5Ljg7zjg4jjg57jg4Pjg5fjgpLmj4/nlLsKcDIgPC0gY29ycmVsYXRpb25fbWF0cml4IHw+CiAgZ2dwbG90KGFlcyh4ID0gcm93bmFtZSwgeSA9IG5hbWUsIGZpbGwgPSB2YWx1ZSwgbGFiZWwgPSByb3VuZCh2YWx1ZSwgMikpKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gInR1cmJvIikgKyAKICBnZW9tX3RpbGUoKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGFzcGVjdC5yYXRpbyA9IDEKICApCgojIOaVsOWApOWFpeOCjOOCiwpwMyA8LSBwMSArCiAgZ2VvbV90ZXh0KG51ZGdlX3kgPSAxLCBzaXplID0gMi41KQoKcDQgPC0gcDIgKwogIGdlb21fdGV4dChzaXplID0gMywgYWVzKGNvbG9yID0gKHZhbHVlID4gMC43NSB8IHZhbHVlIDwgLTAuNSkpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImJsYWNrIiwgIndoaXRlIikpICsKICBndWlkZXMoY29sb3IgPSAibm9uZSIpCgp7cDEgfCBwMn0gLyB7cDMgfCBwNH0KCmBgYAoKCiMjIyA4LjEuNyDou7jjg6njg5njg6vjgpLoqqzmmI7nmoTjgavjgZnjgosKCmBgYHtyfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBhdGNod29yaykKCmRhdGEoaXJpcykKCmJhc2VfcCA8LSBpcmlzIHw+CiAgZ2dwbG90KGFlcyh4ID0gUGV0YWwuTGVuZ3RoLCB5ID0gUGV0YWwuV2lkdGgsIGNvbG9yID0gU3BlY2llcykpICsKICBnZW9tX3BvaW50KCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpCgpwMSA8LSBiYXNlX3AgKyBsYWJzKAogICAgeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKCJMIilbaXRhbGljKCJwIildKSksCiAgICB5ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMoIlciKVtpdGFsaWMoInAiKV0pKQogICAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICLou7jjg6njg5njg6vjgYzjgo/jgYvjgorjgavjgY/jgYTlm7MiKQoKcDIgPC0gYmFzZV9wICsKICBsYWJzKAogICAgeCA9IGV4cHJlc3Npb24ocGFzdGUoIuiKseW8geOBrumVt+OBlSBbY21dLCAiLCBpdGFsaWMoIkwiKVtpdGFsaWMoInAiKV0pKSwKICAgIHkgPSBleHByZXNzaW9uKHBhc3RlKCLoirHlvIHjga7luYUgW2NtXSwgIiwgaXRhbGljKCJXIilbaXRhbGljKCJwIildKSkKICAgICkgKwogIHNjYWxlX2NvbG9yX2h1ZShsYWJlbHMgPSBjKCJzZXRvc2EiID0gIuOCu+ODiOOCtSIsICJ2ZXJzaWNvbG9yIiA9IuODkOODvOOCuOOCq+ODqeODvCIsICJ2aXJnaW5pY2EiID0i44OQ44O844K444OL44KrIikpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yLCAwLjgpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpCiAgICApICsKICBsYWJzKHRpdGxlID0gIui7uOODqeODmeODq+OCkuOCj+OBi+OCiuOChOOBmeOBj+OBl+OBn+WbsyIpCgpwMSArIHAyCmBgYAoKIyMjIDguMS44IOODkeODjeODq+OBruODrOOCpOOCouOCpuODiOOCkuiAg+OBiOOCiyAKCiMjIyMgOC4xLjguMSDjgo/jgYvjgorjgavjgY/jgYTjg6zjgqTjgqLjgqbjg4gKCmBgYHtyIGZpZy5oZWlnaHQ9Ni42NiwgZmlnLndpZHRoPTEwfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBhdGNod29yaykKCmRhdGEoaXJpcykKCnAxIDwtIGlyaXMgfD4KICBkcGx5cjo6ZmlsdGVyKFNwZWNpZXMgPT0gInNldG9zYSIpIHw+CiAgZ2dwbG90KGFlcyh4ID0gUGV0YWwuTGVuZ3RoLCB5ID0gUGV0YWwuV2lkdGgpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAi6Iqx5byB44Gu6ZW344GVIFtjbV0iLCB5ID0gIuiKseW8geOBruW5hSBbY21dIiwgdGl0bGUgPSAi44K744OI44K1ICjoirHlvIHplbcgdnMg6Iqx5byB5bmFKSIpICsKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKQoKcDIgPC0gaXJpcyB8PgogIGRwbHlyOjpmaWx0ZXIoU3BlY2llcyA9PSAic2V0b3NhIikgfD4KICBnZ3Bsb3QoYWVzKHggPSBTZXBhbC5MZW5ndGgsIHkgPSBQZXRhbC5MZW5ndGgpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAi44GM44GP54mH44Gu6ZW344GVIFtjbV0iLCB5ID0gIuiKseW8geOBrumVt+OBlSBbY21dIiwgdGl0bGUgPSAi44K744OI44K1ICjjgYzjgY/niYfplbfjgZUgdnMg6Iqx5byB6ZW3KSIpICsKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKQoKcDMgPC0gaXJpcyB8PgogIGRwbHlyOjpmaWx0ZXIoU3BlY2llcyA9PSAidmVyc2ljb2xvciIpIHw+CiAgZ2dwbG90KGFlcyh4ID0gUGV0YWwuTGVuZ3RoLCB5ID0gUGV0YWwuV2lkdGgpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAi6Iqx5byB44Gu6ZW344GVIFtjbV0iLCB5ID0gIuiKseW8geOBruW5hSBbY21dIiwgdGl0bGUgPSAi44OQ44O844K444Kr44Op44O8ICjoirHlvIHplbcgdnMg6Iqx5byB5bmFKSIpICsKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKQoKcDQgPC0gIGlyaXMgfD4KICBkcGx5cjo6ZmlsdGVyKFNwZWNpZXMgPT0gInZlcnNpY29sb3IiKSB8PgogIGdncGxvdChhZXMoeCA9IFNlcGFsLkxlbmd0aCwgeSA9IFBldGFsLkxlbmd0aCkpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeCA9ICLjgYzjgY/niYfjga7plbfjgZUgW2NtXSIsIHkgPSAi6Iqx5byB44Gu6ZW344GVIFtjbV0iLCB0aXRsZSA9ICLjg5Djg7zjgrjjgqvjg6njg7wgKOOBjOOBj+eJh+mVt+OBlSB2cyDoirHlvIHplbcpIikgKwogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpCgpwNSA8LSBpcmlzIHw+CiAgZHBseXI6OmZpbHRlcihTcGVjaWVzID09ICJ2aXJnaW5pY2EiKSB8PgogIGdncGxvdChhZXMoeCA9IFBldGFsLkxlbmd0aCwgeSA9IFBldGFsLldpZHRoKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4ID0gIuiKseW8geOBrumVt+OBlSBbY21dIiwgeSA9ICLoirHlvIHjga7luYUgW2NtXSIsIHRpdGxlID0gIuODkOODvOOCuOODi+OCqyAo6Iqx5byB6ZW3IHZzIOiKseW8geW5hSkiKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMSkKCnA2IDwtICBpcmlzIHw+CiAgZHBseXI6OmZpbHRlcihTcGVjaWVzID09ICJ2aXJnaW5pY2EiKSB8PgogIGdncGxvdChhZXMoeCA9IFNlcGFsLkxlbmd0aCwgeSA9IFBldGFsLkxlbmd0aCkpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeCA9ICLjgYzjgY/niYfjga7plbfjgZUgW2NtXSIsIHkgPSAi6Iqx5byB44Gu6ZW344GVIFtjbV0iLCB0aXRsZSA9ICLjg5Djg7zjgrjjg4vjgqsgKOOBjOOBj+eJh+mVt+OBlSB2cyDoirHlvIHplbcpIikgKwogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpCgp7cDEgfCBwMiB8IHAzfSAvIHtwNCB8IHA1IHwgcDZ9CmBgYAoKIyMjIyA4LjEuOC4yIOOCj+OBi+OCiuOChOOBmeOBhOODrOOCpOOCouOCpuODiAoKYGBge3IgZmlnLmhlaWdodD02LjY2LCBmaWcud2lkdGg9MTB9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGF0Y2h3b3JrKQoKZGF0YShpcmlzKQoKcGxvdF9pcmlzIDwtIGlyaXMgfD4KICBtdXRhdGUoCiAgICBTcGVjaWVzID0gY2FzZV93aGVuKAogICAgICBTcGVjaWVzID09ICJzZXRvc2EiIH4gIuOCu+ODiOOCtSIsCiAgICAgIFNwZWNpZXMgPT0gInZlcnNpY29sb3IiIH4gIuODkOODvOOCuOOCq+ODqeODvCIsCiAgICAgIFNwZWNpZXMgPT0gInZpcmdpbmljYSIgfiAi44OQ44O844K444OL44KrIgogICAgICApCiAgICApCgpwMSA8LSBwbG90X2lyaXMgfD4KICBnZ3Bsb3QoYWVzKHggPSBQZXRhbC5MZW5ndGgsIHkgPSBQZXRhbC5XaWR0aCwgY29sb3IgPSBTcGVjaWVzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4ID0gIuiKseW8geOBrumVt+OBlSBbY21dIiwgeSA9ICLoirHlvIHjga7luYUgW2NtXSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGFzcGVjdC5yYXRpbyA9IDEpICsKICBmYWNldF93cmFwKHZhcnMoU3BlY2llcyksIHNjYWxlcyA9ICJmcmVlIikKcDIgPC0gcGxvdF9pcmlzIHw+CiAgZ2dwbG90KGFlcyh4ID0gUGV0YWwuTGVuZ3RoLCB5ID0gU2VwYWwuTGVuZ3RoLCBjb2xvciA9IFNwZWNpZXMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAi6Iqx5byB44Gu6ZW344GVIFtjbV0iLCB5ID0gIuOBjOOBj+eJh+OBrumVt+OBlSBbY21dIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgYXNwZWN0LnJhdGlvID0gMSkgKwogIGZhY2V0X3dyYXAodmFycyhTcGVjaWVzKSwgc2NhbGVzID0gImZyZWUiKQoKCnAxIC8gcDIKYGBgCgrjgZPjgozjgavjgaTjgYTjgabjga/jgIHjgrnjgrHjg7zjg6vjgpLmj4PjgYjjgZ/jgbvjgYbjgYzoqqTop6PjgYznhKHjgYTjgajmgJ3jgYbjgIIKCuOBk+OCk+OBqumiqOOBq+OAggoKYGBge3IgZmlnLmhlaWdodD02LjY2LCBmaWcud2lkdGg9MTB9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGF0Y2h3b3JrKQoKZGF0YShpcmlzKQoKcGxvdF9pcmlzIDwtIGlyaXMgfD4KICBtdXRhdGUoCiAgICBTcGVjaWVzID0gY2FzZV93aGVuKAogICAgICBTcGVjaWVzID09ICJzZXRvc2EiIH4gIuOCu+ODiOOCtSIsCiAgICAgIFNwZWNpZXMgPT0gInZlcnNpY29sb3IiIH4gIuODkOODvOOCuOOCq+ODqeODvCIsCiAgICAgIFNwZWNpZXMgPT0gInZpcmdpbmljYSIgfiAi44OQ44O844K444OL44KrIgogICAgKQogICkKCnAxIDwtIHBsb3RfaXJpcyB8PgogIGdncGxvdChhZXMoeCA9IFBldGFsLkxlbmd0aCwgeSA9IFBldGFsLldpZHRoLCBjb2xvciA9IFNwZWNpZXMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAi6Iqx5byB44Gu6ZW344GVIFtjbV0iLCB5ID0gIuiKseW8geOBruW5hSBbY21dIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgYXNwZWN0LnJhdGlvID0gMSkgKwogIGZhY2V0X3dyYXAodmFycyhTcGVjaWVzKSkKcDIgPC0gcGxvdF9pcmlzIHw+CiAgZ2dwbG90KGFlcyh4ID0gUGV0YWwuTGVuZ3RoLCB5ID0gU2VwYWwuTGVuZ3RoLCBjb2xvciA9IFNwZWNpZXMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAi6Iqx5byB44Gu6ZW344GVIFtjbV0iLCB5ID0gIuOBjOOBj+eJh+OBrumVt+OBlSBbY21dIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgYXNwZWN0LnJhdGlvID0gMSkgKwogIGZhY2V0X3dyYXAodmFycyhTcGVjaWVzKSkKCgpwMSAvIHAyCmBgYAoKCiMjIDguMiDmjIfmqJnljJbjgYvjgonlj6/oppbljJbjga7miKbnlaXjgpLogIPjgYjjgosKCiMjIyA4LjIuNCDlpJbjgozlgKTjg7vnlbDluLjlgKTjgpLmjIfmqJnljJbjgZfjgabjgZfjgb7jgYbjgajigKbigKYKCmBgYHtyfQpsaWJyYXJ5KGNvbmZsaWN0ZWQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdnYmVlc3dhcm0pCgpuIDwtIDIwCnNldC5zZWVkKDApCnNhbXBsZXMgPC0gcHVycnI6Om1hcDIoCiAgYygxMCwgMTUsIDEyLCAyMCksICNtZWFuCiAgYyg1LCA1LCA1LCA1KSwgICAgICNzZAogIFwoeCwgeSkgcm5vcm0obiwgeCwgeSkKICApCgojIOOCteODs+ODl+ODq0HjgavlpJbjgozlgKTjgpLov73liqAKc2FtcGxlc1tbMV1dWzFdIDwtIDEwMAoKbmFtZXMoc2FtcGxlcykgPC0gTEVUVEVSU1sxOjRdCgojIOODh+ODvOOCv+ODleODrOODvOODoOOCkuS9nOaIkApkZiA8LSBzYW1wbGVzIHw+CiAgYXMuZGF0YS5mcmFtZSgpIHw+CiAgcGl2b3RfbG9uZ2VyKGV2ZXJ5dGhpbmcoKSkKCiMg44K544Km44Kp44O844Og44OX44Ot44OD44OICnAxIDwtIGRmIHw+CiAgZ2dwbG90KGFlcyh4ID0gbmFtZSwgeSA9IHZhbHVlLCBjb2xvciA9IG5hbWUpKSArCiAgZ2VvbV9xdWFzaXJhbmRvbSgpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBhc3BlY3QucmF0aW8gPSAxCiAgKSArIAogIGxhYnModGl0bGUgPSAi5YWD44Go44Gq44KL44OH44O844K/IikKCiMg5qOS44Kw44Op44OV77yI5bmz5Z2H5YCk77yJCnAyIDwtIGRmIHw+CiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHZhbHVlKSwgLmJ5ID0gbmFtZSkgfD4KICBnZ3Bsb3QoYWVzKHggPSBuYW1lLCB5ID0gbWVhbiwgZmlsbCA9IG5hbWUpKSArCiAgZ2VvbV9jb2woKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgYXNwZWN0LnJhdGlvID0gMQogICkgKyAKICBsYWJzKHRpdGxlID0gIuaMh+aomeWMluOBl+OBn+OCguOBru+8iOW5s+Wdh++8iSIpCgoKcDEgKyBwMgpgYGAKCiMjIyA4LjMuMiDjgbDjgonjgaTjgY3luqblkIjjgYTjgajnibnlvrTjga7lvLfjgZUKCn5+44K/44Kk44OI44Or44Gu5pac5L2T44KE5LiL5LuY44GN5paH5a2X44Go44Kq44OW44K444Kn44Kv44OI44GM5ZCM5bGF44Gn44GN44Gq44GEfn4KClvmlZnjgYjjgabjgYTjgZ/jgaDjgYTjgaZdKGh0dHBzOi8vdHdpdHRlci5jb20vdGFrZXNoaW5pc2hpbXVyL3N0YXR1cy8xNzUxMjM2MTA3ODUxOTc2OTM4KeOBp+OBjeOBvuOBl+OBn++8gQoKYGBge3J9CmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2diZWVzd2FybSkKbGlicmFyeShicm9vbSkKbGlicmFyeShzY2FsZXMpICNtdXRlZCgpCmxpYnJhcnkocGF0Y2h3b3JrKQoKIyDjg4fjg7zjgr/jga7nlJ/miJAKc2V0LnNlZWQoMikKc2FtcGxlcyA8LSBwdXJycjo6cG1hcCgKICBsaXN0KAogICAgbiA9IGMoMjAsIDIwLCA0MDAsIDQwMCksCiAgICBtZWFuID0gYyg2LCA2LCA2LCA1Ljc1KSwKICAgIHNkID0gYygyLCAyLCAyLCAyKQogICksCiAgXChuLCBtZWFuLCBzZCkgcm5vcm0obiwgbWVhbiwgc2QpCikKCm5hbWVzKHNhbXBsZXMpIDwtIGMoInYxMSIsICJ2MTIiLCAidjIxIiwgInYyMiIpCgojIHTmpJzlrpoKdF90ZXN0MSA8LSB0aWR5KHQudGVzdChzYW1wbGVzJHYxMSwgc2FtcGxlcyR2MTIpKQp0X3Rlc3QyIDwtIHRpZHkodC50ZXN0KHNhbXBsZXMkdjIxLCBzYW1wbGVzJHYyMikpCgojIOODh+ODvOOCv+OBruaVtOW9ogpkYXRhMSA8LSBkYXRhLmZyYW1lKAogIEdyb3VwID0gcmVwKGMoIkdyb3VwIDEiLCAiR3JvdXAgMiIpLCBlYWNoID0gMjApLAogIFZhbHVlID0gYyhzYW1wbGVzJHYxMSwgc2FtcGxlcyR2MTIpCiAgKQpkYXRhMV9tZWFuIDwtIGRhdGExIHw+CiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKFZhbHVlKSwgLmJ5ID0gR3JvdXApCgpkYXRhMiA8LSBkYXRhLmZyYW1lKAogIEdyb3VwID0gcmVwKGMoIkdyb3VwIDEiLCAiR3JvdXAgMiIpLCBlYWNoID0gNDAwKSwKICBWYWx1ZSA9IGMoc2FtcGxlcyR2MjEsIHNhbXBsZXMkdjIyKQogICkKCmRhdGEyX21lYW4gPC0gZGF0YTIgfD4KICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oVmFsdWUpLCAuYnkgPSBHcm91cCkKCnAxIDwtIGdncGxvdCgpICsKICBnZW9tX2NvbChkYXRhID0gZGF0YTFfbWVhbiwgYWVzKHggPSBHcm91cCwgeSA9IG1lYW4sIGZpbGwgPSBHcm91cCApKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0YTEsIGFlcyh4ID0gR3JvdXAsIHkgPSBWYWx1ZSwgY29sb3IgPSBHcm91cCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjQ0FCMkQ2IiwgIiNCMkRGOEEiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjNkEzRDlBIiwgIiMzM0EwMkMiKSkgKyAKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTIpKSArCiAgbGFicygKICAgIHRpdGxlID0gIuaomeacrOW5s+Wdh+OBruW3ruOBr+Wkp+OBjeOBhOOBjOKApuKApu+8nyIsIAogICAgc3VidGl0bGUgPSBicXVvdGUoaXRhbGljKHQpWzIwXSA9PSAuKHJvdW5kKHRfdGVzdDEkc3RhdGlzdGljLCAyKSkgfiAiLCBwLXZhbHVlID0gIiB+IC4ocm91bmQodF90ZXN0MSRwLnZhbHVlLCA0KSkpCiAjICAgc3VidGl0bGUgPSBleHByZXNzaW9uKHBhc3RlKHtpdGFsaWModClbMjBdfSwgIiA9ICIsIHJvdW5kKHRfdGVzdDEkc3RhdGlzdGljLCAyKSwgIiwgcC12YWx1ZSA9ICIsIHJvdW5kKHRfdGVzdDEkcC52YWx1ZSwgNCkpKQojICAgIHN1YnRpdGxlID0gcGFzdGUoInQyMCA9ICIsIHJvdW5kKHRfdGVzdDEkc3RhdGlzdGljLCAyKSwgIiwgcC12YWx1ZSA9ICIsIHJvdW5kKHRfdGVzdDEkcC52YWx1ZSwgNCkpCgogICAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSAKCnRlc3QgPC0gZXhwcmVzc2lvbih7aXRhbGljKHQpWzQwMF19KQpwMiA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9jb2woZGF0YSA9IGRhdGEyX21lYW4sIGFlcyh4ID0gR3JvdXAsIHkgPSBtZWFuLCBmaWxsID0gR3JvdXAgKSkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdGEyLCBhZXMoeCA9IEdyb3VwLCB5ID0gVmFsdWUsIGNvbG9yID0gR3JvdXApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0NBQjJENiIsICIjQjJERjhBIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzZBM0Q5QSIsICIjMzNBMDJDIikpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTIpKSArCiAgbGFicygKICAgIHRpdGxlID0gIuaomeacrOW5s+Wdh+OBruW3ruOBr+Wwj+OBleOBhOOBjOKApuKApu+8nyIsCiAgICBzdWJ0aXRsZSA9IGJxdW90ZShpdGFsaWModClbNDAwXSA9PSAuKHJvdW5kKHRfdGVzdDEkc3RhdGlzdGljLCAyKSkgfiAiLCBwLXZhbHVlID0gIiB+IC4ocm91bmQodF90ZXN0MiRwLnZhbHVlLCA0KSkpCiAgIyAgc3VidGl0bGUgPSBwYXN0ZSgidDQwMCA9ICIsIHJvdW5kKHRfdGVzdDIkc3RhdGlzdGljLCAyKSwgIiwgcC12YWx1ZSA9ICIsIHJvdW5kKHRfdGVzdDIkcC52YWx1ZSwgNCkpCiAgICApICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpIAoKcDEgKyBwMgpgYGAKCgrnrKw456ug44GT44GT44G+44GnCg==