README:再現方法とファイル構成

このオンライン補遺と再現コードは、論文「多党制は経済投票を弱めるのか?:政党の手がかりと経済の手がかりをめぐるコンジョイント実験」で報告する3つの実験の分析について、本文図、補遺図表、頑健性分析、無作為化・バランス診断、および支持政党別分析結果をまとめ、さらにそれらを再現するためのコードをまとめたものである。以下の手順で、入力データの読込みから最終的な図表・診断結果の整理までを一括して実行できる。

1. 再現に必要なファイル等

次の4ファイルを同じ作業ディレクトリに置いてもらう。データファイル名や保存場所を変更する場合は、このRmd冒頭の params を変更してもらえばよい。

ファイル 内容
partynum.csv 実験1の入力データ
conjoint_study2.csv 実験2の入力データ
conjoint_S3.csv 実験3の入力データ

2. 必要なRパッケージ

分析コードで使用する主要パッケージは以下のとおりである。

install.packages(c(
  "dplyr", "tidyr", "stringr", "purrr", "readr",
  "fixest", "tibble", "forcats", "ggplot2", "scales",
  "survival", "ggtext", "patchwork", "rmarkdown", "knitr"
))

3. 各種のデフォルト設定

冒頭の params で、入力ファイル、出力先、ブートストラップ回数を変更可能である。現在の主要なデフォルト値は次のとおりである。

パラメータ デフォルト 意味
output_root conjoint_replication_results 全出力を保存するルートディレクトリ
relative_cue_bootstrap_B 2000 主要な重要度・相対比重のブートストラップ反復数
support_bootstrap_B 500 支持政党別分析のブートストラップ反復数

4. 出力ファイル

分析結果はデフォルトで conjoint_replication_results/ 内に保存される設定になっている。主な構成は以下の通り。

  • main_text/:本文用の図と表
  • supplement/:実験別および実験横断の補遺図表(CSV、LaTeX、図)
  • diagnostics/:標本スクリーニング、割付バランス、プロフィール無作為化の診断
  • model_objects/:再利用可能なモデル・分析オブジェクト
  • logs/sessionInfo などの再現性情報

各分析の途中の経過作成される各種オブジェクトなどは _working/ に保存され、最終段階で上記のディレクトリに整理するように設定した。Rおよび各パッケージの実行環境は、分析完了後に sessionInfo として保存される設定となっている。

5. このオンライン補遺と再現コードの読み方

A節は本文・補遺の図表を生成する実行コード、B節以降は分析標本、推定量、無作為化・バランス診断、および各補足結果を、コードと対応させて確認するためのセクションである。J節には、実験1〜3で実際に用いた調査票の質問文・回答形式を、重複するコンジョイント課題を整理したうえで再掲する。画面上部の Show All Code / Hide All Code または右上の Code メニューから、コード全体の表示・非表示を切り替えられる。

A. 各図表の再現コード

A.1 共通コード

# 共通コード
options(stringsAsFactors = FALSE)

unified_output_root <- getOption(
  "conjoint.output_root",
  "conjoint_replication_results"
)

dir.create(
  unified_output_root,
  showWarnings = FALSE,
  recursive = TRUE
)

unified_config <- list(
  output_root = unified_output_root,

  cue_importance_metric_version = "v4_screening_autodetect",

  relative_cue_bootstrap_B = as.integer(
    getOption("conjoint.relative_cue_bootstrap_B", 2000L)
  ),
  relative_cue_bootstrap_seed = as.integer(
    getOption("conjoint.relative_cue_bootstrap_seed", 20260730L)
  ),
  relative_cue_bootstrap_progress_every = as.integer(
    getOption("conjoint.relative_cue_bootstrap_progress_every", 100L)
  ),
  rerun_relative_cue_bootstrap = isTRUE(
    getOption("conjoint.rerun_relative_cue_bootstrap", FALSE)
  ),

  min_support_total_n = as.integer(
    getOption("conjoint.min_support_total_n", 150L)
  ),
  min_support_cell_n = as.integer(
    getOption("conjoint.min_support_cell_n", 40L)
  ),
  support_bootstrap_B = as.integer(
    getOption("conjoint.support_bootstrap_B", 500L)
  ),
  support_bootstrap_seed = as.integer(
    getOption("conjoint.support_bootstrap_seed", 20260806L)
  ),
  rerun_support_bootstrap = isTRUE(
    getOption("conjoint.rerun_support_bootstrap", FALSE)
  ),

  study1 = list(
    data_file = getOption("conjoint.study1_data", "partynum.csv"),
    output_dir = file.path(unified_output_root, "_working", "study1")
  ),
  study2 = list(
    data_file = getOption("conjoint.study2_data", "conjoint_study2.csv"),
    output_dir = file.path(unified_output_root, "_working", "study2")
  ),
  study3 = list(
    data_file = getOption("conjoint.study3_data", "conjoint_S3.csv"),
    output_dir = file.path(unified_output_root, "_working", "study3")
  )
)

cat(
  "Unified conjoint replication pipeline\n",
  "Output root: ", unified_config$output_root, "\n",
  "Study 1 data: ", unified_config$study1$data_file, "\n",
  "Study 2 data: ", unified_config$study2$data_file, "\n",
  "Study 3 data: ", unified_config$study3$data_file, "\n",
  sep = ""
)


detect_final_consent_column <- function(
  raw,
  preferred_candidates = c("Q8.1", "Q9.1", "Q10.1"),
  study_label = "Study"
) {
  if (!is.data.frame(raw) || ncol(raw) == 0L) {
    stop("Check data")
  }

  preview_n <- min(12L, nrow(raw))

  normalize_preview <- function(x) {
    x <- as.character(x)
    x[is.na(x)] <- ""
    x <- gsub(" ", " ", x, fixed = TRUE)
    x <- gsub("[[:space:]]+", " ", x)
    trimws(x)
  }

  score_one <- function(column_name) {
    preview <- paste(
      normalize_preview(utils::head(raw[[column_name]], preview_n)),
      collapse = " "
    )

    score <- 0L

    if (grepl("最終意思確認", preview, fixed = TRUE)) {
      score <- score + 8L
    }
    if (grepl("こちらが調査の最後の画面", preview, fixed = TRUE) ||
        grepl("調査の最後の画面", preview, fixed = TRUE)) {
      score <- score + 6L
    }
    if (grepl("回答結果を送信する", preview, fixed = TRUE)) {
      score <- score + 8L
    }
    if (grepl("回答結果を送信しない", preview, fixed = TRUE) ||
        grepl("回答を送信しない", preview, fixed = TRUE)) {
      score <- score + 5L
    }
    if (grepl("本調査の主旨に同意", preview, fixed = TRUE) ||
        grepl("本調査の趣旨に同意", preview, fixed = TRUE)) {
      score <- score + 3L
    }
    if (column_name %in% preferred_candidates) {
      score <- score + 1L
    }

    score
  }

  candidate_table <- data.frame(
    column = names(raw),
    score = vapply(names(raw), score_one, integer(1)),
    stringsAsFactors = FALSE
  )

  candidate_table <- candidate_table[candidate_table$score > 0L, , drop = FALSE]

  if (nrow(candidate_table) == 0L) {
    existing_preferred <- preferred_candidates[
      preferred_candidates %in% names(raw)
    ]

    if (length(existing_preferred) == 1L) {
      message("Final consent: ", existing_preferred[[1]])
      return(existing_preferred[[1]])
    }

    likely_question_columns <- names(raw)[
      grepl("^Q[0-9]+(\\.[0-9]+)?(_[0-9]+)?$", names(raw))
    ]

    stop("Check final consent")
  }

  max_score <- max(candidate_table$score)
  best <- candidate_table$column[candidate_table$score == max_score]

  if (length(best) > 1L) {
    preferred_best <- preferred_candidates[
      preferred_candidates %in% best
    ]

    if (length(preferred_best) >= 1L) {
      best <- preferred_best[[1]]
    } else {
      stop("Check final consent")
    }
  }

  message("Final consent: ", best[[1]])


  best[[1]]
}

qualtrics_preview_text <- function(raw, column_name, preview_n = 12L) {
  if (!column_name %in% names(raw)) {
    return("")
  }

  x <- as.character(utils::head(raw[[column_name]], min(preview_n, nrow(raw))))
  x[is.na(x)] <- ""
  x <- gsub(" ", " ", x, fixed = TRUE)
  x <- gsub("[[:space:]]+", " ", x)
  trimws(paste(x, collapse = " "))
}

fullwidth_digit <- function(n) {
  substr("0123456789", n + 1L, n + 1L)
}

question_order_key <- function(x) {
  m <- regexec("^Q([0-9]+)\\.([0-9]+)", x)
  parts <- regmatches(x, m)

  vapply(
    parts,
    function(z) {
      if (length(z) < 3L) {
        return(Inf)
      }
      as.numeric(z[[2]]) * 1000 + as.numeric(z[[3]])
    },
    numeric(1)
  )
}

detect_attention_check_column <- function(
  raw,
  preferred_candidates = c("Q25.1_11", "Q25.1_10"),
  study_label = "Study"
) {
  metadata <- data.frame(
    column = names(raw),
    text = vapply(names(raw), function(v) qualtrics_preview_text(raw, v), character(1)),
    stringsAsFactors = FALSE
  )

  score <- integer(nrow(metadata))
  score <- score + ifelse(grepl("必ず", metadata$text, fixed = TRUE), 8L, 0L)
  score <- score + ifelse(grepl("選ん", metadata$text, fixed = TRUE), 5L, 0L)
  score <- score + ifelse(grepl("3|3", metadata$text), 4L, 0L)
  score <- score + ifelse(metadata$column %in% preferred_candidates, 1L, 0L)
  metadata$score <- score

  candidates <- metadata[
    grepl("必ず", metadata$text, fixed = TRUE) &
      grepl("選ん", metadata$text, fixed = TRUE) &
      grepl("3|3", metadata$text),
    ,
    drop = FALSE
  ]

  if (nrow(candidates) == 0L) {
    stop("Check attention item")
  }

  candidates <- candidates[order(-candidates$score), , drop = FALSE]
  best_score <- candidates$score[[1]]
  best <- candidates$column[candidates$score == best_score]

  if (length(best) > 1L) {
    preferred_best <- preferred_candidates[preferred_candidates %in% best]
    if (length(preferred_best) == 1L) {
      best <- preferred_best
    } else {
      stop("Check attention item")
    }
  }

  message("Attention item: ", best[[1]])
  best[[1]]
}

response_code_numeric <- function(x) {
  x <- as.character(x)
  x[is.na(x)] <- ""
  x <- gsub(" ", " ", x, fixed = TRUE)
  x <- trimws(gsub("[[:space:]]+", " ", x))

  exact <- grepl("^[0-9]+(?:\\.0+)?$", x, perl = TRUE)
  out <- rep(NA_real_, length(x))
  out[exact] <- suppressWarnings(as.numeric(x[exact]))

  trailing <- regexec("\\(([0-9]+)\\)\\s*$", x)
  trailing_parts <- regmatches(x, trailing)
  trailing_code <- vapply(
    trailing_parts,
    function(z) if (length(z) >= 2L) as.numeric(z[[2]]) else NA_real_,
    numeric(1)
  )
  out[is.na(out) & !is.na(trailing_code)] <- trailing_code[is.na(out) & !is.na(trailing_code)]

  first_num <- suppressWarnings(readr::parse_number(x))
  out[is.na(out)] <- first_num[is.na(out)]
  out
}

detect_attention_correct_code <- function(
  x,
  displayed_answer = 3L,
  recoded_answer = 6L,
  study_label = "Study"
) {
  code <- response_code_numeric(x)
  tab <- sort(table(code, useNA = "no"), decreasing = TRUE)

  n_display <- sum(code == displayed_answer, na.rm = TRUE)
  n_recode <- sum(code == recoded_answer, na.rm = TRUE)

  chosen <- if (n_recode > n_display) recoded_answer else displayed_answer
  n_nonmissing <- sum(!is.na(code))
  n_chosen <- sum(code == chosen, na.rm = TRUE)

  cat("\n", study_label, ":指示項目の回答コード分布\n", sep = "")
  print(utils::head(tab, 15L))
  cat(
    "採用する正答コード: ", chosen,
    "(表示上の正答は3)\n",
    sep = ""
  )

  if (n_nonmissing == 0L || n_chosen / n_nonmissing < 0.50) {
    stop("Check attention item")
  }

  as.character(chosen)
}

detect_conjoint_choice_map <- function(
  raw,
  party_numbers = 2:5,
  study_label = "Study"
) {
  metadata <- data.frame(
    column = names(raw),
    text = vapply(names(raw), function(v) qualtrics_preview_text(raw, v), character(1)),
    stringsAsFactors = FALSE
  )

  maps <- lapply(
    party_numbers,
    function(n_party) {
      digit_pattern <- paste0("(?:", n_party, "|", fullwidth_digit(n_party), ")\\s*つの選択肢")

      hit <- grepl("以下に", metadata$text, fixed = TRUE) &
        grepl("選択肢", metadata$text, fixed = TRUE) &
        grepl(digit_pattern, metadata$text, perl = TRUE) &
        grepl("衆議院", metadata$text, fixed = TRUE) &
        !grepl("提示された.*選択肢の数", metadata$text, perl = TRUE) &
        grepl("^Q[0-9]+\\.[0-9]+$", metadata$column)

      candidates <- metadata[hit, , drop = FALSE]
      candidates <- candidates[
        order(question_order_key(candidates$column)),
        ,
        drop = FALSE
      ]

      if (nrow(candidates) != 5L) {
        stop("Check choice columns")
      }

      data.frame(
        party_n = n_party,
        task = seq_len(5L),
        choice_var = candidates$column,
        stringsAsFactors = FALSE
      )
    }
  )

  out <- dplyr::bind_rows(maps)
  message("Choice columns: OK")
  print(out)
  out
}

detect_manipulation_map <- function(raw, choice_map, study_label = "Study") {
  metadata_text <- setNames(
    vapply(names(raw), function(v) qualtrics_preview_text(raw, v), character(1)),
    names(raw)
  )

  out <- lapply(
    sort(unique(choice_map$party_n)),
    function(n_party) {
      vars <- choice_map$choice_var[choice_map$party_n == n_party]
      roots <- sub("\\.[0-9]+$", "", vars)
      root <- names(sort(table(roots), decreasing = TRUE))[[1]]
      suffix <- suppressWarnings(as.integer(sub("^.*\\.", "", vars)))
      expected <- paste0(root, ".", max(suffix, na.rm = TRUE) + 1L)

      candidates <- names(metadata_text)[
        startsWith(names(metadata_text), paste0(root, ".")) &
          grepl("提示された", metadata_text, fixed = TRUE) &
          grepl("選択肢の数", metadata_text, fixed = TRUE)
      ]

      if (expected %in% candidates) {
        chosen <- expected
      } else if (length(candidates) == 1L) {
        chosen <- candidates[[1]]
      } else {
        stop("Check manipulation item")
      }

      data.frame(
        party_n = n_party,
        manipulation_var = chosen,
        correct_answer = as.character(n_party),
        stringsAsFactors = FALSE
      )
    }
  )

  out <- dplyr::bind_rows(out)
  message("Manipulation item: OK")
  print(out)
  out
}

parse_choice_position <- function(x) {
  x <- as.character(x)
  x[is.na(x)] <- ""
  x <- gsub(" ", " ", x, fixed = TRUE)
  x <- trimws(gsub("[[:space:]]+", " ", x))

  label_match <- regexec("(?:政党|状況|選択肢)\\s*([1-5])", x, perl = TRUE)
  label_parts <- regmatches(x, label_match)
  label_num <- vapply(
    label_parts,
    function(z) if (length(z) >= 2L) as.numeric(z[[2]]) else NA_real_,
    numeric(1)
  )

  exact <- grepl("^[1-5](?:\\.0+)?$", x, perl = TRUE)
  exact_num <- rep(NA_real_, length(x))
  exact_num[exact] <- suppressWarnings(as.numeric(x[exact]))

  trailing <- regexec("\\(([1-5])\\)\\s*$", x)
  trailing_parts <- regmatches(x, trailing)
  trailing_num <- vapply(
    trailing_parts,
    function(z) if (length(z) >= 2L) as.numeric(z[[2]]) else NA_real_,
    numeric(1)
  )

  out <- label_num
  out[is.na(out)] <- exact_num[is.na(out)]
  out[is.na(out)] <- trailing_num[is.na(out)]
  out
}

A.2 実験1:本文の図4・図5

# 本文コード
study1_env <- local({
required_packages <- c(
    "dplyr",
    "tidyr",
    "stringr",
    "purrr",
    "readr",
    "fixest",
    "tibble",
    "forcats",
    "ggplot2",
    "scales",
    "survival",
    "ggtext",
    "patchwork"
  )

  missing_packages <- required_packages[
    !vapply(required_packages, requireNamespace, logical(1), quietly = TRUE)
  ]

  if (length(missing_packages) > 0) {
    stop("No packages")
  }

  library(dplyr)
  library(tidyr)
  library(stringr)
  library(purrr)
  library(readr)
  library(fixest)
  library(tibble)
  library(forcats)
  library(ggplot2)
  library(scales)
  library(survival)
  library(patchwork)

  data_file <- unified_config$study1$data_file
  output_dir <- unified_config$study1$output_dir

  dir.create(output_dir, showWarnings = FALSE, recursive = TRUE)

  require_initial_consent <- TRUE
  require_final_consent <- TRUE
  initial_consent_var <- "Q1.1"
  final_consent_var <- "Q8.1"

  require_attention_check <- FALSE
  require_manipulation_check <- FALSE
  attention_check_var <- NA_character_
  attention_check_correct <- NA_character_

  require_all_five_tasks <- TRUE

  use_education_covariate <- FALSE

  relative_cue_bootstrap_B <- unified_config$relative_cue_bootstrap_B
  relative_cue_bootstrap_seed <- unified_config$relative_cue_bootstrap_seed + 1L
  relative_cue_bootstrap_progress_every <- unified_config$relative_cue_bootstrap_progress_every

  rerun_relative_cue_bootstrap <- unified_config$rerun_relative_cue_bootstrap


  norm_text <- function(x) {
    x %>%
      as.character() %>%
      str_squish() %>%
      str_replace_all("~", "~") %>%
      str_replace_all("〜", "~")
  }

  as_num <- function(x) {
    suppressWarnings(readr::parse_number(norm_text(x)))
  }

  is_response_code <- function(x, code) {
    x_norm <- norm_text(x)
    code_chr <- as.character(code)

    x_norm == code_chr |
      stringr::str_detect(x_norm, paste0("\\(", code_chr, "\\)$"))
  }

  first_existing <- function(dat, candidates) {
    out <- candidates[candidates %in% names(dat)]
    if (length(out) == 0) NA_character_ else out[1]
  }

  get_var <- function(dat, candidates) {
    v <- first_existing(dat, candidates)
    if (is.na(v)) {
      rep(NA_character_, nrow(dat))
    } else {
      dat[[v]]
    }
  }

  relevel_if_present <- function(x, ref) {
    x <- factor(x)
    if (ref %in% levels(x)) {
      relevel(x, ref = ref)
    } else {
      x
    }
  }

  factor_miss <- function(x, miss = "欠損・無回答") {
    x <- norm_text(x)
    x[is.na(x) | x == "" | x == "NA"] <- miss
    factor(x)
  }

  mean_impute <- function(x) {
    x <- as.numeric(x)
    miss <- as.integer(is.na(x))

    if (all(is.na(x))) {
      value <- x
    } else {
      value <- ifelse(is.na(x), mean(x, na.rm = TRUE), x)
    }

    list(value = value, miss = miss)
  }

  write_csv_safely <- function(x, filename) {
    readr::write_csv(x, file.path(output_dir, filename), na = "")
  }

  save_plot <- function(filename, plot, width, height, dpi = 300) {
    ggplot2::ggsave(
      filename = file.path(output_dir, filename),
      plot = plot,
      width = width,
      height = height,
      dpi = dpi
    )
  }


  if (!file.exists(data_file)) {
    stop("Check data")
  }

  raw <- readr::read_csv(
    data_file,
    col_types = cols(.default = col_character()),
    show_col_types = FALSE,
    name_repair = "minimal"
  )

  if (!"ResponseId" %in% names(raw)) {
    stop("Check data")
  }

  names(raw) <- names(raw) %>%
    str_replace("^F\\.(\\d+)\\.(\\d+)\\.(\\d+)$", "F-\\1-\\2-\\3") %>%
    str_replace("^F\\.(\\d+)\\.(\\d+)$", "F-\\1-\\2")

  if (
    require_final_consent &&
      (
        is.na(final_consent_var) ||
          !final_consent_var %in% names(raw)
      )
  ) {
    consent_question_pattern <- paste0(
      "回答結果を送信する|",
      "回答を送信しない|",
      "回答結果を送信しない|",
      "最終意思確認"
    )

    preview_n <- min(10L, nrow(raw))

    detected_final_consent_vars <- names(raw)[
      vapply(
        raw,
        function(column) {
          preview <- norm_text(
            utils::head(
              column,
              preview_n
            )
          )

          any(
            stringr::str_detect(
              preview,
              consent_question_pattern
            ),
            na.rm = TRUE
          )
        },
        logical(1)
      )
    ]

    if (length(detected_final_consent_vars) == 1L) {
      final_consent_var <- detected_final_consent_vars[[1]]

      message("Final consent: ", final_consent_var)
    } else if (length(detected_final_consent_vars) > 1L) {
      stop("Check final consent")
    } else {
      likely_question_columns <- names(raw)[
        stringr::str_detect(
          names(raw),
          "^Q[0-9]+(?:\\.[0-9]+)?$"
        )
      ]

      stop("Check final consent")
    }
  }

  df_header_removed <- raw %>%
    filter(
      !is.na(ResponseId),
      ResponseId != "",
      !str_detect(
        norm_text(ResponseId),
        "^(Response ID|回答ID)$|ImportId"
      )
    ) %>%
    mutate(ID = as.character(ResponseId))

  duplicate_ids <- df_header_removed %>%
    count(ID) %>%
    filter(n > 1)

  if (nrow(duplicate_ids) > 0) {
    print(duplicate_ids)
    stop("Check")
  }

  sample_flow <- tibble(
    stage = "Qualtrics質問文行・ImportId行を除外後",
    n = nrow(df_header_removed)
  )

  df <- df_header_removed

  if (require_initial_consent) {
    if (is.na(initial_consent_var) || !initial_consent_var %in% names(df)) {
      stop("Check initial consent")
    }
    df <- df %>%
      filter(
        is_response_code(.data[[initial_consent_var]], 1) |
          str_detect(
            norm_text(.data[[initial_consent_var]]),
            "趣旨に同意して.*協力する"
          )
      )
    sample_flow <- bind_rows(
      sample_flow,
      tibble(stage = "初回同意回答を保持", n = nrow(df))
    )
  }

  if (require_final_consent) {
    if (is.na(final_consent_var) || !final_consent_var %in% names(df)) {
      stop("Check final consent")
    }
    df <- df %>%
      filter(
        is_response_code(.data[[final_consent_var]], 1) |
          str_detect(
            norm_text(.data[[final_consent_var]]),
            "同意し.*回答結果を送信する"
          )
      )
    sample_flow <- bind_rows(
      sample_flow,
      tibble(stage = "最終同意回答を保持", n = nrow(df))
    )
  }

  print(sample_flow)
  write_csv_safely(sample_flow, "sample_flow_before_conjoint.csv")


  choice_map <- tribble(
    ~party_n, ~task, ~choice_var,
    2, 1, "Q240",
    2, 2, "Q253",
    2, 3, "Q254",
    2, 4, "Q255",
    2, 5, "Q256",

    3, 1, "Q235",
    3, 2, "Q241",
    3, 3, "Q242",
    3, 4, "Q243",
    3, 5, "Q244",

    4, 1, "Q238",
    4, 2, "Q245",
    4, 3, "Q246",
    4, 4, "Q247",
    4, 5, "Q248",

    5, 1, "Q239",
    5, 2, "Q249",
    5, 3, "Q250",
    5, 4, "Q251",
    5, 5, "Q252"
  )

  if (require_manipulation_check) {
    stop("Check")
  }


  level_to_attr_var <- function(x) {
    x <- norm_text(x)

    case_when(
      x %in% c("右派・保守的", "中道", "左派・革新的") ~
        "policy_position",

      x %in% c("与党", "野党") ~
        "government_status",

      str_detect(x, "GDP成長率") ~
        "gdp_growth",

      str_detect(x, "日経平均") ~
        "nikkei",

      x %in% c("10以下", "10~49", "50~99", "100~199", "200以上") ~
        "seats",

      str_detect(x, "CPI|物価") ~
        "cpi",

      str_detect(x, "失業率|雇用") ~
        "unemployment",

      TRUE ~ NA_character_
    )
  }

  required_attr_vars <- c(
    "policy_position",
    "government_status",
    "gdp_growth",
    "nikkei",
    "seats",
    "cpi",
    "unemployment"
  )

  allowed_levels <- list(
    policy_position = c("右派・保守的", "中道", "左派・革新的"),
    government_status = c("与党", "野党"),
    gdp_growth = c(
      "GDP成長率±0%",
      "GDP成長率プラス1%",
      "GDP成長率マイナス1%"
    ),
    nikkei = c(
      "日経平均前月同期比プラス1000円",
      "日経平均前月同期比マイナス1000円",
      "日経平均前月同期比変わらず"
    ),
    seats = c("10以下", "10~49", "50~99", "100~199", "200以上"),
    cpi = c(
      "CPI前期比±0ポイント",
      "CPI前期比プラス1ポイント",
      "CPI前期比マイナス1ポイント"
    ),
    unemployment = c(
      "失業率前期比±0%",
      "失業率前期比プラス1%",
      "失業率前期比マイナス1%"
    )
  )


  make_profile_long <- function(dat, n_party) {

    map_n <- choice_map %>%
      filter(party_n == n_party)

    qvars <- map_n$choice_var

    missing_q <- setdiff(qvars, names(dat))
    if (length(missing_q) > 0) {
      stop("Check choice columns")
    }

    dat_n <- dat %>%
      filter(
        if_any(
          all_of(qvars),
          ~ !is.na(.x) & norm_text(.x) != ""
        )
      )

    choice_long <- dat_n %>%
      select(ID, all_of(qvars)) %>%
      pivot_longer(
        cols = all_of(qvars),
        names_to = "choice_var",
        values_to = "choice_raw"
      ) %>%
      left_join(map_n, by = "choice_var") %>%
      mutate(choice = as_num(choice_raw)) %>%
      filter(!is.na(choice)) %>%
      select(ID, party_n, task, choice)

    invalid_choice <- choice_long %>%
      filter(choice < 1 | choice > n_party)

    if (nrow(invalid_choice) > 0) {
      print(invalid_choice)
      stop("Check choice values")
    }

    duplicate_choice <- choice_long %>%
      count(ID, task) %>%
      filter(n != 1)

    if (nrow(duplicate_choice) > 0) {
      print(duplicate_choice)
      stop("Check duplicate choices")
    }

    level_regex <- "^F-([1-5])-([1-5])-([1-7])$"
    level_cols <- names(dat_n)[str_detect(names(dat_n), level_regex)]

    if (length(level_cols) == 0) {
      stop("Check attributes")
    }

    level_long <- dat_n %>%
      select(ID, all_of(level_cols)) %>%
      pivot_longer(
        cols = all_of(level_cols),
        names_to = "fvar",
        values_to = "level"
      ) %>%
      extract(
        fvar,
        into = c("task", "profile", "attr_order"),
        regex = level_regex,
        convert = TRUE
      ) %>%
      mutate(level = norm_text(level)) %>%
      filter(
        task %in% 1:5,
        profile %in% 1:n_party,
        attr_order %in% 1:7,
        !is.na(level),
        level != ""
      ) %>%
      mutate(attr_var = level_to_attr_var(level))

    unknown_levels <- level_long %>%
      filter(is.na(attr_var)) %>%
      distinct(level)

    if (nrow(unknown_levels) > 0) {
      print(unknown_levels)
      stop("Check attributes")
    }

    profile_attribute_count <- level_long %>%
      count(ID, task, profile, name = "n_attribute_rows") %>%
      filter(n_attribute_rows != 7)

    if (nrow(profile_attribute_count) > 0) {
      print(head(profile_attribute_count, 50))
      stop("Check attributes")
    }

    duplicate_attribute <- level_long %>%
      count(ID, task, profile, attr_var) %>%
      filter(n != 1)

    if (nrow(duplicate_attribute) > 0) {
      print(head(duplicate_attribute, 50))
      stop("Check attributes")
    }

    profile_wide <- level_long %>%
      inner_join(choice_long, by = c("ID", "task")) %>%
      mutate(
        party_n = n_party,
        selected = as.integer(profile == choice),
        task_id = paste(ID, party_n, task, sep = "_"),
        profile_id = paste(ID, party_n, task, profile, sep = "_")
      ) %>%
      select(
        ID, party_n, task, profile, choice, selected,
        task_id, profile_id, attr_var, level
      ) %>%
      pivot_wider(
        names_from = attr_var,
        values_from = level,
        values_fn = list(level = ~ first(.x))
      )

    missing_attr <- setdiff(required_attr_vars, names(profile_wide))

    if (length(missing_attr) > 0) {
      stop("Check attributes")
    }

    profile_wide %>%
      select(
        ID, party_n, task, profile, choice, selected,
        task_id, profile_id,
        all_of(required_attr_vars)
      ) %>%
      arrange(ID, task, profile)
  }


  conjoint_2 <- make_profile_long(df, 2)
  conjoint_3 <- make_profile_long(df, 3)
  conjoint_4 <- make_profile_long(df, 4)
  conjoint_5 <- make_profile_long(df, 5)

  conjoint_all_unfiltered <- bind_rows(
    conjoint_2,
    conjoint_3,
    conjoint_4,
    conjoint_5
  )


  id_task_check <- conjoint_all_unfiltered %>%
    group_by(ID, party_n, task) %>%
    summarise(
      n_profiles = n(),
      selected_sum = sum(selected),
      .groups = "drop"
    ) %>%
    group_by(ID, party_n) %>%
    summarise(
      n_tasks = n_distinct(task),
      all_tasks_ok = all(n_profiles == party_n & selected_sum == 1),
      .groups = "drop"
    )

  if (require_all_five_tasks) {
    valid_ids <- id_task_check %>%
      filter(n_tasks == 5, all_tasks_ok)
  } else {
    valid_ids <- id_task_check %>%
      filter(all_tasks_ok)
  }

  conjoint_all <- conjoint_all_unfiltered %>%
    semi_join(valid_ids, by = c("ID", "party_n"))

  n_by_party <- valid_ids %>%
    count(party_n, name = "n") %>%
    complete(party_n = 2:5, fill = list(n = 0)) %>%
    arrange(party_n)

  n_total <- valid_ids %>%
    summarise(n = n_distinct(ID)) %>%
    pull(n)

  figure_n_labels <- bind_rows(
    tibble(
      position = "全サンプル",
      label = paste0("全サンプル, n=", scales::comma(n_total))
    ),
    n_by_party %>%
      mutate(
        position = paste0(party_n, "政党選択"),
        label = paste0("n=", scales::comma(n))
      ) %>%
      select(position, label)
  )

  sample_flow <- bind_rows(
    sample_flow,
    tibble(
      stage = "完全な5課題をもつ分析対象者",
      n = n_total
    )
  )

  cat("\n分析対象者数\n")
  print(n_by_party)
  cat("全サンプル n=", n_total, "\n", sep = "")

  write_csv_safely(sample_flow, "sample_flow.csv")
  write_csv_safely(id_task_check, "id_task_check.csv")
  write_csv_safely(valid_ids, "valid_ids.csv")
  write_csv_safely(n_by_party, "n_by_party.csv")
  write_csv_safely(figure_n_labels, "figure_n_labels.csv")


  check_profile <- conjoint_all %>%
    group_by(party_n, ID, task, task_id) %>%
    summarise(
      n_profiles = n(),
      selected_sum = sum(selected),
      .groups = "drop"
    ) %>%
    count(party_n, n_profiles, selected_sum)

  print(check_profile)
  stopifnot(all(check_profile$n_profiles == check_profile$party_n))
  stopifnot(all(check_profile$selected_sum == 1))

  allowed_df <- enframe(allowed_levels, name = "name", value = "value") %>%
    unnest(value)

  unexpected_values <- conjoint_all %>%
    select(all_of(required_attr_vars)) %>%
    pivot_longer(
      cols = everything(),
      names_to = "name",
      values_to = "value"
    ) %>%
    filter(!is.na(value), value != "") %>%
    distinct(name, value) %>%
    anti_join(allowed_df, by = c("name", "value"))

  print(unexpected_values)
  stopifnot(nrow(unexpected_values) == 0)

  observed_levels <- conjoint_all %>%
    select(all_of(required_attr_vars)) %>%
    pivot_longer(
      cols = everything(),
      names_to = "attribute",
      values_to = "level"
    ) %>%
    distinct(attribute, level) %>%
    arrange(attribute, level)

  write_csv_safely(check_profile, "profile_expansion_check.csv")
  write_csv_safely(observed_levels, "observed_attribute_levels.csv")
  write_csv_safely(conjoint_all, "study1_profile_level_data.csv")


  if (require_attention_check) {
    if (
      is.na(attention_check_var) ||
        !attention_check_var %in% names(df) ||
        is.na(attention_check_correct)
    ) {
      stop("Check attention item")
    }
  }

  attention_summary <- tibble(
    note = "2023年元コードでは注意チェックの確定対応表を使用していないため、標準分析では集計を省略。"
  )

  manipulation_summary <- tibble(
    note = "2023年元コードでは政党数確認質問の確定対応表を使用していないため、標準分析では集計を省略。"
  )

  write_csv_safely(attention_summary, "attention_check_summary.csv")
  write_csv_safely(manipulation_summary, "party_number_check_summary.csv")


  conjoint_all_m <- conjoint_all %>%
    mutate(
      selected = as.integer(selected),
      ID = as.character(ID),

      policy_position = factor(
        policy_position,
        levels = c("中道", "右派・保守的", "左派・革新的")
      ),

      government_status = factor(
        government_status,
        levels = c("野党", "与党")
      ),

      gdp_growth = factor(
        gdp_growth,
        levels = c(
          "GDP成長率±0%",
          "GDP成長率プラス1%",
          "GDP成長率マイナス1%"
        )
      ),

      nikkei = factor(
        nikkei,
        levels = c(
          "日経平均前月同期比変わらず",
          "日経平均前月同期比プラス1000円",
          "日経平均前月同期比マイナス1000円"
        )
      ),

      seats = factor(
        seats,
        levels = c("10以下", "10~49", "50~99", "100~199", "200以上")
      ),

      cpi = factor(
        cpi,
        levels = c(
          "CPI前期比±0ポイント",
          "CPI前期比プラス1ポイント",
          "CPI前期比マイナス1ポイント"
        )
      ),

      unemployment = factor(
        unemployment,
        levels = c(
          "失業率前期比±0%",
          "失業率前期比プラス1%",
          "失業率前期比マイナス1%"
        )
      ),

      party_n_f = factor(
        as.character(party_n),
        levels = c("2", "3", "4", "5")
      )
    )

  attr_terms <- c(
    "policy_position",
    "government_status",
    "gdp_growth",
    "nikkei",
    "seats",
    "cpi",
    "unemployment"
  )


  formula_nocov <- as.formula(
    paste("selected ~", paste(attr_terms, collapse = " + "))
  )

  run_amce_nocov <- function(dat) {
    feols(
      formula_nocov,
      data = dat,
      vcov = ~ ID
    )
  }

  models_by_party_n_nocov <- conjoint_all_m %>%
    split(.$party_n) %>%
    map(run_amce_nocov)

  capture.output(
    etable(models_by_party_n_nocov),
    file = file.path(output_dir, "amce_nocov_models.txt")
  )


  m_interaction <- feols(
    selected ~
      party_n_f *
      (
        policy_position +
          government_status +
          gdp_growth +
          nikkei +
          seats +
          cpi +
          unemployment
      ),
    data = conjoint_all_m,
    vcov = ~ ID
  )

  capture.output(
    summary(m_interaction),
    file = file.path(output_dir, "amce_interaction_model.txt")
  )


  tidy_fixest <- function(model) {
    ct <- as.data.frame(fixest::coeftable(model))
    ct$term <- rownames(ct)

    ct %>%
      as_tibble() %>%
      rename(
        estimate = Estimate,
        std.error = `Std. Error`,
        statistic = `t value`,
        p.value = `Pr(>|t|)`
      ) %>%
      mutate(
        conf.low = estimate - 1.96 * std.error,
        conf.high = estimate + 1.96 * std.error
      ) %>%
      select(
        term, estimate, std.error, statistic, p.value,
        conf.low, conf.high
      )
  }

  term_labels <- tribble(
    ~term, ~attribute, ~cue_type, ~label, ~order,

    "government_status与党",
    "与党/野党", "政党の手がかり", "与党", 1,

    "policy_position右派・保守的",
    "政策位置", "政党の手がかり", "右派・保守的", 2,

    "policy_position左派・革新的",
    "政策位置", "政党の手がかり", "左派・革新的", 3,

    "seats10~49",
    "議席数", "政党の手がかり", "議席数:10~49", 4,

    "seats50~99",
    "議席数", "政党の手がかり", "議席数:50~99", 5,

    "seats100~199",
    "議席数", "政党の手がかり", "議席数:100~199", 6,

    "seats200以上",
    "議席数", "政党の手がかり", "議席数:200以上", 7,

    "gdp_growthGDP成長率プラス1%",
    "GDP成長率", "経済の手がかり", "GDP:プラス1%", 8,

    "gdp_growthGDP成長率マイナス1%",
    "GDP成長率", "経済の手がかり", "GDP:マイナス1%", 9,

    "nikkei日経平均前月同期比プラス1000円",
    "日経平均", "経済の手がかり", "日経平均:プラス1000円", 10,

    "nikkei日経平均前月同期比マイナス1000円",
    "日経平均", "経済の手がかり", "日経平均:マイナス1000円", 11,

    "cpiCPI前期比プラス1ポイント",
    "CPI", "経済の手がかり", "CPI:プラス1ポイント", 12,

    "cpiCPI前期比マイナス1ポイント",
    "CPI", "経済の手がかり", "CPI:マイナス1ポイント", 13,

    "unemployment失業率前期比プラス1%",
    "失業率", "経済の手がかり", "失業率:プラス1%", 14,

    "unemployment失業率前期比マイナス1%",
    "失業率", "経済の手がかり", "失業率:マイナス1%", 15
  )

  attribute_order <- c(
    "与党/野党",
    "政策位置",
    "議席数",
    "GDP成長率",
    "日経平均",
    "CPI",
    "失業率"
  )

  label_order <- term_labels %>%
    arrange(order) %>%
    pull(label)

  make_amce_plot_df <- function(models) {
    imap_dfr(
      models,
      ~ tidy_fixest(.x) %>%
        mutate(party_n = as.character(.y))
    ) %>%
      left_join(term_labels, by = "term") %>%
      filter(!is.na(attribute)) %>%
      mutate(
        estimate_pp = estimate * 100,
        conf.low_pp = conf.low * 100,
        conf.high_pp = conf.high * 100,
        party_n = factor(
          party_n,
          levels = c("2", "3", "4", "5"),
          labels = c("2政党", "3政党", "4政党", "5政党")
        ),
        attribute = factor(attribute, levels = attribute_order),
        label = factor(label, levels = rev(label_order))
      )
  }

  amce_plot_nocov <- make_amce_plot_df(models_by_party_n_nocov)
  write_csv_safely(amce_plot_nocov, "amce_nocov_coefficients.csv")

  interaction_plot_df <- tidy_fixest(m_interaction) %>%
    filter(str_detect(term, "party_n_f[345]")) %>%
    mutate(
      party_n_code = str_extract(term, "party_n_f[345]"),
      party_n = str_remove(party_n_code, "party_n_f"),
      base_term = term %>%
        str_remove("party_n_f[345]:") %>%
        str_remove(":party_n_f[345]")
    ) %>%
    left_join(term_labels, by = c("base_term" = "term")) %>%
    filter(!is.na(attribute)) %>%
    mutate(
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,
      party_n_label = factor(
        party_n,
        levels = c("3", "4", "5"),
        labels = c("3政党", "4政党", "5政党")
      ),
      attribute = factor(attribute, levels = attribute_order),
      label = factor(label, levels = rev(label_order))
    )

  write_csv_safely(interaction_plot_df, "amce_interaction_coefficients.csv")


  recode_female_study1 <- function(x) {
    x_chr <- norm_text(x)
    x_num <- as_num(x_chr)

    case_when(
      str_detect(x_chr, "女性") | x_num == 1 ~ 1L,
      str_detect(x_chr, "男性") | x_num == 2 ~ 0L,
      TRUE ~ NA_integer_
    )
  }

  recode_college_grad_study1 <- function(x) {
    x_chr <- norm_text(x)
    x_num <- as_num(x_chr)

    case_when(
      str_detect(x_chr, "4年制大学|4年制大学|大学院") |
        x_num %in% c(4, 5) ~ 1L,
      str_detect(x_chr, "小学校|高校|高等専門|短期大学|専修学校") |
        x_num %in% c(1, 2, 3) ~ 0L,
      TRUE ~ NA_integer_
    )
  }

  recode_party_support_study1 <- function(x) {
    x_chr <- norm_text(x)
    x_num <- as_num(x_chr)

    case_when(
      str_detect(x_chr, "自由民主|自民") | x_num == 1 ~ "自由民主党",
      str_detect(x_chr, "立憲民主") | x_num == 2 ~ "立憲民主党",
      str_detect(x_chr, "公明") | x_num == 3 ~ "公明党",
      str_detect(x_chr, "維新") | x_num == 4 ~ "日本維新の会",
      str_detect(x_chr, "共産") | x_num == 5 ~ "日本共産党",
      str_detect(x_chr, "国民民主") | x_num == 6 ~ "国民民主党",
      str_detect(x_chr, "社会民主|社民") | x_num == 7 ~ "社会民主党",
      str_detect(x_chr, "れいわ") | x_num == 8 ~ "れいわ新選組",
      str_detect(x_chr, "その他") | x_num == 11 ~ "その他",
      str_detect(x_chr, "支持する政党はない|支持政党なし") |
        x_num == 12 ~ "支持政党なし",
      str_detect(x_chr, "わからない") | x_num == 13 ~ "わからない",
      str_detect(x_chr, "答えない|こたえない") | x_num == 14 ~ "答えない",
      TRUE ~ NA_character_
    )
  }

  gender_raw <- get_var(
    df,
    c("Q2.1", "Q2_1", "Q2.1.", "性別", "gender", "Gender")
  )

  age_raw <- get_var(
    df,
    c("Q2.2", "Q2_2", "Q2.2.", "年齢", "age", "Age")
  )

  education_raw <- get_var(
    df,
    c(
      "Q2.3", "Q2_3", "Q2.3.",
      "学歴", "教育歴", "最終学歴", "education", "Education"
    )
  )

  party_support_raw <- get_var(
    df,
    c("Q2.4", "Q2_4", "Q2.4.", "政党支持", "支持政党", "party_support")
  )

  income_gross_raw <- get_var(
    df,
    c("Q3.1_1", "Q3.1.1", "Q3_1_1", "税引き前世帯年収", "income_gross")
  )

  income_net_raw <- get_var(
    df,
    c("Q3.1_2", "Q3.1.2", "Q3_1_2", "手取りの年収", "income_net")
  )

  covar_id <- df %>%
    transmute(
      ID = as.character(ResponseId),
      female = recode_female_study1(gender_raw),
      age_raw_num = as_num(age_raw),
      college_grad = recode_college_grad_study1(education_raw),
      party_support = recode_party_support_study1(party_support_raw),
      party_support_f = factor_miss(party_support),
      income_gross = as_num(income_gross_raw),
      income_net = as_num(income_net_raw),
      income_gross_log = log1p(income_gross),
      income_net_log = log1p(income_net)
    ) %>%
    mutate(
      age = case_when(
        !is.na(age_raw_num) & age_raw_num >= 18 & age_raw_num <= 80 ~
          age_raw_num,
        !is.na(age_raw_num) & age_raw_num >= 1 & age_raw_num <= 63 ~
          age_raw_num + 17,
        TRUE ~ NA_real_
      )
    ) %>%
    semi_join(valid_ids %>% select(ID), by = "ID") %>%
    distinct(ID, .keep_all = TRUE)

  age_imp_obj <- mean_impute(covar_id$age)
  income_gross_imp_obj <- mean_impute(covar_id$income_gross_log)

  covar_id <- covar_id %>%
    mutate(
      female_imp = if_else(is.na(female), 0L, female),
      female_miss = as.integer(is.na(female)),

      college_grad_imp = if_else(is.na(college_grad), 0L, college_grad),
      college_grad_miss = as.integer(is.na(college_grad)),

      age_imp = age_imp_obj$value,
      age_miss = age_imp_obj$miss,

      income_gross_log_imp = income_gross_imp_obj$value,
      income_gross_log_miss = income_gross_imp_obj$miss
    )

  covariate_missing_summary <- covar_id %>%
    summarise(
      n_ids = n_distinct(ID),
      female_missing = sum(is.na(female)),
      age_missing = sum(is.na(age)),
      college_grad_missing = sum(is.na(college_grad)),
      income_gross_missing = sum(is.na(income_gross_log)),
      party_support_missing = sum(is.na(party_support))
    )

  print(covariate_missing_summary)
  write_csv_safely(covar_id, "respondent_covariates.csv")
  write_csv_safely(covariate_missing_summary, "covariate_missing_summary.csv")


  conjoint_all_cov <- conjoint_all_m %>%
    left_join(covar_id, by = "ID")

  covariate_terms <- c(
    "female_imp",
    "female_miss",
    "age_imp",
    "age_miss",
    "income_gross_log_imp",
    "income_gross_log_miss",
    "party_support_f"
  )

  if (use_education_covariate) {
    covariate_terms <- c(
      covariate_terms,
      "college_grad_imp",
      "college_grad_miss"
    )
  }

  has_variation <- function(dat, v) {
    if (!v %in% names(dat)) return(FALSE)
    dplyr::n_distinct(dat[[v]], na.rm = TRUE) > 1
  }

  covariate_terms_use <- covariate_terms[
    map_lgl(covariate_terms, ~ has_variation(conjoint_all_cov, .x))
  ]

  formula_cov <- as.formula(
    paste(
      "selected ~",
      paste(c(attr_terms, covariate_terms_use), collapse = " + ")
    )
  )

  run_amce_cov <- function(dat) {
    feols(
      formula_cov,
      data = dat,
      vcov = ~ ID
    )
  }

  models_by_party_n_cov <- conjoint_all_cov %>%
    split(.$party_n) %>%
    map(run_amce_cov)

  capture.output(
    etable(
      models_by_party_n_nocov,
      models_by_party_n_cov,
      headers = c(
        rep("共変量なし", length(models_by_party_n_nocov)),
        rep("共変量あり", length(models_by_party_n_cov))
      )
    ),
    file = file.path(output_dir, "amce_nocov_and_cov_models.txt")
  )

  amce_plot_cov <- make_amce_plot_df(models_by_party_n_cov)
  write_csv_safely(amce_plot_cov, "amce_cov_coefficients.csv")


  study_label <- "実験1(2023年)"

  term_labels_facet <- term_labels %>%
    mutate(
      attribute_facet = attribute
    )

  attribute_order_facet <- c(
    "与党/野党",
    "政策位置",
    "議席数",
    "GDP成長率",
    "日経平均",
    "CPI",
    "失業率"
  )

  make_amce_facet_df <- function(models) {
    imap_dfr(
      models,
      ~ tidy_fixest(.x) %>%
        mutate(party_n = as.character(.y))
    ) %>%
      left_join(term_labels_facet, by = "term") %>%
      filter(!is.na(attribute_facet)) %>%
      mutate(
        estimate_pp = estimate * 100,
        conf.low_pp = conf.low * 100,
        conf.high_pp = conf.high * 100,
        party_n = factor(
          party_n,
          levels = c("2", "3", "4", "5"),
          labels = c("2政党", "3政党", "4政党", "5政党")
        ),
        attribute_facet = factor(
          attribute_facet,
          levels = attribute_order_facet
        ),
        label = factor(
          label,
          levels = rev(label_order)
        )
      )
  }

  amce_plot_df_cov_facet <- make_amce_facet_df(models_by_party_n_cov)
  amce_plot_df_nocov_facet <- make_amce_facet_df(models_by_party_n_nocov)

  write_csv_safely(
    amce_plot_df_cov_facet,
    "amce_cov_facet_coefficients.csv"
  )

  write_csv_safely(
    amce_plot_df_nocov_facet,
    "amce_nocov_facet_coefficients.csv"
  )


  p_amce_cov_facet <- ggplot(
    amce_plot_df_cov_facet,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(width = 0.65),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.65),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute_facet ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) paste0(x, " pp"),
      breaks = seq(-12, 12, by = 2)
    ) +
    scale_shape_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = 16,
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = "solid",
        "3政党" = "dashed",
        "4政党" = "dotted",
        "5政党" = "dotdash"
      )
    ) +
    labs(
      x = "選択確率の変化",
      y = NULL
    ) +
    theme_bw(
      base_size = 12,
      base_family = "Yu Gothic"
    ) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 16
      ),
      plot.subtitle = element_text(size = 11),
      legend.position = "top",
      legend.title = element_text(face = "bold"),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(size = 9),
      axis.title.x = element_text(face = "bold")
    )

  print(p_amce_cov_facet)

  save_plot(
    "amce_cov_facet_model.png",
    p_amce_cov_facet,
    width = 10.5,
    height = 8.5
  )

  p_amce_cov_main <- p_amce_cov_facet


  make_heatmap_df <- function(amce_plot_df) {
    heat_df <- amce_plot_df %>%
      mutate(
        abs_amce = abs(estimate_pp),
        cue_type_code = case_when(
          cue_type == "政党の手がかり" ~ "party",
          cue_type == "経済の手がかり" ~ "economy",
          TRUE ~ "other"
        )
      ) %>%
      group_by(party_n) %>%
      mutate(
        rank_within_party = min_rank(desc(abs_amce)),
        n_in_col = n(),
        rank_score = if_else(
          n_in_col == 1,
          1,
          1 - (rank_within_party - 1) / (n_in_col - 1)
        )
      ) %>%
      ungroup()

    row_order_df <- heat_df %>%
      group_by(label, cue_type_code) %>%
      summarise(
        mean_abs_amce = mean(abs_amce, na.rm = TRUE),
        .groups = "drop"
      ) %>%
      arrange(desc(mean_abs_amce))

    row_levels <- as.character(row_order_df$label)

    heat_df <- heat_df %>%
      mutate(
        label = factor(
          as.character(label),
          levels = rev(row_levels)
        )
      )

    label_color_map <- row_order_df %>%
      mutate(
        label_markdown = case_when(
          cue_type_code == "party" ~
            paste0(
              "<span style='color:#111111;'>",
              label,
              "</span>"
            ),
          cue_type_code == "economy" ~
            paste0(
              "<span style='color:#8A8A8A;'>",
              label,
              "</span>"
            ),
          TRUE ~ as.character(label)
        )
      )

    label_markdown_vec <- setNames(
      label_color_map$label_markdown,
      as.character(label_color_map$label)
    )

    list(
      heat_df = heat_df,
      label_markdown_vec = label_markdown_vec
    )
  }

  plot_amce_heatmap <- function(
      heat_df,
      label_markdown_vec,
      with_rank = TRUE,
      title_text = NULL) {

    if (with_rank) {
      heat_df <- heat_df %>%
        mutate(
          cell_label = paste0(
            sprintf("%.1f", estimate_pp),
            "\n(",
            rank_within_party,
            "位)"
          )
        )

      text_size <- 3.0
      lineheight <- 0.9
    } else {
      heat_df <- heat_df %>%
        mutate(
          cell_label = sprintf("%.1f", estimate_pp)
        )

      text_size <- 3.4
      lineheight <- 1.0
    }

    ggplot(
      heat_df,
      aes(
        x = party_n,
        y = label,
        fill = rank_score
      )
    ) +
      geom_tile(
        color = "white",
        linewidth = 0.7
      ) +
      geom_text(
        aes(label = cell_label),
        size = text_size,
        fontface = "bold",
        color = "black",
        lineheight = lineheight
      ) +
      scale_y_discrete(
        labels = label_markdown_vec
      ) +
      scale_fill_gradient(
        low = "grey95",
        high = "grey15",
        limits = c(0, 1),
        breaks = c(0, 0.25, 0.50, 0.75, 1.00),
        labels = c("低", "", "", "", "高"),
        name = "列内順位\n(濃いほど高位)"
      ) +
      labs(
        title = title_text,
        x = "政党数選択肢",
        y = NULL
      ) +
      theme_bw(base_size = 12) +
      theme(
        legend.position = "right",
        panel.grid = element_blank(),
        plot.title = element_text(face = "bold"),
        axis.text.x = element_text(size = 10),
        axis.text.y = ggtext::element_markdown(size = 9),
        axis.title.y = element_blank()
      )
  }

  heatmap_input <- make_heatmap_df(amce_plot_cov)

  p_heat_amce_mixed <- plot_amce_heatmap(
    heatmap_input$heat_df,
    heatmap_input$label_markdown_vec,
    with_rank = FALSE,
    title_text = NULL
  )

  print(p_heat_amce_mixed)

  save_plot(
    "amce_heatmap_mixed_rank_colored_labels.png",
    p_heat_amce_mixed,
    width = 8.8,
    height = 8.8
  )

  p_heat_amce_mixed_ranklabel <- plot_amce_heatmap(
    heatmap_input$heat_df,
    heatmap_input$label_markdown_vec,
    with_rank = TRUE,
    title_text = NULL
  )

  print(p_heat_amce_mixed_ranklabel)

  save_plot(
    "amce_heatmap_mixed_rank_colored_labels_withrank.png",
    p_heat_amce_mixed_ranklabel,
    width = 8.8,
    height = 8.8
  )

  p_heat_amce <- p_heat_amce_mixed
  p_heat_amce_rank <- p_heat_amce_mixed_ranklabel


  p_amce_facet_nocov <- ggplot(
    amce_plot_df_nocov_facet,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(width = 0.65),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.65),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute_facet ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) paste0(x, " pp"),
      breaks = seq(-12, 12, by = 2)
    ) +
    scale_shape_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = 16,
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = "solid",
        "3政党" = "dashed",
        "4政党" = "dotted",
        "5政党" = "dotdash"
      )
    ) +
    labs(
      x = "選択確率の変化",
      y = NULL
    ) +
    theme_bw(base_size = 12) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 16
      ),
      plot.subtitle = element_text(size = 11),
      legend.position = "top",
      legend.title = element_text(face = "bold"),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(size = 9),
      axis.title.x = element_text(face = "bold")
    )

  print(p_amce_facet_nocov)

  save_plot(
    "amce_facet_nocov.png",
    p_amce_facet_nocov,
    width = 10.5,
    height = 9
  )

  p_amce_nocov_appendix <- p_amce_facet_nocov


  p_interaction <- ggplot(
    interaction_plot_df,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n_label,
      linetype = party_n_label,
      group = party_n_label
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(width = 0.65),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.65),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) paste0(x, " pp"),
      breaks = seq(-8, 8, by = 2)
    ) +
    scale_shape_manual(
      name = "2政党の場合との比較",
      values = c(
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      name = "2政党の場合との比較",
      values = c(
        "3政党" = "dashed",
        "4政党" = "dotted",
        "5政党" = "dotdash"
      )
    ) +
    labs(
      x = "2政党条件との差",
      y = NULL
    ) +
    theme_bw(base_size = 12) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 15
      ),
      plot.subtitle = element_text(size = 11),
      legend.position = "top",
      legend.title = element_text(face = "bold"),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(size = 9),
      axis.title.x = element_text(face = "bold")
    )

  print(p_interaction)

  save_plot(
    "amce_interaction_difference_from_2party.png",
    p_interaction,
    width = 10.5,
    height = 9
  )


  conjoint_clogit <- conjoint_all_m %>%
    mutate(
      selected = as.integer(selected),
      ID = as.character(ID),
      task_id = factor(task_id),
      policy_position = relevel_if_present(
        policy_position,
        "中道"
      ),
      government_status = relevel_if_present(
        government_status,
        "野党"
      ),
      gdp_growth = relevel_if_present(
        gdp_growth,
        "GDP成長率±0%"
      ),
      nikkei = relevel_if_present(
        nikkei,
        "日経平均前月同期比変わらず"
      ),
      seats = relevel_if_present(
        seats,
        "10以下"
      ),
      cpi = relevel_if_present(
        cpi,
        "CPI前期比±0ポイント"
      ),
      unemployment = relevel_if_present(
        unemployment,
        "失業率前期比±0%"
      )
    )

  formula_clogit_nocov <- as.formula(
    paste0(
      "selected ~ ",
      paste(attr_terms, collapse = " + "),
      " + strata(task_id) + cluster(ID)"
    )
  )

  run_clogit_nocov <- function(dat) {
    survival::clogit(
      formula_clogit_nocov,
      data = dat,
      method = "efron"
    )
  }

  models_clogit_nocov <- conjoint_clogit %>%
    split(.$party_n) %>%
    map(run_clogit_nocov)

  capture.output(
    lapply(models_clogit_nocov, summary),
    file = file.path(
      output_dir,
      "conditional_logit_models.txt"
    )
  )

  tidy_clogit <- function(model) {
    s <- summary(model)
    ct <- as.data.frame(s$coefficients)
    ct$term <- rownames(ct)

    se_col <- if ("robust se" %in% names(ct)) {
      "robust se"
    } else if ("se(coef)" %in% names(ct)) {
      "se(coef)"
    } else {
      stop("Check clogit")
    }

    p_col <- if ("Pr(>|z|)" %in% names(ct)) {
      "Pr(>|z|)"
    } else if ("Pr(>|t|)" %in% names(ct)) {
      "Pr(>|t|)"
    } else {
      NA_character_
    }

    ct %>%
      as_tibble() %>%
      transmute(
        term = term,
        estimate = coef,
        std.error = .data[[se_col]],
        p.value = if (!is.na(p_col)) {
          .data[[p_col]]
        } else {
          NA_real_
        },
        conf.low = estimate - 1.96 * std.error,
        conf.high = estimate + 1.96 * std.error,
        odds_ratio = exp(estimate),
        odds_ratio_low = exp(conf.low),
        odds_ratio_high = exp(conf.high)
      )
  }

  clogit_plot_df <- imap_dfr(
    models_clogit_nocov,
    ~ tidy_clogit(.x) %>%
      mutate(party_n = as.character(.y))
  ) %>%
    left_join(term_labels, by = "term") %>%
    filter(!is.na(attribute)) %>%
    mutate(
      party_n = factor(
        party_n,
        levels = c("2", "3", "4", "5"),
        labels = c("2政党", "3政党", "4政党", "5政党")
      ),
      label = factor(
        label,
        levels = rev(label_order)
      )
    )

  write_csv_safely(
    clogit_plot_df,
    "conditional_logit_coefficients.csv"
  )


  p_clogit_or <- ggplot(
    clogit_plot_df,
    aes(
      x = odds_ratio,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 1,
      linetype = "dashed",
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = odds_ratio_low,
        xmax = odds_ratio_high
      ),
      position = position_dodge(width = 0.72),
      height = 0.15,
      linewidth = 0.45,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.72),
      size = 2.4,
      stroke = 0.7,
      color = "black"
    ) +
    scale_x_log10(
      breaks = c(
        0.6,
        0.8,
        1.0,
        1.25,
        1.5,
        2.0
      ),
      labels = c(
        "0.6",
        "0.8",
        "1.0",
        "1.25",
        "1.5",
        "2.0"
      )
    ) +
    scale_shape_manual(
      values = c(
        "2政党" = 16,
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      values = c(
        "2政党" = "solid",
        "3政党" = "dashed",
        "4政党" = "dotdash",
        "5政党" = "twodash"
      )
    ) +
    labs(
      x = "オッズ比",
      y = NULL,
      shape = "政党数選択肢",
      linetype = "政党数選択肢"
    ) +
    theme_bw(base_size = 12) +
    theme(
      legend.position = "bottom",
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      plot.title = element_text(face = "bold"),
      axis.text.y = element_text(size = 9)
    )

  print(p_clogit_or)

  save_plot(
    "clogit_oddsratio_nocov.png",
    p_clogit_or,
    width = 10.5,
    height = 8.5
  )


  relative_cue_map <- c(
    policy_position = "party",
    government_status = "party",
    seats = "party",
    gdp_growth = "economic",
    nikkei = "economic",
    cpi = "economic",
    unemployment = "economic"
  )

  mean_absolute_pairwise_difference <- function(x) {
    x <- x[is.finite(x)]

    if (length(x) < 2) {
      return(NA_real_)
    }

    pairwise_differences <- combn(
      x,
      2,
      FUN = function(z) abs(z[1] - z[2])
    )

    mean(pairwise_differences)
  }

  linear_slope <- function(y, x) {
    keep <- is.finite(y) & is.finite(x)
    y <- y[keep]
    x <- x[keep]

    if (length(y) < 2 || length(unique(x)) < 2) {
      return(NA_real_)
    }

    unname(coef(lm(y ~ x))[2])
  }

  bootstrap_two_sided_p <- function(x) {
    x <- x[is.finite(x)]
    B_valid <- length(x)

    if (B_valid == 0) {
      return(NA_real_)
    }

    p_lower <- (1 + sum(x <= 0)) / (B_valid + 1)
    p_upper <- (1 + sum(x >= 0)) / (B_valid + 1)

    min(1, 2 * min(p_lower, p_upper))
  }

  safe_quantile <- function(x, probability) {
    x <- x[is.finite(x)]

    if (length(x) == 0) {
      return(NA_real_)
    }

    unname(
      quantile(
        x,
        probs = probability,
        type = 6,
        na.rm = TRUE
      )
    )
  }

  prepare_relative_cue_analysis <- function(data, cue_map) {
    attributes <- names(cue_map)

    required_columns <- c(
      "ID",
      "party_n",
      "selected",
      attributes
    )

    missing_columns <- setdiff(
      required_columns,
      names(data)
    )

    if (length(missing_columns) > 0) {
      stop("Check relative weight")
    }

    if (!all(unname(cue_map) %in% c("party", "economic"))) {
      stop("Check relative weight")
    }

    analysis_data <- data %>%
      select(
        ID,
        party_n,
        selected,
        all_of(attributes)
      ) %>%
      mutate(
        ID = as.character(ID),
        party_n = as.integer(as.character(party_n)),
        selected = as.integer(selected),
        across(
          all_of(attributes),
          as.character
        )
      ) %>%
      filter(
        !is.na(ID),
        party_n %in% 2:5,
        selected %in% c(0L, 1L)
      )

    observed_conditions <- sort(
      unique(analysis_data$party_n)
    )

    if (!identical(observed_conditions, 2:5)) {
      stop("Check")
    }

    long_data <- analysis_data %>%
      pivot_longer(
        cols = all_of(attributes),
        names_to = "attribute",
        values_to = "level"
      ) %>%
      filter(
        !is.na(level),
        level != ""
      )

    expected_cells <- long_data %>%
      distinct(
        attribute,
        level
      ) %>%
      mutate(
        attribute_order = match(
          attribute,
          attributes
        )
      ) %>%
      arrange(
        attribute_order,
        attribute,
        level
      ) %>%
      select(-attribute_order) %>%
      mutate(
        cell_key = paste(
          attribute,
          level,
          sep = "\r"
        )
      )

    respondent_cell <- long_data %>%
      group_by(
        party_n,
        ID,
        attribute,
        level
      ) %>%
      summarise(
        y_sum = sum(selected),
        n_obs = n(),
        .groups = "drop"
      ) %>%
      mutate(
        cell_key = paste(
          attribute,
          level,
          sep = "\r"
        )
      )

    condition_objects <- lapply(
      2:5,
      function(n_value) {
        condition_data <- respondent_cell %>%
          filter(
            party_n == n_value
          )

        id_values <- sort(
          unique(condition_data$ID)
        )
        n_ids <- length(id_values)
        n_cells <- nrow(expected_cells)

        if (n_ids == 0) {
          stop("Check")
        }

        y_matrix <- matrix(
          0,
          nrow = n_ids,
          ncol = n_cells,
          dimnames = list(
            id_values,
            expected_cells$cell_key
          )
        )

        n_matrix <- matrix(
          0,
          nrow = n_ids,
          ncol = n_cells,
          dimnames = list(
            id_values,
            expected_cells$cell_key
          )
        )

        row_index <- match(
          condition_data$ID,
          id_values
        )
        column_index <- match(
          condition_data$cell_key,
          expected_cells$cell_key
        )

        y_matrix[cbind(row_index, column_index)] <-
          condition_data$y_sum
        n_matrix[cbind(row_index, column_index)] <-
          condition_data$n_obs

        if (any(colSums(n_matrix) == 0)) {
          missing_cells <- expected_cells$cell_key[
            colSums(n_matrix) == 0
          ]

          stop("Check attributes")
        }

        list(
          party_n = n_value,
          ids = id_values,
          cell_info = expected_cells,
          y_matrix = y_matrix,
          n_matrix = n_matrix
        )
      }
    )

    names(condition_objects) <- as.character(2:5)

    list(
      cue_map = cue_map,
      attributes = attributes,
      conditions = condition_objects
    )
  }

  estimate_relative_cue_indices <- function(
      prepared,
      cluster_weights = NULL
  ) {
    condition_results <- lapply(
      names(prepared$conditions),
      function(condition_name) {
        object <- prepared$conditions[[condition_name]]

        if (is.null(cluster_weights)) {
          weights <- rep(
            1,
            length(object$ids)
          )
        } else {
          weights <- cluster_weights[[condition_name]]
        }

        if (length(weights) != length(object$ids)) {
          stop("Check")
        }

        numerator <- as.numeric(
          crossprod(
            weights,
            object$y_matrix
          )
        )

        denominator <- as.numeric(
          crossprod(
            weights,
            object$n_matrix
          )
        )

        if (any(denominator <= 0)) {
          stop("Check attributes")
        }

        marginal_means <- numerator / denominator

        mm_table <- object$cell_info %>%
          transmute(
            party_n = object$party_n,
            attribute,
            level,
            marginal_mean = marginal_means
          )

        attribute_table <- mm_table %>%
          group_by(
            party_n,
            attribute
          ) %>%
          summarise(
            importance_pairwise =
              mean_absolute_pairwise_difference(
                marginal_mean
              ),
            n_levels = n(),
            .groups = "drop"
          ) %>%
          mutate(
            cue_family = unname(
              prepared$cue_map[attribute]
            ),
            baseline_selection_probability = 1 / party_n,
            importance_pairwise_adjusted =
              importance_pairwise /
                baseline_selection_probability
          )

        cue_table_long <- attribute_table %>%
          group_by(
            party_n,
            cue_family
          ) %>%
          summarise(
            importance_pairwise = mean(
              importance_pairwise,
              na.rm = TRUE
            ),
            importance_pairwise_adjusted = mean(
              importance_pairwise_adjusted,
              na.rm = TRUE
            ),
            .groups = "drop"
          )

        party_table <- cue_table_long %>%
          filter(
            cue_family == "party"
          ) %>%
          transmute(
            party_n,
            party_importance_pairwise =
              importance_pairwise,
            party_importance_pairwise_adjusted =
              importance_pairwise_adjusted
          )

        economic_table <- cue_table_long %>%
          filter(
            cue_family == "economic"
          ) %>%
          transmute(
            party_n,
            economic_importance_pairwise =
              importance_pairwise,
            economic_importance_pairwise_adjusted =
              importance_pairwise_adjusted
          )

        cue_table <- full_join(
          party_table,
          economic_table,
          by = "party_n"
        ) %>%
          mutate(
            baseline_selection_probability = 1 / party_n,

            total_importance_pairwise =
              party_importance_pairwise +
              economic_importance_pairwise,

            total_importance_pairwise_adjusted =
              party_importance_pairwise_adjusted +
              economic_importance_pairwise_adjusted,

            relative_party_weight_pairwise = if_else(
              total_importance_pairwise > 0,
              party_importance_pairwise /
                total_importance_pairwise,
              NA_real_
            ),

            relative_economic_weight_pairwise =
              1 - relative_party_weight_pairwise,

            relative_party_weight_pairwise_adjusted = if_else(
              total_importance_pairwise_adjusted > 0,
              party_importance_pairwise_adjusted /
                total_importance_pairwise_adjusted,
              NA_real_
            ),

            relative_economic_weight_pairwise_adjusted =
              1 - relative_party_weight_pairwise_adjusted,

            adjustment_identity_difference =
              relative_party_weight_pairwise_adjusted -
                relative_party_weight_pairwise
          )

        if (
          any(
            abs(cue_table$adjustment_identity_difference) > 1e-10,
            na.rm = TRUE
          )
        ) {
          stop("Check relative weight")
        }

        list(
          marginal_means = mm_table,
          attribute_importance = attribute_table,
          cue_importance = cue_table
        )
      }
    )

    list(
      marginal_means = bind_rows(
        lapply(
          condition_results,
          function(x) x$marginal_means
        )
      ),
      attribute_importance = bind_rows(
        lapply(
          condition_results,
          function(x) x$attribute_importance
        )
      ),
      cue_importance = bind_rows(
        lapply(
          condition_results,
          function(x) x$cue_importance
        )
      ) %>%
        arrange(party_n)
    )
  }

  estimate_relative_cue_slopes <- function(cue_importance) {
    cue_importance <- cue_importance %>%
      arrange(party_n)

    if (!identical(cue_importance$party_n, 2:5)) {
      stop("Check relative weight")
    }

    x <- cue_importance$party_n

    c(
      relative_party_weight_pairwise =
        linear_slope(
          cue_importance$relative_party_weight_pairwise,
          x
        ),

      party_importance_pairwise =
        linear_slope(
          cue_importance$party_importance_pairwise,
          x
        ),

      economic_importance_pairwise =
        linear_slope(
          cue_importance$economic_importance_pairwise,
          x
        ),

      party_importance_pairwise_adjusted =
        linear_slope(
          cue_importance$party_importance_pairwise_adjusted,
          x
        ),

      economic_importance_pairwise_adjusted =
        linear_slope(
          cue_importance$economic_importance_pairwise_adjusted,
          x
        )
    )
  }

  run_relative_cue_bootstrap <- function(
      prepared,
      B,
      seed,
      progress_every = 100
  ) {
    set.seed(seed)

    condition_results <- vector(
      "list",
      B
    )

    slope_names <- c(
      "relative_party_weight_pairwise",
      "party_importance_pairwise",
      "economic_importance_pairwise",
      "party_importance_pairwise_adjusted",
      "economic_importance_pairwise_adjusted"
    )

    slope_matrix <- matrix(
      NA_real_,
      nrow = B,
      ncol = length(slope_names),
      dimnames = list(
        NULL,
        slope_names
      )
    )

    for (b in seq_len(B)) {
      cluster_weights <- lapply(
        prepared$conditions,
        function(object) {
          n_ids <- length(object$ids)

          sampled_positions <- sample.int(
            n = n_ids,
            size = n_ids,
            replace = TRUE
          )

          tabulate(
            sampled_positions,
            nbins = n_ids
          )
        }
      )

      bootstrap_estimates <- estimate_relative_cue_indices(
        prepared = prepared,
        cluster_weights = cluster_weights
      )

      condition_results[[b]] <-
        bootstrap_estimates$cue_importance %>%
        select(
          party_n,
          party_importance_pairwise,
          economic_importance_pairwise,
          party_importance_pairwise_adjusted,
          economic_importance_pairwise_adjusted,
          relative_party_weight_pairwise
        ) %>%
        mutate(
          bootstrap_replication = b,
          .before = 1
        )

      slope_matrix[b, ] <- estimate_relative_cue_slopes(
        bootstrap_estimates$cue_importance
      )

      if (
        progress_every > 0 &&
        (b %% progress_every == 0 || b == B)
      ) {
        message("Bootstrap: ", b, "/", B)
      }
    }

    list(
      condition_estimates = bind_rows(
        condition_results
      ),
      slopes = as_tibble(
        slope_matrix
      ) %>%
        mutate(
          bootstrap_replication = row_number(),
          .before = 1
        )
    )
  }

  summarise_condition_intervals <- function(
      observed_cue_importance,
      bootstrap_condition_results
  ) {
    statistics <- c(
      "party_importance_pairwise",
      "economic_importance_pairwise",
      "party_importance_pairwise_adjusted",
      "economic_importance_pairwise_adjusted",
      "relative_party_weight_pairwise"
    )

    observed_long <- observed_cue_importance %>%
      select(
        party_n,
        all_of(statistics)
      ) %>%
      pivot_longer(
        cols = all_of(statistics),
        names_to = "statistic",
        values_to = "estimate"
      )

    bootstrap_long <- bootstrap_condition_results %>%
      pivot_longer(
        cols = all_of(statistics),
        names_to = "statistic",
        values_to = "value"
      ) %>%
      group_by(
        party_n,
        statistic
      ) %>%
      summarise(
        conf_low = safe_quantile(
          value,
          0.025
        ),
        conf_high = safe_quantile(
          value,
          0.975
        ),
        .groups = "drop"
      )

    observed_long %>%
      left_join(
        bootstrap_long,
        by = c(
          "party_n",
          "statistic"
        )
      )
  }

  summarise_slope_inference <- function(
      observed_slopes,
      bootstrap_slopes
  ) {
    statistic_names <- names(observed_slopes)

    map_dfr(
      statistic_names,
      function(statistic_name) {
        bootstrap_values <- bootstrap_slopes[[statistic_name]]
        bootstrap_values <- bootstrap_values[
          is.finite(bootstrap_values)
        ]

        expected_direction <- case_when(
          statistic_name ==
            "economic_importance_pairwise" ~ "negative",
          statistic_name %in% c(
            "party_importance_pairwise",
            "relative_party_weight_pairwise",
            "party_importance_pairwise_adjusted"
          ) ~ "positive",
          TRUE ~ "none"
        )

        analysis_role <- case_when(
          statistic_name %in% c(
            "party_importance_pairwise_adjusted",
            "economic_importance_pairwise_adjusted"
          ) ~ "exploratory_choice_set_adjusted",
          statistic_name == "relative_party_weight_pairwise" ~
            "derived_relative_share",
          TRUE ~ "manuscript_primary_unadjusted"
        )

        estimate <- unname(
          observed_slopes[[statistic_name]]
        )

        tibble(
          study = "Study 1",
          statistic = statistic_name,
          estimate = estimate,
          conf_low = safe_quantile(
            bootstrap_values,
            0.025
          ),
          conf_high = safe_quantile(
            bootstrap_values,
            0.975
          ),
          p_value_two_sided =
            bootstrap_two_sided_p(
              bootstrap_values
            ),
          expected_direction = expected_direction,
          analysis_role = analysis_role,
          estimate_in_expected_direction = case_when(
            expected_direction == "positive" ~ estimate > 0,
            expected_direction == "negative" ~ estimate < 0,
            TRUE ~ NA
          )
        )
      }
    )
  }

  relative_cue_prepared <- prepare_relative_cue_analysis(
    data = conjoint_all_m,
    cue_map = relative_cue_map
  )

  relative_cue_observed <- estimate_relative_cue_indices(
    prepared = relative_cue_prepared
  )

  relative_cue_observed_slopes <- estimate_relative_cue_slopes(
    relative_cue_observed$cue_importance
  )

  write_csv_safely(
    relative_cue_observed$marginal_means,
    "study1_relative_cue_marginal_means.csv"
  )

  write_csv_safely(
    relative_cue_observed$attribute_importance,
    "study1_relative_cue_attribute_importance.csv"
  )

  write_csv_safely(
    relative_cue_observed$cue_importance,
    "study1_relative_cue_importance_and_weight.csv"
  )

  relative_condition_bootstrap_file <- file.path(
    output_dir,
    paste0(
      "study1_relative_cue_condition_bootstrap_",
      unified_config$cue_importance_metric_version,
      "_B",
      relative_cue_bootstrap_B,
      ".csv"
    )
  )

  relative_slope_bootstrap_file <- file.path(
    output_dir,
    paste0(
      "study1_relative_cue_slope_bootstrap_",
      unified_config$cue_importance_metric_version,
      "_B",
      relative_cue_bootstrap_B,
      ".csv"
    )
  )

  use_saved_relative_bootstrap <-
    !rerun_relative_cue_bootstrap &&
    file.exists(relative_condition_bootstrap_file) &&
    file.exists(relative_slope_bootstrap_file)

  if (use_saved_relative_bootstrap) {
    message("Bootstrap cache")

    relative_cue_condition_bootstrap <- readr::read_csv(
      relative_condition_bootstrap_file,
      show_col_types = FALSE
    )

    relative_cue_slope_bootstrap <- readr::read_csv(
      relative_slope_bootstrap_file,
      show_col_types = FALSE
    )

    saved_B_condition <- n_distinct(
      relative_cue_condition_bootstrap$bootstrap_replication
    )
    saved_B_slope <- n_distinct(
      relative_cue_slope_bootstrap$bootstrap_replication
    )

    if (
      saved_B_condition != relative_cue_bootstrap_B ||
      saved_B_slope != relative_cue_bootstrap_B
    ) {
      message("Bootstrap cache")
      use_saved_relative_bootstrap <- FALSE
    }
  }

  if (!use_saved_relative_bootstrap) {
    relative_cue_bootstrap <- run_relative_cue_bootstrap(
      prepared = relative_cue_prepared,
      B = relative_cue_bootstrap_B,
      seed = relative_cue_bootstrap_seed,
      progress_every = relative_cue_bootstrap_progress_every
    )

    relative_cue_condition_bootstrap <-
      relative_cue_bootstrap$condition_estimates

    relative_cue_slope_bootstrap <-
      relative_cue_bootstrap$slopes

    readr::write_csv(
      relative_cue_condition_bootstrap,
      relative_condition_bootstrap_file
    )

    readr::write_csv(
      relative_cue_slope_bootstrap,
      relative_slope_bootstrap_file
    )
  }

  relative_cue_condition_intervals <- summarise_condition_intervals(
    observed_cue_importance =
      relative_cue_observed$cue_importance,
    bootstrap_condition_results =
      relative_cue_condition_bootstrap
  )

  relative_cue_slope_inference <- summarise_slope_inference(
    observed_slopes =
      relative_cue_observed_slopes,
    bootstrap_slopes =
      relative_cue_slope_bootstrap
  )

  write_csv_safely(
    relative_cue_condition_intervals,
    "study1_relative_cue_condition_intervals.csv"
  )

  write_csv_safely(
    relative_cue_slope_inference,
    "study1_relative_cue_slope_inference.csv"
  )

  relative_cue_primary_result <- relative_cue_slope_inference %>%
    filter(
      statistic ==
        "relative_party_weight_pairwise"
    )

  cat("\nStudy 1:相対比重の線形傾向\n")
  print(relative_cue_primary_result)


  relative_x_offset <- 0.075

  relative_panel_a_data <- relative_cue_condition_intervals %>%
    filter(
      statistic %in% c(
        "party_importance_pairwise",
        "economic_importance_pairwise"
      )
    ) %>%
    mutate(
      cue_family = recode(
        statistic,
        party_importance_pairwise = "政党手がかり",
        economic_importance_pairwise = "経済手がかり"
      ),
      cue_family = factor(
        cue_family,
        levels = c(
          "政党手がかり",
          "経済手がかり"
        )
      ),
      x_plot = case_when(
        cue_family == "政党手がかり" ~
          party_n + relative_x_offset,
        cue_family == "経済手がかり" ~
          party_n - relative_x_offset,
        TRUE ~ as.numeric(party_n)
      ),
      value_label = sprintf(
        "%.3f",
        estimate
      )
    )

  relative_panel_b_data <- relative_cue_condition_intervals %>%
    filter(
      statistic ==
        "relative_party_weight_pairwise"
    ) %>%
    mutate(
      value_label = sprintf(
        "%.1f%%",
        100 * estimate
      )
    )

  relative_adjusted_label_map <- relative_panel_a_data %>%
    distinct(
      statistic,
      cue_family
    ) %>%
    mutate(
      statistic = paste0(
        statistic,
        "_adjusted"
      ),
      cue_family = as.character(
        cue_family
      )
    )

  relative_panel_adjusted_data <- relative_cue_condition_intervals %>%
    filter(
      statistic %in% c(
        "party_importance_pairwise_adjusted",
        "economic_importance_pairwise_adjusted"
      )
    ) %>%
    left_join(
      relative_adjusted_label_map,
      by = "statistic"
    ) %>%
    mutate(
      cue_family = factor(
        cue_family,
        levels = levels(
          relative_panel_a_data$cue_family
        )
      ),
      x_plot = if_else(
        as.integer(cue_family) == 1L,
        party_n + relative_x_offset,
        party_n - relative_x_offset
      ),
      value_label = sprintf(
        "%.1f%%",
        100 * estimate
      )
    )

  relative_condition_suffix <- if (
    "政党名手がかり" %in%
      levels(relative_panel_a_data$cue_family)
  ) {
    "選択肢"
  } else {
    "政党"
  }

  relative_condition_axis_title <- if (
    relative_condition_suffix == "選択肢"
  ) {
    "政治経済状況の選択肢数"
  } else {
    "政党選択肢数"
  }

  relative_figure_font_family <- if (
    .Platform$OS.type == "windows"
  ) {
    "Yu Gothic"
  } else {
    "sans"
  }

  relative_theme_japanese_bw <- theme_bw(
    base_size = 12,
    base_family = relative_figure_font_family
  ) +
    theme(
      panel.grid.minor = element_blank(),
      panel.grid.major = element_line(
        linewidth = 0.30,
        color = "grey88"
      ),
      panel.border = element_rect(
        linewidth = 0.65,
        color = "black"
      ),
      axis.text = element_text(
        color = "black"
      ),
      axis.title = element_text(
        color = "black"
      ),
      plot.title = element_text(
        size = 12.5,
        face = "bold",
        hjust = 0
      ),
      plot.subtitle = element_text(
        size = 9.5,
        hjust = 0,
        margin = margin(
          b = 8
        )
      ),
      legend.position = "top",
      legend.justification = "center",
      legend.key.width = grid::unit(
        1.25,
        "cm"
      ),
      plot.margin = margin(
        8,
        10,
        8,
        8
      )
    )

  relative_panel_a <- ggplot(
    relative_panel_a_data,
    aes(
      x = x_plot,
      y = estimate,
      group = cue_family,
      linetype = cue_family
    )
  ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_linetype_manual(
      values = c(
        "政党手がかり" = "solid",
        "経済手がかり" = "dashed"
      )
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        "政党"
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      labels = label_number(
        accuracy = 0.005
      ),
      expand = expansion(
        mult = c(
          0.07,
          0.10
        )
      )
    ) +
    labs(
      title = "A:両手がかりの絶対的重要度",
      subtitle = "",
      x = "政党選択肢数",
      y = "手がかり重要度",
      linetype = NULL
    ) +
    guides(
      linetype = guide_legend(
        override.aes = list(
          linewidth = 0.90
        )
      )
    ) +
    relative_theme_japanese_bw

  relative_adjusted_linetypes <- setNames(
    c(
      "solid",
      "dashed"
    ),
    levels(
      relative_panel_adjusted_data$cue_family
    )
  )

  relative_panel_adjusted <- ggplot(
    relative_panel_adjusted_data,
    aes(
      x = x_plot,
      y = estimate,
      group = cue_family,
      linetype = cue_family
    )
  ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_linetype_manual(
      values = relative_adjusted_linetypes
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        relative_condition_suffix
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      labels = label_percent(
        accuracy = 1
      ),
      expand = expansion(
        mult = c(
          0.07,
          0.10
        )
      )
    ) +
    labs(
      title = "A:選択肢数調整済み重要度",
      subtitle =
        "未調整重要度 ÷ 平均選択確率(1/選択肢数)",
      x = relative_condition_axis_title,
      y = "平均選択確率に対する水準間差",
      linetype = NULL
    ) +
    guides(
      linetype = guide_legend(
        override.aes = list(
          linewidth = 0.90
        )
      )
    ) +
    relative_theme_japanese_bw

  relative_b_range <- range(
    c(
      relative_panel_b_data$conf_low,
      relative_panel_b_data$conf_high,
      0.5
    ),
    na.rm = TRUE
  )

  relative_b_padding <- max(
    0.025,
    0.10 * diff(relative_b_range)
  )

  relative_b_lower <- max(
    0,
    floor(
      20 *
        (relative_b_range[1] - relative_b_padding)
    ) / 20
  )

  relative_b_upper <- min(
    1,
    ceiling(
      20 *
        (relative_b_range[2] + relative_b_padding)
    ) / 20
  )

  if (relative_b_lower >= relative_b_upper) {
    relative_b_lower <- max(
      0,
      relative_b_lower - 0.05
    )
    relative_b_upper <- min(
      1,
      relative_b_upper + 0.05
    )
  }

  relative_panel_b <- ggplot(
    relative_panel_b_data,
    aes(
      x = party_n,
      y = estimate
    )
  ) +
    geom_hline(
      yintercept = 0.5,
      linetype = "dashed",
      linewidth = 0.55,
      color = "black"
    ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        "政党"
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      breaks = seq(
        relative_b_lower,
        relative_b_upper,
        by = 0.05
      ),
      labels = label_percent(
        accuracy = 1
      ),
      expand = expansion(
        mult = c(
          0.05,
          0.08
        )
      )
    ) +
    coord_cartesian(
      ylim = c(
        relative_b_lower,
        relative_b_upper
      )
    ) +
    labs(
      title = "B:相対的な政党手がかりの比重",
      subtitle =
        "政党手がかり重要度 ÷(政党手がかり重要度+経済手がかり重要度)",
      x = "政党選択肢数",
      y = "相対的な政党手がかり比重"
    ) +
    relative_theme_japanese_bw +
    theme(
      legend.position = "none"
    )

  relative_panel_c <- relative_panel_b +
    labs(
      title = paste0(
        "B:相対的な",
        levels(relative_panel_a_data$cue_family)[1],
        "の比重"
      )
    )

  figure_relative_weight_jp <- (
    relative_panel_a |
      relative_panel_b
  ) +
    patchwork::plot_layout(
      widths = c(
        1,
        1
      )
    )

  print(
    figure_relative_weight_jp
  )

  save_plot(
    "fig_study1_relative_cue_weight_jp_bw.png",
    figure_relative_weight_jp,
    width = 11.2,
    height = 5.4,
    dpi = 400
  )

  ggsave(
    filename = file.path(
      output_dir,
      "fig_study1_relative_cue_weight_jp_bw.pdf"
    ),
    plot = figure_relative_weight_jp,
    width = 11.2,
    height = 5.4,
    device = grDevices::cairo_pdf,
    bg = "white"
  )

  figure_relative_weight_adjusted_jp <- (
    relative_panel_adjusted |
      relative_panel_c
  ) +
    patchwork::plot_layout(
      widths = c(
        1,
        1
      )
    )

  print(
    figure_relative_weight_adjusted_jp
  )

  relative_adjusted_figure_stub <- paste0(
    "fig_study",
    stringr::str_extract(
      study_label,
      "[123]"
    ),
    "_relative_cue_weight_choice_set_adjusted_jp_bw"
  )

  save_plot(
    paste0(
      relative_adjusted_figure_stub,
      ".png"
    ),
    figure_relative_weight_adjusted_jp,
    width = 11.2,
    height = 5.4,
    dpi = 400
  )

  ggsave(
    filename = file.path(
      output_dir,
      paste0(
        relative_adjusted_figure_stub,
        ".pdf"
      )
    ),
    plot = figure_relative_weight_adjusted_jp,
    width = 11.2,
    height = 5.4,
    device = grDevices::cairo_pdf,
    bg = "white"
  )

  relative_cue_results <- list(
    prepared = relative_cue_prepared,
    marginal_means =
      relative_cue_observed$marginal_means,
    attribute_importance =
      relative_cue_observed$attribute_importance,
    cue_importance =
      relative_cue_observed$cue_importance,
    observed_slopes =
      relative_cue_observed_slopes,
    condition_bootstrap =
      relative_cue_condition_bootstrap,
    slope_bootstrap =
      relative_cue_slope_bootstrap,
    condition_intervals =
      relative_cue_condition_intervals,
    slope_inference =
      relative_cue_slope_inference,
    primary_result =
      relative_cue_primary_result,
    plots = list(
      absolute_importance = relative_panel_a,
      choice_set_adjusted_importance =
        relative_panel_adjusted,
      relative_party_weight = relative_panel_b,
      relative_party_weight_panel_c =
        relative_panel_c,
      combined = figure_relative_weight_jp,
      combined_with_choice_set_adjustment =
        figure_relative_weight_adjusted_jp
    )
  )

  saveRDS(
    relative_cue_results,
    file = file.path(
      output_dir,
      "study1_relative_cue_results.rds"
    )
  )


  saveRDS(
    list(
      settings = list(
        require_initial_consent = require_initial_consent,
        require_final_consent = require_final_consent,
        require_attention_check = require_attention_check,
        require_manipulation_check = require_manipulation_check
      ),
      sample_flow = sample_flow,
      n_by_party = n_by_party,
      valid_ids = valid_ids,
      conjoint_all = conjoint_all,
      conjoint_all_m = conjoint_all_m,
      covar_id = covar_id,
      models_by_party_n_nocov = models_by_party_n_nocov,
      models_by_party_n_cov = models_by_party_n_cov,
      m_interaction = m_interaction,
      models_clogit_nocov = models_clogit_nocov,
      relative_cue = relative_cue_results,
      plots = list(
        amce_cov = p_amce_cov_main,
        amce_nocov = p_amce_nocov_appendix,
        interaction = p_interaction,
        heatmap = p_heat_amce,
        heatmap_rank = p_heat_amce_rank,
        clogit_odds_ratio = p_clogit_or,
        relative_cue_weight = figure_relative_weight_jp,
        relative_cue_weight_choice_set_adjusted =
          figure_relative_weight_adjusted_jp
      )
    ),
    file = file.path(output_dir, "study1_analysis_objects.rds")
  )

  capture.output(
    sessionInfo(),
    file = file.path(output_dir, "sessionInfo.txt")
  )

  cat("
Done: ", normalizePath(output_dir), "
", sep = "")

  environment()
})

A.3 実験2:本文の図6

# 本文コード
study2_env <- local({
required_packages <- c(
    "dplyr",
    "tidyr",
    "stringr",
    "purrr",
    "readr",
    "fixest",
    "tibble",
    "forcats",
    "ggplot2",
    "scales",
    "survival",
    "ggtext",
    "patchwork"
  )

  missing_packages <- required_packages[
    !vapply(required_packages, requireNamespace, logical(1), quietly = TRUE)
  ]

  if (length(missing_packages) > 0) {
    stop("No packages")
  }

  library(dplyr)
  library(tidyr)
  library(stringr)
  library(purrr)
  library(readr)
  library(fixest)
  library(tibble)
  library(forcats)
  library(ggplot2)
  library(scales)
  library(survival)
  library(patchwork)

  data_file <- unified_config$study2$data_file
  output_dir <- unified_config$study2$output_dir

  dir.create(output_dir, showWarnings = FALSE, recursive = TRUE)

  require_initial_consent <- TRUE
  require_final_consent <- TRUE
  final_consent_var <- "Q8.1"

  require_attention_check <- TRUE
  require_manipulation_check <- TRUE

  attention_check_var <- "Q25.1_11"
  attention_check_correct <- "3"

  relative_cue_bootstrap_B <- unified_config$relative_cue_bootstrap_B
  relative_cue_bootstrap_seed <- unified_config$relative_cue_bootstrap_seed + 2L
  relative_cue_bootstrap_progress_every <- unified_config$relative_cue_bootstrap_progress_every

  rerun_relative_cue_bootstrap <- unified_config$rerun_relative_cue_bootstrap


  norm_text <- function(x) {
    x %>%
      as.character() %>%
      str_squish() %>%
      str_replace_all("~", "~") %>%
      str_replace_all("〜", "~")
  }

  as_num <- function(x) {
    suppressWarnings(readr::parse_number(norm_text(x)))
  }

  is_response_code <- function(x, code) {
    x_norm <- norm_text(x)
    code_chr <- as.character(code)

    x_norm == code_chr |
      stringr::str_detect(x_norm, paste0("\\(", code_chr, "\\)$"))
  }

  first_existing <- function(dat, candidates) {
    out <- candidates[candidates %in% names(dat)]
    if (length(out) == 0) NA_character_ else out[1]
  }

  get_var <- function(dat, candidates) {
    v <- first_existing(dat, candidates)
    if (is.na(v)) {
      rep(NA_character_, nrow(dat))
    } else {
      dat[[v]]
    }
  }

  relevel_if_present <- function(x, ref) {
    x <- factor(x)
    if (ref %in% levels(x)) {
      relevel(x, ref = ref)
    } else {
      x
    }
  }

  factor_miss <- function(x, miss = "欠損・無回答") {
    x <- norm_text(x)
    x[is.na(x) | x == "" | x == "NA"] <- miss
    factor(x)
  }

  mean_impute <- function(x) {
    x <- as.numeric(x)
    miss <- as.integer(is.na(x))

    if (all(is.na(x))) {
      value <- x
    } else {
      value <- ifelse(is.na(x), mean(x, na.rm = TRUE), x)
    }

    list(value = value, miss = miss)
  }

  write_csv_safely <- function(x, filename) {
    readr::write_csv(x, file.path(output_dir, filename), na = "")
  }

  save_plot <- function(filename, plot, width, height, dpi = 300) {
    ggplot2::ggsave(
      filename = file.path(output_dir, filename),
      plot = plot,
      width = width,
      height = height,
      dpi = dpi
    )
  }


  if (!file.exists(data_file)) {
    stop("Check data")
  }

  raw <- readr::read_csv(
    data_file,
    col_types = cols(.default = col_character()),
    show_col_types = FALSE,
    name_repair = "minimal"
  )


  if (require_final_consent) {
    final_consent_var <- detect_final_consent_column(
      raw = raw,
      preferred_candidates = c("Q8.1", "Q9.1", "Q10.1"),
      study_label = "Study 2"
    )
  }

  if (require_attention_check) {
    attention_check_var <- detect_attention_check_column(
      raw = raw,
      preferred_candidates = c("Q25.1_11", "Q25.1_10"),
      study_label = "Study 2"
    )
  }

  df_header_removed <- raw %>%
    filter(
      !is.na(ResponseId),
      ResponseId != "",
      !str_detect(
        norm_text(ResponseId),
        "^(Response ID|回答ID)$|ImportId"
      )
    ) %>%
    mutate(ID = as.character(ResponseId))

  duplicate_ids <- df_header_removed %>%
    count(ID) %>%
    filter(n > 1)

  if (nrow(duplicate_ids) > 0) {
    print(duplicate_ids)
    stop("Check")
  }

  sample_flow <- tibble(
    stage = "Qualtrics質問文行を除外後",
    n = nrow(df_header_removed)
  )

  df <- df_header_removed

  if (require_initial_consent) {
    if (!"Q1.1" %in% names(df)) {
      stop("Check initial consent")
    }

    df <- df %>%
      filter(
        is_response_code(Q1.1, 1) |
          str_detect(norm_text(Q1.1), "趣旨に同意して.*協力する")
      )

    sample_flow <- bind_rows(
      sample_flow,
      tibble(stage = "初回同意 Q1.1 = 1", n = nrow(df))
    )
  }

  if (require_final_consent) {
    if (is.na(final_consent_var) || !final_consent_var %in% names(df)) {
      stop("Check final consent")
    }

    df <- df %>%
      filter(
        is_response_code(.data[[final_consent_var]], 1) |
          str_detect(
            norm_text(.data[[final_consent_var]]),
            "同意し.*回答結果を送信する"
          )
      )

    sample_flow <- bind_rows(
      sample_flow,
      tibble(
        stage = paste0("最終同意 ", final_consent_var, " = 1"),
        n = nrow(df)
      )
    )
  }

  if (require_attention_check) {
    if (!attention_check_var %in% names(df)) {
      stop("Check attention item")
    }

    attention_check_correct <- detect_attention_correct_code(
      df[[attention_check_var]],
      displayed_answer = 3L,
      recoded_answer = 6L,
      study_label = "Study 2"
    )

    df <- df %>%
      filter(
        is_response_code(
          .data[[attention_check_var]],
          attention_check_correct
        )
      )

    sample_flow <- bind_rows(
      sample_flow,
      tibble(
        stage = paste0(
          "指示項目正答(",
          attention_check_var,
          "、保存コード=",
          attention_check_correct,
          ")"
        ),
        n = nrow(df)
      )
    )
  }

  print(sample_flow)
  write_csv_safely(sample_flow, "sample_flow_before_conjoint.csv")


  choice_map <- detect_conjoint_choice_map(
    raw = raw,
    party_numbers = 2:5,
    study_label = "Study 2"
  )

  manipulation_map <- detect_manipulation_map(
    raw = raw,
    choice_map = choice_map,
    study_label = "Study 2"
  )

  write_csv_safely(choice_map, "detected_choice_question_map.csv")
  write_csv_safely(manipulation_map, "detected_manipulation_question_map.csv")


  level_to_attr_var <- function(x) {
    x <- norm_text(x)

    case_when(
      x %in% c("右派・保守的", "中道", "左派・革新的") ~
        "policy_position",

      x %in% c("与党", "野党") ~
        "government_status",

      str_detect(x, "GDP成長率") ~
        "gdp_growth",

      str_detect(x, "日経平均") ~
        "nikkei",

      x %in% c("10以下", "10~49", "50~99", "100~199", "200以上") ~
        "seats",

      str_detect(x, "CPI|物価") ~
        "cpi",

      str_detect(x, "失業率|雇用") ~
        "unemployment",

      TRUE ~ NA_character_
    )
  }

  required_attr_vars <- c(
    "policy_position",
    "government_status",
    "gdp_growth",
    "nikkei",
    "seats",
    "cpi",
    "unemployment"
  )

  allowed_levels <- list(
    policy_position = c("右派・保守的", "中道", "左派・革新的"),
    government_status = c("与党", "野党"),
    gdp_growth = c(
      "GDP成長率±0%",
      "GDP成長率プラス1%",
      "GDP成長率マイナス1%"
    ),
    nikkei = c(
      "日経平均前月同期比プラス1000円",
      "日経平均前月同期比マイナス1000円",
      "日経平均前月同期比変わらず"
    ),
    seats = c("10以下", "10~49", "50~99", "100~199", "200以上"),
    cpi = c(
      "CPI前期比±0ポイント",
      "CPI前期比プラス1ポイント",
      "CPI前期比マイナス1ポイント"
    ),
    unemployment = c(
      "失業率前期比±0%",
      "失業率前期比プラス1%",
      "失業率前期比マイナス1%"
    )
  )


  make_profile_long <- function(dat, n_party) {

    map_n <- choice_map %>%
      filter(party_n == n_party)

    qvars <- map_n$choice_var

    missing_q <- setdiff(qvars, names(dat))
    if (length(missing_q) > 0) {
      stop("Check choice columns")
    }

    dat_n <- dat %>%
      filter(if_any(all_of(qvars), ~ !is.na(.x) & norm_text(.x) != ""))

    if (require_manipulation_check) {
      manipulation_row <- manipulation_map %>%
        filter(party_n == n_party)

      manipulation_var <- manipulation_row$manipulation_var
      correct_answer <- manipulation_row$correct_answer

      if (!manipulation_var %in% names(dat_n)) {
        stop("Check manipulation item")
      }

      dat_n <- dat_n %>%
        filter(
          is_response_code(
            .data[[manipulation_var]],
            correct_answer
          )
        )
    }

    choice_long <- dat_n %>%
      select(ID, all_of(qvars)) %>%
      pivot_longer(
        cols = all_of(qvars),
        names_to = "choice_var",
        values_to = "choice_raw"
      ) %>%
      left_join(map_n, by = "choice_var") %>%
      mutate(choice = parse_choice_position(choice_raw)) %>%
      filter(!is.na(choice)) %>%
      select(ID, party_n, task, choice)

    invalid_choice <- choice_long %>%
      filter(choice < 1 | choice > n_party)

    if (nrow(invalid_choice) > 0) {
      print(invalid_choice)
      stop("Check choice values")
    }

    duplicate_choice <- choice_long %>%
      count(ID, task) %>%
      filter(n != 1)

    if (nrow(duplicate_choice) > 0) {
      print(duplicate_choice)
      stop("Check duplicate choices")
    }

    level_regex <- paste0(
      "^S2_P", n_party,
      "_F_([1-5])_([1-", n_party, "])_([1-7])$"
    )

    level_cols <- names(dat_n)[str_detect(names(dat_n), level_regex)]

    expected_level_cols <- 5 * n_party * 7
    if (length(level_cols) != expected_level_cols) {
      stop("Check attributes")
    }

    level_long <- dat_n %>%
      select(ID, all_of(level_cols)) %>%
      pivot_longer(
        cols = all_of(level_cols),
        names_to = "fvar",
        values_to = "level"
      ) %>%
      extract(
        fvar,
        into = c("task", "profile", "attr_order"),
        regex = level_regex,
        convert = TRUE
      ) %>%
      mutate(level = norm_text(level)) %>%
      filter(
        task %in% 1:5,
        profile %in% 1:n_party,
        attr_order %in% 1:7,
        !is.na(level),
        level != ""
      ) %>%
      mutate(attr_var = level_to_attr_var(level))

    unknown_levels <- level_long %>%
      filter(is.na(attr_var)) %>%
      distinct(level)

    if (nrow(unknown_levels) > 0) {
      print(unknown_levels)
      stop("Check attributes")
    }

    profile_attribute_count <- level_long %>%
      count(ID, task, profile, name = "n_attribute_rows") %>%
      filter(n_attribute_rows != 7)

    if (nrow(profile_attribute_count) > 0) {
      print(head(profile_attribute_count, 50))
      stop("Check attributes")
    }

    duplicate_attribute <- level_long %>%
      count(ID, task, profile, attr_var) %>%
      filter(n != 1)

    if (nrow(duplicate_attribute) > 0) {
      print(head(duplicate_attribute, 50))
      stop("Check attributes")
    }

    profile_wide <- level_long %>%
      inner_join(choice_long, by = c("ID", "task")) %>%
      mutate(
        party_n = n_party,
        selected = as.integer(profile == choice),
        task_id = paste(ID, party_n, task, sep = "_"),
        profile_id = paste(ID, party_n, task, profile, sep = "_")
      ) %>%
      select(
        ID, party_n, task, profile, choice, selected,
        task_id, profile_id, attr_var, level
      ) %>%
      pivot_wider(
        names_from = attr_var,
        values_from = level,
        values_fn = list(level = ~ first(.x))
      )

    missing_attr <- setdiff(required_attr_vars, names(profile_wide))

    if (length(missing_attr) > 0) {
      stop("Check attributes")
    }

    profile_wide <- profile_wide %>%
      select(
        ID, party_n, task, profile, choice, selected,
        task_id, profile_id,
        all_of(required_attr_vars)
      ) %>%
      arrange(ID, task, profile)

    return(profile_wide)
  }


  conjoint_2 <- make_profile_long(df, 2)
  conjoint_3 <- make_profile_long(df, 3)
  conjoint_4 <- make_profile_long(df, 4)
  conjoint_5 <- make_profile_long(df, 5)

  conjoint_all_unfiltered <- bind_rows(
    conjoint_2,
    conjoint_3,
    conjoint_4,
    conjoint_5
  )


  id_task_check <- conjoint_all_unfiltered %>%
    group_by(ID, party_n, task) %>%
    summarise(
      n_profiles = n(),
      selected_sum = sum(selected),
      .groups = "drop"
    ) %>%
    group_by(ID, party_n) %>%
    summarise(
      n_tasks = n_distinct(task),
      all_tasks_ok = all(n_profiles == party_n & selected_sum == 1),
      .groups = "drop"
    )

  valid_ids <- id_task_check %>%
    filter(n_tasks == 5, all_tasks_ok)

  conjoint_all <- conjoint_all_unfiltered %>%
    semi_join(valid_ids, by = c("ID", "party_n"))

  n_by_party <- valid_ids %>%
    count(party_n, name = "n") %>%
    complete(party_n = 2:5, fill = list(n = 0)) %>%
    arrange(party_n)

  n_total <- valid_ids %>%
    summarise(n = n_distinct(ID)) %>%
    pull(n)

  figure_n_labels <- bind_rows(
    tibble(
      position = "全サンプル",
      label = paste0("全サンプル, n=", scales::comma(n_total))
    ),
    n_by_party %>%
      mutate(
        position = paste0(party_n, "政党選択"),
        label = paste0("n=", scales::comma(n))
      ) %>%
      select(position, label)
  )

  cat("\n分析対象者数\n")
  print(n_by_party)
  cat("全サンプル n=", n_total, "\n", sep = "")

  write_csv_safely(id_task_check, "id_task_check.csv")
  write_csv_safely(valid_ids, "valid_ids.csv")
  write_csv_safely(n_by_party, "n_by_party.csv")
  write_csv_safely(figure_n_labels, "figure_n_labels.csv")


  check_profile <- conjoint_all %>%
    group_by(party_n, ID, task, task_id) %>%
    summarise(
      n_profiles = n(),
      selected_sum = sum(selected),
      .groups = "drop"
    ) %>%
    count(party_n, n_profiles, selected_sum)

  print(check_profile)

  stopifnot(all(check_profile$n_profiles == check_profile$party_n))
  stopifnot(all(check_profile$selected_sum == 1))

  allowed_df <- enframe(allowed_levels, name = "name", value = "value") %>%
    unnest(value)

  unexpected_values <- conjoint_all %>%
    select(all_of(required_attr_vars)) %>%
    pivot_longer(
      cols = everything(),
      names_to = "name",
      values_to = "value"
    ) %>%
    filter(!is.na(value), value != "") %>%
    distinct(name, value) %>%
    anti_join(allowed_df, by = c("name", "value"))

  print(unexpected_values)
  stopifnot(nrow(unexpected_values) == 0)

  observed_levels <- conjoint_all %>%
    select(all_of(required_attr_vars)) %>%
    pivot_longer(
      cols = everything(),
      names_to = "attribute",
      values_to = "level"
    ) %>%
    distinct(attribute, level) %>%
    arrange(attribute, level)

  write_csv_safely(check_profile, "profile_expansion_check.csv")
  write_csv_safely(observed_levels, "observed_attribute_levels.csv")
  write_csv_safely(conjoint_all, "study2_profile_level_data.csv")


  analysis_ids <- valid_ids %>%
    select(ID, party_n)

  attention_summary <- df %>%
    semi_join(analysis_ids, by = "ID") %>%
    transmute(
      ID,
      attention_response = norm_text(.data[[attention_check_var]]),
      attention_pass = is_response_code(
        .data[[attention_check_var]],
        attention_check_correct
      )
    ) %>%
    count(attention_response, attention_pass, name = "n") %>%
    arrange(desc(attention_pass), attention_response)

  manipulation_summary <- map_dfr(2:5, function(n_party) {
    manipulation_row <- manipulation_map %>%
      filter(party_n == n_party)

    v <- manipulation_row$manipulation_var
    correct <- manipulation_row$correct_answer

    df %>%
      semi_join(
        analysis_ids %>% filter(party_n == n_party),
        by = "ID"
      ) %>%
      transmute(
        party_n = n_party,
        response = norm_text(.data[[v]]),
        correct = is_response_code(.data[[v]], correct)
      ) %>%
      count(party_n, response, correct, name = "n")
  })

  write_csv_safely(attention_summary, "attention_check_summary.csv")
  write_csv_safely(manipulation_summary, "party_number_check_summary.csv")


  conjoint_all_m <- conjoint_all %>%
    mutate(
      selected = as.integer(selected),
      ID = as.character(ID),

      policy_position = factor(
        policy_position,
        levels = c("中道", "右派・保守的", "左派・革新的")
      ),

      government_status = factor(
        government_status,
        levels = c("野党", "与党")
      ),

      gdp_growth = factor(
        gdp_growth,
        levels = c(
          "GDP成長率±0%",
          "GDP成長率プラス1%",
          "GDP成長率マイナス1%"
        )
      ),

      nikkei = factor(
        nikkei,
        levels = c(
          "日経平均前月同期比変わらず",
          "日経平均前月同期比プラス1000円",
          "日経平均前月同期比マイナス1000円"
        )
      ),

      seats = factor(
        seats,
        levels = c("10以下", "10~49", "50~99", "100~199", "200以上")
      ),

      cpi = factor(
        cpi,
        levels = c(
          "CPI前期比±0ポイント",
          "CPI前期比プラス1ポイント",
          "CPI前期比マイナス1ポイント"
        )
      ),

      unemployment = factor(
        unemployment,
        levels = c(
          "失業率前期比±0%",
          "失業率前期比プラス1%",
          "失業率前期比マイナス1%"
        )
      ),

      party_n_f = factor(
        as.character(party_n),
        levels = c("2", "3", "4", "5")
      )
    )

  attr_terms <- c(
    "policy_position",
    "government_status",
    "gdp_growth",
    "nikkei",
    "seats",
    "cpi",
    "unemployment"
  )


  formula_nocov <- as.formula(
    paste("selected ~", paste(attr_terms, collapse = " + "))
  )

  run_amce_nocov <- function(dat) {
    feols(
      formula_nocov,
      data = dat,
      vcov = ~ ID
    )
  }

  models_by_party_n_nocov <- conjoint_all_m %>%
    split(.$party_n) %>%
    map(run_amce_nocov)

  capture.output(
    etable(models_by_party_n_nocov),
    file = file.path(output_dir, "amce_nocov_models.txt")
  )


  m_interaction <- feols(
    selected ~
      party_n_f *
      (
        policy_position +
          government_status +
          gdp_growth +
          nikkei +
          seats +
          cpi +
          unemployment
      ),
    data = conjoint_all_m,
    vcov = ~ ID
  )

  capture.output(
    summary(m_interaction),
    file = file.path(output_dir, "amce_interaction_model.txt")
  )


  tidy_fixest <- function(model) {
    ct <- as.data.frame(fixest::coeftable(model))
    ct$term <- rownames(ct)

    ct %>%
      as_tibble() %>%
      rename(
        estimate = Estimate,
        std.error = `Std. Error`,
        statistic = `t value`,
        p.value = `Pr(>|t|)`
      ) %>%
      mutate(
        conf.low = estimate - 1.96 * std.error,
        conf.high = estimate + 1.96 * std.error
      ) %>%
      select(
        term, estimate, std.error, statistic, p.value,
        conf.low, conf.high
      )
  }

  term_labels <- tribble(
    ~term, ~attribute, ~cue_type, ~label, ~order,

    "government_status与党",
    "与党/野党", "政党の手がかり", "与党", 1,

    "policy_position右派・保守的",
    "政策位置", "政党の手がかり", "右派・保守的", 2,

    "policy_position左派・革新的",
    "政策位置", "政党の手がかり", "左派・革新的", 3,

    "seats10~49",
    "議席数", "政党の手がかり", "議席数:10~49", 4,

    "seats50~99",
    "議席数", "政党の手がかり", "議席数:50~99", 5,

    "seats100~199",
    "議席数", "政党の手がかり", "議席数:100~199", 6,

    "seats200以上",
    "議席数", "政党の手がかり", "議席数:200以上", 7,

    "gdp_growthGDP成長率プラス1%",
    "GDP成長率", "経済の手がかり", "GDP:プラス1%", 8,

    "gdp_growthGDP成長率マイナス1%",
    "GDP成長率", "経済の手がかり", "GDP:マイナス1%", 9,

    "nikkei日経平均前月同期比プラス1000円",
    "日経平均", "経済の手がかり", "日経平均:プラス1000円", 10,

    "nikkei日経平均前月同期比マイナス1000円",
    "日経平均", "経済の手がかり", "日経平均:マイナス1000円", 11,

    "cpiCPI前期比プラス1ポイント",
    "CPI", "経済の手がかり", "CPI:プラス1ポイント", 12,

    "cpiCPI前期比マイナス1ポイント",
    "CPI", "経済の手がかり", "CPI:マイナス1ポイント", 13,

    "unemployment失業率前期比プラス1%",
    "失業率", "経済の手がかり", "失業率:プラス1%", 14,

    "unemployment失業率前期比マイナス1%",
    "失業率", "経済の手がかり", "失業率:マイナス1%", 15
  )

  attribute_order <- c(
    "与党/野党",
    "政策位置",
    "議席数",
    "GDP成長率",
    "日経平均",
    "CPI",
    "失業率"
  )

  label_order <- term_labels %>%
    arrange(order) %>%
    pull(label)

  make_amce_plot_df <- function(models) {
    imap_dfr(
      models,
      ~ tidy_fixest(.x) %>%
        mutate(party_n = as.character(.y))
    ) %>%
      left_join(term_labels, by = "term") %>%
      filter(!is.na(attribute)) %>%
      mutate(
        estimate_pp = estimate * 100,
        conf.low_pp = conf.low * 100,
        conf.high_pp = conf.high * 100,
        party_n = factor(
          party_n,
          levels = c("2", "3", "4", "5"),
          labels = c("2政党", "3政党", "4政党", "5政党")
        ),
        attribute = factor(attribute, levels = attribute_order),
        label = factor(label, levels = rev(label_order))
      )
  }

  amce_plot_nocov <- make_amce_plot_df(models_by_party_n_nocov)
  write_csv_safely(amce_plot_nocov, "amce_nocov_coefficients.csv")

  interaction_plot_df <- tidy_fixest(m_interaction) %>%
    filter(str_detect(term, "party_n_f[345]")) %>%
    mutate(
      party_n_code = str_extract(term, "party_n_f[345]"),
      party_n = str_remove(party_n_code, "party_n_f"),
      base_term = term %>%
        str_remove("party_n_f[345]:") %>%
        str_remove(":party_n_f[345]")
    ) %>%
    left_join(term_labels, by = c("base_term" = "term")) %>%
    filter(!is.na(attribute)) %>%
    mutate(
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,
      party_n_label = factor(
        party_n,
        levels = c("3", "4", "5"),
        labels = c("3政党", "4政党", "5政党")
      ),
      attribute = factor(attribute, levels = attribute_order),
      label = factor(label, levels = rev(label_order))
    )

  write_csv_safely(interaction_plot_df, "amce_interaction_coefficients.csv")


  recode_female_study2 <- function(x) {
    x_num <- as_num(x)

    case_when(
      x_num == 2 ~ 1L,
      x_num == 1 ~ 0L,
      TRUE ~ NA_integer_
    )
  }

  recode_college_grad_study2 <- function(x) {
    x_num <- as_num(x)

    case_when(
      x_num %in% c(4, 5) ~ 1L,
      x_num %in% c(1, 2, 3) ~ 0L,
      TRUE ~ NA_integer_
    )
  }

  recode_party_support_study2 <- function(x) {
    x_num <- as_num(x)

    case_when(
      x_num == 1 ~ "自由民主党",
      x_num == 2 ~ "中道改革連合",
      x_num == 3 ~ "立憲民主党",
      x_num == 4 ~ "公明党",
      x_num == 5 ~ "日本維新の会",
      x_num == 6 ~ "国民民主党",
      x_num == 7 ~ "れいわ新選組",
      x_num == 8 ~ "日本共産党",
      x_num == 9 ~ "参政党",
      x_num == 10 ~ "日本保守党",
      x_num == 11 ~ "社会民主党",
      x_num == 12 ~ "チームみらい",
      x_num == 13 ~ "その他",
      x_num == 14 ~ "支持政党なし",
      x_num == 15 ~ "わからない",
      x_num == 16 ~ "答えたくない",
      TRUE ~ NA_character_
    )
  }

  gender_raw <- get_var(df, c("Q2.1", "Q2_1"))
  age_raw <- get_var(df, c("Q2.2_2", "Q2.2.2", "Q2_2_2"))
  education_raw <- get_var(df, c("Q2.3", "Q2_3"))
  income_gross_raw <- get_var(df, c("Q2.5_1", "Q2.5.1", "Q2_5_1"))
  income_net_raw <- get_var(df, c("Q2.5_2", "Q2.5.2", "Q2_5_2"))
  party_support_raw <- get_var(df, c("Q8.2", "Q8_2"))

  covar_id <- df %>%
    transmute(
      ID = as.character(ResponseId),
      female = recode_female_study2(gender_raw),
      age = as_num(age_raw),
      college_grad = recode_college_grad_study2(education_raw),
      income_gross = as_num(income_gross_raw),
      income_net = as_num(income_net_raw),
      income_gross_log = log1p(income_gross),
      income_net_log = log1p(income_net),
      party_support = recode_party_support_study2(party_support_raw),
      party_support_f = factor_miss(party_support)
    ) %>%
    semi_join(valid_ids %>% select(ID), by = "ID") %>%
    distinct(ID, .keep_all = TRUE)

  covar_id <- covar_id %>%
    mutate(
      age = if_else(age >= 18 & age <= 79, age, NA_real_)
    )

  age_imp_obj <- mean_impute(covar_id$age)
  income_gross_imp_obj <- mean_impute(covar_id$income_gross_log)

  covar_id <- covar_id %>%
    mutate(
      female_imp = if_else(is.na(female), 0L, female),
      female_miss = as.integer(is.na(female)),

      college_grad_imp = if_else(is.na(college_grad), 0L, college_grad),
      college_grad_miss = as.integer(is.na(college_grad)),

      age_imp = age_imp_obj$value,
      age_miss = age_imp_obj$miss,

      income_gross_log_imp = income_gross_imp_obj$value,
      income_gross_log_miss = income_gross_imp_obj$miss
    )

  covariate_missing_summary <- covar_id %>%
    summarise(
      n_ids = n_distinct(ID),
      female_missing = sum(is.na(female)),
      age_missing = sum(is.na(age)),
      college_grad_missing = sum(is.na(college_grad)),
      income_gross_missing = sum(is.na(income_gross_log)),
      party_support_missing = sum(is.na(party_support))
    )

  print(covariate_missing_summary)
  write_csv_safely(covar_id, "respondent_covariates.csv")
  write_csv_safely(covariate_missing_summary, "covariate_missing_summary.csv")


  conjoint_all_cov <- conjoint_all_m %>%
    left_join(covar_id, by = "ID")

  covariate_terms <- c(
    "female_imp",
    "female_miss",
    "age_imp",
    "age_miss",
    "college_grad_imp",
    "college_grad_miss",
    "income_gross_log_imp",
    "income_gross_log_miss",
    "party_support_f"
  )

  has_variation <- function(dat, v) {
    if (!v %in% names(dat)) return(FALSE)
    dplyr::n_distinct(dat[[v]], na.rm = TRUE) > 1
  }

  covariate_terms_use <- covariate_terms[
    map_lgl(covariate_terms, ~ has_variation(conjoint_all_cov, .x))
  ]

  formula_cov <- as.formula(
    paste(
      "selected ~",
      paste(c(attr_terms, covariate_terms_use), collapse = " + ")
    )
  )

  run_amce_cov <- function(dat) {
    feols(
      formula_cov,
      data = dat,
      vcov = ~ ID
    )
  }

  models_by_party_n_cov <- conjoint_all_cov %>%
    split(.$party_n) %>%
    map(run_amce_cov)

  capture.output(
    etable(
      models_by_party_n_nocov,
      models_by_party_n_cov,
      headers = c(
        rep("共変量なし", length(models_by_party_n_nocov)),
        rep("共変量あり", length(models_by_party_n_cov))
      )
    ),
    file = file.path(output_dir, "amce_nocov_and_cov_models.txt")
  )

  amce_plot_cov <- make_amce_plot_df(models_by_party_n_cov)
  write_csv_safely(amce_plot_cov, "amce_cov_coefficients.csv")


  study_label <- "実験2(2026年)"

  term_labels_facet <- term_labels %>%
    mutate(
      attribute_facet = attribute
    )

  attribute_order_facet <- c(
    "与党/野党",
    "政策位置",
    "議席数",
    "GDP成長率",
    "日経平均",
    "CPI",
    "失業率"
  )

  make_amce_facet_df <- function(models) {
    imap_dfr(
      models,
      ~ tidy_fixest(.x) %>%
        mutate(party_n = as.character(.y))
    ) %>%
      left_join(term_labels_facet, by = "term") %>%
      filter(!is.na(attribute_facet)) %>%
      mutate(
        estimate_pp = estimate * 100,
        conf.low_pp = conf.low * 100,
        conf.high_pp = conf.high * 100,
        party_n = factor(
          party_n,
          levels = c("2", "3", "4", "5"),
          labels = c("2政党", "3政党", "4政党", "5政党")
        ),
        attribute_facet = factor(
          attribute_facet,
          levels = attribute_order_facet
        ),
        label = factor(
          label,
          levels = rev(label_order)
        )
      )
  }

  amce_plot_df_cov_facet <- make_amce_facet_df(models_by_party_n_cov)
  amce_plot_df_nocov_facet <- make_amce_facet_df(models_by_party_n_nocov)

  write_csv_safely(
    amce_plot_df_cov_facet,
    "amce_cov_facet_coefficients.csv"
  )

  write_csv_safely(
    amce_plot_df_nocov_facet,
    "amce_nocov_facet_coefficients.csv"
  )


  p_amce_cov_facet <- ggplot(
    amce_plot_df_cov_facet,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(width = 0.65),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.65),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute_facet ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) paste0(x, " pp"),
      breaks = seq(-12, 12, by = 2)
    ) +
    scale_shape_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = 16,
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = "solid",
        "3政党" = "dashed",
        "4政党" = "dotted",
        "5政党" = "dotdash"
      )
    ) +
    labs(
      x = "選択確率の変化",
      y = NULL
    ) +
    theme_bw(
      base_size = 12,
      base_family = "Yu Gothic"
    ) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 16
      ),
      plot.subtitle = element_text(size = 11),
      legend.position = "top",
      legend.title = element_text(face = "bold"),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(size = 9),
      axis.title.x = element_text(face = "bold")
    )

  print(p_amce_cov_facet)

  save_plot(
    "amce_cov_facet_model.png",
    p_amce_cov_facet,
    width = 10.5,
    height = 8.5
  )

  p_amce_cov_main <- p_amce_cov_facet


  make_heatmap_df <- function(amce_plot_df) {
    heat_df <- amce_plot_df %>%
      mutate(
        abs_amce = abs(estimate_pp),
        cue_type_code = case_when(
          cue_type == "政党の手がかり" ~ "party",
          cue_type == "経済の手がかり" ~ "economy",
          TRUE ~ "other"
        )
      ) %>%
      group_by(party_n) %>%
      mutate(
        rank_within_party = min_rank(desc(abs_amce)),
        n_in_col = n(),
        rank_score = if_else(
          n_in_col == 1,
          1,
          1 - (rank_within_party - 1) / (n_in_col - 1)
        )
      ) %>%
      ungroup()

    row_order_df <- heat_df %>%
      group_by(label, cue_type_code) %>%
      summarise(
        mean_abs_amce = mean(abs_amce, na.rm = TRUE),
        .groups = "drop"
      ) %>%
      arrange(desc(mean_abs_amce))

    row_levels <- as.character(row_order_df$label)

    heat_df <- heat_df %>%
      mutate(
        label = factor(
          as.character(label),
          levels = rev(row_levels)
        )
      )

    label_color_map <- row_order_df %>%
      mutate(
        label_markdown = case_when(
          cue_type_code == "party" ~
            paste0(
              "<span style='color:#111111;'>",
              label,
              "</span>"
            ),
          cue_type_code == "economy" ~
            paste0(
              "<span style='color:#8A8A8A;'>",
              label,
              "</span>"
            ),
          TRUE ~ as.character(label)
        )
      )

    label_markdown_vec <- setNames(
      label_color_map$label_markdown,
      as.character(label_color_map$label)
    )

    list(
      heat_df = heat_df,
      label_markdown_vec = label_markdown_vec
    )
  }

  plot_amce_heatmap <- function(
      heat_df,
      label_markdown_vec,
      with_rank = TRUE,
      title_text = NULL) {

    if (with_rank) {
      heat_df <- heat_df %>%
        mutate(
          cell_label = paste0(
            sprintf("%.1f", estimate_pp),
            "\n(",
            rank_within_party,
            "位)"
          )
        )

      text_size <- 3.0
      lineheight <- 0.9
    } else {
      heat_df <- heat_df %>%
        mutate(
          cell_label = sprintf("%.1f", estimate_pp)
        )

      text_size <- 3.4
      lineheight <- 1.0
    }

    ggplot(
      heat_df,
      aes(
        x = party_n,
        y = label,
        fill = rank_score
      )
    ) +
      geom_tile(
        color = "white",
        linewidth = 0.7
      ) +
      geom_text(
        aes(label = cell_label),
        size = text_size,
        fontface = "bold",
        color = "black",
        lineheight = lineheight
      ) +
      scale_y_discrete(
        labels = label_markdown_vec
      ) +
      scale_fill_gradient(
        low = "grey95",
        high = "grey15",
        limits = c(0, 1),
        breaks = c(0, 0.25, 0.50, 0.75, 1.00),
        labels = c("低", "", "", "", "高"),
        name = "列内順位\n(濃いほど高位)"
      ) +
      labs(
        title = title_text,
        x = "政党数選択肢",
        y = NULL
      ) +
      theme_bw(base_size = 12) +
      theme(
        legend.position = "right",
        panel.grid = element_blank(),
        plot.title = element_text(face = "bold"),
        axis.text.x = element_text(size = 10),
        axis.text.y = ggtext::element_markdown(size = 9),
        axis.title.y = element_blank()
      )
  }

  heatmap_input <- make_heatmap_df(amce_plot_cov)

  p_heat_amce_mixed <- plot_amce_heatmap(
    heatmap_input$heat_df,
    heatmap_input$label_markdown_vec,
    with_rank = FALSE,
    title_text = NULL
  )

  print(p_heat_amce_mixed)

  save_plot(
    "amce_heatmap_mixed_rank_colored_labels.png",
    p_heat_amce_mixed,
    width = 8.8,
    height = 8.8
  )

  p_heat_amce_mixed_ranklabel <- plot_amce_heatmap(
    heatmap_input$heat_df,
    heatmap_input$label_markdown_vec,
    with_rank = TRUE,
    title_text = NULL
  )

  print(p_heat_amce_mixed_ranklabel)

  save_plot(
    "amce_heatmap_mixed_rank_colored_labels_withrank.png",
    p_heat_amce_mixed_ranklabel,
    width = 8.8,
    height = 8.8
  )

  p_heat_amce <- p_heat_amce_mixed
  p_heat_amce_rank <- p_heat_amce_mixed_ranklabel


  p_amce_facet_nocov <- ggplot(
    amce_plot_df_nocov_facet,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(width = 0.65),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.65),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute_facet ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) paste0(x, " pp"),
      breaks = seq(-12, 12, by = 2)
    ) +
    scale_shape_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = 16,
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      name = "政党数選択肢",
      values = c(
        "2政党" = "solid",
        "3政党" = "dashed",
        "4政党" = "dotted",
        "5政党" = "dotdash"
      )
    ) +
    labs(
      x = "選択確率の変化",
      y = NULL
    ) +
    theme_bw(base_size = 12) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 16
      ),
      plot.subtitle = element_text(size = 11),
      legend.position = "top",
      legend.title = element_text(face = "bold"),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(size = 9),
      axis.title.x = element_text(face = "bold")
    )

  print(p_amce_facet_nocov)

  save_plot(
    "amce_facet_nocov.png",
    p_amce_facet_nocov,
    width = 10.5,
    height = 9
  )

  p_amce_nocov_appendix <- p_amce_facet_nocov


  p_interaction <- ggplot(
    interaction_plot_df,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n_label,
      linetype = party_n_label,
      group = party_n_label
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(width = 0.65),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.65),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) paste0(x, " pp"),
      breaks = seq(-8, 8, by = 2)
    ) +
    scale_shape_manual(
      name = "2政党の場合との比較",
      values = c(
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      name = "2政党の場合との比較",
      values = c(
        "3政党" = "dashed",
        "4政党" = "dotted",
        "5政党" = "dotdash"
      )
    ) +
    labs(
      x = "2政党条件との差",
      y = NULL
    ) +
    theme_bw(base_size = 12) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 15
      ),
      plot.subtitle = element_text(size = 11),
      legend.position = "top",
      legend.title = element_text(face = "bold"),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(size = 9),
      axis.title.x = element_text(face = "bold")
    )

  print(p_interaction)

  save_plot(
    "amce_interaction_difference_from_2party.png",
    p_interaction,
    width = 10.5,
    height = 9
  )


  conjoint_clogit <- conjoint_all_m %>%
    mutate(
      selected = as.integer(selected),
      ID = as.character(ID),
      task_id = factor(task_id),
      policy_position = relevel_if_present(
        policy_position,
        "中道"
      ),
      government_status = relevel_if_present(
        government_status,
        "野党"
      ),
      gdp_growth = relevel_if_present(
        gdp_growth,
        "GDP成長率±0%"
      ),
      nikkei = relevel_if_present(
        nikkei,
        "日経平均前月同期比変わらず"
      ),
      seats = relevel_if_present(
        seats,
        "10以下"
      ),
      cpi = relevel_if_present(
        cpi,
        "CPI前期比±0ポイント"
      ),
      unemployment = relevel_if_present(
        unemployment,
        "失業率前期比±0%"
      )
    )

  formula_clogit_nocov <- as.formula(
    paste0(
      "selected ~ ",
      paste(attr_terms, collapse = " + "),
      " + strata(task_id) + cluster(ID)"
    )
  )

  run_clogit_nocov <- function(dat) {
    survival::clogit(
      formula_clogit_nocov,
      data = dat,
      method = "efron"
    )
  }

  models_clogit_nocov <- conjoint_clogit %>%
    split(.$party_n) %>%
    map(run_clogit_nocov)

  capture.output(
    lapply(models_clogit_nocov, summary),
    file = file.path(
      output_dir,
      "conditional_logit_models.txt"
    )
  )

  tidy_clogit <- function(model) {
    s <- summary(model)
    ct <- as.data.frame(s$coefficients)
    ct$term <- rownames(ct)

    se_col <- if ("robust se" %in% names(ct)) {
      "robust se"
    } else if ("se(coef)" %in% names(ct)) {
      "se(coef)"
    } else {
      stop("Check clogit")
    }

    p_col <- if ("Pr(>|z|)" %in% names(ct)) {
      "Pr(>|z|)"
    } else if ("Pr(>|t|)" %in% names(ct)) {
      "Pr(>|t|)"
    } else {
      NA_character_
    }

    ct %>%
      as_tibble() %>%
      transmute(
        term = term,
        estimate = coef,
        std.error = .data[[se_col]],
        p.value = if (!is.na(p_col)) {
          .data[[p_col]]
        } else {
          NA_real_
        },
        conf.low = estimate - 1.96 * std.error,
        conf.high = estimate + 1.96 * std.error,
        odds_ratio = exp(estimate),
        odds_ratio_low = exp(conf.low),
        odds_ratio_high = exp(conf.high)
      )
  }

  clogit_plot_df <- imap_dfr(
    models_clogit_nocov,
    ~ tidy_clogit(.x) %>%
      mutate(party_n = as.character(.y))
  ) %>%
    left_join(term_labels, by = "term") %>%
    filter(!is.na(attribute)) %>%
    mutate(
      party_n = factor(
        party_n,
        levels = c("2", "3", "4", "5"),
        labels = c("2政党", "3政党", "4政党", "5政党")
      ),
      label = factor(
        label,
        levels = rev(label_order)
      )
    )

  write_csv_safely(
    clogit_plot_df,
    "conditional_logit_coefficients.csv"
  )


  p_clogit_or <- ggplot(
    clogit_plot_df,
    aes(
      x = odds_ratio,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 1,
      linetype = "dashed",
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = odds_ratio_low,
        xmax = odds_ratio_high
      ),
      position = position_dodge(width = 0.72),
      height = 0.15,
      linewidth = 0.45,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(width = 0.72),
      size = 2.4,
      stroke = 0.7,
      color = "black"
    ) +
    scale_x_log10(
      breaks = c(
        0.6,
        0.8,
        1.0,
        1.25,
        1.5,
        2.0
      ),
      labels = c(
        "0.6",
        "0.8",
        "1.0",
        "1.25",
        "1.5",
        "2.0"
      )
    ) +
    scale_shape_manual(
      values = c(
        "2政党" = 16,
        "3政党" = 17,
        "4政党" = 15,
        "5政党" = 1
      )
    ) +
    scale_linetype_manual(
      values = c(
        "2政党" = "solid",
        "3政党" = "dashed",
        "4政党" = "dotdash",
        "5政党" = "twodash"
      )
    ) +
    labs(
      x = "オッズ比",
      y = NULL,
      shape = "政党数選択肢",
      linetype = "政党数選択肢"
    ) +
    theme_bw(base_size = 12) +
    theme(
      legend.position = "bottom",
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      plot.title = element_text(face = "bold"),
      axis.text.y = element_text(size = 9)
    )

  print(p_clogit_or)

  save_plot(
    "clogit_oddsratio_nocov.png",
    p_clogit_or,
    width = 10.5,
    height = 8.5
  )


  relative_cue_map <- c(
    policy_position = "party",
    government_status = "party",
    seats = "party",
    gdp_growth = "economic",
    nikkei = "economic",
    cpi = "economic",
    unemployment = "economic"
  )

  mean_absolute_pairwise_difference <- function(x) {
    x <- x[is.finite(x)]

    if (length(x) < 2) {
      return(NA_real_)
    }

    pairwise_differences <- combn(
      x,
      2,
      FUN = function(z) abs(z[1] - z[2])
    )

    mean(pairwise_differences)
  }

  linear_slope <- function(y, x) {
    keep <- is.finite(y) & is.finite(x)
    y <- y[keep]
    x <- x[keep]

    if (length(y) < 2 || length(unique(x)) < 2) {
      return(NA_real_)
    }

    unname(coef(lm(y ~ x))[2])
  }

  bootstrap_two_sided_p <- function(x) {
    x <- x[is.finite(x)]
    B_valid <- length(x)

    if (B_valid == 0) {
      return(NA_real_)
    }

    p_lower <- (1 + sum(x <= 0)) / (B_valid + 1)
    p_upper <- (1 + sum(x >= 0)) / (B_valid + 1)

    min(1, 2 * min(p_lower, p_upper))
  }

  safe_quantile <- function(x, probability) {
    x <- x[is.finite(x)]

    if (length(x) == 0) {
      return(NA_real_)
    }

    unname(
      quantile(
        x,
        probs = probability,
        type = 6,
        na.rm = TRUE
      )
    )
  }

  prepare_relative_cue_analysis <- function(data, cue_map) {
    attributes <- names(cue_map)

    required_columns <- c(
      "ID",
      "party_n",
      "selected",
      attributes
    )

    missing_columns <- setdiff(
      required_columns,
      names(data)
    )

    if (length(missing_columns) > 0) {
      stop("Check relative weight")
    }

    if (!all(unname(cue_map) %in% c("party", "economic"))) {
      stop("Check relative weight")
    }

    analysis_data <- data %>%
      select(
        ID,
        party_n,
        selected,
        all_of(attributes)
      ) %>%
      mutate(
        ID = as.character(ID),
        party_n = as.integer(as.character(party_n)),
        selected = as.integer(selected),
        across(
          all_of(attributes),
          as.character
        )
      ) %>%
      filter(
        !is.na(ID),
        party_n %in% 2:5,
        selected %in% c(0L, 1L)
      )

    observed_conditions <- sort(
      unique(analysis_data$party_n)
    )

    if (!identical(observed_conditions, 2:5)) {
      stop("Check")
    }

    long_data <- analysis_data %>%
      pivot_longer(
        cols = all_of(attributes),
        names_to = "attribute",
        values_to = "level"
      ) %>%
      filter(
        !is.na(level),
        level != ""
      )

    expected_cells <- long_data %>%
      distinct(
        attribute,
        level
      ) %>%
      mutate(
        attribute_order = match(
          attribute,
          attributes
        )
      ) %>%
      arrange(
        attribute_order,
        attribute,
        level
      ) %>%
      select(-attribute_order) %>%
      mutate(
        cell_key = paste(
          attribute,
          level,
          sep = "\r"
        )
      )

    respondent_cell <- long_data %>%
      group_by(
        party_n,
        ID,
        attribute,
        level
      ) %>%
      summarise(
        y_sum = sum(selected),
        n_obs = n(),
        .groups = "drop"
      ) %>%
      mutate(
        cell_key = paste(
          attribute,
          level,
          sep = "\r"
        )
      )

    condition_objects <- lapply(
      2:5,
      function(n_value) {
        condition_data <- respondent_cell %>%
          filter(
            party_n == n_value
          )

        id_values <- sort(
          unique(condition_data$ID)
        )
        n_ids <- length(id_values)
        n_cells <- nrow(expected_cells)

        if (n_ids == 0) {
          stop("Check")
        }

        y_matrix <- matrix(
          0,
          nrow = n_ids,
          ncol = n_cells,
          dimnames = list(
            id_values,
            expected_cells$cell_key
          )
        )

        n_matrix <- matrix(
          0,
          nrow = n_ids,
          ncol = n_cells,
          dimnames = list(
            id_values,
            expected_cells$cell_key
          )
        )

        row_index <- match(
          condition_data$ID,
          id_values
        )
        column_index <- match(
          condition_data$cell_key,
          expected_cells$cell_key
        )

        y_matrix[cbind(row_index, column_index)] <-
          condition_data$y_sum
        n_matrix[cbind(row_index, column_index)] <-
          condition_data$n_obs

        if (any(colSums(n_matrix) == 0)) {
          missing_cells <- expected_cells$cell_key[
            colSums(n_matrix) == 0
          ]

          stop("Check attributes")
        }

        list(
          party_n = n_value,
          ids = id_values,
          cell_info = expected_cells,
          y_matrix = y_matrix,
          n_matrix = n_matrix
        )
      }
    )

    names(condition_objects) <- as.character(2:5)

    list(
      cue_map = cue_map,
      attributes = attributes,
      conditions = condition_objects
    )
  }

  estimate_relative_cue_indices <- function(
      prepared,
      cluster_weights = NULL
  ) {
    condition_results <- lapply(
      names(prepared$conditions),
      function(condition_name) {
        object <- prepared$conditions[[condition_name]]

        if (is.null(cluster_weights)) {
          weights <- rep(
            1,
            length(object$ids)
          )
        } else {
          weights <- cluster_weights[[condition_name]]
        }

        if (length(weights) != length(object$ids)) {
          stop("Check")
        }

        numerator <- as.numeric(
          crossprod(
            weights,
            object$y_matrix
          )
        )

        denominator <- as.numeric(
          crossprod(
            weights,
            object$n_matrix
          )
        )

        if (any(denominator <= 0)) {
          stop("Check attributes")
        }

        marginal_means <- numerator / denominator

        mm_table <- object$cell_info %>%
          transmute(
            party_n = object$party_n,
            attribute,
            level,
            marginal_mean = marginal_means
          )

        attribute_table <- mm_table %>%
          group_by(
            party_n,
            attribute
          ) %>%
          summarise(
            importance_pairwise =
              mean_absolute_pairwise_difference(
                marginal_mean
              ),
            n_levels = n(),
            .groups = "drop"
          ) %>%
          mutate(
            cue_family = unname(
              prepared$cue_map[attribute]
            ),
            baseline_selection_probability = 1 / party_n,
            importance_pairwise_adjusted =
              importance_pairwise /
                baseline_selection_probability
          )

        cue_table_long <- attribute_table %>%
          group_by(
            party_n,
            cue_family
          ) %>%
          summarise(
            importance_pairwise = mean(
              importance_pairwise,
              na.rm = TRUE
            ),
            importance_pairwise_adjusted = mean(
              importance_pairwise_adjusted,
              na.rm = TRUE
            ),
            .groups = "drop"
          )

        party_table <- cue_table_long %>%
          filter(
            cue_family == "party"
          ) %>%
          transmute(
            party_n,
            party_importance_pairwise =
              importance_pairwise,
            party_importance_pairwise_adjusted =
              importance_pairwise_adjusted
          )

        economic_table <- cue_table_long %>%
          filter(
            cue_family == "economic"
          ) %>%
          transmute(
            party_n,
            economic_importance_pairwise =
              importance_pairwise,
            economic_importance_pairwise_adjusted =
              importance_pairwise_adjusted
          )

        cue_table <- full_join(
          party_table,
          economic_table,
          by = "party_n"
        ) %>%
          mutate(
            baseline_selection_probability = 1 / party_n,

            total_importance_pairwise =
              party_importance_pairwise +
              economic_importance_pairwise,

            total_importance_pairwise_adjusted =
              party_importance_pairwise_adjusted +
              economic_importance_pairwise_adjusted,

            relative_party_weight_pairwise = if_else(
              total_importance_pairwise > 0,
              party_importance_pairwise /
                total_importance_pairwise,
              NA_real_
            ),

            relative_economic_weight_pairwise =
              1 - relative_party_weight_pairwise,

            relative_party_weight_pairwise_adjusted = if_else(
              total_importance_pairwise_adjusted > 0,
              party_importance_pairwise_adjusted /
                total_importance_pairwise_adjusted,
              NA_real_
            ),

            relative_economic_weight_pairwise_adjusted =
              1 - relative_party_weight_pairwise_adjusted,

            adjustment_identity_difference =
              relative_party_weight_pairwise_adjusted -
                relative_party_weight_pairwise
          )

        if (
          any(
            abs(cue_table$adjustment_identity_difference) > 1e-10,
            na.rm = TRUE
          )
        ) {
          stop("Check relative weight")
        }

        list(
          marginal_means = mm_table,
          attribute_importance = attribute_table,
          cue_importance = cue_table
        )
      }
    )

    list(
      marginal_means = bind_rows(
        lapply(
          condition_results,
          function(x) x$marginal_means
        )
      ),
      attribute_importance = bind_rows(
        lapply(
          condition_results,
          function(x) x$attribute_importance
        )
      ),
      cue_importance = bind_rows(
        lapply(
          condition_results,
          function(x) x$cue_importance
        )
      ) %>%
        arrange(party_n)
    )
  }

  estimate_relative_cue_slopes <- function(cue_importance) {
    cue_importance <- cue_importance %>%
      arrange(party_n)

    if (!identical(cue_importance$party_n, 2:5)) {
      stop("Check relative weight")
    }

    x <- cue_importance$party_n

    c(
      relative_party_weight_pairwise =
        linear_slope(
          cue_importance$relative_party_weight_pairwise,
          x
        ),

      party_importance_pairwise =
        linear_slope(
          cue_importance$party_importance_pairwise,
          x
        ),

      economic_importance_pairwise =
        linear_slope(
          cue_importance$economic_importance_pairwise,
          x
        ),

      party_importance_pairwise_adjusted =
        linear_slope(
          cue_importance$party_importance_pairwise_adjusted,
          x
        ),

      economic_importance_pairwise_adjusted =
        linear_slope(
          cue_importance$economic_importance_pairwise_adjusted,
          x
        )
    )
  }

  run_relative_cue_bootstrap <- function(
      prepared,
      B,
      seed,
      progress_every = 100
  ) {
    set.seed(seed)

    condition_results <- vector(
      "list",
      B
    )

    slope_names <- c(
      "relative_party_weight_pairwise",
      "party_importance_pairwise",
      "economic_importance_pairwise",
      "party_importance_pairwise_adjusted",
      "economic_importance_pairwise_adjusted"
    )

    slope_matrix <- matrix(
      NA_real_,
      nrow = B,
      ncol = length(slope_names),
      dimnames = list(
        NULL,
        slope_names
      )
    )

    for (b in seq_len(B)) {
      cluster_weights <- lapply(
        prepared$conditions,
        function(object) {
          n_ids <- length(object$ids)

          sampled_positions <- sample.int(
            n = n_ids,
            size = n_ids,
            replace = TRUE
          )

          tabulate(
            sampled_positions,
            nbins = n_ids
          )
        }
      )

      bootstrap_estimates <- estimate_relative_cue_indices(
        prepared = prepared,
        cluster_weights = cluster_weights
      )

      condition_results[[b]] <-
        bootstrap_estimates$cue_importance %>%
        select(
          party_n,
          party_importance_pairwise,
          economic_importance_pairwise,
          party_importance_pairwise_adjusted,
          economic_importance_pairwise_adjusted,
          relative_party_weight_pairwise
        ) %>%
        mutate(
          bootstrap_replication = b,
          .before = 1
        )

      slope_matrix[b, ] <- estimate_relative_cue_slopes(
        bootstrap_estimates$cue_importance
      )

      if (
        progress_every > 0 &&
        (b %% progress_every == 0 || b == B)
      ) {
        message("Bootstrap: ", b, "/", B)
      }
    }

    list(
      condition_estimates = bind_rows(
        condition_results
      ),
      slopes = as_tibble(
        slope_matrix
      ) %>%
        mutate(
          bootstrap_replication = row_number(),
          .before = 1
        )
    )
  }

  summarise_condition_intervals <- function(
      observed_cue_importance,
      bootstrap_condition_results
  ) {
    statistics <- c(
      "party_importance_pairwise",
      "economic_importance_pairwise",
      "party_importance_pairwise_adjusted",
      "economic_importance_pairwise_adjusted",
      "relative_party_weight_pairwise"
    )

    observed_long <- observed_cue_importance %>%
      select(
        party_n,
        all_of(statistics)
      ) %>%
      pivot_longer(
        cols = all_of(statistics),
        names_to = "statistic",
        values_to = "estimate"
      )

    bootstrap_long <- bootstrap_condition_results %>%
      pivot_longer(
        cols = all_of(statistics),
        names_to = "statistic",
        values_to = "value"
      ) %>%
      group_by(
        party_n,
        statistic
      ) %>%
      summarise(
        conf_low = safe_quantile(
          value,
          0.025
        ),
        conf_high = safe_quantile(
          value,
          0.975
        ),
        .groups = "drop"
      )

    observed_long %>%
      left_join(
        bootstrap_long,
        by = c(
          "party_n",
          "statistic"
        )
      )
  }

  summarise_slope_inference <- function(
      observed_slopes,
      bootstrap_slopes
  ) {
    statistic_names <- names(observed_slopes)

    map_dfr(
      statistic_names,
      function(statistic_name) {
        bootstrap_values <- bootstrap_slopes[[statistic_name]]
        bootstrap_values <- bootstrap_values[
          is.finite(bootstrap_values)
        ]

        expected_direction <- case_when(
          statistic_name ==
            "economic_importance_pairwise" ~ "negative",
          statistic_name %in% c(
            "party_importance_pairwise",
            "relative_party_weight_pairwise",
            "party_importance_pairwise_adjusted"
          ) ~ "positive",
          TRUE ~ "none"
        )

        analysis_role <- case_when(
          statistic_name %in% c(
            "party_importance_pairwise_adjusted",
            "economic_importance_pairwise_adjusted"
          ) ~ "exploratory_choice_set_adjusted",
          statistic_name == "relative_party_weight_pairwise" ~
            "derived_relative_share",
          TRUE ~ "manuscript_primary_unadjusted"
        )

        estimate <- unname(
          observed_slopes[[statistic_name]]
        )

        tibble(
          study = "Study 2",
          statistic = statistic_name,
          estimate = estimate,
          conf_low = safe_quantile(
            bootstrap_values,
            0.025
          ),
          conf_high = safe_quantile(
            bootstrap_values,
            0.975
          ),
          p_value_two_sided =
            bootstrap_two_sided_p(
              bootstrap_values
            ),
          expected_direction = expected_direction,
          analysis_role = analysis_role,
          estimate_in_expected_direction = case_when(
            expected_direction == "positive" ~ estimate > 0,
            expected_direction == "negative" ~ estimate < 0,
            TRUE ~ NA
          )
        )
      }
    )
  }

  relative_cue_prepared <- prepare_relative_cue_analysis(
    data = conjoint_all_m,
    cue_map = relative_cue_map
  )

  relative_cue_observed <- estimate_relative_cue_indices(
    prepared = relative_cue_prepared
  )

  relative_cue_observed_slopes <- estimate_relative_cue_slopes(
    relative_cue_observed$cue_importance
  )

  write_csv_safely(
    relative_cue_observed$marginal_means,
    "study2_relative_cue_marginal_means.csv"
  )

  write_csv_safely(
    relative_cue_observed$attribute_importance,
    "study2_relative_cue_attribute_importance.csv"
  )

  write_csv_safely(
    relative_cue_observed$cue_importance,
    "study2_relative_cue_importance_and_weight.csv"
  )

  relative_condition_bootstrap_file <- file.path(
    output_dir,
    paste0(
      "study2_relative_cue_condition_bootstrap_",
      unified_config$cue_importance_metric_version,
      "_B",
      relative_cue_bootstrap_B,
      ".csv"
    )
  )

  relative_slope_bootstrap_file <- file.path(
    output_dir,
    paste0(
      "study2_relative_cue_slope_bootstrap_",
      unified_config$cue_importance_metric_version,
      "_B",
      relative_cue_bootstrap_B,
      ".csv"
    )
  )

  use_saved_relative_bootstrap <-
    !rerun_relative_cue_bootstrap &&
    file.exists(relative_condition_bootstrap_file) &&
    file.exists(relative_slope_bootstrap_file)

  if (use_saved_relative_bootstrap) {
    message("Bootstrap cache")

    relative_cue_condition_bootstrap <- readr::read_csv(
      relative_condition_bootstrap_file,
      show_col_types = FALSE
    )

    relative_cue_slope_bootstrap <- readr::read_csv(
      relative_slope_bootstrap_file,
      show_col_types = FALSE
    )

    saved_B_condition <- n_distinct(
      relative_cue_condition_bootstrap$bootstrap_replication
    )
    saved_B_slope <- n_distinct(
      relative_cue_slope_bootstrap$bootstrap_replication
    )

    if (
      saved_B_condition != relative_cue_bootstrap_B ||
      saved_B_slope != relative_cue_bootstrap_B
    ) {
      message("Bootstrap cache")
      use_saved_relative_bootstrap <- FALSE
    }
  }

  if (!use_saved_relative_bootstrap) {
    relative_cue_bootstrap <- run_relative_cue_bootstrap(
      prepared = relative_cue_prepared,
      B = relative_cue_bootstrap_B,
      seed = relative_cue_bootstrap_seed,
      progress_every = relative_cue_bootstrap_progress_every
    )

    relative_cue_condition_bootstrap <-
      relative_cue_bootstrap$condition_estimates

    relative_cue_slope_bootstrap <-
      relative_cue_bootstrap$slopes

    readr::write_csv(
      relative_cue_condition_bootstrap,
      relative_condition_bootstrap_file
    )

    readr::write_csv(
      relative_cue_slope_bootstrap,
      relative_slope_bootstrap_file
    )
  }

  relative_cue_condition_intervals <- summarise_condition_intervals(
    observed_cue_importance =
      relative_cue_observed$cue_importance,
    bootstrap_condition_results =
      relative_cue_condition_bootstrap
  )

  relative_cue_slope_inference <- summarise_slope_inference(
    observed_slopes =
      relative_cue_observed_slopes,
    bootstrap_slopes =
      relative_cue_slope_bootstrap
  )

  write_csv_safely(
    relative_cue_condition_intervals,
    "study2_relative_cue_condition_intervals.csv"
  )

  write_csv_safely(
    relative_cue_slope_inference,
    "study2_relative_cue_slope_inference.csv"
  )

  relative_cue_primary_result <- relative_cue_slope_inference %>%
    filter(
      statistic ==
        "relative_party_weight_pairwise"
    )

  cat("\nStudy 2:相対比重の線形傾向\n")
  print(relative_cue_primary_result)


  relative_x_offset <- 0.075

  relative_panel_a_data <- relative_cue_condition_intervals %>%
    filter(
      statistic %in% c(
        "party_importance_pairwise",
        "economic_importance_pairwise"
      )
    ) %>%
    mutate(
      cue_family = recode(
        statistic,
        party_importance_pairwise = "政党手がかり",
        economic_importance_pairwise = "経済手がかり"
      ),
      cue_family = factor(
        cue_family,
        levels = c(
          "政党手がかり",
          "経済手がかり"
        )
      ),
      x_plot = case_when(
        cue_family == "政党手がかり" ~
          party_n + relative_x_offset,
        cue_family == "経済手がかり" ~
          party_n - relative_x_offset,
        TRUE ~ as.numeric(party_n)
      ),
      value_label = sprintf(
        "%.3f",
        estimate
      )
    )

  relative_panel_b_data <- relative_cue_condition_intervals %>%
    filter(
      statistic ==
        "relative_party_weight_pairwise"
    ) %>%
    mutate(
      value_label = sprintf(
        "%.1f%%",
        100 * estimate
      )
    )

  relative_adjusted_label_map <- relative_panel_a_data %>%
    distinct(
      statistic,
      cue_family
    ) %>%
    mutate(
      statistic = paste0(
        statistic,
        "_adjusted"
      ),
      cue_family = as.character(
        cue_family
      )
    )

  relative_panel_adjusted_data <- relative_cue_condition_intervals %>%
    filter(
      statistic %in% c(
        "party_importance_pairwise_adjusted",
        "economic_importance_pairwise_adjusted"
      )
    ) %>%
    left_join(
      relative_adjusted_label_map,
      by = "statistic"
    ) %>%
    mutate(
      cue_family = factor(
        cue_family,
        levels = levels(
          relative_panel_a_data$cue_family
        )
      ),
      x_plot = if_else(
        as.integer(cue_family) == 1L,
        party_n + relative_x_offset,
        party_n - relative_x_offset
      ),
      value_label = sprintf(
        "%.1f%%",
        100 * estimate
      )
    )

  relative_condition_suffix <- if (
    "政党名手がかり" %in%
      levels(relative_panel_a_data$cue_family)
  ) {
    "選択肢"
  } else {
    "政党"
  }

  relative_condition_axis_title <- if (
    relative_condition_suffix == "選択肢"
  ) {
    "政治経済状況の選択肢数"
  } else {
    "政党選択肢数"
  }

  relative_figure_font_family <- if (
    .Platform$OS.type == "windows"
  ) {
    "Yu Gothic"
  } else {
    "sans"
  }

  relative_theme_japanese_bw <- theme_bw(
    base_size = 12,
    base_family = relative_figure_font_family
  ) +
    theme(
      panel.grid.minor = element_blank(),
      panel.grid.major = element_line(
        linewidth = 0.30,
        color = "grey88"
      ),
      panel.border = element_rect(
        linewidth = 0.65,
        color = "black"
      ),
      axis.text = element_text(
        color = "black"
      ),
      axis.title = element_text(
        color = "black"
      ),
      plot.title = element_text(
        size = 12.5,
        face = "bold",
        hjust = 0
      ),
      plot.subtitle = element_text(
        size = 9.5,
        hjust = 0,
        margin = margin(
          b = 8
        )
      ),
      legend.position = "top",
      legend.justification = "center",
      legend.key.width = grid::unit(
        1.25,
        "cm"
      ),
      plot.margin = margin(
        8,
        10,
        8,
        8
      )
    )

  relative_panel_a <- ggplot(
    relative_panel_a_data,
    aes(
      x = x_plot,
      y = estimate,
      group = cue_family,
      linetype = cue_family
    )
  ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_linetype_manual(
      values = c(
        "政党手がかり" = "solid",
        "経済手がかり" = "dashed"
      )
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        "政党"
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      labels = label_number(
        accuracy = 0.005
      ),
      expand = expansion(
        mult = c(
          0.07,
          0.10
        )
      )
    ) +
    labs(
      title = "A:両手がかりの絶対的重要度",
      subtitle = "",
      x = "政党選択肢数",
      y = "手がかり重要度",
      linetype = NULL
    ) +
    guides(
      linetype = guide_legend(
        override.aes = list(
          linewidth = 0.90
        )
      )
    ) +
    relative_theme_japanese_bw

  relative_adjusted_linetypes <- setNames(
    c(
      "solid",
      "dashed"
    ),
    levels(
      relative_panel_adjusted_data$cue_family
    )
  )

  relative_panel_adjusted <- ggplot(
    relative_panel_adjusted_data,
    aes(
      x = x_plot,
      y = estimate,
      group = cue_family,
      linetype = cue_family
    )
  ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_linetype_manual(
      values = relative_adjusted_linetypes
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        relative_condition_suffix
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      labels = label_percent(
        accuracy = 1
      ),
      expand = expansion(
        mult = c(
          0.07,
          0.10
        )
      )
    ) +
    labs(
      title = "A:選択肢数調整済み重要度",
      subtitle =
        "未調整重要度 ÷ 平均選択確率(1/選択肢数)",
      x = relative_condition_axis_title,
      y = "平均選択確率に対する水準間差",
      linetype = NULL
    ) +
    guides(
      linetype = guide_legend(
        override.aes = list(
          linewidth = 0.90
        )
      )
    ) +
    relative_theme_japanese_bw

  relative_b_range <- range(
    c(
      relative_panel_b_data$conf_low,
      relative_panel_b_data$conf_high,
      0.5
    ),
    na.rm = TRUE
  )

  relative_b_padding <- max(
    0.025,
    0.10 * diff(relative_b_range)
  )

  relative_b_lower <- max(
    0,
    floor(
      20 *
        (relative_b_range[1] - relative_b_padding)
    ) / 20
  )

  relative_b_upper <- min(
    1,
    ceiling(
      20 *
        (relative_b_range[2] + relative_b_padding)
    ) / 20
  )

  if (relative_b_lower >= relative_b_upper) {
    relative_b_lower <- max(
      0,
      relative_b_lower - 0.05
    )
    relative_b_upper <- min(
      1,
      relative_b_upper + 0.05
    )
  }

  relative_panel_b <- ggplot(
    relative_panel_b_data,
    aes(
      x = party_n,
      y = estimate
    )
  ) +
    geom_hline(
      yintercept = 0.5,
      linetype = "dashed",
      linewidth = 0.55,
      color = "black"
    ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        "政党"
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      breaks = seq(
        relative_b_lower,
        relative_b_upper,
        by = 0.05
      ),
      labels = label_percent(
        accuracy = 1
      ),
      expand = expansion(
        mult = c(
          0.05,
          0.08
        )
      )
    ) +
    coord_cartesian(
      ylim = c(
        relative_b_lower,
        relative_b_upper
      )
    ) +
    labs(
      title = "B:相対的な政党手がかりの比重",
      subtitle =
        "政党手がかり重要度 ÷(政党手がかり重要度+経済手がかり重要度)",
      x = "政党選択肢数",
      y = "相対的な政党手がかり比重"
    ) +
    relative_theme_japanese_bw +
    theme(
      legend.position = "none"
    )

  relative_panel_c <- relative_panel_b +
    labs(
      title = paste0(
        "B:相対的な",
        levels(relative_panel_a_data$cue_family)[1],
        "の比重"
      )
    )

  figure_relative_weight_jp <- (
    relative_panel_a |
      relative_panel_b
  ) +
    patchwork::plot_layout(
      widths = c(
        1,
        1
      )
    )

  print(
    figure_relative_weight_jp
  )

  save_plot(
    "fig_study2_relative_cue_weight_jp_bw.png",
    figure_relative_weight_jp,
    width = 11.2,
    height = 5.4,
    dpi = 400
  )

  ggsave(
    filename = file.path(
      output_dir,
      "fig_study2_relative_cue_weight_jp_bw.pdf"
    ),
    plot = figure_relative_weight_jp,
    width = 11.2,
    height = 5.4,
    device = grDevices::cairo_pdf,
    bg = "white"
  )

  figure_relative_weight_adjusted_jp <- (
    relative_panel_adjusted |
      relative_panel_c
  ) +
    patchwork::plot_layout(
      widths = c(
        1,
        1
      )
    )

  print(
    figure_relative_weight_adjusted_jp
  )

  relative_adjusted_figure_stub <- paste0(
    "fig_study",
    stringr::str_extract(
      study_label,
      "[123]"
    ),
    "_relative_cue_weight_choice_set_adjusted_jp_bw"
  )

  save_plot(
    paste0(
      relative_adjusted_figure_stub,
      ".png"
    ),
    figure_relative_weight_adjusted_jp,
    width = 11.2,
    height = 5.4,
    dpi = 400
  )

  ggsave(
    filename = file.path(
      output_dir,
      paste0(
        relative_adjusted_figure_stub,
        ".pdf"
      )
    ),
    plot = figure_relative_weight_adjusted_jp,
    width = 11.2,
    height = 5.4,
    device = grDevices::cairo_pdf,
    bg = "white"
  )

  relative_cue_results <- list(
    prepared = relative_cue_prepared,
    marginal_means =
      relative_cue_observed$marginal_means,
    attribute_importance =
      relative_cue_observed$attribute_importance,
    cue_importance =
      relative_cue_observed$cue_importance,
    observed_slopes =
      relative_cue_observed_slopes,
    condition_bootstrap =
      relative_cue_condition_bootstrap,
    slope_bootstrap =
      relative_cue_slope_bootstrap,
    condition_intervals =
      relative_cue_condition_intervals,
    slope_inference =
      relative_cue_slope_inference,
    primary_result =
      relative_cue_primary_result,
    plots = list(
      absolute_importance = relative_panel_a,
      choice_set_adjusted_importance =
        relative_panel_adjusted,
      relative_party_weight = relative_panel_b,
      relative_party_weight_panel_c =
        relative_panel_c,
      combined = figure_relative_weight_jp,
      combined_with_choice_set_adjustment =
        figure_relative_weight_adjusted_jp
    )
  )

  saveRDS(
    relative_cue_results,
    file = file.path(
      output_dir,
      "study2_relative_cue_results.rds"
    )
  )


  saveRDS(
    list(
      settings = list(
        require_initial_consent = require_initial_consent,
        require_final_consent = require_final_consent,
        require_attention_check = require_attention_check,
        require_manipulation_check = require_manipulation_check
      ),
      sample_flow = sample_flow,
      n_by_party = n_by_party,
      valid_ids = valid_ids,
      conjoint_all = conjoint_all,
      conjoint_all_m = conjoint_all_m,
      covar_id = covar_id,
      models_by_party_n_nocov = models_by_party_n_nocov,
      models_by_party_n_cov = models_by_party_n_cov,
      m_interaction = m_interaction,
      models_clogit_nocov = models_clogit_nocov,
      relative_cue = relative_cue_results,
      plots = list(
        amce_cov = p_amce_cov_main,
        amce_nocov = p_amce_nocov_appendix,
        interaction = p_interaction,
        heatmap = p_heat_amce,
        heatmap_rank = p_heat_amce_rank,
        clogit_odds_ratio = p_clogit_or,
        relative_cue_weight = figure_relative_weight_jp,
        relative_cue_weight_choice_set_adjusted =
          figure_relative_weight_adjusted_jp
      )
    ),
    file = file.path(output_dir, "study2_analysis_objects.rds")
  )

  capture.output(
    sessionInfo(),
    file = file.path(output_dir, "sessionInfo.txt")
  )

  cat("
Done: ", normalizePath(output_dir), "
", sep = "")

  environment()
})

A.4 実験3:本文の図7・図8・図9

# 本文コード
study3_env <- local({
required_packages <- c(
    "dplyr",
    "tidyr",
    "stringr",
    "purrr",
    "readr",
    "fixest",
    "tibble",
    "forcats",
    "ggplot2",
    "scales",
    "survival",
    "patchwork"
  )

  missing_packages <- required_packages[
    !vapply(required_packages, requireNamespace, logical(1), quietly = TRUE)
  ]

  if (length(missing_packages) > 0) {
    stop("No packages")
  }

  library(dplyr)
  library(tidyr)
  library(stringr)
  library(purrr)
  library(readr)
  library(fixest)
  library(tibble)
  library(forcats)
  library(ggplot2)
  library(scales)
  library(survival)
  library(patchwork)

  data_file <- unified_config$study3$data_file
  output_dir <- unified_config$study3$output_dir

  dir.create(output_dir, showWarnings = FALSE, recursive = TRUE)

  require_initial_consent <- TRUE
  require_final_consent <- TRUE
  final_consent_var <- "Q8.1"

  require_attention_check <- TRUE
  require_manipulation_check <- TRUE

  require_all_five_tasks <- TRUE

  attention_check_var <- "Q25.1_11"
  attention_check_correct <- "3"

  relative_cue_bootstrap_B <- unified_config$relative_cue_bootstrap_B
  relative_cue_bootstrap_seed <- unified_config$relative_cue_bootstrap_seed + 3L
  relative_cue_bootstrap_progress_every <- unified_config$relative_cue_bootstrap_progress_every

  rerun_relative_cue_bootstrap <- unified_config$rerun_relative_cue_bootstrap

  figure_font_family <- if (.Platform$OS.type == "windows") {
    "Yu Gothic"
  } else {
    ""
  }


  norm_text <- function(x) {
    x %>%
      as.character() %>%
      str_replace_all("\u3000", " ") %>%
      str_squish() %>%
      str_replace_all("~", "~") %>%
      str_replace_all("〜", "~")
  }

  as_num <- function(x) {
    suppressWarnings(readr::parse_number(norm_text(x)))
  }

  first_existing <- function(dat, candidates) {
    out <- candidates[candidates %in% names(dat)]
    if (length(out) == 0) {
      NA_character_
    } else {
      out[1]
    }
  }

  get_var <- function(dat, candidates) {
    v <- first_existing(dat, candidates)

    if (is.na(v)) {
      rep(NA_character_, nrow(dat))
    } else {
      dat[[v]]
    }
  }

  is_response_code <- function(x, code) {
    x_norm <- norm_text(x)
    code_chr <- as.character(code)

    x_norm == code_chr |
      str_detect(x_norm, paste0("\\(", code_chr, "\\)$"))
  }

  relevel_if_present <- function(x, ref) {
    x <- factor(x)

    if (ref %in% levels(x)) {
      relevel(x, ref = ref)
    } else {
      x
    }
  }

  factor_miss <- function(x, miss = "欠損・無回答") {
    x <- norm_text(x)
    x[is.na(x) | x == "" | x == "NA"] <- miss
    factor(x)
  }

  mean_impute <- function(x) {
    x <- as.numeric(x)
    miss <- as.integer(is.na(x))

    if (all(is.na(x))) {
      value <- x
    } else {
      value <- ifelse(
        is.na(x),
        mean(x, na.rm = TRUE),
        x
      )
    }

    list(
      value = value,
      miss = miss
    )
  }

  write_csv_safely <- function(x, filename) {
    readr::write_csv(
      x,
      file.path(output_dir, filename),
      na = ""
    )
  }

  save_plot <- function(
    filename,
    plot,
    width,
    height,
    dpi = 300
  ) {
    ggplot2::ggsave(
      filename = file.path(output_dir, filename),
      plot = plot,
      width = width,
      height = height,
      dpi = dpi
    )
  }

  canonicalize_party_name <- function(x) {
    x_norm <- norm_text(x)
    x_compact <- str_replace_all(x_norm, "\\s+", "")

    case_when(
      is.na(x_compact) | x_compact == "" ~ NA_character_,

      x_compact %in% c(
        "自由民主党",
        "自民党",
        "自民"
      ) ~ "自由民主党",

      x_compact %in% c(
        "立憲民主党",
        "立民"
      ) ~ "立憲民主党",

      x_compact %in% c(
        "日本維新の会",
        "維新"
      ) ~ "日本維新の会",

      x_compact == "公明党" ~ "公明党",

      x_compact %in% c(
        "国民民主党",
        "国民"
      ) ~ "国民民主党",

      x_compact %in% c(
        "れいわ新選組",
        "れいわ"
      ) ~ "れいわ新選組",

      x_compact == "参政党" ~ "参政党",

      x_compact %in% c(
        "日本共産党",
        "共産党"
      ) ~ "日本共産党",

      x_compact == "中道改革連合" ~ "中道改革連合",

      x_compact == "日本保守党" ~ "日本保守党",

      x_compact %in% c(
        "社会民主党",
        "社民党"
      ) ~ "社会民主党",

      x_compact == "チームみらい" ~ "チームみらい",

      TRUE ~ x_norm
    )
  }

  canonicalize_economic_level <- function(x) {
    x_norm <- norm_text(x) %>%
      str_replace_all("+", "+") %>%
      str_replace_all("−|-|―", "-") %>%
      str_replace_all("%", "%")

    case_when(
      is.na(x_norm) | x_norm == "" ~ NA_character_,

      str_detect(x_norm, "GDP") &
        str_detect(x_norm, "プラス|\\+\\s*1") ~
        "GDP成長率プラス1%",

      str_detect(x_norm, "GDP") &
        str_detect(x_norm, "マイナス|-\\s*1") ~
        "GDP成長率マイナス1%",

      str_detect(x_norm, "GDP") &
        str_detect(x_norm, \\s*0|0\\s*%|変わらず|変化なし") ~
        "GDP成長率±0%",

      str_detect(x_norm, "日経平均") &
        str_detect(x_norm, "プラス|\\+\\s*1000") ~
        "日経平均前月同期比プラス1000円",

      str_detect(x_norm, "日経平均") &
        str_detect(x_norm, "マイナス|-\\s*1000") ~
        "日経平均前月同期比マイナス1000円",

      str_detect(x_norm, "日経平均") &
        str_detect(x_norm, "変わらず|変化なし|±\\s*0|0\\s*円") ~
        "日経平均前月同期比変わらず",

      str_detect(x_norm, "CPI|物価") &
        str_detect(x_norm, "プラス|\\+\\s*1") ~
        "CPI前期比プラス1ポイント",

      str_detect(x_norm, "CPI|物価") &
        str_detect(x_norm, "マイナス|-\\s*1") ~
        "CPI前期比マイナス1ポイント",

      str_detect(x_norm, "CPI|物価") &
        str_detect(x_norm, \\s*0|0\\s*ポイント|変わらず|変化なし") ~
        "CPI前期比±0ポイント",

      str_detect(x_norm, "失業率|雇用") &
        str_detect(x_norm, "プラス|\\+\\s*1") ~
        "失業率前期比プラス1%",

      str_detect(x_norm, "失業率|雇用") &
        str_detect(x_norm, "マイナス|-\\s*1") ~
        "失業率前期比マイナス1%",

      str_detect(x_norm, "失業率|雇用") &
        str_detect(x_norm, \\s*0|0\\s*%|変わらず|変化なし") ~
        "失業率前期比±0%",

      TRUE ~ x_norm
    )
  }

  level_to_attr_var <- function(x) {
    x_norm <- canonicalize_economic_level(x)

    case_when(
      str_detect(x_norm, "^GDP成長率") ~ "gdp_growth",
      str_detect(x_norm, "^日経平均") ~ "nikkei",
      str_detect(x_norm, "^CPI") ~ "cpi",
      str_detect(x_norm, "^失業率") ~ "unemployment",
      TRUE ~ NA_character_
    )
  }

  tidy_fixest <- function(model) {
    ct <- as.data.frame(fixest::coeftable(model))
    ct$term <- rownames(ct)

    estimate_col <- intersect(
      c("Estimate", "estimate"),
      names(ct)
    )[1]

    se_col <- intersect(
      c("Std. Error", "Std. error", "std.error"),
      names(ct)
    )[1]

    statistic_col <- intersect(
      c("t value", "z value", "statistic"),
      names(ct)
    )[1]

    p_col <- intersect(
      c("Pr(>|t|)", "Pr(>|z|)", "p.value"),
      names(ct)
    )[1]

    if (
      is.na(estimate_col) |
        is.na(se_col) |
        is.na(statistic_col) |
        is.na(p_col)
    ) {
      stop("Check data")
    }

    ct %>%
      as_tibble() %>%
      transmute(
        term = term,
        estimate = .data[[estimate_col]],
        std.error = .data[[se_col]],
        statistic = .data[[statistic_col]],
        p.value = .data[[p_col]],
        conf.low = estimate - 1.96 * std.error,
        conf.high = estimate + 1.96 * std.error
      )
  }


  if (!file.exists(data_file)) {
    stop("Check data")
  }

  raw <- readr::read_csv(
    data_file,
    col_types = cols(.default = col_character()),
    show_col_types = FALSE,
    name_repair = "minimal"
  )


  if (require_final_consent) {
    final_consent_var <- detect_final_consent_column(
      raw = raw,
      preferred_candidates = c("Q8.1", "Q9.1", "Q10.1"),
      study_label = "Study 3"
    )
  }

  if (require_attention_check) {
    attention_check_var <- detect_attention_check_column(
      raw = raw,
      preferred_candidates = c("Q25.1_11", "Q25.1_10"),
      study_label = "Study 3"
    )
  }

  if (!"ResponseId" %in% names(raw)) {
    stop("Check data")
  }

  df_header_removed <- raw %>%
    filter(
      !is.na(ResponseId),
      ResponseId != "",
      !str_detect(
        norm_text(ResponseId),
        "^(Response ID|回答ID)$|ImportId"
      )
    ) %>%
    mutate(ID = as.character(ResponseId))

  duplicate_ids <- df_header_removed %>%
    count(ID) %>%
    filter(n > 1)

  if (nrow(duplicate_ids) > 0) {
    print(duplicate_ids)
    stop("Check")
  }

  sample_flow <- tibble(
    stage = "Qualtrics質問文行・ImportId行を除外後",
    n = nrow(df_header_removed)
  )

  df <- df_header_removed

  if (require_initial_consent) {
    if (!"Q1.1" %in% names(df)) {
      stop("Check initial consent")
    }

    df <- df %>%
      filter(
        is_response_code(Q1.1, 1) |
          str_detect(
            norm_text(Q1.1),
            "趣旨に同意して.*協力する"
          )
      )

    sample_flow <- bind_rows(
      sample_flow,
      tibble(
        stage = "初回同意 Q1.1 = 1",
        n = nrow(df)
      )
    )
  }

  if (require_final_consent) {
    if (is.na(final_consent_var) || !final_consent_var %in% names(df)) {
      stop("Check final consent")
    }

    df <- df %>%
      filter(
        is_response_code(.data[[final_consent_var]], 1) |
          str_detect(
            norm_text(.data[[final_consent_var]]),
            "同意し.*回答結果を送信する"
          )
      )

    sample_flow <- bind_rows(
      sample_flow,
      tibble(
        stage = paste0("最終同意 ", final_consent_var, " = 1"),
        n = nrow(df)
      )
    )
  }

  if (require_attention_check) {
    if (!attention_check_var %in% names(df)) {
      stop("Check attention item")
    }

    attention_check_correct <- detect_attention_correct_code(
      df[[attention_check_var]],
      displayed_answer = 3L,
      recoded_answer = 6L,
      study_label = "Study 3"
    )

    df <- df %>%
      filter(
        is_response_code(
          .data[[attention_check_var]],
          attention_check_correct
        )
      )

    sample_flow <- bind_rows(
      sample_flow,
      tibble(
        stage = paste0(
          "指示項目正答(",
          attention_check_var,
          "、保存コード=",
          attention_check_correct,
          ")"
        ),
        n = nrow(df)
      )
    )
  }

  print(sample_flow)
  write_csv_safely(
    sample_flow,
    "sample_flow_before_conjoint.csv"
  )


  choice_map <- detect_conjoint_choice_map(
    raw = raw,
    party_numbers = 2:5,
    study_label = "Study 3"
  )

  manipulation_map <- detect_manipulation_map(
    raw = raw,
    choice_map = choice_map,
    study_label = "Study 3"
  )

  write_csv_safely(choice_map, "detected_choice_question_map.csv")
  write_csv_safely(manipulation_map, "detected_manipulation_question_map.csv")


  required_attr_vars <- c(
    "party_name",
    "gdp_growth",
    "nikkei",
    "cpi",
    "unemployment"
  )

  expected_party_levels <- c(
    "自由民主党",
    "立憲民主党",
    "日本維新の会",
    "公明党",
    "国民民主党",
    "れいわ新選組",
    "参政党",
    "日本共産党",
    "中道改革連合"
  )

  allowed_economic_levels <- list(
    gdp_growth = c(
      "GDP成長率±0%",
      "GDP成長率プラス1%",
      "GDP成長率マイナス1%"
    ),

    nikkei = c(
      "日経平均前月同期比変わらず",
      "日経平均前月同期比プラス1000円",
      "日経平均前月同期比マイナス1000円"
    ),

    cpi = c(
      "CPI前期比±0ポイント",
      "CPI前期比プラス1ポイント",
      "CPI前期比マイナス1ポイント"
    ),

    unemployment = c(
      "失業率前期比±0%",
      "失業率前期比プラス1%",
      "失業率前期比マイナス1%"
    )
  )


  make_profile_long <- function(dat, n_party) {

    map_n <- choice_map %>%
      filter(party_n == n_party)

    qvars <- map_n$choice_var

    missing_q <- setdiff(qvars, names(dat))

    if (length(missing_q) > 0) {
      stop("Check choice columns")
    }

    dat_n <- dat %>%
      filter(
        if_any(
          all_of(qvars),
          ~ !is.na(.x) & norm_text(.x) != ""
        )
      )

    if (require_manipulation_check) {
      manipulation_row <- manipulation_map %>%
        filter(party_n == n_party)

      manipulation_var <- manipulation_row$manipulation_var
      correct_answer <- manipulation_row$correct_answer

      if (!manipulation_var %in% names(dat_n)) {
        stop("Check manipulation item")
      }

      dat_n <- dat_n %>%
        filter(
          is_response_code(
            .data[[manipulation_var]],
            correct_answer
          )
        )
    }

    choice_long <- dat_n %>%
      select(
        ID,
        all_of(qvars)
      ) %>%
      pivot_longer(
        cols = all_of(qvars),
        names_to = "choice_var",
        values_to = "choice_raw"
      ) %>%
      left_join(
        map_n,
        by = "choice_var"
      ) %>%
      mutate(
        choice = parse_choice_position(choice_raw)
      ) %>%
      filter(!is.na(choice)) %>%
      select(
        ID,
        party_n,
        task,
        choice
      )

    invalid_choice <- choice_long %>%
      filter(
        choice < 1 |
          choice > n_party
      )

    if (nrow(invalid_choice) > 0) {
      print(invalid_choice)
      stop("Check choice values")
    }

    duplicate_choice <- choice_long %>%
      count(
        ID,
        task
      ) %>%
      filter(n != 1)

    if (nrow(duplicate_choice) > 0) {
      print(duplicate_choice)
      stop("Check duplicate choices")
    }

    party_regex <- paste0(
      "^S3_P",
      n_party,
      "_PARTY_([1-5])_([1-",
      n_party,
      "])$"
    )

    party_cols <- names(dat_n)[
      str_detect(
        names(dat_n),
        party_regex
      )
    ]

    expected_party_cols_n <- 5 * n_party

    if (length(party_cols) != expected_party_cols_n) {
      stop("Check")
    }

    party_long <- dat_n %>%
      select(
        ID,
        all_of(party_cols)
      ) %>%
      pivot_longer(
        cols = all_of(party_cols),
        names_to = "party_var",
        values_to = "party_name_raw"
      ) %>%
      extract(
        party_var,
        into = c(
          "task",
          "profile"
        ),
        regex = party_regex,
        convert = TRUE
      ) %>%
      mutate(
        party_name = canonicalize_party_name(
          party_name_raw
        )
      ) %>%
      filter(
        task %in% 1:5,
        profile %in% 1:n_party,
        !is.na(party_name),
        party_name != ""
      ) %>%
      select(
        ID,
        task,
        profile,
        party_name
      )

    duplicate_party_name <- party_long %>%
      count(
        ID,
        task,
        profile
      ) %>%
      filter(n != 1)

    if (nrow(duplicate_party_name) > 0) {
      print(
        head(
          duplicate_party_name,
          50
        )
      )
      stop("Check")
    }

    level_regex <- paste0(
      "^S3_P",
      n_party,
      "_F_([1-5])_([1-",
      n_party,
      "])_([1-4])$"
    )

    level_cols <- names(dat_n)[
      str_detect(
        names(dat_n),
        level_regex
      )
    ]

    expected_level_cols_n <- 5 * n_party * 4

    if (length(level_cols) != expected_level_cols_n) {
      stop("Check attributes")
    }

    level_long <- dat_n %>%
      select(
        ID,
        all_of(level_cols)
      ) %>%
      pivot_longer(
        cols = all_of(level_cols),
        names_to = "fvar",
        values_to = "level_raw"
      ) %>%
      extract(
        fvar,
        into = c(
          "task",
          "profile",
          "attr_order"
        ),
        regex = level_regex,
        convert = TRUE
      ) %>%
      mutate(
        level = canonicalize_economic_level(
          level_raw
        ),
        attr_var = level_to_attr_var(
          level
        )
      ) %>%
      filter(
        task %in% 1:5,
        profile %in% 1:n_party,
        attr_order %in% 1:4,
        !is.na(level),
        level != ""
      )

    unknown_levels <- level_long %>%
      filter(
        is.na(attr_var)
      ) %>%
      distinct(
        level_raw,
        level
      )

    if (nrow(unknown_levels) > 0) {
      print(unknown_levels)
      stop("Check attributes")
    }

    profile_attribute_count <- level_long %>%
      count(
        ID,
        task,
        profile,
        name = "n_attribute_rows"
      ) %>%
      filter(
        n_attribute_rows != 4
      )

    if (nrow(profile_attribute_count) > 0) {
      print(
        head(
          profile_attribute_count,
          50
        )
      )
      stop("Check attributes")
    }

    duplicate_attribute <- level_long %>%
      count(
        ID,
        task,
        profile,
        attr_var
      ) %>%
      filter(n != 1)

    if (nrow(duplicate_attribute) > 0) {
      print(
        head(
          duplicate_attribute,
          50
        )
      )
      stop("Check attributes")
    }

    economic_wide <- level_long %>%
      select(
        ID,
        task,
        profile,
        attr_var,
        level
      ) %>%
      pivot_wider(
        names_from = attr_var,
        values_from = level,
        values_fn = list(
          level = ~ first(.x)
        )
      )

    profile_wide <- party_long %>%
      inner_join(
        economic_wide,
        by = c(
          "ID",
          "task",
          "profile"
        )
      ) %>%
      inner_join(
        choice_long,
        by = c(
          "ID",
          "task"
        )
      ) %>%
      mutate(
        party_n = n_party,
        selected = as.integer(
          profile == choice
        ),
        task_id = paste(
          ID,
          party_n,
          task,
          sep = "_"
        ),
        profile_id = paste(
          ID,
          party_n,
          task,
          profile,
          sep = "_"
        )
      )

    missing_attr <- setdiff(
      required_attr_vars,
      names(profile_wide)
    )

    if (length(missing_attr) > 0) {
      stop("Check attributes")
    }

    profile_wide <- profile_wide %>%
      select(
        ID,
        party_n,
        task,
        profile,
        choice,
        selected,
        task_id,
        profile_id,
        all_of(required_attr_vars)
      ) %>%
      arrange(
        ID,
        task,
        profile
      )

    return(profile_wide)
  }


  conjoint_2 <- make_profile_long(
    df,
    2
  )

  conjoint_3 <- make_profile_long(
    df,
    3
  )

  conjoint_4 <- make_profile_long(
    df,
    4
  )

  conjoint_5 <- make_profile_long(
    df,
    5
  )

  conjoint_all_unfiltered <- bind_rows(
    conjoint_2,
    conjoint_3,
    conjoint_4,
    conjoint_5
  )


  id_task_check <- conjoint_all_unfiltered %>%
    group_by(
      ID,
      party_n,
      task
    ) %>%
    summarise(
      n_profiles = n(),
      selected_sum = sum(selected),
      .groups = "drop"
    ) %>%
    group_by(
      ID,
      party_n
    ) %>%
    summarise(
      n_tasks = n_distinct(task),
      all_tasks_ok = all(
        n_profiles == party_n &
          selected_sum == 1
      ),
      .groups = "drop"
    )

  if (require_all_five_tasks) {
    valid_ids <- id_task_check %>%
      filter(
        n_tasks == 5,
        all_tasks_ok
      )
  } else {
    valid_ids <- id_task_check %>%
      filter(all_tasks_ok)
  }

  conjoint_all <- conjoint_all_unfiltered %>%
    semi_join(
      valid_ids,
      by = c(
        "ID",
        "party_n"
      )
    )

  sample_flow <- bind_rows(
    sample_flow,
    tibble(
      stage = if (require_all_five_tasks) {
        "5課題すべてが完全な回答者"
      } else {
        "回答済み課題がすべて完全な回答者"
      },
      n = n_distinct(conjoint_all$ID)
    )
  )

  n_by_party <- valid_ids %>%
    count(
      party_n,
      name = "n"
    ) %>%
    complete(
      party_n = 2:5,
      fill = list(n = 0)
    ) %>%
    arrange(party_n)

  n_total <- valid_ids %>%
    summarise(
      n = n_distinct(ID)
    ) %>%
    pull(n)

  figure_n_labels <- bind_rows(
    tibble(
      position = "全サンプル",
      label = paste0(
        "全サンプル, n=",
        scales::comma(n_total)
      )
    ),

    n_by_party %>%
      mutate(
        position = paste0(
          party_n,
          "選択肢"
        ),
        label = paste0(
          "n=",
          scales::comma(n)
        )
      ) %>%
      select(
        position,
        label
      )
  )

  cat("\n分析対象者数\n")
  print(n_by_party)
  cat(
    "全サンプル n=",
    n_total,
    "\n",
    sep = ""
  )

  write_csv_safely(
    sample_flow,
    "sample_flow.csv"
  )

  write_csv_safely(
    id_task_check,
    "id_task_check.csv"
  )

  write_csv_safely(
    valid_ids,
    "valid_ids.csv"
  )

  write_csv_safely(
    n_by_party,
    "n_by_party.csv"
  )

  write_csv_safely(
    figure_n_labels,
    "figure_n_labels.csv"
  )


  check_profile <- conjoint_all %>%
    group_by(
      party_n,
      ID,
      task,
      task_id
    ) %>%
    summarise(
      n_profiles = n(),
      selected_sum = sum(selected),
      .groups = "drop"
    ) %>%
    count(
      party_n,
      n_profiles,
      selected_sum
    )

  print(check_profile)

  stopifnot(
    all(
      check_profile$n_profiles ==
        check_profile$party_n
    )
  )

  stopifnot(
    all(
      check_profile$selected_sum == 1
    )
  )

  allowed_economic_df <- enframe(
    allowed_economic_levels,
    name = "name",
    value = "value"
  ) %>%
    unnest(value)

  unexpected_economic_values <- conjoint_all %>%
    select(
      all_of(
        names(allowed_economic_levels)
      )
    ) %>%
    pivot_longer(
      cols = everything(),
      names_to = "name",
      values_to = "value"
    ) %>%
    filter(
      !is.na(value),
      value != ""
    ) %>%
    distinct(
      name,
      value
    ) %>%
    anti_join(
      allowed_economic_df,
      by = c(
        "name",
        "value"
      )
    )

  print(unexpected_economic_values)

  stopifnot(
    nrow(unexpected_economic_values) == 0
  )

  observed_party_levels <- conjoint_all %>%
    distinct(party_name) %>%
    arrange(party_name)

  observed_economic_levels <- conjoint_all %>%
    select(
      all_of(
        names(allowed_economic_levels)
      )
    ) %>%
    pivot_longer(
      cols = everything(),
      names_to = "attribute",
      values_to = "level"
    ) %>%
    distinct(
      attribute,
      level
    ) %>%
    arrange(
      attribute,
      level
    )

  party_level_frequency <- conjoint_all %>%
    count(
      party_n,
      party_name,
      name = "n_profiles"
    ) %>%
    group_by(party_n) %>%
    mutate(
      proportion = n_profiles /
        sum(n_profiles)
    ) %>%
    ungroup()

  economic_level_frequency <- conjoint_all %>%
    select(
      party_n,
      all_of(
        names(allowed_economic_levels)
      )
    ) %>%
    pivot_longer(
      cols = all_of(
        names(allowed_economic_levels)
      ),
      names_to = "attribute",
      values_to = "level"
    ) %>%
    count(
      party_n,
      attribute,
      level,
      name = "n_profiles"
    ) %>%
    group_by(
      party_n,
      attribute
    ) %>%
    mutate(
      proportion = n_profiles /
        sum(n_profiles)
    ) %>%
    ungroup()

  write_csv_safely(
    check_profile,
    "profile_expansion_check.csv"
  )

  write_csv_safely(
    observed_party_levels,
    "observed_party_levels.csv"
  )

  write_csv_safely(
    observed_economic_levels,
    "observed_economic_levels.csv"
  )

  write_csv_safely(
    party_level_frequency,
    "party_level_frequency.csv"
  )

  write_csv_safely(
    economic_level_frequency,
    "economic_level_frequency.csv"
  )

  write_csv_safely(
    conjoint_all,
    "study3_profile_level_data.csv"
  )


  analysis_ids <- valid_ids %>%
    select(
      ID,
      party_n
    )

  if (attention_check_var %in% names(df)) {
    attention_summary <- df %>%
      semi_join(
        analysis_ids,
        by = "ID"
      ) %>%
      transmute(
        ID,
        attention_response = norm_text(
          .data[[attention_check_var]]
        ),
        attention_pass = is_response_code(
          .data[[attention_check_var]],
          attention_check_correct
        )
      ) %>%
      count(
        attention_response,
        attention_pass,
        name = "n"
      ) %>%
      arrange(
        desc(attention_pass),
        attention_response
      )
  } else {
    attention_summary <- tibble(
      attention_response = character(),
      attention_pass = logical(),
      n = integer()
    )
  }

  manipulation_summary <- map_dfr(
    2:5,
    function(n_party) {
      manipulation_row <- manipulation_map %>%
        filter(
          party_n == n_party
        )

      v <- manipulation_row$manipulation_var
      correct <- manipulation_row$correct_answer

      if (!v %in% names(df)) {
        return(
          tibble(
            party_n = n_party,
            response = NA_character_,
            correct = NA,
            n = 0L
          )
        )
      }

      df %>%
        semi_join(
          analysis_ids %>%
            filter(
              party_n == n_party
            ),
          by = "ID"
        ) %>%
        transmute(
          party_n = n_party,
          response = norm_text(
            .data[[v]]
          ),
          correct = is_response_code(
            .data[[v]],
            correct
          )
        ) %>%
        count(
          party_n,
          response,
          correct,
          name = "n"
        )
    }
  )

  write_csv_safely(
    attention_summary,
    "attention_check_summary.csv"
  )

  write_csv_safely(
    manipulation_summary,
    "party_number_check_summary.csv"
  )


  observed_party_vector <- conjoint_all %>%
    distinct(party_name) %>%
    pull(party_name)

  party_reference <- if (
    "自由民主党" %in% observed_party_vector
  ) {
    "自由民主党"
  } else {
    sort(observed_party_vector)[1]
  }

  if (party_reference != "自由民主党") {
    warning("Check")
  }

  party_levels_use <- c(
    party_reference,

    expected_party_levels[
      expected_party_levels %in%
        observed_party_vector &
        expected_party_levels !=
        party_reference
    ],

    sort(
      setdiff(
        observed_party_vector,
        expected_party_levels
      )
    )
  ) %>%
    unique()

  conjoint_all_m <- conjoint_all %>%
    mutate(
      selected = as.integer(selected),
      ID = as.character(ID),

      party_name = factor(
        party_name,
        levels = party_levels_use
      ),

      gdp_growth = factor(
        gdp_growth,
        levels = allowed_economic_levels$gdp_growth
      ),

      nikkei = factor(
        nikkei,
        levels = allowed_economic_levels$nikkei
      ),

      cpi = factor(
        cpi,
        levels = allowed_economic_levels$cpi
      ),

      unemployment = factor(
        unemployment,
        levels = allowed_economic_levels$unemployment
      ),

      party_n_f = factor(
        as.character(party_n),
        levels = c(
          "2",
          "3",
          "4",
          "5"
        )
      ),

      party_n_c = party_n - 2
    )

  attr_terms <- c(
    "party_name",
    "gdp_growth",
    "nikkei",
    "cpi",
    "unemployment"
  )

  economic_attr_terms <- c(
    "gdp_growth",
    "nikkei",
    "cpi",
    "unemployment"
  )


  formula_nocov <- as.formula(
    paste(
      "selected ~",
      paste(
        attr_terms,
        collapse = " + "
      )
    )
  )

  run_amce_nocov <- function(dat) {
    feols(
      formula_nocov,
      data = dat,
      vcov = ~ ID
    )
  }

  models_by_party_n_nocov <- conjoint_all_m %>%
    split(.$party_n) %>%
    map(run_amce_nocov)

  capture.output(
    etable(
      models_by_party_n_nocov
    ),
    file = file.path(
      output_dir,
      "amce_nocov_models.txt"
    )
  )


  m_interaction <- feols(
    selected ~
      party_n_f *
      (
        party_name +
          gdp_growth +
          nikkei +
          cpi +
          unemployment
      ),
    data = conjoint_all_m,
    vcov = ~ ID
  )

  capture.output(
    summary(m_interaction),
    file = file.path(
      output_dir,
      "amce_interaction_model.txt"
    )
  )


  m_linear_trend <- feols(
    selected ~
      party_n_c *
      (
        party_name +
          gdp_growth +
          nikkei +
          cpi +
          unemployment
      ),
    data = conjoint_all_m,
    vcov = ~ ID
  )

  capture.output(
    summary(m_linear_trend),
    file = file.path(
      output_dir,
      "amce_linear_trend_model.txt"
    )
  )


  party_term_labels <- tibble(
    term = paste0(
      "party_name",
      party_levels_use[-1]
    ),
    attribute = "政権与党の政党名",
    cue_type = "政党名の手がかり",
    label = party_levels_use[-1],
    order = seq_along(
      party_levels_use[-1]
    )
  )

  economic_term_labels <- tribble(
    ~term, ~attribute, ~cue_type, ~label, ~order,

    "gdp_growthGDP成長率プラス1%",
    "GDP成長率",
    "経済の手がかり",
    "GDP:プラス1%",
    1,

    "gdp_growthGDP成長率マイナス1%",
    "GDP成長率",
    "経済の手がかり",
    "GDP:マイナス1%",
    2,

    "nikkei日経平均前月同期比プラス1000円",
    "日経平均",
    "経済の手がかり",
    "日経平均:プラス1000円",
    3,

    "nikkei日経平均前月同期比マイナス1000円",
    "日経平均",
    "経済の手がかり",
    "日経平均:マイナス1000円",
    4,

    "cpiCPI前期比プラス1ポイント",
    "CPI",
    "経済の手がかり",
    "CPI:プラス1ポイント",
    5,

    "cpiCPI前期比マイナス1ポイント",
    "CPI",
    "経済の手がかり",
    "CPI:マイナス1ポイント",
    6,

    "unemployment失業率前期比プラス1%",
    "失業率",
    "経済の手がかり",
    "失業率:プラス1%",
    7,

    "unemployment失業率前期比マイナス1%",
    "失業率",
    "経済の手がかり",
    "失業率:マイナス1%",
    8
  )

  term_labels <- bind_rows(
    party_term_labels %>%
      mutate(
        order_global = order
      ),

    economic_term_labels %>%
      mutate(
        order_global =
          max(
            c(
              party_term_labels$order,
              0
            )
          ) +
          order
      )
  ) %>%
    select(
      term,
      attribute,
      cue_type,
      label,
      order = order_global
    )

  attribute_order <- c(
    "政権与党の政党名",
    "GDP成長率",
    "日経平均",
    "CPI",
    "失業率"
  )

  label_order <- term_labels %>%
    arrange(order) %>%
    pull(label)

  make_amce_plot_df <- function(models) {
    imap_dfr(
      models,
      ~ tidy_fixest(.x) %>%
        mutate(
          party_n = as.character(.y)
        )
    ) %>%
      left_join(
        term_labels,
        by = "term"
      ) %>%
      filter(
        !is.na(attribute)
      ) %>%
      mutate(
        estimate_pp = estimate * 100,
        conf.low_pp = conf.low * 100,
        conf.high_pp = conf.high * 100,

        party_n = factor(
          party_n,
          levels = c(
            "2",
            "3",
            "4",
            "5"
          ),
          labels = c(
            "2選択肢",
            "3選択肢",
            "4選択肢",
            "5選択肢"
          )
        ),

        attribute = factor(
          attribute,
          levels = attribute_order
        ),

        label = factor(
          label,
          levels = rev(
            label_order
          )
        )
      )
  }

  amce_plot_nocov <- make_amce_plot_df(
    models_by_party_n_nocov
  )

  write_csv_safely(
    amce_plot_nocov,
    "amce_nocov_coefficients.csv"
  )

  interaction_plot_df <- tidy_fixest(
    m_interaction
  ) %>%
    filter(
      str_detect(
        term,
        "party_n_f[345]"
      )
    ) %>%
    mutate(
      party_n_code = str_extract(
        term,
        "party_n_f[345]"
      ),

      party_n = str_remove(
        party_n_code,
        "party_n_f"
      ),

      base_term = term %>%
        str_remove(
          "party_n_f[345]:"
        ) %>%
        str_remove(
          ":party_n_f[345]"
        )
    ) %>%
    left_join(
      term_labels,
      by = c(
        "base_term" = "term"
      )
    ) %>%
    filter(
      !is.na(attribute)
    ) %>%
    mutate(
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,

      party_n_label = factor(
        party_n,
        levels = c(
          "3",
          "4",
          "5"
        ),
        labels = c(
          "3選択肢",
          "4選択肢",
          "5選択肢"
        )
      ),

      attribute = factor(
        attribute,
        levels = attribute_order
      ),

      label = factor(
        label,
        levels = rev(
          label_order
        )
      )
    )

  write_csv_safely(
    interaction_plot_df,
    "amce_interaction_coefficients.csv"
  )

  linear_trend_plot_df <- tidy_fixest(
    m_linear_trend
  ) %>%
    filter(
      str_detect(
        term,
        "party_n_c:"
      ) |
        str_detect(
          term,
          ":party_n_c"
        )
    ) %>%
    mutate(
      base_term = term %>%
        str_remove(
          "party_n_c:"
        ) %>%
        str_remove(
          ":party_n_c"
        )
    ) %>%
    left_join(
      term_labels,
      by = c(
        "base_term" = "term"
      )
    ) %>%
    filter(
      !is.na(attribute)
    ) %>%
    mutate(
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,

      attribute = factor(
        attribute,
        levels = attribute_order
      ),

      label = factor(
        label,
        levels = rev(
          label_order
        )
      )
    )

  write_csv_safely(
    linear_trend_plot_df,
    "amce_linear_trend_coefficients.csv"
  )


  recode_female_study3 <- function(x) {
    x_num <- as_num(x)

    case_when(
      x_num == 2 ~ 1L,
      x_num == 1 ~ 0L,
      TRUE ~ NA_integer_
    )
  }

  recode_college_grad_study3 <- function(x) {
    x_num <- as_num(x)

    case_when(
      x_num %in% c(
        4,
        5
      ) ~ 1L,

      x_num %in% c(
        1,
        2,
        3
      ) ~ 0L,

      TRUE ~ NA_integer_
    )
  }

  recode_self_ideology_study3 <- function(x) {
    x_num <- as_num(x)

    case_when(
      x_num %in% 1:8 ~ x_num,
      x_num == 12 ~ 9,
      x_num == 13 ~ 10,
      x_num == 14 ~ 11,
      TRUE ~ NA_real_
    )
  }

  recode_party_support_study3 <- function(x) {
    x_num <- as_num(x)

    case_when(
      x_num == 1 ~ "自由民主党",
      x_num == 2 ~ "中道改革連合",
      x_num == 3 ~ "立憲民主党",
      x_num == 4 ~ "公明党",
      x_num == 5 ~ "日本維新の会",
      x_num == 6 ~ "国民民主党",
      x_num == 7 ~ "れいわ新選組",
      x_num == 8 ~ "日本共産党",
      x_num == 9 ~ "参政党",
      x_num == 10 ~ "日本保守党",
      x_num == 11 ~ "社会民主党",
      x_num == 12 ~ "チームみらい",
      x_num == 13 ~ "その他",
      x_num == 14 ~ "支持政党なし",
      x_num == 15 ~ "わからない",
      x_num == 16 ~ "答えたくない",
      TRUE ~ NA_character_
    )
  }

  gender_raw <- get_var(
    df,
    c(
      "Q2.1",
      "Q2_1"
    )
  )

  age_raw <- get_var(
    df,
    c(
      "Q2.2_13",
      "Q2.2.13",
      "Q2_2_13",
      "Q2.2_2",
      "Q2.2.2",
      "Q2_2_2"
    )
  )

  education_raw <- get_var(
    df,
    c(
      "Q2.3",
      "Q2_3"
    )
  )

  region_raw <- get_var(
    df,
    c(
      "Q2.4_1",
      "Q2.4.1",
      "Q2_4_1"
    )
  )

  prefecture_raw <- get_var(
    df,
    c(
      "Q2.4_2",
      "Q2.4.2",
      "Q2_4_2"
    )
  )

  income_gross_raw <- get_var(
    df,
    c(
      "Q2.5_1",
      "Q2.5.1",
      "Q2_5_1"
    )
  )

  income_net_raw <- get_var(
    df,
    c(
      "Q2.5_2",
      "Q2.5.2",
      "Q2_5_2"
    )
  )

  zero_income_reason_raw <- get_var(
    df,
    c(
      "Q2.6",
      "Q2_6"
    )
  )

  self_ideology_raw <- get_var(
    df,
    c(
      "Q25.1_1",
      "Q25.1.1",
      "Q25_1_1"
    )
  )

  party_support_raw <- get_var(
    df,
    c(
      "Q7.2",
      "Q7_2"
    )
  )

  covar_id <- df %>%
    transmute(
      ID = as.character(ResponseId),

      female = recode_female_study3(
        gender_raw
      ),

      age = as_num(
        age_raw
      ),

      college_grad = recode_college_grad_study3(
        education_raw
      ),

      region = factor_miss(
        region_raw
      ),

      prefecture = factor_miss(
        prefecture_raw
      ),

      income_gross = as_num(
        income_gross_raw
      ),

      income_net = as_num(
        income_net_raw
      ),

      income_gross_log = log1p(
        income_gross
      ),

      income_net_log = log1p(
        income_net
      ),

      zero_income_reason = factor_miss(
        zero_income_reason_raw
      ),

      self_ideology = recode_self_ideology_study3(
        self_ideology_raw
      ),

      party_support = recode_party_support_study3(
        party_support_raw
      ),

      party_support_f = factor_miss(
        party_support
      ),

      party_support_profile = canonicalize_party_name(
        party_support
      )
    ) %>%
    semi_join(
      valid_ids %>%
        select(ID),
      by = "ID"
    ) %>%
    distinct(
      ID,
      .keep_all = TRUE
    )

  covar_id <- covar_id %>%
    mutate(
      age = if_else(
        age >= 18 &
          age <= 79,
        age,
        NA_real_
      )
    )

  age_imp_obj <- mean_impute(
    covar_id$age
  )

  income_gross_imp_obj <- mean_impute(
    covar_id$income_gross_log
  )

  self_ideology_imp_obj <- mean_impute(
    covar_id$self_ideology
  )

  covar_id <- covar_id %>%
    mutate(
      female_imp = if_else(
        is.na(female),
        0L,
        female
      ),

      female_miss = as.integer(
        is.na(female)
      ),

      college_grad_imp = if_else(
        is.na(college_grad),
        0L,
        college_grad
      ),

      college_grad_miss = as.integer(
        is.na(college_grad)
      ),

      age_imp = age_imp_obj$value,

      age_miss = age_imp_obj$miss,

      income_gross_log_imp =
        income_gross_imp_obj$value,

      income_gross_log_miss =
        income_gross_imp_obj$miss,

      self_ideology_imp =
        self_ideology_imp_obj$value,

      self_ideology_miss =
        self_ideology_imp_obj$miss
    )

  covariate_missing_summary <- covar_id %>%
    summarise(
      n_ids = n_distinct(ID),
      female_missing = sum(
        is.na(female)
      ),
      age_missing = sum(
        is.na(age)
      ),
      college_grad_missing = sum(
        is.na(college_grad)
      ),
      income_gross_missing = sum(
        is.na(income_gross_log)
      ),
      self_ideology_missing = sum(
        is.na(self_ideology)
      ),
      party_support_missing = sum(
        is.na(party_support)
      )
    )

  zero_income_summary <- covar_id %>%
    count(
      zero_income_reason,
      name = "n"
    ) %>%
    arrange(
      desc(n)
    )

  print(covariate_missing_summary)

  write_csv_safely(
    covar_id,
    "respondent_covariates.csv"
  )

  write_csv_safely(
    covariate_missing_summary,
    "covariate_missing_summary.csv"
  )

  write_csv_safely(
    zero_income_summary,
    "zero_income_reason_summary.csv"
  )


  conjoint_all_cov <- conjoint_all_m %>%
    left_join(
      covar_id,
      by = "ID"
    )

  covariate_terms <- c(
    "female_imp",
    "female_miss",
    "age_imp",
    "age_miss",
    "college_grad_imp",
    "college_grad_miss",
    "income_gross_log_imp",
    "income_gross_log_miss",
    "self_ideology_imp",
    "self_ideology_miss",
    "party_support_f"
  )

  has_variation <- function(dat, v) {
    if (!v %in% names(dat)) {
      return(FALSE)
    }

    dplyr::n_distinct(
      dat[[v]],
      na.rm = TRUE
    ) > 1
  }

  covariate_terms_use <- covariate_terms[
    map_lgl(
      covariate_terms,
      ~ has_variation(
        conjoint_all_cov,
        .x
      )
    )
  ]

  formula_cov <- as.formula(
    paste(
      "selected ~",
      paste(
        c(
          attr_terms,
          covariate_terms_use
        ),
        collapse = " + "
      )
    )
  )

  run_amce_cov <- function(dat) {
    feols(
      formula_cov,
      data = dat,
      vcov = ~ ID
    )
  }

  models_by_party_n_cov <- conjoint_all_cov %>%
    split(.$party_n) %>%
    map(run_amce_cov)

  capture.output(
    etable(
      models_by_party_n_nocov,
      models_by_party_n_cov,
      headers = c(
        rep(
          "共変量なし",
          length(
            models_by_party_n_nocov
          )
        ),
        rep(
          "共変量あり",
          length(
            models_by_party_n_cov
          )
        )
      )
    ),
    file = file.path(
      output_dir,
      "amce_nocov_and_cov_models.txt"
    )
  )

  amce_plot_cov <- make_amce_plot_df(
    models_by_party_n_cov
  )

  write_csv_safely(
    amce_plot_cov,
    "amce_cov_coefficients.csv"
  )


  study_label <- "実験3(2026年)"

  p_amce_cov <- ggplot(
    amce_plot_cov,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(
        width = 0.65
      ),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(
        width = 0.65
      ),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) {
        paste0(x, " pp")
      },
      breaks = scales::pretty_breaks(
        n = 8
      )
    ) +
    scale_shape_manual(
      name = "選択肢数",
      values = c(
        "2選択肢" = 16,
        "3選択肢" = 17,
        "4選択肢" = 15,
        "5選択肢" = 1
      )
    ) +
    scale_linetype_manual(
      name = "選択肢数",
      values = c(
        "2選択肢" = "solid",
        "3選択肢" = "dashed",
        "4選択肢" = "dotted",
        "5選択肢" = "dotdash"
      )
    ) +
    labs(
      subtitle = paste0(
        "政党名の基準カテゴリ:",
        party_reference,
        "。経済属性は変化なしを基準とする。"
      ),
      x = "選択確率の変化",
      y = NULL
    ) +
    theme_bw(
      base_size = 12,
      base_family = figure_font_family
    ) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 16
      ),
      plot.subtitle = element_text(
        size = 10
      ),
      legend.position = "top",
      legend.title = element_text(
        face = "bold"
      ),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(
        size = 9
      ),
      axis.title.x = element_text(
        face = "bold"
      )
    )

  print(p_amce_cov)

  save_plot(
    "amce_cov_facet_model.png",
    p_amce_cov,
    width = 10.5,
    height = 11.5
  )


  p_amce_nocov <- ggplot(
    amce_plot_nocov,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(
        width = 0.65
      ),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(
        width = 0.65
      ),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) {
        paste0(x, " pp")
      },
      breaks = scales::pretty_breaks(
        n = 8
      )
    ) +
    scale_shape_manual(
      name = "選択肢数",
      values = c(
        "2選択肢" = 16,
        "3選択肢" = 17,
        "4選択肢" = 15,
        "5選択肢" = 1
      )
    ) +
    scale_linetype_manual(
      name = "選択肢数",
      values = c(
        "2選択肢" = "solid",
        "3選択肢" = "dashed",
        "4選択肢" = "dotted",
        "5選択肢" = "dotdash"
      )
    ) +
    labs(
      subtitle = paste0(
        "政党名の基準カテゴリ:",
        party_reference,
        "。経済属性は変化なしを基準とする。"
      ),
      x = "選択確率の変化",
      y = NULL
    ) +
    theme_bw(
      base_size = 12,
      base_family = figure_font_family
    ) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 16
      ),
      plot.subtitle = element_text(
        size = 10
      ),
      legend.position = "top",
      legend.title = element_text(
        face = "bold"
      ),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(
        size = 9
      ),
      axis.title.x = element_text(
        face = "bold"
      )
    )

  print(p_amce_nocov)

  save_plot(
    "amce_nocov_facet_model.png",
    p_amce_nocov,
    width = 10.5,
    height = 11.5
  )


  p_interaction <- ggplot(
    interaction_plot_df,
    aes(
      x = estimate_pp,
      y = label,
      shape = party_n_label,
      linetype = party_n_label,
      group = party_n_label
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      position = position_dodge(
        width = 0.65
      ),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(
        width = 0.65
      ),
      size = 2.5,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) {
        paste0(x, " pp")
      },
      breaks = scales::pretty_breaks(
        n = 8
      )
    ) +
    scale_shape_manual(
      name = "2選択肢条件との比較",
      values = c(
        "3選択肢" = 17,
        "4選択肢" = 15,
        "5選択肢" = 1
      )
    ) +
    scale_linetype_manual(
      name = "2選択肢条件との比較",
      values = c(
        "3選択肢" = "dashed",
        "4選択肢" = "dotted",
        "5選択肢" = "dotdash"
      )
    ) +
    labs(
      x = "2選択肢条件との差",
      y = NULL
    ) +
    theme_bw(
      base_size = 12,
      base_family = figure_font_family
    ) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 15
      ),
      legend.position = "top",
      legend.title = element_text(
        face = "bold"
      ),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(
        size = 9
      ),
      axis.title.x = element_text(
        face = "bold"
      )
    )

  print(p_interaction)

  save_plot(
    "amce_interaction_difference_from_2choice.png",
    p_interaction,
    width = 10.5,
    height = 11.5
  )


  p_linear_trend <- ggplot(
    linear_trend_plot_df,
    aes(
      x = estimate_pp,
      y = label
    )
  ) +
    geom_vline(
      xintercept = 0,
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      height = 0.16,
      linewidth = 0.55,
      color = "black"
    ) +
    geom_point(
      size = 2.5,
      shape = 21,
      color = "black",
      fill = "white",
      stroke = 0.8
    ) +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_x_continuous(
      labels = function(x) {
        paste0(x, " pp")
      },
      breaks = scales::pretty_breaks(
        n = 8
      )
    ) +
    labs(
      subtitle = "横軸は、選択肢数が1つ増えたときの属性効果の変化",
      x = "1選択肢増加当たりのAMCE変化",
      y = NULL
    ) +
    theme_bw(
      base_size = 12,
      base_family = figure_font_family
    ) +
    theme(
      plot.title = element_text(
        face = "bold",
        size = 15
      ),
      plot.subtitle = element_text(
        size = 10
      ),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold",
        size = 10
      ),
      axis.text.y = element_text(
        size = 9
      ),
      axis.title.x = element_text(
        face = "bold"
      )
    )

  print(p_linear_trend)

  save_plot(
    "amce_linear_trend.png",
    p_linear_trend,
    width = 10.5,
    height = 11.5
  )


  heatmap_df <- amce_plot_cov %>%
    mutate(
      abs_amce = abs(
        estimate_pp
      )
    ) %>%
    group_by(party_n) %>%
    mutate(
      rank_within_condition =
        min_rank(
          desc(abs_amce)
        ),

      n_in_condition = n(),

      rank_score = if_else(
        n_in_condition == 1,
        1,
        1 -
          (
            rank_within_condition - 1
          ) /
          (
            n_in_condition - 1
          )
      )
    ) %>%
    ungroup()

  heatmap_row_order <- heatmap_df %>%
    group_by(
      label,
      attribute
    ) %>%
    summarise(
      mean_abs_amce = mean(
        abs_amce,
        na.rm = TRUE
      ),
      .groups = "drop"
    ) %>%
    arrange(
      desc(mean_abs_amce)
    ) %>%
    pull(label) %>%
    as.character()

  heatmap_df <- heatmap_df %>%
    mutate(
      label_heat = factor(
        as.character(label),
        levels = rev(
          heatmap_row_order
        )
      )
    )

  p_heat_amce <- ggplot(
    heatmap_df,
    aes(
      x = party_n,
      y = label_heat,
      fill = abs_amce
    )
  ) +
    geom_tile(
      color = "grey45",
      linewidth = 0.3
    ) +
    geom_text(
      aes(
        label = sprintf(
          "%.1f",
          estimate_pp
        ),
        color = if_else(
          rank_score >= 0.55,
          "white",
          "black"
        )
      ),
      size = 3.1
    ) +
    scale_color_identity() +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    scale_fill_gradient(
      low = "white",
      high = "grey20",
      name = "|AMCE|\n(pp)"
    ) +
    labs(
      subtitle = "セル内の数値は符号付きAMCE(percentage points)",
      x = "選択肢数",
      y = NULL
    ) +
    theme_bw(
      base_size = 12,
      base_family = figure_font_family
    ) +
    theme(
      plot.title = element_text(
        face = "bold"
      ),
      legend.position = "right",
      panel.grid = element_blank(),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold"
      ),
      axis.text.y = element_text(
        size = 8.5
      )
    )

  print(p_heat_amce)

  save_plot(
    "amce_cov_heatmap.png",
    p_heat_amce,
    width = 10.5,
    height = 11.5
  )


  conjoint_clogit <- conjoint_all_m %>%
    mutate(
      selected = as.integer(selected),
      ID = as.character(ID),
      task_id = factor(task_id),

      party_name = relevel_if_present(
        party_name,
        party_reference
      ),

      gdp_growth = relevel_if_present(
        gdp_growth,
        allowed_economic_levels$gdp_growth[1]
      ),

      nikkei = relevel_if_present(
        nikkei,
        allowed_economic_levels$nikkei[1]
      ),

      cpi = relevel_if_present(
        cpi,
        allowed_economic_levels$cpi[1]
      ),

      unemployment = relevel_if_present(
        unemployment,
        allowed_economic_levels$unemployment[1]
      )
    )

  formula_clogit_nocov <- as.formula(
    paste0(
      "selected ~ ",
      paste(
        attr_terms,
        collapse = " + "
      ),
      " + strata(task_id) + cluster(ID)"
    )
  )

  run_clogit_nocov <- function(dat) {
    survival::clogit(
      formula_clogit_nocov,
      data = dat,
      method = "efron"
    )
  }

  models_clogit_nocov <- conjoint_clogit %>%
    split(.$party_n) %>%
    map(run_clogit_nocov)

  capture.output(
    lapply(
      models_clogit_nocov,
      summary
    ),
    file = file.path(
      output_dir,
      "conditional_logit_models.txt"
    )
  )

  tidy_clogit <- function(model) {
    s <- summary(model)
    ct <- as.data.frame(
      s$coefficients
    )
    ct$term <- rownames(ct)

    se_col <- if (
      "robust se" %in% names(ct)
    ) {
      "robust se"
    } else if (
      "se(coef)" %in% names(ct)
    ) {
      "se(coef)"
    } else {
      stop("Check clogit")
    }

    p_col <- if (
      "Pr(>|z|)" %in% names(ct)
    ) {
      "Pr(>|z|)"
    } else if (
      "Pr(>|t|)" %in% names(ct)
    ) {
      "Pr(>|t|)"
    } else {
      NA_character_
    }

    ct %>%
      as_tibble() %>%
      transmute(
        term = term,
        estimate = coef,
        std.error = .data[[se_col]],

        p.value = if (
          !is.na(p_col)
        ) {
          .data[[p_col]]
        } else {
          NA_real_
        },

        conf.low =
          estimate -
          1.96 *
          std.error,

        conf.high =
          estimate +
          1.96 *
          std.error,

        odds_ratio = exp(
          estimate
        ),

        odds_ratio_low = exp(
          conf.low
        ),

        odds_ratio_high = exp(
          conf.high
        )
      )
  }

  clogit_plot_df <- imap_dfr(
    models_clogit_nocov,
    ~ tidy_clogit(.x) %>%
      mutate(
        party_n = as.character(.y)
      )
  ) %>%
    left_join(
      term_labels,
      by = "term"
    ) %>%
    filter(
      !is.na(attribute)
    ) %>%
    mutate(
      party_n = factor(
        party_n,
        levels = c(
          "2",
          "3",
          "4",
          "5"
        ),
        labels = c(
          "2選択肢",
          "3選択肢",
          "4選択肢",
          "5選択肢"
        )
      ),

      attribute = factor(
        attribute,
        levels = attribute_order
      ),

      label = factor(
        label,
        levels = rev(
          label_order
        )
      )
    )

  write_csv_safely(
    clogit_plot_df,
    "conditional_logit_coefficients.csv"
  )


  p_clogit_or <- ggplot(
    clogit_plot_df,
    aes(
      x = odds_ratio,
      y = label,
      shape = party_n,
      linetype = party_n,
      group = party_n
    )
  ) +
    geom_vline(
      xintercept = 1,
      linetype = "dashed",
      linewidth = 0.45,
      color = "grey35"
    ) +
    geom_errorbarh(
      aes(
        xmin = odds_ratio_low,
        xmax = odds_ratio_high
      ),
      position = position_dodge(
        width = 0.72
      ),
      height = 0.15,
      linewidth = 0.45,
      color = "black"
    ) +
    geom_point(
      position = position_dodge(
        width = 0.72
      ),
      size = 2.4,
      stroke = 0.7,
      color = "black"
    ) +
    scale_x_log10(
      breaks = scales::log_breaks(
        n = 8
      )
    ) +
    scale_shape_manual(
      values = c(
        "2選択肢" = 16,
        "3選択肢" = 17,
        "4選択肢" = 15,
        "5選択肢" = 1
      )
    ) +
    scale_linetype_manual(
      values = c(
        "2選択肢" = "solid",
        "3選択肢" = "dashed",
        "4選択肢" = "dotdash",
        "5選択肢" = "twodash"
      )
    ) +
    facet_grid(
      attribute ~ .,
      scales = "free_y",
      space = "free_y",
      switch = "y"
    ) +
    labs(
      x = "オッズ比",
      y = NULL,
      shape = "選択肢数",
      linetype = "選択肢数"
    ) +
    theme_bw(
      base_size = 12,
      base_family = figure_font_family
    ) +
    theme(
      legend.position = "bottom",
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      plot.title = element_text(
        face = "bold"
      ),
      strip.placement = "outside",
      strip.background = element_rect(
        fill = "grey92",
        color = "grey55"
      ),
      strip.text.y.left = element_text(
        angle = 0,
        face = "bold"
      ),
      axis.text.y = element_text(
        size = 8.5
      )
    )

  print(p_clogit_or)

  save_plot(
    "clogit_oddsratio_nocov.png",
    p_clogit_or,
    width = 10.5,
    height = 11.5
  )


  experimental_party_names <- as.character(
    party_levels_use
  )

  conjoint_match <- conjoint_all_cov %>%
    mutate(
      party_name_chr = as.character(party_name),
      
      support_party_valid = if_else(
        party_support_profile %in% experimental_party_names,
        party_support_profile,
        NA_character_
      ),
      
      party_match = case_when(
        is.na(support_party_valid) ~ NA_integer_,
        party_name_chr == support_party_valid ~ 1L,
        TRUE ~ 0L
      )
    ) %>%
    filter(
      !is.na(party_match)
    )

  party_match_sample <- conjoint_match %>%
    distinct(
      ID,
      party_n,
      support_party_valid
    ) %>%
    count(
      party_n,
      support_party_valid,
      name = "n_respondents"
    )

  write_csv_safely(
    party_match_sample,
    "party_match_sample.csv"
  )


  formula_party_match_overall <- as.formula(
    paste(
      "selected ~",
      paste(
        c(
          "party_name",
          "party_match",
          economic_attr_terms
        ),
        collapse = " + "
      )
    )
  )

  run_party_match_overall <- function(dat) {
    feols(
      formula_party_match_overall,
      data = dat,
      vcov = ~ ID
    )
  }

  models_party_match_by_n <- conjoint_match %>%
    split(.$party_n) %>%
    map(run_party_match_overall)

  m_party_match_interaction <- feols(
    selected ~
      party_n_f *
      party_match +
      party_name +
      gdp_growth +
      nikkei +
      cpi +
      unemployment,
    data = conjoint_match,
    vcov = ~ ID
  )

  capture.output(
    lapply(
      models_party_match_by_n,
      summary
    ),
    file = file.path(
      output_dir,
      "party_match_models_by_choice_number.txt"
    )
  )

  capture.output(
    summary(m_party_match_interaction),
    file = file.path(
      output_dir,
      "party_match_interaction_model.txt"
    )
  )

  extract_party_match_term <- function(model) {
    out <- tidy_fixest(model) %>%
      filter(term == "party_match")
    
    if (nrow(out) == 0) {
      return(
        tibble(
          term = "party_match",
          estimate = NA_real_,
          std.error = NA_real_,
          statistic = NA_real_,
          p.value = NA_real_,
          conf.low = NA_real_,
          conf.high = NA_real_
        )
      )
    }
    
    out
  }

  party_match_coef_df <- imap_dfr(
    models_party_match_by_n,
    ~ extract_party_match_term(.x) %>%
      mutate(
        support_group = "全体",
        support_group_label = "全体",
        party_n = as.integer(.y)
      )
  ) %>%
    mutate(
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,
      
      party_n_label = factor(
        party_n,
        levels = 2:5,
        labels = c(
          "2選択肢",
          "3選択肢",
          "4選択肢",
          "5選択肢"
        )
      )
    )

  write_csv_safely(
    party_match_coef_df,
    "party_match_coefficients.csv"
  )


  target_support_groups <- c(
    "自由民主党",
    "中道改革連合",
    "立憲民主党",
    "参政党"
  )

  target_support_labels <- c(
    "自由民主党"   = "自民党支持者",
    "中道改革連合" = "中道改革支持者",
    "立憲民主党"   = "立憲支持者",
    "参政党"       = "参政党支持者"
  )

  party_match_subgroup_sample <- conjoint_match %>%
    distinct(
      ID,
      party_n,
      support_party_valid
    ) %>%
    filter(
      support_party_valid %in% target_support_groups
    ) %>%
    count(
      support_party_valid,
      party_n,
      name = "n_respondents"
    ) %>%
    mutate(
      support_group_label = recode(
        support_party_valid,
        !!!target_support_labels
      )
    )

  write_csv_safely(
    party_match_subgroup_sample,
    "party_match_subgroup_sample.csv"
  )

  support_group_total_n <- conjoint_match %>%
    distinct(
      ID,
      support_party_valid
    ) %>%
    filter(
      support_party_valid %in% target_support_groups
    ) %>%
    count(
      support_party_valid,
      name = "n_total"
    )

  formula_party_match_subgroup <- as.formula(
    paste(
      "selected ~",
      paste(
        c(
          "party_match",
          economic_attr_terms
        ),
        collapse = " + "
      )
    )
  )

  run_party_match_subgroup <- function(dat) {
    feols(
      formula_party_match_subgroup,
      data = dat,
      vcov = ~ ID
    )
  }

  estimate_party_match_subgroup <- function(
      dat,
      support_group_value
  ) {
    map_dfr(
      2:5,
      function(n_value) {
        
        dat_n <- dat %>%
          filter(
            party_n == n_value,
            support_party_valid == support_group_value
          )
        
        n_ids <- n_distinct(dat_n$ID)
        
        if (nrow(dat_n) == 0 || n_ids == 0) {
          return(
            tibble(
              term = "party_match",
              estimate = NA_real_,
              std.error = NA_real_,
              statistic = NA_real_,
              p.value = NA_real_,
              conf.low = NA_real_,
              conf.high = NA_real_,
              support_group = support_group_value,
              support_group_label = unname(
                target_support_labels[[support_group_value]]
              ),
              party_n = n_value,
              n_ids = n_ids
            )
          )
        }
        
        model_n <- tryCatch(
          run_party_match_subgroup(dat_n),
          error = function(e) NULL
        )
        
        if (is.null(model_n)) {
          return(
            tibble(
              term = "party_match",
              estimate = NA_real_,
              std.error = NA_real_,
              statistic = NA_real_,
              p.value = NA_real_,
              conf.low = NA_real_,
              conf.high = NA_real_,
              support_group = support_group_value,
              support_group_label = unname(
                target_support_labels[[support_group_value]]
              ),
              party_n = n_value,
              n_ids = n_ids
            )
          )
        }
        
        extract_party_match_term(model_n) %>%
          mutate(
            support_group = support_group_value,
            support_group_label = unname(
              target_support_labels[[support_group_value]]
            ),
            party_n = n_value,
            n_ids = n_ids
          )
      }
    )
  }

  party_match_subgroup_coef_df <- map_dfr(
    target_support_groups,
    ~ estimate_party_match_subgroup(
      conjoint_match,
      .x
    )
  ) %>%
    left_join(
      support_group_total_n,
      by = c(
        "support_group" = "support_party_valid"
      )
    ) %>%
    mutate(
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,
      party_n_label = factor(
        party_n,
        levels = 2:5,
        labels = c(
          "2選択肢",
          "3選択肢",
          "4選択肢",
          "5選択肢"
        )
      )
    )

  write_csv_safely(
    party_match_subgroup_coef_df,
    "party_match_subgroup_coefficients.csv"
  )


  party_match_plot_df_all <- bind_rows(
    party_match_coef_df %>%
      mutate(panel = "overall"),
    party_match_subgroup_coef_df %>%
      mutate(panel = "subgroup")
  ) %>%
    filter(
      is.finite(estimate_pp),
      is.finite(conf.low_pp),
      is.finite(conf.high_pp)
    )

  if (nrow(party_match_plot_df_all) == 0) {
    stop("Check data")
  }

  y_range_match <- range(
    c(
      party_match_plot_df_all$conf.low_pp,
      party_match_plot_df_all$conf.high_pp
    ),
    na.rm = TRUE
  )

  y_span_match <- diff(y_range_match)

  if (!is.finite(y_span_match) || y_span_match <= 0) {
    y_span_match <- 5
  }

  y_pad_match <- max(1.2, 0.10 * y_span_match)

  y_limits_match <- c(
    y_range_match[1] - y_pad_match,
    y_range_match[2] + y_pad_match
  )


  theme_party_match_bw <- theme_bw(
    base_size = 12,
    base_family = figure_font_family
  ) +
    theme(
      panel.grid.minor = element_blank(),
      panel.grid.major = element_line(
        linewidth = 0.30,
        color = "grey88"
      ),
      panel.border = element_rect(
        linewidth = 0.65,
        color = "black"
      ),
      axis.text = element_text(color = "black"),
      axis.title = element_text(color = "black"),
      plot.title = element_text(
        face = "bold"
      ),
      plot.subtitle = element_text(
        size = rel(0.92)
      ),
      plot.margin = margin(
        8, 10, 8, 8
      )
    )


  make_party_match_panel_plot <- function(
      dat,
      panel_title,
      panel_subtitle = NULL,
      base_size = 11,
      show_y_title = TRUE,
      show_x_title = TRUE
  ) {
    ggplot(
      dat,
      aes(
        x = party_n,
        y = estimate_pp
      )
    ) +
      geom_line(
        linewidth = 0.80,
        color = "black",
        na.rm = TRUE
      ) +
      geom_errorbar(
        aes(
          ymin = conf.low_pp,
          ymax = conf.high_pp
        ),
        width = 0.075,
        linewidth = 0.80,
        color = "black",
        na.rm = TRUE
      ) +
      geom_label(
        aes(
          label = sprintf("%.1f pp", estimate_pp)
        ),
        size = 3.45,
        family = figure_font_family,
        label.size = 0,
        label.padding = unit(
          0.12,
          "lines"
        ),
        fill = "white",
        color = "black",
        na.rm = TRUE
      ) +
      scale_x_continuous(
        breaks = 2:5,
        labels = paste0(
          2:5,
          "選択肢"
        ),
        limits = c(1.72, 5.28)
      ) +
      scale_y_continuous(
        labels = function(x) {
          paste0(x, " pp")
        },
        breaks = scales::pretty_breaks(n = 6),
        expand = expansion(
          mult = c(0.05, 0.08)
        )
      ) +
      coord_cartesian(
        ylim = y_limits_match
      ) +
      labs(
        title = panel_title,
        subtitle = panel_subtitle,
        x = if (show_x_title) "選択肢数" else NULL,
        y = if (show_y_title) "一致した場合の選択確率の変化" else NULL
      ) +
      theme_bw(
        base_size = base_size,
        base_family = figure_font_family
      ) +
      theme_party_match_bw +
      theme(
        plot.title = element_text(
          face = "bold"
        ),
        axis.title.x = if (show_x_title) element_text() else element_blank(),
        axis.title.y = if (show_y_title) element_text() else element_blank()
      )
  }

  make_support_group_title <- function(
      support_group_value
  ) {
    n_value <- support_group_total_n %>%
      filter(
        support_party_valid == support_group_value
      ) %>%
      pull(n_total)
    
    if (length(n_value) == 0 || is.na(n_value)) {
      n_value <- 0
    }
    
    paste0(
      target_support_labels[[support_group_value]],
      "\n(n=",
      scales::comma(n_value),
      ")"
    )
  }


  p_party_match_overall <- make_party_match_panel_plot(
    party_match_coef_df,
    panel_title = NULL,
    panel_subtitle =
      "上段は全体、下段は支持政党別(自民・中道改革・立憲・参政)。政党名と経済属性を統制した線形確率モデル。",
    base_size = 12,
    show_y_title = TRUE,
    show_x_title = TRUE
  )


  p_party_match_ldp <- make_party_match_panel_plot(
    party_match_subgroup_coef_df %>%
      filter(support_group == "自由民主党"),
    panel_title = make_support_group_title("自由民主党"),
    base_size = 10,
    show_y_title = TRUE,
    show_x_title = TRUE
  )

  p_party_match_chr <- make_party_match_panel_plot(
    party_match_subgroup_coef_df %>%
      filter(support_group == "中道改革連合"),
    panel_title = make_support_group_title("中道改革連合"),
    base_size = 10,
    show_y_title = FALSE,
    show_x_title = TRUE
  )

  p_party_match_cdp <- make_party_match_panel_plot(
    party_match_subgroup_coef_df %>%
      filter(support_group == "立憲民主党"),
    panel_title = make_support_group_title("立憲民主党"),
    base_size = 10,
    show_y_title = FALSE,
    show_x_title = TRUE
  )

  p_party_match_sansei <- make_party_match_panel_plot(
    party_match_subgroup_coef_df %>%
      filter(support_group == "参政党"),
    panel_title = make_support_group_title("参政党"),
    base_size = 10,
    show_y_title = FALSE,
    show_x_title = TRUE
  )

  p_party_match_bottom <-
    p_party_match_ldp +
    p_party_match_chr +
    p_party_match_cdp +
    p_party_match_sansei +
    patchwork::plot_layout(ncol = 4)

  p_party_match <-
    p_party_match_overall /
    p_party_match_bottom +
    patchwork::plot_layout(
      heights = c(1.25, 1)
    )

  print(p_party_match)

  save_plot(
    "party_match_effect_combined.png",
    p_party_match,
    width = 14,
    height = 8.8
  )


  relative_cue_map <- c(
    party_name = "party",
    gdp_growth = "economic",
    nikkei = "economic",
    cpi = "economic",
    unemployment = "economic"
  )

  mean_absolute_pairwise_difference <- function(x) {
    x <- x[is.finite(x)]

    if (length(x) < 2) {
      return(NA_real_)
    }

    pairwise_differences <- combn(
      x,
      2,
      FUN = function(z) abs(z[1] - z[2])
    )

    mean(pairwise_differences)
  }

  linear_slope <- function(y, x) {
    keep <- is.finite(y) & is.finite(x)
    y <- y[keep]
    x <- x[keep]

    if (length(y) < 2 || length(unique(x)) < 2) {
      return(NA_real_)
    }

    unname(coef(lm(y ~ x))[2])
  }

  bootstrap_two_sided_p <- function(x) {
    x <- x[is.finite(x)]
    B_valid <- length(x)

    if (B_valid == 0) {
      return(NA_real_)
    }

    p_lower <- (1 + sum(x <= 0)) / (B_valid + 1)
    p_upper <- (1 + sum(x >= 0)) / (B_valid + 1)

    min(1, 2 * min(p_lower, p_upper))
  }

  safe_quantile <- function(x, probability) {
    x <- x[is.finite(x)]

    if (length(x) == 0) {
      return(NA_real_)
    }

    unname(
      quantile(
        x,
        probs = probability,
        type = 6,
        na.rm = TRUE
      )
    )
  }

  prepare_relative_cue_analysis <- function(data, cue_map) {
    attributes <- names(cue_map)

    required_columns <- c(
      "ID",
      "party_n",
      "selected",
      attributes
    )

    missing_columns <- setdiff(
      required_columns,
      names(data)
    )

    if (length(missing_columns) > 0) {
      stop("Check relative weight")
    }

    if (!all(unname(cue_map) %in% c("party", "economic"))) {
      stop("Check relative weight")
    }

    analysis_data <- data %>%
      select(
        ID,
        party_n,
        selected,
        all_of(attributes)
      ) %>%
      mutate(
        ID = as.character(ID),
        party_n = as.integer(as.character(party_n)),
        selected = as.integer(selected),
        across(
          all_of(attributes),
          as.character
        )
      ) %>%
      filter(
        !is.na(ID),
        party_n %in% 2:5,
        selected %in% c(0L, 1L)
      )

    observed_conditions <- sort(
      unique(analysis_data$party_n)
    )

    if (!identical(observed_conditions, 2:5)) {
      stop("Check")
    }

    long_data <- analysis_data %>%
      pivot_longer(
        cols = all_of(attributes),
        names_to = "attribute",
        values_to = "level"
      ) %>%
      filter(
        !is.na(level),
        level != ""
      )

    expected_cells <- long_data %>%
      distinct(
        attribute,
        level
      ) %>%
      mutate(
        attribute_order = match(
          attribute,
          attributes
        )
      ) %>%
      arrange(
        attribute_order,
        attribute,
        level
      ) %>%
      select(-attribute_order) %>%
      mutate(
        cell_key = paste(
          attribute,
          level,
          sep = "\r"
        )
      )

    respondent_cell <- long_data %>%
      group_by(
        party_n,
        ID,
        attribute,
        level
      ) %>%
      summarise(
        y_sum = sum(selected),
        n_obs = n(),
        .groups = "drop"
      ) %>%
      mutate(
        cell_key = paste(
          attribute,
          level,
          sep = "\r"
        )
      )

    condition_objects <- lapply(
      2:5,
      function(n_value) {
        condition_data <- respondent_cell %>%
          filter(
            party_n == n_value
          )

        id_values <- sort(
          unique(condition_data$ID)
        )
        n_ids <- length(id_values)
        n_cells <- nrow(expected_cells)

        if (n_ids == 0) {
          stop("Check")
        }

        y_matrix <- matrix(
          0,
          nrow = n_ids,
          ncol = n_cells,
          dimnames = list(
            id_values,
            expected_cells$cell_key
          )
        )

        n_matrix <- matrix(
          0,
          nrow = n_ids,
          ncol = n_cells,
          dimnames = list(
            id_values,
            expected_cells$cell_key
          )
        )

        row_index <- match(
          condition_data$ID,
          id_values
        )
        column_index <- match(
          condition_data$cell_key,
          expected_cells$cell_key
        )

        y_matrix[cbind(row_index, column_index)] <-
          condition_data$y_sum
        n_matrix[cbind(row_index, column_index)] <-
          condition_data$n_obs

        if (any(colSums(n_matrix) == 0)) {
          missing_cells <- expected_cells$cell_key[
            colSums(n_matrix) == 0
          ]

          stop("Check attributes")
        }

        list(
          party_n = n_value,
          ids = id_values,
          cell_info = expected_cells,
          y_matrix = y_matrix,
          n_matrix = n_matrix
        )
      }
    )

    names(condition_objects) <- as.character(2:5)

    list(
      cue_map = cue_map,
      attributes = attributes,
      conditions = condition_objects
    )
  }

  estimate_relative_cue_indices <- function(
      prepared,
      cluster_weights = NULL
  ) {
    condition_results <- lapply(
      names(prepared$conditions),
      function(condition_name) {
        object <- prepared$conditions[[condition_name]]

        if (is.null(cluster_weights)) {
          weights <- rep(
            1,
            length(object$ids)
          )
        } else {
          weights <- cluster_weights[[condition_name]]
        }

        if (length(weights) != length(object$ids)) {
          stop("Check")
        }

        numerator <- as.numeric(
          crossprod(
            weights,
            object$y_matrix
          )
        )

        denominator <- as.numeric(
          crossprod(
            weights,
            object$n_matrix
          )
        )

        if (any(denominator <= 0)) {
          stop("Check attributes")
        }

        marginal_means <- numerator / denominator

        mm_table <- object$cell_info %>%
          transmute(
            party_n = object$party_n,
            attribute,
            level,
            marginal_mean = marginal_means
          )

        attribute_table <- mm_table %>%
          group_by(
            party_n,
            attribute
          ) %>%
          summarise(
            importance_pairwise =
              mean_absolute_pairwise_difference(
                marginal_mean
              ),
            n_levels = n(),
            .groups = "drop"
          ) %>%
          mutate(
            cue_family = unname(
              prepared$cue_map[attribute]
            ),
            baseline_selection_probability = 1 / party_n,
            importance_pairwise_adjusted =
              importance_pairwise /
                baseline_selection_probability
          )

        cue_table_long <- attribute_table %>%
          group_by(
            party_n,
            cue_family
          ) %>%
          summarise(
            importance_pairwise = mean(
              importance_pairwise,
              na.rm = TRUE
            ),
            importance_pairwise_adjusted = mean(
              importance_pairwise_adjusted,
              na.rm = TRUE
            ),
            .groups = "drop"
          )

        party_table <- cue_table_long %>%
          filter(
            cue_family == "party"
          ) %>%
          transmute(
            party_n,
            party_importance_pairwise =
              importance_pairwise,
            party_importance_pairwise_adjusted =
              importance_pairwise_adjusted
          )

        economic_table <- cue_table_long %>%
          filter(
            cue_family == "economic"
          ) %>%
          transmute(
            party_n,
            economic_importance_pairwise =
              importance_pairwise,
            economic_importance_pairwise_adjusted =
              importance_pairwise_adjusted
          )

        cue_table <- full_join(
          party_table,
          economic_table,
          by = "party_n"
        ) %>%
          mutate(
            baseline_selection_probability = 1 / party_n,

            total_importance_pairwise =
              party_importance_pairwise +
              economic_importance_pairwise,

            total_importance_pairwise_adjusted =
              party_importance_pairwise_adjusted +
              economic_importance_pairwise_adjusted,

            relative_party_weight_pairwise = if_else(
              total_importance_pairwise > 0,
              party_importance_pairwise /
                total_importance_pairwise,
              NA_real_
            ),

            relative_economic_weight_pairwise =
              1 - relative_party_weight_pairwise,

            relative_party_weight_pairwise_adjusted = if_else(
              total_importance_pairwise_adjusted > 0,
              party_importance_pairwise_adjusted /
                total_importance_pairwise_adjusted,
              NA_real_
            ),

            relative_economic_weight_pairwise_adjusted =
              1 - relative_party_weight_pairwise_adjusted,

            adjustment_identity_difference =
              relative_party_weight_pairwise_adjusted -
                relative_party_weight_pairwise
          )

        if (
          any(
            abs(cue_table$adjustment_identity_difference) > 1e-10,
            na.rm = TRUE
          )
        ) {
          stop("Check relative weight")
        }

        list(
          marginal_means = mm_table,
          attribute_importance = attribute_table,
          cue_importance = cue_table
        )
      }
    )

    list(
      marginal_means = bind_rows(
        lapply(
          condition_results,
          function(x) x$marginal_means
        )
      ),
      attribute_importance = bind_rows(
        lapply(
          condition_results,
          function(x) x$attribute_importance
        )
      ),
      cue_importance = bind_rows(
        lapply(
          condition_results,
          function(x) x$cue_importance
        )
      ) %>%
        arrange(party_n)
    )
  }

  estimate_relative_cue_slopes <- function(cue_importance) {
    cue_importance <- cue_importance %>%
      arrange(party_n)

    if (!identical(cue_importance$party_n, 2:5)) {
      stop("Check relative weight")
    }

    x <- cue_importance$party_n

    c(
      relative_party_weight_pairwise =
        linear_slope(
          cue_importance$relative_party_weight_pairwise,
          x
        ),

      party_importance_pairwise =
        linear_slope(
          cue_importance$party_importance_pairwise,
          x
        ),

      economic_importance_pairwise =
        linear_slope(
          cue_importance$economic_importance_pairwise,
          x
        ),

      party_importance_pairwise_adjusted =
        linear_slope(
          cue_importance$party_importance_pairwise_adjusted,
          x
        ),

      economic_importance_pairwise_adjusted =
        linear_slope(
          cue_importance$economic_importance_pairwise_adjusted,
          x
        )
    )
  }

  run_relative_cue_bootstrap <- function(
      prepared,
      B,
      seed,
      progress_every = 100
  ) {
    set.seed(seed)

    condition_results <- vector(
      "list",
      B
    )

    slope_names <- c(
      "relative_party_weight_pairwise",
      "party_importance_pairwise",
      "economic_importance_pairwise",
      "party_importance_pairwise_adjusted",
      "economic_importance_pairwise_adjusted"
    )

    slope_matrix <- matrix(
      NA_real_,
      nrow = B,
      ncol = length(slope_names),
      dimnames = list(
        NULL,
        slope_names
      )
    )

    for (b in seq_len(B)) {
      cluster_weights <- lapply(
        prepared$conditions,
        function(object) {
          n_ids <- length(object$ids)

          sampled_positions <- sample.int(
            n = n_ids,
            size = n_ids,
            replace = TRUE
          )

          tabulate(
            sampled_positions,
            nbins = n_ids
          )
        }
      )

      bootstrap_estimates <- estimate_relative_cue_indices(
        prepared = prepared,
        cluster_weights = cluster_weights
      )

      condition_results[[b]] <-
        bootstrap_estimates$cue_importance %>%
        select(
          party_n,
          party_importance_pairwise,
          economic_importance_pairwise,
          party_importance_pairwise_adjusted,
          economic_importance_pairwise_adjusted,
          relative_party_weight_pairwise
        ) %>%
        mutate(
          bootstrap_replication = b,
          .before = 1
        )

      slope_matrix[b, ] <- estimate_relative_cue_slopes(
        bootstrap_estimates$cue_importance
      )

      if (
        progress_every > 0 &&
        (b %% progress_every == 0 || b == B)
      ) {
        message("Bootstrap: ", b, "/", B)
      }
    }

    list(
      condition_estimates = bind_rows(
        condition_results
      ),
      slopes = as_tibble(
        slope_matrix
      ) %>%
        mutate(
          bootstrap_replication = row_number(),
          .before = 1
        )
    )
  }

  summarise_condition_intervals <- function(
      observed_cue_importance,
      bootstrap_condition_results
  ) {
    statistics <- c(
      "party_importance_pairwise",
      "economic_importance_pairwise",
      "party_importance_pairwise_adjusted",
      "economic_importance_pairwise_adjusted",
      "relative_party_weight_pairwise"
    )

    observed_long <- observed_cue_importance %>%
      select(
        party_n,
        all_of(statistics)
      ) %>%
      pivot_longer(
        cols = all_of(statistics),
        names_to = "statistic",
        values_to = "estimate"
      )

    bootstrap_long <- bootstrap_condition_results %>%
      pivot_longer(
        cols = all_of(statistics),
        names_to = "statistic",
        values_to = "value"
      ) %>%
      group_by(
        party_n,
        statistic
      ) %>%
      summarise(
        conf_low = safe_quantile(
          value,
          0.025
        ),
        conf_high = safe_quantile(
          value,
          0.975
        ),
        .groups = "drop"
      )

    observed_long %>%
      left_join(
        bootstrap_long,
        by = c(
          "party_n",
          "statistic"
        )
      )
  }

  summarise_slope_inference <- function(
      observed_slopes,
      bootstrap_slopes
  ) {
    statistic_names <- names(observed_slopes)

    map_dfr(
      statistic_names,
      function(statistic_name) {
        bootstrap_values <- bootstrap_slopes[[statistic_name]]
        bootstrap_values <- bootstrap_values[
          is.finite(bootstrap_values)
        ]

        expected_direction <- case_when(
          statistic_name ==
            "economic_importance_pairwise" ~ "negative",
          statistic_name %in% c(
            "party_importance_pairwise",
            "relative_party_weight_pairwise",
            "party_importance_pairwise_adjusted"
          ) ~ "positive",
          TRUE ~ "none"
        )

        analysis_role <- case_when(
          statistic_name %in% c(
            "party_importance_pairwise_adjusted",
            "economic_importance_pairwise_adjusted"
          ) ~ "exploratory_choice_set_adjusted",
          statistic_name == "relative_party_weight_pairwise" ~
            "derived_relative_share",
          TRUE ~ "manuscript_primary_unadjusted"
        )

        estimate <- unname(
          observed_slopes[[statistic_name]]
        )

        tibble(
          study = "Study 3",
          statistic = statistic_name,
          estimate = estimate,
          conf_low = safe_quantile(
            bootstrap_values,
            0.025
          ),
          conf_high = safe_quantile(
            bootstrap_values,
            0.975
          ),
          p_value_two_sided =
            bootstrap_two_sided_p(
              bootstrap_values
            ),
          expected_direction = expected_direction,
          analysis_role = analysis_role,
          estimate_in_expected_direction = case_when(
            expected_direction == "positive" ~ estimate > 0,
            expected_direction == "negative" ~ estimate < 0,
            TRUE ~ NA
          )
        )
      }
    )
  }

  relative_cue_prepared <- prepare_relative_cue_analysis(
    data = conjoint_all_m,
    cue_map = relative_cue_map
  )

  relative_cue_observed <- estimate_relative_cue_indices(
    prepared = relative_cue_prepared
  )

  relative_cue_observed_slopes <- estimate_relative_cue_slopes(
    relative_cue_observed$cue_importance
  )

  write_csv_safely(
    relative_cue_observed$marginal_means,
    "study3_relative_cue_marginal_means.csv"
  )

  write_csv_safely(
    relative_cue_observed$attribute_importance,
    "study3_relative_cue_attribute_importance.csv"
  )

  write_csv_safely(
    relative_cue_observed$cue_importance,
    "study3_relative_cue_importance_and_weight.csv"
  )

  relative_condition_bootstrap_file <- file.path(
    output_dir,
    paste0(
      "study3_relative_cue_condition_bootstrap_",
      unified_config$cue_importance_metric_version,
      "_B",
      relative_cue_bootstrap_B,
      ".csv"
    )
  )

  relative_slope_bootstrap_file <- file.path(
    output_dir,
    paste0(
      "study3_relative_cue_slope_bootstrap_",
      unified_config$cue_importance_metric_version,
      "_B",
      relative_cue_bootstrap_B,
      ".csv"
    )
  )

  use_saved_relative_bootstrap <-
    !rerun_relative_cue_bootstrap &&
    file.exists(relative_condition_bootstrap_file) &&
    file.exists(relative_slope_bootstrap_file)

  if (use_saved_relative_bootstrap) {
    message("Bootstrap cache")

    relative_cue_condition_bootstrap <- readr::read_csv(
      relative_condition_bootstrap_file,
      show_col_types = FALSE
    )

    relative_cue_slope_bootstrap <- readr::read_csv(
      relative_slope_bootstrap_file,
      show_col_types = FALSE
    )

    saved_B_condition <- n_distinct(
      relative_cue_condition_bootstrap$bootstrap_replication
    )
    saved_B_slope <- n_distinct(
      relative_cue_slope_bootstrap$bootstrap_replication
    )

    if (
      saved_B_condition != relative_cue_bootstrap_B ||
      saved_B_slope != relative_cue_bootstrap_B
    ) {
      message("Bootstrap cache")
      use_saved_relative_bootstrap <- FALSE
    }
  }

  if (!use_saved_relative_bootstrap) {
    relative_cue_bootstrap <- run_relative_cue_bootstrap(
      prepared = relative_cue_prepared,
      B = relative_cue_bootstrap_B,
      seed = relative_cue_bootstrap_seed,
      progress_every = relative_cue_bootstrap_progress_every
    )

    relative_cue_condition_bootstrap <-
      relative_cue_bootstrap$condition_estimates

    relative_cue_slope_bootstrap <-
      relative_cue_bootstrap$slopes

    readr::write_csv(
      relative_cue_condition_bootstrap,
      relative_condition_bootstrap_file
    )

    readr::write_csv(
      relative_cue_slope_bootstrap,
      relative_slope_bootstrap_file
    )
  }

  relative_cue_condition_intervals <- summarise_condition_intervals(
    observed_cue_importance =
      relative_cue_observed$cue_importance,
    bootstrap_condition_results =
      relative_cue_condition_bootstrap
  )

  relative_cue_slope_inference <- summarise_slope_inference(
    observed_slopes =
      relative_cue_observed_slopes,
    bootstrap_slopes =
      relative_cue_slope_bootstrap
  )

  write_csv_safely(
    relative_cue_condition_intervals,
    "study3_relative_cue_condition_intervals.csv"
  )

  write_csv_safely(
    relative_cue_slope_inference,
    "study3_relative_cue_slope_inference.csv"
  )

  relative_cue_primary_result <- relative_cue_slope_inference %>%
    filter(
      statistic ==
        "relative_party_weight_pairwise"
    )

  cat("\nStudy 3:相対比重の線形傾向\n")
  print(relative_cue_primary_result)


  relative_x_offset <- 0.075

  relative_panel_a_data <- relative_cue_condition_intervals %>%
    filter(
      statistic %in% c(
        "party_importance_pairwise",
        "economic_importance_pairwise"
      )
    ) %>%
    mutate(
      cue_family = recode(
        statistic,
        party_importance_pairwise = "政党名手がかり",
        economic_importance_pairwise = "経済手がかり"
      ),
      cue_family = factor(
        cue_family,
        levels = c(
          "政党名手がかり",
          "経済手がかり"
        )
      ),
      x_plot = case_when(
        cue_family == "政党名手がかり" ~
          party_n + relative_x_offset,
        cue_family == "経済手がかり" ~
          party_n - relative_x_offset,
        TRUE ~ as.numeric(party_n)
      ),
      value_label = sprintf(
        "%.3f",
        estimate
      )
    )

  relative_panel_b_data <- relative_cue_condition_intervals %>%
    filter(
      statistic ==
        "relative_party_weight_pairwise"
    ) %>%
    mutate(
      value_label = sprintf(
        "%.1f%%",
        100 * estimate
      )
    )

  relative_adjusted_label_map <- relative_panel_a_data %>%
    distinct(
      statistic,
      cue_family
    ) %>%
    mutate(
      statistic = paste0(
        statistic,
        "_adjusted"
      ),
      cue_family = as.character(
        cue_family
      )
    )

  relative_panel_adjusted_data <- relative_cue_condition_intervals %>%
    filter(
      statistic %in% c(
        "party_importance_pairwise_adjusted",
        "economic_importance_pairwise_adjusted"
      )
    ) %>%
    left_join(
      relative_adjusted_label_map,
      by = "statistic"
    ) %>%
    mutate(
      cue_family = factor(
        cue_family,
        levels = levels(
          relative_panel_a_data$cue_family
        )
      ),
      x_plot = if_else(
        as.integer(cue_family) == 1L,
        party_n + relative_x_offset,
        party_n - relative_x_offset
      ),
      value_label = sprintf(
        "%.1f%%",
        100 * estimate
      )
    )

  relative_condition_suffix <- if (
    "政党名手がかり" %in%
      levels(relative_panel_a_data$cue_family)
  ) {
    "選択肢"
  } else {
    "政党"
  }

  relative_condition_axis_title <- if (
    relative_condition_suffix == "選択肢"
  ) {
    "政治経済状況の選択肢数"
  } else {
    "政党選択肢数"
  }

  relative_figure_font_family <- if (
    .Platform$OS.type == "windows"
  ) {
    "Yu Gothic"
  } else {
    "sans"
  }

  relative_theme_japanese_bw <- theme_bw(
    base_size = 12,
    base_family = relative_figure_font_family
  ) +
    theme(
      panel.grid.minor = element_blank(),
      panel.grid.major = element_line(
        linewidth = 0.30,
        color = "grey88"
      ),
      panel.border = element_rect(
        linewidth = 0.65,
        color = "black"
      ),
      axis.text = element_text(
        color = "black"
      ),
      axis.title = element_text(
        color = "black"
      ),
      plot.title = element_text(
        size = 12.5,
        face = "bold",
        hjust = 0
      ),
      plot.subtitle = element_text(
        size = 9.5,
        hjust = 0,
        margin = margin(
          b = 8
        )
      ),
      legend.position = "top",
      legend.justification = "center",
      legend.key.width = grid::unit(
        1.25,
        "cm"
      ),
      plot.margin = margin(
        8,
        10,
        8,
        8
      )
    )

  relative_panel_a <- ggplot(
    relative_panel_a_data,
    aes(
      x = x_plot,
      y = estimate,
      group = cue_family,
      linetype = cue_family
    )
  ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_linetype_manual(
      values = c(
        "政党名手がかり" = "solid",
        "経済手がかり" = "dashed"
      )
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        "選択肢"
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      labels = label_number(
        accuracy = 0.005
      ),
      expand = expansion(
        mult = c(
          0.07,
          0.10
        )
      )
    ) +
    labs(
      title = "A:両手がかりの絶対的重要度",
      subtitle = "",
      x = "政党選択肢数",
      y = "手がかり重要度",
      linetype = NULL
    ) +
    guides(
      linetype = guide_legend(
        override.aes = list(
          linewidth = 0.90
        )
      )
    ) +
    relative_theme_japanese_bw

  relative_adjusted_linetypes <- setNames(
    c(
      "solid",
      "dashed"
    ),
    levels(
      relative_panel_adjusted_data$cue_family
    )
  )

  relative_panel_adjusted <- ggplot(
    relative_panel_adjusted_data,
    aes(
      x = x_plot,
      y = estimate,
      group = cue_family,
      linetype = cue_family
    )
  ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_linetype_manual(
      values = relative_adjusted_linetypes
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        relative_condition_suffix
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      labels = label_percent(
        accuracy = 1
      ),
      expand = expansion(
        mult = c(
          0.07,
          0.10
        )
      )
    ) +
    labs(
      title = "A:選択肢数調整済み重要度",
      subtitle =
        "未調整重要度 ÷ 平均選択確率(1/選択肢数)",
      x = relative_condition_axis_title,
      y = "平均選択確率に対する水準間差",
      linetype = NULL
    ) +
    guides(
      linetype = guide_legend(
        override.aes = list(
          linewidth = 0.90
        )
      )
    ) +
    relative_theme_japanese_bw

  relative_b_range <- range(
    c(
      relative_panel_b_data$conf_low,
      relative_panel_b_data$conf_high,
      0.5
    ),
    na.rm = TRUE
  )

  relative_b_padding <- max(
    0.025,
    0.10 * diff(relative_b_range)
  )

  relative_b_lower <- max(
    0,
    floor(
      20 *
        (relative_b_range[1] - relative_b_padding)
    ) / 20
  )

  relative_b_upper <- min(
    1,
    ceiling(
      20 *
        (relative_b_range[2] + relative_b_padding)
    ) / 20
  )

  if (relative_b_lower >= relative_b_upper) {
    relative_b_lower <- max(
      0,
      relative_b_lower - 0.05
    )
    relative_b_upper <- min(
      1,
      relative_b_upper + 0.05
    )
  }

  relative_panel_b <- ggplot(
    relative_panel_b_data,
    aes(
      x = party_n,
      y = estimate
    )
  ) +
    geom_hline(
      yintercept = 0.5,
      linetype = "dashed",
      linewidth = 0.55,
      color = "black"
    ) +
    geom_line(
      linewidth = 0.80,
      color = "black"
    ) +
    geom_errorbar(
      aes(
        ymin = conf_low,
        ymax = conf_high
      ),
      width = 0.075,
      linewidth = 0.80,
      color = "black"
    ) +
    geom_label(
      aes(
        label = value_label
      ),
      size = 3.55,
      family = relative_figure_font_family,
      label.size = 0,
      label.padding = grid::unit(
        0.12,
        "lines"
      ),
      fill = "white",
      color = "black"
    ) +
    scale_x_continuous(
      breaks = 2:5,
      labels = paste0(
        2:5,
        "選択肢"
      ),
      limits = c(
        1.72,
        5.28
      )
    ) +
    scale_y_continuous(
      breaks = seq(
        relative_b_lower,
        relative_b_upper,
        by = 0.05
      ),
      labels = label_percent(
        accuracy = 1
      ),
      expand = expansion(
        mult = c(
          0.05,
          0.08
        )
      )
    ) +
    coord_cartesian(
      ylim = c(
        relative_b_lower,
        relative_b_upper
      )
    ) +
    labs(
      title = "B:相対的な政党名手がかりの比重",
      subtitle =
        "政党名手がかり重要度 ÷(政党名手がかり重要度+経済手がかり重要度)",
      x = "政党選択肢数",
      y = "相対的な政党名手がかり比重"
    ) +
    relative_theme_japanese_bw +
    theme(
      legend.position = "none"
    )

  relative_panel_c <- relative_panel_b +
    labs(
      title = paste0(
        "B:相対的な",
        levels(relative_panel_a_data$cue_family)[1],
        "の比重"
      )
    )

  figure_relative_weight_jp <- (
    relative_panel_a |
      relative_panel_b
  ) +
    patchwork::plot_layout(
      widths = c(
        1,
        1
      )
    )

  print(
    figure_relative_weight_jp
  )

  save_plot(
    "fig_study3_relative_cue_weight_jp_bw.png",
    figure_relative_weight_jp,
    width = 11.2,
    height = 5.4,
    dpi = 400
  )

  ggsave(
    filename = file.path(
      output_dir,
      "fig_study3_relative_cue_weight_jp_bw.pdf"
    ),
    plot = figure_relative_weight_jp,
    width = 11.2,
    height = 5.4,
    device = grDevices::cairo_pdf,
    bg = "white"
  )

  figure_relative_weight_adjusted_jp <- (
    relative_panel_adjusted |
      relative_panel_c
  ) +
    patchwork::plot_layout(
      widths = c(
        1,
        1
      )
    )

  print(
    figure_relative_weight_adjusted_jp
  )

  relative_adjusted_figure_stub <- paste0(
    "fig_study",
    stringr::str_extract(
      study_label,
      "[123]"
    ),
    "_relative_cue_weight_choice_set_adjusted_jp_bw"
  )

  save_plot(
    paste0(
      relative_adjusted_figure_stub,
      ".png"
    ),
    figure_relative_weight_adjusted_jp,
    width = 11.2,
    height = 5.4,
    dpi = 400
  )

  ggsave(
    filename = file.path(
      output_dir,
      paste0(
        relative_adjusted_figure_stub,
        ".pdf"
      )
    ),
    plot = figure_relative_weight_adjusted_jp,
    width = 11.2,
    height = 5.4,
    device = grDevices::cairo_pdf,
    bg = "white"
  )

  relative_cue_results <- list(
    prepared = relative_cue_prepared,
    marginal_means =
      relative_cue_observed$marginal_means,
    attribute_importance =
      relative_cue_observed$attribute_importance,
    cue_importance =
      relative_cue_observed$cue_importance,
    observed_slopes =
      relative_cue_observed_slopes,
    condition_bootstrap =
      relative_cue_condition_bootstrap,
    slope_bootstrap =
      relative_cue_slope_bootstrap,
    condition_intervals =
      relative_cue_condition_intervals,
    slope_inference =
      relative_cue_slope_inference,
    primary_result =
      relative_cue_primary_result,
    plots = list(
      absolute_importance = relative_panel_a,
      choice_set_adjusted_importance =
        relative_panel_adjusted,
      relative_party_weight = relative_panel_b,
      relative_party_weight_panel_c =
        relative_panel_c,
      combined = figure_relative_weight_jp,
      combined_with_choice_set_adjustment =
        figure_relative_weight_adjusted_jp
    )
  )

  saveRDS(
    relative_cue_results,
    file = file.path(
      output_dir,
      "study3_relative_cue_results.rds"
    )
  )


  saveRDS(
    list(
      settings = list(
        data_file = data_file,
        require_initial_consent =
          require_initial_consent,
        require_final_consent =
          require_final_consent,
        require_attention_check =
          require_attention_check,
        require_manipulation_check =
          require_manipulation_check,
        require_all_five_tasks =
          require_all_five_tasks,
        party_reference =
          party_reference,
        party_levels_use =
          party_levels_use,
        relative_cue_bootstrap_B =
          relative_cue_bootstrap_B,
        relative_cue_bootstrap_seed =
          relative_cue_bootstrap_seed
      ),

      sample_flow = sample_flow,
      n_by_party = n_by_party,
      valid_ids = valid_ids,

      conjoint_all = conjoint_all,
      conjoint_all_m = conjoint_all_m,
      conjoint_all_cov = conjoint_all_cov,

      covar_id = covar_id,

      models_by_party_n_nocov =
        models_by_party_n_nocov,

      models_by_party_n_cov =
        models_by_party_n_cov,

      m_interaction =
        m_interaction,

      m_linear_trend =
        m_linear_trend,

      models_clogit_nocov =
        models_clogit_nocov,

      party_match = list(
        data = conjoint_match,
        models_by_n =
          models_party_match_by_n,
        interaction_model =
          m_party_match_interaction
      ),

      relative_cue = relative_cue_results,

      plots = list(
        amce_cov =
          p_amce_cov,
        amce_nocov =
          p_amce_nocov,
        interaction =
          p_interaction,
        linear_trend =
          p_linear_trend,
        heatmap =
          p_heat_amce,
        clogit_odds_ratio =
          p_clogit_or,
        party_match =
          p_party_match,
        relative_cue_weight =
          figure_relative_weight_jp,
        relative_cue_weight_choice_set_adjusted =
          figure_relative_weight_adjusted_jp
      )
    ),
    file = file.path(
      output_dir,
      "study3_analysis_objects.rds"
    )
  )

  capture.output(
    sessionInfo(),
    file = file.path(
      output_dir,
      "sessionInfo.txt"
    )
  )

  cat(
    "\nStudy 3の分析コードが最後まで完了しました。\n",
    "出力先: ",
    normalizePath(output_dir),
    "\n",
    sep = ""
  )

  environment()
})

A.5 補遺に関する各種の再現コード

# 補遺共通コード
unified_output_dir <- file.path(
  unified_config$output_root,
  "_working",
  "cross_study"
)
dir.create(unified_output_dir, showWarnings = FALSE, recursive = TRUE)

save_plot_both <- function(filename_stub, plot, width, height, dpi = 400) {
  png_file <- file.path(unified_output_dir, paste0(filename_stub, ".png"))
  pdf_file <- file.path(unified_output_dir, paste0(filename_stub, ".pdf"))
  
  ggplot2::ggsave(
    filename = png_file,
    plot = plot,
    width = width,
    height = height,
    dpi = dpi,
    bg = "white"
  )
  
  ggplot2::ggsave(
    filename = pdf_file,
    plot = plot,
    width = width,
    height = height,
    device = grDevices::cairo_pdf,
    bg = "white"
  )
  
  invisible(c(png = png_file, pdf = pdf_file))
}

write_csv_unified <- function(x, filename) {
  readr::write_csv(
    x,
    file.path(unified_output_dir, filename),
    na = ""
  )
}

safe_filename <- function(x) {
  x <- iconv(as.character(x), from = "", to = "ASCII//TRANSLIT")
  x[is.na(x) | x == ""] <- "group"
  x <- tolower(x)
  x <- gsub("[^a-z0-9]+", "_", x)
  x <- gsub("^_+|_+$", "", x)
  ifelse(x == "", "group", x)
}

tidy_fixest_unified <- function(model) {
  ct <- as.data.frame(fixest::coeftable(model))
  ct$term <- rownames(ct)
  
  estimate_col <- intersect(c("Estimate", "estimate"), names(ct))[1]
  se_col <- intersect(c("Std. Error", "Std. error", "std.error"), names(ct))[1]
  statistic_col <- intersect(c("t value", "z value", "statistic"), names(ct))[1]
  p_col <- intersect(c("Pr(>|t|)", "Pr(>|z|)", "p.value"), names(ct))[1]
  
  if (
    is.na(estimate_col) ||
    is.na(se_col) ||
    is.na(statistic_col) ||
    is.na(p_col)
  ) {
    stop("Check data")
  }
  
  tibble::as_tibble(ct) %>%
    dplyr::transmute(
      term = term,
      estimate = .data[[estimate_col]],
      std.error = .data[[se_col]],
      statistic = .data[[statistic_col]],
      p.value = .data[[p_col]],
      conf.low = estimate - 1.96 * std.error,
      conf.high = estimate + 1.96 * std.error
    )
}

study_specs <- list(
  study1 = list(
    study_id = "study1",
    study_label = "Study 1(2023年)",
    condition_label = "政党数",
    env = study1_env
  ),
  study2 = list(
    study_id = "study2",
    study_label = "Study 2(2026年)",
    condition_label = "政党数",
    env = study2_env
  ),
  study3 = list(
    study_id = "study3",
    study_label = "Study 3(2026年)",
    condition_label = "選択肢数",
    env = study3_env
  )
)

excluded_support_categories <- c(
  "その他",
  "わからない",
  "答えない",
  "答えたくない",
  "欠損・無回答"
)


# 補遺C関連コード
balance_variable_labels <- c(
  female_imp = "女性",
  female_miss = "性別:欠損",
  age_imp = "年齢",
  age_miss = "年齢:欠損",
  college_grad_imp = "4年制大学以上",
  college_grad_miss = "学歴:欠損",
  income_gross_log_imp = "世帯年収(対数)",
  income_gross_log_miss = "世帯年収:欠損",
  self_ideology_imp = "左右自己位置づけ",
  self_ideology_miss = "左右自己位置づけ:欠損"
)

make_balance_design <- function(study_spec) {
  env <- study_spec$env
  
  assignment <- env$conjoint_all %>%
    dplyr::distinct(ID, party_n) %>%
    dplyr::mutate(
      ID = as.character(ID),
      party_n = as.integer(as.character(party_n))
    )
  
  respondent <- env$covar_id %>%
    dplyr::mutate(ID = as.character(ID))
  
  dat <- assignment %>%
    dplyr::left_join(respondent, by = "ID")
  
  numeric_candidates <- c(
    "female_imp",
    "female_miss",
    "age_imp",
    "age_miss",
    "college_grad_imp",
    "college_grad_miss",
    "income_gross_log_imp",
    "income_gross_log_miss",
    "self_ideology_imp",
    "self_ideology_miss"
  )
  
  factor_candidates <- c(
    "party_support_f",
    "region"
  )
  
  numeric_use <- intersect(numeric_candidates, names(dat))
  factor_use <- intersect(factor_candidates, names(dat))
  
  design_source <- dat %>%
    dplyr::select(dplyr::all_of(c(numeric_use, factor_use)))
  
  if (length(factor_use) > 0) {
    design_source <- design_source %>%
      dplyr::mutate(
        dplyr::across(
          dplyr::all_of(factor_use),
          ~ forcats::fct_na_value_to_level(as.factor(.x), level = "欠損・無回答")
        )
      )
  }
  
  mm <- stats::model.matrix(
    stats::as.formula(
      paste0(
        "~ 0 + ",
        paste(names(design_source), collapse = " + ")
      )
    ),
    data = design_source
  )
  
  mm <- as.data.frame(mm, check.names = FALSE)
  
  keep <- vapply(
    mm,
    function(x) {
      x <- as.numeric(x)
      is.finite(stats::sd(x, na.rm = TRUE)) && stats::sd(x, na.rm = TRUE) > 0
    },
    logical(1)
  )
  
  mm <- mm[, keep, drop = FALSE]
  
  mm <- mm %>%
    dplyr::mutate(
      ID = dat$ID,
      party_n = dat$party_n,
      .before = 1
    )
  
  long <- mm %>%
    tidyr::pivot_longer(
      cols = -c(ID, party_n),
      names_to = "variable",
      values_to = "value"
    ) %>%
    dplyr::mutate(
      label = dplyr::case_when(
        variable %in% names(balance_variable_labels) ~
          unname(balance_variable_labels[variable]),
        stringr::str_detect(variable, "^party_support_f") ~
          paste0(
            "支持政党:",
            stringr::str_remove(variable, "^party_support_f")
          ),
        stringr::str_detect(variable, "^region") ~
          paste0(
            "地域:",
            stringr::str_remove(variable, "^region")
          ),
        TRUE ~ variable
      ),
      study_id = study_spec$study_id,
      study_label = study_spec$study_label
    )
  
  list(
    respondent = dat,
    matrix = mm,
    long = long,
    numeric_use = numeric_use,
    factor_use = factor_use
  )
}

pairwise_smd_multiarm <- function(balance_long) {
  groups <- sort(unique(balance_long$party_n))
  pairs <- utils::combn(groups, 2, simplify = FALSE)

  purrr::map_dfr(
    pairs,
    function(pair_value) {
      a <- pair_value[1]
      b <- pair_value[2]

      wide <- balance_long %>%
        dplyr::filter(party_n %in% c(a, b)) %>%
        dplyr::group_by(variable, label, party_n) %>%
        dplyr::summarise(
          mean = mean(value, na.rm = TRUE),
          sd = stats::sd(value, na.rm = TRUE),
          n = sum(!is.na(value)),
          .groups = "drop"
        ) %>%
        tidyr::pivot_wider(
          names_from = party_n,
          values_from = c(mean, sd, n),
          names_sep = "_"
        )

      wide %>%
        dplyr::transmute(
          variable = variable,
          label = label,
          condition_a = a,
          condition_b = b,
          comparison = paste0(a, " vs ", b),
          mean_a = .data[[paste0("mean_", a)]],
          mean_b = .data[[paste0("mean_", b)]],
          sd_a = .data[[paste0("sd_", a)]],
          sd_b = .data[[paste0("sd_", b)]],
          n_a = .data[[paste0("n_", a)]],
          n_b = .data[[paste0("n_", b)]],
          pooled_sd = sqrt((sd_a^2 + sd_b^2) / 2),
          smd = dplyr::if_else(
            is.finite(pooled_sd) & pooled_sd > 0,
            (mean_a - mean_b) / pooled_sd,
            NA_real_
          ),
          abs_smd = abs(smd)
        )
    }
  )
}

omnibus_balance_test <- function(balance_long) {
  balance_long %>%
    dplyr::group_by(variable, label) %>%
    dplyr::group_modify(
      ~ {
        dat <- .x %>%
          dplyr::filter(is.finite(value), !is.na(party_n))
        
        p_value <- tryCatch(
          {
            model <- stats::lm(value ~ factor(party_n), data = dat)
            as.numeric(stats::anova(model)[1, "Pr(>F)"])
          },
          error = function(e) NA_real_
        )
        
        tibble::tibble(p_value = p_value)
      }
    ) %>%
    dplyr::ungroup() %>%
    dplyr::mutate(p_holm = stats::p.adjust(p_value, method = "holm"))
}

make_balance_outputs <- function(study_spec) {
  design <- make_balance_design(study_spec)
  long <- design$long
  pairwise <- pairwise_smd_multiarm(long)
  omnibus <- omnibus_balance_test(long)
  
  max_smd <- pairwise %>%
    dplyr::group_by(variable, label) %>%
    dplyr::summarise(
      max_abs_smd = dplyr::if_else(
        all(is.na(abs_smd)),
        NA_real_,
        max(abs_smd, na.rm = TRUE)
      ),
      mean_abs_smd = dplyr::if_else(
        all(is.na(abs_smd)),
        NA_real_,
        mean(abs_smd, na.rm = TRUE)
      ),
      .groups = "drop"
    )
  
  group_summary <- long %>%
    dplyr::group_by(variable, label, party_n) %>%
    dplyr::summarise(
      mean = mean(value, na.rm = TRUE),
      sd = stats::sd(value, na.rm = TRUE),
      n = sum(!is.na(value)),
      .groups = "drop"
    ) %>%
    tidyr::pivot_wider(
      names_from = party_n,
      values_from = c(mean, sd, n),
      names_glue = "{.value}_condition_{party_n}"
    ) %>%
    dplyr::left_join(max_smd, by = c("variable", "label")) %>%
    dplyr::left_join(omnibus, by = c("variable", "label")) %>%
    dplyr::arrange(dplyr::desc(max_abs_smd))
  
  write_csv_unified(
    pairwise,
    paste0(study_spec$study_id, "_assignment_balance_pairwise_smd.csv")
  )
  write_csv_unified(
    group_summary,
    paste0(study_spec$study_id, "_assignment_balance_summary.csv")
  )
  
  love_df <- pairwise %>%
    dplyr::left_join(max_smd, by = c("variable", "label")) %>%
    dplyr::mutate(
      label_ordered = stats::reorder(label, max_abs_smd)
    )
  
  p_love <- ggplot2::ggplot(
    love_df,
    ggplot2::aes(
      x = abs_smd,
      y = label_ordered
    )
  ) +
    ggplot2::geom_vline(
      xintercept = 0.10,
      linetype = "dashed",
      linewidth = 0.55
    ) +
    ggplot2::geom_point(
      alpha = 0.30,
      size = 1.4,
      position = ggplot2::position_jitter(height = 0.10, width = 0)
    ) +
    ggplot2::geom_point(
      data = max_smd %>%
        dplyr::mutate(label_ordered = stats::reorder(label, max_abs_smd)),
      ggplot2::aes(
        x = max_abs_smd,
        y = label_ordered
      ),
      inherit.aes = FALSE,
      shape = 21,
      fill = "white",
      size = 2.5,
      stroke = 0.8
    ) +
    ggplot2::scale_x_continuous(
      breaks = scales::pretty_breaks(n = 6),
      expand = ggplot2::expansion(mult = c(0, 0.05))
    ) +
    ggplot2::labs(
      x = "条件間の絶対標準化平均差(|SMD|)",
      y = NULL,
      subtitle = paste0(
        study_spec$study_label,
        ":各点は条件ペア、白抜き点は最大絶対SMD"
      ),
      caption = "破線は |SMD| = 0.10。多群無作為割付のため、2・3・4・5条件の全6ペアを比較。"
    ) +
    ggplot2::theme_bw(base_size = 11) +
    ggplot2::theme(
      panel.grid.minor = ggplot2::element_blank(),
      axis.text = ggplot2::element_text(color = "black"),
      plot.subtitle = ggplot2::element_text(face = "bold")
    )
  
  save_plot_both(
    paste0(study_spec$study_id, "_assignment_balance_love_plot"),
    p_love,
    width = 9.2,
    height = max(6.5, 0.23 * dplyr::n_distinct(love_df$label) + 2.5)
  )
  
  standardized_means <- long %>%
    dplyr::group_by(variable, label) %>%
    dplyr::mutate(
      overall_mean = mean(value, na.rm = TRUE),
      overall_sd = stats::sd(value, na.rm = TRUE),
      value_z = dplyr::if_else(
        is.finite(overall_sd) & overall_sd > 0,
        (value - overall_mean) / overall_sd,
        NA_real_
      )
    ) %>%
    dplyr::ungroup() %>%
    dplyr::group_by(variable, label, party_n) %>%
    dplyr::summarise(
      mean_z = mean(value_z, na.rm = TRUE),
      .groups = "drop"
    )
  
  groups <- sort(unique(standardized_means$party_n))
  diagonal_df <- purrr::map_dfr(
    utils::combn(groups, 2, simplify = FALSE),
    function(pair_value) {
      a <- pair_value[1]
      b <- pair_value[2]
      
      standardized_means %>%
        dplyr::filter(party_n %in% c(a, b)) %>%
        tidyr::pivot_wider(
          names_from = party_n,
          values_from = mean_z,
          names_prefix = "condition_"
        ) %>%
        dplyr::mutate(
          condition_a = a,
          condition_b = b,
          comparison = paste0(a, " vs ", b),
          x_mean = .data[[paste0("condition_", a)]],
          y_mean = .data[[paste0("condition_", b)]],
          diagonal_deviation = y_mean - x_mean,
          abs_diagonal_deviation = abs(diagonal_deviation)
        )
    }
  )
  
  top_labels <- diagonal_df %>%
    dplyr::group_by(comparison) %>%
    dplyr::slice_max(
      order_by = abs_diagonal_deviation,
      n = 3,
      with_ties = FALSE
    ) %>%
    dplyr::ungroup()
  
  axis_limit <- max(
    abs(c(diagonal_df$x_mean, diagonal_df$y_mean)),
    na.rm = TRUE
  )
  axis_limit <- max(0.10, axis_limit * 1.15)
  
  p_diagonal <- ggplot2::ggplot(
    diagonal_df,
    ggplot2::aes(x = x_mean, y = y_mean)
  ) +
    ggplot2::geom_abline(
      intercept = 0,
      slope = 1,
      linewidth = 0.60,
      linetype = "dashed"
    ) +
    ggplot2::geom_hline(yintercept = 0, linewidth = 0.25) +
    ggplot2::geom_vline(xintercept = 0, linewidth = 0.25) +
    ggplot2::geom_point(shape = 21, fill = "white", size = 2.2) +
    ggplot2::geom_text(
      data = top_labels,
      ggplot2::aes(label = label),
      size = 2.6,
      check_overlap = TRUE,
      vjust = -0.7
    ) +
    ggplot2::facet_wrap(~ comparison, ncol = 3) +
    ggplot2::coord_equal(
      xlim = c(-axis_limit, axis_limit),
      ylim = c(-axis_limit, axis_limit)
    ) +
    ggplot2::labs(
      x = "左側条件の標準化共変量平均",
      y = "右側条件の標準化共変量平均",
      subtitle = paste0(
        study_spec$study_label,
        ":45度線からの乖離による割付バランス診断"
      ),
      caption = "各点は回答者共変量または支持政党・地域のダミー変数。45度線に近いほど条件間の構成が類似。"
    ) +
    ggplot2::theme_bw(base_size = 10.5) +
    ggplot2::theme(
      panel.grid.minor = ggplot2::element_blank(),
      strip.background = ggplot2::element_rect(fill = "white"),
      strip.text = ggplot2::element_text(face = "bold"),
      axis.text = ggplot2::element_text(color = "black")
    )
  
  write_csv_unified(
    diagonal_df,
    paste0(study_spec$study_id, "_assignment_balance_diagonal_data.csv")
  )
  
  save_plot_both(
    paste0(study_spec$study_id, "_assignment_balance_diagonal_plot"),
    p_diagonal,
    width = 11.5,
    height = 7.5
  )
  
  list(
    design = design,
    pairwise_smd = pairwise,
    summary = group_summary,
    love_plot = p_love,
    diagonal_data = diagonal_df,
    diagonal_plot = p_diagonal
  )
}

assignment_balance_results <- purrr::map(
  study_specs,
  make_balance_outputs
)


make_profile_randomization_outputs <- function(study_spec) {
  env <- study_spec$env
  attributes <- env$attr_terms
  
  randomization_long <- env$conjoint_all_m %>%
    dplyr::select(
      ID,
      party_n,
      task,
      profile,
      dplyr::all_of(attributes)
    ) %>%
    tidyr::pivot_longer(
      cols = dplyr::all_of(attributes),
      names_to = "attribute",
      values_to = "level"
    ) %>%
    dplyr::mutate(
      level = as.character(level),
      party_n = as.integer(as.character(party_n))
    ) %>%
    dplyr::filter(!is.na(level), level != "")
  
  frequency <- randomization_long %>%
    dplyr::count(party_n, attribute, level, name = "observed_n") %>%
    dplyr::group_by(party_n, attribute) %>%
    dplyr::mutate(
      total_n = sum(observed_n),
      n_levels = dplyr::n(),
      observed_share = observed_n / total_n,
      expected_share = 1 / n_levels,
      deviation = observed_share - expected_share,
      abs_deviation = abs(deviation)
    ) %>%
    dplyr::ungroup()
  
  uniformity_tests <- frequency %>%
    dplyr::group_by(party_n, attribute) %>%
    dplyr::group_modify(
      ~ {
        test <- suppressWarnings(
          stats::chisq.test(
            x = .x$observed_n,
            p = rep(1 / nrow(.x), nrow(.x))
          )
        )
        tibble::tibble(
          chi_square = unname(test$statistic),
          df = unname(test$parameter),
          p_value = test$p.value,
          max_abs_share_deviation = max(.x$abs_deviation)
        )
      }
    ) %>%
    dplyr::ungroup() %>%
    dplyr::mutate(p_holm = stats::p.adjust(p_value, method = "holm"))
  
  write_csv_unified(
    frequency,
    paste0(study_spec$study_id, "_profile_level_randomization_frequency.csv")
  )
  write_csv_unified(
    uniformity_tests,
    paste0(study_spec$study_id, "_profile_level_randomization_tests.csv")
  )
  
  top_frequency_labels <- frequency %>%
    dplyr::group_by(party_n, attribute) %>%
    dplyr::slice_max(abs_deviation, n = 1, with_ties = FALSE) %>%
    dplyr::ungroup()
  
  p_randomization <- ggplot2::ggplot(
    frequency,
    ggplot2::aes(
      x = expected_share,
      y = observed_share
    )
  ) +
    ggplot2::geom_abline(
      intercept = 0,
      slope = 1,
      linetype = "dashed",
      linewidth = 0.65
    ) +
    ggplot2::geom_point(
      ggplot2::aes(shape = factor(party_n)),
      size = 2.2,
      fill = "white"
    ) +
    ggplot2::geom_text(
      data = top_frequency_labels,
      ggplot2::aes(label = level),
      size = 2.4,
      check_overlap = TRUE,
      vjust = -0.7
    ) +
    ggplot2::facet_wrap(~ attribute, ncol = 3) +
    ggplot2::coord_equal() +
    ggplot2::labs(
      x = "設計上の期待比率",
      y = "観測比率",
      shape = study_spec$condition_label,
      subtitle = paste0(
        study_spec$study_label,
        ":属性水準の観測比率と期待比率"
      ),
      caption = "各点は属性水準×条件。45度線に近いほど属性水準の無作為提示が設計どおり。"
    ) +
    ggplot2::theme_bw(base_size = 10.5) +
    ggplot2::theme(
      panel.grid.minor = ggplot2::element_blank(),
      strip.background = ggplot2::element_rect(fill = "white"),
      strip.text = ggplot2::element_text(face = "bold"),
      legend.position = "bottom",
      axis.text = ggplot2::element_text(color = "black")
    )
  
  save_plot_both(
    paste0(study_spec$study_id, "_profile_randomization_diagonal_plot"),
    p_randomization,
    width = 11,
    height = ifelse(study_spec$study_id == "study3", 7.5, 8.5)
  )
  
  list(
    frequency = frequency,
    uniformity_tests = uniformity_tests,
    plot = p_randomization
  )
}

profile_randomization_results <- purrr::map(
  study_specs,
  make_profile_randomization_outputs
)


# 補遺H関連コード
make_term_label_table <- function(env) {
  if (exists("term_labels", envir = env, inherits = FALSE)) {
    out <- get("term_labels", envir = env)
    required <- c("term", "attribute", "label")
    if (all(required %in% names(out))) {
      return(out %>% dplyr::select(dplyr::any_of(c(required, "order"))))
    }
  }
  
  tibble::tibble(
    term = character(),
    attribute = character(),
    label = character(),
    order = integer()
  )
}

run_support_amce_heterogeneity <- function(study_spec) {
  env <- study_spec$env
  study_id <- study_spec$study_id
  study_label <- study_spec$study_label
  out_dir <- file.path(unified_output_dir, paste0(study_id, "_party_support"))
  dir.create(out_dir, showWarnings = FALSE, recursive = TRUE)
  
  support_id <- env$covar_id %>%
    dplyr::transmute(
      ID = as.character(ID),
      party_support_h = as.character(party_support_f)
    ) %>%
    dplyr::mutate(
      party_support_h = dplyr::na_if(party_support_h, "欠損・無回答")
    )
  
  dat <- env$conjoint_all_m %>%
    dplyr::mutate(
      ID = as.character(ID),
      party_n = as.integer(as.character(party_n))
    ) %>%
    dplyr::left_join(support_id, by = "ID") %>%
    dplyr::filter(
      !is.na(party_support_h),
      party_support_h != "",
      !party_support_h %in% excluded_support_categories
    )
  
  support_counts <- dat %>%
    dplyr::distinct(ID, party_n, party_support_h) %>%
    dplyr::count(party_support_h, party_n, name = "n_condition") %>%
    dplyr::group_by(party_support_h) %>%
    dplyr::mutate(
      n_total = sum(n_condition),
      min_condition_n = min(n_condition),
      conditions_observed = dplyr::n_distinct(party_n)
    ) %>%
    dplyr::ungroup()
  
  support_totals <- dat %>%
    dplyr::distinct(ID, party_support_h) %>%
    dplyr::count(party_support_h, name = "n_total_distinct")
  
  support_counts <- support_counts %>%
    dplyr::left_join(support_totals, by = "party_support_h") %>%
    dplyr::arrange(dplyr::desc(n_total_distinct), party_support_h)
  
  eligible_groups <- support_counts %>%
    dplyr::distinct(
      party_support_h,
      n_total_distinct,
      min_condition_n,
      conditions_observed
    ) %>%
    dplyr::filter(
      n_total_distinct >= unified_config$min_support_total_n,
      conditions_observed == 4
    ) %>%
    dplyr::pull(party_support_h)
  
  readr::write_csv(
    support_counts,
    file.path(out_dir, "party_support_sample_counts.csv"),
    na = ""
  )
  
  formula_subgroup <- stats::as.formula(
    paste(
      "selected ~",
      paste(env$attr_terms, collapse = " + ")
    )
  )
  
  estimate_one_cell <- function(group_value, n_value) {
    dat_cell <- dat %>%
      dplyr::filter(
        party_support_h == group_value,
        party_n == n_value
      )
    
    n_ids <- dplyr::n_distinct(dat_cell$ID)
    
    if (n_ids < unified_config$min_support_cell_n) {
      return(
        tibble::tibble(
          term = NA_character_,
          estimate = NA_real_,
          std.error = NA_real_,
          statistic = NA_real_,
          p.value = NA_real_,
          conf.low = NA_real_,
          conf.high = NA_real_,
          party_support_h = group_value,
          party_n = n_value,
          n_ids = n_ids,
          status = "insufficient_cell_n"
        )
      )
    }
    
    model <- tryCatch(
      fixest::feols(
        formula_subgroup,
        data = dat_cell,
        vcov = ~ ID
      ),
      error = function(e) e
    )
    
    if (inherits(model, "error")) {
      return(
        tibble::tibble(
          term = NA_character_,
          estimate = NA_real_,
          std.error = NA_real_,
          statistic = NA_real_,
          p.value = NA_real_,
          conf.low = NA_real_,
          conf.high = NA_real_,
          party_support_h = group_value,
          party_n = n_value,
          n_ids = n_ids,
          status = paste0("model_error: ", conditionMessage(model))
        )
      )
    }
    
    tidy_fixest_unified(model) %>%
      dplyr::mutate(
        party_support_h = group_value,
        party_n = n_value,
        n_ids = n_ids,
        status = "estimated"
      )
  }
  
  subgroup_coefficients <- purrr::map_dfr(
    eligible_groups,
    function(group_value) {
      purrr::map_dfr(
        2:5,
        ~ estimate_one_cell(group_value, .x)
      )
    }
  )
  
  term_label_table <- make_term_label_table(env)
  
  subgroup_coefficients <- subgroup_coefficients %>%
    dplyr::left_join(term_label_table, by = "term") %>%
    dplyr::mutate(
      attribute = dplyr::coalesce(attribute, "その他"),
      label = dplyr::coalesce(label, term),
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,
      party_n_label = factor(
        party_n,
        levels = 2:5,
        labels = paste0(2:5, ifelse(study_id == "study3", "選択肢", "政党"))
      )
    )
  
  readr::write_csv(
    subgroup_coefficients,
    file.path(out_dir, "party_support_subgroup_amce_coefficients.csv"),
    na = ""
  )
  
  for (group_value in eligible_groups) {
    plot_dat <- subgroup_coefficients %>%
      dplyr::filter(
        party_support_h == group_value,
        status == "estimated",
        !is.na(term)
      )
    
    if (nrow(plot_dat) == 0) next
    
    label_order <- plot_dat %>%
      dplyr::arrange(attribute, dplyr::coalesce(order, 9999), label) %>%
      dplyr::distinct(label) %>%
      dplyr::pull(label)
    
    plot_dat <- plot_dat %>%
      dplyr::mutate(
        label = factor(label, levels = rev(label_order))
      )
    
    n_group <- support_totals %>%
      dplyr::filter(party_support_h == group_value) %>%
      dplyr::pull(n_total_distinct)
    
    p_group <- ggplot2::ggplot(
      plot_dat,
      ggplot2::aes(
        x = estimate_pp,
        y = label,
        shape = party_n_label
      )
    ) +
      ggplot2::geom_vline(xintercept = 0, linewidth = 0.45) +
      ggplot2::geom_errorbarh(
        ggplot2::aes(
          xmin = conf.low_pp,
          xmax = conf.high_pp
        ),
        height = 0.10,
        position = ggplot2::position_dodge(width = 0.55),
        linewidth = 0.55
      ) +
      ggplot2::geom_point(
        position = ggplot2::position_dodge(width = 0.55),
        size = 2.3,
        fill = "white"
      ) +
      ggplot2::facet_grid(
        attribute ~ .,
        scales = "free_y",
        space = "free_y"
      ) +
      ggplot2::labs(
        x = "選択確率への効果(percentage points)",
        y = NULL,
        shape = study_spec$condition_label,
        subtitle = paste0(
          study_label,
          ":",
          group_value,
          "支持者(n = ",
          scales::comma(n_group),
          ")"
        ),
        caption = paste0(
          "回答者IDでクラスタ化した標準誤差。各条件セルn < ",
          unified_config$min_support_cell_n,
          "は推定しない。"
        )
      ) +
      ggplot2::theme_bw(base_size = 10.5) +
      ggplot2::theme(
        panel.grid.minor = ggplot2::element_blank(),
        strip.background = ggplot2::element_rect(fill = "white"),
        strip.text = ggplot2::element_text(face = "bold"),
        legend.position = "bottom",
        axis.text = ggplot2::element_text(color = "black")
      )
    
    group_index <- match(group_value, eligible_groups)
    file_stub <- paste0(
      study_id,
      "_party_support_amce_",
      sprintf("%02d", group_index),
      "_",
      safe_filename(group_value)
    )
    
    ggplot2::ggsave(
      filename = file.path(out_dir, paste0(file_stub, ".png")),
      plot = p_group,
      width = 10.5,
      height = ifelse(study_id == "study3", 11.5, 10.0),
      dpi = 400,
      bg = "white"
    )
    
    ggplot2::ggsave(
      filename = file.path(out_dir, paste0(file_stub, ".pdf")),
      plot = p_group,
      width = 10.5,
      height = ifelse(study_id == "study3", 11.5, 10.0),
      device = grDevices::cairo_pdf,
      bg = "white"
    )
  }
  
  interaction_models <- list()
  interaction_test_text <- character()
  
  dat_interaction <- dat %>%
    dplyr::filter(party_support_h %in% eligible_groups) %>%
    dplyr::mutate(
      party_support_h = factor(party_support_h)
    )
  
  if ("支持政党なし" %in% levels(dat_interaction$party_support_h)) {
    dat_interaction <- dat_interaction %>%
      dplyr::mutate(
        party_support_h = stats::relevel(
          party_support_h,
          ref = "支持政党なし"
        )
      )
  } else if (nrow(support_totals) > 0) {
    largest_group <- support_totals %>%
      dplyr::filter(party_support_h %in% eligible_groups) %>%
      dplyr::slice_max(n_total_distinct, n = 1, with_ties = FALSE) %>%
      dplyr::pull(party_support_h)
    
    if (length(largest_group) == 1) {
      dat_interaction <- dat_interaction %>%
        dplyr::mutate(
          party_support_h = stats::relevel(
            party_support_h,
            ref = largest_group
          )
        )
    }
  }
  
  formula_interaction <- stats::as.formula(
    paste0(
      "selected ~ party_support_h * (",
      paste(env$attr_terms, collapse = " + "),
      ")"
    )
  )
  
  for (n_value in 2:5) {
    dat_n <- dat_interaction %>% dplyr::filter(party_n == n_value)
    
    model_n <- tryCatch(
      fixest::feols(
        formula_interaction,
        data = dat_n,
        vcov = ~ ID
      ),
      error = function(e) e
    )
    
    interaction_models[[as.character(n_value)]] <- model_n
    
    interaction_test_text <- c(
      interaction_test_text,
      paste0("\n===== ", study_label, ": condition ", n_value, " =====\n")
    )
    
    if (inherits(model_n, "error")) {
      interaction_test_text <- c(
        interaction_test_text,
        paste0("Model error: ", conditionMessage(model_n), "\n")
      )
    } else {
      interaction_test_text <- c(
        interaction_test_text,
        capture.output(summary(model_n)),
        "\n--- Joint Wald test for party-support interaction terms ---\n",
        tryCatch(
          capture.output(
            fixest::wald(
              model_n,
              keep = "party_support_h.*:|:party_support_h"
            )
          ),
          error = function(e) paste0("Wald test error: ", conditionMessage(e))
        )
      )
    }
  }
  
  writeLines(
    interaction_test_text,
    con = file.path(out_dir, "party_support_interaction_models_and_wald_tests.txt")
  )
  
  list(
    support_counts = support_counts,
    eligible_groups = eligible_groups,
    subgroup_coefficients = subgroup_coefficients,
    interaction_models = interaction_models,
    data = dat
  )
}

party_support_amce_results <- purrr::map(
  study_specs,
  run_support_amce_heterogeneity
)

run_support_relative_cue <- function(study_spec, amce_result) {
  env <- study_spec$env
  study_id <- study_spec$study_id
  out_dir <- file.path(unified_output_dir, paste0(study_id, "_party_support"))
  
  dat <- amce_result$data
  eligible_groups <- amce_result$eligible_groups
  
  observed_list <- list()
  interval_list <- list()
  slope_list <- list()
  failure_list <- list()
  
  for (group_index in seq_along(eligible_groups)) {
    group_value <- eligible_groups[group_index]
    dat_group <- dat %>%
      dplyr::filter(party_support_h == group_value)
    
    condition_counts <- dat_group %>%
      dplyr::distinct(ID, party_n) %>%
      dplyr::count(party_n, name = "n_ids")
    
    if (
      !identical(sort(condition_counts$party_n), 2:5) ||
      any(condition_counts$n_ids < unified_config$min_support_cell_n)
    ) {
      failure_list[[group_value]] <- tibble::tibble(
        party_support_h = group_value,
        reason = "Not all four conditions meet the minimum cell size"
      )
      next
    }
    
    prepared <- tryCatch(
      env$prepare_relative_cue_analysis(
        data = dat_group,
        cue_map = env$relative_cue_map
      ),
      error = function(e) e
    )
    
    if (inherits(prepared, "error")) {
      failure_list[[group_value]] <- tibble::tibble(
        party_support_h = group_value,
        reason = conditionMessage(prepared)
      )
      next
    }
    
    observed <- env$estimate_relative_cue_indices(prepared)
    observed_slopes <- env$estimate_relative_cue_slopes(
      observed$cue_importance
    )
    
    observed_list[[group_value]] <- observed$cue_importance %>%
      dplyr::mutate(
        party_support_h = group_value,
        .before = 1
      )
    
    slope_list[[group_value]] <- tibble::tibble(
      party_support_h = group_value,
      statistic = names(observed_slopes),
      estimate = as.numeric(observed_slopes)
    )
    
    B <- unified_config$support_bootstrap_B
    
    if (B > 0) {
      cache_file <- file.path(
        out_dir,
        paste0(
          "support_relative_cue_bootstrap_",
          unified_config$cue_importance_metric_version,
          "_",
          sprintf("%02d", group_index),
          "_B",
          B,
          ".rds"
        )
      )
      
      if (
        file.exists(cache_file) &&
        !unified_config$rerun_support_bootstrap
      ) {
        bootstrap_result <- readRDS(cache_file)
      } else {
        bootstrap_result <- env$run_relative_cue_bootstrap(
          prepared = prepared,
          B = B,
          seed = unified_config$support_bootstrap_seed +
            1000 * match(study_id, names(study_specs)) +
            group_index,
          progress_every = max(0, floor(B / 5))
        )
        saveRDS(bootstrap_result, cache_file)
      }
      
      intervals <- env$summarise_condition_intervals(
        observed_cue_importance = observed$cue_importance,
        bootstrap_condition_results = bootstrap_result$condition_estimates
      ) %>%
        dplyr::mutate(
          party_support_h = group_value,
          .before = 1
        )
      
      slope_inference <- env$summarise_slope_inference(
        observed_slopes = observed_slopes,
        bootstrap_slopes = bootstrap_result$slopes
      ) %>%
        dplyr::mutate(
          party_support_h = group_value,
          .before = 1
        )
      
      interval_list[[group_value]] <- intervals
      slope_list[[paste0(group_value, "_inference")]] <- slope_inference
    }
  }
  
  observed_df <- dplyr::bind_rows(observed_list)
  interval_df <- dplyr::bind_rows(interval_list)
  slope_df <- dplyr::bind_rows(slope_list)
  failures_df <- dplyr::bind_rows(failure_list)
  
  readr::write_csv(
    observed_df,
    file.path(out_dir, "party_support_relative_cue_observed.csv"),
    na = ""
  )
  readr::write_csv(
    interval_df,
    file.path(out_dir, "party_support_relative_cue_intervals.csv"),
    na = ""
  )
  readr::write_csv(
    slope_df,
    file.path(out_dir, "party_support_relative_cue_slopes.csv"),
    na = ""
  )
  readr::write_csv(
    failures_df,
    file.path(out_dir, "party_support_relative_cue_failures.csv"),
    na = ""
  )
  
  if (nrow(interval_df) > 0) {
    plot_df <- interval_df %>%
      dplyr::filter(statistic == "relative_party_weight_pairwise") %>%
      dplyr::mutate(
        estimate_pct = estimate * 100,
        conf_low_pct = conf_low * 100,
        conf_high_pct = conf_high * 100
      )
  } else {
    plot_df <- observed_df %>%
      dplyr::transmute(
        party_support_h,
        party_n,
        estimate_pct = relative_party_weight_pairwise * 100,
        conf_low_pct = NA_real_,
        conf_high_pct = NA_real_
      )
  }
  
  if (nrow(plot_df) > 0) {
    p_relative_support <- ggplot2::ggplot(
      plot_df,
      ggplot2::aes(
        x = party_n,
        y = estimate_pct,
        group = 1
      )
    ) +
      ggplot2::geom_hline(yintercept = 50, linetype = "dashed", linewidth = 0.45) +
      ggplot2::geom_line(linewidth = 0.70) +
      ggplot2::geom_errorbar(
        ggplot2::aes(
          ymin = conf_low_pct,
          ymax = conf_high_pct
        ),
        width = 0.08,
        linewidth = 0.55,
        na.rm = TRUE
      ) +
      ggplot2::geom_point(shape = 21, fill = "white", size = 2.5) +
      ggplot2::facet_wrap(~ party_support_h, ncol = 3) +
      ggplot2::scale_x_continuous(
        breaks = 2:5,
        labels = paste0(2:5, ifelse(study_id == "study3", "選択肢", "政党"))
      ) +
      ggplot2::scale_y_continuous(
        labels = function(x) paste0(x, "%"),
        breaks = scales::pretty_breaks(n = 6)
      ) +
      ggplot2::labs(
        x = study_spec$condition_label,
        y = "政党手がかりの相対比重",
        subtitle = paste0(
          study_spec$study_label,
          ":支持政党別の政党手がかり相対比重"
        ),
        caption = paste0(
          "各属性内の限界平均の平均絶対ペア差に基づく。",
          ifelse(
            unified_config$support_bootstrap_B > 0,
            paste0(
              "95%信頼区間は回答者クラスタ・ブートストラップ(B = ",
              unified_config$support_bootstrap_B,
              ")。"
            ),
            "信頼区間は未計算。"
          )
        )
      ) +
      ggplot2::theme_bw(base_size = 10.5) +
      ggplot2::theme(
        panel.grid.minor = ggplot2::element_blank(),
        strip.background = ggplot2::element_rect(fill = "white"),
        strip.text = ggplot2::element_text(face = "bold"),
        axis.text = ggplot2::element_text(color = "black")
      )
    
    ggplot2::ggsave(
      filename = file.path(out_dir, "party_support_relative_cue_weight.png"),
      plot = p_relative_support,
      width = 11.5,
      height = max(7.0, 2.6 * ceiling(dplyr::n_distinct(plot_df$party_support_h) / 3)),
      dpi = 400,
      bg = "white"
    )
    
    ggplot2::ggsave(
      filename = file.path(out_dir, "party_support_relative_cue_weight.pdf"),
      plot = p_relative_support,
      width = 11.5,
      height = max(7.0, 2.6 * ceiling(dplyr::n_distinct(plot_df$party_support_h) / 3)),
      device = grDevices::cairo_pdf,
      bg = "white"
    )
  } else {
    p_relative_support <- NULL
  }
  
  list(
    observed = observed_df,
    intervals = interval_df,
    slopes = slope_df,
    failures = failures_df,
    plot = p_relative_support
  )
}

party_support_relative_cue_results <- purrr::map2(
  study_specs,
  party_support_amce_results,
  run_support_relative_cue
)


# 補遺I関連コード
extract_cue_slope_inference <- function(study_spec) {
  env <- study_spec$env
  
  env$relative_cue_slope_inference %>%
    dplyr::mutate(
      study_id = study_spec$study_id,
      study_label = study_spec$study_label,
      .before = 1
    )
}

cue_slope_inference_all <- purrr::map_dfr(
  study_specs,
  extract_cue_slope_inference
) %>%
  dplyr::mutate(
    statistic_label = dplyr::recode(
      statistic,
      party_importance_pairwise = "政党の手がかりの未調整重要度",
      economic_importance_pairwise = "経済の手がかりの未調整重要度",
      party_importance_pairwise_adjusted =
        "政党の手がかりの選択肢数調整済み重要度",
      economic_importance_pairwise_adjusted =
        "経済の手がかりの選択肢数調整済み重要度",
      relative_party_weight_pairwise = "政党の手がかりの相対比重"
    ),
    metric_scale = dplyr::case_when(
      statistic %in% c(
        "party_importance_pairwise_adjusted",
        "economic_importance_pairwise_adjusted"
      ) ~ "choice_set_adjusted_baseline_relative",
      statistic == "relative_party_weight_pairwise" ~
        "relative_share",
      TRUE ~ "unadjusted_probability_difference"
    ),
    estimate_pp_per_option = estimate * 100,
    conf_low_pp_per_option = conf_low * 100,
    conf_high_pp_per_option = conf_high * 100
  )

write_csv_unified(
  cue_slope_inference_all,
  "cue_importance_linear_slope_all_studies.csv"
)

choice_set_adjusted_slope_summary <- cue_slope_inference_all %>%
  dplyr::filter(
    statistic %in% c(
      "party_importance_pairwise_adjusted",
      "economic_importance_pairwise_adjusted"
    )
  ) %>%
  dplyr::mutate(
    cue_family = dplyr::recode(
      statistic,
      party_importance_pairwise_adjusted =
        "政党・政党名手がかり",
      economic_importance_pairwise_adjusted =
        "経済手がかり"
    ),
    estimate_baseline_pct_per_option = estimate * 100,
    conf_low_baseline_pct_per_option = conf_low * 100,
    conf_high_baseline_pct_per_option = conf_high * 100
  )

write_csv_unified(
  choice_set_adjusted_slope_summary,
  "choice_set_adjusted_importance_linear_slopes.csv"
)

hypothesis_map <- tibble::tribble(
  ~study_id, ~hypothesis, ~statistic, ~expected_direction,
  "study1", "H1a(実験1)", "party_importance_pairwise", "positive",
  "study1", "H1b(実験1)", "economic_importance_pairwise", "negative",
  "study2", "H1a(実験2)", "party_importance_pairwise", "positive",
  "study2", "H1b(実験2)", "economic_importance_pairwise", "negative",
  "study3", "H2a(実験3)", "party_importance_pairwise", "positive",
  "study3", "H2b(実験3)", "economic_importance_pairwise", "negative"
)

hypothesis_test_summary <- hypothesis_map %>%
  dplyr::left_join(
    cue_slope_inference_all %>%
      dplyr::select(
        study_id,
        study_label,
        statistic,
        estimate,
        conf_low,
        conf_high,
        p_value_two_sided
      ),
    by = c("study_id", "statistic")
  ) %>%
  dplyr::mutate(
    estimate_in_expected_direction = dplyr::case_when(
      expected_direction == "positive" ~ estimate > 0,
      expected_direction == "negative" ~ estimate < 0,
      TRUE ~ NA
    ),
    ci_excludes_zero_in_expected_direction = dplyr::case_when(
      expected_direction == "positive" ~ conf_low > 0,
      expected_direction == "negative" ~ conf_high < 0,
      TRUE ~ NA
    ),
    conclusion = dplyr::case_when(
      ci_excludes_zero_in_expected_direction ~
        "予測方向で95%信頼区間が0を含まず、統計的に支持",
      estimate_in_expected_direction ~
        "点推定は予測方向だが、95%信頼区間が0を含む",
      TRUE ~
        "点推定が予測方向と一致しない"
    ),
    estimate_pp_per_option = estimate * 100,
    conf_low_pp_per_option = conf_low * 100,
    conf_high_pp_per_option = conf_high * 100,
    hypothesis = factor(
      hypothesis,
      levels = rev(hypothesis_map$hypothesis)
    )
  )

write_csv_unified(
  hypothesis_test_summary,
  "main_hypothesis_linear_trend_tests.csv"
)

p_hypothesis_slopes <- ggplot2::ggplot(
  hypothesis_test_summary,
  ggplot2::aes(
    x = estimate_pp_per_option,
    y = hypothesis,
    shape = expected_direction
  )
) +
  ggplot2::geom_vline(
    xintercept = 0,
    linewidth = 0.45
  ) +
  ggplot2::geom_errorbarh(
    ggplot2::aes(
      xmin = conf_low_pp_per_option,
      xmax = conf_high_pp_per_option
    ),
    height = 0.12,
    linewidth = 0.60
  ) +
  ggplot2::geom_point(
    size = 2.7,
    fill = "white"
  ) +
  ggplot2::scale_shape_manual(
    values = c(
      positive = 21,
      negative = 24
    ),
    labels = c(
      positive = "正の傾向を予測",
      negative = "負の傾向を予測"
    )
  ) +
  ggplot2::labs(
    x = "選択肢が1つ増えるときの重要度の変化(pp)",
    y = NULL,
    shape = NULL,
    caption = paste0(
      "重要度は、同一属性内の全水準ペアについて限界平均の絶対差を求め、",
      "その平均として算出。横線は回答者クラスタ・ブートストラップ95%信頼区間。"
    )
  ) +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(
    panel.grid.minor = ggplot2::element_blank(),
    legend.position = "bottom",
    axis.text = ggplot2::element_text(color = "black")
  )

save_plot_both(
  "fig_supp_hypothesis_linear_trend_tests",
  p_hypothesis_slopes,
  width = 9.5,
  height = 5.8
)

choice_set_adjusted_slope_summary <- choice_set_adjusted_slope_summary %>%
  dplyr::mutate(
    study_cue_label = paste0(
      study_label,
      ":",
      cue_family
    ),
    study_cue_label = factor(
      study_cue_label,
      levels = rev(
        unique(study_cue_label)
      )
    )
  )

p_choice_set_adjusted_slopes <- ggplot2::ggplot(
  choice_set_adjusted_slope_summary,
  ggplot2::aes(
    x = estimate_baseline_pct_per_option,
    y = study_cue_label,
    shape = cue_family
  )
) +
  ggplot2::geom_vline(
    xintercept = 0,
    linewidth = 0.45
  ) +
  ggplot2::geom_errorbarh(
    ggplot2::aes(
      xmin = conf_low_baseline_pct_per_option,
      xmax = conf_high_baseline_pct_per_option
    ),
    height = 0.12,
    linewidth = 0.60
  ) +
  ggplot2::geom_point(
    size = 2.7,
    fill = "white"
  ) +
  ggplot2::scale_shape_manual(
    values = c(
      "政党・政党名手がかり" = 21,
      "経済手がかり" = 24
    )
  ) +
  ggplot2::labs(
    x = paste0(
      "選択肢が1つ増えるときの調整済み重要度の変化",
      "(平均選択確率に対する割合:pp)"
    ),
    y = NULL,
    shape = NULL,
    caption = paste0(
      "調整済み重要度 = 未調整重要度 ÷(1/選択肢数)。",
      "事前登録済み仮説の判定ではなく、記述的・感度分析として示す。"
    )
  ) +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(
    panel.grid.minor = ggplot2::element_blank(),
    legend.position = "bottom",
    axis.text = ggplot2::element_text(color = "black")
  )

save_plot_both(
  "fig_supp_choice_set_adjusted_importance_slopes",
  p_choice_set_adjusted_slopes,
  width = 10.5,
  height = 6.2
)


# 本文コード
run_study3_all_party_match <- function() {
  env <- study3_env
  out_dir <- file.path(unified_output_dir, "study3_party_match_all_parties")
  dir.create(out_dir, showWarnings = FALSE, recursive = TRUE)
  
  dat <- env$conjoint_match %>%
    dplyr::mutate(
      ID = as.character(ID),
      party_n = as.integer(as.character(party_n)),
      support_party_valid = as.character(support_party_valid)
    ) %>%
    dplyr::filter(
      !is.na(support_party_valid),
      support_party_valid != ""
    )
  
  support_cell_counts <- dat %>%
    dplyr::distinct(ID, support_party_valid, party_n) %>%
    dplyr::count(
      support_party_valid,
      party_n,
      name = "n_respondents"
    ) %>%
    tidyr::complete(
      support_party_valid,
      party_n = 2:5,
      fill = list(n_respondents = 0L)
    ) %>%
    dplyr::group_by(support_party_valid) %>%
    dplyr::mutate(
      n_total = sum(n_respondents),
      min_cell_n = min(n_respondents),
      all_four_conditions = all(n_respondents > 0)
    ) %>%
    dplyr::ungroup()
  
  eligible_parties <- support_cell_counts %>%
    dplyr::distinct(
      support_party_valid,
      n_total,
      min_cell_n,
      all_four_conditions
    ) %>%
    dplyr::filter(
      n_total >= unified_config$min_support_total_n,
      min_cell_n >= unified_config$min_support_cell_n,
      all_four_conditions
    ) %>%
    dplyr::arrange(dplyr::desc(n_total)) %>%
    dplyr::pull(support_party_valid)
  
  readr::write_csv(
    support_cell_counts,
    file.path(out_dir, "party_match_all_party_sample_counts.csv"),
    na = ""
  )
  
  formula_cell <- stats::as.formula(
    paste(
      "selected ~",
      paste(
        c(
          "party_match",
          env$economic_attr_terms
        ),
        collapse = " + "
      )
    )
  )
  
  estimate_cell <- function(group_value, n_value) {
    dat_cell <- dat %>%
      dplyr::filter(
        support_party_valid == group_value,
        party_n == n_value
      )
    
    n_ids <- dplyr::n_distinct(dat_cell$ID)
    
    if (n_ids < unified_config$min_support_cell_n) {
      return(
        tibble::tibble(
          support_party_valid = group_value,
          party_n = n_value,
          n_ids = n_ids,
          estimate = NA_real_,
          std.error = NA_real_,
          conf.low = NA_real_,
          conf.high = NA_real_,
          p.value = NA_real_,
          status = "insufficient_cell_n"
        )
      )
    }
    
    model <- tryCatch(
      fixest::feols(
        formula_cell,
        data = dat_cell,
        vcov = ~ ID
      ),
      error = function(e) e
    )
    
    if (inherits(model, "error")) {
      return(
        tibble::tibble(
          support_party_valid = group_value,
          party_n = n_value,
          n_ids = n_ids,
          estimate = NA_real_,
          std.error = NA_real_,
          conf.low = NA_real_,
          conf.high = NA_real_,
          p.value = NA_real_,
          status = paste0("model_error: ", conditionMessage(model))
        )
      )
    }
    
    tidy_fixest_unified(model) %>%
      dplyr::filter(term == "party_match") %>%
      dplyr::transmute(
        support_party_valid = group_value,
        party_n = n_value,
        n_ids = n_ids,
        estimate,
        std.error,
        conf.low,
        conf.high,
        p.value,
        status = "estimated"
      )
  }
  
  cell_coefficients <- purrr::map_dfr(
    eligible_parties,
    function(group_value) {
      purrr::map_dfr(
        2:5,
        ~ estimate_cell(group_value, .x)
      )
    }
  ) %>%
    dplyr::mutate(
      estimate_pp = estimate * 100,
      conf.low_pp = conf.low * 100,
      conf.high_pp = conf.high * 100,
      party_n_label = factor(
        party_n,
        levels = 2:5,
        labels = paste0(2:5, "選択肢")
      ),
      main_text_party = support_party_valid %in% c(
        "自由民主党",
        "中道改革連合",
        "立憲民主党",
        "参政党"
      )
    )
  
  readr::write_csv(
    cell_coefficients,
    file.path(out_dir, "party_match_all_party_coefficients.csv"),
    na = ""
  )
  
  estimate_trend <- function(group_value) {
    dat_group <- dat %>%
      dplyr::filter(support_party_valid == group_value) %>%
      dplyr::mutate(
        party_n_f_heterogeneity = factor(
          party_n,
          levels = 2:5
        ),
        party_n_c_heterogeneity = party_n - 2
      )
    
    formula_trend <- stats::as.formula(
      paste(
        "selected ~ party_n_f_heterogeneity + party_match +",
        "party_match:party_n_c_heterogeneity +",
        paste(env$economic_attr_terms, collapse = " + ")
      )
    )
    
    model <- tryCatch(
      fixest::feols(
        formula_trend,
        data = dat_group,
        vcov = ~ ID
      ),
      error = function(e) e
    )
    
    if (inherits(model, "error")) {
      return(
        tibble::tibble(
          support_party_valid = group_value,
          term = "party_match:party_n_c_heterogeneity",
          estimate = NA_real_,
          std.error = NA_real_,
          conf.low = NA_real_,
          conf.high = NA_real_,
          p.value = NA_real_,
          status = paste0("model_error: ", conditionMessage(model))
        )
      )
    }
    
    tidy_fixest_unified(model) %>%
      dplyr::filter(
        stringr::str_detect(
          term,
          "party_match:party_n_c_heterogeneity|party_n_c_heterogeneity:party_match"
        )
      ) %>%
      dplyr::mutate(
        support_party_valid = group_value,
        status = "estimated",
        .before = 1
      )
  }
  
  trend_coefficients <- purrr::map_dfr(
    eligible_parties,
    estimate_trend
  ) %>%
    dplyr::mutate(
      estimate_pp_per_option = estimate * 100,
      conf.low_pp_per_option = conf.low * 100,
      conf.high_pp_per_option = conf.high * 100
    )
  
  readr::write_csv(
    trend_coefficients,
    file.path(out_dir, "party_match_all_party_linear_trends.csv"),
    na = ""
  )
  
  plot_df <- cell_coefficients %>%
    dplyr::filter(
      status == "estimated",
      is.finite(estimate_pp)
    ) %>%
    dplyr::mutate(
      support_party_valid = factor(
        support_party_valid,
        levels = eligible_parties
      )
    )
  
  if (nrow(plot_df) > 0) {
    p_all_party_match <- ggplot2::ggplot(
      plot_df,
      ggplot2::aes(
        x = party_n,
        y = estimate_pp,
        group = 1
      )
    ) +
      ggplot2::geom_hline(
        yintercept = 0,
        linewidth = 0.40
      ) +
      ggplot2::geom_line(
        linewidth = 0.65
      ) +
      ggplot2::geom_errorbar(
        ggplot2::aes(
          ymin = conf.low_pp,
          ymax = conf.high_pp
        ),
        width = 0.08,
        linewidth = 0.55
      ) +
      ggplot2::geom_point(
        shape = 21,
        fill = "white",
        size = 2.4
      ) +
      ggplot2::facet_wrap(
        ~ support_party_valid,
        ncol = 3
      ) +
      ggplot2::scale_x_continuous(
        breaks = 2:5,
        labels = paste0(2:5, "選択肢")
      ) +
      ggplot2::labs(
        x = "提示される選択肢数",
        y = "支持政党と提示政党名の一致効果(pp)",
        caption = paste0(
          "各支持政党サブグループ内で selected ~ party_match + 経済属性を推定。",
          "標準誤差は回答者IDでクラスタ化。"
        )
      ) +
      ggplot2::theme_bw(base_size = 10.5) +
      ggplot2::theme(
        panel.grid.minor = ggplot2::element_blank(),
        strip.background = ggplot2::element_rect(fill = "white"),
        strip.text = ggplot2::element_text(face = "bold"),
        axis.text = ggplot2::element_text(color = "black")
      )
    
    ggplot2::ggsave(
      filename = file.path(out_dir, "party_match_all_parties.png"),
      plot = p_all_party_match,
      width = 11.5,
      height = max(
        7.0,
        2.7 * ceiling(length(eligible_parties) / 3)
      ),
      dpi = 400,
      bg = "white"
    )
    
    ggplot2::ggsave(
      filename = file.path(out_dir, "party_match_all_parties.pdf"),
      plot = p_all_party_match,
      width = 11.5,
      height = max(
        7.0,
        2.7 * ceiling(length(eligible_parties) / 3)
      ),
      device = grDevices::cairo_pdf,
      bg = "white"
    )
  } else {
    p_all_party_match <- NULL
  }
  
  list(
    sample_counts = support_cell_counts,
    eligible_parties = eligible_parties,
    coefficients = cell_coefficients,
    trends = trend_coefficients,
    plot = p_all_party_match
  )
}

study3_all_party_match_results <- run_study3_all_party_match()


extract_cross_study_relative_weight <- function(study_spec) {
  env <- study_spec$env
  
  env$relative_cue_condition_intervals %>%
    dplyr::filter(
      statistic == "relative_party_weight_pairwise"
    ) %>%
    dplyr::transmute(
      study_id = study_spec$study_id,
      study_label = study_spec$study_label,
      party_n,
      estimate,
      conf_low,
      conf_high
    )
}

cross_study_relative_weight <- purrr::map_dfr(
  study_specs,
  extract_cross_study_relative_weight
) %>%
  dplyr::mutate(
    estimate_pct = estimate * 100,
    conf_low_pct = conf_low * 100,
    conf_high_pct = conf_high * 100,
    study_label = factor(
      study_label,
      levels = vapply(
        study_specs,
        `[[`,
        character(1),
        "study_label"
      )
    )
  )

write_csv_unified(
  cross_study_relative_weight,
  "cross_study_relative_party_weight.csv"
)

p_cross_study_relative <- ggplot2::ggplot(
  cross_study_relative_weight,
  ggplot2::aes(
    x = party_n,
    y = estimate_pct,
    linetype = study_label,
    shape = study_label,
    group = study_label
  )
) +
  ggplot2::geom_hline(
    yintercept = 50,
    linetype = "dotted",
    linewidth = 0.45
  ) +
  ggplot2::geom_line(
    linewidth = 0.80
  ) +
  ggplot2::geom_errorbar(
    ggplot2::aes(
      ymin = conf_low_pct,
      ymax = conf_high_pct
    ),
    width = 0.07,
    linewidth = 0.60,
    position = ggplot2::position_dodge(width = 0.08)
  ) +
  ggplot2::geom_point(
    size = 2.7,
    fill = "white",
    position = ggplot2::position_dodge(width = 0.08)
  ) +
  ggplot2::scale_x_continuous(
    breaks = 2:5,
    labels = paste0(2:5, "選択肢")
  ) +
  ggplot2::scale_y_continuous(
    labels = function(x) paste0(x, "%"),
    breaks = scales::pretty_breaks(n = 6)
  ) +
  ggplot2::labs(
    x = "提示される選択肢数",
    y = "政党の手がかりの相対比重",
    linetype = NULL,
    shape = NULL,
    caption = paste0(
      "限界平均の平均絶対ペア差に基づく。",
      "エラーバーは回答者クラスタ・ブートストラップ95%信頼区間。"
    )
  ) +
  ggplot2::theme_bw(base_size = 11.5) +
  ggplot2::theme(
    panel.grid.minor = ggplot2::element_blank(),
    legend.position = "bottom",
    axis.text = ggplot2::element_text(color = "black")
  )

save_plot_both(
  "fig_supp_cross_study_relative_party_weight",
  p_cross_study_relative,
  width = 9.5,
  height = 6.0
)


# 出力整理コード
main_text_figure_manifest <- tibble::tribble(
  ~figure_number, ~study, ~analysis, ~file_png, ~file_pdf,
  "Figure 4", "Study 1", "共変量調整済みAMCE",
  file.path(unified_config$study1$output_dir, "amce_cov_facet_model.png"),
  NA_character_,
  "Figure 5", "Study 1", "政党・経済手がかりの重要度と相対比重",
  file.path(unified_config$study1$output_dir, "fig_study1_relative_cue_weight_jp_bw.png"),
  file.path(unified_config$study1$output_dir, "fig_study1_relative_cue_weight_jp_bw.pdf"),
  "Figure 6", "Study 2", "共変量調整済みAMCE",
  file.path(unified_config$study2$output_dir, "amce_cov_facet_model.png"),
  NA_character_,
  "Figure 7", "Study 2", "政党・経済手がかりの重要度と相対比重",
  file.path(unified_config$study2$output_dir, "fig_study2_relative_cue_weight_jp_bw.png"),
  file.path(unified_config$study2$output_dir, "fig_study2_relative_cue_weight_jp_bw.pdf"),
  "Figure 8", "Study 3", "共変量調整済みAMCE",
  file.path(unified_config$study3$output_dir, "amce_cov_facet_model.png"),
  NA_character_,
  "Figure 9", "Study 3", "政党名・経済手がかりの重要度と相対比重",
  file.path(unified_config$study3$output_dir, "fig_study3_relative_cue_weight_jp_bw.png"),
  file.path(unified_config$study3$output_dir, "fig_study3_relative_cue_weight_jp_bw.pdf"),
  "Figure 10", "Study 3", "支持政党と提示政党名の一致効果",
  file.path(unified_config$study3$output_dir, "party_match_effect_combined.png"),
  NA_character_
)

write_csv_unified(
  main_text_figure_manifest,
  "main_text_figure_reproduction_manifest.csv"
)

supplement_figure_manifest <- tibble::tribble(
  ~section, ~study, ~analysis, ~file_png,
  "B", "Study 1", "回答者割付バランス:Love plot",
  file.path(unified_output_dir, "study1_assignment_balance_love_plot.png"),
  "B", "Study 2", "回答者割付バランス:Love plot",
  file.path(unified_output_dir, "study2_assignment_balance_love_plot.png"),
  "B", "Study 3", "回答者割付バランス:Love plot",
  file.path(unified_output_dir, "study3_assignment_balance_love_plot.png"),
  "B", "Study 1", "回答者割付バランス:45度線診断",
  file.path(unified_output_dir, "study1_assignment_balance_diagonal_plot.png"),
  "B", "Study 2", "回答者割付バランス:45度線診断",
  file.path(unified_output_dir, "study2_assignment_balance_diagonal_plot.png"),
  "B", "Study 3", "回答者割付バランス:45度線診断",
  file.path(unified_output_dir, "study3_assignment_balance_diagonal_plot.png"),
  "B", "Study 1", "属性水準の観測比率対期待比率",
  file.path(unified_output_dir, "study1_profile_randomization_diagonal_plot.png"),
  "B", "Study 2", "属性水準の観測比率対期待比率",
  file.path(unified_output_dir, "study2_profile_randomization_diagonal_plot.png"),
  "B", "Study 3", "属性水準の観測比率対期待比率",
  file.path(unified_output_dir, "study3_profile_randomization_diagonal_plot.png"),
  "C", "Study 1–3", "H1a/H1b/H2a/H2bの線形傾向検定",
  file.path(unified_output_dir, "fig_supp_hypothesis_linear_trend_tests.png"),
  "C", "Study 1–3", "選択肢数調整済み重要度の線形傾向",
  file.path(unified_output_dir, "fig_supp_choice_set_adjusted_importance_slopes.png"),
  "C", "Study 1", "未調整・選択肢数調整済み重要度・相対比重",
  file.path(
    unified_config$study1$output_dir,
    "fig_study1_relative_cue_weight_choice_set_adjusted_jp_bw.png"
  ),
  "C", "Study 2", "未調整・選択肢数調整済み重要度・相対比重",
  file.path(
    unified_config$study2$output_dir,
    "fig_study2_relative_cue_weight_choice_set_adjusted_jp_bw.png"
  ),
  "C", "Study 3", "未調整・選択肢数調整済み重要度・相対比重",
  file.path(
    unified_config$study3$output_dir,
    "fig_study3_relative_cue_weight_choice_set_adjusted_jp_bw.png"
  ),
  "F", "Study 1–3", "政党手がかり相対比重の横断比較",
  file.path(unified_output_dir, "fig_supp_cross_study_relative_party_weight.png"),
  "G", "Study 3", "全ての十分な標本をもつ支持政党の一致効果",
  file.path(
    unified_output_dir,
    "study3_party_match_all_parties",
    "party_match_all_parties.png"
  ),
  "G", "Study 1–3", "支持政党別AMCE・相対比重",
  file.path(unified_output_dir, "<study>_party_support")
)

write_csv_unified(
  supplement_figure_manifest,
  "supplement_figure_manifest.csv"
)

supplement_section_manifest <- tibble::tribble(
  ~section, ~title, ~placement_logic, ~core_outputs,
  "A", "調査設計・質問文・標本構築",
  "読者が3実験の相違と分析対象者の形成を先に確認できるようにする。",
  "調査フロー、属性・水準、質問文、sample_flow、条件別n、欠損集計",
  "B", "無作為割付・属性提示・データ品質の診断",
  "推定結果より前に、処置条件とコンジョイント属性の無作為化が機能したことを示す。",
  "条件別共変量表、全6条件ペアのSMD、Love plot、45度線図、属性水準の観測対期待比率",
  "C", "推定量・相対比重・仮説検定",
  "本文の式(1)(2)とH1a/H1b/H2a/H2bの判定方法を一か所に集約する。",
  paste0(
    "AMCE、限界平均、平均絶対ペア差、選択肢数調整済み重要度、",
    "相対比重、ブートストラップ、線形傾向統合表"
  ),
  "D", "実験1(2023年)の完全な結果",
  "本文図4・5の再現後に、補助分析を同じ実験内でまとめる。",
  "調整済み・未調整AMCE、交互作用、ヒートマップ、条件付きロジット、相対比重傾向",
  "E", "実験2(2026年)と2023–2026年比較",
  "実験1の再現性と時点間変化を連続して読めるようにする。",
  "調整済み・未調整AMCE、交互作用、ヒートマップ、条件付きロジット、相対比重傾向、時点比較",
  "F", "実験3(2026年)の完全な結果",
  "具体的政党名の分析と、本文図8・9・10の追加推定をまとめる。",
  "AMCE、カテゴリカル・線形トレンド、条件付きロジット、相対比重、一致効果",
  "G", "政党支持による異質性",
  "本文の党派性メカニズムに直結するため、頑健性分析から独立させる。",
  "支持政党別AMCE、支持政党×属性Wald検定、支持政党別相対比重、全政党一致効果",
  "H", "除外基準・推定法・標本定義に関する感度分析",
  "主要結論が分析上の選択に依存しないかを最後に確認する。",
  "注意・操作確認、完全5課題、共変量なし、条件付きロジット、代替標本",
  "I", "再現性情報",
  "全ての分析後に、再現に必要な技術情報をまとめる。",
  "ファイル一覧、乱数シード、ブートストラップ回数、パッケージ、sessionInfo"
)

write_csv_unified(
  supplement_section_manifest,
  "supplement_section_manifest.csv"
)

saveRDS(
  list(
    config = unified_config,
    assignment_balance = assignment_balance_results,
    profile_randomization = profile_randomization_results,
    cue_slope_inference = cue_slope_inference_all,
    choice_set_adjusted_slope_summary =
      choice_set_adjusted_slope_summary,
    choice_set_adjusted_slope_plot =
      p_choice_set_adjusted_slopes,
    hypothesis_tests = hypothesis_test_summary,
    party_support_amce = party_support_amce_results,
    party_support_relative_cue = party_support_relative_cue_results,
    study3_all_party_match = study3_all_party_match_results,
    cross_study_relative_weight = cross_study_relative_weight,
    cross_study_relative_plot = p_cross_study_relative,
    main_text_figure_manifest = main_text_figure_manifest,
    supplement_figure_manifest = supplement_figure_manifest,
    supplement_section_manifest = supplement_section_manifest
  ),
  file = file.path(
    unified_output_dir,
    "unified_supplement_objects.rds"
  )
)

capture.output(
  sessionInfo(),
  file = file.path(
    unified_output_dir,
    "sessionInfo_unified.txt"
  )
)

cat(
  "\n3実験の本文図再現・補遺分析・支持政党別異質性分析が完了しました。\n",
  "統合出力先: ",
  normalizePath(unified_output_dir),
  "\n",
  sep = ""
)


final_output_root <- unified_config$output_root

final_dirs <- list(
  main_figures = file.path(final_output_root, "main_text", "figures"),
  main_tables = file.path(final_output_root, "main_text", "tables"),
  supplement_root = file.path(final_output_root, "supplement"),
  supplement_cross = file.path(final_output_root, "supplement", "cross_study"),
  diagnostics_root = file.path(final_output_root, "diagnostics"),
  model_objects_root = file.path(final_output_root, "model_objects"),
  logs = file.path(final_output_root, "logs")
)

invisible(
  lapply(
    final_dirs,
    dir.create,
    showWarnings = FALSE,
    recursive = TRUE
  )
)

for (study_id in names(study_specs)) {
  for (subdir in c("figures", "tables_csv", "tables_tex")) {
    dir.create(
      file.path(final_dirs$supplement_root, study_id, subdir),
      showWarnings = FALSE,
      recursive = TRUE
    )
  }
  for (subdir in c("screening", "balance", "randomization")) {
    dir.create(
      file.path(final_dirs$diagnostics_root, study_id, subdir),
      showWarnings = FALSE,
      recursive = TRUE
    )
  }
  dir.create(
    file.path(final_dirs$model_objects_root, study_id),
    showWarnings = FALSE,
    recursive = TRUE
  )
}

for (subdir in c("figures", "tables_csv", "tables_tex")) {
  dir.create(
    file.path(final_dirs$supplement_cross, subdir),
    showWarnings = FALSE,
    recursive = TRUE
  )
}


copy_file_if_exists <- function(source, destination) {
  if (is.na(source) || !nzchar(source) || !file.exists(source)) {
    return(FALSE)
  }
  dir.create(dirname(destination), showWarnings = FALSE, recursive = TRUE)
  isTRUE(file.copy(source, destination, overwrite = TRUE, copy.mode = TRUE))
}

copy_files_by_pattern <- function(source_dir, destination_dir, pattern) {
  if (!dir.exists(source_dir)) {
    return(character())
  }
  files <- list.files(
    source_dir,
    pattern = pattern,
    full.names = TRUE,
    recursive = TRUE,
    ignore.case = TRUE
  )
  if (length(files) == 0) {
    return(character())
  }
  dir.create(destination_dir, showWarnings = FALSE, recursive = TRUE)
  destinations <- file.path(destination_dir, basename(files))
  copied <- vapply(
    seq_along(files),
    function(i) copy_file_if_exists(files[i], destinations[i]),
    logical(1)
  )
  destinations[copied]
}

latex_escape <- function(x) {
  x <- as.character(x)
  x[is.na(x)] <- ""

  escape_one <- function(s) {
    chars <- strsplit(s, "", fixed = TRUE)[[1]]

    if (length(chars) == 0L) {
      return("")
    }

    replacement <- c(
      "\\" = "\\textbackslash{}",
      "&"  = "\\&",
      "%"  = "\\%",
      "$"  = "\\$",
      "#"  = "\\#",
      "_"  = "\\_",
      "{"  = "\\{",
      "}"  = "\\}",
      "~"  = "\\textasciitilde{}",
      "^"  = "\\textasciicircum{}"
    )

    out <- vapply(
      chars,
      function(ch) {
        if (ch %in% names(replacement)) {
          unname(replacement[[ch]])
        } else {
          ch
        }
      },
      character(1)
    )

    paste0(out, collapse = "")
  }

  vapply(x, escape_one, character(1), USE.NAMES = FALSE)
}

format_number <- function(x, digits = 3) {
  out <- ifelse(
    is.na(x),
    "",
    formatC(x, format = "f", digits = digits)
  )
  as.character(out)
}

format_integer <- function(x) {
  ifelse(is.na(x), "", scales::comma(as.integer(round(x))))
}

format_p_value <- function(x) {
  dplyr::case_when(
    is.na(x) ~ "",
    x < 0.001 ~ "< .001",
    TRUE ~ sub("^0", "", formatC(x, format = "f", digits = 3))
  )
}

write_latex_longtable <- function(
    data,
    file,
    caption,
    label,
    notes = NULL,
    landscape = ncol(data) >= 7) {
  
  data <- as.data.frame(data, stringsAsFactors = FALSE)
  if (ncol(data) == 0) {
    data <- data.frame(note = "該当する推定結果はありません。")
  }
  
  display <- data
  display[] <- lapply(display, function(x) latex_escape(as.character(x)))
  headers <- latex_escape(names(display))
  
  numeric_column <- vapply(data, is.numeric, logical(1))
  alignment <- paste0(ifelse(numeric_column, "r", "l"), collapse = "")
  
  lines <- character()
  lines <- c(lines, "% Generated automatically by the replication script.")
  if (landscape) {
    lines <- c(lines, "\\begin{landscape}")
  }
  lines <- c(
    lines,
    "\\begingroup",
    "\\small",
    paste0("\\begin{longtable}{", alignment, "}"),
    paste0("\\caption{", latex_escape(caption), "}\\label{", label, "}\\\\"),
    "\\toprule",
    paste(headers, collapse = " & "),
    "\\\\",
    "\\midrule",
    "\\endfirsthead",
    paste0("\\multicolumn{", ncol(display), "}{l}{\\tablename~\\thetable{}(続き)}\\\\"),
    "\\toprule",
    paste(headers, collapse = " & "),
    "\\\\",
    "\\midrule",
    "\\endhead",
    paste0("\\midrule\\multicolumn{", ncol(display), "}{r}{次頁に続く}\\\\"),
    "\\endfoot",
    "\\bottomrule",
    "\\endlastfoot"
  )
  
  if (nrow(display) > 0) {
    row_lines <- apply(
      display,
      1,
      function(row) paste0(paste(row, collapse = " & "), " \\\\")
    )
    lines <- c(lines, row_lines)
  }
  
  lines <- c(lines, "\\end{longtable}")
  if (!is.null(notes) && nzchar(notes)) {
    lines <- c(
      lines,
      "\\vspace{-0.5em}",
      "\\begin{minipage}{\\linewidth}",
      "\\footnotesize",
      paste0("\\textit{注:}", latex_escape(notes)),
      "\\end{minipage}"
    )
  }
  lines <- c(lines, "\\endgroup")
  if (landscape) {
    lines <- c(lines, "\\end{landscape}")
  }
  
  dir.create(dirname(file), showWarnings = FALSE, recursive = TRUE)
  writeLines(lines, con = file, useBytes = TRUE)
  invisible(file)
}

write_csv_and_tex <- function(
    data,
    csv_file,
    tex_file,
    caption,
    label,
    notes = NULL,
    landscape = ncol(data) >= 7) {
  dir.create(dirname(csv_file), showWarnings = FALSE, recursive = TRUE)
  readr::write_csv(data, csv_file, na = "")
  write_latex_longtable(
    data = data,
    file = tex_file,
    caption = caption,
    label = label,
    notes = notes,
    landscape = landscape
  )
  invisible(list(csv = csv_file, tex = tex_file))
}

attribute_label_map <- c(
  policy_position = "政策位置",
  government_status = "与野党地位",
  seats = "議席数",
  party_name = "政党名",
  gdp_growth = "GDP成長率",
  nikkei = "日経平均株価",
  cpi = "消費者物価指数(CPI)",
  unemployment = "失業率"
)

cue_family_label <- c(
  party = "政党の手がかり",
  economic = "経済の手がかり"
)


screening_specs <- list(
  study1 = list(
    initial_consent_var = "Q1.1",
    final_consent_var = study1_env$final_consent_var,
    attention_var = NA_character_,
    attention_answer = NA_character_,
    manipulation_available = FALSE,
    intro_map = NULL
  ),
  study2 = list(
    initial_consent_var = "Q1.1",
    final_consent_var = study2_env$final_consent_var,
    attention_var = study2_env$attention_check_var,
    attention_answer = as.character(study2_env$attention_check_correct),
    manipulation_available = TRUE,
    intro_map = NULL
  ),
  study3 = list(
    initial_consent_var = "Q1.1",
    final_consent_var = study3_env$final_consent_var,
    attention_var = study3_env$attention_check_var,
    attention_answer = as.character(study3_env$attention_check_correct),
    manipulation_available = TRUE,
    intro_map = NULL
  )
)

response_present <- function(x) {
  x <- as.character(x)
  !is.na(x) & stringr::str_squish(x) != ""
}

response_is_code <- function(x, code) {
  x <- stringr::str_squish(as.character(x))
  code <- as.character(code)
  out <- x == code | stringr::str_detect(x, paste0("\\(", code, "\\)$"))
  out[is.na(out)] <- FALSE
  out
}

get_mapped_response <- function(data, assigned_n, map, value_column) {
  result <- rep(NA_character_, nrow(data))
  for (n_value in 2:5) {
    row <- map[map$party_n == n_value, , drop = FALSE]
    if (nrow(row) == 0) next
    variable <- as.character(row[[value_column]][1])
    if (!variable %in% names(data)) next
    take <- !is.na(assigned_n) & assigned_n == n_value
    result[take] <- as.character(data[[variable]][take])
  }
  result
}

infer_assigned_condition <- function(data, choice_map, manipulation_map = NULL, intro_map = NULL) {
  candidate <- matrix(FALSE, nrow = nrow(data), ncol = 4)
  colnames(candidate) <- as.character(2:5)
  
  for (n_value in 2:5) {
    variables <- choice_map$choice_var[choice_map$party_n == n_value]
    if (!is.null(manipulation_map) && nrow(manipulation_map) > 0) {
      variables <- c(
        variables,
        manipulation_map$manipulation_var[manipulation_map$party_n == n_value]
      )
    }
    if (!is.null(intro_map) && as.character(n_value) %in% names(intro_map)) {
      variables <- c(variables, unname(intro_map[as.character(n_value)]))
    }
    variables <- intersect(unique(variables), names(data))
    if (length(variables) > 0) {
      candidate[, as.character(n_value)] <- apply(
        data[, variables, drop = FALSE],
        1,
        function(row) any(response_present(row))
      )
    }
  }
  
  n_candidates <- rowSums(candidate)
  assigned <- rep(NA_integer_, nrow(data))
  single <- n_candidates == 1
  assigned[single] <- as.integer(colnames(candidate)[max.col(candidate[single, , drop = FALSE])])
  
  if (any(n_candidates > 1)) {
    warning("Check")
  }
  assigned
}

build_screening_outputs <- function(study_spec) {
  study_id <- study_spec$study_id
  env <- study_spec$env
  spec <- screening_specs[[study_id]]
  raw <- env$df_header_removed %>%
    dplyr::mutate(ID = as.character(ID)) %>%
    dplyr::distinct(ID, .keep_all = TRUE)
  
  manipulation_map <- if (
    spec$manipulation_available &&
    exists("manipulation_map", envir = env, inherits = FALSE)
  ) {
    get("manipulation_map", envir = env, inherits = FALSE)
  } else {
    NULL
  }
  
  assigned_n <- infer_assigned_condition(
    data = raw,
    choice_map = env$choice_map,
    manipulation_map = manipulation_map,
    intro_map = spec$intro_map
  )
  
  if (exists("id_task_check", envir = env, inherits = FALSE)) {
    analysis_assignment <- get("id_task_check", envir = env, inherits = FALSE) %>%
      dplyr::mutate(
        ID = as.character(ID),
        party_n = as.integer(as.character(party_n))
      ) %>%
      dplyr::group_by(ID) %>%
      dplyr::summarise(
        n_condition_candidates = dplyr::n_distinct(party_n),
        assigned_from_analysis = dplyr::if_else(
          n_condition_candidates == 1L,
          dplyr::first(party_n),
          NA_integer_
        ),
        .groups = "drop"
      )
    
    analysis_match <- match(raw$ID, analysis_assignment$ID)
    use_analysis_assignment <- !is.na(analysis_match) &
      !is.na(analysis_assignment$assigned_from_analysis[analysis_match])
    assigned_n[use_analysis_assignment] <-
      analysis_assignment$assigned_from_analysis[analysis_match[use_analysis_assignment]]
  }
  
  if (exists("valid_ids", envir = env, inherits = FALSE)) {
    final_assignment <- get("valid_ids", envir = env, inherits = FALSE) %>%
      dplyr::mutate(
        ID = as.character(ID),
        party_n = as.integer(as.character(party_n))
      ) %>%
      dplyr::distinct(ID, party_n) %>%
      dplyr::group_by(ID) %>%
      dplyr::summarise(
        n_condition_candidates = dplyr::n_distinct(party_n),
        assigned_from_final = dplyr::if_else(
          n_condition_candidates == 1L,
          dplyr::first(party_n),
          NA_integer_
        ),
        .groups = "drop"
      )
    
    final_match <- match(raw$ID, final_assignment$ID)
    use_final_assignment <- !is.na(final_match) &
      !is.na(final_assignment$assigned_from_final[final_match])
    assigned_n[use_final_assignment] <-
      final_assignment$assigned_from_final[final_match[use_final_assignment]]
  }
  
  initial_response <- if (spec$initial_consent_var %in% names(raw)) {
    raw[[spec$initial_consent_var]]
  } else {
    rep(NA_character_, nrow(raw))
  }
  final_response <- if (spec$final_consent_var %in% names(raw)) {
    raw[[spec$final_consent_var]]
  } else {
    rep(NA_character_, nrow(raw))
  }
  
  task_responses <- lapply(
    1:5,
    function(task_value) {
      task_map <- env$choice_map[env$choice_map$task == task_value, , drop = FALSE]
      get_mapped_response(raw, assigned_n, task_map, "choice_var")
    }
  )
  
  task_pass <- lapply(
    task_responses,
    function(response) {
      parsed <- suppressWarnings(readr::parse_number(as.character(response)))
      !is.na(assigned_n) & !is.na(parsed) & parsed >= 1 & parsed <= assigned_n
    }
  )
  
  if (!is.null(manipulation_map)) {
    manipulation_response <- get_mapped_response(
      raw,
      assigned_n,
      manipulation_map,
      "manipulation_var"
    )
    manipulation_answer <- rep(NA_character_, nrow(raw))
    for (n_value in 2:5) {
      answer <- manipulation_map$correct_answer[manipulation_map$party_n == n_value]
      manipulation_answer[!is.na(assigned_n) & assigned_n == n_value] <- answer[1]
    }
    manipulation_pass <- !is.na(assigned_n) & response_is_code(
      manipulation_response,
      manipulation_answer
    )
  } else {
    manipulation_response <- rep(NA_character_, nrow(raw))
    manipulation_pass <- rep(TRUE, nrow(raw))
  }
  
  if (!is.na(spec$attention_var) && spec$attention_var %in% names(raw)) {
    attention_response <- raw[[spec$attention_var]]
    attention_pass <- response_is_code(attention_response, spec$attention_answer)
  } else {
    attention_response <- rep(NA_character_, nrow(raw))
    attention_pass <- rep(TRUE, nrow(raw))
  }
  
  initial_pass <- response_is_code(initial_response, 1) |
    stringr::str_detect(
      stringr::str_squish(as.character(initial_response)),
      "趣旨に同意して.*協力する"
    )
  final_pass <- response_is_code(final_response, 1) |
    stringr::str_detect(
      stringr::str_squish(as.character(final_response)),
      "同意し.*回答結果を送信する"
    )
  
  final_ids <- as.character(env$valid_ids$ID)
  
  audit <- tibble::tibble(
    ID = raw$ID,
    assigned_condition = assigned_n,
    initial_consent_response = as.character(initial_response),
    initial_consent_pass = initial_pass,
    reached_conjoint_block = !is.na(assigned_n),
    task1_response = as.character(task_responses[[1]]),
    task1_complete = task_pass[[1]],
    task2_response = as.character(task_responses[[2]]),
    task2_complete = task_pass[[2]],
    task3_response = as.character(task_responses[[3]]),
    task3_complete = task_pass[[3]],
    task4_response = as.character(task_responses[[4]]),
    task4_complete = task_pass[[4]],
    task5_response = as.character(task_responses[[5]]),
    task5_complete = task_pass[[5]],
    all_five_tasks_complete = Reduce(`&`, task_pass),
    manipulation_response = as.character(manipulation_response),
    manipulation_check_pass = manipulation_pass,
    attention_response = as.character(attention_response),
    attention_check_pass = attention_pass,
    final_consent_response = as.character(final_response),
    final_consent_pass = final_pass,
    included_in_final_analysis = ID %in% final_ids
  )
  
  cumulative <- rep(TRUE, nrow(audit))
  stage_records <- list()
  add_stage <- function(stage, question_variable, criterion) {
    cumulative <<- cumulative & criterion
    stage_records[[length(stage_records) + 1L]] <<- tibble::tibble(
      stage_order = length(stage_records) + 1L,
      stage = stage,
      question_variable = question_variable,
      n_remaining = sum(cumulative, na.rm = TRUE)
    )
  }
  
  add_stage("Qualtricsの質問文・ImportId行を除外", "ResponseId", rep(TRUE, nrow(audit)))
  add_stage("初回同意", spec$initial_consent_var, audit$initial_consent_pass)
  add_stage("割付されたコンジョイント・ブロックに到達", "Q3.1/Q4.1/Q5.1/Q6.1 または最初の選択課題", audit$reached_conjoint_block)
  for (task_value in 1:5) {
    add_stage(
      paste0("選択課題", task_value, "を有効回答"),
      paste0("条件別 choice task ", task_value),
      audit[[paste0("task", task_value, "_complete")]]
    )
  }
  if (spec$manipulation_available) {
    add_stage(
      "提示された選択肢数を正答",
      "条件別に自動検出した選択肢数確認質問",
      audit$manipulation_check_pass
    )
  }
  if (!is.na(spec$attention_var)) {
    add_stage(
      "イデオロギー行列の指示項目に正答",
      spec$attention_var,
      audit$attention_check_pass
    )
  }
  add_stage("最終送信同意", spec$final_consent_var, audit$final_consent_pass)
  add_stage("最終分析標本", "全基準の積集合", audit$included_in_final_analysis)
  
  flow <- dplyr::bind_rows(stage_records) %>%
    dplyr::mutate(
      n_excluded_at_stage = dplyr::lag(n_remaining, default = dplyr::first(n_remaining)) - n_remaining,
      retention_from_previous_pct = dplyr::if_else(
        dplyr::lag(n_remaining, default = dplyr::first(n_remaining)) > 0,
        100 * n_remaining / dplyr::lag(n_remaining, default = dplyr::first(n_remaining)),
        NA_real_
      ),
      retention_from_initial_pct = 100 * n_remaining / dplyr::first(n_remaining)
    )
  
  condition_flow <- purrr::map_dfr(
    2:5,
    function(n_value) {
      subset_audit <- audit %>% dplyr::filter(assigned_condition == n_value)
      if (nrow(subset_audit) == 0) {
        return(tibble::tibble())
      }
      criteria <- list(
        "割付条件を識別" = rep(TRUE, nrow(subset_audit)),
        "選択課題1" = subset_audit$task1_complete,
        "選択課題2" = subset_audit$task2_complete,
        "選択課題3" = subset_audit$task3_complete,
        "選択課題4" = subset_audit$task4_complete,
        "選択課題5" = subset_audit$task5_complete
      )
      if (spec$manipulation_available) {
        criteria[["選択肢数確認"]] <- subset_audit$manipulation_check_pass
      }
      if (!is.na(spec$attention_var)) {
        criteria[["指示項目"]] <- subset_audit$attention_check_pass
      }
      criteria[["最終送信同意"]] <- subset_audit$final_consent_pass
      criteria[["最終分析標本"]] <- subset_audit$included_in_final_analysis
      
      keep <- rep(TRUE, nrow(subset_audit))
      records <- purrr::imap_dfr(
        criteria,
        function(criterion, stage_name) {
          keep <<- keep & criterion
          tibble::tibble(
            assigned_condition = n_value,
            stage_order = which(names(criteria) == stage_name),
            stage = stage_name,
            n_remaining = sum(keep, na.rm = TRUE)
          )
        }
      )
      records %>%
        dplyr::mutate(
          n_excluded_at_stage = dplyr::lag(n_remaining, default = dplyr::first(n_remaining)) - n_remaining,
          retention_from_condition_start_pct = 100 * n_remaining / dplyr::first(n_remaining)
        )
    }
  )
  
  final_audit <- audit %>% dplyr::filter(included_in_final_analysis)
  required_final <- final_audit$initial_consent_pass &
    final_audit$all_five_tasks_complete &
    final_audit$manipulation_check_pass &
    final_audit$attention_check_pass &
    final_audit$final_consent_pass
  if (!all(required_final)) {
    stop("Check")
  }
  if (nrow(final_audit) != dplyr::n_distinct(env$valid_ids$ID)) {
    stop("Check")
  }
  
  list(audit = audit, flow = flow, condition_flow = condition_flow)
}


make_amce_table <- function(env, adjusted = TRUE) {
  source <- if (adjusted) env$amce_plot_cov else env$amce_plot_nocov
  n_table <- env$n_by_party %>%
    dplyr::transmute(
      party_n_numeric = as.integer(as.character(party_n)),
      respondents = n
    )
  
  source %>%
    dplyr::mutate(
      party_n_numeric = suppressWarnings(readr::parse_number(as.character(party_n)))
    ) %>%
    dplyr::left_join(n_table, by = "party_n_numeric") %>%
    dplyr::transmute(
      `条件` = as.character(party_n),
      `属性` = as.character(attribute),
      `水準(基準水準との差)` = as.character(label),
      `推定値(pp)` = format_number(100 * estimate, 2),
      `標準誤差(pp)` = format_number(100 * std.error, 2),
      `95% CI下限(pp)` = format_number(100 * conf.low, 2),
      `95% CI上限(pp)` = format_number(100 * conf.high, 2),
      `p値` = format_p_value(p.value),
      `回答者数` = format_integer(respondents)
    )
}

make_interaction_table <- function(env) {
  source <- env$interaction_plot_df
  condition_column <- intersect(c("party_n_label", "party_n"), names(source))[1]
  if (is.na(condition_column)) {
    source$condition_label <- ""
  } else {
    source$condition_label <- as.character(source[[condition_column]])
  }
  source %>%
    dplyr::transmute(
      `比較条件` = condition_label,
      `属性` = as.character(attribute),
      `水準` = as.character(label),
      `2選択肢条件との差(pp)` = format_number(100 * estimate, 2),
      `標準誤差(pp)` = format_number(100 * std.error, 2),
      `95% CI下限(pp)` = format_number(100 * conf.low, 2),
      `95% CI上限(pp)` = format_number(100 * conf.high, 2),
      `p値` = format_p_value(p.value)
    )
}

clustered_mean_summary <- function(y, cluster) {
  y <- as.numeric(y)
  cluster <- as.character(cluster)
  keep <- is.finite(y) & !is.na(cluster)
  y <- y[keep]
  cluster <- cluster[keep]
  n <- length(y)
  g <- dplyr::n_distinct(cluster)
  if (n == 0) {
    return(c(estimate = NA_real_, se = NA_real_, low = NA_real_, high = NA_real_, n = 0, g = 0))
  }
  estimate <- mean(y)
  if (g <= 1) {
    se <- NA_real_
  } else {
    cluster_score <- tapply(y - estimate, cluster, sum)
    variance <- (g / (g - 1)) * sum(cluster_score^2) / (n^2)
    se <- sqrt(variance)
  }
  c(
    estimate = estimate,
    se = se,
    low = estimate - 1.96 * se,
    high = estimate + 1.96 * se,
    n = n,
    g = g
  )
}

make_mm_table <- function(env) {
  attributes <- names(env$relative_cue_map)
  long <- env$conjoint_all_m %>%
    dplyr::select(ID, party_n, selected, dplyr::all_of(attributes)) %>%
    tidyr::pivot_longer(
      cols = dplyr::all_of(attributes),
      names_to = "attribute",
      values_to = "level"
    ) %>%
    dplyr::filter(!is.na(level), as.character(level) != "") %>%
    dplyr::mutate(level = as.character(level))
  
  summary <- long %>%
    dplyr::group_by(party_n, attribute, level) %>%
    dplyr::group_modify(
      ~ {
        values <- clustered_mean_summary(.x$selected, .x$ID)
        tibble::tibble(
          marginal_mean = values["estimate"],
          cluster_se = values["se"],
          conf_low = values["low"],
          conf_high = values["high"],
          n_profiles = values["n"],
          n_respondents = values["g"]
        )
      }
    ) %>%
    dplyr::ungroup() %>%
    dplyr::mutate(
      cue_family = unname(env$relative_cue_map[attribute]),
      attribute_label = dplyr::coalesce(unname(attribute_label_map[attribute]), attribute),
      cue_label = dplyr::coalesce(unname(cue_family_label[cue_family]), cue_family)
    )
  
  summary %>%
    dplyr::transmute(
      `条件` = paste0(party_n, ifelse("party_name" %in% attributes, "選択肢", "政党")),
      `手がかり群` = cue_label,
      `属性` = attribute_label,
      `水準` = level,
      `限界平均(%)` = format_number(100 * marginal_mean, 2),
      `クラスタSE(pp)` = format_number(100 * cluster_se, 2),
      `95% CI下限(%)` = format_number(100 * conf_low, 2),
      `95% CI上限(%)` = format_number(100 * conf_high, 2),
      `プロファイル数` = format_integer(n_profiles),
      `回答者数` = format_integer(n_respondents)
    )
}

make_attribute_importance_table <- function(env) {
  source <- env$relative_cue_observed$attribute_importance
  adjusted_col <- intersect(
    c("importance_pairwise_adjusted", "choice_set_adjusted_importance_pairwise"),
    names(source)
  )[1]
  adjusted <- if (!is.na(adjusted_col)) source[[adjusted_col]] else source$party_n * source$importance_pairwise
  
  source %>%
    dplyr::mutate(
      adjusted_value = adjusted,
      attribute_label = dplyr::coalesce(unname(attribute_label_map[attribute]), attribute),
      cue_label = dplyr::coalesce(unname(cue_family_label[cue_family]), cue_family)
    ) %>%
    dplyr::transmute(
      `条件` = party_n,
      `手がかり群` = cue_label,
      `属性` = attribute_label,
      `水準数` = n_levels,
      `未調整重要度(pp)` = format_number(100 * importance_pairwise, 2),
      `選択肢数調整済み重要度(%)` = format_number(100 * adjusted_value, 2)
    )
}

make_cue_importance_table <- function(env) {
  source <- env$relative_cue_condition_intervals
  labels <- c(
    party_importance_pairwise = "政党手がかり:未調整重要度",
    economic_importance_pairwise = "経済手がかり:未調整重要度",
    party_importance_pairwise_adjusted = "政党手がかり:選択肢数調整済み重要度",
    economic_importance_pairwise_adjusted = "経済手がかり:選択肢数調整済み重要度",
    relative_party_weight_pairwise = "政党手がかりの相対比重"
  )
  source <- source %>% dplyr::filter(statistic %in% names(labels))
  source %>%
    dplyr::mutate(
      `指標` = unname(labels[statistic]),
      `単位` = dplyr::case_when(
        statistic %in% c("party_importance_pairwise", "economic_importance_pairwise") ~ "pp",
        TRUE ~ "%"
      ),
      multiplier = 100
    ) %>%
    dplyr::transmute(
      `条件` = party_n,
      `指標` = `指標`,
      `単位` = `単位`,
      `推定値` = format_number(multiplier * estimate, 2),
      `95% CI下限` = format_number(multiplier * conf_low, 2),
      `95% CI上限` = format_number(multiplier * conf_high, 2)
    )
}

make_clogit_table <- function(env) {
  env$clogit_plot_df %>%
    dplyr::transmute(
      `条件` = as.character(party_n),
      `属性` = as.character(attribute),
      `水準(基準水準との差)` = as.character(label),
      `log係数` = format_number(estimate, 3),
      `標準誤差` = format_number(std.error, 3),
      `オッズ比` = format_number(odds_ratio, 3),
      `95% CI下限(OR)` = format_number(odds_ratio_low, 3),
      `95% CI上限(OR)` = format_number(odds_ratio_high, 3),
      `p値` = format_p_value(p.value)
    )
}

make_linear_trend_table <- function(env) {
  if (!exists("linear_trend_plot_df", envir = env, inherits = FALSE)) {
    return(tibble::tibble())
  }
  env$linear_trend_plot_df %>%
    dplyr::transmute(
      `属性` = as.character(attribute),
      `水準` = as.character(label),
      `選択肢が1つ増えるときの変化(pp)` = format_number(100 * estimate, 2),
      `標準誤差(pp)` = format_number(100 * std.error, 2),
      `95% CI下限(pp)` = format_number(100 * conf.low, 2),
      `95% CI上限(pp)` = format_number(100 * conf.high, 2),
      `p値` = format_p_value(p.value)
    )
}

make_party_match_table <- function(env) {
  if (!exists("party_match_coef_df", envir = env, inherits = FALSE)) {
    return(tibble::tibble())
  }
  overall <- env$party_match_coef_df
  subgroup <- if (exists("party_match_subgroup_coef_df", envir = env, inherits = FALSE)) {
    env$party_match_subgroup_coef_df
  } else {
    tibble::tibble()
  }
  combined <- dplyr::bind_rows(overall, subgroup)
  if (!"n_ids" %in% names(combined)) combined$n_ids <- NA_real_
  if (!"support_group_label" %in% names(combined)) combined$support_group_label <- "全体"
  combined %>%
    dplyr::mutate(
      support_group_label = dplyr::coalesce(as.character(support_group_label), "全体"),
      n_ids = suppressWarnings(as.numeric(n_ids))
    ) %>%
    dplyr::transmute(
      `対象` = support_group_label,
      `選択肢数` = party_n,
      `一致効果(pp)` = format_number(100 * estimate, 2),
      `標準誤差(pp)` = format_number(100 * std.error, 2),
      `95% CI下限(pp)` = format_number(100 * conf.low, 2),
      `95% CI上限(pp)` = format_number(100 * conf.high, 2),
      `p値` = format_p_value(p.value),
      `回答者数` = format_integer(n_ids)
    )
}


screening_question_wording <- function(study_id, stage, party_n = NA_integer_) {
  stage <- as.character(stage)
  party_n <- suppressWarnings(as.integer(party_n))
  if (length(party_n) == 1L && length(stage) > 1L) {
    party_n <- rep(party_n, length(stage))
  }
  if (length(party_n) != length(stage)) {
    party_n <- rep(NA_integer_, length(stage))
  }

  purrr::map2_chr(stage, party_n, function(stage_value, n_value) {
    k_text <- ifelse(is.na(n_value), "k", as.character(n_value))

    if (stringr::str_detect(stage_value, "Qualtrics")) {
      return("(Qualtricsのメタデータ行。調査質問ではない)")
    }

    if (stage_value == "初回同意") {
      return("「本調査の趣旨に同意して、本調査に協力する」")
    }

    if (stringr::str_detect(stage_value, "コンジョイント・ブロックに到達|割付条件を識別")) {
      if (study_id == "study3") {
        return(paste0(
          "「今から、日本の政党めぐる", k_text,
          "つの選択肢を順に提示していきます。…", k_text,
          "つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」"
        ))
      }
      return(paste0(
        "「今から、日本の政党めぐる", k_text,
        "つの選択肢を順に提示していきます。…", k_text,
        "つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」"
      ))
    }

    if (stringr::str_detect(stage_value, "^選択課題[1-5]")) {
      if (study_id == "study3") {
        return(paste0(
          "「以下に、日本の政党をめぐる", k_text,
          "つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」"
        ))
      }
      if (study_id == "study2") {
        return(paste0(
          "「以下に、日本の政党をめぐる", k_text,
          "つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」"
        ))
      }
      return(paste0(
        "「以下に、日本の政党をめぐる", k_text,
        "つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」"
      ))
    }

    if (stringr::str_detect(stage_value, "提示された選択肢数を正答|選択肢数確認")) {
      if (study_id == "study2") {
        return("「あなたに提示された政党の選択肢の数は、いくつでしたか。」")
      }
      if (study_id == "study3") {
        return("「あなたに提示された選択肢の数は、いくつでしたか。」")
      }
      return("(Study 1では該当質問なし)")
    }

    if (stringr::str_detect(stage_value, "イデオロギー行列の指示項目|指示項目")) {
      if (study_id %in% c("study2", "study3")) {
        return("「!この項目は必ず『3』を選んでください!」")
      }
      return("(Study 1では該当質問なし)")
    }

    if (stage_value == "最終送信同意") {
      return("「本調査の主旨に同意し、回答結果を送信する。」")
    }

    if (stage_value == "最終分析標本") {
      return("(質問文なし。上記の全基準の積集合)")
    }

    "—"
  })
}


screening_results <- list()
study_table_paths <- list()

for (study_id in names(study_specs)) {
  spec <- study_specs[[study_id]]
  env <- spec$env
  study_label <- spec$study_label
  csv_dir <- file.path(final_dirs$supplement_root, study_id, "tables_csv")
  tex_dir <- file.path(final_dirs$supplement_root, study_id, "tables_tex")
  diag_screen_dir <- file.path(final_dirs$diagnostics_root, study_id, "screening")
  diag_balance_dir <- file.path(final_dirs$diagnostics_root, study_id, "balance")
  diag_random_dir <- file.path(final_dirs$diagnostics_root, study_id, "randomization")
  
  screening <- build_screening_outputs(spec)
  screening_results[[study_id]] <- screening
  
  readr::write_csv(screening$audit, file.path(diag_screen_dir, "respondent_screening_audit.csv"), na = "")
  readr::write_csv(screening$flow, file.path(diag_screen_dir, "sequential_sample_flow.csv"), na = "")
  readr::write_csv(screening$condition_flow, file.path(diag_screen_dir, "sequential_sample_flow_by_condition.csv"), na = "")
  
  attrition_table <- screening$flow %>%
    dplyr::transmute(
      `順序` = stage_order,
      `段階` = stage,
      `質問・変数` = question_variable,
      `質問文(調査票・要約)` = screening_question_wording(study_id, stage),
      `残存N` = format_integer(n_remaining),
      `当該段階での除外N` = format_integer(n_excluded_at_stage),
      `前段階からの残存率(%)` = format_number(retention_from_previous_pct, 1),
      `初期標本からの残存率(%)` = format_number(retention_from_initial_pct, 1)
    )
  
  write_csv_and_tex(
    attrition_table,
    file.path(csv_dir, "table_sample_attrition.csv"),
    file.path(tex_dir, "table_sample_attrition.tex"),
    paste0(study_label, ":質問段階ごとの逐次的な標本減少"),
    paste0("tab:", study_id, "-attrition"),
    notes = paste0(
      "各行は直前までの基準を満たした回答者に次の基準を順に適用した残存数を示す。",
      ifelse(
        study_id == "study1",
        "Study 1では選択肢数確認質問および指示項目は調査票に設けられていない。",
        "最終分析は、選択肢数確認とQ25.1_11の指示項目の双方に正答した回答者に限定した。"
      )
    )
  )
  
  condition_attrition_table <- screening$condition_flow %>%
    dplyr::transmute(
      `条件` = assigned_condition,
      `順序` = stage_order,
      `段階` = stage,
      `質問文(調査票・要約)` = screening_question_wording(study_id, stage, assigned_condition),
      `残存N` = format_integer(n_remaining),
      `当該段階での除外N` = format_integer(n_excluded_at_stage),
      `条件開始時からの残存率(%)` = format_number(retention_from_condition_start_pct, 1)
    )
  write_csv_and_tex(
    condition_attrition_table,
    file.path(csv_dir, "table_sample_attrition_by_condition.csv"),
    file.path(tex_dir, "table_sample_attrition_by_condition.tex"),
    paste0(study_label, ":条件別の逐次的な標本減少"),
    paste0("tab:", study_id, "-attrition-condition"),
    notes = "条件を回答履歴から識別できた回答者について、各条件内で基準を累積的に適用した。"
  )
  
  manipulation_table <- screening$audit %>%
    dplyr::filter(!is.na(assigned_condition)) %>%
    dplyr::count(
      assigned_condition,
      manipulation_response,
      manipulation_check_pass,
      name = "n"
    ) %>%
    dplyr::transmute(
      `条件` = assigned_condition,
      `質問文(調査票)` = screening_question_wording(study_id, "選択肢数確認", assigned_condition),
      `回答` = dplyr::coalesce(manipulation_response, "未実施・欠損"),
      `正答` = ifelse(manipulation_check_pass, "正答", "不正答・欠損"),
      `N` = format_integer(n)
    )
  if (study_id == "study1") {
    manipulation_table <- tibble::tibble(
      `条件` = "全条件",
      `質問文(調査票)` = "(Study 1では該当質問なし)",
      `回答` = "調査票に選択肢数確認質問なし",
      `正答` = "適用外",
      `N` = ""
    )
  }
  write_csv_and_tex(
    manipulation_table,
    file.path(csv_dir, "table_manipulation_check.csv"),
    file.path(tex_dir, "table_manipulation_check.tex"),
    paste0(study_label, ":選択肢数の操作確認"),
    paste0("tab:", study_id, "-manipulation-check"),
    notes = "Study 2・3では、割り当てられた選択肢数と同じ回答を正答とした。"
  )
  
  attention_table <- screening$audit %>%
    dplyr::count(attention_response, attention_check_pass, name = "n") %>%
    dplyr::transmute(
      `質問文(調査票)` = screening_question_wording(study_id, "指示項目"),
      `回答` = dplyr::coalesce(attention_response, "未実施・欠損"),
      `判定` = ifelse(attention_check_pass, "正答", "不正答・欠損"),
      `N` = format_integer(n)
    )
  if (study_id == "study1") {
    attention_table <- tibble::tibble(
      `質問文(調査票)` = "(Study 1では該当質問なし)",
      `回答` = "調査票に指示項目なし",
      `判定` = "適用外",
      `N` = ""
    )
  }
  write_csv_and_tex(
    attention_table,
    file.path(csv_dir, "table_attention_check.csv"),
    file.path(tex_dir, "table_attention_check.tex"),
    paste0(study_label, ":イデオロギー行列の指示項目"),
    paste0("tab:", study_id, "-attention-check"),
    notes = "Study 2・3では、調査画面上の指示項目で「3」を選択した回答者を正答とした。Qualtricsの保存コードが表示値と異なる場合は、本分析で自動検出された保存コードを用いた。"
  )
  
  amce_cov <- make_amce_table(env, adjusted = TRUE)
  amce_nocov <- make_amce_table(env, adjusted = FALSE)
  interaction <- make_interaction_table(env)
  mm_table <- make_mm_table(env)
  attr_importance <- make_attribute_importance_table(env)
  cue_importance <- make_cue_importance_table(env)
  clogit_table <- make_clogit_table(env)
  linear_trend_table <- make_linear_trend_table(env)
  party_match_table <- make_party_match_table(env)
  
  write_csv_and_tex(
    amce_cov,
    file.path(csv_dir, "table_amce_covariate_adjusted.csv"),
    file.path(tex_dir, "table_amce_covariate_adjusted.tex"),
    paste0(study_label, ":共変量調整済みAMCE"),
    paste0("tab:", study_id, "-amce-adjusted"),
    notes = "推定値の単位はパーセントポイント。標準誤差は回答者単位でクラスタ化した。"
  )
  write_csv_and_tex(
    amce_nocov,
    file.path(csv_dir, "table_amce_unadjusted.csv"),
    file.path(tex_dir, "table_amce_unadjusted.tex"),
    paste0(study_label, ":共変量を含めないAMCE"),
    paste0("tab:", study_id, "-amce-unadjusted"),
    notes = "推定値の単位はパーセントポイント。標準誤差は回答者単位でクラスタ化した。"
  )
  write_csv_and_tex(
    interaction,
    file.path(csv_dir, "table_amce_interaction.csv"),
    file.path(tex_dir, "table_amce_interaction.tex"),
    paste0(study_label, ":2選択肢条件との差を表すAMCE交互作用"),
    paste0("tab:", study_id, "-amce-interaction"),
    notes = "正の値は、当該条件におけるAMCEが2選択肢条件より大きいことを示す。"
  )
  write_csv_and_tex(
    mm_table,
    file.path(csv_dir, "table_marginal_means.csv"),
    file.path(tex_dir, "table_marginal_means.tex"),
    paste0(study_label, ":属性水準別の限界平均(MM)"),
    paste0("tab:", study_id, "-marginal-means"),
    notes = "限界平均は当該水準をもつプロファイルの平均選択確率。SEと信頼区間は回答者クラスタに対応した切片のみの線形確率モデルと同値の計算による。"
  )
  write_csv_and_tex(
    attr_importance,
    file.path(csv_dir, "table_attribute_importance.csv"),
    file.path(tex_dir, "table_attribute_importance.tex"),
    paste0(study_label, ":属性別の未調整・選択肢数調整済み重要度"),
    paste0("tab:", study_id, "-attribute-importance"),
    notes = "未調整重要度は限界平均の全水準ペアの絶対差の平均。調整済み重要度は未調整重要度を1/選択肢数で除した。"
  )
  write_csv_and_tex(
    cue_importance,
    file.path(csv_dir, "table_cue_importance.csv"),
    file.path(tex_dir, "table_cue_importance.tex"),
    paste0(study_label, ":政党・経済手がかりの重要度と相対比重"),
    paste0("tab:", study_id, "-cue-importance"),
    notes = "95%信頼区間は条件内で回答者を復元抽出するクラスタ・ブートストラップによる。"
  )
  write_csv_and_tex(
    clogit_table,
    file.path(csv_dir, "table_conditional_logit.csv"),
    file.path(tex_dir, "table_conditional_logit.tex"),
    paste0(study_label, ":条件付きロジット推定"),
    paste0("tab:", study_id, "-conditional-logit"),
    notes = "各選択課題をstratumとするMcFadden型条件付きロジット。標準誤差は回答者単位でクラスタ化した。"
  )
  
  if (nrow(linear_trend_table) > 0) {
    write_csv_and_tex(
      linear_trend_table,
      file.path(csv_dir, "table_amce_linear_trend.csv"),
      file.path(tex_dir, "table_amce_linear_trend.tex"),
      paste0(study_label, ":選択肢数に対するAMCEの線形トレンド"),
      paste0("tab:", study_id, "-amce-linear-trend"),
      notes = "係数は選択肢数が1つ増えたときのAMCEの変化をパーセントポイントで示す。"
    )
  }
  
  if (nrow(party_match_table) > 0) {
    write_csv_and_tex(
      party_match_table,
      file.path(csv_dir, "table_party_match.csv"),
      file.path(tex_dir, "table_party_match.tex"),
      paste0(study_label, ":支持政党と提示政党名の一致効果"),
      paste0("tab:", study_id, "-party-match"),
      notes = "一致効果は、回答者の支持政党と提示された政党名が一致することによる選択確率差。"
    )
  }
  
  balance <- assignment_balance_results[[study_id]]
  balance_summary <- balance$summary %>%
    dplyr::mutate(dplyr::across(where(is.numeric), ~ format_number(.x, 3)))
  balance_pairwise <- balance$pairwise_smd %>%
    dplyr::mutate(dplyr::across(where(is.numeric), ~ format_number(.x, 3)))
  
  write_csv_and_tex(
    balance_summary,
    file.path(csv_dir, "table_assignment_balance_summary.csv"),
    file.path(tex_dir, "table_assignment_balance_summary.tex"),
    paste0(study_label, ":条件別の回答者属性"),
    paste0("tab:", study_id, "-balance-summary"),
    notes = "Love plotおよび45度線診断に対応する条件別集計。"
  )
  write_csv_and_tex(
    balance_pairwise,
    file.path(csv_dir, "table_assignment_balance_pairwise_smd.csv"),
    file.path(tex_dir, "table_assignment_balance_pairwise_smd.tex"),
    paste0(study_label, ":全条件ペアの標準化平均差"),
    paste0("tab:", study_id, "-balance-smd"),
    notes = "絶対SMDが0.10未満であれば、通常は実質的に小さい不均衡と解釈される。"
  )
  readr::write_csv(balance$summary, file.path(diag_balance_dir, "assignment_balance_summary.csv"), na = "")
  readr::write_csv(balance$pairwise_smd, file.path(diag_balance_dir, "assignment_balance_pairwise_smd.csv"), na = "")
  readr::write_csv(balance$diagonal_data, file.path(diag_balance_dir, "assignment_balance_diagonal_data.csv"), na = "")
  
  randomization <- profile_randomization_results[[study_id]]
  random_tests <- randomization$uniformity_tests %>%
    dplyr::mutate(dplyr::across(where(is.numeric), ~ format_number(.x, 4)))
  random_frequency <- randomization$frequency %>%
    dplyr::mutate(dplyr::across(where(is.numeric), ~ format_number(.x, 4)))
  write_csv_and_tex(
    random_tests,
    file.path(csv_dir, "table_profile_randomization_tests.csv"),
    file.path(tex_dir, "table_profile_randomization_tests.tex"),
    paste0(study_label, ":属性水準提示の一様性検定"),
    paste0("tab:", study_id, "-profile-randomization-tests"),
    notes = "属性×条件ごとのカイ二乗検定。p値はHolm法でも補正した。"
  )
  write_csv_and_tex(
    random_frequency,
    file.path(csv_dir, "table_profile_randomization_frequency.csv"),
    file.path(tex_dir, "table_profile_randomization_frequency.tex"),
    paste0(study_label, ":属性水準の観測比率と設計上の期待比率"),
    paste0("tab:", study_id, "-profile-randomization-frequency"),
    notes = "属性提示の45度線図に対応する数値表。"
  )
  readr::write_csv(randomization$uniformity_tests, file.path(diag_random_dir, "profile_randomization_tests.csv"), na = "")
  readr::write_csv(randomization$frequency, file.path(diag_random_dir, "profile_randomization_frequency.csv"), na = "")
  
  support_amce <- party_support_amce_results[[study_id]]
  if (!is.null(support_amce$subgroup_coefficients)) {
    support_amce_table <- support_amce$subgroup_coefficients %>%
      dplyr::mutate(dplyr::across(where(is.numeric), ~ format_number(.x, 3)))
    write_csv_and_tex(
      support_amce_table,
      file.path(csv_dir, "table_party_support_amce.csv"),
      file.path(tex_dir, "table_party_support_amce.tex"),
      paste0(study_label, ":支持政党別AMCE"),
      paste0("tab:", study_id, "-party-support-amce"),
      notes = "支持政党別AMCE図に対応する推定値。"
    )
  }
  support_relative <- party_support_relative_cue_results[[study_id]]
  if (!is.null(support_relative$intervals)) {
    support_relative_table <- support_relative$intervals %>%
      dplyr::mutate(dplyr::across(where(is.numeric), ~ format_number(.x, 3)))
    write_csv_and_tex(
      support_relative_table,
      file.path(csv_dir, "table_party_support_relative_cue.csv"),
      file.path(tex_dir, "table_party_support_relative_cue.tex"),
      paste0(study_label, ":支持政党別の手がかり重要度と相対比重"),
      paste0("tab:", study_id, "-party-support-relative"),
      notes = "支持政党別の相対比重図に対応する回答者クラスタ・ブートストラップ推定。"
    )
  }
  
  study_table_paths[[study_id]] <- list(csv_dir = csv_dir, tex_dir = tex_dir)
}


cross_csv_dir <- file.path(final_dirs$supplement_cross, "tables_csv")
cross_tex_dir <- file.path(final_dirs$supplement_cross, "tables_tex")

cross_tables <- list(
  hypothesis = hypothesis_test_summary,
  adjusted_slopes = choice_set_adjusted_slope_summary,
  cross_relative = cross_study_relative_weight,
  all_party_match_coefficients = study3_all_party_match_results$coefficients,
  all_party_match_trends = study3_all_party_match_results$trends
)

cross_caption <- c(
  hypothesis = "3実験の主要仮説に対応する線形傾向検定",
  adjusted_slopes = "3実験の選択肢数調整済み重要度の線形傾向",
  cross_relative = "3実験横断の政党手がかり相対比重",
  all_party_match_coefficients = "Study 3:すべての対象支持政党における一致効果",
  all_party_match_trends = "Study 3:一致効果の選択肢数トレンド"
)

for (table_name in names(cross_tables)) {
  table_data <- cross_tables[[table_name]]
  if (is.null(table_data)) next
  table_data <- as.data.frame(table_data) %>%
    dplyr::mutate(dplyr::across(where(is.numeric), ~ format_number(.x, 4)))
  write_csv_and_tex(
    table_data,
    file.path(cross_csv_dir, paste0("table_", table_name, ".csv")),
    file.path(cross_tex_dir, paste0("table_", table_name, ".tex")),
    unname(cross_caption[table_name]),
    paste0("tab:cross-", gsub("_", "-", table_name)),
    notes = "対応する補遺図の数値を表形式で再掲した。"
  )
}


for (study_id in names(study_specs)) {
  working_dir <- unified_config[[study_id]]$output_dir
  supplement_fig_dir <- file.path(final_dirs$supplement_root, study_id, "figures")
  copy_files_by_pattern(working_dir, supplement_fig_dir, "\\.(png|pdf)$")
  copy_files_by_pattern(
    working_dir,
    file.path(final_dirs$model_objects_root, study_id),
    "\\.(rds|RDS)$"
  )
  copy_files_by_pattern(working_dir, final_dirs$logs, "(sessionInfo|\\.txt$)")
  
  support_dir <- file.path(unified_output_dir, paste0(study_id, "_party_support"))
  copy_files_by_pattern(support_dir, supplement_fig_dir, "\\.(png|pdf)$")
}

copy_files_by_pattern(
  unified_output_dir,
  file.path(final_dirs$supplement_cross, "figures"),
  "\\.(png|pdf)$"
)
copy_files_by_pattern(unified_output_dir, final_dirs$logs, "(sessionInfo|\\.txt$)")
copy_files_by_pattern(
  unified_output_dir,
  file.path(final_dirs$model_objects_root, "cross_study"),
  "\\.(rds|RDS)$"
)

for (study_id in names(study_specs)) {
  for (kind in c("assignment_balance_love_plot", "assignment_balance_diagonal_plot")) {
    for (extension in c("png", "pdf")) {
      source <- file.path(unified_output_dir, paste0(study_id, "_", kind, ".", extension))
      destination <- file.path(final_dirs$diagnostics_root, study_id, "balance", basename(source))
      copy_file_if_exists(source, destination)
    }
  }
  for (extension in c("png", "pdf")) {
    source <- file.path(unified_output_dir, paste0(study_id, "_profile_randomization_diagonal_plot.", extension))
    destination <- file.path(final_dirs$diagnostics_root, study_id, "randomization", basename(source))
    copy_file_if_exists(source, destination)
  }
}

if (exists("main_text_figure_manifest")) {
  purrr::pwalk(
    main_text_figure_manifest,
    function(figure_number, study, analysis, file_png, file_pdf) {
      prefix <- gsub("[^A-Za-z0-9]+", "_", figure_number)
      if (!is.na(file_png)) {
        copy_file_if_exists(
          file_png,
          file.path(final_dirs$main_figures, paste0(prefix, "_", basename(file_png)))
        )
      }
      if (!is.na(file_pdf)) {
        copy_file_if_exists(
          file_pdf,
          file.path(final_dirs$main_figures, paste0(prefix, "_", basename(file_pdf)))
        )
      }
    }
  )
}

main_table_map <- list(
  study1 = c("table_amce_covariate_adjusted.tex", "table_cue_importance.tex"),
  study2 = c("table_amce_covariate_adjusted.tex", "table_cue_importance.tex"),
  study3 = c("table_amce_covariate_adjusted.tex", "table_cue_importance.tex", "table_party_match.tex")
)
for (study_id in names(main_table_map)) {
  for (table_file in main_table_map[[study_id]]) {
    source <- file.path(final_dirs$supplement_root, study_id, "tables_tex", table_file)
    copy_file_if_exists(
      source,
      file.path(final_dirs$main_tables, paste0(study_id, "_", table_file))
    )
  }
}


pair_manifest <- tibble::tribble(
  ~study_id, ~section_title, ~figure_file, ~table_files,
  "study1", "共変量調整済みAMCE", "amce_cov_facet_model.png", "table_amce_covariate_adjusted.tex",
  "study1", "AMCEヒートマップ", "amce_heatmap_mixed_rank_colored_labels.png", "table_amce_covariate_adjusted.tex",
  "study1", "共変量を含めないAMCE", "amce_facet_nocov.png", "table_amce_unadjusted.tex",
  "study1", "AMCEの条件差", "amce_interaction_difference_from_2party.png", "table_amce_interaction.tex",
  "study1", "条件付きロジット", "clogit_oddsratio_nocov.png", "table_conditional_logit.tex",
  "study1", "手がかり重要度と相対比重", "fig_study1_relative_cue_weight_choice_set_adjusted_jp_bw.png", "table_marginal_means.tex;table_attribute_importance.tex;table_cue_importance.tex",
  "study2", "共変量調整済みAMCE", "amce_cov_facet_model.png", "table_amce_covariate_adjusted.tex",
  "study2", "AMCEヒートマップ", "amce_heatmap_mixed_rank_colored_labels.png", "table_amce_covariate_adjusted.tex",
  "study2", "共変量を含めないAMCE", "amce_facet_nocov.png", "table_amce_unadjusted.tex",
  "study2", "AMCEの条件差", "amce_interaction_difference_from_2party.png", "table_amce_interaction.tex",
  "study2", "条件付きロジット", "clogit_oddsratio_nocov.png", "table_conditional_logit.tex",
  "study2", "手がかり重要度と相対比重", "fig_study2_relative_cue_weight_choice_set_adjusted_jp_bw.png", "table_marginal_means.tex;table_attribute_importance.tex;table_cue_importance.tex",
  "study3", "共変量調整済みAMCE", "amce_cov_facet_model.png", "table_amce_covariate_adjusted.tex",
  "study3", "共変量を含めないAMCE", "amce_nocov_facet_model.png", "table_amce_unadjusted.tex",
  "study3", "AMCEの条件差", "amce_interaction_difference_from_2choice.png", "table_amce_interaction.tex",
  "study3", "AMCEの線形トレンド", "amce_linear_trend.png", "table_amce_linear_trend.tex",
  "study3", "AMCEヒートマップ", "amce_cov_heatmap.png", "table_amce_covariate_adjusted.tex",
  "study3", "条件付きロジット", "clogit_oddsratio_nocov.png", "table_conditional_logit.tex",
  "study3", "支持政党と提示政党名の一致効果", "party_match_effect_combined.png", "table_party_match.tex",
  "study3", "手がかり重要度と相対比重", "fig_study3_relative_cue_weight_choice_set_adjusted_jp_bw.png", "table_marginal_means.tex;table_attribute_importance.tex;table_cue_importance.tex"
)

for (study_id in names(study_specs)) {
  support_figures <- list.files(
    file.path(final_dirs$supplement_root, study_id, "figures"),
    pattern = "party_support_amce_.*\\.png$",
    full.names = FALSE
  )
  if (length(support_figures) > 0) {
    pair_manifest <- dplyr::bind_rows(
      pair_manifest,
      tibble::tibble(
        study_id = study_id,
        section_title = paste0("支持政党別AMCE:", support_figures),
        figure_file = support_figures,
        table_files = "table_party_support_amce.tex"
      )
    )
  }
  if (file.exists(file.path(final_dirs$supplement_root, study_id, "figures", "party_support_relative_cue_weight.png"))) {
    pair_manifest <- dplyr::bind_rows(
      pair_manifest,
      tibble::tibble(
        study_id = study_id,
        section_title = "支持政党別の手がかり相対比重",
        figure_file = "party_support_relative_cue_weight.png",
        table_files = "table_party_support_relative_cue.tex"
      )
    )
  }
}

readr::write_csv(
  pair_manifest,
  file.path(final_dirs$supplement_root, "figure_table_pair_manifest.csv"),
  na = ""
)

pair_tex_lines <- c(
  "% Generated automatically. Run LuaLaTeX from the supplement directory.",
  "\\providecommand{\\ConjointSupplementRoot}{.}",
  "\\section{標本構築・データ品質・分析結果}"
)

for (study_id in names(study_specs)) {
  study_label <- study_specs[[study_id]]$study_label
  pair_tex_lines <- c(
    pair_tex_lines,
    paste0("\\section{", latex_escape(study_label), "}"),
    "\\subsection{標本構築とスクリーニング}",
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_sample_attrition.tex}"),
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_sample_attrition_by_condition.tex}"),
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_manipulation_check.tex}"),
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_attention_check.tex}"),
    "\\clearpage",
    "\\subsection{回答者割付のバランス}",
    "\\begin{figure}[p]",
    "\\centering",
    paste0(
      "\\includegraphics[width=0.92\\linewidth]{\\ConjointSupplementRoot/../diagnostics/",
      study_id,
      "/balance/",
      study_id,
      "_assignment_balance_love_plot.png}"
    ),
    paste0("\\caption{", latex_escape(study_label), ":回答者割付のLove plot}"),
    "\\end{figure}",
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_assignment_balance_pairwise_smd.tex}"),
    "\\begin{figure}[p]",
    "\\centering",
    paste0(
      "\\includegraphics[width=0.92\\linewidth]{\\ConjointSupplementRoot/../diagnostics/",
      study_id,
      "/balance/",
      study_id,
      "_assignment_balance_diagonal_plot.png}"
    ),
    paste0("\\caption{", latex_escape(study_label), ":条件別共変量平均の45度線診断}"),
    "\\end{figure}",
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_assignment_balance_summary.tex}"),
    "\\clearpage",
    "\\subsection{コンジョイント属性提示の無作為化診断}",
    "\\begin{figure}[p]",
    "\\centering",
    paste0(
      "\\includegraphics[width=0.92\\linewidth]{\\ConjointSupplementRoot/../diagnostics/",
      study_id,
      "/randomization/",
      study_id,
      "_profile_randomization_diagonal_plot.png}"
    ),
    paste0("\\caption{", latex_escape(study_label), ":属性水準の観測比率と期待比率}"),
    "\\end{figure}",
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_profile_randomization_tests.tex}"),
    paste0("\\input{\\ConjointSupplementRoot/", study_id, "/tables_tex/table_profile_randomization_frequency.tex}"),
    "\\clearpage",
    "\\subsection{推定結果:図と対応する表}"
  )
  
  study_pairs <- pair_manifest %>% dplyr::filter(.data$study_id == study_id)
  for (i in seq_len(nrow(study_pairs))) {
    row <- study_pairs[i, ]
    figure_path <- file.path(row$study_id, "figures", row$figure_file)
    tables <- unlist(strsplit(row$table_files, ";", fixed = TRUE))
    pair_tex_lines <- c(
      pair_tex_lines,
      paste0("\\subsubsection{", latex_escape(row$section_title), "}"),
      "\\begin{figure}[p]",
      "\\centering",
      paste0("\\includegraphics[width=0.96\\linewidth]{\\ConjointSupplementRoot/", gsub("\\\\", "/", figure_path), "}"),
      paste0("\\caption{", latex_escape(row$section_title), "}"),
      "\\end{figure}"
    )
    for (table_file in tables) {
      table_path <- file.path(row$study_id, "tables_tex", table_file)
      if (file.exists(file.path(final_dirs$supplement_root, table_path))) {
        pair_tex_lines <- c(
          pair_tex_lines,
          paste0("\\input{\\ConjointSupplementRoot/", gsub("\\\\", "/", table_path), "}")
        )
      }
    }
    pair_tex_lines <- c(pair_tex_lines, "\\clearpage")
  }
}

pair_tex_lines <- c(
  pair_tex_lines,
  "\\section{3実験横断の分析}",
  "\\subsection{主要仮説の線形傾向検定}",
  "\\begin{figure}[p]",
  "\\centering",
  "\\includegraphics[width=0.92\\linewidth]{\\ConjointSupplementRoot/cross_study/figures/fig_supp_hypothesis_linear_trend_tests.png}",
  "\\caption{3実験の主要仮説に対応する線形傾向検定}",
  "\\end{figure}",
  "\\input{\\ConjointSupplementRoot/cross_study/tables_tex/table_hypothesis.tex}",
  "\\clearpage",
  "\\subsection{選択肢数調整済み重要度の線形傾向}",
  "\\begin{figure}[p]",
  "\\centering",
  "\\includegraphics[width=0.92\\linewidth]{\\ConjointSupplementRoot/cross_study/figures/fig_supp_choice_set_adjusted_importance_slopes.png}",
  "\\caption{3実験の選択肢数調整済み重要度の線形傾向}",
  "\\end{figure}",
  "\\input{\\ConjointSupplementRoot/cross_study/tables_tex/table_adjusted_slopes.tex}",
  "\\clearpage",
  "\\subsection{3実験横断の政党手がかり相対比重}",
  "\\begin{figure}[p]",
  "\\centering",
  "\\includegraphics[width=0.92\\linewidth]{\\ConjointSupplementRoot/cross_study/figures/fig_supp_cross_study_relative_party_weight.png}",
  "\\caption{3実験横断の政党手がかり相対比重}",
  "\\end{figure}",
  "\\input{\\ConjointSupplementRoot/cross_study/tables_tex/table_cross_relative.tex}",
  "\\clearpage"
)

if (file.exists(file.path(final_dirs$supplement_cross, "figures", "party_match_all_parties.png"))) {
  pair_tex_lines <- c(
    pair_tex_lines,
    "\\subsection{Study 3:すべての対象支持政党における一致効果}",
    "\\begin{figure}[p]",
    "\\centering",
    "\\includegraphics[width=0.92\\linewidth]{\\ConjointSupplementRoot/cross_study/figures/party_match_all_parties.png}",
    "\\caption{すべての対象支持政党における支持政党名一致効果}",
    "\\end{figure}",
    "\\input{\\ConjointSupplementRoot/cross_study/tables_tex/table_all_party_match_coefficients.tex}",
    "\\input{\\ConjointSupplementRoot/cross_study/tables_tex/table_all_party_match_trends.tex}",
    "\\clearpage"
  )
}

writeLines(
  pair_tex_lines,
  con = file.path(final_dirs$supplement_root, "all_studies_figure_table_pairs.tex"),
  useBytes = TRUE
)

preamble_lines <- c(
  "% Add these packages to the preamble of appendix.tex.",
  "\\usepackage{graphicx}",
  "\\usepackage{booktabs}",
  "\\usepackage{longtable}",
  "\\usepackage{array}",
  "\\usepackage{pdflscape}",
  "\\usepackage{caption}",
  "% Compile with LuaLaTeX because the generated captions and tables contain Japanese."
)
writeLines(
  preamble_lines,
  con = file.path(final_dirs$supplement_root, "latex_preamble_snippet.tex"),
  useBytes = TRUE
)

standalone_lines <- c(
  "% !TeX program = lualatex",
  "\\documentclass[a4paper,11pt]{ltjsarticle}",
  "\\usepackage[margin=22mm]{geometry}",
  "\\usepackage{graphicx}",
  "\\usepackage{booktabs}",
  "\\usepackage{longtable}",
  "\\usepackage{array}",
  "\\usepackage{pdflscape}",
  "\\usepackage{caption}",
  "\\begin{document}",
  "\\tableofcontents",
  "\\clearpage",
  "\\input{all_studies_figure_table_pairs.tex}",
  "\\end{document}"
)
writeLines(
  standalone_lines,
  con = file.path(final_dirs$supplement_root, "supplement_tables_figures_master.tex"),
  useBytes = TRUE
)

layout_lines <- c(
  "OUTPUT DIRECTORY STRUCTURE",
  "==========================",
  "main_text/figures      : manuscript figures",
  "main_text/tables       : LaTeX tables corresponding to manuscript figures",
  "supplement/study1-3    : per-study figures, CSV tables, and LaTeX tables",
  "supplement/cross_study : cross-study figures and tables",
  "diagnostics/study1-3   : respondent screening, balance, and randomization diagnostics",
  "model_objects          : RDS model and analysis objects",
  "logs                   : text model summaries and session information",
  "_working               : original intermediate outputs produced by each analysis module",
  "",
  "LATEX",
  "-----",
  "Add the packages in supplement/latex_preamble_snippet.tex to appendix.tex.",
  "Then input supplement/all_studies_figure_table_pairs.tex, or compile",
  "supplement/supplement_tables_figures_master.tex with LuaLaTeX."
)
writeLines(
  layout_lines,
  con = file.path(final_output_root, "OUTPUT_STRUCTURE_AND_LATEX_README.txt"),
  useBytes = TRUE
)

saveRDS(
  list(
    screening = screening_results,
    pair_manifest = pair_manifest,
    final_dirs = final_dirs
  ),
  file = file.path(final_dirs$model_objects_root, "screening_and_latex_export_objects.rds")
)

cat(
  "\nScreened-sample audit, LaTeX tables, figure-table pairs, and final output organization completed.\n",
  "Final output root: ", normalizePath(final_output_root), "\n",
  "LaTeX master: ",
  normalizePath(file.path(final_dirs$supplement_root, "supplement_tables_figures_master.tex")),
  "\n",
  sep = ""
)

B. 推定方法と分析標本の定義

B.1 分析標本

各回答者は2、3、4、5のいずれかの選択肢数条件に割り当てられ、5つの選択課題に回答した。従属変数は、各課題に提示されたプロフィールが選択された場合に1、選択されなかった場合に0をとる二値変数である。

実験1では、初回同意、最終送信同意、および割り当てられた条件における5課題の有効回答を満たす回答者を分析対象とした。実験2・3では、これらに加えて、イデオロギー行列中の指示項目と選択肢数の操作確認質問に正答した回答者に限定した。

B.2 AMCE

回答者を \(i\)、選択課題を \(t\)、プロフィールを \(j\)、選択肢数条件を \(k\in\{2,3,4,5\}\) とする。従属変数を

\[ Y_{itj} = \mathbf{1}\{\text{プロフィール }j\text{ が選択された}\} \]

と定義する。各選択肢数条件について、線形確率モデルを別々に推定する。

\[ Y_{itj} = \alpha^{(k)} + \sum_{a} \sum_{\ell\neq \ell_{a0}} \beta_{a\ell}^{(k)}D_{itj,a\ell} + \boldsymbol{\gamma}^{(k)\prime}\boldsymbol{Z}_{i} + \varepsilon_{itj}^{(k)}. \]

\(\beta_{a\ell}^{(k)}\) は、\(k\) 選択肢条件において、属性 \(a\) を基準水準 \(\ell_{a0}\) から水準 \(\ell\) に変更したときの平均限界要素効果(AMCE)である。標準誤差は回答者単位でクラスタ化した。

実験1・2では、政策位置の基準を中道、与野党地位の基準を野党、議席数の基準を10以下とし、GDP成長率、日経平均株価、CPI、失業率はいずれも変化なしを基準とした。実験3では政党名の基準を自由民主党とした。

B.3 限界平均と属性重要度

\(k\) 選択肢条件における属性 \(a\) の水準 \(\ell\) の限界平均を、

\[ \widehat{\mu}_{a\ell}^{(k)} = \frac{ \sum_{i,t,j} \mathbf{1}\{X_{itj,a}=\ell\}Y_{itj} }{ \sum_{i,t,j} \mathbf{1}\{X_{itj,a}=\ell\} } \]

とする。

属性 \(a\)\(L_a\) 個の水準をもつとき、属性重要度を全水準ペアの限界平均差の絶対値の平均として、

\[ \widehat{I}_{a}^{(k)} = \binom{L_a}{2}^{-1} \sum_{\ell<\ell'} \left| \widehat{\mu}_{a\ell}^{(k)} - \widehat{\mu}_{a\ell'}^{(k)} \right| \]

と定義した。

実験1・2の政党手がかりの重要度は、政策位置、与野党地位、議席数の3属性の重要度を等しい加重で平均した。実験3では政党名属性の重要度を政党手がかりの重要度とした。経済手がかりは、3実験ともGDP成長率、日経平均株価、CPI、失業率の4属性の重要度を等しい加重で平均した。

B.4 選択肢数調整済み重要度と相対比重

\(k\) 個のプロフィールから必ず1つを選択するため、プロフィール1件あたりの平均選択確率は \(1/k\) となる。条件間比較のため、属性 \(a\) の選択肢数調整済み重要度を、

\[ \widehat{I}_{a}^{\mathrm{adj},(k)} = \frac{\widehat{I}_{a}^{(k)}}{1/k} = k\widehat{I}_{a}^{(k)} \]

とした。

政党手がかりの重要度を \(\widehat{P}^{(k)}\)、経済手がかりの重要度を \(\widehat{E}^{(k)}\) とすると、政党手がかりの相対比重は、

\[ \widehat{W}^{(k)} = \frac{\widehat{P}^{(k)}} {\widehat{P}^{(k)}+\widehat{E}^{(k)}} \]

である。政党・経済の両重要度に同じ \(k\) を乗じても相対比重は変化しない。

B.5 ブートストラップと線形トレンド

重要度と相対比重の95%信頼区間は、各選択肢数条件内で回答者を単位として復元抽出し、各回答者の5課題・全プロフィールに欠損のない回答者クラスター・ブートストラップから算出した。主要分析では2,000回反復させた。

各指標 \(Q^{(k)}\) の選択肢数に対する線形傾向は、

\[ Q^{(k)}=\eta+\delta k+u^{(k)} \]

として4条件の点推定値にOLSを当てはめ、傾き \(\delta\) を求めた。各ブートストラップ反復でも同じ傾きを再推定し、95%信頼区間と両側ブートストラップ \(p\) 値を算出した。H1a、H1b、H2a、H2bの形式的な判定には未調整重要度の線形トレンドを用い、選択肢数調整済み重要度の線形トレンドは条件間比較の感度分析として併用した。

B.6 条件付きロジット

強制選択課題の構造を考慮する頑健性分析として、各選択肢数条件について条件付きロジットを推定した。

\[ \Pr(Y_{itj}=1\mid \mathcal{C}_{it}) = \frac{\exp(\boldsymbol{X}_{itj}^{\prime}\boldsymbol{\beta}^{(k)})} {\sum_{r\in\mathcal{C}_{it}}\exp(\boldsymbol{X}_{itr}^{\prime}\boldsymbol{\beta}^{(k)})}. \]

ここで、\(r\) は同一選択課題内のプロフィールを走る添字であり、\(k\) は選択肢数条件を表す。課題を層(stratum)とし、回答者単位でクラスタ化した。回答者レベル共変量は同一選択課題内で一定であるため、条件付きロジットにはプロフィール属性のみを投入した。

B.7 支持政党名との一致効果

実験3では、

\[ M_{itj} = \mathbf{1}\{\text{提示政党名}_{itj}=\text{支持政党}_{i}\} \]

を作成した。全体モデルでは、支持政党名一致、提示政党名、4つの経済属性を投入し、選択肢数条件ごとに推定した。なお、支持政党別の分析では、政党名と一致指標が完全に対応してしまうため、政党名主効果を除き、一致指標と経済属性を用いた。

B.8 バランスと無作為化診断

回答者割付のバランスは、2、3、4、5条件の全条件ペアについて標準化平均差を算出した。用いた回答者属性は、各実験で利用可能な性別、年齢、4年制大学以上、対数世帯年収、自己イデオロギー、およびそれらの欠損指標と支持政党である。地域・都道府県はこの割付バランス診断には用いていない。Love plot は全6条件ペアの絶対SMDを示し、対角線図は同じ回答者共変量について各条件平均を標準化し、二条件ずつ45度線と比較する補助的な可視化である。

\[ \mathrm{SMD}_{ab} = \frac{\overline{x}_a-\overline{x}_b} {\sqrt{(s_a^2+s_b^2)/2}}. \]

プロフィール属性の提示については、選択肢数条件×属性×水準ごとに観測比率を求め、水準数を \(L_a\) とした設計上の期待比率 \(1/L_a\) と比較した。属性×条件ごとに一様分布を帰無仮説とするカイ二乗検定を行い、Holm法による補正値も報告した。

C. 無作為化についての各種検討

以下で、回答者レベルの割付バランスとプロフィール属性の無作為提示は別々に確認する。回答者レベルではLove plotと45度線診断を併用し、プロフィールレベルでは各属性水準の観測比率を設計上の期待比率と比較する。

B.1 実験1(2023年)

図C1:回答者割付のLove plot

実験1仕様 <- study_specs$study1
実験1割付設計 <- make_balance_design(実験1仕様)
実験1SMD <- pairwise_smd_multiarm(実験1割付設計$long)
実験1最大SMD <- 実験1SMD %>%
  dplyr::group_by(variable, label) %>%
  dplyr::summarise(max_abs_smd = max(abs_smd, na.rm = TRUE), .groups = "drop")

Loveデータ <- 実験1SMD %>%
  dplyr::left_join(実験1最大SMD, by = c("variable", "label")) %>%
  dplyr::mutate(表示名 = stats::reorder(label, max_abs_smd))

図C1 <- ggplot2::ggplot(Loveデータ, ggplot2::aes(x = abs_smd, y = 表示名)) +
  ggplot2::geom_vline(xintercept = 0.10, linetype = "dashed", linewidth = 0.55) +
  ggplot2::geom_point(alpha = 0.30, size = 1.4, position = ggplot2::position_jitter(height = 0.10, width = 0)) +
  ggplot2::geom_point(
    data = 実験1最大SMD %>% dplyr::mutate(表示名 = stats::reorder(label, max_abs_smd)),
    ggplot2::aes(x = max_abs_smd, y = 表示名),
    inherit.aes = FALSE, shape = 21, fill = "white", size = 2.5, stroke = 0.8
  ) +
  ggplot2::labs(x = "条件間の絶対標準化平均差(|SMD|)", y = NULL,
                subtitle = "実験1(2023年):各点は条件ペア、白抜き点は最大絶対SMD") +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
図C1

表C1には図C1の各点に対応する。各行には比較する2条件の平均とSMDを示す。

表C1 <- 実験1SMD %>%
  dplyr::transmute(
    変数 = label,
    比較 = paste0(condition_a, "政党条件-", condition_b, "政党条件"),
    `前者の平均` = round(mean_a, 3),
    `後者の平均` = round(mean_b, 3),
    `前者N` = n_a,
    `後者N` = n_b,
    SMD = round(smd, 3),
    `|SMD|` = round(abs_smd, 3)
  )
knitr::kable(表日本語(表C1), format = "html", row.names = FALSE)
変数 比較 前者の平均 後者の平均 前者N 後者N SMD |SMD|
年齢 2政党条件-3政党条件 35.374 34.896 815 843 0.049 0.049
女性 2政党条件-3政党条件 0.297 0.305 815 843 -0.017 0.017
性別:欠損 2政党条件-3政党条件 0.021 0.017 815 843 0.031 0.031
世帯年収(対数) 2政党条件-3政党条件 5.890 6.068 815 843 -0.133 0.133
支持政党:公明党 2政党条件-3政党条件 0.189 0.168 815 843 0.054 0.054
支持政党:国民民主党 2政党条件-3政党条件 0.000 0.002 815 843 -0.069 0.069
支持政党:日本共産党 2政党条件-3政党条件 0.055 0.058 815 843 -0.013 0.013
支持政党:日本維新の会 2政党条件-3政党条件 0.499 0.509 815 843 -0.019 0.019
支持政党:社会民主党 2政党条件-3政党条件 0.009 0.013 815 843 -0.043 0.043
支持政党:立憲民主党 2政党条件-3政党条件 0.240 0.238 815 843 0.005 0.005
支持政党:自由民主党 2政党条件-3政党条件 0.007 0.011 815 843 -0.035 0.035
年齢 2政党条件-4政党条件 35.374 35.760 815 882 -0.040 0.040
女性 2政党条件-4政党条件 0.297 0.296 815 882 0.002 0.002
性別:欠損 2政党条件-4政党条件 0.021 0.018 815 882 0.020 0.020
世帯年収(対数) 2政党条件-4政党条件 5.890 6.007 815 882 -0.084 0.084
支持政党:公明党 2政党条件-4政党条件 0.189 0.202 815 882 -0.032 0.032
支持政党:国民民主党 2政党条件-4政党条件 0.000 0.002 815 882 -0.067 0.067
支持政党:日本共産党 2政党条件-4政党条件 0.055 0.084 815 882 -0.113 0.113
支持政党:日本維新の会 2政党条件-4政党条件 0.499 0.456 815 882 0.087 0.087
支持政党:社会民主党 2政党条件-4政党条件 0.009 0.015 815 882 -0.057 0.057
支持政党:立憲民主党 2政党条件-4政党条件 0.240 0.240 815 882 0.000 0.000
支持政党:自由民主党 2政党条件-4政党条件 0.007 0.001 815 882 0.096 0.096
年齢 2政党条件-5政党条件 35.374 34.901 815 842 0.048 0.048
女性 2政党条件-5政党条件 0.297 0.293 815 842 0.008 0.008
性別:欠損 2政党条件-5政党条件 0.021 0.018 815 842 0.022 0.022
世帯年収(対数) 2政党条件-5政党条件 5.890 6.033 815 842 -0.105 0.105
支持政党:公明党 2政党条件-5政党条件 0.189 0.185 815 842 0.009 0.009
支持政党:国民民主党 2政党条件-5政党条件 0.000 0.002 815 842 -0.069 0.069
支持政党:日本共産党 2政党条件-5政党条件 0.055 0.065 815 842 -0.042 0.042
支持政党:日本維新の会 2政党条件-5政党条件 0.499 0.458 815 842 0.082 0.082
支持政党:社会民主党 2政党条件-5政党条件 0.009 0.010 815 842 -0.010 0.010
支持政党:立憲民主党 2政党条件-5政党条件 0.240 0.278 815 842 -0.085 0.085
支持政党:自由民主党 2政党条件-5政党条件 0.007 0.001 815 842 0.095 0.095
年齢 3政党条件-4政党条件 34.896 35.760 843 882 -0.090 0.090
女性 3政党条件-4政党条件 0.305 0.296 843 882 0.020 0.020
性別:欠損 3政党条件-4政党条件 0.017 0.018 843 882 -0.012 0.012
世帯年収(対数) 3政党条件-4政党条件 6.068 6.007 843 882 0.049 0.049
支持政党:公明党 3政党条件-4政党条件 0.168 0.202 843 882 -0.086 0.086
支持政党:国民民主党 3政党条件-4政党条件 0.002 0.002 843 882 0.002 0.002
支持政党:日本共産党 3政党条件-4政党条件 0.058 0.084 843 882 -0.100 0.100
支持政党:日本維新の会 3政党条件-4政党条件 0.509 0.456 843 882 0.106 0.106
支持政党:社会民主党 3政党条件-4政党条件 0.013 0.015 843 882 -0.014 0.014
支持政党:立憲民主党 3政党条件-4政党条件 0.238 0.240 843 882 -0.005 0.005
支持政党:自由民主党 3政党条件-4政党条件 0.011 0.001 843 882 0.125 0.125
年齢 3政党条件-5政党条件 34.896 34.901 843 842 -0.001 0.001
女性 3政党条件-5政党条件 0.305 0.293 843 842 0.025 0.025
性別:欠損 3政党条件-5政党条件 0.017 0.018 843 842 -0.009 0.009
世帯年収(対数) 3政党条件-5政党条件 6.068 6.033 843 842 0.029 0.029
支持政党:公明党 3政党条件-5政党条件 0.168 0.185 843 842 -0.044 0.044
支持政党:国民民主党 3政党条件-5政党条件 0.002 0.002 843 842 0.000 0.000
支持政党:日本共産党 3政党条件-5政党条件 0.058 0.065 843 842 -0.030 0.030
支持政党:日本維新の会 3政党条件-5政党条件 0.509 0.458 843 842 0.101 0.101
支持政党:社会民主党 3政党条件-5政党条件 0.013 0.010 843 842 0.034 0.034
支持政党:立憲民主党 3政党条件-5政党条件 0.238 0.278 843 842 -0.090 0.090
支持政党:自由民主党 3政党条件-5政党条件 0.011 0.001 843 842 0.124 0.124
年齢 4政党条件-5政党条件 35.760 34.901 882 842 0.089 0.089
女性 4政党条件-5政党条件 0.296 0.293 882 842 0.006 0.006
性別:欠損 4政党条件-5政党条件 0.018 0.018 882 842 0.002 0.002
世帯年収(対数) 4政党条件-5政党条件 6.007 6.033 882 842 -0.020 0.020
支持政党:公明党 4政党条件-5政党条件 0.202 0.185 882 842 0.042 0.042
支持政党:国民民主党 4政党条件-5政党条件 0.002 0.002 882 842 -0.002 0.002
支持政党:日本共産党 4政党条件-5政党条件 0.084 0.065 882 842 0.071 0.071
支持政党:日本維新の会 4政党条件-5政党条件 0.456 0.458 882 842 -0.005 0.005
支持政党:社会民主党 4政党条件-5政党条件 0.015 0.010 882 842 0.048 0.048
支持政党:立憲民主党 4政党条件-5政党条件 0.240 0.278 882 842 -0.086 0.086
支持政党:自由民主党 4政党条件-5政党条件 0.001 0.001 882 842 -0.002 0.002

図C2:条件平均の45度線診断

図C2は図C1と同じ回答者レベルの割付バランスを、各共変量の条件平均を標準化したうえで二条件ずつ45度線と比較したものである。

対角線データ <- assignment_balance_results$study1$diagonal_data %>%
  dplyr::mutate(
    比較 = paste0(condition_a, "政党条件-", condition_b, "政党条件")
  )

ラベル対象 <- 対角線データ %>%
  dplyr::group_by(比較) %>%
  dplyr::slice_max(abs_diagonal_deviation, n = 3, with_ties = FALSE) %>%
  dplyr::ungroup()

軸範囲 <- max(abs(c(対角線データ$x_mean, 対角線データ$y_mean)), na.rm = TRUE)
軸範囲 <- max(0.10, 軸範囲 * 1.15)

図C2 <- ggplot2::ggplot(対角線データ, ggplot2::aes(x = x_mean, y = y_mean)) +
  ggplot2::geom_abline(intercept = 0, slope = 1, linetype = "dashed", linewidth = 0.60) +
  ggplot2::geom_hline(yintercept = 0, linewidth = 0.25) +
  ggplot2::geom_vline(xintercept = 0, linewidth = 0.25) +
  ggplot2::geom_point(shape = 21, fill = "white", size = 2.2) +
  ggplot2::geom_text(data = ラベル対象, ggplot2::aes(label = label), size = 2.6, check_overlap = TRUE, vjust = -0.7) +
  ggplot2::facet_wrap(~ 比較, ncol = 3) +
  ggplot2::coord_equal(xlim = c(-軸範囲, 軸範囲), ylim = c(-軸範囲, 軸範囲)) +
  ggplot2::labs(x = "左側条件の標準化共変量平均", y = "右側条件の標準化共変量平均") +
  ggplot2::theme_bw(base_size = 10.5) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
図C2

表C2 <- assignment_balance_results$study1$summary %>%
  dplyr::transmute(
    変数 = label,
    `2政党条件の平均` = round(mean_condition_2, 3),
    `3政党条件の平均` = round(mean_condition_3, 3),
    `4政党条件の平均` = round(mean_condition_4, 3),
    `5政党条件の平均` = round(mean_condition_5, 3),
    `最大|SMD|` = round(max_abs_smd, 3),
    `Holm補正p値` = signif(p_holm, 3)
  )
knitr::kable(表日本語(表C2), format = "html", row.names = FALSE)
変数 2政党条件の平均 3政党条件の平均 4政党条件の平均 5政党条件の平均 最大|SMD| Holm補正p値
世帯年収(対数) 5.890 6.068 6.007 6.033 0.133 0.336
支持政党:自由民主党 0.007 0.011 0.001 0.001 0.125 0.106
支持政党:日本共産党 0.055 0.058 0.084 0.065 0.113 0.580
支持政党:日本維新の会 0.499 0.509 0.456 0.458 0.106 0.476
年齢 35.374 34.896 35.760 34.901 0.090 1.000
支持政党:立憲民主党 0.240 0.238 0.240 0.278 0.090 1.000
支持政党:公明党 0.189 0.168 0.202 0.185 0.086 1.000
支持政党:国民民主党 0.000 0.002 0.002 0.002 0.069 1.000
支持政党:社会民主党 0.009 0.013 0.015 0.010 0.057 1.000
性別:欠損 0.021 0.017 0.018 0.018 0.031 1.000
女性 0.297 0.305 0.296 0.293 0.025 1.000

図C3:プロフィール属性水準の無作為提示

図C3は回答者の条件割付ではなく、各コンジョイント課題内で属性水準が設計どおり一様に提示されているかを確認したものである。

属性頻度 <- profile_randomization_results$study1$frequency %>%
  dplyr::mutate(
    属性 = 属性日本語(attribute),
    条件 = 条件日本語(party_n, "study1")
  )

表示ラベル <- 属性頻度 %>%
  dplyr::group_by(属性, 条件) %>%
  dplyr::slice_max(abs_deviation, n = 2, with_ties = FALSE) %>%
  dplyr::ungroup()

図C3 <- ggplot2::ggplot(属性頻度, ggplot2::aes(x = expected_share, y = observed_share, shape = 条件)) +
  ggplot2::geom_abline(intercept = 0, slope = 1, linetype = "dashed", linewidth = 0.65) +
  ggplot2::geom_point(size = 2.2, fill = "white") +
  ggplot2::geom_text(data = 表示ラベル, ggplot2::aes(label = level), size = 2.4, check_overlap = TRUE, vjust = -0.7) +
  ggplot2::facet_wrap(~ 属性, ncol = 3) +
  ggplot2::coord_equal() +
  ggplot2::labs(x = "設計上の期待比率", y = "観測比率", shape = "条件") +
  ggplot2::theme_bw(base_size = 10.5) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank(), legend.position = "bottom")
図C3

表C3 <- profile_randomization_results$study1$uniformity_tests %>%
  dplyr::transmute(
    条件 = 条件日本語(party_n, "study1"),
    属性 = 属性日本語(attribute),
    `カイ二乗値` = round(chi_square, 3),
    自由度 = df,
    p値 = signif(p_value, 3),
    `Holm補正p値` = signif(p_holm, 3),
    `最大絶対比率差` = round(max_abs_share_deviation, 4)
  )
knitr::kable(表日本語(表C3), format = "html", row.names = FALSE)
条件 属性 カイ二乗値 自由度 p値 Holm補正p値 最大絶対比率差
2政党条件 消費者物価指数(CPI) 2.339 2 3.110000e-01 1.000000e+00 0.0078
2政党条件 GDP成長率 4.032 2 1.330000e-01 1.000000e+00 0.0091
2政党条件 与野党地位 2.474 1 1.160000e-01 1.000000e+00 0.0087
2政党条件 日経平均株価 0.108 2 9.480000e-01 1.000000e+00 0.0017
2政党条件 政策位置 0.022 2 9.890000e-01 1.000000e+00 0.0007
2政党条件 衆議院議席数 6.683 4 1.540000e-01 1.000000e+00 0.0080
2政党条件 失業率 1.851 2 3.960000e-01 1.000000e+00 0.0071
3政党条件 消費者物価指数(CPI) 1.489 2 4.750000e-01 1.000000e+00 0.0049
3政党条件 GDP成長率 7.043 2 2.950000e-02 6.500000e-01 0.0111
3政党条件 与野党地位 1476.555 1 4.940656e-323 1.240105e-321 0.1709
3政党条件 日経平均株価 1.700 2 4.270000e-01 1.000000e+00 0.0055
3政党条件 政策位置 4.462 2 1.070000e-01 1.000000e+00 0.0081
3政党条件 衆議院議席数 209.363 4 3.640000e-44 8.380000e-43 0.0335
3政党条件 失業率 1.219 2 5.440000e-01 1.000000e+00 0.0042
4政党条件 消費者物価指数(CPI) 4.270 2 1.180000e-01 1.000000e+00 0.0073
4政党条件 GDP成長率 0.127 2 9.390000e-01 1.000000e+00 0.0012
4政党条件 与野党地位 4587.756 1 0.000000e+00 0.000000e+00 0.2550
4政党条件 日経平均株価 1.221 2 5.430000e-01 1.000000e+00 0.0037
4政党条件 政策位置 4.136 2 1.260000e-01 1.000000e+00 0.0070
4政党条件 衆議院議席数 896.584 4 9.160000e-193 2.200000e-191 0.0739
4政党条件 失業率 0.551 2 7.590000e-01 1.000000e+00 0.0025
5政党条件 消費者物価指数(CPI) 2.511 2 2.850000e-01 1.000000e+00 0.0051
5政党条件 GDP成長率 3.062 2 2.160000e-01 1.000000e+00 0.0056
5政党条件 与野党地位 7618.855 1 0.000000e+00 0.000000e+00 0.3008
5政党条件 日経平均株価 1.781 2 4.100000e-01 1.000000e+00 0.0041
5政党条件 政策位置 0.632 2 7.290000e-01 1.000000e+00 0.0025
5政党条件 衆議院議席数 3958.393 4 0.000000e+00 0.000000e+00 0.1051
5政党条件 失業率 6.864 2 3.230000e-02 6.790000e-01 0.0079
表C4 <- 属性頻度 %>%
  dplyr::transmute(
    条件,
    属性,
    水準 = level,
    観測数 = observed_n,
    総数 = total_n,
    観測比率 = round(observed_share, 4),
    期待比率 = round(expected_share, 4),
= round(deviation, 4)
  )
knitr::kable(表日本語(表C4), format = "html", row.names = FALSE)
条件 属性 水準 観測数 総数 観測比率 期待比率
2政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 2672 8150 0.3279 0.3333 -0.0055
2政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 2780 8150 0.3411 0.3333 0.0078
2政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 2698 8150 0.3310 0.3333 -0.0023
2政党条件 GDP成長率 GDP成長率±0% 2716 8150 0.3333 0.3333 -0.0001
2政党条件 GDP成長率 GDP成長率プラス1% 2791 8150 0.3425 0.3333 0.0091
2政党条件 GDP成長率 GDP成長率マイナス1% 2643 8150 0.3243 0.3333 -0.0090
2政党条件 与野党地位 与党 4146 8150 0.5087 0.5000 0.0087
2政党条件 与野党地位 野党 4004 8150 0.4913 0.5000 -0.0087
2政党条件 日経平均株価 日経平均前月同期比プラス1000円 2721 8150 0.3339 0.3333 0.0005
2政党条件 日経平均株価 日経平均前月同期比マイナス1000円 2726 8150 0.3345 0.3333 0.0011
2政党条件 日経平均株価 日経平均前月同期比変わらず 2703 8150 0.3317 0.3333 -0.0017
2政党条件 政策位置 中道 2717 8150 0.3334 0.3333 0.0000
2政党条件 政策位置 右派・保守的 2711 8150 0.3326 0.3333 -0.0007
2政党条件 政策位置 左派・革新的 2722 8150 0.3340 0.3333 0.0007
2政党条件 衆議院議席数 100~199 1662 8150 0.2039 0.2000 0.0039
2政党条件 衆議院議席数 10~49 1565 8150 0.1920 0.2000 -0.0080
2政党条件 衆議院議席数 10以下 1686 8150 0.2069 0.2000 0.0069
2政党条件 衆議院議席数 200以上 1652 8150 0.2027 0.2000 0.0027
2政党条件 衆議院議席数 50~99 1585 8150 0.1945 0.2000 -0.0055
2政党条件 失業率 失業率前期比±0% 2750 8150 0.3374 0.3333 0.0041
2政党条件 失業率 失業率前期比プラス1% 2741 8150 0.3363 0.3333 0.0030
2政党条件 失業率 失業率前期比マイナス1% 2659 8150 0.3263 0.3333 -0.0071
3政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 4168 12645 0.3296 0.3333 -0.0037
3政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 4277 12645 0.3382 0.3333 0.0049
3政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 4200 12645 0.3321 0.3333 -0.0012
3政党条件 GDP成長率 GDP成長率±0% 4297 12645 0.3398 0.3333 0.0065
3政党条件 GDP成長率 GDP成長率プラス1% 4075 12645 0.3223 0.3333 -0.0111
3政党条件 GDP成長率 GDP成長率マイナス1% 4273 12645 0.3379 0.3333 0.0046
3政党条件 与野党地位 与党 4162 12645 0.3291 0.5000 -0.1709
3政党条件 与野党地位 野党 8483 12645 0.6709 0.5000 0.1709
3政党条件 日経平均株価 日経平均前月同期比プラス1000円 4177 12645 0.3303 0.3333 -0.0030
3政党条件 日経平均株価 日経平均前月同期比マイナス1000円 4284 12645 0.3388 0.3333 0.0055
3政党条件 日経平均株価 日経平均前月同期比変わらず 4184 12645 0.3309 0.3333 -0.0025
3政党条件 政策位置 中道 4113 12645 0.3253 0.3333 -0.0081
3政党条件 政策位置 右派・保守的 4306 12645 0.3405 0.3333 0.0072
3政党条件 政策位置 左派・革新的 4226 12645 0.3342 0.3333 0.0009
3政党条件 衆議院議席数 100~199 2105 12645 0.1665 0.2000 -0.0335
3政党条件 衆議院議席数 10~49 2802 12645 0.2216 0.2000 0.0216
3政党条件 衆議院議席数 10以下 2794 12645 0.2210 0.2000 0.0210
3政党条件 衆議院議席数 200以上 2157 12645 0.1706 0.2000 -0.0294
3政党条件 衆議院議席数 50~99 2787 12645 0.2204 0.2000 0.0204
3政党条件 失業率 失業率前期比±0% 4268 12645 0.3375 0.3333 0.0042
3政党条件 失業率 失業率前期比プラス1% 4167 12645 0.3295 0.3333 -0.0038
3政党条件 失業率 失業率前期比マイナス1% 4210 12645 0.3329 0.3333 -0.0004
4政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 6009 17640 0.3406 0.3333 0.0073
4政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 5824 17640 0.3302 0.3333 -0.0032
4政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 5807 17640 0.3292 0.3333 -0.0041
4政党条件 GDP成長率 GDP成長率±0% 5894 17640 0.3341 0.3333 0.0008
4政党条件 GDP成長率 GDP成長率プラス1% 5858 17640 0.3321 0.3333 -0.0012
4政党条件 GDP成長率 GDP成長率マイナス1% 5888 17640 0.3338 0.3333 0.0005
4政党条件 与野党地位 与党 4322 17640 0.2450 0.5000 -0.2550
4政党条件 与野党地位 野党 13318 17640 0.7550 0.5000 0.2550
4政党条件 日経平均株価 日経平均前月同期比プラス1000円 5814 17640 0.3296 0.3333 -0.0037
4政党条件 日経平均株価 日経平均前月同期比マイナス1000円 5931 17640 0.3362 0.3333 0.0029
4政党条件 日経平均株価 日経平均前月同期比変わらず 5895 17640 0.3342 0.3333 0.0009
4政党条件 政策位置 中道 5913 17640 0.3352 0.3333 0.0019
4政党条件 政策位置 右派・保守的 5757 17640 0.3264 0.3333 -0.0070
4政党条件 政策位置 左派・革新的 5970 17640 0.3384 0.3333 0.0051
4政党条件 衆議院議席数 100~199 2977 17640 0.1688 0.2000 -0.0312
4政党条件 衆議院議席数 10~49 4205 17640 0.2384 0.2000 0.0384
4政党条件 衆議院議席数 10以下 4058 17640 0.2300 0.2000 0.0300
4政党条件 衆議院議席数 200以上 2224 17640 0.1261 0.2000 -0.0739
4政党条件 衆議院議席数 50~99 4176 17640 0.2367 0.2000 0.0367
4政党条件 失業率 失業率前期比±0% 5889 17640 0.3338 0.3333 0.0005
4政党条件 失業率 失業率前期比プラス1% 5915 17640 0.3353 0.3333 0.0020
4政党条件 失業率 失業率前期比マイナス1% 5836 17640 0.3308 0.3333 -0.0025
5政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 6965 21050 0.3309 0.3333 -0.0025
5政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 6960 21050 0.3306 0.3333 -0.0027
5政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 7125 21050 0.3385 0.3333 0.0051
5政党条件 GDP成長率 GDP成長率±0% 7135 21050 0.3390 0.3333 0.0056
5政党条件 GDP成長率 GDP成長率プラス1% 6973 21050 0.3313 0.3333 -0.0021
5政党条件 GDP成長率 GDP成長率マイナス1% 6942 21050 0.3298 0.3333 -0.0035
5政党条件 与野党地位 与党 4193 21050 0.1992 0.5000 -0.3008
5政党条件 与野党地位 野党 16857 21050 0.8008 0.5000 0.3008
5政党条件 日経平均株価 日経平均前月同期比プラス1000円 6996 21050 0.3324 0.3333 -0.0010
5政党条件 日経平均株価 日経平均前月同期比マイナス1000円 6950 21050 0.3302 0.3333 -0.0032
5政党条件 日経平均株価 日経平均前月同期比変わらず 7104 21050 0.3375 0.3333 0.0041
5政党条件 政策位置 中道 7051 21050 0.3350 0.3333 0.0016
5政党条件 政策位置 右派・保守的 6963 21050 0.3308 0.3333 -0.0025
5政党条件 政策位置 左派・革新的 7036 21050 0.3343 0.3333 0.0009
5政党条件 衆議院議席数 100~199 2615 21050 0.1242 0.2000 -0.0758
5政党条件 衆議院議席数 10~49 6423 21050 0.3051 0.2000 0.1051
5政党条件 衆議院議席数 10以下 6338 21050 0.3011 0.2000 0.1011
5政党条件 衆議院議席数 200以上 2157 21050 0.1025 0.2000 -0.0975
5政党条件 衆議院議席数 50~99 3517 21050 0.1671 0.2000 -0.0329
5政党条件 失業率 失業率前期比±0% 6850 21050 0.3254 0.3333 -0.0079
5政党条件 失業率 失業率前期比プラス1% 7157 21050 0.3400 0.3333 0.0067
5政党条件 失業率 失業率前期比マイナス1% 7043 21050 0.3346 0.3333 0.0013

B.2 実験2(2026年)

図C4:回答者割付のLove plot

実験2仕様 <- study_specs$study2
実験2割付設計 <- make_balance_design(実験2仕様)
実験2SMD <- pairwise_smd_multiarm(実験2割付設計$long)
実験2最大SMD <- 実験2SMD %>%
  dplyr::group_by(variable, label) %>%
  dplyr::summarise(max_abs_smd = max(abs_smd, na.rm = TRUE), .groups = "drop")

Loveデータ <- 実験2SMD %>%
  dplyr::left_join(実験2最大SMD, by = c("variable", "label")) %>%
  dplyr::mutate(表示名 = stats::reorder(label, max_abs_smd))

図C4 <- ggplot2::ggplot(Loveデータ, ggplot2::aes(x = abs_smd, y = 表示名)) +
  ggplot2::geom_vline(xintercept = 0.10, linetype = "dashed", linewidth = 0.55) +
  ggplot2::geom_point(alpha = 0.30, size = 1.4, position = ggplot2::position_jitter(height = 0.10, width = 0)) +
  ggplot2::geom_point(
    data = 実験2最大SMD %>% dplyr::mutate(表示名 = stats::reorder(label, max_abs_smd)),
    ggplot2::aes(x = max_abs_smd, y = 表示名),
    inherit.aes = FALSE, shape = 21, fill = "white", size = 2.5, stroke = 0.8
  ) +
  ggplot2::labs(x = "条件間の絶対標準化平均差(|SMD|)", y = NULL,
                subtitle = "実験2(2026年):各点は条件ペア、白抜き点は最大絶対SMD") +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
図C4

表C5は図C4の各点に対応する。各行には比較する2条件の平均とSMDだけを残し、他条件に由来する構造的な欠損値は表示しない。

表C5 <- 実験2SMD %>%
  dplyr::transmute(
    変数 = label,
    比較 = paste0(condition_a, "政党条件-", condition_b, "政党条件"),
    `前者の平均` = round(mean_a, 3),
    `後者の平均` = round(mean_b, 3),
    `前者N` = n_a,
    `後者N` = n_b,
    SMD = round(smd, 3),
    `|SMD|` = round(abs_smd, 3)
  )
knitr::kable(表日本語(表C5), format = "html", row.names = FALSE)
変数 比較 前者の平均 後者の平均 前者N 後者N SMD |SMD|
年齢 2政党条件-3政党条件 42.000 41.814 711 1062 0.016 0.016
年齢:欠損 2政党条件-3政党条件 0.052 0.044 711 1062 0.036 0.036
4年制大学以上 2政党条件-3政党条件 0.591 0.571 711 1062 0.041 0.041
学歴:欠損 2政党条件-3政党条件 0.007 0.008 711 1062 -0.006 0.006
女性 2政党条件-3政党条件 0.308 0.298 711 1062 0.023 0.023
性別:欠損 2政党条件-3政党条件 0.010 0.011 711 1062 -0.014 0.014
世帯年収(対数) 2政党条件-3政党条件 5.956 6.018 711 1062 -0.044 0.044
支持政党:その他 2政党条件-3政党条件 0.003 0.001 711 1062 0.043 0.043
支持政党:れいわ新選組 2政党条件-3政党条件 0.013 0.021 711 1062 -0.063 0.063
支持政党:わからない 2政党条件-3政党条件 0.028 0.038 711 1062 -0.053 0.053
支持政党:チームみらい 2政党条件-3政党条件 0.059 0.047 711 1062 0.053 0.053
支持政党:中道改革連合 2政党条件-3政党条件 0.028 0.024 711 1062 0.029 0.029
支持政党:公明党 2政党条件-3政党条件 0.024 0.023 711 1062 0.009 0.009
支持政党:参政党 2政党条件-3政党条件 0.051 0.039 711 1062 0.058 0.058
支持政党:国民民主党 2政党条件-3政党条件 0.059 0.069 711 1062 -0.040 0.040
支持政党:支持政党なし 2政党条件-3政党条件 0.360 0.358 711 1062 0.005 0.005
支持政党:日本保守党 2政党条件-3政党条件 0.023 0.022 711 1062 0.006 0.006
支持政党:日本共産党 2政党条件-3政党条件 0.017 0.025 711 1062 -0.059 0.059
支持政党:日本維新の会 2政党条件-3政党条件 0.063 0.062 711 1062 0.005 0.005
支持政党:社会民主党 2政党条件-3政党条件 0.004 0.001 711 1062 0.065 0.065
支持政党:立憲民主党 2政党条件-3政党条件 0.045 0.040 711 1062 0.027 0.027
支持政党:答えたくない 2政党条件-3政党条件 0.020 0.017 711 1062 0.020 0.020
支持政党:自由民主党 2政党条件-3政党条件 0.204 0.216 711 1062 -0.029 0.029
年齢 2政党条件-4政党条件 42.000 42.459 711 1097 -0.041 0.041
年齢:欠損 2政党条件-4政党条件 0.052 0.055 711 1097 -0.012 0.012
4年制大学以上 2政党条件-4政党条件 0.591 0.599 711 1097 -0.017 0.017
学歴:欠損 2政党条件-4政党条件 0.007 0.011 711 1097 -0.041 0.041
女性 2政党条件-4政党条件 0.308 0.315 711 1097 -0.016 0.016
性別:欠損 2政党条件-4政党条件 0.010 0.004 711 1097 0.076 0.076
世帯年収(対数) 2政党条件-4政党条件 5.956 5.955 711 1097 0.001 0.001
支持政党:その他 2政党条件-4政党条件 0.003 0.003 711 1097 0.001 0.001
支持政党:れいわ新選組 2政党条件-4政党条件 0.013 0.016 711 1097 -0.031 0.031
支持政党:わからない 2政党条件-4政党条件 0.028 0.041 711 1097 -0.071 0.071
支持政党:チームみらい 2政党条件-4政党条件 0.059 0.056 711 1097 0.015 0.015
支持政党:中道改革連合 2政党条件-4政党条件 0.028 0.020 711 1097 0.053 0.053
支持政党:公明党 2政党条件-4政党条件 0.024 0.021 711 1097 0.020 0.020
支持政党:参政党 2政党条件-4政党条件 0.051 0.043 711 1097 0.037 0.037
支持政党:国民民主党 2政党条件-4政党条件 0.059 0.057 711 1097 0.011 0.011
支持政党:支持政党なし 2政党条件-4政党条件 0.360 0.356 711 1097 0.008 0.008
支持政党:日本保守党 2政党条件-4政党条件 0.023 0.027 711 1097 -0.031 0.031
支持政党:日本共産党 2政党条件-4政党条件 0.017 0.028 711 1097 -0.077 0.077
支持政党:日本維新の会 2政党条件-4政党条件 0.063 0.053 711 1097 0.045 0.045
支持政党:社会民主党 2政党条件-4政党条件 0.004 0.002 711 1097 0.044 0.044
支持政党:立憲民主党 2政党条件-4政党条件 0.045 0.040 711 1097 0.024 0.024
支持政党:答えたくない 2政党条件-4政党条件 0.020 0.014 711 1097 0.047 0.047
支持政党:自由民主党 2政党条件-4政党条件 0.204 0.223 711 1097 -0.047 0.047
年齢 2政党条件-5政党条件 42.000 42.447 711 1322 -0.039 0.039
年齢:欠損 2政党条件-5政党条件 0.052 0.047 711 1322 0.024 0.024
4年制大学以上 2政党条件-5政党条件 0.591 0.581 711 1322 0.020 0.020
学歴:欠損 2政党条件-5政党条件 0.007 0.008 711 1322 -0.015 0.015
女性 2政党条件-5政党条件 0.308 0.293 711 1322 0.033 0.033
性別:欠損 2政党条件-5政党条件 0.010 0.014 711 1322 -0.035 0.035
世帯年収(対数) 2政党条件-5政党条件 5.956 6.076 711 1322 -0.088 0.088
支持政党:その他 2政党条件-5政党条件 0.003 0.005 711 1322 -0.029 0.029
支持政党:れいわ新選組 2政党条件-5政党条件 0.013 0.016 711 1322 -0.027 0.027
支持政党:わからない 2政党条件-5政党条件 0.028 0.050 711 1322 -0.113 0.113
支持政党:チームみらい 2政党条件-5政党条件 0.059 0.057 711 1322 0.007 0.007
支持政党:中道改革連合 2政党条件-5政党条件 0.028 0.021 711 1322 0.045 0.045
支持政党:公明党 2政党条件-5政党条件 0.024 0.020 711 1322 0.029 0.029
支持政党:参政党 2政党条件-5政党条件 0.051 0.048 711 1322 0.014 0.014
支持政党:国民民主党 2政党条件-5政党条件 0.059 0.057 711 1322 0.007 0.007
支持政党:支持政党なし 2政党条件-5政党条件 0.360 0.328 711 1322 0.067 0.067
支持政党:日本保守党 2政党条件-5政党条件 0.023 0.030 711 1322 -0.048 0.048
支持政党:日本共産党 2政党条件-5政党条件 0.017 0.025 711 1322 -0.056 0.056
支持政党:日本維新の会 2政党条件-5政党条件 0.063 0.051 711 1322 0.054 0.054
支持政党:社会民主党 2政党条件-5政党条件 0.004 0.002 711 1322 0.034 0.034
支持政党:立憲民主党 2政党条件-5政党条件 0.045 0.045 711 1322 0.002 0.002
支持政党:答えたくない 2政党条件-5政党条件 0.020 0.024 711 1322 -0.031 0.031
支持政党:自由民主党 2政党条件-5政党条件 0.204 0.221 711 1322 -0.041 0.041
年齢 3政党条件-4政党条件 41.814 42.459 1062 1097 -0.057 0.057
年齢:欠損 3政党条件-4政党条件 0.044 0.055 1062 1097 -0.048 0.048
4年制大学以上 3政党条件-4政党条件 0.571 0.599 1062 1097 -0.057 0.057
学歴:欠損 3政党条件-4政党条件 0.008 0.011 1062 1097 -0.036 0.036
女性 3政党条件-4政党条件 0.298 0.315 1062 1097 -0.039 0.039
性別:欠損 3政党条件-4政党条件 0.011 0.004 1062 1097 0.089 0.089
世帯年収(対数) 3政党条件-4政党条件 6.018 5.955 1062 1097 0.044 0.044
支持政党:その他 3政党条件-4政党条件 0.001 0.003 1062 1097 -0.042 0.042
支持政党:れいわ新選組 3政党条件-4政党条件 0.021 0.016 1062 1097 0.032 0.032
支持政党:わからない 3政党条件-4政党条件 0.038 0.041 1062 1097 -0.017 0.017
支持政党:チームみらい 3政党条件-4政党条件 0.047 0.056 1062 1097 -0.039 0.039
支持政党:中道改革連合 3政党条件-4政党条件 0.024 0.020 1062 1097 0.024 0.024
支持政党:公明党 3政党条件-4政党条件 0.023 0.021 1062 1097 0.011 0.011
支持政党:参政党 3政党条件-4政党条件 0.039 0.043 1062 1097 -0.021 0.021
支持政党:国民民主党 3政党条件-4政党条件 0.069 0.057 1062 1097 0.050 0.050
支持政党:支持政党なし 3政党条件-4政党条件 0.358 0.356 1062 1097 0.003 0.003
支持政党:日本保守党 3政党条件-4政党条件 0.022 0.027 1062 1097 -0.037 0.037
支持政党:日本共産党 3政党条件-4政党条件 0.025 0.028 1062 1097 -0.018 0.018
支持政党:日本維新の会 3政党条件-4政党条件 0.062 0.053 1062 1097 0.040 0.040
支持政党:社会民主党 3政党条件-4政党条件 0.001 0.002 1062 1097 -0.024 0.024
支持政党:立憲民主党 3政党条件-4政党条件 0.040 0.040 1062 1097 -0.003 0.003
支持政党:答えたくない 3政党条件-4政党条件 0.017 0.014 1062 1097 0.027 0.027
支持政党:自由民主党 3政党条件-4政党条件 0.216 0.223 1062 1097 -0.019 0.019
年齢 3政党条件-5政党条件 41.814 42.447 1062 1322 -0.055 0.055
年齢:欠損 3政党条件-5政党条件 0.044 0.047 1062 1322 -0.013 0.013
4年制大学以上 3政党条件-5政党条件 0.571 0.581 1062 1322 -0.021 0.021
学歴:欠損 3政党条件-5政党条件 0.008 0.008 1062 1322 -0.009 0.009
女性 3政党条件-5政党条件 0.298 0.293 1062 1322 0.011 0.011
性別:欠損 3政党条件-5政党条件 0.011 0.014 1062 1322 -0.021 0.021
世帯年収(対数) 3政党条件-5政党条件 6.018 6.076 1062 1322 -0.045 0.045
支持政党:その他 3政党条件-5政党条件 0.001 0.005 1062 1322 -0.069 0.069
支持政党:れいわ新選組 3政党条件-5政党条件 0.021 0.016 1062 1322 0.036 0.036
支持政党:わからない 3政党条件-5政党条件 0.038 0.050 1062 1322 -0.060 0.060
支持政党:チームみらい 3政党条件-5政党条件 0.047 0.057 1062 1322 -0.047 0.047
支持政党:中道改革連合 3政党条件-5政党条件 0.024 0.021 1062 1322 0.016 0.016
支持政党:公明党 3政党条件-5政党条件 0.023 0.020 1062 1322 0.020 0.020
支持政党:参政党 3政党条件-5政党条件 0.039 0.048 1062 1322 -0.045 0.045
支持政党:国民民主党 3政党条件-5政党条件 0.069 0.057 1062 1322 0.046 0.046
支持政党:支持政党なし 3政党条件-5政党条件 0.358 0.328 1062 1322 0.062 0.062
支持政党:日本保守党 3政党条件-5政党条件 0.022 0.030 1062 1322 -0.054 0.054
支持政党:日本共産党 3政党条件-5政党条件 0.025 0.025 1062 1322 0.003 0.003
支持政党:日本維新の会 3政党条件-5政党条件 0.062 0.051 1062 1322 0.050 0.050
支持政党:社会民主党 3政党条件-5政党条件 0.001 0.002 1062 1322 -0.033 0.033
支持政党:立憲民主党 3政党条件-5政党条件 0.040 0.045 1062 1322 -0.025 0.025
支持政党:答えたくない 3政党条件-5政党条件 0.017 0.024 1062 1322 -0.051 0.051
支持政党:自由民主党 3政党条件-5政党条件 0.216 0.221 1062 1322 -0.013 0.013
年齢 4政党条件-5政党条件 42.459 42.447 1097 1322 0.001 0.001
年齢:欠損 4政党条件-5政党条件 0.055 0.047 1097 1322 0.035 0.035
4年制大学以上 4政党条件-5政党条件 0.599 0.581 1097 1322 0.037 0.037
学歴:欠損 4政党条件-5政党条件 0.011 0.008 1097 1322 0.027 0.027
女性 4政党条件-5政党条件 0.315 0.293 1097 1322 0.049 0.049
性別:欠損 4政党条件-5政党条件 0.004 0.014 1097 1322 -0.108 0.108
世帯年収(対数) 4政党条件-5政党条件 5.955 6.076 1097 1322 -0.086 0.086
支持政党:その他 4政党条件-5政党条件 0.003 0.005 1097 1322 -0.030 0.030
支持政党:れいわ新選組 4政党条件-5政党条件 0.016 0.016 1097 1322 0.004 0.004
支持政党:わからない 4政党条件-5政党条件 0.041 0.050 1097 1322 -0.043 0.043
支持政党:チームみらい 4政党条件-5政党条件 0.056 0.057 1097 1322 -0.008 0.008
支持政党:中道改革連合 4政党条件-5政党条件 0.020 0.021 1097 1322 -0.008 0.008
支持政党:公明党 4政党条件-5政党条件 0.021 0.020 1097 1322 0.009 0.009
支持政党:参政党 4政党条件-5政党条件 0.043 0.048 1097 1322 -0.023 0.023
支持政党:国民民主党 4政党条件-5政党条件 0.057 0.057 1097 1322 -0.004 0.004
支持政党:支持政党なし 4政党条件-5政党条件 0.356 0.328 1097 1322 0.059 0.059
支持政党:日本保守党 4政党条件-5政党条件 0.027 0.030 1097 1322 -0.017 0.017
支持政党:日本共産党 4政党条件-5政党条件 0.028 0.025 1097 1322 0.020 0.020
支持政党:日本維新の会 4政党条件-5政党条件 0.053 0.051 1097 1322 0.010 0.010
支持政党:社会民主党 4政党条件-5政党条件 0.002 0.002 1097 1322 -0.010 0.010
支持政党:立憲民主党 4政党条件-5政党条件 0.040 0.045 1097 1322 -0.022 0.022
支持政党:答えたくない 4政党条件-5政党条件 0.014 0.024 1097 1322 -0.077 0.077
支持政党:自由民主党 4政党条件-5政党条件 0.223 0.221 1097 1322 0.006 0.006

図C5:条件平均の45度線診断

図C5は図C4と同じ回答者レベルの割付バランスを、各共変量の条件平均を標準化したうえで2条件ずつ45度線と比較したものである。

対角線データ <- assignment_balance_results$study2$diagonal_data %>%
  dplyr::mutate(
    比較 = paste0(condition_a, "政党条件-", condition_b, "政党条件")
  )

ラベル対象 <- 対角線データ %>%
  dplyr::group_by(比較) %>%
  dplyr::slice_max(abs_diagonal_deviation, n = 3, with_ties = FALSE) %>%
  dplyr::ungroup()

軸範囲 <- max(abs(c(対角線データ$x_mean, 対角線データ$y_mean)), na.rm = TRUE)
軸範囲 <- max(0.10, 軸範囲 * 1.15)

図C5 <- ggplot2::ggplot(対角線データ, ggplot2::aes(x = x_mean, y = y_mean)) +
  ggplot2::geom_abline(intercept = 0, slope = 1, linetype = "dashed", linewidth = 0.60) +
  ggplot2::geom_hline(yintercept = 0, linewidth = 0.25) +
  ggplot2::geom_vline(xintercept = 0, linewidth = 0.25) +
  ggplot2::geom_point(shape = 21, fill = "white", size = 2.2) +
  ggplot2::geom_text(data = ラベル対象, ggplot2::aes(label = label), size = 2.6, check_overlap = TRUE, vjust = -0.7) +
  ggplot2::facet_wrap(~ 比較, ncol = 3) +
  ggplot2::coord_equal(xlim = c(-軸範囲, 軸範囲), ylim = c(-軸範囲, 軸範囲)) +
  ggplot2::labs(x = "左側条件の標準化共変量平均", y = "右側条件の標準化共変量平均") +
  ggplot2::theme_bw(base_size = 10.5) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
図C5

表C6 <- assignment_balance_results$study2$summary %>%
  dplyr::transmute(
    変数 = label,
    `2政党条件の平均` = round(mean_condition_2, 3),
    `3政党条件の平均` = round(mean_condition_3, 3),
    `4政党条件の平均` = round(mean_condition_4, 3),
    `5政党条件の平均` = round(mean_condition_5, 3),
    `最大|SMD|` = round(max_abs_smd, 3),
    `Holm補正p値` = signif(p_holm, 3)
  )
knitr::kable(表日本語(表C6), format = "html", row.names = FALSE)
変数 2政党条件の平均 3政党条件の平均 4政党条件の平均 5政党条件の平均 最大|SMD| Holm補正p値
支持政党:わからない 0.028 0.038 0.041 0.050 0.113 1
性別:欠損 0.010 0.011 0.004 0.014 0.108 1
世帯年収(対数) 5.956 6.018 5.955 6.076 0.088 1
支持政党:答えたくない 0.020 0.017 0.014 0.024 0.077 1
支持政党:日本共産党 0.017 0.025 0.028 0.025 0.077 1
支持政党:その他 0.003 0.001 0.003 0.005 0.069 1
支持政党:支持政党なし 0.360 0.358 0.356 0.328 0.067 1
支持政党:社会民主党 0.004 0.001 0.002 0.002 0.065 1
支持政党:れいわ新選組 0.013 0.021 0.016 0.016 0.063 1
支持政党:参政党 0.051 0.039 0.043 0.048 0.058 1
4年制大学以上 0.591 0.571 0.599 0.581 0.057 1
年齢 42.000 41.814 42.459 42.447 0.057 1
支持政党:日本維新の会 0.063 0.062 0.053 0.051 0.054 1
支持政党:日本保守党 0.023 0.022 0.027 0.030 0.054 1
支持政党:チームみらい 0.059 0.047 0.056 0.057 0.053 1
支持政党:中道改革連合 0.028 0.024 0.020 0.021 0.053 1
支持政党:国民民主党 0.059 0.069 0.057 0.057 0.050 1
女性 0.308 0.298 0.315 0.293 0.049 1
年齢:欠損 0.052 0.044 0.055 0.047 0.048 1
支持政党:自由民主党 0.204 0.216 0.223 0.221 0.047 1
学歴:欠損 0.007 0.008 0.011 0.008 0.041 1
支持政党:公明党 0.024 0.023 0.021 0.020 0.029 1
支持政党:立憲民主党 0.045 0.040 0.040 0.045 0.027 1

図C6:プロフィール属性水準の無作為提示

図C6以降は回答者の条件割付ではなく、各コンジョイント課題内で属性水準が設計どおり一様に提示されているかを確認するものである。

属性頻度 <- profile_randomization_results$study2$frequency %>%
  dplyr::mutate(
    属性 = 属性日本語(attribute),
    条件 = 条件日本語(party_n, "study2")
  )

表示ラベル <- 属性頻度 %>%
  dplyr::group_by(属性, 条件) %>%
  dplyr::slice_max(abs_deviation, n = 2, with_ties = FALSE) %>%
  dplyr::ungroup()

図C6 <- ggplot2::ggplot(属性頻度, ggplot2::aes(x = expected_share, y = observed_share, shape = 条件)) +
  ggplot2::geom_abline(intercept = 0, slope = 1, linetype = "dashed", linewidth = 0.65) +
  ggplot2::geom_point(size = 2.2, fill = "white") +
  ggplot2::geom_text(data = 表示ラベル, ggplot2::aes(label = level), size = 2.4, check_overlap = TRUE, vjust = -0.7) +
  ggplot2::facet_wrap(~ 属性, ncol = 3) +
  ggplot2::coord_equal() +
  ggplot2::labs(x = "設計上の期待比率", y = "観測比率", shape = "条件") +
  ggplot2::theme_bw(base_size = 10.5) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank(), legend.position = "bottom")
図C6

表C7 <- profile_randomization_results$study2$uniformity_tests %>%
  dplyr::transmute(
    条件 = 条件日本語(party_n, "study2"),
    属性 = 属性日本語(attribute),
    `カイ二乗値` = round(chi_square, 3),
    自由度 = df,
    p値 = signif(p_value, 3),
    `Holm補正p値` = signif(p_holm, 3),
    `最大絶対比率差` = round(max_abs_share_deviation, 4)
  )
knitr::kable(表日本語(表C7), format = "html", row.names = FALSE)
条件 属性 カイ二乗値 自由度 p値 Holm補正p値 最大絶対比率差
2政党条件 消費者物価指数(CPI) 1.667 2 0.43500 1.000 0.0070
2政党条件 GDP成長率 0.740 2 0.69100 1.000 0.0044
2政党条件 与野党地位 2.601 1 0.10700 1.000 0.0096
2政党条件 日経平均株価 9.289 2 0.00961 0.260 0.0158
2政党条件 政策位置 2.624 2 0.26900 1.000 0.0089
2政党条件 衆議院議席数 9.259 4 0.05490 1.000 0.0100
2政党条件 失業率 0.276 2 0.87100 1.000 0.0027
3政党条件 消費者物価指数(CPI) 0.285 2 0.86700 1.000 0.0018
3政党条件 GDP成長率 3.260 2 0.19600 1.000 0.0063
3政党条件 与野党地位 0.081 1 0.77500 1.000 0.0011
3政党条件 日経平均株価 0.390 2 0.82300 1.000 0.0023
3政党条件 政策位置 1.996 2 0.36900 1.000 0.0051
3政党条件 衆議院議席数 2.861 4 0.58100 1.000 0.0038
3政党条件 失業率 2.895 2 0.23500 1.000 0.0062
4政党条件 消費者物価指数(CPI) 1.732 2 0.42100 1.000 0.0041
4政党条件 GDP成長率 0.239 2 0.88700 1.000 0.0015
4政党条件 与野党地位 0.164 1 0.68500 1.000 0.0014
4政党条件 日経平均株価 9.409 2 0.00906 0.254 0.0097
4政党条件 政策位置 1.147 2 0.56400 1.000 0.0033
4政党条件 衆議院議席数 2.153 4 0.70800 1.000 0.0038
4政党条件 失業率 2.351 2 0.30900 1.000 0.0045
5政党条件 消費者物価指数(CPI) 0.564 2 0.75400 1.000 0.0018
5政党条件 GDP成長率 0.215 2 0.89800 1.000 0.0012
5政党条件 与野党地位 0.327 1 0.56700 1.000 0.0016
5政党条件 日経平均株価 2.328 2 0.31200 1.000 0.0039
5政党条件 政策位置 1.792 2 0.40800 1.000 0.0034
5政党条件 衆議院議席数 1.764 4 0.77900 1.000 0.0026
5政党条件 失業率 4.171 2 0.12400 1.000 0.0053
表C8 <- 属性頻度 %>%
  dplyr::transmute(
    条件,
    属性,
    水準 = level,
    観測数 = observed_n,
    総数 = total_n,
    観測比率 = round(observed_share, 4),
    期待比率 = round(expected_share, 4),
= round(deviation, 4)
  )
knitr::kable(表日本語(表C8), format = "html", row.names = FALSE)
条件 属性 水準 観測数 総数 観測比率 期待比率
2政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 2335 7110 0.3284 0.3333 -0.0049
2政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 2355 7110 0.3312 0.3333 -0.0021
2政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 2420 7110 0.3404 0.3333 0.0070
2政党条件 GDP成長率 GDP成長率±0% 2342 7110 0.3294 0.3333 -0.0039
2政党条件 GDP成長率 GDP成長率プラス1% 2401 7110 0.3377 0.3333 0.0044
2政党条件 GDP成長率 GDP成長率マイナス1% 2367 7110 0.3329 0.3333 -0.0004
2政党条件 与野党地位 与党 3623 7110 0.5096 0.5000 0.0096
2政党条件 与野党地位 野党 3487 7110 0.4904 0.5000 -0.0096
2政党条件 日経平均株価 日経平均前月同期比プラス1000円 2354 7110 0.3311 0.3333 -0.0023
2政党条件 日経平均株価 日経平均前月同期比マイナス1000円 2274 7110 0.3198 0.3333 -0.0135
2政党条件 日経平均株価 日経平均前月同期比変わらず 2482 7110 0.3491 0.3333 0.0158
2政党条件 政策位置 中道 2413 7110 0.3394 0.3333 0.0060
2政党条件 政策位置 右派・保守的 2390 7110 0.3361 0.3333 0.0028
2政党条件 政策位置 左派・革新的 2307 7110 0.3245 0.3333 -0.0089
2政党条件 衆議院議席数 100~199 1400 7110 0.1969 0.2000 -0.0031
2政党条件 衆議院議席数 10~49 1351 7110 0.1900 0.2000 -0.0100
2政党条件 衆議院議席数 10以下 1491 7110 0.2097 0.2000 0.0097
2政党条件 衆議院議席数 200以上 1398 7110 0.1966 0.2000 -0.0034
2政党条件 衆議院議席数 50~99 1470 7110 0.2068 0.2000 0.0068
2政党条件 失業率 失業率前期比±0% 2389 7110 0.3360 0.3333 0.0027
2政党条件 失業率 失業率前期比プラス1% 2353 7110 0.3309 0.3333 -0.0024
2政党条件 失業率 失業率前期比マイナス1% 2368 7110 0.3331 0.3333 -0.0003
3政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 5282 15930 0.3316 0.3333 -0.0018
3政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 5311 15930 0.3334 0.3333 0.0001
3政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 5337 15930 0.3350 0.3333 0.0017
3政党条件 GDP成長率 GDP成長率±0% 5394 15930 0.3386 0.3333 0.0053
3政党条件 GDP成長率 GDP成長率プラス1% 5210 15930 0.3271 0.3333 -0.0063
3政党条件 GDP成長率 GDP成長率マイナス1% 5326 15930 0.3343 0.3333 0.0010
3政党条件 与野党地位 与党 7947 15930 0.4989 0.5000 -0.0011
3政党条件 与野党地位 野党 7983 15930 0.5011 0.5000 0.0011
3政党条件 日経平均株価 日経平均前月同期比プラス1000円 5336 15930 0.3350 0.3333 0.0016
3政党条件 日経平均株価 日経平均前月同期比マイナス1000円 5320 15930 0.3340 0.3333 0.0006
3政党条件 日経平均株価 日経平均前月同期比変わらず 5274 15930 0.3311 0.3333 -0.0023
3政党条件 政策位置 中道 5392 15930 0.3385 0.3333 0.0051
3政党条件 政策位置 右派・保守的 5285 15930 0.3318 0.3333 -0.0016
3政党条件 政策位置 左派・革新的 5253 15930 0.3298 0.3333 -0.0036
3政党条件 衆議院議席数 100~199 3246 15930 0.2038 0.2000 0.0038
3政党条件 衆議院議席数 10~49 3149 15930 0.1977 0.2000 -0.0023
3政党条件 衆議院議席数 10以下 3201 15930 0.2009 0.2000 0.0009
3政党条件 衆議院議席数 200以上 3207 15930 0.2013 0.2000 0.0013
3政党条件 衆議院議席数 50~99 3127 15930 0.1963 0.2000 -0.0037
3政党条件 失業率 失業率前期比±0% 5212 15930 0.3272 0.3333 -0.0062
3政党条件 失業率 失業率前期比プラス1% 5381 15930 0.3378 0.3333 0.0045
3政党条件 失業率 失業率前期比マイナス1% 5337 15930 0.3350 0.3333 0.0017
4政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 7255 21940 0.3307 0.3333 -0.0027
4政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 7404 21940 0.3375 0.3333 0.0041
4政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 7281 21940 0.3319 0.3333 -0.0015
4政党条件 GDP成長率 GDP成長率±0% 7281 21940 0.3319 0.3333 -0.0015
4政党条件 GDP成長率 GDP成長率プラス1% 7339 21940 0.3345 0.3333 0.0012
4政党条件 GDP成長率 GDP成長率マイナス1% 7320 21940 0.3336 0.3333 0.0003
4政党条件 与野党地位 与党 11000 21940 0.5014 0.5000 0.0014
4政党条件 与野党地位 野党 10940 21940 0.4986 0.5000 -0.0014
4政党条件 日経平均株価 日経平均前月同期比プラス1000円 7229 21940 0.3295 0.3333 -0.0038
4政党条件 日経平均株価 日経平均前月同期比マイナス1000円 7185 21940 0.3275 0.3333 -0.0058
4政党条件 日経平均株価 日経平均前月同期比変わらず 7526 21940 0.3430 0.3333 0.0097
4政党条件 政策位置 中道 7296 21940 0.3325 0.3333 -0.0008
4政党条件 政策位置 右派・保守的 7259 21940 0.3309 0.3333 -0.0025
4政党条件 政策位置 左派・革新的 7385 21940 0.3366 0.3333 0.0033
4政党条件 衆議院議席数 100~199 4471 21940 0.2038 0.2000 0.0038
4政党条件 衆議院議席数 10~49 4371 21940 0.1992 0.2000 -0.0008
4政党条件 衆議院議席数 10以下 4389 21940 0.2000 0.2000 0.0000
4政党条件 衆議院議席数 200以上 4358 21940 0.1986 0.2000 -0.0014
4政党条件 衆議院議席数 50~99 4351 21940 0.1983 0.2000 -0.0017
4政党条件 失業率 失業率前期比±0% 7412 21940 0.3378 0.3333 0.0045
4政党条件 失業率 失業率前期比プラス1% 7228 21940 0.3294 0.3333 -0.0039
4政党条件 失業率 失業率前期比マイナス1% 7300 21940 0.3327 0.3333 -0.0006
5政党条件 消費者物価指数(CPI) CPI前期比±0ポイント 11075 33050 0.3351 0.3333 0.0018
5政党条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 11011 33050 0.3332 0.3333 -0.0002
5政党条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 10964 33050 0.3317 0.3333 -0.0016
5政党条件 GDP成長率 GDP成長率±0% 11038 33050 0.3340 0.3333 0.0006
5政党条件 GDP成長率 GDP成長率プラス1% 10977 33050 0.3321 0.3333 -0.0012
5政党条件 GDP成長率 GDP成長率マイナス1% 11035 33050 0.3339 0.3333 0.0006
5政党条件 与野党地位 与党 16473 33050 0.4984 0.5000 -0.0016
5政党条件 与野党地位 野党 16577 33050 0.5016 0.5000 0.0016
5政党条件 日経平均株価 日経平均前月同期比プラス1000円 11056 33050 0.3345 0.3333 0.0012
5政党条件 日経平均株価 日経平均前月同期比マイナス1000円 11105 33050 0.3360 0.3333 0.0027
5政党条件 日経平均株価 日経平均前月同期比変わらず 10889 33050 0.3295 0.3333 -0.0039
5政党条件 政策位置 中道 10985 33050 0.3324 0.3333 -0.0010
5政党条件 政策位置 右派・保守的 11128 33050 0.3367 0.3333 0.0034
5政党条件 政策位置 左派・革新的 10937 33050 0.3309 0.3333 -0.0024
5政党条件 衆議院議席数 100~199 6589 33050 0.1994 0.2000 -0.0006
5政党条件 衆議院議席数 10~49 6697 33050 0.2026 0.2000 0.0026
5政党条件 衆議院議席数 10以下 6550 33050 0.1982 0.2000 -0.0018
5政党条件 衆議院議席数 200以上 6611 33050 0.2000 0.2000 0.0000
5政党条件 衆議院議席数 50~99 6603 33050 0.1998 0.2000 -0.0002
5政党条件 失業率 失業率前期比±0% 11191 33050 0.3386 0.3333 0.0053
5政党条件 失業率 失業率前期比プラス1% 10916 33050 0.3303 0.3333 -0.0030
5政党条件 失業率 失業率前期比マイナス1% 10943 33050 0.3311 0.3333 -0.0022

B.3 実験3(2026年)

図C7:回答者割付のLove plot

実験3仕様 <- study_specs$study3
実験3割付設計 <- make_balance_design(実験3仕様)
実験3SMD <- pairwise_smd_multiarm(実験3割付設計$long)
実験3最大SMD <- 実験3SMD %>%
  dplyr::group_by(variable, label) %>%
  dplyr::summarise(max_abs_smd = max(abs_smd, na.rm = TRUE), .groups = "drop")

Loveデータ <- 実験3SMD %>%
  dplyr::left_join(実験3最大SMD, by = c("variable", "label")) %>%
  dplyr::mutate(表示名 = stats::reorder(label, max_abs_smd))

図C7 <- ggplot2::ggplot(Loveデータ, ggplot2::aes(x = abs_smd, y = 表示名)) +
  ggplot2::geom_vline(xintercept = 0.10, linetype = "dashed", linewidth = 0.55) +
  ggplot2::geom_point(alpha = 0.30, size = 1.4, position = ggplot2::position_jitter(height = 0.10, width = 0)) +
  ggplot2::geom_point(
    data = 実験3最大SMD %>% dplyr::mutate(表示名 = stats::reorder(label, max_abs_smd)),
    ggplot2::aes(x = max_abs_smd, y = 表示名),
    inherit.aes = FALSE, shape = 21, fill = "white", size = 2.5, stroke = 0.8
  ) +
  ggplot2::labs(x = "条件間の絶対標準化平均差(|SMD|)", y = NULL,
                subtitle = "実験3(2026年):各点は条件ペア、白抜き点は最大絶対SMD") +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
図C7

表C9は図C7の各点に対応する。

表C9 <- 実験3SMD %>%
  dplyr::transmute(
    変数 = label,
    比較 = paste0(condition_a, "選択肢条件-", condition_b, "選択肢条件"),
    `前者の平均` = round(mean_a, 3),
    `後者の平均` = round(mean_b, 3),
    `前者N` = n_a,
    `後者N` = n_b,
    SMD = round(smd, 3),
    `|SMD|` = round(abs_smd, 3)
  )
knitr::kable(表日本語(表C9), format = "html", row.names = FALSE)
変数 比較 前者の平均 後者の平均 前者N 後者N SMD |SMD|
年齢 2選択肢条件-3選択肢条件 41.246 42.353 716 939 -0.097 0.097
年齢:欠損 2選択肢条件-3選択肢条件 0.052 0.052 716 939 -0.002 0.002
4年制大学以上 2選択肢条件-3選択肢条件 0.609 0.600 716 939 0.019 0.019
学歴:欠損 2選択肢条件-3選択肢条件 0.007 0.009 716 939 -0.018 0.018
女性 2選択肢条件-3選択肢条件 0.246 0.298 716 939 -0.118 0.118
性別:欠損 2選択肢条件-3選択肢条件 0.020 0.012 716 939 0.063 0.063
世帯年収(対数) 2選択肢条件-3選択肢条件 5.919 6.034 716 939 -0.079 0.079
支持政党:その他 2選択肢条件-3選択肢条件 0.003 0.002 716 939 0.013 0.013
支持政党:れいわ新選組 2選択肢条件-3選択肢条件 0.015 0.013 716 939 0.022 0.022
支持政党:わからない 2選択肢条件-3選択肢条件 0.038 0.049 716 939 -0.055 0.055
支持政党:チームみらい 2選択肢条件-3選択肢条件 0.042 0.040 716 939 0.007 0.007
支持政党:中道改革連合 2選択肢条件-3選択肢条件 0.032 0.024 716 939 0.046 0.046
支持政党:公明党 2選択肢条件-3選択肢条件 0.011 0.011 716 939 0.005 0.005
支持政党:参政党 2選択肢条件-3選択肢条件 0.042 0.049 716 939 -0.034 0.034
支持政党:国民民主党 2選択肢条件-3選択肢条件 0.068 0.081 716 939 -0.048 0.048
支持政党:支持政党なし 2選択肢条件-3選択肢条件 0.365 0.357 716 939 0.016 0.016
支持政党:日本保守党 2選択肢条件-3選択肢条件 0.025 0.015 716 939 0.073 0.073
支持政党:日本共産党 2選択肢条件-3選択肢条件 0.022 0.014 716 939 0.064 0.064
支持政党:日本維新の会 2選択肢条件-3選択肢条件 0.053 0.049 716 939 0.019 0.019
支持政党:社会民主党 2選択肢条件-3選択肢条件 0.003 0.003 716 939 -0.007 0.007
支持政党:立憲民主党 2選択肢条件-3選択肢条件 0.036 0.040 716 939 -0.022 0.022
支持政党:答えたくない 2選択肢条件-3選択肢条件 0.017 0.019 716 939 -0.018 0.018
支持政党:自由民主党 2選択肢条件-3選択肢条件 0.228 0.233 716 939 -0.013 0.013
地域:17 2選択肢条件-3選択肢条件 0.145 0.153 716 939 -0.023 0.023
地域:27 2選択肢条件-3選択肢条件 0.214 0.201 716 939 0.031 0.031
地域:35 2選択肢条件-3選択肢条件 0.085 0.085 716 939 0.000 0.000
地域:45 2選択肢条件-3選択肢条件 0.087 0.081 716 939 0.020 0.020
地域:9 2選択肢条件-3選択肢条件 0.383 0.396 716 939 -0.028 0.028
左右自己位置づけ 2選択肢条件-3選択肢条件 5.430 5.384 716 939 0.025 0.025
左右自己位置づけ:欠損 2選択肢条件-3選択肢条件 0.080 0.096 716 939 -0.057 0.057
年齢 2選択肢条件-4選択肢条件 41.246 42.935 716 1063 -0.145 0.145
年齢:欠損 2選択肢条件-4選択肢条件 0.052 0.047 716 1063 0.021 0.021
4年制大学以上 2選択肢条件-4選択肢条件 0.609 0.583 716 1063 0.052 0.052
学歴:欠損 2選択肢条件-4選択肢条件 0.007 0.008 716 1063 -0.006 0.006
女性 2選択肢条件-4選択肢条件 0.246 0.285 716 1063 -0.089 0.089
性別:欠損 2選択肢条件-4選択肢条件 0.020 0.014 716 1063 0.042 0.042
世帯年収(対数) 2選択肢条件-4選択肢条件 5.919 5.964 716 1063 -0.030 0.030
支持政党:その他 2選択肢条件-4選択肢条件 0.003 0.001 716 1063 0.043 0.043
支持政党:れいわ新選組 2選択肢条件-4選択肢条件 0.015 0.014 716 1063 0.010 0.010
支持政党:わからない 2選択肢条件-4選択肢条件 0.038 0.040 716 1063 -0.014 0.014
支持政党:チームみらい 2選択肢条件-4選択肢条件 0.042 0.048 716 1063 -0.029 0.029
支持政党:中道改革連合 2選択肢条件-4選択肢条件 0.032 0.032 716 1063 0.001 0.001
支持政党:公明党 2選択肢条件-4選択肢条件 0.011 0.009 716 1063 0.017 0.017
支持政党:参政党 2選択肢条件-4選択肢条件 0.042 0.040 716 1063 0.012 0.012
支持政党:国民民主党 2選択肢条件-4選択肢条件 0.068 0.066 716 1063 0.010 0.010
支持政党:支持政党なし 2選択肢条件-4選択肢条件 0.365 0.348 716 1063 0.034 0.034
支持政党:日本保守党 2選択肢条件-4選択肢条件 0.025 0.024 716 1063 0.011 0.011
支持政党:日本共産党 2選択肢条件-4選択肢条件 0.022 0.021 716 1063 0.011 0.011
支持政党:日本維新の会 2選択肢条件-4選択肢条件 0.053 0.060 716 1063 -0.031 0.031
支持政党:社会民主党 2選択肢条件-4選択肢条件 0.003 0.004 716 1063 -0.017 0.017
支持政党:立憲民主党 2選択肢条件-4選択肢条件 0.036 0.035 716 1063 0.008 0.008
支持政党:答えたくない 2選択肢条件-4選択肢条件 0.017 0.020 716 1063 -0.022 0.022
支持政党:自由民主党 2選択肢条件-4選択肢条件 0.228 0.239 716 1063 -0.027 0.027
地域:17 2選択肢条件-4選択肢条件 0.145 0.165 716 1063 -0.054 0.054
地域:27 2選択肢条件-4選択肢条件 0.214 0.200 716 1063 0.033 0.033
地域:35 2選択肢条件-4選択肢条件 0.085 0.092 716 1063 -0.025 0.025
地域:45 2選択肢条件-4選択肢条件 0.087 0.073 716 1063 0.049 0.049
地域:9 2選択肢条件-4選択肢条件 0.383 0.365 716 1063 0.037 0.037
左右自己位置づけ 2選択肢条件-4選択肢条件 5.430 5.373 716 1063 0.031 0.031
左右自己位置づけ:欠損 2選択肢条件-4選択肢条件 0.080 0.076 716 1063 0.013 0.013
年齢 2選択肢条件-5選択肢条件 41.246 43.582 716 1314 -0.203 0.203
年齢:欠損 2選択肢条件-5選択肢条件 0.052 0.042 716 1314 0.046 0.046
4年制大学以上 2選択肢条件-5選択肢条件 0.609 0.561 716 1314 0.098 0.098
学歴:欠損 2選択肢条件-5選択肢条件 0.007 0.010 716 1314 -0.032 0.032
女性 2選択肢条件-5選択肢条件 0.246 0.271 716 1314 -0.057 0.057
性別:欠損 2選択肢条件-5選択肢条件 0.020 0.015 716 1314 0.033 0.033
世帯年収(対数) 2選択肢条件-5選択肢条件 5.919 5.990 716 1314 -0.050 0.050
支持政党:その他 2選択肢条件-5選択肢条件 0.003 0.003 716 1314 -0.005 0.005
支持政党:れいわ新選組 2選択肢条件-5選択肢条件 0.015 0.018 716 1314 -0.023 0.023
支持政党:わからない 2選択肢条件-5選択肢条件 0.038 0.036 716 1314 0.010 0.010
支持政党:チームみらい 2選択肢条件-5選択肢条件 0.042 0.051 716 1314 -0.043 0.043
支持政党:中道改革連合 2選択肢条件-5選択肢条件 0.032 0.030 716 1314 0.010 0.010
支持政党:公明党 2選択肢条件-5選択肢条件 0.011 0.012 716 1314 -0.009 0.009
支持政党:参政党 2選択肢条件-5選択肢条件 0.042 0.040 716 1314 0.012 0.012
支持政党:国民民主党 2選択肢条件-5選択肢条件 0.068 0.069 716 1314 -0.003 0.003
支持政党:支持政党なし 2選択肢条件-5選択肢条件 0.365 0.340 716 1314 0.051 0.051
支持政党:日本保守党 2選択肢条件-5選択肢条件 0.025 0.024 716 1314 0.005 0.005
支持政党:日本共産党 2選択肢条件-5選択肢条件 0.022 0.021 716 1314 0.012 0.012
支持政党:日本維新の会 2選択肢条件-5選択肢条件 0.053 0.046 716 1314 0.034 0.034
支持政党:社会民主党 2選択肢条件-5選択肢条件 0.003 0.005 716 1314 -0.029 0.029
支持政党:立憲民主党 2選択肢条件-5選択肢条件 0.036 0.048 716 1314 -0.058 0.058
支持政党:答えたくない 2選択肢条件-5選択肢条件 0.017 0.021 716 1314 -0.028 0.028
支持政党:自由民主党 2選択肢条件-5選択肢条件 0.228 0.237 716 1314 -0.021 0.021
地域:17 2選択肢条件-5選択肢条件 0.145 0.170 716 1314 -0.067 0.067
地域:27 2選択肢条件-5選択肢条件 0.214 0.196 716 1314 0.043 0.043
地域:35 2選択肢条件-5選択肢条件 0.085 0.074 716 1314 0.042 0.042
地域:45 2選択肢条件-5選択肢条件 0.087 0.091 716 1314 -0.014 0.014
地域:9 2選択肢条件-5選択肢条件 0.383 0.364 716 1314 0.039 0.039
左右自己位置づけ 2選択肢条件-5選択肢条件 5.430 5.414 716 1314 0.009 0.009
左右自己位置づけ:欠損 2選択肢条件-5選択肢条件 0.080 0.088 716 1314 -0.029 0.029
年齢 3選択肢条件-4選択肢条件 42.353 42.935 939 1063 -0.051 0.051
年齢:欠損 3選択肢条件-4選択肢条件 0.052 0.047 939 1063 0.024 0.024
4年制大学以上 3選択肢条件-4選択肢条件 0.600 0.583 939 1063 0.033 0.033
学歴:欠損 3選択肢条件-4選択肢条件 0.009 0.008 939 1063 0.011 0.011
女性 3選択肢条件-4選択肢条件 0.298 0.285 939 1063 0.029 0.029
性別:欠損 3選択肢条件-4選択肢条件 0.012 0.014 939 1063 -0.021 0.021
世帯年収(対数) 3選択肢条件-4選択肢条件 6.034 5.964 939 1063 0.049 0.049
支持政党:その他 3選択肢条件-4選択肢条件 0.002 0.001 939 1063 0.030 0.030
支持政党:れいわ新選組 3選択肢条件-4選択肢条件 0.013 0.014 939 1063 -0.012 0.012
支持政党:わからない 3選択肢条件-4選択肢条件 0.049 0.040 939 1063 0.041 0.041
支持政党:チームみらい 3選択肢条件-4選択肢条件 0.040 0.048 939 1063 -0.037 0.037
支持政党:中道改革連合 3選択肢条件-4選択肢条件 0.024 0.032 939 1063 -0.045 0.045
支持政党:公明党 3選択肢条件-4選択肢条件 0.011 0.009 939 1063 0.012 0.012
支持政党:参政党 3選択肢条件-4選択肢条件 0.049 0.040 939 1063 0.046 0.046
支持政党:国民民主党 3選択肢条件-4選択肢条件 0.081 0.066 939 1063 0.058 0.058
支持政党:支持政党なし 3選択肢条件-4選択肢条件 0.357 0.348 939 1063 0.018 0.018
支持政党:日本保守党 3選択肢条件-4選択肢条件 0.015 0.024 939 1063 -0.063 0.063
支持政党:日本共産党 3選択肢条件-4選択肢条件 0.014 0.021 939 1063 -0.053 0.053
支持政党:日本維新の会 3選択肢条件-4選択肢条件 0.049 0.060 939 1063 -0.049 0.049
支持政党:社会民主党 3選択肢条件-4選択肢条件 0.003 0.004 939 1063 -0.010 0.010
支持政党:立憲民主党 3選択肢条件-4選択肢条件 0.040 0.035 939 1063 0.030 0.030
支持政党:答えたくない 3選択肢条件-4選択肢条件 0.019 0.020 939 1063 -0.004 0.004
支持政党:自由民主党 3選択肢条件-4選択肢条件 0.233 0.239 939 1063 -0.013 0.013
地域:17 3選択肢条件-4選択肢条件 0.153 0.165 939 1063 -0.031 0.031
地域:27 3選択肢条件-4選択肢条件 0.201 0.200 939 1063 0.002 0.002
地域:35 3選択肢条件-4選択肢条件 0.085 0.092 939 1063 -0.025 0.025
地域:45 3選択肢条件-4選択肢条件 0.081 0.073 939 1063 0.028 0.028
地域:9 3選択肢条件-4選択肢条件 0.396 0.365 939 1063 0.064 0.064
左右自己位置づけ 3選択肢条件-4選択肢条件 5.384 5.373 939 1063 0.006 0.006
左右自己位置づけ:欠損 3選択肢条件-4選択肢条件 0.096 0.076 939 1063 0.070 0.070
年齢 3選択肢条件-5選択肢条件 42.353 43.582 939 1314 -0.108 0.108
年齢:欠損 3選択肢条件-5選択肢条件 0.052 0.042 939 1314 0.049 0.049
4年制大学以上 3選択肢条件-5選択肢条件 0.600 0.561 939 1314 0.078 0.078
学歴:欠損 3選択肢条件-5選択肢条件 0.009 0.010 939 1314 -0.014 0.014
女性 3選択肢条件-5選択肢条件 0.298 0.271 939 1314 0.060 0.060
性別:欠損 3選択肢条件-5選択肢条件 0.012 0.015 939 1314 -0.030 0.030
世帯年収(対数) 3選択肢条件-5選択肢条件 6.034 5.990 939 1314 0.031 0.031
支持政党:その他 3選択肢条件-5選択肢条件 0.002 0.003 939 1314 -0.018 0.018
支持政党:れいわ新選組 3選択肢条件-5選択肢条件 0.013 0.018 939 1314 -0.044 0.044
支持政党:わからない 3選択肢条件-5選択肢条件 0.049 0.036 939 1314 0.066 0.066
支持政党:チームみらい 3選択肢条件-5選択肢条件 0.040 0.051 939 1314 -0.050 0.050
支持政党:中道改革連合 3選択肢条件-5選択肢条件 0.024 0.030 939 1314 -0.036 0.036
支持政党:公明党 3選択肢条件-5選択肢条件 0.011 0.012 939 1314 -0.014 0.014
支持政党:参政党 3選択肢条件-5選択肢条件 0.049 0.040 939 1314 0.046 0.046
支持政党:国民民主党 3選択肢条件-5選択肢条件 0.081 0.069 939 1314 0.044 0.044
支持政党:支持政党なし 3選択肢条件-5選択肢条件 0.357 0.340 939 1314 0.035 0.035
支持政党:日本保守党 3選択肢条件-5選択肢条件 0.015 0.024 939 1314 -0.068 0.068
支持政党:日本共産党 3選択肢条件-5選択肢条件 0.014 0.021 939 1314 -0.052 0.052
支持政党:日本維新の会 3選択肢条件-5選択肢条件 0.049 0.046 939 1314 0.016 0.016
支持政党:社会民主党 3選択肢条件-5選択肢条件 0.003 0.005 939 1314 -0.022 0.022
支持政党:立憲民主党 3選択肢条件-5選択肢条件 0.040 0.048 939 1314 -0.036 0.036
支持政党:答えたくない 3選択肢条件-5選択肢条件 0.019 0.021 939 1314 -0.010 0.010
支持政党:自由民主党 3選択肢条件-5選択肢条件 0.233 0.237 939 1314 -0.008 0.008
地域:17 3選択肢条件-5選択肢条件 0.153 0.170 939 1314 -0.044 0.044
地域:27 3選択肢条件-5選択肢条件 0.201 0.196 939 1314 0.012 0.012
地域:35 3選択肢条件-5選択肢条件 0.085 0.074 939 1314 0.042 0.042
地域:45 3選択肢条件-5選択肢条件 0.081 0.091 939 1314 -0.034 0.034
地域:9 3選択肢条件-5選択肢条件 0.396 0.364 939 1314 0.067 0.067
左右自己位置づけ 3選択肢条件-5選択肢条件 5.384 5.414 939 1314 -0.017 0.017
左右自己位置づけ:欠損 3選択肢条件-5選択肢条件 0.096 0.088 939 1314 0.029 0.029
年齢 4選択肢条件-5選択肢条件 42.935 43.582 1063 1314 -0.056 0.056
年齢:欠損 4選択肢条件-5選択肢条件 0.047 0.042 1063 1314 0.025 0.025
4年制大学以上 4選択肢条件-5選択肢条件 0.583 0.561 1063 1314 0.045 0.045
学歴:欠損 4選択肢条件-5選択肢条件 0.008 0.010 1063 1314 -0.025 0.025
女性 4選択肢条件-5選択肢条件 0.285 0.271 1063 1314 0.031 0.031
性別:欠損 4選択肢条件-5選択肢条件 0.014 0.015 1063 1314 -0.009 0.009
世帯年収(対数) 4選択肢条件-5選択肢条件 5.964 5.990 1063 1314 -0.019 0.019
支持政党:その他 4選択肢条件-5選択肢条件 0.001 0.003 1063 1314 -0.047 0.047
支持政党:れいわ新選組 4選択肢条件-5選択肢条件 0.014 0.018 1063 1314 -0.033 0.033
支持政党:わからない 4選択肢条件-5選択肢条件 0.040 0.036 1063 1314 0.024 0.024
支持政党:チームみらい 4選択肢条件-5選択肢条件 0.048 0.051 1063 1314 -0.014 0.014
支持政党:中道改革連合 4選択肢条件-5選択肢条件 0.032 0.030 1063 1314 0.009 0.009
支持政党:公明党 4選択肢条件-5選択肢条件 0.009 0.012 1063 1314 -0.027 0.027
支持政党:参政党 4選択肢条件-5選択肢条件 0.040 0.040 1063 1314 0.000 0.000
支持政党:国民民主党 4選択肢条件-5選択肢条件 0.066 0.069 1063 1314 -0.014 0.014
支持政党:支持政党なし 4選択肢条件-5選択肢条件 0.348 0.340 1063 1314 0.017 0.017
支持政党:日本保守党 4選択肢条件-5選択肢条件 0.024 0.024 1063 1314 -0.005 0.005
支持政党:日本共産党 4選択肢条件-5選択肢条件 0.021 0.021 1063 1314 0.001 0.001
支持政党:日本維新の会 4選択肢条件-5選択肢条件 0.060 0.046 1063 1314 0.065 0.065
支持政党:社会民主党 4選択肢条件-5選択肢条件 0.004 0.005 1063 1314 -0.012 0.012
支持政党:立憲民主党 4選択肢条件-5選択肢条件 0.035 0.048 1063 1314 -0.066 0.066
支持政党:答えたくない 4選択肢条件-5選択肢条件 0.020 0.021 1063 1314 -0.006 0.006
支持政党:自由民主党 4選択肢条件-5選択肢条件 0.239 0.237 1063 1314 0.005 0.005
地域:17 4選択肢条件-5選択肢条件 0.165 0.170 1063 1314 -0.014 0.014
地域:27 4選択肢条件-5選択肢条件 0.200 0.196 1063 1314 0.010 0.010
地域:35 4選択肢条件-5選択肢条件 0.092 0.074 1063 1314 0.067 0.067
地域:45 4選択肢条件-5選択肢条件 0.073 0.091 1063 1314 -0.063 0.063
地域:9 4選択肢条件-5選択肢条件 0.365 0.364 1063 1314 0.003 0.003
左右自己位置づけ 4選択肢条件-5選択肢条件 5.373 5.414 1063 1314 -0.022 0.022
左右自己位置づけ:欠損 4選択肢条件-5選択肢条件 0.076 0.088 1063 1314 -0.041 0.041

図C8:条件平均の45度線診断

図C8は図C7と同じ回答者レベルの割付バランスを、各共変量の条件平均を標準化したうえで2条件ずつ45度線と比較したものである。

対角線データ <- assignment_balance_results$study3$diagonal_data %>%
  dplyr::mutate(
    比較 = paste0(condition_a, "選択肢条件-", condition_b, "選択肢条件")
  )

ラベル対象 <- 対角線データ %>%
  dplyr::group_by(比較) %>%
  dplyr::slice_max(abs_diagonal_deviation, n = 3, with_ties = FALSE) %>%
  dplyr::ungroup()

軸範囲 <- max(abs(c(対角線データ$x_mean, 対角線データ$y_mean)), na.rm = TRUE)
軸範囲 <- max(0.10, 軸範囲 * 1.15)

図C8 <- ggplot2::ggplot(対角線データ, ggplot2::aes(x = x_mean, y = y_mean)) +
  ggplot2::geom_abline(intercept = 0, slope = 1, linetype = "dashed", linewidth = 0.60) +
  ggplot2::geom_hline(yintercept = 0, linewidth = 0.25) +
  ggplot2::geom_vline(xintercept = 0, linewidth = 0.25) +
  ggplot2::geom_point(shape = 21, fill = "white", size = 2.2) +
  ggplot2::geom_text(data = ラベル対象, ggplot2::aes(label = label), size = 2.6, check_overlap = TRUE, vjust = -0.7) +
  ggplot2::facet_wrap(~ 比較, ncol = 3) +
  ggplot2::coord_equal(xlim = c(-軸範囲, 軸範囲), ylim = c(-軸範囲, 軸範囲)) +
  ggplot2::labs(x = "左側条件の標準化共変量平均", y = "右側条件の標準化共変量平均") +
  ggplot2::theme_bw(base_size = 10.5) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
図C8

表C10 <- assignment_balance_results$study3$summary %>%
  dplyr::transmute(
    変数 = label,
    `2選択肢条件の平均` = round(mean_condition_2, 3),
    `3選択肢条件の平均` = round(mean_condition_3, 3),
    `4選択肢条件の平均` = round(mean_condition_4, 3),
    `5選択肢条件の平均` = round(mean_condition_5, 3),
    `最大|SMD|` = round(max_abs_smd, 3),
    `Holm補正p値` = signif(p_holm, 3)
  )
knitr::kable(表日本語(表C10), format = "html", row.names = FALSE)
変数 2選択肢条件の平均 3選択肢条件の平均 4選択肢条件の平均 5選択肢条件の平均 最大|SMD| Holm補正p値
年齢 41.246 42.353 42.935 43.582 0.203 0.00415
女性 0.246 0.298 0.285 0.271 0.118 1.00000
4年制大学以上 0.609 0.600 0.583 0.561 0.098 1.00000
世帯年収(対数) 5.919 6.034 5.964 5.990 0.079 1.00000
支持政党:日本保守党 0.025 0.015 0.024 0.024 0.073 1.00000
左右自己位置づけ:欠損 0.080 0.096 0.076 0.088 0.070 1.00000
地域:17 0.145 0.153 0.165 0.170 0.067 1.00000
地域:9 0.383 0.396 0.365 0.364 0.067 1.00000
地域:35 0.085 0.085 0.092 0.074 0.067 1.00000
支持政党:立憲民主党 0.036 0.040 0.035 0.048 0.066 1.00000
支持政党:わからない 0.038 0.049 0.040 0.036 0.066 1.00000
支持政党:日本維新の会 0.053 0.049 0.060 0.046 0.065 1.00000
支持政党:日本共産党 0.022 0.014 0.021 0.021 0.064 1.00000
性別:欠損 0.020 0.012 0.014 0.015 0.063 1.00000
地域:45 0.087 0.081 0.073 0.091 0.063 1.00000
支持政党:国民民主党 0.068 0.081 0.066 0.069 0.058 1.00000
支持政党:支持政党なし 0.365 0.357 0.348 0.340 0.051 1.00000
支持政党:チームみらい 0.042 0.040 0.048 0.051 0.050 1.00000
年齢:欠損 0.052 0.052 0.047 0.042 0.049 1.00000
支持政党:その他 0.003 0.002 0.001 0.003 0.047 1.00000
支持政党:参政党 0.042 0.049 0.040 0.040 0.046 1.00000
支持政党:中道改革連合 0.032 0.024 0.032 0.030 0.046 1.00000
支持政党:れいわ新選組 0.015 0.013 0.014 0.018 0.044 1.00000
地域:27 0.214 0.201 0.200 0.196 0.043 1.00000
学歴:欠損 0.007 0.009 0.008 0.010 0.032 1.00000
左右自己位置づけ 5.430 5.384 5.373 5.414 0.031 1.00000
支持政党:社会民主党 0.003 0.003 0.004 0.005 0.029 1.00000
支持政党:答えたくない 0.017 0.019 0.020 0.021 0.028 1.00000
支持政党:公明党 0.011 0.011 0.009 0.012 0.027 1.00000
支持政党:自由民主党 0.228 0.233 0.239 0.237 0.027 1.00000

図C9:プロフィール属性水準の無作為提示

図C9は回答者の条件割付ではなく、各コンジョイント課題内で属性水準が設計どおり一様に提示されているかを確認するものである。

属性頻度 <- profile_randomization_results$study3$frequency %>%
  dplyr::mutate(
    属性 = 属性日本語(attribute),
    条件 = 条件日本語(party_n, "study3")
  )

表示ラベル <- 属性頻度 %>%
  dplyr::group_by(属性, 条件) %>%
  dplyr::slice_max(abs_deviation, n = 2, with_ties = FALSE) %>%
  dplyr::ungroup()

図C9 <- ggplot2::ggplot(属性頻度, ggplot2::aes(x = expected_share, y = observed_share, shape = 条件)) +
  ggplot2::geom_abline(intercept = 0, slope = 1, linetype = "dashed", linewidth = 0.65) +
  ggplot2::geom_point(size = 2.2, fill = "white") +
  ggplot2::geom_text(data = 表示ラベル, ggplot2::aes(label = level), size = 2.4, check_overlap = TRUE, vjust = -0.7) +
  ggplot2::facet_wrap(~ 属性, ncol = 3) +
  ggplot2::coord_equal() +
  ggplot2::labs(x = "設計上の期待比率", y = "観測比率", shape = "条件") +
  ggplot2::theme_bw(base_size = 10.5) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank(), legend.position = "bottom")
図C9

表C11 <- profile_randomization_results$study3$uniformity_tests %>%
  dplyr::transmute(
    条件 = 条件日本語(party_n, "study3"),
    属性 = 属性日本語(attribute),
    `カイ二乗値` = round(chi_square, 3),
    自由度 = df,
    p値 = signif(p_value, 3),
    `Holm補正p値` = signif(p_holm, 3),
    `最大絶対比率差` = round(max_abs_share_deviation, 4)
  )
knitr::kable(表日本語(表C11), format = "html", row.names = FALSE)
条件 属性 カイ二乗値 自由度 p値 Holm補正p値 最大絶対比率差
2選択肢条件 消費者物価指数(CPI) 0.000 2 1.000 1 0.0001
2選択肢条件 GDP成長率 1.386 2 0.500 1 0.0060
2選択肢条件 日経平均株価 0.555 2 0.758 1 0.0041
2選択肢条件 政党名 5.126 9 0.823 1 0.0056
2選択肢条件 失業率 1.668 2 0.434 1 0.0065
3選択肢条件 消費者物価指数(CPI) 0.545 2 0.762 1 0.0027
3選択肢条件 GDP成長率 0.073 2 0.964 1 0.0011
3選択肢条件 日経平均株価 0.833 2 0.659 1 0.0035
3選択肢条件 政党名 6.035 9 0.736 1 0.0031
3選択肢条件 失業率 2.016 2 0.365 1 0.0054
4選択肢条件 消費者物価指数(CPI) 2.607 2 0.272 1 0.0046
4選択肢条件 GDP成長率 0.104 2 0.949 1 0.0010
4選択肢条件 日経平均株価 3.268 2 0.195 1 0.0056
4選択肢条件 政党名 5.990 9 0.741 1 0.0031
4選択肢条件 失業率 0.107 2 0.948 1 0.0009
5選択肢条件 消費者物価指数(CPI) 0.879 2 0.644 1 0.0024
5選択肢条件 GDP成長率 0.107 2 0.948 1 0.0008
5選択肢条件 日経平均株価 2.946 2 0.229 1 0.0044
5選択肢条件 政党名 3.828 9 0.922 1 0.0020
5選択肢条件 失業率 5.593 2 0.061 1 0.0055
表C12 <- 属性頻度 %>%
  dplyr::transmute(
    条件,
    属性,
    水準 = level,
    観測数 = observed_n,
    総数 = total_n,
    観測比率 = round(observed_share, 4),
    期待比率 = round(expected_share, 4),
= round(deviation, 4)
  )
knitr::kable(表日本語(表C12), format = "html", row.names = FALSE)
条件 属性 水準 観測数 総数 観測比率 期待比率
2選択肢条件 消費者物価指数(CPI) CPI前期比±0ポイント 2387 7160 0.3334 0.3333 0.0000
2選択肢条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 2387 7160 0.3334 0.3333 0.0000
2選択肢条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 2386 7160 0.3332 0.3333 -0.0001
2選択肢条件 GDP成長率 GDP成長率±0% 2344 7160 0.3274 0.3333 -0.0060
2選択肢条件 GDP成長率 GDP成長率プラス1% 2425 7160 0.3387 0.3333 0.0054
2選択肢条件 GDP成長率 GDP成長率マイナス1% 2391 7160 0.3339 0.3333 0.0006
2選択肢条件 日経平均株価 日経平均前月同期比プラス1000円 2357 7160 0.3292 0.3333 -0.0041
2選択肢条件 日経平均株価 日経平均前月同期比マイナス1000円 2400 7160 0.3352 0.3333 0.0019
2選択肢条件 日経平均株価 日経平均前月同期比変わらず 2403 7160 0.3356 0.3333 0.0023
2選択肢条件 政党名 れいわ新選組 676 7160 0.0944 0.1000 -0.0056
2選択肢条件 政党名 チームみらい 730 7160 0.1020 0.1000 0.0020
2選択肢条件 政党名 中道改革連合 728 7160 0.1017 0.1000 0.0017
2選択肢条件 政党名 公明党 700 7160 0.0978 0.1000 -0.0022
2選択肢条件 政党名 参政党 746 7160 0.1042 0.1000 0.0042
2選択肢条件 政党名 国民民主党 703 7160 0.0982 0.1000 -0.0018
2選択肢条件 政党名 日本共産党 708 7160 0.0989 0.1000 -0.0011
2選択肢条件 政党名 日本維新の会 734 7160 0.1025 0.1000 0.0025
2選択肢条件 政党名 立憲民主党 720 7160 0.1006 0.1000 0.0006
2選択肢条件 政党名 自由民主党 715 7160 0.0999 0.1000 -0.0001
2選択肢条件 失業率 失業率前期比±0% 2433 7160 0.3398 0.3333 0.0065
2選択肢条件 失業率 失業率前期比プラス1% 2383 7160 0.3328 0.3333 -0.0005
2選択肢条件 失業率 失業率前期比マイナス1% 2344 7160 0.3274 0.3333 -0.0060
3選択肢条件 消費者物価指数(CPI) CPI前期比±0ポイント 4728 14085 0.3357 0.3333 0.0023
3選択肢条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 4700 14085 0.3337 0.3333 0.0004
3選択肢条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 4657 14085 0.3306 0.3333 -0.0027
3選択肢条件 GDP成長率 GDP成長率±0% 4704 14085 0.3340 0.3333 0.0006
3選択肢条件 GDP成長率 GDP成長率プラス1% 4701 14085 0.3338 0.3333 0.0004
3選択肢条件 GDP成長率 GDP成長率マイナス1% 4680 14085 0.3323 0.3333 -0.0011
3選択肢条件 日経平均株価 日経平均前月同期比プラス1000円 4661 14085 0.3309 0.3333 -0.0024
3選択肢条件 日経平均株価 日経平均前月同期比マイナス1000円 4679 14085 0.3322 0.3333 -0.0011
3選択肢条件 日経平均株価 日経平均前月同期比変わらず 4745 14085 0.3369 0.3333 0.0035
3選択肢条件 政党名 れいわ新選組 1388 14085 0.0985 0.1000 -0.0015
3選択肢条件 政党名 チームみらい 1403 14085 0.0996 0.1000 -0.0004
3選択肢条件 政党名 中道改革連合 1451 14085 0.1030 0.1000 0.0030
3選択肢条件 政党名 公明党 1382 14085 0.0981 0.1000 -0.0019
3選択肢条件 政党名 参政党 1376 14085 0.0977 0.1000 -0.0023
3選択肢条件 政党名 国民民主党 1446 14085 0.1027 0.1000 0.0027
3選択肢条件 政党名 日本共産党 1452 14085 0.1031 0.1000 0.0031
3選択肢条件 政党名 日本維新の会 1413 14085 0.1003 0.1000 0.0003
3選択肢条件 政党名 立憲民主党 1376 14085 0.0977 0.1000 -0.0023
3選択肢条件 政党名 自由民主党 1398 14085 0.0993 0.1000 -0.0007
3選択肢条件 失業率 失業率前期比±0% 4771 14085 0.3387 0.3333 0.0054
3選択肢条件 失業率 失業率前期比プラス1% 4677 14085 0.3321 0.3333 -0.0013
3選択肢条件 失業率 失業率前期比マイナス1% 4637 14085 0.3292 0.3333 -0.0041
4選択肢条件 消費者物価指数(CPI) CPI前期比±0ポイント 7180 21260 0.3377 0.3333 0.0044
4選択肢条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 6988 21260 0.3287 0.3333 -0.0046
4選択肢条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 7092 21260 0.3336 0.3333 0.0003
4選択肢条件 GDP成長率 GDP成長率±0% 7090 21260 0.3335 0.3333 0.0002
4選択肢条件 GDP成長率 GDP成長率プラス1% 7104 21260 0.3341 0.3333 0.0008
4選択肢条件 GDP成長率 GDP成長率マイナス1% 7066 21260 0.3324 0.3333 -0.0010
4選択肢条件 日経平均株価 日経平均前月同期比プラス1000円 7057 21260 0.3319 0.3333 -0.0014
4選択肢条件 日経平均株価 日経平均前月同期比マイナス1000円 7206 21260 0.3389 0.3333 0.0056
4選択肢条件 日経平均株価 日経平均前月同期比変わらず 6997 21260 0.3291 0.3333 -0.0042
4選択肢条件 政党名 れいわ新選組 2164 21260 0.1018 0.1000 0.0018
4選択肢条件 政党名 チームみらい 2144 21260 0.1008 0.1000 0.0008
4選択肢条件 政党名 中道改革連合 2079 21260 0.0978 0.1000 -0.0022
4選択肢条件 政党名 公明党 2150 21260 0.1011 0.1000 0.0011
4選択肢条件 政党名 参政党 2126 21260 0.1000 0.1000 0.0000
4選択肢条件 政党名 国民民主党 2115 21260 0.0995 0.1000 -0.0005
4選択肢条件 政党名 日本共産党 2184 21260 0.1027 0.1000 0.0027
4選択肢条件 政党名 日本維新の会 2108 21260 0.0992 0.1000 -0.0008
4選択肢条件 政党名 立憲民主党 2060 21260 0.0969 0.1000 -0.0031
4選択肢条件 政党名 自由民主党 2130 21260 0.1002 0.1000 0.0002
4選択肢条件 失業率 失業率前期比±0% 7067 21260 0.3324 0.3333 -0.0009
4選択肢条件 失業率 失業率前期比プラス1% 7087 21260 0.3333 0.3333 0.0000
4選択肢条件 失業率 失業率前期比マイナス1% 7106 21260 0.3342 0.3333 0.0009
5選択肢条件 消費者物価指数(CPI) CPI前期比±0ポイント 10978 32850 0.3342 0.3333 0.0009
5選択肢条件 消費者物価指数(CPI) CPI前期比プラス1ポイント 11001 32850 0.3349 0.3333 0.0016
5選択肢条件 消費者物価指数(CPI) CPI前期比マイナス1ポイント 10871 32850 0.3309 0.3333 -0.0024
5選択肢条件 GDP成長率 GDP成長率±0% 10924 32850 0.3325 0.3333 -0.0008
5選択肢条件 GDP成長率 GDP成長率プラス1% 10954 32850 0.3335 0.3333 0.0001
5選択肢条件 GDP成長率 GDP成長率マイナス1% 10972 32850 0.3340 0.3333 0.0007
5選択肢条件 日経平均株価 日経平均前月同期比プラス1000円 11046 32850 0.3363 0.3333 0.0029
5選択肢条件 日経平均株価 日経平均前月同期比マイナス1000円 10806 32850 0.3289 0.3333 -0.0044
5選択肢条件 日経平均株価 日経平均前月同期比変わらず 10998 32850 0.3348 0.3333 0.0015
5選択肢条件 政党名 れいわ新選組 3277 32850 0.0998 0.1000 -0.0002
5選択肢条件 政党名 チームみらい 3351 32850 0.1020 0.1000 0.0020
5選択肢条件 政党名 中道改革連合 3311 32850 0.1008 0.1000 0.0008
5選択肢条件 政党名 公明党 3243 32850 0.0987 0.1000 -0.0013
5選択肢条件 政党名 参政党 3280 32850 0.0998 0.1000 -0.0002
5選択肢条件 政党名 国民民主党 3315 32850 0.1009 0.1000 0.0009
5選択肢条件 政党名 日本共産党 3271 32850 0.0996 0.1000 -0.0004
5選択肢条件 政党名 日本維新の会 3218 32850 0.0980 0.1000 -0.0020
5選択肢条件 政党名 立憲民主党 3290 32850 0.1002 0.1000 0.0002
5選択肢条件 政党名 自由民主党 3294 32850 0.1003 0.1000 0.0003
5選択肢条件 失業率 失業率前期比±0% 10965 32850 0.3338 0.3333 0.0005
5選択肢条件 失業率 失業率前期比プラス1% 10768 32850 0.3278 0.3333 -0.0055
5選択肢条件 失業率 失業率前期比マイナス1% 11117 32850 0.3384 0.3333 0.0051

C.4 標本減少とスクリーニング

以下の標本減少表では、各スクリーニング段階に対応する調査票上の質問文(要約)を併記する。質問文は表の可読性を保つため簡潔に示し、原文の完全な質問文・回答選択肢・コンジョイント課題の提示形式は補遺J「調査票」にまとめて掲載する。

実験1(2023年)

実験1標本減少 <- readr::read_csv(study_csv("study1", "table_sample_attrition.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(
    段階 = stringr::str_replace_all(段階, c("choice_task([1-5])" = "選択課題\\1", "Choice task ([1-5])" = "選択課題\\1"))
  ) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験1標本減少, format = "html", row.names = FALSE, caption = "表C13:実験1の標本減少")
表C13:実験1の標本減少
順序 段階 質問・変数 質問文(調査票・要約) 残存N 当該段階での除外N 前段階からの残存率(%) 初期標本からの残存率(%)
1 Qualtricsの質問文・ImportId行を除外 ResponseId (Qualtricsのメタデータ行。調査質問ではない) 3826 0 100 100
2 初回同意 Q1.1 「本調査の趣旨に同意して、本調査に協力する」 3730 96 97.5 97.5
3 割付されたコンジョイント・ブロックに到達 Q3.1/Q4.1/Q5.1/Q6.1 または最初の選択課題 「今から、日本の政党めぐるkつの選択肢を順に提示していきます。…kつの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 3426 304 91.8 89.5
4 選択課題1を有効回答 条件別 choice task 1 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 3426 0 100 89.5
5 選択課題2を有効回答 条件別 choice task 2 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 3417 9 99.7 89.3
6 選択課題3を有効回答 条件別 choice task 3 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 3412 5 99.9 89.2
7 選択課題4を有効回答 条件別 choice task 4 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 3410 2 99.9 89.1
8 選択課題5を有効回答 条件別 choice task 5 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 3407 3 99.9 89
9 最終送信同意 Q10.1 「本調査の主旨に同意し、回答結果を送信する。」 3382 25 99.3 88.4
10 最終分析標本 全基準の積集合 (質問文なし。上記の全基準の積集合) 3382 0 100 88.4
実験1条件別標本 <- readr::read_csv(study_csv("study1", "table_sample_attrition_by_condition.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(
    条件 = 条件日本語(条件, "study1"),
    段階 = stringr::str_replace_all(段階, c("choice_task([1-5])" = "選択課題\\1", "Choice task ([1-5])" = "選択課題\\1"))
  ) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験1条件別標本, format = "html", row.names = FALSE, caption = "表C14:実験1の条件別標本減少")
表C14:実験1の条件別標本減少
条件 順序 段階 質問文(調査票・要約) 残存N 当該段階での除外N 条件開始時からの残存率(%)
2政党条件 1 割付条件を識別 「今から、日本の政党めぐる2つの選択肢を順に提示していきます。…2つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 821 0 100
2政党条件 2 選択課題1 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 821 0 100
2政党条件 3 選択課題2 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 821 0 100
2政党条件 4 選択課題3 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 820 1 99.9
2政党条件 5 選択課題4 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 820 0 99.9
2政党条件 6 選択課題5 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 820 0 99.9
2政党条件 7 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 815 5 99.3
2政党条件 8 最終分析標本 (質問文なし。上記の全基準の積集合) 815 0 99.3
3政党条件 1 割付条件を識別 「今から、日本の政党めぐる3つの選択肢を順に提示していきます。…3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 855 0 100
3政党条件 2 選択課題1 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 855 0 100
3政党条件 3 選択課題2 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 852 3 99.6
3政党条件 4 選択課題3 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 851 1 99.5
3政党条件 5 選択課題4 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 850 1 99.4
3政党条件 6 選択課題5 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 849 1 99.3
3政党条件 7 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 843 6 98.6
3政党条件 8 最終分析標本 (質問文なし。上記の全基準の積集合) 843 0 98.6
4政党条件 1 割付条件を識別 「今から、日本の政党めぐる4つの選択肢を順に提示していきます。…4つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 894 0 100
4政党条件 2 選択課題1 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 894 0 100
4政党条件 3 選択課題2 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 891 3 99.7
4政党条件 4 選択課題3 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 889 2 99.4
4政党条件 5 選択課題4 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 889 0 99.4
4政党条件 6 選択課題5 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 888 1 99.3
4政党条件 7 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 882 6 98.7
4政党条件 8 最終分析標本 (質問文なし。上記の全基準の積集合) 882 0 98.7
5政党条件 1 割付条件を識別 「今から、日本の政党めぐる5つの選択肢を順に提示していきます。…5つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 856 0 100
5政党条件 2 選択課題1 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 856 0 100
5政党条件 3 選択課題2 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 853 3 99.6
5政党条件 4 選択課題3 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 852 1 99.5
5政党条件 5 選択課題4 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 851 1 99.4
5政党条件 6 選択課題5 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、提示された政党の中から1つを選択してください。」 850 1 99.3
5政党条件 7 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 842 8 98.4
5政党条件 8 最終分析標本 (質問文なし。上記の全基準の積集合) 842 0 98.4

実験2(2026年)

実験2標本減少 <- readr::read_csv(study_csv("study2", "table_sample_attrition.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(段階 = stringr::str_replace_all(段階, c("choice_task([1-5])" = "選択課題\\1", "Choice task ([1-5])" = "選択課題\\1"))) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験2標本減少, format = "html", row.names = FALSE, caption = "表C17:実験2の標本減少")
表C17:実験2の標本減少
順序 段階 質問・変数 質問文(調査票・要約) 残存N 当該段階での除外N 前段階からの残存率(%) 初期標本からの残存率(%)
1 Qualtricsの質問文・ImportId行を除外 ResponseId (Qualtricsのメタデータ行。調査質問ではない) 7365 0 100 100
2 初回同意 Q1.1 「本調査の趣旨に同意して、本調査に協力する」 7114 251 96.6 96.6
3 割付されたコンジョイント・ブロックに到達 Q3.1/Q4.1/Q5.1/Q6.1 または最初の選択課題 「今から、日本の政党めぐるkつの選択肢を順に提示していきます。…kつの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 7113 1 100 96.6
4 選択課題1を有効回答 条件別 choice task 1 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 7113 0 100 96.6
5 選択課題2を有効回答 条件別 choice task 2 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 7113 0 100 96.6
6 選択課題3を有効回答 条件別 choice task 3 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 7113 0 100 96.6
7 選択課題4を有効回答 条件別 choice task 4 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 7113 0 100 96.6
8 選択課題5を有効回答 条件別 choice task 5 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 7113 0 100 96.6
9 提示された選択肢数を正答 条件別に自動検出した選択肢数確認質問 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 4350 2763 61.2 59.1
10 イデオロギー行列の指示項目に正答 Q25.1_10 「!この項目は必ず『3』を選んでください!」 4241 109 97.5 57.6
11 最終送信同意 Q9.1 「本調査の主旨に同意し、回答結果を送信する。」 4192 49 98.8 56.9
12 最終分析標本 全基準の積集合 (質問文なし。上記の全基準の積集合) 4192 0 100 56.9
実験2条件別標本 <- readr::read_csv(study_csv("study2", "table_sample_attrition_by_condition.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study2"), 段階 = stringr::str_replace_all(段階, c("choice_task([1-5])" = "選択課題\\1", "Choice task ([1-5])" = "選択課題\\1"))) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験2条件別標本, format = "html", row.names = FALSE, caption = "表C18:実験2の条件別標本減少")
表C18:実験2の条件別標本減少
条件 順序 段階 質問文(調査票・要約) 残存N 当該段階での除外N 条件開始時からの残存率(%)
2政党条件 1 割付条件を識別 「今から、日本の政党めぐる2つの選択肢を順に提示していきます。…2つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1785 0 100
2政党条件 2 選択課題1 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1785 0 100
2政党条件 3 選択課題2 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1785 0 100
2政党条件 4 選択課題3 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1785 0 100
2政党条件 5 選択課題4 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1785 0 100
2政党条件 6 選択課題5 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1785 0 100
2政党条件 7 選択肢数確認 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 734 1051 41.1
2政党条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 716 18 40.1
2政党条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 711 5 39.8
2政党条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 711 0 39.8
3政党条件 1 割付条件を識別 「今から、日本の政党めぐる3つの選択肢を順に提示していきます。…3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1791 0 100
3政党条件 2 選択課題1 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1791 0 100
3政党条件 3 選択課題2 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1791 0 100
3政党条件 4 選択課題3 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1791 0 100
3政党条件 5 選択課題4 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1791 0 100
3政党条件 6 選択課題5 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1791 0 100
3政党条件 7 選択肢数確認 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 1098 693 61.3
3政党条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 1069 29 59.7
3政党条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 1062 7 59.3
3政党条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 1062 0 59.3
4政党条件 1 割付条件を識別 「今から、日本の政党めぐる4つの選択肢を順に提示していきます。…4つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1741 0 100
4政党条件 2 選択課題1 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1741 0 100
4政党条件 3 選択課題2 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1741 0 100
4政党条件 4 選択課題3 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1741 0 100
4政党条件 5 選択課題4 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1741 0 100
4政党条件 6 選択課題5 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1741 0 100
4政党条件 7 選択肢数確認 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 1141 600 65.5
4政党条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 1113 28 63.9
4政党条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 1097 16 63
4政党条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 1097 0 63
5政党条件 1 割付条件を識別 「今から、日本の政党めぐる5つの選択肢を順に提示していきます。…5つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1796 0 100
5政党条件 2 選択課題1 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1796 0 100
5政党条件 3 選択課題2 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1796 0 100
5政党条件 4 選択課題3 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1796 0 100
5政党条件 5 選択課題4 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1796 0 100
5政党条件 6 選択課題5 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。」 1796 0 100
5政党条件 7 選択肢数確認 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 1377 419 76.7
5政党条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 1343 34 74.8
5政党条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 1322 21 73.6
5政党条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 1322 0 73.6
実験2操作確認 <- readr::read_csv(study_csv("study2", "table_manipulation_check.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", response = "回答", status = "判定", n = "N")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study2"), dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験2操作確認, format = "html", row.names = FALSE, caption = "表C19:実験2の選択肢数操作確認")
表C19:実験2の選択肢数操作確認
条件 質問文(調査票) 回答 正答 N
2政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 1 不正答・欠損 29
2政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 2 正答 734
2政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 3 不正答・欠損 91
2政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 4 不正答・欠損 124
2政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 5 不正答・欠損 559
2政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 6 不正答・欠損 248
3政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 1 不正答・欠損 25
3政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 2 不正答・欠損 64
3政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 3 正答 1098
3政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 4 不正答・欠損 66
3政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 5 不正答・欠損 329
3政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 6 不正答・欠損 209
4政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 1 不正答・欠損 30
4政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 2 不正答・欠損 46
4政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 3 不正答・欠損 49
4政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 4 正答 1141
4政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 5 不正答・欠損 289
4政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 6 不正答・欠損 186
5政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 1 不正答・欠損 37
5政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 2 不正答・欠損 53
5政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 3 不正答・欠損 76
5政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 4 不正答・欠損 90
5政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 5 正答 1377
5政党条件 「あなたに提示された政党の選択肢の数は、いくつでしたか。」 6 不正答・欠損 163
実験2指示項目 <- readr::read_csv(study_csv("study2", "table_attention_check.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, response = "回答コード", status = "判定", n = "N")) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験2指示項目, format = "html", row.names = FALSE, caption = "表C20:実験2の指示項目")
表C20:実験2の指示項目
質問文(調査票) 回答 判定 N
「!この項目は必ず『3』を選んでください!」 1 不正答・欠損 12
「!この項目は必ず『3』を選んでください!」 12 不正答・欠損 7
「!この項目は必ず『3』を選んでください!」 13 不正答・欠損 6
「!この項目は必ず『3』を選んでください!」 14 不正答・欠損 7
「!この項目は必ず『3』を選んでください!」 15 不正答・欠損 70
「!この項目は必ず『3』を選んでください!」 16 不正答・欠損 26
「!この項目は必ず『3』を選んでください!」 2 不正答・欠損 8
「!この項目は必ず『3』を選んでください!」 3 正答 6842
「!この項目は必ず『3』を選んでください!」 4 不正答・欠損 24
「!この項目は必ず『3』を選んでください!」 5 不正答・欠損 12
「!この項目は必ず『3』を選んでください!」 6 不正答・欠損 83
「!この項目は必ず『3』を選んでください!」 7 不正答・欠損 12
「!この項目は必ず『3』を選んでください!」 8 不正答・欠損 6
「!この項目は必ず『3』を選んでください!」 未実施・欠損 不正答・欠損 250

実験3(2026年)

実験3標本減少 <- readr::read_csv(study_csv("study3", "table_sample_attrition.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(段階 = stringr::str_replace_all(段階, c("choice_task([1-5])" = "選択課題\\1", "Choice task ([1-5])" = "選択課題\\1"))) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験3標本減少, format = "html", row.names = FALSE, caption = "表C21:実験3の標本減少")
表C21:実験3の標本減少
順序 段階 質問・変数 質問文(調査票・要約) 残存N 当該段階での除外N 前段階からの残存率(%) 初期標本からの残存率(%)
1 Qualtricsの質問文・ImportId行を除外 ResponseId (Qualtricsのメタデータ行。調査質問ではない) 7012 0 100 100
2 初回同意 Q1.1 「本調査の趣旨に同意して、本調査に協力する」 6852 160 97.7 97.7
3 割付されたコンジョイント・ブロックに到達 Q3.1/Q4.1/Q5.1/Q6.1 または最初の選択課題 「今から、日本の政党めぐるkつの選択肢を順に提示していきます。…kつの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 6852 0 100 97.7
4 選択課題1を有効回答 条件別 choice task 1 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 6852 0 100 97.7
5 選択課題2を有効回答 条件別 choice task 2 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 6852 0 100 97.7
6 選択課題3を有効回答 条件別 choice task 3 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 6852 0 100 97.7
7 選択課題4を有効回答 条件別 choice task 4 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 6852 0 100 97.7
8 選択課題5を有効回答 条件別 choice task 5 「以下に、日本の政党をめぐるkつの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 6852 0 100 97.7
9 提示された選択肢数を正答 条件別に自動検出した選択肢数確認質問 「あなたに提示された選択肢の数は、いくつでしたか。」 4184 2668 61.1 59.7
10 イデオロギー行列の指示項目に正答 Q25.1_10 「!この項目は必ず『3』を選んでください!」 4053 131 96.9 57.8
11 最終送信同意 Q8.1 「本調査の主旨に同意し、回答結果を送信する。」 4032 21 99.5 57.5
12 最終分析標本 全基準の積集合 (質問文なし。上記の全基準の積集合) 4032 0 100 57.5
実験3条件別標本 <- readr::read_csv(study_csv("study3", "table_sample_attrition_by_condition.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study3"), 段階 = stringr::str_replace_all(段階, c("choice_task([1-5])" = "選択課題\\1", "Choice task ([1-5])" = "選択課題\\1"))) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験3条件別標本, format = "html", row.names = FALSE, caption = "表C22:実験3の条件別標本減少")
表C22:実験3の条件別標本減少
条件 順序 段階 質問文(調査票・要約) 残存N 当該段階での除外N 条件開始時からの残存率(%)
2選択肢条件 1 割付条件を識別 「今から、日本の政党めぐる2つの選択肢を順に提示していきます。…2つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1684 0 100
2選択肢条件 2 選択課題1 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1684 0 100
2選択肢条件 3 選択課題2 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1684 0 100
2選択肢条件 4 選択課題3 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1684 0 100
2選択肢条件 5 選択課題4 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1684 0 100
2選択肢条件 6 選択課題5 「以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1684 0 100
2選択肢条件 7 選択肢数確認 「あなたに提示された選択肢の数は、いくつでしたか。」 741 943 44
2選択肢条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 721 20 42.8
2選択肢条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 716 5 42.5
2選択肢条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 716 0 42.5
3選択肢条件 1 割付条件を識別 「今から、日本の政党めぐる3つの選択肢を順に提示していきます。…3つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1769 0 100
3選択肢条件 2 選択課題1 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1769 0 100
3選択肢条件 3 選択課題2 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1769 0 100
3選択肢条件 4 選択課題3 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1769 0 100
3選択肢条件 5 選択課題4 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1769 0 100
3選択肢条件 6 選択課題5 「以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1769 0 100
3選択肢条件 7 選択肢数確認 「あなたに提示された選択肢の数は、いくつでしたか。」 982 787 55.5
3選択肢条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 944 38 53.4
3選択肢条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 939 5 53.1
3選択肢条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 939 0 53.1
4選択肢条件 1 割付条件を識別 「今から、日本の政党めぐる4つの選択肢を順に提示していきます。…4つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1722 0 100
4選択肢条件 2 選択課題1 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1722 0 100
4選択肢条件 3 選択課題2 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1722 0 100
4選択肢条件 4 選択課題3 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1722 0 100
4選択肢条件 5 選択課題4 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1722 0 100
4選択肢条件 6 選択課題5 「以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1722 0 100
4選択肢条件 7 選択肢数確認 「あなたに提示された選択肢の数は、いくつでしたか。」 1099 623 63.8
4選択肢条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 1064 35 61.8
4選択肢条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 1063 1 61.7
4選択肢条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 1063 0 61.7
5選択肢条件 1 割付条件を識別 「今から、日本の政党めぐる5つの選択肢を順に提示していきます。…5つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。作業は5回繰り返されます。」 1677 0 100
5選択肢条件 2 選択課題1 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1677 0 100
5選択肢条件 3 選択課題2 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1677 0 100
5選択肢条件 4 選択課題3 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1677 0 100
5選択肢条件 5 選択課題4 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1677 0 100
5選択肢条件 6 選択課題5 「以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。…政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。」 1677 0 100
5選択肢条件 7 選択肢数確認 「あなたに提示された選択肢の数は、いくつでしたか。」 1362 315 81.2
5選択肢条件 8 指示項目 「!この項目は必ず『3』を選んでください!」 1324 38 79
5選択肢条件 9 最終送信同意 「本調査の主旨に同意し、回答結果を送信する。」 1314 10 78.4
5選択肢条件 10 最終分析標本 (質問文なし。上記の全基準の積集合) 1314 0 78.4
実験3操作確認 <- readr::read_csv(study_csv("study3", "table_manipulation_check.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", response = "回答", status = "判定", n = "N")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study3"), dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験3操作確認, format = "html", row.names = FALSE, caption = "表C23:実験3の選択肢数操作確認")
表C23:実験3の選択肢数操作確認
条件 質問文(調査票) 回答 正答 N
2選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 1 不正答・欠損 15
2選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 2 正答 741
2選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 3 不正答・欠損 47
2選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 4 不正答・欠損 121
2選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 5 不正答・欠損 603
2選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 6 不正答・欠損 157
3選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 1 不正答・欠損 19
3選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 2 不正答・欠損 27
3選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 3 正答 982
3選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 4 不正答・欠損 93
3選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 5 不正答・欠損 490
3選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 6 不正答・欠損 158
4選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 1 不正答・欠損 16
4選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 2 不正答・欠損 18
4選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 3 不正答・欠損 38
4選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 4 正答 1099
4選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 5 不正答・欠損 415
4選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 6 不正答・欠損 135
4選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 未実施・欠損 不正答・欠損 1
5選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 1 不正答・欠損 20
5選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 2 不正答・欠損 27
5選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 3 不正答・欠損 36
5選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 4 不正答・欠損 89
5選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 5 正答 1362
5選択肢条件 「あなたに提示された選択肢の数は、いくつでしたか。」 6 不正答・欠損 143
実験3指示項目 <- readr::read_csv(study_csv("study3", "table_attention_check.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, response = "回答コード", status = "判定", n = "N")) %>%
  dplyr::mutate(dplyr::across(dplyr::everything(), ~ tidyr::replace_na(as.character(.x), "—")))
knitr::kable(実験3指示項目, format = "html", row.names = FALSE, caption = "表C24:実験3の指示項目")
表C24:実験3の指示項目
質問文(調査票) 回答 判定 N
「!この項目は必ず『3』を選んでください!」 1 不正答・欠損 8
「!この項目は必ず『3』を選んでください!」 12 不正答・欠損 9
「!この項目は必ず『3』を選んでください!」 13 不正答・欠損 4
「!この項目は必ず『3』を選んでください!」 14 不正答・欠損 7
「!この項目は必ず『3』を選んでください!」 15 不正答・欠損 94
「!この項目は必ず『3』を選んでください!」 16 不正答・欠損 11
「!この項目は必ず『3』を選んでください!」 2 不正答・欠損 11
「!この項目は必ず『3』を選んでください!」 3 正答 6545
「!この項目は必ず『3』を選んでください!」 4 不正答・欠損 35
「!この項目は必ず『3』を選んでください!」 5 不正答・欠損 14
「!この項目は必ず『3』を選んでください!」 6 不正答・欠損 89
「!この項目は必ず『3』を選んでください!」 7 不正答・欠損 17
「!この項目は必ず『3』を選んでください!」 8 不正答・欠損 7
「!この項目は必ず『3』を選んでください!」 未実施・欠損 不正答・欠損 161

D. 本文図の再現

この節の図(表)番号は本文と一致したものである。本文の分析結果で用いる図は図4から図9までであり、実験2のAMCEは本文図には表示せず、補遺Eに掲示されている。

図4:実験1(2023年)の共変量調整済みAMCE

図4データ <- study1_env$amce_plot_df_cov_facet
図4 <- ggplot2::ggplot(
  図4データ,
  ggplot2::aes(x = estimate_pp, y = label, shape = party_n, linetype = party_n, group = party_n)
) +
  ggplot2::geom_vline(xintercept = 0, linewidth = 0.45, color = "grey35") +
  ggplot2::geom_errorbarh(
    ggplot2::aes(xmin = conf.low_pp, xmax = conf.high_pp),
    position = ggplot2::position_dodge(width = 0.65), height = 0.16, linewidth = 0.55
  ) +
  ggplot2::geom_point(position = ggplot2::position_dodge(width = 0.65), size = 2.5, fill = "white", stroke = 0.8) +
  ggplot2::facet_grid(attribute_facet ~ ., scales = "free_y", space = "free_y", switch = "y") +
  ggplot2::scale_shape_manual(values = c("2政党" = 16, "3政党" = 17, "4政党" = 15, "5政党" = 1)) +
  ggplot2::scale_linetype_manual(values = c("2政党" = "solid", "3政党" = "dashed", "4政党" = "dotted", "5政党" = "dotdash")) +
  ggplot2::labs(x = "選択確率の変化", y = NULL, shape = "政党数条件", linetype = "政党数条件") +
  ggplot2::theme_bw(base_size = 12) +
  ggplot2::theme(legend.position = "top", panel.grid.major.y = ggplot2::element_blank(), panel.grid.minor = ggplot2::element_blank())
図4

表D1 <- readr::read_csv(study_csv("study1", "table_amce_covariate_adjusted.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = paste0(stringr::str_remove(条件, "条件$"), "条件"))
knitr::kable(表日本語(表D1), format = "html", row.names = FALSE, caption = "表D1:図4に対応する共変量調整済みAMCE")
表D1:図4に対応する共変量調整済みAMCE
条件 属性 水準(基準水準との差) 推定値(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値 回答者数
2政党条件 政策位置 右派・保守的 -2.51 1.44 -5.33 0.32 .082 815
2政党条件 政策位置 左派・革新的 -8.04 1.43 -10.85 -5.23 < .001 815
2政党条件 与党/野党 与党 4.78 1.21 2.41 7.15 < .001 815
2政党条件 GDP成長率 GDP:プラス1% 7.73 1.40 4.99 10.47 < .001 815
2政党条件 GDP成長率 GDP:マイナス1% -2.75 1.38 -5.45 -0.05 .046 815
2政党条件 日経平均 日経平均:プラス1000円 6.35 1.39 3.63 9.07 < .001 815
2政党条件 日経平均 日経平均:マイナス1000円 -5.44 1.34 -8.07 -2.81 < .001 815
2政党条件 議席数 議席数:10~49 2.16 1.74 -1.25 5.57 .214 815
2政党条件 議席数 議席数:50~99 7.55 1.76 4.09 11.01 < .001 815
2政党条件 議席数 議席数:100~199 8.90 1.78 5.41 12.40 < .001 815
2政党条件 議席数 議席数:200以上 10.73 1.84 7.13 14.34 < .001 815
2政党条件 CPI CPI:プラス1ポイント -0.14 1.38 -2.85 2.57 .918 815
2政党条件 CPI CPI:マイナス1ポイント -1.13 1.38 -3.83 1.57 .413 815
2政党条件 失業率 失業率:プラス1% -4.50 1.38 -7.22 -1.79 .001 815
2政党条件 失業率 失業率:マイナス1% -2.83 1.39 -5.55 -0.10 .042 815
3政党条件 政策位置 右派・保守的 -4.79 1.22 -7.18 -2.40 < .001 843
3政党条件 政策位置 左派・革新的 -8.99 1.22 -11.39 -6.60 < .001 843
3政党条件 与党/野党 与党 3.50 1.10 1.35 5.65 .001 843
3政党条件 GDP成長率 GDP:プラス1% 8.05 1.02 6.05 10.06 < .001 843
3政党条件 GDP成長率 GDP:マイナス1% -2.67 0.96 -4.55 -0.80 .005 843
3政党条件 日経平均 日経平均:プラス1000円 6.07 1.06 3.99 8.14 < .001 843
3政党条件 日経平均 日経平均:マイナス1000円 -4.23 1.04 -6.28 -2.19 < .001 843
3政党条件 議席数 議席数:10~49 3.66 1.24 1.23 6.09 .003 843
3政党条件 議席数 議席数:50~99 8.36 1.28 5.86 10.86 < .001 843
3政党条件 議席数 議席数:100~199 11.70 1.48 8.79 14.61 < .001 843
3政党条件 議席数 議席数:200以上 11.28 1.52 8.29 14.26 < .001 843
3政党条件 CPI CPI:プラス1ポイント 1.15 1.01 -0.82 3.13 .253 843
3政党条件 CPI CPI:マイナス1ポイント 0.14 1.01 -1.84 2.12 .892 843
3政党条件 失業率 失業率:プラス1% -3.40 1.05 -5.47 -1.34 .001 843
3政党条件 失業率 失業率:マイナス1% -2.05 1.06 -4.12 0.03 .053 843
4政党条件 政策位置 右派・保守的 -5.27 1.00 -7.22 -3.32 < .001 882
4政党条件 政策位置 左派・革新的 -8.28 0.99 -10.22 -6.34 < .001 882
4政党条件 与党/野党 与党 4.27 0.95 2.40 6.14 < .001 882
4政党条件 GDP成長率 GDP:プラス1% 7.39 0.88 5.67 9.11 < .001 882
4政党条件 GDP成長率 GDP:マイナス1% -3.46 0.78 -4.98 -1.94 < .001 882
4政党条件 日経平均 日経平均:プラス1000円 3.24 0.86 1.55 4.93 < .001 882
4政党条件 日経平均 日経平均:マイナス1000円 -5.21 0.77 -6.71 -3.70 < .001 882
4政党条件 議席数 議席数:10~49 3.79 0.89 2.05 5.54 < .001 882
4政党条件 議席数 議席数:50~99 6.69 0.99 4.74 8.63 < .001 882
4政党条件 議席数 議席数:100~199 10.17 1.14 7.93 12.41 < .001 882
4政党条件 議席数 議席数:200以上 9.91 1.30 7.36 12.47 < .001 882
4政党条件 CPI CPI:プラス1ポイント 2.79 0.81 1.21 4.38 < .001 882
4政党条件 CPI CPI:マイナス1ポイント 0.05 0.81 -1.53 1.62 .955 882
4政党条件 失業率 失業率:プラス1% -3.58 0.84 -5.23 -1.93 < .001 882
4政党条件 失業率 失業率:マイナス1% -0.44 0.82 -2.05 1.17 .589 882
5政党条件 政策位置 右派・保守的 -4.37 0.85 -6.04 -2.70 < .001 842
5政党条件 政策位置 左派・革新的 -6.56 0.85 -8.23 -4.89 < .001 842
5政党条件 与党/野党 与党 4.94 0.87 3.23 6.65 < .001 842
5政党条件 GDP成長率 GDP:プラス1% 6.42 0.77 4.91 7.93 < .001 842
5政党条件 GDP成長率 GDP:マイナス1% -3.26 0.67 -4.58 -1.94 < .001 842
5政党条件 日経平均 日経平均:プラス1000円 3.79 0.72 2.38 5.20 < .001 842
5政党条件 日経平均 日経平均:マイナス1000円 -4.52 0.65 -5.79 -3.25 < .001 842
5政党条件 議席数 議席数:10~49 3.80 0.71 2.41 5.18 < .001 842
5政党条件 議席数 議席数:50~99 8.22 0.93 6.40 10.04 < .001 842
5政党条件 議席数 議席数:100~199 9.81 1.09 7.68 11.94 < .001 842
5政党条件 議席数 議席数:200以上 10.13 1.14 7.90 12.36 < .001 842
5政党条件 CPI CPI:プラス1ポイント 0.89 0.69 -0.45 2.23 .194 842
5政党条件 CPI CPI:マイナス1ポイント -1.16 0.67 -2.48 0.16 .086 842
5政党条件 失業率 失業率:プラス1% -2.97 0.71 -4.36 -1.58 < .001 842
5政党条件 失業率 失業率:マイナス1% -0.07 0.72 -1.48 1.34 .924 842

図5:実験1(2023年)の政党・経済手がかりの重要度と相対比重

図5重要度データ <- study1_env$relative_panel_adjusted_data
図5相対比重データ <- study1_env$relative_panel_b_data
図5パネルA <- study1_env$relative_panel_adjusted
図5パネルB <- study1_env$relative_panel_c
図5 <- (図5パネルA | 図5パネルB) + patchwork::plot_layout(widths = c(1, 1))
図5

表D2 <- readr::read_csv(study_csv("study1", "table_marginal_means.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性", level = "水準")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study1"), 属性 = 属性日本語(属性))
knitr::kable(表日本語(表D2), format = "html", row.names = FALSE, caption = "表D2:限界平均")
表D2:限界平均
条件 手がかり群 属性 水準 限界平均(%) クラスタSE(pp) 95% CI下限(%) 95% CI上限(%) プロファイル数 回答者数
2政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 50.37 0.80 48.81 51.94 2672 799
2政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 50.36 0.82 48.76 51.96 2780 804
2政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 49.26 0.82 47.64 50.88 2698 800
2政党 経済の手がかり GDP成長率 GDP成長率±0% 48.09 0.81 46.50 49.67 2716 797
2政党 経済の手がかり GDP成長率 GDP成長率プラス1% 56.04 0.82 54.44 57.64 2791 801
2政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 45.59 0.83 43.97 47.21 2643 800
2政党 政党の手がかり 与野党地位 与党 52.41 0.61 51.22 53.61 4146 815
2政党 政党の手がかり 与野党地位 野党 47.50 0.63 46.27 48.74 4004 814
2政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 56.27 0.82 54.65 57.88 2721 802
2政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 44.13 0.79 42.58 45.68 2726 798
2政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 49.61 0.79 48.07 51.16 2703 792
2政党 政党の手がかり 政策位置 中道 53.44 0.81 51.86 55.02 2717 800
2政党 政党の手がかり 政策位置 右派・保守的 51.09 0.91 49.31 52.87 2711 801
2政党 政党の手がかり 政策位置 左派・革新的 45.48 0.89 43.73 47.23 2722 802
2政党 政党の手がかり 議席数 100~199 53.13 1.13 50.92 55.34 1662 744
2政党 政党の手がかり 議席数 10~49 46.26 1.15 44.01 48.51 1565 721
2政党 政党の手がかり 議席数 10以下 44.13 1.11 41.96 46.30 1686 725
2政党 政党の手がかり 議席数 200以上 54.84 1.17 52.55 57.13 1652 730
2政党 政党の手がかり 議席数 50~99 51.61 1.16 49.34 53.88 1585 721
2政党 経済の手がかり 失業率 失業率前期比±0% 52.47 0.81 50.88 54.07 2750 796
2政党 経済の手がかり 失業率 失業率前期比プラス1% 48.08 0.81 46.50 49.67 2741 806
2政党 経済の手がかり 失業率 失業率前期比マイナス1% 49.42 0.83 47.80 51.04 2659 802
3政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 32.89 0.59 31.73 34.06 4168 841
3政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 33.95 0.60 32.77 35.12 4277 842
3政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 33.14 0.61 31.95 34.33 4200 839
3政党 経済の手がかり GDP成長率 GDP成長率±0% 31.77 0.56 30.68 32.85 4297 842
3政党 経済の手がかり GDP成長率 GDP成長率プラス1% 39.75 0.66 38.46 41.05 4075 839
3政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 28.79 0.61 27.60 29.97 4273 843
3政党 政党の手がかり 与野党地位 与党 35.46 0.74 34.01 36.92 4162 842
3政党 政党の手がかり 与野党地位 野党 32.29 0.36 31.58 33.00 8483 843
3政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 38.95 0.63 37.71 40.19 4177 842
3政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 28.55 0.62 27.33 29.77 4284 842
3政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 32.62 0.61 31.43 33.82 4184 843
3政党 政党の手がかり 政策位置 中道 38.05 0.71 36.65 39.45 4113 841
3政党 政党の手がかり 政策位置 右派・保守的 33.14 0.72 31.73 34.55 4306 841
3政党 政党の手がかり 政策位置 左派・革新的 28.94 0.72 27.52 30.36 4226 841
3政党 政党の手がかり 議席数 100~199 38.67 1.01 36.70 40.64 2105 793
3政党 政党の手がかり 議席数 10~49 30.41 0.79 28.86 31.95 2802 826
3政党 政党の手がかり 議席数 10以下 26.84 0.84 25.20 28.49 2794 828
3政党 政党の手がかり 議席数 200以上 38.06 1.03 36.05 40.07 2157 796
3政党 政党の手がかり 議席数 50~99 35.09 0.81 33.49 36.69 2787 825
3政党 経済の手がかり 失業率 失業率前期比±0% 35.07 0.61 33.88 36.27 4268 842
3政党 経済の手がかり 失業率 失業率前期比プラス1% 31.85 0.64 30.58 33.11 4167 839
3政党 経済の手がかり 失業率 失業率前期比マイナス1% 33.04 0.64 31.79 34.29 4210 839
4政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 24.15 0.47 23.23 25.06 6009 882
4政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 26.61 0.48 25.68 27.55 5824 882
4政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 24.26 0.48 23.33 25.20 5807 882
4政党 経済の手がかり GDP成長率 GDP成長率±0% 23.80 0.47 22.89 24.72 5894 881
4政党 経済の手がかり GDP成長率 GDP成長率プラス1% 31.10 0.55 30.03 32.18 5858 882
4政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 20.13 0.48 19.18 21.07 5888 882
4政党 政党の手がかり 与野党地位 与党 28.30 0.72 26.88 29.71 4322 878
4政党 政党の手がかり 与野党地位 野党 23.93 0.23 23.47 24.39 13318 882
4政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 28.93 0.53 27.89 29.97 5814 881
4政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 20.62 0.47 19.70 21.54 5931 882
4政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 25.53 0.47 24.61 26.45 5895 881
4政党 政党の手がかり 政策位置 中道 29.38 0.57 28.26 30.49 5913 882
4政党 政党の手がかり 政策位置 右派・保守的 24.23 0.60 23.06 25.40 5757 882
4政党 政党の手がかり 政策位置 左派・革新的 21.41 0.58 20.28 22.54 5970 882
4政党 政党の手がかり 議席数 100~199 29.83 0.80 28.27 31.39 2977 859
4政党 政党の手がかり 議席数 10~49 23.26 0.58 22.11 24.40 4205 879
4政党 政党の手がかり 議席数 10以下 19.49 0.62 18.28 20.70 4058 875
4政党 政党の手がかり 議席数 200以上 29.36 0.99 27.42 31.30 2224 828
4政党 政党の手がかり 議席数 50~99 26.34 0.62 25.12 27.56 4176 879
4政党 経済の手がかり 失業率 失業率前期比±0% 26.30 0.48 25.36 27.25 5889 882
4政党 経済の手がかり 失業率 失業率前期比プラス1% 22.79 0.50 21.81 23.76 5915 882
4政党 経済の手がかり 失業率 失業率前期比マイナス1% 25.93 0.48 24.98 26.87 5836 881
5政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 20.10 0.40 19.33 20.87 6965 842
5政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 21.08 0.42 20.26 21.90 6960 842
5政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 18.85 0.40 18.06 19.64 7125 842
5政党 経済の手がかり GDP成長率 GDP成長率±0% 18.96 0.41 18.17 19.76 7135 842
5政党 経済の手がかり GDP成長率 GDP成長率プラス1% 25.37 0.48 24.44 26.30 6973 842
5政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 15.67 0.42 14.85 16.50 6942 842
5政党 政党の手がかり 与野党地位 与党 24.06 0.70 22.69 25.44 4193 839
5政党 政党の手がかり 与野党地位 野党 18.99 0.17 18.65 19.33 16857 842
5政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 24.07 0.44 23.21 24.93 6996 841
5政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 15.67 0.40 14.89 16.45 6950 842
5政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 20.23 0.39 19.47 20.99 7104 842
5政党 政党の手がかり 政策位置 中道 23.66 0.50 22.68 24.63 7051 842
5政党 政党の手がかり 政策位置 右派・保守的 19.22 0.50 18.23 20.20 6963 842
5政党 政党の手がかり 政策位置 左派・革新的 17.11 0.49 16.15 18.08 7036 842
5政党 政党の手がかり 議席数 100~199 24.93 0.86 23.25 26.62 2615 813
5政党 政党の手がかり 議席数 10~49 19.03 0.44 18.15 19.90 6423 842
5政党 政党の手がかり 議席数 10以下 15.13 0.46 14.24 16.02 6338 842
5政党 政党の手がかり 議席数 200以上 25.36 0.94 23.51 27.21 2157 789
5政党 政党の手がかり 議席数 50~99 23.60 0.67 22.28 24.92 3517 837
5政党 経済の手がかり 失業率 失業率前期比±0% 21.11 0.42 20.29 21.93 6850 842
5政党 経済の手がかり 失業率 失業率前期比プラス1% 17.91 0.42 17.09 18.74 7157 842
5政党 経済の手がかり 失業率 失業率前期比マイナス1% 21.04 0.44 20.18 21.90 7043 841
表D3 <- readr::read_csv(study_csv("study1", "table_attribute_importance.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study1"), 属性 = 属性日本語(属性))
knitr::kable(表日本語(表D3), format = "html", row.names = FALSE, caption = "表D3:属性重要度")
表D3:属性重要度
条件 手がかり群 属性 水準数 未調整重要度(pp) 選択肢数調整済み重要度(%)
2政党条件 経済の手がかり 消費者物価指数(CPI) 3 0.74 1.49
2政党条件 経済の手がかり GDP成長率 3 6.96 13.93
2政党条件 政党の手がかり 与野党地位 2 4.91 9.82
2政党条件 経済の手がかり 日経平均株価 3 8.09 16.18
2政党条件 政党の手がかり 政策位置 3 5.31 10.61
2政党条件 政党の手がかり 議席数 5 5.66 11.32
2政党条件 経済の手がかり 失業率 3 2.93 5.85
3政党条件 経済の手がかり 消費者物価指数(CPI) 3 0.70 2.11
3政党条件 経済の手がかり GDP成長率 3 7.31 21.94
3政党条件 政党の手がかり 与野党地位 2 3.18 9.53
3政党条件 経済の手がかり 日経平均株価 3 6.94 20.81
3政党条件 政党の手がかり 政策位置 3 6.07 18.22
3政党条件 政党の手がかり 議席数 5 6.26 18.79
3政党条件 経済の手がかり 失業率 3 2.15 6.46
4政党条件 経済の手がかり 消費者物価指数(CPI) 3 1.64 6.58
4政党条件 経済の手がかり GDP成長率 3 7.32 29.27
4政党条件 政党の手がかり 与野党地位 2 4.37 17.47
4政党条件 経済の手がかり 日経平均株価 3 5.54 22.16
4政党条件 政党の手がかり 政策位置 3 5.31 21.25
4政党条件 政党の手がかり 議席数 5 5.36 21.42
4政党条件 経済の手がかり 失業率 3 2.34 9.37
5政党条件 経済の手がかり 消費者物価指数(CPI) 3 1.49 7.43
5政党条件 経済の手がかり GDP成長率 3 6.46 32.32
5政党条件 政党の手がかり 与野党地位 2 5.07 25.37
5政党条件 経済の手がかり 日経平均株価 3 5.60 28.01
5政党条件 政党の手がかり 政策位置 3 4.36 21.81
5政党条件 政党の手がかり 議席数 5 5.27 26.36
5政党条件 経済の手がかり 失業率 3 2.13 10.66
表D4 <- readr::read_csv(study_csv("study1", "table_cue_importance.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", statistic = "指標")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study1"), 指標 = 統計量日本語(指標, "study1"))
knitr::kable(表日本語(表D4), format = "html", row.names = FALSE, caption = "表D4:政党・経済手がかりの重要度と相対比重")
表D4:政党・経済手がかりの重要度と相対比重
条件 指標 単位 推定値 95% CI下限 95% CI上限
2政党条件 政党手がかり:未調整重要度 pp 5.29 4.20 6.51
2政党条件 経済手がかり:未調整重要度 pp 4.68 4.03 5.72
2政党条件 政党手がかり:選択肢数調整済み重要度 % 10.58 8.40 13.02
2政党条件 経済手がかり:選択肢数調整済み重要度 % 9.36 8.06 11.44
2政党条件 政党手がかりの相対比重 % 53.06 44.85 59.61
3政党条件 政党手がかり:未調整重要度 pp 5.17 4.16 6.23
3政党条件 経済手がかり:未調整重要度 pp 4.28 3.73 5.04
3政党条件 政党手がかり:選択肢数調整済み重要度 % 15.51 12.47 18.68
3政党条件 経済手がかり:選択肢数調整済み重要度 % 12.83 11.20 15.11
3政党条件 政党手がかりの相対比重 % 54.73 47.38 60.49
4政党条件 政党手がかり:未調整重要度 pp 5.01 4.22 5.94
4政党条件 経済手がかり:未調整重要度 pp 4.21 3.73 4.84
4政党条件 政党手がかり:選択肢数調整済み重要度 % 20.05 16.88 23.76
4政党条件 経済手がかり:選択肢数調整済み重要度 % 16.84 14.90 19.34
4政党条件 政党手がかりの相対比重 % 54.34 48.53 59.45
5政党条件 政党手がかり:未調整重要度 pp 4.90 4.12 5.76
5政党条件 経済手がかり:未調整重要度 pp 3.92 3.49 4.50
5政党条件 政党手がかり:選択肢数調整済み重要度 % 24.52 20.58 28.81
5政党条件 経済手がかり:選択肢数調整済み重要度 % 19.60 17.47 22.52
5政党条件 政党手がかりの相対比重 % 55.57 49.63 60.52

図6:実験2(2026年)の政党・経済手がかりの重要度と相対比重

図6重要度データ <- study2_env$relative_panel_adjusted_data
図6相対比重データ <- study2_env$relative_panel_b_data
図6パネルA <- study2_env$relative_panel_adjusted
図6パネルB <- study2_env$relative_panel_c
図6 <- (図6パネルA | 図6パネルB) + patchwork::plot_layout(widths = c(1, 1))
図6

表D5 <- readr::read_csv(study_csv("study2", "table_marginal_means.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性", level = "水準")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study2"), 属性 = 属性日本語(属性))
knitr::kable(表日本語(表D5), format = "html", row.names = FALSE, caption = "表D5:限界平均")
表D5:限界平均
条件 手がかり群 属性 水準 限界平均(%) クラスタSE(pp) 95% CI下限(%) 95% CI上限(%) プロファイル数 回答者数
2政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 48.57 0.82 46.95 50.18 2335 696
2政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 50.74 0.86 49.06 52.43 2355 700
2政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 50.66 0.83 49.04 52.28 2420 699
2政党 経済の手がかり GDP成長率 GDP成長率±0% 48.98 0.90 47.21 50.74 2342 701
2政党 経済の手がかり GDP成長率 GDP成長率プラス1% 57.31 0.90 55.54 59.08 2401 704
2政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 43.60 0.89 41.86 45.34 2367 702
2政党 政党の手がかり 与野党地位 与党 51.78 0.65 50.51 53.05 3623 711
2政党 政党の手がかり 与野党地位 野党 48.15 0.67 46.83 49.47 3487 709
2政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 55.23 0.90 53.47 56.98 2354 697
2政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 43.71 0.92 41.91 45.52 2274 695
2政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 50.81 0.84 49.15 52.46 2482 699
2政党 政党の手がかり 政策位置 中道 53.58 0.89 51.84 55.33 2413 703
2政党 政党の手がかり 政策位置 右派・保守的 51.80 0.98 49.89 53.71 2390 698
2政党 政党の手がかり 政策位置 左派・革新的 44.39 0.99 42.45 46.33 2307 698
2政党 政党の手がかり 議席数 100~199 54.21 1.26 51.75 56.67 1400 622
2政党 政党の手がかり 議席数 10~49 46.04 1.19 43.70 48.38 1351 624
2政党 政党の手がかり 議席数 10以下 45.27 1.20 42.92 47.62 1491 632
2政党 政党の手がかり 議席数 200以上 53.93 1.28 51.42 56.45 1398 634
2政党 政党の手がかり 議席数 50~99 50.68 1.12 48.48 52.88 1470 641
2政党 経済の手がかり 失業率 失業率前期比±0% 52.49 0.88 50.76 54.22 2389 700
2政党 経済の手がかり 失業率 失業率前期比プラス1% 47.90 0.87 46.18 49.61 2353 696
2政党 経済の手がかり 失業率 失業率前期比マイナス1% 49.58 0.87 47.88 51.28 2368 700
3政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 33.81 0.54 32.75 34.87 5282 1058
3政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 35.00 0.56 33.91 36.10 5311 1061
3政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 31.20 0.57 30.08 32.32 5337 1061
3政党 経済の手がかり GDP成長率 GDP成長率±0% 33.50 0.52 32.48 34.52 5394 1059
3政党 経済の手がかり GDP成長率 GDP成長率プラス1% 39.44 0.60 38.26 40.62 5210 1061
3政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 27.19 0.55 26.11 28.26 5326 1059
3政党 政党の手がかり 与野党地位 与党 34.20 0.45 33.31 35.09 7947 1062
3政党 政党の手がかり 与野党地位 野党 32.47 0.45 31.59 33.35 7983 1062
3政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 38.36 0.57 37.25 39.48 5336 1060
3政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 28.59 0.55 27.50 29.68 5320 1059
3政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 33.03 0.56 31.94 34.12 5274 1061
3政党 政党の手がかり 政策位置 中道 36.48 0.62 35.26 37.70 5392 1061
3政党 政党の手がかり 政策位置 右派・保守的 36.06 0.72 34.65 37.47 5285 1059
3政党 政党の手がかり 政策位置 左派・革新的 27.36 0.64 26.09 28.62 5253 1056
3政党 政党の手がかり 議席数 100~199 37.71 0.76 36.23 39.19 3246 1031
3政党 政党の手がかり 議席数 10~49 30.52 0.78 28.99 32.04 3149 1016
3政党 政党の手がかり 議席数 10以下 26.93 0.76 25.43 28.43 3201 1028
3政党 政党の手がかり 議席数 200以上 37.11 0.82 35.50 38.71 3207 1027
3政党 政党の手がかり 議席数 50~99 34.31 0.79 32.77 35.85 3127 1019
3政党 経済の手がかり 失業率 失業率前期比±0% 35.23 0.57 34.11 36.34 5212 1059
3政党 経済の手がかり 失業率 失業率前期比プラス1% 30.91 0.55 29.82 31.99 5381 1059
3政党 経済の手がかり 失業率 失業率前期比マイナス1% 33.93 0.56 32.84 35.03 5337 1059
4政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 24.56 0.43 23.72 25.40 7255 1097
4政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 26.38 0.44 25.51 27.25 7404 1097
4政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 24.04 0.44 23.18 24.89 7281 1097
4政党 経済の手がかり GDP成長率 GDP成長率±0% 24.42 0.42 23.60 25.24 7281 1097
4政党 経済の手がかり GDP成長率 GDP成長率プラス1% 30.85 0.45 29.96 31.74 7339 1097
4政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 19.71 0.41 18.90 20.53 7320 1097
4政党 政党の手がかり 与野党地位 与党 25.95 0.36 25.23 26.66 11000 1097
4政党 政党の手がかり 与野党地位 野党 24.05 0.37 23.33 24.77 10940 1097
4政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 28.33 0.48 27.40 29.26 7229 1097
4政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 20.81 0.44 19.94 21.67 7185 1097
4政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 25.80 0.42 24.99 26.62 7526 1097
4政党 政党の手がかり 政策位置 中道 27.52 0.53 26.48 28.57 7296 1096
4政党 政党の手がかり 政策位置 右派・保守的 28.59 0.59 27.43 29.74 7259 1097
4政党 政党の手がかり 政策位置 左派・革新的 18.98 0.51 17.98 19.99 7385 1097
4政党 政党の手がかり 議席数 100~199 28.92 0.61 27.73 30.11 4471 1077
4政党 政党の手がかり 議席数 10~49 22.83 0.59 21.68 23.99 4371 1077
4政党 政党の手がかり 議席数 10以下 17.95 0.60 16.79 19.12 4389 1079
4政党 政党の手がかり 議席数 200以上 29.28 0.66 27.99 30.57 4358 1086
4政党 政党の手がかり 議席数 50~99 25.97 0.62 24.75 27.19 4351 1081
4政党 経済の手がかり 失業率 失業率前期比±0% 26.71 0.45 25.83 27.60 7412 1097
4政党 経済の手がかり 失業率 失業率前期比プラス1% 22.57 0.44 21.69 23.44 7228 1097
4政党 経済の手がかり 失業率 失業率前期比マイナス1% 25.67 0.47 24.76 26.58 7300 1097
5政党 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 20.07 0.32 19.45 20.69 11075 1322
5政党 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 20.33 0.31 19.72 20.95 11011 1322
5政党 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 19.59 0.32 18.97 20.21 10964 1322
5政党 経済の手がかり GDP成長率 GDP成長率±0% 19.23 0.32 18.61 19.86 11038 1322
5政党 経済の手がかり GDP成長率 GDP成長率プラス1% 24.41 0.36 23.70 25.12 10977 1322
5政党 経済の手がかり GDP成長率 GDP成長率マイナス1% 16.38 0.32 15.76 17.01 11035 1322
5政党 政党の手がかり 与野党地位 与党 21.36 0.28 20.82 21.91 16473 1322
5政党 政党の手がかり 与野党地位 野党 18.65 0.28 18.11 19.19 16577 1322
5政党 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 23.67 0.36 22.97 24.37 11056 1322
5政党 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 16.60 0.34 15.94 17.26 11105 1322
5政党 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 19.74 0.32 19.12 20.37 10889 1322
5政党 政党の手がかり 政策位置 中道 21.66 0.42 20.83 22.48 10985 1322
5政党 政党の手がかり 政策位置 右派・保守的 22.72 0.46 21.82 23.62 11128 1322
5政党 政党の手がかり 政策位置 左派・革新的 15.57 0.41 14.77 16.37 10937 1322
5政党 政党の手がかり 議席数 100~199 23.74 0.49 22.77 24.70 6589 1316
5政党 政党の手がかり 議席数 10~49 16.37 0.42 15.54 17.19 6697 1317
5政党 政党の手がかり 議席数 10以下 14.15 0.44 13.29 15.01 6550 1316
5政党 政党の手がかり 議席数 200以上 24.75 0.52 23.72 25.77 6611 1318
5政党 政党の手がかり 議席数 50~99 21.01 0.48 20.07 21.94 6603 1321
5政党 経済の手がかり 失業率 失業率前期比±0% 20.78 0.33 20.14 21.42 11191 1322
5政党 経済の手がかり 失業率 失業率前期比プラス1% 18.57 0.33 17.92 19.22 10916 1322
5政党 経済の手がかり 失業率 失業率前期比マイナス1% 20.63 0.36 19.93 21.32 10943 1322
表D6 <- readr::read_csv(study_csv("study2", "table_attribute_importance.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study2"), 属性 = 属性日本語(属性))
knitr::kable(表日本語(表D6), format = "html", row.names = FALSE, caption = "表D6:属性重要度")
表D6:属性重要度
条件 手がかり群 属性 水準数 未調整重要度(pp) 選択肢数調整済み重要度(%)
2政党条件 経済の手がかり 消費者物価指数(CPI) 3 1.45 2.90
2政党条件 経済の手がかり GDP成長率 3 9.14 18.28
2政党条件 政党の手がかり 与野党地位 2 3.63 7.26
2政党条件 経済の手がかり 日経平均株価 3 7.68 15.35
2政党条件 政党の手がかり 政策位置 3 6.13 12.26
2政党条件 政党の手がかり 議席数 5 5.16 10.31
2政党条件 経済の手がかり 失業率 3 3.06 6.13
3政党条件 経済の手がかり 消費者物価指数(CPI) 3 2.54 7.61
3政党条件 経済の手がかり GDP成長率 3 8.17 24.51
3政党条件 政党の手がかり 与野党地位 2 1.73 5.20
3政党条件 経済の手がかり 日経平均株価 3 6.51 19.54
3政党条件 政党の手がかり 政策位置 3 6.08 18.25
3政党条件 政党の手がかり 議席数 5 5.63 16.89
3政党条件 経済の手がかり 失業率 3 2.88 8.64
4政党条件 経済の手がかり 消費者物価指数(CPI) 3 1.56 6.25
4政党条件 経済の手がかり GDP成長率 3 7.42 29.70
4政党条件 政党の手がかり 与野党地位 2 1.90 7.58
4政党条件 経済の手がかり 日経平均株価 3 5.02 20.06
4政党条件 政党の手がかり 政策位置 3 6.40 25.60
4政党条件 政党の手がかり 議席数 5 5.75 22.99
4政党条件 経済の手がかり 失業率 3 2.77 11.06
5政党条件 経済の手がかり 消費者物価指数(CPI) 3 0.50 2.48
5政党条件 経済の手がかり GDP成長率 3 5.35 26.74
5政党条件 政党の手がかり 与野党地位 2 2.72 13.58
5政党条件 経済の手がかり 日経平均株価 3 4.72 23.58
5政党条件 政党の手がかり 政策位置 3 4.76 23.82
5政党条件 政党の手がかり 議席数 5 5.71 28.56
5政党条件 経済の手がかり 失業率 3 1.48 7.38
表D7 <- readr::read_csv(study_csv("study2", "table_cue_importance.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", statistic = "指標")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study2"), 指標 = 統計量日本語(指標, "study2"))
knitr::kable(表日本語(表D7), format = "html", row.names = FALSE, caption = "表D7:政党・経済手がかりの重要度と相対比重")
表D7:政党・経済手がかりの重要度と相対比重
条件 指標 単位 推定値 95% CI下限 95% CI上限
2政党条件 政党手がかり:未調整重要度 pp 4.97 3.74 6.35
2政党条件 経済手がかり:未調整重要度 pp 5.33 4.53 6.42
2政党条件 政党手がかり:選択肢数調整済み重要度 % 9.95 7.48 12.70
2政党条件 経済手がかり:選択肢数調整済み重要度 % 10.67 9.06 12.85
2政党条件 政党手がかりの相対比重 % 48.25 39.91 55.66
3政党条件 政党手がかり:未調整重要度 pp 4.48 3.77 5.40
3政党条件 経済手がかり:未調整重要度 pp 5.03 4.39 5.66
3政党条件 政党手がかり:選択肢数調整済み重要度 % 13.44 11.31 16.20
3政党条件 経済手がかり:選択肢数調整済み重要度 % 15.08 13.18 16.99
3政党条件 政党手がかりの相対比重 % 47.14 42.11 53.05
4政党条件 政党手がかり:未調整重要度 pp 4.68 3.98 5.46
4政党条件 経済手がかり:未調整重要度 pp 4.19 3.72 4.76
4政党条件 政党手がかり:選択肢数調整済み重要度 % 18.73 15.93 21.84
4政党条件 経済手がかり:選択肢数調整済み重要度 % 16.77 14.90 19.06
4政党条件 政党手がかりの相対比重 % 52.76 47.46 57.72
5政党条件 政党手がかり:未調整重要度 pp 4.40 3.86 4.98
5政党条件 経済手がかり:未調整重要度 pp 3.01 2.70 3.45
5政党条件 政党手がかり:選択肢数調整済み重要度 % 21.99 19.31 24.88
5政党条件 経済手がかり:選択肢数調整済み重要度 % 15.04 13.50 17.26
5政党条件 政党手がかりの相対比重 % 59.37 54.43 63.34

図7:実験3(2026年)の共変量調整済みAMCE

図7データ <- study3_env$amce_plot_cov
図7 <- ggplot2::ggplot(
  図7データ,
  ggplot2::aes(x = estimate_pp, y = label, shape = party_n, linetype = party_n, group = party_n)
) +
  ggplot2::geom_vline(xintercept = 0, linewidth = 0.45, color = "grey35") +
  ggplot2::geom_errorbarh(
    ggplot2::aes(xmin = conf.low_pp, xmax = conf.high_pp),
    position = ggplot2::position_dodge(width = 0.65), height = 0.16, linewidth = 0.55
  ) +
  ggplot2::geom_point(position = ggplot2::position_dodge(width = 0.65), size = 2.5, fill = "white", stroke = 0.8) +
  ggplot2::facet_grid(attribute ~ ., scales = "free_y", space = "free_y", switch = "y") +
  ggplot2::scale_shape_manual(values = c("2選択肢" = 16, "3選択肢" = 17, "4選択肢" = 15, "5選択肢" = 1)) +
  ggplot2::scale_linetype_manual(values = c("2選択肢" = "solid", "3選択肢" = "dashed", "4選択肢" = "dotted", "5選択肢" = "dotdash")) +
  ggplot2::labs(x = "選択確率の変化", y = NULL, shape = "選択肢数", linetype = "選択肢数") +
  ggplot2::theme_bw(base_size = 12) +
  ggplot2::theme(legend.position = "top", panel.grid.major.y = ggplot2::element_blank(), panel.grid.minor = ggplot2::element_blank())
図7

表D8 <- readr::read_csv(study_csv("study3", "table_amce_covariate_adjusted.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = paste0(stringr::str_remove(条件, "条件$"), "条件"))
knitr::kable(表日本語(表D8), format = "html", row.names = FALSE, caption = "表D8:図7に対応する共変量調整済みAMCE")
表D8:図7に対応する共変量調整済みAMCE
条件 属性 水準(基準水準との差) 推定値(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値 回答者数
2選択肢条件 政権与党の政党名 立憲民主党 -8.88 3.12 -15.00 -2.76 .005 716
2選択肢条件 政権与党の政党名 日本維新の会 -5.97 2.78 -11.42 -0.53 .032 716
2選択肢条件 政権与党の政党名 公明党 -23.60 2.91 -29.30 -17.89 < .001 716
2選択肢条件 政権与党の政党名 国民民主党 -1.29 2.81 -6.80 4.21 .645 716
2選択肢条件 政権与党の政党名 れいわ新選組 -28.42 3.04 -34.39 -22.45 < .001 716
2選択肢条件 政権与党の政党名 参政党 -14.98 2.78 -20.42 -9.53 < .001 716
2選択肢条件 政権与党の政党名 日本共産党 -33.71 2.91 -39.41 -28.01 < .001 716
2選択肢条件 政権与党の政党名 中道改革連合 -12.57 2.92 -18.30 -6.84 < .001 716
2選択肢条件 政権与党の政党名 チームみらい -5.19 2.82 -10.72 0.34 .066 716
2選択肢条件 GDP成長率 GDP:プラス1% 7.64 1.44 4.82 10.46 < .001 716
2選択肢条件 GDP成長率 GDP:マイナス1% -5.92 1.44 -8.75 -3.09 < .001 716
2選択肢条件 日経平均 日経平均:プラス1000円 2.84 1.42 0.06 5.62 .046 716
2選択肢条件 日経平均 日経平均:マイナス1000円 -5.27 1.43 -8.08 -2.46 < .001 716
2選択肢条件 CPI CPI:プラス1ポイント -0.48 1.43 -3.28 2.31 .735 716
2選択肢条件 CPI CPI:マイナス1ポイント -2.25 1.43 -5.06 0.56 .117 716
2選択肢条件 失業率 失業率:プラス1% -6.05 1.43 -8.85 -3.24 < .001 716
2選択肢条件 失業率 失業率:マイナス1% -1.47 1.42 -4.26 1.32 .301 716
3選択肢条件 政権与党の政党名 立憲民主党 -13.89 2.26 -18.32 -9.46 < .001 939
3選択肢条件 政権与党の政党名 日本維新の会 -9.02 2.05 -13.04 -4.99 < .001 939
3選択肢条件 政権与党の政党名 公明党 -25.32 2.00 -29.24 -21.39 < .001 939
3選択肢条件 政権与党の政党名 国民民主党 -2.57 2.15 -6.79 1.65 .233 939
3選択肢条件 政権与党の政党名 れいわ新選組 -26.05 2.19 -30.35 -21.76 < .001 939
3選択肢条件 政権与党の政党名 参政党 -12.46 2.16 -16.69 -8.22 < .001 939
3選択肢条件 政権与党の政党名 日本共産党 -28.06 2.16 -32.29 -23.84 < .001 939
3選択肢条件 政権与党の政党名 中道改革連合 -18.38 2.26 -22.81 -13.95 < .001 939
3選択肢条件 政権与党の政党名 チームみらい -8.31 2.16 -12.54 -4.07 < .001 939
3選択肢条件 GDP成長率 GDP:プラス1% 7.10 1.00 5.14 9.06 < .001 939
3選択肢条件 GDP成長率 GDP:マイナス1% -4.80 0.97 -6.71 -2.89 < .001 939
3選択肢条件 日経平均 日経平均:プラス1000円 3.38 1.02 1.37 5.39 .001 939
3選択肢条件 日経平均 日経平均:マイナス1000円 -5.27 0.95 -7.13 -3.42 < .001 939
3選択肢条件 CPI CPI:プラス1ポイント -0.44 0.96 -2.33 1.44 .645 939
3選択肢条件 CPI CPI:マイナス1ポイント -1.38 0.94 -3.22 0.46 .142 939
3選択肢条件 失業率 失業率:プラス1% -4.47 0.96 -6.36 -2.58 < .001 939
3選択肢条件 失業率 失業率:マイナス1% -1.96 0.97 -3.87 -0.05 .044 939
4選択肢条件 政権与党の政党名 立憲民主党 -16.35 1.88 -20.03 -12.66 < .001 1063
4選択肢条件 政権与党の政党名 日本維新の会 -9.35 1.73 -12.74 -5.96 < .001 1063
4選択肢条件 政権与党の政党名 公明党 -24.45 1.67 -27.73 -21.17 < .001 1063
4選択肢条件 政権与党の政党名 国民民主党 -4.97 1.80 -8.50 -1.43 .006 1063
4選択肢条件 政権与党の政党名 れいわ新選組 -25.32 1.76 -28.77 -21.88 < .001 1063
4選択肢条件 政権与党の政党名 参政党 -12.38 1.81 -15.93 -8.83 < .001 1063
4選択肢条件 政権与党の政党名 日本共産党 -25.68 1.80 -29.21 -22.15 < .001 1063
4選択肢条件 政権与党の政党名 中道改革連合 -17.95 1.93 -21.72 -14.17 < .001 1063
4選択肢条件 政権与党の政党名 チームみらい -11.30 1.89 -15.01 -7.59 < .001 1063
4選択肢条件 GDP成長率 GDP:プラス1% 5.04 0.76 3.55 6.53 < .001 1063
4選択肢条件 GDP成長率 GDP:マイナス1% -3.49 0.72 -4.91 -2.08 < .001 1063
4選択肢条件 日経平均 日経平均:プラス1000円 3.87 0.80 2.31 5.43 < .001 1063
4選択肢条件 日経平均 日経平均:マイナス1000円 -3.33 0.72 -4.75 -1.91 < .001 1063
4選択肢条件 CPI CPI:プラス1ポイント 0.54 0.73 -0.89 1.98 .459 1063
4選択肢条件 CPI CPI:マイナス1ポイント -1.26 0.73 -2.70 0.18 .087 1063
4選択肢条件 失業率 失業率:プラス1% -3.73 0.71 -5.12 -2.33 < .001 1063
4選択肢条件 失業率 失業率:マイナス1% -2.02 0.73 -3.45 -0.59 .006 1063
5選択肢条件 政権与党の政党名 立憲民主党 -12.98 1.59 -16.11 -9.86 < .001 1314
5選択肢条件 政権与党の政党名 日本維新の会 -8.62 1.42 -11.41 -5.84 < .001 1314
5選択肢条件 政権与党の政党名 公明党 -21.75 1.38 -24.46 -19.04 < .001 1314
5選択肢条件 政権与党の政党名 国民民主党 -5.06 1.49 -7.99 -2.14 < .001 1314
5選択肢条件 政権与党の政党名 れいわ新選組 -21.60 1.41 -24.38 -18.83 < .001 1314
5選択肢条件 政権与党の政党名 参政党 -13.08 1.49 -16.00 -10.15 < .001 1314
5選択肢条件 政権与党の政党名 日本共産党 -21.88 1.42 -24.66 -19.09 < .001 1314
5選択肢条件 政権与党の政党名 中道改革連合 -16.65 1.50 -19.60 -13.70 < .001 1314
5選択肢条件 政権与党の政党名 チームみらい -12.21 1.51 -15.17 -9.26 < .001 1314
5選択肢条件 GDP成長率 GDP:プラス1% 5.49 0.59 4.33 6.64 < .001 1314
5選択肢条件 GDP成長率 GDP:マイナス1% -2.10 0.52 -3.13 -1.08 < .001 1314
5選択肢条件 日経平均 日経平均:プラス1000円 3.78 0.55 2.70 4.86 < .001 1314
5選択肢条件 日経平均 日経平均:マイナス1000円 -2.15 0.53 -3.19 -1.12 < .001 1314
5選択肢条件 CPI CPI:プラス1ポイント 0.42 0.53 -0.62 1.47 .428 1314
5選択肢条件 CPI CPI:マイナス1ポイント -0.10 0.55 -1.18 0.99 .863 1314
5選択肢条件 失業率 失業率:プラス1% -2.85 0.56 -3.93 -1.76 < .001 1314
5選択肢条件 失業率 失業率:マイナス1% -0.89 0.56 -1.98 0.20 .108 1314

図8:実験3(2026年)の政党名・経済手がかりの重要度と相対比重

図8重要度データ <- study3_env$relative_panel_adjusted_data
図8相対比重データ <- study3_env$relative_panel_b_data
図8パネルA <- study3_env$relative_panel_adjusted
図8パネルB <- study3_env$relative_panel_c
図8 <- (図8パネルA | 図8パネルB) + patchwork::plot_layout(widths = c(1, 1))
図8

表D9 <- readr::read_csv(study_csv("study3", "table_marginal_means.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性", level = "水準")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study3"), 属性 = 属性日本語(属性))
knitr::kable(表日本語(表D9), format = "html", row.names = FALSE, caption = "表D9:限界平均")
表D9:限界平均
条件 手がかり群 属性 水準 限界平均(%) クラスタSE(pp) 95% CI下限(%) 95% CI上限(%) プロファイル数 回答者数
2選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 50.82 0.85 49.15 52.48 2387 706
2選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 50.27 0.85 48.62 51.93 2387 697
2選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 48.91 0.86 47.23 50.59 2386 707
2選択肢 経済の手がかり GDP成長率 GDP成長率±0% 49.53 0.85 47.87 51.19 2344 705
2選択肢 経済の手がかり GDP成長率 GDP成長率プラス1% 57.15 0.84 55.50 58.80 2425 708
2選択肢 経済の手がかり GDP成長率 GDP成長率マイナス1% 43.20 0.87 41.51 44.90 2391 701
2選択肢 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 53.29 0.86 51.60 54.98 2357 709
2選択肢 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 45.62 0.85 43.96 47.29 2400 706
2選択肢 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 51.14 0.84 49.50 52.79 2403 707
2選択肢 政党の手がかり 政党名 れいわ新選組 35.36 2.01 31.41 39.30 676 465
2選択肢 政党の手がかり 政党名 チームみらい 58.49 1.93 54.71 62.28 730 475
2選択肢 政党の手がかり 政党名 中道改革連合 50.41 1.90 46.68 54.14 728 471
2選択肢 政党の手がかり 政党名 公明党 39.29 1.95 35.46 43.11 700 479
2選択肢 政党の手がかり 政党名 参政党 48.53 1.95 44.70 52.36 746 512
2選択肢 政党の手がかり 政党名 国民民主党 62.16 1.94 58.37 65.96 703 468
2選択肢 政党の手がかり 政党名 日本共産党 29.52 1.90 25.80 33.24 708 484
2選択肢 政党の手がかり 政党名 日本維新の会 57.49 2.03 53.51 61.47 734 476
2選択肢 政党の手がかり 政党名 立憲民主党 54.44 2.07 50.39 58.49 720 466
2選択肢 政党の手がかり 政党名 自由民主党 62.94 1.94 59.14 66.74 715 481
2選択肢 経済の手がかり 失業率 失業率前期比±0% 52.94 0.83 51.31 54.56 2433 708
2選択肢 経済の手がかり 失業率 失業率前期比プラス1% 46.41 0.84 44.76 48.07 2383 705
2選択肢 経済の手がかり 失業率 失業率前期比マイナス1% 50.60 0.86 48.91 52.29 2344 709
3選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 33.86 0.56 32.77 34.96 4728 937
3選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 33.51 0.57 32.39 34.63 4700 934
3選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 32.62 0.56 31.51 33.72 4657 935
3選択肢 経済の手がかり GDP成長率 GDP成長率±0% 32.55 0.57 31.43 33.66 4704 937
3選択肢 経済の手がかり GDP成長率 GDP成長率プラス1% 39.61 0.61 38.41 40.81 4701 936
3選択肢 経済の手がかり GDP成長率 GDP成長率マイナス1% 27.82 0.59 26.66 28.98 4680 935
3選択肢 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 37.31 0.61 36.11 38.51 4661 938
3選択肢 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 28.75 0.57 27.63 29.86 4679 937
3選択肢 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 33.95 0.58 32.82 35.08 4745 935
3選択肢 政党の手がかり 政党名 れいわ新選組 21.61 1.26 19.15 24.08 1388 808
3選択肢 政党の手がかり 政党名 チームみらい 39.42 1.41 36.65 42.18 1403 779
3選択肢 政党の手がかり 政党名 中道改革連合 29.22 1.36 26.55 31.89 1451 800
3選択肢 政党の手がかり 政党名 公明党 22.58 1.19 20.25 24.90 1382 778
3選択肢 政党の手がかり 政党名 参政党 35.54 1.48 32.63 38.44 1376 776
3選択肢 政党の手がかり 政党名 国民民主党 45.02 1.43 42.21 47.83 1446 791
3選択肢 政党の手がかり 政党名 日本共産党 19.49 1.24 17.06 21.92 1452 782
3選択肢 政党の手がかり 政党名 日本維新の会 38.85 1.48 35.95 41.76 1413 771
3選択肢 政党の手がかり 政党名 立憲民主党 33.87 1.39 31.14 36.59 1376 778
3選択肢 政党の手がかり 政党名 自由民主党 47.78 1.53 44.78 50.79 1398 791
3選択肢 経済の手がかり 失業率 失業率前期比±0% 35.76 0.56 34.67 36.85 4771 936
3選択肢 経済の手がかり 失業率 失業率前期比プラス1% 30.77 0.59 29.61 31.92 4677 936
3選択肢 経済の手がかり 失業率 失業率前期比マイナス1% 33.43 0.60 32.25 34.61 4637 937
4選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 25.18 0.42 24.35 26.01 7180 1062
4選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 25.83 0.46 24.94 26.72 6988 1063
4選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 24.00 0.45 23.11 24.89 7092 1063
4選択肢 経済の手がかり GDP成長率 GDP成長率±0% 24.43 0.43 23.59 25.27 7090 1063
4選択肢 経済の手がかり GDP成長率 GDP成長率プラス1% 29.52 0.46 28.61 30.43 7104 1060
4選択肢 経済の手がかり GDP成長率 GDP成長率マイナス1% 21.03 0.44 20.17 21.89 7066 1063
4選択肢 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 28.78 0.47 27.85 29.71 7057 1063
4選択肢 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 21.55 0.43 20.71 22.39 7206 1063
4選択肢 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 24.74 0.44 23.87 25.61 6997 1063
4選択肢 政党の手がかり 政党名 れいわ新選組 14.42 0.89 12.67 16.16 2164 978
4選択肢 政党の手がかり 政党名 チームみらい 28.40 1.13 26.19 30.62 2144 977
4選択肢 政党の手がかり 政党名 中道改革連合 21.79 1.10 19.64 23.94 2079 970
4選択肢 政党の手がかり 政党名 公明党 15.49 0.90 13.72 17.25 2150 992
4選択肢 政党の手がかり 政党名 参政党 27.28 1.14 25.04 29.52 2126 975
4選択肢 政党の手がかり 政党名 国民民主党 34.80 1.18 32.49 37.11 2115 982
4選択肢 政党の手がかり 政党名 日本共産党 14.24 0.90 12.48 16.00 2184 988
4選択肢 政党の手がかり 政党名 日本維新の会 30.69 1.15 28.44 32.95 2108 987
4選択肢 政党の手がかり 政党名 立憲民主党 23.50 1.07 21.40 25.59 2060 978
4選択肢 政党の手がかり 政党名 自由民主党 39.91 1.34 37.29 42.52 2130 976
4選択肢 経済の手がかり 失業率 失業率前期比±0% 27.07 0.42 26.25 27.89 7067 1063
4選択肢 経済の手がかり 失業率 失業率前期比プラス1% 23.14 0.42 22.31 23.97 7087 1062
4選択肢 経済の手がかり 失業率 失業率前期比マイナス1% 24.80 0.43 23.94 25.65 7106 1062
5選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比±0ポイント 19.78 0.31 19.16 20.39 10978 1314
5選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比プラス1ポイント 20.43 0.32 19.80 21.07 11001 1314
5選択肢 経済の手がかり 消費者物価指数(CPI) CPI前期比マイナス1ポイント 19.79 0.34 19.13 20.45 10871 1314
5選択肢 経済の手がかり GDP成長率 GDP成長率±0% 18.91 0.32 18.29 19.54 10924 1314
5選択肢 経済の手がかり GDP成長率 GDP成長率プラス1% 24.36 0.36 23.64 25.07 10954 1314
5選択肢 経済の手がかり GDP成長率 GDP成長率マイナス1% 16.73 0.33 16.09 17.38 10972 1314
5選択肢 経済の手がかり 日経平均株価 日経平均前月同期比プラス1000円 23.22 0.33 22.57 23.87 11046 1314
5選択肢 経済の手がかり 日経平均株価 日経平均前月同期比マイナス1000円 17.33 0.33 16.69 17.97 10806 1314
5選択肢 経済の手がかり 日経平均株価 日経平均前月同期比変わらず 19.39 0.31 18.78 19.99 10998 1314
5選択肢 政党の手がかり 政党名 れいわ新選組 11.66 0.67 10.34 12.97 3277 1281
5選択肢 政党の手がかり 政党名 チームみらい 21.13 0.87 19.43 22.83 3351 1281
5選択肢 政党の手がかり 政党名 中道改革連合 16.82 0.80 15.26 18.39 3311 1275
5選択肢 政党の手がかり 政党名 公明党 11.63 0.67 10.31 12.94 3243 1262
5選択肢 政党の手がかり 政党名 参政党 20.21 0.89 18.47 21.96 3280 1270
5選択肢 政党の手がかり 政党名 国民民主党 28.33 0.92 26.51 30.14 3315 1274
5選択肢 政党の手がかり 政党名 日本共産党 11.49 0.67 10.18 12.81 3271 1276
5選択肢 政党の手がかり 政党名 日本維新の会 24.77 0.93 22.93 26.60 3218 1275
5選択肢 政党の手がかり 政党名 立憲民主党 20.46 0.88 18.73 22.18 3290 1277
5選択肢 政党の手がかり 政党名 自由民主党 33.33 1.11 31.16 35.51 3294 1278
5選択肢 経済の手がかり 失業率 失業率前期比±0% 21.24 0.32 20.60 21.88 10965 1314
5選択肢 経済の手がかり 失業率 失業率前期比プラス1% 18.51 0.33 17.86 19.16 10768 1313
5選択肢 経済の手がかり 失業率 失業率前期比マイナス1% 20.22 0.32 19.59 20.85 11117 1314
表D10 <- readr::read_csv(study_csv("study3", "table_attribute_importance.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study3"), 属性 = 属性日本語(属性))
knitr::kable(表日本語(表D10), format = "html", row.names = FALSE, caption = "表D10:属性重要度")
表D10:属性重要度
条件 手がかり群 属性 水準数 未調整重要度(pp) 選択肢数調整済み重要度(%)
2選択肢条件 経済の手がかり 消費者物価指数(CPI) 3 1.27 2.54
2選択肢条件 経済の手がかり GDP成長率 3 9.30 18.60
2選択肢条件 経済の手がかり 日経平均株価 3 5.11 10.22
2選択肢条件 政党の手がかり 政党名 10 13.68 27.35
2選択肢条件 経済の手がかり 失業率 3 4.35 8.70
3選択肢条件 経済の手がかり 消費者物価指数(CPI) 3 0.83 2.49
3選択肢条件 経済の手がかり GDP成長率 3 7.86 23.58
3選択肢条件 経済の手がかり 日経平均株価 3 5.71 17.13
3選択肢条件 政党の手がかり 政党名 10 11.85 35.55
3選択肢条件 経済の手がかり 失業率 3 3.33 9.98
4選択肢条件 経済の手がかり 消費者物価指数(CPI) 3 1.22 4.88
4選択肢条件 経済の手がかり GDP成長率 3 5.66 22.64
4選択肢条件 経済の手がかり 日経平均株価 3 4.82 19.28
4選択肢条件 政党の手がかり 政党名 10 10.52 42.07
4選択肢条件 経済の手がかり 失業率 3 2.62 10.48
5選択肢条件 経済の手がかり 消費者物価指数(CPI) 3 0.44 2.20
5選択肢条件 経済の手がかり GDP成長率 3 5.08 25.41
5選択肢条件 経済の手がかり 日経平均株価 3 3.93 19.63
5選択肢条件 政党の手がかり 政党名 10 8.71 43.57
5選択肢条件 経済の手がかり 失業率 3 1.82 9.11
表D11 <- readr::read_csv(study_csv("study3", "table_cue_importance.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", statistic = "指標")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study3"), 指標 = 統計量日本語(指標, "study3"))
knitr::kable(表日本語(表D11), format = "html", row.names = FALSE, caption = "表D11:政党名・経済手がかりの重要度と相対比重")
表D11:政党名・経済手がかりの重要度と相対比重
条件 指標 単位 推定値 95% CI下限 95% CI上限
2選択肢条件 政党手がかり:未調整重要度 pp 13.68 12.04 15.55
2選択肢条件 経済手がかり:未調整重要度 pp 5.01 4.18 6.05
2選択肢条件 政党手がかり:選択肢数調整済み重要度 % 27.35 24.08 31.09
2選択肢条件 経済手がかり:選択肢数調整済み重要度 % 10.02 8.36 12.09
2選択肢条件 政党手がかりの相対比重 % 73.20 68.24 77.40
3選択肢条件 政党手がかり:未調整重要度 pp 11.85 10.54 13.20
3選択肢条件 経済手がかり:未調整重要度 pp 4.43 3.85 5.10
3選択肢条件 政党手がかり:選択肢数調整済み重要度 % 35.55 31.61 39.59
3選択肢条件 経済手がかり:選択肢数調整済み重要度 % 13.29 11.55 15.31
3選択肢条件 政党手がかりの相対比重 % 72.78 68.90 76.46
4選択肢条件 政党手がかり:未調整重要度 pp 10.52 9.54 11.69
4選択肢条件 経済手がかり:未調整重要度 pp 3.58 3.05 4.09
4選択肢条件 政党手がかり:選択肢数調整済み重要度 % 42.07 38.15 46.76
4選択肢条件 経済手がかり:選択肢数調整済み重要度 % 14.32 12.21 16.37
4選択肢条件 政党手がかりの相対比重 % 74.61 71.03 78.20
5選択肢条件 政党手がかり:未調整重要度 pp 8.71 8.04 9.57
5選択肢条件 経済手がかり:未調整重要度 pp 2.82 2.46 3.26
5選択肢条件 政党手がかり:選択肢数調整済み重要度 % 43.57 40.22 47.87
5選択肢条件 経済手がかり:選択肢数調整済み重要度 % 14.08 12.31 16.30
5選択肢条件 政党手がかりの相対比重 % 75.57 72.24 78.63

図9:実験3(2026年)の支持政党と提示政党名の一致効果

図9 <- study3_env$p_party_match
図9

表D12元 <- readr::read_csv(study_csv("study3", "table_party_match.csv"), show_col_types = FALSE)

表D12条件列 <- intersect(c("選択肢数", "条件", "party_n"), names(表D12元))
if (length(表D12条件列) == 0) stop("Check condition column")
表D12条件列 <- 表D12条件列[[1]]

if (!"回答者数" %in% names(表D12元)) {
  表D12元$回答者数 <- NA_character_
}

実験3条件人数 <- study3_env$conjoint_all_m %>%
  dplyr::distinct(ID, party_n) %>%
  dplyr::count(party_n, name = "回答者数補完")

表D12 <- 表D12元 %>%
  dplyr::mutate(条件数 = 数値列(.data[[表D12条件列]])) %>%
  dplyr::select(-dplyr::all_of(表D12条件列)) %>%
  dplyr::left_join(実験3条件人数, by = c("条件数" = "party_n")) %>%
  dplyr::mutate(
    回答者数 = dplyr::coalesce(数値列(回答者数), 回答者数補完),
    条件 = 条件日本語(条件数, "study3")
  ) %>%
  dplyr::select(-条件数, -回答者数補完) %>%
  dplyr::relocate(条件, .after = 対象)

knitr::kable(
  表日本語(表D12),
  format = "html",
  row.names = FALSE,
  caption = "表D12:支持政党と提示政党名の一致効果"
)
表D12:支持政党と提示政党名の一致効果
対象 条件 一致効果(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値 回答者数
全体 2選択肢条件 28.82 2.86 23.21 34.43 < .001 716
全体 3選択肢条件 38.91 2.17 34.66 43.16 < .001 939
全体 4選択肢条件 44.35 1.99 40.44 48.25 < .001 1063
全体 5選択肢条件 44.83 1.82 41.25 48.41 < .001 1314
自民党支持者 2選択肢条件 34.77 3.43 28.06 41.49 < .001 163
自民党支持者 3選択肢条件 42.74 3.13 36.61 48.87 < .001 219
自民党支持者 4選択肢条件 47.62 2.88 41.97 53.28 < .001 254
自民党支持者 5選択肢条件 49.55 2.70 44.26 54.84 < .001 311
中道改革支持者 2選択肢条件 27.10 13.17 1.30 52.91 .052 23
中道改革支持者 3選択肢条件 35.16 9.34 16.85 53.48 .001 23
中道改革支持者 4選択肢条件 36.97 7.47 22.33 51.60 < .001 34
中道改革支持者 5選択肢条件 46.37 7.16 32.33 60.40 < .001 40
立憲支持者 2選択肢条件 18.12 12.01 -5.41 41.66 .144 26
立憲支持者 3選択肢条件 46.89 7.00 33.16 60.61 < .001 38
立憲支持者 4選択肢条件 41.34 5.79 30.00 52.69 < .001 37
立憲支持者 5選択肢条件 40.03 6.09 28.09 51.97 < .001 63
参政党支持者 2選択肢条件 39.23 7.32 24.88 53.59 < .001 30
参政党支持者 3選択肢条件 53.61 6.14 41.57 65.65 < .001 46
参政党支持者 4選択肢条件 62.99 5.48 52.25 73.72 < .001 42
参政党支持者 5選択肢条件 61.03 5.53 50.20 71.86 < .001 52

E. 実験1(2023年)の補足分析

補図E1:共変量を含めないAMCE

補図E1データ <- study1_env$amce_plot_df_nocov_facet
補図E1 <- study1_env$p_amce_facet_nocov
補図E1

表E1 <- readr::read_csv(study_csv("study1", "table_amce_unadjusted.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = paste0(stringr::str_remove(条件, "条件$"), "条件"))
knitr::kable(表日本語(表E1), format = "html", row.names = FALSE)
条件 属性 水準(基準水準との差) 推定値(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値 回答者数
2政党条件 政策位置 右派・保守的 -2.50 1.44 -5.32 0.32 .082 815
2政党条件 政策位置 左派・革新的 -8.04 1.43 -10.85 -5.23 < .001 815
2政党条件 与党/野党 与党 4.77 1.21 2.40 7.14 < .001 815
2政党条件 GDP成長率 GDP:プラス1% 7.72 1.40 4.99 10.46 < .001 815
2政党条件 GDP成長率 GDP:マイナス1% -2.74 1.37 -5.44 -0.05 .046 815
2政党条件 日経平均 日経平均:プラス1000円 6.33 1.39 3.62 9.05 < .001 815
2政党条件 日経平均 日経平均:マイナス1000円 -5.45 1.34 -8.08 -2.82 < .001 815
2政党条件 議席数 議席数:10~49 2.14 1.74 -1.26 5.55 .218 815
2政党条件 議席数 議席数:50~99 7.52 1.76 4.08 10.97 < .001 815
2政党条件 議席数 議席数:100~199 8.89 1.78 5.40 12.39 < .001 815
2政党条件 議席数 議席数:200以上 10.72 1.83 7.12 14.31 < .001 815
2政党条件 CPI CPI:プラス1ポイント -0.14 1.38 -2.85 2.56 .918 815
2政党条件 CPI CPI:マイナス1ポイント -1.13 1.38 -3.83 1.56 .410 815
2政党条件 失業率 失業率:プラス1% -4.50 1.38 -7.21 -1.79 .001 815
2政党条件 失業率 失業率:マイナス1% -2.82 1.39 -5.54 -0.10 .042 815
3政党条件 政策位置 右派・保守的 -4.78 1.22 -7.17 -2.40 < .001 843
3政党条件 政策位置 左派・革新的 -8.99 1.22 -11.39 -6.59 < .001 843
3政党条件 与党/野党 与党 3.50 1.10 1.35 5.65 .001 843
3政党条件 GDP成長率 GDP:プラス1% 8.04 1.02 6.04 10.05 < .001 843
3政党条件 GDP成長率 GDP:マイナス1% -2.67 0.96 -4.55 -0.80 .005 843
3政党条件 日経平均 日経平均:プラス1000円 6.05 1.06 3.99 8.12 < .001 843
3政党条件 日経平均 日経平均:マイナス1000円 -4.23 1.04 -6.27 -2.19 < .001 843
3政党条件 議席数 議席数:10~49 3.67 1.24 1.24 6.09 .003 843
3政党条件 議席数 議席数:50~99 8.36 1.28 5.86 10.86 < .001 843
3政党条件 議席数 議席数:100~199 11.70 1.48 8.79 14.60 < .001 843
3政党条件 議席数 議席数:200以上 11.27 1.52 8.29 14.25 < .001 843
3政党条件 CPI CPI:プラス1ポイント 1.16 1.01 -0.82 3.13 .252 843
3政党条件 CPI CPI:マイナス1ポイント 0.15 1.01 -1.83 2.12 .885 843
3政党条件 失業率 失業率:プラス1% -3.40 1.05 -5.47 -1.34 .001 843
3政党条件 失業率 失業率:マイナス1% -2.05 1.06 -4.12 0.03 .054 843
4政党条件 政策位置 右派・保守的 -5.27 0.99 -7.22 -3.32 < .001 882
4政党条件 政策位置 左派・革新的 -8.27 0.99 -10.21 -6.33 < .001 882
4政党条件 与党/野党 与党 4.26 0.95 2.40 6.13 < .001 882
4政党条件 GDP成長率 GDP:プラス1% 7.38 0.88 5.66 9.11 < .001 882
4政党条件 GDP成長率 GDP:マイナス1% -3.46 0.78 -4.98 -1.94 < .001 882
4政党条件 日経平均 日経平均:プラス1000円 3.24 0.86 1.55 4.93 < .001 882
4政党条件 日経平均 日経平均:マイナス1000円 -5.21 0.77 -6.71 -3.71 < .001 882
4政党条件 議席数 議席数:10~49 3.79 0.89 2.05 5.53 < .001 882
4政党条件 議席数 議席数:50~99 6.68 0.99 4.74 8.62 < .001 882
4政党条件 議席数 議席数:100~199 10.16 1.14 7.93 12.40 < .001 882
4政党条件 議席数 議席数:200以上 9.90 1.30 7.35 12.45 < .001 882
4政党条件 CPI CPI:プラス1ポイント 2.79 0.81 1.21 4.38 < .001 882
4政党条件 CPI CPI:マイナス1ポイント 0.05 0.80 -1.53 1.63 .952 882
4政党条件 失業率 失業率:プラス1% -3.58 0.84 -5.23 -1.94 < .001 882
4政党条件 失業率 失業率:マイナス1% -0.45 0.82 -2.05 1.16 .586 882
5政党条件 政策位置 右派・保守的 -4.37 0.85 -6.04 -2.70 < .001 842
5政党条件 政策位置 左派・革新的 -6.56 0.85 -8.23 -4.89 < .001 842
5政党条件 与党/野党 与党 4.94 0.87 3.23 6.65 < .001 842
5政党条件 GDP成長率 GDP:プラス1% 6.41 0.77 4.91 7.92 < .001 842
5政党条件 GDP成長率 GDP:マイナス1% -3.27 0.67 -4.59 -1.95 < .001 842
5政党条件 日経平均 日経平均:プラス1000円 3.79 0.72 2.38 5.19 < .001 842
5政党条件 日経平均 日経平均:マイナス1000円 -4.52 0.65 -5.79 -3.25 < .001 842
5政党条件 議席数 議席数:10~49 3.79 0.71 2.41 5.18 < .001 842
5政党条件 議席数 議席数:50~99 8.21 0.93 6.39 10.03 < .001 842
5政党条件 議席数 議席数:100~199 9.80 1.09 7.67 11.93 < .001 842
5政党条件 議席数 議席数:200以上 10.12 1.14 7.89 12.35 < .001 842
5政党条件 CPI CPI:プラス1ポイント 0.89 0.68 -0.45 2.23 .195 842
5政党条件 CPI CPI:マイナス1ポイント -1.16 0.67 -2.47 0.16 .087 842
5政党条件 失業率 失業率:プラス1% -2.97 0.71 -4.36 -1.59 < .001 842
5政党条件 失業率 失業率:マイナス1% -0.07 0.72 -1.47 1.34 .927 842

補図E2:2政党条件との差

補図E2データ <- study1_env$interaction_plot_df
補図E2 <- study1_env$p_interaction
補図E2

表E2 <- readr::read_csv(study_csv("study1", "table_amce_interaction.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, attribute = "属性")) %>%
  dplyr::mutate(dplyr::across(dplyr::any_of("属性"), 属性日本語))
knitr::kable(表日本語(表E2), format = "html", row.names = FALSE)
比較条件 属性 水準 2選択肢条件との差(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値
3政党 政策位置 右派・保守的 -2.28 1.88 -5.97 1.41 0.226
4政党 政策位置 右派・保守的 -2.77 1.75 -6.19 0.66 0.114
5政党 政策位置 右派・保守的 -1.87 1.67 -5.14 1.41 0.264
3政党 政策位置 左派・革新的 -0.95 1.88 -4.64 2.74 0.613
4政党 政策位置 左派・革新的 -0.23 1.74 -3.64 3.18 0.893
5政党 政策位置 左派・革新的 1.48 1.66 -1.78 4.74 0.374
3政党 与党/野党 与党 -1.27 1.63 -4.47 1.92 0.435
4政党 与党/野党 与党 -0.51 1.54 -3.52 2.50 0.740
5政党 与党/野党 与党 0.17 1.49 -2.75 3.09 0.910
3政党 GDP成長率 GDP:プラス1% 0.32 1.73 -3.07 3.71 0.852
4政党 GDP成長率 GDP:プラス1% -0.34 1.65 -3.57 2.89 0.838
5政党 GDP成長率 GDP:プラス1% -1.31 1.59 -4.43 1.81 0.412
3政党 GDP成長率 GDP:マイナス1% 0.07 1.67 -3.21 3.35 0.967
4政党 GDP成長率 GDP:マイナス1% -0.72 1.58 -3.81 2.38 0.650
5政党 GDP成長率 GDP:マイナス1% -0.53 1.53 -3.53 2.47 0.730
3政党 日経平均 日経平均:プラス1000円 -0.28 1.74 -3.69 3.13 0.873
4政党 日経平均 日経平均:プラス1000円 -3.10 1.63 -6.29 0.10 0.058
5政党 日経平均 日経平均:プラス1000円 -2.55 1.56 -5.60 0.51 0.102
3政党 日経平均 日経平均:マイナス1000円 1.22 1.70 -2.10 4.55 0.471
4政党 日経平均 日経平均:マイナス1000円 0.24 1.54 -2.78 3.27 0.875
5政党 日経平均 日経平均:マイナス1000円 0.93 1.49 -1.99 3.85 0.532
3政党 議席数 議席数:10~49 1.52 2.13 -2.66 5.70 0.475
4政党 議席数 議席数:10~49 1.65 1.95 -2.18 5.47 0.398
5政党 議席数 議席数:10~49 1.65 1.87 -2.02 5.33 0.379
3政党 議席数 議席数:50~99 0.84 2.17 -3.42 5.09 0.700
4政党 議席数 議席数:50~99 -0.84 2.02 -4.80 3.11 0.676
5政党 議席数 議席数:50~99 0.69 1.99 -3.21 4.58 0.729
3政党 議席数 議席数:100~199 2.80 2.32 -1.74 7.35 0.226
4政党 議席数 議席数:100~199 1.27 2.12 -2.87 5.42 0.548
5政党 議席数 議席数:100~199 0.91 2.09 -3.18 4.99 0.664
3政党 議席数 議席数:200以上 0.55 2.38 -4.12 5.22 0.817
4政党 議席数 議席数:200以上 -0.82 2.25 -5.22 3.59 0.717
5政党 議席数 議席数:200以上 -0.60 2.16 -4.82 3.63 0.781
3政党 CPI CPI:プラス1ポイント 1.30 1.71 -2.05 4.65 0.447
4政党 CPI CPI:プラス1ポイント 2.93 1.60 -0.20 6.07 0.066
5政党 CPI CPI:プラス1ポイント 1.03 1.54 -1.99 4.05 0.504
3政党 CPI CPI:マイナス1ポイント 1.28 1.70 -2.06 4.62 0.453
4政党 CPI CPI:マイナス1ポイント 1.18 1.59 -1.94 4.30 0.458
5政党 CPI CPI:マイナス1ポイント -0.02 1.53 -3.02 2.98 0.988
3政党 失業率 失業率:プラス1% 1.10 1.74 -2.30 4.50 0.527
4政党 失業率 失業率:プラス1% 0.92 1.62 -2.25 4.08 0.571
5政党 失業率 失業率:プラス1% 1.53 1.55 -1.52 4.57 0.325
3政党 失業率 失業率:マイナス1% 0.78 1.74 -2.64 4.19 0.657
4政党 失業率 失業率:マイナス1% 2.37 1.61 -0.78 5.53 0.141
5政党 失業率 失業率:マイナス1% 2.76 1.56 -0.31 5.82 0.078

補図E3:条件付きロジット

補図E3 <- study1_env$p_clogit_or
補図E3

表E3 <- readr::read_csv(study_csv("study1", "table_conditional_logit.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性", label = "水準")) %>%
  dplyr::mutate(
    条件 = 条件日本語(条件, "study1"),
    属性 = 属性日本語(属性)
  ) %>%
  dplyr::select(-dplyr::any_of(c("term", "variable", "policy_position", "government_status")))
knitr::kable(表日本語(表E3), format = "html", row.names = FALSE)
条件 属性 水準(基準水準との差) log係数 標準誤差 オッズ比 95% CI下限(OR) 95% CI上限(OR) p値
2政党 政策位置 右派・保守的 -0.115 0.060 0.891 0.792 1.003 .055
2政党 政策位置 左派・革新的 -0.350 0.060 0.705 0.627 0.793 < .001
2政党 与党/野党 与党 0.207 0.051 1.229 1.112 1.359 < .001
2政党 GDP成長率 GDP:プラス1% 0.309 0.058 1.362 1.215 1.526 < .001
2政党 GDP成長率 GDP:マイナス1% -0.133 0.058 0.876 0.782 0.980 .021
2政党 日経平均 日経平均:プラス1000円 0.261 0.059 1.298 1.156 1.457 < .001
2政党 日経平均 日経平均:マイナス1000円 -0.246 0.058 0.782 0.698 0.876 < .001
2政党 議席数 議席数:10~49 0.112 0.074 1.118 0.968 1.291 .130
2政党 議席数 議席数:50~99 0.331 0.074 1.392 1.205 1.608 < .001
2政党 議席数 議席数:100~199 0.378 0.077 1.459 1.255 1.696 < .001
2政党 議席数 議席数:200以上 0.442 0.077 1.555 1.337 1.810 < .001
2政党 CPI CPI:プラス1ポイント 0.020 0.057 1.020 0.911 1.142 .728
2政党 CPI CPI:マイナス1ポイント -0.047 0.058 0.954 0.852 1.068 .414
2政党 失業率 失業率:プラス1% -0.201 0.059 0.818 0.728 0.918 < .001
2政党 失業率 失業率:マイナス1% -0.136 0.058 0.873 0.779 0.978 .019
3政党 政策位置 右派・保守的 -0.225 0.056 0.798 0.716 0.891 < .001
3政党 政策位置 左派・革新的 -0.435 0.059 0.647 0.576 0.726 < .001
3政党 与党/野党 与党 0.177 0.051 1.193 1.080 1.318 < .001
3政党 GDP成長率 GDP:プラス1% 0.373 0.047 1.451 1.323 1.592 < .001
3政党 GDP成長率 GDP:マイナス1% -0.136 0.048 0.872 0.794 0.959 .005
3政党 日経平均 日経平均:プラス1000円 0.283 0.049 1.328 1.207 1.460 < .001
3政党 日経平均 日経平均:マイナス1000円 -0.201 0.051 0.818 0.741 0.903 < .001
3政党 議席数 議席数:10~49 0.197 0.063 1.218 1.076 1.379 .002
3政党 議席数 議席数:50~99 0.410 0.063 1.506 1.330 1.706 < .001
3政党 議席数 議席数:100~199 0.574 0.072 1.776 1.542 2.045 < .001
3政党 議席数 議席数:200以上 0.544 0.073 1.723 1.492 1.989 < .001
3政党 CPI CPI:プラス1ポイント 0.053 0.048 1.054 0.959 1.159 .273
3政党 CPI CPI:マイナス1ポイント -0.001 0.047 0.999 0.911 1.096 .989
3政党 失業率 失業率:プラス1% -0.167 0.049 0.846 0.768 0.932 < .001
3政党 失業率 失業率:マイナス1% -0.103 0.049 0.902 0.819 0.994 .037
4政党 政策位置 右派・保守的 -0.286 0.054 0.752 0.676 0.835 < .001
4政党 政策位置 左派・革新的 -0.468 0.057 0.626 0.560 0.700 < .001
4政党 与党/野党 与党 0.241 0.051 1.273 1.153 1.405 < .001
4政党 GDP成長率 GDP:プラス1% 0.384 0.046 1.468 1.342 1.605 < .001
4政党 GDP成長率 GDP:マイナス1% -0.207 0.047 0.813 0.741 0.891 < .001
4政党 日経平均 日経平均:プラス1000円 0.168 0.045 1.183 1.083 1.293 < .001
4政党 日経平均 日経平均:マイナス1000円 -0.301 0.045 0.740 0.677 0.809 < .001
4政党 議席数 議席数:10~49 0.232 0.056 1.261 1.130 1.406 < .001
4政党 議席数 議席数:50~99 0.399 0.060 1.491 1.326 1.676 < .001
4政党 議席数 議席数:100~199 0.585 0.065 1.795 1.579 2.040 < .001
4政党 議席数 議席数:200以上 0.567 0.073 1.762 1.527 2.033 < .001
4政党 CPI CPI:プラス1ポイント 0.150 0.045 1.161 1.063 1.269 < .001
4政党 CPI CPI:マイナス1ポイント -0.001 0.046 0.999 0.912 1.094 .983
4政党 失業率 失業率:プラス1% -0.204 0.048 0.815 0.742 0.895 < .001
4政党 失業率 失業率:マイナス1% -0.020 0.044 0.981 0.900 1.069 .656
5政党 政策位置 右派・保守的 -0.271 0.054 0.763 0.686 0.848 < .001
5政党 政策位置 左派・革新的 -0.419 0.056 0.657 0.589 0.734 < .001
5政党 与党/野党 与党 0.306 0.052 1.358 1.226 1.504 < .001
5政党 GDP成長率 GDP:プラス1% 0.389 0.046 1.475 1.348 1.615 < .001
5政党 GDP成長率 GDP:マイナス1% -0.228 0.048 0.796 0.725 0.874 < .001
5政党 日経平均 日経平均:プラス1000円 0.231 0.044 1.260 1.157 1.373 < .001
5政党 日経平均 日経平均:マイナス1000円 -0.323 0.046 0.724 0.662 0.792 < .001
5政党 議席数 議席数:10~49 0.275 0.052 1.317 1.190 1.457 < .001
5政党 議席数 議席数:50~99 0.544 0.060 1.722 1.530 1.938 < .001
5政党 議席数 議席数:100~199 0.643 0.068 1.902 1.665 2.172 < .001
5政党 議席数 議席数:200以上 0.651 0.070 1.917 1.671 2.199 < .001
5政党 CPI CPI:プラス1ポイント 0.054 0.044 1.055 0.969 1.149 .216
5政党 CPI CPI:マイナス1ポイント -0.083 0.045 0.920 0.843 1.005 .065
5政党 失業率 失業率:プラス1% -0.190 0.047 0.827 0.754 0.907 < .001
5政党 失業率 失業率:マイナス1% -0.005 0.045 0.995 0.911 1.087 .912

F. 実験2(2026年)の補足分析

本文では実験2のAMCEの方向性を記述し、詳細を補遺に回しているため、共変量調整済みAMCEを補図F1として最初に示す。

補図F1:共変量調整済みAMCE

補図F1データ <- study2_env$amce_plot_df_cov_facet
補図F1 <- study2_env$p_amce_cov_facet
補図F1

表F1 <- readr::read_csv(study_csv("study2", "table_amce_covariate_adjusted.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = paste0(stringr::str_remove(条件, "条件$"), "条件"))
knitr::kable(表日本語(表F1), format = "html", row.names = FALSE)
条件 属性 水準(基準水準との差) 推定値(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値 回答者数
2政党条件 政策位置 右派・保守的 -1.96 1.61 -5.11 1.19 .223 711
2政党条件 政策位置 左派・革新的 -9.43 1.58 -12.53 -6.34 < .001 711
2政党条件 与党/野党 与党 3.43 1.31 0.87 5.99 .009 711
2政党条件 GDP成長率 GDP:プラス1% 8.29 1.56 5.23 11.35 < .001 711
2政党条件 GDP成長率 GDP:マイナス1% -5.54 1.52 -8.52 -2.56 < .001 711
2政党条件 日経平均 日経平均:プラス1000円 4.28 1.49 1.35 7.20 .004 711
2政党条件 日経平均 日経平均:マイナス1000円 -7.03 1.52 -10.01 -4.06 < .001 711
2政党条件 議席数 議席数:10~49 1.05 1.85 -2.58 4.67 .572 711
2政党条件 議席数 議席数:50~99 5.40 1.80 1.87 8.93 .003 711
2政党条件 議席数 議席数:100~199 8.38 2.00 4.46 12.30 < .001 711
2政党条件 議席数 議席数:200以上 8.34 1.99 4.43 12.24 < .001 711
2政党条件 CPI CPI:プラス1ポイント 1.84 1.43 -0.97 4.64 .200 711
2政党条件 CPI CPI:マイナス1ポイント 1.64 1.41 -1.13 4.40 .246 711
2政党条件 失業率 失業率:プラス1% -4.71 1.52 -7.69 -1.73 .002 711
2政党条件 失業率 失業率:マイナス1% -3.02 1.50 -5.96 -0.08 .045 711
3政党条件 政策位置 右派・保守的 -0.29 1.18 -2.59 2.02 .807 1062
3政党条件 政策位置 左派・革新的 -9.14 1.04 -11.19 -7.10 < .001 1062
3政党条件 与党/野党 与党 1.80 0.91 0.02 3.57 .048 1062
3政党条件 GDP成長率 GDP:プラス1% 5.85 0.97 3.95 7.75 < .001 1062
3政党条件 GDP成長率 GDP:マイナス1% -6.32 0.88 -8.05 -4.58 < .001 1062
3政党条件 日経平均 日経平均:プラス1000円 5.06 0.96 3.18 6.94 < .001 1062
3政党条件 日経平均 日経平均:マイナス1000円 -4.63 0.94 -6.46 -2.79 < .001 1062
3政党条件 議席数 議席数:10~49 3.52 1.17 1.23 5.81 .003 1062
3政党条件 議席数 議席数:50~99 7.32 1.19 4.99 9.65 < .001 1062
3政党条件 議席数 議席数:100~199 10.83 1.21 8.46 13.20 < .001 1062
3政党条件 議席数 議席数:200以上 10.08 1.25 7.63 12.52 < .001 1062
3政党条件 CPI CPI:プラス1ポイント 1.32 0.92 -0.47 3.12 .149 1062
3政党条件 CPI CPI:マイナス1ポイント -2.66 0.94 -4.51 -0.81 .005 1062
3政党条件 失業率 失業率:プラス1% -4.23 0.95 -6.09 -2.37 < .001 1062
3政党条件 失業率 失業率:マイナス1% -1.38 0.96 -3.26 0.50 .150 1062
4政党条件 政策位置 右派・保守的 1.11 0.98 -0.82 3.03 .260 1097
4政党条件 政策位置 左派・革新的 -8.64 0.86 -10.32 -6.96 < .001 1097
4政党条件 与党/野党 与党 1.85 0.72 0.43 3.27 .011 1097
4政党条件 GDP成長率 GDP:プラス1% 6.40 0.76 4.92 7.89 < .001 1097
4政党条件 GDP成長率 GDP:マイナス1% -4.84 0.69 -6.19 -3.50 < .001 1097
4政党条件 日経平均 日経平均:プラス1000円 2.72 0.77 1.20 4.23 < .001 1097
4政党条件 日経平均 日経平均:マイナス1000円 -5.12 0.71 -6.52 -3.73 < .001 1097
4政党条件 議席数 議席数:10~49 5.18 0.87 3.47 6.89 < .001 1097
4政党条件 議席数 議席数:50~99 8.18 0.94 6.34 10.02 < .001 1097
4政党条件 議席数 議席数:100~199 11.17 0.97 9.28 13.07 < .001 1097
4政党条件 議席数 議席数:200以上 11.28 1.02 9.28 13.29 < .001 1097
4政党条件 CPI CPI:プラス1ポイント 1.67 0.74 0.21 3.12 .025 1097
4政党条件 CPI CPI:マイナス1ポイント -0.57 0.73 -2.00 0.86 .433 1097
4政党条件 失業率 失業率:プラス1% -4.23 0.75 -5.70 -2.76 < .001 1097
4政党条件 失業率 失業率:マイナス1% -1.18 0.79 -2.73 0.37 .136 1097
5政党条件 政策位置 右派・保守的 1.01 0.78 -0.52 2.55 .195 1322
5政党条件 政策位置 左派・革新的 -6.08 0.68 -7.42 -4.75 < .001 1322
5政党条件 与党/野党 与党 2.76 0.55 1.68 3.83 < .001 1322
5政党条件 GDP成長率 GDP:プラス1% 5.07 0.59 3.91 6.23 < .001 1322
5政党条件 GDP成長率 GDP:マイナス1% -2.96 0.52 -3.98 -1.94 < .001 1322
5政党条件 日経平均 日経平均:プラス1000円 4.09 0.58 2.97 5.22 < .001 1322
5政党条件 日経平均 日経平均:マイナス1000円 -3.13 0.55 -4.20 -2.07 < .001 1322
5政党条件 議席数 議席数:10~49 2.26 0.63 1.02 3.50 < .001 1322
5政党条件 議席数 議席数:50~99 6.91 0.70 5.54 8.28 < .001 1322
5政党条件 議席数 議席数:100~199 9.65 0.75 8.18 11.12 < .001 1322
5政党条件 議席数 議席数:200以上 10.56 0.77 9.05 12.08 < .001 1322
5政党条件 CPI CPI:プラス1ポイント 0.28 0.54 -0.78 1.35 .602 1322
5政党条件 CPI CPI:マイナス1ポイント -0.43 0.55 -1.50 0.65 .436 1322
5政党条件 失業率 失業率:プラス1% -2.36 0.55 -3.43 -1.28 < .001 1322
5政党条件 失業率 失業率:マイナス1% -0.19 0.59 -1.34 0.97 .753 1322

補図F2:共変量を含めないAMCE

補図F2データ <- study2_env$amce_plot_df_nocov_facet
補図F2 <- study2_env$p_amce_facet_nocov
補図F2

表F2 <- readr::read_csv(study_csv("study2", "table_amce_unadjusted.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = paste0(stringr::str_remove(条件, "条件$"), "条件"))
knitr::kable(表日本語(表F2), format = "html", row.names = FALSE)
条件 属性 水準(基準水準との差) 推定値(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値 回答者数
2政党条件 政策位置 右派・保守的 -1.94 1.60 -5.08 1.19 .225 711
2政党条件 政策位置 左派・革新的 -9.40 1.57 -12.48 -6.31 < .001 711
2政党条件 与党/野党 与党 3.43 1.30 0.88 5.98 .009 711
2政党条件 GDP成長率 GDP:プラス1% 8.26 1.56 5.21 11.31 < .001 711
2政党条件 GDP成長率 GDP:マイナス1% -5.53 1.51 -8.49 -2.56 < .001 711
2政党条件 日経平均 日経平均:プラス1000円 4.27 1.49 1.36 7.18 .004 711
2政党条件 日経平均 日経平均:マイナス1000円 -7.01 1.51 -9.97 -4.05 < .001 711
2政党条件 議席数 議席数:10~49 1.03 1.84 -2.59 4.64 .578 711
2政党条件 議席数 議席数:50~99 5.37 1.79 1.86 8.89 .003 711
2政党条件 議席数 議席数:100~199 8.35 1.99 4.45 12.25 < .001 711
2政党条件 議席数 議席数:200以上 8.33 1.98 4.44 12.21 < .001 711
2政党条件 CPI CPI:プラス1ポイント 1.85 1.43 -0.95 4.64 .195 711
2政党条件 CPI CPI:マイナス1ポイント 1.62 1.40 -1.14 4.37 .250 711
2政党条件 失業率 失業率:プラス1% -4.72 1.51 -7.68 -1.75 .002 711
2政党条件 失業率 失業率:マイナス1% -3.02 1.49 -5.95 -0.10 .043 711
3政党条件 政策位置 右派・保守的 -0.28 1.17 -2.58 2.02 .810 1062
3政党条件 政策位置 左派・革新的 -9.12 1.04 -11.16 -7.08 < .001 1062
3政党条件 与党/野党 与党 1.79 0.91 0.01 3.56 .049 1062
3政党条件 GDP成長率 GDP:プラス1% 5.85 0.97 3.95 7.74 < .001 1062
3政党条件 GDP成長率 GDP:マイナス1% -6.31 0.88 -8.03 -4.58 < .001 1062
3政党条件 日経平均 日経平均:プラス1000円 5.05 0.96 3.18 6.93 < .001 1062
3政党条件 日経平均 日経平均:マイナス1000円 -4.62 0.93 -6.46 -2.79 < .001 1062
3政党条件 議席数 議席数:10~49 3.52 1.17 1.23 5.81 .003 1062
3政党条件 議席数 議席数:50~99 7.31 1.19 4.99 9.63 < .001 1062
3政党条件 議席数 議席数:100~199 10.81 1.21 8.45 13.18 < .001 1062
3政党条件 議席数 議席数:200以上 10.06 1.24 7.62 12.50 < .001 1062
3政党条件 CPI CPI:プラス1ポイント 1.33 0.92 -0.47 3.13 .148 1062
3政党条件 CPI CPI:マイナス1ポイント -2.66 0.94 -4.51 -0.81 .005 1062
3政党条件 失業率 失業率:プラス1% -4.23 0.95 -6.08 -2.37 < .001 1062
3政党条件 失業率 失業率:マイナス1% -1.39 0.96 -3.26 0.49 .147 1062
4政党条件 政策位置 右派・保守的 1.11 0.98 -0.82 3.03 .260 1097
4政党条件 政策位置 左派・革新的 -8.63 0.86 -10.31 -6.96 < .001 1097
4政党条件 与党/野党 与党 1.85 0.72 0.43 3.27 .011 1097
4政党条件 GDP成長率 GDP:プラス1% 6.40 0.76 4.91 7.88 < .001 1097
4政党条件 GDP成長率 GDP:マイナス1% -4.84 0.69 -6.18 -3.50 < .001 1097
4政党条件 日経平均 日経平均:プラス1000円 2.72 0.77 1.20 4.23 < .001 1097
4政党条件 日経平均 日経平均:マイナス1000円 -5.12 0.71 -6.51 -3.73 < .001 1097
4政党条件 議席数 議席数:10~49 5.18 0.87 3.47 6.88 < .001 1097
4政党条件 議席数 議席数:50~99 8.17 0.94 6.33 10.01 < .001 1097
4政党条件 議席数 議席数:100~199 11.17 0.96 9.28 13.06 < .001 1097
4政党条件 議席数 議席数:200以上 11.28 1.02 9.28 13.28 < .001 1097
4政党条件 CPI CPI:プラス1ポイント 1.67 0.74 0.22 3.12 .024 1097
4政党条件 CPI CPI:マイナス1ポイント -0.57 0.73 -1.99 0.86 .435 1097
4政党条件 失業率 失業率:プラス1% -4.22 0.75 -5.69 -2.75 < .001 1097
4政党条件 失業率 失業率:マイナス1% -1.18 0.79 -2.73 0.37 .137 1097
5政党条件 政策位置 右派・保守的 1.02 0.78 -0.51 2.55 .194 1322
5政党条件 政策位置 左派・革新的 -6.08 0.68 -7.41 -4.75 < .001 1322
5政党条件 与党/野党 与党 2.75 0.55 1.67 3.82 < .001 1322
5政党条件 GDP成長率 GDP:プラス1% 5.07 0.59 3.91 6.23 < .001 1322
5政党条件 GDP成長率 GDP:マイナス1% -2.96 0.52 -3.97 -1.94 < .001 1322
5政党条件 日経平均 日経平均:プラス1000円 4.09 0.57 2.96 5.22 < .001 1322
5政党条件 日経平均 日経平均:マイナス1000円 -3.13 0.55 -4.20 -2.06 < .001 1322
5政党条件 議席数 議席数:10~49 2.26 0.63 1.02 3.50 < .001 1322
5政党条件 議席数 議席数:50~99 6.91 0.70 5.54 8.27 < .001 1322
5政党条件 議席数 議席数:100~199 9.65 0.75 8.18 11.12 < .001 1322
5政党条件 議席数 議席数:200以上 10.56 0.77 9.05 12.07 < .001 1322
5政党条件 CPI CPI:プラス1ポイント 0.28 0.54 -0.78 1.35 .602 1322
5政党条件 CPI CPI:マイナス1ポイント -0.42 0.55 -1.50 0.65 .438 1322
5政党条件 失業率 失業率:プラス1% -2.36 0.55 -3.44 -1.28 < .001 1322
5政党条件 失業率 失業率:マイナス1% -0.19 0.59 -1.34 0.96 .749 1322

補図F3:2政党条件との差

補図F3データ <- study2_env$interaction_plot_df
補図F3 <- study2_env$p_interaction
補図F3

表F3 <- readr::read_csv(study_csv("study2", "table_amce_interaction.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, attribute = "属性")) %>%
  dplyr::mutate(dplyr::across(dplyr::any_of("属性"), 属性日本語))
knitr::kable(表日本語(表F3), format = "html", row.names = FALSE)
比較条件 属性 水準 2選択肢条件との差(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値
3政党 政策位置 右派・保守的 1.66 1.98 -2.22 5.55 0.402
4政党 政策位置 右派・保守的 3.05 1.88 -0.63 6.73 0.104
5政党 政策位置 右派・保守的 2.96 1.78 -0.53 6.45 0.096
3政党 政策位置 左派・革新的 0.28 1.88 -3.42 3.97 0.882
4政党 政策位置 左派・革新的 0.77 1.79 -2.74 4.27 0.668
5政党 政策位置 左派・革新的 3.32 1.71 -0.04 6.68 0.053
3政党 与党/野党 与党 -1.64 1.58 -4.74 1.46 0.300
4政党 与党/野党 与党 -1.58 1.49 -4.49 1.33 0.288
5政党 与党/野党 与党 -0.68 1.41 -3.44 2.08 0.630
3政党 GDP成長率 GDP:プラス1% -2.42 1.83 -6.00 1.17 0.187
4政党 GDP成長率 GDP:プラス1% -1.87 1.73 -5.25 1.52 0.280
5政党 GDP成長率 GDP:プラス1% -3.20 1.66 -6.45 0.06 0.055
3政党 GDP成長率 GDP:マイナス1% -0.78 1.75 -4.21 2.65 0.656
4政党 GDP成長率 GDP:マイナス1% 0.69 1.66 -2.56 3.93 0.679
5政党 GDP成長率 GDP:マイナス1% 2.57 1.60 -0.56 5.70 0.108
3政党 日経平均 日経平均:プラス1000円 0.78 1.77 -2.68 4.24 0.658
4政党 日経平均 日経平均:プラス1000円 -1.56 1.67 -4.83 1.72 0.353
5政党 日経平均 日経平均:プラス1000円 -0.18 1.59 -3.30 2.94 0.909
3政党 日経平均 日経平均:マイナス1000円 2.39 1.78 -1.09 5.87 0.179
4政党 日経平均 日経平均:マイナス1000円 1.89 1.67 -1.38 5.16 0.257
5政党 日経平均 日経平均:マイナス1000円 3.88 1.60 0.73 7.02 0.016
3政党 議席数 議席数:10~49 2.49 2.18 -1.79 6.76 0.254
4政党 議席数 議席数:10~49 4.15 2.04 0.16 8.14 0.042
5政党 議席数 議席数:10~49 1.23 1.95 -2.58 5.05 0.527
3政党 議席数 議席数:50~99 1.94 2.15 -2.27 6.15 0.367
4政党 議席数 議席数:50~99 2.80 2.02 -1.17 6.76 0.167
5政党 議席数 議席数:50~99 1.53 1.92 -2.24 5.30 0.425
3政党 議席数 議席数:100~199 2.46 2.32 -2.09 7.02 0.289
4政党 議席数 議席数:100~199 2.82 2.21 -1.51 7.15 0.202
5政党 議席数 議席数:100~199 1.30 2.12 -2.87 5.46 0.542
3政党 議席数 議席数:200以上 1.74 2.34 -2.85 6.32 0.458
4政党 議席数 議席数:200以上 2.95 2.23 -1.42 7.32 0.185
5政党 議席数 議席数:200以上 2.23 2.13 -1.93 6.40 0.293
3政党 CPI CPI:プラス1ポイント -0.52 1.69 -3.84 2.80 0.759
4政党 CPI CPI:プラス1ポイント -0.18 1.61 -3.32 2.97 0.912
5政党 CPI CPI:プラス1ポイント -1.56 1.52 -4.55 1.42 0.305
3政党 CPI CPI:マイナス1ポイント -4.28 1.69 -7.59 -0.97 0.011
4政党 CPI CPI:マイナス1ポイント -2.18 1.58 -5.28 0.91 0.167
5政党 CPI CPI:マイナス1ポイント -2.04 1.51 -4.99 0.91 0.175
3政党 失業率 失業率:プラス1% 0.49 1.78 -3.00 3.99 0.782
4政党 失業率 失業率:プラス1% 0.50 1.69 -2.81 3.80 0.769
5政党 失業率 失業率:プラス1% 2.36 1.61 -0.79 5.51 0.142
3政党 失業率 失業率:マイナス1% 1.64 1.77 -1.84 5.11 0.355
4政党 失業率 失業率:マイナス1% 1.85 1.69 -1.46 5.16 0.274
5政党 失業率 失業率:マイナス1% 2.84 1.60 -0.31 5.98 0.077

補図F4:条件付きロジット

補図F4 <- study2_env$p_clogit_or
補図F4

表F4 <- readr::read_csv(study_csv("study2", "table_conditional_logit.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性", label = "水準")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study2"), 属性 = 属性日本語(属性)) %>%
  dplyr::select(-dplyr::any_of(c("term", "variable", "policy_position", "government_status")))
knitr::kable(表日本語(表F4), format = "html", row.names = FALSE)
条件 属性 水準(基準水準との差) log係数 標準誤差 オッズ比 95% CI下限(OR) 95% CI上限(OR) p値
2政党 政策位置 右派・保守的 -0.086 0.072 0.918 0.797 1.057 .234
2政党 政策位置 左派・革新的 -0.408 0.069 0.665 0.581 0.762 < .001
2政党 与党/野党 与党 0.137 0.054 1.147 1.031 1.276 .012
2政党 GDP成長率 GDP:プラス1% 0.346 0.065 1.413 1.245 1.603 < .001
2政党 GDP成長率 GDP:マイナス1% -0.224 0.063 0.799 0.706 0.905 < .001
2政党 日経平均 日経平均:プラス1000円 0.187 0.063 1.205 1.066 1.363 .003
2政党 日経平均 日経平均:マイナス1000円 -0.294 0.064 0.745 0.658 0.844 < .001
2政党 議席数 議席数:10~49 0.054 0.076 1.056 0.910 1.225 .474
2政党 議席数 議席数:50~99 0.254 0.079 1.290 1.105 1.505 .001
2政党 議席数 議席数:100~199 0.349 0.084 1.418 1.202 1.672 < .001
2政党 議席数 議席数:200以上 0.351 0.087 1.420 1.199 1.683 < .001
2政党 CPI CPI:プラス1ポイント 0.099 0.062 1.104 0.977 1.247 .112
2政党 CPI CPI:マイナス1ポイント 0.087 0.061 1.091 0.968 1.230 .153
2政党 失業率 失業率:プラス1% -0.190 0.064 0.827 0.729 0.938 .003
2政党 失業率 失業率:マイナス1% -0.131 0.064 0.877 0.774 0.993 .039
3政党 政策位置 右派・保守的 -0.014 0.053 0.986 0.889 1.093 .791
3政党 政策位置 左派・革新的 -0.444 0.051 0.641 0.580 0.709 < .001
3政党 与党/野党 与党 0.089 0.042 1.093 1.006 1.187 .036
3政党 GDP成長率 GDP:プラス1% 0.263 0.043 1.301 1.196 1.415 < .001
3政党 GDP成長率 GDP:マイナス1% -0.309 0.043 0.734 0.675 0.798 < .001
3政党 日経平均 日経平均:プラス1000円 0.228 0.044 1.256 1.153 1.369 < .001
3政党 日経平均 日経平均:マイナス1000円 -0.232 0.046 0.793 0.724 0.869 < .001
3政党 議席数 議席数:10~49 0.182 0.060 1.200 1.066 1.350 .003
3政党 議席数 議席数:50~99 0.377 0.060 1.457 1.295 1.640 < .001
3政党 議席数 議席数:100~199 0.536 0.060 1.710 1.519 1.924 < .001
3政党 議席数 議席数:200以上 0.495 0.062 1.640 1.454 1.850 < .001
3政党 CPI CPI:プラス1ポイント 0.066 0.043 1.068 0.983 1.161 .120
3政党 CPI CPI:マイナス1ポイント -0.117 0.045 0.890 0.815 0.971 .009
3政党 失業率 失業率:プラス1% -0.200 0.044 0.819 0.751 0.893 < .001
3政党 失業率 失業率:マイナス1% -0.063 0.044 0.939 0.862 1.024 .156
4政党 政策位置 右派・保守的 0.053 0.050 1.055 0.957 1.163 .285
4政党 政策位置 左派・革新的 -0.519 0.052 0.595 0.538 0.659 < .001
4政党 与党/野党 与党 0.099 0.040 1.104 1.020 1.195 .014
4政党 GDP成長率 GDP:プラス1% 0.340 0.040 1.405 1.300 1.518 < .001
4政党 GDP成長率 GDP:マイナス1% -0.294 0.042 0.745 0.687 0.809 < .001
4政党 日経平均 日経平均:プラス1000円 0.142 0.040 1.152 1.065 1.247 < .001
4政党 日経平均 日経平均:マイナス1000円 -0.300 0.042 0.741 0.683 0.804 < .001
4政党 議席数 議席数:10~49 0.331 0.056 1.392 1.247 1.553 < .001
4政党 議席数 議席数:50~99 0.497 0.058 1.645 1.467 1.844 < .001
4政党 議席数 議席数:100~199 0.656 0.059 1.927 1.716 2.163 < .001
4政党 議席数 議席数:200以上 0.656 0.062 1.928 1.709 2.175 < .001
4政党 CPI CPI:プラス1ポイント 0.098 0.040 1.103 1.019 1.194 .015
4政党 CPI CPI:マイナス1ポイント -0.031 0.041 0.969 0.894 1.051 .447
4政党 失業率 失業率:プラス1% -0.232 0.042 0.793 0.730 0.862 < .001
4政党 失業率 失業率:マイナス1% -0.065 0.043 0.937 0.862 1.019 .127
5政党 政策位置 右派・保守的 0.064 0.047 1.066 0.973 1.168 .173
5政党 政策位置 左派・革新的 -0.418 0.047 0.658 0.600 0.722 < .001
5政党 与党/野党 与党 0.185 0.036 1.203 1.121 1.291 < .001
5政党 GDP成長率 GDP:プラス1% 0.311 0.036 1.365 1.272 1.464 < .001
5政党 GDP成長率 GDP:マイナス1% -0.209 0.037 0.812 0.755 0.873 < .001
5政党 日経平均 日経平均:プラス1000円 0.245 0.035 1.278 1.193 1.369 < .001
5政党 日経平均 日経平均:マイナス1000円 -0.221 0.038 0.802 0.745 0.864 < .001
5政党 議席数 議席数:10~49 0.182 0.050 1.200 1.087 1.324 < .001
5政党 議席数 議席数:50~99 0.493 0.050 1.638 1.484 1.808 < .001
5政党 議席数 議席数:100~199 0.665 0.053 1.945 1.752 2.159 < .001
5政党 議席数 議席数:200以上 0.716 0.054 2.047 1.843 2.274 < .001
5政党 CPI CPI:プラス1ポイント 0.023 0.035 1.023 0.955 1.096 .513
5政党 CPI CPI:マイナス1ポイント -0.027 0.036 0.973 0.907 1.044 .443
5政党 失業率 失業率:プラス1% -0.160 0.036 0.852 0.794 0.914 < .001
5政党 失業率 失業率:マイナス1% -0.016 0.037 0.985 0.916 1.058 .674

G. 実験3(2026年)の補足分析

補図G1:共変量を含めないAMCE

補図G1データ <- study3_env$amce_plot_nocov
補図G1 <- study3_env$p_amce_nocov
補図G1

表G1 <- readr::read_csv(study_csv("study3", "table_amce_unadjusted.csv"), show_col_types = FALSE) %>%
  dplyr::mutate(条件 = paste0(stringr::str_remove(条件, "条件$"), "条件"))
knitr::kable(表日本語(表G1), format = "html", row.names = FALSE)
条件 属性 水準(基準水準との差) 推定値(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値 回答者数
2選択肢条件 政権与党の政党名 立憲民主党 -8.81 3.11 -14.91 -2.72 .005 716
2選択肢条件 政権与党の政党名 日本維新の会 -5.98 2.76 -11.39 -0.56 .031 716
2選択肢条件 政権与党の政党名 公明党 -23.50 2.89 -29.17 -17.83 < .001 716
2選択肢条件 政権与党の政党名 国民民主党 -1.24 2.79 -6.71 4.24 .659 716
2選択肢条件 政権与党の政党名 れいわ新選組 -28.29 3.03 -34.23 -22.36 < .001 716
2選択肢条件 政権与党の政党名 参政党 -14.93 2.76 -20.35 -9.52 < .001 716
2選択肢条件 政権与党の政党名 日本共産党 -33.63 2.89 -39.30 -27.95 < .001 716
2選択肢条件 政権与党の政党名 中道改革連合 -12.51 2.91 -18.22 -6.80 < .001 716
2選択肢条件 政権与党の政党名 チームみらい -5.10 2.81 -10.60 0.40 .070 716
2選択肢条件 GDP成長率 GDP:プラス1% 7.63 1.43 4.82 10.44 < .001 716
2選択肢条件 GDP成長率 GDP:マイナス1% -5.89 1.44 -8.71 -3.07 < .001 716
2選択肢条件 日経平均 日経平均:プラス1000円 2.84 1.41 0.07 5.61 .045 716
2選択肢条件 日経平均 日経平均:マイナス1000円 -5.26 1.43 -8.06 -2.46 < .001 716
2選択肢条件 CPI CPI:プラス1ポイント -0.48 1.42 -3.26 2.30 .733 716
2選択肢条件 CPI CPI:マイナス1ポイント -2.27 1.43 -5.07 0.52 .112 716
2選択肢条件 失業率 失業率:プラス1% -6.06 1.42 -8.85 -3.27 < .001 716
2選択肢条件 失業率 失業率:マイナス1% -1.49 1.42 -4.26 1.29 .295 716
3選択肢条件 政権与党の政党名 立憲民主党 -13.87 2.26 -18.29 -9.45 < .001 939
3選択肢条件 政権与党の政党名 日本維新の会 -9.01 2.05 -13.02 -5.00 < .001 939
3選択肢条件 政権与党の政党名 公明党 -25.30 2.00 -29.22 -21.38 < .001 939
3選択肢条件 政権与党の政党名 国民民主党 -2.58 2.15 -6.79 1.64 .231 939
3選択肢条件 政権与党の政党名 れいわ新選組 -26.00 2.18 -30.28 -21.73 < .001 939
3選択肢条件 政権与党の政党名 参政党 -12.43 2.15 -16.66 -8.21 < .001 939
3選択肢条件 政権与党の政党名 日本共産党 -28.06 2.15 -32.28 -23.84 < .001 939
3選択肢条件 政権与党の政党名 中道改革連合 -18.36 2.26 -22.78 -13.94 < .001 939
3選択肢条件 政権与党の政党名 チームみらい -8.30 2.16 -12.53 -4.07 < .001 939
3選択肢条件 GDP成長率 GDP:プラス1% 7.09 1.00 5.14 9.05 < .001 939
3選択肢条件 GDP成長率 GDP:マイナス1% -4.80 0.97 -6.70 -2.89 < .001 939
3選択肢条件 日経平均 日経平均:プラス1000円 3.37 1.02 1.37 5.38 .001 939
3選択肢条件 日経平均 日経平均:マイナス1000円 -5.28 0.94 -7.13 -3.43 < .001 939
3選択肢条件 CPI CPI:プラス1ポイント -0.44 0.96 -2.32 1.44 .645 939
3選択肢条件 CPI CPI:マイナス1ポイント -1.37 0.94 -3.21 0.46 .143 939
3選択肢条件 失業率 失業率:プラス1% -4.46 0.96 -6.34 -2.58 < .001 939
3選択肢条件 失業率 失業率:マイナス1% -1.96 0.97 -3.86 -0.05 .044 939
4選択肢条件 政権与党の政党名 立憲民主党 -16.33 1.88 -20.01 -12.64 < .001 1063
4選択肢条件 政権与党の政党名 日本維新の会 -9.34 1.73 -12.73 -5.95 < .001 1063
4選択肢条件 政権与党の政党名 公明党 -24.43 1.67 -27.71 -21.16 < .001 1063
4選択肢条件 政権与党の政党名 国民民主党 -4.96 1.80 -8.49 -1.43 .006 1063
4選択肢条件 政権与党の政党名 れいわ新選組 -25.30 1.75 -28.74 -21.86 < .001 1063
4選択肢条件 政権与党の政党名 参政党 -12.36 1.81 -15.91 -8.81 < .001 1063
4選択肢条件 政権与党の政党名 日本共産党 -25.65 1.80 -29.17 -22.13 < .001 1063
4選択肢条件 政権与党の政党名 中道改革連合 -17.92 1.92 -21.69 -14.15 < .001 1063
4選択肢条件 政権与党の政党名 チームみらい -11.29 1.89 -14.99 -7.58 < .001 1063
4選択肢条件 GDP成長率 GDP:プラス1% 5.03 0.76 3.54 6.52 < .001 1063
4選択肢条件 GDP成長率 GDP:マイナス1% -3.49 0.72 -4.91 -2.08 < .001 1063
4選択肢条件 日経平均 日経平均:プラス1000円 3.87 0.80 2.31 5.43 < .001 1063
4選択肢条件 日経平均 日経平均:マイナス1000円 -3.32 0.72 -4.74 -1.90 < .001 1063
4選択肢条件 CPI CPI:プラス1ポイント 0.54 0.73 -0.89 1.98 .457 1063
4選択肢条件 CPI CPI:マイナス1ポイント -1.25 0.73 -2.69 0.19 .088 1063
4選択肢条件 失業率 失業率:プラス1% -3.72 0.71 -5.11 -2.33 < .001 1063
4選択肢条件 失業率 失業率:マイナス1% -2.01 0.73 -3.44 -0.58 .006 1063
5選択肢条件 政権与党の政党名 立憲民主党 -12.98 1.59 -16.10 -9.86 < .001 1314
5選択肢条件 政権与党の政党名 日本維新の会 -8.62 1.42 -11.40 -5.84 < .001 1314
5選択肢条件 政権与党の政党名 公明党 -21.75 1.38 -24.46 -19.03 < .001 1314
5選択肢条件 政権与党の政党名 国民民主党 -5.06 1.49 -7.98 -2.14 < .001 1314
5選択肢条件 政権与党の政党名 れいわ新選組 -21.60 1.41 -24.37 -18.83 < .001 1314
5選択肢条件 政権与党の政党名 参政党 -13.07 1.49 -16.00 -10.15 < .001 1314
5選択肢条件 政権与党の政党名 日本共産党 -21.87 1.42 -24.65 -19.09 < .001 1314
5選択肢条件 政権与党の政党名 中道改革連合 -16.65 1.50 -19.60 -13.70 < .001 1314
5選択肢条件 政権与党の政党名 チームみらい -12.21 1.51 -15.16 -9.26 < .001 1314
5選択肢条件 GDP成長率 GDP:プラス1% 5.48 0.59 4.32 6.64 < .001 1314
5選択肢条件 GDP成長率 GDP:マイナス1% -2.10 0.52 -3.13 -1.08 < .001 1314
5選択肢条件 日経平均 日経平均:プラス1000円 3.78 0.55 2.70 4.86 < .001 1314
5選択肢条件 日経平均 日経平均:マイナス1000円 -2.15 0.53 -3.19 -1.12 < .001 1314
5選択肢条件 CPI CPI:プラス1ポイント 0.42 0.53 -0.62 1.47 .430 1314
5選択肢条件 CPI CPI:マイナス1ポイント -0.10 0.55 -1.18 0.99 .863 1314
5選択肢条件 失業率 失業率:プラス1% -2.85 0.55 -3.93 -1.76 < .001 1314
5選択肢条件 失業率 失業率:マイナス1% -0.89 0.55 -1.98 0.19 .107 1314

補図G2:2選択肢条件との差

補図G2 <- study3_env$p_interaction
補図G2

表G2 <- readr::read_csv(study_csv("study3", "table_amce_interaction.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, attribute = "属性")) %>%
  dplyr::mutate(dplyr::across(dplyr::any_of("属性"), 属性日本語))
knitr::kable(表日本語(表G2), format = "html", row.names = FALSE)
比較条件 属性 水準 2選択肢条件との差(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値
3選択肢 政権与党の政党名 立憲民主党 -5.05 3.84 -12.57 2.47 .188
4選択肢 政権与党の政党名 立憲民主党 -7.51 3.63 -14.62 -0.40 .038
5選択肢 政権与党の政党名 立憲民主党 -4.16 3.49 -11.00 2.67 .233
3選択肢 政権与党の政党名 日本維新の会 -3.03 3.43 -9.77 3.70 .377
4選択肢 政権与党の政党名 日本維新の会 -3.36 3.26 -9.74 3.02 .302
5選択肢 政権与党の政党名 日本維新の会 -2.65 3.10 -8.72 3.43 .394
3選択肢 政権与党の政党名 公明党 -1.80 3.51 -8.69 5.08 .608
4選択肢 政権与党の政党名 公明党 -0.93 3.34 -7.48 5.61 .780
5選択肢 政権与党の政党名 公明党 1.75 3.20 -4.53 8.03 .584
3選択肢 政権与党の政党名 国民民主党 -1.34 3.52 -8.24 5.56 .703
4選択肢 政権与党の政党名 国民民主党 -3.72 3.32 -10.24 2.79 .262
5選択肢 政権与党の政党名 国民民主党 -3.83 3.16 -10.03 2.38 .227
3選択肢 政権与党の政党名 れいわ新選組 2.29 3.73 -5.02 9.60 .539
4選択肢 政権与党の政党名 れいわ新選組 2.99 3.50 -3.86 9.84 .392
5選択肢 政権与党の政党名 れいわ新選組 6.69 3.34 0.15 13.24 .045
3選択肢 政権与党の政党名 参政党 2.50 3.50 -4.36 9.36 .475
4選択肢 政権与党の政党名 参政党 2.57 3.30 -3.89 9.04 .436
5選択肢 政権与党の政党名 参政党 1.86 3.14 -4.29 8.01 .553
3選択肢 政権与党の政党名 日本共産党 5.57 3.60 -1.49 12.63 .122
4選択肢 政権与党の政党名 日本共産党 7.98 3.40 1.31 14.65 .019
5選択肢 政権与党の政党名 日本共産党 11.76 3.22 5.44 18.07 < .001
3選択肢 政権与党の政党名 中道改革連合 -5.85 3.68 -13.07 1.36 .112
4選択肢 政権与党の政党名 中道改革連合 -5.41 3.49 -12.25 1.42 .121
5選択肢 政権与党の政党名 中道改革連合 -4.15 3.28 -10.56 2.27 .206
3選択肢 政権与党の政党名 チームみらい -3.20 3.54 -10.13 3.73 .365
4選択肢 政権与党の政党名 チームみらい -6.19 3.38 -12.81 0.44 .067
5選択肢 政権与党の政党名 チームみらい -7.11 3.18 -13.35 -0.87 .026
3選択肢 GDP成長率 GDP:プラス1% -0.54 1.75 -3.96 2.88 .758
4選択肢 GDP成長率 GDP:プラス1% -2.60 1.62 -5.78 0.58 .109
5選択肢 GDP成長率 GDP:プラス1% -2.15 1.55 -5.19 0.89 .165
3選択肢 GDP成長率 GDP:マイナス1% 1.09 1.73 -2.31 4.49 .529
4選択肢 GDP成長率 GDP:マイナス1% 2.39 1.61 -0.76 5.54 .136
5選択肢 GDP成長率 GDP:マイナス1% 3.78 1.53 0.79 6.78 .013
3選択肢 日経平均 日経平均:プラス1000円 0.53 1.74 -2.88 3.95 .759
4選択肢 日経平均 日経平均:プラス1000円 1.03 1.62 -2.14 4.21 .525
5選択肢 日経平均 日経平均:プラス1000円 0.94 1.52 -2.03 3.91 .535
3選択肢 日経平均 日経平均:マイナス1000円 -0.02 1.71 -3.37 3.33 .991
4選択肢 日経平均 日経平均:マイナス1000円 1.94 1.60 -1.20 5.07 .226
5選択肢 日経平均 日経平均:マイナス1000円 3.11 1.52 0.12 6.09 .041
3選択肢 CPI CPI:プラス1ポイント 0.04 1.71 -3.31 3.40 .980
4選択肢 CPI CPI:プラス1ポイント 1.03 1.59 -2.10 4.15 .519
5選択肢 CPI CPI:プラス1ポイント 0.91 1.51 -2.06 3.87 .550
3選択肢 CPI CPI:マイナス1ポイント 0.90 1.71 -2.44 4.24 .598
4選択肢 CPI CPI:マイナス1ポイント 1.02 1.60 -2.12 4.16 .525
5選択肢 CPI CPI:マイナス1ポイント 2.18 1.53 -0.82 5.18 .154
3選択肢 失業率 失業率:プラス1% 1.59 1.72 -1.77 4.96 .353
4選択肢 失業率 失業率:プラス1% 2.34 1.59 -0.78 5.45 .142
5選択肢 失業率 失業率:プラス1% 3.21 1.53 0.22 6.21 .035
3選択肢 失業率 失業率:マイナス1% -0.47 1.72 -3.84 2.89 .784
4選択肢 失業率 失業率:マイナス1% -0.53 1.59 -3.65 2.59 .740
5選択肢 失業率 失業率:マイナス1% 0.59 1.52 -2.39 3.57 .697

補図G3:AMCEの線形トレンド

補図G3 <- study3_env$p_linear_trend
補図G3

表G3 <- readr::read_csv(study_csv("study3", "table_amce_linear_trend.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, attribute = "属性", label = "水準")) %>%
  dplyr::mutate(dplyr::across(dplyr::any_of("属性"), 属性日本語)) %>%
  dplyr::select(-dplyr::any_of(c("term", "variable")))
knitr::kable(表日本語(表G3), format = "html", row.names = FALSE)
属性 水準 選択肢が1つ増えるときの変化(pp) 標準誤差(pp) 95% CI下限(pp) 95% CI上限(pp) p値
政権与党の政党名 立憲民主党 -0.61 1.00 -2.57 1.36 .545
政権与党の政党名 日本維新の会 -0.47 0.89 -2.22 1.28 .599
政権与党の政党名 公明党 1.10 0.90 -0.66 2.85 .221
政権与党の政党名 国民民主党 -1.22 0.93 -3.04 0.60 .189
政権与党の政党名 れいわ新選組 2.28 0.94 0.45 4.12 .015
政権与党の政党名 参政党 0.18 0.92 -1.62 1.99 .844
政権与党の政党名 日本共産党 3.61 0.92 1.81 5.40 < .001
政権与党の政党名 中道改革連合 -0.44 0.96 -2.31 1.43 .644
政権与党の政党名 チームみらい -2.19 0.93 -4.01 -0.36 .019
GDP成長率 GDP:プラス1% -0.74 0.42 -1.57 0.09 .079
GDP成長率 GDP:マイナス1% 1.29 0.40 0.50 2.08 .001
日経平均 日経平均:プラス1000円 0.29 0.41 -0.52 1.10 .483
日経平均 日経平均:マイナス1000円 1.24 0.40 0.45 2.03 .002
CPI CPI:プラス1ポイント 0.36 0.40 -0.43 1.15 .372
CPI CPI:マイナス1ポイント 0.70 0.40 -0.09 1.49 .083
失業率 失業率:プラス1% 0.97 0.41 0.17 1.77 .018
失業率 失業率:マイナス1% 0.39 0.41 -0.42 1.19 .346

補図G4:条件付きロジット

補図G4 <- study3_env$p_clogit_or
補図G4

表G4 <- readr::read_csv(study_csv("study3", "table_conditional_logit.csv"), show_col_types = FALSE) %>%
  dplyr::rename_with(~ dplyr::recode(.x, party_n = "条件", attribute = "属性", label = "水準")) %>%
  dplyr::mutate(条件 = 条件日本語(条件, "study3"), 属性 = 属性日本語(属性)) %>%
  dplyr::select(-dplyr::any_of(c("term", "variable")))
knitr::kable(表日本語(表G4), format = "html", row.names = FALSE)
条件 属性 水準(基準水準との差) log係数 標準誤差 オッズ比 95% CI下限(OR) 95% CI上限(OR) p値
2選択肢 政権与党の政党名 立憲民主党 -0.328 0.123 0.721 0.567 0.916 .008
2選択肢 政権与党の政党名 日本維新の会 -0.248 0.111 0.781 0.628 0.970 .026
2選択肢 政権与党の政党名 公明党 -0.952 0.118 0.386 0.306 0.486 < .001
2選択肢 政権与党の政党名 国民民主党 -0.056 0.114 0.946 0.756 1.183 .625
2選択肢 政権与党の政党名 れいわ新選組 -1.155 0.129 0.315 0.245 0.406 < .001
2選択肢 政権与党の政党名 参政党 -0.598 0.110 0.550 0.443 0.682 < .001
2選択肢 政権与党の政党名 日本共産党 -1.364 0.129 0.256 0.199 0.329 < .001
2選択肢 政権与党の政党名 中道改革連合 -0.524 0.118 0.592 0.470 0.746 < .001
2選択肢 政権与党の政党名 チームみらい -0.206 0.110 0.814 0.655 1.011 .062
2選択肢 GDP成長率 GDP:プラス1% 0.363 0.066 1.438 1.264 1.635 < .001
2選択肢 GDP成長率 GDP:マイナス1% -0.266 0.064 0.766 0.676 0.869 < .001
2選択肢 日経平均 日経平均:プラス1000円 0.133 0.063 1.143 1.009 1.294 .035
2選択肢 日経平均 日経平均:マイナス1000円 -0.248 0.064 0.781 0.688 0.886 < .001
2選択肢 CPI CPI:プラス1ポイント -0.021 0.063 0.980 0.865 1.109 .746
2選択肢 CPI CPI:マイナス1ポイント -0.120 0.063 0.887 0.784 1.003 .055
2選択肢 失業率 失業率:プラス1% -0.256 0.063 0.774 0.684 0.876 < .001
2選択肢 失業率 失業率:マイナス1% -0.064 0.065 0.938 0.825 1.066 .327
3選択肢 政権与党の政党名 立憲民主党 -0.543 0.089 0.581 0.488 0.691 < .001
3選択肢 政権与党の政党名 日本維新の会 -0.341 0.077 0.711 0.612 0.826 < .001
3選択肢 政権与党の政党名 公明党 -1.061 0.087 0.346 0.291 0.411 < .001
3選択肢 政権与党の政党名 国民民主党 -0.096 0.079 0.908 0.778 1.061 .224
3選択肢 政権与党の政党名 れいわ新選組 -1.121 0.100 0.326 0.268 0.396 < .001
3選択肢 政権与党の政党名 参政党 -0.487 0.084 0.614 0.521 0.725 < .001
3選択肢 政権与党の政党名 日本共産党 -1.226 0.103 0.293 0.240 0.359 < .001
3選択肢 政権与党の政党名 中道改革連合 -0.738 0.092 0.478 0.399 0.573 < .001
3選択肢 政権与党の政党名 チームみらい -0.322 0.081 0.725 0.618 0.850 < .001
3選択肢 GDP成長率 GDP:プラス1% 0.331 0.046 1.393 1.273 1.523 < .001
3選択肢 GDP成長率 GDP:マイナス1% -0.264 0.050 0.768 0.696 0.846 < .001
3選択肢 日経平均 日経平均:プラス1000円 0.157 0.048 1.170 1.066 1.285 < .001
3選択肢 日経平均 日経平均:マイナス1000円 -0.275 0.047 0.760 0.692 0.834 < .001
3選択肢 CPI CPI:プラス1ポイント -0.016 0.046 0.984 0.900 1.076 .725
3選択肢 CPI CPI:マイナス1ポイント -0.084 0.045 0.920 0.841 1.005 .065
3選択肢 失業率 失業率:プラス1% -0.224 0.047 0.799 0.729 0.876 < .001
3選択肢 失業率 失業率:マイナス1% -0.097 0.046 0.907 0.828 0.993 .035
4選択肢 政権与党の政党名 立憲民主党 -0.689 0.081 0.502 0.428 0.589 < .001
4選択肢 政権与党の政党名 日本維新の会 -0.362 0.068 0.696 0.609 0.795 < .001
4選択肢 政権与党の政党名 公明党 -1.181 0.085 0.307 0.260 0.363 < .001
4選択肢 政権与党の政党名 国民民主党 -0.186 0.068 0.830 0.726 0.949 .007
4選択肢 政権与党の政党名 れいわ新選組 -1.257 0.093 0.285 0.237 0.342 < .001
4選択肢 政権与党の政党名 参政党 -0.502 0.074 0.605 0.524 0.700 < .001
4選択肢 政権与党の政党名 日本共産党 -1.270 0.096 0.281 0.233 0.339 < .001
4選択肢 政権与党の政党名 中道改革連合 -0.783 0.086 0.457 0.386 0.542 < .001
4選択肢 政権与党の政党名 チームみらい -0.452 0.077 0.636 0.547 0.740 < .001
4選択肢 GDP成長率 GDP:プラス1% 0.271 0.041 1.311 1.209 1.421 < .001
4選択肢 GDP成長率 GDP:マイナス1% -0.205 0.043 0.814 0.748 0.887 < .001
4選択肢 日経平均 日経平均:プラス1000円 0.202 0.043 1.223 1.125 1.330 < .001
4選択肢 日経平均 日経平均:マイナス1000円 -0.211 0.043 0.810 0.744 0.881 < .001
4選択肢 CPI CPI:プラス1ポイント 0.037 0.041 1.038 0.958 1.124 .366
4選択肢 CPI CPI:マイナス1ポイント -0.061 0.042 0.941 0.867 1.021 .145
4選択肢 失業率 失業率:プラス1% -0.209 0.040 0.811 0.749 0.878 < .001
4選択肢 失業率 失業率:マイナス1% -0.116 0.041 0.890 0.822 0.964 .004
5選択肢 政権与党の政党名 立憲民主党 -0.598 0.074 0.550 0.476 0.636 < .001
5選択肢 政権与党の政党名 日本維新の会 -0.371 0.061 0.690 0.612 0.778 < .001
5選択肢 政権与党の政党名 公明党 -1.223 0.081 0.294 0.251 0.345 < .001
5選択肢 政権与党の政党名 国民民主党 -0.211 0.061 0.810 0.718 0.913 < .001
5選択肢 政権与党の政党名 れいわ新選組 -1.214 0.083 0.297 0.252 0.349 < .001
5選択肢 政権与党の政党名 参政党 -0.603 0.070 0.547 0.477 0.627 < .001
5選択肢 政権与党の政党名 日本共産党 -1.238 0.084 0.290 0.246 0.342 < .001
5選択肢 政権与党の政党名 中道改革連合 -0.822 0.076 0.439 0.379 0.510 < .001
5選択肢 政権与党の政党名 チームみらい -0.553 0.069 0.575 0.503 0.658 < .001
5選択肢 GDP成長率 GDP:プラス1% 0.340 0.037 1.404 1.307 1.509 < .001
5選択肢 GDP成長率 GDP:マイナス1% -0.155 0.037 0.857 0.796 0.922 < .001
5選択肢 日経平均 日経平均:プラス1000円 0.232 0.034 1.262 1.179 1.350 < .001
5選択肢 日経平均 日経平均:マイナス1000円 -0.152 0.037 0.859 0.799 0.923 < .001
5選択肢 CPI CPI:プラス1ポイント 0.028 0.035 1.028 0.961 1.101 .421
5選択肢 CPI CPI:マイナス1ポイント -0.007 0.037 0.993 0.925 1.067 .852
5選択肢 失業率 失業率:プラス1% -0.188 0.037 0.829 0.771 0.891 < .001
5選択肢 失業率 失業率:マイナス1% -0.051 0.035 0.951 0.887 1.019 .152

H. 政党支持による異質性

支持政党別AMCEでは、各条件に該当する回答者数が40人未満のセルは推定対象外としている。したがって、以下では insufficient_cell_n をNAのまま表示せず、推定可能であった支持政党×選択肢数条件のみを掲載する。

補図H1:支持政党別AMCE

補図H1は、支持政党によるAMCEの異質性を実験ごとに示す。可読性のため、結果は実験1・2・3に分け、1つのパネルを1つの支持政党に対応させる。縦軸には属性名と水準名を一体として表示し、同一の支持政党について各属性・水準の推定結果を上から順に確認できるようにした。点はAMCE、横線は95%信頼区間を示し、点の形で選択肢数条件を区別する。

対応表も実験ごとに分け、選択肢数条件を列方向に展開する。各セルは AMCE [95% CI](pp) を示し、回答者数は支持政党×選択肢数条件ごとの小表として別に示す。この形式により、同じ属性・水準について2・3・4・5選択肢条件を横方向に直接比較できる。表示表では情報を点推定値と95%信頼区間に集約し、p値を含む完全な係数表は各実験のCSV出力 table_party_support_amce.csv に保存する。

支持AMCE一覧 <- dplyr::bind_rows(
  party_support_amce_results$study1$subgroup_coefficients %>%
    dplyr::mutate(実験 = "実験1(2023年)", study_id = "study1"),
  party_support_amce_results$study2$subgroup_coefficients %>%
    dplyr::mutate(実験 = "実験2(2026年)", study_id = "study2"),
  party_support_amce_results$study3$subgroup_coefficients %>%
    dplyr::mutate(実験 = "実験3(2026年)", study_id = "study3")
) %>%
  dplyr::filter(
    status == "estimated",
    !is.na(term),
    term != "(Intercept)",
    !is.na(estimate)
  ) %>%
  dplyr::mutate(
    属性表示 = 属性日本語(attribute),
    条件表示 = purrr::map2_chr(party_n, study_id, 条件日本語),
    水準表示 = 水準日本語(term, label, attribute),
    表示項目 = paste0(属性表示, ":", 水準表示)
  )

補図H1作成 <- function(描画データ, 実験名) {
  項目順 <- 描画データ %>%
    dplyr::distinct(属性表示, 水準表示, 表示項目) %>%
    dplyr::pull(表示項目)

  条件順 <- 描画データ %>%
    dplyr::distinct(party_n, 条件表示) %>%
    dplyr::arrange(party_n) %>%
    dplyr::pull(条件表示)

  描画データ <- 描画データ %>%
    dplyr::mutate(
      表示項目 = factor(表示項目, levels = rev(項目順)),
      条件表示 = factor(条件表示, levels = 条件順)
    )

  dodge <- ggplot2::position_dodge(width = 0.52)

  ggplot2::ggplot(
    描画データ,
    ggplot2::aes(
      x = estimate_pp,
      y = 表示項目,
      shape = 条件表示
    )
  ) +
    ggplot2::geom_vline(
      xintercept = 0,
      linewidth = 0.45
    ) +
    ggplot2::geom_errorbarh(
      ggplot2::aes(
        xmin = conf.low_pp,
        xmax = conf.high_pp
      ),
      height = 0.12,
      position = dodge,
      linewidth = 0.55
    ) +
    ggplot2::geom_point(
      position = dodge,
      size = 2.25,
      fill = "white"
    ) +
    ggplot2::facet_wrap(
      ~ party_support_h,
      ncol = 2,
      scales = "free_y"
    ) +
    ggplot2::labs(
      title = 実験名,
      subtitle = "各パネルは支持政党別の推定結果。点はAMCE、横線は95%信頼区間。",
      x = "選択確率への効果(pp)",
      y = NULL,
      shape = "選択肢数条件",
      caption = "回答者数が40人未満の支持政党×選択肢数条件は推定対象外。"
    ) +
    ggplot2::theme_bw(base_size = 10.5) +
    ggplot2::theme(
      legend.position = "top",
      legend.justification = "center",
      panel.grid.minor = ggplot2::element_blank(),
      strip.background = ggplot2::element_rect(fill = "white"),
      strip.text = ggplot2::element_text(face = "bold", size = 10.5),
      axis.text.y = ggplot2::element_text(size = 8.6, color = "black"),
      axis.text.x = ggplot2::element_text(color = "black"),
      plot.title = ggplot2::element_text(face = "bold"),
      plot.subtitle = ggplot2::element_text(size = 9.5),
      plot.caption = ggplot2::element_text(hjust = 0, size = 8.5),
      panel.spacing = grid::unit(1.0, "lines")
    )
}

表H1作成 <- function(表データ) {
  支持順 <- unique(表データ$party_support_h)
  項目順 <- unique(表データ$表示項目)

  表データ %>%
    dplyr::mutate(
      支持政党 = factor(party_support_h, levels = 支持順),
      `属性・水準` = factor(表示項目, levels = 項目順),
      結果 = sprintf(
        "%.2f [%.2f, %.2f]",
        estimate_pp,
        conf.low_pp,
        conf.high_pp
      )
    ) %>%
    dplyr::select(
      支持政党,
      `属性・水準`,
      条件 = 条件表示,
      結果
    ) %>%
    tidyr::pivot_wider(
      names_from = 条件,
      values_from = 結果,
      values_fill = "—"
    ) %>%
    dplyr::arrange(支持政党, `属性・水準`) %>%
    dplyr::mutate(
      支持政党 = as.character(支持政党),
      `属性・水準` = as.character(`属性・水準`)
    )
}

表H1回答者数作成 <- function(表データ) {
  表データ %>%
    dplyr::distinct(
      支持政党 = party_support_h,
      条件 = 条件表示,
      回答者数 = n_ids
    ) %>%
    dplyr::mutate(回答者数 = as.character(回答者数)) %>%
    tidyr::pivot_wider(
      names_from = 条件,
      values_from = 回答者数,
      values_fill = "—"
    ) %>%
    dplyr::arrange(支持政党)
}

補図H1a:実験1(2023年)

実験1について、推定可能であった支持政党別にAMCEを示す。各パネル内では、同一の属性・水準について4つの政党数条件を比較できる。

H1_実験1 <- 支持AMCE一覧 %>%
  dplyr::filter(study_id == "study1")

補図H1a <- 補図H1作成(
  H1_実験1,
  "補図H1a:実験1(2023年)の支持政党別AMCE"
)
補図H1a

対応する回答者数とAMCEを以下に示す。AMCE表では、各条件の点推定値と95%信頼区間を1セルにまとめている。

表H1a回答者数 <- 表H1回答者数作成(H1_実験1)
knitr::kable(
  表H1a回答者数,
  format = "html",
  row.names = FALSE,
  table.attr = 'class="table table-condensed" style="font-size:90%;"',
  caption = "表H1a-1:実験1(2023年)の支持政党別回答者数"
)
表H1a-1:実験1(2023年)の支持政党別回答者数
支持政党 2政党条件 3政党条件 4政党条件 5政党条件
公明党 154 142 178 156
日本共産党 45 49 74 55
日本維新の会 407 429 402 386
立憲民主党 196 201 212 234
表H1a <- 表H1作成(H1_実験1)
knitr::kable(
  表H1a,
  format = "html",
  row.names = FALSE,
  table.attr = 'class="table table-condensed" style="font-size:90%;"',
  caption = "表H1a-2:実験1(2023年)の支持政党別AMCE[点推定値 [95% CI]、pp]"
)
表H1a-2:実験1(2023年)の支持政党別AMCE[点推定値 [95% CI]、pp]
支持政党 属性・水準 2政党条件 3政党条件 4政党条件 5政党条件
日本維新の会 政策位置:右派・保守的 -2.02 [-6.12, 2.09] -4.21 [-7.71, -0.72] -4.37 [-7.21, -1.52] -3.88 [-6.37, -1.39]
日本維新の会 政策位置:左派・革新的 -7.84 [-11.76, -3.91] -10.14 [-13.58, -6.70] -8.27 [-11.26, -5.29] -6.54 [-9.06, -4.01]
日本維新の会 与党/野党:与党 4.29 [1.09, 7.49] 5.53 [2.43, 8.63] 4.98 [2.12, 7.84] 6.28 [3.67, 8.90]
日本維新の会 GDP成長率:GDP:プラス1% 9.39 [5.46, 13.32] 7.02 [4.10, 9.94] 10.53 [7.92, 13.14] 7.61 [5.31, 9.92]
日本維新の会 GDP成長率:GDP:マイナス1% -2.10 [-5.83, 1.63] -3.60 [-6.23, -0.98] -1.39 [-3.60, 0.81] -2.84 [-4.83, -0.84]
日本維新の会 日経平均:日経平均:プラス1000円 9.57 [5.82, 13.32] 7.44 [4.50, 10.37] 3.01 [0.46, 5.56] 3.72 [1.63, 5.80]
日本維新の会 日経平均:日経平均:マイナス1000円 -2.55 [-6.29, 1.18] -2.52 [-5.45, 0.42] -4.61 [-6.85, -2.37] -4.94 [-6.79, -3.09]
日本維新の会 議席数:議席数:10~49 -0.21 [-4.87, 4.44] 5.13 [1.78, 8.47] 5.04 [2.43, 7.64] 3.23 [1.14, 5.32]
日本維新の会 議席数:議席数:50~99 3.66 [-1.21, 8.54] 9.66 [6.32, 13.00] 8.13 [5.40, 10.85] 7.38 [4.73, 10.03]
日本維新の会 議席数:議席数:100~199 8.60 [3.71, 13.49] 12.47 [8.39, 16.54] 11.98 [8.84, 15.12] 10.64 [7.43, 13.85]
日本維新の会 議席数:議席数:200以上 9.37 [4.45, 14.28] 12.65 [8.56, 16.73] 11.95 [8.28, 15.62] 9.46 [6.33, 12.60]
日本維新の会 CPI:CPI:プラス1ポイント -1.55 [-5.32, 2.23] 2.12 [-0.57, 4.81] 3.50 [1.04, 5.95] 0.36 [-1.63, 2.34]
日本維新の会 CPI:CPI:マイナス1ポイント -2.30 [-6.10, 1.50] 1.09 [-1.54, 3.72] 0.24 [-2.18, 2.65] -2.10 [-4.09, -0.10]
日本維新の会 失業率:失業率:プラス1% -6.14 [-10.03, -2.25] -3.68 [-6.55, -0.81] -3.93 [-6.34, -1.52] -3.18 [-5.29, -1.06]
日本維新の会 失業率:失業率:マイナス1% -4.70 [-8.54, -0.86] -0.08 [-2.96, 2.79] 0.28 [-2.14, 2.70] 0.63 [-1.46, 2.72]
立憲民主党 政策位置:右派・保守的 1.68 [-4.14, 7.50] -2.04 [-6.81, 2.74] -7.38 [-11.43, -3.33] -4.18 [-7.28, -1.07]
立憲民主党 政策位置:左派・革新的 -2.46 [-7.90, 2.97] -4.68 [-9.39, 0.03] -10.03 [-14.11, -5.95] -6.24 [-9.32, -3.16]
立憲民主党 与党/野党:与党 5.90 [0.91, 10.89] -0.95 [-5.23, 3.33] 4.58 [0.73, 8.43] 4.83 [1.73, 7.93]
立憲民主党 GDP成長率:GDP:プラス1% 4.26 [-1.15, 9.67] 7.79 [3.81, 11.77] 0.87 [-2.46, 4.21] 4.99 [2.25, 7.72]
立憲民主党 GDP成長率:GDP:マイナス1% -2.43 [-7.98, 3.12] -1.69 [-5.42, 2.05] -5.32 [-8.34, -2.31] -4.11 [-6.62, -1.60]
立憲民主党 日経平均:日経平均:プラス1000円 2.07 [-3.85, 7.99] 4.48 [0.23, 8.73] 6.86 [3.36, 10.36] 3.84 [1.11, 6.58]
立憲民主党 日経平均:日経平均:マイナス1000円 -9.22 [-14.88, -3.55] -6.24 [-10.44, -2.05] -4.88 [-8.01, -1.75] -3.32 [-5.76, -0.89]
立憲民主党 議席数:議席数:10~49 3.77 [-3.44, 10.98] 3.27 [-1.61, 8.14] 2.11 [-1.57, 5.78] 3.34 [0.72, 5.96]
立憲民主党 議席数:議席数:50~99 10.85 [3.95, 17.75] 8.47 [3.09, 13.85] 3.47 [-0.61, 7.55] 7.26 [3.51, 11.02]
立憲民主党 議席数:議席数:100~199 10.32 [3.13, 17.50] 12.99 [6.69, 19.30] 6.38 [1.53, 11.24] 7.71 [3.53, 11.89]
立憲民主党 議席数:議席数:200以上 13.65 [5.86, 21.43] 9.09 [2.89, 15.29] 9.05 [3.35, 14.74] 9.53 [5.05, 14.01]
立憲民主党 CPI:CPI:プラス1ポイント -1.68 [-7.12, 3.76] -1.44 [-5.77, 2.90] 1.12 [-2.05, 4.28] 1.41 [-1.22, 4.05]
立憲民主党 CPI:CPI:マイナス1ポイント -1.08 [-6.68, 4.51] -1.23 [-5.49, 3.03] 0.57 [-2.84, 3.97] -1.98 [-4.50, 0.53]
立憲民主党 失業率:失業率:プラス1% -3.16 [-8.35, 2.02] -0.91 [-5.22, 3.40] -1.99 [-5.29, 1.31] -1.46 [-4.13, 1.21]
立憲民主党 失業率:失業率:マイナス1% -3.36 [-8.86, 2.14] -0.88 [-5.27, 3.51] -1.42 [-4.71, 1.86] -0.30 [-2.96, 2.36]
公明党 政策位置:右派・保守的 -11.27 [-17.21, -5.32] -10.45 [-15.76, -5.13] -5.60 [-9.85, -1.34] -7.78 [-11.72, -3.85]
公明党 政策位置:左派・革新的 -14.02 [-21.01, -7.02] -13.15 [-18.79, -7.51] -6.01 [-10.21, -1.81] -9.00 [-12.70, -5.29]
公明党 与党/野党:与党 5.22 [-0.79, 11.23] 3.82 [-1.21, 8.85] 2.53 [-1.40, 6.45] 1.82 [-2.01, 5.66]
公明党 GDP成長率:GDP:プラス1% 10.04 [3.83, 16.26] 11.68 [7.20, 16.16] 6.66 [2.77, 10.54] 5.91 [2.47, 9.35]
公明党 GDP成長率:GDP:マイナス1% -3.03 [-9.39, 3.32] -1.12 [-5.81, 3.57] -5.15 [-8.79, -1.52] -3.67 [-6.41, -0.93]
公明党 日経平均:日経平均:プラス1000円 2.06 [-4.11, 8.23] 8.41 [3.59, 13.24] 1.06 [-2.43, 4.54] 3.17 [0.37, 5.97]
公明党 日経平均:日経平均:マイナス1000円 -8.74 [-14.57, -2.91] -3.61 [-8.08, 0.85] -5.31 [-8.66, -1.96] -5.07 [-8.07, -2.07]
公明党 議席数:議席数:10~49 6.80 [-1.14, 14.74] 2.23 [-3.79, 8.26] 3.24 [-0.67, 7.15] 5.32 [2.20, 8.43]
公明党 議席数:議席数:50~99 14.72 [6.81, 22.63] 6.69 [0.29, 13.10] 7.54 [3.01, 12.07] 9.88 [5.94, 13.83]
公明党 議席数:議席数:100~199 8.74 [0.57, 16.90] 9.11 [1.93, 16.29] 7.68 [2.78, 12.58] 10.58 [5.78, 15.38]
公明党 議席数:議席数:200以上 11.71 [3.24, 20.17] 9.84 [2.38, 17.31] 8.06 [2.60, 13.53] 13.12 [7.50, 18.73]
公明党 CPI:CPI:プラス1ポイント 3.63 [-2.61, 9.87] -1.42 [-5.87, 3.02] 4.33 [1.07, 7.58] 0.47 [-2.48, 3.43]
公明党 CPI:CPI:マイナス1ポイント 1.00 [-4.76, 6.76] -1.40 [-6.50, 3.70] 0.14 [-3.20, 3.48] 1.56 [-1.43, 4.56]
公明党 失業率:失業率:プラス1% -1.56 [-8.11, 5.00] -5.22 [-10.28, -0.15] -3.94 [-7.70, -0.18] -4.48 [-7.39, -1.56]
公明党 失業率:失業率:マイナス1% -0.09 [-6.46, 6.28] -8.89 [-13.97, -3.81] -1.53 [-5.08, 2.02] -0.34 [-3.66, 2.97]
日本共産党 政策位置:右派・保守的 7.15 [-3.36, 17.66] -8.37 [-17.89, 1.15] -4.96 [-11.98, 2.05] 0.84 [-5.37, 7.06]
日本共産党 政策位置:左派・革新的 -8.98 [-20.58, 2.61] -4.85 [-15.18, 5.48] -8.90 [-14.23, -3.57] -2.65 [-9.38, 4.08]
日本共産党 与党/野党:与党 4.30 [-6.01, 14.61] 3.83 [-4.13, 11.78] 4.73 [-1.08, 10.55] 5.33 [-1.85, 12.50]
日本共産党 GDP成長率:GDP:プラス1% 7.02 [-5.08, 19.13] 4.94 [-3.49, 13.38] 12.25 [6.63, 17.87] 6.32 [0.63, 12.00]
日本共産党 GDP成長率:GDP:マイナス1% -8.82 [-21.36, 3.72] -10.69 [-17.77, -3.62] -5.77 [-11.31, -0.24] -0.52 [-6.47, 5.43]
日本共産党 日経平均:日経平均:プラス1000円 10.03 [-2.67, 22.73] 0.91 [-7.89, 9.71] 1.20 [-4.60, 7.01] 3.33 [-3.10, 9.76]
日本共産党 日経平均:日経平均:マイナス1000円 -4.13 [-13.56, 5.29] -11.70 [-19.14, -4.26] -8.69 [-13.57, -3.80] -5.35 [-10.61, -0.10]
日本共産党 議席数:議席数:10~49 8.41 [-7.24, 24.06] -5.14 [-15.60, 5.33] 1.20 [-4.69, 7.09] 6.08 [0.91, 11.26]
日本共産党 議席数:議席数:50~99 12.54 [-2.61, 27.68] 6.40 [-3.36, 16.16] 5.10 [-1.82, 12.02] 13.52 [6.70, 20.34]
日本共産党 議席数:議席数:100~199 8.06 [-7.07, 23.20] 10.40 [0.91, 19.89] 13.55 [5.20, 21.90] 11.38 [4.33, 18.43]
日本共産党 議席数:議席数:200以上 4.37 [-10.39, 19.14] 14.57 [2.31, 26.84] 4.59 [-3.69, 12.88] 10.02 [2.10, 17.94]
日本共産党 CPI:CPI:プラス1ポイント 2.37 [-11.47, 16.21] 7.74 [-0.24, 15.73] 0.22 [-5.28, 5.72] 0.24 [-4.98, 5.46]
日本共産党 CPI:CPI:マイナス1ポイント 2.77 [-11.16, 16.70] 0.00 [-7.77, 7.78] -0.61 [-4.92, 3.70] -0.48 [-5.00, 4.04]
日本共産党 失業率:失業率:プラス1% -5.40 [-16.48, 5.67] 0.39 [-7.53, 8.30] -3.56 [-9.26, 2.14] -4.99 [-10.87, 0.90]
日本共産党 失業率:失業率:マイナス1% 3.38 [-9.03, 15.79] -0.21 [-8.41, 8.00] 1.82 [-3.54, 7.17] -3.39 [-8.66, 1.88]

補図H1b:実験2(2026年)

実験2についても同じ形式で示す。支持政党の種類が実験1より多いため、支持政党を2列のファセットに分け、各パネルで属性・水準を縦方向に追えるようにした。

H1_実験2 <- 支持AMCE一覧 %>%
  dplyr::filter(study_id == "study2")

補図H1b <- 補図H1作成(
  H1_実験2,
  "補図H1b:実験2(2026年)の支持政党別AMCE"
)
補図H1b

表H1b回答者数 <- 表H1回答者数作成(H1_実験2)
knitr::kable(
  表H1b回答者数,
  format = "html",
  row.names = FALSE,
  table.attr = 'class="table table-condensed" style="font-size:90%;"',
  caption = "表H1b-1:実験2(2026年)の支持政党別回答者数"
)
表H1b-1:実験2(2026年)の支持政党別回答者数
支持政党 2政党条件 3政党条件 4政党条件 5政党条件
チームみらい 42 50 61 76
参政党 41 47 63
国民民主党 42 73 62 76
支持政党なし 256 380 391 434
日本維新の会 45 66 58 67
立憲民主党 42 44 59
自由民主党 145 229 245 292
表H1b <- 表H1作成(H1_実験2)
knitr::kable(
  表H1b,
  format = "html",
  row.names = FALSE,
  table.attr = 'class="table table-condensed" style="font-size:90%;"',
  caption = "表H1b-2:実験2(2026年)の支持政党別AMCE[点推定値 [95% CI]、pp]"
)
表H1b-2:実験2(2026年)の支持政党別AMCE[点推定値 [95% CI]、pp]
支持政党 属性・水準 2政党条件 3政党条件 4政党条件 5政党条件
支持政党なし 政策位置:右派・保守的 -5.32 [-10.45, -0.19] -5.78 [-9.58, -1.98] -4.90 [-8.16, -1.63] -2.86 [-5.42, -0.30]
支持政党なし 政策位置:左派・革新的 -9.73 [-14.90, -4.57] -10.05 [-13.48, -6.63] -12.04 [-14.87, -9.22] -7.02 [-9.36, -4.69]
支持政党なし 与党/野党:与党 0.53 [-3.65, 4.71] -0.22 [-3.15, 2.70] 0.86 [-1.57, 3.28] 2.22 [0.35, 4.08]
支持政党なし GDP成長率:GDP:プラス1% 13.04 [8.25, 17.82] 7.34 [4.26, 10.42] 5.63 [3.19, 8.06] 6.25 [4.23, 8.27]
支持政党なし GDP成長率:GDP:マイナス1% -4.71 [-9.66, 0.24] -7.39 [-10.18, -4.60] -5.53 [-7.72, -3.33] -3.32 [-5.02, -1.62]
支持政党なし 日経平均:日経平均:プラス1000円 4.47 [-0.53, 9.47] 3.75 [0.47, 7.04] 3.53 [0.82, 6.23] 5.40 [3.39, 7.42]
支持政党なし 日経平均:日経平均:マイナス1000円 -6.79 [-11.90, -1.67] -5.07 [-8.21, -1.93] -7.19 [-9.52, -4.85] -3.53 [-5.42, -1.64]
支持政党なし 議席数:議席数:10~49 5.62 [-0.15, 11.39] 4.94 [1.13, 8.75] 5.15 [2.39, 7.91] 1.60 [-0.54, 3.74]
支持政党なし 議席数:議席数:50~99 3.90 [-1.78, 9.58] 9.72 [5.97, 13.46] 8.92 [5.99, 11.86] 5.34 [2.74, 7.94]
支持政党なし 議席数:議席数:100~199 8.74 [1.90, 15.58] 12.15 [8.13, 16.17] 11.13 [8.01, 14.24] 8.50 [5.92, 11.09]
支持政党なし 議席数:議席数:200以上 8.17 [1.87, 14.48] 11.60 [7.76, 15.43] 10.33 [7.06, 13.59] 8.48 [5.81, 11.15]
支持政党なし CPI:CPI:プラス1ポイント 2.97 [-1.82, 7.76] 1.71 [-1.24, 4.66] 2.73 [0.26, 5.19] -1.39 [-3.17, 0.40]
支持政党なし CPI:CPI:マイナス1ポイント 4.75 [0.14, 9.37] -1.38 [-4.56, 1.79] -0.11 [-2.29, 2.07] -0.66 [-2.60, 1.27]
支持政党なし 失業率:失業率:プラス1% -5.94 [-10.98, -0.89] -4.25 [-7.44, -1.05] -4.78 [-7.25, -2.30] -3.58 [-5.48, -1.68]
支持政党なし 失業率:失業率:マイナス1% -0.94 [-6.05, 4.18] -0.28 [-3.44, 2.87] 0.25 [-2.42, 2.91] -0.20 [-2.30, 1.90]
自由民主党 政策位置:右派・保守的 8.49 [1.93, 15.04] 10.25 [5.28, 15.22] 10.36 [6.36, 14.35] 11.35 [8.21, 14.50]
自由民主党 政策位置:左派・革新的 -14.32 [-20.62, -8.03] -10.94 [-15.34, -6.53] -8.94 [-12.08, -5.81] -5.16 [-7.53, -2.79]
自由民主党 与党/野党:与党 12.28 [6.77, 17.79] 14.94 [11.42, 18.45] 11.56 [8.79, 14.34] 10.70 [8.59, 12.81]
自由民主党 GDP成長率:GDP:プラス1% 4.20 [-2.37, 10.77] 6.41 [2.59, 10.22] 6.24 [3.11, 9.37] 5.43 [3.13, 7.72]
自由民主党 GDP成長率:GDP:マイナス1% -3.93 [-9.85, 1.98] -3.77 [-7.56, 0.01] -4.71 [-7.51, -1.91] -1.11 [-3.24, 1.03]
自由民主党 日経平均:日経平均:プラス1000円 5.58 [-0.54, 11.69] 3.74 [-0.07, 7.56] 4.59 [1.52, 7.66] 3.48 [1.18, 5.78]
自由民主党 日経平均:日経平均:マイナス1000円 -4.32 [-10.55, 1.90] -6.64 [-10.66, -2.62] -4.25 [-7.06, -1.45] -1.86 [-4.07, 0.36]
自由民主党 議席数:議席数:10~49 -7.17 [-15.36, 1.02] 1.49 [-3.27, 6.24] 3.28 [0.00, 6.56] 2.94 [0.45, 5.44]
自由民主党 議席数:議席数:50~99 0.90 [-6.68, 8.48] 6.90 [1.74, 12.05] 5.46 [1.82, 9.11] 7.67 [5.11, 10.23]
自由民主党 議席数:議席数:100~199 6.99 [-0.51, 14.49] 13.18 [8.35, 18.02] 14.22 [10.29, 18.14] 12.19 [9.35, 15.04]
自由民主党 議席数:議席数:200以上 9.20 [0.84, 17.56] 12.10 [6.78, 17.42] 15.83 [11.83, 19.83] 18.24 [15.07, 21.42]
自由民主党 CPI:CPI:プラス1ポイント 4.74 [-1.81, 11.28] 2.31 [-1.30, 5.91] 1.73 [-1.38, 4.84] 1.50 [-0.79, 3.79]
自由民主党 CPI:CPI:マイナス1ポイント 2.40 [-3.79, 8.59] -5.04 [-8.68, -1.41] -0.44 [-3.54, 2.66] 0.68 [-1.45, 2.81]
自由民主党 失業率:失業率:プラス1% -4.43 [-11.01, 2.14] -3.10 [-6.86, 0.66] -3.21 [-6.13, -0.29] -1.41 [-3.61, 0.78]
自由民主党 失業率:失業率:マイナス1% -7.10 [-13.45, -0.76] -1.47 [-5.37, 2.43] -0.93 [-4.01, 2.14] -0.66 [-2.91, 1.58]
国民民主党 政策位置:右派・保守的 -4.67 [-16.44, 7.11] 7.63 [-0.76, 16.02] 1.35 [-4.69, 7.39] 3.76 [-1.81, 9.34]
国民民主党 政策位置:左派・革新的 -7.60 [-22.25, 7.05] -8.67 [-16.07, -1.27] -7.07 [-14.65, 0.50] -4.19 [-9.26, 0.89]
国民民主党 与党/野党:与党 3.08 [-5.91, 12.07] 0.14 [-5.99, 6.27] 0.16 [-5.98, 6.30] 1.79 [-2.77, 6.35]
国民民主党 GDP成長率:GDP:プラス1% 14.78 [1.85, 27.71] 6.71 [-0.54, 13.96] 13.69 [7.15, 20.24] 6.22 [1.46, 10.97]
国民民主党 GDP成長率:GDP:マイナス1% -17.70 [-30.01, -5.40] -5.86 [-11.60, -0.12] -4.51 [-10.34, 1.32] -3.45 [-7.58, 0.68]
国民民主党 日経平均:日経平均:プラス1000円 1.74 [-9.48, 12.96] 3.55 [-4.53, 11.62] 2.87 [-3.72, 9.46] 8.04 [2.98, 13.09]
国民民主党 日経平均:日経平均:マイナス1000円 -5.52 [-17.80, 6.76] -11.10 [-18.38, -3.83] -0.67 [-6.89, 5.56] -4.12 [-8.28, 0.04]
国民民主党 議席数:議席数:10~49 -1.97 [-15.00, 11.05] 12.16 [4.35, 19.97] 7.31 [-0.05, 14.68] 7.29 [2.31, 12.28]
国民民主党 議席数:議席数:50~99 13.44 [0.04, 26.83] 11.24 [2.12, 20.35] 11.10 [4.23, 17.96] 16.48 [10.52, 22.43]
国民民主党 議席数:議席数:100~199 12.27 [-2.31, 26.85] 15.41 [7.03, 23.79] 12.42 [4.72, 20.12] 13.28 [6.78, 19.78]
国民民主党 議席数:議席数:200以上 -2.29 [-19.03, 14.45] 13.91 [5.64, 22.19] 8.34 [-0.34, 17.02] 8.22 [2.30, 14.14]
国民民主党 CPI:CPI:プラス1ポイント -1.87 [-13.90, 10.16] 3.97 [-4.22, 12.17] -1.85 [-7.98, 4.29] 0.55 [-3.70, 4.80]
国民民主党 CPI:CPI:マイナス1ポイント 4.08 [-7.08, 15.24] -1.03 [-9.02, 6.95] -2.61 [-9.58, 4.35] 1.46 [-2.75, 5.67]
国民民主党 失業率:失業率:プラス1% 1.08 [-12.09, 14.24] -4.10 [-11.45, 3.26] -6.77 [-13.58, 0.04] -1.00 [-5.42, 3.41]
国民民主党 失業率:失業率:マイナス1% -0.00 [-11.80, 11.79] 3.28 [-3.64, 10.20] -8.96 [-14.65, -3.28] -0.67 [-5.43, 4.09]
日本維新の会 政策位置:右派・保守的 10.02 [-3.12, 23.16] -5.26 [-13.72, 3.21] 7.51 [-0.56, 15.57] -0.22 [-6.58, 6.13]
日本維新の会 政策位置:左派・革新的 -0.35 [-12.27, 11.56] -8.33 [-16.28, -0.37] 1.10 [-6.48, 8.68] -2.90 [-9.21, 3.42]
日本維新の会 与党/野党:与党 3.60 [-5.19, 12.39] 2.05 [-5.39, 9.48] 5.57 [-0.19, 11.33] 9.28 [5.28, 13.29]
日本維新の会 GDP成長率:GDP:プラス1% 0.86 [-9.29, 11.02] 6.10 [-2.12, 14.32] 10.92 [3.72, 18.12] 0.34 [-4.83, 5.51]
日本維新の会 GDP成長率:GDP:マイナス1% -1.07 [-12.02, 9.89] -3.08 [-10.95, 4.78] -1.32 [-7.54, 4.90] -5.40 [-10.04, -0.76]
日本維新の会 日経平均:日経平均:プラス1000円 5.31 [-6.01, 16.63] 8.54 [1.06, 16.03] 0.57 [-5.99, 7.12] -0.42 [-5.54, 4.70]
日本維新の会 日経平均:日経平均:マイナス1000円 -16.57 [-26.80, -6.33] -7.06 [-13.16, -0.96] -2.72 [-9.37, 3.94] -4.23 [-8.92, 0.46]
日本維新の会 議席数:議席数:10~49 -8.42 [-23.38, 6.54] 2.90 [-6.92, 12.72] 3.27 [-4.52, 11.06] 1.30 [-3.85, 6.45]
日本維新の会 議席数:議席数:50~99 3.42 [-11.94, 18.77] 2.25 [-7.39, 11.90] 13.24 [5.10, 21.38] 4.45 [-1.38, 10.28]
日本維新の会 議席数:議席数:100~199 7.12 [-11.10, 25.34] 12.03 [2.19, 21.88] 13.63 [4.86, 22.39] 6.33 [-0.43, 13.09]
日本維新の会 議席数:議席数:200以上 10.35 [-6.59, 27.29] 9.51 [-1.06, 20.09] 13.38 [3.97, 22.79] 7.46 [1.17, 13.74]
日本維新の会 CPI:CPI:プラス1ポイント -1.17 [-10.32, 7.97] -0.23 [-7.17, 6.71] -0.69 [-5.69, 4.32] 1.94 [-2.87, 6.75]
日本維新の会 CPI:CPI:マイナス1ポイント -5.28 [-16.62, 6.06] -2.37 [-10.06, 5.32] -1.81 [-8.00, 4.38] 1.20 [-3.20, 5.61]
日本維新の会 失業率:失業率:プラス1% -0.40 [-11.05, 10.25] 0.35 [-6.12, 6.81] -6.22 [-12.37, -0.07] -3.05 [-8.01, 1.91]
日本維新の会 失業率:失業率:マイナス1% 4.27 [-6.11, 14.66] -5.57 [-12.45, 1.30] -2.02 [-9.66, 5.63] -0.44 [-6.76, 5.88]
チームみらい 政策位置:右派・保守的 -2.83 [-16.96, 11.30] 7.51 [-2.39, 17.41] -4.17 [-11.01, 2.67] -5.25 [-10.18, -0.32]
チームみらい 政策位置:左派・革新的 -23.88 [-36.67, -11.09] 1.71 [-7.07, 10.50] -0.97 [-8.67, 6.73] -3.89 [-9.49, 1.71]
チームみらい 与党/野党:与党 4.88 [-5.07, 14.83] 2.88 [-3.49, 9.26] -1.22 [-6.85, 4.41] -1.70 [-5.89, 2.49]
チームみらい GDP成長率:GDP:プラス1% 7.65 [-3.71, 19.01] 17.19 [7.90, 26.47] 4.91 [-0.63, 10.45] 7.69 [2.40, 12.97]
チームみらい GDP成長率:GDP:マイナス1% 0.42 [-10.48, 11.32] -9.27 [-17.38, -1.15] -5.31 [-11.66, 1.04] -3.11 [-7.73, 1.50]
チームみらい 日経平均:日経平均:プラス1000円 12.99 [0.23, 25.75] 7.78 [-1.94, 17.51] 2.96 [-4.00, 9.93] 6.49 [2.04, 10.95]
チームみらい 日経平均:日経平均:マイナス1000円 2.12 [-8.91, 13.16] -1.88 [-9.42, 5.65] -4.96 [-10.44, 0.52] -2.41 [-6.90, 2.07]
チームみらい 議席数:議席数:10~49 -13.36 [-29.33, 2.61] -2.48 [-11.56, 6.59] 5.08 [-1.67, 11.83] 4.74 [0.04, 9.43]
チームみらい 議席数:議席数:50~99 17.12 [2.17, 32.07] 3.76 [-5.38, 12.90] 14.46 [5.75, 23.17] 4.61 [-0.73, 9.96]
チームみらい 議席数:議席数:100~199 9.78 [-8.67, 28.23] 0.13 [-11.36, 11.61] 13.68 [5.16, 22.20] 11.66 [5.03, 18.28]
チームみらい 議席数:議席数:200以上 22.76 [6.96, 38.56] 7.46 [-4.10, 19.01] 16.06 [7.41, 24.72] 10.21 [3.45, 16.96]
チームみらい CPI:CPI:プラス1ポイント -0.44 [-9.71, 8.83] 2.73 [-4.71, 10.16] 1.39 [-4.61, 7.40] -1.29 [-6.00, 3.42]
チームみらい CPI:CPI:マイナス1ポイント -0.01 [-10.26, 10.25] -3.01 [-11.79, 5.77] 2.10 [-4.30, 8.49] -2.47 [-7.24, 2.31]
チームみらい 失業率:失業率:プラス1% -7.32 [-20.30, 5.66] -7.56 [-16.69, 1.57] -9.35 [-14.99, -3.71] -2.77 [-7.71, 2.18]
チームみらい 失業率:失業率:マイナス1% -3.36 [-16.07, 9.36] -6.96 [-14.87, 0.95] -0.71 [-7.99, 6.58] -2.29 [-6.92, 2.34]
参政党 政策位置:右派・保守的 8.98 [-2.54, 20.50] 21.91 [12.61, 31.20] 20.94 [13.55, 28.32]
参政党 政策位置:左派・革新的 -7.06 [-17.57, 3.44] -11.33 [-18.02, -4.63] -3.70 [-9.44, 2.04]
参政党 与党/野党:与党 5.16 [-4.17, 14.49] -2.06 [-8.23, 4.12] 2.20 [-2.37, 6.77]
参政党 GDP成長率:GDP:プラス1% -0.00 [-10.97, 10.96] 10.22 [4.18, 16.26] 2.38 [-2.88, 7.65]
参政党 GDP成長率:GDP:マイナス1% -11.63 [-20.54, -2.71] -1.82 [-8.18, 4.53] -6.06 [-10.65, -1.47]
参政党 日経平均:日経平均:プラス1000円 2.68 [-5.22, 10.58] 1.60 [-4.21, 7.40] 5.21 [0.27, 10.15]
参政党 日経平均:日経平均:マイナス1000円 -2.13 [-10.56, 6.30] -0.64 [-7.85, 6.57] -3.55 [-8.36, 1.25]
参政党 議席数:議席数:10~49 8.87 [-3.29, 21.02] 12.68 [3.95, 21.42] 0.35 [-5.18, 5.88]
参政党 議席数:議席数:50~99 7.89 [-5.55, 21.34] 2.86 [-7.19, 12.90] 7.64 [1.94, 13.34]
参政党 議席数:議席数:100~199 8.37 [-2.80, 19.55] 8.36 [0.40, 16.33] 13.52 [7.32, 19.72]
参政党 議席数:議席数:200以上 -1.16 [-11.62, 9.30] 5.56 [-3.43, 14.54] 7.42 [1.48, 13.36]
参政党 CPI:CPI:プラス1ポイント 2.03 [-8.17, 12.23] 3.02 [-4.33, 10.37] 0.74 [-3.50, 4.98]
参政党 CPI:CPI:マイナス1ポイント -1.31 [-9.19, 6.57] -6.90 [-13.39, -0.41] -1.75 [-5.54, 2.03]
参政党 失業率:失業率:プラス1% -8.95 [-18.92, 1.03] -6.11 [-12.84, 0.62] -0.64 [-4.91, 3.63]
参政党 失業率:失業率:マイナス1% -3.20 [-13.56, 7.16] -3.64 [-10.48, 3.20] 0.72 [-3.92, 5.36]
立憲民主党 政策位置:右派・保守的 -25.44 [-35.61, -15.27] -13.26 [-21.65, -4.86] -13.47 [-19.20, -7.75]
立憲民主党 政策位置:左派・革新的 -9.91 [-20.81, 0.99] -1.30 [-10.26, 7.66] -3.82 [-11.59, 3.95]
立憲民主党 与党/野党:与党 -21.18 [-30.32, -12.05] -16.42 [-23.36, -9.48] -10.36 [-15.77, -4.94]
立憲民主党 GDP成長率:GDP:プラス1% 0.55 [-8.17, 9.27] 7.34 [-0.65, 15.33] 3.01 [-3.02, 9.04]
立憲民主党 GDP成長率:GDP:マイナス1% -6.62 [-15.08, 1.84] -9.22 [-15.77, -2.67] -3.81 [-9.28, 1.65]
立憲民主党 日経平均:日経平均:プラス1000円 13.37 [4.33, 22.41] 5.53 [-1.70, 12.76] 2.26 [-2.21, 6.73]
立憲民主党 日経平均:日経平均:マイナス1000円 -1.75 [-11.65, 8.14] -3.39 [-9.74, 2.97] -4.68 [-9.05, -0.32]
立憲民主党 議席数:議席数:10~49 -0.02 [-13.33, 13.28] 1.61 [-8.16, 11.37] 2.79 [-2.83, 8.40]
立憲民主党 議席数:議席数:50~99 -0.54 [-11.64, 10.55] 3.62 [-6.49, 13.73] 15.37 [8.55, 22.20]
立憲民主党 議席数:議席数:100~199 -0.12 [-12.37, 12.13] 16.52 [5.89, 27.14] 18.38 [11.88, 24.88]
立憲民主党 議席数:議席数:200以上 2.50 [-8.03, 13.03] 15.37 [3.83, 26.91] 14.99 [8.86, 21.12]
立憲民主党 CPI:CPI:プラス1ポイント -1.53 [-10.59, 7.53] -5.12 [-12.63, 2.39] -0.85 [-5.52, 3.83]
立憲民主党 CPI:CPI:マイナス1ポイント 1.98 [-8.09, 12.04] -6.33 [-13.37, 0.70] -1.06 [-6.05, 3.93]
立憲民主党 失業率:失業率:プラス1% -14.23 [-23.21, -5.26] -2.82 [-10.02, 4.38] 1.73 [-3.15, 6.61]
立憲民主党 失業率:失業率:マイナス1% -1.25 [-11.04, 8.54] 4.26 [-1.50, 10.03] 4.48 [-1.21, 10.17]

補図H1c:実験3(2026年)

実験3では、政党属性が政党名として提示される。図の構成は実験1・2と揃え、支持政党ごとに、政党名および経済属性の各水準に対するAMCEを比較できるようにした。

H1_実験3 <- 支持AMCE一覧 %>%
  dplyr::filter(study_id == "study3")

補図H1c <- 補図H1作成(
  H1_実験3,
  "補図H1c:実験3(2026年)の支持政党別AMCE"
)
補図H1c

表H1c回答者数 <- 表H1回答者数作成(H1_実験3)
knitr::kable(
  表H1c回答者数,
  format = "html",
  row.names = FALSE,
  table.attr = 'class="table table-condensed" style="font-size:90%;"',
  caption = "表H1c-1:実験3(2026年)の支持政党別回答者数"
)
表H1c-1:実験3(2026年)の支持政党別回答者数
支持政党 2選択肢条件 3選択肢条件 4選択肢条件 5選択肢条件
チームみらい 51 67
参政党 46 42 52
国民民主党 49 76 70 91
支持政党なし 261 335 370 447
日本維新の会 46 64 60
立憲民主党 63
自由民主党 163 219 254 311
表H1c <- 表H1作成(H1_実験3)
knitr::kable(
  表H1c,
  format = "html",
  row.names = FALSE,
  table.attr = 'class="table table-condensed" style="font-size:90%;"',
  caption = "表H1c-2:実験3(2026年)の支持政党別AMCE[点推定値 [95% CI]、pp]"
)
表H1c-2:実験3(2026年)の支持政党別AMCE[点推定値 [95% CI]、pp]
支持政党 属性・水準 2選択肢条件 3選択肢条件 4選択肢条件 5選択肢条件
支持政党なし 政権与党の政党名:立憲民主党 0.74 [-9.09, 10.58] -4.79 [-11.87, 2.29] -9.12 [-15.28, -2.96] -1.85 [-6.48, 2.78]
支持政党なし 政権与党の政党名:日本維新の会 -10.06 [-19.64, -0.48] -5.74 [-12.08, 0.59] -9.50 [-14.98, -4.02] -3.09 [-7.45, 1.27]
支持政党なし 政権与党の政党名:公明党 -21.56 [-30.97, -12.15] -18.37 [-24.99, -11.75] -18.40 [-23.82, -12.98] -12.61 [-16.50, -8.72]
支持政党なし 政権与党の政党名:国民民主党 1.09 [-7.88, 10.05] 2.36 [-4.42, 9.14] 1.93 [-3.80, 7.65] 4.80 [0.21, 9.39]
支持政党なし 政権与党の政党名:れいわ新選組 -26.73 [-36.50, -16.96] -17.04 [-24.11, -9.97] -17.85 [-23.57, -12.12] -11.85 [-15.95, -7.76]
支持政党なし 政権与党の政党名:参政党 -11.28 [-20.49, -2.07] -11.58 [-18.31, -4.85] -10.52 [-16.29, -4.75] -4.16 [-8.49, 0.17]
支持政党なし 政権与党の政党名:日本共産党 -26.13 [-35.60, -16.65] -17.25 [-24.46, -10.03] -17.12 [-22.84, -11.40] -11.77 [-15.80, -7.75]
支持政党なし 政権与党の政党名:中道改革連合 -7.07 [-16.79, 2.65] -7.74 [-15.15, -0.34] -7.72 [-14.12, -1.33] -5.69 [-10.01, -1.36]
支持政党なし 政権与党の政党名:チームみらい -0.43 [-9.60, 8.74] -3.81 [-10.45, 2.83] -5.40 [-11.52, 0.71] 0.22 [-4.44, 4.89]
支持政党なし GDP成長率:GDP:プラス1% 12.93 [8.34, 17.53] 6.60 [3.32, 9.89] 6.12 [3.53, 8.71] 7.30 [5.31, 9.30]
支持政党なし GDP成長率:GDP:マイナス1% -1.81 [-6.51, 2.89] -7.01 [-10.16, -3.85] -3.47 [-5.90, -1.03] -3.64 [-5.37, -1.91]
支持政党なし 日経平均:日経平均:プラス1000円 2.95 [-1.44, 7.34] 4.26 [0.95, 7.56] 4.92 [2.25, 7.60] 5.75 [3.83, 7.67]
支持政党なし 日経平均:日経平均:マイナス1000円 -5.85 [-10.93, -0.77] -4.97 [-8.05, -1.89] -4.75 [-7.25, -2.24] -2.92 [-4.72, -1.13]
支持政党なし CPI:CPI:プラス1ポイント -2.01 [-6.72, 2.70] -0.30 [-3.52, 2.92] -0.88 [-3.26, 1.51] -0.07 [-1.90, 1.76]
支持政党なし CPI:CPI:マイナス1ポイント -0.97 [-5.59, 3.65] -2.28 [-5.45, 0.89] -4.47 [-6.86, -2.08] -1.44 [-3.38, 0.50]
支持政党なし 失業率:失業率:プラス1% -7.45 [-12.32, -2.58] -6.78 [-9.93, -3.63] -4.65 [-7.13, -2.16] -3.04 [-5.04, -1.04]
支持政党なし 失業率:失業率:マイナス1% -3.03 [-7.81, 1.75] -1.01 [-4.28, 2.26] -2.87 [-5.37, -0.36] -1.22 [-3.22, 0.79]
自由民主党 政権与党の政党名:立憲民主党 -35.30 [-46.48, -24.12] -46.59 [-54.80, -38.38] -47.57 [-54.70, -40.43] -53.57 [-59.43, -47.71]
自由民主党 政権与党の政党名:日本維新の会 -16.83 [-25.95, -7.71] -24.49 [-32.31, -16.68] -30.95 [-37.84, -24.06] -30.79 [-36.94, -24.63]
自由民主党 政権与党の政党名:公明党 -31.29 [-42.09, -20.49] -50.52 [-57.89, -43.15] -55.88 [-62.15, -49.61] -53.05 [-59.05, -47.05]
自由民主党 政権与党の政党名:国民民主党 -17.49 [-27.60, -7.39] -29.14 [-36.79, -21.48] -36.79 [-43.25, -30.34] -41.21 [-47.00, -35.41]
自由民主党 政権与党の政党名:れいわ新選組 -56.09 [-66.06, -46.11] -54.33 [-62.75, -45.90] -56.75 [-63.59, -49.91] -56.38 [-62.21, -50.55]
自由民主党 政権与党の政党名:参政党 -35.62 [-45.83, -25.41] -33.32 [-41.68, -24.96] -40.05 [-47.03, -33.06] -50.66 [-56.69, -44.63]
自由民主党 政権与党の政党名:日本共産党 -58.61 [-68.30, -48.92] -59.57 [-67.10, -52.05] -61.82 [-68.02, -55.62] -57.78 [-63.55, -52.00]
自由民主党 政権与党の政党名:中道改革連合 -38.53 [-49.49, -27.57] -52.07 [-59.96, -44.17] -54.80 [-61.67, -47.93] -55.26 [-61.09, -49.43]
自由民主党 政権与党の政党名:チームみらい -26.52 [-36.15, -16.89] -34.90 [-43.04, -26.75] -44.00 [-51.21, -36.78] -47.44 [-53.49, -41.39]
自由民主党 GDP成長率:GDP:プラス1% 8.28 [2.69, 13.87] 5.82 [2.38, 9.25] 4.12 [1.26, 6.97] 4.45 [2.32, 6.58]
自由民主党 GDP成長率:GDP:マイナス1% -3.23 [-8.67, 2.22] -5.21 [-9.17, -1.26] -3.47 [-6.25, -0.68] -0.66 [-2.49, 1.17]
自由民主党 日経平均:日経平均:プラス1000円 7.71 [2.22, 13.20] 3.19 [-0.74, 7.11] 3.35 [0.36, 6.34] 3.04 [0.91, 5.17]
自由民主党 日経平均:日経平均:マイナス1000円 -4.77 [-10.45, 0.91] -5.98 [-9.57, -2.39] -1.26 [-3.95, 1.43] -2.15 [-4.23, -0.07]
自由民主党 CPI:CPI:プラス1ポイント 0.33 [-5.12, 5.78] 1.43 [-2.09, 4.95] 1.08 [-1.79, 3.94] 1.18 [-0.74, 3.10]
自由民主党 CPI:CPI:マイナス1ポイント -2.90 [-8.42, 2.62] 0.44 [-3.27, 4.15] 0.26 [-2.39, 2.91] -0.03 [-1.98, 1.93]
自由民主党 失業率:失業率:プラス1% -6.54 [-12.52, -0.57] -3.98 [-7.61, -0.34] -2.52 [-5.13, 0.10] -0.10 [-2.10, 1.90]
自由民主党 失業率:失業率:マイナス1% -3.37 [-8.97, 2.24] -4.23 [-7.62, -0.84] -0.47 [-3.16, 2.23] -0.75 [-2.71, 1.22]
国民民主党 政権与党の政党名:立憲民主党 6.08 [-17.38, 29.54] -12.86 [-27.13, 1.41] -5.60 [-19.28, 8.07] -13.60 [-25.01, -2.19]
国民民主党 政権与党の政党名:日本維新の会 9.72 [-12.02, 31.47] -12.07 [-27.33, 3.19] 4.44 [-9.23, 18.12] -9.03 [-19.63, 1.56]
国民民主党 政権与党の政党名:公明党 -7.82 [-30.54, 14.90] -29.46 [-40.25, -18.68] -9.01 [-19.36, 1.35] -23.18 [-32.61, -13.75]
国民民主党 政権与党の政党名:国民民主党 25.68 [4.69, 46.68] 28.20 [14.82, 41.57] 40.51 [26.54, 54.48] 27.05 [15.13, 38.97]
国民民主党 政権与党の政党名:れいわ新選組 -21.96 [-46.38, 2.46] -25.26 [-36.79, -13.73] -21.76 [-32.24, -11.29] -21.73 [-31.88, -11.58]
国民民主党 政権与党の政党名:参政党 7.75 [-13.83, 29.32] -0.67 [-17.07, 15.74] -2.81 [-15.32, 9.70] -14.58 [-24.85, -4.31]
国民民主党 政権与党の政党名:日本共産党 -20.58 [-41.93, 0.77] -19.83 [-33.22, -6.43] -20.86 [-30.73, -10.99] -24.39 [-33.49, -15.29]
国民民主党 政権与党の政党名:中道改革連合 6.29 [-12.94, 25.51] -23.73 [-36.82, -10.65] -11.83 [-23.78, 0.13] -17.41 [-28.07, -6.75]
国民民主党 政権与党の政党名:チームみらい 21.97 [2.03, 41.92] 5.68 [-8.86, 20.22] 0.48 [-14.09, 15.05] -11.79 [-22.39, -1.18]
国民民主党 GDP成長率:GDP:プラス1% -2.73 [-11.95, 6.49] 10.68 [4.08, 17.28] 6.52 [-0.10, 13.13] 5.54 [0.83, 10.25]
国民民主党 GDP成長率:GDP:マイナス1% -10.99 [-21.40, -0.57] -1.80 [-7.92, 4.32] -5.53 [-10.67, -0.38] 0.41 [-3.24, 4.07]
国民民主党 日経平均:日経平均:プラス1000円 1.02 [-9.64, 11.68] 3.55 [-3.79, 10.89] 1.09 [-4.92, 7.11] 0.98 [-2.68, 4.63]
国民民主党 日経平均:日経平均:マイナス1000円 -5.45 [-16.73, 5.83] -2.26 [-9.46, 4.94] -4.25 [-9.30, 0.80] -3.44 [-6.57, -0.31]
国民民主党 CPI:CPI:プラス1ポイント -0.60 [-12.81, 11.61] 1.17 [-4.87, 7.21] 0.27 [-4.77, 5.32] 0.68 [-3.48, 4.84]
国民民主党 CPI:CPI:マイナス1ポイント -1.55 [-12.37, 9.26] 4.04 [-1.60, 9.69] 1.23 [-4.88, 7.35] 4.22 [0.34, 8.10]
国民民主党 失業率:失業率:プラス1% -3.54 [-13.05, 5.98] -6.22 [-13.09, 0.65] -1.05 [-5.89, 3.80] -2.38 [-5.88, 1.12]
国民民主党 失業率:失業率:マイナス1% -1.72 [-11.23, 7.80] -2.08 [-8.92, 4.75] 2.36 [-2.32, 7.04] 0.65 [-3.31, 4.61]
日本維新の会 政権与党の政党名:立憲民主党 -23.66 [-43.24, -4.08] -20.02 [-33.48, -6.57] -21.64 [-32.04, -11.24]
日本維新の会 政権与党の政党名:日本維新の会 18.89 [0.97, 36.80] 21.51 [6.23, 36.79] 35.33 [19.19, 51.48]
日本維新の会 政権与党の政党名:公明党 -36.32 [-53.85, -18.79] -22.15 [-35.20, -9.09] -22.37 [-32.76, -11.98]
日本維新の会 政権与党の政党名:国民民主党 -20.71 [-40.44, -0.98] -9.87 [-24.34, 4.60] -6.76 [-18.76, 5.25]
日本維新の会 政権与党の政党名:れいわ新選組 -45.42 [-61.49, -29.35] -22.65 [-35.00, -10.31] -14.15 [-26.23, -2.06]
日本維新の会 政権与党の政党名:参政党 -13.95 [-31.21, 3.31] -10.22 [-24.83, 4.39] -16.40 [-26.41, -6.40]
日本維新の会 政権与党の政党名:日本共産党 -40.77 [-57.04, -24.49] -27.21 [-39.61, -14.82] -21.59 [-31.75, -11.42]
日本維新の会 政権与党の政党名:中道改革連合 -34.64 [-54.04, -15.23] -18.34 [-33.65, -3.04] -15.87 [-28.04, -3.70]
日本維新の会 政権与党の政党名:チームみらい -8.52 [-29.27, 12.24] -7.07 [-20.54, 6.39] -7.28 [-20.35, 5.80]
日本維新の会 GDP成長率:GDP:プラス1% 5.13 [-2.27, 12.54] 8.34 [3.24, 13.43] 2.45 [-1.47, 6.37]
日本維新の会 GDP成長率:GDP:マイナス1% -5.35 [-13.02, 2.33] 2.95 [-2.72, 8.62] -6.55 [-10.87, -2.22]
日本維新の会 日経平均:日経平均:プラス1000円 4.91 [-4.27, 14.09] -3.11 [-10.64, 4.42] 2.14 [-2.61, 6.89]
日本維新の会 日経平均:日経平均:マイナス1000円 -7.38 [-15.22, 0.47] -7.98 [-13.94, -2.01] -2.23 [-6.47, 2.01]
日本維新の会 CPI:CPI:プラス1ポイント -2.65 [-11.05, 5.75] -2.66 [-8.07, 2.74] -0.44 [-4.92, 4.03]
日本維新の会 CPI:CPI:マイナス1ポイント -0.30 [-7.61, 7.01] 0.78 [-4.96, 6.51] 3.72 [-0.75, 8.18]
日本維新の会 失業率:失業率:プラス1% -2.34 [-10.83, 6.14] -4.58 [-10.19, 1.04] -0.27 [-5.98, 5.43]
日本維新の会 失業率:失業率:マイナス1% -1.90 [-9.41, 5.61] 1.46 [-4.78, 7.70] 2.56 [-1.60, 6.72]
チームみらい 政権与党の政党名:立憲民主党 -6.71 [-19.68, 6.26] 0.81 [-11.15, 12.76]
チームみらい 政権与党の政党名:日本維新の会 9.18 [-4.41, 22.77] -3.20 [-12.14, 5.75]
チームみらい 政権与党の政党名:公明党 -16.16 [-26.87, -5.45] -12.75 [-21.24, -4.27]
チームみらい 政権与党の政党名:国民民主党 1.21 [-11.62, 14.04] 3.82 [-5.60, 13.24]
チームみらい 政権与党の政党名:れいわ新選組 -18.02 [-29.24, -6.79] -13.33 [-22.00, -4.67]
チームみらい 政権与党の政党名:参政党 4.18 [-10.11, 18.46] -2.68 [-13.01, 7.64]
チームみらい 政権与党の政党名:日本共産党 -16.03 [-27.71, -4.36] -13.93 [-23.34, -4.52]
チームみらい 政権与党の政党名:中道改革連合 -13.19 [-25.56, -0.81] -4.76 [-15.38, 5.86]
チームみらい 政権与党の政党名:チームみらい 48.94 [35.13, 62.74] 37.67 [23.97, 51.37]
チームみらい GDP成長率:GDP:プラス1% 8.54 [1.61, 15.47] 9.10 [3.48, 14.71]
チームみらい GDP成長率:GDP:マイナス1% -3.19 [-9.18, 2.81] -4.16 [-8.90, 0.58]
チームみらい 日経平均:日経平均:プラス1000円 0.62 [-5.37, 6.62] 2.70 [-1.45, 6.85]
チームみらい 日経平均:日経平均:マイナス1000円 -3.43 [-9.65, 2.79] -3.20 [-7.11, 0.72]
チームみらい CPI:CPI:プラス1ポイント 2.78 [-3.70, 9.26] -3.34 [-7.59, 0.90]
チームみらい CPI:CPI:マイナス1ポイント -1.61 [-8.78, 5.55] -0.56 [-5.33, 4.21]
チームみらい 失業率:失業率:プラス1% -0.21 [-5.42, 4.99] -4.60 [-8.74, -0.46]
チームみらい 失業率:失業率:マイナス1% -1.80 [-7.78, 4.17] -0.08 [-4.33, 4.17]
参政党 政権与党の政党名:立憲民主党 -31.17 [-48.83, -13.51] -23.63 [-33.43, -13.82] -23.29 [-33.83, -12.76]
参政党 政権与党の政党名:日本維新の会 -8.75 [-25.57, 8.06] -4.13 [-15.54, 7.28] -11.14 [-21.99, -0.28]
参政党 政権与党の政党名:公明党 -29.26 [-45.87, -12.65] -17.96 [-30.38, -5.55] -27.02 [-36.77, -17.28]
参政党 政権与党の政党名:国民民主党 -14.78 [-34.48, 4.92] 15.24 [-1.44, 31.92] -6.82 [-19.94, 6.29]
参政党 政権与党の政党名:れいわ新選組 -35.49 [-53.20, -17.79] -18.05 [-31.32, -4.79] -22.87 [-33.73, -12.01]
参政党 政権与党の政党名:参政党 28.82 [14.23, 43.41] 52.99 [40.57, 65.42] 43.77 [29.78, 57.75]
参政党 政権与党の政党名:日本共産党 -43.09 [-59.59, -26.59] -21.44 [-33.47, -9.41] -23.24 [-34.51, -11.97]
参政党 政権与党の政党名:中道改革連合 -41.85 [-57.51, -26.20] -22.82 [-33.16, -12.48] -24.34 [-34.61, -14.07]
参政党 政権与党の政党名:チームみらい -17.61 [-35.44, 0.23] 2.83 [-12.16, 17.82] -15.39 [-27.36, -3.43]
参政党 GDP成長率:GDP:プラス1% 8.78 [1.61, 15.96] 4.79 [-3.30, 12.87] 3.01 [-2.78, 8.79]
参政党 GDP成長率:GDP:マイナス1% -6.46 [-13.58, 0.66] -5.66 [-12.64, 1.32] -2.31 [-6.76, 2.14]
参政党 日経平均:日経平均:プラス1000円 4.40 [-6.02, 14.82] 0.25 [-6.40, 6.91] 3.43 [-1.26, 8.12]
参政党 日経平均:日経平均:マイナス1000円 0.20 [-9.41, 9.82] -4.26 [-9.99, 1.47] 0.22 [-4.17, 4.60]
参政党 CPI:CPI:プラス1ポイント -0.78 [-8.29, 6.74] 3.49 [-2.11, 9.09] 1.40 [-3.09, 5.90]
参政党 CPI:CPI:マイナス1ポイント -4.56 [-10.79, 1.67] -0.07 [-6.57, 6.42] -1.81 [-6.65, 3.04]
参政党 失業率:失業率:プラス1% -1.84 [-9.72, 6.04] -0.63 [-6.03, 4.76] -0.26 [-5.25, 4.73]
参政党 失業率:失業率:マイナス1% -3.19 [-8.63, 2.24] -3.86 [-10.66, 2.95] 1.05 [-3.67, 5.77]
立憲民主党 政権与党の政党名:立憲民主党 42.48 [28.96, 56.00]
立憲民主党 政権与党の政党名:日本維新の会 -1.82 [-10.06, 6.41]
立憲民主党 政権与党の政党名:公明党 -4.14 [-11.47, 3.18]
立憲民主党 政権与党の政党名:国民民主党 14.88 [4.04, 25.72]
立憲民主党 政権与党の政党名:れいわ新選組 -2.95 [-10.04, 4.14]
立憲民主党 政権与党の政党名:参政党 -1.03 [-8.16, 6.10]
立憲民主党 政権与党の政党名:日本共産党 1.91 [-6.64, 10.45]
立憲民主党 政権与党の政党名:中道改革連合 15.25 [5.75, 24.75]
立憲民主党 政権与党の政党名:チームみらい -0.05 [-7.52, 7.43]
立憲民主党 GDP成長率:GDP:プラス1% 7.46 [2.35, 12.56]
立憲民主党 GDP成長率:GDP:マイナス1% -2.33 [-6.77, 2.12]
立憲民主党 日経平均:日経平均:プラス1000円 2.79 [-2.46, 8.03]
立憲民主党 日経平均:日経平均:マイナス1000円 -0.33 [-5.52, 4.87]
立憲民主党 CPI:CPI:プラス1ポイント -1.81 [-6.24, 2.62]
立憲民主党 CPI:CPI:マイナス1ポイント -0.72 [-4.91, 3.47]
立憲民主党 失業率:失業率:プラス1% -4.70 [-9.93, 0.53]
立憲民主党 失業率:失業率:マイナス1% -3.89 [-8.39, 0.61]

補図H2:支持政党別の手がかり重要度と相対比重

支持手がかり一覧 <- dplyr::bind_rows(
  party_support_relative_cue_results$study1$intervals %>% dplyr::mutate(実験 = "実験1(2023年)", study_id = "study1"),
  party_support_relative_cue_results$study2$intervals %>% dplyr::mutate(実験 = "実験2(2026年)", study_id = "study2"),
  party_support_relative_cue_results$study3$intervals %>% dplyr::mutate(実験 = "実験3(2026年)", study_id = "study3")
) %>%
  dplyr::mutate(
    条件 = purrr::map2_chr(party_n, study_id, 条件日本語),
    指標 = purrr::map2_chr(statistic, study_id, 統計量日本語),
    表示値 = dplyr::if_else(statistic == "relative_party_weight_pairwise", 100 * estimate, 100 * estimate),
    下限 = 100 * conf_low,
    上限 = 100 * conf_high,
    単位 = dplyr::if_else(statistic == "relative_party_weight_pairwise", "%", "pp")
  )

相対比重データ <- 支持手がかり一覧 %>%
  dplyr::filter(statistic == "relative_party_weight_pairwise") %>%
  dplyr::mutate(数値ラベル = sprintf("%.1f%%", 表示値))

for (実験名 in unique(相対比重データ$実験)) {
  描画データ <- 相対比重データ %>% dplyr::filter(実験 == 実験名)
<- ggplot2::ggplot(描画データ, ggplot2::aes(x = party_n, y = 表示値, group = party_support_h)) +
    ggplot2::geom_hline(yintercept = 50, linetype = "dashed", linewidth = 0.4) +
    ggplot2::geom_line(linewidth = 0.65) +
    ggplot2::geom_errorbar(ggplot2::aes(ymin = 下限, ymax = 上限), width = 0.08, linewidth = 0.45) +
    ggplot2::geom_label(ggplot2::aes(label = 数値ラベル), size = 3.0, label.size = 0, fill = "white") +
    ggplot2::facet_wrap(~ party_support_h, scales = "free_y") +
    ggplot2::scale_x_continuous(breaks = 2:5, labels = 条件日本語(2:5, ifelse(unique(描画データ$study_id) == "study3", "study3", "study1"))) +
    ggplot2::labs(x = NULL, y = "政党手がかり相対比重(%)", subtitle = 実験名) +
    ggplot2::theme_bw(base_size = 10) +
    ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
  print(図)
}

表H2 <- 支持手がかり一覧 %>%
  dplyr::transmute(
    実験,
    支持政党 = party_support_h,
    `条件・指標` = paste0(条件, ":", 指標),
    推定値 = round(表示値, 2),
    `95%CI下限` = round(下限, 2),
    `95%CI上限` = round(上限, 2),
    単位
  )
knitr::kable(表日本語(表H2), format = "html", row.names = FALSE, caption = "表H2:支持政党別の手がかり重要度と相対比重")
表H2:支持政党別の手がかり重要度と相対比重
実験 支持政党 条件・指標 推定値 95%CI下限 95%CI上限 単位
実験1(2023年) 日本維新の会 2政党条件:政党重要度 5.09 3.59 6.78 pp
実験1(2023年) 日本維新の会 2政党条件:経済重要度 5.41 4.47 6.90 pp
実験1(2023年) 日本維新の会 2政党条件:政党重要度(選択肢数調整済み) 10.17 7.18 13.57 pp
実験1(2023年) 日本維新の会 2政党条件:経済重要度(選択肢数調整済み) 10.82 8.93 13.79 pp
実験1(2023年) 日本維新の会 2政党条件:政党手がかり相対比重 48.44 38.23 57.41 %
実験1(2023年) 日本維新の会 3政党条件:政党重要度 6.19 4.83 7.84 pp
実験1(2023年) 日本維新の会 3政党条件:経済重要度 4.38 3.68 5.51 pp
実験1(2023年) 日本維新の会 3政党条件:政党重要度(選択肢数調整済み) 18.58 14.49 23.52 pp
実験1(2023年) 日本維新の会 3政党条件:経済重要度(選択肢数調整済み) 13.15 11.03 16.53 pp
実験1(2023年) 日本維新の会 3政党条件:政党手がかり相対比重 58.56 49.36 65.52 %
実験1(2023年) 日本維新の会 4政党条件:政党重要度 5.52 4.24 6.99 pp
実験1(2023年) 日本維新の会 4政党条件:経済重要度 4.48 3.85 5.42 pp
実験1(2023年) 日本維新の会 4政党条件:政党重要度(選択肢数調整済み) 22.07 16.95 27.95 pp
実験1(2023年) 日本維新の会 4政党条件:経済重要度(選択肢数調整済み) 17.92 15.42 21.66 pp
実験1(2023年) 日本維新の会 4政党条件:政党手がかり相対比重 55.19 47.29 62.14 %
実験1(2023年) 日本維新の会 5政党条件:政党重要度 5.44 4.24 6.68 pp
実験1(2023年) 日本維新の会 5政党条件:経済重要度 4.30 3.64 5.03 pp
実験1(2023年) 日本維新の会 5政党条件:政党重要度(選択肢数調整済み) 27.22 21.22 33.40 pp
実験1(2023年) 日本維新の会 5政党条件:経済重要度(選択肢数調整済み) 21.51 18.22 25.14 pp
実験1(2023年) 日本維新の会 5政党条件:政党手がかり相対比重 55.87 48.23 62.06 %
実験1(2023年) 立憲民主党 2政党条件:政党重要度 5.20 3.31 7.93 pp
実験1(2023年) 立憲民主党 2政党条件:経済重要度 3.83 2.96 6.14 pp
実験1(2023年) 立憲民主党 2政党条件:政党重要度(選択肢数調整済み) 10.41 6.62 15.85 pp
実験1(2023年) 立憲民主党 2政党条件:経済重要度(選択肢数調整済み) 7.66 5.92 12.27 pp
実験1(2023年) 立憲民主党 2政党条件:政党手がかり相対比重 57.60 39.96 67.43 %
実験1(2023年) 立憲民主党 3政党条件:政党重要度 3.40 2.49 5.81 pp
実験1(2023年) 立憲民主党 3政党条件:経済重要度 3.88 3.29 5.75 pp
実験1(2023年) 立憲民主党 3政党条件:政党重要度(選択肢数調整済み) 10.19 7.46 17.42 pp
実験1(2023年) 立憲民主党 3政党条件:経済重要度(選択肢数調整済み) 11.63 9.87 17.25 pp
実験1(2023年) 立憲民主党 3政党条件:政党手がかり相対比重 46.70 33.47 57.85 %
実験1(2023年) 立憲民主党 4政党条件:政党重要度 5.25 3.56 7.11 pp
実験1(2023年) 立憲民主党 4政党条件:経済重要度 3.42 2.92 4.93 pp
実験1(2023年) 立憲民主党 4政党条件:政党重要度(選択肢数調整済み) 21.00 14.25 28.46 pp
実験1(2023年) 立憲民主党 4政党条件:経済重要度(選択肢数調整済み) 13.69 11.70 19.73 pp
実験1(2023年) 立憲民主党 4政党条件:政党手がかり相対比重 60.54 46.06 68.15 %
実験1(2023年) 立憲民主党 5政党条件:政党重要度 4.58 3.37 6.02 pp
実験1(2023年) 立憲民主党 5政党条件:経済重要度 3.58 2.75 4.60 pp
実験1(2023年) 立憲民主党 5政党条件:政党重要度(選択肢数調整済み) 22.91 16.87 30.08 pp
実験1(2023年) 立憲民主党 5政党条件:経済重要度(選択肢数調整済み) 17.88 13.74 22.99 pp
実験1(2023年) 立憲民主党 5政党条件:政党手がかり相対比重 56.17 46.56 65.70 %
実験1(2023年) 公明党 2政党条件:政党重要度 7.42 4.97 10.33 pp
実験1(2023年) 公明党 2政党条件:経済重要度 4.92 4.05 7.50 pp
実験1(2023年) 公明党 2政党条件:政党重要度(選択肢数調整済み) 14.85 9.95 20.66 pp
実験1(2023年) 公明党 2政党条件:経済重要度(選択肢数調整済み) 9.85 8.11 15.00 pp
実験1(2023年) 公明党 2政党条件:政党手がかり相対比重 60.12 46.64 68.04 %
実験1(2023年) 公明党 3政党条件:政党重要度 5.86 4.17 8.22 pp
実験1(2023年) 公明党 3政党条件:経済重要度 5.92 4.96 7.76 pp
実験1(2023年) 公明党 3政党条件:政党重要度(選択肢数調整済み) 17.57 12.52 24.67 pp
実験1(2023年) 公明党 3政党条件:経済重要度(選択肢数調整済み) 17.75 14.87 23.27 pp
実験1(2023年) 公明党 3政党条件:政党手がかり相対比重 49.75 37.47 59.67 %
実験1(2023年) 公明党 4政党条件:政党重要度 3.72 2.51 5.81 pp
実験1(2023年) 公明党 4政党条件:経済重要度 4.23 3.13 5.75 pp
実験1(2023年) 公明党 4政党条件:政党重要度(選択肢数調整済み) 14.86 10.02 23.22 pp
実験1(2023年) 公明党 4政党条件:経済重要度(選択肢数調整済み) 16.91 12.52 22.98 pp
実験1(2023年) 公明党 4政党条件:政党手がかり相対比重 46.78 34.69 60.02 %
実験1(2023年) 公明党 5政党条件:政党重要度 4.60 3.50 6.53 pp
実験1(2023年) 公明党 5政党条件:経済重要度 4.08 3.42 5.36 pp
実験1(2023年) 公明党 5政党条件:政党重要度(選択肢数調整済み) 23.02 17.51 32.64 pp
実験1(2023年) 公明党 5政党条件:経済重要度(選択肢数調整済み) 20.38 17.09 26.80 pp
実験1(2023年) 公明党 5政党条件:政党手がかり相対比重 53.04 42.31 63.34 %
実験1(2023年) 日本共産党 2政党条件:政党重要度 6.39 4.56 11.78 pp
実験1(2023年) 日本共産党 2政党条件:経済重要度 6.23 4.76 11.78 pp
実験1(2023年) 日本共産党 2政党条件:政党重要度(選択肢数調整済み) 12.78 9.11 23.56 pp
実験1(2023年) 日本共産党 2政党条件:経済重要度(選択肢数調整済み) 12.46 9.52 23.57 pp
実験1(2023年) 日本共産党 2政党条件:政党手がかり相対比重 50.64 31.63 66.38 %
実験1(2023年) 日本共産党 3政党条件:政党重要度 6.34 4.27 10.29 pp
実験1(2023年) 日本共産党 3政党条件:経済重要度 6.85 5.14 10.57 pp
実験1(2023年) 日本共産党 3政党条件:政党重要度(選択肢数調整済み) 19.01 12.82 30.87 pp
実験1(2023年) 日本共産党 3政党条件:経済重要度(選択肢数調整済み) 20.55 15.42 31.71 pp
実験1(2023年) 日本共産党 3政党条件:政党手がかり相対比重 48.05 32.82 62.62 %
実験1(2023年) 日本共産党 4政党条件:政党重要度 5.39 3.49 8.70 pp
実験1(2023年) 日本共産党 4政党条件:経済重要度 5.99 4.48 8.79 pp
実験1(2023年) 日本共産党 4政党条件:政党重要度(選択肢数調整済み) 21.57 13.97 34.78 pp
実験1(2023年) 日本共産党 4政党条件:経済重要度(選択肢数調整済み) 23.95 17.93 35.14 pp
実験1(2023年) 日本共産党 4政党条件:政党手がかり相対比重 47.38 34.06 60.47 %
実験1(2023年) 日本共産党 5政党条件:政党重要度 4.81 3.03 8.47 pp
実験1(2023年) 日本共産党 5政党条件:経済重要度 3.57 2.82 5.89 pp
実験1(2023年) 日本共産党 5政党条件:政党重要度(選択肢数調整済み) 24.07 15.17 42.36 pp
実験1(2023年) 日本共産党 5政党条件:経済重要度(選択肢数調整済み) 17.84 14.10 29.45 pp
実験1(2023年) 日本共産党 5政党条件:政党手がかり相対比重 57.44 38.54 71.29 %
実験2(2026年) 支持政党なし 2政党条件:政党重要度 3.83 2.53 6.22 pp
実験2(2026年) 支持政党なし 2政党条件:経済重要度 6.22 5.02 7.93 pp
実験2(2026年) 支持政党なし 2政党条件:政党重要度(選択肢数調整済み) 7.66 5.07 12.44 pp
実験2(2026年) 支持政党なし 2政党条件:経済重要度(選択肢数調整済み) 12.43 10.04 15.86 pp
実験2(2026年) 支持政党なし 2政党条件:政党手がかり相対比重 38.12 27.09 50.95 %
実験2(2026年) 支持政党なし 3政党条件:政党重要度 4.33 3.62 5.92 pp
実験2(2026年) 支持政党なし 3政党条件:経済重要度 5.24 4.35 6.50 pp
実験2(2026年) 支持政党なし 3政党条件:政党重要度(選択肢数調整済み) 13.00 10.87 17.77 pp
実験2(2026年) 支持政党なし 3政党条件:経済重要度(選択肢数調整済み) 15.72 13.05 19.50 pp
実験2(2026年) 支持政党なし 3政党条件:政党手がかり相対比重 45.26 38.89 54.38 %
実験2(2026年) 支持政党なし 4政党条件:政党重要度 4.85 3.96 6.09 pp
実験2(2026年) 支持政党なし 4政党条件:経済重要度 4.84 4.07 5.71 pp
実験2(2026年) 支持政党なし 4政党条件:政党重要度(選択肢数調整済み) 19.42 15.85 24.34 pp
実験2(2026年) 支持政党なし 4政党条件:経済重要度(選択肢数調整済み) 19.37 16.26 22.83 pp
実験2(2026年) 支持政党なし 4政党条件:政党手がかり相対比重 50.06 43.40 57.04 %
実験2(2026年) 支持政党なし 5政党条件:政党重要度 3.91 2.98 4.87 pp
実験2(2026年) 支持政党なし 5政党条件:経済重要度 3.90 3.34 4.73 pp
実験2(2026年) 支持政党なし 5政党条件:政党重要度(選択肢数調整済み) 19.53 14.91 24.35 pp
実験2(2026年) 支持政党なし 5政党条件:経済重要度(選択肢数調整済み) 19.49 16.69 23.64 pp
実験2(2026年) 支持政党なし 5政党条件:政党手がかり相対比重 50.05 41.26 57.35 %
実験2(2026年) 自由民主党 2政党条件:政党重要度 11.95 9.31 14.87 pp
実験2(2026年) 自由民主党 2政党条件:経済重要度 4.99 3.53 7.23 pp
実験2(2026年) 自由民主党 2政党条件:政党重要度(選択肢数調整済み) 23.89 18.62 29.73 pp
実験2(2026年) 自由民主党 2政党条件:経済重要度(選択肢数調整済み) 9.98 7.05 14.46 pp
実験2(2026年) 自由民主党 2政党条件:政党手がかり相対比重 70.53 60.77 78.71 %
実験2(2026年) 自由民主党 3政党条件:政党重要度 11.71 9.95 13.43 pp
実験2(2026年) 自由民主党 3政党条件:経済重要度 5.18 3.88 6.75 pp
実験2(2026年) 自由民主党 3政党条件:政党重要度(選択肢数調整済み) 35.13 29.86 40.30 pp
実験2(2026年) 自由民主党 3政党条件:経済重要度(選択肢数調整済み) 15.53 11.64 20.25 pp
実験2(2026年) 自由民主党 3政党条件:政党手がかり相対比重 69.35 61.89 76.20 %
実験2(2026年) 自由民主党 4政党条件:政党重要度 10.84 9.30 12.34 pp
実験2(2026年) 自由民主党 4政党条件:経済重要度 3.96 3.20 5.18 pp
実験2(2026年) 自由民主党 4政党条件:政党重要度(選択肢数調整済み) 43.36 37.21 49.37 pp
実験2(2026年) 自由民主党 4政党条件:経済重要度(選択肢数調整済み) 15.84 12.80 20.74 pp
実験2(2026年) 自由民主党 4政党条件:政党手がかり相対比重 73.24 65.54 78.08 %
実験2(2026年) 自由民主党 5政党条件:政党重要度 10.62 9.61 11.74 pp
実験2(2026年) 自由民主党 5政党条件:経済重要度 2.40 1.90 3.27 pp
実験2(2026年) 自由民主党 5政党条件:政党重要度(選択肢数調整済み) 53.11 48.05 58.72 pp
実験2(2026年) 自由民主党 5政党条件:経済重要度(選択肢数調整済み) 12.00 9.52 16.35 pp
実験2(2026年) 自由民主党 5政党条件:政党手がかり相対比重 81.57 75.95 85.34 %
実験2(2026年) 国民民主党 2政党条件:政党重要度 5.66 4.06 12.30 pp
実験2(2026年) 国民民主党 2政党条件:経済重要度 8.46 6.45 13.94 pp
実験2(2026年) 国民民主党 2政党条件:政党重要度(選択肢数調整済み) 11.33 8.11 24.60 pp
実験2(2026年) 国民民主党 2政党条件:経済重要度(選択肢数調整済み) 16.93 12.89 27.87 pp
実験2(2026年) 国民民主党 2政党条件:政党手がかり相対比重 40.09 27.47 59.50 %
実験2(2026年) 国民民主党 3政党条件:政党重要度 6.22 4.94 9.76 pp
実験2(2026年) 国民民主党 3政党条件:経済重要度 6.91 5.32 9.75 pp
実験2(2026年) 国民民主党 3政党条件:政党重要度(選択肢数調整済み) 18.65 14.83 29.28 pp
実験2(2026年) 国民民主党 3政党条件:経済重要度(選択肢数調整済み) 20.74 15.96 29.24 pp
実験2(2026年) 国民民主党 3政党条件:政党手がかり相対比重 47.34 38.02 60.40 %
実験2(2026年) 国民民主党 4政党条件:政党重要度 3.98 2.94 7.73 pp
実験2(2026年) 国民民主党 4政党条件:経済重要度 5.50 4.46 8.17 pp
実験2(2026年) 国民民主党 4政党条件:政党重要度(選択肢数調整済み) 15.94 11.76 30.91 pp
実験2(2026年) 国民民主党 4政党条件:経済重要度(選択肢数調整済み) 22.01 17.82 32.68 pp
実験2(2026年) 国民民主党 4政党条件:政党手がかり相対比重 42.00 31.79 58.16 %
実験2(2026年) 国民民主党 5政党条件:政党重要度 5.02 3.68 7.36 pp
実験2(2026年) 国民民主党 5政党条件:経済重要度 4.19 3.36 6.32 pp
実験2(2026年) 国民民主党 5政党条件:政党重要度(選択肢数調整済み) 25.11 18.42 36.81 pp
実験2(2026年) 国民民主党 5政党条件:経済重要度(選択肢数調整済み) 20.95 16.82 31.60 pp
実験2(2026年) 国民民主党 5政党条件:政党手がかり相対比重 54.51 40.84 65.60 %
実験2(2026年) 日本維新の会 2政党条件:政党重要度 6.99 4.19 12.61 pp
実験2(2026年) 日本維新の会 2政党条件:経済重要度 5.86 4.48 10.95 pp
実験2(2026年) 日本維新の会 2政党条件:政党重要度(選択肢数調整済み) 13.98 8.38 25.22 pp
実験2(2026年) 日本維新の会 2政党条件:経済重要度(選択肢数調整済み) 11.73 8.95 21.90 pp
実験2(2026年) 日本維新の会 2政党条件:政党手がかり相対比重 54.38 36.28 65.23 %
実験2(2026年) 日本維新の会 3政党条件:政党重要度 4.58 3.07 8.58 pp
実験2(2026年) 日本維新の会 3政党条件:経済重要度 5.69 4.53 8.49 pp
実験2(2026年) 日本維新の会 3政党条件:政党重要度(選択肢数調整済み) 13.74 9.20 25.75 pp
実験2(2026年) 日本維新の会 3政党条件:経済重要度(選択肢数調整済み) 17.06 13.60 25.48 pp
実験2(2026年) 日本維新の会 3政党条件:政党手がかり相対比重 44.60 30.75 59.88 %
実験2(2026年) 日本維新の会 4政党条件:政党重要度 6.29 4.16 10.00 pp
実験2(2026年) 日本維新の会 4政党条件:経済重要度 4.11 3.14 7.15 pp
実験2(2026年) 日本維新の会 4政党条件:政党重要度(選択肢数調整済み) 25.16 16.64 39.99 pp
実験2(2026年) 日本維新の会 4政党条件:経済重要度(選択肢数調整済み) 16.45 12.58 28.59 pp
実験2(2026年) 日本維新の会 4政党条件:政党手がかり相対比重 60.46 42.10 72.36 %
実験2(2026年) 日本維新の会 5政党条件:政党重要度 5.28 3.88 7.83 pp
実験2(2026年) 日本維新の会 5政党条件:経済重要度 2.56 2.06 4.94 pp
実験2(2026年) 日本維新の会 5政党条件:政党重要度(選択肢数調整済み) 26.39 19.38 39.16 pp
実験2(2026年) 日本維新の会 5政党条件:経済重要度(選択肢数調整済み) 12.79 10.31 24.70 pp
実験2(2026年) 日本維新の会 5政党条件:政党手がかり相対比重 67.36 51.12 76.48 %
実験2(2026年) チームみらい 2政党条件:政党重要度 12.13 9.48 17.24 pp
実験2(2026年) チームみらい 2政党条件:経済重要度 5.89 4.43 11.21 pp
実験2(2026年) チームみらい 2政党条件:政党重要度(選択肢数調整済み) 24.27 18.95 34.47 pp
実験2(2026年) チームみらい 2政党条件:経済重要度(選択肢数調整済み) 11.78 8.86 22.41 pp
実験2(2026年) チームみらい 2政党条件:政党手がかり相対比重 67.32 51.58 76.76 %
実験2(2026年) チームみらい 3政党条件:政党重要度 2.76 2.42 7.43 pp
実験2(2026年) チームみらい 3政党条件:経済重要度 7.71 5.93 11.02 pp
実験2(2026年) チームみらい 3政党条件:政党重要度(選択肢数調整済み) 8.28 7.27 22.29 pp
実験2(2026年) チームみらい 3政党条件:経済重要度(選択肢数調整済み) 23.13 17.78 33.07 pp
実験2(2026年) チームみらい 3政党条件:政党手がかり相対比重 26.35 20.72 50.97 %
実験2(2026年) チームみらい 4政党条件:政党重要度 4.06 3.43 7.56 pp
実験2(2026年) チームみらい 4政党条件:経済重要度 4.97 3.60 7.89 pp
実験2(2026年) チームみらい 4政党条件:政党重要度(選択肢数調整済み) 16.23 13.74 30.24 pp
実験2(2026年) チームみらい 4政党条件:経済重要度(選択肢数調整済み) 19.86 14.41 31.56 pp
実験2(2026年) チームみらい 4政党条件:政党手がかり相対比重 44.96 36.39 63.14 %
実験2(2026年) チームみらい 5政党条件:政党重要度 3.80 2.63 5.99 pp
実験2(2026年) チームみらい 5政党条件:経済重要度 3.92 2.86 6.21 pp
実験2(2026年) チームみらい 5政党条件:政党重要度(選択肢数調整済み) 18.98 13.16 29.96 pp
実験2(2026年) チームみらい 5政党条件:経済重要度(選択肢数調整済み) 19.62 14.29 31.07 pp
実験2(2026年) チームみらい 5政党条件:政党手がかり相対比重 49.17 33.67 61.87 %
実験3(2026年) 支持政党なし 2選択肢条件:政党名重要度 12.75 10.83 15.93 pp
実験3(2026年) 支持政党なし 2選択肢条件:経済重要度 5.38 4.23 7.47 pp
実験3(2026年) 支持政党なし 2選択肢条件:政党名重要度(選択肢数調整済み) 25.49 21.66 31.87 pp
実験3(2026年) 支持政党なし 2選択肢条件:経済重要度(選択肢数調整済み) 10.76 8.47 14.93 pp
実験3(2026年) 支持政党なし 2選択肢条件:政党手がかり相対比重 70.32 62.45 77.48 %
実験3(2026年) 支持政党なし 3選択肢条件:政党名重要度 8.88 7.27 11.32 pp
実験3(2026年) 支持政党なし 3選択肢条件:経済重要度 5.34 4.46 6.49 pp
実験3(2026年) 支持政党なし 3選択肢条件:政党名重要度(選択肢数調整済み) 26.63 21.82 33.95 pp
実験3(2026年) 支持政党なし 3選択肢条件:経済重要度(選択肢数調整済み) 16.01 13.38 19.46 pp
実験3(2026年) 支持政党なし 3選択肢条件:政党手がかり相対比重 62.46 55.62 69.13 %
実験3(2026年) 支持政党なし 4選択肢条件:政党名重要度 8.31 7.00 10.19 pp
実験3(2026年) 支持政党なし 4選択肢条件:経済重要度 4.77 3.96 5.78 pp
実験3(2026年) 支持政党なし 4選択肢条件:政党名重要度(選択肢数調整済み) 33.24 27.99 40.76 pp
実験3(2026年) 支持政党なし 4選択肢条件:経済重要度(選択肢数調整済み) 19.09 15.84 23.12 pp
実験3(2026年) 支持政党なし 4選択肢条件:政党手がかり相対比重 63.52 57.46 70.08 %
実験3(2026年) 支持政党なし 5選択肢条件:政党名重要度 7.05 6.04 8.37 pp
実験3(2026年) 支持政党なし 5選択肢条件:経済重要度 4.04 3.47 4.74 pp
実験3(2026年) 支持政党なし 5選択肢条件:政党名重要度(選択肢数調整済み) 35.27 30.22 41.84 pp
実験3(2026年) 支持政党なし 5選択肢条件:経済重要度(選択肢数調整済み) 20.19 17.35 23.71 pp
実験3(2026年) 支持政党なし 5選択肢条件:政党手がかり相対比重 63.60 58.13 69.15 %
実験3(2026年) 自由民主党 2選択肢条件:政党名重要度 20.69 17.88 24.62 pp
実験3(2026年) 自由民主党 2選択肢条件:経済重要度 5.70 4.22 7.54 pp
実験3(2026年) 自由民主党 2選択肢条件:政党名重要度(選択肢数調整済み) 41.38 35.75 49.24 pp
実験3(2026年) 自由民主党 2選択肢条件:経済重要度(選択肢数調整済み) 11.40 8.44 15.08 pp
実験3(2026年) 自由民主党 2選択肢条件:政党手がかり相対比重 78.40 72.05 84.06 %
実験3(2026年) 自由民主党 3選択肢条件:政党名重要度 20.57 17.85 23.03 pp
実験3(2026年) 自由民主党 3選択肢条件:経済重要度 4.48 3.55 6.23 pp
実験3(2026年) 自由民主党 3選択肢条件:政党名重要度(選択肢数調整済み) 61.71 53.54 69.10 pp
実験3(2026年) 自由民主党 3選択肢条件:経済重要度(選択肢数調整済み) 13.44 10.64 18.68 pp
実験3(2026年) 自由民主党 3選択肢条件:政党手がかり相対比重 82.12 75.41 85.88 %
実験3(2026年) 自由民主党 4選択肢条件:政党名重要度 19.66 17.72 21.53 pp
実験3(2026年) 自由民主党 4選択肢条件:経済重要度 2.91 2.30 4.26 pp
実験3(2026年) 自由民主党 4選択肢条件:政党名重要度(選択肢数調整済み) 78.63 70.87 86.13 pp
実験3(2026年) 自由民主党 4選択肢条件:経済重要度(選択肢数調整済み) 11.63 9.20 17.05 pp
実験3(2026年) 自由民主党 4選択肢条件:政党手がかり相対比重 87.11 81.82 89.73 %
実験3(2026年) 自由民主党 5選択肢条件:政党名重要度 17.57 16.08 19.23 pp
実験3(2026年) 自由民主党 5選択肢条件:経済重要度 2.33 1.78 3.22 pp
実験3(2026年) 自由民主党 5選択肢条件:政党名重要度(選択肢数調整済み) 87.87 80.41 96.13 pp
実験3(2026年) 自由民主党 5選択肢条件:経済重要度(選択肢数調整済み) 11.64 8.92 16.08 pp
実験3(2026年) 自由民主党 5選択肢条件:政党手がかり相対比重 88.30 84.32 90.95 %
実験3(2026年) 国民民主党 2選択肢条件:政党名重要度 18.98 14.97 26.31 pp
実験3(2026年) 国民民主党 2選択肢条件:経済重要度 4.32 3.47 9.09 pp
実験3(2026年) 国民民主党 2選択肢条件:政党名重要度(選択肢数調整済み) 37.96 29.93 52.62 pp
実験3(2026年) 国民民主党 2選択肢条件:経済重要度(選択肢数調整済み) 8.64 6.93 18.17 pp
実験3(2026年) 国民民主党 2選択肢条件:政党手がかり相対比重 81.46 67.84 86.08 %
実験3(2026年) 国民民主党 3選択肢条件:政党名重要度 20.20 16.30 24.53 pp
実験3(2026年) 国民民主党 3選択肢条件:経済重要度 4.36 3.16 7.22 pp
実験3(2026年) 国民民主党 3選択肢条件:政党名重要度(選択肢数調整済み) 60.59 48.89 73.59 pp
実験3(2026年) 国民民主党 3選択肢条件:経済重要度(選択肢数調整済み) 13.09 9.49 21.67 pp
実験3(2026年) 国民民主党 3選択肢条件:政党手がかり相対比重 82.23 71.68 87.02 %
実験3(2026年) 国民民主党 4選択肢条件:政党名重要度 18.43 16.01 22.51 pp
実験3(2026年) 国民民主党 4選択肢条件:経済重要度 3.81 2.92 6.42 pp
実験3(2026年) 国民民主党 4選択肢条件:政党名重要度(選択肢数調整済み) 73.73 64.04 90.02 pp
実験3(2026年) 国民民主党 4選択肢条件:経済重要度(選択肢数調整済み) 15.25 11.69 25.66 pp
実験3(2026年) 国民民主党 4選択肢条件:政党手がかり相対比重 82.86 73.39 86.89 %
実験3(2026年) 国民民主党 5選択肢条件:政党名重要度 15.75 13.01 19.17 pp
実験3(2026年) 国民民主党 5選択肢条件:経済重要度 3.05 2.20 4.78 pp
実験3(2026年) 国民民主党 5選択肢条件:政党名重要度(選択肢数調整済み) 78.73 65.05 95.85 pp
実験3(2026年) 国民民主党 5選択肢条件:経済重要度(選択肢数調整済み) 15.27 11.01 23.88 pp
実験3(2026年) 国民民主党 5選択肢条件:政党手がかり相対比重 83.75 75.55 88.48 %

補図H3:対象となる支持政党別の一致効果

一致効果 <- study3_all_party_match_results$coefficients %>%
  dplyr::filter(status == "estimated", !is.na(estimate)) %>%
  dplyr::mutate(
    条件 = 条件日本語(party_n, "study3"),
    数値ラベル = sprintf("%.1f", estimate_pp)
  )

補図H3 <- ggplot2::ggplot(一致効果, ggplot2::aes(x = party_n, y = estimate_pp, group = 1)) +
  ggplot2::geom_hline(yintercept = 0, linewidth = 0.4) +
  ggplot2::geom_line(linewidth = 0.65) +
  ggplot2::geom_errorbar(ggplot2::aes(ymin = conf.low_pp, ymax = conf.high_pp), width = 0.08, linewidth = 0.45) +
  ggplot2::geom_label(ggplot2::aes(label = 数値ラベル), size = 3.0, label.size = 0, fill = "white") +
  ggplot2::facet_wrap(~ support_party_valid) +
  ggplot2::scale_x_continuous(breaks = 2:5, labels = paste0(2:5, "選択肢")) +
  ggplot2::labs(x = "選択肢数", y = "一致効果(pp)") +
  ggplot2::theme_bw(base_size = 10) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
補図H3

表H3 <- 一致効果 %>%
  dplyr::transmute(
    支持政党 = support_party_valid,
    条件,
    回答者数 = n_ids,
    `一致効果(pp)` = round(estimate_pp, 2),
    `95%CI下限` = round(conf.low_pp, 2),
    `95%CI上限` = round(conf.high_pp, 2),
    p値 = signif(p.value, 3)
  )
knitr::kable(表日本語(表H3), format = "html", row.names = FALSE)
支持政党 条件 回答者数 一致効果(pp) 95%CI下限 95%CI上限 p値
自由民主党 2選択肢条件 163 34.77 28.06 41.49 0.00000000000000000048599999999999995625374338281687869
自由民主党 3選択肢条件 219 42.74 36.61 48.87 0.00000000000000000000000000000037699999999999995606639
自由民主党 4選択肢条件 254 47.62 41.97 53.28 0.00000000000000000000000000000000000000000476000000000
自由民主党 5選択肢条件 311 49.55 44.26 54.84 0.00000000000000000000000000000000000000000000000000197
国民民主党 2選択肢条件 49 25.26 8.98 41.53 0.00379999999999999999236721670570204878458753228187561
国民民主党 3選択肢条件 76 41.28 30.79 51.76 0.00000000004140000000000000050619231029003231014939956
国民民主党 4選択肢条件 70 48.40 37.40 59.40 0.00000000000143999999999999992264000658881428762470023
国民民主党 5選択肢条件 91 42.08 32.42 51.74 0.00000000000031500000000000002089040745945069943445560
表H4 <- study3_all_party_match_results$trends %>%
  dplyr::filter(status == "estimated") %>%
  dplyr::transmute(
    支持政党 = support_party_valid,
    `1選択肢増加あたりの変化(pp)` = round(estimate * 100, 2),
    `95%CI下限` = round(conf.low * 100, 2),
    `95%CI上限` = round(conf.high * 100, 2),
    p値 = signif(p.value, 3)
  )
knitr::kable(表日本語(表H4), format = "html", row.names = FALSE)
支持政党 1選択肢増加あたりの変化(pp) 95%CI下限 95%CI上限 p値
自由民主党 4.20 1.37 7.03 0.00372
国民民主党 3.23 -2.26 8.73 0.25000

I. 3実験横断分析

補図I1:主要仮説の線形傾向

主要仮説 <- hypothesis_test_summary %>%
  dplyr::mutate(
    実験 = dplyr::recode(study_id, study1 = "実験1(2023年)", study2 = "実験2(2026年)", study3 = "実験3(2026年)"),
    指標 = dplyr::case_when(
      stringr::str_detect(statistic, "party") ~ "政党手がかり重要度",
      stringr::str_detect(statistic, "economic") ~ "経済手がかり重要度",
      TRUE ~ statistic
    ),
    予測方向 = dplyr::recode(expected_direction, positive = "正", negative = "負")
  )

主要仮説 <- 主要仮説 %>%
  dplyr::mutate(
    傾きpp = 100 * estimate,
    下限pp = 100 * conf_low,
    上限pp = 100 * conf_high,
    表示行 = paste0(hypothesis, ":", 指標),
    数値ラベル = sprintf("%.2f", 傾きpp)
  )

補図I1 <- ggplot2::ggplot(主要仮説, ggplot2::aes(x = 傾きpp, y = stats::reorder(表示行, 傾きpp))) +
  ggplot2::geom_vline(xintercept = 0, linewidth = 0.45) +
  ggplot2::geom_errorbarh(ggplot2::aes(xmin = 下限pp, xmax = 上限pp), height = 0.12, linewidth = 0.55) +
  ggplot2::geom_label(ggplot2::aes(label = 数値ラベル), size = 3.1, label.size = 0, fill = "white") +
  ggplot2::labs(x = "選択肢が1つ増えるときの重要度の変化(pp)", y = NULL) +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
補図I1

表I1 <- 主要仮説 %>%
  dplyr::transmute(
    実験,
    仮説 = hypothesis,
    指標,
    予測方向,
    傾き = round(estimate, 4),
    `95%CI下限` = round(conf_low, 4),
    `95%CI上限` = round(conf_high, 4),
    p値 = signif(p_value_two_sided, 3),
    判定 = conclusion
  )
knitr::kable(表日本語(表I1), format = "html", row.names = FALSE)
実験 仮説 指標 予測方向 傾き 95%CI下限 95%CI上限 p値 判定
実験1(2023年) H1a(実験1) 政党手がかり重要度 -0.0013 -0.0057 0.0030 0.536 点推定が予測方向と一致しない
実験1(2023年) H1b(実験1) 経済手がかり重要度 -0.0023 -0.0058 0.0002 0.076 点推定は予測方向だが、95%信頼区間が0を含む
実験2(2026年) H1a(実験2) 政党手がかり重要度 -0.0015 -0.0062 0.0025 0.387 点推定が予測方向と一致しない
実験2(2026年) H1b(実験2) 経済手がかり重要度 -0.0078 -0.0113 -0.0046 0.001 予測方向で95%信頼区間が0を含まず、統計的に支持
実験3(2026年) H2a(実験3) 政党手がかり重要度 -0.0162 -0.0223 -0.0103 0.001 点推定が予測方向と一致しない
実験3(2026年) H2b(実験3) 経済手がかり重要度 -0.0074 -0.0106 -0.0045 0.001 予測方向で95%信頼区間が0を含まず、統計的に支持

補図I2:選択肢数調整済み重要度の線形傾向

調整済み傾向 <- choice_set_adjusted_slope_summary %>%
  dplyr::mutate(
    実験 = dplyr::recode(study_id, study1 = "実験1(2023年)", study2 = "実験2(2026年)", study3 = "実験3(2026年)"),
    指標 = dplyr::case_when(
      stringr::str_detect(statistic, "party") ~ "政党手がかり重要度(選択肢数調整済み)",
      stringr::str_detect(statistic, "economic") ~ "経済手がかり重要度(選択肢数調整済み)",
      TRUE ~ statistic
    )
  )

調整済み傾向 <- 調整済み傾向 %>%
  dplyr::mutate(
    傾き表示 = 100 * estimate,
    下限表示 = 100 * conf_low,
    上限表示 = 100 * conf_high,
    表示行 = paste0(実験, ":", 指標),
    数値ラベル = sprintf("%.2f", 傾き表示)
  )

補図I2 <- ggplot2::ggplot(調整済み傾向, ggplot2::aes(x = 傾き表示, y = stats::reorder(表示行, 傾き表示))) +
  ggplot2::geom_vline(xintercept = 0, linewidth = 0.45) +
  ggplot2::geom_errorbarh(ggplot2::aes(xmin = 下限表示, xmax = 上限表示), height = 0.12, linewidth = 0.55) +
  ggplot2::geom_label(ggplot2::aes(label = 数値ラベル), size = 3.1, label.size = 0, fill = "white") +
  ggplot2::labs(x = "選択肢が1つ増えるときの調整済み重要度の変化(%)", y = NULL) +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank())
補図I2

表I2 <- 調整済み傾向 %>%
  dplyr::transmute(
    実験,
    指標,
    傾き = round(estimate, 4),
    `95%CI下限` = round(conf_low, 4),
    `95%CI上限` = round(conf_high, 4),
    p値 = signif(p_value_two_sided, 3)
  )
knitr::kable(表日本語(表I2), format = "html", row.names = FALSE)
実験 指標 傾き 95%CI下限 95%CI上限 p値
実験1(2023年) 政党手がかり重要度(選択肢数調整済み) 0.0463 0.0319 0.0616 0.001
実験1(2023年) 経済手がかり重要度(選択肢数調整済み) 0.0347 0.0253 0.0440 0.001
実験2(2026年) 政党手がかり重要度(選択肢数調整済み) 0.0414 0.0289 0.0528 0.001
実験2(2026年) 経済手がかり重要度(選択肢数調整済み) 0.0148 0.0064 0.0239 0.001
実験3(2026年) 政党手がかり重要度(選択肢数調整済み) 0.0552 0.0394 0.0734 0.001
実験3(2026年) 経済手がかり重要度(選択肢数調整済み) 0.0132 0.0047 0.0216 0.002

補図I3:政党手がかり相対比重の3実験比較

横断相対比重 <- cross_study_relative_weight %>%
  dplyr::mutate(
    実験 = dplyr::recode(study_id, study1 = "実験1(2023年)", study2 = "実験2(2026年)", study3 = "実験3(2026年)"),
    相対比重 = 100 * estimate,
    下限 = 100 * conf_low,
    上限 = 100 * conf_high,
    数値ラベル = sprintf("%.1f%%", 相対比重)
  )

補図I3 <- ggplot2::ggplot(横断相対比重, ggplot2::aes(x = party_n, y = 相対比重, group = 実験, linetype = 実験)) +
  ggplot2::geom_hline(yintercept = 50, linetype = "dashed", linewidth = 0.4) +
  ggplot2::geom_line(linewidth = 0.75) +
  ggplot2::geom_errorbar(ggplot2::aes(ymin = 下限, ymax = 上限), width = 0.07, linewidth = 0.45) +
  ggplot2::geom_label(ggplot2::aes(label = 数値ラベル), size = 3.0, label.size = 0, fill = "white") +
  ggplot2::scale_x_continuous(breaks = 2:5, labels = paste0(2:5, "選択肢")) +
  ggplot2::labs(x = "選択肢数", y = "政党手がかり相対比重(%)", linetype = NULL) +
  ggplot2::theme_bw(base_size = 11) +
  ggplot2::theme(panel.grid.minor = ggplot2::element_blank(), legend.position = "top")
補図I3

表I3 <- 横断相対比重 %>%
  dplyr::transmute(
    実験,
    条件 = paste0(party_n, "選択肢条件"),
    `政党手がかり相対比重(%)` = round(相対比重, 1),
    `95%CI下限` = round(下限, 1),
    `95%CI上限` = round(上限, 1)
  )
knitr::kable(表日本語(表I3), format = "html", row.names = FALSE)
実験 条件 政党手がかり相対比重(%) 95%CI下限 95%CI上限
実験1(2023年) 2選択肢条件 53.1 44.8 59.6
実験1(2023年) 3選択肢条件 54.7 47.4 60.5
実験1(2023年) 4選択肢条件 54.3 48.5 59.5
実験1(2023年) 5選択肢条件 55.6 49.6 60.5
実験2(2026年) 2選択肢条件 48.3 39.9 55.7
実験2(2026年) 3選択肢条件 47.1 42.1 53.1
実験2(2026年) 4選択肢条件 52.8 47.5 57.7
実験2(2026年) 5選択肢条件 59.4 54.4 63.3
実験3(2026年) 2選択肢条件 73.2 68.2 77.4
実験3(2026年) 3選択肢条件 72.8 68.9 76.5
実験3(2026年) 4選択肢条件 74.6 71.0 78.2
実験3(2026年) 5選択肢条件 75.6 72.2 78.6

J. 調査票

本節では、実験1(2023年)、実験2(2026年)、実験3(2026年)で回答者に提示した調査票をまとめて再掲する。質問文と回答選択肢は、各Qualtrics調査票のエクスポートに基づき、原文の表記を原則として維持した。コンジョイント課題は各条件で5回繰り返されるため、同一の質問文を5回重複掲載する代わりに、すべての質問IDを列挙したうえで共通の質問文を1回示す。各課題でランダムに差し込まれるQualtricsのEmbedded Dataコードは、回答者にとっての実質的な質問文ではないため省略し、その代わりに無作為化された属性と水準を表として示す。Qualtricsのフロー制御、WebService、ページ区切り等の技術的メタデータも省略する。 なお、元の調査票に残る表記上の不統一は、ここで内容を変えてしまわないよう原則としてそのまま掲載する。とくに実験1のQ258、Q259、Q260には、4・5・2選択肢条件の説明中に「3つの選択肢」とする表記が残っている。また、実験1の複数選択肢条件の選択課題には「以下のどちらの政党」という表記が残っている。これらは原文ママである。 ## J.1 実験1(2023年) ### J.1.1 調査開始時の説明と同意
Q1.1 調査説明(クリックして全文を表示)

「経済評価と政権交代をめぐる意識調査」 ご協力のお願い 関西学院大学 総合政策学部 教授 大村 華子 (おおむら はなこ) ◆ このアンケート調査は、文部科学省による研究助成(研究課題番号:22K01320 「 経済と政治的支持の関係ー『不平の非対称性』仮説から見る日本の有権者」)に基づき実施される学術調査です。 ◆ 営利目的や、特定の政治勢力を支援するためのアンケート調査ではありません。また、あなたがこの調査に協力することによって、不利益を被ることもありません。 ◆ 本調査では、あなたの政治、経済に関する意識などもお伺いすることになりますので、ご承知おきいただきたく存じます。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ また本調査では、あなたの所得についてもお尋ねします。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ 政治や行政についての質問には、答えづらいものもあります。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ 得られた回答はすべて統計的に処理し、回答者の属性などがわからないようにします。個人の情報が特定されることはありませんので、安心してご回答ください。 ◆ アンケート調査の分析結果については、新聞などを通じて一般の人に対しても積極的に発信する予定です。皆さまのご協力の程、よろしくお願い申し上げます。 ◆ 不適切な回答を行うことは、調査結果の質を低下させます。すべての質問に対して、不適切な形で回答しないよう、よろしくお願い申し上げます。不適切な回答を行った場合は、調査を終了させて頂く場合がございます。 ◆ 本アンケート調査に関してご不明な点等がございましたら、下記メールアドレスまでお問い合わせください。 e-mail: 以上をご確認の上、調査を開始する場合は、 「本調査の趣旨と個人情報の取り扱いに同意して、調査を開始する」 ボタンをクリックして、右下の「>>」または「次へ」ボタンを押して、調査を開始してください。

回答選択肢

  • 本調査の趣旨に同意して、本調査に協力する (1)
  • 本調査の趣旨に同意しないので、本調査に協力しない (2)

J.1.2 フェイスシート、政党支持、所得

質問ID 質問文 回答形式・選択肢
Q2.1 あなたの性別は、以下のうちどちらに該当しますでしょうか。 女性 (1)/男性 (2)/どちらでもない (3)/答えない (4)
Q2.2 あなたの現在のご年齢を記入してください。 ※記入に際しては、半角数字で入力してください。 18~80歳(Qualtricsのドロップダウン)
Q2.4 あなたが最後に卒業した学校は次のうちどれでしょうか。 *中退した方や在籍中の方も卒業とみなしてください。 小学校(旧小・旧高小)卒業 (1)/高校(旧中)卒業 (2)/高等専門・短期大学・専修学校卒業 (3)/4年制大学卒業 (4)/大学院卒業 (5)/わからない (6)/こたえない (7)
Q2.7 あなたはどの政党を支持しておられますか。 自由民主党 (1)/立憲民主党 (2)/公明党 (3)/日本維新の会 (4)/日本共産党 (5)/国民民主党 (6)/社会民主党 (7)/れいわ新選組 (8)/その他 (11)/支持する政党はない (12)/わからない (13)/答えない (14)
Q3.1 あなたの世帯の税引き前の世帯年収と手取りの年収は、だいたいおいくらぐらいでしょうか。 税引き前の収入とは、一般的に「額面の収入」と言われるものです。その額面の収入から、税金や社会保険料を引いた残りが「手取りの収入」と言われるものです。 あなたの収入、配偶者の収入をすべて含めたものを、以下の物差しをスライドさせながら、おおまかに指定してください。 いずれもが「3000万円以上」の人は、「3000」を選択してください。 税引き前世帯年収・手取り年収の2項目。0~3000万円のスライダー(3000=3000万円以上)

J.1.3 コンジョイント課題

回答者は、2・3・4・5政党のいずれか1条件に無作為に割り当てられ、同じ選択肢数の課題に5回答えた。各課題では、下表の7属性の水準がプロフィールごとに無作為に提示された。 | 属性 | 水準 | |—|—| | 政策位置 | 右派・保守的/中道/左派・革新的 | | 与野党地位 | 与党/野党 | | 議席数 | 10以下/10~49/50~99/100~199/200以上 | | GDP成長率 | ±0%/プラス1%/マイナス1% | | 日経平均株価 | 前月同期比 変わらず/プラス1000円/マイナス1000円 | | CPI | 前期比 ±0ポイント/プラス1ポイント/マイナス1ポイント | | 失業率 | 前期比 ±0%/プラス1%/マイナス1% |

条件別の説明文・選択課題

2政党条件(\(k=2\)

導入質問 Q260
今から、日本の政党めぐる2つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q240, Q253, Q254, Q255, Q256(5回)
以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のどちらの政党をお選びになりますか。 政党1 政党2 ${e://Field/F-1-1} ${e://Field/F-1-1-1} ${e://Field/F-1-2-1} ${e://Field/F-1-2} ${e://Field/F-1-1-2} ${e://Field/F-1-2-2} ${e://Field/F-1-3} ${e://Field/F-1-1-3} ${e://Field/F-1-2-3} ${e://Field/F-1-4} ${e://Field/F-1-1-4} ${e://Field/F-1-2-4} ${e://Field/F-1-5} ${e://Field/F-1-1-5} ${e://Field/F-1-2-5} ${e://Field/F-1-6} ${e://Field/F-1-1-6} ${e://Field/F-1-2-6} ${e://Field/F-1-7} ${e://Field/F-1-1-7} ${e://Field/F-1-2-7}

回答選択肢:政党1 (1)/政党2 (2)

3政党条件(\(k=3\)

導入質問 Q257
今から、日本の政党めぐる3つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q235, Q241, Q242, Q243, Q244(5回)
以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のどちらの政党をお選びになりますか。 政党1 政党2 政党3 ${e://Field/F-1-1} ${e://Field/F-1-1-1} ${e://Field/F-1-2-1} ${e://Field/F-1-3-1} ${e://Field/F-1-2} ${e://Field/F-1-1-2} ${e://Field/F-1-2-2} ${e://Field/F-1-3-2} ${e://Field/F-1-3} ${e://Field/F-1-1-3} ${e://Field/F-1-2-3} ${e://Field/F-1-3-3} ${e://Field/F-1-4} ${e://Field/F-1-1-4} ${e://Field/F-1-2-4} ${e://Field/F-1-3-4} ${e://Field/F-1-5} ${e://Field/F-1-1-5} ${e://Field/F-1-2-5} ${e://Field/F-1-3-5} ${e://Field/F-1-6} ${e://Field/F-1-1-6} ${e://Field/F-1-2-6} ${e://Field/F-1-3-6} ${e://Field/F-1-7} ${e://Field/F-1-1-7} ${e://Field/F-1-2-7} ${e://Field/F-1-3-7}

回答選択肢:政党1 (1)/政党2 (2)/政党3 (3)

4政党条件(\(k=4\)

導入質問 Q258
今から、日本の政党めぐる4つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q238, Q245, Q246, Q247, Q248(5回)
以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のどちらの政党をお選びになりますか。 政党1 政党2 政党3 政党4 ${e://Field/F-1-1} ${e://Field/F-1-1-1} ${e://Field/F-1-2-1} ${e://Field/F-1-3-1} ${e://Field/F-1-4-1} ${e://Field/F-1-2} ${e://Field/F-1-1-2} ${e://Field/F-1-2-2} ${e://Field/F-1-3-2} ${e://Field/F-1-4-2} ${e://Field/F-1-3} ${e://Field/F-1-1-3} ${e://Field/F-1-2-3} ${e://Field/F-1-3-3} ${e://Field/F-1-4-3} ${e://Field/F-1-4} ${e://Field/F-1-1-4} ${e://Field/F-1-2-4} ${e://Field/F-1-3-4} ${e://Field/F-1-4-4} ${e://Field/F-1-5} ${e://Field/F-1-1-5} ${e://Field/F-1-2-5} ${e://Field/F-1-3-5} ${e://Field/F-1-4-5} ${e://Field/F-1-6} ${e://Field/F-1-1-6} ${e://Field/F-1-2-6} ${e://Field/F-1-3-6} ${e://Field/F-1-4-6} ${e://Field/F-1-7} ${e://Field/F-1-1-7} ${e://Field/F-1-2-7} ${e://Field/F-1-3-7} ${e://Field/F-1-4-7}

回答選択肢:政党1 (1)/政党2 (2)/政党3 (3)/政党4 (4)

5政党条件(\(k=5\)

導入質問 Q259
今から、日本の政党めぐる5つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q239, Q249, Q250, Q251, Q252(5回)
以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のどちらの政党をお選びになりますか。 政党1 政党2 政党3 政党4 政党5 ${e://Field/F-1-1} ${e://Field/F-1-1-1} ${e://Field/F-1-2-1} ${e://Field/F-1-3-1} ${e://Field/F-1-4-1} ${e://Field/F-1-5-1} ${e://Field/F-1-2} ${e://Field/F-1-1-2} ${e://Field/F-1-2-2} ${e://Field/F-1-3-2} ${e://Field/F-1-4-2} ${e://Field/F-1-5-2} ${e://Field/F-1-3} ${e://Field/F-1-1-3} ${e://Field/F-1-2-3} ${e://Field/F-1-3-3} ${e://Field/F-1-4-3} ${e://Field/F-1-5-3} ${e://Field/F-1-4} ${e://Field/F-1-1-4} ${e://Field/F-1-2-4} ${e://Field/F-1-3-4} ${e://Field/F-1-4-4} ${e://Field/F-1-5-4} ${e://Field/F-1-5} ${e://Field/F-1-1-5} ${e://Field/F-1-2-5} ${e://Field/F-1-3-5} ${e://Field/F-1-4-5} ${e://Field/F-1-5-5} ${e://Field/F-1-6} ${e://Field/F-1-1-6} ${e://Field/F-1-2-6} ${e://Field/F-1-3-6} ${e://Field/F-1-4-6} ${e://Field/F-1-5-6} ${e://Field/F-1-7} ${e://Field/F-1-1-7} ${e://Field/F-1-2-7} ${e://Field/F-1-3-7} ${e://Field/F-1-4-7} ${e://Field/F-1-5-7}

回答選択肢:政党1 (1)/政党2 (2)/政党3 (3)/政党4 (4)/政党5 (5)

実験1には、実験2・3で用いた選択肢数の操作確認質問およびイデオロギー行列中の指示項目は設けられていない。 ### J.1.4 調査趣旨の再説明と最終送信同意
Q10.1 デブリーフィング・最終意思確認(クリックして全文を表示)

こちらが調査の最後の画面である「調査趣旨の再説明」と「回答結果の送信に関する最終意思確認」のページになります。 ・本調査では、政治、経済に関する意識などをお伺いさせていただきました。調査にご協力いただきましたことに、深く感謝申し上げます。 ・本調査に関してご不明な点等がございましたら、下記メールアドレスまでお問い合わせください。 e-mail: ・ 繰り返しとなりますが、得られた回答はすべて統計的に処理し、回答者の属性などがわからないようにします。個人の情報が特定されることはありませんので、ご安心ください。それでも個人情報の保護等に関して、回答者であるあなたがご不安を感じられる場合には「本調査の趣旨に同意しないので、回答を送信しない」という選択をすることも可能です。 以下では、本調査におけるいくつかの処置・操作につきまして、その目的・背景・仕組みを、より詳しく解説をさせていただきます。可能な限りご一読いただき、「本調査の趣旨に同意するので、回答結果を送信する」か「本調査の趣旨に同意しないので、回答結果を送信しない」をご選択くださいますようよろしくお願いいたします。 上記の内容をご確認いただいた上で、改めて「本調査の趣旨に同意しないので、回答結果を送信しない」という選択をすることも可能ですので、以下でご選択ください。

回答選択肢

  • 本調査の主旨に同意し、回答結果を送信する。 (1)
  • 本調査の主旨に同意しないので、回答結果を送信しない。 (2)
調査票末尾にはQ261「ここをクリックして質問文を入力」というQualtrics上の未使用プレースホルダーが残っているが、 実質的な調査項目ではないため、本節の質問一覧からは除外した。 ## J.2 実験2(2026年) ### J.2.1 調査開始時の説明と同意
Q1.1 調査説明(クリックして全文を表示)

「経済評価と政権運営をめぐる意識調査」 ご協力のお願い 京都大学 公共政策連携研究部 教授 大村 華子 (おおむら はなこ) ◆ このアンケート調査は、文部科学省による研究助成(研究課題番号:26K04751「政策業績評価の研究-政治行動論と行動公共政策論の架橋」)に基づき実施される学術調査です。 ◆ 営利目的や、特定の政治勢力を支援するためのアンケート調査ではありません。また、あなたがこの調査に協力することによって、不利益を被ることもありません。 ◆ 本調査では、あなたの政治、経済に関する意識などもお伺いすることになりますので、ご承知おきいただきたく存じます。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ また本調査では、あなたの所得についてもお尋ねします。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ 政治や行政についての質問には、答えづらいものもあります。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ 得られた回答はすべて統計的に処理し、回答者の属性などがわからないようにします。個人の情報が特定されることはありませんので、安心してご回答ください。 ◆ アンケート調査の分析結果については、新聞などを通じて一般の人に対しても積極的に発信する予定です。皆さまのご協力の程、よろしくお願い申し上げます。 ◆ 不適切な回答を行うことは、調査結果の質を低下させます。すべての質問に対して、不適切な形で回答しないよう、よろしくお願い申し上げます。不適切な回答を行った場合は、調査を終了させて頂く場合がございます。 ◆ 本アンケート調査に関してご不明な点等がございましたら、下記メールアドレスまでお問い合わせください。 e-mail: 以上をご確認の上、調査を開始する場合は、 「本調査の趣旨と個人情報の取り扱いに同意して、調査を開始する」 ボタンをクリックして、右下の「>>」または「次へ」ボタンを押して、調査を開始してください。

回答選択肢

  • 本調査の趣旨に同意して、本調査に協力する (1)
  • 本調査の趣旨に同意しないので、本調査に協力しない (2)

J.2.2 フェイスシート

質問ID 質問文 回答形式・選択肢
Q2.1 あなたの性別を選んでください。 男性 (1)/女性 (2)/その他 (3)/こたえたくない (4)
Q2.2 あなたの年齢区分と現在の年齢を選んでください。 「年代」と「年齢」の連動ドロップダウン。調査票エクスポート上では選択肢一覧が省略表示されている。
Q2.3 あなたが現在お住まいの地域と都道府県を選んでください 「地域」と「都道府県」の連動ドロップダウン。調査票エクスポート上では選択肢一覧が省略表示されている。
Q2.4 あなたの世帯の税引き前の世帯年収と手取りの年収は、だいたいおいくらぐらいでしょうか。 税引き前の収入とは、一般的に「額面の収入」と言われるものです。その額面の収入から、税金や社会保険料を引いた残りが「手取りの収入」と言われるものです。 あなたの収入、配偶者の収入をすべて含めたものを、以下の物差しをスライドさせながら、おおまかに指定してください。 いずれもが「3000万円以上」の人は、「3000」を選択してください。 税引き前世帯年収・手取り年収の2項目。0~3000万円のスライダー(3000=3000万円以上)

J.2.3 コンジョイント課題

回答者は2・3・4・5政党のいずれか1条件に無作為に割り当てられ、5つの選択課題に回答した。プロフィールには次の7属性が提示された。 | 属性 | 水準 | |—|—| | 政策位置 | 右派・保守的/中道/左派・革新的 | | 与野党地位 | 与党/野党 | | 議席数 | 10以下/10~49/50~99/100~199/200以上 | | GDP成長率 | ±0%/プラス1%/マイナス1% | | 日経平均株価 | 前月同期比 変わらず/プラス1000円/マイナス1000円 | | CPI | 前期比 ±0ポイント/プラス1ポイント/マイナス1ポイント | | 失業率 | 前期比 ±0%/プラス1%/マイナス1% |

条件別の説明文・選択課題・操作確認

2政党条件(\(k=2\)

導入質問 Q6.1
今から、日本の政党めぐる2つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは2つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q6.2–Q6.6(5回)
以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。

回答選択肢:政党1 (1)/政党2 (2)

操作確認 Q6.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された政党の選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

3政党条件(\(k=3\)

導入質問 Q3.1
今から、日本の政党めぐる3つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q3.2–Q3.6(5回)
以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。

回答選択肢:政党1 (1)/政党2 (2)/政党3 (3)

操作確認 Q3.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された政党の選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

4政党条件(\(k=4\)

導入質問 Q4.1
今から、日本の政党めぐる4つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは4つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q4.2–Q4.6(5回)
以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。

回答選択肢:政党1 (1)/政党2 (2)/政党3 (3)/政党4 (4)

操作確認 Q4.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された政党の選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

5政党条件(\(k=5\)

導入質問 Q5.1
今から、日本の政党めぐる5つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは5つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q5.2–Q5.6(5回)
以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。 あなたは、衆議院議員総選挙において、以下のいずれの政党をお選びになりますか。

回答選択肢:政党1 (1)/政党2 (2)/政党3 (3)/政党4 (4)/政党5 (5)

操作確認 Q5.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された政党の選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

J.2.4 政治質問

Q7.1
政治的立場を表すのに、よく「右派」「左派」という言葉が使われます。1が右派的、6が中間、11が左派的だとすると、あなたや主要政党はどのあたりに位置付けられるとお考えでしょうか。

回答尺度:1(右派的)/2/3/4/5/6(中間)/7/8/9/10/11(左派的)/わからない/こたえたくない。

評価対象:あなた自身(Q25.1_1)、自由民主党(Q25.1_2)、立憲民主党(Q25.1_3)、日本維新の会(Q25.1_4)、公明党(Q25.1_10)、国民民主党(Q25.1_5)、れいわ新選組(Q25.1_6)、参政党(Q25.1_7)、共産党(Q25.1_8)、中道改革連合(Q25.1_9)、「!この項目は必ず『3』を選んでください!」(Q25.1_11)

Q7.2
選挙でどこに投票するかは別にして、国の政治で、あなたはどの政党あるいは政治団体を支持していますか。

  • 自由民主党 (1)
  • 中道改革連合 (2)
  • 立憲民主党 (18)
  • 公明党 (19)
  • 日本維新の会 (3)
  • 国民民主党 (4)
  • れいわ新選組 (5)
  • 共産党 (6)
  • 参政党 (7)
  • 日本保守党 (8)
  • 社民党 (9)
  • チームみらい (10)
  • その他の政党・政治団体(具体的に) (12) __________________________________________________
  • そのような政党はない (13)
  • わからない (14)
  • こたえたくない (15)

Q7.3
あなたが普段、政治に関する情報を見たり、聞いたりするために使う媒体は、どれでしょうか。あるだけ選んでください。

  • 新聞(朝刊) (1)
  • スポーツ新聞 (2)
  • 週刊誌 (3)
  • 政見放送 (4)
  • テレビのニュース (5)
  • ワイドショーや討論番組 (6)
  • マニフェスト・選挙公報 (7)
  • インターネット上のニュース記事(SNS含む) (8)
  • 政党や候補者のホームページなど(SNS含む) (9)
  • その他(具体的に) (10) __________________________________________________
  • ⊗見聞きしていない (11)
  • ⊗わからない (12)
  • ⊗こたえたくない (13)

J.2.5 調査趣旨の再説明と最終送信同意

Q8.1 デブリーフィング・最終意思確認(クリックして全文を表示)

こちらが調査の最後の画面である「調査趣旨の再説明」と「回答結果の送信に関する最終意思確認」のページになります。まずはここまで調査にご協力くださいましたことに、心から御礼申し上げる次第です。 ・本調査では、政治、経済に関する意識などをお伺いさしました。調査にご協力いただきましたことに、深く感謝申し上げます。 ・本調査に関してご不明な点等がございましたら、下記メールアドレスまでお問い合わせください。 e-mail: 【本調査・本実験に関するご説明:表があって、表に政党名や経済状況が表示されるものをなぜご覧いただいたのか?】 ・本調査では、表があって、その表に政党名や経済状況がたくさん示されたものをご覧になっていただきました。皆様には、 2つの政党の中から1つを選ぶ 3つの政党の中から1つを選ぶ 4つの政党の中から1つを選ぶ 5つの政党の中から1つを選ぶ という作業のうちの1つを、繰り返して5回行っていただきました。 ・表の中にたくさんの情報が組み込まれているうえに、さらに質問を重ねたことで、皆さまの中には、回答がわずらわしく、何かを考えたり選んだりする作業を面倒だと感じ、回答を不快に思われた方がおられたかもしれません。そのような中、最後までご回答くださったことに、何より感謝申し上げます。 ・本調査は、政党名と経済状況が示された時に、私たちはどちらにもとづいて政党を選ぼうとするのかを明らかにするためのものでした。 ・そのために皆様には、政治集団、イデオロギー、党派性に関わることをお答えいただいたり、それらに対する皆様のお考え・ご意向をお伺いすることになりました。 ・このような背景をもつ調査ではありますが、回答にご協力くださった皆様の中には、不快感を抱かれた方がおられるかもしれません。そのような方は、以下の「本調査の趣旨に同意せず、回答結果を送信しない」ボタンを押して、本調査を終了してください。その場合に、本調査への回答を分析に使用させていただくことは致しません。その場合であっても、ポイントは付与されますので、どうかご安心ください。 ・また本調査には、研究者が独自に収集・作成したデータが含まれます。それらを無断で転記、転写、スクリーンショットなどによって、さまざまな媒体に配布することは、著作権に抵触する恐れがあります。調査画面の無断での転記、転写、スクリーンショット等により公開・共有するといった行為はお控えいただきますようよろしくお願い致します。

回答選択肢

  • 本調査の主旨に同意し、回答結果を送信する。 (1)
  • 本調査の主旨に同意しないので、回答結果を送信しない。 (2)

J.3 実験3(2026年)

J.3.1 調査開始時の説明と同意

Q1.1 調査説明(クリックして全文を表示)

「経済評価と政権運営をめぐる意識調査」 ご協力のお願い 京都大学 公共政策連携研究部 教授 大村 華子 (おおむら はなこ) ◆ このアンケート調査は、文部科学省による研究助成(研究課題番号:26K04751「政策業績評価の研究-政治行動論と行動公共政策論の架橋」)に基づき実施される学術調査です。 ◆ 営利目的や、特定の政治勢力を支援するためのアンケート調査ではありません。また、あなたがこの調査に協力することによって、不利益を被ることもありません。 ◆ 本調査では、あなたの政治、経済に関する意識などもお伺いすることになりますので、ご承知おきいただきたく存じます。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ また本調査では、あなたの所得についてもお尋ねします。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ 政治や行政についての質問には、答えづらいものもあります。もし回答を不快に感じられた場合、あなたはいつでも回答をやめることができます。 ◆ 得られた回答はすべて統計的に処理し、回答者の属性などがわからないようにします。個人の情報が特定されることはありませんので、安心してご回答ください。 ◆ アンケート調査の分析結果については、新聞などを通じて一般の人に対しても積極的に発信する予定です。皆さまのご協力の程、よろしくお願い申し上げます。 ◆ 不適切な回答を行うことは、調査結果の質を低下させます。すべての質問に対して、不適切な形で回答しないよう、よろしくお願い申し上げます。不適切な回答を行った場合は、調査を終了させて頂く場合がございます。 ◆ 本アンケート調査に関してご不明な点等がございましたら、下記メールアドレスまでお問い合わせください。 e-mail: 以上をご確認の上、調査を開始する場合は、 「本調査の趣旨と個人情報の取り扱いに同意して、調査を開始する」 ボタンをクリックして、右下の「>>」または「次へ」ボタンを押して、調査を開始してください。

回答選択肢

  • 本調査の趣旨に同意して、本調査に協力する (1)
  • 本調査の趣旨に同意しないので、本調査に協力しない (2)

J.3.2 フェイスシート

実験3のQ2.1~Q2.4は実験2と同じ質問文・回答形式である。再現性のため、質問IDと内容を再掲する。

質問ID 質問文 回答形式・選択肢
Q2.1 あなたの性別を選んでください。 男性 (1)/女性 (2)/その他 (3)/こたえたくない (4)
Q2.2 あなたの年齢区分と現在の年齢を選んでください。 「年代」と「年齢」の連動ドロップダウン。調査票エクスポート上では選択肢一覧が省略表示されている。
Q2.3 あなたが現在お住まいの地域と都道府県を選んでください 「地域」と「都道府県」の連動ドロップダウン。調査票エクスポート上では選択肢一覧が省略表示されている。
Q2.4 あなたの世帯の税引き前の世帯年収と手取りの年収は、だいたいおいくらぐらいでしょうか。 税引き前の収入とは、一般的に「額面の収入」と言われるものです。その額面の収入から、税金や社会保険料を引いた残りが「手取りの収入」と言われるものです。 あなたの収入、配偶者の収入をすべて含めたものを、以下の物差しをスライドさせながら、おおまかに指定してください。 いずれもが「3000万円以上」の人は、「3000」を選択してください。 税引き前世帯年収・手取り年収の2項目。0~3000万円のスライダー(3000=3000万円以上)

J.3.3 コンジョイント課題

実験3では、政党名と4つの経済属性からなるプロフィールを提示した。回答者は2・3・4・5選択肢のいずれか1条件に無作為に割り当てられ、5課題に回答した。 | 属性 | 水準 | |—|—| | 政党名 | 自由民主党/立憲民主党/日本維新の会/公明党/国民民主党/れいわ新選組/参政党/日本共産党/中道改革連合 | | GDP成長率 | ±0%/プラス1%/マイナス1% | | 日経平均株価 | 前月同期比 変わらず/プラス1000円/マイナス1000円 | | CPI | 前期比 ±0ポイント/プラス1ポイント/マイナス1ポイント | | 失業率 | 前期比 ±0%/プラス1%/マイナス1% |

条件別の説明文・選択課題・操作確認

2選択肢条件(\(k=2\)

導入質問 Q6.1
今から、日本の政党めぐる2つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは2つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q6.2–Q6.6(5回)
以下に、日本の政党をめぐる2つの選択肢を提示させていただきます。 表の一番上に上がっている政党が政権与党であったり、連立政権として与党に加わっているとします。そして衆議院総選挙があるとお考え下さい。 政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。 選択肢の順は、左から状況1、状況2とします。

回答選択肢:状況1 (1)/状況2 (2)

操作確認 Q6.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

3選択肢条件(\(k=3\)

導入質問 Q3.1
今から、日本の政党めぐる3つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは3つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q3.2–Q3.6(5回)
以下に、日本の政党をめぐる3つの選択肢を提示させていただきます。 表の一番上に上がっている政党が政権与党であったり、連立政権として与党に加わっているとします。そして衆議院総選挙があるとお考え下さい。 政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。 選択肢の順は、左から状況1、状況2、状況3とします。

回答選択肢:状況1 (1)/状況2 (2)/状況3 (3)

操作確認 Q3.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

4選択肢条件(\(k=4\)

導入質問 Q4.1
今から、日本の政党めぐる4つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは4つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q4.2–Q4.6(5回)
以下に、日本の政党をめぐる4つの選択肢を提示させていただきます。 表の一番上に上がっている政党が政権与党であったり、連立政権として与党に加わっているとします。そして衆議院総選挙があるとお考え下さい。 政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。 選択肢の順は、左から状況1、状況2、状況3、状況4とします。

回答選択肢:状況1 (1)/状況2 (2)/状況3 (3)/状況4 (4)

操作確認 Q4.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

5選択肢条件(\(k=5\)

導入質問 Q5.1
今から、日本の政党めぐる5つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは5つの選択肢の中からどの状況を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題 Q5.2–Q5.6(5回)
以下に、日本の政党をめぐる5つの選択肢を提示させていただきます。 表の一番上に上がっている政党が政権与党であったり、連立政権として与党に加わっているとします。そして衆議院総選挙があるとお考え下さい。 政権与党にある政党と経済状況の組み合わせのうち、あなたはどの状況であれば、政権与党に投票しますか。 選択肢の順は、左から状況1、状況2、状況3、状況4、状況5とします。

回答選択肢:状況1 (1)/状況2 (2)/状況3 (3)/状況4 (4)/状況5 (5)

操作確認 Q5.7
あなたには、複数の選択肢の中から1つの状況を選んでもらう作業を行っていただきました。 あなたに提示された選択肢の数は、いくつでしたか。

回答選択肢:1 (1)/2 (2)/3 (3)/4 (4)/5 (5)/おぼえていない (6)

J.3.4 政治質問

Q7.1
政治的立場を表すのに、よく「右派」「左派」という言葉が使われます。1が右派的、6が中間、11が左派的だとすると、あなたや主要政党はどのあたりに位置付けられるとお考えでしょうか。

回答尺度:1(右派的)/2/3/4/5/6(中間)/7/8/9/10/11(左派的)/わからない/こたえたくない。

評価対象:あなた自身(Q25.1_1)、自由民主党(Q25.1_2)、立憲民主党(Q25.1_3)、日本維新の会(Q25.1_4)、公明党(Q25.1_10)、国民民主党(Q25.1_5)、れいわ新選組(Q25.1_6)、参政党(Q25.1_7)、共産党(Q25.1_8)、中道改革連合(Q25.1_9)、「!この項目は必ず『3』を選んでください!」(Q25.1_11)

Q7.2
選挙でどこに投票するかは別にして、国の政治で、あなたはどの政党あるいは政治団体を支持していますか。

  • 自由民主党 (1)
  • 中道改革連合 (2)
  • 立憲民主党 (18)
  • 公明党 (19)
  • 日本維新の会 (3)
  • 国民民主党 (4)
  • れいわ新選組 (5)
  • 共産党 (6)
  • 参政党 (7)
  • 日本保守党 (8)
  • 社民党 (9)
  • チームみらい (10)
  • その他の政党・政治団体(具体的に) (12) __________________________________________________
  • そのような政党はない (13)
  • わからない (14)
  • こたえたくない (15)

Q7.3
あなたが普段、政治に関する情報を見たり、聞いたりするために使う媒体は、どれでしょうか。あるだけ選んでください。

  • 新聞(朝刊) (1)
  • スポーツ新聞 (2)
  • 週刊誌 (3)
  • 政見放送 (4)
  • テレビのニュース (5)
  • ワイドショーや討論番組 (6)
  • マニフェスト・選挙公報 (7)
  • インターネット上のニュース記事(SNS含む) (8)
  • 政党や候補者のホームページなど(SNS含む) (9)
  • その他(具体的に) (10) __________________________________________________
  • ⊗見聞きしていない (11)
  • ⊗わからない (12)
  • ⊗こたえたくない (13)

J.3.5 調査趣旨の再説明と最終送信同意

Q8.1 デブリーフィング・最終意思確認(クリックして全文を表示)

こちらが調査の最後の画面である「調査趣旨の再説明」と「回答結果の送信に関する最終意思確認」のページになります。まずはここまで調査にご協力くださいましたことに、心から御礼申し上げる次第です。 ・本調査では、政治、経済に関する意識などをお伺いさしました。調査にご協力いただきましたことに、深く感謝申し上げます。 ・本調査に関してご不明な点等がございましたら、下記メールアドレスまでお問い合わせください。 e-mail: 【本調査・本実験に関するご説明:表があって、表に政党名や経済状況が表示されるものをなぜご覧いただいたのか?】 ・本調査では、表があって、その表に政党名や経済状況がたくさん示されたものをご覧になっていただきました。皆様には、 2つの状況の中から1つを選ぶ 3つの状況の中から1つを選ぶ 4つの状況の中から1つを選ぶ 5つの状況の中から1つを選ぶ という作業のうちの1つを、繰り返して5回行っていただきました。 ・また具体的な政党名とともに提示された経済状況は、現実とは異なる仮想の情報になります。また、具体的な政党が「与党/連立与党である」ということも想起してもらいました。ご覧になっていただいた政党の中には、実際には与党/連立与党ではない政党が複数含まれていました。この点も、研究の設計上必要となるものではありましたが、現実社会における事実とは異なるものです。この点に留意していただき、ご納得いただけた場合には、「回答結果を送信する」ボタンを押してください。 ・表の中にたくさんの情報が組み込まれているうえに、さらに質問を重ねたことで、皆さまの中には、回答がわずらわしく、何かを考えたり選んだりする作業を面倒だと感じ、回答を不快に思われた方がおられたかもしれません。そのような中、最後までご回答くださったことに、何より感謝申し上げます。 ・本調査は、政党名と経済状況が示された時に、私たちはどちらにもとづいて政党を選ぼうとするのかを明らかにするためのものでした。 ・そのために皆様には、政治集団、イデオロギー、党派性に関わることをお答えいただいたり、それらに対する皆様のお考え・ご意向をお伺いすることになりました。 このような背景をもつ調査ではありますが、回答にご協力くださった皆様の中には、不快感を抱かれた方がおられるかもしれません。そのような方は、以下の「本調査の趣旨に同意せず、回答結果を送信しない」ボタンを押して、本調査を終了してください。その場合に、本調査への回答を分析に使用させていただくことは致しません。その場合であっても、ポイントは付与されますので、どうかご安心ください。 また本調査には、研究者が独自に収集・作成したデータが含まれます。それらを無断で転記、転写、スクリーンショットなどによって、さまざまな媒体に配布することは、著作権に抵触する恐れがあります。調査画面の無断での転記、転写、スクリーンショット等により公開・共有するといった行為はお控えいただきますようよろしくお願い致します。

回答選択肢

  • 本調査の主旨に同意し、回答結果を送信する。 (1)
  • 本調査の主旨に同意しないので、回答結果を送信しない。 (2)

J.4 調査票と再現コードの対応

C.4の標本減少・スクリーニング表では、上記の質問文のうち分析標本の判定に直接用いる項目を短く要約して併記している。実験1では初回同意、5つの選択課題、最終送信同意を主な判定項目とする。実験2・3ではこれらに加え、各選択肢数条件の操作確認(Q3.7/Q4.7/Q5.7/Q6.7)と、イデオロギー行列の指示項目Q25.1_11を用いる。したがって、C.4の「質問文(調査票・要約)」列と、本節の完全な質問文を対応させて確認できる。

LS0tCnRpdGxlOiAi44Kq44Oz44Op44Kk44Oz5LiK44Gn44Gu6KOc6YG644Go5YaN54++44Kz44O844OJIgpzdWJ0aXRsZTogIuWkmuWFmuWItuOBr+e1jOa4iOaKleelqOOCkuW8seOCgeOCi+OBruOBi++8n++8muaUv+WFmuOBruaJi+OBjOOBi+OCiuOBqOe1jOa4iOOBruaJi+OBjOOBi+OCiuOCkuOCgeOBkOOCi+OCs+ODs+OCuOODp+OCpOODs+ODiOWun+mokyIKYXV0aG9yOiAiSGFuYWtvIE9obXVyYSIKZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJVktJW0tJWQnKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiBrYXRlCiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKcGFyYW1zOgogIHN0dWR5MV9kYXRhOiAicGFydHludW0uY3N2IgogIHN0dWR5Ml9kYXRhOiAiY29uam9pbnRfc3R1ZHkyLmNzdiIKICBzdHVkeTNfZGF0YTogImNvbmpvaW50X1MzLmNzdiIKICBvdXRwdXRfcm9vdDogImNvbmpvaW50X3JlcGxpY2F0aW9uX3Jlc3VsdHMiCiAgcnVuX2FuYWx5c2lzOiB0cnVlCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9COiAyMDAwCiAgc3VwcG9ydF9ib290c3RyYXBfQjogNTAwCiAgcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcDogZmFsc2UKICByZXJ1bl9zdXBwb3J0X2Jvb3RzdHJhcDogZmFsc2UKICBtaW5fc3VwcG9ydF90b3RhbF9uOiAxNTAKICBtaW5fc3VwcG9ydF9jZWxsX246IDQwCi0tLQoKPHN0eWxlPgpib2R5IHsKICBmb250LWZhbWlseTogIkhlbHZldGljYSBOZXVlIiwgQXJpYWwsICJZdSBHb3RoaWMiLCAiSGlyYWdpbm8gS2FrdSBHb3RoaWMgUHJvTiIsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxNnB4OwogIGxpbmUtaGVpZ2h0OiAxLjc1Owp9Ci5tYWluLWNvbnRhaW5lciB7IG1heC13aWR0aDogMTEyMHB4OyB9CmgxLCBoMiwgaDMsIGg0IHsgZm9udC13ZWlnaHQ6IDcwMDsgfQpoMiB7CiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNkOGRlZTQ7CiAgcGFkZGluZy1ib3R0b206IDAuMjVlbTsKfQpwcmUsIGNvZGUgeyBmb250LXNpemU6IDAuOTBlbTsgfQp0YWJsZSB7IGZvbnQtc2l6ZTogMC45MGVtOyB9Ci50YWJsZS1zY3JvbGwgeyBvdmVyZmxvdy14OiBhdXRvOyBtYXJnaW4tYm90dG9tOiAxLjVlbTsgfQppbWcgeyBtYXgtd2lkdGg6IDEwMCU7IGhlaWdodDogYXV0bzsgZGlzcGxheTogaW5saW5lLWJsb2NrOyB9Ci5jb2RlLWNvbnRyb2xzIHsgbWFyZ2luOiAwLjVlbSAwIDEuMmVtIDA7IH0KLmNvZGUtY29udHJvbHMgYnV0dG9uIHsgbWFyZ2luLXJpZ2h0OiAwLjVlbTsgcGFkZGluZzogMC4zNWVtIDAuOGVtOyB9Cjwvc3R5bGU+Cgo8c2NyaXB0Pgpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCJET01Db250ZW50TG9hZGVkIiwgZnVuY3Rpb24oKSB7CiAgY29uc3Qgc2hvd0J1dHRvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJzaG93LWFsbC1jb2RlIik7CiAgY29uc3QgaGlkZUJ1dHRvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJoaWRlLWFsbC1jb2RlIik7CiAgaWYgKHNob3dCdXR0b24pIHsKICAgIHNob3dCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLCBmdW5jdGlvbigpIHsKICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiZGl2LnNvdXJjZUNvZGUiKS5mb3JFYWNoKGZ1bmN0aW9uKGVsKSB7CiAgICAgICAgZWwuc3R5bGUuZGlzcGxheSA9ICJibG9jayI7CiAgICAgIH0pOwogICAgfSk7CiAgfQogIGlmIChoaWRlQnV0dG9uKSB7CiAgICBoaWRlQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIiwgZnVuY3Rpb24oKSB7CiAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoImRpdi5zb3VyY2VDb2RlIikuZm9yRWFjaChmdW5jdGlvbihlbCkgewogICAgICAgIGVsLnN0eWxlLmRpc3BsYXkgPSAibm9uZSI7CiAgICAgIH0pOwogICAgfSk7CiAgfQp9KTsKPC9zY3JpcHQ+Cgo8ZGl2IGNsYXNzPSJjb2RlLWNvbnRyb2xzIj4KPGJ1dHRvbiBpZD0ic2hvdy1hbGwtY29kZSIgdHlwZT0iYnV0dG9uIj5TaG93IEFsbCBDb2RlPC9idXR0b24+CjxidXR0b24gaWQ9ImhpZGUtYWxsLWNvZGUiIHR5cGU9ImJ1dHRvbiI+SGlkZSBBbGwgQ29kZTwvYnV0dG9uPgo8L2Rpdj4KCgojIFJFQURNRe+8muWGjeePvuaWueazleOBqOODleOCoeOCpOODq+ani+aIkAoK44GT44Gu44Kq44Oz44Op44Kk44Oz6KOc6YG644Go5YaN54++44Kz44O844OJ44Gv44CB6KuW5paH44CM5aSa5YWa5Yi244Gv57WM5riI5oqV56Wo44KS5byx44KB44KL44Gu44GL77yf77ya5pS/5YWa44Gu5omL44GM44GL44KK44Go57WM5riI44Gu5omL44GM44GL44KK44KS44KB44GQ44KL44Kz44Oz44K444On44Kk44Oz44OI5a6f6aiT44CN44Gn5aCx5ZGK44GZ44KLM+OBpOOBruWun+mok+OBruWIhuaekOOBq+OBpOOBhOOBpuOAgeacrOaWh+Wbs+OAgeijnOmBuuWbs+ihqOOAgemgkeWBpeaAp+WIhuaekOOAgeeEoeS9nOeCuuWMluODu+ODkOODqeODs+OCueiouuaWreOAgeOBiuOCiOOBs+aUr+aMgeaUv+WFmuWIpeWIhuaekOe1kOaenOOCkuOBvuOBqOOCgeOAgeOBleOCieOBq+OBneOCjOOCieOCkuWGjeePvuOBmeOCi+OBn+OCgeOBruOCs+ODvOODieOCkuOBvuOBqOOCgeOBn+OCguOBruOBp+OBguOCi+OAguS7peS4i+OBruaJi+mghuOBp+OAgeWFpeWKm+ODh+ODvOOCv+OBruiqrei+vOOBv+OBi+OCieacgOe1gueahOOBquWbs+ihqOODu+iouuaWree1kOaenOOBruaVtOeQhuOBvuOBp+OCkuS4gOaLrOOBl+OBpuWun+ihjOOBp+OBjeOCi+OAggoKIyMgMS4g5YaN54++44Gr5b+F6KaB44Gq44OV44Kh44Kk44Or562JCgrmrKHjga4044OV44Kh44Kk44Or44KS5ZCM44GY5L2c5qWt44OH44Kj44Os44Kv44OI44Oq44Gr572u44GE44Gm44KC44KJ44GG44CC44OH44O844K/44OV44Kh44Kk44Or5ZCN44KE5L+d5a2Y5aC05omA44KS5aSJ5pu044GZ44KL5aC05ZCI44Gv44CB44GT44GuUm1k5YaS6aCt44GuIGBwYXJhbXNgIOOCkuWkieabtOOBl+OBpuOCguOCieOBiOOBsOOCiOOBhOOAggoKfCDjg5XjgqHjgqTjg6sgfCDlhoXlrrkgfAp8LS0tfC0tLXwKfCBgcGFydHludW0uY3N2YCB8IOWun+mokzHjga7lhaXlipvjg4fjg7zjgr8gfAp8IGBjb25qb2ludF9zdHVkeTIuY3N2YCB8IOWun+mokzLjga7lhaXlipvjg4fjg7zjgr8gfAp8IGBjb25qb2ludF9TMy5jc3ZgIHwg5a6f6aiTM+OBruWFpeWKm+ODh+ODvOOCvyB8CgojIyAyLiDlv4XopoHjgapS44OR44OD44Kx44O844K4CgrliIbmnpDjgrPjg7zjg4njgafkvb/nlKjjgZnjgovkuLvopoHjg5Hjg4PjgrHjg7zjgrjjga/ku6XkuIvjga7jgajjgYrjgorjgafjgYLjgovjgIIKCmBgYHtyIHJlYWRtZS1pbnN0YWxsLXBhY2thZ2VzLCBldmFsPUZBTFNFfQppbnN0YWxsLnBhY2thZ2VzKGMoCiAgImRwbHlyIiwgInRpZHlyIiwgInN0cmluZ3IiLCAicHVycnIiLCAicmVhZHIiLAogICJmaXhlc3QiLCAidGliYmxlIiwgImZvcmNhdHMiLCAiZ2dwbG90MiIsICJzY2FsZXMiLAogICJzdXJ2aXZhbCIsICJnZ3RleHQiLCAicGF0Y2h3b3JrIiwgInJtYXJrZG93biIsICJrbml0ciIKKSkKYGBgCgojIyAzLiDlkITnqK7jga7jg4fjg5Xjgqnjg6vjg4joqK3lrpoKCuWGkumgreOBriBgcGFyYW1zYCDjgafjgIHlhaXlipvjg5XjgqHjgqTjg6vjgIHlh7rlipvlhYjjgIHjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5flm57mlbDjgpLlpInmm7Tlj6/og73jgafjgYLjgovjgILnj77lnKjjga7kuLvopoHjgarjg4fjg5Xjgqnjg6vjg4jlgKTjga/mrKHjga7jgajjgYrjgorjgafjgYLjgovjgIIKCnwg44OR44Op44Oh44O844K/IHwg44OH44OV44Kp44Or44OIIHwg5oSP5ZGzIHwKfC0tLXwtLS06fC0tLXwKfCBgb3V0cHV0X3Jvb3RgIHwgYGNvbmpvaW50X3JlcGxpY2F0aW9uX3Jlc3VsdHNgIHwg5YWo5Ye65Yqb44KS5L+d5a2Y44GZ44KL44Or44O844OI44OH44Kj44Os44Kv44OI44OqIHwKfCBgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CYCB8IDIwMDAgfCDkuLvopoHjgarph43opoHluqbjg7vnm7jlr77mr5Tph43jga7jg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5flj43lvqnmlbAgfAp8IGBzdXBwb3J0X2Jvb3RzdHJhcF9CYCB8IDUwMCB8IOaUr+aMgeaUv+WFmuWIpeWIhuaekOOBruODluODvOODiOOCueODiOODqeODg+ODl+WPjeW+qeaVsCB8CgoKCiMjIDQuIOWHuuWKm+ODleOCoeOCpOODqwoK5YiG5p6Q57WQ5p6c44Gv44OH44OV44Kp44Or44OI44GnIGBjb25qb2ludF9yZXBsaWNhdGlvbl9yZXN1bHRzL2Ag5YaF44Gr5L+d5a2Y44GV44KM44KL6Kit5a6a44Gr44Gq44Gj44Gm44GE44KL44CC5Li744Gq5qeL5oiQ44Gv5Lul5LiL44Gu6YCa44KK44CCCgotIGBtYWluX3RleHQvYO+8muacrOaWh+eUqOOBruWbs+OBqOihqAotIGBzdXBwbGVtZW50L2DvvJrlrp/pqJPliKXjgYrjgojjgbPlrp/pqJPmqKrmlq3jga7oo5zpgbrlm7PooajvvIhDU1bjgIFMYVRlWOOAgeWbs++8iQotIGBkaWFnbm9zdGljcy9g77ya5qiZ5pys44K544Kv44Oq44O844OL44Oz44Kw44CB5Ymy5LuY44OQ44Op44Oz44K544CB44OX44Ot44OV44Kj44O844Or54Sh5L2c54K65YyW44Gu6Ki65patCi0gYG1vZGVsX29iamVjdHMvYO+8muWGjeWIqeeUqOWPr+iDveOBquODouODh+ODq+ODu+WIhuaekOOCquODluOCuOOCp+OCr+ODiAotIGBsb2dzL2DvvJpgc2Vzc2lvbkluZm9gIOOBquOBqeOBruWGjeePvuaAp+aDheWgsQoK5ZCE5YiG5p6Q44Gu6YCU5Lit44Gu57WM6YGO5L2c5oiQ44GV44KM44KL5ZCE56iu44Kq44OW44K444Kn44Kv44OI44Gq44Gp44GvIGBfd29ya2luZy9gIOOBq+S/neWtmOOBleOCjOOAgeacgOe1guautemajuOBp+S4iuiomOOBruODh+OCo+ODrOOCr+ODiOODquOBq+aVtOeQhuOBmeOCi+OCiOOBhuOBq+ioreWumuOBl+OBn+OAglLjgYrjgojjgbPlkITjg5Hjg4PjgrHjg7zjgrjjga7lrp/ooYznkrDlooPjga/jgIHliIbmnpDlrozkuoblvozjgasgYHNlc3Npb25JbmZvYCDjgajjgZfjgabkv53lrZjjgZXjgozjgovoqK3lrprjgajjgarjgaPjgabjgYTjgovjgIIKCiMjIDUuIOOBk+OBruOCquODs+ODqeOCpOODs+ijnOmBuuOBqOWGjeePvuOCs+ODvOODieOBruiqreOBv+aWuQoKKipB56+AKirjga/mnKzmlofjg7voo5zpgbrjga7lm7PooajjgpLnlJ/miJDjgZnjgovlrp/ooYzjgrPjg7zjg4njgIEqKkLnr4AqKuS7pemZjeOBr+WIhuaekOaomeacrOOAgeaOqOWumumHj+OAgeeEoeS9nOeCuuWMluODu+ODkOODqeODs+OCueiouuaWreOAgeOBiuOCiOOBs+WQhOijnOi2s+e1kOaenOOCkuOAgeOCs+ODvOODieOBqOWvvuW/nOOBleOBm+OBpueiuuiqjeOBmeOCi+OBn+OCgeOBruOCu+OCr+OCt+ODp+ODs+OBp+OBguOCi+OAgioqSuevgCoq44Gr44Gv44CB5a6f6aiTMeOAnDPjgaflrp/pmpvjgavnlKjjgYTjgZ/oqr/mn7vnpajjga7os6rllY/mlofjg7vlm57nrZTlvaLlvI/jgpLjgIHph43opIfjgZnjgovjgrPjg7Pjgrjjg6fjgqTjg7Pjg4joqrLpoYzjgpLmlbTnkIbjgZfjgZ/jgYbjgYjjgaflho3mjrLjgZnjgovjgILnlLvpnaLkuIrpg6jjga4gKipTaG93IEFsbCBDb2RlIC8gSGlkZSBBbGwgQ29kZSoqIOOBvuOBn+OBr+WPs+S4iuOBriAqKkNvZGUqKiDjg6Hjg4vjg6Xjg7zjgYvjgonjgIHjgrPjg7zjg4nlhajkvZPjga7ooajnpLrjg7vpnZ7ooajnpLrjgpLliIfjgormm7/jgYjjgonjgozjgovjgIIKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsCiAgbWVzc2FnZSA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBjb21tZW50ID0gIiM+IiwKICBvdXQud2lkdGggPSAiOTYlIgopCgpvcHRpb25zKAogIGNvbmpvaW50LnN0dWR5MV9kYXRhID0gcGFyYW1zJHN0dWR5MV9kYXRhLAogIGNvbmpvaW50LnN0dWR5Ml9kYXRhID0gcGFyYW1zJHN0dWR5Ml9kYXRhLAogIGNvbmpvaW50LnN0dWR5M19kYXRhID0gcGFyYW1zJHN0dWR5M19kYXRhLAogIGNvbmpvaW50Lm91dHB1dF9yb290ID0gcGFyYW1zJG91dHB1dF9yb290LAogIGNvbmpvaW50LnJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiA9IGFzLmludGVnZXIocGFyYW1zJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiksCiAgY29uam9pbnQuc3VwcG9ydF9ib290c3RyYXBfQiA9IGFzLmludGVnZXIocGFyYW1zJHN1cHBvcnRfYm9vdHN0cmFwX0IpLAogIGNvbmpvaW50LnJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAgPSBpc1RSVUUocGFyYW1zJHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXApLAogIGNvbmpvaW50LnJlcnVuX3N1cHBvcnRfYm9vdHN0cmFwID0gaXNUUlVFKHBhcmFtcyRyZXJ1bl9zdXBwb3J0X2Jvb3RzdHJhcCksCiAgY29uam9pbnQubWluX3N1cHBvcnRfdG90YWxfbiA9IGFzLmludGVnZXIocGFyYW1zJG1pbl9zdXBwb3J0X3RvdGFsX24pLAogIGNvbmpvaW50Lm1pbl9zdXBwb3J0X2NlbGxfbiA9IGFzLmludGVnZXIocGFyYW1zJG1pbl9zdXBwb3J0X2NlbGxfbikKKQoKc3VwcF9yb290IDwtIGZpbGUucGF0aChwYXJhbXMkb3V0cHV0X3Jvb3QsICJzdXBwbGVtZW50IikKZGlhZ19yb290IDwtIGZpbGUucGF0aChwYXJhbXMkb3V0cHV0X3Jvb3QsICJkaWFnbm9zdGljcyIpCmNyb3NzX3Jvb3QgPC0gZmlsZS5wYXRoKHN1cHBfcm9vdCwgImNyb3NzX3N0dWR5IikKCgpzdHVkeV9jc3YgPC0gZnVuY3Rpb24oc3R1ZHlfaWQsIGZpbGUpIHsKICBmaWxlLnBhdGgoc3VwcF9yb290LCBzdHVkeV9pZCwgInRhYmxlc19jc3YiLCBmaWxlKQp9CnN0dWR5X2ZpZyA8LSBmdW5jdGlvbihzdHVkeV9pZCwgZmlsZSkgewogIGZpbGUucGF0aChzdXBwX3Jvb3QsIHN0dWR5X2lkLCAiZmlndXJlcyIsIGZpbGUpCn0KZGlhZ19maWcgPC0gZnVuY3Rpb24oc3R1ZHlfaWQsIHR5cGUsIGZpbGUpIHsKICBmaWxlLnBhdGgoZGlhZ19yb290LCBzdHVkeV9pZCwgdHlwZSwgZmlsZSkKfQpjcm9zc19jc3YgPC0gZnVuY3Rpb24oZmlsZSkgewogIGZpbGUucGF0aChjcm9zc19yb290LCAidGFibGVzX2NzdiIsIGZpbGUpCn0KY3Jvc3NfZmlnIDwtIGZ1bmN0aW9uKGZpbGUpIHsKICBmaWxlLnBhdGgoY3Jvc3Nfcm9vdCwgImZpZ3VyZXMiLCBmaWxlKQp9CmBgYAoKCiMgQS4g5ZCE5Zuz6KGo44Gu5YaN54++44Kz44O844OJCgojIyBBLjEg5YWx6YCa44Kz44O844OJCgpgYGB7ciBhMS1jb21tb24tY29kZSwgZXZhbD1wYXJhbXMkcnVuX2FuYWx5c2lzLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQojIOWFsemAmuOCs+ODvOODiQpvcHRpb25zKHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCnVuaWZpZWRfb3V0cHV0X3Jvb3QgPC0gZ2V0T3B0aW9uKAogICJjb25qb2ludC5vdXRwdXRfcm9vdCIsCiAgImNvbmpvaW50X3JlcGxpY2F0aW9uX3Jlc3VsdHMiCikKCmRpci5jcmVhdGUoCiAgdW5pZmllZF9vdXRwdXRfcm9vdCwKICBzaG93V2FybmluZ3MgPSBGQUxTRSwKICByZWN1cnNpdmUgPSBUUlVFCikKCnVuaWZpZWRfY29uZmlnIDwtIGxpc3QoCiAgb3V0cHV0X3Jvb3QgPSB1bmlmaWVkX291dHB1dF9yb290LAoKICBjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiA9ICJ2NF9zY3JlZW5pbmdfYXV0b2RldGVjdCIsCgogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiA9IGFzLmludGVnZXIoCiAgICBnZXRPcHRpb24oImNvbmpvaW50LnJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiIsIDIwMDBMKQogICksCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkID0gYXMuaW50ZWdlcigKICAgIGdldE9wdGlvbigiY29uam9pbnQucmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkIiwgMjAyNjA3MzBMKQogICksCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeSA9IGFzLmludGVnZXIoCiAgICBnZXRPcHRpb24oImNvbmpvaW50LnJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkiLCAxMDBMKQogICksCiAgcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA9IGlzVFJVRSgKICAgIGdldE9wdGlvbigiY29uam9pbnQucmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCIsIEZBTFNFKQogICksCgogIG1pbl9zdXBwb3J0X3RvdGFsX24gPSBhcy5pbnRlZ2VyKAogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5taW5fc3VwcG9ydF90b3RhbF9uIiwgMTUwTCkKICApLAogIG1pbl9zdXBwb3J0X2NlbGxfbiA9IGFzLmludGVnZXIoCiAgICBnZXRPcHRpb24oImNvbmpvaW50Lm1pbl9zdXBwb3J0X2NlbGxfbiIsIDQwTCkKICApLAogIHN1cHBvcnRfYm9vdHN0cmFwX0IgPSBhcy5pbnRlZ2VyKAogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5zdXBwb3J0X2Jvb3RzdHJhcF9CIiwgNTAwTCkKICApLAogIHN1cHBvcnRfYm9vdHN0cmFwX3NlZWQgPSBhcy5pbnRlZ2VyKAogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5zdXBwb3J0X2Jvb3RzdHJhcF9zZWVkIiwgMjAyNjA4MDZMKQogICksCiAgcmVydW5fc3VwcG9ydF9ib290c3RyYXAgPSBpc1RSVUUoCiAgICBnZXRPcHRpb24oImNvbmpvaW50LnJlcnVuX3N1cHBvcnRfYm9vdHN0cmFwIiwgRkFMU0UpCiAgKSwKCiAgc3R1ZHkxID0gbGlzdCgKICAgIGRhdGFfZmlsZSA9IGdldE9wdGlvbigiY29uam9pbnQuc3R1ZHkxX2RhdGEiLCAicGFydHludW0uY3N2IiksCiAgICBvdXRwdXRfZGlyID0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X3Jvb3QsICJfd29ya2luZyIsICJzdHVkeTEiKQogICksCiAgc3R1ZHkyID0gbGlzdCgKICAgIGRhdGFfZmlsZSA9IGdldE9wdGlvbigiY29uam9pbnQuc3R1ZHkyX2RhdGEiLCAiY29uam9pbnRfc3R1ZHkyLmNzdiIpLAogICAgb3V0cHV0X2RpciA9IGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9yb290LCAiX3dvcmtpbmciLCAic3R1ZHkyIikKICApLAogIHN0dWR5MyA9IGxpc3QoCiAgICBkYXRhX2ZpbGUgPSBnZXRPcHRpb24oImNvbmpvaW50LnN0dWR5M19kYXRhIiwgImNvbmpvaW50X1MzLmNzdiIpLAogICAgb3V0cHV0X2RpciA9IGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9yb290LCAiX3dvcmtpbmciLCAic3R1ZHkzIikKICApCikKCmNhdCgKICAiVW5pZmllZCBjb25qb2ludCByZXBsaWNhdGlvbiBwaXBlbGluZVxuIiwKICAiT3V0cHV0IHJvb3Q6ICIsIHVuaWZpZWRfY29uZmlnJG91dHB1dF9yb290LCAiXG4iLAogICJTdHVkeSAxIGRhdGE6ICIsIHVuaWZpZWRfY29uZmlnJHN0dWR5MSRkYXRhX2ZpbGUsICJcbiIsCiAgIlN0dWR5IDIgZGF0YTogIiwgdW5pZmllZF9jb25maWckc3R1ZHkyJGRhdGFfZmlsZSwgIlxuIiwKICAiU3R1ZHkgMyBkYXRhOiAiLCB1bmlmaWVkX2NvbmZpZyRzdHVkeTMkZGF0YV9maWxlLCAiXG4iLAogIHNlcCA9ICIiCikKCgpkZXRlY3RfZmluYWxfY29uc2VudF9jb2x1bW4gPC0gZnVuY3Rpb24oCiAgcmF3LAogIHByZWZlcnJlZF9jYW5kaWRhdGVzID0gYygiUTguMSIsICJROS4xIiwgIlExMC4xIiksCiAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkiCikgewogIGlmICghaXMuZGF0YS5mcmFtZShyYXcpIHx8IG5jb2wocmF3KSA9PSAwTCkgewogICAgc3RvcCgiQ2hlY2sgZGF0YSIpCiAgfQoKICBwcmV2aWV3X24gPC0gbWluKDEyTCwgbnJvdyhyYXcpKQoKICBub3JtYWxpemVfcHJldmlldyA8LSBmdW5jdGlvbih4KSB7CiAgICB4IDwtIGFzLmNoYXJhY3Rlcih4KQogICAgeFtpcy5uYSh4KV0gPC0gIiIKICAgIHggPC0gZ3N1Yigi44CAIiwgIiAiLCB4LCBmaXhlZCA9IFRSVUUpCiAgICB4IDwtIGdzdWIoIltbOnNwYWNlOl1dKyIsICIgIiwgeCkKICAgIHRyaW13cyh4KQogIH0KCiAgc2NvcmVfb25lIDwtIGZ1bmN0aW9uKGNvbHVtbl9uYW1lKSB7CiAgICBwcmV2aWV3IDwtIHBhc3RlKAogICAgICBub3JtYWxpemVfcHJldmlldyh1dGlsczo6aGVhZChyYXdbW2NvbHVtbl9uYW1lXV0sIHByZXZpZXdfbikpLAogICAgICBjb2xsYXBzZSA9ICIgIgogICAgKQoKICAgIHNjb3JlIDwtIDBMCgogICAgaWYgKGdyZXBsKCLmnIDntYLmhI/mgJ3norroqo0iLCBwcmV2aWV3LCBmaXhlZCA9IFRSVUUpKSB7CiAgICAgIHNjb3JlIDwtIHNjb3JlICsgOEwKICAgIH0KICAgIGlmIChncmVwbCgi44GT44Gh44KJ44GM6Kq/5p+744Gu5pyA5b6M44Gu55S76Z2iIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSB8fAogICAgICAgIGdyZXBsKCLoqr/mn7vjga7mnIDlvozjga7nlLvpnaIiLCBwcmV2aWV3LCBmaXhlZCA9IFRSVUUpKSB7CiAgICAgIHNjb3JlIDwtIHNjb3JlICsgNkwKICAgIH0KICAgIGlmIChncmVwbCgi5Zue562U57WQ5p6c44KS6YCB5L+h44GZ44KLIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSkgewogICAgICBzY29yZSA8LSBzY29yZSArIDhMCiAgICB9CiAgICBpZiAoZ3JlcGwoIuWbnuetlOe1kOaenOOCkumAgeS/oeOBl+OBquOBhCIsIHByZXZpZXcsIGZpeGVkID0gVFJVRSkgfHwKICAgICAgICBncmVwbCgi5Zue562U44KS6YCB5L+h44GX44Gq44GEIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSkgewogICAgICBzY29yZSA8LSBzY29yZSArIDVMCiAgICB9CiAgICBpZiAoZ3JlcGwoIuacrOiqv+afu+OBruS4u+aXqOOBq+WQjOaEjyIsIHByZXZpZXcsIGZpeGVkID0gVFJVRSkgfHwKICAgICAgICBncmVwbCgi5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSPIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSkgewogICAgICBzY29yZSA8LSBzY29yZSArIDNMCiAgICB9CiAgICBpZiAoY29sdW1uX25hbWUgJWluJSBwcmVmZXJyZWRfY2FuZGlkYXRlcykgewogICAgICBzY29yZSA8LSBzY29yZSArIDFMCiAgICB9CgogICAgc2NvcmUKICB9CgogIGNhbmRpZGF0ZV90YWJsZSA8LSBkYXRhLmZyYW1lKAogICAgY29sdW1uID0gbmFtZXMocmF3KSwKICAgIHNjb3JlID0gdmFwcGx5KG5hbWVzKHJhdyksIHNjb3JlX29uZSwgaW50ZWdlcigxKSksCiAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UKICApCgogIGNhbmRpZGF0ZV90YWJsZSA8LSBjYW5kaWRhdGVfdGFibGVbY2FuZGlkYXRlX3RhYmxlJHNjb3JlID4gMEwsICwgZHJvcCA9IEZBTFNFXQoKICBpZiAobnJvdyhjYW5kaWRhdGVfdGFibGUpID09IDBMKSB7CiAgICBleGlzdGluZ19wcmVmZXJyZWQgPC0gcHJlZmVycmVkX2NhbmRpZGF0ZXNbCiAgICAgIHByZWZlcnJlZF9jYW5kaWRhdGVzICVpbiUgbmFtZXMocmF3KQogICAgXQoKICAgIGlmIChsZW5ndGgoZXhpc3RpbmdfcHJlZmVycmVkKSA9PSAxTCkgewogICAgICBtZXNzYWdlKCJGaW5hbCBjb25zZW50OiAiLCBleGlzdGluZ19wcmVmZXJyZWRbWzFdXSkKICAgICAgcmV0dXJuKGV4aXN0aW5nX3ByZWZlcnJlZFtbMV1dKQogICAgfQoKICAgIGxpa2VseV9xdWVzdGlvbl9jb2x1bW5zIDwtIG5hbWVzKHJhdylbCiAgICAgIGdyZXBsKCJeUVswLTldKyhcXC5bMC05XSspPyhfWzAtOV0rKT8kIiwgbmFtZXMocmF3KSkKICAgIF0KCiAgICBzdG9wKCJDaGVjayBmaW5hbCBjb25zZW50IikKICB9CgogIG1heF9zY29yZSA8LSBtYXgoY2FuZGlkYXRlX3RhYmxlJHNjb3JlKQogIGJlc3QgPC0gY2FuZGlkYXRlX3RhYmxlJGNvbHVtbltjYW5kaWRhdGVfdGFibGUkc2NvcmUgPT0gbWF4X3Njb3JlXQoKICBpZiAobGVuZ3RoKGJlc3QpID4gMUwpIHsKICAgIHByZWZlcnJlZF9iZXN0IDwtIHByZWZlcnJlZF9jYW5kaWRhdGVzWwogICAgICBwcmVmZXJyZWRfY2FuZGlkYXRlcyAlaW4lIGJlc3QKICAgIF0KCiAgICBpZiAobGVuZ3RoKHByZWZlcnJlZF9iZXN0KSA+PSAxTCkgewogICAgICBiZXN0IDwtIHByZWZlcnJlZF9iZXN0W1sxXV0KICAgIH0gZWxzZSB7CiAgICAgIHN0b3AoIkNoZWNrIGZpbmFsIGNvbnNlbnQiKQogICAgfQogIH0KCiAgbWVzc2FnZSgiRmluYWwgY29uc2VudDogIiwgYmVzdFtbMV1dKQoKCiAgYmVzdFtbMV1dCn0KCnF1YWx0cmljc19wcmV2aWV3X3RleHQgPC0gZnVuY3Rpb24ocmF3LCBjb2x1bW5fbmFtZSwgcHJldmlld19uID0gMTJMKSB7CiAgaWYgKCFjb2x1bW5fbmFtZSAlaW4lIG5hbWVzKHJhdykpIHsKICAgIHJldHVybigiIikKICB9CgogIHggPC0gYXMuY2hhcmFjdGVyKHV0aWxzOjpoZWFkKHJhd1tbY29sdW1uX25hbWVdXSwgbWluKHByZXZpZXdfbiwgbnJvdyhyYXcpKSkpCiAgeFtpcy5uYSh4KV0gPC0gIiIKICB4IDwtIGdzdWIoIuOAgCIsICIgIiwgeCwgZml4ZWQgPSBUUlVFKQogIHggPC0gZ3N1YigiW1s6c3BhY2U6XV0rIiwgIiAiLCB4KQogIHRyaW13cyhwYXN0ZSh4LCBjb2xsYXBzZSA9ICIgIikpCn0KCmZ1bGx3aWR0aF9kaWdpdCA8LSBmdW5jdGlvbihuKSB7CiAgc3Vic3RyKCLvvJDvvJHvvJLvvJPvvJTvvJXvvJbvvJfvvJjvvJkiLCBuICsgMUwsIG4gKyAxTCkKfQoKcXVlc3Rpb25fb3JkZXJfa2V5IDwtIGZ1bmN0aW9uKHgpIHsKICBtIDwtIHJlZ2V4ZWMoIl5RKFswLTldKylcXC4oWzAtOV0rKSIsIHgpCiAgcGFydHMgPC0gcmVnbWF0Y2hlcyh4LCBtKQoKICB2YXBwbHkoCiAgICBwYXJ0cywKICAgIGZ1bmN0aW9uKHopIHsKICAgICAgaWYgKGxlbmd0aCh6KSA8IDNMKSB7CiAgICAgICAgcmV0dXJuKEluZikKICAgICAgfQogICAgICBhcy5udW1lcmljKHpbWzJdXSkgKiAxMDAwICsgYXMubnVtZXJpYyh6W1szXV0pCiAgICB9LAogICAgbnVtZXJpYygxKQogICkKfQoKZGV0ZWN0X2F0dGVudGlvbl9jaGVja19jb2x1bW4gPC0gZnVuY3Rpb24oCiAgcmF3LAogIHByZWZlcnJlZF9jYW5kaWRhdGVzID0gYygiUTI1LjFfMTEiLCAiUTI1LjFfMTAiKSwKICBzdHVkeV9sYWJlbCA9ICJTdHVkeSIKKSB7CiAgbWV0YWRhdGEgPC0gZGF0YS5mcmFtZSgKICAgIGNvbHVtbiA9IG5hbWVzKHJhdyksCiAgICB0ZXh0ID0gdmFwcGx5KG5hbWVzKHJhdyksIGZ1bmN0aW9uKHYpIHF1YWx0cmljc19wcmV2aWV3X3RleHQocmF3LCB2KSwgY2hhcmFjdGVyKDEpKSwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQogICkKCiAgc2NvcmUgPC0gaW50ZWdlcihucm93KG1ldGFkYXRhKSkKICBzY29yZSA8LSBzY29yZSArIGlmZWxzZShncmVwbCgi5b+F44GaIiwgbWV0YWRhdGEkdGV4dCwgZml4ZWQgPSBUUlVFKSwgOEwsIDBMKQogIHNjb3JlIDwtIHNjb3JlICsgaWZlbHNlKGdyZXBsKCLpgbjjgpMiLCBtZXRhZGF0YSR0ZXh0LCBmaXhlZCA9IFRSVUUpLCA1TCwgMEwpCiAgc2NvcmUgPC0gc2NvcmUgKyBpZmVsc2UoZ3JlcGwoIjN877yTIiwgbWV0YWRhdGEkdGV4dCksIDRMLCAwTCkKICBzY29yZSA8LSBzY29yZSArIGlmZWxzZShtZXRhZGF0YSRjb2x1bW4gJWluJSBwcmVmZXJyZWRfY2FuZGlkYXRlcywgMUwsIDBMKQogIG1ldGFkYXRhJHNjb3JlIDwtIHNjb3JlCgogIGNhbmRpZGF0ZXMgPC0gbWV0YWRhdGFbCiAgICBncmVwbCgi5b+F44GaIiwgbWV0YWRhdGEkdGV4dCwgZml4ZWQgPSBUUlVFKSAmCiAgICAgIGdyZXBsKCLpgbjjgpMiLCBtZXRhZGF0YSR0ZXh0LCBmaXhlZCA9IFRSVUUpICYKICAgICAgZ3JlcGwoIjN877yTIiwgbWV0YWRhdGEkdGV4dCksCiAgICAsCiAgICBkcm9wID0gRkFMU0UKICBdCgogIGlmIChucm93KGNhbmRpZGF0ZXMpID09IDBMKSB7CiAgICBzdG9wKCJDaGVjayBhdHRlbnRpb24gaXRlbSIpCiAgfQoKICBjYW5kaWRhdGVzIDwtIGNhbmRpZGF0ZXNbb3JkZXIoLWNhbmRpZGF0ZXMkc2NvcmUpLCAsIGRyb3AgPSBGQUxTRV0KICBiZXN0X3Njb3JlIDwtIGNhbmRpZGF0ZXMkc2NvcmVbWzFdXQogIGJlc3QgPC0gY2FuZGlkYXRlcyRjb2x1bW5bY2FuZGlkYXRlcyRzY29yZSA9PSBiZXN0X3Njb3JlXQoKICBpZiAobGVuZ3RoKGJlc3QpID4gMUwpIHsKICAgIHByZWZlcnJlZF9iZXN0IDwtIHByZWZlcnJlZF9jYW5kaWRhdGVzW3ByZWZlcnJlZF9jYW5kaWRhdGVzICVpbiUgYmVzdF0KICAgIGlmIChsZW5ndGgocHJlZmVycmVkX2Jlc3QpID09IDFMKSB7CiAgICAgIGJlc3QgPC0gcHJlZmVycmVkX2Jlc3QKICAgIH0gZWxzZSB7CiAgICAgIHN0b3AoIkNoZWNrIGF0dGVudGlvbiBpdGVtIikKICAgIH0KICB9CgogIG1lc3NhZ2UoIkF0dGVudGlvbiBpdGVtOiAiLCBiZXN0W1sxXV0pCiAgYmVzdFtbMV1dCn0KCnJlc3BvbnNlX2NvZGVfbnVtZXJpYyA8LSBmdW5jdGlvbih4KSB7CiAgeCA8LSBhcy5jaGFyYWN0ZXIoeCkKICB4W2lzLm5hKHgpXSA8LSAiIgogIHggPC0gZ3N1Yigi44CAIiwgIiAiLCB4LCBmaXhlZCA9IFRSVUUpCiAgeCA8LSB0cmltd3MoZ3N1YigiW1s6c3BhY2U6XV0rIiwgIiAiLCB4KSkKCiAgZXhhY3QgPC0gZ3JlcGwoIl5bMC05XSsoPzpcXC4wKyk/JCIsIHgsIHBlcmwgPSBUUlVFKQogIG91dCA8LSByZXAoTkFfcmVhbF8sIGxlbmd0aCh4KSkKICBvdXRbZXhhY3RdIDwtIHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyh4W2V4YWN0XSkpCgogIHRyYWlsaW5nIDwtIHJlZ2V4ZWMoIlxcKChbMC05XSspXFwpXFxzKiQiLCB4KQogIHRyYWlsaW5nX3BhcnRzIDwtIHJlZ21hdGNoZXMoeCwgdHJhaWxpbmcpCiAgdHJhaWxpbmdfY29kZSA8LSB2YXBwbHkoCiAgICB0cmFpbGluZ19wYXJ0cywKICAgIGZ1bmN0aW9uKHopIGlmIChsZW5ndGgoeikgPj0gMkwpIGFzLm51bWVyaWMoeltbMl1dKSBlbHNlIE5BX3JlYWxfLAogICAgbnVtZXJpYygxKQogICkKICBvdXRbaXMubmEob3V0KSAmICFpcy5uYSh0cmFpbGluZ19jb2RlKV0gPC0gdHJhaWxpbmdfY29kZVtpcy5uYShvdXQpICYgIWlzLm5hKHRyYWlsaW5nX2NvZGUpXQoKICBmaXJzdF9udW0gPC0gc3VwcHJlc3NXYXJuaW5ncyhyZWFkcjo6cGFyc2VfbnVtYmVyKHgpKQogIG91dFtpcy5uYShvdXQpXSA8LSBmaXJzdF9udW1baXMubmEob3V0KV0KICBvdXQKfQoKZGV0ZWN0X2F0dGVudGlvbl9jb3JyZWN0X2NvZGUgPC0gZnVuY3Rpb24oCiAgeCwKICBkaXNwbGF5ZWRfYW5zd2VyID0gM0wsCiAgcmVjb2RlZF9hbnN3ZXIgPSA2TCwKICBzdHVkeV9sYWJlbCA9ICJTdHVkeSIKKSB7CiAgY29kZSA8LSByZXNwb25zZV9jb2RlX251bWVyaWMoeCkKICB0YWIgPC0gc29ydCh0YWJsZShjb2RlLCB1c2VOQSA9ICJubyIpLCBkZWNyZWFzaW5nID0gVFJVRSkKCiAgbl9kaXNwbGF5IDwtIHN1bShjb2RlID09IGRpc3BsYXllZF9hbnN3ZXIsIG5hLnJtID0gVFJVRSkKICBuX3JlY29kZSA8LSBzdW0oY29kZSA9PSByZWNvZGVkX2Fuc3dlciwgbmEucm0gPSBUUlVFKQoKICBjaG9zZW4gPC0gaWYgKG5fcmVjb2RlID4gbl9kaXNwbGF5KSByZWNvZGVkX2Fuc3dlciBlbHNlIGRpc3BsYXllZF9hbnN3ZXIKICBuX25vbm1pc3NpbmcgPC0gc3VtKCFpcy5uYShjb2RlKSkKICBuX2Nob3NlbiA8LSBzdW0oY29kZSA9PSBjaG9zZW4sIG5hLnJtID0gVFJVRSkKCiAgY2F0KCJcbiIsIHN0dWR5X2xhYmVsLCAi77ya5oyH56S66aCF55uu44Gu5Zue562U44Kz44O844OJ5YiG5biDXG4iLCBzZXAgPSAiIikKICBwcmludCh1dGlsczo6aGVhZCh0YWIsIDE1TCkpCiAgY2F0KAogICAgIuaOoeeUqOOBmeOCi+ato+etlOOCs+ODvOODiTogIiwgY2hvc2VuLAogICAgIu+8iOihqOekuuS4iuOBruato+etlOOBrzPvvIlcbiIsCiAgICBzZXAgPSAiIgogICkKCiAgaWYgKG5fbm9ubWlzc2luZyA9PSAwTCB8fCBuX2Nob3NlbiAvIG5fbm9ubWlzc2luZyA8IDAuNTApIHsKICAgIHN0b3AoIkNoZWNrIGF0dGVudGlvbiBpdGVtIikKICB9CgogIGFzLmNoYXJhY3RlcihjaG9zZW4pCn0KCmRldGVjdF9jb25qb2ludF9jaG9pY2VfbWFwIDwtIGZ1bmN0aW9uKAogIHJhdywKICBwYXJ0eV9udW1iZXJzID0gMjo1LAogIHN0dWR5X2xhYmVsID0gIlN0dWR5IgopIHsKICBtZXRhZGF0YSA8LSBkYXRhLmZyYW1lKAogICAgY29sdW1uID0gbmFtZXMocmF3KSwKICAgIHRleHQgPSB2YXBwbHkobmFtZXMocmF3KSwgZnVuY3Rpb24odikgcXVhbHRyaWNzX3ByZXZpZXdfdGV4dChyYXcsIHYpLCBjaGFyYWN0ZXIoMSkpLAogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgKQoKICBtYXBzIDwtIGxhcHBseSgKICAgIHBhcnR5X251bWJlcnMsCiAgICBmdW5jdGlvbihuX3BhcnR5KSB7CiAgICAgIGRpZ2l0X3BhdHRlcm4gPC0gcGFzdGUwKCIoPzoiLCBuX3BhcnR5LCAifCIsIGZ1bGx3aWR0aF9kaWdpdChuX3BhcnR5KSwgIilcXHMq44Gk44Gu6YG45oqe6IKiIikKCiAgICAgIGhpdCA8LSBncmVwbCgi5Lul5LiL44GrIiwgbWV0YWRhdGEkdGV4dCwgZml4ZWQgPSBUUlVFKSAmCiAgICAgICAgZ3JlcGwoIumBuOaKnuiCoiIsIG1ldGFkYXRhJHRleHQsIGZpeGVkID0gVFJVRSkgJgogICAgICAgIGdyZXBsKGRpZ2l0X3BhdHRlcm4sIG1ldGFkYXRhJHRleHQsIHBlcmwgPSBUUlVFKSAmCiAgICAgICAgZ3JlcGwoIuihhuitsOmZoiIsIG1ldGFkYXRhJHRleHQsIGZpeGVkID0gVFJVRSkgJgogICAgICAgICFncmVwbCgi5o+Q56S644GV44KM44GfLirpgbjmip7ogqLjga7mlbAiLCBtZXRhZGF0YSR0ZXh0LCBwZXJsID0gVFJVRSkgJgogICAgICAgIGdyZXBsKCJeUVswLTldK1xcLlswLTldKyQiLCBtZXRhZGF0YSRjb2x1bW4pCgogICAgICBjYW5kaWRhdGVzIDwtIG1ldGFkYXRhW2hpdCwgLCBkcm9wID0gRkFMU0VdCiAgICAgIGNhbmRpZGF0ZXMgPC0gY2FuZGlkYXRlc1sKICAgICAgICBvcmRlcihxdWVzdGlvbl9vcmRlcl9rZXkoY2FuZGlkYXRlcyRjb2x1bW4pKSwKICAgICAgICAsCiAgICAgICAgZHJvcCA9IEZBTFNFCiAgICAgIF0KCiAgICAgIGlmIChucm93KGNhbmRpZGF0ZXMpICE9IDVMKSB7CiAgICAgICAgc3RvcCgiQ2hlY2sgY2hvaWNlIGNvbHVtbnMiKQogICAgICB9CgogICAgICBkYXRhLmZyYW1lKAogICAgICAgIHBhcnR5X24gPSBuX3BhcnR5LAogICAgICAgIHRhc2sgPSBzZXFfbGVuKDVMKSwKICAgICAgICBjaG9pY2VfdmFyID0gY2FuZGlkYXRlcyRjb2x1bW4sCiAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgICAgICkKICAgIH0KICApCgogIG91dCA8LSBkcGx5cjo6YmluZF9yb3dzKG1hcHMpCiAgbWVzc2FnZSgiQ2hvaWNlIGNvbHVtbnM6IE9LIikKICBwcmludChvdXQpCiAgb3V0Cn0KCmRldGVjdF9tYW5pcHVsYXRpb25fbWFwIDwtIGZ1bmN0aW9uKHJhdywgY2hvaWNlX21hcCwgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkiKSB7CiAgbWV0YWRhdGFfdGV4dCA8LSBzZXROYW1lcygKICAgIHZhcHBseShuYW1lcyhyYXcpLCBmdW5jdGlvbih2KSBxdWFsdHJpY3NfcHJldmlld190ZXh0KHJhdywgdiksIGNoYXJhY3RlcigxKSksCiAgICBuYW1lcyhyYXcpCiAgKQoKICBvdXQgPC0gbGFwcGx5KAogICAgc29ydCh1bmlxdWUoY2hvaWNlX21hcCRwYXJ0eV9uKSksCiAgICBmdW5jdGlvbihuX3BhcnR5KSB7CiAgICAgIHZhcnMgPC0gY2hvaWNlX21hcCRjaG9pY2VfdmFyW2Nob2ljZV9tYXAkcGFydHlfbiA9PSBuX3BhcnR5XQogICAgICByb290cyA8LSBzdWIoIlxcLlswLTldKyQiLCAiIiwgdmFycykKICAgICAgcm9vdCA8LSBuYW1lcyhzb3J0KHRhYmxlKHJvb3RzKSwgZGVjcmVhc2luZyA9IFRSVUUpKVtbMV1dCiAgICAgIHN1ZmZpeCA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLmludGVnZXIoc3ViKCJeLipcXC4iLCAiIiwgdmFycykpKQogICAgICBleHBlY3RlZCA8LSBwYXN0ZTAocm9vdCwgIi4iLCBtYXgoc3VmZml4LCBuYS5ybSA9IFRSVUUpICsgMUwpCgogICAgICBjYW5kaWRhdGVzIDwtIG5hbWVzKG1ldGFkYXRhX3RleHQpWwogICAgICAgIHN0YXJ0c1dpdGgobmFtZXMobWV0YWRhdGFfdGV4dCksIHBhc3RlMChyb290LCAiLiIpKSAmCiAgICAgICAgICBncmVwbCgi5o+Q56S644GV44KM44GfIiwgbWV0YWRhdGFfdGV4dCwgZml4ZWQgPSBUUlVFKSAmCiAgICAgICAgICBncmVwbCgi6YG45oqe6IKi44Gu5pWwIiwgbWV0YWRhdGFfdGV4dCwgZml4ZWQgPSBUUlVFKQogICAgICBdCgogICAgICBpZiAoZXhwZWN0ZWQgJWluJSBjYW5kaWRhdGVzKSB7CiAgICAgICAgY2hvc2VuIDwtIGV4cGVjdGVkCiAgICAgIH0gZWxzZSBpZiAobGVuZ3RoKGNhbmRpZGF0ZXMpID09IDFMKSB7CiAgICAgICAgY2hvc2VuIDwtIGNhbmRpZGF0ZXNbWzFdXQogICAgICB9IGVsc2UgewogICAgICAgIHN0b3AoIkNoZWNrIG1hbmlwdWxhdGlvbiBpdGVtIikKICAgICAgfQoKICAgICAgZGF0YS5mcmFtZSgKICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwKICAgICAgICBtYW5pcHVsYXRpb25fdmFyID0gY2hvc2VuLAogICAgICAgIGNvcnJlY3RfYW5zd2VyID0gYXMuY2hhcmFjdGVyKG5fcGFydHkpLAogICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQogICAgICApCiAgICB9CiAgKQoKICBvdXQgPC0gZHBseXI6OmJpbmRfcm93cyhvdXQpCiAgbWVzc2FnZSgiTWFuaXB1bGF0aW9uIGl0ZW06IE9LIikKICBwcmludChvdXQpCiAgb3V0Cn0KCnBhcnNlX2Nob2ljZV9wb3NpdGlvbiA8LSBmdW5jdGlvbih4KSB7CiAgeCA8LSBhcy5jaGFyYWN0ZXIoeCkKICB4W2lzLm5hKHgpXSA8LSAiIgogIHggPC0gZ3N1Yigi44CAIiwgIiAiLCB4LCBmaXhlZCA9IFRSVUUpCiAgeCA8LSB0cmltd3MoZ3N1YigiW1s6c3BhY2U6XV0rIiwgIiAiLCB4KSkKCiAgbGFiZWxfbWF0Y2ggPC0gcmVnZXhlYygiKD865pS/5YWafOeKtuazgXzpgbjmip7ogqIpXFxzKihbMS01XSkiLCB4LCBwZXJsID0gVFJVRSkKICBsYWJlbF9wYXJ0cyA8LSByZWdtYXRjaGVzKHgsIGxhYmVsX21hdGNoKQogIGxhYmVsX251bSA8LSB2YXBwbHkoCiAgICBsYWJlbF9wYXJ0cywKICAgIGZ1bmN0aW9uKHopIGlmIChsZW5ndGgoeikgPj0gMkwpIGFzLm51bWVyaWMoeltbMl1dKSBlbHNlIE5BX3JlYWxfLAogICAgbnVtZXJpYygxKQogICkKCiAgZXhhY3QgPC0gZ3JlcGwoIl5bMS01XSg/OlxcLjArKT8kIiwgeCwgcGVybCA9IFRSVUUpCiAgZXhhY3RfbnVtIDwtIHJlcChOQV9yZWFsXywgbGVuZ3RoKHgpKQogIGV4YWN0X251bVtleGFjdF0gPC0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKHhbZXhhY3RdKSkKCiAgdHJhaWxpbmcgPC0gcmVnZXhlYygiXFwoKFsxLTVdKVxcKVxccyokIiwgeCkKICB0cmFpbGluZ19wYXJ0cyA8LSByZWdtYXRjaGVzKHgsIHRyYWlsaW5nKQogIHRyYWlsaW5nX251bSA8LSB2YXBwbHkoCiAgICB0cmFpbGluZ19wYXJ0cywKICAgIGZ1bmN0aW9uKHopIGlmIChsZW5ndGgoeikgPj0gMkwpIGFzLm51bWVyaWMoeltbMl1dKSBlbHNlIE5BX3JlYWxfLAogICAgbnVtZXJpYygxKQogICkKCiAgb3V0IDwtIGxhYmVsX251bQogIG91dFtpcy5uYShvdXQpXSA8LSBleGFjdF9udW1baXMubmEob3V0KV0KICBvdXRbaXMubmEob3V0KV0gPC0gdHJhaWxpbmdfbnVtW2lzLm5hKG91dCldCiAgb3V0Cn0KCgpgYGAKCiMjIEEuMiDlrp/pqJMx77ya5pys5paH44Gu5ZuzNOODu+WbszUKCmBgYHtyIGEyLXN0dWR5MS1jb2RlLCBldmFsPXBhcmFtcyRydW5fYW5hbHlzaXMsIHJlc3VsdHM9J2hpZGUnLCBmaWcuc2hvdz0naGlkZSd9CiMg5pys5paH44Kz44O844OJCnN0dWR5MV9lbnYgPC0gbG9jYWwoewpyZXF1aXJlZF9wYWNrYWdlcyA8LSBjKAogICAgImRwbHlyIiwKICAgICJ0aWR5ciIsCiAgICAic3RyaW5nciIsCiAgICAicHVycnIiLAogICAgInJlYWRyIiwKICAgICJmaXhlc3QiLAogICAgInRpYmJsZSIsCiAgICAiZm9yY2F0cyIsCiAgICAiZ2dwbG90MiIsCiAgICAic2NhbGVzIiwKICAgICJzdXJ2aXZhbCIsCiAgICAiZ2d0ZXh0IiwKICAgICJwYXRjaHdvcmsiCiAgKQoKICBtaXNzaW5nX3BhY2thZ2VzIDwtIHJlcXVpcmVkX3BhY2thZ2VzWwogICAgIXZhcHBseShyZXF1aXJlZF9wYWNrYWdlcywgcmVxdWlyZU5hbWVzcGFjZSwgbG9naWNhbCgxKSwgcXVpZXRseSA9IFRSVUUpCiAgXQoKICBpZiAobGVuZ3RoKG1pc3NpbmdfcGFja2FnZXMpID4gMCkgewogICAgc3RvcCgiTm8gcGFja2FnZXMiKQogIH0KCiAgbGlicmFyeShkcGx5cikKICBsaWJyYXJ5KHRpZHlyKQogIGxpYnJhcnkoc3RyaW5ncikKICBsaWJyYXJ5KHB1cnJyKQogIGxpYnJhcnkocmVhZHIpCiAgbGlicmFyeShmaXhlc3QpCiAgbGlicmFyeSh0aWJibGUpCiAgbGlicmFyeShmb3JjYXRzKQogIGxpYnJhcnkoZ2dwbG90MikKICBsaWJyYXJ5KHNjYWxlcykKICBsaWJyYXJ5KHN1cnZpdmFsKQogIGxpYnJhcnkocGF0Y2h3b3JrKQoKICBkYXRhX2ZpbGUgPC0gdW5pZmllZF9jb25maWckc3R1ZHkxJGRhdGFfZmlsZQogIG91dHB1dF9kaXIgPC0gdW5pZmllZF9jb25maWckc3R1ZHkxJG91dHB1dF9kaXIKCiAgZGlyLmNyZWF0ZShvdXRwdXRfZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkKCiAgcmVxdWlyZV9pbml0aWFsX2NvbnNlbnQgPC0gVFJVRQogIHJlcXVpcmVfZmluYWxfY29uc2VudCA8LSBUUlVFCiAgaW5pdGlhbF9jb25zZW50X3ZhciA8LSAiUTEuMSIKICBmaW5hbF9jb25zZW50X3ZhciA8LSAiUTguMSIKCiAgcmVxdWlyZV9hdHRlbnRpb25fY2hlY2sgPC0gRkFMU0UKICByZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjayA8LSBGQUxTRQogIGF0dGVudGlvbl9jaGVja192YXIgPC0gTkFfY2hhcmFjdGVyXwogIGF0dGVudGlvbl9jaGVja19jb3JyZWN0IDwtIE5BX2NoYXJhY3Rlcl8KCiAgcmVxdWlyZV9hbGxfZml2ZV90YXNrcyA8LSBUUlVFCgogIHVzZV9lZHVjYXRpb25fY292YXJpYXRlIDwtIEZBTFNFCgogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiA8LSB1bmlmaWVkX2NvbmZpZyRyZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IKICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQgPC0gdW5pZmllZF9jb25maWckcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkICsgMUwKICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3Byb2dyZXNzX2V2ZXJ5IDwtIHVuaWZpZWRfY29uZmlnJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkKCiAgcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA8LSB1bmlmaWVkX2NvbmZpZyRyZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwCgoKICBub3JtX3RleHQgPC0gZnVuY3Rpb24oeCkgewogICAgeCAlPiUKICAgICAgYXMuY2hhcmFjdGVyKCkgJT4lCiAgICAgIHN0cl9zcXVpc2goKSAlPiUKICAgICAgc3RyX3JlcGxhY2VfYWxsKCLvvZ4iLCAifiIpICU+JQogICAgICBzdHJfcmVwbGFjZV9hbGwoIuOAnCIsICJ+IikKICB9CgogIGFzX251bSA8LSBmdW5jdGlvbih4KSB7CiAgICBzdXBwcmVzc1dhcm5pbmdzKHJlYWRyOjpwYXJzZV9udW1iZXIobm9ybV90ZXh0KHgpKSkKICB9CgogIGlzX3Jlc3BvbnNlX2NvZGUgPC0gZnVuY3Rpb24oeCwgY29kZSkgewogICAgeF9ub3JtIDwtIG5vcm1fdGV4dCh4KQogICAgY29kZV9jaHIgPC0gYXMuY2hhcmFjdGVyKGNvZGUpCgogICAgeF9ub3JtID09IGNvZGVfY2hyIHwKICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCh4X25vcm0sIHBhc3RlMCgiXFwoIiwgY29kZV9jaHIsICJcXCkkIikpCiAgfQoKICBmaXJzdF9leGlzdGluZyA8LSBmdW5jdGlvbihkYXQsIGNhbmRpZGF0ZXMpIHsKICAgIG91dCA8LSBjYW5kaWRhdGVzW2NhbmRpZGF0ZXMgJWluJSBuYW1lcyhkYXQpXQogICAgaWYgKGxlbmd0aChvdXQpID09IDApIE5BX2NoYXJhY3Rlcl8gZWxzZSBvdXRbMV0KICB9CgogIGdldF92YXIgPC0gZnVuY3Rpb24oZGF0LCBjYW5kaWRhdGVzKSB7CiAgICB2IDwtIGZpcnN0X2V4aXN0aW5nKGRhdCwgY2FuZGlkYXRlcykKICAgIGlmIChpcy5uYSh2KSkgewogICAgICByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhkYXQpKQogICAgfSBlbHNlIHsKICAgICAgZGF0W1t2XV0KICAgIH0KICB9CgogIHJlbGV2ZWxfaWZfcHJlc2VudCA8LSBmdW5jdGlvbih4LCByZWYpIHsKICAgIHggPC0gZmFjdG9yKHgpCiAgICBpZiAocmVmICVpbiUgbGV2ZWxzKHgpKSB7CiAgICAgIHJlbGV2ZWwoeCwgcmVmID0gcmVmKQogICAgfSBlbHNlIHsKICAgICAgeAogICAgfQogIH0KCiAgZmFjdG9yX21pc3MgPC0gZnVuY3Rpb24oeCwgbWlzcyA9ICLmrKDmkI3jg7vnhKHlm57nrZQiKSB7CiAgICB4IDwtIG5vcm1fdGV4dCh4KQogICAgeFtpcy5uYSh4KSB8IHggPT0gIiIgfCB4ID09ICJOQSJdIDwtIG1pc3MKICAgIGZhY3Rvcih4KQogIH0KCiAgbWVhbl9pbXB1dGUgPC0gZnVuY3Rpb24oeCkgewogICAgeCA8LSBhcy5udW1lcmljKHgpCiAgICBtaXNzIDwtIGFzLmludGVnZXIoaXMubmEoeCkpCgogICAgaWYgKGFsbChpcy5uYSh4KSkpIHsKICAgICAgdmFsdWUgPC0geAogICAgfSBlbHNlIHsKICAgICAgdmFsdWUgPC0gaWZlbHNlKGlzLm5hKHgpLCBtZWFuKHgsIG5hLnJtID0gVFJVRSksIHgpCiAgICB9CgogICAgbGlzdCh2YWx1ZSA9IHZhbHVlLCBtaXNzID0gbWlzcykKICB9CgogIHdyaXRlX2Nzdl9zYWZlbHkgPC0gZnVuY3Rpb24oeCwgZmlsZW5hbWUpIHsKICAgIHJlYWRyOjp3cml0ZV9jc3YoeCwgZmlsZS5wYXRoKG91dHB1dF9kaXIsIGZpbGVuYW1lKSwgbmEgPSAiIikKICB9CgogIHNhdmVfcGxvdCA8LSBmdW5jdGlvbihmaWxlbmFtZSwgcGxvdCwgd2lkdGgsIGhlaWdodCwgZHBpID0gMzAwKSB7CiAgICBnZ3Bsb3QyOjpnZ3NhdmUoCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsIGZpbGVuYW1lKSwKICAgICAgcGxvdCA9IHBsb3QsCiAgICAgIHdpZHRoID0gd2lkdGgsCiAgICAgIGhlaWdodCA9IGhlaWdodCwKICAgICAgZHBpID0gZHBpCiAgICApCiAgfQoKCiAgaWYgKCFmaWxlLmV4aXN0cyhkYXRhX2ZpbGUpKSB7CiAgICBzdG9wKCJDaGVjayBkYXRhIikKICB9CgogIHJhdyA8LSByZWFkcjo6cmVhZF9jc3YoCiAgICBkYXRhX2ZpbGUsCiAgICBjb2xfdHlwZXMgPSBjb2xzKC5kZWZhdWx0ID0gY29sX2NoYXJhY3RlcigpKSwKICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UsCiAgICBuYW1lX3JlcGFpciA9ICJtaW5pbWFsIgogICkKCiAgaWYgKCEiUmVzcG9uc2VJZCIgJWluJSBuYW1lcyhyYXcpKSB7CiAgICBzdG9wKCJDaGVjayBkYXRhIikKICB9CgogIG5hbWVzKHJhdykgPC0gbmFtZXMocmF3KSAlPiUKICAgIHN0cl9yZXBsYWNlKCJeRlxcLihcXGQrKVxcLihcXGQrKVxcLihcXGQrKSQiLCAiRi1cXDEtXFwyLVxcMyIpICU+JQogICAgc3RyX3JlcGxhY2UoIl5GXFwuKFxcZCspXFwuKFxcZCspJCIsICJGLVxcMS1cXDIiKQoKICBpZiAoCiAgICByZXF1aXJlX2ZpbmFsX2NvbnNlbnQgJiYKICAgICAgKAogICAgICAgIGlzLm5hKGZpbmFsX2NvbnNlbnRfdmFyKSB8fAogICAgICAgICAgIWZpbmFsX2NvbnNlbnRfdmFyICVpbiUgbmFtZXMocmF3KQogICAgICApCiAgKSB7CiAgICBjb25zZW50X3F1ZXN0aW9uX3BhdHRlcm4gPC0gcGFzdGUwKAogICAgICAi5Zue562U57WQ5p6c44KS6YCB5L+h44GZ44KLfCIsCiAgICAgICLlm57nrZTjgpLpgIHkv6HjgZfjgarjgYR8IiwKICAgICAgIuWbnuetlOe1kOaenOOCkumAgeS/oeOBl+OBquOBhHwiLAogICAgICAi5pyA57WC5oSP5oCd56K66KqNIgogICAgKQoKICAgIHByZXZpZXdfbiA8LSBtaW4oMTBMLCBucm93KHJhdykpCgogICAgZGV0ZWN0ZWRfZmluYWxfY29uc2VudF92YXJzIDwtIG5hbWVzKHJhdylbCiAgICAgIHZhcHBseSgKICAgICAgICByYXcsCiAgICAgICAgZnVuY3Rpb24oY29sdW1uKSB7CiAgICAgICAgICBwcmV2aWV3IDwtIG5vcm1fdGV4dCgKICAgICAgICAgICAgdXRpbHM6OmhlYWQoCiAgICAgICAgICAgICAgY29sdW1uLAogICAgICAgICAgICAgIHByZXZpZXdfbgogICAgICAgICAgICApCiAgICAgICAgICApCgogICAgICAgICAgYW55KAogICAgICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KAogICAgICAgICAgICAgIHByZXZpZXcsCiAgICAgICAgICAgICAgY29uc2VudF9xdWVzdGlvbl9wYXR0ZXJuCiAgICAgICAgICAgICksCiAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgKQogICAgICAgIH0sCiAgICAgICAgbG9naWNhbCgxKQogICAgICApCiAgICBdCgogICAgaWYgKGxlbmd0aChkZXRlY3RlZF9maW5hbF9jb25zZW50X3ZhcnMpID09IDFMKSB7CiAgICAgIGZpbmFsX2NvbnNlbnRfdmFyIDwtIGRldGVjdGVkX2ZpbmFsX2NvbnNlbnRfdmFyc1tbMV1dCgogICAgICBtZXNzYWdlKCJGaW5hbCBjb25zZW50OiAiLCBmaW5hbF9jb25zZW50X3ZhcikKICAgIH0gZWxzZSBpZiAobGVuZ3RoKGRldGVjdGVkX2ZpbmFsX2NvbnNlbnRfdmFycykgPiAxTCkgewogICAgICBzdG9wKCJDaGVjayBmaW5hbCBjb25zZW50IikKICAgIH0gZWxzZSB7CiAgICAgIGxpa2VseV9xdWVzdGlvbl9jb2x1bW5zIDwtIG5hbWVzKHJhdylbCiAgICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCgKICAgICAgICAgIG5hbWVzKHJhdyksCiAgICAgICAgICAiXlFbMC05XSsoPzpcXC5bMC05XSspPyQiCiAgICAgICAgKQogICAgICBdCgogICAgICBzdG9wKCJDaGVjayBmaW5hbCBjb25zZW50IikKICAgIH0KICB9CgogIGRmX2hlYWRlcl9yZW1vdmVkIDwtIHJhdyAlPiUKICAgIGZpbHRlcigKICAgICAgIWlzLm5hKFJlc3BvbnNlSWQpLAogICAgICBSZXNwb25zZUlkICE9ICIiLAogICAgICAhc3RyX2RldGVjdCgKICAgICAgICBub3JtX3RleHQoUmVzcG9uc2VJZCksCiAgICAgICAgIl4oUmVzcG9uc2UgSUR85Zue562USUQpJHxJbXBvcnRJZCIKICAgICAgKQogICAgKSAlPiUKICAgIG11dGF0ZShJRCA9IGFzLmNoYXJhY3RlcihSZXNwb25zZUlkKSkKCiAgZHVwbGljYXRlX2lkcyA8LSBkZl9oZWFkZXJfcmVtb3ZlZCAlPiUKICAgIGNvdW50KElEKSAlPiUKICAgIGZpbHRlcihuID4gMSkKCiAgaWYgKG5yb3coZHVwbGljYXRlX2lkcykgPiAwKSB7CiAgICBwcmludChkdXBsaWNhdGVfaWRzKQogICAgc3RvcCgiQ2hlY2siKQogIH0KCiAgc2FtcGxlX2Zsb3cgPC0gdGliYmxlKAogICAgc3RhZ2UgPSAiUXVhbHRyaWNz6LOq5ZWP5paH6KGM44O7SW1wb3J0SWTooYzjgpLpmaTlpJblvowiLAogICAgbiA9IG5yb3coZGZfaGVhZGVyX3JlbW92ZWQpCiAgKQoKICBkZiA8LSBkZl9oZWFkZXJfcmVtb3ZlZAoKICBpZiAocmVxdWlyZV9pbml0aWFsX2NvbnNlbnQpIHsKICAgIGlmIChpcy5uYShpbml0aWFsX2NvbnNlbnRfdmFyKSB8fCAhaW5pdGlhbF9jb25zZW50X3ZhciAlaW4lIG5hbWVzKGRmKSkgewogICAgICBzdG9wKCJDaGVjayBpbml0aWFsIGNvbnNlbnQiKQogICAgfQogICAgZGYgPC0gZGYgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICBpc19yZXNwb25zZV9jb2RlKC5kYXRhW1tpbml0aWFsX2NvbnNlbnRfdmFyXV0sIDEpIHwKICAgICAgICAgIHN0cl9kZXRlY3QoCiAgICAgICAgICAgIG5vcm1fdGV4dCguZGF0YVtbaW5pdGlhbF9jb25zZW50X3Zhcl1dKSwKICAgICAgICAgICAgIui2o+aXqOOBq+WQjOaEj+OBl+OBpi4q5Y2U5Yqb44GZ44KLIgogICAgICAgICAgKQogICAgICApCiAgICBzYW1wbGVfZmxvdyA8LSBiaW5kX3Jvd3MoCiAgICAgIHNhbXBsZV9mbG93LAogICAgICB0aWJibGUoc3RhZ2UgPSAi5Yid5Zue5ZCM5oSP5Zue562U44KS5L+d5oyBIiwgbiA9IG5yb3coZGYpKQogICAgKQogIH0KCiAgaWYgKHJlcXVpcmVfZmluYWxfY29uc2VudCkgewogICAgaWYgKGlzLm5hKGZpbmFsX2NvbnNlbnRfdmFyKSB8fCAhZmluYWxfY29uc2VudF92YXIgJWluJSBuYW1lcyhkZikpIHsKICAgICAgc3RvcCgiQ2hlY2sgZmluYWwgY29uc2VudCIpCiAgICB9CiAgICBkZiA8LSBkZiAlPiUKICAgICAgZmlsdGVyKAogICAgICAgIGlzX3Jlc3BvbnNlX2NvZGUoLmRhdGFbW2ZpbmFsX2NvbnNlbnRfdmFyXV0sIDEpIHwKICAgICAgICAgIHN0cl9kZXRlY3QoCiAgICAgICAgICAgIG5vcm1fdGV4dCguZGF0YVtbZmluYWxfY29uc2VudF92YXJdXSksCiAgICAgICAgICAgICLlkIzmhI/jgZcuKuWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCiyIKICAgICAgICAgICkKICAgICAgKQogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKAogICAgICBzYW1wbGVfZmxvdywKICAgICAgdGliYmxlKHN0YWdlID0gIuacgOe1guWQjOaEj+WbnuetlOOCkuS/neaMgSIsIG4gPSBucm93KGRmKSkKICAgICkKICB9CgogIHByaW50KHNhbXBsZV9mbG93KQogIHdyaXRlX2Nzdl9zYWZlbHkoc2FtcGxlX2Zsb3csICJzYW1wbGVfZmxvd19iZWZvcmVfY29uam9pbnQuY3N2IikKCgogIGNob2ljZV9tYXAgPC0gdHJpYmJsZSgKICAgIH5wYXJ0eV9uLCB+dGFzaywgfmNob2ljZV92YXIsCiAgICAyLCAxLCAiUTI0MCIsCiAgICAyLCAyLCAiUTI1MyIsCiAgICAyLCAzLCAiUTI1NCIsCiAgICAyLCA0LCAiUTI1NSIsCiAgICAyLCA1LCAiUTI1NiIsCgogICAgMywgMSwgIlEyMzUiLAogICAgMywgMiwgIlEyNDEiLAogICAgMywgMywgIlEyNDIiLAogICAgMywgNCwgIlEyNDMiLAogICAgMywgNSwgIlEyNDQiLAoKICAgIDQsIDEsICJRMjM4IiwKICAgIDQsIDIsICJRMjQ1IiwKICAgIDQsIDMsICJRMjQ2IiwKICAgIDQsIDQsICJRMjQ3IiwKICAgIDQsIDUsICJRMjQ4IiwKCiAgICA1LCAxLCAiUTIzOSIsCiAgICA1LCAyLCAiUTI0OSIsCiAgICA1LCAzLCAiUTI1MCIsCiAgICA1LCA0LCAiUTI1MSIsCiAgICA1LCA1LCAiUTI1MiIKICApCgogIGlmIChyZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjaykgewogICAgc3RvcCgiQ2hlY2siKQogIH0KCgogIGxldmVsX3RvX2F0dHJfdmFyIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHggPC0gbm9ybV90ZXh0KHgpCgogICAgY2FzZV93aGVuKAogICAgICB4ICVpbiUgYygi5Y+z5rS+44O75L+d5a6I55qEIiwgIuS4remBkyIsICLlt6bmtL7jg7vpnanmlrDnmoQiKSB+CiAgICAgICAgInBvbGljeV9wb3NpdGlvbiIsCgogICAgICB4ICVpbiUgYygi5LiO5YWaIiwgIumHjuWFmiIpIH4KICAgICAgICAiZ292ZXJubWVudF9zdGF0dXMiLAoKICAgICAgc3RyX2RldGVjdCh4LCAiR0RQ5oiQ6ZW3546HIikgfgogICAgICAgICJnZHBfZ3Jvd3RoIiwKCiAgICAgIHN0cl9kZXRlY3QoeCwgIuaXpee1jOW5s+WdhyIpIH4KICAgICAgICAibmlra2VpIiwKCiAgICAgIHggJWluJSBjKCIxMOS7peS4iyIsICIxMH40OSIsICI1MH45OSIsICIxMDB+MTk5IiwgIjIwMOS7peS4iiIpIH4KICAgICAgICAic2VhdHMiLAoKICAgICAgc3RyX2RldGVjdCh4LCAiQ1BJfOeJqeS+oSIpIH4KICAgICAgICAiY3BpIiwKCiAgICAgIHN0cl9kZXRlY3QoeCwgIuWksealreeOh3zpm4fnlKgiKSB+CiAgICAgICAgInVuZW1wbG95bWVudCIsCgogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXwogICAgKQogIH0KCiAgcmVxdWlyZWRfYXR0cl92YXJzIDwtIGMoCiAgICAicG9saWN5X3Bvc2l0aW9uIiwKICAgICJnb3Zlcm5tZW50X3N0YXR1cyIsCiAgICAiZ2RwX2dyb3d0aCIsCiAgICAibmlra2VpIiwKICAgICJzZWF0cyIsCiAgICAiY3BpIiwKICAgICJ1bmVtcGxveW1lbnQiCiAgKQoKICBhbGxvd2VkX2xldmVscyA8LSBsaXN0KAogICAgcG9saWN5X3Bvc2l0aW9uID0gYygi5Y+z5rS+44O75L+d5a6I55qEIiwgIuS4remBkyIsICLlt6bmtL7jg7vpnanmlrDnmoQiKSwKICAgIGdvdmVybm1lbnRfc3RhdHVzID0gYygi5LiO5YWaIiwgIumHjuWFmiIpLAogICAgZ2RwX2dyb3d0aCA9IGMoCiAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiLAogICAgICAiR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAgICJHRFDmiJDplbfnjofjg57jgqTjg4rjgrkx77yFIgogICAgKSwKICAgIG5pa2tlaSA9IGMoCiAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwKICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODnuOCpOODiuOCuTEwMDDlhoYiLAogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIgogICAgKSwKICAgIHNlYXRzID0gYygiMTDku6XkuIsiLCAiMTB+NDkiLCAiNTB+OTkiLCAiMTAwfjE5OSIsICIyMDDku6XkuIoiKSwKICAgIGNwaSA9IGMoCiAgICAgICJDUEnliY3mnJ/mr5TCsTDjg53jgqTjg7Pjg4giLAogICAgICAiQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsCiAgICAgICJDUEnliY3mnJ/mr5Tjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIgogICAgKSwKICAgIHVuZW1wbG95bWVudCA9IGMoCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiLAogICAgICAi5aSx5qWt546H5YmN5pyf5q+U44OX44Op44K5Me+8hSIsCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg57jgqTjg4rjgrkx77yFIgogICAgKQogICkKCgogIG1ha2VfcHJvZmlsZV9sb25nIDwtIGZ1bmN0aW9uKGRhdCwgbl9wYXJ0eSkgewoKICAgIG1hcF9uIDwtIGNob2ljZV9tYXAgJT4lCiAgICAgIGZpbHRlcihwYXJ0eV9uID09IG5fcGFydHkpCgogICAgcXZhcnMgPC0gbWFwX24kY2hvaWNlX3ZhcgoKICAgIG1pc3NpbmdfcSA8LSBzZXRkaWZmKHF2YXJzLCBuYW1lcyhkYXQpKQogICAgaWYgKGxlbmd0aChtaXNzaW5nX3EpID4gMCkgewogICAgICBzdG9wKCJDaGVjayBjaG9pY2UgY29sdW1ucyIpCiAgICB9CgogICAgZGF0X24gPC0gZGF0ICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgaWZfYW55KAogICAgICAgICAgYWxsX29mKHF2YXJzKSwKICAgICAgICAgIH4gIWlzLm5hKC54KSAmIG5vcm1fdGV4dCgueCkgIT0gIiIKICAgICAgICApCiAgICAgICkKCiAgICBjaG9pY2VfbG9uZyA8LSBkYXRfbiAlPiUKICAgICAgc2VsZWN0KElELCBhbGxfb2YocXZhcnMpKSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBhbGxfb2YocXZhcnMpLAogICAgICAgIG5hbWVzX3RvID0gImNob2ljZV92YXIiLAogICAgICAgIHZhbHVlc190byA9ICJjaG9pY2VfcmF3IgogICAgICApICU+JQogICAgICBsZWZ0X2pvaW4obWFwX24sIGJ5ID0gImNob2ljZV92YXIiKSAlPiUKICAgICAgbXV0YXRlKGNob2ljZSA9IGFzX251bShjaG9pY2VfcmF3KSkgJT4lCiAgICAgIGZpbHRlcighaXMubmEoY2hvaWNlKSkgJT4lCiAgICAgIHNlbGVjdChJRCwgcGFydHlfbiwgdGFzaywgY2hvaWNlKQoKICAgIGludmFsaWRfY2hvaWNlIDwtIGNob2ljZV9sb25nICU+JQogICAgICBmaWx0ZXIoY2hvaWNlIDwgMSB8IGNob2ljZSA+IG5fcGFydHkpCgogICAgaWYgKG5yb3coaW52YWxpZF9jaG9pY2UpID4gMCkgewogICAgICBwcmludChpbnZhbGlkX2Nob2ljZSkKICAgICAgc3RvcCgiQ2hlY2sgY2hvaWNlIHZhbHVlcyIpCiAgICB9CgogICAgZHVwbGljYXRlX2Nob2ljZSA8LSBjaG9pY2VfbG9uZyAlPiUKICAgICAgY291bnQoSUQsIHRhc2spICU+JQogICAgICBmaWx0ZXIobiAhPSAxKQoKICAgIGlmIChucm93KGR1cGxpY2F0ZV9jaG9pY2UpID4gMCkgewogICAgICBwcmludChkdXBsaWNhdGVfY2hvaWNlKQogICAgICBzdG9wKCJDaGVjayBkdXBsaWNhdGUgY2hvaWNlcyIpCiAgICB9CgogICAgbGV2ZWxfcmVnZXggPC0gIl5GLShbMS01XSktKFsxLTVdKS0oWzEtN10pJCIKICAgIGxldmVsX2NvbHMgPC0gbmFtZXMoZGF0X24pW3N0cl9kZXRlY3QobmFtZXMoZGF0X24pLCBsZXZlbF9yZWdleCldCgogICAgaWYgKGxlbmd0aChsZXZlbF9jb2xzKSA9PSAwKSB7CiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgfQoKICAgIGxldmVsX2xvbmcgPC0gZGF0X24gJT4lCiAgICAgIHNlbGVjdChJRCwgYWxsX29mKGxldmVsX2NvbHMpKSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBhbGxfb2YobGV2ZWxfY29scyksCiAgICAgICAgbmFtZXNfdG8gPSAiZnZhciIsCiAgICAgICAgdmFsdWVzX3RvID0gImxldmVsIgogICAgICApICU+JQogICAgICBleHRyYWN0KAogICAgICAgIGZ2YXIsCiAgICAgICAgaW50byA9IGMoInRhc2siLCAicHJvZmlsZSIsICJhdHRyX29yZGVyIiksCiAgICAgICAgcmVnZXggPSBsZXZlbF9yZWdleCwKICAgICAgICBjb252ZXJ0ID0gVFJVRQogICAgICApICU+JQogICAgICBtdXRhdGUobGV2ZWwgPSBub3JtX3RleHQobGV2ZWwpKSAlPiUKICAgICAgZmlsdGVyKAogICAgICAgIHRhc2sgJWluJSAxOjUsCiAgICAgICAgcHJvZmlsZSAlaW4lIDE6bl9wYXJ0eSwKICAgICAgICBhdHRyX29yZGVyICVpbiUgMTo3LAogICAgICAgICFpcy5uYShsZXZlbCksCiAgICAgICAgbGV2ZWwgIT0gIiIKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKGF0dHJfdmFyID0gbGV2ZWxfdG9fYXR0cl92YXIobGV2ZWwpKQoKICAgIHVua25vd25fbGV2ZWxzIDwtIGxldmVsX2xvbmcgJT4lCiAgICAgIGZpbHRlcihpcy5uYShhdHRyX3ZhcikpICU+JQogICAgICBkaXN0aW5jdChsZXZlbCkKCiAgICBpZiAobnJvdyh1bmtub3duX2xldmVscykgPiAwKSB7CiAgICAgIHByaW50KHVua25vd25fbGV2ZWxzKQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgIH0KCiAgICBwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCA8LSBsZXZlbF9sb25nICU+JQogICAgICBjb3VudChJRCwgdGFzaywgcHJvZmlsZSwgbmFtZSA9ICJuX2F0dHJpYnV0ZV9yb3dzIikgJT4lCiAgICAgIGZpbHRlcihuX2F0dHJpYnV0ZV9yb3dzICE9IDcpCgogICAgaWYgKG5yb3cocHJvZmlsZV9hdHRyaWJ1dGVfY291bnQpID4gMCkgewogICAgICBwcmludChoZWFkKHByb2ZpbGVfYXR0cmlidXRlX2NvdW50LCA1MCkpCiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgfQoKICAgIGR1cGxpY2F0ZV9hdHRyaWJ1dGUgPC0gbGV2ZWxfbG9uZyAlPiUKICAgICAgY291bnQoSUQsIHRhc2ssIHByb2ZpbGUsIGF0dHJfdmFyKSAlPiUKICAgICAgZmlsdGVyKG4gIT0gMSkKCiAgICBpZiAobnJvdyhkdXBsaWNhdGVfYXR0cmlidXRlKSA+IDApIHsKICAgICAgcHJpbnQoaGVhZChkdXBsaWNhdGVfYXR0cmlidXRlLCA1MCkpCiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgfQoKICAgIHByb2ZpbGVfd2lkZSA8LSBsZXZlbF9sb25nICU+JQogICAgICBpbm5lcl9qb2luKGNob2ljZV9sb25nLCBieSA9IGMoIklEIiwgInRhc2siKSkgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwKICAgICAgICBzZWxlY3RlZCA9IGFzLmludGVnZXIocHJvZmlsZSA9PSBjaG9pY2UpLAogICAgICAgIHRhc2tfaWQgPSBwYXN0ZShJRCwgcGFydHlfbiwgdGFzaywgc2VwID0gIl8iKSwKICAgICAgICBwcm9maWxlX2lkID0gcGFzdGUoSUQsIHBhcnR5X24sIHRhc2ssIHByb2ZpbGUsIHNlcCA9ICJfIikKICAgICAgKSAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIElELCBwYXJ0eV9uLCB0YXNrLCBwcm9maWxlLCBjaG9pY2UsIHNlbGVjdGVkLAogICAgICAgIHRhc2tfaWQsIHByb2ZpbGVfaWQsIGF0dHJfdmFyLCBsZXZlbAogICAgICApICU+JQogICAgICBwaXZvdF93aWRlcigKICAgICAgICBuYW1lc19mcm9tID0gYXR0cl92YXIsCiAgICAgICAgdmFsdWVzX2Zyb20gPSBsZXZlbCwKICAgICAgICB2YWx1ZXNfZm4gPSBsaXN0KGxldmVsID0gfiBmaXJzdCgueCkpCiAgICAgICkKCiAgICBtaXNzaW5nX2F0dHIgPC0gc2V0ZGlmZihyZXF1aXJlZF9hdHRyX3ZhcnMsIG5hbWVzKHByb2ZpbGVfd2lkZSkpCgogICAgaWYgKGxlbmd0aChtaXNzaW5nX2F0dHIpID4gMCkgewogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgIH0KCiAgICBwcm9maWxlX3dpZGUgJT4lCiAgICAgIHNlbGVjdCgKICAgICAgICBJRCwgcGFydHlfbiwgdGFzaywgcHJvZmlsZSwgY2hvaWNlLCBzZWxlY3RlZCwKICAgICAgICB0YXNrX2lkLCBwcm9maWxlX2lkLAogICAgICAgIGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpCiAgICAgICkgJT4lCiAgICAgIGFycmFuZ2UoSUQsIHRhc2ssIHByb2ZpbGUpCiAgfQoKCiAgY29uam9pbnRfMiA8LSBtYWtlX3Byb2ZpbGVfbG9uZyhkZiwgMikKICBjb25qb2ludF8zIDwtIG1ha2VfcHJvZmlsZV9sb25nKGRmLCAzKQogIGNvbmpvaW50XzQgPC0gbWFrZV9wcm9maWxlX2xvbmcoZGYsIDQpCiAgY29uam9pbnRfNSA8LSBtYWtlX3Byb2ZpbGVfbG9uZyhkZiwgNSkKCiAgY29uam9pbnRfYWxsX3VuZmlsdGVyZWQgPC0gYmluZF9yb3dzKAogICAgY29uam9pbnRfMiwKICAgIGNvbmpvaW50XzMsCiAgICBjb25qb2ludF80LAogICAgY29uam9pbnRfNQogICkKCgogIGlkX3Rhc2tfY2hlY2sgPC0gY29uam9pbnRfYWxsX3VuZmlsdGVyZWQgJT4lCiAgICBncm91cF9ieShJRCwgcGFydHlfbiwgdGFzaykgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIG5fcHJvZmlsZXMgPSBuKCksCiAgICAgIHNlbGVjdGVkX3N1bSA9IHN1bShzZWxlY3RlZCksCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkgJT4lCiAgICBncm91cF9ieShJRCwgcGFydHlfbikgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIG5fdGFza3MgPSBuX2Rpc3RpbmN0KHRhc2spLAogICAgICBhbGxfdGFza3Nfb2sgPSBhbGwobl9wcm9maWxlcyA9PSBwYXJ0eV9uICYgc2VsZWN0ZWRfc3VtID09IDEpLAogICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICApCgogIGlmIChyZXF1aXJlX2FsbF9maXZlX3Rhc2tzKSB7CiAgICB2YWxpZF9pZHMgPC0gaWRfdGFza19jaGVjayAlPiUKICAgICAgZmlsdGVyKG5fdGFza3MgPT0gNSwgYWxsX3Rhc2tzX29rKQogIH0gZWxzZSB7CiAgICB2YWxpZF9pZHMgPC0gaWRfdGFza19jaGVjayAlPiUKICAgICAgZmlsdGVyKGFsbF90YXNrc19vaykKICB9CgogIGNvbmpvaW50X2FsbCA8LSBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCAlPiUKICAgIHNlbWlfam9pbih2YWxpZF9pZHMsIGJ5ID0gYygiSUQiLCAicGFydHlfbiIpKQoKICBuX2J5X3BhcnR5IDwtIHZhbGlkX2lkcyAlPiUKICAgIGNvdW50KHBhcnR5X24sIG5hbWUgPSAibiIpICU+JQogICAgY29tcGxldGUocGFydHlfbiA9IDI6NSwgZmlsbCA9IGxpc3QobiA9IDApKSAlPiUKICAgIGFycmFuZ2UocGFydHlfbikKCiAgbl90b3RhbCA8LSB2YWxpZF9pZHMgJT4lCiAgICBzdW1tYXJpc2UobiA9IG5fZGlzdGluY3QoSUQpKSAlPiUKICAgIHB1bGwobikKCiAgZmlndXJlX25fbGFiZWxzIDwtIGJpbmRfcm93cygKICAgIHRpYmJsZSgKICAgICAgcG9zaXRpb24gPSAi5YWo44K144Oz44OX44OrIiwKICAgICAgbGFiZWwgPSBwYXN0ZTAoIuWFqOOCteODs+ODl+ODqywgbj0iLCBzY2FsZXM6OmNvbW1hKG5fdG90YWwpKQogICAgKSwKICAgIG5fYnlfcGFydHkgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBwb3NpdGlvbiA9IHBhc3RlMChwYXJ0eV9uLCAi5pS/5YWa6YG45oqeIiksCiAgICAgICAgbGFiZWwgPSBwYXN0ZTAoIm49Iiwgc2NhbGVzOjpjb21tYShuKSkKICAgICAgKSAlPiUKICAgICAgc2VsZWN0KHBvc2l0aW9uLCBsYWJlbCkKICApCgogIHNhbXBsZV9mbG93IDwtIGJpbmRfcm93cygKICAgIHNhbXBsZV9mbG93LAogICAgdGliYmxlKAogICAgICBzdGFnZSA9ICLlrozlhajjgao16Kqy6aGM44KS44KC44Gk5YiG5p6Q5a++6LGh6ICFIiwKICAgICAgbiA9IG5fdG90YWwKICAgICkKICApCgogIGNhdCgiXG7liIbmnpDlr77osaHogIXmlbBcbiIpCiAgcHJpbnQobl9ieV9wYXJ0eSkKICBjYXQoIuWFqOOCteODs+ODl+ODqyBuPSIsIG5fdG90YWwsICJcbiIsIHNlcCA9ICIiKQoKICB3cml0ZV9jc3Zfc2FmZWx5KHNhbXBsZV9mbG93LCAic2FtcGxlX2Zsb3cuY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KGlkX3Rhc2tfY2hlY2ssICJpZF90YXNrX2NoZWNrLmNzdiIpCiAgd3JpdGVfY3N2X3NhZmVseSh2YWxpZF9pZHMsICJ2YWxpZF9pZHMuY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KG5fYnlfcGFydHksICJuX2J5X3BhcnR5LmNzdiIpCiAgd3JpdGVfY3N2X3NhZmVseShmaWd1cmVfbl9sYWJlbHMsICJmaWd1cmVfbl9sYWJlbHMuY3N2IikKCgogIGNoZWNrX3Byb2ZpbGUgPC0gY29uam9pbnRfYWxsICU+JQogICAgZ3JvdXBfYnkocGFydHlfbiwgSUQsIHRhc2ssIHRhc2tfaWQpICU+JQogICAgc3VtbWFyaXNlKAogICAgICBuX3Byb2ZpbGVzID0gbigpLAogICAgICBzZWxlY3RlZF9zdW0gPSBzdW0oc2VsZWN0ZWQpLAogICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICApICU+JQogICAgY291bnQocGFydHlfbiwgbl9wcm9maWxlcywgc2VsZWN0ZWRfc3VtKQoKICBwcmludChjaGVja19wcm9maWxlKQogIHN0b3BpZm5vdChhbGwoY2hlY2tfcHJvZmlsZSRuX3Byb2ZpbGVzID09IGNoZWNrX3Byb2ZpbGUkcGFydHlfbikpCiAgc3RvcGlmbm90KGFsbChjaGVja19wcm9maWxlJHNlbGVjdGVkX3N1bSA9PSAxKSkKCiAgYWxsb3dlZF9kZiA8LSBlbmZyYW1lKGFsbG93ZWRfbGV2ZWxzLCBuYW1lID0gIm5hbWUiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JQogICAgdW5uZXN0KHZhbHVlKQoKICB1bmV4cGVjdGVkX3ZhbHVlcyA8LSBjb25qb2ludF9hbGwgJT4lCiAgICBzZWxlY3QoYWxsX29mKHJlcXVpcmVkX2F0dHJfdmFycykpICU+JQogICAgcGl2b3RfbG9uZ2VyKAogICAgICBjb2xzID0gZXZlcnl0aGluZygpLAogICAgICBuYW1lc190byA9ICJuYW1lIiwKICAgICAgdmFsdWVzX3RvID0gInZhbHVlIgogICAgKSAlPiUKICAgIGZpbHRlcighaXMubmEodmFsdWUpLCB2YWx1ZSAhPSAiIikgJT4lCiAgICBkaXN0aW5jdChuYW1lLCB2YWx1ZSkgJT4lCiAgICBhbnRpX2pvaW4oYWxsb3dlZF9kZiwgYnkgPSBjKCJuYW1lIiwgInZhbHVlIikpCgogIHByaW50KHVuZXhwZWN0ZWRfdmFsdWVzKQogIHN0b3BpZm5vdChucm93KHVuZXhwZWN0ZWRfdmFsdWVzKSA9PSAwKQoKICBvYnNlcnZlZF9sZXZlbHMgPC0gY29uam9pbnRfYWxsICU+JQogICAgc2VsZWN0KGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpKSAlPiUKICAgIHBpdm90X2xvbmdlcigKICAgICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwKICAgICAgdmFsdWVzX3RvID0gImxldmVsIgogICAgKSAlPiUKICAgIGRpc3RpbmN0KGF0dHJpYnV0ZSwgbGV2ZWwpICU+JQogICAgYXJyYW5nZShhdHRyaWJ1dGUsIGxldmVsKQoKICB3cml0ZV9jc3Zfc2FmZWx5KGNoZWNrX3Byb2ZpbGUsICJwcm9maWxlX2V4cGFuc2lvbl9jaGVjay5jc3YiKQogIHdyaXRlX2Nzdl9zYWZlbHkob2JzZXJ2ZWRfbGV2ZWxzLCAib2JzZXJ2ZWRfYXR0cmlidXRlX2xldmVscy5jc3YiKQogIHdyaXRlX2Nzdl9zYWZlbHkoY29uam9pbnRfYWxsLCAic3R1ZHkxX3Byb2ZpbGVfbGV2ZWxfZGF0YS5jc3YiKQoKCiAgaWYgKHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrKSB7CiAgICBpZiAoCiAgICAgIGlzLm5hKGF0dGVudGlvbl9jaGVja192YXIpIHx8CiAgICAgICAgIWF0dGVudGlvbl9jaGVja192YXIgJWluJSBuYW1lcyhkZikgfHwKICAgICAgICBpcy5uYShhdHRlbnRpb25fY2hlY2tfY29ycmVjdCkKICAgICkgewogICAgICBzdG9wKCJDaGVjayBhdHRlbnRpb24gaXRlbSIpCiAgICB9CiAgfQoKICBhdHRlbnRpb25fc3VtbWFyeSA8LSB0aWJibGUoCiAgICBub3RlID0gIjIwMjPlubTlhYPjgrPjg7zjg4njgafjga/ms6jmhI/jg4Hjgqfjg4Pjgq/jga7norrlrprlr77lv5zooajjgpLkvb/nlKjjgZfjgabjgYTjgarjgYTjgZ/jgoHjgIHmqJnmupbliIbmnpDjgafjga/pm4boqIjjgpLnnIHnlaXjgIIiCiAgKQoKICBtYW5pcHVsYXRpb25fc3VtbWFyeSA8LSB0aWJibGUoCiAgICBub3RlID0gIjIwMjPlubTlhYPjgrPjg7zjg4njgafjga/mlL/lhZrmlbDnorroqo3os6rllY/jga7norrlrprlr77lv5zooajjgpLkvb/nlKjjgZfjgabjgYTjgarjgYTjgZ/jgoHjgIHmqJnmupbliIbmnpDjgafjga/pm4boqIjjgpLnnIHnlaXjgIIiCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KGF0dGVudGlvbl9zdW1tYXJ5LCAiYXR0ZW50aW9uX2NoZWNrX3N1bW1hcnkuY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KG1hbmlwdWxhdGlvbl9zdW1tYXJ5LCAicGFydHlfbnVtYmVyX2NoZWNrX3N1bW1hcnkuY3N2IikKCgogIGNvbmpvaW50X2FsbF9tIDwtIGNvbmpvaW50X2FsbCAlPiUKICAgIG11dGF0ZSgKICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHNlbGVjdGVkKSwKICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAoKICAgICAgcG9saWN5X3Bvc2l0aW9uID0gZmFjdG9yKAogICAgICAgIHBvbGljeV9wb3NpdGlvbiwKICAgICAgICBsZXZlbHMgPSBjKCLkuK3pgZMiLCAi5Y+z5rS+44O75L+d5a6I55qEIiwgIuW3pua0vuODu+mdqeaWsOeahCIpCiAgICAgICksCgogICAgICBnb3Zlcm5tZW50X3N0YXR1cyA9IGZhY3RvcigKICAgICAgICBnb3Zlcm5tZW50X3N0YXR1cywKICAgICAgICBsZXZlbHMgPSBjKCLph47lhZoiLCAi5LiO5YWaIikKICAgICAgKSwKCiAgICAgIGdkcF9ncm93dGggPSBmYWN0b3IoCiAgICAgICAgZ2RwX2dyb3d0aCwKICAgICAgICBsZXZlbHMgPSBjKAogICAgICAgICAgIkdEUOaIkOmVt+eOh8KxMO+8hSIsCiAgICAgICAgICAiR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAgICAgICAiR0RQ5oiQ6ZW3546H44Oe44Kk44OK44K5Me+8hSIKICAgICAgICApCiAgICAgICksCgogICAgICBuaWtrZWkgPSBmYWN0b3IoCiAgICAgICAgbmlra2VpLAogICAgICAgIGxldmVscyA9IGMoCiAgICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIiwKICAgICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwKICAgICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIgogICAgICAgICkKICAgICAgKSwKCiAgICAgIHNlYXRzID0gZmFjdG9yKAogICAgICAgIHNlYXRzLAogICAgICAgIGxldmVscyA9IGMoIjEw5Lul5LiLIiwgIjEwfjQ5IiwgIjUwfjk5IiwgIjEwMH4xOTkiLCAiMjAw5Lul5LiKIikKICAgICAgKSwKCiAgICAgIGNwaSA9IGZhY3RvcigKICAgICAgICBjcGksCiAgICAgICAgbGV2ZWxzID0gYygKICAgICAgICAgICJDUEnliY3mnJ/mr5TCsTDjg53jgqTjg7Pjg4giLAogICAgICAgICAgIkNQSeWJjeacn+avlOODl+ODqeOCuTHjg53jgqTjg7Pjg4giLAogICAgICAgICAgIkNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giCiAgICAgICAgKQogICAgICApLAoKICAgICAgdW5lbXBsb3ltZW50ID0gZmFjdG9yKAogICAgICAgIHVuZW1wbG95bWVudCwKICAgICAgICBsZXZlbHMgPSBjKAogICAgICAgICAgIuWksealreeOh+WJjeacn+avlMKxMO+8hSIsCiAgICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+U44OX44Op44K5Me+8hSIsCiAgICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+U44Oe44Kk44OK44K5Me+8hSIKICAgICAgICApCiAgICAgICksCgogICAgICBwYXJ0eV9uX2YgPSBmYWN0b3IoCiAgICAgICAgYXMuY2hhcmFjdGVyKHBhcnR5X24pLAogICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKQogICAgICApCiAgICApCgogIGF0dHJfdGVybXMgPC0gYygKICAgICJwb2xpY3lfcG9zaXRpb24iLAogICAgImdvdmVybm1lbnRfc3RhdHVzIiwKICAgICJnZHBfZ3Jvd3RoIiwKICAgICJuaWtrZWkiLAogICAgInNlYXRzIiwKICAgICJjcGkiLAogICAgInVuZW1wbG95bWVudCIKICApCgoKICBmb3JtdWxhX25vY292IDwtIGFzLmZvcm11bGEoCiAgICBwYXN0ZSgic2VsZWN0ZWQgfiIsIHBhc3RlKGF0dHJfdGVybXMsIGNvbGxhcHNlID0gIiArICIpKQogICkKCiAgcnVuX2FtY2Vfbm9jb3YgPC0gZnVuY3Rpb24oZGF0KSB7CiAgICBmZW9scygKICAgICAgZm9ybXVsYV9ub2NvdiwKICAgICAgZGF0YSA9IGRhdCwKICAgICAgdmNvdiA9IH4gSUQKICAgICkKICB9CgogIG1vZGVsc19ieV9wYXJ0eV9uX25vY292IDwtIGNvbmpvaW50X2FsbF9tICU+JQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUKICAgIG1hcChydW5fYW1jZV9ub2NvdikKCiAgY2FwdHVyZS5vdXRwdXQoCiAgICBldGFibGUobW9kZWxzX2J5X3BhcnR5X25fbm9jb3YpLAogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAiYW1jZV9ub2Nvdl9tb2RlbHMudHh0IikKICApCgoKICBtX2ludGVyYWN0aW9uIDwtIGZlb2xzKAogICAgc2VsZWN0ZWQgfgogICAgICBwYXJ0eV9uX2YgKgogICAgICAoCiAgICAgICAgcG9saWN5X3Bvc2l0aW9uICsKICAgICAgICAgIGdvdmVybm1lbnRfc3RhdHVzICsKICAgICAgICAgIGdkcF9ncm93dGggKwogICAgICAgICAgbmlra2VpICsKICAgICAgICAgIHNlYXRzICsKICAgICAgICAgIGNwaSArCiAgICAgICAgICB1bmVtcGxveW1lbnQKICAgICAgKSwKICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwKICAgIHZjb3YgPSB+IElECiAgKQoKICBjYXB0dXJlLm91dHB1dCgKICAgIHN1bW1hcnkobV9pbnRlcmFjdGlvbiksCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJhbWNlX2ludGVyYWN0aW9uX21vZGVsLnR4dCIpCiAgKQoKCiAgdGlkeV9maXhlc3QgPC0gZnVuY3Rpb24obW9kZWwpIHsKICAgIGN0IDwtIGFzLmRhdGEuZnJhbWUoZml4ZXN0Ojpjb2VmdGFibGUobW9kZWwpKQogICAgY3QkdGVybSA8LSByb3duYW1lcyhjdCkKCiAgICBjdCAlPiUKICAgICAgYXNfdGliYmxlKCkgJT4lCiAgICAgIHJlbmFtZSgKICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlLAogICAgICAgIHN0ZC5lcnJvciA9IGBTdGQuIEVycm9yYCwKICAgICAgICBzdGF0aXN0aWMgPSBgdCB2YWx1ZWAsCiAgICAgICAgcC52YWx1ZSA9IGBQcig+fHR8KWAKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGNvbmYubG93ID0gZXN0aW1hdGUgLSAxLjk2ICogc3RkLmVycm9yLAogICAgICAgIGNvbmYuaGlnaCA9IGVzdGltYXRlICsgMS45NiAqIHN0ZC5lcnJvcgogICAgICApICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgdGVybSwgZXN0aW1hdGUsIHN0ZC5lcnJvciwgc3RhdGlzdGljLCBwLnZhbHVlLAogICAgICAgIGNvbmYubG93LCBjb25mLmhpZ2gKICAgICAgKQogIH0KCiAgdGVybV9sYWJlbHMgPC0gdHJpYmJsZSgKICAgIH50ZXJtLCB+YXR0cmlidXRlLCB+Y3VlX3R5cGUsIH5sYWJlbCwgfm9yZGVyLAoKICAgICJnb3Zlcm5tZW50X3N0YXR1c+S4juWFmiIsCiAgICAi5LiO5YWa77yP6YeO5YWaIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLkuI7lhZoiLCAxLAoKICAgICJwb2xpY3lfcG9zaXRpb27lj7PmtL7jg7vkv53lrojnmoQiLAogICAgIuaUv+etluS9jee9riIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi5Y+z5rS+44O75L+d5a6I55qEIiwgMiwKCiAgICAicG9saWN5X3Bvc2l0aW9u5bem5rS+44O76Z2p5paw55qEIiwKICAgICLmlL/nrZbkvY3nva4iLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuW3pua0vuODu+mdqeaWsOeahCIsIDMsCgogICAgInNlYXRzMTB+NDkiLAogICAgIuitsOW4reaVsCIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi6K2w5bit5pWw77yaMTDvvZ40OSIsIDQsCgogICAgInNlYXRzNTB+OTkiLAogICAgIuitsOW4reaVsCIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi6K2w5bit5pWw77yaNTDvvZ45OSIsIDUsCgogICAgInNlYXRzMTAwfjE5OSIsCiAgICAi6K2w5bit5pWwIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLorbDluK3mlbDvvJoxMDDvvZ4xOTkiLCA2LAoKICAgICJzZWF0czIwMOS7peS4iiIsCiAgICAi6K2w5bit5pWwIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLorbDluK3mlbDvvJoyMDDku6XkuIoiLCA3LAoKICAgICJnZHBfZ3Jvd3RoR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAiR0RQ5oiQ6ZW3546HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICJHRFDvvJrjg5fjg6njgrkx77yFIiwgOCwKCiAgICAiZ2RwX2dyb3d0aEdEUOaIkOmVt+eOh+ODnuOCpOODiuOCuTHvvIUiLAogICAgIkdEUOaIkOmVt+eOhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAiR0RQ77ya44Oe44Kk44OK44K5Me+8hSIsIDksCgogICAgIm5pa2tlaeaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLAogICAgIuaXpee1jOW5s+WdhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAi5pel57WM5bmz5Z2H77ya44OX44Op44K5MTAwMOWGhiIsIDEwLAoKICAgICJuaWtrZWnml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIiwKICAgICLml6XntYzlubPlnYciLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIuaXpee1jOW5s+Wdh++8muODnuOCpOODiuOCuTEwMDDlhoYiLCAxMSwKCiAgICAiY3BpQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsCiAgICAiQ1BJIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICJDUEnvvJrjg5fjg6njgrkx44Od44Kk44Oz44OIIiwgMTIsCgogICAgImNwaUNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giLAogICAgIkNQSSIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAiQ1BJ77ya44Oe44Kk44OK44K5MeODneOCpOODs+ODiCIsIDEzLAoKICAgICJ1bmVtcGxveW1lbnTlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwKICAgICLlpLHmpa3njociLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIuWksealreeOh++8muODl+ODqeOCuTHvvIUiLCAxNCwKCiAgICAidW5lbXBsb3ltZW505aSx5qWt546H5YmN5pyf5q+U44Oe44Kk44OK44K5Me+8hSIsCiAgICAi5aSx5qWt546HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICLlpLHmpa3njofvvJrjg57jgqTjg4rjgrkx77yFIiwgMTUKICApCgogIGF0dHJpYnV0ZV9vcmRlciA8LSBjKAogICAgIuS4juWFmu+8j+mHjuWFmiIsCiAgICAi5pS/562W5L2N572uIiwKICAgICLorbDluK3mlbAiLAogICAgIkdEUOaIkOmVt+eOhyIsCiAgICAi5pel57WM5bmz5Z2HIiwKICAgICJDUEkiLAogICAgIuWksealreeOhyIKICApCgogIGxhYmVsX29yZGVyIDwtIHRlcm1fbGFiZWxzICU+JQogICAgYXJyYW5nZShvcmRlcikgJT4lCiAgICBwdWxsKGxhYmVsKQoKICBtYWtlX2FtY2VfcGxvdF9kZiA8LSBmdW5jdGlvbihtb2RlbHMpIHsKICAgIGltYXBfZGZyKAogICAgICBtb2RlbHMsCiAgICAgIH4gdGlkeV9maXhlc3QoLngpICU+JQogICAgICAgIG11dGF0ZShwYXJ0eV9uID0gYXMuY2hhcmFjdGVyKC55KSkKICAgICkgJT4lCiAgICAgIGxlZnRfam9pbih0ZXJtX2xhYmVscywgYnkgPSAidGVybSIpICU+JQogICAgICBmaWx0ZXIoIWlzLm5hKGF0dHJpYnV0ZSkpICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwKICAgICAgICBjb25mLmxvd19wcCA9IGNvbmYubG93ICogMTAwLAogICAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwKICAgICAgICBwYXJ0eV9uID0gZmFjdG9yKAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKSwKICAgICAgICAgIGxhYmVscyA9IGMoIjLmlL/lhZoiLCAiM+aUv+WFmiIsICI05pS/5YWaIiwgIjXmlL/lhZoiKQogICAgICAgICksCiAgICAgICAgYXR0cmlidXRlID0gZmFjdG9yKGF0dHJpYnV0ZSwgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyKSwKICAgICAgICBsYWJlbCA9IGZhY3RvcihsYWJlbCwgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKSkKICAgICAgKQogIH0KCiAgYW1jZV9wbG90X25vY292IDwtIG1ha2VfYW1jZV9wbG90X2RmKG1vZGVsc19ieV9wYXJ0eV9uX25vY292KQogIHdyaXRlX2Nzdl9zYWZlbHkoYW1jZV9wbG90X25vY292LCAiYW1jZV9ub2Nvdl9jb2VmZmljaWVudHMuY3N2IikKCiAgaW50ZXJhY3Rpb25fcGxvdF9kZiA8LSB0aWR5X2ZpeGVzdChtX2ludGVyYWN0aW9uKSAlPiUKICAgIGZpbHRlcihzdHJfZGV0ZWN0KHRlcm0sICJwYXJ0eV9uX2ZbMzQ1XSIpKSAlPiUKICAgIG11dGF0ZSgKICAgICAgcGFydHlfbl9jb2RlID0gc3RyX2V4dHJhY3QodGVybSwgInBhcnR5X25fZlszNDVdIiksCiAgICAgIHBhcnR5X24gPSBzdHJfcmVtb3ZlKHBhcnR5X25fY29kZSwgInBhcnR5X25fZiIpLAogICAgICBiYXNlX3Rlcm0gPSB0ZXJtICU+JQogICAgICAgIHN0cl9yZW1vdmUoInBhcnR5X25fZlszNDVdOiIpICU+JQogICAgICAgIHN0cl9yZW1vdmUoIjpwYXJ0eV9uX2ZbMzQ1XSIpCiAgICApICU+JQogICAgbGVmdF9qb2luKHRlcm1fbGFiZWxzLCBieSA9IGMoImJhc2VfdGVybSIgPSAidGVybSIpKSAlPiUKICAgIGZpbHRlcighaXMubmEoYXR0cmlidXRlKSkgJT4lCiAgICBtdXRhdGUoCiAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwKICAgICAgcGFydHlfbl9sYWJlbCA9IGZhY3RvcigKICAgICAgICBwYXJ0eV9uLAogICAgICAgIGxldmVscyA9IGMoIjMiLCAiNCIsICI1IiksCiAgICAgICAgbGFiZWxzID0gYygiM+aUv+WFmiIsICI05pS/5YWaIiwgIjXmlL/lhZoiKQogICAgICApLAogICAgICBhdHRyaWJ1dGUgPSBmYWN0b3IoYXR0cmlidXRlLCBsZXZlbHMgPSBhdHRyaWJ1dGVfb3JkZXIpLAogICAgICBsYWJlbCA9IGZhY3RvcihsYWJlbCwgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKSkKICAgICkKCiAgd3JpdGVfY3N2X3NhZmVseShpbnRlcmFjdGlvbl9wbG90X2RmLCAiYW1jZV9pbnRlcmFjdGlvbl9jb2VmZmljaWVudHMuY3N2IikKCgogIHJlY29kZV9mZW1hbGVfc3R1ZHkxIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHhfY2hyIDwtIG5vcm1fdGV4dCh4KQogICAgeF9udW0gPC0gYXNfbnVtKHhfY2hyKQoKICAgIGNhc2Vfd2hlbigKICAgICAgc3RyX2RldGVjdCh4X2NociwgIuWls+aApyIpIHwgeF9udW0gPT0gMSB+IDFMLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi55S35oCnIikgfCB4X251bSA9PSAyIH4gMEwsCiAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXwogICAgKQogIH0KCiAgcmVjb2RlX2NvbGxlZ2VfZ3JhZF9zdHVkeTEgPC0gZnVuY3Rpb24oeCkgewogICAgeF9jaHIgPC0gbm9ybV90ZXh0KHgpCiAgICB4X251bSA8LSBhc19udW0oeF9jaHIpCgogICAgY2FzZV93aGVuKAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAiNOW5tOWItuWkp+WtpnzvvJTlubTliLblpKflraZ85aSn5a2m6ZmiIikgfAogICAgICAgIHhfbnVtICVpbiUgYyg0LCA1KSB+IDFMLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi5bCP5a2m5qChfOmrmOagoXzpq5jnrYnlsILploB855+t5pyf5aSn5a2mfOWwguS/ruWtpuagoSIpIHwKICAgICAgICB4X251bSAlaW4lIGMoMSwgMiwgMykgfiAwTCwKICAgICAgVFJVRSB+IE5BX2ludGVnZXJfCiAgICApCiAgfQoKICByZWNvZGVfcGFydHlfc3VwcG9ydF9zdHVkeTEgPC0gZnVuY3Rpb24oeCkgewogICAgeF9jaHIgPC0gbm9ybV90ZXh0KHgpCiAgICB4X251bSA8LSBhc19udW0oeF9jaHIpCgogICAgY2FzZV93aGVuKAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi6Ieq55Sx5rCR5Li7fOiHquawkSIpIHwgeF9udW0gPT0gMSB+ICLoh6rnlLHmsJHkuLvlhZoiLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi56uL5oay5rCR5Li7IikgfCB4X251bSA9PSAyIH4gIueri+aGsuawkeS4u+WFmiIsCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLlhazmmI4iKSB8IHhfbnVtID09IDMgfiAi5YWs5piO5YWaIiwKICAgICAgc3RyX2RldGVjdCh4X2NociwgIue2reaWsCIpIHwgeF9udW0gPT0gNCB+ICLml6XmnKzntq3mlrDjga7kvJoiLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi5YWx55SjIikgfCB4X251bSA9PSA1IH4gIuaXpeacrOWFseeUo+WFmiIsCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLlm73msJHmsJHkuLsiKSB8IHhfbnVtID09IDYgfiAi5Zu95rCR5rCR5Li75YWaIiwKICAgICAgc3RyX2RldGVjdCh4X2NociwgIuekvuS8muawkeS4u3znpL7msJEiKSB8IHhfbnVtID09IDcgfiAi56S+5Lya5rCR5Li75YWaIiwKICAgICAgc3RyX2RldGVjdCh4X2NociwgIuOCjOOBhOOCjyIpIHwgeF9udW0gPT0gOCB+ICLjgozjgYTjgo/mlrDpgbjntYQiLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi44Gd44Gu5LuWIikgfCB4X251bSA9PSAxMSB+ICLjgZ3jga7ku5YiLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi5pSv5oyB44GZ44KL5pS/5YWa44Gv44Gq44GEfOaUr+aMgeaUv+WFmuOBquOBlyIpIHwKICAgICAgICB4X251bSA9PSAxMiB+ICLmlK/mjIHmlL/lhZrjgarjgZciLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi44KP44GL44KJ44Gq44GEIikgfCB4X251bSA9PSAxMyB+ICLjgo/jgYvjgonjgarjgYQiLAogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi562U44GI44Gq44GEfOOBk+OBn+OBiOOBquOBhCIpIHwgeF9udW0gPT0gMTQgfiAi562U44GI44Gq44GEIiwKICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8KICAgICkKICB9CgogIGdlbmRlcl9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygiUTIuMSIsICJRMl8xIiwgIlEyLjEuIiwgIuaAp+WIpSIsICJnZW5kZXIiLCAiR2VuZGVyIikKICApCgogIGFnZV9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygiUTIuMiIsICJRMl8yIiwgIlEyLjIuIiwgIuW5tOm9oiIsICJhZ2UiLCAiQWdlIikKICApCgogIGVkdWNhdGlvbl9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygKICAgICAgIlEyLjMiLCAiUTJfMyIsICJRMi4zLiIsCiAgICAgICLlrabmrbQiLCAi5pWZ6IKy5q20IiwgIuacgOe1guWtpuattCIsICJlZHVjYXRpb24iLCAiRWR1Y2F0aW9uIgogICAgKQogICkKCiAgcGFydHlfc3VwcG9ydF9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygiUTIuNCIsICJRMl80IiwgIlEyLjQuIiwgIuaUv+WFmuaUr+aMgSIsICLmlK/mjIHmlL/lhZoiLCAicGFydHlfc3VwcG9ydCIpCiAgKQoKICBpbmNvbWVfZ3Jvc3NfcmF3IDwtIGdldF92YXIoCiAgICBkZiwKICAgIGMoIlEzLjFfMSIsICJRMy4xLjEiLCAiUTNfMV8xIiwgIueojuW8leOBjeWJjeS4luW4r+W5tOWPjiIsICJpbmNvbWVfZ3Jvc3MiKQogICkKCiAgaW5jb21lX25ldF9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygiUTMuMV8yIiwgIlEzLjEuMiIsICJRM18xXzIiLCAi5omL5Y+W44KK44Gu5bm05Y+OIiwgImluY29tZV9uZXQiKQogICkKCiAgY292YXJfaWQgPC0gZGYgJT4lCiAgICB0cmFuc211dGUoCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKFJlc3BvbnNlSWQpLAogICAgICBmZW1hbGUgPSByZWNvZGVfZmVtYWxlX3N0dWR5MShnZW5kZXJfcmF3KSwKICAgICAgYWdlX3Jhd19udW0gPSBhc19udW0oYWdlX3JhdyksCiAgICAgIGNvbGxlZ2VfZ3JhZCA9IHJlY29kZV9jb2xsZWdlX2dyYWRfc3R1ZHkxKGVkdWNhdGlvbl9yYXcpLAogICAgICBwYXJ0eV9zdXBwb3J0ID0gcmVjb2RlX3BhcnR5X3N1cHBvcnRfc3R1ZHkxKHBhcnR5X3N1cHBvcnRfcmF3KSwKICAgICAgcGFydHlfc3VwcG9ydF9mID0gZmFjdG9yX21pc3MocGFydHlfc3VwcG9ydCksCiAgICAgIGluY29tZV9ncm9zcyA9IGFzX251bShpbmNvbWVfZ3Jvc3NfcmF3KSwKICAgICAgaW5jb21lX25ldCA9IGFzX251bShpbmNvbWVfbmV0X3JhdyksCiAgICAgIGluY29tZV9ncm9zc19sb2cgPSBsb2cxcChpbmNvbWVfZ3Jvc3MpLAogICAgICBpbmNvbWVfbmV0X2xvZyA9IGxvZzFwKGluY29tZV9uZXQpCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICBhZ2UgPSBjYXNlX3doZW4oCiAgICAgICAgIWlzLm5hKGFnZV9yYXdfbnVtKSAmIGFnZV9yYXdfbnVtID49IDE4ICYgYWdlX3Jhd19udW0gPD0gODAgfgogICAgICAgICAgYWdlX3Jhd19udW0sCiAgICAgICAgIWlzLm5hKGFnZV9yYXdfbnVtKSAmIGFnZV9yYXdfbnVtID49IDEgJiBhZ2VfcmF3X251bSA8PSA2MyB+CiAgICAgICAgICBhZ2VfcmF3X251bSArIDE3LAogICAgICAgIFRSVUUgfiBOQV9yZWFsXwogICAgICApCiAgICApICU+JQogICAgc2VtaV9qb2luKHZhbGlkX2lkcyAlPiUgc2VsZWN0KElEKSwgYnkgPSAiSUQiKSAlPiUKICAgIGRpc3RpbmN0KElELCAua2VlcF9hbGwgPSBUUlVFKQoKICBhZ2VfaW1wX29iaiA8LSBtZWFuX2ltcHV0ZShjb3Zhcl9pZCRhZ2UpCiAgaW5jb21lX2dyb3NzX2ltcF9vYmogPC0gbWVhbl9pbXB1dGUoY292YXJfaWQkaW5jb21lX2dyb3NzX2xvZykKCiAgY292YXJfaWQgPC0gY292YXJfaWQgJT4lCiAgICBtdXRhdGUoCiAgICAgIGZlbWFsZV9pbXAgPSBpZl9lbHNlKGlzLm5hKGZlbWFsZSksIDBMLCBmZW1hbGUpLAogICAgICBmZW1hbGVfbWlzcyA9IGFzLmludGVnZXIoaXMubmEoZmVtYWxlKSksCgogICAgICBjb2xsZWdlX2dyYWRfaW1wID0gaWZfZWxzZShpcy5uYShjb2xsZWdlX2dyYWQpLCAwTCwgY29sbGVnZV9ncmFkKSwKICAgICAgY29sbGVnZV9ncmFkX21pc3MgPSBhcy5pbnRlZ2VyKGlzLm5hKGNvbGxlZ2VfZ3JhZCkpLAoKICAgICAgYWdlX2ltcCA9IGFnZV9pbXBfb2JqJHZhbHVlLAogICAgICBhZ2VfbWlzcyA9IGFnZV9pbXBfb2JqJG1pc3MsCgogICAgICBpbmNvbWVfZ3Jvc3NfbG9nX2ltcCA9IGluY29tZV9ncm9zc19pbXBfb2JqJHZhbHVlLAogICAgICBpbmNvbWVfZ3Jvc3NfbG9nX21pc3MgPSBpbmNvbWVfZ3Jvc3NfaW1wX29iaiRtaXNzCiAgICApCgogIGNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnkgPC0gY292YXJfaWQgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIG5faWRzID0gbl9kaXN0aW5jdChJRCksCiAgICAgIGZlbWFsZV9taXNzaW5nID0gc3VtKGlzLm5hKGZlbWFsZSkpLAogICAgICBhZ2VfbWlzc2luZyA9IHN1bShpcy5uYShhZ2UpKSwKICAgICAgY29sbGVnZV9ncmFkX21pc3NpbmcgPSBzdW0oaXMubmEoY29sbGVnZV9ncmFkKSksCiAgICAgIGluY29tZV9ncm9zc19taXNzaW5nID0gc3VtKGlzLm5hKGluY29tZV9ncm9zc19sb2cpKSwKICAgICAgcGFydHlfc3VwcG9ydF9taXNzaW5nID0gc3VtKGlzLm5hKHBhcnR5X3N1cHBvcnQpKQogICAgKQoKICBwcmludChjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5KQogIHdyaXRlX2Nzdl9zYWZlbHkoY292YXJfaWQsICJyZXNwb25kZW50X2NvdmFyaWF0ZXMuY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KGNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnksICJjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5LmNzdiIpCgoKICBjb25qb2ludF9hbGxfY292IDwtIGNvbmpvaW50X2FsbF9tICU+JQogICAgbGVmdF9qb2luKGNvdmFyX2lkLCBieSA9ICJJRCIpCgogIGNvdmFyaWF0ZV90ZXJtcyA8LSBjKAogICAgImZlbWFsZV9pbXAiLAogICAgImZlbWFsZV9taXNzIiwKICAgICJhZ2VfaW1wIiwKICAgICJhZ2VfbWlzcyIsCiAgICAiaW5jb21lX2dyb3NzX2xvZ19pbXAiLAogICAgImluY29tZV9ncm9zc19sb2dfbWlzcyIsCiAgICAicGFydHlfc3VwcG9ydF9mIgogICkKCiAgaWYgKHVzZV9lZHVjYXRpb25fY292YXJpYXRlKSB7CiAgICBjb3ZhcmlhdGVfdGVybXMgPC0gYygKICAgICAgY292YXJpYXRlX3Rlcm1zLAogICAgICAiY29sbGVnZV9ncmFkX2ltcCIsCiAgICAgICJjb2xsZWdlX2dyYWRfbWlzcyIKICAgICkKICB9CgogIGhhc192YXJpYXRpb24gPC0gZnVuY3Rpb24oZGF0LCB2KSB7CiAgICBpZiAoIXYgJWluJSBuYW1lcyhkYXQpKSByZXR1cm4oRkFMU0UpCiAgICBkcGx5cjo6bl9kaXN0aW5jdChkYXRbW3ZdXSwgbmEucm0gPSBUUlVFKSA+IDEKICB9CgogIGNvdmFyaWF0ZV90ZXJtc191c2UgPC0gY292YXJpYXRlX3Rlcm1zWwogICAgbWFwX2xnbChjb3ZhcmlhdGVfdGVybXMsIH4gaGFzX3ZhcmlhdGlvbihjb25qb2ludF9hbGxfY292LCAueCkpCiAgXQoKICBmb3JtdWxhX2NvdiA8LSBhcy5mb3JtdWxhKAogICAgcGFzdGUoCiAgICAgICJzZWxlY3RlZCB+IiwKICAgICAgcGFzdGUoYyhhdHRyX3Rlcm1zLCBjb3ZhcmlhdGVfdGVybXNfdXNlKSwgY29sbGFwc2UgPSAiICsgIikKICAgICkKICApCgogIHJ1bl9hbWNlX2NvdiA8LSBmdW5jdGlvbihkYXQpIHsKICAgIGZlb2xzKAogICAgICBmb3JtdWxhX2NvdiwKICAgICAgZGF0YSA9IGRhdCwKICAgICAgdmNvdiA9IH4gSUQKICAgICkKICB9CgogIG1vZGVsc19ieV9wYXJ0eV9uX2NvdiA8LSBjb25qb2ludF9hbGxfY292ICU+JQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUKICAgIG1hcChydW5fYW1jZV9jb3YpCgogIGNhcHR1cmUub3V0cHV0KAogICAgZXRhYmxlKAogICAgICBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiwKICAgICAgbW9kZWxzX2J5X3BhcnR5X25fY292LAogICAgICBoZWFkZXJzID0gYygKICAgICAgICByZXAoIuWFseWkiemHj+OBquOBlyIsIGxlbmd0aChtb2RlbHNfYnlfcGFydHlfbl9ub2NvdikpLAogICAgICAgIHJlcCgi5YWx5aSJ6YeP44GC44KKIiwgbGVuZ3RoKG1vZGVsc19ieV9wYXJ0eV9uX2NvdikpCiAgICAgICkKICAgICksCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJhbWNlX25vY292X2FuZF9jb3ZfbW9kZWxzLnR4dCIpCiAgKQoKICBhbWNlX3Bsb3RfY292IDwtIG1ha2VfYW1jZV9wbG90X2RmKG1vZGVsc19ieV9wYXJ0eV9uX2NvdikKICB3cml0ZV9jc3Zfc2FmZWx5KGFtY2VfcGxvdF9jb3YsICJhbWNlX2Nvdl9jb2VmZmljaWVudHMuY3N2IikKCgogIHN0dWR5X2xhYmVsIDwtICLlrp/pqJMx77yIMjAyM+W5tO+8iSIKCiAgdGVybV9sYWJlbHNfZmFjZXQgPC0gdGVybV9sYWJlbHMgJT4lCiAgICBtdXRhdGUoCiAgICAgIGF0dHJpYnV0ZV9mYWNldCA9IGF0dHJpYnV0ZQogICAgKQoKICBhdHRyaWJ1dGVfb3JkZXJfZmFjZXQgPC0gYygKICAgICLkuI7lhZrvvI/ph47lhZoiLAogICAgIuaUv+etluS9jee9riIsCiAgICAi6K2w5bit5pWwIiwKICAgICJHRFDmiJDplbfnjociLAogICAgIuaXpee1jOW5s+WdhyIsCiAgICAiQ1BJIiwKICAgICLlpLHmpa3njociCiAgKQoKICBtYWtlX2FtY2VfZmFjZXRfZGYgPC0gZnVuY3Rpb24obW9kZWxzKSB7CiAgICBpbWFwX2RmcigKICAgICAgbW9kZWxzLAogICAgICB+IHRpZHlfZml4ZXN0KC54KSAlPiUKICAgICAgICBtdXRhdGUocGFydHlfbiA9IGFzLmNoYXJhY3RlcigueSkpCiAgICApICU+JQogICAgICBsZWZ0X2pvaW4odGVybV9sYWJlbHNfZmFjZXQsIGJ5ID0gInRlcm0iKSAlPiUKICAgICAgZmlsdGVyKCFpcy5uYShhdHRyaWJ1dGVfZmFjZXQpKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsCiAgICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwKICAgICAgICBjb25mLmhpZ2hfcHAgPSBjb25mLmhpZ2ggKiAxMDAsCiAgICAgICAgcGFydHlfbiA9IGZhY3RvcigKICAgICAgICAgIHBhcnR5X24sCiAgICAgICAgICBsZXZlbHMgPSBjKCIyIiwgIjMiLCAiNCIsICI1IiksCiAgICAgICAgICBsYWJlbHMgPSBjKCIy5pS/5YWaIiwgIjPmlL/lhZoiLCAiNOaUv+WFmiIsICI15pS/5YWaIikKICAgICAgICApLAogICAgICAgIGF0dHJpYnV0ZV9mYWNldCA9IGZhY3RvcigKICAgICAgICAgIGF0dHJpYnV0ZV9mYWNldCwKICAgICAgICAgIGxldmVscyA9IGF0dHJpYnV0ZV9vcmRlcl9mYWNldAogICAgICAgICksCiAgICAgICAgbGFiZWwgPSBmYWN0b3IoCiAgICAgICAgICBsYWJlbCwKICAgICAgICAgIGxldmVscyA9IHJldihsYWJlbF9vcmRlcikKICAgICAgICApCiAgICAgICkKICB9CgogIGFtY2VfcGxvdF9kZl9jb3ZfZmFjZXQgPC0gbWFrZV9hbWNlX2ZhY2V0X2RmKG1vZGVsc19ieV9wYXJ0eV9uX2NvdikKICBhbWNlX3Bsb3RfZGZfbm9jb3ZfZmFjZXQgPC0gbWFrZV9hbWNlX2ZhY2V0X2RmKG1vZGVsc19ieV9wYXJ0eV9uX25vY292KQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgYW1jZV9wbG90X2RmX2Nvdl9mYWNldCwKICAgICJhbWNlX2Nvdl9mYWNldF9jb2VmZmljaWVudHMuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIGFtY2VfcGxvdF9kZl9ub2Nvdl9mYWNldCwKICAgICJhbWNlX25vY292X2ZhY2V0X2NvZWZmaWNpZW50cy5jc3YiCiAgKQoKCiAgcF9hbWNlX2Nvdl9mYWNldCA8LSBnZ3Bsb3QoCiAgICBhbWNlX3Bsb3RfZGZfY292X2ZhY2V0LAogICAgYWVzKAogICAgICB4ID0gZXN0aW1hdGVfcHAsCiAgICAgIHkgPSBsYWJlbCwKICAgICAgc2hhcGUgPSBwYXJ0eV9uLAogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sCiAgICAgIGdyb3VwID0gcGFydHlfbgogICAgKQogICkgKwogICAgZ2VvbV92bGluZSgKICAgICAgeGludGVyY2VwdCA9IDAsCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsCiAgICAgIGNvbG9yID0gImdyZXkzNSIKICAgICkgKwogICAgZ2VvbV9lcnJvcmJhcmgoCiAgICAgIGFlcygKICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsCiAgICAgICAgeG1heCA9IGNvbmYuaGlnaF9wcAogICAgICApLAogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksCiAgICAgIGhlaWdodCA9IDAuMTYsCiAgICAgIGxpbmV3aWR0aCA9IDAuNTUsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBnZW9tX3BvaW50KAogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksCiAgICAgIHNpemUgPSAyLjUsCiAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgZmlsbCA9ICJ3aGl0ZSIsCiAgICAgIHN0cm9rZSA9IDAuOAogICAgKSArCiAgICBmYWNldF9ncmlkKAogICAgICBhdHRyaWJ1dGVfZmFjZXQgfiAuLAogICAgICBzY2FsZXMgPSAiZnJlZV95IiwKICAgICAgc3BhY2UgPSAiZnJlZV95IiwKICAgICAgc3dpdGNoID0gInkiCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgsICIgcHAiKSwKICAgICAgYnJlYWtzID0gc2VxKC0xMiwgMTIsIGJ5ID0gMikKICAgICkgKwogICAgc2NhbGVfc2hhcGVfbWFudWFsKAogICAgICBuYW1lID0gIuaUv+WFmuaVsOmBuOaKnuiCoiIsCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjLmlL/lhZoiID0gMTYsCiAgICAgICAgIjPmlL/lhZoiID0gMTcsCiAgICAgICAgIjTmlL/lhZoiID0gMTUsCiAgICAgICAgIjXmlL/lhZoiID0gMQogICAgICApCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgbmFtZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIy5pS/5YWaIiA9ICJzb2xpZCIsCiAgICAgICAgIjPmlL/lhZoiID0gImRhc2hlZCIsCiAgICAgICAgIjTmlL/lhZoiID0gImRvdHRlZCIsCiAgICAgICAgIjXmlL/lhZoiID0gImRvdGRhc2giCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgeCA9ICLpgbjmip7norrnjofjga7lpInljJYiLAogICAgICB5ID0gTlVMTAogICAgKSArCiAgICB0aGVtZV9idygKICAgICAgYmFzZV9zaXplID0gMTIsCiAgICAgIGJhc2VfZmFtaWx5ID0gIll1IEdvdGhpYyIKICAgICkgKwogICAgdGhlbWUoCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICBzaXplID0gMTYKICAgICAgKSwKICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgKICAgICAgICBmaWxsID0gImdyZXk5MiIsCiAgICAgICAgY29sb3IgPSAiZ3JleTU1IgogICAgICApLAogICAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBhbmdsZSA9IDAsCiAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICBzaXplID0gMTAKICAgICAgKSwKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikKICAgICkKCiAgcHJpbnQocF9hbWNlX2Nvdl9mYWNldCkKCiAgc2F2ZV9wbG90KAogICAgImFtY2VfY292X2ZhY2V0X21vZGVsLnBuZyIsCiAgICBwX2FtY2VfY292X2ZhY2V0LAogICAgd2lkdGggPSAxMC41LAogICAgaGVpZ2h0ID0gOC41CiAgKQoKICBwX2FtY2VfY292X21haW4gPC0gcF9hbWNlX2Nvdl9mYWNldAoKCiAgbWFrZV9oZWF0bWFwX2RmIDwtIGZ1bmN0aW9uKGFtY2VfcGxvdF9kZikgewogICAgaGVhdF9kZiA8LSBhbWNlX3Bsb3RfZGYgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBhYnNfYW1jZSA9IGFicyhlc3RpbWF0ZV9wcCksCiAgICAgICAgY3VlX3R5cGVfY29kZSA9IGNhc2Vfd2hlbigKICAgICAgICAgIGN1ZV90eXBlID09ICLmlL/lhZrjga7miYvjgYzjgYvjgooiIH4gInBhcnR5IiwKICAgICAgICAgIGN1ZV90eXBlID09ICLntYzmuIjjga7miYvjgYzjgYvjgooiIH4gImVjb25vbXkiLAogICAgICAgICAgVFJVRSB+ICJvdGhlciIKICAgICAgICApCiAgICAgICkgJT4lCiAgICAgIGdyb3VwX2J5KHBhcnR5X24pICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgcmFua193aXRoaW5fcGFydHkgPSBtaW5fcmFuayhkZXNjKGFic19hbWNlKSksCiAgICAgICAgbl9pbl9jb2wgPSBuKCksCiAgICAgICAgcmFua19zY29yZSA9IGlmX2Vsc2UoCiAgICAgICAgICBuX2luX2NvbCA9PSAxLAogICAgICAgICAgMSwKICAgICAgICAgIDEgLSAocmFua193aXRoaW5fcGFydHkgLSAxKSAvIChuX2luX2NvbCAtIDEpCiAgICAgICAgKQogICAgICApICU+JQogICAgICB1bmdyb3VwKCkKCiAgICByb3dfb3JkZXJfZGYgPC0gaGVhdF9kZiAlPiUKICAgICAgZ3JvdXBfYnkobGFiZWwsIGN1ZV90eXBlX2NvZGUpICU+JQogICAgICBzdW1tYXJpc2UoCiAgICAgICAgbWVhbl9hYnNfYW1jZSA9IG1lYW4oYWJzX2FtY2UsIG5hLnJtID0gVFJVRSksCiAgICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgICApICU+JQogICAgICBhcnJhbmdlKGRlc2MobWVhbl9hYnNfYW1jZSkpCgogICAgcm93X2xldmVscyA8LSBhcy5jaGFyYWN0ZXIocm93X29yZGVyX2RmJGxhYmVsKQoKICAgIGhlYXRfZGYgPC0gaGVhdF9kZiAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGxhYmVsID0gZmFjdG9yKAogICAgICAgICAgYXMuY2hhcmFjdGVyKGxhYmVsKSwKICAgICAgICAgIGxldmVscyA9IHJldihyb3dfbGV2ZWxzKQogICAgICAgICkKICAgICAgKQoKICAgIGxhYmVsX2NvbG9yX21hcCA8LSByb3dfb3JkZXJfZGYgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBsYWJlbF9tYXJrZG93biA9IGNhc2Vfd2hlbigKICAgICAgICAgIGN1ZV90eXBlX2NvZGUgPT0gInBhcnR5IiB+CiAgICAgICAgICAgIHBhc3RlMCgKICAgICAgICAgICAgICAiPHNwYW4gc3R5bGU9J2NvbG9yOiMxMTExMTE7Jz4iLAogICAgICAgICAgICAgIGxhYmVsLAogICAgICAgICAgICAgICI8L3NwYW4+IgogICAgICAgICAgICApLAogICAgICAgICAgY3VlX3R5cGVfY29kZSA9PSAiZWNvbm9teSIgfgogICAgICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAgICAgIjxzcGFuIHN0eWxlPSdjb2xvcjojOEE4QThBOyc+IiwKICAgICAgICAgICAgICBsYWJlbCwKICAgICAgICAgICAgICAiPC9zcGFuPiIKICAgICAgICAgICAgKSwKICAgICAgICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIobGFiZWwpCiAgICAgICAgKQogICAgICApCgogICAgbGFiZWxfbWFya2Rvd25fdmVjIDwtIHNldE5hbWVzKAogICAgICBsYWJlbF9jb2xvcl9tYXAkbGFiZWxfbWFya2Rvd24sCiAgICAgIGFzLmNoYXJhY3RlcihsYWJlbF9jb2xvcl9tYXAkbGFiZWwpCiAgICApCgogICAgbGlzdCgKICAgICAgaGVhdF9kZiA9IGhlYXRfZGYsCiAgICAgIGxhYmVsX21hcmtkb3duX3ZlYyA9IGxhYmVsX21hcmtkb3duX3ZlYwogICAgKQogIH0KCiAgcGxvdF9hbWNlX2hlYXRtYXAgPC0gZnVuY3Rpb24oCiAgICAgIGhlYXRfZGYsCiAgICAgIGxhYmVsX21hcmtkb3duX3ZlYywKICAgICAgd2l0aF9yYW5rID0gVFJVRSwKICAgICAgdGl0bGVfdGV4dCA9IE5VTEwpIHsKCiAgICBpZiAod2l0aF9yYW5rKSB7CiAgICAgIGhlYXRfZGYgPC0gaGVhdF9kZiAlPiUKICAgICAgICBtdXRhdGUoCiAgICAgICAgICBjZWxsX2xhYmVsID0gcGFzdGUwKAogICAgICAgICAgICBzcHJpbnRmKCIlLjFmIiwgZXN0aW1hdGVfcHApLAogICAgICAgICAgICAiXG4oIiwKICAgICAgICAgICAgcmFua193aXRoaW5fcGFydHksCiAgICAgICAgICAgICLkvY0pIgogICAgICAgICAgKQogICAgICAgICkKCiAgICAgIHRleHRfc2l6ZSA8LSAzLjAKICAgICAgbGluZWhlaWdodCA8LSAwLjkKICAgIH0gZWxzZSB7CiAgICAgIGhlYXRfZGYgPC0gaGVhdF9kZiAlPiUKICAgICAgICBtdXRhdGUoCiAgICAgICAgICBjZWxsX2xhYmVsID0gc3ByaW50ZigiJS4xZiIsIGVzdGltYXRlX3BwKQogICAgICAgICkKCiAgICAgIHRleHRfc2l6ZSA8LSAzLjQKICAgICAgbGluZWhlaWdodCA8LSAxLjAKICAgIH0KCiAgICBnZ3Bsb3QoCiAgICAgIGhlYXRfZGYsCiAgICAgIGFlcygKICAgICAgICB4ID0gcGFydHlfbiwKICAgICAgICB5ID0gbGFiZWwsCiAgICAgICAgZmlsbCA9IHJhbmtfc2NvcmUKICAgICAgKQogICAgKSArCiAgICAgIGdlb21fdGlsZSgKICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsCiAgICAgICAgbGluZXdpZHRoID0gMC43CiAgICAgICkgKwogICAgICBnZW9tX3RleHQoCiAgICAgICAgYWVzKGxhYmVsID0gY2VsbF9sYWJlbCksCiAgICAgICAgc2l6ZSA9IHRleHRfc2l6ZSwKICAgICAgICBmb250ZmFjZSA9ICJib2xkIiwKICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgbGluZWhlaWdodCA9IGxpbmVoZWlnaHQKICAgICAgKSArCiAgICAgIHNjYWxlX3lfZGlzY3JldGUoCiAgICAgICAgbGFiZWxzID0gbGFiZWxfbWFya2Rvd25fdmVjCiAgICAgICkgKwogICAgICBzY2FsZV9maWxsX2dyYWRpZW50KAogICAgICAgIGxvdyA9ICJncmV5OTUiLAogICAgICAgIGhpZ2ggPSAiZ3JleTE1IiwKICAgICAgICBsaW1pdHMgPSBjKDAsIDEpLAogICAgICAgIGJyZWFrcyA9IGMoMCwgMC4yNSwgMC41MCwgMC43NSwgMS4wMCksCiAgICAgICAgbGFiZWxzID0gYygi5L2OIiwgIiIsICIiLCAiIiwgIumrmCIpLAogICAgICAgIG5hbWUgPSAi5YiX5YaF6aCG5L2NXG7vvIjmv4PjgYTjgbvjganpq5jkvY3vvIkiCiAgICAgICkgKwogICAgICBsYWJzKAogICAgICAgIHRpdGxlID0gdGl0bGVfdGV4dCwKICAgICAgICB4ID0gIuaUv+WFmuaVsOmBuOaKnuiCoiIsCiAgICAgICAgeSA9IE5VTEwKICAgICAgKSArCiAgICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArCiAgICAgIHRoZW1lKAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsCiAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3RleHQ6OmVsZW1lbnRfbWFya2Rvd24oc2l6ZSA9IDkpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKQogICAgICApCiAgfQoKICBoZWF0bWFwX2lucHV0IDwtIG1ha2VfaGVhdG1hcF9kZihhbWNlX3Bsb3RfY292KQoKICBwX2hlYXRfYW1jZV9taXhlZCA8LSBwbG90X2FtY2VfaGVhdG1hcCgKICAgIGhlYXRtYXBfaW5wdXQkaGVhdF9kZiwKICAgIGhlYXRtYXBfaW5wdXQkbGFiZWxfbWFya2Rvd25fdmVjLAogICAgd2l0aF9yYW5rID0gRkFMU0UsCiAgICB0aXRsZV90ZXh0ID0gTlVMTAogICkKCiAgcHJpbnQocF9oZWF0X2FtY2VfbWl4ZWQpCgogIHNhdmVfcGxvdCgKICAgICJhbWNlX2hlYXRtYXBfbWl4ZWRfcmFua19jb2xvcmVkX2xhYmVscy5wbmciLAogICAgcF9oZWF0X2FtY2VfbWl4ZWQsCiAgICB3aWR0aCA9IDguOCwKICAgIGhlaWdodCA9IDguOAogICkKCiAgcF9oZWF0X2FtY2VfbWl4ZWRfcmFua2xhYmVsIDwtIHBsb3RfYW1jZV9oZWF0bWFwKAogICAgaGVhdG1hcF9pbnB1dCRoZWF0X2RmLAogICAgaGVhdG1hcF9pbnB1dCRsYWJlbF9tYXJrZG93bl92ZWMsCiAgICB3aXRoX3JhbmsgPSBUUlVFLAogICAgdGl0bGVfdGV4dCA9IE5VTEwKICApCgogIHByaW50KHBfaGVhdF9hbWNlX21peGVkX3JhbmtsYWJlbCkKCiAgc2F2ZV9wbG90KAogICAgImFtY2VfaGVhdG1hcF9taXhlZF9yYW5rX2NvbG9yZWRfbGFiZWxzX3dpdGhyYW5rLnBuZyIsCiAgICBwX2hlYXRfYW1jZV9taXhlZF9yYW5rbGFiZWwsCiAgICB3aWR0aCA9IDguOCwKICAgIGhlaWdodCA9IDguOAogICkKCiAgcF9oZWF0X2FtY2UgPC0gcF9oZWF0X2FtY2VfbWl4ZWQKICBwX2hlYXRfYW1jZV9yYW5rIDwtIHBfaGVhdF9hbWNlX21peGVkX3JhbmtsYWJlbAoKCiAgcF9hbWNlX2ZhY2V0X25vY292IDwtIGdncGxvdCgKICAgIGFtY2VfcGxvdF9kZl9ub2Nvdl9mYWNldCwKICAgIGFlcygKICAgICAgeCA9IGVzdGltYXRlX3BwLAogICAgICB5ID0gbGFiZWwsCiAgICAgIHNoYXBlID0gcGFydHlfbiwKICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uLAogICAgICBncm91cCA9IHBhcnR5X24KICAgICkKICApICsKICAgIGdlb21fdmxpbmUoCiAgICAgIHhpbnRlcmNlcHQgPSAwLAogICAgICBsaW5ld2lkdGggPSAwLjQ1LAogICAgICBjb2xvciA9ICJncmV5MzUiCiAgICApICsKICAgIGdlb21fZXJyb3JiYXJoKAogICAgICBhZXMoCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLAogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHAKICAgICAgKSwKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLAogICAgICBoZWlnaHQgPSAwLjE2LAogICAgICBsaW5ld2lkdGggPSAwLjU1LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9wb2ludCgKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLAogICAgICBzaXplID0gMi41LAogICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgIGZpbGwgPSAid2hpdGUiLAogICAgICBzdHJva2UgPSAwLjgKICAgICkgKwogICAgZmFjZXRfZ3JpZCgKICAgICAgYXR0cmlidXRlX2ZhY2V0IH4gLiwKICAgICAgc2NhbGVzID0gImZyZWVfeSIsCiAgICAgIHNwYWNlID0gImZyZWVfeSIsCiAgICAgIHN3aXRjaCA9ICJ5IgogICAgKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAiIHBwIiksCiAgICAgIGJyZWFrcyA9IHNlcSgtMTIsIDEyLCBieSA9IDIpCiAgICApICsKICAgIHNjYWxlX3NoYXBlX21hbnVhbCgKICAgICAgbmFtZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIy5pS/5YWaIiA9IDE2LAogICAgICAgICIz5pS/5YWaIiA9IDE3LAogICAgICAgICI05pS/5YWaIiA9IDE1LAogICAgICAgICI15pS/5YWaIiA9IDEKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIG5hbWUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIiwKICAgICAgdmFsdWVzID0gYygKICAgICAgICAiMuaUv+WFmiIgPSAic29saWQiLAogICAgICAgICIz5pS/5YWaIiA9ICJkYXNoZWQiLAogICAgICAgICI05pS/5YWaIiA9ICJkb3R0ZWQiLAogICAgICAgICI15pS/5YWaIiA9ICJkb3RkYXNoIgogICAgICApCiAgICApICsKICAgIGxhYnMoCiAgICAgIHggPSAi6YG45oqe56K6546H44Gu5aSJ5YyWIiwKICAgICAgeSA9IE5VTEwKICAgICkgKwogICAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpICsKICAgIHRoZW1lKAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDE2CiAgICAgICksCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLAogICAgICAgIGNvbG9yID0gImdyZXk1NSIKICAgICAgKSwKICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoCiAgICAgICAgYW5nbGUgPSAwLAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDEwCiAgICAgICksCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpCiAgICApCgogIHByaW50KHBfYW1jZV9mYWNldF9ub2NvdikKCiAgc2F2ZV9wbG90KAogICAgImFtY2VfZmFjZXRfbm9jb3YucG5nIiwKICAgIHBfYW1jZV9mYWNldF9ub2NvdiwKICAgIHdpZHRoID0gMTAuNSwKICAgIGhlaWdodCA9IDkKICApCgogIHBfYW1jZV9ub2Nvdl9hcHBlbmRpeCA8LSBwX2FtY2VfZmFjZXRfbm9jb3YKCgogIHBfaW50ZXJhY3Rpb24gPC0gZ2dwbG90KAogICAgaW50ZXJhY3Rpb25fcGxvdF9kZiwKICAgIGFlcygKICAgICAgeCA9IGVzdGltYXRlX3BwLAogICAgICB5ID0gbGFiZWwsCiAgICAgIHNoYXBlID0gcGFydHlfbl9sYWJlbCwKICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uX2xhYmVsLAogICAgICBncm91cCA9IHBhcnR5X25fbGFiZWwKICAgICkKICApICsKICAgIGdlb21fdmxpbmUoCiAgICAgIHhpbnRlcmNlcHQgPSAwLAogICAgICBsaW5ld2lkdGggPSAwLjQ1LAogICAgICBjb2xvciA9ICJncmV5MzUiCiAgICApICsKICAgIGdlb21fZXJyb3JiYXJoKAogICAgICBhZXMoCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLAogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHAKICAgICAgKSwKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLAogICAgICBoZWlnaHQgPSAwLjE2LAogICAgICBsaW5ld2lkdGggPSAwLjU1LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9wb2ludCgKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLAogICAgICBzaXplID0gMi41LAogICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgIGZpbGwgPSAid2hpdGUiLAogICAgICBzdHJva2UgPSAwLjgKICAgICkgKwogICAgZmFjZXRfZ3JpZCgKICAgICAgYXR0cmlidXRlIH4gLiwKICAgICAgc2NhbGVzID0gImZyZWVfeSIsCiAgICAgIHNwYWNlID0gImZyZWVfeSIsCiAgICAgIHN3aXRjaCA9ICJ5IgogICAgKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAiIHBwIiksCiAgICAgIGJyZWFrcyA9IHNlcSgtOCwgOCwgYnkgPSAyKQogICAgKSArCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoCiAgICAgIG5hbWUgPSAiMuaUv+WFmuOBruWgtOWQiOOBqOOBruavlOi8gyIsCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjPmlL/lhZoiID0gMTcsCiAgICAgICAgIjTmlL/lhZoiID0gMTUsCiAgICAgICAgIjXmlL/lhZoiID0gMQogICAgICApCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgbmFtZSA9ICIy5pS/5YWa44Gu5aC05ZCI44Go44Gu5q+U6LyDIiwKICAgICAgdmFsdWVzID0gYygKICAgICAgICAiM+aUv+WFmiIgPSAiZGFzaGVkIiwKICAgICAgICAiNOaUv+WFmiIgPSAiZG90dGVkIiwKICAgICAgICAiNeaUv+WFmiIgPSAiZG90ZGFzaCIKICAgICAgKQogICAgKSArCiAgICBsYWJzKAogICAgICB4ID0gIjLmlL/lhZrmnaHku7bjgajjga7lt64iLAogICAgICB5ID0gTlVMTAogICAgKSArCiAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikgKwogICAgdGhlbWUoCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICBzaXplID0gMTUKICAgICAgKSwKICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgKICAgICAgICBmaWxsID0gImdyZXk5MiIsCiAgICAgICAgY29sb3IgPSAiZ3JleTU1IgogICAgICApLAogICAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBhbmdsZSA9IDAsCiAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICBzaXplID0gMTAKICAgICAgKSwKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikKICAgICkKCiAgcHJpbnQocF9pbnRlcmFjdGlvbikKCiAgc2F2ZV9wbG90KAogICAgImFtY2VfaW50ZXJhY3Rpb25fZGlmZmVyZW5jZV9mcm9tXzJwYXJ0eS5wbmciLAogICAgcF9pbnRlcmFjdGlvbiwKICAgIHdpZHRoID0gMTAuNSwKICAgIGhlaWdodCA9IDkKICApCgoKICBjb25qb2ludF9jbG9naXQgPC0gY29uam9pbnRfYWxsX20gJT4lCiAgICBtdXRhdGUoCiAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihzZWxlY3RlZCksCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwKICAgICAgdGFza19pZCA9IGZhY3Rvcih0YXNrX2lkKSwKICAgICAgcG9saWN5X3Bvc2l0aW9uID0gcmVsZXZlbF9pZl9wcmVzZW50KAogICAgICAgIHBvbGljeV9wb3NpdGlvbiwKICAgICAgICAi5Lit6YGTIgogICAgICApLAogICAgICBnb3Zlcm5tZW50X3N0YXR1cyA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICBnb3Zlcm5tZW50X3N0YXR1cywKICAgICAgICAi6YeO5YWaIgogICAgICApLAogICAgICBnZHBfZ3Jvd3RoID0gcmVsZXZlbF9pZl9wcmVzZW50KAogICAgICAgIGdkcF9ncm93dGgsCiAgICAgICAgIkdEUOaIkOmVt+eOh8KxMO+8hSIKICAgICAgKSwKICAgICAgbmlra2VpID0gcmVsZXZlbF9pZl9wcmVzZW50KAogICAgICAgIG5pa2tlaSwKICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIgogICAgICApLAogICAgICBzZWF0cyA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICBzZWF0cywKICAgICAgICAiMTDku6XkuIsiCiAgICAgICksCiAgICAgIGNwaSA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICBjcGksCiAgICAgICAgIkNQSeWJjeacn+avlMKxMOODneOCpOODs+ODiCIKICAgICAgKSwKICAgICAgdW5lbXBsb3ltZW50ID0gcmVsZXZlbF9pZl9wcmVzZW50KAogICAgICAgIHVuZW1wbG95bWVudCwKICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+UwrEw77yFIgogICAgICApCiAgICApCgogIGZvcm11bGFfY2xvZ2l0X25vY292IDwtIGFzLmZvcm11bGEoCiAgICBwYXN0ZTAoCiAgICAgICJzZWxlY3RlZCB+ICIsCiAgICAgIHBhc3RlKGF0dHJfdGVybXMsIGNvbGxhcHNlID0gIiArICIpLAogICAgICAiICsgc3RyYXRhKHRhc2tfaWQpICsgY2x1c3RlcihJRCkiCiAgICApCiAgKQoKICBydW5fY2xvZ2l0X25vY292IDwtIGZ1bmN0aW9uKGRhdCkgewogICAgc3Vydml2YWw6OmNsb2dpdCgKICAgICAgZm9ybXVsYV9jbG9naXRfbm9jb3YsCiAgICAgIGRhdGEgPSBkYXQsCiAgICAgIG1ldGhvZCA9ICJlZnJvbiIKICAgICkKICB9CgogIG1vZGVsc19jbG9naXRfbm9jb3YgPC0gY29uam9pbnRfY2xvZ2l0ICU+JQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUKICAgIG1hcChydW5fY2xvZ2l0X25vY292KQoKICBjYXB0dXJlLm91dHB1dCgKICAgIGxhcHBseShtb2RlbHNfY2xvZ2l0X25vY292LCBzdW1tYXJ5KSwKICAgIGZpbGUgPSBmaWxlLnBhdGgoCiAgICAgIG91dHB1dF9kaXIsCiAgICAgICJjb25kaXRpb25hbF9sb2dpdF9tb2RlbHMudHh0IgogICAgKQogICkKCiAgdGlkeV9jbG9naXQgPC0gZnVuY3Rpb24obW9kZWwpIHsKICAgIHMgPC0gc3VtbWFyeShtb2RlbCkKICAgIGN0IDwtIGFzLmRhdGEuZnJhbWUocyRjb2VmZmljaWVudHMpCiAgICBjdCR0ZXJtIDwtIHJvd25hbWVzKGN0KQoKICAgIHNlX2NvbCA8LSBpZiAoInJvYnVzdCBzZSIgJWluJSBuYW1lcyhjdCkpIHsKICAgICAgInJvYnVzdCBzZSIKICAgIH0gZWxzZSBpZiAoInNlKGNvZWYpIiAlaW4lIG5hbWVzKGN0KSkgewogICAgICAic2UoY29lZikiCiAgICB9IGVsc2UgewogICAgICBzdG9wKCJDaGVjayBjbG9naXQiKQogICAgfQoKICAgIHBfY29sIDwtIGlmICgiUHIoPnx6fCkiICVpbiUgbmFtZXMoY3QpKSB7CiAgICAgICJQcig+fHp8KSIKICAgIH0gZWxzZSBpZiAoIlByKD58dHwpIiAlaW4lIG5hbWVzKGN0KSkgewogICAgICAiUHIoPnx0fCkiCiAgICB9IGVsc2UgewogICAgICBOQV9jaGFyYWN0ZXJfCiAgICB9CgogICAgY3QgJT4lCiAgICAgIGFzX3RpYmJsZSgpICU+JQogICAgICB0cmFuc211dGUoCiAgICAgICAgdGVybSA9IHRlcm0sCiAgICAgICAgZXN0aW1hdGUgPSBjb2VmLAogICAgICAgIHN0ZC5lcnJvciA9IC5kYXRhW1tzZV9jb2xdXSwKICAgICAgICBwLnZhbHVlID0gaWYgKCFpcy5uYShwX2NvbCkpIHsKICAgICAgICAgIC5kYXRhW1twX2NvbF1dCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIE5BX3JlYWxfCiAgICAgICAgfSwKICAgICAgICBjb25mLmxvdyA9IGVzdGltYXRlIC0gMS45NiAqIHN0ZC5lcnJvciwKICAgICAgICBjb25mLmhpZ2ggPSBlc3RpbWF0ZSArIDEuOTYgKiBzdGQuZXJyb3IsCiAgICAgICAgb2Rkc19yYXRpbyA9IGV4cChlc3RpbWF0ZSksCiAgICAgICAgb2Rkc19yYXRpb19sb3cgPSBleHAoY29uZi5sb3cpLAogICAgICAgIG9kZHNfcmF0aW9faGlnaCA9IGV4cChjb25mLmhpZ2gpCiAgICAgICkKICB9CgogIGNsb2dpdF9wbG90X2RmIDwtIGltYXBfZGZyKAogICAgbW9kZWxzX2Nsb2dpdF9ub2NvdiwKICAgIH4gdGlkeV9jbG9naXQoLngpICU+JQogICAgICBtdXRhdGUocGFydHlfbiA9IGFzLmNoYXJhY3RlcigueSkpCiAgKSAlPiUKICAgIGxlZnRfam9pbih0ZXJtX2xhYmVscywgYnkgPSAidGVybSIpICU+JQogICAgZmlsdGVyKCFpcy5uYShhdHRyaWJ1dGUpKSAlPiUKICAgIG11dGF0ZSgKICAgICAgcGFydHlfbiA9IGZhY3RvcigKICAgICAgICBwYXJ0eV9uLAogICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKSwKICAgICAgICBsYWJlbHMgPSBjKCIy5pS/5YWaIiwgIjPmlL/lhZoiLCAiNOaUv+WFmiIsICI15pS/5YWaIikKICAgICAgKSwKICAgICAgbGFiZWwgPSBmYWN0b3IoCiAgICAgICAgbGFiZWwsCiAgICAgICAgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKQogICAgICApCiAgICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICBjbG9naXRfcGxvdF9kZiwKICAgICJjb25kaXRpb25hbF9sb2dpdF9jb2VmZmljaWVudHMuY3N2IgogICkKCgogIHBfY2xvZ2l0X29yIDwtIGdncGxvdCgKICAgIGNsb2dpdF9wbG90X2RmLAogICAgYWVzKAogICAgICB4ID0gb2Rkc19yYXRpbywKICAgICAgeSA9IGxhYmVsLAogICAgICBzaGFwZSA9IHBhcnR5X24sCiAgICAgIGxpbmV0eXBlID0gcGFydHlfbiwKICAgICAgZ3JvdXAgPSBwYXJ0eV9uCiAgICApCiAgKSArCiAgICBnZW9tX3ZsaW5lKAogICAgICB4aW50ZXJjZXB0ID0gMSwKICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgICAgbGluZXdpZHRoID0gMC40NSwKICAgICAgY29sb3IgPSAiZ3JleTM1IgogICAgKSArCiAgICBnZW9tX2Vycm9yYmFyaCgKICAgICAgYWVzKAogICAgICAgIHhtaW4gPSBvZGRzX3JhdGlvX2xvdywKICAgICAgICB4bWF4ID0gb2Rkc19yYXRpb19oaWdoCiAgICAgICksCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcyKSwKICAgICAgaGVpZ2h0ID0gMC4xNSwKICAgICAgbGluZXdpZHRoID0gMC40NSwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fcG9pbnQoCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcyKSwKICAgICAgc2l6ZSA9IDIuNCwKICAgICAgc3Ryb2tlID0gMC43LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgc2NhbGVfeF9sb2cxMCgKICAgICAgYnJlYWtzID0gYygKICAgICAgICAwLjYsCiAgICAgICAgMC44LAogICAgICAgIDEuMCwKICAgICAgICAxLjI1LAogICAgICAgIDEuNSwKICAgICAgICAyLjAKICAgICAgKSwKICAgICAgbGFiZWxzID0gYygKICAgICAgICAiMC42IiwKICAgICAgICAiMC44IiwKICAgICAgICAiMS4wIiwKICAgICAgICAiMS4yNSIsCiAgICAgICAgIjEuNSIsCiAgICAgICAgIjIuMCIKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjLmlL/lhZoiID0gMTYsCiAgICAgICAgIjPmlL/lhZoiID0gMTcsCiAgICAgICAgIjTmlL/lhZoiID0gMTUsCiAgICAgICAgIjXmlL/lhZoiID0gMQogICAgICApCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgdmFsdWVzID0gYygKICAgICAgICAiMuaUv+WFmiIgPSAic29saWQiLAogICAgICAgICIz5pS/5YWaIiA9ICJkYXNoZWQiLAogICAgICAgICI05pS/5YWaIiA9ICJkb3RkYXNoIiwKICAgICAgICAiNeaUv+WFmiIgPSAidHdvZGFzaCIKICAgICAgKQogICAgKSArCiAgICBsYWJzKAogICAgICB4ID0gIuOCquODg+OCuuavlCIsCiAgICAgIHkgPSBOVUxMLAogICAgICBzaGFwZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLAogICAgICBsaW5ldHlwZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiCiAgICApICsKICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArCiAgICB0aGVtZSgKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpCiAgICApCgogIHByaW50KHBfY2xvZ2l0X29yKQoKICBzYXZlX3Bsb3QoCiAgICAiY2xvZ2l0X29kZHNyYXRpb19ub2Nvdi5wbmciLAogICAgcF9jbG9naXRfb3IsCiAgICB3aWR0aCA9IDEwLjUsCiAgICBoZWlnaHQgPSA4LjUKICApCgoKICByZWxhdGl2ZV9jdWVfbWFwIDwtIGMoCiAgICBwb2xpY3lfcG9zaXRpb24gPSAicGFydHkiLAogICAgZ292ZXJubWVudF9zdGF0dXMgPSAicGFydHkiLAogICAgc2VhdHMgPSAicGFydHkiLAogICAgZ2RwX2dyb3d0aCA9ICJlY29ub21pYyIsCiAgICBuaWtrZWkgPSAiZWNvbm9taWMiLAogICAgY3BpID0gImVjb25vbWljIiwKICAgIHVuZW1wbG95bWVudCA9ICJlY29ub21pYyIKICApCgogIG1lYW5fYWJzb2x1dGVfcGFpcndpc2VfZGlmZmVyZW5jZSA8LSBmdW5jdGlvbih4KSB7CiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXQoKICAgIGlmIChsZW5ndGgoeCkgPCAyKSB7CiAgICAgIHJldHVybihOQV9yZWFsXykKICAgIH0KCiAgICBwYWlyd2lzZV9kaWZmZXJlbmNlcyA8LSBjb21ibigKICAgICAgeCwKICAgICAgMiwKICAgICAgRlVOID0gZnVuY3Rpb24oeikgYWJzKHpbMV0gLSB6WzJdKQogICAgKQoKICAgIG1lYW4ocGFpcndpc2VfZGlmZmVyZW5jZXMpCiAgfQoKICBsaW5lYXJfc2xvcGUgPC0gZnVuY3Rpb24oeSwgeCkgewogICAga2VlcCA8LSBpcy5maW5pdGUoeSkgJiBpcy5maW5pdGUoeCkKICAgIHkgPC0geVtrZWVwXQogICAgeCA8LSB4W2tlZXBdCgogICAgaWYgKGxlbmd0aCh5KSA8IDIgfHwgbGVuZ3RoKHVuaXF1ZSh4KSkgPCAyKSB7CiAgICAgIHJldHVybihOQV9yZWFsXykKICAgIH0KCiAgICB1bm5hbWUoY29lZihsbSh5IH4geCkpWzJdKQogIH0KCiAgYm9vdHN0cmFwX3R3b19zaWRlZF9wIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHggPC0geFtpcy5maW5pdGUoeCldCiAgICBCX3ZhbGlkIDwtIGxlbmd0aCh4KQoKICAgIGlmIChCX3ZhbGlkID09IDApIHsKICAgICAgcmV0dXJuKE5BX3JlYWxfKQogICAgfQoKICAgIHBfbG93ZXIgPC0gKDEgKyBzdW0oeCA8PSAwKSkgLyAoQl92YWxpZCArIDEpCiAgICBwX3VwcGVyIDwtICgxICsgc3VtKHggPj0gMCkpIC8gKEJfdmFsaWQgKyAxKQoKICAgIG1pbigxLCAyICogbWluKHBfbG93ZXIsIHBfdXBwZXIpKQogIH0KCiAgc2FmZV9xdWFudGlsZSA8LSBmdW5jdGlvbih4LCBwcm9iYWJpbGl0eSkgewogICAgeCA8LSB4W2lzLmZpbml0ZSh4KV0KCiAgICBpZiAobGVuZ3RoKHgpID09IDApIHsKICAgICAgcmV0dXJuKE5BX3JlYWxfKQogICAgfQoKICAgIHVubmFtZSgKICAgICAgcXVhbnRpbGUoCiAgICAgICAgeCwKICAgICAgICBwcm9icyA9IHByb2JhYmlsaXR5LAogICAgICAgIHR5cGUgPSA2LAogICAgICAgIG5hLnJtID0gVFJVRQogICAgICApCiAgICApCiAgfQoKICBwcmVwYXJlX3JlbGF0aXZlX2N1ZV9hbmFseXNpcyA8LSBmdW5jdGlvbihkYXRhLCBjdWVfbWFwKSB7CiAgICBhdHRyaWJ1dGVzIDwtIG5hbWVzKGN1ZV9tYXApCgogICAgcmVxdWlyZWRfY29sdW1ucyA8LSBjKAogICAgICAiSUQiLAogICAgICAicGFydHlfbiIsCiAgICAgICJzZWxlY3RlZCIsCiAgICAgIGF0dHJpYnV0ZXMKICAgICkKCiAgICBtaXNzaW5nX2NvbHVtbnMgPC0gc2V0ZGlmZigKICAgICAgcmVxdWlyZWRfY29sdW1ucywKICAgICAgbmFtZXMoZGF0YSkKICAgICkKCiAgICBpZiAobGVuZ3RoKG1pc3NpbmdfY29sdW1ucykgPiAwKSB7CiAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpCiAgICB9CgogICAgaWYgKCFhbGwodW5uYW1lKGN1ZV9tYXApICVpbiUgYygicGFydHkiLCAiZWNvbm9taWMiKSkpIHsKICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikKICAgIH0KCiAgICBhbmFseXNpc19kYXRhIDwtIGRhdGEgJT4lCiAgICAgIHNlbGVjdCgKICAgICAgICBJRCwKICAgICAgICBwYXJ0eV9uLAogICAgICAgIHNlbGVjdGVkLAogICAgICAgIGFsbF9vZihhdHRyaWJ1dGVzKQogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSksCiAgICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHNlbGVjdGVkKSwKICAgICAgICBhY3Jvc3MoCiAgICAgICAgICBhbGxfb2YoYXR0cmlidXRlcyksCiAgICAgICAgICBhcy5jaGFyYWN0ZXIKICAgICAgICApCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICAhaXMubmEoSUQpLAogICAgICAgIHBhcnR5X24gJWluJSAyOjUsCiAgICAgICAgc2VsZWN0ZWQgJWluJSBjKDBMLCAxTCkKICAgICAgKQoKICAgIG9ic2VydmVkX2NvbmRpdGlvbnMgPC0gc29ydCgKICAgICAgdW5pcXVlKGFuYWx5c2lzX2RhdGEkcGFydHlfbikKICAgICkKCiAgICBpZiAoIWlkZW50aWNhbChvYnNlcnZlZF9jb25kaXRpb25zLCAyOjUpKSB7CiAgICAgIHN0b3AoIkNoZWNrIikKICAgIH0KCiAgICBsb25nX2RhdGEgPC0gYW5hbHlzaXNfZGF0YSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBhbGxfb2YoYXR0cmlidXRlcyksCiAgICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwKICAgICAgICB2YWx1ZXNfdG8gPSAibGV2ZWwiCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICAhaXMubmEobGV2ZWwpLAogICAgICAgIGxldmVsICE9ICIiCiAgICAgICkKCiAgICBleHBlY3RlZF9jZWxscyA8LSBsb25nX2RhdGEgJT4lCiAgICAgIGRpc3RpbmN0KAogICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICBsZXZlbAogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgYXR0cmlidXRlX29yZGVyID0gbWF0Y2goCiAgICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgICBhdHRyaWJ1dGVzCiAgICAgICAgKQogICAgICApICU+JQogICAgICBhcnJhbmdlKAogICAgICAgIGF0dHJpYnV0ZV9vcmRlciwKICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgbGV2ZWwKICAgICAgKSAlPiUKICAgICAgc2VsZWN0KC1hdHRyaWJ1dGVfb3JkZXIpICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgY2VsbF9rZXkgPSBwYXN0ZSgKICAgICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICAgIGxldmVsLAogICAgICAgICAgc2VwID0gIlxyIgogICAgICAgICkKICAgICAgKQoKICAgIHJlc3BvbmRlbnRfY2VsbCA8LSBsb25nX2RhdGEgJT4lCiAgICAgIGdyb3VwX2J5KAogICAgICAgIHBhcnR5X24sCiAgICAgICAgSUQsCiAgICAgICAgYXR0cmlidXRlLAogICAgICAgIGxldmVsCiAgICAgICkgJT4lCiAgICAgIHN1bW1hcmlzZSgKICAgICAgICB5X3N1bSA9IHN1bShzZWxlY3RlZCksCiAgICAgICAgbl9vYnMgPSBuKCksCiAgICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgY2VsbF9rZXkgPSBwYXN0ZSgKICAgICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICAgIGxldmVsLAogICAgICAgICAgc2VwID0gIlxyIgogICAgICAgICkKICAgICAgKQoKICAgIGNvbmRpdGlvbl9vYmplY3RzIDwtIGxhcHBseSgKICAgICAgMjo1LAogICAgICBmdW5jdGlvbihuX3ZhbHVlKSB7CiAgICAgICAgY29uZGl0aW9uX2RhdGEgPC0gcmVzcG9uZGVudF9jZWxsICU+JQogICAgICAgICAgZmlsdGVyKAogICAgICAgICAgICBwYXJ0eV9uID09IG5fdmFsdWUKICAgICAgICAgICkKCiAgICAgICAgaWRfdmFsdWVzIDwtIHNvcnQoCiAgICAgICAgICB1bmlxdWUoY29uZGl0aW9uX2RhdGEkSUQpCiAgICAgICAgKQogICAgICAgIG5faWRzIDwtIGxlbmd0aChpZF92YWx1ZXMpCiAgICAgICAgbl9jZWxscyA8LSBucm93KGV4cGVjdGVkX2NlbGxzKQoKICAgICAgICBpZiAobl9pZHMgPT0gMCkgewogICAgICAgICAgc3RvcCgiQ2hlY2siKQogICAgICAgIH0KCiAgICAgICAgeV9tYXRyaXggPC0gbWF0cml4KAogICAgICAgICAgMCwKICAgICAgICAgIG5yb3cgPSBuX2lkcywKICAgICAgICAgIG5jb2wgPSBuX2NlbGxzLAogICAgICAgICAgZGltbmFtZXMgPSBsaXN0KAogICAgICAgICAgICBpZF92YWx1ZXMsCiAgICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5CiAgICAgICAgICApCiAgICAgICAgKQoKICAgICAgICBuX21hdHJpeCA8LSBtYXRyaXgoCiAgICAgICAgICAwLAogICAgICAgICAgbnJvdyA9IG5faWRzLAogICAgICAgICAgbmNvbCA9IG5fY2VsbHMsCiAgICAgICAgICBkaW1uYW1lcyA9IGxpc3QoCiAgICAgICAgICAgIGlkX3ZhbHVlcywKICAgICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkKICAgICAgICAgICkKICAgICAgICApCgogICAgICAgIHJvd19pbmRleCA8LSBtYXRjaCgKICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJElELAogICAgICAgICAgaWRfdmFsdWVzCiAgICAgICAgKQogICAgICAgIGNvbHVtbl9pbmRleCA8LSBtYXRjaCgKICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJGNlbGxfa2V5LAogICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkKICAgICAgICApCgogICAgICAgIHlfbWF0cml4W2NiaW5kKHJvd19pbmRleCwgY29sdW1uX2luZGV4KV0gPC0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJHlfc3VtCiAgICAgICAgbl9tYXRyaXhbY2JpbmQocm93X2luZGV4LCBjb2x1bW5faW5kZXgpXSA8LQogICAgICAgICAgY29uZGl0aW9uX2RhdGEkbl9vYnMKCiAgICAgICAgaWYgKGFueShjb2xTdW1zKG5fbWF0cml4KSA9PSAwKSkgewogICAgICAgICAgbWlzc2luZ19jZWxscyA8LSBleHBlY3RlZF9jZWxscyRjZWxsX2tleVsKICAgICAgICAgICAgY29sU3VtcyhuX21hdHJpeCkgPT0gMAogICAgICAgICAgXQoKICAgICAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgICAgIH0KCiAgICAgICAgbGlzdCgKICAgICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLAogICAgICAgICAgaWRzID0gaWRfdmFsdWVzLAogICAgICAgICAgY2VsbF9pbmZvID0gZXhwZWN0ZWRfY2VsbHMsCiAgICAgICAgICB5X21hdHJpeCA9IHlfbWF0cml4LAogICAgICAgICAgbl9tYXRyaXggPSBuX21hdHJpeAogICAgICAgICkKICAgICAgfQogICAgKQoKICAgIG5hbWVzKGNvbmRpdGlvbl9vYmplY3RzKSA8LSBhcy5jaGFyYWN0ZXIoMjo1KQoKICAgIGxpc3QoCiAgICAgIGN1ZV9tYXAgPSBjdWVfbWFwLAogICAgICBhdHRyaWJ1dGVzID0gYXR0cmlidXRlcywKICAgICAgY29uZGl0aW9ucyA9IGNvbmRpdGlvbl9vYmplY3RzCiAgICApCiAgfQoKICBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcyA8LSBmdW5jdGlvbigKICAgICAgcHJlcGFyZWQsCiAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA9IE5VTEwKICApIHsKICAgIGNvbmRpdGlvbl9yZXN1bHRzIDwtIGxhcHBseSgKICAgICAgbmFtZXMocHJlcGFyZWQkY29uZGl0aW9ucyksCiAgICAgIGZ1bmN0aW9uKGNvbmRpdGlvbl9uYW1lKSB7CiAgICAgICAgb2JqZWN0IDwtIHByZXBhcmVkJGNvbmRpdGlvbnNbW2NvbmRpdGlvbl9uYW1lXV0KCiAgICAgICAgaWYgKGlzLm51bGwoY2x1c3Rlcl93ZWlnaHRzKSkgewogICAgICAgICAgd2VpZ2h0cyA8LSByZXAoCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIGxlbmd0aChvYmplY3QkaWRzKQogICAgICAgICAgKQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB3ZWlnaHRzIDwtIGNsdXN0ZXJfd2VpZ2h0c1tbY29uZGl0aW9uX25hbWVdXQogICAgICAgIH0KCiAgICAgICAgaWYgKGxlbmd0aCh3ZWlnaHRzKSAhPSBsZW5ndGgob2JqZWN0JGlkcykpIHsKICAgICAgICAgIHN0b3AoIkNoZWNrIikKICAgICAgICB9CgogICAgICAgIG51bWVyYXRvciA8LSBhcy5udW1lcmljKAogICAgICAgICAgY3Jvc3Nwcm9kKAogICAgICAgICAgICB3ZWlnaHRzLAogICAgICAgICAgICBvYmplY3QkeV9tYXRyaXgKICAgICAgICAgICkKICAgICAgICApCgogICAgICAgIGRlbm9taW5hdG9yIDwtIGFzLm51bWVyaWMoCiAgICAgICAgICBjcm9zc3Byb2QoCiAgICAgICAgICAgIHdlaWdodHMsCiAgICAgICAgICAgIG9iamVjdCRuX21hdHJpeAogICAgICAgICAgKQogICAgICAgICkKCiAgICAgICAgaWYgKGFueShkZW5vbWluYXRvciA8PSAwKSkgewogICAgICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpCiAgICAgICAgfQoKICAgICAgICBtYXJnaW5hbF9tZWFucyA8LSBudW1lcmF0b3IgLyBkZW5vbWluYXRvcgoKICAgICAgICBtbV90YWJsZSA8LSBvYmplY3QkY2VsbF9pbmZvICU+JQogICAgICAgICAgdHJhbnNtdXRlKAogICAgICAgICAgICBwYXJ0eV9uID0gb2JqZWN0JHBhcnR5X24sCiAgICAgICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICAgICAgbGV2ZWwsCiAgICAgICAgICAgIG1hcmdpbmFsX21lYW4gPSBtYXJnaW5hbF9tZWFucwogICAgICAgICAgKQoKICAgICAgICBhdHRyaWJ1dGVfdGFibGUgPC0gbW1fdGFibGUgJT4lCiAgICAgICAgICBncm91cF9ieSgKICAgICAgICAgICAgcGFydHlfbiwKICAgICAgICAgICAgYXR0cmlidXRlCiAgICAgICAgICApICU+JQogICAgICAgICAgc3VtbWFyaXNlKAogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICAgICAgICBtZWFuX2Fic29sdXRlX3BhaXJ3aXNlX2RpZmZlcmVuY2UoCiAgICAgICAgICAgICAgICBtYXJnaW5hbF9tZWFuCiAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgbl9sZXZlbHMgPSBuKCksCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgICAgICkgJT4lCiAgICAgICAgICBtdXRhdGUoCiAgICAgICAgICAgIGN1ZV9mYW1pbHkgPSB1bm5hbWUoCiAgICAgICAgICAgICAgcHJlcGFyZWQkY3VlX21hcFthdHRyaWJ1dGVdCiAgICAgICAgICAgICksCiAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eSA9IDEgLyBwYXJ0eV9uLAogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlIC8KICAgICAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eQogICAgICAgICAgKQoKICAgICAgICBjdWVfdGFibGVfbG9uZyA8LSBhdHRyaWJ1dGVfdGFibGUgJT4lCiAgICAgICAgICBncm91cF9ieSgKICAgICAgICAgICAgcGFydHlfbiwKICAgICAgICAgICAgY3VlX2ZhbWlseQogICAgICAgICAgKSAlPiUKICAgICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSA9IG1lYW4oCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgKSwKICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9IG1lYW4oCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwKICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgKSwKICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgICAgICAgKQoKICAgICAgICBwYXJ0eV90YWJsZSA8LSBjdWVfdGFibGVfbG9uZyAlPiUKICAgICAgICAgIGZpbHRlcigKICAgICAgICAgICAgY3VlX2ZhbWlseSA9PSAicGFydHkiCiAgICAgICAgICApICU+JQogICAgICAgICAgdHJhbnNtdXRlKAogICAgICAgICAgICBwYXJ0eV9uLAogICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkCiAgICAgICAgICApCgogICAgICAgIGVjb25vbWljX3RhYmxlIDwtIGN1ZV90YWJsZV9sb25nICU+JQogICAgICAgICAgZmlsdGVyKAogICAgICAgICAgICBjdWVfZmFtaWx5ID09ICJlY29ub21pYyIKICAgICAgICAgICkgJT4lCiAgICAgICAgICB0cmFuc211dGUoCiAgICAgICAgICAgIHBhcnR5X24sCiAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UsCiAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQKICAgICAgICAgICkKCiAgICAgICAgY3VlX3RhYmxlIDwtIGZ1bGxfam9pbigKICAgICAgICAgIHBhcnR5X3RhYmxlLAogICAgICAgICAgZWNvbm9taWNfdGFibGUsCiAgICAgICAgICBieSA9ICJwYXJ0eV9uIgogICAgICAgICkgJT4lCiAgICAgICAgICBtdXRhdGUoCiAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eSA9IDEgLyBwYXJ0eV9uLAoKICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZSA9CiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSArCiAgICAgICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSwKCiAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgKwogICAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsCgogICAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UgPSBpZl9lbHNlKAogICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2UgPiAwLAogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgLwogICAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgICAgICBOQV9yZWFsXwogICAgICAgICAgICApLAoKICAgICAgICAgICAgcmVsYXRpdmVfZWNvbm9taWNfd2VpZ2h0X3BhaXJ3aXNlID0KICAgICAgICAgICAgICAxIC0gcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlLAoKICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlX2FkanVzdGVkID0gaWZfZWxzZSgKICAgICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID4gMCwKICAgICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIC8KICAgICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsCiAgICAgICAgICAgICAgTkFfcmVhbF8KICAgICAgICAgICAgKSwKCiAgICAgICAgICAgIHJlbGF0aXZlX2Vjb25vbWljX3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgICAgICAgMSAtIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCwKCiAgICAgICAgICAgIGFkanVzdG1lbnRfaWRlbnRpdHlfZGlmZmVyZW5jZSA9CiAgICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlX2FkanVzdGVkIC0KICAgICAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZQogICAgICAgICAgKQoKICAgICAgICBpZiAoCiAgICAgICAgICBhbnkoCiAgICAgICAgICAgIGFicyhjdWVfdGFibGUkYWRqdXN0bWVudF9pZGVudGl0eV9kaWZmZXJlbmNlKSA+IDFlLTEwLAogICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICkKICAgICAgICApIHsKICAgICAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpCiAgICAgICAgfQoKICAgICAgICBsaXN0KAogICAgICAgICAgbWFyZ2luYWxfbWVhbnMgPSBtbV90YWJsZSwKICAgICAgICAgIGF0dHJpYnV0ZV9pbXBvcnRhbmNlID0gYXR0cmlidXRlX3RhYmxlLAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UgPSBjdWVfdGFibGUKICAgICAgICApCiAgICAgIH0KICAgICkKCiAgICBsaXN0KAogICAgICBtYXJnaW5hbF9tZWFucyA9IGJpbmRfcm93cygKICAgICAgICBsYXBwbHkoCiAgICAgICAgICBjb25kaXRpb25fcmVzdWx0cywKICAgICAgICAgIGZ1bmN0aW9uKHgpIHgkbWFyZ2luYWxfbWVhbnMKICAgICAgICApCiAgICAgICksCiAgICAgIGF0dHJpYnV0ZV9pbXBvcnRhbmNlID0gYmluZF9yb3dzKAogICAgICAgIGxhcHBseSgKICAgICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzLAogICAgICAgICAgZnVuY3Rpb24oeCkgeCRhdHRyaWJ1dGVfaW1wb3J0YW5jZQogICAgICAgICkKICAgICAgKSwKICAgICAgY3VlX2ltcG9ydGFuY2UgPSBiaW5kX3Jvd3MoCiAgICAgICAgbGFwcGx5KAogICAgICAgICAgY29uZGl0aW9uX3Jlc3VsdHMsCiAgICAgICAgICBmdW5jdGlvbih4KSB4JGN1ZV9pbXBvcnRhbmNlCiAgICAgICAgKQogICAgICApICU+JQogICAgICAgIGFycmFuZ2UocGFydHlfbikKICAgICkKICB9CgogIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMgPC0gZnVuY3Rpb24oY3VlX2ltcG9ydGFuY2UpIHsKICAgIGN1ZV9pbXBvcnRhbmNlIDwtIGN1ZV9pbXBvcnRhbmNlICU+JQogICAgICBhcnJhbmdlKHBhcnR5X24pCgogICAgaWYgKCFpZGVudGljYWwoY3VlX2ltcG9ydGFuY2UkcGFydHlfbiwgMjo1KSkgewogICAgICBzdG9wKCJDaGVjayByZWxhdGl2ZSB3ZWlnaHQiKQogICAgfQoKICAgIHggPC0gY3VlX2ltcG9ydGFuY2UkcGFydHlfbgoKICAgIGMoCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSA9CiAgICAgICAgbGluZWFyX3Nsb3BlKAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAogICAgICAgICAgeAogICAgICAgICkKICAgICkKICB9CgogIHJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwIDwtIGZ1bmN0aW9uKAogICAgICBwcmVwYXJlZCwKICAgICAgQiwKICAgICAgc2VlZCwKICAgICAgcHJvZ3Jlc3NfZXZlcnkgPSAxMDAKICApIHsKICAgIHNldC5zZWVkKHNlZWQpCgogICAgY29uZGl0aW9uX3Jlc3VsdHMgPC0gdmVjdG9yKAogICAgICAibGlzdCIsCiAgICAgIEIKICAgICkKCiAgICBzbG9wZV9uYW1lcyA8LSBjKAogICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwKICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIsCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiCiAgICApCgogICAgc2xvcGVfbWF0cml4IDwtIG1hdHJpeCgKICAgICAgTkFfcmVhbF8sCiAgICAgIG5yb3cgPSBCLAogICAgICBuY29sID0gbGVuZ3RoKHNsb3BlX25hbWVzKSwKICAgICAgZGltbmFtZXMgPSBsaXN0KAogICAgICAgIE5VTEwsCiAgICAgICAgc2xvcGVfbmFtZXMKICAgICAgKQogICAgKQoKICAgIGZvciAoYiBpbiBzZXFfbGVuKEIpKSB7CiAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA8LSBsYXBwbHkoCiAgICAgICAgcHJlcGFyZWQkY29uZGl0aW9ucywKICAgICAgICBmdW5jdGlvbihvYmplY3QpIHsKICAgICAgICAgIG5faWRzIDwtIGxlbmd0aChvYmplY3QkaWRzKQoKICAgICAgICAgIHNhbXBsZWRfcG9zaXRpb25zIDwtIHNhbXBsZS5pbnQoCiAgICAgICAgICAgIG4gPSBuX2lkcywKICAgICAgICAgICAgc2l6ZSA9IG5faWRzLAogICAgICAgICAgICByZXBsYWNlID0gVFJVRQogICAgICAgICAgKQoKICAgICAgICAgIHRhYnVsYXRlKAogICAgICAgICAgICBzYW1wbGVkX3Bvc2l0aW9ucywKICAgICAgICAgICAgbmJpbnMgPSBuX2lkcwogICAgICAgICAgKQogICAgICAgIH0KICAgICAgKQoKICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcygKICAgICAgICBwcmVwYXJlZCA9IHByZXBhcmVkLAogICAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA9IGNsdXN0ZXJfd2VpZ2h0cwogICAgICApCgogICAgICBjb25kaXRpb25fcmVzdWx0c1tbYl1dIDwtCiAgICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyRjdWVfaW1wb3J0YW5jZSAlPiUKICAgICAgICBzZWxlY3QoCiAgICAgICAgICBwYXJ0eV9uLAogICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UsCiAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAogICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwKICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZQogICAgICAgICkgJT4lCiAgICAgICAgbXV0YXRlKAogICAgICAgICAgYm9vdHN0cmFwX3JlcGxpY2F0aW9uID0gYiwKICAgICAgICAgIC5iZWZvcmUgPSAxCiAgICAgICAgKQoKICAgICAgc2xvcGVfbWF0cml4W2IsIF0gPC0gZXN0aW1hdGVfcmVsYXRpdmVfY3VlX3Nsb3BlcygKICAgICAgICBib290c3RyYXBfZXN0aW1hdGVzJGN1ZV9pbXBvcnRhbmNlCiAgICAgICkKCiAgICAgIGlmICgKICAgICAgICBwcm9ncmVzc19ldmVyeSA+IDAgJiYKICAgICAgICAoYiAlJSBwcm9ncmVzc19ldmVyeSA9PSAwIHx8IGIgPT0gQikKICAgICAgKSB7CiAgICAgICAgbWVzc2FnZSgiQm9vdHN0cmFwOiAiLCBiLCAiLyIsIEIpCiAgICAgIH0KICAgIH0KCiAgICBsaXN0KAogICAgICBjb25kaXRpb25fZXN0aW1hdGVzID0gYmluZF9yb3dzKAogICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzCiAgICAgICksCiAgICAgIHNsb3BlcyA9IGFzX3RpYmJsZSgKICAgICAgICBzbG9wZV9tYXRyaXgKICAgICAgKSAlPiUKICAgICAgICBtdXRhdGUoCiAgICAgICAgICBib290c3RyYXBfcmVwbGljYXRpb24gPSByb3dfbnVtYmVyKCksCiAgICAgICAgICAuYmVmb3JlID0gMQogICAgICAgICkKICAgICkKICB9CgogIHN1bW1hcmlzZV9jb25kaXRpb25faW50ZXJ2YWxzIDwtIGZ1bmN0aW9uKAogICAgICBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSwKICAgICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzCiAgKSB7CiAgICBzdGF0aXN0aWNzIDwtIGMoCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwKICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIKICAgICkKCiAgICBvYnNlcnZlZF9sb25nIDwtIG9ic2VydmVkX2N1ZV9pbXBvcnRhbmNlICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgcGFydHlfbiwKICAgICAgICBhbGxfb2Yoc3RhdGlzdGljcykKICAgICAgKSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBhbGxfb2Yoc3RhdGlzdGljcyksCiAgICAgICAgbmFtZXNfdG8gPSAic3RhdGlzdGljIiwKICAgICAgICB2YWx1ZXNfdG8gPSAiZXN0aW1hdGUiCiAgICAgICkKCiAgICBib290c3RyYXBfbG9uZyA8LSBib290c3RyYXBfY29uZGl0aW9uX3Jlc3VsdHMgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gYWxsX29mKHN0YXRpc3RpY3MpLAogICAgICAgIG5hbWVzX3RvID0gInN0YXRpc3RpYyIsCiAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIgogICAgICApICU+JQogICAgICBncm91cF9ieSgKICAgICAgICBwYXJ0eV9uLAogICAgICAgIHN0YXRpc3RpYwogICAgICApICU+JQogICAgICBzdW1tYXJpc2UoCiAgICAgICAgY29uZl9sb3cgPSBzYWZlX3F1YW50aWxlKAogICAgICAgICAgdmFsdWUsCiAgICAgICAgICAwLjAyNQogICAgICAgICksCiAgICAgICAgY29uZl9oaWdoID0gc2FmZV9xdWFudGlsZSgKICAgICAgICAgIHZhbHVlLAogICAgICAgICAgMC45NzUKICAgICAgICApLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKQoKICAgIG9ic2VydmVkX2xvbmcgJT4lCiAgICAgIGxlZnRfam9pbigKICAgICAgICBib290c3RyYXBfbG9uZywKICAgICAgICBieSA9IGMoCiAgICAgICAgICAicGFydHlfbiIsCiAgICAgICAgICAic3RhdGlzdGljIgogICAgICAgICkKICAgICAgKQogIH0KCiAgc3VtbWFyaXNlX3Nsb3BlX2luZmVyZW5jZSA8LSBmdW5jdGlvbigKICAgICAgb2JzZXJ2ZWRfc2xvcGVzLAogICAgICBib290c3RyYXBfc2xvcGVzCiAgKSB7CiAgICBzdGF0aXN0aWNfbmFtZXMgPC0gbmFtZXMob2JzZXJ2ZWRfc2xvcGVzKQoKICAgIG1hcF9kZnIoCiAgICAgIHN0YXRpc3RpY19uYW1lcywKICAgICAgZnVuY3Rpb24oc3RhdGlzdGljX25hbWUpIHsKICAgICAgICBib290c3RyYXBfdmFsdWVzIDwtIGJvb3RzdHJhcF9zbG9wZXNbW3N0YXRpc3RpY19uYW1lXV0KICAgICAgICBib290c3RyYXBfdmFsdWVzIDwtIGJvb3RzdHJhcF92YWx1ZXNbCiAgICAgICAgICBpcy5maW5pdGUoYm9vdHN0cmFwX3ZhbHVlcykKICAgICAgICBdCgogICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA8LSBjYXNlX3doZW4oCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSA9PQogICAgICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIgfiAibmVnYXRpdmUiLAogICAgICAgICAgc3RhdGlzdGljX25hbWUgJWluJSBjKAogICAgICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsCiAgICAgICAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiLAogICAgICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIKICAgICAgICAgICkgfiAicG9zaXRpdmUiLAogICAgICAgICAgVFJVRSB+ICJub25lIgogICAgICAgICkKCiAgICAgICAgYW5hbHlzaXNfcm9sZSA8LSBjYXNlX3doZW4oCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSAlaW4lIGMoCiAgICAgICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiCiAgICAgICAgICApIH4gImV4cGxvcmF0b3J5X2Nob2ljZV9zZXRfYWRqdXN0ZWQiLAogICAgICAgICAgc3RhdGlzdGljX25hbWUgPT0gInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIgfgogICAgICAgICAgICAiZGVyaXZlZF9yZWxhdGl2ZV9zaGFyZSIsCiAgICAgICAgICBUUlVFIH4gIm1hbnVzY3JpcHRfcHJpbWFyeV91bmFkanVzdGVkIgogICAgICAgICkKCiAgICAgICAgZXN0aW1hdGUgPC0gdW5uYW1lKAogICAgICAgICAgb2JzZXJ2ZWRfc2xvcGVzW1tzdGF0aXN0aWNfbmFtZV1dCiAgICAgICAgKQoKICAgICAgICB0aWJibGUoCiAgICAgICAgICBzdHVkeSA9ICJTdHVkeSAxIiwKICAgICAgICAgIHN0YXRpc3RpYyA9IHN0YXRpc3RpY19uYW1lLAogICAgICAgICAgZXN0aW1hdGUgPSBlc3RpbWF0ZSwKICAgICAgICAgIGNvbmZfbG93ID0gc2FmZV9xdWFudGlsZSgKICAgICAgICAgICAgYm9vdHN0cmFwX3ZhbHVlcywKICAgICAgICAgICAgMC4wMjUKICAgICAgICAgICksCiAgICAgICAgICBjb25mX2hpZ2ggPSBzYWZlX3F1YW50aWxlKAogICAgICAgICAgICBib290c3RyYXBfdmFsdWVzLAogICAgICAgICAgICAwLjk3NQogICAgICAgICAgKSwKICAgICAgICAgIHBfdmFsdWVfdHdvX3NpZGVkID0KICAgICAgICAgICAgYm9vdHN0cmFwX3R3b19zaWRlZF9wKAogICAgICAgICAgICAgIGJvb3RzdHJhcF92YWx1ZXMKICAgICAgICAgICAgKSwKICAgICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9IGV4cGVjdGVkX2RpcmVjdGlvbiwKICAgICAgICAgIGFuYWx5c2lzX3JvbGUgPSBhbmFseXNpc19yb2xlLAogICAgICAgICAgZXN0aW1hdGVfaW5fZXhwZWN0ZWRfZGlyZWN0aW9uID0gY2FzZV93aGVuKAogICAgICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gInBvc2l0aXZlIiB+IGVzdGltYXRlID4gMCwKICAgICAgICAgICAgZXhwZWN0ZWRfZGlyZWN0aW9uID09ICJuZWdhdGl2ZSIgfiBlc3RpbWF0ZSA8IDAsCiAgICAgICAgICAgIFRSVUUgfiBOQQogICAgICAgICAgKQogICAgICAgICkKICAgICAgfQogICAgKQogIH0KCiAgcmVsYXRpdmVfY3VlX3ByZXBhcmVkIDwtIHByZXBhcmVfcmVsYXRpdmVfY3VlX2FuYWx5c2lzKAogICAgZGF0YSA9IGNvbmpvaW50X2FsbF9tLAogICAgY3VlX21hcCA9IHJlbGF0aXZlX2N1ZV9tYXAKICApCgogIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcygKICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkCiAgKQoKICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzIDwtIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMoCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkbWFyZ2luYWxfbWVhbnMsCiAgICAic3R1ZHkxX3JlbGF0aXZlX2N1ZV9tYXJnaW5hbF9tZWFucy5jc3YiCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGF0dHJpYnV0ZV9pbXBvcnRhbmNlLAogICAgInN0dWR5MV9yZWxhdGl2ZV9jdWVfYXR0cmlidXRlX2ltcG9ydGFuY2UuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRjdWVfaW1wb3J0YW5jZSwKICAgICJzdHVkeTFfcmVsYXRpdmVfY3VlX2ltcG9ydGFuY2VfYW5kX3dlaWdodC5jc3YiCiAgKQoKICByZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUgPC0gZmlsZS5wYXRoKAogICAgb3V0cHV0X2RpciwKICAgIHBhc3RlMCgKICAgICAgInN0dWR5MV9yZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcF8iLAogICAgICB1bmlmaWVkX2NvbmZpZyRjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiwKICAgICAgIl9CIiwKICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLAogICAgICAiLmNzdiIKICAgICkKICApCgogIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlIDwtIGZpbGUucGF0aCgKICAgIG91dHB1dF9kaXIsCiAgICBwYXN0ZTAoCiAgICAgICJzdHVkeTFfcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcF8iLAogICAgICB1bmlmaWVkX2NvbmZpZyRjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiwKICAgICAgIl9CIiwKICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLAogICAgICAiLmNzdiIKICAgICkKICApCgogIHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXAgPC0KICAgICFyZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwICYmCiAgICBmaWxlLmV4aXN0cyhyZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUpICYmCiAgICBmaWxlLmV4aXN0cyhyZWxhdGl2ZV9zbG9wZV9ib290c3RyYXBfZmlsZSkKCiAgaWYgKHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXApIHsKICAgIG1lc3NhZ2UoIkJvb3RzdHJhcCBjYWNoZSIpCgogICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAgPC0gcmVhZHI6OnJlYWRfY3N2KAogICAgICByZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUsCiAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UKICAgICkKCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwIDwtIHJlYWRyOjpyZWFkX2NzdigKICAgICAgcmVsYXRpdmVfc2xvcGVfYm9vdHN0cmFwX2ZpbGUsCiAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UKICAgICkKCiAgICBzYXZlZF9CX2NvbmRpdGlvbiA8LSBuX2Rpc3RpbmN0KAogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24KICAgICkKICAgIHNhdmVkX0Jfc2xvcGUgPC0gbl9kaXN0aW5jdCgKICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24KICAgICkKCiAgICBpZiAoCiAgICAgIHNhdmVkX0JfY29uZGl0aW9uICE9IHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiB8fAogICAgICBzYXZlZF9CX3Nsb3BlICE9IHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQgogICAgKSB7CiAgICAgIG1lc3NhZ2UoIkJvb3RzdHJhcCBjYWNoZSIpCiAgICAgIHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXAgPC0gRkFMU0UKICAgIH0KICB9CgogIGlmICghdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCkgewogICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA8LSBydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCgKICAgICAgcHJlcGFyZWQgPSByZWxhdGl2ZV9jdWVfcHJlcGFyZWQsCiAgICAgIEIgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IsCiAgICAgIHNlZWQgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQsCiAgICAgIHByb2dyZXNzX2V2ZXJ5ID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeQogICAgKQoKICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwIDwtCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAkY29uZGl0aW9uX2VzdGltYXRlcwoKICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAgPC0KICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCRzbG9wZXMKCiAgICByZWFkcjo6d3JpdGVfY3N2KAogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCwKICAgICAgcmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlCiAgICApCgogICAgcmVhZHI6OndyaXRlX2NzdigKICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCwKICAgICAgcmVsYXRpdmVfc2xvcGVfYm9vdHN0cmFwX2ZpbGUKICAgICkKICB9CgogIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzIDwtIHN1bW1hcmlzZV9jb25kaXRpb25faW50ZXJ2YWxzKAogICAgb2JzZXJ2ZWRfY3VlX2ltcG9ydGFuY2UgPQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsCiAgICBib290c3RyYXBfY29uZGl0aW9uX3Jlc3VsdHMgPQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcAogICkKCiAgcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSA8LSBzdW1tYXJpc2Vfc2xvcGVfaW5mZXJlbmNlKAogICAgb2JzZXJ2ZWRfc2xvcGVzID0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkX3Nsb3BlcywKICAgIGJvb3RzdHJhcF9zbG9wZXMgPQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMsCiAgICAic3R1ZHkxX3JlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzLmNzdiIKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlLAogICAgInN0dWR5MV9yZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlLmNzdiIKICApCgogIHJlbGF0aXZlX2N1ZV9wcmltYXJ5X3Jlc3VsdCA8LSByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlICU+JQogICAgZmlsdGVyKAogICAgICBzdGF0aXN0aWMgPT0KICAgICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIgogICAgKQoKICBjYXQoIlxuU3R1ZHkgMe+8muebuOWvvuavlOmHjeOBrue3muW9ouWCvuWQkVxuIikKICBwcmludChyZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQpCgoKICByZWxhdGl2ZV94X29mZnNldCA8LSAwLjA3NQoKICByZWxhdGl2ZV9wYW5lbF9hX2RhdGEgPC0gcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMgJT4lCiAgICBmaWx0ZXIoCiAgICAgIHN0YXRpc3RpYyAlaW4lIGMoCiAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIgogICAgICApCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICBjdWVfZmFtaWx5ID0gcmVjb2RlKAogICAgICAgIHN0YXRpc3RpYywKICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0gIuaUv+WFmuaJi+OBjOOBi+OCiiIsCiAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLntYzmuIjmiYvjgYzjgYvjgooiCiAgICAgICksCiAgICAgIGN1ZV9mYW1pbHkgPSBmYWN0b3IoCiAgICAgICAgY3VlX2ZhbWlseSwKICAgICAgICBsZXZlbHMgPSBjKAogICAgICAgICAgIuaUv+WFmuaJi+OBjOOBi+OCiiIsCiAgICAgICAgICAi57WM5riI5omL44GM44GL44KKIgogICAgICAgICkKICAgICAgKSwKICAgICAgeF9wbG90ID0gY2FzZV93aGVuKAogICAgICAgIGN1ZV9mYW1pbHkgPT0gIuaUv+WFmuaJi+OBjOOBi+OCiiIgfgogICAgICAgICAgcGFydHlfbiArIHJlbGF0aXZlX3hfb2Zmc2V0LAogICAgICAgIGN1ZV9mYW1pbHkgPT0gIue1jOa4iOaJi+OBjOOBi+OCiiIgfgogICAgICAgICAgcGFydHlfbiAtIHJlbGF0aXZlX3hfb2Zmc2V0LAogICAgICAgIFRSVUUgfiBhcy5udW1lcmljKHBhcnR5X24pCiAgICAgICksCiAgICAgIHZhbHVlX2xhYmVsID0gc3ByaW50ZigKICAgICAgICAiJS4zZiIsCiAgICAgICAgZXN0aW1hdGUKICAgICAgKQogICAgKQoKICByZWxhdGl2ZV9wYW5lbF9iX2RhdGEgPC0gcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMgJT4lCiAgICBmaWx0ZXIoCiAgICAgIHN0YXRpc3RpYyA9PQogICAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICB2YWx1ZV9sYWJlbCA9IHNwcmludGYoCiAgICAgICAgIiUuMWYlJSIsCiAgICAgICAgMTAwICogZXN0aW1hdGUKICAgICAgKQogICAgKQoKICByZWxhdGl2ZV9hZGp1c3RlZF9sYWJlbF9tYXAgPC0gcmVsYXRpdmVfcGFuZWxfYV9kYXRhICU+JQogICAgZGlzdGluY3QoCiAgICAgIHN0YXRpc3RpYywKICAgICAgY3VlX2ZhbWlseQogICAgKSAlPiUKICAgIG11dGF0ZSgKICAgICAgc3RhdGlzdGljID0gcGFzdGUwKAogICAgICAgIHN0YXRpc3RpYywKICAgICAgICAiX2FkanVzdGVkIgogICAgICApLAogICAgICBjdWVfZmFtaWx5ID0gYXMuY2hhcmFjdGVyKAogICAgICAgIGN1ZV9mYW1pbHkKICAgICAgKQogICAgKQoKICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQogICAgZmlsdGVyKAogICAgICBzdGF0aXN0aWMgJWluJSBjKAogICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIKICAgICAgKQogICAgKSAlPiUKICAgIGxlZnRfam9pbigKICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfbGFiZWxfbWFwLAogICAgICBieSA9ICJzdGF0aXN0aWMiCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICBjdWVfZmFtaWx5ID0gZmFjdG9yKAogICAgICAgIGN1ZV9mYW1pbHksCiAgICAgICAgbGV2ZWxzID0gbGV2ZWxzKAogICAgICAgICAgcmVsYXRpdmVfcGFuZWxfYV9kYXRhJGN1ZV9mYW1pbHkKICAgICAgICApCiAgICAgICksCiAgICAgIHhfcGxvdCA9IGlmX2Vsc2UoCiAgICAgICAgYXMuaW50ZWdlcihjdWVfZmFtaWx5KSA9PSAxTCwKICAgICAgICBwYXJ0eV9uICsgcmVsYXRpdmVfeF9vZmZzZXQsCiAgICAgICAgcGFydHlfbiAtIHJlbGF0aXZlX3hfb2Zmc2V0CiAgICAgICksCiAgICAgIHZhbHVlX2xhYmVsID0gc3ByaW50ZigKICAgICAgICAiJS4xZiUlIiwKICAgICAgICAxMDAgKiBlc3RpbWF0ZQogICAgICApCiAgICApCgogIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXggPC0gaWYgKAogICAgIuaUv+WFmuWQjeaJi+OBjOOBi+OCiiIgJWluJQogICAgICBsZXZlbHMocmVsYXRpdmVfcGFuZWxfYV9kYXRhJGN1ZV9mYW1pbHkpCiAgKSB7CiAgICAi6YG45oqe6IKiIgogIH0gZWxzZSB7CiAgICAi5pS/5YWaIgogIH0KCiAgcmVsYXRpdmVfY29uZGl0aW9uX2F4aXNfdGl0bGUgPC0gaWYgKAogICAgcmVsYXRpdmVfY29uZGl0aW9uX3N1ZmZpeCA9PSAi6YG45oqe6IKiIgogICkgewogICAgIuaUv+ayu+e1jOa4iOeKtuazgeOBrumBuOaKnuiCouaVsCIKICB9IGVsc2UgewogICAgIuaUv+WFmumBuOaKnuiCouaVsCIKICB9CgogIHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSA8LSBpZiAoCiAgICAuUGxhdGZvcm0kT1MudHlwZSA9PSAid2luZG93cyIKICApIHsKICAgICJZdSBHb3RoaWMiCiAgfSBlbHNlIHsKICAgICJzYW5zIgogIH0KCiAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncgPC0gdGhlbWVfYncoCiAgICBiYXNlX3NpemUgPSAxMiwKICAgIGJhc2VfZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5CiAgKSArCiAgICB0aGVtZSgKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZSgKICAgICAgICBsaW5ld2lkdGggPSAwLjMwLAogICAgICAgIGNvbG9yID0gImdyZXk4OCIKICAgICAgKSwKICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KAogICAgICAgIGxpbmV3aWR0aCA9IDAuNjUsCiAgICAgICAgY29sb3IgPSAiYmxhY2siCiAgICAgICksCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBjb2xvciA9ICJibGFjayIKICAgICAgKSwKICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBjb2xvciA9ICJibGFjayIKICAgICAgKSwKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBzaXplID0gMTIuNSwKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIGhqdXN0ID0gMAogICAgICApLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSA5LjUsCiAgICAgICAgaGp1c3QgPSAwLAogICAgICAgIG1hcmdpbiA9IG1hcmdpbigKICAgICAgICAgIGIgPSA4CiAgICAgICAgKQogICAgICApLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIiwKICAgICAgbGVnZW5kLmtleS53aWR0aCA9IGdyaWQ6OnVuaXQoCiAgICAgICAgMS4yNSwKICAgICAgICAiY20iCiAgICAgICksCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKAogICAgICAgIDgsCiAgICAgICAgMTAsCiAgICAgICAgOCwKICAgICAgICA4CiAgICAgICkKICAgICkKCiAgcmVsYXRpdmVfcGFuZWxfYSA8LSBnZ3Bsb3QoCiAgICByZWxhdGl2ZV9wYW5lbF9hX2RhdGEsCiAgICBhZXMoCiAgICAgIHggPSB4X3Bsb3QsCiAgICAgIHkgPSBlc3RpbWF0ZSwKICAgICAgZ3JvdXAgPSBjdWVfZmFtaWx5LAogICAgICBsaW5ldHlwZSA9IGN1ZV9mYW1pbHkKICAgICkKICApICsKICAgIGdlb21fbGluZSgKICAgICAgbGluZXdpZHRoID0gMC44MCwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fZXJyb3JiYXIoCiAgICAgIGFlcygKICAgICAgICB5bWluID0gY29uZl9sb3csCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaAogICAgICApLAogICAgICB3aWR0aCA9IDAuMDc1LAogICAgICBsaW5ld2lkdGggPSAwLjgwLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9sYWJlbCgKICAgICAgYWVzKAogICAgICAgIGxhYmVsID0gdmFsdWVfbGFiZWwKICAgICAgKSwKICAgICAgc2l6ZSA9IDMuNTUsCiAgICAgIGZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSwKICAgICAgbGFiZWwuc2l6ZSA9IDAsCiAgICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KAogICAgICAgIDAuMTIsCiAgICAgICAgImxpbmVzIgogICAgICApLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgdmFsdWVzID0gYygKICAgICAgICAi5pS/5YWa5omL44GM44GL44KKIiA9ICJzb2xpZCIsCiAgICAgICAgIue1jOa4iOaJi+OBjOOBi+OCiiIgPSAiZGFzaGVkIgogICAgICApCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgYnJlYWtzID0gMjo1LAogICAgICBsYWJlbHMgPSBwYXN0ZTAoCiAgICAgICAgMjo1LAogICAgICAgICLmlL/lhZoiCiAgICAgICksCiAgICAgIGxpbWl0cyA9IGMoCiAgICAgICAgMS43MiwKICAgICAgICA1LjI4CiAgICAgICkKICAgICkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKAogICAgICBsYWJlbHMgPSBsYWJlbF9udW1iZXIoCiAgICAgICAgYWNjdXJhY3kgPSAwLjAwNQogICAgICApLAogICAgICBleHBhbmQgPSBleHBhbnNpb24oCiAgICAgICAgbXVsdCA9IGMoCiAgICAgICAgICAwLjA3LAogICAgICAgICAgMC4xMAogICAgICAgICkKICAgICAgKQogICAgKSArCiAgICBsYWJzKAogICAgICB0aXRsZSA9ICJB77ya5Lih5omL44GM44GL44KK44Gu57W25a++55qE6YeN6KaB5bqmIiwKICAgICAgc3VidGl0bGUgPSAiIiwKICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLAogICAgICB5ID0gIuaJi+OBjOOBi+OCiumHjeimgeW6piIsCiAgICAgIGxpbmV0eXBlID0gTlVMTAogICAgKSArCiAgICBndWlkZXMoCiAgICAgIGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKAogICAgICAgIG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBsaW5ld2lkdGggPSAwLjkwCiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3CgogIHJlbGF0aXZlX2FkanVzdGVkX2xpbmV0eXBlcyA8LSBzZXROYW1lcygKICAgIGMoCiAgICAgICJzb2xpZCIsCiAgICAgICJkYXNoZWQiCiAgICApLAogICAgbGV2ZWxzKAogICAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhJGN1ZV9mYW1pbHkKICAgICkKICApCgogIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkIDwtIGdncGxvdCgKICAgIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGEsCiAgICBhZXMoCiAgICAgIHggPSB4X3Bsb3QsCiAgICAgIHkgPSBlc3RpbWF0ZSwKICAgICAgZ3JvdXAgPSBjdWVfZmFtaWx5LAogICAgICBsaW5ldHlwZSA9IGN1ZV9mYW1pbHkKICAgICkKICApICsKICAgIGdlb21fbGluZSgKICAgICAgbGluZXdpZHRoID0gMC44MCwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fZXJyb3JiYXIoCiAgICAgIGFlcygKICAgICAgICB5bWluID0gY29uZl9sb3csCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaAogICAgICApLAogICAgICB3aWR0aCA9IDAuMDc1LAogICAgICBsaW5ld2lkdGggPSAwLjgwLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9sYWJlbCgKICAgICAgYWVzKAogICAgICAgIGxhYmVsID0gdmFsdWVfbGFiZWwKICAgICAgKSwKICAgICAgc2l6ZSA9IDMuNTUsCiAgICAgIGZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSwKICAgICAgbGFiZWwuc2l6ZSA9IDAsCiAgICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KAogICAgICAgIDAuMTIsCiAgICAgICAgImxpbmVzIgogICAgICApLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgdmFsdWVzID0gcmVsYXRpdmVfYWRqdXN0ZWRfbGluZXR5cGVzCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgYnJlYWtzID0gMjo1LAogICAgICBsYWJlbHMgPSBwYXN0ZTAoCiAgICAgICAgMjo1LAogICAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXgKICAgICAgKSwKICAgICAgbGltaXRzID0gYygKICAgICAgICAxLjcyLAogICAgICAgIDUuMjgKICAgICAgKQogICAgKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICAgIGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoCiAgICAgICAgYWNjdXJhY3kgPSAxCiAgICAgICksCiAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbigKICAgICAgICBtdWx0ID0gYygKICAgICAgICAgIDAuMDcsCiAgICAgICAgICAwLjEwCiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gIkHvvJrpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiLAogICAgICBzdWJ0aXRsZSA9CiAgICAgICAgIuacquiqv+aVtOmHjeimgeW6piDDtyDlubPlnYfpgbjmip7norrnjofvvIgx77yP6YG45oqe6IKi5pWw77yJIiwKICAgICAgeCA9IHJlbGF0aXZlX2NvbmRpdGlvbl9heGlzX3RpdGxlLAogICAgICB5ID0gIuW5s+Wdh+mBuOaKnueiuueOh+OBq+WvvuOBmeOCi+awtOa6lumWk+W3riIsCiAgICAgIGxpbmV0eXBlID0gTlVMTAogICAgKSArCiAgICBndWlkZXMoCiAgICAgIGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKAogICAgICAgIG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBsaW5ld2lkdGggPSAwLjkwCiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3CgogIHJlbGF0aXZlX2JfcmFuZ2UgPC0gcmFuZ2UoCiAgICBjKAogICAgICByZWxhdGl2ZV9wYW5lbF9iX2RhdGEkY29uZl9sb3csCiAgICAgIHJlbGF0aXZlX3BhbmVsX2JfZGF0YSRjb25mX2hpZ2gsCiAgICAgIDAuNQogICAgKSwKICAgIG5hLnJtID0gVFJVRQogICkKCiAgcmVsYXRpdmVfYl9wYWRkaW5nIDwtIG1heCgKICAgIDAuMDI1LAogICAgMC4xMCAqIGRpZmYocmVsYXRpdmVfYl9yYW5nZSkKICApCgogIHJlbGF0aXZlX2JfbG93ZXIgPC0gbWF4KAogICAgMCwKICAgIGZsb29yKAogICAgICAyMCAqCiAgICAgICAgKHJlbGF0aXZlX2JfcmFuZ2VbMV0gLSByZWxhdGl2ZV9iX3BhZGRpbmcpCiAgICApIC8gMjAKICApCgogIHJlbGF0aXZlX2JfdXBwZXIgPC0gbWluKAogICAgMSwKICAgIGNlaWxpbmcoCiAgICAgIDIwICoKICAgICAgICAocmVsYXRpdmVfYl9yYW5nZVsyXSArIHJlbGF0aXZlX2JfcGFkZGluZykKICAgICkgLyAyMAogICkKCiAgaWYgKHJlbGF0aXZlX2JfbG93ZXIgPj0gcmVsYXRpdmVfYl91cHBlcikgewogICAgcmVsYXRpdmVfYl9sb3dlciA8LSBtYXgoCiAgICAgIDAsCiAgICAgIHJlbGF0aXZlX2JfbG93ZXIgLSAwLjA1CiAgICApCiAgICByZWxhdGl2ZV9iX3VwcGVyIDwtIG1pbigKICAgICAgMSwKICAgICAgcmVsYXRpdmVfYl91cHBlciArIDAuMDUKICAgICkKICB9CgogIHJlbGF0aXZlX3BhbmVsX2IgPC0gZ2dwbG90KAogICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhLAogICAgYWVzKAogICAgICB4ID0gcGFydHlfbiwKICAgICAgeSA9IGVzdGltYXRlCiAgICApCiAgKSArCiAgICBnZW9tX2hsaW5lKAogICAgICB5aW50ZXJjZXB0ID0gMC41LAogICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLAogICAgICBsaW5ld2lkdGggPSAwLjU1LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9saW5lKAogICAgICBsaW5ld2lkdGggPSAwLjgwLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9lcnJvcmJhcigKICAgICAgYWVzKAogICAgICAgIHltaW4gPSBjb25mX2xvdywKICAgICAgICB5bWF4ID0gY29uZl9oaWdoCiAgICAgICksCiAgICAgIHdpZHRoID0gMC4wNzUsCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBnZW9tX2xhYmVsKAogICAgICBhZXMoCiAgICAgICAgbGFiZWwgPSB2YWx1ZV9sYWJlbAogICAgICApLAogICAgICBzaXplID0gMy41NSwKICAgICAgZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5LAogICAgICBsYWJlbC5zaXplID0gMCwKICAgICAgbGFiZWwucGFkZGluZyA9IGdyaWQ6OnVuaXQoCiAgICAgICAgMC4xMiwKICAgICAgICAibGluZXMiCiAgICAgICksCiAgICAgIGZpbGwgPSAid2hpdGUiLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKAogICAgICBicmVha3MgPSAyOjUsCiAgICAgIGxhYmVscyA9IHBhc3RlMCgKICAgICAgICAyOjUsCiAgICAgICAgIuaUv+WFmiIKICAgICAgKSwKICAgICAgbGltaXRzID0gYygKICAgICAgICAxLjcyLAogICAgICAgIDUuMjgKICAgICAgKQogICAgKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICAgIGJyZWFrcyA9IHNlcSgKICAgICAgICByZWxhdGl2ZV9iX2xvd2VyLAogICAgICAgIHJlbGF0aXZlX2JfdXBwZXIsCiAgICAgICAgYnkgPSAwLjA1CiAgICAgICksCiAgICAgIGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoCiAgICAgICAgYWNjdXJhY3kgPSAxCiAgICAgICksCiAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbigKICAgICAgICBtdWx0ID0gYygKICAgICAgICAgIDAuMDUsCiAgICAgICAgICAwLjA4CiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIGNvb3JkX2NhcnRlc2lhbigKICAgICAgeWxpbSA9IGMoCiAgICAgICAgcmVsYXRpdmVfYl9sb3dlciwKICAgICAgICByZWxhdGl2ZV9iX3VwcGVyCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgdGl0bGUgPSAiQu+8muebuOWvvueahOOBquaUv+WFmuaJi+OBjOOBi+OCiuOBruavlOmHjSIsCiAgICAgIHN1YnRpdGxlID0KICAgICAgICAi5pS/5YWa5omL44GM44GL44KK6YeN6KaB5bqmIMO377yI5pS/5YWa5omL44GM44GL44KK6YeN6KaB5bqm77yL57WM5riI5omL44GM44GL44KK6YeN6KaB5bqm77yJIiwKICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLAogICAgICB5ID0gIuebuOWvvueahOOBquaUv+WFmuaJi+OBjOOBi+OCiuavlOmHjSIKICAgICkgKwogICAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncgKwogICAgdGhlbWUoCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICAgKQoKICByZWxhdGl2ZV9wYW5lbF9jIDwtIHJlbGF0aXZlX3BhbmVsX2IgKwogICAgbGFicygKICAgICAgdGl0bGUgPSBwYXN0ZTAoCiAgICAgICAgIkLvvJrnm7jlr77nmoTjgaoiLAogICAgICAgIGxldmVscyhyZWxhdGl2ZV9wYW5lbF9hX2RhdGEkY3VlX2ZhbWlseSlbMV0sCiAgICAgICAgIuOBruavlOmHjSIKICAgICAgKQogICAgKQoKICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwIDwtICgKICAgIHJlbGF0aXZlX3BhbmVsX2EgfAogICAgICByZWxhdGl2ZV9wYW5lbF9iCiAgKSArCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KAogICAgICB3aWR0aHMgPSBjKAogICAgICAgIDEsCiAgICAgICAgMQogICAgICApCiAgICApCgogIHByaW50KAogICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcAogICkKCiAgc2F2ZV9wbG90KAogICAgImZpZ19zdHVkeTFfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wbmciLAogICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCwKICAgIHdpZHRoID0gMTEuMiwKICAgIGhlaWdodCA9IDUuNCwKICAgIGRwaSA9IDQwMAogICkKCiAgZ2dzYXZlKAogICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoCiAgICAgIG91dHB1dF9kaXIsCiAgICAgICJmaWdfc3R1ZHkxX3JlbGF0aXZlX2N1ZV93ZWlnaHRfanBfYncucGRmIgogICAgKSwKICAgIHBsb3QgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLAogICAgd2lkdGggPSAxMS4yLAogICAgaGVpZ2h0ID0gNS40LAogICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsCiAgICBiZyA9ICJ3aGl0ZSIKICApCgogIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAgPC0gKAogICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQgfAogICAgICByZWxhdGl2ZV9wYW5lbF9jCiAgKSArCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KAogICAgICB3aWR0aHMgPSBjKAogICAgICAgIDEsCiAgICAgICAgMQogICAgICApCiAgICApCgogIHByaW50KAogICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcAogICkKCiAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIgPC0gcGFzdGUwKAogICAgImZpZ19zdHVkeSIsCiAgICBzdHJpbmdyOjpzdHJfZXh0cmFjdCgKICAgICAgc3R1ZHlfbGFiZWwsCiAgICAgICJbMTIzXSIKICAgICksCiAgICAiX3JlbGF0aXZlX2N1ZV93ZWlnaHRfY2hvaWNlX3NldF9hZGp1c3RlZF9qcF9idyIKICApCgogIHNhdmVfcGxvdCgKICAgIHBhc3RlMCgKICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIsCiAgICAgICIucG5nIgogICAgKSwKICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAsCiAgICB3aWR0aCA9IDExLjIsCiAgICBoZWlnaHQgPSA1LjQsCiAgICBkcGkgPSA0MDAKICApCgogIGdnc2F2ZSgKICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICBwYXN0ZTAoCiAgICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIsCiAgICAgICAgIi5wZGYiCiAgICAgICkKICAgICksCiAgICBwbG90ID0gZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcCwKICAgIHdpZHRoID0gMTEuMiwKICAgIGhlaWdodCA9IDUuNCwKICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLAogICAgYmcgPSAid2hpdGUiCiAgKQoKICByZWxhdGl2ZV9jdWVfcmVzdWx0cyA8LSBsaXN0KAogICAgcHJlcGFyZWQgPSByZWxhdGl2ZV9jdWVfcHJlcGFyZWQsCiAgICBtYXJnaW5hbF9tZWFucyA9CiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRtYXJnaW5hbF9tZWFucywKICAgIGF0dHJpYnV0ZV9pbXBvcnRhbmNlID0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGF0dHJpYnV0ZV9pbXBvcnRhbmNlLAogICAgY3VlX2ltcG9ydGFuY2UgPQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsCiAgICBvYnNlcnZlZF9zbG9wZXMgPQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzLAogICAgY29uZGl0aW9uX2Jvb3RzdHJhcCA9CiAgICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwLAogICAgc2xvcGVfYm9vdHN0cmFwID0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCwKICAgIGNvbmRpdGlvbl9pbnRlcnZhbHMgPQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscywKICAgIHNsb3BlX2luZmVyZW5jZSA9CiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9pbmZlcmVuY2UsCiAgICBwcmltYXJ5X3Jlc3VsdCA9CiAgICAgIHJlbGF0aXZlX2N1ZV9wcmltYXJ5X3Jlc3VsdCwKICAgIHBsb3RzID0gbGlzdCgKICAgICAgYWJzb2x1dGVfaW1wb3J0YW5jZSA9IHJlbGF0aXZlX3BhbmVsX2EsCiAgICAgIGNob2ljZV9zZXRfYWRqdXN0ZWRfaW1wb3J0YW5jZSA9CiAgICAgICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQsCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodCA9IHJlbGF0aXZlX3BhbmVsX2IsCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYW5lbF9jID0KICAgICAgICByZWxhdGl2ZV9wYW5lbF9jLAogICAgICBjb21iaW5lZCA9IGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsCiAgICAgIGNvbWJpbmVkX3dpdGhfY2hvaWNlX3NldF9hZGp1c3RtZW50ID0KICAgICAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwCiAgICApCiAgKQoKICBzYXZlUkRTKAogICAgcmVsYXRpdmVfY3VlX3Jlc3VsdHMsCiAgICBmaWxlID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAic3R1ZHkxX3JlbGF0aXZlX2N1ZV9yZXN1bHRzLnJkcyIKICAgICkKICApCgoKICBzYXZlUkRTKAogICAgbGlzdCgKICAgICAgc2V0dGluZ3MgPSBsaXN0KAogICAgICAgIHJlcXVpcmVfaW5pdGlhbF9jb25zZW50ID0gcmVxdWlyZV9pbml0aWFsX2NvbnNlbnQsCiAgICAgICAgcmVxdWlyZV9maW5hbF9jb25zZW50ID0gcmVxdWlyZV9maW5hbF9jb25zZW50LAogICAgICAgIHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrID0gcmVxdWlyZV9hdHRlbnRpb25fY2hlY2ssCiAgICAgICAgcmVxdWlyZV9tYW5pcHVsYXRpb25fY2hlY2sgPSByZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjawogICAgICApLAogICAgICBzYW1wbGVfZmxvdyA9IHNhbXBsZV9mbG93LAogICAgICBuX2J5X3BhcnR5ID0gbl9ieV9wYXJ0eSwKICAgICAgdmFsaWRfaWRzID0gdmFsaWRfaWRzLAogICAgICBjb25qb2ludF9hbGwgPSBjb25qb2ludF9hbGwsCiAgICAgIGNvbmpvaW50X2FsbF9tID0gY29uam9pbnRfYWxsX20sCiAgICAgIGNvdmFyX2lkID0gY292YXJfaWQsCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX25vY292ID0gbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YsCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX2NvdiA9IG1vZGVsc19ieV9wYXJ0eV9uX2NvdiwKICAgICAgbV9pbnRlcmFjdGlvbiA9IG1faW50ZXJhY3Rpb24sCiAgICAgIG1vZGVsc19jbG9naXRfbm9jb3YgPSBtb2RlbHNfY2xvZ2l0X25vY292LAogICAgICByZWxhdGl2ZV9jdWUgPSByZWxhdGl2ZV9jdWVfcmVzdWx0cywKICAgICAgcGxvdHMgPSBsaXN0KAogICAgICAgIGFtY2VfY292ID0gcF9hbWNlX2Nvdl9tYWluLAogICAgICAgIGFtY2Vfbm9jb3YgPSBwX2FtY2Vfbm9jb3ZfYXBwZW5kaXgsCiAgICAgICAgaW50ZXJhY3Rpb24gPSBwX2ludGVyYWN0aW9uLAogICAgICAgIGhlYXRtYXAgPSBwX2hlYXRfYW1jZSwKICAgICAgICBoZWF0bWFwX3JhbmsgPSBwX2hlYXRfYW1jZV9yYW5rLAogICAgICAgIGNsb2dpdF9vZGRzX3JhdGlvID0gcF9jbG9naXRfb3IsCiAgICAgICAgcmVsYXRpdmVfY3VlX3dlaWdodCA9IGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsCiAgICAgICAgcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkID0KICAgICAgICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAKICAgICAgKQogICAgKSwKICAgIGZpbGUgPSBmaWxlLnBhdGgob3V0cHV0X2RpciwgInN0dWR5MV9hbmFseXNpc19vYmplY3RzLnJkcyIpCiAgKQoKICBjYXB0dXJlLm91dHB1dCgKICAgIHNlc3Npb25JbmZvKCksCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJzZXNzaW9uSW5mby50eHQiKQogICkKCiAgY2F0KCIKRG9uZTogIiwgbm9ybWFsaXplUGF0aChvdXRwdXRfZGlyKSwgIgoiLCBzZXAgPSAiIikKCiAgZW52aXJvbm1lbnQoKQp9KQoKCmBgYAoKIyMgQS4zIOWun+mokzLvvJrmnKzmlofjga7lm7M2CgpgYGB7ciBhMy1zdHVkeTItY29kZSwgZXZhbD1wYXJhbXMkcnVuX2FuYWx5c2lzLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQojIOacrOaWh+OCs+ODvOODiQpzdHVkeTJfZW52IDwtIGxvY2FsKHsKcmVxdWlyZWRfcGFja2FnZXMgPC0gYygKICAgICJkcGx5ciIsCiAgICAidGlkeXIiLAogICAgInN0cmluZ3IiLAogICAgInB1cnJyIiwKICAgICJyZWFkciIsCiAgICAiZml4ZXN0IiwKICAgICJ0aWJibGUiLAogICAgImZvcmNhdHMiLAogICAgImdncGxvdDIiLAogICAgInNjYWxlcyIsCiAgICAic3Vydml2YWwiLAogICAgImdndGV4dCIsCiAgICAicGF0Y2h3b3JrIgogICkKCiAgbWlzc2luZ19wYWNrYWdlcyA8LSByZXF1aXJlZF9wYWNrYWdlc1sKICAgICF2YXBwbHkocmVxdWlyZWRfcGFja2FnZXMsIHJlcXVpcmVOYW1lc3BhY2UsIGxvZ2ljYWwoMSksIHF1aWV0bHkgPSBUUlVFKQogIF0KCiAgaWYgKGxlbmd0aChtaXNzaW5nX3BhY2thZ2VzKSA+IDApIHsKICAgIHN0b3AoIk5vIHBhY2thZ2VzIikKICB9CgogIGxpYnJhcnkoZHBseXIpCiAgbGlicmFyeSh0aWR5cikKICBsaWJyYXJ5KHN0cmluZ3IpCiAgbGlicmFyeShwdXJycikKICBsaWJyYXJ5KHJlYWRyKQogIGxpYnJhcnkoZml4ZXN0KQogIGxpYnJhcnkodGliYmxlKQogIGxpYnJhcnkoZm9yY2F0cykKICBsaWJyYXJ5KGdncGxvdDIpCiAgbGlicmFyeShzY2FsZXMpCiAgbGlicmFyeShzdXJ2aXZhbCkKICBsaWJyYXJ5KHBhdGNod29yaykKCiAgZGF0YV9maWxlIDwtIHVuaWZpZWRfY29uZmlnJHN0dWR5MiRkYXRhX2ZpbGUKICBvdXRwdXRfZGlyIDwtIHVuaWZpZWRfY29uZmlnJHN0dWR5MiRvdXRwdXRfZGlyCgogIGRpci5jcmVhdGUob3V0cHV0X2Rpciwgc2hvd1dhcm5pbmdzID0gRkFMU0UsIHJlY3Vyc2l2ZSA9IFRSVUUpCgogIHJlcXVpcmVfaW5pdGlhbF9jb25zZW50IDwtIFRSVUUKICByZXF1aXJlX2ZpbmFsX2NvbnNlbnQgPC0gVFJVRQogIGZpbmFsX2NvbnNlbnRfdmFyIDwtICJROC4xIgoKICByZXF1aXJlX2F0dGVudGlvbl9jaGVjayA8LSBUUlVFCiAgcmVxdWlyZV9tYW5pcHVsYXRpb25fY2hlY2sgPC0gVFJVRQoKICBhdHRlbnRpb25fY2hlY2tfdmFyIDwtICJRMjUuMV8xMSIKICBhdHRlbnRpb25fY2hlY2tfY29ycmVjdCA8LSAiMyIKCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CIDwtIHVuaWZpZWRfY29uZmlnJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQgogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCA8LSB1bmlmaWVkX2NvbmZpZyRyZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQgKyAyTAogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkgPC0gdW5pZmllZF9jb25maWckcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeQoKICByZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwIDwtIHVuaWZpZWRfY29uZmlnJHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAKCgogIG5vcm1fdGV4dCA8LSBmdW5jdGlvbih4KSB7CiAgICB4ICU+JQogICAgICBhcy5jaGFyYWN0ZXIoKSAlPiUKICAgICAgc3RyX3NxdWlzaCgpICU+JQogICAgICBzdHJfcmVwbGFjZV9hbGwoIu+9niIsICJ+IikgJT4lCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgi44CcIiwgIn4iKQogIH0KCiAgYXNfbnVtIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHN1cHByZXNzV2FybmluZ3MocmVhZHI6OnBhcnNlX251bWJlcihub3JtX3RleHQoeCkpKQogIH0KCiAgaXNfcmVzcG9uc2VfY29kZSA8LSBmdW5jdGlvbih4LCBjb2RlKSB7CiAgICB4X25vcm0gPC0gbm9ybV90ZXh0KHgpCiAgICBjb2RlX2NociA8LSBhcy5jaGFyYWN0ZXIoY29kZSkKCiAgICB4X25vcm0gPT0gY29kZV9jaHIgfAogICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KHhfbm9ybSwgcGFzdGUwKCJcXCgiLCBjb2RlX2NociwgIlxcKSQiKSkKICB9CgogIGZpcnN0X2V4aXN0aW5nIDwtIGZ1bmN0aW9uKGRhdCwgY2FuZGlkYXRlcykgewogICAgb3V0IDwtIGNhbmRpZGF0ZXNbY2FuZGlkYXRlcyAlaW4lIG5hbWVzKGRhdCldCiAgICBpZiAobGVuZ3RoKG91dCkgPT0gMCkgTkFfY2hhcmFjdGVyXyBlbHNlIG91dFsxXQogIH0KCiAgZ2V0X3ZhciA8LSBmdW5jdGlvbihkYXQsIGNhbmRpZGF0ZXMpIHsKICAgIHYgPC0gZmlyc3RfZXhpc3RpbmcoZGF0LCBjYW5kaWRhdGVzKQogICAgaWYgKGlzLm5hKHYpKSB7CiAgICAgIHJlcChOQV9jaGFyYWN0ZXJfLCBucm93KGRhdCkpCiAgICB9IGVsc2UgewogICAgICBkYXRbW3ZdXQogICAgfQogIH0KCiAgcmVsZXZlbF9pZl9wcmVzZW50IDwtIGZ1bmN0aW9uKHgsIHJlZikgewogICAgeCA8LSBmYWN0b3IoeCkKICAgIGlmIChyZWYgJWluJSBsZXZlbHMoeCkpIHsKICAgICAgcmVsZXZlbCh4LCByZWYgPSByZWYpCiAgICB9IGVsc2UgewogICAgICB4CiAgICB9CiAgfQoKICBmYWN0b3JfbWlzcyA8LSBmdW5jdGlvbih4LCBtaXNzID0gIuasoOaQjeODu+eEoeWbnuetlCIpIHsKICAgIHggPC0gbm9ybV90ZXh0KHgpCiAgICB4W2lzLm5hKHgpIHwgeCA9PSAiIiB8IHggPT0gIk5BIl0gPC0gbWlzcwogICAgZmFjdG9yKHgpCiAgfQoKICBtZWFuX2ltcHV0ZSA8LSBmdW5jdGlvbih4KSB7CiAgICB4IDwtIGFzLm51bWVyaWMoeCkKICAgIG1pc3MgPC0gYXMuaW50ZWdlcihpcy5uYSh4KSkKCiAgICBpZiAoYWxsKGlzLm5hKHgpKSkgewogICAgICB2YWx1ZSA8LSB4CiAgICB9IGVsc2UgewogICAgICB2YWx1ZSA8LSBpZmVsc2UoaXMubmEoeCksIG1lYW4oeCwgbmEucm0gPSBUUlVFKSwgeCkKICAgIH0KCiAgICBsaXN0KHZhbHVlID0gdmFsdWUsIG1pc3MgPSBtaXNzKQogIH0KCiAgd3JpdGVfY3N2X3NhZmVseSA8LSBmdW5jdGlvbih4LCBmaWxlbmFtZSkgewogICAgcmVhZHI6OndyaXRlX2Nzdih4LCBmaWxlLnBhdGgob3V0cHV0X2RpciwgZmlsZW5hbWUpLCBuYSA9ICIiKQogIH0KCiAgc2F2ZV9wbG90IDwtIGZ1bmN0aW9uKGZpbGVuYW1lLCBwbG90LCB3aWR0aCwgaGVpZ2h0LCBkcGkgPSAzMDApIHsKICAgIGdncGxvdDI6Omdnc2F2ZSgKICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgob3V0cHV0X2RpciwgZmlsZW5hbWUpLAogICAgICBwbG90ID0gcGxvdCwKICAgICAgd2lkdGggPSB3aWR0aCwKICAgICAgaGVpZ2h0ID0gaGVpZ2h0LAogICAgICBkcGkgPSBkcGkKICAgICkKICB9CgoKICBpZiAoIWZpbGUuZXhpc3RzKGRhdGFfZmlsZSkpIHsKICAgIHN0b3AoIkNoZWNrIGRhdGEiKQogIH0KCiAgcmF3IDwtIHJlYWRyOjpyZWFkX2NzdigKICAgIGRhdGFfZmlsZSwKICAgIGNvbF90eXBlcyA9IGNvbHMoLmRlZmF1bHQgPSBjb2xfY2hhcmFjdGVyKCkpLAogICAgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSwKICAgIG5hbWVfcmVwYWlyID0gIm1pbmltYWwiCiAgKQoKCiAgaWYgKHJlcXVpcmVfZmluYWxfY29uc2VudCkgewogICAgZmluYWxfY29uc2VudF92YXIgPC0gZGV0ZWN0X2ZpbmFsX2NvbnNlbnRfY29sdW1uKAogICAgICByYXcgPSByYXcsCiAgICAgIHByZWZlcnJlZF9jYW5kaWRhdGVzID0gYygiUTguMSIsICJROS4xIiwgIlExMC4xIiksCiAgICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDIiCiAgICApCiAgfQoKICBpZiAocmVxdWlyZV9hdHRlbnRpb25fY2hlY2spIHsKICAgIGF0dGVudGlvbl9jaGVja192YXIgPC0gZGV0ZWN0X2F0dGVudGlvbl9jaGVja19jb2x1bW4oCiAgICAgIHJhdyA9IHJhdywKICAgICAgcHJlZmVycmVkX2NhbmRpZGF0ZXMgPSBjKCJRMjUuMV8xMSIsICJRMjUuMV8xMCIpLAogICAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAyIgogICAgKQogIH0KCiAgZGZfaGVhZGVyX3JlbW92ZWQgPC0gcmF3ICU+JQogICAgZmlsdGVyKAogICAgICAhaXMubmEoUmVzcG9uc2VJZCksCiAgICAgIFJlc3BvbnNlSWQgIT0gIiIsCiAgICAgICFzdHJfZGV0ZWN0KAogICAgICAgIG5vcm1fdGV4dChSZXNwb25zZUlkKSwKICAgICAgICAiXihSZXNwb25zZSBJRHzlm57nrZRJRCkkfEltcG9ydElkIgogICAgICApCiAgICApICU+JQogICAgbXV0YXRlKElEID0gYXMuY2hhcmFjdGVyKFJlc3BvbnNlSWQpKQoKICBkdXBsaWNhdGVfaWRzIDwtIGRmX2hlYWRlcl9yZW1vdmVkICU+JQogICAgY291bnQoSUQpICU+JQogICAgZmlsdGVyKG4gPiAxKQoKICBpZiAobnJvdyhkdXBsaWNhdGVfaWRzKSA+IDApIHsKICAgIHByaW50KGR1cGxpY2F0ZV9pZHMpCiAgICBzdG9wKCJDaGVjayIpCiAgfQoKICBzYW1wbGVfZmxvdyA8LSB0aWJibGUoCiAgICBzdGFnZSA9ICJRdWFsdHJpY3Pos6rllY/mlofooYzjgpLpmaTlpJblvowiLAogICAgbiA9IG5yb3coZGZfaGVhZGVyX3JlbW92ZWQpCiAgKQoKICBkZiA8LSBkZl9oZWFkZXJfcmVtb3ZlZAoKICBpZiAocmVxdWlyZV9pbml0aWFsX2NvbnNlbnQpIHsKICAgIGlmICghIlExLjEiICVpbiUgbmFtZXMoZGYpKSB7CiAgICAgIHN0b3AoIkNoZWNrIGluaXRpYWwgY29uc2VudCIpCiAgICB9CgogICAgZGYgPC0gZGYgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICBpc19yZXNwb25zZV9jb2RlKFExLjEsIDEpIHwKICAgICAgICAgIHN0cl9kZXRlY3Qobm9ybV90ZXh0KFExLjEpLCAi6Laj5peo44Gr5ZCM5oSP44GX44GmLirljZTlipvjgZnjgosiKQogICAgICApCgogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKAogICAgICBzYW1wbGVfZmxvdywKICAgICAgdGliYmxlKHN0YWdlID0gIuWIneWbnuWQjOaEjyBRMS4xID0gMSIsIG4gPSBucm93KGRmKSkKICAgICkKICB9CgogIGlmIChyZXF1aXJlX2ZpbmFsX2NvbnNlbnQpIHsKICAgIGlmIChpcy5uYShmaW5hbF9jb25zZW50X3ZhcikgfHwgIWZpbmFsX2NvbnNlbnRfdmFyICVpbiUgbmFtZXMoZGYpKSB7CiAgICAgIHN0b3AoIkNoZWNrIGZpbmFsIGNvbnNlbnQiKQogICAgfQoKICAgIGRmIDwtIGRmICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgaXNfcmVzcG9uc2VfY29kZSguZGF0YVtbZmluYWxfY29uc2VudF92YXJdXSwgMSkgfAogICAgICAgICAgc3RyX2RldGVjdCgKICAgICAgICAgICAgbm9ybV90ZXh0KC5kYXRhW1tmaW5hbF9jb25zZW50X3Zhcl1dKSwKICAgICAgICAgICAgIuWQjOaEj+OBly4q5Zue562U57WQ5p6c44KS6YCB5L+h44GZ44KLIgogICAgICAgICAgKQogICAgICApCgogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKAogICAgICBzYW1wbGVfZmxvdywKICAgICAgdGliYmxlKAogICAgICAgIHN0YWdlID0gcGFzdGUwKCLmnIDntYLlkIzmhI8gIiwgZmluYWxfY29uc2VudF92YXIsICIgPSAxIiksCiAgICAgICAgbiA9IG5yb3coZGYpCiAgICAgICkKICAgICkKICB9CgogIGlmIChyZXF1aXJlX2F0dGVudGlvbl9jaGVjaykgewogICAgaWYgKCFhdHRlbnRpb25fY2hlY2tfdmFyICVpbiUgbmFtZXMoZGYpKSB7CiAgICAgIHN0b3AoIkNoZWNrIGF0dGVudGlvbiBpdGVtIikKICAgIH0KCiAgICBhdHRlbnRpb25fY2hlY2tfY29ycmVjdCA8LSBkZXRlY3RfYXR0ZW50aW9uX2NvcnJlY3RfY29kZSgKICAgICAgZGZbW2F0dGVudGlvbl9jaGVja192YXJdXSwKICAgICAgZGlzcGxheWVkX2Fuc3dlciA9IDNMLAogICAgICByZWNvZGVkX2Fuc3dlciA9IDZMLAogICAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAyIgogICAgKQoKICAgIGRmIDwtIGRmICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgaXNfcmVzcG9uc2VfY29kZSgKICAgICAgICAgIC5kYXRhW1thdHRlbnRpb25fY2hlY2tfdmFyXV0sCiAgICAgICAgICBhdHRlbnRpb25fY2hlY2tfY29ycmVjdAogICAgICAgICkKICAgICAgKQoKICAgIHNhbXBsZV9mbG93IDwtIGJpbmRfcm93cygKICAgICAgc2FtcGxlX2Zsb3csCiAgICAgIHRpYmJsZSgKICAgICAgICBzdGFnZSA9IHBhc3RlMCgKICAgICAgICAgICLmjIfnpLrpoIXnm67mraPnrZTvvIgiLAogICAgICAgICAgYXR0ZW50aW9uX2NoZWNrX3ZhciwKICAgICAgICAgICLjgIHkv53lrZjjgrPjg7zjg4k9IiwKICAgICAgICAgIGF0dGVudGlvbl9jaGVja19jb3JyZWN0LAogICAgICAgICAgIu+8iSIKICAgICAgICApLAogICAgICAgIG4gPSBucm93KGRmKQogICAgICApCiAgICApCiAgfQoKICBwcmludChzYW1wbGVfZmxvdykKICB3cml0ZV9jc3Zfc2FmZWx5KHNhbXBsZV9mbG93LCAic2FtcGxlX2Zsb3dfYmVmb3JlX2NvbmpvaW50LmNzdiIpCgoKICBjaG9pY2VfbWFwIDwtIGRldGVjdF9jb25qb2ludF9jaG9pY2VfbWFwKAogICAgcmF3ID0gcmF3LAogICAgcGFydHlfbnVtYmVycyA9IDI6NSwKICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDIiCiAgKQoKICBtYW5pcHVsYXRpb25fbWFwIDwtIGRldGVjdF9tYW5pcHVsYXRpb25fbWFwKAogICAgcmF3ID0gcmF3LAogICAgY2hvaWNlX21hcCA9IGNob2ljZV9tYXAsCiAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAyIgogICkKCiAgd3JpdGVfY3N2X3NhZmVseShjaG9pY2VfbWFwLCAiZGV0ZWN0ZWRfY2hvaWNlX3F1ZXN0aW9uX21hcC5jc3YiKQogIHdyaXRlX2Nzdl9zYWZlbHkobWFuaXB1bGF0aW9uX21hcCwgImRldGVjdGVkX21hbmlwdWxhdGlvbl9xdWVzdGlvbl9tYXAuY3N2IikKCgogIGxldmVsX3RvX2F0dHJfdmFyIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHggPC0gbm9ybV90ZXh0KHgpCgogICAgY2FzZV93aGVuKAogICAgICB4ICVpbiUgYygi5Y+z5rS+44O75L+d5a6I55qEIiwgIuS4remBkyIsICLlt6bmtL7jg7vpnanmlrDnmoQiKSB+CiAgICAgICAgInBvbGljeV9wb3NpdGlvbiIsCgogICAgICB4ICVpbiUgYygi5LiO5YWaIiwgIumHjuWFmiIpIH4KICAgICAgICAiZ292ZXJubWVudF9zdGF0dXMiLAoKICAgICAgc3RyX2RldGVjdCh4LCAiR0RQ5oiQ6ZW3546HIikgfgogICAgICAgICJnZHBfZ3Jvd3RoIiwKCiAgICAgIHN0cl9kZXRlY3QoeCwgIuaXpee1jOW5s+WdhyIpIH4KICAgICAgICAibmlra2VpIiwKCiAgICAgIHggJWluJSBjKCIxMOS7peS4iyIsICIxMH40OSIsICI1MH45OSIsICIxMDB+MTk5IiwgIjIwMOS7peS4iiIpIH4KICAgICAgICAic2VhdHMiLAoKICAgICAgc3RyX2RldGVjdCh4LCAiQ1BJfOeJqeS+oSIpIH4KICAgICAgICAiY3BpIiwKCiAgICAgIHN0cl9kZXRlY3QoeCwgIuWksealreeOh3zpm4fnlKgiKSB+CiAgICAgICAgInVuZW1wbG95bWVudCIsCgogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXwogICAgKQogIH0KCiAgcmVxdWlyZWRfYXR0cl92YXJzIDwtIGMoCiAgICAicG9saWN5X3Bvc2l0aW9uIiwKICAgICJnb3Zlcm5tZW50X3N0YXR1cyIsCiAgICAiZ2RwX2dyb3d0aCIsCiAgICAibmlra2VpIiwKICAgICJzZWF0cyIsCiAgICAiY3BpIiwKICAgICJ1bmVtcGxveW1lbnQiCiAgKQoKICBhbGxvd2VkX2xldmVscyA8LSBsaXN0KAogICAgcG9saWN5X3Bvc2l0aW9uID0gYygi5Y+z5rS+44O75L+d5a6I55qEIiwgIuS4remBkyIsICLlt6bmtL7jg7vpnanmlrDnmoQiKSwKICAgIGdvdmVybm1lbnRfc3RhdHVzID0gYygi5LiO5YWaIiwgIumHjuWFmiIpLAogICAgZ2RwX2dyb3d0aCA9IGMoCiAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiLAogICAgICAiR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAgICJHRFDmiJDplbfnjofjg57jgqTjg4rjgrkx77yFIgogICAgKSwKICAgIG5pa2tlaSA9IGMoCiAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwKICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODnuOCpOODiuOCuTEwMDDlhoYiLAogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIgogICAgKSwKICAgIHNlYXRzID0gYygiMTDku6XkuIsiLCAiMTB+NDkiLCAiNTB+OTkiLCAiMTAwfjE5OSIsICIyMDDku6XkuIoiKSwKICAgIGNwaSA9IGMoCiAgICAgICJDUEnliY3mnJ/mr5TCsTDjg53jgqTjg7Pjg4giLAogICAgICAiQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsCiAgICAgICJDUEnliY3mnJ/mr5Tjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIgogICAgKSwKICAgIHVuZW1wbG95bWVudCA9IGMoCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiLAogICAgICAi5aSx5qWt546H5YmN5pyf5q+U44OX44Op44K5Me+8hSIsCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg57jgqTjg4rjgrkx77yFIgogICAgKQogICkKCgogIG1ha2VfcHJvZmlsZV9sb25nIDwtIGZ1bmN0aW9uKGRhdCwgbl9wYXJ0eSkgewoKICAgIG1hcF9uIDwtIGNob2ljZV9tYXAgJT4lCiAgICAgIGZpbHRlcihwYXJ0eV9uID09IG5fcGFydHkpCgogICAgcXZhcnMgPC0gbWFwX24kY2hvaWNlX3ZhcgoKICAgIG1pc3NpbmdfcSA8LSBzZXRkaWZmKHF2YXJzLCBuYW1lcyhkYXQpKQogICAgaWYgKGxlbmd0aChtaXNzaW5nX3EpID4gMCkgewogICAgICBzdG9wKCJDaGVjayBjaG9pY2UgY29sdW1ucyIpCiAgICB9CgogICAgZGF0X24gPC0gZGF0ICU+JQogICAgICBmaWx0ZXIoaWZfYW55KGFsbF9vZihxdmFycyksIH4gIWlzLm5hKC54KSAmIG5vcm1fdGV4dCgueCkgIT0gIiIpKQoKICAgIGlmIChyZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjaykgewogICAgICBtYW5pcHVsYXRpb25fcm93IDwtIG1hbmlwdWxhdGlvbl9tYXAgJT4lCiAgICAgICAgZmlsdGVyKHBhcnR5X24gPT0gbl9wYXJ0eSkKCiAgICAgIG1hbmlwdWxhdGlvbl92YXIgPC0gbWFuaXB1bGF0aW9uX3JvdyRtYW5pcHVsYXRpb25fdmFyCiAgICAgIGNvcnJlY3RfYW5zd2VyIDwtIG1hbmlwdWxhdGlvbl9yb3ckY29ycmVjdF9hbnN3ZXIKCiAgICAgIGlmICghbWFuaXB1bGF0aW9uX3ZhciAlaW4lIG5hbWVzKGRhdF9uKSkgewogICAgICAgIHN0b3AoIkNoZWNrIG1hbmlwdWxhdGlvbiBpdGVtIikKICAgICAgfQoKICAgICAgZGF0X24gPC0gZGF0X24gJT4lCiAgICAgICAgZmlsdGVyKAogICAgICAgICAgaXNfcmVzcG9uc2VfY29kZSgKICAgICAgICAgICAgLmRhdGFbW21hbmlwdWxhdGlvbl92YXJdXSwKICAgICAgICAgICAgY29ycmVjdF9hbnN3ZXIKICAgICAgICAgICkKICAgICAgICApCiAgICB9CgoKICAgIGNob2ljZV9sb25nIDwtIGRhdF9uICU+JQogICAgICBzZWxlY3QoSUQsIGFsbF9vZihxdmFycykpICU+JQogICAgICBwaXZvdF9sb25nZXIoCiAgICAgICAgY29scyA9IGFsbF9vZihxdmFycyksCiAgICAgICAgbmFtZXNfdG8gPSAiY2hvaWNlX3ZhciIsCiAgICAgICAgdmFsdWVzX3RvID0gImNob2ljZV9yYXciCiAgICAgICkgJT4lCiAgICAgIGxlZnRfam9pbihtYXBfbiwgYnkgPSAiY2hvaWNlX3ZhciIpICU+JQogICAgICBtdXRhdGUoY2hvaWNlID0gcGFyc2VfY2hvaWNlX3Bvc2l0aW9uKGNob2ljZV9yYXcpKSAlPiUKICAgICAgZmlsdGVyKCFpcy5uYShjaG9pY2UpKSAlPiUKICAgICAgc2VsZWN0KElELCBwYXJ0eV9uLCB0YXNrLCBjaG9pY2UpCgogICAgaW52YWxpZF9jaG9pY2UgPC0gY2hvaWNlX2xvbmcgJT4lCiAgICAgIGZpbHRlcihjaG9pY2UgPCAxIHwgY2hvaWNlID4gbl9wYXJ0eSkKCiAgICBpZiAobnJvdyhpbnZhbGlkX2Nob2ljZSkgPiAwKSB7CiAgICAgIHByaW50KGludmFsaWRfY2hvaWNlKQogICAgICBzdG9wKCJDaGVjayBjaG9pY2UgdmFsdWVzIikKICAgIH0KCiAgICBkdXBsaWNhdGVfY2hvaWNlIDwtIGNob2ljZV9sb25nICU+JQogICAgICBjb3VudChJRCwgdGFzaykgJT4lCiAgICAgIGZpbHRlcihuICE9IDEpCgogICAgaWYgKG5yb3coZHVwbGljYXRlX2Nob2ljZSkgPiAwKSB7CiAgICAgIHByaW50KGR1cGxpY2F0ZV9jaG9pY2UpCiAgICAgIHN0b3AoIkNoZWNrIGR1cGxpY2F0ZSBjaG9pY2VzIikKICAgIH0KCgogICAgbGV2ZWxfcmVnZXggPC0gcGFzdGUwKAogICAgICAiXlMyX1AiLCBuX3BhcnR5LAogICAgICAiX0ZfKFsxLTVdKV8oWzEtIiwgbl9wYXJ0eSwgIl0pXyhbMS03XSkkIgogICAgKQoKICAgIGxldmVsX2NvbHMgPC0gbmFtZXMoZGF0X24pW3N0cl9kZXRlY3QobmFtZXMoZGF0X24pLCBsZXZlbF9yZWdleCldCgogICAgZXhwZWN0ZWRfbGV2ZWxfY29scyA8LSA1ICogbl9wYXJ0eSAqIDcKICAgIGlmIChsZW5ndGgobGV2ZWxfY29scykgIT0gZXhwZWN0ZWRfbGV2ZWxfY29scykgewogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgIH0KCiAgICBsZXZlbF9sb25nIDwtIGRhdF9uICU+JQogICAgICBzZWxlY3QoSUQsIGFsbF9vZihsZXZlbF9jb2xzKSkgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gYWxsX29mKGxldmVsX2NvbHMpLAogICAgICAgIG5hbWVzX3RvID0gImZ2YXIiLAogICAgICAgIHZhbHVlc190byA9ICJsZXZlbCIKICAgICAgKSAlPiUKICAgICAgZXh0cmFjdCgKICAgICAgICBmdmFyLAogICAgICAgIGludG8gPSBjKCJ0YXNrIiwgInByb2ZpbGUiLCAiYXR0cl9vcmRlciIpLAogICAgICAgIHJlZ2V4ID0gbGV2ZWxfcmVnZXgsCiAgICAgICAgY29udmVydCA9IFRSVUUKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKGxldmVsID0gbm9ybV90ZXh0KGxldmVsKSkgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICB0YXNrICVpbiUgMTo1LAogICAgICAgIHByb2ZpbGUgJWluJSAxOm5fcGFydHksCiAgICAgICAgYXR0cl9vcmRlciAlaW4lIDE6NywKICAgICAgICAhaXMubmEobGV2ZWwpLAogICAgICAgIGxldmVsICE9ICIiCiAgICAgICkgJT4lCiAgICAgIG11dGF0ZShhdHRyX3ZhciA9IGxldmVsX3RvX2F0dHJfdmFyKGxldmVsKSkKCiAgICB1bmtub3duX2xldmVscyA8LSBsZXZlbF9sb25nICU+JQogICAgICBmaWx0ZXIoaXMubmEoYXR0cl92YXIpKSAlPiUKICAgICAgZGlzdGluY3QobGV2ZWwpCgogICAgaWYgKG5yb3codW5rbm93bl9sZXZlbHMpID4gMCkgewogICAgICBwcmludCh1bmtub3duX2xldmVscykKICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpCiAgICB9CgogICAgcHJvZmlsZV9hdHRyaWJ1dGVfY291bnQgPC0gbGV2ZWxfbG9uZyAlPiUKICAgICAgY291bnQoSUQsIHRhc2ssIHByb2ZpbGUsIG5hbWUgPSAibl9hdHRyaWJ1dGVfcm93cyIpICU+JQogICAgICBmaWx0ZXIobl9hdHRyaWJ1dGVfcm93cyAhPSA3KQoKICAgIGlmIChucm93KHByb2ZpbGVfYXR0cmlidXRlX2NvdW50KSA+IDApIHsKICAgICAgcHJpbnQoaGVhZChwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCwgNTApKQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgIH0KCiAgICBkdXBsaWNhdGVfYXR0cmlidXRlIDwtIGxldmVsX2xvbmcgJT4lCiAgICAgIGNvdW50KElELCB0YXNrLCBwcm9maWxlLCBhdHRyX3ZhcikgJT4lCiAgICAgIGZpbHRlcihuICE9IDEpCgogICAgaWYgKG5yb3coZHVwbGljYXRlX2F0dHJpYnV0ZSkgPiAwKSB7CiAgICAgIHByaW50KGhlYWQoZHVwbGljYXRlX2F0dHJpYnV0ZSwgNTApKQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgIH0KCgogICAgcHJvZmlsZV93aWRlIDwtIGxldmVsX2xvbmcgJT4lCiAgICAgIGlubmVyX2pvaW4oY2hvaWNlX2xvbmcsIGJ5ID0gYygiSUQiLCAidGFzayIpKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIHBhcnR5X24gPSBuX3BhcnR5LAogICAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihwcm9maWxlID09IGNob2ljZSksCiAgICAgICAgdGFza19pZCA9IHBhc3RlKElELCBwYXJ0eV9uLCB0YXNrLCBzZXAgPSAiXyIpLAogICAgICAgIHByb2ZpbGVfaWQgPSBwYXN0ZShJRCwgcGFydHlfbiwgdGFzaywgcHJvZmlsZSwgc2VwID0gIl8iKQogICAgICApICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgSUQsIHBhcnR5X24sIHRhc2ssIHByb2ZpbGUsIGNob2ljZSwgc2VsZWN0ZWQsCiAgICAgICAgdGFza19pZCwgcHJvZmlsZV9pZCwgYXR0cl92YXIsIGxldmVsCiAgICAgICkgJT4lCiAgICAgIHBpdm90X3dpZGVyKAogICAgICAgIG5hbWVzX2Zyb20gPSBhdHRyX3ZhciwKICAgICAgICB2YWx1ZXNfZnJvbSA9IGxldmVsLAogICAgICAgIHZhbHVlc19mbiA9IGxpc3QobGV2ZWwgPSB+IGZpcnN0KC54KSkKICAgICAgKQoKICAgIG1pc3NpbmdfYXR0ciA8LSBzZXRkaWZmKHJlcXVpcmVkX2F0dHJfdmFycywgbmFtZXMocHJvZmlsZV93aWRlKSkKCiAgICBpZiAobGVuZ3RoKG1pc3NpbmdfYXR0cikgPiAwKSB7CiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgfQoKICAgIHByb2ZpbGVfd2lkZSA8LSBwcm9maWxlX3dpZGUgJT4lCiAgICAgIHNlbGVjdCgKICAgICAgICBJRCwgcGFydHlfbiwgdGFzaywgcHJvZmlsZSwgY2hvaWNlLCBzZWxlY3RlZCwKICAgICAgICB0YXNrX2lkLCBwcm9maWxlX2lkLAogICAgICAgIGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpCiAgICAgICkgJT4lCiAgICAgIGFycmFuZ2UoSUQsIHRhc2ssIHByb2ZpbGUpCgogICAgcmV0dXJuKHByb2ZpbGVfd2lkZSkKICB9CgoKICBjb25qb2ludF8yIDwtIG1ha2VfcHJvZmlsZV9sb25nKGRmLCAyKQogIGNvbmpvaW50XzMgPC0gbWFrZV9wcm9maWxlX2xvbmcoZGYsIDMpCiAgY29uam9pbnRfNCA8LSBtYWtlX3Byb2ZpbGVfbG9uZyhkZiwgNCkKICBjb25qb2ludF81IDwtIG1ha2VfcHJvZmlsZV9sb25nKGRmLCA1KQoKICBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCA8LSBiaW5kX3Jvd3MoCiAgICBjb25qb2ludF8yLAogICAgY29uam9pbnRfMywKICAgIGNvbmpvaW50XzQsCiAgICBjb25qb2ludF81CiAgKQoKCiAgaWRfdGFza19jaGVjayA8LSBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCAlPiUKICAgIGdyb3VwX2J5KElELCBwYXJ0eV9uLCB0YXNrKSAlPiUKICAgIHN1bW1hcmlzZSgKICAgICAgbl9wcm9maWxlcyA9IG4oKSwKICAgICAgc2VsZWN0ZWRfc3VtID0gc3VtKHNlbGVjdGVkKSwKICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgKSAlPiUKICAgIGdyb3VwX2J5KElELCBwYXJ0eV9uKSAlPiUKICAgIHN1bW1hcmlzZSgKICAgICAgbl90YXNrcyA9IG5fZGlzdGluY3QodGFzayksCiAgICAgIGFsbF90YXNrc19vayA9IGFsbChuX3Byb2ZpbGVzID09IHBhcnR5X24gJiBzZWxlY3RlZF9zdW0gPT0gMSksCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkKCiAgdmFsaWRfaWRzIDwtIGlkX3Rhc2tfY2hlY2sgJT4lCiAgICBmaWx0ZXIobl90YXNrcyA9PSA1LCBhbGxfdGFza3Nfb2spCgogIGNvbmpvaW50X2FsbCA8LSBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCAlPiUKICAgIHNlbWlfam9pbih2YWxpZF9pZHMsIGJ5ID0gYygiSUQiLCAicGFydHlfbiIpKQoKICBuX2J5X3BhcnR5IDwtIHZhbGlkX2lkcyAlPiUKICAgIGNvdW50KHBhcnR5X24sIG5hbWUgPSAibiIpICU+JQogICAgY29tcGxldGUocGFydHlfbiA9IDI6NSwgZmlsbCA9IGxpc3QobiA9IDApKSAlPiUKICAgIGFycmFuZ2UocGFydHlfbikKCiAgbl90b3RhbCA8LSB2YWxpZF9pZHMgJT4lCiAgICBzdW1tYXJpc2UobiA9IG5fZGlzdGluY3QoSUQpKSAlPiUKICAgIHB1bGwobikKCiAgZmlndXJlX25fbGFiZWxzIDwtIGJpbmRfcm93cygKICAgIHRpYmJsZSgKICAgICAgcG9zaXRpb24gPSAi5YWo44K144Oz44OX44OrIiwKICAgICAgbGFiZWwgPSBwYXN0ZTAoIuWFqOOCteODs+ODl+ODqywgbj0iLCBzY2FsZXM6OmNvbW1hKG5fdG90YWwpKQogICAgKSwKICAgIG5fYnlfcGFydHkgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBwb3NpdGlvbiA9IHBhc3RlMChwYXJ0eV9uLCAi5pS/5YWa6YG45oqeIiksCiAgICAgICAgbGFiZWwgPSBwYXN0ZTAoIm49Iiwgc2NhbGVzOjpjb21tYShuKSkKICAgICAgKSAlPiUKICAgICAgc2VsZWN0KHBvc2l0aW9uLCBsYWJlbCkKICApCgogIGNhdCgiXG7liIbmnpDlr77osaHogIXmlbBcbiIpCiAgcHJpbnQobl9ieV9wYXJ0eSkKICBjYXQoIuWFqOOCteODs+ODl+ODqyBuPSIsIG5fdG90YWwsICJcbiIsIHNlcCA9ICIiKQoKICB3cml0ZV9jc3Zfc2FmZWx5KGlkX3Rhc2tfY2hlY2ssICJpZF90YXNrX2NoZWNrLmNzdiIpCiAgd3JpdGVfY3N2X3NhZmVseSh2YWxpZF9pZHMsICJ2YWxpZF9pZHMuY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KG5fYnlfcGFydHksICJuX2J5X3BhcnR5LmNzdiIpCiAgd3JpdGVfY3N2X3NhZmVseShmaWd1cmVfbl9sYWJlbHMsICJmaWd1cmVfbl9sYWJlbHMuY3N2IikKCgogIGNoZWNrX3Byb2ZpbGUgPC0gY29uam9pbnRfYWxsICU+JQogICAgZ3JvdXBfYnkocGFydHlfbiwgSUQsIHRhc2ssIHRhc2tfaWQpICU+JQogICAgc3VtbWFyaXNlKAogICAgICBuX3Byb2ZpbGVzID0gbigpLAogICAgICBzZWxlY3RlZF9zdW0gPSBzdW0oc2VsZWN0ZWQpLAogICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICApICU+JQogICAgY291bnQocGFydHlfbiwgbl9wcm9maWxlcywgc2VsZWN0ZWRfc3VtKQoKICBwcmludChjaGVja19wcm9maWxlKQoKICBzdG9waWZub3QoYWxsKGNoZWNrX3Byb2ZpbGUkbl9wcm9maWxlcyA9PSBjaGVja19wcm9maWxlJHBhcnR5X24pKQogIHN0b3BpZm5vdChhbGwoY2hlY2tfcHJvZmlsZSRzZWxlY3RlZF9zdW0gPT0gMSkpCgogIGFsbG93ZWRfZGYgPC0gZW5mcmFtZShhbGxvd2VkX2xldmVscywgbmFtZSA9ICJuYW1lIiwgdmFsdWUgPSAidmFsdWUiKSAlPiUKICAgIHVubmVzdCh2YWx1ZSkKCiAgdW5leHBlY3RlZF92YWx1ZXMgPC0gY29uam9pbnRfYWxsICU+JQogICAgc2VsZWN0KGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpKSAlPiUKICAgIHBpdm90X2xvbmdlcigKICAgICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgbmFtZXNfdG8gPSAibmFtZSIsCiAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIKICAgICkgJT4lCiAgICBmaWx0ZXIoIWlzLm5hKHZhbHVlKSwgdmFsdWUgIT0gIiIpICU+JQogICAgZGlzdGluY3QobmFtZSwgdmFsdWUpICU+JQogICAgYW50aV9qb2luKGFsbG93ZWRfZGYsIGJ5ID0gYygibmFtZSIsICJ2YWx1ZSIpKQoKICBwcmludCh1bmV4cGVjdGVkX3ZhbHVlcykKICBzdG9waWZub3QobnJvdyh1bmV4cGVjdGVkX3ZhbHVlcykgPT0gMCkKCiAgb2JzZXJ2ZWRfbGV2ZWxzIDwtIGNvbmpvaW50X2FsbCAlPiUKICAgIHNlbGVjdChhbGxfb2YocmVxdWlyZWRfYXR0cl92YXJzKSkgJT4lCiAgICBwaXZvdF9sb25nZXIoCiAgICAgIGNvbHMgPSBldmVyeXRoaW5nKCksCiAgICAgIG5hbWVzX3RvID0gImF0dHJpYnV0ZSIsCiAgICAgIHZhbHVlc190byA9ICJsZXZlbCIKICAgICkgJT4lCiAgICBkaXN0aW5jdChhdHRyaWJ1dGUsIGxldmVsKSAlPiUKICAgIGFycmFuZ2UoYXR0cmlidXRlLCBsZXZlbCkKCiAgd3JpdGVfY3N2X3NhZmVseShjaGVja19wcm9maWxlLCAicHJvZmlsZV9leHBhbnNpb25fY2hlY2suY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KG9ic2VydmVkX2xldmVscywgIm9ic2VydmVkX2F0dHJpYnV0ZV9sZXZlbHMuY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KGNvbmpvaW50X2FsbCwgInN0dWR5Ml9wcm9maWxlX2xldmVsX2RhdGEuY3N2IikKCgogIGFuYWx5c2lzX2lkcyA8LSB2YWxpZF9pZHMgJT4lCiAgICBzZWxlY3QoSUQsIHBhcnR5X24pCgogIGF0dGVudGlvbl9zdW1tYXJ5IDwtIGRmICU+JQogICAgc2VtaV9qb2luKGFuYWx5c2lzX2lkcywgYnkgPSAiSUQiKSAlPiUKICAgIHRyYW5zbXV0ZSgKICAgICAgSUQsCiAgICAgIGF0dGVudGlvbl9yZXNwb25zZSA9IG5vcm1fdGV4dCguZGF0YVtbYXR0ZW50aW9uX2NoZWNrX3Zhcl1dKSwKICAgICAgYXR0ZW50aW9uX3Bhc3MgPSBpc19yZXNwb25zZV9jb2RlKAogICAgICAgIC5kYXRhW1thdHRlbnRpb25fY2hlY2tfdmFyXV0sCiAgICAgICAgYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QKICAgICAgKQogICAgKSAlPiUKICAgIGNvdW50KGF0dGVudGlvbl9yZXNwb25zZSwgYXR0ZW50aW9uX3Bhc3MsIG5hbWUgPSAibiIpICU+JQogICAgYXJyYW5nZShkZXNjKGF0dGVudGlvbl9wYXNzKSwgYXR0ZW50aW9uX3Jlc3BvbnNlKQoKICBtYW5pcHVsYXRpb25fc3VtbWFyeSA8LSBtYXBfZGZyKDI6NSwgZnVuY3Rpb24obl9wYXJ0eSkgewogICAgbWFuaXB1bGF0aW9uX3JvdyA8LSBtYW5pcHVsYXRpb25fbWFwICU+JQogICAgICBmaWx0ZXIocGFydHlfbiA9PSBuX3BhcnR5KQoKICAgIHYgPC0gbWFuaXB1bGF0aW9uX3JvdyRtYW5pcHVsYXRpb25fdmFyCiAgICBjb3JyZWN0IDwtIG1hbmlwdWxhdGlvbl9yb3ckY29ycmVjdF9hbnN3ZXIKCiAgICBkZiAlPiUKICAgICAgc2VtaV9qb2luKAogICAgICAgIGFuYWx5c2lzX2lkcyAlPiUgZmlsdGVyKHBhcnR5X24gPT0gbl9wYXJ0eSksCiAgICAgICAgYnkgPSAiSUQiCiAgICAgICkgJT4lCiAgICAgIHRyYW5zbXV0ZSgKICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwKICAgICAgICByZXNwb25zZSA9IG5vcm1fdGV4dCguZGF0YVtbdl1dKSwKICAgICAgICBjb3JyZWN0ID0gaXNfcmVzcG9uc2VfY29kZSguZGF0YVtbdl1dLCBjb3JyZWN0KQogICAgICApICU+JQogICAgICBjb3VudChwYXJ0eV9uLCByZXNwb25zZSwgY29ycmVjdCwgbmFtZSA9ICJuIikKICB9KQoKICB3cml0ZV9jc3Zfc2FmZWx5KGF0dGVudGlvbl9zdW1tYXJ5LCAiYXR0ZW50aW9uX2NoZWNrX3N1bW1hcnkuY3N2IikKICB3cml0ZV9jc3Zfc2FmZWx5KG1hbmlwdWxhdGlvbl9zdW1tYXJ5LCAicGFydHlfbnVtYmVyX2NoZWNrX3N1bW1hcnkuY3N2IikKCgogIGNvbmpvaW50X2FsbF9tIDwtIGNvbmpvaW50X2FsbCAlPiUKICAgIG11dGF0ZSgKICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHNlbGVjdGVkKSwKICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAoKICAgICAgcG9saWN5X3Bvc2l0aW9uID0gZmFjdG9yKAogICAgICAgIHBvbGljeV9wb3NpdGlvbiwKICAgICAgICBsZXZlbHMgPSBjKCLkuK3pgZMiLCAi5Y+z5rS+44O75L+d5a6I55qEIiwgIuW3pua0vuODu+mdqeaWsOeahCIpCiAgICAgICksCgogICAgICBnb3Zlcm5tZW50X3N0YXR1cyA9IGZhY3RvcigKICAgICAgICBnb3Zlcm5tZW50X3N0YXR1cywKICAgICAgICBsZXZlbHMgPSBjKCLph47lhZoiLCAi5LiO5YWaIikKICAgICAgKSwKCiAgICAgIGdkcF9ncm93dGggPSBmYWN0b3IoCiAgICAgICAgZ2RwX2dyb3d0aCwKICAgICAgICBsZXZlbHMgPSBjKAogICAgICAgICAgIkdEUOaIkOmVt+eOh8KxMO+8hSIsCiAgICAgICAgICAiR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAgICAgICAiR0RQ5oiQ6ZW3546H44Oe44Kk44OK44K5Me+8hSIKICAgICAgICApCiAgICAgICksCgogICAgICBuaWtrZWkgPSBmYWN0b3IoCiAgICAgICAgbmlra2VpLAogICAgICAgIGxldmVscyA9IGMoCiAgICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIiwKICAgICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwKICAgICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIgogICAgICAgICkKICAgICAgKSwKCiAgICAgIHNlYXRzID0gZmFjdG9yKAogICAgICAgIHNlYXRzLAogICAgICAgIGxldmVscyA9IGMoIjEw5Lul5LiLIiwgIjEwfjQ5IiwgIjUwfjk5IiwgIjEwMH4xOTkiLCAiMjAw5Lul5LiKIikKICAgICAgKSwKCiAgICAgIGNwaSA9IGZhY3RvcigKICAgICAgICBjcGksCiAgICAgICAgbGV2ZWxzID0gYygKICAgICAgICAgICJDUEnliY3mnJ/mr5TCsTDjg53jgqTjg7Pjg4giLAogICAgICAgICAgIkNQSeWJjeacn+avlOODl+ODqeOCuTHjg53jgqTjg7Pjg4giLAogICAgICAgICAgIkNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giCiAgICAgICAgKQogICAgICApLAoKICAgICAgdW5lbXBsb3ltZW50ID0gZmFjdG9yKAogICAgICAgIHVuZW1wbG95bWVudCwKICAgICAgICBsZXZlbHMgPSBjKAogICAgICAgICAgIuWksealreeOh+WJjeacn+avlMKxMO+8hSIsCiAgICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+U44OX44Op44K5Me+8hSIsCiAgICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+U44Oe44Kk44OK44K5Me+8hSIKICAgICAgICApCiAgICAgICksCgogICAgICBwYXJ0eV9uX2YgPSBmYWN0b3IoCiAgICAgICAgYXMuY2hhcmFjdGVyKHBhcnR5X24pLAogICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKQogICAgICApCiAgICApCgogIGF0dHJfdGVybXMgPC0gYygKICAgICJwb2xpY3lfcG9zaXRpb24iLAogICAgImdvdmVybm1lbnRfc3RhdHVzIiwKICAgICJnZHBfZ3Jvd3RoIiwKICAgICJuaWtrZWkiLAogICAgInNlYXRzIiwKICAgICJjcGkiLAogICAgInVuZW1wbG95bWVudCIKICApCgoKICBmb3JtdWxhX25vY292IDwtIGFzLmZvcm11bGEoCiAgICBwYXN0ZSgic2VsZWN0ZWQgfiIsIHBhc3RlKGF0dHJfdGVybXMsIGNvbGxhcHNlID0gIiArICIpKQogICkKCiAgcnVuX2FtY2Vfbm9jb3YgPC0gZnVuY3Rpb24oZGF0KSB7CiAgICBmZW9scygKICAgICAgZm9ybXVsYV9ub2NvdiwKICAgICAgZGF0YSA9IGRhdCwKICAgICAgdmNvdiA9IH4gSUQKICAgICkKICB9CgogIG1vZGVsc19ieV9wYXJ0eV9uX25vY292IDwtIGNvbmpvaW50X2FsbF9tICU+JQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUKICAgIG1hcChydW5fYW1jZV9ub2NvdikKCiAgY2FwdHVyZS5vdXRwdXQoCiAgICBldGFibGUobW9kZWxzX2J5X3BhcnR5X25fbm9jb3YpLAogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAiYW1jZV9ub2Nvdl9tb2RlbHMudHh0IikKICApCgoKICBtX2ludGVyYWN0aW9uIDwtIGZlb2xzKAogICAgc2VsZWN0ZWQgfgogICAgICBwYXJ0eV9uX2YgKgogICAgICAoCiAgICAgICAgcG9saWN5X3Bvc2l0aW9uICsKICAgICAgICAgIGdvdmVybm1lbnRfc3RhdHVzICsKICAgICAgICAgIGdkcF9ncm93dGggKwogICAgICAgICAgbmlra2VpICsKICAgICAgICAgIHNlYXRzICsKICAgICAgICAgIGNwaSArCiAgICAgICAgICB1bmVtcGxveW1lbnQKICAgICAgKSwKICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwKICAgIHZjb3YgPSB+IElECiAgKQoKICBjYXB0dXJlLm91dHB1dCgKICAgIHN1bW1hcnkobV9pbnRlcmFjdGlvbiksCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJhbWNlX2ludGVyYWN0aW9uX21vZGVsLnR4dCIpCiAgKQoKCiAgdGlkeV9maXhlc3QgPC0gZnVuY3Rpb24obW9kZWwpIHsKICAgIGN0IDwtIGFzLmRhdGEuZnJhbWUoZml4ZXN0Ojpjb2VmdGFibGUobW9kZWwpKQogICAgY3QkdGVybSA8LSByb3duYW1lcyhjdCkKCiAgICBjdCAlPiUKICAgICAgYXNfdGliYmxlKCkgJT4lCiAgICAgIHJlbmFtZSgKICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlLAogICAgICAgIHN0ZC5lcnJvciA9IGBTdGQuIEVycm9yYCwKICAgICAgICBzdGF0aXN0aWMgPSBgdCB2YWx1ZWAsCiAgICAgICAgcC52YWx1ZSA9IGBQcig+fHR8KWAKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGNvbmYubG93ID0gZXN0aW1hdGUgLSAxLjk2ICogc3RkLmVycm9yLAogICAgICAgIGNvbmYuaGlnaCA9IGVzdGltYXRlICsgMS45NiAqIHN0ZC5lcnJvcgogICAgICApICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgdGVybSwgZXN0aW1hdGUsIHN0ZC5lcnJvciwgc3RhdGlzdGljLCBwLnZhbHVlLAogICAgICAgIGNvbmYubG93LCBjb25mLmhpZ2gKICAgICAgKQogIH0KCiAgdGVybV9sYWJlbHMgPC0gdHJpYmJsZSgKICAgIH50ZXJtLCB+YXR0cmlidXRlLCB+Y3VlX3R5cGUsIH5sYWJlbCwgfm9yZGVyLAoKICAgICJnb3Zlcm5tZW50X3N0YXR1c+S4juWFmiIsCiAgICAi5LiO5YWa77yP6YeO5YWaIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLkuI7lhZoiLCAxLAoKICAgICJwb2xpY3lfcG9zaXRpb27lj7PmtL7jg7vkv53lrojnmoQiLAogICAgIuaUv+etluS9jee9riIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi5Y+z5rS+44O75L+d5a6I55qEIiwgMiwKCiAgICAicG9saWN5X3Bvc2l0aW9u5bem5rS+44O76Z2p5paw55qEIiwKICAgICLmlL/nrZbkvY3nva4iLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuW3pua0vuODu+mdqeaWsOeahCIsIDMsCgogICAgInNlYXRzMTB+NDkiLAogICAgIuitsOW4reaVsCIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi6K2w5bit5pWw77yaMTDvvZ40OSIsIDQsCgogICAgInNlYXRzNTB+OTkiLAogICAgIuitsOW4reaVsCIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi6K2w5bit5pWw77yaNTDvvZ45OSIsIDUsCgogICAgInNlYXRzMTAwfjE5OSIsCiAgICAi6K2w5bit5pWwIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLorbDluK3mlbDvvJoxMDDvvZ4xOTkiLCA2LAoKICAgICJzZWF0czIwMOS7peS4iiIsCiAgICAi6K2w5bit5pWwIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLorbDluK3mlbDvvJoyMDDku6XkuIoiLCA3LAoKICAgICJnZHBfZ3Jvd3RoR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAiR0RQ5oiQ6ZW3546HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICJHRFDvvJrjg5fjg6njgrkx77yFIiwgOCwKCiAgICAiZ2RwX2dyb3d0aEdEUOaIkOmVt+eOh+ODnuOCpOODiuOCuTHvvIUiLAogICAgIkdEUOaIkOmVt+eOhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAiR0RQ77ya44Oe44Kk44OK44K5Me+8hSIsIDksCgogICAgIm5pa2tlaeaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLAogICAgIuaXpee1jOW5s+WdhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAi5pel57WM5bmz5Z2H77ya44OX44Op44K5MTAwMOWGhiIsIDEwLAoKICAgICJuaWtrZWnml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIiwKICAgICLml6XntYzlubPlnYciLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIuaXpee1jOW5s+Wdh++8muODnuOCpOODiuOCuTEwMDDlhoYiLCAxMSwKCiAgICAiY3BpQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsCiAgICAiQ1BJIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICJDUEnvvJrjg5fjg6njgrkx44Od44Kk44Oz44OIIiwgMTIsCgogICAgImNwaUNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giLAogICAgIkNQSSIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAiQ1BJ77ya44Oe44Kk44OK44K5MeODneOCpOODs+ODiCIsIDEzLAoKICAgICJ1bmVtcGxveW1lbnTlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwKICAgICLlpLHmpa3njociLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIuWksealreeOh++8muODl+ODqeOCuTHvvIUiLCAxNCwKCiAgICAidW5lbXBsb3ltZW505aSx5qWt546H5YmN5pyf5q+U44Oe44Kk44OK44K5Me+8hSIsCiAgICAi5aSx5qWt546HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICLlpLHmpa3njofvvJrjg57jgqTjg4rjgrkx77yFIiwgMTUKICApCgogIGF0dHJpYnV0ZV9vcmRlciA8LSBjKAogICAgIuS4juWFmu+8j+mHjuWFmiIsCiAgICAi5pS/562W5L2N572uIiwKICAgICLorbDluK3mlbAiLAogICAgIkdEUOaIkOmVt+eOhyIsCiAgICAi5pel57WM5bmz5Z2HIiwKICAgICJDUEkiLAogICAgIuWksealreeOhyIKICApCgogIGxhYmVsX29yZGVyIDwtIHRlcm1fbGFiZWxzICU+JQogICAgYXJyYW5nZShvcmRlcikgJT4lCiAgICBwdWxsKGxhYmVsKQoKICBtYWtlX2FtY2VfcGxvdF9kZiA8LSBmdW5jdGlvbihtb2RlbHMpIHsKICAgIGltYXBfZGZyKAogICAgICBtb2RlbHMsCiAgICAgIH4gdGlkeV9maXhlc3QoLngpICU+JQogICAgICAgIG11dGF0ZShwYXJ0eV9uID0gYXMuY2hhcmFjdGVyKC55KSkKICAgICkgJT4lCiAgICAgIGxlZnRfam9pbih0ZXJtX2xhYmVscywgYnkgPSAidGVybSIpICU+JQogICAgICBmaWx0ZXIoIWlzLm5hKGF0dHJpYnV0ZSkpICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwKICAgICAgICBjb25mLmxvd19wcCA9IGNvbmYubG93ICogMTAwLAogICAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwKICAgICAgICBwYXJ0eV9uID0gZmFjdG9yKAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKSwKICAgICAgICAgIGxhYmVscyA9IGMoIjLmlL/lhZoiLCAiM+aUv+WFmiIsICI05pS/5YWaIiwgIjXmlL/lhZoiKQogICAgICAgICksCiAgICAgICAgYXR0cmlidXRlID0gZmFjdG9yKGF0dHJpYnV0ZSwgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyKSwKICAgICAgICBsYWJlbCA9IGZhY3RvcihsYWJlbCwgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKSkKICAgICAgKQogIH0KCiAgYW1jZV9wbG90X25vY292IDwtIG1ha2VfYW1jZV9wbG90X2RmKG1vZGVsc19ieV9wYXJ0eV9uX25vY292KQogIHdyaXRlX2Nzdl9zYWZlbHkoYW1jZV9wbG90X25vY292LCAiYW1jZV9ub2Nvdl9jb2VmZmljaWVudHMuY3N2IikKCiAgaW50ZXJhY3Rpb25fcGxvdF9kZiA8LSB0aWR5X2ZpeGVzdChtX2ludGVyYWN0aW9uKSAlPiUKICAgIGZpbHRlcihzdHJfZGV0ZWN0KHRlcm0sICJwYXJ0eV9uX2ZbMzQ1XSIpKSAlPiUKICAgIG11dGF0ZSgKICAgICAgcGFydHlfbl9jb2RlID0gc3RyX2V4dHJhY3QodGVybSwgInBhcnR5X25fZlszNDVdIiksCiAgICAgIHBhcnR5X24gPSBzdHJfcmVtb3ZlKHBhcnR5X25fY29kZSwgInBhcnR5X25fZiIpLAogICAgICBiYXNlX3Rlcm0gPSB0ZXJtICU+JQogICAgICAgIHN0cl9yZW1vdmUoInBhcnR5X25fZlszNDVdOiIpICU+JQogICAgICAgIHN0cl9yZW1vdmUoIjpwYXJ0eV9uX2ZbMzQ1XSIpCiAgICApICU+JQogICAgbGVmdF9qb2luKHRlcm1fbGFiZWxzLCBieSA9IGMoImJhc2VfdGVybSIgPSAidGVybSIpKSAlPiUKICAgIGZpbHRlcighaXMubmEoYXR0cmlidXRlKSkgJT4lCiAgICBtdXRhdGUoCiAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwKICAgICAgcGFydHlfbl9sYWJlbCA9IGZhY3RvcigKICAgICAgICBwYXJ0eV9uLAogICAgICAgIGxldmVscyA9IGMoIjMiLCAiNCIsICI1IiksCiAgICAgICAgbGFiZWxzID0gYygiM+aUv+WFmiIsICI05pS/5YWaIiwgIjXmlL/lhZoiKQogICAgICApLAogICAgICBhdHRyaWJ1dGUgPSBmYWN0b3IoYXR0cmlidXRlLCBsZXZlbHMgPSBhdHRyaWJ1dGVfb3JkZXIpLAogICAgICBsYWJlbCA9IGZhY3RvcihsYWJlbCwgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKSkKICAgICkKCiAgd3JpdGVfY3N2X3NhZmVseShpbnRlcmFjdGlvbl9wbG90X2RmLCAiYW1jZV9pbnRlcmFjdGlvbl9jb2VmZmljaWVudHMuY3N2IikKCgogIHJlY29kZV9mZW1hbGVfc3R1ZHkyIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHhfbnVtIDwtIGFzX251bSh4KQoKICAgIGNhc2Vfd2hlbigKICAgICAgeF9udW0gPT0gMiB+IDFMLAogICAgICB4X251bSA9PSAxIH4gMEwsCiAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXwogICAgKQogIH0KCiAgcmVjb2RlX2NvbGxlZ2VfZ3JhZF9zdHVkeTIgPC0gZnVuY3Rpb24oeCkgewogICAgeF9udW0gPC0gYXNfbnVtKHgpCgogICAgY2FzZV93aGVuKAogICAgICB4X251bSAlaW4lIGMoNCwgNSkgfiAxTCwKICAgICAgeF9udW0gJWluJSBjKDEsIDIsIDMpIH4gMEwsCiAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXwogICAgKQogIH0KCiAgcmVjb2RlX3BhcnR5X3N1cHBvcnRfc3R1ZHkyIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHhfbnVtIDwtIGFzX251bSh4KQoKICAgIGNhc2Vfd2hlbigKICAgICAgeF9udW0gPT0gMSB+ICLoh6rnlLHmsJHkuLvlhZoiLAogICAgICB4X251bSA9PSAyIH4gIuS4remBk+aUuemdqemAo+WQiCIsCiAgICAgIHhfbnVtID09IDMgfiAi56uL5oay5rCR5Li75YWaIiwKICAgICAgeF9udW0gPT0gNCB+ICLlhazmmI7lhZoiLAogICAgICB4X251bSA9PSA1IH4gIuaXpeacrOe2reaWsOOBruS8miIsCiAgICAgIHhfbnVtID09IDYgfiAi5Zu95rCR5rCR5Li75YWaIiwKICAgICAgeF9udW0gPT0gNyB+ICLjgozjgYTjgo/mlrDpgbjntYQiLAogICAgICB4X251bSA9PSA4IH4gIuaXpeacrOWFseeUo+WFmiIsCiAgICAgIHhfbnVtID09IDkgfiAi5Y+C5pS/5YWaIiwKICAgICAgeF9udW0gPT0gMTAgfiAi5pel5pys5L+d5a6I5YWaIiwKICAgICAgeF9udW0gPT0gMTEgfiAi56S+5Lya5rCR5Li75YWaIiwKICAgICAgeF9udW0gPT0gMTIgfiAi44OB44O844Og44G/44KJ44GEIiwKICAgICAgeF9udW0gPT0gMTMgfiAi44Gd44Gu5LuWIiwKICAgICAgeF9udW0gPT0gMTQgfiAi5pSv5oyB5pS/5YWa44Gq44GXIiwKICAgICAgeF9udW0gPT0gMTUgfiAi44KP44GL44KJ44Gq44GEIiwKICAgICAgeF9udW0gPT0gMTYgfiAi562U44GI44Gf44GP44Gq44GEIiwKICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8KICAgICkKICB9CgogIGdlbmRlcl9yYXcgPC0gZ2V0X3ZhcihkZiwgYygiUTIuMSIsICJRMl8xIikpCiAgYWdlX3JhdyA8LSBnZXRfdmFyKGRmLCBjKCJRMi4yXzIiLCAiUTIuMi4yIiwgIlEyXzJfMiIpKQogIGVkdWNhdGlvbl9yYXcgPC0gZ2V0X3ZhcihkZiwgYygiUTIuMyIsICJRMl8zIikpCiAgaW5jb21lX2dyb3NzX3JhdyA8LSBnZXRfdmFyKGRmLCBjKCJRMi41XzEiLCAiUTIuNS4xIiwgIlEyXzVfMSIpKQogIGluY29tZV9uZXRfcmF3IDwtIGdldF92YXIoZGYsIGMoIlEyLjVfMiIsICJRMi41LjIiLCAiUTJfNV8yIikpCiAgcGFydHlfc3VwcG9ydF9yYXcgPC0gZ2V0X3ZhcihkZiwgYygiUTguMiIsICJROF8yIikpCgogIGNvdmFyX2lkIDwtIGRmICU+JQogICAgdHJhbnNtdXRlKAogICAgICBJRCA9IGFzLmNoYXJhY3RlcihSZXNwb25zZUlkKSwKICAgICAgZmVtYWxlID0gcmVjb2RlX2ZlbWFsZV9zdHVkeTIoZ2VuZGVyX3JhdyksCiAgICAgIGFnZSA9IGFzX251bShhZ2VfcmF3KSwKICAgICAgY29sbGVnZV9ncmFkID0gcmVjb2RlX2NvbGxlZ2VfZ3JhZF9zdHVkeTIoZWR1Y2F0aW9uX3JhdyksCiAgICAgIGluY29tZV9ncm9zcyA9IGFzX251bShpbmNvbWVfZ3Jvc3NfcmF3KSwKICAgICAgaW5jb21lX25ldCA9IGFzX251bShpbmNvbWVfbmV0X3JhdyksCiAgICAgIGluY29tZV9ncm9zc19sb2cgPSBsb2cxcChpbmNvbWVfZ3Jvc3MpLAogICAgICBpbmNvbWVfbmV0X2xvZyA9IGxvZzFwKGluY29tZV9uZXQpLAogICAgICBwYXJ0eV9zdXBwb3J0ID0gcmVjb2RlX3BhcnR5X3N1cHBvcnRfc3R1ZHkyKHBhcnR5X3N1cHBvcnRfcmF3KSwKICAgICAgcGFydHlfc3VwcG9ydF9mID0gZmFjdG9yX21pc3MocGFydHlfc3VwcG9ydCkKICAgICkgJT4lCiAgICBzZW1pX2pvaW4odmFsaWRfaWRzICU+JSBzZWxlY3QoSUQpLCBieSA9ICJJRCIpICU+JQogICAgZGlzdGluY3QoSUQsIC5rZWVwX2FsbCA9IFRSVUUpCgogIGNvdmFyX2lkIDwtIGNvdmFyX2lkICU+JQogICAgbXV0YXRlKAogICAgICBhZ2UgPSBpZl9lbHNlKGFnZSA+PSAxOCAmIGFnZSA8PSA3OSwgYWdlLCBOQV9yZWFsXykKICAgICkKCiAgYWdlX2ltcF9vYmogPC0gbWVhbl9pbXB1dGUoY292YXJfaWQkYWdlKQogIGluY29tZV9ncm9zc19pbXBfb2JqIDwtIG1lYW5faW1wdXRlKGNvdmFyX2lkJGluY29tZV9ncm9zc19sb2cpCgogIGNvdmFyX2lkIDwtIGNvdmFyX2lkICU+JQogICAgbXV0YXRlKAogICAgICBmZW1hbGVfaW1wID0gaWZfZWxzZShpcy5uYShmZW1hbGUpLCAwTCwgZmVtYWxlKSwKICAgICAgZmVtYWxlX21pc3MgPSBhcy5pbnRlZ2VyKGlzLm5hKGZlbWFsZSkpLAoKICAgICAgY29sbGVnZV9ncmFkX2ltcCA9IGlmX2Vsc2UoaXMubmEoY29sbGVnZV9ncmFkKSwgMEwsIGNvbGxlZ2VfZ3JhZCksCiAgICAgIGNvbGxlZ2VfZ3JhZF9taXNzID0gYXMuaW50ZWdlcihpcy5uYShjb2xsZWdlX2dyYWQpKSwKCiAgICAgIGFnZV9pbXAgPSBhZ2VfaW1wX29iaiR2YWx1ZSwKICAgICAgYWdlX21pc3MgPSBhZ2VfaW1wX29iaiRtaXNzLAoKICAgICAgaW5jb21lX2dyb3NzX2xvZ19pbXAgPSBpbmNvbWVfZ3Jvc3NfaW1wX29iaiR2YWx1ZSwKICAgICAgaW5jb21lX2dyb3NzX2xvZ19taXNzID0gaW5jb21lX2dyb3NzX2ltcF9vYmokbWlzcwogICAgKQoKICBjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5IDwtIGNvdmFyX2lkICU+JQogICAgc3VtbWFyaXNlKAogICAgICBuX2lkcyA9IG5fZGlzdGluY3QoSUQpLAogICAgICBmZW1hbGVfbWlzc2luZyA9IHN1bShpcy5uYShmZW1hbGUpKSwKICAgICAgYWdlX21pc3NpbmcgPSBzdW0oaXMubmEoYWdlKSksCiAgICAgIGNvbGxlZ2VfZ3JhZF9taXNzaW5nID0gc3VtKGlzLm5hKGNvbGxlZ2VfZ3JhZCkpLAogICAgICBpbmNvbWVfZ3Jvc3NfbWlzc2luZyA9IHN1bShpcy5uYShpbmNvbWVfZ3Jvc3NfbG9nKSksCiAgICAgIHBhcnR5X3N1cHBvcnRfbWlzc2luZyA9IHN1bShpcy5uYShwYXJ0eV9zdXBwb3J0KSkKICAgICkKCiAgcHJpbnQoY292YXJpYXRlX21pc3Npbmdfc3VtbWFyeSkKICB3cml0ZV9jc3Zfc2FmZWx5KGNvdmFyX2lkLCAicmVzcG9uZGVudF9jb3ZhcmlhdGVzLmNzdiIpCiAgd3JpdGVfY3N2X3NhZmVseShjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5LCAiY292YXJpYXRlX21pc3Npbmdfc3VtbWFyeS5jc3YiKQoKCiAgY29uam9pbnRfYWxsX2NvdiA8LSBjb25qb2ludF9hbGxfbSAlPiUKICAgIGxlZnRfam9pbihjb3Zhcl9pZCwgYnkgPSAiSUQiKQoKICBjb3ZhcmlhdGVfdGVybXMgPC0gYygKICAgICJmZW1hbGVfaW1wIiwKICAgICJmZW1hbGVfbWlzcyIsCiAgICAiYWdlX2ltcCIsCiAgICAiYWdlX21pc3MiLAogICAgImNvbGxlZ2VfZ3JhZF9pbXAiLAogICAgImNvbGxlZ2VfZ3JhZF9taXNzIiwKICAgICJpbmNvbWVfZ3Jvc3NfbG9nX2ltcCIsCiAgICAiaW5jb21lX2dyb3NzX2xvZ19taXNzIiwKICAgICJwYXJ0eV9zdXBwb3J0X2YiCiAgKQoKICBoYXNfdmFyaWF0aW9uIDwtIGZ1bmN0aW9uKGRhdCwgdikgewogICAgaWYgKCF2ICVpbiUgbmFtZXMoZGF0KSkgcmV0dXJuKEZBTFNFKQogICAgZHBseXI6Om5fZGlzdGluY3QoZGF0W1t2XV0sIG5hLnJtID0gVFJVRSkgPiAxCiAgfQoKICBjb3ZhcmlhdGVfdGVybXNfdXNlIDwtIGNvdmFyaWF0ZV90ZXJtc1sKICAgIG1hcF9sZ2woY292YXJpYXRlX3Rlcm1zLCB+IGhhc192YXJpYXRpb24oY29uam9pbnRfYWxsX2NvdiwgLngpKQogIF0KCiAgZm9ybXVsYV9jb3YgPC0gYXMuZm9ybXVsYSgKICAgIHBhc3RlKAogICAgICAic2VsZWN0ZWQgfiIsCiAgICAgIHBhc3RlKGMoYXR0cl90ZXJtcywgY292YXJpYXRlX3Rlcm1zX3VzZSksIGNvbGxhcHNlID0gIiArICIpCiAgICApCiAgKQoKICBydW5fYW1jZV9jb3YgPC0gZnVuY3Rpb24oZGF0KSB7CiAgICBmZW9scygKICAgICAgZm9ybXVsYV9jb3YsCiAgICAgIGRhdGEgPSBkYXQsCiAgICAgIHZjb3YgPSB+IElECiAgICApCiAgfQoKICBtb2RlbHNfYnlfcGFydHlfbl9jb3YgPC0gY29uam9pbnRfYWxsX2NvdiAlPiUKICAgIHNwbGl0KC4kcGFydHlfbikgJT4lCiAgICBtYXAocnVuX2FtY2VfY292KQoKICBjYXB0dXJlLm91dHB1dCgKICAgIGV0YWJsZSgKICAgICAgbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YsCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX2NvdiwKICAgICAgaGVhZGVycyA9IGMoCiAgICAgICAgcmVwKCLlhbHlpInph4/jgarjgZciLCBsZW5ndGgobW9kZWxzX2J5X3BhcnR5X25fbm9jb3YpKSwKICAgICAgICByZXAoIuWFseWkiemHj+OBguOCiiIsIGxlbmd0aChtb2RlbHNfYnlfcGFydHlfbl9jb3YpKQogICAgICApCiAgICApLAogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAiYW1jZV9ub2Nvdl9hbmRfY292X21vZGVscy50eHQiKQogICkKCiAgYW1jZV9wbG90X2NvdiA8LSBtYWtlX2FtY2VfcGxvdF9kZihtb2RlbHNfYnlfcGFydHlfbl9jb3YpCiAgd3JpdGVfY3N2X3NhZmVseShhbWNlX3Bsb3RfY292LCAiYW1jZV9jb3ZfY29lZmZpY2llbnRzLmNzdiIpCgoKICBzdHVkeV9sYWJlbCA8LSAi5a6f6aiTMu+8iDIwMjblubTvvIkiCgogIHRlcm1fbGFiZWxzX2ZhY2V0IDwtIHRlcm1fbGFiZWxzICU+JQogICAgbXV0YXRlKAogICAgICBhdHRyaWJ1dGVfZmFjZXQgPSBhdHRyaWJ1dGUKICAgICkKCiAgYXR0cmlidXRlX29yZGVyX2ZhY2V0IDwtIGMoCiAgICAi5LiO5YWa77yP6YeO5YWaIiwKICAgICLmlL/nrZbkvY3nva4iLAogICAgIuitsOW4reaVsCIsCiAgICAiR0RQ5oiQ6ZW3546HIiwKICAgICLml6XntYzlubPlnYciLAogICAgIkNQSSIsCiAgICAi5aSx5qWt546HIgogICkKCiAgbWFrZV9hbWNlX2ZhY2V0X2RmIDwtIGZ1bmN0aW9uKG1vZGVscykgewogICAgaW1hcF9kZnIoCiAgICAgIG1vZGVscywKICAgICAgfiB0aWR5X2ZpeGVzdCgueCkgJT4lCiAgICAgICAgbXV0YXRlKHBhcnR5X24gPSBhcy5jaGFyYWN0ZXIoLnkpKQogICAgKSAlPiUKICAgICAgbGVmdF9qb2luKHRlcm1fbGFiZWxzX2ZhY2V0LCBieSA9ICJ0ZXJtIikgJT4lCiAgICAgIGZpbHRlcighaXMubmEoYXR0cmlidXRlX2ZhY2V0KSkgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBlc3RpbWF0ZV9wcCA9IGVzdGltYXRlICogMTAwLAogICAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsCiAgICAgICAgY29uZi5oaWdoX3BwID0gY29uZi5oaWdoICogMTAwLAogICAgICAgIHBhcnR5X24gPSBmYWN0b3IoCiAgICAgICAgICBwYXJ0eV9uLAogICAgICAgICAgbGV2ZWxzID0gYygiMiIsICIzIiwgIjQiLCAiNSIpLAogICAgICAgICAgbGFiZWxzID0gYygiMuaUv+WFmiIsICIz5pS/5YWaIiwgIjTmlL/lhZoiLCAiNeaUv+WFmiIpCiAgICAgICAgKSwKICAgICAgICBhdHRyaWJ1dGVfZmFjZXQgPSBmYWN0b3IoCiAgICAgICAgICBhdHRyaWJ1dGVfZmFjZXQsCiAgICAgICAgICBsZXZlbHMgPSBhdHRyaWJ1dGVfb3JkZXJfZmFjZXQKICAgICAgICApLAogICAgICAgIGxhYmVsID0gZmFjdG9yKAogICAgICAgICAgbGFiZWwsCiAgICAgICAgICBsZXZlbHMgPSByZXYobGFiZWxfb3JkZXIpCiAgICAgICAgKQogICAgICApCiAgfQoKICBhbWNlX3Bsb3RfZGZfY292X2ZhY2V0IDwtIG1ha2VfYW1jZV9mYWNldF9kZihtb2RlbHNfYnlfcGFydHlfbl9jb3YpCiAgYW1jZV9wbG90X2RmX25vY292X2ZhY2V0IDwtIG1ha2VfYW1jZV9mYWNldF9kZihtb2RlbHNfYnlfcGFydHlfbl9ub2NvdikKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIGFtY2VfcGxvdF9kZl9jb3ZfZmFjZXQsCiAgICAiYW1jZV9jb3ZfZmFjZXRfY29lZmZpY2llbnRzLmNzdiIKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICBhbWNlX3Bsb3RfZGZfbm9jb3ZfZmFjZXQsCiAgICAiYW1jZV9ub2Nvdl9mYWNldF9jb2VmZmljaWVudHMuY3N2IgogICkKCgogIHBfYW1jZV9jb3ZfZmFjZXQgPC0gZ2dwbG90KAogICAgYW1jZV9wbG90X2RmX2Nvdl9mYWNldCwKICAgIGFlcygKICAgICAgeCA9IGVzdGltYXRlX3BwLAogICAgICB5ID0gbGFiZWwsCiAgICAgIHNoYXBlID0gcGFydHlfbiwKICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uLAogICAgICBncm91cCA9IHBhcnR5X24KICAgICkKICApICsKICAgIGdlb21fdmxpbmUoCiAgICAgIHhpbnRlcmNlcHQgPSAwLAogICAgICBsaW5ld2lkdGggPSAwLjQ1LAogICAgICBjb2xvciA9ICJncmV5MzUiCiAgICApICsKICAgIGdlb21fZXJyb3JiYXJoKAogICAgICBhZXMoCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLAogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHAKICAgICAgKSwKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLAogICAgICBoZWlnaHQgPSAwLjE2LAogICAgICBsaW5ld2lkdGggPSAwLjU1LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9wb2ludCgKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLAogICAgICBzaXplID0gMi41LAogICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgIGZpbGwgPSAid2hpdGUiLAogICAgICBzdHJva2UgPSAwLjgKICAgICkgKwogICAgZmFjZXRfZ3JpZCgKICAgICAgYXR0cmlidXRlX2ZhY2V0IH4gLiwKICAgICAgc2NhbGVzID0gImZyZWVfeSIsCiAgICAgIHNwYWNlID0gImZyZWVfeSIsCiAgICAgIHN3aXRjaCA9ICJ5IgogICAgKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAiIHBwIiksCiAgICAgIGJyZWFrcyA9IHNlcSgtMTIsIDEyLCBieSA9IDIpCiAgICApICsKICAgIHNjYWxlX3NoYXBlX21hbnVhbCgKICAgICAgbmFtZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIy5pS/5YWaIiA9IDE2LAogICAgICAgICIz5pS/5YWaIiA9IDE3LAogICAgICAgICI05pS/5YWaIiA9IDE1LAogICAgICAgICI15pS/5YWaIiA9IDEKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIG5hbWUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIiwKICAgICAgdmFsdWVzID0gYygKICAgICAgICAiMuaUv+WFmiIgPSAic29saWQiLAogICAgICAgICIz5pS/5YWaIiA9ICJkYXNoZWQiLAogICAgICAgICI05pS/5YWaIiA9ICJkb3R0ZWQiLAogICAgICAgICI15pS/5YWaIiA9ICJkb3RkYXNoIgogICAgICApCiAgICApICsKICAgIGxhYnMoCiAgICAgIHggPSAi6YG45oqe56K6546H44Gu5aSJ5YyWIiwKICAgICAgeSA9IE5VTEwKICAgICkgKwogICAgdGhlbWVfYncoCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLAogICAgICBiYXNlX2ZhbWlseSA9ICJZdSBHb3RoaWMiCiAgICApICsKICAgIHRoZW1lKAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDE2CiAgICAgICksCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLAogICAgICAgIGNvbG9yID0gImdyZXk1NSIKICAgICAgKSwKICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoCiAgICAgICAgYW5nbGUgPSAwLAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDEwCiAgICAgICksCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpCiAgICApCgogIHByaW50KHBfYW1jZV9jb3ZfZmFjZXQpCgogIHNhdmVfcGxvdCgKICAgICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciLAogICAgcF9hbWNlX2Nvdl9mYWNldCwKICAgIHdpZHRoID0gMTAuNSwKICAgIGhlaWdodCA9IDguNQogICkKCiAgcF9hbWNlX2Nvdl9tYWluIDwtIHBfYW1jZV9jb3ZfZmFjZXQKCgogIG1ha2VfaGVhdG1hcF9kZiA8LSBmdW5jdGlvbihhbWNlX3Bsb3RfZGYpIHsKICAgIGhlYXRfZGYgPC0gYW1jZV9wbG90X2RmICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgYWJzX2FtY2UgPSBhYnMoZXN0aW1hdGVfcHApLAogICAgICAgIGN1ZV90eXBlX2NvZGUgPSBjYXNlX3doZW4oCiAgICAgICAgICBjdWVfdHlwZSA9PSAi5pS/5YWa44Gu5omL44GM44GL44KKIiB+ICJwYXJ0eSIsCiAgICAgICAgICBjdWVfdHlwZSA9PSAi57WM5riI44Gu5omL44GM44GL44KKIiB+ICJlY29ub215IiwKICAgICAgICAgIFRSVUUgfiAib3RoZXIiCiAgICAgICAgKQogICAgICApICU+JQogICAgICBncm91cF9ieShwYXJ0eV9uKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIHJhbmtfd2l0aGluX3BhcnR5ID0gbWluX3JhbmsoZGVzYyhhYnNfYW1jZSkpLAogICAgICAgIG5faW5fY29sID0gbigpLAogICAgICAgIHJhbmtfc2NvcmUgPSBpZl9lbHNlKAogICAgICAgICAgbl9pbl9jb2wgPT0gMSwKICAgICAgICAgIDEsCiAgICAgICAgICAxIC0gKHJhbmtfd2l0aGluX3BhcnR5IC0gMSkgLyAobl9pbl9jb2wgLSAxKQogICAgICAgICkKICAgICAgKSAlPiUKICAgICAgdW5ncm91cCgpCgogICAgcm93X29yZGVyX2RmIDwtIGhlYXRfZGYgJT4lCiAgICAgIGdyb3VwX2J5KGxhYmVsLCBjdWVfdHlwZV9jb2RlKSAlPiUKICAgICAgc3VtbWFyaXNlKAogICAgICAgIG1lYW5fYWJzX2FtY2UgPSBtZWFuKGFic19hbWNlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKSAlPiUKICAgICAgYXJyYW5nZShkZXNjKG1lYW5fYWJzX2FtY2UpKQoKICAgIHJvd19sZXZlbHMgPC0gYXMuY2hhcmFjdGVyKHJvd19vcmRlcl9kZiRsYWJlbCkKCiAgICBoZWF0X2RmIDwtIGhlYXRfZGYgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBsYWJlbCA9IGZhY3RvcigKICAgICAgICAgIGFzLmNoYXJhY3RlcihsYWJlbCksCiAgICAgICAgICBsZXZlbHMgPSByZXYocm93X2xldmVscykKICAgICAgICApCiAgICAgICkKCiAgICBsYWJlbF9jb2xvcl9tYXAgPC0gcm93X29yZGVyX2RmICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgbGFiZWxfbWFya2Rvd24gPSBjYXNlX3doZW4oCiAgICAgICAgICBjdWVfdHlwZV9jb2RlID09ICJwYXJ0eSIgfgogICAgICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAgICAgIjxzcGFuIHN0eWxlPSdjb2xvcjojMTExMTExOyc+IiwKICAgICAgICAgICAgICBsYWJlbCwKICAgICAgICAgICAgICAiPC9zcGFuPiIKICAgICAgICAgICAgKSwKICAgICAgICAgIGN1ZV90eXBlX2NvZGUgPT0gImVjb25vbXkiIH4KICAgICAgICAgICAgcGFzdGUwKAogICAgICAgICAgICAgICI8c3BhbiBzdHlsZT0nY29sb3I6IzhBOEE4QTsnPiIsCiAgICAgICAgICAgICAgbGFiZWwsCiAgICAgICAgICAgICAgIjwvc3Bhbj4iCiAgICAgICAgICAgICksCiAgICAgICAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKGxhYmVsKQogICAgICAgICkKICAgICAgKQoKICAgIGxhYmVsX21hcmtkb3duX3ZlYyA8LSBzZXROYW1lcygKICAgICAgbGFiZWxfY29sb3JfbWFwJGxhYmVsX21hcmtkb3duLAogICAgICBhcy5jaGFyYWN0ZXIobGFiZWxfY29sb3JfbWFwJGxhYmVsKQogICAgKQoKICAgIGxpc3QoCiAgICAgIGhlYXRfZGYgPSBoZWF0X2RmLAogICAgICBsYWJlbF9tYXJrZG93bl92ZWMgPSBsYWJlbF9tYXJrZG93bl92ZWMKICAgICkKICB9CgogIHBsb3RfYW1jZV9oZWF0bWFwIDwtIGZ1bmN0aW9uKAogICAgICBoZWF0X2RmLAogICAgICBsYWJlbF9tYXJrZG93bl92ZWMsCiAgICAgIHdpdGhfcmFuayA9IFRSVUUsCiAgICAgIHRpdGxlX3RleHQgPSBOVUxMKSB7CgogICAgaWYgKHdpdGhfcmFuaykgewogICAgICBoZWF0X2RmIDwtIGhlYXRfZGYgJT4lCiAgICAgICAgbXV0YXRlKAogICAgICAgICAgY2VsbF9sYWJlbCA9IHBhc3RlMCgKICAgICAgICAgICAgc3ByaW50ZigiJS4xZiIsIGVzdGltYXRlX3BwKSwKICAgICAgICAgICAgIlxuKCIsCiAgICAgICAgICAgIHJhbmtfd2l0aGluX3BhcnR5LAogICAgICAgICAgICAi5L2NKSIKICAgICAgICAgICkKICAgICAgICApCgogICAgICB0ZXh0X3NpemUgPC0gMy4wCiAgICAgIGxpbmVoZWlnaHQgPC0gMC45CiAgICB9IGVsc2UgewogICAgICBoZWF0X2RmIDwtIGhlYXRfZGYgJT4lCiAgICAgICAgbXV0YXRlKAogICAgICAgICAgY2VsbF9sYWJlbCA9IHNwcmludGYoIiUuMWYiLCBlc3RpbWF0ZV9wcCkKICAgICAgICApCgogICAgICB0ZXh0X3NpemUgPC0gMy40CiAgICAgIGxpbmVoZWlnaHQgPC0gMS4wCiAgICB9CgogICAgZ2dwbG90KAogICAgICBoZWF0X2RmLAogICAgICBhZXMoCiAgICAgICAgeCA9IHBhcnR5X24sCiAgICAgICAgeSA9IGxhYmVsLAogICAgICAgIGZpbGwgPSByYW5rX3Njb3JlCiAgICAgICkKICAgICkgKwogICAgICBnZW9tX3RpbGUoCiAgICAgICAgY29sb3IgPSAid2hpdGUiLAogICAgICAgIGxpbmV3aWR0aCA9IDAuNwogICAgICApICsKICAgICAgZ2VvbV90ZXh0KAogICAgICAgIGFlcyhsYWJlbCA9IGNlbGxfbGFiZWwpLAogICAgICAgIHNpemUgPSB0ZXh0X3NpemUsCiAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsCiAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgIGxpbmVoZWlnaHQgPSBsaW5laGVpZ2h0CiAgICAgICkgKwogICAgICBzY2FsZV95X2Rpc2NyZXRlKAogICAgICAgIGxhYmVscyA9IGxhYmVsX21hcmtkb3duX3ZlYwogICAgICApICsKICAgICAgc2NhbGVfZmlsbF9ncmFkaWVudCgKICAgICAgICBsb3cgPSAiZ3JleTk1IiwKICAgICAgICBoaWdoID0gImdyZXkxNSIsCiAgICAgICAgbGltaXRzID0gYygwLCAxKSwKICAgICAgICBicmVha3MgPSBjKDAsIDAuMjUsIDAuNTAsIDAuNzUsIDEuMDApLAogICAgICAgIGxhYmVscyA9IGMoIuS9jiIsICIiLCAiIiwgIiIsICLpq5giKSwKICAgICAgICBuYW1lID0gIuWIl+WGhemghuS9jVxu77yI5r+D44GE44G744Gp6auY5L2N77yJIgogICAgICApICsKICAgICAgbGFicygKICAgICAgICB0aXRsZSA9IHRpdGxlX3RleHQsCiAgICAgICAgeCA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLAogICAgICAgIHkgPSBOVUxMCiAgICAgICkgKwogICAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikgKwogICAgICB0aGVtZSgKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGV4dC55ID0gZ2d0ZXh0OjplbGVtZW50X21hcmtkb3duKHNpemUgPSA5KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgKQogIH0KCiAgaGVhdG1hcF9pbnB1dCA8LSBtYWtlX2hlYXRtYXBfZGYoYW1jZV9wbG90X2NvdikKCiAgcF9oZWF0X2FtY2VfbWl4ZWQgPC0gcGxvdF9hbWNlX2hlYXRtYXAoCiAgICBoZWF0bWFwX2lucHV0JGhlYXRfZGYsCiAgICBoZWF0bWFwX2lucHV0JGxhYmVsX21hcmtkb3duX3ZlYywKICAgIHdpdGhfcmFuayA9IEZBTFNFLAogICAgdGl0bGVfdGV4dCA9IE5VTEwKICApCgogIHByaW50KHBfaGVhdF9hbWNlX21peGVkKQoKICBzYXZlX3Bsb3QoCiAgICAiYW1jZV9oZWF0bWFwX21peGVkX3JhbmtfY29sb3JlZF9sYWJlbHMucG5nIiwKICAgIHBfaGVhdF9hbWNlX21peGVkLAogICAgd2lkdGggPSA4LjgsCiAgICBoZWlnaHQgPSA4LjgKICApCgogIHBfaGVhdF9hbWNlX21peGVkX3JhbmtsYWJlbCA8LSBwbG90X2FtY2VfaGVhdG1hcCgKICAgIGhlYXRtYXBfaW5wdXQkaGVhdF9kZiwKICAgIGhlYXRtYXBfaW5wdXQkbGFiZWxfbWFya2Rvd25fdmVjLAogICAgd2l0aF9yYW5rID0gVFJVRSwKICAgIHRpdGxlX3RleHQgPSBOVUxMCiAgKQoKICBwcmludChwX2hlYXRfYW1jZV9taXhlZF9yYW5rbGFiZWwpCgogIHNhdmVfcGxvdCgKICAgICJhbWNlX2hlYXRtYXBfbWl4ZWRfcmFua19jb2xvcmVkX2xhYmVsc193aXRocmFuay5wbmciLAogICAgcF9oZWF0X2FtY2VfbWl4ZWRfcmFua2xhYmVsLAogICAgd2lkdGggPSA4LjgsCiAgICBoZWlnaHQgPSA4LjgKICApCgogIHBfaGVhdF9hbWNlIDwtIHBfaGVhdF9hbWNlX21peGVkCiAgcF9oZWF0X2FtY2VfcmFuayA8LSBwX2hlYXRfYW1jZV9taXhlZF9yYW5rbGFiZWwKCgogIHBfYW1jZV9mYWNldF9ub2NvdiA8LSBnZ3Bsb3QoCiAgICBhbWNlX3Bsb3RfZGZfbm9jb3ZfZmFjZXQsCiAgICBhZXMoCiAgICAgIHggPSBlc3RpbWF0ZV9wcCwKICAgICAgeSA9IGxhYmVsLAogICAgICBzaGFwZSA9IHBhcnR5X24sCiAgICAgIGxpbmV0eXBlID0gcGFydHlfbiwKICAgICAgZ3JvdXAgPSBwYXJ0eV9uCiAgICApCiAgKSArCiAgICBnZW9tX3ZsaW5lKAogICAgICB4aW50ZXJjZXB0ID0gMCwKICAgICAgbGluZXdpZHRoID0gMC40NSwKICAgICAgY29sb3IgPSAiZ3JleTM1IgogICAgKSArCiAgICBnZW9tX2Vycm9yYmFyaCgKICAgICAgYWVzKAogICAgICAgIHhtaW4gPSBjb25mLmxvd19wcCwKICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwCiAgICAgICksCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwKICAgICAgaGVpZ2h0ID0gMC4xNiwKICAgICAgbGluZXdpZHRoID0gMC41NSwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fcG9pbnQoCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwKICAgICAgc2l6ZSA9IDIuNSwKICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgc3Ryb2tlID0gMC44CiAgICApICsKICAgIGZhY2V0X2dyaWQoCiAgICAgIGF0dHJpYnV0ZV9mYWNldCB+IC4sCiAgICAgIHNjYWxlcyA9ICJmcmVlX3kiLAogICAgICBzcGFjZSA9ICJmcmVlX3kiLAogICAgICBzd2l0Y2ggPSAieSIKICAgICkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKAogICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIiBwcCIpLAogICAgICBicmVha3MgPSBzZXEoLTEyLCAxMiwgYnkgPSAyKQogICAgKSArCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoCiAgICAgIG5hbWUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIiwKICAgICAgdmFsdWVzID0gYygKICAgICAgICAiMuaUv+WFmiIgPSAxNiwKICAgICAgICAiM+aUv+WFmiIgPSAxNywKICAgICAgICAiNOaUv+WFmiIgPSAxNSwKICAgICAgICAiNeaUv+WFmiIgPSAxCiAgICAgICkKICAgICkgKwogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKAogICAgICBuYW1lID0gIuaUv+WFmuaVsOmBuOaKnuiCoiIsCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjLmlL/lhZoiID0gInNvbGlkIiwKICAgICAgICAiM+aUv+WFmiIgPSAiZGFzaGVkIiwKICAgICAgICAiNOaUv+WFmiIgPSAiZG90dGVkIiwKICAgICAgICAiNeaUv+WFmiIgPSAiZG90ZGFzaCIKICAgICAgKQogICAgKSArCiAgICBsYWJzKAogICAgICB4ID0gIumBuOaKnueiuueOh+OBruWkieWMliIsCiAgICAgIHkgPSBOVUxMCiAgICApICsKICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIHNpemUgPSAxNgogICAgICApLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksCiAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiLAogICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KAogICAgICAgIGZpbGwgPSAiZ3JleTkyIiwKICAgICAgICBjb2xvciA9ICJncmV5NTUiCiAgICAgICksCiAgICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KAogICAgICAgIGFuZ2xlID0gMCwKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIHNpemUgPSAxMAogICAgICApLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKQogICAgKQoKICBwcmludChwX2FtY2VfZmFjZXRfbm9jb3YpCgogIHNhdmVfcGxvdCgKICAgICJhbWNlX2ZhY2V0X25vY292LnBuZyIsCiAgICBwX2FtY2VfZmFjZXRfbm9jb3YsCiAgICB3aWR0aCA9IDEwLjUsCiAgICBoZWlnaHQgPSA5CiAgKQoKICBwX2FtY2Vfbm9jb3ZfYXBwZW5kaXggPC0gcF9hbWNlX2ZhY2V0X25vY292CgoKICBwX2ludGVyYWN0aW9uIDwtIGdncGxvdCgKICAgIGludGVyYWN0aW9uX3Bsb3RfZGYsCiAgICBhZXMoCiAgICAgIHggPSBlc3RpbWF0ZV9wcCwKICAgICAgeSA9IGxhYmVsLAogICAgICBzaGFwZSA9IHBhcnR5X25fbGFiZWwsCiAgICAgIGxpbmV0eXBlID0gcGFydHlfbl9sYWJlbCwKICAgICAgZ3JvdXAgPSBwYXJ0eV9uX2xhYmVsCiAgICApCiAgKSArCiAgICBnZW9tX3ZsaW5lKAogICAgICB4aW50ZXJjZXB0ID0gMCwKICAgICAgbGluZXdpZHRoID0gMC40NSwKICAgICAgY29sb3IgPSAiZ3JleTM1IgogICAgKSArCiAgICBnZW9tX2Vycm9yYmFyaCgKICAgICAgYWVzKAogICAgICAgIHhtaW4gPSBjb25mLmxvd19wcCwKICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwCiAgICAgICksCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwKICAgICAgaGVpZ2h0ID0gMC4xNiwKICAgICAgbGluZXdpZHRoID0gMC41NSwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fcG9pbnQoCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwKICAgICAgc2l6ZSA9IDIuNSwKICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgc3Ryb2tlID0gMC44CiAgICApICsKICAgIGZhY2V0X2dyaWQoCiAgICAgIGF0dHJpYnV0ZSB+IC4sCiAgICAgIHNjYWxlcyA9ICJmcmVlX3kiLAogICAgICBzcGFjZSA9ICJmcmVlX3kiLAogICAgICBzd2l0Y2ggPSAieSIKICAgICkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKAogICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIiBwcCIpLAogICAgICBicmVha3MgPSBzZXEoLTgsIDgsIGJ5ID0gMikKICAgICkgKwogICAgc2NhbGVfc2hhcGVfbWFudWFsKAogICAgICBuYW1lID0gIjLmlL/lhZrjga7loLTlkIjjgajjga7mr5TovIMiLAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIz5pS/5YWaIiA9IDE3LAogICAgICAgICI05pS/5YWaIiA9IDE1LAogICAgICAgICI15pS/5YWaIiA9IDEKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIG5hbWUgPSAiMuaUv+WFmuOBruWgtOWQiOOBqOOBruavlOi8gyIsCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjPmlL/lhZoiID0gImRhc2hlZCIsCiAgICAgICAgIjTmlL/lhZoiID0gImRvdHRlZCIsCiAgICAgICAgIjXmlL/lhZoiID0gImRvdGRhc2giCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgeCA9ICIy5pS/5YWa5p2h5Lu244Go44Gu5beuIiwKICAgICAgeSA9IE5VTEwKICAgICkgKwogICAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpICsKICAgIHRoZW1lKAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDE1CiAgICAgICksCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLAogICAgICAgIGNvbG9yID0gImdyZXk1NSIKICAgICAgKSwKICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoCiAgICAgICAgYW5nbGUgPSAwLAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDEwCiAgICAgICksCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpCiAgICApCgogIHByaW50KHBfaW50ZXJhY3Rpb24pCgogIHNhdmVfcGxvdCgKICAgICJhbWNlX2ludGVyYWN0aW9uX2RpZmZlcmVuY2VfZnJvbV8ycGFydHkucG5nIiwKICAgIHBfaW50ZXJhY3Rpb24sCiAgICB3aWR0aCA9IDEwLjUsCiAgICBoZWlnaHQgPSA5CiAgKQoKCiAgY29uam9pbnRfY2xvZ2l0IDwtIGNvbmpvaW50X2FsbF9tICU+JQogICAgbXV0YXRlKAogICAgICBzZWxlY3RlZCA9IGFzLmludGVnZXIoc2VsZWN0ZWQpLAogICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksCiAgICAgIHRhc2tfaWQgPSBmYWN0b3IodGFza19pZCksCiAgICAgIHBvbGljeV9wb3NpdGlvbiA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICBwb2xpY3lfcG9zaXRpb24sCiAgICAgICAgIuS4remBkyIKICAgICAgKSwKICAgICAgZ292ZXJubWVudF9zdGF0dXMgPSByZWxldmVsX2lmX3ByZXNlbnQoCiAgICAgICAgZ292ZXJubWVudF9zdGF0dXMsCiAgICAgICAgIumHjuWFmiIKICAgICAgKSwKICAgICAgZ2RwX2dyb3d0aCA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICBnZHBfZ3Jvd3RoLAogICAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiCiAgICAgICksCiAgICAgIG5pa2tlaSA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICBuaWtrZWksCiAgICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOWkieOCj+OCieOBmiIKICAgICAgKSwKICAgICAgc2VhdHMgPSByZWxldmVsX2lmX3ByZXNlbnQoCiAgICAgICAgc2VhdHMsCiAgICAgICAgIjEw5Lul5LiLIgogICAgICApLAogICAgICBjcGkgPSByZWxldmVsX2lmX3ByZXNlbnQoCiAgICAgICAgY3BpLAogICAgICAgICJDUEnliY3mnJ/mr5TCsTDjg53jgqTjg7Pjg4giCiAgICAgICksCiAgICAgIHVuZW1wbG95bWVudCA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICB1bmVtcGxveW1lbnQsCiAgICAgICAgIuWksealreeOh+WJjeacn+avlMKxMO+8hSIKICAgICAgKQogICAgKQoKICBmb3JtdWxhX2Nsb2dpdF9ub2NvdiA8LSBhcy5mb3JtdWxhKAogICAgcGFzdGUwKAogICAgICAic2VsZWN0ZWQgfiAiLAogICAgICBwYXN0ZShhdHRyX3Rlcm1zLCBjb2xsYXBzZSA9ICIgKyAiKSwKICAgICAgIiArIHN0cmF0YSh0YXNrX2lkKSArIGNsdXN0ZXIoSUQpIgogICAgKQogICkKCiAgcnVuX2Nsb2dpdF9ub2NvdiA8LSBmdW5jdGlvbihkYXQpIHsKICAgIHN1cnZpdmFsOjpjbG9naXQoCiAgICAgIGZvcm11bGFfY2xvZ2l0X25vY292LAogICAgICBkYXRhID0gZGF0LAogICAgICBtZXRob2QgPSAiZWZyb24iCiAgICApCiAgfQoKICBtb2RlbHNfY2xvZ2l0X25vY292IDwtIGNvbmpvaW50X2Nsb2dpdCAlPiUKICAgIHNwbGl0KC4kcGFydHlfbikgJT4lCiAgICBtYXAocnVuX2Nsb2dpdF9ub2NvdikKCiAgY2FwdHVyZS5vdXRwdXQoCiAgICBsYXBwbHkobW9kZWxzX2Nsb2dpdF9ub2Nvdiwgc3VtbWFyeSksCiAgICBmaWxlID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAiY29uZGl0aW9uYWxfbG9naXRfbW9kZWxzLnR4dCIKICAgICkKICApCgogIHRpZHlfY2xvZ2l0IDwtIGZ1bmN0aW9uKG1vZGVsKSB7CiAgICBzIDwtIHN1bW1hcnkobW9kZWwpCiAgICBjdCA8LSBhcy5kYXRhLmZyYW1lKHMkY29lZmZpY2llbnRzKQogICAgY3QkdGVybSA8LSByb3duYW1lcyhjdCkKCiAgICBzZV9jb2wgPC0gaWYgKCJyb2J1c3Qgc2UiICVpbiUgbmFtZXMoY3QpKSB7CiAgICAgICJyb2J1c3Qgc2UiCiAgICB9IGVsc2UgaWYgKCJzZShjb2VmKSIgJWluJSBuYW1lcyhjdCkpIHsKICAgICAgInNlKGNvZWYpIgogICAgfSBlbHNlIHsKICAgICAgc3RvcCgiQ2hlY2sgY2xvZ2l0IikKICAgIH0KCiAgICBwX2NvbCA8LSBpZiAoIlByKD58enwpIiAlaW4lIG5hbWVzKGN0KSkgewogICAgICAiUHIoPnx6fCkiCiAgICB9IGVsc2UgaWYgKCJQcig+fHR8KSIgJWluJSBuYW1lcyhjdCkpIHsKICAgICAgIlByKD58dHwpIgogICAgfSBlbHNlIHsKICAgICAgTkFfY2hhcmFjdGVyXwogICAgfQoKICAgIGN0ICU+JQogICAgICBhc190aWJibGUoKSAlPiUKICAgICAgdHJhbnNtdXRlKAogICAgICAgIHRlcm0gPSB0ZXJtLAogICAgICAgIGVzdGltYXRlID0gY29lZiwKICAgICAgICBzdGQuZXJyb3IgPSAuZGF0YVtbc2VfY29sXV0sCiAgICAgICAgcC52YWx1ZSA9IGlmICghaXMubmEocF9jb2wpKSB7CiAgICAgICAgICAuZGF0YVtbcF9jb2xdXQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBOQV9yZWFsXwogICAgICAgIH0sCiAgICAgICAgY29uZi5sb3cgPSBlc3RpbWF0ZSAtIDEuOTYgKiBzdGQuZXJyb3IsCiAgICAgICAgY29uZi5oaWdoID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yLAogICAgICAgIG9kZHNfcmF0aW8gPSBleHAoZXN0aW1hdGUpLAogICAgICAgIG9kZHNfcmF0aW9fbG93ID0gZXhwKGNvbmYubG93KSwKICAgICAgICBvZGRzX3JhdGlvX2hpZ2ggPSBleHAoY29uZi5oaWdoKQogICAgICApCiAgfQoKICBjbG9naXRfcGxvdF9kZiA8LSBpbWFwX2RmcigKICAgIG1vZGVsc19jbG9naXRfbm9jb3YsCiAgICB+IHRpZHlfY2xvZ2l0KC54KSAlPiUKICAgICAgbXV0YXRlKHBhcnR5X24gPSBhcy5jaGFyYWN0ZXIoLnkpKQogICkgJT4lCiAgICBsZWZ0X2pvaW4odGVybV9sYWJlbHMsIGJ5ID0gInRlcm0iKSAlPiUKICAgIGZpbHRlcighaXMubmEoYXR0cmlidXRlKSkgJT4lCiAgICBtdXRhdGUoCiAgICAgIHBhcnR5X24gPSBmYWN0b3IoCiAgICAgICAgcGFydHlfbiwKICAgICAgICBsZXZlbHMgPSBjKCIyIiwgIjMiLCAiNCIsICI1IiksCiAgICAgICAgbGFiZWxzID0gYygiMuaUv+WFmiIsICIz5pS/5YWaIiwgIjTmlL/lhZoiLCAiNeaUv+WFmiIpCiAgICAgICksCiAgICAgIGxhYmVsID0gZmFjdG9yKAogICAgICAgIGxhYmVsLAogICAgICAgIGxldmVscyA9IHJldihsYWJlbF9vcmRlcikKICAgICAgKQogICAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgY2xvZ2l0X3Bsb3RfZGYsCiAgICAiY29uZGl0aW9uYWxfbG9naXRfY29lZmZpY2llbnRzLmNzdiIKICApCgoKICBwX2Nsb2dpdF9vciA8LSBnZ3Bsb3QoCiAgICBjbG9naXRfcGxvdF9kZiwKICAgIGFlcygKICAgICAgeCA9IG9kZHNfcmF0aW8sCiAgICAgIHkgPSBsYWJlbCwKICAgICAgc2hhcGUgPSBwYXJ0eV9uLAogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sCiAgICAgIGdyb3VwID0gcGFydHlfbgogICAgKQogICkgKwogICAgZ2VvbV92bGluZSgKICAgICAgeGludGVyY2VwdCA9IDEsCiAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsCiAgICAgIGNvbG9yID0gImdyZXkzNSIKICAgICkgKwogICAgZ2VvbV9lcnJvcmJhcmgoCiAgICAgIGFlcygKICAgICAgICB4bWluID0gb2Rkc19yYXRpb19sb3csCiAgICAgICAgeG1heCA9IG9kZHNfcmF0aW9faGlnaAogICAgICApLAogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43MiksCiAgICAgIGhlaWdodCA9IDAuMTUsCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBnZW9tX3BvaW50KAogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43MiksCiAgICAgIHNpemUgPSAyLjQsCiAgICAgIHN0cm9rZSA9IDAuNywKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIHNjYWxlX3hfbG9nMTAoCiAgICAgIGJyZWFrcyA9IGMoCiAgICAgICAgMC42LAogICAgICAgIDAuOCwKICAgICAgICAxLjAsCiAgICAgICAgMS4yNSwKICAgICAgICAxLjUsCiAgICAgICAgMi4wCiAgICAgICksCiAgICAgIGxhYmVscyA9IGMoCiAgICAgICAgIjAuNiIsCiAgICAgICAgIjAuOCIsCiAgICAgICAgIjEuMCIsCiAgICAgICAgIjEuMjUiLAogICAgICAgICIxLjUiLAogICAgICAgICIyLjAiCiAgICAgICkKICAgICkgKwogICAgc2NhbGVfc2hhcGVfbWFudWFsKAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIy5pS/5YWaIiA9IDE2LAogICAgICAgICIz5pS/5YWaIiA9IDE3LAogICAgICAgICI05pS/5YWaIiA9IDE1LAogICAgICAgICI15pS/5YWaIiA9IDEKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjLmlL/lhZoiID0gInNvbGlkIiwKICAgICAgICAiM+aUv+WFmiIgPSAiZGFzaGVkIiwKICAgICAgICAiNOaUv+WFmiIgPSAiZG90ZGFzaCIsCiAgICAgICAgIjXmlL/lhZoiID0gInR3b2Rhc2giCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgeCA9ICLjgqrjg4Pjgrrmr5QiLAogICAgICB5ID0gTlVMTCwKICAgICAgc2hhcGUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIiwKICAgICAgbGluZXR5cGUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIgogICAgKSArCiAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikgKwogICAgdGhlbWUoCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KQogICAgKQoKICBwcmludChwX2Nsb2dpdF9vcikKCiAgc2F2ZV9wbG90KAogICAgImNsb2dpdF9vZGRzcmF0aW9fbm9jb3YucG5nIiwKICAgIHBfY2xvZ2l0X29yLAogICAgd2lkdGggPSAxMC41LAogICAgaGVpZ2h0ID0gOC41CiAgKQoKCiAgcmVsYXRpdmVfY3VlX21hcCA8LSBjKAogICAgcG9saWN5X3Bvc2l0aW9uID0gInBhcnR5IiwKICAgIGdvdmVybm1lbnRfc3RhdHVzID0gInBhcnR5IiwKICAgIHNlYXRzID0gInBhcnR5IiwKICAgIGdkcF9ncm93dGggPSAiZWNvbm9taWMiLAogICAgbmlra2VpID0gImVjb25vbWljIiwKICAgIGNwaSA9ICJlY29ub21pYyIsCiAgICB1bmVtcGxveW1lbnQgPSAiZWNvbm9taWMiCiAgKQoKICBtZWFuX2Fic29sdXRlX3BhaXJ3aXNlX2RpZmZlcmVuY2UgPC0gZnVuY3Rpb24oeCkgewogICAgeCA8LSB4W2lzLmZpbml0ZSh4KV0KCiAgICBpZiAobGVuZ3RoKHgpIDwgMikgewogICAgICByZXR1cm4oTkFfcmVhbF8pCiAgICB9CgogICAgcGFpcndpc2VfZGlmZmVyZW5jZXMgPC0gY29tYm4oCiAgICAgIHgsCiAgICAgIDIsCiAgICAgIEZVTiA9IGZ1bmN0aW9uKHopIGFicyh6WzFdIC0gelsyXSkKICAgICkKCiAgICBtZWFuKHBhaXJ3aXNlX2RpZmZlcmVuY2VzKQogIH0KCiAgbGluZWFyX3Nsb3BlIDwtIGZ1bmN0aW9uKHksIHgpIHsKICAgIGtlZXAgPC0gaXMuZmluaXRlKHkpICYgaXMuZmluaXRlKHgpCiAgICB5IDwtIHlba2VlcF0KICAgIHggPC0geFtrZWVwXQoKICAgIGlmIChsZW5ndGgoeSkgPCAyIHx8IGxlbmd0aCh1bmlxdWUoeCkpIDwgMikgewogICAgICByZXR1cm4oTkFfcmVhbF8pCiAgICB9CgogICAgdW5uYW1lKGNvZWYobG0oeSB+IHgpKVsyXSkKICB9CgogIGJvb3RzdHJhcF90d29fc2lkZWRfcCA8LSBmdW5jdGlvbih4KSB7CiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXQogICAgQl92YWxpZCA8LSBsZW5ndGgoeCkKCiAgICBpZiAoQl92YWxpZCA9PSAwKSB7CiAgICAgIHJldHVybihOQV9yZWFsXykKICAgIH0KCiAgICBwX2xvd2VyIDwtICgxICsgc3VtKHggPD0gMCkpIC8gKEJfdmFsaWQgKyAxKQogICAgcF91cHBlciA8LSAoMSArIHN1bSh4ID49IDApKSAvIChCX3ZhbGlkICsgMSkKCiAgICBtaW4oMSwgMiAqIG1pbihwX2xvd2VyLCBwX3VwcGVyKSkKICB9CgogIHNhZmVfcXVhbnRpbGUgPC0gZnVuY3Rpb24oeCwgcHJvYmFiaWxpdHkpIHsKICAgIHggPC0geFtpcy5maW5pdGUoeCldCgogICAgaWYgKGxlbmd0aCh4KSA9PSAwKSB7CiAgICAgIHJldHVybihOQV9yZWFsXykKICAgIH0KCiAgICB1bm5hbWUoCiAgICAgIHF1YW50aWxlKAogICAgICAgIHgsCiAgICAgICAgcHJvYnMgPSBwcm9iYWJpbGl0eSwKICAgICAgICB0eXBlID0gNiwKICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgKQogICAgKQogIH0KCiAgcHJlcGFyZV9yZWxhdGl2ZV9jdWVfYW5hbHlzaXMgPC0gZnVuY3Rpb24oZGF0YSwgY3VlX21hcCkgewogICAgYXR0cmlidXRlcyA8LSBuYW1lcyhjdWVfbWFwKQoKICAgIHJlcXVpcmVkX2NvbHVtbnMgPC0gYygKICAgICAgIklEIiwKICAgICAgInBhcnR5X24iLAogICAgICAic2VsZWN0ZWQiLAogICAgICBhdHRyaWJ1dGVzCiAgICApCgogICAgbWlzc2luZ19jb2x1bW5zIDwtIHNldGRpZmYoCiAgICAgIHJlcXVpcmVkX2NvbHVtbnMsCiAgICAgIG5hbWVzKGRhdGEpCiAgICApCgogICAgaWYgKGxlbmd0aChtaXNzaW5nX2NvbHVtbnMpID4gMCkgewogICAgICBzdG9wKCJDaGVjayByZWxhdGl2ZSB3ZWlnaHQiKQogICAgfQoKICAgIGlmICghYWxsKHVubmFtZShjdWVfbWFwKSAlaW4lIGMoInBhcnR5IiwgImVjb25vbWljIikpKSB7CiAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpCiAgICB9CgogICAgYW5hbHlzaXNfZGF0YSA8LSBkYXRhICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgSUQsCiAgICAgICAgcGFydHlfbiwKICAgICAgICBzZWxlY3RlZCwKICAgICAgICBhbGxfb2YoYXR0cmlidXRlcykKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwKICAgICAgICBwYXJ0eV9uID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocGFydHlfbikpLAogICAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihzZWxlY3RlZCksCiAgICAgICAgYWNyb3NzKAogICAgICAgICAgYWxsX29mKGF0dHJpYnV0ZXMpLAogICAgICAgICAgYXMuY2hhcmFjdGVyCiAgICAgICAgKQogICAgICApICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgIWlzLm5hKElEKSwKICAgICAgICBwYXJ0eV9uICVpbiUgMjo1LAogICAgICAgIHNlbGVjdGVkICVpbiUgYygwTCwgMUwpCiAgICAgICkKCiAgICBvYnNlcnZlZF9jb25kaXRpb25zIDwtIHNvcnQoCiAgICAgIHVuaXF1ZShhbmFseXNpc19kYXRhJHBhcnR5X24pCiAgICApCgogICAgaWYgKCFpZGVudGljYWwob2JzZXJ2ZWRfY29uZGl0aW9ucywgMjo1KSkgewogICAgICBzdG9wKCJDaGVjayIpCiAgICB9CgogICAgbG9uZ19kYXRhIDwtIGFuYWx5c2lzX2RhdGEgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gYWxsX29mKGF0dHJpYnV0ZXMpLAogICAgICAgIG5hbWVzX3RvID0gImF0dHJpYnV0ZSIsCiAgICAgICAgdmFsdWVzX3RvID0gImxldmVsIgogICAgICApICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgIWlzLm5hKGxldmVsKSwKICAgICAgICBsZXZlbCAhPSAiIgogICAgICApCgogICAgZXhwZWN0ZWRfY2VsbHMgPC0gbG9uZ19kYXRhICU+JQogICAgICBkaXN0aW5jdCgKICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgbGV2ZWwKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGF0dHJpYnV0ZV9vcmRlciA9IG1hdGNoKAogICAgICAgICAgYXR0cmlidXRlLAogICAgICAgICAgYXR0cmlidXRlcwogICAgICAgICkKICAgICAgKSAlPiUKICAgICAgYXJyYW5nZSgKICAgICAgICBhdHRyaWJ1dGVfb3JkZXIsCiAgICAgICAgYXR0cmlidXRlLAogICAgICAgIGxldmVsCiAgICAgICkgJT4lCiAgICAgIHNlbGVjdCgtYXR0cmlidXRlX29yZGVyKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGNlbGxfa2V5ID0gcGFzdGUoCiAgICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgICBsZXZlbCwKICAgICAgICAgIHNlcCA9ICJcciIKICAgICAgICApCiAgICAgICkKCiAgICByZXNwb25kZW50X2NlbGwgPC0gbG9uZ19kYXRhICU+JQogICAgICBncm91cF9ieSgKICAgICAgICBwYXJ0eV9uLAogICAgICAgIElELAogICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICBsZXZlbAogICAgICApICU+JQogICAgICBzdW1tYXJpc2UoCiAgICAgICAgeV9zdW0gPSBzdW0oc2VsZWN0ZWQpLAogICAgICAgIG5fb2JzID0gbigpLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGNlbGxfa2V5ID0gcGFzdGUoCiAgICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgICBsZXZlbCwKICAgICAgICAgIHNlcCA9ICJcciIKICAgICAgICApCiAgICAgICkKCiAgICBjb25kaXRpb25fb2JqZWN0cyA8LSBsYXBwbHkoCiAgICAgIDI6NSwKICAgICAgZnVuY3Rpb24obl92YWx1ZSkgewogICAgICAgIGNvbmRpdGlvbl9kYXRhIDwtIHJlc3BvbmRlbnRfY2VsbCAlPiUKICAgICAgICAgIGZpbHRlcigKICAgICAgICAgICAgcGFydHlfbiA9PSBuX3ZhbHVlCiAgICAgICAgICApCgogICAgICAgIGlkX3ZhbHVlcyA8LSBzb3J0KAogICAgICAgICAgdW5pcXVlKGNvbmRpdGlvbl9kYXRhJElEKQogICAgICAgICkKICAgICAgICBuX2lkcyA8LSBsZW5ndGgoaWRfdmFsdWVzKQogICAgICAgIG5fY2VsbHMgPC0gbnJvdyhleHBlY3RlZF9jZWxscykKCiAgICAgICAgaWYgKG5faWRzID09IDApIHsKICAgICAgICAgIHN0b3AoIkNoZWNrIikKICAgICAgICB9CgogICAgICAgIHlfbWF0cml4IDwtIG1hdHJpeCgKICAgICAgICAgIDAsCiAgICAgICAgICBucm93ID0gbl9pZHMsCiAgICAgICAgICBuY29sID0gbl9jZWxscywKICAgICAgICAgIGRpbW5hbWVzID0gbGlzdCgKICAgICAgICAgICAgaWRfdmFsdWVzLAogICAgICAgICAgICBleHBlY3RlZF9jZWxscyRjZWxsX2tleQogICAgICAgICAgKQogICAgICAgICkKCiAgICAgICAgbl9tYXRyaXggPC0gbWF0cml4KAogICAgICAgICAgMCwKICAgICAgICAgIG5yb3cgPSBuX2lkcywKICAgICAgICAgIG5jb2wgPSBuX2NlbGxzLAogICAgICAgICAgZGltbmFtZXMgPSBsaXN0KAogICAgICAgICAgICBpZF92YWx1ZXMsCiAgICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5CiAgICAgICAgICApCiAgICAgICAgKQoKICAgICAgICByb3dfaW5kZXggPC0gbWF0Y2goCiAgICAgICAgICBjb25kaXRpb25fZGF0YSRJRCwKICAgICAgICAgIGlkX3ZhbHVlcwogICAgICAgICkKICAgICAgICBjb2x1bW5faW5kZXggPC0gbWF0Y2goCiAgICAgICAgICBjb25kaXRpb25fZGF0YSRjZWxsX2tleSwKICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5CiAgICAgICAgKQoKICAgICAgICB5X21hdHJpeFtjYmluZChyb3dfaW5kZXgsIGNvbHVtbl9pbmRleCldIDwtCiAgICAgICAgICBjb25kaXRpb25fZGF0YSR5X3N1bQogICAgICAgIG5fbWF0cml4W2NiaW5kKHJvd19pbmRleCwgY29sdW1uX2luZGV4KV0gPC0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJG5fb2JzCgogICAgICAgIGlmIChhbnkoY29sU3VtcyhuX21hdHJpeCkgPT0gMCkpIHsKICAgICAgICAgIG1pc3NpbmdfY2VsbHMgPC0gZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXlbCiAgICAgICAgICAgIGNvbFN1bXMobl9tYXRyaXgpID09IDAKICAgICAgICAgIF0KCiAgICAgICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgICAgICB9CgogICAgICAgIGxpc3QoCiAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwKICAgICAgICAgIGlkcyA9IGlkX3ZhbHVlcywKICAgICAgICAgIGNlbGxfaW5mbyA9IGV4cGVjdGVkX2NlbGxzLAogICAgICAgICAgeV9tYXRyaXggPSB5X21hdHJpeCwKICAgICAgICAgIG5fbWF0cml4ID0gbl9tYXRyaXgKICAgICAgICApCiAgICAgIH0KICAgICkKCiAgICBuYW1lcyhjb25kaXRpb25fb2JqZWN0cykgPC0gYXMuY2hhcmFjdGVyKDI6NSkKCiAgICBsaXN0KAogICAgICBjdWVfbWFwID0gY3VlX21hcCwKICAgICAgYXR0cmlidXRlcyA9IGF0dHJpYnV0ZXMsCiAgICAgIGNvbmRpdGlvbnMgPSBjb25kaXRpb25fb2JqZWN0cwogICAgKQogIH0KCiAgZXN0aW1hdGVfcmVsYXRpdmVfY3VlX2luZGljZXMgPC0gZnVuY3Rpb24oCiAgICAgIHByZXBhcmVkLAogICAgICBjbHVzdGVyX3dlaWdodHMgPSBOVUxMCiAgKSB7CiAgICBjb25kaXRpb25fcmVzdWx0cyA8LSBsYXBwbHkoCiAgICAgIG5hbWVzKHByZXBhcmVkJGNvbmRpdGlvbnMpLAogICAgICBmdW5jdGlvbihjb25kaXRpb25fbmFtZSkgewogICAgICAgIG9iamVjdCA8LSBwcmVwYXJlZCRjb25kaXRpb25zW1tjb25kaXRpb25fbmFtZV1dCgogICAgICAgIGlmIChpcy5udWxsKGNsdXN0ZXJfd2VpZ2h0cykpIHsKICAgICAgICAgIHdlaWdodHMgPC0gcmVwKAogICAgICAgICAgICAxLAogICAgICAgICAgICBsZW5ndGgob2JqZWN0JGlkcykKICAgICAgICAgICkKICAgICAgICB9IGVsc2UgewogICAgICAgICAgd2VpZ2h0cyA8LSBjbHVzdGVyX3dlaWdodHNbW2NvbmRpdGlvbl9uYW1lXV0KICAgICAgICB9CgogICAgICAgIGlmIChsZW5ndGgod2VpZ2h0cykgIT0gbGVuZ3RoKG9iamVjdCRpZHMpKSB7CiAgICAgICAgICBzdG9wKCJDaGVjayIpCiAgICAgICAgfQoKICAgICAgICBudW1lcmF0b3IgPC0gYXMubnVtZXJpYygKICAgICAgICAgIGNyb3NzcHJvZCgKICAgICAgICAgICAgd2VpZ2h0cywKICAgICAgICAgICAgb2JqZWN0JHlfbWF0cml4CiAgICAgICAgICApCiAgICAgICAgKQoKICAgICAgICBkZW5vbWluYXRvciA8LSBhcy5udW1lcmljKAogICAgICAgICAgY3Jvc3Nwcm9kKAogICAgICAgICAgICB3ZWlnaHRzLAogICAgICAgICAgICBvYmplY3Qkbl9tYXRyaXgKICAgICAgICAgICkKICAgICAgICApCgogICAgICAgIGlmIChhbnkoZGVub21pbmF0b3IgPD0gMCkpIHsKICAgICAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgICAgIH0KCiAgICAgICAgbWFyZ2luYWxfbWVhbnMgPC0gbnVtZXJhdG9yIC8gZGVub21pbmF0b3IKCiAgICAgICAgbW1fdGFibGUgPC0gb2JqZWN0JGNlbGxfaW5mbyAlPiUKICAgICAgICAgIHRyYW5zbXV0ZSgKICAgICAgICAgICAgcGFydHlfbiA9IG9iamVjdCRwYXJ0eV9uLAogICAgICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgICAgIGxldmVsLAogICAgICAgICAgICBtYXJnaW5hbF9tZWFuID0gbWFyZ2luYWxfbWVhbnMKICAgICAgICAgICkKCiAgICAgICAgYXR0cmlidXRlX3RhYmxlIDwtIG1tX3RhYmxlICU+JQogICAgICAgICAgZ3JvdXBfYnkoCiAgICAgICAgICAgIHBhcnR5X24sCiAgICAgICAgICAgIGF0dHJpYnV0ZQogICAgICAgICAgKSAlPiUKICAgICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSA9CiAgICAgICAgICAgICAgbWVhbl9hYnNvbHV0ZV9wYWlyd2lzZV9kaWZmZXJlbmNlKAogICAgICAgICAgICAgICAgbWFyZ2luYWxfbWVhbgogICAgICAgICAgICAgICksCiAgICAgICAgICAgIG5fbGV2ZWxzID0gbigpLAogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICAgICAgICApICU+JQogICAgICAgICAgbXV0YXRlKAogICAgICAgICAgICBjdWVfZmFtaWx5ID0gdW5uYW1lKAogICAgICAgICAgICAgIHByZXBhcmVkJGN1ZV9tYXBbYXR0cmlidXRlXQogICAgICAgICAgICApLAogICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkgPSAxIC8gcGFydHlfbiwKICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSAvCiAgICAgICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkKICAgICAgICAgICkKCiAgICAgICAgY3VlX3RhYmxlX2xvbmcgPC0gYXR0cmlidXRlX3RhYmxlICU+JQogICAgICAgICAgZ3JvdXBfYnkoCiAgICAgICAgICAgIHBhcnR5X24sCiAgICAgICAgICAgIGN1ZV9mYW1pbHkKICAgICAgICAgICkgJT4lCiAgICAgICAgICBzdW1tYXJpc2UoCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UgPSBtZWFuKAogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UsCiAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICksCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPSBtZWFuKAogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsCiAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICksCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgICAgICkKCiAgICAgICAgcGFydHlfdGFibGUgPC0gY3VlX3RhYmxlX2xvbmcgJT4lCiAgICAgICAgICBmaWx0ZXIoCiAgICAgICAgICAgIGN1ZV9mYW1pbHkgPT0gInBhcnR5IgogICAgICAgICAgKSAlPiUKICAgICAgICAgIHRyYW5zbXV0ZSgKICAgICAgICAgICAgcGFydHlfbiwKICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSA9CiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZAogICAgICAgICAgKQoKICAgICAgICBlY29ub21pY190YWJsZSA8LSBjdWVfdGFibGVfbG9uZyAlPiUKICAgICAgICAgIGZpbHRlcigKICAgICAgICAgICAgY3VlX2ZhbWlseSA9PSAiZWNvbm9taWMiCiAgICAgICAgICApICU+JQogICAgICAgICAgdHJhbnNtdXRlKAogICAgICAgICAgICBwYXJ0eV9uLAogICAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkCiAgICAgICAgICApCgogICAgICAgIGN1ZV90YWJsZSA8LSBmdWxsX2pvaW4oCiAgICAgICAgICBwYXJ0eV90YWJsZSwKICAgICAgICAgIGVjb25vbWljX3RhYmxlLAogICAgICAgICAgYnkgPSAicGFydHlfbiIKICAgICAgICApICU+JQogICAgICAgICAgbXV0YXRlKAogICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkgPSAxIC8gcGFydHlfbiwKCiAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2UgPQogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgKwogICAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UsCgogICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkICsKICAgICAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAoKICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0gaWZfZWxzZSgKICAgICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlID4gMCwKICAgICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIC8KICAgICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2UsCiAgICAgICAgICAgICAgTkFfcmVhbF8KICAgICAgICAgICAgKSwKCiAgICAgICAgICAgIHJlbGF0aXZlX2Vjb25vbWljX3dlaWdodF9wYWlyd2lzZSA9CiAgICAgICAgICAgICAgMSAtIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSwKCiAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCA9IGlmX2Vsc2UoCiAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA+IDAsCiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCAvCiAgICAgICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAogICAgICAgICAgICAgIE5BX3JlYWxfCiAgICAgICAgICAgICksCgogICAgICAgICAgICByZWxhdGl2ZV9lY29ub21pY193ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQgPQogICAgICAgICAgICAgIDEgLSByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQsCgogICAgICAgICAgICBhZGp1c3RtZW50X2lkZW50aXR5X2RpZmZlcmVuY2UgPQogICAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCAtCiAgICAgICAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UKICAgICAgICAgICkKCiAgICAgICAgaWYgKAogICAgICAgICAgYW55KAogICAgICAgICAgICBhYnMoY3VlX3RhYmxlJGFkanVzdG1lbnRfaWRlbnRpdHlfZGlmZmVyZW5jZSkgPiAxZS0xMCwKICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICApCiAgICAgICAgKSB7CiAgICAgICAgICBzdG9wKCJDaGVjayByZWxhdGl2ZSB3ZWlnaHQiKQogICAgICAgIH0KCiAgICAgICAgbGlzdCgKICAgICAgICAgIG1hcmdpbmFsX21lYW5zID0gbW1fdGFibGUsCiAgICAgICAgICBhdHRyaWJ1dGVfaW1wb3J0YW5jZSA9IGF0dHJpYnV0ZV90YWJsZSwKICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlID0gY3VlX3RhYmxlCiAgICAgICAgKQogICAgICB9CiAgICApCgogICAgbGlzdCgKICAgICAgbWFyZ2luYWxfbWVhbnMgPSBiaW5kX3Jvd3MoCiAgICAgICAgbGFwcGx5KAogICAgICAgICAgY29uZGl0aW9uX3Jlc3VsdHMsCiAgICAgICAgICBmdW5jdGlvbih4KSB4JG1hcmdpbmFsX21lYW5zCiAgICAgICAgKQogICAgICApLAogICAgICBhdHRyaWJ1dGVfaW1wb3J0YW5jZSA9IGJpbmRfcm93cygKICAgICAgICBsYXBwbHkoCiAgICAgICAgICBjb25kaXRpb25fcmVzdWx0cywKICAgICAgICAgIGZ1bmN0aW9uKHgpIHgkYXR0cmlidXRlX2ltcG9ydGFuY2UKICAgICAgICApCiAgICAgICksCiAgICAgIGN1ZV9pbXBvcnRhbmNlID0gYmluZF9yb3dzKAogICAgICAgIGxhcHBseSgKICAgICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzLAogICAgICAgICAgZnVuY3Rpb24oeCkgeCRjdWVfaW1wb3J0YW5jZQogICAgICAgICkKICAgICAgKSAlPiUKICAgICAgICBhcnJhbmdlKHBhcnR5X24pCiAgICApCiAgfQoKICBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfc2xvcGVzIDwtIGZ1bmN0aW9uKGN1ZV9pbXBvcnRhbmNlKSB7CiAgICBjdWVfaW1wb3J0YW5jZSA8LSBjdWVfaW1wb3J0YW5jZSAlPiUKICAgICAgYXJyYW5nZShwYXJ0eV9uKQoKICAgIGlmICghaWRlbnRpY2FsKGN1ZV9pbXBvcnRhbmNlJHBhcnR5X24sIDI6NSkpIHsKICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikKICAgIH0KCiAgICB4IDwtIGN1ZV9pbXBvcnRhbmNlJHBhcnR5X24KCiAgICBjKAogICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UgPQogICAgICAgIGxpbmVhcl9zbG9wZSgKICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlJHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSwKICAgICAgICAgIHgKICAgICAgICApLAoKICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSA9CiAgICAgICAgbGluZWFyX3Nsb3BlKAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgIHgKICAgICAgICApLAoKICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9CiAgICAgICAgbGluZWFyX3Nsb3BlKAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgIHgKICAgICAgICApLAoKICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgbGluZWFyX3Nsb3BlKAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwKICAgICAgICAgIHgKICAgICAgICApLAoKICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgbGluZWFyX3Nsb3BlKAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwKICAgICAgICAgIHgKICAgICAgICApCiAgICApCiAgfQoKICBydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA8LSBmdW5jdGlvbigKICAgICAgcHJlcGFyZWQsCiAgICAgIEIsCiAgICAgIHNlZWQsCiAgICAgIHByb2dyZXNzX2V2ZXJ5ID0gMTAwCiAgKSB7CiAgICBzZXQuc2VlZChzZWVkKQoKICAgIGNvbmRpdGlvbl9yZXN1bHRzIDwtIHZlY3RvcigKICAgICAgImxpc3QiLAogICAgICBCCiAgICApCgogICAgc2xvcGVfbmFtZXMgPC0gYygKICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIsCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwKICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIgogICAgKQoKICAgIHNsb3BlX21hdHJpeCA8LSBtYXRyaXgoCiAgICAgIE5BX3JlYWxfLAogICAgICBucm93ID0gQiwKICAgICAgbmNvbCA9IGxlbmd0aChzbG9wZV9uYW1lcyksCiAgICAgIGRpbW5hbWVzID0gbGlzdCgKICAgICAgICBOVUxMLAogICAgICAgIHNsb3BlX25hbWVzCiAgICAgICkKICAgICkKCiAgICBmb3IgKGIgaW4gc2VxX2xlbihCKSkgewogICAgICBjbHVzdGVyX3dlaWdodHMgPC0gbGFwcGx5KAogICAgICAgIHByZXBhcmVkJGNvbmRpdGlvbnMsCiAgICAgICAgZnVuY3Rpb24ob2JqZWN0KSB7CiAgICAgICAgICBuX2lkcyA8LSBsZW5ndGgob2JqZWN0JGlkcykKCiAgICAgICAgICBzYW1wbGVkX3Bvc2l0aW9ucyA8LSBzYW1wbGUuaW50KAogICAgICAgICAgICBuID0gbl9pZHMsCiAgICAgICAgICAgIHNpemUgPSBuX2lkcywKICAgICAgICAgICAgcmVwbGFjZSA9IFRSVUUKICAgICAgICAgICkKCiAgICAgICAgICB0YWJ1bGF0ZSgKICAgICAgICAgICAgc2FtcGxlZF9wb3NpdGlvbnMsCiAgICAgICAgICAgIG5iaW5zID0gbl9pZHMKICAgICAgICAgICkKICAgICAgICB9CiAgICAgICkKCiAgICAgIGJvb3RzdHJhcF9lc3RpbWF0ZXMgPC0gZXN0aW1hdGVfcmVsYXRpdmVfY3VlX2luZGljZXMoCiAgICAgICAgcHJlcGFyZWQgPSBwcmVwYXJlZCwKICAgICAgICBjbHVzdGVyX3dlaWdodHMgPSBjbHVzdGVyX3dlaWdodHMKICAgICAgKQoKICAgICAgY29uZGl0aW9uX3Jlc3VsdHNbW2JdXSA8LQogICAgICAgIGJvb3RzdHJhcF9lc3RpbWF0ZXMkY3VlX2ltcG9ydGFuY2UgJT4lCiAgICAgICAgc2VsZWN0KAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UsCiAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwKICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsCiAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UKICAgICAgICApICU+JQogICAgICAgIG11dGF0ZSgKICAgICAgICAgIGJvb3RzdHJhcF9yZXBsaWNhdGlvbiA9IGIsCiAgICAgICAgICAuYmVmb3JlID0gMQogICAgICAgICkKCiAgICAgIHNsb3BlX21hdHJpeFtiLCBdIDwtIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMoCiAgICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyRjdWVfaW1wb3J0YW5jZQogICAgICApCgogICAgICBpZiAoCiAgICAgICAgcHJvZ3Jlc3NfZXZlcnkgPiAwICYmCiAgICAgICAgKGIgJSUgcHJvZ3Jlc3NfZXZlcnkgPT0gMCB8fCBiID09IEIpCiAgICAgICkgewogICAgICAgIG1lc3NhZ2UoIkJvb3RzdHJhcDogIiwgYiwgIi8iLCBCKQogICAgICB9CiAgICB9CgogICAgbGlzdCgKICAgICAgY29uZGl0aW9uX2VzdGltYXRlcyA9IGJpbmRfcm93cygKICAgICAgICBjb25kaXRpb25fcmVzdWx0cwogICAgICApLAogICAgICBzbG9wZXMgPSBhc190aWJibGUoCiAgICAgICAgc2xvcGVfbWF0cml4CiAgICAgICkgJT4lCiAgICAgICAgbXV0YXRlKAogICAgICAgICAgYm9vdHN0cmFwX3JlcGxpY2F0aW9uID0gcm93X251bWJlcigpLAogICAgICAgICAgLmJlZm9yZSA9IDEKICAgICAgICApCiAgICApCiAgfQoKICBzdW1tYXJpc2VfY29uZGl0aW9uX2ludGVydmFscyA8LSBmdW5jdGlvbigKICAgICAgb2JzZXJ2ZWRfY3VlX2ltcG9ydGFuY2UsCiAgICAgIGJvb3RzdHJhcF9jb25kaXRpb25fcmVzdWx0cwogICkgewogICAgc3RhdGlzdGljcyA8LSBjKAogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiwKICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiLAogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsCiAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiCiAgICApCgogICAgb2JzZXJ2ZWRfbG9uZyA8LSBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIHBhcnR5X24sCiAgICAgICAgYWxsX29mKHN0YXRpc3RpY3MpCiAgICAgICkgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gYWxsX29mKHN0YXRpc3RpY3MpLAogICAgICAgIG5hbWVzX3RvID0gInN0YXRpc3RpYyIsCiAgICAgICAgdmFsdWVzX3RvID0gImVzdGltYXRlIgogICAgICApCgogICAgYm9vdHN0cmFwX2xvbmcgPC0gYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzICU+JQogICAgICBwaXZvdF9sb25nZXIoCiAgICAgICAgY29scyA9IGFsbF9vZihzdGF0aXN0aWNzKSwKICAgICAgICBuYW1lc190byA9ICJzdGF0aXN0aWMiLAogICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIKICAgICAgKSAlPiUKICAgICAgZ3JvdXBfYnkoCiAgICAgICAgcGFydHlfbiwKICAgICAgICBzdGF0aXN0aWMKICAgICAgKSAlPiUKICAgICAgc3VtbWFyaXNlKAogICAgICAgIGNvbmZfbG93ID0gc2FmZV9xdWFudGlsZSgKICAgICAgICAgIHZhbHVlLAogICAgICAgICAgMC4wMjUKICAgICAgICApLAogICAgICAgIGNvbmZfaGlnaCA9IHNhZmVfcXVhbnRpbGUoCiAgICAgICAgICB2YWx1ZSwKICAgICAgICAgIDAuOTc1CiAgICAgICAgKSwKICAgICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICAgICkKCiAgICBvYnNlcnZlZF9sb25nICU+JQogICAgICBsZWZ0X2pvaW4oCiAgICAgICAgYm9vdHN0cmFwX2xvbmcsCiAgICAgICAgYnkgPSBjKAogICAgICAgICAgInBhcnR5X24iLAogICAgICAgICAgInN0YXRpc3RpYyIKICAgICAgICApCiAgICAgICkKICB9CgogIHN1bW1hcmlzZV9zbG9wZV9pbmZlcmVuY2UgPC0gZnVuY3Rpb24oCiAgICAgIG9ic2VydmVkX3Nsb3BlcywKICAgICAgYm9vdHN0cmFwX3Nsb3BlcwogICkgewogICAgc3RhdGlzdGljX25hbWVzIDwtIG5hbWVzKG9ic2VydmVkX3Nsb3BlcykKCiAgICBtYXBfZGZyKAogICAgICBzdGF0aXN0aWNfbmFtZXMsCiAgICAgIGZ1bmN0aW9uKHN0YXRpc3RpY19uYW1lKSB7CiAgICAgICAgYm9vdHN0cmFwX3ZhbHVlcyA8LSBib290c3RyYXBfc2xvcGVzW1tzdGF0aXN0aWNfbmFtZV1dCiAgICAgICAgYm9vdHN0cmFwX3ZhbHVlcyA8LSBib290c3RyYXBfdmFsdWVzWwogICAgICAgICAgaXMuZmluaXRlKGJvb3RzdHJhcF92YWx1ZXMpCiAgICAgICAgXQoKICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPC0gY2FzZV93aGVuKAogICAgICAgICAgc3RhdGlzdGljX25hbWUgPT0KICAgICAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiIH4gIm5lZ2F0aXZlIiwKICAgICAgICAgIHN0YXRpc3RpY19uYW1lICVpbiUgYygKICAgICAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAgICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwKICAgICAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiCiAgICAgICAgICApIH4gInBvc2l0aXZlIiwKICAgICAgICAgIFRSVUUgfiAibm9uZSIKICAgICAgICApCgogICAgICAgIGFuYWx5c2lzX3JvbGUgPC0gY2FzZV93aGVuKAogICAgICAgICAgc3RhdGlzdGljX25hbWUgJWluJSBjKAogICAgICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsCiAgICAgICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIgogICAgICAgICAgKSB+ICJleHBsb3JhdG9yeV9jaG9pY2Vfc2V0X2FkanVzdGVkIiwKICAgICAgICAgIHN0YXRpc3RpY19uYW1lID09ICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiIH4KICAgICAgICAgICAgImRlcml2ZWRfcmVsYXRpdmVfc2hhcmUiLAogICAgICAgICAgVFJVRSB+ICJtYW51c2NyaXB0X3ByaW1hcnlfdW5hZGp1c3RlZCIKICAgICAgICApCgogICAgICAgIGVzdGltYXRlIDwtIHVubmFtZSgKICAgICAgICAgIG9ic2VydmVkX3Nsb3Blc1tbc3RhdGlzdGljX25hbWVdXQogICAgICAgICkKCiAgICAgICAgdGliYmxlKAogICAgICAgICAgc3R1ZHkgPSAiU3R1ZHkgMiIsCiAgICAgICAgICBzdGF0aXN0aWMgPSBzdGF0aXN0aWNfbmFtZSwKICAgICAgICAgIGVzdGltYXRlID0gZXN0aW1hdGUsCiAgICAgICAgICBjb25mX2xvdyA9IHNhZmVfcXVhbnRpbGUoCiAgICAgICAgICAgIGJvb3RzdHJhcF92YWx1ZXMsCiAgICAgICAgICAgIDAuMDI1CiAgICAgICAgICApLAogICAgICAgICAgY29uZl9oaWdoID0gc2FmZV9xdWFudGlsZSgKICAgICAgICAgICAgYm9vdHN0cmFwX3ZhbHVlcywKICAgICAgICAgICAgMC45NzUKICAgICAgICAgICksCiAgICAgICAgICBwX3ZhbHVlX3R3b19zaWRlZCA9CiAgICAgICAgICAgIGJvb3RzdHJhcF90d29fc2lkZWRfcCgKICAgICAgICAgICAgICBib290c3RyYXBfdmFsdWVzCiAgICAgICAgICAgICksCiAgICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPSBleHBlY3RlZF9kaXJlY3Rpb24sCiAgICAgICAgICBhbmFseXNpc19yb2xlID0gYW5hbHlzaXNfcm9sZSwKICAgICAgICAgIGVzdGltYXRlX2luX2V4cGVjdGVkX2RpcmVjdGlvbiA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgZXhwZWN0ZWRfZGlyZWN0aW9uID09ICJwb3NpdGl2ZSIgfiBlc3RpbWF0ZSA+IDAsCiAgICAgICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9PSAibmVnYXRpdmUiIH4gZXN0aW1hdGUgPCAwLAogICAgICAgICAgICBUUlVFIH4gTkEKICAgICAgICAgICkKICAgICAgICApCiAgICAgIH0KICAgICkKICB9CgogIHJlbGF0aXZlX2N1ZV9wcmVwYXJlZCA8LSBwcmVwYXJlX3JlbGF0aXZlX2N1ZV9hbmFseXNpcygKICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwKICAgIGN1ZV9tYXAgPSByZWxhdGl2ZV9jdWVfbWFwCiAgKQoKICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQgPC0gZXN0aW1hdGVfcmVsYXRpdmVfY3VlX2luZGljZXMoCiAgICBwcmVwYXJlZCA9IHJlbGF0aXZlX2N1ZV9wcmVwYXJlZAogICkKCiAgcmVsYXRpdmVfY3VlX29ic2VydmVkX3Nsb3BlcyA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfc2xvcGVzKAogICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJG1hcmdpbmFsX21lYW5zLAogICAgInN0dWR5Ml9yZWxhdGl2ZV9jdWVfbWFyZ2luYWxfbWVhbnMuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRhdHRyaWJ1dGVfaW1wb3J0YW5jZSwKICAgICJzdHVkeTJfcmVsYXRpdmVfY3VlX2F0dHJpYnV0ZV9pbXBvcnRhbmNlLmNzdiIKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsCiAgICAic3R1ZHkyX3JlbGF0aXZlX2N1ZV9pbXBvcnRhbmNlX2FuZF93ZWlnaHQuY3N2IgogICkKCiAgcmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlIDwtIGZpbGUucGF0aCgKICAgIG91dHB1dF9kaXIsCiAgICBwYXN0ZTAoCiAgICAgICJzdHVkeTJfcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXBfIiwKICAgICAgdW5pZmllZF9jb25maWckY3VlX2ltcG9ydGFuY2VfbWV0cmljX3ZlcnNpb24sCiAgICAgICJfQiIsCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiwKICAgICAgIi5jc3YiCiAgICApCiAgKQoKICByZWxhdGl2ZV9zbG9wZV9ib290c3RyYXBfZmlsZSA8LSBmaWxlLnBhdGgoCiAgICBvdXRwdXRfZGlyLAogICAgcGFzdGUwKAogICAgICAic3R1ZHkyX3JlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXBfIiwKICAgICAgdW5pZmllZF9jb25maWckY3VlX2ltcG9ydGFuY2VfbWV0cmljX3ZlcnNpb24sCiAgICAgICJfQiIsCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiwKICAgICAgIi5jc3YiCiAgICApCiAgKQoKICB1c2Vfc2F2ZWRfcmVsYXRpdmVfYm9vdHN0cmFwIDwtCiAgICAhcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCAmJgogICAgZmlsZS5leGlzdHMocmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlKSAmJgogICAgZmlsZS5leGlzdHMocmVsYXRpdmVfc2xvcGVfYm9vdHN0cmFwX2ZpbGUpCgogIGlmICh1c2Vfc2F2ZWRfcmVsYXRpdmVfYm9vdHN0cmFwKSB7CiAgICBtZXNzYWdlKCJCb290c3RyYXAgY2FjaGUiKQoKICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwIDwtIHJlYWRyOjpyZWFkX2NzdigKICAgICAgcmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlLAogICAgICBzaG93X2NvbF90eXBlcyA9IEZBTFNFCiAgICApCgogICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCA8LSByZWFkcjo6cmVhZF9jc3YoCiAgICAgIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlLAogICAgICBzaG93X2NvbF90eXBlcyA9IEZBTFNFCiAgICApCgogICAgc2F2ZWRfQl9jb25kaXRpb24gPC0gbl9kaXN0aW5jdCgKICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAkYm9vdHN0cmFwX3JlcGxpY2F0aW9uCiAgICApCiAgICBzYXZlZF9CX3Nsb3BlIDwtIG5fZGlzdGluY3QoCiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAkYm9vdHN0cmFwX3JlcGxpY2F0aW9uCiAgICApCgogICAgaWYgKAogICAgICBzYXZlZF9CX2NvbmRpdGlvbiAhPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgfHwKICAgICAgc2F2ZWRfQl9zbG9wZSAhPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IKICAgICkgewogICAgICBtZXNzYWdlKCJCb290c3RyYXAgY2FjaGUiKQogICAgICB1c2Vfc2F2ZWRfcmVsYXRpdmVfYm9vdHN0cmFwIDwtIEZBTFNFCiAgICB9CiAgfQoKICBpZiAoIXVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXApIHsKICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAgPC0gcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAoCiAgICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkLAogICAgICBCID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLAogICAgICBzZWVkID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkLAogICAgICBwcm9ncmVzc19ldmVyeSA9IHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkKICAgICkKCiAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCA8LQogICAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwJGNvbmRpdGlvbl9lc3RpbWF0ZXMKCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwIDwtCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAkc2xvcGVzCgogICAgcmVhZHI6OndyaXRlX2NzdigKICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAsCiAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9ib290c3RyYXBfZmlsZQogICAgKQoKICAgIHJlYWRyOjp3cml0ZV9jc3YoCiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAsCiAgICAgIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlCiAgICApCiAgfQoKICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyA8LSBzdW1tYXJpc2VfY29uZGl0aW9uX2ludGVydmFscygKICAgIG9ic2VydmVkX2N1ZV9pbXBvcnRhbmNlID0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlLAogICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzID0KICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAKICApCgogIHJlbGF0aXZlX2N1ZV9zbG9wZV9pbmZlcmVuY2UgPC0gc3VtbWFyaXNlX3Nsb3BlX2luZmVyZW5jZSgKICAgIG9ic2VydmVkX3Nsb3BlcyA9CiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZF9zbG9wZXMsCiAgICBib290c3RyYXBfc2xvcGVzID0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcAogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzLAogICAgInN0dWR5Ml9yZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscy5jc3YiCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSwKICAgICJzdHVkeTJfcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZS5jc3YiCiAgKQoKICByZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQgPC0gcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSAlPiUKICAgIGZpbHRlcigKICAgICAgc3RhdGlzdGljID09CiAgICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIKICAgICkKCiAgY2F0KCJcblN0dWR5IDLvvJrnm7jlr77mr5Tph43jga7nt5rlvaLlgr7lkJFcbiIpCiAgcHJpbnQocmVsYXRpdmVfY3VlX3ByaW1hcnlfcmVzdWx0KQoKCiAgcmVsYXRpdmVfeF9vZmZzZXQgPC0gMC4wNzUKCiAgcmVsYXRpdmVfcGFuZWxfYV9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQogICAgZmlsdGVyKAogICAgICBzdGF0aXN0aWMgJWluJSBjKAogICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwKICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIKICAgICAgKQogICAgKSAlPiUKICAgIG11dGF0ZSgKICAgICAgY3VlX2ZhbWlseSA9IHJlY29kZSgKICAgICAgICBzdGF0aXN0aWMsCiAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLmlL/lhZrmiYvjgYzjgYvjgooiLAogICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPSAi57WM5riI5omL44GM44GL44KKIgogICAgICApLAogICAgICBjdWVfZmFtaWx5ID0gZmFjdG9yKAogICAgICAgIGN1ZV9mYW1pbHksCiAgICAgICAgbGV2ZWxzID0gYygKICAgICAgICAgICLmlL/lhZrmiYvjgYzjgYvjgooiLAogICAgICAgICAgIue1jOa4iOaJi+OBjOOBi+OCiiIKICAgICAgICApCiAgICAgICksCiAgICAgIHhfcGxvdCA9IGNhc2Vfd2hlbigKICAgICAgICBjdWVfZmFtaWx5ID09ICLmlL/lhZrmiYvjgYzjgYvjgooiIH4KICAgICAgICAgIHBhcnR5X24gKyByZWxhdGl2ZV94X29mZnNldCwKICAgICAgICBjdWVfZmFtaWx5ID09ICLntYzmuIjmiYvjgYzjgYvjgooiIH4KICAgICAgICAgIHBhcnR5X24gLSByZWxhdGl2ZV94X29mZnNldCwKICAgICAgICBUUlVFIH4gYXMubnVtZXJpYyhwYXJ0eV9uKQogICAgICApLAogICAgICB2YWx1ZV9sYWJlbCA9IHNwcmludGYoCiAgICAgICAgIiUuM2YiLAogICAgICAgIGVzdGltYXRlCiAgICAgICkKICAgICkKCiAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQogICAgZmlsdGVyKAogICAgICBzdGF0aXN0aWMgPT0KICAgICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIgogICAgKSAlPiUKICAgIG11dGF0ZSgKICAgICAgdmFsdWVfbGFiZWwgPSBzcHJpbnRmKAogICAgICAgICIlLjFmJSUiLAogICAgICAgIDEwMCAqIGVzdGltYXRlCiAgICAgICkKICAgICkKCiAgcmVsYXRpdmVfYWRqdXN0ZWRfbGFiZWxfbWFwIDwtIHJlbGF0aXZlX3BhbmVsX2FfZGF0YSAlPiUKICAgIGRpc3RpbmN0KAogICAgICBzdGF0aXN0aWMsCiAgICAgIGN1ZV9mYW1pbHkKICAgICkgJT4lCiAgICBtdXRhdGUoCiAgICAgIHN0YXRpc3RpYyA9IHBhc3RlMCgKICAgICAgICBzdGF0aXN0aWMsCiAgICAgICAgIl9hZGp1c3RlZCIKICAgICAgKSwKICAgICAgY3VlX2ZhbWlseSA9IGFzLmNoYXJhY3RlcigKICAgICAgICBjdWVfZmFtaWx5CiAgICAgICkKICAgICkKCiAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWRfZGF0YSA8LSByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyAlPiUKICAgIGZpbHRlcigKICAgICAgc3RhdGlzdGljICVpbiUgYygKICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsCiAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiCiAgICAgICkKICAgICkgJT4lCiAgICBsZWZ0X2pvaW4oCiAgICAgIHJlbGF0aXZlX2FkanVzdGVkX2xhYmVsX21hcCwKICAgICAgYnkgPSAic3RhdGlzdGljIgogICAgKSAlPiUKICAgIG11dGF0ZSgKICAgICAgY3VlX2ZhbWlseSA9IGZhY3RvcigKICAgICAgICBjdWVfZmFtaWx5LAogICAgICAgIGxldmVscyA9IGxldmVscygKICAgICAgICAgIHJlbGF0aXZlX3BhbmVsX2FfZGF0YSRjdWVfZmFtaWx5CiAgICAgICAgKQogICAgICApLAogICAgICB4X3Bsb3QgPSBpZl9lbHNlKAogICAgICAgIGFzLmludGVnZXIoY3VlX2ZhbWlseSkgPT0gMUwsCiAgICAgICAgcGFydHlfbiArIHJlbGF0aXZlX3hfb2Zmc2V0LAogICAgICAgIHBhcnR5X24gLSByZWxhdGl2ZV94X29mZnNldAogICAgICApLAogICAgICB2YWx1ZV9sYWJlbCA9IHNwcmludGYoCiAgICAgICAgIiUuMWYlJSIsCiAgICAgICAgMTAwICogZXN0aW1hdGUKICAgICAgKQogICAgKQoKICByZWxhdGl2ZV9jb25kaXRpb25fc3VmZml4IDwtIGlmICgKICAgICLmlL/lhZrlkI3miYvjgYzjgYvjgooiICVpbiUKICAgICAgbGV2ZWxzKHJlbGF0aXZlX3BhbmVsX2FfZGF0YSRjdWVfZmFtaWx5KQogICkgewogICAgIumBuOaKnuiCoiIKICB9IGVsc2UgewogICAgIuaUv+WFmiIKICB9CgogIHJlbGF0aXZlX2NvbmRpdGlvbl9heGlzX3RpdGxlIDwtIGlmICgKICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXggPT0gIumBuOaKnuiCoiIKICApIHsKICAgICLmlL/msrvntYzmuIjnirbms4Hjga7pgbjmip7ogqLmlbAiCiAgfSBlbHNlIHsKICAgICLmlL/lhZrpgbjmip7ogqLmlbAiCiAgfQoKICByZWxhdGl2ZV9maWd1cmVfZm9udF9mYW1pbHkgPC0gaWYgKAogICAgLlBsYXRmb3JtJE9TLnR5cGUgPT0gIndpbmRvd3MiCiAgKSB7CiAgICAiWXUgR290aGljIgogIH0gZWxzZSB7CiAgICAic2FucyIKICB9CgogIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3IDwtIHRoZW1lX2J3KAogICAgYmFzZV9zaXplID0gMTIsCiAgICBiYXNlX2ZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseQogICkgKwogICAgdGhlbWUoCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoCiAgICAgICAgbGluZXdpZHRoID0gMC4zMCwKICAgICAgICBjb2xvciA9ICJncmV5ODgiCiAgICAgICksCiAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdCgKICAgICAgICBsaW5ld2lkdGggPSAwLjY1LAogICAgICAgIGNvbG9yID0gImJsYWNrIgogICAgICApLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoCiAgICAgICAgY29sb3IgPSAiYmxhY2siCiAgICAgICksCiAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgY29sb3IgPSAiYmxhY2siCiAgICAgICksCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgc2l6ZSA9IDEyLjUsCiAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICBoanVzdCA9IDAKICAgICAgKSwKICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBzaXplID0gOS41LAogICAgICAgIGhqdXN0ID0gMCwKICAgICAgICBtYXJnaW4gPSBtYXJnaW4oCiAgICAgICAgICBiID0gOAogICAgICAgICkKICAgICAgKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gImNlbnRlciIsCiAgICAgIGxlZ2VuZC5rZXkud2lkdGggPSBncmlkOjp1bml0KAogICAgICAgIDEuMjUsCiAgICAgICAgImNtIgogICAgICApLAogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigKICAgICAgICA4LAogICAgICAgIDEwLAogICAgICAgIDgsCiAgICAgICAgOAogICAgICApCiAgICApCgogIHJlbGF0aXZlX3BhbmVsX2EgPC0gZ2dwbG90KAogICAgcmVsYXRpdmVfcGFuZWxfYV9kYXRhLAogICAgYWVzKAogICAgICB4ID0geF9wbG90LAogICAgICB5ID0gZXN0aW1hdGUsCiAgICAgIGdyb3VwID0gY3VlX2ZhbWlseSwKICAgICAgbGluZXR5cGUgPSBjdWVfZmFtaWx5CiAgICApCiAgKSArCiAgICBnZW9tX2xpbmUoCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBnZW9tX2Vycm9yYmFyKAogICAgICBhZXMoCiAgICAgICAgeW1pbiA9IGNvbmZfbG93LAogICAgICAgIHltYXggPSBjb25mX2hpZ2gKICAgICAgKSwKICAgICAgd2lkdGggPSAwLjA3NSwKICAgICAgbGluZXdpZHRoID0gMC44MCwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fbGFiZWwoCiAgICAgIGFlcygKICAgICAgICBsYWJlbCA9IHZhbHVlX2xhYmVsCiAgICAgICksCiAgICAgIHNpemUgPSAzLjU1LAogICAgICBmYW1pbHkgPSByZWxhdGl2ZV9maWd1cmVfZm9udF9mYW1pbHksCiAgICAgIGxhYmVsLnNpemUgPSAwLAogICAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdCgKICAgICAgICAwLjEyLAogICAgICAgICJsaW5lcyIKICAgICAgKSwKICAgICAgZmlsbCA9ICJ3aGl0ZSIsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIuaUv+WFmuaJi+OBjOOBi+OCiiIgPSAic29saWQiLAogICAgICAgICLntYzmuIjmiYvjgYzjgYvjgooiID0gImRhc2hlZCIKICAgICAgKQogICAgKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgIGJyZWFrcyA9IDI6NSwKICAgICAgbGFiZWxzID0gcGFzdGUwKAogICAgICAgIDI6NSwKICAgICAgICAi5pS/5YWaIgogICAgICApLAogICAgICBsaW1pdHMgPSBjKAogICAgICAgIDEuNzIsCiAgICAgICAgNS4yOAogICAgICApCiAgICApICsKICAgIHNjYWxlX3lfY29udGludW91cygKICAgICAgbGFiZWxzID0gbGFiZWxfbnVtYmVyKAogICAgICAgIGFjY3VyYWN5ID0gMC4wMDUKICAgICAgKSwKICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKAogICAgICAgIG11bHQgPSBjKAogICAgICAgICAgMC4wNywKICAgICAgICAgIDAuMTAKICAgICAgICApCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgdGl0bGUgPSAiQe+8muS4oeaJi+OBjOOBi+OCiuOBrue1tuWvvueahOmHjeimgeW6piIsCiAgICAgIHN1YnRpdGxlID0gIiIsCiAgICAgIHggPSAi5pS/5YWa6YG45oqe6IKi5pWwIiwKICAgICAgeSA9ICLmiYvjgYzjgYvjgorph43opoHluqYiLAogICAgICBsaW5ldHlwZSA9IE5VTEwKICAgICkgKwogICAgZ3VpZGVzKAogICAgICBsaW5ldHlwZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBvdmVycmlkZS5hZXMgPSBsaXN0KAogICAgICAgICAgbGluZXdpZHRoID0gMC45MAogICAgICAgICkKICAgICAgKQogICAgKSArCiAgICByZWxhdGl2ZV90aGVtZV9qYXBhbmVzZV9idwoKICByZWxhdGl2ZV9hZGp1c3RlZF9saW5ldHlwZXMgPC0gc2V0TmFtZXMoCiAgICBjKAogICAgICAic29saWQiLAogICAgICAiZGFzaGVkIgogICAgKSwKICAgIGxldmVscygKICAgICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWRfZGF0YSRjdWVfZmFtaWx5CiAgICApCiAgKQoKICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZCA8LSBnZ3Bsb3QoCiAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhLAogICAgYWVzKAogICAgICB4ID0geF9wbG90LAogICAgICB5ID0gZXN0aW1hdGUsCiAgICAgIGdyb3VwID0gY3VlX2ZhbWlseSwKICAgICAgbGluZXR5cGUgPSBjdWVfZmFtaWx5CiAgICApCiAgKSArCiAgICBnZW9tX2xpbmUoCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBnZW9tX2Vycm9yYmFyKAogICAgICBhZXMoCiAgICAgICAgeW1pbiA9IGNvbmZfbG93LAogICAgICAgIHltYXggPSBjb25mX2hpZ2gKICAgICAgKSwKICAgICAgd2lkdGggPSAwLjA3NSwKICAgICAgbGluZXdpZHRoID0gMC44MCwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fbGFiZWwoCiAgICAgIGFlcygKICAgICAgICBsYWJlbCA9IHZhbHVlX2xhYmVsCiAgICAgICksCiAgICAgIHNpemUgPSAzLjU1LAogICAgICBmYW1pbHkgPSByZWxhdGl2ZV9maWd1cmVfZm9udF9mYW1pbHksCiAgICAgIGxhYmVsLnNpemUgPSAwLAogICAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdCgKICAgICAgICAwLjEyLAogICAgICAgICJsaW5lcyIKICAgICAgKSwKICAgICAgZmlsbCA9ICJ3aGl0ZSIsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIHZhbHVlcyA9IHJlbGF0aXZlX2FkanVzdGVkX2xpbmV0eXBlcwogICAgKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgIGJyZWFrcyA9IDI6NSwKICAgICAgbGFiZWxzID0gcGFzdGUwKAogICAgICAgIDI6NSwKICAgICAgICByZWxhdGl2ZV9jb25kaXRpb25fc3VmZml4CiAgICAgICksCiAgICAgIGxpbWl0cyA9IGMoCiAgICAgICAgMS43MiwKICAgICAgICA1LjI4CiAgICAgICkKICAgICkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKAogICAgICBsYWJlbHMgPSBsYWJlbF9wZXJjZW50KAogICAgICAgIGFjY3VyYWN5ID0gMQogICAgICApLAogICAgICBleHBhbmQgPSBleHBhbnNpb24oCiAgICAgICAgbXVsdCA9IGMoCiAgICAgICAgICAwLjA3LAogICAgICAgICAgMC4xMAogICAgICAgICkKICAgICAgKQogICAgKSArCiAgICBsYWJzKAogICAgICB0aXRsZSA9ICJB77ya6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqmIiwKICAgICAgc3VidGl0bGUgPQogICAgICAgICLmnKroqr/mlbTph43opoHluqYgw7cg5bmz5Z2H6YG45oqe56K6546H77yIMe+8j+mBuOaKnuiCouaVsO+8iSIsCiAgICAgIHggPSByZWxhdGl2ZV9jb25kaXRpb25fYXhpc190aXRsZSwKICAgICAgeSA9ICLlubPlnYfpgbjmip7norrnjofjgavlr77jgZnjgovmsLTmupbplpPlt64iLAogICAgICBsaW5ldHlwZSA9IE5VTEwKICAgICkgKwogICAgZ3VpZGVzKAogICAgICBsaW5ldHlwZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBvdmVycmlkZS5hZXMgPSBsaXN0KAogICAgICAgICAgbGluZXdpZHRoID0gMC45MAogICAgICAgICkKICAgICAgKQogICAgKSArCiAgICByZWxhdGl2ZV90aGVtZV9qYXBhbmVzZV9idwoKICByZWxhdGl2ZV9iX3JhbmdlIDwtIHJhbmdlKAogICAgYygKICAgICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhJGNvbmZfbG93LAogICAgICByZWxhdGl2ZV9wYW5lbF9iX2RhdGEkY29uZl9oaWdoLAogICAgICAwLjUKICAgICksCiAgICBuYS5ybSA9IFRSVUUKICApCgogIHJlbGF0aXZlX2JfcGFkZGluZyA8LSBtYXgoCiAgICAwLjAyNSwKICAgIDAuMTAgKiBkaWZmKHJlbGF0aXZlX2JfcmFuZ2UpCiAgKQoKICByZWxhdGl2ZV9iX2xvd2VyIDwtIG1heCgKICAgIDAsCiAgICBmbG9vcigKICAgICAgMjAgKgogICAgICAgIChyZWxhdGl2ZV9iX3JhbmdlWzFdIC0gcmVsYXRpdmVfYl9wYWRkaW5nKQogICAgKSAvIDIwCiAgKQoKICByZWxhdGl2ZV9iX3VwcGVyIDwtIG1pbigKICAgIDEsCiAgICBjZWlsaW5nKAogICAgICAyMCAqCiAgICAgICAgKHJlbGF0aXZlX2JfcmFuZ2VbMl0gKyByZWxhdGl2ZV9iX3BhZGRpbmcpCiAgICApIC8gMjAKICApCgogIGlmIChyZWxhdGl2ZV9iX2xvd2VyID49IHJlbGF0aXZlX2JfdXBwZXIpIHsKICAgIHJlbGF0aXZlX2JfbG93ZXIgPC0gbWF4KAogICAgICAwLAogICAgICByZWxhdGl2ZV9iX2xvd2VyIC0gMC4wNQogICAgKQogICAgcmVsYXRpdmVfYl91cHBlciA8LSBtaW4oCiAgICAgIDEsCiAgICAgIHJlbGF0aXZlX2JfdXBwZXIgKyAwLjA1CiAgICApCiAgfQoKICByZWxhdGl2ZV9wYW5lbF9iIDwtIGdncGxvdCgKICAgIHJlbGF0aXZlX3BhbmVsX2JfZGF0YSwKICAgIGFlcygKICAgICAgeCA9IHBhcnR5X24sCiAgICAgIHkgPSBlc3RpbWF0ZQogICAgKQogICkgKwogICAgZ2VvbV9obGluZSgKICAgICAgeWludGVyY2VwdCA9IDAuNSwKICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgICAgbGluZXdpZHRoID0gMC41NSwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fbGluZSgKICAgICAgbGluZXdpZHRoID0gMC44MCwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fZXJyb3JiYXIoCiAgICAgIGFlcygKICAgICAgICB5bWluID0gY29uZl9sb3csCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaAogICAgICApLAogICAgICB3aWR0aCA9IDAuMDc1LAogICAgICBsaW5ld2lkdGggPSAwLjgwLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9sYWJlbCgKICAgICAgYWVzKAogICAgICAgIGxhYmVsID0gdmFsdWVfbGFiZWwKICAgICAgKSwKICAgICAgc2l6ZSA9IDMuNTUsCiAgICAgIGZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSwKICAgICAgbGFiZWwuc2l6ZSA9IDAsCiAgICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KAogICAgICAgIDAuMTIsCiAgICAgICAgImxpbmVzIgogICAgICApLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgYnJlYWtzID0gMjo1LAogICAgICBsYWJlbHMgPSBwYXN0ZTAoCiAgICAgICAgMjo1LAogICAgICAgICLmlL/lhZoiCiAgICAgICksCiAgICAgIGxpbWl0cyA9IGMoCiAgICAgICAgMS43MiwKICAgICAgICA1LjI4CiAgICAgICkKICAgICkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKAogICAgICBicmVha3MgPSBzZXEoCiAgICAgICAgcmVsYXRpdmVfYl9sb3dlciwKICAgICAgICByZWxhdGl2ZV9iX3VwcGVyLAogICAgICAgIGJ5ID0gMC4wNQogICAgICApLAogICAgICBsYWJlbHMgPSBsYWJlbF9wZXJjZW50KAogICAgICAgIGFjY3VyYWN5ID0gMQogICAgICApLAogICAgICBleHBhbmQgPSBleHBhbnNpb24oCiAgICAgICAgbXVsdCA9IGMoCiAgICAgICAgICAwLjA1LAogICAgICAgICAgMC4wOAogICAgICAgICkKICAgICAgKQogICAgKSArCiAgICBjb29yZF9jYXJ0ZXNpYW4oCiAgICAgIHlsaW0gPSBjKAogICAgICAgIHJlbGF0aXZlX2JfbG93ZXIsCiAgICAgICAgcmVsYXRpdmVfYl91cHBlcgogICAgICApCiAgICApICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gIkLvvJrnm7jlr77nmoTjgarmlL/lhZrmiYvjgYzjgYvjgorjga7mr5Tph40iLAogICAgICBzdWJ0aXRsZSA9CiAgICAgICAgIuaUv+WFmuaJi+OBjOOBi+OCiumHjeimgeW6piDDt++8iOaUv+WFmuaJi+OBjOOBi+OCiumHjeimgeW6pu+8i+e1jOa4iOaJi+OBjOOBi+OCiumHjeimgeW6pu+8iSIsCiAgICAgIHggPSAi5pS/5YWa6YG45oqe6IKi5pWwIiwKICAgICAgeSA9ICLnm7jlr77nmoTjgarmlL/lhZrmiYvjgYzjgYvjgormr5Tph40iCiAgICApICsKICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3ICsKICAgIHRoZW1lKAogICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICAgICkKCiAgcmVsYXRpdmVfcGFuZWxfYyA8LSByZWxhdGl2ZV9wYW5lbF9iICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gcGFzdGUwKAogICAgICAgICJC77ya55u45a++55qE44GqIiwKICAgICAgICBsZXZlbHMocmVsYXRpdmVfcGFuZWxfYV9kYXRhJGN1ZV9mYW1pbHkpWzFdLAogICAgICAgICLjga7mr5Tph40iCiAgICAgICkKICAgICkKCiAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCA8LSAoCiAgICByZWxhdGl2ZV9wYW5lbF9hIHwKICAgICAgcmVsYXRpdmVfcGFuZWxfYgogICkgKwogICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dCgKICAgICAgd2lkdGhzID0gYygKICAgICAgICAxLAogICAgICAgIDEKICAgICAgKQogICAgKQoKICBwcmludCgKICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAKICApCgogIHNhdmVfcGxvdCgKICAgICJmaWdfc3R1ZHkyX3JlbGF0aXZlX2N1ZV93ZWlnaHRfanBfYncucG5nIiwKICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsCiAgICB3aWR0aCA9IDExLjIsCiAgICBoZWlnaHQgPSA1LjQsCiAgICBkcGkgPSA0MDAKICApCgogIGdnc2F2ZSgKICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAiZmlnX3N0dWR5Ml9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBkZiIKICAgICksCiAgICBwbG90ID0gZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCwKICAgIHdpZHRoID0gMTEuMiwKICAgIGhlaWdodCA9IDUuNCwKICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLAogICAgYmcgPSAid2hpdGUiCiAgKQoKICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwIDwtICgKICAgIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkIHwKICAgICAgcmVsYXRpdmVfcGFuZWxfYwogICkgKwogICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dCgKICAgICAgd2lkdGhzID0gYygKICAgICAgICAxLAogICAgICAgIDEKICAgICAgKQogICAgKQoKICBwcmludCgKICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAKICApCgogIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViIDwtIHBhc3RlMCgKICAgICJmaWdfc3R1ZHkiLAogICAgc3RyaW5ncjo6c3RyX2V4dHJhY3QoCiAgICAgIHN0dWR5X2xhYmVsLAogICAgICAiWzEyM10iCiAgICApLAogICAgIl9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYnciCiAgKQoKICBzYXZlX3Bsb3QoCiAgICBwYXN0ZTAoCiAgICAgIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViLAogICAgICAiLnBuZyIKICAgICksCiAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwLAogICAgd2lkdGggPSAxMS4yLAogICAgaGVpZ2h0ID0gNS40LAogICAgZHBpID0gNDAwCiAgKQoKICBnZ3NhdmUoCiAgICBmaWxlbmFtZSA9IGZpbGUucGF0aCgKICAgICAgb3V0cHV0X2RpciwKICAgICAgcGFzdGUwKAogICAgICAgIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViLAogICAgICAgICIucGRmIgogICAgICApCiAgICApLAogICAgcGxvdCA9IGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAsCiAgICB3aWR0aCA9IDExLjIsCiAgICBoZWlnaHQgPSA1LjQsCiAgICBkZXZpY2UgPSBnckRldmljZXM6OmNhaXJvX3BkZiwKICAgIGJnID0gIndoaXRlIgogICkKCiAgcmVsYXRpdmVfY3VlX3Jlc3VsdHMgPC0gbGlzdCgKICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkLAogICAgbWFyZ2luYWxfbWVhbnMgPQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkbWFyZ2luYWxfbWVhbnMsCiAgICBhdHRyaWJ1dGVfaW1wb3J0YW5jZSA9CiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRhdHRyaWJ1dGVfaW1wb3J0YW5jZSwKICAgIGN1ZV9pbXBvcnRhbmNlID0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlLAogICAgb2JzZXJ2ZWRfc2xvcGVzID0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkX3Nsb3BlcywKICAgIGNvbmRpdGlvbl9ib290c3RyYXAgPQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCwKICAgIHNsb3BlX2Jvb3RzdHJhcCA9CiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAsCiAgICBjb25kaXRpb25faW50ZXJ2YWxzID0KICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMsCiAgICBzbG9wZV9pbmZlcmVuY2UgPQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlLAogICAgcHJpbWFyeV9yZXN1bHQgPQogICAgICByZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQsCiAgICBwbG90cyA9IGxpc3QoCiAgICAgIGFic29sdXRlX2ltcG9ydGFuY2UgPSByZWxhdGl2ZV9wYW5lbF9hLAogICAgICBjaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2UgPQogICAgICAgIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkLAogICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHQgPSByZWxhdGl2ZV9wYW5lbF9iLAogICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFuZWxfYyA9CiAgICAgICAgcmVsYXRpdmVfcGFuZWxfYywKICAgICAgY29tYmluZWQgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLAogICAgICBjb21iaW5lZF93aXRoX2Nob2ljZV9zZXRfYWRqdXN0bWVudCA9CiAgICAgICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcAogICAgKQogICkKCiAgc2F2ZVJEUygKICAgIHJlbGF0aXZlX2N1ZV9yZXN1bHRzLAogICAgZmlsZSA9IGZpbGUucGF0aCgKICAgICAgb3V0cHV0X2RpciwKICAgICAgInN0dWR5Ml9yZWxhdGl2ZV9jdWVfcmVzdWx0cy5yZHMiCiAgICApCiAgKQoKCiAgc2F2ZVJEUygKICAgIGxpc3QoCiAgICAgIHNldHRpbmdzID0gbGlzdCgKICAgICAgICByZXF1aXJlX2luaXRpYWxfY29uc2VudCA9IHJlcXVpcmVfaW5pdGlhbF9jb25zZW50LAogICAgICAgIHJlcXVpcmVfZmluYWxfY29uc2VudCA9IHJlcXVpcmVfZmluYWxfY29uc2VudCwKICAgICAgICByZXF1aXJlX2F0dGVudGlvbl9jaGVjayA9IHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrLAogICAgICAgIHJlcXVpcmVfbWFuaXB1bGF0aW9uX2NoZWNrID0gcmVxdWlyZV9tYW5pcHVsYXRpb25fY2hlY2sKICAgICAgKSwKICAgICAgc2FtcGxlX2Zsb3cgPSBzYW1wbGVfZmxvdywKICAgICAgbl9ieV9wYXJ0eSA9IG5fYnlfcGFydHksCiAgICAgIHZhbGlkX2lkcyA9IHZhbGlkX2lkcywKICAgICAgY29uam9pbnRfYWxsID0gY29uam9pbnRfYWxsLAogICAgICBjb25qb2ludF9hbGxfbSA9IGNvbmpvaW50X2FsbF9tLAogICAgICBjb3Zhcl9pZCA9IGNvdmFyX2lkLAogICAgICBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiA9IG1vZGVsc19ieV9wYXJ0eV9uX25vY292LAogICAgICBtb2RlbHNfYnlfcGFydHlfbl9jb3YgPSBtb2RlbHNfYnlfcGFydHlfbl9jb3YsCiAgICAgIG1faW50ZXJhY3Rpb24gPSBtX2ludGVyYWN0aW9uLAogICAgICBtb2RlbHNfY2xvZ2l0X25vY292ID0gbW9kZWxzX2Nsb2dpdF9ub2NvdiwKICAgICAgcmVsYXRpdmVfY3VlID0gcmVsYXRpdmVfY3VlX3Jlc3VsdHMsCiAgICAgIHBsb3RzID0gbGlzdCgKICAgICAgICBhbWNlX2NvdiA9IHBfYW1jZV9jb3ZfbWFpbiwKICAgICAgICBhbWNlX25vY292ID0gcF9hbWNlX25vY292X2FwcGVuZGl4LAogICAgICAgIGludGVyYWN0aW9uID0gcF9pbnRlcmFjdGlvbiwKICAgICAgICBoZWF0bWFwID0gcF9oZWF0X2FtY2UsCiAgICAgICAgaGVhdG1hcF9yYW5rID0gcF9oZWF0X2FtY2VfcmFuaywKICAgICAgICBjbG9naXRfb2Rkc19yYXRpbyA9IHBfY2xvZ2l0X29yLAogICAgICAgIHJlbGF0aXZlX2N1ZV93ZWlnaHQgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLAogICAgICAgIHJlbGF0aXZlX2N1ZV93ZWlnaHRfY2hvaWNlX3NldF9hZGp1c3RlZCA9CiAgICAgICAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwCiAgICAgICkKICAgICksCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJzdHVkeTJfYW5hbHlzaXNfb2JqZWN0cy5yZHMiKQogICkKCiAgY2FwdHVyZS5vdXRwdXQoCiAgICBzZXNzaW9uSW5mbygpLAogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAic2Vzc2lvbkluZm8udHh0IikKICApCgogIGNhdCgiCkRvbmU6ICIsIG5vcm1hbGl6ZVBhdGgob3V0cHV0X2RpciksICIKIiwgc2VwID0gIiIpCgogIGVudmlyb25tZW50KCkKfSkKCgpgYGAKCiMjIEEuNCDlrp/pqJMz77ya5pys5paH44Gu5ZuzN+ODu+Wbszjjg7vlm7M5CgpgYGB7ciBhNC1zdHVkeTMtY29kZSwgZXZhbD1wYXJhbXMkcnVuX2FuYWx5c2lzLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQojIOacrOaWh+OCs+ODvOODiQpzdHVkeTNfZW52IDwtIGxvY2FsKHsKcmVxdWlyZWRfcGFja2FnZXMgPC0gYygKICAgICJkcGx5ciIsCiAgICAidGlkeXIiLAogICAgInN0cmluZ3IiLAogICAgInB1cnJyIiwKICAgICJyZWFkciIsCiAgICAiZml4ZXN0IiwKICAgICJ0aWJibGUiLAogICAgImZvcmNhdHMiLAogICAgImdncGxvdDIiLAogICAgInNjYWxlcyIsCiAgICAic3Vydml2YWwiLAogICAgInBhdGNod29yayIKICApCgogIG1pc3NpbmdfcGFja2FnZXMgPC0gcmVxdWlyZWRfcGFja2FnZXNbCiAgICAhdmFwcGx5KHJlcXVpcmVkX3BhY2thZ2VzLCByZXF1aXJlTmFtZXNwYWNlLCBsb2dpY2FsKDEpLCBxdWlldGx5ID0gVFJVRSkKICBdCgogIGlmIChsZW5ndGgobWlzc2luZ19wYWNrYWdlcykgPiAwKSB7CiAgICBzdG9wKCJObyBwYWNrYWdlcyIpCiAgfQoKICBsaWJyYXJ5KGRwbHlyKQogIGxpYnJhcnkodGlkeXIpCiAgbGlicmFyeShzdHJpbmdyKQogIGxpYnJhcnkocHVycnIpCiAgbGlicmFyeShyZWFkcikKICBsaWJyYXJ5KGZpeGVzdCkKICBsaWJyYXJ5KHRpYmJsZSkKICBsaWJyYXJ5KGZvcmNhdHMpCiAgbGlicmFyeShnZ3Bsb3QyKQogIGxpYnJhcnkoc2NhbGVzKQogIGxpYnJhcnkoc3Vydml2YWwpCiAgbGlicmFyeShwYXRjaHdvcmspCgogIGRhdGFfZmlsZSA8LSB1bmlmaWVkX2NvbmZpZyRzdHVkeTMkZGF0YV9maWxlCiAgb3V0cHV0X2RpciA8LSB1bmlmaWVkX2NvbmZpZyRzdHVkeTMkb3V0cHV0X2RpcgoKICBkaXIuY3JlYXRlKG91dHB1dF9kaXIsIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQoKICByZXF1aXJlX2luaXRpYWxfY29uc2VudCA8LSBUUlVFCiAgcmVxdWlyZV9maW5hbF9jb25zZW50IDwtIFRSVUUKICBmaW5hbF9jb25zZW50X3ZhciA8LSAiUTguMSIKCiAgcmVxdWlyZV9hdHRlbnRpb25fY2hlY2sgPC0gVFJVRQogIHJlcXVpcmVfbWFuaXB1bGF0aW9uX2NoZWNrIDwtIFRSVUUKCiAgcmVxdWlyZV9hbGxfZml2ZV90YXNrcyA8LSBUUlVFCgogIGF0dGVudGlvbl9jaGVja192YXIgPC0gIlEyNS4xXzExIgogIGF0dGVudGlvbl9jaGVja19jb3JyZWN0IDwtICIzIgoKICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgPC0gdW5pZmllZF9jb25maWckcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkIDwtIHVuaWZpZWRfY29uZmlnJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCArIDNMCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeSA8LSB1bmlmaWVkX2NvbmZpZyRyZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3Byb2dyZXNzX2V2ZXJ5CgogIHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAgPC0gdW5pZmllZF9jb25maWckcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcAoKICBmaWd1cmVfZm9udF9mYW1pbHkgPC0gaWYgKC5QbGF0Zm9ybSRPUy50eXBlID09ICJ3aW5kb3dzIikgewogICAgIll1IEdvdGhpYyIKICB9IGVsc2UgewogICAgIiIKICB9CgoKICBub3JtX3RleHQgPC0gZnVuY3Rpb24oeCkgewogICAgeCAlPiUKICAgICAgYXMuY2hhcmFjdGVyKCkgJT4lCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgiXHUzMDAwIiwgIiAiKSAlPiUKICAgICAgc3RyX3NxdWlzaCgpICU+JQogICAgICBzdHJfcmVwbGFjZV9hbGwoIu+9niIsICJ+IikgJT4lCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgi44CcIiwgIn4iKQogIH0KCiAgYXNfbnVtIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHN1cHByZXNzV2FybmluZ3MocmVhZHI6OnBhcnNlX251bWJlcihub3JtX3RleHQoeCkpKQogIH0KCiAgZmlyc3RfZXhpc3RpbmcgPC0gZnVuY3Rpb24oZGF0LCBjYW5kaWRhdGVzKSB7CiAgICBvdXQgPC0gY2FuZGlkYXRlc1tjYW5kaWRhdGVzICVpbiUgbmFtZXMoZGF0KV0KICAgIGlmIChsZW5ndGgob3V0KSA9PSAwKSB7CiAgICAgIE5BX2NoYXJhY3Rlcl8KICAgIH0gZWxzZSB7CiAgICAgIG91dFsxXQogICAgfQogIH0KCiAgZ2V0X3ZhciA8LSBmdW5jdGlvbihkYXQsIGNhbmRpZGF0ZXMpIHsKICAgIHYgPC0gZmlyc3RfZXhpc3RpbmcoZGF0LCBjYW5kaWRhdGVzKQoKICAgIGlmIChpcy5uYSh2KSkgewogICAgICByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhkYXQpKQogICAgfSBlbHNlIHsKICAgICAgZGF0W1t2XV0KICAgIH0KICB9CgogIGlzX3Jlc3BvbnNlX2NvZGUgPC0gZnVuY3Rpb24oeCwgY29kZSkgewogICAgeF9ub3JtIDwtIG5vcm1fdGV4dCh4KQogICAgY29kZV9jaHIgPC0gYXMuY2hhcmFjdGVyKGNvZGUpCgogICAgeF9ub3JtID09IGNvZGVfY2hyIHwKICAgICAgc3RyX2RldGVjdCh4X25vcm0sIHBhc3RlMCgiXFwoIiwgY29kZV9jaHIsICJcXCkkIikpCiAgfQoKICByZWxldmVsX2lmX3ByZXNlbnQgPC0gZnVuY3Rpb24oeCwgcmVmKSB7CiAgICB4IDwtIGZhY3Rvcih4KQoKICAgIGlmIChyZWYgJWluJSBsZXZlbHMoeCkpIHsKICAgICAgcmVsZXZlbCh4LCByZWYgPSByZWYpCiAgICB9IGVsc2UgewogICAgICB4CiAgICB9CiAgfQoKICBmYWN0b3JfbWlzcyA8LSBmdW5jdGlvbih4LCBtaXNzID0gIuasoOaQjeODu+eEoeWbnuetlCIpIHsKICAgIHggPC0gbm9ybV90ZXh0KHgpCiAgICB4W2lzLm5hKHgpIHwgeCA9PSAiIiB8IHggPT0gIk5BIl0gPC0gbWlzcwogICAgZmFjdG9yKHgpCiAgfQoKICBtZWFuX2ltcHV0ZSA8LSBmdW5jdGlvbih4KSB7CiAgICB4IDwtIGFzLm51bWVyaWMoeCkKICAgIG1pc3MgPC0gYXMuaW50ZWdlcihpcy5uYSh4KSkKCiAgICBpZiAoYWxsKGlzLm5hKHgpKSkgewogICAgICB2YWx1ZSA8LSB4CiAgICB9IGVsc2UgewogICAgICB2YWx1ZSA8LSBpZmVsc2UoCiAgICAgICAgaXMubmEoeCksCiAgICAgICAgbWVhbih4LCBuYS5ybSA9IFRSVUUpLAogICAgICAgIHgKICAgICAgKQogICAgfQoKICAgIGxpc3QoCiAgICAgIHZhbHVlID0gdmFsdWUsCiAgICAgIG1pc3MgPSBtaXNzCiAgICApCiAgfQoKICB3cml0ZV9jc3Zfc2FmZWx5IDwtIGZ1bmN0aW9uKHgsIGZpbGVuYW1lKSB7CiAgICByZWFkcjo6d3JpdGVfY3N2KAogICAgICB4LAogICAgICBmaWxlLnBhdGgob3V0cHV0X2RpciwgZmlsZW5hbWUpLAogICAgICBuYSA9ICIiCiAgICApCiAgfQoKICBzYXZlX3Bsb3QgPC0gZnVuY3Rpb24oCiAgICBmaWxlbmFtZSwKICAgIHBsb3QsCiAgICB3aWR0aCwKICAgIGhlaWdodCwKICAgIGRwaSA9IDMwMAogICkgewogICAgZ2dwbG90Mjo6Z2dzYXZlKAogICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCBmaWxlbmFtZSksCiAgICAgIHBsb3QgPSBwbG90LAogICAgICB3aWR0aCA9IHdpZHRoLAogICAgICBoZWlnaHQgPSBoZWlnaHQsCiAgICAgIGRwaSA9IGRwaQogICAgKQogIH0KCiAgY2Fub25pY2FsaXplX3BhcnR5X25hbWUgPC0gZnVuY3Rpb24oeCkgewogICAgeF9ub3JtIDwtIG5vcm1fdGV4dCh4KQogICAgeF9jb21wYWN0IDwtIHN0cl9yZXBsYWNlX2FsbCh4X25vcm0sICJcXHMrIiwgIiIpCgogICAgY2FzZV93aGVuKAogICAgICBpcy5uYSh4X2NvbXBhY3QpIHwgeF9jb21wYWN0ID09ICIiIH4gTkFfY2hhcmFjdGVyXywKCiAgICAgIHhfY29tcGFjdCAlaW4lIGMoCiAgICAgICAgIuiHqueUseawkeS4u+WFmiIsCiAgICAgICAgIuiHquawkeWFmiIsCiAgICAgICAgIuiHquawkSIKICAgICAgKSB+ICLoh6rnlLHmsJHkuLvlhZoiLAoKICAgICAgeF9jb21wYWN0ICVpbiUgYygKICAgICAgICAi56uL5oay5rCR5Li75YWaIiwKICAgICAgICAi56uL5rCRIgogICAgICApIH4gIueri+aGsuawkeS4u+WFmiIsCgogICAgICB4X2NvbXBhY3QgJWluJSBjKAogICAgICAgICLml6XmnKzntq3mlrDjga7kvJoiLAogICAgICAgICLntq3mlrAiCiAgICAgICkgfiAi5pel5pys57at5paw44Gu5LyaIiwKCiAgICAgIHhfY29tcGFjdCA9PSAi5YWs5piO5YWaIiB+ICLlhazmmI7lhZoiLAoKICAgICAgeF9jb21wYWN0ICVpbiUgYygKICAgICAgICAi5Zu95rCR5rCR5Li75YWaIiwKICAgICAgICAi5Zu95rCRIgogICAgICApIH4gIuWbveawkeawkeS4u+WFmiIsCgogICAgICB4X2NvbXBhY3QgJWluJSBjKAogICAgICAgICLjgozjgYTjgo/mlrDpgbjntYQiLAogICAgICAgICLjgozjgYTjgo8iCiAgICAgICkgfiAi44KM44GE44KP5paw6YG457WEIiwKCiAgICAgIHhfY29tcGFjdCA9PSAi5Y+C5pS/5YWaIiB+ICLlj4LmlL/lhZoiLAoKICAgICAgeF9jb21wYWN0ICVpbiUgYygKICAgICAgICAi5pel5pys5YWx55Sj5YWaIiwKICAgICAgICAi5YWx55Sj5YWaIgogICAgICApIH4gIuaXpeacrOWFseeUo+WFmiIsCgogICAgICB4X2NvbXBhY3QgPT0gIuS4remBk+aUuemdqemAo+WQiCIgfiAi5Lit6YGT5pS56Z2p6YCj5ZCIIiwKCiAgICAgIHhfY29tcGFjdCA9PSAi5pel5pys5L+d5a6I5YWaIiB+ICLml6XmnKzkv53lrojlhZoiLAoKICAgICAgeF9jb21wYWN0ICVpbiUgYygKICAgICAgICAi56S+5Lya5rCR5Li75YWaIiwKICAgICAgICAi56S+5rCR5YWaIgogICAgICApIH4gIuekvuS8muawkeS4u+WFmiIsCgogICAgICB4X2NvbXBhY3QgPT0gIuODgeODvOODoOOBv+OCieOBhCIgfiAi44OB44O844Og44G/44KJ44GEIiwKCiAgICAgIFRSVUUgfiB4X25vcm0KICAgICkKICB9CgogIGNhbm9uaWNhbGl6ZV9lY29ub21pY19sZXZlbCA8LSBmdW5jdGlvbih4KSB7CiAgICB4X25vcm0gPC0gbm9ybV90ZXh0KHgpICU+JQogICAgICBzdHJfcmVwbGFjZV9hbGwoIu+8iyIsICIrIikgJT4lCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgi4oiSfO+8jXzigJUiLCAiLSIpICU+JQogICAgICBzdHJfcmVwbGFjZV9hbGwoIiUiLCAi77yFIikKCiAgICBjYXNlX3doZW4oCiAgICAgIGlzLm5hKHhfbm9ybSkgfCB4X25vcm0gPT0gIiIgfiBOQV9jaGFyYWN0ZXJfLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJHRFAiKSAmCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg5fjg6njgrl8XFwrXFxzKjEiKSB+CiAgICAgICAgIkdEUOaIkOmVt+eOh+ODl+ODqeOCuTHvvIUiLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJHRFAiKSAmCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg57jgqTjg4rjgrl8LVxccyoxIikgfgogICAgICAgICJHRFDmiJDplbfnjofjg57jgqTjg4rjgrkx77yFIiwKCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiR0RQIikgJgogICAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiwrFcXHMqMHwwXFxzKu+8hXzlpInjgo/jgonjgZp85aSJ5YyW44Gq44GXIikgfgogICAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLml6XntYzlubPlnYciKSAmCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg5fjg6njgrl8XFwrXFxzKjEwMDAiKSB+CiAgICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLml6XntYzlubPlnYciKSAmCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg57jgqTjg4rjgrl8LVxccyoxMDAwIikgfgogICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIiwKCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi5pel57WM5bmz5Z2HIikgJgogICAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi5aSJ44KP44KJ44GafOWkieWMluOBquOBl3zCsVxccyowfDBcXHMq5YaGIikgfgogICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5TlpInjgo/jgonjgZoiLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJDUEl854mp5L6hIikgJgogICAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi44OX44Op44K5fFxcK1xccyoxIikgfgogICAgICAgICJDUEnliY3mnJ/mr5Tjg5fjg6njgrkx44Od44Kk44Oz44OIIiwKCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiQ1BJfOeJqeS+oSIpICYKICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuODnuOCpOODiuOCuXwtXFxzKjEiKSB+CiAgICAgICAgIkNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJDUEl854mp5L6hIikgJgogICAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiwrFcXHMqMHwwXFxzKuODneOCpOODs+ODiHzlpInjgo/jgonjgZp85aSJ5YyW44Gq44GXIikgfgogICAgICAgICJDUEnliY3mnJ/mr5TCsTDjg53jgqTjg7Pjg4giLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLlpLHmpa3njod86ZuH55SoIikgJgogICAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi44OX44Op44K5fFxcK1xccyoxIikgfgogICAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwKCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi5aSx5qWt546HfOmbh+eUqCIpICYKICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuODnuOCpOODiuOCuXwtXFxzKjEiKSB+CiAgICAgICAgIuWksealreeOh+WJjeacn+avlOODnuOCpOODiuOCuTHvvIUiLAoKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLlpLHmpa3njod86ZuH55SoIikgJgogICAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiwrFcXHMqMHwwXFxzKu+8hXzlpInjgo/jgonjgZp85aSJ5YyW44Gq44GXIikgfgogICAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiLAoKICAgICAgVFJVRSB+IHhfbm9ybQogICAgKQogIH0KCiAgbGV2ZWxfdG9fYXR0cl92YXIgPC0gZnVuY3Rpb24oeCkgewogICAgeF9ub3JtIDwtIGNhbm9uaWNhbGl6ZV9lY29ub21pY19sZXZlbCh4KQoKICAgIGNhc2Vfd2hlbigKICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJeR0RQ5oiQ6ZW3546HIikgfiAiZ2RwX2dyb3d0aCIsCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiXuaXpee1jOW5s+WdhyIpIH4gIm5pa2tlaSIsCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiXkNQSSIpIH4gImNwaSIsCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiXuWksealreeOhyIpIH4gInVuZW1wbG95bWVudCIsCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfCiAgICApCiAgfQoKICB0aWR5X2ZpeGVzdCA8LSBmdW5jdGlvbihtb2RlbCkgewogICAgY3QgPC0gYXMuZGF0YS5mcmFtZShmaXhlc3Q6OmNvZWZ0YWJsZShtb2RlbCkpCiAgICBjdCR0ZXJtIDwtIHJvd25hbWVzKGN0KQoKICAgIGVzdGltYXRlX2NvbCA8LSBpbnRlcnNlY3QoCiAgICAgIGMoIkVzdGltYXRlIiwgImVzdGltYXRlIiksCiAgICAgIG5hbWVzKGN0KQogICAgKVsxXQoKICAgIHNlX2NvbCA8LSBpbnRlcnNlY3QoCiAgICAgIGMoIlN0ZC4gRXJyb3IiLCAiU3RkLiBlcnJvciIsICJzdGQuZXJyb3IiKSwKICAgICAgbmFtZXMoY3QpCiAgICApWzFdCgogICAgc3RhdGlzdGljX2NvbCA8LSBpbnRlcnNlY3QoCiAgICAgIGMoInQgdmFsdWUiLCAieiB2YWx1ZSIsICJzdGF0aXN0aWMiKSwKICAgICAgbmFtZXMoY3QpCiAgICApWzFdCgogICAgcF9jb2wgPC0gaW50ZXJzZWN0KAogICAgICBjKCJQcig+fHR8KSIsICJQcig+fHp8KSIsICJwLnZhbHVlIiksCiAgICAgIG5hbWVzKGN0KQogICAgKVsxXQoKICAgIGlmICgKICAgICAgaXMubmEoZXN0aW1hdGVfY29sKSB8CiAgICAgICAgaXMubmEoc2VfY29sKSB8CiAgICAgICAgaXMubmEoc3RhdGlzdGljX2NvbCkgfAogICAgICAgIGlzLm5hKHBfY29sKQogICAgKSB7CiAgICAgIHN0b3AoIkNoZWNrIGRhdGEiKQogICAgfQoKICAgIGN0ICU+JQogICAgICBhc190aWJibGUoKSAlPiUKICAgICAgdHJhbnNtdXRlKAogICAgICAgIHRlcm0gPSB0ZXJtLAogICAgICAgIGVzdGltYXRlID0gLmRhdGFbW2VzdGltYXRlX2NvbF1dLAogICAgICAgIHN0ZC5lcnJvciA9IC5kYXRhW1tzZV9jb2xdXSwKICAgICAgICBzdGF0aXN0aWMgPSAuZGF0YVtbc3RhdGlzdGljX2NvbF1dLAogICAgICAgIHAudmFsdWUgPSAuZGF0YVtbcF9jb2xdXSwKICAgICAgICBjb25mLmxvdyA9IGVzdGltYXRlIC0gMS45NiAqIHN0ZC5lcnJvciwKICAgICAgICBjb25mLmhpZ2ggPSBlc3RpbWF0ZSArIDEuOTYgKiBzdGQuZXJyb3IKICAgICAgKQogIH0KCgogIGlmICghZmlsZS5leGlzdHMoZGF0YV9maWxlKSkgewogICAgc3RvcCgiQ2hlY2sgZGF0YSIpCiAgfQoKICByYXcgPC0gcmVhZHI6OnJlYWRfY3N2KAogICAgZGF0YV9maWxlLAogICAgY29sX3R5cGVzID0gY29scyguZGVmYXVsdCA9IGNvbF9jaGFyYWN0ZXIoKSksCiAgICBzaG93X2NvbF90eXBlcyA9IEZBTFNFLAogICAgbmFtZV9yZXBhaXIgPSAibWluaW1hbCIKICApCgoKICBpZiAocmVxdWlyZV9maW5hbF9jb25zZW50KSB7CiAgICBmaW5hbF9jb25zZW50X3ZhciA8LSBkZXRlY3RfZmluYWxfY29uc2VudF9jb2x1bW4oCiAgICAgIHJhdyA9IHJhdywKICAgICAgcHJlZmVycmVkX2NhbmRpZGF0ZXMgPSBjKCJROC4xIiwgIlE5LjEiLCAiUTEwLjEiKSwKICAgICAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkgMyIKICAgICkKICB9CgogIGlmIChyZXF1aXJlX2F0dGVudGlvbl9jaGVjaykgewogICAgYXR0ZW50aW9uX2NoZWNrX3ZhciA8LSBkZXRlY3RfYXR0ZW50aW9uX2NoZWNrX2NvbHVtbigKICAgICAgcmF3ID0gcmF3LAogICAgICBwcmVmZXJyZWRfY2FuZGlkYXRlcyA9IGMoIlEyNS4xXzExIiwgIlEyNS4xXzEwIiksCiAgICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDMiCiAgICApCiAgfQoKICBpZiAoISJSZXNwb25zZUlkIiAlaW4lIG5hbWVzKHJhdykpIHsKICAgIHN0b3AoIkNoZWNrIGRhdGEiKQogIH0KCiAgZGZfaGVhZGVyX3JlbW92ZWQgPC0gcmF3ICU+JQogICAgZmlsdGVyKAogICAgICAhaXMubmEoUmVzcG9uc2VJZCksCiAgICAgIFJlc3BvbnNlSWQgIT0gIiIsCiAgICAgICFzdHJfZGV0ZWN0KAogICAgICAgIG5vcm1fdGV4dChSZXNwb25zZUlkKSwKICAgICAgICAiXihSZXNwb25zZSBJRHzlm57nrZRJRCkkfEltcG9ydElkIgogICAgICApCiAgICApICU+JQogICAgbXV0YXRlKElEID0gYXMuY2hhcmFjdGVyKFJlc3BvbnNlSWQpKQoKICBkdXBsaWNhdGVfaWRzIDwtIGRmX2hlYWRlcl9yZW1vdmVkICU+JQogICAgY291bnQoSUQpICU+JQogICAgZmlsdGVyKG4gPiAxKQoKICBpZiAobnJvdyhkdXBsaWNhdGVfaWRzKSA+IDApIHsKICAgIHByaW50KGR1cGxpY2F0ZV9pZHMpCiAgICBzdG9wKCJDaGVjayIpCiAgfQoKICBzYW1wbGVfZmxvdyA8LSB0aWJibGUoCiAgICBzdGFnZSA9ICJRdWFsdHJpY3Pos6rllY/mlofooYzjg7tJbXBvcnRJZOihjOOCkumZpOWkluW+jCIsCiAgICBuID0gbnJvdyhkZl9oZWFkZXJfcmVtb3ZlZCkKICApCgogIGRmIDwtIGRmX2hlYWRlcl9yZW1vdmVkCgogIGlmIChyZXF1aXJlX2luaXRpYWxfY29uc2VudCkgewogICAgaWYgKCEiUTEuMSIgJWluJSBuYW1lcyhkZikpIHsKICAgICAgc3RvcCgiQ2hlY2sgaW5pdGlhbCBjb25zZW50IikKICAgIH0KCiAgICBkZiA8LSBkZiAlPiUKICAgICAgZmlsdGVyKAogICAgICAgIGlzX3Jlc3BvbnNlX2NvZGUoUTEuMSwgMSkgfAogICAgICAgICAgc3RyX2RldGVjdCgKICAgICAgICAgICAgbm9ybV90ZXh0KFExLjEpLAogICAgICAgICAgICAi6Laj5peo44Gr5ZCM5oSP44GX44GmLirljZTlipvjgZnjgosiCiAgICAgICAgICApCiAgICAgICkKCiAgICBzYW1wbGVfZmxvdyA8LSBiaW5kX3Jvd3MoCiAgICAgIHNhbXBsZV9mbG93LAogICAgICB0aWJibGUoCiAgICAgICAgc3RhZ2UgPSAi5Yid5Zue5ZCM5oSPIFExLjEgPSAxIiwKICAgICAgICBuID0gbnJvdyhkZikKICAgICAgKQogICAgKQogIH0KCiAgaWYgKHJlcXVpcmVfZmluYWxfY29uc2VudCkgewogICAgaWYgKGlzLm5hKGZpbmFsX2NvbnNlbnRfdmFyKSB8fCAhZmluYWxfY29uc2VudF92YXIgJWluJSBuYW1lcyhkZikpIHsKICAgICAgc3RvcCgiQ2hlY2sgZmluYWwgY29uc2VudCIpCiAgICB9CgogICAgZGYgPC0gZGYgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICBpc19yZXNwb25zZV9jb2RlKC5kYXRhW1tmaW5hbF9jb25zZW50X3Zhcl1dLCAxKSB8CiAgICAgICAgICBzdHJfZGV0ZWN0KAogICAgICAgICAgICBub3JtX3RleHQoLmRhdGFbW2ZpbmFsX2NvbnNlbnRfdmFyXV0pLAogICAgICAgICAgICAi5ZCM5oSP44GXLirlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgosiCiAgICAgICAgICApCiAgICAgICkKCiAgICBzYW1wbGVfZmxvdyA8LSBiaW5kX3Jvd3MoCiAgICAgIHNhbXBsZV9mbG93LAogICAgICB0aWJibGUoCiAgICAgICAgc3RhZ2UgPSBwYXN0ZTAoIuacgOe1guWQjOaEjyAiLCBmaW5hbF9jb25zZW50X3ZhciwgIiA9IDEiKSwKICAgICAgICBuID0gbnJvdyhkZikKICAgICAgKQogICAgKQogIH0KCiAgaWYgKHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrKSB7CiAgICBpZiAoIWF0dGVudGlvbl9jaGVja192YXIgJWluJSBuYW1lcyhkZikpIHsKICAgICAgc3RvcCgiQ2hlY2sgYXR0ZW50aW9uIGl0ZW0iKQogICAgfQoKICAgIGF0dGVudGlvbl9jaGVja19jb3JyZWN0IDwtIGRldGVjdF9hdHRlbnRpb25fY29ycmVjdF9jb2RlKAogICAgICBkZltbYXR0ZW50aW9uX2NoZWNrX3Zhcl1dLAogICAgICBkaXNwbGF5ZWRfYW5zd2VyID0gM0wsCiAgICAgIHJlY29kZWRfYW5zd2VyID0gNkwsCiAgICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDMiCiAgICApCgogICAgZGYgPC0gZGYgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICBpc19yZXNwb25zZV9jb2RlKAogICAgICAgICAgLmRhdGFbW2F0dGVudGlvbl9jaGVja192YXJdXSwKICAgICAgICAgIGF0dGVudGlvbl9jaGVja19jb3JyZWN0CiAgICAgICAgKQogICAgICApCgogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKAogICAgICBzYW1wbGVfZmxvdywKICAgICAgdGliYmxlKAogICAgICAgIHN0YWdlID0gcGFzdGUwKAogICAgICAgICAgIuaMh+ekuumgheebruato+etlO+8iCIsCiAgICAgICAgICBhdHRlbnRpb25fY2hlY2tfdmFyLAogICAgICAgICAgIuOAgeS/neWtmOOCs+ODvOODiT0iLAogICAgICAgICAgYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QsCiAgICAgICAgICAi77yJIgogICAgICAgICksCiAgICAgICAgbiA9IG5yb3coZGYpCiAgICAgICkKICAgICkKICB9CgogIHByaW50KHNhbXBsZV9mbG93KQogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICBzYW1wbGVfZmxvdywKICAgICJzYW1wbGVfZmxvd19iZWZvcmVfY29uam9pbnQuY3N2IgogICkKCgogIGNob2ljZV9tYXAgPC0gZGV0ZWN0X2NvbmpvaW50X2Nob2ljZV9tYXAoCiAgICByYXcgPSByYXcsCiAgICBwYXJ0eV9udW1iZXJzID0gMjo1LAogICAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkgMyIKICApCgogIG1hbmlwdWxhdGlvbl9tYXAgPC0gZGV0ZWN0X21hbmlwdWxhdGlvbl9tYXAoCiAgICByYXcgPSByYXcsCiAgICBjaG9pY2VfbWFwID0gY2hvaWNlX21hcCwKICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDMiCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KGNob2ljZV9tYXAsICJkZXRlY3RlZF9jaG9pY2VfcXVlc3Rpb25fbWFwLmNzdiIpCiAgd3JpdGVfY3N2X3NhZmVseShtYW5pcHVsYXRpb25fbWFwLCAiZGV0ZWN0ZWRfbWFuaXB1bGF0aW9uX3F1ZXN0aW9uX21hcC5jc3YiKQoKCiAgcmVxdWlyZWRfYXR0cl92YXJzIDwtIGMoCiAgICAicGFydHlfbmFtZSIsCiAgICAiZ2RwX2dyb3d0aCIsCiAgICAibmlra2VpIiwKICAgICJjcGkiLAogICAgInVuZW1wbG95bWVudCIKICApCgogIGV4cGVjdGVkX3BhcnR5X2xldmVscyA8LSBjKAogICAgIuiHqueUseawkeS4u+WFmiIsCiAgICAi56uL5oay5rCR5Li75YWaIiwKICAgICLml6XmnKzntq3mlrDjga7kvJoiLAogICAgIuWFrOaYjuWFmiIsCiAgICAi5Zu95rCR5rCR5Li75YWaIiwKICAgICLjgozjgYTjgo/mlrDpgbjntYQiLAogICAgIuWPguaUv+WFmiIsCiAgICAi5pel5pys5YWx55Sj5YWaIiwKICAgICLkuK3pgZPmlLnpnanpgKPlkIgiCiAgKQoKICBhbGxvd2VkX2Vjb25vbWljX2xldmVscyA8LSBsaXN0KAogICAgZ2RwX2dyb3d0aCA9IGMoCiAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiLAogICAgICAiR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAgICJHRFDmiJDplbfnjofjg57jgqTjg4rjgrkx77yFIgogICAgKSwKCiAgICBuaWtrZWkgPSBjKAogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIiwKICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLAogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U44Oe44Kk44OK44K5MTAwMOWGhiIKICAgICksCgogICAgY3BpID0gYygKICAgICAgIkNQSeWJjeacn+avlMKxMOODneOCpOODs+ODiCIsCiAgICAgICJDUEnliY3mnJ/mr5Tjg5fjg6njgrkx44Od44Kk44Oz44OIIiwKICAgICAgIkNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giCiAgICApLAoKICAgIHVuZW1wbG95bWVudCA9IGMoCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiLAogICAgICAi5aSx5qWt546H5YmN5pyf5q+U44OX44Op44K5Me+8hSIsCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg57jgqTjg4rjgrkx77yFIgogICAgKQogICkKCgogIG1ha2VfcHJvZmlsZV9sb25nIDwtIGZ1bmN0aW9uKGRhdCwgbl9wYXJ0eSkgewoKICAgIG1hcF9uIDwtIGNob2ljZV9tYXAgJT4lCiAgICAgIGZpbHRlcihwYXJ0eV9uID09IG5fcGFydHkpCgogICAgcXZhcnMgPC0gbWFwX24kY2hvaWNlX3ZhcgoKICAgIG1pc3NpbmdfcSA8LSBzZXRkaWZmKHF2YXJzLCBuYW1lcyhkYXQpKQoKICAgIGlmIChsZW5ndGgobWlzc2luZ19xKSA+IDApIHsKICAgICAgc3RvcCgiQ2hlY2sgY2hvaWNlIGNvbHVtbnMiKQogICAgfQoKICAgIGRhdF9uIDwtIGRhdCAlPiUKICAgICAgZmlsdGVyKAogICAgICAgIGlmX2FueSgKICAgICAgICAgIGFsbF9vZihxdmFycyksCiAgICAgICAgICB+ICFpcy5uYSgueCkgJiBub3JtX3RleHQoLngpICE9ICIiCiAgICAgICAgKQogICAgICApCgogICAgaWYgKHJlcXVpcmVfbWFuaXB1bGF0aW9uX2NoZWNrKSB7CiAgICAgIG1hbmlwdWxhdGlvbl9yb3cgPC0gbWFuaXB1bGF0aW9uX21hcCAlPiUKICAgICAgICBmaWx0ZXIocGFydHlfbiA9PSBuX3BhcnR5KQoKICAgICAgbWFuaXB1bGF0aW9uX3ZhciA8LSBtYW5pcHVsYXRpb25fcm93JG1hbmlwdWxhdGlvbl92YXIKICAgICAgY29ycmVjdF9hbnN3ZXIgPC0gbWFuaXB1bGF0aW9uX3JvdyRjb3JyZWN0X2Fuc3dlcgoKICAgICAgaWYgKCFtYW5pcHVsYXRpb25fdmFyICVpbiUgbmFtZXMoZGF0X24pKSB7CiAgICAgICAgc3RvcCgiQ2hlY2sgbWFuaXB1bGF0aW9uIGl0ZW0iKQogICAgICB9CgogICAgICBkYXRfbiA8LSBkYXRfbiAlPiUKICAgICAgICBmaWx0ZXIoCiAgICAgICAgICBpc19yZXNwb25zZV9jb2RlKAogICAgICAgICAgICAuZGF0YVtbbWFuaXB1bGF0aW9uX3Zhcl1dLAogICAgICAgICAgICBjb3JyZWN0X2Fuc3dlcgogICAgICAgICAgKQogICAgICAgICkKICAgIH0KCgogICAgY2hvaWNlX2xvbmcgPC0gZGF0X24gJT4lCiAgICAgIHNlbGVjdCgKICAgICAgICBJRCwKICAgICAgICBhbGxfb2YocXZhcnMpCiAgICAgICkgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gYWxsX29mKHF2YXJzKSwKICAgICAgICBuYW1lc190byA9ICJjaG9pY2VfdmFyIiwKICAgICAgICB2YWx1ZXNfdG8gPSAiY2hvaWNlX3JhdyIKICAgICAgKSAlPiUKICAgICAgbGVmdF9qb2luKAogICAgICAgIG1hcF9uLAogICAgICAgIGJ5ID0gImNob2ljZV92YXIiCiAgICAgICkgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBjaG9pY2UgPSBwYXJzZV9jaG9pY2VfcG9zaXRpb24oY2hvaWNlX3JhdykKICAgICAgKSAlPiUKICAgICAgZmlsdGVyKCFpcy5uYShjaG9pY2UpKSAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIElELAogICAgICAgIHBhcnR5X24sCiAgICAgICAgdGFzaywKICAgICAgICBjaG9pY2UKICAgICAgKQoKICAgIGludmFsaWRfY2hvaWNlIDwtIGNob2ljZV9sb25nICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgY2hvaWNlIDwgMSB8CiAgICAgICAgICBjaG9pY2UgPiBuX3BhcnR5CiAgICAgICkKCiAgICBpZiAobnJvdyhpbnZhbGlkX2Nob2ljZSkgPiAwKSB7CiAgICAgIHByaW50KGludmFsaWRfY2hvaWNlKQogICAgICBzdG9wKCJDaGVjayBjaG9pY2UgdmFsdWVzIikKICAgIH0KCiAgICBkdXBsaWNhdGVfY2hvaWNlIDwtIGNob2ljZV9sb25nICU+JQogICAgICBjb3VudCgKICAgICAgICBJRCwKICAgICAgICB0YXNrCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcihuICE9IDEpCgogICAgaWYgKG5yb3coZHVwbGljYXRlX2Nob2ljZSkgPiAwKSB7CiAgICAgIHByaW50KGR1cGxpY2F0ZV9jaG9pY2UpCiAgICAgIHN0b3AoIkNoZWNrIGR1cGxpY2F0ZSBjaG9pY2VzIikKICAgIH0KCgogICAgcGFydHlfcmVnZXggPC0gcGFzdGUwKAogICAgICAiXlMzX1AiLAogICAgICBuX3BhcnR5LAogICAgICAiX1BBUlRZXyhbMS01XSlfKFsxLSIsCiAgICAgIG5fcGFydHksCiAgICAgICJdKSQiCiAgICApCgogICAgcGFydHlfY29scyA8LSBuYW1lcyhkYXRfbilbCiAgICAgIHN0cl9kZXRlY3QoCiAgICAgICAgbmFtZXMoZGF0X24pLAogICAgICAgIHBhcnR5X3JlZ2V4CiAgICAgICkKICAgIF0KCiAgICBleHBlY3RlZF9wYXJ0eV9jb2xzX24gPC0gNSAqIG5fcGFydHkKCiAgICBpZiAobGVuZ3RoKHBhcnR5X2NvbHMpICE9IGV4cGVjdGVkX3BhcnR5X2NvbHNfbikgewogICAgICBzdG9wKCJDaGVjayIpCiAgICB9CgogICAgcGFydHlfbG9uZyA8LSBkYXRfbiAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIElELAogICAgICAgIGFsbF9vZihwYXJ0eV9jb2xzKQogICAgICApICU+JQogICAgICBwaXZvdF9sb25nZXIoCiAgICAgICAgY29scyA9IGFsbF9vZihwYXJ0eV9jb2xzKSwKICAgICAgICBuYW1lc190byA9ICJwYXJ0eV92YXIiLAogICAgICAgIHZhbHVlc190byA9ICJwYXJ0eV9uYW1lX3JhdyIKICAgICAgKSAlPiUKICAgICAgZXh0cmFjdCgKICAgICAgICBwYXJ0eV92YXIsCiAgICAgICAgaW50byA9IGMoCiAgICAgICAgICAidGFzayIsCiAgICAgICAgICAicHJvZmlsZSIKICAgICAgICApLAogICAgICAgIHJlZ2V4ID0gcGFydHlfcmVnZXgsCiAgICAgICAgY29udmVydCA9IFRSVUUKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIHBhcnR5X25hbWUgPSBjYW5vbmljYWxpemVfcGFydHlfbmFtZSgKICAgICAgICAgIHBhcnR5X25hbWVfcmF3CiAgICAgICAgKQogICAgICApICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgdGFzayAlaW4lIDE6NSwKICAgICAgICBwcm9maWxlICVpbiUgMTpuX3BhcnR5LAogICAgICAgICFpcy5uYShwYXJ0eV9uYW1lKSwKICAgICAgICBwYXJ0eV9uYW1lICE9ICIiCiAgICAgICkgJT4lCiAgICAgIHNlbGVjdCgKICAgICAgICBJRCwKICAgICAgICB0YXNrLAogICAgICAgIHByb2ZpbGUsCiAgICAgICAgcGFydHlfbmFtZQogICAgICApCgogICAgZHVwbGljYXRlX3BhcnR5X25hbWUgPC0gcGFydHlfbG9uZyAlPiUKICAgICAgY291bnQoCiAgICAgICAgSUQsCiAgICAgICAgdGFzaywKICAgICAgICBwcm9maWxlCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcihuICE9IDEpCgogICAgaWYgKG5yb3coZHVwbGljYXRlX3BhcnR5X25hbWUpID4gMCkgewogICAgICBwcmludCgKICAgICAgICBoZWFkKAogICAgICAgICAgZHVwbGljYXRlX3BhcnR5X25hbWUsCiAgICAgICAgICA1MAogICAgICAgICkKICAgICAgKQogICAgICBzdG9wKCJDaGVjayIpCiAgICB9CgoKICAgIGxldmVsX3JlZ2V4IDwtIHBhc3RlMCgKICAgICAgIl5TM19QIiwKICAgICAgbl9wYXJ0eSwKICAgICAgIl9GXyhbMS01XSlfKFsxLSIsCiAgICAgIG5fcGFydHksCiAgICAgICJdKV8oWzEtNF0pJCIKICAgICkKCiAgICBsZXZlbF9jb2xzIDwtIG5hbWVzKGRhdF9uKVsKICAgICAgc3RyX2RldGVjdCgKICAgICAgICBuYW1lcyhkYXRfbiksCiAgICAgICAgbGV2ZWxfcmVnZXgKICAgICAgKQogICAgXQoKICAgIGV4cGVjdGVkX2xldmVsX2NvbHNfbiA8LSA1ICogbl9wYXJ0eSAqIDQKCiAgICBpZiAobGVuZ3RoKGxldmVsX2NvbHMpICE9IGV4cGVjdGVkX2xldmVsX2NvbHNfbikgewogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgIH0KCiAgICBsZXZlbF9sb25nIDwtIGRhdF9uICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgSUQsCiAgICAgICAgYWxsX29mKGxldmVsX2NvbHMpCiAgICAgICkgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gYWxsX29mKGxldmVsX2NvbHMpLAogICAgICAgIG5hbWVzX3RvID0gImZ2YXIiLAogICAgICAgIHZhbHVlc190byA9ICJsZXZlbF9yYXciCiAgICAgICkgJT4lCiAgICAgIGV4dHJhY3QoCiAgICAgICAgZnZhciwKICAgICAgICBpbnRvID0gYygKICAgICAgICAgICJ0YXNrIiwKICAgICAgICAgICJwcm9maWxlIiwKICAgICAgICAgICJhdHRyX29yZGVyIgogICAgICAgICksCiAgICAgICAgcmVnZXggPSBsZXZlbF9yZWdleCwKICAgICAgICBjb252ZXJ0ID0gVFJVRQogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgbGV2ZWwgPSBjYW5vbmljYWxpemVfZWNvbm9taWNfbGV2ZWwoCiAgICAgICAgICBsZXZlbF9yYXcKICAgICAgICApLAogICAgICAgIGF0dHJfdmFyID0gbGV2ZWxfdG9fYXR0cl92YXIoCiAgICAgICAgICBsZXZlbAogICAgICAgICkKICAgICAgKSAlPiUKICAgICAgZmlsdGVyKAogICAgICAgIHRhc2sgJWluJSAxOjUsCiAgICAgICAgcHJvZmlsZSAlaW4lIDE6bl9wYXJ0eSwKICAgICAgICBhdHRyX29yZGVyICVpbiUgMTo0LAogICAgICAgICFpcy5uYShsZXZlbCksCiAgICAgICAgbGV2ZWwgIT0gIiIKICAgICAgKQoKICAgIHVua25vd25fbGV2ZWxzIDwtIGxldmVsX2xvbmcgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICBpcy5uYShhdHRyX3ZhcikKICAgICAgKSAlPiUKICAgICAgZGlzdGluY3QoCiAgICAgICAgbGV2ZWxfcmF3LAogICAgICAgIGxldmVsCiAgICAgICkKCiAgICBpZiAobnJvdyh1bmtub3duX2xldmVscykgPiAwKSB7CiAgICAgIHByaW50KHVua25vd25fbGV2ZWxzKQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikKICAgIH0KCiAgICBwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCA8LSBsZXZlbF9sb25nICU+JQogICAgICBjb3VudCgKICAgICAgICBJRCwKICAgICAgICB0YXNrLAogICAgICAgIHByb2ZpbGUsCiAgICAgICAgbmFtZSA9ICJuX2F0dHJpYnV0ZV9yb3dzIgogICAgICApICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgbl9hdHRyaWJ1dGVfcm93cyAhPSA0CiAgICAgICkKCiAgICBpZiAobnJvdyhwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCkgPiAwKSB7CiAgICAgIHByaW50KAogICAgICAgIGhlYWQoCiAgICAgICAgICBwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCwKICAgICAgICAgIDUwCiAgICAgICAgKQogICAgICApCiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgfQoKICAgIGR1cGxpY2F0ZV9hdHRyaWJ1dGUgPC0gbGV2ZWxfbG9uZyAlPiUKICAgICAgY291bnQoCiAgICAgICAgSUQsCiAgICAgICAgdGFzaywKICAgICAgICBwcm9maWxlLAogICAgICAgIGF0dHJfdmFyCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcihuICE9IDEpCgogICAgaWYgKG5yb3coZHVwbGljYXRlX2F0dHJpYnV0ZSkgPiAwKSB7CiAgICAgIHByaW50KAogICAgICAgIGhlYWQoCiAgICAgICAgICBkdXBsaWNhdGVfYXR0cmlidXRlLAogICAgICAgICAgNTAKICAgICAgICApCiAgICAgICkKICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpCiAgICB9CgoKICAgIGVjb25vbWljX3dpZGUgPC0gbGV2ZWxfbG9uZyAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIElELAogICAgICAgIHRhc2ssCiAgICAgICAgcHJvZmlsZSwKICAgICAgICBhdHRyX3ZhciwKICAgICAgICBsZXZlbAogICAgICApICU+JQogICAgICBwaXZvdF93aWRlcigKICAgICAgICBuYW1lc19mcm9tID0gYXR0cl92YXIsCiAgICAgICAgdmFsdWVzX2Zyb20gPSBsZXZlbCwKICAgICAgICB2YWx1ZXNfZm4gPSBsaXN0KAogICAgICAgICAgbGV2ZWwgPSB+IGZpcnN0KC54KQogICAgICAgICkKICAgICAgKQoKICAgIHByb2ZpbGVfd2lkZSA8LSBwYXJ0eV9sb25nICU+JQogICAgICBpbm5lcl9qb2luKAogICAgICAgIGVjb25vbWljX3dpZGUsCiAgICAgICAgYnkgPSBjKAogICAgICAgICAgIklEIiwKICAgICAgICAgICJ0YXNrIiwKICAgICAgICAgICJwcm9maWxlIgogICAgICAgICkKICAgICAgKSAlPiUKICAgICAgaW5uZXJfam9pbigKICAgICAgICBjaG9pY2VfbG9uZywKICAgICAgICBieSA9IGMoCiAgICAgICAgICAiSUQiLAogICAgICAgICAgInRhc2siCiAgICAgICAgKQogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgcGFydHlfbiA9IG5fcGFydHksCiAgICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKAogICAgICAgICAgcHJvZmlsZSA9PSBjaG9pY2UKICAgICAgICApLAogICAgICAgIHRhc2tfaWQgPSBwYXN0ZSgKICAgICAgICAgIElELAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgIHRhc2ssCiAgICAgICAgICBzZXAgPSAiXyIKICAgICAgICApLAogICAgICAgIHByb2ZpbGVfaWQgPSBwYXN0ZSgKICAgICAgICAgIElELAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgIHRhc2ssCiAgICAgICAgICBwcm9maWxlLAogICAgICAgICAgc2VwID0gIl8iCiAgICAgICAgKQogICAgICApCgogICAgbWlzc2luZ19hdHRyIDwtIHNldGRpZmYoCiAgICAgIHJlcXVpcmVkX2F0dHJfdmFycywKICAgICAgbmFtZXMocHJvZmlsZV93aWRlKQogICAgKQoKICAgIGlmIChsZW5ndGgobWlzc2luZ19hdHRyKSA+IDApIHsKICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpCiAgICB9CgogICAgcHJvZmlsZV93aWRlIDwtIHByb2ZpbGVfd2lkZSAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIElELAogICAgICAgIHBhcnR5X24sCiAgICAgICAgdGFzaywKICAgICAgICBwcm9maWxlLAogICAgICAgIGNob2ljZSwKICAgICAgICBzZWxlY3RlZCwKICAgICAgICB0YXNrX2lkLAogICAgICAgIHByb2ZpbGVfaWQsCiAgICAgICAgYWxsX29mKHJlcXVpcmVkX2F0dHJfdmFycykKICAgICAgKSAlPiUKICAgICAgYXJyYW5nZSgKICAgICAgICBJRCwKICAgICAgICB0YXNrLAogICAgICAgIHByb2ZpbGUKICAgICAgKQoKICAgIHJldHVybihwcm9maWxlX3dpZGUpCiAgfQoKCiAgY29uam9pbnRfMiA8LSBtYWtlX3Byb2ZpbGVfbG9uZygKICAgIGRmLAogICAgMgogICkKCiAgY29uam9pbnRfMyA8LSBtYWtlX3Byb2ZpbGVfbG9uZygKICAgIGRmLAogICAgMwogICkKCiAgY29uam9pbnRfNCA8LSBtYWtlX3Byb2ZpbGVfbG9uZygKICAgIGRmLAogICAgNAogICkKCiAgY29uam9pbnRfNSA8LSBtYWtlX3Byb2ZpbGVfbG9uZygKICAgIGRmLAogICAgNQogICkKCiAgY29uam9pbnRfYWxsX3VuZmlsdGVyZWQgPC0gYmluZF9yb3dzKAogICAgY29uam9pbnRfMiwKICAgIGNvbmpvaW50XzMsCiAgICBjb25qb2ludF80LAogICAgY29uam9pbnRfNQogICkKCgogIGlkX3Rhc2tfY2hlY2sgPC0gY29uam9pbnRfYWxsX3VuZmlsdGVyZWQgJT4lCiAgICBncm91cF9ieSgKICAgICAgSUQsCiAgICAgIHBhcnR5X24sCiAgICAgIHRhc2sKICAgICkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIG5fcHJvZmlsZXMgPSBuKCksCiAgICAgIHNlbGVjdGVkX3N1bSA9IHN1bShzZWxlY3RlZCksCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkgJT4lCiAgICBncm91cF9ieSgKICAgICAgSUQsCiAgICAgIHBhcnR5X24KICAgICkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIG5fdGFza3MgPSBuX2Rpc3RpbmN0KHRhc2spLAogICAgICBhbGxfdGFza3Nfb2sgPSBhbGwoCiAgICAgICAgbl9wcm9maWxlcyA9PSBwYXJ0eV9uICYKICAgICAgICAgIHNlbGVjdGVkX3N1bSA9PSAxCiAgICAgICksCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkKCiAgaWYgKHJlcXVpcmVfYWxsX2ZpdmVfdGFza3MpIHsKICAgIHZhbGlkX2lkcyA8LSBpZF90YXNrX2NoZWNrICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgbl90YXNrcyA9PSA1LAogICAgICAgIGFsbF90YXNrc19vawogICAgICApCiAgfSBlbHNlIHsKICAgIHZhbGlkX2lkcyA8LSBpZF90YXNrX2NoZWNrICU+JQogICAgICBmaWx0ZXIoYWxsX3Rhc2tzX29rKQogIH0KCiAgY29uam9pbnRfYWxsIDwtIGNvbmpvaW50X2FsbF91bmZpbHRlcmVkICU+JQogICAgc2VtaV9qb2luKAogICAgICB2YWxpZF9pZHMsCiAgICAgIGJ5ID0gYygKICAgICAgICAiSUQiLAogICAgICAgICJwYXJ0eV9uIgogICAgICApCiAgICApCgogIHNhbXBsZV9mbG93IDwtIGJpbmRfcm93cygKICAgIHNhbXBsZV9mbG93LAogICAgdGliYmxlKAogICAgICBzdGFnZSA9IGlmIChyZXF1aXJlX2FsbF9maXZlX3Rhc2tzKSB7CiAgICAgICAgIjXoqrLpoYzjgZnjgbnjgabjgYzlrozlhajjgarlm57nrZTogIUiCiAgICAgIH0gZWxzZSB7CiAgICAgICAgIuWbnuetlOa4iOOBv+iqsumhjOOBjOOBmeOBueOBpuWujOWFqOOBquWbnuetlOiAhSIKICAgICAgfSwKICAgICAgbiA9IG5fZGlzdGluY3QoY29uam9pbnRfYWxsJElEKQogICAgKQogICkKCiAgbl9ieV9wYXJ0eSA8LSB2YWxpZF9pZHMgJT4lCiAgICBjb3VudCgKICAgICAgcGFydHlfbiwKICAgICAgbmFtZSA9ICJuIgogICAgKSAlPiUKICAgIGNvbXBsZXRlKAogICAgICBwYXJ0eV9uID0gMjo1LAogICAgICBmaWxsID0gbGlzdChuID0gMCkKICAgICkgJT4lCiAgICBhcnJhbmdlKHBhcnR5X24pCgogIG5fdG90YWwgPC0gdmFsaWRfaWRzICU+JQogICAgc3VtbWFyaXNlKAogICAgICBuID0gbl9kaXN0aW5jdChJRCkKICAgICkgJT4lCiAgICBwdWxsKG4pCgogIGZpZ3VyZV9uX2xhYmVscyA8LSBiaW5kX3Jvd3MoCiAgICB0aWJibGUoCiAgICAgIHBvc2l0aW9uID0gIuWFqOOCteODs+ODl+ODqyIsCiAgICAgIGxhYmVsID0gcGFzdGUwKAogICAgICAgICLlhajjgrXjg7Pjg5fjg6ssIG49IiwKICAgICAgICBzY2FsZXM6OmNvbW1hKG5fdG90YWwpCiAgICAgICkKICAgICksCgogICAgbl9ieV9wYXJ0eSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIHBvc2l0aW9uID0gcGFzdGUwKAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgICLpgbjmip7ogqIiCiAgICAgICAgKSwKICAgICAgICBsYWJlbCA9IHBhc3RlMCgKICAgICAgICAgICJuPSIsCiAgICAgICAgICBzY2FsZXM6OmNvbW1hKG4pCiAgICAgICAgKQogICAgICApICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgcG9zaXRpb24sCiAgICAgICAgbGFiZWwKICAgICAgKQogICkKCiAgY2F0KCJcbuWIhuaekOWvvuixoeiAheaVsFxuIikKICBwcmludChuX2J5X3BhcnR5KQogIGNhdCgKICAgICLlhajjgrXjg7Pjg5fjg6sgbj0iLAogICAgbl90b3RhbCwKICAgICJcbiIsCiAgICBzZXAgPSAiIgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIHNhbXBsZV9mbG93LAogICAgInNhbXBsZV9mbG93LmNzdiIKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICBpZF90YXNrX2NoZWNrLAogICAgImlkX3Rhc2tfY2hlY2suY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIHZhbGlkX2lkcywKICAgICJ2YWxpZF9pZHMuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIG5fYnlfcGFydHksCiAgICAibl9ieV9wYXJ0eS5jc3YiCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgZmlndXJlX25fbGFiZWxzLAogICAgImZpZ3VyZV9uX2xhYmVscy5jc3YiCiAgKQoKCiAgY2hlY2tfcHJvZmlsZSA8LSBjb25qb2ludF9hbGwgJT4lCiAgICBncm91cF9ieSgKICAgICAgcGFydHlfbiwKICAgICAgSUQsCiAgICAgIHRhc2ssCiAgICAgIHRhc2tfaWQKICAgICkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIG5fcHJvZmlsZXMgPSBuKCksCiAgICAgIHNlbGVjdGVkX3N1bSA9IHN1bShzZWxlY3RlZCksCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkgJT4lCiAgICBjb3VudCgKICAgICAgcGFydHlfbiwKICAgICAgbl9wcm9maWxlcywKICAgICAgc2VsZWN0ZWRfc3VtCiAgICApCgogIHByaW50KGNoZWNrX3Byb2ZpbGUpCgogIHN0b3BpZm5vdCgKICAgIGFsbCgKICAgICAgY2hlY2tfcHJvZmlsZSRuX3Byb2ZpbGVzID09CiAgICAgICAgY2hlY2tfcHJvZmlsZSRwYXJ0eV9uCiAgICApCiAgKQoKICBzdG9waWZub3QoCiAgICBhbGwoCiAgICAgIGNoZWNrX3Byb2ZpbGUkc2VsZWN0ZWRfc3VtID09IDEKICAgICkKICApCgogIGFsbG93ZWRfZWNvbm9taWNfZGYgPC0gZW5mcmFtZSgKICAgIGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzLAogICAgbmFtZSA9ICJuYW1lIiwKICAgIHZhbHVlID0gInZhbHVlIgogICkgJT4lCiAgICB1bm5lc3QodmFsdWUpCgogIHVuZXhwZWN0ZWRfZWNvbm9taWNfdmFsdWVzIDwtIGNvbmpvaW50X2FsbCAlPiUKICAgIHNlbGVjdCgKICAgICAgYWxsX29mKAogICAgICAgIG5hbWVzKGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzKQogICAgICApCiAgICApICU+JQogICAgcGl2b3RfbG9uZ2VyKAogICAgICBjb2xzID0gZXZlcnl0aGluZygpLAogICAgICBuYW1lc190byA9ICJuYW1lIiwKICAgICAgdmFsdWVzX3RvID0gInZhbHVlIgogICAgKSAlPiUKICAgIGZpbHRlcigKICAgICAgIWlzLm5hKHZhbHVlKSwKICAgICAgdmFsdWUgIT0gIiIKICAgICkgJT4lCiAgICBkaXN0aW5jdCgKICAgICAgbmFtZSwKICAgICAgdmFsdWUKICAgICkgJT4lCiAgICBhbnRpX2pvaW4oCiAgICAgIGFsbG93ZWRfZWNvbm9taWNfZGYsCiAgICAgIGJ5ID0gYygKICAgICAgICAibmFtZSIsCiAgICAgICAgInZhbHVlIgogICAgICApCiAgICApCgogIHByaW50KHVuZXhwZWN0ZWRfZWNvbm9taWNfdmFsdWVzKQoKICBzdG9waWZub3QoCiAgICBucm93KHVuZXhwZWN0ZWRfZWNvbm9taWNfdmFsdWVzKSA9PSAwCiAgKQoKICBvYnNlcnZlZF9wYXJ0eV9sZXZlbHMgPC0gY29uam9pbnRfYWxsICU+JQogICAgZGlzdGluY3QocGFydHlfbmFtZSkgJT4lCiAgICBhcnJhbmdlKHBhcnR5X25hbWUpCgogIG9ic2VydmVkX2Vjb25vbWljX2xldmVscyA8LSBjb25qb2ludF9hbGwgJT4lCiAgICBzZWxlY3QoCiAgICAgIGFsbF9vZigKICAgICAgICBuYW1lcyhhbGxvd2VkX2Vjb25vbWljX2xldmVscykKICAgICAgKQogICAgKSAlPiUKICAgIHBpdm90X2xvbmdlcigKICAgICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwKICAgICAgdmFsdWVzX3RvID0gImxldmVsIgogICAgKSAlPiUKICAgIGRpc3RpbmN0KAogICAgICBhdHRyaWJ1dGUsCiAgICAgIGxldmVsCiAgICApICU+JQogICAgYXJyYW5nZSgKICAgICAgYXR0cmlidXRlLAogICAgICBsZXZlbAogICAgKQoKICBwYXJ0eV9sZXZlbF9mcmVxdWVuY3kgPC0gY29uam9pbnRfYWxsICU+JQogICAgY291bnQoCiAgICAgIHBhcnR5X24sCiAgICAgIHBhcnR5X25hbWUsCiAgICAgIG5hbWUgPSAibl9wcm9maWxlcyIKICAgICkgJT4lCiAgICBncm91cF9ieShwYXJ0eV9uKSAlPiUKICAgIG11dGF0ZSgKICAgICAgcHJvcG9ydGlvbiA9IG5fcHJvZmlsZXMgLwogICAgICAgIHN1bShuX3Byb2ZpbGVzKQogICAgKSAlPiUKICAgIHVuZ3JvdXAoKQoKICBlY29ub21pY19sZXZlbF9mcmVxdWVuY3kgPC0gY29uam9pbnRfYWxsICU+JQogICAgc2VsZWN0KAogICAgICBwYXJ0eV9uLAogICAgICBhbGxfb2YoCiAgICAgICAgbmFtZXMoYWxsb3dlZF9lY29ub21pY19sZXZlbHMpCiAgICAgICkKICAgICkgJT4lCiAgICBwaXZvdF9sb25nZXIoCiAgICAgIGNvbHMgPSBhbGxfb2YoCiAgICAgICAgbmFtZXMoYWxsb3dlZF9lY29ub21pY19sZXZlbHMpCiAgICAgICksCiAgICAgIG5hbWVzX3RvID0gImF0dHJpYnV0ZSIsCiAgICAgIHZhbHVlc190byA9ICJsZXZlbCIKICAgICkgJT4lCiAgICBjb3VudCgKICAgICAgcGFydHlfbiwKICAgICAgYXR0cmlidXRlLAogICAgICBsZXZlbCwKICAgICAgbmFtZSA9ICJuX3Byb2ZpbGVzIgogICAgKSAlPiUKICAgIGdyb3VwX2J5KAogICAgICBwYXJ0eV9uLAogICAgICBhdHRyaWJ1dGUKICAgICkgJT4lCiAgICBtdXRhdGUoCiAgICAgIHByb3BvcnRpb24gPSBuX3Byb2ZpbGVzIC8KICAgICAgICBzdW0obl9wcm9maWxlcykKICAgICkgJT4lCiAgICB1bmdyb3VwKCkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIGNoZWNrX3Byb2ZpbGUsCiAgICAicHJvZmlsZV9leHBhbnNpb25fY2hlY2suY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIG9ic2VydmVkX3BhcnR5X2xldmVscywKICAgICJvYnNlcnZlZF9wYXJ0eV9sZXZlbHMuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIG9ic2VydmVkX2Vjb25vbWljX2xldmVscywKICAgICJvYnNlcnZlZF9lY29ub21pY19sZXZlbHMuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIHBhcnR5X2xldmVsX2ZyZXF1ZW5jeSwKICAgICJwYXJ0eV9sZXZlbF9mcmVxdWVuY3kuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIGVjb25vbWljX2xldmVsX2ZyZXF1ZW5jeSwKICAgICJlY29ub21pY19sZXZlbF9mcmVxdWVuY3kuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIGNvbmpvaW50X2FsbCwKICAgICJzdHVkeTNfcHJvZmlsZV9sZXZlbF9kYXRhLmNzdiIKICApCgoKICBhbmFseXNpc19pZHMgPC0gdmFsaWRfaWRzICU+JQogICAgc2VsZWN0KAogICAgICBJRCwKICAgICAgcGFydHlfbgogICAgKQoKICBpZiAoYXR0ZW50aW9uX2NoZWNrX3ZhciAlaW4lIG5hbWVzKGRmKSkgewogICAgYXR0ZW50aW9uX3N1bW1hcnkgPC0gZGYgJT4lCiAgICAgIHNlbWlfam9pbigKICAgICAgICBhbmFseXNpc19pZHMsCiAgICAgICAgYnkgPSAiSUQiCiAgICAgICkgJT4lCiAgICAgIHRyYW5zbXV0ZSgKICAgICAgICBJRCwKICAgICAgICBhdHRlbnRpb25fcmVzcG9uc2UgPSBub3JtX3RleHQoCiAgICAgICAgICAuZGF0YVtbYXR0ZW50aW9uX2NoZWNrX3Zhcl1dCiAgICAgICAgKSwKICAgICAgICBhdHRlbnRpb25fcGFzcyA9IGlzX3Jlc3BvbnNlX2NvZGUoCiAgICAgICAgICAuZGF0YVtbYXR0ZW50aW9uX2NoZWNrX3Zhcl1dLAogICAgICAgICAgYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QKICAgICAgICApCiAgICAgICkgJT4lCiAgICAgIGNvdW50KAogICAgICAgIGF0dGVudGlvbl9yZXNwb25zZSwKICAgICAgICBhdHRlbnRpb25fcGFzcywKICAgICAgICBuYW1lID0gIm4iCiAgICAgICkgJT4lCiAgICAgIGFycmFuZ2UoCiAgICAgICAgZGVzYyhhdHRlbnRpb25fcGFzcyksCiAgICAgICAgYXR0ZW50aW9uX3Jlc3BvbnNlCiAgICAgICkKICB9IGVsc2UgewogICAgYXR0ZW50aW9uX3N1bW1hcnkgPC0gdGliYmxlKAogICAgICBhdHRlbnRpb25fcmVzcG9uc2UgPSBjaGFyYWN0ZXIoKSwKICAgICAgYXR0ZW50aW9uX3Bhc3MgPSBsb2dpY2FsKCksCiAgICAgIG4gPSBpbnRlZ2VyKCkKICAgICkKICB9CgogIG1hbmlwdWxhdGlvbl9zdW1tYXJ5IDwtIG1hcF9kZnIoCiAgICAyOjUsCiAgICBmdW5jdGlvbihuX3BhcnR5KSB7CiAgICAgIG1hbmlwdWxhdGlvbl9yb3cgPC0gbWFuaXB1bGF0aW9uX21hcCAlPiUKICAgICAgICBmaWx0ZXIoCiAgICAgICAgICBwYXJ0eV9uID09IG5fcGFydHkKICAgICAgICApCgogICAgICB2IDwtIG1hbmlwdWxhdGlvbl9yb3ckbWFuaXB1bGF0aW9uX3ZhcgogICAgICBjb3JyZWN0IDwtIG1hbmlwdWxhdGlvbl9yb3ckY29ycmVjdF9hbnN3ZXIKCiAgICAgIGlmICghdiAlaW4lIG5hbWVzKGRmKSkgewogICAgICAgIHJldHVybigKICAgICAgICAgIHRpYmJsZSgKICAgICAgICAgICAgcGFydHlfbiA9IG5fcGFydHksCiAgICAgICAgICAgIHJlc3BvbnNlID0gTkFfY2hhcmFjdGVyXywKICAgICAgICAgICAgY29ycmVjdCA9IE5BLAogICAgICAgICAgICBuID0gMEwKICAgICAgICAgICkKICAgICAgICApCiAgICAgIH0KCiAgICAgIGRmICU+JQogICAgICAgIHNlbWlfam9pbigKICAgICAgICAgIGFuYWx5c2lzX2lkcyAlPiUKICAgICAgICAgICAgZmlsdGVyKAogICAgICAgICAgICAgIHBhcnR5X24gPT0gbl9wYXJ0eQogICAgICAgICAgICApLAogICAgICAgICAgYnkgPSAiSUQiCiAgICAgICAgKSAlPiUKICAgICAgICB0cmFuc211dGUoCiAgICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwKICAgICAgICAgIHJlc3BvbnNlID0gbm9ybV90ZXh0KAogICAgICAgICAgICAuZGF0YVtbdl1dCiAgICAgICAgICApLAogICAgICAgICAgY29ycmVjdCA9IGlzX3Jlc3BvbnNlX2NvZGUoCiAgICAgICAgICAgIC5kYXRhW1t2XV0sCiAgICAgICAgICAgIGNvcnJlY3QKICAgICAgICAgICkKICAgICAgICApICU+JQogICAgICAgIGNvdW50KAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgIHJlc3BvbnNlLAogICAgICAgICAgY29ycmVjdCwKICAgICAgICAgIG5hbWUgPSAibiIKICAgICAgICApCiAgICB9CiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgYXR0ZW50aW9uX3N1bW1hcnksCiAgICAiYXR0ZW50aW9uX2NoZWNrX3N1bW1hcnkuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIG1hbmlwdWxhdGlvbl9zdW1tYXJ5LAogICAgInBhcnR5X251bWJlcl9jaGVja19zdW1tYXJ5LmNzdiIKICApCgoKICBvYnNlcnZlZF9wYXJ0eV92ZWN0b3IgPC0gY29uam9pbnRfYWxsICU+JQogICAgZGlzdGluY3QocGFydHlfbmFtZSkgJT4lCiAgICBwdWxsKHBhcnR5X25hbWUpCgogIHBhcnR5X3JlZmVyZW5jZSA8LSBpZiAoCiAgICAi6Ieq55Sx5rCR5Li75YWaIiAlaW4lIG9ic2VydmVkX3BhcnR5X3ZlY3RvcgogICkgewogICAgIuiHqueUseawkeS4u+WFmiIKICB9IGVsc2UgewogICAgc29ydChvYnNlcnZlZF9wYXJ0eV92ZWN0b3IpWzFdCiAgfQoKICBpZiAocGFydHlfcmVmZXJlbmNlICE9ICLoh6rnlLHmsJHkuLvlhZoiKSB7CiAgICB3YXJuaW5nKCJDaGVjayIpCiAgfQoKICBwYXJ0eV9sZXZlbHNfdXNlIDwtIGMoCiAgICBwYXJ0eV9yZWZlcmVuY2UsCgogICAgZXhwZWN0ZWRfcGFydHlfbGV2ZWxzWwogICAgICBleHBlY3RlZF9wYXJ0eV9sZXZlbHMgJWluJQogICAgICAgIG9ic2VydmVkX3BhcnR5X3ZlY3RvciAmCiAgICAgICAgZXhwZWN0ZWRfcGFydHlfbGV2ZWxzICE9CiAgICAgICAgcGFydHlfcmVmZXJlbmNlCiAgICBdLAoKICAgIHNvcnQoCiAgICAgIHNldGRpZmYoCiAgICAgICAgb2JzZXJ2ZWRfcGFydHlfdmVjdG9yLAogICAgICAgIGV4cGVjdGVkX3BhcnR5X2xldmVscwogICAgICApCiAgICApCiAgKSAlPiUKICAgIHVuaXF1ZSgpCgogIGNvbmpvaW50X2FsbF9tIDwtIGNvbmpvaW50X2FsbCAlPiUKICAgIG11dGF0ZSgKICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHNlbGVjdGVkKSwKICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAoKICAgICAgcGFydHlfbmFtZSA9IGZhY3RvcigKICAgICAgICBwYXJ0eV9uYW1lLAogICAgICAgIGxldmVscyA9IHBhcnR5X2xldmVsc191c2UKICAgICAgKSwKCiAgICAgIGdkcF9ncm93dGggPSBmYWN0b3IoCiAgICAgICAgZ2RwX2dyb3d0aCwKICAgICAgICBsZXZlbHMgPSBhbGxvd2VkX2Vjb25vbWljX2xldmVscyRnZHBfZ3Jvd3RoCiAgICAgICksCgogICAgICBuaWtrZWkgPSBmYWN0b3IoCiAgICAgICAgbmlra2VpLAogICAgICAgIGxldmVscyA9IGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzJG5pa2tlaQogICAgICApLAoKICAgICAgY3BpID0gZmFjdG9yKAogICAgICAgIGNwaSwKICAgICAgICBsZXZlbHMgPSBhbGxvd2VkX2Vjb25vbWljX2xldmVscyRjcGkKICAgICAgKSwKCiAgICAgIHVuZW1wbG95bWVudCA9IGZhY3RvcigKICAgICAgICB1bmVtcGxveW1lbnQsCiAgICAgICAgbGV2ZWxzID0gYWxsb3dlZF9lY29ub21pY19sZXZlbHMkdW5lbXBsb3ltZW50CiAgICAgICksCgogICAgICBwYXJ0eV9uX2YgPSBmYWN0b3IoCiAgICAgICAgYXMuY2hhcmFjdGVyKHBhcnR5X24pLAogICAgICAgIGxldmVscyA9IGMoCiAgICAgICAgICAiMiIsCiAgICAgICAgICAiMyIsCiAgICAgICAgICAiNCIsCiAgICAgICAgICAiNSIKICAgICAgICApCiAgICAgICksCgogICAgICBwYXJ0eV9uX2MgPSBwYXJ0eV9uIC0gMgogICAgKQoKICBhdHRyX3Rlcm1zIDwtIGMoCiAgICAicGFydHlfbmFtZSIsCiAgICAiZ2RwX2dyb3d0aCIsCiAgICAibmlra2VpIiwKICAgICJjcGkiLAogICAgInVuZW1wbG95bWVudCIKICApCgogIGVjb25vbWljX2F0dHJfdGVybXMgPC0gYygKICAgICJnZHBfZ3Jvd3RoIiwKICAgICJuaWtrZWkiLAogICAgImNwaSIsCiAgICAidW5lbXBsb3ltZW50IgogICkKCgogIGZvcm11bGFfbm9jb3YgPC0gYXMuZm9ybXVsYSgKICAgIHBhc3RlKAogICAgICAic2VsZWN0ZWQgfiIsCiAgICAgIHBhc3RlKAogICAgICAgIGF0dHJfdGVybXMsCiAgICAgICAgY29sbGFwc2UgPSAiICsgIgogICAgICApCiAgICApCiAgKQoKICBydW5fYW1jZV9ub2NvdiA8LSBmdW5jdGlvbihkYXQpIHsKICAgIGZlb2xzKAogICAgICBmb3JtdWxhX25vY292LAogICAgICBkYXRhID0gZGF0LAogICAgICB2Y292ID0gfiBJRAogICAgKQogIH0KCiAgbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YgPC0gY29uam9pbnRfYWxsX20gJT4lCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQogICAgbWFwKHJ1bl9hbWNlX25vY292KQoKICBjYXB0dXJlLm91dHB1dCgKICAgIGV0YWJsZSgKICAgICAgbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YKICAgICksCiAgICBmaWxlID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAiYW1jZV9ub2Nvdl9tb2RlbHMudHh0IgogICAgKQogICkKCgogIG1faW50ZXJhY3Rpb24gPC0gZmVvbHMoCiAgICBzZWxlY3RlZCB+CiAgICAgIHBhcnR5X25fZiAqCiAgICAgICgKICAgICAgICBwYXJ0eV9uYW1lICsKICAgICAgICAgIGdkcF9ncm93dGggKwogICAgICAgICAgbmlra2VpICsKICAgICAgICAgIGNwaSArCiAgICAgICAgICB1bmVtcGxveW1lbnQKICAgICAgKSwKICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwKICAgIHZjb3YgPSB+IElECiAgKQoKICBjYXB0dXJlLm91dHB1dCgKICAgIHN1bW1hcnkobV9pbnRlcmFjdGlvbiksCiAgICBmaWxlID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAiYW1jZV9pbnRlcmFjdGlvbl9tb2RlbC50eHQiCiAgICApCiAgKQoKCiAgbV9saW5lYXJfdHJlbmQgPC0gZmVvbHMoCiAgICBzZWxlY3RlZCB+CiAgICAgIHBhcnR5X25fYyAqCiAgICAgICgKICAgICAgICBwYXJ0eV9uYW1lICsKICAgICAgICAgIGdkcF9ncm93dGggKwogICAgICAgICAgbmlra2VpICsKICAgICAgICAgIGNwaSArCiAgICAgICAgICB1bmVtcGxveW1lbnQKICAgICAgKSwKICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwKICAgIHZjb3YgPSB+IElECiAgKQoKICBjYXB0dXJlLm91dHB1dCgKICAgIHN1bW1hcnkobV9saW5lYXJfdHJlbmQpLAogICAgZmlsZSA9IGZpbGUucGF0aCgKICAgICAgb3V0cHV0X2RpciwKICAgICAgImFtY2VfbGluZWFyX3RyZW5kX21vZGVsLnR4dCIKICAgICkKICApCgoKICBwYXJ0eV90ZXJtX2xhYmVscyA8LSB0aWJibGUoCiAgICB0ZXJtID0gcGFzdGUwKAogICAgICAicGFydHlfbmFtZSIsCiAgICAgIHBhcnR5X2xldmVsc191c2VbLTFdCiAgICApLAogICAgYXR0cmlidXRlID0gIuaUv+aoqeS4juWFmuOBruaUv+WFmuWQjSIsCiAgICBjdWVfdHlwZSA9ICLmlL/lhZrlkI3jga7miYvjgYzjgYvjgooiLAogICAgbGFiZWwgPSBwYXJ0eV9sZXZlbHNfdXNlWy0xXSwKICAgIG9yZGVyID0gc2VxX2Fsb25nKAogICAgICBwYXJ0eV9sZXZlbHNfdXNlWy0xXQogICAgKQogICkKCiAgZWNvbm9taWNfdGVybV9sYWJlbHMgPC0gdHJpYmJsZSgKICAgIH50ZXJtLCB+YXR0cmlidXRlLCB+Y3VlX3R5cGUsIH5sYWJlbCwgfm9yZGVyLAoKICAgICJnZHBfZ3Jvd3RoR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsCiAgICAiR0RQ5oiQ6ZW3546HIiwKICAgICLntYzmuIjjga7miYvjgYzjgYvjgooiLAogICAgIkdEUO+8muODl+ODqeOCuTHvvIUiLAogICAgMSwKCiAgICAiZ2RwX2dyb3d0aEdEUOaIkOmVt+eOh+ODnuOCpOODiuOCuTHvvIUiLAogICAgIkdEUOaIkOmVt+eOhyIsCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwKICAgICJHRFDvvJrjg57jgqTjg4rjgrkx77yFIiwKICAgIDIsCgogICAgIm5pa2tlaeaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLAogICAgIuaXpee1jOW5s+WdhyIsCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwKICAgICLml6XntYzlubPlnYfvvJrjg5fjg6njgrkxMDAw5YaGIiwKICAgIDMsCgogICAgIm5pa2tlaeaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODnuOCpOODiuOCuTEwMDDlhoYiLAogICAgIuaXpee1jOW5s+WdhyIsCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwKICAgICLml6XntYzlubPlnYfvvJrjg57jgqTjg4rjgrkxMDAw5YaGIiwKICAgIDQsCgogICAgImNwaUNQSeWJjeacn+avlOODl+ODqeOCuTHjg53jgqTjg7Pjg4giLAogICAgIkNQSSIsCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwKICAgICJDUEnvvJrjg5fjg6njgrkx44Od44Kk44Oz44OIIiwKICAgIDUsCgogICAgImNwaUNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giLAogICAgIkNQSSIsCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwKICAgICJDUEnvvJrjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIiwKICAgIDYsCgogICAgInVuZW1wbG95bWVudOWksealreeOh+WJjeacn+avlOODl+ODqeOCuTHvvIUiLAogICAgIuWksealreeOhyIsCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwKICAgICLlpLHmpa3njofvvJrjg5fjg6njgrkx77yFIiwKICAgIDcsCgogICAgInVuZW1wbG95bWVudOWksealreeOh+WJjeacn+avlOODnuOCpOODiuOCuTHvvIUiLAogICAgIuWksealreeOhyIsCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwKICAgICLlpLHmpa3njofvvJrjg57jgqTjg4rjgrkx77yFIiwKICAgIDgKICApCgogIHRlcm1fbGFiZWxzIDwtIGJpbmRfcm93cygKICAgIHBhcnR5X3Rlcm1fbGFiZWxzICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgb3JkZXJfZ2xvYmFsID0gb3JkZXIKICAgICAgKSwKCiAgICBlY29ub21pY190ZXJtX2xhYmVscyAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIG9yZGVyX2dsb2JhbCA9CiAgICAgICAgICBtYXgoCiAgICAgICAgICAgIGMoCiAgICAgICAgICAgICAgcGFydHlfdGVybV9sYWJlbHMkb3JkZXIsCiAgICAgICAgICAgICAgMAogICAgICAgICAgICApCiAgICAgICAgICApICsKICAgICAgICAgIG9yZGVyCiAgICAgICkKICApICU+JQogICAgc2VsZWN0KAogICAgICB0ZXJtLAogICAgICBhdHRyaWJ1dGUsCiAgICAgIGN1ZV90eXBlLAogICAgICBsYWJlbCwKICAgICAgb3JkZXIgPSBvcmRlcl9nbG9iYWwKICAgICkKCiAgYXR0cmlidXRlX29yZGVyIDwtIGMoCiAgICAi5pS/5qip5LiO5YWa44Gu5pS/5YWa5ZCNIiwKICAgICJHRFDmiJDplbfnjociLAogICAgIuaXpee1jOW5s+WdhyIsCiAgICAiQ1BJIiwKICAgICLlpLHmpa3njociCiAgKQoKICBsYWJlbF9vcmRlciA8LSB0ZXJtX2xhYmVscyAlPiUKICAgIGFycmFuZ2Uob3JkZXIpICU+JQogICAgcHVsbChsYWJlbCkKCiAgbWFrZV9hbWNlX3Bsb3RfZGYgPC0gZnVuY3Rpb24obW9kZWxzKSB7CiAgICBpbWFwX2RmcigKICAgICAgbW9kZWxzLAogICAgICB+IHRpZHlfZml4ZXN0KC54KSAlPiUKICAgICAgICBtdXRhdGUoCiAgICAgICAgICBwYXJ0eV9uID0gYXMuY2hhcmFjdGVyKC55KQogICAgICAgICkKICAgICkgJT4lCiAgICAgIGxlZnRfam9pbigKICAgICAgICB0ZXJtX2xhYmVscywKICAgICAgICBieSA9ICJ0ZXJtIgogICAgICApICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgIWlzLm5hKGF0dHJpYnV0ZSkKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsCiAgICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwKICAgICAgICBjb25mLmhpZ2hfcHAgPSBjb25mLmhpZ2ggKiAxMDAsCgogICAgICAgIHBhcnR5X24gPSBmYWN0b3IoCiAgICAgICAgICBwYXJ0eV9uLAogICAgICAgICAgbGV2ZWxzID0gYygKICAgICAgICAgICAgIjIiLAogICAgICAgICAgICAiMyIsCiAgICAgICAgICAgICI0IiwKICAgICAgICAgICAgIjUiCiAgICAgICAgICApLAogICAgICAgICAgbGFiZWxzID0gYygKICAgICAgICAgICAgIjLpgbjmip7ogqIiLAogICAgICAgICAgICAiM+mBuOaKnuiCoiIsCiAgICAgICAgICAgICI06YG45oqe6IKiIiwKICAgICAgICAgICAgIjXpgbjmip7ogqIiCiAgICAgICAgICApCiAgICAgICAgKSwKCiAgICAgICAgYXR0cmlidXRlID0gZmFjdG9yKAogICAgICAgICAgYXR0cmlidXRlLAogICAgICAgICAgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyCiAgICAgICAgKSwKCiAgICAgICAgbGFiZWwgPSBmYWN0b3IoCiAgICAgICAgICBsYWJlbCwKICAgICAgICAgIGxldmVscyA9IHJldigKICAgICAgICAgICAgbGFiZWxfb3JkZXIKICAgICAgICAgICkKICAgICAgICApCiAgICAgICkKICB9CgogIGFtY2VfcGxvdF9ub2NvdiA8LSBtYWtlX2FtY2VfcGxvdF9kZigKICAgIG1vZGVsc19ieV9wYXJ0eV9uX25vY292CiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgYW1jZV9wbG90X25vY292LAogICAgImFtY2Vfbm9jb3ZfY29lZmZpY2llbnRzLmNzdiIKICApCgogIGludGVyYWN0aW9uX3Bsb3RfZGYgPC0gdGlkeV9maXhlc3QoCiAgICBtX2ludGVyYWN0aW9uCiAgKSAlPiUKICAgIGZpbHRlcigKICAgICAgc3RyX2RldGVjdCgKICAgICAgICB0ZXJtLAogICAgICAgICJwYXJ0eV9uX2ZbMzQ1XSIKICAgICAgKQogICAgKSAlPiUKICAgIG11dGF0ZSgKICAgICAgcGFydHlfbl9jb2RlID0gc3RyX2V4dHJhY3QoCiAgICAgICAgdGVybSwKICAgICAgICAicGFydHlfbl9mWzM0NV0iCiAgICAgICksCgogICAgICBwYXJ0eV9uID0gc3RyX3JlbW92ZSgKICAgICAgICBwYXJ0eV9uX2NvZGUsCiAgICAgICAgInBhcnR5X25fZiIKICAgICAgKSwKCiAgICAgIGJhc2VfdGVybSA9IHRlcm0gJT4lCiAgICAgICAgc3RyX3JlbW92ZSgKICAgICAgICAgICJwYXJ0eV9uX2ZbMzQ1XToiCiAgICAgICAgKSAlPiUKICAgICAgICBzdHJfcmVtb3ZlKAogICAgICAgICAgIjpwYXJ0eV9uX2ZbMzQ1XSIKICAgICAgICApCiAgICApICU+JQogICAgbGVmdF9qb2luKAogICAgICB0ZXJtX2xhYmVscywKICAgICAgYnkgPSBjKAogICAgICAgICJiYXNlX3Rlcm0iID0gInRlcm0iCiAgICAgICkKICAgICkgJT4lCiAgICBmaWx0ZXIoCiAgICAgICFpcy5uYShhdHRyaWJ1dGUpCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICBlc3RpbWF0ZV9wcCA9IGVzdGltYXRlICogMTAwLAogICAgICBjb25mLmxvd19wcCA9IGNvbmYubG93ICogMTAwLAogICAgICBjb25mLmhpZ2hfcHAgPSBjb25mLmhpZ2ggKiAxMDAsCgogICAgICBwYXJ0eV9uX2xhYmVsID0gZmFjdG9yKAogICAgICAgIHBhcnR5X24sCiAgICAgICAgbGV2ZWxzID0gYygKICAgICAgICAgICIzIiwKICAgICAgICAgICI0IiwKICAgICAgICAgICI1IgogICAgICAgICksCiAgICAgICAgbGFiZWxzID0gYygKICAgICAgICAgICIz6YG45oqe6IKiIiwKICAgICAgICAgICI06YG45oqe6IKiIiwKICAgICAgICAgICI16YG45oqe6IKiIgogICAgICAgICkKICAgICAgKSwKCiAgICAgIGF0dHJpYnV0ZSA9IGZhY3RvcigKICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyCiAgICAgICksCgogICAgICBsYWJlbCA9IGZhY3RvcigKICAgICAgICBsYWJlbCwKICAgICAgICBsZXZlbHMgPSByZXYoCiAgICAgICAgICBsYWJlbF9vcmRlcgogICAgICAgICkKICAgICAgKQogICAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgaW50ZXJhY3Rpb25fcGxvdF9kZiwKICAgICJhbWNlX2ludGVyYWN0aW9uX2NvZWZmaWNpZW50cy5jc3YiCiAgKQoKICBsaW5lYXJfdHJlbmRfcGxvdF9kZiA8LSB0aWR5X2ZpeGVzdCgKICAgIG1fbGluZWFyX3RyZW5kCiAgKSAlPiUKICAgIGZpbHRlcigKICAgICAgc3RyX2RldGVjdCgKICAgICAgICB0ZXJtLAogICAgICAgICJwYXJ0eV9uX2M6IgogICAgICApIHwKICAgICAgICBzdHJfZGV0ZWN0KAogICAgICAgICAgdGVybSwKICAgICAgICAgICI6cGFydHlfbl9jIgogICAgICAgICkKICAgICkgJT4lCiAgICBtdXRhdGUoCiAgICAgIGJhc2VfdGVybSA9IHRlcm0gJT4lCiAgICAgICAgc3RyX3JlbW92ZSgKICAgICAgICAgICJwYXJ0eV9uX2M6IgogICAgICAgICkgJT4lCiAgICAgICAgc3RyX3JlbW92ZSgKICAgICAgICAgICI6cGFydHlfbl9jIgogICAgICAgICkKICAgICkgJT4lCiAgICBsZWZ0X2pvaW4oCiAgICAgIHRlcm1fbGFiZWxzLAogICAgICBieSA9IGMoCiAgICAgICAgImJhc2VfdGVybSIgPSAidGVybSIKICAgICAgKQogICAgKSAlPiUKICAgIGZpbHRlcigKICAgICAgIWlzLm5hKGF0dHJpYnV0ZSkKICAgICkgJT4lCiAgICBtdXRhdGUoCiAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwKCiAgICAgIGF0dHJpYnV0ZSA9IGZhY3RvcigKICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyCiAgICAgICksCgogICAgICBsYWJlbCA9IGZhY3RvcigKICAgICAgICBsYWJlbCwKICAgICAgICBsZXZlbHMgPSByZXYoCiAgICAgICAgICBsYWJlbF9vcmRlcgogICAgICAgICkKICAgICAgKQogICAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgbGluZWFyX3RyZW5kX3Bsb3RfZGYsCiAgICAiYW1jZV9saW5lYXJfdHJlbmRfY29lZmZpY2llbnRzLmNzdiIKICApCgoKICByZWNvZGVfZmVtYWxlX3N0dWR5MyA8LSBmdW5jdGlvbih4KSB7CiAgICB4X251bSA8LSBhc19udW0oeCkKCiAgICBjYXNlX3doZW4oCiAgICAgIHhfbnVtID09IDIgfiAxTCwKICAgICAgeF9udW0gPT0gMSB+IDBMLAogICAgICBUUlVFIH4gTkFfaW50ZWdlcl8KICAgICkKICB9CgogIHJlY29kZV9jb2xsZWdlX2dyYWRfc3R1ZHkzIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHhfbnVtIDwtIGFzX251bSh4KQoKICAgIGNhc2Vfd2hlbigKICAgICAgeF9udW0gJWluJSBjKAogICAgICAgIDQsCiAgICAgICAgNQogICAgICApIH4gMUwsCgogICAgICB4X251bSAlaW4lIGMoCiAgICAgICAgMSwKICAgICAgICAyLAogICAgICAgIDMKICAgICAgKSB+IDBMLAoKICAgICAgVFJVRSB+IE5BX2ludGVnZXJfCiAgICApCiAgfQoKICByZWNvZGVfc2VsZl9pZGVvbG9neV9zdHVkeTMgPC0gZnVuY3Rpb24oeCkgewogICAgeF9udW0gPC0gYXNfbnVtKHgpCgogICAgY2FzZV93aGVuKAogICAgICB4X251bSAlaW4lIDE6OCB+IHhfbnVtLAogICAgICB4X251bSA9PSAxMiB+IDksCiAgICAgIHhfbnVtID09IDEzIH4gMTAsCiAgICAgIHhfbnVtID09IDE0IH4gMTEsCiAgICAgIFRSVUUgfiBOQV9yZWFsXwogICAgKQogIH0KCiAgcmVjb2RlX3BhcnR5X3N1cHBvcnRfc3R1ZHkzIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHhfbnVtIDwtIGFzX251bSh4KQoKICAgIGNhc2Vfd2hlbigKICAgICAgeF9udW0gPT0gMSB+ICLoh6rnlLHmsJHkuLvlhZoiLAogICAgICB4X251bSA9PSAyIH4gIuS4remBk+aUuemdqemAo+WQiCIsCiAgICAgIHhfbnVtID09IDMgfiAi56uL5oay5rCR5Li75YWaIiwKICAgICAgeF9udW0gPT0gNCB+ICLlhazmmI7lhZoiLAogICAgICB4X251bSA9PSA1IH4gIuaXpeacrOe2reaWsOOBruS8miIsCiAgICAgIHhfbnVtID09IDYgfiAi5Zu95rCR5rCR5Li75YWaIiwKICAgICAgeF9udW0gPT0gNyB+ICLjgozjgYTjgo/mlrDpgbjntYQiLAogICAgICB4X251bSA9PSA4IH4gIuaXpeacrOWFseeUo+WFmiIsCiAgICAgIHhfbnVtID09IDkgfiAi5Y+C5pS/5YWaIiwKICAgICAgeF9udW0gPT0gMTAgfiAi5pel5pys5L+d5a6I5YWaIiwKICAgICAgeF9udW0gPT0gMTEgfiAi56S+5Lya5rCR5Li75YWaIiwKICAgICAgeF9udW0gPT0gMTIgfiAi44OB44O844Og44G/44KJ44GEIiwKICAgICAgeF9udW0gPT0gMTMgfiAi44Gd44Gu5LuWIiwKICAgICAgeF9udW0gPT0gMTQgfiAi5pSv5oyB5pS/5YWa44Gq44GXIiwKICAgICAgeF9udW0gPT0gMTUgfiAi44KP44GL44KJ44Gq44GEIiwKICAgICAgeF9udW0gPT0gMTYgfiAi562U44GI44Gf44GP44Gq44GEIiwKICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8KICAgICkKICB9CgogIGdlbmRlcl9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygKICAgICAgIlEyLjEiLAogICAgICAiUTJfMSIKICAgICkKICApCgogIGFnZV9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygKICAgICAgIlEyLjJfMTMiLAogICAgICAiUTIuMi4xMyIsCiAgICAgICJRMl8yXzEzIiwKICAgICAgIlEyLjJfMiIsCiAgICAgICJRMi4yLjIiLAogICAgICAiUTJfMl8yIgogICAgKQogICkKCiAgZWR1Y2F0aW9uX3JhdyA8LSBnZXRfdmFyKAogICAgZGYsCiAgICBjKAogICAgICAiUTIuMyIsCiAgICAgICJRMl8zIgogICAgKQogICkKCiAgcmVnaW9uX3JhdyA8LSBnZXRfdmFyKAogICAgZGYsCiAgICBjKAogICAgICAiUTIuNF8xIiwKICAgICAgIlEyLjQuMSIsCiAgICAgICJRMl80XzEiCiAgICApCiAgKQoKICBwcmVmZWN0dXJlX3JhdyA8LSBnZXRfdmFyKAogICAgZGYsCiAgICBjKAogICAgICAiUTIuNF8yIiwKICAgICAgIlEyLjQuMiIsCiAgICAgICJRMl80XzIiCiAgICApCiAgKQoKICBpbmNvbWVfZ3Jvc3NfcmF3IDwtIGdldF92YXIoCiAgICBkZiwKICAgIGMoCiAgICAgICJRMi41XzEiLAogICAgICAiUTIuNS4xIiwKICAgICAgIlEyXzVfMSIKICAgICkKICApCgogIGluY29tZV9uZXRfcmF3IDwtIGdldF92YXIoCiAgICBkZiwKICAgIGMoCiAgICAgICJRMi41XzIiLAogICAgICAiUTIuNS4yIiwKICAgICAgIlEyXzVfMiIKICAgICkKICApCgogIHplcm9faW5jb21lX3JlYXNvbl9yYXcgPC0gZ2V0X3ZhcigKICAgIGRmLAogICAgYygKICAgICAgIlEyLjYiLAogICAgICAiUTJfNiIKICAgICkKICApCgogIHNlbGZfaWRlb2xvZ3lfcmF3IDwtIGdldF92YXIoCiAgICBkZiwKICAgIGMoCiAgICAgICJRMjUuMV8xIiwKICAgICAgIlEyNS4xLjEiLAogICAgICAiUTI1XzFfMSIKICAgICkKICApCgogIHBhcnR5X3N1cHBvcnRfcmF3IDwtIGdldF92YXIoCiAgICBkZiwKICAgIGMoCiAgICAgICJRNy4yIiwKICAgICAgIlE3XzIiCiAgICApCiAgKQoKICBjb3Zhcl9pZCA8LSBkZiAlPiUKICAgIHRyYW5zbXV0ZSgKICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoUmVzcG9uc2VJZCksCgogICAgICBmZW1hbGUgPSByZWNvZGVfZmVtYWxlX3N0dWR5MygKICAgICAgICBnZW5kZXJfcmF3CiAgICAgICksCgogICAgICBhZ2UgPSBhc19udW0oCiAgICAgICAgYWdlX3JhdwogICAgICApLAoKICAgICAgY29sbGVnZV9ncmFkID0gcmVjb2RlX2NvbGxlZ2VfZ3JhZF9zdHVkeTMoCiAgICAgICAgZWR1Y2F0aW9uX3JhdwogICAgICApLAoKICAgICAgcmVnaW9uID0gZmFjdG9yX21pc3MoCiAgICAgICAgcmVnaW9uX3JhdwogICAgICApLAoKICAgICAgcHJlZmVjdHVyZSA9IGZhY3Rvcl9taXNzKAogICAgICAgIHByZWZlY3R1cmVfcmF3CiAgICAgICksCgogICAgICBpbmNvbWVfZ3Jvc3MgPSBhc19udW0oCiAgICAgICAgaW5jb21lX2dyb3NzX3JhdwogICAgICApLAoKICAgICAgaW5jb21lX25ldCA9IGFzX251bSgKICAgICAgICBpbmNvbWVfbmV0X3JhdwogICAgICApLAoKICAgICAgaW5jb21lX2dyb3NzX2xvZyA9IGxvZzFwKAogICAgICAgIGluY29tZV9ncm9zcwogICAgICApLAoKICAgICAgaW5jb21lX25ldF9sb2cgPSBsb2cxcCgKICAgICAgICBpbmNvbWVfbmV0CiAgICAgICksCgogICAgICB6ZXJvX2luY29tZV9yZWFzb24gPSBmYWN0b3JfbWlzcygKICAgICAgICB6ZXJvX2luY29tZV9yZWFzb25fcmF3CiAgICAgICksCgogICAgICBzZWxmX2lkZW9sb2d5ID0gcmVjb2RlX3NlbGZfaWRlb2xvZ3lfc3R1ZHkzKAogICAgICAgIHNlbGZfaWRlb2xvZ3lfcmF3CiAgICAgICksCgogICAgICBwYXJ0eV9zdXBwb3J0ID0gcmVjb2RlX3BhcnR5X3N1cHBvcnRfc3R1ZHkzKAogICAgICAgIHBhcnR5X3N1cHBvcnRfcmF3CiAgICAgICksCgogICAgICBwYXJ0eV9zdXBwb3J0X2YgPSBmYWN0b3JfbWlzcygKICAgICAgICBwYXJ0eV9zdXBwb3J0CiAgICAgICksCgogICAgICBwYXJ0eV9zdXBwb3J0X3Byb2ZpbGUgPSBjYW5vbmljYWxpemVfcGFydHlfbmFtZSgKICAgICAgICBwYXJ0eV9zdXBwb3J0CiAgICAgICkKICAgICkgJT4lCiAgICBzZW1pX2pvaW4oCiAgICAgIHZhbGlkX2lkcyAlPiUKICAgICAgICBzZWxlY3QoSUQpLAogICAgICBieSA9ICJJRCIKICAgICkgJT4lCiAgICBkaXN0aW5jdCgKICAgICAgSUQsCiAgICAgIC5rZWVwX2FsbCA9IFRSVUUKICAgICkKCiAgY292YXJfaWQgPC0gY292YXJfaWQgJT4lCiAgICBtdXRhdGUoCiAgICAgIGFnZSA9IGlmX2Vsc2UoCiAgICAgICAgYWdlID49IDE4ICYKICAgICAgICAgIGFnZSA8PSA3OSwKICAgICAgICBhZ2UsCiAgICAgICAgTkFfcmVhbF8KICAgICAgKQogICAgKQoKICBhZ2VfaW1wX29iaiA8LSBtZWFuX2ltcHV0ZSgKICAgIGNvdmFyX2lkJGFnZQogICkKCiAgaW5jb21lX2dyb3NzX2ltcF9vYmogPC0gbWVhbl9pbXB1dGUoCiAgICBjb3Zhcl9pZCRpbmNvbWVfZ3Jvc3NfbG9nCiAgKQoKICBzZWxmX2lkZW9sb2d5X2ltcF9vYmogPC0gbWVhbl9pbXB1dGUoCiAgICBjb3Zhcl9pZCRzZWxmX2lkZW9sb2d5CiAgKQoKICBjb3Zhcl9pZCA8LSBjb3Zhcl9pZCAlPiUKICAgIG11dGF0ZSgKICAgICAgZmVtYWxlX2ltcCA9IGlmX2Vsc2UoCiAgICAgICAgaXMubmEoZmVtYWxlKSwKICAgICAgICAwTCwKICAgICAgICBmZW1hbGUKICAgICAgKSwKCiAgICAgIGZlbWFsZV9taXNzID0gYXMuaW50ZWdlcigKICAgICAgICBpcy5uYShmZW1hbGUpCiAgICAgICksCgogICAgICBjb2xsZWdlX2dyYWRfaW1wID0gaWZfZWxzZSgKICAgICAgICBpcy5uYShjb2xsZWdlX2dyYWQpLAogICAgICAgIDBMLAogICAgICAgIGNvbGxlZ2VfZ3JhZAogICAgICApLAoKICAgICAgY29sbGVnZV9ncmFkX21pc3MgPSBhcy5pbnRlZ2VyKAogICAgICAgIGlzLm5hKGNvbGxlZ2VfZ3JhZCkKICAgICAgKSwKCiAgICAgIGFnZV9pbXAgPSBhZ2VfaW1wX29iaiR2YWx1ZSwKCiAgICAgIGFnZV9taXNzID0gYWdlX2ltcF9vYmokbWlzcywKCiAgICAgIGluY29tZV9ncm9zc19sb2dfaW1wID0KICAgICAgICBpbmNvbWVfZ3Jvc3NfaW1wX29iaiR2YWx1ZSwKCiAgICAgIGluY29tZV9ncm9zc19sb2dfbWlzcyA9CiAgICAgICAgaW5jb21lX2dyb3NzX2ltcF9vYmokbWlzcywKCiAgICAgIHNlbGZfaWRlb2xvZ3lfaW1wID0KICAgICAgICBzZWxmX2lkZW9sb2d5X2ltcF9vYmokdmFsdWUsCgogICAgICBzZWxmX2lkZW9sb2d5X21pc3MgPQogICAgICAgIHNlbGZfaWRlb2xvZ3lfaW1wX29iaiRtaXNzCiAgICApCgogIGNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnkgPC0gY292YXJfaWQgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIG5faWRzID0gbl9kaXN0aW5jdChJRCksCiAgICAgIGZlbWFsZV9taXNzaW5nID0gc3VtKAogICAgICAgIGlzLm5hKGZlbWFsZSkKICAgICAgKSwKICAgICAgYWdlX21pc3NpbmcgPSBzdW0oCiAgICAgICAgaXMubmEoYWdlKQogICAgICApLAogICAgICBjb2xsZWdlX2dyYWRfbWlzc2luZyA9IHN1bSgKICAgICAgICBpcy5uYShjb2xsZWdlX2dyYWQpCiAgICAgICksCiAgICAgIGluY29tZV9ncm9zc19taXNzaW5nID0gc3VtKAogICAgICAgIGlzLm5hKGluY29tZV9ncm9zc19sb2cpCiAgICAgICksCiAgICAgIHNlbGZfaWRlb2xvZ3lfbWlzc2luZyA9IHN1bSgKICAgICAgICBpcy5uYShzZWxmX2lkZW9sb2d5KQogICAgICApLAogICAgICBwYXJ0eV9zdXBwb3J0X21pc3NpbmcgPSBzdW0oCiAgICAgICAgaXMubmEocGFydHlfc3VwcG9ydCkKICAgICAgKQogICAgKQoKICB6ZXJvX2luY29tZV9zdW1tYXJ5IDwtIGNvdmFyX2lkICU+JQogICAgY291bnQoCiAgICAgIHplcm9faW5jb21lX3JlYXNvbiwKICAgICAgbmFtZSA9ICJuIgogICAgKSAlPiUKICAgIGFycmFuZ2UoCiAgICAgIGRlc2MobikKICAgICkKCiAgcHJpbnQoY292YXJpYXRlX21pc3Npbmdfc3VtbWFyeSkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIGNvdmFyX2lkLAogICAgInJlc3BvbmRlbnRfY292YXJpYXRlcy5jc3YiCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgY292YXJpYXRlX21pc3Npbmdfc3VtbWFyeSwKICAgICJjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5LmNzdiIKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICB6ZXJvX2luY29tZV9zdW1tYXJ5LAogICAgInplcm9faW5jb21lX3JlYXNvbl9zdW1tYXJ5LmNzdiIKICApCgoKICBjb25qb2ludF9hbGxfY292IDwtIGNvbmpvaW50X2FsbF9tICU+JQogICAgbGVmdF9qb2luKAogICAgICBjb3Zhcl9pZCwKICAgICAgYnkgPSAiSUQiCiAgICApCgogIGNvdmFyaWF0ZV90ZXJtcyA8LSBjKAogICAgImZlbWFsZV9pbXAiLAogICAgImZlbWFsZV9taXNzIiwKICAgICJhZ2VfaW1wIiwKICAgICJhZ2VfbWlzcyIsCiAgICAiY29sbGVnZV9ncmFkX2ltcCIsCiAgICAiY29sbGVnZV9ncmFkX21pc3MiLAogICAgImluY29tZV9ncm9zc19sb2dfaW1wIiwKICAgICJpbmNvbWVfZ3Jvc3NfbG9nX21pc3MiLAogICAgInNlbGZfaWRlb2xvZ3lfaW1wIiwKICAgICJzZWxmX2lkZW9sb2d5X21pc3MiLAogICAgInBhcnR5X3N1cHBvcnRfZiIKICApCgogIGhhc192YXJpYXRpb24gPC0gZnVuY3Rpb24oZGF0LCB2KSB7CiAgICBpZiAoIXYgJWluJSBuYW1lcyhkYXQpKSB7CiAgICAgIHJldHVybihGQUxTRSkKICAgIH0KCiAgICBkcGx5cjo6bl9kaXN0aW5jdCgKICAgICAgZGF0W1t2XV0sCiAgICAgIG5hLnJtID0gVFJVRQogICAgKSA+IDEKICB9CgogIGNvdmFyaWF0ZV90ZXJtc191c2UgPC0gY292YXJpYXRlX3Rlcm1zWwogICAgbWFwX2xnbCgKICAgICAgY292YXJpYXRlX3Rlcm1zLAogICAgICB+IGhhc192YXJpYXRpb24oCiAgICAgICAgY29uam9pbnRfYWxsX2NvdiwKICAgICAgICAueAogICAgICApCiAgICApCiAgXQoKICBmb3JtdWxhX2NvdiA8LSBhcy5mb3JtdWxhKAogICAgcGFzdGUoCiAgICAgICJzZWxlY3RlZCB+IiwKICAgICAgcGFzdGUoCiAgICAgICAgYygKICAgICAgICAgIGF0dHJfdGVybXMsCiAgICAgICAgICBjb3ZhcmlhdGVfdGVybXNfdXNlCiAgICAgICAgKSwKICAgICAgICBjb2xsYXBzZSA9ICIgKyAiCiAgICAgICkKICAgICkKICApCgogIHJ1bl9hbWNlX2NvdiA8LSBmdW5jdGlvbihkYXQpIHsKICAgIGZlb2xzKAogICAgICBmb3JtdWxhX2NvdiwKICAgICAgZGF0YSA9IGRhdCwKICAgICAgdmNvdiA9IH4gSUQKICAgICkKICB9CgogIG1vZGVsc19ieV9wYXJ0eV9uX2NvdiA8LSBjb25qb2ludF9hbGxfY292ICU+JQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUKICAgIG1hcChydW5fYW1jZV9jb3YpCgogIGNhcHR1cmUub3V0cHV0KAogICAgZXRhYmxlKAogICAgICBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiwKICAgICAgbW9kZWxzX2J5X3BhcnR5X25fY292LAogICAgICBoZWFkZXJzID0gYygKICAgICAgICByZXAoCiAgICAgICAgICAi5YWx5aSJ6YeP44Gq44GXIiwKICAgICAgICAgIGxlbmd0aCgKICAgICAgICAgICAgbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YKICAgICAgICAgICkKICAgICAgICApLAogICAgICAgIHJlcCgKICAgICAgICAgICLlhbHlpInph4/jgYLjgooiLAogICAgICAgICAgbGVuZ3RoKAogICAgICAgICAgICBtb2RlbHNfYnlfcGFydHlfbl9jb3YKICAgICAgICAgICkKICAgICAgICApCiAgICAgICkKICAgICksCiAgICBmaWxlID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAiYW1jZV9ub2Nvdl9hbmRfY292X21vZGVscy50eHQiCiAgICApCiAgKQoKICBhbWNlX3Bsb3RfY292IDwtIG1ha2VfYW1jZV9wbG90X2RmKAogICAgbW9kZWxzX2J5X3BhcnR5X25fY292CiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgYW1jZV9wbG90X2NvdiwKICAgICJhbWNlX2Nvdl9jb2VmZmljaWVudHMuY3N2IgogICkKCgogIHN0dWR5X2xhYmVsIDwtICLlrp/pqJMz77yIMjAyNuW5tO+8iSIKCiAgcF9hbWNlX2NvdiA8LSBnZ3Bsb3QoCiAgICBhbWNlX3Bsb3RfY292LAogICAgYWVzKAogICAgICB4ID0gZXN0aW1hdGVfcHAsCiAgICAgIHkgPSBsYWJlbCwKICAgICAgc2hhcGUgPSBwYXJ0eV9uLAogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sCiAgICAgIGdyb3VwID0gcGFydHlfbgogICAgKQogICkgKwogICAgZ2VvbV92bGluZSgKICAgICAgeGludGVyY2VwdCA9IDAsCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsCiAgICAgIGNvbG9yID0gImdyZXkzNSIKICAgICkgKwogICAgZ2VvbV9lcnJvcmJhcmgoCiAgICAgIGFlcygKICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsCiAgICAgICAgeG1heCA9IGNvbmYuaGlnaF9wcAogICAgICApLAogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKAogICAgICAgIHdpZHRoID0gMC42NQogICAgICApLAogICAgICBoZWlnaHQgPSAwLjE2LAogICAgICBsaW5ld2lkdGggPSAwLjU1LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9wb2ludCgKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgKICAgICAgICB3aWR0aCA9IDAuNjUKICAgICAgKSwKICAgICAgc2l6ZSA9IDIuNSwKICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgc3Ryb2tlID0gMC44CiAgICApICsKICAgIGZhY2V0X2dyaWQoCiAgICAgIGF0dHJpYnV0ZSB+IC4sCiAgICAgIHNjYWxlcyA9ICJmcmVlX3kiLAogICAgICBzcGFjZSA9ICJmcmVlX3kiLAogICAgICBzd2l0Y2ggPSAieSIKICAgICkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKAogICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSB7CiAgICAgICAgcGFzdGUwKHgsICIgcHAiKQogICAgICB9LAogICAgICBicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MoCiAgICAgICAgbiA9IDgKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoCiAgICAgIG5hbWUgPSAi6YG45oqe6IKi5pWwIiwKICAgICAgdmFsdWVzID0gYygKICAgICAgICAiMumBuOaKnuiCoiIgPSAxNiwKICAgICAgICAiM+mBuOaKnuiCoiIgPSAxNywKICAgICAgICAiNOmBuOaKnuiCoiIgPSAxNSwKICAgICAgICAiNemBuOaKnuiCoiIgPSAxCiAgICAgICkKICAgICkgKwogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKAogICAgICBuYW1lID0gIumBuOaKnuiCouaVsCIsCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjLpgbjmip7ogqIiID0gInNvbGlkIiwKICAgICAgICAiM+mBuOaKnuiCoiIgPSAiZGFzaGVkIiwKICAgICAgICAiNOmBuOaKnuiCoiIgPSAiZG90dGVkIiwKICAgICAgICAiNemBuOaKnuiCoiIgPSAiZG90ZGFzaCIKICAgICAgKQogICAgKSArCiAgICBsYWJzKAogICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgKICAgICAgICAi5pS/5YWa5ZCN44Gu5Z+65rqW44Kr44OG44K044Oq77yaIiwKICAgICAgICBwYXJ0eV9yZWZlcmVuY2UsCiAgICAgICAgIuOAgue1jOa4iOWxnuaAp+OBr+WkieWMluOBquOBl+OCkuWfuua6luOBqOOBmeOCi+OAgiIKICAgICAgKSwKICAgICAgeCA9ICLpgbjmip7norrnjofjga7lpInljJYiLAogICAgICB5ID0gTlVMTAogICAgKSArCiAgICB0aGVtZV9idygKICAgICAgYmFzZV9zaXplID0gMTIsCiAgICAgIGJhc2VfZmFtaWx5ID0gZmlndXJlX2ZvbnRfZmFtaWx5CiAgICApICsKICAgIHRoZW1lKAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDE2CiAgICAgICksCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgc2l6ZSA9IDEwCiAgICAgICksCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgZmFjZSA9ICJib2xkIgogICAgICApLAogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgKICAgICAgICBmaWxsID0gImdyZXk5MiIsCiAgICAgICAgY29sb3IgPSAiZ3JleTU1IgogICAgICApLAogICAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBhbmdsZSA9IDAsCiAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICBzaXplID0gMTAKICAgICAgKSwKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoCiAgICAgICAgc2l6ZSA9IDkKICAgICAgKSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIKICAgICAgKQogICAgKQoKICBwcmludChwX2FtY2VfY292KQoKICBzYXZlX3Bsb3QoCiAgICAiYW1jZV9jb3ZfZmFjZXRfbW9kZWwucG5nIiwKICAgIHBfYW1jZV9jb3YsCiAgICB3aWR0aCA9IDEwLjUsCiAgICBoZWlnaHQgPSAxMS41CiAgKQoKCiAgcF9hbWNlX25vY292IDwtIGdncGxvdCgKICAgIGFtY2VfcGxvdF9ub2NvdiwKICAgIGFlcygKICAgICAgeCA9IGVzdGltYXRlX3BwLAogICAgICB5ID0gbGFiZWwsCiAgICAgIHNoYXBlID0gcGFydHlfbiwKICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uLAogICAgICBncm91cCA9IHBhcnR5X24KICAgICkKICApICsKICAgIGdlb21fdmxpbmUoCiAgICAgIHhpbnRlcmNlcHQgPSAwLAogICAgICBsaW5ld2lkdGggPSAwLjQ1LAogICAgICBjb2xvciA9ICJncmV5MzUiCiAgICApICsKICAgIGdlb21fZXJyb3JiYXJoKAogICAgICBhZXMoCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLAogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHAKICAgICAgKSwKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgKICAgICAgICB3aWR0aCA9IDAuNjUKICAgICAgKSwKICAgICAgaGVpZ2h0ID0gMC4xNiwKICAgICAgbGluZXdpZHRoID0gMC41NSwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fcG9pbnQoCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoCiAgICAgICAgd2lkdGggPSAwLjY1CiAgICAgICksCiAgICAgIHNpemUgPSAyLjUsCiAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgZmlsbCA9ICJ3aGl0ZSIsCiAgICAgIHN0cm9rZSA9IDAuOAogICAgKSArCiAgICBmYWNldF9ncmlkKAogICAgICBhdHRyaWJ1dGUgfiAuLAogICAgICBzY2FsZXMgPSAiZnJlZV95IiwKICAgICAgc3BhY2UgPSAiZnJlZV95IiwKICAgICAgc3dpdGNoID0gInkiCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgewogICAgICAgIHBhc3RlMCh4LCAiIHBwIikKICAgICAgfSwKICAgICAgYnJlYWtzID0gc2NhbGVzOjpwcmV0dHlfYnJlYWtzKAogICAgICAgIG4gPSA4CiAgICAgICkKICAgICkgKwogICAgc2NhbGVfc2hhcGVfbWFudWFsKAogICAgICBuYW1lID0gIumBuOaKnuiCouaVsCIsCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjLpgbjmip7ogqIiID0gMTYsCiAgICAgICAgIjPpgbjmip7ogqIiID0gMTcsCiAgICAgICAgIjTpgbjmip7ogqIiID0gMTUsCiAgICAgICAgIjXpgbjmip7ogqIiID0gMQogICAgICApCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgbmFtZSA9ICLpgbjmip7ogqLmlbAiLAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIy6YG45oqe6IKiIiA9ICJzb2xpZCIsCiAgICAgICAgIjPpgbjmip7ogqIiID0gImRhc2hlZCIsCiAgICAgICAgIjTpgbjmip7ogqIiID0gImRvdHRlZCIsCiAgICAgICAgIjXpgbjmip7ogqIiID0gImRvdGRhc2giCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoCiAgICAgICAgIuaUv+WFmuWQjeOBruWfuua6luOCq+ODhuOCtOODqu+8miIsCiAgICAgICAgcGFydHlfcmVmZXJlbmNlLAogICAgICAgICLjgILntYzmuIjlsZ7mgKfjga/lpInljJbjgarjgZfjgpLln7rmupbjgajjgZnjgovjgIIiCiAgICAgICksCiAgICAgIHggPSAi6YG45oqe56K6546H44Gu5aSJ5YyWIiwKICAgICAgeSA9IE5VTEwKICAgICkgKwogICAgdGhlbWVfYncoCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLAogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQogICAgKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIHNpemUgPSAxNgogICAgICApLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSAxMAogICAgICApLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIKICAgICAgKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLAogICAgICAgIGNvbG9yID0gImdyZXk1NSIKICAgICAgKSwKICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoCiAgICAgICAgYW5nbGUgPSAwLAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDEwCiAgICAgICksCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSA5CiAgICAgICksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBmYWNlID0gImJvbGQiCiAgICAgICkKICAgICkKCiAgcHJpbnQocF9hbWNlX25vY292KQoKICBzYXZlX3Bsb3QoCiAgICAiYW1jZV9ub2Nvdl9mYWNldF9tb2RlbC5wbmciLAogICAgcF9hbWNlX25vY292LAogICAgd2lkdGggPSAxMC41LAogICAgaGVpZ2h0ID0gMTEuNQogICkKCgogIHBfaW50ZXJhY3Rpb24gPC0gZ2dwbG90KAogICAgaW50ZXJhY3Rpb25fcGxvdF9kZiwKICAgIGFlcygKICAgICAgeCA9IGVzdGltYXRlX3BwLAogICAgICB5ID0gbGFiZWwsCiAgICAgIHNoYXBlID0gcGFydHlfbl9sYWJlbCwKICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uX2xhYmVsLAogICAgICBncm91cCA9IHBhcnR5X25fbGFiZWwKICAgICkKICApICsKICAgIGdlb21fdmxpbmUoCiAgICAgIHhpbnRlcmNlcHQgPSAwLAogICAgICBsaW5ld2lkdGggPSAwLjQ1LAogICAgICBjb2xvciA9ICJncmV5MzUiCiAgICApICsKICAgIGdlb21fZXJyb3JiYXJoKAogICAgICBhZXMoCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLAogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHAKICAgICAgKSwKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgKICAgICAgICB3aWR0aCA9IDAuNjUKICAgICAgKSwKICAgICAgaGVpZ2h0ID0gMC4xNiwKICAgICAgbGluZXdpZHRoID0gMC41NSwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fcG9pbnQoCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoCiAgICAgICAgd2lkdGggPSAwLjY1CiAgICAgICksCiAgICAgIHNpemUgPSAyLjUsCiAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgZmlsbCA9ICJ3aGl0ZSIsCiAgICAgIHN0cm9rZSA9IDAuOAogICAgKSArCiAgICBmYWNldF9ncmlkKAogICAgICBhdHRyaWJ1dGUgfiAuLAogICAgICBzY2FsZXMgPSAiZnJlZV95IiwKICAgICAgc3BhY2UgPSAiZnJlZV95IiwKICAgICAgc3dpdGNoID0gInkiCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgewogICAgICAgIHBhc3RlMCh4LCAiIHBwIikKICAgICAgfSwKICAgICAgYnJlYWtzID0gc2NhbGVzOjpwcmV0dHlfYnJlYWtzKAogICAgICAgIG4gPSA4CiAgICAgICkKICAgICkgKwogICAgc2NhbGVfc2hhcGVfbWFudWFsKAogICAgICBuYW1lID0gIjLpgbjmip7ogqLmnaHku7bjgajjga7mr5TovIMiLAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIz6YG45oqe6IKiIiA9IDE3LAogICAgICAgICI06YG45oqe6IKiIiA9IDE1LAogICAgICAgICI16YG45oqe6IKiIiA9IDEKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIG5hbWUgPSAiMumBuOaKnuiCouadoeS7tuOBqOOBruavlOi8gyIsCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjPpgbjmip7ogqIiID0gImRhc2hlZCIsCiAgICAgICAgIjTpgbjmip7ogqIiID0gImRvdHRlZCIsCiAgICAgICAgIjXpgbjmip7ogqIiID0gImRvdGRhc2giCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgeCA9ICIy6YG45oqe6IKi5p2h5Lu244Go44Gu5beuIiwKICAgICAgeSA9IE5VTEwKICAgICkgKwogICAgdGhlbWVfYncoCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLAogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQogICAgKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIHNpemUgPSAxNQogICAgICApLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIKICAgICAgKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLAogICAgICAgIGNvbG9yID0gImdyZXk1NSIKICAgICAgKSwKICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoCiAgICAgICAgYW5nbGUgPSAwLAogICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgc2l6ZSA9IDEwCiAgICAgICksCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSA5CiAgICAgICksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBmYWNlID0gImJvbGQiCiAgICAgICkKICAgICkKCiAgcHJpbnQocF9pbnRlcmFjdGlvbikKCiAgc2F2ZV9wbG90KAogICAgImFtY2VfaW50ZXJhY3Rpb25fZGlmZmVyZW5jZV9mcm9tXzJjaG9pY2UucG5nIiwKICAgIHBfaW50ZXJhY3Rpb24sCiAgICB3aWR0aCA9IDEwLjUsCiAgICBoZWlnaHQgPSAxMS41CiAgKQoKCiAgcF9saW5lYXJfdHJlbmQgPC0gZ2dwbG90KAogICAgbGluZWFyX3RyZW5kX3Bsb3RfZGYsCiAgICBhZXMoCiAgICAgIHggPSBlc3RpbWF0ZV9wcCwKICAgICAgeSA9IGxhYmVsCiAgICApCiAgKSArCiAgICBnZW9tX3ZsaW5lKAogICAgICB4aW50ZXJjZXB0ID0gMCwKICAgICAgbGluZXdpZHRoID0gMC40NSwKICAgICAgY29sb3IgPSAiZ3JleTM1IgogICAgKSArCiAgICBnZW9tX2Vycm9yYmFyaCgKICAgICAgYWVzKAogICAgICAgIHhtaW4gPSBjb25mLmxvd19wcCwKICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwCiAgICAgICksCiAgICAgIGhlaWdodCA9IDAuMTYsCiAgICAgIGxpbmV3aWR0aCA9IDAuNTUsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBnZW9tX3BvaW50KAogICAgICBzaXplID0gMi41LAogICAgICBzaGFwZSA9IDIxLAogICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgIGZpbGwgPSAid2hpdGUiLAogICAgICBzdHJva2UgPSAwLjgKICAgICkgKwogICAgZmFjZXRfZ3JpZCgKICAgICAgYXR0cmlidXRlIH4gLiwKICAgICAgc2NhbGVzID0gImZyZWVfeSIsCiAgICAgIHNwYWNlID0gImZyZWVfeSIsCiAgICAgIHN3aXRjaCA9ICJ5IgogICAgKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHsKICAgICAgICBwYXN0ZTAoeCwgIiBwcCIpCiAgICAgIH0sCiAgICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcygKICAgICAgICBuID0gOAogICAgICApCiAgICApICsKICAgIGxhYnMoCiAgICAgIHN1YnRpdGxlID0gIuaoqui7uOOBr+OAgemBuOaKnuiCouaVsOOBjDHjgaTlopfjgYjjgZ/jgajjgY3jga7lsZ7mgKflirnmnpzjga7lpInljJYiLAogICAgICB4ID0gIjHpgbjmip7ogqLlopfliqDlvZPjgZ/jgorjga5BTUNF5aSJ5YyWIiwKICAgICAgeSA9IE5VTEwKICAgICkgKwogICAgdGhlbWVfYncoCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLAogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQogICAgKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIHNpemUgPSAxNQogICAgICApLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSAxMAogICAgICApLAogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgKICAgICAgICBmaWxsID0gImdyZXk5MiIsCiAgICAgICAgY29sb3IgPSAiZ3JleTU1IgogICAgICApLAogICAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBhbmdsZSA9IDAsCiAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICBzaXplID0gMTAKICAgICAgKSwKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoCiAgICAgICAgc2l6ZSA9IDkKICAgICAgKSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KAogICAgICAgIGZhY2UgPSAiYm9sZCIKICAgICAgKQogICAgKQoKICBwcmludChwX2xpbmVhcl90cmVuZCkKCiAgc2F2ZV9wbG90KAogICAgImFtY2VfbGluZWFyX3RyZW5kLnBuZyIsCiAgICBwX2xpbmVhcl90cmVuZCwKICAgIHdpZHRoID0gMTAuNSwKICAgIGhlaWdodCA9IDExLjUKICApCgoKICBoZWF0bWFwX2RmIDwtIGFtY2VfcGxvdF9jb3YgJT4lCiAgICBtdXRhdGUoCiAgICAgIGFic19hbWNlID0gYWJzKAogICAgICAgIGVzdGltYXRlX3BwCiAgICAgICkKICAgICkgJT4lCiAgICBncm91cF9ieShwYXJ0eV9uKSAlPiUKICAgIG11dGF0ZSgKICAgICAgcmFua193aXRoaW5fY29uZGl0aW9uID0KICAgICAgICBtaW5fcmFuaygKICAgICAgICAgIGRlc2MoYWJzX2FtY2UpCiAgICAgICAgKSwKCiAgICAgIG5faW5fY29uZGl0aW9uID0gbigpLAoKICAgICAgcmFua19zY29yZSA9IGlmX2Vsc2UoCiAgICAgICAgbl9pbl9jb25kaXRpb24gPT0gMSwKICAgICAgICAxLAogICAgICAgIDEgLQogICAgICAgICAgKAogICAgICAgICAgICByYW5rX3dpdGhpbl9jb25kaXRpb24gLSAxCiAgICAgICAgICApIC8KICAgICAgICAgICgKICAgICAgICAgICAgbl9pbl9jb25kaXRpb24gLSAxCiAgICAgICAgICApCiAgICAgICkKICAgICkgJT4lCiAgICB1bmdyb3VwKCkKCiAgaGVhdG1hcF9yb3dfb3JkZXIgPC0gaGVhdG1hcF9kZiAlPiUKICAgIGdyb3VwX2J5KAogICAgICBsYWJlbCwKICAgICAgYXR0cmlidXRlCiAgICApICU+JQogICAgc3VtbWFyaXNlKAogICAgICBtZWFuX2Fic19hbWNlID0gbWVhbigKICAgICAgICBhYnNfYW1jZSwKICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgKSwKICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgKSAlPiUKICAgIGFycmFuZ2UoCiAgICAgIGRlc2MobWVhbl9hYnNfYW1jZSkKICAgICkgJT4lCiAgICBwdWxsKGxhYmVsKSAlPiUKICAgIGFzLmNoYXJhY3RlcigpCgogIGhlYXRtYXBfZGYgPC0gaGVhdG1hcF9kZiAlPiUKICAgIG11dGF0ZSgKICAgICAgbGFiZWxfaGVhdCA9IGZhY3RvcigKICAgICAgICBhcy5jaGFyYWN0ZXIobGFiZWwpLAogICAgICAgIGxldmVscyA9IHJldigKICAgICAgICAgIGhlYXRtYXBfcm93X29yZGVyCiAgICAgICAgKQogICAgICApCiAgICApCgogIHBfaGVhdF9hbWNlIDwtIGdncGxvdCgKICAgIGhlYXRtYXBfZGYsCiAgICBhZXMoCiAgICAgIHggPSBwYXJ0eV9uLAogICAgICB5ID0gbGFiZWxfaGVhdCwKICAgICAgZmlsbCA9IGFic19hbWNlCiAgICApCiAgKSArCiAgICBnZW9tX3RpbGUoCiAgICAgIGNvbG9yID0gImdyZXk0NSIsCiAgICAgIGxpbmV3aWR0aCA9IDAuMwogICAgKSArCiAgICBnZW9tX3RleHQoCiAgICAgIGFlcygKICAgICAgICBsYWJlbCA9IHNwcmludGYoCiAgICAgICAgICAiJS4xZiIsCiAgICAgICAgICBlc3RpbWF0ZV9wcAogICAgICAgICksCiAgICAgICAgY29sb3IgPSBpZl9lbHNlKAogICAgICAgICAgcmFua19zY29yZSA+PSAwLjU1LAogICAgICAgICAgIndoaXRlIiwKICAgICAgICAgICJibGFjayIKICAgICAgICApCiAgICAgICksCiAgICAgIHNpemUgPSAzLjEKICAgICkgKwogICAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArCiAgICBmYWNldF9ncmlkKAogICAgICBhdHRyaWJ1dGUgfiAuLAogICAgICBzY2FsZXMgPSAiZnJlZV95IiwKICAgICAgc3BhY2UgPSAiZnJlZV95IiwKICAgICAgc3dpdGNoID0gInkiCiAgICApICsKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQoCiAgICAgIGxvdyA9ICJ3aGl0ZSIsCiAgICAgIGhpZ2ggPSAiZ3JleTIwIiwKICAgICAgbmFtZSA9ICJ8QU1DRXxcbihwcCkiCiAgICApICsKICAgIGxhYnMoCiAgICAgIHN1YnRpdGxlID0gIuOCu+ODq+WGheOBruaVsOWApOOBr+espuWPt+S7mOOBjUFNQ0XvvIhwZXJjZW50YWdlIHBvaW50c++8iSIsCiAgICAgIHggPSAi6YG45oqe6IKi5pWwIiwKICAgICAgeSA9IE5VTEwKICAgICkgKwogICAgdGhlbWVfYncoCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLAogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQogICAgKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBmYWNlID0gImJvbGQiCiAgICAgICksCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsCiAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgKICAgICAgICBmaWxsID0gImdyZXk5MiIsCiAgICAgICAgY29sb3IgPSAiZ3JleTU1IgogICAgICApLAogICAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBhbmdsZSA9IDAsCiAgICAgICAgZmFjZSA9ICJib2xkIgogICAgICApLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBzaXplID0gOC41CiAgICAgICkKICAgICkKCiAgcHJpbnQocF9oZWF0X2FtY2UpCgogIHNhdmVfcGxvdCgKICAgICJhbWNlX2Nvdl9oZWF0bWFwLnBuZyIsCiAgICBwX2hlYXRfYW1jZSwKICAgIHdpZHRoID0gMTAuNSwKICAgIGhlaWdodCA9IDExLjUKICApCgoKICBjb25qb2ludF9jbG9naXQgPC0gY29uam9pbnRfYWxsX20gJT4lCiAgICBtdXRhdGUoCiAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihzZWxlY3RlZCksCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwKICAgICAgdGFza19pZCA9IGZhY3Rvcih0YXNrX2lkKSwKCiAgICAgIHBhcnR5X25hbWUgPSByZWxldmVsX2lmX3ByZXNlbnQoCiAgICAgICAgcGFydHlfbmFtZSwKICAgICAgICBwYXJ0eV9yZWZlcmVuY2UKICAgICAgKSwKCiAgICAgIGdkcF9ncm93dGggPSByZWxldmVsX2lmX3ByZXNlbnQoCiAgICAgICAgZ2RwX2dyb3d0aCwKICAgICAgICBhbGxvd2VkX2Vjb25vbWljX2xldmVscyRnZHBfZ3Jvd3RoWzFdCiAgICAgICksCgogICAgICBuaWtrZWkgPSByZWxldmVsX2lmX3ByZXNlbnQoCiAgICAgICAgbmlra2VpLAogICAgICAgIGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzJG5pa2tlaVsxXQogICAgICApLAoKICAgICAgY3BpID0gcmVsZXZlbF9pZl9wcmVzZW50KAogICAgICAgIGNwaSwKICAgICAgICBhbGxvd2VkX2Vjb25vbWljX2xldmVscyRjcGlbMV0KICAgICAgKSwKCiAgICAgIHVuZW1wbG95bWVudCA9IHJlbGV2ZWxfaWZfcHJlc2VudCgKICAgICAgICB1bmVtcGxveW1lbnQsCiAgICAgICAgYWxsb3dlZF9lY29ub21pY19sZXZlbHMkdW5lbXBsb3ltZW50WzFdCiAgICAgICkKICAgICkKCiAgZm9ybXVsYV9jbG9naXRfbm9jb3YgPC0gYXMuZm9ybXVsYSgKICAgIHBhc3RlMCgKICAgICAgInNlbGVjdGVkIH4gIiwKICAgICAgcGFzdGUoCiAgICAgICAgYXR0cl90ZXJtcywKICAgICAgICBjb2xsYXBzZSA9ICIgKyAiCiAgICAgICksCiAgICAgICIgKyBzdHJhdGEodGFza19pZCkgKyBjbHVzdGVyKElEKSIKICAgICkKICApCgogIHJ1bl9jbG9naXRfbm9jb3YgPC0gZnVuY3Rpb24oZGF0KSB7CiAgICBzdXJ2aXZhbDo6Y2xvZ2l0KAogICAgICBmb3JtdWxhX2Nsb2dpdF9ub2NvdiwKICAgICAgZGF0YSA9IGRhdCwKICAgICAgbWV0aG9kID0gImVmcm9uIgogICAgKQogIH0KCiAgbW9kZWxzX2Nsb2dpdF9ub2NvdiA8LSBjb25qb2ludF9jbG9naXQgJT4lCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQogICAgbWFwKHJ1bl9jbG9naXRfbm9jb3YpCgogIGNhcHR1cmUub3V0cHV0KAogICAgbGFwcGx5KAogICAgICBtb2RlbHNfY2xvZ2l0X25vY292LAogICAgICBzdW1tYXJ5CiAgICApLAogICAgZmlsZSA9IGZpbGUucGF0aCgKICAgICAgb3V0cHV0X2RpciwKICAgICAgImNvbmRpdGlvbmFsX2xvZ2l0X21vZGVscy50eHQiCiAgICApCiAgKQoKICB0aWR5X2Nsb2dpdCA8LSBmdW5jdGlvbihtb2RlbCkgewogICAgcyA8LSBzdW1tYXJ5KG1vZGVsKQogICAgY3QgPC0gYXMuZGF0YS5mcmFtZSgKICAgICAgcyRjb2VmZmljaWVudHMKICAgICkKICAgIGN0JHRlcm0gPC0gcm93bmFtZXMoY3QpCgogICAgc2VfY29sIDwtIGlmICgKICAgICAgInJvYnVzdCBzZSIgJWluJSBuYW1lcyhjdCkKICAgICkgewogICAgICAicm9idXN0IHNlIgogICAgfSBlbHNlIGlmICgKICAgICAgInNlKGNvZWYpIiAlaW4lIG5hbWVzKGN0KQogICAgKSB7CiAgICAgICJzZShjb2VmKSIKICAgIH0gZWxzZSB7CiAgICAgIHN0b3AoIkNoZWNrIGNsb2dpdCIpCiAgICB9CgogICAgcF9jb2wgPC0gaWYgKAogICAgICAiUHIoPnx6fCkiICVpbiUgbmFtZXMoY3QpCiAgICApIHsKICAgICAgIlByKD58enwpIgogICAgfSBlbHNlIGlmICgKICAgICAgIlByKD58dHwpIiAlaW4lIG5hbWVzKGN0KQogICAgKSB7CiAgICAgICJQcig+fHR8KSIKICAgIH0gZWxzZSB7CiAgICAgIE5BX2NoYXJhY3Rlcl8KICAgIH0KCiAgICBjdCAlPiUKICAgICAgYXNfdGliYmxlKCkgJT4lCiAgICAgIHRyYW5zbXV0ZSgKICAgICAgICB0ZXJtID0gdGVybSwKICAgICAgICBlc3RpbWF0ZSA9IGNvZWYsCiAgICAgICAgc3RkLmVycm9yID0gLmRhdGFbW3NlX2NvbF1dLAoKICAgICAgICBwLnZhbHVlID0gaWYgKAogICAgICAgICAgIWlzLm5hKHBfY29sKQogICAgICAgICkgewogICAgICAgICAgLmRhdGFbW3BfY29sXV0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgTkFfcmVhbF8KICAgICAgICB9LAoKICAgICAgICBjb25mLmxvdyA9CiAgICAgICAgICBlc3RpbWF0ZSAtCiAgICAgICAgICAxLjk2ICoKICAgICAgICAgIHN0ZC5lcnJvciwKCiAgICAgICAgY29uZi5oaWdoID0KICAgICAgICAgIGVzdGltYXRlICsKICAgICAgICAgIDEuOTYgKgogICAgICAgICAgc3RkLmVycm9yLAoKICAgICAgICBvZGRzX3JhdGlvID0gZXhwKAogICAgICAgICAgZXN0aW1hdGUKICAgICAgICApLAoKICAgICAgICBvZGRzX3JhdGlvX2xvdyA9IGV4cCgKICAgICAgICAgIGNvbmYubG93CiAgICAgICAgKSwKCiAgICAgICAgb2Rkc19yYXRpb19oaWdoID0gZXhwKAogICAgICAgICAgY29uZi5oaWdoCiAgICAgICAgKQogICAgICApCiAgfQoKICBjbG9naXRfcGxvdF9kZiA8LSBpbWFwX2RmcigKICAgIG1vZGVsc19jbG9naXRfbm9jb3YsCiAgICB+IHRpZHlfY2xvZ2l0KC54KSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIHBhcnR5X24gPSBhcy5jaGFyYWN0ZXIoLnkpCiAgICAgICkKICApICU+JQogICAgbGVmdF9qb2luKAogICAgICB0ZXJtX2xhYmVscywKICAgICAgYnkgPSAidGVybSIKICAgICkgJT4lCiAgICBmaWx0ZXIoCiAgICAgICFpcy5uYShhdHRyaWJ1dGUpCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICBwYXJ0eV9uID0gZmFjdG9yKAogICAgICAgIHBhcnR5X24sCiAgICAgICAgbGV2ZWxzID0gYygKICAgICAgICAgICIyIiwKICAgICAgICAgICIzIiwKICAgICAgICAgICI0IiwKICAgICAgICAgICI1IgogICAgICAgICksCiAgICAgICAgbGFiZWxzID0gYygKICAgICAgICAgICIy6YG45oqe6IKiIiwKICAgICAgICAgICIz6YG45oqe6IKiIiwKICAgICAgICAgICI06YG45oqe6IKiIiwKICAgICAgICAgICI16YG45oqe6IKiIgogICAgICAgICkKICAgICAgKSwKCiAgICAgIGF0dHJpYnV0ZSA9IGZhY3RvcigKICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyCiAgICAgICksCgogICAgICBsYWJlbCA9IGZhY3RvcigKICAgICAgICBsYWJlbCwKICAgICAgICBsZXZlbHMgPSByZXYoCiAgICAgICAgICBsYWJlbF9vcmRlcgogICAgICAgICkKICAgICAgKQogICAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgY2xvZ2l0X3Bsb3RfZGYsCiAgICAiY29uZGl0aW9uYWxfbG9naXRfY29lZmZpY2llbnRzLmNzdiIKICApCgoKICBwX2Nsb2dpdF9vciA8LSBnZ3Bsb3QoCiAgICBjbG9naXRfcGxvdF9kZiwKICAgIGFlcygKICAgICAgeCA9IG9kZHNfcmF0aW8sCiAgICAgIHkgPSBsYWJlbCwKICAgICAgc2hhcGUgPSBwYXJ0eV9uLAogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sCiAgICAgIGdyb3VwID0gcGFydHlfbgogICAgKQogICkgKwogICAgZ2VvbV92bGluZSgKICAgICAgeGludGVyY2VwdCA9IDEsCiAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsCiAgICAgIGNvbG9yID0gImdyZXkzNSIKICAgICkgKwogICAgZ2VvbV9lcnJvcmJhcmgoCiAgICAgIGFlcygKICAgICAgICB4bWluID0gb2Rkc19yYXRpb19sb3csCiAgICAgICAgeG1heCA9IG9kZHNfcmF0aW9faGlnaAogICAgICApLAogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKAogICAgICAgIHdpZHRoID0gMC43MgogICAgICApLAogICAgICBoZWlnaHQgPSAwLjE1LAogICAgICBsaW5ld2lkdGggPSAwLjQ1LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9wb2ludCgKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgKICAgICAgICB3aWR0aCA9IDAuNzIKICAgICAgKSwKICAgICAgc2l6ZSA9IDIuNCwKICAgICAgc3Ryb2tlID0gMC43LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgc2NhbGVfeF9sb2cxMCgKICAgICAgYnJlYWtzID0gc2NhbGVzOjpsb2dfYnJlYWtzKAogICAgICAgIG4gPSA4CiAgICAgICkKICAgICkgKwogICAgc2NhbGVfc2hhcGVfbWFudWFsKAogICAgICB2YWx1ZXMgPSBjKAogICAgICAgICIy6YG45oqe6IKiIiA9IDE2LAogICAgICAgICIz6YG45oqe6IKiIiA9IDE3LAogICAgICAgICI06YG45oqe6IKiIiA9IDE1LAogICAgICAgICI16YG45oqe6IKiIiA9IDEKICAgICAgKQogICAgKSArCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgIjLpgbjmip7ogqIiID0gInNvbGlkIiwKICAgICAgICAiM+mBuOaKnuiCoiIgPSAiZGFzaGVkIiwKICAgICAgICAiNOmBuOaKnuiCoiIgPSAiZG90ZGFzaCIsCiAgICAgICAgIjXpgbjmip7ogqIiID0gInR3b2Rhc2giCiAgICAgICkKICAgICkgKwogICAgZmFjZXRfZ3JpZCgKICAgICAgYXR0cmlidXRlIH4gLiwKICAgICAgc2NhbGVzID0gImZyZWVfeSIsCiAgICAgIHNwYWNlID0gImZyZWVfeSIsCiAgICAgIHN3aXRjaCA9ICJ5IgogICAgKSArCiAgICBsYWJzKAogICAgICB4ID0gIuOCquODg+OCuuavlCIsCiAgICAgIHkgPSBOVUxMLAogICAgICBzaGFwZSA9ICLpgbjmip7ogqLmlbAiLAogICAgICBsaW5ldHlwZSA9ICLpgbjmip7ogqLmlbAiCiAgICApICsKICAgIHRoZW1lX2J3KAogICAgICBiYXNlX3NpemUgPSAxMiwKICAgICAgYmFzZV9mYW1pbHkgPSBmaWd1cmVfZm9udF9mYW1pbHkKICAgICkgKwogICAgdGhlbWUoCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgZmFjZSA9ICJib2xkIgogICAgICApLAogICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLAogICAgICAgIGNvbG9yID0gImdyZXk1NSIKICAgICAgKSwKICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoCiAgICAgICAgYW5nbGUgPSAwLAogICAgICAgIGZhY2UgPSAiYm9sZCIKICAgICAgKSwKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoCiAgICAgICAgc2l6ZSA9IDguNQogICAgICApCiAgICApCgogIHByaW50KHBfY2xvZ2l0X29yKQoKICBzYXZlX3Bsb3QoCiAgICAiY2xvZ2l0X29kZHNyYXRpb19ub2Nvdi5wbmciLAogICAgcF9jbG9naXRfb3IsCiAgICB3aWR0aCA9IDEwLjUsCiAgICBoZWlnaHQgPSAxMS41CiAgKQoKCiAgZXhwZXJpbWVudGFsX3BhcnR5X25hbWVzIDwtIGFzLmNoYXJhY3RlcigKICAgIHBhcnR5X2xldmVsc191c2UKICApCgogIGNvbmpvaW50X21hdGNoIDwtIGNvbmpvaW50X2FsbF9jb3YgJT4lCiAgICBtdXRhdGUoCiAgICAgIHBhcnR5X25hbWVfY2hyID0gYXMuY2hhcmFjdGVyKHBhcnR5X25hbWUpLAogICAgICAKICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9IGlmX2Vsc2UoCiAgICAgICAgcGFydHlfc3VwcG9ydF9wcm9maWxlICVpbiUgZXhwZXJpbWVudGFsX3BhcnR5X25hbWVzLAogICAgICAgIHBhcnR5X3N1cHBvcnRfcHJvZmlsZSwKICAgICAgICBOQV9jaGFyYWN0ZXJfCiAgICAgICksCiAgICAgIAogICAgICBwYXJ0eV9tYXRjaCA9IGNhc2Vfd2hlbigKICAgICAgICBpcy5uYShzdXBwb3J0X3BhcnR5X3ZhbGlkKSB+IE5BX2ludGVnZXJfLAogICAgICAgIHBhcnR5X25hbWVfY2hyID09IHN1cHBvcnRfcGFydHlfdmFsaWQgfiAxTCwKICAgICAgICBUUlVFIH4gMEwKICAgICAgKQogICAgKSAlPiUKICAgIGZpbHRlcigKICAgICAgIWlzLm5hKHBhcnR5X21hdGNoKQogICAgKQoKICBwYXJ0eV9tYXRjaF9zYW1wbGUgPC0gY29uam9pbnRfbWF0Y2ggJT4lCiAgICBkaXN0aW5jdCgKICAgICAgSUQsCiAgICAgIHBhcnR5X24sCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQKICAgICkgJT4lCiAgICBjb3VudCgKICAgICAgcGFydHlfbiwKICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCwKICAgICAgbmFtZSA9ICJuX3Jlc3BvbmRlbnRzIgogICAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcGFydHlfbWF0Y2hfc2FtcGxlLAogICAgInBhcnR5X21hdGNoX3NhbXBsZS5jc3YiCiAgKQoKCiAgZm9ybXVsYV9wYXJ0eV9tYXRjaF9vdmVyYWxsIDwtIGFzLmZvcm11bGEoCiAgICBwYXN0ZSgKICAgICAgInNlbGVjdGVkIH4iLAogICAgICBwYXN0ZSgKICAgICAgICBjKAogICAgICAgICAgInBhcnR5X25hbWUiLAogICAgICAgICAgInBhcnR5X21hdGNoIiwKICAgICAgICAgIGVjb25vbWljX2F0dHJfdGVybXMKICAgICAgICApLAogICAgICAgIGNvbGxhcHNlID0gIiArICIKICAgICAgKQogICAgKQogICkKCiAgcnVuX3BhcnR5X21hdGNoX292ZXJhbGwgPC0gZnVuY3Rpb24oZGF0KSB7CiAgICBmZW9scygKICAgICAgZm9ybXVsYV9wYXJ0eV9tYXRjaF9vdmVyYWxsLAogICAgICBkYXRhID0gZGF0LAogICAgICB2Y292ID0gfiBJRAogICAgKQogIH0KCiAgbW9kZWxzX3BhcnR5X21hdGNoX2J5X24gPC0gY29uam9pbnRfbWF0Y2ggJT4lCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQogICAgbWFwKHJ1bl9wYXJ0eV9tYXRjaF9vdmVyYWxsKQoKICBtX3BhcnR5X21hdGNoX2ludGVyYWN0aW9uIDwtIGZlb2xzKAogICAgc2VsZWN0ZWQgfgogICAgICBwYXJ0eV9uX2YgKgogICAgICBwYXJ0eV9tYXRjaCArCiAgICAgIHBhcnR5X25hbWUgKwogICAgICBnZHBfZ3Jvd3RoICsKICAgICAgbmlra2VpICsKICAgICAgY3BpICsKICAgICAgdW5lbXBsb3ltZW50LAogICAgZGF0YSA9IGNvbmpvaW50X21hdGNoLAogICAgdmNvdiA9IH4gSUQKICApCgogIGNhcHR1cmUub3V0cHV0KAogICAgbGFwcGx5KAogICAgICBtb2RlbHNfcGFydHlfbWF0Y2hfYnlfbiwKICAgICAgc3VtbWFyeQogICAgKSwKICAgIGZpbGUgPSBmaWxlLnBhdGgoCiAgICAgIG91dHB1dF9kaXIsCiAgICAgICJwYXJ0eV9tYXRjaF9tb2RlbHNfYnlfY2hvaWNlX251bWJlci50eHQiCiAgICApCiAgKQoKICBjYXB0dXJlLm91dHB1dCgKICAgIHN1bW1hcnkobV9wYXJ0eV9tYXRjaF9pbnRlcmFjdGlvbiksCiAgICBmaWxlID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAicGFydHlfbWF0Y2hfaW50ZXJhY3Rpb25fbW9kZWwudHh0IgogICAgKQogICkKCiAgZXh0cmFjdF9wYXJ0eV9tYXRjaF90ZXJtIDwtIGZ1bmN0aW9uKG1vZGVsKSB7CiAgICBvdXQgPC0gdGlkeV9maXhlc3QobW9kZWwpICU+JQogICAgICBmaWx0ZXIodGVybSA9PSAicGFydHlfbWF0Y2giKQogICAgCiAgICBpZiAobnJvdyhvdXQpID09IDApIHsKICAgICAgcmV0dXJuKAogICAgICAgIHRpYmJsZSgKICAgICAgICAgIHRlcm0gPSAicGFydHlfbWF0Y2giLAogICAgICAgICAgZXN0aW1hdGUgPSBOQV9yZWFsXywKICAgICAgICAgIHN0ZC5lcnJvciA9IE5BX3JlYWxfLAogICAgICAgICAgc3RhdGlzdGljID0gTkFfcmVhbF8sCiAgICAgICAgICBwLnZhbHVlID0gTkFfcmVhbF8sCiAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLAogICAgICAgICAgY29uZi5oaWdoID0gTkFfcmVhbF8KICAgICAgICApCiAgICAgICkKICAgIH0KICAgIAogICAgb3V0CiAgfQoKICBwYXJ0eV9tYXRjaF9jb2VmX2RmIDwtIGltYXBfZGZyKAogICAgbW9kZWxzX3BhcnR5X21hdGNoX2J5X24sCiAgICB+IGV4dHJhY3RfcGFydHlfbWF0Y2hfdGVybSgueCkgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBzdXBwb3J0X2dyb3VwID0gIuWFqOS9kyIsCiAgICAgICAgc3VwcG9ydF9ncm91cF9sYWJlbCA9ICLlhajkvZMiLAogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKC55KQogICAgICApCiAgKSAlPiUKICAgIG11dGF0ZSgKICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwKICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwKICAgICAgY29uZi5oaWdoX3BwID0gY29uZi5oaWdoICogMTAwLAogICAgICAKICAgICAgcGFydHlfbl9sYWJlbCA9IGZhY3RvcigKICAgICAgICBwYXJ0eV9uLAogICAgICAgIGxldmVscyA9IDI6NSwKICAgICAgICBsYWJlbHMgPSBjKAogICAgICAgICAgIjLpgbjmip7ogqIiLAogICAgICAgICAgIjPpgbjmip7ogqIiLAogICAgICAgICAgIjTpgbjmip7ogqIiLAogICAgICAgICAgIjXpgbjmip7ogqIiCiAgICAgICAgKQogICAgICApCiAgICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICBwYXJ0eV9tYXRjaF9jb2VmX2RmLAogICAgInBhcnR5X21hdGNoX2NvZWZmaWNpZW50cy5jc3YiCiAgKQoKCiAgdGFyZ2V0X3N1cHBvcnRfZ3JvdXBzIDwtIGMoCiAgICAi6Ieq55Sx5rCR5Li75YWaIiwKICAgICLkuK3pgZPmlLnpnanpgKPlkIgiLAogICAgIueri+aGsuawkeS4u+WFmiIsCiAgICAi5Y+C5pS/5YWaIgogICkKCiAgdGFyZ2V0X3N1cHBvcnRfbGFiZWxzIDwtIGMoCiAgICAi6Ieq55Sx5rCR5Li75YWaIiAgID0gIuiHquawkeWFmuaUr+aMgeiAhSIsCiAgICAi5Lit6YGT5pS56Z2p6YCj5ZCIIiA9ICLkuK3pgZPmlLnpnanmlK/mjIHogIUiLAogICAgIueri+aGsuawkeS4u+WFmiIgICA9ICLnq4vmhrLmlK/mjIHogIUiLAogICAgIuWPguaUv+WFmiIgICAgICAgPSAi5Y+C5pS/5YWa5pSv5oyB6ICFIgogICkKCiAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfc2FtcGxlIDwtIGNvbmpvaW50X21hdGNoICU+JQogICAgZGlzdGluY3QoCiAgICAgIElELAogICAgICBwYXJ0eV9uLAogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkCiAgICApICU+JQogICAgZmlsdGVyKAogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkICVpbiUgdGFyZ2V0X3N1cHBvcnRfZ3JvdXBzCiAgICApICU+JQogICAgY291bnQoCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQsCiAgICAgIHBhcnR5X24sCiAgICAgIG5hbWUgPSAibl9yZXNwb25kZW50cyIKICAgICkgJT4lCiAgICBtdXRhdGUoCiAgICAgIHN1cHBvcnRfZ3JvdXBfbGFiZWwgPSByZWNvZGUoCiAgICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCwKICAgICAgICAhISF0YXJnZXRfc3VwcG9ydF9sYWJlbHMKICAgICAgKQogICAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfc2FtcGxlLAogICAgInBhcnR5X21hdGNoX3N1Ymdyb3VwX3NhbXBsZS5jc3YiCiAgKQoKICBzdXBwb3J0X2dyb3VwX3RvdGFsX24gPC0gY29uam9pbnRfbWF0Y2ggJT4lCiAgICBkaXN0aW5jdCgKICAgICAgSUQsCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQKICAgICkgJT4lCiAgICBmaWx0ZXIoCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgJWluJSB0YXJnZXRfc3VwcG9ydF9ncm91cHMKICAgICkgJT4lCiAgICBjb3VudCgKICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCwKICAgICAgbmFtZSA9ICJuX3RvdGFsIgogICAgKQoKICBmb3JtdWxhX3BhcnR5X21hdGNoX3N1Ymdyb3VwIDwtIGFzLmZvcm11bGEoCiAgICBwYXN0ZSgKICAgICAgInNlbGVjdGVkIH4iLAogICAgICBwYXN0ZSgKICAgICAgICBjKAogICAgICAgICAgInBhcnR5X21hdGNoIiwKICAgICAgICAgIGVjb25vbWljX2F0dHJfdGVybXMKICAgICAgICApLAogICAgICAgIGNvbGxhcHNlID0gIiArICIKICAgICAgKQogICAgKQogICkKCiAgcnVuX3BhcnR5X21hdGNoX3N1Ymdyb3VwIDwtIGZ1bmN0aW9uKGRhdCkgewogICAgZmVvbHMoCiAgICAgIGZvcm11bGFfcGFydHlfbWF0Y2hfc3ViZ3JvdXAsCiAgICAgIGRhdGEgPSBkYXQsCiAgICAgIHZjb3YgPSB+IElECiAgICApCiAgfQoKICBlc3RpbWF0ZV9wYXJ0eV9tYXRjaF9zdWJncm91cCA8LSBmdW5jdGlvbigKICAgICAgZGF0LAogICAgICBzdXBwb3J0X2dyb3VwX3ZhbHVlCiAgKSB7CiAgICBtYXBfZGZyKAogICAgICAyOjUsCiAgICAgIGZ1bmN0aW9uKG5fdmFsdWUpIHsKICAgICAgICAKICAgICAgICBkYXRfbiA8LSBkYXQgJT4lCiAgICAgICAgICBmaWx0ZXIoCiAgICAgICAgICAgIHBhcnR5X24gPT0gbl92YWx1ZSwKICAgICAgICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9PSBzdXBwb3J0X2dyb3VwX3ZhbHVlCiAgICAgICAgICApCiAgICAgICAgCiAgICAgICAgbl9pZHMgPC0gbl9kaXN0aW5jdChkYXRfbiRJRCkKICAgICAgICAKICAgICAgICBpZiAobnJvdyhkYXRfbikgPT0gMCB8fCBuX2lkcyA9PSAwKSB7CiAgICAgICAgICByZXR1cm4oCiAgICAgICAgICAgIHRpYmJsZSgKICAgICAgICAgICAgICB0ZXJtID0gInBhcnR5X21hdGNoIiwKICAgICAgICAgICAgICBlc3RpbWF0ZSA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHN0ZC5lcnJvciA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHN0YXRpc3RpYyA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHAudmFsdWUgPSBOQV9yZWFsXywKICAgICAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIGNvbmYuaGlnaCA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHN1cHBvcnRfZ3JvdXAgPSBzdXBwb3J0X2dyb3VwX3ZhbHVlLAogICAgICAgICAgICAgIHN1cHBvcnRfZ3JvdXBfbGFiZWwgPSB1bm5hbWUoCiAgICAgICAgICAgICAgICB0YXJnZXRfc3VwcG9ydF9sYWJlbHNbW3N1cHBvcnRfZ3JvdXBfdmFsdWVdXQogICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgcGFydHlfbiA9IG5fdmFsdWUsCiAgICAgICAgICAgICAgbl9pZHMgPSBuX2lkcwogICAgICAgICAgICApCiAgICAgICAgICApCiAgICAgICAgfQogICAgICAgIAogICAgICAgIG1vZGVsX24gPC0gdHJ5Q2F0Y2goCiAgICAgICAgICBydW5fcGFydHlfbWF0Y2hfc3ViZ3JvdXAoZGF0X24pLAogICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSBOVUxMCiAgICAgICAgKQogICAgICAgIAogICAgICAgIGlmIChpcy5udWxsKG1vZGVsX24pKSB7CiAgICAgICAgICByZXR1cm4oCiAgICAgICAgICAgIHRpYmJsZSgKICAgICAgICAgICAgICB0ZXJtID0gInBhcnR5X21hdGNoIiwKICAgICAgICAgICAgICBlc3RpbWF0ZSA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHN0ZC5lcnJvciA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHN0YXRpc3RpYyA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHAudmFsdWUgPSBOQV9yZWFsXywKICAgICAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIGNvbmYuaGlnaCA9IE5BX3JlYWxfLAogICAgICAgICAgICAgIHN1cHBvcnRfZ3JvdXAgPSBzdXBwb3J0X2dyb3VwX3ZhbHVlLAogICAgICAgICAgICAgIHN1cHBvcnRfZ3JvdXBfbGFiZWwgPSB1bm5hbWUoCiAgICAgICAgICAgICAgICB0YXJnZXRfc3VwcG9ydF9sYWJlbHNbW3N1cHBvcnRfZ3JvdXBfdmFsdWVdXQogICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgcGFydHlfbiA9IG5fdmFsdWUsCiAgICAgICAgICAgICAgbl9pZHMgPSBuX2lkcwogICAgICAgICAgICApCiAgICAgICAgICApCiAgICAgICAgfQogICAgICAgIAogICAgICAgIGV4dHJhY3RfcGFydHlfbWF0Y2hfdGVybShtb2RlbF9uKSAlPiUKICAgICAgICAgIG11dGF0ZSgKICAgICAgICAgICAgc3VwcG9ydF9ncm91cCA9IHN1cHBvcnRfZ3JvdXBfdmFsdWUsCiAgICAgICAgICAgIHN1cHBvcnRfZ3JvdXBfbGFiZWwgPSB1bm5hbWUoCiAgICAgICAgICAgICAgdGFyZ2V0X3N1cHBvcnRfbGFiZWxzW1tzdXBwb3J0X2dyb3VwX3ZhbHVlXV0KICAgICAgICAgICAgKSwKICAgICAgICAgICAgcGFydHlfbiA9IG5fdmFsdWUsCiAgICAgICAgICAgIG5faWRzID0gbl9pZHMKICAgICAgICAgICkKICAgICAgfQogICAgKQogIH0KCiAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZiA8LSBtYXBfZGZyKAogICAgdGFyZ2V0X3N1cHBvcnRfZ3JvdXBzLAogICAgfiBlc3RpbWF0ZV9wYXJ0eV9tYXRjaF9zdWJncm91cCgKICAgICAgY29uam9pbnRfbWF0Y2gsCiAgICAgIC54CiAgICApCiAgKSAlPiUKICAgIGxlZnRfam9pbigKICAgICAgc3VwcG9ydF9ncm91cF90b3RhbF9uLAogICAgICBieSA9IGMoCiAgICAgICAgInN1cHBvcnRfZ3JvdXAiID0gInN1cHBvcnRfcGFydHlfdmFsaWQiCiAgICAgICkKICAgICkgJT4lCiAgICBtdXRhdGUoCiAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwKICAgICAgcGFydHlfbl9sYWJlbCA9IGZhY3RvcigKICAgICAgICBwYXJ0eV9uLAogICAgICAgIGxldmVscyA9IDI6NSwKICAgICAgICBsYWJlbHMgPSBjKAogICAgICAgICAgIjLpgbjmip7ogqIiLAogICAgICAgICAgIjPpgbjmip7ogqIiLAogICAgICAgICAgIjTpgbjmip7ogqIiLAogICAgICAgICAgIjXpgbjmip7ogqIiCiAgICAgICAgKQogICAgICApCiAgICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICBwYXJ0eV9tYXRjaF9zdWJncm91cF9jb2VmX2RmLAogICAgInBhcnR5X21hdGNoX3N1Ymdyb3VwX2NvZWZmaWNpZW50cy5jc3YiCiAgKQoKCiAgcGFydHlfbWF0Y2hfcGxvdF9kZl9hbGwgPC0gYmluZF9yb3dzKAogICAgcGFydHlfbWF0Y2hfY29lZl9kZiAlPiUKICAgICAgbXV0YXRlKHBhbmVsID0gIm92ZXJhbGwiKSwKICAgIHBhcnR5X21hdGNoX3N1Ymdyb3VwX2NvZWZfZGYgJT4lCiAgICAgIG11dGF0ZShwYW5lbCA9ICJzdWJncm91cCIpCiAgKSAlPiUKICAgIGZpbHRlcigKICAgICAgaXMuZmluaXRlKGVzdGltYXRlX3BwKSwKICAgICAgaXMuZmluaXRlKGNvbmYubG93X3BwKSwKICAgICAgaXMuZmluaXRlKGNvbmYuaGlnaF9wcCkKICAgICkKCiAgaWYgKG5yb3cocGFydHlfbWF0Y2hfcGxvdF9kZl9hbGwpID09IDApIHsKICAgIHN0b3AoIkNoZWNrIGRhdGEiKQogIH0KCiAgeV9yYW5nZV9tYXRjaCA8LSByYW5nZSgKICAgIGMoCiAgICAgIHBhcnR5X21hdGNoX3Bsb3RfZGZfYWxsJGNvbmYubG93X3BwLAogICAgICBwYXJ0eV9tYXRjaF9wbG90X2RmX2FsbCRjb25mLmhpZ2hfcHAKICAgICksCiAgICBuYS5ybSA9IFRSVUUKICApCgogIHlfc3Bhbl9tYXRjaCA8LSBkaWZmKHlfcmFuZ2VfbWF0Y2gpCgogIGlmICghaXMuZmluaXRlKHlfc3Bhbl9tYXRjaCkgfHwgeV9zcGFuX21hdGNoIDw9IDApIHsKICAgIHlfc3Bhbl9tYXRjaCA8LSA1CiAgfQoKICB5X3BhZF9tYXRjaCA8LSBtYXgoMS4yLCAwLjEwICogeV9zcGFuX21hdGNoKQoKICB5X2xpbWl0c19tYXRjaCA8LSBjKAogICAgeV9yYW5nZV9tYXRjaFsxXSAtIHlfcGFkX21hdGNoLAogICAgeV9yYW5nZV9tYXRjaFsyXSArIHlfcGFkX21hdGNoCiAgKQoKCiAgdGhlbWVfcGFydHlfbWF0Y2hfYncgPC0gdGhlbWVfYncoCiAgICBiYXNlX3NpemUgPSAxMiwKICAgIGJhc2VfZmFtaWx5ID0gZmlndXJlX2ZvbnRfZmFtaWx5CiAgKSArCiAgICB0aGVtZSgKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZSgKICAgICAgICBsaW5ld2lkdGggPSAwLjMwLAogICAgICAgIGNvbG9yID0gImdyZXk4OCIKICAgICAgKSwKICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KAogICAgICAgIGxpbmV3aWR0aCA9IDAuNjUsCiAgICAgICAgY29sb3IgPSAiYmxhY2siCiAgICAgICksCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLAogICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgZmFjZSA9ICJib2xkIgogICAgICApLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSByZWwoMC45MikKICAgICAgKSwKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oCiAgICAgICAgOCwgMTAsIDgsIDgKICAgICAgKQogICAgKQoKCiAgbWFrZV9wYXJ0eV9tYXRjaF9wYW5lbF9wbG90IDwtIGZ1bmN0aW9uKAogICAgICBkYXQsCiAgICAgIHBhbmVsX3RpdGxlLAogICAgICBwYW5lbF9zdWJ0aXRsZSA9IE5VTEwsCiAgICAgIGJhc2Vfc2l6ZSA9IDExLAogICAgICBzaG93X3lfdGl0bGUgPSBUUlVFLAogICAgICBzaG93X3hfdGl0bGUgPSBUUlVFCiAgKSB7CiAgICBnZ3Bsb3QoCiAgICAgIGRhdCwKICAgICAgYWVzKAogICAgICAgIHggPSBwYXJ0eV9uLAogICAgICAgIHkgPSBlc3RpbWF0ZV9wcAogICAgICApCiAgICApICsKICAgICAgZ2VvbV9saW5lKAogICAgICAgIGxpbmV3aWR0aCA9IDAuODAsCiAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgIG5hLnJtID0gVFJVRQogICAgICApICsKICAgICAgZ2VvbV9lcnJvcmJhcigKICAgICAgICBhZXMoCiAgICAgICAgICB5bWluID0gY29uZi5sb3dfcHAsCiAgICAgICAgICB5bWF4ID0gY29uZi5oaWdoX3BwCiAgICAgICAgKSwKICAgICAgICB3aWR0aCA9IDAuMDc1LAogICAgICAgIGxpbmV3aWR0aCA9IDAuODAsCiAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgIG5hLnJtID0gVFJVRQogICAgICApICsKICAgICAgZ2VvbV9sYWJlbCgKICAgICAgICBhZXMoCiAgICAgICAgICBsYWJlbCA9IHNwcmludGYoIiUuMWYgcHAiLCBlc3RpbWF0ZV9wcCkKICAgICAgICApLAogICAgICAgIHNpemUgPSAzLjQ1LAogICAgICAgIGZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseSwKICAgICAgICBsYWJlbC5zaXplID0gMCwKICAgICAgICBsYWJlbC5wYWRkaW5nID0gdW5pdCgKICAgICAgICAgIDAuMTIsCiAgICAgICAgICAibGluZXMiCiAgICAgICAgKSwKICAgICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICkgKwogICAgICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgICAgYnJlYWtzID0gMjo1LAogICAgICAgIGxhYmVscyA9IHBhc3RlMCgKICAgICAgICAgIDI6NSwKICAgICAgICAgICLpgbjmip7ogqIiCiAgICAgICAgKSwKICAgICAgICBsaW1pdHMgPSBjKDEuNzIsIDUuMjgpCiAgICAgICkgKwogICAgICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgewogICAgICAgICAgcGFzdGUwKHgsICIgcHAiKQogICAgICAgIH0sCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjpwcmV0dHlfYnJlYWtzKG4gPSA2KSwKICAgICAgICBleHBhbmQgPSBleHBhbnNpb24oCiAgICAgICAgICBtdWx0ID0gYygwLjA1LCAwLjA4KQogICAgICAgICkKICAgICAgKSArCiAgICAgIGNvb3JkX2NhcnRlc2lhbigKICAgICAgICB5bGltID0geV9saW1pdHNfbWF0Y2gKICAgICAgKSArCiAgICAgIGxhYnMoCiAgICAgICAgdGl0bGUgPSBwYW5lbF90aXRsZSwKICAgICAgICBzdWJ0aXRsZSA9IHBhbmVsX3N1YnRpdGxlLAogICAgICAgIHggPSBpZiAoc2hvd194X3RpdGxlKSAi6YG45oqe6IKi5pWwIiBlbHNlIE5VTEwsCiAgICAgICAgeSA9IGlmIChzaG93X3lfdGl0bGUpICLkuIDoh7TjgZfjgZ/loLTlkIjjga7pgbjmip7norrnjofjga7lpInljJYiIGVsc2UgTlVMTAogICAgICApICsKICAgICAgdGhlbWVfYncoCiAgICAgICAgYmFzZV9zaXplID0gYmFzZV9zaXplLAogICAgICAgIGJhc2VfZmFtaWx5ID0gZmlndXJlX2ZvbnRfZmFtaWx5CiAgICAgICkgKwogICAgICB0aGVtZV9wYXJ0eV9tYXRjaF9idyArCiAgICAgIHRoZW1lKAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoCiAgICAgICAgICBmYWNlID0gImJvbGQiCiAgICAgICAgKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBpZiAoc2hvd194X3RpdGxlKSBlbGVtZW50X3RleHQoKSBlbHNlIGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBpZiAoc2hvd195X3RpdGxlKSBlbGVtZW50X3RleHQoKSBlbHNlIGVsZW1lbnRfYmxhbmsoKQogICAgICApCiAgfQoKICBtYWtlX3N1cHBvcnRfZ3JvdXBfdGl0bGUgPC0gZnVuY3Rpb24oCiAgICAgIHN1cHBvcnRfZ3JvdXBfdmFsdWUKICApIHsKICAgIG5fdmFsdWUgPC0gc3VwcG9ydF9ncm91cF90b3RhbF9uICU+JQogICAgICBmaWx0ZXIoCiAgICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9PSBzdXBwb3J0X2dyb3VwX3ZhbHVlCiAgICAgICkgJT4lCiAgICAgIHB1bGwobl90b3RhbCkKICAgIAogICAgaWYgKGxlbmd0aChuX3ZhbHVlKSA9PSAwIHx8IGlzLm5hKG5fdmFsdWUpKSB7CiAgICAgIG5fdmFsdWUgPC0gMAogICAgfQogICAgCiAgICBwYXN0ZTAoCiAgICAgIHRhcmdldF9zdXBwb3J0X2xhYmVsc1tbc3VwcG9ydF9ncm91cF92YWx1ZV1dLAogICAgICAiXG4obj0iLAogICAgICBzY2FsZXM6OmNvbW1hKG5fdmFsdWUpLAogICAgICAiKSIKICAgICkKICB9CgoKICBwX3BhcnR5X21hdGNoX292ZXJhbGwgPC0gbWFrZV9wYXJ0eV9tYXRjaF9wYW5lbF9wbG90KAogICAgcGFydHlfbWF0Y2hfY29lZl9kZiwKICAgIHBhbmVsX3RpdGxlID0gTlVMTCwKICAgIHBhbmVsX3N1YnRpdGxlID0KICAgICAgIuS4iuauteOBr+WFqOS9k+OAgeS4i+auteOBr+aUr+aMgeaUv+WFmuWIpe+8iOiHquawkeODu+S4remBk+aUuemdqeODu+eri+aGsuODu+WPguaUv++8ieOAguaUv+WFmuWQjeOBqOe1jOa4iOWxnuaAp+OCkue1seWItuOBl+OBn+e3muW9oueiuueOh+ODouODh+ODq+OAgiIsCiAgICBiYXNlX3NpemUgPSAxMiwKICAgIHNob3dfeV90aXRsZSA9IFRSVUUsCiAgICBzaG93X3hfdGl0bGUgPSBUUlVFCiAgKQoKCiAgcF9wYXJ0eV9tYXRjaF9sZHAgPC0gbWFrZV9wYXJ0eV9tYXRjaF9wYW5lbF9wbG90KAogICAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZiAlPiUKICAgICAgZmlsdGVyKHN1cHBvcnRfZ3JvdXAgPT0gIuiHqueUseawkeS4u+WFmiIpLAogICAgcGFuZWxfdGl0bGUgPSBtYWtlX3N1cHBvcnRfZ3JvdXBfdGl0bGUoIuiHqueUseawkeS4u+WFmiIpLAogICAgYmFzZV9zaXplID0gMTAsCiAgICBzaG93X3lfdGl0bGUgPSBUUlVFLAogICAgc2hvd194X3RpdGxlID0gVFJVRQogICkKCiAgcF9wYXJ0eV9tYXRjaF9jaHIgPC0gbWFrZV9wYXJ0eV9tYXRjaF9wYW5lbF9wbG90KAogICAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZiAlPiUKICAgICAgZmlsdGVyKHN1cHBvcnRfZ3JvdXAgPT0gIuS4remBk+aUuemdqemAo+WQiCIpLAogICAgcGFuZWxfdGl0bGUgPSBtYWtlX3N1cHBvcnRfZ3JvdXBfdGl0bGUoIuS4remBk+aUuemdqemAo+WQiCIpLAogICAgYmFzZV9zaXplID0gMTAsCiAgICBzaG93X3lfdGl0bGUgPSBGQUxTRSwKICAgIHNob3dfeF90aXRsZSA9IFRSVUUKICApCgogIHBfcGFydHlfbWF0Y2hfY2RwIDwtIG1ha2VfcGFydHlfbWF0Y2hfcGFuZWxfcGxvdCgKICAgIHBhcnR5X21hdGNoX3N1Ymdyb3VwX2NvZWZfZGYgJT4lCiAgICAgIGZpbHRlcihzdXBwb3J0X2dyb3VwID09ICLnq4vmhrLmsJHkuLvlhZoiKSwKICAgIHBhbmVsX3RpdGxlID0gbWFrZV9zdXBwb3J0X2dyb3VwX3RpdGxlKCLnq4vmhrLmsJHkuLvlhZoiKSwKICAgIGJhc2Vfc2l6ZSA9IDEwLAogICAgc2hvd195X3RpdGxlID0gRkFMU0UsCiAgICBzaG93X3hfdGl0bGUgPSBUUlVFCiAgKQoKICBwX3BhcnR5X21hdGNoX3NhbnNlaSA8LSBtYWtlX3BhcnR5X21hdGNoX3BhbmVsX3Bsb3QoCiAgICBwYXJ0eV9tYXRjaF9zdWJncm91cF9jb2VmX2RmICU+JQogICAgICBmaWx0ZXIoc3VwcG9ydF9ncm91cCA9PSAi5Y+C5pS/5YWaIiksCiAgICBwYW5lbF90aXRsZSA9IG1ha2Vfc3VwcG9ydF9ncm91cF90aXRsZSgi5Y+C5pS/5YWaIiksCiAgICBiYXNlX3NpemUgPSAxMCwKICAgIHNob3dfeV90aXRsZSA9IEZBTFNFLAogICAgc2hvd194X3RpdGxlID0gVFJVRQogICkKCiAgcF9wYXJ0eV9tYXRjaF9ib3R0b20gPC0KICAgIHBfcGFydHlfbWF0Y2hfbGRwICsKICAgIHBfcGFydHlfbWF0Y2hfY2hyICsKICAgIHBfcGFydHlfbWF0Y2hfY2RwICsKICAgIHBfcGFydHlfbWF0Y2hfc2Fuc2VpICsKICAgIHBhdGNod29yazo6cGxvdF9sYXlvdXQobmNvbCA9IDQpCgogIHBfcGFydHlfbWF0Y2ggPC0KICAgIHBfcGFydHlfbWF0Y2hfb3ZlcmFsbCAvCiAgICBwX3BhcnR5X21hdGNoX2JvdHRvbSArCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KAogICAgICBoZWlnaHRzID0gYygxLjI1LCAxKQogICAgKQoKICBwcmludChwX3BhcnR5X21hdGNoKQoKICBzYXZlX3Bsb3QoCiAgICAicGFydHlfbWF0Y2hfZWZmZWN0X2NvbWJpbmVkLnBuZyIsCiAgICBwX3BhcnR5X21hdGNoLAogICAgd2lkdGggPSAxNCwKICAgIGhlaWdodCA9IDguOAogICkKCgogIHJlbGF0aXZlX2N1ZV9tYXAgPC0gYygKICAgIHBhcnR5X25hbWUgPSAicGFydHkiLAogICAgZ2RwX2dyb3d0aCA9ICJlY29ub21pYyIsCiAgICBuaWtrZWkgPSAiZWNvbm9taWMiLAogICAgY3BpID0gImVjb25vbWljIiwKICAgIHVuZW1wbG95bWVudCA9ICJlY29ub21pYyIKICApCgogIG1lYW5fYWJzb2x1dGVfcGFpcndpc2VfZGlmZmVyZW5jZSA8LSBmdW5jdGlvbih4KSB7CiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXQoKICAgIGlmIChsZW5ndGgoeCkgPCAyKSB7CiAgICAgIHJldHVybihOQV9yZWFsXykKICAgIH0KCiAgICBwYWlyd2lzZV9kaWZmZXJlbmNlcyA8LSBjb21ibigKICAgICAgeCwKICAgICAgMiwKICAgICAgRlVOID0gZnVuY3Rpb24oeikgYWJzKHpbMV0gLSB6WzJdKQogICAgKQoKICAgIG1lYW4ocGFpcndpc2VfZGlmZmVyZW5jZXMpCiAgfQoKICBsaW5lYXJfc2xvcGUgPC0gZnVuY3Rpb24oeSwgeCkgewogICAga2VlcCA8LSBpcy5maW5pdGUoeSkgJiBpcy5maW5pdGUoeCkKICAgIHkgPC0geVtrZWVwXQogICAgeCA8LSB4W2tlZXBdCgogICAgaWYgKGxlbmd0aCh5KSA8IDIgfHwgbGVuZ3RoKHVuaXF1ZSh4KSkgPCAyKSB7CiAgICAgIHJldHVybihOQV9yZWFsXykKICAgIH0KCiAgICB1bm5hbWUoY29lZihsbSh5IH4geCkpWzJdKQogIH0KCiAgYm9vdHN0cmFwX3R3b19zaWRlZF9wIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHggPC0geFtpcy5maW5pdGUoeCldCiAgICBCX3ZhbGlkIDwtIGxlbmd0aCh4KQoKICAgIGlmIChCX3ZhbGlkID09IDApIHsKICAgICAgcmV0dXJuKE5BX3JlYWxfKQogICAgfQoKICAgIHBfbG93ZXIgPC0gKDEgKyBzdW0oeCA8PSAwKSkgLyAoQl92YWxpZCArIDEpCiAgICBwX3VwcGVyIDwtICgxICsgc3VtKHggPj0gMCkpIC8gKEJfdmFsaWQgKyAxKQoKICAgIG1pbigxLCAyICogbWluKHBfbG93ZXIsIHBfdXBwZXIpKQogIH0KCiAgc2FmZV9xdWFudGlsZSA8LSBmdW5jdGlvbih4LCBwcm9iYWJpbGl0eSkgewogICAgeCA8LSB4W2lzLmZpbml0ZSh4KV0KCiAgICBpZiAobGVuZ3RoKHgpID09IDApIHsKICAgICAgcmV0dXJuKE5BX3JlYWxfKQogICAgfQoKICAgIHVubmFtZSgKICAgICAgcXVhbnRpbGUoCiAgICAgICAgeCwKICAgICAgICBwcm9icyA9IHByb2JhYmlsaXR5LAogICAgICAgIHR5cGUgPSA2LAogICAgICAgIG5hLnJtID0gVFJVRQogICAgICApCiAgICApCiAgfQoKICBwcmVwYXJlX3JlbGF0aXZlX2N1ZV9hbmFseXNpcyA8LSBmdW5jdGlvbihkYXRhLCBjdWVfbWFwKSB7CiAgICBhdHRyaWJ1dGVzIDwtIG5hbWVzKGN1ZV9tYXApCgogICAgcmVxdWlyZWRfY29sdW1ucyA8LSBjKAogICAgICAiSUQiLAogICAgICAicGFydHlfbiIsCiAgICAgICJzZWxlY3RlZCIsCiAgICAgIGF0dHJpYnV0ZXMKICAgICkKCiAgICBtaXNzaW5nX2NvbHVtbnMgPC0gc2V0ZGlmZigKICAgICAgcmVxdWlyZWRfY29sdW1ucywKICAgICAgbmFtZXMoZGF0YSkKICAgICkKCiAgICBpZiAobGVuZ3RoKG1pc3NpbmdfY29sdW1ucykgPiAwKSB7CiAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpCiAgICB9CgogICAgaWYgKCFhbGwodW5uYW1lKGN1ZV9tYXApICVpbiUgYygicGFydHkiLCAiZWNvbm9taWMiKSkpIHsKICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikKICAgIH0KCiAgICBhbmFseXNpc19kYXRhIDwtIGRhdGEgJT4lCiAgICAgIHNlbGVjdCgKICAgICAgICBJRCwKICAgICAgICBwYXJ0eV9uLAogICAgICAgIHNlbGVjdGVkLAogICAgICAgIGFsbF9vZihhdHRyaWJ1dGVzKQogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSksCiAgICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHNlbGVjdGVkKSwKICAgICAgICBhY3Jvc3MoCiAgICAgICAgICBhbGxfb2YoYXR0cmlidXRlcyksCiAgICAgICAgICBhcy5jaGFyYWN0ZXIKICAgICAgICApCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICAhaXMubmEoSUQpLAogICAgICAgIHBhcnR5X24gJWluJSAyOjUsCiAgICAgICAgc2VsZWN0ZWQgJWluJSBjKDBMLCAxTCkKICAgICAgKQoKICAgIG9ic2VydmVkX2NvbmRpdGlvbnMgPC0gc29ydCgKICAgICAgdW5pcXVlKGFuYWx5c2lzX2RhdGEkcGFydHlfbikKICAgICkKCiAgICBpZiAoIWlkZW50aWNhbChvYnNlcnZlZF9jb25kaXRpb25zLCAyOjUpKSB7CiAgICAgIHN0b3AoIkNoZWNrIikKICAgIH0KCiAgICBsb25nX2RhdGEgPC0gYW5hbHlzaXNfZGF0YSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBhbGxfb2YoYXR0cmlidXRlcyksCiAgICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwKICAgICAgICB2YWx1ZXNfdG8gPSAibGV2ZWwiCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcigKICAgICAgICAhaXMubmEobGV2ZWwpLAogICAgICAgIGxldmVsICE9ICIiCiAgICAgICkKCiAgICBleHBlY3RlZF9jZWxscyA8LSBsb25nX2RhdGEgJT4lCiAgICAgIGRpc3RpbmN0KAogICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICBsZXZlbAogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgYXR0cmlidXRlX29yZGVyID0gbWF0Y2goCiAgICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgICBhdHRyaWJ1dGVzCiAgICAgICAgKQogICAgICApICU+JQogICAgICBhcnJhbmdlKAogICAgICAgIGF0dHJpYnV0ZV9vcmRlciwKICAgICAgICBhdHRyaWJ1dGUsCiAgICAgICAgbGV2ZWwKICAgICAgKSAlPiUKICAgICAgc2VsZWN0KC1hdHRyaWJ1dGVfb3JkZXIpICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgY2VsbF9rZXkgPSBwYXN0ZSgKICAgICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICAgIGxldmVsLAogICAgICAgICAgc2VwID0gIlxyIgogICAgICAgICkKICAgICAgKQoKICAgIHJlc3BvbmRlbnRfY2VsbCA8LSBsb25nX2RhdGEgJT4lCiAgICAgIGdyb3VwX2J5KAogICAgICAgIHBhcnR5X24sCiAgICAgICAgSUQsCiAgICAgICAgYXR0cmlidXRlLAogICAgICAgIGxldmVsCiAgICAgICkgJT4lCiAgICAgIHN1bW1hcmlzZSgKICAgICAgICB5X3N1bSA9IHN1bShzZWxlY3RlZCksCiAgICAgICAgbl9vYnMgPSBuKCksCiAgICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgICApICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgY2VsbF9rZXkgPSBwYXN0ZSgKICAgICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICAgIGxldmVsLAogICAgICAgICAgc2VwID0gIlxyIgogICAgICAgICkKICAgICAgKQoKICAgIGNvbmRpdGlvbl9vYmplY3RzIDwtIGxhcHBseSgKICAgICAgMjo1LAogICAgICBmdW5jdGlvbihuX3ZhbHVlKSB7CiAgICAgICAgY29uZGl0aW9uX2RhdGEgPC0gcmVzcG9uZGVudF9jZWxsICU+JQogICAgICAgICAgZmlsdGVyKAogICAgICAgICAgICBwYXJ0eV9uID09IG5fdmFsdWUKICAgICAgICAgICkKCiAgICAgICAgaWRfdmFsdWVzIDwtIHNvcnQoCiAgICAgICAgICB1bmlxdWUoY29uZGl0aW9uX2RhdGEkSUQpCiAgICAgICAgKQogICAgICAgIG5faWRzIDwtIGxlbmd0aChpZF92YWx1ZXMpCiAgICAgICAgbl9jZWxscyA8LSBucm93KGV4cGVjdGVkX2NlbGxzKQoKICAgICAgICBpZiAobl9pZHMgPT0gMCkgewogICAgICAgICAgc3RvcCgiQ2hlY2siKQogICAgICAgIH0KCiAgICAgICAgeV9tYXRyaXggPC0gbWF0cml4KAogICAgICAgICAgMCwKICAgICAgICAgIG5yb3cgPSBuX2lkcywKICAgICAgICAgIG5jb2wgPSBuX2NlbGxzLAogICAgICAgICAgZGltbmFtZXMgPSBsaXN0KAogICAgICAgICAgICBpZF92YWx1ZXMsCiAgICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5CiAgICAgICAgICApCiAgICAgICAgKQoKICAgICAgICBuX21hdHJpeCA8LSBtYXRyaXgoCiAgICAgICAgICAwLAogICAgICAgICAgbnJvdyA9IG5faWRzLAogICAgICAgICAgbmNvbCA9IG5fY2VsbHMsCiAgICAgICAgICBkaW1uYW1lcyA9IGxpc3QoCiAgICAgICAgICAgIGlkX3ZhbHVlcywKICAgICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkKICAgICAgICAgICkKICAgICAgICApCgogICAgICAgIHJvd19pbmRleCA8LSBtYXRjaCgKICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJElELAogICAgICAgICAgaWRfdmFsdWVzCiAgICAgICAgKQogICAgICAgIGNvbHVtbl9pbmRleCA8LSBtYXRjaCgKICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJGNlbGxfa2V5LAogICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkKICAgICAgICApCgogICAgICAgIHlfbWF0cml4W2NiaW5kKHJvd19pbmRleCwgY29sdW1uX2luZGV4KV0gPC0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJHlfc3VtCiAgICAgICAgbl9tYXRyaXhbY2JpbmQocm93X2luZGV4LCBjb2x1bW5faW5kZXgpXSA8LQogICAgICAgICAgY29uZGl0aW9uX2RhdGEkbl9vYnMKCiAgICAgICAgaWYgKGFueShjb2xTdW1zKG5fbWF0cml4KSA9PSAwKSkgewogICAgICAgICAgbWlzc2luZ19jZWxscyA8LSBleHBlY3RlZF9jZWxscyRjZWxsX2tleVsKICAgICAgICAgICAgY29sU3VtcyhuX21hdHJpeCkgPT0gMAogICAgICAgICAgXQoKICAgICAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQogICAgICAgIH0KCiAgICAgICAgbGlzdCgKICAgICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLAogICAgICAgICAgaWRzID0gaWRfdmFsdWVzLAogICAgICAgICAgY2VsbF9pbmZvID0gZXhwZWN0ZWRfY2VsbHMsCiAgICAgICAgICB5X21hdHJpeCA9IHlfbWF0cml4LAogICAgICAgICAgbl9tYXRyaXggPSBuX21hdHJpeAogICAgICAgICkKICAgICAgfQogICAgKQoKICAgIG5hbWVzKGNvbmRpdGlvbl9vYmplY3RzKSA8LSBhcy5jaGFyYWN0ZXIoMjo1KQoKICAgIGxpc3QoCiAgICAgIGN1ZV9tYXAgPSBjdWVfbWFwLAogICAgICBhdHRyaWJ1dGVzID0gYXR0cmlidXRlcywKICAgICAgY29uZGl0aW9ucyA9IGNvbmRpdGlvbl9vYmplY3RzCiAgICApCiAgfQoKICBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcyA8LSBmdW5jdGlvbigKICAgICAgcHJlcGFyZWQsCiAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA9IE5VTEwKICApIHsKICAgIGNvbmRpdGlvbl9yZXN1bHRzIDwtIGxhcHBseSgKICAgICAgbmFtZXMocHJlcGFyZWQkY29uZGl0aW9ucyksCiAgICAgIGZ1bmN0aW9uKGNvbmRpdGlvbl9uYW1lKSB7CiAgICAgICAgb2JqZWN0IDwtIHByZXBhcmVkJGNvbmRpdGlvbnNbW2NvbmRpdGlvbl9uYW1lXV0KCiAgICAgICAgaWYgKGlzLm51bGwoY2x1c3Rlcl93ZWlnaHRzKSkgewogICAgICAgICAgd2VpZ2h0cyA8LSByZXAoCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIGxlbmd0aChvYmplY3QkaWRzKQogICAgICAgICAgKQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB3ZWlnaHRzIDwtIGNsdXN0ZXJfd2VpZ2h0c1tbY29uZGl0aW9uX25hbWVdXQogICAgICAgIH0KCiAgICAgICAgaWYgKGxlbmd0aCh3ZWlnaHRzKSAhPSBsZW5ndGgob2JqZWN0JGlkcykpIHsKICAgICAgICAgIHN0b3AoIkNoZWNrIikKICAgICAgICB9CgogICAgICAgIG51bWVyYXRvciA8LSBhcy5udW1lcmljKAogICAgICAgICAgY3Jvc3Nwcm9kKAogICAgICAgICAgICB3ZWlnaHRzLAogICAgICAgICAgICBvYmplY3QkeV9tYXRyaXgKICAgICAgICAgICkKICAgICAgICApCgogICAgICAgIGRlbm9taW5hdG9yIDwtIGFzLm51bWVyaWMoCiAgICAgICAgICBjcm9zc3Byb2QoCiAgICAgICAgICAgIHdlaWdodHMsCiAgICAgICAgICAgIG9iamVjdCRuX21hdHJpeAogICAgICAgICAgKQogICAgICAgICkKCiAgICAgICAgaWYgKGFueShkZW5vbWluYXRvciA8PSAwKSkgewogICAgICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpCiAgICAgICAgfQoKICAgICAgICBtYXJnaW5hbF9tZWFucyA8LSBudW1lcmF0b3IgLyBkZW5vbWluYXRvcgoKICAgICAgICBtbV90YWJsZSA8LSBvYmplY3QkY2VsbF9pbmZvICU+JQogICAgICAgICAgdHJhbnNtdXRlKAogICAgICAgICAgICBwYXJ0eV9uID0gb2JqZWN0JHBhcnR5X24sCiAgICAgICAgICAgIGF0dHJpYnV0ZSwKICAgICAgICAgICAgbGV2ZWwsCiAgICAgICAgICAgIG1hcmdpbmFsX21lYW4gPSBtYXJnaW5hbF9tZWFucwogICAgICAgICAgKQoKICAgICAgICBhdHRyaWJ1dGVfdGFibGUgPC0gbW1fdGFibGUgJT4lCiAgICAgICAgICBncm91cF9ieSgKICAgICAgICAgICAgcGFydHlfbiwKICAgICAgICAgICAgYXR0cmlidXRlCiAgICAgICAgICApICU+JQogICAgICAgICAgc3VtbWFyaXNlKAogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICAgICAgICBtZWFuX2Fic29sdXRlX3BhaXJ3aXNlX2RpZmZlcmVuY2UoCiAgICAgICAgICAgICAgICBtYXJnaW5hbF9tZWFuCiAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgbl9sZXZlbHMgPSBuKCksCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgICAgICkgJT4lCiAgICAgICAgICBtdXRhdGUoCiAgICAgICAgICAgIGN1ZV9mYW1pbHkgPSB1bm5hbWUoCiAgICAgICAgICAgICAgcHJlcGFyZWQkY3VlX21hcFthdHRyaWJ1dGVdCiAgICAgICAgICAgICksCiAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eSA9IDEgLyBwYXJ0eV9uLAogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlIC8KICAgICAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eQogICAgICAgICAgKQoKICAgICAgICBjdWVfdGFibGVfbG9uZyA8LSBhdHRyaWJ1dGVfdGFibGUgJT4lCiAgICAgICAgICBncm91cF9ieSgKICAgICAgICAgICAgcGFydHlfbiwKICAgICAgICAgICAgY3VlX2ZhbWlseQogICAgICAgICAgKSAlPiUKICAgICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSA9IG1lYW4oCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgKSwKICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9IG1lYW4oCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwKICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgKSwKICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgICAgICAgKQoKICAgICAgICBwYXJ0eV90YWJsZSA8LSBjdWVfdGFibGVfbG9uZyAlPiUKICAgICAgICAgIGZpbHRlcigKICAgICAgICAgICAgY3VlX2ZhbWlseSA9PSAicGFydHkiCiAgICAgICAgICApICU+JQogICAgICAgICAgdHJhbnNtdXRlKAogICAgICAgICAgICBwYXJ0eV9uLAogICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkCiAgICAgICAgICApCgogICAgICAgIGVjb25vbWljX3RhYmxlIDwtIGN1ZV90YWJsZV9sb25nICU+JQogICAgICAgICAgZmlsdGVyKAogICAgICAgICAgICBjdWVfZmFtaWx5ID09ICJlY29ub21pYyIKICAgICAgICAgICkgJT4lCiAgICAgICAgICB0cmFuc211dGUoCiAgICAgICAgICAgIHBhcnR5X24sCiAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UsCiAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQKICAgICAgICAgICkKCiAgICAgICAgY3VlX3RhYmxlIDwtIGZ1bGxfam9pbigKICAgICAgICAgIHBhcnR5X3RhYmxlLAogICAgICAgICAgZWNvbm9taWNfdGFibGUsCiAgICAgICAgICBieSA9ICJwYXJ0eV9uIgogICAgICAgICkgJT4lCiAgICAgICAgICBtdXRhdGUoCiAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eSA9IDEgLyBwYXJ0eV9uLAoKICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZSA9CiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSArCiAgICAgICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSwKCiAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgKwogICAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsCgogICAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UgPSBpZl9lbHNlKAogICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2UgPiAwLAogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgLwogICAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgICAgICBOQV9yZWFsXwogICAgICAgICAgICApLAoKICAgICAgICAgICAgcmVsYXRpdmVfZWNvbm9taWNfd2VpZ2h0X3BhaXJ3aXNlID0KICAgICAgICAgICAgICAxIC0gcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlLAoKICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlX2FkanVzdGVkID0gaWZfZWxzZSgKICAgICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID4gMCwKICAgICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIC8KICAgICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsCiAgICAgICAgICAgICAgTkFfcmVhbF8KICAgICAgICAgICAgKSwKCiAgICAgICAgICAgIHJlbGF0aXZlX2Vjb25vbWljX3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgICAgICAgMSAtIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCwKCiAgICAgICAgICAgIGFkanVzdG1lbnRfaWRlbnRpdHlfZGlmZmVyZW5jZSA9CiAgICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlX2FkanVzdGVkIC0KICAgICAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZQogICAgICAgICAgKQoKICAgICAgICBpZiAoCiAgICAgICAgICBhbnkoCiAgICAgICAgICAgIGFicyhjdWVfdGFibGUkYWRqdXN0bWVudF9pZGVudGl0eV9kaWZmZXJlbmNlKSA+IDFlLTEwLAogICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICkKICAgICAgICApIHsKICAgICAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpCiAgICAgICAgfQoKICAgICAgICBsaXN0KAogICAgICAgICAgbWFyZ2luYWxfbWVhbnMgPSBtbV90YWJsZSwKICAgICAgICAgIGF0dHJpYnV0ZV9pbXBvcnRhbmNlID0gYXR0cmlidXRlX3RhYmxlLAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UgPSBjdWVfdGFibGUKICAgICAgICApCiAgICAgIH0KICAgICkKCiAgICBsaXN0KAogICAgICBtYXJnaW5hbF9tZWFucyA9IGJpbmRfcm93cygKICAgICAgICBsYXBwbHkoCiAgICAgICAgICBjb25kaXRpb25fcmVzdWx0cywKICAgICAgICAgIGZ1bmN0aW9uKHgpIHgkbWFyZ2luYWxfbWVhbnMKICAgICAgICApCiAgICAgICksCiAgICAgIGF0dHJpYnV0ZV9pbXBvcnRhbmNlID0gYmluZF9yb3dzKAogICAgICAgIGxhcHBseSgKICAgICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzLAogICAgICAgICAgZnVuY3Rpb24oeCkgeCRhdHRyaWJ1dGVfaW1wb3J0YW5jZQogICAgICAgICkKICAgICAgKSwKICAgICAgY3VlX2ltcG9ydGFuY2UgPSBiaW5kX3Jvd3MoCiAgICAgICAgbGFwcGx5KAogICAgICAgICAgY29uZGl0aW9uX3Jlc3VsdHMsCiAgICAgICAgICBmdW5jdGlvbih4KSB4JGN1ZV9pbXBvcnRhbmNlCiAgICAgICAgKQogICAgICApICU+JQogICAgICAgIGFycmFuZ2UocGFydHlfbikKICAgICkKICB9CgogIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMgPC0gZnVuY3Rpb24oY3VlX2ltcG9ydGFuY2UpIHsKICAgIGN1ZV9pbXBvcnRhbmNlIDwtIGN1ZV9pbXBvcnRhbmNlICU+JQogICAgICBhcnJhbmdlKHBhcnR5X24pCgogICAgaWYgKCFpZGVudGljYWwoY3VlX2ltcG9ydGFuY2UkcGFydHlfbiwgMjo1KSkgewogICAgICBzdG9wKCJDaGVjayByZWxhdGl2ZSB3ZWlnaHQiKQogICAgfQoKICAgIHggPC0gY3VlX2ltcG9ydGFuY2UkcGFydHlfbgoKICAgIGMoCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSA9CiAgICAgICAgbGluZWFyX3Nsb3BlKAogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAogICAgICAgICAgeAogICAgICAgICksCgogICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICBsaW5lYXJfc2xvcGUoCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAogICAgICAgICAgeAogICAgICAgICkKICAgICkKICB9CgogIHJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwIDwtIGZ1bmN0aW9uKAogICAgICBwcmVwYXJlZCwKICAgICAgQiwKICAgICAgc2VlZCwKICAgICAgcHJvZ3Jlc3NfZXZlcnkgPSAxMDAKICApIHsKICAgIHNldC5zZWVkKHNlZWQpCgogICAgY29uZGl0aW9uX3Jlc3VsdHMgPC0gdmVjdG9yKAogICAgICAibGlzdCIsCiAgICAgIEIKICAgICkKCiAgICBzbG9wZV9uYW1lcyA8LSBjKAogICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwKICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIsCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiCiAgICApCgogICAgc2xvcGVfbWF0cml4IDwtIG1hdHJpeCgKICAgICAgTkFfcmVhbF8sCiAgICAgIG5yb3cgPSBCLAogICAgICBuY29sID0gbGVuZ3RoKHNsb3BlX25hbWVzKSwKICAgICAgZGltbmFtZXMgPSBsaXN0KAogICAgICAgIE5VTEwsCiAgICAgICAgc2xvcGVfbmFtZXMKICAgICAgKQogICAgKQoKICAgIGZvciAoYiBpbiBzZXFfbGVuKEIpKSB7CiAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA8LSBsYXBwbHkoCiAgICAgICAgcHJlcGFyZWQkY29uZGl0aW9ucywKICAgICAgICBmdW5jdGlvbihvYmplY3QpIHsKICAgICAgICAgIG5faWRzIDwtIGxlbmd0aChvYmplY3QkaWRzKQoKICAgICAgICAgIHNhbXBsZWRfcG9zaXRpb25zIDwtIHNhbXBsZS5pbnQoCiAgICAgICAgICAgIG4gPSBuX2lkcywKICAgICAgICAgICAgc2l6ZSA9IG5faWRzLAogICAgICAgICAgICByZXBsYWNlID0gVFJVRQogICAgICAgICAgKQoKICAgICAgICAgIHRhYnVsYXRlKAogICAgICAgICAgICBzYW1wbGVkX3Bvc2l0aW9ucywKICAgICAgICAgICAgbmJpbnMgPSBuX2lkcwogICAgICAgICAgKQogICAgICAgIH0KICAgICAgKQoKICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcygKICAgICAgICBwcmVwYXJlZCA9IHByZXBhcmVkLAogICAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA9IGNsdXN0ZXJfd2VpZ2h0cwogICAgICApCgogICAgICBjb25kaXRpb25fcmVzdWx0c1tbYl1dIDwtCiAgICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyRjdWVfaW1wb3J0YW5jZSAlPiUKICAgICAgICBzZWxlY3QoCiAgICAgICAgICBwYXJ0eV9uLAogICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSwKICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UsCiAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLAogICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwKICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZQogICAgICAgICkgJT4lCiAgICAgICAgbXV0YXRlKAogICAgICAgICAgYm9vdHN0cmFwX3JlcGxpY2F0aW9uID0gYiwKICAgICAgICAgIC5iZWZvcmUgPSAxCiAgICAgICAgKQoKICAgICAgc2xvcGVfbWF0cml4W2IsIF0gPC0gZXN0aW1hdGVfcmVsYXRpdmVfY3VlX3Nsb3BlcygKICAgICAgICBib290c3RyYXBfZXN0aW1hdGVzJGN1ZV9pbXBvcnRhbmNlCiAgICAgICkKCiAgICAgIGlmICgKICAgICAgICBwcm9ncmVzc19ldmVyeSA+IDAgJiYKICAgICAgICAoYiAlJSBwcm9ncmVzc19ldmVyeSA9PSAwIHx8IGIgPT0gQikKICAgICAgKSB7CiAgICAgICAgbWVzc2FnZSgiQm9vdHN0cmFwOiAiLCBiLCAiLyIsIEIpCiAgICAgIH0KICAgIH0KCiAgICBsaXN0KAogICAgICBjb25kaXRpb25fZXN0aW1hdGVzID0gYmluZF9yb3dzKAogICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzCiAgICAgICksCiAgICAgIHNsb3BlcyA9IGFzX3RpYmJsZSgKICAgICAgICBzbG9wZV9tYXRyaXgKICAgICAgKSAlPiUKICAgICAgICBtdXRhdGUoCiAgICAgICAgICBib290c3RyYXBfcmVwbGljYXRpb24gPSByb3dfbnVtYmVyKCksCiAgICAgICAgICAuYmVmb3JlID0gMQogICAgICAgICkKICAgICkKICB9CgogIHN1bW1hcmlzZV9jb25kaXRpb25faW50ZXJ2YWxzIDwtIGZ1bmN0aW9uKAogICAgICBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSwKICAgICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzCiAgKSB7CiAgICBzdGF0aXN0aWNzIDwtIGMoCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwKICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIKICAgICkKCiAgICBvYnNlcnZlZF9sb25nIDwtIG9ic2VydmVkX2N1ZV9pbXBvcnRhbmNlICU+JQogICAgICBzZWxlY3QoCiAgICAgICAgcGFydHlfbiwKICAgICAgICBhbGxfb2Yoc3RhdGlzdGljcykKICAgICAgKSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBhbGxfb2Yoc3RhdGlzdGljcyksCiAgICAgICAgbmFtZXNfdG8gPSAic3RhdGlzdGljIiwKICAgICAgICB2YWx1ZXNfdG8gPSAiZXN0aW1hdGUiCiAgICAgICkKCiAgICBib290c3RyYXBfbG9uZyA8LSBib290c3RyYXBfY29uZGl0aW9uX3Jlc3VsdHMgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gYWxsX29mKHN0YXRpc3RpY3MpLAogICAgICAgIG5hbWVzX3RvID0gInN0YXRpc3RpYyIsCiAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIgogICAgICApICU+JQogICAgICBncm91cF9ieSgKICAgICAgICBwYXJ0eV9uLAogICAgICAgIHN0YXRpc3RpYwogICAgICApICU+JQogICAgICBzdW1tYXJpc2UoCiAgICAgICAgY29uZl9sb3cgPSBzYWZlX3F1YW50aWxlKAogICAgICAgICAgdmFsdWUsCiAgICAgICAgICAwLjAyNQogICAgICAgICksCiAgICAgICAgY29uZl9oaWdoID0gc2FmZV9xdWFudGlsZSgKICAgICAgICAgIHZhbHVlLAogICAgICAgICAgMC45NzUKICAgICAgICApLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKQoKICAgIG9ic2VydmVkX2xvbmcgJT4lCiAgICAgIGxlZnRfam9pbigKICAgICAgICBib290c3RyYXBfbG9uZywKICAgICAgICBieSA9IGMoCiAgICAgICAgICAicGFydHlfbiIsCiAgICAgICAgICAic3RhdGlzdGljIgogICAgICAgICkKICAgICAgKQogIH0KCiAgc3VtbWFyaXNlX3Nsb3BlX2luZmVyZW5jZSA8LSBmdW5jdGlvbigKICAgICAgb2JzZXJ2ZWRfc2xvcGVzLAogICAgICBib290c3RyYXBfc2xvcGVzCiAgKSB7CiAgICBzdGF0aXN0aWNfbmFtZXMgPC0gbmFtZXMob2JzZXJ2ZWRfc2xvcGVzKQoKICAgIG1hcF9kZnIoCiAgICAgIHN0YXRpc3RpY19uYW1lcywKICAgICAgZnVuY3Rpb24oc3RhdGlzdGljX25hbWUpIHsKICAgICAgICBib290c3RyYXBfdmFsdWVzIDwtIGJvb3RzdHJhcF9zbG9wZXNbW3N0YXRpc3RpY19uYW1lXV0KICAgICAgICBib290c3RyYXBfdmFsdWVzIDwtIGJvb3RzdHJhcF92YWx1ZXNbCiAgICAgICAgICBpcy5maW5pdGUoYm9vdHN0cmFwX3ZhbHVlcykKICAgICAgICBdCgogICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA8LSBjYXNlX3doZW4oCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSA9PQogICAgICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIgfiAibmVnYXRpdmUiLAogICAgICAgICAgc3RhdGlzdGljX25hbWUgJWluJSBjKAogICAgICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsCiAgICAgICAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiLAogICAgICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIKICAgICAgICAgICkgfiAicG9zaXRpdmUiLAogICAgICAgICAgVFJVRSB+ICJub25lIgogICAgICAgICkKCiAgICAgICAgYW5hbHlzaXNfcm9sZSA8LSBjYXNlX3doZW4oCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSAlaW4lIGMoCiAgICAgICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiCiAgICAgICAgICApIH4gImV4cGxvcmF0b3J5X2Nob2ljZV9zZXRfYWRqdXN0ZWQiLAogICAgICAgICAgc3RhdGlzdGljX25hbWUgPT0gInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIgfgogICAgICAgICAgICAiZGVyaXZlZF9yZWxhdGl2ZV9zaGFyZSIsCiAgICAgICAgICBUUlVFIH4gIm1hbnVzY3JpcHRfcHJpbWFyeV91bmFkanVzdGVkIgogICAgICAgICkKCiAgICAgICAgZXN0aW1hdGUgPC0gdW5uYW1lKAogICAgICAgICAgb2JzZXJ2ZWRfc2xvcGVzW1tzdGF0aXN0aWNfbmFtZV1dCiAgICAgICAgKQoKICAgICAgICB0aWJibGUoCiAgICAgICAgICBzdHVkeSA9ICJTdHVkeSAzIiwKICAgICAgICAgIHN0YXRpc3RpYyA9IHN0YXRpc3RpY19uYW1lLAogICAgICAgICAgZXN0aW1hdGUgPSBlc3RpbWF0ZSwKICAgICAgICAgIGNvbmZfbG93ID0gc2FmZV9xdWFudGlsZSgKICAgICAgICAgICAgYm9vdHN0cmFwX3ZhbHVlcywKICAgICAgICAgICAgMC4wMjUKICAgICAgICAgICksCiAgICAgICAgICBjb25mX2hpZ2ggPSBzYWZlX3F1YW50aWxlKAogICAgICAgICAgICBib290c3RyYXBfdmFsdWVzLAogICAgICAgICAgICAwLjk3NQogICAgICAgICAgKSwKICAgICAgICAgIHBfdmFsdWVfdHdvX3NpZGVkID0KICAgICAgICAgICAgYm9vdHN0cmFwX3R3b19zaWRlZF9wKAogICAgICAgICAgICAgIGJvb3RzdHJhcF92YWx1ZXMKICAgICAgICAgICAgKSwKICAgICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9IGV4cGVjdGVkX2RpcmVjdGlvbiwKICAgICAgICAgIGFuYWx5c2lzX3JvbGUgPSBhbmFseXNpc19yb2xlLAogICAgICAgICAgZXN0aW1hdGVfaW5fZXhwZWN0ZWRfZGlyZWN0aW9uID0gY2FzZV93aGVuKAogICAgICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gInBvc2l0aXZlIiB+IGVzdGltYXRlID4gMCwKICAgICAgICAgICAgZXhwZWN0ZWRfZGlyZWN0aW9uID09ICJuZWdhdGl2ZSIgfiBlc3RpbWF0ZSA8IDAsCiAgICAgICAgICAgIFRSVUUgfiBOQQogICAgICAgICAgKQogICAgICAgICkKICAgICAgfQogICAgKQogIH0KCiAgcmVsYXRpdmVfY3VlX3ByZXBhcmVkIDwtIHByZXBhcmVfcmVsYXRpdmVfY3VlX2FuYWx5c2lzKAogICAgZGF0YSA9IGNvbmpvaW50X2FsbF9tLAogICAgY3VlX21hcCA9IHJlbGF0aXZlX2N1ZV9tYXAKICApCgogIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcygKICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkCiAgKQoKICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzIDwtIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMoCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkbWFyZ2luYWxfbWVhbnMsCiAgICAic3R1ZHkzX3JlbGF0aXZlX2N1ZV9tYXJnaW5hbF9tZWFucy5jc3YiCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGF0dHJpYnV0ZV9pbXBvcnRhbmNlLAogICAgInN0dWR5M19yZWxhdGl2ZV9jdWVfYXR0cmlidXRlX2ltcG9ydGFuY2UuY3N2IgogICkKCiAgd3JpdGVfY3N2X3NhZmVseSgKICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRjdWVfaW1wb3J0YW5jZSwKICAgICJzdHVkeTNfcmVsYXRpdmVfY3VlX2ltcG9ydGFuY2VfYW5kX3dlaWdodC5jc3YiCiAgKQoKICByZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUgPC0gZmlsZS5wYXRoKAogICAgb3V0cHV0X2RpciwKICAgIHBhc3RlMCgKICAgICAgInN0dWR5M19yZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcF8iLAogICAgICB1bmlmaWVkX2NvbmZpZyRjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiwKICAgICAgIl9CIiwKICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLAogICAgICAiLmNzdiIKICAgICkKICApCgogIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlIDwtIGZpbGUucGF0aCgKICAgIG91dHB1dF9kaXIsCiAgICBwYXN0ZTAoCiAgICAgICJzdHVkeTNfcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcF8iLAogICAgICB1bmlmaWVkX2NvbmZpZyRjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiwKICAgICAgIl9CIiwKICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLAogICAgICAiLmNzdiIKICAgICkKICApCgogIHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXAgPC0KICAgICFyZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwICYmCiAgICBmaWxlLmV4aXN0cyhyZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUpICYmCiAgICBmaWxlLmV4aXN0cyhyZWxhdGl2ZV9zbG9wZV9ib290c3RyYXBfZmlsZSkKCiAgaWYgKHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXApIHsKICAgIG1lc3NhZ2UoIkJvb3RzdHJhcCBjYWNoZSIpCgogICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAgPC0gcmVhZHI6OnJlYWRfY3N2KAogICAgICByZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUsCiAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UKICAgICkKCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwIDwtIHJlYWRyOjpyZWFkX2NzdigKICAgICAgcmVsYXRpdmVfc2xvcGVfYm9vdHN0cmFwX2ZpbGUsCiAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UKICAgICkKCiAgICBzYXZlZF9CX2NvbmRpdGlvbiA8LSBuX2Rpc3RpbmN0KAogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24KICAgICkKICAgIHNhdmVkX0Jfc2xvcGUgPC0gbl9kaXN0aW5jdCgKICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24KICAgICkKCiAgICBpZiAoCiAgICAgIHNhdmVkX0JfY29uZGl0aW9uICE9IHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiB8fAogICAgICBzYXZlZF9CX3Nsb3BlICE9IHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQgogICAgKSB7CiAgICAgIG1lc3NhZ2UoIkJvb3RzdHJhcCBjYWNoZSIpCiAgICAgIHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXAgPC0gRkFMU0UKICAgIH0KICB9CgogIGlmICghdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCkgewogICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA8LSBydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCgKICAgICAgcHJlcGFyZWQgPSByZWxhdGl2ZV9jdWVfcHJlcGFyZWQsCiAgICAgIEIgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IsCiAgICAgIHNlZWQgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQsCiAgICAgIHByb2dyZXNzX2V2ZXJ5ID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeQogICAgKQoKICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwIDwtCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAkY29uZGl0aW9uX2VzdGltYXRlcwoKICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAgPC0KICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCRzbG9wZXMKCiAgICByZWFkcjo6d3JpdGVfY3N2KAogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCwKICAgICAgcmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlCiAgICApCgogICAgcmVhZHI6OndyaXRlX2NzdigKICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCwKICAgICAgcmVsYXRpdmVfc2xvcGVfYm9vdHN0cmFwX2ZpbGUKICAgICkKICB9CgogIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzIDwtIHN1bW1hcmlzZV9jb25kaXRpb25faW50ZXJ2YWxzKAogICAgb2JzZXJ2ZWRfY3VlX2ltcG9ydGFuY2UgPQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsCiAgICBib290c3RyYXBfY29uZGl0aW9uX3Jlc3VsdHMgPQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcAogICkKCiAgcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSA8LSBzdW1tYXJpc2Vfc2xvcGVfaW5mZXJlbmNlKAogICAgb2JzZXJ2ZWRfc2xvcGVzID0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkX3Nsb3BlcywKICAgIGJvb3RzdHJhcF9zbG9wZXMgPQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwCiAgKQoKICB3cml0ZV9jc3Zfc2FmZWx5KAogICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMsCiAgICAic3R1ZHkzX3JlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzLmNzdiIKICApCgogIHdyaXRlX2Nzdl9zYWZlbHkoCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlLAogICAgInN0dWR5M19yZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlLmNzdiIKICApCgogIHJlbGF0aXZlX2N1ZV9wcmltYXJ5X3Jlc3VsdCA8LSByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlICU+JQogICAgZmlsdGVyKAogICAgICBzdGF0aXN0aWMgPT0KICAgICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIgogICAgKQoKICBjYXQoIlxuU3R1ZHkgM++8muebuOWvvuavlOmHjeOBrue3muW9ouWCvuWQkVxuIikKICBwcmludChyZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQpCgoKICByZWxhdGl2ZV94X29mZnNldCA8LSAwLjA3NQoKICByZWxhdGl2ZV9wYW5lbF9hX2RhdGEgPC0gcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMgJT4lCiAgICBmaWx0ZXIoCiAgICAgIHN0YXRpc3RpYyAlaW4lIGMoCiAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLAogICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIgogICAgICApCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICBjdWVfZmFtaWx5ID0gcmVjb2RlKAogICAgICAgIHN0YXRpc3RpYywKICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0gIuaUv+WFmuWQjeaJi+OBjOOBi+OCiiIsCiAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLntYzmuIjmiYvjgYzjgYvjgooiCiAgICAgICksCiAgICAgIGN1ZV9mYW1pbHkgPSBmYWN0b3IoCiAgICAgICAgY3VlX2ZhbWlseSwKICAgICAgICBsZXZlbHMgPSBjKAogICAgICAgICAgIuaUv+WFmuWQjeaJi+OBjOOBi+OCiiIsCiAgICAgICAgICAi57WM5riI5omL44GM44GL44KKIgogICAgICAgICkKICAgICAgKSwKICAgICAgeF9wbG90ID0gY2FzZV93aGVuKAogICAgICAgIGN1ZV9mYW1pbHkgPT0gIuaUv+WFmuWQjeaJi+OBjOOBi+OCiiIgfgogICAgICAgICAgcGFydHlfbiArIHJlbGF0aXZlX3hfb2Zmc2V0LAogICAgICAgIGN1ZV9mYW1pbHkgPT0gIue1jOa4iOaJi+OBjOOBi+OCiiIgfgogICAgICAgICAgcGFydHlfbiAtIHJlbGF0aXZlX3hfb2Zmc2V0LAogICAgICAgIFRSVUUgfiBhcy5udW1lcmljKHBhcnR5X24pCiAgICAgICksCiAgICAgIHZhbHVlX2xhYmVsID0gc3ByaW50ZigKICAgICAgICAiJS4zZiIsCiAgICAgICAgZXN0aW1hdGUKICAgICAgKQogICAgKQoKICByZWxhdGl2ZV9wYW5lbF9iX2RhdGEgPC0gcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMgJT4lCiAgICBmaWx0ZXIoCiAgICAgIHN0YXRpc3RpYyA9PQogICAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICB2YWx1ZV9sYWJlbCA9IHNwcmludGYoCiAgICAgICAgIiUuMWYlJSIsCiAgICAgICAgMTAwICogZXN0aW1hdGUKICAgICAgKQogICAgKQoKICByZWxhdGl2ZV9hZGp1c3RlZF9sYWJlbF9tYXAgPC0gcmVsYXRpdmVfcGFuZWxfYV9kYXRhICU+JQogICAgZGlzdGluY3QoCiAgICAgIHN0YXRpc3RpYywKICAgICAgY3VlX2ZhbWlseQogICAgKSAlPiUKICAgIG11dGF0ZSgKICAgICAgc3RhdGlzdGljID0gcGFzdGUwKAogICAgICAgIHN0YXRpc3RpYywKICAgICAgICAiX2FkanVzdGVkIgogICAgICApLAogICAgICBjdWVfZmFtaWx5ID0gYXMuY2hhcmFjdGVyKAogICAgICAgIGN1ZV9mYW1pbHkKICAgICAgKQogICAgKQoKICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQogICAgZmlsdGVyKAogICAgICBzdGF0aXN0aWMgJWluJSBjKAogICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwKICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIKICAgICAgKQogICAgKSAlPiUKICAgIGxlZnRfam9pbigKICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfbGFiZWxfbWFwLAogICAgICBieSA9ICJzdGF0aXN0aWMiCiAgICApICU+JQogICAgbXV0YXRlKAogICAgICBjdWVfZmFtaWx5ID0gZmFjdG9yKAogICAgICAgIGN1ZV9mYW1pbHksCiAgICAgICAgbGV2ZWxzID0gbGV2ZWxzKAogICAgICAgICAgcmVsYXRpdmVfcGFuZWxfYV9kYXRhJGN1ZV9mYW1pbHkKICAgICAgICApCiAgICAgICksCiAgICAgIHhfcGxvdCA9IGlmX2Vsc2UoCiAgICAgICAgYXMuaW50ZWdlcihjdWVfZmFtaWx5KSA9PSAxTCwKICAgICAgICBwYXJ0eV9uICsgcmVsYXRpdmVfeF9vZmZzZXQsCiAgICAgICAgcGFydHlfbiAtIHJlbGF0aXZlX3hfb2Zmc2V0CiAgICAgICksCiAgICAgIHZhbHVlX2xhYmVsID0gc3ByaW50ZigKICAgICAgICAiJS4xZiUlIiwKICAgICAgICAxMDAgKiBlc3RpbWF0ZQogICAgICApCiAgICApCgogIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXggPC0gaWYgKAogICAgIuaUv+WFmuWQjeaJi+OBjOOBi+OCiiIgJWluJQogICAgICBsZXZlbHMocmVsYXRpdmVfcGFuZWxfYV9kYXRhJGN1ZV9mYW1pbHkpCiAgKSB7CiAgICAi6YG45oqe6IKiIgogIH0gZWxzZSB7CiAgICAi5pS/5YWaIgogIH0KCiAgcmVsYXRpdmVfY29uZGl0aW9uX2F4aXNfdGl0bGUgPC0gaWYgKAogICAgcmVsYXRpdmVfY29uZGl0aW9uX3N1ZmZpeCA9PSAi6YG45oqe6IKiIgogICkgewogICAgIuaUv+ayu+e1jOa4iOeKtuazgeOBrumBuOaKnuiCouaVsCIKICB9IGVsc2UgewogICAgIuaUv+WFmumBuOaKnuiCouaVsCIKICB9CgogIHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSA8LSBpZiAoCiAgICAuUGxhdGZvcm0kT1MudHlwZSA9PSAid2luZG93cyIKICApIHsKICAgICJZdSBHb3RoaWMiCiAgfSBlbHNlIHsKICAgICJzYW5zIgogIH0KCiAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncgPC0gdGhlbWVfYncoCiAgICBiYXNlX3NpemUgPSAxMiwKICAgIGJhc2VfZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5CiAgKSArCiAgICB0aGVtZSgKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZSgKICAgICAgICBsaW5ld2lkdGggPSAwLjMwLAogICAgICAgIGNvbG9yID0gImdyZXk4OCIKICAgICAgKSwKICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KAogICAgICAgIGxpbmV3aWR0aCA9IDAuNjUsCiAgICAgICAgY29sb3IgPSAiYmxhY2siCiAgICAgICksCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBjb2xvciA9ICJibGFjayIKICAgICAgKSwKICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBjb2xvciA9ICJibGFjayIKICAgICAgKSwKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgKICAgICAgICBzaXplID0gMTIuNSwKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIGhqdXN0ID0gMAogICAgICApLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSA5LjUsCiAgICAgICAgaGp1c3QgPSAwLAogICAgICAgIG1hcmdpbiA9IG1hcmdpbigKICAgICAgICAgIGIgPSA4CiAgICAgICAgKQogICAgICApLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIiwKICAgICAgbGVnZW5kLmtleS53aWR0aCA9IGdyaWQ6OnVuaXQoCiAgICAgICAgMS4yNSwKICAgICAgICAiY20iCiAgICAgICksCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKAogICAgICAgIDgsCiAgICAgICAgMTAsCiAgICAgICAgOCwKICAgICAgICA4CiAgICAgICkKICAgICkKCiAgcmVsYXRpdmVfcGFuZWxfYSA8LSBnZ3Bsb3QoCiAgICByZWxhdGl2ZV9wYW5lbF9hX2RhdGEsCiAgICBhZXMoCiAgICAgIHggPSB4X3Bsb3QsCiAgICAgIHkgPSBlc3RpbWF0ZSwKICAgICAgZ3JvdXAgPSBjdWVfZmFtaWx5LAogICAgICBsaW5ldHlwZSA9IGN1ZV9mYW1pbHkKICAgICkKICApICsKICAgIGdlb21fbGluZSgKICAgICAgbGluZXdpZHRoID0gMC44MCwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fZXJyb3JiYXIoCiAgICAgIGFlcygKICAgICAgICB5bWluID0gY29uZl9sb3csCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaAogICAgICApLAogICAgICB3aWR0aCA9IDAuMDc1LAogICAgICBsaW5ld2lkdGggPSAwLjgwLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9sYWJlbCgKICAgICAgYWVzKAogICAgICAgIGxhYmVsID0gdmFsdWVfbGFiZWwKICAgICAgKSwKICAgICAgc2l6ZSA9IDMuNTUsCiAgICAgIGZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSwKICAgICAgbGFiZWwuc2l6ZSA9IDAsCiAgICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KAogICAgICAgIDAuMTIsCiAgICAgICAgImxpbmVzIgogICAgICApLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgdmFsdWVzID0gYygKICAgICAgICAi5pS/5YWa5ZCN5omL44GM44GL44KKIiA9ICJzb2xpZCIsCiAgICAgICAgIue1jOa4iOaJi+OBjOOBi+OCiiIgPSAiZGFzaGVkIgogICAgICApCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgYnJlYWtzID0gMjo1LAogICAgICBsYWJlbHMgPSBwYXN0ZTAoCiAgICAgICAgMjo1LAogICAgICAgICLpgbjmip7ogqIiCiAgICAgICksCiAgICAgIGxpbWl0cyA9IGMoCiAgICAgICAgMS43MiwKICAgICAgICA1LjI4CiAgICAgICkKICAgICkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKAogICAgICBsYWJlbHMgPSBsYWJlbF9udW1iZXIoCiAgICAgICAgYWNjdXJhY3kgPSAwLjAwNQogICAgICApLAogICAgICBleHBhbmQgPSBleHBhbnNpb24oCiAgICAgICAgbXVsdCA9IGMoCiAgICAgICAgICAwLjA3LAogICAgICAgICAgMC4xMAogICAgICAgICkKICAgICAgKQogICAgKSArCiAgICBsYWJzKAogICAgICB0aXRsZSA9ICJB77ya5Lih5omL44GM44GL44KK44Gu57W25a++55qE6YeN6KaB5bqmIiwKICAgICAgc3VidGl0bGUgPSAiIiwKICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLAogICAgICB5ID0gIuaJi+OBjOOBi+OCiumHjeimgeW6piIsCiAgICAgIGxpbmV0eXBlID0gTlVMTAogICAgKSArCiAgICBndWlkZXMoCiAgICAgIGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKAogICAgICAgIG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBsaW5ld2lkdGggPSAwLjkwCiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3CgogIHJlbGF0aXZlX2FkanVzdGVkX2xpbmV0eXBlcyA8LSBzZXROYW1lcygKICAgIGMoCiAgICAgICJzb2xpZCIsCiAgICAgICJkYXNoZWQiCiAgICApLAogICAgbGV2ZWxzKAogICAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhJGN1ZV9mYW1pbHkKICAgICkKICApCgogIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkIDwtIGdncGxvdCgKICAgIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGEsCiAgICBhZXMoCiAgICAgIHggPSB4X3Bsb3QsCiAgICAgIHkgPSBlc3RpbWF0ZSwKICAgICAgZ3JvdXAgPSBjdWVfZmFtaWx5LAogICAgICBsaW5ldHlwZSA9IGN1ZV9mYW1pbHkKICAgICkKICApICsKICAgIGdlb21fbGluZSgKICAgICAgbGluZXdpZHRoID0gMC44MCwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIGdlb21fZXJyb3JiYXIoCiAgICAgIGFlcygKICAgICAgICB5bWluID0gY29uZl9sb3csCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaAogICAgICApLAogICAgICB3aWR0aCA9IDAuMDc1LAogICAgICBsaW5ld2lkdGggPSAwLjgwLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9sYWJlbCgKICAgICAgYWVzKAogICAgICAgIGxhYmVsID0gdmFsdWVfbGFiZWwKICAgICAgKSwKICAgICAgc2l6ZSA9IDMuNTUsCiAgICAgIGZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSwKICAgICAgbGFiZWwuc2l6ZSA9IDAsCiAgICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KAogICAgICAgIDAuMTIsCiAgICAgICAgImxpbmVzIgogICAgICApLAogICAgICBmaWxsID0gIndoaXRlIiwKICAgICAgY29sb3IgPSAiYmxhY2siCiAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgKICAgICAgdmFsdWVzID0gcmVsYXRpdmVfYWRqdXN0ZWRfbGluZXR5cGVzCiAgICApICsKICAgIHNjYWxlX3hfY29udGludW91cygKICAgICAgYnJlYWtzID0gMjo1LAogICAgICBsYWJlbHMgPSBwYXN0ZTAoCiAgICAgICAgMjo1LAogICAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXgKICAgICAgKSwKICAgICAgbGltaXRzID0gYygKICAgICAgICAxLjcyLAogICAgICAgIDUuMjgKICAgICAgKQogICAgKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICAgIGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoCiAgICAgICAgYWNjdXJhY3kgPSAxCiAgICAgICksCiAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbigKICAgICAgICBtdWx0ID0gYygKICAgICAgICAgIDAuMDcsCiAgICAgICAgICAwLjEwCiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gIkHvvJrpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiLAogICAgICBzdWJ0aXRsZSA9CiAgICAgICAgIuacquiqv+aVtOmHjeimgeW6piDDtyDlubPlnYfpgbjmip7norrnjofvvIgx77yP6YG45oqe6IKi5pWw77yJIiwKICAgICAgeCA9IHJlbGF0aXZlX2NvbmRpdGlvbl9heGlzX3RpdGxlLAogICAgICB5ID0gIuW5s+Wdh+mBuOaKnueiuueOh+OBq+WvvuOBmeOCi+awtOa6lumWk+W3riIsCiAgICAgIGxpbmV0eXBlID0gTlVMTAogICAgKSArCiAgICBndWlkZXMoCiAgICAgIGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKAogICAgICAgIG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBsaW5ld2lkdGggPSAwLjkwCiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3CgogIHJlbGF0aXZlX2JfcmFuZ2UgPC0gcmFuZ2UoCiAgICBjKAogICAgICByZWxhdGl2ZV9wYW5lbF9iX2RhdGEkY29uZl9sb3csCiAgICAgIHJlbGF0aXZlX3BhbmVsX2JfZGF0YSRjb25mX2hpZ2gsCiAgICAgIDAuNQogICAgKSwKICAgIG5hLnJtID0gVFJVRQogICkKCiAgcmVsYXRpdmVfYl9wYWRkaW5nIDwtIG1heCgKICAgIDAuMDI1LAogICAgMC4xMCAqIGRpZmYocmVsYXRpdmVfYl9yYW5nZSkKICApCgogIHJlbGF0aXZlX2JfbG93ZXIgPC0gbWF4KAogICAgMCwKICAgIGZsb29yKAogICAgICAyMCAqCiAgICAgICAgKHJlbGF0aXZlX2JfcmFuZ2VbMV0gLSByZWxhdGl2ZV9iX3BhZGRpbmcpCiAgICApIC8gMjAKICApCgogIHJlbGF0aXZlX2JfdXBwZXIgPC0gbWluKAogICAgMSwKICAgIGNlaWxpbmcoCiAgICAgIDIwICoKICAgICAgICAocmVsYXRpdmVfYl9yYW5nZVsyXSArIHJlbGF0aXZlX2JfcGFkZGluZykKICAgICkgLyAyMAogICkKCiAgaWYgKHJlbGF0aXZlX2JfbG93ZXIgPj0gcmVsYXRpdmVfYl91cHBlcikgewogICAgcmVsYXRpdmVfYl9sb3dlciA8LSBtYXgoCiAgICAgIDAsCiAgICAgIHJlbGF0aXZlX2JfbG93ZXIgLSAwLjA1CiAgICApCiAgICByZWxhdGl2ZV9iX3VwcGVyIDwtIG1pbigKICAgICAgMSwKICAgICAgcmVsYXRpdmVfYl91cHBlciArIDAuMDUKICAgICkKICB9CgogIHJlbGF0aXZlX3BhbmVsX2IgPC0gZ2dwbG90KAogICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhLAogICAgYWVzKAogICAgICB4ID0gcGFydHlfbiwKICAgICAgeSA9IGVzdGltYXRlCiAgICApCiAgKSArCiAgICBnZW9tX2hsaW5lKAogICAgICB5aW50ZXJjZXB0ID0gMC41LAogICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLAogICAgICBsaW5ld2lkdGggPSAwLjU1LAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9saW5lKAogICAgICBsaW5ld2lkdGggPSAwLjgwLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgZ2VvbV9lcnJvcmJhcigKICAgICAgYWVzKAogICAgICAgIHltaW4gPSBjb25mX2xvdywKICAgICAgICB5bWF4ID0gY29uZl9oaWdoCiAgICAgICksCiAgICAgIHdpZHRoID0gMC4wNzUsCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsCiAgICAgIGNvbG9yID0gImJsYWNrIgogICAgKSArCiAgICBnZW9tX2xhYmVsKAogICAgICBhZXMoCiAgICAgICAgbGFiZWwgPSB2YWx1ZV9sYWJlbAogICAgICApLAogICAgICBzaXplID0gMy41NSwKICAgICAgZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5LAogICAgICBsYWJlbC5zaXplID0gMCwKICAgICAgbGFiZWwucGFkZGluZyA9IGdyaWQ6OnVuaXQoCiAgICAgICAgMC4xMiwKICAgICAgICAibGluZXMiCiAgICAgICksCiAgICAgIGZpbGwgPSAid2hpdGUiLAogICAgICBjb2xvciA9ICJibGFjayIKICAgICkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKAogICAgICBicmVha3MgPSAyOjUsCiAgICAgIGxhYmVscyA9IHBhc3RlMCgKICAgICAgICAyOjUsCiAgICAgICAgIumBuOaKnuiCoiIKICAgICAgKSwKICAgICAgbGltaXRzID0gYygKICAgICAgICAxLjcyLAogICAgICAgIDUuMjgKICAgICAgKQogICAgKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICAgIGJyZWFrcyA9IHNlcSgKICAgICAgICByZWxhdGl2ZV9iX2xvd2VyLAogICAgICAgIHJlbGF0aXZlX2JfdXBwZXIsCiAgICAgICAgYnkgPSAwLjA1CiAgICAgICksCiAgICAgIGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoCiAgICAgICAgYWNjdXJhY3kgPSAxCiAgICAgICksCiAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbigKICAgICAgICBtdWx0ID0gYygKICAgICAgICAgIDAuMDUsCiAgICAgICAgICAwLjA4CiAgICAgICAgKQogICAgICApCiAgICApICsKICAgIGNvb3JkX2NhcnRlc2lhbigKICAgICAgeWxpbSA9IGMoCiAgICAgICAgcmVsYXRpdmVfYl9sb3dlciwKICAgICAgICByZWxhdGl2ZV9iX3VwcGVyCiAgICAgICkKICAgICkgKwogICAgbGFicygKICAgICAgdGl0bGUgPSAiQu+8muebuOWvvueahOOBquaUv+WFmuWQjeaJi+OBjOOBi+OCiuOBruavlOmHjSIsCiAgICAgIHN1YnRpdGxlID0KICAgICAgICAi5pS/5YWa5ZCN5omL44GM44GL44KK6YeN6KaB5bqmIMO377yI5pS/5YWa5ZCN5omL44GM44GL44KK6YeN6KaB5bqm77yL57WM5riI5omL44GM44GL44KK6YeN6KaB5bqm77yJIiwKICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLAogICAgICB5ID0gIuebuOWvvueahOOBquaUv+WFmuWQjeaJi+OBjOOBi+OCiuavlOmHjSIKICAgICkgKwogICAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncgKwogICAgdGhlbWUoCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICAgKQoKICByZWxhdGl2ZV9wYW5lbF9jIDwtIHJlbGF0aXZlX3BhbmVsX2IgKwogICAgbGFicygKICAgICAgdGl0bGUgPSBwYXN0ZTAoCiAgICAgICAgIkLvvJrnm7jlr77nmoTjgaoiLAogICAgICAgIGxldmVscyhyZWxhdGl2ZV9wYW5lbF9hX2RhdGEkY3VlX2ZhbWlseSlbMV0sCiAgICAgICAgIuOBruavlOmHjSIKICAgICAgKQogICAgKQoKICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwIDwtICgKICAgIHJlbGF0aXZlX3BhbmVsX2EgfAogICAgICByZWxhdGl2ZV9wYW5lbF9iCiAgKSArCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KAogICAgICB3aWR0aHMgPSBjKAogICAgICAgIDEsCiAgICAgICAgMQogICAgICApCiAgICApCgogIHByaW50KAogICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcAogICkKCiAgc2F2ZV9wbG90KAogICAgImZpZ19zdHVkeTNfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wbmciLAogICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCwKICAgIHdpZHRoID0gMTEuMiwKICAgIGhlaWdodCA9IDUuNCwKICAgIGRwaSA9IDQwMAogICkKCiAgZ2dzYXZlKAogICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoCiAgICAgIG91dHB1dF9kaXIsCiAgICAgICJmaWdfc3R1ZHkzX3JlbGF0aXZlX2N1ZV93ZWlnaHRfanBfYncucGRmIgogICAgKSwKICAgIHBsb3QgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLAogICAgd2lkdGggPSAxMS4yLAogICAgaGVpZ2h0ID0gNS40LAogICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsCiAgICBiZyA9ICJ3aGl0ZSIKICApCgogIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAgPC0gKAogICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQgfAogICAgICByZWxhdGl2ZV9wYW5lbF9jCiAgKSArCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KAogICAgICB3aWR0aHMgPSBjKAogICAgICAgIDEsCiAgICAgICAgMQogICAgICApCiAgICApCgogIHByaW50KAogICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcAogICkKCiAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIgPC0gcGFzdGUwKAogICAgImZpZ19zdHVkeSIsCiAgICBzdHJpbmdyOjpzdHJfZXh0cmFjdCgKICAgICAgc3R1ZHlfbGFiZWwsCiAgICAgICJbMTIzXSIKICAgICksCiAgICAiX3JlbGF0aXZlX2N1ZV93ZWlnaHRfY2hvaWNlX3NldF9hZGp1c3RlZF9qcF9idyIKICApCgogIHNhdmVfcGxvdCgKICAgIHBhc3RlMCgKICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIsCiAgICAgICIucG5nIgogICAgKSwKICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAsCiAgICB3aWR0aCA9IDExLjIsCiAgICBoZWlnaHQgPSA1LjQsCiAgICBkcGkgPSA0MDAKICApCgogIGdnc2F2ZSgKICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICBwYXN0ZTAoCiAgICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIsCiAgICAgICAgIi5wZGYiCiAgICAgICkKICAgICksCiAgICBwbG90ID0gZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcCwKICAgIHdpZHRoID0gMTEuMiwKICAgIGhlaWdodCA9IDUuNCwKICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLAogICAgYmcgPSAid2hpdGUiCiAgKQoKICByZWxhdGl2ZV9jdWVfcmVzdWx0cyA8LSBsaXN0KAogICAgcHJlcGFyZWQgPSByZWxhdGl2ZV9jdWVfcHJlcGFyZWQsCiAgICBtYXJnaW5hbF9tZWFucyA9CiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRtYXJnaW5hbF9tZWFucywKICAgIGF0dHJpYnV0ZV9pbXBvcnRhbmNlID0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGF0dHJpYnV0ZV9pbXBvcnRhbmNlLAogICAgY3VlX2ltcG9ydGFuY2UgPQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsCiAgICBvYnNlcnZlZF9zbG9wZXMgPQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzLAogICAgY29uZGl0aW9uX2Jvb3RzdHJhcCA9CiAgICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwLAogICAgc2xvcGVfYm9vdHN0cmFwID0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCwKICAgIGNvbmRpdGlvbl9pbnRlcnZhbHMgPQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscywKICAgIHNsb3BlX2luZmVyZW5jZSA9CiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9pbmZlcmVuY2UsCiAgICBwcmltYXJ5X3Jlc3VsdCA9CiAgICAgIHJlbGF0aXZlX2N1ZV9wcmltYXJ5X3Jlc3VsdCwKICAgIHBsb3RzID0gbGlzdCgKICAgICAgYWJzb2x1dGVfaW1wb3J0YW5jZSA9IHJlbGF0aXZlX3BhbmVsX2EsCiAgICAgIGNob2ljZV9zZXRfYWRqdXN0ZWRfaW1wb3J0YW5jZSA9CiAgICAgICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQsCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodCA9IHJlbGF0aXZlX3BhbmVsX2IsCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYW5lbF9jID0KICAgICAgICByZWxhdGl2ZV9wYW5lbF9jLAogICAgICBjb21iaW5lZCA9IGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsCiAgICAgIGNvbWJpbmVkX3dpdGhfY2hvaWNlX3NldF9hZGp1c3RtZW50ID0KICAgICAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwCiAgICApCiAgKQoKICBzYXZlUkRTKAogICAgcmVsYXRpdmVfY3VlX3Jlc3VsdHMsCiAgICBmaWxlID0gZmlsZS5wYXRoKAogICAgICBvdXRwdXRfZGlyLAogICAgICAic3R1ZHkzX3JlbGF0aXZlX2N1ZV9yZXN1bHRzLnJkcyIKICAgICkKICApCgoKICBzYXZlUkRTKAogICAgbGlzdCgKICAgICAgc2V0dGluZ3MgPSBsaXN0KAogICAgICAgIGRhdGFfZmlsZSA9IGRhdGFfZmlsZSwKICAgICAgICByZXF1aXJlX2luaXRpYWxfY29uc2VudCA9CiAgICAgICAgICByZXF1aXJlX2luaXRpYWxfY29uc2VudCwKICAgICAgICByZXF1aXJlX2ZpbmFsX2NvbnNlbnQgPQogICAgICAgICAgcmVxdWlyZV9maW5hbF9jb25zZW50LAogICAgICAgIHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrID0KICAgICAgICAgIHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrLAogICAgICAgIHJlcXVpcmVfbWFuaXB1bGF0aW9uX2NoZWNrID0KICAgICAgICAgIHJlcXVpcmVfbWFuaXB1bGF0aW9uX2NoZWNrLAogICAgICAgIHJlcXVpcmVfYWxsX2ZpdmVfdGFza3MgPQogICAgICAgICAgcmVxdWlyZV9hbGxfZml2ZV90YXNrcywKICAgICAgICBwYXJ0eV9yZWZlcmVuY2UgPQogICAgICAgICAgcGFydHlfcmVmZXJlbmNlLAogICAgICAgIHBhcnR5X2xldmVsc191c2UgPQogICAgICAgICAgcGFydHlfbGV2ZWxzX3VzZSwKICAgICAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgPQogICAgICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLAogICAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCA9CiAgICAgICAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQKICAgICAgKSwKCiAgICAgIHNhbXBsZV9mbG93ID0gc2FtcGxlX2Zsb3csCiAgICAgIG5fYnlfcGFydHkgPSBuX2J5X3BhcnR5LAogICAgICB2YWxpZF9pZHMgPSB2YWxpZF9pZHMsCgogICAgICBjb25qb2ludF9hbGwgPSBjb25qb2ludF9hbGwsCiAgICAgIGNvbmpvaW50X2FsbF9tID0gY29uam9pbnRfYWxsX20sCiAgICAgIGNvbmpvaW50X2FsbF9jb3YgPSBjb25qb2ludF9hbGxfY292LAoKICAgICAgY292YXJfaWQgPSBjb3Zhcl9pZCwKCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX25vY292ID0KICAgICAgICBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiwKCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX2NvdiA9CiAgICAgICAgbW9kZWxzX2J5X3BhcnR5X25fY292LAoKICAgICAgbV9pbnRlcmFjdGlvbiA9CiAgICAgICAgbV9pbnRlcmFjdGlvbiwKCiAgICAgIG1fbGluZWFyX3RyZW5kID0KICAgICAgICBtX2xpbmVhcl90cmVuZCwKCiAgICAgIG1vZGVsc19jbG9naXRfbm9jb3YgPQogICAgICAgIG1vZGVsc19jbG9naXRfbm9jb3YsCgogICAgICBwYXJ0eV9tYXRjaCA9IGxpc3QoCiAgICAgICAgZGF0YSA9IGNvbmpvaW50X21hdGNoLAogICAgICAgIG1vZGVsc19ieV9uID0KICAgICAgICAgIG1vZGVsc19wYXJ0eV9tYXRjaF9ieV9uLAogICAgICAgIGludGVyYWN0aW9uX21vZGVsID0KICAgICAgICAgIG1fcGFydHlfbWF0Y2hfaW50ZXJhY3Rpb24KICAgICAgKSwKCiAgICAgIHJlbGF0aXZlX2N1ZSA9IHJlbGF0aXZlX2N1ZV9yZXN1bHRzLAoKICAgICAgcGxvdHMgPSBsaXN0KAogICAgICAgIGFtY2VfY292ID0KICAgICAgICAgIHBfYW1jZV9jb3YsCiAgICAgICAgYW1jZV9ub2NvdiA9CiAgICAgICAgICBwX2FtY2Vfbm9jb3YsCiAgICAgICAgaW50ZXJhY3Rpb24gPQogICAgICAgICAgcF9pbnRlcmFjdGlvbiwKICAgICAgICBsaW5lYXJfdHJlbmQgPQogICAgICAgICAgcF9saW5lYXJfdHJlbmQsCiAgICAgICAgaGVhdG1hcCA9CiAgICAgICAgICBwX2hlYXRfYW1jZSwKICAgICAgICBjbG9naXRfb2Rkc19yYXRpbyA9CiAgICAgICAgICBwX2Nsb2dpdF9vciwKICAgICAgICBwYXJ0eV9tYXRjaCA9CiAgICAgICAgICBwX3BhcnR5X21hdGNoLAogICAgICAgIHJlbGF0aXZlX2N1ZV93ZWlnaHQgPQogICAgICAgICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCwKICAgICAgICByZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWQgPQogICAgICAgICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcAogICAgICApCiAgICApLAogICAgZmlsZSA9IGZpbGUucGF0aCgKICAgICAgb3V0cHV0X2RpciwKICAgICAgInN0dWR5M19hbmFseXNpc19vYmplY3RzLnJkcyIKICAgICkKICApCgogIGNhcHR1cmUub3V0cHV0KAogICAgc2Vzc2lvbkluZm8oKSwKICAgIGZpbGUgPSBmaWxlLnBhdGgoCiAgICAgIG91dHB1dF9kaXIsCiAgICAgICJzZXNzaW9uSW5mby50eHQiCiAgICApCiAgKQoKICBjYXQoCiAgICAiXG5TdHVkeSAz44Gu5YiG5p6Q44Kz44O844OJ44GM5pyA5b6M44G+44Gn5a6M5LqG44GX44G+44GX44Gf44CCXG4iLAogICAgIuWHuuWKm+WFiDogIiwKICAgIG5vcm1hbGl6ZVBhdGgob3V0cHV0X2RpciksCiAgICAiXG4iLAogICAgc2VwID0gIiIKICApCgogIGVudmlyb25tZW50KCkKfSkKYGBgCgojIyBBLjUg6KOc6YG644Gr6Zai44GZ44KL5ZCE56iu44Gu5YaN54++44Kz44O844OJCgpgYGB7ciBhNS1zdXBwbGVtZW50LWNvZGUsIGV2YWw9cGFyYW1zJHJ1bl9hbmFseXNpcywgcmVzdWx0cz0naGlkZScsIGZpZy5zaG93PSdoaWRlJ30KCiMg6KOc6YG65YWx6YCa44Kz44O844OJCnVuaWZpZWRfb3V0cHV0X2RpciA8LSBmaWxlLnBhdGgoCiAgdW5pZmllZF9jb25maWckb3V0cHV0X3Jvb3QsCiAgIl93b3JraW5nIiwKICAiY3Jvc3Nfc3R1ZHkiCikKZGlyLmNyZWF0ZSh1bmlmaWVkX291dHB1dF9kaXIsIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQoKc2F2ZV9wbG90X2JvdGggPC0gZnVuY3Rpb24oZmlsZW5hbWVfc3R1YiwgcGxvdCwgd2lkdGgsIGhlaWdodCwgZHBpID0gNDAwKSB7CiAgcG5nX2ZpbGUgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKGZpbGVuYW1lX3N0dWIsICIucG5nIikpCiAgcGRmX2ZpbGUgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKGZpbGVuYW1lX3N0dWIsICIucGRmIikpCiAgCiAgZ2dwbG90Mjo6Z2dzYXZlKAogICAgZmlsZW5hbWUgPSBwbmdfZmlsZSwKICAgIHBsb3QgPSBwbG90LAogICAgd2lkdGggPSB3aWR0aCwKICAgIGhlaWdodCA9IGhlaWdodCwKICAgIGRwaSA9IGRwaSwKICAgIGJnID0gIndoaXRlIgogICkKICAKICBnZ3Bsb3QyOjpnZ3NhdmUoCiAgICBmaWxlbmFtZSA9IHBkZl9maWxlLAogICAgcGxvdCA9IHBsb3QsCiAgICB3aWR0aCA9IHdpZHRoLAogICAgaGVpZ2h0ID0gaGVpZ2h0LAogICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsCiAgICBiZyA9ICJ3aGl0ZSIKICApCiAgCiAgaW52aXNpYmxlKGMocG5nID0gcG5nX2ZpbGUsIHBkZiA9IHBkZl9maWxlKSkKfQoKd3JpdGVfY3N2X3VuaWZpZWQgPC0gZnVuY3Rpb24oeCwgZmlsZW5hbWUpIHsKICByZWFkcjo6d3JpdGVfY3N2KAogICAgeCwKICAgIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsIGZpbGVuYW1lKSwKICAgIG5hID0gIiIKICApCn0KCnNhZmVfZmlsZW5hbWUgPC0gZnVuY3Rpb24oeCkgewogIHggPC0gaWNvbnYoYXMuY2hhcmFjdGVyKHgpLCBmcm9tID0gIiIsIHRvID0gIkFTQ0lJLy9UUkFOU0xJVCIpCiAgeFtpcy5uYSh4KSB8IHggPT0gIiJdIDwtICJncm91cCIKICB4IDwtIHRvbG93ZXIoeCkKICB4IDwtIGdzdWIoIlteYS16MC05XSsiLCAiXyIsIHgpCiAgeCA8LSBnc3ViKCJeXyt8XyskIiwgIiIsIHgpCiAgaWZlbHNlKHggPT0gIiIsICJncm91cCIsIHgpCn0KCnRpZHlfZml4ZXN0X3VuaWZpZWQgPC0gZnVuY3Rpb24obW9kZWwpIHsKICBjdCA8LSBhcy5kYXRhLmZyYW1lKGZpeGVzdDo6Y29lZnRhYmxlKG1vZGVsKSkKICBjdCR0ZXJtIDwtIHJvd25hbWVzKGN0KQogIAogIGVzdGltYXRlX2NvbCA8LSBpbnRlcnNlY3QoYygiRXN0aW1hdGUiLCAiZXN0aW1hdGUiKSwgbmFtZXMoY3QpKVsxXQogIHNlX2NvbCA8LSBpbnRlcnNlY3QoYygiU3RkLiBFcnJvciIsICJTdGQuIGVycm9yIiwgInN0ZC5lcnJvciIpLCBuYW1lcyhjdCkpWzFdCiAgc3RhdGlzdGljX2NvbCA8LSBpbnRlcnNlY3QoYygidCB2YWx1ZSIsICJ6IHZhbHVlIiwgInN0YXRpc3RpYyIpLCBuYW1lcyhjdCkpWzFdCiAgcF9jb2wgPC0gaW50ZXJzZWN0KGMoIlByKD58dHwpIiwgIlByKD58enwpIiwgInAudmFsdWUiKSwgbmFtZXMoY3QpKVsxXQogIAogIGlmICgKICAgIGlzLm5hKGVzdGltYXRlX2NvbCkgfHwKICAgIGlzLm5hKHNlX2NvbCkgfHwKICAgIGlzLm5hKHN0YXRpc3RpY19jb2wpIHx8CiAgICBpcy5uYShwX2NvbCkKICApIHsKICAgIHN0b3AoIkNoZWNrIGRhdGEiKQogIH0KICAKICB0aWJibGU6OmFzX3RpYmJsZShjdCkgJT4lCiAgICBkcGx5cjo6dHJhbnNtdXRlKAogICAgICB0ZXJtID0gdGVybSwKICAgICAgZXN0aW1hdGUgPSAuZGF0YVtbZXN0aW1hdGVfY29sXV0sCiAgICAgIHN0ZC5lcnJvciA9IC5kYXRhW1tzZV9jb2xdXSwKICAgICAgc3RhdGlzdGljID0gLmRhdGFbW3N0YXRpc3RpY19jb2xdXSwKICAgICAgcC52YWx1ZSA9IC5kYXRhW1twX2NvbF1dLAogICAgICBjb25mLmxvdyA9IGVzdGltYXRlIC0gMS45NiAqIHN0ZC5lcnJvciwKICAgICAgY29uZi5oaWdoID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yCiAgICApCn0KCnN0dWR5X3NwZWNzIDwtIGxpc3QoCiAgc3R1ZHkxID0gbGlzdCgKICAgIHN0dWR5X2lkID0gInN0dWR5MSIsCiAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAx77yIMjAyM+W5tO+8iSIsCiAgICBjb25kaXRpb25fbGFiZWwgPSAi5pS/5YWa5pWwIiwKICAgIGVudiA9IHN0dWR5MV9lbnYKICApLAogIHN0dWR5MiA9IGxpc3QoCiAgICBzdHVkeV9pZCA9ICJzdHVkeTIiLAogICAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkgMu+8iDIwMjblubTvvIkiLAogICAgY29uZGl0aW9uX2xhYmVsID0gIuaUv+WFmuaVsCIsCiAgICBlbnYgPSBzdHVkeTJfZW52CiAgKSwKICBzdHVkeTMgPSBsaXN0KAogICAgc3R1ZHlfaWQgPSAic3R1ZHkzIiwKICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDPvvIgyMDI25bm077yJIiwKICAgIGNvbmRpdGlvbl9sYWJlbCA9ICLpgbjmip7ogqLmlbAiLAogICAgZW52ID0gc3R1ZHkzX2VudgogICkKKQoKZXhjbHVkZWRfc3VwcG9ydF9jYXRlZ29yaWVzIDwtIGMoCiAgIuOBneOBruS7liIsCiAgIuOCj+OBi+OCieOBquOBhCIsCiAgIuetlOOBiOOBquOBhCIsCiAgIuetlOOBiOOBn+OBj+OBquOBhCIsCiAgIuasoOaQjeODu+eEoeWbnuetlCIKKQoKCiMg6KOc6YG6Q+mWoumAo+OCs+ODvOODiQpiYWxhbmNlX3ZhcmlhYmxlX2xhYmVscyA8LSBjKAogIGZlbWFsZV9pbXAgPSAi5aWz5oCnIiwKICBmZW1hbGVfbWlzcyA9ICLmgKfliKXvvJrmrKDmkI0iLAogIGFnZV9pbXAgPSAi5bm06b2iIiwKICBhZ2VfbWlzcyA9ICLlubTpvaLvvJrmrKDmkI0iLAogIGNvbGxlZ2VfZ3JhZF9pbXAgPSAiNOW5tOWItuWkp+WtpuS7peS4iiIsCiAgY29sbGVnZV9ncmFkX21pc3MgPSAi5a2m5q2077ya5qyg5pCNIiwKICBpbmNvbWVfZ3Jvc3NfbG9nX2ltcCA9ICLkuJbluK/lubTlj47vvIjlr77mlbDvvIkiLAogIGluY29tZV9ncm9zc19sb2dfbWlzcyA9ICLkuJbluK/lubTlj47vvJrmrKDmkI0iLAogIHNlbGZfaWRlb2xvZ3lfaW1wID0gIuW3puWPs+iHquW3seS9jee9ruOBpeOBkSIsCiAgc2VsZl9pZGVvbG9neV9taXNzID0gIuW3puWPs+iHquW3seS9jee9ruOBpeOBke+8muasoOaQjSIKKQoKbWFrZV9iYWxhbmNlX2Rlc2lnbiA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7CiAgZW52IDwtIHN0dWR5X3NwZWMkZW52CiAgCiAgYXNzaWdubWVudCA8LSBlbnYkY29uam9pbnRfYWxsICU+JQogICAgZHBseXI6OmRpc3RpbmN0KElELCBwYXJ0eV9uKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwKICAgICAgcGFydHlfbiA9IGFzLmludGVnZXIoYXMuY2hhcmFjdGVyKHBhcnR5X24pKQogICAgKQogIAogIHJlc3BvbmRlbnQgPC0gZW52JGNvdmFyX2lkICU+JQogICAgZHBseXI6Om11dGF0ZShJRCA9IGFzLmNoYXJhY3RlcihJRCkpCiAgCiAgZGF0IDwtIGFzc2lnbm1lbnQgJT4lCiAgICBkcGx5cjo6bGVmdF9qb2luKHJlc3BvbmRlbnQsIGJ5ID0gIklEIikKICAKICBudW1lcmljX2NhbmRpZGF0ZXMgPC0gYygKICAgICJmZW1hbGVfaW1wIiwKICAgICJmZW1hbGVfbWlzcyIsCiAgICAiYWdlX2ltcCIsCiAgICAiYWdlX21pc3MiLAogICAgImNvbGxlZ2VfZ3JhZF9pbXAiLAogICAgImNvbGxlZ2VfZ3JhZF9taXNzIiwKICAgICJpbmNvbWVfZ3Jvc3NfbG9nX2ltcCIsCiAgICAiaW5jb21lX2dyb3NzX2xvZ19taXNzIiwKICAgICJzZWxmX2lkZW9sb2d5X2ltcCIsCiAgICAic2VsZl9pZGVvbG9neV9taXNzIgogICkKICAKICBmYWN0b3JfY2FuZGlkYXRlcyA8LSBjKAogICAgInBhcnR5X3N1cHBvcnRfZiIsCiAgICAicmVnaW9uIgogICkKICAKICBudW1lcmljX3VzZSA8LSBpbnRlcnNlY3QobnVtZXJpY19jYW5kaWRhdGVzLCBuYW1lcyhkYXQpKQogIGZhY3Rvcl91c2UgPC0gaW50ZXJzZWN0KGZhY3Rvcl9jYW5kaWRhdGVzLCBuYW1lcyhkYXQpKQogIAogIGRlc2lnbl9zb3VyY2UgPC0gZGF0ICU+JQogICAgZHBseXI6OnNlbGVjdChkcGx5cjo6YWxsX29mKGMobnVtZXJpY191c2UsIGZhY3Rvcl91c2UpKSkKICAKICBpZiAobGVuZ3RoKGZhY3Rvcl91c2UpID4gMCkgewogICAgZGVzaWduX3NvdXJjZSA8LSBkZXNpZ25fc291cmNlICU+JQogICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgIGRwbHlyOjphY3Jvc3MoCiAgICAgICAgICBkcGx5cjo6YWxsX29mKGZhY3Rvcl91c2UpLAogICAgICAgICAgfiBmb3JjYXRzOjpmY3RfbmFfdmFsdWVfdG9fbGV2ZWwoYXMuZmFjdG9yKC54KSwgbGV2ZWwgPSAi5qyg5pCN44O754Sh5Zue562UIikKICAgICAgICApCiAgICAgICkKICB9CiAgCiAgbW0gPC0gc3RhdHM6Om1vZGVsLm1hdHJpeCgKICAgIHN0YXRzOjphcy5mb3JtdWxhKAogICAgICBwYXN0ZTAoCiAgICAgICAgIn4gMCArICIsCiAgICAgICAgcGFzdGUobmFtZXMoZGVzaWduX3NvdXJjZSksIGNvbGxhcHNlID0gIiArICIpCiAgICAgICkKICAgICksCiAgICBkYXRhID0gZGVzaWduX3NvdXJjZQogICkKICAKICBtbSA8LSBhcy5kYXRhLmZyYW1lKG1tLCBjaGVjay5uYW1lcyA9IEZBTFNFKQogIAogIGtlZXAgPC0gdmFwcGx5KAogICAgbW0sCiAgICBmdW5jdGlvbih4KSB7CiAgICAgIHggPC0gYXMubnVtZXJpYyh4KQogICAgICBpcy5maW5pdGUoc3RhdHM6OnNkKHgsIG5hLnJtID0gVFJVRSkpICYmIHN0YXRzOjpzZCh4LCBuYS5ybSA9IFRSVUUpID4gMAogICAgfSwKICAgIGxvZ2ljYWwoMSkKICApCiAgCiAgbW0gPC0gbW1bLCBrZWVwLCBkcm9wID0gRkFMU0VdCiAgCiAgbW0gPC0gbW0gJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBJRCA9IGRhdCRJRCwKICAgICAgcGFydHlfbiA9IGRhdCRwYXJ0eV9uLAogICAgICAuYmVmb3JlID0gMQogICAgKQogIAogIGxvbmcgPC0gbW0gJT4lCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKAogICAgICBjb2xzID0gLWMoSUQsIHBhcnR5X24pLAogICAgICBuYW1lc190byA9ICJ2YXJpYWJsZSIsCiAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIKICAgICkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBsYWJlbCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgdmFyaWFibGUgJWluJSBuYW1lcyhiYWxhbmNlX3ZhcmlhYmxlX2xhYmVscykgfgogICAgICAgICAgdW5uYW1lKGJhbGFuY2VfdmFyaWFibGVfbGFiZWxzW3ZhcmlhYmxlXSksCiAgICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCh2YXJpYWJsZSwgIl5wYXJ0eV9zdXBwb3J0X2YiKSB+CiAgICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAgICLmlK/mjIHmlL/lhZrvvJoiLAogICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlKHZhcmlhYmxlLCAiXnBhcnR5X3N1cHBvcnRfZiIpCiAgICAgICAgICApLAogICAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QodmFyaWFibGUsICJecmVnaW9uIikgfgogICAgICAgICAgcGFzdGUwKAogICAgICAgICAgICAi5Zyw5Z+f77yaIiwKICAgICAgICAgICAgc3RyaW5ncjo6c3RyX3JlbW92ZSh2YXJpYWJsZSwgIl5yZWdpb24iKQogICAgICAgICAgKSwKICAgICAgICBUUlVFIH4gdmFyaWFibGUKICAgICAgKSwKICAgICAgc3R1ZHlfaWQgPSBzdHVkeV9zcGVjJHN0dWR5X2lkLAogICAgICBzdHVkeV9sYWJlbCA9IHN0dWR5X3NwZWMkc3R1ZHlfbGFiZWwKICAgICkKICAKICBsaXN0KAogICAgcmVzcG9uZGVudCA9IGRhdCwKICAgIG1hdHJpeCA9IG1tLAogICAgbG9uZyA9IGxvbmcsCiAgICBudW1lcmljX3VzZSA9IG51bWVyaWNfdXNlLAogICAgZmFjdG9yX3VzZSA9IGZhY3Rvcl91c2UKICApCn0KCnBhaXJ3aXNlX3NtZF9tdWx0aWFybSA8LSBmdW5jdGlvbihiYWxhbmNlX2xvbmcpIHsKICBncm91cHMgPC0gc29ydCh1bmlxdWUoYmFsYW5jZV9sb25nJHBhcnR5X24pKQogIHBhaXJzIDwtIHV0aWxzOjpjb21ibihncm91cHMsIDIsIHNpbXBsaWZ5ID0gRkFMU0UpCgogIHB1cnJyOjptYXBfZGZyKAogICAgcGFpcnMsCiAgICBmdW5jdGlvbihwYWlyX3ZhbHVlKSB7CiAgICAgIGEgPC0gcGFpcl92YWx1ZVsxXQogICAgICBiIDwtIHBhaXJfdmFsdWVbMl0KCiAgICAgIHdpZGUgPC0gYmFsYW5jZV9sb25nICU+JQogICAgICAgIGRwbHlyOjpmaWx0ZXIocGFydHlfbiAlaW4lIGMoYSwgYikpICU+JQogICAgICAgIGRwbHlyOjpncm91cF9ieSh2YXJpYWJsZSwgbGFiZWwsIHBhcnR5X24pICU+JQogICAgICAgIGRwbHlyOjpzdW1tYXJpc2UoCiAgICAgICAgICBtZWFuID0gbWVhbih2YWx1ZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgIHNkID0gc3RhdHM6OnNkKHZhbHVlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgbiA9IHN1bSghaXMubmEodmFsdWUpKSwKICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgICApICU+JQogICAgICAgIHRpZHlyOjpwaXZvdF93aWRlcigKICAgICAgICAgIG5hbWVzX2Zyb20gPSBwYXJ0eV9uLAogICAgICAgICAgdmFsdWVzX2Zyb20gPSBjKG1lYW4sIHNkLCBuKSwKICAgICAgICAgIG5hbWVzX3NlcCA9ICJfIgogICAgICAgICkKCiAgICAgIHdpZGUgJT4lCiAgICAgICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgICAgIHZhcmlhYmxlID0gdmFyaWFibGUsCiAgICAgICAgICBsYWJlbCA9IGxhYmVsLAogICAgICAgICAgY29uZGl0aW9uX2EgPSBhLAogICAgICAgICAgY29uZGl0aW9uX2IgPSBiLAogICAgICAgICAgY29tcGFyaXNvbiA9IHBhc3RlMChhLCAiIHZzICIsIGIpLAogICAgICAgICAgbWVhbl9hID0gLmRhdGFbW3Bhc3RlMCgibWVhbl8iLCBhKV1dLAogICAgICAgICAgbWVhbl9iID0gLmRhdGFbW3Bhc3RlMCgibWVhbl8iLCBiKV1dLAogICAgICAgICAgc2RfYSA9IC5kYXRhW1twYXN0ZTAoInNkXyIsIGEpXV0sCiAgICAgICAgICBzZF9iID0gLmRhdGFbW3Bhc3RlMCgic2RfIiwgYildXSwKICAgICAgICAgIG5fYSA9IC5kYXRhW1twYXN0ZTAoIm5fIiwgYSldXSwKICAgICAgICAgIG5fYiA9IC5kYXRhW1twYXN0ZTAoIm5fIiwgYildXSwKICAgICAgICAgIHBvb2xlZF9zZCA9IHNxcnQoKHNkX2FeMiArIHNkX2JeMikgLyAyKSwKICAgICAgICAgIHNtZCA9IGRwbHlyOjppZl9lbHNlKAogICAgICAgICAgICBpcy5maW5pdGUocG9vbGVkX3NkKSAmIHBvb2xlZF9zZCA+IDAsCiAgICAgICAgICAgIChtZWFuX2EgLSBtZWFuX2IpIC8gcG9vbGVkX3NkLAogICAgICAgICAgICBOQV9yZWFsXwogICAgICAgICAgKSwKICAgICAgICAgIGFic19zbWQgPSBhYnMoc21kKQogICAgICAgICkKICAgIH0KICApCn0KCm9tbmlidXNfYmFsYW5jZV90ZXN0IDwtIGZ1bmN0aW9uKGJhbGFuY2VfbG9uZykgewogIGJhbGFuY2VfbG9uZyAlPiUKICAgIGRwbHlyOjpncm91cF9ieSh2YXJpYWJsZSwgbGFiZWwpICU+JQogICAgZHBseXI6Omdyb3VwX21vZGlmeSgKICAgICAgfiB7CiAgICAgICAgZGF0IDwtIC54ICU+JQogICAgICAgICAgZHBseXI6OmZpbHRlcihpcy5maW5pdGUodmFsdWUpLCAhaXMubmEocGFydHlfbikpCiAgICAgICAgCiAgICAgICAgcF92YWx1ZSA8LSB0cnlDYXRjaCgKICAgICAgICAgIHsKICAgICAgICAgICAgbW9kZWwgPC0gc3RhdHM6OmxtKHZhbHVlIH4gZmFjdG9yKHBhcnR5X24pLCBkYXRhID0gZGF0KQogICAgICAgICAgICBhcy5udW1lcmljKHN0YXRzOjphbm92YShtb2RlbClbMSwgIlByKD5GKSJdKQogICAgICAgICAgfSwKICAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgTkFfcmVhbF8KICAgICAgICApCiAgICAgICAgCiAgICAgICAgdGliYmxlOjp0aWJibGUocF92YWx1ZSA9IHBfdmFsdWUpCiAgICAgIH0KICAgICkgJT4lCiAgICBkcGx5cjo6dW5ncm91cCgpICU+JQogICAgZHBseXI6Om11dGF0ZShwX2hvbG0gPSBzdGF0czo6cC5hZGp1c3QocF92YWx1ZSwgbWV0aG9kID0gImhvbG0iKSkKfQoKbWFrZV9iYWxhbmNlX291dHB1dHMgPC0gZnVuY3Rpb24oc3R1ZHlfc3BlYykgewogIGRlc2lnbiA8LSBtYWtlX2JhbGFuY2VfZGVzaWduKHN0dWR5X3NwZWMpCiAgbG9uZyA8LSBkZXNpZ24kbG9uZwogIHBhaXJ3aXNlIDwtIHBhaXJ3aXNlX3NtZF9tdWx0aWFybShsb25nKQogIG9tbmlidXMgPC0gb21uaWJ1c19iYWxhbmNlX3Rlc3QobG9uZykKICAKICBtYXhfc21kIDwtIHBhaXJ3aXNlICU+JQogICAgZHBseXI6Omdyb3VwX2J5KHZhcmlhYmxlLCBsYWJlbCkgJT4lCiAgICBkcGx5cjo6c3VtbWFyaXNlKAogICAgICBtYXhfYWJzX3NtZCA9IGRwbHlyOjppZl9lbHNlKAogICAgICAgIGFsbChpcy5uYShhYnNfc21kKSksCiAgICAgICAgTkFfcmVhbF8sCiAgICAgICAgbWF4KGFic19zbWQsIG5hLnJtID0gVFJVRSkKICAgICAgKSwKICAgICAgbWVhbl9hYnNfc21kID0gZHBseXI6OmlmX2Vsc2UoCiAgICAgICAgYWxsKGlzLm5hKGFic19zbWQpKSwKICAgICAgICBOQV9yZWFsXywKICAgICAgICBtZWFuKGFic19zbWQsIG5hLnJtID0gVFJVRSkKICAgICAgKSwKICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgKQogIAogIGdyb3VwX3N1bW1hcnkgPC0gbG9uZyAlPiUKICAgIGRwbHlyOjpncm91cF9ieSh2YXJpYWJsZSwgbGFiZWwsIHBhcnR5X24pICU+JQogICAgZHBseXI6OnN1bW1hcmlzZSgKICAgICAgbWVhbiA9IG1lYW4odmFsdWUsIG5hLnJtID0gVFJVRSksCiAgICAgIHNkID0gc3RhdHM6OnNkKHZhbHVlLCBuYS5ybSA9IFRSVUUpLAogICAgICBuID0gc3VtKCFpcy5uYSh2YWx1ZSkpLAogICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICApICU+JQogICAgdGlkeXI6OnBpdm90X3dpZGVyKAogICAgICBuYW1lc19mcm9tID0gcGFydHlfbiwKICAgICAgdmFsdWVzX2Zyb20gPSBjKG1lYW4sIHNkLCBuKSwKICAgICAgbmFtZXNfZ2x1ZSA9ICJ7LnZhbHVlfV9jb25kaXRpb25fe3BhcnR5X259IgogICAgKSAlPiUKICAgIGRwbHlyOjpsZWZ0X2pvaW4obWF4X3NtZCwgYnkgPSBjKCJ2YXJpYWJsZSIsICJsYWJlbCIpKSAlPiUKICAgIGRwbHlyOjpsZWZ0X2pvaW4ob21uaWJ1cywgYnkgPSBjKCJ2YXJpYWJsZSIsICJsYWJlbCIpKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKGRwbHlyOjpkZXNjKG1heF9hYnNfc21kKSkKICAKICB3cml0ZV9jc3ZfdW5pZmllZCgKICAgIHBhaXJ3aXNlLAogICAgcGFzdGUwKHN0dWR5X3NwZWMkc3R1ZHlfaWQsICJfYXNzaWdubWVudF9iYWxhbmNlX3BhaXJ3aXNlX3NtZC5jc3YiKQogICkKICB3cml0ZV9jc3ZfdW5pZmllZCgKICAgIGdyb3VwX3N1bW1hcnksCiAgICBwYXN0ZTAoc3R1ZHlfc3BlYyRzdHVkeV9pZCwgIl9hc3NpZ25tZW50X2JhbGFuY2Vfc3VtbWFyeS5jc3YiKQogICkKICAKICBsb3ZlX2RmIDwtIHBhaXJ3aXNlICU+JQogICAgZHBseXI6OmxlZnRfam9pbihtYXhfc21kLCBieSA9IGMoInZhcmlhYmxlIiwgImxhYmVsIikpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbGFiZWxfb3JkZXJlZCA9IHN0YXRzOjpyZW9yZGVyKGxhYmVsLCBtYXhfYWJzX3NtZCkKICAgICkKICAKICBwX2xvdmUgPC0gZ2dwbG90Mjo6Z2dwbG90KAogICAgbG92ZV9kZiwKICAgIGdncGxvdDI6OmFlcygKICAgICAgeCA9IGFic19zbWQsCiAgICAgIHkgPSBsYWJlbF9vcmRlcmVkCiAgICApCiAgKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKAogICAgICB4aW50ZXJjZXB0ID0gMC4xMCwKICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgICAgbGluZXdpZHRoID0gMC41NQogICAgKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3BvaW50KAogICAgICBhbHBoYSA9IDAuMzAsCiAgICAgIHNpemUgPSAxLjQsCiAgICAgIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25faml0dGVyKGhlaWdodCA9IDAuMTAsIHdpZHRoID0gMCkKICAgICkgKwogICAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgKICAgICAgZGF0YSA9IG1heF9zbWQgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZShsYWJlbF9vcmRlcmVkID0gc3RhdHM6OnJlb3JkZXIobGFiZWwsIG1heF9hYnNfc21kKSksCiAgICAgIGdncGxvdDI6OmFlcygKICAgICAgICB4ID0gbWF4X2Fic19zbWQsCiAgICAgICAgeSA9IGxhYmVsX29yZGVyZWQKICAgICAgKSwKICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwKICAgICAgc2hhcGUgPSAyMSwKICAgICAgZmlsbCA9ICJ3aGl0ZSIsCiAgICAgIHNpemUgPSAyLjUsCiAgICAgIHN0cm9rZSA9IDAuOAogICAgKSArCiAgICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcyhuID0gNiksCiAgICAgIGV4cGFuZCA9IGdncGxvdDI6OmV4cGFuc2lvbihtdWx0ID0gYygwLCAwLjA1KSkKICAgICkgKwogICAgZ2dwbG90Mjo6bGFicygKICAgICAgeCA9ICLmnaHku7bplpPjga7ntbblr77mqJnmupbljJblubPlnYflt67vvIh8U01EfO+8iSIsCiAgICAgIHkgPSBOVUxMLAogICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgKICAgICAgICBzdHVkeV9zcGVjJHN0dWR5X2xhYmVsLAogICAgICAgICLvvJrlkITngrnjga/mnaHku7bjg5rjgqLjgIHnmb3mipzjgY3ngrnjga/mnIDlpKfntbblr75TTUQiCiAgICAgICksCiAgICAgIGNhcHRpb24gPSAi56C057ea44GvIHxTTUR8ID0gMC4xMOOAguWkmue+pOeEoeS9nOeCuuWJsuS7mOOBruOBn+OCgeOAgTLjg7sz44O7NOODuzXmnaHku7bjga7lhag244Oa44Ki44KS5q+U6LyD44CCIgogICAgKSArCiAgICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKwogICAgZ2dwbG90Mjo6dGhlbWUoCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksCiAgICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLAogICAgICBwbG90LnN1YnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpCiAgICApCiAgCiAgc2F2ZV9wbG90X2JvdGgoCiAgICBwYXN0ZTAoc3R1ZHlfc3BlYyRzdHVkeV9pZCwgIl9hc3NpZ25tZW50X2JhbGFuY2VfbG92ZV9wbG90IiksCiAgICBwX2xvdmUsCiAgICB3aWR0aCA9IDkuMiwKICAgIGhlaWdodCA9IG1heCg2LjUsIDAuMjMgKiBkcGx5cjo6bl9kaXN0aW5jdChsb3ZlX2RmJGxhYmVsKSArIDIuNSkKICApCiAgCiAgc3RhbmRhcmRpemVkX21lYW5zIDwtIGxvbmcgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkodmFyaWFibGUsIGxhYmVsKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIG92ZXJhbGxfbWVhbiA9IG1lYW4odmFsdWUsIG5hLnJtID0gVFJVRSksCiAgICAgIG92ZXJhbGxfc2QgPSBzdGF0czo6c2QodmFsdWUsIG5hLnJtID0gVFJVRSksCiAgICAgIHZhbHVlX3ogPSBkcGx5cjo6aWZfZWxzZSgKICAgICAgICBpcy5maW5pdGUob3ZlcmFsbF9zZCkgJiBvdmVyYWxsX3NkID4gMCwKICAgICAgICAodmFsdWUgLSBvdmVyYWxsX21lYW4pIC8gb3ZlcmFsbF9zZCwKICAgICAgICBOQV9yZWFsXwogICAgICApCiAgICApICU+JQogICAgZHBseXI6OnVuZ3JvdXAoKSAlPiUKICAgIGRwbHlyOjpncm91cF9ieSh2YXJpYWJsZSwgbGFiZWwsIHBhcnR5X24pICU+JQogICAgZHBseXI6OnN1bW1hcmlzZSgKICAgICAgbWVhbl96ID0gbWVhbih2YWx1ZV96LCBuYS5ybSA9IFRSVUUpLAogICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICApCiAgCiAgZ3JvdXBzIDwtIHNvcnQodW5pcXVlKHN0YW5kYXJkaXplZF9tZWFucyRwYXJ0eV9uKSkKICBkaWFnb25hbF9kZiA8LSBwdXJycjo6bWFwX2RmcigKICAgIHV0aWxzOjpjb21ibihncm91cHMsIDIsIHNpbXBsaWZ5ID0gRkFMU0UpLAogICAgZnVuY3Rpb24ocGFpcl92YWx1ZSkgewogICAgICBhIDwtIHBhaXJfdmFsdWVbMV0KICAgICAgYiA8LSBwYWlyX3ZhbHVlWzJdCiAgICAgIAogICAgICBzdGFuZGFyZGl6ZWRfbWVhbnMgJT4lCiAgICAgICAgZHBseXI6OmZpbHRlcihwYXJ0eV9uICVpbiUgYyhhLCBiKSkgJT4lCiAgICAgICAgdGlkeXI6OnBpdm90X3dpZGVyKAogICAgICAgICAgbmFtZXNfZnJvbSA9IHBhcnR5X24sCiAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG1lYW5feiwKICAgICAgICAgIG5hbWVzX3ByZWZpeCA9ICJjb25kaXRpb25fIgogICAgICAgICkgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgIGNvbmRpdGlvbl9hID0gYSwKICAgICAgICAgIGNvbmRpdGlvbl9iID0gYiwKICAgICAgICAgIGNvbXBhcmlzb24gPSBwYXN0ZTAoYSwgIiB2cyAiLCBiKSwKICAgICAgICAgIHhfbWVhbiA9IC5kYXRhW1twYXN0ZTAoImNvbmRpdGlvbl8iLCBhKV1dLAogICAgICAgICAgeV9tZWFuID0gLmRhdGFbW3Bhc3RlMCgiY29uZGl0aW9uXyIsIGIpXV0sCiAgICAgICAgICBkaWFnb25hbF9kZXZpYXRpb24gPSB5X21lYW4gLSB4X21lYW4sCiAgICAgICAgICBhYnNfZGlhZ29uYWxfZGV2aWF0aW9uID0gYWJzKGRpYWdvbmFsX2RldmlhdGlvbikKICAgICAgICApCiAgICB9CiAgKQogIAogIHRvcF9sYWJlbHMgPC0gZGlhZ29uYWxfZGYgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoY29tcGFyaXNvbikgJT4lCiAgICBkcGx5cjo6c2xpY2VfbWF4KAogICAgICBvcmRlcl9ieSA9IGFic19kaWFnb25hbF9kZXZpYXRpb24sCiAgICAgIG4gPSAzLAogICAgICB3aXRoX3RpZXMgPSBGQUxTRQogICAgKSAlPiUKICAgIGRwbHlyOjp1bmdyb3VwKCkKICAKICBheGlzX2xpbWl0IDwtIG1heCgKICAgIGFicyhjKGRpYWdvbmFsX2RmJHhfbWVhbiwgZGlhZ29uYWxfZGYkeV9tZWFuKSksCiAgICBuYS5ybSA9IFRSVUUKICApCiAgYXhpc19saW1pdCA8LSBtYXgoMC4xMCwgYXhpc19saW1pdCAqIDEuMTUpCiAgCiAgcF9kaWFnb25hbCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoCiAgICBkaWFnb25hbF9kZiwKICAgIGdncGxvdDI6OmFlcyh4ID0geF9tZWFuLCB5ID0geV9tZWFuKQogICkgKwogICAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoCiAgICAgIGludGVyY2VwdCA9IDAsCiAgICAgIHNsb3BlID0gMSwKICAgICAgbGluZXdpZHRoID0gMC42MCwKICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIgogICAgKSArCiAgICBnZ3Bsb3QyOjpnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjI1KSArCiAgICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjI1KSArCiAgICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAid2hpdGUiLCBzaXplID0gMi4yKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3RleHQoCiAgICAgIGRhdGEgPSB0b3BfbGFiZWxzLAogICAgICBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsYWJlbCksCiAgICAgIHNpemUgPSAyLjYsCiAgICAgIGNoZWNrX292ZXJsYXAgPSBUUlVFLAogICAgICB2anVzdCA9IC0wLjcKICAgICkgKwogICAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IGNvbXBhcmlzb24sIG5jb2wgPSAzKSArCiAgICBnZ3Bsb3QyOjpjb29yZF9lcXVhbCgKICAgICAgeGxpbSA9IGMoLWF4aXNfbGltaXQsIGF4aXNfbGltaXQpLAogICAgICB5bGltID0gYygtYXhpc19saW1pdCwgYXhpc19saW1pdCkKICAgICkgKwogICAgZ2dwbG90Mjo6bGFicygKICAgICAgeCA9ICLlt6blgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciLAogICAgICB5ID0gIuWPs+WBtOadoeS7tuOBruaomea6luWMluWFseWkiemHj+W5s+WdhyIsCiAgICAgIHN1YnRpdGxlID0gcGFzdGUwKAogICAgICAgIHN0dWR5X3NwZWMkc3R1ZHlfbGFiZWwsCiAgICAgICAgIu+8mjQ15bqm57ea44GL44KJ44Gu5LmW6Zui44Gr44KI44KL5Ymy5LuY44OQ44Op44Oz44K56Ki65patIgogICAgICApLAogICAgICBjYXB0aW9uID0gIuWQhOeCueOBr+WbnuetlOiAheWFseWkiemHj+OBvuOBn+OBr+aUr+aMgeaUv+WFmuODu+WcsOWfn+OBruODgOODn+ODvOWkieaVsOOAgjQ15bqm57ea44Gr6L+R44GE44G744Gp5p2h5Lu26ZaT44Gu5qeL5oiQ44GM6aGe5Ly844CCIgogICAgKSArCiAgICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMC41KSArCiAgICBnZ3Bsb3QyOjp0aGVtZSgKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGdncGxvdDI6OmVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksCiAgICAgIHN0cmlwLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksCiAgICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpCiAgICApCiAgCiAgd3JpdGVfY3N2X3VuaWZpZWQoCiAgICBkaWFnb25hbF9kZiwKICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX2Fzc2lnbm1lbnRfYmFsYW5jZV9kaWFnb25hbF9kYXRhLmNzdiIpCiAgKQogIAogIHNhdmVfcGxvdF9ib3RoKAogICAgcGFzdGUwKHN0dWR5X3NwZWMkc3R1ZHlfaWQsICJfYXNzaWdubWVudF9iYWxhbmNlX2RpYWdvbmFsX3Bsb3QiKSwKICAgIHBfZGlhZ29uYWwsCiAgICB3aWR0aCA9IDExLjUsCiAgICBoZWlnaHQgPSA3LjUKICApCiAgCiAgbGlzdCgKICAgIGRlc2lnbiA9IGRlc2lnbiwKICAgIHBhaXJ3aXNlX3NtZCA9IHBhaXJ3aXNlLAogICAgc3VtbWFyeSA9IGdyb3VwX3N1bW1hcnksCiAgICBsb3ZlX3Bsb3QgPSBwX2xvdmUsCiAgICBkaWFnb25hbF9kYXRhID0gZGlhZ29uYWxfZGYsCiAgICBkaWFnb25hbF9wbG90ID0gcF9kaWFnb25hbAogICkKfQoKYXNzaWdubWVudF9iYWxhbmNlX3Jlc3VsdHMgPC0gcHVycnI6Om1hcCgKICBzdHVkeV9zcGVjcywKICBtYWtlX2JhbGFuY2Vfb3V0cHV0cwopCgoKbWFrZV9wcm9maWxlX3JhbmRvbWl6YXRpb25fb3V0cHV0cyA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7CiAgZW52IDwtIHN0dWR5X3NwZWMkZW52CiAgYXR0cmlidXRlcyA8LSBlbnYkYXR0cl90ZXJtcwogIAogIHJhbmRvbWl6YXRpb25fbG9uZyA8LSBlbnYkY29uam9pbnRfYWxsX20gJT4lCiAgICBkcGx5cjo6c2VsZWN0KAogICAgICBJRCwKICAgICAgcGFydHlfbiwKICAgICAgdGFzaywKICAgICAgcHJvZmlsZSwKICAgICAgZHBseXI6OmFsbF9vZihhdHRyaWJ1dGVzKQogICAgKSAlPiUKICAgIHRpZHlyOjpwaXZvdF9sb25nZXIoCiAgICAgIGNvbHMgPSBkcGx5cjo6YWxsX29mKGF0dHJpYnV0ZXMpLAogICAgICBuYW1lc190byA9ICJhdHRyaWJ1dGUiLAogICAgICB2YWx1ZXNfdG8gPSAibGV2ZWwiCiAgICApICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbGV2ZWwgPSBhcy5jaGFyYWN0ZXIobGV2ZWwpLAogICAgICBwYXJ0eV9uID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocGFydHlfbikpCiAgICApICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEobGV2ZWwpLCBsZXZlbCAhPSAiIikKICAKICBmcmVxdWVuY3kgPC0gcmFuZG9taXphdGlvbl9sb25nICU+JQogICAgZHBseXI6OmNvdW50KHBhcnR5X24sIGF0dHJpYnV0ZSwgbGV2ZWwsIG5hbWUgPSAib2JzZXJ2ZWRfbiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KHBhcnR5X24sIGF0dHJpYnV0ZSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICB0b3RhbF9uID0gc3VtKG9ic2VydmVkX24pLAogICAgICBuX2xldmVscyA9IGRwbHlyOjpuKCksCiAgICAgIG9ic2VydmVkX3NoYXJlID0gb2JzZXJ2ZWRfbiAvIHRvdGFsX24sCiAgICAgIGV4cGVjdGVkX3NoYXJlID0gMSAvIG5fbGV2ZWxzLAogICAgICBkZXZpYXRpb24gPSBvYnNlcnZlZF9zaGFyZSAtIGV4cGVjdGVkX3NoYXJlLAogICAgICBhYnNfZGV2aWF0aW9uID0gYWJzKGRldmlhdGlvbikKICAgICkgJT4lCiAgICBkcGx5cjo6dW5ncm91cCgpCiAgCiAgdW5pZm9ybWl0eV90ZXN0cyA8LSBmcmVxdWVuY3kgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkocGFydHlfbiwgYXR0cmlidXRlKSAlPiUKICAgIGRwbHlyOjpncm91cF9tb2RpZnkoCiAgICAgIH4gewogICAgICAgIHRlc3QgPC0gc3VwcHJlc3NXYXJuaW5ncygKICAgICAgICAgIHN0YXRzOjpjaGlzcS50ZXN0KAogICAgICAgICAgICB4ID0gLngkb2JzZXJ2ZWRfbiwKICAgICAgICAgICAgcCA9IHJlcCgxIC8gbnJvdygueCksIG5yb3coLngpKQogICAgICAgICAgKQogICAgICAgICkKICAgICAgICB0aWJibGU6OnRpYmJsZSgKICAgICAgICAgIGNoaV9zcXVhcmUgPSB1bm5hbWUodGVzdCRzdGF0aXN0aWMpLAogICAgICAgICAgZGYgPSB1bm5hbWUodGVzdCRwYXJhbWV0ZXIpLAogICAgICAgICAgcF92YWx1ZSA9IHRlc3QkcC52YWx1ZSwKICAgICAgICAgIG1heF9hYnNfc2hhcmVfZGV2aWF0aW9uID0gbWF4KC54JGFic19kZXZpYXRpb24pCiAgICAgICAgKQogICAgICB9CiAgICApICU+JQogICAgZHBseXI6OnVuZ3JvdXAoKSAlPiUKICAgIGRwbHlyOjptdXRhdGUocF9ob2xtID0gc3RhdHM6OnAuYWRqdXN0KHBfdmFsdWUsIG1ldGhvZCA9ICJob2xtIikpCiAgCiAgd3JpdGVfY3N2X3VuaWZpZWQoCiAgICBmcmVxdWVuY3ksCiAgICBwYXN0ZTAoc3R1ZHlfc3BlYyRzdHVkeV9pZCwgIl9wcm9maWxlX2xldmVsX3JhbmRvbWl6YXRpb25fZnJlcXVlbmN5LmNzdiIpCiAgKQogIHdyaXRlX2Nzdl91bmlmaWVkKAogICAgdW5pZm9ybWl0eV90ZXN0cywKICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX3Byb2ZpbGVfbGV2ZWxfcmFuZG9taXphdGlvbl90ZXN0cy5jc3YiKQogICkKICAKICB0b3BfZnJlcXVlbmN5X2xhYmVscyA8LSBmcmVxdWVuY3kgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkocGFydHlfbiwgYXR0cmlidXRlKSAlPiUKICAgIGRwbHlyOjpzbGljZV9tYXgoYWJzX2RldmlhdGlvbiwgbiA9IDEsIHdpdGhfdGllcyA9IEZBTFNFKSAlPiUKICAgIGRwbHlyOjp1bmdyb3VwKCkKICAKICBwX3JhbmRvbWl6YXRpb24gPC0gZ2dwbG90Mjo6Z2dwbG90KAogICAgZnJlcXVlbmN5LAogICAgZ2dwbG90Mjo6YWVzKAogICAgICB4ID0gZXhwZWN0ZWRfc2hhcmUsCiAgICAgIHkgPSBvYnNlcnZlZF9zaGFyZQogICAgKQogICkgKwogICAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoCiAgICAgIGludGVyY2VwdCA9IDAsCiAgICAgIHNsb3BlID0gMSwKICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgICAgbGluZXdpZHRoID0gMC42NQogICAgKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3BvaW50KAogICAgICBnZ3Bsb3QyOjphZXMoc2hhcGUgPSBmYWN0b3IocGFydHlfbikpLAogICAgICBzaXplID0gMi4yLAogICAgICBmaWxsID0gIndoaXRlIgogICAgKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3RleHQoCiAgICAgIGRhdGEgPSB0b3BfZnJlcXVlbmN5X2xhYmVscywKICAgICAgZ2dwbG90Mjo6YWVzKGxhYmVsID0gbGV2ZWwpLAogICAgICBzaXplID0gMi40LAogICAgICBjaGVja19vdmVybGFwID0gVFJVRSwKICAgICAgdmp1c3QgPSAtMC43CiAgICApICsKICAgIGdncGxvdDI6OmZhY2V0X3dyYXAofiBhdHRyaWJ1dGUsIG5jb2wgPSAzKSArCiAgICBnZ3Bsb3QyOjpjb29yZF9lcXVhbCgpICsKICAgIGdncGxvdDI6OmxhYnMoCiAgICAgIHggPSAi6Kit6KiI5LiK44Gu5pyf5b6F5q+U546HIiwKICAgICAgeSA9ICLoprPmuKzmr5TnjociLAogICAgICBzaGFwZSA9IHN0dWR5X3NwZWMkY29uZGl0aW9uX2xhYmVsLAogICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgKICAgICAgICBzdHVkeV9zcGVjJHN0dWR5X2xhYmVsLAogICAgICAgICLvvJrlsZ7mgKfmsLTmupbjga7oprPmuKzmr5TnjofjgajmnJ/lvoXmr5TnjociCiAgICAgICksCiAgICAgIGNhcHRpb24gPSAi5ZCE54K544Gv5bGe5oCn5rC05rqWw5fmnaHku7bjgII0NeW6pue3muOBq+i/keOBhOOBu+OBqeWxnuaAp+awtOa6luOBrueEoeS9nOeCuuaPkOekuuOBjOioreioiOOBqeOBiuOCiuOAgiIKICAgICkgKwogICAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKwogICAgZ2dwbG90Mjo6dGhlbWUoCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBnZ3Bsb3QyOjplbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLAogICAgICBzdHJpcC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikKICAgICkKICAKICBzYXZlX3Bsb3RfYm90aCgKICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9kaWFnb25hbF9wbG90IiksCiAgICBwX3JhbmRvbWl6YXRpb24sCiAgICB3aWR0aCA9IDExLAogICAgaGVpZ2h0ID0gaWZlbHNlKHN0dWR5X3NwZWMkc3R1ZHlfaWQgPT0gInN0dWR5MyIsIDcuNSwgOC41KQogICkKICAKICBsaXN0KAogICAgZnJlcXVlbmN5ID0gZnJlcXVlbmN5LAogICAgdW5pZm9ybWl0eV90ZXN0cyA9IHVuaWZvcm1pdHlfdGVzdHMsCiAgICBwbG90ID0gcF9yYW5kb21pemF0aW9uCiAgKQp9Cgpwcm9maWxlX3JhbmRvbWl6YXRpb25fcmVzdWx0cyA8LSBwdXJycjo6bWFwKAogIHN0dWR5X3NwZWNzLAogIG1ha2VfcHJvZmlsZV9yYW5kb21pemF0aW9uX291dHB1dHMKKQoKCiMg6KOc6YG6SOmWoumAo+OCs+ODvOODiQptYWtlX3Rlcm1fbGFiZWxfdGFibGUgPC0gZnVuY3Rpb24oZW52KSB7CiAgaWYgKGV4aXN0cygidGVybV9sYWJlbHMiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsKICAgIG91dCA8LSBnZXQoInRlcm1fbGFiZWxzIiwgZW52aXIgPSBlbnYpCiAgICByZXF1aXJlZCA8LSBjKCJ0ZXJtIiwgImF0dHJpYnV0ZSIsICJsYWJlbCIpCiAgICBpZiAoYWxsKHJlcXVpcmVkICVpbiUgbmFtZXMob3V0KSkpIHsKICAgICAgcmV0dXJuKG91dCAlPiUgZHBseXI6OnNlbGVjdChkcGx5cjo6YW55X29mKGMocmVxdWlyZWQsICJvcmRlciIpKSkpCiAgICB9CiAgfQogIAogIHRpYmJsZTo6dGliYmxlKAogICAgdGVybSA9IGNoYXJhY3RlcigpLAogICAgYXR0cmlidXRlID0gY2hhcmFjdGVyKCksCiAgICBsYWJlbCA9IGNoYXJhY3RlcigpLAogICAgb3JkZXIgPSBpbnRlZ2VyKCkKICApCn0KCnJ1bl9zdXBwb3J0X2FtY2VfaGV0ZXJvZ2VuZWl0eSA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7CiAgZW52IDwtIHN0dWR5X3NwZWMkZW52CiAgc3R1ZHlfaWQgPC0gc3R1ZHlfc3BlYyRzdHVkeV9pZAogIHN0dWR5X2xhYmVsIDwtIHN0dWR5X3NwZWMkc3R1ZHlfbGFiZWwKICBvdXRfZGlyIDwtIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsIHBhc3RlMChzdHVkeV9pZCwgIl9wYXJ0eV9zdXBwb3J0IikpCiAgZGlyLmNyZWF0ZShvdXRfZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkKICAKICBzdXBwb3J0X2lkIDwtIGVudiRjb3Zhcl9pZCAlPiUKICAgIGRwbHlyOjp0cmFuc211dGUoCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwKICAgICAgcGFydHlfc3VwcG9ydF9oID0gYXMuY2hhcmFjdGVyKHBhcnR5X3N1cHBvcnRfZikKICAgICkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBkcGx5cjo6bmFfaWYocGFydHlfc3VwcG9ydF9oLCAi5qyg5pCN44O754Sh5Zue562UIikKICAgICkKICAKICBkYXQgPC0gZW52JGNvbmpvaW50X2FsbF9tICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAogICAgICBwYXJ0eV9uID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocGFydHlfbikpCiAgICApICU+JQogICAgZHBseXI6OmxlZnRfam9pbihzdXBwb3J0X2lkLCBieSA9ICJJRCIpICU+JQogICAgZHBseXI6OmZpbHRlcigKICAgICAgIWlzLm5hKHBhcnR5X3N1cHBvcnRfaCksCiAgICAgIHBhcnR5X3N1cHBvcnRfaCAhPSAiIiwKICAgICAgIXBhcnR5X3N1cHBvcnRfaCAlaW4lIGV4Y2x1ZGVkX3N1cHBvcnRfY2F0ZWdvcmllcwogICAgKQogIAogIHN1cHBvcnRfY291bnRzIDwtIGRhdCAlPiUKICAgIGRwbHlyOjpkaXN0aW5jdChJRCwgcGFydHlfbiwgcGFydHlfc3VwcG9ydF9oKSAlPiUKICAgIGRwbHlyOjpjb3VudChwYXJ0eV9zdXBwb3J0X2gsIHBhcnR5X24sIG5hbWUgPSAibl9jb25kaXRpb24iKSAlPiUKICAgIGRwbHlyOjpncm91cF9ieShwYXJ0eV9zdXBwb3J0X2gpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbl90b3RhbCA9IHN1bShuX2NvbmRpdGlvbiksCiAgICAgIG1pbl9jb25kaXRpb25fbiA9IG1pbihuX2NvbmRpdGlvbiksCiAgICAgIGNvbmRpdGlvbnNfb2JzZXJ2ZWQgPSBkcGx5cjo6bl9kaXN0aW5jdChwYXJ0eV9uKQogICAgKSAlPiUKICAgIGRwbHlyOjp1bmdyb3VwKCkKICAKICBzdXBwb3J0X3RvdGFscyA8LSBkYXQgJT4lCiAgICBkcGx5cjo6ZGlzdGluY3QoSUQsIHBhcnR5X3N1cHBvcnRfaCkgJT4lCiAgICBkcGx5cjo6Y291bnQocGFydHlfc3VwcG9ydF9oLCBuYW1lID0gIm5fdG90YWxfZGlzdGluY3QiKQogIAogIHN1cHBvcnRfY291bnRzIDwtIHN1cHBvcnRfY291bnRzICU+JQogICAgZHBseXI6OmxlZnRfam9pbihzdXBwb3J0X3RvdGFscywgYnkgPSAicGFydHlfc3VwcG9ydF9oIikgJT4lCiAgICBkcGx5cjo6YXJyYW5nZShkcGx5cjo6ZGVzYyhuX3RvdGFsX2Rpc3RpbmN0KSwgcGFydHlfc3VwcG9ydF9oKQogIAogIGVsaWdpYmxlX2dyb3VwcyA8LSBzdXBwb3J0X2NvdW50cyAlPiUKICAgIGRwbHlyOjpkaXN0aW5jdCgKICAgICAgcGFydHlfc3VwcG9ydF9oLAogICAgICBuX3RvdGFsX2Rpc3RpbmN0LAogICAgICBtaW5fY29uZGl0aW9uX24sCiAgICAgIGNvbmRpdGlvbnNfb2JzZXJ2ZWQKICAgICkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKAogICAgICBuX3RvdGFsX2Rpc3RpbmN0ID49IHVuaWZpZWRfY29uZmlnJG1pbl9zdXBwb3J0X3RvdGFsX24sCiAgICAgIGNvbmRpdGlvbnNfb2JzZXJ2ZWQgPT0gNAogICAgKSAlPiUKICAgIGRwbHlyOjpwdWxsKHBhcnR5X3N1cHBvcnRfaCkKICAKICByZWFkcjo6d3JpdGVfY3N2KAogICAgc3VwcG9ydF9jb3VudHMsCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X3N1cHBvcnRfc2FtcGxlX2NvdW50cy5jc3YiKSwKICAgIG5hID0gIiIKICApCiAgCiAgZm9ybXVsYV9zdWJncm91cCA8LSBzdGF0czo6YXMuZm9ybXVsYSgKICAgIHBhc3RlKAogICAgICAic2VsZWN0ZWQgfiIsCiAgICAgIHBhc3RlKGVudiRhdHRyX3Rlcm1zLCBjb2xsYXBzZSA9ICIgKyAiKQogICAgKQogICkKICAKICBlc3RpbWF0ZV9vbmVfY2VsbCA8LSBmdW5jdGlvbihncm91cF92YWx1ZSwgbl92YWx1ZSkgewogICAgZGF0X2NlbGwgPC0gZGF0ICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKAogICAgICAgIHBhcnR5X3N1cHBvcnRfaCA9PSBncm91cF92YWx1ZSwKICAgICAgICBwYXJ0eV9uID09IG5fdmFsdWUKICAgICAgKQogICAgCiAgICBuX2lkcyA8LSBkcGx5cjo6bl9kaXN0aW5jdChkYXRfY2VsbCRJRCkKICAgIAogICAgaWYgKG5faWRzIDwgdW5pZmllZF9jb25maWckbWluX3N1cHBvcnRfY2VsbF9uKSB7CiAgICAgIHJldHVybigKICAgICAgICB0aWJibGU6OnRpYmJsZSgKICAgICAgICAgIHRlcm0gPSBOQV9jaGFyYWN0ZXJfLAogICAgICAgICAgZXN0aW1hdGUgPSBOQV9yZWFsXywKICAgICAgICAgIHN0ZC5lcnJvciA9IE5BX3JlYWxfLAogICAgICAgICAgc3RhdGlzdGljID0gTkFfcmVhbF8sCiAgICAgICAgICBwLnZhbHVlID0gTkFfcmVhbF8sCiAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLAogICAgICAgICAgY29uZi5oaWdoID0gTkFfcmVhbF8sCiAgICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwKICAgICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLAogICAgICAgICAgbl9pZHMgPSBuX2lkcywKICAgICAgICAgIHN0YXR1cyA9ICJpbnN1ZmZpY2llbnRfY2VsbF9uIgogICAgICAgICkKICAgICAgKQogICAgfQogICAgCiAgICBtb2RlbCA8LSB0cnlDYXRjaCgKICAgICAgZml4ZXN0OjpmZW9scygKICAgICAgICBmb3JtdWxhX3N1Ymdyb3VwLAogICAgICAgIGRhdGEgPSBkYXRfY2VsbCwKICAgICAgICB2Y292ID0gfiBJRAogICAgICApLAogICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIGUKICAgICkKICAgIAogICAgaWYgKGluaGVyaXRzKG1vZGVsLCAiZXJyb3IiKSkgewogICAgICByZXR1cm4oCiAgICAgICAgdGliYmxlOjp0aWJibGUoCiAgICAgICAgICB0ZXJtID0gTkFfY2hhcmFjdGVyXywKICAgICAgICAgIGVzdGltYXRlID0gTkFfcmVhbF8sCiAgICAgICAgICBzdGQuZXJyb3IgPSBOQV9yZWFsXywKICAgICAgICAgIHN0YXRpc3RpYyA9IE5BX3JlYWxfLAogICAgICAgICAgcC52YWx1ZSA9IE5BX3JlYWxfLAogICAgICAgICAgY29uZi5sb3cgPSBOQV9yZWFsXywKICAgICAgICAgIGNvbmYuaGlnaCA9IE5BX3JlYWxfLAogICAgICAgICAgcGFydHlfc3VwcG9ydF9oID0gZ3JvdXBfdmFsdWUsCiAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwKICAgICAgICAgIG5faWRzID0gbl9pZHMsCiAgICAgICAgICBzdGF0dXMgPSBwYXN0ZTAoIm1vZGVsX2Vycm9yOiAiLCBjb25kaXRpb25NZXNzYWdlKG1vZGVsKSkKICAgICAgICApCiAgICAgICkKICAgIH0KICAgIAogICAgdGlkeV9maXhlc3RfdW5pZmllZChtb2RlbCkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgcGFydHlfc3VwcG9ydF9oID0gZ3JvdXBfdmFsdWUsCiAgICAgICAgcGFydHlfbiA9IG5fdmFsdWUsCiAgICAgICAgbl9pZHMgPSBuX2lkcywKICAgICAgICBzdGF0dXMgPSAiZXN0aW1hdGVkIgogICAgICApCiAgfQogIAogIHN1Ymdyb3VwX2NvZWZmaWNpZW50cyA8LSBwdXJycjo6bWFwX2RmcigKICAgIGVsaWdpYmxlX2dyb3VwcywKICAgIGZ1bmN0aW9uKGdyb3VwX3ZhbHVlKSB7CiAgICAgIHB1cnJyOjptYXBfZGZyKAogICAgICAgIDI6NSwKICAgICAgICB+IGVzdGltYXRlX29uZV9jZWxsKGdyb3VwX3ZhbHVlLCAueCkKICAgICAgKQogICAgfQogICkKICAKICB0ZXJtX2xhYmVsX3RhYmxlIDwtIG1ha2VfdGVybV9sYWJlbF90YWJsZShlbnYpCiAgCiAgc3ViZ3JvdXBfY29lZmZpY2llbnRzIDwtIHN1Ymdyb3VwX2NvZWZmaWNpZW50cyAlPiUKICAgIGRwbHlyOjpsZWZ0X2pvaW4odGVybV9sYWJlbF90YWJsZSwgYnkgPSAidGVybSIpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgYXR0cmlidXRlID0gZHBseXI6OmNvYWxlc2NlKGF0dHJpYnV0ZSwgIuOBneOBruS7liIpLAogICAgICBsYWJlbCA9IGRwbHlyOjpjb2FsZXNjZShsYWJlbCwgdGVybSksCiAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwKICAgICAgcGFydHlfbl9sYWJlbCA9IGZhY3RvcigKICAgICAgICBwYXJ0eV9uLAogICAgICAgIGxldmVscyA9IDI6NSwKICAgICAgICBsYWJlbHMgPSBwYXN0ZTAoMjo1LCBpZmVsc2Uoc3R1ZHlfaWQgPT0gInN0dWR5MyIsICLpgbjmip7ogqIiLCAi5pS/5YWaIikpCiAgICAgICkKICAgICkKICAKICByZWFkcjo6d3JpdGVfY3N2KAogICAgc3ViZ3JvdXBfY29lZmZpY2llbnRzLAogICAgZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9zdXBwb3J0X3N1Ymdyb3VwX2FtY2VfY29lZmZpY2llbnRzLmNzdiIpLAogICAgbmEgPSAiIgogICkKICAKICBmb3IgKGdyb3VwX3ZhbHVlIGluIGVsaWdpYmxlX2dyb3VwcykgewogICAgcGxvdF9kYXQgPC0gc3ViZ3JvdXBfY29lZmZpY2llbnRzICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKAogICAgICAgIHBhcnR5X3N1cHBvcnRfaCA9PSBncm91cF92YWx1ZSwKICAgICAgICBzdGF0dXMgPT0gImVzdGltYXRlZCIsCiAgICAgICAgIWlzLm5hKHRlcm0pCiAgICAgICkKICAgIAogICAgaWYgKG5yb3cocGxvdF9kYXQpID09IDApIG5leHQKICAgIAogICAgbGFiZWxfb3JkZXIgPC0gcGxvdF9kYXQgJT4lCiAgICAgIGRwbHlyOjphcnJhbmdlKGF0dHJpYnV0ZSwgZHBseXI6OmNvYWxlc2NlKG9yZGVyLCA5OTk5KSwgbGFiZWwpICU+JQogICAgICBkcGx5cjo6ZGlzdGluY3QobGFiZWwpICU+JQogICAgICBkcGx5cjo6cHVsbChsYWJlbCkKICAgIAogICAgcGxvdF9kYXQgPC0gcGxvdF9kYXQgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgbGFiZWwgPSBmYWN0b3IobGFiZWwsIGxldmVscyA9IHJldihsYWJlbF9vcmRlcikpCiAgICAgICkKICAgIAogICAgbl9ncm91cCA8LSBzdXBwb3J0X3RvdGFscyAlPiUKICAgICAgZHBseXI6OmZpbHRlcihwYXJ0eV9zdXBwb3J0X2ggPT0gZ3JvdXBfdmFsdWUpICU+JQogICAgICBkcGx5cjo6cHVsbChuX3RvdGFsX2Rpc3RpbmN0KQogICAgCiAgICBwX2dyb3VwIDwtIGdncGxvdDI6OmdncGxvdCgKICAgICAgcGxvdF9kYXQsCiAgICAgIGdncGxvdDI6OmFlcygKICAgICAgICB4ID0gZXN0aW1hdGVfcHAsCiAgICAgICAgeSA9IGxhYmVsLAogICAgICAgIHNoYXBlID0gcGFydHlfbl9sYWJlbAogICAgICApCiAgICApICsKICAgICAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC40NSkgKwogICAgICBnZ3Bsb3QyOjpnZW9tX2Vycm9yYmFyaCgKICAgICAgICBnZ3Bsb3QyOjphZXMoCiAgICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsCiAgICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwCiAgICAgICAgKSwKICAgICAgICBoZWlnaHQgPSAwLjEwLAogICAgICAgIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjU1KSwKICAgICAgICBsaW5ld2lkdGggPSAwLjU1CiAgICAgICkgKwogICAgICBnZ3Bsb3QyOjpnZW9tX3BvaW50KAogICAgICAgIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjU1KSwKICAgICAgICBzaXplID0gMi4zLAogICAgICAgIGZpbGwgPSAid2hpdGUiCiAgICAgICkgKwogICAgICBnZ3Bsb3QyOjpmYWNldF9ncmlkKAogICAgICAgIGF0dHJpYnV0ZSB+IC4sCiAgICAgICAgc2NhbGVzID0gImZyZWVfeSIsCiAgICAgICAgc3BhY2UgPSAiZnJlZV95IgogICAgICApICsKICAgICAgZ2dwbG90Mjo6bGFicygKICAgICAgICB4ID0gIumBuOaKnueiuueOh+OBuOOBruWKueaenO+8iHBlcmNlbnRhZ2UgcG9pbnRz77yJIiwKICAgICAgICB5ID0gTlVMTCwKICAgICAgICBzaGFwZSA9IHN0dWR5X3NwZWMkY29uZGl0aW9uX2xhYmVsLAogICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKAogICAgICAgICAgc3R1ZHlfbGFiZWwsCiAgICAgICAgICAi77yaIiwKICAgICAgICAgIGdyb3VwX3ZhbHVlLAogICAgICAgICAgIuaUr+aMgeiAhe+8iG4gPSAiLAogICAgICAgICAgc2NhbGVzOjpjb21tYShuX2dyb3VwKSwKICAgICAgICAgICLvvIkiCiAgICAgICAgKSwKICAgICAgICBjYXB0aW9uID0gcGFzdGUwKAogICAgICAgICAgIuWbnuetlOiAhUlE44Gn44Kv44Op44K544K/5YyW44GX44Gf5qiZ5rqW6Kqk5beu44CC5ZCE5p2h5Lu244K744OrbiA8ICIsCiAgICAgICAgICB1bmlmaWVkX2NvbmZpZyRtaW5fc3VwcG9ydF9jZWxsX24sCiAgICAgICAgICAi44Gv5o6o5a6a44GX44Gq44GE44CCIgogICAgICAgICkKICAgICAgKSArCiAgICAgIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsKICAgICAgZ2dwbG90Mjo6dGhlbWUoCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZ2dwbG90Mjo6ZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpCiAgICAgICkKICAgIAogICAgZ3JvdXBfaW5kZXggPC0gbWF0Y2goZ3JvdXBfdmFsdWUsIGVsaWdpYmxlX2dyb3VwcykKICAgIGZpbGVfc3R1YiA8LSBwYXN0ZTAoCiAgICAgIHN0dWR5X2lkLAogICAgICAiX3BhcnR5X3N1cHBvcnRfYW1jZV8iLAogICAgICBzcHJpbnRmKCIlMDJkIiwgZ3JvdXBfaW5kZXgpLAogICAgICAiXyIsCiAgICAgIHNhZmVfZmlsZW5hbWUoZ3JvdXBfdmFsdWUpCiAgICApCiAgICAKICAgIGdncGxvdDI6Omdnc2F2ZSgKICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgob3V0X2RpciwgcGFzdGUwKGZpbGVfc3R1YiwgIi5wbmciKSksCiAgICAgIHBsb3QgPSBwX2dyb3VwLAogICAgICB3aWR0aCA9IDEwLjUsCiAgICAgIGhlaWdodCA9IGlmZWxzZShzdHVkeV9pZCA9PSAic3R1ZHkzIiwgMTEuNSwgMTAuMCksCiAgICAgIGRwaSA9IDQwMCwKICAgICAgYmcgPSAid2hpdGUiCiAgICApCiAgICAKICAgIGdncGxvdDI6Omdnc2F2ZSgKICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgob3V0X2RpciwgcGFzdGUwKGZpbGVfc3R1YiwgIi5wZGYiKSksCiAgICAgIHBsb3QgPSBwX2dyb3VwLAogICAgICB3aWR0aCA9IDEwLjUsCiAgICAgIGhlaWdodCA9IGlmZWxzZShzdHVkeV9pZCA9PSAic3R1ZHkzIiwgMTEuNSwgMTAuMCksCiAgICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLAogICAgICBiZyA9ICJ3aGl0ZSIKICAgICkKICB9CiAgCiAgaW50ZXJhY3Rpb25fbW9kZWxzIDwtIGxpc3QoKQogIGludGVyYWN0aW9uX3Rlc3RfdGV4dCA8LSBjaGFyYWN0ZXIoKQogIAogIGRhdF9pbnRlcmFjdGlvbiA8LSBkYXQgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKHBhcnR5X3N1cHBvcnRfaCAlaW4lIGVsaWdpYmxlX2dyb3VwcykgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBmYWN0b3IocGFydHlfc3VwcG9ydF9oKQogICAgKQogIAogIGlmICgi5pSv5oyB5pS/5YWa44Gq44GXIiAlaW4lIGxldmVscyhkYXRfaW50ZXJhY3Rpb24kcGFydHlfc3VwcG9ydF9oKSkgewogICAgZGF0X2ludGVyYWN0aW9uIDwtIGRhdF9pbnRlcmFjdGlvbiAlPiUKICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBzdGF0czo6cmVsZXZlbCgKICAgICAgICAgIHBhcnR5X3N1cHBvcnRfaCwKICAgICAgICAgIHJlZiA9ICLmlK/mjIHmlL/lhZrjgarjgZciCiAgICAgICAgKQogICAgICApCiAgfSBlbHNlIGlmIChucm93KHN1cHBvcnRfdG90YWxzKSA+IDApIHsKICAgIGxhcmdlc3RfZ3JvdXAgPC0gc3VwcG9ydF90b3RhbHMgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIocGFydHlfc3VwcG9ydF9oICVpbiUgZWxpZ2libGVfZ3JvdXBzKSAlPiUKICAgICAgZHBseXI6OnNsaWNlX21heChuX3RvdGFsX2Rpc3RpbmN0LCBuID0gMSwgd2l0aF90aWVzID0gRkFMU0UpICU+JQogICAgICBkcGx5cjo6cHVsbChwYXJ0eV9zdXBwb3J0X2gpCiAgICAKICAgIGlmIChsZW5ndGgobGFyZ2VzdF9ncm91cCkgPT0gMSkgewogICAgICBkYXRfaW50ZXJhY3Rpb24gPC0gZGF0X2ludGVyYWN0aW9uICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBzdGF0czo6cmVsZXZlbCgKICAgICAgICAgICAgcGFydHlfc3VwcG9ydF9oLAogICAgICAgICAgICByZWYgPSBsYXJnZXN0X2dyb3VwCiAgICAgICAgICApCiAgICAgICAgKQogICAgfQogIH0KICAKICBmb3JtdWxhX2ludGVyYWN0aW9uIDwtIHN0YXRzOjphcy5mb3JtdWxhKAogICAgcGFzdGUwKAogICAgICAic2VsZWN0ZWQgfiBwYXJ0eV9zdXBwb3J0X2ggKiAoIiwKICAgICAgcGFzdGUoZW52JGF0dHJfdGVybXMsIGNvbGxhcHNlID0gIiArICIpLAogICAgICAiKSIKICAgICkKICApCiAgCiAgZm9yIChuX3ZhbHVlIGluIDI6NSkgewogICAgZGF0X24gPC0gZGF0X2ludGVyYWN0aW9uICU+JSBkcGx5cjo6ZmlsdGVyKHBhcnR5X24gPT0gbl92YWx1ZSkKICAgIAogICAgbW9kZWxfbiA8LSB0cnlDYXRjaCgKICAgICAgZml4ZXN0OjpmZW9scygKICAgICAgICBmb3JtdWxhX2ludGVyYWN0aW9uLAogICAgICAgIGRhdGEgPSBkYXRfbiwKICAgICAgICB2Y292ID0gfiBJRAogICAgICApLAogICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIGUKICAgICkKICAgIAogICAgaW50ZXJhY3Rpb25fbW9kZWxzW1thcy5jaGFyYWN0ZXIobl92YWx1ZSldXSA8LSBtb2RlbF9uCiAgICAKICAgIGludGVyYWN0aW9uX3Rlc3RfdGV4dCA8LSBjKAogICAgICBpbnRlcmFjdGlvbl90ZXN0X3RleHQsCiAgICAgIHBhc3RlMCgiXG49PT09PSAiLCBzdHVkeV9sYWJlbCwgIjogY29uZGl0aW9uICIsIG5fdmFsdWUsICIgPT09PT1cbiIpCiAgICApCiAgICAKICAgIGlmIChpbmhlcml0cyhtb2RlbF9uLCAiZXJyb3IiKSkgewogICAgICBpbnRlcmFjdGlvbl90ZXN0X3RleHQgPC0gYygKICAgICAgICBpbnRlcmFjdGlvbl90ZXN0X3RleHQsCiAgICAgICAgcGFzdGUwKCJNb2RlbCBlcnJvcjogIiwgY29uZGl0aW9uTWVzc2FnZShtb2RlbF9uKSwgIlxuIikKICAgICAgKQogICAgfSBlbHNlIHsKICAgICAgaW50ZXJhY3Rpb25fdGVzdF90ZXh0IDwtIGMoCiAgICAgICAgaW50ZXJhY3Rpb25fdGVzdF90ZXh0LAogICAgICAgIGNhcHR1cmUub3V0cHV0KHN1bW1hcnkobW9kZWxfbikpLAogICAgICAgICJcbi0tLSBKb2ludCBXYWxkIHRlc3QgZm9yIHBhcnR5LXN1cHBvcnQgaW50ZXJhY3Rpb24gdGVybXMgLS0tXG4iLAogICAgICAgIHRyeUNhdGNoKAogICAgICAgICAgY2FwdHVyZS5vdXRwdXQoCiAgICAgICAgICAgIGZpeGVzdDo6d2FsZCgKICAgICAgICAgICAgICBtb2RlbF9uLAogICAgICAgICAgICAgIGtlZXAgPSAicGFydHlfc3VwcG9ydF9oLio6fDpwYXJ0eV9zdXBwb3J0X2giCiAgICAgICAgICAgICkKICAgICAgICAgICksCiAgICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHBhc3RlMCgiV2FsZCB0ZXN0IGVycm9yOiAiLCBjb25kaXRpb25NZXNzYWdlKGUpKQogICAgICAgICkKICAgICAgKQogICAgfQogIH0KICAKICB3cml0ZUxpbmVzKAogICAgaW50ZXJhY3Rpb25fdGVzdF90ZXh0LAogICAgY29uID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9zdXBwb3J0X2ludGVyYWN0aW9uX21vZGVsc19hbmRfd2FsZF90ZXN0cy50eHQiKQogICkKICAKICBsaXN0KAogICAgc3VwcG9ydF9jb3VudHMgPSBzdXBwb3J0X2NvdW50cywKICAgIGVsaWdpYmxlX2dyb3VwcyA9IGVsaWdpYmxlX2dyb3VwcywKICAgIHN1Ymdyb3VwX2NvZWZmaWNpZW50cyA9IHN1Ymdyb3VwX2NvZWZmaWNpZW50cywKICAgIGludGVyYWN0aW9uX21vZGVscyA9IGludGVyYWN0aW9uX21vZGVscywKICAgIGRhdGEgPSBkYXQKICApCn0KCnBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzIDwtIHB1cnJyOjptYXAoCiAgc3R1ZHlfc3BlY3MsCiAgcnVuX3N1cHBvcnRfYW1jZV9oZXRlcm9nZW5laXR5CikKCnJ1bl9zdXBwb3J0X3JlbGF0aXZlX2N1ZSA8LSBmdW5jdGlvbihzdHVkeV9zcGVjLCBhbWNlX3Jlc3VsdCkgewogIGVudiA8LSBzdHVkeV9zcGVjJGVudgogIHN0dWR5X2lkIDwtIHN0dWR5X3NwZWMkc3R1ZHlfaWQKICBvdXRfZGlyIDwtIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsIHBhc3RlMChzdHVkeV9pZCwgIl9wYXJ0eV9zdXBwb3J0IikpCiAgCiAgZGF0IDwtIGFtY2VfcmVzdWx0JGRhdGEKICBlbGlnaWJsZV9ncm91cHMgPC0gYW1jZV9yZXN1bHQkZWxpZ2libGVfZ3JvdXBzCiAgCiAgb2JzZXJ2ZWRfbGlzdCA8LSBsaXN0KCkKICBpbnRlcnZhbF9saXN0IDwtIGxpc3QoKQogIHNsb3BlX2xpc3QgPC0gbGlzdCgpCiAgZmFpbHVyZV9saXN0IDwtIGxpc3QoKQogIAogIGZvciAoZ3JvdXBfaW5kZXggaW4gc2VxX2Fsb25nKGVsaWdpYmxlX2dyb3VwcykpIHsKICAgIGdyb3VwX3ZhbHVlIDwtIGVsaWdpYmxlX2dyb3Vwc1tncm91cF9pbmRleF0KICAgIGRhdF9ncm91cCA8LSBkYXQgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIocGFydHlfc3VwcG9ydF9oID09IGdyb3VwX3ZhbHVlKQogICAgCiAgICBjb25kaXRpb25fY291bnRzIDwtIGRhdF9ncm91cCAlPiUKICAgICAgZHBseXI6OmRpc3RpbmN0KElELCBwYXJ0eV9uKSAlPiUKICAgICAgZHBseXI6OmNvdW50KHBhcnR5X24sIG5hbWUgPSAibl9pZHMiKQogICAgCiAgICBpZiAoCiAgICAgICFpZGVudGljYWwoc29ydChjb25kaXRpb25fY291bnRzJHBhcnR5X24pLCAyOjUpIHx8CiAgICAgIGFueShjb25kaXRpb25fY291bnRzJG5faWRzIDwgdW5pZmllZF9jb25maWckbWluX3N1cHBvcnRfY2VsbF9uKQogICAgKSB7CiAgICAgIGZhaWx1cmVfbGlzdFtbZ3JvdXBfdmFsdWVdXSA8LSB0aWJibGU6OnRpYmJsZSgKICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwKICAgICAgICByZWFzb24gPSAiTm90IGFsbCBmb3VyIGNvbmRpdGlvbnMgbWVldCB0aGUgbWluaW11bSBjZWxsIHNpemUiCiAgICAgICkKICAgICAgbmV4dAogICAgfQogICAgCiAgICBwcmVwYXJlZCA8LSB0cnlDYXRjaCgKICAgICAgZW52JHByZXBhcmVfcmVsYXRpdmVfY3VlX2FuYWx5c2lzKAogICAgICAgIGRhdGEgPSBkYXRfZ3JvdXAsCiAgICAgICAgY3VlX21hcCA9IGVudiRyZWxhdGl2ZV9jdWVfbWFwCiAgICAgICksCiAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgZQogICAgKQogICAgCiAgICBpZiAoaW5oZXJpdHMocHJlcGFyZWQsICJlcnJvciIpKSB7CiAgICAgIGZhaWx1cmVfbGlzdFtbZ3JvdXBfdmFsdWVdXSA8LSB0aWJibGU6OnRpYmJsZSgKICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwKICAgICAgICByZWFzb24gPSBjb25kaXRpb25NZXNzYWdlKHByZXBhcmVkKQogICAgICApCiAgICAgIG5leHQKICAgIH0KICAgIAogICAgb2JzZXJ2ZWQgPC0gZW52JGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9pbmRpY2VzKHByZXBhcmVkKQogICAgb2JzZXJ2ZWRfc2xvcGVzIDwtIGVudiRlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfc2xvcGVzKAogICAgICBvYnNlcnZlZCRjdWVfaW1wb3J0YW5jZQogICAgKQogICAgCiAgICBvYnNlcnZlZF9saXN0W1tncm91cF92YWx1ZV1dIDwtIG9ic2VydmVkJGN1ZV9pbXBvcnRhbmNlICU+JQogICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgIHBhcnR5X3N1cHBvcnRfaCA9IGdyb3VwX3ZhbHVlLAogICAgICAgIC5iZWZvcmUgPSAxCiAgICAgICkKICAgIAogICAgc2xvcGVfbGlzdFtbZ3JvdXBfdmFsdWVdXSA8LSB0aWJibGU6OnRpYmJsZSgKICAgICAgcGFydHlfc3VwcG9ydF9oID0gZ3JvdXBfdmFsdWUsCiAgICAgIHN0YXRpc3RpYyA9IG5hbWVzKG9ic2VydmVkX3Nsb3BlcyksCiAgICAgIGVzdGltYXRlID0gYXMubnVtZXJpYyhvYnNlcnZlZF9zbG9wZXMpCiAgICApCiAgICAKICAgIEIgPC0gdW5pZmllZF9jb25maWckc3VwcG9ydF9ib290c3RyYXBfQgogICAgCiAgICBpZiAoQiA+IDApIHsKICAgICAgY2FjaGVfZmlsZSA8LSBmaWxlLnBhdGgoCiAgICAgICAgb3V0X2RpciwKICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAic3VwcG9ydF9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwXyIsCiAgICAgICAgICB1bmlmaWVkX2NvbmZpZyRjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiwKICAgICAgICAgICJfIiwKICAgICAgICAgIHNwcmludGYoIiUwMmQiLCBncm91cF9pbmRleCksCiAgICAgICAgICAiX0IiLAogICAgICAgICAgQiwKICAgICAgICAgICIucmRzIgogICAgICAgICkKICAgICAgKQogICAgICAKICAgICAgaWYgKAogICAgICAgIGZpbGUuZXhpc3RzKGNhY2hlX2ZpbGUpICYmCiAgICAgICAgIXVuaWZpZWRfY29uZmlnJHJlcnVuX3N1cHBvcnRfYm9vdHN0cmFwCiAgICAgICkgewogICAgICAgIGJvb3RzdHJhcF9yZXN1bHQgPC0gcmVhZFJEUyhjYWNoZV9maWxlKQogICAgICB9IGVsc2UgewogICAgICAgIGJvb3RzdHJhcF9yZXN1bHQgPC0gZW52JHJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwKAogICAgICAgICAgcHJlcGFyZWQgPSBwcmVwYXJlZCwKICAgICAgICAgIEIgPSBCLAogICAgICAgICAgc2VlZCA9IHVuaWZpZWRfY29uZmlnJHN1cHBvcnRfYm9vdHN0cmFwX3NlZWQgKwogICAgICAgICAgICAxMDAwICogbWF0Y2goc3R1ZHlfaWQsIG5hbWVzKHN0dWR5X3NwZWNzKSkgKwogICAgICAgICAgICBncm91cF9pbmRleCwKICAgICAgICAgIHByb2dyZXNzX2V2ZXJ5ID0gbWF4KDAsIGZsb29yKEIgLyA1KSkKICAgICAgICApCiAgICAgICAgc2F2ZVJEUyhib290c3RyYXBfcmVzdWx0LCBjYWNoZV9maWxlKQogICAgICB9CiAgICAgIAogICAgICBpbnRlcnZhbHMgPC0gZW52JHN1bW1hcmlzZV9jb25kaXRpb25faW50ZXJ2YWxzKAogICAgICAgIG9ic2VydmVkX2N1ZV9pbXBvcnRhbmNlID0gb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsCiAgICAgICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzID0gYm9vdHN0cmFwX3Jlc3VsdCRjb25kaXRpb25fZXN0aW1hdGVzCiAgICAgICkgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgIHBhcnR5X3N1cHBvcnRfaCA9IGdyb3VwX3ZhbHVlLAogICAgICAgICAgLmJlZm9yZSA9IDEKICAgICAgICApCiAgICAgIAogICAgICBzbG9wZV9pbmZlcmVuY2UgPC0gZW52JHN1bW1hcmlzZV9zbG9wZV9pbmZlcmVuY2UoCiAgICAgICAgb2JzZXJ2ZWRfc2xvcGVzID0gb2JzZXJ2ZWRfc2xvcGVzLAogICAgICAgIGJvb3RzdHJhcF9zbG9wZXMgPSBib290c3RyYXBfcmVzdWx0JHNsb3BlcwogICAgICApICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwKICAgICAgICAgIC5iZWZvcmUgPSAxCiAgICAgICAgKQogICAgICAKICAgICAgaW50ZXJ2YWxfbGlzdFtbZ3JvdXBfdmFsdWVdXSA8LSBpbnRlcnZhbHMKICAgICAgc2xvcGVfbGlzdFtbcGFzdGUwKGdyb3VwX3ZhbHVlLCAiX2luZmVyZW5jZSIpXV0gPC0gc2xvcGVfaW5mZXJlbmNlCiAgICB9CiAgfQogIAogIG9ic2VydmVkX2RmIDwtIGRwbHlyOjpiaW5kX3Jvd3Mob2JzZXJ2ZWRfbGlzdCkKICBpbnRlcnZhbF9kZiA8LSBkcGx5cjo6YmluZF9yb3dzKGludGVydmFsX2xpc3QpCiAgc2xvcGVfZGYgPC0gZHBseXI6OmJpbmRfcm93cyhzbG9wZV9saXN0KQogIGZhaWx1cmVzX2RmIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZmFpbHVyZV9saXN0KQogIAogIHJlYWRyOjp3cml0ZV9jc3YoCiAgICBvYnNlcnZlZF9kZiwKICAgIGZpbGUucGF0aChvdXRfZGlyLCAicGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQuY3N2IiksCiAgICBuYSA9ICIiCiAgKQogIHJlYWRyOjp3cml0ZV9jc3YoCiAgICBpbnRlcnZhbF9kZiwKICAgIGZpbGUucGF0aChvdXRfZGlyLCAicGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfaW50ZXJ2YWxzLmNzdiIpLAogICAgbmEgPSAiIgogICkKICByZWFkcjo6d3JpdGVfY3N2KAogICAgc2xvcGVfZGYsCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX3Nsb3Blcy5jc3YiKSwKICAgIG5hID0gIiIKICApCiAgcmVhZHI6OndyaXRlX2NzdigKICAgIGZhaWx1cmVzX2RmLAogICAgZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV9mYWlsdXJlcy5jc3YiKSwKICAgIG5hID0gIiIKICApCiAgCiAgaWYgKG5yb3coaW50ZXJ2YWxfZGYpID4gMCkgewogICAgcGxvdF9kZiA8LSBpbnRlcnZhbF9kZiAlPiUKICAgICAgZHBseXI6OmZpbHRlcihzdGF0aXN0aWMgPT0gInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgIGVzdGltYXRlX3BjdCA9IGVzdGltYXRlICogMTAwLAogICAgICAgIGNvbmZfbG93X3BjdCA9IGNvbmZfbG93ICogMTAwLAogICAgICAgIGNvbmZfaGlnaF9wY3QgPSBjb25mX2hpZ2ggKiAxMDAKICAgICAgKQogIH0gZWxzZSB7CiAgICBwbG90X2RmIDwtIG9ic2VydmVkX2RmICU+JQogICAgICBkcGx5cjo6dHJhbnNtdXRlKAogICAgICAgIHBhcnR5X3N1cHBvcnRfaCwKICAgICAgICBwYXJ0eV9uLAogICAgICAgIGVzdGltYXRlX3BjdCA9IHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSAqIDEwMCwKICAgICAgICBjb25mX2xvd19wY3QgPSBOQV9yZWFsXywKICAgICAgICBjb25mX2hpZ2hfcGN0ID0gTkFfcmVhbF8KICAgICAgKQogIH0KICAKICBpZiAobnJvdyhwbG90X2RmKSA+IDApIHsKICAgIHBfcmVsYXRpdmVfc3VwcG9ydCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoCiAgICAgIHBsb3RfZGYsCiAgICAgIGdncGxvdDI6OmFlcygKICAgICAgICB4ID0gcGFydHlfbiwKICAgICAgICB5ID0gZXN0aW1hdGVfcGN0LAogICAgICAgIGdyb3VwID0gMQogICAgICApCiAgICApICsKICAgICAgZ2dwbG90Mjo6Z2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNTAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNDUpICsKICAgICAgZ2dwbG90Mjo6Z2VvbV9saW5lKGxpbmV3aWR0aCA9IDAuNzApICsKICAgICAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcigKICAgICAgICBnZ3Bsb3QyOjphZXMoCiAgICAgICAgICB5bWluID0gY29uZl9sb3dfcGN0LAogICAgICAgICAgeW1heCA9IGNvbmZfaGlnaF9wY3QKICAgICAgICApLAogICAgICAgIHdpZHRoID0gMC4wOCwKICAgICAgICBsaW5ld2lkdGggPSAwLjU1LAogICAgICAgIG5hLnJtID0gVFJVRQogICAgICApICsKICAgICAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc2l6ZSA9IDIuNSkgKwogICAgICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4gcGFydHlfc3VwcG9ydF9oLCBuY29sID0gMykgKwogICAgICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgICAgYnJlYWtzID0gMjo1LAogICAgICAgIGxhYmVscyA9IHBhc3RlMCgyOjUsIGlmZWxzZShzdHVkeV9pZCA9PSAic3R1ZHkzIiwgIumBuOaKnuiCoiIsICLmlL/lhZoiKSkKICAgICAgKSArCiAgICAgIGdncGxvdDI6OnNjYWxlX3lfY29udGludW91cygKICAgICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIiUiKSwKICAgICAgICBicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDYpCiAgICAgICkgKwogICAgICBnZ3Bsb3QyOjpsYWJzKAogICAgICAgIHggPSBzdHVkeV9zcGVjJGNvbmRpdGlvbl9sYWJlbCwKICAgICAgICB5ID0gIuaUv+WFmuaJi+OBjOOBi+OCiuOBruebuOWvvuavlOmHjSIsCiAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoCiAgICAgICAgICBzdHVkeV9zcGVjJHN0dWR5X2xhYmVsLAogICAgICAgICAgIu+8muaUr+aMgeaUv+WFmuWIpeOBruaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHjSIKICAgICAgICApLAogICAgICAgIGNhcHRpb24gPSBwYXN0ZTAoCiAgICAgICAgICAi5ZCE5bGe5oCn5YaF44Gu6ZmQ55WM5bmz5Z2H44Gu5bmz5Z2H57W25a++44Oa44Ki5beu44Gr5Z+644Gl44GP44CCIiwKICAgICAgICAgIGlmZWxzZSgKICAgICAgICAgICAgdW5pZmllZF9jb25maWckc3VwcG9ydF9ib290c3RyYXBfQiA+IDAsCiAgICAgICAgICAgIHBhc3RlMCgKICAgICAgICAgICAgICAiOTUl5L+h6aC85Yy66ZaT44Gv5Zue562U6ICF44Kv44Op44K544K/44O744OW44O844OI44K544OI44Op44OD44OX77yIQiA9ICIsCiAgICAgICAgICAgICAgdW5pZmllZF9jb25maWckc3VwcG9ydF9ib290c3RyYXBfQiwKICAgICAgICAgICAgICAi77yJ44CCIgogICAgICAgICAgICApLAogICAgICAgICAgICAi5L+h6aC85Yy66ZaT44Gv5pyq6KiI566X44CCIgogICAgICAgICAgKQogICAgICAgICkKICAgICAgKSArCiAgICAgIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsKICAgICAgZ2dwbG90Mjo6dGhlbWUoCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZ2dwbG90Mjo6ZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpCiAgICAgICkKICAgIAogICAgZ2dwbG90Mjo6Z2dzYXZlKAogICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChvdXRfZGlyLCAicGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfd2VpZ2h0LnBuZyIpLAogICAgICBwbG90ID0gcF9yZWxhdGl2ZV9zdXBwb3J0LAogICAgICB3aWR0aCA9IDExLjUsCiAgICAgIGhlaWdodCA9IG1heCg3LjAsIDIuNiAqIGNlaWxpbmcoZHBseXI6Om5fZGlzdGluY3QocGxvdF9kZiRwYXJ0eV9zdXBwb3J0X2gpIC8gMykpLAogICAgICBkcGkgPSA0MDAsCiAgICAgIGJnID0gIndoaXRlIgogICAgKQogICAgCiAgICBnZ3Bsb3QyOjpnZ3NhdmUoCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV93ZWlnaHQucGRmIiksCiAgICAgIHBsb3QgPSBwX3JlbGF0aXZlX3N1cHBvcnQsCiAgICAgIHdpZHRoID0gMTEuNSwKICAgICAgaGVpZ2h0ID0gbWF4KDcuMCwgMi42ICogY2VpbGluZyhkcGx5cjo6bl9kaXN0aW5jdChwbG90X2RmJHBhcnR5X3N1cHBvcnRfaCkgLyAzKSksCiAgICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLAogICAgICBiZyA9ICJ3aGl0ZSIKICAgICkKICB9IGVsc2UgewogICAgcF9yZWxhdGl2ZV9zdXBwb3J0IDwtIE5VTEwKICB9CiAgCiAgbGlzdCgKICAgIG9ic2VydmVkID0gb2JzZXJ2ZWRfZGYsCiAgICBpbnRlcnZhbHMgPSBpbnRlcnZhbF9kZiwKICAgIHNsb3BlcyA9IHNsb3BlX2RmLAogICAgZmFpbHVyZXMgPSBmYWlsdXJlc19kZiwKICAgIHBsb3QgPSBwX3JlbGF0aXZlX3N1cHBvcnQKICApCn0KCnBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX3Jlc3VsdHMgPC0gcHVycnI6Om1hcDIoCiAgc3R1ZHlfc3BlY3MsCiAgcGFydHlfc3VwcG9ydF9hbWNlX3Jlc3VsdHMsCiAgcnVuX3N1cHBvcnRfcmVsYXRpdmVfY3VlCikKCgojIOijnOmBuknplqLpgKPjgrPjg7zjg4kKZXh0cmFjdF9jdWVfc2xvcGVfaW5mZXJlbmNlIDwtIGZ1bmN0aW9uKHN0dWR5X3NwZWMpIHsKICBlbnYgPC0gc3R1ZHlfc3BlYyRlbnYKICAKICBlbnYkcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIHN0dWR5X2lkID0gc3R1ZHlfc3BlYyRzdHVkeV9pZCwKICAgICAgc3R1ZHlfbGFiZWwgPSBzdHVkeV9zcGVjJHN0dWR5X2xhYmVsLAogICAgICAuYmVmb3JlID0gMQogICAgKQp9CgpjdWVfc2xvcGVfaW5mZXJlbmNlX2FsbCA8LSBwdXJycjo6bWFwX2RmcigKICBzdHVkeV9zcGVjcywKICBleHRyYWN0X2N1ZV9zbG9wZV9pbmZlcmVuY2UKKSAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAgc3RhdGlzdGljX2xhYmVsID0gZHBseXI6OnJlY29kZSgKICAgICAgc3RhdGlzdGljLAogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0gIuaUv+WFmuOBruaJi+OBjOOBi+OCiuOBruacquiqv+aVtOmHjeimgeW6piIsCiAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPSAi57WM5riI44Gu5omL44GM44GL44KK44Gu5pyq6Kq/5pW06YeN6KaB5bqmIiwKICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgIuaUv+WFmuOBruaJi+OBjOOBi+OCiuOBrumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6piIsCiAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQogICAgICAgICLntYzmuIjjga7miYvjgYzjgYvjgorjga7pgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiLAogICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UgPSAi5pS/5YWa44Gu5omL44GM44GL44KK44Gu55u45a++5q+U6YeNIgogICAgKSwKICAgIG1ldHJpY19zY2FsZSA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgIHN0YXRpc3RpYyAlaW4lIGMoCiAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiLAogICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIgogICAgICApIH4gImNob2ljZV9zZXRfYWRqdXN0ZWRfYmFzZWxpbmVfcmVsYXRpdmUiLAogICAgICBzdGF0aXN0aWMgPT0gInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIgfgogICAgICAgICJyZWxhdGl2ZV9zaGFyZSIsCiAgICAgIFRSVUUgfiAidW5hZGp1c3RlZF9wcm9iYWJpbGl0eV9kaWZmZXJlbmNlIgogICAgKSwKICAgIGVzdGltYXRlX3BwX3Blcl9vcHRpb24gPSBlc3RpbWF0ZSAqIDEwMCwKICAgIGNvbmZfbG93X3BwX3Blcl9vcHRpb24gPSBjb25mX2xvdyAqIDEwMCwKICAgIGNvbmZfaGlnaF9wcF9wZXJfb3B0aW9uID0gY29uZl9oaWdoICogMTAwCiAgKQoKd3JpdGVfY3N2X3VuaWZpZWQoCiAgY3VlX3Nsb3BlX2luZmVyZW5jZV9hbGwsCiAgImN1ZV9pbXBvcnRhbmNlX2xpbmVhcl9zbG9wZV9hbGxfc3R1ZGllcy5jc3YiCikKCmNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSA8LSBjdWVfc2xvcGVfaW5mZXJlbmNlX2FsbCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgc3RhdGlzdGljICVpbiUgYygKICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiLAogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIKICAgICkKICApICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICBjdWVfZmFtaWx5ID0gZHBseXI6OnJlY29kZSgKICAgICAgc3RhdGlzdGljLAogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0KICAgICAgICAi5pS/5YWa44O75pS/5YWa5ZCN5omL44GM44GL44KKIiwKICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9CiAgICAgICAgIue1jOa4iOaJi+OBjOOBi+OCiiIKICAgICksCiAgICBlc3RpbWF0ZV9iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9IGVzdGltYXRlICogMTAwLAogICAgY29uZl9sb3dfYmFzZWxpbmVfcGN0X3Blcl9vcHRpb24gPSBjb25mX2xvdyAqIDEwMCwKICAgIGNvbmZfaGlnaF9iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9IGNvbmZfaGlnaCAqIDEwMAogICkKCndyaXRlX2Nzdl91bmlmaWVkKAogIGNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSwKICAiY2hvaWNlX3NldF9hZGp1c3RlZF9pbXBvcnRhbmNlX2xpbmVhcl9zbG9wZXMuY3N2IgopCgpoeXBvdGhlc2lzX21hcCA8LSB0aWJibGU6OnRyaWJibGUoCiAgfnN0dWR5X2lkLCB+aHlwb3RoZXNpcywgfnN0YXRpc3RpYywgfmV4cGVjdGVkX2RpcmVjdGlvbiwKICAic3R1ZHkxIiwgIkgxYe+8iOWun+mokzHvvIkiLCAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsICJwb3NpdGl2ZSIsCiAgInN0dWR5MSIsICJIMWLvvIjlrp/pqJMx77yJIiwgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiLCAibmVnYXRpdmUiLAogICJzdHVkeTIiLCAiSDFh77yI5a6f6aiTMu+8iSIsICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwgInBvc2l0aXZlIiwKICAic3R1ZHkyIiwgIkgxYu+8iOWun+mokzLvvIkiLCAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIsICJuZWdhdGl2ZSIsCiAgInN0dWR5MyIsICJIMmHvvIjlrp/pqJMz77yJIiwgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLCAicG9zaXRpdmUiLAogICJzdHVkeTMiLCAiSDJi77yI5a6f6aiTM++8iSIsICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiwgIm5lZ2F0aXZlIgopCgpoeXBvdGhlc2lzX3Rlc3Rfc3VtbWFyeSA8LSBoeXBvdGhlc2lzX21hcCAlPiUKICBkcGx5cjo6bGVmdF9qb2luKAogICAgY3VlX3Nsb3BlX2luZmVyZW5jZV9hbGwgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoCiAgICAgICAgc3R1ZHlfaWQsCiAgICAgICAgc3R1ZHlfbGFiZWwsCiAgICAgICAgc3RhdGlzdGljLAogICAgICAgIGVzdGltYXRlLAogICAgICAgIGNvbmZfbG93LAogICAgICAgIGNvbmZfaGlnaCwKICAgICAgICBwX3ZhbHVlX3R3b19zaWRlZAogICAgICApLAogICAgYnkgPSBjKCJzdHVkeV9pZCIsICJzdGF0aXN0aWMiKQogICkgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIGVzdGltYXRlX2luX2V4cGVjdGVkX2RpcmVjdGlvbiA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9PSAicG9zaXRpdmUiIH4gZXN0aW1hdGUgPiAwLAogICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gIm5lZ2F0aXZlIiB+IGVzdGltYXRlIDwgMCwKICAgICAgVFJVRSB+IE5BCiAgICApLAogICAgY2lfZXhjbHVkZXNfemVyb19pbl9leHBlY3RlZF9kaXJlY3Rpb24gPSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gInBvc2l0aXZlIiB+IGNvbmZfbG93ID4gMCwKICAgICAgZXhwZWN0ZWRfZGlyZWN0aW9uID09ICJuZWdhdGl2ZSIgfiBjb25mX2hpZ2ggPCAwLAogICAgICBUUlVFIH4gTkEKICAgICksCiAgICBjb25jbHVzaW9uID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgY2lfZXhjbHVkZXNfemVyb19pbl9leHBlY3RlZF9kaXJlY3Rpb24gfgogICAgICAgICLkuojmuKzmlrnlkJHjgac5NSXkv6HpoLzljLrplpPjgYww44KS5ZCr44G+44Ga44CB57Wx6KiI55qE44Gr5pSv5oyBIiwKICAgICAgZXN0aW1hdGVfaW5fZXhwZWN0ZWRfZGlyZWN0aW9uIH4KICAgICAgICAi54K55o6o5a6a44Gv5LqI5ris5pa55ZCR44Gg44GM44CBOTUl5L+h6aC85Yy66ZaT44GMMOOCkuWQq+OCgCIsCiAgICAgIFRSVUUgfgogICAgICAgICLngrnmjqjlrprjgYzkuojmuKzmlrnlkJHjgajkuIDoh7TjgZfjgarjgYQiCiAgICApLAogICAgZXN0aW1hdGVfcHBfcGVyX29wdGlvbiA9IGVzdGltYXRlICogMTAwLAogICAgY29uZl9sb3dfcHBfcGVyX29wdGlvbiA9IGNvbmZfbG93ICogMTAwLAogICAgY29uZl9oaWdoX3BwX3Blcl9vcHRpb24gPSBjb25mX2hpZ2ggKiAxMDAsCiAgICBoeXBvdGhlc2lzID0gZmFjdG9yKAogICAgICBoeXBvdGhlc2lzLAogICAgICBsZXZlbHMgPSByZXYoaHlwb3RoZXNpc19tYXAkaHlwb3RoZXNpcykKICAgICkKICApCgp3cml0ZV9jc3ZfdW5pZmllZCgKICBoeXBvdGhlc2lzX3Rlc3Rfc3VtbWFyeSwKICAibWFpbl9oeXBvdGhlc2lzX2xpbmVhcl90cmVuZF90ZXN0cy5jc3YiCikKCnBfaHlwb3RoZXNpc19zbG9wZXMgPC0gZ2dwbG90Mjo6Z2dwbG90KAogIGh5cG90aGVzaXNfdGVzdF9zdW1tYXJ5LAogIGdncGxvdDI6OmFlcygKICAgIHggPSBlc3RpbWF0ZV9wcF9wZXJfb3B0aW9uLAogICAgeSA9IGh5cG90aGVzaXMsCiAgICBzaGFwZSA9IGV4cGVjdGVkX2RpcmVjdGlvbgogICkKKSArCiAgZ2dwbG90Mjo6Z2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSAwLAogICAgbGluZXdpZHRoID0gMC40NQogICkgKwogIGdncGxvdDI6Omdlb21fZXJyb3JiYXJoKAogICAgZ2dwbG90Mjo6YWVzKAogICAgICB4bWluID0gY29uZl9sb3dfcHBfcGVyX29wdGlvbiwKICAgICAgeG1heCA9IGNvbmZfaGlnaF9wcF9wZXJfb3B0aW9uCiAgICApLAogICAgaGVpZ2h0ID0gMC4xMiwKICAgIGxpbmV3aWR0aCA9IDAuNjAKICApICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KAogICAgc2l6ZSA9IDIuNywKICAgIGZpbGwgPSAid2hpdGUiCiAgKSArCiAgZ2dwbG90Mjo6c2NhbGVfc2hhcGVfbWFudWFsKAogICAgdmFsdWVzID0gYygKICAgICAgcG9zaXRpdmUgPSAyMSwKICAgICAgbmVnYXRpdmUgPSAyNAogICAgKSwKICAgIGxhYmVscyA9IGMoCiAgICAgIHBvc2l0aXZlID0gIuato+OBruWCvuWQkeOCkuS6iOa4rCIsCiAgICAgIG5lZ2F0aXZlID0gIuiyoOOBruWCvuWQkeOCkuS6iOa4rCIKICAgICkKICApICsKICBnZ3Bsb3QyOjpsYWJzKAogICAgeCA9ICLpgbjmip7ogqLjgYwx44Gk5aKX44GI44KL44Go44GN44Gu6YeN6KaB5bqm44Gu5aSJ5YyW77yIcHDvvIkiLAogICAgeSA9IE5VTEwsCiAgICBzaGFwZSA9IE5VTEwsCiAgICBjYXB0aW9uID0gcGFzdGUwKAogICAgICAi6YeN6KaB5bqm44Gv44CB5ZCM5LiA5bGe5oCn5YaF44Gu5YWo5rC05rqW44Oa44Ki44Gr44Gk44GE44Gm6ZmQ55WM5bmz5Z2H44Gu57W25a++5beu44KS5rGC44KB44CBIiwKICAgICAgIuOBneOBruW5s+Wdh+OBqOOBl+OBpueul+WHuuOAguaoque3muOBr+WbnuetlOiAheOCr+ODqeOCueOCv+ODu+ODluODvOODiOOCueODiOODqeODg+ODlzk1JeS/oemgvOWMuumWk+OAgiIKICAgICkKICApICsKICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKwogIGdncGxvdDI6OnRoZW1lKAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikKICApCgpzYXZlX3Bsb3RfYm90aCgKICAiZmlnX3N1cHBfaHlwb3RoZXNpc19saW5lYXJfdHJlbmRfdGVzdHMiLAogIHBfaHlwb3RoZXNpc19zbG9wZXMsCiAgd2lkdGggPSA5LjUsCiAgaGVpZ2h0ID0gNS44CikKCmNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSA8LSBjaG9pY2Vfc2V0X2FkanVzdGVkX3Nsb3BlX3N1bW1hcnkgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIHN0dWR5X2N1ZV9sYWJlbCA9IHBhc3RlMCgKICAgICAgc3R1ZHlfbGFiZWwsCiAgICAgICLvvJoiLAogICAgICBjdWVfZmFtaWx5CiAgICApLAogICAgc3R1ZHlfY3VlX2xhYmVsID0gZmFjdG9yKAogICAgICBzdHVkeV9jdWVfbGFiZWwsCiAgICAgIGxldmVscyA9IHJldigKICAgICAgICB1bmlxdWUoc3R1ZHlfY3VlX2xhYmVsKQogICAgICApCiAgICApCiAgKQoKcF9jaG9pY2Vfc2V0X2FkanVzdGVkX3Nsb3BlcyA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoCiAgY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZV9zdW1tYXJ5LAogIGdncGxvdDI6OmFlcygKICAgIHggPSBlc3RpbWF0ZV9iYXNlbGluZV9wY3RfcGVyX29wdGlvbiwKICAgIHkgPSBzdHVkeV9jdWVfbGFiZWwsCiAgICBzaGFwZSA9IGN1ZV9mYW1pbHkKICApCikgKwogIGdncGxvdDI6Omdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gMCwKICAgIGxpbmV3aWR0aCA9IDAuNDUKICApICsKICBnZ3Bsb3QyOjpnZW9tX2Vycm9yYmFyaCgKICAgIGdncGxvdDI6OmFlcygKICAgICAgeG1pbiA9IGNvbmZfbG93X2Jhc2VsaW5lX3BjdF9wZXJfb3B0aW9uLAogICAgICB4bWF4ID0gY29uZl9oaWdoX2Jhc2VsaW5lX3BjdF9wZXJfb3B0aW9uCiAgICApLAogICAgaGVpZ2h0ID0gMC4xMiwKICAgIGxpbmV3aWR0aCA9IDAuNjAKICApICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KAogICAgc2l6ZSA9IDIuNywKICAgIGZpbGwgPSAid2hpdGUiCiAgKSArCiAgZ2dwbG90Mjo6c2NhbGVfc2hhcGVfbWFudWFsKAogICAgdmFsdWVzID0gYygKICAgICAgIuaUv+WFmuODu+aUv+WFmuWQjeaJi+OBjOOBi+OCiiIgPSAyMSwKICAgICAgIue1jOa4iOaJi+OBjOOBi+OCiiIgPSAyNAogICAgKQogICkgKwogIGdncGxvdDI6OmxhYnMoCiAgICB4ID0gcGFzdGUwKAogICAgICAi6YG45oqe6IKi44GMMeOBpOWil+OBiOOCi+OBqOOBjeOBruiqv+aVtOa4iOOBv+mHjeimgeW6puOBruWkieWMliIsCiAgICAgICLvvIjlubPlnYfpgbjmip7norrnjofjgavlr77jgZnjgovlibLlkIjvvJpwcO+8iSIKICAgICksCiAgICB5ID0gTlVMTCwKICAgIHNoYXBlID0gTlVMTCwKICAgIGNhcHRpb24gPSBwYXN0ZTAoCiAgICAgICLoqr/mlbTmuIjjgb/ph43opoHluqYgPSDmnKroqr/mlbTph43opoHluqYgw7fvvIgx77yP6YG45oqe6IKi5pWw77yJ44CCIiwKICAgICAgIuS6i+WJjeeZu+mMsua4iOOBv+S7ruiqrOOBruWIpOWumuOBp+OBr+OBquOBj+OAgeiomOi/sOeahOODu+aEn+W6puWIhuaekOOBqOOBl+OBpuekuuOBmeOAgiIKICAgICkKICApICsKICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKwogIGdncGxvdDI6OnRoZW1lKAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikKICApCgpzYXZlX3Bsb3RfYm90aCgKICAiZmlnX3N1cHBfY2hvaWNlX3NldF9hZGp1c3RlZF9pbXBvcnRhbmNlX3Nsb3BlcyIsCiAgcF9jaG9pY2Vfc2V0X2FkanVzdGVkX3Nsb3BlcywKICB3aWR0aCA9IDEwLjUsCiAgaGVpZ2h0ID0gNi4yCikKCgojIOacrOaWh+OCs+ODvOODiQpydW5fc3R1ZHkzX2FsbF9wYXJ0eV9tYXRjaCA8LSBmdW5jdGlvbigpIHsKICBlbnYgPC0gc3R1ZHkzX2VudgogIG91dF9kaXIgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5M19wYXJ0eV9tYXRjaF9hbGxfcGFydGllcyIpCiAgZGlyLmNyZWF0ZShvdXRfZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkKICAKICBkYXQgPC0gZW52JGNvbmpvaW50X21hdGNoICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAogICAgICBwYXJ0eV9uID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocGFydHlfbikpLAogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gYXMuY2hhcmFjdGVyKHN1cHBvcnRfcGFydHlfdmFsaWQpCiAgICApICU+JQogICAgZHBseXI6OmZpbHRlcigKICAgICAgIWlzLm5hKHN1cHBvcnRfcGFydHlfdmFsaWQpLAogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkICE9ICIiCiAgICApCiAgCiAgc3VwcG9ydF9jZWxsX2NvdW50cyA8LSBkYXQgJT4lCiAgICBkcGx5cjo6ZGlzdGluY3QoSUQsIHN1cHBvcnRfcGFydHlfdmFsaWQsIHBhcnR5X24pICU+JQogICAgZHBseXI6OmNvdW50KAogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkLAogICAgICBwYXJ0eV9uLAogICAgICBuYW1lID0gIm5fcmVzcG9uZGVudHMiCiAgICApICU+JQogICAgdGlkeXI6OmNvbXBsZXRlKAogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkLAogICAgICBwYXJ0eV9uID0gMjo1LAogICAgICBmaWxsID0gbGlzdChuX3Jlc3BvbmRlbnRzID0gMEwpCiAgICApICU+JQogICAgZHBseXI6Omdyb3VwX2J5KHN1cHBvcnRfcGFydHlfdmFsaWQpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbl90b3RhbCA9IHN1bShuX3Jlc3BvbmRlbnRzKSwKICAgICAgbWluX2NlbGxfbiA9IG1pbihuX3Jlc3BvbmRlbnRzKSwKICAgICAgYWxsX2ZvdXJfY29uZGl0aW9ucyA9IGFsbChuX3Jlc3BvbmRlbnRzID4gMCkKICAgICkgJT4lCiAgICBkcGx5cjo6dW5ncm91cCgpCiAgCiAgZWxpZ2libGVfcGFydGllcyA8LSBzdXBwb3J0X2NlbGxfY291bnRzICU+JQogICAgZHBseXI6OmRpc3RpbmN0KAogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkLAogICAgICBuX3RvdGFsLAogICAgICBtaW5fY2VsbF9uLAogICAgICBhbGxfZm91cl9jb25kaXRpb25zCiAgICApICU+JQogICAgZHBseXI6OmZpbHRlcigKICAgICAgbl90b3RhbCA+PSB1bmlmaWVkX2NvbmZpZyRtaW5fc3VwcG9ydF90b3RhbF9uLAogICAgICBtaW5fY2VsbF9uID49IHVuaWZpZWRfY29uZmlnJG1pbl9zdXBwb3J0X2NlbGxfbiwKICAgICAgYWxsX2ZvdXJfY29uZGl0aW9ucwogICAgKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKGRwbHlyOjpkZXNjKG5fdG90YWwpKSAlPiUKICAgIGRwbHlyOjpwdWxsKHN1cHBvcnRfcGFydHlfdmFsaWQpCiAgCiAgcmVhZHI6OndyaXRlX2NzdigKICAgIHN1cHBvcnRfY2VsbF9jb3VudHMsCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X21hdGNoX2FsbF9wYXJ0eV9zYW1wbGVfY291bnRzLmNzdiIpLAogICAgbmEgPSAiIgogICkKICAKICBmb3JtdWxhX2NlbGwgPC0gc3RhdHM6OmFzLmZvcm11bGEoCiAgICBwYXN0ZSgKICAgICAgInNlbGVjdGVkIH4iLAogICAgICBwYXN0ZSgKICAgICAgICBjKAogICAgICAgICAgInBhcnR5X21hdGNoIiwKICAgICAgICAgIGVudiRlY29ub21pY19hdHRyX3Rlcm1zCiAgICAgICAgKSwKICAgICAgICBjb2xsYXBzZSA9ICIgKyAiCiAgICAgICkKICAgICkKICApCiAgCiAgZXN0aW1hdGVfY2VsbCA8LSBmdW5jdGlvbihncm91cF92YWx1ZSwgbl92YWx1ZSkgewogICAgZGF0X2NlbGwgPC0gZGF0ICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKAogICAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgPT0gZ3JvdXBfdmFsdWUsCiAgICAgICAgcGFydHlfbiA9PSBuX3ZhbHVlCiAgICAgICkKICAgIAogICAgbl9pZHMgPC0gZHBseXI6Om5fZGlzdGluY3QoZGF0X2NlbGwkSUQpCiAgICAKICAgIGlmIChuX2lkcyA8IHVuaWZpZWRfY29uZmlnJG1pbl9zdXBwb3J0X2NlbGxfbikgewogICAgICByZXR1cm4oCiAgICAgICAgdGliYmxlOjp0aWJibGUoCiAgICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gZ3JvdXBfdmFsdWUsCiAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwKICAgICAgICAgIG5faWRzID0gbl9pZHMsCiAgICAgICAgICBlc3RpbWF0ZSA9IE5BX3JlYWxfLAogICAgICAgICAgc3RkLmVycm9yID0gTkFfcmVhbF8sCiAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLAogICAgICAgICAgY29uZi5oaWdoID0gTkFfcmVhbF8sCiAgICAgICAgICBwLnZhbHVlID0gTkFfcmVhbF8sCiAgICAgICAgICBzdGF0dXMgPSAiaW5zdWZmaWNpZW50X2NlbGxfbiIKICAgICAgICApCiAgICAgICkKICAgIH0KICAgIAogICAgbW9kZWwgPC0gdHJ5Q2F0Y2goCiAgICAgIGZpeGVzdDo6ZmVvbHMoCiAgICAgICAgZm9ybXVsYV9jZWxsLAogICAgICAgIGRhdGEgPSBkYXRfY2VsbCwKICAgICAgICB2Y292ID0gfiBJRAogICAgICApLAogICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIGUKICAgICkKICAgIAogICAgaWYgKGluaGVyaXRzKG1vZGVsLCAiZXJyb3IiKSkgewogICAgICByZXR1cm4oCiAgICAgICAgdGliYmxlOjp0aWJibGUoCiAgICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gZ3JvdXBfdmFsdWUsCiAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwKICAgICAgICAgIG5faWRzID0gbl9pZHMsCiAgICAgICAgICBlc3RpbWF0ZSA9IE5BX3JlYWxfLAogICAgICAgICAgc3RkLmVycm9yID0gTkFfcmVhbF8sCiAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLAogICAgICAgICAgY29uZi5oaWdoID0gTkFfcmVhbF8sCiAgICAgICAgICBwLnZhbHVlID0gTkFfcmVhbF8sCiAgICAgICAgICBzdGF0dXMgPSBwYXN0ZTAoIm1vZGVsX2Vycm9yOiAiLCBjb25kaXRpb25NZXNzYWdlKG1vZGVsKSkKICAgICAgICApCiAgICAgICkKICAgIH0KICAgIAogICAgdGlkeV9maXhlc3RfdW5pZmllZChtb2RlbCkgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIodGVybSA9PSAicGFydHlfbWF0Y2giKSAlPiUKICAgICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gZ3JvdXBfdmFsdWUsCiAgICAgICAgcGFydHlfbiA9IG5fdmFsdWUsCiAgICAgICAgbl9pZHMgPSBuX2lkcywKICAgICAgICBlc3RpbWF0ZSwKICAgICAgICBzdGQuZXJyb3IsCiAgICAgICAgY29uZi5sb3csCiAgICAgICAgY29uZi5oaWdoLAogICAgICAgIHAudmFsdWUsCiAgICAgICAgc3RhdHVzID0gImVzdGltYXRlZCIKICAgICAgKQogIH0KICAKICBjZWxsX2NvZWZmaWNpZW50cyA8LSBwdXJycjo6bWFwX2RmcigKICAgIGVsaWdpYmxlX3BhcnRpZXMsCiAgICBmdW5jdGlvbihncm91cF92YWx1ZSkgewogICAgICBwdXJycjo6bWFwX2RmcigKICAgICAgICAyOjUsCiAgICAgICAgfiBlc3RpbWF0ZV9jZWxsKGdyb3VwX3ZhbHVlLCAueCkKICAgICAgKQogICAgfQogICkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBlc3RpbWF0ZV9wcCA9IGVzdGltYXRlICogMTAwLAogICAgICBjb25mLmxvd19wcCA9IGNvbmYubG93ICogMTAwLAogICAgICBjb25mLmhpZ2hfcHAgPSBjb25mLmhpZ2ggKiAxMDAsCiAgICAgIHBhcnR5X25fbGFiZWwgPSBmYWN0b3IoCiAgICAgICAgcGFydHlfbiwKICAgICAgICBsZXZlbHMgPSAyOjUsCiAgICAgICAgbGFiZWxzID0gcGFzdGUwKDI6NSwgIumBuOaKnuiCoiIpCiAgICAgICksCiAgICAgIG1haW5fdGV4dF9wYXJ0eSA9IHN1cHBvcnRfcGFydHlfdmFsaWQgJWluJSBjKAogICAgICAgICLoh6rnlLHmsJHkuLvlhZoiLAogICAgICAgICLkuK3pgZPmlLnpnanpgKPlkIgiLAogICAgICAgICLnq4vmhrLmsJHkuLvlhZoiLAogICAgICAgICLlj4LmlL/lhZoiCiAgICAgICkKICAgICkKICAKICByZWFkcjo6d3JpdGVfY3N2KAogICAgY2VsbF9jb2VmZmljaWVudHMsCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X21hdGNoX2FsbF9wYXJ0eV9jb2VmZmljaWVudHMuY3N2IiksCiAgICBuYSA9ICIiCiAgKQogIAogIGVzdGltYXRlX3RyZW5kIDwtIGZ1bmN0aW9uKGdyb3VwX3ZhbHVlKSB7CiAgICBkYXRfZ3JvdXAgPC0gZGF0ICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKHN1cHBvcnRfcGFydHlfdmFsaWQgPT0gZ3JvdXBfdmFsdWUpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgIHBhcnR5X25fZl9oZXRlcm9nZW5laXR5ID0gZmFjdG9yKAogICAgICAgICAgcGFydHlfbiwKICAgICAgICAgIGxldmVscyA9IDI6NQogICAgICAgICksCiAgICAgICAgcGFydHlfbl9jX2hldGVyb2dlbmVpdHkgPSBwYXJ0eV9uIC0gMgogICAgICApCiAgICAKICAgIGZvcm11bGFfdHJlbmQgPC0gc3RhdHM6OmFzLmZvcm11bGEoCiAgICAgIHBhc3RlKAogICAgICAgICJzZWxlY3RlZCB+IHBhcnR5X25fZl9oZXRlcm9nZW5laXR5ICsgcGFydHlfbWF0Y2ggKyIsCiAgICAgICAgInBhcnR5X21hdGNoOnBhcnR5X25fY19oZXRlcm9nZW5laXR5ICsiLAogICAgICAgIHBhc3RlKGVudiRlY29ub21pY19hdHRyX3Rlcm1zLCBjb2xsYXBzZSA9ICIgKyAiKQogICAgICApCiAgICApCiAgICAKICAgIG1vZGVsIDwtIHRyeUNhdGNoKAogICAgICBmaXhlc3Q6OmZlb2xzKAogICAgICAgIGZvcm11bGFfdHJlbmQsCiAgICAgICAgZGF0YSA9IGRhdF9ncm91cCwKICAgICAgICB2Y292ID0gfiBJRAogICAgICApLAogICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIGUKICAgICkKICAgIAogICAgaWYgKGluaGVyaXRzKG1vZGVsLCAiZXJyb3IiKSkgewogICAgICByZXR1cm4oCiAgICAgICAgdGliYmxlOjp0aWJibGUoCiAgICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gZ3JvdXBfdmFsdWUsCiAgICAgICAgICB0ZXJtID0gInBhcnR5X21hdGNoOnBhcnR5X25fY19oZXRlcm9nZW5laXR5IiwKICAgICAgICAgIGVzdGltYXRlID0gTkFfcmVhbF8sCiAgICAgICAgICBzdGQuZXJyb3IgPSBOQV9yZWFsXywKICAgICAgICAgIGNvbmYubG93ID0gTkFfcmVhbF8sCiAgICAgICAgICBjb25mLmhpZ2ggPSBOQV9yZWFsXywKICAgICAgICAgIHAudmFsdWUgPSBOQV9yZWFsXywKICAgICAgICAgIHN0YXR1cyA9IHBhc3RlMCgibW9kZWxfZXJyb3I6ICIsIGNvbmRpdGlvbk1lc3NhZ2UobW9kZWwpKQogICAgICAgICkKICAgICAgKQogICAgfQogICAgCiAgICB0aWR5X2ZpeGVzdF91bmlmaWVkKG1vZGVsKSAlPiUKICAgICAgZHBseXI6OmZpbHRlcigKICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KAogICAgICAgICAgdGVybSwKICAgICAgICAgICJwYXJ0eV9tYXRjaDpwYXJ0eV9uX2NfaGV0ZXJvZ2VuZWl0eXxwYXJ0eV9uX2NfaGV0ZXJvZ2VuZWl0eTpwYXJ0eV9tYXRjaCIKICAgICAgICApCiAgICAgICkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9IGdyb3VwX3ZhbHVlLAogICAgICAgIHN0YXR1cyA9ICJlc3RpbWF0ZWQiLAogICAgICAgIC5iZWZvcmUgPSAxCiAgICAgICkKICB9CiAgCiAgdHJlbmRfY29lZmZpY2llbnRzIDwtIHB1cnJyOjptYXBfZGZyKAogICAgZWxpZ2libGVfcGFydGllcywKICAgIGVzdGltYXRlX3RyZW5kCiAgKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIGVzdGltYXRlX3BwX3Blcl9vcHRpb24gPSBlc3RpbWF0ZSAqIDEwMCwKICAgICAgY29uZi5sb3dfcHBfcGVyX29wdGlvbiA9IGNvbmYubG93ICogMTAwLAogICAgICBjb25mLmhpZ2hfcHBfcGVyX29wdGlvbiA9IGNvbmYuaGlnaCAqIDEwMAogICAgKQogIAogIHJlYWRyOjp3cml0ZV9jc3YoCiAgICB0cmVuZF9jb2VmZmljaWVudHMsCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X21hdGNoX2FsbF9wYXJ0eV9saW5lYXJfdHJlbmRzLmNzdiIpLAogICAgbmEgPSAiIgogICkKICAKICBwbG90X2RmIDwtIGNlbGxfY29lZmZpY2llbnRzICU+JQogICAgZHBseXI6OmZpbHRlcigKICAgICAgc3RhdHVzID09ICJlc3RpbWF0ZWQiLAogICAgICBpcy5maW5pdGUoZXN0aW1hdGVfcHApCiAgICApICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9IGZhY3RvcigKICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkLAogICAgICAgIGxldmVscyA9IGVsaWdpYmxlX3BhcnRpZXMKICAgICAgKQogICAgKQogIAogIGlmIChucm93KHBsb3RfZGYpID4gMCkgewogICAgcF9hbGxfcGFydHlfbWF0Y2ggPC0gZ2dwbG90Mjo6Z2dwbG90KAogICAgICBwbG90X2RmLAogICAgICBnZ3Bsb3QyOjphZXMoCiAgICAgICAgeCA9IHBhcnR5X24sCiAgICAgICAgeSA9IGVzdGltYXRlX3BwLAogICAgICAgIGdyb3VwID0gMQogICAgICApCiAgICApICsKICAgICAgZ2dwbG90Mjo6Z2VvbV9obGluZSgKICAgICAgICB5aW50ZXJjZXB0ID0gMCwKICAgICAgICBsaW5ld2lkdGggPSAwLjQwCiAgICAgICkgKwogICAgICBnZ3Bsb3QyOjpnZW9tX2xpbmUoCiAgICAgICAgbGluZXdpZHRoID0gMC42NQogICAgICApICsKICAgICAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcigKICAgICAgICBnZ3Bsb3QyOjphZXMoCiAgICAgICAgICB5bWluID0gY29uZi5sb3dfcHAsCiAgICAgICAgICB5bWF4ID0gY29uZi5oaWdoX3BwCiAgICAgICAgKSwKICAgICAgICB3aWR0aCA9IDAuMDgsCiAgICAgICAgbGluZXdpZHRoID0gMC41NQogICAgICApICsKICAgICAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgKICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgIGZpbGwgPSAid2hpdGUiLAogICAgICAgIHNpemUgPSAyLjQKICAgICAgKSArCiAgICAgIGdncGxvdDI6OmZhY2V0X3dyYXAoCiAgICAgICAgfiBzdXBwb3J0X3BhcnR5X3ZhbGlkLAogICAgICAgIG5jb2wgPSAzCiAgICAgICkgKwogICAgICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoCiAgICAgICAgYnJlYWtzID0gMjo1LAogICAgICAgIGxhYmVscyA9IHBhc3RlMCgyOjUsICLpgbjmip7ogqIiKQogICAgICApICsKICAgICAgZ2dwbG90Mjo6bGFicygKICAgICAgICB4ID0gIuaPkOekuuOBleOCjOOCi+mBuOaKnuiCouaVsCIsCiAgICAgICAgeSA9ICLmlK/mjIHmlL/lhZrjgajmj5DnpLrmlL/lhZrlkI3jga7kuIDoh7TlirnmnpzvvIhwcO+8iSIsCiAgICAgICAgY2FwdGlvbiA9IHBhc3RlMCgKICAgICAgICAgICLlkITmlK/mjIHmlL/lhZrjgrXjg5bjgrDjg6vjg7zjg5flhoXjgacgc2VsZWN0ZWQgfiBwYXJ0eV9tYXRjaCArIOe1jOa4iOWxnuaAp+OCkuaOqOWumuOAgiIsCiAgICAgICAgICAi5qiZ5rqW6Kqk5beu44Gv5Zue562U6ICFSUTjgafjgq/jg6njgrnjgr/ljJbjgIIiCiAgICAgICAgKQogICAgICApICsKICAgICAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKwogICAgICBnZ3Bsb3QyOjp0aGVtZSgKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBnZ3Bsb3QyOjplbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLAogICAgICAgIHN0cmlwLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikKICAgICAgKQogICAgCiAgICBnZ3Bsb3QyOjpnZ3NhdmUoCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9tYXRjaF9hbGxfcGFydGllcy5wbmciKSwKICAgICAgcGxvdCA9IHBfYWxsX3BhcnR5X21hdGNoLAogICAgICB3aWR0aCA9IDExLjUsCiAgICAgIGhlaWdodCA9IG1heCgKICAgICAgICA3LjAsCiAgICAgICAgMi43ICogY2VpbGluZyhsZW5ndGgoZWxpZ2libGVfcGFydGllcykgLyAzKQogICAgICApLAogICAgICBkcGkgPSA0MDAsCiAgICAgIGJnID0gIndoaXRlIgogICAgKQogICAgCiAgICBnZ3Bsb3QyOjpnZ3NhdmUoCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9tYXRjaF9hbGxfcGFydGllcy5wZGYiKSwKICAgICAgcGxvdCA9IHBfYWxsX3BhcnR5X21hdGNoLAogICAgICB3aWR0aCA9IDExLjUsCiAgICAgIGhlaWdodCA9IG1heCgKICAgICAgICA3LjAsCiAgICAgICAgMi43ICogY2VpbGluZyhsZW5ndGgoZWxpZ2libGVfcGFydGllcykgLyAzKQogICAgICApLAogICAgICBkZXZpY2UgPSBnckRldmljZXM6OmNhaXJvX3BkZiwKICAgICAgYmcgPSAid2hpdGUiCiAgICApCiAgfSBlbHNlIHsKICAgIHBfYWxsX3BhcnR5X21hdGNoIDwtIE5VTEwKICB9CiAgCiAgbGlzdCgKICAgIHNhbXBsZV9jb3VudHMgPSBzdXBwb3J0X2NlbGxfY291bnRzLAogICAgZWxpZ2libGVfcGFydGllcyA9IGVsaWdpYmxlX3BhcnRpZXMsCiAgICBjb2VmZmljaWVudHMgPSBjZWxsX2NvZWZmaWNpZW50cywKICAgIHRyZW5kcyA9IHRyZW5kX2NvZWZmaWNpZW50cywKICAgIHBsb3QgPSBwX2FsbF9wYXJ0eV9tYXRjaAogICkKfQoKc3R1ZHkzX2FsbF9wYXJ0eV9tYXRjaF9yZXN1bHRzIDwtIHJ1bl9zdHVkeTNfYWxsX3BhcnR5X21hdGNoKCkKCgpleHRyYWN0X2Nyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7CiAgZW52IDwtIHN0dWR5X3NwZWMkZW52CiAgCiAgZW52JHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQogICAgZHBseXI6OmZpbHRlcigKICAgICAgc3RhdGlzdGljID09ICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiCiAgICApICU+JQogICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgc3R1ZHlfaWQgPSBzdHVkeV9zcGVjJHN0dWR5X2lkLAogICAgICBzdHVkeV9sYWJlbCA9IHN0dWR5X3NwZWMkc3R1ZHlfbGFiZWwsCiAgICAgIHBhcnR5X24sCiAgICAgIGVzdGltYXRlLAogICAgICBjb25mX2xvdywKICAgICAgY29uZl9oaWdoCiAgICApCn0KCmNyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCA8LSBwdXJycjo6bWFwX2RmcigKICBzdHVkeV9zcGVjcywKICBleHRyYWN0X2Nyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodAopICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICBlc3RpbWF0ZV9wY3QgPSBlc3RpbWF0ZSAqIDEwMCwKICAgIGNvbmZfbG93X3BjdCA9IGNvbmZfbG93ICogMTAwLAogICAgY29uZl9oaWdoX3BjdCA9IGNvbmZfaGlnaCAqIDEwMCwKICAgIHN0dWR5X2xhYmVsID0gZmFjdG9yKAogICAgICBzdHVkeV9sYWJlbCwKICAgICAgbGV2ZWxzID0gdmFwcGx5KAogICAgICAgIHN0dWR5X3NwZWNzLAogICAgICAgIGBbW2AsCiAgICAgICAgY2hhcmFjdGVyKDEpLAogICAgICAgICJzdHVkeV9sYWJlbCIKICAgICAgKQogICAgKQogICkKCndyaXRlX2Nzdl91bmlmaWVkKAogIGNyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCwKICAiY3Jvc3Nfc3R1ZHlfcmVsYXRpdmVfcGFydHlfd2VpZ2h0LmNzdiIKKQoKcF9jcm9zc19zdHVkeV9yZWxhdGl2ZSA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoCiAgY3Jvc3Nfc3R1ZHlfcmVsYXRpdmVfd2VpZ2h0LAogIGdncGxvdDI6OmFlcygKICAgIHggPSBwYXJ0eV9uLAogICAgeSA9IGVzdGltYXRlX3BjdCwKICAgIGxpbmV0eXBlID0gc3R1ZHlfbGFiZWwsCiAgICBzaGFwZSA9IHN0dWR5X2xhYmVsLAogICAgZ3JvdXAgPSBzdHVkeV9sYWJlbAogICkKKSArCiAgZ2dwbG90Mjo6Z2VvbV9obGluZSgKICAgIHlpbnRlcmNlcHQgPSA1MCwKICAgIGxpbmV0eXBlID0gImRvdHRlZCIsCiAgICBsaW5ld2lkdGggPSAwLjQ1CiAgKSArCiAgZ2dwbG90Mjo6Z2VvbV9saW5lKAogICAgbGluZXdpZHRoID0gMC44MAogICkgKwogIGdncGxvdDI6Omdlb21fZXJyb3JiYXIoCiAgICBnZ3Bsb3QyOjphZXMoCiAgICAgIHltaW4gPSBjb25mX2xvd19wY3QsCiAgICAgIHltYXggPSBjb25mX2hpZ2hfcGN0CiAgICApLAogICAgd2lkdGggPSAwLjA3LAogICAgbGluZXdpZHRoID0gMC42MCwKICAgIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjA4KQogICkgKwogIGdncGxvdDI6Omdlb21fcG9pbnQoCiAgICBzaXplID0gMi43LAogICAgZmlsbCA9ICJ3aGl0ZSIsCiAgICBwb3NpdGlvbiA9IGdncGxvdDI6OnBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4wOCkKICApICsKICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoCiAgICBicmVha3MgPSAyOjUsCiAgICBsYWJlbHMgPSBwYXN0ZTAoMjo1LCAi6YG45oqe6IKiIikKICApICsKICBnZ3Bsb3QyOjpzY2FsZV95X2NvbnRpbnVvdXMoCiAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIiUiKSwKICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcyhuID0gNikKICApICsKICBnZ3Bsb3QyOjpsYWJzKAogICAgeCA9ICLmj5DnpLrjgZXjgozjgovpgbjmip7ogqLmlbAiLAogICAgeSA9ICLmlL/lhZrjga7miYvjgYzjgYvjgorjga7nm7jlr77mr5Tph40iLAogICAgbGluZXR5cGUgPSBOVUxMLAogICAgc2hhcGUgPSBOVUxMLAogICAgY2FwdGlvbiA9IHBhc3RlMCgKICAgICAgIumZkOeVjOW5s+Wdh+OBruW5s+Wdh+e1tuWvvuODmuOCouW3ruOBq+WfuuOBpeOBj+OAgiIsCiAgICAgICLjgqjjg6njg7zjg5Djg7zjga/lm57nrZTogIXjgq/jg6njgrnjgr/jg7vjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5c5NSXkv6HpoLzljLrplpPjgIIiCiAgICApCiAgKSArCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEuNSkgKwogIGdncGxvdDI6OnRoZW1lKAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikKICApCgpzYXZlX3Bsb3RfYm90aCgKICAiZmlnX3N1cHBfY3Jvc3Nfc3R1ZHlfcmVsYXRpdmVfcGFydHlfd2VpZ2h0IiwKICBwX2Nyb3NzX3N0dWR5X3JlbGF0aXZlLAogIHdpZHRoID0gOS41LAogIGhlaWdodCA9IDYuMAopCgoKIyDlh7rlipvmlbTnkIbjgrPjg7zjg4kKbWFpbl90ZXh0X2ZpZ3VyZV9tYW5pZmVzdCA8LSB0aWJibGU6OnRyaWJibGUoCiAgfmZpZ3VyZV9udW1iZXIsIH5zdHVkeSwgfmFuYWx5c2lzLCB+ZmlsZV9wbmcsIH5maWxlX3BkZiwKICAiRmlndXJlIDQiLCAiU3R1ZHkgMSIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwKICBmaWxlLnBhdGgodW5pZmllZF9jb25maWckc3R1ZHkxJG91dHB1dF9kaXIsICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciKSwKICBOQV9jaGFyYWN0ZXJfLAogICJGaWd1cmUgNSIsICJTdHVkeSAxIiwgIuaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MSRvdXRwdXRfZGlyLCAiZmlnX3N0dWR5MV9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBuZyIpLAogIGZpbGUucGF0aCh1bmlmaWVkX2NvbmZpZyRzdHVkeTEkb3V0cHV0X2RpciwgImZpZ19zdHVkeTFfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wZGYiKSwKICAiRmlndXJlIDYiLCAiU3R1ZHkgMiIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwKICBmaWxlLnBhdGgodW5pZmllZF9jb25maWckc3R1ZHkyJG91dHB1dF9kaXIsICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciKSwKICBOQV9jaGFyYWN0ZXJfLAogICJGaWd1cmUgNyIsICJTdHVkeSAyIiwgIuaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MiRvdXRwdXRfZGlyLCAiZmlnX3N0dWR5Ml9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBuZyIpLAogIGZpbGUucGF0aCh1bmlmaWVkX2NvbmZpZyRzdHVkeTIkb3V0cHV0X2RpciwgImZpZ19zdHVkeTJfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wZGYiKSwKICAiRmlndXJlIDgiLCAiU3R1ZHkgMyIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwKICBmaWxlLnBhdGgodW5pZmllZF9jb25maWckc3R1ZHkzJG91dHB1dF9kaXIsICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciKSwKICBOQV9jaGFyYWN0ZXJfLAogICJGaWd1cmUgOSIsICJTdHVkeSAzIiwgIuaUv+WFmuWQjeODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MyRvdXRwdXRfZGlyLCAiZmlnX3N0dWR5M19yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBuZyIpLAogIGZpbGUucGF0aCh1bmlmaWVkX2NvbmZpZyRzdHVkeTMkb3V0cHV0X2RpciwgImZpZ19zdHVkeTNfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wZGYiKSwKICAiRmlndXJlIDEwIiwgIlN0dWR5IDMiLCAi5pSv5oyB5pS/5YWa44Go5o+Q56S65pS/5YWa5ZCN44Gu5LiA6Ie05Yq55p6cIiwKICBmaWxlLnBhdGgodW5pZmllZF9jb25maWckc3R1ZHkzJG91dHB1dF9kaXIsICJwYXJ0eV9tYXRjaF9lZmZlY3RfY29tYmluZWQucG5nIiksCiAgTkFfY2hhcmFjdGVyXwopCgp3cml0ZV9jc3ZfdW5pZmllZCgKICBtYWluX3RleHRfZmlndXJlX21hbmlmZXN0LAogICJtYWluX3RleHRfZmlndXJlX3JlcHJvZHVjdGlvbl9tYW5pZmVzdC5jc3YiCikKCnN1cHBsZW1lbnRfZmlndXJlX21hbmlmZXN0IDwtIHRpYmJsZTo6dHJpYmJsZSgKICB+c2VjdGlvbiwgfnN0dWR5LCB+YW5hbHlzaXMsIH5maWxlX3BuZywKICAiQiIsICJTdHVkeSAxIiwgIuWbnuetlOiAheWJsuS7mOODkOODqeODs+OCue+8mkxvdmUgcGxvdCIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5MV9hc3NpZ25tZW50X2JhbGFuY2VfbG92ZV9wbG90LnBuZyIpLAogICJCIiwgIlN0dWR5IDIiLCAi5Zue562U6ICF5Ymy5LuY44OQ44Op44Oz44K577yaTG92ZSBwbG90IiwKICBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAic3R1ZHkyX2Fzc2lnbm1lbnRfYmFsYW5jZV9sb3ZlX3Bsb3QucG5nIiksCiAgIkIiLCAiU3R1ZHkgMyIsICLlm57nrZTogIXlibLku5jjg5Djg6njg7PjgrnvvJpMb3ZlIHBsb3QiLAogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJzdHVkeTNfYXNzaWdubWVudF9iYWxhbmNlX2xvdmVfcGxvdC5wbmciKSwKICAiQiIsICJTdHVkeSAxIiwgIuWbnuetlOiAheWJsuS7mOODkOODqeODs+OCue+8mjQ15bqm57ea6Ki65patIiwKICBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAic3R1ZHkxX2Fzc2lnbm1lbnRfYmFsYW5jZV9kaWFnb25hbF9wbG90LnBuZyIpLAogICJCIiwgIlN0dWR5IDIiLCAi5Zue562U6ICF5Ymy5LuY44OQ44Op44Oz44K577yaNDXluqbnt5roqLrmlq0iLAogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJzdHVkeTJfYXNzaWdubWVudF9iYWxhbmNlX2RpYWdvbmFsX3Bsb3QucG5nIiksCiAgIkIiLCAiU3R1ZHkgMyIsICLlm57nrZTogIXlibLku5jjg5Djg6njg7PjgrnvvJo0NeW6pue3muiouuaWrSIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5M19hc3NpZ25tZW50X2JhbGFuY2VfZGlhZ29uYWxfcGxvdC5wbmciKSwKICAiQiIsICJTdHVkeSAxIiwgIuWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+Wvvuacn+W+heavlOeOhyIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5MV9wcm9maWxlX3JhbmRvbWl6YXRpb25fZGlhZ29uYWxfcGxvdC5wbmciKSwKICAiQiIsICJTdHVkeSAyIiwgIuWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+Wvvuacn+W+heavlOeOhyIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5Ml9wcm9maWxlX3JhbmRvbWl6YXRpb25fZGlhZ29uYWxfcGxvdC5wbmciKSwKICAiQiIsICJTdHVkeSAzIiwgIuWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+Wvvuacn+W+heavlOeOhyIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5M19wcm9maWxlX3JhbmRvbWl6YXRpb25fZGlhZ29uYWxfcGxvdC5wbmciKSwKICAiQyIsICJTdHVkeSAx4oCTMyIsICJIMWEvSDFiL0gyYS9IMmLjga7nt5rlvaLlgr7lkJHmpJzlrpoiLAogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJmaWdfc3VwcF9oeXBvdGhlc2lzX2xpbmVhcl90cmVuZF90ZXN0cy5wbmciKSwKICAiQyIsICJTdHVkeSAx4oCTMyIsICLpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbjga7nt5rlvaLlgr7lkJEiLAogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJmaWdfc3VwcF9jaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2Vfc2xvcGVzLnBuZyIpLAogICJDIiwgIlN0dWR5IDEiLCAi5pyq6Kq/5pW044O76YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqm44O755u45a++5q+U6YeNIiwKICBmaWxlLnBhdGgoCiAgICB1bmlmaWVkX2NvbmZpZyRzdHVkeTEkb3V0cHV0X2RpciwKICAgICJmaWdfc3R1ZHkxX3JlbGF0aXZlX2N1ZV93ZWlnaHRfY2hvaWNlX3NldF9hZGp1c3RlZF9qcF9idy5wbmciCiAgKSwKICAiQyIsICJTdHVkeSAyIiwgIuacquiqv+aVtOODu+mBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puODu+ebuOWvvuavlOmHjSIsCiAgZmlsZS5wYXRoKAogICAgdW5pZmllZF9jb25maWckc3R1ZHkyJG91dHB1dF9kaXIsCiAgICAiZmlnX3N0dWR5Ml9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYncucG5nIgogICksCiAgIkMiLCAiU3R1ZHkgMyIsICLmnKroqr/mlbTjg7vpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbjg7vnm7jlr77mr5Tph40iLAogIGZpbGUucGF0aCgKICAgIHVuaWZpZWRfY29uZmlnJHN0dWR5MyRvdXRwdXRfZGlyLAogICAgImZpZ19zdHVkeTNfcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkX2pwX2J3LnBuZyIKICApLAogICJGIiwgIlN0dWR5IDHigJMzIiwgIuaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHjeOBruaoquaWreavlOi8gyIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgImZpZ19zdXBwX2Nyb3NzX3N0dWR5X3JlbGF0aXZlX3BhcnR5X3dlaWdodC5wbmciKSwKICAiRyIsICJTdHVkeSAzIiwgIuWFqOOBpuOBruWNgeWIhuOBquaomeacrOOCkuOCguOBpOaUr+aMgeaUv+WFmuOBruS4gOiHtOWKueaenCIsCiAgZmlsZS5wYXRoKAogICAgdW5pZmllZF9vdXRwdXRfZGlyLAogICAgInN0dWR5M19wYXJ0eV9tYXRjaF9hbGxfcGFydGllcyIsCiAgICAicGFydHlfbWF0Y2hfYWxsX3BhcnRpZXMucG5nIgogICksCiAgIkciLCAiU3R1ZHkgMeKAkzMiLCAi5pSv5oyB5pS/5YWa5YilQU1DReODu+ebuOWvvuavlOmHjSIsCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgIjxzdHVkeT5fcGFydHlfc3VwcG9ydCIpCikKCndyaXRlX2Nzdl91bmlmaWVkKAogIHN1cHBsZW1lbnRfZmlndXJlX21hbmlmZXN0LAogICJzdXBwbGVtZW50X2ZpZ3VyZV9tYW5pZmVzdC5jc3YiCikKCnN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdCA8LSB0aWJibGU6OnRyaWJibGUoCiAgfnNlY3Rpb24sIH50aXRsZSwgfnBsYWNlbWVudF9sb2dpYywgfmNvcmVfb3V0cHV0cywKICAiQSIsICLoqr/mn7voqK3oqIjjg7vos6rllY/mlofjg7vmqJnmnKzmp4vnr4kiLAogICLoqq3ogIXjgYwz5a6f6aiT44Gu55u46YGV44Go5YiG5p6Q5a++6LGh6ICF44Gu5b2i5oiQ44KS5YWI44Gr56K66KqN44Gn44GN44KL44KI44GG44Gr44GZ44KL44CCIiwKICAi6Kq/5p+744OV44Ot44O844CB5bGe5oCn44O75rC05rqW44CB6LOq5ZWP5paH44CBc2FtcGxlX2Zsb3fjgIHmnaHku7bliKVu44CB5qyg5pCN6ZuG6KiIIiwKICAiQiIsICLnhKHkvZzngrrlibLku5jjg7vlsZ7mgKfmj5DnpLrjg7vjg4fjg7zjgr/lk4Hos6rjga7oqLrmlq0iLAogICLmjqjlrprntZDmnpzjgojjgorliY3jgavjgIHlh6bnva7mnaHku7bjgajjgrPjg7Pjgrjjg6fjgqTjg7Pjg4jlsZ7mgKfjga7nhKHkvZzngrrljJbjgYzmqZ/og73jgZfjgZ/jgZPjgajjgpLnpLrjgZnjgIIiLAogICLmnaHku7bliKXlhbHlpInph4/ooajjgIHlhag25p2h5Lu244Oa44Ki44GuU01E44CBTG92ZSBwbG9044CBNDXluqbnt5rlm7PjgIHlsZ7mgKfmsLTmupbjga7oprPmuKzlr77mnJ/lvoXmr5TnjociLAogICJDIiwgIuaOqOWumumHj+ODu+ebuOWvvuavlOmHjeODu+S7ruiqrOaknOWumiIsCiAgIuacrOaWh+OBruW8jygxKSgyKeOBqEgxYS9IMWIvSDJhL0gyYuOBruWIpOWumuaWueazleOCkuS4gOOBi+aJgOOBq+mbhue0hOOBmeOCi+OAgiIsCiAgcGFzdGUwKAogICAgIkFNQ0XjgIHpmZDnlYzlubPlnYfjgIHlubPlnYfntbblr77jg5rjgqLlt67jgIHpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbjgIEiLAogICAgIuebuOWvvuavlOmHjeOAgeODluODvOODiOOCueODiOODqeODg+ODl+OAgee3muW9ouWCvuWQkee1seWQiOihqCIKICApLAogICJEIiwgIuWun+mokzHvvIgyMDIz5bm077yJ44Gu5a6M5YWo44Gq57WQ5p6cIiwKICAi5pys5paH5ZuzNOODuzXjga7lho3nj77lvozjgavjgIHoo5zliqnliIbmnpDjgpLlkIzjgZjlrp/pqJPlhoXjgafjgb7jgajjgoHjgovjgIIiLAogICLoqr/mlbTmuIjjgb/jg7vmnKroqr/mlbRBTUNF44CB5Lqk5LqS5L2c55So44CB44OS44O844OI44Oe44OD44OX44CB5p2h5Lu25LuY44GN44Ot44K444OD44OI44CB55u45a++5q+U6YeN5YK+5ZCRIiwKICAiRSIsICLlrp/pqJMy77yIMjAyNuW5tO+8ieOBqDIwMjPigJMyMDI25bm05q+U6LyDIiwKICAi5a6f6aiTMeOBruWGjeePvuaAp+OBqOaZgueCuemWk+WkieWMluOCkumAo+e2muOBl+OBpuiqreOCgeOCi+OCiOOBhuOBq+OBmeOCi+OAgiIsCiAgIuiqv+aVtOa4iOOBv+ODu+acquiqv+aVtEFNQ0XjgIHkuqTkupLkvZznlKjjgIHjg5Ljg7zjg4jjg57jg4Pjg5fjgIHmnaHku7bku5jjgY3jg63jgrjjg4Pjg4jjgIHnm7jlr77mr5Tph43lgr7lkJHjgIHmmYLngrnmr5TovIMiLAogICJGIiwgIuWun+mokzPvvIgyMDI25bm077yJ44Gu5a6M5YWo44Gq57WQ5p6cIiwKICAi5YW35L2T55qE5pS/5YWa5ZCN44Gu5YiG5p6Q44Go44CB5pys5paH5ZuzOOODuznjg7sxMOOBrui/veWKoOaOqOWumuOCkuOBvuOBqOOCgeOCi+OAgiIsCiAgIkFNQ0XjgIHjgqvjg4bjgrTjg6rjgqvjg6vjg7vnt5rlvaLjg4jjg6zjg7Pjg4njgIHmnaHku7bku5jjgY3jg63jgrjjg4Pjg4jjgIHnm7jlr77mr5Tph43jgIHkuIDoh7TlirnmnpwiLAogICJHIiwgIuaUv+WFmuaUr+aMgeOBq+OCiOOCi+eVsOizquaApyIsCiAgIuacrOaWh+OBruWFmua0vuaAp+ODoeOCq+ODi+OCuuODoOOBq+ebtOe1kOOBmeOCi+OBn+OCgeOAgemgkeWBpeaAp+WIhuaekOOBi+OCieeLrOeri+OBleOBm+OCi+OAgiIsCiAgIuaUr+aMgeaUv+WFmuWIpUFNQ0XjgIHmlK/mjIHmlL/lhZrDl+WxnuaAp1dhbGTmpJzlrprjgIHmlK/mjIHmlL/lhZrliKXnm7jlr77mr5Tph43jgIHlhajmlL/lhZrkuIDoh7TlirnmnpwiLAogICJIIiwgIumZpOWkluWfuua6luODu+aOqOWumuazleODu+aomeacrOWumue+qeOBq+mWouOBmeOCi+aEn+W6puWIhuaekCIsCiAgIuS4u+imgee1kOirluOBjOWIhuaekOS4iuOBrumBuOaKnuOBq+S+neWtmOOBl+OBquOBhOOBi+OCkuacgOW+jOOBq+eiuuiqjeOBmeOCi+OAgiIsCiAgIuazqOaEj+ODu+aTjeS9nOeiuuiqjeOAgeWujOWFqDXoqrLpoYzjgIHlhbHlpInph4/jgarjgZfjgIHmnaHku7bku5jjgY3jg63jgrjjg4Pjg4jjgIHku6Pmm7/mqJnmnKwiLAogICJJIiwgIuWGjeePvuaAp+aDheWgsSIsCiAgIuWFqOOBpuOBruWIhuaekOW+jOOBq+OAgeWGjeePvuOBq+W/heimgeOBquaKgOihk+aDheWgseOCkuOBvuOBqOOCgeOCi+OAgiIsCiAgIuODleOCoeOCpOODq+S4gOimp+OAgeS5seaVsOOCt+ODvOODieOAgeODluODvOODiOOCueODiOODqeODg+ODl+WbnuaVsOOAgeODkeODg+OCseODvOOCuOOAgXNlc3Npb25JbmZvIgopCgp3cml0ZV9jc3ZfdW5pZmllZCgKICBzdXBwbGVtZW50X3NlY3Rpb25fbWFuaWZlc3QsCiAgInN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdC5jc3YiCikKCnNhdmVSRFMoCiAgbGlzdCgKICAgIGNvbmZpZyA9IHVuaWZpZWRfY29uZmlnLAogICAgYXNzaWdubWVudF9iYWxhbmNlID0gYXNzaWdubWVudF9iYWxhbmNlX3Jlc3VsdHMsCiAgICBwcm9maWxlX3JhbmRvbWl6YXRpb24gPSBwcm9maWxlX3JhbmRvbWl6YXRpb25fcmVzdWx0cywKICAgIGN1ZV9zbG9wZV9pbmZlcmVuY2UgPSBjdWVfc2xvcGVfaW5mZXJlbmNlX2FsbCwKICAgIGNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSA9CiAgICAgIGNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSwKICAgIGNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfcGxvdCA9CiAgICAgIHBfY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZXMsCiAgICBoeXBvdGhlc2lzX3Rlc3RzID0gaHlwb3RoZXNpc190ZXN0X3N1bW1hcnksCiAgICBwYXJ0eV9zdXBwb3J0X2FtY2UgPSBwYXJ0eV9zdXBwb3J0X2FtY2VfcmVzdWx0cywKICAgIHBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlID0gcGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfcmVzdWx0cywKICAgIHN0dWR5M19hbGxfcGFydHlfbWF0Y2ggPSBzdHVkeTNfYWxsX3BhcnR5X21hdGNoX3Jlc3VsdHMsCiAgICBjcm9zc19zdHVkeV9yZWxhdGl2ZV93ZWlnaHQgPSBjcm9zc19zdHVkeV9yZWxhdGl2ZV93ZWlnaHQsCiAgICBjcm9zc19zdHVkeV9yZWxhdGl2ZV9wbG90ID0gcF9jcm9zc19zdHVkeV9yZWxhdGl2ZSwKICAgIG1haW5fdGV4dF9maWd1cmVfbWFuaWZlc3QgPSBtYWluX3RleHRfZmlndXJlX21hbmlmZXN0LAogICAgc3VwcGxlbWVudF9maWd1cmVfbWFuaWZlc3QgPSBzdXBwbGVtZW50X2ZpZ3VyZV9tYW5pZmVzdCwKICAgIHN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdCA9IHN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdAogICksCiAgZmlsZSA9IGZpbGUucGF0aCgKICAgIHVuaWZpZWRfb3V0cHV0X2RpciwKICAgICJ1bmlmaWVkX3N1cHBsZW1lbnRfb2JqZWN0cy5yZHMiCiAgKQopCgpjYXB0dXJlLm91dHB1dCgKICBzZXNzaW9uSW5mbygpLAogIGZpbGUgPSBmaWxlLnBhdGgoCiAgICB1bmlmaWVkX291dHB1dF9kaXIsCiAgICAic2Vzc2lvbkluZm9fdW5pZmllZC50eHQiCiAgKQopCgpjYXQoCiAgIlxuM+Wun+mok+OBruacrOaWh+Wbs+WGjeePvuODu+ijnOmBuuWIhuaekOODu+aUr+aMgeaUv+WFmuWIpeeVsOizquaAp+WIhuaekOOBjOWujOS6huOBl+OBvuOBl+OBn+OAglxuIiwKICAi57Wx5ZCI5Ye65Yqb5YWIOiAiLAogIG5vcm1hbGl6ZVBhdGgodW5pZmllZF9vdXRwdXRfZGlyKSwKICAiXG4iLAogIHNlcCA9ICIiCikKCgpmaW5hbF9vdXRwdXRfcm9vdCA8LSB1bmlmaWVkX2NvbmZpZyRvdXRwdXRfcm9vdAoKZmluYWxfZGlycyA8LSBsaXN0KAogIG1haW5fZmlndXJlcyA9IGZpbGUucGF0aChmaW5hbF9vdXRwdXRfcm9vdCwgIm1haW5fdGV4dCIsICJmaWd1cmVzIiksCiAgbWFpbl90YWJsZXMgPSBmaWxlLnBhdGgoZmluYWxfb3V0cHV0X3Jvb3QsICJtYWluX3RleHQiLCAidGFibGVzIiksCiAgc3VwcGxlbWVudF9yb290ID0gZmlsZS5wYXRoKGZpbmFsX291dHB1dF9yb290LCAic3VwcGxlbWVudCIpLAogIHN1cHBsZW1lbnRfY3Jvc3MgPSBmaWxlLnBhdGgoZmluYWxfb3V0cHV0X3Jvb3QsICJzdXBwbGVtZW50IiwgImNyb3NzX3N0dWR5IiksCiAgZGlhZ25vc3RpY3Nfcm9vdCA9IGZpbGUucGF0aChmaW5hbF9vdXRwdXRfcm9vdCwgImRpYWdub3N0aWNzIiksCiAgbW9kZWxfb2JqZWN0c19yb290ID0gZmlsZS5wYXRoKGZpbmFsX291dHB1dF9yb290LCAibW9kZWxfb2JqZWN0cyIpLAogIGxvZ3MgPSBmaWxlLnBhdGgoZmluYWxfb3V0cHV0X3Jvb3QsICJsb2dzIikKKQoKaW52aXNpYmxlKAogIGxhcHBseSgKICAgIGZpbmFsX2RpcnMsCiAgICBkaXIuY3JlYXRlLAogICAgc2hvd1dhcm5pbmdzID0gRkFMU0UsCiAgICByZWN1cnNpdmUgPSBUUlVFCiAgKQopCgpmb3IgKHN0dWR5X2lkIGluIG5hbWVzKHN0dWR5X3NwZWNzKSkgewogIGZvciAoc3ViZGlyIGluIGMoImZpZ3VyZXMiLCAidGFibGVzX2NzdiIsICJ0YWJsZXNfdGV4IikpIHsKICAgIGRpci5jcmVhdGUoCiAgICAgIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgc3R1ZHlfaWQsIHN1YmRpciksCiAgICAgIHNob3dXYXJuaW5ncyA9IEZBTFNFLAogICAgICByZWN1cnNpdmUgPSBUUlVFCiAgICApCiAgfQogIGZvciAoc3ViZGlyIGluIGMoInNjcmVlbmluZyIsICJiYWxhbmNlIiwgInJhbmRvbWl6YXRpb24iKSkgewogICAgZGlyLmNyZWF0ZSgKICAgICAgZmlsZS5wYXRoKGZpbmFsX2RpcnMkZGlhZ25vc3RpY3Nfcm9vdCwgc3R1ZHlfaWQsIHN1YmRpciksCiAgICAgIHNob3dXYXJuaW5ncyA9IEZBTFNFLAogICAgICByZWN1cnNpdmUgPSBUUlVFCiAgICApCiAgfQogIGRpci5jcmVhdGUoCiAgICBmaWxlLnBhdGgoZmluYWxfZGlycyRtb2RlbF9vYmplY3RzX3Jvb3QsIHN0dWR5X2lkKSwKICAgIHNob3dXYXJuaW5ncyA9IEZBTFNFLAogICAgcmVjdXJzaXZlID0gVFJVRQogICkKfQoKZm9yIChzdWJkaXIgaW4gYygiZmlndXJlcyIsICJ0YWJsZXNfY3N2IiwgInRhYmxlc190ZXgiKSkgewogIGRpci5jcmVhdGUoCiAgICBmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X2Nyb3NzLCBzdWJkaXIpLAogICAgc2hvd1dhcm5pbmdzID0gRkFMU0UsCiAgICByZWN1cnNpdmUgPSBUUlVFCiAgKQp9CgoKY29weV9maWxlX2lmX2V4aXN0cyA8LSBmdW5jdGlvbihzb3VyY2UsIGRlc3RpbmF0aW9uKSB7CiAgaWYgKGlzLm5hKHNvdXJjZSkgfHwgIW56Y2hhcihzb3VyY2UpIHx8ICFmaWxlLmV4aXN0cyhzb3VyY2UpKSB7CiAgICByZXR1cm4oRkFMU0UpCiAgfQogIGRpci5jcmVhdGUoZGlybmFtZShkZXN0aW5hdGlvbiksIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQogIGlzVFJVRShmaWxlLmNvcHkoc291cmNlLCBkZXN0aW5hdGlvbiwgb3ZlcndyaXRlID0gVFJVRSwgY29weS5tb2RlID0gVFJVRSkpCn0KCmNvcHlfZmlsZXNfYnlfcGF0dGVybiA8LSBmdW5jdGlvbihzb3VyY2VfZGlyLCBkZXN0aW5hdGlvbl9kaXIsIHBhdHRlcm4pIHsKICBpZiAoIWRpci5leGlzdHMoc291cmNlX2RpcikpIHsKICAgIHJldHVybihjaGFyYWN0ZXIoKSkKICB9CiAgZmlsZXMgPC0gbGlzdC5maWxlcygKICAgIHNvdXJjZV9kaXIsCiAgICBwYXR0ZXJuID0gcGF0dGVybiwKICAgIGZ1bGwubmFtZXMgPSBUUlVFLAogICAgcmVjdXJzaXZlID0gVFJVRSwKICAgIGlnbm9yZS5jYXNlID0gVFJVRQogICkKICBpZiAobGVuZ3RoKGZpbGVzKSA9PSAwKSB7CiAgICByZXR1cm4oY2hhcmFjdGVyKCkpCiAgfQogIGRpci5jcmVhdGUoZGVzdGluYXRpb25fZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkKICBkZXN0aW5hdGlvbnMgPC0gZmlsZS5wYXRoKGRlc3RpbmF0aW9uX2RpciwgYmFzZW5hbWUoZmlsZXMpKQogIGNvcGllZCA8LSB2YXBwbHkoCiAgICBzZXFfYWxvbmcoZmlsZXMpLAogICAgZnVuY3Rpb24oaSkgY29weV9maWxlX2lmX2V4aXN0cyhmaWxlc1tpXSwgZGVzdGluYXRpb25zW2ldKSwKICAgIGxvZ2ljYWwoMSkKICApCiAgZGVzdGluYXRpb25zW2NvcGllZF0KfQoKbGF0ZXhfZXNjYXBlIDwtIGZ1bmN0aW9uKHgpIHsKICB4IDwtIGFzLmNoYXJhY3Rlcih4KQogIHhbaXMubmEoeCldIDwtICIiCgogIGVzY2FwZV9vbmUgPC0gZnVuY3Rpb24ocykgewogICAgY2hhcnMgPC0gc3Ryc3BsaXQocywgIiIsIGZpeGVkID0gVFJVRSlbWzFdXQoKICAgIGlmIChsZW5ndGgoY2hhcnMpID09IDBMKSB7CiAgICAgIHJldHVybigiIikKICAgIH0KCiAgICByZXBsYWNlbWVudCA8LSBjKAogICAgICAiXFwiID0gIlxcdGV4dGJhY2tzbGFzaHt9IiwKICAgICAgIiYiICA9ICJcXCYiLAogICAgICAiJSIgID0gIlxcJSIsCiAgICAgICIkIiAgPSAiXFwkIiwKICAgICAgIiMiICA9ICJcXCMiLAogICAgICAiXyIgID0gIlxcXyIsCiAgICAgICJ7IiAgPSAiXFx7IiwKICAgICAgIn0iICA9ICJcXH0iLAogICAgICAifiIgID0gIlxcdGV4dGFzY2lpdGlsZGV7fSIsCiAgICAgICJeIiAgPSAiXFx0ZXh0YXNjaWljaXJjdW17fSIKICAgICkKCiAgICBvdXQgPC0gdmFwcGx5KAogICAgICBjaGFycywKICAgICAgZnVuY3Rpb24oY2gpIHsKICAgICAgICBpZiAoY2ggJWluJSBuYW1lcyhyZXBsYWNlbWVudCkpIHsKICAgICAgICAgIHVubmFtZShyZXBsYWNlbWVudFtbY2hdXSkKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY2gKICAgICAgICB9CiAgICAgIH0sCiAgICAgIGNoYXJhY3RlcigxKQogICAgKQoKICAgIHBhc3RlMChvdXQsIGNvbGxhcHNlID0gIiIpCiAgfQoKICB2YXBwbHkoeCwgZXNjYXBlX29uZSwgY2hhcmFjdGVyKDEpLCBVU0UuTkFNRVMgPSBGQUxTRSkKfQoKZm9ybWF0X251bWJlciA8LSBmdW5jdGlvbih4LCBkaWdpdHMgPSAzKSB7CiAgb3V0IDwtIGlmZWxzZSgKICAgIGlzLm5hKHgpLAogICAgIiIsCiAgICBmb3JtYXRDKHgsIGZvcm1hdCA9ICJmIiwgZGlnaXRzID0gZGlnaXRzKQogICkKICBhcy5jaGFyYWN0ZXIob3V0KQp9Cgpmb3JtYXRfaW50ZWdlciA8LSBmdW5jdGlvbih4KSB7CiAgaWZlbHNlKGlzLm5hKHgpLCAiIiwgc2NhbGVzOjpjb21tYShhcy5pbnRlZ2VyKHJvdW5kKHgpKSkpCn0KCmZvcm1hdF9wX3ZhbHVlIDwtIGZ1bmN0aW9uKHgpIHsKICBkcGx5cjo6Y2FzZV93aGVuKAogICAgaXMubmEoeCkgfiAiIiwKICAgIHggPCAwLjAwMSB+ICI8IC4wMDEiLAogICAgVFJVRSB+IHN1YigiXjAiLCAiIiwgZm9ybWF0Qyh4LCBmb3JtYXQgPSAiZiIsIGRpZ2l0cyA9IDMpKQogICkKfQoKd3JpdGVfbGF0ZXhfbG9uZ3RhYmxlIDwtIGZ1bmN0aW9uKAogICAgZGF0YSwKICAgIGZpbGUsCiAgICBjYXB0aW9uLAogICAgbGFiZWwsCiAgICBub3RlcyA9IE5VTEwsCiAgICBsYW5kc2NhcGUgPSBuY29sKGRhdGEpID49IDcpIHsKICAKICBkYXRhIDwtIGFzLmRhdGEuZnJhbWUoZGF0YSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQogIGlmIChuY29sKGRhdGEpID09IDApIHsKICAgIGRhdGEgPC0gZGF0YS5mcmFtZShub3RlID0gIuipsuW9k+OBmeOCi+aOqOWumue1kOaenOOBr+OBguOCiuOBvuOBm+OCk+OAgiIpCiAgfQogIAogIGRpc3BsYXkgPC0gZGF0YQogIGRpc3BsYXlbXSA8LSBsYXBwbHkoZGlzcGxheSwgZnVuY3Rpb24oeCkgbGF0ZXhfZXNjYXBlKGFzLmNoYXJhY3Rlcih4KSkpCiAgaGVhZGVycyA8LSBsYXRleF9lc2NhcGUobmFtZXMoZGlzcGxheSkpCiAgCiAgbnVtZXJpY19jb2x1bW4gPC0gdmFwcGx5KGRhdGEsIGlzLm51bWVyaWMsIGxvZ2ljYWwoMSkpCiAgYWxpZ25tZW50IDwtIHBhc3RlMChpZmVsc2UobnVtZXJpY19jb2x1bW4sICJyIiwgImwiKSwgY29sbGFwc2UgPSAiIikKICAKICBsaW5lcyA8LSBjaGFyYWN0ZXIoKQogIGxpbmVzIDwtIGMobGluZXMsICIlIEdlbmVyYXRlZCBhdXRvbWF0aWNhbGx5IGJ5IHRoZSByZXBsaWNhdGlvbiBzY3JpcHQuIikKICBpZiAobGFuZHNjYXBlKSB7CiAgICBsaW5lcyA8LSBjKGxpbmVzLCAiXFxiZWdpbntsYW5kc2NhcGV9IikKICB9CiAgbGluZXMgPC0gYygKICAgIGxpbmVzLAogICAgIlxcYmVnaW5ncm91cCIsCiAgICAiXFxzbWFsbCIsCiAgICBwYXN0ZTAoIlxcYmVnaW57bG9uZ3RhYmxlfXsiLCBhbGlnbm1lbnQsICJ9IiksCiAgICBwYXN0ZTAoIlxcY2FwdGlvbnsiLCBsYXRleF9lc2NhcGUoY2FwdGlvbiksICJ9XFxsYWJlbHsiLCBsYWJlbCwgIn1cXFxcIiksCiAgICAiXFx0b3BydWxlIiwKICAgIHBhc3RlKGhlYWRlcnMsIGNvbGxhcHNlID0gIiAmICIpLAogICAgIlxcXFwiLAogICAgIlxcbWlkcnVsZSIsCiAgICAiXFxlbmRmaXJzdGhlYWQiLAogICAgcGFzdGUwKCJcXG11bHRpY29sdW1ueyIsIG5jb2woZGlzcGxheSksICJ9e2x9e1xcdGFibGVuYW1lflxcdGhldGFibGV7fe+8iOe2muOBje+8iX1cXFxcIiksCiAgICAiXFx0b3BydWxlIiwKICAgIHBhc3RlKGhlYWRlcnMsIGNvbGxhcHNlID0gIiAmICIpLAogICAgIlxcXFwiLAogICAgIlxcbWlkcnVsZSIsCiAgICAiXFxlbmRoZWFkIiwKICAgIHBhc3RlMCgiXFxtaWRydWxlXFxtdWx0aWNvbHVtbnsiLCBuY29sKGRpc3BsYXkpLCAifXtyfXvmrKHpoIHjgavntprjgY99XFxcXCIpLAogICAgIlxcZW5kZm9vdCIsCiAgICAiXFxib3R0b21ydWxlIiwKICAgICJcXGVuZGxhc3Rmb290IgogICkKICAKICBpZiAobnJvdyhkaXNwbGF5KSA+IDApIHsKICAgIHJvd19saW5lcyA8LSBhcHBseSgKICAgICAgZGlzcGxheSwKICAgICAgMSwKICAgICAgZnVuY3Rpb24ocm93KSBwYXN0ZTAocGFzdGUocm93LCBjb2xsYXBzZSA9ICIgJiAiKSwgIiBcXFxcIikKICAgICkKICAgIGxpbmVzIDwtIGMobGluZXMsIHJvd19saW5lcykKICB9CiAgCiAgbGluZXMgPC0gYyhsaW5lcywgIlxcZW5ke2xvbmd0YWJsZX0iKQogIGlmICghaXMubnVsbChub3RlcykgJiYgbnpjaGFyKG5vdGVzKSkgewogICAgbGluZXMgPC0gYygKICAgICAgbGluZXMsCiAgICAgICJcXHZzcGFjZXstMC41ZW19IiwKICAgICAgIlxcYmVnaW57bWluaXBhZ2V9e1xcbGluZXdpZHRofSIsCiAgICAgICJcXGZvb3Rub3Rlc2l6ZSIsCiAgICAgIHBhc3RlMCgiXFx0ZXh0aXR75rOo77yafSIsIGxhdGV4X2VzY2FwZShub3RlcykpLAogICAgICAiXFxlbmR7bWluaXBhZ2V9IgogICAgKQogIH0KICBsaW5lcyA8LSBjKGxpbmVzLCAiXFxlbmRncm91cCIpCiAgaWYgKGxhbmRzY2FwZSkgewogICAgbGluZXMgPC0gYyhsaW5lcywgIlxcZW5ke2xhbmRzY2FwZX0iKQogIH0KICAKICBkaXIuY3JlYXRlKGRpcm5hbWUoZmlsZSksIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQogIHdyaXRlTGluZXMobGluZXMsIGNvbiA9IGZpbGUsIHVzZUJ5dGVzID0gVFJVRSkKICBpbnZpc2libGUoZmlsZSkKfQoKd3JpdGVfY3N2X2FuZF90ZXggPC0gZnVuY3Rpb24oCiAgICBkYXRhLAogICAgY3N2X2ZpbGUsCiAgICB0ZXhfZmlsZSwKICAgIGNhcHRpb24sCiAgICBsYWJlbCwKICAgIG5vdGVzID0gTlVMTCwKICAgIGxhbmRzY2FwZSA9IG5jb2woZGF0YSkgPj0gNykgewogIGRpci5jcmVhdGUoZGlybmFtZShjc3ZfZmlsZSksIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQogIHJlYWRyOjp3cml0ZV9jc3YoZGF0YSwgY3N2X2ZpbGUsIG5hID0gIiIpCiAgd3JpdGVfbGF0ZXhfbG9uZ3RhYmxlKAogICAgZGF0YSA9IGRhdGEsCiAgICBmaWxlID0gdGV4X2ZpbGUsCiAgICBjYXB0aW9uID0gY2FwdGlvbiwKICAgIGxhYmVsID0gbGFiZWwsCiAgICBub3RlcyA9IG5vdGVzLAogICAgbGFuZHNjYXBlID0gbGFuZHNjYXBlCiAgKQogIGludmlzaWJsZShsaXN0KGNzdiA9IGNzdl9maWxlLCB0ZXggPSB0ZXhfZmlsZSkpCn0KCmF0dHJpYnV0ZV9sYWJlbF9tYXAgPC0gYygKICBwb2xpY3lfcG9zaXRpb24gPSAi5pS/562W5L2N572uIiwKICBnb3Zlcm5tZW50X3N0YXR1cyA9ICLkuI7ph47lhZrlnLDkvY0iLAogIHNlYXRzID0gIuitsOW4reaVsCIsCiAgcGFydHlfbmFtZSA9ICLmlL/lhZrlkI0iLAogIGdkcF9ncm93dGggPSAiR0RQ5oiQ6ZW3546HIiwKICBuaWtrZWkgPSAi5pel57WM5bmz5Z2H5qCq5L6hIiwKICBjcGkgPSAi5raI6LK76ICF54mp5L6h5oyH5pWw77yIQ1BJ77yJIiwKICB1bmVtcGxveW1lbnQgPSAi5aSx5qWt546HIgopCgpjdWVfZmFtaWx5X2xhYmVsIDwtIGMoCiAgcGFydHkgPSAi5pS/5YWa44Gu5omL44GM44GL44KKIiwKICBlY29ub21pYyA9ICLntYzmuIjjga7miYvjgYzjgYvjgooiCikKCgpzY3JlZW5pbmdfc3BlY3MgPC0gbGlzdCgKICBzdHVkeTEgPSBsaXN0KAogICAgaW5pdGlhbF9jb25zZW50X3ZhciA9ICJRMS4xIiwKICAgIGZpbmFsX2NvbnNlbnRfdmFyID0gc3R1ZHkxX2VudiRmaW5hbF9jb25zZW50X3ZhciwKICAgIGF0dGVudGlvbl92YXIgPSBOQV9jaGFyYWN0ZXJfLAogICAgYXR0ZW50aW9uX2Fuc3dlciA9IE5BX2NoYXJhY3Rlcl8sCiAgICBtYW5pcHVsYXRpb25fYXZhaWxhYmxlID0gRkFMU0UsCiAgICBpbnRyb19tYXAgPSBOVUxMCiAgKSwKICBzdHVkeTIgPSBsaXN0KAogICAgaW5pdGlhbF9jb25zZW50X3ZhciA9ICJRMS4xIiwKICAgIGZpbmFsX2NvbnNlbnRfdmFyID0gc3R1ZHkyX2VudiRmaW5hbF9jb25zZW50X3ZhciwKICAgIGF0dGVudGlvbl92YXIgPSBzdHVkeTJfZW52JGF0dGVudGlvbl9jaGVja192YXIsCiAgICBhdHRlbnRpb25fYW5zd2VyID0gYXMuY2hhcmFjdGVyKHN0dWR5Ml9lbnYkYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QpLAogICAgbWFuaXB1bGF0aW9uX2F2YWlsYWJsZSA9IFRSVUUsCiAgICBpbnRyb19tYXAgPSBOVUxMCiAgKSwKICBzdHVkeTMgPSBsaXN0KAogICAgaW5pdGlhbF9jb25zZW50X3ZhciA9ICJRMS4xIiwKICAgIGZpbmFsX2NvbnNlbnRfdmFyID0gc3R1ZHkzX2VudiRmaW5hbF9jb25zZW50X3ZhciwKICAgIGF0dGVudGlvbl92YXIgPSBzdHVkeTNfZW52JGF0dGVudGlvbl9jaGVja192YXIsCiAgICBhdHRlbnRpb25fYW5zd2VyID0gYXMuY2hhcmFjdGVyKHN0dWR5M19lbnYkYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QpLAogICAgbWFuaXB1bGF0aW9uX2F2YWlsYWJsZSA9IFRSVUUsCiAgICBpbnRyb19tYXAgPSBOVUxMCiAgKQopCgpyZXNwb25zZV9wcmVzZW50IDwtIGZ1bmN0aW9uKHgpIHsKICB4IDwtIGFzLmNoYXJhY3Rlcih4KQogICFpcy5uYSh4KSAmIHN0cmluZ3I6OnN0cl9zcXVpc2goeCkgIT0gIiIKfQoKcmVzcG9uc2VfaXNfY29kZSA8LSBmdW5jdGlvbih4LCBjb2RlKSB7CiAgeCA8LSBzdHJpbmdyOjpzdHJfc3F1aXNoKGFzLmNoYXJhY3Rlcih4KSkKICBjb2RlIDwtIGFzLmNoYXJhY3Rlcihjb2RlKQogIG91dCA8LSB4ID09IGNvZGUgfCBzdHJpbmdyOjpzdHJfZGV0ZWN0KHgsIHBhc3RlMCgiXFwoIiwgY29kZSwgIlxcKSQiKSkKICBvdXRbaXMubmEob3V0KV0gPC0gRkFMU0UKICBvdXQKfQoKZ2V0X21hcHBlZF9yZXNwb25zZSA8LSBmdW5jdGlvbihkYXRhLCBhc3NpZ25lZF9uLCBtYXAsIHZhbHVlX2NvbHVtbikgewogIHJlc3VsdCA8LSByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhkYXRhKSkKICBmb3IgKG5fdmFsdWUgaW4gMjo1KSB7CiAgICByb3cgPC0gbWFwW21hcCRwYXJ0eV9uID09IG5fdmFsdWUsICwgZHJvcCA9IEZBTFNFXQogICAgaWYgKG5yb3cocm93KSA9PSAwKSBuZXh0CiAgICB2YXJpYWJsZSA8LSBhcy5jaGFyYWN0ZXIocm93W1t2YWx1ZV9jb2x1bW5dXVsxXSkKICAgIGlmICghdmFyaWFibGUgJWluJSBuYW1lcyhkYXRhKSkgbmV4dAogICAgdGFrZSA8LSAhaXMubmEoYXNzaWduZWRfbikgJiBhc3NpZ25lZF9uID09IG5fdmFsdWUKICAgIHJlc3VsdFt0YWtlXSA8LSBhcy5jaGFyYWN0ZXIoZGF0YVtbdmFyaWFibGVdXVt0YWtlXSkKICB9CiAgcmVzdWx0Cn0KCmluZmVyX2Fzc2lnbmVkX2NvbmRpdGlvbiA8LSBmdW5jdGlvbihkYXRhLCBjaG9pY2VfbWFwLCBtYW5pcHVsYXRpb25fbWFwID0gTlVMTCwgaW50cm9fbWFwID0gTlVMTCkgewogIGNhbmRpZGF0ZSA8LSBtYXRyaXgoRkFMU0UsIG5yb3cgPSBucm93KGRhdGEpLCBuY29sID0gNCkKICBjb2xuYW1lcyhjYW5kaWRhdGUpIDwtIGFzLmNoYXJhY3RlcigyOjUpCiAgCiAgZm9yIChuX3ZhbHVlIGluIDI6NSkgewogICAgdmFyaWFibGVzIDwtIGNob2ljZV9tYXAkY2hvaWNlX3ZhcltjaG9pY2VfbWFwJHBhcnR5X24gPT0gbl92YWx1ZV0KICAgIGlmICghaXMubnVsbChtYW5pcHVsYXRpb25fbWFwKSAmJiBucm93KG1hbmlwdWxhdGlvbl9tYXApID4gMCkgewogICAgICB2YXJpYWJsZXMgPC0gYygKICAgICAgICB2YXJpYWJsZXMsCiAgICAgICAgbWFuaXB1bGF0aW9uX21hcCRtYW5pcHVsYXRpb25fdmFyW21hbmlwdWxhdGlvbl9tYXAkcGFydHlfbiA9PSBuX3ZhbHVlXQogICAgICApCiAgICB9CiAgICBpZiAoIWlzLm51bGwoaW50cm9fbWFwKSAmJiBhcy5jaGFyYWN0ZXIobl92YWx1ZSkgJWluJSBuYW1lcyhpbnRyb19tYXApKSB7CiAgICAgIHZhcmlhYmxlcyA8LSBjKHZhcmlhYmxlcywgdW5uYW1lKGludHJvX21hcFthcy5jaGFyYWN0ZXIobl92YWx1ZSldKSkKICAgIH0KICAgIHZhcmlhYmxlcyA8LSBpbnRlcnNlY3QodW5pcXVlKHZhcmlhYmxlcyksIG5hbWVzKGRhdGEpKQogICAgaWYgKGxlbmd0aCh2YXJpYWJsZXMpID4gMCkgewogICAgICBjYW5kaWRhdGVbLCBhcy5jaGFyYWN0ZXIobl92YWx1ZSldIDwtIGFwcGx5KAogICAgICAgIGRhdGFbLCB2YXJpYWJsZXMsIGRyb3AgPSBGQUxTRV0sCiAgICAgICAgMSwKICAgICAgICBmdW5jdGlvbihyb3cpIGFueShyZXNwb25zZV9wcmVzZW50KHJvdykpCiAgICAgICkKICAgIH0KICB9CiAgCiAgbl9jYW5kaWRhdGVzIDwtIHJvd1N1bXMoY2FuZGlkYXRlKQogIGFzc2lnbmVkIDwtIHJlcChOQV9pbnRlZ2VyXywgbnJvdyhkYXRhKSkKICBzaW5nbGUgPC0gbl9jYW5kaWRhdGVzID09IDEKICBhc3NpZ25lZFtzaW5nbGVdIDwtIGFzLmludGVnZXIoY29sbmFtZXMoY2FuZGlkYXRlKVttYXguY29sKGNhbmRpZGF0ZVtzaW5nbGUsICwgZHJvcCA9IEZBTFNFXSldKQogIAogIGlmIChhbnkobl9jYW5kaWRhdGVzID4gMSkpIHsKICAgIHdhcm5pbmcoIkNoZWNrIikKICB9CiAgYXNzaWduZWQKfQoKYnVpbGRfc2NyZWVuaW5nX291dHB1dHMgPC0gZnVuY3Rpb24oc3R1ZHlfc3BlYykgewogIHN0dWR5X2lkIDwtIHN0dWR5X3NwZWMkc3R1ZHlfaWQKICBlbnYgPC0gc3R1ZHlfc3BlYyRlbnYKICBzcGVjIDwtIHNjcmVlbmluZ19zcGVjc1tbc3R1ZHlfaWRdXQogIHJhdyA8LSBlbnYkZGZfaGVhZGVyX3JlbW92ZWQgJT4lCiAgICBkcGx5cjo6bXV0YXRlKElEID0gYXMuY2hhcmFjdGVyKElEKSkgJT4lCiAgICBkcGx5cjo6ZGlzdGluY3QoSUQsIC5rZWVwX2FsbCA9IFRSVUUpCiAgCiAgbWFuaXB1bGF0aW9uX21hcCA8LSBpZiAoCiAgICBzcGVjJG1hbmlwdWxhdGlvbl9hdmFpbGFibGUgJiYKICAgIGV4aXN0cygibWFuaXB1bGF0aW9uX21hcCIsIGVudmlyID0gZW52LCBpbmhlcml0cyA9IEZBTFNFKQogICkgewogICAgZ2V0KCJtYW5pcHVsYXRpb25fbWFwIiwgZW52aXIgPSBlbnYsIGluaGVyaXRzID0gRkFMU0UpCiAgfSBlbHNlIHsKICAgIE5VTEwKICB9CiAgCiAgYXNzaWduZWRfbiA8LSBpbmZlcl9hc3NpZ25lZF9jb25kaXRpb24oCiAgICBkYXRhID0gcmF3LAogICAgY2hvaWNlX21hcCA9IGVudiRjaG9pY2VfbWFwLAogICAgbWFuaXB1bGF0aW9uX21hcCA9IG1hbmlwdWxhdGlvbl9tYXAsCiAgICBpbnRyb19tYXAgPSBzcGVjJGludHJvX21hcAogICkKICAKICBpZiAoZXhpc3RzKCJpZF90YXNrX2NoZWNrIiwgZW52aXIgPSBlbnYsIGluaGVyaXRzID0gRkFMU0UpKSB7CiAgICBhbmFseXNpc19hc3NpZ25tZW50IDwtIGdldCgiaWRfdGFza19jaGVjayIsIGVudmlyID0gZW52LCBpbmhlcml0cyA9IEZBTFNFKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksCiAgICAgICAgcGFydHlfbiA9IGFzLmludGVnZXIoYXMuY2hhcmFjdGVyKHBhcnR5X24pKQogICAgICApICU+JQogICAgICBkcGx5cjo6Z3JvdXBfYnkoSUQpICU+JQogICAgICBkcGx5cjo6c3VtbWFyaXNlKAogICAgICAgIG5fY29uZGl0aW9uX2NhbmRpZGF0ZXMgPSBkcGx5cjo6bl9kaXN0aW5jdChwYXJ0eV9uKSwKICAgICAgICBhc3NpZ25lZF9mcm9tX2FuYWx5c2lzID0gZHBseXI6OmlmX2Vsc2UoCiAgICAgICAgICBuX2NvbmRpdGlvbl9jYW5kaWRhdGVzID09IDFMLAogICAgICAgICAgZHBseXI6OmZpcnN0KHBhcnR5X24pLAogICAgICAgICAgTkFfaW50ZWdlcl8KICAgICAgICApLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKQogICAgCiAgICBhbmFseXNpc19tYXRjaCA8LSBtYXRjaChyYXckSUQsIGFuYWx5c2lzX2Fzc2lnbm1lbnQkSUQpCiAgICB1c2VfYW5hbHlzaXNfYXNzaWdubWVudCA8LSAhaXMubmEoYW5hbHlzaXNfbWF0Y2gpICYKICAgICAgIWlzLm5hKGFuYWx5c2lzX2Fzc2lnbm1lbnQkYXNzaWduZWRfZnJvbV9hbmFseXNpc1thbmFseXNpc19tYXRjaF0pCiAgICBhc3NpZ25lZF9uW3VzZV9hbmFseXNpc19hc3NpZ25tZW50XSA8LQogICAgICBhbmFseXNpc19hc3NpZ25tZW50JGFzc2lnbmVkX2Zyb21fYW5hbHlzaXNbYW5hbHlzaXNfbWF0Y2hbdXNlX2FuYWx5c2lzX2Fzc2lnbm1lbnRdXQogIH0KICAKICBpZiAoZXhpc3RzKCJ2YWxpZF9pZHMiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsKICAgIGZpbmFsX2Fzc2lnbm1lbnQgPC0gZ2V0KCJ2YWxpZF9pZHMiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLAogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSkKICAgICAgKSAlPiUKICAgICAgZHBseXI6OmRpc3RpbmN0KElELCBwYXJ0eV9uKSAlPiUKICAgICAgZHBseXI6Omdyb3VwX2J5KElEKSAlPiUKICAgICAgZHBseXI6OnN1bW1hcmlzZSgKICAgICAgICBuX2NvbmRpdGlvbl9jYW5kaWRhdGVzID0gZHBseXI6Om5fZGlzdGluY3QocGFydHlfbiksCiAgICAgICAgYXNzaWduZWRfZnJvbV9maW5hbCA9IGRwbHlyOjppZl9lbHNlKAogICAgICAgICAgbl9jb25kaXRpb25fY2FuZGlkYXRlcyA9PSAxTCwKICAgICAgICAgIGRwbHlyOjpmaXJzdChwYXJ0eV9uKSwKICAgICAgICAgIE5BX2ludGVnZXJfCiAgICAgICAgKSwKICAgICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICAgICkKICAgIAogICAgZmluYWxfbWF0Y2ggPC0gbWF0Y2gocmF3JElELCBmaW5hbF9hc3NpZ25tZW50JElEKQogICAgdXNlX2ZpbmFsX2Fzc2lnbm1lbnQgPC0gIWlzLm5hKGZpbmFsX21hdGNoKSAmCiAgICAgICFpcy5uYShmaW5hbF9hc3NpZ25tZW50JGFzc2lnbmVkX2Zyb21fZmluYWxbZmluYWxfbWF0Y2hdKQogICAgYXNzaWduZWRfblt1c2VfZmluYWxfYXNzaWdubWVudF0gPC0KICAgICAgZmluYWxfYXNzaWdubWVudCRhc3NpZ25lZF9mcm9tX2ZpbmFsW2ZpbmFsX21hdGNoW3VzZV9maW5hbF9hc3NpZ25tZW50XV0KICB9CiAgCiAgaW5pdGlhbF9yZXNwb25zZSA8LSBpZiAoc3BlYyRpbml0aWFsX2NvbnNlbnRfdmFyICVpbiUgbmFtZXMocmF3KSkgewogICAgcmF3W1tzcGVjJGluaXRpYWxfY29uc2VudF92YXJdXQogIH0gZWxzZSB7CiAgICByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhyYXcpKQogIH0KICBmaW5hbF9yZXNwb25zZSA8LSBpZiAoc3BlYyRmaW5hbF9jb25zZW50X3ZhciAlaW4lIG5hbWVzKHJhdykpIHsKICAgIHJhd1tbc3BlYyRmaW5hbF9jb25zZW50X3Zhcl1dCiAgfSBlbHNlIHsKICAgIHJlcChOQV9jaGFyYWN0ZXJfLCBucm93KHJhdykpCiAgfQogIAogIHRhc2tfcmVzcG9uc2VzIDwtIGxhcHBseSgKICAgIDE6NSwKICAgIGZ1bmN0aW9uKHRhc2tfdmFsdWUpIHsKICAgICAgdGFza19tYXAgPC0gZW52JGNob2ljZV9tYXBbZW52JGNob2ljZV9tYXAkdGFzayA9PSB0YXNrX3ZhbHVlLCAsIGRyb3AgPSBGQUxTRV0KICAgICAgZ2V0X21hcHBlZF9yZXNwb25zZShyYXcsIGFzc2lnbmVkX24sIHRhc2tfbWFwLCAiY2hvaWNlX3ZhciIpCiAgICB9CiAgKQogIAogIHRhc2tfcGFzcyA8LSBsYXBwbHkoCiAgICB0YXNrX3Jlc3BvbnNlcywKICAgIGZ1bmN0aW9uKHJlc3BvbnNlKSB7CiAgICAgIHBhcnNlZCA8LSBzdXBwcmVzc1dhcm5pbmdzKHJlYWRyOjpwYXJzZV9udW1iZXIoYXMuY2hhcmFjdGVyKHJlc3BvbnNlKSkpCiAgICAgICFpcy5uYShhc3NpZ25lZF9uKSAmICFpcy5uYShwYXJzZWQpICYgcGFyc2VkID49IDEgJiBwYXJzZWQgPD0gYXNzaWduZWRfbgogICAgfQogICkKICAKICBpZiAoIWlzLm51bGwobWFuaXB1bGF0aW9uX21hcCkpIHsKICAgIG1hbmlwdWxhdGlvbl9yZXNwb25zZSA8LSBnZXRfbWFwcGVkX3Jlc3BvbnNlKAogICAgICByYXcsCiAgICAgIGFzc2lnbmVkX24sCiAgICAgIG1hbmlwdWxhdGlvbl9tYXAsCiAgICAgICJtYW5pcHVsYXRpb25fdmFyIgogICAgKQogICAgbWFuaXB1bGF0aW9uX2Fuc3dlciA8LSByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhyYXcpKQogICAgZm9yIChuX3ZhbHVlIGluIDI6NSkgewogICAgICBhbnN3ZXIgPC0gbWFuaXB1bGF0aW9uX21hcCRjb3JyZWN0X2Fuc3dlclttYW5pcHVsYXRpb25fbWFwJHBhcnR5X24gPT0gbl92YWx1ZV0KICAgICAgbWFuaXB1bGF0aW9uX2Fuc3dlclshaXMubmEoYXNzaWduZWRfbikgJiBhc3NpZ25lZF9uID09IG5fdmFsdWVdIDwtIGFuc3dlclsxXQogICAgfQogICAgbWFuaXB1bGF0aW9uX3Bhc3MgPC0gIWlzLm5hKGFzc2lnbmVkX24pICYgcmVzcG9uc2VfaXNfY29kZSgKICAgICAgbWFuaXB1bGF0aW9uX3Jlc3BvbnNlLAogICAgICBtYW5pcHVsYXRpb25fYW5zd2VyCiAgICApCiAgfSBlbHNlIHsKICAgIG1hbmlwdWxhdGlvbl9yZXNwb25zZSA8LSByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhyYXcpKQogICAgbWFuaXB1bGF0aW9uX3Bhc3MgPC0gcmVwKFRSVUUsIG5yb3cocmF3KSkKICB9CiAgCiAgaWYgKCFpcy5uYShzcGVjJGF0dGVudGlvbl92YXIpICYmIHNwZWMkYXR0ZW50aW9uX3ZhciAlaW4lIG5hbWVzKHJhdykpIHsKICAgIGF0dGVudGlvbl9yZXNwb25zZSA8LSByYXdbW3NwZWMkYXR0ZW50aW9uX3Zhcl1dCiAgICBhdHRlbnRpb25fcGFzcyA8LSByZXNwb25zZV9pc19jb2RlKGF0dGVudGlvbl9yZXNwb25zZSwgc3BlYyRhdHRlbnRpb25fYW5zd2VyKQogIH0gZWxzZSB7CiAgICBhdHRlbnRpb25fcmVzcG9uc2UgPC0gcmVwKE5BX2NoYXJhY3Rlcl8sIG5yb3cocmF3KSkKICAgIGF0dGVudGlvbl9wYXNzIDwtIHJlcChUUlVFLCBucm93KHJhdykpCiAgfQogIAogIGluaXRpYWxfcGFzcyA8LSByZXNwb25zZV9pc19jb2RlKGluaXRpYWxfcmVzcG9uc2UsIDEpIHwKICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoCiAgICAgIHN0cmluZ3I6OnN0cl9zcXVpc2goYXMuY2hhcmFjdGVyKGluaXRpYWxfcmVzcG9uc2UpKSwKICAgICAgIui2o+aXqOOBq+WQjOaEj+OBl+OBpi4q5Y2U5Yqb44GZ44KLIgogICAgKQogIGZpbmFsX3Bhc3MgPC0gcmVzcG9uc2VfaXNfY29kZShmaW5hbF9yZXNwb25zZSwgMSkgfAogICAgc3RyaW5ncjo6c3RyX2RldGVjdCgKICAgICAgc3RyaW5ncjo6c3RyX3NxdWlzaChhcy5jaGFyYWN0ZXIoZmluYWxfcmVzcG9uc2UpKSwKICAgICAgIuWQjOaEj+OBly4q5Zue562U57WQ5p6c44KS6YCB5L+h44GZ44KLIgogICAgKQogIAogIGZpbmFsX2lkcyA8LSBhcy5jaGFyYWN0ZXIoZW52JHZhbGlkX2lkcyRJRCkKICAKICBhdWRpdCA8LSB0aWJibGU6OnRpYmJsZSgKICAgIElEID0gcmF3JElELAogICAgYXNzaWduZWRfY29uZGl0aW9uID0gYXNzaWduZWRfbiwKICAgIGluaXRpYWxfY29uc2VudF9yZXNwb25zZSA9IGFzLmNoYXJhY3Rlcihpbml0aWFsX3Jlc3BvbnNlKSwKICAgIGluaXRpYWxfY29uc2VudF9wYXNzID0gaW5pdGlhbF9wYXNzLAogICAgcmVhY2hlZF9jb25qb2ludF9ibG9jayA9ICFpcy5uYShhc3NpZ25lZF9uKSwKICAgIHRhc2sxX3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKHRhc2tfcmVzcG9uc2VzW1sxXV0pLAogICAgdGFzazFfY29tcGxldGUgPSB0YXNrX3Bhc3NbWzFdXSwKICAgIHRhc2syX3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKHRhc2tfcmVzcG9uc2VzW1syXV0pLAogICAgdGFzazJfY29tcGxldGUgPSB0YXNrX3Bhc3NbWzJdXSwKICAgIHRhc2szX3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKHRhc2tfcmVzcG9uc2VzW1szXV0pLAogICAgdGFzazNfY29tcGxldGUgPSB0YXNrX3Bhc3NbWzNdXSwKICAgIHRhc2s0X3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKHRhc2tfcmVzcG9uc2VzW1s0XV0pLAogICAgdGFzazRfY29tcGxldGUgPSB0YXNrX3Bhc3NbWzRdXSwKICAgIHRhc2s1X3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKHRhc2tfcmVzcG9uc2VzW1s1XV0pLAogICAgdGFzazVfY29tcGxldGUgPSB0YXNrX3Bhc3NbWzVdXSwKICAgIGFsbF9maXZlX3Rhc2tzX2NvbXBsZXRlID0gUmVkdWNlKGAmYCwgdGFza19wYXNzKSwKICAgIG1hbmlwdWxhdGlvbl9yZXNwb25zZSA9IGFzLmNoYXJhY3RlcihtYW5pcHVsYXRpb25fcmVzcG9uc2UpLAogICAgbWFuaXB1bGF0aW9uX2NoZWNrX3Bhc3MgPSBtYW5pcHVsYXRpb25fcGFzcywKICAgIGF0dGVudGlvbl9yZXNwb25zZSA9IGFzLmNoYXJhY3RlcihhdHRlbnRpb25fcmVzcG9uc2UpLAogICAgYXR0ZW50aW9uX2NoZWNrX3Bhc3MgPSBhdHRlbnRpb25fcGFzcywKICAgIGZpbmFsX2NvbnNlbnRfcmVzcG9uc2UgPSBhcy5jaGFyYWN0ZXIoZmluYWxfcmVzcG9uc2UpLAogICAgZmluYWxfY29uc2VudF9wYXNzID0gZmluYWxfcGFzcywKICAgIGluY2x1ZGVkX2luX2ZpbmFsX2FuYWx5c2lzID0gSUQgJWluJSBmaW5hbF9pZHMKICApCiAgCiAgY3VtdWxhdGl2ZSA8LSByZXAoVFJVRSwgbnJvdyhhdWRpdCkpCiAgc3RhZ2VfcmVjb3JkcyA8LSBsaXN0KCkKICBhZGRfc3RhZ2UgPC0gZnVuY3Rpb24oc3RhZ2UsIHF1ZXN0aW9uX3ZhcmlhYmxlLCBjcml0ZXJpb24pIHsKICAgIGN1bXVsYXRpdmUgPDwtIGN1bXVsYXRpdmUgJiBjcml0ZXJpb24KICAgIHN0YWdlX3JlY29yZHNbW2xlbmd0aChzdGFnZV9yZWNvcmRzKSArIDFMXV0gPDwtIHRpYmJsZTo6dGliYmxlKAogICAgICBzdGFnZV9vcmRlciA9IGxlbmd0aChzdGFnZV9yZWNvcmRzKSArIDFMLAogICAgICBzdGFnZSA9IHN0YWdlLAogICAgICBxdWVzdGlvbl92YXJpYWJsZSA9IHF1ZXN0aW9uX3ZhcmlhYmxlLAogICAgICBuX3JlbWFpbmluZyA9IHN1bShjdW11bGF0aXZlLCBuYS5ybSA9IFRSVUUpCiAgICApCiAgfQogIAogIGFkZF9zdGFnZSgiUXVhbHRyaWNz44Gu6LOq5ZWP5paH44O7SW1wb3J0SWTooYzjgpLpmaTlpJYiLCAiUmVzcG9uc2VJZCIsIHJlcChUUlVFLCBucm93KGF1ZGl0KSkpCiAgYWRkX3N0YWdlKCLliJ3lm57lkIzmhI8iLCBzcGVjJGluaXRpYWxfY29uc2VudF92YXIsIGF1ZGl0JGluaXRpYWxfY29uc2VudF9wYXNzKQogIGFkZF9zdGFnZSgi5Ymy5LuY44GV44KM44Gf44Kz44Oz44K444On44Kk44Oz44OI44O744OW44Ot44OD44Kv44Gr5Yiw6YGUIiwgIlEzLjEvUTQuMS9RNS4xL1E2LjEg44G+44Gf44Gv5pyA5Yid44Gu6YG45oqe6Kqy6aGMIiwgYXVkaXQkcmVhY2hlZF9jb25qb2ludF9ibG9jaykKICBmb3IgKHRhc2tfdmFsdWUgaW4gMTo1KSB7CiAgICBhZGRfc3RhZ2UoCiAgICAgIHBhc3RlMCgi6YG45oqe6Kqy6aGMIiwgdGFza192YWx1ZSwgIuOCkuacieWKueWbnuetlCIpLAogICAgICBwYXN0ZTAoIuadoeS7tuWIpSBjaG9pY2UgdGFzayAiLCB0YXNrX3ZhbHVlKSwKICAgICAgYXVkaXRbW3Bhc3RlMCgidGFzayIsIHRhc2tfdmFsdWUsICJfY29tcGxldGUiKV1dCiAgICApCiAgfQogIGlmIChzcGVjJG1hbmlwdWxhdGlvbl9hdmFpbGFibGUpIHsKICAgIGFkZF9zdGFnZSgKICAgICAgIuaPkOekuuOBleOCjOOBn+mBuOaKnuiCouaVsOOCkuato+etlCIsCiAgICAgICLmnaHku7bliKXjgavoh6rli5XmpJzlh7rjgZfjgZ/pgbjmip7ogqLmlbDnorroqo3os6rllY8iLAogICAgICBhdWRpdCRtYW5pcHVsYXRpb25fY2hlY2tfcGFzcwogICAgKQogIH0KICBpZiAoIWlzLm5hKHNwZWMkYXR0ZW50aW9uX3ZhcikpIHsKICAgIGFkZF9zdGFnZSgKICAgICAgIuOCpOODh+OCquODreOCruODvOihjOWIl+OBruaMh+ekuumgheebruOBq+ato+etlCIsCiAgICAgIHNwZWMkYXR0ZW50aW9uX3ZhciwKICAgICAgYXVkaXQkYXR0ZW50aW9uX2NoZWNrX3Bhc3MKICAgICkKICB9CiAgYWRkX3N0YWdlKCLmnIDntYLpgIHkv6HlkIzmhI8iLCBzcGVjJGZpbmFsX2NvbnNlbnRfdmFyLCBhdWRpdCRmaW5hbF9jb25zZW50X3Bhc3MpCiAgYWRkX3N0YWdlKCLmnIDntYLliIbmnpDmqJnmnKwiLCAi5YWo5Z+65rqW44Gu56mN6ZuG5ZCIIiwgYXVkaXQkaW5jbHVkZWRfaW5fZmluYWxfYW5hbHlzaXMpCiAgCiAgZmxvdyA8LSBkcGx5cjo6YmluZF9yb3dzKHN0YWdlX3JlY29yZHMpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbl9leGNsdWRlZF9hdF9zdGFnZSA9IGRwbHlyOjpsYWcobl9yZW1haW5pbmcsIGRlZmF1bHQgPSBkcGx5cjo6Zmlyc3Qobl9yZW1haW5pbmcpKSAtIG5fcmVtYWluaW5nLAogICAgICByZXRlbnRpb25fZnJvbV9wcmV2aW91c19wY3QgPSBkcGx5cjo6aWZfZWxzZSgKICAgICAgICBkcGx5cjo6bGFnKG5fcmVtYWluaW5nLCBkZWZhdWx0ID0gZHBseXI6OmZpcnN0KG5fcmVtYWluaW5nKSkgPiAwLAogICAgICAgIDEwMCAqIG5fcmVtYWluaW5nIC8gZHBseXI6OmxhZyhuX3JlbWFpbmluZywgZGVmYXVsdCA9IGRwbHlyOjpmaXJzdChuX3JlbWFpbmluZykpLAogICAgICAgIE5BX3JlYWxfCiAgICAgICksCiAgICAgIHJldGVudGlvbl9mcm9tX2luaXRpYWxfcGN0ID0gMTAwICogbl9yZW1haW5pbmcgLyBkcGx5cjo6Zmlyc3Qobl9yZW1haW5pbmcpCiAgICApCiAgCiAgY29uZGl0aW9uX2Zsb3cgPC0gcHVycnI6Om1hcF9kZnIoCiAgICAyOjUsCiAgICBmdW5jdGlvbihuX3ZhbHVlKSB7CiAgICAgIHN1YnNldF9hdWRpdCA8LSBhdWRpdCAlPiUgZHBseXI6OmZpbHRlcihhc3NpZ25lZF9jb25kaXRpb24gPT0gbl92YWx1ZSkKICAgICAgaWYgKG5yb3coc3Vic2V0X2F1ZGl0KSA9PSAwKSB7CiAgICAgICAgcmV0dXJuKHRpYmJsZTo6dGliYmxlKCkpCiAgICAgIH0KICAgICAgY3JpdGVyaWEgPC0gbGlzdCgKICAgICAgICAi5Ymy5LuY5p2h5Lu244KS6K2Y5YilIiA9IHJlcChUUlVFLCBucm93KHN1YnNldF9hdWRpdCkpLAogICAgICAgICLpgbjmip7oqrLpoYwxIiA9IHN1YnNldF9hdWRpdCR0YXNrMV9jb21wbGV0ZSwKICAgICAgICAi6YG45oqe6Kqy6aGMMiIgPSBzdWJzZXRfYXVkaXQkdGFzazJfY29tcGxldGUsCiAgICAgICAgIumBuOaKnuiqsumhjDMiID0gc3Vic2V0X2F1ZGl0JHRhc2szX2NvbXBsZXRlLAogICAgICAgICLpgbjmip7oqrLpoYw0IiA9IHN1YnNldF9hdWRpdCR0YXNrNF9jb21wbGV0ZSwKICAgICAgICAi6YG45oqe6Kqy6aGMNSIgPSBzdWJzZXRfYXVkaXQkdGFzazVfY29tcGxldGUKICAgICAgKQogICAgICBpZiAoc3BlYyRtYW5pcHVsYXRpb25fYXZhaWxhYmxlKSB7CiAgICAgICAgY3JpdGVyaWFbWyLpgbjmip7ogqLmlbDnorroqo0iXV0gPC0gc3Vic2V0X2F1ZGl0JG1hbmlwdWxhdGlvbl9jaGVja19wYXNzCiAgICAgIH0KICAgICAgaWYgKCFpcy5uYShzcGVjJGF0dGVudGlvbl92YXIpKSB7CiAgICAgICAgY3JpdGVyaWFbWyLmjIfnpLrpoIXnm64iXV0gPC0gc3Vic2V0X2F1ZGl0JGF0dGVudGlvbl9jaGVja19wYXNzCiAgICAgIH0KICAgICAgY3JpdGVyaWFbWyLmnIDntYLpgIHkv6HlkIzmhI8iXV0gPC0gc3Vic2V0X2F1ZGl0JGZpbmFsX2NvbnNlbnRfcGFzcwogICAgICBjcml0ZXJpYVtbIuacgOe1guWIhuaekOaomeacrCJdXSA8LSBzdWJzZXRfYXVkaXQkaW5jbHVkZWRfaW5fZmluYWxfYW5hbHlzaXMKICAgICAgCiAgICAgIGtlZXAgPC0gcmVwKFRSVUUsIG5yb3coc3Vic2V0X2F1ZGl0KSkKICAgICAgcmVjb3JkcyA8LSBwdXJycjo6aW1hcF9kZnIoCiAgICAgICAgY3JpdGVyaWEsCiAgICAgICAgZnVuY3Rpb24oY3JpdGVyaW9uLCBzdGFnZV9uYW1lKSB7CiAgICAgICAgICBrZWVwIDw8LSBrZWVwICYgY3JpdGVyaW9uCiAgICAgICAgICB0aWJibGU6OnRpYmJsZSgKICAgICAgICAgICAgYXNzaWduZWRfY29uZGl0aW9uID0gbl92YWx1ZSwKICAgICAgICAgICAgc3RhZ2Vfb3JkZXIgPSB3aGljaChuYW1lcyhjcml0ZXJpYSkgPT0gc3RhZ2VfbmFtZSksCiAgICAgICAgICAgIHN0YWdlID0gc3RhZ2VfbmFtZSwKICAgICAgICAgICAgbl9yZW1haW5pbmcgPSBzdW0oa2VlcCwgbmEucm0gPSBUUlVFKQogICAgICAgICAgKQogICAgICAgIH0KICAgICAgKQogICAgICByZWNvcmRzICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBuX2V4Y2x1ZGVkX2F0X3N0YWdlID0gZHBseXI6OmxhZyhuX3JlbWFpbmluZywgZGVmYXVsdCA9IGRwbHlyOjpmaXJzdChuX3JlbWFpbmluZykpIC0gbl9yZW1haW5pbmcsCiAgICAgICAgICByZXRlbnRpb25fZnJvbV9jb25kaXRpb25fc3RhcnRfcGN0ID0gMTAwICogbl9yZW1haW5pbmcgLyBkcGx5cjo6Zmlyc3Qobl9yZW1haW5pbmcpCiAgICAgICAgKQogICAgfQogICkKICAKICBmaW5hbF9hdWRpdCA8LSBhdWRpdCAlPiUgZHBseXI6OmZpbHRlcihpbmNsdWRlZF9pbl9maW5hbF9hbmFseXNpcykKICByZXF1aXJlZF9maW5hbCA8LSBmaW5hbF9hdWRpdCRpbml0aWFsX2NvbnNlbnRfcGFzcyAmCiAgICBmaW5hbF9hdWRpdCRhbGxfZml2ZV90YXNrc19jb21wbGV0ZSAmCiAgICBmaW5hbF9hdWRpdCRtYW5pcHVsYXRpb25fY2hlY2tfcGFzcyAmCiAgICBmaW5hbF9hdWRpdCRhdHRlbnRpb25fY2hlY2tfcGFzcyAmCiAgICBmaW5hbF9hdWRpdCRmaW5hbF9jb25zZW50X3Bhc3MKICBpZiAoIWFsbChyZXF1aXJlZF9maW5hbCkpIHsKICAgIHN0b3AoIkNoZWNrIikKICB9CiAgaWYgKG5yb3coZmluYWxfYXVkaXQpICE9IGRwbHlyOjpuX2Rpc3RpbmN0KGVudiR2YWxpZF9pZHMkSUQpKSB7CiAgICBzdG9wKCJDaGVjayIpCiAgfQogIAogIGxpc3QoYXVkaXQgPSBhdWRpdCwgZmxvdyA9IGZsb3csIGNvbmRpdGlvbl9mbG93ID0gY29uZGl0aW9uX2Zsb3cpCn0KCgptYWtlX2FtY2VfdGFibGUgPC0gZnVuY3Rpb24oZW52LCBhZGp1c3RlZCA9IFRSVUUpIHsKICBzb3VyY2UgPC0gaWYgKGFkanVzdGVkKSBlbnYkYW1jZV9wbG90X2NvdiBlbHNlIGVudiRhbWNlX3Bsb3Rfbm9jb3YKICBuX3RhYmxlIDwtIGVudiRuX2J5X3BhcnR5ICU+JQogICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgcGFydHlfbl9udW1lcmljID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocGFydHlfbikpLAogICAgICByZXNwb25kZW50cyA9IG4KICAgICkKICAKICBzb3VyY2UgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBwYXJ0eV9uX251bWVyaWMgPSBzdXBwcmVzc1dhcm5pbmdzKHJlYWRyOjpwYXJzZV9udW1iZXIoYXMuY2hhcmFjdGVyKHBhcnR5X24pKSkKICAgICkgJT4lCiAgICBkcGx5cjo6bGVmdF9qb2luKG5fdGFibGUsIGJ5ID0gInBhcnR5X25fbnVtZXJpYyIpICU+JQogICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgYOadoeS7tmAgPSBhcy5jaGFyYWN0ZXIocGFydHlfbiksCiAgICAgIGDlsZ7mgKdgID0gYXMuY2hhcmFjdGVyKGF0dHJpYnV0ZSksCiAgICAgIGDmsLTmupbvvIjln7rmupbmsLTmupbjgajjga7lt67vvIlgID0gYXMuY2hhcmFjdGVyKGxhYmVsKSwKICAgICAgYOaOqOWumuWApO+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogZXN0aW1hdGUsIDIpLAogICAgICBg5qiZ5rqW6Kqk5beu77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBzdGQuZXJyb3IsIDIpLAogICAgICBgOTUlIENJ5LiL6ZmQ77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mLmxvdywgMiksCiAgICAgIGA5NSUgQ0nkuIrpmZDvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNvbmYuaGlnaCwgMiksCiAgICAgIGBw5YCkYCA9IGZvcm1hdF9wX3ZhbHVlKHAudmFsdWUpLAogICAgICBg5Zue562U6ICF5pWwYCA9IGZvcm1hdF9pbnRlZ2VyKHJlc3BvbmRlbnRzKQogICAgKQp9CgptYWtlX2ludGVyYWN0aW9uX3RhYmxlIDwtIGZ1bmN0aW9uKGVudikgewogIHNvdXJjZSA8LSBlbnYkaW50ZXJhY3Rpb25fcGxvdF9kZgogIGNvbmRpdGlvbl9jb2x1bW4gPC0gaW50ZXJzZWN0KGMoInBhcnR5X25fbGFiZWwiLCAicGFydHlfbiIpLCBuYW1lcyhzb3VyY2UpKVsxXQogIGlmIChpcy5uYShjb25kaXRpb25fY29sdW1uKSkgewogICAgc291cmNlJGNvbmRpdGlvbl9sYWJlbCA8LSAiIgogIH0gZWxzZSB7CiAgICBzb3VyY2UkY29uZGl0aW9uX2xhYmVsIDwtIGFzLmNoYXJhY3Rlcihzb3VyY2VbW2NvbmRpdGlvbl9jb2x1bW5dXSkKICB9CiAgc291cmNlICU+JQogICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgYOavlOi8g+adoeS7tmAgPSBjb25kaXRpb25fbGFiZWwsCiAgICAgIGDlsZ7mgKdgID0gYXMuY2hhcmFjdGVyKGF0dHJpYnV0ZSksCiAgICAgIGDmsLTmupZgID0gYXMuY2hhcmFjdGVyKGxhYmVsKSwKICAgICAgYDLpgbjmip7ogqLmnaHku7bjgajjga7lt67vvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGVzdGltYXRlLCAyKSwKICAgICAgYOaomea6luiqpOW3ru+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogc3RkLmVycm9yLCAyKSwKICAgICAgYDk1JSBDSeS4i+mZkO+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogY29uZi5sb3csIDIpLAogICAgICBgOTUlIENJ5LiK6ZmQ77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mLmhpZ2gsIDIpLAogICAgICBgcOWApGAgPSBmb3JtYXRfcF92YWx1ZShwLnZhbHVlKQogICAgKQp9CgpjbHVzdGVyZWRfbWVhbl9zdW1tYXJ5IDwtIGZ1bmN0aW9uKHksIGNsdXN0ZXIpIHsKICB5IDwtIGFzLm51bWVyaWMoeSkKICBjbHVzdGVyIDwtIGFzLmNoYXJhY3RlcihjbHVzdGVyKQogIGtlZXAgPC0gaXMuZmluaXRlKHkpICYgIWlzLm5hKGNsdXN0ZXIpCiAgeSA8LSB5W2tlZXBdCiAgY2x1c3RlciA8LSBjbHVzdGVyW2tlZXBdCiAgbiA8LSBsZW5ndGgoeSkKICBnIDwtIGRwbHlyOjpuX2Rpc3RpbmN0KGNsdXN0ZXIpCiAgaWYgKG4gPT0gMCkgewogICAgcmV0dXJuKGMoZXN0aW1hdGUgPSBOQV9yZWFsXywgc2UgPSBOQV9yZWFsXywgbG93ID0gTkFfcmVhbF8sIGhpZ2ggPSBOQV9yZWFsXywgbiA9IDAsIGcgPSAwKSkKICB9CiAgZXN0aW1hdGUgPC0gbWVhbih5KQogIGlmIChnIDw9IDEpIHsKICAgIHNlIDwtIE5BX3JlYWxfCiAgfSBlbHNlIHsKICAgIGNsdXN0ZXJfc2NvcmUgPC0gdGFwcGx5KHkgLSBlc3RpbWF0ZSwgY2x1c3Rlciwgc3VtKQogICAgdmFyaWFuY2UgPC0gKGcgLyAoZyAtIDEpKSAqIHN1bShjbHVzdGVyX3Njb3JlXjIpIC8gKG5eMikKICAgIHNlIDwtIHNxcnQodmFyaWFuY2UpCiAgfQogIGMoCiAgICBlc3RpbWF0ZSA9IGVzdGltYXRlLAogICAgc2UgPSBzZSwKICAgIGxvdyA9IGVzdGltYXRlIC0gMS45NiAqIHNlLAogICAgaGlnaCA9IGVzdGltYXRlICsgMS45NiAqIHNlLAogICAgbiA9IG4sCiAgICBnID0gZwogICkKfQoKbWFrZV9tbV90YWJsZSA8LSBmdW5jdGlvbihlbnYpIHsKICBhdHRyaWJ1dGVzIDwtIG5hbWVzKGVudiRyZWxhdGl2ZV9jdWVfbWFwKQogIGxvbmcgPC0gZW52JGNvbmpvaW50X2FsbF9tICU+JQogICAgZHBseXI6OnNlbGVjdChJRCwgcGFydHlfbiwgc2VsZWN0ZWQsIGRwbHlyOjphbGxfb2YoYXR0cmlidXRlcykpICU+JQogICAgdGlkeXI6OnBpdm90X2xvbmdlcigKICAgICAgY29scyA9IGRwbHlyOjphbGxfb2YoYXR0cmlidXRlcyksCiAgICAgIG5hbWVzX3RvID0gImF0dHJpYnV0ZSIsCiAgICAgIHZhbHVlc190byA9ICJsZXZlbCIKICAgICkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShsZXZlbCksIGFzLmNoYXJhY3RlcihsZXZlbCkgIT0gIiIpICU+JQogICAgZHBseXI6Om11dGF0ZShsZXZlbCA9IGFzLmNoYXJhY3RlcihsZXZlbCkpCiAgCiAgc3VtbWFyeSA8LSBsb25nICU+JQogICAgZHBseXI6Omdyb3VwX2J5KHBhcnR5X24sIGF0dHJpYnV0ZSwgbGV2ZWwpICU+JQogICAgZHBseXI6Omdyb3VwX21vZGlmeSgKICAgICAgfiB7CiAgICAgICAgdmFsdWVzIDwtIGNsdXN0ZXJlZF9tZWFuX3N1bW1hcnkoLngkc2VsZWN0ZWQsIC54JElEKQogICAgICAgIHRpYmJsZTo6dGliYmxlKAogICAgICAgICAgbWFyZ2luYWxfbWVhbiA9IHZhbHVlc1siZXN0aW1hdGUiXSwKICAgICAgICAgIGNsdXN0ZXJfc2UgPSB2YWx1ZXNbInNlIl0sCiAgICAgICAgICBjb25mX2xvdyA9IHZhbHVlc1sibG93Il0sCiAgICAgICAgICBjb25mX2hpZ2ggPSB2YWx1ZXNbImhpZ2giXSwKICAgICAgICAgIG5fcHJvZmlsZXMgPSB2YWx1ZXNbIm4iXSwKICAgICAgICAgIG5fcmVzcG9uZGVudHMgPSB2YWx1ZXNbImciXQogICAgICAgICkKICAgICAgfQogICAgKSAlPiUKICAgIGRwbHlyOjp1bmdyb3VwKCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBjdWVfZmFtaWx5ID0gdW5uYW1lKGVudiRyZWxhdGl2ZV9jdWVfbWFwW2F0dHJpYnV0ZV0pLAogICAgICBhdHRyaWJ1dGVfbGFiZWwgPSBkcGx5cjo6Y29hbGVzY2UodW5uYW1lKGF0dHJpYnV0ZV9sYWJlbF9tYXBbYXR0cmlidXRlXSksIGF0dHJpYnV0ZSksCiAgICAgIGN1ZV9sYWJlbCA9IGRwbHlyOjpjb2FsZXNjZSh1bm5hbWUoY3VlX2ZhbWlseV9sYWJlbFtjdWVfZmFtaWx5XSksIGN1ZV9mYW1pbHkpCiAgICApCiAgCiAgc3VtbWFyeSAlPiUKICAgIGRwbHlyOjp0cmFuc211dGUoCiAgICAgIGDmnaHku7ZgID0gcGFzdGUwKHBhcnR5X24sIGlmZWxzZSgicGFydHlfbmFtZSIgJWluJSBhdHRyaWJ1dGVzLCAi6YG45oqe6IKiIiwgIuaUv+WFmiIpKSwKICAgICAgYOaJi+OBjOOBi+OCiue+pGAgPSBjdWVfbGFiZWwsCiAgICAgIGDlsZ7mgKdgID0gYXR0cmlidXRlX2xhYmVsLAogICAgICBg5rC05rqWYCA9IGxldmVsLAogICAgICBg6ZmQ55WM5bmz5Z2H77yIJe+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIG1hcmdpbmFsX21lYW4sIDIpLAogICAgICBg44Kv44Op44K544K/U0XvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNsdXN0ZXJfc2UsIDIpLAogICAgICBgOTUlIENJ5LiL6ZmQ77yIJe+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNvbmZfbG93LCAyKSwKICAgICAgYDk1JSBDSeS4iumZkO+8iCXvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mX2hpZ2gsIDIpLAogICAgICBg44OX44Ot44OV44Kh44Kk44Or5pWwYCA9IGZvcm1hdF9pbnRlZ2VyKG5fcHJvZmlsZXMpLAogICAgICBg5Zue562U6ICF5pWwYCA9IGZvcm1hdF9pbnRlZ2VyKG5fcmVzcG9uZGVudHMpCiAgICApCn0KCm1ha2VfYXR0cmlidXRlX2ltcG9ydGFuY2VfdGFibGUgPC0gZnVuY3Rpb24oZW52KSB7CiAgc291cmNlIDwtIGVudiRyZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkYXR0cmlidXRlX2ltcG9ydGFuY2UKICBhZGp1c3RlZF9jb2wgPC0gaW50ZXJzZWN0KAogICAgYygiaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsICJjaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2VfcGFpcndpc2UiKSwKICAgIG5hbWVzKHNvdXJjZSkKICApWzFdCiAgYWRqdXN0ZWQgPC0gaWYgKCFpcy5uYShhZGp1c3RlZF9jb2wpKSBzb3VyY2VbW2FkanVzdGVkX2NvbF1dIGVsc2Ugc291cmNlJHBhcnR5X24gKiBzb3VyY2UkaW1wb3J0YW5jZV9wYWlyd2lzZQogIAogIHNvdXJjZSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIGFkanVzdGVkX3ZhbHVlID0gYWRqdXN0ZWQsCiAgICAgIGF0dHJpYnV0ZV9sYWJlbCA9IGRwbHlyOjpjb2FsZXNjZSh1bm5hbWUoYXR0cmlidXRlX2xhYmVsX21hcFthdHRyaWJ1dGVdKSwgYXR0cmlidXRlKSwKICAgICAgY3VlX2xhYmVsID0gZHBseXI6OmNvYWxlc2NlKHVubmFtZShjdWVfZmFtaWx5X2xhYmVsW2N1ZV9mYW1pbHldKSwgY3VlX2ZhbWlseSkKICAgICkgJT4lCiAgICBkcGx5cjo6dHJhbnNtdXRlKAogICAgICBg5p2h5Lu2YCA9IHBhcnR5X24sCiAgICAgIGDmiYvjgYzjgYvjgornvqRgID0gY3VlX2xhYmVsLAogICAgICBg5bGe5oCnYCA9IGF0dHJpYnV0ZV9sYWJlbCwKICAgICAgYOawtOa6luaVsGAgPSBuX2xldmVscywKICAgICAgYOacquiqv+aVtOmHjeimgeW6pu+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogaW1wb3J0YW5jZV9wYWlyd2lzZSwgMiksCiAgICAgIGDpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbvvIgl77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogYWRqdXN0ZWRfdmFsdWUsIDIpCiAgICApCn0KCm1ha2VfY3VlX2ltcG9ydGFuY2VfdGFibGUgPC0gZnVuY3Rpb24oZW52KSB7CiAgc291cmNlIDwtIGVudiRyZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscwogIGxhYmVscyA8LSBjKAogICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLmlL/lhZrmiYvjgYzjgYvjgorvvJrmnKroqr/mlbTph43opoHluqYiLAogICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLntYzmuIjmiYvjgYzjgYvjgorvvJrmnKroqr/mlbTph43opoHluqYiLAogICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9ICLmlL/lhZrmiYvjgYzjgYvjgorvvJrpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiLAogICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9ICLntYzmuIjmiYvjgYzjgYvjgorvvJrpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiLAogICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0gIuaUv+WFmuaJi+OBjOOBi+OCiuOBruebuOWvvuavlOmHjSIKICApCiAgc291cmNlIDwtIHNvdXJjZSAlPiUgZHBseXI6OmZpbHRlcihzdGF0aXN0aWMgJWluJSBuYW1lcyhsYWJlbHMpKQogIHNvdXJjZSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIGDmjIfmqJlgID0gdW5uYW1lKGxhYmVsc1tzdGF0aXN0aWNdKSwKICAgICAgYOWNmOS9jWAgPSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICAgIHN0YXRpc3RpYyAlaW4lIGMoInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLCAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIpIH4gInBwIiwKICAgICAgICBUUlVFIH4gIiUiCiAgICAgICksCiAgICAgIG11bHRpcGxpZXIgPSAxMDAKICAgICkgJT4lCiAgICBkcGx5cjo6dHJhbnNtdXRlKAogICAgICBg5p2h5Lu2YCA9IHBhcnR5X24sCiAgICAgIGDmjIfmqJlgID0gYOaMh+aomWAsCiAgICAgIGDljZjkvY1gID0gYOWNmOS9jWAsCiAgICAgIGDmjqjlrprlgKRgID0gZm9ybWF0X251bWJlcihtdWx0aXBsaWVyICogZXN0aW1hdGUsIDIpLAogICAgICBgOTUlIENJ5LiL6ZmQYCA9IGZvcm1hdF9udW1iZXIobXVsdGlwbGllciAqIGNvbmZfbG93LCAyKSwKICAgICAgYDk1JSBDSeS4iumZkGAgPSBmb3JtYXRfbnVtYmVyKG11bHRpcGxpZXIgKiBjb25mX2hpZ2gsIDIpCiAgICApCn0KCm1ha2VfY2xvZ2l0X3RhYmxlIDwtIGZ1bmN0aW9uKGVudikgewogIGVudiRjbG9naXRfcGxvdF9kZiAlPiUKICAgIGRwbHlyOjp0cmFuc211dGUoCiAgICAgIGDmnaHku7ZgID0gYXMuY2hhcmFjdGVyKHBhcnR5X24pLAogICAgICBg5bGe5oCnYCA9IGFzLmNoYXJhY3RlcihhdHRyaWJ1dGUpLAogICAgICBg5rC05rqW77yI5Z+65rqW5rC05rqW44Go44Gu5beu77yJYCA9IGFzLmNoYXJhY3RlcihsYWJlbCksCiAgICAgIGBsb2fkv4LmlbBgID0gZm9ybWF0X251bWJlcihlc3RpbWF0ZSwgMyksCiAgICAgIGDmqJnmupboqqTlt65gID0gZm9ybWF0X251bWJlcihzdGQuZXJyb3IsIDMpLAogICAgICBg44Kq44OD44K65q+UYCA9IGZvcm1hdF9udW1iZXIob2Rkc19yYXRpbywgMyksCiAgICAgIGA5NSUgQ0nkuIvpmZDvvIhPUu+8iWAgPSBmb3JtYXRfbnVtYmVyKG9kZHNfcmF0aW9fbG93LCAzKSwKICAgICAgYDk1JSBDSeS4iumZkO+8iE9S77yJYCA9IGZvcm1hdF9udW1iZXIob2Rkc19yYXRpb19oaWdoLCAzKSwKICAgICAgYHDlgKRgID0gZm9ybWF0X3BfdmFsdWUocC52YWx1ZSkKICAgICkKfQoKbWFrZV9saW5lYXJfdHJlbmRfdGFibGUgPC0gZnVuY3Rpb24oZW52KSB7CiAgaWYgKCFleGlzdHMoImxpbmVhcl90cmVuZF9wbG90X2RmIiwgZW52aXIgPSBlbnYsIGluaGVyaXRzID0gRkFMU0UpKSB7CiAgICByZXR1cm4odGliYmxlOjp0aWJibGUoKSkKICB9CiAgZW52JGxpbmVhcl90cmVuZF9wbG90X2RmICU+JQogICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgYOWxnuaAp2AgPSBhcy5jaGFyYWN0ZXIoYXR0cmlidXRlKSwKICAgICAgYOawtOa6lmAgPSBhcy5jaGFyYWN0ZXIobGFiZWwpLAogICAgICBg6YG45oqe6IKi44GMMeOBpOWil+OBiOOCi+OBqOOBjeOBruWkieWMlu+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogZXN0aW1hdGUsIDIpLAogICAgICBg5qiZ5rqW6Kqk5beu77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBzdGQuZXJyb3IsIDIpLAogICAgICBgOTUlIENJ5LiL6ZmQ77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mLmxvdywgMiksCiAgICAgIGA5NSUgQ0nkuIrpmZDvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNvbmYuaGlnaCwgMiksCiAgICAgIGBw5YCkYCA9IGZvcm1hdF9wX3ZhbHVlKHAudmFsdWUpCiAgICApCn0KCm1ha2VfcGFydHlfbWF0Y2hfdGFibGUgPC0gZnVuY3Rpb24oZW52KSB7CiAgaWYgKCFleGlzdHMoInBhcnR5X21hdGNoX2NvZWZfZGYiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsKICAgIHJldHVybih0aWJibGU6OnRpYmJsZSgpKQogIH0KICBvdmVyYWxsIDwtIGVudiRwYXJ0eV9tYXRjaF9jb2VmX2RmCiAgc3ViZ3JvdXAgPC0gaWYgKGV4aXN0cygicGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZiIsIGVudmlyID0gZW52LCBpbmhlcml0cyA9IEZBTFNFKSkgewogICAgZW52JHBhcnR5X21hdGNoX3N1Ymdyb3VwX2NvZWZfZGYKICB9IGVsc2UgewogICAgdGliYmxlOjp0aWJibGUoKQogIH0KICBjb21iaW5lZCA8LSBkcGx5cjo6YmluZF9yb3dzKG92ZXJhbGwsIHN1Ymdyb3VwKQogIGlmICghIm5faWRzIiAlaW4lIG5hbWVzKGNvbWJpbmVkKSkgY29tYmluZWQkbl9pZHMgPC0gTkFfcmVhbF8KICBpZiAoISJzdXBwb3J0X2dyb3VwX2xhYmVsIiAlaW4lIG5hbWVzKGNvbWJpbmVkKSkgY29tYmluZWQkc3VwcG9ydF9ncm91cF9sYWJlbCA8LSAi5YWo5L2TIgogIGNvbWJpbmVkICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgc3VwcG9ydF9ncm91cF9sYWJlbCA9IGRwbHlyOjpjb2FsZXNjZShhcy5jaGFyYWN0ZXIoc3VwcG9ydF9ncm91cF9sYWJlbCksICLlhajkvZMiKSwKICAgICAgbl9pZHMgPSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMobl9pZHMpKQogICAgKSAlPiUKICAgIGRwbHlyOjp0cmFuc211dGUoCiAgICAgIGDlr77osaFgID0gc3VwcG9ydF9ncm91cF9sYWJlbCwKICAgICAgYOmBuOaKnuiCouaVsGAgPSBwYXJ0eV9uLAogICAgICBg5LiA6Ie05Yq55p6c77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBlc3RpbWF0ZSwgMiksCiAgICAgIGDmqJnmupboqqTlt67vvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIHN0ZC5lcnJvciwgMiksCiAgICAgIGA5NSUgQ0nkuIvpmZDvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNvbmYubG93LCAyKSwKICAgICAgYDk1JSBDSeS4iumZkO+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogY29uZi5oaWdoLCAyKSwKICAgICAgYHDlgKRgID0gZm9ybWF0X3BfdmFsdWUocC52YWx1ZSksCiAgICAgIGDlm57nrZTogIXmlbBgID0gZm9ybWF0X2ludGVnZXIobl9pZHMpCiAgICApCn0KCgpzY3JlZW5pbmdfcXVlc3Rpb25fd29yZGluZyA8LSBmdW5jdGlvbihzdHVkeV9pZCwgc3RhZ2UsIHBhcnR5X24gPSBOQV9pbnRlZ2VyXykgewogIHN0YWdlIDwtIGFzLmNoYXJhY3RlcihzdGFnZSkKICBwYXJ0eV9uIDwtIHN1cHByZXNzV2FybmluZ3MoYXMuaW50ZWdlcihwYXJ0eV9uKSkKICBpZiAobGVuZ3RoKHBhcnR5X24pID09IDFMICYmIGxlbmd0aChzdGFnZSkgPiAxTCkgewogICAgcGFydHlfbiA8LSByZXAocGFydHlfbiwgbGVuZ3RoKHN0YWdlKSkKICB9CiAgaWYgKGxlbmd0aChwYXJ0eV9uKSAhPSBsZW5ndGgoc3RhZ2UpKSB7CiAgICBwYXJ0eV9uIDwtIHJlcChOQV9pbnRlZ2VyXywgbGVuZ3RoKHN0YWdlKSkKICB9CgogIHB1cnJyOjptYXAyX2NocihzdGFnZSwgcGFydHlfbiwgZnVuY3Rpb24oc3RhZ2VfdmFsdWUsIG5fdmFsdWUpIHsKICAgIGtfdGV4dCA8LSBpZmVsc2UoaXMubmEobl92YWx1ZSksICJrIiwgYXMuY2hhcmFjdGVyKG5fdmFsdWUpKQoKICAgIGlmIChzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YWdlX3ZhbHVlLCAiUXVhbHRyaWNzIikpIHsKICAgICAgcmV0dXJuKCLvvIhRdWFsdHJpY3Pjga7jg6Hjgr/jg4fjg7zjgr/ooYzjgILoqr/mn7vos6rllY/jgafjga/jgarjgYTvvIkiKQogICAgfQoKICAgIGlmIChzdGFnZV92YWx1ZSA9PSAi5Yid5Zue5ZCM5oSPIikgewogICAgICByZXR1cm4oIuOAjOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBpuOAgeacrOiqv+afu+OBq+WNlOWKm+OBmeOCi+OAjSIpCiAgICB9CgogICAgaWYgKHN0cmluZ3I6OnN0cl9kZXRlY3Qoc3RhZ2VfdmFsdWUsICLjgrPjg7Pjgrjjg6fjgqTjg7Pjg4jjg7vjg5bjg63jg4Pjgq/jgavliLDpgZR85Ymy5LuY5p2h5Lu244KS6K2Y5YilIikpIHsKICAgICAgaWYgKHN0dWR5X2lkID09ICJzdHVkeTMiKSB7CiAgICAgICAgcmV0dXJuKHBhc3RlMCgKICAgICAgICAgICLjgIzku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgosiLCBrX3RleHQsCiAgICAgICAgICAi44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CC4oCmIiwga190ZXh0LAogICAgICAgICAgIuOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBrueKtuazgeOCkumBuOaKnuOBleOCjOOCi+OBi+OAgTHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgILkvZzmpa3jga815Zue57mw44KK6L+U44GV44KM44G+44GZ44CC44CNIgogICAgICAgICkpCiAgICAgIH0KICAgICAgcmV0dXJuKHBhc3RlMCgKICAgICAgICAi44CM5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KLIiwga190ZXh0LAogICAgICAgICLjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgILigKYiLCBrX3RleHQsCiAgICAgICAgIuOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAgTHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgILkvZzmpa3jga815Zue57mw44KK6L+U44GV44KM44G+44GZ44CC44CNIgogICAgICApKQogICAgfQoKICAgIGlmIChzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YWdlX3ZhbHVlLCAiXumBuOaKnuiqsumhjFsxLTVdIikpIHsKICAgICAgaWYgKHN0dWR5X2lkID09ICJzdHVkeTMiKSB7CiAgICAgICAgcmV0dXJuKHBhc3RlMCgKICAgICAgICAgICLjgIzku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgosiLCBrX3RleHQsCiAgICAgICAgICAi44Gk44Gu6YG45oqe6IKi44KS5o+Q56S644GV44Gb44Gm44GE44Gf44Gg44GN44G+44GZ44CC4oCm5pS/5qip5LiO5YWa44Gr44GC44KL5pS/5YWa44Go57WM5riI54q25rOB44Gu57WE44G/5ZCI44KP44Gb44Gu44GG44Gh44CB44GC44Gq44Gf44Gv44Gp44Gu54q25rOB44Gn44GC44KM44Gw44CB5pS/5qip5LiO5YWa44Gr5oqV56Wo44GX44G+44GZ44GL44CC44CNIgogICAgICAgICkpCiAgICAgIH0KICAgICAgaWYgKHN0dWR5X2lkID09ICJzdHVkeTIiKSB7CiAgICAgICAgcmV0dXJuKHBhc3RlMCgKICAgICAgICAgICLjgIzku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgosiLCBrX3RleHQsCiAgICAgICAgICAi44Gk44Gu6YG45oqe6IKi44KS5o+Q56S644GV44Gb44Gm44GE44Gf44Gg44GN44G+44GZ44CC44GC44Gq44Gf44Gv44CB6KGG6K2w6Zmi6K2w5ZOh57eP6YG45oyZ44Gr44GK44GE44Gm44CB5Lul5LiL44Gu44GE44Ga44KM44Gu5pS/5YWa44KS44GK6YG444Gz44Gr44Gq44KK44G+44GZ44GL44CC44CNIgogICAgICAgICkpCiAgICAgIH0KICAgICAgcmV0dXJuKHBhc3RlMCgKICAgICAgICAi44CM5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLIiwga190ZXh0LAogICAgICAgICLjgaTjga7pgbjmip7ogqLjgpLmj5DnpLrjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgILjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHmj5DnpLrjgZXjgozjgZ/mlL/lhZrjga7kuK3jgYvjgokx44Gk44KS6YG45oqe44GX44Gm44GP44Gg44GV44GE44CC44CNIgogICAgICApKQogICAgfQoKICAgIGlmIChzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YWdlX3ZhbHVlLCAi5o+Q56S644GV44KM44Gf6YG45oqe6IKi5pWw44KS5q2j562UfOmBuOaKnuiCouaVsOeiuuiqjSIpKSB7CiAgICAgIGlmIChzdHVkeV9pZCA9PSAic3R1ZHkyIikgewogICAgICAgIHJldHVybigi44CM44GC44Gq44Gf44Gr5o+Q56S644GV44KM44Gf5pS/5YWa44Gu6YG45oqe6IKi44Gu5pWw44Gv44CB44GE44GP44Gk44Gn44GX44Gf44GL44CC44CNIikKICAgICAgfQogICAgICBpZiAoc3R1ZHlfaWQgPT0gInN0dWR5MyIpIHsKICAgICAgICByZXR1cm4oIuOAjOOBguOBquOBn+OBq+aPkOekuuOBleOCjOOBn+mBuOaKnuiCouOBruaVsOOBr+OAgeOBhOOBj+OBpOOBp+OBl+OBn+OBi+OAguOAjSIpCiAgICAgIH0KICAgICAgcmV0dXJuKCLvvIhTdHVkeSAx44Gn44Gv6Kmy5b2T6LOq5ZWP44Gq44GX77yJIikKICAgIH0KCiAgICBpZiAoc3RyaW5ncjo6c3RyX2RldGVjdChzdGFnZV92YWx1ZSwgIuOCpOODh+OCquODreOCruODvOihjOWIl+OBruaMh+ekuumgheebrnzmjIfnpLrpoIXnm64iKSkgewogICAgICBpZiAoc3R1ZHlfaWQgJWluJSBjKCJzdHVkeTIiLCAic3R1ZHkzIikpIHsKICAgICAgICByZXR1cm4oIuOAjO+8geOBk+OBrumgheebruOBr+W/heOBmuOAjjPjgI/jgpLpgbjjgpPjgafjgY/jgaDjgZXjgYTvvIHjgI0iKQogICAgICB9CiAgICAgIHJldHVybigi77yIU3R1ZHkgMeOBp+OBr+ipsuW9k+izquWVj+OBquOBl++8iSIpCiAgICB9CgogICAgaWYgKHN0YWdlX3ZhbHVlID09ICLmnIDntYLpgIHkv6HlkIzmhI8iKSB7CiAgICAgIHJldHVybigi44CM5pys6Kq/5p+744Gu5Li75peo44Gr5ZCM5oSP44GX44CB5Zue562U57WQ5p6c44KS6YCB5L+h44GZ44KL44CC44CNIikKICAgIH0KCiAgICBpZiAoc3RhZ2VfdmFsdWUgPT0gIuacgOe1guWIhuaekOaomeacrCIpIHsKICAgICAgcmV0dXJuKCLvvIjos6rllY/mlofjgarjgZfjgILkuIroqJjjga7lhajln7rmupbjga7nqY3pm4blkIjvvIkiKQogICAgfQoKICAgICLigJQiCiAgfSkKfQoKCnNjcmVlbmluZ19yZXN1bHRzIDwtIGxpc3QoKQpzdHVkeV90YWJsZV9wYXRocyA8LSBsaXN0KCkKCmZvciAoc3R1ZHlfaWQgaW4gbmFtZXMoc3R1ZHlfc3BlY3MpKSB7CiAgc3BlYyA8LSBzdHVkeV9zcGVjc1tbc3R1ZHlfaWRdXQogIGVudiA8LSBzcGVjJGVudgogIHN0dWR5X2xhYmVsIDwtIHNwZWMkc3R1ZHlfbGFiZWwKICBjc3ZfZGlyIDwtIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgc3R1ZHlfaWQsICJ0YWJsZXNfY3N2IikKICB0ZXhfZGlyIDwtIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgc3R1ZHlfaWQsICJ0YWJsZXNfdGV4IikKICBkaWFnX3NjcmVlbl9kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkZGlhZ25vc3RpY3Nfcm9vdCwgc3R1ZHlfaWQsICJzY3JlZW5pbmciKQogIGRpYWdfYmFsYW5jZV9kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkZGlhZ25vc3RpY3Nfcm9vdCwgc3R1ZHlfaWQsICJiYWxhbmNlIikKICBkaWFnX3JhbmRvbV9kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkZGlhZ25vc3RpY3Nfcm9vdCwgc3R1ZHlfaWQsICJyYW5kb21pemF0aW9uIikKICAKICBzY3JlZW5pbmcgPC0gYnVpbGRfc2NyZWVuaW5nX291dHB1dHMoc3BlYykKICBzY3JlZW5pbmdfcmVzdWx0c1tbc3R1ZHlfaWRdXSA8LSBzY3JlZW5pbmcKICAKICByZWFkcjo6d3JpdGVfY3N2KHNjcmVlbmluZyRhdWRpdCwgZmlsZS5wYXRoKGRpYWdfc2NyZWVuX2RpciwgInJlc3BvbmRlbnRfc2NyZWVuaW5nX2F1ZGl0LmNzdiIpLCBuYSA9ICIiKQogIHJlYWRyOjp3cml0ZV9jc3Yoc2NyZWVuaW5nJGZsb3csIGZpbGUucGF0aChkaWFnX3NjcmVlbl9kaXIsICJzZXF1ZW50aWFsX3NhbXBsZV9mbG93LmNzdiIpLCBuYSA9ICIiKQogIHJlYWRyOjp3cml0ZV9jc3Yoc2NyZWVuaW5nJGNvbmRpdGlvbl9mbG93LCBmaWxlLnBhdGgoZGlhZ19zY3JlZW5fZGlyLCAic2VxdWVudGlhbF9zYW1wbGVfZmxvd19ieV9jb25kaXRpb24uY3N2IiksIG5hID0gIiIpCiAgCiAgYXR0cml0aW9uX3RhYmxlIDwtIHNjcmVlbmluZyRmbG93ICU+JQogICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgYOmghuW6j2AgPSBzdGFnZV9vcmRlciwKICAgICAgYOautemajmAgPSBzdGFnZSwKICAgICAgYOizquWVj+ODu+WkieaVsGAgPSBxdWVzdGlvbl92YXJpYWJsZSwKICAgICAgYOizquWVj+aWh++8iOiqv+afu+elqOODu+imgee0hO+8iWAgPSBzY3JlZW5pbmdfcXVlc3Rpb25fd29yZGluZyhzdHVkeV9pZCwgc3RhZ2UpLAogICAgICBg5q6L5a2YTmAgPSBmb3JtYXRfaW50ZWdlcihuX3JlbWFpbmluZyksCiAgICAgIGDlvZPoqbLmrrXpmo7jgafjga7pmaTlpJZOYCA9IGZvcm1hdF9pbnRlZ2VyKG5fZXhjbHVkZWRfYXRfc3RhZ2UpLAogICAgICBg5YmN5q616ZqO44GL44KJ44Gu5q6L5a2Y546H77yIJe+8iWAgPSBmb3JtYXRfbnVtYmVyKHJldGVudGlvbl9mcm9tX3ByZXZpb3VzX3BjdCwgMSksCiAgICAgIGDliJ3mnJ/mqJnmnKzjgYvjgonjga7mrovlrZjnjofvvIgl77yJYCA9IGZvcm1hdF9udW1iZXIocmV0ZW50aW9uX2Zyb21faW5pdGlhbF9wY3QsIDEpCiAgICApCiAgCiAgd3JpdGVfY3N2X2FuZF90ZXgoCiAgICBhdHRyaXRpb25fdGFibGUsCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb24uY3N2IiksCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb24udGV4IiksCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJros6rllY/mrrXpmo7jgZTjgajjga7pgJDmrKHnmoTjgarmqJnmnKzmuJvlsJEiKSwKICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLWF0dHJpdGlvbiIpLAogICAgbm90ZXMgPSBwYXN0ZTAoCiAgICAgICLlkITooYzjga/nm7TliY3jgb7jgafjga7ln7rmupbjgpLmuoDjgZ/jgZfjgZ/lm57nrZTogIXjgavmrKHjga7ln7rmupbjgpLpoIbjgavpgannlKjjgZfjgZ/mrovlrZjmlbDjgpLnpLrjgZnjgIIiLAogICAgICBpZmVsc2UoCiAgICAgICAgc3R1ZHlfaWQgPT0gInN0dWR5MSIsCiAgICAgICAgIlN0dWR5IDHjgafjga/pgbjmip7ogqLmlbDnorroqo3os6rllY/jgYrjgojjgbPmjIfnpLrpoIXnm67jga/oqr/mn7vnpajjgavoqK3jgZHjgonjgozjgabjgYTjgarjgYTjgIIiLAogICAgICAgICLmnIDntYLliIbmnpDjga/jgIHpgbjmip7ogqLmlbDnorroqo3jgahRMjUuMV8xMeOBruaMh+ekuumgheebruOBruWPjOaWueOBq+ato+etlOOBl+OBn+WbnuetlOiAheOBq+mZkOWumuOBl+OBn+OAgiIKICAgICAgKQogICAgKQogICkKICAKICBjb25kaXRpb25fYXR0cml0aW9uX3RhYmxlIDwtIHNjcmVlbmluZyRjb25kaXRpb25fZmxvdyAlPiUKICAgIGRwbHlyOjp0cmFuc211dGUoCiAgICAgIGDmnaHku7ZgID0gYXNzaWduZWRfY29uZGl0aW9uLAogICAgICBg6aCG5bqPYCA9IHN0YWdlX29yZGVyLAogICAgICBg5q616ZqOYCA9IHN0YWdlLAogICAgICBg6LOq5ZWP5paH77yI6Kq/5p+756Wo44O76KaB57SE77yJYCA9IHNjcmVlbmluZ19xdWVzdGlvbl93b3JkaW5nKHN0dWR5X2lkLCBzdGFnZSwgYXNzaWduZWRfY29uZGl0aW9uKSwKICAgICAgYOaui+WtmE5gID0gZm9ybWF0X2ludGVnZXIobl9yZW1haW5pbmcpLAogICAgICBg5b2T6Kmy5q616ZqO44Gn44Gu6Zmk5aSWTmAgPSBmb3JtYXRfaW50ZWdlcihuX2V4Y2x1ZGVkX2F0X3N0YWdlKSwKICAgICAgYOadoeS7tumWi+Wni+aZguOBi+OCieOBruaui+WtmOeOh++8iCXvvIlgID0gZm9ybWF0X251bWJlcihyZXRlbnRpb25fZnJvbV9jb25kaXRpb25fc3RhcnRfcGN0LCAxKQogICAgKQogIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgY29uZGl0aW9uX2F0dHJpdGlvbl90YWJsZSwKICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfc2FtcGxlX2F0dHJpdGlvbl9ieV9jb25kaXRpb24uY3N2IiksCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb25fYnlfY29uZGl0aW9uLnRleCIpLAogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5p2h5Lu25Yil44Gu6YCQ5qyh55qE44Gq5qiZ5pys5rib5bCRIiksCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1hdHRyaXRpb24tY29uZGl0aW9uIiksCiAgICBub3RlcyA9ICLmnaHku7bjgpLlm57nrZTlsaXmrbTjgYvjgonorZjliKXjgafjgY3jgZ/lm57nrZTogIXjgavjgaTjgYTjgabjgIHlkITmnaHku7blhoXjgafln7rmupbjgpLntK/nqY3nmoTjgavpgannlKjjgZfjgZ/jgIIiCiAgKQogIAogIG1hbmlwdWxhdGlvbl90YWJsZSA8LSBzY3JlZW5pbmckYXVkaXQgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShhc3NpZ25lZF9jb25kaXRpb24pKSAlPiUKICAgIGRwbHlyOjpjb3VudCgKICAgICAgYXNzaWduZWRfY29uZGl0aW9uLAogICAgICBtYW5pcHVsYXRpb25fcmVzcG9uc2UsCiAgICAgIG1hbmlwdWxhdGlvbl9jaGVja19wYXNzLAogICAgICBuYW1lID0gIm4iCiAgICApICU+JQogICAgZHBseXI6OnRyYW5zbXV0ZSgKICAgICAgYOadoeS7tmAgPSBhc3NpZ25lZF9jb25kaXRpb24sCiAgICAgIGDos6rllY/mlofvvIjoqr/mn7vnpajvvIlgID0gc2NyZWVuaW5nX3F1ZXN0aW9uX3dvcmRpbmcoc3R1ZHlfaWQsICLpgbjmip7ogqLmlbDnorroqo0iLCBhc3NpZ25lZF9jb25kaXRpb24pLAogICAgICBg5Zue562UYCA9IGRwbHlyOjpjb2FsZXNjZShtYW5pcHVsYXRpb25fcmVzcG9uc2UsICLmnKrlrp/mlr3jg7vmrKDmkI0iKSwKICAgICAgYOato+etlGAgPSBpZmVsc2UobWFuaXB1bGF0aW9uX2NoZWNrX3Bhc3MsICLmraPnrZQiLCAi5LiN5q2j562U44O75qyg5pCNIiksCiAgICAgIGBOYCA9IGZvcm1hdF9pbnRlZ2VyKG4pCiAgICApCiAgaWYgKHN0dWR5X2lkID09ICJzdHVkeTEiKSB7CiAgICBtYW5pcHVsYXRpb25fdGFibGUgPC0gdGliYmxlOjp0aWJibGUoCiAgICAgIGDmnaHku7ZgID0gIuWFqOadoeS7tiIsCiAgICAgIGDos6rllY/mlofvvIjoqr/mn7vnpajvvIlgID0gIu+8iFN0dWR5IDHjgafjga/oqbLlvZPos6rllY/jgarjgZfvvIkiLAogICAgICBg5Zue562UYCA9ICLoqr/mn7vnpajjgavpgbjmip7ogqLmlbDnorroqo3os6rllY/jgarjgZciLAogICAgICBg5q2j562UYCA9ICLpgannlKjlpJYiLAogICAgICBgTmAgPSAiIgogICAgKQogIH0KICB3cml0ZV9jc3ZfYW5kX3RleCgKICAgIG1hbmlwdWxhdGlvbl90YWJsZSwKICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfbWFuaXB1bGF0aW9uX2NoZWNrLmNzdiIpLAogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9tYW5pcHVsYXRpb25fY2hlY2sudGV4IiksCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrpgbjmip7ogqLmlbDjga7mk43kvZznorroqo0iKSwKICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLW1hbmlwdWxhdGlvbi1jaGVjayIpLAogICAgbm90ZXMgPSAiU3R1ZHkgMuODuzPjgafjga/jgIHlibLjgorlvZPjgabjgonjgozjgZ/pgbjmip7ogqLmlbDjgajlkIzjgZjlm57nrZTjgpLmraPnrZTjgajjgZfjgZ/jgIIiCiAgKQogIAogIGF0dGVudGlvbl90YWJsZSA8LSBzY3JlZW5pbmckYXVkaXQgJT4lCiAgICBkcGx5cjo6Y291bnQoYXR0ZW50aW9uX3Jlc3BvbnNlLCBhdHRlbnRpb25fY2hlY2tfcGFzcywgbmFtZSA9ICJuIikgJT4lCiAgICBkcGx5cjo6dHJhbnNtdXRlKAogICAgICBg6LOq5ZWP5paH77yI6Kq/5p+756Wo77yJYCA9IHNjcmVlbmluZ19xdWVzdGlvbl93b3JkaW5nKHN0dWR5X2lkLCAi5oyH56S66aCF55uuIiksCiAgICAgIGDlm57nrZRgID0gZHBseXI6OmNvYWxlc2NlKGF0dGVudGlvbl9yZXNwb25zZSwgIuacquWun+aWveODu+asoOaQjSIpLAogICAgICBg5Yik5a6aYCA9IGlmZWxzZShhdHRlbnRpb25fY2hlY2tfcGFzcywgIuato+etlCIsICLkuI3mraPnrZTjg7vmrKDmkI0iKSwKICAgICAgYE5gID0gZm9ybWF0X2ludGVnZXIobikKICAgICkKICBpZiAoc3R1ZHlfaWQgPT0gInN0dWR5MSIpIHsKICAgIGF0dGVudGlvbl90YWJsZSA8LSB0aWJibGU6OnRpYmJsZSgKICAgICAgYOizquWVj+aWh++8iOiqv+afu+elqO+8iWAgPSAi77yIU3R1ZHkgMeOBp+OBr+ipsuW9k+izquWVj+OBquOBl++8iSIsCiAgICAgIGDlm57nrZRgID0gIuiqv+afu+elqOOBq+aMh+ekuumgheebruOBquOBlyIsCiAgICAgIGDliKTlrppgID0gIumBqeeUqOWkliIsCiAgICAgIGBOYCA9ICIiCiAgICApCiAgfQogIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgYXR0ZW50aW9uX3RhYmxlLAogICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9hdHRlbnRpb25fY2hlY2suY3N2IiksCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX2F0dGVudGlvbl9jaGVjay50ZXgiKSwKICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muOCpOODh+OCquODreOCruODvOihjOWIl+OBruaMh+ekuumgheebriIpLAogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYXR0ZW50aW9uLWNoZWNrIiksCiAgICBub3RlcyA9ICJTdHVkeSAy44O7M+OBp+OBr+OAgeiqv+afu+eUu+mdouS4iuOBruaMh+ekuumgheebruOBp+OAjDPjgI3jgpLpgbjmip7jgZfjgZ/lm57nrZTogIXjgpLmraPnrZTjgajjgZfjgZ/jgIJRdWFsdHJpY3Pjga7kv53lrZjjgrPjg7zjg4njgYzooajnpLrlgKTjgajnlbDjgarjgovloLTlkIjjga/jgIHmnKzliIbmnpDjgafoh6rli5XmpJzlh7rjgZXjgozjgZ/kv53lrZjjgrPjg7zjg4njgpLnlKjjgYTjgZ/jgIIiCiAgKQogIAogIGFtY2VfY292IDwtIG1ha2VfYW1jZV90YWJsZShlbnYsIGFkanVzdGVkID0gVFJVRSkKICBhbWNlX25vY292IDwtIG1ha2VfYW1jZV90YWJsZShlbnYsIGFkanVzdGVkID0gRkFMU0UpCiAgaW50ZXJhY3Rpb24gPC0gbWFrZV9pbnRlcmFjdGlvbl90YWJsZShlbnYpCiAgbW1fdGFibGUgPC0gbWFrZV9tbV90YWJsZShlbnYpCiAgYXR0cl9pbXBvcnRhbmNlIDwtIG1ha2VfYXR0cmlidXRlX2ltcG9ydGFuY2VfdGFibGUoZW52KQogIGN1ZV9pbXBvcnRhbmNlIDwtIG1ha2VfY3VlX2ltcG9ydGFuY2VfdGFibGUoZW52KQogIGNsb2dpdF90YWJsZSA8LSBtYWtlX2Nsb2dpdF90YWJsZShlbnYpCiAgbGluZWFyX3RyZW5kX3RhYmxlIDwtIG1ha2VfbGluZWFyX3RyZW5kX3RhYmxlKGVudikKICBwYXJ0eV9tYXRjaF90YWJsZSA8LSBtYWtlX3BhcnR5X21hdGNoX3RhYmxlKGVudikKICAKICB3cml0ZV9jc3ZfYW5kX3RleCgKICAgIGFtY2VfY292LAogICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC5jc3YiKSwKICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQudGV4IiksCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiksCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1hbWNlLWFkanVzdGVkIiksCiAgICBub3RlcyA9ICLmjqjlrprlgKTjga7ljZjkvY3jga/jg5Hjg7zjgrvjg7Pjg4jjg53jgqTjg7Pjg4jjgILmqJnmupboqqTlt67jga/lm57nrZTogIXljZjkvY3jgafjgq/jg6njgrnjgr/ljJbjgZfjgZ/jgIIiCiAgKQogIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgYW1jZV9ub2NvdiwKICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfYW1jZV91bmFkanVzdGVkLmNzdiIpLAogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9hbWNlX3VuYWRqdXN0ZWQudGV4IiksCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrlhbHlpInph4/jgpLlkKvjgoHjgarjgYRBTUNFIiksCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1hbWNlLXVuYWRqdXN0ZWQiKSwKICAgIG5vdGVzID0gIuaOqOWumuWApOOBruWNmOS9jeOBr+ODkeODvOOCu+ODs+ODiOODneOCpOODs+ODiOOAguaomea6luiqpOW3ruOBr+WbnuetlOiAheWNmOS9jeOBp+OCr+ODqeOCueOCv+WMluOBl+OBn+OAgiIKICApCiAgd3JpdGVfY3N2X2FuZF90ZXgoCiAgICBpbnRlcmFjdGlvbiwKICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfYW1jZV9pbnRlcmFjdGlvbi5jc3YiKSwKICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfYW1jZV9pbnRlcmFjdGlvbi50ZXgiKSwKICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8mjLpgbjmip7ogqLmnaHku7bjgajjga7lt67jgpLooajjgZlBTUNF5Lqk5LqS5L2c55SoIiksCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1hbWNlLWludGVyYWN0aW9uIiksCiAgICBub3RlcyA9ICLmraPjga7lgKTjga/jgIHlvZPoqbLmnaHku7bjgavjgYrjgZHjgotBTUNF44GMMumBuOaKnuiCouadoeS7tuOCiOOCiuWkp+OBjeOBhOOBk+OBqOOCkuekuuOBmeOAgiIKICApCiAgd3JpdGVfY3N2X2FuZF90ZXgoCiAgICBtbV90YWJsZSwKICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfbWFyZ2luYWxfbWVhbnMuY3N2IiksCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX21hcmdpbmFsX21lYW5zLnRleCIpLAogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5bGe5oCn5rC05rqW5Yil44Gu6ZmQ55WM5bmz5Z2H77yITU3vvIkiKSwKICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLW1hcmdpbmFsLW1lYW5zIiksCiAgICBub3RlcyA9ICLpmZDnlYzlubPlnYfjga/lvZPoqbLmsLTmupbjgpLjgoLjgaTjg5fjg63jg5XjgqHjgqTjg6vjga7lubPlnYfpgbjmip7norrnjofjgIJTReOBqOS/oemgvOWMuumWk+OBr+WbnuetlOiAheOCr+ODqeOCueOCv+OBq+WvvuW/nOOBl+OBn+WIh+eJh+OBruOBv+OBrue3muW9oueiuueOh+ODouODh+ODq+OBqOWQjOWApOOBruioiOeul+OBq+OCiOOCi+OAgiIKICApCiAgd3JpdGVfY3N2X2FuZF90ZXgoCiAgICBhdHRyX2ltcG9ydGFuY2UsCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX2F0dHJpYnV0ZV9pbXBvcnRhbmNlLmNzdiIpLAogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS50ZXgiKSwKICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muWxnuaAp+WIpeOBruacquiqv+aVtOODu+mBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6piIpLAogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYXR0cmlidXRlLWltcG9ydGFuY2UiKSwKICAgIG5vdGVzID0gIuacquiqv+aVtOmHjeimgeW6puOBr+mZkOeVjOW5s+Wdh+OBruWFqOawtOa6luODmuOCouOBrue1tuWvvuW3ruOBruW5s+Wdh+OAguiqv+aVtOa4iOOBv+mHjeimgeW6puOBr+acquiqv+aVtOmHjeimgeW6puOCkjHvvI/pgbjmip7ogqLmlbDjgafpmaTjgZfjgZ/jgIIiCiAgKQogIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgY3VlX2ltcG9ydGFuY2UsCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX2N1ZV9pbXBvcnRhbmNlLmNzdiIpLAogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS50ZXgiKSwKICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIpLAogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItY3VlLWltcG9ydGFuY2UiKSwKICAgIG5vdGVzID0gIjk1JeS/oemgvOWMuumWk+OBr+adoeS7tuWGheOBp+WbnuetlOiAheOCkuW+qeWFg+aKveWHuuOBmeOCi+OCr+ODqeOCueOCv+ODu+ODluODvOODiOOCueODiOODqeODg+ODl+OBq+OCiOOCi+OAgiIKICApCiAgd3JpdGVfY3N2X2FuZF90ZXgoCiAgICBjbG9naXRfdGFibGUsCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LmNzdiIpLAogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9jb25kaXRpb25hbF9sb2dpdC50ZXgiKSwKICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muadoeS7tuS7mOOBjeODreOCuOODg+ODiOaOqOWumiIpLAogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItY29uZGl0aW9uYWwtbG9naXQiKSwKICAgIG5vdGVzID0gIuWQhOmBuOaKnuiqsumhjOOCknN0cmF0dW3jgajjgZnjgotNY0ZhZGRlbuWei+adoeS7tuS7mOOBjeODreOCuOODg+ODiOOAguaomea6luiqpOW3ruOBr+WbnuetlOiAheWNmOS9jeOBp+OCr+ODqeOCueOCv+WMluOBl+OBn+OAgiIKICApCiAgCiAgaWYgKG5yb3cobGluZWFyX3RyZW5kX3RhYmxlKSA+IDApIHsKICAgIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgICBsaW5lYXJfdHJlbmRfdGFibGUsCiAgICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfYW1jZV9saW5lYXJfdHJlbmQuY3N2IiksCiAgICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfYW1jZV9saW5lYXJfdHJlbmQudGV4IiksCiAgICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8mumBuOaKnuiCouaVsOOBq+WvvuOBmeOCi0FNQ0Xjga7nt5rlvaLjg4jjg6zjg7Pjg4kiKSwKICAgICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYW1jZS1saW5lYXItdHJlbmQiKSwKICAgICAgbm90ZXMgPSAi5L+C5pWw44Gv6YG45oqe6IKi5pWw44GMMeOBpOWil+OBiOOBn+OBqOOBjeOBrkFNQ0Xjga7lpInljJbjgpLjg5Hjg7zjgrvjg7Pjg4jjg53jgqTjg7Pjg4jjgafnpLrjgZnjgIIiCiAgICApCiAgfQogIAogIGlmIChucm93KHBhcnR5X21hdGNoX3RhYmxlKSA+IDApIHsKICAgIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgICBwYXJ0eV9tYXRjaF90YWJsZSwKICAgICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9wYXJ0eV9tYXRjaC5jc3YiKSwKICAgICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9wYXJ0eV9tYXRjaC50ZXgiKSwKICAgICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5pSv5oyB5pS/5YWa44Go5o+Q56S65pS/5YWa5ZCN44Gu5LiA6Ie05Yq55p6cIiksCiAgICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLXBhcnR5LW1hdGNoIiksCiAgICAgIG5vdGVzID0gIuS4gOiHtOWKueaenOOBr+OAgeWbnuetlOiAheOBruaUr+aMgeaUv+WFmuOBqOaPkOekuuOBleOCjOOBn+aUv+WFmuWQjeOBjOS4gOiHtOOBmeOCi+OBk+OBqOOBq+OCiOOCi+mBuOaKnueiuueOh+W3ruOAgiIKICAgICkKICB9CiAgCiAgYmFsYW5jZSA8LSBhc3NpZ25tZW50X2JhbGFuY2VfcmVzdWx0c1tbc3R1ZHlfaWRdXQogIGJhbGFuY2Vfc3VtbWFyeSA8LSBiYWxhbmNlJHN1bW1hcnkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gZm9ybWF0X251bWJlcigueCwgMykpKQogIGJhbGFuY2VfcGFpcndpc2UgPC0gYmFsYW5jZSRwYWlyd2lzZV9zbWQgJT4lCiAgICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gZm9ybWF0X251bWJlcigueCwgMykpKQogIAogIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgYmFsYW5jZV9zdW1tYXJ5LAogICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9hc3NpZ25tZW50X2JhbGFuY2Vfc3VtbWFyeS5jc3YiKSwKICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfYXNzaWdubWVudF9iYWxhbmNlX3N1bW1hcnkudGV4IiksCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrmnaHku7bliKXjga7lm57nrZTogIXlsZ7mgKciKSwKICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLWJhbGFuY2Utc3VtbWFyeSIpLAogICAgbm90ZXMgPSAiTG92ZSBwbG9044GK44KI44GzNDXluqbnt5roqLrmlq3jgavlr77lv5zjgZnjgovmnaHku7bliKXpm4boqIjjgIIiCiAgKQogIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgYmFsYW5jZV9wYWlyd2lzZSwKICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfYXNzaWdubWVudF9iYWxhbmNlX3BhaXJ3aXNlX3NtZC5jc3YiKSwKICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfYXNzaWdubWVudF9iYWxhbmNlX3BhaXJ3aXNlX3NtZC50ZXgiKSwKICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muWFqOadoeS7tuODmuOCouOBruaomea6luWMluW5s+Wdh+W3riIpLAogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYmFsYW5jZS1zbWQiKSwKICAgIG5vdGVzID0gIue1tuWvvlNNROOBjDAuMTDmnKrmuoDjgafjgYLjgozjgbDjgIHpgJrluLjjga/lrp/os6rnmoTjgavlsI/jgZXjgYTkuI3lnYfooaHjgajop6Pph4jjgZXjgozjgovjgIIiCiAgKQogIHJlYWRyOjp3cml0ZV9jc3YoYmFsYW5jZSRzdW1tYXJ5LCBmaWxlLnBhdGgoZGlhZ19iYWxhbmNlX2RpciwgImFzc2lnbm1lbnRfYmFsYW5jZV9zdW1tYXJ5LmNzdiIpLCBuYSA9ICIiKQogIHJlYWRyOjp3cml0ZV9jc3YoYmFsYW5jZSRwYWlyd2lzZV9zbWQsIGZpbGUucGF0aChkaWFnX2JhbGFuY2VfZGlyLCAiYXNzaWdubWVudF9iYWxhbmNlX3BhaXJ3aXNlX3NtZC5jc3YiKSwgbmEgPSAiIikKICByZWFkcjo6d3JpdGVfY3N2KGJhbGFuY2UkZGlhZ29uYWxfZGF0YSwgZmlsZS5wYXRoKGRpYWdfYmFsYW5jZV9kaXIsICJhc3NpZ25tZW50X2JhbGFuY2VfZGlhZ29uYWxfZGF0YS5jc3YiKSwgbmEgPSAiIikKICAKICByYW5kb21pemF0aW9uIDwtIHByb2ZpbGVfcmFuZG9taXphdGlvbl9yZXN1bHRzW1tzdHVkeV9pZF1dCiAgcmFuZG9tX3Rlc3RzIDwtIHJhbmRvbWl6YXRpb24kdW5pZm9ybWl0eV90ZXN0cyAlPiUKICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXRfbnVtYmVyKC54LCA0KSkpCiAgcmFuZG9tX2ZyZXF1ZW5jeSA8LSByYW5kb21pemF0aW9uJGZyZXF1ZW5jeSAlPiUKICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXRfbnVtYmVyKC54LCA0KSkpCiAgd3JpdGVfY3N2X2FuZF90ZXgoCiAgICByYW5kb21fdGVzdHMsCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX3Byb2ZpbGVfcmFuZG9taXphdGlvbl90ZXN0cy5jc3YiKSwKICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfcHJvZmlsZV9yYW5kb21pemF0aW9uX3Rlc3RzLnRleCIpLAogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5bGe5oCn5rC05rqW5o+Q56S644Gu5LiA5qeY5oCn5qSc5a6aIiksCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1wcm9maWxlLXJhbmRvbWl6YXRpb24tdGVzdHMiKSwKICAgIG5vdGVzID0gIuWxnuaAp8OX5p2h5Lu244GU44Go44Gu44Kr44Kk5LqM5LmX5qSc5a6a44CCcOWApOOBr0hvbG3ms5XjgafjgoLoo5zmraPjgZfjgZ/jgIIiCiAgKQogIHdyaXRlX2Nzdl9hbmRfdGV4KAogICAgcmFuZG9tX2ZyZXF1ZW5jeSwKICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfcHJvZmlsZV9yYW5kb21pemF0aW9uX2ZyZXF1ZW5jeS5jc3YiKSwKICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfcHJvZmlsZV9yYW5kb21pemF0aW9uX2ZyZXF1ZW5jeS50ZXgiKSwKICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+OBqOioreioiOS4iuOBruacn+W+heavlOeOhyIpLAogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItcHJvZmlsZS1yYW5kb21pemF0aW9uLWZyZXF1ZW5jeSIpLAogICAgbm90ZXMgPSAi5bGe5oCn5o+Q56S644GuNDXluqbnt5rlm7Pjgavlr77lv5zjgZnjgovmlbDlgKTooajjgIIiCiAgKQogIHJlYWRyOjp3cml0ZV9jc3YocmFuZG9taXphdGlvbiR1bmlmb3JtaXR5X3Rlc3RzLCBmaWxlLnBhdGgoZGlhZ19yYW5kb21fZGlyLCAicHJvZmlsZV9yYW5kb21pemF0aW9uX3Rlc3RzLmNzdiIpLCBuYSA9ICIiKQogIHJlYWRyOjp3cml0ZV9jc3YocmFuZG9taXphdGlvbiRmcmVxdWVuY3ksIGZpbGUucGF0aChkaWFnX3JhbmRvbV9kaXIsICJwcm9maWxlX3JhbmRvbWl6YXRpb25fZnJlcXVlbmN5LmNzdiIpLCBuYSA9ICIiKQogIAogIHN1cHBvcnRfYW1jZSA8LSBwYXJ0eV9zdXBwb3J0X2FtY2VfcmVzdWx0c1tbc3R1ZHlfaWRdXQogIGlmICghaXMubnVsbChzdXBwb3J0X2FtY2Ukc3ViZ3JvdXBfY29lZmZpY2llbnRzKSkgewogICAgc3VwcG9ydF9hbWNlX3RhYmxlIDwtIHN1cHBvcnRfYW1jZSRzdWJncm91cF9jb2VmZmljaWVudHMgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXRfbnVtYmVyKC54LCAzKSkpCiAgICB3cml0ZV9jc3ZfYW5kX3RleCgKICAgICAgc3VwcG9ydF9hbWNlX3RhYmxlLAogICAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX3BhcnR5X3N1cHBvcnRfYW1jZS5jc3YiKSwKICAgICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9wYXJ0eV9zdXBwb3J0X2FtY2UudGV4IiksCiAgICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muaUr+aMgeaUv+WFmuWIpUFNQ0UiKSwKICAgICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItcGFydHktc3VwcG9ydC1hbWNlIiksCiAgICAgIG5vdGVzID0gIuaUr+aMgeaUv+WFmuWIpUFNQ0Xlm7Pjgavlr77lv5zjgZnjgovmjqjlrprlgKTjgIIiCiAgICApCiAgfQogIHN1cHBvcnRfcmVsYXRpdmUgPC0gcGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfcmVzdWx0c1tbc3R1ZHlfaWRdXQogIGlmICghaXMubnVsbChzdXBwb3J0X3JlbGF0aXZlJGludGVydmFscykpIHsKICAgIHN1cHBvcnRfcmVsYXRpdmVfdGFibGUgPC0gc3VwcG9ydF9yZWxhdGl2ZSRpbnRlcnZhbHMgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXRfbnVtYmVyKC54LCAzKSkpCiAgICB3cml0ZV9jc3ZfYW5kX3RleCgKICAgICAgc3VwcG9ydF9yZWxhdGl2ZV90YWJsZSwKICAgICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9wYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZS5jc3YiKSwKICAgICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9wYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZS50ZXgiKSwKICAgICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5pSv5oyB5pS/5YWa5Yil44Gu5omL44GM44GL44KK6YeN6KaB5bqm44Go55u45a++5q+U6YeNIiksCiAgICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLXBhcnR5LXN1cHBvcnQtcmVsYXRpdmUiKSwKICAgICAgbm90ZXMgPSAi5pSv5oyB5pS/5YWa5Yil44Gu55u45a++5q+U6YeN5Zuz44Gr5a++5b+c44GZ44KL5Zue562U6ICF44Kv44Op44K544K/44O744OW44O844OI44K544OI44Op44OD44OX5o6o5a6a44CCIgogICAgKQogIH0KICAKICBzdHVkeV90YWJsZV9wYXRoc1tbc3R1ZHlfaWRdXSA8LSBsaXN0KGNzdl9kaXIgPSBjc3ZfZGlyLCB0ZXhfZGlyID0gdGV4X2RpcikKfQoKCmNyb3NzX2Nzdl9kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9jcm9zcywgInRhYmxlc19jc3YiKQpjcm9zc190ZXhfZGlyIDwtIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfY3Jvc3MsICJ0YWJsZXNfdGV4IikKCmNyb3NzX3RhYmxlcyA8LSBsaXN0KAogIGh5cG90aGVzaXMgPSBoeXBvdGhlc2lzX3Rlc3Rfc3VtbWFyeSwKICBhZGp1c3RlZF9zbG9wZXMgPSBjaG9pY2Vfc2V0X2FkanVzdGVkX3Nsb3BlX3N1bW1hcnksCiAgY3Jvc3NfcmVsYXRpdmUgPSBjcm9zc19zdHVkeV9yZWxhdGl2ZV93ZWlnaHQsCiAgYWxsX3BhcnR5X21hdGNoX2NvZWZmaWNpZW50cyA9IHN0dWR5M19hbGxfcGFydHlfbWF0Y2hfcmVzdWx0cyRjb2VmZmljaWVudHMsCiAgYWxsX3BhcnR5X21hdGNoX3RyZW5kcyA9IHN0dWR5M19hbGxfcGFydHlfbWF0Y2hfcmVzdWx0cyR0cmVuZHMKKQoKY3Jvc3NfY2FwdGlvbiA8LSBjKAogIGh5cG90aGVzaXMgPSAiM+Wun+mok+OBruS4u+imgeS7ruiqrOOBq+WvvuW/nOOBmeOCi+e3muW9ouWCvuWQkeaknOWumiIsCiAgYWRqdXN0ZWRfc2xvcGVzID0gIjPlrp/pqJPjga7pgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbjga7nt5rlvaLlgr7lkJEiLAogIGNyb3NzX3JlbGF0aXZlID0gIjPlrp/pqJPmqKrmlq3jga7mlL/lhZrmiYvjgYzjgYvjgornm7jlr77mr5Tph40iLAogIGFsbF9wYXJ0eV9tYXRjaF9jb2VmZmljaWVudHMgPSAiU3R1ZHkgM++8muOBmeOBueOBpuOBruWvvuixoeaUr+aMgeaUv+WFmuOBq+OBiuOBkeOCi+S4gOiHtOWKueaenCIsCiAgYWxsX3BhcnR5X21hdGNoX3RyZW5kcyA9ICJTdHVkeSAz77ya5LiA6Ie05Yq55p6c44Gu6YG45oqe6IKi5pWw44OI44Os44Oz44OJIgopCgpmb3IgKHRhYmxlX25hbWUgaW4gbmFtZXMoY3Jvc3NfdGFibGVzKSkgewogIHRhYmxlX2RhdGEgPC0gY3Jvc3NfdGFibGVzW1t0YWJsZV9uYW1lXV0KICBpZiAoaXMubnVsbCh0YWJsZV9kYXRhKSkgbmV4dAogIHRhYmxlX2RhdGEgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZV9kYXRhKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXRfbnVtYmVyKC54LCA0KSkpCiAgd3JpdGVfY3N2X2FuZF90ZXgoCiAgICB0YWJsZV9kYXRhLAogICAgZmlsZS5wYXRoKGNyb3NzX2Nzdl9kaXIsIHBhc3RlMCgidGFibGVfIiwgdGFibGVfbmFtZSwgIi5jc3YiKSksCiAgICBmaWxlLnBhdGgoY3Jvc3NfdGV4X2RpciwgcGFzdGUwKCJ0YWJsZV8iLCB0YWJsZV9uYW1lLCAiLnRleCIpKSwKICAgIHVubmFtZShjcm9zc19jYXB0aW9uW3RhYmxlX25hbWVdKSwKICAgIHBhc3RlMCgidGFiOmNyb3NzLSIsIGdzdWIoIl8iLCAiLSIsIHRhYmxlX25hbWUpKSwKICAgIG5vdGVzID0gIuWvvuW/nOOBmeOCi+ijnOmBuuWbs+OBruaVsOWApOOCkuihqOW9ouW8j+OBp+WGjeaOsuOBl+OBn+OAgiIKICApCn0KCgpmb3IgKHN0dWR5X2lkIGluIG5hbWVzKHN0dWR5X3NwZWNzKSkgewogIHdvcmtpbmdfZGlyIDwtIHVuaWZpZWRfY29uZmlnW1tzdHVkeV9pZF1dJG91dHB1dF9kaXIKICBzdXBwbGVtZW50X2ZpZ19kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCBzdHVkeV9pZCwgImZpZ3VyZXMiKQogIGNvcHlfZmlsZXNfYnlfcGF0dGVybih3b3JraW5nX2Rpciwgc3VwcGxlbWVudF9maWdfZGlyLCAiXFwuKHBuZ3xwZGYpJCIpCiAgY29weV9maWxlc19ieV9wYXR0ZXJuKAogICAgd29ya2luZ19kaXIsCiAgICBmaWxlLnBhdGgoZmluYWxfZGlycyRtb2RlbF9vYmplY3RzX3Jvb3QsIHN0dWR5X2lkKSwKICAgICJcXC4ocmRzfFJEUykkIgogICkKICBjb3B5X2ZpbGVzX2J5X3BhdHRlcm4od29ya2luZ19kaXIsIGZpbmFsX2RpcnMkbG9ncywgIihzZXNzaW9uSW5mb3xcXC50eHQkKSIpCiAgCiAgc3VwcG9ydF9kaXIgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKHN0dWR5X2lkLCAiX3BhcnR5X3N1cHBvcnQiKSkKICBjb3B5X2ZpbGVzX2J5X3BhdHRlcm4oc3VwcG9ydF9kaXIsIHN1cHBsZW1lbnRfZmlnX2RpciwgIlxcLihwbmd8cGRmKSQiKQp9Cgpjb3B5X2ZpbGVzX2J5X3BhdHRlcm4oCiAgdW5pZmllZF9vdXRwdXRfZGlyLAogIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfY3Jvc3MsICJmaWd1cmVzIiksCiAgIlxcLihwbmd8cGRmKSQiCikKY29weV9maWxlc19ieV9wYXR0ZXJuKHVuaWZpZWRfb3V0cHV0X2RpciwgZmluYWxfZGlycyRsb2dzLCAiKHNlc3Npb25JbmZvfFxcLnR4dCQpIikKY29weV9maWxlc19ieV9wYXR0ZXJuKAogIHVuaWZpZWRfb3V0cHV0X2RpciwKICBmaWxlLnBhdGgoZmluYWxfZGlycyRtb2RlbF9vYmplY3RzX3Jvb3QsICJjcm9zc19zdHVkeSIpLAogICJcXC4ocmRzfFJEUykkIgopCgpmb3IgKHN0dWR5X2lkIGluIG5hbWVzKHN0dWR5X3NwZWNzKSkgewogIGZvciAoa2luZCBpbiBjKCJhc3NpZ25tZW50X2JhbGFuY2VfbG92ZV9wbG90IiwgImFzc2lnbm1lbnRfYmFsYW5jZV9kaWFnb25hbF9wbG90IikpIHsKICAgIGZvciAoZXh0ZW5zaW9uIGluIGMoInBuZyIsICJwZGYiKSkgewogICAgICBzb3VyY2UgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKHN0dWR5X2lkLCAiXyIsIGtpbmQsICIuIiwgZXh0ZW5zaW9uKSkKICAgICAgZGVzdGluYXRpb24gPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkZGlhZ25vc3RpY3Nfcm9vdCwgc3R1ZHlfaWQsICJiYWxhbmNlIiwgYmFzZW5hbWUoc291cmNlKSkKICAgICAgY29weV9maWxlX2lmX2V4aXN0cyhzb3VyY2UsIGRlc3RpbmF0aW9uKQogICAgfQogIH0KICBmb3IgKGV4dGVuc2lvbiBpbiBjKCJwbmciLCAicGRmIikpIHsKICAgIHNvdXJjZSA8LSBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCBwYXN0ZTAoc3R1ZHlfaWQsICJfcHJvZmlsZV9yYW5kb21pemF0aW9uX2RpYWdvbmFsX3Bsb3QuIiwgZXh0ZW5zaW9uKSkKICAgIGRlc3RpbmF0aW9uIDwtIGZpbGUucGF0aChmaW5hbF9kaXJzJGRpYWdub3N0aWNzX3Jvb3QsIHN0dWR5X2lkLCAicmFuZG9taXphdGlvbiIsIGJhc2VuYW1lKHNvdXJjZSkpCiAgICBjb3B5X2ZpbGVfaWZfZXhpc3RzKHNvdXJjZSwgZGVzdGluYXRpb24pCiAgfQp9CgppZiAoZXhpc3RzKCJtYWluX3RleHRfZmlndXJlX21hbmlmZXN0IikpIHsKICBwdXJycjo6cHdhbGsoCiAgICBtYWluX3RleHRfZmlndXJlX21hbmlmZXN0LAogICAgZnVuY3Rpb24oZmlndXJlX251bWJlciwgc3R1ZHksIGFuYWx5c2lzLCBmaWxlX3BuZywgZmlsZV9wZGYpIHsKICAgICAgcHJlZml4IDwtIGdzdWIoIlteQS1aYS16MC05XSsiLCAiXyIsIGZpZ3VyZV9udW1iZXIpCiAgICAgIGlmICghaXMubmEoZmlsZV9wbmcpKSB7CiAgICAgICAgY29weV9maWxlX2lmX2V4aXN0cygKICAgICAgICAgIGZpbGVfcG5nLAogICAgICAgICAgZmlsZS5wYXRoKGZpbmFsX2RpcnMkbWFpbl9maWd1cmVzLCBwYXN0ZTAocHJlZml4LCAiXyIsIGJhc2VuYW1lKGZpbGVfcG5nKSkpCiAgICAgICAgKQogICAgICB9CiAgICAgIGlmICghaXMubmEoZmlsZV9wZGYpKSB7CiAgICAgICAgY29weV9maWxlX2lmX2V4aXN0cygKICAgICAgICAgIGZpbGVfcGRmLAogICAgICAgICAgZmlsZS5wYXRoKGZpbmFsX2RpcnMkbWFpbl9maWd1cmVzLCBwYXN0ZTAocHJlZml4LCAiXyIsIGJhc2VuYW1lKGZpbGVfcGRmKSkpCiAgICAgICAgKQogICAgICB9CiAgICB9CiAgKQp9CgptYWluX3RhYmxlX21hcCA8LSBsaXN0KAogIHN0dWR5MSA9IGMoInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLnRleCIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS50ZXgiKSwKICBzdHVkeTIgPSBjKCJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC50ZXgiLCAidGFibGVfY3VlX2ltcG9ydGFuY2UudGV4IiksCiAgc3R1ZHkzID0gYygidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQudGV4IiwgInRhYmxlX2N1ZV9pbXBvcnRhbmNlLnRleCIsICJ0YWJsZV9wYXJ0eV9tYXRjaC50ZXgiKQopCmZvciAoc3R1ZHlfaWQgaW4gbmFtZXMobWFpbl90YWJsZV9tYXApKSB7CiAgZm9yICh0YWJsZV9maWxlIGluIG1haW5fdGFibGVfbWFwW1tzdHVkeV9pZF1dKSB7CiAgICBzb3VyY2UgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCBzdHVkeV9pZCwgInRhYmxlc190ZXgiLCB0YWJsZV9maWxlKQogICAgY29weV9maWxlX2lmX2V4aXN0cygKICAgICAgc291cmNlLAogICAgICBmaWxlLnBhdGgoZmluYWxfZGlycyRtYWluX3RhYmxlcywgcGFzdGUwKHN0dWR5X2lkLCAiXyIsIHRhYmxlX2ZpbGUpKQogICAgKQogIH0KfQoKCnBhaXJfbWFuaWZlc3QgPC0gdGliYmxlOjp0cmliYmxlKAogIH5zdHVkeV9pZCwgfnNlY3Rpb25fdGl0bGUsIH5maWd1cmVfZmlsZSwgfnRhYmxlX2ZpbGVzLAogICJzdHVkeTEiLCAi5YWx5aSJ6YeP6Kq/5pW05riI44G/QU1DRSIsICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciLCAidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQudGV4IiwKICAic3R1ZHkxIiwgIkFNQ0Xjg5Ljg7zjg4jjg57jg4Pjg5ciLCAiYW1jZV9oZWF0bWFwX21peGVkX3JhbmtfY29sb3JlZF9sYWJlbHMucG5nIiwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLnRleCIsCiAgInN0dWR5MSIsICLlhbHlpInph4/jgpLlkKvjgoHjgarjgYRBTUNFIiwgImFtY2VfZmFjZXRfbm9jb3YucG5nIiwgInRhYmxlX2FtY2VfdW5hZGp1c3RlZC50ZXgiLAogICJzdHVkeTEiLCAiQU1DReOBruadoeS7tuW3riIsICJhbWNlX2ludGVyYWN0aW9uX2RpZmZlcmVuY2VfZnJvbV8ycGFydHkucG5nIiwgInRhYmxlX2FtY2VfaW50ZXJhY3Rpb24udGV4IiwKICAic3R1ZHkxIiwgIuadoeS7tuS7mOOBjeODreOCuOODg+ODiCIsICJjbG9naXRfb2Rkc3JhdGlvX25vY292LnBuZyIsICJ0YWJsZV9jb25kaXRpb25hbF9sb2dpdC50ZXgiLAogICJzdHVkeTEiLCAi5omL44GM44GL44KK6YeN6KaB5bqm44Go55u45a++5q+U6YeNIiwgImZpZ19zdHVkeTFfcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkX2pwX2J3LnBuZyIsICJ0YWJsZV9tYXJnaW5hbF9tZWFucy50ZXg7dGFibGVfYXR0cmlidXRlX2ltcG9ydGFuY2UudGV4O3RhYmxlX2N1ZV9pbXBvcnRhbmNlLnRleCIsCiAgInN0dWR5MiIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwgImFtY2VfY292X2ZhY2V0X21vZGVsLnBuZyIsICJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC50ZXgiLAogICJzdHVkeTIiLCAiQU1DReODkuODvOODiOODnuODg+ODlyIsICJhbWNlX2hlYXRtYXBfbWl4ZWRfcmFua19jb2xvcmVkX2xhYmVscy5wbmciLCAidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQudGV4IiwKICAic3R1ZHkyIiwgIuWFseWkiemHj+OCkuWQq+OCgeOBquOBhEFNQ0UiLCAiYW1jZV9mYWNldF9ub2Nvdi5wbmciLCAidGFibGVfYW1jZV91bmFkanVzdGVkLnRleCIsCiAgInN0dWR5MiIsICJBTUNF44Gu5p2h5Lu25beuIiwgImFtY2VfaW50ZXJhY3Rpb25fZGlmZmVyZW5jZV9mcm9tXzJwYXJ0eS5wbmciLCAidGFibGVfYW1jZV9pbnRlcmFjdGlvbi50ZXgiLAogICJzdHVkeTIiLCAi5p2h5Lu25LuY44GN44Ot44K444OD44OIIiwgImNsb2dpdF9vZGRzcmF0aW9fbm9jb3YucG5nIiwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LnRleCIsCiAgInN0dWR5MiIsICLmiYvjgYzjgYvjgorph43opoHluqbjgajnm7jlr77mr5Tph40iLCAiZmlnX3N0dWR5Ml9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYncucG5nIiwgInRhYmxlX21hcmdpbmFsX21lYW5zLnRleDt0YWJsZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS50ZXg7dGFibGVfY3VlX2ltcG9ydGFuY2UudGV4IiwKICAic3R1ZHkzIiwgIuWFseWkiemHj+iqv+aVtOa4iOOBv0FNQ0UiLCAiYW1jZV9jb3ZfZmFjZXRfbW9kZWwucG5nIiwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLnRleCIsCiAgInN0dWR5MyIsICLlhbHlpInph4/jgpLlkKvjgoHjgarjgYRBTUNFIiwgImFtY2Vfbm9jb3ZfZmFjZXRfbW9kZWwucG5nIiwgInRhYmxlX2FtY2VfdW5hZGp1c3RlZC50ZXgiLAogICJzdHVkeTMiLCAiQU1DReOBruadoeS7tuW3riIsICJhbWNlX2ludGVyYWN0aW9uX2RpZmZlcmVuY2VfZnJvbV8yY2hvaWNlLnBuZyIsICJ0YWJsZV9hbWNlX2ludGVyYWN0aW9uLnRleCIsCiAgInN0dWR5MyIsICJBTUNF44Gu57ea5b2i44OI44Os44Oz44OJIiwgImFtY2VfbGluZWFyX3RyZW5kLnBuZyIsICJ0YWJsZV9hbWNlX2xpbmVhcl90cmVuZC50ZXgiLAogICJzdHVkeTMiLCAiQU1DReODkuODvOODiOODnuODg+ODlyIsICJhbWNlX2Nvdl9oZWF0bWFwLnBuZyIsICJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC50ZXgiLAogICJzdHVkeTMiLCAi5p2h5Lu25LuY44GN44Ot44K444OD44OIIiwgImNsb2dpdF9vZGRzcmF0aW9fbm9jb3YucG5nIiwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LnRleCIsCiAgInN0dWR5MyIsICLmlK/mjIHmlL/lhZrjgajmj5DnpLrmlL/lhZrlkI3jga7kuIDoh7TlirnmnpwiLCAicGFydHlfbWF0Y2hfZWZmZWN0X2NvbWJpbmVkLnBuZyIsICJ0YWJsZV9wYXJ0eV9tYXRjaC50ZXgiLAogICJzdHVkeTMiLCAi5omL44GM44GL44KK6YeN6KaB5bqm44Go55u45a++5q+U6YeNIiwgImZpZ19zdHVkeTNfcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkX2pwX2J3LnBuZyIsICJ0YWJsZV9tYXJnaW5hbF9tZWFucy50ZXg7dGFibGVfYXR0cmlidXRlX2ltcG9ydGFuY2UudGV4O3RhYmxlX2N1ZV9pbXBvcnRhbmNlLnRleCIKKQoKZm9yIChzdHVkeV9pZCBpbiBuYW1lcyhzdHVkeV9zcGVjcykpIHsKICBzdXBwb3J0X2ZpZ3VyZXMgPC0gbGlzdC5maWxlcygKICAgIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgc3R1ZHlfaWQsICJmaWd1cmVzIiksCiAgICBwYXR0ZXJuID0gInBhcnR5X3N1cHBvcnRfYW1jZV8uKlxcLnBuZyQiLAogICAgZnVsbC5uYW1lcyA9IEZBTFNFCiAgKQogIGlmIChsZW5ndGgoc3VwcG9ydF9maWd1cmVzKSA+IDApIHsKICAgIHBhaXJfbWFuaWZlc3QgPC0gZHBseXI6OmJpbmRfcm93cygKICAgICAgcGFpcl9tYW5pZmVzdCwKICAgICAgdGliYmxlOjp0aWJibGUoCiAgICAgICAgc3R1ZHlfaWQgPSBzdHVkeV9pZCwKICAgICAgICBzZWN0aW9uX3RpdGxlID0gcGFzdGUwKCLmlK/mjIHmlL/lhZrliKVBTUNF77yaIiwgc3VwcG9ydF9maWd1cmVzKSwKICAgICAgICBmaWd1cmVfZmlsZSA9IHN1cHBvcnRfZmlndXJlcywKICAgICAgICB0YWJsZV9maWxlcyA9ICJ0YWJsZV9wYXJ0eV9zdXBwb3J0X2FtY2UudGV4IgogICAgICApCiAgICApCiAgfQogIGlmIChmaWxlLmV4aXN0cyhmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X3Jvb3QsIHN0dWR5X2lkLCAiZmlndXJlcyIsICJwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV93ZWlnaHQucG5nIikpKSB7CiAgICBwYWlyX21hbmlmZXN0IDwtIGRwbHlyOjpiaW5kX3Jvd3MoCiAgICAgIHBhaXJfbWFuaWZlc3QsCiAgICAgIHRpYmJsZTo6dGliYmxlKAogICAgICAgIHN0dWR5X2lkID0gc3R1ZHlfaWQsCiAgICAgICAgc2VjdGlvbl90aXRsZSA9ICLmlK/mjIHmlL/lhZrliKXjga7miYvjgYzjgYvjgornm7jlr77mr5Tph40iLAogICAgICAgIGZpZ3VyZV9maWxlID0gInBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX3dlaWdodC5wbmciLAogICAgICAgIHRhYmxlX2ZpbGVzID0gInRhYmxlX3BhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlLnRleCIKICAgICAgKQogICAgKQogIH0KfQoKcmVhZHI6OndyaXRlX2NzdigKICBwYWlyX21hbmlmZXN0LAogIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgImZpZ3VyZV90YWJsZV9wYWlyX21hbmlmZXN0LmNzdiIpLAogIG5hID0gIiIKKQoKcGFpcl90ZXhfbGluZXMgPC0gYygKICAiJSBHZW5lcmF0ZWQgYXV0b21hdGljYWxseS4gUnVuIEx1YUxhVGVYIGZyb20gdGhlIHN1cHBsZW1lbnQgZGlyZWN0b3J5LiIsCiAgIlxccHJvdmlkZWNvbW1hbmR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290fXsufSIsCiAgIlxcc2VjdGlvbnvmqJnmnKzmp4vnr4njg7vjg4fjg7zjgr/lk4Hos6rjg7vliIbmnpDntZDmnpx9IgopCgpmb3IgKHN0dWR5X2lkIGluIG5hbWVzKHN0dWR5X3NwZWNzKSkgewogIHN0dWR5X2xhYmVsIDwtIHN0dWR5X3NwZWNzW1tzdHVkeV9pZF1dJHN0dWR5X2xhYmVsCiAgcGFpcl90ZXhfbGluZXMgPC0gYygKICAgIHBhaXJfdGV4X2xpbmVzLAogICAgcGFzdGUwKCJcXHNlY3Rpb257IiwgbGF0ZXhfZXNjYXBlKHN0dWR5X2xhYmVsKSwgIn0iKSwKICAgICJcXHN1YnNlY3Rpb2575qiZ5pys5qeL56+J44Go44K544Kv44Oq44O844OL44Oz44KwfSIsCiAgICBwYXN0ZTAoIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIHN0dWR5X2lkLCAiL3RhYmxlc190ZXgvdGFibGVfc2FtcGxlX2F0dHJpdGlvbi50ZXh9IiksCiAgICBwYXN0ZTAoIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIHN0dWR5X2lkLCAiL3RhYmxlc190ZXgvdGFibGVfc2FtcGxlX2F0dHJpdGlvbl9ieV9jb25kaXRpb24udGV4fSIpLAogICAgcGFzdGUwKCJcXGlucHV0e1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC8iLCBzdHVkeV9pZCwgIi90YWJsZXNfdGV4L3RhYmxlX21hbmlwdWxhdGlvbl9jaGVjay50ZXh9IiksCiAgICBwYXN0ZTAoIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIHN0dWR5X2lkLCAiL3RhYmxlc190ZXgvdGFibGVfYXR0ZW50aW9uX2NoZWNrLnRleH0iKSwKICAgICJcXGNsZWFycGFnZSIsCiAgICAiXFxzdWJzZWN0aW9ue+WbnuetlOiAheWJsuS7mOOBruODkOODqeODs+OCuX0iLAogICAgIlxcYmVnaW57ZmlndXJlfVtwXSIsCiAgICAiXFxjZW50ZXJpbmciLAogICAgcGFzdGUwKAogICAgICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvLi4vZGlhZ25vc3RpY3MvIiwKICAgICAgc3R1ZHlfaWQsCiAgICAgICIvYmFsYW5jZS8iLAogICAgICBzdHVkeV9pZCwKICAgICAgIl9hc3NpZ25tZW50X2JhbGFuY2VfbG92ZV9wbG90LnBuZ30iCiAgICApLAogICAgcGFzdGUwKCJcXGNhcHRpb257IiwgbGF0ZXhfZXNjYXBlKHN0dWR5X2xhYmVsKSwgIu+8muWbnuetlOiAheWJsuS7mOOBrkxvdmUgcGxvdH0iKSwKICAgICJcXGVuZHtmaWd1cmV9IiwKICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgc3R1ZHlfaWQsICIvdGFibGVzX3RleC90YWJsZV9hc3NpZ25tZW50X2JhbGFuY2VfcGFpcndpc2Vfc21kLnRleH0iKSwKICAgICJcXGJlZ2lue2ZpZ3VyZX1bcF0iLAogICAgIlxcY2VudGVyaW5nIiwKICAgIHBhc3RlMCgKICAgICAgIlxcaW5jbHVkZWdyYXBoaWNzW3dpZHRoPTAuOTJcXGxpbmV3aWR0aF17XFxDb25qb2ludFN1cHBsZW1lbnRSb290Ly4uL2RpYWdub3N0aWNzLyIsCiAgICAgIHN0dWR5X2lkLAogICAgICAiL2JhbGFuY2UvIiwKICAgICAgc3R1ZHlfaWQsCiAgICAgICJfYXNzaWdubWVudF9iYWxhbmNlX2RpYWdvbmFsX3Bsb3QucG5nfSIKICAgICksCiAgICBwYXN0ZTAoIlxcY2FwdGlvbnsiLCBsYXRleF9lc2NhcGUoc3R1ZHlfbGFiZWwpLCAi77ya5p2h5Lu25Yil5YWx5aSJ6YeP5bmz5Z2H44GuNDXluqbnt5roqLrmlq19IiksCiAgICAiXFxlbmR7ZmlndXJlfSIsCiAgICBwYXN0ZTAoIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIHN0dWR5X2lkLCAiL3RhYmxlc190ZXgvdGFibGVfYXNzaWdubWVudF9iYWxhbmNlX3N1bW1hcnkudGV4fSIpLAogICAgIlxcY2xlYXJwYWdlIiwKICAgICJcXHN1YnNlY3Rpb25744Kz44Oz44K444On44Kk44Oz44OI5bGe5oCn5o+Q56S644Gu54Sh5L2c54K65YyW6Ki65patfSIsCiAgICAiXFxiZWdpbntmaWd1cmV9W3BdIiwKICAgICJcXGNlbnRlcmluZyIsCiAgICBwYXN0ZTAoCiAgICAgICJcXGluY2x1ZGVncmFwaGljc1t3aWR0aD0wLjkyXFxsaW5ld2lkdGhde1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC8uLi9kaWFnbm9zdGljcy8iLAogICAgICBzdHVkeV9pZCwKICAgICAgIi9yYW5kb21pemF0aW9uLyIsCiAgICAgIHN0dWR5X2lkLAogICAgICAiX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9kaWFnb25hbF9wbG90LnBuZ30iCiAgICApLAogICAgcGFzdGUwKCJcXGNhcHRpb257IiwgbGF0ZXhfZXNjYXBlKHN0dWR5X2xhYmVsKSwgIu+8muWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+OBqOacn+W+heavlOeOh30iKSwKICAgICJcXGVuZHtmaWd1cmV9IiwKICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgc3R1ZHlfaWQsICIvdGFibGVzX3RleC90YWJsZV9wcm9maWxlX3JhbmRvbWl6YXRpb25fdGVzdHMudGV4fSIpLAogICAgcGFzdGUwKCJcXGlucHV0e1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC8iLCBzdHVkeV9pZCwgIi90YWJsZXNfdGV4L3RhYmxlX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9mcmVxdWVuY3kudGV4fSIpLAogICAgIlxcY2xlYXJwYWdlIiwKICAgICJcXHN1YnNlY3Rpb2575o6o5a6a57WQ5p6c77ya5Zuz44Go5a++5b+c44GZ44KL6KGofSIKICApCiAgCiAgc3R1ZHlfcGFpcnMgPC0gcGFpcl9tYW5pZmVzdCAlPiUgZHBseXI6OmZpbHRlciguZGF0YSRzdHVkeV9pZCA9PSBzdHVkeV9pZCkKICBmb3IgKGkgaW4gc2VxX2xlbihucm93KHN0dWR5X3BhaXJzKSkpIHsKICAgIHJvdyA8LSBzdHVkeV9wYWlyc1tpLCBdCiAgICBmaWd1cmVfcGF0aCA8LSBmaWxlLnBhdGgocm93JHN0dWR5X2lkLCAiZmlndXJlcyIsIHJvdyRmaWd1cmVfZmlsZSkKICAgIHRhYmxlcyA8LSB1bmxpc3Qoc3Ryc3BsaXQocm93JHRhYmxlX2ZpbGVzLCAiOyIsIGZpeGVkID0gVFJVRSkpCiAgICBwYWlyX3RleF9saW5lcyA8LSBjKAogICAgICBwYWlyX3RleF9saW5lcywKICAgICAgcGFzdGUwKCJcXHN1YnN1YnNlY3Rpb257IiwgbGF0ZXhfZXNjYXBlKHJvdyRzZWN0aW9uX3RpdGxlKSwgIn0iKSwKICAgICAgIlxcYmVnaW57ZmlndXJlfVtwXSIsCiAgICAgICJcXGNlbnRlcmluZyIsCiAgICAgIHBhc3RlMCgiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45NlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgZ3N1YigiXFxcXCIsICIvIiwgZmlndXJlX3BhdGgpLCAifSIpLAogICAgICBwYXN0ZTAoIlxcY2FwdGlvbnsiLCBsYXRleF9lc2NhcGUocm93JHNlY3Rpb25fdGl0bGUpLCAifSIpLAogICAgICAiXFxlbmR7ZmlndXJlfSIKICAgICkKICAgIGZvciAodGFibGVfZmlsZSBpbiB0YWJsZXMpIHsKICAgICAgdGFibGVfcGF0aCA8LSBmaWxlLnBhdGgocm93JHN0dWR5X2lkLCAidGFibGVzX3RleCIsIHRhYmxlX2ZpbGUpCiAgICAgIGlmIChmaWxlLmV4aXN0cyhmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X3Jvb3QsIHRhYmxlX3BhdGgpKSkgewogICAgICAgIHBhaXJfdGV4X2xpbmVzIDwtIGMoCiAgICAgICAgICBwYWlyX3RleF9saW5lcywKICAgICAgICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgZ3N1YigiXFxcXCIsICIvIiwgdGFibGVfcGF0aCksICJ9IikKICAgICAgICApCiAgICAgIH0KICAgIH0KICAgIHBhaXJfdGV4X2xpbmVzIDwtIGMocGFpcl90ZXhfbGluZXMsICJcXGNsZWFycGFnZSIpCiAgfQp9CgpwYWlyX3RleF9saW5lcyA8LSBjKAogIHBhaXJfdGV4X2xpbmVzLAogICJcXHNlY3Rpb257M+Wun+mok+aoquaWreOBruWIhuaekH0iLAogICJcXHN1YnNlY3Rpb2575Li76KaB5Luu6Kqs44Gu57ea5b2i5YK+5ZCR5qSc5a6afSIsCiAgIlxcYmVnaW57ZmlndXJlfVtwXSIsCiAgIlxcY2VudGVyaW5nIiwKICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvY3Jvc3Nfc3R1ZHkvZmlndXJlcy9maWdfc3VwcF9oeXBvdGhlc2lzX2xpbmVhcl90cmVuZF90ZXN0cy5wbmd9IiwKICAiXFxjYXB0aW9uezPlrp/pqJPjga7kuLvopoHku67oqqzjgavlr77lv5zjgZnjgovnt5rlvaLlgr7lkJHmpJzlrpp9IiwKICAiXFxlbmR7ZmlndXJlfSIsCiAgIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290L2Nyb3NzX3N0dWR5L3RhYmxlc190ZXgvdGFibGVfaHlwb3RoZXNpcy50ZXh9IiwKICAiXFxjbGVhcnBhZ2UiLAogICJcXHN1YnNlY3Rpb2576YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqm44Gu57ea5b2i5YK+5ZCRfSIsCiAgIlxcYmVnaW57ZmlndXJlfVtwXSIsCiAgIlxcY2VudGVyaW5nIiwKICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvY3Jvc3Nfc3R1ZHkvZmlndXJlcy9maWdfc3VwcF9jaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2Vfc2xvcGVzLnBuZ30iLAogICJcXGNhcHRpb257M+Wun+mok+OBrumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOBrue3muW9ouWCvuWQkX0iLAogICJcXGVuZHtmaWd1cmV9IiwKICAiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvY3Jvc3Nfc3R1ZHkvdGFibGVzX3RleC90YWJsZV9hZGp1c3RlZF9zbG9wZXMudGV4fSIsCiAgIlxcY2xlYXJwYWdlIiwKICAiXFxzdWJzZWN0aW9uezPlrp/pqJPmqKrmlq3jga7mlL/lhZrmiYvjgYzjgYvjgornm7jlr77mr5Tph419IiwKICAiXFxiZWdpbntmaWd1cmV9W3BdIiwKICAiXFxjZW50ZXJpbmciLAogICJcXGluY2x1ZGVncmFwaGljc1t3aWR0aD0wLjkyXFxsaW5ld2lkdGhde1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC9jcm9zc19zdHVkeS9maWd1cmVzL2ZpZ19zdXBwX2Nyb3NzX3N0dWR5X3JlbGF0aXZlX3BhcnR5X3dlaWdodC5wbmd9IiwKICAiXFxjYXB0aW9uezPlrp/pqJPmqKrmlq3jga7mlL/lhZrmiYvjgYzjgYvjgornm7jlr77mr5Tph419IiwKICAiXFxlbmR7ZmlndXJlfSIsCiAgIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290L2Nyb3NzX3N0dWR5L3RhYmxlc190ZXgvdGFibGVfY3Jvc3NfcmVsYXRpdmUudGV4fSIsCiAgIlxcY2xlYXJwYWdlIgopCgppZiAoZmlsZS5leGlzdHMoZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9jcm9zcywgImZpZ3VyZXMiLCAicGFydHlfbWF0Y2hfYWxsX3BhcnRpZXMucG5nIikpKSB7CiAgcGFpcl90ZXhfbGluZXMgPC0gYygKICAgIHBhaXJfdGV4X2xpbmVzLAogICAgIlxcc3Vic2VjdGlvbntTdHVkeSAz77ya44GZ44G544Gm44Gu5a++6LGh5pSv5oyB5pS/5YWa44Gr44GK44GR44KL5LiA6Ie05Yq55p6cfSIsCiAgICAiXFxiZWdpbntmaWd1cmV9W3BdIiwKICAgICJcXGNlbnRlcmluZyIsCiAgICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvY3Jvc3Nfc3R1ZHkvZmlndXJlcy9wYXJ0eV9tYXRjaF9hbGxfcGFydGllcy5wbmd9IiwKICAgICJcXGNhcHRpb25744GZ44G544Gm44Gu5a++6LGh5pSv5oyB5pS/5YWa44Gr44GK44GR44KL5pSv5oyB5pS/5YWa5ZCN5LiA6Ie05Yq55p6cfSIsCiAgICAiXFxlbmR7ZmlndXJlfSIsCiAgICAiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvY3Jvc3Nfc3R1ZHkvdGFibGVzX3RleC90YWJsZV9hbGxfcGFydHlfbWF0Y2hfY29lZmZpY2llbnRzLnRleH0iLAogICAgIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290L2Nyb3NzX3N0dWR5L3RhYmxlc190ZXgvdGFibGVfYWxsX3BhcnR5X21hdGNoX3RyZW5kcy50ZXh9IiwKICAgICJcXGNsZWFycGFnZSIKICApCn0KCndyaXRlTGluZXMoCiAgcGFpcl90ZXhfbGluZXMsCiAgY29uID0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCAiYWxsX3N0dWRpZXNfZmlndXJlX3RhYmxlX3BhaXJzLnRleCIpLAogIHVzZUJ5dGVzID0gVFJVRQopCgpwcmVhbWJsZV9saW5lcyA8LSBjKAogICIlIEFkZCB0aGVzZSBwYWNrYWdlcyB0byB0aGUgcHJlYW1ibGUgb2YgYXBwZW5kaXgudGV4LiIsCiAgIlxcdXNlcGFja2FnZXtncmFwaGljeH0iLAogICJcXHVzZXBhY2thZ2V7Ym9va3RhYnN9IiwKICAiXFx1c2VwYWNrYWdle2xvbmd0YWJsZX0iLAogICJcXHVzZXBhY2thZ2V7YXJyYXl9IiwKICAiXFx1c2VwYWNrYWdle3BkZmxzY2FwZX0iLAogICJcXHVzZXBhY2thZ2V7Y2FwdGlvbn0iLAogICIlIENvbXBpbGUgd2l0aCBMdWFMYVRlWCBiZWNhdXNlIHRoZSBnZW5lcmF0ZWQgY2FwdGlvbnMgYW5kIHRhYmxlcyBjb250YWluIEphcGFuZXNlLiIKKQp3cml0ZUxpbmVzKAogIHByZWFtYmxlX2xpbmVzLAogIGNvbiA9IGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgImxhdGV4X3ByZWFtYmxlX3NuaXBwZXQudGV4IiksCiAgdXNlQnl0ZXMgPSBUUlVFCikKCnN0YW5kYWxvbmVfbGluZXMgPC0gYygKICAiJSAhVGVYIHByb2dyYW0gPSBsdWFsYXRleCIsCiAgIlxcZG9jdW1lbnRjbGFzc1thNHBhcGVyLDExcHRde2x0anNhcnRpY2xlfSIsCiAgIlxcdXNlcGFja2FnZVttYXJnaW49MjJtbV17Z2VvbWV0cnl9IiwKICAiXFx1c2VwYWNrYWdle2dyYXBoaWN4fSIsCiAgIlxcdXNlcGFja2FnZXtib29rdGFic30iLAogICJcXHVzZXBhY2thZ2V7bG9uZ3RhYmxlfSIsCiAgIlxcdXNlcGFja2FnZXthcnJheX0iLAogICJcXHVzZXBhY2thZ2V7cGRmbHNjYXBlfSIsCiAgIlxcdXNlcGFja2FnZXtjYXB0aW9ufSIsCiAgIlxcYmVnaW57ZG9jdW1lbnR9IiwKICAiXFx0YWJsZW9mY29udGVudHMiLAogICJcXGNsZWFycGFnZSIsCiAgIlxcaW5wdXR7YWxsX3N0dWRpZXNfZmlndXJlX3RhYmxlX3BhaXJzLnRleH0iLAogICJcXGVuZHtkb2N1bWVudH0iCikKd3JpdGVMaW5lcygKICBzdGFuZGFsb25lX2xpbmVzLAogIGNvbiA9IGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgInN1cHBsZW1lbnRfdGFibGVzX2ZpZ3VyZXNfbWFzdGVyLnRleCIpLAogIHVzZUJ5dGVzID0gVFJVRQopCgpsYXlvdXRfbGluZXMgPC0gYygKICAiT1VUUFVUIERJUkVDVE9SWSBTVFJVQ1RVUkUiLAogICI9PT09PT09PT09PT09PT09PT09PT09PT09PSIsCiAgIm1haW5fdGV4dC9maWd1cmVzICAgICAgOiBtYW51c2NyaXB0IGZpZ3VyZXMiLAogICJtYWluX3RleHQvdGFibGVzICAgICAgIDogTGFUZVggdGFibGVzIGNvcnJlc3BvbmRpbmcgdG8gbWFudXNjcmlwdCBmaWd1cmVzIiwKICAic3VwcGxlbWVudC9zdHVkeTEtMyAgICA6IHBlci1zdHVkeSBmaWd1cmVzLCBDU1YgdGFibGVzLCBhbmQgTGFUZVggdGFibGVzIiwKICAic3VwcGxlbWVudC9jcm9zc19zdHVkeSA6IGNyb3NzLXN0dWR5IGZpZ3VyZXMgYW5kIHRhYmxlcyIsCiAgImRpYWdub3N0aWNzL3N0dWR5MS0zICAgOiByZXNwb25kZW50IHNjcmVlbmluZywgYmFsYW5jZSwgYW5kIHJhbmRvbWl6YXRpb24gZGlhZ25vc3RpY3MiLAogICJtb2RlbF9vYmplY3RzICAgICAgICAgIDogUkRTIG1vZGVsIGFuZCBhbmFseXNpcyBvYmplY3RzIiwKICAibG9ncyAgICAgICAgICAgICAgICAgICA6IHRleHQgbW9kZWwgc3VtbWFyaWVzIGFuZCBzZXNzaW9uIGluZm9ybWF0aW9uIiwKICAiX3dvcmtpbmcgICAgICAgICAgICAgICA6IG9yaWdpbmFsIGludGVybWVkaWF0ZSBvdXRwdXRzIHByb2R1Y2VkIGJ5IGVhY2ggYW5hbHlzaXMgbW9kdWxlIiwKICAiIiwKICAiTEFURVgiLAogICItLS0tLSIsCiAgIkFkZCB0aGUgcGFja2FnZXMgaW4gc3VwcGxlbWVudC9sYXRleF9wcmVhbWJsZV9zbmlwcGV0LnRleCB0byBhcHBlbmRpeC50ZXguIiwKICAiVGhlbiBpbnB1dCBzdXBwbGVtZW50L2FsbF9zdHVkaWVzX2ZpZ3VyZV90YWJsZV9wYWlycy50ZXgsIG9yIGNvbXBpbGUiLAogICJzdXBwbGVtZW50L3N1cHBsZW1lbnRfdGFibGVzX2ZpZ3VyZXNfbWFzdGVyLnRleCB3aXRoIEx1YUxhVGVYLiIKKQp3cml0ZUxpbmVzKAogIGxheW91dF9saW5lcywKICBjb24gPSBmaWxlLnBhdGgoZmluYWxfb3V0cHV0X3Jvb3QsICJPVVRQVVRfU1RSVUNUVVJFX0FORF9MQVRFWF9SRUFETUUudHh0IiksCiAgdXNlQnl0ZXMgPSBUUlVFCikKCnNhdmVSRFMoCiAgbGlzdCgKICAgIHNjcmVlbmluZyA9IHNjcmVlbmluZ19yZXN1bHRzLAogICAgcGFpcl9tYW5pZmVzdCA9IHBhaXJfbWFuaWZlc3QsCiAgICBmaW5hbF9kaXJzID0gZmluYWxfZGlycwogICksCiAgZmlsZSA9IGZpbGUucGF0aChmaW5hbF9kaXJzJG1vZGVsX29iamVjdHNfcm9vdCwgInNjcmVlbmluZ19hbmRfbGF0ZXhfZXhwb3J0X29iamVjdHMucmRzIikKKQoKY2F0KAogICJcblNjcmVlbmVkLXNhbXBsZSBhdWRpdCwgTGFUZVggdGFibGVzLCBmaWd1cmUtdGFibGUgcGFpcnMsIGFuZCBmaW5hbCBvdXRwdXQgb3JnYW5pemF0aW9uIGNvbXBsZXRlZC5cbiIsCiAgIkZpbmFsIG91dHB1dCByb290OiAiLCBub3JtYWxpemVQYXRoKGZpbmFsX291dHB1dF9yb290KSwgIlxuIiwKICAiTGFUZVggbWFzdGVyOiAiLAogIG5vcm1hbGl6ZVBhdGgoZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCAic3VwcGxlbWVudF90YWJsZXNfZmlndXJlc19tYXN0ZXIudGV4IikpLAogICJcbiIsCiAgc2VwID0gIiIKKQpgYGAKCiMgQi4g5o6o5a6a5pa55rOV44Go5YiG5p6Q5qiZ5pys44Gu5a6a576pCgojIyBCLjEg5YiG5p6Q5qiZ5pysCgrlkITlm57nrZTogIXjga8y44CBM+OAgTTjgIE144Gu44GE44Ga44KM44GL44Gu6YG45oqe6IKi5pWw5p2h5Lu244Gr5Ymy44KK5b2T44Gm44KJ44KM44CBNeOBpOOBrumBuOaKnuiqsumhjOOBq+WbnuetlOOBl+OBn+OAguW+k+WxnuWkieaVsOOBr+OAgeWQhOiqsumhjOOBq+aPkOekuuOBleOCjOOBn+ODl+ODreODleOCo+ODvOODq+OBjOmBuOaKnuOBleOCjOOBn+WgtOWQiOOBqzHjgIHpgbjmip7jgZXjgozjgarjgYvjgaPjgZ/loLTlkIjjgasw44KS44Go44KL5LqM5YCk5aSJ5pWw44Gn44GC44KL44CCCgrlrp/pqJMx44Gn44Gv44CB5Yid5Zue5ZCM5oSP44CB5pyA57WC6YCB5L+h5ZCM5oSP44CB44GK44KI44Gz5Ymy44KK5b2T44Gm44KJ44KM44Gf5p2h5Lu244Gr44GK44GR44KLNeiqsumhjOOBruacieWKueWbnuetlOOCkua6gOOBn+OBmeWbnuetlOiAheOCkuWIhuaekOWvvuixoeOBqOOBl+OBn+OAguWun+mokzLjg7sz44Gn44Gv44CB44GT44KM44KJ44Gr5Yqg44GI44Gm44CB44Kk44OH44Kq44Ot44Ku44O86KGM5YiX5Lit44Gu5oyH56S66aCF55uu44Go6YG45oqe6IKi5pWw44Gu5pON5L2c56K66KqN6LOq5ZWP44Gr5q2j562U44GX44Gf5Zue562U6ICF44Gr6ZmQ5a6a44GX44Gf44CCCgojIyBCLjIgQU1DRQoK5Zue562U6ICF44KSICRpJOOAgemBuOaKnuiqsumhjOOCkiAkdCTjgIHjg5fjg63jg5XjgqPjg7zjg6vjgpIgJGok44CB6YG45oqe6IKi5pWw5p2h5Lu244KSICRrXGluXHsyLDMsNCw1XH0kIOOBqOOBmeOCi+OAguW+k+WxnuWkieaVsOOCkgoKJCQKWV97aXRqfQo9ClxtYXRoYmZ7MX1ce1x0ZXh0e+ODl+ODreODleOCo+ODvOODqyB9alx0ZXh0eyDjgYzpgbjmip7jgZXjgozjgZ99XH0KJCQKCuOBqOWumue+qeOBmeOCi+OAguWQhOmBuOaKnuiCouaVsOadoeS7tuOBq+OBpOOBhOOBpuOAgee3muW9oueiuueOh+ODouODh+ODq+OCkuWIpeOAheOBq+aOqOWumuOBmeOCi+OAggoKJCQKWV97aXRqfQo9ClxhbHBoYV57KGspfQorClxzdW1fe2F9ClxzdW1fe1xlbGxcbmVxIFxlbGxfe2EwfX0KXGJldGFfe2FcZWxsfV57KGspfURfe2l0aixhXGVsbH0KKwpcYm9sZHN5bWJvbHtcZ2FtbWF9XnsoaylccHJpbWV9XGJvbGRzeW1ib2x7Wn1fe2l9CisKXHZhcmVwc2lsb25fe2l0an1eeyhrKX0uCiQkCgokXGJldGFfe2FcZWxsfV57KGspfSQg44Gv44CBJGskIOmBuOaKnuiCouadoeS7tuOBq+OBiuOBhOOBpuOAgeWxnuaApyAkYSQg44KS5Z+65rqW5rC05rqWICRcZWxsX3thMH0kIOOBi+OCieawtOa6liAkXGVsbCQg44Gr5aSJ5pu044GX44Gf44Go44GN44Gu5bmz5Z2H6ZmQ55WM6KaB57Sg5Yq55p6c77yIQU1DRe+8ieOBp+OBguOCi+OAguaomea6luiqpOW3ruOBr+WbnuetlOiAheWNmOS9jeOBp+OCr+ODqeOCueOCv+WMluOBl+OBn+OAggoK5a6f6aiTMeODuzLjgafjga/jgIHmlL/nrZbkvY3nva7jga7ln7rmupbjgpLkuK3pgZPjgIHkuI7ph47lhZrlnLDkvY3jga7ln7rmupbjgpLph47lhZrjgIHorbDluK3mlbDjga7ln7rmupbjgpIxMOS7peS4i+OBqOOBl+OAgUdEUOaIkOmVt+eOh+OAgeaXpee1jOW5s+Wdh+agquS+oeOAgUNQSeOAgeWksealreeOh+OBr+OBhOOBmuOCjOOCguWkieWMluOBquOBl+OCkuWfuua6luOBqOOBl+OBn+OAguWun+mokzPjgafjga/mlL/lhZrlkI3jga7ln7rmupbjgpLoh6rnlLHmsJHkuLvlhZrjgajjgZfjgZ/jgIIKCgojIyBCLjMg6ZmQ55WM5bmz5Z2H44Go5bGe5oCn6YeN6KaB5bqmCgokayQg6YG45oqe6IKi5p2h5Lu244Gr44GK44GR44KL5bGe5oCnICRhJCDjga7msLTmupYgJFxlbGwkIOOBrumZkOeVjOW5s+Wdh+OCkuOAgQoKJCQKXHdpZGVoYXR7XG11fV97YVxlbGx9Xnsoayl9Cj0KXGZyYWN7ClxzdW1fe2ksdCxqfQpcbWF0aGJmezF9XHtYX3tpdGosYX09XGVsbFx9WV97aXRqfQp9ewpcc3VtX3tpLHQsan0KXG1hdGhiZnsxfVx7WF97aXRqLGF9PVxlbGxcfQp9CiQkCgrjgajjgZnjgovjgIIKCuWxnuaApyAkYSQg44GMICRMX2EkIOWAi+OBruawtOa6luOCkuOCguOBpOOBqOOBjeOAgeWxnuaAp+mHjeimgeW6puOCkuWFqOawtOa6luODmuOCouOBrumZkOeVjOW5s+Wdh+W3ruOBrue1tuWvvuWApOOBruW5s+Wdh+OBqOOBl+OBpuOAgQoKJCQKXHdpZGVoYXR7SX1fe2F9Xnsoayl9Cj0KXGJpbm9te0xfYX17Mn1eey0xfQpcc3VtX3tcZWxsPFxlbGwnfQpcbGVmdHwKXHdpZGVoYXR7XG11fV97YVxlbGx9Xnsoayl9Ci0KXHdpZGVoYXR7XG11fV97YVxlbGwnfV57KGspfQpccmlnaHR8CiQkCgrjgajlrprnvqnjgZfjgZ/jgIIKCuWun+mokzHjg7sy44Gu5pS/5YWa5omL44GM44GL44KK44Gu6YeN6KaB5bqm44Gv44CB5pS/562W5L2N572u44CB5LiO6YeO5YWa5Zyw5L2N44CB6K2w5bit5pWw44GuM+WxnuaAp+OBrumHjeimgeW6puOCkuetieOBl+OBhOWKoOmHjeOBp+W5s+Wdh+OBl+OBn+OAguWun+mokzPjgafjga/mlL/lhZrlkI3lsZ7mgKfjga7ph43opoHluqbjgpLmlL/lhZrmiYvjgYzjgYvjgorjga7ph43opoHluqbjgajjgZfjgZ/jgILntYzmuIjmiYvjgYzjgYvjgorjga/jgIEz5a6f6aiT44Go44KCR0RQ5oiQ6ZW3546H44CB5pel57WM5bmz5Z2H5qCq5L6h44CBQ1BJ44CB5aSx5qWt546H44GuNOWxnuaAp+OBrumHjeimgeW6puOCkuetieOBl+OBhOWKoOmHjeOBp+W5s+Wdh+OBl+OBn+OAggoKIyMgQi40IOmBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOBqOebuOWvvuavlOmHjQoKJGskIOWAi+OBruODl+ODreODleOCo+ODvOODq+OBi+OCieW/heOBmjHjgaTjgpLpgbjmip7jgZnjgovjgZ/jgoHjgIHjg5fjg63jg5XjgqPjg7zjg6sx5Lu244GC44Gf44KK44Gu5bmz5Z2H6YG45oqe56K6546H44GvICQxL2skIOOBqOOBquOCi+OAguadoeS7tumWk+avlOi8g+OBruOBn+OCgeOAgeWxnuaApyAkYSQg44Gu6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqm44KS44CBCgokJApcd2lkZWhhdHtJfV97YX1ee1xtYXRocm17YWRqfSwoayl9Cj0KXGZyYWN7XHdpZGVoYXR7SX1fe2F9Xnsoayl9fXsxL2t9Cj0Ka1x3aWRlaGF0e0l9X3thfV57KGspfQokJAoK44Go44GX44Gf44CCCgrmlL/lhZrmiYvjgYzjgYvjgorjga7ph43opoHluqbjgpIgJFx3aWRlaGF0e1B9Xnsoayl9JOOAgee1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOCkiAkXHdpZGVoYXR7RX1eeyhrKX0kIOOBqOOBmeOCi+OBqOOAgeaUv+WFmuaJi+OBjOOBi+OCiuOBruebuOWvvuavlOmHjeOBr+OAgQoKJCQKXHdpZGVoYXR7V31eeyhrKX0KPQpcZnJhY3tcd2lkZWhhdHtQfV57KGspfX0Ke1x3aWRlaGF0e1B9Xnsoayl9K1x3aWRlaGF0e0V9Xnsoayl9fQokJAoK44Gn44GC44KL44CC5pS/5YWa44O757WM5riI44Gu5Lih6YeN6KaB5bqm44Gr5ZCM44GYICRrJCDjgpLkuZfjgZjjgabjgoLnm7jlr77mr5Tph43jga/lpInljJbjgZfjgarjgYTjgIIKCiMjIEIuNSDjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5fjgajnt5rlvaLjg4jjg6zjg7Pjg4kKCumHjeimgeW6puOBqOebuOWvvuavlOmHjeOBrjk1JeS/oemgvOWMuumWk+OBr+OAgeWQhOmBuOaKnuiCouaVsOadoeS7tuWGheOBp+WbnuetlOiAheOCkuWNmOS9jeOBqOOBl+OBpuW+qeWFg+aKveWHuuOBl+OAgeWQhOWbnuetlOiAheOBrjXoqrLpoYzjg7vlhajjg5fjg63jg5XjgqPjg7zjg6vjgavmrKDmkI3jga7jgarjgYTlm57nrZTogIXjgq/jg6njgrnjgr/jg7zjg7vjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5fjgYvjgonnrpflh7rjgZfjgZ/jgILkuLvopoHliIbmnpDjgafjga8yLDAwMOWbnuWPjeW+qeOBleOBm+OBn+OAggoK5ZCE5oyH5qiZICRRXnsoayl9JCDjga7pgbjmip7ogqLmlbDjgavlr77jgZnjgovnt5rlvaLlgr7lkJHjga/jgIEKCiQkClFeeyhrKX09XGV0YStcZGVsdGEgayt1Xnsoayl9CiQkCgrjgajjgZfjgaY05p2h5Lu244Gu54K55o6o5a6a5YCk44GrT0xT44KS5b2T44Gm44Gv44KB44CB5YK+44GNICRcZGVsdGEkIOOCkuaxguOCgeOBn+OAguWQhOODluODvOODiOOCueODiOODqeODg+ODl+WPjeW+qeOBp+OCguWQjOOBmOWCvuOBjeOCkuWGjeaOqOWumuOBl+OAgTk1JeS/oemgvOWMuumWk+OBqOS4oeWBtOODluODvOODiOOCueODiOODqeODg+ODlyAkcCQg5YCk44KS566X5Ye644GX44Gf44CCSDFh44CBSDFi44CBSDJh44CBSDJi44Gu5b2i5byP55qE44Gq5Yik5a6a44Gr44Gv5pyq6Kq/5pW06YeN6KaB5bqm44Gu57ea5b2i44OI44Os44Oz44OJ44KS55So44GE44CB6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqm44Gu57ea5b2i44OI44Os44Oz44OJ44Gv5p2h5Lu26ZaT5q+U6LyD44Gu5oSf5bqm5YiG5p6Q44Go44GX44Gm5L2155So44GX44Gf44CCCgojIyBCLjYg5p2h5Lu25LuY44GN44Ot44K444OD44OICgrlvLfliLbpgbjmip7oqrLpoYzjga7mp4vpgKDjgpLogIPmha7jgZnjgovpoJHlgaXmgKfliIbmnpDjgajjgZfjgabjgIHlkITpgbjmip7ogqLmlbDmnaHku7bjgavjgaTjgYTjgabmnaHku7bku5jjgY3jg63jgrjjg4Pjg4jjgpLmjqjlrprjgZfjgZ/jgIIKCiQkClxQcihZX3tpdGp9PTFcbWlkIFxtYXRoY2Fse0N9X3tpdH0pCj0KXGZyYWN7XGV4cChcYm9sZHN5bWJvbHtYfV97aXRqfV57XHByaW1lfVxib2xkc3ltYm9se1xiZXRhfV57KGspfSl9Cntcc3VtX3tyXGluXG1hdGhjYWx7Q31fe2l0fX1cZXhwKFxib2xkc3ltYm9se1h9X3tpdHJ9XntccHJpbWV9XGJvbGRzeW1ib2x7XGJldGF9Xnsoayl9KX0uCiQkCgrjgZPjgZPjgafjgIEkciQg44Gv5ZCM5LiA6YG45oqe6Kqy6aGM5YaF44Gu44OX44Ot44OV44Kj44O844Or44KS6LWw44KL5re75a2X44Gn44GC44KK44CBJGskIOOBr+mBuOaKnuiCouaVsOadoeS7tuOCkuihqOOBmeOAguiqsumhjOOCkuWxpO+8iHN0cmF0dW3vvInjgajjgZfjgIHlm57nrZTogIXljZjkvY3jgafjgq/jg6njgrnjgr/ljJbjgZfjgZ/jgILlm57nrZTogIXjg6zjg5njg6vlhbHlpInph4/jga/lkIzkuIDpgbjmip7oqrLpoYzlhoXjgafkuIDlrprjgafjgYLjgovjgZ/jgoHjgIHmnaHku7bku5jjgY3jg63jgrjjg4Pjg4jjgavjga/jg5fjg63jg5XjgqPjg7zjg6vlsZ7mgKfjga7jgb/jgpLmipXlhaXjgZfjgZ/jgIIKCiMjIEIuNyDmlK/mjIHmlL/lhZrlkI3jgajjga7kuIDoh7TlirnmnpwKCuWun+mokzPjgafjga/jgIEKCiQkCk1fe2l0an0KPQpcbWF0aGJmezF9XHtcdGV4dHvmj5DnpLrmlL/lhZrlkI19X3tpdGp9PVx0ZXh0e+aUr+aMgeaUv+WFmn1fe2l9XH0KJCQKCuOCkuS9nOaIkOOBl+OBn+OAguWFqOS9k+ODouODh+ODq+OBp+OBr+OAgeaUr+aMgeaUv+WFmuWQjeS4gOiHtOOAgeaPkOekuuaUv+WFmuWQjeOAgTTjgaTjga7ntYzmuIjlsZ7mgKfjgpLmipXlhaXjgZfjgIHpgbjmip7ogqLmlbDmnaHku7bjgZTjgajjgavmjqjlrprjgZfjgZ/jgILjgarjgYrjgIHmlK/mjIHmlL/lhZrliKXjga7liIbmnpDjgafjga/jgIHmlL/lhZrlkI3jgajkuIDoh7TmjIfmqJnjgYzlrozlhajjgavlr77lv5zjgZfjgabjgZfjgb7jgYbjgZ/jgoHjgIHmlL/lhZrlkI3kuLvlirnmnpzjgpLpmaTjgY3jgIHkuIDoh7TmjIfmqJnjgajntYzmuIjlsZ7mgKfjgpLnlKjjgYTjgZ/jgIIKCiMjIEIuOCDjg5Djg6njg7PjgrnjgajnhKHkvZzngrrljJboqLrmlq0KCuWbnuetlOiAheWJsuS7mOOBruODkOODqeODs+OCueOBr+OAgTLjgIEz44CBNOOAgTXmnaHku7bjga7lhajmnaHku7bjg5rjgqLjgavjgaTjgYTjgabmqJnmupbljJblubPlnYflt67jgpLnrpflh7rjgZfjgZ/jgILnlKjjgYTjgZ/lm57nrZTogIXlsZ7mgKfjga/jgIHlkITlrp/pqJPjgafliKnnlKjlj6/og73jgarmgKfliKXjgIHlubTpvaLjgIE05bm05Yi25aSn5a2m5Lul5LiK44CB5a++5pWw5LiW5biv5bm05Y+O44CB6Ieq5bex44Kk44OH44Kq44Ot44Ku44O844CB44GK44KI44Gz44Gd44KM44KJ44Gu5qyg5pCN5oyH5qiZ44Go5pSv5oyB5pS/5YWa44Gn44GC44KL44CC5Zyw5Z+f44O76YO96YGT5bqc55yM44Gv44GT44Gu5Ymy5LuY44OQ44Op44Oz44K56Ki65pat44Gr44Gv55So44GE44Gm44GE44Gq44GE44CCTG92ZSBwbG90IOOBr+WFqDbmnaHku7bjg5rjgqLjga7ntbblr75TTUTjgpLnpLrjgZfjgIHlr77op5Lnt5rlm7Pjga/lkIzjgZjlm57nrZTogIXlhbHlpInph4/jgavjgaTjgYTjgablkITmnaHku7blubPlnYfjgpLmqJnmupbljJbjgZfjgIHkuozmnaHku7bjgZrjgaQ0NeW6pue3muOBqOavlOi8g+OBmeOCi+ijnOWKqeeahOOBquWPr+imluWMluOBp+OBguOCi+OAggoKJCQKXG1hdGhybXtTTUR9X3thYn0KPQpcZnJhY3tcb3ZlcmxpbmV7eH1fYS1cb3ZlcmxpbmV7eH1fYn0Ke1xzcXJ0eyhzX2FeMitzX2JeMikvMn19LgokJAoK44OX44Ot44OV44Kj44O844Or5bGe5oCn44Gu5o+Q56S644Gr44Gk44GE44Gm44Gv44CB6YG45oqe6IKi5pWw5p2h5Lu2w5flsZ7mgKfDl+awtOa6luOBlOOBqOOBq+ims+a4rOavlOeOh+OCkuaxguOCgeOAgeawtOa6luaVsOOCkiAkTF9hJCDjgajjgZfjgZ/oqK3oqIjkuIrjga7mnJ/lvoXmr5TnjocgJDEvTF9hJCDjgajmr5TovIPjgZfjgZ/jgILlsZ7mgKfDl+adoeS7tuOBlOOBqOOBq+S4gOanmOWIhuW4g+OCkuW4sOeEoeS7ruiqrOOBqOOBmeOCi+OCq+OCpOS6jOS5l+aknOWumuOCkuihjOOBhOOAgUhvbG3ms5Xjgavjgojjgovoo5zmraPlgKTjgoLloLHlkYrjgZfjgZ/jgIIKCgpgYGB7ciBkaXNwbGF5LWhlbHBlcnMsIGluY2x1ZGU9RkFMU0V9CuWxnuaAp+aXpeacrOiqniA8LSBmdW5jdGlvbih4KSB7CiAgZHBseXI6OmNhc2Vfd2hlbigKICAgIHggPT0gInBvbGljeV9wb3NpdGlvbiIgfiAi5pS/562W5L2N572uIiwKICAgIHggPT0gImdvdmVybm1lbnRfc3RhdHVzIiB+ICLkuI7ph47lhZrlnLDkvY0iLAogICAgeCA9PSAic2VhdHMiIH4gIuihhuitsOmZouitsOW4reaVsCIsCiAgICB4ID09ICJnZHBfZ3Jvd3RoIiB+ICJHRFDmiJDplbfnjociLAogICAgeCA9PSAibmlra2VpIiB+ICLml6XntYzlubPlnYfmoKrkvqEiLAogICAgeCA9PSAiY3BpIiB+ICLmtojosrvogIXniankvqHmjIfmlbDvvIhDUEnvvIkiLAogICAgeCA9PSAidW5lbXBsb3ltZW50IiB+ICLlpLHmpa3njociLAogICAgeCA9PSAicGFydHlfbmFtZSIgfiAi5pS/5YWa5ZCNIiwKICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIoeCkKICApCn0KCuadoeS7tuaXpeacrOiqniA8LSBmdW5jdGlvbih4LCBzdHVkeV9pZCkgewogIHN1ZmZpeCA8LSBpZiAoc3R1ZHlfaWQgPT0gInN0dWR5MyIpICLpgbjmip7ogqLmnaHku7YiIGVsc2UgIuaUv+WFmuadoeS7tiIKICB4X2NociA8LSBhcy5jaGFyYWN0ZXIoeCkKICBkcGx5cjo6aWZfZWxzZSgKICAgIHhfY2hyICVpbiUgYXMuY2hhcmFjdGVyKDI6NSksCiAgICBwYXN0ZTAoeF9jaHIsIHN1ZmZpeCksCiAgICB4X2NocgogICkKfQoK57Wx6KiI6YeP5pel5pys6KqeIDwtIGZ1bmN0aW9uKHgsIHN0dWR5X2lkKSB7CiAgcGFydHlfbmFtZSA8LSBpZiAoc3R1ZHlfaWQgPT0gInN0dWR5MyIpICLmlL/lhZrlkI3ph43opoHluqYiIGVsc2UgIuaUv+WFmumHjeimgeW6piIKICBkcGx5cjo6Y2FzZV93aGVuKAogICAgeCA9PSAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIgfiBwYXJ0eV9uYW1lLAogICAgeCA9PSAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIgfiAi57WM5riI6YeN6KaB5bqmIiwKICAgIHggPT0gInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiIH4gcGFzdGUwKHBhcnR5X25hbWUsICLvvIjpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/vvIkiKSwKICAgIHggPT0gImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiIH4gIue1jOa4iOmHjeimgeW6pu+8iOmBuOaKnuiCouaVsOiqv+aVtOa4iOOBv++8iSIsCiAgICB4ID09ICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiIH4gIuaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHjSIsCiAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKHgpCiAgKQp9CgrmlbDlgKTliJcgPC0gZnVuY3Rpb24oeCkgewogIHN1cHByZXNzV2FybmluZ3MocmVhZHI6OnBhcnNlX251bWJlcihhcy5jaGFyYWN0ZXIoeCkpKQp9CgrliJflkI3ml6XmnKzoqp4gPC0gZnVuY3Rpb24oeCkgewogIOWvvuW/nCA8LSBjKAogICAgdmFyaWFibGUgPSAi5aSJ5pWwIiwKICAgIGxhYmVsID0gIuawtOa6luODu+ihqOekuuWQjSIsCiAgICBwYXJ0eV9uID0gIuadoeS7tiIsCiAgICBwYXJ0eV9uX2xhYmVsID0gIuadoeS7tiIsCiAgICBhdHRyaWJ1dGUgPSAi5bGe5oCnIiwKICAgIGxldmVsID0gIuawtOa6liIsCiAgICB0ZXJtID0gIuODouODh+ODq+mghSIsCiAgICBlc3RpbWF0ZSA9ICLmjqjlrprlgKQiLAogICAgYHN0ZC5lcnJvcmAgPSAi5qiZ5rqW6Kqk5beuIiwKICAgIHN0YXRpc3RpYyA9ICLmjIfmqJkiLAogICAgYHAudmFsdWVgID0gInDlgKQiLAogICAgYGNvbmYubG93YCA9ICI5NSVDSeS4i+mZkCIsCiAgICBgY29uZi5oaWdoYCA9ICI5NSVDSeS4iumZkCIsCiAgICBlc3RpbWF0ZV9wcCA9ICLmjqjlrprlgKTvvIhwcO+8iSIsCiAgICBjb25mLmxvd19wcCA9ICI5NSVDSeS4i+mZkO+8iHBw77yJIiwKICAgIGNvbmYuaGlnaF9wcCA9ICI5NSVDSeS4iumZkO+8iHBw77yJIiwKICAgIG5faWRzID0gIuWbnuetlOiAheaVsCIsCiAgICBzdGF0dXMgPSAi5o6o5a6a54q25oWLIiwKICAgIG9yZGVyID0gIuihqOekuumghiIsCiAgICBwYXJ0eV9zdXBwb3J0X2ggPSAi5pSv5oyB5pS/5YWaIiwKICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgPSAi5pSv5oyB5pS/5YWaIiwKICAgIHN0dWR5X2lkID0gIuWun+mok0lEIiwKICAgIHN0dWR5X2xhYmVsID0gIuWun+mokyIsCiAgICBzdHVkeSA9ICLlrp/pqJMiLAogICAgY29tcGFyaXNvbiA9ICLmr5TovIMiLAogICAgY29uZGl0aW9uX2EgPSAi5p2h5Lu2QSIsCiAgICBjb25kaXRpb25fYiA9ICLmnaHku7ZCIiwKICAgIG1lYW5fYSA9ICLmnaHku7ZB5bmz5Z2HIiwKICAgIG1lYW5fYiA9ICLmnaHku7ZC5bmz5Z2HIiwKICAgIHNkX2EgPSAi5p2h5Lu2Qeaomea6luWBj+W3riIsCiAgICBzZF9iID0gIuadoeS7tkLmqJnmupblgY/lt64iLAogICAgbl9hID0gIuadoeS7tkHlm57nrZTogIXmlbAiLAogICAgbl9iID0gIuadoeS7tkLlm57nrZTogIXmlbAiLAogICAgcG9vbGVkX3NkID0gIuODl+ODvOODq+aomea6luWBj+W3riIsCiAgICBzbWQgPSAiU01EIiwKICAgIGFic19zbWQgPSAifFNNRHwiLAogICAgbWF4X2Fic19zbWQgPSAi5pyA5aSnfFNNRHwiLAogICAgbWVhbl9hYnNfc21kID0gIuW5s+Wdh3xTTUR8IiwKICAgIGNoaV9zcXVhcmUgPSAi44Kr44Kk5LqM5LmX5YCkIiwKICAgIGRmID0gIuiHqueUseW6piIsCiAgICBwX3ZhbHVlID0gInDlgKQiLAogICAgcF9ob2xtID0gIkhvbG3oo5zmraNw5YCkIiwKICAgIG9ic2VydmVkX24gPSAi6Kaz5ris5pWwIiwKICAgIHRvdGFsX24gPSAi57eP5pWwIiwKICAgIG5fbGV2ZWxzID0gIuawtOa6luaVsCIsCiAgICBvYnNlcnZlZF9zaGFyZSA9ICLoprPmuKzmr5TnjociLAogICAgZXhwZWN0ZWRfc2hhcmUgPSAi5pyf5b6F5q+U546HIiwKICAgIGRldmlhdGlvbiA9ICLoprPmuKzvvI3mnJ/lvoUiLAogICAgYWJzX2RldmlhdGlvbiA9ICLntbblr77lt64iLAogICAgbWF4X2Fic19zaGFyZV9kZXZpYXRpb24gPSAi5pyA5aSn57W25a++5q+U546H5beuIiwKICAgIGh5cG90aGVzaXMgPSAi5Luu6KqsIiwKICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9ICLkuojmuKzmlrnlkJEiLAogICAgY29uY2x1c2lvbiA9ICLliKTlrpoiLAogICAgcF92YWx1ZV90d29fc2lkZWQgPSAi5Lih5YG0cOWApCIsCiAgICBjdWVfZmFtaWx5ID0gIuaJi+OBjOOBi+OCiue+pCIsCiAgICBzdGF0aXN0aWNfbGFiZWwgPSAi5oyH5qiZIiwKICAgIGFuYWx5c2lzX3JvbGUgPSAi5YiG5p6Q5LiK44Gu5L2N572u44Gl44GRIiwKICAgIG1ldHJpY19zY2FsZSA9ICLlsLrluqYiLAogICAgZXN0aW1hdGVfYmFzZWxpbmVfcGN0X3Blcl9vcHRpb24gPSAi5YK+44GN77yIJe+8iSIsCiAgICBjb25mX2xvd19iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9ICI5NSVDSeS4i+mZkO+8iCXvvIkiLAogICAgY29uZl9oaWdoX2Jhc2VsaW5lX3BjdF9wZXJfb3B0aW9uID0gIjk1JUNJ5LiK6ZmQ77yIJe+8iSIsCiAgICBlc3RpbWF0ZV9wcF9wZXJfb3B0aW9uID0gIuWCvuOBje+8iHBw77yJIiwKICAgIGNvbmZfbG93X3BwX3Blcl9vcHRpb24gPSAiOTUlQ0nkuIvpmZDvvIhwcO+8iSIsCiAgICBjb25mX2hpZ2hfcHBfcGVyX29wdGlvbiA9ICI5NSVDSeS4iumZkO+8iHBw77yJIiwKICAgIGVzdGltYXRlX3BjdCA9ICLmjqjlrprlgKTvvIgl77yJIiwKICAgIGNvbmZfbG93X3BjdCA9ICI5NSVDSeS4i+mZkO+8iCXvvIkiLAogICAgY29uZl9oaWdoX3BjdCA9ICI5NSVDSeS4iumZkO+8iCXvvIkiCiAgKQogIGRwbHlyOjppZl9lbHNlKHggJWluJSBuYW1lcyjlr77lv5wpLCB1bm5hbWUo5a++5b+cW3hdKSwgeCkKfQoK6KGo5pel5pys6KqeIDwtIGZ1bmN0aW9uKHgpIHsKICB4ICU+JQogICAgZHBseXI6OnJlbmFtZV93aXRoKOWIl+WQjeaXpeacrOiqnikgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBkcGx5cjo6YWNyb3NzKAogICAgICAgIGRwbHlyOjpldmVyeXRoaW5nKCksCiAgICAgICAgfiBpZiAoaXMubnVtZXJpYygueCkpIHsKICAgICAgICAgIGRwbHlyOjppZl9lbHNlKGlzLm5hKC54KSwgIuKAlCIsIGZvcm1hdCgueCwgdHJpbSA9IFRSVUUsIHNjaWVudGlmaWMgPSBGQUxTRSkpCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKQogICAgICAgIH0KICAgICAgKQogICAgKQp9CgrmsLTmupbml6XmnKzoqp4gPC0gZnVuY3Rpb24odGVybSwgbGFiZWwsIGF0dHJpYnV0ZSkgewogIGRwbHlyOjpjYXNlX3doZW4oCiAgICBhdHRyaWJ1dGUgPT0gInBvbGljeV9wb3NpdGlvbiIgfiBzdHJpbmdyOjpzdHJfcmVtb3ZlKHRlcm0sICJecG9saWN5X3Bvc2l0aW9uIiksCiAgICBhdHRyaWJ1dGUgPT0gImdvdmVybm1lbnRfc3RhdHVzIiB+IHN0cmluZ3I6OnN0cl9yZW1vdmUodGVybSwgIl5nb3Zlcm5tZW50X3N0YXR1cyIpLAogICAgYXR0cmlidXRlID09ICJzZWF0cyIgfiBzdHJpbmdyOjpzdHJfcmVtb3ZlKHRlcm0sICJec2VhdHMiKSwKICAgIGF0dHJpYnV0ZSA9PSAiZ2RwX2dyb3d0aCIgfiBwYXN0ZTAoIkdEUO+8miIsIHN0cmluZ3I6OnN0cl9yZW1vdmUodGVybSwgIl5nZHBfZ3Jvd3RoR0RQ5oiQ6ZW3546HIikpLAogICAgYXR0cmlidXRlID09ICJuaWtrZWkiIH4gcGFzdGUwKCLml6XntYzlubPlnYfvvJoiLCBzdHJpbmdyOjpzdHJfcmVtb3ZlKHRlcm0sICJebmlra2Vp5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+UIikpLAogICAgYXR0cmlidXRlID09ICJjcGkiIH4gcGFzdGUwKCJDUEnvvJoiLCBzdHJpbmdyOjpzdHJfcmVtb3ZlKHRlcm0sICJeY3BpQ1BJ5YmN5pyf5q+UIikpLAogICAgYXR0cmlidXRlID09ICJ1bmVtcGxveW1lbnQiIH4gcGFzdGUwKCLlpLHmpa3njofvvJoiLCBzdHJpbmdyOjpzdHJfcmVtb3ZlKHRlcm0sICJedW5lbXBsb3ltZW505aSx5qWt546H5YmN5pyf5q+UIikpLAogICAgYXR0cmlidXRlID09ICJwYXJ0eV9uYW1lIiB+IHN0cmluZ3I6OnN0cl9yZW1vdmUodGVybSwgIl5wYXJ0eV9uYW1lIiksCiAgICAhaXMubmEobGFiZWwpICYgbGFiZWwgIT0gIiIgfiBhcy5jaGFyYWN0ZXIobGFiZWwpLAogICAgVFJVRSB+IGFzLmNoYXJhY3Rlcih0ZXJtKQogICkKfQpgYGAKCiMgQy4g54Sh5L2c54K65YyW44Gr44Gk44GE44Gm44Gu5ZCE56iu5qSc6KiOCgrku6XkuIvjgafjgIHlm57nrZTogIXjg6zjg5njg6vjga7libLku5jjg5Djg6njg7Pjgrnjgajjg5fjg63jg5XjgqPjg7zjg6vlsZ7mgKfjga7nhKHkvZzngrrmj5DnpLrjga/liKXjgIXjgavnorroqo3jgZnjgovjgILlm57nrZTogIXjg6zjg5njg6vjgafjga9Mb3ZlIHBsb3Tjgag0NeW6pue3muiouuaWreOCkuS9teeUqOOBl+OAgeODl+ODreODleOCo+ODvOODq+ODrOODmeODq+OBp+OBr+WQhOWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+OCkuioreioiOS4iuOBruacn+W+heavlOeOh+OBqOavlOi8g+OBmeOCi+OAggoKKipCLjEg5a6f6aiTMe+8iDIwMjPlubTvvIkqKgoKIyMg5ZuzQzHvvJrlm57nrZTogIXlibLku5jjga5Mb3ZlIHBsb3QKCmBgYHtyIGIxLWxvdmUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrlrp/pqJMx5LuV5qeYIDwtIHN0dWR5X3NwZWNzJHN0dWR5MQrlrp/pqJMx5Ymy5LuY6Kit6KiIIDwtIG1ha2VfYmFsYW5jZV9kZXNpZ24o5a6f6aiTMeS7leanmCkK5a6f6aiTMVNNRCA8LSBwYWlyd2lzZV9zbWRfbXVsdGlhcm0o5a6f6aiTMeWJsuS7mOioreioiCRsb25nKQrlrp/pqJMx5pyA5aSnU01EIDwtIOWun+mokzFTTUQgJT4lCiAgZHBseXI6Omdyb3VwX2J5KHZhcmlhYmxlLCBsYWJlbCkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShtYXhfYWJzX3NtZCA9IG1heChhYnNfc21kLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKTG92ZeODh+ODvOOCvyA8LSDlrp/pqJMxU01EICU+JQogIGRwbHlyOjpsZWZ0X2pvaW4o5a6f6aiTMeacgOWkp1NNRCwgYnkgPSBjKCJ2YXJpYWJsZSIsICJsYWJlbCIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKOihqOekuuWQjSA9IHN0YXRzOjpyZW9yZGVyKGxhYmVsLCBtYXhfYWJzX3NtZCkpCgrlm7NDMSA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoTG92ZeODh+ODvOOCvywgZ2dwbG90Mjo6YWVzKHggPSBhYnNfc21kLCB5ID0g6KGo56S65ZCNKSkgKwogIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMTAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNTUpICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KGFscGhhID0gMC4zMCwgc2l6ZSA9IDEuNCwgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9qaXR0ZXIoaGVpZ2h0ID0gMC4xMCwgd2lkdGggPSAwKSkgKwogIGdncGxvdDI6Omdlb21fcG9pbnQoCiAgICBkYXRhID0g5a6f6aiTMeacgOWkp1NNRCAlPiUgZHBseXI6Om11dGF0ZSjooajnpLrlkI0gPSBzdGF0czo6cmVvcmRlcihsYWJlbCwgbWF4X2Fic19zbWQpKSwKICAgIGdncGxvdDI6OmFlcyh4ID0gbWF4X2Fic19zbWQsIHkgPSDooajnpLrlkI0pLAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwgc2hhcGUgPSAyMSwgZmlsbCA9ICJ3aGl0ZSIsIHNpemUgPSAyLjUsIHN0cm9rZSA9IDAuOAogICkgKwogIGdncGxvdDI6OmxhYnMoeCA9ICLmnaHku7bplpPjga7ntbblr77mqJnmupbljJblubPlnYflt67vvIh8U01EfO+8iSIsIHkgPSBOVUxMLAogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAi5a6f6aiTMe+8iDIwMjPlubTvvInvvJrlkITngrnjga/mnaHku7bjg5rjgqLjgIHnmb3mipzjgY3ngrnjga/mnIDlpKfntbblr75TTUQiKSArCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEpICsKICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpKQrlm7NDMQpgYGAKCuihqEMx44Gr44Gv5ZuzQzHjga7lkITngrnjgavlr77lv5zjgZnjgovjgILlkITooYzjgavjga/mr5TovIPjgZnjgosy5p2h5Lu244Gu5bmz5Z2H44GoU01E44KS56S644GZ44CCCgpgYGB7ciBiMS1zbWQtdGFibGUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrooahDMSA8LSDlrp/pqJMxU01EICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDlpInmlbAgPSBsYWJlbCwKICAgIOavlOi8gyA9IHBhc3RlMChjb25kaXRpb25fYSwgIuaUv+WFmuadoeS7tu+8jSIsIGNvbmRpdGlvbl9iLCAi5pS/5YWa5p2h5Lu2IiksCiAgICBg5YmN6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYSwgMyksCiAgICBg5b6M6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYiwgMyksCiAgICBg5YmN6ICFTmAgPSBuX2EsCiAgICBg5b6M6ICFTmAgPSBuX2IsCiAgICBTTUQgPSByb3VuZChzbWQsIDMpLAogICAgYHxTTUR8YCA9IHJvdW5kKGFic19zbWQsIDMpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEMxKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyDlm7NDMu+8muadoeS7tuW5s+Wdh+OBrjQ15bqm57ea6Ki65patCgrlm7NDMuOBr+Wbs0Mx44Go5ZCM44GY5Zue562U6ICF44Os44OZ44Or44Gu5Ymy5LuY44OQ44Op44Oz44K544KS44CB5ZCE5YWx5aSJ6YeP44Gu5p2h5Lu25bmz5Z2H44KS5qiZ5rqW5YyW44GX44Gf44GG44GI44Gn5LqM5p2h5Lu244Ga44GkNDXluqbnt5rjgajmr5TovIPjgZfjgZ/jgoLjga7jgafjgYLjgovjgIIKCmBgYHtyIGIxLWRpYWdvbmFsLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5a++6KeS57ea44OH44O844K/IDwtIGFzc2lnbm1lbnRfYmFsYW5jZV9yZXN1bHRzJHN0dWR5MSRkaWFnb25hbF9kYXRhICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICDmr5TovIMgPSBwYXN0ZTAoY29uZGl0aW9uX2EsICLmlL/lhZrmnaHku7bvvI0iLCBjb25kaXRpb25fYiwgIuaUv+WFmuadoeS7tiIpCiAgKQoK44Op44OZ44Or5a++6LGhIDwtIOWvvuinkue3muODh+ODvOOCvyAlPiUKICBkcGx5cjo6Z3JvdXBfYnko5q+U6LyDKSAlPiUKICBkcGx5cjo6c2xpY2VfbWF4KGFic19kaWFnb25hbF9kZXZpYXRpb24sIG4gPSAzLCB3aXRoX3RpZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnVuZ3JvdXAoKQoK6Lu456+E5ZuyIDwtIG1heChhYnMoYyjlr77op5Lnt5rjg4fjg7zjgr8keF9tZWFuLCDlr77op5Lnt5rjg4fjg7zjgr8keV9tZWFuKSksIG5hLnJtID0gVFJVRSkK6Lu456+E5ZuyIDwtIG1heCgwLjEwLCDou7jnr4Tlm7IgKiAxLjE1KQoK5ZuzQzIgPC0gZ2dwbG90Mjo6Z2dwbG90KOWvvuinkue3muODh+ODvOOCvywgZ2dwbG90Mjo6YWVzKHggPSB4X21lYW4sIHkgPSB5X21lYW4pKSArCiAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjYwKSArCiAgZ2dwbG90Mjo6Z2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC4yNSkgKwogIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuMjUpICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAid2hpdGUiLCBzaXplID0gMi4yKSArCiAgZ2dwbG90Mjo6Z2VvbV90ZXh0KGRhdGEgPSDjg6njg5njg6vlr77osaEsIGdncGxvdDI6OmFlcyhsYWJlbCA9IGxhYmVsKSwgc2l6ZSA9IDIuNiwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIHZqdXN0ID0gLTAuNykgKwogIGdncGxvdDI6OmZhY2V0X3dyYXAofiDmr5TovIMsIG5jb2wgPSAzKSArCiAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoeGxpbSA9IGMoLei7uOevhOWbsiwg6Lu456+E5ZuyKSwgeWxpbSA9IGMoLei7uOevhOWbsiwg6Lu456+E5ZuyKSkgKwogIGdncGxvdDI6OmxhYnMoeCA9ICLlt6blgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciLCB5ID0gIuWPs+WBtOadoeS7tuOBruaomea6luWMluWFseWkiemHj+W5s+WdhyIpICsKICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMC41KSArCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkK5ZuzQzIKYGBgCgpgYGB7ciBiMS1iYWxhbmNlLXN1bW1hcnksIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrooahDMiA8LSBhc3NpZ25tZW50X2JhbGFuY2VfcmVzdWx0cyRzdHVkeTEkc3VtbWFyeSAlPiUKICBkcGx5cjo6dHJhbnNtdXRlKAogICAg5aSJ5pWwID0gbGFiZWwsCiAgICBgMuaUv+WFmuadoeS7tuOBruW5s+Wdh2AgPSByb3VuZChtZWFuX2NvbmRpdGlvbl8yLCAzKSwKICAgIGAz5pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzMsIDMpLAogICAgYDTmlL/lhZrmnaHku7bjga7lubPlnYdgID0gcm91bmQobWVhbl9jb25kaXRpb25fNCwgMyksCiAgICBgNeaUv+WFmuadoeS7tuOBruW5s+Wdh2AgPSByb3VuZChtZWFuX2NvbmRpdGlvbl81LCAzKSwKICAgIGDmnIDlpKd8U01EfGAgPSByb3VuZChtYXhfYWJzX3NtZCwgMyksCiAgICBgSG9sbeijnOato3DlgKRgID0gc2lnbmlmKHBfaG9sbSwgMykKICApCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIOWbs0Mz77ya44OX44Ot44OV44Kj44O844Or5bGe5oCn5rC05rqW44Gu54Sh5L2c54K65o+Q56S6Cgrlm7NDM+OBr+WbnuetlOiAheOBruadoeS7tuWJsuS7mOOBp+OBr+OBquOBj+OAgeWQhOOCs+ODs+OCuOODp+OCpOODs+ODiOiqsumhjOWGheOBp+WxnuaAp+awtOa6luOBjOioreioiOOBqeOBiuOCiuS4gOanmOOBq+aPkOekuuOBleOCjOOBpuOBhOOCi+OBi+OCkueiuuiqjeOBl+OBn+OCguOBruOBp+OBguOCi+OAggoKYGBge3IgYjEtcHJvZmlsZS1yYW5kb21pemF0aW9uLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5bGe5oCn6aC75bqmIDwtIHByb2ZpbGVfcmFuZG9taXphdGlvbl9yZXN1bHRzJHN0dWR5MSRmcmVxdWVuY3kgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnihhdHRyaWJ1dGUpLAogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTEiKQogICkKCuihqOekuuODqeODmeODqyA8LSDlsZ7mgKfpoLvluqYgJT4lCiAgZHBseXI6Omdyb3VwX2J5KOWxnuaApywg5p2h5Lu2KSAlPiUKICBkcGx5cjo6c2xpY2VfbWF4KGFic19kZXZpYXRpb24sIG4gPSAyLCB3aXRoX3RpZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnVuZ3JvdXAoKQoK5ZuzQzMgPC0gZ2dwbG90Mjo6Z2dwbG90KOWxnuaAp+mgu+W6piwgZ2dwbG90Mjo6YWVzKHggPSBleHBlY3RlZF9zaGFyZSwgeSA9IG9ic2VydmVkX3NoYXJlLCBzaGFwZSA9IOadoeS7tikpICsKICBnZ3Bsb3QyOjpnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNjUpICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNpemUgPSAyLjIsIGZpbGwgPSAid2hpdGUiKSArCiAgZ2dwbG90Mjo6Z2VvbV90ZXh0KGRhdGEgPSDooajnpLrjg6njg5njg6ssIGdncGxvdDI6OmFlcyhsYWJlbCA9IGxldmVsKSwgc2l6ZSA9IDIuNCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIHZqdXN0ID0gLTAuNykgKwogIGdncGxvdDI6OmZhY2V0X3dyYXAofiDlsZ7mgKcsIG5jb2wgPSAzKSArCiAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoKSArCiAgZ2dwbG90Mjo6bGFicyh4ID0gIuioreioiOS4iuOBruacn+W+heavlOeOhyIsIHkgPSAi6Kaz5ris5q+U546HIiwgc2hhcGUgPSAi5p2h5Lu2IikgKwogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsKICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikK5ZuzQzMKYGBgCgpgYGB7ciBiMS1yYW5kb21pemF0aW9uLXRhYmxlcywgZWNobz1UUlVFLCBldmFsPVRSVUV9CuihqEMzIDwtIHByb2ZpbGVfcmFuZG9taXphdGlvbl9yZXN1bHRzJHN0dWR5MSR1bmlmb3JtaXR5X3Rlc3RzICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDmnaHku7YgPSDmnaHku7bml6XmnKzoqp4ocGFydHlfbiwgInN0dWR5MSIpLAogICAg5bGe5oCnID0g5bGe5oCn5pel5pys6KqeKGF0dHJpYnV0ZSksCiAgICBg44Kr44Kk5LqM5LmX5YCkYCA9IHJvdW5kKGNoaV9zcXVhcmUsIDMpLAogICAg6Ieq55Sx5bqmID0gZGYsCiAgICBw5YCkID0gc2lnbmlmKHBfdmFsdWUsIDMpLAogICAgYEhvbG3oo5zmraNw5YCkYCA9IHNpZ25pZihwX2hvbG0sIDMpLAogICAgYOacgOWkp+e1tuWvvuavlOeOh+W3rmAgPSByb3VuZChtYXhfYWJzX3NoYXJlX2RldmlhdGlvbiwgNCkKICApCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzMpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQoK6KGoQzQgPC0g5bGe5oCn6aC75bqmICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDmnaHku7YsCiAgICDlsZ7mgKcsCiAgICDmsLTmupYgPSBsZXZlbCwKICAgIOims+a4rOaVsCA9IG9ic2VydmVkX24sCiAgICDnt4/mlbAgPSB0b3RhbF9uLAogICAg6Kaz5ris5q+U546HID0gcm91bmQob2JzZXJ2ZWRfc2hhcmUsIDQpLAogICAg5pyf5b6F5q+U546HID0gcm91bmQoZXhwZWN0ZWRfc2hhcmUsIDQpLAogICAg5beuID0gcm91bmQoZGV2aWF0aW9uLCA0KQogICkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahDNCksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKKipCLjIg5a6f6aiTMu+8iDIwMjblubTvvIkqKgoKIyMg5ZuzQzTvvJrlm57nrZTogIXlibLku5jjga5Mb3ZlIHBsb3QKCmBgYHtyIGIyLWxvdmUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrlrp/pqJMy5LuV5qeYIDwtIHN0dWR5X3NwZWNzJHN0dWR5Mgrlrp/pqJMy5Ymy5LuY6Kit6KiIIDwtIG1ha2VfYmFsYW5jZV9kZXNpZ24o5a6f6aiTMuS7leanmCkK5a6f6aiTMlNNRCA8LSBwYWlyd2lzZV9zbWRfbXVsdGlhcm0o5a6f6aiTMuWJsuS7mOioreioiCRsb25nKQrlrp/pqJMy5pyA5aSnU01EIDwtIOWun+mokzJTTUQgJT4lCiAgZHBseXI6Omdyb3VwX2J5KHZhcmlhYmxlLCBsYWJlbCkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShtYXhfYWJzX3NtZCA9IG1heChhYnNfc21kLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKTG92ZeODh+ODvOOCvyA8LSDlrp/pqJMyU01EICU+JQogIGRwbHlyOjpsZWZ0X2pvaW4o5a6f6aiTMuacgOWkp1NNRCwgYnkgPSBjKCJ2YXJpYWJsZSIsICJsYWJlbCIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKOihqOekuuWQjSA9IHN0YXRzOjpyZW9yZGVyKGxhYmVsLCBtYXhfYWJzX3NtZCkpCgrlm7NDNCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoTG92ZeODh+ODvOOCvywgZ2dwbG90Mjo6YWVzKHggPSBhYnNfc21kLCB5ID0g6KGo56S65ZCNKSkgKwogIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMTAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNTUpICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KGFscGhhID0gMC4zMCwgc2l6ZSA9IDEuNCwgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9qaXR0ZXIoaGVpZ2h0ID0gMC4xMCwgd2lkdGggPSAwKSkgKwogIGdncGxvdDI6Omdlb21fcG9pbnQoCiAgICBkYXRhID0g5a6f6aiTMuacgOWkp1NNRCAlPiUgZHBseXI6Om11dGF0ZSjooajnpLrlkI0gPSBzdGF0czo6cmVvcmRlcihsYWJlbCwgbWF4X2Fic19zbWQpKSwKICAgIGdncGxvdDI6OmFlcyh4ID0gbWF4X2Fic19zbWQsIHkgPSDooajnpLrlkI0pLAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwgc2hhcGUgPSAyMSwgZmlsbCA9ICJ3aGl0ZSIsIHNpemUgPSAyLjUsIHN0cm9rZSA9IDAuOAogICkgKwogIGdncGxvdDI6OmxhYnMoeCA9ICLmnaHku7bplpPjga7ntbblr77mqJnmupbljJblubPlnYflt67vvIh8U01EfO+8iSIsIHkgPSBOVUxMLAogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAi5a6f6aiTMu+8iDIwMjblubTvvInvvJrlkITngrnjga/mnaHku7bjg5rjgqLjgIHnmb3mipzjgY3ngrnjga/mnIDlpKfntbblr75TTUQiKSArCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEpICsKICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpKQrlm7NDNApgYGAKCuihqEM144Gv5ZuzQzTjga7lkITngrnjgavlr77lv5zjgZnjgovjgILlkITooYzjgavjga/mr5TovIPjgZnjgosy5p2h5Lu244Gu5bmz5Z2H44GoU01E44Gg44GR44KS5q6L44GX44CB5LuW5p2h5Lu244Gr55Sx5p2l44GZ44KL5qeL6YCg55qE44Gq5qyg5pCN5YCk44Gv6KGo56S644GX44Gq44GE44CCCgpgYGB7ciBiMi1zbWQtdGFibGUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrooahDNSA8LSDlrp/pqJMyU01EICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDlpInmlbAgPSBsYWJlbCwKICAgIOavlOi8gyA9IHBhc3RlMChjb25kaXRpb25fYSwgIuaUv+WFmuadoeS7tu+8jSIsIGNvbmRpdGlvbl9iLCAi5pS/5YWa5p2h5Lu2IiksCiAgICBg5YmN6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYSwgMyksCiAgICBg5b6M6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYiwgMyksCiAgICBg5YmN6ICFTmAgPSBuX2EsCiAgICBg5b6M6ICFTmAgPSBuX2IsCiAgICBTTUQgPSByb3VuZChzbWQsIDMpLAogICAgYHxTTUR8YCA9IHJvdW5kKGFic19zbWQsIDMpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEM1KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyDlm7NDNe+8muadoeS7tuW5s+Wdh+OBrjQ15bqm57ea6Ki65patCgrlm7NDNeOBr+Wbs0M044Go5ZCM44GY5Zue562U6ICF44Os44OZ44Or44Gu5Ymy5LuY44OQ44Op44Oz44K544KS44CB5ZCE5YWx5aSJ6YeP44Gu5p2h5Lu25bmz5Z2H44KS5qiZ5rqW5YyW44GX44Gf44GG44GI44GnMuadoeS7tuOBmuOBpDQ15bqm57ea44Go5q+U6LyD44GX44Gf44KC44Gu44Gn44GC44KL44CCCgpgYGB7ciBiMi1kaWFnb25hbCwgZWNobz1UUlVFLCBldmFsPVRSVUV9CuWvvuinkue3muODh+ODvOOCvyA8LSBhc3NpZ25tZW50X2JhbGFuY2VfcmVzdWx0cyRzdHVkeTIkZGlhZ29uYWxfZGF0YSAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAg5q+U6LyDID0gcGFzdGUwKGNvbmRpdGlvbl9hLCAi5pS/5YWa5p2h5Lu277yNIiwgY29uZGl0aW9uX2IsICLmlL/lhZrmnaHku7YiKQogICkKCuODqeODmeODq+WvvuixoSA8LSDlr77op5Lnt5rjg4fjg7zjgr8gJT4lCiAgZHBseXI6Omdyb3VwX2J5KOavlOi8gykgJT4lCiAgZHBseXI6OnNsaWNlX21heChhYnNfZGlhZ29uYWxfZGV2aWF0aW9uLCBuID0gMywgd2l0aF90aWVzID0gRkFMU0UpICU+JQogIGRwbHlyOjp1bmdyb3VwKCkKCui7uOevhOWbsiA8LSBtYXgoYWJzKGMo5a++6KeS57ea44OH44O844K/JHhfbWVhbiwg5a++6KeS57ea44OH44O844K/JHlfbWVhbikpLCBuYS5ybSA9IFRSVUUpCui7uOevhOWbsiA8LSBtYXgoMC4xMCwg6Lu456+E5ZuyICogMS4xNSkKCuWbs0M1IDwtIGdncGxvdDI6OmdncGxvdCjlr77op5Lnt5rjg4fjg7zjgr8sIGdncGxvdDI6OmFlcyh4ID0geF9tZWFuLCB5ID0geV9tZWFuKSkgKwogIGdncGxvdDI6Omdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbGluZXdpZHRoID0gMC42MCkgKwogIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuMjUpICsKICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjI1KSArCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc2l6ZSA9IDIuMikgKwogIGdncGxvdDI6Omdlb21fdGV4dChkYXRhID0g44Op44OZ44Or5a++6LGhLCBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsYWJlbCksIHNpemUgPSAyLjYsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCB2anVzdCA9IC0wLjcpICsKICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4g5q+U6LyDLCBuY29sID0gMykgKwogIGdncGxvdDI6OmNvb3JkX2VxdWFsKHhsaW0gPSBjKC3ou7jnr4Tlm7IsIOi7uOevhOWbsiksIHlsaW0gPSBjKC3ou7jnr4Tlm7IsIOi7uOevhOWbsikpICsKICBnZ3Bsb3QyOjpsYWJzKHggPSAi5bem5YG05p2h5Lu244Gu5qiZ5rqW5YyW5YWx5aSJ6YeP5bmz5Z2HIiwgeSA9ICLlj7PlgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciKSArCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKwogIGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkpCuWbs0M1CmBgYAoKYGBge3IgYjItYmFsYW5jZS1zdW1tYXJ5LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KGoQzYgPC0gYXNzaWdubWVudF9iYWxhbmNlX3Jlc3VsdHMkc3R1ZHkyJHN1bW1hcnkgJT4lCiAgZHBseXI6OnRyYW5zbXV0ZSgKICAgIOWkieaVsCA9IGxhYmVsLAogICAgYDLmlL/lhZrmnaHku7bjga7lubPlnYdgID0gcm91bmQobWVhbl9jb25kaXRpb25fMiwgMyksCiAgICBgM+aUv+WFmuadoeS7tuOBruW5s+Wdh2AgPSByb3VuZChtZWFuX2NvbmRpdGlvbl8zLCAzKSwKICAgIGA05pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzQsIDMpLAogICAgYDXmlL/lhZrmnaHku7bjga7lubPlnYdgID0gcm91bmQobWVhbl9jb25kaXRpb25fNSwgMyksCiAgICBg5pyA5aSnfFNNRHxgID0gcm91bmQobWF4X2Fic19zbWQsIDMpLAogICAgYEhvbG3oo5zmraNw5YCkYCA9IHNpZ25pZihwX2hvbG0sIDMpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEM2KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyDlm7NDNu+8muODl+ODreODleOCo+ODvOODq+WxnuaAp+awtOa6luOBrueEoeS9nOeCuuaPkOekugoK5ZuzQzbku6XpmY3jga/lm57nrZTogIXjga7mnaHku7blibLku5jjgafjga/jgarjgY/jgIHlkITjgrPjg7Pjgrjjg6fjgqTjg7Pjg4joqrLpoYzlhoXjgaflsZ7mgKfmsLTmupbjgYzoqK3oqIjjganjgYrjgorkuIDmp5jjgavmj5DnpLrjgZXjgozjgabjgYTjgovjgYvjgpLnorroqo3jgZnjgovjgoLjga7jgafjgYLjgovjgIIKCmBgYHtyIGIyLXByb2ZpbGUtcmFuZG9taXphdGlvbiwgZWNobz1UUlVFLCBldmFsPVRSVUV9CuWxnuaAp+mgu+W6piA8LSBwcm9maWxlX3JhbmRvbWl6YXRpb25fcmVzdWx0cyRzdHVkeTIkZnJlcXVlbmN5ICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4oYXR0cmlidXRlKSwKICAgIOadoeS7tiA9IOadoeS7tuaXpeacrOiqnihwYXJ0eV9uLCAic3R1ZHkyIikKICApCgrooajnpLrjg6njg5njg6sgPC0g5bGe5oCn6aC75bqmICU+JQogIGRwbHlyOjpncm91cF9ieSjlsZ7mgKcsIOadoeS7tikgJT4lCiAgZHBseXI6OnNsaWNlX21heChhYnNfZGV2aWF0aW9uLCBuID0gMiwgd2l0aF90aWVzID0gRkFMU0UpICU+JQogIGRwbHlyOjp1bmdyb3VwKCkKCuWbs0M2IDwtIGdncGxvdDI6OmdncGxvdCjlsZ7mgKfpoLvluqYsIGdncGxvdDI6OmFlcyh4ID0gZXhwZWN0ZWRfc2hhcmUsIHkgPSBvYnNlcnZlZF9zaGFyZSwgc2hhcGUgPSDmnaHku7YpKSArCiAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjY1KSArCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzaXplID0gMi4yLCBmaWxsID0gIndoaXRlIikgKwogIGdncGxvdDI6Omdlb21fdGV4dChkYXRhID0g6KGo56S644Op44OZ44OrLCBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsZXZlbCksIHNpemUgPSAyLjQsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCB2anVzdCA9IC0wLjcpICsKICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4g5bGe5oCnLCBuY29sID0gMykgKwogIGdncGxvdDI6OmNvb3JkX2VxdWFsKCkgKwogIGdncGxvdDI6OmxhYnMoeCA9ICLoqK3oqIjkuIrjga7mnJ/lvoXmr5TnjociLCB5ID0gIuims+a4rOavlOeOhyIsIHNoYXBlID0gIuadoeS7tiIpICsKICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMC41KSArCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCuWbs0M2CmBgYAoKYGBge3IgYjItcmFuZG9taXphdGlvbi10YWJsZXMsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrooahDNyA8LSBwcm9maWxlX3JhbmRvbWl6YXRpb25fcmVzdWx0cyRzdHVkeTIkdW5pZm9ybWl0eV90ZXN0cyAlPiUKICBkcGx5cjo6dHJhbnNtdXRlKAogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTIiKSwKICAgIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnihhdHRyaWJ1dGUpLAogICAgYOOCq+OCpOS6jOS5l+WApGAgPSByb3VuZChjaGlfc3F1YXJlLCAzKSwKICAgIOiHqueUseW6piA9IGRmLAogICAgcOWApCA9IHNpZ25pZihwX3ZhbHVlLCAzKSwKICAgIGBIb2xt6KOc5q2jcOWApGAgPSBzaWduaWYocF9ob2xtLCAzKSwKICAgIGDmnIDlpKfntbblr77mr5Tnjoflt65gID0gcm91bmQobWF4X2Fic19zaGFyZV9kZXZpYXRpb24sIDQpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEM3KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKCuihqEM4IDwtIOWxnuaAp+mgu+W6piAlPiUKICBkcGx5cjo6dHJhbnNtdXRlKAogICAg5p2h5Lu2LAogICAg5bGe5oCnLAogICAg5rC05rqWID0gbGV2ZWwsCiAgICDoprPmuKzmlbAgPSBvYnNlcnZlZF9uLAogICAg57eP5pWwID0gdG90YWxfbiwKICAgIOims+a4rOavlOeOhyA9IHJvdW5kKG9ic2VydmVkX3NoYXJlLCA0KSwKICAgIOacn+W+heavlOeOhyA9IHJvdW5kKGV4cGVjdGVkX3NoYXJlLCA0KSwKICAgIOW3riA9IHJvdW5kKGRldmlhdGlvbiwgNCkKICApCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzgpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCioqQi4zIOWun+mokzPvvIgyMDI25bm077yJKioKCiMjIOWbs0M377ya5Zue562U6ICF5Ymy5LuY44GuTG92ZSBwbG90CgpgYGB7ciBiMy1sb3ZlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5a6f6aiTM+S7leanmCA8LSBzdHVkeV9zcGVjcyRzdHVkeTMK5a6f6aiTM+WJsuS7mOioreioiCA8LSBtYWtlX2JhbGFuY2VfZGVzaWduKOWun+mokzPku5Xmp5gpCuWun+mokzNTTUQgPC0gcGFpcndpc2Vfc21kX211bHRpYXJtKOWun+mokzPlibLku5joqK3oqIgkbG9uZykK5a6f6aiTM+acgOWkp1NNRCA8LSDlrp/pqJMzU01EICU+JQogIGRwbHlyOjpncm91cF9ieSh2YXJpYWJsZSwgbGFiZWwpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UobWF4X2Fic19zbWQgPSBtYXgoYWJzX3NtZCwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCkxvdmXjg4fjg7zjgr8gPC0g5a6f6aiTM1NNRCAlPiUKICBkcGx5cjo6bGVmdF9qb2luKOWun+mokzPmnIDlpKdTTUQsIGJ5ID0gYygidmFyaWFibGUiLCAibGFiZWwiKSkgJT4lCiAgZHBseXI6Om11dGF0ZSjooajnpLrlkI0gPSBzdGF0czo6cmVvcmRlcihsYWJlbCwgbWF4X2Fic19zbWQpKQoK5ZuzQzcgPC0gZ2dwbG90Mjo6Z2dwbG90KExvdmXjg4fjg7zjgr8sIGdncGxvdDI6OmFlcyh4ID0gYWJzX3NtZCwgeSA9IOihqOekuuWQjSkpICsKICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjEwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjU1KSArCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChhbHBoYSA9IDAuMzAsIHNpemUgPSAxLjQsIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25faml0dGVyKGhlaWdodCA9IDAuMTAsIHdpZHRoID0gMCkpICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KAogICAgZGF0YSA9IOWun+mokzPmnIDlpKdTTUQgJT4lIGRwbHlyOjptdXRhdGUo6KGo56S65ZCNID0gc3RhdHM6OnJlb3JkZXIobGFiZWwsIG1heF9hYnNfc21kKSksCiAgICBnZ3Bsb3QyOjphZXMoeCA9IG1heF9hYnNfc21kLCB5ID0g6KGo56S65ZCNKSwKICAgIGluaGVyaXQuYWVzID0gRkFMU0UsIHNoYXBlID0gMjEsIGZpbGwgPSAid2hpdGUiLCBzaXplID0gMi41LCBzdHJva2UgPSAwLjgKICApICsKICBnZ3Bsb3QyOjpsYWJzKHggPSAi5p2h5Lu26ZaT44Gu57W25a++5qiZ5rqW5YyW5bmz5Z2H5beu77yIfFNNRHzvvIkiLCB5ID0gTlVMTCwKICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIuWun+mokzPvvIgyMDI25bm077yJ77ya5ZCE54K544Gv5p2h5Lu244Oa44Ki44CB55m95oqc44GN54K544Gv5pyA5aSn57W25a++U01EIikgKwogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDExKSArCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkK5ZuzQzcKYGBgCgrooahDOeOBr+Wbs0M344Gu5ZCE54K544Gr5a++5b+c44GZ44KL44CCCgpgYGB7ciBiMy1zbWQtdGFibGUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrooahDOSA8LSDlrp/pqJMzU01EICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDlpInmlbAgPSBsYWJlbCwKICAgIOavlOi8gyA9IHBhc3RlMChjb25kaXRpb25fYSwgIumBuOaKnuiCouadoeS7tu+8jSIsIGNvbmRpdGlvbl9iLCAi6YG45oqe6IKi5p2h5Lu2IiksCiAgICBg5YmN6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYSwgMyksCiAgICBg5b6M6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYiwgMyksCiAgICBg5YmN6ICFTmAgPSBuX2EsCiAgICBg5b6M6ICFTmAgPSBuX2IsCiAgICBTTUQgPSByb3VuZChzbWQsIDMpLAogICAgYHxTTUR8YCA9IHJvdW5kKGFic19zbWQsIDMpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEM5KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyDlm7NDOO+8muadoeS7tuW5s+Wdh+OBrjQ15bqm57ea6Ki65patCgrlm7NDOOOBr+Wbs0M344Go5ZCM44GY5Zue562U6ICF44Os44OZ44Or44Gu5Ymy5LuY44OQ44Op44Oz44K544KS44CB5ZCE5YWx5aSJ6YeP44Gu5p2h5Lu25bmz5Z2H44KS5qiZ5rqW5YyW44GX44Gf44GG44GI44GnMuadoeS7tuOBmuOBpDQ15bqm57ea44Go5q+U6LyD44GX44Gf44KC44Gu44Gn44GC44KL44CCCgpgYGB7ciBiMy1kaWFnb25hbCwgZWNobz1UUlVFLCBldmFsPVRSVUV9CuWvvuinkue3muODh+ODvOOCvyA8LSBhc3NpZ25tZW50X2JhbGFuY2VfcmVzdWx0cyRzdHVkeTMkZGlhZ29uYWxfZGF0YSAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAg5q+U6LyDID0gcGFzdGUwKGNvbmRpdGlvbl9hLCAi6YG45oqe6IKi5p2h5Lu277yNIiwgY29uZGl0aW9uX2IsICLpgbjmip7ogqLmnaHku7YiKQogICkKCuODqeODmeODq+WvvuixoSA8LSDlr77op5Lnt5rjg4fjg7zjgr8gJT4lCiAgZHBseXI6Omdyb3VwX2J5KOavlOi8gykgJT4lCiAgZHBseXI6OnNsaWNlX21heChhYnNfZGlhZ29uYWxfZGV2aWF0aW9uLCBuID0gMywgd2l0aF90aWVzID0gRkFMU0UpICU+JQogIGRwbHlyOjp1bmdyb3VwKCkKCui7uOevhOWbsiA8LSBtYXgoYWJzKGMo5a++6KeS57ea44OH44O844K/JHhfbWVhbiwg5a++6KeS57ea44OH44O844K/JHlfbWVhbikpLCBuYS5ybSA9IFRSVUUpCui7uOevhOWbsiA8LSBtYXgoMC4xMCwg6Lu456+E5ZuyICogMS4xNSkKCuWbs0M4IDwtIGdncGxvdDI6OmdncGxvdCjlr77op5Lnt5rjg4fjg7zjgr8sIGdncGxvdDI6OmFlcyh4ID0geF9tZWFuLCB5ID0geV9tZWFuKSkgKwogIGdncGxvdDI6Omdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbGluZXdpZHRoID0gMC42MCkgKwogIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuMjUpICsKICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjI1KSArCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc2l6ZSA9IDIuMikgKwogIGdncGxvdDI6Omdlb21fdGV4dChkYXRhID0g44Op44OZ44Or5a++6LGhLCBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsYWJlbCksIHNpemUgPSAyLjYsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCB2anVzdCA9IC0wLjcpICsKICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4g5q+U6LyDLCBuY29sID0gMykgKwogIGdncGxvdDI6OmNvb3JkX2VxdWFsKHhsaW0gPSBjKC3ou7jnr4Tlm7IsIOi7uOevhOWbsiksIHlsaW0gPSBjKC3ou7jnr4Tlm7IsIOi7uOevhOWbsikpICsKICBnZ3Bsb3QyOjpsYWJzKHggPSAi5bem5YG05p2h5Lu244Gu5qiZ5rqW5YyW5YWx5aSJ6YeP5bmz5Z2HIiwgeSA9ICLlj7PlgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciKSArCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKwogIGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkpCuWbs0M4CmBgYAoKYGBge3IgYjMtYmFsYW5jZS1zdW1tYXJ5LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KGoQzEwIDwtIGFzc2lnbm1lbnRfYmFsYW5jZV9yZXN1bHRzJHN0dWR5MyRzdW1tYXJ5ICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDlpInmlbAgPSBsYWJlbCwKICAgIGAy6YG45oqe6IKi5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzIsIDMpLAogICAgYDPpgbjmip7ogqLmnaHku7bjga7lubPlnYdgID0gcm91bmQobWVhbl9jb25kaXRpb25fMywgMyksCiAgICBgNOmBuOaKnuiCouadoeS7tuOBruW5s+Wdh2AgPSByb3VuZChtZWFuX2NvbmRpdGlvbl80LCAzKSwKICAgIGA16YG45oqe6IKi5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzUsIDMpLAogICAgYOacgOWkp3xTTUR8YCA9IHJvdW5kKG1heF9hYnNfc21kLCAzKSwKICAgIGBIb2xt6KOc5q2jcOWApGAgPSBzaWduaWYocF9ob2xtLCAzKQogICkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahDMTApLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIOWbs0M577ya44OX44Ot44OV44Kj44O844Or5bGe5oCn5rC05rqW44Gu54Sh5L2c54K65o+Q56S6Cgrlm7NDOeOBr+WbnuetlOiAheOBruadoeS7tuWJsuS7mOOBp+OBr+OBquOBj+OAgeWQhOOCs+ODs+OCuOODp+OCpOODs+ODiOiqsumhjOWGheOBp+WxnuaAp+awtOa6luOBjOioreioiOOBqeOBiuOCiuS4gOanmOOBq+aPkOekuuOBleOCjOOBpuOBhOOCi+OBi+OCkueiuuiqjeOBmeOCi+OCguOBruOBp+OBguOCi+OAggoKYGBge3IgYjMtcHJvZmlsZS1yYW5kb21pemF0aW9uLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5bGe5oCn6aC75bqmIDwtIHByb2ZpbGVfcmFuZG9taXphdGlvbl9yZXN1bHRzJHN0dWR5MyRmcmVxdWVuY3kgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnihhdHRyaWJ1dGUpLAogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTMiKQogICkKCuihqOekuuODqeODmeODqyA8LSDlsZ7mgKfpoLvluqYgJT4lCiAgZHBseXI6Omdyb3VwX2J5KOWxnuaApywg5p2h5Lu2KSAlPiUKICBkcGx5cjo6c2xpY2VfbWF4KGFic19kZXZpYXRpb24sIG4gPSAyLCB3aXRoX3RpZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnVuZ3JvdXAoKQoK5ZuzQzkgPC0gZ2dwbG90Mjo6Z2dwbG90KOWxnuaAp+mgu+W6piwgZ2dwbG90Mjo6YWVzKHggPSBleHBlY3RlZF9zaGFyZSwgeSA9IG9ic2VydmVkX3NoYXJlLCBzaGFwZSA9IOadoeS7tikpICsKICBnZ3Bsb3QyOjpnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNjUpICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNpemUgPSAyLjIsIGZpbGwgPSAid2hpdGUiKSArCiAgZ2dwbG90Mjo6Z2VvbV90ZXh0KGRhdGEgPSDooajnpLrjg6njg5njg6ssIGdncGxvdDI6OmFlcyhsYWJlbCA9IGxldmVsKSwgc2l6ZSA9IDIuNCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIHZqdXN0ID0gLTAuNykgKwogIGdncGxvdDI6OmZhY2V0X3dyYXAofiDlsZ7mgKcsIG5jb2wgPSAzKSArCiAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoKSArCiAgZ2dwbG90Mjo6bGFicyh4ID0gIuioreioiOS4iuOBruacn+W+heavlOeOhyIsIHkgPSAi6Kaz5ris5q+U546HIiwgc2hhcGUgPSAi5p2h5Lu2IikgKwogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsKICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikK5ZuzQzkKYGBgCgpgYGB7ciBiMy1yYW5kb21pemF0aW9uLXRhYmxlcywgZWNobz1UUlVFLCBldmFsPVRSVUV9CuihqEMxMSA8LSBwcm9maWxlX3JhbmRvbWl6YXRpb25fcmVzdWx0cyRzdHVkeTMkdW5pZm9ybWl0eV90ZXN0cyAlPiUKICBkcGx5cjo6dHJhbnNtdXRlKAogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTMiKSwKICAgIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnihhdHRyaWJ1dGUpLAogICAgYOOCq+OCpOS6jOS5l+WApGAgPSByb3VuZChjaGlfc3F1YXJlLCAzKSwKICAgIOiHqueUseW6piA9IGRmLAogICAgcOWApCA9IHNpZ25pZihwX3ZhbHVlLCAzKSwKICAgIGBIb2xt6KOc5q2jcOWApGAgPSBzaWduaWYocF9ob2xtLCAzKSwKICAgIGDmnIDlpKfntbblr77mr5Tnjoflt65gID0gcm91bmQobWF4X2Fic19zaGFyZV9kZXZpYXRpb24sIDQpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEMxMSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpCgrooahDMTIgPC0g5bGe5oCn6aC75bqmICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDmnaHku7YsCiAgICDlsZ7mgKcsCiAgICDmsLTmupYgPSBsZXZlbCwKICAgIOims+a4rOaVsCA9IG9ic2VydmVkX24sCiAgICDnt4/mlbAgPSB0b3RhbF9uLAogICAg6Kaz5ris5q+U546HID0gcm91bmQob2JzZXJ2ZWRfc2hhcmUsIDQpLAogICAg5pyf5b6F5q+U546HID0gcm91bmQoZXhwZWN0ZWRfc2hhcmUsIDQpLAogICAg5beuID0gcm91bmQoZGV2aWF0aW9uLCA0KQogICkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahDMTIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIEMuNCDmqJnmnKzmuJvlsJHjgajjgrnjgq/jg6rjg7zjg4vjg7PjgrAKCuS7peS4i+OBruaomeacrOa4m+WwkeihqOOBp+OBr+OAgeWQhOOCueOCr+ODquODvOODi+ODs+OCsOautemajuOBq+WvvuW/nOOBmeOCiyoq6Kq/5p+756Wo5LiK44Gu6LOq5ZWP5paH77yI6KaB57SE77yJKirjgpLkvbXoqJjjgZnjgovjgILos6rllY/mlofjga/ooajjga7lj6/oqq3mgKfjgpLkv53jgaTjgZ/jgoHnsKHmvZTjgavnpLrjgZfjgIHljp/mlofjga7lrozlhajjgaros6rllY/mlofjg7vlm57nrZTpgbjmip7ogqLjg7vjgrPjg7Pjgrjjg6fjgqTjg7Pjg4joqrLpoYzjga7mj5DnpLrlvaLlvI/jga8qKuijnOmBukrjgIzoqr/mn7vnpajjgI0qKuOBq+OBvuOBqOOCgeOBpuaOsui8ieOBmeOCi+OAggoKIyMjIOWun+mokzHvvIgyMDIz5bm077yJCgpgYGB7ciBiNC1zdHVkeTEtc2NyZWVuaW5nLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5a6f6aiTMeaomeacrOa4m+WwkSA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfc2FtcGxlX2F0dHJpdGlvbi5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIOautemajiA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCjmrrXpmo4sIGMoImNob2ljZV90YXNrKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIiwgIkNob2ljZSB0YXNrIChbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIpKQogICkgJT4lCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkKa25pdHI6OmthYmxlKOWun+mokzHmqJnmnKzmuJvlsJEsIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzEz77ya5a6f6aiTMeOBruaomeacrOa4m+WwkSIpCgrlrp/pqJMx5p2h5Lu25Yil5qiZ5pysIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MSIsICJ0YWJsZV9zYW1wbGVfYXR0cml0aW9uX2J5X2NvbmRpdGlvbi5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTEiKSwKICAgIOautemajiA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCjmrrXpmo4sIGMoImNob2ljZV90YXNrKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIiwgIkNob2ljZSB0YXNrIChbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIpKQogICkgJT4lCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkKa25pdHI6OmthYmxlKOWun+mokzHmnaHku7bliKXmqJnmnKwsIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzE077ya5a6f6aiTMeOBruadoeS7tuWIpeaomeacrOa4m+WwkSIpCmBgYAoKCgojIyMg5a6f6aiTMu+8iDIwMjblubTvvIkKCmBgYHtyIGI0LXN0dWR5Mi1zY3JlZW5pbmcsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrlrp/pqJMy5qiZ5pys5rib5bCRIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9zYW1wbGVfYXR0cml0aW9uLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6bXV0YXRlKOautemajiA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCjmrrXpmo4sIGMoImNob2ljZV90YXNrKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIiwgIkNob2ljZSB0YXNrIChbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIpKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkKa25pdHI6OmthYmxlKOWun+mokzLmqJnmnKzmuJvlsJEsIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzE377ya5a6f6aiTMuOBruaomeacrOa4m+WwkSIpCgrlrp/pqJMy5p2h5Lu25Yil5qiZ5pysIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9zYW1wbGVfYXR0cml0aW9uX2J5X2NvbmRpdGlvbi5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkyIiksIOautemajiA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCjmrrXpmo4sIGMoImNob2ljZV90YXNrKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIiwgIkNob2ljZSB0YXNrIChbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIpKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkKa25pdHI6OmthYmxlKOWun+mokzLmnaHku7bliKXmqJnmnKwsIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzE477ya5a6f6aiTMuOBruadoeS7tuWIpeaomeacrOa4m+WwkSIpCgrlrp/pqJMy5pON5L2c56K66KqNIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9tYW5pcHVsYXRpb25fY2hlY2suY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2IiwgcmVzcG9uc2UgPSAi5Zue562UIiwgc3RhdHVzID0gIuWIpOWumiIsIG4gPSAiTiIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTIiKSwgZHBseXI6OmFjcm9zcyhkcGx5cjo6ZXZlcnl0aGluZygpLCB+IHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKSkpCmtuaXRyOjprYWJsZSjlrp/pqJMy5pON5L2c56K66KqNLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEMxOe+8muWun+mokzLjga7pgbjmip7ogqLmlbDmk43kvZznorroqo0iKQoK5a6f6aiTMuaMh+ekuumgheebriA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTIiLCAidGFibGVfYXR0ZW50aW9uX2NoZWNrLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCByZXNwb25zZSA9ICLlm57nrZTjgrPjg7zjg4kiLCBzdGF0dXMgPSAi5Yik5a6aIiwgbiA9ICJOIikpICU+JQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6ZXZlcnl0aGluZygpLCB+IHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKSkpCmtuaXRyOjprYWJsZSjlrp/pqJMy5oyH56S66aCF55uuLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEMyMO+8muWun+mokzLjga7mjIfnpLrpoIXnm64iKQpgYGAKCiMjIyDlrp/pqJMz77yIMjAyNuW5tO+8iQoKYGBge3IgYjQtc3R1ZHkzLXNjcmVlbmluZywgZWNobz1UUlVFLCBldmFsPVRSVUV9CuWun+mokzPmqJnmnKzmuJvlsJEgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb24uY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjptdXRhdGUo5q616ZqOID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKOautemajiwgYygiY2hvaWNlX3Rhc2soWzEtNV0pIiA9ICLpgbjmip7oqrLpoYxcXDEiLCAiQ2hvaWNlIHRhc2sgKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIikpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmV2ZXJ5dGhpbmcoKSwgfiB0aWR5cjo6cmVwbGFjZV9uYShhcy5jaGFyYWN0ZXIoLngpLCAi4oCUIikpKQprbml0cjo6a2FibGUo5a6f6aiTM+aomeacrOa4m+WwkSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahDMjHvvJrlrp/pqJMz44Gu5qiZ5pys5rib5bCRIikKCuWun+mokzPmnaHku7bliKXmqJnmnKwgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb25fYnlfY29uZGl0aW9uLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTMiKSwg5q616ZqOID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKOautemajiwgYygiY2hvaWNlX3Rhc2soWzEtNV0pIiA9ICLpgbjmip7oqrLpoYxcXDEiLCAiQ2hvaWNlIHRhc2sgKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIikpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmV2ZXJ5dGhpbmcoKSwgfiB0aWR5cjo6cmVwbGFjZV9uYShhcy5jaGFyYWN0ZXIoLngpLCAi4oCUIikpKQprbml0cjo6a2FibGUo5a6f6aiTM+adoeS7tuWIpeaomeacrCwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahDMjLvvJrlrp/pqJMz44Gu5p2h5Lu25Yil5qiZ5pys5rib5bCRIikKCuWun+mokzPmk43kvZznorroqo0gPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX21hbmlwdWxhdGlvbl9jaGVjay5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCByZXNwb25zZSA9ICLlm57nrZQiLCBzdGF0dXMgPSAi5Yik5a6aIiwgbiA9ICJOIikpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MyIpLCBkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkKa25pdHI6OmthYmxlKOWun+mokzPmk43kvZznorroqo0sIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzIz77ya5a6f6aiTM+OBrumBuOaKnuiCouaVsOaTjeS9nOeiuuiqjSIpCgrlrp/pqJMz5oyH56S66aCF55uuIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9hdHRlbnRpb25fY2hlY2suY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHJlc3BvbnNlID0gIuWbnuetlOOCs+ODvOODiSIsIHN0YXR1cyA9ICLliKTlrpoiLCBuID0gIk4iKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkKa25pdHI6OmthYmxlKOWun+mokzPmjIfnpLrpoIXnm64sIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzI077ya5a6f6aiTM+OBruaMh+ekuumgheebriIpCmBgYAoKIyBELiDmnKzmloflm7Pjga7lho3nj74KCuOBk+OBruevgOOBruWbs++8iOihqO+8ieeVquWPt+OBr+acrOaWh+OBqOS4gOiHtOOBl+OBn+OCguOBruOBp+OBguOCi+OAguacrOaWh+OBruWIhuaekOe1kOaenOOBp+eUqOOBhOOCi+Wbs+OBr+WbszTjgYvjgonlm7M544G+44Gn44Gn44GC44KK44CB5a6f6aiTMuOBrkFNQ0Xjga/mnKzmloflm7Pjgavjga/ooajnpLrjgZvjgZrjgIHoo5zpgbpF44Gr5o6y56S644GV44KM44Gm44GE44KL44CCCgojIyDlm7M077ya5a6f6aiTMe+8iDIwMjPlubTvvInjga7lhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFCgpgYGB7ciBjLWZpZzQsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrlm7M044OH44O844K/IDwtIHN0dWR5MV9lbnYkYW1jZV9wbG90X2RmX2Nvdl9mYWNldArlm7M0IDwtIGdncGxvdDI6OmdncGxvdCgKICDlm7M044OH44O844K/LAogIGdncGxvdDI6OmFlcyh4ID0gZXN0aW1hdGVfcHAsIHkgPSBsYWJlbCwgc2hhcGUgPSBwYXJ0eV9uLCBsaW5ldHlwZSA9IHBhcnR5X24sIGdyb3VwID0gcGFydHlfbikKKSArCiAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC40NSwgY29sb3IgPSAiZ3JleTM1IikgKwogIGdncGxvdDI6Omdlb21fZXJyb3JiYXJoKAogICAgZ2dwbG90Mjo6YWVzKHhtaW4gPSBjb25mLmxvd19wcCwgeG1heCA9IGNvbmYuaGlnaF9wcCksCiAgICBwb3NpdGlvbiA9IGdncGxvdDI6OnBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksIGhlaWdodCA9IDAuMTYsIGxpbmV3aWR0aCA9IDAuNTUKICApICsKICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwgc2l6ZSA9IDIuNSwgZmlsbCA9ICJ3aGl0ZSIsIHN0cm9rZSA9IDAuOCkgKwogIGdncGxvdDI6OmZhY2V0X2dyaWQoYXR0cmlidXRlX2ZhY2V0IH4gLiwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlID0gImZyZWVfeSIsIHN3aXRjaCA9ICJ5IikgKwogIGdncGxvdDI6OnNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKCIy5pS/5YWaIiA9IDE2LCAiM+aUv+WFmiIgPSAxNywgIjTmlL/lhZoiID0gMTUsICI15pS/5YWaIiA9IDEpKSArCiAgZ2dwbG90Mjo6c2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoIjLmlL/lhZoiID0gInNvbGlkIiwgIjPmlL/lhZoiID0gImRhc2hlZCIsICI05pS/5YWaIiA9ICJkb3R0ZWQiLCAiNeaUv+WFmiIgPSAiZG90ZGFzaCIpKSArCiAgZ2dwbG90Mjo6bGFicyh4ID0gIumBuOaKnueiuueOh+OBruWkieWMliIsIHkgPSBOVUxMLCBzaGFwZSA9ICLmlL/lhZrmlbDmnaHku7YiLCBsaW5ldHlwZSA9ICLmlL/lhZrmlbDmnaHku7YiKSArCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpICsKICBnZ3Bsb3QyOjp0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgcGFuZWwuZ3JpZC5tYWpvci55ID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpKQrlm7M0CgrooahEMSA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0gcGFzdGUwKHN0cmluZ3I6OnN0cl9yZW1vdmUo5p2h5Lu2LCAi5p2h5Lu2JCIpLCAi5p2h5Lu2IikpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQx77ya5ZuzNOOBq+WvvuW/nOOBmeOCi+WFseWkiemHj+iqv+aVtOa4iOOBv0FNQ0UiKQpgYGAKCiMjIOWbszXvvJrlrp/pqJMx77yIMjAyM+W5tO+8ieOBruaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjQoKYGBge3IgYy1maWc1LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5ZuzNemHjeimgeW6puODh+ODvOOCvyA8LSBzdHVkeTFfZW52JHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGEK5ZuzNeebuOWvvuavlOmHjeODh+ODvOOCvyA8LSBzdHVkeTFfZW52JHJlbGF0aXZlX3BhbmVsX2JfZGF0YQrlm7M144OR44ON44OrQSA8LSBzdHVkeTFfZW52JHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkCuWbszXjg5Hjg43jg6tCIDwtIHN0dWR5MV9lbnYkcmVsYXRpdmVfcGFuZWxfYwrlm7M1IDwtICjlm7M144OR44ON44OrQSB8IOWbszXjg5Hjg43jg6tCKSArIHBhdGNod29yazo6cGxvdF9sYXlvdXQod2lkdGhzID0gYygxLCAxKSkK5ZuzNQoK6KGoRDIgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkxIiwgInRhYmxlX21hcmdpbmFsX21lYW5zLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLCBsZXZlbCA9ICLmsLTmupYiKSkgJT4lCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkxIiksIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnijlsZ7mgKcpKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQyKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahEMu+8mumZkOeVjOW5s+WdhyIpCgrooahEMyA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfYXR0cmlidXRlX2ltcG9ydGFuY2UuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2IiwgYXR0cmlidXRlID0gIuWxnuaApyIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTEiKSwg5bGe5oCnID0g5bGe5oCn5pel5pys6KqeKOWxnuaApykpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDMpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQz77ya5bGe5oCn6YeN6KaB5bqmIikKCuihqEQ0IDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MSIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBzdGF0aXN0aWMgPSAi5oyH5qiZIikpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MSIpLCDmjIfmqJkgPSDntbHoqIjph4/ml6XmnKzoqp4o5oyH5qiZLCAic3R1ZHkxIikpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDQpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQ077ya5pS/5YWa44O757WM5riI5omL44GM44GL44KK44Gu6YeN6KaB5bqm44Go55u45a++5q+U6YeNIikKYGBgCgojIyDlm7M277ya5a6f6aiTMu+8iDIwMjblubTvvInjga7mlL/lhZrjg7vntYzmuIjmiYvjgYzjgYvjgorjga7ph43opoHluqbjgajnm7jlr77mr5Tph40KCmBgYHtyIGMtZmlnNiwgZWNobz1UUlVFLCBldmFsPVRSVUV9CuWbszbph43opoHluqbjg4fjg7zjgr8gPC0gc3R1ZHkyX2VudiRyZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhCuWbszbnm7jlr77mr5Tph43jg4fjg7zjgr8gPC0gc3R1ZHkyX2VudiRyZWxhdGl2ZV9wYW5lbF9iX2RhdGEK5ZuzNuODkeODjeODq0EgPC0gc3R1ZHkyX2VudiRyZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZArlm7M244OR44ON44OrQiA8LSBzdHVkeTJfZW52JHJlbGF0aXZlX3BhbmVsX2MK5ZuzNiA8LSAo5ZuzNuODkeODjeODq0EgfCDlm7M244OR44ON44OrQikgKyBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMSwgMSkpCuWbszYKCuihqEQ1IDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9tYXJnaW5hbF9tZWFucy5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBhdHRyaWJ1dGUgPSAi5bGe5oCnIiwgbGV2ZWwgPSAi5rC05rqWIikpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MiIpLCDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4o5bGe5oCnKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahENSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoRDXvvJrpmZDnlYzlubPlnYciKQoK6KGoRDYgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkyIiwgInRhYmxlX2F0dHJpYnV0ZV9pbXBvcnRhbmNlLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciKSkgJT4lCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkyIiksIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnijlsZ7mgKcpKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQ2KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahENu+8muWxnuaAp+mHjeimgeW6piIpCgrooahENyA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTIiLCAidGFibGVfY3VlX2ltcG9ydGFuY2UuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2Iiwgc3RhdGlzdGljID0gIuaMh+aomSIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTIiKSwg5oyH5qiZID0g57Wx6KiI6YeP5pel5pys6KqeKOaMh+aomSwgInN0dWR5MiIpKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQ3KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahEN++8muaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIpCmBgYAoKIyMg5ZuzN++8muWun+mokzPvvIgyMDI25bm077yJ44Gu5YWx5aSJ6YeP6Kq/5pW05riI44G/QU1DRQoKYGBge3IgYy1maWc3LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5ZuzN+ODh+ODvOOCvyA8LSBzdHVkeTNfZW52JGFtY2VfcGxvdF9jb3YK5ZuzNyA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoCiAg5ZuzN+ODh+ODvOOCvywKICBnZ3Bsb3QyOjphZXMoeCA9IGVzdGltYXRlX3BwLCB5ID0gbGFiZWwsIHNoYXBlID0gcGFydHlfbiwgbGluZXR5cGUgPSBwYXJ0eV9uLCBncm91cCA9IHBhcnR5X24pCikgKwogIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuNDUsIGNvbG9yID0gImdyZXkzNSIpICsKICBnZ3Bsb3QyOjpnZW9tX2Vycm9yYmFyaCgKICAgIGdncGxvdDI6OmFlcyh4bWluID0gY29uZi5sb3dfcHAsIHhtYXggPSBjb25mLmhpZ2hfcHApLAogICAgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLCBoZWlnaHQgPSAwLjE2LCBsaW5ld2lkdGggPSAwLjU1CiAgKSArCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChwb3NpdGlvbiA9IGdncGxvdDI6OnBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksIHNpemUgPSAyLjUsIGZpbGwgPSAid2hpdGUiLCBzdHJva2UgPSAwLjgpICsKICBnZ3Bsb3QyOjpmYWNldF9ncmlkKGF0dHJpYnV0ZSB+IC4sIHNjYWxlcyA9ICJmcmVlX3kiLCBzcGFjZSA9ICJmcmVlX3kiLCBzd2l0Y2ggPSAieSIpICsKICBnZ3Bsb3QyOjpzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygiMumBuOaKnuiCoiIgPSAxNiwgIjPpgbjmip7ogqIiID0gMTcsICI06YG45oqe6IKiIiA9IDE1LCAiNemBuOaKnuiCoiIgPSAxKSkgKwogIGdncGxvdDI6OnNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKCIy6YG45oqe6IKiIiA9ICJzb2xpZCIsICIz6YG45oqe6IKiIiA9ICJkYXNoZWQiLCAiNOmBuOaKnuiCoiIgPSAiZG90dGVkIiwgIjXpgbjmip7ogqIiID0gImRvdGRhc2giKSkgKwogIGdncGxvdDI6OmxhYnMoeCA9ICLpgbjmip7norrnjofjga7lpInljJYiLCB5ID0gTlVMTCwgc2hhcGUgPSAi6YG45oqe6IKi5pWwIiwgbGluZXR5cGUgPSAi6YG45oqe6IKi5pWwIikgKwogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArCiAgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIHBhbmVsLmdyaWQubWFqb3IueSA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkK5ZuzNwoK6KGoRDggPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IHBhc3RlMChzdHJpbmdyOjpzdHJfcmVtb3ZlKOadoeS7tiwgIuadoeS7tiQiKSwgIuadoeS7tiIpKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQ4KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahEOO+8muWbszfjgavlr77lv5zjgZnjgovlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIikKYGBgCgojIyDlm7M477ya5a6f6aiTM++8iDIwMjblubTvvInjga7mlL/lhZrlkI3jg7vntYzmuIjmiYvjgYzjgYvjgorjga7ph43opoHluqbjgajnm7jlr77mr5Tph40KCmBgYHtyIGMtZmlnOCwgZWNobz1UUlVFLCBldmFsPVRSVUV9CuWbszjph43opoHluqbjg4fjg7zjgr8gPC0gc3R1ZHkzX2VudiRyZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhCuWbszjnm7jlr77mr5Tph43jg4fjg7zjgr8gPC0gc3R1ZHkzX2VudiRyZWxhdGl2ZV9wYW5lbF9iX2RhdGEK5ZuzOOODkeODjeODq0EgPC0gc3R1ZHkzX2VudiRyZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZArlm7M444OR44ON44OrQiA8LSBzdHVkeTNfZW52JHJlbGF0aXZlX3BhbmVsX2MK5ZuzOCA8LSAo5ZuzOOODkeODjeODq0EgfCDlm7M444OR44ON44OrQikgKyBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMSwgMSkpCuWbszgKCuihqEQ5IDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9tYXJnaW5hbF9tZWFucy5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBhdHRyaWJ1dGUgPSAi5bGe5oCnIiwgbGV2ZWwgPSAi5rC05rqWIikpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MyIpLCDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4o5bGe5oCnKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahEOSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoRDnvvJrpmZDnlYzlubPlnYciKQoK6KGoRDEwIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBhdHRyaWJ1dGUgPSAi5bGe5oCnIikpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MyIpLCDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4o5bGe5oCnKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahEMTApLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQxMO+8muWxnuaAp+mHjeimgeW6piIpCgrooahEMTEgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX2N1ZV9pbXBvcnRhbmNlLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIHN0YXRpc3RpYyA9ICLmjIfmqJkiKSkgJT4lCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkzIiksIOaMh+aomSA9IOe1seioiOmHj+aXpeacrOiqnijmjIfmqJksICJzdHVkeTMiKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahEMTEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQxMe+8muaUv+WFmuWQjeODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIpCmBgYAoKIyMg5ZuzOe+8muWun+mokzPvvIgyMDI25bm077yJ44Gu5pSv5oyB5pS/5YWa44Go5o+Q56S65pS/5YWa5ZCN44Gu5LiA6Ie05Yq55p6cCgpgYGB7ciBjLWZpZzksIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrlm7M5IDwtIHN0dWR5M19lbnYkcF9wYXJ0eV9tYXRjaArlm7M5CgrooahEMTLlhYMgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX3BhcnR5X21hdGNoLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQoK6KGoRDEy5p2h5Lu25YiXIDwtIGludGVyc2VjdChjKCLpgbjmip7ogqLmlbAiLCAi5p2h5Lu2IiwgInBhcnR5X24iKSwgbmFtZXMo6KGoRDEy5YWDKSkKaWYgKGxlbmd0aCjooahEMTLmnaHku7bliJcpID09IDApIHN0b3AoIkNoZWNrIGNvbmRpdGlvbiBjb2x1bW4iKQrooahEMTLmnaHku7bliJcgPC0g6KGoRDEy5p2h5Lu25YiXW1sxXV0KCmlmICghIuWbnuetlOiAheaVsCIgJWluJSBuYW1lcyjooahEMTLlhYMpKSB7CiAg6KGoRDEy5YWDJOWbnuetlOiAheaVsCA8LSBOQV9jaGFyYWN0ZXJfCn0KCuWun+mokzPmnaHku7bkurrmlbAgPC0gc3R1ZHkzX2VudiRjb25qb2ludF9hbGxfbSAlPiUKICBkcGx5cjo6ZGlzdGluY3QoSUQsIHBhcnR5X24pICU+JQogIGRwbHlyOjpjb3VudChwYXJ0eV9uLCBuYW1lID0gIuWbnuetlOiAheaVsOijnOWujCIpCgrooahEMTIgPC0g6KGoRDEy5YWDICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu25pWwID0g5pWw5YCk5YiXKC5kYXRhW1vooahEMTLmnaHku7bliJddXSkpICU+JQogIGRwbHlyOjpzZWxlY3QoLWRwbHlyOjphbGxfb2Yo6KGoRDEy5p2h5Lu25YiXKSkgJT4lCiAgZHBseXI6OmxlZnRfam9pbijlrp/pqJMz5p2h5Lu25Lq65pWwLCBieSA9IGMoIuadoeS7tuaVsCIgPSAicGFydHlfbiIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAg5Zue562U6ICF5pWwID0gZHBseXI6OmNvYWxlc2NlKOaVsOWApOWIlyjlm57nrZTogIXmlbApLCDlm57nrZTogIXmlbDoo5zlrowpLAogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tuaVsCwgInN0dWR5MyIpCiAgKSAlPiUKICBkcGx5cjo6c2VsZWN0KC3mnaHku7bmlbAsIC3lm57nrZTogIXmlbDoo5zlrowpICU+JQogIGRwbHlyOjpyZWxvY2F0ZSjmnaHku7YsIC5hZnRlciA9IOWvvuixoSkKCmtuaXRyOjprYWJsZSgKICDooajml6XmnKzoqp4o6KGoRDEyKSwKICBmb3JtYXQgPSAiaHRtbCIsCiAgcm93Lm5hbWVzID0gRkFMU0UsCiAgY2FwdGlvbiA9ICLooahEMTLvvJrmlK/mjIHmlL/lhZrjgajmj5DnpLrmlL/lhZrlkI3jga7kuIDoh7TlirnmnpwiCikKYGBgCgojIEUuIOWun+mokzHvvIgyMDIz5bm077yJ44Gu6KOc6Laz5YiG5p6QCgojIyDoo5zlm7NFMe+8muWFseWkiemHj+OCkuWQq+OCgeOBquOBhEFNQ0UKCmBgYHtyIGQxLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KOc5ZuzRTHjg4fjg7zjgr8gPC0gc3R1ZHkxX2VudiRhbWNlX3Bsb3RfZGZfbm9jb3ZfZmFjZXQK6KOc5ZuzRTEgPC0gc3R1ZHkxX2VudiRwX2FtY2VfZmFjZXRfbm9jb3YK6KOc5ZuzRTEKCuihqEUxIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MSIsICJ0YWJsZV9hbWNlX3VuYWRqdXN0ZWQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0gcGFzdGUwKHN0cmluZ3I6OnN0cl9yZW1vdmUo5p2h5Lu2LCAi5p2h5Lu2JCIpLCAi5p2h5Lu2IikpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRTEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIOijnOWbs0Uy77yaMuaUv+WFmuadoeS7tuOBqOOBruW3rgoKYGBge3IgZDIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQroo5zlm7NFMuODh+ODvOOCvyA8LSBzdHVkeTFfZW52JGludGVyYWN0aW9uX3Bsb3RfZGYK6KOc5ZuzRTIgPC0gc3R1ZHkxX2VudiRwX2ludGVyYWN0aW9uCuijnOWbs0UyCgrooahFMiA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfYW1jZV9pbnRlcmFjdGlvbi5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgYXR0cmlidXRlID0gIuWxnuaApyIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmFueV9vZigi5bGe5oCnIiksIOWxnuaAp+aXpeacrOiqnikpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRTIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIOijnOWbs0Uz77ya5p2h5Lu25LuY44GN44Ot44K444OD44OICgpgYGB7ciBkMywgZWNobz1UUlVFLCBldmFsPVRSVUV9CuijnOWbs0UzIDwtIHN0dWR5MV9lbnYkcF9jbG9naXRfb3IK6KOc5ZuzRTMKCuihqEUzIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MSIsICJ0YWJsZV9jb25kaXRpb25hbF9sb2dpdC5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBhdHRyaWJ1dGUgPSAi5bGe5oCnIiwgbGFiZWwgPSAi5rC05rqWIikpICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICDmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkxIiksCiAgICDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4o5bGe5oCnKQogICkgJT4lCiAgZHBseXI6OnNlbGVjdCgtZHBseXI6OmFueV9vZihjKCJ0ZXJtIiwgInZhcmlhYmxlIiwgInBvbGljeV9wb3NpdGlvbiIsICJnb3Zlcm5tZW50X3N0YXR1cyIpKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahFMyksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyBGLiDlrp/pqJMy77yIMjAyNuW5tO+8ieOBruijnOi2s+WIhuaekAoK5pys5paH44Gn44Gv5a6f6aiTMuOBrkFNQ0Xjga7mlrnlkJHmgKfjgpLoqJjov7DjgZfjgIHoqbPntLDjgpLoo5zpgbrjgavlm57jgZfjgabjgYTjgovjgZ/jgoHjgIHlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNF44KS6KOc5ZuzRjHjgajjgZfjgabmnIDliJ3jgavnpLrjgZnjgIIKCiMjIOijnOWbs0Yx77ya5YWx5aSJ6YeP6Kq/5pW05riI44G/QU1DRQoKYGBge3IgZTEsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQroo5zlm7NGMeODh+ODvOOCvyA8LSBzdHVkeTJfZW52JGFtY2VfcGxvdF9kZl9jb3ZfZmFjZXQK6KOc5ZuzRjEgPC0gc3R1ZHkyX2VudiRwX2FtY2VfY292X2ZhY2V0CuijnOWbs0YxCgrooahGMSA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTIiLCAidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0gcGFzdGUwKHN0cmluZ3I6OnN0cl9yZW1vdmUo5p2h5Lu2LCAi5p2h5Lu2JCIpLCAi5p2h5Lu2IikpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRjEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIOijnOWbs0Yy77ya5YWx5aSJ6YeP44KS5ZCr44KB44Gq44GEQU1DRQoKYGBge3IgZTIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQroo5zlm7NGMuODh+ODvOOCvyA8LSBzdHVkeTJfZW52JGFtY2VfcGxvdF9kZl9ub2Nvdl9mYWNldAroo5zlm7NGMiA8LSBzdHVkeTJfZW52JHBfYW1jZV9mYWNldF9ub2Nvdgroo5zlm7NGMgoK6KGoRjIgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkyIiwgInRhYmxlX2FtY2VfdW5hZGp1c3RlZC5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSBwYXN0ZTAoc3RyaW5ncjo6c3RyX3JlbW92ZSjmnaHku7YsICLmnaHku7YkIiksICLmnaHku7YiKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahGMiksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMg6KOc5ZuzRjPvvJoy5pS/5YWa5p2h5Lu244Go44Gu5beuCgpgYGB7ciBlMywgZWNobz1UUlVFLCBldmFsPVRSVUV9CuijnOWbs0Yz44OH44O844K/IDwtIHN0dWR5Ml9lbnYkaW50ZXJhY3Rpb25fcGxvdF9kZgroo5zlm7NGMyA8LSBzdHVkeTJfZW52JHBfaW50ZXJhY3Rpb24K6KOc5ZuzRjMKCuihqEYzIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9hbWNlX2ludGVyYWN0aW9uLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBhdHRyaWJ1dGUgPSAi5bGe5oCnIikpICU+JQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6YW55X29mKCLlsZ7mgKciKSwg5bGe5oCn5pel5pys6KqeKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahGMyksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMg6KOc5ZuzRjTvvJrmnaHku7bku5jjgY3jg63jgrjjg4Pjg4gKCmBgYHtyIGU0LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KOc5ZuzRjQgPC0gc3R1ZHkyX2VudiRwX2Nsb2dpdF9vcgroo5zlm7NGNAoK6KGoRjQgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkyIiwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLCBsYWJlbCA9ICLmsLTmupYiKSkgJT4lCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkyIiksIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnijlsZ7mgKcpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1kcGx5cjo6YW55X29mKGMoInRlcm0iLCAidmFyaWFibGUiLCAicG9saWN5X3Bvc2l0aW9uIiwgImdvdmVybm1lbnRfc3RhdHVzIikpKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEY0KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIEcuIOWun+mokzPvvIgyMDI25bm077yJ44Gu6KOc6Laz5YiG5p6QCgojIyDoo5zlm7NHMe+8muWFseWkiemHj+OCkuWQq+OCgeOBquOBhEFNQ0UKCmBgYHtyIGYxLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KOc5ZuzRzHjg4fjg7zjgr8gPC0gc3R1ZHkzX2VudiRhbWNlX3Bsb3Rfbm9jb3YK6KOc5ZuzRzEgPC0gc3R1ZHkzX2VudiRwX2FtY2Vfbm9jb3YK6KOc5ZuzRzEKCuihqEcxIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9hbWNlX3VuYWRqdXN0ZWQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0gcGFzdGUwKHN0cmluZ3I6OnN0cl9yZW1vdmUo5p2h5Lu2LCAi5p2h5Lu2JCIpLCAi5p2h5Lu2IikpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRzEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIOijnOWbs0cy77yaMumBuOaKnuiCouadoeS7tuOBqOOBruW3rgoKYGBge3IgZjIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQroo5zlm7NHMiA8LSBzdHVkeTNfZW52JHBfaW50ZXJhY3Rpb24K6KOc5ZuzRzIKCuihqEcyIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9hbWNlX2ludGVyYWN0aW9uLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBhdHRyaWJ1dGUgPSAi5bGe5oCnIikpICU+JQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6YW55X29mKCLlsZ7mgKciKSwg5bGe5oCn5pel5pys6KqeKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahHMiksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMg6KOc5ZuzRzPvvJpBTUNF44Gu57ea5b2i44OI44Os44Oz44OJCgpgYGB7ciBmMywgZWNobz1UUlVFLCBldmFsPVRSVUV9CuijnOWbs0czIDwtIHN0dWR5M19lbnYkcF9saW5lYXJfdHJlbmQK6KOc5ZuzRzMKCuihqEczIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9hbWNlX2xpbmVhcl90cmVuZC5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgYXR0cmlidXRlID0gIuWxnuaApyIsIGxhYmVsID0gIuawtOa6liIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmFueV9vZigi5bGe5oCnIiksIOWxnuaAp+aXpeacrOiqnikpICU+JQogIGRwbHlyOjpzZWxlY3QoLWRwbHlyOjphbnlfb2YoYygidGVybSIsICJ2YXJpYWJsZSIpKSkKa25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahHMyksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMg6KOc5ZuzRzTvvJrmnaHku7bku5jjgY3jg63jgrjjg4Pjg4gKCmBgYHtyIGY0LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KOc5ZuzRzQgPC0gc3R1ZHkzX2VudiRwX2Nsb2dpdF9vcgroo5zlm7NHNAoK6KGoRzQgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLCBsYWJlbCA9ICLmsLTmupYiKSkgJT4lCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkzIiksIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnijlsZ7mgKcpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1kcGx5cjo6YW55X29mKGMoInRlcm0iLCAidmFyaWFibGUiKSkpCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRzQpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMgSC4g5pS/5YWa5pSv5oyB44Gr44KI44KL55Ww6LOq5oCnCgrmlK/mjIHmlL/lhZrliKVBTUNF44Gn44Gv44CB5ZCE5p2h5Lu244Gr6Kmy5b2T44GZ44KL5Zue562U6ICF5pWw44GMNDDkurrmnKrmuoDjga7jgrvjg6vjga/mjqjlrprlr77osaHlpJbjgajjgZfjgabjgYTjgovjgILjgZfjgZ/jgYzjgaPjgabjgIHku6XkuIvjgafjga8gYGluc3VmZmljaWVudF9jZWxsX25gIOOCkk5B44Gu44G+44G+6KGo56S644Gb44Ga44CB5o6o5a6a5Y+v6IO944Gn44GC44Gj44Gf5pSv5oyB5pS/5YWaw5fpgbjmip7ogqLmlbDmnaHku7bjga7jgb/jgpLmjrLovInjgZnjgovjgIIKCiMjIOijnOWbs0gx77ya5pSv5oyB5pS/5YWa5YilQU1DRQoK6KOc5ZuzSDHjga/jgIHmlK/mjIHmlL/lhZrjgavjgojjgotBTUNF44Gu55Ww6LOq5oCn44KS5a6f6aiT44GU44Go44Gr56S644GZ44CC5Y+v6Kqt5oCn44Gu44Gf44KB44CB57WQ5p6c44Gv5a6f6aiTMeODuzLjg7sz44Gr5YiG44GR44CBKiox44Gk44Gu44OR44ON44Or44KSMeOBpOOBruaUr+aMgeaUv+WFmuOBq+WvvuW/nOOBleOBm+OCiyoq44CC57im6Lu444Gr44Gv5bGe5oCn5ZCN44Go5rC05rqW5ZCN44KS5LiA5L2T44Go44GX44Gm6KGo56S644GX44CB5ZCM5LiA44Gu5pSv5oyB5pS/5YWa44Gr44Gk44GE44Gm5ZCE5bGe5oCn44O75rC05rqW44Gu5o6o5a6a57WQ5p6c44KS5LiK44GL44KJ6aCG44Gr56K66KqN44Gn44GN44KL44KI44GG44Gr44GX44Gf44CC54K544GvQU1DReOAgeaoque3muOBrzk1JeS/oemgvOWMuumWk+OCkuekuuOBl+OAgeeCueOBruW9ouOBp+mBuOaKnuiCouaVsOadoeS7tuOCkuWMuuWIpeOBmeOCi+OAggoK5a++5b+c6KGo44KC5a6f6aiT44GU44Go44Gr5YiG44GR44CB6YG45oqe6IKi5pWw5p2h5Lu244KS5YiX5pa55ZCR44Gr5bGV6ZaL44GZ44KL44CC5ZCE44K744Or44GvICoqQU1DRSBbOTUlIENJXe+8iHBw77yJKiog44KS56S644GX44CB5Zue562U6ICF5pWw44Gv5pSv5oyB5pS/5YWaw5fpgbjmip7ogqLmlbDmnaHku7bjgZTjgajjga7lsI/ooajjgajjgZfjgabliKXjgavnpLrjgZnjgILjgZPjga7lvaLlvI/jgavjgojjgorjgIHlkIzjgZjlsZ7mgKfjg7vmsLTmupbjgavjgaTjgYTjgaYy44O7M+ODuzTjg7s16YG45oqe6IKi5p2h5Lu244KS5qiq5pa55ZCR44Gr55u05o6l5q+U6LyD44Gn44GN44KL44CC6KGo56S66KGo44Gn44Gv5oOF5aCx44KS54K55o6o5a6a5YCk44GoOTUl5L+h6aC85Yy66ZaT44Gr6ZuG57SE44GX44CBcOWApOOCkuWQq+OCgOWujOWFqOOBquS/guaVsOihqOOBr+WQhOWun+mok+OBrkNTVuWHuuWKmyBgdGFibGVfcGFydHlfc3VwcG9ydF9hbWNlLmNzdmAg44Gr5L+d5a2Y44GZ44KL44CCCgpgYGB7ciBnMS1wcmVwYXJlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5pSv5oyBQU1DReS4gOimpyA8LSBkcGx5cjo6YmluZF9yb3dzKAogIHBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzJHN0dWR5MSRzdWJncm91cF9jb2VmZmljaWVudHMgJT4lCiAgICBkcGx5cjo6bXV0YXRlKOWun+mokyA9ICLlrp/pqJMx77yIMjAyM+W5tO+8iSIsIHN0dWR5X2lkID0gInN0dWR5MSIpLAogIHBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzJHN0dWR5MiRzdWJncm91cF9jb2VmZmljaWVudHMgJT4lCiAgICBkcGx5cjo6bXV0YXRlKOWun+mokyA9ICLlrp/pqJMy77yIMjAyNuW5tO+8iSIsIHN0dWR5X2lkID0gInN0dWR5MiIpLAogIHBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzJHN0dWR5MyRzdWJncm91cF9jb2VmZmljaWVudHMgJT4lCiAgICBkcGx5cjo6bXV0YXRlKOWun+mokyA9ICLlrp/pqJMz77yIMjAyNuW5tO+8iSIsIHN0dWR5X2lkID0gInN0dWR5MyIpCikgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgIHN0YXR1cyA9PSAiZXN0aW1hdGVkIiwKICAgICFpcy5uYSh0ZXJtKSwKICAgIHRlcm0gIT0gIihJbnRlcmNlcHQpIiwKICAgICFpcy5uYShlc3RpbWF0ZSkKICApICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICDlsZ7mgKfooajnpLogPSDlsZ7mgKfml6XmnKzoqp4oYXR0cmlidXRlKSwKICAgIOadoeS7tuihqOekuiA9IHB1cnJyOjptYXAyX2NocihwYXJ0eV9uLCBzdHVkeV9pZCwg5p2h5Lu25pel5pys6KqeKSwKICAgIOawtOa6luihqOekuiA9IOawtOa6luaXpeacrOiqnih0ZXJtLCBsYWJlbCwgYXR0cmlidXRlKSwKICAgIOihqOekuumgheebriA9IHBhc3RlMCjlsZ7mgKfooajnpLosICLvvJoiLCDmsLTmupbooajnpLopCiAgKQoK6KOc5ZuzSDHkvZzmiJAgPC0gZnVuY3Rpb24o5o+P55S744OH44O844K/LCDlrp/pqJPlkI0pIHsKICDpoIXnm67poIYgPC0g5o+P55S744OH44O844K/ICU+JQogICAgZHBseXI6OmRpc3RpbmN0KOWxnuaAp+ihqOekuiwg5rC05rqW6KGo56S6LCDooajnpLrpoIXnm64pICU+JQogICAgZHBseXI6OnB1bGwo6KGo56S66aCF55uuKQoKICDmnaHku7bpoIYgPC0g5o+P55S744OH44O844K/ICU+JQogICAgZHBseXI6OmRpc3RpbmN0KHBhcnR5X24sIOadoeS7tuihqOekuikgJT4lCiAgICBkcGx5cjo6YXJyYW5nZShwYXJ0eV9uKSAlPiUKICAgIGRwbHlyOjpwdWxsKOadoeS7tuihqOekuikKCiAg5o+P55S744OH44O844K/IDwtIOaPj+eUu+ODh+ODvOOCvyAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIOihqOekuumgheebriA9IGZhY3RvcijooajnpLrpoIXnm64sIGxldmVscyA9IHJldijpoIXnm67poIYpKSwKICAgICAg5p2h5Lu26KGo56S6ID0gZmFjdG9yKOadoeS7tuihqOekuiwgbGV2ZWxzID0g5p2h5Lu26aCGKQogICAgKQoKICBkb2RnZSA8LSBnZ3Bsb3QyOjpwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNTIpCgogIGdncGxvdDI6OmdncGxvdCgKICAgIOaPj+eUu+ODh+ODvOOCvywKICAgIGdncGxvdDI6OmFlcygKICAgICAgeCA9IGVzdGltYXRlX3BwLAogICAgICB5ID0g6KGo56S66aCF55uuLAogICAgICBzaGFwZSA9IOadoeS7tuihqOekugogICAgKQogICkgKwogICAgZ2dwbG90Mjo6Z2VvbV92bGluZSgKICAgICAgeGludGVyY2VwdCA9IDAsCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUKICAgICkgKwogICAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcmgoCiAgICAgIGdncGxvdDI6OmFlcygKICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsCiAgICAgICAgeG1heCA9IGNvbmYuaGlnaF9wcAogICAgICApLAogICAgICBoZWlnaHQgPSAwLjEyLAogICAgICBwb3NpdGlvbiA9IGRvZGdlLAogICAgICBsaW5ld2lkdGggPSAwLjU1CiAgICApICsKICAgIGdncGxvdDI6Omdlb21fcG9pbnQoCiAgICAgIHBvc2l0aW9uID0gZG9kZ2UsCiAgICAgIHNpemUgPSAyLjI1LAogICAgICBmaWxsID0gIndoaXRlIgogICAgKSArCiAgICBnZ3Bsb3QyOjpmYWNldF93cmFwKAogICAgICB+IHBhcnR5X3N1cHBvcnRfaCwKICAgICAgbmNvbCA9IDIsCiAgICAgIHNjYWxlcyA9ICJmcmVlX3kiCiAgICApICsKICAgIGdncGxvdDI6OmxhYnMoCiAgICAgIHRpdGxlID0g5a6f6aiT5ZCNLAogICAgICBzdWJ0aXRsZSA9ICLlkITjg5Hjg43jg6vjga/mlK/mjIHmlL/lhZrliKXjga7mjqjlrprntZDmnpzjgILngrnjga9BTUNF44CB5qiq57ea44GvOTUl5L+h6aC85Yy66ZaT44CCIiwKICAgICAgeCA9ICLpgbjmip7norrnjofjgbjjga7lirnmnpzvvIhwcO+8iSIsCiAgICAgIHkgPSBOVUxMLAogICAgICBzaGFwZSA9ICLpgbjmip7ogqLmlbDmnaHku7YiLAogICAgICBjYXB0aW9uID0gIuWbnuetlOiAheaVsOOBjDQw5Lq65pyq5rqA44Gu5pSv5oyB5pS/5YWaw5fpgbjmip7ogqLmlbDmnaHku7bjga/mjqjlrprlr77osaHlpJbjgIIiCiAgICApICsKICAgIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsKICAgIGdncGxvdDI6OnRoZW1lKAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIiwKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwKICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGdncGxvdDI6OmVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksCiAgICAgIHN0cmlwLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEwLjUpLAogICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gOC42LCBjb2xvciA9ICJibGFjayIpLAogICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLAogICAgICBwbG90LnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICBwbG90LnN1YnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSA5LjUpLAogICAgICBwbG90LmNhcHRpb24gPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoaGp1c3QgPSAwLCBzaXplID0gOC41KSwKICAgICAgcGFuZWwuc3BhY2luZyA9IGdyaWQ6OnVuaXQoMS4wLCAibGluZXMiKQogICAgKQp9CgrooahIMeS9nOaIkCA8LSBmdW5jdGlvbijooajjg4fjg7zjgr8pIHsKICDmlK/mjIHpoIYgPC0gdW5pcXVlKOihqOODh+ODvOOCvyRwYXJ0eV9zdXBwb3J0X2gpCiAg6aCF55uu6aCGIDwtIHVuaXF1ZSjooajjg4fjg7zjgr8k6KGo56S66aCF55uuKQoKICDooajjg4fjg7zjgr8gJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICDmlK/mjIHmlL/lhZogPSBmYWN0b3IocGFydHlfc3VwcG9ydF9oLCBsZXZlbHMgPSDmlK/mjIHpoIYpLAogICAgICBg5bGe5oCn44O75rC05rqWYCA9IGZhY3RvcijooajnpLrpoIXnm64sIGxldmVscyA9IOmgheebrumghiksCiAgICAgIOe1kOaenCA9IHNwcmludGYoCiAgICAgICAgIiUuMmYgWyUuMmYsICUuMmZdIiwKICAgICAgICBlc3RpbWF0ZV9wcCwKICAgICAgICBjb25mLmxvd19wcCwKICAgICAgICBjb25mLmhpZ2hfcHAKICAgICAgKQogICAgKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoCiAgICAgIOaUr+aMgeaUv+WFmiwKICAgICAgYOWxnuaAp+ODu+awtOa6lmAsCiAgICAgIOadoeS7tiA9IOadoeS7tuihqOekuiwKICAgICAg57WQ5p6cCiAgICApICU+JQogICAgdGlkeXI6OnBpdm90X3dpZGVyKAogICAgICBuYW1lc19mcm9tID0g5p2h5Lu2LAogICAgICB2YWx1ZXNfZnJvbSA9IOe1kOaenCwKICAgICAgdmFsdWVzX2ZpbGwgPSAi4oCUIgogICAgKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKOaUr+aMgeaUv+WFmiwgYOWxnuaAp+ODu+awtOa6lmApICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAg5pSv5oyB5pS/5YWaID0gYXMuY2hhcmFjdGVyKOaUr+aMgeaUv+WFmiksCiAgICAgIGDlsZ7mgKfjg7vmsLTmupZgID0gYXMuY2hhcmFjdGVyKGDlsZ7mgKfjg7vmsLTmupZgKQogICAgKQp9CgrooahIMeWbnuetlOiAheaVsOS9nOaIkCA8LSBmdW5jdGlvbijooajjg4fjg7zjgr8pIHsKICDooajjg4fjg7zjgr8gJT4lCiAgICBkcGx5cjo6ZGlzdGluY3QoCiAgICAgIOaUr+aMgeaUv+WFmiA9IHBhcnR5X3N1cHBvcnRfaCwKICAgICAg5p2h5Lu2ID0g5p2h5Lu26KGo56S6LAogICAgICDlm57nrZTogIXmlbAgPSBuX2lkcwogICAgKSAlPiUKICAgIGRwbHlyOjptdXRhdGUo5Zue562U6ICF5pWwID0gYXMuY2hhcmFjdGVyKOWbnuetlOiAheaVsCkpICU+JQogICAgdGlkeXI6OnBpdm90X3dpZGVyKAogICAgICBuYW1lc19mcm9tID0g5p2h5Lu2LAogICAgICB2YWx1ZXNfZnJvbSA9IOWbnuetlOiAheaVsCwKICAgICAgdmFsdWVzX2ZpbGwgPSAi4oCUIgogICAgKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKOaUr+aMgeaUv+WFmikKfQpgYGAKCiMjIyDoo5zlm7NIMWHvvJrlrp/pqJMx77yIMjAyM+W5tO+8iQoK5a6f6aiTMeOBq+OBpOOBhOOBpuOAgeaOqOWumuWPr+iDveOBp+OBguOBo+OBn+aUr+aMgeaUv+WFmuWIpeOBq0FNQ0XjgpLnpLrjgZnjgILlkITjg5Hjg43jg6vlhoXjgafjga/jgIHlkIzkuIDjga7lsZ7mgKfjg7vmsLTmupbjgavjgaTjgYTjgaY044Gk44Gu5pS/5YWa5pWw5p2h5Lu244KS5q+U6LyD44Gn44GN44KL44CCCgpgYGB7ciBnMS1zdHVkeTEtZmlndXJlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRSwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTkuNSwgb3V0LndpZHRoPScxMDAlJ30KSDFf5a6f6aiTMSA8LSDmlK/mjIFBTUNF5LiA6KanICU+JQogIGRwbHlyOjpmaWx0ZXIoc3R1ZHlfaWQgPT0gInN0dWR5MSIpCgroo5zlm7NIMWEgPC0g6KOc5ZuzSDHkvZzmiJAoCiAgSDFf5a6f6aiTMSwKICAi6KOc5ZuzSDFh77ya5a6f6aiTMe+8iDIwMjPlubTvvInjga7mlK/mjIHmlL/lhZrliKVBTUNFIgopCuijnOWbs0gxYQpgYGAKCuWvvuW/nOOBmeOCi+WbnuetlOiAheaVsOOBqEFNQ0XjgpLku6XkuIvjgavnpLrjgZnjgIJBTUNF6KGo44Gn44Gv44CB5ZCE5p2h5Lu244Gu54K55o6o5a6a5YCk44GoOTUl5L+h6aC85Yy66ZaT44KSMeOCu+ODq+OBq+OBvuOBqOOCgeOBpuOBhOOCi+OAggoKYGBge3IgZzEtc3R1ZHkxLXRhYmxlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KGoSDFh5Zue562U6ICF5pWwIDwtIOihqEgx5Zue562U6ICF5pWw5L2c5oiQKEgxX+Wun+mokzEpCmtuaXRyOjprYWJsZSgKICDooahIMWHlm57nrZTogIXmlbAsCiAgZm9ybWF0ID0gImh0bWwiLAogIHJvdy5uYW1lcyA9IEZBTFNFLAogIHRhYmxlLmF0dHIgPSAnY2xhc3M9InRhYmxlIHRhYmxlLWNvbmRlbnNlZCIgc3R5bGU9ImZvbnQtc2l6ZTo5MCU7IicsCiAgY2FwdGlvbiA9ICLooahIMWEtMe+8muWun+mokzHvvIgyMDIz5bm077yJ44Gu5pSv5oyB5pS/5YWa5Yil5Zue562U6ICF5pWwIgopCgrooahIMWEgPC0g6KGoSDHkvZzmiJAoSDFf5a6f6aiTMSkKa25pdHI6OmthYmxlKAogIOihqEgxYSwKICBmb3JtYXQgPSAiaHRtbCIsCiAgcm93Lm5hbWVzID0gRkFMU0UsCiAgdGFibGUuYXR0ciA9ICdjbGFzcz0idGFibGUgdGFibGUtY29uZGVuc2VkIiBzdHlsZT0iZm9udC1zaXplOjkwJTsiJywKICBjYXB0aW9uID0gIuihqEgxYS0y77ya5a6f6aiTMe+8iDIwMjPlubTvvInjga7mlK/mjIHmlL/lhZrliKVBTUNF77y754K55o6o5a6a5YCkIFs5NSUgQ0ld44CBcHDvvL0iCikKYGBgCgojIyMg6KOc5ZuzSDFi77ya5a6f6aiTMu+8iDIwMjblubTvvIkKCuWun+mokzLjgavjgaTjgYTjgabjgoLlkIzjgZjlvaLlvI/jgafnpLrjgZnjgILmlK/mjIHmlL/lhZrjga7nqK7poZ7jgYzlrp/pqJMx44KI44KK5aSa44GE44Gf44KB44CB5pSv5oyB5pS/5YWa44KSMuWIl+OBruODleOCoeOCu+ODg+ODiOOBq+WIhuOBkeOAgeWQhOODkeODjeODq+OBp+WxnuaAp+ODu+awtOa6luOCkue4puaWueWQkeOBq+i/veOBiOOCi+OCiOOBhuOBq+OBl+OBn+OAggoKYGBge3IgZzEtc3R1ZHkyLWZpZ3VyZSwgZWNobz1UUlVFLCBldmFsPVRSVUUsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xNiwgb3V0LndpZHRoPScxMDAlJ30KSDFf5a6f6aiTMiA8LSDmlK/mjIFBTUNF5LiA6KanICU+JQogIGRwbHlyOjpmaWx0ZXIoc3R1ZHlfaWQgPT0gInN0dWR5MiIpCgroo5zlm7NIMWIgPC0g6KOc5ZuzSDHkvZzmiJAoCiAgSDFf5a6f6aiTMiwKICAi6KOc5ZuzSDFi77ya5a6f6aiTMu+8iDIwMjblubTvvInjga7mlK/mjIHmlL/lhZrliKVBTUNFIgopCuijnOWbs0gxYgpgYGAKCmBgYHtyIGcxLXN0dWR5Mi10YWJsZSwgZWNobz1UUlVFLCBldmFsPVRSVUV9CuihqEgxYuWbnuetlOiAheaVsCA8LSDooahIMeWbnuetlOiAheaVsOS9nOaIkChIMV/lrp/pqJMyKQprbml0cjo6a2FibGUoCiAg6KGoSDFi5Zue562U6ICF5pWwLAogIGZvcm1hdCA9ICJodG1sIiwKICByb3cubmFtZXMgPSBGQUxTRSwKICB0YWJsZS5hdHRyID0gJ2NsYXNzPSJ0YWJsZSB0YWJsZS1jb25kZW5zZWQiIHN0eWxlPSJmb250LXNpemU6OTAlOyInLAogIGNhcHRpb24gPSAi6KGoSDFiLTHvvJrlrp/pqJMy77yIMjAyNuW5tO+8ieOBruaUr+aMgeaUv+WFmuWIpeWbnuetlOiAheaVsCIKKQoK6KGoSDFiIDwtIOihqEgx5L2c5oiQKEgxX+Wun+mokzIpCmtuaXRyOjprYWJsZSgKICDooahIMWIsCiAgZm9ybWF0ID0gImh0bWwiLAogIHJvdy5uYW1lcyA9IEZBTFNFLAogIHRhYmxlLmF0dHIgPSAnY2xhc3M9InRhYmxlIHRhYmxlLWNvbmRlbnNlZCIgc3R5bGU9ImZvbnQtc2l6ZTo5MCU7IicsCiAgY2FwdGlvbiA9ICLooahIMWItMu+8muWun+mokzLvvIgyMDI25bm077yJ44Gu5pSv5oyB5pS/5YWa5YilQU1DRe+8u+eCueaOqOWumuWApCBbOTUlIENJXeOAgXBw77y9IgopCmBgYAoKIyMjIOijnOWbs0gxY++8muWun+mokzPvvIgyMDI25bm077yJCgrlrp/pqJMz44Gn44Gv44CB5pS/5YWa5bGe5oCn44GM5pS/5YWa5ZCN44Go44GX44Gm5o+Q56S644GV44KM44KL44CC5Zuz44Gu5qeL5oiQ44Gv5a6f6aiTMeODuzLjgajmj4PjgYjjgIHmlK/mjIHmlL/lhZrjgZTjgajjgavjgIHmlL/lhZrlkI3jgYrjgojjgbPntYzmuIjlsZ7mgKfjga7lkITmsLTmupbjgavlr77jgZnjgotBTUNF44KS5q+U6LyD44Gn44GN44KL44KI44GG44Gr44GX44Gf44CCCgpgYGB7ciBnMS1zdHVkeTMtZmlndXJlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRSwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTE2LCBvdXQud2lkdGg9JzEwMCUnfQpIMV/lrp/pqJMzIDwtIOaUr+aMgUFNQ0XkuIDopqcgJT4lCiAgZHBseXI6OmZpbHRlcihzdHVkeV9pZCA9PSAic3R1ZHkzIikKCuijnOWbs0gxYyA8LSDoo5zlm7NIMeS9nOaIkCgKICBIMV/lrp/pqJMzLAogICLoo5zlm7NIMWPvvJrlrp/pqJMz77yIMjAyNuW5tO+8ieOBruaUr+aMgeaUv+WFmuWIpUFNQ0UiCikK6KOc5ZuzSDFjCmBgYAoKYGBge3IgZzEtc3R1ZHkzLXRhYmxlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K6KGoSDFj5Zue562U6ICF5pWwIDwtIOihqEgx5Zue562U6ICF5pWw5L2c5oiQKEgxX+Wun+mokzMpCmtuaXRyOjprYWJsZSgKICDooahIMWPlm57nrZTogIXmlbAsCiAgZm9ybWF0ID0gImh0bWwiLAogIHJvdy5uYW1lcyA9IEZBTFNFLAogIHRhYmxlLmF0dHIgPSAnY2xhc3M9InRhYmxlIHRhYmxlLWNvbmRlbnNlZCIgc3R5bGU9ImZvbnQtc2l6ZTo5MCU7IicsCiAgY2FwdGlvbiA9ICLooahIMWMtMe+8muWun+mokzPvvIgyMDI25bm077yJ44Gu5pSv5oyB5pS/5YWa5Yil5Zue562U6ICF5pWwIgopCgrooahIMWMgPC0g6KGoSDHkvZzmiJAoSDFf5a6f6aiTMykKa25pdHI6OmthYmxlKAogIOihqEgxYywKICBmb3JtYXQgPSAiaHRtbCIsCiAgcm93Lm5hbWVzID0gRkFMU0UsCiAgdGFibGUuYXR0ciA9ICdjbGFzcz0idGFibGUgdGFibGUtY29uZGVuc2VkIiBzdHlsZT0iZm9udC1zaXplOjkwJTsiJywKICBjYXB0aW9uID0gIuihqEgxYy0y77ya5a6f6aiTM++8iDIwMjblubTvvInjga7mlK/mjIHmlL/lhZrliKVBTUNF77y754K55o6o5a6a5YCkIFs5NSUgQ0ld44CBcHDvvL0iCikKYGBgCgojIyDoo5zlm7NIMu+8muaUr+aMgeaUv+WFmuWIpeOBruaJi+OBjOOBi+OCiumHjeimgeW6puOBqOebuOWvvuavlOmHjQoKYGBge3IgZzIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrmlK/mjIHmiYvjgYzjgYvjgorkuIDopqcgPC0gZHBseXI6OmJpbmRfcm93cygKICBwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV9yZXN1bHRzJHN0dWR5MSRpbnRlcnZhbHMgJT4lIGRwbHlyOjptdXRhdGUo5a6f6aiTID0gIuWun+mokzHvvIgyMDIz5bm077yJIiwgc3R1ZHlfaWQgPSAic3R1ZHkxIiksCiAgcGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfcmVzdWx0cyRzdHVkeTIkaW50ZXJ2YWxzICU+JSBkcGx5cjo6bXV0YXRlKOWun+mokyA9ICLlrp/pqJMy77yIMjAyNuW5tO+8iSIsIHN0dWR5X2lkID0gInN0dWR5MiIpLAogIHBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX3Jlc3VsdHMkc3R1ZHkzJGludGVydmFscyAlPiUgZHBseXI6Om11dGF0ZSjlrp/pqJMgPSAi5a6f6aiTM++8iDIwMjblubTvvIkiLCBzdHVkeV9pZCA9ICJzdHVkeTMiKQopICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICDmnaHku7YgPSBwdXJycjo6bWFwMl9jaHIocGFydHlfbiwgc3R1ZHlfaWQsIOadoeS7tuaXpeacrOiqniksCiAgICDmjIfmqJkgPSBwdXJycjo6bWFwMl9jaHIoc3RhdGlzdGljLCBzdHVkeV9pZCwg57Wx6KiI6YeP5pel5pys6KqeKSwKICAgIOihqOekuuWApCA9IGRwbHlyOjppZl9lbHNlKHN0YXRpc3RpYyA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwgMTAwICogZXN0aW1hdGUsIDEwMCAqIGVzdGltYXRlKSwKICAgIOS4i+mZkCA9IDEwMCAqIGNvbmZfbG93LAogICAg5LiK6ZmQID0gMTAwICogY29uZl9oaWdoLAogICAg5Y2Y5L2NID0gZHBseXI6OmlmX2Vsc2Uoc3RhdGlzdGljID09ICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiLCAiJSIsICJwcCIpCiAgKQoK55u45a++5q+U6YeN44OH44O844K/IDwtIOaUr+aMgeaJi+OBjOOBi+OCiuS4gOimpyAlPiUKICBkcGx5cjo6ZmlsdGVyKHN0YXRpc3RpYyA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIikgJT4lCiAgZHBseXI6Om11dGF0ZSjmlbDlgKTjg6njg5njg6sgPSBzcHJpbnRmKCIlLjFmJSUiLCDooajnpLrlgKQpKQoKZm9yICjlrp/pqJPlkI0gaW4gdW5pcXVlKOebuOWvvuavlOmHjeODh+ODvOOCvyTlrp/pqJMpKSB7CiAg5o+P55S744OH44O844K/IDwtIOebuOWvvuavlOmHjeODh+ODvOOCvyAlPiUgZHBseXI6OmZpbHRlcijlrp/pqJMgPT0g5a6f6aiT5ZCNKQogIOWbsyA8LSBnZ3Bsb3QyOjpnZ3Bsb3Qo5o+P55S744OH44O844K/LCBnZ3Bsb3QyOjphZXMoeCA9IHBhcnR5X24sIHkgPSDooajnpLrlgKQsIGdyb3VwID0gcGFydHlfc3VwcG9ydF9oKSkgKwogICAgZ2dwbG90Mjo6Z2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNTAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNCkgKwogICAgZ2dwbG90Mjo6Z2VvbV9saW5lKGxpbmV3aWR0aCA9IDAuNjUpICsKICAgIGdncGxvdDI6Omdlb21fZXJyb3JiYXIoZ2dwbG90Mjo6YWVzKHltaW4gPSDkuIvpmZAsIHltYXggPSDkuIrpmZApLCB3aWR0aCA9IDAuMDgsIGxpbmV3aWR0aCA9IDAuNDUpICsKICAgIGdncGxvdDI6Omdlb21fbGFiZWwoZ2dwbG90Mjo6YWVzKGxhYmVsID0g5pWw5YCk44Op44OZ44OrKSwgc2l6ZSA9IDMuMCwgbGFiZWwuc2l6ZSA9IDAsIGZpbGwgPSAid2hpdGUiKSArCiAgICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4gcGFydHlfc3VwcG9ydF9oLCBzY2FsZXMgPSAiZnJlZV95IikgKwogICAgZ2dwbG90Mjo6c2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDI6NSwgbGFiZWxzID0g5p2h5Lu25pel5pys6KqeKDI6NSwgaWZlbHNlKHVuaXF1ZSjmj4/nlLvjg4fjg7zjgr8kc3R1ZHlfaWQpID09ICJzdHVkeTMiLCAic3R1ZHkzIiwgInN0dWR5MSIpKSkgKwogICAgZ2dwbG90Mjo6bGFicyh4ID0gTlVMTCwgeSA9ICLmlL/lhZrmiYvjgYzjgYvjgornm7jlr77mr5Tph43vvIgl77yJIiwgc3VidGl0bGUgPSDlrp/pqJPlkI0pICsKICAgIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwKSArCiAgICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpKQogIHByaW50KOWbsykKfQoK6KGoSDIgPC0g5pSv5oyB5omL44GM44GL44KK5LiA6KanICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDlrp/pqJMsCiAgICDmlK/mjIHmlL/lhZogPSBwYXJ0eV9zdXBwb3J0X2gsCiAgICBg5p2h5Lu244O75oyH5qiZYCA9IHBhc3RlMCjmnaHku7YsICLvvJoiLCDmjIfmqJkpLAogICAg5o6o5a6a5YCkID0gcm91bmQo6KGo56S65YCkLCAyKSwKICAgIGA5NSVDSeS4i+mZkGAgPSByb3VuZCjkuIvpmZAsIDIpLAogICAgYDk1JUNJ5LiK6ZmQYCA9IHJvdW5kKOS4iumZkCwgMiksCiAgICDljZjkvY0KICApCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoSDIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEgy77ya5pSv5oyB5pS/5YWa5Yil44Gu5omL44GM44GL44KK6YeN6KaB5bqm44Go55u45a++5q+U6YeNIikKYGBgCgojIyDoo5zlm7NIM++8muWvvuixoeOBqOOBquOCi+aUr+aMgeaUv+WFmuWIpeOBruS4gOiHtOWKueaenAoKYGBge3IgZzMsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQrkuIDoh7TlirnmnpwgPC0gc3R1ZHkzX2FsbF9wYXJ0eV9tYXRjaF9yZXN1bHRzJGNvZWZmaWNpZW50cyAlPiUKICBkcGx5cjo6ZmlsdGVyKHN0YXR1cyA9PSAiZXN0aW1hdGVkIiwgIWlzLm5hKGVzdGltYXRlKSkgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIOadoeS7tiA9IOadoeS7tuaXpeacrOiqnihwYXJ0eV9uLCAic3R1ZHkzIiksCiAgICDmlbDlgKTjg6njg5njg6sgPSBzcHJpbnRmKCIlLjFmIiwgZXN0aW1hdGVfcHApCiAgKQoK6KOc5ZuzSDMgPC0gZ2dwbG90Mjo6Z2dwbG90KOS4gOiHtOWKueaenCwgZ2dwbG90Mjo6YWVzKHggPSBwYXJ0eV9uLCB5ID0gZXN0aW1hdGVfcHAsIGdyb3VwID0gMSkpICsKICBnZ3Bsb3QyOjpnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjQpICsKICBnZ3Bsb3QyOjpnZW9tX2xpbmUobGluZXdpZHRoID0gMC42NSkgKwogIGdncGxvdDI6Omdlb21fZXJyb3JiYXIoZ2dwbG90Mjo6YWVzKHltaW4gPSBjb25mLmxvd19wcCwgeW1heCA9IGNvbmYuaGlnaF9wcCksIHdpZHRoID0gMC4wOCwgbGluZXdpZHRoID0gMC40NSkgKwogIGdncGxvdDI6Omdlb21fbGFiZWwoZ2dwbG90Mjo6YWVzKGxhYmVsID0g5pWw5YCk44Op44OZ44OrKSwgc2l6ZSA9IDMuMCwgbGFiZWwuc2l6ZSA9IDAsIGZpbGwgPSAid2hpdGUiKSArCiAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IHN1cHBvcnRfcGFydHlfdmFsaWQpICsKICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMjo1LCBsYWJlbHMgPSBwYXN0ZTAoMjo1LCAi6YG45oqe6IKiIikpICsKICBnZ3Bsb3QyOjpsYWJzKHggPSAi6YG45oqe6IKi5pWwIiwgeSA9ICLkuIDoh7TlirnmnpzvvIhwcO+8iSIpICsKICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMCkgKwogIGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkpCuijnOWbs0gzCgrooahIMyA8LSDkuIDoh7TlirnmnpwgJT4lCiAgZHBseXI6OnRyYW5zbXV0ZSgKICAgIOaUr+aMgeaUv+WFmiA9IHN1cHBvcnRfcGFydHlfdmFsaWQsCiAgICDmnaHku7YsCiAgICDlm57nrZTogIXmlbAgPSBuX2lkcywKICAgIGDkuIDoh7TlirnmnpzvvIhwcO+8iWAgPSByb3VuZChlc3RpbWF0ZV9wcCwgMiksCiAgICBgOTUlQ0nkuIvpmZBgID0gcm91bmQoY29uZi5sb3dfcHAsIDIpLAogICAgYDk1JUNJ5LiK6ZmQYCA9IHJvdW5kKGNvbmYuaGlnaF9wcCwgMiksCiAgICBw5YCkID0gc2lnbmlmKHAudmFsdWUsIDMpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEgzKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKCuihqEg0IDwtIHN0dWR5M19hbGxfcGFydHlfbWF0Y2hfcmVzdWx0cyR0cmVuZHMgJT4lCiAgZHBseXI6OmZpbHRlcihzdGF0dXMgPT0gImVzdGltYXRlZCIpICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDmlK/mjIHmlL/lhZogPSBzdXBwb3J0X3BhcnR5X3ZhbGlkLAogICAgYDHpgbjmip7ogqLlopfliqDjgYLjgZ/jgorjga7lpInljJbvvIhwcO+8iWAgPSByb3VuZChlc3RpbWF0ZSAqIDEwMCwgMiksCiAgICBgOTUlQ0nkuIvpmZBgID0gcm91bmQoY29uZi5sb3cgKiAxMDAsIDIpLAogICAgYDk1JUNJ5LiK6ZmQYCA9IHJvdW5kKGNvbmYuaGlnaCAqIDEwMCwgMiksCiAgICBw5YCkID0gc2lnbmlmKHAudmFsdWUsIDMpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEg0KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIEkuIDPlrp/pqJPmqKrmlq3liIbmnpAKCiMjIOijnOWbs0kx77ya5Li76KaB5Luu6Kqs44Gu57ea5b2i5YK+5ZCRCgpgYGB7ciBoMSwgZWNobz1UUlVFLCBldmFsPVRSVUV9CuS4u+imgeS7ruiqrCA8LSBoeXBvdGhlc2lzX3Rlc3Rfc3VtbWFyeSAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAg5a6f6aiTID0gZHBseXI6OnJlY29kZShzdHVkeV9pZCwgc3R1ZHkxID0gIuWun+mokzHvvIgyMDIz5bm077yJIiwgc3R1ZHkyID0gIuWun+mokzLvvIgyMDI25bm077yJIiwgc3R1ZHkzID0gIuWun+mokzPvvIgyMDI25bm077yJIiksCiAgICDmjIfmqJkgPSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YXRpc3RpYywgInBhcnR5IikgfiAi5pS/5YWa5omL44GM44GL44KK6YeN6KaB5bqmIiwKICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdChzdGF0aXN0aWMsICJlY29ub21pYyIpIH4gIue1jOa4iOaJi+OBjOOBi+OCiumHjeimgeW6piIsCiAgICAgIFRSVUUgfiBzdGF0aXN0aWMKICAgICksCiAgICDkuojmuKzmlrnlkJEgPSBkcGx5cjo6cmVjb2RlKGV4cGVjdGVkX2RpcmVjdGlvbiwgcG9zaXRpdmUgPSAi5q2jIiwgbmVnYXRpdmUgPSAi6LKgIikKICApCgrkuLvopoHku67oqqwgPC0g5Li76KaB5Luu6KqsICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICDlgr7jgY1wcCA9IDEwMCAqIGVzdGltYXRlLAogICAg5LiL6ZmQcHAgPSAxMDAgKiBjb25mX2xvdywKICAgIOS4iumZkHBwID0gMTAwICogY29uZl9oaWdoLAogICAg6KGo56S66KGMID0gcGFzdGUwKGh5cG90aGVzaXMsICLvvJoiLCDmjIfmqJkpLAogICAg5pWw5YCk44Op44OZ44OrID0gc3ByaW50ZigiJS4yZiIsIOWCvuOBjXBwKQogICkKCuijnOWbs0kxIDwtIGdncGxvdDI6OmdncGxvdCjkuLvopoHku67oqqwsIGdncGxvdDI6OmFlcyh4ID0g5YK+44GNcHAsIHkgPSBzdGF0czo6cmVvcmRlcijooajnpLrooYwsIOWCvuOBjXBwKSkpICsKICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjQ1KSArCiAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcmgoZ2dwbG90Mjo6YWVzKHhtaW4gPSDkuIvpmZBwcCwgeG1heCA9IOS4iumZkHBwKSwgaGVpZ2h0ID0gMC4xMiwgbGluZXdpZHRoID0gMC41NSkgKwogIGdncGxvdDI6Omdlb21fbGFiZWwoZ2dwbG90Mjo6YWVzKGxhYmVsID0g5pWw5YCk44Op44OZ44OrKSwgc2l6ZSA9IDMuMSwgbGFiZWwuc2l6ZSA9IDAsIGZpbGwgPSAid2hpdGUiKSArCiAgZ2dwbG90Mjo6bGFicyh4ID0gIumBuOaKnuiCouOBjDHjgaTlopfjgYjjgovjgajjgY3jga7ph43opoHluqbjga7lpInljJbvvIhwcO+8iSIsIHkgPSBOVUxMKSArCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEpICsKICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpKQroo5zlm7NJMQoK6KGoSTEgPC0g5Li76KaB5Luu6KqsICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDlrp/pqJMsCiAgICDku67oqqwgPSBoeXBvdGhlc2lzLAogICAg5oyH5qiZLAogICAg5LqI5ris5pa55ZCRLAogICAg5YK+44GNID0gcm91bmQoZXN0aW1hdGUsIDQpLAogICAgYDk1JUNJ5LiL6ZmQYCA9IHJvdW5kKGNvbmZfbG93LCA0KSwKICAgIGA5NSVDSeS4iumZkGAgPSByb3VuZChjb25mX2hpZ2gsIDQpLAogICAgcOWApCA9IHNpZ25pZihwX3ZhbHVlX3R3b19zaWRlZCwgMyksCiAgICDliKTlrpogPSBjb25jbHVzaW9uCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEkxKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyDoo5zlm7NJMu+8mumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOBrue3muW9ouWCvuWQkQoKYGBge3IgaDIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQroqr/mlbTmuIjjgb/lgr7lkJEgPC0gY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZV9zdW1tYXJ5ICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICDlrp/pqJMgPSBkcGx5cjo6cmVjb2RlKHN0dWR5X2lkLCBzdHVkeTEgPSAi5a6f6aiTMe+8iDIwMjPlubTvvIkiLCBzdHVkeTIgPSAi5a6f6aiTMu+8iDIwMjblubTvvIkiLCBzdHVkeTMgPSAi5a6f6aiTM++8iDIwMjblubTvvIkiKSwKICAgIOaMh+aomSA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3Qoc3RhdGlzdGljLCAicGFydHkiKSB+ICLmlL/lhZrmiYvjgYzjgYvjgorph43opoHluqbvvIjpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/vvIkiLAogICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YXRpc3RpYywgImVjb25vbWljIikgfiAi57WM5riI5omL44GM44GL44KK6YeN6KaB5bqm77yI6YG45oqe6IKi5pWw6Kq/5pW05riI44G/77yJIiwKICAgICAgVFJVRSB+IHN0YXRpc3RpYwogICAgKQogICkKCuiqv+aVtOa4iOOBv+WCvuWQkSA8LSDoqr/mlbTmuIjjgb/lgr7lkJEgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIOWCvuOBjeihqOekuiA9IDEwMCAqIGVzdGltYXRlLAogICAg5LiL6ZmQ6KGo56S6ID0gMTAwICogY29uZl9sb3csCiAgICDkuIrpmZDooajnpLogPSAxMDAgKiBjb25mX2hpZ2gsCiAgICDooajnpLrooYwgPSBwYXN0ZTAo5a6f6aiTLCAi77yaIiwg5oyH5qiZKSwKICAgIOaVsOWApOODqeODmeODqyA9IHNwcmludGYoIiUuMmYiLCDlgr7jgY3ooajnpLopCiAgKQoK6KOc5ZuzSTIgPC0gZ2dwbG90Mjo6Z2dwbG90KOiqv+aVtOa4iOOBv+WCvuWQkSwgZ2dwbG90Mjo6YWVzKHggPSDlgr7jgY3ooajnpLosIHkgPSBzdGF0czo6cmVvcmRlcijooajnpLrooYwsIOWCvuOBjeihqOekuikpKSArCiAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC40NSkgKwogIGdncGxvdDI6Omdlb21fZXJyb3JiYXJoKGdncGxvdDI6OmFlcyh4bWluID0g5LiL6ZmQ6KGo56S6LCB4bWF4ID0g5LiK6ZmQ6KGo56S6KSwgaGVpZ2h0ID0gMC4xMiwgbGluZXdpZHRoID0gMC41NSkgKwogIGdncGxvdDI6Omdlb21fbGFiZWwoZ2dwbG90Mjo6YWVzKGxhYmVsID0g5pWw5YCk44Op44OZ44OrKSwgc2l6ZSA9IDMuMSwgbGFiZWwuc2l6ZSA9IDAsIGZpbGwgPSAid2hpdGUiKSArCiAgZ2dwbG90Mjo6bGFicyh4ID0gIumBuOaKnuiCouOBjDHjgaTlopfjgYjjgovjgajjgY3jga7oqr/mlbTmuIjjgb/ph43opoHluqbjga7lpInljJbvvIgl77yJIiwgeSA9IE5VTEwpICsKICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKwogIGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkpCuijnOWbs0kyCgrooahJMiA8LSDoqr/mlbTmuIjjgb/lgr7lkJEgJT4lCiAgZHBseXI6OnRyYW5zbXV0ZSgKICAgIOWun+mokywKICAgIOaMh+aomSwKICAgIOWCvuOBjSA9IHJvdW5kKGVzdGltYXRlLCA0KSwKICAgIGA5NSVDSeS4i+mZkGAgPSByb3VuZChjb25mX2xvdywgNCksCiAgICBgOTUlQ0nkuIrpmZBgID0gcm91bmQoY29uZl9oaWdoLCA0KSwKICAgIHDlgKQgPSBzaWduaWYocF92YWx1ZV90d29fc2lkZWQsIDMpCiAgKQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEkyKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyDoo5zlm7NJM++8muaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHjeOBrjPlrp/pqJPmr5TovIMKCmBgYHtyIGgzLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0K5qiq5pat55u45a++5q+U6YeNIDwtIGNyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAg5a6f6aiTID0gZHBseXI6OnJlY29kZShzdHVkeV9pZCwgc3R1ZHkxID0gIuWun+mokzHvvIgyMDIz5bm077yJIiwgc3R1ZHkyID0gIuWun+mokzLvvIgyMDI25bm077yJIiwgc3R1ZHkzID0gIuWun+mokzPvvIgyMDI25bm077yJIiksCiAgICDnm7jlr77mr5Tph40gPSAxMDAgKiBlc3RpbWF0ZSwKICAgIOS4i+mZkCA9IDEwMCAqIGNvbmZfbG93LAogICAg5LiK6ZmQID0gMTAwICogY29uZl9oaWdoLAogICAg5pWw5YCk44Op44OZ44OrID0gc3ByaW50ZigiJS4xZiUlIiwg55u45a++5q+U6YeNKQogICkKCuijnOWbs0kzIDwtIGdncGxvdDI6OmdncGxvdCjmqKrmlq3nm7jlr77mr5Tph40sIGdncGxvdDI6OmFlcyh4ID0gcGFydHlfbiwgeSA9IOebuOWvvuavlOmHjSwgZ3JvdXAgPSDlrp/pqJMsIGxpbmV0eXBlID0g5a6f6aiTKSkgKwogIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjQpICsKICBnZ3Bsb3QyOjpnZW9tX2xpbmUobGluZXdpZHRoID0gMC43NSkgKwogIGdncGxvdDI6Omdlb21fZXJyb3JiYXIoZ2dwbG90Mjo6YWVzKHltaW4gPSDkuIvpmZAsIHltYXggPSDkuIrpmZApLCB3aWR0aCA9IDAuMDcsIGxpbmV3aWR0aCA9IDAuNDUpICsKICBnZ3Bsb3QyOjpnZW9tX2xhYmVsKGdncGxvdDI6OmFlcyhsYWJlbCA9IOaVsOWApOODqeODmeODqyksIHNpemUgPSAzLjAsIGxhYmVsLnNpemUgPSAwLCBmaWxsID0gIndoaXRlIikgKwogIGdncGxvdDI6OnNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAyOjUsIGxhYmVscyA9IHBhc3RlMCgyOjUsICLpgbjmip7ogqIiKSkgKwogIGdncGxvdDI6OmxhYnMoeCA9ICLpgbjmip7ogqLmlbAiLCB5ID0gIuaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHje+8iCXvvIkiLCBsaW5ldHlwZSA9IE5VTEwpICsKICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKwogIGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQroo5zlm7NJMwoK6KGoSTMgPC0g5qiq5pat55u45a++5q+U6YeNICU+JQogIGRwbHlyOjp0cmFuc211dGUoCiAgICDlrp/pqJMsCiAgICDmnaHku7YgPSBwYXN0ZTAocGFydHlfbiwgIumBuOaKnuiCouadoeS7tiIpLAogICAgYOaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHje+8iCXvvIlgID0gcm91bmQo55u45a++5q+U6YeNLCAxKSwKICAgIGA5NSVDSeS4i+mZkGAgPSByb3VuZCjkuIvpmZAsIDEpLAogICAgYDk1JUNJ5LiK6ZmQYCA9IHJvdW5kKOS4iumZkCwgMSkKICApCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoSTMpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMgSi4g6Kq/5p+756WoCuacrOevgOOBp+OBr+OAgeWun+mokzHvvIgyMDIz5bm077yJ44CB5a6f6aiTMu+8iDIwMjblubTvvInjgIHlrp/pqJMz77yIMjAyNuW5tO+8ieOBp+WbnuetlOiAheOBq+aPkOekuuOBl+OBn+iqv+afu+elqOOCkuOBvuOBqOOCgeOBpuWGjeaOsuOBmeOCi+OAguizquWVj+aWh+OBqOWbnuetlOmBuOaKnuiCouOBr+OAgeWQhFF1YWx0cmljc+iqv+afu+elqOOBruOCqOOCr+OCueODneODvOODiOOBq+WfuuOBpeOBjeOAgeWOn+aWh+OBruihqOiomOOCkuWOn+WJh+OBqOOBl+OBpue2reaMgeOBl+OBn+OAguOCs+ODs+OCuOODp+OCpOODs+ODiOiqsumhjOOBr+WQhOadoeS7tuOBpzXlm57nubDjgorov5TjgZXjgozjgovjgZ/jgoHjgIHlkIzkuIDjga7os6rllY/mlofjgpI15Zue6YeN6KSH5o6y6LyJ44GZ44KL5Luj44KP44KK44Gr44CBKirjgZnjgbnjgabjga7os6rllY9JROOCkuWIl+aMmeOBl+OBn+OBhuOBiOOBp+WFsemAmuOBruizquWVj+aWh+OCkjHlm57npLrjgZkqKuOAguWQhOiqsumhjOOBp+ODqeODs+ODgOODoOOBq+W3ruOBl+i+vOOBvuOCjOOCi1F1YWx0cmljc+OBrkVtYmVkZGVkIERhdGHjgrPjg7zjg4njga/jgIHlm57nrZTogIXjgavjgajjgaPjgabjga7lrp/os6rnmoTjgaros6rllY/mlofjgafjga/jgarjgYTjgZ/jgoHnnIHnlaXjgZfjgIHjgZ3jga7ku6Pjgo/jgorjgavnhKHkvZzngrrljJbjgZXjgozjgZ/lsZ7mgKfjgajmsLTmupbjgpLooajjgajjgZfjgabnpLrjgZnjgIJRdWFsdHJpY3Pjga7jg5Xjg63jg7zliLblvqHjgIFXZWJTZXJ2aWNl44CB44Oa44O844K45Yy65YiH44KK562J44Gu5oqA6KGT55qE44Oh44K/44OH44O844K/44KC55yB55Wl44GZ44KL44CCCuOBquOBiuOAgeWFg+OBruiqv+afu+elqOOBq+aui+OCi+ihqOiomOS4iuOBruS4jee1seS4gOOBr+OAgeOBk+OBk+OBp+WGheWuueOCkuWkieOBiOOBpuOBl+OBvuOCj+OBquOBhOOCiOOBhuWOn+WJh+OBqOOBl+OBpuOBneOBruOBvuOBvuaOsui8ieOBmeOCi+OAguOBqOOBj+OBq+Wun+mokzHjga5RMjU444CBUTI1OeOAgVEyNjDjgavjga/jgIE044O7NeODuzLpgbjmip7ogqLmnaHku7bjga7oqqzmmI7kuK3jgavjgIwz44Gk44Gu6YG45oqe6IKi44CN44Go44GZ44KL6KGo6KiY44GM5q6L44Gj44Gm44GE44KL44CC44G+44Gf44CB5a6f6aiTMeOBruikh+aVsOmBuOaKnuiCouadoeS7tuOBrumBuOaKnuiqsumhjOOBq+OBr+OAjOS7peS4i+OBruOBqeOBoeOCieOBruaUv+WFmuOAjeOBqOOBhOOBhuihqOiomOOBjOaui+OBo+OBpuOBhOOCi+OAguOBk+OCjOOCieOBryoq5Y6f5paH44Oe44OeKirjgafjgYLjgovjgIIKIyMgSi4xIOWun+mokzHvvIgyMDIz5bm077yJCiMjIyBKLjEuMSDoqr/mn7vplovlp4vmmYLjga7oqqzmmI7jgajlkIzmhI8KPGRldGFpbHM+CjxzdW1tYXJ5PjxzdHJvbmc+UTEuMSDoqr/mn7voqqzmmI7vvIjjgq/jg6rjg4Pjgq/jgZfjgablhajmlofjgpLooajnpLrvvIk8L3N0cm9uZz48L3N1bW1hcnk+Cgo8cD7jgIzntYzmuIjoqZXkvqHjgajmlL/mqKnkuqTku6PjgpLjgoHjgZDjgovmhI/orZjoqr/mn7vjgI0g44GU5Y2U5Yqb44Gu44GK6aGY44GEIOmWouilv+WtpumZouWkp+WtpiDnt4/lkIjmlL/nrZblrabpg6gg5pWZ5o6IIOWkp+adkSDoj6/lrZAg77yI44GK44GK44KA44KJIOOBr+OBquOBk++8iSDil4Yg44GT44Gu44Ki44Oz44Kx44O844OI6Kq/5p+744Gv44CB5paH6YOo56eR5a2m55yB44Gr44KI44KL56CU56m25Yqp5oiQ77yI56CU56m26Kqy6aGM55Wq5Y+377yaMjJLMDEzMjAg44CMIOe1jOa4iOOBqOaUv+ayu+eahOaUr+aMgeOBrumWouS/guODvOOAjuS4jeW5s+OBrumdnuWvvuensOaAp+OAj+S7ruiqrOOBi+OCieimi+OCi+aXpeacrOOBruacieaoqeiAheOAje+8ieOBq+WfuuOBpeOBjeWun+aWveOBleOCjOOCi+Wtpuihk+iqv+afu+OBp+OBmeOAgiDil4Yg5Za25Yip55uu55qE44KE44CB54m55a6a44Gu5pS/5rK75Yui5Yqb44KS5pSv5o+044GZ44KL44Gf44KB44Gu44Ki44Oz44Kx44O844OI6Kq/5p+744Gn44Gv44GC44KK44G+44Gb44KT44CC44G+44Gf44CB44GC44Gq44Gf44GM44GT44Gu6Kq/5p+744Gr5Y2U5Yqb44GZ44KL44GT44Go44Gr44KI44Gj44Gm44CB5LiN5Yip55uK44KS6KKr44KL44GT44Go44KC44GC44KK44G+44Gb44KT44CCIOKXhiDmnKzoqr/mn7vjgafjga/jgIHjgYLjgarjgZ/jga7mlL/msrvjgIHntYzmuIjjgavplqLjgZnjgovmhI/orZjjgarjganjgoLjgYrkvLrjgYTjgZnjgovjgZPjgajjgavjgarjgorjgb7jgZnjga7jgafjgIHjgZTmib/nn6XjgYrjgY3jgYTjgZ/jgaDjgY3jgZ/jgY/lrZjjgZjjgb7jgZnjgILjgoLjgZflm57nrZTjgpLkuI3lv6vjgavmhJ/jgZjjgonjgozjgZ/loLTlkIjjgIHjgYLjgarjgZ/jga/jgYTjgaTjgafjgoLlm57nrZTjgpLjgoTjgoHjgovjgZPjgajjgYzjgafjgY3jgb7jgZnjgIIg4peGIOOBvuOBn+acrOiqv+afu+OBp+OBr+OAgeOBguOBquOBn+OBruaJgOW+l+OBq+OBpOOBhOOBpuOCguOBiuWwi+OBreOBl+OBvuOBmeOAguOCguOBl+WbnuetlOOCkuS4jeW/q+OBq+aEn+OBmOOCieOCjOOBn+WgtOWQiOOAgeOBguOBquOBn+OBr+OBhOOBpOOBp+OCguWbnuetlOOCkuOChOOCgeOCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAgiDil4Yg5pS/5rK744KE6KGM5pS/44Gr44Gk44GE44Gm44Gu6LOq5ZWP44Gr44Gv44CB562U44GI44Gl44KJ44GE44KC44Gu44KC44GC44KK44G+44GZ44CC44KC44GX5Zue562U44KS5LiN5b+r44Gr5oSf44GY44KJ44KM44Gf5aC05ZCI44CB44GC44Gq44Gf44Gv44GE44Gk44Gn44KC5Zue562U44KS44KE44KB44KL44GT44Go44GM44Gn44GN44G+44GZ44CCIOKXhiDlvpfjgonjgozjgZ/lm57nrZTjga/jgZnjgbnjgabntbHoqIjnmoTjgavlh6bnkIbjgZfjgIHlm57nrZTogIXjga7lsZ7mgKfjgarjganjgYzjgo/jgYvjgonjgarjgYTjgojjgYbjgavjgZfjgb7jgZnjgILlgIvkurrjga7mg4XloLHjgYznibnlrprjgZXjgozjgovjgZPjgajjga/jgYLjgorjgb7jgZvjgpPjga7jgafjgIHlronlv4PjgZfjgabjgZTlm57nrZTjgY/jgaDjgZXjgYTjgIIg4peGIOOCouODs+OCseODvOODiOiqv+afu+OBruWIhuaekOe1kOaenOOBq+OBpOOBhOOBpuOBr+OAgeaWsOiBnuOBquOBqeOCkumAmuOBmOOBpuS4gOiIrOOBruS6uuOBq+WvvuOBl+OBpuOCguepjealteeahOOBq+eZuuS/oeOBmeOCi+S6iOWumuOBp+OBmeOAgueahuOBleOBvuOBruOBlOWNlOWKm+OBrueoi+OAgeOCiOOCjeOBl+OBj+OBiumhmOOBhOeUs+OBl+S4iuOBkuOBvuOBmeOAgiDil4Yg5LiN6YGp5YiH44Gq5Zue562U44KS6KGM44GG44GT44Go44Gv44CB6Kq/5p+757WQ5p6c44Gu6LOq44KS5L2O5LiL44GV44Gb44G+44GZ44CC44GZ44G544Gm44Gu6LOq5ZWP44Gr5a++44GX44Gm44CB5LiN6YGp5YiH44Gq5b2i44Gn5Zue562U44GX44Gq44GE44KI44GG44CB44KI44KN44GX44GP44GK6aGY44GE55Sz44GX5LiK44GS44G+44GZ44CC5LiN6YGp5YiH44Gq5Zue562U44KS6KGM44Gj44Gf5aC05ZCI44Gv44CB6Kq/5p+744KS57WC5LqG44GV44Gb44Gm6aCC44GP5aC05ZCI44GM44GU44GW44GE44G+44GZ44CCIOKXhiDmnKzjgqLjg7PjgrHjg7zjg4joqr/mn7vjgavplqLjgZfjgabjgZTkuI3mmI7jgarngrnnrYnjgYzjgZTjgZbjgYTjgb7jgZfjgZ/jgonjgIHkuIvoqJjjg6Hjg7zjg6vjgqLjg4njg6zjgrnjgb7jgafjgYrllY/jgYTlkIjjgo/jgZvjgY/jgaDjgZXjgYTjgIIgZS1tYWlsOiBoYW5ha29vaG11cmE2MTAzMUBnbWFpbC5jb20g5Lul5LiK44KS44GU56K66KqN44Gu5LiK44CB6Kq/5p+744KS6ZaL5aeL44GZ44KL5aC05ZCI44Gv44CBIOOAjOacrOiqv+afu+OBrui2o+aXqOOBqOWAi+S6uuaDheWgseOBruWPluOCiuaJseOBhOOBq+WQjOaEj+OBl+OBpuOAgeiqv+afu+OCkumWi+Wni+OBmeOCi+OAjSDjg5zjgr/jg7PjgpLjgq/jg6rjg4Pjgq/jgZfjgabjgIHlj7PkuIvjga7jgIzvvJ7vvJ7jgI3jgb7jgZ/jga/jgIzmrKHjgbjjgI3jg5zjgr/jg7PjgpLmirzjgZfjgabjgIHoqr/mn7vjgpLplovlp4vjgZfjgabjgY/jgaDjgZXjgYTjgII8L3A+Cgo8L2RldGFpbHM+CgoqKuWbnuetlOmBuOaKnuiCoioqCgotIOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBpuOAgeacrOiqv+afu+OBq+WNlOWKm+OBmeOCiyAoMSkKLSDmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZfjgarjgYTjga7jgafjgIHmnKzoqr/mn7vjgavljZTlipvjgZfjgarjgYQgKDIpCgojIyMgSi4xLjIg44OV44Kn44Kk44K544K344O844OI44CB5pS/5YWa5pSv5oyB44CB5omA5b6XCnwg6LOq5ZWPSUQgfCDos6rllY/mlocgfCDlm57nrZTlvaLlvI/jg7vpgbjmip7ogqIgfAp8LS0tfC0tLXwtLS18CnwgUTIuMSB8IOOBguOBquOBn+OBruaAp+WIpeOBr+OAgeS7peS4i+OBruOBhuOBoeOBqeOBoeOCieOBq+ipsuW9k+OBl+OBvuOBmeOBp+OBl+OCh+OBhuOBi+OAgiB8IOWls+aApyAoMSnvvI/nlLfmgKcgKDIp77yP44Gp44Gh44KJ44Gn44KC44Gq44GEICgzKe+8j+etlOOBiOOBquOBhCAoNCkgfAp8IFEyLjIgfCDjgYLjgarjgZ/jga7nj77lnKjjga7jgZTlubTpvaLjgpLoqJjlhaXjgZfjgabjgY/jgaDjgZXjgYTjgIIg4oC76KiY5YWl44Gr6Zqb44GX44Gm44Gv44CB5Y2K6KeS5pWw5a2X44Gn5YWl5Yqb44GX44Gm44GP44Gg44GV44GE44CCIHwgMTjvvZ44MOats++8iFF1YWx0cmljc+OBruODieODreODg+ODl+ODgOOCpuODs++8iSB8CnwgUTIuNCB8IOOBguOBquOBn+OBjOacgOW+jOOBq+WNkualreOBl+OBn+WtpuagoeOBr+asoeOBruOBhuOBoeOBqeOCjOOBp+OBl+OCh+OBhuOBi+OAgiDvvIrkuK3pgIDjgZfjgZ/mlrnjgoTlnKjnsY3kuK3jga7mlrnjgoLljZLmpa3jgajjgb/jgarjgZfjgabjgY/jgaDjgZXjgYTjgIIgfCDlsI/lrabmoKHvvIjml6flsI/jg7vml6fpq5jlsI/vvInljZLmpa0gKDEp77yP6auY5qCh77yI5pen5Lit77yJ5Y2S5qWtICgyKe+8j+mrmOetieWwgumWgOODu+efreacn+Wkp+WtpuODu+WwguS/ruWtpuagoeWNkualrSAoMynvvI805bm05Yi25aSn5a2m5Y2S5qWtICg0Ke+8j+Wkp+WtpumZouWNkualrSAoNSnvvI/jgo/jgYvjgonjgarjgYQgKDYp77yP44GT44Gf44GI44Gq44GEICg3KSB8CnwgUTIuNyB8IOOBguOBquOBn+OBr+OBqeOBruaUv+WFmuOCkuaUr+aMgeOBl+OBpuOBiuOCieOCjOOBvuOBmeOBi+OAgiB8IOiHqueUseawkeS4u+WFmiAoMSnvvI/nq4vmhrLmsJHkuLvlhZogKDIp77yP5YWs5piO5YWaICgzKe+8j+aXpeacrOe2reaWsOOBruS8miAoNCnvvI/ml6XmnKzlhbHnlKPlhZogKDUp77yP5Zu95rCR5rCR5Li75YWaICg2Ke+8j+ekvuS8muawkeS4u+WFmiAoNynvvI/jgozjgYTjgo/mlrDpgbjntYQgKDgp77yP44Gd44Gu5LuWICgxMSnvvI/mlK/mjIHjgZnjgovmlL/lhZrjga/jgarjgYQgKDEyKe+8j+OCj+OBi+OCieOBquOBhCAoMTMp77yP562U44GI44Gq44GEICgxNCkgfAp8IFEzLjEgfCDjgYLjgarjgZ/jga7kuJbluK/jga7nqI7lvJXjgY3liY3jga7kuJbluK/lubTlj47jgajmiYvlj5bjgorjga7lubTlj47jga/jgIHjgaDjgYTjgZ/jgYTjgYrjgYTjgY/jgonjgZDjgonjgYTjgafjgZfjgofjgYbjgYvjgIIg56iO5byV44GN5YmN44Gu5Y+O5YWl44Go44Gv44CB5LiA6Iis55qE44Gr44CM6aGN6Z2i44Gu5Y+O5YWl44CN44Go6KiA44KP44KM44KL44KC44Gu44Gn44GZ44CC44Gd44Gu6aGN6Z2i44Gu5Y+O5YWl44GL44KJ44CB56iO6YeR44KE56S+5Lya5L+d6Zm65paZ44KS5byV44GE44Gf5q6L44KK44GM44CM5omL5Y+W44KK44Gu5Y+O5YWl44CN44Go6KiA44KP44KM44KL44KC44Gu44Gn44GZ44CCIOOBguOBquOBn+OBruWPjuWFpeOAgemFjeWBtuiAheOBruWPjuWFpeOCkuOBmeOBueOBpuWQq+OCgeOBn+OCguOBruOCkuOAgeS7peS4i+OBrueJqeW3ruOBl+OCkuOCueODqeOCpOODieOBleOBm+OBquOBjOOCieOAgeOBiuOBiuOBvuOBi+OBq+aMh+WumuOBl+OBpuOBj+OBoOOBleOBhOOAgiDjgYTjgZrjgozjgoLjgYzjgIwzMDAw5LiH5YaG5Lul5LiK44CN44Gu5Lq644Gv44CB44CMMzAwMOOAjeOCkumBuOaKnuOBl+OBpuOBj+OBoOOBleOBhOOAgiB8IOeojuW8leOBjeWJjeS4luW4r+W5tOWPjuODu+aJi+WPluOCiuW5tOWPjuOBrjLpoIXnm67jgIIw772eMzAwMOS4h+WGhuOBruOCueODqeOCpOODgOODvO+8iDMwMDDvvJ0zMDAw5LiH5YaG5Lul5LiK77yJIHwKIyMjIEouMS4zIOOCs+ODs+OCuOODp+OCpOODs+ODiOiqsumhjArlm57nrZTogIXjga/jgIEy44O7M+ODuzTjg7s15pS/5YWa44Gu44GE44Ga44KM44GLMeadoeS7tuOBq+eEoeS9nOeCuuOBq+WJsuOCiuW9k+OBpuOCieOCjOOAgeWQjOOBmOmBuOaKnuiCouaVsOOBruiqsumhjOOBqzXlm57nrZTjgYjjgZ/jgILlkIToqrLpoYzjgafjga/jgIHkuIvooajjga435bGe5oCn44Gu5rC05rqW44GM44OX44Ot44OV44Kj44O844Or44GU44Go44Gr54Sh5L2c54K644Gr5o+Q56S644GV44KM44Gf44CCCnwg5bGe5oCnIHwg5rC05rqWIHwKfC0tLXwtLS18Cnwg5pS/562W5L2N572uIHwg5Y+z5rS+44O75L+d5a6I55qE77yP5Lit6YGT77yP5bem5rS+44O76Z2p5paw55qEIHwKfCDkuI7ph47lhZrlnLDkvY0gfCDkuI7lhZrvvI/ph47lhZogfAp8IOitsOW4reaVsCB8IDEw5Lul5LiL77yPMTDvvZ40Oe+8jzUw772eOTnvvI8xMDDvvZ4xOTnvvI8yMDDku6XkuIogfAp8IEdEUOaIkOmVt+eOhyB8IMKxMO+8he+8j+ODl+ODqeOCuTHvvIXvvI/jg57jgqTjg4rjgrkx77yFIHwKfCDml6XntYzlubPlnYfmoKrkvqEgfCDliY3mnIjlkIzmnJ/mr5Qg5aSJ44KP44KJ44Ga77yP44OX44Op44K5MTAwMOWGhu+8j+ODnuOCpOODiuOCuTEwMDDlhoYgfAp8IENQSSB8IOWJjeacn+avlCDCsTDjg53jgqTjg7Pjg4jvvI/jg5fjg6njgrkx44Od44Kk44Oz44OI77yP44Oe44Kk44OK44K5MeODneOCpOODs+ODiCB8Cnwg5aSx5qWt546HIHwg5YmN5pyf5q+UIMKxMO+8he+8j+ODl+ODqeOCuTHvvIXvvI/jg57jgqTjg4rjgrkx77yFIHwKCioq5p2h5Lu25Yil44Gu6Kqs5piO5paH44O76YG45oqe6Kqy6aGMKioKCiMjIyMgMuaUv+WFmuadoeS7tu+8iCRrPTIk77yJCioq5bCO5YWl6LOq5ZWPIFEyNjAqKiAgCuS7iuOBi+OCieOAgeaXpeacrOOBruaUv+WFmuOCgeOBkOOCi++8kuOBpOOBrumBuOaKnuiCouOCkumghuOBq+aPkOekuuOBl+OBpuOBhOOBjeOBvuOBmeOAgiDjgZ3jgZfjgabjgIHooYborbDpmaLnt4/pgbjmjJnjgYzjgYLjgovjgajjgYrogIPjgYjkuIvjgZXjgYTjgILjgZ3jga7mmYLjgIHjgYLjgarjgZ/jga/vvJPjgaTjga7pgbjmip7ogqLjga7kuK3jgYvjgonjganjga7mlL/lhZrjgpLpgbjmip7jgZXjgozjgovjgYvjgIHvvJHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgIIg5L2c5qWt44Gv77yV5Zue57mw44KK6L+U44GV44KM44G+44GZ44CCCgrlm57nrZTvvJrjgIzkuIroqJjjga7mlofnq6DjgpLoqq3jgpPjgaDjgIIgKDEp44CNCgoqKumBuOaKnuiqsumhjCBRMjQwLCBRMjUzLCBRMjU0LCBRMjU1LCBRMjU277yINeWbnu+8iSoqICAK5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLMuOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jganjgaHjgonjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIg5pS/5YWaMSDmlL/lhZoyICR7ZTovL0ZpZWxkL0YtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMi0xfSAke2U6Ly9GaWVsZC9GLTEtMn0gJHtlOi8vRmllbGQvRi0xLTEtMn0gJHtlOi8vRmllbGQvRi0xLTItMn0gJHtlOi8vRmllbGQvRi0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0yLTN9ICR7ZTovL0ZpZWxkL0YtMS00fSAke2U6Ly9GaWVsZC9GLTEtMS00fSAke2U6Ly9GaWVsZC9GLTEtMi00fSAke2U6Ly9GaWVsZC9GLTEtNX0gJHtlOi8vRmllbGQvRi0xLTEtNX0gJHtlOi8vRmllbGQvRi0xLTItNX0gJHtlOi8vRmllbGQvRi0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0yLTZ9ICR7ZTovL0ZpZWxkL0YtMS03fSAke2U6Ly9GaWVsZC9GLTEtMS03fSAke2U6Ly9GaWVsZC9GLTEtMi03fQoK5Zue562U6YG45oqe6IKi77ya5pS/5YWaMSAoMSnvvI/mlL/lhZoyICgyKQoKIyMjIyAz5pS/5YWa5p2h5Lu277yIJGs9MyTvvIkKKirlsI7lhaXos6rllY8gUTI1NyoqICAK5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yT44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBr++8k+OBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIIKCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0KCioq6YG45oqe6Kqy6aGMIFEyMzUsIFEyNDEsIFEyNDIsIFEyNDMsIFEyNDTvvIg15Zue77yJKiogIArku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgovvvJPjgaTjga7pgbjmip7ogqLjgpLmj5DnpLrjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgIIg44GC44Gq44Gf44Gv44CB6KGG6K2w6Zmi6K2w5ZOh57eP6YG45oyZ44Gr44GK44GE44Gm44CB5Lul5LiL44Gu44Gp44Gh44KJ44Gu5pS/5YWa44KS44GK6YG444Gz44Gr44Gq44KK44G+44GZ44GL44CCIOaUv+WFmjEg5pS/5YWaMiDmlL/lhZozICR7ZTovL0ZpZWxkL0YtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMi0xfSAke2U6Ly9GaWVsZC9GLTEtMy0xfSAke2U6Ly9GaWVsZC9GLTEtMn0gJHtlOi8vRmllbGQvRi0xLTEtMn0gJHtlOi8vRmllbGQvRi0xLTItMn0gJHtlOi8vRmllbGQvRi0xLTMtMn0gJHtlOi8vRmllbGQvRi0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0yLTN9ICR7ZTovL0ZpZWxkL0YtMS0zLTN9ICR7ZTovL0ZpZWxkL0YtMS00fSAke2U6Ly9GaWVsZC9GLTEtMS00fSAke2U6Ly9GaWVsZC9GLTEtMi00fSAke2U6Ly9GaWVsZC9GLTEtMy00fSAke2U6Ly9GaWVsZC9GLTEtNX0gJHtlOi8vRmllbGQvRi0xLTEtNX0gJHtlOi8vRmllbGQvRi0xLTItNX0gJHtlOi8vRmllbGQvRi0xLTMtNX0gJHtlOi8vRmllbGQvRi0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0yLTZ9ICR7ZTovL0ZpZWxkL0YtMS0zLTZ9ICR7ZTovL0ZpZWxkL0YtMS03fSAke2U6Ly9GaWVsZC9GLTEtMS03fSAke2U6Ly9GaWVsZC9GLTEtMi03fSAke2U6Ly9GaWVsZC9GLTEtMy03fQoK5Zue562U6YG45oqe6IKi77ya5pS/5YWaMSAoMSnvvI/mlL/lhZoyICgyKe+8j+aUv+WFmjMgKDMpCgojIyMjIDTmlL/lhZrmnaHku7bvvIgkaz00JO+8iQoqKuWwjuWFpeizquWVjyBRMjU4KiogIArku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJTjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44Gv77yT44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu5pS/5YWa44KS6YG45oqe44GV44KM44KL44GL44CB77yR44Gk6YG444KT44Gn44GK562U44GI44GP44Gg44GV44GE44CCIOS9nOalreOBr++8leWbnue5sOOCiui/lOOBleOCjOOBvuOBmeOAggoK5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQoKKirpgbjmip7oqrLpoYwgUTIzOCwgUTI0NSwgUTI0NiwgUTI0NywgUTI0OO+8iDXlm57vvIkqKiAgCuS7peS4i+OBq+OAgeaXpeacrOOBruaUv+WFmuOCkuOCgeOBkOOCi++8lOOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jganjgaHjgonjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIg5pS/5YWaMSDmlL/lhZoyIOaUv+WFmjMg5pS/5YWaNCAke2U6Ly9GaWVsZC9GLTEtMX0gJHtlOi8vRmllbGQvRi0xLTEtMX0gJHtlOi8vRmllbGQvRi0xLTItMX0gJHtlOi8vRmllbGQvRi0xLTMtMX0gJHtlOi8vRmllbGQvRi0xLTQtMX0gJHtlOi8vRmllbGQvRi0xLTJ9ICR7ZTovL0ZpZWxkL0YtMS0xLTJ9ICR7ZTovL0ZpZWxkL0YtMS0yLTJ9ICR7ZTovL0ZpZWxkL0YtMS0zLTJ9ICR7ZTovL0ZpZWxkL0YtMS00LTJ9ICR7ZTovL0ZpZWxkL0YtMS0zfSAke2U6Ly9GaWVsZC9GLTEtMS0zfSAke2U6Ly9GaWVsZC9GLTEtMi0zfSAke2U6Ly9GaWVsZC9GLTEtMy0zfSAke2U6Ly9GaWVsZC9GLTEtNC0zfSAke2U6Ly9GaWVsZC9GLTEtNH0gJHtlOi8vRmllbGQvRi0xLTEtNH0gJHtlOi8vRmllbGQvRi0xLTItNH0gJHtlOi8vRmllbGQvRi0xLTMtNH0gJHtlOi8vRmllbGQvRi0xLTQtNH0gJHtlOi8vRmllbGQvRi0xLTV9ICR7ZTovL0ZpZWxkL0YtMS0xLTV9ICR7ZTovL0ZpZWxkL0YtMS0yLTV9ICR7ZTovL0ZpZWxkL0YtMS0zLTV9ICR7ZTovL0ZpZWxkL0YtMS00LTV9ICR7ZTovL0ZpZWxkL0YtMS02fSAke2U6Ly9GaWVsZC9GLTEtMS02fSAke2U6Ly9GaWVsZC9GLTEtMi02fSAke2U6Ly9GaWVsZC9GLTEtMy02fSAke2U6Ly9GaWVsZC9GLTEtNC02fSAke2U6Ly9GaWVsZC9GLTEtN30gJHtlOi8vRmllbGQvRi0xLTEtN30gJHtlOi8vRmllbGQvRi0xLTItN30gJHtlOi8vRmllbGQvRi0xLTMtN30gJHtlOi8vRmllbGQvRi0xLTQtN30KCuWbnuetlOmBuOaKnuiCou+8muaUv+WFmjEgKDEp77yP5pS/5YWaMiAoMinvvI/mlL/lhZozICgzKe+8j+aUv+WFmjQgKDQpCgojIyMjIDXmlL/lhZrmnaHku7bvvIgkaz01JO+8iQoqKuWwjuWFpeizquWVjyBRMjU5KiogIArku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJXjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44Gv77yT44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu5pS/5YWa44KS6YG45oqe44GV44KM44KL44GL44CB77yR44Gk6YG444KT44Gn44GK562U44GI44GP44Gg44GV44GE44CCIOS9nOalreOBr++8leWbnue5sOOCiui/lOOBleOCjOOBvuOBmeOAggoK5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQoKKirpgbjmip7oqrLpoYwgUTIzOSwgUTI0OSwgUTI1MCwgUTI1MSwgUTI1Mu+8iDXlm57vvIkqKiAgCuS7peS4i+OBq+OAgeaXpeacrOOBruaUv+WFmuOCkuOCgeOBkOOCi++8leOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jganjgaHjgonjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIg5pS/5YWaMSDmlL/lhZoyIOaUv+WFmjMg5pS/5YWaNCDmlL/lhZo1ICR7ZTovL0ZpZWxkL0YtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMi0xfSAke2U6Ly9GaWVsZC9GLTEtMy0xfSAke2U6Ly9GaWVsZC9GLTEtNC0xfSAke2U6Ly9GaWVsZC9GLTEtNS0xfSAke2U6Ly9GaWVsZC9GLTEtMn0gJHtlOi8vRmllbGQvRi0xLTEtMn0gJHtlOi8vRmllbGQvRi0xLTItMn0gJHtlOi8vRmllbGQvRi0xLTMtMn0gJHtlOi8vRmllbGQvRi0xLTQtMn0gJHtlOi8vRmllbGQvRi0xLTUtMn0gJHtlOi8vRmllbGQvRi0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0yLTN9ICR7ZTovL0ZpZWxkL0YtMS0zLTN9ICR7ZTovL0ZpZWxkL0YtMS00LTN9ICR7ZTovL0ZpZWxkL0YtMS01LTN9ICR7ZTovL0ZpZWxkL0YtMS00fSAke2U6Ly9GaWVsZC9GLTEtMS00fSAke2U6Ly9GaWVsZC9GLTEtMi00fSAke2U6Ly9GaWVsZC9GLTEtMy00fSAke2U6Ly9GaWVsZC9GLTEtNC00fSAke2U6Ly9GaWVsZC9GLTEtNS00fSAke2U6Ly9GaWVsZC9GLTEtNX0gJHtlOi8vRmllbGQvRi0xLTEtNX0gJHtlOi8vRmllbGQvRi0xLTItNX0gJHtlOi8vRmllbGQvRi0xLTMtNX0gJHtlOi8vRmllbGQvRi0xLTQtNX0gJHtlOi8vRmllbGQvRi0xLTUtNX0gJHtlOi8vRmllbGQvRi0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0yLTZ9ICR7ZTovL0ZpZWxkL0YtMS0zLTZ9ICR7ZTovL0ZpZWxkL0YtMS00LTZ9ICR7ZTovL0ZpZWxkL0YtMS01LTZ9ICR7ZTovL0ZpZWxkL0YtMS03fSAke2U6Ly9GaWVsZC9GLTEtMS03fSAke2U6Ly9GaWVsZC9GLTEtMi03fSAke2U6Ly9GaWVsZC9GLTEtMy03fSAke2U6Ly9GaWVsZC9GLTEtNC03fSAke2U6Ly9GaWVsZC9GLTEtNS03fQoK5Zue562U6YG45oqe6IKi77ya5pS/5YWaMSAoMSnvvI/mlL/lhZoyICgyKe+8j+aUv+WFmjMgKDMp77yP5pS/5YWaNCAoNCnvvI/mlL/lhZo1ICg1KQoK5a6f6aiTMeOBq+OBr+OAgeWun+mokzLjg7sz44Gn55So44GE44Gf6YG45oqe6IKi5pWw44Gu5pON5L2c56K66KqN6LOq5ZWP44GK44KI44Gz44Kk44OH44Kq44Ot44Ku44O86KGM5YiX5Lit44Gu5oyH56S66aCF55uu44Gv6Kit44GR44KJ44KM44Gm44GE44Gq44GE44CCCiMjIyBKLjEuNCDoqr/mn7votqPml6jjga7lho3oqqzmmI7jgajmnIDntYLpgIHkv6HlkIzmhI8KPGRldGFpbHM+CjxzdW1tYXJ5PjxzdHJvbmc+UTEwLjEg44OH44OW44Oq44O844OV44Kj44Oz44Kw44O75pyA57WC5oSP5oCd56K66KqN77yI44Kv44Oq44OD44Kv44GX44Gm5YWo5paH44KS6KGo56S677yJPC9zdHJvbmc+PC9zdW1tYXJ5PgoKPHA+44GT44Gh44KJ44GM6Kq/5p+744Gu5pyA5b6M44Gu55S76Z2i44Gn44GC44KL44CM6Kq/5p+76Laj5peo44Gu5YaN6Kqs5piO44CN44Go44CM5Zue562U57WQ5p6c44Gu6YCB5L+h44Gr6Zai44GZ44KL5pyA57WC5oSP5oCd56K66KqN44CN44Gu44Oa44O844K444Gr44Gq44KK44G+44GZ44CCIOODu+acrOiqv+afu+OBp+OBr+OAgeaUv+ayu+OAgee1jOa4iOOBq+mWouOBmeOCi+aEj+itmOOBquOBqeOCkuOBiuS8uuOBhOOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAguiqv+afu+OBq+OBlOWNlOWKm+OBhOOBn+OBoOOBjeOBvuOBl+OBn+OBk+OBqOOBq+OAgea3seOBj+aEn+isneeUs+OBl+S4iuOBkuOBvuOBmeOAgiDjg7vmnKzoqr/mn7vjgavplqLjgZfjgabjgZTkuI3mmI7jgarngrnnrYnjgYzjgZTjgZbjgYTjgb7jgZfjgZ/jgonjgIHkuIvoqJjjg6Hjg7zjg6vjgqLjg4njg6zjgrnjgb7jgafjgYrllY/jgYTlkIjjgo/jgZvjgY/jgaDjgZXjgYTjgIIgZS1tYWlsOiBoYW5ha29vaG11cmE2MTAzMUBnbWFpbC5jb20g44O7IOe5sOOCiui/lOOBl+OBqOOBquOCiuOBvuOBmeOBjOOAgeW+l+OCieOCjOOBn+WbnuetlOOBr+OBmeOBueOBpue1seioiOeahOOBq+WHpueQhuOBl+OAgeWbnuetlOiAheOBruWxnuaAp+OBquOBqeOBjOOCj+OBi+OCieOBquOBhOOCiOOBhuOBq+OBl+OBvuOBmeOAguWAi+S6uuOBruaDheWgseOBjOeJueWumuOBleOCjOOCi+OBk+OBqOOBr+OBguOCiuOBvuOBm+OCk+OBruOBp+OAgeOBlOWuieW/g+OBj+OBoOOBleOBhOOAguOBneOCjOOBp+OCguWAi+S6uuaDheWgseOBruS/neitt+etieOBq+mWouOBl+OBpuOAgeWbnuetlOiAheOBp+OBguOCi+OBguOBquOBn+OBjOOBlOS4jeWuieOCkuaEn+OBmOOCieOCjOOCi+WgtOWQiOOBq+OBr+OAjOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBquOBhOOBruOBp+OAgeWbnuetlOOCkumAgeS/oeOBl+OBquOBhOOAjeOBqOOBhOOBhumBuOaKnuOCkuOBmeOCi+OBk+OBqOOCguWPr+iDveOBp+OBmeOAgiDku6XkuIvjgafjga/jgIHmnKzoqr/mn7vjgavjgYrjgZHjgovjgYTjgY/jgaTjgYvjga7lh6bnva7jg7vmk43kvZzjgavjgaTjgY3jgb7jgZfjgabjgIHjgZ3jga7nm67nmoTjg7vog4zmma/jg7vku5XntYTjgb/jgpLjgIHjgojjgoroqbPjgZfjgY/op6PoqqzjgpLjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgILlj6/og73jgarpmZDjgorjgZTkuIDoqq3jgYTjgZ/jgaDjgY3jgIHjgIzmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZnjgovjga7jgafjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgovjgI3jgYvjgIzmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZfjgarjgYTjga7jgafjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZfjgarjgYTjgI3jgpLjgZTpgbjmip7jgY/jgaDjgZXjgYTjgb7jgZnjgojjgYbjgojjgo3jgZfjgY/jgYrpoZjjgYTjgYTjgZ/jgZfjgb7jgZnjgIIg5LiK6KiY44Gu5YaF5a6544KS44GU56K66KqN44GE44Gf44Gg44GE44Gf5LiK44Gn44CB5pS544KB44Gm44CM5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5Zue562U57WQ5p6c44KS6YCB5L+h44GX44Gq44GE44CN44Go44GE44GG6YG45oqe44KS44GZ44KL44GT44Go44KC5Y+v6IO944Gn44GZ44Gu44Gn44CB5Lul5LiL44Gn44GU6YG45oqe44GP44Gg44GV44GE44CCPC9wPgoKPC9kZXRhaWxzPgoKKirlm57nrZTpgbjmip7ogqIqKgoKLSDmnKzoqr/mn7vjga7kuLvml6jjgavlkIzmhI/jgZfjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgovjgIIgKDEpCi0g5pys6Kq/5p+744Gu5Li75peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5Zue562U57WQ5p6c44KS6YCB5L+h44GX44Gq44GE44CCICgyKQoK6Kq/5p+756Wo5pyr5bC+44Gr44GvUTI2MeOAjOOBk+OBk+OCkuOCr+ODquODg+OCr+OBl+OBpuizquWVj+aWh+OCkuWFpeWKm+OAjeOBqOOBhOOBhlF1YWx0cmljc+S4iuOBruacquS9v+eUqOODl+ODrOODvOOCueODm+ODq+ODgOODvOOBjOaui+OBo+OBpuOBhOOCi+OBjOOAgSDlrp/os6rnmoTjgaroqr/mn7vpoIXnm67jgafjga/jgarjgYTjgZ/jgoHjgIHmnKznr4Djga7os6rllY/kuIDopqfjgYvjgonjga/pmaTlpJbjgZfjgZ/jgIIKIyMgSi4yIOWun+mokzLvvIgyMDI25bm077yJCiMjIyBKLjIuMSDoqr/mn7vplovlp4vmmYLjga7oqqzmmI7jgajlkIzmhI8KPGRldGFpbHM+CjxzdW1tYXJ5PjxzdHJvbmc+UTEuMSDoqr/mn7voqqzmmI7vvIjjgq/jg6rjg4Pjgq/jgZfjgablhajmlofjgpLooajnpLrvvIk8L3N0cm9uZz48L3N1bW1hcnk+Cgo8cD7jgIzntYzmuIjoqZXkvqHjgajmlL/mqKnpgYvllrbjgpLjgoHjgZDjgovmhI/orZjoqr/mn7vjgI0g44GU5Y2U5Yqb44Gu44GK6aGY44GEIOS6rOmDveWkp+WtpiDlhazlhbHmlL/nrZbpgKPmkLrnoJTnqbbpg6gg5pWZ5o6IIOWkp+adkSDoj6/lrZAg77yI44GK44GK44KA44KJIOOBr+OBquOBk++8iSDil4Yg44GT44Gu44Ki44Oz44Kx44O844OI6Kq/5p+744Gv44CB5paH6YOo56eR5a2m55yB44Gr44KI44KL56CU56m25Yqp5oiQ77yI56CU56m26Kqy6aGM55Wq5Y+377yaMjZLMDQ3NTHjgIzmlL/nrZbmpa3nuL7oqZXkvqHjga7noJTnqbbvvI3mlL/msrvooYzli5Xoq5bjgajooYzli5XlhazlhbHmlL/nrZboq5bjga7mnrbmqYvjgI3vvInjgavln7rjgaXjgY3lrp/mlr3jgZXjgozjgovlrabooZPoqr/mn7vjgafjgZnjgIIg4peGIOWWtuWIqeebrueahOOChOOAgeeJueWumuOBruaUv+ayu+WLouWKm+OCkuaUr+aPtOOBmeOCi+OBn+OCgeOBruOCouODs+OCseODvOODiOiqv+afu+OBp+OBr+OBguOCiuOBvuOBm+OCk+OAguOBvuOBn+OAgeOBguOBquOBn+OBjOOBk+OBruiqv+afu+OBq+WNlOWKm+OBmeOCi+OBk+OBqOOBq+OCiOOBo+OBpuOAgeS4jeWIqeebiuOCkuiiq+OCi+OBk+OBqOOCguOBguOCiuOBvuOBm+OCk+OAgiDil4Yg5pys6Kq/5p+744Gn44Gv44CB44GC44Gq44Gf44Gu5pS/5rK744CB57WM5riI44Gr6Zai44GZ44KL5oSP6K2Y44Gq44Gp44KC44GK5Ly644GE44GZ44KL44GT44Go44Gr44Gq44KK44G+44GZ44Gu44Gn44CB44GU5om/55+l44GK44GN44GE44Gf44Gg44GN44Gf44GP5a2Y44GY44G+44GZ44CC44KC44GX5Zue562U44KS5LiN5b+r44Gr5oSf44GY44KJ44KM44Gf5aC05ZCI44CB44GC44Gq44Gf44Gv44GE44Gk44Gn44KC5Zue562U44KS44KE44KB44KL44GT44Go44GM44Gn44GN44G+44GZ44CCIOKXhiDjgb7jgZ/mnKzoqr/mn7vjgafjga/jgIHjgYLjgarjgZ/jga7miYDlvpfjgavjgaTjgYTjgabjgoLjgYrlsIvjga3jgZfjgb7jgZnjgILjgoLjgZflm57nrZTjgpLkuI3lv6vjgavmhJ/jgZjjgonjgozjgZ/loLTlkIjjgIHjgYLjgarjgZ/jga/jgYTjgaTjgafjgoLlm57nrZTjgpLjgoTjgoHjgovjgZPjgajjgYzjgafjgY3jgb7jgZnjgIIg4peGIOaUv+ayu+OChOihjOaUv+OBq+OBpOOBhOOBpuOBruizquWVj+OBq+OBr+OAgeetlOOBiOOBpeOCieOBhOOCguOBruOCguOBguOCiuOBvuOBmeOAguOCguOBl+WbnuetlOOCkuS4jeW/q+OBq+aEn+OBmOOCieOCjOOBn+WgtOWQiOOAgeOBguOBquOBn+OBr+OBhOOBpOOBp+OCguWbnuetlOOCkuOChOOCgeOCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAgiDil4Yg5b6X44KJ44KM44Gf5Zue562U44Gv44GZ44G544Gm57Wx6KiI55qE44Gr5Yem55CG44GX44CB5Zue562U6ICF44Gu5bGe5oCn44Gq44Gp44GM44KP44GL44KJ44Gq44GE44KI44GG44Gr44GX44G+44GZ44CC5YCL5Lq644Gu5oOF5aCx44GM54m55a6a44GV44KM44KL44GT44Go44Gv44GC44KK44G+44Gb44KT44Gu44Gn44CB5a6J5b+D44GX44Gm44GU5Zue562U44GP44Gg44GV44GE44CCIOKXhiDjgqLjg7PjgrHjg7zjg4joqr/mn7vjga7liIbmnpDntZDmnpzjgavjgaTjgYTjgabjga/jgIHmlrDogZ7jgarjganjgpLpgJrjgZjjgabkuIDoiKzjga7kurrjgavlr77jgZfjgabjgoLnqY3mpbXnmoTjgavnmbrkv6HjgZnjgovkuojlrprjgafjgZnjgILnmobjgZXjgb7jga7jgZTljZTlipvjga7nqIvjgIHjgojjgo3jgZfjgY/jgYrpoZjjgYTnlLPjgZfkuIrjgZLjgb7jgZnjgIIg4peGIOS4jemBqeWIh+OBquWbnuetlOOCkuihjOOBhuOBk+OBqOOBr+OAgeiqv+afu+e1kOaenOOBruizquOCkuS9juS4i+OBleOBm+OBvuOBmeOAguOBmeOBueOBpuOBruizquWVj+OBq+WvvuOBl+OBpuOAgeS4jemBqeWIh+OBquW9ouOBp+WbnuetlOOBl+OBquOBhOOCiOOBhuOAgeOCiOOCjeOBl+OBj+OBiumhmOOBhOeUs+OBl+S4iuOBkuOBvuOBmeOAguS4jemBqeWIh+OBquWbnuetlOOCkuihjOOBo+OBn+WgtOWQiOOBr+OAgeiqv+afu+OCkue1guS6huOBleOBm+OBpumgguOBj+WgtOWQiOOBjOOBlOOBluOBhOOBvuOBmeOAgiDil4Yg5pys44Ki44Oz44Kx44O844OI6Kq/5p+744Gr6Zai44GX44Gm44GU5LiN5piO44Gq54K5562J44GM44GU44GW44GE44G+44GX44Gf44KJ44CB5LiL6KiY44Oh44O844Or44Ki44OJ44Os44K544G+44Gn44GK5ZWP44GE5ZCI44KP44Gb44GP44Gg44GV44GE44CCIGUtbWFpbDogaGFuYWtvb2htdXJhNjEwMzFAZ21haWwuY29tIOS7peS4iuOCkuOBlOeiuuiqjeOBruS4iuOAgeiqv+afu+OCkumWi+Wni+OBmeOCi+WgtOWQiOOBr+OAgSDjgIzmnKzoqr/mn7vjga7otqPml6jjgajlgIvkurrmg4XloLHjga7lj5bjgormibHjgYTjgavlkIzmhI/jgZfjgabjgIHoqr/mn7vjgpLplovlp4vjgZnjgovjgI0g44Oc44K/44Oz44KS44Kv44Oq44OD44Kv44GX44Gm44CB5Y+z5LiL44Gu44CM77ye77ye44CN44G+44Gf44Gv44CM5qyh44G444CN44Oc44K/44Oz44KS5oq844GX44Gm44CB6Kq/5p+744KS6ZaL5aeL44GX44Gm44GP44Gg44GV44GE44CCPC9wPgoKPC9kZXRhaWxzPgoKKirlm57nrZTpgbjmip7ogqIqKgoKLSDmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZfjgabjgIHmnKzoqr/mn7vjgavljZTlipvjgZnjgosgKDEpCi0g5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5pys6Kq/5p+744Gr5Y2U5Yqb44GX44Gq44GEICgyKQoKIyMjIEouMi4yIOODleOCp+OCpOOCueOCt+ODvOODiAp8IOizquWVj0lEIHwg6LOq5ZWP5paHIHwg5Zue562U5b2i5byP44O76YG45oqe6IKiIHwKfC0tLXwtLS18LS0tfAp8IFEyLjEgfCDjgYLjgarjgZ/jga7mgKfliKXjgpLpgbjjgpPjgafjgY/jgaDjgZXjgYTjgIIgfCDnlLfmgKcgKDEp77yP5aWz5oCnICgyKe+8j+OBneOBruS7liAoMynvvI/jgZPjgZ/jgYjjgZ/jgY/jgarjgYQgKDQpIHwKfCBRMi4yIHwg44GC44Gq44Gf44Gu5bm06b2i5Yy65YiG44Go54++5Zyo44Gu5bm06b2i44KS6YG444KT44Gn44GP44Gg44GV44GE44CCIHwg44CM5bm05Luj44CN44Go44CM5bm06b2i44CN44Gu6YCj5YuV44OJ44Ot44OD44OX44OA44Km44Oz44CC6Kq/5p+756Wo44Ko44Kv44K544Od44O844OI5LiK44Gn44Gv6YG45oqe6IKi5LiA6Kan44GM55yB55Wl6KGo56S644GV44KM44Gm44GE44KL44CCIHwKfCBRMi4zIHwg44GC44Gq44Gf44GM54++5Zyo44GK5L2P44G+44GE44Gu5Zyw5Z+f44Go6YO96YGT5bqc55yM44KS6YG444KT44Gn44GP44Gg44GV44GEIHwg44CM5Zyw5Z+f44CN44Go44CM6YO96YGT5bqc55yM44CN44Gu6YCj5YuV44OJ44Ot44OD44OX44OA44Km44Oz44CC6Kq/5p+756Wo44Ko44Kv44K544Od44O844OI5LiK44Gn44Gv6YG45oqe6IKi5LiA6Kan44GM55yB55Wl6KGo56S644GV44KM44Gm44GE44KL44CCIHwKfCBRMi40IHwg44GC44Gq44Gf44Gu5LiW5biv44Gu56iO5byV44GN5YmN44Gu5LiW5biv5bm05Y+O44Go5omL5Y+W44KK44Gu5bm05Y+O44Gv44CB44Gg44GE44Gf44GE44GK44GE44GP44KJ44GQ44KJ44GE44Gn44GX44KH44GG44GL44CCIOeojuW8leOBjeWJjeOBruWPjuWFpeOBqOOBr+OAgeS4gOiIrOeahOOBq+OAjOmhjemdouOBruWPjuWFpeOAjeOBqOiogOOCj+OCjOOCi+OCguOBruOBp+OBmeOAguOBneOBrumhjemdouOBruWPjuWFpeOBi+OCieOAgeeojumHkeOChOekvuS8muS/nemZuuaWmeOCkuW8leOBhOOBn+aui+OCiuOBjOOAjOaJi+WPluOCiuOBruWPjuWFpeOAjeOBqOiogOOCj+OCjOOCi+OCguOBruOBp+OBmeOAgiDjgYLjgarjgZ/jga7lj47lhaXjgIHphY3lgbbogIXjga7lj47lhaXjgpLjgZnjgbnjgablkKvjgoHjgZ/jgoLjga7jgpLjgIHku6XkuIvjga7nianlt67jgZfjgpLjgrnjg6njgqTjg4njgZXjgZvjgarjgYzjgonjgIHjgYrjgYrjgb7jgYvjgavmjIflrprjgZfjgabjgY/jgaDjgZXjgYTjgIIg44GE44Ga44KM44KC44GM44CMMzAwMOS4h+WGhuS7peS4iuOAjeOBruS6uuOBr+OAgeOAjDMwMDDjgI3jgpLpgbjmip7jgZfjgabjgY/jgaDjgZXjgYTjgIIgfCDnqI7lvJXjgY3liY3kuJbluK/lubTlj47jg7vmiYvlj5bjgorlubTlj47jga4y6aCF55uu44CCMO+9njMwMDDkuIflhobjga7jgrnjg6njgqTjg4Djg7zvvIgzMDAw77ydMzAwMOS4h+WGhuS7peS4iu+8iSB8CiMjIyBKLjIuMyDjgrPjg7Pjgrjjg6fjgqTjg7Pjg4joqrLpoYwK5Zue562U6ICF44GvMuODuzPjg7s044O7NeaUv+WFmuOBruOBhOOBmuOCjOOBizHmnaHku7bjgavnhKHkvZzngrrjgavlibLjgorlvZPjgabjgonjgozjgIE144Gk44Gu6YG45oqe6Kqy6aGM44Gr5Zue562U44GX44Gf44CC44OX44Ot44OV44Kj44O844Or44Gr44Gv5qyh44GuN+WxnuaAp+OBjOaPkOekuuOBleOCjOOBn+OAggp8IOWxnuaApyB8IOawtOa6liB8CnwtLS18LS0tfAp8IOaUv+etluS9jee9riB8IOWPs+a0vuODu+S/neWuiOeahO+8j+S4remBk++8j+W3pua0vuODu+mdqeaWsOeahCB8Cnwg5LiO6YeO5YWa5Zyw5L2NIHwg5LiO5YWa77yP6YeO5YWaIHwKfCDorbDluK3mlbAgfCAxMOS7peS4i++8jzEw772eNDnvvI81MO+9njk577yPMTAw772eMTk577yPMjAw5Lul5LiKIHwKfCBHRFDmiJDplbfnjocgfCDCsTDvvIXvvI/jg5fjg6njgrkx77yF77yP44Oe44Kk44OK44K5Me+8hSB8Cnwg5pel57WM5bmz5Z2H5qCq5L6hIHwg5YmN5pyI5ZCM5pyf5q+UIOWkieOCj+OCieOBmu+8j+ODl+ODqeOCuTEwMDDlhobvvI/jg57jgqTjg4rjgrkxMDAw5YaGIHwKfCBDUEkgfCDliY3mnJ/mr5QgwrEw44Od44Kk44Oz44OI77yP44OX44Op44K5MeODneOCpOODs+ODiO+8j+ODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4ggfAp8IOWksealreeOhyB8IOWJjeacn+avlCDCsTDvvIXvvI/jg5fjg6njgrkx77yF77yP44Oe44Kk44OK44K5Me+8hSB8CgoqKuadoeS7tuWIpeOBruiqrOaYjuaWh+ODu+mBuOaKnuiqsumhjOODu+aTjeS9nOeiuuiqjSoqCgojIyMjIDLmlL/lhZrmnaHku7bvvIgkaz0yJO+8iQoqKuWwjuWFpeizquWVjyBRNi4xKiogIArku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJLjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44GvMuOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIIKCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0KCioq6YG45oqe6Kqy6aGMIFE2LjLigJNRNi4277yINeWbnu+8iSoqICAK5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLMuOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jgYTjgZrjgozjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIKCuWbnuetlOmBuOaKnuiCou+8muaUv+WFmjEgKDEp77yP5pS/5YWaMiAoMikKCioq5pON5L2c56K66KqNIFE2LjcqKiAgCuOBguOBquOBn+OBq+OBr+OAgeikh+aVsOOBrumBuOaKnuiCouOBruS4reOBi+OCiTHjgaTjga7nirbms4HjgpLpgbjjgpPjgafjgoLjgonjgYbkvZzmpa3jgpLooYzjgaPjgabjgYTjgZ/jgaDjgY3jgb7jgZfjgZ/jgIIg44GC44Gq44Gf44Gr5o+Q56S644GV44KM44Gf5pS/5YWa44Gu6YG45oqe6IKi44Gu5pWw44Gv44CB44GE44GP44Gk44Gn44GX44Gf44GL44CCCgrlm57nrZTpgbjmip7ogqLvvJoxICgxKe+8jzIgKDIp77yPMyAoMynvvI80ICg0Ke+8jzUgKDUp77yP44GK44G844GI44Gm44GE44Gq44GEICg2KQoKIyMjIyAz5pS/5YWa5p2h5Lu277yIJGs9MyTvvIkKKirlsI7lhaXos6rllY8gUTMuMSoqICAK5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yT44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBr++8k+OBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIIKCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0KCioq6YG45oqe6Kqy6aGMIFEzLjLigJNRMy4277yINeWbnu+8iSoqICAK5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLM+OBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jgYTjgZrjgozjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIKCuWbnuetlOmBuOaKnuiCou+8muaUv+WFmjEgKDEp77yP5pS/5YWaMiAoMinvvI/mlL/lhZozICgzKQoKKirmk43kvZznorroqo0gUTMuNyoqICAK44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/mlL/lhZrjga7pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIIKCuWbnuetlOmBuOaKnuiCou+8mjEgKDEp77yPMiAoMinvvI8zICgzKe+8jzQgKDQp77yPNSAoNSnvvI/jgYrjgbzjgYjjgabjgYTjgarjgYQgKDYpCgojIyMjIDTmlL/lhZrmnaHku7bvvIgkaz00JO+8iQoqKuWwjuWFpeizquWVjyBRNC4xKiogIArku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJTjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44GvNOOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIIKCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0KCioq6YG45oqe6Kqy6aGMIFE0LjLigJNRNC4277yINeWbnu+8iSoqICAK5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLNOOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jgYTjgZrjgozjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIKCuWbnuetlOmBuOaKnuiCou+8muaUv+WFmjEgKDEp77yP5pS/5YWaMiAoMinvvI/mlL/lhZozICgzKe+8j+aUv+WFmjQgKDQpCgoqKuaTjeS9nOeiuuiqjSBRNC43KiogIArjgYLjgarjgZ/jgavjga/jgIHopIfmlbDjga7pgbjmip7ogqLjga7kuK3jgYvjgokx44Gk44Gu54q25rOB44KS6YG444KT44Gn44KC44KJ44GG5L2c5qWt44KS6KGM44Gj44Gm44GE44Gf44Gg44GN44G+44GX44Gf44CCIOOBguOBquOBn+OBq+aPkOekuuOBleOCjOOBn+aUv+WFmuOBrumBuOaKnuiCouOBruaVsOOBr+OAgeOBhOOBj+OBpOOBp+OBl+OBn+OBi+OAggoK5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikKCiMjIyMgNeaUv+WFmuadoeS7tu+8iCRrPTUk77yJCioq5bCO5YWl6LOq5ZWPIFE1LjEqKiAgCuS7iuOBi+OCieOAgeaXpeacrOOBruaUv+WFmuOCgeOBkOOCi++8leOBpOOBrumBuOaKnuiCouOCkumghuOBq+aPkOekuuOBl+OBpuOBhOOBjeOBvuOBmeOAgiDjgZ3jgZfjgabjgIHooYborbDpmaLnt4/pgbjmjJnjgYzjgYLjgovjgajjgYrogIPjgYjkuIvjgZXjgYTjgILjgZ3jga7mmYLjgIHjgYLjgarjgZ/jga8144Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu5pS/5YWa44KS6YG45oqe44GV44KM44KL44GL44CB77yR44Gk6YG444KT44Gn44GK562U44GI44GP44Gg44GV44GE44CCIOS9nOalreOBr++8leWbnue5sOOCiui/lOOBleOCjOOBvuOBmeOAggoK5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQoKKirpgbjmip7oqrLpoYwgUTUuMuKAk1E1LjbvvIg15Zue77yJKiogIArku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgos144Gk44Gu6YG45oqe6IKi44KS5o+Q56S644GV44Gb44Gm44GE44Gf44Gg44GN44G+44GZ44CCIOOBguOBquOBn+OBr+OAgeihhuitsOmZouitsOWToee3j+mBuOaMmeOBq+OBiuOBhOOBpuOAgeS7peS4i+OBruOBhOOBmuOCjOOBruaUv+WFmuOCkuOBiumBuOOBs+OBq+OBquOCiuOBvuOBmeOBi+OAggoK5Zue562U6YG45oqe6IKi77ya5pS/5YWaMSAoMSnvvI/mlL/lhZoyICgyKe+8j+aUv+WFmjMgKDMp77yP5pS/5YWaNCAoNCnvvI/mlL/lhZo1ICg1KQoKKirmk43kvZznorroqo0gUTUuNyoqICAK44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/mlL/lhZrjga7pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIIKCuWbnuetlOmBuOaKnuiCou+8mjEgKDEp77yPMiAoMinvvI8zICgzKe+8jzQgKDQp77yPNSAoNSnvvI/jgYrjgbzjgYjjgabjgYTjgarjgYQgKDYpCgojIyMgSi4yLjQg5pS/5rK76LOq5ZWPCioqUTcuMSoqICAK5pS/5rK755qE56uL5aC044KS6KGo44GZ44Gu44Gr44CB44KI44GP44CM5Y+z5rS+44CN44CM5bem5rS+44CN44Go44GE44GG6KiA6JGJ44GM5L2/44KP44KM44G+44GZ44CCMeOBjOWPs+a0vueahOOAgTbjgYzkuK3plpPjgIExMeOBjOW3pua0vueahOOBoOOBqOOBmeOCi+OBqOOAgeOBguOBquOBn+OChOS4u+imgeaUv+WFmuOBr+OBqeOBruOBguOBn+OCiuOBq+S9jee9ruS7mOOBkeOCieOCjOOCi+OBqOOBiuiAg+OBiOOBp+OBl+OCh+OBhuOBi+OAggoK5Zue562U5bC65bqm77yaMe+8iOWPs+a0vueahO+8ie+8jzLvvI8z77yPNO+8jzXvvI8277yI5Lit6ZaT77yJ77yPN++8jzjvvI8577yPMTDvvI8xMe+8iOW3pua0vueahO+8ie+8j+OCj+OBi+OCieOBquOBhO+8j+OBk+OBn+OBiOOBn+OBj+OBquOBhOOAggoK6KmV5L6h5a++6LGh77ya44GC44Gq44Gf6Ieq6Lqr77yIUTI1LjFfMe+8ieOAgeiHqueUseawkeS4u+WFmu+8iFEyNS4xXzLvvInjgIHnq4vmhrLmsJHkuLvlhZrvvIhRMjUuMV8z77yJ44CB5pel5pys57at5paw44Gu5Lya77yIUTI1LjFfNO+8ieOAgeWFrOaYjuWFmu+8iFEyNS4xXzEw77yJ44CB5Zu95rCR5rCR5Li75YWa77yIUTI1LjFfNe+8ieOAgeOCjOOBhOOCj+aWsOmBuOe1hO+8iFEyNS4xXzbvvInjgIHlj4LmlL/lhZrvvIhRMjUuMV8377yJ44CB5YWx55Sj5YWa77yIUTI1LjFfOO+8ieOAgeS4remBk+aUuemdqemAo+WQiO+8iFEyNS4xXznvvInjgIEqKuOAjO+8geOBk+OBrumgheebruOBr+W/heOBmuOAjjPjgI/jgpLpgbjjgpPjgafjgY/jgaDjgZXjgYTvvIHjgI3vvIhRMjUuMV8xMe+8iSoq44CCCgoqKlE3LjIqKiAgCumBuOaMmeOBp+OBqeOBk+OBq+aKleelqOOBmeOCi+OBi+OBr+WIpeOBq+OBl+OBpuOAgeWbveOBruaUv+ayu+OBp+OAgeOBguOBquOBn+OBr+OBqeOBruaUv+WFmuOBguOCi+OBhOOBr+aUv+ayu+Wbo+S9k+OCkuaUr+aMgeOBl+OBpuOBhOOBvuOBmeOBi+OAggoKLSDoh6rnlLHmsJHkuLvlhZogKDEpCi0g5Lit6YGT5pS56Z2p6YCj5ZCIICgyKQotIOeri+aGsuawkeS4u+WFmiAoMTgpCi0g5YWs5piO5YWaICgxOSkKLSDml6XmnKzntq3mlrDjga7kvJogKDMpCi0g5Zu95rCR5rCR5Li75YWaICg0KQotIOOCjOOBhOOCj+aWsOmBuOe1hCAoNSkKLSDlhbHnlKPlhZogKDYpCi0g5Y+C5pS/5YWaICg3KQotIOaXpeacrOS/neWuiOWFmiAoOCkKLSDnpL7msJHlhZogKDkpCi0g44OB44O844Og44G/44KJ44GEICgxMCkKLSDjgZ3jga7ku5bjga7mlL/lhZrjg7vmlL/msrvlm6PkvZPvvIjlhbfkvZPnmoTjgavvvIkgKDEyKSBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwotIOOBneOBruOCiOOBhuOBquaUv+WFmuOBr+OBquOBhCAoMTMpCi0g44KP44GL44KJ44Gq44GEICgxNCkKLSDjgZPjgZ/jgYjjgZ/jgY/jgarjgYQgKDE1KQoKKipRNy4zKiogIArjgYLjgarjgZ/jgYzmma7mrrXjgIHmlL/msrvjgavplqLjgZnjgovmg4XloLHjgpLopovjgZ/jgorjgIHogZ7jgYTjgZ/jgorjgZnjgovjgZ/jgoHjgavkvb/jgYblqpLkvZPjga/jgIHjganjgozjgafjgZfjgofjgYbjgYvjgILjgYLjgovjgaDjgZHpgbjjgpPjgafjgY/jgaDjgZXjgYTjgIIKCi0g5paw6IGe77yI5pyd5YiK77yJICgxKQotIOOCueODneODvOODhOaWsOiBniAoMikKLSDpgLHliIroqowgKDMpCi0g5pS/6KaL5pS+6YCBICg0KQotIOODhuODrOODk+OBruODi+ODpeODvOOCuSAoNSkKLSDjg6/jgqTjg4njgrfjg6fjg7zjgoToqI7oq5bnlarntYQgKDYpCi0g44Oe44OL44OV44Kn44K544OI44O76YG45oyZ5YWs5aCxICg3KQotIOOCpOODs+OCv+ODvOODjeODg+ODiOS4iuOBruODi+ODpeODvOOCueiomOS6iyhTTlPlkKvjgoApICg4KQotIOaUv+WFmuOChOWAmeijnOiAheOBruODm+ODvOODoOODmuODvOOCuOOBquOBqShTTlPlkKvjgoApICg5KQotIOOBneOBruS7lu+8iOWFt+S9k+eahOOBq++8iSAoMTApIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCi0g4oqX6KaL6IGe44GN44GX44Gm44GE44Gq44GEICgxMSkKLSDiipfjgo/jgYvjgonjgarjgYQgKDEyKQotIOKKl+OBk+OBn+OBiOOBn+OBj+OBquOBhCAoMTMpCgojIyMgSi4yLjUg6Kq/5p+76Laj5peo44Gu5YaN6Kqs5piO44Go5pyA57WC6YCB5L+h5ZCM5oSPCjxkZXRhaWxzPgo8c3VtbWFyeT48c3Ryb25nPlE4LjEg44OH44OW44Oq44O844OV44Kj44Oz44Kw44O75pyA57WC5oSP5oCd56K66KqN77yI44Kv44Oq44OD44Kv44GX44Gm5YWo5paH44KS6KGo56S677yJPC9zdHJvbmc+PC9zdW1tYXJ5PgoKPHA+44GT44Gh44KJ44GM6Kq/5p+744Gu5pyA5b6M44Gu55S76Z2i44Gn44GC44KL44CM6Kq/5p+76Laj5peo44Gu5YaN6Kqs5piO44CN44Go44CM5Zue562U57WQ5p6c44Gu6YCB5L+h44Gr6Zai44GZ44KL5pyA57WC5oSP5oCd56K66KqN44CN44Gu44Oa44O844K444Gr44Gq44KK44G+44GZ44CC44G+44Ga44Gv44GT44GT44G+44Gn6Kq/5p+744Gr44GU5Y2U5Yqb44GP44Gg44GV44GE44G+44GX44Gf44GT44Go44Gr44CB5b+D44GL44KJ5b6h56S855Sz44GX5LiK44GS44KL5qyh56ys44Gn44GZ44CCIOODu+acrOiqv+afu+OBp+OBr+OAgeaUv+ayu+OAgee1jOa4iOOBq+mWouOBmeOCi+aEj+itmOOBquOBqeOCkuOBiuS8uuOBhOOBleOBl+OBvuOBl+OBn+OAguiqv+afu+OBq+OBlOWNlOWKm+OBhOOBn+OBoOOBjeOBvuOBl+OBn+OBk+OBqOOBq+OAgea3seOBj+aEn+isneeUs+OBl+S4iuOBkuOBvuOBmeOAgiDjg7vmnKzoqr/mn7vjgavplqLjgZfjgabjgZTkuI3mmI7jgarngrnnrYnjgYzjgZTjgZbjgYTjgb7jgZfjgZ/jgonjgIHkuIvoqJjjg6Hjg7zjg6vjgqLjg4njg6zjgrnjgb7jgafjgYrllY/jgYTlkIjjgo/jgZvjgY/jgaDjgZXjgYTjgIIgZS1tYWlsOiBoYW5ha29vaG11cmE2MTAzMUBnbWFpbC5jb20g44CQ5pys6Kq/5p+744O75pys5a6f6aiT44Gr6Zai44GZ44KL44GU6Kqs5piO77ya6KGo44GM44GC44Gj44Gm44CB6KGo44Gr5pS/5YWa5ZCN44KE57WM5riI54q25rOB44GM6KGo56S644GV44KM44KL44KC44Gu44KS44Gq44Gc44GU6Kan44GE44Gf44Gg44GE44Gf44Gu44GL77yf44CRIOODu+acrOiqv+afu+OBp+OBr+OAgeihqOOBjOOBguOBo+OBpuOAgeOBneOBruihqOOBq+aUv+WFmuWQjeOChOe1jOa4iOeKtuazgeOBjOOBn+OBj+OBleOCk+ekuuOBleOCjOOBn+OCguOBruOCkuOBlOimp+OBq+OBquOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgueahuanmOOBq+OBr+OAgSAy44Gk44Gu5pS/5YWa44Gu5Lit44GL44KJMeOBpOOCkumBuOOBtiAz44Gk44Gu5pS/5YWa44Gu5Lit44GL44KJMeOBpOOCkumBuOOBtiA044Gk44Gu5pS/5YWa44Gu5Lit44GL44KJMeOBpOOCkumBuOOBtiA144Gk44Gu5pS/5YWa44Gu5Lit44GL44KJMeOBpOOCkumBuOOBtiDjgajjgYTjgYbkvZzmpa3jga7jgYbjgaHjga4x44Gk44KS44CB57mw44KK6L+U44GX44GmNeWbnuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjg7vooajjga7kuK3jgavjgZ/jgY/jgZXjgpPjga7mg4XloLHjgYzntYTjgb/ovrzjgb7jgozjgabjgYTjgovjgYbjgYjjgavjgIHjgZXjgonjgavos6rllY/jgpLph43jga3jgZ/jgZPjgajjgafjgIHnmobjgZXjgb7jga7kuK3jgavjga/jgIHlm57nrZTjgYzjgo/jgZrjgonjgo/jgZfjgY/jgIHkvZXjgYvjgpLogIPjgYjjgZ/jgorpgbjjgpPjgaDjgorjgZnjgovkvZzmpa3jgpLpnaLlgJLjgaDjgajmhJ/jgZjjgIHlm57nrZTjgpLkuI3lv6vjgavmgJ3jgo/jgozjgZ/mlrnjgYzjgYrjgonjgozjgZ/jgYvjgoLjgZfjgozjgb7jgZvjgpPjgILjgZ3jga7jgojjgYbjgarkuK3jgIHmnIDlvozjgb7jgafjgZTlm57nrZTjgY/jgaDjgZXjgaPjgZ/jgZPjgajjgavjgIHkvZXjgojjgormhJ/orJ3nlLPjgZfkuIrjgZLjgb7jgZnjgIIg44O75pys6Kq/5p+744Gv44CB5pS/5YWa5ZCN44Go57WM5riI54q25rOB44GM56S644GV44KM44Gf5pmC44Gr44CB56eB44Gf44Gh44Gv44Gp44Gh44KJ44Gr44KC44Go44Gl44GE44Gm5pS/5YWa44KS6YG444G844GG44Go44GZ44KL44Gu44GL44KS5piO44KJ44GL44Gr44GZ44KL44Gf44KB44Gu44KC44Gu44Gn44GX44Gf44CCIOODu+OBneOBruOBn+OCgeOBq+eahuanmOOBq+OBr+OAgeaUv+ayu+mbhuWbo+OAgeOCpOODh+OCquODreOCruODvOOAgeWFmua0vuaAp+OBq+mWouOCj+OCi+OBk+OBqOOCkuOBiuetlOOBiOOBhOOBn+OBoOOBhOOBn+OCiuOAgeOBneOCjOOCieOBq+WvvuOBmeOCi+eahuanmOOBruOBiuiAg+OBiOODu+OBlOaEj+WQkeOCkuOBiuS8uuOBhOOBmeOCi+OBk+OBqOOBq+OBquOCiuOBvuOBl+OBn+OAgiDjg7vjgZPjga7jgojjgYbjgarog4zmma/jgpLjgoLjgaToqr/mn7vjgafjga/jgYLjgorjgb7jgZnjgYzjgIHlm57nrZTjgavjgZTljZTlipvjgY/jgaDjgZXjgaPjgZ/nmobmp5jjga7kuK3jgavjga/jgIHkuI3lv6vmhJ/jgpLmirHjgYvjgozjgZ/mlrnjgYzjgYrjgonjgozjgovjgYvjgoLjgZfjgozjgb7jgZvjgpPjgILjgZ3jga7jgojjgYbjgarmlrnjga/jgIHku6XkuIvjga7jgIzmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZvjgZrjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZfjgarjgYTjgI3jg5zjgr/jg7PjgpLmirzjgZfjgabjgIHmnKzoqr/mn7vjgpLntYLkuobjgZfjgabjgY/jgaDjgZXjgYTjgILjgZ3jga7loLTlkIjjgavjgIHmnKzoqr/mn7vjgbjjga7lm57nrZTjgpLliIbmnpDjgavkvb/nlKjjgZXjgZvjgabjgYTjgZ/jgaDjgY/jgZPjgajjga/oh7TjgZfjgb7jgZvjgpPjgILjgZ3jga7loLTlkIjjgafjgYLjgaPjgabjgoLjgIHjg53jgqTjg7Pjg4jjga/ku5jkuI7jgZXjgozjgb7jgZnjga7jgafjgIHjganjgYbjgYvjgZTlronlv4PjgY/jgaDjgZXjgYTjgIIg44O744G+44Gf5pys6Kq/5p+744Gr44Gv44CB56CU56m26ICF44GM54us6Ieq44Gr5Y+O6ZuG44O75L2c5oiQ44GX44Gf44OH44O844K/44GM5ZCr44G+44KM44G+44GZ44CC44Gd44KM44KJ44KS54Sh5pat44Gn6Lui6KiY44CB6Lui5YaZ44CB44K544Kv44Oq44O844Oz44K344On44OD44OI44Gq44Gp44Gr44KI44Gj44Gm44CB44GV44G+44GW44G+44Gq5aqS5L2T44Gr6YWN5biD44GZ44KL44GT44Go44Gv44CB6JGX5L2c5qip44Gr5oq16Kem44GZ44KL5oGQ44KM44GM44GC44KK44G+44GZ44CC6Kq/5p+755S76Z2i44Gu54Sh5pat44Gn44Gu6Lui6KiY44CB6Lui5YaZ44CB44K544Kv44Oq44O844Oz44K344On44OD44OI562J44Gr44KI44KK5YWs6ZaL44O75YWx5pyJ44GZ44KL44Go44GE44Gj44Gf6KGM54K644Gv44GK5o6n44GI44GE44Gf44Gg44GN44G+44GZ44KI44GG44KI44KN44GX44GP44GK6aGY44GE6Ie044GX44G+44GZ44CCPC9wPgoKPC9kZXRhaWxzPgoKKirlm57nrZTpgbjmip7ogqIqKgoKLSDmnKzoqr/mn7vjga7kuLvml6jjgavlkIzmhI/jgZfjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgovjgIIgKDEpCi0g5pys6Kq/5p+744Gu5Li75peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5Zue562U57WQ5p6c44KS6YCB5L+h44GX44Gq44GE44CCICgyKQoKIyMgSi4zIOWun+mokzPvvIgyMDI25bm077yJCiMjIyBKLjMuMSDoqr/mn7vplovlp4vmmYLjga7oqqzmmI7jgajlkIzmhI8KPGRldGFpbHM+CjxzdW1tYXJ5PjxzdHJvbmc+UTEuMSDoqr/mn7voqqzmmI7vvIjjgq/jg6rjg4Pjgq/jgZfjgablhajmlofjgpLooajnpLrvvIk8L3N0cm9uZz48L3N1bW1hcnk+Cgo8cD7jgIzntYzmuIjoqZXkvqHjgajmlL/mqKnpgYvllrbjgpLjgoHjgZDjgovmhI/orZjoqr/mn7vjgI0g44GU5Y2U5Yqb44Gu44GK6aGY44GEIOS6rOmDveWkp+WtpiDlhazlhbHmlL/nrZbpgKPmkLrnoJTnqbbpg6gg5pWZ5o6IIOWkp+adkSDoj6/lrZAg77yI44GK44GK44KA44KJIOOBr+OBquOBk++8iSDil4Yg44GT44Gu44Ki44Oz44Kx44O844OI6Kq/5p+744Gv44CB5paH6YOo56eR5a2m55yB44Gr44KI44KL56CU56m25Yqp5oiQ77yI56CU56m26Kqy6aGM55Wq5Y+377yaMjZLMDQ3NTHjgIzmlL/nrZbmpa3nuL7oqZXkvqHjga7noJTnqbbvvI3mlL/msrvooYzli5Xoq5bjgajooYzli5XlhazlhbHmlL/nrZboq5bjga7mnrbmqYvjgI3vvInjgavln7rjgaXjgY3lrp/mlr3jgZXjgozjgovlrabooZPoqr/mn7vjgafjgZnjgIIg4peGIOWWtuWIqeebrueahOOChOOAgeeJueWumuOBruaUv+ayu+WLouWKm+OCkuaUr+aPtOOBmeOCi+OBn+OCgeOBruOCouODs+OCseODvOODiOiqv+afu+OBp+OBr+OBguOCiuOBvuOBm+OCk+OAguOBvuOBn+OAgeOBguOBquOBn+OBjOOBk+OBruiqv+afu+OBq+WNlOWKm+OBmeOCi+OBk+OBqOOBq+OCiOOBo+OBpuOAgeS4jeWIqeebiuOCkuiiq+OCi+OBk+OBqOOCguOBguOCiuOBvuOBm+OCk+OAgiDil4Yg5pys6Kq/5p+744Gn44Gv44CB44GC44Gq44Gf44Gu5pS/5rK744CB57WM5riI44Gr6Zai44GZ44KL5oSP6K2Y44Gq44Gp44KC44GK5Ly644GE44GZ44KL44GT44Go44Gr44Gq44KK44G+44GZ44Gu44Gn44CB44GU5om/55+l44GK44GN44GE44Gf44Gg44GN44Gf44GP5a2Y44GY44G+44GZ44CC44KC44GX5Zue562U44KS5LiN5b+r44Gr5oSf44GY44KJ44KM44Gf5aC05ZCI44CB44GC44Gq44Gf44Gv44GE44Gk44Gn44KC5Zue562U44KS44KE44KB44KL44GT44Go44GM44Gn44GN44G+44GZ44CCIOKXhiDjgb7jgZ/mnKzoqr/mn7vjgafjga/jgIHjgYLjgarjgZ/jga7miYDlvpfjgavjgaTjgYTjgabjgoLjgYrlsIvjga3jgZfjgb7jgZnjgILjgoLjgZflm57nrZTjgpLkuI3lv6vjgavmhJ/jgZjjgonjgozjgZ/loLTlkIjjgIHjgYLjgarjgZ/jga/jgYTjgaTjgafjgoLlm57nrZTjgpLjgoTjgoHjgovjgZPjgajjgYzjgafjgY3jgb7jgZnjgIIg4peGIOaUv+ayu+OChOihjOaUv+OBq+OBpOOBhOOBpuOBruizquWVj+OBq+OBr+OAgeetlOOBiOOBpeOCieOBhOOCguOBruOCguOBguOCiuOBvuOBmeOAguOCguOBl+WbnuetlOOCkuS4jeW/q+OBq+aEn+OBmOOCieOCjOOBn+WgtOWQiOOAgeOBguOBquOBn+OBr+OBhOOBpOOBp+OCguWbnuetlOOCkuOChOOCgeOCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAgiDil4Yg5b6X44KJ44KM44Gf5Zue562U44Gv44GZ44G544Gm57Wx6KiI55qE44Gr5Yem55CG44GX44CB5Zue562U6ICF44Gu5bGe5oCn44Gq44Gp44GM44KP44GL44KJ44Gq44GE44KI44GG44Gr44GX44G+44GZ44CC5YCL5Lq644Gu5oOF5aCx44GM54m55a6a44GV44KM44KL44GT44Go44Gv44GC44KK44G+44Gb44KT44Gu44Gn44CB5a6J5b+D44GX44Gm44GU5Zue562U44GP44Gg44GV44GE44CCIOKXhiDjgqLjg7PjgrHjg7zjg4joqr/mn7vjga7liIbmnpDntZDmnpzjgavjgaTjgYTjgabjga/jgIHmlrDogZ7jgarjganjgpLpgJrjgZjjgabkuIDoiKzjga7kurrjgavlr77jgZfjgabjgoLnqY3mpbXnmoTjgavnmbrkv6HjgZnjgovkuojlrprjgafjgZnjgILnmobjgZXjgb7jga7jgZTljZTlipvjga7nqIvjgIHjgojjgo3jgZfjgY/jgYrpoZjjgYTnlLPjgZfkuIrjgZLjgb7jgZnjgIIg4peGIOS4jemBqeWIh+OBquWbnuetlOOCkuihjOOBhuOBk+OBqOOBr+OAgeiqv+afu+e1kOaenOOBruizquOCkuS9juS4i+OBleOBm+OBvuOBmeOAguOBmeOBueOBpuOBruizquWVj+OBq+WvvuOBl+OBpuOAgeS4jemBqeWIh+OBquW9ouOBp+WbnuetlOOBl+OBquOBhOOCiOOBhuOAgeOCiOOCjeOBl+OBj+OBiumhmOOBhOeUs+OBl+S4iuOBkuOBvuOBmeOAguS4jemBqeWIh+OBquWbnuetlOOCkuihjOOBo+OBn+WgtOWQiOOBr+OAgeiqv+afu+OCkue1guS6huOBleOBm+OBpumgguOBj+WgtOWQiOOBjOOBlOOBluOBhOOBvuOBmeOAgiDil4Yg5pys44Ki44Oz44Kx44O844OI6Kq/5p+744Gr6Zai44GX44Gm44GU5LiN5piO44Gq54K5562J44GM44GU44GW44GE44G+44GX44Gf44KJ44CB5LiL6KiY44Oh44O844Or44Ki44OJ44Os44K544G+44Gn44GK5ZWP44GE5ZCI44KP44Gb44GP44Gg44GV44GE44CCIGUtbWFpbDogaGFuYWtvb2htdXJhNjEwMzFAZ21haWwuY29tIOS7peS4iuOCkuOBlOeiuuiqjeOBruS4iuOAgeiqv+afu+OCkumWi+Wni+OBmeOCi+WgtOWQiOOBr+OAgSDjgIzmnKzoqr/mn7vjga7otqPml6jjgajlgIvkurrmg4XloLHjga7lj5bjgormibHjgYTjgavlkIzmhI/jgZfjgabjgIHoqr/mn7vjgpLplovlp4vjgZnjgovjgI0g44Oc44K/44Oz44KS44Kv44Oq44OD44Kv44GX44Gm44CB5Y+z5LiL44Gu44CM77ye77ye44CN44G+44Gf44Gv44CM5qyh44G444CN44Oc44K/44Oz44KS5oq844GX44Gm44CB6Kq/5p+744KS6ZaL5aeL44GX44Gm44GP44Gg44GV44GE44CCPC9wPgoKPC9kZXRhaWxzPgoKKirlm57nrZTpgbjmip7ogqIqKgoKLSDmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZfjgabjgIHmnKzoqr/mn7vjgavljZTlipvjgZnjgosgKDEpCi0g5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5pys6Kq/5p+744Gr5Y2U5Yqb44GX44Gq44GEICgyKQoKIyMjIEouMy4yIOODleOCp+OCpOOCueOCt+ODvOODiArlrp/pqJMz44GuUTIuMe+9nlEyLjTjga/lrp/pqJMy44Go5ZCM44GY6LOq5ZWP5paH44O75Zue562U5b2i5byP44Gn44GC44KL44CC5YaN54++5oCn44Gu44Gf44KB44CB6LOq5ZWPSUTjgajlhoXlrrnjgpLlho3mjrLjgZnjgovjgIIKCnwg6LOq5ZWPSUQgfCDos6rllY/mlocgfCDlm57nrZTlvaLlvI/jg7vpgbjmip7ogqIgfAp8LS0tfC0tLXwtLS18CnwgUTIuMSB8IOOBguOBquOBn+OBruaAp+WIpeOCkumBuOOCk+OBp+OBj+OBoOOBleOBhOOAgiB8IOeUt+aApyAoMSnvvI/lpbPmgKcgKDIp77yP44Gd44Gu5LuWICgzKe+8j+OBk+OBn+OBiOOBn+OBj+OBquOBhCAoNCkgfAp8IFEyLjIgfCDjgYLjgarjgZ/jga7lubTpvaLljLrliIbjgajnj77lnKjjga7lubTpvaLjgpLpgbjjgpPjgafjgY/jgaDjgZXjgYTjgIIgfCDjgIzlubTku6PjgI3jgajjgIzlubTpvaLjgI3jga7pgKPli5Xjg4njg63jg4Pjg5fjg4Djgqbjg7PjgILoqr/mn7vnpajjgqjjgq/jgrnjg53jg7zjg4jkuIrjgafjga/pgbjmip7ogqLkuIDopqfjgYznnIHnlaXooajnpLrjgZXjgozjgabjgYTjgovjgIIgfAp8IFEyLjMgfCDjgYLjgarjgZ/jgYznj77lnKjjgYrkvY/jgb7jgYTjga7lnLDln5/jgajpg73pgZPlupznnIzjgpLpgbjjgpPjgafjgY/jgaDjgZXjgYQgfCDjgIzlnLDln5/jgI3jgajjgIzpg73pgZPlupznnIzjgI3jga7pgKPli5Xjg4njg63jg4Pjg5fjg4Djgqbjg7PjgILoqr/mn7vnpajjgqjjgq/jgrnjg53jg7zjg4jkuIrjgafjga/pgbjmip7ogqLkuIDopqfjgYznnIHnlaXooajnpLrjgZXjgozjgabjgYTjgovjgIIgfAp8IFEyLjQgfCDjgYLjgarjgZ/jga7kuJbluK/jga7nqI7lvJXjgY3liY3jga7kuJbluK/lubTlj47jgajmiYvlj5bjgorjga7lubTlj47jga/jgIHjgaDjgYTjgZ/jgYTjgYrjgYTjgY/jgonjgZDjgonjgYTjgafjgZfjgofjgYbjgYvjgIIg56iO5byV44GN5YmN44Gu5Y+O5YWl44Go44Gv44CB5LiA6Iis55qE44Gr44CM6aGN6Z2i44Gu5Y+O5YWl44CN44Go6KiA44KP44KM44KL44KC44Gu44Gn44GZ44CC44Gd44Gu6aGN6Z2i44Gu5Y+O5YWl44GL44KJ44CB56iO6YeR44KE56S+5Lya5L+d6Zm65paZ44KS5byV44GE44Gf5q6L44KK44GM44CM5omL5Y+W44KK44Gu5Y+O5YWl44CN44Go6KiA44KP44KM44KL44KC44Gu44Gn44GZ44CCIOOBguOBquOBn+OBruWPjuWFpeOAgemFjeWBtuiAheOBruWPjuWFpeOCkuOBmeOBueOBpuWQq+OCgeOBn+OCguOBruOCkuOAgeS7peS4i+OBrueJqeW3ruOBl+OCkuOCueODqeOCpOODieOBleOBm+OBquOBjOOCieOAgeOBiuOBiuOBvuOBi+OBq+aMh+WumuOBl+OBpuOBj+OBoOOBleOBhOOAgiDjgYTjgZrjgozjgoLjgYzjgIwzMDAw5LiH5YaG5Lul5LiK44CN44Gu5Lq644Gv44CB44CMMzAwMOOAjeOCkumBuOaKnuOBl+OBpuOBj+OBoOOBleOBhOOAgiB8IOeojuW8leOBjeWJjeS4luW4r+W5tOWPjuODu+aJi+WPluOCiuW5tOWPjuOBrjLpoIXnm67jgIIw772eMzAwMOS4h+WGhuOBruOCueODqeOCpOODgOODvO+8iDMwMDDvvJ0zMDAw5LiH5YaG5Lul5LiK77yJIHwKIyMjIEouMy4zIOOCs+ODs+OCuOODp+OCpOODs+ODiOiqsumhjArlrp/pqJMz44Gn44Gv44CB5pS/5YWa5ZCN44GoNOOBpOOBrue1jOa4iOWxnuaAp+OBi+OCieOBquOCi+ODl+ODreODleOCo+ODvOODq+OCkuaPkOekuuOBl+OBn+OAguWbnuetlOiAheOBrzLjg7sz44O7NOODuzXpgbjmip7ogqLjga7jgYTjgZrjgozjgYsx5p2h5Lu244Gr54Sh5L2c54K644Gr5Ymy44KK5b2T44Gm44KJ44KM44CBNeiqsumhjOOBq+WbnuetlOOBl+OBn+OAggp8IOWxnuaApyB8IOawtOa6liB8CnwtLS18LS0tfAp8IOaUv+WFmuWQjSB8IOiHqueUseawkeS4u+WFmu+8j+eri+aGsuawkeS4u+WFmu+8j+aXpeacrOe2reaWsOOBruS8mu+8j+WFrOaYjuWFmu+8j+WbveawkeawkeS4u+WFmu+8j+OCjOOBhOOCj+aWsOmBuOe1hO+8j+WPguaUv+WFmu+8j+aXpeacrOWFseeUo+WFmu+8j+S4remBk+aUuemdqemAo+WQiCB8CnwgR0RQ5oiQ6ZW3546HIHwgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfAp8IOaXpee1jOW5s+Wdh+agquS+oSB8IOWJjeaciOWQjOacn+avlCDlpInjgo/jgonjgZrvvI/jg5fjg6njgrkxMDAw5YaG77yP44Oe44Kk44OK44K5MTAwMOWGhiB8CnwgQ1BJIHwg5YmN5pyf5q+UIMKxMOODneOCpOODs+ODiO+8j+ODl+ODqeOCuTHjg53jgqTjg7Pjg4jvvI/jg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIHwKfCDlpLHmpa3njocgfCDliY3mnJ/mr5QgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfAoKKirmnaHku7bliKXjga7oqqzmmI7mlofjg7vpgbjmip7oqrLpoYzjg7vmk43kvZznorroqo0qKgoKIyMjIyAy6YG45oqe6IKi5p2h5Lu277yIJGs9MiTvvIkKKirlsI7lhaXos6rllY8gUTYuMSoqICAK5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yS44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBrzLjgaTjga7pgbjmip7ogqLjga7kuK3jgYvjgonjganjga7nirbms4HjgpLpgbjmip7jgZXjgozjgovjgYvjgIHvvJHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgIIg5L2c5qWt44Gv77yV5Zue57mw44KK6L+U44GV44KM44G+44GZ44CCCgrlm57nrZTvvJrjgIzkuIroqJjjga7mlofnq6DjgpLoqq3jgpPjgaDjgIIgKDEp44CNCgoqKumBuOaKnuiqsumhjCBRNi4y4oCTUTYuNu+8iDXlm57vvIkqKiAgCuS7peS4i+OBq+OAgeaXpeacrOOBruaUv+WFmuOCkuOCgeOBkOOCizLjgaTjga7pgbjmip7ogqLjgpLmj5DnpLrjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgIIg6KGo44Gu5LiA55Wq5LiK44Gr5LiK44GM44Gj44Gm44GE44KL5pS/5YWa44GM5pS/5qip5LiO5YWa44Gn44GC44Gj44Gf44KK44CB6YCj56uL5pS/5qip44Go44GX44Gm5LiO5YWa44Gr5Yqg44KP44Gj44Gm44GE44KL44Go44GX44G+44GZ44CC44Gd44GX44Gm6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CCIOaUv+aoqeS4juWFmuOBq+OBguOCi+aUv+WFmuOBqOe1jOa4iOeKtuazgeOBrue1hOOBv+WQiOOCj+OBm+OBruOBhuOBoeOAgeOBguOBquOBn+OBr+OBqeOBrueKtuazgeOBp+OBguOCjOOBsOOAgeaUv+aoqeS4juWFmuOBq+aKleelqOOBl+OBvuOBmeOBi+OAgiDpgbjmip7ogqLjga7poIbjga/jgIHlt6bjgYvjgonnirbms4Ex44CB54q25rOBMuOBqOOBl+OBvuOBmeOAggoK5Zue562U6YG45oqe6IKi77ya54q25rOBMSAoMSnvvI/nirbms4EyICgyKQoKKirmk43kvZznorroqo0gUTYuNyoqICAK44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIIKCuWbnuetlOmBuOaKnuiCou+8mjEgKDEp77yPMiAoMinvvI8zICgzKe+8jzQgKDQp77yPNSAoNSnvvI/jgYrjgbzjgYjjgabjgYTjgarjgYQgKDYpCgojIyMjIDPpgbjmip7ogqLmnaHku7bvvIgkaz0zJO+8iQoqKuWwjuWFpeizquWVjyBRMy4xKiogIArku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJPjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44Gv77yT44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu54q25rOB44KS6YG45oqe44GV44KM44KL44GL44CB77yR44Gk6YG444KT44Gn44GK562U44GI44GP44Gg44GV44GE44CCIOS9nOalreOBr++8leWbnue5sOOCiui/lOOBleOCjOOBvuOBmeOAggoK5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQoKKirpgbjmip7oqrLpoYwgUTMuMuKAk1EzLjbvvIg15Zue77yJKiogIArku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgosz44Gk44Gu6YG45oqe6IKi44KS5o+Q56S644GV44Gb44Gm44GE44Gf44Gg44GN44G+44GZ44CCIOihqOOBruS4gOeVquS4iuOBq+S4iuOBjOOBo+OBpuOBhOOCi+aUv+WFmuOBjOaUv+aoqeS4juWFmuOBp+OBguOBo+OBn+OCiuOAgemAo+eri+aUv+aoqeOBqOOBl+OBpuS4juWFmuOBq+WKoOOCj+OBo+OBpuOBhOOCi+OBqOOBl+OBvuOBmeOAguOBneOBl+OBpuihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAgiDmlL/mqKnkuI7lhZrjgavjgYLjgovmlL/lhZrjgajntYzmuIjnirbms4Hjga7ntYTjgb/lkIjjgo/jgZvjga7jgYbjgaHjgIHjgYLjgarjgZ/jga/jganjga7nirbms4HjgafjgYLjgozjgbDjgIHmlL/mqKnkuI7lhZrjgavmipXnpajjgZfjgb7jgZnjgYvjgIIg6YG45oqe6IKi44Gu6aCG44Gv44CB5bem44GL44KJ54q25rOBMeOAgeeKtuazgTLjgIHnirbms4Ez44Go44GX44G+44GZ44CCCgrlm57nrZTpgbjmip7ogqLvvJrnirbms4ExICgxKe+8j+eKtuazgTIgKDIp77yP54q25rOBMyAoMykKCioq5pON5L2c56K66KqNIFEzLjcqKiAgCuOBguOBquOBn+OBq+OBr+OAgeikh+aVsOOBrumBuOaKnuiCouOBruS4reOBi+OCiTHjgaTjga7nirbms4HjgpLpgbjjgpPjgafjgoLjgonjgYbkvZzmpa3jgpLooYzjgaPjgabjgYTjgZ/jgaDjgY3jgb7jgZfjgZ/jgIIg44GC44Gq44Gf44Gr5o+Q56S644GV44KM44Gf6YG45oqe6IKi44Gu5pWw44Gv44CB44GE44GP44Gk44Gn44GX44Gf44GL44CCCgrlm57nrZTpgbjmip7ogqLvvJoxICgxKe+8jzIgKDIp77yPMyAoMynvvI80ICg0Ke+8jzUgKDUp77yP44GK44G844GI44Gm44GE44Gq44GEICg2KQoKIyMjIyA06YG45oqe6IKi5p2h5Lu277yIJGs9NCTvvIkKKirlsI7lhaXos6rllY8gUTQuMSoqICAK5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yU44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBrzTjgaTjga7pgbjmip7ogqLjga7kuK3jgYvjgonjganjga7nirbms4HjgpLpgbjmip7jgZXjgozjgovjgYvjgIHvvJHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgIIg5L2c5qWt44Gv77yV5Zue57mw44KK6L+U44GV44KM44G+44GZ44CCCgrlm57nrZTvvJrjgIzkuIroqJjjga7mlofnq6DjgpLoqq3jgpPjgaDjgIIgKDEp44CNCgoqKumBuOaKnuiqsumhjCBRNC4y4oCTUTQuNu+8iDXlm57vvIkqKiAgCuS7peS4i+OBq+OAgeaXpeacrOOBruaUv+WFmuOCkuOCgeOBkOOCizTjgaTjga7pgbjmip7ogqLjgpLmj5DnpLrjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgIIg6KGo44Gu5LiA55Wq5LiK44Gr5LiK44GM44Gj44Gm44GE44KL5pS/5YWa44GM5pS/5qip5LiO5YWa44Gn44GC44Gj44Gf44KK44CB6YCj56uL5pS/5qip44Go44GX44Gm5LiO5YWa44Gr5Yqg44KP44Gj44Gm44GE44KL44Go44GX44G+44GZ44CC44Gd44GX44Gm6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CCIOaUv+aoqeS4juWFmuOBq+OBguOCi+aUv+WFmuOBqOe1jOa4iOeKtuazgeOBrue1hOOBv+WQiOOCj+OBm+OBruOBhuOBoeOAgeOBguOBquOBn+OBr+OBqeOBrueKtuazgeOBp+OBguOCjOOBsOOAgeaUv+aoqeS4juWFmuOBq+aKleelqOOBl+OBvuOBmeOBi+OAgiDpgbjmip7ogqLjga7poIbjga/jgIHlt6bjgYvjgonnirbms4Ex44CB54q25rOBMuOAgeeKtuazgTPjgIHnirbms4E044Go44GX44G+44GZ44CCCgrlm57nrZTpgbjmip7ogqLvvJrnirbms4ExICgxKe+8j+eKtuazgTIgKDIp77yP54q25rOBMyAoMynvvI/nirbms4E0ICg0KQoKKirmk43kvZznorroqo0gUTQuNyoqICAK44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIIKCuWbnuetlOmBuOaKnuiCou+8mjEgKDEp77yPMiAoMinvvI8zICgzKe+8jzQgKDQp77yPNSAoNSnvvI/jgYrjgbzjgYjjgabjgYTjgarjgYQgKDYpCgojIyMjIDXpgbjmip7ogqLmnaHku7bvvIgkaz01JO+8iQoqKuWwjuWFpeizquWVjyBRNS4xKiogIArku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJXjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44GvNeOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBrueKtuazgeOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIIKCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0KCioq6YG45oqe6Kqy6aGMIFE1LjLigJNRNS4277yINeWbnu+8iSoqICAK5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLNeOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDooajjga7kuIDnlarkuIrjgavkuIrjgYzjgaPjgabjgYTjgovmlL/lhZrjgYzmlL/mqKnkuI7lhZrjgafjgYLjgaPjgZ/jgorjgIHpgKPnq4vmlL/mqKnjgajjgZfjgabkuI7lhZrjgavliqDjgo/jgaPjgabjgYTjgovjgajjgZfjgb7jgZnjgILjgZ3jgZfjgabooYborbDpmaLnt4/pgbjmjJnjgYzjgYLjgovjgajjgYrogIPjgYjkuIvjgZXjgYTjgIIg5pS/5qip5LiO5YWa44Gr44GC44KL5pS/5YWa44Go57WM5riI54q25rOB44Gu57WE44G/5ZCI44KP44Gb44Gu44GG44Gh44CB44GC44Gq44Gf44Gv44Gp44Gu54q25rOB44Gn44GC44KM44Gw44CB5pS/5qip5LiO5YWa44Gr5oqV56Wo44GX44G+44GZ44GL44CCIOmBuOaKnuiCouOBrumghuOBr+OAgeW3puOBi+OCieeKtuazgTHjgIHnirbms4Ey44CB54q25rOBM+OAgeeKtuazgTTjgIHnirbms4E144Go44GX44G+44GZ44CCCgrlm57nrZTpgbjmip7ogqLvvJrnirbms4ExICgxKe+8j+eKtuazgTIgKDIp77yP54q25rOBMyAoMynvvI/nirbms4E0ICg0Ke+8j+eKtuazgTUgKDUpCgoqKuaTjeS9nOeiuuiqjSBRNS43KiogIArjgYLjgarjgZ/jgavjga/jgIHopIfmlbDjga7pgbjmip7ogqLjga7kuK3jgYvjgokx44Gk44Gu54q25rOB44KS6YG444KT44Gn44KC44KJ44GG5L2c5qWt44KS6KGM44Gj44Gm44GE44Gf44Gg44GN44G+44GX44Gf44CCIOOBguOBquOBn+OBq+aPkOekuuOBleOCjOOBn+mBuOaKnuiCouOBruaVsOOBr+OAgeOBhOOBj+OBpOOBp+OBl+OBn+OBi+OAggoK5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikKCiMjIyBKLjMuNCDmlL/msrvos6rllY8KKipRNy4xKiogIArmlL/msrvnmoTnq4vloLTjgpLooajjgZnjga7jgavjgIHjgojjgY/jgIzlj7PmtL7jgI3jgIzlt6bmtL7jgI3jgajjgYTjgYboqIDokYnjgYzkvb/jgo/jgozjgb7jgZnjgIIx44GM5Y+z5rS+55qE44CBNuOBjOS4remWk+OAgTEx44GM5bem5rS+55qE44Gg44Go44GZ44KL44Go44CB44GC44Gq44Gf44KE5Li76KaB5pS/5YWa44Gv44Gp44Gu44GC44Gf44KK44Gr5L2N572u5LuY44GR44KJ44KM44KL44Go44GK6ICD44GI44Gn44GX44KH44GG44GL44CCCgrlm57nrZTlsLrluqbvvJox77yI5Y+z5rS+55qE77yJ77yPMu+8jzPvvI8077yPNe+8jzbvvIjkuK3plpPvvInvvI8377yPOO+8jznvvI8xMO+8jzEx77yI5bem5rS+55qE77yJ77yP44KP44GL44KJ44Gq44GE77yP44GT44Gf44GI44Gf44GP44Gq44GE44CCCgroqZXkvqHlr77osaHvvJrjgYLjgarjgZ/oh6rouqvvvIhRMjUuMV8x77yJ44CB6Ieq55Sx5rCR5Li75YWa77yIUTI1LjFfMu+8ieOAgeeri+aGsuawkeS4u+WFmu+8iFEyNS4xXzPvvInjgIHml6XmnKzntq3mlrDjga7kvJrvvIhRMjUuMV8077yJ44CB5YWs5piO5YWa77yIUTI1LjFfMTDvvInjgIHlm73msJHmsJHkuLvlhZrvvIhRMjUuMV8177yJ44CB44KM44GE44KP5paw6YG457WE77yIUTI1LjFfNu+8ieOAgeWPguaUv+WFmu+8iFEyNS4xXzfvvInjgIHlhbHnlKPlhZrvvIhRMjUuMV8477yJ44CB5Lit6YGT5pS56Z2p6YCj5ZCI77yIUTI1LjFfOe+8ieOAgSoq44CM77yB44GT44Gu6aCF55uu44Gv5b+F44Ga44COM+OAj+OCkumBuOOCk+OBp+OBj+OBoOOBleOBhO+8geOAje+8iFEyNS4xXzEx77yJKirjgIIKCioqUTcuMioqICAK6YG45oyZ44Gn44Gp44GT44Gr5oqV56Wo44GZ44KL44GL44Gv5Yil44Gr44GX44Gm44CB5Zu944Gu5pS/5rK744Gn44CB44GC44Gq44Gf44Gv44Gp44Gu5pS/5YWa44GC44KL44GE44Gv5pS/5rK75Zuj5L2T44KS5pSv5oyB44GX44Gm44GE44G+44GZ44GL44CCCgotIOiHqueUseawkeS4u+WFmiAoMSkKLSDkuK3pgZPmlLnpnanpgKPlkIggKDIpCi0g56uL5oay5rCR5Li75YWaICgxOCkKLSDlhazmmI7lhZogKDE5KQotIOaXpeacrOe2reaWsOOBruS8miAoMykKLSDlm73msJHmsJHkuLvlhZogKDQpCi0g44KM44GE44KP5paw6YG457WEICg1KQotIOWFseeUo+WFmiAoNikKLSDlj4LmlL/lhZogKDcpCi0g5pel5pys5L+d5a6I5YWaICg4KQotIOekvuawkeWFmiAoOSkKLSDjg4Hjg7zjg6Djgb/jgonjgYQgKDEwKQotIOOBneOBruS7luOBruaUv+WFmuODu+aUv+ayu+Wbo+S9k++8iOWFt+S9k+eahOOBq++8iSAoMTIpIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCi0g44Gd44Gu44KI44GG44Gq5pS/5YWa44Gv44Gq44GEICgxMykKLSDjgo/jgYvjgonjgarjgYQgKDE0KQotIOOBk+OBn+OBiOOBn+OBj+OBquOBhCAoMTUpCgoqKlE3LjMqKiAgCuOBguOBquOBn+OBjOaZruauteOAgeaUv+ayu+OBq+mWouOBmeOCi+aDheWgseOCkuimi+OBn+OCiuOAgeiBnuOBhOOBn+OCiuOBmeOCi+OBn+OCgeOBq+S9v+OBhuWqkuS9k+OBr+OAgeOBqeOCjOOBp+OBl+OCh+OBhuOBi+OAguOBguOCi+OBoOOBkemBuOOCk+OBp+OBj+OBoOOBleOBhOOAggoKLSDmlrDogZ7vvIjmnJ3liIrvvIkgKDEpCi0g44K544Od44O844OE5paw6IGeICgyKQotIOmAseWIiuiqjCAoMykKLSDmlL/opovmlL7pgIEgKDQpCi0g44OG44Os44OT44Gu44OL44Ol44O844K5ICg1KQotIOODr+OCpOODieOCt+ODp+ODvOOChOiojuirlueVque1hCAoNikKLSDjg57jg4vjg5Xjgqfjgrnjg4jjg7vpgbjmjJnlhazloLEgKDcpCi0g44Kk44Oz44K/44O844ON44OD44OI5LiK44Gu44OL44Ol44O844K56KiY5LqLKFNOU+WQq+OCgCkgKDgpCi0g5pS/5YWa44KE5YCZ6KOc6ICF44Gu44Ob44O844Og44Oa44O844K444Gq44GpKFNOU+WQq+OCgCkgKDkpCi0g44Gd44Gu5LuW77yI5YW35L2T55qE44Gr77yJICgxMCkgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KLSDiipfopovogZ7jgY3jgZfjgabjgYTjgarjgYQgKDExKQotIOKKl+OCj+OBi+OCieOBquOBhCAoMTIpCi0g4oqX44GT44Gf44GI44Gf44GP44Gq44GEICgxMykKCiMjIyBKLjMuNSDoqr/mn7votqPml6jjga7lho3oqqzmmI7jgajmnIDntYLpgIHkv6HlkIzmhI8KPGRldGFpbHM+CjxzdW1tYXJ5PjxzdHJvbmc+UTguMSDjg4fjg5bjg6rjg7zjg5XjgqPjg7PjgrDjg7vmnIDntYLmhI/mgJ3norroqo3vvIjjgq/jg6rjg4Pjgq/jgZfjgablhajmlofjgpLooajnpLrvvIk8L3N0cm9uZz48L3N1bW1hcnk+Cgo8cD7jgZPjgaHjgonjgYzoqr/mn7vjga7mnIDlvozjga7nlLvpnaLjgafjgYLjgovjgIzoqr/mn7votqPml6jjga7lho3oqqzmmI7jgI3jgajjgIzlm57nrZTntZDmnpzjga7pgIHkv6HjgavplqLjgZnjgovmnIDntYLmhI/mgJ3norroqo3jgI3jga7jg5rjg7zjgrjjgavjgarjgorjgb7jgZnjgILjgb7jgZrjga/jgZPjgZPjgb7jgafoqr/mn7vjgavjgZTljZTlipvjgY/jgaDjgZXjgYTjgb7jgZfjgZ/jgZPjgajjgavjgIHlv4PjgYvjgonlvqHnpLznlLPjgZfkuIrjgZLjgovmrKHnrKzjgafjgZnjgIIg44O75pys6Kq/5p+744Gn44Gv44CB5pS/5rK744CB57WM5riI44Gr6Zai44GZ44KL5oSP6K2Y44Gq44Gp44KS44GK5Ly644GE44GV44GX44G+44GX44Gf44CC6Kq/5p+744Gr44GU5Y2U5Yqb44GE44Gf44Gg44GN44G+44GX44Gf44GT44Go44Gr44CB5rex44GP5oSf6Kyd55Sz44GX5LiK44GS44G+44GZ44CCIOODu+acrOiqv+afu+OBq+mWouOBl+OBpuOBlOS4jeaYjuOBqueCueetieOBjOOBlOOBluOBhOOBvuOBl+OBn+OCieOAgeS4i+iomOODoeODvOODq+OCouODieODrOOCueOBvuOBp+OBiuWVj+OBhOWQiOOCj+OBm+OBj+OBoOOBleOBhOOAgiBlLW1haWw6IGhhbmFrb29obXVyYTYxMDMxQGdtYWlsLmNvbSDjgJDmnKzoqr/mn7vjg7vmnKzlrp/pqJPjgavplqLjgZnjgovjgZToqqzmmI7vvJrooajjgYzjgYLjgaPjgabjgIHooajjgavmlL/lhZrlkI3jgoTntYzmuIjnirbms4HjgYzooajnpLrjgZXjgozjgovjgoLjga7jgpLjgarjgZzjgZTopqfjgYTjgZ/jgaDjgYTjgZ/jga7jgYvvvJ/jgJEg44O75pys6Kq/5p+744Gn44Gv44CB6KGo44GM44GC44Gj44Gm44CB44Gd44Gu6KGo44Gr5pS/5YWa5ZCN44KE57WM5riI54q25rOB44GM44Gf44GP44GV44KT56S644GV44KM44Gf44KC44Gu44KS44GU6Kan44Gr44Gq44Gj44Gm44GE44Gf44Gg44GN44G+44GX44Gf44CC55qG5qeY44Gr44Gv44CBIDLjgaTjga7nirbms4Hjga7kuK3jgYvjgokx44Gk44KS6YG444G2IDPjgaTjga7nirbms4Hjga7kuK3jgYvjgokx44Gk44KS6YG444G2IDTjgaTjga7nirbms4Hjga7kuK3jgYvjgokx44Gk44KS6YG444G2IDXjgaTjga7nirbms4Hjga7kuK3jgYvjgokx44Gk44KS6YG444G2IOOBqOOBhOOBhuS9nOalreOBruOBhuOBoeOBrjHjgaTjgpLjgIHnubDjgorov5TjgZfjgaY15Zue6KGM44Gj44Gm44GE44Gf44Gg44GN44G+44GX44Gf44CCIOODu+OBvuOBn+WFt+S9k+eahOOBquaUv+WFmuWQjeOBqOOBqOOCguOBq+aPkOekuuOBleOCjOOBn+e1jOa4iOeKtuazgeOBr+OAgeePvuWun+OBqOOBr+eVsOOBquOCi+S7ruaDs+OBruaDheWgseOBq+OBquOCiuOBvuOBmeOAguOBvuOBn+OAgeWFt+S9k+eahOOBquaUv+WFmuOBjOOAjOS4juWFmu+8j+mAo+eri+S4juWFmuOBp+OBguOCi+OAjeOBqOOBhOOBhuOBk+OBqOOCguaDs+i1t+OBl+OBpuOCguOCieOBhOOBvuOBl+OBn+OAguOBlOimp+OBq+OBquOBo+OBpuOBhOOBn+OBoOOBhOOBn+aUv+WFmuOBruS4reOBq+OBr+OAgeWun+mam+OBq+OBr+S4juWFmu+8j+mAo+eri+S4juWFmuOBp+OBr+OBquOBhOaUv+WFmuOBjOikh+aVsOWQq+OBvuOCjOOBpuOBhOOBvuOBl+OBn+OAguOBk+OBrueCueOCguOAgeeglOeptuOBruioreioiOS4iuW/heimgeOBqOOBquOCi+OCguOBruOBp+OBr+OBguOCiuOBvuOBl+OBn+OBjOOAgeePvuWun+ekvuS8muOBq+OBiuOBkeOCi+S6i+Wun+OBqOOBr+eVsOOBquOCi+OCguOBruOBp+OBmeOAguOBk+OBrueCueOBq+eVmeaEj+OBl+OBpuOBhOOBn+OBoOOBjeOAgeOBlOe0jeW+l+OBhOOBn+OBoOOBkeOBn+WgtOWQiOOBq+OBr+OAgeOAjOWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCi+OAjeODnOOCv+ODs+OCkuaKvOOBl+OBpuOBj+OBoOOBleOBhOOAgiDjg7vooajjga7kuK3jgavjgZ/jgY/jgZXjgpPjga7mg4XloLHjgYzntYTjgb/ovrzjgb7jgozjgabjgYTjgovjgYbjgYjjgavjgIHjgZXjgonjgavos6rllY/jgpLph43jga3jgZ/jgZPjgajjgafjgIHnmobjgZXjgb7jga7kuK3jgavjga/jgIHlm57nrZTjgYzjgo/jgZrjgonjgo/jgZfjgY/jgIHkvZXjgYvjgpLogIPjgYjjgZ/jgorpgbjjgpPjgaDjgorjgZnjgovkvZzmpa3jgpLpnaLlgJLjgaDjgajmhJ/jgZjjgIHlm57nrZTjgpLkuI3lv6vjgavmgJ3jgo/jgozjgZ/mlrnjgYzjgYrjgonjgozjgZ/jgYvjgoLjgZfjgozjgb7jgZvjgpPjgILjgZ3jga7jgojjgYbjgarkuK3jgIHmnIDlvozjgb7jgafjgZTlm57nrZTjgY/jgaDjgZXjgaPjgZ/jgZPjgajjgavjgIHkvZXjgojjgormhJ/orJ3nlLPjgZfkuIrjgZLjgb7jgZnjgIIg44O75pys6Kq/5p+744Gv44CB5pS/5YWa5ZCN44Go57WM5riI54q25rOB44GM56S644GV44KM44Gf5pmC44Gr44CB56eB44Gf44Gh44Gv44Gp44Gh44KJ44Gr44KC44Go44Gl44GE44Gm5pS/5YWa44KS6YG444G844GG44Go44GZ44KL44Gu44GL44KS5piO44KJ44GL44Gr44GZ44KL44Gf44KB44Gu44KC44Gu44Gn44GX44Gf44CCIOODu+OBneOBruOBn+OCgeOBq+eahuanmOOBq+OBr+OAgeaUv+ayu+mbhuWbo+OAgeOCpOODh+OCquODreOCruODvOOAgeWFmua0vuaAp+OBq+mWouOCj+OCi+OBk+OBqOOCkuOBiuetlOOBiOOBhOOBn+OBoOOBhOOBn+OCiuOAgeOBneOCjOOCieOBq+WvvuOBmeOCi+eahuanmOOBruOBiuiAg+OBiOODu+OBlOaEj+WQkeOCkuOBiuS8uuOBhOOBmeOCi+OBk+OBqOOBq+OBquOCiuOBvuOBl+OBn+OAgiDjgZPjga7jgojjgYbjgarog4zmma/jgpLjgoLjgaToqr/mn7vjgafjga/jgYLjgorjgb7jgZnjgYzjgIHlm57nrZTjgavjgZTljZTlipvjgY/jgaDjgZXjgaPjgZ/nmobmp5jjga7kuK3jgavjga/jgIHkuI3lv6vmhJ/jgpLmirHjgYvjgozjgZ/mlrnjgYzjgYrjgonjgozjgovjgYvjgoLjgZfjgozjgb7jgZvjgpPjgILjgZ3jga7jgojjgYbjgarmlrnjga/jgIHku6XkuIvjga7jgIzmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZvjgZrjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZfjgarjgYTjgI3jg5zjgr/jg7PjgpLmirzjgZfjgabjgIHmnKzoqr/mn7vjgpLntYLkuobjgZfjgabjgY/jgaDjgZXjgYTjgILjgZ3jga7loLTlkIjjgavjgIHmnKzoqr/mn7vjgbjjga7lm57nrZTjgpLliIbmnpDjgavkvb/nlKjjgZXjgZvjgabjgYTjgZ/jgaDjgY/jgZPjgajjga/oh7TjgZfjgb7jgZvjgpPjgILjgZ3jga7loLTlkIjjgafjgYLjgaPjgabjgoLjgIHjg53jgqTjg7Pjg4jjga/ku5jkuI7jgZXjgozjgb7jgZnjga7jgafjgIHjganjgYbjgYvjgZTlronlv4PjgY/jgaDjgZXjgYTjgIIg44G+44Gf5pys6Kq/5p+744Gr44Gv44CB56CU56m26ICF44GM54us6Ieq44Gr5Y+O6ZuG44O75L2c5oiQ44GX44Gf44OH44O844K/44GM5ZCr44G+44KM44G+44GZ44CC44Gd44KM44KJ44KS54Sh5pat44Gn6Lui6KiY44CB6Lui5YaZ44CB44K544Kv44Oq44O844Oz44K344On44OD44OI44Gq44Gp44Gr44KI44Gj44Gm44CB44GV44G+44GW44G+44Gq5aqS5L2T44Gr6YWN5biD44GZ44KL44GT44Go44Gv44CB6JGX5L2c5qip44Gr5oq16Kem44GZ44KL5oGQ44KM44GM44GC44KK44G+44GZ44CC6Kq/5p+755S76Z2i44Gu54Sh5pat44Gn44Gu6Lui6KiY44CB6Lui5YaZ44CB44K544Kv44Oq44O844Oz44K344On44OD44OI562J44Gr44KI44KK5YWs6ZaL44O75YWx5pyJ44GZ44KL44Go44GE44Gj44Gf6KGM54K644Gv44GK5o6n44GI44GE44Gf44Gg44GN44G+44GZ44KI44GG44KI44KN44GX44GP44GK6aGY44GE6Ie044GX44G+44GZ44CCPC9wPgoKPC9kZXRhaWxzPgoKKirlm57nrZTpgbjmip7ogqIqKgoKLSDmnKzoqr/mn7vjga7kuLvml6jjgavlkIzmhI/jgZfjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgovjgIIgKDEpCi0g5pys6Kq/5p+744Gu5Li75peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5Zue562U57WQ5p6c44KS6YCB5L+h44GX44Gq44GE44CCICgyKQoKIyMgSi40IOiqv+afu+elqOOBqOWGjeePvuOCs+ODvOODieOBruWvvuW/nApDLjTjga7mqJnmnKzmuJvlsJHjg7vjgrnjgq/jg6rjg7zjg4vjg7PjgrDooajjgafjga/jgIHkuIroqJjjga7os6rllY/mlofjga7jgYbjgaHliIbmnpDmqJnmnKzjga7liKTlrprjgavnm7TmjqXnlKjjgYTjgovpoIXnm67jgpLnn63jgY/opoHntITjgZfjgabkvbXoqJjjgZfjgabjgYTjgovjgILlrp/pqJMx44Gn44Gv5Yid5Zue5ZCM5oSP44CBNeOBpOOBrumBuOaKnuiqsumhjOOAgeacgOe1gumAgeS/oeWQjOaEj+OCkuS4u+OBquWIpOWumumgheebruOBqOOBmeOCi+OAguWun+mokzLjg7sz44Gn44Gv44GT44KM44KJ44Gr5Yqg44GI44CB5ZCE6YG45oqe6IKi5pWw5p2h5Lu244Gu5pON5L2c56K66KqN77yIUTMuN++8j1E0LjfvvI9RNS4377yPUTYuN++8ieOBqOOAgeOCpOODh+OCquODreOCruODvOihjOWIl+OBruaMh+ekuumgheebrlEyNS4xXzEx44KS55So44GE44KL44CC44GX44Gf44GM44Gj44Gm44CBQy4044Gu44CM6LOq5ZWP5paH77yI6Kq/5p+756Wo44O76KaB57SE77yJ44CN5YiX44Go44CB5pys56+A44Gu5a6M5YWo44Gq6LOq5ZWP5paH44KS5a++5b+c44GV44Gb44Gm56K66KqN44Gn44GN44KL44CCCgo=