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、ページ区切り等の技術的メタデータも省略する。

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\)

導入質問
今から、日本の政党めぐる2つの選択肢を順に提示していきます。 そして、衆議院総選挙があるとお考え下さい。その時、あなたは3つの選択肢の中からどの政党を選択されるか、1つ選んでお答えください。 作業は5回繰り返されます。

回答:「上記の文章を読んだ。 (1)」

選択課題(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)」

選択課題(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)」

選択課題(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)」

選択課題(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の「質問文(調査票・要約)」列と、本節の完全な質問文を対応させて確認できる。

LS0tDQp0aXRsZTogIuOCquODs+ODqeOCpOODs+S4iuOBp+OBruijnOmBuuOBqOWGjeePvuOCs+ODvOODiSINCnN1YnRpdGxlOiAi5aSa5YWa5Yi244Gv57WM5riI5oqV56Wo44KS5byx44KB44KL44Gu44GL77yf77ya5pS/5YWa44Gu5omL44GM44GL44KK44Go57WM5riI44Gu5omL44GM44GL44KK44KS44KB44GQ44KL44Kz44Oz44K444On44Kk44Oz44OI5a6f6aiTIg0KYXV0aG9yOiAiSGFuYWtvIE9obXVyYSINCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVZLSVtLSVkJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICBoaWdobGlnaHQ6IGthdGUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDINCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQ0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQpwYXJhbXM6DQogIHN0dWR5MV9kYXRhOiAicGFydHludW0uY3N2Ig0KICBzdHVkeTJfZGF0YTogImNvbmpvaW50X3N0dWR5Mi5jc3YiDQogIHN0dWR5M19kYXRhOiAiY29uam9pbnRfUzMuY3N2Ig0KICBvdXRwdXRfcm9vdDogImNvbmpvaW50X3JlcGxpY2F0aW9uX3Jlc3VsdHMiDQogIHJ1bl9hbmFseXNpczogdHJ1ZQ0KICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0I6IDIwMDANCiAgc3VwcG9ydF9ib290c3RyYXBfQjogNTAwDQogIHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXA6IGZhbHNlDQogIHJlcnVuX3N1cHBvcnRfYm9vdHN0cmFwOiBmYWxzZQ0KICBtaW5fc3VwcG9ydF90b3RhbF9uOiAxNTANCiAgbWluX3N1cHBvcnRfY2VsbF9uOiA0MA0KLS0tDQoNCjxzdHlsZT4NCmJvZHkgew0KICBmb250LWZhbWlseTogIkhlbHZldGljYSBOZXVlIiwgQXJpYWwsICJZdSBHb3RoaWMiLCAiSGlyYWdpbm8gS2FrdSBHb3RoaWMgUHJvTiIsIHNhbnMtc2VyaWY7DQogIGZvbnQtc2l6ZTogMTZweDsNCiAgbGluZS1oZWlnaHQ6IDEuNzU7DQp9DQoubWFpbi1jb250YWluZXIgeyBtYXgtd2lkdGg6IDExMjBweDsgfQ0KaDEsIGgyLCBoMywgaDQgeyBmb250LXdlaWdodDogNzAwOyB9DQpoMiB7DQogIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZDhkZWU0Ow0KICBwYWRkaW5nLWJvdHRvbTogMC4yNWVtOw0KfQ0KcHJlLCBjb2RlIHsgZm9udC1zaXplOiAwLjkwZW07IH0NCnRhYmxlIHsgZm9udC1zaXplOiAwLjkwZW07IH0NCi50YWJsZS1zY3JvbGwgeyBvdmVyZmxvdy14OiBhdXRvOyBtYXJnaW4tYm90dG9tOiAxLjVlbTsgfQ0KaW1nIHsgbWF4LXdpZHRoOiAxMDAlOyBoZWlnaHQ6IGF1dG87IGRpc3BsYXk6IGlubGluZS1ibG9jazsgfQ0KLmNvZGUtY29udHJvbHMgeyBtYXJnaW46IDAuNWVtIDAgMS4yZW0gMDsgfQ0KLmNvZGUtY29udHJvbHMgYnV0dG9uIHsgbWFyZ2luLXJpZ2h0OiAwLjVlbTsgcGFkZGluZzogMC4zNWVtIDAuOGVtOyB9DQo8L3N0eWxlPg0KDQo8c2NyaXB0Pg0KZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsIGZ1bmN0aW9uKCkgew0KICBjb25zdCBzaG93QnV0dG9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNob3ctYWxsLWNvZGUiKTsNCiAgY29uc3QgaGlkZUJ1dHRvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJoaWRlLWFsbC1jb2RlIik7DQogIGlmIChzaG93QnV0dG9uKSB7DQogICAgc2hvd0J1dHRvbi5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsIGZ1bmN0aW9uKCkgew0KICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiZGl2LnNvdXJjZUNvZGUiKS5mb3JFYWNoKGZ1bmN0aW9uKGVsKSB7DQogICAgICAgIGVsLnN0eWxlLmRpc3BsYXkgPSAiYmxvY2siOw0KICAgICAgfSk7DQogICAgfSk7DQogIH0NCiAgaWYgKGhpZGVCdXR0b24pIHsNCiAgICBoaWRlQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIiwgZnVuY3Rpb24oKSB7DQogICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCJkaXYuc291cmNlQ29kZSIpLmZvckVhY2goZnVuY3Rpb24oZWwpIHsNCiAgICAgICAgZWwuc3R5bGUuZGlzcGxheSA9ICJub25lIjsNCiAgICAgIH0pOw0KICAgIH0pOw0KICB9DQp9KTsNCjwvc2NyaXB0Pg0KDQo8ZGl2IGNsYXNzPSJjb2RlLWNvbnRyb2xzIj4NCjxidXR0b24gaWQ9InNob3ctYWxsLWNvZGUiIHR5cGU9ImJ1dHRvbiI+U2hvdyBBbGwgQ29kZTwvYnV0dG9uPg0KPGJ1dHRvbiBpZD0iaGlkZS1hbGwtY29kZSIgdHlwZT0iYnV0dG9uIj5IaWRlIEFsbCBDb2RlPC9idXR0b24+DQo8L2Rpdj4NCg0KDQojIFJFQURNRe+8muWGjeePvuaWueazleOBqOODleOCoeOCpOODq+ani+aIkA0KDQrjgZPjga7jgqrjg7Pjg6njgqTjg7Poo5zpgbrjgajlho3nj77jgrPjg7zjg4njga/jgIHoq5bmlofjgIzlpJrlhZrliLbjga/ntYzmuIjmipXnpajjgpLlvLHjgoHjgovjga7jgYvvvJ/vvJrmlL/lhZrjga7miYvjgYzjgYvjgorjgajntYzmuIjjga7miYvjgYzjgYvjgorjgpLjgoHjgZDjgovjgrPjg7Pjgrjjg6fjgqTjg7Pjg4jlrp/pqJPjgI3jgafloLHlkYrjgZnjgosz44Gk44Gu5a6f6aiT44Gu5YiG5p6Q44Gr44Gk44GE44Gm44CB5pys5paH5Zuz44CB6KOc6YG65Zuz6KGo44CB6aCR5YGl5oCn5YiG5p6Q44CB54Sh5L2c54K65YyW44O744OQ44Op44Oz44K56Ki65pat44CB44GK44KI44Gz5pSv5oyB5pS/5YWa5Yil5YiG5p6Q57WQ5p6c44KS44G+44Go44KB44CB44GV44KJ44Gr44Gd44KM44KJ44KS5YaN54++44GZ44KL44Gf44KB44Gu44Kz44O844OJ44KS44G+44Go44KB44Gf44KC44Gu44Gn44GC44KL44CC5Lul5LiL44Gu5omL6aCG44Gn44CB5YWl5Yqb44OH44O844K/44Gu6Kqt6L6844G/44GL44KJ5pyA57WC55qE44Gq5Zuz6KGo44O76Ki65pat57WQ5p6c44Gu5pW055CG44G+44Gn44KS5LiA5ous44GX44Gm5a6f6KGM44Gn44GN44KL44CCDQoNCiMjIDEuIOWGjeePvuOBq+W/heimgeOBquODleOCoeOCpOODq+etiQ0KDQrmrKHjga4044OV44Kh44Kk44Or44KS5ZCM44GY5L2c5qWt44OH44Kj44Os44Kv44OI44Oq44Gr572u44GE44Gm44KC44KJ44GG44CC44OH44O844K/44OV44Kh44Kk44Or5ZCN44KE5L+d5a2Y5aC05omA44KS5aSJ5pu044GZ44KL5aC05ZCI44Gv44CB44GT44GuUm1k5YaS6aCt44GuIGBwYXJhbXNgIOOCkuWkieabtOOBl+OBpuOCguOCieOBiOOBsOOCiOOBhOOAgg0KDQp8IOODleOCoeOCpOODqyB8IOWGheWuuSB8DQp8LS0tfC0tLXwNCnwgYHBhcnR5bnVtLmNzdmAgfCDlrp/pqJMx44Gu5YWl5Yqb44OH44O844K/IHwNCnwgYGNvbmpvaW50X3N0dWR5Mi5jc3ZgIHwg5a6f6aiTMuOBruWFpeWKm+ODh+ODvOOCvyB8DQp8IGBjb25qb2ludF9TMy5jc3ZgIHwg5a6f6aiTM+OBruWFpeWKm+ODh+ODvOOCvyB8DQoNCiMjIDIuIOW/heimgeOBqlLjg5Hjg4PjgrHjg7zjgrgNCg0K5YiG5p6Q44Kz44O844OJ44Gn5L2/55So44GZ44KL5Li76KaB44OR44OD44Kx44O844K444Gv5Lul5LiL44Gu44Go44GK44KK44Gn44GC44KL44CCDQoNCmBgYHtyIHJlYWRtZS1pbnN0YWxsLXBhY2thZ2VzLCBldmFsPUZBTFNFfQ0KaW5zdGFsbC5wYWNrYWdlcyhjKA0KICAiZHBseXIiLCAidGlkeXIiLCAic3RyaW5nciIsICJwdXJyciIsICJyZWFkciIsDQogICJmaXhlc3QiLCAidGliYmxlIiwgImZvcmNhdHMiLCAiZ2dwbG90MiIsICJzY2FsZXMiLA0KICAic3Vydml2YWwiLCAiZ2d0ZXh0IiwgInBhdGNod29yayIsICJybWFya2Rvd24iLCAia25pdHIiDQopKQ0KYGBgDQoNCiMjIDMuIOWQhOeoruOBruODh+ODleOCqeODq+ODiOioreWumg0KDQrlhpLpoK3jga4gYHBhcmFtc2Ag44Gn44CB5YWl5Yqb44OV44Kh44Kk44Or44CB5Ye65Yqb5YWI44CB44OW44O844OI44K544OI44Op44OD44OX5Zue5pWw44KS5aSJ5pu05Y+v6IO944Gn44GC44KL44CC54++5Zyo44Gu5Li76KaB44Gq44OH44OV44Kp44Or44OI5YCk44Gv5qyh44Gu44Go44GK44KK44Gn44GC44KL44CCDQoNCnwg44OR44Op44Oh44O844K/IHwg44OH44OV44Kp44Or44OIIHwg5oSP5ZGzIHwNCnwtLS18LS0tOnwtLS18DQp8IGBvdXRwdXRfcm9vdGAgfCBgY29uam9pbnRfcmVwbGljYXRpb25fcmVzdWx0c2AgfCDlhajlh7rlipvjgpLkv53lrZjjgZnjgovjg6vjg7zjg4jjg4fjgqPjg6zjgq/jg4jjg6ogfA0KfCBgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CYCB8IDIwMDAgfCDkuLvopoHjgarph43opoHluqbjg7vnm7jlr77mr5Tph43jga7jg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5flj43lvqnmlbAgfA0KfCBgc3VwcG9ydF9ib290c3RyYXBfQmAgfCA1MDAgfCDmlK/mjIHmlL/lhZrliKXliIbmnpDjga7jg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5flj43lvqnmlbAgfA0KDQoNCg0KIyMgNC4g5Ye65Yqb44OV44Kh44Kk44OrDQoNCuWIhuaekOe1kOaenOOBr+ODh+ODleOCqeODq+ODiOOBpyBgY29uam9pbnRfcmVwbGljYXRpb25fcmVzdWx0cy9gIOWGheOBq+S/neWtmOOBleOCjOOCi+ioreWumuOBq+OBquOBo+OBpuOBhOOCi+OAguS4u+OBquani+aIkOOBr+S7peS4i+OBrumAmuOCiuOAgg0KDQotIGBtYWluX3RleHQvYO+8muacrOaWh+eUqOOBruWbs+OBqOihqA0KLSBgc3VwcGxlbWVudC9g77ya5a6f6aiT5Yil44GK44KI44Gz5a6f6aiT5qiq5pat44Gu6KOc6YG65Zuz6KGo77yIQ1NW44CBTGFUZVjjgIHlm7PvvIkNCi0gYGRpYWdub3N0aWNzL2DvvJrmqJnmnKzjgrnjgq/jg6rjg7zjg4vjg7PjgrDjgIHlibLku5jjg5Djg6njg7PjgrnjgIHjg5fjg63jg5XjgqPjg7zjg6vnhKHkvZzngrrljJbjga7oqLrmlq0NCi0gYG1vZGVsX29iamVjdHMvYO+8muWGjeWIqeeUqOWPr+iDveOBquODouODh+ODq+ODu+WIhuaekOOCquODluOCuOOCp+OCr+ODiA0KLSBgbG9ncy9g77yaYHNlc3Npb25JbmZvYCDjgarjganjga7lho3nj77mgKfmg4XloLENCg0K5ZCE5YiG5p6Q44Gu6YCU5Lit44Gu57WM6YGO5L2c5oiQ44GV44KM44KL5ZCE56iu44Kq44OW44K444Kn44Kv44OI44Gq44Gp44GvIGBfd29ya2luZy9gIOOBq+S/neWtmOOBleOCjOOAgeacgOe1guautemajuOBp+S4iuiomOOBruODh+OCo+ODrOOCr+ODiOODquOBq+aVtOeQhuOBmeOCi+OCiOOBhuOBq+ioreWumuOBl+OBn+OAglLjgYrjgojjgbPlkITjg5Hjg4PjgrHjg7zjgrjjga7lrp/ooYznkrDlooPjga/jgIHliIbmnpDlrozkuoblvozjgasgYHNlc3Npb25JbmZvYCDjgajjgZfjgabkv53lrZjjgZXjgozjgovoqK3lrprjgajjgarjgaPjgabjgYTjgovjgIINCg0KIyMgNS4g44GT44Gu44Kq44Oz44Op44Kk44Oz6KOc6YG644Go5YaN54++44Kz44O844OJ44Gu6Kqt44G/5pa5DQoNCioqQeevgCoq44Gv5pys5paH44O76KOc6YG644Gu5Zuz6KGo44KS55Sf5oiQ44GZ44KL5a6f6KGM44Kz44O844OJ44CBKipC56+AKirku6XpmY3jga/liIbmnpDmqJnmnKzjgIHmjqjlrprph4/jgIHnhKHkvZzngrrljJbjg7vjg5Djg6njg7PjgrnoqLrmlq3jgIHjgYrjgojjgbPlkIToo5zotrPntZDmnpzjgpLjgIHjgrPjg7zjg4njgajlr77lv5zjgZXjgZvjgabnorroqo3jgZnjgovjgZ/jgoHjga7jgrvjgq/jgrfjg6fjg7PjgafjgYLjgovjgIIqKkrnr4AqKuOBq+OBr+OAgeWun+mokzHjgJwz44Gn5a6f6Zqb44Gr55So44GE44Gf6Kq/5p+756Wo44Gu6LOq5ZWP5paH44O75Zue562U5b2i5byP44KS44CB6YeN6KSH44GZ44KL44Kz44Oz44K444On44Kk44Oz44OI6Kqy6aGM44KS5pW055CG44GX44Gf44GG44GI44Gn5YaN5o6y44GZ44KL44CC55S76Z2i5LiK6YOo44GuICoqU2hvdyBBbGwgQ29kZSAvIEhpZGUgQWxsIENvZGUqKiDjgb7jgZ/jga/lj7PkuIrjga4gKipDb2RlKiog44Oh44OL44Ol44O844GL44KJ44CB44Kz44O844OJ5YWo5L2T44Gu6KGo56S644O76Z2e6KGo56S644KS5YiH44KK5pu/44GI44KJ44KM44KL44CCDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBlY2hvID0gVFJVRSwNCiAgbWVzc2FnZSA9IEZBTFNFLA0KICB3YXJuaW5nID0gRkFMU0UsDQogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLA0KICBjb21tZW50ID0gIiM+IiwNCiAgb3V0LndpZHRoID0gIjk2JSINCikNCg0Kb3B0aW9ucygNCiAgY29uam9pbnQuc3R1ZHkxX2RhdGEgPSBwYXJhbXMkc3R1ZHkxX2RhdGEsDQogIGNvbmpvaW50LnN0dWR5Ml9kYXRhID0gcGFyYW1zJHN0dWR5Ml9kYXRhLA0KICBjb25qb2ludC5zdHVkeTNfZGF0YSA9IHBhcmFtcyRzdHVkeTNfZGF0YSwNCiAgY29uam9pbnQub3V0cHV0X3Jvb3QgPSBwYXJhbXMkb3V0cHV0X3Jvb3QsDQogIGNvbmpvaW50LnJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiA9IGFzLmludGVnZXIocGFyYW1zJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiksDQogIGNvbmpvaW50LnN1cHBvcnRfYm9vdHN0cmFwX0IgPSBhcy5pbnRlZ2VyKHBhcmFtcyRzdXBwb3J0X2Jvb3RzdHJhcF9CKSwNCiAgY29uam9pbnQucmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA9IGlzVFJVRShwYXJhbXMkcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCksDQogIGNvbmpvaW50LnJlcnVuX3N1cHBvcnRfYm9vdHN0cmFwID0gaXNUUlVFKHBhcmFtcyRyZXJ1bl9zdXBwb3J0X2Jvb3RzdHJhcCksDQogIGNvbmpvaW50Lm1pbl9zdXBwb3J0X3RvdGFsX24gPSBhcy5pbnRlZ2VyKHBhcmFtcyRtaW5fc3VwcG9ydF90b3RhbF9uKSwNCiAgY29uam9pbnQubWluX3N1cHBvcnRfY2VsbF9uID0gYXMuaW50ZWdlcihwYXJhbXMkbWluX3N1cHBvcnRfY2VsbF9uKQ0KKQ0KDQpzdXBwX3Jvb3QgPC0gZmlsZS5wYXRoKHBhcmFtcyRvdXRwdXRfcm9vdCwgInN1cHBsZW1lbnQiKQ0KZGlhZ19yb290IDwtIGZpbGUucGF0aChwYXJhbXMkb3V0cHV0X3Jvb3QsICJkaWFnbm9zdGljcyIpDQpjcm9zc19yb290IDwtIGZpbGUucGF0aChzdXBwX3Jvb3QsICJjcm9zc19zdHVkeSIpDQoNCg0Kc3R1ZHlfY3N2IDwtIGZ1bmN0aW9uKHN0dWR5X2lkLCBmaWxlKSB7DQogIGZpbGUucGF0aChzdXBwX3Jvb3QsIHN0dWR5X2lkLCAidGFibGVzX2NzdiIsIGZpbGUpDQp9DQpzdHVkeV9maWcgPC0gZnVuY3Rpb24oc3R1ZHlfaWQsIGZpbGUpIHsNCiAgZmlsZS5wYXRoKHN1cHBfcm9vdCwgc3R1ZHlfaWQsICJmaWd1cmVzIiwgZmlsZSkNCn0NCmRpYWdfZmlnIDwtIGZ1bmN0aW9uKHN0dWR5X2lkLCB0eXBlLCBmaWxlKSB7DQogIGZpbGUucGF0aChkaWFnX3Jvb3QsIHN0dWR5X2lkLCB0eXBlLCBmaWxlKQ0KfQ0KY3Jvc3NfY3N2IDwtIGZ1bmN0aW9uKGZpbGUpIHsNCiAgZmlsZS5wYXRoKGNyb3NzX3Jvb3QsICJ0YWJsZXNfY3N2IiwgZmlsZSkNCn0NCmNyb3NzX2ZpZyA8LSBmdW5jdGlvbihmaWxlKSB7DQogIGZpbGUucGF0aChjcm9zc19yb290LCAiZmlndXJlcyIsIGZpbGUpDQp9DQpgYGANCg0KDQojIEEuIOWQhOWbs+ihqOOBruWGjeePvuOCs+ODvOODiQ0KDQojIyBBLjEg5YWx6YCa44Kz44O844OJDQoNCmBgYHtyIGExLWNvbW1vbi1jb2RlLCBldmFsPXBhcmFtcyRydW5fYW5hbHlzaXMsIHJlc3VsdHM9J2hpZGUnLCBmaWcuc2hvdz0naGlkZSd9DQojIOWFsemAmuOCs+ODvOODiQ0Kb3B0aW9ucyhzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQoNCnVuaWZpZWRfb3V0cHV0X3Jvb3QgPC0gZ2V0T3B0aW9uKA0KICAiY29uam9pbnQub3V0cHV0X3Jvb3QiLA0KICAiY29uam9pbnRfcmVwbGljYXRpb25fcmVzdWx0cyINCikNCg0KZGlyLmNyZWF0ZSgNCiAgdW5pZmllZF9vdXRwdXRfcm9vdCwNCiAgc2hvd1dhcm5pbmdzID0gRkFMU0UsDQogIHJlY3Vyc2l2ZSA9IFRSVUUNCikNCg0KdW5pZmllZF9jb25maWcgPC0gbGlzdCgNCiAgb3V0cHV0X3Jvb3QgPSB1bmlmaWVkX291dHB1dF9yb290LA0KDQogIGN1ZV9pbXBvcnRhbmNlX21ldHJpY192ZXJzaW9uID0gInY0X3NjcmVlbmluZ19hdXRvZGV0ZWN0IiwNCg0KICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgPSBhcy5pbnRlZ2VyKA0KICAgIGdldE9wdGlvbigiY29uam9pbnQucmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CIiwgMjAwMEwpDQogICksDQogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCA9IGFzLmludGVnZXIoDQogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQiLCAyMDI2MDczMEwpDQogICksDQogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkgPSBhcy5pbnRlZ2VyKA0KICAgIGdldE9wdGlvbigiY29uam9pbnQucmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeSIsIDEwMEwpDQogICksDQogIHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAgPSBpc1RSVUUoDQogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5yZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwIiwgRkFMU0UpDQogICksDQoNCiAgbWluX3N1cHBvcnRfdG90YWxfbiA9IGFzLmludGVnZXIoDQogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5taW5fc3VwcG9ydF90b3RhbF9uIiwgMTUwTCkNCiAgKSwNCiAgbWluX3N1cHBvcnRfY2VsbF9uID0gYXMuaW50ZWdlcigNCiAgICBnZXRPcHRpb24oImNvbmpvaW50Lm1pbl9zdXBwb3J0X2NlbGxfbiIsIDQwTCkNCiAgKSwNCiAgc3VwcG9ydF9ib290c3RyYXBfQiA9IGFzLmludGVnZXIoDQogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5zdXBwb3J0X2Jvb3RzdHJhcF9CIiwgNTAwTCkNCiAgKSwNCiAgc3VwcG9ydF9ib290c3RyYXBfc2VlZCA9IGFzLmludGVnZXIoDQogICAgZ2V0T3B0aW9uKCJjb25qb2ludC5zdXBwb3J0X2Jvb3RzdHJhcF9zZWVkIiwgMjAyNjA4MDZMKQ0KICApLA0KICByZXJ1bl9zdXBwb3J0X2Jvb3RzdHJhcCA9IGlzVFJVRSgNCiAgICBnZXRPcHRpb24oImNvbmpvaW50LnJlcnVuX3N1cHBvcnRfYm9vdHN0cmFwIiwgRkFMU0UpDQogICksDQoNCiAgc3R1ZHkxID0gbGlzdCgNCiAgICBkYXRhX2ZpbGUgPSBnZXRPcHRpb24oImNvbmpvaW50LnN0dWR5MV9kYXRhIiwgInBhcnR5bnVtLmNzdiIpLA0KICAgIG91dHB1dF9kaXIgPSBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfcm9vdCwgIl93b3JraW5nIiwgInN0dWR5MSIpDQogICksDQogIHN0dWR5MiA9IGxpc3QoDQogICAgZGF0YV9maWxlID0gZ2V0T3B0aW9uKCJjb25qb2ludC5zdHVkeTJfZGF0YSIsICJjb25qb2ludF9zdHVkeTIuY3N2IiksDQogICAgb3V0cHV0X2RpciA9IGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9yb290LCAiX3dvcmtpbmciLCAic3R1ZHkyIikNCiAgKSwNCiAgc3R1ZHkzID0gbGlzdCgNCiAgICBkYXRhX2ZpbGUgPSBnZXRPcHRpb24oImNvbmpvaW50LnN0dWR5M19kYXRhIiwgImNvbmpvaW50X1MzLmNzdiIpLA0KICAgIG91dHB1dF9kaXIgPSBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfcm9vdCwgIl93b3JraW5nIiwgInN0dWR5MyIpDQogICkNCikNCg0KY2F0KA0KICAiVW5pZmllZCBjb25qb2ludCByZXBsaWNhdGlvbiBwaXBlbGluZVxuIiwNCiAgIk91dHB1dCByb290OiAiLCB1bmlmaWVkX2NvbmZpZyRvdXRwdXRfcm9vdCwgIlxuIiwNCiAgIlN0dWR5IDEgZGF0YTogIiwgdW5pZmllZF9jb25maWckc3R1ZHkxJGRhdGFfZmlsZSwgIlxuIiwNCiAgIlN0dWR5IDIgZGF0YTogIiwgdW5pZmllZF9jb25maWckc3R1ZHkyJGRhdGFfZmlsZSwgIlxuIiwNCiAgIlN0dWR5IDMgZGF0YTogIiwgdW5pZmllZF9jb25maWckc3R1ZHkzJGRhdGFfZmlsZSwgIlxuIiwNCiAgc2VwID0gIiINCikNCg0KDQpkZXRlY3RfZmluYWxfY29uc2VudF9jb2x1bW4gPC0gZnVuY3Rpb24oDQogIHJhdywNCiAgcHJlZmVycmVkX2NhbmRpZGF0ZXMgPSBjKCJROC4xIiwgIlE5LjEiLCAiUTEwLjEiKSwNCiAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkiDQopIHsNCiAgaWYgKCFpcy5kYXRhLmZyYW1lKHJhdykgfHwgbmNvbChyYXcpID09IDBMKSB7DQogICAgc3RvcCgiQ2hlY2sgZGF0YSIpDQogIH0NCg0KICBwcmV2aWV3X24gPC0gbWluKDEyTCwgbnJvdyhyYXcpKQ0KDQogIG5vcm1hbGl6ZV9wcmV2aWV3IDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4IDwtIGFzLmNoYXJhY3Rlcih4KQ0KICAgIHhbaXMubmEoeCldIDwtICIiDQogICAgeCA8LSBnc3ViKCLjgIAiLCAiICIsIHgsIGZpeGVkID0gVFJVRSkNCiAgICB4IDwtIGdzdWIoIltbOnNwYWNlOl1dKyIsICIgIiwgeCkNCiAgICB0cmltd3MoeCkNCiAgfQ0KDQogIHNjb3JlX29uZSA8LSBmdW5jdGlvbihjb2x1bW5fbmFtZSkgew0KICAgIHByZXZpZXcgPC0gcGFzdGUoDQogICAgICBub3JtYWxpemVfcHJldmlldyh1dGlsczo6aGVhZChyYXdbW2NvbHVtbl9uYW1lXV0sIHByZXZpZXdfbikpLA0KICAgICAgY29sbGFwc2UgPSAiICINCiAgICApDQoNCiAgICBzY29yZSA8LSAwTA0KDQogICAgaWYgKGdyZXBsKCLmnIDntYLmhI/mgJ3norroqo0iLCBwcmV2aWV3LCBmaXhlZCA9IFRSVUUpKSB7DQogICAgICBzY29yZSA8LSBzY29yZSArIDhMDQogICAgfQ0KICAgIGlmIChncmVwbCgi44GT44Gh44KJ44GM6Kq/5p+744Gu5pyA5b6M44Gu55S76Z2iIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSB8fA0KICAgICAgICBncmVwbCgi6Kq/5p+744Gu5pyA5b6M44Gu55S76Z2iIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSkgew0KICAgICAgc2NvcmUgPC0gc2NvcmUgKyA2TA0KICAgIH0NCiAgICBpZiAoZ3JlcGwoIuWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCiyIsIHByZXZpZXcsIGZpeGVkID0gVFJVRSkpIHsNCiAgICAgIHNjb3JlIDwtIHNjb3JlICsgOEwNCiAgICB9DQogICAgaWYgKGdyZXBsKCLlm57nrZTntZDmnpzjgpLpgIHkv6HjgZfjgarjgYQiLCBwcmV2aWV3LCBmaXhlZCA9IFRSVUUpIHx8DQogICAgICAgIGdyZXBsKCLlm57nrZTjgpLpgIHkv6HjgZfjgarjgYQiLCBwcmV2aWV3LCBmaXhlZCA9IFRSVUUpKSB7DQogICAgICBzY29yZSA8LSBzY29yZSArIDVMDQogICAgfQ0KICAgIGlmIChncmVwbCgi5pys6Kq/5p+744Gu5Li75peo44Gr5ZCM5oSPIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSB8fA0KICAgICAgICBncmVwbCgi5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSPIiwgcHJldmlldywgZml4ZWQgPSBUUlVFKSkgew0KICAgICAgc2NvcmUgPC0gc2NvcmUgKyAzTA0KICAgIH0NCiAgICBpZiAoY29sdW1uX25hbWUgJWluJSBwcmVmZXJyZWRfY2FuZGlkYXRlcykgew0KICAgICAgc2NvcmUgPC0gc2NvcmUgKyAxTA0KICAgIH0NCg0KICAgIHNjb3JlDQogIH0NCg0KICBjYW5kaWRhdGVfdGFibGUgPC0gZGF0YS5mcmFtZSgNCiAgICBjb2x1bW4gPSBuYW1lcyhyYXcpLA0KICAgIHNjb3JlID0gdmFwcGx5KG5hbWVzKHJhdyksIHNjb3JlX29uZSwgaW50ZWdlcigxKSksDQogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQogICkNCg0KICBjYW5kaWRhdGVfdGFibGUgPC0gY2FuZGlkYXRlX3RhYmxlW2NhbmRpZGF0ZV90YWJsZSRzY29yZSA+IDBMLCAsIGRyb3AgPSBGQUxTRV0NCg0KICBpZiAobnJvdyhjYW5kaWRhdGVfdGFibGUpID09IDBMKSB7DQogICAgZXhpc3RpbmdfcHJlZmVycmVkIDwtIHByZWZlcnJlZF9jYW5kaWRhdGVzWw0KICAgICAgcHJlZmVycmVkX2NhbmRpZGF0ZXMgJWluJSBuYW1lcyhyYXcpDQogICAgXQ0KDQogICAgaWYgKGxlbmd0aChleGlzdGluZ19wcmVmZXJyZWQpID09IDFMKSB7DQogICAgICBtZXNzYWdlKCJGaW5hbCBjb25zZW50OiAiLCBleGlzdGluZ19wcmVmZXJyZWRbWzFdXSkNCiAgICAgIHJldHVybihleGlzdGluZ19wcmVmZXJyZWRbWzFdXSkNCiAgICB9DQoNCiAgICBsaWtlbHlfcXVlc3Rpb25fY29sdW1ucyA8LSBuYW1lcyhyYXcpWw0KICAgICAgZ3JlcGwoIl5RWzAtOV0rKFxcLlswLTldKyk/KF9bMC05XSspPyQiLCBuYW1lcyhyYXcpKQ0KICAgIF0NCg0KICAgIHN0b3AoIkNoZWNrIGZpbmFsIGNvbnNlbnQiKQ0KICB9DQoNCiAgbWF4X3Njb3JlIDwtIG1heChjYW5kaWRhdGVfdGFibGUkc2NvcmUpDQogIGJlc3QgPC0gY2FuZGlkYXRlX3RhYmxlJGNvbHVtbltjYW5kaWRhdGVfdGFibGUkc2NvcmUgPT0gbWF4X3Njb3JlXQ0KDQogIGlmIChsZW5ndGgoYmVzdCkgPiAxTCkgew0KICAgIHByZWZlcnJlZF9iZXN0IDwtIHByZWZlcnJlZF9jYW5kaWRhdGVzWw0KICAgICAgcHJlZmVycmVkX2NhbmRpZGF0ZXMgJWluJSBiZXN0DQogICAgXQ0KDQogICAgaWYgKGxlbmd0aChwcmVmZXJyZWRfYmVzdCkgPj0gMUwpIHsNCiAgICAgIGJlc3QgPC0gcHJlZmVycmVkX2Jlc3RbWzFdXQ0KICAgIH0gZWxzZSB7DQogICAgICBzdG9wKCJDaGVjayBmaW5hbCBjb25zZW50IikNCiAgICB9DQogIH0NCg0KICBtZXNzYWdlKCJGaW5hbCBjb25zZW50OiAiLCBiZXN0W1sxXV0pDQoNCg0KICBiZXN0W1sxXV0NCn0NCg0KcXVhbHRyaWNzX3ByZXZpZXdfdGV4dCA8LSBmdW5jdGlvbihyYXcsIGNvbHVtbl9uYW1lLCBwcmV2aWV3X24gPSAxMkwpIHsNCiAgaWYgKCFjb2x1bW5fbmFtZSAlaW4lIG5hbWVzKHJhdykpIHsNCiAgICByZXR1cm4oIiIpDQogIH0NCg0KICB4IDwtIGFzLmNoYXJhY3Rlcih1dGlsczo6aGVhZChyYXdbW2NvbHVtbl9uYW1lXV0sIG1pbihwcmV2aWV3X24sIG5yb3cocmF3KSkpKQ0KICB4W2lzLm5hKHgpXSA8LSAiIg0KICB4IDwtIGdzdWIoIuOAgCIsICIgIiwgeCwgZml4ZWQgPSBUUlVFKQ0KICB4IDwtIGdzdWIoIltbOnNwYWNlOl1dKyIsICIgIiwgeCkNCiAgdHJpbXdzKHBhc3RlKHgsIGNvbGxhcHNlID0gIiAiKSkNCn0NCg0KZnVsbHdpZHRoX2RpZ2l0IDwtIGZ1bmN0aW9uKG4pIHsNCiAgc3Vic3RyKCLvvJDvvJHvvJLvvJPvvJTvvJXvvJbvvJfvvJjvvJkiLCBuICsgMUwsIG4gKyAxTCkNCn0NCg0KcXVlc3Rpb25fb3JkZXJfa2V5IDwtIGZ1bmN0aW9uKHgpIHsNCiAgbSA8LSByZWdleGVjKCJeUShbMC05XSspXFwuKFswLTldKykiLCB4KQ0KICBwYXJ0cyA8LSByZWdtYXRjaGVzKHgsIG0pDQoNCiAgdmFwcGx5KA0KICAgIHBhcnRzLA0KICAgIGZ1bmN0aW9uKHopIHsNCiAgICAgIGlmIChsZW5ndGgoeikgPCAzTCkgew0KICAgICAgICByZXR1cm4oSW5mKQ0KICAgICAgfQ0KICAgICAgYXMubnVtZXJpYyh6W1syXV0pICogMTAwMCArIGFzLm51bWVyaWMoeltbM11dKQ0KICAgIH0sDQogICAgbnVtZXJpYygxKQ0KICApDQp9DQoNCmRldGVjdF9hdHRlbnRpb25fY2hlY2tfY29sdW1uIDwtIGZ1bmN0aW9uKA0KICByYXcsDQogIHByZWZlcnJlZF9jYW5kaWRhdGVzID0gYygiUTI1LjFfMTEiLCAiUTI1LjFfMTAiKSwNCiAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkiDQopIHsNCiAgbWV0YWRhdGEgPC0gZGF0YS5mcmFtZSgNCiAgICBjb2x1bW4gPSBuYW1lcyhyYXcpLA0KICAgIHRleHQgPSB2YXBwbHkobmFtZXMocmF3KSwgZnVuY3Rpb24odikgcXVhbHRyaWNzX3ByZXZpZXdfdGV4dChyYXcsIHYpLCBjaGFyYWN0ZXIoMSkpLA0KICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KICApDQoNCiAgc2NvcmUgPC0gaW50ZWdlcihucm93KG1ldGFkYXRhKSkNCiAgc2NvcmUgPC0gc2NvcmUgKyBpZmVsc2UoZ3JlcGwoIuW/heOBmiIsIG1ldGFkYXRhJHRleHQsIGZpeGVkID0gVFJVRSksIDhMLCAwTCkNCiAgc2NvcmUgPC0gc2NvcmUgKyBpZmVsc2UoZ3JlcGwoIumBuOOCkyIsIG1ldGFkYXRhJHRleHQsIGZpeGVkID0gVFJVRSksIDVMLCAwTCkNCiAgc2NvcmUgPC0gc2NvcmUgKyBpZmVsc2UoZ3JlcGwoIjN877yTIiwgbWV0YWRhdGEkdGV4dCksIDRMLCAwTCkNCiAgc2NvcmUgPC0gc2NvcmUgKyBpZmVsc2UobWV0YWRhdGEkY29sdW1uICVpbiUgcHJlZmVycmVkX2NhbmRpZGF0ZXMsIDFMLCAwTCkNCiAgbWV0YWRhdGEkc2NvcmUgPC0gc2NvcmUNCg0KICBjYW5kaWRhdGVzIDwtIG1ldGFkYXRhWw0KICAgIGdyZXBsKCLlv4XjgZoiLCBtZXRhZGF0YSR0ZXh0LCBmaXhlZCA9IFRSVUUpICYNCiAgICAgIGdyZXBsKCLpgbjjgpMiLCBtZXRhZGF0YSR0ZXh0LCBmaXhlZCA9IFRSVUUpICYNCiAgICAgIGdyZXBsKCIzfO+8kyIsIG1ldGFkYXRhJHRleHQpLA0KICAgICwNCiAgICBkcm9wID0gRkFMU0UNCiAgXQ0KDQogIGlmIChucm93KGNhbmRpZGF0ZXMpID09IDBMKSB7DQogICAgc3RvcCgiQ2hlY2sgYXR0ZW50aW9uIGl0ZW0iKQ0KICB9DQoNCiAgY2FuZGlkYXRlcyA8LSBjYW5kaWRhdGVzW29yZGVyKC1jYW5kaWRhdGVzJHNjb3JlKSwgLCBkcm9wID0gRkFMU0VdDQogIGJlc3Rfc2NvcmUgPC0gY2FuZGlkYXRlcyRzY29yZVtbMV1dDQogIGJlc3QgPC0gY2FuZGlkYXRlcyRjb2x1bW5bY2FuZGlkYXRlcyRzY29yZSA9PSBiZXN0X3Njb3JlXQ0KDQogIGlmIChsZW5ndGgoYmVzdCkgPiAxTCkgew0KICAgIHByZWZlcnJlZF9iZXN0IDwtIHByZWZlcnJlZF9jYW5kaWRhdGVzW3ByZWZlcnJlZF9jYW5kaWRhdGVzICVpbiUgYmVzdF0NCiAgICBpZiAobGVuZ3RoKHByZWZlcnJlZF9iZXN0KSA9PSAxTCkgew0KICAgICAgYmVzdCA8LSBwcmVmZXJyZWRfYmVzdA0KICAgIH0gZWxzZSB7DQogICAgICBzdG9wKCJDaGVjayBhdHRlbnRpb24gaXRlbSIpDQogICAgfQ0KICB9DQoNCiAgbWVzc2FnZSgiQXR0ZW50aW9uIGl0ZW06ICIsIGJlc3RbWzFdXSkNCiAgYmVzdFtbMV1dDQp9DQoNCnJlc3BvbnNlX2NvZGVfbnVtZXJpYyA8LSBmdW5jdGlvbih4KSB7DQogIHggPC0gYXMuY2hhcmFjdGVyKHgpDQogIHhbaXMubmEoeCldIDwtICIiDQogIHggPC0gZ3N1Yigi44CAIiwgIiAiLCB4LCBmaXhlZCA9IFRSVUUpDQogIHggPC0gdHJpbXdzKGdzdWIoIltbOnNwYWNlOl1dKyIsICIgIiwgeCkpDQoNCiAgZXhhY3QgPC0gZ3JlcGwoIl5bMC05XSsoPzpcXC4wKyk/JCIsIHgsIHBlcmwgPSBUUlVFKQ0KICBvdXQgPC0gcmVwKE5BX3JlYWxfLCBsZW5ndGgoeCkpDQogIG91dFtleGFjdF0gPC0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKHhbZXhhY3RdKSkNCg0KICB0cmFpbGluZyA8LSByZWdleGVjKCJcXCgoWzAtOV0rKVxcKVxccyokIiwgeCkNCiAgdHJhaWxpbmdfcGFydHMgPC0gcmVnbWF0Y2hlcyh4LCB0cmFpbGluZykNCiAgdHJhaWxpbmdfY29kZSA8LSB2YXBwbHkoDQogICAgdHJhaWxpbmdfcGFydHMsDQogICAgZnVuY3Rpb24oeikgaWYgKGxlbmd0aCh6KSA+PSAyTCkgYXMubnVtZXJpYyh6W1syXV0pIGVsc2UgTkFfcmVhbF8sDQogICAgbnVtZXJpYygxKQ0KICApDQogIG91dFtpcy5uYShvdXQpICYgIWlzLm5hKHRyYWlsaW5nX2NvZGUpXSA8LSB0cmFpbGluZ19jb2RlW2lzLm5hKG91dCkgJiAhaXMubmEodHJhaWxpbmdfY29kZSldDQoNCiAgZmlyc3RfbnVtIDwtIHN1cHByZXNzV2FybmluZ3MocmVhZHI6OnBhcnNlX251bWJlcih4KSkNCiAgb3V0W2lzLm5hKG91dCldIDwtIGZpcnN0X251bVtpcy5uYShvdXQpXQ0KICBvdXQNCn0NCg0KZGV0ZWN0X2F0dGVudGlvbl9jb3JyZWN0X2NvZGUgPC0gZnVuY3Rpb24oDQogIHgsDQogIGRpc3BsYXllZF9hbnN3ZXIgPSAzTCwNCiAgcmVjb2RlZF9hbnN3ZXIgPSA2TCwNCiAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkiDQopIHsNCiAgY29kZSA8LSByZXNwb25zZV9jb2RlX251bWVyaWMoeCkNCiAgdGFiIDwtIHNvcnQodGFibGUoY29kZSwgdXNlTkEgPSAibm8iKSwgZGVjcmVhc2luZyA9IFRSVUUpDQoNCiAgbl9kaXNwbGF5IDwtIHN1bShjb2RlID09IGRpc3BsYXllZF9hbnN3ZXIsIG5hLnJtID0gVFJVRSkNCiAgbl9yZWNvZGUgPC0gc3VtKGNvZGUgPT0gcmVjb2RlZF9hbnN3ZXIsIG5hLnJtID0gVFJVRSkNCg0KICBjaG9zZW4gPC0gaWYgKG5fcmVjb2RlID4gbl9kaXNwbGF5KSByZWNvZGVkX2Fuc3dlciBlbHNlIGRpc3BsYXllZF9hbnN3ZXINCiAgbl9ub25taXNzaW5nIDwtIHN1bSghaXMubmEoY29kZSkpDQogIG5fY2hvc2VuIDwtIHN1bShjb2RlID09IGNob3NlbiwgbmEucm0gPSBUUlVFKQ0KDQogIGNhdCgiXG4iLCBzdHVkeV9sYWJlbCwgIu+8muaMh+ekuumgheebruOBruWbnuetlOOCs+ODvOODieWIhuW4g1xuIiwgc2VwID0gIiIpDQogIHByaW50KHV0aWxzOjpoZWFkKHRhYiwgMTVMKSkNCiAgY2F0KA0KICAgICLmjqHnlKjjgZnjgovmraPnrZTjgrPjg7zjg4k6ICIsIGNob3NlbiwNCiAgICAi77yI6KGo56S65LiK44Gu5q2j562U44GvM++8iVxuIiwNCiAgICBzZXAgPSAiIg0KICApDQoNCiAgaWYgKG5fbm9ubWlzc2luZyA9PSAwTCB8fCBuX2Nob3NlbiAvIG5fbm9ubWlzc2luZyA8IDAuNTApIHsNCiAgICBzdG9wKCJDaGVjayBhdHRlbnRpb24gaXRlbSIpDQogIH0NCg0KICBhcy5jaGFyYWN0ZXIoY2hvc2VuKQ0KfQ0KDQpkZXRlY3RfY29uam9pbnRfY2hvaWNlX21hcCA8LSBmdW5jdGlvbigNCiAgcmF3LA0KICBwYXJ0eV9udW1iZXJzID0gMjo1LA0KICBzdHVkeV9sYWJlbCA9ICJTdHVkeSINCikgew0KICBtZXRhZGF0YSA8LSBkYXRhLmZyYW1lKA0KICAgIGNvbHVtbiA9IG5hbWVzKHJhdyksDQogICAgdGV4dCA9IHZhcHBseShuYW1lcyhyYXcpLCBmdW5jdGlvbih2KSBxdWFsdHJpY3NfcHJldmlld190ZXh0KHJhdywgdiksIGNoYXJhY3RlcigxKSksDQogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQogICkNCg0KICBtYXBzIDwtIGxhcHBseSgNCiAgICBwYXJ0eV9udW1iZXJzLA0KICAgIGZ1bmN0aW9uKG5fcGFydHkpIHsNCiAgICAgIGRpZ2l0X3BhdHRlcm4gPC0gcGFzdGUwKCIoPzoiLCBuX3BhcnR5LCAifCIsIGZ1bGx3aWR0aF9kaWdpdChuX3BhcnR5KSwgIilcXHMq44Gk44Gu6YG45oqe6IKiIikNCg0KICAgICAgaGl0IDwtIGdyZXBsKCLku6XkuIvjgasiLCBtZXRhZGF0YSR0ZXh0LCBmaXhlZCA9IFRSVUUpICYNCiAgICAgICAgZ3JlcGwoIumBuOaKnuiCoiIsIG1ldGFkYXRhJHRleHQsIGZpeGVkID0gVFJVRSkgJg0KICAgICAgICBncmVwbChkaWdpdF9wYXR0ZXJuLCBtZXRhZGF0YSR0ZXh0LCBwZXJsID0gVFJVRSkgJg0KICAgICAgICBncmVwbCgi6KGG6K2w6ZmiIiwgbWV0YWRhdGEkdGV4dCwgZml4ZWQgPSBUUlVFKSAmDQogICAgICAgICFncmVwbCgi5o+Q56S644GV44KM44GfLirpgbjmip7ogqLjga7mlbAiLCBtZXRhZGF0YSR0ZXh0LCBwZXJsID0gVFJVRSkgJg0KICAgICAgICBncmVwbCgiXlFbMC05XStcXC5bMC05XSskIiwgbWV0YWRhdGEkY29sdW1uKQ0KDQogICAgICBjYW5kaWRhdGVzIDwtIG1ldGFkYXRhW2hpdCwgLCBkcm9wID0gRkFMU0VdDQogICAgICBjYW5kaWRhdGVzIDwtIGNhbmRpZGF0ZXNbDQogICAgICAgIG9yZGVyKHF1ZXN0aW9uX29yZGVyX2tleShjYW5kaWRhdGVzJGNvbHVtbikpLA0KICAgICAgICAsDQogICAgICAgIGRyb3AgPSBGQUxTRQ0KICAgICAgXQ0KDQogICAgICBpZiAobnJvdyhjYW5kaWRhdGVzKSAhPSA1TCkgew0KICAgICAgICBzdG9wKCJDaGVjayBjaG9pY2UgY29sdW1ucyIpDQogICAgICB9DQoNCiAgICAgIGRhdGEuZnJhbWUoDQogICAgICAgIHBhcnR5X24gPSBuX3BhcnR5LA0KICAgICAgICB0YXNrID0gc2VxX2xlbig1TCksDQogICAgICAgIGNob2ljZV92YXIgPSBjYW5kaWRhdGVzJGNvbHVtbiwNCiAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQogICAgICApDQogICAgfQ0KICApDQoNCiAgb3V0IDwtIGRwbHlyOjpiaW5kX3Jvd3MobWFwcykNCiAgbWVzc2FnZSgiQ2hvaWNlIGNvbHVtbnM6IE9LIikNCiAgcHJpbnQob3V0KQ0KICBvdXQNCn0NCg0KZGV0ZWN0X21hbmlwdWxhdGlvbl9tYXAgPC0gZnVuY3Rpb24ocmF3LCBjaG9pY2VfbWFwLCBzdHVkeV9sYWJlbCA9ICJTdHVkeSIpIHsNCiAgbWV0YWRhdGFfdGV4dCA8LSBzZXROYW1lcygNCiAgICB2YXBwbHkobmFtZXMocmF3KSwgZnVuY3Rpb24odikgcXVhbHRyaWNzX3ByZXZpZXdfdGV4dChyYXcsIHYpLCBjaGFyYWN0ZXIoMSkpLA0KICAgIG5hbWVzKHJhdykNCiAgKQ0KDQogIG91dCA8LSBsYXBwbHkoDQogICAgc29ydCh1bmlxdWUoY2hvaWNlX21hcCRwYXJ0eV9uKSksDQogICAgZnVuY3Rpb24obl9wYXJ0eSkgew0KICAgICAgdmFycyA8LSBjaG9pY2VfbWFwJGNob2ljZV92YXJbY2hvaWNlX21hcCRwYXJ0eV9uID09IG5fcGFydHldDQogICAgICByb290cyA8LSBzdWIoIlxcLlswLTldKyQiLCAiIiwgdmFycykNCiAgICAgIHJvb3QgPC0gbmFtZXMoc29ydCh0YWJsZShyb290cyksIGRlY3JlYXNpbmcgPSBUUlVFKSlbWzFdXQ0KICAgICAgc3VmZml4IDwtIHN1cHByZXNzV2FybmluZ3MoYXMuaW50ZWdlcihzdWIoIl4uKlxcLiIsICIiLCB2YXJzKSkpDQogICAgICBleHBlY3RlZCA8LSBwYXN0ZTAocm9vdCwgIi4iLCBtYXgoc3VmZml4LCBuYS5ybSA9IFRSVUUpICsgMUwpDQoNCiAgICAgIGNhbmRpZGF0ZXMgPC0gbmFtZXMobWV0YWRhdGFfdGV4dClbDQogICAgICAgIHN0YXJ0c1dpdGgobmFtZXMobWV0YWRhdGFfdGV4dCksIHBhc3RlMChyb290LCAiLiIpKSAmDQogICAgICAgICAgZ3JlcGwoIuaPkOekuuOBleOCjOOBnyIsIG1ldGFkYXRhX3RleHQsIGZpeGVkID0gVFJVRSkgJg0KICAgICAgICAgIGdyZXBsKCLpgbjmip7ogqLjga7mlbAiLCBtZXRhZGF0YV90ZXh0LCBmaXhlZCA9IFRSVUUpDQogICAgICBdDQoNCiAgICAgIGlmIChleHBlY3RlZCAlaW4lIGNhbmRpZGF0ZXMpIHsNCiAgICAgICAgY2hvc2VuIDwtIGV4cGVjdGVkDQogICAgICB9IGVsc2UgaWYgKGxlbmd0aChjYW5kaWRhdGVzKSA9PSAxTCkgew0KICAgICAgICBjaG9zZW4gPC0gY2FuZGlkYXRlc1tbMV1dDQogICAgICB9IGVsc2Ugew0KICAgICAgICBzdG9wKCJDaGVjayBtYW5pcHVsYXRpb24gaXRlbSIpDQogICAgICB9DQoNCiAgICAgIGRhdGEuZnJhbWUoDQogICAgICAgIHBhcnR5X24gPSBuX3BhcnR5LA0KICAgICAgICBtYW5pcHVsYXRpb25fdmFyID0gY2hvc2VuLA0KICAgICAgICBjb3JyZWN0X2Fuc3dlciA9IGFzLmNoYXJhY3RlcihuX3BhcnR5KSwNCiAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQogICAgICApDQogICAgfQ0KICApDQoNCiAgb3V0IDwtIGRwbHlyOjpiaW5kX3Jvd3Mob3V0KQ0KICBtZXNzYWdlKCJNYW5pcHVsYXRpb24gaXRlbTogT0siKQ0KICBwcmludChvdXQpDQogIG91dA0KfQ0KDQpwYXJzZV9jaG9pY2VfcG9zaXRpb24gPC0gZnVuY3Rpb24oeCkgew0KICB4IDwtIGFzLmNoYXJhY3Rlcih4KQ0KICB4W2lzLm5hKHgpXSA8LSAiIg0KICB4IDwtIGdzdWIoIuOAgCIsICIgIiwgeCwgZml4ZWQgPSBUUlVFKQ0KICB4IDwtIHRyaW13cyhnc3ViKCJbWzpzcGFjZTpdXSsiLCAiICIsIHgpKQ0KDQogIGxhYmVsX21hdGNoIDwtIHJlZ2V4ZWMoIig/OuaUv+WFmnznirbms4F86YG45oqe6IKiKVxccyooWzEtNV0pIiwgeCwgcGVybCA9IFRSVUUpDQogIGxhYmVsX3BhcnRzIDwtIHJlZ21hdGNoZXMoeCwgbGFiZWxfbWF0Y2gpDQogIGxhYmVsX251bSA8LSB2YXBwbHkoDQogICAgbGFiZWxfcGFydHMsDQogICAgZnVuY3Rpb24oeikgaWYgKGxlbmd0aCh6KSA+PSAyTCkgYXMubnVtZXJpYyh6W1syXV0pIGVsc2UgTkFfcmVhbF8sDQogICAgbnVtZXJpYygxKQ0KICApDQoNCiAgZXhhY3QgPC0gZ3JlcGwoIl5bMS01XSg/OlxcLjArKT8kIiwgeCwgcGVybCA9IFRSVUUpDQogIGV4YWN0X251bSA8LSByZXAoTkFfcmVhbF8sIGxlbmd0aCh4KSkNCiAgZXhhY3RfbnVtW2V4YWN0XSA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoeFtleGFjdF0pKQ0KDQogIHRyYWlsaW5nIDwtIHJlZ2V4ZWMoIlxcKChbMS01XSlcXClcXHMqJCIsIHgpDQogIHRyYWlsaW5nX3BhcnRzIDwtIHJlZ21hdGNoZXMoeCwgdHJhaWxpbmcpDQogIHRyYWlsaW5nX251bSA8LSB2YXBwbHkoDQogICAgdHJhaWxpbmdfcGFydHMsDQogICAgZnVuY3Rpb24oeikgaWYgKGxlbmd0aCh6KSA+PSAyTCkgYXMubnVtZXJpYyh6W1syXV0pIGVsc2UgTkFfcmVhbF8sDQogICAgbnVtZXJpYygxKQ0KICApDQoNCiAgb3V0IDwtIGxhYmVsX251bQ0KICBvdXRbaXMubmEob3V0KV0gPC0gZXhhY3RfbnVtW2lzLm5hKG91dCldDQogIG91dFtpcy5uYShvdXQpXSA8LSB0cmFpbGluZ19udW1baXMubmEob3V0KV0NCiAgb3V0DQp9DQoNCg0KYGBgDQoNCiMjIEEuMiDlrp/pqJMx77ya5pys5paH44Gu5ZuzNOODu+WbszUNCg0KYGBge3IgYTItc3R1ZHkxLWNvZGUsIGV2YWw9cGFyYW1zJHJ1bl9hbmFseXNpcywgcmVzdWx0cz0naGlkZScsIGZpZy5zaG93PSdoaWRlJ30NCiMg5pys5paH44Kz44O844OJDQpzdHVkeTFfZW52IDwtIGxvY2FsKHsNCnJlcXVpcmVkX3BhY2thZ2VzIDwtIGMoDQogICAgImRwbHlyIiwNCiAgICAidGlkeXIiLA0KICAgICJzdHJpbmdyIiwNCiAgICAicHVycnIiLA0KICAgICJyZWFkciIsDQogICAgImZpeGVzdCIsDQogICAgInRpYmJsZSIsDQogICAgImZvcmNhdHMiLA0KICAgICJnZ3Bsb3QyIiwNCiAgICAic2NhbGVzIiwNCiAgICAic3Vydml2YWwiLA0KICAgICJnZ3RleHQiLA0KICAgICJwYXRjaHdvcmsiDQogICkNCg0KICBtaXNzaW5nX3BhY2thZ2VzIDwtIHJlcXVpcmVkX3BhY2thZ2VzWw0KICAgICF2YXBwbHkocmVxdWlyZWRfcGFja2FnZXMsIHJlcXVpcmVOYW1lc3BhY2UsIGxvZ2ljYWwoMSksIHF1aWV0bHkgPSBUUlVFKQ0KICBdDQoNCiAgaWYgKGxlbmd0aChtaXNzaW5nX3BhY2thZ2VzKSA+IDApIHsNCiAgICBzdG9wKCJObyBwYWNrYWdlcyIpDQogIH0NCg0KICBsaWJyYXJ5KGRwbHlyKQ0KICBsaWJyYXJ5KHRpZHlyKQ0KICBsaWJyYXJ5KHN0cmluZ3IpDQogIGxpYnJhcnkocHVycnIpDQogIGxpYnJhcnkocmVhZHIpDQogIGxpYnJhcnkoZml4ZXN0KQ0KICBsaWJyYXJ5KHRpYmJsZSkNCiAgbGlicmFyeShmb3JjYXRzKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQogIGxpYnJhcnkoc2NhbGVzKQ0KICBsaWJyYXJ5KHN1cnZpdmFsKQ0KICBsaWJyYXJ5KHBhdGNod29yaykNCg0KICBkYXRhX2ZpbGUgPC0gdW5pZmllZF9jb25maWckc3R1ZHkxJGRhdGFfZmlsZQ0KICBvdXRwdXRfZGlyIDwtIHVuaWZpZWRfY29uZmlnJHN0dWR5MSRvdXRwdXRfZGlyDQoNCiAgZGlyLmNyZWF0ZShvdXRwdXRfZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkNCg0KICByZXF1aXJlX2luaXRpYWxfY29uc2VudCA8LSBUUlVFDQogIHJlcXVpcmVfZmluYWxfY29uc2VudCA8LSBUUlVFDQogIGluaXRpYWxfY29uc2VudF92YXIgPC0gIlExLjEiDQogIGZpbmFsX2NvbnNlbnRfdmFyIDwtICJROC4xIg0KDQogIHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrIDwtIEZBTFNFDQogIHJlcXVpcmVfbWFuaXB1bGF0aW9uX2NoZWNrIDwtIEZBTFNFDQogIGF0dGVudGlvbl9jaGVja192YXIgPC0gTkFfY2hhcmFjdGVyXw0KICBhdHRlbnRpb25fY2hlY2tfY29ycmVjdCA8LSBOQV9jaGFyYWN0ZXJfDQoNCiAgcmVxdWlyZV9hbGxfZml2ZV90YXNrcyA8LSBUUlVFDQoNCiAgdXNlX2VkdWNhdGlvbl9jb3ZhcmlhdGUgPC0gRkFMU0UNCg0KICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgPC0gdW5pZmllZF9jb25maWckcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CDQogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCA8LSB1bmlmaWVkX2NvbmZpZyRyZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQgKyAxTA0KICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3Byb2dyZXNzX2V2ZXJ5IDwtIHVuaWZpZWRfY29uZmlnJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkNCg0KICByZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwIDwtIHVuaWZpZWRfY29uZmlnJHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXANCg0KDQogIG5vcm1fdGV4dCA8LSBmdW5jdGlvbih4KSB7DQogICAgeCAlPiUNCiAgICAgIGFzLmNoYXJhY3RlcigpICU+JQ0KICAgICAgc3RyX3NxdWlzaCgpICU+JQ0KICAgICAgc3RyX3JlcGxhY2VfYWxsKCLvvZ4iLCAifiIpICU+JQ0KICAgICAgc3RyX3JlcGxhY2VfYWxsKCLjgJwiLCAifiIpDQogIH0NCg0KICBhc19udW0gPC0gZnVuY3Rpb24oeCkgew0KICAgIHN1cHByZXNzV2FybmluZ3MocmVhZHI6OnBhcnNlX251bWJlcihub3JtX3RleHQoeCkpKQ0KICB9DQoNCiAgaXNfcmVzcG9uc2VfY29kZSA8LSBmdW5jdGlvbih4LCBjb2RlKSB7DQogICAgeF9ub3JtIDwtIG5vcm1fdGV4dCh4KQ0KICAgIGNvZGVfY2hyIDwtIGFzLmNoYXJhY3Rlcihjb2RlKQ0KDQogICAgeF9ub3JtID09IGNvZGVfY2hyIHwNCiAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoeF9ub3JtLCBwYXN0ZTAoIlxcKCIsIGNvZGVfY2hyLCAiXFwpJCIpKQ0KICB9DQoNCiAgZmlyc3RfZXhpc3RpbmcgPC0gZnVuY3Rpb24oZGF0LCBjYW5kaWRhdGVzKSB7DQogICAgb3V0IDwtIGNhbmRpZGF0ZXNbY2FuZGlkYXRlcyAlaW4lIG5hbWVzKGRhdCldDQogICAgaWYgKGxlbmd0aChvdXQpID09IDApIE5BX2NoYXJhY3Rlcl8gZWxzZSBvdXRbMV0NCiAgfQ0KDQogIGdldF92YXIgPC0gZnVuY3Rpb24oZGF0LCBjYW5kaWRhdGVzKSB7DQogICAgdiA8LSBmaXJzdF9leGlzdGluZyhkYXQsIGNhbmRpZGF0ZXMpDQogICAgaWYgKGlzLm5hKHYpKSB7DQogICAgICByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhkYXQpKQ0KICAgIH0gZWxzZSB7DQogICAgICBkYXRbW3ZdXQ0KICAgIH0NCiAgfQ0KDQogIHJlbGV2ZWxfaWZfcHJlc2VudCA8LSBmdW5jdGlvbih4LCByZWYpIHsNCiAgICB4IDwtIGZhY3Rvcih4KQ0KICAgIGlmIChyZWYgJWluJSBsZXZlbHMoeCkpIHsNCiAgICAgIHJlbGV2ZWwoeCwgcmVmID0gcmVmKQ0KICAgIH0gZWxzZSB7DQogICAgICB4DQogICAgfQ0KICB9DQoNCiAgZmFjdG9yX21pc3MgPC0gZnVuY3Rpb24oeCwgbWlzcyA9ICLmrKDmkI3jg7vnhKHlm57nrZQiKSB7DQogICAgeCA8LSBub3JtX3RleHQoeCkNCiAgICB4W2lzLm5hKHgpIHwgeCA9PSAiIiB8IHggPT0gIk5BIl0gPC0gbWlzcw0KICAgIGZhY3Rvcih4KQ0KICB9DQoNCiAgbWVhbl9pbXB1dGUgPC0gZnVuY3Rpb24oeCkgew0KICAgIHggPC0gYXMubnVtZXJpYyh4KQ0KICAgIG1pc3MgPC0gYXMuaW50ZWdlcihpcy5uYSh4KSkNCg0KICAgIGlmIChhbGwoaXMubmEoeCkpKSB7DQogICAgICB2YWx1ZSA8LSB4DQogICAgfSBlbHNlIHsNCiAgICAgIHZhbHVlIDwtIGlmZWxzZShpcy5uYSh4KSwgbWVhbih4LCBuYS5ybSA9IFRSVUUpLCB4KQ0KICAgIH0NCg0KICAgIGxpc3QodmFsdWUgPSB2YWx1ZSwgbWlzcyA9IG1pc3MpDQogIH0NCg0KICB3cml0ZV9jc3Zfc2FmZWx5IDwtIGZ1bmN0aW9uKHgsIGZpbGVuYW1lKSB7DQogICAgcmVhZHI6OndyaXRlX2Nzdih4LCBmaWxlLnBhdGgob3V0cHV0X2RpciwgZmlsZW5hbWUpLCBuYSA9ICIiKQ0KICB9DQoNCiAgc2F2ZV9wbG90IDwtIGZ1bmN0aW9uKGZpbGVuYW1lLCBwbG90LCB3aWR0aCwgaGVpZ2h0LCBkcGkgPSAzMDApIHsNCiAgICBnZ3Bsb3QyOjpnZ3NhdmUoDQogICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCBmaWxlbmFtZSksDQogICAgICBwbG90ID0gcGxvdCwNCiAgICAgIHdpZHRoID0gd2lkdGgsDQogICAgICBoZWlnaHQgPSBoZWlnaHQsDQogICAgICBkcGkgPSBkcGkNCiAgICApDQogIH0NCg0KDQogIGlmICghZmlsZS5leGlzdHMoZGF0YV9maWxlKSkgew0KICAgIHN0b3AoIkNoZWNrIGRhdGEiKQ0KICB9DQoNCiAgcmF3IDwtIHJlYWRyOjpyZWFkX2NzdigNCiAgICBkYXRhX2ZpbGUsDQogICAgY29sX3R5cGVzID0gY29scyguZGVmYXVsdCA9IGNvbF9jaGFyYWN0ZXIoKSksDQogICAgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSwNCiAgICBuYW1lX3JlcGFpciA9ICJtaW5pbWFsIg0KICApDQoNCiAgaWYgKCEiUmVzcG9uc2VJZCIgJWluJSBuYW1lcyhyYXcpKSB7DQogICAgc3RvcCgiQ2hlY2sgZGF0YSIpDQogIH0NCg0KICBuYW1lcyhyYXcpIDwtIG5hbWVzKHJhdykgJT4lDQogICAgc3RyX3JlcGxhY2UoIl5GXFwuKFxcZCspXFwuKFxcZCspXFwuKFxcZCspJCIsICJGLVxcMS1cXDItXFwzIikgJT4lDQogICAgc3RyX3JlcGxhY2UoIl5GXFwuKFxcZCspXFwuKFxcZCspJCIsICJGLVxcMS1cXDIiKQ0KDQogIGlmICgNCiAgICByZXF1aXJlX2ZpbmFsX2NvbnNlbnQgJiYNCiAgICAgICgNCiAgICAgICAgaXMubmEoZmluYWxfY29uc2VudF92YXIpIHx8DQogICAgICAgICAgIWZpbmFsX2NvbnNlbnRfdmFyICVpbiUgbmFtZXMocmF3KQ0KICAgICAgKQ0KICApIHsNCiAgICBjb25zZW50X3F1ZXN0aW9uX3BhdHRlcm4gPC0gcGFzdGUwKA0KICAgICAgIuWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCi3wiLA0KICAgICAgIuWbnuetlOOCkumAgeS/oeOBl+OBquOBhHwiLA0KICAgICAgIuWbnuetlOe1kOaenOOCkumAgeS/oeOBl+OBquOBhHwiLA0KICAgICAgIuacgOe1guaEj+aAneeiuuiqjSINCiAgICApDQoNCiAgICBwcmV2aWV3X24gPC0gbWluKDEwTCwgbnJvdyhyYXcpKQ0KDQogICAgZGV0ZWN0ZWRfZmluYWxfY29uc2VudF92YXJzIDwtIG5hbWVzKHJhdylbDQogICAgICB2YXBwbHkoDQogICAgICAgIHJhdywNCiAgICAgICAgZnVuY3Rpb24oY29sdW1uKSB7DQogICAgICAgICAgcHJldmlldyA8LSBub3JtX3RleHQoDQogICAgICAgICAgICB1dGlsczo6aGVhZCgNCiAgICAgICAgICAgICAgY29sdW1uLA0KICAgICAgICAgICAgICBwcmV2aWV3X24NCiAgICAgICAgICAgICkNCiAgICAgICAgICApDQoNCiAgICAgICAgICBhbnkoDQogICAgICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KA0KICAgICAgICAgICAgICBwcmV2aWV3LA0KICAgICAgICAgICAgICBjb25zZW50X3F1ZXN0aW9uX3BhdHRlcm4NCiAgICAgICAgICAgICksDQogICAgICAgICAgICBuYS5ybSA9IFRSVUUNCiAgICAgICAgICApDQogICAgICAgIH0sDQogICAgICAgIGxvZ2ljYWwoMSkNCiAgICAgICkNCiAgICBdDQoNCiAgICBpZiAobGVuZ3RoKGRldGVjdGVkX2ZpbmFsX2NvbnNlbnRfdmFycykgPT0gMUwpIHsNCiAgICAgIGZpbmFsX2NvbnNlbnRfdmFyIDwtIGRldGVjdGVkX2ZpbmFsX2NvbnNlbnRfdmFyc1tbMV1dDQoNCiAgICAgIG1lc3NhZ2UoIkZpbmFsIGNvbnNlbnQ6ICIsIGZpbmFsX2NvbnNlbnRfdmFyKQ0KICAgIH0gZWxzZSBpZiAobGVuZ3RoKGRldGVjdGVkX2ZpbmFsX2NvbnNlbnRfdmFycykgPiAxTCkgew0KICAgICAgc3RvcCgiQ2hlY2sgZmluYWwgY29uc2VudCIpDQogICAgfSBlbHNlIHsNCiAgICAgIGxpa2VseV9xdWVzdGlvbl9jb2x1bW5zIDwtIG5hbWVzKHJhdylbDQogICAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoDQogICAgICAgICAgbmFtZXMocmF3KSwNCiAgICAgICAgICAiXlFbMC05XSsoPzpcXC5bMC05XSspPyQiDQogICAgICAgICkNCiAgICAgIF0NCg0KICAgICAgc3RvcCgiQ2hlY2sgZmluYWwgY29uc2VudCIpDQogICAgfQ0KICB9DQoNCiAgZGZfaGVhZGVyX3JlbW92ZWQgPC0gcmF3ICU+JQ0KICAgIGZpbHRlcigNCiAgICAgICFpcy5uYShSZXNwb25zZUlkKSwNCiAgICAgIFJlc3BvbnNlSWQgIT0gIiIsDQogICAgICAhc3RyX2RldGVjdCgNCiAgICAgICAgbm9ybV90ZXh0KFJlc3BvbnNlSWQpLA0KICAgICAgICAiXihSZXNwb25zZSBJRHzlm57nrZRJRCkkfEltcG9ydElkIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgbXV0YXRlKElEID0gYXMuY2hhcmFjdGVyKFJlc3BvbnNlSWQpKQ0KDQogIGR1cGxpY2F0ZV9pZHMgPC0gZGZfaGVhZGVyX3JlbW92ZWQgJT4lDQogICAgY291bnQoSUQpICU+JQ0KICAgIGZpbHRlcihuID4gMSkNCg0KICBpZiAobnJvdyhkdXBsaWNhdGVfaWRzKSA+IDApIHsNCiAgICBwcmludChkdXBsaWNhdGVfaWRzKQ0KICAgIHN0b3AoIkNoZWNrIikNCiAgfQ0KDQogIHNhbXBsZV9mbG93IDwtIHRpYmJsZSgNCiAgICBzdGFnZSA9ICJRdWFsdHJpY3Pos6rllY/mlofooYzjg7tJbXBvcnRJZOihjOOCkumZpOWkluW+jCIsDQogICAgbiA9IG5yb3coZGZfaGVhZGVyX3JlbW92ZWQpDQogICkNCg0KICBkZiA8LSBkZl9oZWFkZXJfcmVtb3ZlZA0KDQogIGlmIChyZXF1aXJlX2luaXRpYWxfY29uc2VudCkgew0KICAgIGlmIChpcy5uYShpbml0aWFsX2NvbnNlbnRfdmFyKSB8fCAhaW5pdGlhbF9jb25zZW50X3ZhciAlaW4lIG5hbWVzKGRmKSkgew0KICAgICAgc3RvcCgiQ2hlY2sgaW5pdGlhbCBjb25zZW50IikNCiAgICB9DQogICAgZGYgPC0gZGYgJT4lDQogICAgICBmaWx0ZXIoDQogICAgICAgIGlzX3Jlc3BvbnNlX2NvZGUoLmRhdGFbW2luaXRpYWxfY29uc2VudF92YXJdXSwgMSkgfA0KICAgICAgICAgIHN0cl9kZXRlY3QoDQogICAgICAgICAgICBub3JtX3RleHQoLmRhdGFbW2luaXRpYWxfY29uc2VudF92YXJdXSksDQogICAgICAgICAgICAi6Laj5peo44Gr5ZCM5oSP44GX44GmLirljZTlipvjgZnjgosiDQogICAgICAgICAgKQ0KICAgICAgKQ0KICAgIHNhbXBsZV9mbG93IDwtIGJpbmRfcm93cygNCiAgICAgIHNhbXBsZV9mbG93LA0KICAgICAgdGliYmxlKHN0YWdlID0gIuWIneWbnuWQjOaEj+WbnuetlOOCkuS/neaMgSIsIG4gPSBucm93KGRmKSkNCiAgICApDQogIH0NCg0KICBpZiAocmVxdWlyZV9maW5hbF9jb25zZW50KSB7DQogICAgaWYgKGlzLm5hKGZpbmFsX2NvbnNlbnRfdmFyKSB8fCAhZmluYWxfY29uc2VudF92YXIgJWluJSBuYW1lcyhkZikpIHsNCiAgICAgIHN0b3AoIkNoZWNrIGZpbmFsIGNvbnNlbnQiKQ0KICAgIH0NCiAgICBkZiA8LSBkZiAlPiUNCiAgICAgIGZpbHRlcigNCiAgICAgICAgaXNfcmVzcG9uc2VfY29kZSguZGF0YVtbZmluYWxfY29uc2VudF92YXJdXSwgMSkgfA0KICAgICAgICAgIHN0cl9kZXRlY3QoDQogICAgICAgICAgICBub3JtX3RleHQoLmRhdGFbW2ZpbmFsX2NvbnNlbnRfdmFyXV0pLA0KICAgICAgICAgICAgIuWQjOaEj+OBly4q5Zue562U57WQ5p6c44KS6YCB5L+h44GZ44KLIg0KICAgICAgICAgICkNCiAgICAgICkNCiAgICBzYW1wbGVfZmxvdyA8LSBiaW5kX3Jvd3MoDQogICAgICBzYW1wbGVfZmxvdywNCiAgICAgIHRpYmJsZShzdGFnZSA9ICLmnIDntYLlkIzmhI/lm57nrZTjgpLkv53mjIEiLCBuID0gbnJvdyhkZikpDQogICAgKQ0KICB9DQoNCiAgcHJpbnQoc2FtcGxlX2Zsb3cpDQogIHdyaXRlX2Nzdl9zYWZlbHkoc2FtcGxlX2Zsb3csICJzYW1wbGVfZmxvd19iZWZvcmVfY29uam9pbnQuY3N2IikNCg0KDQogIGNob2ljZV9tYXAgPC0gdHJpYmJsZSgNCiAgICB+cGFydHlfbiwgfnRhc2ssIH5jaG9pY2VfdmFyLA0KICAgIDIsIDEsICJRMjQwIiwNCiAgICAyLCAyLCAiUTI1MyIsDQogICAgMiwgMywgIlEyNTQiLA0KICAgIDIsIDQsICJRMjU1IiwNCiAgICAyLCA1LCAiUTI1NiIsDQoNCiAgICAzLCAxLCAiUTIzNSIsDQogICAgMywgMiwgIlEyNDEiLA0KICAgIDMsIDMsICJRMjQyIiwNCiAgICAzLCA0LCAiUTI0MyIsDQogICAgMywgNSwgIlEyNDQiLA0KDQogICAgNCwgMSwgIlEyMzgiLA0KICAgIDQsIDIsICJRMjQ1IiwNCiAgICA0LCAzLCAiUTI0NiIsDQogICAgNCwgNCwgIlEyNDciLA0KICAgIDQsIDUsICJRMjQ4IiwNCg0KICAgIDUsIDEsICJRMjM5IiwNCiAgICA1LCAyLCAiUTI0OSIsDQogICAgNSwgMywgIlEyNTAiLA0KICAgIDUsIDQsICJRMjUxIiwNCiAgICA1LCA1LCAiUTI1MiINCiAgKQ0KDQogIGlmIChyZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjaykgew0KICAgIHN0b3AoIkNoZWNrIikNCiAgfQ0KDQoNCiAgbGV2ZWxfdG9fYXR0cl92YXIgPC0gZnVuY3Rpb24oeCkgew0KICAgIHggPC0gbm9ybV90ZXh0KHgpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICB4ICVpbiUgYygi5Y+z5rS+44O75L+d5a6I55qEIiwgIuS4remBkyIsICLlt6bmtL7jg7vpnanmlrDnmoQiKSB+DQogICAgICAgICJwb2xpY3lfcG9zaXRpb24iLA0KDQogICAgICB4ICVpbiUgYygi5LiO5YWaIiwgIumHjuWFmiIpIH4NCiAgICAgICAgImdvdmVybm1lbnRfc3RhdHVzIiwNCg0KICAgICAgc3RyX2RldGVjdCh4LCAiR0RQ5oiQ6ZW3546HIikgfg0KICAgICAgICAiZ2RwX2dyb3d0aCIsDQoNCiAgICAgIHN0cl9kZXRlY3QoeCwgIuaXpee1jOW5s+WdhyIpIH4NCiAgICAgICAgIm5pa2tlaSIsDQoNCiAgICAgIHggJWluJSBjKCIxMOS7peS4iyIsICIxMH40OSIsICI1MH45OSIsICIxMDB+MTk5IiwgIjIwMOS7peS4iiIpIH4NCiAgICAgICAgInNlYXRzIiwNCg0KICAgICAgc3RyX2RldGVjdCh4LCAiQ1BJfOeJqeS+oSIpIH4NCiAgICAgICAgImNwaSIsDQoNCiAgICAgIHN0cl9kZXRlY3QoeCwgIuWksealreeOh3zpm4fnlKgiKSB+DQogICAgICAgICJ1bmVtcGxveW1lbnQiLA0KDQogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICAgICkNCiAgfQ0KDQogIHJlcXVpcmVkX2F0dHJfdmFycyA8LSBjKA0KICAgICJwb2xpY3lfcG9zaXRpb24iLA0KICAgICJnb3Zlcm5tZW50X3N0YXR1cyIsDQogICAgImdkcF9ncm93dGgiLA0KICAgICJuaWtrZWkiLA0KICAgICJzZWF0cyIsDQogICAgImNwaSIsDQogICAgInVuZW1wbG95bWVudCINCiAgKQ0KDQogIGFsbG93ZWRfbGV2ZWxzIDwtIGxpc3QoDQogICAgcG9saWN5X3Bvc2l0aW9uID0gYygi5Y+z5rS+44O75L+d5a6I55qEIiwgIuS4remBkyIsICLlt6bmtL7jg7vpnanmlrDnmoQiKSwNCiAgICBnb3Zlcm5tZW50X3N0YXR1cyA9IGMoIuS4juWFmiIsICLph47lhZoiKSwNCiAgICBnZHBfZ3Jvd3RoID0gYygNCiAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiLA0KICAgICAgIkdEUOaIkOmVt+eOh+ODl+ODqeOCuTHvvIUiLA0KICAgICAgIkdEUOaIkOmVt+eOh+ODnuOCpOODiuOCuTHvvIUiDQogICAgKSwNCiAgICBuaWtrZWkgPSBjKA0KICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLA0KICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODnuOCpOODiuOCuTEwMDDlhoYiLA0KICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOWkieOCj+OCieOBmiINCiAgICApLA0KICAgIHNlYXRzID0gYygiMTDku6XkuIsiLCAiMTB+NDkiLCAiNTB+OTkiLCAiMTAwfjE5OSIsICIyMDDku6XkuIoiKSwNCiAgICBjcGkgPSBjKA0KICAgICAgIkNQSeWJjeacn+avlMKxMOODneOCpOODs+ODiCIsDQogICAgICAiQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsDQogICAgICAiQ1BJ5YmN5pyf5q+U44Oe44Kk44OK44K5MeODneOCpOODs+ODiCINCiAgICApLA0KICAgIHVuZW1wbG95bWVudCA9IGMoDQogICAgICAi5aSx5qWt546H5YmN5pyf5q+UwrEw77yFIiwNCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwNCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg57jgqTjg4rjgrkx77yFIg0KICAgICkNCiAgKQ0KDQoNCiAgbWFrZV9wcm9maWxlX2xvbmcgPC0gZnVuY3Rpb24oZGF0LCBuX3BhcnR5KSB7DQoNCiAgICBtYXBfbiA8LSBjaG9pY2VfbWFwICU+JQ0KICAgICAgZmlsdGVyKHBhcnR5X24gPT0gbl9wYXJ0eSkNCg0KICAgIHF2YXJzIDwtIG1hcF9uJGNob2ljZV92YXINCg0KICAgIG1pc3NpbmdfcSA8LSBzZXRkaWZmKHF2YXJzLCBuYW1lcyhkYXQpKQ0KICAgIGlmIChsZW5ndGgobWlzc2luZ19xKSA+IDApIHsNCiAgICAgIHN0b3AoIkNoZWNrIGNob2ljZSBjb2x1bW5zIikNCiAgICB9DQoNCiAgICBkYXRfbiA8LSBkYXQgJT4lDQogICAgICBmaWx0ZXIoDQogICAgICAgIGlmX2FueSgNCiAgICAgICAgICBhbGxfb2YocXZhcnMpLA0KICAgICAgICAgIH4gIWlzLm5hKC54KSAmIG5vcm1fdGV4dCgueCkgIT0gIiINCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgY2hvaWNlX2xvbmcgPC0gZGF0X24gJT4lDQogICAgICBzZWxlY3QoSUQsIGFsbF9vZihxdmFycykpICU+JQ0KICAgICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgICBjb2xzID0gYWxsX29mKHF2YXJzKSwNCiAgICAgICAgbmFtZXNfdG8gPSAiY2hvaWNlX3ZhciIsDQogICAgICAgIHZhbHVlc190byA9ICJjaG9pY2VfcmF3Ig0KICAgICAgKSAlPiUNCiAgICAgIGxlZnRfam9pbihtYXBfbiwgYnkgPSAiY2hvaWNlX3ZhciIpICU+JQ0KICAgICAgbXV0YXRlKGNob2ljZSA9IGFzX251bShjaG9pY2VfcmF3KSkgJT4lDQogICAgICBmaWx0ZXIoIWlzLm5hKGNob2ljZSkpICU+JQ0KICAgICAgc2VsZWN0KElELCBwYXJ0eV9uLCB0YXNrLCBjaG9pY2UpDQoNCiAgICBpbnZhbGlkX2Nob2ljZSA8LSBjaG9pY2VfbG9uZyAlPiUNCiAgICAgIGZpbHRlcihjaG9pY2UgPCAxIHwgY2hvaWNlID4gbl9wYXJ0eSkNCg0KICAgIGlmIChucm93KGludmFsaWRfY2hvaWNlKSA+IDApIHsNCiAgICAgIHByaW50KGludmFsaWRfY2hvaWNlKQ0KICAgICAgc3RvcCgiQ2hlY2sgY2hvaWNlIHZhbHVlcyIpDQogICAgfQ0KDQogICAgZHVwbGljYXRlX2Nob2ljZSA8LSBjaG9pY2VfbG9uZyAlPiUNCiAgICAgIGNvdW50KElELCB0YXNrKSAlPiUNCiAgICAgIGZpbHRlcihuICE9IDEpDQoNCiAgICBpZiAobnJvdyhkdXBsaWNhdGVfY2hvaWNlKSA+IDApIHsNCiAgICAgIHByaW50KGR1cGxpY2F0ZV9jaG9pY2UpDQogICAgICBzdG9wKCJDaGVjayBkdXBsaWNhdGUgY2hvaWNlcyIpDQogICAgfQ0KDQogICAgbGV2ZWxfcmVnZXggPC0gIl5GLShbMS01XSktKFsxLTVdKS0oWzEtN10pJCINCiAgICBsZXZlbF9jb2xzIDwtIG5hbWVzKGRhdF9uKVtzdHJfZGV0ZWN0KG5hbWVzKGRhdF9uKSwgbGV2ZWxfcmVnZXgpXQ0KDQogICAgaWYgKGxlbmd0aChsZXZlbF9jb2xzKSA9PSAwKSB7DQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICB9DQoNCiAgICBsZXZlbF9sb25nIDwtIGRhdF9uICU+JQ0KICAgICAgc2VsZWN0KElELCBhbGxfb2YobGV2ZWxfY29scykpICU+JQ0KICAgICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgICBjb2xzID0gYWxsX29mKGxldmVsX2NvbHMpLA0KICAgICAgICBuYW1lc190byA9ICJmdmFyIiwNCiAgICAgICAgdmFsdWVzX3RvID0gImxldmVsIg0KICAgICAgKSAlPiUNCiAgICAgIGV4dHJhY3QoDQogICAgICAgIGZ2YXIsDQogICAgICAgIGludG8gPSBjKCJ0YXNrIiwgInByb2ZpbGUiLCAiYXR0cl9vcmRlciIpLA0KICAgICAgICByZWdleCA9IGxldmVsX3JlZ2V4LA0KICAgICAgICBjb252ZXJ0ID0gVFJVRQ0KICAgICAgKSAlPiUNCiAgICAgIG11dGF0ZShsZXZlbCA9IG5vcm1fdGV4dChsZXZlbCkpICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICB0YXNrICVpbiUgMTo1LA0KICAgICAgICBwcm9maWxlICVpbiUgMTpuX3BhcnR5LA0KICAgICAgICBhdHRyX29yZGVyICVpbiUgMTo3LA0KICAgICAgICAhaXMubmEobGV2ZWwpLA0KICAgICAgICBsZXZlbCAhPSAiIg0KICAgICAgKSAlPiUNCiAgICAgIG11dGF0ZShhdHRyX3ZhciA9IGxldmVsX3RvX2F0dHJfdmFyKGxldmVsKSkNCg0KICAgIHVua25vd25fbGV2ZWxzIDwtIGxldmVsX2xvbmcgJT4lDQogICAgICBmaWx0ZXIoaXMubmEoYXR0cl92YXIpKSAlPiUNCiAgICAgIGRpc3RpbmN0KGxldmVsKQ0KDQogICAgaWYgKG5yb3codW5rbm93bl9sZXZlbHMpID4gMCkgew0KICAgICAgcHJpbnQodW5rbm93bl9sZXZlbHMpDQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICB9DQoNCiAgICBwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCA8LSBsZXZlbF9sb25nICU+JQ0KICAgICAgY291bnQoSUQsIHRhc2ssIHByb2ZpbGUsIG5hbWUgPSAibl9hdHRyaWJ1dGVfcm93cyIpICU+JQ0KICAgICAgZmlsdGVyKG5fYXR0cmlidXRlX3Jvd3MgIT0gNykNCg0KICAgIGlmIChucm93KHByb2ZpbGVfYXR0cmlidXRlX2NvdW50KSA+IDApIHsNCiAgICAgIHByaW50KGhlYWQocHJvZmlsZV9hdHRyaWJ1dGVfY291bnQsIDUwKSkNCiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQ0KICAgIH0NCg0KICAgIGR1cGxpY2F0ZV9hdHRyaWJ1dGUgPC0gbGV2ZWxfbG9uZyAlPiUNCiAgICAgIGNvdW50KElELCB0YXNrLCBwcm9maWxlLCBhdHRyX3ZhcikgJT4lDQogICAgICBmaWx0ZXIobiAhPSAxKQ0KDQogICAgaWYgKG5yb3coZHVwbGljYXRlX2F0dHJpYnV0ZSkgPiAwKSB7DQogICAgICBwcmludChoZWFkKGR1cGxpY2F0ZV9hdHRyaWJ1dGUsIDUwKSkNCiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQ0KICAgIH0NCg0KICAgIHByb2ZpbGVfd2lkZSA8LSBsZXZlbF9sb25nICU+JQ0KICAgICAgaW5uZXJfam9pbihjaG9pY2VfbG9uZywgYnkgPSBjKCJJRCIsICJ0YXNrIikpICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwNCiAgICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHByb2ZpbGUgPT0gY2hvaWNlKSwNCiAgICAgICAgdGFza19pZCA9IHBhc3RlKElELCBwYXJ0eV9uLCB0YXNrLCBzZXAgPSAiXyIpLA0KICAgICAgICBwcm9maWxlX2lkID0gcGFzdGUoSUQsIHBhcnR5X24sIHRhc2ssIHByb2ZpbGUsIHNlcCA9ICJfIikNCiAgICAgICkgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIElELCBwYXJ0eV9uLCB0YXNrLCBwcm9maWxlLCBjaG9pY2UsIHNlbGVjdGVkLA0KICAgICAgICB0YXNrX2lkLCBwcm9maWxlX2lkLCBhdHRyX3ZhciwgbGV2ZWwNCiAgICAgICkgJT4lDQogICAgICBwaXZvdF93aWRlcigNCiAgICAgICAgbmFtZXNfZnJvbSA9IGF0dHJfdmFyLA0KICAgICAgICB2YWx1ZXNfZnJvbSA9IGxldmVsLA0KICAgICAgICB2YWx1ZXNfZm4gPSBsaXN0KGxldmVsID0gfiBmaXJzdCgueCkpDQogICAgICApDQoNCiAgICBtaXNzaW5nX2F0dHIgPC0gc2V0ZGlmZihyZXF1aXJlZF9hdHRyX3ZhcnMsIG5hbWVzKHByb2ZpbGVfd2lkZSkpDQoNCiAgICBpZiAobGVuZ3RoKG1pc3NpbmdfYXR0cikgPiAwKSB7DQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICB9DQoNCiAgICBwcm9maWxlX3dpZGUgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIElELCBwYXJ0eV9uLCB0YXNrLCBwcm9maWxlLCBjaG9pY2UsIHNlbGVjdGVkLA0KICAgICAgICB0YXNrX2lkLCBwcm9maWxlX2lkLA0KICAgICAgICBhbGxfb2YocmVxdWlyZWRfYXR0cl92YXJzKQ0KICAgICAgKSAlPiUNCiAgICAgIGFycmFuZ2UoSUQsIHRhc2ssIHByb2ZpbGUpDQogIH0NCg0KDQogIGNvbmpvaW50XzIgPC0gbWFrZV9wcm9maWxlX2xvbmcoZGYsIDIpDQogIGNvbmpvaW50XzMgPC0gbWFrZV9wcm9maWxlX2xvbmcoZGYsIDMpDQogIGNvbmpvaW50XzQgPC0gbWFrZV9wcm9maWxlX2xvbmcoZGYsIDQpDQogIGNvbmpvaW50XzUgPC0gbWFrZV9wcm9maWxlX2xvbmcoZGYsIDUpDQoNCiAgY29uam9pbnRfYWxsX3VuZmlsdGVyZWQgPC0gYmluZF9yb3dzKA0KICAgIGNvbmpvaW50XzIsDQogICAgY29uam9pbnRfMywNCiAgICBjb25qb2ludF80LA0KICAgIGNvbmpvaW50XzUNCiAgKQ0KDQoNCiAgaWRfdGFza19jaGVjayA8LSBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCAlPiUNCiAgICBncm91cF9ieShJRCwgcGFydHlfbiwgdGFzaykgJT4lDQogICAgc3VtbWFyaXNlKA0KICAgICAgbl9wcm9maWxlcyA9IG4oKSwNCiAgICAgIHNlbGVjdGVkX3N1bSA9IHN1bShzZWxlY3RlZCksDQogICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgKSAlPiUNCiAgICBncm91cF9ieShJRCwgcGFydHlfbikgJT4lDQogICAgc3VtbWFyaXNlKA0KICAgICAgbl90YXNrcyA9IG5fZGlzdGluY3QodGFzayksDQogICAgICBhbGxfdGFza3Nfb2sgPSBhbGwobl9wcm9maWxlcyA9PSBwYXJ0eV9uICYgc2VsZWN0ZWRfc3VtID09IDEpLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICkNCg0KICBpZiAocmVxdWlyZV9hbGxfZml2ZV90YXNrcykgew0KICAgIHZhbGlkX2lkcyA8LSBpZF90YXNrX2NoZWNrICU+JQ0KICAgICAgZmlsdGVyKG5fdGFza3MgPT0gNSwgYWxsX3Rhc2tzX29rKQ0KICB9IGVsc2Ugew0KICAgIHZhbGlkX2lkcyA8LSBpZF90YXNrX2NoZWNrICU+JQ0KICAgICAgZmlsdGVyKGFsbF90YXNrc19vaykNCiAgfQ0KDQogIGNvbmpvaW50X2FsbCA8LSBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCAlPiUNCiAgICBzZW1pX2pvaW4odmFsaWRfaWRzLCBieSA9IGMoIklEIiwgInBhcnR5X24iKSkNCg0KICBuX2J5X3BhcnR5IDwtIHZhbGlkX2lkcyAlPiUNCiAgICBjb3VudChwYXJ0eV9uLCBuYW1lID0gIm4iKSAlPiUNCiAgICBjb21wbGV0ZShwYXJ0eV9uID0gMjo1LCBmaWxsID0gbGlzdChuID0gMCkpICU+JQ0KICAgIGFycmFuZ2UocGFydHlfbikNCg0KICBuX3RvdGFsIDwtIHZhbGlkX2lkcyAlPiUNCiAgICBzdW1tYXJpc2UobiA9IG5fZGlzdGluY3QoSUQpKSAlPiUNCiAgICBwdWxsKG4pDQoNCiAgZmlndXJlX25fbGFiZWxzIDwtIGJpbmRfcm93cygNCiAgICB0aWJibGUoDQogICAgICBwb3NpdGlvbiA9ICLlhajjgrXjg7Pjg5fjg6siLA0KICAgICAgbGFiZWwgPSBwYXN0ZTAoIuWFqOOCteODs+ODl+ODqywgbj0iLCBzY2FsZXM6OmNvbW1hKG5fdG90YWwpKQ0KICAgICksDQogICAgbl9ieV9wYXJ0eSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgcG9zaXRpb24gPSBwYXN0ZTAocGFydHlfbiwgIuaUv+WFmumBuOaKniIpLA0KICAgICAgICBsYWJlbCA9IHBhc3RlMCgibj0iLCBzY2FsZXM6OmNvbW1hKG4pKQ0KICAgICAgKSAlPiUNCiAgICAgIHNlbGVjdChwb3NpdGlvbiwgbGFiZWwpDQogICkNCg0KICBzYW1wbGVfZmxvdyA8LSBiaW5kX3Jvd3MoDQogICAgc2FtcGxlX2Zsb3csDQogICAgdGliYmxlKA0KICAgICAgc3RhZ2UgPSAi5a6M5YWo44GqNeiqsumhjOOCkuOCguOBpOWIhuaekOWvvuixoeiAhSIsDQogICAgICBuID0gbl90b3RhbA0KICAgICkNCiAgKQ0KDQogIGNhdCgiXG7liIbmnpDlr77osaHogIXmlbBcbiIpDQogIHByaW50KG5fYnlfcGFydHkpDQogIGNhdCgi5YWo44K144Oz44OX44OrIG49Iiwgbl90b3RhbCwgIlxuIiwgc2VwID0gIiIpDQoNCiAgd3JpdGVfY3N2X3NhZmVseShzYW1wbGVfZmxvdywgInNhbXBsZV9mbG93LmNzdiIpDQogIHdyaXRlX2Nzdl9zYWZlbHkoaWRfdGFza19jaGVjaywgImlkX3Rhc2tfY2hlY2suY3N2IikNCiAgd3JpdGVfY3N2X3NhZmVseSh2YWxpZF9pZHMsICJ2YWxpZF9pZHMuY3N2IikNCiAgd3JpdGVfY3N2X3NhZmVseShuX2J5X3BhcnR5LCAibl9ieV9wYXJ0eS5jc3YiKQ0KICB3cml0ZV9jc3Zfc2FmZWx5KGZpZ3VyZV9uX2xhYmVscywgImZpZ3VyZV9uX2xhYmVscy5jc3YiKQ0KDQoNCiAgY2hlY2tfcHJvZmlsZSA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgZ3JvdXBfYnkocGFydHlfbiwgSUQsIHRhc2ssIHRhc2tfaWQpICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIG5fcHJvZmlsZXMgPSBuKCksDQogICAgICBzZWxlY3RlZF9zdW0gPSBzdW0oc2VsZWN0ZWQpLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICkgJT4lDQogICAgY291bnQocGFydHlfbiwgbl9wcm9maWxlcywgc2VsZWN0ZWRfc3VtKQ0KDQogIHByaW50KGNoZWNrX3Byb2ZpbGUpDQogIHN0b3BpZm5vdChhbGwoY2hlY2tfcHJvZmlsZSRuX3Byb2ZpbGVzID09IGNoZWNrX3Byb2ZpbGUkcGFydHlfbikpDQogIHN0b3BpZm5vdChhbGwoY2hlY2tfcHJvZmlsZSRzZWxlY3RlZF9zdW0gPT0gMSkpDQoNCiAgYWxsb3dlZF9kZiA8LSBlbmZyYW1lKGFsbG93ZWRfbGV2ZWxzLCBuYW1lID0gIm5hbWUiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JQ0KICAgIHVubmVzdCh2YWx1ZSkNCg0KICB1bmV4cGVjdGVkX3ZhbHVlcyA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgc2VsZWN0KGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpKSAlPiUNCiAgICBwaXZvdF9sb25nZXIoDQogICAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgICAgbmFtZXNfdG8gPSAibmFtZSIsDQogICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiDQogICAgKSAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKHZhbHVlKSwgdmFsdWUgIT0gIiIpICU+JQ0KICAgIGRpc3RpbmN0KG5hbWUsIHZhbHVlKSAlPiUNCiAgICBhbnRpX2pvaW4oYWxsb3dlZF9kZiwgYnkgPSBjKCJuYW1lIiwgInZhbHVlIikpDQoNCiAgcHJpbnQodW5leHBlY3RlZF92YWx1ZXMpDQogIHN0b3BpZm5vdChucm93KHVuZXhwZWN0ZWRfdmFsdWVzKSA9PSAwKQ0KDQogIG9ic2VydmVkX2xldmVscyA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgc2VsZWN0KGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpKSAlPiUNCiAgICBwaXZvdF9sb25nZXIoDQogICAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwNCiAgICAgIHZhbHVlc190byA9ICJsZXZlbCINCiAgICApICU+JQ0KICAgIGRpc3RpbmN0KGF0dHJpYnV0ZSwgbGV2ZWwpICU+JQ0KICAgIGFycmFuZ2UoYXR0cmlidXRlLCBsZXZlbCkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KGNoZWNrX3Byb2ZpbGUsICJwcm9maWxlX2V4cGFuc2lvbl9jaGVjay5jc3YiKQ0KICB3cml0ZV9jc3Zfc2FmZWx5KG9ic2VydmVkX2xldmVscywgIm9ic2VydmVkX2F0dHJpYnV0ZV9sZXZlbHMuY3N2IikNCiAgd3JpdGVfY3N2X3NhZmVseShjb25qb2ludF9hbGwsICJzdHVkeTFfcHJvZmlsZV9sZXZlbF9kYXRhLmNzdiIpDQoNCg0KICBpZiAocmVxdWlyZV9hdHRlbnRpb25fY2hlY2spIHsNCiAgICBpZiAoDQogICAgICBpcy5uYShhdHRlbnRpb25fY2hlY2tfdmFyKSB8fA0KICAgICAgICAhYXR0ZW50aW9uX2NoZWNrX3ZhciAlaW4lIG5hbWVzKGRmKSB8fA0KICAgICAgICBpcy5uYShhdHRlbnRpb25fY2hlY2tfY29ycmVjdCkNCiAgICApIHsNCiAgICAgIHN0b3AoIkNoZWNrIGF0dGVudGlvbiBpdGVtIikNCiAgICB9DQogIH0NCg0KICBhdHRlbnRpb25fc3VtbWFyeSA8LSB0aWJibGUoDQogICAgbm90ZSA9ICIyMDIz5bm05YWD44Kz44O844OJ44Gn44Gv5rOo5oSP44OB44Kn44OD44Kv44Gu56K65a6a5a++5b+c6KGo44KS5L2/55So44GX44Gm44GE44Gq44GE44Gf44KB44CB5qiZ5rqW5YiG5p6Q44Gn44Gv6ZuG6KiI44KS55yB55Wl44CCIg0KICApDQoNCiAgbWFuaXB1bGF0aW9uX3N1bW1hcnkgPC0gdGliYmxlKA0KICAgIG5vdGUgPSAiMjAyM+W5tOWFg+OCs+ODvOODieOBp+OBr+aUv+WFmuaVsOeiuuiqjeizquWVj+OBrueiuuWumuWvvuW/nOihqOOCkuS9v+eUqOOBl+OBpuOBhOOBquOBhOOBn+OCgeOAgeaomea6luWIhuaekOOBp+OBr+mbhuioiOOCkuecgeeVpeOAgiINCiAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoYXR0ZW50aW9uX3N1bW1hcnksICJhdHRlbnRpb25fY2hlY2tfc3VtbWFyeS5jc3YiKQ0KICB3cml0ZV9jc3Zfc2FmZWx5KG1hbmlwdWxhdGlvbl9zdW1tYXJ5LCAicGFydHlfbnVtYmVyX2NoZWNrX3N1bW1hcnkuY3N2IikNCg0KDQogIGNvbmpvaW50X2FsbF9tIDwtIGNvbmpvaW50X2FsbCAlPiUNCiAgICBtdXRhdGUoDQogICAgICBzZWxlY3RlZCA9IGFzLmludGVnZXIoc2VsZWN0ZWQpLA0KICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLA0KDQogICAgICBwb2xpY3lfcG9zaXRpb24gPSBmYWN0b3IoDQogICAgICAgIHBvbGljeV9wb3NpdGlvbiwNCiAgICAgICAgbGV2ZWxzID0gYygi5Lit6YGTIiwgIuWPs+a0vuODu+S/neWuiOeahCIsICLlt6bmtL7jg7vpnanmlrDnmoQiKQ0KICAgICAgKSwNCg0KICAgICAgZ292ZXJubWVudF9zdGF0dXMgPSBmYWN0b3IoDQogICAgICAgIGdvdmVybm1lbnRfc3RhdHVzLA0KICAgICAgICBsZXZlbHMgPSBjKCLph47lhZoiLCAi5LiO5YWaIikNCiAgICAgICksDQoNCiAgICAgIGdkcF9ncm93dGggPSBmYWN0b3IoDQogICAgICAgIGdkcF9ncm93dGgsDQogICAgICAgIGxldmVscyA9IGMoDQogICAgICAgICAgIkdEUOaIkOmVt+eOh8KxMO+8hSIsDQogICAgICAgICAgIkdEUOaIkOmVt+eOh+ODl+ODqeOCuTHvvIUiLA0KICAgICAgICAgICJHRFDmiJDplbfnjofjg57jgqTjg4rjgrkx77yFIg0KICAgICAgICApDQogICAgICApLA0KDQogICAgICBuaWtrZWkgPSBmYWN0b3IoDQogICAgICAgIG5pa2tlaSwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIiwNCiAgICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U44OX44Op44K5MTAwMOWGhiIsDQogICAgICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODnuOCpOODiuOCuTEwMDDlhoYiDQogICAgICAgICkNCiAgICAgICksDQoNCiAgICAgIHNlYXRzID0gZmFjdG9yKA0KICAgICAgICBzZWF0cywNCiAgICAgICAgbGV2ZWxzID0gYygiMTDku6XkuIsiLCAiMTB+NDkiLCAiNTB+OTkiLCAiMTAwfjE5OSIsICIyMDDku6XkuIoiKQ0KICAgICAgKSwNCg0KICAgICAgY3BpID0gZmFjdG9yKA0KICAgICAgICBjcGksDQogICAgICAgIGxldmVscyA9IGMoDQogICAgICAgICAgIkNQSeWJjeacn+avlMKxMOODneOCpOODs+ODiCIsDQogICAgICAgICAgIkNQSeWJjeacn+avlOODl+ODqeOCuTHjg53jgqTjg7Pjg4giLA0KICAgICAgICAgICJDUEnliY3mnJ/mr5Tjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIg0KICAgICAgICApDQogICAgICApLA0KDQogICAgICB1bmVtcGxveW1lbnQgPSBmYWN0b3IoDQogICAgICAgIHVuZW1wbG95bWVudCwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+UwrEw77yFIiwNCiAgICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+U44OX44Op44K5Me+8hSIsDQogICAgICAgICAgIuWksealreeOh+WJjeacn+avlOODnuOCpOODiuOCuTHvvIUiDQogICAgICAgICkNCiAgICAgICksDQoNCiAgICAgIHBhcnR5X25fZiA9IGZhY3RvcigNCiAgICAgICAgYXMuY2hhcmFjdGVyKHBhcnR5X24pLA0KICAgICAgICBsZXZlbHMgPSBjKCIyIiwgIjMiLCAiNCIsICI1IikNCiAgICAgICkNCiAgICApDQoNCiAgYXR0cl90ZXJtcyA8LSBjKA0KICAgICJwb2xpY3lfcG9zaXRpb24iLA0KICAgICJnb3Zlcm5tZW50X3N0YXR1cyIsDQogICAgImdkcF9ncm93dGgiLA0KICAgICJuaWtrZWkiLA0KICAgICJzZWF0cyIsDQogICAgImNwaSIsDQogICAgInVuZW1wbG95bWVudCINCiAgKQ0KDQoNCiAgZm9ybXVsYV9ub2NvdiA8LSBhcy5mb3JtdWxhKA0KICAgIHBhc3RlKCJzZWxlY3RlZCB+IiwgcGFzdGUoYXR0cl90ZXJtcywgY29sbGFwc2UgPSAiICsgIikpDQogICkNCg0KICBydW5fYW1jZV9ub2NvdiA8LSBmdW5jdGlvbihkYXQpIHsNCiAgICBmZW9scygNCiAgICAgIGZvcm11bGFfbm9jb3YsDQogICAgICBkYXRhID0gZGF0LA0KICAgICAgdmNvdiA9IH4gSUQNCiAgICApDQogIH0NCg0KICBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiA8LSBjb25qb2ludF9hbGxfbSAlPiUNCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQ0KICAgIG1hcChydW5fYW1jZV9ub2NvdikNCg0KICBjYXB0dXJlLm91dHB1dCgNCiAgICBldGFibGUobW9kZWxzX2J5X3BhcnR5X25fbm9jb3YpLA0KICAgIGZpbGUgPSBmaWxlLnBhdGgob3V0cHV0X2RpciwgImFtY2Vfbm9jb3ZfbW9kZWxzLnR4dCIpDQogICkNCg0KDQogIG1faW50ZXJhY3Rpb24gPC0gZmVvbHMoDQogICAgc2VsZWN0ZWQgfg0KICAgICAgcGFydHlfbl9mICoNCiAgICAgICgNCiAgICAgICAgcG9saWN5X3Bvc2l0aW9uICsNCiAgICAgICAgICBnb3Zlcm5tZW50X3N0YXR1cyArDQogICAgICAgICAgZ2RwX2dyb3d0aCArDQogICAgICAgICAgbmlra2VpICsNCiAgICAgICAgICBzZWF0cyArDQogICAgICAgICAgY3BpICsNCiAgICAgICAgICB1bmVtcGxveW1lbnQNCiAgICAgICksDQogICAgZGF0YSA9IGNvbmpvaW50X2FsbF9tLA0KICAgIHZjb3YgPSB+IElEDQogICkNCg0KICBjYXB0dXJlLm91dHB1dCgNCiAgICBzdW1tYXJ5KG1faW50ZXJhY3Rpb24pLA0KICAgIGZpbGUgPSBmaWxlLnBhdGgob3V0cHV0X2RpciwgImFtY2VfaW50ZXJhY3Rpb25fbW9kZWwudHh0IikNCiAgKQ0KDQoNCiAgdGlkeV9maXhlc3QgPC0gZnVuY3Rpb24obW9kZWwpIHsNCiAgICBjdCA8LSBhcy5kYXRhLmZyYW1lKGZpeGVzdDo6Y29lZnRhYmxlKG1vZGVsKSkNCiAgICBjdCR0ZXJtIDwtIHJvd25hbWVzKGN0KQ0KDQogICAgY3QgJT4lDQogICAgICBhc190aWJibGUoKSAlPiUNCiAgICAgIHJlbmFtZSgNCiAgICAgICAgZXN0aW1hdGUgPSBFc3RpbWF0ZSwNCiAgICAgICAgc3RkLmVycm9yID0gYFN0ZC4gRXJyb3JgLA0KICAgICAgICBzdGF0aXN0aWMgPSBgdCB2YWx1ZWAsDQogICAgICAgIHAudmFsdWUgPSBgUHIoPnx0fClgDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBjb25mLmxvdyA9IGVzdGltYXRlIC0gMS45NiAqIHN0ZC5lcnJvciwNCiAgICAgICAgY29uZi5oaWdoID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yDQogICAgICApICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICB0ZXJtLCBlc3RpbWF0ZSwgc3RkLmVycm9yLCBzdGF0aXN0aWMsIHAudmFsdWUsDQogICAgICAgIGNvbmYubG93LCBjb25mLmhpZ2gNCiAgICAgICkNCiAgfQ0KDQogIHRlcm1fbGFiZWxzIDwtIHRyaWJibGUoDQogICAgfnRlcm0sIH5hdHRyaWJ1dGUsIH5jdWVfdHlwZSwgfmxhYmVsLCB+b3JkZXIsDQoNCiAgICAiZ292ZXJubWVudF9zdGF0dXPkuI7lhZoiLA0KICAgICLkuI7lhZrvvI/ph47lhZoiLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuS4juWFmiIsIDEsDQoNCiAgICAicG9saWN5X3Bvc2l0aW9u5Y+z5rS+44O75L+d5a6I55qEIiwNCiAgICAi5pS/562W5L2N572uIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLlj7PmtL7jg7vkv53lrojnmoQiLCAyLA0KDQogICAgInBvbGljeV9wb3NpdGlvbuW3pua0vuODu+mdqeaWsOeahCIsDQogICAgIuaUv+etluS9jee9riIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi5bem5rS+44O76Z2p5paw55qEIiwgMywNCg0KICAgICJzZWF0czEwfjQ5IiwNCiAgICAi6K2w5bit5pWwIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLorbDluK3mlbDvvJoxMO+9njQ5IiwgNCwNCg0KICAgICJzZWF0czUwfjk5IiwNCiAgICAi6K2w5bit5pWwIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLorbDluK3mlbDvvJo1MO+9njk5IiwgNSwNCg0KICAgICJzZWF0czEwMH4xOTkiLA0KICAgICLorbDluK3mlbAiLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuitsOW4reaVsO+8mjEwMO+9njE5OSIsIDYsDQoNCiAgICAic2VhdHMyMDDku6XkuIoiLA0KICAgICLorbDluK3mlbAiLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuitsOW4reaVsO+8mjIwMOS7peS4iiIsIDcsDQoNCiAgICAiZ2RwX2dyb3d0aEdEUOaIkOmVt+eOh+ODl+ODqeOCuTHvvIUiLA0KICAgICJHRFDmiJDplbfnjociLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIkdEUO+8muODl+ODqeOCuTHvvIUiLCA4LA0KDQogICAgImdkcF9ncm93dGhHRFDmiJDplbfnjofjg57jgqTjg4rjgrkx77yFIiwNCiAgICAiR0RQ5oiQ6ZW3546HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICJHRFDvvJrjg57jgqTjg4rjgrkx77yFIiwgOSwNCg0KICAgICJuaWtrZWnml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwNCiAgICAi5pel57WM5bmz5Z2HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICLml6XntYzlubPlnYfvvJrjg5fjg6njgrkxMDAw5YaGIiwgMTAsDQoNCiAgICAibmlra2Vp5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U44Oe44Kk44OK44K5MTAwMOWGhiIsDQogICAgIuaXpee1jOW5s+WdhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAi5pel57WM5bmz5Z2H77ya44Oe44Kk44OK44K5MTAwMOWGhiIsIDExLA0KDQogICAgImNwaUNQSeWJjeacn+avlOODl+ODqeOCuTHjg53jgqTjg7Pjg4giLA0KICAgICJDUEkiLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIkNQSe+8muODl+ODqeOCuTHjg53jgqTjg7Pjg4giLCAxMiwNCg0KICAgICJjcGlDUEnliY3mnJ/mr5Tjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIiwNCiAgICAiQ1BJIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICJDUEnvvJrjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIiwgMTMsDQoNCiAgICAidW5lbXBsb3ltZW505aSx5qWt546H5YmN5pyf5q+U44OX44Op44K5Me+8hSIsDQogICAgIuWksealreeOhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAi5aSx5qWt546H77ya44OX44Op44K5Me+8hSIsIDE0LA0KDQogICAgInVuZW1wbG95bWVudOWksealreeOh+WJjeacn+avlOODnuOCpOODiuOCuTHvvIUiLA0KICAgICLlpLHmpa3njociLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIuWksealreeOh++8muODnuOCpOODiuOCuTHvvIUiLCAxNQ0KICApDQoNCiAgYXR0cmlidXRlX29yZGVyIDwtIGMoDQogICAgIuS4juWFmu+8j+mHjuWFmiIsDQogICAgIuaUv+etluS9jee9riIsDQogICAgIuitsOW4reaVsCIsDQogICAgIkdEUOaIkOmVt+eOhyIsDQogICAgIuaXpee1jOW5s+WdhyIsDQogICAgIkNQSSIsDQogICAgIuWksealreeOhyINCiAgKQ0KDQogIGxhYmVsX29yZGVyIDwtIHRlcm1fbGFiZWxzICU+JQ0KICAgIGFycmFuZ2Uob3JkZXIpICU+JQ0KICAgIHB1bGwobGFiZWwpDQoNCiAgbWFrZV9hbWNlX3Bsb3RfZGYgPC0gZnVuY3Rpb24obW9kZWxzKSB7DQogICAgaW1hcF9kZnIoDQogICAgICBtb2RlbHMsDQogICAgICB+IHRpZHlfZml4ZXN0KC54KSAlPiUNCiAgICAgICAgbXV0YXRlKHBhcnR5X24gPSBhcy5jaGFyYWN0ZXIoLnkpKQ0KICAgICkgJT4lDQogICAgICBsZWZ0X2pvaW4odGVybV9sYWJlbHMsIGJ5ID0gInRlcm0iKSAlPiUNCiAgICAgIGZpbHRlcighaXMubmEoYXR0cmlidXRlKSkgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsDQogICAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsDQogICAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwNCiAgICAgICAgcGFydHlfbiA9IGZhY3RvcigNCiAgICAgICAgICBwYXJ0eV9uLA0KICAgICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKSwNCiAgICAgICAgICBsYWJlbHMgPSBjKCIy5pS/5YWaIiwgIjPmlL/lhZoiLCAiNOaUv+WFmiIsICI15pS/5YWaIikNCiAgICAgICAgKSwNCiAgICAgICAgYXR0cmlidXRlID0gZmFjdG9yKGF0dHJpYnV0ZSwgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyKSwNCiAgICAgICAgbGFiZWwgPSBmYWN0b3IobGFiZWwsIGxldmVscyA9IHJldihsYWJlbF9vcmRlcikpDQogICAgICApDQogIH0NCg0KICBhbWNlX3Bsb3Rfbm9jb3YgPC0gbWFrZV9hbWNlX3Bsb3RfZGYobW9kZWxzX2J5X3BhcnR5X25fbm9jb3YpDQogIHdyaXRlX2Nzdl9zYWZlbHkoYW1jZV9wbG90X25vY292LCAiYW1jZV9ub2Nvdl9jb2VmZmljaWVudHMuY3N2IikNCg0KICBpbnRlcmFjdGlvbl9wbG90X2RmIDwtIHRpZHlfZml4ZXN0KG1faW50ZXJhY3Rpb24pICU+JQ0KICAgIGZpbHRlcihzdHJfZGV0ZWN0KHRlcm0sICJwYXJ0eV9uX2ZbMzQ1XSIpKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBwYXJ0eV9uX2NvZGUgPSBzdHJfZXh0cmFjdCh0ZXJtLCAicGFydHlfbl9mWzM0NV0iKSwNCiAgICAgIHBhcnR5X24gPSBzdHJfcmVtb3ZlKHBhcnR5X25fY29kZSwgInBhcnR5X25fZiIpLA0KICAgICAgYmFzZV90ZXJtID0gdGVybSAlPiUNCiAgICAgICAgc3RyX3JlbW92ZSgicGFydHlfbl9mWzM0NV06IikgJT4lDQogICAgICAgIHN0cl9yZW1vdmUoIjpwYXJ0eV9uX2ZbMzQ1XSIpDQogICAgKSAlPiUNCiAgICBsZWZ0X2pvaW4odGVybV9sYWJlbHMsIGJ5ID0gYygiYmFzZV90ZXJtIiA9ICJ0ZXJtIikpICU+JQ0KICAgIGZpbHRlcighaXMubmEoYXR0cmlidXRlKSkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsDQogICAgICBjb25mLmhpZ2hfcHAgPSBjb25mLmhpZ2ggKiAxMDAsDQogICAgICBwYXJ0eV9uX2xhYmVsID0gZmFjdG9yKA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBsZXZlbHMgPSBjKCIzIiwgIjQiLCAiNSIpLA0KICAgICAgICBsYWJlbHMgPSBjKCIz5pS/5YWaIiwgIjTmlL/lhZoiLCAiNeaUv+WFmiIpDQogICAgICApLA0KICAgICAgYXR0cmlidXRlID0gZmFjdG9yKGF0dHJpYnV0ZSwgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyKSwNCiAgICAgIGxhYmVsID0gZmFjdG9yKGxhYmVsLCBsZXZlbHMgPSByZXYobGFiZWxfb3JkZXIpKQ0KICAgICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KGludGVyYWN0aW9uX3Bsb3RfZGYsICJhbWNlX2ludGVyYWN0aW9uX2NvZWZmaWNpZW50cy5jc3YiKQ0KDQoNCiAgcmVjb2RlX2ZlbWFsZV9zdHVkeTEgPC0gZnVuY3Rpb24oeCkgew0KICAgIHhfY2hyIDwtIG5vcm1fdGV4dCh4KQ0KICAgIHhfbnVtIDwtIGFzX251bSh4X2NocikNCg0KICAgIGNhc2Vfd2hlbigNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLlpbPmgKciKSB8IHhfbnVtID09IDEgfiAxTCwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLnlLfmgKciKSB8IHhfbnVtID09IDIgfiAwTCwNCiAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXw0KICAgICkNCiAgfQ0KDQogIHJlY29kZV9jb2xsZWdlX2dyYWRfc3R1ZHkxIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4X2NociA8LSBub3JtX3RleHQoeCkNCiAgICB4X251bSA8LSBhc19udW0oeF9jaHIpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAiNOW5tOWItuWkp+WtpnzvvJTlubTliLblpKflraZ85aSn5a2m6ZmiIikgfA0KICAgICAgICB4X251bSAlaW4lIGMoNCwgNSkgfiAxTCwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLlsI/lrabmoKF86auY5qChfOmrmOetieWwgumWgHznn63mnJ/lpKflraZ85bCC5L+u5a2m5qChIikgfA0KICAgICAgICB4X251bSAlaW4lIGMoMSwgMiwgMykgfiAwTCwNCiAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXw0KICAgICkNCiAgfQ0KDQogIHJlY29kZV9wYXJ0eV9zdXBwb3J0X3N0dWR5MSA8LSBmdW5jdGlvbih4KSB7DQogICAgeF9jaHIgPC0gbm9ybV90ZXh0KHgpDQogICAgeF9udW0gPC0gYXNfbnVtKHhfY2hyKQ0KDQogICAgY2FzZV93aGVuKA0KICAgICAgc3RyX2RldGVjdCh4X2NociwgIuiHqueUseawkeS4u3zoh6rmsJEiKSB8IHhfbnVtID09IDEgfiAi6Ieq55Sx5rCR5Li75YWaIiwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLnq4vmhrLmsJHkuLsiKSB8IHhfbnVtID09IDIgfiAi56uL5oay5rCR5Li75YWaIiwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLlhazmmI4iKSB8IHhfbnVtID09IDMgfiAi5YWs5piO5YWaIiwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLntq3mlrAiKSB8IHhfbnVtID09IDQgfiAi5pel5pys57at5paw44Gu5LyaIiwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLlhbHnlKMiKSB8IHhfbnVtID09IDUgfiAi5pel5pys5YWx55Sj5YWaIiwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLlm73msJHmsJHkuLsiKSB8IHhfbnVtID09IDYgfiAi5Zu95rCR5rCR5Li75YWaIiwNCiAgICAgIHN0cl9kZXRlY3QoeF9jaHIsICLnpL7kvJrmsJHkuLt856S+5rCRIikgfCB4X251bSA9PSA3IH4gIuekvuS8muawkeS4u+WFmiIsDQogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi44KM44GE44KPIikgfCB4X251bSA9PSA4IH4gIuOCjOOBhOOCj+aWsOmBuOe1hCIsDQogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi44Gd44Gu5LuWIikgfCB4X251bSA9PSAxMSB+ICLjgZ3jga7ku5YiLA0KICAgICAgc3RyX2RldGVjdCh4X2NociwgIuaUr+aMgeOBmeOCi+aUv+WFmuOBr+OBquOBhHzmlK/mjIHmlL/lhZrjgarjgZciKSB8DQogICAgICAgIHhfbnVtID09IDEyIH4gIuaUr+aMgeaUv+WFmuOBquOBlyIsDQogICAgICBzdHJfZGV0ZWN0KHhfY2hyLCAi44KP44GL44KJ44Gq44GEIikgfCB4X251bSA9PSAxMyB+ICLjgo/jgYvjgonjgarjgYQiLA0KICAgICAgc3RyX2RldGVjdCh4X2NociwgIuetlOOBiOOBquOBhHzjgZPjgZ/jgYjjgarjgYQiKSB8IHhfbnVtID09IDE0IH4gIuetlOOBiOOBquOBhCIsDQogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICAgICkNCiAgfQ0KDQogIGdlbmRlcl9yYXcgPC0gZ2V0X3ZhcigNCiAgICBkZiwNCiAgICBjKCJRMi4xIiwgIlEyXzEiLCAiUTIuMS4iLCAi5oCn5YilIiwgImdlbmRlciIsICJHZW5kZXIiKQ0KICApDQoNCiAgYWdlX3JhdyA8LSBnZXRfdmFyKA0KICAgIGRmLA0KICAgIGMoIlEyLjIiLCAiUTJfMiIsICJRMi4yLiIsICLlubTpvaIiLCAiYWdlIiwgIkFnZSIpDQogICkNCg0KICBlZHVjYXRpb25fcmF3IDwtIGdldF92YXIoDQogICAgZGYsDQogICAgYygNCiAgICAgICJRMi4zIiwgIlEyXzMiLCAiUTIuMy4iLA0KICAgICAgIuWtpuattCIsICLmlZnogrLmrbQiLCAi5pyA57WC5a2m5q20IiwgImVkdWNhdGlvbiIsICJFZHVjYXRpb24iDQogICAgKQ0KICApDQoNCiAgcGFydHlfc3VwcG9ydF9yYXcgPC0gZ2V0X3ZhcigNCiAgICBkZiwNCiAgICBjKCJRMi40IiwgIlEyXzQiLCAiUTIuNC4iLCAi5pS/5YWa5pSv5oyBIiwgIuaUr+aMgeaUv+WFmiIsICJwYXJ0eV9zdXBwb3J0IikNCiAgKQ0KDQogIGluY29tZV9ncm9zc19yYXcgPC0gZ2V0X3ZhcigNCiAgICBkZiwNCiAgICBjKCJRMy4xXzEiLCAiUTMuMS4xIiwgIlEzXzFfMSIsICLnqI7lvJXjgY3liY3kuJbluK/lubTlj44iLCAiaW5jb21lX2dyb3NzIikNCiAgKQ0KDQogIGluY29tZV9uZXRfcmF3IDwtIGdldF92YXIoDQogICAgZGYsDQogICAgYygiUTMuMV8yIiwgIlEzLjEuMiIsICJRM18xXzIiLCAi5omL5Y+W44KK44Gu5bm05Y+OIiwgImluY29tZV9uZXQiKQ0KICApDQoNCiAgY292YXJfaWQgPC0gZGYgJT4lDQogICAgdHJhbnNtdXRlKA0KICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoUmVzcG9uc2VJZCksDQogICAgICBmZW1hbGUgPSByZWNvZGVfZmVtYWxlX3N0dWR5MShnZW5kZXJfcmF3KSwNCiAgICAgIGFnZV9yYXdfbnVtID0gYXNfbnVtKGFnZV9yYXcpLA0KICAgICAgY29sbGVnZV9ncmFkID0gcmVjb2RlX2NvbGxlZ2VfZ3JhZF9zdHVkeTEoZWR1Y2F0aW9uX3JhdyksDQogICAgICBwYXJ0eV9zdXBwb3J0ID0gcmVjb2RlX3BhcnR5X3N1cHBvcnRfc3R1ZHkxKHBhcnR5X3N1cHBvcnRfcmF3KSwNCiAgICAgIHBhcnR5X3N1cHBvcnRfZiA9IGZhY3Rvcl9taXNzKHBhcnR5X3N1cHBvcnQpLA0KICAgICAgaW5jb21lX2dyb3NzID0gYXNfbnVtKGluY29tZV9ncm9zc19yYXcpLA0KICAgICAgaW5jb21lX25ldCA9IGFzX251bShpbmNvbWVfbmV0X3JhdyksDQogICAgICBpbmNvbWVfZ3Jvc3NfbG9nID0gbG9nMXAoaW5jb21lX2dyb3NzKSwNCiAgICAgIGluY29tZV9uZXRfbG9nID0gbG9nMXAoaW5jb21lX25ldCkNCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIGFnZSA9IGNhc2Vfd2hlbigNCiAgICAgICAgIWlzLm5hKGFnZV9yYXdfbnVtKSAmIGFnZV9yYXdfbnVtID49IDE4ICYgYWdlX3Jhd19udW0gPD0gODAgfg0KICAgICAgICAgIGFnZV9yYXdfbnVtLA0KICAgICAgICAhaXMubmEoYWdlX3Jhd19udW0pICYgYWdlX3Jhd19udW0gPj0gMSAmIGFnZV9yYXdfbnVtIDw9IDYzIH4NCiAgICAgICAgICBhZ2VfcmF3X251bSArIDE3LA0KICAgICAgICBUUlVFIH4gTkFfcmVhbF8NCiAgICAgICkNCiAgICApICU+JQ0KICAgIHNlbWlfam9pbih2YWxpZF9pZHMgJT4lIHNlbGVjdChJRCksIGJ5ID0gIklEIikgJT4lDQogICAgZGlzdGluY3QoSUQsIC5rZWVwX2FsbCA9IFRSVUUpDQoNCiAgYWdlX2ltcF9vYmogPC0gbWVhbl9pbXB1dGUoY292YXJfaWQkYWdlKQ0KICBpbmNvbWVfZ3Jvc3NfaW1wX29iaiA8LSBtZWFuX2ltcHV0ZShjb3Zhcl9pZCRpbmNvbWVfZ3Jvc3NfbG9nKQ0KDQogIGNvdmFyX2lkIDwtIGNvdmFyX2lkICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIGZlbWFsZV9pbXAgPSBpZl9lbHNlKGlzLm5hKGZlbWFsZSksIDBMLCBmZW1hbGUpLA0KICAgICAgZmVtYWxlX21pc3MgPSBhcy5pbnRlZ2VyKGlzLm5hKGZlbWFsZSkpLA0KDQogICAgICBjb2xsZWdlX2dyYWRfaW1wID0gaWZfZWxzZShpcy5uYShjb2xsZWdlX2dyYWQpLCAwTCwgY29sbGVnZV9ncmFkKSwNCiAgICAgIGNvbGxlZ2VfZ3JhZF9taXNzID0gYXMuaW50ZWdlcihpcy5uYShjb2xsZWdlX2dyYWQpKSwNCg0KICAgICAgYWdlX2ltcCA9IGFnZV9pbXBfb2JqJHZhbHVlLA0KICAgICAgYWdlX21pc3MgPSBhZ2VfaW1wX29iaiRtaXNzLA0KDQogICAgICBpbmNvbWVfZ3Jvc3NfbG9nX2ltcCA9IGluY29tZV9ncm9zc19pbXBfb2JqJHZhbHVlLA0KICAgICAgaW5jb21lX2dyb3NzX2xvZ19taXNzID0gaW5jb21lX2dyb3NzX2ltcF9vYmokbWlzcw0KICAgICkNCg0KICBjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5IDwtIGNvdmFyX2lkICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIG5faWRzID0gbl9kaXN0aW5jdChJRCksDQogICAgICBmZW1hbGVfbWlzc2luZyA9IHN1bShpcy5uYShmZW1hbGUpKSwNCiAgICAgIGFnZV9taXNzaW5nID0gc3VtKGlzLm5hKGFnZSkpLA0KICAgICAgY29sbGVnZV9ncmFkX21pc3NpbmcgPSBzdW0oaXMubmEoY29sbGVnZV9ncmFkKSksDQogICAgICBpbmNvbWVfZ3Jvc3NfbWlzc2luZyA9IHN1bShpcy5uYShpbmNvbWVfZ3Jvc3NfbG9nKSksDQogICAgICBwYXJ0eV9zdXBwb3J0X21pc3NpbmcgPSBzdW0oaXMubmEocGFydHlfc3VwcG9ydCkpDQogICAgKQ0KDQogIHByaW50KGNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnkpDQogIHdyaXRlX2Nzdl9zYWZlbHkoY292YXJfaWQsICJyZXNwb25kZW50X2NvdmFyaWF0ZXMuY3N2IikNCiAgd3JpdGVfY3N2X3NhZmVseShjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5LCAiY292YXJpYXRlX21pc3Npbmdfc3VtbWFyeS5jc3YiKQ0KDQoNCiAgY29uam9pbnRfYWxsX2NvdiA8LSBjb25qb2ludF9hbGxfbSAlPiUNCiAgICBsZWZ0X2pvaW4oY292YXJfaWQsIGJ5ID0gIklEIikNCg0KICBjb3ZhcmlhdGVfdGVybXMgPC0gYygNCiAgICAiZmVtYWxlX2ltcCIsDQogICAgImZlbWFsZV9taXNzIiwNCiAgICAiYWdlX2ltcCIsDQogICAgImFnZV9taXNzIiwNCiAgICAiaW5jb21lX2dyb3NzX2xvZ19pbXAiLA0KICAgICJpbmNvbWVfZ3Jvc3NfbG9nX21pc3MiLA0KICAgICJwYXJ0eV9zdXBwb3J0X2YiDQogICkNCg0KICBpZiAodXNlX2VkdWNhdGlvbl9jb3ZhcmlhdGUpIHsNCiAgICBjb3ZhcmlhdGVfdGVybXMgPC0gYygNCiAgICAgIGNvdmFyaWF0ZV90ZXJtcywNCiAgICAgICJjb2xsZWdlX2dyYWRfaW1wIiwNCiAgICAgICJjb2xsZWdlX2dyYWRfbWlzcyINCiAgICApDQogIH0NCg0KICBoYXNfdmFyaWF0aW9uIDwtIGZ1bmN0aW9uKGRhdCwgdikgew0KICAgIGlmICghdiAlaW4lIG5hbWVzKGRhdCkpIHJldHVybihGQUxTRSkNCiAgICBkcGx5cjo6bl9kaXN0aW5jdChkYXRbW3ZdXSwgbmEucm0gPSBUUlVFKSA+IDENCiAgfQ0KDQogIGNvdmFyaWF0ZV90ZXJtc191c2UgPC0gY292YXJpYXRlX3Rlcm1zWw0KICAgIG1hcF9sZ2woY292YXJpYXRlX3Rlcm1zLCB+IGhhc192YXJpYXRpb24oY29uam9pbnRfYWxsX2NvdiwgLngpKQ0KICBdDQoNCiAgZm9ybXVsYV9jb3YgPC0gYXMuZm9ybXVsYSgNCiAgICBwYXN0ZSgNCiAgICAgICJzZWxlY3RlZCB+IiwNCiAgICAgIHBhc3RlKGMoYXR0cl90ZXJtcywgY292YXJpYXRlX3Rlcm1zX3VzZSksIGNvbGxhcHNlID0gIiArICIpDQogICAgKQ0KICApDQoNCiAgcnVuX2FtY2VfY292IDwtIGZ1bmN0aW9uKGRhdCkgew0KICAgIGZlb2xzKA0KICAgICAgZm9ybXVsYV9jb3YsDQogICAgICBkYXRhID0gZGF0LA0KICAgICAgdmNvdiA9IH4gSUQNCiAgICApDQogIH0NCg0KICBtb2RlbHNfYnlfcGFydHlfbl9jb3YgPC0gY29uam9pbnRfYWxsX2NvdiAlPiUNCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQ0KICAgIG1hcChydW5fYW1jZV9jb3YpDQoNCiAgY2FwdHVyZS5vdXRwdXQoDQogICAgZXRhYmxlKA0KICAgICAgbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YsDQogICAgICBtb2RlbHNfYnlfcGFydHlfbl9jb3YsDQogICAgICBoZWFkZXJzID0gYygNCiAgICAgICAgcmVwKCLlhbHlpInph4/jgarjgZciLCBsZW5ndGgobW9kZWxzX2J5X3BhcnR5X25fbm9jb3YpKSwNCiAgICAgICAgcmVwKCLlhbHlpInph4/jgYLjgooiLCBsZW5ndGgobW9kZWxzX2J5X3BhcnR5X25fY292KSkNCiAgICAgICkNCiAgICApLA0KICAgIGZpbGUgPSBmaWxlLnBhdGgob3V0cHV0X2RpciwgImFtY2Vfbm9jb3ZfYW5kX2Nvdl9tb2RlbHMudHh0IikNCiAgKQ0KDQogIGFtY2VfcGxvdF9jb3YgPC0gbWFrZV9hbWNlX3Bsb3RfZGYobW9kZWxzX2J5X3BhcnR5X25fY292KQ0KICB3cml0ZV9jc3Zfc2FmZWx5KGFtY2VfcGxvdF9jb3YsICJhbWNlX2Nvdl9jb2VmZmljaWVudHMuY3N2IikNCg0KDQogIHN0dWR5X2xhYmVsIDwtICLlrp/pqJMx77yIMjAyM+W5tO+8iSINCg0KICB0ZXJtX2xhYmVsc19mYWNldCA8LSB0ZXJtX2xhYmVscyAlPiUNCiAgICBtdXRhdGUoDQogICAgICBhdHRyaWJ1dGVfZmFjZXQgPSBhdHRyaWJ1dGUNCiAgICApDQoNCiAgYXR0cmlidXRlX29yZGVyX2ZhY2V0IDwtIGMoDQogICAgIuS4juWFmu+8j+mHjuWFmiIsDQogICAgIuaUv+etluS9jee9riIsDQogICAgIuitsOW4reaVsCIsDQogICAgIkdEUOaIkOmVt+eOhyIsDQogICAgIuaXpee1jOW5s+WdhyIsDQogICAgIkNQSSIsDQogICAgIuWksealreeOhyINCiAgKQ0KDQogIG1ha2VfYW1jZV9mYWNldF9kZiA8LSBmdW5jdGlvbihtb2RlbHMpIHsNCiAgICBpbWFwX2RmcigNCiAgICAgIG1vZGVscywNCiAgICAgIH4gdGlkeV9maXhlc3QoLngpICU+JQ0KICAgICAgICBtdXRhdGUocGFydHlfbiA9IGFzLmNoYXJhY3RlcigueSkpDQogICAgKSAlPiUNCiAgICAgIGxlZnRfam9pbih0ZXJtX2xhYmVsc19mYWNldCwgYnkgPSAidGVybSIpICU+JQ0KICAgICAgZmlsdGVyKCFpcy5uYShhdHRyaWJ1dGVfZmFjZXQpKSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwNCiAgICAgICAgY29uZi5oaWdoX3BwID0gY29uZi5oaWdoICogMTAwLA0KICAgICAgICBwYXJ0eV9uID0gZmFjdG9yKA0KICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgbGV2ZWxzID0gYygiMiIsICIzIiwgIjQiLCAiNSIpLA0KICAgICAgICAgIGxhYmVscyA9IGMoIjLmlL/lhZoiLCAiM+aUv+WFmiIsICI05pS/5YWaIiwgIjXmlL/lhZoiKQ0KICAgICAgICApLA0KICAgICAgICBhdHRyaWJ1dGVfZmFjZXQgPSBmYWN0b3IoDQogICAgICAgICAgYXR0cmlidXRlX2ZhY2V0LA0KICAgICAgICAgIGxldmVscyA9IGF0dHJpYnV0ZV9vcmRlcl9mYWNldA0KICAgICAgICApLA0KICAgICAgICBsYWJlbCA9IGZhY3RvcigNCiAgICAgICAgICBsYWJlbCwNCiAgICAgICAgICBsZXZlbHMgPSByZXYobGFiZWxfb3JkZXIpDQogICAgICAgICkNCiAgICAgICkNCiAgfQ0KDQogIGFtY2VfcGxvdF9kZl9jb3ZfZmFjZXQgPC0gbWFrZV9hbWNlX2ZhY2V0X2RmKG1vZGVsc19ieV9wYXJ0eV9uX2NvdikNCiAgYW1jZV9wbG90X2RmX25vY292X2ZhY2V0IDwtIG1ha2VfYW1jZV9mYWNldF9kZihtb2RlbHNfYnlfcGFydHlfbl9ub2NvdikNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGFtY2VfcGxvdF9kZl9jb3ZfZmFjZXQsDQogICAgImFtY2VfY292X2ZhY2V0X2NvZWZmaWNpZW50cy5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGFtY2VfcGxvdF9kZl9ub2Nvdl9mYWNldCwNCiAgICAiYW1jZV9ub2Nvdl9mYWNldF9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCg0KICBwX2FtY2VfY292X2ZhY2V0IDwtIGdncGxvdCgNCiAgICBhbWNlX3Bsb3RfZGZfY292X2ZhY2V0LA0KICAgIGFlcygNCiAgICAgIHggPSBlc3RpbWF0ZV9wcCwNCiAgICAgIHkgPSBsYWJlbCwNCiAgICAgIHNoYXBlID0gcGFydHlfbiwNCiAgICAgIGxpbmV0eXBlID0gcGFydHlfbiwNCiAgICAgIGdyb3VwID0gcGFydHlfbg0KICAgICkNCiAgKSArDQogICAgZ2VvbV92bGluZSgNCiAgICAgIHhpbnRlcmNlcHQgPSAwLA0KICAgICAgbGluZXdpZHRoID0gMC40NSwNCiAgICAgIGNvbG9yID0gImdyZXkzNSINCiAgICApICsNCiAgICBnZW9tX2Vycm9yYmFyaCgNCiAgICAgIGFlcygNCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLA0KICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwDQogICAgICApLA0KICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgICAgaGVpZ2h0ID0gMC4xNiwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNTUsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX3BvaW50KA0KICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgc3Ryb2tlID0gMC44DQogICAgKSArDQogICAgZmFjZXRfZ3JpZCgNCiAgICAgIGF0dHJpYnV0ZV9mYWNldCB+IC4sDQogICAgICBzY2FsZXMgPSAiZnJlZV95IiwNCiAgICAgIHNwYWNlID0gImZyZWVfeSIsDQogICAgICBzd2l0Y2ggPSAieSINCiAgICApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIiBwcCIpLA0KICAgICAgYnJlYWtzID0gc2VxKC0xMiwgMTIsIGJ5ID0gMikNCiAgICApICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgICBuYW1lID0gIuaUv+WFmuaVsOmBuOaKnuiCoiIsDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiMuaUv+WFmiIgPSAxNiwNCiAgICAgICAgIjPmlL/lhZoiID0gMTcsDQogICAgICAgICI05pS/5YWaIiA9IDE1LA0KICAgICAgICAiNeaUv+WFmiIgPSAxDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjLmlL/lhZoiID0gInNvbGlkIiwNCiAgICAgICAgIjPmlL/lhZoiID0gImRhc2hlZCIsDQogICAgICAgICI05pS/5YWaIiA9ICJkb3R0ZWQiLA0KICAgICAgICAiNeaUv+WFmiIgPSAiZG90ZGFzaCINCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgeCA9ICLpgbjmip7norrnjofjga7lpInljJYiLA0KICAgICAgeSA9IE5VTEwNCiAgICApICsNCiAgICB0aGVtZV9idygNCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLA0KICAgICAgYmFzZV9mYW1pbHkgPSAiWXUgR290aGljIg0KICAgICkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDE2DQogICAgICApLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiLA0KICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgNCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLA0KICAgICAgICBjb2xvciA9ICJncmV5NTUiDQogICAgICApLA0KICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGFuZ2xlID0gMCwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDEwDQogICAgICApLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLA0KICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpDQogICAgKQ0KDQogIHByaW50KHBfYW1jZV9jb3ZfZmFjZXQpDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciLA0KICAgIHBfYW1jZV9jb3ZfZmFjZXQsDQogICAgd2lkdGggPSAxMC41LA0KICAgIGhlaWdodCA9IDguNQ0KICApDQoNCiAgcF9hbWNlX2Nvdl9tYWluIDwtIHBfYW1jZV9jb3ZfZmFjZXQNCg0KDQogIG1ha2VfaGVhdG1hcF9kZiA8LSBmdW5jdGlvbihhbWNlX3Bsb3RfZGYpIHsNCiAgICBoZWF0X2RmIDwtIGFtY2VfcGxvdF9kZiAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgYWJzX2FtY2UgPSBhYnMoZXN0aW1hdGVfcHApLA0KICAgICAgICBjdWVfdHlwZV9jb2RlID0gY2FzZV93aGVuKA0KICAgICAgICAgIGN1ZV90eXBlID09ICLmlL/lhZrjga7miYvjgYzjgYvjgooiIH4gInBhcnR5IiwNCiAgICAgICAgICBjdWVfdHlwZSA9PSAi57WM5riI44Gu5omL44GM44GL44KKIiB+ICJlY29ub215IiwNCiAgICAgICAgICBUUlVFIH4gIm90aGVyIg0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgZ3JvdXBfYnkocGFydHlfbikgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIHJhbmtfd2l0aGluX3BhcnR5ID0gbWluX3JhbmsoZGVzYyhhYnNfYW1jZSkpLA0KICAgICAgICBuX2luX2NvbCA9IG4oKSwNCiAgICAgICAgcmFua19zY29yZSA9IGlmX2Vsc2UoDQogICAgICAgICAgbl9pbl9jb2wgPT0gMSwNCiAgICAgICAgICAxLA0KICAgICAgICAgIDEgLSAocmFua193aXRoaW5fcGFydHkgLSAxKSAvIChuX2luX2NvbCAtIDEpDQogICAgICAgICkNCiAgICAgICkgJT4lDQogICAgICB1bmdyb3VwKCkNCg0KICAgIHJvd19vcmRlcl9kZiA8LSBoZWF0X2RmICU+JQ0KICAgICAgZ3JvdXBfYnkobGFiZWwsIGN1ZV90eXBlX2NvZGUpICU+JQ0KICAgICAgc3VtbWFyaXNlKA0KICAgICAgICBtZWFuX2Fic19hbWNlID0gbWVhbihhYnNfYW1jZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICAgKSAlPiUNCiAgICAgIGFycmFuZ2UoZGVzYyhtZWFuX2Fic19hbWNlKSkNCg0KICAgIHJvd19sZXZlbHMgPC0gYXMuY2hhcmFjdGVyKHJvd19vcmRlcl9kZiRsYWJlbCkNCg0KICAgIGhlYXRfZGYgPC0gaGVhdF9kZiAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgbGFiZWwgPSBmYWN0b3IoDQogICAgICAgICAgYXMuY2hhcmFjdGVyKGxhYmVsKSwNCiAgICAgICAgICBsZXZlbHMgPSByZXYocm93X2xldmVscykNCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgbGFiZWxfY29sb3JfbWFwIDwtIHJvd19vcmRlcl9kZiAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgbGFiZWxfbWFya2Rvd24gPSBjYXNlX3doZW4oDQogICAgICAgICAgY3VlX3R5cGVfY29kZSA9PSAicGFydHkiIH4NCiAgICAgICAgICAgIHBhc3RlMCgNCiAgICAgICAgICAgICAgIjxzcGFuIHN0eWxlPSdjb2xvcjojMTExMTExOyc+IiwNCiAgICAgICAgICAgICAgbGFiZWwsDQogICAgICAgICAgICAgICI8L3NwYW4+Ig0KICAgICAgICAgICAgKSwNCiAgICAgICAgICBjdWVfdHlwZV9jb2RlID09ICJlY29ub215IiB+DQogICAgICAgICAgICBwYXN0ZTAoDQogICAgICAgICAgICAgICI8c3BhbiBzdHlsZT0nY29sb3I6IzhBOEE4QTsnPiIsDQogICAgICAgICAgICAgIGxhYmVsLA0KICAgICAgICAgICAgICAiPC9zcGFuPiINCiAgICAgICAgICAgICksDQogICAgICAgICAgVFJVRSB+IGFzLmNoYXJhY3RlcihsYWJlbCkNCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgbGFiZWxfbWFya2Rvd25fdmVjIDwtIHNldE5hbWVzKA0KICAgICAgbGFiZWxfY29sb3JfbWFwJGxhYmVsX21hcmtkb3duLA0KICAgICAgYXMuY2hhcmFjdGVyKGxhYmVsX2NvbG9yX21hcCRsYWJlbCkNCiAgICApDQoNCiAgICBsaXN0KA0KICAgICAgaGVhdF9kZiA9IGhlYXRfZGYsDQogICAgICBsYWJlbF9tYXJrZG93bl92ZWMgPSBsYWJlbF9tYXJrZG93bl92ZWMNCiAgICApDQogIH0NCg0KICBwbG90X2FtY2VfaGVhdG1hcCA8LSBmdW5jdGlvbigNCiAgICAgIGhlYXRfZGYsDQogICAgICBsYWJlbF9tYXJrZG93bl92ZWMsDQogICAgICB3aXRoX3JhbmsgPSBUUlVFLA0KICAgICAgdGl0bGVfdGV4dCA9IE5VTEwpIHsNCg0KICAgIGlmICh3aXRoX3JhbmspIHsNCiAgICAgIGhlYXRfZGYgPC0gaGVhdF9kZiAlPiUNCiAgICAgICAgbXV0YXRlKA0KICAgICAgICAgIGNlbGxfbGFiZWwgPSBwYXN0ZTAoDQogICAgICAgICAgICBzcHJpbnRmKCIlLjFmIiwgZXN0aW1hdGVfcHApLA0KICAgICAgICAgICAgIlxuKCIsDQogICAgICAgICAgICByYW5rX3dpdGhpbl9wYXJ0eSwNCiAgICAgICAgICAgICLkvY0pIg0KICAgICAgICAgICkNCiAgICAgICAgKQ0KDQogICAgICB0ZXh0X3NpemUgPC0gMy4wDQogICAgICBsaW5laGVpZ2h0IDwtIDAuOQ0KICAgIH0gZWxzZSB7DQogICAgICBoZWF0X2RmIDwtIGhlYXRfZGYgJT4lDQogICAgICAgIG11dGF0ZSgNCiAgICAgICAgICBjZWxsX2xhYmVsID0gc3ByaW50ZigiJS4xZiIsIGVzdGltYXRlX3BwKQ0KICAgICAgICApDQoNCiAgICAgIHRleHRfc2l6ZSA8LSAzLjQNCiAgICAgIGxpbmVoZWlnaHQgPC0gMS4wDQogICAgfQ0KDQogICAgZ2dwbG90KA0KICAgICAgaGVhdF9kZiwNCiAgICAgIGFlcygNCiAgICAgICAgeCA9IHBhcnR5X24sDQogICAgICAgIHkgPSBsYWJlbCwNCiAgICAgICAgZmlsbCA9IHJhbmtfc2NvcmUNCiAgICAgICkNCiAgICApICsNCiAgICAgIGdlb21fdGlsZSgNCiAgICAgICAgY29sb3IgPSAid2hpdGUiLA0KICAgICAgICBsaW5ld2lkdGggPSAwLjcNCiAgICAgICkgKw0KICAgICAgZ2VvbV90ZXh0KA0KICAgICAgICBhZXMobGFiZWwgPSBjZWxsX2xhYmVsKSwNCiAgICAgICAgc2l6ZSA9IHRleHRfc2l6ZSwNCiAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsDQogICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgbGluZWhlaWdodCA9IGxpbmVoZWlnaHQNCiAgICAgICkgKw0KICAgICAgc2NhbGVfeV9kaXNjcmV0ZSgNCiAgICAgICAgbGFiZWxzID0gbGFiZWxfbWFya2Rvd25fdmVjDQogICAgICApICsNCiAgICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQoDQogICAgICAgIGxvdyA9ICJncmV5OTUiLA0KICAgICAgICBoaWdoID0gImdyZXkxNSIsDQogICAgICAgIGxpbWl0cyA9IGMoMCwgMSksDQogICAgICAgIGJyZWFrcyA9IGMoMCwgMC4yNSwgMC41MCwgMC43NSwgMS4wMCksDQogICAgICAgIGxhYmVscyA9IGMoIuS9jiIsICIiLCAiIiwgIiIsICLpq5giKSwNCiAgICAgICAgbmFtZSA9ICLliJflhoXpoIbkvY1cbu+8iOa/g+OBhOOBu+OBqemrmOS9je+8iSINCiAgICAgICkgKw0KICAgICAgbGFicygNCiAgICAgICAgdGl0bGUgPSB0aXRsZV90ZXh0LA0KICAgICAgICB4ID0gIuaUv+WFmuaVsOmBuOaKnuiCoiIsDQogICAgICAgIHkgPSBOVUxMDQogICAgICApICsNCiAgICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArDQogICAgICB0aGVtZSgNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3RleHQ6OmVsZW1lbnRfbWFya2Rvd24oc2l6ZSA9IDkpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkNCiAgICAgICkNCiAgfQ0KDQogIGhlYXRtYXBfaW5wdXQgPC0gbWFrZV9oZWF0bWFwX2RmKGFtY2VfcGxvdF9jb3YpDQoNCiAgcF9oZWF0X2FtY2VfbWl4ZWQgPC0gcGxvdF9hbWNlX2hlYXRtYXAoDQogICAgaGVhdG1hcF9pbnB1dCRoZWF0X2RmLA0KICAgIGhlYXRtYXBfaW5wdXQkbGFiZWxfbWFya2Rvd25fdmVjLA0KICAgIHdpdGhfcmFuayA9IEZBTFNFLA0KICAgIHRpdGxlX3RleHQgPSBOVUxMDQogICkNCg0KICBwcmludChwX2hlYXRfYW1jZV9taXhlZCkNCg0KICBzYXZlX3Bsb3QoDQogICAgImFtY2VfaGVhdG1hcF9taXhlZF9yYW5rX2NvbG9yZWRfbGFiZWxzLnBuZyIsDQogICAgcF9oZWF0X2FtY2VfbWl4ZWQsDQogICAgd2lkdGggPSA4LjgsDQogICAgaGVpZ2h0ID0gOC44DQogICkNCg0KICBwX2hlYXRfYW1jZV9taXhlZF9yYW5rbGFiZWwgPC0gcGxvdF9hbWNlX2hlYXRtYXAoDQogICAgaGVhdG1hcF9pbnB1dCRoZWF0X2RmLA0KICAgIGhlYXRtYXBfaW5wdXQkbGFiZWxfbWFya2Rvd25fdmVjLA0KICAgIHdpdGhfcmFuayA9IFRSVUUsDQogICAgdGl0bGVfdGV4dCA9IE5VTEwNCiAgKQ0KDQogIHByaW50KHBfaGVhdF9hbWNlX21peGVkX3JhbmtsYWJlbCkNCg0KICBzYXZlX3Bsb3QoDQogICAgImFtY2VfaGVhdG1hcF9taXhlZF9yYW5rX2NvbG9yZWRfbGFiZWxzX3dpdGhyYW5rLnBuZyIsDQogICAgcF9oZWF0X2FtY2VfbWl4ZWRfcmFua2xhYmVsLA0KICAgIHdpZHRoID0gOC44LA0KICAgIGhlaWdodCA9IDguOA0KICApDQoNCiAgcF9oZWF0X2FtY2UgPC0gcF9oZWF0X2FtY2VfbWl4ZWQNCiAgcF9oZWF0X2FtY2VfcmFuayA8LSBwX2hlYXRfYW1jZV9taXhlZF9yYW5rbGFiZWwNCg0KDQogIHBfYW1jZV9mYWNldF9ub2NvdiA8LSBnZ3Bsb3QoDQogICAgYW1jZV9wbG90X2RmX25vY292X2ZhY2V0LA0KICAgIGFlcygNCiAgICAgIHggPSBlc3RpbWF0ZV9wcCwNCiAgICAgIHkgPSBsYWJlbCwNCiAgICAgIHNoYXBlID0gcGFydHlfbiwNCiAgICAgIGxpbmV0eXBlID0gcGFydHlfbiwNCiAgICAgIGdyb3VwID0gcGFydHlfbg0KICAgICkNCiAgKSArDQogICAgZ2VvbV92bGluZSgNCiAgICAgIHhpbnRlcmNlcHQgPSAwLA0KICAgICAgbGluZXdpZHRoID0gMC40NSwNCiAgICAgIGNvbG9yID0gImdyZXkzNSINCiAgICApICsNCiAgICBnZW9tX2Vycm9yYmFyaCgNCiAgICAgIGFlcygNCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLA0KICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwDQogICAgICApLA0KICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgICAgaGVpZ2h0ID0gMC4xNiwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNTUsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX3BvaW50KA0KICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgc3Ryb2tlID0gMC44DQogICAgKSArDQogICAgZmFjZXRfZ3JpZCgNCiAgICAgIGF0dHJpYnV0ZV9mYWNldCB+IC4sDQogICAgICBzY2FsZXMgPSAiZnJlZV95IiwNCiAgICAgIHNwYWNlID0gImZyZWVfeSIsDQogICAgICBzd2l0Y2ggPSAieSINCiAgICApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIiBwcCIpLA0KICAgICAgYnJlYWtzID0gc2VxKC0xMiwgMTIsIGJ5ID0gMikNCiAgICApICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgICBuYW1lID0gIuaUv+WFmuaVsOmBuOaKnuiCoiIsDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiMuaUv+WFmiIgPSAxNiwNCiAgICAgICAgIjPmlL/lhZoiID0gMTcsDQogICAgICAgICI05pS/5YWaIiA9IDE1LA0KICAgICAgICAiNeaUv+WFmiIgPSAxDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjLmlL/lhZoiID0gInNvbGlkIiwNCiAgICAgICAgIjPmlL/lhZoiID0gImRhc2hlZCIsDQogICAgICAgICI05pS/5YWaIiA9ICJkb3R0ZWQiLA0KICAgICAgICAiNeaUv+WFmiIgPSAiZG90ZGFzaCINCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgeCA9ICLpgbjmip7norrnjofjga7lpInljJYiLA0KICAgICAgeSA9IE5VTEwNCiAgICApICsNCiAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDE2DQogICAgICApLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiLA0KICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgNCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLA0KICAgICAgICBjb2xvciA9ICJncmV5NTUiDQogICAgICApLA0KICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGFuZ2xlID0gMCwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDEwDQogICAgICApLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLA0KICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpDQogICAgKQ0KDQogIHByaW50KHBfYW1jZV9mYWNldF9ub2NvdikNCg0KICBzYXZlX3Bsb3QoDQogICAgImFtY2VfZmFjZXRfbm9jb3YucG5nIiwNCiAgICBwX2FtY2VfZmFjZXRfbm9jb3YsDQogICAgd2lkdGggPSAxMC41LA0KICAgIGhlaWdodCA9IDkNCiAgKQ0KDQogIHBfYW1jZV9ub2Nvdl9hcHBlbmRpeCA8LSBwX2FtY2VfZmFjZXRfbm9jb3YNCg0KDQogIHBfaW50ZXJhY3Rpb24gPC0gZ2dwbG90KA0KICAgIGludGVyYWN0aW9uX3Bsb3RfZGYsDQogICAgYWVzKA0KICAgICAgeCA9IGVzdGltYXRlX3BwLA0KICAgICAgeSA9IGxhYmVsLA0KICAgICAgc2hhcGUgPSBwYXJ0eV9uX2xhYmVsLA0KICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uX2xhYmVsLA0KICAgICAgZ3JvdXAgPSBwYXJ0eV9uX2xhYmVsDQogICAgKQ0KICApICsNCiAgICBnZW9tX3ZsaW5lKA0KICAgICAgeGludGVyY2VwdCA9IDAsDQogICAgICBsaW5ld2lkdGggPSAwLjQ1LA0KICAgICAgY29sb3IgPSAiZ3JleTM1Ig0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXJoKA0KICAgICAgYWVzKA0KICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsDQogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHANCiAgICAgICksDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICAgICBoZWlnaHQgPSAwLjE2LA0KICAgICAgbGluZXdpZHRoID0gMC41NSwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fcG9pbnQoDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICAgICBzaXplID0gMi41LA0KICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICBzdHJva2UgPSAwLjgNCiAgICApICsNCiAgICBmYWNldF9ncmlkKA0KICAgICAgYXR0cmlidXRlIH4gLiwNCiAgICAgIHNjYWxlcyA9ICJmcmVlX3kiLA0KICAgICAgc3BhY2UgPSAiZnJlZV95IiwNCiAgICAgIHN3aXRjaCA9ICJ5Ig0KICAgICkgKw0KICAgIHNjYWxlX3hfY29udGludW91cygNCiAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAiIHBwIiksDQogICAgICBicmVha3MgPSBzZXEoLTgsIDgsIGJ5ID0gMikNCiAgICApICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgICBuYW1lID0gIjLmlL/lhZrjga7loLTlkIjjgajjga7mr5TovIMiLA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjPmlL/lhZoiID0gMTcsDQogICAgICAgICI05pS/5YWaIiA9IDE1LA0KICAgICAgICAiNeaUv+WFmiIgPSAxDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICIy5pS/5YWa44Gu5aC05ZCI44Go44Gu5q+U6LyDIiwNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICIz5pS/5YWaIiA9ICJkYXNoZWQiLA0KICAgICAgICAiNOaUv+WFmiIgPSAiZG90dGVkIiwNCiAgICAgICAgIjXmlL/lhZoiID0gImRvdGRhc2giDQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHggPSAiMuaUv+WFmuadoeS7tuOBqOOBruW3riIsDQogICAgICB5ID0gTlVMTA0KICAgICkgKw0KICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArDQogICAgdGhlbWUoDQogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBmYWNlID0gImJvbGQiLA0KICAgICAgICBzaXplID0gMTUNCiAgICAgICksDQogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksDQogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwNCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsDQogICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KA0KICAgICAgICBmaWxsID0gImdyZXk5MiIsDQogICAgICAgIGNvbG9yID0gImdyZXk1NSINCiAgICAgICksDQogICAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgYW5nbGUgPSAwLA0KICAgICAgICBmYWNlID0gImJvbGQiLA0KICAgICAgICBzaXplID0gMTANCiAgICAgICksDQogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikNCiAgICApDQoNCiAgcHJpbnQocF9pbnRlcmFjdGlvbikNCg0KICBzYXZlX3Bsb3QoDQogICAgImFtY2VfaW50ZXJhY3Rpb25fZGlmZmVyZW5jZV9mcm9tXzJwYXJ0eS5wbmciLA0KICAgIHBfaW50ZXJhY3Rpb24sDQogICAgd2lkdGggPSAxMC41LA0KICAgIGhlaWdodCA9IDkNCiAgKQ0KDQoNCiAgY29uam9pbnRfY2xvZ2l0IDwtIGNvbmpvaW50X2FsbF9tICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihzZWxlY3RlZCksDQogICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksDQogICAgICB0YXNrX2lkID0gZmFjdG9yKHRhc2tfaWQpLA0KICAgICAgcG9saWN5X3Bvc2l0aW9uID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBwb2xpY3lfcG9zaXRpb24sDQogICAgICAgICLkuK3pgZMiDQogICAgICApLA0KICAgICAgZ292ZXJubWVudF9zdGF0dXMgPSByZWxldmVsX2lmX3ByZXNlbnQoDQogICAgICAgIGdvdmVybm1lbnRfc3RhdHVzLA0KICAgICAgICAi6YeO5YWaIg0KICAgICAgKSwNCiAgICAgIGdkcF9ncm93dGggPSByZWxldmVsX2lmX3ByZXNlbnQoDQogICAgICAgIGdkcF9ncm93dGgsDQogICAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiDQogICAgICApLA0KICAgICAgbmlra2VpID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBuaWtrZWksDQogICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5TlpInjgo/jgonjgZoiDQogICAgICApLA0KICAgICAgc2VhdHMgPSByZWxldmVsX2lmX3ByZXNlbnQoDQogICAgICAgIHNlYXRzLA0KICAgICAgICAiMTDku6XkuIsiDQogICAgICApLA0KICAgICAgY3BpID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBjcGksDQogICAgICAgICJDUEnliY3mnJ/mr5TCsTDjg53jgqTjg7Pjg4giDQogICAgICApLA0KICAgICAgdW5lbXBsb3ltZW50ID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICB1bmVtcGxveW1lbnQsDQogICAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiDQogICAgICApDQogICAgKQ0KDQogIGZvcm11bGFfY2xvZ2l0X25vY292IDwtIGFzLmZvcm11bGEoDQogICAgcGFzdGUwKA0KICAgICAgInNlbGVjdGVkIH4gIiwNCiAgICAgIHBhc3RlKGF0dHJfdGVybXMsIGNvbGxhcHNlID0gIiArICIpLA0KICAgICAgIiArIHN0cmF0YSh0YXNrX2lkKSArIGNsdXN0ZXIoSUQpIg0KICAgICkNCiAgKQ0KDQogIHJ1bl9jbG9naXRfbm9jb3YgPC0gZnVuY3Rpb24oZGF0KSB7DQogICAgc3Vydml2YWw6OmNsb2dpdCgNCiAgICAgIGZvcm11bGFfY2xvZ2l0X25vY292LA0KICAgICAgZGF0YSA9IGRhdCwNCiAgICAgIG1ldGhvZCA9ICJlZnJvbiINCiAgICApDQogIH0NCg0KICBtb2RlbHNfY2xvZ2l0X25vY292IDwtIGNvbmpvaW50X2Nsb2dpdCAlPiUNCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQ0KICAgIG1hcChydW5fY2xvZ2l0X25vY292KQ0KDQogIGNhcHR1cmUub3V0cHV0KA0KICAgIGxhcHBseShtb2RlbHNfY2xvZ2l0X25vY292LCBzdW1tYXJ5KSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJjb25kaXRpb25hbF9sb2dpdF9tb2RlbHMudHh0Ig0KICAgICkNCiAgKQ0KDQogIHRpZHlfY2xvZ2l0IDwtIGZ1bmN0aW9uKG1vZGVsKSB7DQogICAgcyA8LSBzdW1tYXJ5KG1vZGVsKQ0KICAgIGN0IDwtIGFzLmRhdGEuZnJhbWUocyRjb2VmZmljaWVudHMpDQogICAgY3QkdGVybSA8LSByb3duYW1lcyhjdCkNCg0KICAgIHNlX2NvbCA8LSBpZiAoInJvYnVzdCBzZSIgJWluJSBuYW1lcyhjdCkpIHsNCiAgICAgICJyb2J1c3Qgc2UiDQogICAgfSBlbHNlIGlmICgic2UoY29lZikiICVpbiUgbmFtZXMoY3QpKSB7DQogICAgICAic2UoY29lZikiDQogICAgfSBlbHNlIHsNCiAgICAgIHN0b3AoIkNoZWNrIGNsb2dpdCIpDQogICAgfQ0KDQogICAgcF9jb2wgPC0gaWYgKCJQcig+fHp8KSIgJWluJSBuYW1lcyhjdCkpIHsNCiAgICAgICJQcig+fHp8KSINCiAgICB9IGVsc2UgaWYgKCJQcig+fHR8KSIgJWluJSBuYW1lcyhjdCkpIHsNCiAgICAgICJQcig+fHR8KSINCiAgICB9IGVsc2Ugew0KICAgICAgTkFfY2hhcmFjdGVyXw0KICAgIH0NCg0KICAgIGN0ICU+JQ0KICAgICAgYXNfdGliYmxlKCkgJT4lDQogICAgICB0cmFuc211dGUoDQogICAgICAgIHRlcm0gPSB0ZXJtLA0KICAgICAgICBlc3RpbWF0ZSA9IGNvZWYsDQogICAgICAgIHN0ZC5lcnJvciA9IC5kYXRhW1tzZV9jb2xdXSwNCiAgICAgICAgcC52YWx1ZSA9IGlmICghaXMubmEocF9jb2wpKSB7DQogICAgICAgICAgLmRhdGFbW3BfY29sXV0NCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBOQV9yZWFsXw0KICAgICAgICB9LA0KICAgICAgICBjb25mLmxvdyA9IGVzdGltYXRlIC0gMS45NiAqIHN0ZC5lcnJvciwNCiAgICAgICAgY29uZi5oaWdoID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yLA0KICAgICAgICBvZGRzX3JhdGlvID0gZXhwKGVzdGltYXRlKSwNCiAgICAgICAgb2Rkc19yYXRpb19sb3cgPSBleHAoY29uZi5sb3cpLA0KICAgICAgICBvZGRzX3JhdGlvX2hpZ2ggPSBleHAoY29uZi5oaWdoKQ0KICAgICAgKQ0KICB9DQoNCiAgY2xvZ2l0X3Bsb3RfZGYgPC0gaW1hcF9kZnIoDQogICAgbW9kZWxzX2Nsb2dpdF9ub2NvdiwNCiAgICB+IHRpZHlfY2xvZ2l0KC54KSAlPiUNCiAgICAgIG11dGF0ZShwYXJ0eV9uID0gYXMuY2hhcmFjdGVyKC55KSkNCiAgKSAlPiUNCiAgICBsZWZ0X2pvaW4odGVybV9sYWJlbHMsIGJ5ID0gInRlcm0iKSAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKGF0dHJpYnV0ZSkpICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHBhcnR5X24gPSBmYWN0b3IoDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKSwNCiAgICAgICAgbGFiZWxzID0gYygiMuaUv+WFmiIsICIz5pS/5YWaIiwgIjTmlL/lhZoiLCAiNeaUv+WFmiIpDQogICAgICApLA0KICAgICAgbGFiZWwgPSBmYWN0b3IoDQogICAgICAgIGxhYmVsLA0KICAgICAgICBsZXZlbHMgPSByZXYobGFiZWxfb3JkZXIpDQogICAgICApDQogICAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgY2xvZ2l0X3Bsb3RfZGYsDQogICAgImNvbmRpdGlvbmFsX2xvZ2l0X2NvZWZmaWNpZW50cy5jc3YiDQogICkNCg0KDQogIHBfY2xvZ2l0X29yIDwtIGdncGxvdCgNCiAgICBjbG9naXRfcGxvdF9kZiwNCiAgICBhZXMoDQogICAgICB4ID0gb2Rkc19yYXRpbywNCiAgICAgIHkgPSBsYWJlbCwNCiAgICAgIHNoYXBlID0gcGFydHlfbiwNCiAgICAgIGxpbmV0eXBlID0gcGFydHlfbiwNCiAgICAgIGdyb3VwID0gcGFydHlfbg0KICAgICkNCiAgKSArDQogICAgZ2VvbV92bGluZSgNCiAgICAgIHhpbnRlcmNlcHQgPSAxLA0KICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsDQogICAgICBjb2xvciA9ICJncmV5MzUiDQogICAgKSArDQogICAgZ2VvbV9lcnJvcmJhcmgoDQogICAgICBhZXMoDQogICAgICAgIHhtaW4gPSBvZGRzX3JhdGlvX2xvdywNCiAgICAgICAgeG1heCA9IG9kZHNfcmF0aW9faGlnaA0KICAgICAgKSwNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcyKSwNCiAgICAgIGhlaWdodCA9IDAuMTUsDQogICAgICBsaW5ld2lkdGggPSAwLjQ1LA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9wb2ludCgNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcyKSwNCiAgICAgIHNpemUgPSAyLjQsDQogICAgICBzdHJva2UgPSAwLjcsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBzY2FsZV94X2xvZzEwKA0KICAgICAgYnJlYWtzID0gYygNCiAgICAgICAgMC42LA0KICAgICAgICAwLjgsDQogICAgICAgIDEuMCwNCiAgICAgICAgMS4yNSwNCiAgICAgICAgMS41LA0KICAgICAgICAyLjANCiAgICAgICksDQogICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAiMC42IiwNCiAgICAgICAgIjAuOCIsDQogICAgICAgICIxLjAiLA0KICAgICAgICAiMS4yNSIsDQogICAgICAgICIxLjUiLA0KICAgICAgICAiMi4wIg0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX3NoYXBlX21hbnVhbCgNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICIy5pS/5YWaIiA9IDE2LA0KICAgICAgICAiM+aUv+WFmiIgPSAxNywNCiAgICAgICAgIjTmlL/lhZoiID0gMTUsDQogICAgICAgICI15pS/5YWaIiA9IDENCiAgICAgICkNCiAgICApICsNCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiMuaUv+WFmiIgPSAic29saWQiLA0KICAgICAgICAiM+aUv+WFmiIgPSAiZGFzaGVkIiwNCiAgICAgICAgIjTmlL/lhZoiID0gImRvdGRhc2giLA0KICAgICAgICAiNeaUv+WFmiIgPSAidHdvZGFzaCINCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgeCA9ICLjgqrjg4Pjgrrmr5QiLA0KICAgICAgeSA9IE5VTEwsDQogICAgICBzaGFwZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLA0KICAgICAgbGluZXR5cGUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIg0KICAgICkgKw0KICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArDQogICAgdGhlbWUoDQogICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpDQogICAgKQ0KDQogIHByaW50KHBfY2xvZ2l0X29yKQ0KDQogIHNhdmVfcGxvdCgNCiAgICAiY2xvZ2l0X29kZHNyYXRpb19ub2Nvdi5wbmciLA0KICAgIHBfY2xvZ2l0X29yLA0KICAgIHdpZHRoID0gMTAuNSwNCiAgICBoZWlnaHQgPSA4LjUNCiAgKQ0KDQoNCiAgcmVsYXRpdmVfY3VlX21hcCA8LSBjKA0KICAgIHBvbGljeV9wb3NpdGlvbiA9ICJwYXJ0eSIsDQogICAgZ292ZXJubWVudF9zdGF0dXMgPSAicGFydHkiLA0KICAgIHNlYXRzID0gInBhcnR5IiwNCiAgICBnZHBfZ3Jvd3RoID0gImVjb25vbWljIiwNCiAgICBuaWtrZWkgPSAiZWNvbm9taWMiLA0KICAgIGNwaSA9ICJlY29ub21pYyIsDQogICAgdW5lbXBsb3ltZW50ID0gImVjb25vbWljIg0KICApDQoNCiAgbWVhbl9hYnNvbHV0ZV9wYWlyd2lzZV9kaWZmZXJlbmNlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXQ0KDQogICAgaWYgKGxlbmd0aCh4KSA8IDIpIHsNCiAgICAgIHJldHVybihOQV9yZWFsXykNCiAgICB9DQoNCiAgICBwYWlyd2lzZV9kaWZmZXJlbmNlcyA8LSBjb21ibigNCiAgICAgIHgsDQogICAgICAyLA0KICAgICAgRlVOID0gZnVuY3Rpb24oeikgYWJzKHpbMV0gLSB6WzJdKQ0KICAgICkNCg0KICAgIG1lYW4ocGFpcndpc2VfZGlmZmVyZW5jZXMpDQogIH0NCg0KICBsaW5lYXJfc2xvcGUgPC0gZnVuY3Rpb24oeSwgeCkgew0KICAgIGtlZXAgPC0gaXMuZmluaXRlKHkpICYgaXMuZmluaXRlKHgpDQogICAgeSA8LSB5W2tlZXBdDQogICAgeCA8LSB4W2tlZXBdDQoNCiAgICBpZiAobGVuZ3RoKHkpIDwgMiB8fCBsZW5ndGgodW5pcXVlKHgpKSA8IDIpIHsNCiAgICAgIHJldHVybihOQV9yZWFsXykNCiAgICB9DQoNCiAgICB1bm5hbWUoY29lZihsbSh5IH4geCkpWzJdKQ0KICB9DQoNCiAgYm9vdHN0cmFwX3R3b19zaWRlZF9wIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXQ0KICAgIEJfdmFsaWQgPC0gbGVuZ3RoKHgpDQoNCiAgICBpZiAoQl92YWxpZCA9PSAwKSB7DQogICAgICByZXR1cm4oTkFfcmVhbF8pDQogICAgfQ0KDQogICAgcF9sb3dlciA8LSAoMSArIHN1bSh4IDw9IDApKSAvIChCX3ZhbGlkICsgMSkNCiAgICBwX3VwcGVyIDwtICgxICsgc3VtKHggPj0gMCkpIC8gKEJfdmFsaWQgKyAxKQ0KDQogICAgbWluKDEsIDIgKiBtaW4ocF9sb3dlciwgcF91cHBlcikpDQogIH0NCg0KICBzYWZlX3F1YW50aWxlIDwtIGZ1bmN0aW9uKHgsIHByb2JhYmlsaXR5KSB7DQogICAgeCA8LSB4W2lzLmZpbml0ZSh4KV0NCg0KICAgIGlmIChsZW5ndGgoeCkgPT0gMCkgew0KICAgICAgcmV0dXJuKE5BX3JlYWxfKQ0KICAgIH0NCg0KICAgIHVubmFtZSgNCiAgICAgIHF1YW50aWxlKA0KICAgICAgICB4LA0KICAgICAgICBwcm9icyA9IHByb2JhYmlsaXR5LA0KICAgICAgICB0eXBlID0gNiwNCiAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICApDQogICAgKQ0KICB9DQoNCiAgcHJlcGFyZV9yZWxhdGl2ZV9jdWVfYW5hbHlzaXMgPC0gZnVuY3Rpb24oZGF0YSwgY3VlX21hcCkgew0KICAgIGF0dHJpYnV0ZXMgPC0gbmFtZXMoY3VlX21hcCkNCg0KICAgIHJlcXVpcmVkX2NvbHVtbnMgPC0gYygNCiAgICAgICJJRCIsDQogICAgICAicGFydHlfbiIsDQogICAgICAic2VsZWN0ZWQiLA0KICAgICAgYXR0cmlidXRlcw0KICAgICkNCg0KICAgIG1pc3NpbmdfY29sdW1ucyA8LSBzZXRkaWZmKA0KICAgICAgcmVxdWlyZWRfY29sdW1ucywNCiAgICAgIG5hbWVzKGRhdGEpDQogICAgKQ0KDQogICAgaWYgKGxlbmd0aChtaXNzaW5nX2NvbHVtbnMpID4gMCkgew0KICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikNCiAgICB9DQoNCiAgICBpZiAoIWFsbCh1bm5hbWUoY3VlX21hcCkgJWluJSBjKCJwYXJ0eSIsICJlY29ub21pYyIpKSkgew0KICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikNCiAgICB9DQoNCiAgICBhbmFseXNpc19kYXRhIDwtIGRhdGEgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIElELA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBzZWxlY3RlZCwNCiAgICAgICAgYWxsX29mKGF0dHJpYnV0ZXMpDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksDQogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSksDQogICAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihzZWxlY3RlZCksDQogICAgICAgIGFjcm9zcygNCiAgICAgICAgICBhbGxfb2YoYXR0cmlidXRlcyksDQogICAgICAgICAgYXMuY2hhcmFjdGVyDQogICAgICAgICkNCiAgICAgICkgJT4lDQogICAgICBmaWx0ZXIoDQogICAgICAgICFpcy5uYShJRCksDQogICAgICAgIHBhcnR5X24gJWluJSAyOjUsDQogICAgICAgIHNlbGVjdGVkICVpbiUgYygwTCwgMUwpDQogICAgICApDQoNCiAgICBvYnNlcnZlZF9jb25kaXRpb25zIDwtIHNvcnQoDQogICAgICB1bmlxdWUoYW5hbHlzaXNfZGF0YSRwYXJ0eV9uKQ0KICAgICkNCg0KICAgIGlmICghaWRlbnRpY2FsKG9ic2VydmVkX2NvbmRpdGlvbnMsIDI6NSkpIHsNCiAgICAgIHN0b3AoIkNoZWNrIikNCiAgICB9DQoNCiAgICBsb25nX2RhdGEgPC0gYW5hbHlzaXNfZGF0YSAlPiUNCiAgICAgIHBpdm90X2xvbmdlcigNCiAgICAgICAgY29scyA9IGFsbF9vZihhdHRyaWJ1dGVzKSwNCiAgICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwNCiAgICAgICAgdmFsdWVzX3RvID0gImxldmVsIg0KICAgICAgKSAlPiUNCiAgICAgIGZpbHRlcigNCiAgICAgICAgIWlzLm5hKGxldmVsKSwNCiAgICAgICAgbGV2ZWwgIT0gIiINCiAgICAgICkNCg0KICAgIGV4cGVjdGVkX2NlbGxzIDwtIGxvbmdfZGF0YSAlPiUNCiAgICAgIGRpc3RpbmN0KA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVsDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBhdHRyaWJ1dGVfb3JkZXIgPSBtYXRjaCgNCiAgICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgICAgYXR0cmlidXRlcw0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgYXJyYW5nZSgNCiAgICAgICAgYXR0cmlidXRlX29yZGVyLA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVsDQogICAgICApICU+JQ0KICAgICAgc2VsZWN0KC1hdHRyaWJ1dGVfb3JkZXIpICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBjZWxsX2tleSA9IHBhc3RlKA0KICAgICAgICAgIGF0dHJpYnV0ZSwNCiAgICAgICAgICBsZXZlbCwNCiAgICAgICAgICBzZXAgPSAiXHIiDQogICAgICAgICkNCiAgICAgICkNCg0KICAgIHJlc3BvbmRlbnRfY2VsbCA8LSBsb25nX2RhdGEgJT4lDQogICAgICBncm91cF9ieSgNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgSUQsDQogICAgICAgIGF0dHJpYnV0ZSwNCiAgICAgICAgbGV2ZWwNCiAgICAgICkgJT4lDQogICAgICBzdW1tYXJpc2UoDQogICAgICAgIHlfc3VtID0gc3VtKHNlbGVjdGVkKSwNCiAgICAgICAgbl9vYnMgPSBuKCksDQogICAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICAgICkgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGNlbGxfa2V5ID0gcGFzdGUoDQogICAgICAgICAgYXR0cmlidXRlLA0KICAgICAgICAgIGxldmVsLA0KICAgICAgICAgIHNlcCA9ICJcciINCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgY29uZGl0aW9uX29iamVjdHMgPC0gbGFwcGx5KA0KICAgICAgMjo1LA0KICAgICAgZnVuY3Rpb24obl92YWx1ZSkgew0KICAgICAgICBjb25kaXRpb25fZGF0YSA8LSByZXNwb25kZW50X2NlbGwgJT4lDQogICAgICAgICAgZmlsdGVyKA0KICAgICAgICAgICAgcGFydHlfbiA9PSBuX3ZhbHVlDQogICAgICAgICAgKQ0KDQogICAgICAgIGlkX3ZhbHVlcyA8LSBzb3J0KA0KICAgICAgICAgIHVuaXF1ZShjb25kaXRpb25fZGF0YSRJRCkNCiAgICAgICAgKQ0KICAgICAgICBuX2lkcyA8LSBsZW5ndGgoaWRfdmFsdWVzKQ0KICAgICAgICBuX2NlbGxzIDwtIG5yb3coZXhwZWN0ZWRfY2VsbHMpDQoNCiAgICAgICAgaWYgKG5faWRzID09IDApIHsNCiAgICAgICAgICBzdG9wKCJDaGVjayIpDQogICAgICAgIH0NCg0KICAgICAgICB5X21hdHJpeCA8LSBtYXRyaXgoDQogICAgICAgICAgMCwNCiAgICAgICAgICBucm93ID0gbl9pZHMsDQogICAgICAgICAgbmNvbCA9IG5fY2VsbHMsDQogICAgICAgICAgZGltbmFtZXMgPSBsaXN0KA0KICAgICAgICAgICAgaWRfdmFsdWVzLA0KICAgICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkNCiAgICAgICAgICApDQogICAgICAgICkNCg0KICAgICAgICBuX21hdHJpeCA8LSBtYXRyaXgoDQogICAgICAgICAgMCwNCiAgICAgICAgICBucm93ID0gbl9pZHMsDQogICAgICAgICAgbmNvbCA9IG5fY2VsbHMsDQogICAgICAgICAgZGltbmFtZXMgPSBsaXN0KA0KICAgICAgICAgICAgaWRfdmFsdWVzLA0KICAgICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkNCiAgICAgICAgICApDQogICAgICAgICkNCg0KICAgICAgICByb3dfaW5kZXggPC0gbWF0Y2goDQogICAgICAgICAgY29uZGl0aW9uX2RhdGEkSUQsDQogICAgICAgICAgaWRfdmFsdWVzDQogICAgICAgICkNCiAgICAgICAgY29sdW1uX2luZGV4IDwtIG1hdGNoKA0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJGNlbGxfa2V5LA0KICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5DQogICAgICAgICkNCg0KICAgICAgICB5X21hdHJpeFtjYmluZChyb3dfaW5kZXgsIGNvbHVtbl9pbmRleCldIDwtDQogICAgICAgICAgY29uZGl0aW9uX2RhdGEkeV9zdW0NCiAgICAgICAgbl9tYXRyaXhbY2JpbmQocm93X2luZGV4LCBjb2x1bW5faW5kZXgpXSA8LQ0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJG5fb2JzDQoNCiAgICAgICAgaWYgKGFueShjb2xTdW1zKG5fbWF0cml4KSA9PSAwKSkgew0KICAgICAgICAgIG1pc3NpbmdfY2VsbHMgPC0gZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXlbDQogICAgICAgICAgICBjb2xTdW1zKG5fbWF0cml4KSA9PSAwDQogICAgICAgICAgXQ0KDQogICAgICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpDQogICAgICAgIH0NCg0KICAgICAgICBsaXN0KA0KICAgICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLA0KICAgICAgICAgIGlkcyA9IGlkX3ZhbHVlcywNCiAgICAgICAgICBjZWxsX2luZm8gPSBleHBlY3RlZF9jZWxscywNCiAgICAgICAgICB5X21hdHJpeCA9IHlfbWF0cml4LA0KICAgICAgICAgIG5fbWF0cml4ID0gbl9tYXRyaXgNCiAgICAgICAgKQ0KICAgICAgfQ0KICAgICkNCg0KICAgIG5hbWVzKGNvbmRpdGlvbl9vYmplY3RzKSA8LSBhcy5jaGFyYWN0ZXIoMjo1KQ0KDQogICAgbGlzdCgNCiAgICAgIGN1ZV9tYXAgPSBjdWVfbWFwLA0KICAgICAgYXR0cmlidXRlcyA9IGF0dHJpYnV0ZXMsDQogICAgICBjb25kaXRpb25zID0gY29uZGl0aW9uX29iamVjdHMNCiAgICApDQogIH0NCg0KICBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcyA8LSBmdW5jdGlvbigNCiAgICAgIHByZXBhcmVkLA0KICAgICAgY2x1c3Rlcl93ZWlnaHRzID0gTlVMTA0KICApIHsNCiAgICBjb25kaXRpb25fcmVzdWx0cyA8LSBsYXBwbHkoDQogICAgICBuYW1lcyhwcmVwYXJlZCRjb25kaXRpb25zKSwNCiAgICAgIGZ1bmN0aW9uKGNvbmRpdGlvbl9uYW1lKSB7DQogICAgICAgIG9iamVjdCA8LSBwcmVwYXJlZCRjb25kaXRpb25zW1tjb25kaXRpb25fbmFtZV1dDQoNCiAgICAgICAgaWYgKGlzLm51bGwoY2x1c3Rlcl93ZWlnaHRzKSkgew0KICAgICAgICAgIHdlaWdodHMgPC0gcmVwKA0KICAgICAgICAgICAgMSwNCiAgICAgICAgICAgIGxlbmd0aChvYmplY3QkaWRzKQ0KICAgICAgICAgICkNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICB3ZWlnaHRzIDwtIGNsdXN0ZXJfd2VpZ2h0c1tbY29uZGl0aW9uX25hbWVdXQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGxlbmd0aCh3ZWlnaHRzKSAhPSBsZW5ndGgob2JqZWN0JGlkcykpIHsNCiAgICAgICAgICBzdG9wKCJDaGVjayIpDQogICAgICAgIH0NCg0KICAgICAgICBudW1lcmF0b3IgPC0gYXMubnVtZXJpYygNCiAgICAgICAgICBjcm9zc3Byb2QoDQogICAgICAgICAgICB3ZWlnaHRzLA0KICAgICAgICAgICAgb2JqZWN0JHlfbWF0cml4DQogICAgICAgICAgKQ0KICAgICAgICApDQoNCiAgICAgICAgZGVub21pbmF0b3IgPC0gYXMubnVtZXJpYygNCiAgICAgICAgICBjcm9zc3Byb2QoDQogICAgICAgICAgICB3ZWlnaHRzLA0KICAgICAgICAgICAgb2JqZWN0JG5fbWF0cml4DQogICAgICAgICAgKQ0KICAgICAgICApDQoNCiAgICAgICAgaWYgKGFueShkZW5vbWluYXRvciA8PSAwKSkgew0KICAgICAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQ0KICAgICAgICB9DQoNCiAgICAgICAgbWFyZ2luYWxfbWVhbnMgPC0gbnVtZXJhdG9yIC8gZGVub21pbmF0b3INCg0KICAgICAgICBtbV90YWJsZSA8LSBvYmplY3QkY2VsbF9pbmZvICU+JQ0KICAgICAgICAgIHRyYW5zbXV0ZSgNCiAgICAgICAgICAgIHBhcnR5X24gPSBvYmplY3QkcGFydHlfbiwNCiAgICAgICAgICAgIGF0dHJpYnV0ZSwNCiAgICAgICAgICAgIGxldmVsLA0KICAgICAgICAgICAgbWFyZ2luYWxfbWVhbiA9IG1hcmdpbmFsX21lYW5zDQogICAgICAgICAgKQ0KDQogICAgICAgIGF0dHJpYnV0ZV90YWJsZSA8LSBtbV90YWJsZSAlPiUNCiAgICAgICAgICBncm91cF9ieSgNCiAgICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgICBhdHRyaWJ1dGUNCiAgICAgICAgICApICU+JQ0KICAgICAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICAgICAgICBtZWFuX2Fic29sdXRlX3BhaXJ3aXNlX2RpZmZlcmVuY2UoDQogICAgICAgICAgICAgICAgbWFyZ2luYWxfbWVhbg0KICAgICAgICAgICAgICApLA0KICAgICAgICAgICAgbl9sZXZlbHMgPSBuKCksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgICAgICAgKSAlPiUNCiAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICBjdWVfZmFtaWx5ID0gdW5uYW1lKA0KICAgICAgICAgICAgICBwcmVwYXJlZCRjdWVfbWFwW2F0dHJpYnV0ZV0NCiAgICAgICAgICAgICksDQogICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkgPSAxIC8gcGFydHlfbiwNCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlIC8NCiAgICAgICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkNCiAgICAgICAgICApDQoNCiAgICAgICAgY3VlX3RhYmxlX2xvbmcgPC0gYXR0cmlidXRlX3RhYmxlICU+JQ0KICAgICAgICAgIGdyb3VwX2J5KA0KICAgICAgICAgICAgcGFydHlfbiwNCiAgICAgICAgICAgIGN1ZV9mYW1pbHkNCiAgICAgICAgICApICU+JQ0KICAgICAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UgPSBtZWFuKA0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlLA0KICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUNCiAgICAgICAgICAgICksDQogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0gbWVhbigNCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICAgICAgICkNCg0KICAgICAgICBwYXJ0eV90YWJsZSA8LSBjdWVfdGFibGVfbG9uZyAlPiUNCiAgICAgICAgICBmaWx0ZXIoDQogICAgICAgICAgICBjdWVfZmFtaWx5ID09ICJwYXJ0eSINCiAgICAgICAgICApICU+JQ0KICAgICAgICAgIHRyYW5zbXV0ZSgNCiAgICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkDQogICAgICAgICAgKQ0KDQogICAgICAgIGVjb25vbWljX3RhYmxlIDwtIGN1ZV90YWJsZV9sb25nICU+JQ0KICAgICAgICAgIGZpbHRlcigNCiAgICAgICAgICAgIGN1ZV9mYW1pbHkgPT0gImVjb25vbWljIg0KICAgICAgICAgICkgJT4lDQogICAgICAgICAgdHJhbnNtdXRlKA0KICAgICAgICAgICAgcGFydHlfbiwNCiAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlLA0KICAgICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9DQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQNCiAgICAgICAgICApDQoNCiAgICAgICAgY3VlX3RhYmxlIDwtIGZ1bGxfam9pbigNCiAgICAgICAgICBwYXJ0eV90YWJsZSwNCiAgICAgICAgICBlY29ub21pY190YWJsZSwNCiAgICAgICAgICBieSA9ICJwYXJ0eV9uIg0KICAgICAgICApICU+JQ0KICAgICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eSA9IDEgLyBwYXJ0eV9uLA0KDQogICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSArDQogICAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UsDQoNCiAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkICsNCiAgICAgICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCg0KICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0gaWZfZWxzZSgNCiAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZSA+IDAsDQogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgLw0KICAgICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2UsDQogICAgICAgICAgICAgIE5BX3JlYWxfDQogICAgICAgICAgICApLA0KDQogICAgICAgICAgICByZWxhdGl2ZV9lY29ub21pY193ZWlnaHRfcGFpcndpc2UgPQ0KICAgICAgICAgICAgICAxIC0gcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlLA0KDQogICAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQgPSBpZl9lbHNlKA0KICAgICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID4gMCwNCiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCAvDQogICAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICAgICAgTkFfcmVhbF8NCiAgICAgICAgICAgICksDQoNCiAgICAgICAgICAgIHJlbGF0aXZlX2Vjb25vbWljX3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCA9DQogICAgICAgICAgICAgIDEgLSByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQsDQoNCiAgICAgICAgICAgIGFkanVzdG1lbnRfaWRlbnRpdHlfZGlmZmVyZW5jZSA9DQogICAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCAtDQogICAgICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlDQogICAgICAgICAgKQ0KDQogICAgICAgIGlmICgNCiAgICAgICAgICBhbnkoDQogICAgICAgICAgICBhYnMoY3VlX3RhYmxlJGFkanVzdG1lbnRfaWRlbnRpdHlfZGlmZmVyZW5jZSkgPiAxZS0xMCwNCiAgICAgICAgICAgIG5hLnJtID0gVFJVRQ0KICAgICAgICAgICkNCiAgICAgICAgKSB7DQogICAgICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikNCiAgICAgICAgfQ0KDQogICAgICAgIGxpc3QoDQogICAgICAgICAgbWFyZ2luYWxfbWVhbnMgPSBtbV90YWJsZSwNCiAgICAgICAgICBhdHRyaWJ1dGVfaW1wb3J0YW5jZSA9IGF0dHJpYnV0ZV90YWJsZSwNCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSA9IGN1ZV90YWJsZQ0KICAgICAgICApDQogICAgICB9DQogICAgKQ0KDQogICAgbGlzdCgNCiAgICAgIG1hcmdpbmFsX21lYW5zID0gYmluZF9yb3dzKA0KICAgICAgICBsYXBwbHkoDQogICAgICAgICAgY29uZGl0aW9uX3Jlc3VsdHMsDQogICAgICAgICAgZnVuY3Rpb24oeCkgeCRtYXJnaW5hbF9tZWFucw0KICAgICAgICApDQogICAgICApLA0KICAgICAgYXR0cmlidXRlX2ltcG9ydGFuY2UgPSBiaW5kX3Jvd3MoDQogICAgICAgIGxhcHBseSgNCiAgICAgICAgICBjb25kaXRpb25fcmVzdWx0cywNCiAgICAgICAgICBmdW5jdGlvbih4KSB4JGF0dHJpYnV0ZV9pbXBvcnRhbmNlDQogICAgICAgICkNCiAgICAgICksDQogICAgICBjdWVfaW1wb3J0YW5jZSA9IGJpbmRfcm93cygNCiAgICAgICAgbGFwcGx5KA0KICAgICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzLA0KICAgICAgICAgIGZ1bmN0aW9uKHgpIHgkY3VlX2ltcG9ydGFuY2UNCiAgICAgICAgKQ0KICAgICAgKSAlPiUNCiAgICAgICAgYXJyYW5nZShwYXJ0eV9uKQ0KICAgICkNCiAgfQ0KDQogIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMgPC0gZnVuY3Rpb24oY3VlX2ltcG9ydGFuY2UpIHsNCiAgICBjdWVfaW1wb3J0YW5jZSA8LSBjdWVfaW1wb3J0YW5jZSAlPiUNCiAgICAgIGFycmFuZ2UocGFydHlfbikNCg0KICAgIGlmICghaWRlbnRpY2FsKGN1ZV9pbXBvcnRhbmNlJHBhcnR5X24sIDI6NSkpIHsNCiAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpDQogICAgfQ0KDQogICAgeCA8LSBjdWVfaW1wb3J0YW5jZSRwYXJ0eV9uDQoNCiAgICBjKA0KICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0NCiAgICAgICAgbGluZWFyX3Nsb3BlKA0KICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlJHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICB4DQogICAgICAgICkNCiAgICApDQogIH0NCg0KICBydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA8LSBmdW5jdGlvbigNCiAgICAgIHByZXBhcmVkLA0KICAgICAgQiwNCiAgICAgIHNlZWQsDQogICAgICBwcm9ncmVzc19ldmVyeSA9IDEwMA0KICApIHsNCiAgICBzZXQuc2VlZChzZWVkKQ0KDQogICAgY29uZGl0aW9uX3Jlc3VsdHMgPC0gdmVjdG9yKA0KICAgICAgImxpc3QiLA0KICAgICAgQg0KICAgICkNCg0KICAgIHNsb3BlX25hbWVzIDwtIGMoDQogICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICkNCg0KICAgIHNsb3BlX21hdHJpeCA8LSBtYXRyaXgoDQogICAgICBOQV9yZWFsXywNCiAgICAgIG5yb3cgPSBCLA0KICAgICAgbmNvbCA9IGxlbmd0aChzbG9wZV9uYW1lcyksDQogICAgICBkaW1uYW1lcyA9IGxpc3QoDQogICAgICAgIE5VTEwsDQogICAgICAgIHNsb3BlX25hbWVzDQogICAgICApDQogICAgKQ0KDQogICAgZm9yIChiIGluIHNlcV9sZW4oQikpIHsNCiAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA8LSBsYXBwbHkoDQogICAgICAgIHByZXBhcmVkJGNvbmRpdGlvbnMsDQogICAgICAgIGZ1bmN0aW9uKG9iamVjdCkgew0KICAgICAgICAgIG5faWRzIDwtIGxlbmd0aChvYmplY3QkaWRzKQ0KDQogICAgICAgICAgc2FtcGxlZF9wb3NpdGlvbnMgPC0gc2FtcGxlLmludCgNCiAgICAgICAgICAgIG4gPSBuX2lkcywNCiAgICAgICAgICAgIHNpemUgPSBuX2lkcywNCiAgICAgICAgICAgIHJlcGxhY2UgPSBUUlVFDQogICAgICAgICAgKQ0KDQogICAgICAgICAgdGFidWxhdGUoDQogICAgICAgICAgICBzYW1wbGVkX3Bvc2l0aW9ucywNCiAgICAgICAgICAgIG5iaW5zID0gbl9pZHMNCiAgICAgICAgICApDQogICAgICAgIH0NCiAgICAgICkNCg0KICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcygNCiAgICAgICAgcHJlcGFyZWQgPSBwcmVwYXJlZCwNCiAgICAgICAgY2x1c3Rlcl93ZWlnaHRzID0gY2x1c3Rlcl93ZWlnaHRzDQogICAgICApDQoNCiAgICAgIGNvbmRpdGlvbl9yZXN1bHRzW1tiXV0gPC0NCiAgICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyRjdWVfaW1wb3J0YW5jZSAlPiUNCiAgICAgICAgc2VsZWN0KA0KICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlLA0KICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQogICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UNCiAgICAgICAgKSAlPiUNCiAgICAgICAgbXV0YXRlKA0KICAgICAgICAgIGJvb3RzdHJhcF9yZXBsaWNhdGlvbiA9IGIsDQogICAgICAgICAgLmJlZm9yZSA9IDENCiAgICAgICAgKQ0KDQogICAgICBzbG9wZV9tYXRyaXhbYiwgXSA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfc2xvcGVzKA0KICAgICAgICBib290c3RyYXBfZXN0aW1hdGVzJGN1ZV9pbXBvcnRhbmNlDQogICAgICApDQoNCiAgICAgIGlmICgNCiAgICAgICAgcHJvZ3Jlc3NfZXZlcnkgPiAwICYmDQogICAgICAgIChiICUlIHByb2dyZXNzX2V2ZXJ5ID09IDAgfHwgYiA9PSBCKQ0KICAgICAgKSB7DQogICAgICAgIG1lc3NhZ2UoIkJvb3RzdHJhcDogIiwgYiwgIi8iLCBCKQ0KICAgICAgfQ0KICAgIH0NCg0KICAgIGxpc3QoDQogICAgICBjb25kaXRpb25fZXN0aW1hdGVzID0gYmluZF9yb3dzKA0KICAgICAgICBjb25kaXRpb25fcmVzdWx0cw0KICAgICAgKSwNCiAgICAgIHNsb3BlcyA9IGFzX3RpYmJsZSgNCiAgICAgICAgc2xvcGVfbWF0cml4DQogICAgICApICU+JQ0KICAgICAgICBtdXRhdGUoDQogICAgICAgICAgYm9vdHN0cmFwX3JlcGxpY2F0aW9uID0gcm93X251bWJlcigpLA0KICAgICAgICAgIC5iZWZvcmUgPSAxDQogICAgICAgICkNCiAgICApDQogIH0NCg0KICBzdW1tYXJpc2VfY29uZGl0aW9uX2ludGVydmFscyA8LSBmdW5jdGlvbigNCiAgICAgIG9ic2VydmVkX2N1ZV9pbXBvcnRhbmNlLA0KICAgICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzDQogICkgew0KICAgIHN0YXRpc3RpY3MgPC0gYygNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiDQogICAgKQ0KDQogICAgb2JzZXJ2ZWRfbG9uZyA8LSBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgYWxsX29mKHN0YXRpc3RpY3MpDQogICAgICApICU+JQ0KICAgICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgICBjb2xzID0gYWxsX29mKHN0YXRpc3RpY3MpLA0KICAgICAgICBuYW1lc190byA9ICJzdGF0aXN0aWMiLA0KICAgICAgICB2YWx1ZXNfdG8gPSAiZXN0aW1hdGUiDQogICAgICApDQoNCiAgICBib290c3RyYXBfbG9uZyA8LSBib290c3RyYXBfY29uZGl0aW9uX3Jlc3VsdHMgJT4lDQogICAgICBwaXZvdF9sb25nZXIoDQogICAgICAgIGNvbHMgPSBhbGxfb2Yoc3RhdGlzdGljcyksDQogICAgICAgIG5hbWVzX3RvID0gInN0YXRpc3RpYyIsDQogICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSINCiAgICAgICkgJT4lDQogICAgICBncm91cF9ieSgNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgc3RhdGlzdGljDQogICAgICApICU+JQ0KICAgICAgc3VtbWFyaXNlKA0KICAgICAgICBjb25mX2xvdyA9IHNhZmVfcXVhbnRpbGUoDQogICAgICAgICAgdmFsdWUsDQogICAgICAgICAgMC4wMjUNCiAgICAgICAgKSwNCiAgICAgICAgY29uZl9oaWdoID0gc2FmZV9xdWFudGlsZSgNCiAgICAgICAgICB2YWx1ZSwNCiAgICAgICAgICAwLjk3NQ0KICAgICAgICApLA0KICAgICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgICApDQoNCiAgICBvYnNlcnZlZF9sb25nICU+JQ0KICAgICAgbGVmdF9qb2luKA0KICAgICAgICBib290c3RyYXBfbG9uZywNCiAgICAgICAgYnkgPSBjKA0KICAgICAgICAgICJwYXJ0eV9uIiwNCiAgICAgICAgICAic3RhdGlzdGljIg0KICAgICAgICApDQogICAgICApDQogIH0NCg0KICBzdW1tYXJpc2Vfc2xvcGVfaW5mZXJlbmNlIDwtIGZ1bmN0aW9uKA0KICAgICAgb2JzZXJ2ZWRfc2xvcGVzLA0KICAgICAgYm9vdHN0cmFwX3Nsb3Blcw0KICApIHsNCiAgICBzdGF0aXN0aWNfbmFtZXMgPC0gbmFtZXMob2JzZXJ2ZWRfc2xvcGVzKQ0KDQogICAgbWFwX2RmcigNCiAgICAgIHN0YXRpc3RpY19uYW1lcywNCiAgICAgIGZ1bmN0aW9uKHN0YXRpc3RpY19uYW1lKSB7DQogICAgICAgIGJvb3RzdHJhcF92YWx1ZXMgPC0gYm9vdHN0cmFwX3Nsb3Blc1tbc3RhdGlzdGljX25hbWVdXQ0KICAgICAgICBib290c3RyYXBfdmFsdWVzIDwtIGJvb3RzdHJhcF92YWx1ZXNbDQogICAgICAgICAgaXMuZmluaXRlKGJvb3RzdHJhcF92YWx1ZXMpDQogICAgICAgIF0NCg0KICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPC0gY2FzZV93aGVuKA0KICAgICAgICAgIHN0YXRpc3RpY19uYW1lID09DQogICAgICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIgfiAibmVnYXRpdmUiLA0KICAgICAgICAgIHN0YXRpc3RpY19uYW1lICVpbiUgYygNCiAgICAgICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiLA0KICAgICAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiDQogICAgICAgICAgKSB+ICJwb3NpdGl2ZSIsDQogICAgICAgICAgVFJVRSB+ICJub25lIg0KICAgICAgICApDQoNCiAgICAgICAgYW5hbHlzaXNfcm9sZSA8LSBjYXNlX3doZW4oDQogICAgICAgICAgc3RhdGlzdGljX25hbWUgJWluJSBjKA0KICAgICAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiLA0KICAgICAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiDQogICAgICAgICAgKSB+ICJleHBsb3JhdG9yeV9jaG9pY2Vfc2V0X2FkanVzdGVkIiwNCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiB+DQogICAgICAgICAgICAiZGVyaXZlZF9yZWxhdGl2ZV9zaGFyZSIsDQogICAgICAgICAgVFJVRSB+ICJtYW51c2NyaXB0X3ByaW1hcnlfdW5hZGp1c3RlZCINCiAgICAgICAgKQ0KDQogICAgICAgIGVzdGltYXRlIDwtIHVubmFtZSgNCiAgICAgICAgICBvYnNlcnZlZF9zbG9wZXNbW3N0YXRpc3RpY19uYW1lXV0NCiAgICAgICAgKQ0KDQogICAgICAgIHRpYmJsZSgNCiAgICAgICAgICBzdHVkeSA9ICJTdHVkeSAxIiwNCiAgICAgICAgICBzdGF0aXN0aWMgPSBzdGF0aXN0aWNfbmFtZSwNCiAgICAgICAgICBlc3RpbWF0ZSA9IGVzdGltYXRlLA0KICAgICAgICAgIGNvbmZfbG93ID0gc2FmZV9xdWFudGlsZSgNCiAgICAgICAgICAgIGJvb3RzdHJhcF92YWx1ZXMsDQogICAgICAgICAgICAwLjAyNQ0KICAgICAgICAgICksDQogICAgICAgICAgY29uZl9oaWdoID0gc2FmZV9xdWFudGlsZSgNCiAgICAgICAgICAgIGJvb3RzdHJhcF92YWx1ZXMsDQogICAgICAgICAgICAwLjk3NQ0KICAgICAgICAgICksDQogICAgICAgICAgcF92YWx1ZV90d29fc2lkZWQgPQ0KICAgICAgICAgICAgYm9vdHN0cmFwX3R3b19zaWRlZF9wKA0KICAgICAgICAgICAgICBib290c3RyYXBfdmFsdWVzDQogICAgICAgICAgICApLA0KICAgICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9IGV4cGVjdGVkX2RpcmVjdGlvbiwNCiAgICAgICAgICBhbmFseXNpc19yb2xlID0gYW5hbHlzaXNfcm9sZSwNCiAgICAgICAgICBlc3RpbWF0ZV9pbl9leHBlY3RlZF9kaXJlY3Rpb24gPSBjYXNlX3doZW4oDQogICAgICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gInBvc2l0aXZlIiB+IGVzdGltYXRlID4gMCwNCiAgICAgICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9PSAibmVnYXRpdmUiIH4gZXN0aW1hdGUgPCAwLA0KICAgICAgICAgICAgVFJVRSB+IE5BDQogICAgICAgICAgKQ0KICAgICAgICApDQogICAgICB9DQogICAgKQ0KICB9DQoNCiAgcmVsYXRpdmVfY3VlX3ByZXBhcmVkIDwtIHByZXBhcmVfcmVsYXRpdmVfY3VlX2FuYWx5c2lzKA0KICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwNCiAgICBjdWVfbWFwID0gcmVsYXRpdmVfY3VlX21hcA0KICApDQoNCiAgcmVsYXRpdmVfY3VlX29ic2VydmVkIDwtIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9pbmRpY2VzKA0KICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkDQogICkNCg0KICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzIDwtIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMoDQogICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRtYXJnaW5hbF9tZWFucywNCiAgICAic3R1ZHkxX3JlbGF0aXZlX2N1ZV9tYXJnaW5hbF9tZWFucy5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRhdHRyaWJ1dGVfaW1wb3J0YW5jZSwNCiAgICAic3R1ZHkxX3JlbGF0aXZlX2N1ZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRjdWVfaW1wb3J0YW5jZSwNCiAgICAic3R1ZHkxX3JlbGF0aXZlX2N1ZV9pbXBvcnRhbmNlX2FuZF93ZWlnaHQuY3N2Ig0KICApDQoNCiAgcmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlIDwtIGZpbGUucGF0aCgNCiAgICBvdXRwdXRfZGlyLA0KICAgIHBhc3RlMCgNCiAgICAgICJzdHVkeTFfcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXBfIiwNCiAgICAgIHVuaWZpZWRfY29uZmlnJGN1ZV9pbXBvcnRhbmNlX21ldHJpY192ZXJzaW9uLA0KICAgICAgIl9CIiwNCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiwNCiAgICAgICIuY3N2Ig0KICAgICkNCiAgKQ0KDQogIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlIDwtIGZpbGUucGF0aCgNCiAgICBvdXRwdXRfZGlyLA0KICAgIHBhc3RlMCgNCiAgICAgICJzdHVkeTFfcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcF8iLA0KICAgICAgdW5pZmllZF9jb25maWckY3VlX2ltcG9ydGFuY2VfbWV0cmljX3ZlcnNpb24sDQogICAgICAiX0IiLA0KICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLA0KICAgICAgIi5jc3YiDQogICAgKQ0KICApDQoNCiAgdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCA8LQ0KICAgICFyZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwICYmDQogICAgZmlsZS5leGlzdHMocmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlKSAmJg0KICAgIGZpbGUuZXhpc3RzKHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlKQ0KDQogIGlmICh1c2Vfc2F2ZWRfcmVsYXRpdmVfYm9vdHN0cmFwKSB7DQogICAgbWVzc2FnZSgiQm9vdHN0cmFwIGNhY2hlIikNCg0KICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwIDwtIHJlYWRyOjpyZWFkX2NzdigNCiAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9ib290c3RyYXBfZmlsZSwNCiAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UNCiAgICApDQoNCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwIDwtIHJlYWRyOjpyZWFkX2NzdigNCiAgICAgIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlLA0KICAgICAgc2hvd19jb2xfdHlwZXMgPSBGQUxTRQ0KICAgICkNCg0KICAgIHNhdmVkX0JfY29uZGl0aW9uIDwtIG5fZGlzdGluY3QoDQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24NCiAgICApDQogICAgc2F2ZWRfQl9zbG9wZSA8LSBuX2Rpc3RpbmN0KA0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24NCiAgICApDQoNCiAgICBpZiAoDQogICAgICBzYXZlZF9CX2NvbmRpdGlvbiAhPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgfHwNCiAgICAgIHNhdmVkX0Jfc2xvcGUgIT0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CDQogICAgKSB7DQogICAgICBtZXNzYWdlKCJCb290c3RyYXAgY2FjaGUiKQ0KICAgICAgdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCA8LSBGQUxTRQ0KICAgIH0NCiAgfQ0KDQogIGlmICghdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCkgew0KICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAgPC0gcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAoDQogICAgICBwcmVwYXJlZCA9IHJlbGF0aXZlX2N1ZV9wcmVwYXJlZCwNCiAgICAgIEIgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IsDQogICAgICBzZWVkID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkLA0KICAgICAgcHJvZ3Jlc3NfZXZlcnkgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3Byb2dyZXNzX2V2ZXJ5DQogICAgKQ0KDQogICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAgPC0NCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAkY29uZGl0aW9uX2VzdGltYXRlcw0KDQogICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCA8LQ0KICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCRzbG9wZXMNCg0KICAgIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCwNCiAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9ib290c3RyYXBfZmlsZQ0KICAgICkNCg0KICAgIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwLA0KICAgICAgcmVsYXRpdmVfc2xvcGVfYm9vdHN0cmFwX2ZpbGUNCiAgICApDQogIH0NCg0KICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyA8LSBzdW1tYXJpc2VfY29uZGl0aW9uX2ludGVydmFscygNCiAgICBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsDQogICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwDQogICkNCg0KICByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlIDwtIHN1bW1hcmlzZV9zbG9wZV9pbmZlcmVuY2UoDQogICAgb2JzZXJ2ZWRfc2xvcGVzID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZF9zbG9wZXMsDQogICAgYm9vdHN0cmFwX3Nsb3BlcyA9DQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzLA0KICAgICJzdHVkeTFfcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlLA0KICAgICJzdHVkeTFfcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZS5jc3YiDQogICkNCg0KICByZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQgPC0gcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSAlPiUNCiAgICBmaWx0ZXIoDQogICAgICBzdGF0aXN0aWMgPT0NCiAgICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSINCiAgICApDQoNCiAgY2F0KCJcblN0dWR5IDHvvJrnm7jlr77mr5Tph43jga7nt5rlvaLlgr7lkJFcbiIpDQogIHByaW50KHJlbGF0aXZlX2N1ZV9wcmltYXJ5X3Jlc3VsdCkNCg0KDQogIHJlbGF0aXZlX3hfb2Zmc2V0IDwtIDAuMDc1DQoNCiAgcmVsYXRpdmVfcGFuZWxfYV9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQ0KICAgIGZpbHRlcigNCiAgICAgIHN0YXRpc3RpYyAlaW4lIGMoDQogICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiDQogICAgICApDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBjdWVfZmFtaWx5ID0gcmVjb2RlKA0KICAgICAgICBzdGF0aXN0aWMsDQogICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgPSAi5pS/5YWa5omL44GM44GL44KKIiwNCiAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLntYzmuIjmiYvjgYzjgYvjgooiDQogICAgICApLA0KICAgICAgY3VlX2ZhbWlseSA9IGZhY3RvcigNCiAgICAgICAgY3VlX2ZhbWlseSwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAi5pS/5YWa5omL44GM44GL44KKIiwNCiAgICAgICAgICAi57WM5riI5omL44GM44GL44KKIg0KICAgICAgICApDQogICAgICApLA0KICAgICAgeF9wbG90ID0gY2FzZV93aGVuKA0KICAgICAgICBjdWVfZmFtaWx5ID09ICLmlL/lhZrmiYvjgYzjgYvjgooiIH4NCiAgICAgICAgICBwYXJ0eV9uICsgcmVsYXRpdmVfeF9vZmZzZXQsDQogICAgICAgIGN1ZV9mYW1pbHkgPT0gIue1jOa4iOaJi+OBjOOBi+OCiiIgfg0KICAgICAgICAgIHBhcnR5X24gLSByZWxhdGl2ZV94X29mZnNldCwNCiAgICAgICAgVFJVRSB+IGFzLm51bWVyaWMocGFydHlfbikNCiAgICAgICksDQogICAgICB2YWx1ZV9sYWJlbCA9IHNwcmludGYoDQogICAgICAgICIlLjNmIiwNCiAgICAgICAgZXN0aW1hdGUNCiAgICAgICkNCiAgICApDQoNCiAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQ0KICAgIGZpbHRlcigNCiAgICAgIHN0YXRpc3RpYyA9PQ0KICAgICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIg0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgdmFsdWVfbGFiZWwgPSBzcHJpbnRmKA0KICAgICAgICAiJS4xZiUlIiwNCiAgICAgICAgMTAwICogZXN0aW1hdGUNCiAgICAgICkNCiAgICApDQoNCiAgcmVsYXRpdmVfYWRqdXN0ZWRfbGFiZWxfbWFwIDwtIHJlbGF0aXZlX3BhbmVsX2FfZGF0YSAlPiUNCiAgICBkaXN0aW5jdCgNCiAgICAgIHN0YXRpc3RpYywNCiAgICAgIGN1ZV9mYW1pbHkNCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHN0YXRpc3RpYyA9IHBhc3RlMCgNCiAgICAgICAgc3RhdGlzdGljLA0KICAgICAgICAiX2FkanVzdGVkIg0KICAgICAgKSwNCiAgICAgIGN1ZV9mYW1pbHkgPSBhcy5jaGFyYWN0ZXIoDQogICAgICAgIGN1ZV9mYW1pbHkNCiAgICAgICkNCiAgICApDQoNCiAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWRfZGF0YSA8LSByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyAlPiUNCiAgICBmaWx0ZXIoDQogICAgICBzdGF0aXN0aWMgJWluJSBjKA0KICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsDQogICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgbGVmdF9qb2luKA0KICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfbGFiZWxfbWFwLA0KICAgICAgYnkgPSAic3RhdGlzdGljIg0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgY3VlX2ZhbWlseSA9IGZhY3RvcigNCiAgICAgICAgY3VlX2ZhbWlseSwNCiAgICAgICAgbGV2ZWxzID0gbGV2ZWxzKA0KICAgICAgICAgIHJlbGF0aXZlX3BhbmVsX2FfZGF0YSRjdWVfZmFtaWx5DQogICAgICAgICkNCiAgICAgICksDQogICAgICB4X3Bsb3QgPSBpZl9lbHNlKA0KICAgICAgICBhcy5pbnRlZ2VyKGN1ZV9mYW1pbHkpID09IDFMLA0KICAgICAgICBwYXJ0eV9uICsgcmVsYXRpdmVfeF9vZmZzZXQsDQogICAgICAgIHBhcnR5X24gLSByZWxhdGl2ZV94X29mZnNldA0KICAgICAgKSwNCiAgICAgIHZhbHVlX2xhYmVsID0gc3ByaW50ZigNCiAgICAgICAgIiUuMWYlJSIsDQogICAgICAgIDEwMCAqIGVzdGltYXRlDQogICAgICApDQogICAgKQ0KDQogIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXggPC0gaWYgKA0KICAgICLmlL/lhZrlkI3miYvjgYzjgYvjgooiICVpbiUNCiAgICAgIGxldmVscyhyZWxhdGl2ZV9wYW5lbF9hX2RhdGEkY3VlX2ZhbWlseSkNCiAgKSB7DQogICAgIumBuOaKnuiCoiINCiAgfSBlbHNlIHsNCiAgICAi5pS/5YWaIg0KICB9DQoNCiAgcmVsYXRpdmVfY29uZGl0aW9uX2F4aXNfdGl0bGUgPC0gaWYgKA0KICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXggPT0gIumBuOaKnuiCoiINCiAgKSB7DQogICAgIuaUv+ayu+e1jOa4iOeKtuazgeOBrumBuOaKnuiCouaVsCINCiAgfSBlbHNlIHsNCiAgICAi5pS/5YWa6YG45oqe6IKi5pWwIg0KICB9DQoNCiAgcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5IDwtIGlmICgNCiAgICAuUGxhdGZvcm0kT1MudHlwZSA9PSAid2luZG93cyINCiAgKSB7DQogICAgIll1IEdvdGhpYyINCiAgfSBlbHNlIHsNCiAgICAic2FucyINCiAgfQ0KDQogIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3IDwtIHRoZW1lX2J3KA0KICAgIGJhc2Vfc2l6ZSA9IDEyLA0KICAgIGJhc2VfZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5DQogICkgKw0KICAgIHRoZW1lKA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoDQogICAgICAgIGxpbmV3aWR0aCA9IDAuMzAsDQogICAgICAgIGNvbG9yID0gImdyZXk4OCINCiAgICAgICksDQogICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGxpbmV3aWR0aCA9IDAuNjUsDQogICAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICAgKSwNCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgICApLA0KICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgICApLA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgc2l6ZSA9IDEyLjUsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIGhqdXN0ID0gMA0KICAgICAgKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIHNpemUgPSA5LjUsDQogICAgICAgIGhqdXN0ID0gMCwNCiAgICAgICAgbWFyZ2luID0gbWFyZ2luKA0KICAgICAgICAgIGIgPSA4DQogICAgICAgICkNCiAgICAgICksDQogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwNCiAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gImNlbnRlciIsDQogICAgICBsZWdlbmQua2V5LndpZHRoID0gZ3JpZDo6dW5pdCgNCiAgICAgICAgMS4yNSwNCiAgICAgICAgImNtIg0KICAgICAgKSwNCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKA0KICAgICAgICA4LA0KICAgICAgICAxMCwNCiAgICAgICAgOCwNCiAgICAgICAgOA0KICAgICAgKQ0KICAgICkNCg0KICByZWxhdGl2ZV9wYW5lbF9hIDwtIGdncGxvdCgNCiAgICByZWxhdGl2ZV9wYW5lbF9hX2RhdGEsDQogICAgYWVzKA0KICAgICAgeCA9IHhfcGxvdCwNCiAgICAgIHkgPSBlc3RpbWF0ZSwNCiAgICAgIGdyb3VwID0gY3VlX2ZhbWlseSwNCiAgICAgIGxpbmV0eXBlID0gY3VlX2ZhbWlseQ0KICAgICkNCiAgKSArDQogICAgZ2VvbV9saW5lKA0KICAgICAgbGluZXdpZHRoID0gMC44MCwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXIoDQogICAgICBhZXMoDQogICAgICAgIHltaW4gPSBjb25mX2xvdywNCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaA0KICAgICAgKSwNCiAgICAgIHdpZHRoID0gMC4wNzUsDQogICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9sYWJlbCgNCiAgICAgIGFlcygNCiAgICAgICAgbGFiZWwgPSB2YWx1ZV9sYWJlbA0KICAgICAgKSwNCiAgICAgIHNpemUgPSAzLjU1LA0KICAgICAgZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5LA0KICAgICAgbGFiZWwuc2l6ZSA9IDAsDQogICAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdCgNCiAgICAgICAgMC4xMiwNCiAgICAgICAgImxpbmVzIg0KICAgICAgKSwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIuaUv+WFmuaJi+OBjOOBi+OCiiIgPSAic29saWQiLA0KICAgICAgICAi57WM5riI5omL44GM44GL44KKIiA9ICJkYXNoZWQiDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgYnJlYWtzID0gMjo1LA0KICAgICAgbGFiZWxzID0gcGFzdGUwKA0KICAgICAgICAyOjUsDQogICAgICAgICLmlL/lhZoiDQogICAgICApLA0KICAgICAgbGltaXRzID0gYygNCiAgICAgICAgMS43MiwNCiAgICAgICAgNS4yOA0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX3lfY29udGludW91cygNCiAgICAgIGxhYmVscyA9IGxhYmVsX251bWJlcigNCiAgICAgICAgYWNjdXJhY3kgPSAwLjAwNQ0KICAgICAgKSwNCiAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbigNCiAgICAgICAgbXVsdCA9IGMoDQogICAgICAgICAgMC4wNywNCiAgICAgICAgICAwLjEwDQogICAgICAgICkNCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiQe+8muS4oeaJi+OBjOOBi+OCiuOBrue1tuWvvueahOmHjeimgeW6piIsDQogICAgICBzdWJ0aXRsZSA9ICIiLA0KICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLA0KICAgICAgeSA9ICLmiYvjgYzjgYvjgorph43opoHluqYiLA0KICAgICAgbGluZXR5cGUgPSBOVUxMDQogICAgKSArDQogICAgZ3VpZGVzKA0KICAgICAgbGluZXR5cGUgPSBndWlkZV9sZWdlbmQoDQogICAgICAgIG92ZXJyaWRlLmFlcyA9IGxpc3QoDQogICAgICAgICAgbGluZXdpZHRoID0gMC45MA0KICAgICAgICApDQogICAgICApDQogICAgKSArDQogICAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncNCg0KICByZWxhdGl2ZV9hZGp1c3RlZF9saW5ldHlwZXMgPC0gc2V0TmFtZXMoDQogICAgYygNCiAgICAgICJzb2xpZCIsDQogICAgICAiZGFzaGVkIg0KICAgICksDQogICAgbGV2ZWxzKA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWRfZGF0YSRjdWVfZmFtaWx5DQogICAgKQ0KICApDQoNCiAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQgPC0gZ2dwbG90KA0KICAgIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGEsDQogICAgYWVzKA0KICAgICAgeCA9IHhfcGxvdCwNCiAgICAgIHkgPSBlc3RpbWF0ZSwNCiAgICAgIGdyb3VwID0gY3VlX2ZhbWlseSwNCiAgICAgIGxpbmV0eXBlID0gY3VlX2ZhbWlseQ0KICAgICkNCiAgKSArDQogICAgZ2VvbV9saW5lKA0KICAgICAgbGluZXdpZHRoID0gMC44MCwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXIoDQogICAgICBhZXMoDQogICAgICAgIHltaW4gPSBjb25mX2xvdywNCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaA0KICAgICAgKSwNCiAgICAgIHdpZHRoID0gMC4wNzUsDQogICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9sYWJlbCgNCiAgICAgIGFlcygNCiAgICAgICAgbGFiZWwgPSB2YWx1ZV9sYWJlbA0KICAgICAgKSwNCiAgICAgIHNpemUgPSAzLjU1LA0KICAgICAgZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5LA0KICAgICAgbGFiZWwuc2l6ZSA9IDAsDQogICAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdCgNCiAgICAgICAgMC4xMiwNCiAgICAgICAgImxpbmVzIg0KICAgICAgKSwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgdmFsdWVzID0gcmVsYXRpdmVfYWRqdXN0ZWRfbGluZXR5cGVzDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgYnJlYWtzID0gMjo1LA0KICAgICAgbGFiZWxzID0gcGFzdGUwKA0KICAgICAgICAyOjUsDQogICAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXgNCiAgICAgICksDQogICAgICBsaW1pdHMgPSBjKA0KICAgICAgICAxLjcyLA0KICAgICAgICA1LjI4DQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICAgbGFiZWxzID0gbGFiZWxfcGVyY2VudCgNCiAgICAgICAgYWNjdXJhY3kgPSAxDQogICAgICApLA0KICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKA0KICAgICAgICBtdWx0ID0gYygNCiAgICAgICAgICAwLjA3LA0KICAgICAgICAgIDAuMTANCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICJB77ya6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqmIiwNCiAgICAgIHN1YnRpdGxlID0NCiAgICAgICAgIuacquiqv+aVtOmHjeimgeW6piDDtyDlubPlnYfpgbjmip7norrnjofvvIgx77yP6YG45oqe6IKi5pWw77yJIiwNCiAgICAgIHggPSByZWxhdGl2ZV9jb25kaXRpb25fYXhpc190aXRsZSwNCiAgICAgIHkgPSAi5bmz5Z2H6YG45oqe56K6546H44Gr5a++44GZ44KL5rC05rqW6ZaT5beuIiwNCiAgICAgIGxpbmV0eXBlID0gTlVMTA0KICAgICkgKw0KICAgIGd1aWRlcygNCiAgICAgIGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKA0KICAgICAgICBvdmVycmlkZS5hZXMgPSBsaXN0KA0KICAgICAgICAgIGxpbmV3aWR0aCA9IDAuOTANCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkgKw0KICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3DQoNCiAgcmVsYXRpdmVfYl9yYW5nZSA8LSByYW5nZSgNCiAgICBjKA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhJGNvbmZfbG93LA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhJGNvbmZfaGlnaCwNCiAgICAgIDAuNQ0KICAgICksDQogICAgbmEucm0gPSBUUlVFDQogICkNCg0KICByZWxhdGl2ZV9iX3BhZGRpbmcgPC0gbWF4KA0KICAgIDAuMDI1LA0KICAgIDAuMTAgKiBkaWZmKHJlbGF0aXZlX2JfcmFuZ2UpDQogICkNCg0KICByZWxhdGl2ZV9iX2xvd2VyIDwtIG1heCgNCiAgICAwLA0KICAgIGZsb29yKA0KICAgICAgMjAgKg0KICAgICAgICAocmVsYXRpdmVfYl9yYW5nZVsxXSAtIHJlbGF0aXZlX2JfcGFkZGluZykNCiAgICApIC8gMjANCiAgKQ0KDQogIHJlbGF0aXZlX2JfdXBwZXIgPC0gbWluKA0KICAgIDEsDQogICAgY2VpbGluZygNCiAgICAgIDIwICoNCiAgICAgICAgKHJlbGF0aXZlX2JfcmFuZ2VbMl0gKyByZWxhdGl2ZV9iX3BhZGRpbmcpDQogICAgKSAvIDIwDQogICkNCg0KICBpZiAocmVsYXRpdmVfYl9sb3dlciA+PSByZWxhdGl2ZV9iX3VwcGVyKSB7DQogICAgcmVsYXRpdmVfYl9sb3dlciA8LSBtYXgoDQogICAgICAwLA0KICAgICAgcmVsYXRpdmVfYl9sb3dlciAtIDAuMDUNCiAgICApDQogICAgcmVsYXRpdmVfYl91cHBlciA8LSBtaW4oDQogICAgICAxLA0KICAgICAgcmVsYXRpdmVfYl91cHBlciArIDAuMDUNCiAgICApDQogIH0NCg0KICByZWxhdGl2ZV9wYW5lbF9iIDwtIGdncGxvdCgNCiAgICByZWxhdGl2ZV9wYW5lbF9iX2RhdGEsDQogICAgYWVzKA0KICAgICAgeCA9IHBhcnR5X24sDQogICAgICB5ID0gZXN0aW1hdGUNCiAgICApDQogICkgKw0KICAgIGdlb21faGxpbmUoDQogICAgICB5aW50ZXJjZXB0ID0gMC41LA0KICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNTUsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX2xpbmUoDQogICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9lcnJvcmJhcigNCiAgICAgIGFlcygNCiAgICAgICAgeW1pbiA9IGNvbmZfbG93LA0KICAgICAgICB5bWF4ID0gY29uZl9oaWdoDQogICAgICApLA0KICAgICAgd2lkdGggPSAwLjA3NSwNCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX2xhYmVsKA0KICAgICAgYWVzKA0KICAgICAgICBsYWJlbCA9IHZhbHVlX2xhYmVsDQogICAgICApLA0KICAgICAgc2l6ZSA9IDMuNTUsDQogICAgICBmYW1pbHkgPSByZWxhdGl2ZV9maWd1cmVfZm9udF9mYW1pbHksDQogICAgICBsYWJlbC5zaXplID0gMCwNCiAgICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KA0KICAgICAgICAwLjEyLA0KICAgICAgICAibGluZXMiDQogICAgICApLA0KICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgICBicmVha3MgPSAyOjUsDQogICAgICBsYWJlbHMgPSBwYXN0ZTAoDQogICAgICAgIDI6NSwNCiAgICAgICAgIuaUv+WFmiINCiAgICAgICksDQogICAgICBsaW1pdHMgPSBjKA0KICAgICAgICAxLjcyLA0KICAgICAgICA1LjI4DQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICAgYnJlYWtzID0gc2VxKA0KICAgICAgICByZWxhdGl2ZV9iX2xvd2VyLA0KICAgICAgICByZWxhdGl2ZV9iX3VwcGVyLA0KICAgICAgICBieSA9IDAuMDUNCiAgICAgICksDQogICAgICBsYWJlbHMgPSBsYWJlbF9wZXJjZW50KA0KICAgICAgICBhY2N1cmFjeSA9IDENCiAgICAgICksDQogICAgICBleHBhbmQgPSBleHBhbnNpb24oDQogICAgICAgIG11bHQgPSBjKA0KICAgICAgICAgIDAuMDUsDQogICAgICAgICAgMC4wOA0KICAgICAgICApDQogICAgICApDQogICAgKSArDQogICAgY29vcmRfY2FydGVzaWFuKA0KICAgICAgeWxpbSA9IGMoDQogICAgICAgIHJlbGF0aXZlX2JfbG93ZXIsDQogICAgICAgIHJlbGF0aXZlX2JfdXBwZXINCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiQu+8muebuOWvvueahOOBquaUv+WFmuaJi+OBjOOBi+OCiuOBruavlOmHjSIsDQogICAgICBzdWJ0aXRsZSA9DQogICAgICAgICLmlL/lhZrmiYvjgYzjgYvjgorph43opoHluqYgw7fvvIjmlL/lhZrmiYvjgYzjgYvjgorph43opoHluqbvvIvntYzmuIjmiYvjgYzjgYvjgorph43opoHluqbvvIkiLA0KICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLA0KICAgICAgeSA9ICLnm7jlr77nmoTjgarmlL/lhZrmiYvjgYzjgYvjgormr5Tph40iDQogICAgKSArDQogICAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncgKw0KICAgIHRoZW1lKA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiDQogICAgKQ0KDQogIHJlbGF0aXZlX3BhbmVsX2MgPC0gcmVsYXRpdmVfcGFuZWxfYiArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gcGFzdGUwKA0KICAgICAgICAiQu+8muebuOWvvueahOOBqiIsDQogICAgICAgIGxldmVscyhyZWxhdGl2ZV9wYW5lbF9hX2RhdGEkY3VlX2ZhbWlseSlbMV0sDQogICAgICAgICLjga7mr5Tph40iDQogICAgICApDQogICAgKQ0KDQogIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAgPC0gKA0KICAgIHJlbGF0aXZlX3BhbmVsX2EgfA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYg0KICApICsNCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KA0KICAgICAgd2lkdGhzID0gYygNCiAgICAgICAgMSwNCiAgICAgICAgMQ0KICAgICAgKQ0KICAgICkNCg0KICBwcmludCgNCiAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwDQogICkNCg0KICBzYXZlX3Bsb3QoDQogICAgImZpZ19zdHVkeTFfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wbmciLA0KICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsDQogICAgd2lkdGggPSAxMS4yLA0KICAgIGhlaWdodCA9IDUuNCwNCiAgICBkcGkgPSA0MDANCiAgKQ0KDQogIGdnc2F2ZSgNCiAgICBmaWxlbmFtZSA9IGZpbGUucGF0aCgNCiAgICAgIG91dHB1dF9kaXIsDQogICAgICAiZmlnX3N0dWR5MV9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBkZiINCiAgICApLA0KICAgIHBsb3QgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLA0KICAgIHdpZHRoID0gMTEuMiwNCiAgICBoZWlnaHQgPSA1LjQsDQogICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsDQogICAgYmcgPSAid2hpdGUiDQogICkNCg0KICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwIDwtICgNCiAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZCB8DQogICAgICByZWxhdGl2ZV9wYW5lbF9jDQogICkgKw0KICAgIHBhdGNod29yazo6cGxvdF9sYXlvdXQoDQogICAgICB3aWR0aHMgPSBjKA0KICAgICAgICAxLA0KICAgICAgICAxDQogICAgICApDQogICAgKQ0KDQogIHByaW50KA0KICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanANCiAgKQ0KDQogIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViIDwtIHBhc3RlMCgNCiAgICAiZmlnX3N0dWR5IiwNCiAgICBzdHJpbmdyOjpzdHJfZXh0cmFjdCgNCiAgICAgIHN0dWR5X2xhYmVsLA0KICAgICAgIlsxMjNdIg0KICAgICksDQogICAgIl9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYnciDQogICkNCg0KICBzYXZlX3Bsb3QoDQogICAgcGFzdGUwKA0KICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIsDQogICAgICAiLnBuZyINCiAgICApLA0KICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAsDQogICAgd2lkdGggPSAxMS4yLA0KICAgIGhlaWdodCA9IDUuNCwNCiAgICBkcGkgPSA0MDANCiAgKQ0KDQogIGdnc2F2ZSgNCiAgICBmaWxlbmFtZSA9IGZpbGUucGF0aCgNCiAgICAgIG91dHB1dF9kaXIsDQogICAgICBwYXN0ZTAoDQogICAgICAgIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViLA0KICAgICAgICAiLnBkZiINCiAgICAgICkNCiAgICApLA0KICAgIHBsb3QgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwLA0KICAgIHdpZHRoID0gMTEuMiwNCiAgICBoZWlnaHQgPSA1LjQsDQogICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsDQogICAgYmcgPSAid2hpdGUiDQogICkNCg0KICByZWxhdGl2ZV9jdWVfcmVzdWx0cyA8LSBsaXN0KA0KICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkLA0KICAgIG1hcmdpbmFsX21lYW5zID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRtYXJnaW5hbF9tZWFucywNCiAgICBhdHRyaWJ1dGVfaW1wb3J0YW5jZSA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkYXR0cmlidXRlX2ltcG9ydGFuY2UsDQogICAgY3VlX2ltcG9ydGFuY2UgPQ0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlLA0KICAgIG9ic2VydmVkX3Nsb3BlcyA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzLA0KICAgIGNvbmRpdGlvbl9ib290c3RyYXAgPQ0KICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAsDQogICAgc2xvcGVfYm9vdHN0cmFwID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAsDQogICAgY29uZGl0aW9uX2ludGVydmFscyA9DQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscywNCiAgICBzbG9wZV9pbmZlcmVuY2UgPQ0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSwNCiAgICBwcmltYXJ5X3Jlc3VsdCA9DQogICAgICByZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQsDQogICAgcGxvdHMgPSBsaXN0KA0KICAgICAgYWJzb2x1dGVfaW1wb3J0YW5jZSA9IHJlbGF0aXZlX3BhbmVsX2EsDQogICAgICBjaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2UgPQ0KICAgICAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZCwNCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodCA9IHJlbGF0aXZlX3BhbmVsX2IsDQogICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFuZWxfYyA9DQogICAgICAgIHJlbGF0aXZlX3BhbmVsX2MsDQogICAgICBjb21iaW5lZCA9IGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsDQogICAgICBjb21iaW5lZF93aXRoX2Nob2ljZV9zZXRfYWRqdXN0bWVudCA9DQogICAgICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanANCiAgICApDQogICkNCg0KICBzYXZlUkRTKA0KICAgIHJlbGF0aXZlX2N1ZV9yZXN1bHRzLA0KICAgIGZpbGUgPSBmaWxlLnBhdGgoDQogICAgICBvdXRwdXRfZGlyLA0KICAgICAgInN0dWR5MV9yZWxhdGl2ZV9jdWVfcmVzdWx0cy5yZHMiDQogICAgKQ0KICApDQoNCg0KICBzYXZlUkRTKA0KICAgIGxpc3QoDQogICAgICBzZXR0aW5ncyA9IGxpc3QoDQogICAgICAgIHJlcXVpcmVfaW5pdGlhbF9jb25zZW50ID0gcmVxdWlyZV9pbml0aWFsX2NvbnNlbnQsDQogICAgICAgIHJlcXVpcmVfZmluYWxfY29uc2VudCA9IHJlcXVpcmVfZmluYWxfY29uc2VudCwNCiAgICAgICAgcmVxdWlyZV9hdHRlbnRpb25fY2hlY2sgPSByZXF1aXJlX2F0dGVudGlvbl9jaGVjaywNCiAgICAgICAgcmVxdWlyZV9tYW5pcHVsYXRpb25fY2hlY2sgPSByZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjaw0KICAgICAgKSwNCiAgICAgIHNhbXBsZV9mbG93ID0gc2FtcGxlX2Zsb3csDQogICAgICBuX2J5X3BhcnR5ID0gbl9ieV9wYXJ0eSwNCiAgICAgIHZhbGlkX2lkcyA9IHZhbGlkX2lkcywNCiAgICAgIGNvbmpvaW50X2FsbCA9IGNvbmpvaW50X2FsbCwNCiAgICAgIGNvbmpvaW50X2FsbF9tID0gY29uam9pbnRfYWxsX20sDQogICAgICBjb3Zhcl9pZCA9IGNvdmFyX2lkLA0KICAgICAgbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YgPSBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiwNCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX2NvdiA9IG1vZGVsc19ieV9wYXJ0eV9uX2NvdiwNCiAgICAgIG1faW50ZXJhY3Rpb24gPSBtX2ludGVyYWN0aW9uLA0KICAgICAgbW9kZWxzX2Nsb2dpdF9ub2NvdiA9IG1vZGVsc19jbG9naXRfbm9jb3YsDQogICAgICByZWxhdGl2ZV9jdWUgPSByZWxhdGl2ZV9jdWVfcmVzdWx0cywNCiAgICAgIHBsb3RzID0gbGlzdCgNCiAgICAgICAgYW1jZV9jb3YgPSBwX2FtY2VfY292X21haW4sDQogICAgICAgIGFtY2Vfbm9jb3YgPSBwX2FtY2Vfbm9jb3ZfYXBwZW5kaXgsDQogICAgICAgIGludGVyYWN0aW9uID0gcF9pbnRlcmFjdGlvbiwNCiAgICAgICAgaGVhdG1hcCA9IHBfaGVhdF9hbWNlLA0KICAgICAgICBoZWF0bWFwX3JhbmsgPSBwX2hlYXRfYW1jZV9yYW5rLA0KICAgICAgICBjbG9naXRfb2Rkc19yYXRpbyA9IHBfY2xvZ2l0X29yLA0KICAgICAgICByZWxhdGl2ZV9jdWVfd2VpZ2h0ID0gZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCwNCiAgICAgICAgcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkID0NCiAgICAgICAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwDQogICAgICApDQogICAgKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJzdHVkeTFfYW5hbHlzaXNfb2JqZWN0cy5yZHMiKQ0KICApDQoNCiAgY2FwdHVyZS5vdXRwdXQoDQogICAgc2Vzc2lvbkluZm8oKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJzZXNzaW9uSW5mby50eHQiKQ0KICApDQoNCiAgY2F0KCINCkRvbmU6ICIsIG5vcm1hbGl6ZVBhdGgob3V0cHV0X2RpciksICINCiIsIHNlcCA9ICIiKQ0KDQogIGVudmlyb25tZW50KCkNCn0pDQoNCg0KYGBgDQoNCiMjIEEuMyDlrp/pqJMy77ya5pys5paH44Gu5ZuzNg0KDQpgYGB7ciBhMy1zdHVkeTItY29kZSwgZXZhbD1wYXJhbXMkcnVuX2FuYWx5c2lzLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQ0KIyDmnKzmlofjgrPjg7zjg4kNCnN0dWR5Ml9lbnYgPC0gbG9jYWwoew0KcmVxdWlyZWRfcGFja2FnZXMgPC0gYygNCiAgICAiZHBseXIiLA0KICAgICJ0aWR5ciIsDQogICAgInN0cmluZ3IiLA0KICAgICJwdXJyciIsDQogICAgInJlYWRyIiwNCiAgICAiZml4ZXN0IiwNCiAgICAidGliYmxlIiwNCiAgICAiZm9yY2F0cyIsDQogICAgImdncGxvdDIiLA0KICAgICJzY2FsZXMiLA0KICAgICJzdXJ2aXZhbCIsDQogICAgImdndGV4dCIsDQogICAgInBhdGNod29yayINCiAgKQ0KDQogIG1pc3NpbmdfcGFja2FnZXMgPC0gcmVxdWlyZWRfcGFja2FnZXNbDQogICAgIXZhcHBseShyZXF1aXJlZF9wYWNrYWdlcywgcmVxdWlyZU5hbWVzcGFjZSwgbG9naWNhbCgxKSwgcXVpZXRseSA9IFRSVUUpDQogIF0NCg0KICBpZiAobGVuZ3RoKG1pc3NpbmdfcGFja2FnZXMpID4gMCkgew0KICAgIHN0b3AoIk5vIHBhY2thZ2VzIikNCiAgfQ0KDQogIGxpYnJhcnkoZHBseXIpDQogIGxpYnJhcnkodGlkeXIpDQogIGxpYnJhcnkoc3RyaW5ncikNCiAgbGlicmFyeShwdXJycikNCiAgbGlicmFyeShyZWFkcikNCiAgbGlicmFyeShmaXhlc3QpDQogIGxpYnJhcnkodGliYmxlKQ0KICBsaWJyYXJ5KGZvcmNhdHMpDQogIGxpYnJhcnkoZ2dwbG90MikNCiAgbGlicmFyeShzY2FsZXMpDQogIGxpYnJhcnkoc3Vydml2YWwpDQogIGxpYnJhcnkocGF0Y2h3b3JrKQ0KDQogIGRhdGFfZmlsZSA8LSB1bmlmaWVkX2NvbmZpZyRzdHVkeTIkZGF0YV9maWxlDQogIG91dHB1dF9kaXIgPC0gdW5pZmllZF9jb25maWckc3R1ZHkyJG91dHB1dF9kaXINCg0KICBkaXIuY3JlYXRlKG91dHB1dF9kaXIsIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQ0KDQogIHJlcXVpcmVfaW5pdGlhbF9jb25zZW50IDwtIFRSVUUNCiAgcmVxdWlyZV9maW5hbF9jb25zZW50IDwtIFRSVUUNCiAgZmluYWxfY29uc2VudF92YXIgPC0gIlE4LjEiDQoNCiAgcmVxdWlyZV9hdHRlbnRpb25fY2hlY2sgPC0gVFJVRQ0KICByZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjayA8LSBUUlVFDQoNCiAgYXR0ZW50aW9uX2NoZWNrX3ZhciA8LSAiUTI1LjFfMTEiDQogIGF0dGVudGlvbl9jaGVja19jb3JyZWN0IDwtICIzIg0KDQogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiA8LSB1bmlmaWVkX2NvbmZpZyRyZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0INCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkIDwtIHVuaWZpZWRfY29uZmlnJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCArIDJMDQogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkgPC0gdW5pZmllZF9jb25maWckcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeQ0KDQogIHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAgPC0gdW5pZmllZF9jb25maWckcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcA0KDQoNCiAgbm9ybV90ZXh0IDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4ICU+JQ0KICAgICAgYXMuY2hhcmFjdGVyKCkgJT4lDQogICAgICBzdHJfc3F1aXNoKCkgJT4lDQogICAgICBzdHJfcmVwbGFjZV9hbGwoIu+9niIsICJ+IikgJT4lDQogICAgICBzdHJfcmVwbGFjZV9hbGwoIuOAnCIsICJ+IikNCiAgfQ0KDQogIGFzX251bSA8LSBmdW5jdGlvbih4KSB7DQogICAgc3VwcHJlc3NXYXJuaW5ncyhyZWFkcjo6cGFyc2VfbnVtYmVyKG5vcm1fdGV4dCh4KSkpDQogIH0NCg0KICBpc19yZXNwb25zZV9jb2RlIDwtIGZ1bmN0aW9uKHgsIGNvZGUpIHsNCiAgICB4X25vcm0gPC0gbm9ybV90ZXh0KHgpDQogICAgY29kZV9jaHIgPC0gYXMuY2hhcmFjdGVyKGNvZGUpDQoNCiAgICB4X25vcm0gPT0gY29kZV9jaHIgfA0KICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCh4X25vcm0sIHBhc3RlMCgiXFwoIiwgY29kZV9jaHIsICJcXCkkIikpDQogIH0NCg0KICBmaXJzdF9leGlzdGluZyA8LSBmdW5jdGlvbihkYXQsIGNhbmRpZGF0ZXMpIHsNCiAgICBvdXQgPC0gY2FuZGlkYXRlc1tjYW5kaWRhdGVzICVpbiUgbmFtZXMoZGF0KV0NCiAgICBpZiAobGVuZ3RoKG91dCkgPT0gMCkgTkFfY2hhcmFjdGVyXyBlbHNlIG91dFsxXQ0KICB9DQoNCiAgZ2V0X3ZhciA8LSBmdW5jdGlvbihkYXQsIGNhbmRpZGF0ZXMpIHsNCiAgICB2IDwtIGZpcnN0X2V4aXN0aW5nKGRhdCwgY2FuZGlkYXRlcykNCiAgICBpZiAoaXMubmEodikpIHsNCiAgICAgIHJlcChOQV9jaGFyYWN0ZXJfLCBucm93KGRhdCkpDQogICAgfSBlbHNlIHsNCiAgICAgIGRhdFtbdl1dDQogICAgfQ0KICB9DQoNCiAgcmVsZXZlbF9pZl9wcmVzZW50IDwtIGZ1bmN0aW9uKHgsIHJlZikgew0KICAgIHggPC0gZmFjdG9yKHgpDQogICAgaWYgKHJlZiAlaW4lIGxldmVscyh4KSkgew0KICAgICAgcmVsZXZlbCh4LCByZWYgPSByZWYpDQogICAgfSBlbHNlIHsNCiAgICAgIHgNCiAgICB9DQogIH0NCg0KICBmYWN0b3JfbWlzcyA8LSBmdW5jdGlvbih4LCBtaXNzID0gIuasoOaQjeODu+eEoeWbnuetlCIpIHsNCiAgICB4IDwtIG5vcm1fdGV4dCh4KQ0KICAgIHhbaXMubmEoeCkgfCB4ID09ICIiIHwgeCA9PSAiTkEiXSA8LSBtaXNzDQogICAgZmFjdG9yKHgpDQogIH0NCg0KICBtZWFuX2ltcHV0ZSA8LSBmdW5jdGlvbih4KSB7DQogICAgeCA8LSBhcy5udW1lcmljKHgpDQogICAgbWlzcyA8LSBhcy5pbnRlZ2VyKGlzLm5hKHgpKQ0KDQogICAgaWYgKGFsbChpcy5uYSh4KSkpIHsNCiAgICAgIHZhbHVlIDwtIHgNCiAgICB9IGVsc2Ugew0KICAgICAgdmFsdWUgPC0gaWZlbHNlKGlzLm5hKHgpLCBtZWFuKHgsIG5hLnJtID0gVFJVRSksIHgpDQogICAgfQ0KDQogICAgbGlzdCh2YWx1ZSA9IHZhbHVlLCBtaXNzID0gbWlzcykNCiAgfQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkgPC0gZnVuY3Rpb24oeCwgZmlsZW5hbWUpIHsNCiAgICByZWFkcjo6d3JpdGVfY3N2KHgsIGZpbGUucGF0aChvdXRwdXRfZGlyLCBmaWxlbmFtZSksIG5hID0gIiIpDQogIH0NCg0KICBzYXZlX3Bsb3QgPC0gZnVuY3Rpb24oZmlsZW5hbWUsIHBsb3QsIHdpZHRoLCBoZWlnaHQsIGRwaSA9IDMwMCkgew0KICAgIGdncGxvdDI6Omdnc2F2ZSgNCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsIGZpbGVuYW1lKSwNCiAgICAgIHBsb3QgPSBwbG90LA0KICAgICAgd2lkdGggPSB3aWR0aCwNCiAgICAgIGhlaWdodCA9IGhlaWdodCwNCiAgICAgIGRwaSA9IGRwaQ0KICAgICkNCiAgfQ0KDQoNCiAgaWYgKCFmaWxlLmV4aXN0cyhkYXRhX2ZpbGUpKSB7DQogICAgc3RvcCgiQ2hlY2sgZGF0YSIpDQogIH0NCg0KICByYXcgPC0gcmVhZHI6OnJlYWRfY3N2KA0KICAgIGRhdGFfZmlsZSwNCiAgICBjb2xfdHlwZXMgPSBjb2xzKC5kZWZhdWx0ID0gY29sX2NoYXJhY3RlcigpKSwNCiAgICBzaG93X2NvbF90eXBlcyA9IEZBTFNFLA0KICAgIG5hbWVfcmVwYWlyID0gIm1pbmltYWwiDQogICkNCg0KDQogIGlmIChyZXF1aXJlX2ZpbmFsX2NvbnNlbnQpIHsNCiAgICBmaW5hbF9jb25zZW50X3ZhciA8LSBkZXRlY3RfZmluYWxfY29uc2VudF9jb2x1bW4oDQogICAgICByYXcgPSByYXcsDQogICAgICBwcmVmZXJyZWRfY2FuZGlkYXRlcyA9IGMoIlE4LjEiLCAiUTkuMSIsICJRMTAuMSIpLA0KICAgICAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkgMiINCiAgICApDQogIH0NCg0KICBpZiAocmVxdWlyZV9hdHRlbnRpb25fY2hlY2spIHsNCiAgICBhdHRlbnRpb25fY2hlY2tfdmFyIDwtIGRldGVjdF9hdHRlbnRpb25fY2hlY2tfY29sdW1uKA0KICAgICAgcmF3ID0gcmF3LA0KICAgICAgcHJlZmVycmVkX2NhbmRpZGF0ZXMgPSBjKCJRMjUuMV8xMSIsICJRMjUuMV8xMCIpLA0KICAgICAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkgMiINCiAgICApDQogIH0NCg0KICBkZl9oZWFkZXJfcmVtb3ZlZCA8LSByYXcgJT4lDQogICAgZmlsdGVyKA0KICAgICAgIWlzLm5hKFJlc3BvbnNlSWQpLA0KICAgICAgUmVzcG9uc2VJZCAhPSAiIiwNCiAgICAgICFzdHJfZGV0ZWN0KA0KICAgICAgICBub3JtX3RleHQoUmVzcG9uc2VJZCksDQogICAgICAgICJeKFJlc3BvbnNlIElEfOWbnuetlElEKSR8SW1wb3J0SWQiDQogICAgICApDQogICAgKSAlPiUNCiAgICBtdXRhdGUoSUQgPSBhcy5jaGFyYWN0ZXIoUmVzcG9uc2VJZCkpDQoNCiAgZHVwbGljYXRlX2lkcyA8LSBkZl9oZWFkZXJfcmVtb3ZlZCAlPiUNCiAgICBjb3VudChJRCkgJT4lDQogICAgZmlsdGVyKG4gPiAxKQ0KDQogIGlmIChucm93KGR1cGxpY2F0ZV9pZHMpID4gMCkgew0KICAgIHByaW50KGR1cGxpY2F0ZV9pZHMpDQogICAgc3RvcCgiQ2hlY2siKQ0KICB9DQoNCiAgc2FtcGxlX2Zsb3cgPC0gdGliYmxlKA0KICAgIHN0YWdlID0gIlF1YWx0cmljc+izquWVj+aWh+ihjOOCkumZpOWkluW+jCIsDQogICAgbiA9IG5yb3coZGZfaGVhZGVyX3JlbW92ZWQpDQogICkNCg0KICBkZiA8LSBkZl9oZWFkZXJfcmVtb3ZlZA0KDQogIGlmIChyZXF1aXJlX2luaXRpYWxfY29uc2VudCkgew0KICAgIGlmICghIlExLjEiICVpbiUgbmFtZXMoZGYpKSB7DQogICAgICBzdG9wKCJDaGVjayBpbml0aWFsIGNvbnNlbnQiKQ0KICAgIH0NCg0KICAgIGRmIDwtIGRmICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpc19yZXNwb25zZV9jb2RlKFExLjEsIDEpIHwNCiAgICAgICAgICBzdHJfZGV0ZWN0KG5vcm1fdGV4dChRMS4xKSwgIui2o+aXqOOBq+WQjOaEj+OBl+OBpi4q5Y2U5Yqb44GZ44KLIikNCiAgICAgICkNCg0KICAgIHNhbXBsZV9mbG93IDwtIGJpbmRfcm93cygNCiAgICAgIHNhbXBsZV9mbG93LA0KICAgICAgdGliYmxlKHN0YWdlID0gIuWIneWbnuWQjOaEjyBRMS4xID0gMSIsIG4gPSBucm93KGRmKSkNCiAgICApDQogIH0NCg0KICBpZiAocmVxdWlyZV9maW5hbF9jb25zZW50KSB7DQogICAgaWYgKGlzLm5hKGZpbmFsX2NvbnNlbnRfdmFyKSB8fCAhZmluYWxfY29uc2VudF92YXIgJWluJSBuYW1lcyhkZikpIHsNCiAgICAgIHN0b3AoIkNoZWNrIGZpbmFsIGNvbnNlbnQiKQ0KICAgIH0NCg0KICAgIGRmIDwtIGRmICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpc19yZXNwb25zZV9jb2RlKC5kYXRhW1tmaW5hbF9jb25zZW50X3Zhcl1dLCAxKSB8DQogICAgICAgICAgc3RyX2RldGVjdCgNCiAgICAgICAgICAgIG5vcm1fdGV4dCguZGF0YVtbZmluYWxfY29uc2VudF92YXJdXSksDQogICAgICAgICAgICAi5ZCM5oSP44GXLirlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgosiDQogICAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKA0KICAgICAgc2FtcGxlX2Zsb3csDQogICAgICB0aWJibGUoDQogICAgICAgIHN0YWdlID0gcGFzdGUwKCLmnIDntYLlkIzmhI8gIiwgZmluYWxfY29uc2VudF92YXIsICIgPSAxIiksDQogICAgICAgIG4gPSBucm93KGRmKQ0KICAgICAgKQ0KICAgICkNCiAgfQ0KDQogIGlmIChyZXF1aXJlX2F0dGVudGlvbl9jaGVjaykgew0KICAgIGlmICghYXR0ZW50aW9uX2NoZWNrX3ZhciAlaW4lIG5hbWVzKGRmKSkgew0KICAgICAgc3RvcCgiQ2hlY2sgYXR0ZW50aW9uIGl0ZW0iKQ0KICAgIH0NCg0KICAgIGF0dGVudGlvbl9jaGVja19jb3JyZWN0IDwtIGRldGVjdF9hdHRlbnRpb25fY29ycmVjdF9jb2RlKA0KICAgICAgZGZbW2F0dGVudGlvbl9jaGVja192YXJdXSwNCiAgICAgIGRpc3BsYXllZF9hbnN3ZXIgPSAzTCwNCiAgICAgIHJlY29kZWRfYW5zd2VyID0gNkwsDQogICAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAyIg0KICAgICkNCg0KICAgIGRmIDwtIGRmICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpc19yZXNwb25zZV9jb2RlKA0KICAgICAgICAgIC5kYXRhW1thdHRlbnRpb25fY2hlY2tfdmFyXV0sDQogICAgICAgICAgYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QNCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKA0KICAgICAgc2FtcGxlX2Zsb3csDQogICAgICB0aWJibGUoDQogICAgICAgIHN0YWdlID0gcGFzdGUwKA0KICAgICAgICAgICLmjIfnpLrpoIXnm67mraPnrZTvvIgiLA0KICAgICAgICAgIGF0dGVudGlvbl9jaGVja192YXIsDQogICAgICAgICAgIuOAgeS/neWtmOOCs+ODvOODiT0iLA0KICAgICAgICAgIGF0dGVudGlvbl9jaGVja19jb3JyZWN0LA0KICAgICAgICAgICLvvIkiDQogICAgICAgICksDQogICAgICAgIG4gPSBucm93KGRmKQ0KICAgICAgKQ0KICAgICkNCiAgfQ0KDQogIHByaW50KHNhbXBsZV9mbG93KQ0KICB3cml0ZV9jc3Zfc2FmZWx5KHNhbXBsZV9mbG93LCAic2FtcGxlX2Zsb3dfYmVmb3JlX2NvbmpvaW50LmNzdiIpDQoNCg0KICBjaG9pY2VfbWFwIDwtIGRldGVjdF9jb25qb2ludF9jaG9pY2VfbWFwKA0KICAgIHJhdyA9IHJhdywNCiAgICBwYXJ0eV9udW1iZXJzID0gMjo1LA0KICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDIiDQogICkNCg0KICBtYW5pcHVsYXRpb25fbWFwIDwtIGRldGVjdF9tYW5pcHVsYXRpb25fbWFwKA0KICAgIHJhdyA9IHJhdywNCiAgICBjaG9pY2VfbWFwID0gY2hvaWNlX21hcCwNCiAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAyIg0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseShjaG9pY2VfbWFwLCAiZGV0ZWN0ZWRfY2hvaWNlX3F1ZXN0aW9uX21hcC5jc3YiKQ0KICB3cml0ZV9jc3Zfc2FmZWx5KG1hbmlwdWxhdGlvbl9tYXAsICJkZXRlY3RlZF9tYW5pcHVsYXRpb25fcXVlc3Rpb25fbWFwLmNzdiIpDQoNCg0KICBsZXZlbF90b19hdHRyX3ZhciA8LSBmdW5jdGlvbih4KSB7DQogICAgeCA8LSBub3JtX3RleHQoeCkNCg0KICAgIGNhc2Vfd2hlbigNCiAgICAgIHggJWluJSBjKCLlj7PmtL7jg7vkv53lrojnmoQiLCAi5Lit6YGTIiwgIuW3pua0vuODu+mdqeaWsOeahCIpIH4NCiAgICAgICAgInBvbGljeV9wb3NpdGlvbiIsDQoNCiAgICAgIHggJWluJSBjKCLkuI7lhZoiLCAi6YeO5YWaIikgfg0KICAgICAgICAiZ292ZXJubWVudF9zdGF0dXMiLA0KDQogICAgICBzdHJfZGV0ZWN0KHgsICJHRFDmiJDplbfnjociKSB+DQogICAgICAgICJnZHBfZ3Jvd3RoIiwNCg0KICAgICAgc3RyX2RldGVjdCh4LCAi5pel57WM5bmz5Z2HIikgfg0KICAgICAgICAibmlra2VpIiwNCg0KICAgICAgeCAlaW4lIGMoIjEw5Lul5LiLIiwgIjEwfjQ5IiwgIjUwfjk5IiwgIjEwMH4xOTkiLCAiMjAw5Lul5LiKIikgfg0KICAgICAgICAic2VhdHMiLA0KDQogICAgICBzdHJfZGV0ZWN0KHgsICJDUEl854mp5L6hIikgfg0KICAgICAgICAiY3BpIiwNCg0KICAgICAgc3RyX2RldGVjdCh4LCAi5aSx5qWt546HfOmbh+eUqCIpIH4NCiAgICAgICAgInVuZW1wbG95bWVudCIsDQoNCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgKQ0KICB9DQoNCiAgcmVxdWlyZWRfYXR0cl92YXJzIDwtIGMoDQogICAgInBvbGljeV9wb3NpdGlvbiIsDQogICAgImdvdmVybm1lbnRfc3RhdHVzIiwNCiAgICAiZ2RwX2dyb3d0aCIsDQogICAgIm5pa2tlaSIsDQogICAgInNlYXRzIiwNCiAgICAiY3BpIiwNCiAgICAidW5lbXBsb3ltZW50Ig0KICApDQoNCiAgYWxsb3dlZF9sZXZlbHMgPC0gbGlzdCgNCiAgICBwb2xpY3lfcG9zaXRpb24gPSBjKCLlj7PmtL7jg7vkv53lrojnmoQiLCAi5Lit6YGTIiwgIuW3pua0vuODu+mdqeaWsOeahCIpLA0KICAgIGdvdmVybm1lbnRfc3RhdHVzID0gYygi5LiO5YWaIiwgIumHjuWFmiIpLA0KICAgIGdkcF9ncm93dGggPSBjKA0KICAgICAgIkdEUOaIkOmVt+eOh8KxMO+8hSIsDQogICAgICAiR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsDQogICAgICAiR0RQ5oiQ6ZW3546H44Oe44Kk44OK44K5Me+8hSINCiAgICApLA0KICAgIG5pa2tlaSA9IGMoDQogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U44OX44Op44K5MTAwMOWGhiIsDQogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U44Oe44Kk44OK44K5MTAwMOWGhiIsDQogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIg0KICAgICksDQogICAgc2VhdHMgPSBjKCIxMOS7peS4iyIsICIxMH40OSIsICI1MH45OSIsICIxMDB+MTk5IiwgIjIwMOS7peS4iiIpLA0KICAgIGNwaSA9IGMoDQogICAgICAiQ1BJ5YmN5pyf5q+UwrEw44Od44Kk44Oz44OIIiwNCiAgICAgICJDUEnliY3mnJ/mr5Tjg5fjg6njgrkx44Od44Kk44Oz44OIIiwNCiAgICAgICJDUEnliY3mnJ/mr5Tjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIg0KICAgICksDQogICAgdW5lbXBsb3ltZW50ID0gYygNCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiLA0KICAgICAgIuWksealreeOh+WJjeacn+avlOODl+ODqeOCuTHvvIUiLA0KICAgICAgIuWksealreeOh+WJjeacn+avlOODnuOCpOODiuOCuTHvvIUiDQogICAgKQ0KICApDQoNCg0KICBtYWtlX3Byb2ZpbGVfbG9uZyA8LSBmdW5jdGlvbihkYXQsIG5fcGFydHkpIHsNCg0KICAgIG1hcF9uIDwtIGNob2ljZV9tYXAgJT4lDQogICAgICBmaWx0ZXIocGFydHlfbiA9PSBuX3BhcnR5KQ0KDQogICAgcXZhcnMgPC0gbWFwX24kY2hvaWNlX3Zhcg0KDQogICAgbWlzc2luZ19xIDwtIHNldGRpZmYocXZhcnMsIG5hbWVzKGRhdCkpDQogICAgaWYgKGxlbmd0aChtaXNzaW5nX3EpID4gMCkgew0KICAgICAgc3RvcCgiQ2hlY2sgY2hvaWNlIGNvbHVtbnMiKQ0KICAgIH0NCg0KICAgIGRhdF9uIDwtIGRhdCAlPiUNCiAgICAgIGZpbHRlcihpZl9hbnkoYWxsX29mKHF2YXJzKSwgfiAhaXMubmEoLngpICYgbm9ybV90ZXh0KC54KSAhPSAiIikpDQoNCiAgICBpZiAocmVxdWlyZV9tYW5pcHVsYXRpb25fY2hlY2spIHsNCiAgICAgIG1hbmlwdWxhdGlvbl9yb3cgPC0gbWFuaXB1bGF0aW9uX21hcCAlPiUNCiAgICAgICAgZmlsdGVyKHBhcnR5X24gPT0gbl9wYXJ0eSkNCg0KICAgICAgbWFuaXB1bGF0aW9uX3ZhciA8LSBtYW5pcHVsYXRpb25fcm93JG1hbmlwdWxhdGlvbl92YXINCiAgICAgIGNvcnJlY3RfYW5zd2VyIDwtIG1hbmlwdWxhdGlvbl9yb3ckY29ycmVjdF9hbnN3ZXINCg0KICAgICAgaWYgKCFtYW5pcHVsYXRpb25fdmFyICVpbiUgbmFtZXMoZGF0X24pKSB7DQogICAgICAgIHN0b3AoIkNoZWNrIG1hbmlwdWxhdGlvbiBpdGVtIikNCiAgICAgIH0NCg0KICAgICAgZGF0X24gPC0gZGF0X24gJT4lDQogICAgICAgIGZpbHRlcigNCiAgICAgICAgICBpc19yZXNwb25zZV9jb2RlKA0KICAgICAgICAgICAgLmRhdGFbW21hbmlwdWxhdGlvbl92YXJdXSwNCiAgICAgICAgICAgIGNvcnJlY3RfYW5zd2VyDQogICAgICAgICAgKQ0KICAgICAgICApDQogICAgfQ0KDQoNCiAgICBjaG9pY2VfbG9uZyA8LSBkYXRfbiAlPiUNCiAgICAgIHNlbGVjdChJRCwgYWxsX29mKHF2YXJzKSkgJT4lDQogICAgICBwaXZvdF9sb25nZXIoDQogICAgICAgIGNvbHMgPSBhbGxfb2YocXZhcnMpLA0KICAgICAgICBuYW1lc190byA9ICJjaG9pY2VfdmFyIiwNCiAgICAgICAgdmFsdWVzX3RvID0gImNob2ljZV9yYXciDQogICAgICApICU+JQ0KICAgICAgbGVmdF9qb2luKG1hcF9uLCBieSA9ICJjaG9pY2VfdmFyIikgJT4lDQogICAgICBtdXRhdGUoY2hvaWNlID0gcGFyc2VfY2hvaWNlX3Bvc2l0aW9uKGNob2ljZV9yYXcpKSAlPiUNCiAgICAgIGZpbHRlcighaXMubmEoY2hvaWNlKSkgJT4lDQogICAgICBzZWxlY3QoSUQsIHBhcnR5X24sIHRhc2ssIGNob2ljZSkNCg0KICAgIGludmFsaWRfY2hvaWNlIDwtIGNob2ljZV9sb25nICU+JQ0KICAgICAgZmlsdGVyKGNob2ljZSA8IDEgfCBjaG9pY2UgPiBuX3BhcnR5KQ0KDQogICAgaWYgKG5yb3coaW52YWxpZF9jaG9pY2UpID4gMCkgew0KICAgICAgcHJpbnQoaW52YWxpZF9jaG9pY2UpDQogICAgICBzdG9wKCJDaGVjayBjaG9pY2UgdmFsdWVzIikNCiAgICB9DQoNCiAgICBkdXBsaWNhdGVfY2hvaWNlIDwtIGNob2ljZV9sb25nICU+JQ0KICAgICAgY291bnQoSUQsIHRhc2spICU+JQ0KICAgICAgZmlsdGVyKG4gIT0gMSkNCg0KICAgIGlmIChucm93KGR1cGxpY2F0ZV9jaG9pY2UpID4gMCkgew0KICAgICAgcHJpbnQoZHVwbGljYXRlX2Nob2ljZSkNCiAgICAgIHN0b3AoIkNoZWNrIGR1cGxpY2F0ZSBjaG9pY2VzIikNCiAgICB9DQoNCg0KICAgIGxldmVsX3JlZ2V4IDwtIHBhc3RlMCgNCiAgICAgICJeUzJfUCIsIG5fcGFydHksDQogICAgICAiX0ZfKFsxLTVdKV8oWzEtIiwgbl9wYXJ0eSwgIl0pXyhbMS03XSkkIg0KICAgICkNCg0KICAgIGxldmVsX2NvbHMgPC0gbmFtZXMoZGF0X24pW3N0cl9kZXRlY3QobmFtZXMoZGF0X24pLCBsZXZlbF9yZWdleCldDQoNCiAgICBleHBlY3RlZF9sZXZlbF9jb2xzIDwtIDUgKiBuX3BhcnR5ICogNw0KICAgIGlmIChsZW5ndGgobGV2ZWxfY29scykgIT0gZXhwZWN0ZWRfbGV2ZWxfY29scykgew0KICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpDQogICAgfQ0KDQogICAgbGV2ZWxfbG9uZyA8LSBkYXRfbiAlPiUNCiAgICAgIHNlbGVjdChJRCwgYWxsX29mKGxldmVsX2NvbHMpKSAlPiUNCiAgICAgIHBpdm90X2xvbmdlcigNCiAgICAgICAgY29scyA9IGFsbF9vZihsZXZlbF9jb2xzKSwNCiAgICAgICAgbmFtZXNfdG8gPSAiZnZhciIsDQogICAgICAgIHZhbHVlc190byA9ICJsZXZlbCINCiAgICAgICkgJT4lDQogICAgICBleHRyYWN0KA0KICAgICAgICBmdmFyLA0KICAgICAgICBpbnRvID0gYygidGFzayIsICJwcm9maWxlIiwgImF0dHJfb3JkZXIiKSwNCiAgICAgICAgcmVnZXggPSBsZXZlbF9yZWdleCwNCiAgICAgICAgY29udmVydCA9IFRSVUUNCiAgICAgICkgJT4lDQogICAgICBtdXRhdGUobGV2ZWwgPSBub3JtX3RleHQobGV2ZWwpKSAlPiUNCiAgICAgIGZpbHRlcigNCiAgICAgICAgdGFzayAlaW4lIDE6NSwNCiAgICAgICAgcHJvZmlsZSAlaW4lIDE6bl9wYXJ0eSwNCiAgICAgICAgYXR0cl9vcmRlciAlaW4lIDE6NywNCiAgICAgICAgIWlzLm5hKGxldmVsKSwNCiAgICAgICAgbGV2ZWwgIT0gIiINCiAgICAgICkgJT4lDQogICAgICBtdXRhdGUoYXR0cl92YXIgPSBsZXZlbF90b19hdHRyX3ZhcihsZXZlbCkpDQoNCiAgICB1bmtub3duX2xldmVscyA8LSBsZXZlbF9sb25nICU+JQ0KICAgICAgZmlsdGVyKGlzLm5hKGF0dHJfdmFyKSkgJT4lDQogICAgICBkaXN0aW5jdChsZXZlbCkNCg0KICAgIGlmIChucm93KHVua25vd25fbGV2ZWxzKSA+IDApIHsNCiAgICAgIHByaW50KHVua25vd25fbGV2ZWxzKQ0KICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpDQogICAgfQ0KDQogICAgcHJvZmlsZV9hdHRyaWJ1dGVfY291bnQgPC0gbGV2ZWxfbG9uZyAlPiUNCiAgICAgIGNvdW50KElELCB0YXNrLCBwcm9maWxlLCBuYW1lID0gIm5fYXR0cmlidXRlX3Jvd3MiKSAlPiUNCiAgICAgIGZpbHRlcihuX2F0dHJpYnV0ZV9yb3dzICE9IDcpDQoNCiAgICBpZiAobnJvdyhwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCkgPiAwKSB7DQogICAgICBwcmludChoZWFkKHByb2ZpbGVfYXR0cmlidXRlX2NvdW50LCA1MCkpDQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICB9DQoNCiAgICBkdXBsaWNhdGVfYXR0cmlidXRlIDwtIGxldmVsX2xvbmcgJT4lDQogICAgICBjb3VudChJRCwgdGFzaywgcHJvZmlsZSwgYXR0cl92YXIpICU+JQ0KICAgICAgZmlsdGVyKG4gIT0gMSkNCg0KICAgIGlmIChucm93KGR1cGxpY2F0ZV9hdHRyaWJ1dGUpID4gMCkgew0KICAgICAgcHJpbnQoaGVhZChkdXBsaWNhdGVfYXR0cmlidXRlLCA1MCkpDQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICB9DQoNCg0KICAgIHByb2ZpbGVfd2lkZSA8LSBsZXZlbF9sb25nICU+JQ0KICAgICAgaW5uZXJfam9pbihjaG9pY2VfbG9uZywgYnkgPSBjKCJJRCIsICJ0YXNrIikpICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwNCiAgICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHByb2ZpbGUgPT0gY2hvaWNlKSwNCiAgICAgICAgdGFza19pZCA9IHBhc3RlKElELCBwYXJ0eV9uLCB0YXNrLCBzZXAgPSAiXyIpLA0KICAgICAgICBwcm9maWxlX2lkID0gcGFzdGUoSUQsIHBhcnR5X24sIHRhc2ssIHByb2ZpbGUsIHNlcCA9ICJfIikNCiAgICAgICkgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIElELCBwYXJ0eV9uLCB0YXNrLCBwcm9maWxlLCBjaG9pY2UsIHNlbGVjdGVkLA0KICAgICAgICB0YXNrX2lkLCBwcm9maWxlX2lkLCBhdHRyX3ZhciwgbGV2ZWwNCiAgICAgICkgJT4lDQogICAgICBwaXZvdF93aWRlcigNCiAgICAgICAgbmFtZXNfZnJvbSA9IGF0dHJfdmFyLA0KICAgICAgICB2YWx1ZXNfZnJvbSA9IGxldmVsLA0KICAgICAgICB2YWx1ZXNfZm4gPSBsaXN0KGxldmVsID0gfiBmaXJzdCgueCkpDQogICAgICApDQoNCiAgICBtaXNzaW5nX2F0dHIgPC0gc2V0ZGlmZihyZXF1aXJlZF9hdHRyX3ZhcnMsIG5hbWVzKHByb2ZpbGVfd2lkZSkpDQoNCiAgICBpZiAobGVuZ3RoKG1pc3NpbmdfYXR0cikgPiAwKSB7DQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICB9DQoNCiAgICBwcm9maWxlX3dpZGUgPC0gcHJvZmlsZV93aWRlICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICBJRCwgcGFydHlfbiwgdGFzaywgcHJvZmlsZSwgY2hvaWNlLCBzZWxlY3RlZCwNCiAgICAgICAgdGFza19pZCwgcHJvZmlsZV9pZCwNCiAgICAgICAgYWxsX29mKHJlcXVpcmVkX2F0dHJfdmFycykNCiAgICAgICkgJT4lDQogICAgICBhcnJhbmdlKElELCB0YXNrLCBwcm9maWxlKQ0KDQogICAgcmV0dXJuKHByb2ZpbGVfd2lkZSkNCiAgfQ0KDQoNCiAgY29uam9pbnRfMiA8LSBtYWtlX3Byb2ZpbGVfbG9uZyhkZiwgMikNCiAgY29uam9pbnRfMyA8LSBtYWtlX3Byb2ZpbGVfbG9uZyhkZiwgMykNCiAgY29uam9pbnRfNCA8LSBtYWtlX3Byb2ZpbGVfbG9uZyhkZiwgNCkNCiAgY29uam9pbnRfNSA8LSBtYWtlX3Byb2ZpbGVfbG9uZyhkZiwgNSkNCg0KICBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCA8LSBiaW5kX3Jvd3MoDQogICAgY29uam9pbnRfMiwNCiAgICBjb25qb2ludF8zLA0KICAgIGNvbmpvaW50XzQsDQogICAgY29uam9pbnRfNQ0KICApDQoNCg0KICBpZF90YXNrX2NoZWNrIDwtIGNvbmpvaW50X2FsbF91bmZpbHRlcmVkICU+JQ0KICAgIGdyb3VwX2J5KElELCBwYXJ0eV9uLCB0YXNrKSAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBuX3Byb2ZpbGVzID0gbigpLA0KICAgICAgc2VsZWN0ZWRfc3VtID0gc3VtKHNlbGVjdGVkKSwNCiAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICApICU+JQ0KICAgIGdyb3VwX2J5KElELCBwYXJ0eV9uKSAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBuX3Rhc2tzID0gbl9kaXN0aW5jdCh0YXNrKSwNCiAgICAgIGFsbF90YXNrc19vayA9IGFsbChuX3Byb2ZpbGVzID09IHBhcnR5X24gJiBzZWxlY3RlZF9zdW0gPT0gMSksDQogICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgKQ0KDQogIHZhbGlkX2lkcyA8LSBpZF90YXNrX2NoZWNrICU+JQ0KICAgIGZpbHRlcihuX3Rhc2tzID09IDUsIGFsbF90YXNrc19vaykNCg0KICBjb25qb2ludF9hbGwgPC0gY29uam9pbnRfYWxsX3VuZmlsdGVyZWQgJT4lDQogICAgc2VtaV9qb2luKHZhbGlkX2lkcywgYnkgPSBjKCJJRCIsICJwYXJ0eV9uIikpDQoNCiAgbl9ieV9wYXJ0eSA8LSB2YWxpZF9pZHMgJT4lDQogICAgY291bnQocGFydHlfbiwgbmFtZSA9ICJuIikgJT4lDQogICAgY29tcGxldGUocGFydHlfbiA9IDI6NSwgZmlsbCA9IGxpc3QobiA9IDApKSAlPiUNCiAgICBhcnJhbmdlKHBhcnR5X24pDQoNCiAgbl90b3RhbCA8LSB2YWxpZF9pZHMgJT4lDQogICAgc3VtbWFyaXNlKG4gPSBuX2Rpc3RpbmN0KElEKSkgJT4lDQogICAgcHVsbChuKQ0KDQogIGZpZ3VyZV9uX2xhYmVscyA8LSBiaW5kX3Jvd3MoDQogICAgdGliYmxlKA0KICAgICAgcG9zaXRpb24gPSAi5YWo44K144Oz44OX44OrIiwNCiAgICAgIGxhYmVsID0gcGFzdGUwKCLlhajjgrXjg7Pjg5fjg6ssIG49Iiwgc2NhbGVzOjpjb21tYShuX3RvdGFsKSkNCiAgICApLA0KICAgIG5fYnlfcGFydHkgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIHBvc2l0aW9uID0gcGFzdGUwKHBhcnR5X24sICLmlL/lhZrpgbjmip4iKSwNCiAgICAgICAgbGFiZWwgPSBwYXN0ZTAoIm49Iiwgc2NhbGVzOjpjb21tYShuKSkNCiAgICAgICkgJT4lDQogICAgICBzZWxlY3QocG9zaXRpb24sIGxhYmVsKQ0KICApDQoNCiAgY2F0KCJcbuWIhuaekOWvvuixoeiAheaVsFxuIikNCiAgcHJpbnQobl9ieV9wYXJ0eSkNCiAgY2F0KCLlhajjgrXjg7Pjg5fjg6sgbj0iLCBuX3RvdGFsLCAiXG4iLCBzZXAgPSAiIikNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KGlkX3Rhc2tfY2hlY2ssICJpZF90YXNrX2NoZWNrLmNzdiIpDQogIHdyaXRlX2Nzdl9zYWZlbHkodmFsaWRfaWRzLCAidmFsaWRfaWRzLmNzdiIpDQogIHdyaXRlX2Nzdl9zYWZlbHkobl9ieV9wYXJ0eSwgIm5fYnlfcGFydHkuY3N2IikNCiAgd3JpdGVfY3N2X3NhZmVseShmaWd1cmVfbl9sYWJlbHMsICJmaWd1cmVfbl9sYWJlbHMuY3N2IikNCg0KDQogIGNoZWNrX3Byb2ZpbGUgPC0gY29uam9pbnRfYWxsICU+JQ0KICAgIGdyb3VwX2J5KHBhcnR5X24sIElELCB0YXNrLCB0YXNrX2lkKSAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBuX3Byb2ZpbGVzID0gbigpLA0KICAgICAgc2VsZWN0ZWRfc3VtID0gc3VtKHNlbGVjdGVkKSwNCiAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICApICU+JQ0KICAgIGNvdW50KHBhcnR5X24sIG5fcHJvZmlsZXMsIHNlbGVjdGVkX3N1bSkNCg0KICBwcmludChjaGVja19wcm9maWxlKQ0KDQogIHN0b3BpZm5vdChhbGwoY2hlY2tfcHJvZmlsZSRuX3Byb2ZpbGVzID09IGNoZWNrX3Byb2ZpbGUkcGFydHlfbikpDQogIHN0b3BpZm5vdChhbGwoY2hlY2tfcHJvZmlsZSRzZWxlY3RlZF9zdW0gPT0gMSkpDQoNCiAgYWxsb3dlZF9kZiA8LSBlbmZyYW1lKGFsbG93ZWRfbGV2ZWxzLCBuYW1lID0gIm5hbWUiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JQ0KICAgIHVubmVzdCh2YWx1ZSkNCg0KICB1bmV4cGVjdGVkX3ZhbHVlcyA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgc2VsZWN0KGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpKSAlPiUNCiAgICBwaXZvdF9sb25nZXIoDQogICAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgICAgbmFtZXNfdG8gPSAibmFtZSIsDQogICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiDQogICAgKSAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKHZhbHVlKSwgdmFsdWUgIT0gIiIpICU+JQ0KICAgIGRpc3RpbmN0KG5hbWUsIHZhbHVlKSAlPiUNCiAgICBhbnRpX2pvaW4oYWxsb3dlZF9kZiwgYnkgPSBjKCJuYW1lIiwgInZhbHVlIikpDQoNCiAgcHJpbnQodW5leHBlY3RlZF92YWx1ZXMpDQogIHN0b3BpZm5vdChucm93KHVuZXhwZWN0ZWRfdmFsdWVzKSA9PSAwKQ0KDQogIG9ic2VydmVkX2xldmVscyA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgc2VsZWN0KGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpKSAlPiUNCiAgICBwaXZvdF9sb25nZXIoDQogICAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwNCiAgICAgIHZhbHVlc190byA9ICJsZXZlbCINCiAgICApICU+JQ0KICAgIGRpc3RpbmN0KGF0dHJpYnV0ZSwgbGV2ZWwpICU+JQ0KICAgIGFycmFuZ2UoYXR0cmlidXRlLCBsZXZlbCkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KGNoZWNrX3Byb2ZpbGUsICJwcm9maWxlX2V4cGFuc2lvbl9jaGVjay5jc3YiKQ0KICB3cml0ZV9jc3Zfc2FmZWx5KG9ic2VydmVkX2xldmVscywgIm9ic2VydmVkX2F0dHJpYnV0ZV9sZXZlbHMuY3N2IikNCiAgd3JpdGVfY3N2X3NhZmVseShjb25qb2ludF9hbGwsICJzdHVkeTJfcHJvZmlsZV9sZXZlbF9kYXRhLmNzdiIpDQoNCg0KICBhbmFseXNpc19pZHMgPC0gdmFsaWRfaWRzICU+JQ0KICAgIHNlbGVjdChJRCwgcGFydHlfbikNCg0KICBhdHRlbnRpb25fc3VtbWFyeSA8LSBkZiAlPiUNCiAgICBzZW1pX2pvaW4oYW5hbHlzaXNfaWRzLCBieSA9ICJJRCIpICU+JQ0KICAgIHRyYW5zbXV0ZSgNCiAgICAgIElELA0KICAgICAgYXR0ZW50aW9uX3Jlc3BvbnNlID0gbm9ybV90ZXh0KC5kYXRhW1thdHRlbnRpb25fY2hlY2tfdmFyXV0pLA0KICAgICAgYXR0ZW50aW9uX3Bhc3MgPSBpc19yZXNwb25zZV9jb2RlKA0KICAgICAgICAuZGF0YVtbYXR0ZW50aW9uX2NoZWNrX3Zhcl1dLA0KICAgICAgICBhdHRlbnRpb25fY2hlY2tfY29ycmVjdA0KICAgICAgKQ0KICAgICkgJT4lDQogICAgY291bnQoYXR0ZW50aW9uX3Jlc3BvbnNlLCBhdHRlbnRpb25fcGFzcywgbmFtZSA9ICJuIikgJT4lDQogICAgYXJyYW5nZShkZXNjKGF0dGVudGlvbl9wYXNzKSwgYXR0ZW50aW9uX3Jlc3BvbnNlKQ0KDQogIG1hbmlwdWxhdGlvbl9zdW1tYXJ5IDwtIG1hcF9kZnIoMjo1LCBmdW5jdGlvbihuX3BhcnR5KSB7DQogICAgbWFuaXB1bGF0aW9uX3JvdyA8LSBtYW5pcHVsYXRpb25fbWFwICU+JQ0KICAgICAgZmlsdGVyKHBhcnR5X24gPT0gbl9wYXJ0eSkNCg0KICAgIHYgPC0gbWFuaXB1bGF0aW9uX3JvdyRtYW5pcHVsYXRpb25fdmFyDQogICAgY29ycmVjdCA8LSBtYW5pcHVsYXRpb25fcm93JGNvcnJlY3RfYW5zd2VyDQoNCiAgICBkZiAlPiUNCiAgICAgIHNlbWlfam9pbigNCiAgICAgICAgYW5hbHlzaXNfaWRzICU+JSBmaWx0ZXIocGFydHlfbiA9PSBuX3BhcnR5KSwNCiAgICAgICAgYnkgPSAiSUQiDQogICAgICApICU+JQ0KICAgICAgdHJhbnNtdXRlKA0KICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwNCiAgICAgICAgcmVzcG9uc2UgPSBub3JtX3RleHQoLmRhdGFbW3ZdXSksDQogICAgICAgIGNvcnJlY3QgPSBpc19yZXNwb25zZV9jb2RlKC5kYXRhW1t2XV0sIGNvcnJlY3QpDQogICAgICApICU+JQ0KICAgICAgY291bnQocGFydHlfbiwgcmVzcG9uc2UsIGNvcnJlY3QsIG5hbWUgPSAibiIpDQogIH0pDQoNCiAgd3JpdGVfY3N2X3NhZmVseShhdHRlbnRpb25fc3VtbWFyeSwgImF0dGVudGlvbl9jaGVja19zdW1tYXJ5LmNzdiIpDQogIHdyaXRlX2Nzdl9zYWZlbHkobWFuaXB1bGF0aW9uX3N1bW1hcnksICJwYXJ0eV9udW1iZXJfY2hlY2tfc3VtbWFyeS5jc3YiKQ0KDQoNCiAgY29uam9pbnRfYWxsX20gPC0gY29uam9pbnRfYWxsICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihzZWxlY3RlZCksDQogICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksDQoNCiAgICAgIHBvbGljeV9wb3NpdGlvbiA9IGZhY3RvcigNCiAgICAgICAgcG9saWN5X3Bvc2l0aW9uLA0KICAgICAgICBsZXZlbHMgPSBjKCLkuK3pgZMiLCAi5Y+z5rS+44O75L+d5a6I55qEIiwgIuW3pua0vuODu+mdqeaWsOeahCIpDQogICAgICApLA0KDQogICAgICBnb3Zlcm5tZW50X3N0YXR1cyA9IGZhY3RvcigNCiAgICAgICAgZ292ZXJubWVudF9zdGF0dXMsDQogICAgICAgIGxldmVscyA9IGMoIumHjuWFmiIsICLkuI7lhZoiKQ0KICAgICAgKSwNCg0KICAgICAgZ2RwX2dyb3d0aCA9IGZhY3RvcigNCiAgICAgICAgZ2RwX2dyb3d0aCwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAiR0RQ5oiQ6ZW3546HwrEw77yFIiwNCiAgICAgICAgICAiR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsDQogICAgICAgICAgIkdEUOaIkOmVt+eOh+ODnuOCpOODiuOCuTHvvIUiDQogICAgICAgICkNCiAgICAgICksDQoNCiAgICAgIG5pa2tlaSA9IGZhY3RvcigNCiAgICAgICAgbmlra2VpLA0KICAgICAgICBsZXZlbHMgPSBjKA0KICAgICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5TlpInjgo/jgonjgZoiLA0KICAgICAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwNCiAgICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U44Oe44Kk44OK44K5MTAwMOWGhiINCiAgICAgICAgKQ0KICAgICAgKSwNCg0KICAgICAgc2VhdHMgPSBmYWN0b3IoDQogICAgICAgIHNlYXRzLA0KICAgICAgICBsZXZlbHMgPSBjKCIxMOS7peS4iyIsICIxMH40OSIsICI1MH45OSIsICIxMDB+MTk5IiwgIjIwMOS7peS4iiIpDQogICAgICApLA0KDQogICAgICBjcGkgPSBmYWN0b3IoDQogICAgICAgIGNwaSwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAiQ1BJ5YmN5pyf5q+UwrEw44Od44Kk44Oz44OIIiwNCiAgICAgICAgICAiQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsDQogICAgICAgICAgIkNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giDQogICAgICAgICkNCiAgICAgICksDQoNCiAgICAgIHVuZW1wbG95bWVudCA9IGZhY3RvcigNCiAgICAgICAgdW5lbXBsb3ltZW50LA0KICAgICAgICBsZXZlbHMgPSBjKA0KICAgICAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiLA0KICAgICAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwNCiAgICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+U44Oe44Kk44OK44K5Me+8hSINCiAgICAgICAgKQ0KICAgICAgKSwNCg0KICAgICAgcGFydHlfbl9mID0gZmFjdG9yKA0KICAgICAgICBhcy5jaGFyYWN0ZXIocGFydHlfbiksDQogICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKQ0KICAgICAgKQ0KICAgICkNCg0KICBhdHRyX3Rlcm1zIDwtIGMoDQogICAgInBvbGljeV9wb3NpdGlvbiIsDQogICAgImdvdmVybm1lbnRfc3RhdHVzIiwNCiAgICAiZ2RwX2dyb3d0aCIsDQogICAgIm5pa2tlaSIsDQogICAgInNlYXRzIiwNCiAgICAiY3BpIiwNCiAgICAidW5lbXBsb3ltZW50Ig0KICApDQoNCg0KICBmb3JtdWxhX25vY292IDwtIGFzLmZvcm11bGEoDQogICAgcGFzdGUoInNlbGVjdGVkIH4iLCBwYXN0ZShhdHRyX3Rlcm1zLCBjb2xsYXBzZSA9ICIgKyAiKSkNCiAgKQ0KDQogIHJ1bl9hbWNlX25vY292IDwtIGZ1bmN0aW9uKGRhdCkgew0KICAgIGZlb2xzKA0KICAgICAgZm9ybXVsYV9ub2NvdiwNCiAgICAgIGRhdGEgPSBkYXQsDQogICAgICB2Y292ID0gfiBJRA0KICAgICkNCiAgfQ0KDQogIG1vZGVsc19ieV9wYXJ0eV9uX25vY292IDwtIGNvbmpvaW50X2FsbF9tICU+JQ0KICAgIHNwbGl0KC4kcGFydHlfbikgJT4lDQogICAgbWFwKHJ1bl9hbWNlX25vY292KQ0KDQogIGNhcHR1cmUub3V0cHV0KA0KICAgIGV0YWJsZShtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiksDQogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAiYW1jZV9ub2Nvdl9tb2RlbHMudHh0IikNCiAgKQ0KDQoNCiAgbV9pbnRlcmFjdGlvbiA8LSBmZW9scygNCiAgICBzZWxlY3RlZCB+DQogICAgICBwYXJ0eV9uX2YgKg0KICAgICAgKA0KICAgICAgICBwb2xpY3lfcG9zaXRpb24gKw0KICAgICAgICAgIGdvdmVybm1lbnRfc3RhdHVzICsNCiAgICAgICAgICBnZHBfZ3Jvd3RoICsNCiAgICAgICAgICBuaWtrZWkgKw0KICAgICAgICAgIHNlYXRzICsNCiAgICAgICAgICBjcGkgKw0KICAgICAgICAgIHVuZW1wbG95bWVudA0KICAgICAgKSwNCiAgICBkYXRhID0gY29uam9pbnRfYWxsX20sDQogICAgdmNvdiA9IH4gSUQNCiAgKQ0KDQogIGNhcHR1cmUub3V0cHV0KA0KICAgIHN1bW1hcnkobV9pbnRlcmFjdGlvbiksDQogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAiYW1jZV9pbnRlcmFjdGlvbl9tb2RlbC50eHQiKQ0KICApDQoNCg0KICB0aWR5X2ZpeGVzdCA8LSBmdW5jdGlvbihtb2RlbCkgew0KICAgIGN0IDwtIGFzLmRhdGEuZnJhbWUoZml4ZXN0Ojpjb2VmdGFibGUobW9kZWwpKQ0KICAgIGN0JHRlcm0gPC0gcm93bmFtZXMoY3QpDQoNCiAgICBjdCAlPiUNCiAgICAgIGFzX3RpYmJsZSgpICU+JQ0KICAgICAgcmVuYW1lKA0KICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlLA0KICAgICAgICBzdGQuZXJyb3IgPSBgU3RkLiBFcnJvcmAsDQogICAgICAgIHN0YXRpc3RpYyA9IGB0IHZhbHVlYCwNCiAgICAgICAgcC52YWx1ZSA9IGBQcig+fHR8KWANCiAgICAgICkgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGNvbmYubG93ID0gZXN0aW1hdGUgLSAxLjk2ICogc3RkLmVycm9yLA0KICAgICAgICBjb25mLmhpZ2ggPSBlc3RpbWF0ZSArIDEuOTYgKiBzdGQuZXJyb3INCiAgICAgICkgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIHRlcm0sIGVzdGltYXRlLCBzdGQuZXJyb3IsIHN0YXRpc3RpYywgcC52YWx1ZSwNCiAgICAgICAgY29uZi5sb3csIGNvbmYuaGlnaA0KICAgICAgKQ0KICB9DQoNCiAgdGVybV9sYWJlbHMgPC0gdHJpYmJsZSgNCiAgICB+dGVybSwgfmF0dHJpYnV0ZSwgfmN1ZV90eXBlLCB+bGFiZWwsIH5vcmRlciwNCg0KICAgICJnb3Zlcm5tZW50X3N0YXR1c+S4juWFmiIsDQogICAgIuS4juWFmu+8j+mHjuWFmiIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi5LiO5YWaIiwgMSwNCg0KICAgICJwb2xpY3lfcG9zaXRpb27lj7PmtL7jg7vkv53lrojnmoQiLA0KICAgICLmlL/nrZbkvY3nva4iLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuWPs+a0vuODu+S/neWuiOeahCIsIDIsDQoNCiAgICAicG9saWN5X3Bvc2l0aW9u5bem5rS+44O76Z2p5paw55qEIiwNCiAgICAi5pS/562W5L2N572uIiwgIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsICLlt6bmtL7jg7vpnanmlrDnmoQiLCAzLA0KDQogICAgInNlYXRzMTB+NDkiLA0KICAgICLorbDluK3mlbAiLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuitsOW4reaVsO+8mjEw772eNDkiLCA0LA0KDQogICAgInNlYXRzNTB+OTkiLA0KICAgICLorbDluK3mlbAiLCAi5pS/5YWa44Gu5omL44GM44GL44KKIiwgIuitsOW4reaVsO+8mjUw772eOTkiLCA1LA0KDQogICAgInNlYXRzMTAwfjE5OSIsDQogICAgIuitsOW4reaVsCIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi6K2w5bit5pWw77yaMTAw772eMTk5IiwgNiwNCg0KICAgICJzZWF0czIwMOS7peS4iiIsDQogICAgIuitsOW4reaVsCIsICLmlL/lhZrjga7miYvjgYzjgYvjgooiLCAi6K2w5bit5pWw77yaMjAw5Lul5LiKIiwgNywNCg0KICAgICJnZHBfZ3Jvd3RoR0RQ5oiQ6ZW3546H44OX44Op44K5Me+8hSIsDQogICAgIkdEUOaIkOmVt+eOhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAiR0RQ77ya44OX44Op44K5Me+8hSIsIDgsDQoNCiAgICAiZ2RwX2dyb3d0aEdEUOaIkOmVt+eOh+ODnuOCpOODiuOCuTHvvIUiLA0KICAgICJHRFDmiJDplbfnjociLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIkdEUO+8muODnuOCpOODiuOCuTHvvIUiLCA5LA0KDQogICAgIm5pa2tlaeaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLA0KICAgICLml6XntYzlubPlnYciLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIuaXpee1jOW5s+Wdh++8muODl+ODqeOCuTEwMDDlhoYiLCAxMCwNCg0KICAgICJuaWtrZWnml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIiwNCiAgICAi5pel57WM5bmz5Z2HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICLml6XntYzlubPlnYfvvJrjg57jgqTjg4rjgrkxMDAw5YaGIiwgMTEsDQoNCiAgICAiY3BpQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsDQogICAgIkNQSSIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAiQ1BJ77ya44OX44Op44K5MeODneOCpOODs+ODiCIsIDEyLA0KDQogICAgImNwaUNQSeWJjeacn+avlOODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giLA0KICAgICJDUEkiLCAi57WM5riI44Gu5omL44GM44GL44KKIiwgIkNQSe+8muODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4giLCAxMywNCg0KICAgICJ1bmVtcGxveW1lbnTlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwNCiAgICAi5aSx5qWt546HIiwgIue1jOa4iOOBruaJi+OBjOOBi+OCiiIsICLlpLHmpa3njofvvJrjg5fjg6njgrkx77yFIiwgMTQsDQoNCiAgICAidW5lbXBsb3ltZW505aSx5qWt546H5YmN5pyf5q+U44Oe44Kk44OK44K5Me+8hSIsDQogICAgIuWksealreeOhyIsICLntYzmuIjjga7miYvjgYzjgYvjgooiLCAi5aSx5qWt546H77ya44Oe44Kk44OK44K5Me+8hSIsIDE1DQogICkNCg0KICBhdHRyaWJ1dGVfb3JkZXIgPC0gYygNCiAgICAi5LiO5YWa77yP6YeO5YWaIiwNCiAgICAi5pS/562W5L2N572uIiwNCiAgICAi6K2w5bit5pWwIiwNCiAgICAiR0RQ5oiQ6ZW3546HIiwNCiAgICAi5pel57WM5bmz5Z2HIiwNCiAgICAiQ1BJIiwNCiAgICAi5aSx5qWt546HIg0KICApDQoNCiAgbGFiZWxfb3JkZXIgPC0gdGVybV9sYWJlbHMgJT4lDQogICAgYXJyYW5nZShvcmRlcikgJT4lDQogICAgcHVsbChsYWJlbCkNCg0KICBtYWtlX2FtY2VfcGxvdF9kZiA8LSBmdW5jdGlvbihtb2RlbHMpIHsNCiAgICBpbWFwX2RmcigNCiAgICAgIG1vZGVscywNCiAgICAgIH4gdGlkeV9maXhlc3QoLngpICU+JQ0KICAgICAgICBtdXRhdGUocGFydHlfbiA9IGFzLmNoYXJhY3RlcigueSkpDQogICAgKSAlPiUNCiAgICAgIGxlZnRfam9pbih0ZXJtX2xhYmVscywgYnkgPSAidGVybSIpICU+JQ0KICAgICAgZmlsdGVyKCFpcy5uYShhdHRyaWJ1dGUpKSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwNCiAgICAgICAgY29uZi5oaWdoX3BwID0gY29uZi5oaWdoICogMTAwLA0KICAgICAgICBwYXJ0eV9uID0gZmFjdG9yKA0KICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgbGV2ZWxzID0gYygiMiIsICIzIiwgIjQiLCAiNSIpLA0KICAgICAgICAgIGxhYmVscyA9IGMoIjLmlL/lhZoiLCAiM+aUv+WFmiIsICI05pS/5YWaIiwgIjXmlL/lhZoiKQ0KICAgICAgICApLA0KICAgICAgICBhdHRyaWJ1dGUgPSBmYWN0b3IoYXR0cmlidXRlLCBsZXZlbHMgPSBhdHRyaWJ1dGVfb3JkZXIpLA0KICAgICAgICBsYWJlbCA9IGZhY3RvcihsYWJlbCwgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKSkNCiAgICAgICkNCiAgfQ0KDQogIGFtY2VfcGxvdF9ub2NvdiA8LSBtYWtlX2FtY2VfcGxvdF9kZihtb2RlbHNfYnlfcGFydHlfbl9ub2NvdikNCiAgd3JpdGVfY3N2X3NhZmVseShhbWNlX3Bsb3Rfbm9jb3YsICJhbWNlX25vY292X2NvZWZmaWNpZW50cy5jc3YiKQ0KDQogIGludGVyYWN0aW9uX3Bsb3RfZGYgPC0gdGlkeV9maXhlc3QobV9pbnRlcmFjdGlvbikgJT4lDQogICAgZmlsdGVyKHN0cl9kZXRlY3QodGVybSwgInBhcnR5X25fZlszNDVdIikpICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHBhcnR5X25fY29kZSA9IHN0cl9leHRyYWN0KHRlcm0sICJwYXJ0eV9uX2ZbMzQ1XSIpLA0KICAgICAgcGFydHlfbiA9IHN0cl9yZW1vdmUocGFydHlfbl9jb2RlLCAicGFydHlfbl9mIiksDQogICAgICBiYXNlX3Rlcm0gPSB0ZXJtICU+JQ0KICAgICAgICBzdHJfcmVtb3ZlKCJwYXJ0eV9uX2ZbMzQ1XToiKSAlPiUNCiAgICAgICAgc3RyX3JlbW92ZSgiOnBhcnR5X25fZlszNDVdIikNCiAgICApICU+JQ0KICAgIGxlZnRfam9pbih0ZXJtX2xhYmVscywgYnkgPSBjKCJiYXNlX3Rlcm0iID0gInRlcm0iKSkgJT4lDQogICAgZmlsdGVyKCFpcy5uYShhdHRyaWJ1dGUpKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBlc3RpbWF0ZV9wcCA9IGVzdGltYXRlICogMTAwLA0KICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwNCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwNCiAgICAgIHBhcnR5X25fbGFiZWwgPSBmYWN0b3IoDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIGxldmVscyA9IGMoIjMiLCAiNCIsICI1IiksDQogICAgICAgIGxhYmVscyA9IGMoIjPmlL/lhZoiLCAiNOaUv+WFmiIsICI15pS/5YWaIikNCiAgICAgICksDQogICAgICBhdHRyaWJ1dGUgPSBmYWN0b3IoYXR0cmlidXRlLCBsZXZlbHMgPSBhdHRyaWJ1dGVfb3JkZXIpLA0KICAgICAgbGFiZWwgPSBmYWN0b3IobGFiZWwsIGxldmVscyA9IHJldihsYWJlbF9vcmRlcikpDQogICAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoaW50ZXJhY3Rpb25fcGxvdF9kZiwgImFtY2VfaW50ZXJhY3Rpb25fY29lZmZpY2llbnRzLmNzdiIpDQoNCg0KICByZWNvZGVfZmVtYWxlX3N0dWR5MiA8LSBmdW5jdGlvbih4KSB7DQogICAgeF9udW0gPC0gYXNfbnVtKHgpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICB4X251bSA9PSAyIH4gMUwsDQogICAgICB4X251bSA9PSAxIH4gMEwsDQogICAgICBUUlVFIH4gTkFfaW50ZWdlcl8NCiAgICApDQogIH0NCg0KICByZWNvZGVfY29sbGVnZV9ncmFkX3N0dWR5MiA8LSBmdW5jdGlvbih4KSB7DQogICAgeF9udW0gPC0gYXNfbnVtKHgpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICB4X251bSAlaW4lIGMoNCwgNSkgfiAxTCwNCiAgICAgIHhfbnVtICVpbiUgYygxLCAyLCAzKSB+IDBMLA0KICAgICAgVFJVRSB+IE5BX2ludGVnZXJfDQogICAgKQ0KICB9DQoNCiAgcmVjb2RlX3BhcnR5X3N1cHBvcnRfc3R1ZHkyIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4X251bSA8LSBhc19udW0oeCkNCg0KICAgIGNhc2Vfd2hlbigNCiAgICAgIHhfbnVtID09IDEgfiAi6Ieq55Sx5rCR5Li75YWaIiwNCiAgICAgIHhfbnVtID09IDIgfiAi5Lit6YGT5pS56Z2p6YCj5ZCIIiwNCiAgICAgIHhfbnVtID09IDMgfiAi56uL5oay5rCR5Li75YWaIiwNCiAgICAgIHhfbnVtID09IDQgfiAi5YWs5piO5YWaIiwNCiAgICAgIHhfbnVtID09IDUgfiAi5pel5pys57at5paw44Gu5LyaIiwNCiAgICAgIHhfbnVtID09IDYgfiAi5Zu95rCR5rCR5Li75YWaIiwNCiAgICAgIHhfbnVtID09IDcgfiAi44KM44GE44KP5paw6YG457WEIiwNCiAgICAgIHhfbnVtID09IDggfiAi5pel5pys5YWx55Sj5YWaIiwNCiAgICAgIHhfbnVtID09IDkgfiAi5Y+C5pS/5YWaIiwNCiAgICAgIHhfbnVtID09IDEwIH4gIuaXpeacrOS/neWuiOWFmiIsDQogICAgICB4X251bSA9PSAxMSB+ICLnpL7kvJrmsJHkuLvlhZoiLA0KICAgICAgeF9udW0gPT0gMTIgfiAi44OB44O844Og44G/44KJ44GEIiwNCiAgICAgIHhfbnVtID09IDEzIH4gIuOBneOBruS7liIsDQogICAgICB4X251bSA9PSAxNCB+ICLmlK/mjIHmlL/lhZrjgarjgZciLA0KICAgICAgeF9udW0gPT0gMTUgfiAi44KP44GL44KJ44Gq44GEIiwNCiAgICAgIHhfbnVtID09IDE2IH4gIuetlOOBiOOBn+OBj+OBquOBhCIsDQogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICAgICkNCiAgfQ0KDQogIGdlbmRlcl9yYXcgPC0gZ2V0X3ZhcihkZiwgYygiUTIuMSIsICJRMl8xIikpDQogIGFnZV9yYXcgPC0gZ2V0X3ZhcihkZiwgYygiUTIuMl8yIiwgIlEyLjIuMiIsICJRMl8yXzIiKSkNCiAgZWR1Y2F0aW9uX3JhdyA8LSBnZXRfdmFyKGRmLCBjKCJRMi4zIiwgIlEyXzMiKSkNCiAgaW5jb21lX2dyb3NzX3JhdyA8LSBnZXRfdmFyKGRmLCBjKCJRMi41XzEiLCAiUTIuNS4xIiwgIlEyXzVfMSIpKQ0KICBpbmNvbWVfbmV0X3JhdyA8LSBnZXRfdmFyKGRmLCBjKCJRMi41XzIiLCAiUTIuNS4yIiwgIlEyXzVfMiIpKQ0KICBwYXJ0eV9zdXBwb3J0X3JhdyA8LSBnZXRfdmFyKGRmLCBjKCJROC4yIiwgIlE4XzIiKSkNCg0KICBjb3Zhcl9pZCA8LSBkZiAlPiUNCiAgICB0cmFuc211dGUoDQogICAgICBJRCA9IGFzLmNoYXJhY3RlcihSZXNwb25zZUlkKSwNCiAgICAgIGZlbWFsZSA9IHJlY29kZV9mZW1hbGVfc3R1ZHkyKGdlbmRlcl9yYXcpLA0KICAgICAgYWdlID0gYXNfbnVtKGFnZV9yYXcpLA0KICAgICAgY29sbGVnZV9ncmFkID0gcmVjb2RlX2NvbGxlZ2VfZ3JhZF9zdHVkeTIoZWR1Y2F0aW9uX3JhdyksDQogICAgICBpbmNvbWVfZ3Jvc3MgPSBhc19udW0oaW5jb21lX2dyb3NzX3JhdyksDQogICAgICBpbmNvbWVfbmV0ID0gYXNfbnVtKGluY29tZV9uZXRfcmF3KSwNCiAgICAgIGluY29tZV9ncm9zc19sb2cgPSBsb2cxcChpbmNvbWVfZ3Jvc3MpLA0KICAgICAgaW5jb21lX25ldF9sb2cgPSBsb2cxcChpbmNvbWVfbmV0KSwNCiAgICAgIHBhcnR5X3N1cHBvcnQgPSByZWNvZGVfcGFydHlfc3VwcG9ydF9zdHVkeTIocGFydHlfc3VwcG9ydF9yYXcpLA0KICAgICAgcGFydHlfc3VwcG9ydF9mID0gZmFjdG9yX21pc3MocGFydHlfc3VwcG9ydCkNCiAgICApICU+JQ0KICAgIHNlbWlfam9pbih2YWxpZF9pZHMgJT4lIHNlbGVjdChJRCksIGJ5ID0gIklEIikgJT4lDQogICAgZGlzdGluY3QoSUQsIC5rZWVwX2FsbCA9IFRSVUUpDQoNCiAgY292YXJfaWQgPC0gY292YXJfaWQgJT4lDQogICAgbXV0YXRlKA0KICAgICAgYWdlID0gaWZfZWxzZShhZ2UgPj0gMTggJiBhZ2UgPD0gNzksIGFnZSwgTkFfcmVhbF8pDQogICAgKQ0KDQogIGFnZV9pbXBfb2JqIDwtIG1lYW5faW1wdXRlKGNvdmFyX2lkJGFnZSkNCiAgaW5jb21lX2dyb3NzX2ltcF9vYmogPC0gbWVhbl9pbXB1dGUoY292YXJfaWQkaW5jb21lX2dyb3NzX2xvZykNCg0KICBjb3Zhcl9pZCA8LSBjb3Zhcl9pZCAlPiUNCiAgICBtdXRhdGUoDQogICAgICBmZW1hbGVfaW1wID0gaWZfZWxzZShpcy5uYShmZW1hbGUpLCAwTCwgZmVtYWxlKSwNCiAgICAgIGZlbWFsZV9taXNzID0gYXMuaW50ZWdlcihpcy5uYShmZW1hbGUpKSwNCg0KICAgICAgY29sbGVnZV9ncmFkX2ltcCA9IGlmX2Vsc2UoaXMubmEoY29sbGVnZV9ncmFkKSwgMEwsIGNvbGxlZ2VfZ3JhZCksDQogICAgICBjb2xsZWdlX2dyYWRfbWlzcyA9IGFzLmludGVnZXIoaXMubmEoY29sbGVnZV9ncmFkKSksDQoNCiAgICAgIGFnZV9pbXAgPSBhZ2VfaW1wX29iaiR2YWx1ZSwNCiAgICAgIGFnZV9taXNzID0gYWdlX2ltcF9vYmokbWlzcywNCg0KICAgICAgaW5jb21lX2dyb3NzX2xvZ19pbXAgPSBpbmNvbWVfZ3Jvc3NfaW1wX29iaiR2YWx1ZSwNCiAgICAgIGluY29tZV9ncm9zc19sb2dfbWlzcyA9IGluY29tZV9ncm9zc19pbXBfb2JqJG1pc3MNCiAgICApDQoNCiAgY292YXJpYXRlX21pc3Npbmdfc3VtbWFyeSA8LSBjb3Zhcl9pZCAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBuX2lkcyA9IG5fZGlzdGluY3QoSUQpLA0KICAgICAgZmVtYWxlX21pc3NpbmcgPSBzdW0oaXMubmEoZmVtYWxlKSksDQogICAgICBhZ2VfbWlzc2luZyA9IHN1bShpcy5uYShhZ2UpKSwNCiAgICAgIGNvbGxlZ2VfZ3JhZF9taXNzaW5nID0gc3VtKGlzLm5hKGNvbGxlZ2VfZ3JhZCkpLA0KICAgICAgaW5jb21lX2dyb3NzX21pc3NpbmcgPSBzdW0oaXMubmEoaW5jb21lX2dyb3NzX2xvZykpLA0KICAgICAgcGFydHlfc3VwcG9ydF9taXNzaW5nID0gc3VtKGlzLm5hKHBhcnR5X3N1cHBvcnQpKQ0KICAgICkNCg0KICBwcmludChjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5KQ0KICB3cml0ZV9jc3Zfc2FmZWx5KGNvdmFyX2lkLCAicmVzcG9uZGVudF9jb3ZhcmlhdGVzLmNzdiIpDQogIHdyaXRlX2Nzdl9zYWZlbHkoY292YXJpYXRlX21pc3Npbmdfc3VtbWFyeSwgImNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnkuY3N2IikNCg0KDQogIGNvbmpvaW50X2FsbF9jb3YgPC0gY29uam9pbnRfYWxsX20gJT4lDQogICAgbGVmdF9qb2luKGNvdmFyX2lkLCBieSA9ICJJRCIpDQoNCiAgY292YXJpYXRlX3Rlcm1zIDwtIGMoDQogICAgImZlbWFsZV9pbXAiLA0KICAgICJmZW1hbGVfbWlzcyIsDQogICAgImFnZV9pbXAiLA0KICAgICJhZ2VfbWlzcyIsDQogICAgImNvbGxlZ2VfZ3JhZF9pbXAiLA0KICAgICJjb2xsZWdlX2dyYWRfbWlzcyIsDQogICAgImluY29tZV9ncm9zc19sb2dfaW1wIiwNCiAgICAiaW5jb21lX2dyb3NzX2xvZ19taXNzIiwNCiAgICAicGFydHlfc3VwcG9ydF9mIg0KICApDQoNCiAgaGFzX3ZhcmlhdGlvbiA8LSBmdW5jdGlvbihkYXQsIHYpIHsNCiAgICBpZiAoIXYgJWluJSBuYW1lcyhkYXQpKSByZXR1cm4oRkFMU0UpDQogICAgZHBseXI6Om5fZGlzdGluY3QoZGF0W1t2XV0sIG5hLnJtID0gVFJVRSkgPiAxDQogIH0NCg0KICBjb3ZhcmlhdGVfdGVybXNfdXNlIDwtIGNvdmFyaWF0ZV90ZXJtc1sNCiAgICBtYXBfbGdsKGNvdmFyaWF0ZV90ZXJtcywgfiBoYXNfdmFyaWF0aW9uKGNvbmpvaW50X2FsbF9jb3YsIC54KSkNCiAgXQ0KDQogIGZvcm11bGFfY292IDwtIGFzLmZvcm11bGEoDQogICAgcGFzdGUoDQogICAgICAic2VsZWN0ZWQgfiIsDQogICAgICBwYXN0ZShjKGF0dHJfdGVybXMsIGNvdmFyaWF0ZV90ZXJtc191c2UpLCBjb2xsYXBzZSA9ICIgKyAiKQ0KICAgICkNCiAgKQ0KDQogIHJ1bl9hbWNlX2NvdiA8LSBmdW5jdGlvbihkYXQpIHsNCiAgICBmZW9scygNCiAgICAgIGZvcm11bGFfY292LA0KICAgICAgZGF0YSA9IGRhdCwNCiAgICAgIHZjb3YgPSB+IElEDQogICAgKQ0KICB9DQoNCiAgbW9kZWxzX2J5X3BhcnR5X25fY292IDwtIGNvbmpvaW50X2FsbF9jb3YgJT4lDQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUNCiAgICBtYXAocnVuX2FtY2VfY292KQ0KDQogIGNhcHR1cmUub3V0cHV0KA0KICAgIGV0YWJsZSgNCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX25vY292LA0KICAgICAgbW9kZWxzX2J5X3BhcnR5X25fY292LA0KICAgICAgaGVhZGVycyA9IGMoDQogICAgICAgIHJlcCgi5YWx5aSJ6YeP44Gq44GXIiwgbGVuZ3RoKG1vZGVsc19ieV9wYXJ0eV9uX25vY292KSksDQogICAgICAgIHJlcCgi5YWx5aSJ6YeP44GC44KKIiwgbGVuZ3RoKG1vZGVsc19ieV9wYXJ0eV9uX2NvdikpDQogICAgICApDQogICAgKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsICJhbWNlX25vY292X2FuZF9jb3ZfbW9kZWxzLnR4dCIpDQogICkNCg0KICBhbWNlX3Bsb3RfY292IDwtIG1ha2VfYW1jZV9wbG90X2RmKG1vZGVsc19ieV9wYXJ0eV9uX2NvdikNCiAgd3JpdGVfY3N2X3NhZmVseShhbWNlX3Bsb3RfY292LCAiYW1jZV9jb3ZfY29lZmZpY2llbnRzLmNzdiIpDQoNCg0KICBzdHVkeV9sYWJlbCA8LSAi5a6f6aiTMu+8iDIwMjblubTvvIkiDQoNCiAgdGVybV9sYWJlbHNfZmFjZXQgPC0gdGVybV9sYWJlbHMgJT4lDQogICAgbXV0YXRlKA0KICAgICAgYXR0cmlidXRlX2ZhY2V0ID0gYXR0cmlidXRlDQogICAgKQ0KDQogIGF0dHJpYnV0ZV9vcmRlcl9mYWNldCA8LSBjKA0KICAgICLkuI7lhZrvvI/ph47lhZoiLA0KICAgICLmlL/nrZbkvY3nva4iLA0KICAgICLorbDluK3mlbAiLA0KICAgICJHRFDmiJDplbfnjociLA0KICAgICLml6XntYzlubPlnYciLA0KICAgICJDUEkiLA0KICAgICLlpLHmpa3njociDQogICkNCg0KICBtYWtlX2FtY2VfZmFjZXRfZGYgPC0gZnVuY3Rpb24obW9kZWxzKSB7DQogICAgaW1hcF9kZnIoDQogICAgICBtb2RlbHMsDQogICAgICB+IHRpZHlfZml4ZXN0KC54KSAlPiUNCiAgICAgICAgbXV0YXRlKHBhcnR5X24gPSBhcy5jaGFyYWN0ZXIoLnkpKQ0KICAgICkgJT4lDQogICAgICBsZWZ0X2pvaW4odGVybV9sYWJlbHNfZmFjZXQsIGJ5ID0gInRlcm0iKSAlPiUNCiAgICAgIGZpbHRlcighaXMubmEoYXR0cmlidXRlX2ZhY2V0KSkgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsDQogICAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsDQogICAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwNCiAgICAgICAgcGFydHlfbiA9IGZhY3RvcigNCiAgICAgICAgICBwYXJ0eV9uLA0KICAgICAgICAgIGxldmVscyA9IGMoIjIiLCAiMyIsICI0IiwgIjUiKSwNCiAgICAgICAgICBsYWJlbHMgPSBjKCIy5pS/5YWaIiwgIjPmlL/lhZoiLCAiNOaUv+WFmiIsICI15pS/5YWaIikNCiAgICAgICAgKSwNCiAgICAgICAgYXR0cmlidXRlX2ZhY2V0ID0gZmFjdG9yKA0KICAgICAgICAgIGF0dHJpYnV0ZV9mYWNldCwNCiAgICAgICAgICBsZXZlbHMgPSBhdHRyaWJ1dGVfb3JkZXJfZmFjZXQNCiAgICAgICAgKSwNCiAgICAgICAgbGFiZWwgPSBmYWN0b3IoDQogICAgICAgICAgbGFiZWwsDQogICAgICAgICAgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKQ0KICAgICAgICApDQogICAgICApDQogIH0NCg0KICBhbWNlX3Bsb3RfZGZfY292X2ZhY2V0IDwtIG1ha2VfYW1jZV9mYWNldF9kZihtb2RlbHNfYnlfcGFydHlfbl9jb3YpDQogIGFtY2VfcGxvdF9kZl9ub2Nvdl9mYWNldCA8LSBtYWtlX2FtY2VfZmFjZXRfZGYobW9kZWxzX2J5X3BhcnR5X25fbm9jb3YpDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBhbWNlX3Bsb3RfZGZfY292X2ZhY2V0LA0KICAgICJhbWNlX2Nvdl9mYWNldF9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBhbWNlX3Bsb3RfZGZfbm9jb3ZfZmFjZXQsDQogICAgImFtY2Vfbm9jb3ZfZmFjZXRfY29lZmZpY2llbnRzLmNzdiINCiAgKQ0KDQoNCiAgcF9hbWNlX2Nvdl9mYWNldCA8LSBnZ3Bsb3QoDQogICAgYW1jZV9wbG90X2RmX2Nvdl9mYWNldCwNCiAgICBhZXMoDQogICAgICB4ID0gZXN0aW1hdGVfcHAsDQogICAgICB5ID0gbGFiZWwsDQogICAgICBzaGFwZSA9IHBhcnR5X24sDQogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sDQogICAgICBncm91cCA9IHBhcnR5X24NCiAgICApDQogICkgKw0KICAgIGdlb21fdmxpbmUoDQogICAgICB4aW50ZXJjZXB0ID0gMCwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsDQogICAgICBjb2xvciA9ICJncmV5MzUiDQogICAgKSArDQogICAgZ2VvbV9lcnJvcmJhcmgoDQogICAgICBhZXMoDQogICAgICAgIHhtaW4gPSBjb25mLmxvd19wcCwNCiAgICAgICAgeG1heCA9IGNvbmYuaGlnaF9wcA0KICAgICAgKSwNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwNCiAgICAgIGhlaWdodCA9IDAuMTYsDQogICAgICBsaW5ld2lkdGggPSAwLjU1LA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9wb2ludCgNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwNCiAgICAgIHNpemUgPSAyLjUsDQogICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICBmaWxsID0gIndoaXRlIiwNCiAgICAgIHN0cm9rZSA9IDAuOA0KICAgICkgKw0KICAgIGZhY2V0X2dyaWQoDQogICAgICBhdHRyaWJ1dGVfZmFjZXQgfiAuLA0KICAgICAgc2NhbGVzID0gImZyZWVfeSIsDQogICAgICBzcGFjZSA9ICJmcmVlX3kiLA0KICAgICAgc3dpdGNoID0gInkiDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgsICIgcHAiKSwNCiAgICAgIGJyZWFrcyA9IHNlcSgtMTIsIDEyLCBieSA9IDIpDQogICAgKSArDQogICAgc2NhbGVfc2hhcGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjLmlL/lhZoiID0gMTYsDQogICAgICAgICIz5pS/5YWaIiA9IDE3LA0KICAgICAgICAiNOaUv+WFmiIgPSAxNSwNCiAgICAgICAgIjXmlL/lhZoiID0gMQ0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICAgIG5hbWUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIiwNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICIy5pS/5YWaIiA9ICJzb2xpZCIsDQogICAgICAgICIz5pS/5YWaIiA9ICJkYXNoZWQiLA0KICAgICAgICAiNOaUv+WFmiIgPSAiZG90dGVkIiwNCiAgICAgICAgIjXmlL/lhZoiID0gImRvdGRhc2giDQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHggPSAi6YG45oqe56K6546H44Gu5aSJ5YyWIiwNCiAgICAgIHkgPSBOVUxMDQogICAgKSArDQogICAgdGhlbWVfYncoDQogICAgICBiYXNlX3NpemUgPSAxMiwNCiAgICAgIGJhc2VfZmFtaWx5ID0gIll1IEdvdGhpYyINCiAgICApICsNCiAgICB0aGVtZSgNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIHNpemUgPSAxNg0KICAgICAgKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwNCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGZpbGwgPSAiZ3JleTkyIiwNCiAgICAgICAgY29sb3IgPSAiZ3JleTU1Ig0KICAgICAgKSwNCiAgICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBhbmdsZSA9IDAsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIHNpemUgPSAxMA0KICAgICAgKSwNCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwNCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKQ0KICAgICkNCg0KICBwcmludChwX2FtY2VfY292X2ZhY2V0KQ0KDQogIHNhdmVfcGxvdCgNCiAgICAiYW1jZV9jb3ZfZmFjZXRfbW9kZWwucG5nIiwNCiAgICBwX2FtY2VfY292X2ZhY2V0LA0KICAgIHdpZHRoID0gMTAuNSwNCiAgICBoZWlnaHQgPSA4LjUNCiAgKQ0KDQogIHBfYW1jZV9jb3ZfbWFpbiA8LSBwX2FtY2VfY292X2ZhY2V0DQoNCg0KICBtYWtlX2hlYXRtYXBfZGYgPC0gZnVuY3Rpb24oYW1jZV9wbG90X2RmKSB7DQogICAgaGVhdF9kZiA8LSBhbWNlX3Bsb3RfZGYgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGFic19hbWNlID0gYWJzKGVzdGltYXRlX3BwKSwNCiAgICAgICAgY3VlX3R5cGVfY29kZSA9IGNhc2Vfd2hlbigNCiAgICAgICAgICBjdWVfdHlwZSA9PSAi5pS/5YWa44Gu5omL44GM44GL44KKIiB+ICJwYXJ0eSIsDQogICAgICAgICAgY3VlX3R5cGUgPT0gIue1jOa4iOOBruaJi+OBjOOBi+OCiiIgfiAiZWNvbm9teSIsDQogICAgICAgICAgVFJVRSB+ICJvdGhlciINCiAgICAgICAgKQ0KICAgICAgKSAlPiUNCiAgICAgIGdyb3VwX2J5KHBhcnR5X24pICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICByYW5rX3dpdGhpbl9wYXJ0eSA9IG1pbl9yYW5rKGRlc2MoYWJzX2FtY2UpKSwNCiAgICAgICAgbl9pbl9jb2wgPSBuKCksDQogICAgICAgIHJhbmtfc2NvcmUgPSBpZl9lbHNlKA0KICAgICAgICAgIG5faW5fY29sID09IDEsDQogICAgICAgICAgMSwNCiAgICAgICAgICAxIC0gKHJhbmtfd2l0aGluX3BhcnR5IC0gMSkgLyAobl9pbl9jb2wgLSAxKQ0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgdW5ncm91cCgpDQoNCiAgICByb3dfb3JkZXJfZGYgPC0gaGVhdF9kZiAlPiUNCiAgICAgIGdyb3VwX2J5KGxhYmVsLCBjdWVfdHlwZV9jb2RlKSAlPiUNCiAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgbWVhbl9hYnNfYW1jZSA9IG1lYW4oYWJzX2FtY2UsIG5hLnJtID0gVFJVRSksDQogICAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICAgICkgJT4lDQogICAgICBhcnJhbmdlKGRlc2MobWVhbl9hYnNfYW1jZSkpDQoNCiAgICByb3dfbGV2ZWxzIDwtIGFzLmNoYXJhY3Rlcihyb3dfb3JkZXJfZGYkbGFiZWwpDQoNCiAgICBoZWF0X2RmIDwtIGhlYXRfZGYgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGxhYmVsID0gZmFjdG9yKA0KICAgICAgICAgIGFzLmNoYXJhY3RlcihsYWJlbCksDQogICAgICAgICAgbGV2ZWxzID0gcmV2KHJvd19sZXZlbHMpDQogICAgICAgICkNCiAgICAgICkNCg0KICAgIGxhYmVsX2NvbG9yX21hcCA8LSByb3dfb3JkZXJfZGYgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGxhYmVsX21hcmtkb3duID0gY2FzZV93aGVuKA0KICAgICAgICAgIGN1ZV90eXBlX2NvZGUgPT0gInBhcnR5IiB+DQogICAgICAgICAgICBwYXN0ZTAoDQogICAgICAgICAgICAgICI8c3BhbiBzdHlsZT0nY29sb3I6IzExMTExMTsnPiIsDQogICAgICAgICAgICAgIGxhYmVsLA0KICAgICAgICAgICAgICAiPC9zcGFuPiINCiAgICAgICAgICAgICksDQogICAgICAgICAgY3VlX3R5cGVfY29kZSA9PSAiZWNvbm9teSIgfg0KICAgICAgICAgICAgcGFzdGUwKA0KICAgICAgICAgICAgICAiPHNwYW4gc3R5bGU9J2NvbG9yOiM4QThBOEE7Jz4iLA0KICAgICAgICAgICAgICBsYWJlbCwNCiAgICAgICAgICAgICAgIjwvc3Bhbj4iDQogICAgICAgICAgICApLA0KICAgICAgICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIobGFiZWwpDQogICAgICAgICkNCiAgICAgICkNCg0KICAgIGxhYmVsX21hcmtkb3duX3ZlYyA8LSBzZXROYW1lcygNCiAgICAgIGxhYmVsX2NvbG9yX21hcCRsYWJlbF9tYXJrZG93biwNCiAgICAgIGFzLmNoYXJhY3RlcihsYWJlbF9jb2xvcl9tYXAkbGFiZWwpDQogICAgKQ0KDQogICAgbGlzdCgNCiAgICAgIGhlYXRfZGYgPSBoZWF0X2RmLA0KICAgICAgbGFiZWxfbWFya2Rvd25fdmVjID0gbGFiZWxfbWFya2Rvd25fdmVjDQogICAgKQ0KICB9DQoNCiAgcGxvdF9hbWNlX2hlYXRtYXAgPC0gZnVuY3Rpb24oDQogICAgICBoZWF0X2RmLA0KICAgICAgbGFiZWxfbWFya2Rvd25fdmVjLA0KICAgICAgd2l0aF9yYW5rID0gVFJVRSwNCiAgICAgIHRpdGxlX3RleHQgPSBOVUxMKSB7DQoNCiAgICBpZiAod2l0aF9yYW5rKSB7DQogICAgICBoZWF0X2RmIDwtIGhlYXRfZGYgJT4lDQogICAgICAgIG11dGF0ZSgNCiAgICAgICAgICBjZWxsX2xhYmVsID0gcGFzdGUwKA0KICAgICAgICAgICAgc3ByaW50ZigiJS4xZiIsIGVzdGltYXRlX3BwKSwNCiAgICAgICAgICAgICJcbigiLA0KICAgICAgICAgICAgcmFua193aXRoaW5fcGFydHksDQogICAgICAgICAgICAi5L2NKSINCiAgICAgICAgICApDQogICAgICAgICkNCg0KICAgICAgdGV4dF9zaXplIDwtIDMuMA0KICAgICAgbGluZWhlaWdodCA8LSAwLjkNCiAgICB9IGVsc2Ugew0KICAgICAgaGVhdF9kZiA8LSBoZWF0X2RmICU+JQ0KICAgICAgICBtdXRhdGUoDQogICAgICAgICAgY2VsbF9sYWJlbCA9IHNwcmludGYoIiUuMWYiLCBlc3RpbWF0ZV9wcCkNCiAgICAgICAgKQ0KDQogICAgICB0ZXh0X3NpemUgPC0gMy40DQogICAgICBsaW5laGVpZ2h0IDwtIDEuMA0KICAgIH0NCg0KICAgIGdncGxvdCgNCiAgICAgIGhlYXRfZGYsDQogICAgICBhZXMoDQogICAgICAgIHggPSBwYXJ0eV9uLA0KICAgICAgICB5ID0gbGFiZWwsDQogICAgICAgIGZpbGwgPSByYW5rX3Njb3JlDQogICAgICApDQogICAgKSArDQogICAgICBnZW9tX3RpbGUoDQogICAgICAgIGNvbG9yID0gIndoaXRlIiwNCiAgICAgICAgbGluZXdpZHRoID0gMC43DQogICAgICApICsNCiAgICAgIGdlb21fdGV4dCgNCiAgICAgICAgYWVzKGxhYmVsID0gY2VsbF9sYWJlbCksDQogICAgICAgIHNpemUgPSB0ZXh0X3NpemUsDQogICAgICAgIGZvbnRmYWNlID0gImJvbGQiLA0KICAgICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICAgIGxpbmVoZWlnaHQgPSBsaW5laGVpZ2h0DQogICAgICApICsNCiAgICAgIHNjYWxlX3lfZGlzY3JldGUoDQogICAgICAgIGxhYmVscyA9IGxhYmVsX21hcmtkb3duX3ZlYw0KICAgICAgKSArDQogICAgICBzY2FsZV9maWxsX2dyYWRpZW50KA0KICAgICAgICBsb3cgPSAiZ3JleTk1IiwNCiAgICAgICAgaGlnaCA9ICJncmV5MTUiLA0KICAgICAgICBsaW1pdHMgPSBjKDAsIDEpLA0KICAgICAgICBicmVha3MgPSBjKDAsIDAuMjUsIDAuNTAsIDAuNzUsIDEuMDApLA0KICAgICAgICBsYWJlbHMgPSBjKCLkvY4iLCAiIiwgIiIsICIiLCAi6auYIiksDQogICAgICAgIG5hbWUgPSAi5YiX5YaF6aCG5L2NXG7vvIjmv4PjgYTjgbvjganpq5jkvY3vvIkiDQogICAgICApICsNCiAgICAgIGxhYnMoDQogICAgICAgIHRpdGxlID0gdGl0bGVfdGV4dCwNCiAgICAgICAgeCA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLA0KICAgICAgICB5ID0gTlVMTA0KICAgICAgKSArDQogICAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikgKw0KICAgICAgdGhlbWUoDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgICAgIGF4aXMudGV4dC55ID0gZ2d0ZXh0OjplbGVtZW50X21hcmtkb3duKHNpemUgPSA5KSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpDQogICAgICApDQogIH0NCg0KICBoZWF0bWFwX2lucHV0IDwtIG1ha2VfaGVhdG1hcF9kZihhbWNlX3Bsb3RfY292KQ0KDQogIHBfaGVhdF9hbWNlX21peGVkIDwtIHBsb3RfYW1jZV9oZWF0bWFwKA0KICAgIGhlYXRtYXBfaW5wdXQkaGVhdF9kZiwNCiAgICBoZWF0bWFwX2lucHV0JGxhYmVsX21hcmtkb3duX3ZlYywNCiAgICB3aXRoX3JhbmsgPSBGQUxTRSwNCiAgICB0aXRsZV90ZXh0ID0gTlVMTA0KICApDQoNCiAgcHJpbnQocF9oZWF0X2FtY2VfbWl4ZWQpDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX2hlYXRtYXBfbWl4ZWRfcmFua19jb2xvcmVkX2xhYmVscy5wbmciLA0KICAgIHBfaGVhdF9hbWNlX21peGVkLA0KICAgIHdpZHRoID0gOC44LA0KICAgIGhlaWdodCA9IDguOA0KICApDQoNCiAgcF9oZWF0X2FtY2VfbWl4ZWRfcmFua2xhYmVsIDwtIHBsb3RfYW1jZV9oZWF0bWFwKA0KICAgIGhlYXRtYXBfaW5wdXQkaGVhdF9kZiwNCiAgICBoZWF0bWFwX2lucHV0JGxhYmVsX21hcmtkb3duX3ZlYywNCiAgICB3aXRoX3JhbmsgPSBUUlVFLA0KICAgIHRpdGxlX3RleHQgPSBOVUxMDQogICkNCg0KICBwcmludChwX2hlYXRfYW1jZV9taXhlZF9yYW5rbGFiZWwpDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX2hlYXRtYXBfbWl4ZWRfcmFua19jb2xvcmVkX2xhYmVsc193aXRocmFuay5wbmciLA0KICAgIHBfaGVhdF9hbWNlX21peGVkX3JhbmtsYWJlbCwNCiAgICB3aWR0aCA9IDguOCwNCiAgICBoZWlnaHQgPSA4LjgNCiAgKQ0KDQogIHBfaGVhdF9hbWNlIDwtIHBfaGVhdF9hbWNlX21peGVkDQogIHBfaGVhdF9hbWNlX3JhbmsgPC0gcF9oZWF0X2FtY2VfbWl4ZWRfcmFua2xhYmVsDQoNCg0KICBwX2FtY2VfZmFjZXRfbm9jb3YgPC0gZ2dwbG90KA0KICAgIGFtY2VfcGxvdF9kZl9ub2Nvdl9mYWNldCwNCiAgICBhZXMoDQogICAgICB4ID0gZXN0aW1hdGVfcHAsDQogICAgICB5ID0gbGFiZWwsDQogICAgICBzaGFwZSA9IHBhcnR5X24sDQogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sDQogICAgICBncm91cCA9IHBhcnR5X24NCiAgICApDQogICkgKw0KICAgIGdlb21fdmxpbmUoDQogICAgICB4aW50ZXJjZXB0ID0gMCwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsDQogICAgICBjb2xvciA9ICJncmV5MzUiDQogICAgKSArDQogICAgZ2VvbV9lcnJvcmJhcmgoDQogICAgICBhZXMoDQogICAgICAgIHhtaW4gPSBjb25mLmxvd19wcCwNCiAgICAgICAgeG1heCA9IGNvbmYuaGlnaF9wcA0KICAgICAgKSwNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwNCiAgICAgIGhlaWdodCA9IDAuMTYsDQogICAgICBsaW5ld2lkdGggPSAwLjU1LA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9wb2ludCgNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwNCiAgICAgIHNpemUgPSAyLjUsDQogICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICBmaWxsID0gIndoaXRlIiwNCiAgICAgIHN0cm9rZSA9IDAuOA0KICAgICkgKw0KICAgIGZhY2V0X2dyaWQoDQogICAgICBhdHRyaWJ1dGVfZmFjZXQgfiAuLA0KICAgICAgc2NhbGVzID0gImZyZWVfeSIsDQogICAgICBzcGFjZSA9ICJmcmVlX3kiLA0KICAgICAgc3dpdGNoID0gInkiDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgsICIgcHAiKSwNCiAgICAgIGJyZWFrcyA9IHNlcSgtMTIsIDEyLCBieSA9IDIpDQogICAgKSArDQogICAgc2NhbGVfc2hhcGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICLmlL/lhZrmlbDpgbjmip7ogqIiLA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjLmlL/lhZoiID0gMTYsDQogICAgICAgICIz5pS/5YWaIiA9IDE3LA0KICAgICAgICAiNOaUv+WFmiIgPSAxNSwNCiAgICAgICAgIjXmlL/lhZoiID0gMQ0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICAgIG5hbWUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIiwNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICIy5pS/5YWaIiA9ICJzb2xpZCIsDQogICAgICAgICIz5pS/5YWaIiA9ICJkYXNoZWQiLA0KICAgICAgICAiNOaUv+WFmiIgPSAiZG90dGVkIiwNCiAgICAgICAgIjXmlL/lhZoiID0gImRvdGRhc2giDQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHggPSAi6YG45oqe56K6546H44Gu5aSJ5YyWIiwNCiAgICAgIHkgPSBOVUxMDQogICAgKSArDQogICAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpICsNCiAgICB0aGVtZSgNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIHNpemUgPSAxNg0KICAgICAgKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwNCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGZpbGwgPSAiZ3JleTkyIiwNCiAgICAgICAgY29sb3IgPSAiZ3JleTU1Ig0KICAgICAgKSwNCiAgICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBhbmdsZSA9IDAsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIHNpemUgPSAxMA0KICAgICAgKSwNCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwNCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKQ0KICAgICkNCg0KICBwcmludChwX2FtY2VfZmFjZXRfbm9jb3YpDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX2ZhY2V0X25vY292LnBuZyIsDQogICAgcF9hbWNlX2ZhY2V0X25vY292LA0KICAgIHdpZHRoID0gMTAuNSwNCiAgICBoZWlnaHQgPSA5DQogICkNCg0KICBwX2FtY2Vfbm9jb3ZfYXBwZW5kaXggPC0gcF9hbWNlX2ZhY2V0X25vY292DQoNCg0KICBwX2ludGVyYWN0aW9uIDwtIGdncGxvdCgNCiAgICBpbnRlcmFjdGlvbl9wbG90X2RmLA0KICAgIGFlcygNCiAgICAgIHggPSBlc3RpbWF0ZV9wcCwNCiAgICAgIHkgPSBsYWJlbCwNCiAgICAgIHNoYXBlID0gcGFydHlfbl9sYWJlbCwNCiAgICAgIGxpbmV0eXBlID0gcGFydHlfbl9sYWJlbCwNCiAgICAgIGdyb3VwID0gcGFydHlfbl9sYWJlbA0KICAgICkNCiAgKSArDQogICAgZ2VvbV92bGluZSgNCiAgICAgIHhpbnRlcmNlcHQgPSAwLA0KICAgICAgbGluZXdpZHRoID0gMC40NSwNCiAgICAgIGNvbG9yID0gImdyZXkzNSINCiAgICApICsNCiAgICBnZW9tX2Vycm9yYmFyaCgNCiAgICAgIGFlcygNCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLA0KICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwDQogICAgICApLA0KICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgICAgaGVpZ2h0ID0gMC4xNiwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNTUsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX3BvaW50KA0KICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgc3Ryb2tlID0gMC44DQogICAgKSArDQogICAgZmFjZXRfZ3JpZCgNCiAgICAgIGF0dHJpYnV0ZSB+IC4sDQogICAgICBzY2FsZXMgPSAiZnJlZV95IiwNCiAgICAgIHNwYWNlID0gImZyZWVfeSIsDQogICAgICBzd2l0Y2ggPSAieSINCiAgICApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIiBwcCIpLA0KICAgICAgYnJlYWtzID0gc2VxKC04LCA4LCBieSA9IDIpDQogICAgKSArDQogICAgc2NhbGVfc2hhcGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICIy5pS/5YWa44Gu5aC05ZCI44Go44Gu5q+U6LyDIiwNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICIz5pS/5YWaIiA9IDE3LA0KICAgICAgICAiNOaUv+WFmiIgPSAxNSwNCiAgICAgICAgIjXmlL/lhZoiID0gMQ0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICAgIG5hbWUgPSAiMuaUv+WFmuOBruWgtOWQiOOBqOOBruavlOi8gyIsDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiM+aUv+WFmiIgPSAiZGFzaGVkIiwNCiAgICAgICAgIjTmlL/lhZoiID0gImRvdHRlZCIsDQogICAgICAgICI15pS/5YWaIiA9ICJkb3RkYXNoIg0KICAgICAgKQ0KICAgICkgKw0KICAgIGxhYnMoDQogICAgICB4ID0gIjLmlL/lhZrmnaHku7bjgajjga7lt64iLA0KICAgICAgeSA9IE5VTEwNCiAgICApICsNCiAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDE1DQogICAgICApLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiLA0KICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgNCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLA0KICAgICAgICBjb2xvciA9ICJncmV5NTUiDQogICAgICApLA0KICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGFuZ2xlID0gMCwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDEwDQogICAgICApLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLA0KICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpDQogICAgKQ0KDQogIHByaW50KHBfaW50ZXJhY3Rpb24pDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX2ludGVyYWN0aW9uX2RpZmZlcmVuY2VfZnJvbV8ycGFydHkucG5nIiwNCiAgICBwX2ludGVyYWN0aW9uLA0KICAgIHdpZHRoID0gMTAuNSwNCiAgICBoZWlnaHQgPSA5DQogICkNCg0KDQogIGNvbmpvaW50X2Nsb2dpdCA8LSBjb25qb2ludF9hbGxfbSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBzZWxlY3RlZCA9IGFzLmludGVnZXIoc2VsZWN0ZWQpLA0KICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLA0KICAgICAgdGFza19pZCA9IGZhY3Rvcih0YXNrX2lkKSwNCiAgICAgIHBvbGljeV9wb3NpdGlvbiA9IHJlbGV2ZWxfaWZfcHJlc2VudCgNCiAgICAgICAgcG9saWN5X3Bvc2l0aW9uLA0KICAgICAgICAi5Lit6YGTIg0KICAgICAgKSwNCiAgICAgIGdvdmVybm1lbnRfc3RhdHVzID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBnb3Zlcm5tZW50X3N0YXR1cywNCiAgICAgICAgIumHjuWFmiINCiAgICAgICksDQogICAgICBnZHBfZ3Jvd3RoID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBnZHBfZ3Jvd3RoLA0KICAgICAgICAiR0RQ5oiQ6ZW3546HwrEw77yFIg0KICAgICAgKSwNCiAgICAgIG5pa2tlaSA9IHJlbGV2ZWxfaWZfcHJlc2VudCgNCiAgICAgICAgbmlra2VpLA0KICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIg0KICAgICAgKSwNCiAgICAgIHNlYXRzID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBzZWF0cywNCiAgICAgICAgIjEw5Lul5LiLIg0KICAgICAgKSwNCiAgICAgIGNwaSA9IHJlbGV2ZWxfaWZfcHJlc2VudCgNCiAgICAgICAgY3BpLA0KICAgICAgICAiQ1BJ5YmN5pyf5q+UwrEw44Od44Kk44Oz44OIIg0KICAgICAgKSwNCiAgICAgIHVuZW1wbG95bWVudCA9IHJlbGV2ZWxfaWZfcHJlc2VudCgNCiAgICAgICAgdW5lbXBsb3ltZW50LA0KICAgICAgICAi5aSx5qWt546H5YmN5pyf5q+UwrEw77yFIg0KICAgICAgKQ0KICAgICkNCg0KICBmb3JtdWxhX2Nsb2dpdF9ub2NvdiA8LSBhcy5mb3JtdWxhKA0KICAgIHBhc3RlMCgNCiAgICAgICJzZWxlY3RlZCB+ICIsDQogICAgICBwYXN0ZShhdHRyX3Rlcm1zLCBjb2xsYXBzZSA9ICIgKyAiKSwNCiAgICAgICIgKyBzdHJhdGEodGFza19pZCkgKyBjbHVzdGVyKElEKSINCiAgICApDQogICkNCg0KICBydW5fY2xvZ2l0X25vY292IDwtIGZ1bmN0aW9uKGRhdCkgew0KICAgIHN1cnZpdmFsOjpjbG9naXQoDQogICAgICBmb3JtdWxhX2Nsb2dpdF9ub2NvdiwNCiAgICAgIGRhdGEgPSBkYXQsDQogICAgICBtZXRob2QgPSAiZWZyb24iDQogICAgKQ0KICB9DQoNCiAgbW9kZWxzX2Nsb2dpdF9ub2NvdiA8LSBjb25qb2ludF9jbG9naXQgJT4lDQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUNCiAgICBtYXAocnVuX2Nsb2dpdF9ub2NvdikNCg0KICBjYXB0dXJlLm91dHB1dCgNCiAgICBsYXBwbHkobW9kZWxzX2Nsb2dpdF9ub2Nvdiwgc3VtbWFyeSksDQogICAgZmlsZSA9IGZpbGUucGF0aCgNCiAgICAgIG91dHB1dF9kaXIsDQogICAgICAiY29uZGl0aW9uYWxfbG9naXRfbW9kZWxzLnR4dCINCiAgICApDQogICkNCg0KICB0aWR5X2Nsb2dpdCA8LSBmdW5jdGlvbihtb2RlbCkgew0KICAgIHMgPC0gc3VtbWFyeShtb2RlbCkNCiAgICBjdCA8LSBhcy5kYXRhLmZyYW1lKHMkY29lZmZpY2llbnRzKQ0KICAgIGN0JHRlcm0gPC0gcm93bmFtZXMoY3QpDQoNCiAgICBzZV9jb2wgPC0gaWYgKCJyb2J1c3Qgc2UiICVpbiUgbmFtZXMoY3QpKSB7DQogICAgICAicm9idXN0IHNlIg0KICAgIH0gZWxzZSBpZiAoInNlKGNvZWYpIiAlaW4lIG5hbWVzKGN0KSkgew0KICAgICAgInNlKGNvZWYpIg0KICAgIH0gZWxzZSB7DQogICAgICBzdG9wKCJDaGVjayBjbG9naXQiKQ0KICAgIH0NCg0KICAgIHBfY29sIDwtIGlmICgiUHIoPnx6fCkiICVpbiUgbmFtZXMoY3QpKSB7DQogICAgICAiUHIoPnx6fCkiDQogICAgfSBlbHNlIGlmICgiUHIoPnx0fCkiICVpbiUgbmFtZXMoY3QpKSB7DQogICAgICAiUHIoPnx0fCkiDQogICAgfSBlbHNlIHsNCiAgICAgIE5BX2NoYXJhY3Rlcl8NCiAgICB9DQoNCiAgICBjdCAlPiUNCiAgICAgIGFzX3RpYmJsZSgpICU+JQ0KICAgICAgdHJhbnNtdXRlKA0KICAgICAgICB0ZXJtID0gdGVybSwNCiAgICAgICAgZXN0aW1hdGUgPSBjb2VmLA0KICAgICAgICBzdGQuZXJyb3IgPSAuZGF0YVtbc2VfY29sXV0sDQogICAgICAgIHAudmFsdWUgPSBpZiAoIWlzLm5hKHBfY29sKSkgew0KICAgICAgICAgIC5kYXRhW1twX2NvbF1dDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgTkFfcmVhbF8NCiAgICAgICAgfSwNCiAgICAgICAgY29uZi5sb3cgPSBlc3RpbWF0ZSAtIDEuOTYgKiBzdGQuZXJyb3IsDQogICAgICAgIGNvbmYuaGlnaCA9IGVzdGltYXRlICsgMS45NiAqIHN0ZC5lcnJvciwNCiAgICAgICAgb2Rkc19yYXRpbyA9IGV4cChlc3RpbWF0ZSksDQogICAgICAgIG9kZHNfcmF0aW9fbG93ID0gZXhwKGNvbmYubG93KSwNCiAgICAgICAgb2Rkc19yYXRpb19oaWdoID0gZXhwKGNvbmYuaGlnaCkNCiAgICAgICkNCiAgfQ0KDQogIGNsb2dpdF9wbG90X2RmIDwtIGltYXBfZGZyKA0KICAgIG1vZGVsc19jbG9naXRfbm9jb3YsDQogICAgfiB0aWR5X2Nsb2dpdCgueCkgJT4lDQogICAgICBtdXRhdGUocGFydHlfbiA9IGFzLmNoYXJhY3RlcigueSkpDQogICkgJT4lDQogICAgbGVmdF9qb2luKHRlcm1fbGFiZWxzLCBieSA9ICJ0ZXJtIikgJT4lDQogICAgZmlsdGVyKCFpcy5uYShhdHRyaWJ1dGUpKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBwYXJ0eV9uID0gZmFjdG9yKA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBsZXZlbHMgPSBjKCIyIiwgIjMiLCAiNCIsICI1IiksDQogICAgICAgIGxhYmVscyA9IGMoIjLmlL/lhZoiLCAiM+aUv+WFmiIsICI05pS/5YWaIiwgIjXmlL/lhZoiKQ0KICAgICAgKSwNCiAgICAgIGxhYmVsID0gZmFjdG9yKA0KICAgICAgICBsYWJlbCwNCiAgICAgICAgbGV2ZWxzID0gcmV2KGxhYmVsX29yZGVyKQ0KICAgICAgKQ0KICAgICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGNsb2dpdF9wbG90X2RmLA0KICAgICJjb25kaXRpb25hbF9sb2dpdF9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCg0KICBwX2Nsb2dpdF9vciA8LSBnZ3Bsb3QoDQogICAgY2xvZ2l0X3Bsb3RfZGYsDQogICAgYWVzKA0KICAgICAgeCA9IG9kZHNfcmF0aW8sDQogICAgICB5ID0gbGFiZWwsDQogICAgICBzaGFwZSA9IHBhcnR5X24sDQogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sDQogICAgICBncm91cCA9IHBhcnR5X24NCiAgICApDQogICkgKw0KICAgIGdlb21fdmxpbmUoDQogICAgICB4aW50ZXJjZXB0ID0gMSwNCiAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIsDQogICAgICBsaW5ld2lkdGggPSAwLjQ1LA0KICAgICAgY29sb3IgPSAiZ3JleTM1Ig0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXJoKA0KICAgICAgYWVzKA0KICAgICAgICB4bWluID0gb2Rkc19yYXRpb19sb3csDQogICAgICAgIHhtYXggPSBvZGRzX3JhdGlvX2hpZ2gNCiAgICAgICksDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43MiksDQogICAgICBoZWlnaHQgPSAwLjE1LA0KICAgICAgbGluZXdpZHRoID0gMC40NSwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fcG9pbnQoDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43MiksDQogICAgICBzaXplID0gMi40LA0KICAgICAgc3Ryb2tlID0gMC43LA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgc2NhbGVfeF9sb2cxMCgNCiAgICAgIGJyZWFrcyA9IGMoDQogICAgICAgIDAuNiwNCiAgICAgICAgMC44LA0KICAgICAgICAxLjAsDQogICAgICAgIDEuMjUsDQogICAgICAgIDEuNSwNCiAgICAgICAgMi4wDQogICAgICApLA0KICAgICAgbGFiZWxzID0gYygNCiAgICAgICAgIjAuNiIsDQogICAgICAgICIwLjgiLA0KICAgICAgICAiMS4wIiwNCiAgICAgICAgIjEuMjUiLA0KICAgICAgICAiMS41IiwNCiAgICAgICAgIjIuMCINCiAgICAgICkNCiAgICApICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiMuaUv+WFmiIgPSAxNiwNCiAgICAgICAgIjPmlL/lhZoiID0gMTcsDQogICAgICAgICI05pS/5YWaIiA9IDE1LA0KICAgICAgICAiNeaUv+WFmiIgPSAxDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjLmlL/lhZoiID0gInNvbGlkIiwNCiAgICAgICAgIjPmlL/lhZoiID0gImRhc2hlZCIsDQogICAgICAgICI05pS/5YWaIiA9ICJkb3RkYXNoIiwNCiAgICAgICAgIjXmlL/lhZoiID0gInR3b2Rhc2giDQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHggPSAi44Kq44OD44K65q+UIiwNCiAgICAgIHkgPSBOVUxMLA0KICAgICAgc2hhcGUgPSAi5pS/5YWa5pWw6YG45oqe6IKiIiwNCiAgICAgIGxpbmV0eXBlID0gIuaUv+WFmuaVsOmBuOaKnuiCoiINCiAgICApICsNCiAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikgKw0KICAgIHRoZW1lKA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KQ0KICAgICkNCg0KICBwcmludChwX2Nsb2dpdF9vcikNCg0KICBzYXZlX3Bsb3QoDQogICAgImNsb2dpdF9vZGRzcmF0aW9fbm9jb3YucG5nIiwNCiAgICBwX2Nsb2dpdF9vciwNCiAgICB3aWR0aCA9IDEwLjUsDQogICAgaGVpZ2h0ID0gOC41DQogICkNCg0KDQogIHJlbGF0aXZlX2N1ZV9tYXAgPC0gYygNCiAgICBwb2xpY3lfcG9zaXRpb24gPSAicGFydHkiLA0KICAgIGdvdmVybm1lbnRfc3RhdHVzID0gInBhcnR5IiwNCiAgICBzZWF0cyA9ICJwYXJ0eSIsDQogICAgZ2RwX2dyb3d0aCA9ICJlY29ub21pYyIsDQogICAgbmlra2VpID0gImVjb25vbWljIiwNCiAgICBjcGkgPSAiZWNvbm9taWMiLA0KICAgIHVuZW1wbG95bWVudCA9ICJlY29ub21pYyINCiAgKQ0KDQogIG1lYW5fYWJzb2x1dGVfcGFpcndpc2VfZGlmZmVyZW5jZSA8LSBmdW5jdGlvbih4KSB7DQogICAgeCA8LSB4W2lzLmZpbml0ZSh4KV0NCg0KICAgIGlmIChsZW5ndGgoeCkgPCAyKSB7DQogICAgICByZXR1cm4oTkFfcmVhbF8pDQogICAgfQ0KDQogICAgcGFpcndpc2VfZGlmZmVyZW5jZXMgPC0gY29tYm4oDQogICAgICB4LA0KICAgICAgMiwNCiAgICAgIEZVTiA9IGZ1bmN0aW9uKHopIGFicyh6WzFdIC0gelsyXSkNCiAgICApDQoNCiAgICBtZWFuKHBhaXJ3aXNlX2RpZmZlcmVuY2VzKQ0KICB9DQoNCiAgbGluZWFyX3Nsb3BlIDwtIGZ1bmN0aW9uKHksIHgpIHsNCiAgICBrZWVwIDwtIGlzLmZpbml0ZSh5KSAmIGlzLmZpbml0ZSh4KQ0KICAgIHkgPC0geVtrZWVwXQ0KICAgIHggPC0geFtrZWVwXQ0KDQogICAgaWYgKGxlbmd0aCh5KSA8IDIgfHwgbGVuZ3RoKHVuaXF1ZSh4KSkgPCAyKSB7DQogICAgICByZXR1cm4oTkFfcmVhbF8pDQogICAgfQ0KDQogICAgdW5uYW1lKGNvZWYobG0oeSB+IHgpKVsyXSkNCiAgfQ0KDQogIGJvb3RzdHJhcF90d29fc2lkZWRfcCA8LSBmdW5jdGlvbih4KSB7DQogICAgeCA8LSB4W2lzLmZpbml0ZSh4KV0NCiAgICBCX3ZhbGlkIDwtIGxlbmd0aCh4KQ0KDQogICAgaWYgKEJfdmFsaWQgPT0gMCkgew0KICAgICAgcmV0dXJuKE5BX3JlYWxfKQ0KICAgIH0NCg0KICAgIHBfbG93ZXIgPC0gKDEgKyBzdW0oeCA8PSAwKSkgLyAoQl92YWxpZCArIDEpDQogICAgcF91cHBlciA8LSAoMSArIHN1bSh4ID49IDApKSAvIChCX3ZhbGlkICsgMSkNCg0KICAgIG1pbigxLCAyICogbWluKHBfbG93ZXIsIHBfdXBwZXIpKQ0KICB9DQoNCiAgc2FmZV9xdWFudGlsZSA8LSBmdW5jdGlvbih4LCBwcm9iYWJpbGl0eSkgew0KICAgIHggPC0geFtpcy5maW5pdGUoeCldDQoNCiAgICBpZiAobGVuZ3RoKHgpID09IDApIHsNCiAgICAgIHJldHVybihOQV9yZWFsXykNCiAgICB9DQoNCiAgICB1bm5hbWUoDQogICAgICBxdWFudGlsZSgNCiAgICAgICAgeCwNCiAgICAgICAgcHJvYnMgPSBwcm9iYWJpbGl0eSwNCiAgICAgICAgdHlwZSA9IDYsDQogICAgICAgIG5hLnJtID0gVFJVRQ0KICAgICAgKQ0KICAgICkNCiAgfQ0KDQogIHByZXBhcmVfcmVsYXRpdmVfY3VlX2FuYWx5c2lzIDwtIGZ1bmN0aW9uKGRhdGEsIGN1ZV9tYXApIHsNCiAgICBhdHRyaWJ1dGVzIDwtIG5hbWVzKGN1ZV9tYXApDQoNCiAgICByZXF1aXJlZF9jb2x1bW5zIDwtIGMoDQogICAgICAiSUQiLA0KICAgICAgInBhcnR5X24iLA0KICAgICAgInNlbGVjdGVkIiwNCiAgICAgIGF0dHJpYnV0ZXMNCiAgICApDQoNCiAgICBtaXNzaW5nX2NvbHVtbnMgPC0gc2V0ZGlmZigNCiAgICAgIHJlcXVpcmVkX2NvbHVtbnMsDQogICAgICBuYW1lcyhkYXRhKQ0KICAgICkNCg0KICAgIGlmIChsZW5ndGgobWlzc2luZ19jb2x1bW5zKSA+IDApIHsNCiAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpDQogICAgfQ0KDQogICAgaWYgKCFhbGwodW5uYW1lKGN1ZV9tYXApICVpbiUgYygicGFydHkiLCAiZWNvbm9taWMiKSkpIHsNCiAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpDQogICAgfQ0KDQogICAgYW5hbHlzaXNfZGF0YSA8LSBkYXRhICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICBJRCwNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgc2VsZWN0ZWQsDQogICAgICAgIGFsbF9vZihhdHRyaWJ1dGVzKQ0KICAgICAgKSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLA0KICAgICAgICBwYXJ0eV9uID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocGFydHlfbikpLA0KICAgICAgICBzZWxlY3RlZCA9IGFzLmludGVnZXIoc2VsZWN0ZWQpLA0KICAgICAgICBhY3Jvc3MoDQogICAgICAgICAgYWxsX29mKGF0dHJpYnV0ZXMpLA0KICAgICAgICAgIGFzLmNoYXJhY3Rlcg0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICAhaXMubmEoSUQpLA0KICAgICAgICBwYXJ0eV9uICVpbiUgMjo1LA0KICAgICAgICBzZWxlY3RlZCAlaW4lIGMoMEwsIDFMKQ0KICAgICAgKQ0KDQogICAgb2JzZXJ2ZWRfY29uZGl0aW9ucyA8LSBzb3J0KA0KICAgICAgdW5pcXVlKGFuYWx5c2lzX2RhdGEkcGFydHlfbikNCiAgICApDQoNCiAgICBpZiAoIWlkZW50aWNhbChvYnNlcnZlZF9jb25kaXRpb25zLCAyOjUpKSB7DQogICAgICBzdG9wKCJDaGVjayIpDQogICAgfQ0KDQogICAgbG9uZ19kYXRhIDwtIGFuYWx5c2lzX2RhdGEgJT4lDQogICAgICBwaXZvdF9sb25nZXIoDQogICAgICAgIGNvbHMgPSBhbGxfb2YoYXR0cmlidXRlcyksDQogICAgICAgIG5hbWVzX3RvID0gImF0dHJpYnV0ZSIsDQogICAgICAgIHZhbHVlc190byA9ICJsZXZlbCINCiAgICAgICkgJT4lDQogICAgICBmaWx0ZXIoDQogICAgICAgICFpcy5uYShsZXZlbCksDQogICAgICAgIGxldmVsICE9ICIiDQogICAgICApDQoNCiAgICBleHBlY3RlZF9jZWxscyA8LSBsb25nX2RhdGEgJT4lDQogICAgICBkaXN0aW5jdCgNCiAgICAgICAgYXR0cmlidXRlLA0KICAgICAgICBsZXZlbA0KICAgICAgKSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgYXR0cmlidXRlX29yZGVyID0gbWF0Y2goDQogICAgICAgICAgYXR0cmlidXRlLA0KICAgICAgICAgIGF0dHJpYnV0ZXMNCiAgICAgICAgKQ0KICAgICAgKSAlPiUNCiAgICAgIGFycmFuZ2UoDQogICAgICAgIGF0dHJpYnV0ZV9vcmRlciwNCiAgICAgICAgYXR0cmlidXRlLA0KICAgICAgICBsZXZlbA0KICAgICAgKSAlPiUNCiAgICAgIHNlbGVjdCgtYXR0cmlidXRlX29yZGVyKSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgY2VsbF9rZXkgPSBwYXN0ZSgNCiAgICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgICAgbGV2ZWwsDQogICAgICAgICAgc2VwID0gIlxyIg0KICAgICAgICApDQogICAgICApDQoNCiAgICByZXNwb25kZW50X2NlbGwgPC0gbG9uZ19kYXRhICU+JQ0KICAgICAgZ3JvdXBfYnkoDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIElELA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVsDQogICAgICApICU+JQ0KICAgICAgc3VtbWFyaXNlKA0KICAgICAgICB5X3N1bSA9IHN1bShzZWxlY3RlZCksDQogICAgICAgIG5fb2JzID0gbigpLA0KICAgICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBjZWxsX2tleSA9IHBhc3RlKA0KICAgICAgICAgIGF0dHJpYnV0ZSwNCiAgICAgICAgICBsZXZlbCwNCiAgICAgICAgICBzZXAgPSAiXHIiDQogICAgICAgICkNCiAgICAgICkNCg0KICAgIGNvbmRpdGlvbl9vYmplY3RzIDwtIGxhcHBseSgNCiAgICAgIDI6NSwNCiAgICAgIGZ1bmN0aW9uKG5fdmFsdWUpIHsNCiAgICAgICAgY29uZGl0aW9uX2RhdGEgPC0gcmVzcG9uZGVudF9jZWxsICU+JQ0KICAgICAgICAgIGZpbHRlcigNCiAgICAgICAgICAgIHBhcnR5X24gPT0gbl92YWx1ZQ0KICAgICAgICAgICkNCg0KICAgICAgICBpZF92YWx1ZXMgPC0gc29ydCgNCiAgICAgICAgICB1bmlxdWUoY29uZGl0aW9uX2RhdGEkSUQpDQogICAgICAgICkNCiAgICAgICAgbl9pZHMgPC0gbGVuZ3RoKGlkX3ZhbHVlcykNCiAgICAgICAgbl9jZWxscyA8LSBucm93KGV4cGVjdGVkX2NlbGxzKQ0KDQogICAgICAgIGlmIChuX2lkcyA9PSAwKSB7DQogICAgICAgICAgc3RvcCgiQ2hlY2siKQ0KICAgICAgICB9DQoNCiAgICAgICAgeV9tYXRyaXggPC0gbWF0cml4KA0KICAgICAgICAgIDAsDQogICAgICAgICAgbnJvdyA9IG5faWRzLA0KICAgICAgICAgIG5jb2wgPSBuX2NlbGxzLA0KICAgICAgICAgIGRpbW5hbWVzID0gbGlzdCgNCiAgICAgICAgICAgIGlkX3ZhbHVlcywNCiAgICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5DQogICAgICAgICAgKQ0KICAgICAgICApDQoNCiAgICAgICAgbl9tYXRyaXggPC0gbWF0cml4KA0KICAgICAgICAgIDAsDQogICAgICAgICAgbnJvdyA9IG5faWRzLA0KICAgICAgICAgIG5jb2wgPSBuX2NlbGxzLA0KICAgICAgICAgIGRpbW5hbWVzID0gbGlzdCgNCiAgICAgICAgICAgIGlkX3ZhbHVlcywNCiAgICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5DQogICAgICAgICAgKQ0KICAgICAgICApDQoNCiAgICAgICAgcm93X2luZGV4IDwtIG1hdGNoKA0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJElELA0KICAgICAgICAgIGlkX3ZhbHVlcw0KICAgICAgICApDQogICAgICAgIGNvbHVtbl9pbmRleCA8LSBtYXRjaCgNCiAgICAgICAgICBjb25kaXRpb25fZGF0YSRjZWxsX2tleSwNCiAgICAgICAgICBleHBlY3RlZF9jZWxscyRjZWxsX2tleQ0KICAgICAgICApDQoNCiAgICAgICAgeV9tYXRyaXhbY2JpbmQocm93X2luZGV4LCBjb2x1bW5faW5kZXgpXSA8LQ0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJHlfc3VtDQogICAgICAgIG5fbWF0cml4W2NiaW5kKHJvd19pbmRleCwgY29sdW1uX2luZGV4KV0gPC0NCiAgICAgICAgICBjb25kaXRpb25fZGF0YSRuX29icw0KDQogICAgICAgIGlmIChhbnkoY29sU3VtcyhuX21hdHJpeCkgPT0gMCkpIHsNCiAgICAgICAgICBtaXNzaW5nX2NlbGxzIDwtIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5Ww0KICAgICAgICAgICAgY29sU3VtcyhuX21hdHJpeCkgPT0gMA0KICAgICAgICAgIF0NCg0KICAgICAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQ0KICAgICAgICB9DQoNCiAgICAgICAgbGlzdCgNCiAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwNCiAgICAgICAgICBpZHMgPSBpZF92YWx1ZXMsDQogICAgICAgICAgY2VsbF9pbmZvID0gZXhwZWN0ZWRfY2VsbHMsDQogICAgICAgICAgeV9tYXRyaXggPSB5X21hdHJpeCwNCiAgICAgICAgICBuX21hdHJpeCA9IG5fbWF0cml4DQogICAgICAgICkNCiAgICAgIH0NCiAgICApDQoNCiAgICBuYW1lcyhjb25kaXRpb25fb2JqZWN0cykgPC0gYXMuY2hhcmFjdGVyKDI6NSkNCg0KICAgIGxpc3QoDQogICAgICBjdWVfbWFwID0gY3VlX21hcCwNCiAgICAgIGF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzLA0KICAgICAgY29uZGl0aW9ucyA9IGNvbmRpdGlvbl9vYmplY3RzDQogICAgKQ0KICB9DQoNCiAgZXN0aW1hdGVfcmVsYXRpdmVfY3VlX2luZGljZXMgPC0gZnVuY3Rpb24oDQogICAgICBwcmVwYXJlZCwNCiAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA9IE5VTEwNCiAgKSB7DQogICAgY29uZGl0aW9uX3Jlc3VsdHMgPC0gbGFwcGx5KA0KICAgICAgbmFtZXMocHJlcGFyZWQkY29uZGl0aW9ucyksDQogICAgICBmdW5jdGlvbihjb25kaXRpb25fbmFtZSkgew0KICAgICAgICBvYmplY3QgPC0gcHJlcGFyZWQkY29uZGl0aW9uc1tbY29uZGl0aW9uX25hbWVdXQ0KDQogICAgICAgIGlmIChpcy5udWxsKGNsdXN0ZXJfd2VpZ2h0cykpIHsNCiAgICAgICAgICB3ZWlnaHRzIDwtIHJlcCgNCiAgICAgICAgICAgIDEsDQogICAgICAgICAgICBsZW5ndGgob2JqZWN0JGlkcykNCiAgICAgICAgICApDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgd2VpZ2h0cyA8LSBjbHVzdGVyX3dlaWdodHNbW2NvbmRpdGlvbl9uYW1lXV0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChsZW5ndGgod2VpZ2h0cykgIT0gbGVuZ3RoKG9iamVjdCRpZHMpKSB7DQogICAgICAgICAgc3RvcCgiQ2hlY2siKQ0KICAgICAgICB9DQoNCiAgICAgICAgbnVtZXJhdG9yIDwtIGFzLm51bWVyaWMoDQogICAgICAgICAgY3Jvc3Nwcm9kKA0KICAgICAgICAgICAgd2VpZ2h0cywNCiAgICAgICAgICAgIG9iamVjdCR5X21hdHJpeA0KICAgICAgICAgICkNCiAgICAgICAgKQ0KDQogICAgICAgIGRlbm9taW5hdG9yIDwtIGFzLm51bWVyaWMoDQogICAgICAgICAgY3Jvc3Nwcm9kKA0KICAgICAgICAgICAgd2VpZ2h0cywNCiAgICAgICAgICAgIG9iamVjdCRuX21hdHJpeA0KICAgICAgICAgICkNCiAgICAgICAgKQ0KDQogICAgICAgIGlmIChhbnkoZGVub21pbmF0b3IgPD0gMCkpIHsNCiAgICAgICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICAgICAgfQ0KDQogICAgICAgIG1hcmdpbmFsX21lYW5zIDwtIG51bWVyYXRvciAvIGRlbm9taW5hdG9yDQoNCiAgICAgICAgbW1fdGFibGUgPC0gb2JqZWN0JGNlbGxfaW5mbyAlPiUNCiAgICAgICAgICB0cmFuc211dGUoDQogICAgICAgICAgICBwYXJ0eV9uID0gb2JqZWN0JHBhcnR5X24sDQogICAgICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgICAgICBsZXZlbCwNCiAgICAgICAgICAgIG1hcmdpbmFsX21lYW4gPSBtYXJnaW5hbF9tZWFucw0KICAgICAgICAgICkNCg0KICAgICAgICBhdHRyaWJ1dGVfdGFibGUgPC0gbW1fdGFibGUgJT4lDQogICAgICAgICAgZ3JvdXBfYnkoDQogICAgICAgICAgICBwYXJ0eV9uLA0KICAgICAgICAgICAgYXR0cmlidXRlDQogICAgICAgICAgKSAlPiUNCiAgICAgICAgICBzdW1tYXJpc2UoDQogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgICAgICAgbWVhbl9hYnNvbHV0ZV9wYWlyd2lzZV9kaWZmZXJlbmNlKA0KICAgICAgICAgICAgICAgIG1hcmdpbmFsX21lYW4NCiAgICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIG5fbGV2ZWxzID0gbigpLA0KICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICAgICAgICkgJT4lDQogICAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgY3VlX2ZhbWlseSA9IHVubmFtZSgNCiAgICAgICAgICAgICAgcHJlcGFyZWQkY3VlX21hcFthdHRyaWJ1dGVdDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgYmFzZWxpbmVfc2VsZWN0aW9uX3Byb2JhYmlsaXR5ID0gMSAvIHBhcnR5X24sDQogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0NCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSAvDQogICAgICAgICAgICAgICAgYmFzZWxpbmVfc2VsZWN0aW9uX3Byb2JhYmlsaXR5DQogICAgICAgICAgKQ0KDQogICAgICAgIGN1ZV90YWJsZV9sb25nIDwtIGF0dHJpYnV0ZV90YWJsZSAlPiUNCiAgICAgICAgICBncm91cF9ieSgNCiAgICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgICBjdWVfZmFtaWx5DQogICAgICAgICAgKSAlPiUNCiAgICAgICAgICBzdW1tYXJpc2UoDQogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlID0gbWVhbigNCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9IG1lYW4oDQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQogICAgICAgICAgICAgIG5hLnJtID0gVFJVRQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICAgICAgICApDQoNCiAgICAgICAgcGFydHlfdGFibGUgPC0gY3VlX3RhYmxlX2xvbmcgJT4lDQogICAgICAgICAgZmlsdGVyKA0KICAgICAgICAgICAgY3VlX2ZhbWlseSA9PSAicGFydHkiDQogICAgICAgICAgKSAlPiUNCiAgICAgICAgICB0cmFuc211dGUoDQogICAgICAgICAgICBwYXJ0eV9uLA0KICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSA9DQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UsDQogICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0NCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZA0KICAgICAgICAgICkNCg0KICAgICAgICBlY29ub21pY190YWJsZSA8LSBjdWVfdGFibGVfbG9uZyAlPiUNCiAgICAgICAgICBmaWx0ZXIoDQogICAgICAgICAgICBjdWVfZmFtaWx5ID09ICJlY29ub21pYyINCiAgICAgICAgICApICU+JQ0KICAgICAgICAgIHRyYW5zbXV0ZSgNCiAgICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkDQogICAgICAgICAgKQ0KDQogICAgICAgIGN1ZV90YWJsZSA8LSBmdWxsX2pvaW4oDQogICAgICAgICAgcGFydHlfdGFibGUsDQogICAgICAgICAgZWNvbm9taWNfdGFibGUsDQogICAgICAgICAgYnkgPSAicGFydHlfbiINCiAgICAgICAgKSAlPiUNCiAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkgPSAxIC8gcGFydHlfbiwNCg0KICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZSA9DQogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgKw0KICAgICAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlLA0KDQogICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0NCiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCArDQogICAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQoNCiAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSA9IGlmX2Vsc2UoDQogICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2UgPiAwLA0KICAgICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIC8NCiAgICAgICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlLA0KICAgICAgICAgICAgICBOQV9yZWFsXw0KICAgICAgICAgICAgKSwNCg0KICAgICAgICAgICAgcmVsYXRpdmVfZWNvbm9taWNfd2VpZ2h0X3BhaXJ3aXNlID0NCiAgICAgICAgICAgICAgMSAtIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSwNCg0KICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlX2FkanVzdGVkID0gaWZfZWxzZSgNCiAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA+IDAsDQogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgLw0KICAgICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQogICAgICAgICAgICAgIE5BX3JlYWxfDQogICAgICAgICAgICApLA0KDQogICAgICAgICAgICByZWxhdGl2ZV9lY29ub21pY193ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICAxIC0gcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlX2FkanVzdGVkLA0KDQogICAgICAgICAgICBhZGp1c3RtZW50X2lkZW50aXR5X2RpZmZlcmVuY2UgPQ0KICAgICAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQgLQ0KICAgICAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZQ0KICAgICAgICAgICkNCg0KICAgICAgICBpZiAoDQogICAgICAgICAgYW55KA0KICAgICAgICAgICAgYWJzKGN1ZV90YWJsZSRhZGp1c3RtZW50X2lkZW50aXR5X2RpZmZlcmVuY2UpID4gMWUtMTAsDQogICAgICAgICAgICBuYS5ybSA9IFRSVUUNCiAgICAgICAgICApDQogICAgICAgICkgew0KICAgICAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpDQogICAgICAgIH0NCg0KICAgICAgICBsaXN0KA0KICAgICAgICAgIG1hcmdpbmFsX21lYW5zID0gbW1fdGFibGUsDQogICAgICAgICAgYXR0cmlidXRlX2ltcG9ydGFuY2UgPSBhdHRyaWJ1dGVfdGFibGUsDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UgPSBjdWVfdGFibGUNCiAgICAgICAgKQ0KICAgICAgfQ0KICAgICkNCg0KICAgIGxpc3QoDQogICAgICBtYXJnaW5hbF9tZWFucyA9IGJpbmRfcm93cygNCiAgICAgICAgbGFwcGx5KA0KICAgICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzLA0KICAgICAgICAgIGZ1bmN0aW9uKHgpIHgkbWFyZ2luYWxfbWVhbnMNCiAgICAgICAgKQ0KICAgICAgKSwNCiAgICAgIGF0dHJpYnV0ZV9pbXBvcnRhbmNlID0gYmluZF9yb3dzKA0KICAgICAgICBsYXBwbHkoDQogICAgICAgICAgY29uZGl0aW9uX3Jlc3VsdHMsDQogICAgICAgICAgZnVuY3Rpb24oeCkgeCRhdHRyaWJ1dGVfaW1wb3J0YW5jZQ0KICAgICAgICApDQogICAgICApLA0KICAgICAgY3VlX2ltcG9ydGFuY2UgPSBiaW5kX3Jvd3MoDQogICAgICAgIGxhcHBseSgNCiAgICAgICAgICBjb25kaXRpb25fcmVzdWx0cywNCiAgICAgICAgICBmdW5jdGlvbih4KSB4JGN1ZV9pbXBvcnRhbmNlDQogICAgICAgICkNCiAgICAgICkgJT4lDQogICAgICAgIGFycmFuZ2UocGFydHlfbikNCiAgICApDQogIH0NCg0KICBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfc2xvcGVzIDwtIGZ1bmN0aW9uKGN1ZV9pbXBvcnRhbmNlKSB7DQogICAgY3VlX2ltcG9ydGFuY2UgPC0gY3VlX2ltcG9ydGFuY2UgJT4lDQogICAgICBhcnJhbmdlKHBhcnR5X24pDQoNCiAgICBpZiAoIWlkZW50aWNhbChjdWVfaW1wb3J0YW5jZSRwYXJ0eV9uLCAyOjUpKSB7DQogICAgICBzdG9wKCJDaGVjayByZWxhdGl2ZSB3ZWlnaHQiKQ0KICAgIH0NCg0KICAgIHggPC0gY3VlX2ltcG9ydGFuY2UkcGFydHlfbg0KDQogICAgYygNCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSA9DQogICAgICAgIGxpbmVhcl9zbG9wZSgNCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSRyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UsDQogICAgICAgICAgeA0KICAgICAgICApLA0KDQogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgbGluZWFyX3Nsb3BlKA0KICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlJHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UsDQogICAgICAgICAgeA0KICAgICAgICApLA0KDQogICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgbGluZWFyX3Nsb3BlKA0KICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlJGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UsDQogICAgICAgICAgeA0KICAgICAgICApLA0KDQogICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0NCiAgICAgICAgbGluZWFyX3Nsb3BlKA0KICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlJHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQogICAgICAgICAgeA0KICAgICAgICApLA0KDQogICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0NCiAgICAgICAgbGluZWFyX3Nsb3BlKA0KICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlJGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQogICAgICAgICAgeA0KICAgICAgICApDQogICAgKQ0KICB9DQoNCiAgcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAgPC0gZnVuY3Rpb24oDQogICAgICBwcmVwYXJlZCwNCiAgICAgIEIsDQogICAgICBzZWVkLA0KICAgICAgcHJvZ3Jlc3NfZXZlcnkgPSAxMDANCiAgKSB7DQogICAgc2V0LnNlZWQoc2VlZCkNCg0KICAgIGNvbmRpdGlvbl9yZXN1bHRzIDwtIHZlY3RvcigNCiAgICAgICJsaXN0IiwNCiAgICAgIEINCiAgICApDQoNCiAgICBzbG9wZV9uYW1lcyA8LSBjKA0KICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIsDQogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsDQogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIsDQogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsDQogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCINCiAgICApDQoNCiAgICBzbG9wZV9tYXRyaXggPC0gbWF0cml4KA0KICAgICAgTkFfcmVhbF8sDQogICAgICBucm93ID0gQiwNCiAgICAgIG5jb2wgPSBsZW5ndGgoc2xvcGVfbmFtZXMpLA0KICAgICAgZGltbmFtZXMgPSBsaXN0KA0KICAgICAgICBOVUxMLA0KICAgICAgICBzbG9wZV9uYW1lcw0KICAgICAgKQ0KICAgICkNCg0KICAgIGZvciAoYiBpbiBzZXFfbGVuKEIpKSB7DQogICAgICBjbHVzdGVyX3dlaWdodHMgPC0gbGFwcGx5KA0KICAgICAgICBwcmVwYXJlZCRjb25kaXRpb25zLA0KICAgICAgICBmdW5jdGlvbihvYmplY3QpIHsNCiAgICAgICAgICBuX2lkcyA8LSBsZW5ndGgob2JqZWN0JGlkcykNCg0KICAgICAgICAgIHNhbXBsZWRfcG9zaXRpb25zIDwtIHNhbXBsZS5pbnQoDQogICAgICAgICAgICBuID0gbl9pZHMsDQogICAgICAgICAgICBzaXplID0gbl9pZHMsDQogICAgICAgICAgICByZXBsYWNlID0gVFJVRQ0KICAgICAgICAgICkNCg0KICAgICAgICAgIHRhYnVsYXRlKA0KICAgICAgICAgICAgc2FtcGxlZF9wb3NpdGlvbnMsDQogICAgICAgICAgICBuYmlucyA9IG5faWRzDQogICAgICAgICAgKQ0KICAgICAgICB9DQogICAgICApDQoNCiAgICAgIGJvb3RzdHJhcF9lc3RpbWF0ZXMgPC0gZXN0aW1hdGVfcmVsYXRpdmVfY3VlX2luZGljZXMoDQogICAgICAgIHByZXBhcmVkID0gcHJlcGFyZWQsDQogICAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA9IGNsdXN0ZXJfd2VpZ2h0cw0KICAgICAgKQ0KDQogICAgICBjb25kaXRpb25fcmVzdWx0c1tbYl1dIDwtDQogICAgICAgIGJvb3RzdHJhcF9lc3RpbWF0ZXMkY3VlX2ltcG9ydGFuY2UgJT4lDQogICAgICAgIHNlbGVjdCgNCiAgICAgICAgICBwYXJ0eV9uLA0KICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UsDQogICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkLA0KICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQogICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlDQogICAgICAgICkgJT4lDQogICAgICAgIG11dGF0ZSgNCiAgICAgICAgICBib290c3RyYXBfcmVwbGljYXRpb24gPSBiLA0KICAgICAgICAgIC5iZWZvcmUgPSAxDQogICAgICAgICkNCg0KICAgICAgc2xvcGVfbWF0cml4W2IsIF0gPC0gZXN0aW1hdGVfcmVsYXRpdmVfY3VlX3Nsb3BlcygNCiAgICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyRjdWVfaW1wb3J0YW5jZQ0KICAgICAgKQ0KDQogICAgICBpZiAoDQogICAgICAgIHByb2dyZXNzX2V2ZXJ5ID4gMCAmJg0KICAgICAgICAoYiAlJSBwcm9ncmVzc19ldmVyeSA9PSAwIHx8IGIgPT0gQikNCiAgICAgICkgew0KICAgICAgICBtZXNzYWdlKCJCb290c3RyYXA6ICIsIGIsICIvIiwgQikNCiAgICAgIH0NCiAgICB9DQoNCiAgICBsaXN0KA0KICAgICAgY29uZGl0aW9uX2VzdGltYXRlcyA9IGJpbmRfcm93cygNCiAgICAgICAgY29uZGl0aW9uX3Jlc3VsdHMNCiAgICAgICksDQogICAgICBzbG9wZXMgPSBhc190aWJibGUoDQogICAgICAgIHNsb3BlX21hdHJpeA0KICAgICAgKSAlPiUNCiAgICAgICAgbXV0YXRlKA0KICAgICAgICAgIGJvb3RzdHJhcF9yZXBsaWNhdGlvbiA9IHJvd19udW1iZXIoKSwNCiAgICAgICAgICAuYmVmb3JlID0gMQ0KICAgICAgICApDQogICAgKQ0KICB9DQoNCiAgc3VtbWFyaXNlX2NvbmRpdGlvbl9pbnRlcnZhbHMgPC0gZnVuY3Rpb24oDQogICAgICBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSwNCiAgICAgIGJvb3RzdHJhcF9jb25kaXRpb25fcmVzdWx0cw0KICApIHsNCiAgICBzdGF0aXN0aWNzIDwtIGMoDQogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsDQogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIsDQogICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsDQogICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsDQogICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIg0KICAgICkNCg0KICAgIG9ic2VydmVkX2xvbmcgPC0gb2JzZXJ2ZWRfY3VlX2ltcG9ydGFuY2UgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIGFsbF9vZihzdGF0aXN0aWNzKQ0KICAgICAgKSAlPiUNCiAgICAgIHBpdm90X2xvbmdlcigNCiAgICAgICAgY29scyA9IGFsbF9vZihzdGF0aXN0aWNzKSwNCiAgICAgICAgbmFtZXNfdG8gPSAic3RhdGlzdGljIiwNCiAgICAgICAgdmFsdWVzX3RvID0gImVzdGltYXRlIg0KICAgICAgKQ0KDQogICAgYm9vdHN0cmFwX2xvbmcgPC0gYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzICU+JQ0KICAgICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgICBjb2xzID0gYWxsX29mKHN0YXRpc3RpY3MpLA0KICAgICAgICBuYW1lc190byA9ICJzdGF0aXN0aWMiLA0KICAgICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiDQogICAgICApICU+JQ0KICAgICAgZ3JvdXBfYnkoDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIHN0YXRpc3RpYw0KICAgICAgKSAlPiUNCiAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgY29uZl9sb3cgPSBzYWZlX3F1YW50aWxlKA0KICAgICAgICAgIHZhbHVlLA0KICAgICAgICAgIDAuMDI1DQogICAgICAgICksDQogICAgICAgIGNvbmZfaGlnaCA9IHNhZmVfcXVhbnRpbGUoDQogICAgICAgICAgdmFsdWUsDQogICAgICAgICAgMC45NzUNCiAgICAgICAgKSwNCiAgICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICAgKQ0KDQogICAgb2JzZXJ2ZWRfbG9uZyAlPiUNCiAgICAgIGxlZnRfam9pbigNCiAgICAgICAgYm9vdHN0cmFwX2xvbmcsDQogICAgICAgIGJ5ID0gYygNCiAgICAgICAgICAicGFydHlfbiIsDQogICAgICAgICAgInN0YXRpc3RpYyINCiAgICAgICAgKQ0KICAgICAgKQ0KICB9DQoNCiAgc3VtbWFyaXNlX3Nsb3BlX2luZmVyZW5jZSA8LSBmdW5jdGlvbigNCiAgICAgIG9ic2VydmVkX3Nsb3BlcywNCiAgICAgIGJvb3RzdHJhcF9zbG9wZXMNCiAgKSB7DQogICAgc3RhdGlzdGljX25hbWVzIDwtIG5hbWVzKG9ic2VydmVkX3Nsb3BlcykNCg0KICAgIG1hcF9kZnIoDQogICAgICBzdGF0aXN0aWNfbmFtZXMsDQogICAgICBmdW5jdGlvbihzdGF0aXN0aWNfbmFtZSkgew0KICAgICAgICBib290c3RyYXBfdmFsdWVzIDwtIGJvb3RzdHJhcF9zbG9wZXNbW3N0YXRpc3RpY19uYW1lXV0NCiAgICAgICAgYm9vdHN0cmFwX3ZhbHVlcyA8LSBib290c3RyYXBfdmFsdWVzWw0KICAgICAgICAgIGlzLmZpbml0ZShib290c3RyYXBfdmFsdWVzKQ0KICAgICAgICBdDQoNCiAgICAgICAgZXhwZWN0ZWRfZGlyZWN0aW9uIDwtIGNhc2Vfd2hlbigNCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSA9PQ0KICAgICAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiIH4gIm5lZ2F0aXZlIiwNCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSAlaW4lIGMoDQogICAgICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsDQogICAgICAgICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwNCiAgICAgICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICAgICAgICkgfiAicG9zaXRpdmUiLA0KICAgICAgICAgIFRSVUUgfiAibm9uZSINCiAgICAgICAgKQ0KDQogICAgICAgIGFuYWx5c2lzX3JvbGUgPC0gY2FzZV93aGVuKA0KICAgICAgICAgIHN0YXRpc3RpY19uYW1lICVpbiUgYygNCiAgICAgICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICAgICAgICkgfiAiZXhwbG9yYXRvcnlfY2hvaWNlX3NldF9hZGp1c3RlZCIsDQogICAgICAgICAgc3RhdGlzdGljX25hbWUgPT0gInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIgfg0KICAgICAgICAgICAgImRlcml2ZWRfcmVsYXRpdmVfc2hhcmUiLA0KICAgICAgICAgIFRSVUUgfiAibWFudXNjcmlwdF9wcmltYXJ5X3VuYWRqdXN0ZWQiDQogICAgICAgICkNCg0KICAgICAgICBlc3RpbWF0ZSA8LSB1bm5hbWUoDQogICAgICAgICAgb2JzZXJ2ZWRfc2xvcGVzW1tzdGF0aXN0aWNfbmFtZV1dDQogICAgICAgICkNCg0KICAgICAgICB0aWJibGUoDQogICAgICAgICAgc3R1ZHkgPSAiU3R1ZHkgMiIsDQogICAgICAgICAgc3RhdGlzdGljID0gc3RhdGlzdGljX25hbWUsDQogICAgICAgICAgZXN0aW1hdGUgPSBlc3RpbWF0ZSwNCiAgICAgICAgICBjb25mX2xvdyA9IHNhZmVfcXVhbnRpbGUoDQogICAgICAgICAgICBib290c3RyYXBfdmFsdWVzLA0KICAgICAgICAgICAgMC4wMjUNCiAgICAgICAgICApLA0KICAgICAgICAgIGNvbmZfaGlnaCA9IHNhZmVfcXVhbnRpbGUoDQogICAgICAgICAgICBib290c3RyYXBfdmFsdWVzLA0KICAgICAgICAgICAgMC45NzUNCiAgICAgICAgICApLA0KICAgICAgICAgIHBfdmFsdWVfdHdvX3NpZGVkID0NCiAgICAgICAgICAgIGJvb3RzdHJhcF90d29fc2lkZWRfcCgNCiAgICAgICAgICAgICAgYm9vdHN0cmFwX3ZhbHVlcw0KICAgICAgICAgICAgKSwNCiAgICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPSBleHBlY3RlZF9kaXJlY3Rpb24sDQogICAgICAgICAgYW5hbHlzaXNfcm9sZSA9IGFuYWx5c2lzX3JvbGUsDQogICAgICAgICAgZXN0aW1hdGVfaW5fZXhwZWN0ZWRfZGlyZWN0aW9uID0gY2FzZV93aGVuKA0KICAgICAgICAgICAgZXhwZWN0ZWRfZGlyZWN0aW9uID09ICJwb3NpdGl2ZSIgfiBlc3RpbWF0ZSA+IDAsDQogICAgICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gIm5lZ2F0aXZlIiB+IGVzdGltYXRlIDwgMCwNCiAgICAgICAgICAgIFRSVUUgfiBOQQ0KICAgICAgICAgICkNCiAgICAgICAgKQ0KICAgICAgfQ0KICAgICkNCiAgfQ0KDQogIHJlbGF0aXZlX2N1ZV9wcmVwYXJlZCA8LSBwcmVwYXJlX3JlbGF0aXZlX2N1ZV9hbmFseXNpcygNCiAgICBkYXRhID0gY29uam9pbnRfYWxsX20sDQogICAgY3VlX21hcCA9IHJlbGF0aXZlX2N1ZV9tYXANCiAgKQ0KDQogIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcygNCiAgICBwcmVwYXJlZCA9IHJlbGF0aXZlX2N1ZV9wcmVwYXJlZA0KICApDQoNCiAgcmVsYXRpdmVfY3VlX29ic2VydmVkX3Nsb3BlcyA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfc2xvcGVzKA0KICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRjdWVfaW1wb3J0YW5jZQ0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkbWFyZ2luYWxfbWVhbnMsDQogICAgInN0dWR5Ml9yZWxhdGl2ZV9jdWVfbWFyZ2luYWxfbWVhbnMuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkYXR0cmlidXRlX2ltcG9ydGFuY2UsDQogICAgInN0dWR5Ml9yZWxhdGl2ZV9jdWVfYXR0cmlidXRlX2ltcG9ydGFuY2UuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsDQogICAgInN0dWR5Ml9yZWxhdGl2ZV9jdWVfaW1wb3J0YW5jZV9hbmRfd2VpZ2h0LmNzdiINCiAgKQ0KDQogIHJlbGF0aXZlX2NvbmRpdGlvbl9ib290c3RyYXBfZmlsZSA8LSBmaWxlLnBhdGgoDQogICAgb3V0cHV0X2RpciwNCiAgICBwYXN0ZTAoDQogICAgICAic3R1ZHkyX3JlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwXyIsDQogICAgICB1bmlmaWVkX2NvbmZpZyRjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiwNCiAgICAgICJfQiIsDQogICAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IsDQogICAgICAiLmNzdiINCiAgICApDQogICkNCg0KICByZWxhdGl2ZV9zbG9wZV9ib290c3RyYXBfZmlsZSA8LSBmaWxlLnBhdGgoDQogICAgb3V0cHV0X2RpciwNCiAgICBwYXN0ZTAoDQogICAgICAic3R1ZHkyX3JlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXBfIiwNCiAgICAgIHVuaWZpZWRfY29uZmlnJGN1ZV9pbXBvcnRhbmNlX21ldHJpY192ZXJzaW9uLA0KICAgICAgIl9CIiwNCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiwNCiAgICAgICIuY3N2Ig0KICAgICkNCiAgKQ0KDQogIHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXAgPC0NCiAgICAhcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCAmJg0KICAgIGZpbGUuZXhpc3RzKHJlbGF0aXZlX2NvbmRpdGlvbl9ib290c3RyYXBfZmlsZSkgJiYNCiAgICBmaWxlLmV4aXN0cyhyZWxhdGl2ZV9zbG9wZV9ib290c3RyYXBfZmlsZSkNCg0KICBpZiAodXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCkgew0KICAgIG1lc3NhZ2UoIkJvb3RzdHJhcCBjYWNoZSIpDQoNCiAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCA8LSByZWFkcjo6cmVhZF9jc3YoDQogICAgICByZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUsDQogICAgICBzaG93X2NvbF90eXBlcyA9IEZBTFNFDQogICAgKQ0KDQogICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCA8LSByZWFkcjo6cmVhZF9jc3YoDQogICAgICByZWxhdGl2ZV9zbG9wZV9ib290c3RyYXBfZmlsZSwNCiAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UNCiAgICApDQoNCiAgICBzYXZlZF9CX2NvbmRpdGlvbiA8LSBuX2Rpc3RpbmN0KA0KICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAkYm9vdHN0cmFwX3JlcGxpY2F0aW9uDQogICAgKQ0KICAgIHNhdmVkX0Jfc2xvcGUgPC0gbl9kaXN0aW5jdCgNCiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAkYm9vdHN0cmFwX3JlcGxpY2F0aW9uDQogICAgKQ0KDQogICAgaWYgKA0KICAgICAgc2F2ZWRfQl9jb25kaXRpb24gIT0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CIHx8DQogICAgICBzYXZlZF9CX3Nsb3BlICE9IHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQg0KICAgICkgew0KICAgICAgbWVzc2FnZSgiQm9vdHN0cmFwIGNhY2hlIikNCiAgICAgIHVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXAgPC0gRkFMU0UNCiAgICB9DQogIH0NCg0KICBpZiAoIXVzZV9zYXZlZF9yZWxhdGl2ZV9ib290c3RyYXApIHsNCiAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwIDwtIHJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwKA0KICAgICAgcHJlcGFyZWQgPSByZWxhdGl2ZV9jdWVfcHJlcGFyZWQsDQogICAgICBCID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLA0KICAgICAgc2VlZCA9IHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCwNCiAgICAgIHByb2dyZXNzX2V2ZXJ5ID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeQ0KICAgICkNCg0KICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwIDwtDQogICAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwJGNvbmRpdGlvbl9lc3RpbWF0ZXMNCg0KICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAgPC0NCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAkc2xvcGVzDQoNCiAgICByZWFkcjo6d3JpdGVfY3N2KA0KICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAsDQogICAgICByZWxhdGl2ZV9jb25kaXRpb25fYm9vdHN0cmFwX2ZpbGUNCiAgICApDQoNCiAgICByZWFkcjo6d3JpdGVfY3N2KA0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCwNCiAgICAgIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlDQogICAgKQ0KICB9DQoNCiAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMgPC0gc3VtbWFyaXNlX2NvbmRpdGlvbl9pbnRlcnZhbHMoDQogICAgb2JzZXJ2ZWRfY3VlX2ltcG9ydGFuY2UgPQ0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlLA0KICAgIGJvb3RzdHJhcF9jb25kaXRpb25fcmVzdWx0cyA9DQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcA0KICApDQoNCiAgcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSA8LSBzdW1tYXJpc2Vfc2xvcGVfaW5mZXJlbmNlKA0KICAgIG9ic2VydmVkX3Nsb3BlcyA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzLA0KICAgIGJvb3RzdHJhcF9zbG9wZXMgPQ0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcA0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscywNCiAgICAic3R1ZHkyX3JlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzLmNzdiINCiAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSwNCiAgICAic3R1ZHkyX3JlbGF0aXZlX2N1ZV9zbG9wZV9pbmZlcmVuY2UuY3N2Ig0KICApDQoNCiAgcmVsYXRpdmVfY3VlX3ByaW1hcnlfcmVzdWx0IDwtIHJlbGF0aXZlX2N1ZV9zbG9wZV9pbmZlcmVuY2UgJT4lDQogICAgZmlsdGVyKA0KICAgICAgc3RhdGlzdGljID09DQogICAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiDQogICAgKQ0KDQogIGNhdCgiXG5TdHVkeSAy77ya55u45a++5q+U6YeN44Gu57ea5b2i5YK+5ZCRXG4iKQ0KICBwcmludChyZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQpDQoNCg0KICByZWxhdGl2ZV94X29mZnNldCA8LSAwLjA3NQ0KDQogIHJlbGF0aXZlX3BhbmVsX2FfZGF0YSA8LSByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyAlPiUNCiAgICBmaWx0ZXIoDQogICAgICBzdGF0aXN0aWMgJWluJSBjKA0KICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsDQogICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgY3VlX2ZhbWlseSA9IHJlY29kZSgNCiAgICAgICAgc3RhdGlzdGljLA0KICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0gIuaUv+WFmuaJi+OBjOOBi+OCiiIsDQogICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPSAi57WM5riI5omL44GM44GL44KKIg0KICAgICAgKSwNCiAgICAgIGN1ZV9mYW1pbHkgPSBmYWN0b3IoDQogICAgICAgIGN1ZV9mYW1pbHksDQogICAgICAgIGxldmVscyA9IGMoDQogICAgICAgICAgIuaUv+WFmuaJi+OBjOOBi+OCiiIsDQogICAgICAgICAgIue1jOa4iOaJi+OBjOOBi+OCiiINCiAgICAgICAgKQ0KICAgICAgKSwNCiAgICAgIHhfcGxvdCA9IGNhc2Vfd2hlbigNCiAgICAgICAgY3VlX2ZhbWlseSA9PSAi5pS/5YWa5omL44GM44GL44KKIiB+DQogICAgICAgICAgcGFydHlfbiArIHJlbGF0aXZlX3hfb2Zmc2V0LA0KICAgICAgICBjdWVfZmFtaWx5ID09ICLntYzmuIjmiYvjgYzjgYvjgooiIH4NCiAgICAgICAgICBwYXJ0eV9uIC0gcmVsYXRpdmVfeF9vZmZzZXQsDQogICAgICAgIFRSVUUgfiBhcy5udW1lcmljKHBhcnR5X24pDQogICAgICApLA0KICAgICAgdmFsdWVfbGFiZWwgPSBzcHJpbnRmKA0KICAgICAgICAiJS4zZiIsDQogICAgICAgIGVzdGltYXRlDQogICAgICApDQogICAgKQ0KDQogIHJlbGF0aXZlX3BhbmVsX2JfZGF0YSA8LSByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyAlPiUNCiAgICBmaWx0ZXIoDQogICAgICBzdGF0aXN0aWMgPT0NCiAgICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSINCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHZhbHVlX2xhYmVsID0gc3ByaW50ZigNCiAgICAgICAgIiUuMWYlJSIsDQogICAgICAgIDEwMCAqIGVzdGltYXRlDQogICAgICApDQogICAgKQ0KDQogIHJlbGF0aXZlX2FkanVzdGVkX2xhYmVsX21hcCA8LSByZWxhdGl2ZV9wYW5lbF9hX2RhdGEgJT4lDQogICAgZGlzdGluY3QoDQogICAgICBzdGF0aXN0aWMsDQogICAgICBjdWVfZmFtaWx5DQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBzdGF0aXN0aWMgPSBwYXN0ZTAoDQogICAgICAgIHN0YXRpc3RpYywNCiAgICAgICAgIl9hZGp1c3RlZCINCiAgICAgICksDQogICAgICBjdWVfZmFtaWx5ID0gYXMuY2hhcmFjdGVyKA0KICAgICAgICBjdWVfZmFtaWx5DQogICAgICApDQogICAgKQ0KDQogIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGEgPC0gcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMgJT4lDQogICAgZmlsdGVyKA0KICAgICAgc3RhdGlzdGljICVpbiUgYygNCiAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiLA0KICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCINCiAgICAgICkNCiAgICApICU+JQ0KICAgIGxlZnRfam9pbigNCiAgICAgIHJlbGF0aXZlX2FkanVzdGVkX2xhYmVsX21hcCwNCiAgICAgIGJ5ID0gInN0YXRpc3RpYyINCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIGN1ZV9mYW1pbHkgPSBmYWN0b3IoDQogICAgICAgIGN1ZV9mYW1pbHksDQogICAgICAgIGxldmVscyA9IGxldmVscygNCiAgICAgICAgICByZWxhdGl2ZV9wYW5lbF9hX2RhdGEkY3VlX2ZhbWlseQ0KICAgICAgICApDQogICAgICApLA0KICAgICAgeF9wbG90ID0gaWZfZWxzZSgNCiAgICAgICAgYXMuaW50ZWdlcihjdWVfZmFtaWx5KSA9PSAxTCwNCiAgICAgICAgcGFydHlfbiArIHJlbGF0aXZlX3hfb2Zmc2V0LA0KICAgICAgICBwYXJ0eV9uIC0gcmVsYXRpdmVfeF9vZmZzZXQNCiAgICAgICksDQogICAgICB2YWx1ZV9sYWJlbCA9IHNwcmludGYoDQogICAgICAgICIlLjFmJSUiLA0KICAgICAgICAxMDAgKiBlc3RpbWF0ZQ0KICAgICAgKQ0KICAgICkNCg0KICByZWxhdGl2ZV9jb25kaXRpb25fc3VmZml4IDwtIGlmICgNCiAgICAi5pS/5YWa5ZCN5omL44GM44GL44KKIiAlaW4lDQogICAgICBsZXZlbHMocmVsYXRpdmVfcGFuZWxfYV9kYXRhJGN1ZV9mYW1pbHkpDQogICkgew0KICAgICLpgbjmip7ogqIiDQogIH0gZWxzZSB7DQogICAgIuaUv+WFmiINCiAgfQ0KDQogIHJlbGF0aXZlX2NvbmRpdGlvbl9heGlzX3RpdGxlIDwtIGlmICgNCiAgICByZWxhdGl2ZV9jb25kaXRpb25fc3VmZml4ID09ICLpgbjmip7ogqIiDQogICkgew0KICAgICLmlL/msrvntYzmuIjnirbms4Hjga7pgbjmip7ogqLmlbAiDQogIH0gZWxzZSB7DQogICAgIuaUv+WFmumBuOaKnuiCouaVsCINCiAgfQ0KDQogIHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSA8LSBpZiAoDQogICAgLlBsYXRmb3JtJE9TLnR5cGUgPT0gIndpbmRvd3MiDQogICkgew0KICAgICJZdSBHb3RoaWMiDQogIH0gZWxzZSB7DQogICAgInNhbnMiDQogIH0NCg0KICByZWxhdGl2ZV90aGVtZV9qYXBhbmVzZV9idyA8LSB0aGVtZV9idygNCiAgICBiYXNlX3NpemUgPSAxMiwNCiAgICBiYXNlX2ZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseQ0KICApICsNCiAgICB0aGVtZSgNCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKA0KICAgICAgICBsaW5ld2lkdGggPSAwLjMwLA0KICAgICAgICBjb2xvciA9ICJncmV5ODgiDQogICAgICApLA0KICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KA0KICAgICAgICBsaW5ld2lkdGggPSAwLjY1LA0KICAgICAgICBjb2xvciA9ICJibGFjayINCiAgICAgICksDQogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICAgKSwNCiAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICAgKSwNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIHNpemUgPSAxMi41LA0KICAgICAgICBmYWNlID0gImJvbGQiLA0KICAgICAgICBoanVzdCA9IDANCiAgICAgICksDQogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBzaXplID0gOS41LA0KICAgICAgICBoanVzdCA9IDAsDQogICAgICAgIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgICAgICBiID0gOA0KICAgICAgICApDQogICAgICApLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJjZW50ZXIiLA0KICAgICAgbGVnZW5kLmtleS53aWR0aCA9IGdyaWQ6OnVuaXQoDQogICAgICAgIDEuMjUsDQogICAgICAgICJjbSINCiAgICAgICksDQogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigNCiAgICAgICAgOCwNCiAgICAgICAgMTAsDQogICAgICAgIDgsDQogICAgICAgIDgNCiAgICAgICkNCiAgICApDQoNCiAgcmVsYXRpdmVfcGFuZWxfYSA8LSBnZ3Bsb3QoDQogICAgcmVsYXRpdmVfcGFuZWxfYV9kYXRhLA0KICAgIGFlcygNCiAgICAgIHggPSB4X3Bsb3QsDQogICAgICB5ID0gZXN0aW1hdGUsDQogICAgICBncm91cCA9IGN1ZV9mYW1pbHksDQogICAgICBsaW5ldHlwZSA9IGN1ZV9mYW1pbHkNCiAgICApDQogICkgKw0KICAgIGdlb21fbGluZSgNCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX2Vycm9yYmFyKA0KICAgICAgYWVzKA0KICAgICAgICB5bWluID0gY29uZl9sb3csDQogICAgICAgIHltYXggPSBjb25mX2hpZ2gNCiAgICAgICksDQogICAgICB3aWR0aCA9IDAuMDc1LA0KICAgICAgbGluZXdpZHRoID0gMC44MCwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fbGFiZWwoDQogICAgICBhZXMoDQogICAgICAgIGxhYmVsID0gdmFsdWVfbGFiZWwNCiAgICAgICksDQogICAgICBzaXplID0gMy41NSwNCiAgICAgIGZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSwNCiAgICAgIGxhYmVsLnNpemUgPSAwLA0KICAgICAgbGFiZWwucGFkZGluZyA9IGdyaWQ6OnVuaXQoDQogICAgICAgIDAuMTIsDQogICAgICAgICJsaW5lcyINCiAgICAgICksDQogICAgICBmaWxsID0gIndoaXRlIiwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICLmlL/lhZrmiYvjgYzjgYvjgooiID0gInNvbGlkIiwNCiAgICAgICAgIue1jOa4iOaJi+OBjOOBi+OCiiIgPSAiZGFzaGVkIg0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX3hfY29udGludW91cygNCiAgICAgIGJyZWFrcyA9IDI6NSwNCiAgICAgIGxhYmVscyA9IHBhc3RlMCgNCiAgICAgICAgMjo1LA0KICAgICAgICAi5pS/5YWaIg0KICAgICAgKSwNCiAgICAgIGxpbWl0cyA9IGMoDQogICAgICAgIDEuNzIsDQogICAgICAgIDUuMjgNCiAgICAgICkNCiAgICApICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgICBsYWJlbHMgPSBsYWJlbF9udW1iZXIoDQogICAgICAgIGFjY3VyYWN5ID0gMC4wMDUNCiAgICAgICksDQogICAgICBleHBhbmQgPSBleHBhbnNpb24oDQogICAgICAgIG11bHQgPSBjKA0KICAgICAgICAgIDAuMDcsDQogICAgICAgICAgMC4xMA0KICAgICAgICApDQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIkHvvJrkuKHmiYvjgYzjgYvjgorjga7ntbblr77nmoTph43opoHluqYiLA0KICAgICAgc3VidGl0bGUgPSAiIiwNCiAgICAgIHggPSAi5pS/5YWa6YG45oqe6IKi5pWwIiwNCiAgICAgIHkgPSAi5omL44GM44GL44KK6YeN6KaB5bqmIiwNCiAgICAgIGxpbmV0eXBlID0gTlVMTA0KICAgICkgKw0KICAgIGd1aWRlcygNCiAgICAgIGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKA0KICAgICAgICBvdmVycmlkZS5hZXMgPSBsaXN0KA0KICAgICAgICAgIGxpbmV3aWR0aCA9IDAuOTANCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkgKw0KICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3DQoNCiAgcmVsYXRpdmVfYWRqdXN0ZWRfbGluZXR5cGVzIDwtIHNldE5hbWVzKA0KICAgIGMoDQogICAgICAic29saWQiLA0KICAgICAgImRhc2hlZCINCiAgICApLA0KICAgIGxldmVscygNCiAgICAgIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGEkY3VlX2ZhbWlseQ0KICAgICkNCiAgKQ0KDQogIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkIDwtIGdncGxvdCgNCiAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhLA0KICAgIGFlcygNCiAgICAgIHggPSB4X3Bsb3QsDQogICAgICB5ID0gZXN0aW1hdGUsDQogICAgICBncm91cCA9IGN1ZV9mYW1pbHksDQogICAgICBsaW5ldHlwZSA9IGN1ZV9mYW1pbHkNCiAgICApDQogICkgKw0KICAgIGdlb21fbGluZSgNCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX2Vycm9yYmFyKA0KICAgICAgYWVzKA0KICAgICAgICB5bWluID0gY29uZl9sb3csDQogICAgICAgIHltYXggPSBjb25mX2hpZ2gNCiAgICAgICksDQogICAgICB3aWR0aCA9IDAuMDc1LA0KICAgICAgbGluZXdpZHRoID0gMC44MCwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fbGFiZWwoDQogICAgICBhZXMoDQogICAgICAgIGxhYmVsID0gdmFsdWVfbGFiZWwNCiAgICAgICksDQogICAgICBzaXplID0gMy41NSwNCiAgICAgIGZhbWlseSA9IHJlbGF0aXZlX2ZpZ3VyZV9mb250X2ZhbWlseSwNCiAgICAgIGxhYmVsLnNpemUgPSAwLA0KICAgICAgbGFiZWwucGFkZGluZyA9IGdyaWQ6OnVuaXQoDQogICAgICAgIDAuMTIsDQogICAgICAgICJsaW5lcyINCiAgICAgICksDQogICAgICBmaWxsID0gIndoaXRlIiwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICAgIHZhbHVlcyA9IHJlbGF0aXZlX2FkanVzdGVkX2xpbmV0eXBlcw0KICAgICkgKw0KICAgIHNjYWxlX3hfY29udGludW91cygNCiAgICAgIGJyZWFrcyA9IDI6NSwNCiAgICAgIGxhYmVscyA9IHBhc3RlMCgNCiAgICAgICAgMjo1LA0KICAgICAgICByZWxhdGl2ZV9jb25kaXRpb25fc3VmZml4DQogICAgICApLA0KICAgICAgbGltaXRzID0gYygNCiAgICAgICAgMS43MiwNCiAgICAgICAgNS4yOA0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX3lfY29udGludW91cygNCiAgICAgIGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoDQogICAgICAgIGFjY3VyYWN5ID0gMQ0KICAgICAgKSwNCiAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbigNCiAgICAgICAgbXVsdCA9IGMoDQogICAgICAgICAgMC4wNywNCiAgICAgICAgICAwLjEwDQogICAgICAgICkNCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiQe+8mumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6piIsDQogICAgICBzdWJ0aXRsZSA9DQogICAgICAgICLmnKroqr/mlbTph43opoHluqYgw7cg5bmz5Z2H6YG45oqe56K6546H77yIMe+8j+mBuOaKnuiCouaVsO+8iSIsDQogICAgICB4ID0gcmVsYXRpdmVfY29uZGl0aW9uX2F4aXNfdGl0bGUsDQogICAgICB5ID0gIuW5s+Wdh+mBuOaKnueiuueOh+OBq+WvvuOBmeOCi+awtOa6lumWk+W3riIsDQogICAgICBsaW5ldHlwZSA9IE5VTEwNCiAgICApICsNCiAgICBndWlkZXMoDQogICAgICBsaW5ldHlwZSA9IGd1aWRlX2xlZ2VuZCgNCiAgICAgICAgb3ZlcnJpZGUuYWVzID0gbGlzdCgNCiAgICAgICAgICBsaW5ld2lkdGggPSAwLjkwDQogICAgICAgICkNCiAgICAgICkNCiAgICApICsNCiAgICByZWxhdGl2ZV90aGVtZV9qYXBhbmVzZV9idw0KDQogIHJlbGF0aXZlX2JfcmFuZ2UgPC0gcmFuZ2UoDQogICAgYygNCiAgICAgIHJlbGF0aXZlX3BhbmVsX2JfZGF0YSRjb25mX2xvdywNCiAgICAgIHJlbGF0aXZlX3BhbmVsX2JfZGF0YSRjb25mX2hpZ2gsDQogICAgICAwLjUNCiAgICApLA0KICAgIG5hLnJtID0gVFJVRQ0KICApDQoNCiAgcmVsYXRpdmVfYl9wYWRkaW5nIDwtIG1heCgNCiAgICAwLjAyNSwNCiAgICAwLjEwICogZGlmZihyZWxhdGl2ZV9iX3JhbmdlKQ0KICApDQoNCiAgcmVsYXRpdmVfYl9sb3dlciA8LSBtYXgoDQogICAgMCwNCiAgICBmbG9vcigNCiAgICAgIDIwICoNCiAgICAgICAgKHJlbGF0aXZlX2JfcmFuZ2VbMV0gLSByZWxhdGl2ZV9iX3BhZGRpbmcpDQogICAgKSAvIDIwDQogICkNCg0KICByZWxhdGl2ZV9iX3VwcGVyIDwtIG1pbigNCiAgICAxLA0KICAgIGNlaWxpbmcoDQogICAgICAyMCAqDQogICAgICAgIChyZWxhdGl2ZV9iX3JhbmdlWzJdICsgcmVsYXRpdmVfYl9wYWRkaW5nKQ0KICAgICkgLyAyMA0KICApDQoNCiAgaWYgKHJlbGF0aXZlX2JfbG93ZXIgPj0gcmVsYXRpdmVfYl91cHBlcikgew0KICAgIHJlbGF0aXZlX2JfbG93ZXIgPC0gbWF4KA0KICAgICAgMCwNCiAgICAgIHJlbGF0aXZlX2JfbG93ZXIgLSAwLjA1DQogICAgKQ0KICAgIHJlbGF0aXZlX2JfdXBwZXIgPC0gbWluKA0KICAgICAgMSwNCiAgICAgIHJlbGF0aXZlX2JfdXBwZXIgKyAwLjA1DQogICAgKQ0KICB9DQoNCiAgcmVsYXRpdmVfcGFuZWxfYiA8LSBnZ3Bsb3QoDQogICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhLA0KICAgIGFlcygNCiAgICAgIHggPSBwYXJ0eV9uLA0KICAgICAgeSA9IGVzdGltYXRlDQogICAgKQ0KICApICsNCiAgICBnZW9tX2hsaW5lKA0KICAgICAgeWludGVyY2VwdCA9IDAuNSwNCiAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIsDQogICAgICBsaW5ld2lkdGggPSAwLjU1LA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9saW5lKA0KICAgICAgbGluZXdpZHRoID0gMC44MCwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXIoDQogICAgICBhZXMoDQogICAgICAgIHltaW4gPSBjb25mX2xvdywNCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaA0KICAgICAgKSwNCiAgICAgIHdpZHRoID0gMC4wNzUsDQogICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9sYWJlbCgNCiAgICAgIGFlcygNCiAgICAgICAgbGFiZWwgPSB2YWx1ZV9sYWJlbA0KICAgICAgKSwNCiAgICAgIHNpemUgPSAzLjU1LA0KICAgICAgZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5LA0KICAgICAgbGFiZWwuc2l6ZSA9IDAsDQogICAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdCgNCiAgICAgICAgMC4xMiwNCiAgICAgICAgImxpbmVzIg0KICAgICAgKSwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgYnJlYWtzID0gMjo1LA0KICAgICAgbGFiZWxzID0gcGFzdGUwKA0KICAgICAgICAyOjUsDQogICAgICAgICLmlL/lhZoiDQogICAgICApLA0KICAgICAgbGltaXRzID0gYygNCiAgICAgICAgMS43MiwNCiAgICAgICAgNS4yOA0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX3lfY29udGludW91cygNCiAgICAgIGJyZWFrcyA9IHNlcSgNCiAgICAgICAgcmVsYXRpdmVfYl9sb3dlciwNCiAgICAgICAgcmVsYXRpdmVfYl91cHBlciwNCiAgICAgICAgYnkgPSAwLjA1DQogICAgICApLA0KICAgICAgbGFiZWxzID0gbGFiZWxfcGVyY2VudCgNCiAgICAgICAgYWNjdXJhY3kgPSAxDQogICAgICApLA0KICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKA0KICAgICAgICBtdWx0ID0gYygNCiAgICAgICAgICAwLjA1LA0KICAgICAgICAgIDAuMDgNCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkgKw0KICAgIGNvb3JkX2NhcnRlc2lhbigNCiAgICAgIHlsaW0gPSBjKA0KICAgICAgICByZWxhdGl2ZV9iX2xvd2VyLA0KICAgICAgICByZWxhdGl2ZV9iX3VwcGVyDQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIkLvvJrnm7jlr77nmoTjgarmlL/lhZrmiYvjgYzjgYvjgorjga7mr5Tph40iLA0KICAgICAgc3VidGl0bGUgPQ0KICAgICAgICAi5pS/5YWa5omL44GM44GL44KK6YeN6KaB5bqmIMO377yI5pS/5YWa5omL44GM44GL44KK6YeN6KaB5bqm77yL57WM5riI5omL44GM44GL44KK6YeN6KaB5bqm77yJIiwNCiAgICAgIHggPSAi5pS/5YWa6YG45oqe6IKi5pWwIiwNCiAgICAgIHkgPSAi55u45a++55qE44Gq5pS/5YWa5omL44GM44GL44KK5q+U6YeNIg0KICAgICkgKw0KICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3ICsNCiAgICB0aGVtZSgNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIg0KICAgICkNCg0KICByZWxhdGl2ZV9wYW5lbF9jIDwtIHJlbGF0aXZlX3BhbmVsX2IgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9IHBhc3RlMCgNCiAgICAgICAgIkLvvJrnm7jlr77nmoTjgaoiLA0KICAgICAgICBsZXZlbHMocmVsYXRpdmVfcGFuZWxfYV9kYXRhJGN1ZV9mYW1pbHkpWzFdLA0KICAgICAgICAi44Gu5q+U6YeNIg0KICAgICAgKQ0KICAgICkNCg0KICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwIDwtICgNCiAgICByZWxhdGl2ZV9wYW5lbF9hIHwNCiAgICAgIHJlbGF0aXZlX3BhbmVsX2INCiAgKSArDQogICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dCgNCiAgICAgIHdpZHRocyA9IGMoDQogICAgICAgIDEsDQogICAgICAgIDENCiAgICAgICkNCiAgICApDQoNCiAgcHJpbnQoDQogICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcA0KICApDQoNCiAgc2F2ZV9wbG90KA0KICAgICJmaWdfc3R1ZHkyX3JlbGF0aXZlX2N1ZV93ZWlnaHRfanBfYncucG5nIiwNCiAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLA0KICAgIHdpZHRoID0gMTEuMiwNCiAgICBoZWlnaHQgPSA1LjQsDQogICAgZHBpID0gNDAwDQogICkNCg0KICBnZ3NhdmUoDQogICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoDQogICAgICBvdXRwdXRfZGlyLA0KICAgICAgImZpZ19zdHVkeTJfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wZGYiDQogICAgKSwNCiAgICBwbG90ID0gZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCwNCiAgICB3aWR0aCA9IDExLjIsDQogICAgaGVpZ2h0ID0gNS40LA0KICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLA0KICAgIGJnID0gIndoaXRlIg0KICApDQoNCiAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcCA8LSAoDQogICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQgfA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYw0KICApICsNCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KA0KICAgICAgd2lkdGhzID0gYygNCiAgICAgICAgMSwNCiAgICAgICAgMQ0KICAgICAgKQ0KICAgICkNCg0KICBwcmludCgNCiAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwDQogICkNCg0KICByZWxhdGl2ZV9hZGp1c3RlZF9maWd1cmVfc3R1YiA8LSBwYXN0ZTAoDQogICAgImZpZ19zdHVkeSIsDQogICAgc3RyaW5ncjo6c3RyX2V4dHJhY3QoDQogICAgICBzdHVkeV9sYWJlbCwNCiAgICAgICJbMTIzXSINCiAgICApLA0KICAgICJfcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkX2pwX2J3Ig0KICApDQoNCiAgc2F2ZV9wbG90KA0KICAgIHBhc3RlMCgNCiAgICAgIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViLA0KICAgICAgIi5wbmciDQogICAgKSwNCiAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwLA0KICAgIHdpZHRoID0gMTEuMiwNCiAgICBoZWlnaHQgPSA1LjQsDQogICAgZHBpID0gNDAwDQogICkNCg0KICBnZ3NhdmUoDQogICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoDQogICAgICBvdXRwdXRfZGlyLA0KICAgICAgcGFzdGUwKA0KICAgICAgICByZWxhdGl2ZV9hZGp1c3RlZF9maWd1cmVfc3R1YiwNCiAgICAgICAgIi5wZGYiDQogICAgICApDQogICAgKSwNCiAgICBwbG90ID0gZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcCwNCiAgICB3aWR0aCA9IDExLjIsDQogICAgaGVpZ2h0ID0gNS40LA0KICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLA0KICAgIGJnID0gIndoaXRlIg0KICApDQoNCiAgcmVsYXRpdmVfY3VlX3Jlc3VsdHMgPC0gbGlzdCgNCiAgICBwcmVwYXJlZCA9IHJlbGF0aXZlX2N1ZV9wcmVwYXJlZCwNCiAgICBtYXJnaW5hbF9tZWFucyA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkbWFyZ2luYWxfbWVhbnMsDQogICAgYXR0cmlidXRlX2ltcG9ydGFuY2UgPQ0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGF0dHJpYnV0ZV9pbXBvcnRhbmNlLA0KICAgIGN1ZV9pbXBvcnRhbmNlID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRjdWVfaW1wb3J0YW5jZSwNCiAgICBvYnNlcnZlZF9zbG9wZXMgPQ0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkX3Nsb3BlcywNCiAgICBjb25kaXRpb25fYm9vdHN0cmFwID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwLA0KICAgIHNsb3BlX2Jvb3RzdHJhcCA9DQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwLA0KICAgIGNvbmRpdGlvbl9pbnRlcnZhbHMgPQ0KICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMsDQogICAgc2xvcGVfaW5mZXJlbmNlID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9pbmZlcmVuY2UsDQogICAgcHJpbWFyeV9yZXN1bHQgPQ0KICAgICAgcmVsYXRpdmVfY3VlX3ByaW1hcnlfcmVzdWx0LA0KICAgIHBsb3RzID0gbGlzdCgNCiAgICAgIGFic29sdXRlX2ltcG9ydGFuY2UgPSByZWxhdGl2ZV9wYW5lbF9hLA0KICAgICAgY2hvaWNlX3NldF9hZGp1c3RlZF9pbXBvcnRhbmNlID0NCiAgICAgICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQsDQogICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHQgPSByZWxhdGl2ZV9wYW5lbF9iLA0KICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhbmVsX2MgPQ0KICAgICAgICByZWxhdGl2ZV9wYW5lbF9jLA0KICAgICAgY29tYmluZWQgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLA0KICAgICAgY29tYmluZWRfd2l0aF9jaG9pY2Vfc2V0X2FkanVzdG1lbnQgPQ0KICAgICAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwDQogICAgKQ0KICApDQoNCiAgc2F2ZVJEUygNCiAgICByZWxhdGl2ZV9jdWVfcmVzdWx0cywNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJzdHVkeTJfcmVsYXRpdmVfY3VlX3Jlc3VsdHMucmRzIg0KICAgICkNCiAgKQ0KDQoNCiAgc2F2ZVJEUygNCiAgICBsaXN0KA0KICAgICAgc2V0dGluZ3MgPSBsaXN0KA0KICAgICAgICByZXF1aXJlX2luaXRpYWxfY29uc2VudCA9IHJlcXVpcmVfaW5pdGlhbF9jb25zZW50LA0KICAgICAgICByZXF1aXJlX2ZpbmFsX2NvbnNlbnQgPSByZXF1aXJlX2ZpbmFsX2NvbnNlbnQsDQogICAgICAgIHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrID0gcmVxdWlyZV9hdHRlbnRpb25fY2hlY2ssDQogICAgICAgIHJlcXVpcmVfbWFuaXB1bGF0aW9uX2NoZWNrID0gcmVxdWlyZV9tYW5pcHVsYXRpb25fY2hlY2sNCiAgICAgICksDQogICAgICBzYW1wbGVfZmxvdyA9IHNhbXBsZV9mbG93LA0KICAgICAgbl9ieV9wYXJ0eSA9IG5fYnlfcGFydHksDQogICAgICB2YWxpZF9pZHMgPSB2YWxpZF9pZHMsDQogICAgICBjb25qb2ludF9hbGwgPSBjb25qb2ludF9hbGwsDQogICAgICBjb25qb2ludF9hbGxfbSA9IGNvbmpvaW50X2FsbF9tLA0KICAgICAgY292YXJfaWQgPSBjb3Zhcl9pZCwNCiAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX25vY292ID0gbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YsDQogICAgICBtb2RlbHNfYnlfcGFydHlfbl9jb3YgPSBtb2RlbHNfYnlfcGFydHlfbl9jb3YsDQogICAgICBtX2ludGVyYWN0aW9uID0gbV9pbnRlcmFjdGlvbiwNCiAgICAgIG1vZGVsc19jbG9naXRfbm9jb3YgPSBtb2RlbHNfY2xvZ2l0X25vY292LA0KICAgICAgcmVsYXRpdmVfY3VlID0gcmVsYXRpdmVfY3VlX3Jlc3VsdHMsDQogICAgICBwbG90cyA9IGxpc3QoDQogICAgICAgIGFtY2VfY292ID0gcF9hbWNlX2Nvdl9tYWluLA0KICAgICAgICBhbWNlX25vY292ID0gcF9hbWNlX25vY292X2FwcGVuZGl4LA0KICAgICAgICBpbnRlcmFjdGlvbiA9IHBfaW50ZXJhY3Rpb24sDQogICAgICAgIGhlYXRtYXAgPSBwX2hlYXRfYW1jZSwNCiAgICAgICAgaGVhdG1hcF9yYW5rID0gcF9oZWF0X2FtY2VfcmFuaywNCiAgICAgICAgY2xvZ2l0X29kZHNfcmF0aW8gPSBwX2Nsb2dpdF9vciwNCiAgICAgICAgcmVsYXRpdmVfY3VlX3dlaWdodCA9IGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsDQogICAgICAgIHJlbGF0aXZlX2N1ZV93ZWlnaHRfY2hvaWNlX3NldF9hZGp1c3RlZCA9DQogICAgICAgICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9hZGp1c3RlZF9qcA0KICAgICAgKQ0KICAgICksDQogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAic3R1ZHkyX2FuYWx5c2lzX29iamVjdHMucmRzIikNCiAgKQ0KDQogIGNhcHR1cmUub3V0cHV0KA0KICAgIHNlc3Npb25JbmZvKCksDQogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAic2Vzc2lvbkluZm8udHh0IikNCiAgKQ0KDQogIGNhdCgiDQpEb25lOiAiLCBub3JtYWxpemVQYXRoKG91dHB1dF9kaXIpLCAiDQoiLCBzZXAgPSAiIikNCg0KICBlbnZpcm9ubWVudCgpDQp9KQ0KDQoNCmBgYA0KDQojIyBBLjQg5a6f6aiTM++8muacrOaWh+OBruWbszfjg7vlm7M444O75ZuzOQ0KDQpgYGB7ciBhNC1zdHVkeTMtY29kZSwgZXZhbD1wYXJhbXMkcnVuX2FuYWx5c2lzLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQ0KIyDmnKzmlofjgrPjg7zjg4kNCnN0dWR5M19lbnYgPC0gbG9jYWwoew0KcmVxdWlyZWRfcGFja2FnZXMgPC0gYygNCiAgICAiZHBseXIiLA0KICAgICJ0aWR5ciIsDQogICAgInN0cmluZ3IiLA0KICAgICJwdXJyciIsDQogICAgInJlYWRyIiwNCiAgICAiZml4ZXN0IiwNCiAgICAidGliYmxlIiwNCiAgICAiZm9yY2F0cyIsDQogICAgImdncGxvdDIiLA0KICAgICJzY2FsZXMiLA0KICAgICJzdXJ2aXZhbCIsDQogICAgInBhdGNod29yayINCiAgKQ0KDQogIG1pc3NpbmdfcGFja2FnZXMgPC0gcmVxdWlyZWRfcGFja2FnZXNbDQogICAgIXZhcHBseShyZXF1aXJlZF9wYWNrYWdlcywgcmVxdWlyZU5hbWVzcGFjZSwgbG9naWNhbCgxKSwgcXVpZXRseSA9IFRSVUUpDQogIF0NCg0KICBpZiAobGVuZ3RoKG1pc3NpbmdfcGFja2FnZXMpID4gMCkgew0KICAgIHN0b3AoIk5vIHBhY2thZ2VzIikNCiAgfQ0KDQogIGxpYnJhcnkoZHBseXIpDQogIGxpYnJhcnkodGlkeXIpDQogIGxpYnJhcnkoc3RyaW5ncikNCiAgbGlicmFyeShwdXJycikNCiAgbGlicmFyeShyZWFkcikNCiAgbGlicmFyeShmaXhlc3QpDQogIGxpYnJhcnkodGliYmxlKQ0KICBsaWJyYXJ5KGZvcmNhdHMpDQogIGxpYnJhcnkoZ2dwbG90MikNCiAgbGlicmFyeShzY2FsZXMpDQogIGxpYnJhcnkoc3Vydml2YWwpDQogIGxpYnJhcnkocGF0Y2h3b3JrKQ0KDQogIGRhdGFfZmlsZSA8LSB1bmlmaWVkX2NvbmZpZyRzdHVkeTMkZGF0YV9maWxlDQogIG91dHB1dF9kaXIgPC0gdW5pZmllZF9jb25maWckc3R1ZHkzJG91dHB1dF9kaXINCg0KICBkaXIuY3JlYXRlKG91dHB1dF9kaXIsIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQ0KDQogIHJlcXVpcmVfaW5pdGlhbF9jb25zZW50IDwtIFRSVUUNCiAgcmVxdWlyZV9maW5hbF9jb25zZW50IDwtIFRSVUUNCiAgZmluYWxfY29uc2VudF92YXIgPC0gIlE4LjEiDQoNCiAgcmVxdWlyZV9hdHRlbnRpb25fY2hlY2sgPC0gVFJVRQ0KICByZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjayA8LSBUUlVFDQoNCiAgcmVxdWlyZV9hbGxfZml2ZV90YXNrcyA8LSBUUlVFDQoNCiAgYXR0ZW50aW9uX2NoZWNrX3ZhciA8LSAiUTI1LjFfMTEiDQogIGF0dGVudGlvbl9jaGVja19jb3JyZWN0IDwtICIzIg0KDQogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiA8LSB1bmlmaWVkX2NvbmZpZyRyZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0INCiAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkIDwtIHVuaWZpZWRfY29uZmlnJHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfc2VlZCArIDNMDQogIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfcHJvZ3Jlc3NfZXZlcnkgPC0gdW5pZmllZF9jb25maWckcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9wcm9ncmVzc19ldmVyeQ0KDQogIHJlcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAgPC0gdW5pZmllZF9jb25maWckcmVydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcA0KDQogIGZpZ3VyZV9mb250X2ZhbWlseSA8LSBpZiAoLlBsYXRmb3JtJE9TLnR5cGUgPT0gIndpbmRvd3MiKSB7DQogICAgIll1IEdvdGhpYyINCiAgfSBlbHNlIHsNCiAgICAiIg0KICB9DQoNCg0KICBub3JtX3RleHQgPC0gZnVuY3Rpb24oeCkgew0KICAgIHggJT4lDQogICAgICBhcy5jaGFyYWN0ZXIoKSAlPiUNCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgiXHUzMDAwIiwgIiAiKSAlPiUNCiAgICAgIHN0cl9zcXVpc2goKSAlPiUNCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgi772eIiwgIn4iKSAlPiUNCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgi44CcIiwgIn4iKQ0KICB9DQoNCiAgYXNfbnVtIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICBzdXBwcmVzc1dhcm5pbmdzKHJlYWRyOjpwYXJzZV9udW1iZXIobm9ybV90ZXh0KHgpKSkNCiAgfQ0KDQogIGZpcnN0X2V4aXN0aW5nIDwtIGZ1bmN0aW9uKGRhdCwgY2FuZGlkYXRlcykgew0KICAgIG91dCA8LSBjYW5kaWRhdGVzW2NhbmRpZGF0ZXMgJWluJSBuYW1lcyhkYXQpXQ0KICAgIGlmIChsZW5ndGgob3V0KSA9PSAwKSB7DQogICAgICBOQV9jaGFyYWN0ZXJfDQogICAgfSBlbHNlIHsNCiAgICAgIG91dFsxXQ0KICAgIH0NCiAgfQ0KDQogIGdldF92YXIgPC0gZnVuY3Rpb24oZGF0LCBjYW5kaWRhdGVzKSB7DQogICAgdiA8LSBmaXJzdF9leGlzdGluZyhkYXQsIGNhbmRpZGF0ZXMpDQoNCiAgICBpZiAoaXMubmEodikpIHsNCiAgICAgIHJlcChOQV9jaGFyYWN0ZXJfLCBucm93KGRhdCkpDQogICAgfSBlbHNlIHsNCiAgICAgIGRhdFtbdl1dDQogICAgfQ0KICB9DQoNCiAgaXNfcmVzcG9uc2VfY29kZSA8LSBmdW5jdGlvbih4LCBjb2RlKSB7DQogICAgeF9ub3JtIDwtIG5vcm1fdGV4dCh4KQ0KICAgIGNvZGVfY2hyIDwtIGFzLmNoYXJhY3Rlcihjb2RlKQ0KDQogICAgeF9ub3JtID09IGNvZGVfY2hyIHwNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCBwYXN0ZTAoIlxcKCIsIGNvZGVfY2hyLCAiXFwpJCIpKQ0KICB9DQoNCiAgcmVsZXZlbF9pZl9wcmVzZW50IDwtIGZ1bmN0aW9uKHgsIHJlZikgew0KICAgIHggPC0gZmFjdG9yKHgpDQoNCiAgICBpZiAocmVmICVpbiUgbGV2ZWxzKHgpKSB7DQogICAgICByZWxldmVsKHgsIHJlZiA9IHJlZikNCiAgICB9IGVsc2Ugew0KICAgICAgeA0KICAgIH0NCiAgfQ0KDQogIGZhY3Rvcl9taXNzIDwtIGZ1bmN0aW9uKHgsIG1pc3MgPSAi5qyg5pCN44O754Sh5Zue562UIikgew0KICAgIHggPC0gbm9ybV90ZXh0KHgpDQogICAgeFtpcy5uYSh4KSB8IHggPT0gIiIgfCB4ID09ICJOQSJdIDwtIG1pc3MNCiAgICBmYWN0b3IoeCkNCiAgfQ0KDQogIG1lYW5faW1wdXRlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4IDwtIGFzLm51bWVyaWMoeCkNCiAgICBtaXNzIDwtIGFzLmludGVnZXIoaXMubmEoeCkpDQoNCiAgICBpZiAoYWxsKGlzLm5hKHgpKSkgew0KICAgICAgdmFsdWUgPC0geA0KICAgIH0gZWxzZSB7DQogICAgICB2YWx1ZSA8LSBpZmVsc2UoDQogICAgICAgIGlzLm5hKHgpLA0KICAgICAgICBtZWFuKHgsIG5hLnJtID0gVFJVRSksDQogICAgICAgIHgNCiAgICAgICkNCiAgICB9DQoNCiAgICBsaXN0KA0KICAgICAgdmFsdWUgPSB2YWx1ZSwNCiAgICAgIG1pc3MgPSBtaXNzDQogICAgKQ0KICB9DQoNCiAgd3JpdGVfY3N2X3NhZmVseSA8LSBmdW5jdGlvbih4LCBmaWxlbmFtZSkgew0KICAgIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgICB4LA0KICAgICAgZmlsZS5wYXRoKG91dHB1dF9kaXIsIGZpbGVuYW1lKSwNCiAgICAgIG5hID0gIiINCiAgICApDQogIH0NCg0KICBzYXZlX3Bsb3QgPC0gZnVuY3Rpb24oDQogICAgZmlsZW5hbWUsDQogICAgcGxvdCwNCiAgICB3aWR0aCwNCiAgICBoZWlnaHQsDQogICAgZHBpID0gMzAwDQogICkgew0KICAgIGdncGxvdDI6Omdnc2F2ZSgNCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dHB1dF9kaXIsIGZpbGVuYW1lKSwNCiAgICAgIHBsb3QgPSBwbG90LA0KICAgICAgd2lkdGggPSB3aWR0aCwNCiAgICAgIGhlaWdodCA9IGhlaWdodCwNCiAgICAgIGRwaSA9IGRwaQ0KICAgICkNCiAgfQ0KDQogIGNhbm9uaWNhbGl6ZV9wYXJ0eV9uYW1lIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4X25vcm0gPC0gbm9ybV90ZXh0KHgpDQogICAgeF9jb21wYWN0IDwtIHN0cl9yZXBsYWNlX2FsbCh4X25vcm0sICJcXHMrIiwgIiIpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICBpcy5uYSh4X2NvbXBhY3QpIHwgeF9jb21wYWN0ID09ICIiIH4gTkFfY2hhcmFjdGVyXywNCg0KICAgICAgeF9jb21wYWN0ICVpbiUgYygNCiAgICAgICAgIuiHqueUseawkeS4u+WFmiIsDQogICAgICAgICLoh6rmsJHlhZoiLA0KICAgICAgICAi6Ieq5rCRIg0KICAgICAgKSB+ICLoh6rnlLHmsJHkuLvlhZoiLA0KDQogICAgICB4X2NvbXBhY3QgJWluJSBjKA0KICAgICAgICAi56uL5oay5rCR5Li75YWaIiwNCiAgICAgICAgIueri+awkSINCiAgICAgICkgfiAi56uL5oay5rCR5Li75YWaIiwNCg0KICAgICAgeF9jb21wYWN0ICVpbiUgYygNCiAgICAgICAgIuaXpeacrOe2reaWsOOBruS8miIsDQogICAgICAgICLntq3mlrAiDQogICAgICApIH4gIuaXpeacrOe2reaWsOOBruS8miIsDQoNCiAgICAgIHhfY29tcGFjdCA9PSAi5YWs5piO5YWaIiB+ICLlhazmmI7lhZoiLA0KDQogICAgICB4X2NvbXBhY3QgJWluJSBjKA0KICAgICAgICAi5Zu95rCR5rCR5Li75YWaIiwNCiAgICAgICAgIuWbveawkSINCiAgICAgICkgfiAi5Zu95rCR5rCR5Li75YWaIiwNCg0KICAgICAgeF9jb21wYWN0ICVpbiUgYygNCiAgICAgICAgIuOCjOOBhOOCj+aWsOmBuOe1hCIsDQogICAgICAgICLjgozjgYTjgo8iDQogICAgICApIH4gIuOCjOOBhOOCj+aWsOmBuOe1hCIsDQoNCiAgICAgIHhfY29tcGFjdCA9PSAi5Y+C5pS/5YWaIiB+ICLlj4LmlL/lhZoiLA0KDQogICAgICB4X2NvbXBhY3QgJWluJSBjKA0KICAgICAgICAi5pel5pys5YWx55Sj5YWaIiwNCiAgICAgICAgIuWFseeUo+WFmiINCiAgICAgICkgfiAi5pel5pys5YWx55Sj5YWaIiwNCg0KICAgICAgeF9jb21wYWN0ID09ICLkuK3pgZPmlLnpnanpgKPlkIgiIH4gIuS4remBk+aUuemdqemAo+WQiCIsDQoNCiAgICAgIHhfY29tcGFjdCA9PSAi5pel5pys5L+d5a6I5YWaIiB+ICLml6XmnKzkv53lrojlhZoiLA0KDQogICAgICB4X2NvbXBhY3QgJWluJSBjKA0KICAgICAgICAi56S+5Lya5rCR5Li75YWaIiwNCiAgICAgICAgIuekvuawkeWFmiINCiAgICAgICkgfiAi56S+5Lya5rCR5Li75YWaIiwNCg0KICAgICAgeF9jb21wYWN0ID09ICLjg4Hjg7zjg6Djgb/jgonjgYQiIH4gIuODgeODvOODoOOBv+OCieOBhCIsDQoNCiAgICAgIFRSVUUgfiB4X25vcm0NCiAgICApDQogIH0NCg0KICBjYW5vbmljYWxpemVfZWNvbm9taWNfbGV2ZWwgPC0gZnVuY3Rpb24oeCkgew0KICAgIHhfbm9ybSA8LSBub3JtX3RleHQoeCkgJT4lDQogICAgICBzdHJfcmVwbGFjZV9hbGwoIu+8iyIsICIrIikgJT4lDQogICAgICBzdHJfcmVwbGFjZV9hbGwoIuKIknzvvI184oCVIiwgIi0iKSAlPiUNCiAgICAgIHN0cl9yZXBsYWNlX2FsbCgiJSIsICLvvIUiKQ0KDQogICAgY2FzZV93aGVuKA0KICAgICAgaXMubmEoeF9ub3JtKSB8IHhfbm9ybSA9PSAiIiB+IE5BX2NoYXJhY3Rlcl8sDQoNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiR0RQIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuODl+ODqeOCuXxcXCtcXHMqMSIpIH4NCiAgICAgICAgIkdEUOaIkOmVt+eOh+ODl+ODqeOCuTHvvIUiLA0KDQogICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIkdEUCIpICYNCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg57jgqTjg4rjgrl8LVxccyoxIikgfg0KICAgICAgICAiR0RQ5oiQ6ZW3546H44Oe44Kk44OK44K5Me+8hSIsDQoNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiR0RQIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIsKxXFxzKjB8MFxccyrvvIV85aSJ44KP44KJ44GafOWkieWMluOBquOBlyIpIH4NCiAgICAgICAgIkdEUOaIkOmVt+eOh8KxMO+8hSIsDQoNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi5pel57WM5bmz5Z2HIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuODl+ODqeOCuXxcXCtcXHMqMTAwMCIpIH4NCiAgICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOODl+ODqeOCuTEwMDDlhoYiLA0KDQogICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuaXpee1jOW5s+WdhyIpICYNCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg57jgqTjg4rjgrl8LVxccyoxMDAwIikgfg0KICAgICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U44Oe44Kk44OK44K5MTAwMOWGhiIsDQoNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi5pel57WM5bmz5Z2HIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuWkieOCj+OCieOBmnzlpInljJbjgarjgZd8wrFcXHMqMHwwXFxzKuWGhiIpIH4NCiAgICAgICAgIuaXpee1jOW5s+Wdh+WJjeaciOWQjOacn+avlOWkieOCj+OCieOBmiIsDQoNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiQ1BJfOeJqeS+oSIpICYNCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg5fjg6njgrl8XFwrXFxzKjEiKSB+DQogICAgICAgICJDUEnliY3mnJ/mr5Tjg5fjg6njgrkx44Od44Kk44Oz44OIIiwNCg0KICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJDUEl854mp5L6hIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuODnuOCpOODiuOCuXwtXFxzKjEiKSB+DQogICAgICAgICJDUEnliY3mnJ/mr5Tjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIiwNCg0KICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJDUEl854mp5L6hIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIsKxXFxzKjB8MFxccyrjg53jgqTjg7Pjg4h85aSJ44KP44KJ44GafOWkieWMluOBquOBlyIpIH4NCiAgICAgICAgIkNQSeWJjeacn+avlMKxMOODneOCpOODs+ODiCIsDQoNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAi5aSx5qWt546HfOmbh+eUqCIpICYNCiAgICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLjg5fjg6njgrl8XFwrXFxzKjEiKSB+DQogICAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwNCg0KICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLlpLHmpa3njod86ZuH55SoIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIuODnuOCpOODiuOCuXwtXFxzKjEiKSB+DQogICAgICAgICLlpLHmpa3njofliY3mnJ/mr5Tjg57jgqTjg4rjgrkx77yFIiwNCg0KICAgICAgc3RyX2RldGVjdCh4X25vcm0sICLlpLHmpa3njod86ZuH55SoIikgJg0KICAgICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIsKxXFxzKjB8MFxccyrvvIV85aSJ44KP44KJ44GafOWkieWMluOBquOBlyIpIH4NCiAgICAgICAgIuWksealreeOh+WJjeacn+avlMKxMO+8hSIsDQoNCiAgICAgIFRSVUUgfiB4X25vcm0NCiAgICApDQogIH0NCg0KICBsZXZlbF90b19hdHRyX3ZhciA8LSBmdW5jdGlvbih4KSB7DQogICAgeF9ub3JtIDwtIGNhbm9uaWNhbGl6ZV9lY29ub21pY19sZXZlbCh4KQ0KDQogICAgY2FzZV93aGVuKA0KICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJeR0RQ5oiQ6ZW3546HIikgfiAiZ2RwX2dyb3d0aCIsDQogICAgICBzdHJfZGV0ZWN0KHhfbm9ybSwgIl7ml6XntYzlubPlnYciKSB+ICJuaWtrZWkiLA0KICAgICAgc3RyX2RldGVjdCh4X25vcm0sICJeQ1BJIikgfiAiY3BpIiwNCiAgICAgIHN0cl9kZXRlY3QoeF9ub3JtLCAiXuWksealreeOhyIpIH4gInVuZW1wbG95bWVudCIsDQogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICAgICkNCiAgfQ0KDQogIHRpZHlfZml4ZXN0IDwtIGZ1bmN0aW9uKG1vZGVsKSB7DQogICAgY3QgPC0gYXMuZGF0YS5mcmFtZShmaXhlc3Q6OmNvZWZ0YWJsZShtb2RlbCkpDQogICAgY3QkdGVybSA8LSByb3duYW1lcyhjdCkNCg0KICAgIGVzdGltYXRlX2NvbCA8LSBpbnRlcnNlY3QoDQogICAgICBjKCJFc3RpbWF0ZSIsICJlc3RpbWF0ZSIpLA0KICAgICAgbmFtZXMoY3QpDQogICAgKVsxXQ0KDQogICAgc2VfY29sIDwtIGludGVyc2VjdCgNCiAgICAgIGMoIlN0ZC4gRXJyb3IiLCAiU3RkLiBlcnJvciIsICJzdGQuZXJyb3IiKSwNCiAgICAgIG5hbWVzKGN0KQ0KICAgIClbMV0NCg0KICAgIHN0YXRpc3RpY19jb2wgPC0gaW50ZXJzZWN0KA0KICAgICAgYygidCB2YWx1ZSIsICJ6IHZhbHVlIiwgInN0YXRpc3RpYyIpLA0KICAgICAgbmFtZXMoY3QpDQogICAgKVsxXQ0KDQogICAgcF9jb2wgPC0gaW50ZXJzZWN0KA0KICAgICAgYygiUHIoPnx0fCkiLCAiUHIoPnx6fCkiLCAicC52YWx1ZSIpLA0KICAgICAgbmFtZXMoY3QpDQogICAgKVsxXQ0KDQogICAgaWYgKA0KICAgICAgaXMubmEoZXN0aW1hdGVfY29sKSB8DQogICAgICAgIGlzLm5hKHNlX2NvbCkgfA0KICAgICAgICBpcy5uYShzdGF0aXN0aWNfY29sKSB8DQogICAgICAgIGlzLm5hKHBfY29sKQ0KICAgICkgew0KICAgICAgc3RvcCgiQ2hlY2sgZGF0YSIpDQogICAgfQ0KDQogICAgY3QgJT4lDQogICAgICBhc190aWJibGUoKSAlPiUNCiAgICAgIHRyYW5zbXV0ZSgNCiAgICAgICAgdGVybSA9IHRlcm0sDQogICAgICAgIGVzdGltYXRlID0gLmRhdGFbW2VzdGltYXRlX2NvbF1dLA0KICAgICAgICBzdGQuZXJyb3IgPSAuZGF0YVtbc2VfY29sXV0sDQogICAgICAgIHN0YXRpc3RpYyA9IC5kYXRhW1tzdGF0aXN0aWNfY29sXV0sDQogICAgICAgIHAudmFsdWUgPSAuZGF0YVtbcF9jb2xdXSwNCiAgICAgICAgY29uZi5sb3cgPSBlc3RpbWF0ZSAtIDEuOTYgKiBzdGQuZXJyb3IsDQogICAgICAgIGNvbmYuaGlnaCA9IGVzdGltYXRlICsgMS45NiAqIHN0ZC5lcnJvcg0KICAgICAgKQ0KICB9DQoNCg0KICBpZiAoIWZpbGUuZXhpc3RzKGRhdGFfZmlsZSkpIHsNCiAgICBzdG9wKCJDaGVjayBkYXRhIikNCiAgfQ0KDQogIHJhdyA8LSByZWFkcjo6cmVhZF9jc3YoDQogICAgZGF0YV9maWxlLA0KICAgIGNvbF90eXBlcyA9IGNvbHMoLmRlZmF1bHQgPSBjb2xfY2hhcmFjdGVyKCkpLA0KICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UsDQogICAgbmFtZV9yZXBhaXIgPSAibWluaW1hbCINCiAgKQ0KDQoNCiAgaWYgKHJlcXVpcmVfZmluYWxfY29uc2VudCkgew0KICAgIGZpbmFsX2NvbnNlbnRfdmFyIDwtIGRldGVjdF9maW5hbF9jb25zZW50X2NvbHVtbigNCiAgICAgIHJhdyA9IHJhdywNCiAgICAgIHByZWZlcnJlZF9jYW5kaWRhdGVzID0gYygiUTguMSIsICJROS4xIiwgIlExMC4xIiksDQogICAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAzIg0KICAgICkNCiAgfQ0KDQogIGlmIChyZXF1aXJlX2F0dGVudGlvbl9jaGVjaykgew0KICAgIGF0dGVudGlvbl9jaGVja192YXIgPC0gZGV0ZWN0X2F0dGVudGlvbl9jaGVja19jb2x1bW4oDQogICAgICByYXcgPSByYXcsDQogICAgICBwcmVmZXJyZWRfY2FuZGlkYXRlcyA9IGMoIlEyNS4xXzExIiwgIlEyNS4xXzEwIiksDQogICAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAzIg0KICAgICkNCiAgfQ0KDQogIGlmICghIlJlc3BvbnNlSWQiICVpbiUgbmFtZXMocmF3KSkgew0KICAgIHN0b3AoIkNoZWNrIGRhdGEiKQ0KICB9DQoNCiAgZGZfaGVhZGVyX3JlbW92ZWQgPC0gcmF3ICU+JQ0KICAgIGZpbHRlcigNCiAgICAgICFpcy5uYShSZXNwb25zZUlkKSwNCiAgICAgIFJlc3BvbnNlSWQgIT0gIiIsDQogICAgICAhc3RyX2RldGVjdCgNCiAgICAgICAgbm9ybV90ZXh0KFJlc3BvbnNlSWQpLA0KICAgICAgICAiXihSZXNwb25zZSBJRHzlm57nrZRJRCkkfEltcG9ydElkIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgbXV0YXRlKElEID0gYXMuY2hhcmFjdGVyKFJlc3BvbnNlSWQpKQ0KDQogIGR1cGxpY2F0ZV9pZHMgPC0gZGZfaGVhZGVyX3JlbW92ZWQgJT4lDQogICAgY291bnQoSUQpICU+JQ0KICAgIGZpbHRlcihuID4gMSkNCg0KICBpZiAobnJvdyhkdXBsaWNhdGVfaWRzKSA+IDApIHsNCiAgICBwcmludChkdXBsaWNhdGVfaWRzKQ0KICAgIHN0b3AoIkNoZWNrIikNCiAgfQ0KDQogIHNhbXBsZV9mbG93IDwtIHRpYmJsZSgNCiAgICBzdGFnZSA9ICJRdWFsdHJpY3Pos6rllY/mlofooYzjg7tJbXBvcnRJZOihjOOCkumZpOWkluW+jCIsDQogICAgbiA9IG5yb3coZGZfaGVhZGVyX3JlbW92ZWQpDQogICkNCg0KICBkZiA8LSBkZl9oZWFkZXJfcmVtb3ZlZA0KDQogIGlmIChyZXF1aXJlX2luaXRpYWxfY29uc2VudCkgew0KICAgIGlmICghIlExLjEiICVpbiUgbmFtZXMoZGYpKSB7DQogICAgICBzdG9wKCJDaGVjayBpbml0aWFsIGNvbnNlbnQiKQ0KICAgIH0NCg0KICAgIGRmIDwtIGRmICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpc19yZXNwb25zZV9jb2RlKFExLjEsIDEpIHwNCiAgICAgICAgICBzdHJfZGV0ZWN0KA0KICAgICAgICAgICAgbm9ybV90ZXh0KFExLjEpLA0KICAgICAgICAgICAgIui2o+aXqOOBq+WQjOaEj+OBl+OBpi4q5Y2U5Yqb44GZ44KLIg0KICAgICAgICAgICkNCiAgICAgICkNCg0KICAgIHNhbXBsZV9mbG93IDwtIGJpbmRfcm93cygNCiAgICAgIHNhbXBsZV9mbG93LA0KICAgICAgdGliYmxlKA0KICAgICAgICBzdGFnZSA9ICLliJ3lm57lkIzmhI8gUTEuMSA9IDEiLA0KICAgICAgICBuID0gbnJvdyhkZikNCiAgICAgICkNCiAgICApDQogIH0NCg0KICBpZiAocmVxdWlyZV9maW5hbF9jb25zZW50KSB7DQogICAgaWYgKGlzLm5hKGZpbmFsX2NvbnNlbnRfdmFyKSB8fCAhZmluYWxfY29uc2VudF92YXIgJWluJSBuYW1lcyhkZikpIHsNCiAgICAgIHN0b3AoIkNoZWNrIGZpbmFsIGNvbnNlbnQiKQ0KICAgIH0NCg0KICAgIGRmIDwtIGRmICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpc19yZXNwb25zZV9jb2RlKC5kYXRhW1tmaW5hbF9jb25zZW50X3Zhcl1dLCAxKSB8DQogICAgICAgICAgc3RyX2RldGVjdCgNCiAgICAgICAgICAgIG5vcm1fdGV4dCguZGF0YVtbZmluYWxfY29uc2VudF92YXJdXSksDQogICAgICAgICAgICAi5ZCM5oSP44GXLirlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgosiDQogICAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKA0KICAgICAgc2FtcGxlX2Zsb3csDQogICAgICB0aWJibGUoDQogICAgICAgIHN0YWdlID0gcGFzdGUwKCLmnIDntYLlkIzmhI8gIiwgZmluYWxfY29uc2VudF92YXIsICIgPSAxIiksDQogICAgICAgIG4gPSBucm93KGRmKQ0KICAgICAgKQ0KICAgICkNCiAgfQ0KDQogIGlmIChyZXF1aXJlX2F0dGVudGlvbl9jaGVjaykgew0KICAgIGlmICghYXR0ZW50aW9uX2NoZWNrX3ZhciAlaW4lIG5hbWVzKGRmKSkgew0KICAgICAgc3RvcCgiQ2hlY2sgYXR0ZW50aW9uIGl0ZW0iKQ0KICAgIH0NCg0KICAgIGF0dGVudGlvbl9jaGVja19jb3JyZWN0IDwtIGRldGVjdF9hdHRlbnRpb25fY29ycmVjdF9jb2RlKA0KICAgICAgZGZbW2F0dGVudGlvbl9jaGVja192YXJdXSwNCiAgICAgIGRpc3BsYXllZF9hbnN3ZXIgPSAzTCwNCiAgICAgIHJlY29kZWRfYW5zd2VyID0gNkwsDQogICAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAzIg0KICAgICkNCg0KICAgIGRmIDwtIGRmICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpc19yZXNwb25zZV9jb2RlKA0KICAgICAgICAgIC5kYXRhW1thdHRlbnRpb25fY2hlY2tfdmFyXV0sDQogICAgICAgICAgYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QNCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgc2FtcGxlX2Zsb3cgPC0gYmluZF9yb3dzKA0KICAgICAgc2FtcGxlX2Zsb3csDQogICAgICB0aWJibGUoDQogICAgICAgIHN0YWdlID0gcGFzdGUwKA0KICAgICAgICAgICLmjIfnpLrpoIXnm67mraPnrZTvvIgiLA0KICAgICAgICAgIGF0dGVudGlvbl9jaGVja192YXIsDQogICAgICAgICAgIuOAgeS/neWtmOOCs+ODvOODiT0iLA0KICAgICAgICAgIGF0dGVudGlvbl9jaGVja19jb3JyZWN0LA0KICAgICAgICAgICLvvIkiDQogICAgICAgICksDQogICAgICAgIG4gPSBucm93KGRmKQ0KICAgICAgKQ0KICAgICkNCiAgfQ0KDQogIHByaW50KHNhbXBsZV9mbG93KQ0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHNhbXBsZV9mbG93LA0KICAgICJzYW1wbGVfZmxvd19iZWZvcmVfY29uam9pbnQuY3N2Ig0KICApDQoNCg0KICBjaG9pY2VfbWFwIDwtIGRldGVjdF9jb25qb2ludF9jaG9pY2VfbWFwKA0KICAgIHJhdyA9IHJhdywNCiAgICBwYXJ0eV9udW1iZXJzID0gMjo1LA0KICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDMiDQogICkNCg0KICBtYW5pcHVsYXRpb25fbWFwIDwtIGRldGVjdF9tYW5pcHVsYXRpb25fbWFwKA0KICAgIHJhdyA9IHJhdywNCiAgICBjaG9pY2VfbWFwID0gY2hvaWNlX21hcCwNCiAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAzIg0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseShjaG9pY2VfbWFwLCAiZGV0ZWN0ZWRfY2hvaWNlX3F1ZXN0aW9uX21hcC5jc3YiKQ0KICB3cml0ZV9jc3Zfc2FmZWx5KG1hbmlwdWxhdGlvbl9tYXAsICJkZXRlY3RlZF9tYW5pcHVsYXRpb25fcXVlc3Rpb25fbWFwLmNzdiIpDQoNCg0KICByZXF1aXJlZF9hdHRyX3ZhcnMgPC0gYygNCiAgICAicGFydHlfbmFtZSIsDQogICAgImdkcF9ncm93dGgiLA0KICAgICJuaWtrZWkiLA0KICAgICJjcGkiLA0KICAgICJ1bmVtcGxveW1lbnQiDQogICkNCg0KICBleHBlY3RlZF9wYXJ0eV9sZXZlbHMgPC0gYygNCiAgICAi6Ieq55Sx5rCR5Li75YWaIiwNCiAgICAi56uL5oay5rCR5Li75YWaIiwNCiAgICAi5pel5pys57at5paw44Gu5LyaIiwNCiAgICAi5YWs5piO5YWaIiwNCiAgICAi5Zu95rCR5rCR5Li75YWaIiwNCiAgICAi44KM44GE44KP5paw6YG457WEIiwNCiAgICAi5Y+C5pS/5YWaIiwNCiAgICAi5pel5pys5YWx55Sj5YWaIiwNCiAgICAi5Lit6YGT5pS56Z2p6YCj5ZCIIg0KICApDQoNCiAgYWxsb3dlZF9lY29ub21pY19sZXZlbHMgPC0gbGlzdCgNCiAgICBnZHBfZ3Jvd3RoID0gYygNCiAgICAgICJHRFDmiJDplbfnjofCsTDvvIUiLA0KICAgICAgIkdEUOaIkOmVt+eOh+ODl+ODqeOCuTHvvIUiLA0KICAgICAgIkdEUOaIkOmVt+eOh+ODnuOCpOODiuOCuTHvvIUiDQogICAgKSwNCg0KICAgIG5pa2tlaSA9IGMoDQogICAgICAi5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+U5aSJ44KP44KJ44GaIiwNCiAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwNCiAgICAgICLml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIg0KICAgICksDQoNCiAgICBjcGkgPSBjKA0KICAgICAgIkNQSeWJjeacn+avlMKxMOODneOCpOODs+ODiCIsDQogICAgICAiQ1BJ5YmN5pyf5q+U44OX44Op44K5MeODneOCpOODs+ODiCIsDQogICAgICAiQ1BJ5YmN5pyf5q+U44Oe44Kk44OK44K5MeODneOCpOODs+ODiCINCiAgICApLA0KDQogICAgdW5lbXBsb3ltZW50ID0gYygNCiAgICAgICLlpLHmpa3njofliY3mnJ/mr5TCsTDvvIUiLA0KICAgICAgIuWksealreeOh+WJjeacn+avlOODl+ODqeOCuTHvvIUiLA0KICAgICAgIuWksealreeOh+WJjeacn+avlOODnuOCpOODiuOCuTHvvIUiDQogICAgKQ0KICApDQoNCg0KICBtYWtlX3Byb2ZpbGVfbG9uZyA8LSBmdW5jdGlvbihkYXQsIG5fcGFydHkpIHsNCg0KICAgIG1hcF9uIDwtIGNob2ljZV9tYXAgJT4lDQogICAgICBmaWx0ZXIocGFydHlfbiA9PSBuX3BhcnR5KQ0KDQogICAgcXZhcnMgPC0gbWFwX24kY2hvaWNlX3Zhcg0KDQogICAgbWlzc2luZ19xIDwtIHNldGRpZmYocXZhcnMsIG5hbWVzKGRhdCkpDQoNCiAgICBpZiAobGVuZ3RoKG1pc3NpbmdfcSkgPiAwKSB7DQogICAgICBzdG9wKCJDaGVjayBjaG9pY2UgY29sdW1ucyIpDQogICAgfQ0KDQogICAgZGF0X24gPC0gZGF0ICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpZl9hbnkoDQogICAgICAgICAgYWxsX29mKHF2YXJzKSwNCiAgICAgICAgICB+ICFpcy5uYSgueCkgJiBub3JtX3RleHQoLngpICE9ICIiDQogICAgICAgICkNCiAgICAgICkNCg0KICAgIGlmIChyZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjaykgew0KICAgICAgbWFuaXB1bGF0aW9uX3JvdyA8LSBtYW5pcHVsYXRpb25fbWFwICU+JQ0KICAgICAgICBmaWx0ZXIocGFydHlfbiA9PSBuX3BhcnR5KQ0KDQogICAgICBtYW5pcHVsYXRpb25fdmFyIDwtIG1hbmlwdWxhdGlvbl9yb3ckbWFuaXB1bGF0aW9uX3Zhcg0KICAgICAgY29ycmVjdF9hbnN3ZXIgPC0gbWFuaXB1bGF0aW9uX3JvdyRjb3JyZWN0X2Fuc3dlcg0KDQogICAgICBpZiAoIW1hbmlwdWxhdGlvbl92YXIgJWluJSBuYW1lcyhkYXRfbikpIHsNCiAgICAgICAgc3RvcCgiQ2hlY2sgbWFuaXB1bGF0aW9uIGl0ZW0iKQ0KICAgICAgfQ0KDQogICAgICBkYXRfbiA8LSBkYXRfbiAlPiUNCiAgICAgICAgZmlsdGVyKA0KICAgICAgICAgIGlzX3Jlc3BvbnNlX2NvZGUoDQogICAgICAgICAgICAuZGF0YVtbbWFuaXB1bGF0aW9uX3Zhcl1dLA0KICAgICAgICAgICAgY29ycmVjdF9hbnN3ZXINCiAgICAgICAgICApDQogICAgICAgICkNCiAgICB9DQoNCg0KICAgIGNob2ljZV9sb25nIDwtIGRhdF9uICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICBJRCwNCiAgICAgICAgYWxsX29mKHF2YXJzKQ0KICAgICAgKSAlPiUNCiAgICAgIHBpdm90X2xvbmdlcigNCiAgICAgICAgY29scyA9IGFsbF9vZihxdmFycyksDQogICAgICAgIG5hbWVzX3RvID0gImNob2ljZV92YXIiLA0KICAgICAgICB2YWx1ZXNfdG8gPSAiY2hvaWNlX3JhdyINCiAgICAgICkgJT4lDQogICAgICBsZWZ0X2pvaW4oDQogICAgICAgIG1hcF9uLA0KICAgICAgICBieSA9ICJjaG9pY2VfdmFyIg0KICAgICAgKSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgY2hvaWNlID0gcGFyc2VfY2hvaWNlX3Bvc2l0aW9uKGNob2ljZV9yYXcpDQogICAgICApICU+JQ0KICAgICAgZmlsdGVyKCFpcy5uYShjaG9pY2UpKSAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgSUQsDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIHRhc2ssDQogICAgICAgIGNob2ljZQ0KICAgICAgKQ0KDQogICAgaW52YWxpZF9jaG9pY2UgPC0gY2hvaWNlX2xvbmcgJT4lDQogICAgICBmaWx0ZXIoDQogICAgICAgIGNob2ljZSA8IDEgfA0KICAgICAgICAgIGNob2ljZSA+IG5fcGFydHkNCiAgICAgICkNCg0KICAgIGlmIChucm93KGludmFsaWRfY2hvaWNlKSA+IDApIHsNCiAgICAgIHByaW50KGludmFsaWRfY2hvaWNlKQ0KICAgICAgc3RvcCgiQ2hlY2sgY2hvaWNlIHZhbHVlcyIpDQogICAgfQ0KDQogICAgZHVwbGljYXRlX2Nob2ljZSA8LSBjaG9pY2VfbG9uZyAlPiUNCiAgICAgIGNvdW50KA0KICAgICAgICBJRCwNCiAgICAgICAgdGFzaw0KICAgICAgKSAlPiUNCiAgICAgIGZpbHRlcihuICE9IDEpDQoNCiAgICBpZiAobnJvdyhkdXBsaWNhdGVfY2hvaWNlKSA+IDApIHsNCiAgICAgIHByaW50KGR1cGxpY2F0ZV9jaG9pY2UpDQogICAgICBzdG9wKCJDaGVjayBkdXBsaWNhdGUgY2hvaWNlcyIpDQogICAgfQ0KDQoNCiAgICBwYXJ0eV9yZWdleCA8LSBwYXN0ZTAoDQogICAgICAiXlMzX1AiLA0KICAgICAgbl9wYXJ0eSwNCiAgICAgICJfUEFSVFlfKFsxLTVdKV8oWzEtIiwNCiAgICAgIG5fcGFydHksDQogICAgICAiXSkkIg0KICAgICkNCg0KICAgIHBhcnR5X2NvbHMgPC0gbmFtZXMoZGF0X24pWw0KICAgICAgc3RyX2RldGVjdCgNCiAgICAgICAgbmFtZXMoZGF0X24pLA0KICAgICAgICBwYXJ0eV9yZWdleA0KICAgICAgKQ0KICAgIF0NCg0KICAgIGV4cGVjdGVkX3BhcnR5X2NvbHNfbiA8LSA1ICogbl9wYXJ0eQ0KDQogICAgaWYgKGxlbmd0aChwYXJ0eV9jb2xzKSAhPSBleHBlY3RlZF9wYXJ0eV9jb2xzX24pIHsNCiAgICAgIHN0b3AoIkNoZWNrIikNCiAgICB9DQoNCiAgICBwYXJ0eV9sb25nIDwtIGRhdF9uICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICBJRCwNCiAgICAgICAgYWxsX29mKHBhcnR5X2NvbHMpDQogICAgICApICU+JQ0KICAgICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgICBjb2xzID0gYWxsX29mKHBhcnR5X2NvbHMpLA0KICAgICAgICBuYW1lc190byA9ICJwYXJ0eV92YXIiLA0KICAgICAgICB2YWx1ZXNfdG8gPSAicGFydHlfbmFtZV9yYXciDQogICAgICApICU+JQ0KICAgICAgZXh0cmFjdCgNCiAgICAgICAgcGFydHlfdmFyLA0KICAgICAgICBpbnRvID0gYygNCiAgICAgICAgICAidGFzayIsDQogICAgICAgICAgInByb2ZpbGUiDQogICAgICAgICksDQogICAgICAgIHJlZ2V4ID0gcGFydHlfcmVnZXgsDQogICAgICAgIGNvbnZlcnQgPSBUUlVFDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBwYXJ0eV9uYW1lID0gY2Fub25pY2FsaXplX3BhcnR5X25hbWUoDQogICAgICAgICAgcGFydHlfbmFtZV9yYXcNCiAgICAgICAgKQ0KICAgICAgKSAlPiUNCiAgICAgIGZpbHRlcigNCiAgICAgICAgdGFzayAlaW4lIDE6NSwNCiAgICAgICAgcHJvZmlsZSAlaW4lIDE6bl9wYXJ0eSwNCiAgICAgICAgIWlzLm5hKHBhcnR5X25hbWUpLA0KICAgICAgICBwYXJ0eV9uYW1lICE9ICIiDQogICAgICApICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICBJRCwNCiAgICAgICAgdGFzaywNCiAgICAgICAgcHJvZmlsZSwNCiAgICAgICAgcGFydHlfbmFtZQ0KICAgICAgKQ0KDQogICAgZHVwbGljYXRlX3BhcnR5X25hbWUgPC0gcGFydHlfbG9uZyAlPiUNCiAgICAgIGNvdW50KA0KICAgICAgICBJRCwNCiAgICAgICAgdGFzaywNCiAgICAgICAgcHJvZmlsZQ0KICAgICAgKSAlPiUNCiAgICAgIGZpbHRlcihuICE9IDEpDQoNCiAgICBpZiAobnJvdyhkdXBsaWNhdGVfcGFydHlfbmFtZSkgPiAwKSB7DQogICAgICBwcmludCgNCiAgICAgICAgaGVhZCgNCiAgICAgICAgICBkdXBsaWNhdGVfcGFydHlfbmFtZSwNCiAgICAgICAgICA1MA0KICAgICAgICApDQogICAgICApDQogICAgICBzdG9wKCJDaGVjayIpDQogICAgfQ0KDQoNCiAgICBsZXZlbF9yZWdleCA8LSBwYXN0ZTAoDQogICAgICAiXlMzX1AiLA0KICAgICAgbl9wYXJ0eSwNCiAgICAgICJfRl8oWzEtNV0pXyhbMS0iLA0KICAgICAgbl9wYXJ0eSwNCiAgICAgICJdKV8oWzEtNF0pJCINCiAgICApDQoNCiAgICBsZXZlbF9jb2xzIDwtIG5hbWVzKGRhdF9uKVsNCiAgICAgIHN0cl9kZXRlY3QoDQogICAgICAgIG5hbWVzKGRhdF9uKSwNCiAgICAgICAgbGV2ZWxfcmVnZXgNCiAgICAgICkNCiAgICBdDQoNCiAgICBleHBlY3RlZF9sZXZlbF9jb2xzX24gPC0gNSAqIG5fcGFydHkgKiA0DQoNCiAgICBpZiAobGVuZ3RoKGxldmVsX2NvbHMpICE9IGV4cGVjdGVkX2xldmVsX2NvbHNfbikgew0KICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpDQogICAgfQ0KDQogICAgbGV2ZWxfbG9uZyA8LSBkYXRfbiAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgSUQsDQogICAgICAgIGFsbF9vZihsZXZlbF9jb2xzKQ0KICAgICAgKSAlPiUNCiAgICAgIHBpdm90X2xvbmdlcigNCiAgICAgICAgY29scyA9IGFsbF9vZihsZXZlbF9jb2xzKSwNCiAgICAgICAgbmFtZXNfdG8gPSAiZnZhciIsDQogICAgICAgIHZhbHVlc190byA9ICJsZXZlbF9yYXciDQogICAgICApICU+JQ0KICAgICAgZXh0cmFjdCgNCiAgICAgICAgZnZhciwNCiAgICAgICAgaW50byA9IGMoDQogICAgICAgICAgInRhc2siLA0KICAgICAgICAgICJwcm9maWxlIiwNCiAgICAgICAgICAiYXR0cl9vcmRlciINCiAgICAgICAgKSwNCiAgICAgICAgcmVnZXggPSBsZXZlbF9yZWdleCwNCiAgICAgICAgY29udmVydCA9IFRSVUUNCiAgICAgICkgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGxldmVsID0gY2Fub25pY2FsaXplX2Vjb25vbWljX2xldmVsKA0KICAgICAgICAgIGxldmVsX3Jhdw0KICAgICAgICApLA0KICAgICAgICBhdHRyX3ZhciA9IGxldmVsX3RvX2F0dHJfdmFyKA0KICAgICAgICAgIGxldmVsDQogICAgICAgICkNCiAgICAgICkgJT4lDQogICAgICBmaWx0ZXIoDQogICAgICAgIHRhc2sgJWluJSAxOjUsDQogICAgICAgIHByb2ZpbGUgJWluJSAxOm5fcGFydHksDQogICAgICAgIGF0dHJfb3JkZXIgJWluJSAxOjQsDQogICAgICAgICFpcy5uYShsZXZlbCksDQogICAgICAgIGxldmVsICE9ICIiDQogICAgICApDQoNCiAgICB1bmtub3duX2xldmVscyA8LSBsZXZlbF9sb25nICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpcy5uYShhdHRyX3ZhcikNCiAgICAgICkgJT4lDQogICAgICBkaXN0aW5jdCgNCiAgICAgICAgbGV2ZWxfcmF3LA0KICAgICAgICBsZXZlbA0KICAgICAgKQ0KDQogICAgaWYgKG5yb3codW5rbm93bl9sZXZlbHMpID4gMCkgew0KICAgICAgcHJpbnQodW5rbm93bl9sZXZlbHMpDQogICAgICBzdG9wKCJDaGVjayBhdHRyaWJ1dGVzIikNCiAgICB9DQoNCiAgICBwcm9maWxlX2F0dHJpYnV0ZV9jb3VudCA8LSBsZXZlbF9sb25nICU+JQ0KICAgICAgY291bnQoDQogICAgICAgIElELA0KICAgICAgICB0YXNrLA0KICAgICAgICBwcm9maWxlLA0KICAgICAgICBuYW1lID0gIm5fYXR0cmlidXRlX3Jvd3MiDQogICAgICApICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBuX2F0dHJpYnV0ZV9yb3dzICE9IDQNCiAgICAgICkNCg0KICAgIGlmIChucm93KHByb2ZpbGVfYXR0cmlidXRlX2NvdW50KSA+IDApIHsNCiAgICAgIHByaW50KA0KICAgICAgICBoZWFkKA0KICAgICAgICAgIHByb2ZpbGVfYXR0cmlidXRlX2NvdW50LA0KICAgICAgICAgIDUwDQogICAgICAgICkNCiAgICAgICkNCiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQ0KICAgIH0NCg0KICAgIGR1cGxpY2F0ZV9hdHRyaWJ1dGUgPC0gbGV2ZWxfbG9uZyAlPiUNCiAgICAgIGNvdW50KA0KICAgICAgICBJRCwNCiAgICAgICAgdGFzaywNCiAgICAgICAgcHJvZmlsZSwNCiAgICAgICAgYXR0cl92YXINCiAgICAgICkgJT4lDQogICAgICBmaWx0ZXIobiAhPSAxKQ0KDQogICAgaWYgKG5yb3coZHVwbGljYXRlX2F0dHJpYnV0ZSkgPiAwKSB7DQogICAgICBwcmludCgNCiAgICAgICAgaGVhZCgNCiAgICAgICAgICBkdXBsaWNhdGVfYXR0cmlidXRlLA0KICAgICAgICAgIDUwDQogICAgICAgICkNCiAgICAgICkNCiAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQ0KICAgIH0NCg0KDQogICAgZWNvbm9taWNfd2lkZSA8LSBsZXZlbF9sb25nICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICBJRCwNCiAgICAgICAgdGFzaywNCiAgICAgICAgcHJvZmlsZSwNCiAgICAgICAgYXR0cl92YXIsDQogICAgICAgIGxldmVsDQogICAgICApICU+JQ0KICAgICAgcGl2b3Rfd2lkZXIoDQogICAgICAgIG5hbWVzX2Zyb20gPSBhdHRyX3ZhciwNCiAgICAgICAgdmFsdWVzX2Zyb20gPSBsZXZlbCwNCiAgICAgICAgdmFsdWVzX2ZuID0gbGlzdCgNCiAgICAgICAgICBsZXZlbCA9IH4gZmlyc3QoLngpDQogICAgICAgICkNCiAgICAgICkNCg0KICAgIHByb2ZpbGVfd2lkZSA8LSBwYXJ0eV9sb25nICU+JQ0KICAgICAgaW5uZXJfam9pbigNCiAgICAgICAgZWNvbm9taWNfd2lkZSwNCiAgICAgICAgYnkgPSBjKA0KICAgICAgICAgICJJRCIsDQogICAgICAgICAgInRhc2siLA0KICAgICAgICAgICJwcm9maWxlIg0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgaW5uZXJfam9pbigNCiAgICAgICAgY2hvaWNlX2xvbmcsDQogICAgICAgIGJ5ID0gYygNCiAgICAgICAgICAiSUQiLA0KICAgICAgICAgICJ0YXNrIg0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBwYXJ0eV9uID0gbl9wYXJ0eSwNCiAgICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKA0KICAgICAgICAgIHByb2ZpbGUgPT0gY2hvaWNlDQogICAgICAgICksDQogICAgICAgIHRhc2tfaWQgPSBwYXN0ZSgNCiAgICAgICAgICBJRCwNCiAgICAgICAgICBwYXJ0eV9uLA0KICAgICAgICAgIHRhc2ssDQogICAgICAgICAgc2VwID0gIl8iDQogICAgICAgICksDQogICAgICAgIHByb2ZpbGVfaWQgPSBwYXN0ZSgNCiAgICAgICAgICBJRCwNCiAgICAgICAgICBwYXJ0eV9uLA0KICAgICAgICAgIHRhc2ssDQogICAgICAgICAgcHJvZmlsZSwNCiAgICAgICAgICBzZXAgPSAiXyINCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgbWlzc2luZ19hdHRyIDwtIHNldGRpZmYoDQogICAgICByZXF1aXJlZF9hdHRyX3ZhcnMsDQogICAgICBuYW1lcyhwcm9maWxlX3dpZGUpDQogICAgKQ0KDQogICAgaWYgKGxlbmd0aChtaXNzaW5nX2F0dHIpID4gMCkgew0KICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpDQogICAgfQ0KDQogICAgcHJvZmlsZV93aWRlIDwtIHByb2ZpbGVfd2lkZSAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgSUQsDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIHRhc2ssDQogICAgICAgIHByb2ZpbGUsDQogICAgICAgIGNob2ljZSwNCiAgICAgICAgc2VsZWN0ZWQsDQogICAgICAgIHRhc2tfaWQsDQogICAgICAgIHByb2ZpbGVfaWQsDQogICAgICAgIGFsbF9vZihyZXF1aXJlZF9hdHRyX3ZhcnMpDQogICAgICApICU+JQ0KICAgICAgYXJyYW5nZSgNCiAgICAgICAgSUQsDQogICAgICAgIHRhc2ssDQogICAgICAgIHByb2ZpbGUNCiAgICAgICkNCg0KICAgIHJldHVybihwcm9maWxlX3dpZGUpDQogIH0NCg0KDQogIGNvbmpvaW50XzIgPC0gbWFrZV9wcm9maWxlX2xvbmcoDQogICAgZGYsDQogICAgMg0KICApDQoNCiAgY29uam9pbnRfMyA8LSBtYWtlX3Byb2ZpbGVfbG9uZygNCiAgICBkZiwNCiAgICAzDQogICkNCg0KICBjb25qb2ludF80IDwtIG1ha2VfcHJvZmlsZV9sb25nKA0KICAgIGRmLA0KICAgIDQNCiAgKQ0KDQogIGNvbmpvaW50XzUgPC0gbWFrZV9wcm9maWxlX2xvbmcoDQogICAgZGYsDQogICAgNQ0KICApDQoNCiAgY29uam9pbnRfYWxsX3VuZmlsdGVyZWQgPC0gYmluZF9yb3dzKA0KICAgIGNvbmpvaW50XzIsDQogICAgY29uam9pbnRfMywNCiAgICBjb25qb2ludF80LA0KICAgIGNvbmpvaW50XzUNCiAgKQ0KDQoNCiAgaWRfdGFza19jaGVjayA8LSBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCAlPiUNCiAgICBncm91cF9ieSgNCiAgICAgIElELA0KICAgICAgcGFydHlfbiwNCiAgICAgIHRhc2sNCiAgICApICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIG5fcHJvZmlsZXMgPSBuKCksDQogICAgICBzZWxlY3RlZF9zdW0gPSBzdW0oc2VsZWN0ZWQpLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICkgJT4lDQogICAgZ3JvdXBfYnkoDQogICAgICBJRCwNCiAgICAgIHBhcnR5X24NCiAgICApICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIG5fdGFza3MgPSBuX2Rpc3RpbmN0KHRhc2spLA0KICAgICAgYWxsX3Rhc2tzX29rID0gYWxsKA0KICAgICAgICBuX3Byb2ZpbGVzID09IHBhcnR5X24gJg0KICAgICAgICAgIHNlbGVjdGVkX3N1bSA9PSAxDQogICAgICApLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICkNCg0KICBpZiAocmVxdWlyZV9hbGxfZml2ZV90YXNrcykgew0KICAgIHZhbGlkX2lkcyA8LSBpZF90YXNrX2NoZWNrICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBuX3Rhc2tzID09IDUsDQogICAgICAgIGFsbF90YXNrc19vaw0KICAgICAgKQ0KICB9IGVsc2Ugew0KICAgIHZhbGlkX2lkcyA8LSBpZF90YXNrX2NoZWNrICU+JQ0KICAgICAgZmlsdGVyKGFsbF90YXNrc19vaykNCiAgfQ0KDQogIGNvbmpvaW50X2FsbCA8LSBjb25qb2ludF9hbGxfdW5maWx0ZXJlZCAlPiUNCiAgICBzZW1pX2pvaW4oDQogICAgICB2YWxpZF9pZHMsDQogICAgICBieSA9IGMoDQogICAgICAgICJJRCIsDQogICAgICAgICJwYXJ0eV9uIg0KICAgICAgKQ0KICAgICkNCg0KICBzYW1wbGVfZmxvdyA8LSBiaW5kX3Jvd3MoDQogICAgc2FtcGxlX2Zsb3csDQogICAgdGliYmxlKA0KICAgICAgc3RhZ2UgPSBpZiAocmVxdWlyZV9hbGxfZml2ZV90YXNrcykgew0KICAgICAgICAiNeiqsumhjOOBmeOBueOBpuOBjOWujOWFqOOBquWbnuetlOiAhSINCiAgICAgIH0gZWxzZSB7DQogICAgICAgICLlm57nrZTmuIjjgb/oqrLpoYzjgYzjgZnjgbnjgablrozlhajjgarlm57nrZTogIUiDQogICAgICB9LA0KICAgICAgbiA9IG5fZGlzdGluY3QoY29uam9pbnRfYWxsJElEKQ0KICAgICkNCiAgKQ0KDQogIG5fYnlfcGFydHkgPC0gdmFsaWRfaWRzICU+JQ0KICAgIGNvdW50KA0KICAgICAgcGFydHlfbiwNCiAgICAgIG5hbWUgPSAibiINCiAgICApICU+JQ0KICAgIGNvbXBsZXRlKA0KICAgICAgcGFydHlfbiA9IDI6NSwNCiAgICAgIGZpbGwgPSBsaXN0KG4gPSAwKQ0KICAgICkgJT4lDQogICAgYXJyYW5nZShwYXJ0eV9uKQ0KDQogIG5fdG90YWwgPC0gdmFsaWRfaWRzICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIG4gPSBuX2Rpc3RpbmN0KElEKQ0KICAgICkgJT4lDQogICAgcHVsbChuKQ0KDQogIGZpZ3VyZV9uX2xhYmVscyA8LSBiaW5kX3Jvd3MoDQogICAgdGliYmxlKA0KICAgICAgcG9zaXRpb24gPSAi5YWo44K144Oz44OX44OrIiwNCiAgICAgIGxhYmVsID0gcGFzdGUwKA0KICAgICAgICAi5YWo44K144Oz44OX44OrLCBuPSIsDQogICAgICAgIHNjYWxlczo6Y29tbWEobl90b3RhbCkNCiAgICAgICkNCiAgICApLA0KDQogICAgbl9ieV9wYXJ0eSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgcG9zaXRpb24gPSBwYXN0ZTAoDQogICAgICAgICAgcGFydHlfbiwNCiAgICAgICAgICAi6YG45oqe6IKiIg0KICAgICAgICApLA0KICAgICAgICBsYWJlbCA9IHBhc3RlMCgNCiAgICAgICAgICAibj0iLA0KICAgICAgICAgIHNjYWxlczo6Y29tbWEobikNCiAgICAgICAgKQ0KICAgICAgKSAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgcG9zaXRpb24sDQogICAgICAgIGxhYmVsDQogICAgICApDQogICkNCg0KICBjYXQoIlxu5YiG5p6Q5a++6LGh6ICF5pWwXG4iKQ0KICBwcmludChuX2J5X3BhcnR5KQ0KICBjYXQoDQogICAgIuWFqOOCteODs+ODl+ODqyBuPSIsDQogICAgbl90b3RhbCwNCiAgICAiXG4iLA0KICAgIHNlcCA9ICIiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHNhbXBsZV9mbG93LA0KICAgICJzYW1wbGVfZmxvdy5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGlkX3Rhc2tfY2hlY2ssDQogICAgImlkX3Rhc2tfY2hlY2suY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICB2YWxpZF9pZHMsDQogICAgInZhbGlkX2lkcy5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIG5fYnlfcGFydHksDQogICAgIm5fYnlfcGFydHkuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBmaWd1cmVfbl9sYWJlbHMsDQogICAgImZpZ3VyZV9uX2xhYmVscy5jc3YiDQogICkNCg0KDQogIGNoZWNrX3Byb2ZpbGUgPC0gY29uam9pbnRfYWxsICU+JQ0KICAgIGdyb3VwX2J5KA0KICAgICAgcGFydHlfbiwNCiAgICAgIElELA0KICAgICAgdGFzaywNCiAgICAgIHRhc2tfaWQNCiAgICApICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIG5fcHJvZmlsZXMgPSBuKCksDQogICAgICBzZWxlY3RlZF9zdW0gPSBzdW0oc2VsZWN0ZWQpLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICkgJT4lDQogICAgY291bnQoDQogICAgICBwYXJ0eV9uLA0KICAgICAgbl9wcm9maWxlcywNCiAgICAgIHNlbGVjdGVkX3N1bQ0KICAgICkNCg0KICBwcmludChjaGVja19wcm9maWxlKQ0KDQogIHN0b3BpZm5vdCgNCiAgICBhbGwoDQogICAgICBjaGVja19wcm9maWxlJG5fcHJvZmlsZXMgPT0NCiAgICAgICAgY2hlY2tfcHJvZmlsZSRwYXJ0eV9uDQogICAgKQ0KICApDQoNCiAgc3RvcGlmbm90KA0KICAgIGFsbCgNCiAgICAgIGNoZWNrX3Byb2ZpbGUkc2VsZWN0ZWRfc3VtID09IDENCiAgICApDQogICkNCg0KICBhbGxvd2VkX2Vjb25vbWljX2RmIDwtIGVuZnJhbWUoDQogICAgYWxsb3dlZF9lY29ub21pY19sZXZlbHMsDQogICAgbmFtZSA9ICJuYW1lIiwNCiAgICB2YWx1ZSA9ICJ2YWx1ZSINCiAgKSAlPiUNCiAgICB1bm5lc3QodmFsdWUpDQoNCiAgdW5leHBlY3RlZF9lY29ub21pY192YWx1ZXMgPC0gY29uam9pbnRfYWxsICU+JQ0KICAgIHNlbGVjdCgNCiAgICAgIGFsbF9vZigNCiAgICAgICAgbmFtZXMoYWxsb3dlZF9lY29ub21pY19sZXZlbHMpDQogICAgICApDQogICAgKSAlPiUNCiAgICBwaXZvdF9sb25nZXIoDQogICAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgICAgbmFtZXNfdG8gPSAibmFtZSIsDQogICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiDQogICAgKSAlPiUNCiAgICBmaWx0ZXIoDQogICAgICAhaXMubmEodmFsdWUpLA0KICAgICAgdmFsdWUgIT0gIiINCiAgICApICU+JQ0KICAgIGRpc3RpbmN0KA0KICAgICAgbmFtZSwNCiAgICAgIHZhbHVlDQogICAgKSAlPiUNCiAgICBhbnRpX2pvaW4oDQogICAgICBhbGxvd2VkX2Vjb25vbWljX2RmLA0KICAgICAgYnkgPSBjKA0KICAgICAgICAibmFtZSIsDQogICAgICAgICJ2YWx1ZSINCiAgICAgICkNCiAgICApDQoNCiAgcHJpbnQodW5leHBlY3RlZF9lY29ub21pY192YWx1ZXMpDQoNCiAgc3RvcGlmbm90KA0KICAgIG5yb3codW5leHBlY3RlZF9lY29ub21pY192YWx1ZXMpID09IDANCiAgKQ0KDQogIG9ic2VydmVkX3BhcnR5X2xldmVscyA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgZGlzdGluY3QocGFydHlfbmFtZSkgJT4lDQogICAgYXJyYW5nZShwYXJ0eV9uYW1lKQ0KDQogIG9ic2VydmVkX2Vjb25vbWljX2xldmVscyA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgc2VsZWN0KA0KICAgICAgYWxsX29mKA0KICAgICAgICBuYW1lcyhhbGxvd2VkX2Vjb25vbWljX2xldmVscykNCiAgICAgICkNCiAgICApICU+JQ0KICAgIHBpdm90X2xvbmdlcigNCiAgICAgIGNvbHMgPSBldmVyeXRoaW5nKCksDQogICAgICBuYW1lc190byA9ICJhdHRyaWJ1dGUiLA0KICAgICAgdmFsdWVzX3RvID0gImxldmVsIg0KICAgICkgJT4lDQogICAgZGlzdGluY3QoDQogICAgICBhdHRyaWJ1dGUsDQogICAgICBsZXZlbA0KICAgICkgJT4lDQogICAgYXJyYW5nZSgNCiAgICAgIGF0dHJpYnV0ZSwNCiAgICAgIGxldmVsDQogICAgKQ0KDQogIHBhcnR5X2xldmVsX2ZyZXF1ZW5jeSA8LSBjb25qb2ludF9hbGwgJT4lDQogICAgY291bnQoDQogICAgICBwYXJ0eV9uLA0KICAgICAgcGFydHlfbmFtZSwNCiAgICAgIG5hbWUgPSAibl9wcm9maWxlcyINCiAgICApICU+JQ0KICAgIGdyb3VwX2J5KHBhcnR5X24pICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHByb3BvcnRpb24gPSBuX3Byb2ZpbGVzIC8NCiAgICAgICAgc3VtKG5fcHJvZmlsZXMpDQogICAgKSAlPiUNCiAgICB1bmdyb3VwKCkNCg0KICBlY29ub21pY19sZXZlbF9mcmVxdWVuY3kgPC0gY29uam9pbnRfYWxsICU+JQ0KICAgIHNlbGVjdCgNCiAgICAgIHBhcnR5X24sDQogICAgICBhbGxfb2YoDQogICAgICAgIG5hbWVzKGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzKQ0KICAgICAgKQ0KICAgICkgJT4lDQogICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgY29scyA9IGFsbF9vZigNCiAgICAgICAgbmFtZXMoYWxsb3dlZF9lY29ub21pY19sZXZlbHMpDQogICAgICApLA0KICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwNCiAgICAgIHZhbHVlc190byA9ICJsZXZlbCINCiAgICApICU+JQ0KICAgIGNvdW50KA0KICAgICAgcGFydHlfbiwNCiAgICAgIGF0dHJpYnV0ZSwNCiAgICAgIGxldmVsLA0KICAgICAgbmFtZSA9ICJuX3Byb2ZpbGVzIg0KICAgICkgJT4lDQogICAgZ3JvdXBfYnkoDQogICAgICBwYXJ0eV9uLA0KICAgICAgYXR0cmlidXRlDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBwcm9wb3J0aW9uID0gbl9wcm9maWxlcyAvDQogICAgICAgIHN1bShuX3Byb2ZpbGVzKQ0KICAgICkgJT4lDQogICAgdW5ncm91cCgpDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBjaGVja19wcm9maWxlLA0KICAgICJwcm9maWxlX2V4cGFuc2lvbl9jaGVjay5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIG9ic2VydmVkX3BhcnR5X2xldmVscywNCiAgICAib2JzZXJ2ZWRfcGFydHlfbGV2ZWxzLmNzdiINCiAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgb2JzZXJ2ZWRfZWNvbm9taWNfbGV2ZWxzLA0KICAgICJvYnNlcnZlZF9lY29ub21pY19sZXZlbHMuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBwYXJ0eV9sZXZlbF9mcmVxdWVuY3ksDQogICAgInBhcnR5X2xldmVsX2ZyZXF1ZW5jeS5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGVjb25vbWljX2xldmVsX2ZyZXF1ZW5jeSwNCiAgICAiZWNvbm9taWNfbGV2ZWxfZnJlcXVlbmN5LmNzdiINCiAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgY29uam9pbnRfYWxsLA0KICAgICJzdHVkeTNfcHJvZmlsZV9sZXZlbF9kYXRhLmNzdiINCiAgKQ0KDQoNCiAgYW5hbHlzaXNfaWRzIDwtIHZhbGlkX2lkcyAlPiUNCiAgICBzZWxlY3QoDQogICAgICBJRCwNCiAgICAgIHBhcnR5X24NCiAgICApDQoNCiAgaWYgKGF0dGVudGlvbl9jaGVja192YXIgJWluJSBuYW1lcyhkZikpIHsNCiAgICBhdHRlbnRpb25fc3VtbWFyeSA8LSBkZiAlPiUNCiAgICAgIHNlbWlfam9pbigNCiAgICAgICAgYW5hbHlzaXNfaWRzLA0KICAgICAgICBieSA9ICJJRCINCiAgICAgICkgJT4lDQogICAgICB0cmFuc211dGUoDQogICAgICAgIElELA0KICAgICAgICBhdHRlbnRpb25fcmVzcG9uc2UgPSBub3JtX3RleHQoDQogICAgICAgICAgLmRhdGFbW2F0dGVudGlvbl9jaGVja192YXJdXQ0KICAgICAgICApLA0KICAgICAgICBhdHRlbnRpb25fcGFzcyA9IGlzX3Jlc3BvbnNlX2NvZGUoDQogICAgICAgICAgLmRhdGFbW2F0dGVudGlvbl9jaGVja192YXJdXSwNCiAgICAgICAgICBhdHRlbnRpb25fY2hlY2tfY29ycmVjdA0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgY291bnQoDQogICAgICAgIGF0dGVudGlvbl9yZXNwb25zZSwNCiAgICAgICAgYXR0ZW50aW9uX3Bhc3MsDQogICAgICAgIG5hbWUgPSAibiINCiAgICAgICkgJT4lDQogICAgICBhcnJhbmdlKA0KICAgICAgICBkZXNjKGF0dGVudGlvbl9wYXNzKSwNCiAgICAgICAgYXR0ZW50aW9uX3Jlc3BvbnNlDQogICAgICApDQogIH0gZWxzZSB7DQogICAgYXR0ZW50aW9uX3N1bW1hcnkgPC0gdGliYmxlKA0KICAgICAgYXR0ZW50aW9uX3Jlc3BvbnNlID0gY2hhcmFjdGVyKCksDQogICAgICBhdHRlbnRpb25fcGFzcyA9IGxvZ2ljYWwoKSwNCiAgICAgIG4gPSBpbnRlZ2VyKCkNCiAgICApDQogIH0NCg0KICBtYW5pcHVsYXRpb25fc3VtbWFyeSA8LSBtYXBfZGZyKA0KICAgIDI6NSwNCiAgICBmdW5jdGlvbihuX3BhcnR5KSB7DQogICAgICBtYW5pcHVsYXRpb25fcm93IDwtIG1hbmlwdWxhdGlvbl9tYXAgJT4lDQogICAgICAgIGZpbHRlcigNCiAgICAgICAgICBwYXJ0eV9uID09IG5fcGFydHkNCiAgICAgICAgKQ0KDQogICAgICB2IDwtIG1hbmlwdWxhdGlvbl9yb3ckbWFuaXB1bGF0aW9uX3Zhcg0KICAgICAgY29ycmVjdCA8LSBtYW5pcHVsYXRpb25fcm93JGNvcnJlY3RfYW5zd2VyDQoNCiAgICAgIGlmICghdiAlaW4lIG5hbWVzKGRmKSkgew0KICAgICAgICByZXR1cm4oDQogICAgICAgICAgdGliYmxlKA0KICAgICAgICAgICAgcGFydHlfbiA9IG5fcGFydHksDQogICAgICAgICAgICByZXNwb25zZSA9IE5BX2NoYXJhY3Rlcl8sDQogICAgICAgICAgICBjb3JyZWN0ID0gTkEsDQogICAgICAgICAgICBuID0gMEwNCiAgICAgICAgICApDQogICAgICAgICkNCiAgICAgIH0NCg0KICAgICAgZGYgJT4lDQogICAgICAgIHNlbWlfam9pbigNCiAgICAgICAgICBhbmFseXNpc19pZHMgJT4lDQogICAgICAgICAgICBmaWx0ZXIoDQogICAgICAgICAgICAgIHBhcnR5X24gPT0gbl9wYXJ0eQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICBieSA9ICJJRCINCiAgICAgICAgKSAlPiUNCiAgICAgICAgdHJhbnNtdXRlKA0KICAgICAgICAgIHBhcnR5X24gPSBuX3BhcnR5LA0KICAgICAgICAgIHJlc3BvbnNlID0gbm9ybV90ZXh0KA0KICAgICAgICAgICAgLmRhdGFbW3ZdXQ0KICAgICAgICAgICksDQogICAgICAgICAgY29ycmVjdCA9IGlzX3Jlc3BvbnNlX2NvZGUoDQogICAgICAgICAgICAuZGF0YVtbdl1dLA0KICAgICAgICAgICAgY29ycmVjdA0KICAgICAgICAgICkNCiAgICAgICAgKSAlPiUNCiAgICAgICAgY291bnQoDQogICAgICAgICAgcGFydHlfbiwNCiAgICAgICAgICByZXNwb25zZSwNCiAgICAgICAgICBjb3JyZWN0LA0KICAgICAgICAgIG5hbWUgPSAibiINCiAgICAgICAgKQ0KICAgIH0NCiAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgYXR0ZW50aW9uX3N1bW1hcnksDQogICAgImF0dGVudGlvbl9jaGVja19zdW1tYXJ5LmNzdiINCiAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgbWFuaXB1bGF0aW9uX3N1bW1hcnksDQogICAgInBhcnR5X251bWJlcl9jaGVja19zdW1tYXJ5LmNzdiINCiAgKQ0KDQoNCiAgb2JzZXJ2ZWRfcGFydHlfdmVjdG9yIDwtIGNvbmpvaW50X2FsbCAlPiUNCiAgICBkaXN0aW5jdChwYXJ0eV9uYW1lKSAlPiUNCiAgICBwdWxsKHBhcnR5X25hbWUpDQoNCiAgcGFydHlfcmVmZXJlbmNlIDwtIGlmICgNCiAgICAi6Ieq55Sx5rCR5Li75YWaIiAlaW4lIG9ic2VydmVkX3BhcnR5X3ZlY3Rvcg0KICApIHsNCiAgICAi6Ieq55Sx5rCR5Li75YWaIg0KICB9IGVsc2Ugew0KICAgIHNvcnQob2JzZXJ2ZWRfcGFydHlfdmVjdG9yKVsxXQ0KICB9DQoNCiAgaWYgKHBhcnR5X3JlZmVyZW5jZSAhPSAi6Ieq55Sx5rCR5Li75YWaIikgew0KICAgIHdhcm5pbmcoIkNoZWNrIikNCiAgfQ0KDQogIHBhcnR5X2xldmVsc191c2UgPC0gYygNCiAgICBwYXJ0eV9yZWZlcmVuY2UsDQoNCiAgICBleHBlY3RlZF9wYXJ0eV9sZXZlbHNbDQogICAgICBleHBlY3RlZF9wYXJ0eV9sZXZlbHMgJWluJQ0KICAgICAgICBvYnNlcnZlZF9wYXJ0eV92ZWN0b3IgJg0KICAgICAgICBleHBlY3RlZF9wYXJ0eV9sZXZlbHMgIT0NCiAgICAgICAgcGFydHlfcmVmZXJlbmNlDQogICAgXSwNCg0KICAgIHNvcnQoDQogICAgICBzZXRkaWZmKA0KICAgICAgICBvYnNlcnZlZF9wYXJ0eV92ZWN0b3IsDQogICAgICAgIGV4cGVjdGVkX3BhcnR5X2xldmVscw0KICAgICAgKQ0KICAgICkNCiAgKSAlPiUNCiAgICB1bmlxdWUoKQ0KDQogIGNvbmpvaW50X2FsbF9tIDwtIGNvbmpvaW50X2FsbCAlPiUNCiAgICBtdXRhdGUoDQogICAgICBzZWxlY3RlZCA9IGFzLmludGVnZXIoc2VsZWN0ZWQpLA0KICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoSUQpLA0KDQogICAgICBwYXJ0eV9uYW1lID0gZmFjdG9yKA0KICAgICAgICBwYXJ0eV9uYW1lLA0KICAgICAgICBsZXZlbHMgPSBwYXJ0eV9sZXZlbHNfdXNlDQogICAgICApLA0KDQogICAgICBnZHBfZ3Jvd3RoID0gZmFjdG9yKA0KICAgICAgICBnZHBfZ3Jvd3RoLA0KICAgICAgICBsZXZlbHMgPSBhbGxvd2VkX2Vjb25vbWljX2xldmVscyRnZHBfZ3Jvd3RoDQogICAgICApLA0KDQogICAgICBuaWtrZWkgPSBmYWN0b3IoDQogICAgICAgIG5pa2tlaSwNCiAgICAgICAgbGV2ZWxzID0gYWxsb3dlZF9lY29ub21pY19sZXZlbHMkbmlra2VpDQogICAgICApLA0KDQogICAgICBjcGkgPSBmYWN0b3IoDQogICAgICAgIGNwaSwNCiAgICAgICAgbGV2ZWxzID0gYWxsb3dlZF9lY29ub21pY19sZXZlbHMkY3BpDQogICAgICApLA0KDQogICAgICB1bmVtcGxveW1lbnQgPSBmYWN0b3IoDQogICAgICAgIHVuZW1wbG95bWVudCwNCiAgICAgICAgbGV2ZWxzID0gYWxsb3dlZF9lY29ub21pY19sZXZlbHMkdW5lbXBsb3ltZW50DQogICAgICApLA0KDQogICAgICBwYXJ0eV9uX2YgPSBmYWN0b3IoDQogICAgICAgIGFzLmNoYXJhY3RlcihwYXJ0eV9uKSwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAiMiIsDQogICAgICAgICAgIjMiLA0KICAgICAgICAgICI0IiwNCiAgICAgICAgICAiNSINCiAgICAgICAgKQ0KICAgICAgKSwNCg0KICAgICAgcGFydHlfbl9jID0gcGFydHlfbiAtIDINCiAgICApDQoNCiAgYXR0cl90ZXJtcyA8LSBjKA0KICAgICJwYXJ0eV9uYW1lIiwNCiAgICAiZ2RwX2dyb3d0aCIsDQogICAgIm5pa2tlaSIsDQogICAgImNwaSIsDQogICAgInVuZW1wbG95bWVudCINCiAgKQ0KDQogIGVjb25vbWljX2F0dHJfdGVybXMgPC0gYygNCiAgICAiZ2RwX2dyb3d0aCIsDQogICAgIm5pa2tlaSIsDQogICAgImNwaSIsDQogICAgInVuZW1wbG95bWVudCINCiAgKQ0KDQoNCiAgZm9ybXVsYV9ub2NvdiA8LSBhcy5mb3JtdWxhKA0KICAgIHBhc3RlKA0KICAgICAgInNlbGVjdGVkIH4iLA0KICAgICAgcGFzdGUoDQogICAgICAgIGF0dHJfdGVybXMsDQogICAgICAgIGNvbGxhcHNlID0gIiArICINCiAgICAgICkNCiAgICApDQogICkNCg0KICBydW5fYW1jZV9ub2NvdiA8LSBmdW5jdGlvbihkYXQpIHsNCiAgICBmZW9scygNCiAgICAgIGZvcm11bGFfbm9jb3YsDQogICAgICBkYXRhID0gZGF0LA0KICAgICAgdmNvdiA9IH4gSUQNCiAgICApDQogIH0NCg0KICBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiA8LSBjb25qb2ludF9hbGxfbSAlPiUNCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQ0KICAgIG1hcChydW5fYW1jZV9ub2NvdikNCg0KICBjYXB0dXJlLm91dHB1dCgNCiAgICBldGFibGUoDQogICAgICBtb2RlbHNfYnlfcGFydHlfbl9ub2Nvdg0KICAgICksDQogICAgZmlsZSA9IGZpbGUucGF0aCgNCiAgICAgIG91dHB1dF9kaXIsDQogICAgICAiYW1jZV9ub2Nvdl9tb2RlbHMudHh0Ig0KICAgICkNCiAgKQ0KDQoNCiAgbV9pbnRlcmFjdGlvbiA8LSBmZW9scygNCiAgICBzZWxlY3RlZCB+DQogICAgICBwYXJ0eV9uX2YgKg0KICAgICAgKA0KICAgICAgICBwYXJ0eV9uYW1lICsNCiAgICAgICAgICBnZHBfZ3Jvd3RoICsNCiAgICAgICAgICBuaWtrZWkgKw0KICAgICAgICAgIGNwaSArDQogICAgICAgICAgdW5lbXBsb3ltZW50DQogICAgICApLA0KICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwNCiAgICB2Y292ID0gfiBJRA0KICApDQoNCiAgY2FwdHVyZS5vdXRwdXQoDQogICAgc3VtbWFyeShtX2ludGVyYWN0aW9uKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJhbWNlX2ludGVyYWN0aW9uX21vZGVsLnR4dCINCiAgICApDQogICkNCg0KDQogIG1fbGluZWFyX3RyZW5kIDwtIGZlb2xzKA0KICAgIHNlbGVjdGVkIH4NCiAgICAgIHBhcnR5X25fYyAqDQogICAgICAoDQogICAgICAgIHBhcnR5X25hbWUgKw0KICAgICAgICAgIGdkcF9ncm93dGggKw0KICAgICAgICAgIG5pa2tlaSArDQogICAgICAgICAgY3BpICsNCiAgICAgICAgICB1bmVtcGxveW1lbnQNCiAgICAgICksDQogICAgZGF0YSA9IGNvbmpvaW50X2FsbF9tLA0KICAgIHZjb3YgPSB+IElEDQogICkNCg0KICBjYXB0dXJlLm91dHB1dCgNCiAgICBzdW1tYXJ5KG1fbGluZWFyX3RyZW5kKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJhbWNlX2xpbmVhcl90cmVuZF9tb2RlbC50eHQiDQogICAgKQ0KICApDQoNCg0KICBwYXJ0eV90ZXJtX2xhYmVscyA8LSB0aWJibGUoDQogICAgdGVybSA9IHBhc3RlMCgNCiAgICAgICJwYXJ0eV9uYW1lIiwNCiAgICAgIHBhcnR5X2xldmVsc191c2VbLTFdDQogICAgKSwNCiAgICBhdHRyaWJ1dGUgPSAi5pS/5qip5LiO5YWa44Gu5pS/5YWa5ZCNIiwNCiAgICBjdWVfdHlwZSA9ICLmlL/lhZrlkI3jga7miYvjgYzjgYvjgooiLA0KICAgIGxhYmVsID0gcGFydHlfbGV2ZWxzX3VzZVstMV0sDQogICAgb3JkZXIgPSBzZXFfYWxvbmcoDQogICAgICBwYXJ0eV9sZXZlbHNfdXNlWy0xXQ0KICAgICkNCiAgKQ0KDQogIGVjb25vbWljX3Rlcm1fbGFiZWxzIDwtIHRyaWJibGUoDQogICAgfnRlcm0sIH5hdHRyaWJ1dGUsIH5jdWVfdHlwZSwgfmxhYmVsLCB+b3JkZXIsDQoNCiAgICAiZ2RwX2dyb3d0aEdEUOaIkOmVt+eOh+ODl+ODqeOCuTHvvIUiLA0KICAgICJHRFDmiJDplbfnjociLA0KICAgICLntYzmuIjjga7miYvjgYzjgYvjgooiLA0KICAgICJHRFDvvJrjg5fjg6njgrkx77yFIiwNCiAgICAxLA0KDQogICAgImdkcF9ncm93dGhHRFDmiJDplbfnjofjg57jgqTjg4rjgrkx77yFIiwNCiAgICAiR0RQ5oiQ6ZW3546HIiwNCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwNCiAgICAiR0RQ77ya44Oe44Kk44OK44K5Me+8hSIsDQogICAgMiwNCg0KICAgICJuaWtrZWnml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg5fjg6njgrkxMDAw5YaGIiwNCiAgICAi5pel57WM5bmz5Z2HIiwNCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwNCiAgICAi5pel57WM5bmz5Z2H77ya44OX44Op44K5MTAwMOWGhiIsDQogICAgMywNCg0KICAgICJuaWtrZWnml6XntYzlubPlnYfliY3mnIjlkIzmnJ/mr5Tjg57jgqTjg4rjgrkxMDAw5YaGIiwNCiAgICAi5pel57WM5bmz5Z2HIiwNCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwNCiAgICAi5pel57WM5bmz5Z2H77ya44Oe44Kk44OK44K5MTAwMOWGhiIsDQogICAgNCwNCg0KICAgICJjcGlDUEnliY3mnJ/mr5Tjg5fjg6njgrkx44Od44Kk44Oz44OIIiwNCiAgICAiQ1BJIiwNCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwNCiAgICAiQ1BJ77ya44OX44Op44K5MeODneOCpOODs+ODiCIsDQogICAgNSwNCg0KICAgICJjcGlDUEnliY3mnJ/mr5Tjg57jgqTjg4rjgrkx44Od44Kk44Oz44OIIiwNCiAgICAiQ1BJIiwNCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwNCiAgICAiQ1BJ77ya44Oe44Kk44OK44K5MeODneOCpOODs+ODiCIsDQogICAgNiwNCg0KICAgICJ1bmVtcGxveW1lbnTlpLHmpa3njofliY3mnJ/mr5Tjg5fjg6njgrkx77yFIiwNCiAgICAi5aSx5qWt546HIiwNCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwNCiAgICAi5aSx5qWt546H77ya44OX44Op44K5Me+8hSIsDQogICAgNywNCg0KICAgICJ1bmVtcGxveW1lbnTlpLHmpa3njofliY3mnJ/mr5Tjg57jgqTjg4rjgrkx77yFIiwNCiAgICAi5aSx5qWt546HIiwNCiAgICAi57WM5riI44Gu5omL44GM44GL44KKIiwNCiAgICAi5aSx5qWt546H77ya44Oe44Kk44OK44K5Me+8hSIsDQogICAgOA0KICApDQoNCiAgdGVybV9sYWJlbHMgPC0gYmluZF9yb3dzKA0KICAgIHBhcnR5X3Rlcm1fbGFiZWxzICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBvcmRlcl9nbG9iYWwgPSBvcmRlcg0KICAgICAgKSwNCg0KICAgIGVjb25vbWljX3Rlcm1fbGFiZWxzICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBvcmRlcl9nbG9iYWwgPQ0KICAgICAgICAgIG1heCgNCiAgICAgICAgICAgIGMoDQogICAgICAgICAgICAgIHBhcnR5X3Rlcm1fbGFiZWxzJG9yZGVyLA0KICAgICAgICAgICAgICAwDQogICAgICAgICAgICApDQogICAgICAgICAgKSArDQogICAgICAgICAgb3JkZXINCiAgICAgICkNCiAgKSAlPiUNCiAgICBzZWxlY3QoDQogICAgICB0ZXJtLA0KICAgICAgYXR0cmlidXRlLA0KICAgICAgY3VlX3R5cGUsDQogICAgICBsYWJlbCwNCiAgICAgIG9yZGVyID0gb3JkZXJfZ2xvYmFsDQogICAgKQ0KDQogIGF0dHJpYnV0ZV9vcmRlciA8LSBjKA0KICAgICLmlL/mqKnkuI7lhZrjga7mlL/lhZrlkI0iLA0KICAgICJHRFDmiJDplbfnjociLA0KICAgICLml6XntYzlubPlnYciLA0KICAgICJDUEkiLA0KICAgICLlpLHmpa3njociDQogICkNCg0KICBsYWJlbF9vcmRlciA8LSB0ZXJtX2xhYmVscyAlPiUNCiAgICBhcnJhbmdlKG9yZGVyKSAlPiUNCiAgICBwdWxsKGxhYmVsKQ0KDQogIG1ha2VfYW1jZV9wbG90X2RmIDwtIGZ1bmN0aW9uKG1vZGVscykgew0KICAgIGltYXBfZGZyKA0KICAgICAgbW9kZWxzLA0KICAgICAgfiB0aWR5X2ZpeGVzdCgueCkgJT4lDQogICAgICAgIG11dGF0ZSgNCiAgICAgICAgICBwYXJ0eV9uID0gYXMuY2hhcmFjdGVyKC55KQ0KICAgICAgICApDQogICAgKSAlPiUNCiAgICAgIGxlZnRfam9pbigNCiAgICAgICAgdGVybV9sYWJlbHMsDQogICAgICAgIGJ5ID0gInRlcm0iDQogICAgICApICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICAhaXMubmEoYXR0cmlidXRlKQ0KICAgICAgKSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwNCiAgICAgICAgY29uZi5oaWdoX3BwID0gY29uZi5oaWdoICogMTAwLA0KDQogICAgICAgIHBhcnR5X24gPSBmYWN0b3IoDQogICAgICAgICAgcGFydHlfbiwNCiAgICAgICAgICBsZXZlbHMgPSBjKA0KICAgICAgICAgICAgIjIiLA0KICAgICAgICAgICAgIjMiLA0KICAgICAgICAgICAgIjQiLA0KICAgICAgICAgICAgIjUiDQogICAgICAgICAgKSwNCiAgICAgICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAgICAgIjLpgbjmip7ogqIiLA0KICAgICAgICAgICAgIjPpgbjmip7ogqIiLA0KICAgICAgICAgICAgIjTpgbjmip7ogqIiLA0KICAgICAgICAgICAgIjXpgbjmip7ogqIiDQogICAgICAgICAgKQ0KICAgICAgICApLA0KDQogICAgICAgIGF0dHJpYnV0ZSA9IGZhY3RvcigNCiAgICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgICAgbGV2ZWxzID0gYXR0cmlidXRlX29yZGVyDQogICAgICAgICksDQoNCiAgICAgICAgbGFiZWwgPSBmYWN0b3IoDQogICAgICAgICAgbGFiZWwsDQogICAgICAgICAgbGV2ZWxzID0gcmV2KA0KICAgICAgICAgICAgbGFiZWxfb3JkZXINCiAgICAgICAgICApDQogICAgICAgICkNCiAgICAgICkNCiAgfQ0KDQogIGFtY2VfcGxvdF9ub2NvdiA8LSBtYWtlX2FtY2VfcGxvdF9kZigNCiAgICBtb2RlbHNfYnlfcGFydHlfbl9ub2Nvdg0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBhbWNlX3Bsb3Rfbm9jb3YsDQogICAgImFtY2Vfbm9jb3ZfY29lZmZpY2llbnRzLmNzdiINCiAgKQ0KDQogIGludGVyYWN0aW9uX3Bsb3RfZGYgPC0gdGlkeV9maXhlc3QoDQogICAgbV9pbnRlcmFjdGlvbg0KICApICU+JQ0KICAgIGZpbHRlcigNCiAgICAgIHN0cl9kZXRlY3QoDQogICAgICAgIHRlcm0sDQogICAgICAgICJwYXJ0eV9uX2ZbMzQ1XSINCiAgICAgICkNCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHBhcnR5X25fY29kZSA9IHN0cl9leHRyYWN0KA0KICAgICAgICB0ZXJtLA0KICAgICAgICAicGFydHlfbl9mWzM0NV0iDQogICAgICApLA0KDQogICAgICBwYXJ0eV9uID0gc3RyX3JlbW92ZSgNCiAgICAgICAgcGFydHlfbl9jb2RlLA0KICAgICAgICAicGFydHlfbl9mIg0KICAgICAgKSwNCg0KICAgICAgYmFzZV90ZXJtID0gdGVybSAlPiUNCiAgICAgICAgc3RyX3JlbW92ZSgNCiAgICAgICAgICAicGFydHlfbl9mWzM0NV06Ig0KICAgICAgICApICU+JQ0KICAgICAgICBzdHJfcmVtb3ZlKA0KICAgICAgICAgICI6cGFydHlfbl9mWzM0NV0iDQogICAgICAgICkNCiAgICApICU+JQ0KICAgIGxlZnRfam9pbigNCiAgICAgIHRlcm1fbGFiZWxzLA0KICAgICAgYnkgPSBjKA0KICAgICAgICAiYmFzZV90ZXJtIiA9ICJ0ZXJtIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgZmlsdGVyKA0KICAgICAgIWlzLm5hKGF0dHJpYnV0ZSkNCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsDQogICAgICBjb25mLmxvd19wcCA9IGNvbmYubG93ICogMTAwLA0KICAgICAgY29uZi5oaWdoX3BwID0gY29uZi5oaWdoICogMTAwLA0KDQogICAgICBwYXJ0eV9uX2xhYmVsID0gZmFjdG9yKA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBsZXZlbHMgPSBjKA0KICAgICAgICAgICIzIiwNCiAgICAgICAgICAiNCIsDQogICAgICAgICAgIjUiDQogICAgICAgICksDQogICAgICAgIGxhYmVscyA9IGMoDQogICAgICAgICAgIjPpgbjmip7ogqIiLA0KICAgICAgICAgICI06YG45oqe6IKiIiwNCiAgICAgICAgICAiNemBuOaKnuiCoiINCiAgICAgICAgKQ0KICAgICAgKSwNCg0KICAgICAgYXR0cmlidXRlID0gZmFjdG9yKA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVscyA9IGF0dHJpYnV0ZV9vcmRlcg0KICAgICAgKSwNCg0KICAgICAgbGFiZWwgPSBmYWN0b3IoDQogICAgICAgIGxhYmVsLA0KICAgICAgICBsZXZlbHMgPSByZXYoDQogICAgICAgICAgbGFiZWxfb3JkZXINCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGludGVyYWN0aW9uX3Bsb3RfZGYsDQogICAgImFtY2VfaW50ZXJhY3Rpb25fY29lZmZpY2llbnRzLmNzdiINCiAgKQ0KDQogIGxpbmVhcl90cmVuZF9wbG90X2RmIDwtIHRpZHlfZml4ZXN0KA0KICAgIG1fbGluZWFyX3RyZW5kDQogICkgJT4lDQogICAgZmlsdGVyKA0KICAgICAgc3RyX2RldGVjdCgNCiAgICAgICAgdGVybSwNCiAgICAgICAgInBhcnR5X25fYzoiDQogICAgICApIHwNCiAgICAgICAgc3RyX2RldGVjdCgNCiAgICAgICAgICB0ZXJtLA0KICAgICAgICAgICI6cGFydHlfbl9jIg0KICAgICAgICApDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBiYXNlX3Rlcm0gPSB0ZXJtICU+JQ0KICAgICAgICBzdHJfcmVtb3ZlKA0KICAgICAgICAgICJwYXJ0eV9uX2M6Ig0KICAgICAgICApICU+JQ0KICAgICAgICBzdHJfcmVtb3ZlKA0KICAgICAgICAgICI6cGFydHlfbl9jIg0KICAgICAgICApDQogICAgKSAlPiUNCiAgICBsZWZ0X2pvaW4oDQogICAgICB0ZXJtX2xhYmVscywNCiAgICAgIGJ5ID0gYygNCiAgICAgICAgImJhc2VfdGVybSIgPSAidGVybSINCiAgICAgICkNCiAgICApICU+JQ0KICAgIGZpbHRlcigNCiAgICAgICFpcy5uYShhdHRyaWJ1dGUpDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBlc3RpbWF0ZV9wcCA9IGVzdGltYXRlICogMTAwLA0KICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwNCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwNCg0KICAgICAgYXR0cmlidXRlID0gZmFjdG9yKA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVscyA9IGF0dHJpYnV0ZV9vcmRlcg0KICAgICAgKSwNCg0KICAgICAgbGFiZWwgPSBmYWN0b3IoDQogICAgICAgIGxhYmVsLA0KICAgICAgICBsZXZlbHMgPSByZXYoDQogICAgICAgICAgbGFiZWxfb3JkZXINCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGxpbmVhcl90cmVuZF9wbG90X2RmLA0KICAgICJhbWNlX2xpbmVhcl90cmVuZF9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCg0KICByZWNvZGVfZmVtYWxlX3N0dWR5MyA8LSBmdW5jdGlvbih4KSB7DQogICAgeF9udW0gPC0gYXNfbnVtKHgpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICB4X251bSA9PSAyIH4gMUwsDQogICAgICB4X251bSA9PSAxIH4gMEwsDQogICAgICBUUlVFIH4gTkFfaW50ZWdlcl8NCiAgICApDQogIH0NCg0KICByZWNvZGVfY29sbGVnZV9ncmFkX3N0dWR5MyA8LSBmdW5jdGlvbih4KSB7DQogICAgeF9udW0gPC0gYXNfbnVtKHgpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICB4X251bSAlaW4lIGMoDQogICAgICAgIDQsDQogICAgICAgIDUNCiAgICAgICkgfiAxTCwNCg0KICAgICAgeF9udW0gJWluJSBjKA0KICAgICAgICAxLA0KICAgICAgICAyLA0KICAgICAgICAzDQogICAgICApIH4gMEwsDQoNCiAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXw0KICAgICkNCiAgfQ0KDQogIHJlY29kZV9zZWxmX2lkZW9sb2d5X3N0dWR5MyA8LSBmdW5jdGlvbih4KSB7DQogICAgeF9udW0gPC0gYXNfbnVtKHgpDQoNCiAgICBjYXNlX3doZW4oDQogICAgICB4X251bSAlaW4lIDE6OCB+IHhfbnVtLA0KICAgICAgeF9udW0gPT0gMTIgfiA5LA0KICAgICAgeF9udW0gPT0gMTMgfiAxMCwNCiAgICAgIHhfbnVtID09IDE0IH4gMTEsDQogICAgICBUUlVFIH4gTkFfcmVhbF8NCiAgICApDQogIH0NCg0KICByZWNvZGVfcGFydHlfc3VwcG9ydF9zdHVkeTMgPC0gZnVuY3Rpb24oeCkgew0KICAgIHhfbnVtIDwtIGFzX251bSh4KQ0KDQogICAgY2FzZV93aGVuKA0KICAgICAgeF9udW0gPT0gMSB+ICLoh6rnlLHmsJHkuLvlhZoiLA0KICAgICAgeF9udW0gPT0gMiB+ICLkuK3pgZPmlLnpnanpgKPlkIgiLA0KICAgICAgeF9udW0gPT0gMyB+ICLnq4vmhrLmsJHkuLvlhZoiLA0KICAgICAgeF9udW0gPT0gNCB+ICLlhazmmI7lhZoiLA0KICAgICAgeF9udW0gPT0gNSB+ICLml6XmnKzntq3mlrDjga7kvJoiLA0KICAgICAgeF9udW0gPT0gNiB+ICLlm73msJHmsJHkuLvlhZoiLA0KICAgICAgeF9udW0gPT0gNyB+ICLjgozjgYTjgo/mlrDpgbjntYQiLA0KICAgICAgeF9udW0gPT0gOCB+ICLml6XmnKzlhbHnlKPlhZoiLA0KICAgICAgeF9udW0gPT0gOSB+ICLlj4LmlL/lhZoiLA0KICAgICAgeF9udW0gPT0gMTAgfiAi5pel5pys5L+d5a6I5YWaIiwNCiAgICAgIHhfbnVtID09IDExIH4gIuekvuS8muawkeS4u+WFmiIsDQogICAgICB4X251bSA9PSAxMiB+ICLjg4Hjg7zjg6Djgb/jgonjgYQiLA0KICAgICAgeF9udW0gPT0gMTMgfiAi44Gd44Gu5LuWIiwNCiAgICAgIHhfbnVtID09IDE0IH4gIuaUr+aMgeaUv+WFmuOBquOBlyIsDQogICAgICB4X251bSA9PSAxNSB+ICLjgo/jgYvjgonjgarjgYQiLA0KICAgICAgeF9udW0gPT0gMTYgfiAi562U44GI44Gf44GP44Gq44GEIiwNCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgKQ0KICB9DQoNCiAgZ2VuZGVyX3JhdyA8LSBnZXRfdmFyKA0KICAgIGRmLA0KICAgIGMoDQogICAgICAiUTIuMSIsDQogICAgICAiUTJfMSINCiAgICApDQogICkNCg0KICBhZ2VfcmF3IDwtIGdldF92YXIoDQogICAgZGYsDQogICAgYygNCiAgICAgICJRMi4yXzEzIiwNCiAgICAgICJRMi4yLjEzIiwNCiAgICAgICJRMl8yXzEzIiwNCiAgICAgICJRMi4yXzIiLA0KICAgICAgIlEyLjIuMiIsDQogICAgICAiUTJfMl8yIg0KICAgICkNCiAgKQ0KDQogIGVkdWNhdGlvbl9yYXcgPC0gZ2V0X3ZhcigNCiAgICBkZiwNCiAgICBjKA0KICAgICAgIlEyLjMiLA0KICAgICAgIlEyXzMiDQogICAgKQ0KICApDQoNCiAgcmVnaW9uX3JhdyA8LSBnZXRfdmFyKA0KICAgIGRmLA0KICAgIGMoDQogICAgICAiUTIuNF8xIiwNCiAgICAgICJRMi40LjEiLA0KICAgICAgIlEyXzRfMSINCiAgICApDQogICkNCg0KICBwcmVmZWN0dXJlX3JhdyA8LSBnZXRfdmFyKA0KICAgIGRmLA0KICAgIGMoDQogICAgICAiUTIuNF8yIiwNCiAgICAgICJRMi40LjIiLA0KICAgICAgIlEyXzRfMiINCiAgICApDQogICkNCg0KICBpbmNvbWVfZ3Jvc3NfcmF3IDwtIGdldF92YXIoDQogICAgZGYsDQogICAgYygNCiAgICAgICJRMi41XzEiLA0KICAgICAgIlEyLjUuMSIsDQogICAgICAiUTJfNV8xIg0KICAgICkNCiAgKQ0KDQogIGluY29tZV9uZXRfcmF3IDwtIGdldF92YXIoDQogICAgZGYsDQogICAgYygNCiAgICAgICJRMi41XzIiLA0KICAgICAgIlEyLjUuMiIsDQogICAgICAiUTJfNV8yIg0KICAgICkNCiAgKQ0KDQogIHplcm9faW5jb21lX3JlYXNvbl9yYXcgPC0gZ2V0X3ZhcigNCiAgICBkZiwNCiAgICBjKA0KICAgICAgIlEyLjYiLA0KICAgICAgIlEyXzYiDQogICAgKQ0KICApDQoNCiAgc2VsZl9pZGVvbG9neV9yYXcgPC0gZ2V0X3ZhcigNCiAgICBkZiwNCiAgICBjKA0KICAgICAgIlEyNS4xXzEiLA0KICAgICAgIlEyNS4xLjEiLA0KICAgICAgIlEyNV8xXzEiDQogICAgKQ0KICApDQoNCiAgcGFydHlfc3VwcG9ydF9yYXcgPC0gZ2V0X3ZhcigNCiAgICBkZiwNCiAgICBjKA0KICAgICAgIlE3LjIiLA0KICAgICAgIlE3XzIiDQogICAgKQ0KICApDQoNCiAgY292YXJfaWQgPC0gZGYgJT4lDQogICAgdHJhbnNtdXRlKA0KICAgICAgSUQgPSBhcy5jaGFyYWN0ZXIoUmVzcG9uc2VJZCksDQoNCiAgICAgIGZlbWFsZSA9IHJlY29kZV9mZW1hbGVfc3R1ZHkzKA0KICAgICAgICBnZW5kZXJfcmF3DQogICAgICApLA0KDQogICAgICBhZ2UgPSBhc19udW0oDQogICAgICAgIGFnZV9yYXcNCiAgICAgICksDQoNCiAgICAgIGNvbGxlZ2VfZ3JhZCA9IHJlY29kZV9jb2xsZWdlX2dyYWRfc3R1ZHkzKA0KICAgICAgICBlZHVjYXRpb25fcmF3DQogICAgICApLA0KDQogICAgICByZWdpb24gPSBmYWN0b3JfbWlzcygNCiAgICAgICAgcmVnaW9uX3Jhdw0KICAgICAgKSwNCg0KICAgICAgcHJlZmVjdHVyZSA9IGZhY3Rvcl9taXNzKA0KICAgICAgICBwcmVmZWN0dXJlX3Jhdw0KICAgICAgKSwNCg0KICAgICAgaW5jb21lX2dyb3NzID0gYXNfbnVtKA0KICAgICAgICBpbmNvbWVfZ3Jvc3NfcmF3DQogICAgICApLA0KDQogICAgICBpbmNvbWVfbmV0ID0gYXNfbnVtKA0KICAgICAgICBpbmNvbWVfbmV0X3Jhdw0KICAgICAgKSwNCg0KICAgICAgaW5jb21lX2dyb3NzX2xvZyA9IGxvZzFwKA0KICAgICAgICBpbmNvbWVfZ3Jvc3MNCiAgICAgICksDQoNCiAgICAgIGluY29tZV9uZXRfbG9nID0gbG9nMXAoDQogICAgICAgIGluY29tZV9uZXQNCiAgICAgICksDQoNCiAgICAgIHplcm9faW5jb21lX3JlYXNvbiA9IGZhY3Rvcl9taXNzKA0KICAgICAgICB6ZXJvX2luY29tZV9yZWFzb25fcmF3DQogICAgICApLA0KDQogICAgICBzZWxmX2lkZW9sb2d5ID0gcmVjb2RlX3NlbGZfaWRlb2xvZ3lfc3R1ZHkzKA0KICAgICAgICBzZWxmX2lkZW9sb2d5X3Jhdw0KICAgICAgKSwNCg0KICAgICAgcGFydHlfc3VwcG9ydCA9IHJlY29kZV9wYXJ0eV9zdXBwb3J0X3N0dWR5MygNCiAgICAgICAgcGFydHlfc3VwcG9ydF9yYXcNCiAgICAgICksDQoNCiAgICAgIHBhcnR5X3N1cHBvcnRfZiA9IGZhY3Rvcl9taXNzKA0KICAgICAgICBwYXJ0eV9zdXBwb3J0DQogICAgICApLA0KDQogICAgICBwYXJ0eV9zdXBwb3J0X3Byb2ZpbGUgPSBjYW5vbmljYWxpemVfcGFydHlfbmFtZSgNCiAgICAgICAgcGFydHlfc3VwcG9ydA0KICAgICAgKQ0KICAgICkgJT4lDQogICAgc2VtaV9qb2luKA0KICAgICAgdmFsaWRfaWRzICU+JQ0KICAgICAgICBzZWxlY3QoSUQpLA0KICAgICAgYnkgPSAiSUQiDQogICAgKSAlPiUNCiAgICBkaXN0aW5jdCgNCiAgICAgIElELA0KICAgICAgLmtlZXBfYWxsID0gVFJVRQ0KICAgICkNCg0KICBjb3Zhcl9pZCA8LSBjb3Zhcl9pZCAlPiUNCiAgICBtdXRhdGUoDQogICAgICBhZ2UgPSBpZl9lbHNlKA0KICAgICAgICBhZ2UgPj0gMTggJg0KICAgICAgICAgIGFnZSA8PSA3OSwNCiAgICAgICAgYWdlLA0KICAgICAgICBOQV9yZWFsXw0KICAgICAgKQ0KICAgICkNCg0KICBhZ2VfaW1wX29iaiA8LSBtZWFuX2ltcHV0ZSgNCiAgICBjb3Zhcl9pZCRhZ2UNCiAgKQ0KDQogIGluY29tZV9ncm9zc19pbXBfb2JqIDwtIG1lYW5faW1wdXRlKA0KICAgIGNvdmFyX2lkJGluY29tZV9ncm9zc19sb2cNCiAgKQ0KDQogIHNlbGZfaWRlb2xvZ3lfaW1wX29iaiA8LSBtZWFuX2ltcHV0ZSgNCiAgICBjb3Zhcl9pZCRzZWxmX2lkZW9sb2d5DQogICkNCg0KICBjb3Zhcl9pZCA8LSBjb3Zhcl9pZCAlPiUNCiAgICBtdXRhdGUoDQogICAgICBmZW1hbGVfaW1wID0gaWZfZWxzZSgNCiAgICAgICAgaXMubmEoZmVtYWxlKSwNCiAgICAgICAgMEwsDQogICAgICAgIGZlbWFsZQ0KICAgICAgKSwNCg0KICAgICAgZmVtYWxlX21pc3MgPSBhcy5pbnRlZ2VyKA0KICAgICAgICBpcy5uYShmZW1hbGUpDQogICAgICApLA0KDQogICAgICBjb2xsZWdlX2dyYWRfaW1wID0gaWZfZWxzZSgNCiAgICAgICAgaXMubmEoY29sbGVnZV9ncmFkKSwNCiAgICAgICAgMEwsDQogICAgICAgIGNvbGxlZ2VfZ3JhZA0KICAgICAgKSwNCg0KICAgICAgY29sbGVnZV9ncmFkX21pc3MgPSBhcy5pbnRlZ2VyKA0KICAgICAgICBpcy5uYShjb2xsZWdlX2dyYWQpDQogICAgICApLA0KDQogICAgICBhZ2VfaW1wID0gYWdlX2ltcF9vYmokdmFsdWUsDQoNCiAgICAgIGFnZV9taXNzID0gYWdlX2ltcF9vYmokbWlzcywNCg0KICAgICAgaW5jb21lX2dyb3NzX2xvZ19pbXAgPQ0KICAgICAgICBpbmNvbWVfZ3Jvc3NfaW1wX29iaiR2YWx1ZSwNCg0KICAgICAgaW5jb21lX2dyb3NzX2xvZ19taXNzID0NCiAgICAgICAgaW5jb21lX2dyb3NzX2ltcF9vYmokbWlzcywNCg0KICAgICAgc2VsZl9pZGVvbG9neV9pbXAgPQ0KICAgICAgICBzZWxmX2lkZW9sb2d5X2ltcF9vYmokdmFsdWUsDQoNCiAgICAgIHNlbGZfaWRlb2xvZ3lfbWlzcyA9DQogICAgICAgIHNlbGZfaWRlb2xvZ3lfaW1wX29iaiRtaXNzDQogICAgKQ0KDQogIGNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnkgPC0gY292YXJfaWQgJT4lDQogICAgc3VtbWFyaXNlKA0KICAgICAgbl9pZHMgPSBuX2Rpc3RpbmN0KElEKSwNCiAgICAgIGZlbWFsZV9taXNzaW5nID0gc3VtKA0KICAgICAgICBpcy5uYShmZW1hbGUpDQogICAgICApLA0KICAgICAgYWdlX21pc3NpbmcgPSBzdW0oDQogICAgICAgIGlzLm5hKGFnZSkNCiAgICAgICksDQogICAgICBjb2xsZWdlX2dyYWRfbWlzc2luZyA9IHN1bSgNCiAgICAgICAgaXMubmEoY29sbGVnZV9ncmFkKQ0KICAgICAgKSwNCiAgICAgIGluY29tZV9ncm9zc19taXNzaW5nID0gc3VtKA0KICAgICAgICBpcy5uYShpbmNvbWVfZ3Jvc3NfbG9nKQ0KICAgICAgKSwNCiAgICAgIHNlbGZfaWRlb2xvZ3lfbWlzc2luZyA9IHN1bSgNCiAgICAgICAgaXMubmEoc2VsZl9pZGVvbG9neSkNCiAgICAgICksDQogICAgICBwYXJ0eV9zdXBwb3J0X21pc3NpbmcgPSBzdW0oDQogICAgICAgIGlzLm5hKHBhcnR5X3N1cHBvcnQpDQogICAgICApDQogICAgKQ0KDQogIHplcm9faW5jb21lX3N1bW1hcnkgPC0gY292YXJfaWQgJT4lDQogICAgY291bnQoDQogICAgICB6ZXJvX2luY29tZV9yZWFzb24sDQogICAgICBuYW1lID0gIm4iDQogICAgKSAlPiUNCiAgICBhcnJhbmdlKA0KICAgICAgZGVzYyhuKQ0KICAgICkNCg0KICBwcmludChjb3ZhcmlhdGVfbWlzc2luZ19zdW1tYXJ5KQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgY292YXJfaWQsDQogICAgInJlc3BvbmRlbnRfY292YXJpYXRlcy5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnksDQogICAgImNvdmFyaWF0ZV9taXNzaW5nX3N1bW1hcnkuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICB6ZXJvX2luY29tZV9zdW1tYXJ5LA0KICAgICJ6ZXJvX2luY29tZV9yZWFzb25fc3VtbWFyeS5jc3YiDQogICkNCg0KDQogIGNvbmpvaW50X2FsbF9jb3YgPC0gY29uam9pbnRfYWxsX20gJT4lDQogICAgbGVmdF9qb2luKA0KICAgICAgY292YXJfaWQsDQogICAgICBieSA9ICJJRCINCiAgICApDQoNCiAgY292YXJpYXRlX3Rlcm1zIDwtIGMoDQogICAgImZlbWFsZV9pbXAiLA0KICAgICJmZW1hbGVfbWlzcyIsDQogICAgImFnZV9pbXAiLA0KICAgICJhZ2VfbWlzcyIsDQogICAgImNvbGxlZ2VfZ3JhZF9pbXAiLA0KICAgICJjb2xsZWdlX2dyYWRfbWlzcyIsDQogICAgImluY29tZV9ncm9zc19sb2dfaW1wIiwNCiAgICAiaW5jb21lX2dyb3NzX2xvZ19taXNzIiwNCiAgICAic2VsZl9pZGVvbG9neV9pbXAiLA0KICAgICJzZWxmX2lkZW9sb2d5X21pc3MiLA0KICAgICJwYXJ0eV9zdXBwb3J0X2YiDQogICkNCg0KICBoYXNfdmFyaWF0aW9uIDwtIGZ1bmN0aW9uKGRhdCwgdikgew0KICAgIGlmICghdiAlaW4lIG5hbWVzKGRhdCkpIHsNCiAgICAgIHJldHVybihGQUxTRSkNCiAgICB9DQoNCiAgICBkcGx5cjo6bl9kaXN0aW5jdCgNCiAgICAgIGRhdFtbdl1dLA0KICAgICAgbmEucm0gPSBUUlVFDQogICAgKSA+IDENCiAgfQ0KDQogIGNvdmFyaWF0ZV90ZXJtc191c2UgPC0gY292YXJpYXRlX3Rlcm1zWw0KICAgIG1hcF9sZ2woDQogICAgICBjb3ZhcmlhdGVfdGVybXMsDQogICAgICB+IGhhc192YXJpYXRpb24oDQogICAgICAgIGNvbmpvaW50X2FsbF9jb3YsDQogICAgICAgIC54DQogICAgICApDQogICAgKQ0KICBdDQoNCiAgZm9ybXVsYV9jb3YgPC0gYXMuZm9ybXVsYSgNCiAgICBwYXN0ZSgNCiAgICAgICJzZWxlY3RlZCB+IiwNCiAgICAgIHBhc3RlKA0KICAgICAgICBjKA0KICAgICAgICAgIGF0dHJfdGVybXMsDQogICAgICAgICAgY292YXJpYXRlX3Rlcm1zX3VzZQ0KICAgICAgICApLA0KICAgICAgICBjb2xsYXBzZSA9ICIgKyAiDQogICAgICApDQogICAgKQ0KICApDQoNCiAgcnVuX2FtY2VfY292IDwtIGZ1bmN0aW9uKGRhdCkgew0KICAgIGZlb2xzKA0KICAgICAgZm9ybXVsYV9jb3YsDQogICAgICBkYXRhID0gZGF0LA0KICAgICAgdmNvdiA9IH4gSUQNCiAgICApDQogIH0NCg0KICBtb2RlbHNfYnlfcGFydHlfbl9jb3YgPC0gY29uam9pbnRfYWxsX2NvdiAlPiUNCiAgICBzcGxpdCguJHBhcnR5X24pICU+JQ0KICAgIG1hcChydW5fYW1jZV9jb3YpDQoNCiAgY2FwdHVyZS5vdXRwdXQoDQogICAgZXRhYmxlKA0KICAgICAgbW9kZWxzX2J5X3BhcnR5X25fbm9jb3YsDQogICAgICBtb2RlbHNfYnlfcGFydHlfbl9jb3YsDQogICAgICBoZWFkZXJzID0gYygNCiAgICAgICAgcmVwKA0KICAgICAgICAgICLlhbHlpInph4/jgarjgZciLA0KICAgICAgICAgIGxlbmd0aCgNCiAgICAgICAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX25vY292DQogICAgICAgICAgKQ0KICAgICAgICApLA0KICAgICAgICByZXAoDQogICAgICAgICAgIuWFseWkiemHj+OBguOCiiIsDQogICAgICAgICAgbGVuZ3RoKA0KICAgICAgICAgICAgbW9kZWxzX2J5X3BhcnR5X25fY292DQogICAgICAgICAgKQ0KICAgICAgICApDQogICAgICApDQogICAgKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJhbWNlX25vY292X2FuZF9jb3ZfbW9kZWxzLnR4dCINCiAgICApDQogICkNCg0KICBhbWNlX3Bsb3RfY292IDwtIG1ha2VfYW1jZV9wbG90X2RmKA0KICAgIG1vZGVsc19ieV9wYXJ0eV9uX2Nvdg0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBhbWNlX3Bsb3RfY292LA0KICAgICJhbWNlX2Nvdl9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCg0KICBzdHVkeV9sYWJlbCA8LSAi5a6f6aiTM++8iDIwMjblubTvvIkiDQoNCiAgcF9hbWNlX2NvdiA8LSBnZ3Bsb3QoDQogICAgYW1jZV9wbG90X2NvdiwNCiAgICBhZXMoDQogICAgICB4ID0gZXN0aW1hdGVfcHAsDQogICAgICB5ID0gbGFiZWwsDQogICAgICBzaGFwZSA9IHBhcnR5X24sDQogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sDQogICAgICBncm91cCA9IHBhcnR5X24NCiAgICApDQogICkgKw0KICAgIGdlb21fdmxpbmUoDQogICAgICB4aW50ZXJjZXB0ID0gMCwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUsDQogICAgICBjb2xvciA9ICJncmV5MzUiDQogICAgKSArDQogICAgZ2VvbV9lcnJvcmJhcmgoDQogICAgICBhZXMoDQogICAgICAgIHhtaW4gPSBjb25mLmxvd19wcCwNCiAgICAgICAgeG1heCA9IGNvbmYuaGlnaF9wcA0KICAgICAgKSwNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoDQogICAgICAgIHdpZHRoID0gMC42NQ0KICAgICAgKSwNCiAgICAgIGhlaWdodCA9IDAuMTYsDQogICAgICBsaW5ld2lkdGggPSAwLjU1LA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9wb2ludCgNCiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoDQogICAgICAgIHdpZHRoID0gMC42NQ0KICAgICAgKSwNCiAgICAgIHNpemUgPSAyLjUsDQogICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICBmaWxsID0gIndoaXRlIiwNCiAgICAgIHN0cm9rZSA9IDAuOA0KICAgICkgKw0KICAgIGZhY2V0X2dyaWQoDQogICAgICBhdHRyaWJ1dGUgfiAuLA0KICAgICAgc2NhbGVzID0gImZyZWVfeSIsDQogICAgICBzcGFjZSA9ICJmcmVlX3kiLA0KICAgICAgc3dpdGNoID0gInkiDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgew0KICAgICAgICBwYXN0ZTAoeCwgIiBwcCIpDQogICAgICB9LA0KICAgICAgYnJlYWtzID0gc2NhbGVzOjpwcmV0dHlfYnJlYWtzKA0KICAgICAgICBuID0gOA0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX3NoYXBlX21hbnVhbCgNCiAgICAgIG5hbWUgPSAi6YG45oqe6IKi5pWwIiwNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICIy6YG45oqe6IKiIiA9IDE2LA0KICAgICAgICAiM+mBuOaKnuiCoiIgPSAxNywNCiAgICAgICAgIjTpgbjmip7ogqIiID0gMTUsDQogICAgICAgICI16YG45oqe6IKiIiA9IDENCiAgICAgICkNCiAgICApICsNCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoDQogICAgICBuYW1lID0gIumBuOaKnuiCouaVsCIsDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiMumBuOaKnuiCoiIgPSAic29saWQiLA0KICAgICAgICAiM+mBuOaKnuiCoiIgPSAiZGFzaGVkIiwNCiAgICAgICAgIjTpgbjmip7ogqIiID0gImRvdHRlZCIsDQogICAgICAgICI16YG45oqe6IKiIiA9ICJkb3RkYXNoIg0KICAgICAgKQ0KICAgICkgKw0KICAgIGxhYnMoDQogICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgNCiAgICAgICAgIuaUv+WFmuWQjeOBruWfuua6luOCq+ODhuOCtOODqu+8miIsDQogICAgICAgIHBhcnR5X3JlZmVyZW5jZSwNCiAgICAgICAgIuOAgue1jOa4iOWxnuaAp+OBr+WkieWMluOBquOBl+OCkuWfuua6luOBqOOBmeOCi+OAgiINCiAgICAgICksDQogICAgICB4ID0gIumBuOaKnueiuueOh+OBruWkieWMliIsDQogICAgICB5ID0gTlVMTA0KICAgICkgKw0KICAgIHRoZW1lX2J3KA0KICAgICAgYmFzZV9zaXplID0gMTIsDQogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQ0KICAgICkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDE2DQogICAgICApLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgc2l6ZSA9IDEwDQogICAgICApLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGZhY2UgPSAiYm9sZCINCiAgICAgICksDQogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiLA0KICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgNCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLA0KICAgICAgICBjb2xvciA9ICJncmV5NTUiDQogICAgICApLA0KICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGFuZ2xlID0gMCwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDEwDQogICAgICApLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQogICAgICAgIHNpemUgPSA5DQogICAgICApLA0KICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBmYWNlID0gImJvbGQiDQogICAgICApDQogICAgKQ0KDQogIHByaW50KHBfYW1jZV9jb3YpDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciLA0KICAgIHBfYW1jZV9jb3YsDQogICAgd2lkdGggPSAxMC41LA0KICAgIGhlaWdodCA9IDExLjUNCiAgKQ0KDQoNCiAgcF9hbWNlX25vY292IDwtIGdncGxvdCgNCiAgICBhbWNlX3Bsb3Rfbm9jb3YsDQogICAgYWVzKA0KICAgICAgeCA9IGVzdGltYXRlX3BwLA0KICAgICAgeSA9IGxhYmVsLA0KICAgICAgc2hhcGUgPSBwYXJ0eV9uLA0KICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uLA0KICAgICAgZ3JvdXAgPSBwYXJ0eV9uDQogICAgKQ0KICApICsNCiAgICBnZW9tX3ZsaW5lKA0KICAgICAgeGludGVyY2VwdCA9IDAsDQogICAgICBsaW5ld2lkdGggPSAwLjQ1LA0KICAgICAgY29sb3IgPSAiZ3JleTM1Ig0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXJoKA0KICAgICAgYWVzKA0KICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsDQogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHANCiAgICAgICksDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKA0KICAgICAgICB3aWR0aCA9IDAuNjUNCiAgICAgICksDQogICAgICBoZWlnaHQgPSAwLjE2LA0KICAgICAgbGluZXdpZHRoID0gMC41NSwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fcG9pbnQoDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKA0KICAgICAgICB3aWR0aCA9IDAuNjUNCiAgICAgICksDQogICAgICBzaXplID0gMi41LA0KICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICBzdHJva2UgPSAwLjgNCiAgICApICsNCiAgICBmYWNldF9ncmlkKA0KICAgICAgYXR0cmlidXRlIH4gLiwNCiAgICAgIHNjYWxlcyA9ICJmcmVlX3kiLA0KICAgICAgc3BhY2UgPSAiZnJlZV95IiwNCiAgICAgIHN3aXRjaCA9ICJ5Ig0KICAgICkgKw0KICAgIHNjYWxlX3hfY29udGludW91cygNCiAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHsNCiAgICAgICAgcGFzdGUwKHgsICIgcHAiKQ0KICAgICAgfSwNCiAgICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcygNCiAgICAgICAgbiA9IDgNCiAgICAgICkNCiAgICApICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgICBuYW1lID0gIumBuOaKnuiCouaVsCIsDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiMumBuOaKnuiCoiIgPSAxNiwNCiAgICAgICAgIjPpgbjmip7ogqIiID0gMTcsDQogICAgICAgICI06YG45oqe6IKiIiA9IDE1LA0KICAgICAgICAiNemBuOaKnuiCoiIgPSAxDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICLpgbjmip7ogqLmlbAiLA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjLpgbjmip7ogqIiID0gInNvbGlkIiwNCiAgICAgICAgIjPpgbjmip7ogqIiID0gImRhc2hlZCIsDQogICAgICAgICI06YG45oqe6IKiIiA9ICJkb3R0ZWQiLA0KICAgICAgICAiNemBuOaKnuiCoiIgPSAiZG90ZGFzaCINCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoDQogICAgICAgICLmlL/lhZrlkI3jga7ln7rmupbjgqvjg4bjgrTjg6rvvJoiLA0KICAgICAgICBwYXJ0eV9yZWZlcmVuY2UsDQogICAgICAgICLjgILntYzmuIjlsZ7mgKfjga/lpInljJbjgarjgZfjgpLln7rmupbjgajjgZnjgovjgIIiDQogICAgICApLA0KICAgICAgeCA9ICLpgbjmip7norrnjofjga7lpInljJYiLA0KICAgICAgeSA9IE5VTEwNCiAgICApICsNCiAgICB0aGVtZV9idygNCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLA0KICAgICAgYmFzZV9mYW1pbHkgPSBmaWd1cmVfZm9udF9mYW1pbHkNCiAgICApICsNCiAgICB0aGVtZSgNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIHNpemUgPSAxNg0KICAgICAgKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIHNpemUgPSAxMA0KICAgICAgKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBmYWNlID0gImJvbGQiDQogICAgICApLA0KICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwNCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGZpbGwgPSAiZ3JleTkyIiwNCiAgICAgICAgY29sb3IgPSAiZ3JleTU1Ig0KICAgICAgKSwNCiAgICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBhbmdsZSA9IDAsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIHNpemUgPSAxMA0KICAgICAgKSwNCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBzaXplID0gOQ0KICAgICAgKSwNCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIg0KICAgICAgKQ0KICAgICkNCg0KICBwcmludChwX2FtY2Vfbm9jb3YpDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX25vY292X2ZhY2V0X21vZGVsLnBuZyIsDQogICAgcF9hbWNlX25vY292LA0KICAgIHdpZHRoID0gMTAuNSwNCiAgICBoZWlnaHQgPSAxMS41DQogICkNCg0KDQogIHBfaW50ZXJhY3Rpb24gPC0gZ2dwbG90KA0KICAgIGludGVyYWN0aW9uX3Bsb3RfZGYsDQogICAgYWVzKA0KICAgICAgeCA9IGVzdGltYXRlX3BwLA0KICAgICAgeSA9IGxhYmVsLA0KICAgICAgc2hhcGUgPSBwYXJ0eV9uX2xhYmVsLA0KICAgICAgbGluZXR5cGUgPSBwYXJ0eV9uX2xhYmVsLA0KICAgICAgZ3JvdXAgPSBwYXJ0eV9uX2xhYmVsDQogICAgKQ0KICApICsNCiAgICBnZW9tX3ZsaW5lKA0KICAgICAgeGludGVyY2VwdCA9IDAsDQogICAgICBsaW5ld2lkdGggPSAwLjQ1LA0KICAgICAgY29sb3IgPSAiZ3JleTM1Ig0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXJoKA0KICAgICAgYWVzKA0KICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsDQogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHANCiAgICAgICksDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKA0KICAgICAgICB3aWR0aCA9IDAuNjUNCiAgICAgICksDQogICAgICBoZWlnaHQgPSAwLjE2LA0KICAgICAgbGluZXdpZHRoID0gMC41NSwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fcG9pbnQoDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKA0KICAgICAgICB3aWR0aCA9IDAuNjUNCiAgICAgICksDQogICAgICBzaXplID0gMi41LA0KICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICBzdHJva2UgPSAwLjgNCiAgICApICsNCiAgICBmYWNldF9ncmlkKA0KICAgICAgYXR0cmlidXRlIH4gLiwNCiAgICAgIHNjYWxlcyA9ICJmcmVlX3kiLA0KICAgICAgc3BhY2UgPSAiZnJlZV95IiwNCiAgICAgIHN3aXRjaCA9ICJ5Ig0KICAgICkgKw0KICAgIHNjYWxlX3hfY29udGludW91cygNCiAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHsNCiAgICAgICAgcGFzdGUwKHgsICIgcHAiKQ0KICAgICAgfSwNCiAgICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcygNCiAgICAgICAgbiA9IDgNCiAgICAgICkNCiAgICApICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgICBuYW1lID0gIjLpgbjmip7ogqLmnaHku7bjgajjga7mr5TovIMiLA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjPpgbjmip7ogqIiID0gMTcsDQogICAgICAgICI06YG45oqe6IKiIiA9IDE1LA0KICAgICAgICAiNemBuOaKnuiCoiIgPSAxDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgbmFtZSA9ICIy6YG45oqe6IKi5p2h5Lu244Go44Gu5q+U6LyDIiwNCiAgICAgIHZhbHVlcyA9IGMoDQogICAgICAgICIz6YG45oqe6IKiIiA9ICJkYXNoZWQiLA0KICAgICAgICAiNOmBuOaKnuiCoiIgPSAiZG90dGVkIiwNCiAgICAgICAgIjXpgbjmip7ogqIiID0gImRvdGRhc2giDQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHggPSAiMumBuOaKnuiCouadoeS7tuOBqOOBruW3riIsDQogICAgICB5ID0gTlVMTA0KICAgICkgKw0KICAgIHRoZW1lX2J3KA0KICAgICAgYmFzZV9zaXplID0gMTIsDQogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQ0KICAgICkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDE1DQogICAgICApLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGZhY2UgPSAiYm9sZCINCiAgICAgICksDQogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgc3RyaXAucGxhY2VtZW50ID0gIm91dHNpZGUiLA0KICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgNCiAgICAgICAgZmlsbCA9ICJncmV5OTIiLA0KICAgICAgICBjb2xvciA9ICJncmV5NTUiDQogICAgICApLA0KICAgICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGFuZ2xlID0gMCwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDEwDQogICAgICApLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQogICAgICAgIHNpemUgPSA5DQogICAgICApLA0KICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBmYWNlID0gImJvbGQiDQogICAgICApDQogICAgKQ0KDQogIHByaW50KHBfaW50ZXJhY3Rpb24pDQoNCiAgc2F2ZV9wbG90KA0KICAgICJhbWNlX2ludGVyYWN0aW9uX2RpZmZlcmVuY2VfZnJvbV8yY2hvaWNlLnBuZyIsDQogICAgcF9pbnRlcmFjdGlvbiwNCiAgICB3aWR0aCA9IDEwLjUsDQogICAgaGVpZ2h0ID0gMTEuNQ0KICApDQoNCg0KICBwX2xpbmVhcl90cmVuZCA8LSBnZ3Bsb3QoDQogICAgbGluZWFyX3RyZW5kX3Bsb3RfZGYsDQogICAgYWVzKA0KICAgICAgeCA9IGVzdGltYXRlX3BwLA0KICAgICAgeSA9IGxhYmVsDQogICAgKQ0KICApICsNCiAgICBnZW9tX3ZsaW5lKA0KICAgICAgeGludGVyY2VwdCA9IDAsDQogICAgICBsaW5ld2lkdGggPSAwLjQ1LA0KICAgICAgY29sb3IgPSAiZ3JleTM1Ig0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXJoKA0KICAgICAgYWVzKA0KICAgICAgICB4bWluID0gY29uZi5sb3dfcHAsDQogICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHANCiAgICAgICksDQogICAgICBoZWlnaHQgPSAwLjE2LA0KICAgICAgbGluZXdpZHRoID0gMC41NSwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fcG9pbnQoDQogICAgICBzaXplID0gMi41LA0KICAgICAgc2hhcGUgPSAyMSwNCiAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgc3Ryb2tlID0gMC44DQogICAgKSArDQogICAgZmFjZXRfZ3JpZCgNCiAgICAgIGF0dHJpYnV0ZSB+IC4sDQogICAgICBzY2FsZXMgPSAiZnJlZV95IiwNCiAgICAgIHNwYWNlID0gImZyZWVfeSIsDQogICAgICBzd2l0Y2ggPSAieSINCiAgICApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSB7DQogICAgICAgIHBhc3RlMCh4LCAiIHBwIikNCiAgICAgIH0sDQogICAgICBicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MoDQogICAgICAgIG4gPSA4DQogICAgICApDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHN1YnRpdGxlID0gIuaoqui7uOOBr+OAgemBuOaKnuiCouaVsOOBjDHjgaTlopfjgYjjgZ/jgajjgY3jga7lsZ7mgKflirnmnpzjga7lpInljJYiLA0KICAgICAgeCA9ICIx6YG45oqe6IKi5aKX5Yqg5b2T44Gf44KK44GuQU1DReWkieWMliIsDQogICAgICB5ID0gTlVMTA0KICAgICkgKw0KICAgIHRoZW1lX2J3KA0KICAgICAgYmFzZV9zaXplID0gMTIsDQogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQ0KICAgICkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgc2l6ZSA9IDE1DQogICAgICApLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgc2l6ZSA9IDEwDQogICAgICApLA0KICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwNCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGZpbGwgPSAiZ3JleTkyIiwNCiAgICAgICAgY29sb3IgPSAiZ3JleTU1Ig0KICAgICAgKSwNCiAgICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBhbmdsZSA9IDAsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIHNpemUgPSAxMA0KICAgICAgKSwNCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBzaXplID0gOQ0KICAgICAgKSwNCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIg0KICAgICAgKQ0KICAgICkNCg0KICBwcmludChwX2xpbmVhcl90cmVuZCkNCg0KICBzYXZlX3Bsb3QoDQogICAgImFtY2VfbGluZWFyX3RyZW5kLnBuZyIsDQogICAgcF9saW5lYXJfdHJlbmQsDQogICAgd2lkdGggPSAxMC41LA0KICAgIGhlaWdodCA9IDExLjUNCiAgKQ0KDQoNCiAgaGVhdG1hcF9kZiA8LSBhbWNlX3Bsb3RfY292ICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIGFic19hbWNlID0gYWJzKA0KICAgICAgICBlc3RpbWF0ZV9wcA0KICAgICAgKQ0KICAgICkgJT4lDQogICAgZ3JvdXBfYnkocGFydHlfbikgJT4lDQogICAgbXV0YXRlKA0KICAgICAgcmFua193aXRoaW5fY29uZGl0aW9uID0NCiAgICAgICAgbWluX3JhbmsoDQogICAgICAgICAgZGVzYyhhYnNfYW1jZSkNCiAgICAgICAgKSwNCg0KICAgICAgbl9pbl9jb25kaXRpb24gPSBuKCksDQoNCiAgICAgIHJhbmtfc2NvcmUgPSBpZl9lbHNlKA0KICAgICAgICBuX2luX2NvbmRpdGlvbiA9PSAxLA0KICAgICAgICAxLA0KICAgICAgICAxIC0NCiAgICAgICAgICAoDQogICAgICAgICAgICByYW5rX3dpdGhpbl9jb25kaXRpb24gLSAxDQogICAgICAgICAgKSAvDQogICAgICAgICAgKA0KICAgICAgICAgICAgbl9pbl9jb25kaXRpb24gLSAxDQogICAgICAgICAgKQ0KICAgICAgKQ0KICAgICkgJT4lDQogICAgdW5ncm91cCgpDQoNCiAgaGVhdG1hcF9yb3dfb3JkZXIgPC0gaGVhdG1hcF9kZiAlPiUNCiAgICBncm91cF9ieSgNCiAgICAgIGxhYmVsLA0KICAgICAgYXR0cmlidXRlDQogICAgKSAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBtZWFuX2Fic19hbWNlID0gbWVhbigNCiAgICAgICAgYWJzX2FtY2UsDQogICAgICAgIG5hLnJtID0gVFJVRQ0KICAgICAgKSwNCiAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICApICU+JQ0KICAgIGFycmFuZ2UoDQogICAgICBkZXNjKG1lYW5fYWJzX2FtY2UpDQogICAgKSAlPiUNCiAgICBwdWxsKGxhYmVsKSAlPiUNCiAgICBhcy5jaGFyYWN0ZXIoKQ0KDQogIGhlYXRtYXBfZGYgPC0gaGVhdG1hcF9kZiAlPiUNCiAgICBtdXRhdGUoDQogICAgICBsYWJlbF9oZWF0ID0gZmFjdG9yKA0KICAgICAgICBhcy5jaGFyYWN0ZXIobGFiZWwpLA0KICAgICAgICBsZXZlbHMgPSByZXYoDQogICAgICAgICAgaGVhdG1hcF9yb3dfb3JkZXINCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkNCg0KICBwX2hlYXRfYW1jZSA8LSBnZ3Bsb3QoDQogICAgaGVhdG1hcF9kZiwNCiAgICBhZXMoDQogICAgICB4ID0gcGFydHlfbiwNCiAgICAgIHkgPSBsYWJlbF9oZWF0LA0KICAgICAgZmlsbCA9IGFic19hbWNlDQogICAgKQ0KICApICsNCiAgICBnZW9tX3RpbGUoDQogICAgICBjb2xvciA9ICJncmV5NDUiLA0KICAgICAgbGluZXdpZHRoID0gMC4zDQogICAgKSArDQogICAgZ2VvbV90ZXh0KA0KICAgICAgYWVzKA0KICAgICAgICBsYWJlbCA9IHNwcmludGYoDQogICAgICAgICAgIiUuMWYiLA0KICAgICAgICAgIGVzdGltYXRlX3BwDQogICAgICAgICksDQogICAgICAgIGNvbG9yID0gaWZfZWxzZSgNCiAgICAgICAgICByYW5rX3Njb3JlID49IDAuNTUsDQogICAgICAgICAgIndoaXRlIiwNCiAgICAgICAgICAiYmxhY2siDQogICAgICAgICkNCiAgICAgICksDQogICAgICBzaXplID0gMy4xDQogICAgKSArDQogICAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArDQogICAgZmFjZXRfZ3JpZCgNCiAgICAgIGF0dHJpYnV0ZSB+IC4sDQogICAgICBzY2FsZXMgPSAiZnJlZV95IiwNCiAgICAgIHNwYWNlID0gImZyZWVfeSIsDQogICAgICBzd2l0Y2ggPSAieSINCiAgICApICsNCiAgICBzY2FsZV9maWxsX2dyYWRpZW50KA0KICAgICAgbG93ID0gIndoaXRlIiwNCiAgICAgIGhpZ2ggPSAiZ3JleTIwIiwNCiAgICAgIG5hbWUgPSAifEFNQ0V8XG4ocHApIg0KICAgICkgKw0KICAgIGxhYnMoDQogICAgICBzdWJ0aXRsZSA9ICLjgrvjg6vlhoXjga7mlbDlgKTjga/nrKblj7fku5jjgY1BTUNF77yIcGVyY2VudGFnZSBwb2ludHPvvIkiLA0KICAgICAgeCA9ICLpgbjmip7ogqLmlbAiLA0KICAgICAgeSA9IE5VTEwNCiAgICApICsNCiAgICB0aGVtZV9idygNCiAgICAgIGJhc2Vfc2l6ZSA9IDEyLA0KICAgICAgYmFzZV9mYW1pbHkgPSBmaWd1cmVfZm9udF9mYW1pbHkNCiAgICApICsNCiAgICB0aGVtZSgNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIGZhY2UgPSAiYm9sZCINCiAgICAgICksDQogICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLA0KICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwNCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGZpbGwgPSAiZ3JleTkyIiwNCiAgICAgICAgY29sb3IgPSAiZ3JleTU1Ig0KICAgICAgKSwNCiAgICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBhbmdsZSA9IDAsDQogICAgICAgIGZhY2UgPSAiYm9sZCINCiAgICAgICksDQogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgc2l6ZSA9IDguNQ0KICAgICAgKQ0KICAgICkNCg0KICBwcmludChwX2hlYXRfYW1jZSkNCg0KICBzYXZlX3Bsb3QoDQogICAgImFtY2VfY292X2hlYXRtYXAucG5nIiwNCiAgICBwX2hlYXRfYW1jZSwNCiAgICB3aWR0aCA9IDEwLjUsDQogICAgaGVpZ2h0ID0gMTEuNQ0KICApDQoNCg0KICBjb25qb2ludF9jbG9naXQgPC0gY29uam9pbnRfYWxsX20gJT4lDQogICAgbXV0YXRlKA0KICAgICAgc2VsZWN0ZWQgPSBhcy5pbnRlZ2VyKHNlbGVjdGVkKSwNCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwNCiAgICAgIHRhc2tfaWQgPSBmYWN0b3IodGFza19pZCksDQoNCiAgICAgIHBhcnR5X25hbWUgPSByZWxldmVsX2lmX3ByZXNlbnQoDQogICAgICAgIHBhcnR5X25hbWUsDQogICAgICAgIHBhcnR5X3JlZmVyZW5jZQ0KICAgICAgKSwNCg0KICAgICAgZ2RwX2dyb3d0aCA9IHJlbGV2ZWxfaWZfcHJlc2VudCgNCiAgICAgICAgZ2RwX2dyb3d0aCwNCiAgICAgICAgYWxsb3dlZF9lY29ub21pY19sZXZlbHMkZ2RwX2dyb3d0aFsxXQ0KICAgICAgKSwNCg0KICAgICAgbmlra2VpID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBuaWtrZWksDQogICAgICAgIGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzJG5pa2tlaVsxXQ0KICAgICAgKSwNCg0KICAgICAgY3BpID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICBjcGksDQogICAgICAgIGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzJGNwaVsxXQ0KICAgICAgKSwNCg0KICAgICAgdW5lbXBsb3ltZW50ID0gcmVsZXZlbF9pZl9wcmVzZW50KA0KICAgICAgICB1bmVtcGxveW1lbnQsDQogICAgICAgIGFsbG93ZWRfZWNvbm9taWNfbGV2ZWxzJHVuZW1wbG95bWVudFsxXQ0KICAgICAgKQ0KICAgICkNCg0KICBmb3JtdWxhX2Nsb2dpdF9ub2NvdiA8LSBhcy5mb3JtdWxhKA0KICAgIHBhc3RlMCgNCiAgICAgICJzZWxlY3RlZCB+ICIsDQogICAgICBwYXN0ZSgNCiAgICAgICAgYXR0cl90ZXJtcywNCiAgICAgICAgY29sbGFwc2UgPSAiICsgIg0KICAgICAgKSwNCiAgICAgICIgKyBzdHJhdGEodGFza19pZCkgKyBjbHVzdGVyKElEKSINCiAgICApDQogICkNCg0KICBydW5fY2xvZ2l0X25vY292IDwtIGZ1bmN0aW9uKGRhdCkgew0KICAgIHN1cnZpdmFsOjpjbG9naXQoDQogICAgICBmb3JtdWxhX2Nsb2dpdF9ub2NvdiwNCiAgICAgIGRhdGEgPSBkYXQsDQogICAgICBtZXRob2QgPSAiZWZyb24iDQogICAgKQ0KICB9DQoNCiAgbW9kZWxzX2Nsb2dpdF9ub2NvdiA8LSBjb25qb2ludF9jbG9naXQgJT4lDQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUNCiAgICBtYXAocnVuX2Nsb2dpdF9ub2NvdikNCg0KICBjYXB0dXJlLm91dHB1dCgNCiAgICBsYXBwbHkoDQogICAgICBtb2RlbHNfY2xvZ2l0X25vY292LA0KICAgICAgc3VtbWFyeQ0KICAgICksDQogICAgZmlsZSA9IGZpbGUucGF0aCgNCiAgICAgIG91dHB1dF9kaXIsDQogICAgICAiY29uZGl0aW9uYWxfbG9naXRfbW9kZWxzLnR4dCINCiAgICApDQogICkNCg0KICB0aWR5X2Nsb2dpdCA8LSBmdW5jdGlvbihtb2RlbCkgew0KICAgIHMgPC0gc3VtbWFyeShtb2RlbCkNCiAgICBjdCA8LSBhcy5kYXRhLmZyYW1lKA0KICAgICAgcyRjb2VmZmljaWVudHMNCiAgICApDQogICAgY3QkdGVybSA8LSByb3duYW1lcyhjdCkNCg0KICAgIHNlX2NvbCA8LSBpZiAoDQogICAgICAicm9idXN0IHNlIiAlaW4lIG5hbWVzKGN0KQ0KICAgICkgew0KICAgICAgInJvYnVzdCBzZSINCiAgICB9IGVsc2UgaWYgKA0KICAgICAgInNlKGNvZWYpIiAlaW4lIG5hbWVzKGN0KQ0KICAgICkgew0KICAgICAgInNlKGNvZWYpIg0KICAgIH0gZWxzZSB7DQogICAgICBzdG9wKCJDaGVjayBjbG9naXQiKQ0KICAgIH0NCg0KICAgIHBfY29sIDwtIGlmICgNCiAgICAgICJQcig+fHp8KSIgJWluJSBuYW1lcyhjdCkNCiAgICApIHsNCiAgICAgICJQcig+fHp8KSINCiAgICB9IGVsc2UgaWYgKA0KICAgICAgIlByKD58dHwpIiAlaW4lIG5hbWVzKGN0KQ0KICAgICkgew0KICAgICAgIlByKD58dHwpIg0KICAgIH0gZWxzZSB7DQogICAgICBOQV9jaGFyYWN0ZXJfDQogICAgfQ0KDQogICAgY3QgJT4lDQogICAgICBhc190aWJibGUoKSAlPiUNCiAgICAgIHRyYW5zbXV0ZSgNCiAgICAgICAgdGVybSA9IHRlcm0sDQogICAgICAgIGVzdGltYXRlID0gY29lZiwNCiAgICAgICAgc3RkLmVycm9yID0gLmRhdGFbW3NlX2NvbF1dLA0KDQogICAgICAgIHAudmFsdWUgPSBpZiAoDQogICAgICAgICAgIWlzLm5hKHBfY29sKQ0KICAgICAgICApIHsNCiAgICAgICAgICAuZGF0YVtbcF9jb2xdXQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIE5BX3JlYWxfDQogICAgICAgIH0sDQoNCiAgICAgICAgY29uZi5sb3cgPQ0KICAgICAgICAgIGVzdGltYXRlIC0NCiAgICAgICAgICAxLjk2ICoNCiAgICAgICAgICBzdGQuZXJyb3IsDQoNCiAgICAgICAgY29uZi5oaWdoID0NCiAgICAgICAgICBlc3RpbWF0ZSArDQogICAgICAgICAgMS45NiAqDQogICAgICAgICAgc3RkLmVycm9yLA0KDQogICAgICAgIG9kZHNfcmF0aW8gPSBleHAoDQogICAgICAgICAgZXN0aW1hdGUNCiAgICAgICAgKSwNCg0KICAgICAgICBvZGRzX3JhdGlvX2xvdyA9IGV4cCgNCiAgICAgICAgICBjb25mLmxvdw0KICAgICAgICApLA0KDQogICAgICAgIG9kZHNfcmF0aW9faGlnaCA9IGV4cCgNCiAgICAgICAgICBjb25mLmhpZ2gNCiAgICAgICAgKQ0KICAgICAgKQ0KICB9DQoNCiAgY2xvZ2l0X3Bsb3RfZGYgPC0gaW1hcF9kZnIoDQogICAgbW9kZWxzX2Nsb2dpdF9ub2NvdiwNCiAgICB+IHRpZHlfY2xvZ2l0KC54KSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgcGFydHlfbiA9IGFzLmNoYXJhY3RlcigueSkNCiAgICAgICkNCiAgKSAlPiUNCiAgICBsZWZ0X2pvaW4oDQogICAgICB0ZXJtX2xhYmVscywNCiAgICAgIGJ5ID0gInRlcm0iDQogICAgKSAlPiUNCiAgICBmaWx0ZXIoDQogICAgICAhaXMubmEoYXR0cmlidXRlKQ0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgcGFydHlfbiA9IGZhY3RvcigNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAiMiIsDQogICAgICAgICAgIjMiLA0KICAgICAgICAgICI0IiwNCiAgICAgICAgICAiNSINCiAgICAgICAgKSwNCiAgICAgICAgbGFiZWxzID0gYygNCiAgICAgICAgICAiMumBuOaKnuiCoiIsDQogICAgICAgICAgIjPpgbjmip7ogqIiLA0KICAgICAgICAgICI06YG45oqe6IKiIiwNCiAgICAgICAgICAiNemBuOaKnuiCoiINCiAgICAgICAgKQ0KICAgICAgKSwNCg0KICAgICAgYXR0cmlidXRlID0gZmFjdG9yKA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVscyA9IGF0dHJpYnV0ZV9vcmRlcg0KICAgICAgKSwNCg0KICAgICAgbGFiZWwgPSBmYWN0b3IoDQogICAgICAgIGxhYmVsLA0KICAgICAgICBsZXZlbHMgPSByZXYoDQogICAgICAgICAgbGFiZWxfb3JkZXINCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIGNsb2dpdF9wbG90X2RmLA0KICAgICJjb25kaXRpb25hbF9sb2dpdF9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCg0KICBwX2Nsb2dpdF9vciA8LSBnZ3Bsb3QoDQogICAgY2xvZ2l0X3Bsb3RfZGYsDQogICAgYWVzKA0KICAgICAgeCA9IG9kZHNfcmF0aW8sDQogICAgICB5ID0gbGFiZWwsDQogICAgICBzaGFwZSA9IHBhcnR5X24sDQogICAgICBsaW5ldHlwZSA9IHBhcnR5X24sDQogICAgICBncm91cCA9IHBhcnR5X24NCiAgICApDQogICkgKw0KICAgIGdlb21fdmxpbmUoDQogICAgICB4aW50ZXJjZXB0ID0gMSwNCiAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIsDQogICAgICBsaW5ld2lkdGggPSAwLjQ1LA0KICAgICAgY29sb3IgPSAiZ3JleTM1Ig0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXJoKA0KICAgICAgYWVzKA0KICAgICAgICB4bWluID0gb2Rkc19yYXRpb19sb3csDQogICAgICAgIHhtYXggPSBvZGRzX3JhdGlvX2hpZ2gNCiAgICAgICksDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKA0KICAgICAgICB3aWR0aCA9IDAuNzINCiAgICAgICksDQogICAgICBoZWlnaHQgPSAwLjE1LA0KICAgICAgbGluZXdpZHRoID0gMC40NSwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fcG9pbnQoDQogICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKA0KICAgICAgICB3aWR0aCA9IDAuNzINCiAgICAgICksDQogICAgICBzaXplID0gMi40LA0KICAgICAgc3Ryb2tlID0gMC43LA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgc2NhbGVfeF9sb2cxMCgNCiAgICAgIGJyZWFrcyA9IHNjYWxlczo6bG9nX2JyZWFrcygNCiAgICAgICAgbiA9IDgNCiAgICAgICkNCiAgICApICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgICB2YWx1ZXMgPSBjKA0KICAgICAgICAiMumBuOaKnuiCoiIgPSAxNiwNCiAgICAgICAgIjPpgbjmip7ogqIiID0gMTcsDQogICAgICAgICI06YG45oqe6IKiIiA9IDE1LA0KICAgICAgICAiNemBuOaKnuiCoiIgPSAxDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIjLpgbjmip7ogqIiID0gInNvbGlkIiwNCiAgICAgICAgIjPpgbjmip7ogqIiID0gImRhc2hlZCIsDQogICAgICAgICI06YG45oqe6IKiIiA9ICJkb3RkYXNoIiwNCiAgICAgICAgIjXpgbjmip7ogqIiID0gInR3b2Rhc2giDQogICAgICApDQogICAgKSArDQogICAgZmFjZXRfZ3JpZCgNCiAgICAgIGF0dHJpYnV0ZSB+IC4sDQogICAgICBzY2FsZXMgPSAiZnJlZV95IiwNCiAgICAgIHNwYWNlID0gImZyZWVfeSIsDQogICAgICBzd2l0Y2ggPSAieSINCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgeCA9ICLjgqrjg4Pjgrrmr5QiLA0KICAgICAgeSA9IE5VTEwsDQogICAgICBzaGFwZSA9ICLpgbjmip7ogqLmlbAiLA0KICAgICAgbGluZXR5cGUgPSAi6YG45oqe6IKi5pWwIg0KICAgICkgKw0KICAgIHRoZW1lX2J3KA0KICAgICAgYmFzZV9zaXplID0gMTIsDQogICAgICBiYXNlX2ZhbWlseSA9IGZpZ3VyZV9mb250X2ZhbWlseQ0KICAgICkgKw0KICAgIHRoZW1lKA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIg0KICAgICAgKSwNCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwNCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGZpbGwgPSAiZ3JleTkyIiwNCiAgICAgICAgY29sb3IgPSAiZ3JleTU1Ig0KICAgICAgKSwNCiAgICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KA0KICAgICAgICBhbmdsZSA9IDAsDQogICAgICAgIGZhY2UgPSAiYm9sZCINCiAgICAgICksDQogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgc2l6ZSA9IDguNQ0KICAgICAgKQ0KICAgICkNCg0KICBwcmludChwX2Nsb2dpdF9vcikNCg0KICBzYXZlX3Bsb3QoDQogICAgImNsb2dpdF9vZGRzcmF0aW9fbm9jb3YucG5nIiwNCiAgICBwX2Nsb2dpdF9vciwNCiAgICB3aWR0aCA9IDEwLjUsDQogICAgaGVpZ2h0ID0gMTEuNQ0KICApDQoNCg0KICBleHBlcmltZW50YWxfcGFydHlfbmFtZXMgPC0gYXMuY2hhcmFjdGVyKA0KICAgIHBhcnR5X2xldmVsc191c2UNCiAgKQ0KDQogIGNvbmpvaW50X21hdGNoIDwtIGNvbmpvaW50X2FsbF9jb3YgJT4lDQogICAgbXV0YXRlKA0KICAgICAgcGFydHlfbmFtZV9jaHIgPSBhcy5jaGFyYWN0ZXIocGFydHlfbmFtZSksDQogICAgICANCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgPSBpZl9lbHNlKA0KICAgICAgICBwYXJ0eV9zdXBwb3J0X3Byb2ZpbGUgJWluJSBleHBlcmltZW50YWxfcGFydHlfbmFtZXMsDQogICAgICAgIHBhcnR5X3N1cHBvcnRfcHJvZmlsZSwNCiAgICAgICAgTkFfY2hhcmFjdGVyXw0KICAgICAgKSwNCiAgICAgIA0KICAgICAgcGFydHlfbWF0Y2ggPSBjYXNlX3doZW4oDQogICAgICAgIGlzLm5hKHN1cHBvcnRfcGFydHlfdmFsaWQpIH4gTkFfaW50ZWdlcl8sDQogICAgICAgIHBhcnR5X25hbWVfY2hyID09IHN1cHBvcnRfcGFydHlfdmFsaWQgfiAxTCwNCiAgICAgICAgVFJVRSB+IDBMDQogICAgICApDQogICAgKSAlPiUNCiAgICBmaWx0ZXIoDQogICAgICAhaXMubmEocGFydHlfbWF0Y2gpDQogICAgKQ0KDQogIHBhcnR5X21hdGNoX3NhbXBsZSA8LSBjb25qb2ludF9tYXRjaCAlPiUNCiAgICBkaXN0aW5jdCgNCiAgICAgIElELA0KICAgICAgcGFydHlfbiwNCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQNCiAgICApICU+JQ0KICAgIGNvdW50KA0KICAgICAgcGFydHlfbiwNCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQsDQogICAgICBuYW1lID0gIm5fcmVzcG9uZGVudHMiDQogICAgKQ0KDQogIHdyaXRlX2Nzdl9zYWZlbHkoDQogICAgcGFydHlfbWF0Y2hfc2FtcGxlLA0KICAgICJwYXJ0eV9tYXRjaF9zYW1wbGUuY3N2Ig0KICApDQoNCg0KICBmb3JtdWxhX3BhcnR5X21hdGNoX292ZXJhbGwgPC0gYXMuZm9ybXVsYSgNCiAgICBwYXN0ZSgNCiAgICAgICJzZWxlY3RlZCB+IiwNCiAgICAgIHBhc3RlKA0KICAgICAgICBjKA0KICAgICAgICAgICJwYXJ0eV9uYW1lIiwNCiAgICAgICAgICAicGFydHlfbWF0Y2giLA0KICAgICAgICAgIGVjb25vbWljX2F0dHJfdGVybXMNCiAgICAgICAgKSwNCiAgICAgICAgY29sbGFwc2UgPSAiICsgIg0KICAgICAgKQ0KICAgICkNCiAgKQ0KDQogIHJ1bl9wYXJ0eV9tYXRjaF9vdmVyYWxsIDwtIGZ1bmN0aW9uKGRhdCkgew0KICAgIGZlb2xzKA0KICAgICAgZm9ybXVsYV9wYXJ0eV9tYXRjaF9vdmVyYWxsLA0KICAgICAgZGF0YSA9IGRhdCwNCiAgICAgIHZjb3YgPSB+IElEDQogICAgKQ0KICB9DQoNCiAgbW9kZWxzX3BhcnR5X21hdGNoX2J5X24gPC0gY29uam9pbnRfbWF0Y2ggJT4lDQogICAgc3BsaXQoLiRwYXJ0eV9uKSAlPiUNCiAgICBtYXAocnVuX3BhcnR5X21hdGNoX292ZXJhbGwpDQoNCiAgbV9wYXJ0eV9tYXRjaF9pbnRlcmFjdGlvbiA8LSBmZW9scygNCiAgICBzZWxlY3RlZCB+DQogICAgICBwYXJ0eV9uX2YgKg0KICAgICAgcGFydHlfbWF0Y2ggKw0KICAgICAgcGFydHlfbmFtZSArDQogICAgICBnZHBfZ3Jvd3RoICsNCiAgICAgIG5pa2tlaSArDQogICAgICBjcGkgKw0KICAgICAgdW5lbXBsb3ltZW50LA0KICAgIGRhdGEgPSBjb25qb2ludF9tYXRjaCwNCiAgICB2Y292ID0gfiBJRA0KICApDQoNCiAgY2FwdHVyZS5vdXRwdXQoDQogICAgbGFwcGx5KA0KICAgICAgbW9kZWxzX3BhcnR5X21hdGNoX2J5X24sDQogICAgICBzdW1tYXJ5DQogICAgKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJwYXJ0eV9tYXRjaF9tb2RlbHNfYnlfY2hvaWNlX251bWJlci50eHQiDQogICAgKQ0KICApDQoNCiAgY2FwdHVyZS5vdXRwdXQoDQogICAgc3VtbWFyeShtX3BhcnR5X21hdGNoX2ludGVyYWN0aW9uKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJwYXJ0eV9tYXRjaF9pbnRlcmFjdGlvbl9tb2RlbC50eHQiDQogICAgKQ0KICApDQoNCiAgZXh0cmFjdF9wYXJ0eV9tYXRjaF90ZXJtIDwtIGZ1bmN0aW9uKG1vZGVsKSB7DQogICAgb3V0IDwtIHRpZHlfZml4ZXN0KG1vZGVsKSAlPiUNCiAgICAgIGZpbHRlcih0ZXJtID09ICJwYXJ0eV9tYXRjaCIpDQogICAgDQogICAgaWYgKG5yb3cob3V0KSA9PSAwKSB7DQogICAgICByZXR1cm4oDQogICAgICAgIHRpYmJsZSgNCiAgICAgICAgICB0ZXJtID0gInBhcnR5X21hdGNoIiwNCiAgICAgICAgICBlc3RpbWF0ZSA9IE5BX3JlYWxfLA0KICAgICAgICAgIHN0ZC5lcnJvciA9IE5BX3JlYWxfLA0KICAgICAgICAgIHN0YXRpc3RpYyA9IE5BX3JlYWxfLA0KICAgICAgICAgIHAudmFsdWUgPSBOQV9yZWFsXywNCiAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLA0KICAgICAgICAgIGNvbmYuaGlnaCA9IE5BX3JlYWxfDQogICAgICAgICkNCiAgICAgICkNCiAgICB9DQogICAgDQogICAgb3V0DQogIH0NCg0KICBwYXJ0eV9tYXRjaF9jb2VmX2RmIDwtIGltYXBfZGZyKA0KICAgIG1vZGVsc19wYXJ0eV9tYXRjaF9ieV9uLA0KICAgIH4gZXh0cmFjdF9wYXJ0eV9tYXRjaF90ZXJtKC54KSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgc3VwcG9ydF9ncm91cCA9ICLlhajkvZMiLA0KICAgICAgICBzdXBwb3J0X2dyb3VwX2xhYmVsID0gIuWFqOS9kyIsDQogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKC55KQ0KICAgICAgKQ0KICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIGVzdGltYXRlX3BwID0gZXN0aW1hdGUgKiAxMDAsDQogICAgICBjb25mLmxvd19wcCA9IGNvbmYubG93ICogMTAwLA0KICAgICAgY29uZi5oaWdoX3BwID0gY29uZi5oaWdoICogMTAwLA0KICAgICAgDQogICAgICBwYXJ0eV9uX2xhYmVsID0gZmFjdG9yKA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBsZXZlbHMgPSAyOjUsDQogICAgICAgIGxhYmVscyA9IGMoDQogICAgICAgICAgIjLpgbjmip7ogqIiLA0KICAgICAgICAgICIz6YG45oqe6IKiIiwNCiAgICAgICAgICAiNOmBuOaKnuiCoiIsDQogICAgICAgICAgIjXpgbjmip7ogqIiDQogICAgICAgICkNCiAgICAgICkNCiAgICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBwYXJ0eV9tYXRjaF9jb2VmX2RmLA0KICAgICJwYXJ0eV9tYXRjaF9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCg0KICB0YXJnZXRfc3VwcG9ydF9ncm91cHMgPC0gYygNCiAgICAi6Ieq55Sx5rCR5Li75YWaIiwNCiAgICAi5Lit6YGT5pS56Z2p6YCj5ZCIIiwNCiAgICAi56uL5oay5rCR5Li75YWaIiwNCiAgICAi5Y+C5pS/5YWaIg0KICApDQoNCiAgdGFyZ2V0X3N1cHBvcnRfbGFiZWxzIDwtIGMoDQogICAgIuiHqueUseawkeS4u+WFmiIgICA9ICLoh6rmsJHlhZrmlK/mjIHogIUiLA0KICAgICLkuK3pgZPmlLnpnanpgKPlkIgiID0gIuS4remBk+aUuemdqeaUr+aMgeiAhSIsDQogICAgIueri+aGsuawkeS4u+WFmiIgICA9ICLnq4vmhrLmlK/mjIHogIUiLA0KICAgICLlj4LmlL/lhZoiICAgICAgID0gIuWPguaUv+WFmuaUr+aMgeiAhSINCiAgKQ0KDQogIHBhcnR5X21hdGNoX3N1Ymdyb3VwX3NhbXBsZSA8LSBjb25qb2ludF9tYXRjaCAlPiUNCiAgICBkaXN0aW5jdCgNCiAgICAgIElELA0KICAgICAgcGFydHlfbiwNCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQNCiAgICApICU+JQ0KICAgIGZpbHRlcigNCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgJWluJSB0YXJnZXRfc3VwcG9ydF9ncm91cHMNCiAgICApICU+JQ0KICAgIGNvdW50KA0KICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCwNCiAgICAgIHBhcnR5X24sDQogICAgICBuYW1lID0gIm5fcmVzcG9uZGVudHMiDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBzdXBwb3J0X2dyb3VwX2xhYmVsID0gcmVjb2RlKA0KICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkLA0KICAgICAgICAhISF0YXJnZXRfc3VwcG9ydF9sYWJlbHMNCiAgICAgICkNCiAgICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBwYXJ0eV9tYXRjaF9zdWJncm91cF9zYW1wbGUsDQogICAgInBhcnR5X21hdGNoX3N1Ymdyb3VwX3NhbXBsZS5jc3YiDQogICkNCg0KICBzdXBwb3J0X2dyb3VwX3RvdGFsX24gPC0gY29uam9pbnRfbWF0Y2ggJT4lDQogICAgZGlzdGluY3QoDQogICAgICBJRCwNCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQNCiAgICApICU+JQ0KICAgIGZpbHRlcigNCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgJWluJSB0YXJnZXRfc3VwcG9ydF9ncm91cHMNCiAgICApICU+JQ0KICAgIGNvdW50KA0KICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCwNCiAgICAgIG5hbWUgPSAibl90b3RhbCINCiAgICApDQoNCiAgZm9ybXVsYV9wYXJ0eV9tYXRjaF9zdWJncm91cCA8LSBhcy5mb3JtdWxhKA0KICAgIHBhc3RlKA0KICAgICAgInNlbGVjdGVkIH4iLA0KICAgICAgcGFzdGUoDQogICAgICAgIGMoDQogICAgICAgICAgInBhcnR5X21hdGNoIiwNCiAgICAgICAgICBlY29ub21pY19hdHRyX3Rlcm1zDQogICAgICAgICksDQogICAgICAgIGNvbGxhcHNlID0gIiArICINCiAgICAgICkNCiAgICApDQogICkNCg0KICBydW5fcGFydHlfbWF0Y2hfc3ViZ3JvdXAgPC0gZnVuY3Rpb24oZGF0KSB7DQogICAgZmVvbHMoDQogICAgICBmb3JtdWxhX3BhcnR5X21hdGNoX3N1Ymdyb3VwLA0KICAgICAgZGF0YSA9IGRhdCwNCiAgICAgIHZjb3YgPSB+IElEDQogICAgKQ0KICB9DQoNCiAgZXN0aW1hdGVfcGFydHlfbWF0Y2hfc3ViZ3JvdXAgPC0gZnVuY3Rpb24oDQogICAgICBkYXQsDQogICAgICBzdXBwb3J0X2dyb3VwX3ZhbHVlDQogICkgew0KICAgIG1hcF9kZnIoDQogICAgICAyOjUsDQogICAgICBmdW5jdGlvbihuX3ZhbHVlKSB7DQogICAgICAgIA0KICAgICAgICBkYXRfbiA8LSBkYXQgJT4lDQogICAgICAgICAgZmlsdGVyKA0KICAgICAgICAgICAgcGFydHlfbiA9PSBuX3ZhbHVlLA0KICAgICAgICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9PSBzdXBwb3J0X2dyb3VwX3ZhbHVlDQogICAgICAgICAgKQ0KICAgICAgICANCiAgICAgICAgbl9pZHMgPC0gbl9kaXN0aW5jdChkYXRfbiRJRCkNCiAgICAgICAgDQogICAgICAgIGlmIChucm93KGRhdF9uKSA9PSAwIHx8IG5faWRzID09IDApIHsNCiAgICAgICAgICByZXR1cm4oDQogICAgICAgICAgICB0aWJibGUoDQogICAgICAgICAgICAgIHRlcm0gPSAicGFydHlfbWF0Y2giLA0KICAgICAgICAgICAgICBlc3RpbWF0ZSA9IE5BX3JlYWxfLA0KICAgICAgICAgICAgICBzdGQuZXJyb3IgPSBOQV9yZWFsXywNCiAgICAgICAgICAgICAgc3RhdGlzdGljID0gTkFfcmVhbF8sDQogICAgICAgICAgICAgIHAudmFsdWUgPSBOQV9yZWFsXywNCiAgICAgICAgICAgICAgY29uZi5sb3cgPSBOQV9yZWFsXywNCiAgICAgICAgICAgICAgY29uZi5oaWdoID0gTkFfcmVhbF8sDQogICAgICAgICAgICAgIHN1cHBvcnRfZ3JvdXAgPSBzdXBwb3J0X2dyb3VwX3ZhbHVlLA0KICAgICAgICAgICAgICBzdXBwb3J0X2dyb3VwX2xhYmVsID0gdW5uYW1lKA0KICAgICAgICAgICAgICAgIHRhcmdldF9zdXBwb3J0X2xhYmVsc1tbc3VwcG9ydF9ncm91cF92YWx1ZV1dDQogICAgICAgICAgICAgICksDQogICAgICAgICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLA0KICAgICAgICAgICAgICBuX2lkcyA9IG5faWRzDQogICAgICAgICAgICApDQogICAgICAgICAgKQ0KICAgICAgICB9DQogICAgICAgIA0KICAgICAgICBtb2RlbF9uIDwtIHRyeUNhdGNoKA0KICAgICAgICAgIHJ1bl9wYXJ0eV9tYXRjaF9zdWJncm91cChkYXRfbiksDQogICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSBOVUxMDQogICAgICAgICkNCiAgICAgICAgDQogICAgICAgIGlmIChpcy5udWxsKG1vZGVsX24pKSB7DQogICAgICAgICAgcmV0dXJuKA0KICAgICAgICAgICAgdGliYmxlKA0KICAgICAgICAgICAgICB0ZXJtID0gInBhcnR5X21hdGNoIiwNCiAgICAgICAgICAgICAgZXN0aW1hdGUgPSBOQV9yZWFsXywNCiAgICAgICAgICAgICAgc3RkLmVycm9yID0gTkFfcmVhbF8sDQogICAgICAgICAgICAgIHN0YXRpc3RpYyA9IE5BX3JlYWxfLA0KICAgICAgICAgICAgICBwLnZhbHVlID0gTkFfcmVhbF8sDQogICAgICAgICAgICAgIGNvbmYubG93ID0gTkFfcmVhbF8sDQogICAgICAgICAgICAgIGNvbmYuaGlnaCA9IE5BX3JlYWxfLA0KICAgICAgICAgICAgICBzdXBwb3J0X2dyb3VwID0gc3VwcG9ydF9ncm91cF92YWx1ZSwNCiAgICAgICAgICAgICAgc3VwcG9ydF9ncm91cF9sYWJlbCA9IHVubmFtZSgNCiAgICAgICAgICAgICAgICB0YXJnZXRfc3VwcG9ydF9sYWJlbHNbW3N1cHBvcnRfZ3JvdXBfdmFsdWVdXQ0KICAgICAgICAgICAgICApLA0KICAgICAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwNCiAgICAgICAgICAgICAgbl9pZHMgPSBuX2lkcw0KICAgICAgICAgICAgKQ0KICAgICAgICAgICkNCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgZXh0cmFjdF9wYXJ0eV9tYXRjaF90ZXJtKG1vZGVsX24pICU+JQ0KICAgICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgIHN1cHBvcnRfZ3JvdXAgPSBzdXBwb3J0X2dyb3VwX3ZhbHVlLA0KICAgICAgICAgICAgc3VwcG9ydF9ncm91cF9sYWJlbCA9IHVubmFtZSgNCiAgICAgICAgICAgICAgdGFyZ2V0X3N1cHBvcnRfbGFiZWxzW1tzdXBwb3J0X2dyb3VwX3ZhbHVlXV0NCiAgICAgICAgICAgICksDQogICAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwNCiAgICAgICAgICAgIG5faWRzID0gbl9pZHMNCiAgICAgICAgICApDQogICAgICB9DQogICAgKQ0KICB9DQoNCiAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZiA8LSBtYXBfZGZyKA0KICAgIHRhcmdldF9zdXBwb3J0X2dyb3VwcywNCiAgICB+IGVzdGltYXRlX3BhcnR5X21hdGNoX3N1Ymdyb3VwKA0KICAgICAgY29uam9pbnRfbWF0Y2gsDQogICAgICAueA0KICAgICkNCiAgKSAlPiUNCiAgICBsZWZ0X2pvaW4oDQogICAgICBzdXBwb3J0X2dyb3VwX3RvdGFsX24sDQogICAgICBieSA9IGMoDQogICAgICAgICJzdXBwb3J0X2dyb3VwIiA9ICJzdXBwb3J0X3BhcnR5X3ZhbGlkIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsDQogICAgICBjb25mLmhpZ2hfcHAgPSBjb25mLmhpZ2ggKiAxMDAsDQogICAgICBwYXJ0eV9uX2xhYmVsID0gZmFjdG9yKA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBsZXZlbHMgPSAyOjUsDQogICAgICAgIGxhYmVscyA9IGMoDQogICAgICAgICAgIjLpgbjmip7ogqIiLA0KICAgICAgICAgICIz6YG45oqe6IKiIiwNCiAgICAgICAgICAiNOmBuOaKnuiCoiIsDQogICAgICAgICAgIjXpgbjmip7ogqIiDQogICAgICAgICkNCiAgICAgICkNCiAgICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICBwYXJ0eV9tYXRjaF9zdWJncm91cF9jb2VmX2RmLA0KICAgICJwYXJ0eV9tYXRjaF9zdWJncm91cF9jb2VmZmljaWVudHMuY3N2Ig0KICApDQoNCg0KICBwYXJ0eV9tYXRjaF9wbG90X2RmX2FsbCA8LSBiaW5kX3Jvd3MoDQogICAgcGFydHlfbWF0Y2hfY29lZl9kZiAlPiUNCiAgICAgIG11dGF0ZShwYW5lbCA9ICJvdmVyYWxsIiksDQogICAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZiAlPiUNCiAgICAgIG11dGF0ZShwYW5lbCA9ICJzdWJncm91cCIpDQogICkgJT4lDQogICAgZmlsdGVyKA0KICAgICAgaXMuZmluaXRlKGVzdGltYXRlX3BwKSwNCiAgICAgIGlzLmZpbml0ZShjb25mLmxvd19wcCksDQogICAgICBpcy5maW5pdGUoY29uZi5oaWdoX3BwKQ0KICAgICkNCg0KICBpZiAobnJvdyhwYXJ0eV9tYXRjaF9wbG90X2RmX2FsbCkgPT0gMCkgew0KICAgIHN0b3AoIkNoZWNrIGRhdGEiKQ0KICB9DQoNCiAgeV9yYW5nZV9tYXRjaCA8LSByYW5nZSgNCiAgICBjKA0KICAgICAgcGFydHlfbWF0Y2hfcGxvdF9kZl9hbGwkY29uZi5sb3dfcHAsDQogICAgICBwYXJ0eV9tYXRjaF9wbG90X2RmX2FsbCRjb25mLmhpZ2hfcHANCiAgICApLA0KICAgIG5hLnJtID0gVFJVRQ0KICApDQoNCiAgeV9zcGFuX21hdGNoIDwtIGRpZmYoeV9yYW5nZV9tYXRjaCkNCg0KICBpZiAoIWlzLmZpbml0ZSh5X3NwYW5fbWF0Y2gpIHx8IHlfc3Bhbl9tYXRjaCA8PSAwKSB7DQogICAgeV9zcGFuX21hdGNoIDwtIDUNCiAgfQ0KDQogIHlfcGFkX21hdGNoIDwtIG1heCgxLjIsIDAuMTAgKiB5X3NwYW5fbWF0Y2gpDQoNCiAgeV9saW1pdHNfbWF0Y2ggPC0gYygNCiAgICB5X3JhbmdlX21hdGNoWzFdIC0geV9wYWRfbWF0Y2gsDQogICAgeV9yYW5nZV9tYXRjaFsyXSArIHlfcGFkX21hdGNoDQogICkNCg0KDQogIHRoZW1lX3BhcnR5X21hdGNoX2J3IDwtIHRoZW1lX2J3KA0KICAgIGJhc2Vfc2l6ZSA9IDEyLA0KICAgIGJhc2VfZmFtaWx5ID0gZmlndXJlX2ZvbnRfZmFtaWx5DQogICkgKw0KICAgIHRoZW1lKA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoDQogICAgICAgIGxpbmV3aWR0aCA9IDAuMzAsDQogICAgICAgIGNvbG9yID0gImdyZXk4OCINCiAgICAgICksDQogICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGxpbmV3aWR0aCA9IDAuNjUsDQogICAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICAgKSwNCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLA0KICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgZmFjZSA9ICJib2xkIg0KICAgICAgKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIHNpemUgPSByZWwoMC45MikNCiAgICAgICksDQogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigNCiAgICAgICAgOCwgMTAsIDgsIDgNCiAgICAgICkNCiAgICApDQoNCg0KICBtYWtlX3BhcnR5X21hdGNoX3BhbmVsX3Bsb3QgPC0gZnVuY3Rpb24oDQogICAgICBkYXQsDQogICAgICBwYW5lbF90aXRsZSwNCiAgICAgIHBhbmVsX3N1YnRpdGxlID0gTlVMTCwNCiAgICAgIGJhc2Vfc2l6ZSA9IDExLA0KICAgICAgc2hvd195X3RpdGxlID0gVFJVRSwNCiAgICAgIHNob3dfeF90aXRsZSA9IFRSVUUNCiAgKSB7DQogICAgZ2dwbG90KA0KICAgICAgZGF0LA0KICAgICAgYWVzKA0KICAgICAgICB4ID0gcGFydHlfbiwNCiAgICAgICAgeSA9IGVzdGltYXRlX3BwDQogICAgICApDQogICAgKSArDQogICAgICBnZW9tX2xpbmUoDQogICAgICAgIGxpbmV3aWR0aCA9IDAuODAsDQogICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICApICsNCiAgICAgIGdlb21fZXJyb3JiYXIoDQogICAgICAgIGFlcygNCiAgICAgICAgICB5bWluID0gY29uZi5sb3dfcHAsDQogICAgICAgICAgeW1heCA9IGNvbmYuaGlnaF9wcA0KICAgICAgICApLA0KICAgICAgICB3aWR0aCA9IDAuMDc1LA0KICAgICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICAgIG5hLnJtID0gVFJVRQ0KICAgICAgKSArDQogICAgICBnZW9tX2xhYmVsKA0KICAgICAgICBhZXMoDQogICAgICAgICAgbGFiZWwgPSBzcHJpbnRmKCIlLjFmIHBwIiwgZXN0aW1hdGVfcHApDQogICAgICAgICksDQogICAgICAgIHNpemUgPSAzLjQ1LA0KICAgICAgICBmYW1pbHkgPSBmaWd1cmVfZm9udF9mYW1pbHksDQogICAgICAgIGxhYmVsLnNpemUgPSAwLA0KICAgICAgICBsYWJlbC5wYWRkaW5nID0gdW5pdCgNCiAgICAgICAgICAwLjEyLA0KICAgICAgICAgICJsaW5lcyINCiAgICAgICAgKSwNCiAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICApICsNCiAgICAgIHNjYWxlX3hfY29udGludW91cygNCiAgICAgICAgYnJlYWtzID0gMjo1LA0KICAgICAgICBsYWJlbHMgPSBwYXN0ZTAoDQogICAgICAgICAgMjo1LA0KICAgICAgICAgICLpgbjmip7ogqIiDQogICAgICAgICksDQogICAgICAgIGxpbWl0cyA9IGMoMS43MiwgNS4yOCkNCiAgICAgICkgKw0KICAgICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSB7DQogICAgICAgICAgcGFzdGUwKHgsICIgcHAiKQ0KICAgICAgICB9LA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDYpLA0KICAgICAgICBleHBhbmQgPSBleHBhbnNpb24oDQogICAgICAgICAgbXVsdCA9IGMoMC4wNSwgMC4wOCkNCiAgICAgICAgKQ0KICAgICAgKSArDQogICAgICBjb29yZF9jYXJ0ZXNpYW4oDQogICAgICAgIHlsaW0gPSB5X2xpbWl0c19tYXRjaA0KICAgICAgKSArDQogICAgICBsYWJzKA0KICAgICAgICB0aXRsZSA9IHBhbmVsX3RpdGxlLA0KICAgICAgICBzdWJ0aXRsZSA9IHBhbmVsX3N1YnRpdGxlLA0KICAgICAgICB4ID0gaWYgKHNob3dfeF90aXRsZSkgIumBuOaKnuiCouaVsCIgZWxzZSBOVUxMLA0KICAgICAgICB5ID0gaWYgKHNob3dfeV90aXRsZSkgIuS4gOiHtOOBl+OBn+WgtOWQiOOBrumBuOaKnueiuueOh+OBruWkieWMliIgZWxzZSBOVUxMDQogICAgICApICsNCiAgICAgIHRoZW1lX2J3KA0KICAgICAgICBiYXNlX3NpemUgPSBiYXNlX3NpemUsDQogICAgICAgIGJhc2VfZmFtaWx5ID0gZmlndXJlX2ZvbnRfZmFtaWx5DQogICAgICApICsNCiAgICAgIHRoZW1lX3BhcnR5X21hdGNoX2J3ICsNCiAgICAgIHRoZW1lKA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KA0KICAgICAgICAgIGZhY2UgPSAiYm9sZCINCiAgICAgICAgKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gaWYgKHNob3dfeF90aXRsZSkgZWxlbWVudF90ZXh0KCkgZWxzZSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGlmIChzaG93X3lfdGl0bGUpIGVsZW1lbnRfdGV4dCgpIGVsc2UgZWxlbWVudF9ibGFuaygpDQogICAgICApDQogIH0NCg0KICBtYWtlX3N1cHBvcnRfZ3JvdXBfdGl0bGUgPC0gZnVuY3Rpb24oDQogICAgICBzdXBwb3J0X2dyb3VwX3ZhbHVlDQogICkgew0KICAgIG5fdmFsdWUgPC0gc3VwcG9ydF9ncm91cF90b3RhbF9uICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID09IHN1cHBvcnRfZ3JvdXBfdmFsdWUNCiAgICAgICkgJT4lDQogICAgICBwdWxsKG5fdG90YWwpDQogICAgDQogICAgaWYgKGxlbmd0aChuX3ZhbHVlKSA9PSAwIHx8IGlzLm5hKG5fdmFsdWUpKSB7DQogICAgICBuX3ZhbHVlIDwtIDANCiAgICB9DQogICAgDQogICAgcGFzdGUwKA0KICAgICAgdGFyZ2V0X3N1cHBvcnRfbGFiZWxzW1tzdXBwb3J0X2dyb3VwX3ZhbHVlXV0sDQogICAgICAiXG4obj0iLA0KICAgICAgc2NhbGVzOjpjb21tYShuX3ZhbHVlKSwNCiAgICAgICIpIg0KICAgICkNCiAgfQ0KDQoNCiAgcF9wYXJ0eV9tYXRjaF9vdmVyYWxsIDwtIG1ha2VfcGFydHlfbWF0Y2hfcGFuZWxfcGxvdCgNCiAgICBwYXJ0eV9tYXRjaF9jb2VmX2RmLA0KICAgIHBhbmVsX3RpdGxlID0gTlVMTCwNCiAgICBwYW5lbF9zdWJ0aXRsZSA9DQogICAgICAi5LiK5q6144Gv5YWo5L2T44CB5LiL5q6144Gv5pSv5oyB5pS/5YWa5Yil77yI6Ieq5rCR44O75Lit6YGT5pS56Z2p44O756uL5oay44O75Y+C5pS/77yJ44CC5pS/5YWa5ZCN44Go57WM5riI5bGe5oCn44KS57Wx5Yi244GX44Gf57ea5b2i56K6546H44Oi44OH44Or44CCIiwNCiAgICBiYXNlX3NpemUgPSAxMiwNCiAgICBzaG93X3lfdGl0bGUgPSBUUlVFLA0KICAgIHNob3dfeF90aXRsZSA9IFRSVUUNCiAgKQ0KDQoNCiAgcF9wYXJ0eV9tYXRjaF9sZHAgPC0gbWFrZV9wYXJ0eV9tYXRjaF9wYW5lbF9wbG90KA0KICAgIHBhcnR5X21hdGNoX3N1Ymdyb3VwX2NvZWZfZGYgJT4lDQogICAgICBmaWx0ZXIoc3VwcG9ydF9ncm91cCA9PSAi6Ieq55Sx5rCR5Li75YWaIiksDQogICAgcGFuZWxfdGl0bGUgPSBtYWtlX3N1cHBvcnRfZ3JvdXBfdGl0bGUoIuiHqueUseawkeS4u+WFmiIpLA0KICAgIGJhc2Vfc2l6ZSA9IDEwLA0KICAgIHNob3dfeV90aXRsZSA9IFRSVUUsDQogICAgc2hvd194X3RpdGxlID0gVFJVRQ0KICApDQoNCiAgcF9wYXJ0eV9tYXRjaF9jaHIgPC0gbWFrZV9wYXJ0eV9tYXRjaF9wYW5lbF9wbG90KA0KICAgIHBhcnR5X21hdGNoX3N1Ymdyb3VwX2NvZWZfZGYgJT4lDQogICAgICBmaWx0ZXIoc3VwcG9ydF9ncm91cCA9PSAi5Lit6YGT5pS56Z2p6YCj5ZCIIiksDQogICAgcGFuZWxfdGl0bGUgPSBtYWtlX3N1cHBvcnRfZ3JvdXBfdGl0bGUoIuS4remBk+aUuemdqemAo+WQiCIpLA0KICAgIGJhc2Vfc2l6ZSA9IDEwLA0KICAgIHNob3dfeV90aXRsZSA9IEZBTFNFLA0KICAgIHNob3dfeF90aXRsZSA9IFRSVUUNCiAgKQ0KDQogIHBfcGFydHlfbWF0Y2hfY2RwIDwtIG1ha2VfcGFydHlfbWF0Y2hfcGFuZWxfcGxvdCgNCiAgICBwYXJ0eV9tYXRjaF9zdWJncm91cF9jb2VmX2RmICU+JQ0KICAgICAgZmlsdGVyKHN1cHBvcnRfZ3JvdXAgPT0gIueri+aGsuawkeS4u+WFmiIpLA0KICAgIHBhbmVsX3RpdGxlID0gbWFrZV9zdXBwb3J0X2dyb3VwX3RpdGxlKCLnq4vmhrLmsJHkuLvlhZoiKSwNCiAgICBiYXNlX3NpemUgPSAxMCwNCiAgICBzaG93X3lfdGl0bGUgPSBGQUxTRSwNCiAgICBzaG93X3hfdGl0bGUgPSBUUlVFDQogICkNCg0KICBwX3BhcnR5X21hdGNoX3NhbnNlaSA8LSBtYWtlX3BhcnR5X21hdGNoX3BhbmVsX3Bsb3QoDQogICAgcGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZiAlPiUNCiAgICAgIGZpbHRlcihzdXBwb3J0X2dyb3VwID09ICLlj4LmlL/lhZoiKSwNCiAgICBwYW5lbF90aXRsZSA9IG1ha2Vfc3VwcG9ydF9ncm91cF90aXRsZSgi5Y+C5pS/5YWaIiksDQogICAgYmFzZV9zaXplID0gMTAsDQogICAgc2hvd195X3RpdGxlID0gRkFMU0UsDQogICAgc2hvd194X3RpdGxlID0gVFJVRQ0KICApDQoNCiAgcF9wYXJ0eV9tYXRjaF9ib3R0b20gPC0NCiAgICBwX3BhcnR5X21hdGNoX2xkcCArDQogICAgcF9wYXJ0eV9tYXRjaF9jaHIgKw0KICAgIHBfcGFydHlfbWF0Y2hfY2RwICsNCiAgICBwX3BhcnR5X21hdGNoX3NhbnNlaSArDQogICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChuY29sID0gNCkNCg0KICBwX3BhcnR5X21hdGNoIDwtDQogICAgcF9wYXJ0eV9tYXRjaF9vdmVyYWxsIC8NCiAgICBwX3BhcnR5X21hdGNoX2JvdHRvbSArDQogICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dCgNCiAgICAgIGhlaWdodHMgPSBjKDEuMjUsIDEpDQogICAgKQ0KDQogIHByaW50KHBfcGFydHlfbWF0Y2gpDQoNCiAgc2F2ZV9wbG90KA0KICAgICJwYXJ0eV9tYXRjaF9lZmZlY3RfY29tYmluZWQucG5nIiwNCiAgICBwX3BhcnR5X21hdGNoLA0KICAgIHdpZHRoID0gMTQsDQogICAgaGVpZ2h0ID0gOC44DQogICkNCg0KDQogIHJlbGF0aXZlX2N1ZV9tYXAgPC0gYygNCiAgICBwYXJ0eV9uYW1lID0gInBhcnR5IiwNCiAgICBnZHBfZ3Jvd3RoID0gImVjb25vbWljIiwNCiAgICBuaWtrZWkgPSAiZWNvbm9taWMiLA0KICAgIGNwaSA9ICJlY29ub21pYyIsDQogICAgdW5lbXBsb3ltZW50ID0gImVjb25vbWljIg0KICApDQoNCiAgbWVhbl9hYnNvbHV0ZV9wYWlyd2lzZV9kaWZmZXJlbmNlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXQ0KDQogICAgaWYgKGxlbmd0aCh4KSA8IDIpIHsNCiAgICAgIHJldHVybihOQV9yZWFsXykNCiAgICB9DQoNCiAgICBwYWlyd2lzZV9kaWZmZXJlbmNlcyA8LSBjb21ibigNCiAgICAgIHgsDQogICAgICAyLA0KICAgICAgRlVOID0gZnVuY3Rpb24oeikgYWJzKHpbMV0gLSB6WzJdKQ0KICAgICkNCg0KICAgIG1lYW4ocGFpcndpc2VfZGlmZmVyZW5jZXMpDQogIH0NCg0KICBsaW5lYXJfc2xvcGUgPC0gZnVuY3Rpb24oeSwgeCkgew0KICAgIGtlZXAgPC0gaXMuZmluaXRlKHkpICYgaXMuZmluaXRlKHgpDQogICAgeSA8LSB5W2tlZXBdDQogICAgeCA8LSB4W2tlZXBdDQoNCiAgICBpZiAobGVuZ3RoKHkpIDwgMiB8fCBsZW5ndGgodW5pcXVlKHgpKSA8IDIpIHsNCiAgICAgIHJldHVybihOQV9yZWFsXykNCiAgICB9DQoNCiAgICB1bm5hbWUoY29lZihsbSh5IH4geCkpWzJdKQ0KICB9DQoNCiAgYm9vdHN0cmFwX3R3b19zaWRlZF9wIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXQ0KICAgIEJfdmFsaWQgPC0gbGVuZ3RoKHgpDQoNCiAgICBpZiAoQl92YWxpZCA9PSAwKSB7DQogICAgICByZXR1cm4oTkFfcmVhbF8pDQogICAgfQ0KDQogICAgcF9sb3dlciA8LSAoMSArIHN1bSh4IDw9IDApKSAvIChCX3ZhbGlkICsgMSkNCiAgICBwX3VwcGVyIDwtICgxICsgc3VtKHggPj0gMCkpIC8gKEJfdmFsaWQgKyAxKQ0KDQogICAgbWluKDEsIDIgKiBtaW4ocF9sb3dlciwgcF91cHBlcikpDQogIH0NCg0KICBzYWZlX3F1YW50aWxlIDwtIGZ1bmN0aW9uKHgsIHByb2JhYmlsaXR5KSB7DQogICAgeCA8LSB4W2lzLmZpbml0ZSh4KV0NCg0KICAgIGlmIChsZW5ndGgoeCkgPT0gMCkgew0KICAgICAgcmV0dXJuKE5BX3JlYWxfKQ0KICAgIH0NCg0KICAgIHVubmFtZSgNCiAgICAgIHF1YW50aWxlKA0KICAgICAgICB4LA0KICAgICAgICBwcm9icyA9IHByb2JhYmlsaXR5LA0KICAgICAgICB0eXBlID0gNiwNCiAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICApDQogICAgKQ0KICB9DQoNCiAgcHJlcGFyZV9yZWxhdGl2ZV9jdWVfYW5hbHlzaXMgPC0gZnVuY3Rpb24oZGF0YSwgY3VlX21hcCkgew0KICAgIGF0dHJpYnV0ZXMgPC0gbmFtZXMoY3VlX21hcCkNCg0KICAgIHJlcXVpcmVkX2NvbHVtbnMgPC0gYygNCiAgICAgICJJRCIsDQogICAgICAicGFydHlfbiIsDQogICAgICAic2VsZWN0ZWQiLA0KICAgICAgYXR0cmlidXRlcw0KICAgICkNCg0KICAgIG1pc3NpbmdfY29sdW1ucyA8LSBzZXRkaWZmKA0KICAgICAgcmVxdWlyZWRfY29sdW1ucywNCiAgICAgIG5hbWVzKGRhdGEpDQogICAgKQ0KDQogICAgaWYgKGxlbmd0aChtaXNzaW5nX2NvbHVtbnMpID4gMCkgew0KICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikNCiAgICB9DQoNCiAgICBpZiAoIWFsbCh1bm5hbWUoY3VlX21hcCkgJWluJSBjKCJwYXJ0eSIsICJlY29ub21pYyIpKSkgew0KICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikNCiAgICB9DQoNCiAgICBhbmFseXNpc19kYXRhIDwtIGRhdGEgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIElELA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBzZWxlY3RlZCwNCiAgICAgICAgYWxsX29mKGF0dHJpYnV0ZXMpDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksDQogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSksDQogICAgICAgIHNlbGVjdGVkID0gYXMuaW50ZWdlcihzZWxlY3RlZCksDQogICAgICAgIGFjcm9zcygNCiAgICAgICAgICBhbGxfb2YoYXR0cmlidXRlcyksDQogICAgICAgICAgYXMuY2hhcmFjdGVyDQogICAgICAgICkNCiAgICAgICkgJT4lDQogICAgICBmaWx0ZXIoDQogICAgICAgICFpcy5uYShJRCksDQogICAgICAgIHBhcnR5X24gJWluJSAyOjUsDQogICAgICAgIHNlbGVjdGVkICVpbiUgYygwTCwgMUwpDQogICAgICApDQoNCiAgICBvYnNlcnZlZF9jb25kaXRpb25zIDwtIHNvcnQoDQogICAgICB1bmlxdWUoYW5hbHlzaXNfZGF0YSRwYXJ0eV9uKQ0KICAgICkNCg0KICAgIGlmICghaWRlbnRpY2FsKG9ic2VydmVkX2NvbmRpdGlvbnMsIDI6NSkpIHsNCiAgICAgIHN0b3AoIkNoZWNrIikNCiAgICB9DQoNCiAgICBsb25nX2RhdGEgPC0gYW5hbHlzaXNfZGF0YSAlPiUNCiAgICAgIHBpdm90X2xvbmdlcigNCiAgICAgICAgY29scyA9IGFsbF9vZihhdHRyaWJ1dGVzKSwNCiAgICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwNCiAgICAgICAgdmFsdWVzX3RvID0gImxldmVsIg0KICAgICAgKSAlPiUNCiAgICAgIGZpbHRlcigNCiAgICAgICAgIWlzLm5hKGxldmVsKSwNCiAgICAgICAgbGV2ZWwgIT0gIiINCiAgICAgICkNCg0KICAgIGV4cGVjdGVkX2NlbGxzIDwtIGxvbmdfZGF0YSAlPiUNCiAgICAgIGRpc3RpbmN0KA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVsDQogICAgICApICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBhdHRyaWJ1dGVfb3JkZXIgPSBtYXRjaCgNCiAgICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgICAgYXR0cmlidXRlcw0KICAgICAgICApDQogICAgICApICU+JQ0KICAgICAgYXJyYW5nZSgNCiAgICAgICAgYXR0cmlidXRlX29yZGVyLA0KICAgICAgICBhdHRyaWJ1dGUsDQogICAgICAgIGxldmVsDQogICAgICApICU+JQ0KICAgICAgc2VsZWN0KC1hdHRyaWJ1dGVfb3JkZXIpICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBjZWxsX2tleSA9IHBhc3RlKA0KICAgICAgICAgIGF0dHJpYnV0ZSwNCiAgICAgICAgICBsZXZlbCwNCiAgICAgICAgICBzZXAgPSAiXHIiDQogICAgICAgICkNCiAgICAgICkNCg0KICAgIHJlc3BvbmRlbnRfY2VsbCA8LSBsb25nX2RhdGEgJT4lDQogICAgICBncm91cF9ieSgNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgSUQsDQogICAgICAgIGF0dHJpYnV0ZSwNCiAgICAgICAgbGV2ZWwNCiAgICAgICkgJT4lDQogICAgICBzdW1tYXJpc2UoDQogICAgICAgIHlfc3VtID0gc3VtKHNlbGVjdGVkKSwNCiAgICAgICAgbl9vYnMgPSBuKCksDQogICAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICAgICkgJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGNlbGxfa2V5ID0gcGFzdGUoDQogICAgICAgICAgYXR0cmlidXRlLA0KICAgICAgICAgIGxldmVsLA0KICAgICAgICAgIHNlcCA9ICJcciINCiAgICAgICAgKQ0KICAgICAgKQ0KDQogICAgY29uZGl0aW9uX29iamVjdHMgPC0gbGFwcGx5KA0KICAgICAgMjo1LA0KICAgICAgZnVuY3Rpb24obl92YWx1ZSkgew0KICAgICAgICBjb25kaXRpb25fZGF0YSA8LSByZXNwb25kZW50X2NlbGwgJT4lDQogICAgICAgICAgZmlsdGVyKA0KICAgICAgICAgICAgcGFydHlfbiA9PSBuX3ZhbHVlDQogICAgICAgICAgKQ0KDQogICAgICAgIGlkX3ZhbHVlcyA8LSBzb3J0KA0KICAgICAgICAgIHVuaXF1ZShjb25kaXRpb25fZGF0YSRJRCkNCiAgICAgICAgKQ0KICAgICAgICBuX2lkcyA8LSBsZW5ndGgoaWRfdmFsdWVzKQ0KICAgICAgICBuX2NlbGxzIDwtIG5yb3coZXhwZWN0ZWRfY2VsbHMpDQoNCiAgICAgICAgaWYgKG5faWRzID09IDApIHsNCiAgICAgICAgICBzdG9wKCJDaGVjayIpDQogICAgICAgIH0NCg0KICAgICAgICB5X21hdHJpeCA8LSBtYXRyaXgoDQogICAgICAgICAgMCwNCiAgICAgICAgICBucm93ID0gbl9pZHMsDQogICAgICAgICAgbmNvbCA9IG5fY2VsbHMsDQogICAgICAgICAgZGltbmFtZXMgPSBsaXN0KA0KICAgICAgICAgICAgaWRfdmFsdWVzLA0KICAgICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkNCiAgICAgICAgICApDQogICAgICAgICkNCg0KICAgICAgICBuX21hdHJpeCA8LSBtYXRyaXgoDQogICAgICAgICAgMCwNCiAgICAgICAgICBucm93ID0gbl9pZHMsDQogICAgICAgICAgbmNvbCA9IG5fY2VsbHMsDQogICAgICAgICAgZGltbmFtZXMgPSBsaXN0KA0KICAgICAgICAgICAgaWRfdmFsdWVzLA0KICAgICAgICAgICAgZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXkNCiAgICAgICAgICApDQogICAgICAgICkNCg0KICAgICAgICByb3dfaW5kZXggPC0gbWF0Y2goDQogICAgICAgICAgY29uZGl0aW9uX2RhdGEkSUQsDQogICAgICAgICAgaWRfdmFsdWVzDQogICAgICAgICkNCiAgICAgICAgY29sdW1uX2luZGV4IDwtIG1hdGNoKA0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJGNlbGxfa2V5LA0KICAgICAgICAgIGV4cGVjdGVkX2NlbGxzJGNlbGxfa2V5DQogICAgICAgICkNCg0KICAgICAgICB5X21hdHJpeFtjYmluZChyb3dfaW5kZXgsIGNvbHVtbl9pbmRleCldIDwtDQogICAgICAgICAgY29uZGl0aW9uX2RhdGEkeV9zdW0NCiAgICAgICAgbl9tYXRyaXhbY2JpbmQocm93X2luZGV4LCBjb2x1bW5faW5kZXgpXSA8LQ0KICAgICAgICAgIGNvbmRpdGlvbl9kYXRhJG5fb2JzDQoNCiAgICAgICAgaWYgKGFueShjb2xTdW1zKG5fbWF0cml4KSA9PSAwKSkgew0KICAgICAgICAgIG1pc3NpbmdfY2VsbHMgPC0gZXhwZWN0ZWRfY2VsbHMkY2VsbF9rZXlbDQogICAgICAgICAgICBjb2xTdW1zKG5fbWF0cml4KSA9PSAwDQogICAgICAgICAgXQ0KDQogICAgICAgICAgc3RvcCgiQ2hlY2sgYXR0cmlidXRlcyIpDQogICAgICAgIH0NCg0KICAgICAgICBsaXN0KA0KICAgICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLA0KICAgICAgICAgIGlkcyA9IGlkX3ZhbHVlcywNCiAgICAgICAgICBjZWxsX2luZm8gPSBleHBlY3RlZF9jZWxscywNCiAgICAgICAgICB5X21hdHJpeCA9IHlfbWF0cml4LA0KICAgICAgICAgIG5fbWF0cml4ID0gbl9tYXRyaXgNCiAgICAgICAgKQ0KICAgICAgfQ0KICAgICkNCg0KICAgIG5hbWVzKGNvbmRpdGlvbl9vYmplY3RzKSA8LSBhcy5jaGFyYWN0ZXIoMjo1KQ0KDQogICAgbGlzdCgNCiAgICAgIGN1ZV9tYXAgPSBjdWVfbWFwLA0KICAgICAgYXR0cmlidXRlcyA9IGF0dHJpYnV0ZXMsDQogICAgICBjb25kaXRpb25zID0gY29uZGl0aW9uX29iamVjdHMNCiAgICApDQogIH0NCg0KICBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcyA8LSBmdW5jdGlvbigNCiAgICAgIHByZXBhcmVkLA0KICAgICAgY2x1c3Rlcl93ZWlnaHRzID0gTlVMTA0KICApIHsNCiAgICBjb25kaXRpb25fcmVzdWx0cyA8LSBsYXBwbHkoDQogICAgICBuYW1lcyhwcmVwYXJlZCRjb25kaXRpb25zKSwNCiAgICAgIGZ1bmN0aW9uKGNvbmRpdGlvbl9uYW1lKSB7DQogICAgICAgIG9iamVjdCA8LSBwcmVwYXJlZCRjb25kaXRpb25zW1tjb25kaXRpb25fbmFtZV1dDQoNCiAgICAgICAgaWYgKGlzLm51bGwoY2x1c3Rlcl93ZWlnaHRzKSkgew0KICAgICAgICAgIHdlaWdodHMgPC0gcmVwKA0KICAgICAgICAgICAgMSwNCiAgICAgICAgICAgIGxlbmd0aChvYmplY3QkaWRzKQ0KICAgICAgICAgICkNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICB3ZWlnaHRzIDwtIGNsdXN0ZXJfd2VpZ2h0c1tbY29uZGl0aW9uX25hbWVdXQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGxlbmd0aCh3ZWlnaHRzKSAhPSBsZW5ndGgob2JqZWN0JGlkcykpIHsNCiAgICAgICAgICBzdG9wKCJDaGVjayIpDQogICAgICAgIH0NCg0KICAgICAgICBudW1lcmF0b3IgPC0gYXMubnVtZXJpYygNCiAgICAgICAgICBjcm9zc3Byb2QoDQogICAgICAgICAgICB3ZWlnaHRzLA0KICAgICAgICAgICAgb2JqZWN0JHlfbWF0cml4DQogICAgICAgICAgKQ0KICAgICAgICApDQoNCiAgICAgICAgZGVub21pbmF0b3IgPC0gYXMubnVtZXJpYygNCiAgICAgICAgICBjcm9zc3Byb2QoDQogICAgICAgICAgICB3ZWlnaHRzLA0KICAgICAgICAgICAgb2JqZWN0JG5fbWF0cml4DQogICAgICAgICAgKQ0KICAgICAgICApDQoNCiAgICAgICAgaWYgKGFueShkZW5vbWluYXRvciA8PSAwKSkgew0KICAgICAgICAgIHN0b3AoIkNoZWNrIGF0dHJpYnV0ZXMiKQ0KICAgICAgICB9DQoNCiAgICAgICAgbWFyZ2luYWxfbWVhbnMgPC0gbnVtZXJhdG9yIC8gZGVub21pbmF0b3INCg0KICAgICAgICBtbV90YWJsZSA8LSBvYmplY3QkY2VsbF9pbmZvICU+JQ0KICAgICAgICAgIHRyYW5zbXV0ZSgNCiAgICAgICAgICAgIHBhcnR5X24gPSBvYmplY3QkcGFydHlfbiwNCiAgICAgICAgICAgIGF0dHJpYnV0ZSwNCiAgICAgICAgICAgIGxldmVsLA0KICAgICAgICAgICAgbWFyZ2luYWxfbWVhbiA9IG1hcmdpbmFsX21lYW5zDQogICAgICAgICAgKQ0KDQogICAgICAgIGF0dHJpYnV0ZV90YWJsZSA8LSBtbV90YWJsZSAlPiUNCiAgICAgICAgICBncm91cF9ieSgNCiAgICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgICBhdHRyaWJ1dGUNCiAgICAgICAgICApICU+JQ0KICAgICAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICAgICAgICBtZWFuX2Fic29sdXRlX3BhaXJ3aXNlX2RpZmZlcmVuY2UoDQogICAgICAgICAgICAgICAgbWFyZ2luYWxfbWVhbg0KICAgICAgICAgICAgICApLA0KICAgICAgICAgICAgbl9sZXZlbHMgPSBuKCksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgICAgICAgKSAlPiUNCiAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICBjdWVfZmFtaWx5ID0gdW5uYW1lKA0KICAgICAgICAgICAgICBwcmVwYXJlZCRjdWVfbWFwW2F0dHJpYnV0ZV0NCiAgICAgICAgICAgICksDQogICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkgPSAxIC8gcGFydHlfbiwNCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlIC8NCiAgICAgICAgICAgICAgICBiYXNlbGluZV9zZWxlY3Rpb25fcHJvYmFiaWxpdHkNCiAgICAgICAgICApDQoNCiAgICAgICAgY3VlX3RhYmxlX2xvbmcgPC0gYXR0cmlidXRlX3RhYmxlICU+JQ0KICAgICAgICAgIGdyb3VwX2J5KA0KICAgICAgICAgICAgcGFydHlfbiwNCiAgICAgICAgICAgIGN1ZV9mYW1pbHkNCiAgICAgICAgICApICU+JQ0KICAgICAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2UgPSBtZWFuKA0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlLA0KICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUNCiAgICAgICAgICAgICksDQogICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0gbWVhbigNCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICAgICAgICkNCg0KICAgICAgICBwYXJ0eV90YWJsZSA8LSBjdWVfdGFibGVfbG9uZyAlPiUNCiAgICAgICAgICBmaWx0ZXIoDQogICAgICAgICAgICBjdWVfZmFtaWx5ID09ICJwYXJ0eSINCiAgICAgICAgICApICU+JQ0KICAgICAgICAgIHRyYW5zbXV0ZSgNCiAgICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgICAgICAgaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkDQogICAgICAgICAgKQ0KDQogICAgICAgIGVjb25vbWljX3RhYmxlIDwtIGN1ZV90YWJsZV9sb25nICU+JQ0KICAgICAgICAgIGZpbHRlcigNCiAgICAgICAgICAgIGN1ZV9mYW1pbHkgPT0gImVjb25vbWljIg0KICAgICAgICAgICkgJT4lDQogICAgICAgICAgdHJhbnNtdXRlKA0KICAgICAgICAgICAgcGFydHlfbiwNCiAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICAgICAgICBpbXBvcnRhbmNlX3BhaXJ3aXNlLA0KICAgICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9DQogICAgICAgICAgICAgIGltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQNCiAgICAgICAgICApDQoNCiAgICAgICAgY3VlX3RhYmxlIDwtIGZ1bGxfam9pbigNCiAgICAgICAgICBwYXJ0eV90YWJsZSwNCiAgICAgICAgICBlY29ub21pY190YWJsZSwNCiAgICAgICAgICBieSA9ICJwYXJ0eV9uIg0KICAgICAgICApICU+JQ0KICAgICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgIGJhc2VsaW5lX3NlbGVjdGlvbl9wcm9iYWJpbGl0eSA9IDEgLyBwYXJ0eV9uLA0KDQogICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlID0NCiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSArDQogICAgICAgICAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UsDQoNCiAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAgICAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkICsNCiAgICAgICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCg0KICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0gaWZfZWxzZSgNCiAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZSA+IDAsDQogICAgICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgLw0KICAgICAgICAgICAgICAgIHRvdGFsX2ltcG9ydGFuY2VfcGFpcndpc2UsDQogICAgICAgICAgICAgIE5BX3JlYWxfDQogICAgICAgICAgICApLA0KDQogICAgICAgICAgICByZWxhdGl2ZV9lY29ub21pY193ZWlnaHRfcGFpcndpc2UgPQ0KICAgICAgICAgICAgICAxIC0gcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlLA0KDQogICAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQgPSBpZl9lbHNlKA0KICAgICAgICAgICAgICB0b3RhbF9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID4gMCwNCiAgICAgICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCAvDQogICAgICAgICAgICAgICAgdG90YWxfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICAgICAgTkFfcmVhbF8NCiAgICAgICAgICAgICksDQoNCiAgICAgICAgICAgIHJlbGF0aXZlX2Vjb25vbWljX3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCA9DQogICAgICAgICAgICAgIDEgLSByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2VfYWRqdXN0ZWQsDQoNCiAgICAgICAgICAgIGFkanVzdG1lbnRfaWRlbnRpdHlfZGlmZmVyZW5jZSA9DQogICAgICAgICAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZV9hZGp1c3RlZCAtDQogICAgICAgICAgICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlDQogICAgICAgICAgKQ0KDQogICAgICAgIGlmICgNCiAgICAgICAgICBhbnkoDQogICAgICAgICAgICBhYnMoY3VlX3RhYmxlJGFkanVzdG1lbnRfaWRlbnRpdHlfZGlmZmVyZW5jZSkgPiAxZS0xMCwNCiAgICAgICAgICAgIG5hLnJtID0gVFJVRQ0KICAgICAgICAgICkNCiAgICAgICAgKSB7DQogICAgICAgICAgc3RvcCgiQ2hlY2sgcmVsYXRpdmUgd2VpZ2h0IikNCiAgICAgICAgfQ0KDQogICAgICAgIGxpc3QoDQogICAgICAgICAgbWFyZ2luYWxfbWVhbnMgPSBtbV90YWJsZSwNCiAgICAgICAgICBhdHRyaWJ1dGVfaW1wb3J0YW5jZSA9IGF0dHJpYnV0ZV90YWJsZSwNCiAgICAgICAgICBjdWVfaW1wb3J0YW5jZSA9IGN1ZV90YWJsZQ0KICAgICAgICApDQogICAgICB9DQogICAgKQ0KDQogICAgbGlzdCgNCiAgICAgIG1hcmdpbmFsX21lYW5zID0gYmluZF9yb3dzKA0KICAgICAgICBsYXBwbHkoDQogICAgICAgICAgY29uZGl0aW9uX3Jlc3VsdHMsDQogICAgICAgICAgZnVuY3Rpb24oeCkgeCRtYXJnaW5hbF9tZWFucw0KICAgICAgICApDQogICAgICApLA0KICAgICAgYXR0cmlidXRlX2ltcG9ydGFuY2UgPSBiaW5kX3Jvd3MoDQogICAgICAgIGxhcHBseSgNCiAgICAgICAgICBjb25kaXRpb25fcmVzdWx0cywNCiAgICAgICAgICBmdW5jdGlvbih4KSB4JGF0dHJpYnV0ZV9pbXBvcnRhbmNlDQogICAgICAgICkNCiAgICAgICksDQogICAgICBjdWVfaW1wb3J0YW5jZSA9IGJpbmRfcm93cygNCiAgICAgICAgbGFwcGx5KA0KICAgICAgICAgIGNvbmRpdGlvbl9yZXN1bHRzLA0KICAgICAgICAgIGZ1bmN0aW9uKHgpIHgkY3VlX2ltcG9ydGFuY2UNCiAgICAgICAgKQ0KICAgICAgKSAlPiUNCiAgICAgICAgYXJyYW5nZShwYXJ0eV9uKQ0KICAgICkNCiAgfQ0KDQogIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMgPC0gZnVuY3Rpb24oY3VlX2ltcG9ydGFuY2UpIHsNCiAgICBjdWVfaW1wb3J0YW5jZSA8LSBjdWVfaW1wb3J0YW5jZSAlPiUNCiAgICAgIGFycmFuZ2UocGFydHlfbikNCg0KICAgIGlmICghaWRlbnRpY2FsKGN1ZV9pbXBvcnRhbmNlJHBhcnR5X24sIDI6NSkpIHsNCiAgICAgIHN0b3AoIkNoZWNrIHJlbGF0aXZlIHdlaWdodCIpDQogICAgfQ0KDQogICAgeCA8LSBjdWVfaW1wb3J0YW5jZSRwYXJ0eV9uDQoNCiAgICBjKA0KICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0NCiAgICAgICAgbGluZWFyX3Nsb3BlKA0KICAgICAgICAgIGN1ZV9pbXBvcnRhbmNlJHJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICB4DQogICAgICAgICksDQoNCiAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICBsaW5lYXJfc2xvcGUoDQogICAgICAgICAgY3VlX2ltcG9ydGFuY2UkZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICB4DQogICAgICAgICkNCiAgICApDQogIH0NCg0KICBydW5fcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCA8LSBmdW5jdGlvbigNCiAgICAgIHByZXBhcmVkLA0KICAgICAgQiwNCiAgICAgIHNlZWQsDQogICAgICBwcm9ncmVzc19ldmVyeSA9IDEwMA0KICApIHsNCiAgICBzZXQuc2VlZChzZWVkKQ0KDQogICAgY29uZGl0aW9uX3Jlc3VsdHMgPC0gdmVjdG9yKA0KICAgICAgImxpc3QiLA0KICAgICAgQg0KICAgICkNCg0KICAgIHNsb3BlX25hbWVzIDwtIGMoDQogICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICkNCg0KICAgIHNsb3BlX21hdHJpeCA8LSBtYXRyaXgoDQogICAgICBOQV9yZWFsXywNCiAgICAgIG5yb3cgPSBCLA0KICAgICAgbmNvbCA9IGxlbmd0aChzbG9wZV9uYW1lcyksDQogICAgICBkaW1uYW1lcyA9IGxpc3QoDQogICAgICAgIE5VTEwsDQogICAgICAgIHNsb3BlX25hbWVzDQogICAgICApDQogICAgKQ0KDQogICAgZm9yIChiIGluIHNlcV9sZW4oQikpIHsNCiAgICAgIGNsdXN0ZXJfd2VpZ2h0cyA8LSBsYXBwbHkoDQogICAgICAgIHByZXBhcmVkJGNvbmRpdGlvbnMsDQogICAgICAgIGZ1bmN0aW9uKG9iamVjdCkgew0KICAgICAgICAgIG5faWRzIDwtIGxlbmd0aChvYmplY3QkaWRzKQ0KDQogICAgICAgICAgc2FtcGxlZF9wb3NpdGlvbnMgPC0gc2FtcGxlLmludCgNCiAgICAgICAgICAgIG4gPSBuX2lkcywNCiAgICAgICAgICAgIHNpemUgPSBuX2lkcywNCiAgICAgICAgICAgIHJlcGxhY2UgPSBUUlVFDQogICAgICAgICAgKQ0KDQogICAgICAgICAgdGFidWxhdGUoDQogICAgICAgICAgICBzYW1wbGVkX3Bvc2l0aW9ucywNCiAgICAgICAgICAgIG5iaW5zID0gbl9pZHMNCiAgICAgICAgICApDQogICAgICAgIH0NCiAgICAgICkNCg0KICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfaW5kaWNlcygNCiAgICAgICAgcHJlcGFyZWQgPSBwcmVwYXJlZCwNCiAgICAgICAgY2x1c3Rlcl93ZWlnaHRzID0gY2x1c3Rlcl93ZWlnaHRzDQogICAgICApDQoNCiAgICAgIGNvbmRpdGlvbl9yZXN1bHRzW1tiXV0gPC0NCiAgICAgICAgYm9vdHN0cmFwX2VzdGltYXRlcyRjdWVfaW1wb3J0YW5jZSAlPiUNCiAgICAgICAgc2VsZWN0KA0KICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSwNCiAgICAgICAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlLA0KICAgICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQsDQogICAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCwNCiAgICAgICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UNCiAgICAgICAgKSAlPiUNCiAgICAgICAgbXV0YXRlKA0KICAgICAgICAgIGJvb3RzdHJhcF9yZXBsaWNhdGlvbiA9IGIsDQogICAgICAgICAgLmJlZm9yZSA9IDENCiAgICAgICAgKQ0KDQogICAgICBzbG9wZV9tYXRyaXhbYiwgXSA8LSBlc3RpbWF0ZV9yZWxhdGl2ZV9jdWVfc2xvcGVzKA0KICAgICAgICBib290c3RyYXBfZXN0aW1hdGVzJGN1ZV9pbXBvcnRhbmNlDQogICAgICApDQoNCiAgICAgIGlmICgNCiAgICAgICAgcHJvZ3Jlc3NfZXZlcnkgPiAwICYmDQogICAgICAgIChiICUlIHByb2dyZXNzX2V2ZXJ5ID09IDAgfHwgYiA9PSBCKQ0KICAgICAgKSB7DQogICAgICAgIG1lc3NhZ2UoIkJvb3RzdHJhcDogIiwgYiwgIi8iLCBCKQ0KICAgICAgfQ0KICAgIH0NCg0KICAgIGxpc3QoDQogICAgICBjb25kaXRpb25fZXN0aW1hdGVzID0gYmluZF9yb3dzKA0KICAgICAgICBjb25kaXRpb25fcmVzdWx0cw0KICAgICAgKSwNCiAgICAgIHNsb3BlcyA9IGFzX3RpYmJsZSgNCiAgICAgICAgc2xvcGVfbWF0cml4DQogICAgICApICU+JQ0KICAgICAgICBtdXRhdGUoDQogICAgICAgICAgYm9vdHN0cmFwX3JlcGxpY2F0aW9uID0gcm93X251bWJlcigpLA0KICAgICAgICAgIC5iZWZvcmUgPSAxDQogICAgICAgICkNCiAgICApDQogIH0NCg0KICBzdW1tYXJpc2VfY29uZGl0aW9uX2ludGVydmFscyA8LSBmdW5jdGlvbigNCiAgICAgIG9ic2VydmVkX2N1ZV9pbXBvcnRhbmNlLA0KICAgICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzDQogICkgew0KICAgIHN0YXRpc3RpY3MgPC0gYygNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiDQogICAgKQ0KDQogICAgb2JzZXJ2ZWRfbG9uZyA8LSBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgYWxsX29mKHN0YXRpc3RpY3MpDQogICAgICApICU+JQ0KICAgICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgICBjb2xzID0gYWxsX29mKHN0YXRpc3RpY3MpLA0KICAgICAgICBuYW1lc190byA9ICJzdGF0aXN0aWMiLA0KICAgICAgICB2YWx1ZXNfdG8gPSAiZXN0aW1hdGUiDQogICAgICApDQoNCiAgICBib290c3RyYXBfbG9uZyA8LSBib290c3RyYXBfY29uZGl0aW9uX3Jlc3VsdHMgJT4lDQogICAgICBwaXZvdF9sb25nZXIoDQogICAgICAgIGNvbHMgPSBhbGxfb2Yoc3RhdGlzdGljcyksDQogICAgICAgIG5hbWVzX3RvID0gInN0YXRpc3RpYyIsDQogICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSINCiAgICAgICkgJT4lDQogICAgICBncm91cF9ieSgNCiAgICAgICAgcGFydHlfbiwNCiAgICAgICAgc3RhdGlzdGljDQogICAgICApICU+JQ0KICAgICAgc3VtbWFyaXNlKA0KICAgICAgICBjb25mX2xvdyA9IHNhZmVfcXVhbnRpbGUoDQogICAgICAgICAgdmFsdWUsDQogICAgICAgICAgMC4wMjUNCiAgICAgICAgKSwNCiAgICAgICAgY29uZl9oaWdoID0gc2FmZV9xdWFudGlsZSgNCiAgICAgICAgICB2YWx1ZSwNCiAgICAgICAgICAwLjk3NQ0KICAgICAgICApLA0KICAgICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgICApDQoNCiAgICBvYnNlcnZlZF9sb25nICU+JQ0KICAgICAgbGVmdF9qb2luKA0KICAgICAgICBib290c3RyYXBfbG9uZywNCiAgICAgICAgYnkgPSBjKA0KICAgICAgICAgICJwYXJ0eV9uIiwNCiAgICAgICAgICAic3RhdGlzdGljIg0KICAgICAgICApDQogICAgICApDQogIH0NCg0KICBzdW1tYXJpc2Vfc2xvcGVfaW5mZXJlbmNlIDwtIGZ1bmN0aW9uKA0KICAgICAgb2JzZXJ2ZWRfc2xvcGVzLA0KICAgICAgYm9vdHN0cmFwX3Nsb3Blcw0KICApIHsNCiAgICBzdGF0aXN0aWNfbmFtZXMgPC0gbmFtZXMob2JzZXJ2ZWRfc2xvcGVzKQ0KDQogICAgbWFwX2RmcigNCiAgICAgIHN0YXRpc3RpY19uYW1lcywNCiAgICAgIGZ1bmN0aW9uKHN0YXRpc3RpY19uYW1lKSB7DQogICAgICAgIGJvb3RzdHJhcF92YWx1ZXMgPC0gYm9vdHN0cmFwX3Nsb3Blc1tbc3RhdGlzdGljX25hbWVdXQ0KICAgICAgICBib290c3RyYXBfdmFsdWVzIDwtIGJvb3RzdHJhcF92YWx1ZXNbDQogICAgICAgICAgaXMuZmluaXRlKGJvb3RzdHJhcF92YWx1ZXMpDQogICAgICAgIF0NCg0KICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPC0gY2FzZV93aGVuKA0KICAgICAgICAgIHN0YXRpc3RpY19uYW1lID09DQogICAgICAgICAgICAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIgfiAibmVnYXRpdmUiLA0KICAgICAgICAgIHN0YXRpc3RpY19uYW1lICVpbiUgYygNCiAgICAgICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICAgICAgICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiLA0KICAgICAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiDQogICAgICAgICAgKSB+ICJwb3NpdGl2ZSIsDQogICAgICAgICAgVFJVRSB+ICJub25lIg0KICAgICAgICApDQoNCiAgICAgICAgYW5hbHlzaXNfcm9sZSA8LSBjYXNlX3doZW4oDQogICAgICAgICAgc3RhdGlzdGljX25hbWUgJWluJSBjKA0KICAgICAgICAgICAgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiLA0KICAgICAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiDQogICAgICAgICAgKSB+ICJleHBsb3JhdG9yeV9jaG9pY2Vfc2V0X2FkanVzdGVkIiwNCiAgICAgICAgICBzdGF0aXN0aWNfbmFtZSA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiB+DQogICAgICAgICAgICAiZGVyaXZlZF9yZWxhdGl2ZV9zaGFyZSIsDQogICAgICAgICAgVFJVRSB+ICJtYW51c2NyaXB0X3ByaW1hcnlfdW5hZGp1c3RlZCINCiAgICAgICAgKQ0KDQogICAgICAgIGVzdGltYXRlIDwtIHVubmFtZSgNCiAgICAgICAgICBvYnNlcnZlZF9zbG9wZXNbW3N0YXRpc3RpY19uYW1lXV0NCiAgICAgICAgKQ0KDQogICAgICAgIHRpYmJsZSgNCiAgICAgICAgICBzdHVkeSA9ICJTdHVkeSAzIiwNCiAgICAgICAgICBzdGF0aXN0aWMgPSBzdGF0aXN0aWNfbmFtZSwNCiAgICAgICAgICBlc3RpbWF0ZSA9IGVzdGltYXRlLA0KICAgICAgICAgIGNvbmZfbG93ID0gc2FmZV9xdWFudGlsZSgNCiAgICAgICAgICAgIGJvb3RzdHJhcF92YWx1ZXMsDQogICAgICAgICAgICAwLjAyNQ0KICAgICAgICAgICksDQogICAgICAgICAgY29uZl9oaWdoID0gc2FmZV9xdWFudGlsZSgNCiAgICAgICAgICAgIGJvb3RzdHJhcF92YWx1ZXMsDQogICAgICAgICAgICAwLjk3NQ0KICAgICAgICAgICksDQogICAgICAgICAgcF92YWx1ZV90d29fc2lkZWQgPQ0KICAgICAgICAgICAgYm9vdHN0cmFwX3R3b19zaWRlZF9wKA0KICAgICAgICAgICAgICBib290c3RyYXBfdmFsdWVzDQogICAgICAgICAgICApLA0KICAgICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9IGV4cGVjdGVkX2RpcmVjdGlvbiwNCiAgICAgICAgICBhbmFseXNpc19yb2xlID0gYW5hbHlzaXNfcm9sZSwNCiAgICAgICAgICBlc3RpbWF0ZV9pbl9leHBlY3RlZF9kaXJlY3Rpb24gPSBjYXNlX3doZW4oDQogICAgICAgICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gInBvc2l0aXZlIiB+IGVzdGltYXRlID4gMCwNCiAgICAgICAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9PSAibmVnYXRpdmUiIH4gZXN0aW1hdGUgPCAwLA0KICAgICAgICAgICAgVFJVRSB+IE5BDQogICAgICAgICAgKQ0KICAgICAgICApDQogICAgICB9DQogICAgKQ0KICB9DQoNCiAgcmVsYXRpdmVfY3VlX3ByZXBhcmVkIDwtIHByZXBhcmVfcmVsYXRpdmVfY3VlX2FuYWx5c2lzKA0KICAgIGRhdGEgPSBjb25qb2ludF9hbGxfbSwNCiAgICBjdWVfbWFwID0gcmVsYXRpdmVfY3VlX21hcA0KICApDQoNCiAgcmVsYXRpdmVfY3VlX29ic2VydmVkIDwtIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9pbmRpY2VzKA0KICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkDQogICkNCg0KICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzIDwtIGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9zbG9wZXMoDQogICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRtYXJnaW5hbF9tZWFucywNCiAgICAic3R1ZHkzX3JlbGF0aXZlX2N1ZV9tYXJnaW5hbF9tZWFucy5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRhdHRyaWJ1dGVfaW1wb3J0YW5jZSwNCiAgICAic3R1ZHkzX3JlbGF0aXZlX2N1ZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS5jc3YiDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRjdWVfaW1wb3J0YW5jZSwNCiAgICAic3R1ZHkzX3JlbGF0aXZlX2N1ZV9pbXBvcnRhbmNlX2FuZF93ZWlnaHQuY3N2Ig0KICApDQoNCiAgcmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlIDwtIGZpbGUucGF0aCgNCiAgICBvdXRwdXRfZGlyLA0KICAgIHBhc3RlMCgNCiAgICAgICJzdHVkeTNfcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXBfIiwNCiAgICAgIHVuaWZpZWRfY29uZmlnJGN1ZV9pbXBvcnRhbmNlX21ldHJpY192ZXJzaW9uLA0KICAgICAgIl9CIiwNCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiwNCiAgICAgICIuY3N2Ig0KICAgICkNCiAgKQ0KDQogIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlIDwtIGZpbGUucGF0aCgNCiAgICBvdXRwdXRfZGlyLA0KICAgIHBhc3RlMCgNCiAgICAgICJzdHVkeTNfcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcF8iLA0KICAgICAgdW5pZmllZF9jb25maWckY3VlX2ltcG9ydGFuY2VfbWV0cmljX3ZlcnNpb24sDQogICAgICAiX0IiLA0KICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CLA0KICAgICAgIi5jc3YiDQogICAgKQ0KICApDQoNCiAgdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCA8LQ0KICAgICFyZXJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwICYmDQogICAgZmlsZS5leGlzdHMocmVsYXRpdmVfY29uZGl0aW9uX2Jvb3RzdHJhcF9maWxlKSAmJg0KICAgIGZpbGUuZXhpc3RzKHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlKQ0KDQogIGlmICh1c2Vfc2F2ZWRfcmVsYXRpdmVfYm9vdHN0cmFwKSB7DQogICAgbWVzc2FnZSgiQm9vdHN0cmFwIGNhY2hlIikNCg0KICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwIDwtIHJlYWRyOjpyZWFkX2NzdigNCiAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9ib290c3RyYXBfZmlsZSwNCiAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UNCiAgICApDQoNCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwIDwtIHJlYWRyOjpyZWFkX2NzdigNCiAgICAgIHJlbGF0aXZlX3Nsb3BlX2Jvb3RzdHJhcF9maWxlLA0KICAgICAgc2hvd19jb2xfdHlwZXMgPSBGQUxTRQ0KICAgICkNCg0KICAgIHNhdmVkX0JfY29uZGl0aW9uIDwtIG5fZGlzdGluY3QoDQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24NCiAgICApDQogICAgc2F2ZWRfQl9zbG9wZSA8LSBuX2Rpc3RpbmN0KA0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCRib290c3RyYXBfcmVwbGljYXRpb24NCiAgICApDQoNCiAgICBpZiAoDQogICAgICBzYXZlZF9CX2NvbmRpdGlvbiAhPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgfHwNCiAgICAgIHNhdmVkX0Jfc2xvcGUgIT0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9CDQogICAgKSB7DQogICAgICBtZXNzYWdlKCJCb290c3RyYXAgY2FjaGUiKQ0KICAgICAgdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCA8LSBGQUxTRQ0KICAgIH0NCiAgfQ0KDQogIGlmICghdXNlX3NhdmVkX3JlbGF0aXZlX2Jvb3RzdHJhcCkgew0KICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAgPC0gcnVuX3JlbGF0aXZlX2N1ZV9ib290c3RyYXAoDQogICAgICBwcmVwYXJlZCA9IHJlbGF0aXZlX2N1ZV9wcmVwYXJlZCwNCiAgICAgIEIgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IsDQogICAgICBzZWVkID0gcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkLA0KICAgICAgcHJvZ3Jlc3NfZXZlcnkgPSByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3Byb2dyZXNzX2V2ZXJ5DQogICAgKQ0KDQogICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAgPC0NCiAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXAkY29uZGl0aW9uX2VzdGltYXRlcw0KDQogICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2Jvb3RzdHJhcCA8LQ0KICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcCRzbG9wZXMNCg0KICAgIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2Jvb3RzdHJhcCwNCiAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9ib290c3RyYXBfZmlsZQ0KICAgICkNCg0KICAgIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwLA0KICAgICAgcmVsYXRpdmVfc2xvcGVfYm9vdHN0cmFwX2ZpbGUNCiAgICApDQogIH0NCg0KICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyA8LSBzdW1tYXJpc2VfY29uZGl0aW9uX2ludGVydmFscygNCiAgICBvYnNlcnZlZF9jdWVfaW1wb3J0YW5jZSA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsDQogICAgYm9vdHN0cmFwX2NvbmRpdGlvbl9yZXN1bHRzID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25fYm9vdHN0cmFwDQogICkNCg0KICByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlIDwtIHN1bW1hcmlzZV9zbG9wZV9pbmZlcmVuY2UoDQogICAgb2JzZXJ2ZWRfc2xvcGVzID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZF9zbG9wZXMsDQogICAgYm9vdHN0cmFwX3Nsb3BlcyA9DQogICAgICByZWxhdGl2ZV9jdWVfc2xvcGVfYm9vdHN0cmFwDQogICkNCg0KICB3cml0ZV9jc3Zfc2FmZWx5KA0KICAgIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzLA0KICAgICJzdHVkeTNfcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMuY3N2Ig0KICApDQoNCiAgd3JpdGVfY3N2X3NhZmVseSgNCiAgICByZWxhdGl2ZV9jdWVfc2xvcGVfaW5mZXJlbmNlLA0KICAgICJzdHVkeTNfcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZS5jc3YiDQogICkNCg0KICByZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQgPC0gcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSAlPiUNCiAgICBmaWx0ZXIoDQogICAgICBzdGF0aXN0aWMgPT0NCiAgICAgICAgInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSINCiAgICApDQoNCiAgY2F0KCJcblN0dWR5IDPvvJrnm7jlr77mr5Tph43jga7nt5rlvaLlgr7lkJFcbiIpDQogIHByaW50KHJlbGF0aXZlX2N1ZV9wcmltYXJ5X3Jlc3VsdCkNCg0KDQogIHJlbGF0aXZlX3hfb2Zmc2V0IDwtIDAuMDc1DQoNCiAgcmVsYXRpdmVfcGFuZWxfYV9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQ0KICAgIGZpbHRlcigNCiAgICAgIHN0YXRpc3RpYyAlaW4lIGMoDQogICAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwNCiAgICAgICAgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiDQogICAgICApDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBjdWVfZmFtaWx5ID0gcmVjb2RlKA0KICAgICAgICBzdGF0aXN0aWMsDQogICAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UgPSAi5pS/5YWa5ZCN5omL44GM44GL44KKIiwNCiAgICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLntYzmuIjmiYvjgYzjgYvjgooiDQogICAgICApLA0KICAgICAgY3VlX2ZhbWlseSA9IGZhY3RvcigNCiAgICAgICAgY3VlX2ZhbWlseSwNCiAgICAgICAgbGV2ZWxzID0gYygNCiAgICAgICAgICAi5pS/5YWa5ZCN5omL44GM44GL44KKIiwNCiAgICAgICAgICAi57WM5riI5omL44GM44GL44KKIg0KICAgICAgICApDQogICAgICApLA0KICAgICAgeF9wbG90ID0gY2FzZV93aGVuKA0KICAgICAgICBjdWVfZmFtaWx5ID09ICLmlL/lhZrlkI3miYvjgYzjgYvjgooiIH4NCiAgICAgICAgICBwYXJ0eV9uICsgcmVsYXRpdmVfeF9vZmZzZXQsDQogICAgICAgIGN1ZV9mYW1pbHkgPT0gIue1jOa4iOaJi+OBjOOBi+OCiiIgfg0KICAgICAgICAgIHBhcnR5X24gLSByZWxhdGl2ZV94X29mZnNldCwNCiAgICAgICAgVFJVRSB+IGFzLm51bWVyaWMocGFydHlfbikNCiAgICAgICksDQogICAgICB2YWx1ZV9sYWJlbCA9IHNwcmludGYoDQogICAgICAgICIlLjNmIiwNCiAgICAgICAgZXN0aW1hdGUNCiAgICAgICkNCiAgICApDQoNCiAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhIDwtIHJlbGF0aXZlX2N1ZV9jb25kaXRpb25faW50ZXJ2YWxzICU+JQ0KICAgIGZpbHRlcigNCiAgICAgIHN0YXRpc3RpYyA9PQ0KICAgICAgICAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIg0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgdmFsdWVfbGFiZWwgPSBzcHJpbnRmKA0KICAgICAgICAiJS4xZiUlIiwNCiAgICAgICAgMTAwICogZXN0aW1hdGUNCiAgICAgICkNCiAgICApDQoNCiAgcmVsYXRpdmVfYWRqdXN0ZWRfbGFiZWxfbWFwIDwtIHJlbGF0aXZlX3BhbmVsX2FfZGF0YSAlPiUNCiAgICBkaXN0aW5jdCgNCiAgICAgIHN0YXRpc3RpYywNCiAgICAgIGN1ZV9mYW1pbHkNCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHN0YXRpc3RpYyA9IHBhc3RlMCgNCiAgICAgICAgc3RhdGlzdGljLA0KICAgICAgICAiX2FkanVzdGVkIg0KICAgICAgKSwNCiAgICAgIGN1ZV9mYW1pbHkgPSBhcy5jaGFyYWN0ZXIoDQogICAgICAgIGN1ZV9mYW1pbHkNCiAgICAgICkNCiAgICApDQoNCiAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWRfZGF0YSA8LSByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscyAlPiUNCiAgICBmaWx0ZXIoDQogICAgICBzdGF0aXN0aWMgJWluJSBjKA0KICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsDQogICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgbGVmdF9qb2luKA0KICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfbGFiZWxfbWFwLA0KICAgICAgYnkgPSAic3RhdGlzdGljIg0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgY3VlX2ZhbWlseSA9IGZhY3RvcigNCiAgICAgICAgY3VlX2ZhbWlseSwNCiAgICAgICAgbGV2ZWxzID0gbGV2ZWxzKA0KICAgICAgICAgIHJlbGF0aXZlX3BhbmVsX2FfZGF0YSRjdWVfZmFtaWx5DQogICAgICAgICkNCiAgICAgICksDQogICAgICB4X3Bsb3QgPSBpZl9lbHNlKA0KICAgICAgICBhcy5pbnRlZ2VyKGN1ZV9mYW1pbHkpID09IDFMLA0KICAgICAgICBwYXJ0eV9uICsgcmVsYXRpdmVfeF9vZmZzZXQsDQogICAgICAgIHBhcnR5X24gLSByZWxhdGl2ZV94X29mZnNldA0KICAgICAgKSwNCiAgICAgIHZhbHVlX2xhYmVsID0gc3ByaW50ZigNCiAgICAgICAgIiUuMWYlJSIsDQogICAgICAgIDEwMCAqIGVzdGltYXRlDQogICAgICApDQogICAgKQ0KDQogIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXggPC0gaWYgKA0KICAgICLmlL/lhZrlkI3miYvjgYzjgYvjgooiICVpbiUNCiAgICAgIGxldmVscyhyZWxhdGl2ZV9wYW5lbF9hX2RhdGEkY3VlX2ZhbWlseSkNCiAgKSB7DQogICAgIumBuOaKnuiCoiINCiAgfSBlbHNlIHsNCiAgICAi5pS/5YWaIg0KICB9DQoNCiAgcmVsYXRpdmVfY29uZGl0aW9uX2F4aXNfdGl0bGUgPC0gaWYgKA0KICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXggPT0gIumBuOaKnuiCoiINCiAgKSB7DQogICAgIuaUv+ayu+e1jOa4iOeKtuazgeOBrumBuOaKnuiCouaVsCINCiAgfSBlbHNlIHsNCiAgICAi5pS/5YWa6YG45oqe6IKi5pWwIg0KICB9DQoNCiAgcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5IDwtIGlmICgNCiAgICAuUGxhdGZvcm0kT1MudHlwZSA9PSAid2luZG93cyINCiAgKSB7DQogICAgIll1IEdvdGhpYyINCiAgfSBlbHNlIHsNCiAgICAic2FucyINCiAgfQ0KDQogIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3IDwtIHRoZW1lX2J3KA0KICAgIGJhc2Vfc2l6ZSA9IDEyLA0KICAgIGJhc2VfZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5DQogICkgKw0KICAgIHRoZW1lKA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoDQogICAgICAgIGxpbmV3aWR0aCA9IDAuMzAsDQogICAgICAgIGNvbG9yID0gImdyZXk4OCINCiAgICAgICksDQogICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoDQogICAgICAgIGxpbmV3aWR0aCA9IDAuNjUsDQogICAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICAgKSwNCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgICApLA0KICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgICApLA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgc2l6ZSA9IDEyLjUsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsDQogICAgICAgIGhqdXN0ID0gMA0KICAgICAgKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICAgIHNpemUgPSA5LjUsDQogICAgICAgIGhqdXN0ID0gMCwNCiAgICAgICAgbWFyZ2luID0gbWFyZ2luKA0KICAgICAgICAgIGIgPSA4DQogICAgICAgICkNCiAgICAgICksDQogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwNCiAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gImNlbnRlciIsDQogICAgICBsZWdlbmQua2V5LndpZHRoID0gZ3JpZDo6dW5pdCgNCiAgICAgICAgMS4yNSwNCiAgICAgICAgImNtIg0KICAgICAgKSwNCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKA0KICAgICAgICA4LA0KICAgICAgICAxMCwNCiAgICAgICAgOCwNCiAgICAgICAgOA0KICAgICAgKQ0KICAgICkNCg0KICByZWxhdGl2ZV9wYW5lbF9hIDwtIGdncGxvdCgNCiAgICByZWxhdGl2ZV9wYW5lbF9hX2RhdGEsDQogICAgYWVzKA0KICAgICAgeCA9IHhfcGxvdCwNCiAgICAgIHkgPSBlc3RpbWF0ZSwNCiAgICAgIGdyb3VwID0gY3VlX2ZhbWlseSwNCiAgICAgIGxpbmV0eXBlID0gY3VlX2ZhbWlseQ0KICAgICkNCiAgKSArDQogICAgZ2VvbV9saW5lKA0KICAgICAgbGluZXdpZHRoID0gMC44MCwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXIoDQogICAgICBhZXMoDQogICAgICAgIHltaW4gPSBjb25mX2xvdywNCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaA0KICAgICAgKSwNCiAgICAgIHdpZHRoID0gMC4wNzUsDQogICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9sYWJlbCgNCiAgICAgIGFlcygNCiAgICAgICAgbGFiZWwgPSB2YWx1ZV9sYWJlbA0KICAgICAgKSwNCiAgICAgIHNpemUgPSAzLjU1LA0KICAgICAgZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5LA0KICAgICAgbGFiZWwuc2l6ZSA9IDAsDQogICAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdCgNCiAgICAgICAgMC4xMiwNCiAgICAgICAgImxpbmVzIg0KICAgICAgKSwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgdmFsdWVzID0gYygNCiAgICAgICAgIuaUv+WFmuWQjeaJi+OBjOOBi+OCiiIgPSAic29saWQiLA0KICAgICAgICAi57WM5riI5omL44GM44GL44KKIiA9ICJkYXNoZWQiDQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgYnJlYWtzID0gMjo1LA0KICAgICAgbGFiZWxzID0gcGFzdGUwKA0KICAgICAgICAyOjUsDQogICAgICAgICLpgbjmip7ogqIiDQogICAgICApLA0KICAgICAgbGltaXRzID0gYygNCiAgICAgICAgMS43MiwNCiAgICAgICAgNS4yOA0KICAgICAgKQ0KICAgICkgKw0KICAgIHNjYWxlX3lfY29udGludW91cygNCiAgICAgIGxhYmVscyA9IGxhYmVsX251bWJlcigNCiAgICAgICAgYWNjdXJhY3kgPSAwLjAwNQ0KICAgICAgKSwNCiAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbigNCiAgICAgICAgbXVsdCA9IGMoDQogICAgICAgICAgMC4wNywNCiAgICAgICAgICAwLjEwDQogICAgICAgICkNCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiQe+8muS4oeaJi+OBjOOBi+OCiuOBrue1tuWvvueahOmHjeimgeW6piIsDQogICAgICBzdWJ0aXRsZSA9ICIiLA0KICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLA0KICAgICAgeSA9ICLmiYvjgYzjgYvjgorph43opoHluqYiLA0KICAgICAgbGluZXR5cGUgPSBOVUxMDQogICAgKSArDQogICAgZ3VpZGVzKA0KICAgICAgbGluZXR5cGUgPSBndWlkZV9sZWdlbmQoDQogICAgICAgIG92ZXJyaWRlLmFlcyA9IGxpc3QoDQogICAgICAgICAgbGluZXdpZHRoID0gMC45MA0KICAgICAgICApDQogICAgICApDQogICAgKSArDQogICAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncNCg0KICByZWxhdGl2ZV9hZGp1c3RlZF9saW5ldHlwZXMgPC0gc2V0TmFtZXMoDQogICAgYygNCiAgICAgICJzb2xpZCIsDQogICAgICAiZGFzaGVkIg0KICAgICksDQogICAgbGV2ZWxzKA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWRfZGF0YSRjdWVfZmFtaWx5DQogICAgKQ0KICApDQoNCiAgcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQgPC0gZ2dwbG90KA0KICAgIHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGEsDQogICAgYWVzKA0KICAgICAgeCA9IHhfcGxvdCwNCiAgICAgIHkgPSBlc3RpbWF0ZSwNCiAgICAgIGdyb3VwID0gY3VlX2ZhbWlseSwNCiAgICAgIGxpbmV0eXBlID0gY3VlX2ZhbWlseQ0KICAgICkNCiAgKSArDQogICAgZ2VvbV9saW5lKA0KICAgICAgbGluZXdpZHRoID0gMC44MCwNCiAgICAgIGNvbG9yID0gImJsYWNrIg0KICAgICkgKw0KICAgIGdlb21fZXJyb3JiYXIoDQogICAgICBhZXMoDQogICAgICAgIHltaW4gPSBjb25mX2xvdywNCiAgICAgICAgeW1heCA9IGNvbmZfaGlnaA0KICAgICAgKSwNCiAgICAgIHdpZHRoID0gMC4wNzUsDQogICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9sYWJlbCgNCiAgICAgIGFlcygNCiAgICAgICAgbGFiZWwgPSB2YWx1ZV9sYWJlbA0KICAgICAgKSwNCiAgICAgIHNpemUgPSAzLjU1LA0KICAgICAgZmFtaWx5ID0gcmVsYXRpdmVfZmlndXJlX2ZvbnRfZmFtaWx5LA0KICAgICAgbGFiZWwuc2l6ZSA9IDAsDQogICAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdCgNCiAgICAgICAgMC4xMiwNCiAgICAgICAgImxpbmVzIg0KICAgICAgKSwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKA0KICAgICAgdmFsdWVzID0gcmVsYXRpdmVfYWRqdXN0ZWRfbGluZXR5cGVzDQogICAgKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgICAgYnJlYWtzID0gMjo1LA0KICAgICAgbGFiZWxzID0gcGFzdGUwKA0KICAgICAgICAyOjUsDQogICAgICAgIHJlbGF0aXZlX2NvbmRpdGlvbl9zdWZmaXgNCiAgICAgICksDQogICAgICBsaW1pdHMgPSBjKA0KICAgICAgICAxLjcyLA0KICAgICAgICA1LjI4DQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICAgbGFiZWxzID0gbGFiZWxfcGVyY2VudCgNCiAgICAgICAgYWNjdXJhY3kgPSAxDQogICAgICApLA0KICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKA0KICAgICAgICBtdWx0ID0gYygNCiAgICAgICAgICAwLjA3LA0KICAgICAgICAgIDAuMTANCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICJB77ya6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqmIiwNCiAgICAgIHN1YnRpdGxlID0NCiAgICAgICAgIuacquiqv+aVtOmHjeimgeW6piDDtyDlubPlnYfpgbjmip7norrnjofvvIgx77yP6YG45oqe6IKi5pWw77yJIiwNCiAgICAgIHggPSByZWxhdGl2ZV9jb25kaXRpb25fYXhpc190aXRsZSwNCiAgICAgIHkgPSAi5bmz5Z2H6YG45oqe56K6546H44Gr5a++44GZ44KL5rC05rqW6ZaT5beuIiwNCiAgICAgIGxpbmV0eXBlID0gTlVMTA0KICAgICkgKw0KICAgIGd1aWRlcygNCiAgICAgIGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKA0KICAgICAgICBvdmVycmlkZS5hZXMgPSBsaXN0KA0KICAgICAgICAgIGxpbmV3aWR0aCA9IDAuOTANCiAgICAgICAgKQ0KICAgICAgKQ0KICAgICkgKw0KICAgIHJlbGF0aXZlX3RoZW1lX2phcGFuZXNlX2J3DQoNCiAgcmVsYXRpdmVfYl9yYW5nZSA8LSByYW5nZSgNCiAgICBjKA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhJGNvbmZfbG93LA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYl9kYXRhJGNvbmZfaGlnaCwNCiAgICAgIDAuNQ0KICAgICksDQogICAgbmEucm0gPSBUUlVFDQogICkNCg0KICByZWxhdGl2ZV9iX3BhZGRpbmcgPC0gbWF4KA0KICAgIDAuMDI1LA0KICAgIDAuMTAgKiBkaWZmKHJlbGF0aXZlX2JfcmFuZ2UpDQogICkNCg0KICByZWxhdGl2ZV9iX2xvd2VyIDwtIG1heCgNCiAgICAwLA0KICAgIGZsb29yKA0KICAgICAgMjAgKg0KICAgICAgICAocmVsYXRpdmVfYl9yYW5nZVsxXSAtIHJlbGF0aXZlX2JfcGFkZGluZykNCiAgICApIC8gMjANCiAgKQ0KDQogIHJlbGF0aXZlX2JfdXBwZXIgPC0gbWluKA0KICAgIDEsDQogICAgY2VpbGluZygNCiAgICAgIDIwICoNCiAgICAgICAgKHJlbGF0aXZlX2JfcmFuZ2VbMl0gKyByZWxhdGl2ZV9iX3BhZGRpbmcpDQogICAgKSAvIDIwDQogICkNCg0KICBpZiAocmVsYXRpdmVfYl9sb3dlciA+PSByZWxhdGl2ZV9iX3VwcGVyKSB7DQogICAgcmVsYXRpdmVfYl9sb3dlciA8LSBtYXgoDQogICAgICAwLA0KICAgICAgcmVsYXRpdmVfYl9sb3dlciAtIDAuMDUNCiAgICApDQogICAgcmVsYXRpdmVfYl91cHBlciA8LSBtaW4oDQogICAgICAxLA0KICAgICAgcmVsYXRpdmVfYl91cHBlciArIDAuMDUNCiAgICApDQogIH0NCg0KICByZWxhdGl2ZV9wYW5lbF9iIDwtIGdncGxvdCgNCiAgICByZWxhdGl2ZV9wYW5lbF9iX2RhdGEsDQogICAgYWVzKA0KICAgICAgeCA9IHBhcnR5X24sDQogICAgICB5ID0gZXN0aW1hdGUNCiAgICApDQogICkgKw0KICAgIGdlb21faGxpbmUoDQogICAgICB5aW50ZXJjZXB0ID0gMC41LA0KICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNTUsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX2xpbmUoDQogICAgICBsaW5ld2lkdGggPSAwLjgwLA0KICAgICAgY29sb3IgPSAiYmxhY2siDQogICAgKSArDQogICAgZ2VvbV9lcnJvcmJhcigNCiAgICAgIGFlcygNCiAgICAgICAgeW1pbiA9IGNvbmZfbG93LA0KICAgICAgICB5bWF4ID0gY29uZl9oaWdoDQogICAgICApLA0KICAgICAgd2lkdGggPSAwLjA3NSwNCiAgICAgIGxpbmV3aWR0aCA9IDAuODAsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBnZW9tX2xhYmVsKA0KICAgICAgYWVzKA0KICAgICAgICBsYWJlbCA9IHZhbHVlX2xhYmVsDQogICAgICApLA0KICAgICAgc2l6ZSA9IDMuNTUsDQogICAgICBmYW1pbHkgPSByZWxhdGl2ZV9maWd1cmVfZm9udF9mYW1pbHksDQogICAgICBsYWJlbC5zaXplID0gMCwNCiAgICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KA0KICAgICAgICAwLjEyLA0KICAgICAgICAibGluZXMiDQogICAgICApLA0KICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICBjb2xvciA9ICJibGFjayINCiAgICApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgICBicmVha3MgPSAyOjUsDQogICAgICBsYWJlbHMgPSBwYXN0ZTAoDQogICAgICAgIDI6NSwNCiAgICAgICAgIumBuOaKnuiCoiINCiAgICAgICksDQogICAgICBsaW1pdHMgPSBjKA0KICAgICAgICAxLjcyLA0KICAgICAgICA1LjI4DQogICAgICApDQogICAgKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICAgYnJlYWtzID0gc2VxKA0KICAgICAgICByZWxhdGl2ZV9iX2xvd2VyLA0KICAgICAgICByZWxhdGl2ZV9iX3VwcGVyLA0KICAgICAgICBieSA9IDAuMDUNCiAgICAgICksDQogICAgICBsYWJlbHMgPSBsYWJlbF9wZXJjZW50KA0KICAgICAgICBhY2N1cmFjeSA9IDENCiAgICAgICksDQogICAgICBleHBhbmQgPSBleHBhbnNpb24oDQogICAgICAgIG11bHQgPSBjKA0KICAgICAgICAgIDAuMDUsDQogICAgICAgICAgMC4wOA0KICAgICAgICApDQogICAgICApDQogICAgKSArDQogICAgY29vcmRfY2FydGVzaWFuKA0KICAgICAgeWxpbSA9IGMoDQogICAgICAgIHJlbGF0aXZlX2JfbG93ZXIsDQogICAgICAgIHJlbGF0aXZlX2JfdXBwZXINCiAgICAgICkNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiQu+8muebuOWvvueahOOBquaUv+WFmuWQjeaJi+OBjOOBi+OCiuOBruavlOmHjSIsDQogICAgICBzdWJ0aXRsZSA9DQogICAgICAgICLmlL/lhZrlkI3miYvjgYzjgYvjgorph43opoHluqYgw7fvvIjmlL/lhZrlkI3miYvjgYzjgYvjgorph43opoHluqbvvIvntYzmuIjmiYvjgYzjgYvjgorph43opoHluqbvvIkiLA0KICAgICAgeCA9ICLmlL/lhZrpgbjmip7ogqLmlbAiLA0KICAgICAgeSA9ICLnm7jlr77nmoTjgarmlL/lhZrlkI3miYvjgYzjgYvjgormr5Tph40iDQogICAgKSArDQogICAgcmVsYXRpdmVfdGhlbWVfamFwYW5lc2VfYncgKw0KICAgIHRoZW1lKA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiDQogICAgKQ0KDQogIHJlbGF0aXZlX3BhbmVsX2MgPC0gcmVsYXRpdmVfcGFuZWxfYiArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gcGFzdGUwKA0KICAgICAgICAiQu+8muebuOWvvueahOOBqiIsDQogICAgICAgIGxldmVscyhyZWxhdGl2ZV9wYW5lbF9hX2RhdGEkY3VlX2ZhbWlseSlbMV0sDQogICAgICAgICLjga7mr5Tph40iDQogICAgICApDQogICAgKQ0KDQogIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAgPC0gKA0KICAgIHJlbGF0aXZlX3BhbmVsX2EgfA0KICAgICAgcmVsYXRpdmVfcGFuZWxfYg0KICApICsNCiAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KA0KICAgICAgd2lkdGhzID0gYygNCiAgICAgICAgMSwNCiAgICAgICAgMQ0KICAgICAgKQ0KICAgICkNCg0KICBwcmludCgNCiAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwDQogICkNCg0KICBzYXZlX3Bsb3QoDQogICAgImZpZ19zdHVkeTNfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wbmciLA0KICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsDQogICAgd2lkdGggPSAxMS4yLA0KICAgIGhlaWdodCA9IDUuNCwNCiAgICBkcGkgPSA0MDANCiAgKQ0KDQogIGdnc2F2ZSgNCiAgICBmaWxlbmFtZSA9IGZpbGUucGF0aCgNCiAgICAgIG91dHB1dF9kaXIsDQogICAgICAiZmlnX3N0dWR5M19yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBkZiINCiAgICApLA0KICAgIHBsb3QgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2pwLA0KICAgIHdpZHRoID0gMTEuMiwNCiAgICBoZWlnaHQgPSA1LjQsDQogICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsDQogICAgYmcgPSAid2hpdGUiDQogICkNCg0KICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwIDwtICgNCiAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZCB8DQogICAgICByZWxhdGl2ZV9wYW5lbF9jDQogICkgKw0KICAgIHBhdGNod29yazo6cGxvdF9sYXlvdXQoDQogICAgICB3aWR0aHMgPSBjKA0KICAgICAgICAxLA0KICAgICAgICAxDQogICAgICApDQogICAgKQ0KDQogIHByaW50KA0KICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanANCiAgKQ0KDQogIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViIDwtIHBhc3RlMCgNCiAgICAiZmlnX3N0dWR5IiwNCiAgICBzdHJpbmdyOjpzdHJfZXh0cmFjdCgNCiAgICAgIHN0dWR5X2xhYmVsLA0KICAgICAgIlsxMjNdIg0KICAgICksDQogICAgIl9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYnciDQogICkNCg0KICBzYXZlX3Bsb3QoDQogICAgcGFzdGUwKA0KICAgICAgcmVsYXRpdmVfYWRqdXN0ZWRfZmlndXJlX3N0dWIsDQogICAgICAiLnBuZyINCiAgICApLA0KICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanAsDQogICAgd2lkdGggPSAxMS4yLA0KICAgIGhlaWdodCA9IDUuNCwNCiAgICBkcGkgPSA0MDANCiAgKQ0KDQogIGdnc2F2ZSgNCiAgICBmaWxlbmFtZSA9IGZpbGUucGF0aCgNCiAgICAgIG91dHB1dF9kaXIsDQogICAgICBwYXN0ZTAoDQogICAgICAgIHJlbGF0aXZlX2FkanVzdGVkX2ZpZ3VyZV9zdHViLA0KICAgICAgICAiLnBkZiINCiAgICAgICkNCiAgICApLA0KICAgIHBsb3QgPSBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwLA0KICAgIHdpZHRoID0gMTEuMiwNCiAgICBoZWlnaHQgPSA1LjQsDQogICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsDQogICAgYmcgPSAid2hpdGUiDQogICkNCg0KICByZWxhdGl2ZV9jdWVfcmVzdWx0cyA8LSBsaXN0KA0KICAgIHByZXBhcmVkID0gcmVsYXRpdmVfY3VlX3ByZXBhcmVkLA0KICAgIG1hcmdpbmFsX21lYW5zID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9vYnNlcnZlZCRtYXJnaW5hbF9tZWFucywNCiAgICBhdHRyaWJ1dGVfaW1wb3J0YW5jZSA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkYXR0cmlidXRlX2ltcG9ydGFuY2UsDQogICAgY3VlX2ltcG9ydGFuY2UgPQ0KICAgICAgcmVsYXRpdmVfY3VlX29ic2VydmVkJGN1ZV9pbXBvcnRhbmNlLA0KICAgIG9ic2VydmVkX3Nsb3BlcyA9DQogICAgICByZWxhdGl2ZV9jdWVfb2JzZXJ2ZWRfc2xvcGVzLA0KICAgIGNvbmRpdGlvbl9ib290c3RyYXAgPQ0KICAgICAgcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9ib290c3RyYXAsDQogICAgc2xvcGVfYm9vdHN0cmFwID0NCiAgICAgIHJlbGF0aXZlX2N1ZV9zbG9wZV9ib290c3RyYXAsDQogICAgY29uZGl0aW9uX2ludGVydmFscyA9DQogICAgICByZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscywNCiAgICBzbG9wZV9pbmZlcmVuY2UgPQ0KICAgICAgcmVsYXRpdmVfY3VlX3Nsb3BlX2luZmVyZW5jZSwNCiAgICBwcmltYXJ5X3Jlc3VsdCA9DQogICAgICByZWxhdGl2ZV9jdWVfcHJpbWFyeV9yZXN1bHQsDQogICAgcGxvdHMgPSBsaXN0KA0KICAgICAgYWJzb2x1dGVfaW1wb3J0YW5jZSA9IHJlbGF0aXZlX3BhbmVsX2EsDQogICAgICBjaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2UgPQ0KICAgICAgICByZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZCwNCiAgICAgIHJlbGF0aXZlX3BhcnR5X3dlaWdodCA9IHJlbGF0aXZlX3BhbmVsX2IsDQogICAgICByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFuZWxfYyA9DQogICAgICAgIHJlbGF0aXZlX3BhbmVsX2MsDQogICAgICBjb21iaW5lZCA9IGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfanAsDQogICAgICBjb21iaW5lZF93aXRoX2Nob2ljZV9zZXRfYWRqdXN0bWVudCA9DQogICAgICAgIGZpZ3VyZV9yZWxhdGl2ZV93ZWlnaHRfYWRqdXN0ZWRfanANCiAgICApDQogICkNCg0KICBzYXZlUkRTKA0KICAgIHJlbGF0aXZlX2N1ZV9yZXN1bHRzLA0KICAgIGZpbGUgPSBmaWxlLnBhdGgoDQogICAgICBvdXRwdXRfZGlyLA0KICAgICAgInN0dWR5M19yZWxhdGl2ZV9jdWVfcmVzdWx0cy5yZHMiDQogICAgKQ0KICApDQoNCg0KICBzYXZlUkRTKA0KICAgIGxpc3QoDQogICAgICBzZXR0aW5ncyA9IGxpc3QoDQogICAgICAgIGRhdGFfZmlsZSA9IGRhdGFfZmlsZSwNCiAgICAgICAgcmVxdWlyZV9pbml0aWFsX2NvbnNlbnQgPQ0KICAgICAgICAgIHJlcXVpcmVfaW5pdGlhbF9jb25zZW50LA0KICAgICAgICByZXF1aXJlX2ZpbmFsX2NvbnNlbnQgPQ0KICAgICAgICAgIHJlcXVpcmVfZmluYWxfY29uc2VudCwNCiAgICAgICAgcmVxdWlyZV9hdHRlbnRpb25fY2hlY2sgPQ0KICAgICAgICAgIHJlcXVpcmVfYXR0ZW50aW9uX2NoZWNrLA0KICAgICAgICByZXF1aXJlX21hbmlwdWxhdGlvbl9jaGVjayA9DQogICAgICAgICAgcmVxdWlyZV9tYW5pcHVsYXRpb25fY2hlY2ssDQogICAgICAgIHJlcXVpcmVfYWxsX2ZpdmVfdGFza3MgPQ0KICAgICAgICAgIHJlcXVpcmVfYWxsX2ZpdmVfdGFza3MsDQogICAgICAgIHBhcnR5X3JlZmVyZW5jZSA9DQogICAgICAgICAgcGFydHlfcmVmZXJlbmNlLA0KICAgICAgICBwYXJ0eV9sZXZlbHNfdXNlID0NCiAgICAgICAgICBwYXJ0eV9sZXZlbHNfdXNlLA0KICAgICAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX0IgPQ0KICAgICAgICAgIHJlbGF0aXZlX2N1ZV9ib290c3RyYXBfQiwNCiAgICAgICAgcmVsYXRpdmVfY3VlX2Jvb3RzdHJhcF9zZWVkID0NCiAgICAgICAgICByZWxhdGl2ZV9jdWVfYm9vdHN0cmFwX3NlZWQNCiAgICAgICksDQoNCiAgICAgIHNhbXBsZV9mbG93ID0gc2FtcGxlX2Zsb3csDQogICAgICBuX2J5X3BhcnR5ID0gbl9ieV9wYXJ0eSwNCiAgICAgIHZhbGlkX2lkcyA9IHZhbGlkX2lkcywNCg0KICAgICAgY29uam9pbnRfYWxsID0gY29uam9pbnRfYWxsLA0KICAgICAgY29uam9pbnRfYWxsX20gPSBjb25qb2ludF9hbGxfbSwNCiAgICAgIGNvbmpvaW50X2FsbF9jb3YgPSBjb25qb2ludF9hbGxfY292LA0KDQogICAgICBjb3Zhcl9pZCA9IGNvdmFyX2lkLA0KDQogICAgICBtb2RlbHNfYnlfcGFydHlfbl9ub2NvdiA9DQogICAgICAgIG1vZGVsc19ieV9wYXJ0eV9uX25vY292LA0KDQogICAgICBtb2RlbHNfYnlfcGFydHlfbl9jb3YgPQ0KICAgICAgICBtb2RlbHNfYnlfcGFydHlfbl9jb3YsDQoNCiAgICAgIG1faW50ZXJhY3Rpb24gPQ0KICAgICAgICBtX2ludGVyYWN0aW9uLA0KDQogICAgICBtX2xpbmVhcl90cmVuZCA9DQogICAgICAgIG1fbGluZWFyX3RyZW5kLA0KDQogICAgICBtb2RlbHNfY2xvZ2l0X25vY292ID0NCiAgICAgICAgbW9kZWxzX2Nsb2dpdF9ub2NvdiwNCg0KICAgICAgcGFydHlfbWF0Y2ggPSBsaXN0KA0KICAgICAgICBkYXRhID0gY29uam9pbnRfbWF0Y2gsDQogICAgICAgIG1vZGVsc19ieV9uID0NCiAgICAgICAgICBtb2RlbHNfcGFydHlfbWF0Y2hfYnlfbiwNCiAgICAgICAgaW50ZXJhY3Rpb25fbW9kZWwgPQ0KICAgICAgICAgIG1fcGFydHlfbWF0Y2hfaW50ZXJhY3Rpb24NCiAgICAgICksDQoNCiAgICAgIHJlbGF0aXZlX2N1ZSA9IHJlbGF0aXZlX2N1ZV9yZXN1bHRzLA0KDQogICAgICBwbG90cyA9IGxpc3QoDQogICAgICAgIGFtY2VfY292ID0NCiAgICAgICAgICBwX2FtY2VfY292LA0KICAgICAgICBhbWNlX25vY292ID0NCiAgICAgICAgICBwX2FtY2Vfbm9jb3YsDQogICAgICAgIGludGVyYWN0aW9uID0NCiAgICAgICAgICBwX2ludGVyYWN0aW9uLA0KICAgICAgICBsaW5lYXJfdHJlbmQgPQ0KICAgICAgICAgIHBfbGluZWFyX3RyZW5kLA0KICAgICAgICBoZWF0bWFwID0NCiAgICAgICAgICBwX2hlYXRfYW1jZSwNCiAgICAgICAgY2xvZ2l0X29kZHNfcmF0aW8gPQ0KICAgICAgICAgIHBfY2xvZ2l0X29yLA0KICAgICAgICBwYXJ0eV9tYXRjaCA9DQogICAgICAgICAgcF9wYXJ0eV9tYXRjaCwNCiAgICAgICAgcmVsYXRpdmVfY3VlX3dlaWdodCA9DQogICAgICAgICAgZmlndXJlX3JlbGF0aXZlX3dlaWdodF9qcCwNCiAgICAgICAgcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkID0NCiAgICAgICAgICBmaWd1cmVfcmVsYXRpdmVfd2VpZ2h0X2FkanVzdGVkX2pwDQogICAgICApDQogICAgKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJzdHVkeTNfYW5hbHlzaXNfb2JqZWN0cy5yZHMiDQogICAgKQ0KICApDQoNCiAgY2FwdHVyZS5vdXRwdXQoDQogICAgc2Vzc2lvbkluZm8oKSwNCiAgICBmaWxlID0gZmlsZS5wYXRoKA0KICAgICAgb3V0cHV0X2RpciwNCiAgICAgICJzZXNzaW9uSW5mby50eHQiDQogICAgKQ0KICApDQoNCiAgY2F0KA0KICAgICJcblN0dWR5IDPjga7liIbmnpDjgrPjg7zjg4njgYzmnIDlvozjgb7jgaflrozkuobjgZfjgb7jgZfjgZ/jgIJcbiIsDQogICAgIuWHuuWKm+WFiDogIiwNCiAgICBub3JtYWxpemVQYXRoKG91dHB1dF9kaXIpLA0KICAgICJcbiIsDQogICAgc2VwID0gIiINCiAgKQ0KDQogIGVudmlyb25tZW50KCkNCn0pDQpgYGANCg0KIyMgQS41IOijnOmBuuOBq+mWouOBmeOCi+WQhOeoruOBruWGjeePvuOCs+ODvOODiQ0KDQpgYGB7ciBhNS1zdXBwbGVtZW50LWNvZGUsIGV2YWw9cGFyYW1zJHJ1bl9hbmFseXNpcywgcmVzdWx0cz0naGlkZScsIGZpZy5zaG93PSdoaWRlJ30NCg0KIyDoo5zpgbrlhbHpgJrjgrPjg7zjg4kNCnVuaWZpZWRfb3V0cHV0X2RpciA8LSBmaWxlLnBhdGgoDQogIHVuaWZpZWRfY29uZmlnJG91dHB1dF9yb290LA0KICAiX3dvcmtpbmciLA0KICAiY3Jvc3Nfc3R1ZHkiDQopDQpkaXIuY3JlYXRlKHVuaWZpZWRfb3V0cHV0X2Rpciwgc2hvd1dhcm5pbmdzID0gRkFMU0UsIHJlY3Vyc2l2ZSA9IFRSVUUpDQoNCnNhdmVfcGxvdF9ib3RoIDwtIGZ1bmN0aW9uKGZpbGVuYW1lX3N0dWIsIHBsb3QsIHdpZHRoLCBoZWlnaHQsIGRwaSA9IDQwMCkgew0KICBwbmdfZmlsZSA8LSBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCBwYXN0ZTAoZmlsZW5hbWVfc3R1YiwgIi5wbmciKSkNCiAgcGRmX2ZpbGUgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKGZpbGVuYW1lX3N0dWIsICIucGRmIikpDQogIA0KICBnZ3Bsb3QyOjpnZ3NhdmUoDQogICAgZmlsZW5hbWUgPSBwbmdfZmlsZSwNCiAgICBwbG90ID0gcGxvdCwNCiAgICB3aWR0aCA9IHdpZHRoLA0KICAgIGhlaWdodCA9IGhlaWdodCwNCiAgICBkcGkgPSBkcGksDQogICAgYmcgPSAid2hpdGUiDQogICkNCiAgDQogIGdncGxvdDI6Omdnc2F2ZSgNCiAgICBmaWxlbmFtZSA9IHBkZl9maWxlLA0KICAgIHBsb3QgPSBwbG90LA0KICAgIHdpZHRoID0gd2lkdGgsDQogICAgaGVpZ2h0ID0gaGVpZ2h0LA0KICAgIGRldmljZSA9IGdyRGV2aWNlczo6Y2Fpcm9fcGRmLA0KICAgIGJnID0gIndoaXRlIg0KICApDQogIA0KICBpbnZpc2libGUoYyhwbmcgPSBwbmdfZmlsZSwgcGRmID0gcGRmX2ZpbGUpKQ0KfQ0KDQp3cml0ZV9jc3ZfdW5pZmllZCA8LSBmdW5jdGlvbih4LCBmaWxlbmFtZSkgew0KICByZWFkcjo6d3JpdGVfY3N2KA0KICAgIHgsDQogICAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgZmlsZW5hbWUpLA0KICAgIG5hID0gIiINCiAgKQ0KfQ0KDQpzYWZlX2ZpbGVuYW1lIDwtIGZ1bmN0aW9uKHgpIHsNCiAgeCA8LSBpY29udihhcy5jaGFyYWN0ZXIoeCksIGZyb20gPSAiIiwgdG8gPSAiQVNDSUkvL1RSQU5TTElUIikNCiAgeFtpcy5uYSh4KSB8IHggPT0gIiJdIDwtICJncm91cCINCiAgeCA8LSB0b2xvd2VyKHgpDQogIHggPC0gZ3N1YigiW15hLXowLTldKyIsICJfIiwgeCkNCiAgeCA8LSBnc3ViKCJeXyt8XyskIiwgIiIsIHgpDQogIGlmZWxzZSh4ID09ICIiLCAiZ3JvdXAiLCB4KQ0KfQ0KDQp0aWR5X2ZpeGVzdF91bmlmaWVkIDwtIGZ1bmN0aW9uKG1vZGVsKSB7DQogIGN0IDwtIGFzLmRhdGEuZnJhbWUoZml4ZXN0Ojpjb2VmdGFibGUobW9kZWwpKQ0KICBjdCR0ZXJtIDwtIHJvd25hbWVzKGN0KQ0KICANCiAgZXN0aW1hdGVfY29sIDwtIGludGVyc2VjdChjKCJFc3RpbWF0ZSIsICJlc3RpbWF0ZSIpLCBuYW1lcyhjdCkpWzFdDQogIHNlX2NvbCA8LSBpbnRlcnNlY3QoYygiU3RkLiBFcnJvciIsICJTdGQuIGVycm9yIiwgInN0ZC5lcnJvciIpLCBuYW1lcyhjdCkpWzFdDQogIHN0YXRpc3RpY19jb2wgPC0gaW50ZXJzZWN0KGMoInQgdmFsdWUiLCAieiB2YWx1ZSIsICJzdGF0aXN0aWMiKSwgbmFtZXMoY3QpKVsxXQ0KICBwX2NvbCA8LSBpbnRlcnNlY3QoYygiUHIoPnx0fCkiLCAiUHIoPnx6fCkiLCAicC52YWx1ZSIpLCBuYW1lcyhjdCkpWzFdDQogIA0KICBpZiAoDQogICAgaXMubmEoZXN0aW1hdGVfY29sKSB8fA0KICAgIGlzLm5hKHNlX2NvbCkgfHwNCiAgICBpcy5uYShzdGF0aXN0aWNfY29sKSB8fA0KICAgIGlzLm5hKHBfY29sKQ0KICApIHsNCiAgICBzdG9wKCJDaGVjayBkYXRhIikNCiAgfQ0KICANCiAgdGliYmxlOjphc190aWJibGUoY3QpICU+JQ0KICAgIGRwbHlyOjp0cmFuc211dGUoDQogICAgICB0ZXJtID0gdGVybSwNCiAgICAgIGVzdGltYXRlID0gLmRhdGFbW2VzdGltYXRlX2NvbF1dLA0KICAgICAgc3RkLmVycm9yID0gLmRhdGFbW3NlX2NvbF1dLA0KICAgICAgc3RhdGlzdGljID0gLmRhdGFbW3N0YXRpc3RpY19jb2xdXSwNCiAgICAgIHAudmFsdWUgPSAuZGF0YVtbcF9jb2xdXSwNCiAgICAgIGNvbmYubG93ID0gZXN0aW1hdGUgLSAxLjk2ICogc3RkLmVycm9yLA0KICAgICAgY29uZi5oaWdoID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yDQogICAgKQ0KfQ0KDQpzdHVkeV9zcGVjcyA8LSBsaXN0KA0KICBzdHVkeTEgPSBsaXN0KA0KICAgIHN0dWR5X2lkID0gInN0dWR5MSIsDQogICAgc3R1ZHlfbGFiZWwgPSAiU3R1ZHkgMe+8iDIwMjPlubTvvIkiLA0KICAgIGNvbmRpdGlvbl9sYWJlbCA9ICLmlL/lhZrmlbAiLA0KICAgIGVudiA9IHN0dWR5MV9lbnYNCiAgKSwNCiAgc3R1ZHkyID0gbGlzdCgNCiAgICBzdHVkeV9pZCA9ICJzdHVkeTIiLA0KICAgIHN0dWR5X2xhYmVsID0gIlN0dWR5IDLvvIgyMDI25bm077yJIiwNCiAgICBjb25kaXRpb25fbGFiZWwgPSAi5pS/5YWa5pWwIiwNCiAgICBlbnYgPSBzdHVkeTJfZW52DQogICksDQogIHN0dWR5MyA9IGxpc3QoDQogICAgc3R1ZHlfaWQgPSAic3R1ZHkzIiwNCiAgICBzdHVkeV9sYWJlbCA9ICJTdHVkeSAz77yIMjAyNuW5tO+8iSIsDQogICAgY29uZGl0aW9uX2xhYmVsID0gIumBuOaKnuiCouaVsCIsDQogICAgZW52ID0gc3R1ZHkzX2Vudg0KICApDQopDQoNCmV4Y2x1ZGVkX3N1cHBvcnRfY2F0ZWdvcmllcyA8LSBjKA0KICAi44Gd44Gu5LuWIiwNCiAgIuOCj+OBi+OCieOBquOBhCIsDQogICLnrZTjgYjjgarjgYQiLA0KICAi562U44GI44Gf44GP44Gq44GEIiwNCiAgIuasoOaQjeODu+eEoeWbnuetlCINCikNCg0KDQojIOijnOmBukPplqLpgKPjgrPjg7zjg4kNCmJhbGFuY2VfdmFyaWFibGVfbGFiZWxzIDwtIGMoDQogIGZlbWFsZV9pbXAgPSAi5aWz5oCnIiwNCiAgZmVtYWxlX21pc3MgPSAi5oCn5Yil77ya5qyg5pCNIiwNCiAgYWdlX2ltcCA9ICLlubTpvaIiLA0KICBhZ2VfbWlzcyA9ICLlubTpvaLvvJrmrKDmkI0iLA0KICBjb2xsZWdlX2dyYWRfaW1wID0gIjTlubTliLblpKflrabku6XkuIoiLA0KICBjb2xsZWdlX2dyYWRfbWlzcyA9ICLlrabmrbTvvJrmrKDmkI0iLA0KICBpbmNvbWVfZ3Jvc3NfbG9nX2ltcCA9ICLkuJbluK/lubTlj47vvIjlr77mlbDvvIkiLA0KICBpbmNvbWVfZ3Jvc3NfbG9nX21pc3MgPSAi5LiW5biv5bm05Y+O77ya5qyg5pCNIiwNCiAgc2VsZl9pZGVvbG9neV9pbXAgPSAi5bem5Y+z6Ieq5bex5L2N572u44Gl44GRIiwNCiAgc2VsZl9pZGVvbG9neV9taXNzID0gIuW3puWPs+iHquW3seS9jee9ruOBpeOBke+8muasoOaQjSINCikNCg0KbWFrZV9iYWxhbmNlX2Rlc2lnbiA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7DQogIGVudiA8LSBzdHVkeV9zcGVjJGVudg0KICANCiAgYXNzaWdubWVudCA8LSBlbnYkY29uam9pbnRfYWxsICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdChJRCwgcGFydHlfbikgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwNCiAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSkNCiAgICApDQogIA0KICByZXNwb25kZW50IDwtIGVudiRjb3Zhcl9pZCAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKElEID0gYXMuY2hhcmFjdGVyKElEKSkNCiAgDQogIGRhdCA8LSBhc3NpZ25tZW50ICU+JQ0KICAgIGRwbHlyOjpsZWZ0X2pvaW4ocmVzcG9uZGVudCwgYnkgPSAiSUQiKQ0KICANCiAgbnVtZXJpY19jYW5kaWRhdGVzIDwtIGMoDQogICAgImZlbWFsZV9pbXAiLA0KICAgICJmZW1hbGVfbWlzcyIsDQogICAgImFnZV9pbXAiLA0KICAgICJhZ2VfbWlzcyIsDQogICAgImNvbGxlZ2VfZ3JhZF9pbXAiLA0KICAgICJjb2xsZWdlX2dyYWRfbWlzcyIsDQogICAgImluY29tZV9ncm9zc19sb2dfaW1wIiwNCiAgICAiaW5jb21lX2dyb3NzX2xvZ19taXNzIiwNCiAgICAic2VsZl9pZGVvbG9neV9pbXAiLA0KICAgICJzZWxmX2lkZW9sb2d5X21pc3MiDQogICkNCiAgDQogIGZhY3Rvcl9jYW5kaWRhdGVzIDwtIGMoDQogICAgInBhcnR5X3N1cHBvcnRfZiIsDQogICAgInJlZ2lvbiINCiAgKQ0KICANCiAgbnVtZXJpY191c2UgPC0gaW50ZXJzZWN0KG51bWVyaWNfY2FuZGlkYXRlcywgbmFtZXMoZGF0KSkNCiAgZmFjdG9yX3VzZSA8LSBpbnRlcnNlY3QoZmFjdG9yX2NhbmRpZGF0ZXMsIG5hbWVzKGRhdCkpDQogIA0KICBkZXNpZ25fc291cmNlIDwtIGRhdCAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KGRwbHlyOjphbGxfb2YoYyhudW1lcmljX3VzZSwgZmFjdG9yX3VzZSkpKQ0KICANCiAgaWYgKGxlbmd0aChmYWN0b3JfdXNlKSA+IDApIHsNCiAgICBkZXNpZ25fc291cmNlIDwtIGRlc2lnbl9zb3VyY2UgJT4lDQogICAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgICBkcGx5cjo6YWNyb3NzKA0KICAgICAgICAgIGRwbHlyOjphbGxfb2YoZmFjdG9yX3VzZSksDQogICAgICAgICAgfiBmb3JjYXRzOjpmY3RfbmFfdmFsdWVfdG9fbGV2ZWwoYXMuZmFjdG9yKC54KSwgbGV2ZWwgPSAi5qyg5pCN44O754Sh5Zue562UIikNCiAgICAgICAgKQ0KICAgICAgKQ0KICB9DQogIA0KICBtbSA8LSBzdGF0czo6bW9kZWwubWF0cml4KA0KICAgIHN0YXRzOjphcy5mb3JtdWxhKA0KICAgICAgcGFzdGUwKA0KICAgICAgICAifiAwICsgIiwNCiAgICAgICAgcGFzdGUobmFtZXMoZGVzaWduX3NvdXJjZSksIGNvbGxhcHNlID0gIiArICIpDQogICAgICApDQogICAgKSwNCiAgICBkYXRhID0gZGVzaWduX3NvdXJjZQ0KICApDQogIA0KICBtbSA8LSBhcy5kYXRhLmZyYW1lKG1tLCBjaGVjay5uYW1lcyA9IEZBTFNFKQ0KICANCiAga2VlcCA8LSB2YXBwbHkoDQogICAgbW0sDQogICAgZnVuY3Rpb24oeCkgew0KICAgICAgeCA8LSBhcy5udW1lcmljKHgpDQogICAgICBpcy5maW5pdGUoc3RhdHM6OnNkKHgsIG5hLnJtID0gVFJVRSkpICYmIHN0YXRzOjpzZCh4LCBuYS5ybSA9IFRSVUUpID4gMA0KICAgIH0sDQogICAgbG9naWNhbCgxKQ0KICApDQogIA0KICBtbSA8LSBtbVssIGtlZXAsIGRyb3AgPSBGQUxTRV0NCiAgDQogIG1tIDwtIG1tICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBJRCA9IGRhdCRJRCwNCiAgICAgIHBhcnR5X24gPSBkYXQkcGFydHlfbiwNCiAgICAgIC5iZWZvcmUgPSAxDQogICAgKQ0KICANCiAgbG9uZyA8LSBtbSAlPiUNCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKA0KICAgICAgY29scyA9IC1jKElELCBwYXJ0eV9uKSwNCiAgICAgIG5hbWVzX3RvID0gInZhcmlhYmxlIiwNCiAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSINCiAgICApICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBsYWJlbCA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICAgIHZhcmlhYmxlICVpbiUgbmFtZXMoYmFsYW5jZV92YXJpYWJsZV9sYWJlbHMpIH4NCiAgICAgICAgICB1bm5hbWUoYmFsYW5jZV92YXJpYWJsZV9sYWJlbHNbdmFyaWFibGVdKSwNCiAgICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCh2YXJpYWJsZSwgIl5wYXJ0eV9zdXBwb3J0X2YiKSB+DQogICAgICAgICAgcGFzdGUwKA0KICAgICAgICAgICAgIuaUr+aMgeaUv+WFmu+8miIsDQogICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlKHZhcmlhYmxlLCAiXnBhcnR5X3N1cHBvcnRfZiIpDQogICAgICAgICAgKSwNCiAgICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCh2YXJpYWJsZSwgIl5yZWdpb24iKSB+DQogICAgICAgICAgcGFzdGUwKA0KICAgICAgICAgICAgIuWcsOWfn++8miIsDQogICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlKHZhcmlhYmxlLCAiXnJlZ2lvbiIpDQogICAgICAgICAgKSwNCiAgICAgICAgVFJVRSB+IHZhcmlhYmxlDQogICAgICApLA0KICAgICAgc3R1ZHlfaWQgPSBzdHVkeV9zcGVjJHN0dWR5X2lkLA0KICAgICAgc3R1ZHlfbGFiZWwgPSBzdHVkeV9zcGVjJHN0dWR5X2xhYmVsDQogICAgKQ0KICANCiAgbGlzdCgNCiAgICByZXNwb25kZW50ID0gZGF0LA0KICAgIG1hdHJpeCA9IG1tLA0KICAgIGxvbmcgPSBsb25nLA0KICAgIG51bWVyaWNfdXNlID0gbnVtZXJpY191c2UsDQogICAgZmFjdG9yX3VzZSA9IGZhY3Rvcl91c2UNCiAgKQ0KfQ0KDQpwYWlyd2lzZV9zbWRfbXVsdGlhcm0gPC0gZnVuY3Rpb24oYmFsYW5jZV9sb25nKSB7DQogIGdyb3VwcyA8LSBzb3J0KHVuaXF1ZShiYWxhbmNlX2xvbmckcGFydHlfbikpDQogIHBhaXJzIDwtIHV0aWxzOjpjb21ibihncm91cHMsIDIsIHNpbXBsaWZ5ID0gRkFMU0UpDQoNCiAgcHVycnI6Om1hcF9kZnIoDQogICAgcGFpcnMsDQogICAgZnVuY3Rpb24ocGFpcl92YWx1ZSkgew0KICAgICAgYSA8LSBwYWlyX3ZhbHVlWzFdDQogICAgICBiIDwtIHBhaXJfdmFsdWVbMl0NCg0KICAgICAgd2lkZSA8LSBiYWxhbmNlX2xvbmcgJT4lDQogICAgICAgIGRwbHlyOjpmaWx0ZXIocGFydHlfbiAlaW4lIGMoYSwgYikpICU+JQ0KICAgICAgICBkcGx5cjo6Z3JvdXBfYnkodmFyaWFibGUsIGxhYmVsLCBwYXJ0eV9uKSAlPiUNCiAgICAgICAgZHBseXI6OnN1bW1hcmlzZSgNCiAgICAgICAgICBtZWFuID0gbWVhbih2YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICBzZCA9IHN0YXRzOjpzZCh2YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICBuID0gc3VtKCFpcy5uYSh2YWx1ZSkpLA0KICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICAgICAgKSAlPiUNCiAgICAgICAgdGlkeXI6OnBpdm90X3dpZGVyKA0KICAgICAgICAgIG5hbWVzX2Zyb20gPSBwYXJ0eV9uLA0KICAgICAgICAgIHZhbHVlc19mcm9tID0gYyhtZWFuLCBzZCwgbiksDQogICAgICAgICAgbmFtZXNfc2VwID0gIl8iDQogICAgICAgICkNCg0KICAgICAgd2lkZSAlPiUNCiAgICAgICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgICAgICB2YXJpYWJsZSA9IHZhcmlhYmxlLA0KICAgICAgICAgIGxhYmVsID0gbGFiZWwsDQogICAgICAgICAgY29uZGl0aW9uX2EgPSBhLA0KICAgICAgICAgIGNvbmRpdGlvbl9iID0gYiwNCiAgICAgICAgICBjb21wYXJpc29uID0gcGFzdGUwKGEsICIgdnMgIiwgYiksDQogICAgICAgICAgbWVhbl9hID0gLmRhdGFbW3Bhc3RlMCgibWVhbl8iLCBhKV1dLA0KICAgICAgICAgIG1lYW5fYiA9IC5kYXRhW1twYXN0ZTAoIm1lYW5fIiwgYildXSwNCiAgICAgICAgICBzZF9hID0gLmRhdGFbW3Bhc3RlMCgic2RfIiwgYSldXSwNCiAgICAgICAgICBzZF9iID0gLmRhdGFbW3Bhc3RlMCgic2RfIiwgYildXSwNCiAgICAgICAgICBuX2EgPSAuZGF0YVtbcGFzdGUwKCJuXyIsIGEpXV0sDQogICAgICAgICAgbl9iID0gLmRhdGFbW3Bhc3RlMCgibl8iLCBiKV1dLA0KICAgICAgICAgIHBvb2xlZF9zZCA9IHNxcnQoKHNkX2FeMiArIHNkX2JeMikgLyAyKSwNCiAgICAgICAgICBzbWQgPSBkcGx5cjo6aWZfZWxzZSgNCiAgICAgICAgICAgIGlzLmZpbml0ZShwb29sZWRfc2QpICYgcG9vbGVkX3NkID4gMCwNCiAgICAgICAgICAgIChtZWFuX2EgLSBtZWFuX2IpIC8gcG9vbGVkX3NkLA0KICAgICAgICAgICAgTkFfcmVhbF8NCiAgICAgICAgICApLA0KICAgICAgICAgIGFic19zbWQgPSBhYnMoc21kKQ0KICAgICAgICApDQogICAgfQ0KICApDQp9DQoNCm9tbmlidXNfYmFsYW5jZV90ZXN0IDwtIGZ1bmN0aW9uKGJhbGFuY2VfbG9uZykgew0KICBiYWxhbmNlX2xvbmcgJT4lDQogICAgZHBseXI6Omdyb3VwX2J5KHZhcmlhYmxlLCBsYWJlbCkgJT4lDQogICAgZHBseXI6Omdyb3VwX21vZGlmeSgNCiAgICAgIH4gew0KICAgICAgICBkYXQgPC0gLnggJT4lDQogICAgICAgICAgZHBseXI6OmZpbHRlcihpcy5maW5pdGUodmFsdWUpLCAhaXMubmEocGFydHlfbikpDQogICAgICAgIA0KICAgICAgICBwX3ZhbHVlIDwtIHRyeUNhdGNoKA0KICAgICAgICAgIHsNCiAgICAgICAgICAgIG1vZGVsIDwtIHN0YXRzOjpsbSh2YWx1ZSB+IGZhY3RvcihwYXJ0eV9uKSwgZGF0YSA9IGRhdCkNCiAgICAgICAgICAgIGFzLm51bWVyaWMoc3RhdHM6OmFub3ZhKG1vZGVsKVsxLCAiUHIoPkYpIl0pDQogICAgICAgICAgfSwNCiAgICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIE5BX3JlYWxfDQogICAgICAgICkNCiAgICAgICAgDQogICAgICAgIHRpYmJsZTo6dGliYmxlKHBfdmFsdWUgPSBwX3ZhbHVlKQ0KICAgICAgfQ0KICAgICkgJT4lDQogICAgZHBseXI6OnVuZ3JvdXAoKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKHBfaG9sbSA9IHN0YXRzOjpwLmFkanVzdChwX3ZhbHVlLCBtZXRob2QgPSAiaG9sbSIpKQ0KfQ0KDQptYWtlX2JhbGFuY2Vfb3V0cHV0cyA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7DQogIGRlc2lnbiA8LSBtYWtlX2JhbGFuY2VfZGVzaWduKHN0dWR5X3NwZWMpDQogIGxvbmcgPC0gZGVzaWduJGxvbmcNCiAgcGFpcndpc2UgPC0gcGFpcndpc2Vfc21kX211bHRpYXJtKGxvbmcpDQogIG9tbmlidXMgPC0gb21uaWJ1c19iYWxhbmNlX3Rlc3QobG9uZykNCiAgDQogIG1heF9zbWQgPC0gcGFpcndpc2UgJT4lDQogICAgZHBseXI6Omdyb3VwX2J5KHZhcmlhYmxlLCBsYWJlbCkgJT4lDQogICAgZHBseXI6OnN1bW1hcmlzZSgNCiAgICAgIG1heF9hYnNfc21kID0gZHBseXI6OmlmX2Vsc2UoDQogICAgICAgIGFsbChpcy5uYShhYnNfc21kKSksDQogICAgICAgIE5BX3JlYWxfLA0KICAgICAgICBtYXgoYWJzX3NtZCwgbmEucm0gPSBUUlVFKQ0KICAgICAgKSwNCiAgICAgIG1lYW5fYWJzX3NtZCA9IGRwbHlyOjppZl9lbHNlKA0KICAgICAgICBhbGwoaXMubmEoYWJzX3NtZCkpLA0KICAgICAgICBOQV9yZWFsXywNCiAgICAgICAgbWVhbihhYnNfc21kLCBuYS5ybSA9IFRSVUUpDQogICAgICApLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICkNCiAgDQogIGdyb3VwX3N1bW1hcnkgPC0gbG9uZyAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkodmFyaWFibGUsIGxhYmVsLCBwYXJ0eV9uKSAlPiUNCiAgICBkcGx5cjo6c3VtbWFyaXNlKA0KICAgICAgbWVhbiA9IG1lYW4odmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgICBzZCA9IHN0YXRzOjpzZCh2YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIG4gPSBzdW0oIWlzLm5hKHZhbHVlKSksDQogICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgKSAlPiUNCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIoDQogICAgICBuYW1lc19mcm9tID0gcGFydHlfbiwNCiAgICAgIHZhbHVlc19mcm9tID0gYyhtZWFuLCBzZCwgbiksDQogICAgICBuYW1lc19nbHVlID0gInsudmFsdWV9X2NvbmRpdGlvbl97cGFydHlfbn0iDQogICAgKSAlPiUNCiAgICBkcGx5cjo6bGVmdF9qb2luKG1heF9zbWQsIGJ5ID0gYygidmFyaWFibGUiLCAibGFiZWwiKSkgJT4lDQogICAgZHBseXI6OmxlZnRfam9pbihvbW5pYnVzLCBieSA9IGMoInZhcmlhYmxlIiwgImxhYmVsIikpICU+JQ0KICAgIGRwbHlyOjphcnJhbmdlKGRwbHlyOjpkZXNjKG1heF9hYnNfc21kKSkNCiAgDQogIHdyaXRlX2Nzdl91bmlmaWVkKA0KICAgIHBhaXJ3aXNlLA0KICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX2Fzc2lnbm1lbnRfYmFsYW5jZV9wYWlyd2lzZV9zbWQuY3N2IikNCiAgKQ0KICB3cml0ZV9jc3ZfdW5pZmllZCgNCiAgICBncm91cF9zdW1tYXJ5LA0KICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX2Fzc2lnbm1lbnRfYmFsYW5jZV9zdW1tYXJ5LmNzdiIpDQogICkNCiAgDQogIGxvdmVfZGYgPC0gcGFpcndpc2UgJT4lDQogICAgZHBseXI6OmxlZnRfam9pbihtYXhfc21kLCBieSA9IGMoInZhcmlhYmxlIiwgImxhYmVsIikpICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBsYWJlbF9vcmRlcmVkID0gc3RhdHM6OnJlb3JkZXIobGFiZWwsIG1heF9hYnNfc21kKQ0KICAgICkNCiAgDQogIHBfbG92ZSA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoDQogICAgbG92ZV9kZiwNCiAgICBnZ3Bsb3QyOjphZXMoDQogICAgICB4ID0gYWJzX3NtZCwNCiAgICAgIHkgPSBsYWJlbF9vcmRlcmVkDQogICAgKQ0KICApICsNCiAgICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKA0KICAgICAgeGludGVyY2VwdCA9IDAuMTAsDQogICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLA0KICAgICAgbGluZXdpZHRoID0gMC41NQ0KICAgICkgKw0KICAgIGdncGxvdDI6Omdlb21fcG9pbnQoDQogICAgICBhbHBoYSA9IDAuMzAsDQogICAgICBzaXplID0gMS40LA0KICAgICAgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9qaXR0ZXIoaGVpZ2h0ID0gMC4xMCwgd2lkdGggPSAwKQ0KICAgICkgKw0KICAgIGdncGxvdDI6Omdlb21fcG9pbnQoDQogICAgICBkYXRhID0gbWF4X3NtZCAlPiUNCiAgICAgICAgZHBseXI6Om11dGF0ZShsYWJlbF9vcmRlcmVkID0gc3RhdHM6OnJlb3JkZXIobGFiZWwsIG1heF9hYnNfc21kKSksDQogICAgICBnZ3Bsb3QyOjphZXMoDQogICAgICAgIHggPSBtYXhfYWJzX3NtZCwNCiAgICAgICAgeSA9IGxhYmVsX29yZGVyZWQNCiAgICAgICksDQogICAgICBpbmhlcml0LmFlcyA9IEZBTFNFLA0KICAgICAgc2hhcGUgPSAyMSwNCiAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgIHN0cm9rZSA9IDAuOA0KICAgICkgKw0KICAgIGdncGxvdDI6OnNjYWxlX3hfY29udGludW91cygNCiAgICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcyhuID0gNiksDQogICAgICBleHBhbmQgPSBnZ3Bsb3QyOjpleHBhbnNpb24obXVsdCA9IGMoMCwgMC4wNSkpDQogICAgKSArDQogICAgZ2dwbG90Mjo6bGFicygNCiAgICAgIHggPSAi5p2h5Lu26ZaT44Gu57W25a++5qiZ5rqW5YyW5bmz5Z2H5beu77yIfFNNRHzvvIkiLA0KICAgICAgeSA9IE5VTEwsDQogICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgNCiAgICAgICAgc3R1ZHlfc3BlYyRzdHVkeV9sYWJlbCwNCiAgICAgICAgIu+8muWQhOeCueOBr+adoeS7tuODmuOCouOAgeeZveaKnOOBjeeCueOBr+acgOWkp+e1tuWvvlNNRCINCiAgICAgICksDQogICAgICBjYXB0aW9uID0gIuegtOe3muOBryB8U01EfCA9IDAuMTDjgILlpJrnvqTnhKHkvZzngrrlibLku5jjga7jgZ/jgoHjgIEy44O7M+ODuzTjg7s15p2h5Lu244Gu5YWoNuODmuOCouOCkuavlOi8g+OAgiINCiAgICApICsNCiAgICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKw0KICAgIGdncGxvdDI6OnRoZW1lKA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKQ0KICAgICkNCiAgDQogIHNhdmVfcGxvdF9ib3RoKA0KICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX2Fzc2lnbm1lbnRfYmFsYW5jZV9sb3ZlX3Bsb3QiKSwNCiAgICBwX2xvdmUsDQogICAgd2lkdGggPSA5LjIsDQogICAgaGVpZ2h0ID0gbWF4KDYuNSwgMC4yMyAqIGRwbHlyOjpuX2Rpc3RpbmN0KGxvdmVfZGYkbGFiZWwpICsgMi41KQ0KICApDQogIA0KICBzdGFuZGFyZGl6ZWRfbWVhbnMgPC0gbG9uZyAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkodmFyaWFibGUsIGxhYmVsKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgb3ZlcmFsbF9tZWFuID0gbWVhbih2YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIG92ZXJhbGxfc2QgPSBzdGF0czo6c2QodmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgICB2YWx1ZV96ID0gZHBseXI6OmlmX2Vsc2UoDQogICAgICAgIGlzLmZpbml0ZShvdmVyYWxsX3NkKSAmIG92ZXJhbGxfc2QgPiAwLA0KICAgICAgICAodmFsdWUgLSBvdmVyYWxsX21lYW4pIC8gb3ZlcmFsbF9zZCwNCiAgICAgICAgTkFfcmVhbF8NCiAgICAgICkNCiAgICApICU+JQ0KICAgIGRwbHlyOjp1bmdyb3VwKCkgJT4lDQogICAgZHBseXI6Omdyb3VwX2J5KHZhcmlhYmxlLCBsYWJlbCwgcGFydHlfbikgJT4lDQogICAgZHBseXI6OnN1bW1hcmlzZSgNCiAgICAgIG1lYW5feiA9IG1lYW4odmFsdWVfeiwgbmEucm0gPSBUUlVFKSwNCiAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICApDQogIA0KICBncm91cHMgPC0gc29ydCh1bmlxdWUoc3RhbmRhcmRpemVkX21lYW5zJHBhcnR5X24pKQ0KICBkaWFnb25hbF9kZiA8LSBwdXJycjo6bWFwX2RmcigNCiAgICB1dGlsczo6Y29tYm4oZ3JvdXBzLCAyLCBzaW1wbGlmeSA9IEZBTFNFKSwNCiAgICBmdW5jdGlvbihwYWlyX3ZhbHVlKSB7DQogICAgICBhIDwtIHBhaXJfdmFsdWVbMV0NCiAgICAgIGIgPC0gcGFpcl92YWx1ZVsyXQ0KICAgICAgDQogICAgICBzdGFuZGFyZGl6ZWRfbWVhbnMgJT4lDQogICAgICAgIGRwbHlyOjpmaWx0ZXIocGFydHlfbiAlaW4lIGMoYSwgYikpICU+JQ0KICAgICAgICB0aWR5cjo6cGl2b3Rfd2lkZXIoDQogICAgICAgICAgbmFtZXNfZnJvbSA9IHBhcnR5X24sDQogICAgICAgICAgdmFsdWVzX2Zyb20gPSBtZWFuX3osDQogICAgICAgICAgbmFtZXNfcHJlZml4ID0gImNvbmRpdGlvbl8iDQogICAgICAgICkgJT4lDQogICAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgICAgY29uZGl0aW9uX2EgPSBhLA0KICAgICAgICAgIGNvbmRpdGlvbl9iID0gYiwNCiAgICAgICAgICBjb21wYXJpc29uID0gcGFzdGUwKGEsICIgdnMgIiwgYiksDQogICAgICAgICAgeF9tZWFuID0gLmRhdGFbW3Bhc3RlMCgiY29uZGl0aW9uXyIsIGEpXV0sDQogICAgICAgICAgeV9tZWFuID0gLmRhdGFbW3Bhc3RlMCgiY29uZGl0aW9uXyIsIGIpXV0sDQogICAgICAgICAgZGlhZ29uYWxfZGV2aWF0aW9uID0geV9tZWFuIC0geF9tZWFuLA0KICAgICAgICAgIGFic19kaWFnb25hbF9kZXZpYXRpb24gPSBhYnMoZGlhZ29uYWxfZGV2aWF0aW9uKQ0KICAgICAgICApDQogICAgfQ0KICApDQogIA0KICB0b3BfbGFiZWxzIDwtIGRpYWdvbmFsX2RmICU+JQ0KICAgIGRwbHlyOjpncm91cF9ieShjb21wYXJpc29uKSAlPiUNCiAgICBkcGx5cjo6c2xpY2VfbWF4KA0KICAgICAgb3JkZXJfYnkgPSBhYnNfZGlhZ29uYWxfZGV2aWF0aW9uLA0KICAgICAgbiA9IDMsDQogICAgICB3aXRoX3RpZXMgPSBGQUxTRQ0KICAgICkgJT4lDQogICAgZHBseXI6OnVuZ3JvdXAoKQ0KICANCiAgYXhpc19saW1pdCA8LSBtYXgoDQogICAgYWJzKGMoZGlhZ29uYWxfZGYkeF9tZWFuLCBkaWFnb25hbF9kZiR5X21lYW4pKSwNCiAgICBuYS5ybSA9IFRSVUUNCiAgKQ0KICBheGlzX2xpbWl0IDwtIG1heCgwLjEwLCBheGlzX2xpbWl0ICogMS4xNSkNCiAgDQogIHBfZGlhZ29uYWwgPC0gZ2dwbG90Mjo6Z2dwbG90KA0KICAgIGRpYWdvbmFsX2RmLA0KICAgIGdncGxvdDI6OmFlcyh4ID0geF9tZWFuLCB5ID0geV9tZWFuKQ0KICApICsNCiAgICBnZ3Bsb3QyOjpnZW9tX2FibGluZSgNCiAgICAgIGludGVyY2VwdCA9IDAsDQogICAgICBzbG9wZSA9IDEsDQogICAgICBsaW5ld2lkdGggPSAwLjYwLA0KICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIg0KICAgICkgKw0KICAgIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuMjUpICsNCiAgICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjI1KSArDQogICAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc2l6ZSA9IDIuMikgKw0KICAgIGdncGxvdDI6Omdlb21fdGV4dCgNCiAgICAgIGRhdGEgPSB0b3BfbGFiZWxzLA0KICAgICAgZ2dwbG90Mjo6YWVzKGxhYmVsID0gbGFiZWwpLA0KICAgICAgc2l6ZSA9IDIuNiwNCiAgICAgIGNoZWNrX292ZXJsYXAgPSBUUlVFLA0KICAgICAgdmp1c3QgPSAtMC43DQogICAgKSArDQogICAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IGNvbXBhcmlzb24sIG5jb2wgPSAzKSArDQogICAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoDQogICAgICB4bGltID0gYygtYXhpc19saW1pdCwgYXhpc19saW1pdCksDQogICAgICB5bGltID0gYygtYXhpc19saW1pdCwgYXhpc19saW1pdCkNCiAgICApICsNCiAgICBnZ3Bsb3QyOjpsYWJzKA0KICAgICAgeCA9ICLlt6blgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciLA0KICAgICAgeSA9ICLlj7PlgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciLA0KICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoDQogICAgICAgIHN0dWR5X3NwZWMkc3R1ZHlfbGFiZWwsDQogICAgICAgICLvvJo0NeW6pue3muOBi+OCieOBruS5lumbouOBq+OCiOOCi+WJsuS7mOODkOODqeODs+OCueiouuaWrSINCiAgICAgICksDQogICAgICBjYXB0aW9uID0gIuWQhOeCueOBr+WbnuetlOiAheWFseWkiemHj+OBvuOBn+OBr+aUr+aMgeaUv+WFmuODu+WcsOWfn+OBruODgOODn+ODvOWkieaVsOOAgjQ15bqm57ea44Gr6L+R44GE44G744Gp5p2h5Lu26ZaT44Gu5qeL5oiQ44GM6aGe5Ly844CCIg0KICAgICkgKw0KICAgIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsNCiAgICBnZ3Bsb3QyOjp0aGVtZSgNCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksDQogICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZ2dwbG90Mjo6ZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICAgIHN0cmlwLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgICBheGlzLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKQ0KICAgICkNCiAgDQogIHdyaXRlX2Nzdl91bmlmaWVkKA0KICAgIGRpYWdvbmFsX2RmLA0KICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX2Fzc2lnbm1lbnRfYmFsYW5jZV9kaWFnb25hbF9kYXRhLmNzdiIpDQogICkNCiAgDQogIHNhdmVfcGxvdF9ib3RoKA0KICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX2Fzc2lnbm1lbnRfYmFsYW5jZV9kaWFnb25hbF9wbG90IiksDQogICAgcF9kaWFnb25hbCwNCiAgICB3aWR0aCA9IDExLjUsDQogICAgaGVpZ2h0ID0gNy41DQogICkNCiAgDQogIGxpc3QoDQogICAgZGVzaWduID0gZGVzaWduLA0KICAgIHBhaXJ3aXNlX3NtZCA9IHBhaXJ3aXNlLA0KICAgIHN1bW1hcnkgPSBncm91cF9zdW1tYXJ5LA0KICAgIGxvdmVfcGxvdCA9IHBfbG92ZSwNCiAgICBkaWFnb25hbF9kYXRhID0gZGlhZ29uYWxfZGYsDQogICAgZGlhZ29uYWxfcGxvdCA9IHBfZGlhZ29uYWwNCiAgKQ0KfQ0KDQphc3NpZ25tZW50X2JhbGFuY2VfcmVzdWx0cyA8LSBwdXJycjo6bWFwKA0KICBzdHVkeV9zcGVjcywNCiAgbWFrZV9iYWxhbmNlX291dHB1dHMNCikNCg0KDQptYWtlX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9vdXRwdXRzIDwtIGZ1bmN0aW9uKHN0dWR5X3NwZWMpIHsNCiAgZW52IDwtIHN0dWR5X3NwZWMkZW52DQogIGF0dHJpYnV0ZXMgPC0gZW52JGF0dHJfdGVybXMNCiAgDQogIHJhbmRvbWl6YXRpb25fbG9uZyA8LSBlbnYkY29uam9pbnRfYWxsX20gJT4lDQogICAgZHBseXI6OnNlbGVjdCgNCiAgICAgIElELA0KICAgICAgcGFydHlfbiwNCiAgICAgIHRhc2ssDQogICAgICBwcm9maWxlLA0KICAgICAgZHBseXI6OmFsbF9vZihhdHRyaWJ1dGVzKQ0KICAgICkgJT4lDQogICAgdGlkeXI6OnBpdm90X2xvbmdlcigNCiAgICAgIGNvbHMgPSBkcGx5cjo6YWxsX29mKGF0dHJpYnV0ZXMpLA0KICAgICAgbmFtZXNfdG8gPSAiYXR0cmlidXRlIiwNCiAgICAgIHZhbHVlc190byA9ICJsZXZlbCINCiAgICApICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBsZXZlbCA9IGFzLmNoYXJhY3RlcihsZXZlbCksDQogICAgICBwYXJ0eV9uID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocGFydHlfbikpDQogICAgKSAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShsZXZlbCksIGxldmVsICE9ICIiKQ0KICANCiAgZnJlcXVlbmN5IDwtIHJhbmRvbWl6YXRpb25fbG9uZyAlPiUNCiAgICBkcGx5cjo6Y291bnQocGFydHlfbiwgYXR0cmlidXRlLCBsZXZlbCwgbmFtZSA9ICJvYnNlcnZlZF9uIikgJT4lDQogICAgZHBseXI6Omdyb3VwX2J5KHBhcnR5X24sIGF0dHJpYnV0ZSkgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIHRvdGFsX24gPSBzdW0ob2JzZXJ2ZWRfbiksDQogICAgICBuX2xldmVscyA9IGRwbHlyOjpuKCksDQogICAgICBvYnNlcnZlZF9zaGFyZSA9IG9ic2VydmVkX24gLyB0b3RhbF9uLA0KICAgICAgZXhwZWN0ZWRfc2hhcmUgPSAxIC8gbl9sZXZlbHMsDQogICAgICBkZXZpYXRpb24gPSBvYnNlcnZlZF9zaGFyZSAtIGV4cGVjdGVkX3NoYXJlLA0KICAgICAgYWJzX2RldmlhdGlvbiA9IGFicyhkZXZpYXRpb24pDQogICAgKSAlPiUNCiAgICBkcGx5cjo6dW5ncm91cCgpDQogIA0KICB1bmlmb3JtaXR5X3Rlc3RzIDwtIGZyZXF1ZW5jeSAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkocGFydHlfbiwgYXR0cmlidXRlKSAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfbW9kaWZ5KA0KICAgICAgfiB7DQogICAgICAgIHRlc3QgPC0gc3VwcHJlc3NXYXJuaW5ncygNCiAgICAgICAgICBzdGF0czo6Y2hpc3EudGVzdCgNCiAgICAgICAgICAgIHggPSAueCRvYnNlcnZlZF9uLA0KICAgICAgICAgICAgcCA9IHJlcCgxIC8gbnJvdygueCksIG5yb3coLngpKQ0KICAgICAgICAgICkNCiAgICAgICAgKQ0KICAgICAgICB0aWJibGU6OnRpYmJsZSgNCiAgICAgICAgICBjaGlfc3F1YXJlID0gdW5uYW1lKHRlc3Qkc3RhdGlzdGljKSwNCiAgICAgICAgICBkZiA9IHVubmFtZSh0ZXN0JHBhcmFtZXRlciksDQogICAgICAgICAgcF92YWx1ZSA9IHRlc3QkcC52YWx1ZSwNCiAgICAgICAgICBtYXhfYWJzX3NoYXJlX2RldmlhdGlvbiA9IG1heCgueCRhYnNfZGV2aWF0aW9uKQ0KICAgICAgICApDQogICAgICB9DQogICAgKSAlPiUNCiAgICBkcGx5cjo6dW5ncm91cCgpICU+JQ0KICAgIGRwbHlyOjptdXRhdGUocF9ob2xtID0gc3RhdHM6OnAuYWRqdXN0KHBfdmFsdWUsIG1ldGhvZCA9ICJob2xtIikpDQogIA0KICB3cml0ZV9jc3ZfdW5pZmllZCgNCiAgICBmcmVxdWVuY3ksDQogICAgcGFzdGUwKHN0dWR5X3NwZWMkc3R1ZHlfaWQsICJfcHJvZmlsZV9sZXZlbF9yYW5kb21pemF0aW9uX2ZyZXF1ZW5jeS5jc3YiKQ0KICApDQogIHdyaXRlX2Nzdl91bmlmaWVkKA0KICAgIHVuaWZvcm1pdHlfdGVzdHMsDQogICAgcGFzdGUwKHN0dWR5X3NwZWMkc3R1ZHlfaWQsICJfcHJvZmlsZV9sZXZlbF9yYW5kb21pemF0aW9uX3Rlc3RzLmNzdiIpDQogICkNCiAgDQogIHRvcF9mcmVxdWVuY3lfbGFiZWxzIDwtIGZyZXF1ZW5jeSAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkocGFydHlfbiwgYXR0cmlidXRlKSAlPiUNCiAgICBkcGx5cjo6c2xpY2VfbWF4KGFic19kZXZpYXRpb24sIG4gPSAxLCB3aXRoX3RpZXMgPSBGQUxTRSkgJT4lDQogICAgZHBseXI6OnVuZ3JvdXAoKQ0KICANCiAgcF9yYW5kb21pemF0aW9uIDwtIGdncGxvdDI6OmdncGxvdCgNCiAgICBmcmVxdWVuY3ksDQogICAgZ2dwbG90Mjo6YWVzKA0KICAgICAgeCA9IGV4cGVjdGVkX3NoYXJlLA0KICAgICAgeSA9IG9ic2VydmVkX3NoYXJlDQogICAgKQ0KICApICsNCiAgICBnZ3Bsb3QyOjpnZW9tX2FibGluZSgNCiAgICAgIGludGVyY2VwdCA9IDAsDQogICAgICBzbG9wZSA9IDEsDQogICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLA0KICAgICAgbGluZXdpZHRoID0gMC42NQ0KICAgICkgKw0KICAgIGdncGxvdDI6Omdlb21fcG9pbnQoDQogICAgICBnZ3Bsb3QyOjphZXMoc2hhcGUgPSBmYWN0b3IocGFydHlfbikpLA0KICAgICAgc2l6ZSA9IDIuMiwNCiAgICAgIGZpbGwgPSAid2hpdGUiDQogICAgKSArDQogICAgZ2dwbG90Mjo6Z2VvbV90ZXh0KA0KICAgICAgZGF0YSA9IHRvcF9mcmVxdWVuY3lfbGFiZWxzLA0KICAgICAgZ2dwbG90Mjo6YWVzKGxhYmVsID0gbGV2ZWwpLA0KICAgICAgc2l6ZSA9IDIuNCwNCiAgICAgIGNoZWNrX292ZXJsYXAgPSBUUlVFLA0KICAgICAgdmp1c3QgPSAtMC43DQogICAgKSArDQogICAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IGF0dHJpYnV0ZSwgbmNvbCA9IDMpICsNCiAgICBnZ3Bsb3QyOjpjb29yZF9lcXVhbCgpICsNCiAgICBnZ3Bsb3QyOjpsYWJzKA0KICAgICAgeCA9ICLoqK3oqIjkuIrjga7mnJ/lvoXmr5TnjociLA0KICAgICAgeSA9ICLoprPmuKzmr5TnjociLA0KICAgICAgc2hhcGUgPSBzdHVkeV9zcGVjJGNvbmRpdGlvbl9sYWJlbCwNCiAgICAgIHN1YnRpdGxlID0gcGFzdGUwKA0KICAgICAgICBzdHVkeV9zcGVjJHN0dWR5X2xhYmVsLA0KICAgICAgICAi77ya5bGe5oCn5rC05rqW44Gu6Kaz5ris5q+U546H44Go5pyf5b6F5q+U546HIg0KICAgICAgKSwNCiAgICAgIGNhcHRpb24gPSAi5ZCE54K544Gv5bGe5oCn5rC05rqWw5fmnaHku7bjgII0NeW6pue3muOBq+i/keOBhOOBu+OBqeWxnuaAp+awtOa6luOBrueEoeS9nOeCuuaPkOekuuOBjOioreioiOOBqeOBiuOCiuOAgiINCiAgICApICsNCiAgICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMC41KSArDQogICAgZ2dwbG90Mjo6dGhlbWUoDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLA0KICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGdncGxvdDI6OmVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQogICAgICBzdHJpcC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICBheGlzLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKQ0KICAgICkNCiAgDQogIHNhdmVfcGxvdF9ib3RoKA0KICAgIHBhc3RlMChzdHVkeV9zcGVjJHN0dWR5X2lkLCAiX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9kaWFnb25hbF9wbG90IiksDQogICAgcF9yYW5kb21pemF0aW9uLA0KICAgIHdpZHRoID0gMTEsDQogICAgaGVpZ2h0ID0gaWZlbHNlKHN0dWR5X3NwZWMkc3R1ZHlfaWQgPT0gInN0dWR5MyIsIDcuNSwgOC41KQ0KICApDQogIA0KICBsaXN0KA0KICAgIGZyZXF1ZW5jeSA9IGZyZXF1ZW5jeSwNCiAgICB1bmlmb3JtaXR5X3Rlc3RzID0gdW5pZm9ybWl0eV90ZXN0cywNCiAgICBwbG90ID0gcF9yYW5kb21pemF0aW9uDQogICkNCn0NCg0KcHJvZmlsZV9yYW5kb21pemF0aW9uX3Jlc3VsdHMgPC0gcHVycnI6Om1hcCgNCiAgc3R1ZHlfc3BlY3MsDQogIG1ha2VfcHJvZmlsZV9yYW5kb21pemF0aW9uX291dHB1dHMNCikNCg0KDQojIOijnOmBukjplqLpgKPjgrPjg7zjg4kNCm1ha2VfdGVybV9sYWJlbF90YWJsZSA8LSBmdW5jdGlvbihlbnYpIHsNCiAgaWYgKGV4aXN0cygidGVybV9sYWJlbHMiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsNCiAgICBvdXQgPC0gZ2V0KCJ0ZXJtX2xhYmVscyIsIGVudmlyID0gZW52KQ0KICAgIHJlcXVpcmVkIDwtIGMoInRlcm0iLCAiYXR0cmlidXRlIiwgImxhYmVsIikNCiAgICBpZiAoYWxsKHJlcXVpcmVkICVpbiUgbmFtZXMob3V0KSkpIHsNCiAgICAgIHJldHVybihvdXQgJT4lIGRwbHlyOjpzZWxlY3QoZHBseXI6OmFueV9vZihjKHJlcXVpcmVkLCAib3JkZXIiKSkpKQ0KICAgIH0NCiAgfQ0KICANCiAgdGliYmxlOjp0aWJibGUoDQogICAgdGVybSA9IGNoYXJhY3RlcigpLA0KICAgIGF0dHJpYnV0ZSA9IGNoYXJhY3RlcigpLA0KICAgIGxhYmVsID0gY2hhcmFjdGVyKCksDQogICAgb3JkZXIgPSBpbnRlZ2VyKCkNCiAgKQ0KfQ0KDQpydW5fc3VwcG9ydF9hbWNlX2hldGVyb2dlbmVpdHkgPC0gZnVuY3Rpb24oc3R1ZHlfc3BlYykgew0KICBlbnYgPC0gc3R1ZHlfc3BlYyRlbnYNCiAgc3R1ZHlfaWQgPC0gc3R1ZHlfc3BlYyRzdHVkeV9pZA0KICBzdHVkeV9sYWJlbCA8LSBzdHVkeV9zcGVjJHN0dWR5X2xhYmVsDQogIG91dF9kaXIgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKHN0dWR5X2lkLCAiX3BhcnR5X3N1cHBvcnQiKSkNCiAgZGlyLmNyZWF0ZShvdXRfZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkNCiAgDQogIHN1cHBvcnRfaWQgPC0gZW52JGNvdmFyX2lkICU+JQ0KICAgIGRwbHlyOjp0cmFuc211dGUoDQogICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksDQogICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBhcy5jaGFyYWN0ZXIocGFydHlfc3VwcG9ydF9mKQ0KICAgICkgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIHBhcnR5X3N1cHBvcnRfaCA9IGRwbHlyOjpuYV9pZihwYXJ0eV9zdXBwb3J0X2gsICLmrKDmkI3jg7vnhKHlm57nrZQiKQ0KICAgICkNCiAgDQogIGRhdCA8LSBlbnYkY29uam9pbnRfYWxsX20gJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwNCiAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSkNCiAgICApICU+JQ0KICAgIGRwbHlyOjpsZWZ0X2pvaW4oc3VwcG9ydF9pZCwgYnkgPSAiSUQiKSAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyKA0KICAgICAgIWlzLm5hKHBhcnR5X3N1cHBvcnRfaCksDQogICAgICBwYXJ0eV9zdXBwb3J0X2ggIT0gIiIsDQogICAgICAhcGFydHlfc3VwcG9ydF9oICVpbiUgZXhjbHVkZWRfc3VwcG9ydF9jYXRlZ29yaWVzDQogICAgKQ0KICANCiAgc3VwcG9ydF9jb3VudHMgPC0gZGF0ICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdChJRCwgcGFydHlfbiwgcGFydHlfc3VwcG9ydF9oKSAlPiUNCiAgICBkcGx5cjo6Y291bnQocGFydHlfc3VwcG9ydF9oLCBwYXJ0eV9uLCBuYW1lID0gIm5fY29uZGl0aW9uIikgJT4lDQogICAgZHBseXI6Omdyb3VwX2J5KHBhcnR5X3N1cHBvcnRfaCkgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIG5fdG90YWwgPSBzdW0obl9jb25kaXRpb24pLA0KICAgICAgbWluX2NvbmRpdGlvbl9uID0gbWluKG5fY29uZGl0aW9uKSwNCiAgICAgIGNvbmRpdGlvbnNfb2JzZXJ2ZWQgPSBkcGx5cjo6bl9kaXN0aW5jdChwYXJ0eV9uKQ0KICAgICkgJT4lDQogICAgZHBseXI6OnVuZ3JvdXAoKQ0KICANCiAgc3VwcG9ydF90b3RhbHMgPC0gZGF0ICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdChJRCwgcGFydHlfc3VwcG9ydF9oKSAlPiUNCiAgICBkcGx5cjo6Y291bnQocGFydHlfc3VwcG9ydF9oLCBuYW1lID0gIm5fdG90YWxfZGlzdGluY3QiKQ0KICANCiAgc3VwcG9ydF9jb3VudHMgPC0gc3VwcG9ydF9jb3VudHMgJT4lDQogICAgZHBseXI6OmxlZnRfam9pbihzdXBwb3J0X3RvdGFscywgYnkgPSAicGFydHlfc3VwcG9ydF9oIikgJT4lDQogICAgZHBseXI6OmFycmFuZ2UoZHBseXI6OmRlc2Mobl90b3RhbF9kaXN0aW5jdCksIHBhcnR5X3N1cHBvcnRfaCkNCiAgDQogIGVsaWdpYmxlX2dyb3VwcyA8LSBzdXBwb3J0X2NvdW50cyAlPiUNCiAgICBkcGx5cjo6ZGlzdGluY3QoDQogICAgICBwYXJ0eV9zdXBwb3J0X2gsDQogICAgICBuX3RvdGFsX2Rpc3RpbmN0LA0KICAgICAgbWluX2NvbmRpdGlvbl9uLA0KICAgICAgY29uZGl0aW9uc19vYnNlcnZlZA0KICAgICkgJT4lDQogICAgZHBseXI6OmZpbHRlcigNCiAgICAgIG5fdG90YWxfZGlzdGluY3QgPj0gdW5pZmllZF9jb25maWckbWluX3N1cHBvcnRfdG90YWxfbiwNCiAgICAgIGNvbmRpdGlvbnNfb2JzZXJ2ZWQgPT0gNA0KICAgICkgJT4lDQogICAgZHBseXI6OnB1bGwocGFydHlfc3VwcG9ydF9oKQ0KICANCiAgcmVhZHI6OndyaXRlX2NzdigNCiAgICBzdXBwb3J0X2NvdW50cywNCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X3N1cHBvcnRfc2FtcGxlX2NvdW50cy5jc3YiKSwNCiAgICBuYSA9ICIiDQogICkNCiAgDQogIGZvcm11bGFfc3ViZ3JvdXAgPC0gc3RhdHM6OmFzLmZvcm11bGEoDQogICAgcGFzdGUoDQogICAgICAic2VsZWN0ZWQgfiIsDQogICAgICBwYXN0ZShlbnYkYXR0cl90ZXJtcywgY29sbGFwc2UgPSAiICsgIikNCiAgICApDQogICkNCiAgDQogIGVzdGltYXRlX29uZV9jZWxsIDwtIGZ1bmN0aW9uKGdyb3VwX3ZhbHVlLCBuX3ZhbHVlKSB7DQogICAgZGF0X2NlbGwgPC0gZGF0ICU+JQ0KICAgICAgZHBseXI6OmZpbHRlcigNCiAgICAgICAgcGFydHlfc3VwcG9ydF9oID09IGdyb3VwX3ZhbHVlLA0KICAgICAgICBwYXJ0eV9uID09IG5fdmFsdWUNCiAgICAgICkNCiAgICANCiAgICBuX2lkcyA8LSBkcGx5cjo6bl9kaXN0aW5jdChkYXRfY2VsbCRJRCkNCiAgICANCiAgICBpZiAobl9pZHMgPCB1bmlmaWVkX2NvbmZpZyRtaW5fc3VwcG9ydF9jZWxsX24pIHsNCiAgICAgIHJldHVybigNCiAgICAgICAgdGliYmxlOjp0aWJibGUoDQogICAgICAgICAgdGVybSA9IE5BX2NoYXJhY3Rlcl8sDQogICAgICAgICAgZXN0aW1hdGUgPSBOQV9yZWFsXywNCiAgICAgICAgICBzdGQuZXJyb3IgPSBOQV9yZWFsXywNCiAgICAgICAgICBzdGF0aXN0aWMgPSBOQV9yZWFsXywNCiAgICAgICAgICBwLnZhbHVlID0gTkFfcmVhbF8sDQogICAgICAgICAgY29uZi5sb3cgPSBOQV9yZWFsXywNCiAgICAgICAgICBjb25mLmhpZ2ggPSBOQV9yZWFsXywNCiAgICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwNCiAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwNCiAgICAgICAgICBuX2lkcyA9IG5faWRzLA0KICAgICAgICAgIHN0YXR1cyA9ICJpbnN1ZmZpY2llbnRfY2VsbF9uIg0KICAgICAgICApDQogICAgICApDQogICAgfQ0KICAgIA0KICAgIG1vZGVsIDwtIHRyeUNhdGNoKA0KICAgICAgZml4ZXN0OjpmZW9scygNCiAgICAgICAgZm9ybXVsYV9zdWJncm91cCwNCiAgICAgICAgZGF0YSA9IGRhdF9jZWxsLA0KICAgICAgICB2Y292ID0gfiBJRA0KICAgICAgKSwNCiAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgZQ0KICAgICkNCiAgICANCiAgICBpZiAoaW5oZXJpdHMobW9kZWwsICJlcnJvciIpKSB7DQogICAgICByZXR1cm4oDQogICAgICAgIHRpYmJsZTo6dGliYmxlKA0KICAgICAgICAgIHRlcm0gPSBOQV9jaGFyYWN0ZXJfLA0KICAgICAgICAgIGVzdGltYXRlID0gTkFfcmVhbF8sDQogICAgICAgICAgc3RkLmVycm9yID0gTkFfcmVhbF8sDQogICAgICAgICAgc3RhdGlzdGljID0gTkFfcmVhbF8sDQogICAgICAgICAgcC52YWx1ZSA9IE5BX3JlYWxfLA0KICAgICAgICAgIGNvbmYubG93ID0gTkFfcmVhbF8sDQogICAgICAgICAgY29uZi5oaWdoID0gTkFfcmVhbF8sDQogICAgICAgICAgcGFydHlfc3VwcG9ydF9oID0gZ3JvdXBfdmFsdWUsDQogICAgICAgICAgcGFydHlfbiA9IG5fdmFsdWUsDQogICAgICAgICAgbl9pZHMgPSBuX2lkcywNCiAgICAgICAgICBzdGF0dXMgPSBwYXN0ZTAoIm1vZGVsX2Vycm9yOiAiLCBjb25kaXRpb25NZXNzYWdlKG1vZGVsKSkNCiAgICAgICAgKQ0KICAgICAgKQ0KICAgIH0NCiAgICANCiAgICB0aWR5X2ZpeGVzdF91bmlmaWVkKG1vZGVsKSAlPiUNCiAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgIHBhcnR5X3N1cHBvcnRfaCA9IGdyb3VwX3ZhbHVlLA0KICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwNCiAgICAgICAgbl9pZHMgPSBuX2lkcywNCiAgICAgICAgc3RhdHVzID0gImVzdGltYXRlZCINCiAgICAgICkNCiAgfQ0KICANCiAgc3ViZ3JvdXBfY29lZmZpY2llbnRzIDwtIHB1cnJyOjptYXBfZGZyKA0KICAgIGVsaWdpYmxlX2dyb3VwcywNCiAgICBmdW5jdGlvbihncm91cF92YWx1ZSkgew0KICAgICAgcHVycnI6Om1hcF9kZnIoDQogICAgICAgIDI6NSwNCiAgICAgICAgfiBlc3RpbWF0ZV9vbmVfY2VsbChncm91cF92YWx1ZSwgLngpDQogICAgICApDQogICAgfQ0KICApDQogIA0KICB0ZXJtX2xhYmVsX3RhYmxlIDwtIG1ha2VfdGVybV9sYWJlbF90YWJsZShlbnYpDQogIA0KICBzdWJncm91cF9jb2VmZmljaWVudHMgPC0gc3ViZ3JvdXBfY29lZmZpY2llbnRzICU+JQ0KICAgIGRwbHlyOjpsZWZ0X2pvaW4odGVybV9sYWJlbF90YWJsZSwgYnkgPSAidGVybSIpICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBhdHRyaWJ1dGUgPSBkcGx5cjo6Y29hbGVzY2UoYXR0cmlidXRlLCAi44Gd44Gu5LuWIiksDQogICAgICBsYWJlbCA9IGRwbHlyOjpjb2FsZXNjZShsYWJlbCwgdGVybSksDQogICAgICBlc3RpbWF0ZV9wcCA9IGVzdGltYXRlICogMTAwLA0KICAgICAgY29uZi5sb3dfcHAgPSBjb25mLmxvdyAqIDEwMCwNCiAgICAgIGNvbmYuaGlnaF9wcCA9IGNvbmYuaGlnaCAqIDEwMCwNCiAgICAgIHBhcnR5X25fbGFiZWwgPSBmYWN0b3IoDQogICAgICAgIHBhcnR5X24sDQogICAgICAgIGxldmVscyA9IDI6NSwNCiAgICAgICAgbGFiZWxzID0gcGFzdGUwKDI6NSwgaWZlbHNlKHN0dWR5X2lkID09ICJzdHVkeTMiLCAi6YG45oqe6IKiIiwgIuaUv+WFmiIpKQ0KICAgICAgKQ0KICAgICkNCiAgDQogIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgc3ViZ3JvdXBfY29lZmZpY2llbnRzLA0KICAgIGZpbGUucGF0aChvdXRfZGlyLCAicGFydHlfc3VwcG9ydF9zdWJncm91cF9hbWNlX2NvZWZmaWNpZW50cy5jc3YiKSwNCiAgICBuYSA9ICIiDQogICkNCiAgDQogIGZvciAoZ3JvdXBfdmFsdWUgaW4gZWxpZ2libGVfZ3JvdXBzKSB7DQogICAgcGxvdF9kYXQgPC0gc3ViZ3JvdXBfY29lZmZpY2llbnRzICU+JQ0KICAgICAgZHBseXI6OmZpbHRlcigNCiAgICAgICAgcGFydHlfc3VwcG9ydF9oID09IGdyb3VwX3ZhbHVlLA0KICAgICAgICBzdGF0dXMgPT0gImVzdGltYXRlZCIsDQogICAgICAgICFpcy5uYSh0ZXJtKQ0KICAgICAgKQ0KICAgIA0KICAgIGlmIChucm93KHBsb3RfZGF0KSA9PSAwKSBuZXh0DQogICAgDQogICAgbGFiZWxfb3JkZXIgPC0gcGxvdF9kYXQgJT4lDQogICAgICBkcGx5cjo6YXJyYW5nZShhdHRyaWJ1dGUsIGRwbHlyOjpjb2FsZXNjZShvcmRlciwgOTk5OSksIGxhYmVsKSAlPiUNCiAgICAgIGRwbHlyOjpkaXN0aW5jdChsYWJlbCkgJT4lDQogICAgICBkcGx5cjo6cHVsbChsYWJlbCkNCiAgICANCiAgICBwbG90X2RhdCA8LSBwbG90X2RhdCAlPiUNCiAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgIGxhYmVsID0gZmFjdG9yKGxhYmVsLCBsZXZlbHMgPSByZXYobGFiZWxfb3JkZXIpKQ0KICAgICAgKQ0KICAgIA0KICAgIG5fZ3JvdXAgPC0gc3VwcG9ydF90b3RhbHMgJT4lDQogICAgICBkcGx5cjo6ZmlsdGVyKHBhcnR5X3N1cHBvcnRfaCA9PSBncm91cF92YWx1ZSkgJT4lDQogICAgICBkcGx5cjo6cHVsbChuX3RvdGFsX2Rpc3RpbmN0KQ0KICAgIA0KICAgIHBfZ3JvdXAgPC0gZ2dwbG90Mjo6Z2dwbG90KA0KICAgICAgcGxvdF9kYXQsDQogICAgICBnZ3Bsb3QyOjphZXMoDQogICAgICAgIHggPSBlc3RpbWF0ZV9wcCwNCiAgICAgICAgeSA9IGxhYmVsLA0KICAgICAgICBzaGFwZSA9IHBhcnR5X25fbGFiZWwNCiAgICAgICkNCiAgICApICsNCiAgICAgIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuNDUpICsNCiAgICAgIGdncGxvdDI6Omdlb21fZXJyb3JiYXJoKA0KICAgICAgICBnZ3Bsb3QyOjphZXMoDQogICAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLA0KICAgICAgICAgIHhtYXggPSBjb25mLmhpZ2hfcHANCiAgICAgICAgKSwNCiAgICAgICAgaGVpZ2h0ID0gMC4xMCwNCiAgICAgICAgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNTUpLA0KICAgICAgICBsaW5ld2lkdGggPSAwLjU1DQogICAgICApICsNCiAgICAgIGdncGxvdDI6Omdlb21fcG9pbnQoDQogICAgICAgIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjU1KSwNCiAgICAgICAgc2l6ZSA9IDIuMywNCiAgICAgICAgZmlsbCA9ICJ3aGl0ZSINCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6ZmFjZXRfZ3JpZCgNCiAgICAgICAgYXR0cmlidXRlIH4gLiwNCiAgICAgICAgc2NhbGVzID0gImZyZWVfeSIsDQogICAgICAgIHNwYWNlID0gImZyZWVfeSINCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6bGFicygNCiAgICAgICAgeCA9ICLpgbjmip7norrnjofjgbjjga7lirnmnpzvvIhwZXJjZW50YWdlIHBvaW50c++8iSIsDQogICAgICAgIHkgPSBOVUxMLA0KICAgICAgICBzaGFwZSA9IHN0dWR5X3NwZWMkY29uZGl0aW9uX2xhYmVsLA0KICAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgNCiAgICAgICAgICBzdHVkeV9sYWJlbCwNCiAgICAgICAgICAi77yaIiwNCiAgICAgICAgICBncm91cF92YWx1ZSwNCiAgICAgICAgICAi5pSv5oyB6ICF77yIbiA9ICIsDQogICAgICAgICAgc2NhbGVzOjpjb21tYShuX2dyb3VwKSwNCiAgICAgICAgICAi77yJIg0KICAgICAgICApLA0KICAgICAgICBjYXB0aW9uID0gcGFzdGUwKA0KICAgICAgICAgICLlm57nrZTogIVJROOBp+OCr+ODqeOCueOCv+WMluOBl+OBn+aomea6luiqpOW3ruOAguWQhOadoeS7tuOCu+ODq24gPCAiLA0KICAgICAgICAgIHVuaWZpZWRfY29uZmlnJG1pbl9zdXBwb3J0X2NlbGxfbiwNCiAgICAgICAgICAi44Gv5o6o5a6a44GX44Gq44GE44CCIg0KICAgICAgICApDQogICAgICApICsNCiAgICAgIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsNCiAgICAgIGdncGxvdDI6OnRoZW1lKA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZ2dwbG90Mjo6ZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpDQogICAgICApDQogICAgDQogICAgZ3JvdXBfaW5kZXggPC0gbWF0Y2goZ3JvdXBfdmFsdWUsIGVsaWdpYmxlX2dyb3VwcykNCiAgICBmaWxlX3N0dWIgPC0gcGFzdGUwKA0KICAgICAgc3R1ZHlfaWQsDQogICAgICAiX3BhcnR5X3N1cHBvcnRfYW1jZV8iLA0KICAgICAgc3ByaW50ZigiJTAyZCIsIGdyb3VwX2luZGV4KSwNCiAgICAgICJfIiwNCiAgICAgIHNhZmVfZmlsZW5hbWUoZ3JvdXBfdmFsdWUpDQogICAgKQ0KICAgIA0KICAgIGdncGxvdDI6Omdnc2F2ZSgNCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsIHBhc3RlMChmaWxlX3N0dWIsICIucG5nIikpLA0KICAgICAgcGxvdCA9IHBfZ3JvdXAsDQogICAgICB3aWR0aCA9IDEwLjUsDQogICAgICBoZWlnaHQgPSBpZmVsc2Uoc3R1ZHlfaWQgPT0gInN0dWR5MyIsIDExLjUsIDEwLjApLA0KICAgICAgZHBpID0gNDAwLA0KICAgICAgYmcgPSAid2hpdGUiDQogICAgKQ0KICAgIA0KICAgIGdncGxvdDI6Omdnc2F2ZSgNCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsIHBhc3RlMChmaWxlX3N0dWIsICIucGRmIikpLA0KICAgICAgcGxvdCA9IHBfZ3JvdXAsDQogICAgICB3aWR0aCA9IDEwLjUsDQogICAgICBoZWlnaHQgPSBpZmVsc2Uoc3R1ZHlfaWQgPT0gInN0dWR5MyIsIDExLjUsIDEwLjApLA0KICAgICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsDQogICAgICBiZyA9ICJ3aGl0ZSINCiAgICApDQogIH0NCiAgDQogIGludGVyYWN0aW9uX21vZGVscyA8LSBsaXN0KCkNCiAgaW50ZXJhY3Rpb25fdGVzdF90ZXh0IDwtIGNoYXJhY3RlcigpDQogIA0KICBkYXRfaW50ZXJhY3Rpb24gPC0gZGF0ICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIocGFydHlfc3VwcG9ydF9oICVpbiUgZWxpZ2libGVfZ3JvdXBzKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgcGFydHlfc3VwcG9ydF9oID0gZmFjdG9yKHBhcnR5X3N1cHBvcnRfaCkNCiAgICApDQogIA0KICBpZiAoIuaUr+aMgeaUv+WFmuOBquOBlyIgJWluJSBsZXZlbHMoZGF0X2ludGVyYWN0aW9uJHBhcnR5X3N1cHBvcnRfaCkpIHsNCiAgICBkYXRfaW50ZXJhY3Rpb24gPC0gZGF0X2ludGVyYWN0aW9uICU+JQ0KICAgICAgZHBseXI6Om11dGF0ZSgNCiAgICAgICAgcGFydHlfc3VwcG9ydF9oID0gc3RhdHM6OnJlbGV2ZWwoDQogICAgICAgICAgcGFydHlfc3VwcG9ydF9oLA0KICAgICAgICAgIHJlZiA9ICLmlK/mjIHmlL/lhZrjgarjgZciDQogICAgICAgICkNCiAgICAgICkNCiAgfSBlbHNlIGlmIChucm93KHN1cHBvcnRfdG90YWxzKSA+IDApIHsNCiAgICBsYXJnZXN0X2dyb3VwIDwtIHN1cHBvcnRfdG90YWxzICU+JQ0KICAgICAgZHBseXI6OmZpbHRlcihwYXJ0eV9zdXBwb3J0X2ggJWluJSBlbGlnaWJsZV9ncm91cHMpICU+JQ0KICAgICAgZHBseXI6OnNsaWNlX21heChuX3RvdGFsX2Rpc3RpbmN0LCBuID0gMSwgd2l0aF90aWVzID0gRkFMU0UpICU+JQ0KICAgICAgZHBseXI6OnB1bGwocGFydHlfc3VwcG9ydF9oKQ0KICAgIA0KICAgIGlmIChsZW5ndGgobGFyZ2VzdF9ncm91cCkgPT0gMSkgew0KICAgICAgZGF0X2ludGVyYWN0aW9uIDwtIGRhdF9pbnRlcmFjdGlvbiAlPiUNCiAgICAgICAgZHBseXI6Om11dGF0ZSgNCiAgICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBzdGF0czo6cmVsZXZlbCgNCiAgICAgICAgICAgIHBhcnR5X3N1cHBvcnRfaCwNCiAgICAgICAgICAgIHJlZiA9IGxhcmdlc3RfZ3JvdXANCiAgICAgICAgICApDQogICAgICAgICkNCiAgICB9DQogIH0NCiAgDQogIGZvcm11bGFfaW50ZXJhY3Rpb24gPC0gc3RhdHM6OmFzLmZvcm11bGEoDQogICAgcGFzdGUwKA0KICAgICAgInNlbGVjdGVkIH4gcGFydHlfc3VwcG9ydF9oICogKCIsDQogICAgICBwYXN0ZShlbnYkYXR0cl90ZXJtcywgY29sbGFwc2UgPSAiICsgIiksDQogICAgICAiKSINCiAgICApDQogICkNCiAgDQogIGZvciAobl92YWx1ZSBpbiAyOjUpIHsNCiAgICBkYXRfbiA8LSBkYXRfaW50ZXJhY3Rpb24gJT4lIGRwbHlyOjpmaWx0ZXIocGFydHlfbiA9PSBuX3ZhbHVlKQ0KICAgIA0KICAgIG1vZGVsX24gPC0gdHJ5Q2F0Y2goDQogICAgICBmaXhlc3Q6OmZlb2xzKA0KICAgICAgICBmb3JtdWxhX2ludGVyYWN0aW9uLA0KICAgICAgICBkYXRhID0gZGF0X24sDQogICAgICAgIHZjb3YgPSB+IElEDQogICAgICApLA0KICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSBlDQogICAgKQ0KICAgIA0KICAgIGludGVyYWN0aW9uX21vZGVsc1tbYXMuY2hhcmFjdGVyKG5fdmFsdWUpXV0gPC0gbW9kZWxfbg0KICAgIA0KICAgIGludGVyYWN0aW9uX3Rlc3RfdGV4dCA8LSBjKA0KICAgICAgaW50ZXJhY3Rpb25fdGVzdF90ZXh0LA0KICAgICAgcGFzdGUwKCJcbj09PT09ICIsIHN0dWR5X2xhYmVsLCAiOiBjb25kaXRpb24gIiwgbl92YWx1ZSwgIiA9PT09PVxuIikNCiAgICApDQogICAgDQogICAgaWYgKGluaGVyaXRzKG1vZGVsX24sICJlcnJvciIpKSB7DQogICAgICBpbnRlcmFjdGlvbl90ZXN0X3RleHQgPC0gYygNCiAgICAgICAgaW50ZXJhY3Rpb25fdGVzdF90ZXh0LA0KICAgICAgICBwYXN0ZTAoIk1vZGVsIGVycm9yOiAiLCBjb25kaXRpb25NZXNzYWdlKG1vZGVsX24pLCAiXG4iKQ0KICAgICAgKQ0KICAgIH0gZWxzZSB7DQogICAgICBpbnRlcmFjdGlvbl90ZXN0X3RleHQgPC0gYygNCiAgICAgICAgaW50ZXJhY3Rpb25fdGVzdF90ZXh0LA0KICAgICAgICBjYXB0dXJlLm91dHB1dChzdW1tYXJ5KG1vZGVsX24pKSwNCiAgICAgICAgIlxuLS0tIEpvaW50IFdhbGQgdGVzdCBmb3IgcGFydHktc3VwcG9ydCBpbnRlcmFjdGlvbiB0ZXJtcyAtLS1cbiIsDQogICAgICAgIHRyeUNhdGNoKA0KICAgICAgICAgIGNhcHR1cmUub3V0cHV0KA0KICAgICAgICAgICAgZml4ZXN0Ojp3YWxkKA0KICAgICAgICAgICAgICBtb2RlbF9uLA0KICAgICAgICAgICAgICBrZWVwID0gInBhcnR5X3N1cHBvcnRfaC4qOnw6cGFydHlfc3VwcG9ydF9oIg0KICAgICAgICAgICAgKQ0KICAgICAgICAgICksDQogICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSBwYXN0ZTAoIldhbGQgdGVzdCBlcnJvcjogIiwgY29uZGl0aW9uTWVzc2FnZShlKSkNCiAgICAgICAgKQ0KICAgICAgKQ0KICAgIH0NCiAgfQ0KICANCiAgd3JpdGVMaW5lcygNCiAgICBpbnRlcmFjdGlvbl90ZXN0X3RleHQsDQogICAgY29uID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9zdXBwb3J0X2ludGVyYWN0aW9uX21vZGVsc19hbmRfd2FsZF90ZXN0cy50eHQiKQ0KICApDQogIA0KICBsaXN0KA0KICAgIHN1cHBvcnRfY291bnRzID0gc3VwcG9ydF9jb3VudHMsDQogICAgZWxpZ2libGVfZ3JvdXBzID0gZWxpZ2libGVfZ3JvdXBzLA0KICAgIHN1Ymdyb3VwX2NvZWZmaWNpZW50cyA9IHN1Ymdyb3VwX2NvZWZmaWNpZW50cywNCiAgICBpbnRlcmFjdGlvbl9tb2RlbHMgPSBpbnRlcmFjdGlvbl9tb2RlbHMsDQogICAgZGF0YSA9IGRhdA0KICApDQp9DQoNCnBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzIDwtIHB1cnJyOjptYXAoDQogIHN0dWR5X3NwZWNzLA0KICBydW5fc3VwcG9ydF9hbWNlX2hldGVyb2dlbmVpdHkNCikNCg0KcnVuX3N1cHBvcnRfcmVsYXRpdmVfY3VlIDwtIGZ1bmN0aW9uKHN0dWR5X3NwZWMsIGFtY2VfcmVzdWx0KSB7DQogIGVudiA8LSBzdHVkeV9zcGVjJGVudg0KICBzdHVkeV9pZCA8LSBzdHVkeV9zcGVjJHN0dWR5X2lkDQogIG91dF9kaXIgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKHN0dWR5X2lkLCAiX3BhcnR5X3N1cHBvcnQiKSkNCiAgDQogIGRhdCA8LSBhbWNlX3Jlc3VsdCRkYXRhDQogIGVsaWdpYmxlX2dyb3VwcyA8LSBhbWNlX3Jlc3VsdCRlbGlnaWJsZV9ncm91cHMNCiAgDQogIG9ic2VydmVkX2xpc3QgPC0gbGlzdCgpDQogIGludGVydmFsX2xpc3QgPC0gbGlzdCgpDQogIHNsb3BlX2xpc3QgPC0gbGlzdCgpDQogIGZhaWx1cmVfbGlzdCA8LSBsaXN0KCkNCiAgDQogIGZvciAoZ3JvdXBfaW5kZXggaW4gc2VxX2Fsb25nKGVsaWdpYmxlX2dyb3VwcykpIHsNCiAgICBncm91cF92YWx1ZSA8LSBlbGlnaWJsZV9ncm91cHNbZ3JvdXBfaW5kZXhdDQogICAgZGF0X2dyb3VwIDwtIGRhdCAlPiUNCiAgICAgIGRwbHlyOjpmaWx0ZXIocGFydHlfc3VwcG9ydF9oID09IGdyb3VwX3ZhbHVlKQ0KICAgIA0KICAgIGNvbmRpdGlvbl9jb3VudHMgPC0gZGF0X2dyb3VwICU+JQ0KICAgICAgZHBseXI6OmRpc3RpbmN0KElELCBwYXJ0eV9uKSAlPiUNCiAgICAgIGRwbHlyOjpjb3VudChwYXJ0eV9uLCBuYW1lID0gIm5faWRzIikNCiAgICANCiAgICBpZiAoDQogICAgICAhaWRlbnRpY2FsKHNvcnQoY29uZGl0aW9uX2NvdW50cyRwYXJ0eV9uKSwgMjo1KSB8fA0KICAgICAgYW55KGNvbmRpdGlvbl9jb3VudHMkbl9pZHMgPCB1bmlmaWVkX2NvbmZpZyRtaW5fc3VwcG9ydF9jZWxsX24pDQogICAgKSB7DQogICAgICBmYWlsdXJlX2xpc3RbW2dyb3VwX3ZhbHVlXV0gPC0gdGliYmxlOjp0aWJibGUoDQogICAgICAgIHBhcnR5X3N1cHBvcnRfaCA9IGdyb3VwX3ZhbHVlLA0KICAgICAgICByZWFzb24gPSAiTm90IGFsbCBmb3VyIGNvbmRpdGlvbnMgbWVldCB0aGUgbWluaW11bSBjZWxsIHNpemUiDQogICAgICApDQogICAgICBuZXh0DQogICAgfQ0KICAgIA0KICAgIHByZXBhcmVkIDwtIHRyeUNhdGNoKA0KICAgICAgZW52JHByZXBhcmVfcmVsYXRpdmVfY3VlX2FuYWx5c2lzKA0KICAgICAgICBkYXRhID0gZGF0X2dyb3VwLA0KICAgICAgICBjdWVfbWFwID0gZW52JHJlbGF0aXZlX2N1ZV9tYXANCiAgICAgICksDQogICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIGUNCiAgICApDQogICAgDQogICAgaWYgKGluaGVyaXRzKHByZXBhcmVkLCAiZXJyb3IiKSkgew0KICAgICAgZmFpbHVyZV9saXN0W1tncm91cF92YWx1ZV1dIDwtIHRpYmJsZTo6dGliYmxlKA0KICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwNCiAgICAgICAgcmVhc29uID0gY29uZGl0aW9uTWVzc2FnZShwcmVwYXJlZCkNCiAgICAgICkNCiAgICAgIG5leHQNCiAgICB9DQogICAgDQogICAgb2JzZXJ2ZWQgPC0gZW52JGVzdGltYXRlX3JlbGF0aXZlX2N1ZV9pbmRpY2VzKHByZXBhcmVkKQ0KICAgIG9ic2VydmVkX3Nsb3BlcyA8LSBlbnYkZXN0aW1hdGVfcmVsYXRpdmVfY3VlX3Nsb3BlcygNCiAgICAgIG9ic2VydmVkJGN1ZV9pbXBvcnRhbmNlDQogICAgKQ0KICAgIA0KICAgIG9ic2VydmVkX2xpc3RbW2dyb3VwX3ZhbHVlXV0gPC0gb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UgJT4lDQogICAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwNCiAgICAgICAgLmJlZm9yZSA9IDENCiAgICAgICkNCiAgICANCiAgICBzbG9wZV9saXN0W1tncm91cF92YWx1ZV1dIDwtIHRpYmJsZTo6dGliYmxlKA0KICAgICAgcGFydHlfc3VwcG9ydF9oID0gZ3JvdXBfdmFsdWUsDQogICAgICBzdGF0aXN0aWMgPSBuYW1lcyhvYnNlcnZlZF9zbG9wZXMpLA0KICAgICAgZXN0aW1hdGUgPSBhcy5udW1lcmljKG9ic2VydmVkX3Nsb3BlcykNCiAgICApDQogICAgDQogICAgQiA8LSB1bmlmaWVkX2NvbmZpZyRzdXBwb3J0X2Jvb3RzdHJhcF9CDQogICAgDQogICAgaWYgKEIgPiAwKSB7DQogICAgICBjYWNoZV9maWxlIDwtIGZpbGUucGF0aCgNCiAgICAgICAgb3V0X2RpciwNCiAgICAgICAgcGFzdGUwKA0KICAgICAgICAgICJzdXBwb3J0X3JlbGF0aXZlX2N1ZV9ib290c3RyYXBfIiwNCiAgICAgICAgICB1bmlmaWVkX2NvbmZpZyRjdWVfaW1wb3J0YW5jZV9tZXRyaWNfdmVyc2lvbiwNCiAgICAgICAgICAiXyIsDQogICAgICAgICAgc3ByaW50ZigiJTAyZCIsIGdyb3VwX2luZGV4KSwNCiAgICAgICAgICAiX0IiLA0KICAgICAgICAgIEIsDQogICAgICAgICAgIi5yZHMiDQogICAgICAgICkNCiAgICAgICkNCiAgICAgIA0KICAgICAgaWYgKA0KICAgICAgICBmaWxlLmV4aXN0cyhjYWNoZV9maWxlKSAmJg0KICAgICAgICAhdW5pZmllZF9jb25maWckcmVydW5fc3VwcG9ydF9ib290c3RyYXANCiAgICAgICkgew0KICAgICAgICBib290c3RyYXBfcmVzdWx0IDwtIHJlYWRSRFMoY2FjaGVfZmlsZSkNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIGJvb3RzdHJhcF9yZXN1bHQgPC0gZW52JHJ1bl9yZWxhdGl2ZV9jdWVfYm9vdHN0cmFwKA0KICAgICAgICAgIHByZXBhcmVkID0gcHJlcGFyZWQsDQogICAgICAgICAgQiA9IEIsDQogICAgICAgICAgc2VlZCA9IHVuaWZpZWRfY29uZmlnJHN1cHBvcnRfYm9vdHN0cmFwX3NlZWQgKw0KICAgICAgICAgICAgMTAwMCAqIG1hdGNoKHN0dWR5X2lkLCBuYW1lcyhzdHVkeV9zcGVjcykpICsNCiAgICAgICAgICAgIGdyb3VwX2luZGV4LA0KICAgICAgICAgIHByb2dyZXNzX2V2ZXJ5ID0gbWF4KDAsIGZsb29yKEIgLyA1KSkNCiAgICAgICAgKQ0KICAgICAgICBzYXZlUkRTKGJvb3RzdHJhcF9yZXN1bHQsIGNhY2hlX2ZpbGUpDQogICAgICB9DQogICAgICANCiAgICAgIGludGVydmFscyA8LSBlbnYkc3VtbWFyaXNlX2NvbmRpdGlvbl9pbnRlcnZhbHMoDQogICAgICAgIG9ic2VydmVkX2N1ZV9pbXBvcnRhbmNlID0gb2JzZXJ2ZWQkY3VlX2ltcG9ydGFuY2UsDQogICAgICAgIGJvb3RzdHJhcF9jb25kaXRpb25fcmVzdWx0cyA9IGJvb3RzdHJhcF9yZXN1bHQkY29uZGl0aW9uX2VzdGltYXRlcw0KICAgICAgKSAlPiUNCiAgICAgICAgZHBseXI6Om11dGF0ZSgNCiAgICAgICAgICBwYXJ0eV9zdXBwb3J0X2ggPSBncm91cF92YWx1ZSwNCiAgICAgICAgICAuYmVmb3JlID0gMQ0KICAgICAgICApDQogICAgICANCiAgICAgIHNsb3BlX2luZmVyZW5jZSA8LSBlbnYkc3VtbWFyaXNlX3Nsb3BlX2luZmVyZW5jZSgNCiAgICAgICAgb2JzZXJ2ZWRfc2xvcGVzID0gb2JzZXJ2ZWRfc2xvcGVzLA0KICAgICAgICBib290c3RyYXBfc2xvcGVzID0gYm9vdHN0cmFwX3Jlc3VsdCRzbG9wZXMNCiAgICAgICkgJT4lDQogICAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgICAgcGFydHlfc3VwcG9ydF9oID0gZ3JvdXBfdmFsdWUsDQogICAgICAgICAgLmJlZm9yZSA9IDENCiAgICAgICAgKQ0KICAgICAgDQogICAgICBpbnRlcnZhbF9saXN0W1tncm91cF92YWx1ZV1dIDwtIGludGVydmFscw0KICAgICAgc2xvcGVfbGlzdFtbcGFzdGUwKGdyb3VwX3ZhbHVlLCAiX2luZmVyZW5jZSIpXV0gPC0gc2xvcGVfaW5mZXJlbmNlDQogICAgfQ0KICB9DQogIA0KICBvYnNlcnZlZF9kZiA8LSBkcGx5cjo6YmluZF9yb3dzKG9ic2VydmVkX2xpc3QpDQogIGludGVydmFsX2RmIDwtIGRwbHlyOjpiaW5kX3Jvd3MoaW50ZXJ2YWxfbGlzdCkNCiAgc2xvcGVfZGYgPC0gZHBseXI6OmJpbmRfcm93cyhzbG9wZV9saXN0KQ0KICBmYWlsdXJlc19kZiA8LSBkcGx5cjo6YmluZF9yb3dzKGZhaWx1cmVfbGlzdCkNCiAgDQogIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgb2JzZXJ2ZWRfZGYsDQogICAgZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV9vYnNlcnZlZC5jc3YiKSwNCiAgICBuYSA9ICIiDQogICkNCiAgcmVhZHI6OndyaXRlX2NzdigNCiAgICBpbnRlcnZhbF9kZiwNCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX2ludGVydmFscy5jc3YiKSwNCiAgICBuYSA9ICIiDQogICkNCiAgcmVhZHI6OndyaXRlX2NzdigNCiAgICBzbG9wZV9kZiwNCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX3Nsb3Blcy5jc3YiKSwNCiAgICBuYSA9ICIiDQogICkNCiAgcmVhZHI6OndyaXRlX2NzdigNCiAgICBmYWlsdXJlc19kZiwNCiAgICBmaWxlLnBhdGgob3V0X2RpciwgInBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX2ZhaWx1cmVzLmNzdiIpLA0KICAgIG5hID0gIiINCiAgKQ0KICANCiAgaWYgKG5yb3coaW50ZXJ2YWxfZGYpID4gMCkgew0KICAgIHBsb3RfZGYgPC0gaW50ZXJ2YWxfZGYgJT4lDQogICAgICBkcGx5cjo6ZmlsdGVyKHN0YXRpc3RpYyA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIikgJT4lDQogICAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgICBlc3RpbWF0ZV9wY3QgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICAgICAgY29uZl9sb3dfcGN0ID0gY29uZl9sb3cgKiAxMDAsDQogICAgICAgIGNvbmZfaGlnaF9wY3QgPSBjb25mX2hpZ2ggKiAxMDANCiAgICAgICkNCiAgfSBlbHNlIHsNCiAgICBwbG90X2RmIDwtIG9ic2VydmVkX2RmICU+JQ0KICAgICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgICAgcGFydHlfc3VwcG9ydF9oLA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBlc3RpbWF0ZV9wY3QgPSByZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UgKiAxMDAsDQogICAgICAgIGNvbmZfbG93X3BjdCA9IE5BX3JlYWxfLA0KICAgICAgICBjb25mX2hpZ2hfcGN0ID0gTkFfcmVhbF8NCiAgICAgICkNCiAgfQ0KICANCiAgaWYgKG5yb3cocGxvdF9kZikgPiAwKSB7DQogICAgcF9yZWxhdGl2ZV9zdXBwb3J0IDwtIGdncGxvdDI6OmdncGxvdCgNCiAgICAgIHBsb3RfZGYsDQogICAgICBnZ3Bsb3QyOjphZXMoDQogICAgICAgIHggPSBwYXJ0eV9uLA0KICAgICAgICB5ID0gZXN0aW1hdGVfcGN0LA0KICAgICAgICBncm91cCA9IDENCiAgICAgICkNCiAgICApICsNCiAgICAgIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjQ1KSArDQogICAgICBnZ3Bsb3QyOjpnZW9tX2xpbmUobGluZXdpZHRoID0gMC43MCkgKw0KICAgICAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcigNCiAgICAgICAgZ2dwbG90Mjo6YWVzKA0KICAgICAgICAgIHltaW4gPSBjb25mX2xvd19wY3QsDQogICAgICAgICAgeW1heCA9IGNvbmZfaGlnaF9wY3QNCiAgICAgICAgKSwNCiAgICAgICAgd2lkdGggPSAwLjA4LA0KICAgICAgICBsaW5ld2lkdGggPSAwLjU1LA0KICAgICAgICBuYS5ybSA9IFRSVUUNCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc2l6ZSA9IDIuNSkgKw0KICAgICAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IHBhcnR5X3N1cHBvcnRfaCwgbmNvbCA9IDMpICsNCiAgICAgIGdncGxvdDI6OnNjYWxlX3hfY29udGludW91cygNCiAgICAgICAgYnJlYWtzID0gMjo1LA0KICAgICAgICBsYWJlbHMgPSBwYXN0ZTAoMjo1LCBpZmVsc2Uoc3R1ZHlfaWQgPT0gInN0dWR5MyIsICLpgbjmip7ogqIiLCAi5pS/5YWaIikpDQogICAgICApICsNCiAgICAgIGdncGxvdDI6OnNjYWxlX3lfY29udGludW91cygNCiAgICAgICAgbGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgsICIlIiksDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcyhuID0gNikNCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6bGFicygNCiAgICAgICAgeCA9IHN0dWR5X3NwZWMkY29uZGl0aW9uX2xhYmVsLA0KICAgICAgICB5ID0gIuaUv+WFmuaJi+OBjOOBi+OCiuOBruebuOWvvuavlOmHjSIsDQogICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKA0KICAgICAgICAgIHN0dWR5X3NwZWMkc3R1ZHlfbGFiZWwsDQogICAgICAgICAgIu+8muaUr+aMgeaUv+WFmuWIpeOBruaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHjSINCiAgICAgICAgKSwNCiAgICAgICAgY2FwdGlvbiA9IHBhc3RlMCgNCiAgICAgICAgICAi5ZCE5bGe5oCn5YaF44Gu6ZmQ55WM5bmz5Z2H44Gu5bmz5Z2H57W25a++44Oa44Ki5beu44Gr5Z+644Gl44GP44CCIiwNCiAgICAgICAgICBpZmVsc2UoDQogICAgICAgICAgICB1bmlmaWVkX2NvbmZpZyRzdXBwb3J0X2Jvb3RzdHJhcF9CID4gMCwNCiAgICAgICAgICAgIHBhc3RlMCgNCiAgICAgICAgICAgICAgIjk1JeS/oemgvOWMuumWk+OBr+WbnuetlOiAheOCr+ODqeOCueOCv+ODu+ODluODvOODiOOCueODiOODqeODg+ODl++8iEIgPSAiLA0KICAgICAgICAgICAgICB1bmlmaWVkX2NvbmZpZyRzdXBwb3J0X2Jvb3RzdHJhcF9CLA0KICAgICAgICAgICAgICAi77yJ44CCIg0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgICLkv6HpoLzljLrplpPjga/mnKroqIjnrpfjgIIiDQogICAgICAgICAgKQ0KICAgICAgICApDQogICAgICApICsNCiAgICAgIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsNCiAgICAgIGdncGxvdDI6OnRoZW1lKA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZ2dwbG90Mjo6ZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikNCiAgICAgICkNCiAgICANCiAgICBnZ3Bsb3QyOjpnZ3NhdmUoDQogICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChvdXRfZGlyLCAicGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfd2VpZ2h0LnBuZyIpLA0KICAgICAgcGxvdCA9IHBfcmVsYXRpdmVfc3VwcG9ydCwNCiAgICAgIHdpZHRoID0gMTEuNSwNCiAgICAgIGhlaWdodCA9IG1heCg3LjAsIDIuNiAqIGNlaWxpbmcoZHBseXI6Om5fZGlzdGluY3QocGxvdF9kZiRwYXJ0eV9zdXBwb3J0X2gpIC8gMykpLA0KICAgICAgZHBpID0gNDAwLA0KICAgICAgYmcgPSAid2hpdGUiDQogICAgKQ0KICAgIA0KICAgIGdncGxvdDI6Omdnc2F2ZSgNCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV93ZWlnaHQucGRmIiksDQogICAgICBwbG90ID0gcF9yZWxhdGl2ZV9zdXBwb3J0LA0KICAgICAgd2lkdGggPSAxMS41LA0KICAgICAgaGVpZ2h0ID0gbWF4KDcuMCwgMi42ICogY2VpbGluZyhkcGx5cjo6bl9kaXN0aW5jdChwbG90X2RmJHBhcnR5X3N1cHBvcnRfaCkgLyAzKSksDQogICAgICBkZXZpY2UgPSBnckRldmljZXM6OmNhaXJvX3BkZiwNCiAgICAgIGJnID0gIndoaXRlIg0KICAgICkNCiAgfSBlbHNlIHsNCiAgICBwX3JlbGF0aXZlX3N1cHBvcnQgPC0gTlVMTA0KICB9DQogIA0KICBsaXN0KA0KICAgIG9ic2VydmVkID0gb2JzZXJ2ZWRfZGYsDQogICAgaW50ZXJ2YWxzID0gaW50ZXJ2YWxfZGYsDQogICAgc2xvcGVzID0gc2xvcGVfZGYsDQogICAgZmFpbHVyZXMgPSBmYWlsdXJlc19kZiwNCiAgICBwbG90ID0gcF9yZWxhdGl2ZV9zdXBwb3J0DQogICkNCn0NCg0KcGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfcmVzdWx0cyA8LSBwdXJycjo6bWFwMigNCiAgc3R1ZHlfc3BlY3MsDQogIHBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzLA0KICBydW5fc3VwcG9ydF9yZWxhdGl2ZV9jdWUNCikNCg0KDQojIOijnOmBuknplqLpgKPjgrPjg7zjg4kNCmV4dHJhY3RfY3VlX3Nsb3BlX2luZmVyZW5jZSA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7DQogIGVudiA8LSBzdHVkeV9zcGVjJGVudg0KICANCiAgZW52JHJlbGF0aXZlX2N1ZV9zbG9wZV9pbmZlcmVuY2UgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIHN0dWR5X2lkID0gc3R1ZHlfc3BlYyRzdHVkeV9pZCwNCiAgICAgIHN0dWR5X2xhYmVsID0gc3R1ZHlfc3BlYyRzdHVkeV9sYWJlbCwNCiAgICAgIC5iZWZvcmUgPSAxDQogICAgKQ0KfQ0KDQpjdWVfc2xvcGVfaW5mZXJlbmNlX2FsbCA8LSBwdXJycjo6bWFwX2RmcigNCiAgc3R1ZHlfc3BlY3MsDQogIGV4dHJhY3RfY3VlX3Nsb3BlX2luZmVyZW5jZQ0KKSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICBzdGF0aXN0aWNfbGFiZWwgPSBkcGx5cjo6cmVjb2RlKA0KICAgICAgc3RhdGlzdGljLA0KICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLmlL/lhZrjga7miYvjgYzjgYvjgorjga7mnKroqr/mlbTph43opoHluqYiLA0KICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLntYzmuIjjga7miYvjgYzjgYvjgorjga7mnKroqr/mlbTph43opoHluqYiLA0KICAgICAgcGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9DQogICAgICAgICLmlL/lhZrjga7miYvjgYzjgYvjgorjga7pgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiLA0KICAgICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCA9DQogICAgICAgICLntYzmuIjjga7miYvjgYzjgYvjgorjga7pgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiLA0KICAgICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0gIuaUv+WFmuOBruaJi+OBjOOBi+OCiuOBruebuOWvvuavlOmHjSINCiAgICApLA0KICAgIG1ldHJpY19zY2FsZSA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICBzdGF0aXN0aWMgJWluJSBjKA0KICAgICAgICAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZV9hZGp1c3RlZCIsDQogICAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICAgKSB+ICJjaG9pY2Vfc2V0X2FkanVzdGVkX2Jhc2VsaW5lX3JlbGF0aXZlIiwNCiAgICAgIHN0YXRpc3RpYyA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiB+DQogICAgICAgICJyZWxhdGl2ZV9zaGFyZSIsDQogICAgICBUUlVFIH4gInVuYWRqdXN0ZWRfcHJvYmFiaWxpdHlfZGlmZmVyZW5jZSINCiAgICApLA0KICAgIGVzdGltYXRlX3BwX3Blcl9vcHRpb24gPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICBjb25mX2xvd19wcF9wZXJfb3B0aW9uID0gY29uZl9sb3cgKiAxMDAsDQogICAgY29uZl9oaWdoX3BwX3Blcl9vcHRpb24gPSBjb25mX2hpZ2ggKiAxMDANCiAgKQ0KDQp3cml0ZV9jc3ZfdW5pZmllZCgNCiAgY3VlX3Nsb3BlX2luZmVyZW5jZV9hbGwsDQogICJjdWVfaW1wb3J0YW5jZV9saW5lYXJfc2xvcGVfYWxsX3N0dWRpZXMuY3N2Ig0KKQ0KDQpjaG9pY2Vfc2V0X2FkanVzdGVkX3Nsb3BlX3N1bW1hcnkgPC0gY3VlX3Nsb3BlX2luZmVyZW5jZV9hbGwgJT4lDQogIGRwbHlyOjpmaWx0ZXIoDQogICAgc3RhdGlzdGljICVpbiUgYygNCiAgICAgICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwNCiAgICAgICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIg0KICAgICkNCiAgKSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICBjdWVfZmFtaWx5ID0gZHBseXI6OnJlY29kZSgNCiAgICAgIHN0YXRpc3RpYywNCiAgICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAi5pS/5YWa44O75pS/5YWa5ZCN5omL44GM44GL44KKIiwNCiAgICAgIGVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPQ0KICAgICAgICAi57WM5riI5omL44GM44GL44KKIg0KICAgICksDQogICAgZXN0aW1hdGVfYmFzZWxpbmVfcGN0X3Blcl9vcHRpb24gPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICBjb25mX2xvd19iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9IGNvbmZfbG93ICogMTAwLA0KICAgIGNvbmZfaGlnaF9iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9IGNvbmZfaGlnaCAqIDEwMA0KICApDQoNCndyaXRlX2Nzdl91bmlmaWVkKA0KICBjaG9pY2Vfc2V0X2FkanVzdGVkX3Nsb3BlX3N1bW1hcnksDQogICJjaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2VfbGluZWFyX3Nsb3Blcy5jc3YiDQopDQoNCmh5cG90aGVzaXNfbWFwIDwtIHRpYmJsZTo6dHJpYmJsZSgNCiAgfnN0dWR5X2lkLCB+aHlwb3RoZXNpcywgfnN0YXRpc3RpYywgfmV4cGVjdGVkX2RpcmVjdGlvbiwNCiAgInN0dWR5MSIsICJIMWHvvIjlrp/pqJMx77yJIiwgInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiLCAicG9zaXRpdmUiLA0KICAic3R1ZHkxIiwgIkgxYu+8iOWun+mokzHvvIkiLCAiZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSIsICJuZWdhdGl2ZSIsDQogICJzdHVkeTIiLCAiSDFh77yI5a6f6aiTMu+8iSIsICJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwgInBvc2l0aXZlIiwNCiAgInN0dWR5MiIsICJIMWLvvIjlrp/pqJMy77yJIiwgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiLCAibmVnYXRpdmUiLA0KICAic3R1ZHkzIiwgIkgyYe+8iOWun+mokzPvvIkiLCAicGFydHlfaW1wb3J0YW5jZV9wYWlyd2lzZSIsICJwb3NpdGl2ZSIsDQogICJzdHVkeTMiLCAiSDJi77yI5a6f6aiTM++8iSIsICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiwgIm5lZ2F0aXZlIg0KKQ0KDQpoeXBvdGhlc2lzX3Rlc3Rfc3VtbWFyeSA8LSBoeXBvdGhlc2lzX21hcCAlPiUNCiAgZHBseXI6OmxlZnRfam9pbigNCiAgICBjdWVfc2xvcGVfaW5mZXJlbmNlX2FsbCAlPiUNCiAgICAgIGRwbHlyOjpzZWxlY3QoDQogICAgICAgIHN0dWR5X2lkLA0KICAgICAgICBzdHVkeV9sYWJlbCwNCiAgICAgICAgc3RhdGlzdGljLA0KICAgICAgICBlc3RpbWF0ZSwNCiAgICAgICAgY29uZl9sb3csDQogICAgICAgIGNvbmZfaGlnaCwNCiAgICAgICAgcF92YWx1ZV90d29fc2lkZWQNCiAgICAgICksDQogICAgYnkgPSBjKCJzdHVkeV9pZCIsICJzdGF0aXN0aWMiKQ0KICApICU+JQ0KICBkcGx5cjo6bXV0YXRlKA0KICAgIGVzdGltYXRlX2luX2V4cGVjdGVkX2RpcmVjdGlvbiA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gInBvc2l0aXZlIiB+IGVzdGltYXRlID4gMCwNCiAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9PSAibmVnYXRpdmUiIH4gZXN0aW1hdGUgPCAwLA0KICAgICAgVFJVRSB+IE5BDQogICAgKSwNCiAgICBjaV9leGNsdWRlc196ZXJvX2luX2V4cGVjdGVkX2RpcmVjdGlvbiA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICBleHBlY3RlZF9kaXJlY3Rpb24gPT0gInBvc2l0aXZlIiB+IGNvbmZfbG93ID4gMCwNCiAgICAgIGV4cGVjdGVkX2RpcmVjdGlvbiA9PSAibmVnYXRpdmUiIH4gY29uZl9oaWdoIDwgMCwNCiAgICAgIFRSVUUgfiBOQQ0KICAgICksDQogICAgY29uY2x1c2lvbiA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICBjaV9leGNsdWRlc196ZXJvX2luX2V4cGVjdGVkX2RpcmVjdGlvbiB+DQogICAgICAgICLkuojmuKzmlrnlkJHjgac5NSXkv6HpoLzljLrplpPjgYww44KS5ZCr44G+44Ga44CB57Wx6KiI55qE44Gr5pSv5oyBIiwNCiAgICAgIGVzdGltYXRlX2luX2V4cGVjdGVkX2RpcmVjdGlvbiB+DQogICAgICAgICLngrnmjqjlrprjga/kuojmuKzmlrnlkJHjgaDjgYzjgIE5NSXkv6HpoLzljLrplpPjgYww44KS5ZCr44KAIiwNCiAgICAgIFRSVUUgfg0KICAgICAgICAi54K55o6o5a6a44GM5LqI5ris5pa55ZCR44Go5LiA6Ie044GX44Gq44GEIg0KICAgICksDQogICAgZXN0aW1hdGVfcHBfcGVyX29wdGlvbiA9IGVzdGltYXRlICogMTAwLA0KICAgIGNvbmZfbG93X3BwX3Blcl9vcHRpb24gPSBjb25mX2xvdyAqIDEwMCwNCiAgICBjb25mX2hpZ2hfcHBfcGVyX29wdGlvbiA9IGNvbmZfaGlnaCAqIDEwMCwNCiAgICBoeXBvdGhlc2lzID0gZmFjdG9yKA0KICAgICAgaHlwb3RoZXNpcywNCiAgICAgIGxldmVscyA9IHJldihoeXBvdGhlc2lzX21hcCRoeXBvdGhlc2lzKQ0KICAgICkNCiAgKQ0KDQp3cml0ZV9jc3ZfdW5pZmllZCgNCiAgaHlwb3RoZXNpc190ZXN0X3N1bW1hcnksDQogICJtYWluX2h5cG90aGVzaXNfbGluZWFyX3RyZW5kX3Rlc3RzLmNzdiINCikNCg0KcF9oeXBvdGhlc2lzX3Nsb3BlcyA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoDQogIGh5cG90aGVzaXNfdGVzdF9zdW1tYXJ5LA0KICBnZ3Bsb3QyOjphZXMoDQogICAgeCA9IGVzdGltYXRlX3BwX3Blcl9vcHRpb24sDQogICAgeSA9IGh5cG90aGVzaXMsDQogICAgc2hhcGUgPSBleHBlY3RlZF9kaXJlY3Rpb24NCiAgKQ0KKSArDQogIGdncGxvdDI6Omdlb21fdmxpbmUoDQogICAgeGludGVyY2VwdCA9IDAsDQogICAgbGluZXdpZHRoID0gMC40NQ0KICApICsNCiAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcmgoDQogICAgZ2dwbG90Mjo6YWVzKA0KICAgICAgeG1pbiA9IGNvbmZfbG93X3BwX3Blcl9vcHRpb24sDQogICAgICB4bWF4ID0gY29uZl9oaWdoX3BwX3Blcl9vcHRpb24NCiAgICApLA0KICAgIGhlaWdodCA9IDAuMTIsDQogICAgbGluZXdpZHRoID0gMC42MA0KICApICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgNCiAgICBzaXplID0gMi43LA0KICAgIGZpbGwgPSAid2hpdGUiDQogICkgKw0KICBnZ3Bsb3QyOjpzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgIHBvc2l0aXZlID0gMjEsDQogICAgICBuZWdhdGl2ZSA9IDI0DQogICAgKSwNCiAgICBsYWJlbHMgPSBjKA0KICAgICAgcG9zaXRpdmUgPSAi5q2j44Gu5YK+5ZCR44KS5LqI5risIiwNCiAgICAgIG5lZ2F0aXZlID0gIuiyoOOBruWCvuWQkeOCkuS6iOa4rCINCiAgICApDQogICkgKw0KICBnZ3Bsb3QyOjpsYWJzKA0KICAgIHggPSAi6YG45oqe6IKi44GMMeOBpOWil+OBiOOCi+OBqOOBjeOBrumHjeimgeW6puOBruWkieWMlu+8iHBw77yJIiwNCiAgICB5ID0gTlVMTCwNCiAgICBzaGFwZSA9IE5VTEwsDQogICAgY2FwdGlvbiA9IHBhc3RlMCgNCiAgICAgICLph43opoHluqbjga/jgIHlkIzkuIDlsZ7mgKflhoXjga7lhajmsLTmupbjg5rjgqLjgavjgaTjgYTjgabpmZDnlYzlubPlnYfjga7ntbblr77lt67jgpLmsYLjgoHjgIEiLA0KICAgICAgIuOBneOBruW5s+Wdh+OBqOOBl+OBpueul+WHuuOAguaoque3muOBr+WbnuetlOiAheOCr+ODqeOCueOCv+ODu+ODluODvOODiOOCueODiOODqeODg+ODlzk1JeS/oemgvOWMuumWk+OAgiINCiAgICApDQogICkgKw0KICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKw0KICBnZ3Bsb3QyOjp0aGVtZSgNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpDQogICkNCg0Kc2F2ZV9wbG90X2JvdGgoDQogICJmaWdfc3VwcF9oeXBvdGhlc2lzX2xpbmVhcl90cmVuZF90ZXN0cyIsDQogIHBfaHlwb3RoZXNpc19zbG9wZXMsDQogIHdpZHRoID0gOS41LA0KICBoZWlnaHQgPSA1LjgNCikNCg0KY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZV9zdW1tYXJ5IDwtIGNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICBzdHVkeV9jdWVfbGFiZWwgPSBwYXN0ZTAoDQogICAgICBzdHVkeV9sYWJlbCwNCiAgICAgICLvvJoiLA0KICAgICAgY3VlX2ZhbWlseQ0KICAgICksDQogICAgc3R1ZHlfY3VlX2xhYmVsID0gZmFjdG9yKA0KICAgICAgc3R1ZHlfY3VlX2xhYmVsLA0KICAgICAgbGV2ZWxzID0gcmV2KA0KICAgICAgICB1bmlxdWUoc3R1ZHlfY3VlX2xhYmVsKQ0KICAgICAgKQ0KICAgICkNCiAgKQ0KDQpwX2Nob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVzIDwtIGdncGxvdDI6OmdncGxvdCgNCiAgY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZV9zdW1tYXJ5LA0KICBnZ3Bsb3QyOjphZXMoDQogICAgeCA9IGVzdGltYXRlX2Jhc2VsaW5lX3BjdF9wZXJfb3B0aW9uLA0KICAgIHkgPSBzdHVkeV9jdWVfbGFiZWwsDQogICAgc2hhcGUgPSBjdWVfZmFtaWx5DQogICkNCikgKw0KICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKA0KICAgIHhpbnRlcmNlcHQgPSAwLA0KICAgIGxpbmV3aWR0aCA9IDAuNDUNCiAgKSArDQogIGdncGxvdDI6Omdlb21fZXJyb3JiYXJoKA0KICAgIGdncGxvdDI6OmFlcygNCiAgICAgIHhtaW4gPSBjb25mX2xvd19iYXNlbGluZV9wY3RfcGVyX29wdGlvbiwNCiAgICAgIHhtYXggPSBjb25mX2hpZ2hfYmFzZWxpbmVfcGN0X3Blcl9vcHRpb24NCiAgICApLA0KICAgIGhlaWdodCA9IDAuMTIsDQogICAgbGluZXdpZHRoID0gMC42MA0KICApICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgNCiAgICBzaXplID0gMi43LA0KICAgIGZpbGwgPSAid2hpdGUiDQogICkgKw0KICBnZ3Bsb3QyOjpzY2FsZV9zaGFwZV9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICLmlL/lhZrjg7vmlL/lhZrlkI3miYvjgYzjgYvjgooiID0gMjEsDQogICAgICAi57WM5riI5omL44GM44GL44KKIiA9IDI0DQogICAgKQ0KICApICsNCiAgZ2dwbG90Mjo6bGFicygNCiAgICB4ID0gcGFzdGUwKA0KICAgICAgIumBuOaKnuiCouOBjDHjgaTlopfjgYjjgovjgajjgY3jga7oqr/mlbTmuIjjgb/ph43opoHluqbjga7lpInljJYiLA0KICAgICAgIu+8iOW5s+Wdh+mBuOaKnueiuueOh+OBq+WvvuOBmeOCi+WJsuWQiO+8mnBw77yJIg0KICAgICksDQogICAgeSA9IE5VTEwsDQogICAgc2hhcGUgPSBOVUxMLA0KICAgIGNhcHRpb24gPSBwYXN0ZTAoDQogICAgICAi6Kq/5pW05riI44G/6YeN6KaB5bqmID0g5pyq6Kq/5pW06YeN6KaB5bqmIMO377yIMe+8j+mBuOaKnuiCouaVsO+8ieOAgiIsDQogICAgICAi5LqL5YmN55m76Yyy5riI44G/5Luu6Kqs44Gu5Yik5a6a44Gn44Gv44Gq44GP44CB6KiY6L+w55qE44O75oSf5bqm5YiG5p6Q44Go44GX44Gm56S644GZ44CCIg0KICAgICkNCiAgKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDExKSArDQogIGdncGxvdDI6OnRoZW1lKA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikNCiAgKQ0KDQpzYXZlX3Bsb3RfYm90aCgNCiAgImZpZ19zdXBwX2Nob2ljZV9zZXRfYWRqdXN0ZWRfaW1wb3J0YW5jZV9zbG9wZXMiLA0KICBwX2Nob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVzLA0KICB3aWR0aCA9IDEwLjUsDQogIGhlaWdodCA9IDYuMg0KKQ0KDQoNCiMg5pys5paH44Kz44O844OJDQpydW5fc3R1ZHkzX2FsbF9wYXJ0eV9tYXRjaCA8LSBmdW5jdGlvbigpIHsNCiAgZW52IDwtIHN0dWR5M19lbnYNCiAgb3V0X2RpciA8LSBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAic3R1ZHkzX3BhcnR5X21hdGNoX2FsbF9wYXJ0aWVzIikNCiAgZGlyLmNyZWF0ZShvdXRfZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkNCiAgDQogIGRhdCA8LSBlbnYkY29uam9pbnRfbWF0Y2ggJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwNCiAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSksDQogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gYXMuY2hhcmFjdGVyKHN1cHBvcnRfcGFydHlfdmFsaWQpDQogICAgKSAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyKA0KICAgICAgIWlzLm5hKHN1cHBvcnRfcGFydHlfdmFsaWQpLA0KICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCAhPSAiIg0KICAgICkNCiAgDQogIHN1cHBvcnRfY2VsbF9jb3VudHMgPC0gZGF0ICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdChJRCwgc3VwcG9ydF9wYXJ0eV92YWxpZCwgcGFydHlfbikgJT4lDQogICAgZHBseXI6OmNvdW50KA0KICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCwNCiAgICAgIHBhcnR5X24sDQogICAgICBuYW1lID0gIm5fcmVzcG9uZGVudHMiDQogICAgKSAlPiUNCiAgICB0aWR5cjo6Y29tcGxldGUoDQogICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkLA0KICAgICAgcGFydHlfbiA9IDI6NSwNCiAgICAgIGZpbGwgPSBsaXN0KG5fcmVzcG9uZGVudHMgPSAwTCkNCiAgICApICU+JQ0KICAgIGRwbHlyOjpncm91cF9ieShzdXBwb3J0X3BhcnR5X3ZhbGlkKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgbl90b3RhbCA9IHN1bShuX3Jlc3BvbmRlbnRzKSwNCiAgICAgIG1pbl9jZWxsX24gPSBtaW4obl9yZXNwb25kZW50cyksDQogICAgICBhbGxfZm91cl9jb25kaXRpb25zID0gYWxsKG5fcmVzcG9uZGVudHMgPiAwKQ0KICAgICkgJT4lDQogICAgZHBseXI6OnVuZ3JvdXAoKQ0KICANCiAgZWxpZ2libGVfcGFydGllcyA8LSBzdXBwb3J0X2NlbGxfY291bnRzICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdCgNCiAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQsDQogICAgICBuX3RvdGFsLA0KICAgICAgbWluX2NlbGxfbiwNCiAgICAgIGFsbF9mb3VyX2NvbmRpdGlvbnMNCiAgICApICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoDQogICAgICBuX3RvdGFsID49IHVuaWZpZWRfY29uZmlnJG1pbl9zdXBwb3J0X3RvdGFsX24sDQogICAgICBtaW5fY2VsbF9uID49IHVuaWZpZWRfY29uZmlnJG1pbl9zdXBwb3J0X2NlbGxfbiwNCiAgICAgIGFsbF9mb3VyX2NvbmRpdGlvbnMNCiAgICApICU+JQ0KICAgIGRwbHlyOjphcnJhbmdlKGRwbHlyOjpkZXNjKG5fdG90YWwpKSAlPiUNCiAgICBkcGx5cjo6cHVsbChzdXBwb3J0X3BhcnR5X3ZhbGlkKQ0KICANCiAgcmVhZHI6OndyaXRlX2NzdigNCiAgICBzdXBwb3J0X2NlbGxfY291bnRzLA0KICAgIGZpbGUucGF0aChvdXRfZGlyLCAicGFydHlfbWF0Y2hfYWxsX3BhcnR5X3NhbXBsZV9jb3VudHMuY3N2IiksDQogICAgbmEgPSAiIg0KICApDQogIA0KICBmb3JtdWxhX2NlbGwgPC0gc3RhdHM6OmFzLmZvcm11bGEoDQogICAgcGFzdGUoDQogICAgICAic2VsZWN0ZWQgfiIsDQogICAgICBwYXN0ZSgNCiAgICAgICAgYygNCiAgICAgICAgICAicGFydHlfbWF0Y2giLA0KICAgICAgICAgIGVudiRlY29ub21pY19hdHRyX3Rlcm1zDQogICAgICAgICksDQogICAgICAgIGNvbGxhcHNlID0gIiArICINCiAgICAgICkNCiAgICApDQogICkNCiAgDQogIGVzdGltYXRlX2NlbGwgPC0gZnVuY3Rpb24oZ3JvdXBfdmFsdWUsIG5fdmFsdWUpIHsNCiAgICBkYXRfY2VsbCA8LSBkYXQgJT4lDQogICAgICBkcGx5cjo6ZmlsdGVyKA0KICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID09IGdyb3VwX3ZhbHVlLA0KICAgICAgICBwYXJ0eV9uID09IG5fdmFsdWUNCiAgICAgICkNCiAgICANCiAgICBuX2lkcyA8LSBkcGx5cjo6bl9kaXN0aW5jdChkYXRfY2VsbCRJRCkNCiAgICANCiAgICBpZiAobl9pZHMgPCB1bmlmaWVkX2NvbmZpZyRtaW5fc3VwcG9ydF9jZWxsX24pIHsNCiAgICAgIHJldHVybigNCiAgICAgICAgdGliYmxlOjp0aWJibGUoDQogICAgICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9IGdyb3VwX3ZhbHVlLA0KICAgICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLA0KICAgICAgICAgIG5faWRzID0gbl9pZHMsDQogICAgICAgICAgZXN0aW1hdGUgPSBOQV9yZWFsXywNCiAgICAgICAgICBzdGQuZXJyb3IgPSBOQV9yZWFsXywNCiAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLA0KICAgICAgICAgIGNvbmYuaGlnaCA9IE5BX3JlYWxfLA0KICAgICAgICAgIHAudmFsdWUgPSBOQV9yZWFsXywNCiAgICAgICAgICBzdGF0dXMgPSAiaW5zdWZmaWNpZW50X2NlbGxfbiINCiAgICAgICAgKQ0KICAgICAgKQ0KICAgIH0NCiAgICANCiAgICBtb2RlbCA8LSB0cnlDYXRjaCgNCiAgICAgIGZpeGVzdDo6ZmVvbHMoDQogICAgICAgIGZvcm11bGFfY2VsbCwNCiAgICAgICAgZGF0YSA9IGRhdF9jZWxsLA0KICAgICAgICB2Y292ID0gfiBJRA0KICAgICAgKSwNCiAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgZQ0KICAgICkNCiAgICANCiAgICBpZiAoaW5oZXJpdHMobW9kZWwsICJlcnJvciIpKSB7DQogICAgICByZXR1cm4oDQogICAgICAgIHRpYmJsZTo6dGliYmxlKA0KICAgICAgICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgPSBncm91cF92YWx1ZSwNCiAgICAgICAgICBwYXJ0eV9uID0gbl92YWx1ZSwNCiAgICAgICAgICBuX2lkcyA9IG5faWRzLA0KICAgICAgICAgIGVzdGltYXRlID0gTkFfcmVhbF8sDQogICAgICAgICAgc3RkLmVycm9yID0gTkFfcmVhbF8sDQogICAgICAgICAgY29uZi5sb3cgPSBOQV9yZWFsXywNCiAgICAgICAgICBjb25mLmhpZ2ggPSBOQV9yZWFsXywNCiAgICAgICAgICBwLnZhbHVlID0gTkFfcmVhbF8sDQogICAgICAgICAgc3RhdHVzID0gcGFzdGUwKCJtb2RlbF9lcnJvcjogIiwgY29uZGl0aW9uTWVzc2FnZShtb2RlbCkpDQogICAgICAgICkNCiAgICAgICkNCiAgICB9DQogICAgDQogICAgdGlkeV9maXhlc3RfdW5pZmllZChtb2RlbCkgJT4lDQogICAgICBkcGx5cjo6ZmlsdGVyKHRlcm0gPT0gInBhcnR5X21hdGNoIikgJT4lDQogICAgICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gZ3JvdXBfdmFsdWUsDQogICAgICAgIHBhcnR5X24gPSBuX3ZhbHVlLA0KICAgICAgICBuX2lkcyA9IG5faWRzLA0KICAgICAgICBlc3RpbWF0ZSwNCiAgICAgICAgc3RkLmVycm9yLA0KICAgICAgICBjb25mLmxvdywNCiAgICAgICAgY29uZi5oaWdoLA0KICAgICAgICBwLnZhbHVlLA0KICAgICAgICBzdGF0dXMgPSAiZXN0aW1hdGVkIg0KICAgICAgKQ0KICB9DQogIA0KICBjZWxsX2NvZWZmaWNpZW50cyA8LSBwdXJycjo6bWFwX2RmcigNCiAgICBlbGlnaWJsZV9wYXJ0aWVzLA0KICAgIGZ1bmN0aW9uKGdyb3VwX3ZhbHVlKSB7DQogICAgICBwdXJycjo6bWFwX2RmcigNCiAgICAgICAgMjo1LA0KICAgICAgICB+IGVzdGltYXRlX2NlbGwoZ3JvdXBfdmFsdWUsIC54KQ0KICAgICAgKQ0KICAgIH0NCiAgKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgZXN0aW1hdGVfcHAgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICAgIGNvbmYubG93X3BwID0gY29uZi5sb3cgKiAxMDAsDQogICAgICBjb25mLmhpZ2hfcHAgPSBjb25mLmhpZ2ggKiAxMDAsDQogICAgICBwYXJ0eV9uX2xhYmVsID0gZmFjdG9yKA0KICAgICAgICBwYXJ0eV9uLA0KICAgICAgICBsZXZlbHMgPSAyOjUsDQogICAgICAgIGxhYmVscyA9IHBhc3RlMCgyOjUsICLpgbjmip7ogqIiKQ0KICAgICAgKSwNCiAgICAgIG1haW5fdGV4dF9wYXJ0eSA9IHN1cHBvcnRfcGFydHlfdmFsaWQgJWluJSBjKA0KICAgICAgICAi6Ieq55Sx5rCR5Li75YWaIiwNCiAgICAgICAgIuS4remBk+aUuemdqemAo+WQiCIsDQogICAgICAgICLnq4vmhrLmsJHkuLvlhZoiLA0KICAgICAgICAi5Y+C5pS/5YWaIg0KICAgICAgKQ0KICAgICkNCiAgDQogIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgY2VsbF9jb2VmZmljaWVudHMsDQogICAgZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9tYXRjaF9hbGxfcGFydHlfY29lZmZpY2llbnRzLmNzdiIpLA0KICAgIG5hID0gIiINCiAgKQ0KICANCiAgZXN0aW1hdGVfdHJlbmQgPC0gZnVuY3Rpb24oZ3JvdXBfdmFsdWUpIHsNCiAgICBkYXRfZ3JvdXAgPC0gZGF0ICU+JQ0KICAgICAgZHBseXI6OmZpbHRlcihzdXBwb3J0X3BhcnR5X3ZhbGlkID09IGdyb3VwX3ZhbHVlKSAlPiUNCiAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgIHBhcnR5X25fZl9oZXRlcm9nZW5laXR5ID0gZmFjdG9yKA0KICAgICAgICAgIHBhcnR5X24sDQogICAgICAgICAgbGV2ZWxzID0gMjo1DQogICAgICAgICksDQogICAgICAgIHBhcnR5X25fY19oZXRlcm9nZW5laXR5ID0gcGFydHlfbiAtIDINCiAgICAgICkNCiAgICANCiAgICBmb3JtdWxhX3RyZW5kIDwtIHN0YXRzOjphcy5mb3JtdWxhKA0KICAgICAgcGFzdGUoDQogICAgICAgICJzZWxlY3RlZCB+IHBhcnR5X25fZl9oZXRlcm9nZW5laXR5ICsgcGFydHlfbWF0Y2ggKyIsDQogICAgICAgICJwYXJ0eV9tYXRjaDpwYXJ0eV9uX2NfaGV0ZXJvZ2VuZWl0eSArIiwNCiAgICAgICAgcGFzdGUoZW52JGVjb25vbWljX2F0dHJfdGVybXMsIGNvbGxhcHNlID0gIiArICIpDQogICAgICApDQogICAgKQ0KICAgIA0KICAgIG1vZGVsIDwtIHRyeUNhdGNoKA0KICAgICAgZml4ZXN0OjpmZW9scygNCiAgICAgICAgZm9ybXVsYV90cmVuZCwNCiAgICAgICAgZGF0YSA9IGRhdF9ncm91cCwNCiAgICAgICAgdmNvdiA9IH4gSUQNCiAgICAgICksDQogICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIGUNCiAgICApDQogICAgDQogICAgaWYgKGluaGVyaXRzKG1vZGVsLCAiZXJyb3IiKSkgew0KICAgICAgcmV0dXJuKA0KICAgICAgICB0aWJibGU6OnRpYmJsZSgNCiAgICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gZ3JvdXBfdmFsdWUsDQogICAgICAgICAgdGVybSA9ICJwYXJ0eV9tYXRjaDpwYXJ0eV9uX2NfaGV0ZXJvZ2VuZWl0eSIsDQogICAgICAgICAgZXN0aW1hdGUgPSBOQV9yZWFsXywNCiAgICAgICAgICBzdGQuZXJyb3IgPSBOQV9yZWFsXywNCiAgICAgICAgICBjb25mLmxvdyA9IE5BX3JlYWxfLA0KICAgICAgICAgIGNvbmYuaGlnaCA9IE5BX3JlYWxfLA0KICAgICAgICAgIHAudmFsdWUgPSBOQV9yZWFsXywNCiAgICAgICAgICBzdGF0dXMgPSBwYXN0ZTAoIm1vZGVsX2Vycm9yOiAiLCBjb25kaXRpb25NZXNzYWdlKG1vZGVsKSkNCiAgICAgICAgKQ0KICAgICAgKQ0KICAgIH0NCiAgICANCiAgICB0aWR5X2ZpeGVzdF91bmlmaWVkKG1vZGVsKSAlPiUNCiAgICAgIGRwbHlyOjpmaWx0ZXIoDQogICAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoDQogICAgICAgICAgdGVybSwNCiAgICAgICAgICAicGFydHlfbWF0Y2g6cGFydHlfbl9jX2hldGVyb2dlbmVpdHl8cGFydHlfbl9jX2hldGVyb2dlbmVpdHk6cGFydHlfbWF0Y2giDQogICAgICAgICkNCiAgICAgICkgJT4lDQogICAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgICBzdXBwb3J0X3BhcnR5X3ZhbGlkID0gZ3JvdXBfdmFsdWUsDQogICAgICAgIHN0YXR1cyA9ICJlc3RpbWF0ZWQiLA0KICAgICAgICAuYmVmb3JlID0gMQ0KICAgICAgKQ0KICB9DQogIA0KICB0cmVuZF9jb2VmZmljaWVudHMgPC0gcHVycnI6Om1hcF9kZnIoDQogICAgZWxpZ2libGVfcGFydGllcywNCiAgICBlc3RpbWF0ZV90cmVuZA0KICApICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBlc3RpbWF0ZV9wcF9wZXJfb3B0aW9uID0gZXN0aW1hdGUgKiAxMDAsDQogICAgICBjb25mLmxvd19wcF9wZXJfb3B0aW9uID0gY29uZi5sb3cgKiAxMDAsDQogICAgICBjb25mLmhpZ2hfcHBfcGVyX29wdGlvbiA9IGNvbmYuaGlnaCAqIDEwMA0KICAgICkNCiAgDQogIHJlYWRyOjp3cml0ZV9jc3YoDQogICAgdHJlbmRfY29lZmZpY2llbnRzLA0KICAgIGZpbGUucGF0aChvdXRfZGlyLCAicGFydHlfbWF0Y2hfYWxsX3BhcnR5X2xpbmVhcl90cmVuZHMuY3N2IiksDQogICAgbmEgPSAiIg0KICApDQogIA0KICBwbG90X2RmIDwtIGNlbGxfY29lZmZpY2llbnRzICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoDQogICAgICBzdGF0dXMgPT0gImVzdGltYXRlZCIsDQogICAgICBpcy5maW5pdGUoZXN0aW1hdGVfcHApDQogICAgKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCA9IGZhY3RvcigNCiAgICAgICAgc3VwcG9ydF9wYXJ0eV92YWxpZCwNCiAgICAgICAgbGV2ZWxzID0gZWxpZ2libGVfcGFydGllcw0KICAgICAgKQ0KICAgICkNCiAgDQogIGlmIChucm93KHBsb3RfZGYpID4gMCkgew0KICAgIHBfYWxsX3BhcnR5X21hdGNoIDwtIGdncGxvdDI6OmdncGxvdCgNCiAgICAgIHBsb3RfZGYsDQogICAgICBnZ3Bsb3QyOjphZXMoDQogICAgICAgIHggPSBwYXJ0eV9uLA0KICAgICAgICB5ID0gZXN0aW1hdGVfcHAsDQogICAgICAgIGdyb3VwID0gMQ0KICAgICAgKQ0KICAgICkgKw0KICAgICAgZ2dwbG90Mjo6Z2VvbV9obGluZSgNCiAgICAgICAgeWludGVyY2VwdCA9IDAsDQogICAgICAgIGxpbmV3aWR0aCA9IDAuNDANCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6Z2VvbV9saW5lKA0KICAgICAgICBsaW5ld2lkdGggPSAwLjY1DQogICAgICApICsNCiAgICAgIGdncGxvdDI6Omdlb21fZXJyb3JiYXIoDQogICAgICAgIGdncGxvdDI6OmFlcygNCiAgICAgICAgICB5bWluID0gY29uZi5sb3dfcHAsDQogICAgICAgICAgeW1heCA9IGNvbmYuaGlnaF9wcA0KICAgICAgICApLA0KICAgICAgICB3aWR0aCA9IDAuMDgsDQogICAgICAgIGxpbmV3aWR0aCA9IDAuNTUNCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgNCiAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgIHNpemUgPSAyLjQNCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCgNCiAgICAgICAgfiBzdXBwb3J0X3BhcnR5X3ZhbGlkLA0KICAgICAgICBuY29sID0gMw0KICAgICAgKSArDQogICAgICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgICAgIGJyZWFrcyA9IDI6NSwNCiAgICAgICAgbGFiZWxzID0gcGFzdGUwKDI6NSwgIumBuOaKnuiCoiIpDQogICAgICApICsNCiAgICAgIGdncGxvdDI6OmxhYnMoDQogICAgICAgIHggPSAi5o+Q56S644GV44KM44KL6YG45oqe6IKi5pWwIiwNCiAgICAgICAgeSA9ICLmlK/mjIHmlL/lhZrjgajmj5DnpLrmlL/lhZrlkI3jga7kuIDoh7TlirnmnpzvvIhwcO+8iSIsDQogICAgICAgIGNhcHRpb24gPSBwYXN0ZTAoDQogICAgICAgICAgIuWQhOaUr+aMgeaUv+WFmuOCteODluOCsOODq+ODvOODl+WGheOBpyBzZWxlY3RlZCB+IHBhcnR5X21hdGNoICsg57WM5riI5bGe5oCn44KS5o6o5a6a44CCIiwNCiAgICAgICAgICAi5qiZ5rqW6Kqk5beu44Gv5Zue562U6ICFSUTjgafjgq/jg6njgrnjgr/ljJbjgIIiDQogICAgICAgICkNCiAgICAgICkgKw0KICAgICAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKw0KICAgICAgZ2dwbG90Mjo6dGhlbWUoDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBnZ3Bsb3QyOjplbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBheGlzLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKQ0KICAgICAgKQ0KICAgIA0KICAgIGdncGxvdDI6Omdnc2F2ZSgNCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9tYXRjaF9hbGxfcGFydGllcy5wbmciKSwNCiAgICAgIHBsb3QgPSBwX2FsbF9wYXJ0eV9tYXRjaCwNCiAgICAgIHdpZHRoID0gMTEuNSwNCiAgICAgIGhlaWdodCA9IG1heCgNCiAgICAgICAgNy4wLA0KICAgICAgICAyLjcgKiBjZWlsaW5nKGxlbmd0aChlbGlnaWJsZV9wYXJ0aWVzKSAvIDMpDQogICAgICApLA0KICAgICAgZHBpID0gNDAwLA0KICAgICAgYmcgPSAid2hpdGUiDQogICAgKQ0KICAgIA0KICAgIGdncGxvdDI6Omdnc2F2ZSgNCiAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKG91dF9kaXIsICJwYXJ0eV9tYXRjaF9hbGxfcGFydGllcy5wZGYiKSwNCiAgICAgIHBsb3QgPSBwX2FsbF9wYXJ0eV9tYXRjaCwNCiAgICAgIHdpZHRoID0gMTEuNSwNCiAgICAgIGhlaWdodCA9IG1heCgNCiAgICAgICAgNy4wLA0KICAgICAgICAyLjcgKiBjZWlsaW5nKGxlbmd0aChlbGlnaWJsZV9wYXJ0aWVzKSAvIDMpDQogICAgICApLA0KICAgICAgZGV2aWNlID0gZ3JEZXZpY2VzOjpjYWlyb19wZGYsDQogICAgICBiZyA9ICJ3aGl0ZSINCiAgICApDQogIH0gZWxzZSB7DQogICAgcF9hbGxfcGFydHlfbWF0Y2ggPC0gTlVMTA0KICB9DQogIA0KICBsaXN0KA0KICAgIHNhbXBsZV9jb3VudHMgPSBzdXBwb3J0X2NlbGxfY291bnRzLA0KICAgIGVsaWdpYmxlX3BhcnRpZXMgPSBlbGlnaWJsZV9wYXJ0aWVzLA0KICAgIGNvZWZmaWNpZW50cyA9IGNlbGxfY29lZmZpY2llbnRzLA0KICAgIHRyZW5kcyA9IHRyZW5kX2NvZWZmaWNpZW50cywNCiAgICBwbG90ID0gcF9hbGxfcGFydHlfbWF0Y2gNCiAgKQ0KfQ0KDQpzdHVkeTNfYWxsX3BhcnR5X21hdGNoX3Jlc3VsdHMgPC0gcnVuX3N0dWR5M19hbGxfcGFydHlfbWF0Y2goKQ0KDQoNCmV4dHJhY3RfY3Jvc3Nfc3R1ZHlfcmVsYXRpdmVfd2VpZ2h0IDwtIGZ1bmN0aW9uKHN0dWR5X3NwZWMpIHsNCiAgZW52IDwtIHN0dWR5X3NwZWMkZW52DQogIA0KICBlbnYkcmVsYXRpdmVfY3VlX2NvbmRpdGlvbl9pbnRlcnZhbHMgJT4lDQogICAgZHBseXI6OmZpbHRlcigNCiAgICAgIHN0YXRpc3RpYyA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIg0KICAgICkgJT4lDQogICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgIHN0dWR5X2lkID0gc3R1ZHlfc3BlYyRzdHVkeV9pZCwNCiAgICAgIHN0dWR5X2xhYmVsID0gc3R1ZHlfc3BlYyRzdHVkeV9sYWJlbCwNCiAgICAgIHBhcnR5X24sDQogICAgICBlc3RpbWF0ZSwNCiAgICAgIGNvbmZfbG93LA0KICAgICAgY29uZl9oaWdoDQogICAgKQ0KfQ0KDQpjcm9zc19zdHVkeV9yZWxhdGl2ZV93ZWlnaHQgPC0gcHVycnI6Om1hcF9kZnIoDQogIHN0dWR5X3NwZWNzLA0KICBleHRyYWN0X2Nyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodA0KKSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICBlc3RpbWF0ZV9wY3QgPSBlc3RpbWF0ZSAqIDEwMCwNCiAgICBjb25mX2xvd19wY3QgPSBjb25mX2xvdyAqIDEwMCwNCiAgICBjb25mX2hpZ2hfcGN0ID0gY29uZl9oaWdoICogMTAwLA0KICAgIHN0dWR5X2xhYmVsID0gZmFjdG9yKA0KICAgICAgc3R1ZHlfbGFiZWwsDQogICAgICBsZXZlbHMgPSB2YXBwbHkoDQogICAgICAgIHN0dWR5X3NwZWNzLA0KICAgICAgICBgW1tgLA0KICAgICAgICBjaGFyYWN0ZXIoMSksDQogICAgICAgICJzdHVkeV9sYWJlbCINCiAgICAgICkNCiAgICApDQogICkNCg0Kd3JpdGVfY3N2X3VuaWZpZWQoDQogIGNyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCwNCiAgImNyb3NzX3N0dWR5X3JlbGF0aXZlX3BhcnR5X3dlaWdodC5jc3YiDQopDQoNCnBfY3Jvc3Nfc3R1ZHlfcmVsYXRpdmUgPC0gZ2dwbG90Mjo6Z2dwbG90KA0KICBjcm9zc19zdHVkeV9yZWxhdGl2ZV93ZWlnaHQsDQogIGdncGxvdDI6OmFlcygNCiAgICB4ID0gcGFydHlfbiwNCiAgICB5ID0gZXN0aW1hdGVfcGN0LA0KICAgIGxpbmV0eXBlID0gc3R1ZHlfbGFiZWwsDQogICAgc2hhcGUgPSBzdHVkeV9sYWJlbCwNCiAgICBncm91cCA9IHN0dWR5X2xhYmVsDQogICkNCikgKw0KICBnZ3Bsb3QyOjpnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSA1MCwNCiAgICBsaW5ldHlwZSA9ICJkb3R0ZWQiLA0KICAgIGxpbmV3aWR0aCA9IDAuNDUNCiAgKSArDQogIGdncGxvdDI6Omdlb21fbGluZSgNCiAgICBsaW5ld2lkdGggPSAwLjgwDQogICkgKw0KICBnZ3Bsb3QyOjpnZW9tX2Vycm9yYmFyKA0KICAgIGdncGxvdDI6OmFlcygNCiAgICAgIHltaW4gPSBjb25mX2xvd19wY3QsDQogICAgICB5bWF4ID0gY29uZl9oaWdoX3BjdA0KICAgICksDQogICAgd2lkdGggPSAwLjA3LA0KICAgIGxpbmV3aWR0aCA9IDAuNjAsDQogICAgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMDgpDQogICkgKw0KICBnZ3Bsb3QyOjpnZW9tX3BvaW50KA0KICAgIHNpemUgPSAyLjcsDQogICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMDgpDQogICkgKw0KICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgYnJlYWtzID0gMjo1LA0KICAgIGxhYmVscyA9IHBhc3RlMCgyOjUsICLpgbjmip7ogqIiKQ0KICApICsNCiAgZ2dwbG90Mjo6c2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAiJSIpLA0KICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcyhuID0gNikNCiAgKSArDQogIGdncGxvdDI6OmxhYnMoDQogICAgeCA9ICLmj5DnpLrjgZXjgozjgovpgbjmip7ogqLmlbAiLA0KICAgIHkgPSAi5pS/5YWa44Gu5omL44GM44GL44KK44Gu55u45a++5q+U6YeNIiwNCiAgICBsaW5ldHlwZSA9IE5VTEwsDQogICAgc2hhcGUgPSBOVUxMLA0KICAgIGNhcHRpb24gPSBwYXN0ZTAoDQogICAgICAi6ZmQ55WM5bmz5Z2H44Gu5bmz5Z2H57W25a++44Oa44Ki5beu44Gr5Z+644Gl44GP44CCIiwNCiAgICAgICLjgqjjg6njg7zjg5Djg7zjga/lm57nrZTogIXjgq/jg6njgrnjgr/jg7vjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5c5NSXkv6HpoLzljLrplpPjgIIiDQogICAgKQ0KICApICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEuNSkgKw0KICBnZ3Bsb3QyOjp0aGVtZSgNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpDQogICkNCg0Kc2F2ZV9wbG90X2JvdGgoDQogICJmaWdfc3VwcF9jcm9zc19zdHVkeV9yZWxhdGl2ZV9wYXJ0eV93ZWlnaHQiLA0KICBwX2Nyb3NzX3N0dWR5X3JlbGF0aXZlLA0KICB3aWR0aCA9IDkuNSwNCiAgaGVpZ2h0ID0gNi4wDQopDQoNCg0KIyDlh7rlipvmlbTnkIbjgrPjg7zjg4kNCm1haW5fdGV4dF9maWd1cmVfbWFuaWZlc3QgPC0gdGliYmxlOjp0cmliYmxlKA0KICB+ZmlndXJlX251bWJlciwgfnN0dWR5LCB+YW5hbHlzaXMsIH5maWxlX3BuZywgfmZpbGVfcGRmLA0KICAiRmlndXJlIDQiLCAiU3R1ZHkgMSIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MSRvdXRwdXRfZGlyLCAiYW1jZV9jb3ZfZmFjZXRfbW9kZWwucG5nIiksDQogIE5BX2NoYXJhY3Rlcl8sDQogICJGaWd1cmUgNSIsICJTdHVkeSAxIiwgIuaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIsDQogIGZpbGUucGF0aCh1bmlmaWVkX2NvbmZpZyRzdHVkeTEkb3V0cHV0X2RpciwgImZpZ19zdHVkeTFfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wbmciKSwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MSRvdXRwdXRfZGlyLCAiZmlnX3N0dWR5MV9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBkZiIpLA0KICAiRmlndXJlIDYiLCAiU3R1ZHkgMiIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MiRvdXRwdXRfZGlyLCAiYW1jZV9jb3ZfZmFjZXRfbW9kZWwucG5nIiksDQogIE5BX2NoYXJhY3Rlcl8sDQogICJGaWd1cmUgNyIsICJTdHVkeSAyIiwgIuaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIsDQogIGZpbGUucGF0aCh1bmlmaWVkX2NvbmZpZyRzdHVkeTIkb3V0cHV0X2RpciwgImZpZ19zdHVkeTJfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wbmciKSwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MiRvdXRwdXRfZGlyLCAiZmlnX3N0dWR5Ml9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBkZiIpLA0KICAiRmlndXJlIDgiLCAiU3R1ZHkgMyIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MyRvdXRwdXRfZGlyLCAiYW1jZV9jb3ZfZmFjZXRfbW9kZWwucG5nIiksDQogIE5BX2NoYXJhY3Rlcl8sDQogICJGaWd1cmUgOSIsICJTdHVkeSAzIiwgIuaUv+WFmuWQjeODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIsDQogIGZpbGUucGF0aCh1bmlmaWVkX2NvbmZpZyRzdHVkeTMkb3V0cHV0X2RpciwgImZpZ19zdHVkeTNfcmVsYXRpdmVfY3VlX3dlaWdodF9qcF9idy5wbmciKSwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MyRvdXRwdXRfZGlyLCAiZmlnX3N0dWR5M19yZWxhdGl2ZV9jdWVfd2VpZ2h0X2pwX2J3LnBkZiIpLA0KICAiRmlndXJlIDEwIiwgIlN0dWR5IDMiLCAi5pSv5oyB5pS/5YWa44Go5o+Q56S65pS/5YWa5ZCN44Gu5LiA6Ie05Yq55p6cIiwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfY29uZmlnJHN0dWR5MyRvdXRwdXRfZGlyLCAicGFydHlfbWF0Y2hfZWZmZWN0X2NvbWJpbmVkLnBuZyIpLA0KICBOQV9jaGFyYWN0ZXJfDQopDQoNCndyaXRlX2Nzdl91bmlmaWVkKA0KICBtYWluX3RleHRfZmlndXJlX21hbmlmZXN0LA0KICAibWFpbl90ZXh0X2ZpZ3VyZV9yZXByb2R1Y3Rpb25fbWFuaWZlc3QuY3N2Ig0KKQ0KDQpzdXBwbGVtZW50X2ZpZ3VyZV9tYW5pZmVzdCA8LSB0aWJibGU6OnRyaWJibGUoDQogIH5zZWN0aW9uLCB+c3R1ZHksIH5hbmFseXNpcywgfmZpbGVfcG5nLA0KICAiQiIsICJTdHVkeSAxIiwgIuWbnuetlOiAheWJsuS7mOODkOODqeODs+OCue+8mkxvdmUgcGxvdCIsDQogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJzdHVkeTFfYXNzaWdubWVudF9iYWxhbmNlX2xvdmVfcGxvdC5wbmciKSwNCiAgIkIiLCAiU3R1ZHkgMiIsICLlm57nrZTogIXlibLku5jjg5Djg6njg7PjgrnvvJpMb3ZlIHBsb3QiLA0KICBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAic3R1ZHkyX2Fzc2lnbm1lbnRfYmFsYW5jZV9sb3ZlX3Bsb3QucG5nIiksDQogICJCIiwgIlN0dWR5IDMiLCAi5Zue562U6ICF5Ymy5LuY44OQ44Op44Oz44K577yaTG92ZSBwbG90IiwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5M19hc3NpZ25tZW50X2JhbGFuY2VfbG92ZV9wbG90LnBuZyIpLA0KICAiQiIsICJTdHVkeSAxIiwgIuWbnuetlOiAheWJsuS7mOODkOODqeODs+OCue+8mjQ15bqm57ea6Ki65patIiwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5MV9hc3NpZ25tZW50X2JhbGFuY2VfZGlhZ29uYWxfcGxvdC5wbmciKSwNCiAgIkIiLCAiU3R1ZHkgMiIsICLlm57nrZTogIXlibLku5jjg5Djg6njg7PjgrnvvJo0NeW6pue3muiouuaWrSIsDQogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJzdHVkeTJfYXNzaWdubWVudF9iYWxhbmNlX2RpYWdvbmFsX3Bsb3QucG5nIiksDQogICJCIiwgIlN0dWR5IDMiLCAi5Zue562U6ICF5Ymy5LuY44OQ44Op44Oz44K577yaNDXluqbnt5roqLrmlq0iLA0KICBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAic3R1ZHkzX2Fzc2lnbm1lbnRfYmFsYW5jZV9kaWFnb25hbF9wbG90LnBuZyIpLA0KICAiQiIsICJTdHVkeSAxIiwgIuWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+Wvvuacn+W+heavlOeOhyIsDQogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJzdHVkeTFfcHJvZmlsZV9yYW5kb21pemF0aW9uX2RpYWdvbmFsX3Bsb3QucG5nIiksDQogICJCIiwgIlN0dWR5IDIiLCAi5bGe5oCn5rC05rqW44Gu6Kaz5ris5q+U546H5a++5pyf5b6F5q+U546HIiwNCiAgZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgInN0dWR5Ml9wcm9maWxlX3JhbmRvbWl6YXRpb25fZGlhZ29uYWxfcGxvdC5wbmciKSwNCiAgIkIiLCAiU3R1ZHkgMyIsICLlsZ7mgKfmsLTmupbjga7oprPmuKzmr5Tnjoflr77mnJ/lvoXmr5TnjociLA0KICBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAic3R1ZHkzX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9kaWFnb25hbF9wbG90LnBuZyIpLA0KICAiQyIsICJTdHVkeSAx4oCTMyIsICJIMWEvSDFiL0gyYS9IMmLjga7nt5rlvaLlgr7lkJHmpJzlrpoiLA0KICBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAiZmlnX3N1cHBfaHlwb3RoZXNpc19saW5lYXJfdHJlbmRfdGVzdHMucG5nIiksDQogICJDIiwgIlN0dWR5IDHigJMzIiwgIumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOBrue3muW9ouWCvuWQkSIsDQogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICJmaWdfc3VwcF9jaG9pY2Vfc2V0X2FkanVzdGVkX2ltcG9ydGFuY2Vfc2xvcGVzLnBuZyIpLA0KICAiQyIsICJTdHVkeSAxIiwgIuacquiqv+aVtOODu+mBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puODu+ebuOWvvuavlOmHjSIsDQogIGZpbGUucGF0aCgNCiAgICB1bmlmaWVkX2NvbmZpZyRzdHVkeTEkb3V0cHV0X2RpciwNCiAgICAiZmlnX3N0dWR5MV9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYncucG5nIg0KICApLA0KICAiQyIsICJTdHVkeSAyIiwgIuacquiqv+aVtOODu+mBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puODu+ebuOWvvuavlOmHjSIsDQogIGZpbGUucGF0aCgNCiAgICB1bmlmaWVkX2NvbmZpZyRzdHVkeTIkb3V0cHV0X2RpciwNCiAgICAiZmlnX3N0dWR5Ml9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYncucG5nIg0KICApLA0KICAiQyIsICJTdHVkeSAzIiwgIuacquiqv+aVtOODu+mBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puODu+ebuOWvvuavlOmHjSIsDQogIGZpbGUucGF0aCgNCiAgICB1bmlmaWVkX2NvbmZpZyRzdHVkeTMkb3V0cHV0X2RpciwNCiAgICAiZmlnX3N0dWR5M19yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYncucG5nIg0KICApLA0KICAiRiIsICJTdHVkeSAx4oCTMyIsICLmlL/lhZrmiYvjgYzjgYvjgornm7jlr77mr5Tph43jga7mqKrmlq3mr5TovIMiLA0KICBmaWxlLnBhdGgodW5pZmllZF9vdXRwdXRfZGlyLCAiZmlnX3N1cHBfY3Jvc3Nfc3R1ZHlfcmVsYXRpdmVfcGFydHlfd2VpZ2h0LnBuZyIpLA0KICAiRyIsICJTdHVkeSAzIiwgIuWFqOOBpuOBruWNgeWIhuOBquaomeacrOOCkuOCguOBpOaUr+aMgeaUv+WFmuOBruS4gOiHtOWKueaenCIsDQogIGZpbGUucGF0aCgNCiAgICB1bmlmaWVkX291dHB1dF9kaXIsDQogICAgInN0dWR5M19wYXJ0eV9tYXRjaF9hbGxfcGFydGllcyIsDQogICAgInBhcnR5X21hdGNoX2FsbF9wYXJ0aWVzLnBuZyINCiAgKSwNCiAgIkciLCAiU3R1ZHkgMeKAkzMiLCAi5pSv5oyB5pS/5YWa5YilQU1DReODu+ebuOWvvuavlOmHjSIsDQogIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsICI8c3R1ZHk+X3BhcnR5X3N1cHBvcnQiKQ0KKQ0KDQp3cml0ZV9jc3ZfdW5pZmllZCgNCiAgc3VwcGxlbWVudF9maWd1cmVfbWFuaWZlc3QsDQogICJzdXBwbGVtZW50X2ZpZ3VyZV9tYW5pZmVzdC5jc3YiDQopDQoNCnN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdCA8LSB0aWJibGU6OnRyaWJibGUoDQogIH5zZWN0aW9uLCB+dGl0bGUsIH5wbGFjZW1lbnRfbG9naWMsIH5jb3JlX291dHB1dHMsDQogICJBIiwgIuiqv+afu+ioreioiOODu+izquWVj+aWh+ODu+aomeacrOani+eviSIsDQogICLoqq3ogIXjgYwz5a6f6aiT44Gu55u46YGV44Go5YiG5p6Q5a++6LGh6ICF44Gu5b2i5oiQ44KS5YWI44Gr56K66KqN44Gn44GN44KL44KI44GG44Gr44GZ44KL44CCIiwNCiAgIuiqv+afu+ODleODreODvOOAgeWxnuaAp+ODu+awtOa6luOAgeizquWVj+aWh+OAgXNhbXBsZV9mbG9344CB5p2h5Lu25YilbuOAgeasoOaQjembhuioiCIsDQogICJCIiwgIueEoeS9nOeCuuWJsuS7mOODu+WxnuaAp+aPkOekuuODu+ODh+ODvOOCv+WTgeizquOBruiouuaWrSIsDQogICLmjqjlrprntZDmnpzjgojjgorliY3jgavjgIHlh6bnva7mnaHku7bjgajjgrPjg7Pjgrjjg6fjgqTjg7Pjg4jlsZ7mgKfjga7nhKHkvZzngrrljJbjgYzmqZ/og73jgZfjgZ/jgZPjgajjgpLnpLrjgZnjgIIiLA0KICAi5p2h5Lu25Yil5YWx5aSJ6YeP6KGo44CB5YWoNuadoeS7tuODmuOCouOBrlNNROOAgUxvdmUgcGxvdOOAgTQ15bqm57ea5Zuz44CB5bGe5oCn5rC05rqW44Gu6Kaz5ris5a++5pyf5b6F5q+U546HIiwNCiAgIkMiLCAi5o6o5a6a6YeP44O755u45a++5q+U6YeN44O75Luu6Kqs5qSc5a6aIiwNCiAgIuacrOaWh+OBruW8jygxKSgyKeOBqEgxYS9IMWIvSDJhL0gyYuOBruWIpOWumuaWueazleOCkuS4gOOBi+aJgOOBq+mbhue0hOOBmeOCi+OAgiIsDQogIHBhc3RlMCgNCiAgICAiQU1DReOAgemZkOeVjOW5s+Wdh+OAgeW5s+Wdh+e1tuWvvuODmuOCouW3ruOAgemBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOAgSIsDQogICAgIuebuOWvvuavlOmHjeOAgeODluODvOODiOOCueODiOODqeODg+ODl+OAgee3muW9ouWCvuWQkee1seWQiOihqCINCiAgKSwNCiAgIkQiLCAi5a6f6aiTMe+8iDIwMjPlubTvvInjga7lrozlhajjgarntZDmnpwiLA0KICAi5pys5paH5ZuzNOODuzXjga7lho3nj77lvozjgavjgIHoo5zliqnliIbmnpDjgpLlkIzjgZjlrp/pqJPlhoXjgafjgb7jgajjgoHjgovjgIIiLA0KICAi6Kq/5pW05riI44G/44O75pyq6Kq/5pW0QU1DReOAgeS6pOS6kuS9nOeUqOOAgeODkuODvOODiOODnuODg+ODl+OAgeadoeS7tuS7mOOBjeODreOCuOODg+ODiOOAgeebuOWvvuavlOmHjeWCvuWQkSIsDQogICJFIiwgIuWun+mokzLvvIgyMDI25bm077yJ44GoMjAyM+KAkzIwMjblubTmr5TovIMiLA0KICAi5a6f6aiTMeOBruWGjeePvuaAp+OBqOaZgueCuemWk+WkieWMluOCkumAo+e2muOBl+OBpuiqreOCgeOCi+OCiOOBhuOBq+OBmeOCi+OAgiIsDQogICLoqr/mlbTmuIjjgb/jg7vmnKroqr/mlbRBTUNF44CB5Lqk5LqS5L2c55So44CB44OS44O844OI44Oe44OD44OX44CB5p2h5Lu25LuY44GN44Ot44K444OD44OI44CB55u45a++5q+U6YeN5YK+5ZCR44CB5pmC54K55q+U6LyDIiwNCiAgIkYiLCAi5a6f6aiTM++8iDIwMjblubTvvInjga7lrozlhajjgarntZDmnpwiLA0KICAi5YW35L2T55qE5pS/5YWa5ZCN44Gu5YiG5p6Q44Go44CB5pys5paH5ZuzOOODuznjg7sxMOOBrui/veWKoOaOqOWumuOCkuOBvuOBqOOCgeOCi+OAgiIsDQogICJBTUNF44CB44Kr44OG44K044Oq44Kr44Or44O757ea5b2i44OI44Os44Oz44OJ44CB5p2h5Lu25LuY44GN44Ot44K444OD44OI44CB55u45a++5q+U6YeN44CB5LiA6Ie05Yq55p6cIiwNCiAgIkciLCAi5pS/5YWa5pSv5oyB44Gr44KI44KL55Ww6LOq5oCnIiwNCiAgIuacrOaWh+OBruWFmua0vuaAp+ODoeOCq+ODi+OCuuODoOOBq+ebtOe1kOOBmeOCi+OBn+OCgeOAgemgkeWBpeaAp+WIhuaekOOBi+OCieeLrOeri+OBleOBm+OCi+OAgiIsDQogICLmlK/mjIHmlL/lhZrliKVBTUNF44CB5pSv5oyB5pS/5YWaw5flsZ7mgKdXYWxk5qSc5a6a44CB5pSv5oyB5pS/5YWa5Yil55u45a++5q+U6YeN44CB5YWo5pS/5YWa5LiA6Ie05Yq55p6cIiwNCiAgIkgiLCAi6Zmk5aSW5Z+65rqW44O75o6o5a6a5rOV44O75qiZ5pys5a6a576p44Gr6Zai44GZ44KL5oSf5bqm5YiG5p6QIiwNCiAgIuS4u+imgee1kOirluOBjOWIhuaekOS4iuOBrumBuOaKnuOBq+S+neWtmOOBl+OBquOBhOOBi+OCkuacgOW+jOOBq+eiuuiqjeOBmeOCi+OAgiIsDQogICLms6jmhI/jg7vmk43kvZznorroqo3jgIHlrozlhag16Kqy6aGM44CB5YWx5aSJ6YeP44Gq44GX44CB5p2h5Lu25LuY44GN44Ot44K444OD44OI44CB5Luj5pu/5qiZ5pysIiwNCiAgIkkiLCAi5YaN54++5oCn5oOF5aCxIiwNCiAgIuWFqOOBpuOBruWIhuaekOW+jOOBq+OAgeWGjeePvuOBq+W/heimgeOBquaKgOihk+aDheWgseOCkuOBvuOBqOOCgeOCi+OAgiIsDQogICLjg5XjgqHjgqTjg6vkuIDopqfjgIHkubHmlbDjgrfjg7zjg4njgIHjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5flm57mlbDjgIHjg5Hjg4PjgrHjg7zjgrjjgIFzZXNzaW9uSW5mbyINCikNCg0Kd3JpdGVfY3N2X3VuaWZpZWQoDQogIHN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdCwNCiAgInN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdC5jc3YiDQopDQoNCnNhdmVSRFMoDQogIGxpc3QoDQogICAgY29uZmlnID0gdW5pZmllZF9jb25maWcsDQogICAgYXNzaWdubWVudF9iYWxhbmNlID0gYXNzaWdubWVudF9iYWxhbmNlX3Jlc3VsdHMsDQogICAgcHJvZmlsZV9yYW5kb21pemF0aW9uID0gcHJvZmlsZV9yYW5kb21pemF0aW9uX3Jlc3VsdHMsDQogICAgY3VlX3Nsb3BlX2luZmVyZW5jZSA9IGN1ZV9zbG9wZV9pbmZlcmVuY2VfYWxsLA0KICAgIGNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSA9DQogICAgICBjaG9pY2Vfc2V0X2FkanVzdGVkX3Nsb3BlX3N1bW1hcnksDQogICAgY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZV9wbG90ID0NCiAgICAgIHBfY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZXMsDQogICAgaHlwb3RoZXNpc190ZXN0cyA9IGh5cG90aGVzaXNfdGVzdF9zdW1tYXJ5LA0KICAgIHBhcnR5X3N1cHBvcnRfYW1jZSA9IHBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzLA0KICAgIHBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlID0gcGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfcmVzdWx0cywNCiAgICBzdHVkeTNfYWxsX3BhcnR5X21hdGNoID0gc3R1ZHkzX2FsbF9wYXJ0eV9tYXRjaF9yZXN1bHRzLA0KICAgIGNyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCA9IGNyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCwNCiAgICBjcm9zc19zdHVkeV9yZWxhdGl2ZV9wbG90ID0gcF9jcm9zc19zdHVkeV9yZWxhdGl2ZSwNCiAgICBtYWluX3RleHRfZmlndXJlX21hbmlmZXN0ID0gbWFpbl90ZXh0X2ZpZ3VyZV9tYW5pZmVzdCwNCiAgICBzdXBwbGVtZW50X2ZpZ3VyZV9tYW5pZmVzdCA9IHN1cHBsZW1lbnRfZmlndXJlX21hbmlmZXN0LA0KICAgIHN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdCA9IHN1cHBsZW1lbnRfc2VjdGlvbl9tYW5pZmVzdA0KICApLA0KICBmaWxlID0gZmlsZS5wYXRoKA0KICAgIHVuaWZpZWRfb3V0cHV0X2RpciwNCiAgICAidW5pZmllZF9zdXBwbGVtZW50X29iamVjdHMucmRzIg0KICApDQopDQoNCmNhcHR1cmUub3V0cHV0KA0KICBzZXNzaW9uSW5mbygpLA0KICBmaWxlID0gZmlsZS5wYXRoKA0KICAgIHVuaWZpZWRfb3V0cHV0X2RpciwNCiAgICAic2Vzc2lvbkluZm9fdW5pZmllZC50eHQiDQogICkNCikNCg0KY2F0KA0KICAiXG4z5a6f6aiT44Gu5pys5paH5Zuz5YaN54++44O76KOc6YG65YiG5p6Q44O75pSv5oyB5pS/5YWa5Yil55Ww6LOq5oCn5YiG5p6Q44GM5a6M5LqG44GX44G+44GX44Gf44CCXG4iLA0KICAi57Wx5ZCI5Ye65Yqb5YWIOiAiLA0KICBub3JtYWxpemVQYXRoKHVuaWZpZWRfb3V0cHV0X2RpciksDQogICJcbiIsDQogIHNlcCA9ICIiDQopDQoNCg0KZmluYWxfb3V0cHV0X3Jvb3QgPC0gdW5pZmllZF9jb25maWckb3V0cHV0X3Jvb3QNCg0KZmluYWxfZGlycyA8LSBsaXN0KA0KICBtYWluX2ZpZ3VyZXMgPSBmaWxlLnBhdGgoZmluYWxfb3V0cHV0X3Jvb3QsICJtYWluX3RleHQiLCAiZmlndXJlcyIpLA0KICBtYWluX3RhYmxlcyA9IGZpbGUucGF0aChmaW5hbF9vdXRwdXRfcm9vdCwgIm1haW5fdGV4dCIsICJ0YWJsZXMiKSwNCiAgc3VwcGxlbWVudF9yb290ID0gZmlsZS5wYXRoKGZpbmFsX291dHB1dF9yb290LCAic3VwcGxlbWVudCIpLA0KICBzdXBwbGVtZW50X2Nyb3NzID0gZmlsZS5wYXRoKGZpbmFsX291dHB1dF9yb290LCAic3VwcGxlbWVudCIsICJjcm9zc19zdHVkeSIpLA0KICBkaWFnbm9zdGljc19yb290ID0gZmlsZS5wYXRoKGZpbmFsX291dHB1dF9yb290LCAiZGlhZ25vc3RpY3MiKSwNCiAgbW9kZWxfb2JqZWN0c19yb290ID0gZmlsZS5wYXRoKGZpbmFsX291dHB1dF9yb290LCAibW9kZWxfb2JqZWN0cyIpLA0KICBsb2dzID0gZmlsZS5wYXRoKGZpbmFsX291dHB1dF9yb290LCAibG9ncyIpDQopDQoNCmludmlzaWJsZSgNCiAgbGFwcGx5KA0KICAgIGZpbmFsX2RpcnMsDQogICAgZGlyLmNyZWF0ZSwNCiAgICBzaG93V2FybmluZ3MgPSBGQUxTRSwNCiAgICByZWN1cnNpdmUgPSBUUlVFDQogICkNCikNCg0KZm9yIChzdHVkeV9pZCBpbiBuYW1lcyhzdHVkeV9zcGVjcykpIHsNCiAgZm9yIChzdWJkaXIgaW4gYygiZmlndXJlcyIsICJ0YWJsZXNfY3N2IiwgInRhYmxlc190ZXgiKSkgew0KICAgIGRpci5jcmVhdGUoDQogICAgICBmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X3Jvb3QsIHN0dWR5X2lkLCBzdWJkaXIpLA0KICAgICAgc2hvd1dhcm5pbmdzID0gRkFMU0UsDQogICAgICByZWN1cnNpdmUgPSBUUlVFDQogICAgKQ0KICB9DQogIGZvciAoc3ViZGlyIGluIGMoInNjcmVlbmluZyIsICJiYWxhbmNlIiwgInJhbmRvbWl6YXRpb24iKSkgew0KICAgIGRpci5jcmVhdGUoDQogICAgICBmaWxlLnBhdGgoZmluYWxfZGlycyRkaWFnbm9zdGljc19yb290LCBzdHVkeV9pZCwgc3ViZGlyKSwNCiAgICAgIHNob3dXYXJuaW5ncyA9IEZBTFNFLA0KICAgICAgcmVjdXJzaXZlID0gVFJVRQ0KICAgICkNCiAgfQ0KICBkaXIuY3JlYXRlKA0KICAgIGZpbGUucGF0aChmaW5hbF9kaXJzJG1vZGVsX29iamVjdHNfcm9vdCwgc3R1ZHlfaWQpLA0KICAgIHNob3dXYXJuaW5ncyA9IEZBTFNFLA0KICAgIHJlY3Vyc2l2ZSA9IFRSVUUNCiAgKQ0KfQ0KDQpmb3IgKHN1YmRpciBpbiBjKCJmaWd1cmVzIiwgInRhYmxlc19jc3YiLCAidGFibGVzX3RleCIpKSB7DQogIGRpci5jcmVhdGUoDQogICAgZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9jcm9zcywgc3ViZGlyKSwNCiAgICBzaG93V2FybmluZ3MgPSBGQUxTRSwNCiAgICByZWN1cnNpdmUgPSBUUlVFDQogICkNCn0NCg0KDQpjb3B5X2ZpbGVfaWZfZXhpc3RzIDwtIGZ1bmN0aW9uKHNvdXJjZSwgZGVzdGluYXRpb24pIHsNCiAgaWYgKGlzLm5hKHNvdXJjZSkgfHwgIW56Y2hhcihzb3VyY2UpIHx8ICFmaWxlLmV4aXN0cyhzb3VyY2UpKSB7DQogICAgcmV0dXJuKEZBTFNFKQ0KICB9DQogIGRpci5jcmVhdGUoZGlybmFtZShkZXN0aW5hdGlvbiksIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQ0KICBpc1RSVUUoZmlsZS5jb3B5KHNvdXJjZSwgZGVzdGluYXRpb24sIG92ZXJ3cml0ZSA9IFRSVUUsIGNvcHkubW9kZSA9IFRSVUUpKQ0KfQ0KDQpjb3B5X2ZpbGVzX2J5X3BhdHRlcm4gPC0gZnVuY3Rpb24oc291cmNlX2RpciwgZGVzdGluYXRpb25fZGlyLCBwYXR0ZXJuKSB7DQogIGlmICghZGlyLmV4aXN0cyhzb3VyY2VfZGlyKSkgew0KICAgIHJldHVybihjaGFyYWN0ZXIoKSkNCiAgfQ0KICBmaWxlcyA8LSBsaXN0LmZpbGVzKA0KICAgIHNvdXJjZV9kaXIsDQogICAgcGF0dGVybiA9IHBhdHRlcm4sDQogICAgZnVsbC5uYW1lcyA9IFRSVUUsDQogICAgcmVjdXJzaXZlID0gVFJVRSwNCiAgICBpZ25vcmUuY2FzZSA9IFRSVUUNCiAgKQ0KICBpZiAobGVuZ3RoKGZpbGVzKSA9PSAwKSB7DQogICAgcmV0dXJuKGNoYXJhY3RlcigpKQ0KICB9DQogIGRpci5jcmVhdGUoZGVzdGluYXRpb25fZGlyLCBzaG93V2FybmluZ3MgPSBGQUxTRSwgcmVjdXJzaXZlID0gVFJVRSkNCiAgZGVzdGluYXRpb25zIDwtIGZpbGUucGF0aChkZXN0aW5hdGlvbl9kaXIsIGJhc2VuYW1lKGZpbGVzKSkNCiAgY29waWVkIDwtIHZhcHBseSgNCiAgICBzZXFfYWxvbmcoZmlsZXMpLA0KICAgIGZ1bmN0aW9uKGkpIGNvcHlfZmlsZV9pZl9leGlzdHMoZmlsZXNbaV0sIGRlc3RpbmF0aW9uc1tpXSksDQogICAgbG9naWNhbCgxKQ0KICApDQogIGRlc3RpbmF0aW9uc1tjb3BpZWRdDQp9DQoNCmxhdGV4X2VzY2FwZSA8LSBmdW5jdGlvbih4KSB7DQogIHggPC0gYXMuY2hhcmFjdGVyKHgpDQogIHhbaXMubmEoeCldIDwtICIiDQoNCiAgZXNjYXBlX29uZSA8LSBmdW5jdGlvbihzKSB7DQogICAgY2hhcnMgPC0gc3Ryc3BsaXQocywgIiIsIGZpeGVkID0gVFJVRSlbWzFdXQ0KDQogICAgaWYgKGxlbmd0aChjaGFycykgPT0gMEwpIHsNCiAgICAgIHJldHVybigiIikNCiAgICB9DQoNCiAgICByZXBsYWNlbWVudCA8LSBjKA0KICAgICAgIlxcIiA9ICJcXHRleHRiYWNrc2xhc2h7fSIsDQogICAgICAiJiIgID0gIlxcJiIsDQogICAgICAiJSIgID0gIlxcJSIsDQogICAgICAiJCIgID0gIlxcJCIsDQogICAgICAiIyIgID0gIlxcIyIsDQogICAgICAiXyIgID0gIlxcXyIsDQogICAgICAieyIgID0gIlxceyIsDQogICAgICAifSIgID0gIlxcfSIsDQogICAgICAifiIgID0gIlxcdGV4dGFzY2lpdGlsZGV7fSIsDQogICAgICAiXiIgID0gIlxcdGV4dGFzY2lpY2lyY3Vte30iDQogICAgKQ0KDQogICAgb3V0IDwtIHZhcHBseSgNCiAgICAgIGNoYXJzLA0KICAgICAgZnVuY3Rpb24oY2gpIHsNCiAgICAgICAgaWYgKGNoICVpbiUgbmFtZXMocmVwbGFjZW1lbnQpKSB7DQogICAgICAgICAgdW5uYW1lKHJlcGxhY2VtZW50W1tjaF1dKQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIGNoDQogICAgICAgIH0NCiAgICAgIH0sDQogICAgICBjaGFyYWN0ZXIoMSkNCiAgICApDQoNCiAgICBwYXN0ZTAob3V0LCBjb2xsYXBzZSA9ICIiKQ0KICB9DQoNCiAgdmFwcGx5KHgsIGVzY2FwZV9vbmUsIGNoYXJhY3RlcigxKSwgVVNFLk5BTUVTID0gRkFMU0UpDQp9DQoNCmZvcm1hdF9udW1iZXIgPC0gZnVuY3Rpb24oeCwgZGlnaXRzID0gMykgew0KICBvdXQgPC0gaWZlbHNlKA0KICAgIGlzLm5hKHgpLA0KICAgICIiLA0KICAgIGZvcm1hdEMoeCwgZm9ybWF0ID0gImYiLCBkaWdpdHMgPSBkaWdpdHMpDQogICkNCiAgYXMuY2hhcmFjdGVyKG91dCkNCn0NCg0KZm9ybWF0X2ludGVnZXIgPC0gZnVuY3Rpb24oeCkgew0KICBpZmVsc2UoaXMubmEoeCksICIiLCBzY2FsZXM6OmNvbW1hKGFzLmludGVnZXIocm91bmQoeCkpKSkNCn0NCg0KZm9ybWF0X3BfdmFsdWUgPC0gZnVuY3Rpb24oeCkgew0KICBkcGx5cjo6Y2FzZV93aGVuKA0KICAgIGlzLm5hKHgpIH4gIiIsDQogICAgeCA8IDAuMDAxIH4gIjwgLjAwMSIsDQogICAgVFJVRSB+IHN1YigiXjAiLCAiIiwgZm9ybWF0Qyh4LCBmb3JtYXQgPSAiZiIsIGRpZ2l0cyA9IDMpKQ0KICApDQp9DQoNCndyaXRlX2xhdGV4X2xvbmd0YWJsZSA8LSBmdW5jdGlvbigNCiAgICBkYXRhLA0KICAgIGZpbGUsDQogICAgY2FwdGlvbiwNCiAgICBsYWJlbCwNCiAgICBub3RlcyA9IE5VTEwsDQogICAgbGFuZHNjYXBlID0gbmNvbChkYXRhKSA+PSA3KSB7DQogIA0KICBkYXRhIDwtIGFzLmRhdGEuZnJhbWUoZGF0YSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KICBpZiAobmNvbChkYXRhKSA9PSAwKSB7DQogICAgZGF0YSA8LSBkYXRhLmZyYW1lKG5vdGUgPSAi6Kmy5b2T44GZ44KL5o6o5a6a57WQ5p6c44Gv44GC44KK44G+44Gb44KT44CCIikNCiAgfQ0KICANCiAgZGlzcGxheSA8LSBkYXRhDQogIGRpc3BsYXlbXSA8LSBsYXBwbHkoZGlzcGxheSwgZnVuY3Rpb24oeCkgbGF0ZXhfZXNjYXBlKGFzLmNoYXJhY3Rlcih4KSkpDQogIGhlYWRlcnMgPC0gbGF0ZXhfZXNjYXBlKG5hbWVzKGRpc3BsYXkpKQ0KICANCiAgbnVtZXJpY19jb2x1bW4gPC0gdmFwcGx5KGRhdGEsIGlzLm51bWVyaWMsIGxvZ2ljYWwoMSkpDQogIGFsaWdubWVudCA8LSBwYXN0ZTAoaWZlbHNlKG51bWVyaWNfY29sdW1uLCAiciIsICJsIiksIGNvbGxhcHNlID0gIiIpDQogIA0KICBsaW5lcyA8LSBjaGFyYWN0ZXIoKQ0KICBsaW5lcyA8LSBjKGxpbmVzLCAiJSBHZW5lcmF0ZWQgYXV0b21hdGljYWxseSBieSB0aGUgcmVwbGljYXRpb24gc2NyaXB0LiIpDQogIGlmIChsYW5kc2NhcGUpIHsNCiAgICBsaW5lcyA8LSBjKGxpbmVzLCAiXFxiZWdpbntsYW5kc2NhcGV9IikNCiAgfQ0KICBsaW5lcyA8LSBjKA0KICAgIGxpbmVzLA0KICAgICJcXGJlZ2luZ3JvdXAiLA0KICAgICJcXHNtYWxsIiwNCiAgICBwYXN0ZTAoIlxcYmVnaW57bG9uZ3RhYmxlfXsiLCBhbGlnbm1lbnQsICJ9IiksDQogICAgcGFzdGUwKCJcXGNhcHRpb257IiwgbGF0ZXhfZXNjYXBlKGNhcHRpb24pLCAifVxcbGFiZWx7IiwgbGFiZWwsICJ9XFxcXCIpLA0KICAgICJcXHRvcHJ1bGUiLA0KICAgIHBhc3RlKGhlYWRlcnMsIGNvbGxhcHNlID0gIiAmICIpLA0KICAgICJcXFxcIiwNCiAgICAiXFxtaWRydWxlIiwNCiAgICAiXFxlbmRmaXJzdGhlYWQiLA0KICAgIHBhc3RlMCgiXFxtdWx0aWNvbHVtbnsiLCBuY29sKGRpc3BsYXkpLCAifXtsfXtcXHRhYmxlbmFtZX5cXHRoZXRhYmxle33vvIjntprjgY3vvIl9XFxcXCIpLA0KICAgICJcXHRvcHJ1bGUiLA0KICAgIHBhc3RlKGhlYWRlcnMsIGNvbGxhcHNlID0gIiAmICIpLA0KICAgICJcXFxcIiwNCiAgICAiXFxtaWRydWxlIiwNCiAgICAiXFxlbmRoZWFkIiwNCiAgICBwYXN0ZTAoIlxcbWlkcnVsZVxcbXVsdGljb2x1bW57IiwgbmNvbChkaXNwbGF5KSwgIn17cn175qyh6aCB44Gr57aa44GPfVxcXFwiKSwNCiAgICAiXFxlbmRmb290IiwNCiAgICAiXFxib3R0b21ydWxlIiwNCiAgICAiXFxlbmRsYXN0Zm9vdCINCiAgKQ0KICANCiAgaWYgKG5yb3coZGlzcGxheSkgPiAwKSB7DQogICAgcm93X2xpbmVzIDwtIGFwcGx5KA0KICAgICAgZGlzcGxheSwNCiAgICAgIDEsDQogICAgICBmdW5jdGlvbihyb3cpIHBhc3RlMChwYXN0ZShyb3csIGNvbGxhcHNlID0gIiAmICIpLCAiIFxcXFwiKQ0KICAgICkNCiAgICBsaW5lcyA8LSBjKGxpbmVzLCByb3dfbGluZXMpDQogIH0NCiAgDQogIGxpbmVzIDwtIGMobGluZXMsICJcXGVuZHtsb25ndGFibGV9IikNCiAgaWYgKCFpcy5udWxsKG5vdGVzKSAmJiBuemNoYXIobm90ZXMpKSB7DQogICAgbGluZXMgPC0gYygNCiAgICAgIGxpbmVzLA0KICAgICAgIlxcdnNwYWNley0wLjVlbX0iLA0KICAgICAgIlxcYmVnaW57bWluaXBhZ2V9e1xcbGluZXdpZHRofSIsDQogICAgICAiXFxmb290bm90ZXNpemUiLA0KICAgICAgcGFzdGUwKCJcXHRleHRpdHvms6jvvJp9IiwgbGF0ZXhfZXNjYXBlKG5vdGVzKSksDQogICAgICAiXFxlbmR7bWluaXBhZ2V9Ig0KICAgICkNCiAgfQ0KICBsaW5lcyA8LSBjKGxpbmVzLCAiXFxlbmRncm91cCIpDQogIGlmIChsYW5kc2NhcGUpIHsNCiAgICBsaW5lcyA8LSBjKGxpbmVzLCAiXFxlbmR7bGFuZHNjYXBlfSIpDQogIH0NCiAgDQogIGRpci5jcmVhdGUoZGlybmFtZShmaWxlKSwgc2hvd1dhcm5pbmdzID0gRkFMU0UsIHJlY3Vyc2l2ZSA9IFRSVUUpDQogIHdyaXRlTGluZXMobGluZXMsIGNvbiA9IGZpbGUsIHVzZUJ5dGVzID0gVFJVRSkNCiAgaW52aXNpYmxlKGZpbGUpDQp9DQoNCndyaXRlX2Nzdl9hbmRfdGV4IDwtIGZ1bmN0aW9uKA0KICAgIGRhdGEsDQogICAgY3N2X2ZpbGUsDQogICAgdGV4X2ZpbGUsDQogICAgY2FwdGlvbiwNCiAgICBsYWJlbCwNCiAgICBub3RlcyA9IE5VTEwsDQogICAgbGFuZHNjYXBlID0gbmNvbChkYXRhKSA+PSA3KSB7DQogIGRpci5jcmVhdGUoZGlybmFtZShjc3ZfZmlsZSksIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQ0KICByZWFkcjo6d3JpdGVfY3N2KGRhdGEsIGNzdl9maWxlLCBuYSA9ICIiKQ0KICB3cml0ZV9sYXRleF9sb25ndGFibGUoDQogICAgZGF0YSA9IGRhdGEsDQogICAgZmlsZSA9IHRleF9maWxlLA0KICAgIGNhcHRpb24gPSBjYXB0aW9uLA0KICAgIGxhYmVsID0gbGFiZWwsDQogICAgbm90ZXMgPSBub3RlcywNCiAgICBsYW5kc2NhcGUgPSBsYW5kc2NhcGUNCiAgKQ0KICBpbnZpc2libGUobGlzdChjc3YgPSBjc3ZfZmlsZSwgdGV4ID0gdGV4X2ZpbGUpKQ0KfQ0KDQphdHRyaWJ1dGVfbGFiZWxfbWFwIDwtIGMoDQogIHBvbGljeV9wb3NpdGlvbiA9ICLmlL/nrZbkvY3nva4iLA0KICBnb3Zlcm5tZW50X3N0YXR1cyA9ICLkuI7ph47lhZrlnLDkvY0iLA0KICBzZWF0cyA9ICLorbDluK3mlbAiLA0KICBwYXJ0eV9uYW1lID0gIuaUv+WFmuWQjSIsDQogIGdkcF9ncm93dGggPSAiR0RQ5oiQ6ZW3546HIiwNCiAgbmlra2VpID0gIuaXpee1jOW5s+Wdh+agquS+oSIsDQogIGNwaSA9ICLmtojosrvogIXniankvqHmjIfmlbDvvIhDUEnvvIkiLA0KICB1bmVtcGxveW1lbnQgPSAi5aSx5qWt546HIg0KKQ0KDQpjdWVfZmFtaWx5X2xhYmVsIDwtIGMoDQogIHBhcnR5ID0gIuaUv+WFmuOBruaJi+OBjOOBi+OCiiIsDQogIGVjb25vbWljID0gIue1jOa4iOOBruaJi+OBjOOBi+OCiiINCikNCg0KDQpzY3JlZW5pbmdfc3BlY3MgPC0gbGlzdCgNCiAgc3R1ZHkxID0gbGlzdCgNCiAgICBpbml0aWFsX2NvbnNlbnRfdmFyID0gIlExLjEiLA0KICAgIGZpbmFsX2NvbnNlbnRfdmFyID0gc3R1ZHkxX2VudiRmaW5hbF9jb25zZW50X3ZhciwNCiAgICBhdHRlbnRpb25fdmFyID0gTkFfY2hhcmFjdGVyXywNCiAgICBhdHRlbnRpb25fYW5zd2VyID0gTkFfY2hhcmFjdGVyXywNCiAgICBtYW5pcHVsYXRpb25fYXZhaWxhYmxlID0gRkFMU0UsDQogICAgaW50cm9fbWFwID0gTlVMTA0KICApLA0KICBzdHVkeTIgPSBsaXN0KA0KICAgIGluaXRpYWxfY29uc2VudF92YXIgPSAiUTEuMSIsDQogICAgZmluYWxfY29uc2VudF92YXIgPSBzdHVkeTJfZW52JGZpbmFsX2NvbnNlbnRfdmFyLA0KICAgIGF0dGVudGlvbl92YXIgPSBzdHVkeTJfZW52JGF0dGVudGlvbl9jaGVja192YXIsDQogICAgYXR0ZW50aW9uX2Fuc3dlciA9IGFzLmNoYXJhY3RlcihzdHVkeTJfZW52JGF0dGVudGlvbl9jaGVja19jb3JyZWN0KSwNCiAgICBtYW5pcHVsYXRpb25fYXZhaWxhYmxlID0gVFJVRSwNCiAgICBpbnRyb19tYXAgPSBOVUxMDQogICksDQogIHN0dWR5MyA9IGxpc3QoDQogICAgaW5pdGlhbF9jb25zZW50X3ZhciA9ICJRMS4xIiwNCiAgICBmaW5hbF9jb25zZW50X3ZhciA9IHN0dWR5M19lbnYkZmluYWxfY29uc2VudF92YXIsDQogICAgYXR0ZW50aW9uX3ZhciA9IHN0dWR5M19lbnYkYXR0ZW50aW9uX2NoZWNrX3ZhciwNCiAgICBhdHRlbnRpb25fYW5zd2VyID0gYXMuY2hhcmFjdGVyKHN0dWR5M19lbnYkYXR0ZW50aW9uX2NoZWNrX2NvcnJlY3QpLA0KICAgIG1hbmlwdWxhdGlvbl9hdmFpbGFibGUgPSBUUlVFLA0KICAgIGludHJvX21hcCA9IE5VTEwNCiAgKQ0KKQ0KDQpyZXNwb25zZV9wcmVzZW50IDwtIGZ1bmN0aW9uKHgpIHsNCiAgeCA8LSBhcy5jaGFyYWN0ZXIoeCkNCiAgIWlzLm5hKHgpICYgc3RyaW5ncjo6c3RyX3NxdWlzaCh4KSAhPSAiIg0KfQ0KDQpyZXNwb25zZV9pc19jb2RlIDwtIGZ1bmN0aW9uKHgsIGNvZGUpIHsNCiAgeCA8LSBzdHJpbmdyOjpzdHJfc3F1aXNoKGFzLmNoYXJhY3Rlcih4KSkNCiAgY29kZSA8LSBhcy5jaGFyYWN0ZXIoY29kZSkNCiAgb3V0IDwtIHggPT0gY29kZSB8IHN0cmluZ3I6OnN0cl9kZXRlY3QoeCwgcGFzdGUwKCJcXCgiLCBjb2RlLCAiXFwpJCIpKQ0KICBvdXRbaXMubmEob3V0KV0gPC0gRkFMU0UNCiAgb3V0DQp9DQoNCmdldF9tYXBwZWRfcmVzcG9uc2UgPC0gZnVuY3Rpb24oZGF0YSwgYXNzaWduZWRfbiwgbWFwLCB2YWx1ZV9jb2x1bW4pIHsNCiAgcmVzdWx0IDwtIHJlcChOQV9jaGFyYWN0ZXJfLCBucm93KGRhdGEpKQ0KICBmb3IgKG5fdmFsdWUgaW4gMjo1KSB7DQogICAgcm93IDwtIG1hcFttYXAkcGFydHlfbiA9PSBuX3ZhbHVlLCAsIGRyb3AgPSBGQUxTRV0NCiAgICBpZiAobnJvdyhyb3cpID09IDApIG5leHQNCiAgICB2YXJpYWJsZSA8LSBhcy5jaGFyYWN0ZXIocm93W1t2YWx1ZV9jb2x1bW5dXVsxXSkNCiAgICBpZiAoIXZhcmlhYmxlICVpbiUgbmFtZXMoZGF0YSkpIG5leHQNCiAgICB0YWtlIDwtICFpcy5uYShhc3NpZ25lZF9uKSAmIGFzc2lnbmVkX24gPT0gbl92YWx1ZQ0KICAgIHJlc3VsdFt0YWtlXSA8LSBhcy5jaGFyYWN0ZXIoZGF0YVtbdmFyaWFibGVdXVt0YWtlXSkNCiAgfQ0KICByZXN1bHQNCn0NCg0KaW5mZXJfYXNzaWduZWRfY29uZGl0aW9uIDwtIGZ1bmN0aW9uKGRhdGEsIGNob2ljZV9tYXAsIG1hbmlwdWxhdGlvbl9tYXAgPSBOVUxMLCBpbnRyb19tYXAgPSBOVUxMKSB7DQogIGNhbmRpZGF0ZSA8LSBtYXRyaXgoRkFMU0UsIG5yb3cgPSBucm93KGRhdGEpLCBuY29sID0gNCkNCiAgY29sbmFtZXMoY2FuZGlkYXRlKSA8LSBhcy5jaGFyYWN0ZXIoMjo1KQ0KICANCiAgZm9yIChuX3ZhbHVlIGluIDI6NSkgew0KICAgIHZhcmlhYmxlcyA8LSBjaG9pY2VfbWFwJGNob2ljZV92YXJbY2hvaWNlX21hcCRwYXJ0eV9uID09IG5fdmFsdWVdDQogICAgaWYgKCFpcy5udWxsKG1hbmlwdWxhdGlvbl9tYXApICYmIG5yb3cobWFuaXB1bGF0aW9uX21hcCkgPiAwKSB7DQogICAgICB2YXJpYWJsZXMgPC0gYygNCiAgICAgICAgdmFyaWFibGVzLA0KICAgICAgICBtYW5pcHVsYXRpb25fbWFwJG1hbmlwdWxhdGlvbl92YXJbbWFuaXB1bGF0aW9uX21hcCRwYXJ0eV9uID09IG5fdmFsdWVdDQogICAgICApDQogICAgfQ0KICAgIGlmICghaXMubnVsbChpbnRyb19tYXApICYmIGFzLmNoYXJhY3RlcihuX3ZhbHVlKSAlaW4lIG5hbWVzKGludHJvX21hcCkpIHsNCiAgICAgIHZhcmlhYmxlcyA8LSBjKHZhcmlhYmxlcywgdW5uYW1lKGludHJvX21hcFthcy5jaGFyYWN0ZXIobl92YWx1ZSldKSkNCiAgICB9DQogICAgdmFyaWFibGVzIDwtIGludGVyc2VjdCh1bmlxdWUodmFyaWFibGVzKSwgbmFtZXMoZGF0YSkpDQogICAgaWYgKGxlbmd0aCh2YXJpYWJsZXMpID4gMCkgew0KICAgICAgY2FuZGlkYXRlWywgYXMuY2hhcmFjdGVyKG5fdmFsdWUpXSA8LSBhcHBseSgNCiAgICAgICAgZGF0YVssIHZhcmlhYmxlcywgZHJvcCA9IEZBTFNFXSwNCiAgICAgICAgMSwNCiAgICAgICAgZnVuY3Rpb24ocm93KSBhbnkocmVzcG9uc2VfcHJlc2VudChyb3cpKQ0KICAgICAgKQ0KICAgIH0NCiAgfQ0KICANCiAgbl9jYW5kaWRhdGVzIDwtIHJvd1N1bXMoY2FuZGlkYXRlKQ0KICBhc3NpZ25lZCA8LSByZXAoTkFfaW50ZWdlcl8sIG5yb3coZGF0YSkpDQogIHNpbmdsZSA8LSBuX2NhbmRpZGF0ZXMgPT0gMQ0KICBhc3NpZ25lZFtzaW5nbGVdIDwtIGFzLmludGVnZXIoY29sbmFtZXMoY2FuZGlkYXRlKVttYXguY29sKGNhbmRpZGF0ZVtzaW5nbGUsICwgZHJvcCA9IEZBTFNFXSldKQ0KICANCiAgaWYgKGFueShuX2NhbmRpZGF0ZXMgPiAxKSkgew0KICAgIHdhcm5pbmcoIkNoZWNrIikNCiAgfQ0KICBhc3NpZ25lZA0KfQ0KDQpidWlsZF9zY3JlZW5pbmdfb3V0cHV0cyA8LSBmdW5jdGlvbihzdHVkeV9zcGVjKSB7DQogIHN0dWR5X2lkIDwtIHN0dWR5X3NwZWMkc3R1ZHlfaWQNCiAgZW52IDwtIHN0dWR5X3NwZWMkZW52DQogIHNwZWMgPC0gc2NyZWVuaW5nX3NwZWNzW1tzdHVkeV9pZF1dDQogIHJhdyA8LSBlbnYkZGZfaGVhZGVyX3JlbW92ZWQgJT4lDQogICAgZHBseXI6Om11dGF0ZShJRCA9IGFzLmNoYXJhY3RlcihJRCkpICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdChJRCwgLmtlZXBfYWxsID0gVFJVRSkNCiAgDQogIG1hbmlwdWxhdGlvbl9tYXAgPC0gaWYgKA0KICAgIHNwZWMkbWFuaXB1bGF0aW9uX2F2YWlsYWJsZSAmJg0KICAgIGV4aXN0cygibWFuaXB1bGF0aW9uX21hcCIsIGVudmlyID0gZW52LCBpbmhlcml0cyA9IEZBTFNFKQ0KICApIHsNCiAgICBnZXQoIm1hbmlwdWxhdGlvbl9tYXAiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkNCiAgfSBlbHNlIHsNCiAgICBOVUxMDQogIH0NCiAgDQogIGFzc2lnbmVkX24gPC0gaW5mZXJfYXNzaWduZWRfY29uZGl0aW9uKA0KICAgIGRhdGEgPSByYXcsDQogICAgY2hvaWNlX21hcCA9IGVudiRjaG9pY2VfbWFwLA0KICAgIG1hbmlwdWxhdGlvbl9tYXAgPSBtYW5pcHVsYXRpb25fbWFwLA0KICAgIGludHJvX21hcCA9IHNwZWMkaW50cm9fbWFwDQogICkNCiAgDQogIGlmIChleGlzdHMoImlkX3Rhc2tfY2hlY2siLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsNCiAgICBhbmFseXNpc19hc3NpZ25tZW50IDwtIGdldCgiaWRfdGFza19jaGVjayIsIGVudmlyID0gZW52LCBpbmhlcml0cyA9IEZBTFNFKSAlPiUNCiAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgIElEID0gYXMuY2hhcmFjdGVyKElEKSwNCiAgICAgICAgcGFydHlfbiA9IGFzLmludGVnZXIoYXMuY2hhcmFjdGVyKHBhcnR5X24pKQ0KICAgICAgKSAlPiUNCiAgICAgIGRwbHlyOjpncm91cF9ieShJRCkgJT4lDQogICAgICBkcGx5cjo6c3VtbWFyaXNlKA0KICAgICAgICBuX2NvbmRpdGlvbl9jYW5kaWRhdGVzID0gZHBseXI6Om5fZGlzdGluY3QocGFydHlfbiksDQogICAgICAgIGFzc2lnbmVkX2Zyb21fYW5hbHlzaXMgPSBkcGx5cjo6aWZfZWxzZSgNCiAgICAgICAgICBuX2NvbmRpdGlvbl9jYW5kaWRhdGVzID09IDFMLA0KICAgICAgICAgIGRwbHlyOjpmaXJzdChwYXJ0eV9uKSwNCiAgICAgICAgICBOQV9pbnRlZ2VyXw0KICAgICAgICApLA0KICAgICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgICApDQogICAgDQogICAgYW5hbHlzaXNfbWF0Y2ggPC0gbWF0Y2gocmF3JElELCBhbmFseXNpc19hc3NpZ25tZW50JElEKQ0KICAgIHVzZV9hbmFseXNpc19hc3NpZ25tZW50IDwtICFpcy5uYShhbmFseXNpc19tYXRjaCkgJg0KICAgICAgIWlzLm5hKGFuYWx5c2lzX2Fzc2lnbm1lbnQkYXNzaWduZWRfZnJvbV9hbmFseXNpc1thbmFseXNpc19tYXRjaF0pDQogICAgYXNzaWduZWRfblt1c2VfYW5hbHlzaXNfYXNzaWdubWVudF0gPC0NCiAgICAgIGFuYWx5c2lzX2Fzc2lnbm1lbnQkYXNzaWduZWRfZnJvbV9hbmFseXNpc1thbmFseXNpc19tYXRjaFt1c2VfYW5hbHlzaXNfYXNzaWdubWVudF1dDQogIH0NCiAgDQogIGlmIChleGlzdHMoInZhbGlkX2lkcyIsIGVudmlyID0gZW52LCBpbmhlcml0cyA9IEZBTFNFKSkgew0KICAgIGZpbmFsX2Fzc2lnbm1lbnQgPC0gZ2V0KCJ2YWxpZF9pZHMiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkgJT4lDQogICAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgICBJRCA9IGFzLmNoYXJhY3RlcihJRCksDQogICAgICAgIHBhcnR5X24gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSkNCiAgICAgICkgJT4lDQogICAgICBkcGx5cjo6ZGlzdGluY3QoSUQsIHBhcnR5X24pICU+JQ0KICAgICAgZHBseXI6Omdyb3VwX2J5KElEKSAlPiUNCiAgICAgIGRwbHlyOjpzdW1tYXJpc2UoDQogICAgICAgIG5fY29uZGl0aW9uX2NhbmRpZGF0ZXMgPSBkcGx5cjo6bl9kaXN0aW5jdChwYXJ0eV9uKSwNCiAgICAgICAgYXNzaWduZWRfZnJvbV9maW5hbCA9IGRwbHlyOjppZl9lbHNlKA0KICAgICAgICAgIG5fY29uZGl0aW9uX2NhbmRpZGF0ZXMgPT0gMUwsDQogICAgICAgICAgZHBseXI6OmZpcnN0KHBhcnR5X24pLA0KICAgICAgICAgIE5BX2ludGVnZXJfDQogICAgICAgICksDQogICAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICAgICkNCiAgICANCiAgICBmaW5hbF9tYXRjaCA8LSBtYXRjaChyYXckSUQsIGZpbmFsX2Fzc2lnbm1lbnQkSUQpDQogICAgdXNlX2ZpbmFsX2Fzc2lnbm1lbnQgPC0gIWlzLm5hKGZpbmFsX21hdGNoKSAmDQogICAgICAhaXMubmEoZmluYWxfYXNzaWdubWVudCRhc3NpZ25lZF9mcm9tX2ZpbmFsW2ZpbmFsX21hdGNoXSkNCiAgICBhc3NpZ25lZF9uW3VzZV9maW5hbF9hc3NpZ25tZW50XSA8LQ0KICAgICAgZmluYWxfYXNzaWdubWVudCRhc3NpZ25lZF9mcm9tX2ZpbmFsW2ZpbmFsX21hdGNoW3VzZV9maW5hbF9hc3NpZ25tZW50XV0NCiAgfQ0KICANCiAgaW5pdGlhbF9yZXNwb25zZSA8LSBpZiAoc3BlYyRpbml0aWFsX2NvbnNlbnRfdmFyICVpbiUgbmFtZXMocmF3KSkgew0KICAgIHJhd1tbc3BlYyRpbml0aWFsX2NvbnNlbnRfdmFyXV0NCiAgfSBlbHNlIHsNCiAgICByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhyYXcpKQ0KICB9DQogIGZpbmFsX3Jlc3BvbnNlIDwtIGlmIChzcGVjJGZpbmFsX2NvbnNlbnRfdmFyICVpbiUgbmFtZXMocmF3KSkgew0KICAgIHJhd1tbc3BlYyRmaW5hbF9jb25zZW50X3Zhcl1dDQogIH0gZWxzZSB7DQogICAgcmVwKE5BX2NoYXJhY3Rlcl8sIG5yb3cocmF3KSkNCiAgfQ0KICANCiAgdGFza19yZXNwb25zZXMgPC0gbGFwcGx5KA0KICAgIDE6NSwNCiAgICBmdW5jdGlvbih0YXNrX3ZhbHVlKSB7DQogICAgICB0YXNrX21hcCA8LSBlbnYkY2hvaWNlX21hcFtlbnYkY2hvaWNlX21hcCR0YXNrID09IHRhc2tfdmFsdWUsICwgZHJvcCA9IEZBTFNFXQ0KICAgICAgZ2V0X21hcHBlZF9yZXNwb25zZShyYXcsIGFzc2lnbmVkX24sIHRhc2tfbWFwLCAiY2hvaWNlX3ZhciIpDQogICAgfQ0KICApDQogIA0KICB0YXNrX3Bhc3MgPC0gbGFwcGx5KA0KICAgIHRhc2tfcmVzcG9uc2VzLA0KICAgIGZ1bmN0aW9uKHJlc3BvbnNlKSB7DQogICAgICBwYXJzZWQgPC0gc3VwcHJlc3NXYXJuaW5ncyhyZWFkcjo6cGFyc2VfbnVtYmVyKGFzLmNoYXJhY3RlcihyZXNwb25zZSkpKQ0KICAgICAgIWlzLm5hKGFzc2lnbmVkX24pICYgIWlzLm5hKHBhcnNlZCkgJiBwYXJzZWQgPj0gMSAmIHBhcnNlZCA8PSBhc3NpZ25lZF9uDQogICAgfQ0KICApDQogIA0KICBpZiAoIWlzLm51bGwobWFuaXB1bGF0aW9uX21hcCkpIHsNCiAgICBtYW5pcHVsYXRpb25fcmVzcG9uc2UgPC0gZ2V0X21hcHBlZF9yZXNwb25zZSgNCiAgICAgIHJhdywNCiAgICAgIGFzc2lnbmVkX24sDQogICAgICBtYW5pcHVsYXRpb25fbWFwLA0KICAgICAgIm1hbmlwdWxhdGlvbl92YXIiDQogICAgKQ0KICAgIG1hbmlwdWxhdGlvbl9hbnN3ZXIgPC0gcmVwKE5BX2NoYXJhY3Rlcl8sIG5yb3cocmF3KSkNCiAgICBmb3IgKG5fdmFsdWUgaW4gMjo1KSB7DQogICAgICBhbnN3ZXIgPC0gbWFuaXB1bGF0aW9uX21hcCRjb3JyZWN0X2Fuc3dlclttYW5pcHVsYXRpb25fbWFwJHBhcnR5X24gPT0gbl92YWx1ZV0NCiAgICAgIG1hbmlwdWxhdGlvbl9hbnN3ZXJbIWlzLm5hKGFzc2lnbmVkX24pICYgYXNzaWduZWRfbiA9PSBuX3ZhbHVlXSA8LSBhbnN3ZXJbMV0NCiAgICB9DQogICAgbWFuaXB1bGF0aW9uX3Bhc3MgPC0gIWlzLm5hKGFzc2lnbmVkX24pICYgcmVzcG9uc2VfaXNfY29kZSgNCiAgICAgIG1hbmlwdWxhdGlvbl9yZXNwb25zZSwNCiAgICAgIG1hbmlwdWxhdGlvbl9hbnN3ZXINCiAgICApDQogIH0gZWxzZSB7DQogICAgbWFuaXB1bGF0aW9uX3Jlc3BvbnNlIDwtIHJlcChOQV9jaGFyYWN0ZXJfLCBucm93KHJhdykpDQogICAgbWFuaXB1bGF0aW9uX3Bhc3MgPC0gcmVwKFRSVUUsIG5yb3cocmF3KSkNCiAgfQ0KICANCiAgaWYgKCFpcy5uYShzcGVjJGF0dGVudGlvbl92YXIpICYmIHNwZWMkYXR0ZW50aW9uX3ZhciAlaW4lIG5hbWVzKHJhdykpIHsNCiAgICBhdHRlbnRpb25fcmVzcG9uc2UgPC0gcmF3W1tzcGVjJGF0dGVudGlvbl92YXJdXQ0KICAgIGF0dGVudGlvbl9wYXNzIDwtIHJlc3BvbnNlX2lzX2NvZGUoYXR0ZW50aW9uX3Jlc3BvbnNlLCBzcGVjJGF0dGVudGlvbl9hbnN3ZXIpDQogIH0gZWxzZSB7DQogICAgYXR0ZW50aW9uX3Jlc3BvbnNlIDwtIHJlcChOQV9jaGFyYWN0ZXJfLCBucm93KHJhdykpDQogICAgYXR0ZW50aW9uX3Bhc3MgPC0gcmVwKFRSVUUsIG5yb3cocmF3KSkNCiAgfQ0KICANCiAgaW5pdGlhbF9wYXNzIDwtIHJlc3BvbnNlX2lzX2NvZGUoaW5pdGlhbF9yZXNwb25zZSwgMSkgfA0KICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoDQogICAgICBzdHJpbmdyOjpzdHJfc3F1aXNoKGFzLmNoYXJhY3Rlcihpbml0aWFsX3Jlc3BvbnNlKSksDQogICAgICAi6Laj5peo44Gr5ZCM5oSP44GX44GmLirljZTlipvjgZnjgosiDQogICAgKQ0KICBmaW5hbF9wYXNzIDwtIHJlc3BvbnNlX2lzX2NvZGUoZmluYWxfcmVzcG9uc2UsIDEpIHwNCiAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KA0KICAgICAgc3RyaW5ncjo6c3RyX3NxdWlzaChhcy5jaGFyYWN0ZXIoZmluYWxfcmVzcG9uc2UpKSwNCiAgICAgICLlkIzmhI/jgZcuKuWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCiyINCiAgICApDQogIA0KICBmaW5hbF9pZHMgPC0gYXMuY2hhcmFjdGVyKGVudiR2YWxpZF9pZHMkSUQpDQogIA0KICBhdWRpdCA8LSB0aWJibGU6OnRpYmJsZSgNCiAgICBJRCA9IHJhdyRJRCwNCiAgICBhc3NpZ25lZF9jb25kaXRpb24gPSBhc3NpZ25lZF9uLA0KICAgIGluaXRpYWxfY29uc2VudF9yZXNwb25zZSA9IGFzLmNoYXJhY3Rlcihpbml0aWFsX3Jlc3BvbnNlKSwNCiAgICBpbml0aWFsX2NvbnNlbnRfcGFzcyA9IGluaXRpYWxfcGFzcywNCiAgICByZWFjaGVkX2NvbmpvaW50X2Jsb2NrID0gIWlzLm5hKGFzc2lnbmVkX24pLA0KICAgIHRhc2sxX3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKHRhc2tfcmVzcG9uc2VzW1sxXV0pLA0KICAgIHRhc2sxX2NvbXBsZXRlID0gdGFza19wYXNzW1sxXV0sDQogICAgdGFzazJfcmVzcG9uc2UgPSBhcy5jaGFyYWN0ZXIodGFza19yZXNwb25zZXNbWzJdXSksDQogICAgdGFzazJfY29tcGxldGUgPSB0YXNrX3Bhc3NbWzJdXSwNCiAgICB0YXNrM19yZXNwb25zZSA9IGFzLmNoYXJhY3Rlcih0YXNrX3Jlc3BvbnNlc1tbM11dKSwNCiAgICB0YXNrM19jb21wbGV0ZSA9IHRhc2tfcGFzc1tbM11dLA0KICAgIHRhc2s0X3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKHRhc2tfcmVzcG9uc2VzW1s0XV0pLA0KICAgIHRhc2s0X2NvbXBsZXRlID0gdGFza19wYXNzW1s0XV0sDQogICAgdGFzazVfcmVzcG9uc2UgPSBhcy5jaGFyYWN0ZXIodGFza19yZXNwb25zZXNbWzVdXSksDQogICAgdGFzazVfY29tcGxldGUgPSB0YXNrX3Bhc3NbWzVdXSwNCiAgICBhbGxfZml2ZV90YXNrc19jb21wbGV0ZSA9IFJlZHVjZShgJmAsIHRhc2tfcGFzcyksDQogICAgbWFuaXB1bGF0aW9uX3Jlc3BvbnNlID0gYXMuY2hhcmFjdGVyKG1hbmlwdWxhdGlvbl9yZXNwb25zZSksDQogICAgbWFuaXB1bGF0aW9uX2NoZWNrX3Bhc3MgPSBtYW5pcHVsYXRpb25fcGFzcywNCiAgICBhdHRlbnRpb25fcmVzcG9uc2UgPSBhcy5jaGFyYWN0ZXIoYXR0ZW50aW9uX3Jlc3BvbnNlKSwNCiAgICBhdHRlbnRpb25fY2hlY2tfcGFzcyA9IGF0dGVudGlvbl9wYXNzLA0KICAgIGZpbmFsX2NvbnNlbnRfcmVzcG9uc2UgPSBhcy5jaGFyYWN0ZXIoZmluYWxfcmVzcG9uc2UpLA0KICAgIGZpbmFsX2NvbnNlbnRfcGFzcyA9IGZpbmFsX3Bhc3MsDQogICAgaW5jbHVkZWRfaW5fZmluYWxfYW5hbHlzaXMgPSBJRCAlaW4lIGZpbmFsX2lkcw0KICApDQogIA0KICBjdW11bGF0aXZlIDwtIHJlcChUUlVFLCBucm93KGF1ZGl0KSkNCiAgc3RhZ2VfcmVjb3JkcyA8LSBsaXN0KCkNCiAgYWRkX3N0YWdlIDwtIGZ1bmN0aW9uKHN0YWdlLCBxdWVzdGlvbl92YXJpYWJsZSwgY3JpdGVyaW9uKSB7DQogICAgY3VtdWxhdGl2ZSA8PC0gY3VtdWxhdGl2ZSAmIGNyaXRlcmlvbg0KICAgIHN0YWdlX3JlY29yZHNbW2xlbmd0aChzdGFnZV9yZWNvcmRzKSArIDFMXV0gPDwtIHRpYmJsZTo6dGliYmxlKA0KICAgICAgc3RhZ2Vfb3JkZXIgPSBsZW5ndGgoc3RhZ2VfcmVjb3JkcykgKyAxTCwNCiAgICAgIHN0YWdlID0gc3RhZ2UsDQogICAgICBxdWVzdGlvbl92YXJpYWJsZSA9IHF1ZXN0aW9uX3ZhcmlhYmxlLA0KICAgICAgbl9yZW1haW5pbmcgPSBzdW0oY3VtdWxhdGl2ZSwgbmEucm0gPSBUUlVFKQ0KICAgICkNCiAgfQ0KICANCiAgYWRkX3N0YWdlKCJRdWFsdHJpY3Pjga7os6rllY/mlofjg7tJbXBvcnRJZOihjOOCkumZpOWkliIsICJSZXNwb25zZUlkIiwgcmVwKFRSVUUsIG5yb3coYXVkaXQpKSkNCiAgYWRkX3N0YWdlKCLliJ3lm57lkIzmhI8iLCBzcGVjJGluaXRpYWxfY29uc2VudF92YXIsIGF1ZGl0JGluaXRpYWxfY29uc2VudF9wYXNzKQ0KICBhZGRfc3RhZ2UoIuWJsuS7mOOBleOCjOOBn+OCs+ODs+OCuOODp+OCpOODs+ODiOODu+ODluODreODg+OCr+OBq+WIsOmBlCIsICJRMy4xL1E0LjEvUTUuMS9RNi4xIOOBvuOBn+OBr+acgOWIneOBrumBuOaKnuiqsumhjCIsIGF1ZGl0JHJlYWNoZWRfY29uam9pbnRfYmxvY2spDQogIGZvciAodGFza192YWx1ZSBpbiAxOjUpIHsNCiAgICBhZGRfc3RhZ2UoDQogICAgICBwYXN0ZTAoIumBuOaKnuiqsumhjCIsIHRhc2tfdmFsdWUsICLjgpLmnInlirnlm57nrZQiKSwNCiAgICAgIHBhc3RlMCgi5p2h5Lu25YilIGNob2ljZSB0YXNrICIsIHRhc2tfdmFsdWUpLA0KICAgICAgYXVkaXRbW3Bhc3RlMCgidGFzayIsIHRhc2tfdmFsdWUsICJfY29tcGxldGUiKV1dDQogICAgKQ0KICB9DQogIGlmIChzcGVjJG1hbmlwdWxhdGlvbl9hdmFpbGFibGUpIHsNCiAgICBhZGRfc3RhZ2UoDQogICAgICAi5o+Q56S644GV44KM44Gf6YG45oqe6IKi5pWw44KS5q2j562UIiwNCiAgICAgICLmnaHku7bliKXjgavoh6rli5XmpJzlh7rjgZfjgZ/pgbjmip7ogqLmlbDnorroqo3os6rllY8iLA0KICAgICAgYXVkaXQkbWFuaXB1bGF0aW9uX2NoZWNrX3Bhc3MNCiAgICApDQogIH0NCiAgaWYgKCFpcy5uYShzcGVjJGF0dGVudGlvbl92YXIpKSB7DQogICAgYWRkX3N0YWdlKA0KICAgICAgIuOCpOODh+OCquODreOCruODvOihjOWIl+OBruaMh+ekuumgheebruOBq+ato+etlCIsDQogICAgICBzcGVjJGF0dGVudGlvbl92YXIsDQogICAgICBhdWRpdCRhdHRlbnRpb25fY2hlY2tfcGFzcw0KICAgICkNCiAgfQ0KICBhZGRfc3RhZ2UoIuacgOe1gumAgeS/oeWQjOaEjyIsIHNwZWMkZmluYWxfY29uc2VudF92YXIsIGF1ZGl0JGZpbmFsX2NvbnNlbnRfcGFzcykNCiAgYWRkX3N0YWdlKCLmnIDntYLliIbmnpDmqJnmnKwiLCAi5YWo5Z+65rqW44Gu56mN6ZuG5ZCIIiwgYXVkaXQkaW5jbHVkZWRfaW5fZmluYWxfYW5hbHlzaXMpDQogIA0KICBmbG93IDwtIGRwbHlyOjpiaW5kX3Jvd3Moc3RhZ2VfcmVjb3JkcykgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIG5fZXhjbHVkZWRfYXRfc3RhZ2UgPSBkcGx5cjo6bGFnKG5fcmVtYWluaW5nLCBkZWZhdWx0ID0gZHBseXI6OmZpcnN0KG5fcmVtYWluaW5nKSkgLSBuX3JlbWFpbmluZywNCiAgICAgIHJldGVudGlvbl9mcm9tX3ByZXZpb3VzX3BjdCA9IGRwbHlyOjppZl9lbHNlKA0KICAgICAgICBkcGx5cjo6bGFnKG5fcmVtYWluaW5nLCBkZWZhdWx0ID0gZHBseXI6OmZpcnN0KG5fcmVtYWluaW5nKSkgPiAwLA0KICAgICAgICAxMDAgKiBuX3JlbWFpbmluZyAvIGRwbHlyOjpsYWcobl9yZW1haW5pbmcsIGRlZmF1bHQgPSBkcGx5cjo6Zmlyc3Qobl9yZW1haW5pbmcpKSwNCiAgICAgICAgTkFfcmVhbF8NCiAgICAgICksDQogICAgICByZXRlbnRpb25fZnJvbV9pbml0aWFsX3BjdCA9IDEwMCAqIG5fcmVtYWluaW5nIC8gZHBseXI6OmZpcnN0KG5fcmVtYWluaW5nKQ0KICAgICkNCiAgDQogIGNvbmRpdGlvbl9mbG93IDwtIHB1cnJyOjptYXBfZGZyKA0KICAgIDI6NSwNCiAgICBmdW5jdGlvbihuX3ZhbHVlKSB7DQogICAgICBzdWJzZXRfYXVkaXQgPC0gYXVkaXQgJT4lIGRwbHlyOjpmaWx0ZXIoYXNzaWduZWRfY29uZGl0aW9uID09IG5fdmFsdWUpDQogICAgICBpZiAobnJvdyhzdWJzZXRfYXVkaXQpID09IDApIHsNCiAgICAgICAgcmV0dXJuKHRpYmJsZTo6dGliYmxlKCkpDQogICAgICB9DQogICAgICBjcml0ZXJpYSA8LSBsaXN0KA0KICAgICAgICAi5Ymy5LuY5p2h5Lu244KS6K2Y5YilIiA9IHJlcChUUlVFLCBucm93KHN1YnNldF9hdWRpdCkpLA0KICAgICAgICAi6YG45oqe6Kqy6aGMMSIgPSBzdWJzZXRfYXVkaXQkdGFzazFfY29tcGxldGUsDQogICAgICAgICLpgbjmip7oqrLpoYwyIiA9IHN1YnNldF9hdWRpdCR0YXNrMl9jb21wbGV0ZSwNCiAgICAgICAgIumBuOaKnuiqsumhjDMiID0gc3Vic2V0X2F1ZGl0JHRhc2szX2NvbXBsZXRlLA0KICAgICAgICAi6YG45oqe6Kqy6aGMNCIgPSBzdWJzZXRfYXVkaXQkdGFzazRfY29tcGxldGUsDQogICAgICAgICLpgbjmip7oqrLpoYw1IiA9IHN1YnNldF9hdWRpdCR0YXNrNV9jb21wbGV0ZQ0KICAgICAgKQ0KICAgICAgaWYgKHNwZWMkbWFuaXB1bGF0aW9uX2F2YWlsYWJsZSkgew0KICAgICAgICBjcml0ZXJpYVtbIumBuOaKnuiCouaVsOeiuuiqjSJdXSA8LSBzdWJzZXRfYXVkaXQkbWFuaXB1bGF0aW9uX2NoZWNrX3Bhc3MNCiAgICAgIH0NCiAgICAgIGlmICghaXMubmEoc3BlYyRhdHRlbnRpb25fdmFyKSkgew0KICAgICAgICBjcml0ZXJpYVtbIuaMh+ekuumgheebriJdXSA8LSBzdWJzZXRfYXVkaXQkYXR0ZW50aW9uX2NoZWNrX3Bhc3MNCiAgICAgIH0NCiAgICAgIGNyaXRlcmlhW1si5pyA57WC6YCB5L+h5ZCM5oSPIl1dIDwtIHN1YnNldF9hdWRpdCRmaW5hbF9jb25zZW50X3Bhc3MNCiAgICAgIGNyaXRlcmlhW1si5pyA57WC5YiG5p6Q5qiZ5pysIl1dIDwtIHN1YnNldF9hdWRpdCRpbmNsdWRlZF9pbl9maW5hbF9hbmFseXNpcw0KICAgICAgDQogICAgICBrZWVwIDwtIHJlcChUUlVFLCBucm93KHN1YnNldF9hdWRpdCkpDQogICAgICByZWNvcmRzIDwtIHB1cnJyOjppbWFwX2RmcigNCiAgICAgICAgY3JpdGVyaWEsDQogICAgICAgIGZ1bmN0aW9uKGNyaXRlcmlvbiwgc3RhZ2VfbmFtZSkgew0KICAgICAgICAgIGtlZXAgPDwtIGtlZXAgJiBjcml0ZXJpb24NCiAgICAgICAgICB0aWJibGU6OnRpYmJsZSgNCiAgICAgICAgICAgIGFzc2lnbmVkX2NvbmRpdGlvbiA9IG5fdmFsdWUsDQogICAgICAgICAgICBzdGFnZV9vcmRlciA9IHdoaWNoKG5hbWVzKGNyaXRlcmlhKSA9PSBzdGFnZV9uYW1lKSwNCiAgICAgICAgICAgIHN0YWdlID0gc3RhZ2VfbmFtZSwNCiAgICAgICAgICAgIG5fcmVtYWluaW5nID0gc3VtKGtlZXAsIG5hLnJtID0gVFJVRSkNCiAgICAgICAgICApDQogICAgICAgIH0NCiAgICAgICkNCiAgICAgIHJlY29yZHMgJT4lDQogICAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgICAgbl9leGNsdWRlZF9hdF9zdGFnZSA9IGRwbHlyOjpsYWcobl9yZW1haW5pbmcsIGRlZmF1bHQgPSBkcGx5cjo6Zmlyc3Qobl9yZW1haW5pbmcpKSAtIG5fcmVtYWluaW5nLA0KICAgICAgICAgIHJldGVudGlvbl9mcm9tX2NvbmRpdGlvbl9zdGFydF9wY3QgPSAxMDAgKiBuX3JlbWFpbmluZyAvIGRwbHlyOjpmaXJzdChuX3JlbWFpbmluZykNCiAgICAgICAgKQ0KICAgIH0NCiAgKQ0KICANCiAgZmluYWxfYXVkaXQgPC0gYXVkaXQgJT4lIGRwbHlyOjpmaWx0ZXIoaW5jbHVkZWRfaW5fZmluYWxfYW5hbHlzaXMpDQogIHJlcXVpcmVkX2ZpbmFsIDwtIGZpbmFsX2F1ZGl0JGluaXRpYWxfY29uc2VudF9wYXNzICYNCiAgICBmaW5hbF9hdWRpdCRhbGxfZml2ZV90YXNrc19jb21wbGV0ZSAmDQogICAgZmluYWxfYXVkaXQkbWFuaXB1bGF0aW9uX2NoZWNrX3Bhc3MgJg0KICAgIGZpbmFsX2F1ZGl0JGF0dGVudGlvbl9jaGVja19wYXNzICYNCiAgICBmaW5hbF9hdWRpdCRmaW5hbF9jb25zZW50X3Bhc3MNCiAgaWYgKCFhbGwocmVxdWlyZWRfZmluYWwpKSB7DQogICAgc3RvcCgiQ2hlY2siKQ0KICB9DQogIGlmIChucm93KGZpbmFsX2F1ZGl0KSAhPSBkcGx5cjo6bl9kaXN0aW5jdChlbnYkdmFsaWRfaWRzJElEKSkgew0KICAgIHN0b3AoIkNoZWNrIikNCiAgfQ0KICANCiAgbGlzdChhdWRpdCA9IGF1ZGl0LCBmbG93ID0gZmxvdywgY29uZGl0aW9uX2Zsb3cgPSBjb25kaXRpb25fZmxvdykNCn0NCg0KDQptYWtlX2FtY2VfdGFibGUgPC0gZnVuY3Rpb24oZW52LCBhZGp1c3RlZCA9IFRSVUUpIHsNCiAgc291cmNlIDwtIGlmIChhZGp1c3RlZCkgZW52JGFtY2VfcGxvdF9jb3YgZWxzZSBlbnYkYW1jZV9wbG90X25vY292DQogIG5fdGFibGUgPC0gZW52JG5fYnlfcGFydHkgJT4lDQogICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgIHBhcnR5X25fbnVtZXJpYyA9IGFzLmludGVnZXIoYXMuY2hhcmFjdGVyKHBhcnR5X24pKSwNCiAgICAgIHJlc3BvbmRlbnRzID0gbg0KICAgICkNCiAgDQogIHNvdXJjZSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgcGFydHlfbl9udW1lcmljID0gc3VwcHJlc3NXYXJuaW5ncyhyZWFkcjo6cGFyc2VfbnVtYmVyKGFzLmNoYXJhY3RlcihwYXJ0eV9uKSkpDQogICAgKSAlPiUNCiAgICBkcGx5cjo6bGVmdF9qb2luKG5fdGFibGUsIGJ5ID0gInBhcnR5X25fbnVtZXJpYyIpICU+JQ0KICAgIGRwbHlyOjp0cmFuc211dGUoDQogICAgICBg5p2h5Lu2YCA9IGFzLmNoYXJhY3RlcihwYXJ0eV9uKSwNCiAgICAgIGDlsZ7mgKdgID0gYXMuY2hhcmFjdGVyKGF0dHJpYnV0ZSksDQogICAgICBg5rC05rqW77yI5Z+65rqW5rC05rqW44Go44Gu5beu77yJYCA9IGFzLmNoYXJhY3RlcihsYWJlbCksDQogICAgICBg5o6o5a6a5YCk77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBlc3RpbWF0ZSwgMiksDQogICAgICBg5qiZ5rqW6Kqk5beu77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBzdGQuZXJyb3IsIDIpLA0KICAgICAgYDk1JSBDSeS4i+mZkO+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogY29uZi5sb3csIDIpLA0KICAgICAgYDk1JSBDSeS4iumZkO+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogY29uZi5oaWdoLCAyKSwNCiAgICAgIGBw5YCkYCA9IGZvcm1hdF9wX3ZhbHVlKHAudmFsdWUpLA0KICAgICAgYOWbnuetlOiAheaVsGAgPSBmb3JtYXRfaW50ZWdlcihyZXNwb25kZW50cykNCiAgICApDQp9DQoNCm1ha2VfaW50ZXJhY3Rpb25fdGFibGUgPC0gZnVuY3Rpb24oZW52KSB7DQogIHNvdXJjZSA8LSBlbnYkaW50ZXJhY3Rpb25fcGxvdF9kZg0KICBjb25kaXRpb25fY29sdW1uIDwtIGludGVyc2VjdChjKCJwYXJ0eV9uX2xhYmVsIiwgInBhcnR5X24iKSwgbmFtZXMoc291cmNlKSlbMV0NCiAgaWYgKGlzLm5hKGNvbmRpdGlvbl9jb2x1bW4pKSB7DQogICAgc291cmNlJGNvbmRpdGlvbl9sYWJlbCA8LSAiIg0KICB9IGVsc2Ugew0KICAgIHNvdXJjZSRjb25kaXRpb25fbGFiZWwgPC0gYXMuY2hhcmFjdGVyKHNvdXJjZVtbY29uZGl0aW9uX2NvbHVtbl1dKQ0KICB9DQogIHNvdXJjZSAlPiUNCiAgICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgICAgYOavlOi8g+adoeS7tmAgPSBjb25kaXRpb25fbGFiZWwsDQogICAgICBg5bGe5oCnYCA9IGFzLmNoYXJhY3RlcihhdHRyaWJ1dGUpLA0KICAgICAgYOawtOa6lmAgPSBhcy5jaGFyYWN0ZXIobGFiZWwpLA0KICAgICAgYDLpgbjmip7ogqLmnaHku7bjgajjga7lt67vvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGVzdGltYXRlLCAyKSwNCiAgICAgIGDmqJnmupboqqTlt67vvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIHN0ZC5lcnJvciwgMiksDQogICAgICBgOTUlIENJ5LiL6ZmQ77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mLmxvdywgMiksDQogICAgICBgOTUlIENJ5LiK6ZmQ77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mLmhpZ2gsIDIpLA0KICAgICAgYHDlgKRgID0gZm9ybWF0X3BfdmFsdWUocC52YWx1ZSkNCiAgICApDQp9DQoNCmNsdXN0ZXJlZF9tZWFuX3N1bW1hcnkgPC0gZnVuY3Rpb24oeSwgY2x1c3Rlcikgew0KICB5IDwtIGFzLm51bWVyaWMoeSkNCiAgY2x1c3RlciA8LSBhcy5jaGFyYWN0ZXIoY2x1c3RlcikNCiAga2VlcCA8LSBpcy5maW5pdGUoeSkgJiAhaXMubmEoY2x1c3RlcikNCiAgeSA8LSB5W2tlZXBdDQogIGNsdXN0ZXIgPC0gY2x1c3RlcltrZWVwXQ0KICBuIDwtIGxlbmd0aCh5KQ0KICBnIDwtIGRwbHlyOjpuX2Rpc3RpbmN0KGNsdXN0ZXIpDQogIGlmIChuID09IDApIHsNCiAgICByZXR1cm4oYyhlc3RpbWF0ZSA9IE5BX3JlYWxfLCBzZSA9IE5BX3JlYWxfLCBsb3cgPSBOQV9yZWFsXywgaGlnaCA9IE5BX3JlYWxfLCBuID0gMCwgZyA9IDApKQ0KICB9DQogIGVzdGltYXRlIDwtIG1lYW4oeSkNCiAgaWYgKGcgPD0gMSkgew0KICAgIHNlIDwtIE5BX3JlYWxfDQogIH0gZWxzZSB7DQogICAgY2x1c3Rlcl9zY29yZSA8LSB0YXBwbHkoeSAtIGVzdGltYXRlLCBjbHVzdGVyLCBzdW0pDQogICAgdmFyaWFuY2UgPC0gKGcgLyAoZyAtIDEpKSAqIHN1bShjbHVzdGVyX3Njb3JlXjIpIC8gKG5eMikNCiAgICBzZSA8LSBzcXJ0KHZhcmlhbmNlKQ0KICB9DQogIGMoDQogICAgZXN0aW1hdGUgPSBlc3RpbWF0ZSwNCiAgICBzZSA9IHNlLA0KICAgIGxvdyA9IGVzdGltYXRlIC0gMS45NiAqIHNlLA0KICAgIGhpZ2ggPSBlc3RpbWF0ZSArIDEuOTYgKiBzZSwNCiAgICBuID0gbiwNCiAgICBnID0gZw0KICApDQp9DQoNCm1ha2VfbW1fdGFibGUgPC0gZnVuY3Rpb24oZW52KSB7DQogIGF0dHJpYnV0ZXMgPC0gbmFtZXMoZW52JHJlbGF0aXZlX2N1ZV9tYXApDQogIGxvbmcgPC0gZW52JGNvbmpvaW50X2FsbF9tICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoSUQsIHBhcnR5X24sIHNlbGVjdGVkLCBkcGx5cjo6YWxsX29mKGF0dHJpYnV0ZXMpKSAlPiUNCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKA0KICAgICAgY29scyA9IGRwbHlyOjphbGxfb2YoYXR0cmlidXRlcyksDQogICAgICBuYW1lc190byA9ICJhdHRyaWJ1dGUiLA0KICAgICAgdmFsdWVzX3RvID0gImxldmVsIg0KICAgICkgJT4lDQogICAgZHBseXI6OmZpbHRlcighaXMubmEobGV2ZWwpLCBhcy5jaGFyYWN0ZXIobGV2ZWwpICE9ICIiKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKGxldmVsID0gYXMuY2hhcmFjdGVyKGxldmVsKSkNCiAgDQogIHN1bW1hcnkgPC0gbG9uZyAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkocGFydHlfbiwgYXR0cmlidXRlLCBsZXZlbCkgJT4lDQogICAgZHBseXI6Omdyb3VwX21vZGlmeSgNCiAgICAgIH4gew0KICAgICAgICB2YWx1ZXMgPC0gY2x1c3RlcmVkX21lYW5fc3VtbWFyeSgueCRzZWxlY3RlZCwgLngkSUQpDQogICAgICAgIHRpYmJsZTo6dGliYmxlKA0KICAgICAgICAgIG1hcmdpbmFsX21lYW4gPSB2YWx1ZXNbImVzdGltYXRlIl0sDQogICAgICAgICAgY2x1c3Rlcl9zZSA9IHZhbHVlc1sic2UiXSwNCiAgICAgICAgICBjb25mX2xvdyA9IHZhbHVlc1sibG93Il0sDQogICAgICAgICAgY29uZl9oaWdoID0gdmFsdWVzWyJoaWdoIl0sDQogICAgICAgICAgbl9wcm9maWxlcyA9IHZhbHVlc1sibiJdLA0KICAgICAgICAgIG5fcmVzcG9uZGVudHMgPSB2YWx1ZXNbImciXQ0KICAgICAgICApDQogICAgICB9DQogICAgKSAlPiUNCiAgICBkcGx5cjo6dW5ncm91cCgpICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBjdWVfZmFtaWx5ID0gdW5uYW1lKGVudiRyZWxhdGl2ZV9jdWVfbWFwW2F0dHJpYnV0ZV0pLA0KICAgICAgYXR0cmlidXRlX2xhYmVsID0gZHBseXI6OmNvYWxlc2NlKHVubmFtZShhdHRyaWJ1dGVfbGFiZWxfbWFwW2F0dHJpYnV0ZV0pLCBhdHRyaWJ1dGUpLA0KICAgICAgY3VlX2xhYmVsID0gZHBseXI6OmNvYWxlc2NlKHVubmFtZShjdWVfZmFtaWx5X2xhYmVsW2N1ZV9mYW1pbHldKSwgY3VlX2ZhbWlseSkNCiAgICApDQogIA0KICBzdW1tYXJ5ICU+JQ0KICAgIGRwbHlyOjp0cmFuc211dGUoDQogICAgICBg5p2h5Lu2YCA9IHBhc3RlMChwYXJ0eV9uLCBpZmVsc2UoInBhcnR5X25hbWUiICVpbiUgYXR0cmlidXRlcywgIumBuOaKnuiCoiIsICLmlL/lhZoiKSksDQogICAgICBg5omL44GM44GL44KK576kYCA9IGN1ZV9sYWJlbCwNCiAgICAgIGDlsZ7mgKdgID0gYXR0cmlidXRlX2xhYmVsLA0KICAgICAgYOawtOa6lmAgPSBsZXZlbCwNCiAgICAgIGDpmZDnlYzlubPlnYfvvIgl77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogbWFyZ2luYWxfbWVhbiwgMiksDQogICAgICBg44Kv44Op44K544K/U0XvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNsdXN0ZXJfc2UsIDIpLA0KICAgICAgYDk1JSBDSeS4i+mZkO+8iCXvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mX2xvdywgMiksDQogICAgICBgOTUlIENJ5LiK6ZmQ77yIJe+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNvbmZfaGlnaCwgMiksDQogICAgICBg44OX44Ot44OV44Kh44Kk44Or5pWwYCA9IGZvcm1hdF9pbnRlZ2VyKG5fcHJvZmlsZXMpLA0KICAgICAgYOWbnuetlOiAheaVsGAgPSBmb3JtYXRfaW50ZWdlcihuX3Jlc3BvbmRlbnRzKQ0KICAgICkNCn0NCg0KbWFrZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZV90YWJsZSA8LSBmdW5jdGlvbihlbnYpIHsNCiAgc291cmNlIDwtIGVudiRyZWxhdGl2ZV9jdWVfb2JzZXJ2ZWQkYXR0cmlidXRlX2ltcG9ydGFuY2UNCiAgYWRqdXN0ZWRfY29sIDwtIGludGVyc2VjdCgNCiAgICBjKCJpbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiwgImNob2ljZV9zZXRfYWRqdXN0ZWRfaW1wb3J0YW5jZV9wYWlyd2lzZSIpLA0KICAgIG5hbWVzKHNvdXJjZSkNCiAgKVsxXQ0KICBhZGp1c3RlZCA8LSBpZiAoIWlzLm5hKGFkanVzdGVkX2NvbCkpIHNvdXJjZVtbYWRqdXN0ZWRfY29sXV0gZWxzZSBzb3VyY2UkcGFydHlfbiAqIHNvdXJjZSRpbXBvcnRhbmNlX3BhaXJ3aXNlDQogIA0KICBzb3VyY2UgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIGFkanVzdGVkX3ZhbHVlID0gYWRqdXN0ZWQsDQogICAgICBhdHRyaWJ1dGVfbGFiZWwgPSBkcGx5cjo6Y29hbGVzY2UodW5uYW1lKGF0dHJpYnV0ZV9sYWJlbF9tYXBbYXR0cmlidXRlXSksIGF0dHJpYnV0ZSksDQogICAgICBjdWVfbGFiZWwgPSBkcGx5cjo6Y29hbGVzY2UodW5uYW1lKGN1ZV9mYW1pbHlfbGFiZWxbY3VlX2ZhbWlseV0pLCBjdWVfZmFtaWx5KQ0KICAgICkgJT4lDQogICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgIGDmnaHku7ZgID0gcGFydHlfbiwNCiAgICAgIGDmiYvjgYzjgYvjgornvqRgID0gY3VlX2xhYmVsLA0KICAgICAgYOWxnuaAp2AgPSBhdHRyaWJ1dGVfbGFiZWwsDQogICAgICBg5rC05rqW5pWwYCA9IG5fbGV2ZWxzLA0KICAgICAgYOacquiqv+aVtOmHjeimgeW6pu+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogaW1wb3J0YW5jZV9wYWlyd2lzZSwgMiksDQogICAgICBg6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqm77yIJe+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGFkanVzdGVkX3ZhbHVlLCAyKQ0KICAgICkNCn0NCg0KbWFrZV9jdWVfaW1wb3J0YW5jZV90YWJsZSA8LSBmdW5jdGlvbihlbnYpIHsNCiAgc291cmNlIDwtIGVudiRyZWxhdGl2ZV9jdWVfY29uZGl0aW9uX2ludGVydmFscw0KICBsYWJlbHMgPC0gYygNCiAgICBwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlID0gIuaUv+WFmuaJi+OBjOOBi+OCiu+8muacquiqv+aVtOmHjeimgeW6piIsDQogICAgZWNvbm9taWNfaW1wb3J0YW5jZV9wYWlyd2lzZSA9ICLntYzmuIjmiYvjgYzjgYvjgorvvJrmnKroqr/mlbTph43opoHluqYiLA0KICAgIHBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQgPSAi5pS/5YWa5omL44GM44GL44KK77ya6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqmIiwNCiAgICBlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkID0gIue1jOa4iOaJi+OBjOOBi+OCiu+8mumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6piIsDQogICAgcmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlID0gIuaUv+WFmuaJi+OBjOOBi+OCiuOBruebuOWvvuavlOmHjSINCiAgKQ0KICBzb3VyY2UgPC0gc291cmNlICU+JSBkcGx5cjo6ZmlsdGVyKHN0YXRpc3RpYyAlaW4lIG5hbWVzKGxhYmVscykpDQogIHNvdXJjZSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgYOaMh+aomWAgPSB1bm5hbWUobGFiZWxzW3N0YXRpc3RpY10pLA0KICAgICAgYOWNmOS9jWAgPSBkcGx5cjo6Y2FzZV93aGVuKA0KICAgICAgICBzdGF0aXN0aWMgJWluJSBjKCJwYXJ0eV9pbXBvcnRhbmNlX3BhaXJ3aXNlIiwgImVjb25vbWljX2ltcG9ydGFuY2VfcGFpcndpc2UiKSB+ICJwcCIsDQogICAgICAgIFRSVUUgfiAiJSINCiAgICAgICksDQogICAgICBtdWx0aXBsaWVyID0gMTAwDQogICAgKSAlPiUNCiAgICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgICAgYOadoeS7tmAgPSBwYXJ0eV9uLA0KICAgICAgYOaMh+aomWAgPSBg5oyH5qiZYCwNCiAgICAgIGDljZjkvY1gID0gYOWNmOS9jWAsDQogICAgICBg5o6o5a6a5YCkYCA9IGZvcm1hdF9udW1iZXIobXVsdGlwbGllciAqIGVzdGltYXRlLCAyKSwNCiAgICAgIGA5NSUgQ0nkuIvpmZBgID0gZm9ybWF0X251bWJlcihtdWx0aXBsaWVyICogY29uZl9sb3csIDIpLA0KICAgICAgYDk1JSBDSeS4iumZkGAgPSBmb3JtYXRfbnVtYmVyKG11bHRpcGxpZXIgKiBjb25mX2hpZ2gsIDIpDQogICAgKQ0KfQ0KDQptYWtlX2Nsb2dpdF90YWJsZSA8LSBmdW5jdGlvbihlbnYpIHsNCiAgZW52JGNsb2dpdF9wbG90X2RmICU+JQ0KICAgIGRwbHlyOjp0cmFuc211dGUoDQogICAgICBg5p2h5Lu2YCA9IGFzLmNoYXJhY3RlcihwYXJ0eV9uKSwNCiAgICAgIGDlsZ7mgKdgID0gYXMuY2hhcmFjdGVyKGF0dHJpYnV0ZSksDQogICAgICBg5rC05rqW77yI5Z+65rqW5rC05rqW44Go44Gu5beu77yJYCA9IGFzLmNoYXJhY3RlcihsYWJlbCksDQogICAgICBgbG9n5L+C5pWwYCA9IGZvcm1hdF9udW1iZXIoZXN0aW1hdGUsIDMpLA0KICAgICAgYOaomea6luiqpOW3rmAgPSBmb3JtYXRfbnVtYmVyKHN0ZC5lcnJvciwgMyksDQogICAgICBg44Kq44OD44K65q+UYCA9IGZvcm1hdF9udW1iZXIob2Rkc19yYXRpbywgMyksDQogICAgICBgOTUlIENJ5LiL6ZmQ77yIT1LvvIlgID0gZm9ybWF0X251bWJlcihvZGRzX3JhdGlvX2xvdywgMyksDQogICAgICBgOTUlIENJ5LiK6ZmQ77yIT1LvvIlgID0gZm9ybWF0X251bWJlcihvZGRzX3JhdGlvX2hpZ2gsIDMpLA0KICAgICAgYHDlgKRgID0gZm9ybWF0X3BfdmFsdWUocC52YWx1ZSkNCiAgICApDQp9DQoNCm1ha2VfbGluZWFyX3RyZW5kX3RhYmxlIDwtIGZ1bmN0aW9uKGVudikgew0KICBpZiAoIWV4aXN0cygibGluZWFyX3RyZW5kX3Bsb3RfZGYiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsNCiAgICByZXR1cm4odGliYmxlOjp0aWJibGUoKSkNCiAgfQ0KICBlbnYkbGluZWFyX3RyZW5kX3Bsb3RfZGYgJT4lDQogICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgIGDlsZ7mgKdgID0gYXMuY2hhcmFjdGVyKGF0dHJpYnV0ZSksDQogICAgICBg5rC05rqWYCA9IGFzLmNoYXJhY3RlcihsYWJlbCksDQogICAgICBg6YG45oqe6IKi44GMMeOBpOWil+OBiOOCi+OBqOOBjeOBruWkieWMlu+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogZXN0aW1hdGUsIDIpLA0KICAgICAgYOaomea6luiqpOW3ru+8iHBw77yJYCA9IGZvcm1hdF9udW1iZXIoMTAwICogc3RkLmVycm9yLCAyKSwNCiAgICAgIGA5NSUgQ0nkuIvpmZDvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNvbmYubG93LCAyKSwNCiAgICAgIGA5NSUgQ0nkuIrpmZDvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGNvbmYuaGlnaCwgMiksDQogICAgICBgcOWApGAgPSBmb3JtYXRfcF92YWx1ZShwLnZhbHVlKQ0KICAgICkNCn0NCg0KbWFrZV9wYXJ0eV9tYXRjaF90YWJsZSA8LSBmdW5jdGlvbihlbnYpIHsNCiAgaWYgKCFleGlzdHMoInBhcnR5X21hdGNoX2NvZWZfZGYiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsNCiAgICByZXR1cm4odGliYmxlOjp0aWJibGUoKSkNCiAgfQ0KICBvdmVyYWxsIDwtIGVudiRwYXJ0eV9tYXRjaF9jb2VmX2RmDQogIHN1Ymdyb3VwIDwtIGlmIChleGlzdHMoInBhcnR5X21hdGNoX3N1Ymdyb3VwX2NvZWZfZGYiLCBlbnZpciA9IGVudiwgaW5oZXJpdHMgPSBGQUxTRSkpIHsNCiAgICBlbnYkcGFydHlfbWF0Y2hfc3ViZ3JvdXBfY29lZl9kZg0KICB9IGVsc2Ugew0KICAgIHRpYmJsZTo6dGliYmxlKCkNCiAgfQ0KICBjb21iaW5lZCA8LSBkcGx5cjo6YmluZF9yb3dzKG92ZXJhbGwsIHN1Ymdyb3VwKQ0KICBpZiAoISJuX2lkcyIgJWluJSBuYW1lcyhjb21iaW5lZCkpIGNvbWJpbmVkJG5faWRzIDwtIE5BX3JlYWxfDQogIGlmICghInN1cHBvcnRfZ3JvdXBfbGFiZWwiICVpbiUgbmFtZXMoY29tYmluZWQpKSBjb21iaW5lZCRzdXBwb3J0X2dyb3VwX2xhYmVsIDwtICLlhajkvZMiDQogIGNvbWJpbmVkICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICBzdXBwb3J0X2dyb3VwX2xhYmVsID0gZHBseXI6OmNvYWxlc2NlKGFzLmNoYXJhY3RlcihzdXBwb3J0X2dyb3VwX2xhYmVsKSwgIuWFqOS9kyIpLA0KICAgICAgbl9pZHMgPSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMobl9pZHMpKQ0KICAgICkgJT4lDQogICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgIGDlr77osaFgID0gc3VwcG9ydF9ncm91cF9sYWJlbCwNCiAgICAgIGDpgbjmip7ogqLmlbBgID0gcGFydHlfbiwNCiAgICAgIGDkuIDoh7TlirnmnpzvvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIGVzdGltYXRlLCAyKSwNCiAgICAgIGDmqJnmupboqqTlt67vvIhwcO+8iWAgPSBmb3JtYXRfbnVtYmVyKDEwMCAqIHN0ZC5lcnJvciwgMiksDQogICAgICBgOTUlIENJ5LiL6ZmQ77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mLmxvdywgMiksDQogICAgICBgOTUlIENJ5LiK6ZmQ77yIcHDvvIlgID0gZm9ybWF0X251bWJlcigxMDAgKiBjb25mLmhpZ2gsIDIpLA0KICAgICAgYHDlgKRgID0gZm9ybWF0X3BfdmFsdWUocC52YWx1ZSksDQogICAgICBg5Zue562U6ICF5pWwYCA9IGZvcm1hdF9pbnRlZ2VyKG5faWRzKQ0KICAgICkNCn0NCg0KDQpzY3JlZW5pbmdfcXVlc3Rpb25fd29yZGluZyA8LSBmdW5jdGlvbihzdHVkeV9pZCwgc3RhZ2UsIHBhcnR5X24gPSBOQV9pbnRlZ2VyXykgew0KICBzdGFnZSA8LSBhcy5jaGFyYWN0ZXIoc3RhZ2UpDQogIHBhcnR5X24gPC0gc3VwcHJlc3NXYXJuaW5ncyhhcy5pbnRlZ2VyKHBhcnR5X24pKQ0KICBpZiAobGVuZ3RoKHBhcnR5X24pID09IDFMICYmIGxlbmd0aChzdGFnZSkgPiAxTCkgew0KICAgIHBhcnR5X24gPC0gcmVwKHBhcnR5X24sIGxlbmd0aChzdGFnZSkpDQogIH0NCiAgaWYgKGxlbmd0aChwYXJ0eV9uKSAhPSBsZW5ndGgoc3RhZ2UpKSB7DQogICAgcGFydHlfbiA8LSByZXAoTkFfaW50ZWdlcl8sIGxlbmd0aChzdGFnZSkpDQogIH0NCg0KICBwdXJycjo6bWFwMl9jaHIoc3RhZ2UsIHBhcnR5X24sIGZ1bmN0aW9uKHN0YWdlX3ZhbHVlLCBuX3ZhbHVlKSB7DQogICAga190ZXh0IDwtIGlmZWxzZShpcy5uYShuX3ZhbHVlKSwgImsiLCBhcy5jaGFyYWN0ZXIobl92YWx1ZSkpDQoNCiAgICBpZiAoc3RyaW5ncjo6c3RyX2RldGVjdChzdGFnZV92YWx1ZSwgIlF1YWx0cmljcyIpKSB7DQogICAgICByZXR1cm4oIu+8iFF1YWx0cmljc+OBruODoeOCv+ODh+ODvOOCv+ihjOOAguiqv+afu+izquWVj+OBp+OBr+OBquOBhO+8iSIpDQogICAgfQ0KDQogICAgaWYgKHN0YWdlX3ZhbHVlID09ICLliJ3lm57lkIzmhI8iKSB7DQogICAgICByZXR1cm4oIuOAjOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBpuOAgeacrOiqv+afu+OBq+WNlOWKm+OBmeOCi+OAjSIpDQogICAgfQ0KDQogICAgaWYgKHN0cmluZ3I6OnN0cl9kZXRlY3Qoc3RhZ2VfdmFsdWUsICLjgrPjg7Pjgrjjg6fjgqTjg7Pjg4jjg7vjg5bjg63jg4Pjgq/jgavliLDpgZR85Ymy5LuY5p2h5Lu244KS6K2Y5YilIikpIHsNCiAgICAgIGlmIChzdHVkeV9pZCA9PSAic3R1ZHkzIikgew0KICAgICAgICByZXR1cm4ocGFzdGUwKA0KICAgICAgICAgICLjgIzku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgosiLCBrX3RleHQsDQogICAgICAgICAgIuOBpOOBrumBuOaKnuiCouOCkumghuOBq+aPkOekuuOBl+OBpuOBhOOBjeOBvuOBmeOAguKApiIsIGtfdGV4dCwNCiAgICAgICAgICAi44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu54q25rOB44KS6YG45oqe44GV44KM44KL44GL44CBMeOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAguS9nOalreOBrzXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgILjgI0iDQogICAgICAgICkpDQogICAgICB9DQogICAgICByZXR1cm4ocGFzdGUwKA0KICAgICAgICAi44CM5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KLIiwga190ZXh0LA0KICAgICAgICAi44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CC4oCmIiwga190ZXh0LA0KICAgICAgICAi44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu5pS/5YWa44KS6YG45oqe44GV44KM44KL44GL44CBMeOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAguS9nOalreOBrzXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgILjgI0iDQogICAgICApKQ0KICAgIH0NCg0KICAgIGlmIChzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YWdlX3ZhbHVlLCAiXumBuOaKnuiqsumhjFsxLTVdIikpIHsNCiAgICAgIGlmIChzdHVkeV9pZCA9PSAic3R1ZHkzIikgew0KICAgICAgICByZXR1cm4ocGFzdGUwKA0KICAgICAgICAgICLjgIzku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgosiLCBrX3RleHQsDQogICAgICAgICAgIuOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAguKApuaUv+aoqeS4juWFmuOBq+OBguOCi+aUv+WFmuOBqOe1jOa4iOeKtuazgeOBrue1hOOBv+WQiOOCj+OBm+OBruOBhuOBoeOAgeOBguOBquOBn+OBr+OBqeOBrueKtuazgeOBp+OBguOCjOOBsOOAgeaUv+aoqeS4juWFmuOBq+aKleelqOOBl+OBvuOBmeOBi+OAguOAjSINCiAgICAgICAgKSkNCiAgICAgIH0NCiAgICAgIGlmIChzdHVkeV9pZCA9PSAic3R1ZHkyIikgew0KICAgICAgICByZXR1cm4ocGFzdGUwKA0KICAgICAgICAgICLjgIzku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgosiLCBrX3RleHQsDQogICAgICAgICAgIuOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAguOBguOBquOBn+OBr+OAgeihhuitsOmZouitsOWToee3j+mBuOaMmeOBq+OBiuOBhOOBpuOAgeS7peS4i+OBruOBhOOBmuOCjOOBruaUv+WFmuOCkuOBiumBuOOBs+OBq+OBquOCiuOBvuOBmeOBi+OAguOAjSINCiAgICAgICAgKSkNCiAgICAgIH0NCiAgICAgIHJldHVybihwYXN0ZTAoDQogICAgICAgICLjgIzku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgosiLCBrX3RleHQsDQogICAgICAgICLjgaTjga7pgbjmip7ogqLjgpLmj5DnpLrjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgILjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHmj5DnpLrjgZXjgozjgZ/mlL/lhZrjga7kuK3jgYvjgokx44Gk44KS6YG45oqe44GX44Gm44GP44Gg44GV44GE44CC44CNIg0KICAgICAgKSkNCiAgICB9DQoNCiAgICBpZiAoc3RyaW5ncjo6c3RyX2RldGVjdChzdGFnZV92YWx1ZSwgIuaPkOekuuOBleOCjOOBn+mBuOaKnuiCouaVsOOCkuato+etlHzpgbjmip7ogqLmlbDnorroqo0iKSkgew0KICAgICAgaWYgKHN0dWR5X2lkID09ICJzdHVkeTIiKSB7DQogICAgICAgIHJldHVybigi44CM44GC44Gq44Gf44Gr5o+Q56S644GV44KM44Gf5pS/5YWa44Gu6YG45oqe6IKi44Gu5pWw44Gv44CB44GE44GP44Gk44Gn44GX44Gf44GL44CC44CNIikNCiAgICAgIH0NCiAgICAgIGlmIChzdHVkeV9pZCA9PSAic3R1ZHkzIikgew0KICAgICAgICByZXR1cm4oIuOAjOOBguOBquOBn+OBq+aPkOekuuOBleOCjOOBn+mBuOaKnuiCouOBruaVsOOBr+OAgeOBhOOBj+OBpOOBp+OBl+OBn+OBi+OAguOAjSIpDQogICAgICB9DQogICAgICByZXR1cm4oIu+8iFN0dWR5IDHjgafjga/oqbLlvZPos6rllY/jgarjgZfvvIkiKQ0KICAgIH0NCg0KICAgIGlmIChzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YWdlX3ZhbHVlLCAi44Kk44OH44Kq44Ot44Ku44O86KGM5YiX44Gu5oyH56S66aCF55uufOaMh+ekuumgheebriIpKSB7DQogICAgICBpZiAoc3R1ZHlfaWQgJWluJSBjKCJzdHVkeTIiLCAic3R1ZHkzIikpIHsNCiAgICAgICAgcmV0dXJuKCLjgIzvvIHjgZPjga7poIXnm67jga/lv4XjgZrjgI4z44CP44KS6YG444KT44Gn44GP44Gg44GV44GE77yB44CNIikNCiAgICAgIH0NCiAgICAgIHJldHVybigi77yIU3R1ZHkgMeOBp+OBr+ipsuW9k+izquWVj+OBquOBl++8iSIpDQogICAgfQ0KDQogICAgaWYgKHN0YWdlX3ZhbHVlID09ICLmnIDntYLpgIHkv6HlkIzmhI8iKSB7DQogICAgICByZXR1cm4oIuOAjOacrOiqv+afu+OBruS4u+aXqOOBq+WQjOaEj+OBl+OAgeWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCi+OAguOAjSIpDQogICAgfQ0KDQogICAgaWYgKHN0YWdlX3ZhbHVlID09ICLmnIDntYLliIbmnpDmqJnmnKwiKSB7DQogICAgICByZXR1cm4oIu+8iOizquWVj+aWh+OBquOBl+OAguS4iuiomOOBruWFqOWfuua6luOBruepjembhuWQiO+8iSIpDQogICAgfQ0KDQogICAgIuKAlCINCiAgfSkNCn0NCg0KDQpzY3JlZW5pbmdfcmVzdWx0cyA8LSBsaXN0KCkNCnN0dWR5X3RhYmxlX3BhdGhzIDwtIGxpc3QoKQ0KDQpmb3IgKHN0dWR5X2lkIGluIG5hbWVzKHN0dWR5X3NwZWNzKSkgew0KICBzcGVjIDwtIHN0dWR5X3NwZWNzW1tzdHVkeV9pZF1dDQogIGVudiA8LSBzcGVjJGVudg0KICBzdHVkeV9sYWJlbCA8LSBzcGVjJHN0dWR5X2xhYmVsDQogIGNzdl9kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCBzdHVkeV9pZCwgInRhYmxlc19jc3YiKQ0KICB0ZXhfZGlyIDwtIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgc3R1ZHlfaWQsICJ0YWJsZXNfdGV4IikNCiAgZGlhZ19zY3JlZW5fZGlyIDwtIGZpbGUucGF0aChmaW5hbF9kaXJzJGRpYWdub3N0aWNzX3Jvb3QsIHN0dWR5X2lkLCAic2NyZWVuaW5nIikNCiAgZGlhZ19iYWxhbmNlX2RpciA8LSBmaWxlLnBhdGgoZmluYWxfZGlycyRkaWFnbm9zdGljc19yb290LCBzdHVkeV9pZCwgImJhbGFuY2UiKQ0KICBkaWFnX3JhbmRvbV9kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkZGlhZ25vc3RpY3Nfcm9vdCwgc3R1ZHlfaWQsICJyYW5kb21pemF0aW9uIikNCiAgDQogIHNjcmVlbmluZyA8LSBidWlsZF9zY3JlZW5pbmdfb3V0cHV0cyhzcGVjKQ0KICBzY3JlZW5pbmdfcmVzdWx0c1tbc3R1ZHlfaWRdXSA8LSBzY3JlZW5pbmcNCiAgDQogIHJlYWRyOjp3cml0ZV9jc3Yoc2NyZWVuaW5nJGF1ZGl0LCBmaWxlLnBhdGgoZGlhZ19zY3JlZW5fZGlyLCAicmVzcG9uZGVudF9zY3JlZW5pbmdfYXVkaXQuY3N2IiksIG5hID0gIiIpDQogIHJlYWRyOjp3cml0ZV9jc3Yoc2NyZWVuaW5nJGZsb3csIGZpbGUucGF0aChkaWFnX3NjcmVlbl9kaXIsICJzZXF1ZW50aWFsX3NhbXBsZV9mbG93LmNzdiIpLCBuYSA9ICIiKQ0KICByZWFkcjo6d3JpdGVfY3N2KHNjcmVlbmluZyRjb25kaXRpb25fZmxvdywgZmlsZS5wYXRoKGRpYWdfc2NyZWVuX2RpciwgInNlcXVlbnRpYWxfc2FtcGxlX2Zsb3dfYnlfY29uZGl0aW9uLmNzdiIpLCBuYSA9ICIiKQ0KICANCiAgYXR0cml0aW9uX3RhYmxlIDwtIHNjcmVlbmluZyRmbG93ICU+JQ0KICAgIGRwbHlyOjp0cmFuc211dGUoDQogICAgICBg6aCG5bqPYCA9IHN0YWdlX29yZGVyLA0KICAgICAgYOautemajmAgPSBzdGFnZSwNCiAgICAgIGDos6rllY/jg7vlpInmlbBgID0gcXVlc3Rpb25fdmFyaWFibGUsDQogICAgICBg6LOq5ZWP5paH77yI6Kq/5p+756Wo44O76KaB57SE77yJYCA9IHNjcmVlbmluZ19xdWVzdGlvbl93b3JkaW5nKHN0dWR5X2lkLCBzdGFnZSksDQogICAgICBg5q6L5a2YTmAgPSBmb3JtYXRfaW50ZWdlcihuX3JlbWFpbmluZyksDQogICAgICBg5b2T6Kmy5q616ZqO44Gn44Gu6Zmk5aSWTmAgPSBmb3JtYXRfaW50ZWdlcihuX2V4Y2x1ZGVkX2F0X3N0YWdlKSwNCiAgICAgIGDliY3mrrXpmo7jgYvjgonjga7mrovlrZjnjofvvIgl77yJYCA9IGZvcm1hdF9udW1iZXIocmV0ZW50aW9uX2Zyb21fcHJldmlvdXNfcGN0LCAxKSwNCiAgICAgIGDliJ3mnJ/mqJnmnKzjgYvjgonjga7mrovlrZjnjofvvIgl77yJYCA9IGZvcm1hdF9udW1iZXIocmV0ZW50aW9uX2Zyb21faW5pdGlhbF9wY3QsIDEpDQogICAgKQ0KICANCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgYXR0cml0aW9uX3RhYmxlLA0KICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfc2FtcGxlX2F0dHJpdGlvbi5jc3YiKSwNCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb24udGV4IiksDQogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya6LOq5ZWP5q616ZqO44GU44Go44Gu6YCQ5qyh55qE44Gq5qiZ5pys5rib5bCRIiksDQogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYXR0cml0aW9uIiksDQogICAgbm90ZXMgPSBwYXN0ZTAoDQogICAgICAi5ZCE6KGM44Gv55u05YmN44G+44Gn44Gu5Z+65rqW44KS5rqA44Gf44GX44Gf5Zue562U6ICF44Gr5qyh44Gu5Z+65rqW44KS6aCG44Gr6YGp55So44GX44Gf5q6L5a2Y5pWw44KS56S644GZ44CCIiwNCiAgICAgIGlmZWxzZSgNCiAgICAgICAgc3R1ZHlfaWQgPT0gInN0dWR5MSIsDQogICAgICAgICJTdHVkeSAx44Gn44Gv6YG45oqe6IKi5pWw56K66KqN6LOq5ZWP44GK44KI44Gz5oyH56S66aCF55uu44Gv6Kq/5p+756Wo44Gr6Kit44GR44KJ44KM44Gm44GE44Gq44GE44CCIiwNCiAgICAgICAgIuacgOe1guWIhuaekOOBr+OAgemBuOaKnuiCouaVsOeiuuiqjeOBqFEyNS4xXzEx44Gu5oyH56S66aCF55uu44Gu5Y+M5pa544Gr5q2j562U44GX44Gf5Zue562U6ICF44Gr6ZmQ5a6a44GX44Gf44CCIg0KICAgICAgKQ0KICAgICkNCiAgKQ0KICANCiAgY29uZGl0aW9uX2F0dHJpdGlvbl90YWJsZSA8LSBzY3JlZW5pbmckY29uZGl0aW9uX2Zsb3cgJT4lDQogICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgIGDmnaHku7ZgID0gYXNzaWduZWRfY29uZGl0aW9uLA0KICAgICAgYOmghuW6j2AgPSBzdGFnZV9vcmRlciwNCiAgICAgIGDmrrXpmo5gID0gc3RhZ2UsDQogICAgICBg6LOq5ZWP5paH77yI6Kq/5p+756Wo44O76KaB57SE77yJYCA9IHNjcmVlbmluZ19xdWVzdGlvbl93b3JkaW5nKHN0dWR5X2lkLCBzdGFnZSwgYXNzaWduZWRfY29uZGl0aW9uKSwNCiAgICAgIGDmrovlrZhOYCA9IGZvcm1hdF9pbnRlZ2VyKG5fcmVtYWluaW5nKSwNCiAgICAgIGDlvZPoqbLmrrXpmo7jgafjga7pmaTlpJZOYCA9IGZvcm1hdF9pbnRlZ2VyKG5fZXhjbHVkZWRfYXRfc3RhZ2UpLA0KICAgICAgYOadoeS7tumWi+Wni+aZguOBi+OCieOBruaui+WtmOeOh++8iCXvvIlgID0gZm9ybWF0X251bWJlcihyZXRlbnRpb25fZnJvbV9jb25kaXRpb25fc3RhcnRfcGN0LCAxKQ0KICAgICkNCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgY29uZGl0aW9uX2F0dHJpdGlvbl90YWJsZSwNCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb25fYnlfY29uZGl0aW9uLmNzdiIpLA0KICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfc2FtcGxlX2F0dHJpdGlvbl9ieV9jb25kaXRpb24udGV4IiksDQogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5p2h5Lu25Yil44Gu6YCQ5qyh55qE44Gq5qiZ5pys5rib5bCRIiksDQogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYXR0cml0aW9uLWNvbmRpdGlvbiIpLA0KICAgIG5vdGVzID0gIuadoeS7tuOCkuWbnuetlOWxpeattOOBi+OCieitmOWIpeOBp+OBjeOBn+WbnuetlOiAheOBq+OBpOOBhOOBpuOAgeWQhOadoeS7tuWGheOBp+Wfuua6luOCkue0r+epjeeahOOBq+mBqeeUqOOBl+OBn+OAgiINCiAgKQ0KICANCiAgbWFuaXB1bGF0aW9uX3RhYmxlIDwtIHNjcmVlbmluZyRhdWRpdCAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShhc3NpZ25lZF9jb25kaXRpb24pKSAlPiUNCiAgICBkcGx5cjo6Y291bnQoDQogICAgICBhc3NpZ25lZF9jb25kaXRpb24sDQogICAgICBtYW5pcHVsYXRpb25fcmVzcG9uc2UsDQogICAgICBtYW5pcHVsYXRpb25fY2hlY2tfcGFzcywNCiAgICAgIG5hbWUgPSAibiINCiAgICApICU+JQ0KICAgIGRwbHlyOjp0cmFuc211dGUoDQogICAgICBg5p2h5Lu2YCA9IGFzc2lnbmVkX2NvbmRpdGlvbiwNCiAgICAgIGDos6rllY/mlofvvIjoqr/mn7vnpajvvIlgID0gc2NyZWVuaW5nX3F1ZXN0aW9uX3dvcmRpbmcoc3R1ZHlfaWQsICLpgbjmip7ogqLmlbDnorroqo0iLCBhc3NpZ25lZF9jb25kaXRpb24pLA0KICAgICAgYOWbnuetlGAgPSBkcGx5cjo6Y29hbGVzY2UobWFuaXB1bGF0aW9uX3Jlc3BvbnNlLCAi5pyq5a6f5pa944O75qyg5pCNIiksDQogICAgICBg5q2j562UYCA9IGlmZWxzZShtYW5pcHVsYXRpb25fY2hlY2tfcGFzcywgIuato+etlCIsICLkuI3mraPnrZTjg7vmrKDmkI0iKSwNCiAgICAgIGBOYCA9IGZvcm1hdF9pbnRlZ2VyKG4pDQogICAgKQ0KICBpZiAoc3R1ZHlfaWQgPT0gInN0dWR5MSIpIHsNCiAgICBtYW5pcHVsYXRpb25fdGFibGUgPC0gdGliYmxlOjp0aWJibGUoDQogICAgICBg5p2h5Lu2YCA9ICLlhajmnaHku7YiLA0KICAgICAgYOizquWVj+aWh++8iOiqv+afu+elqO+8iWAgPSAi77yIU3R1ZHkgMeOBp+OBr+ipsuW9k+izquWVj+OBquOBl++8iSIsDQogICAgICBg5Zue562UYCA9ICLoqr/mn7vnpajjgavpgbjmip7ogqLmlbDnorroqo3os6rllY/jgarjgZciLA0KICAgICAgYOato+etlGAgPSAi6YGp55So5aSWIiwNCiAgICAgIGBOYCA9ICIiDQogICAgKQ0KICB9DQogIHdyaXRlX2Nzdl9hbmRfdGV4KA0KICAgIG1hbmlwdWxhdGlvbl90YWJsZSwNCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX21hbmlwdWxhdGlvbl9jaGVjay5jc3YiKSwNCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX21hbmlwdWxhdGlvbl9jaGVjay50ZXgiKSwNCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrpgbjmip7ogqLmlbDjga7mk43kvZznorroqo0iKSwNCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1tYW5pcHVsYXRpb24tY2hlY2siKSwNCiAgICBub3RlcyA9ICJTdHVkeSAy44O7M+OBp+OBr+OAgeWJsuOCiuW9k+OBpuOCieOCjOOBn+mBuOaKnuiCouaVsOOBqOWQjOOBmOWbnuetlOOCkuato+etlOOBqOOBl+OBn+OAgiINCiAgKQ0KICANCiAgYXR0ZW50aW9uX3RhYmxlIDwtIHNjcmVlbmluZyRhdWRpdCAlPiUNCiAgICBkcGx5cjo6Y291bnQoYXR0ZW50aW9uX3Jlc3BvbnNlLCBhdHRlbnRpb25fY2hlY2tfcGFzcywgbmFtZSA9ICJuIikgJT4lDQogICAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICAgIGDos6rllY/mlofvvIjoqr/mn7vnpajvvIlgID0gc2NyZWVuaW5nX3F1ZXN0aW9uX3dvcmRpbmcoc3R1ZHlfaWQsICLmjIfnpLrpoIXnm64iKSwNCiAgICAgIGDlm57nrZRgID0gZHBseXI6OmNvYWxlc2NlKGF0dGVudGlvbl9yZXNwb25zZSwgIuacquWun+aWveODu+asoOaQjSIpLA0KICAgICAgYOWIpOWummAgPSBpZmVsc2UoYXR0ZW50aW9uX2NoZWNrX3Bhc3MsICLmraPnrZQiLCAi5LiN5q2j562U44O75qyg5pCNIiksDQogICAgICBgTmAgPSBmb3JtYXRfaW50ZWdlcihuKQ0KICAgICkNCiAgaWYgKHN0dWR5X2lkID09ICJzdHVkeTEiKSB7DQogICAgYXR0ZW50aW9uX3RhYmxlIDwtIHRpYmJsZTo6dGliYmxlKA0KICAgICAgYOizquWVj+aWh++8iOiqv+afu+elqO+8iWAgPSAi77yIU3R1ZHkgMeOBp+OBr+ipsuW9k+izquWVj+OBquOBl++8iSIsDQogICAgICBg5Zue562UYCA9ICLoqr/mn7vnpajjgavmjIfnpLrpoIXnm67jgarjgZciLA0KICAgICAgYOWIpOWummAgPSAi6YGp55So5aSWIiwNCiAgICAgIGBOYCA9ICIiDQogICAgKQ0KICB9DQogIHdyaXRlX2Nzdl9hbmRfdGV4KA0KICAgIGF0dGVudGlvbl90YWJsZSwNCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX2F0dGVudGlvbl9jaGVjay5jc3YiKSwNCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX2F0dGVudGlvbl9jaGVjay50ZXgiKSwNCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrjgqTjg4fjgqrjg63jgq7jg7zooYzliJfjga7mjIfnpLrpoIXnm64iKSwNCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1hdHRlbnRpb24tY2hlY2siKSwNCiAgICBub3RlcyA9ICJTdHVkeSAy44O7M+OBp+OBr+OAgeiqv+afu+eUu+mdouS4iuOBruaMh+ekuumgheebruOBp+OAjDPjgI3jgpLpgbjmip7jgZfjgZ/lm57nrZTogIXjgpLmraPnrZTjgajjgZfjgZ/jgIJRdWFsdHJpY3Pjga7kv53lrZjjgrPjg7zjg4njgYzooajnpLrlgKTjgajnlbDjgarjgovloLTlkIjjga/jgIHmnKzliIbmnpDjgafoh6rli5XmpJzlh7rjgZXjgozjgZ/kv53lrZjjgrPjg7zjg4njgpLnlKjjgYTjgZ/jgIIiDQogICkNCiAgDQogIGFtY2VfY292IDwtIG1ha2VfYW1jZV90YWJsZShlbnYsIGFkanVzdGVkID0gVFJVRSkNCiAgYW1jZV9ub2NvdiA8LSBtYWtlX2FtY2VfdGFibGUoZW52LCBhZGp1c3RlZCA9IEZBTFNFKQ0KICBpbnRlcmFjdGlvbiA8LSBtYWtlX2ludGVyYWN0aW9uX3RhYmxlKGVudikNCiAgbW1fdGFibGUgPC0gbWFrZV9tbV90YWJsZShlbnYpDQogIGF0dHJfaW1wb3J0YW5jZSA8LSBtYWtlX2F0dHJpYnV0ZV9pbXBvcnRhbmNlX3RhYmxlKGVudikNCiAgY3VlX2ltcG9ydGFuY2UgPC0gbWFrZV9jdWVfaW1wb3J0YW5jZV90YWJsZShlbnYpDQogIGNsb2dpdF90YWJsZSA8LSBtYWtlX2Nsb2dpdF90YWJsZShlbnYpDQogIGxpbmVhcl90cmVuZF90YWJsZSA8LSBtYWtlX2xpbmVhcl90cmVuZF90YWJsZShlbnYpDQogIHBhcnR5X21hdGNoX3RhYmxlIDwtIG1ha2VfcGFydHlfbWF0Y2hfdGFibGUoZW52KQ0KICANCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgYW1jZV9jb3YsDQogICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC5jc3YiKSwNCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLnRleCIpLA0KICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muWFseWkiemHj+iqv+aVtOa4iOOBv0FNQ0UiKSwNCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1hbWNlLWFkanVzdGVkIiksDQogICAgbm90ZXMgPSAi5o6o5a6a5YCk44Gu5Y2Y5L2N44Gv44OR44O844K744Oz44OI44Od44Kk44Oz44OI44CC5qiZ5rqW6Kqk5beu44Gv5Zue562U6ICF5Y2Y5L2N44Gn44Kv44Op44K544K/5YyW44GX44Gf44CCIg0KICApDQogIHdyaXRlX2Nzdl9hbmRfdGV4KA0KICAgIGFtY2Vfbm9jb3YsDQogICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9hbWNlX3VuYWRqdXN0ZWQuY3N2IiksDQogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9hbWNlX3VuYWRqdXN0ZWQudGV4IiksDQogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5YWx5aSJ6YeP44KS5ZCr44KB44Gq44GEQU1DRSIpLA0KICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLWFtY2UtdW5hZGp1c3RlZCIpLA0KICAgIG5vdGVzID0gIuaOqOWumuWApOOBruWNmOS9jeOBr+ODkeODvOOCu+ODs+ODiOODneOCpOODs+ODiOOAguaomea6luiqpOW3ruOBr+WbnuetlOiAheWNmOS9jeOBp+OCr+ODqeOCueOCv+WMluOBl+OBn+OAgiINCiAgKQ0KICB3cml0ZV9jc3ZfYW5kX3RleCgNCiAgICBpbnRlcmFjdGlvbiwNCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX2FtY2VfaW50ZXJhY3Rpb24uY3N2IiksDQogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9hbWNlX2ludGVyYWN0aW9uLnRleCIpLA0KICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8mjLpgbjmip7ogqLmnaHku7bjgajjga7lt67jgpLooajjgZlBTUNF5Lqk5LqS5L2c55SoIiksDQogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYW1jZS1pbnRlcmFjdGlvbiIpLA0KICAgIG5vdGVzID0gIuato+OBruWApOOBr+OAgeW9k+ipsuadoeS7tuOBq+OBiuOBkeOCi0FNQ0XjgYwy6YG45oqe6IKi5p2h5Lu244KI44KK5aSn44GN44GE44GT44Go44KS56S644GZ44CCIg0KICApDQogIHdyaXRlX2Nzdl9hbmRfdGV4KA0KICAgIG1tX3RhYmxlLA0KICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfbWFyZ2luYWxfbWVhbnMuY3N2IiksDQogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9tYXJnaW5hbF9tZWFucy50ZXgiKSwNCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrlsZ7mgKfmsLTmupbliKXjga7pmZDnlYzlubPlnYfvvIhNTe+8iSIpLA0KICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLW1hcmdpbmFsLW1lYW5zIiksDQogICAgbm90ZXMgPSAi6ZmQ55WM5bmz5Z2H44Gv5b2T6Kmy5rC05rqW44KS44KC44Gk44OX44Ot44OV44Kh44Kk44Or44Gu5bmz5Z2H6YG45oqe56K6546H44CCU0Xjgajkv6HpoLzljLrplpPjga/lm57nrZTogIXjgq/jg6njgrnjgr/jgavlr77lv5zjgZfjgZ/liIfniYfjga7jgb/jga7nt5rlvaLnorrnjofjg6Ljg4fjg6vjgajlkIzlgKTjga7oqIjnrpfjgavjgojjgovjgIIiDQogICkNCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgYXR0cl9pbXBvcnRhbmNlLA0KICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfYXR0cmlidXRlX2ltcG9ydGFuY2UuY3N2IiksDQogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS50ZXgiKSwNCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrlsZ7mgKfliKXjga7mnKroqr/mlbTjg7vpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqYiKSwNCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1hdHRyaWJ1dGUtaW1wb3J0YW5jZSIpLA0KICAgIG5vdGVzID0gIuacquiqv+aVtOmHjeimgeW6puOBr+mZkOeVjOW5s+Wdh+OBruWFqOawtOa6luODmuOCouOBrue1tuWvvuW3ruOBruW5s+Wdh+OAguiqv+aVtOa4iOOBv+mHjeimgeW6puOBr+acquiqv+aVtOmHjeimgeW6puOCkjHvvI/pgbjmip7ogqLmlbDjgafpmaTjgZfjgZ/jgIIiDQogICkNCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgY3VlX2ltcG9ydGFuY2UsDQogICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS5jc3YiKSwNCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX2N1ZV9pbXBvcnRhbmNlLnRleCIpLA0KICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muaUv+WFmuODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjSIpLA0KICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLWN1ZS1pbXBvcnRhbmNlIiksDQogICAgbm90ZXMgPSAiOTUl5L+h6aC85Yy66ZaT44Gv5p2h5Lu25YaF44Gn5Zue562U6ICF44KS5b6p5YWD5oq95Ye644GZ44KL44Kv44Op44K544K/44O744OW44O844OI44K544OI44Op44OD44OX44Gr44KI44KL44CCIg0KICApDQogIHdyaXRlX2Nzdl9hbmRfdGV4KA0KICAgIGNsb2dpdF90YWJsZSwNCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LmNzdiIpLA0KICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfY29uZGl0aW9uYWxfbG9naXQudGV4IiksDQogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5p2h5Lu25LuY44GN44Ot44K444OD44OI5o6o5a6aIiksDQogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItY29uZGl0aW9uYWwtbG9naXQiKSwNCiAgICBub3RlcyA9ICLlkITpgbjmip7oqrLpoYzjgpJzdHJhdHVt44Go44GZ44KLTWNGYWRkZW7lnovmnaHku7bku5jjgY3jg63jgrjjg4Pjg4jjgILmqJnmupboqqTlt67jga/lm57nrZTogIXljZjkvY3jgafjgq/jg6njgrnjgr/ljJbjgZfjgZ/jgIIiDQogICkNCiAgDQogIGlmIChucm93KGxpbmVhcl90cmVuZF90YWJsZSkgPiAwKSB7DQogICAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgICBsaW5lYXJfdHJlbmRfdGFibGUsDQogICAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX2FtY2VfbGluZWFyX3RyZW5kLmNzdiIpLA0KICAgICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9hbWNlX2xpbmVhcl90cmVuZC50ZXgiKSwNCiAgICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8mumBuOaKnuiCouaVsOOBq+WvvuOBmeOCi0FNQ0Xjga7nt5rlvaLjg4jjg6zjg7Pjg4kiKSwNCiAgICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLWFtY2UtbGluZWFyLXRyZW5kIiksDQogICAgICBub3RlcyA9ICLkv4LmlbDjga/pgbjmip7ogqLmlbDjgYwx44Gk5aKX44GI44Gf44Go44GN44GuQU1DReOBruWkieWMluOCkuODkeODvOOCu+ODs+ODiOODneOCpOODs+ODiOOBp+ekuuOBmeOAgiINCiAgICApDQogIH0NCiAgDQogIGlmIChucm93KHBhcnR5X21hdGNoX3RhYmxlKSA+IDApIHsNCiAgICB3cml0ZV9jc3ZfYW5kX3RleCgNCiAgICAgIHBhcnR5X21hdGNoX3RhYmxlLA0KICAgICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9wYXJ0eV9tYXRjaC5jc3YiKSwNCiAgICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfcGFydHlfbWF0Y2gudGV4IiksDQogICAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrmlK/mjIHmlL/lhZrjgajmj5DnpLrmlL/lhZrlkI3jga7kuIDoh7TlirnmnpwiKSwNCiAgICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLXBhcnR5LW1hdGNoIiksDQogICAgICBub3RlcyA9ICLkuIDoh7Tlirnmnpzjga/jgIHlm57nrZTogIXjga7mlK/mjIHmlL/lhZrjgajmj5DnpLrjgZXjgozjgZ/mlL/lhZrlkI3jgYzkuIDoh7TjgZnjgovjgZPjgajjgavjgojjgovpgbjmip7norrnjoflt67jgIIiDQogICAgKQ0KICB9DQogIA0KICBiYWxhbmNlIDwtIGFzc2lnbm1lbnRfYmFsYW5jZV9yZXN1bHRzW1tzdHVkeV9pZF1dDQogIGJhbGFuY2Vfc3VtbWFyeSA8LSBiYWxhbmNlJHN1bW1hcnkgJT4lDQogICAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IGZvcm1hdF9udW1iZXIoLngsIDMpKSkNCiAgYmFsYW5jZV9wYWlyd2lzZSA8LSBiYWxhbmNlJHBhaXJ3aXNlX3NtZCAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gZm9ybWF0X251bWJlcigueCwgMykpKQ0KICANCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgYmFsYW5jZV9zdW1tYXJ5LA0KICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfYXNzaWdubWVudF9iYWxhbmNlX3N1bW1hcnkuY3N2IiksDQogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9hc3NpZ25tZW50X2JhbGFuY2Vfc3VtbWFyeS50ZXgiKSwNCiAgICBwYXN0ZTAoc3R1ZHlfbGFiZWwsICLvvJrmnaHku7bliKXjga7lm57nrZTogIXlsZ7mgKciKSwNCiAgICBwYXN0ZTAoInRhYjoiLCBzdHVkeV9pZCwgIi1iYWxhbmNlLXN1bW1hcnkiKSwNCiAgICBub3RlcyA9ICJMb3ZlIHBsb3TjgYrjgojjgbM0NeW6pue3muiouuaWreOBq+WvvuW/nOOBmeOCi+adoeS7tuWIpembhuioiOOAgiINCiAgKQ0KICB3cml0ZV9jc3ZfYW5kX3RleCgNCiAgICBiYWxhbmNlX3BhaXJ3aXNlLA0KICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfYXNzaWdubWVudF9iYWxhbmNlX3BhaXJ3aXNlX3NtZC5jc3YiKSwNCiAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX2Fzc2lnbm1lbnRfYmFsYW5jZV9wYWlyd2lzZV9zbWQudGV4IiksDQogICAgcGFzdGUwKHN0dWR5X2xhYmVsLCAi77ya5YWo5p2h5Lu244Oa44Ki44Gu5qiZ5rqW5YyW5bmz5Z2H5beuIiksDQogICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItYmFsYW5jZS1zbWQiKSwNCiAgICBub3RlcyA9ICLntbblr75TTUTjgYwwLjEw5pyq5rqA44Gn44GC44KM44Gw44CB6YCa5bi444Gv5a6f6LOq55qE44Gr5bCP44GV44GE5LiN5Z2H6KGh44Go6Kej6YeI44GV44KM44KL44CCIg0KICApDQogIHJlYWRyOjp3cml0ZV9jc3YoYmFsYW5jZSRzdW1tYXJ5LCBmaWxlLnBhdGgoZGlhZ19iYWxhbmNlX2RpciwgImFzc2lnbm1lbnRfYmFsYW5jZV9zdW1tYXJ5LmNzdiIpLCBuYSA9ICIiKQ0KICByZWFkcjo6d3JpdGVfY3N2KGJhbGFuY2UkcGFpcndpc2Vfc21kLCBmaWxlLnBhdGgoZGlhZ19iYWxhbmNlX2RpciwgImFzc2lnbm1lbnRfYmFsYW5jZV9wYWlyd2lzZV9zbWQuY3N2IiksIG5hID0gIiIpDQogIHJlYWRyOjp3cml0ZV9jc3YoYmFsYW5jZSRkaWFnb25hbF9kYXRhLCBmaWxlLnBhdGgoZGlhZ19iYWxhbmNlX2RpciwgImFzc2lnbm1lbnRfYmFsYW5jZV9kaWFnb25hbF9kYXRhLmNzdiIpLCBuYSA9ICIiKQ0KICANCiAgcmFuZG9taXphdGlvbiA8LSBwcm9maWxlX3JhbmRvbWl6YXRpb25fcmVzdWx0c1tbc3R1ZHlfaWRdXQ0KICByYW5kb21fdGVzdHMgPC0gcmFuZG9taXphdGlvbiR1bmlmb3JtaXR5X3Rlc3RzICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXRfbnVtYmVyKC54LCA0KSkpDQogIHJhbmRvbV9mcmVxdWVuY3kgPC0gcmFuZG9taXphdGlvbiRmcmVxdWVuY3kgJT4lDQogICAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IGZvcm1hdF9udW1iZXIoLngsIDQpKSkNCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgcmFuZG9tX3Rlc3RzLA0KICAgIGZpbGUucGF0aChjc3ZfZGlyLCAidGFibGVfcHJvZmlsZV9yYW5kb21pemF0aW9uX3Rlc3RzLmNzdiIpLA0KICAgIGZpbGUucGF0aCh0ZXhfZGlyLCAidGFibGVfcHJvZmlsZV9yYW5kb21pemF0aW9uX3Rlc3RzLnRleCIpLA0KICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muWxnuaAp+awtOa6luaPkOekuuOBruS4gOanmOaAp+aknOWumiIpLA0KICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLXByb2ZpbGUtcmFuZG9taXphdGlvbi10ZXN0cyIpLA0KICAgIG5vdGVzID0gIuWxnuaAp8OX5p2h5Lu244GU44Go44Gu44Kr44Kk5LqM5LmX5qSc5a6a44CCcOWApOOBr0hvbG3ms5XjgafjgoLoo5zmraPjgZfjgZ/jgIIiDQogICkNCiAgd3JpdGVfY3N2X2FuZF90ZXgoDQogICAgcmFuZG9tX2ZyZXF1ZW5jeSwNCiAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9mcmVxdWVuY3kuY3N2IiksDQogICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9wcm9maWxlX3JhbmRvbWl6YXRpb25fZnJlcXVlbmN5LnRleCIpLA0KICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+OBqOioreioiOS4iuOBruacn+W+heavlOeOhyIpLA0KICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLXByb2ZpbGUtcmFuZG9taXphdGlvbi1mcmVxdWVuY3kiKSwNCiAgICBub3RlcyA9ICLlsZ7mgKfmj5DnpLrjga40NeW6pue3muWbs+OBq+WvvuW/nOOBmeOCi+aVsOWApOihqOOAgiINCiAgKQ0KICByZWFkcjo6d3JpdGVfY3N2KHJhbmRvbWl6YXRpb24kdW5pZm9ybWl0eV90ZXN0cywgZmlsZS5wYXRoKGRpYWdfcmFuZG9tX2RpciwgInByb2ZpbGVfcmFuZG9taXphdGlvbl90ZXN0cy5jc3YiKSwgbmEgPSAiIikNCiAgcmVhZHI6OndyaXRlX2NzdihyYW5kb21pemF0aW9uJGZyZXF1ZW5jeSwgZmlsZS5wYXRoKGRpYWdfcmFuZG9tX2RpciwgInByb2ZpbGVfcmFuZG9taXphdGlvbl9mcmVxdWVuY3kuY3N2IiksIG5hID0gIiIpDQogIA0KICBzdXBwb3J0X2FtY2UgPC0gcGFydHlfc3VwcG9ydF9hbWNlX3Jlc3VsdHNbW3N0dWR5X2lkXV0NCiAgaWYgKCFpcy5udWxsKHN1cHBvcnRfYW1jZSRzdWJncm91cF9jb2VmZmljaWVudHMpKSB7DQogICAgc3VwcG9ydF9hbWNlX3RhYmxlIDwtIHN1cHBvcnRfYW1jZSRzdWJncm91cF9jb2VmZmljaWVudHMgJT4lDQogICAgICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gZm9ybWF0X251bWJlcigueCwgMykpKQ0KICAgIHdyaXRlX2Nzdl9hbmRfdGV4KA0KICAgICAgc3VwcG9ydF9hbWNlX3RhYmxlLA0KICAgICAgZmlsZS5wYXRoKGNzdl9kaXIsICJ0YWJsZV9wYXJ0eV9zdXBwb3J0X2FtY2UuY3N2IiksDQogICAgICBmaWxlLnBhdGgodGV4X2RpciwgInRhYmxlX3BhcnR5X3N1cHBvcnRfYW1jZS50ZXgiKSwNCiAgICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muaUr+aMgeaUv+WFmuWIpUFNQ0UiKSwNCiAgICAgIHBhc3RlMCgidGFiOiIsIHN0dWR5X2lkLCAiLXBhcnR5LXN1cHBvcnQtYW1jZSIpLA0KICAgICAgbm90ZXMgPSAi5pSv5oyB5pS/5YWa5YilQU1DReWbs+OBq+WvvuW/nOOBmeOCi+aOqOWumuWApOOAgiINCiAgICApDQogIH0NCiAgc3VwcG9ydF9yZWxhdGl2ZSA8LSBwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV9yZXN1bHRzW1tzdHVkeV9pZF1dDQogIGlmICghaXMubnVsbChzdXBwb3J0X3JlbGF0aXZlJGludGVydmFscykpIHsNCiAgICBzdXBwb3J0X3JlbGF0aXZlX3RhYmxlIDwtIHN1cHBvcnRfcmVsYXRpdmUkaW50ZXJ2YWxzICU+JQ0KICAgICAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IGZvcm1hdF9udW1iZXIoLngsIDMpKSkNCiAgICB3cml0ZV9jc3ZfYW5kX3RleCgNCiAgICAgIHN1cHBvcnRfcmVsYXRpdmVfdGFibGUsDQogICAgICBmaWxlLnBhdGgoY3N2X2RpciwgInRhYmxlX3BhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlLmNzdiIpLA0KICAgICAgZmlsZS5wYXRoKHRleF9kaXIsICJ0YWJsZV9wYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZS50ZXgiKSwNCiAgICAgIHBhc3RlMChzdHVkeV9sYWJlbCwgIu+8muaUr+aMgeaUv+WFmuWIpeOBruaJi+OBjOOBi+OCiumHjeimgeW6puOBqOebuOWvvuavlOmHjSIpLA0KICAgICAgcGFzdGUwKCJ0YWI6Iiwgc3R1ZHlfaWQsICItcGFydHktc3VwcG9ydC1yZWxhdGl2ZSIpLA0KICAgICAgbm90ZXMgPSAi5pSv5oyB5pS/5YWa5Yil44Gu55u45a++5q+U6YeN5Zuz44Gr5a++5b+c44GZ44KL5Zue562U6ICF44Kv44Op44K544K/44O744OW44O844OI44K544OI44Op44OD44OX5o6o5a6a44CCIg0KICAgICkNCiAgfQ0KICANCiAgc3R1ZHlfdGFibGVfcGF0aHNbW3N0dWR5X2lkXV0gPC0gbGlzdChjc3ZfZGlyID0gY3N2X2RpciwgdGV4X2RpciA9IHRleF9kaXIpDQp9DQoNCg0KY3Jvc3NfY3N2X2RpciA8LSBmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X2Nyb3NzLCAidGFibGVzX2NzdiIpDQpjcm9zc190ZXhfZGlyIDwtIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfY3Jvc3MsICJ0YWJsZXNfdGV4IikNCg0KY3Jvc3NfdGFibGVzIDwtIGxpc3QoDQogIGh5cG90aGVzaXMgPSBoeXBvdGhlc2lzX3Rlc3Rfc3VtbWFyeSwNCiAgYWRqdXN0ZWRfc2xvcGVzID0gY2hvaWNlX3NldF9hZGp1c3RlZF9zbG9wZV9zdW1tYXJ5LA0KICBjcm9zc19yZWxhdGl2ZSA9IGNyb3NzX3N0dWR5X3JlbGF0aXZlX3dlaWdodCwNCiAgYWxsX3BhcnR5X21hdGNoX2NvZWZmaWNpZW50cyA9IHN0dWR5M19hbGxfcGFydHlfbWF0Y2hfcmVzdWx0cyRjb2VmZmljaWVudHMsDQogIGFsbF9wYXJ0eV9tYXRjaF90cmVuZHMgPSBzdHVkeTNfYWxsX3BhcnR5X21hdGNoX3Jlc3VsdHMkdHJlbmRzDQopDQoNCmNyb3NzX2NhcHRpb24gPC0gYygNCiAgaHlwb3RoZXNpcyA9ICIz5a6f6aiT44Gu5Li76KaB5Luu6Kqs44Gr5a++5b+c44GZ44KL57ea5b2i5YK+5ZCR5qSc5a6aIiwNCiAgYWRqdXN0ZWRfc2xvcGVzID0gIjPlrp/pqJPjga7pgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbjga7nt5rlvaLlgr7lkJEiLA0KICBjcm9zc19yZWxhdGl2ZSA9ICIz5a6f6aiT5qiq5pat44Gu5pS/5YWa5omL44GM44GL44KK55u45a++5q+U6YeNIiwNCiAgYWxsX3BhcnR5X21hdGNoX2NvZWZmaWNpZW50cyA9ICJTdHVkeSAz77ya44GZ44G544Gm44Gu5a++6LGh5pSv5oyB5pS/5YWa44Gr44GK44GR44KL5LiA6Ie05Yq55p6cIiwNCiAgYWxsX3BhcnR5X21hdGNoX3RyZW5kcyA9ICJTdHVkeSAz77ya5LiA6Ie05Yq55p6c44Gu6YG45oqe6IKi5pWw44OI44Os44Oz44OJIg0KKQ0KDQpmb3IgKHRhYmxlX25hbWUgaW4gbmFtZXMoY3Jvc3NfdGFibGVzKSkgew0KICB0YWJsZV9kYXRhIDwtIGNyb3NzX3RhYmxlc1tbdGFibGVfbmFtZV1dDQogIGlmIChpcy5udWxsKHRhYmxlX2RhdGEpKSBuZXh0DQogIHRhYmxlX2RhdGEgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZV9kYXRhKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gZm9ybWF0X251bWJlcigueCwgNCkpKQ0KICB3cml0ZV9jc3ZfYW5kX3RleCgNCiAgICB0YWJsZV9kYXRhLA0KICAgIGZpbGUucGF0aChjcm9zc19jc3ZfZGlyLCBwYXN0ZTAoInRhYmxlXyIsIHRhYmxlX25hbWUsICIuY3N2IikpLA0KICAgIGZpbGUucGF0aChjcm9zc190ZXhfZGlyLCBwYXN0ZTAoInRhYmxlXyIsIHRhYmxlX25hbWUsICIudGV4IikpLA0KICAgIHVubmFtZShjcm9zc19jYXB0aW9uW3RhYmxlX25hbWVdKSwNCiAgICBwYXN0ZTAoInRhYjpjcm9zcy0iLCBnc3ViKCJfIiwgIi0iLCB0YWJsZV9uYW1lKSksDQogICAgbm90ZXMgPSAi5a++5b+c44GZ44KL6KOc6YG65Zuz44Gu5pWw5YCk44KS6KGo5b2i5byP44Gn5YaN5o6y44GX44Gf44CCIg0KICApDQp9DQoNCg0KZm9yIChzdHVkeV9pZCBpbiBuYW1lcyhzdHVkeV9zcGVjcykpIHsNCiAgd29ya2luZ19kaXIgPC0gdW5pZmllZF9jb25maWdbW3N0dWR5X2lkXV0kb3V0cHV0X2Rpcg0KICBzdXBwbGVtZW50X2ZpZ19kaXIgPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCBzdHVkeV9pZCwgImZpZ3VyZXMiKQ0KICBjb3B5X2ZpbGVzX2J5X3BhdHRlcm4od29ya2luZ19kaXIsIHN1cHBsZW1lbnRfZmlnX2RpciwgIlxcLihwbmd8cGRmKSQiKQ0KICBjb3B5X2ZpbGVzX2J5X3BhdHRlcm4oDQogICAgd29ya2luZ19kaXIsDQogICAgZmlsZS5wYXRoKGZpbmFsX2RpcnMkbW9kZWxfb2JqZWN0c19yb290LCBzdHVkeV9pZCksDQogICAgIlxcLihyZHN8UkRTKSQiDQogICkNCiAgY29weV9maWxlc19ieV9wYXR0ZXJuKHdvcmtpbmdfZGlyLCBmaW5hbF9kaXJzJGxvZ3MsICIoc2Vzc2lvbkluZm98XFwudHh0JCkiKQ0KICANCiAgc3VwcG9ydF9kaXIgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKHN0dWR5X2lkLCAiX3BhcnR5X3N1cHBvcnQiKSkNCiAgY29weV9maWxlc19ieV9wYXR0ZXJuKHN1cHBvcnRfZGlyLCBzdXBwbGVtZW50X2ZpZ19kaXIsICJcXC4ocG5nfHBkZikkIikNCn0NCg0KY29weV9maWxlc19ieV9wYXR0ZXJuKA0KICB1bmlmaWVkX291dHB1dF9kaXIsDQogIGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfY3Jvc3MsICJmaWd1cmVzIiksDQogICJcXC4ocG5nfHBkZikkIg0KKQ0KY29weV9maWxlc19ieV9wYXR0ZXJuKHVuaWZpZWRfb3V0cHV0X2RpciwgZmluYWxfZGlycyRsb2dzLCAiKHNlc3Npb25JbmZvfFxcLnR4dCQpIikNCmNvcHlfZmlsZXNfYnlfcGF0dGVybigNCiAgdW5pZmllZF9vdXRwdXRfZGlyLA0KICBmaWxlLnBhdGgoZmluYWxfZGlycyRtb2RlbF9vYmplY3RzX3Jvb3QsICJjcm9zc19zdHVkeSIpLA0KICAiXFwuKHJkc3xSRFMpJCINCikNCg0KZm9yIChzdHVkeV9pZCBpbiBuYW1lcyhzdHVkeV9zcGVjcykpIHsNCiAgZm9yIChraW5kIGluIGMoImFzc2lnbm1lbnRfYmFsYW5jZV9sb3ZlX3Bsb3QiLCAiYXNzaWdubWVudF9iYWxhbmNlX2RpYWdvbmFsX3Bsb3QiKSkgew0KICAgIGZvciAoZXh0ZW5zaW9uIGluIGMoInBuZyIsICJwZGYiKSkgew0KICAgICAgc291cmNlIDwtIGZpbGUucGF0aCh1bmlmaWVkX291dHB1dF9kaXIsIHBhc3RlMChzdHVkeV9pZCwgIl8iLCBraW5kLCAiLiIsIGV4dGVuc2lvbikpDQogICAgICBkZXN0aW5hdGlvbiA8LSBmaWxlLnBhdGgoZmluYWxfZGlycyRkaWFnbm9zdGljc19yb290LCBzdHVkeV9pZCwgImJhbGFuY2UiLCBiYXNlbmFtZShzb3VyY2UpKQ0KICAgICAgY29weV9maWxlX2lmX2V4aXN0cyhzb3VyY2UsIGRlc3RpbmF0aW9uKQ0KICAgIH0NCiAgfQ0KICBmb3IgKGV4dGVuc2lvbiBpbiBjKCJwbmciLCAicGRmIikpIHsNCiAgICBzb3VyY2UgPC0gZmlsZS5wYXRoKHVuaWZpZWRfb3V0cHV0X2RpciwgcGFzdGUwKHN0dWR5X2lkLCAiX3Byb2ZpbGVfcmFuZG9taXphdGlvbl9kaWFnb25hbF9wbG90LiIsIGV4dGVuc2lvbikpDQogICAgZGVzdGluYXRpb24gPC0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkZGlhZ25vc3RpY3Nfcm9vdCwgc3R1ZHlfaWQsICJyYW5kb21pemF0aW9uIiwgYmFzZW5hbWUoc291cmNlKSkNCiAgICBjb3B5X2ZpbGVfaWZfZXhpc3RzKHNvdXJjZSwgZGVzdGluYXRpb24pDQogIH0NCn0NCg0KaWYgKGV4aXN0cygibWFpbl90ZXh0X2ZpZ3VyZV9tYW5pZmVzdCIpKSB7DQogIHB1cnJyOjpwd2FsaygNCiAgICBtYWluX3RleHRfZmlndXJlX21hbmlmZXN0LA0KICAgIGZ1bmN0aW9uKGZpZ3VyZV9udW1iZXIsIHN0dWR5LCBhbmFseXNpcywgZmlsZV9wbmcsIGZpbGVfcGRmKSB7DQogICAgICBwcmVmaXggPC0gZ3N1YigiW15BLVphLXowLTldKyIsICJfIiwgZmlndXJlX251bWJlcikNCiAgICAgIGlmICghaXMubmEoZmlsZV9wbmcpKSB7DQogICAgICAgIGNvcHlfZmlsZV9pZl9leGlzdHMoDQogICAgICAgICAgZmlsZV9wbmcsDQogICAgICAgICAgZmlsZS5wYXRoKGZpbmFsX2RpcnMkbWFpbl9maWd1cmVzLCBwYXN0ZTAocHJlZml4LCAiXyIsIGJhc2VuYW1lKGZpbGVfcG5nKSkpDQogICAgICAgICkNCiAgICAgIH0NCiAgICAgIGlmICghaXMubmEoZmlsZV9wZGYpKSB7DQogICAgICAgIGNvcHlfZmlsZV9pZl9leGlzdHMoDQogICAgICAgICAgZmlsZV9wZGYsDQogICAgICAgICAgZmlsZS5wYXRoKGZpbmFsX2RpcnMkbWFpbl9maWd1cmVzLCBwYXN0ZTAocHJlZml4LCAiXyIsIGJhc2VuYW1lKGZpbGVfcGRmKSkpDQogICAgICAgICkNCiAgICAgIH0NCiAgICB9DQogICkNCn0NCg0KbWFpbl90YWJsZV9tYXAgPC0gbGlzdCgNCiAgc3R1ZHkxID0gYygidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQudGV4IiwgInRhYmxlX2N1ZV9pbXBvcnRhbmNlLnRleCIpLA0KICBzdHVkeTIgPSBjKCJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC50ZXgiLCAidGFibGVfY3VlX2ltcG9ydGFuY2UudGV4IiksDQogIHN0dWR5MyA9IGMoInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLnRleCIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS50ZXgiLCAidGFibGVfcGFydHlfbWF0Y2gudGV4IikNCikNCmZvciAoc3R1ZHlfaWQgaW4gbmFtZXMobWFpbl90YWJsZV9tYXApKSB7DQogIGZvciAodGFibGVfZmlsZSBpbiBtYWluX3RhYmxlX21hcFtbc3R1ZHlfaWRdXSkgew0KICAgIHNvdXJjZSA8LSBmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X3Jvb3QsIHN0dWR5X2lkLCAidGFibGVzX3RleCIsIHRhYmxlX2ZpbGUpDQogICAgY29weV9maWxlX2lmX2V4aXN0cygNCiAgICAgIHNvdXJjZSwNCiAgICAgIGZpbGUucGF0aChmaW5hbF9kaXJzJG1haW5fdGFibGVzLCBwYXN0ZTAoc3R1ZHlfaWQsICJfIiwgdGFibGVfZmlsZSkpDQogICAgKQ0KICB9DQp9DQoNCg0KcGFpcl9tYW5pZmVzdCA8LSB0aWJibGU6OnRyaWJibGUoDQogIH5zdHVkeV9pZCwgfnNlY3Rpb25fdGl0bGUsIH5maWd1cmVfZmlsZSwgfnRhYmxlX2ZpbGVzLA0KICAic3R1ZHkxIiwgIuWFseWkiemHj+iqv+aVtOa4iOOBv0FNQ0UiLCAiYW1jZV9jb3ZfZmFjZXRfbW9kZWwucG5nIiwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLnRleCIsDQogICJzdHVkeTEiLCAiQU1DReODkuODvOODiOODnuODg+ODlyIsICJhbWNlX2hlYXRtYXBfbWl4ZWRfcmFua19jb2xvcmVkX2xhYmVscy5wbmciLCAidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQudGV4IiwNCiAgInN0dWR5MSIsICLlhbHlpInph4/jgpLlkKvjgoHjgarjgYRBTUNFIiwgImFtY2VfZmFjZXRfbm9jb3YucG5nIiwgInRhYmxlX2FtY2VfdW5hZGp1c3RlZC50ZXgiLA0KICAic3R1ZHkxIiwgIkFNQ0Xjga7mnaHku7blt64iLCAiYW1jZV9pbnRlcmFjdGlvbl9kaWZmZXJlbmNlX2Zyb21fMnBhcnR5LnBuZyIsICJ0YWJsZV9hbWNlX2ludGVyYWN0aW9uLnRleCIsDQogICJzdHVkeTEiLCAi5p2h5Lu25LuY44GN44Ot44K444OD44OIIiwgImNsb2dpdF9vZGRzcmF0aW9fbm9jb3YucG5nIiwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LnRleCIsDQogICJzdHVkeTEiLCAi5omL44GM44GL44KK6YeN6KaB5bqm44Go55u45a++5q+U6YeNIiwgImZpZ19zdHVkeTFfcmVsYXRpdmVfY3VlX3dlaWdodF9jaG9pY2Vfc2V0X2FkanVzdGVkX2pwX2J3LnBuZyIsICJ0YWJsZV9tYXJnaW5hbF9tZWFucy50ZXg7dGFibGVfYXR0cmlidXRlX2ltcG9ydGFuY2UudGV4O3RhYmxlX2N1ZV9pbXBvcnRhbmNlLnRleCIsDQogICJzdHVkeTIiLCAi5YWx5aSJ6YeP6Kq/5pW05riI44G/QU1DRSIsICJhbWNlX2Nvdl9mYWNldF9tb2RlbC5wbmciLCAidGFibGVfYW1jZV9jb3ZhcmlhdGVfYWRqdXN0ZWQudGV4IiwNCiAgInN0dWR5MiIsICJBTUNF44OS44O844OI44Oe44OD44OXIiwgImFtY2VfaGVhdG1hcF9taXhlZF9yYW5rX2NvbG9yZWRfbGFiZWxzLnBuZyIsICJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC50ZXgiLA0KICAic3R1ZHkyIiwgIuWFseWkiemHj+OCkuWQq+OCgeOBquOBhEFNQ0UiLCAiYW1jZV9mYWNldF9ub2Nvdi5wbmciLCAidGFibGVfYW1jZV91bmFkanVzdGVkLnRleCIsDQogICJzdHVkeTIiLCAiQU1DReOBruadoeS7tuW3riIsICJhbWNlX2ludGVyYWN0aW9uX2RpZmZlcmVuY2VfZnJvbV8ycGFydHkucG5nIiwgInRhYmxlX2FtY2VfaW50ZXJhY3Rpb24udGV4IiwNCiAgInN0dWR5MiIsICLmnaHku7bku5jjgY3jg63jgrjjg4Pjg4giLCAiY2xvZ2l0X29kZHNyYXRpb19ub2Nvdi5wbmciLCAidGFibGVfY29uZGl0aW9uYWxfbG9naXQudGV4IiwNCiAgInN0dWR5MiIsICLmiYvjgYzjgYvjgorph43opoHluqbjgajnm7jlr77mr5Tph40iLCAiZmlnX3N0dWR5Ml9yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYncucG5nIiwgInRhYmxlX21hcmdpbmFsX21lYW5zLnRleDt0YWJsZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS50ZXg7dGFibGVfY3VlX2ltcG9ydGFuY2UudGV4IiwNCiAgInN0dWR5MyIsICLlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIiwgImFtY2VfY292X2ZhY2V0X21vZGVsLnBuZyIsICJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC50ZXgiLA0KICAic3R1ZHkzIiwgIuWFseWkiemHj+OCkuWQq+OCgeOBquOBhEFNQ0UiLCAiYW1jZV9ub2Nvdl9mYWNldF9tb2RlbC5wbmciLCAidGFibGVfYW1jZV91bmFkanVzdGVkLnRleCIsDQogICJzdHVkeTMiLCAiQU1DReOBruadoeS7tuW3riIsICJhbWNlX2ludGVyYWN0aW9uX2RpZmZlcmVuY2VfZnJvbV8yY2hvaWNlLnBuZyIsICJ0YWJsZV9hbWNlX2ludGVyYWN0aW9uLnRleCIsDQogICJzdHVkeTMiLCAiQU1DReOBrue3muW9ouODiOODrOODs+ODiSIsICJhbWNlX2xpbmVhcl90cmVuZC5wbmciLCAidGFibGVfYW1jZV9saW5lYXJfdHJlbmQudGV4IiwNCiAgInN0dWR5MyIsICJBTUNF44OS44O844OI44Oe44OD44OXIiwgImFtY2VfY292X2hlYXRtYXAucG5nIiwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLnRleCIsDQogICJzdHVkeTMiLCAi5p2h5Lu25LuY44GN44Ot44K444OD44OIIiwgImNsb2dpdF9vZGRzcmF0aW9fbm9jb3YucG5nIiwgInRhYmxlX2NvbmRpdGlvbmFsX2xvZ2l0LnRleCIsDQogICJzdHVkeTMiLCAi5pSv5oyB5pS/5YWa44Go5o+Q56S65pS/5YWa5ZCN44Gu5LiA6Ie05Yq55p6cIiwgInBhcnR5X21hdGNoX2VmZmVjdF9jb21iaW5lZC5wbmciLCAidGFibGVfcGFydHlfbWF0Y2gudGV4IiwNCiAgInN0dWR5MyIsICLmiYvjgYzjgYvjgorph43opoHluqbjgajnm7jlr77mr5Tph40iLCAiZmlnX3N0dWR5M19yZWxhdGl2ZV9jdWVfd2VpZ2h0X2Nob2ljZV9zZXRfYWRqdXN0ZWRfanBfYncucG5nIiwgInRhYmxlX21hcmdpbmFsX21lYW5zLnRleDt0YWJsZV9hdHRyaWJ1dGVfaW1wb3J0YW5jZS50ZXg7dGFibGVfY3VlX2ltcG9ydGFuY2UudGV4Ig0KKQ0KDQpmb3IgKHN0dWR5X2lkIGluIG5hbWVzKHN0dWR5X3NwZWNzKSkgew0KICBzdXBwb3J0X2ZpZ3VyZXMgPC0gbGlzdC5maWxlcygNCiAgICBmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X3Jvb3QsIHN0dWR5X2lkLCAiZmlndXJlcyIpLA0KICAgIHBhdHRlcm4gPSAicGFydHlfc3VwcG9ydF9hbWNlXy4qXFwucG5nJCIsDQogICAgZnVsbC5uYW1lcyA9IEZBTFNFDQogICkNCiAgaWYgKGxlbmd0aChzdXBwb3J0X2ZpZ3VyZXMpID4gMCkgew0KICAgIHBhaXJfbWFuaWZlc3QgPC0gZHBseXI6OmJpbmRfcm93cygNCiAgICAgIHBhaXJfbWFuaWZlc3QsDQogICAgICB0aWJibGU6OnRpYmJsZSgNCiAgICAgICAgc3R1ZHlfaWQgPSBzdHVkeV9pZCwNCiAgICAgICAgc2VjdGlvbl90aXRsZSA9IHBhc3RlMCgi5pSv5oyB5pS/5YWa5YilQU1DRe+8miIsIHN1cHBvcnRfZmlndXJlcyksDQogICAgICAgIGZpZ3VyZV9maWxlID0gc3VwcG9ydF9maWd1cmVzLA0KICAgICAgICB0YWJsZV9maWxlcyA9ICJ0YWJsZV9wYXJ0eV9zdXBwb3J0X2FtY2UudGV4Ig0KICAgICAgKQ0KICAgICkNCiAgfQ0KICBpZiAoZmlsZS5leGlzdHMoZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCBzdHVkeV9pZCwgImZpZ3VyZXMiLCAicGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfd2VpZ2h0LnBuZyIpKSkgew0KICAgIHBhaXJfbWFuaWZlc3QgPC0gZHBseXI6OmJpbmRfcm93cygNCiAgICAgIHBhaXJfbWFuaWZlc3QsDQogICAgICB0aWJibGU6OnRpYmJsZSgNCiAgICAgICAgc3R1ZHlfaWQgPSBzdHVkeV9pZCwNCiAgICAgICAgc2VjdGlvbl90aXRsZSA9ICLmlK/mjIHmlL/lhZrliKXjga7miYvjgYzjgYvjgornm7jlr77mr5Tph40iLA0KICAgICAgICBmaWd1cmVfZmlsZSA9ICJwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV93ZWlnaHQucG5nIiwNCiAgICAgICAgdGFibGVfZmlsZXMgPSAidGFibGVfcGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWUudGV4Ig0KICAgICAgKQ0KICAgICkNCiAgfQ0KfQ0KDQpyZWFkcjo6d3JpdGVfY3N2KA0KICBwYWlyX21hbmlmZXN0LA0KICBmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X3Jvb3QsICJmaWd1cmVfdGFibGVfcGFpcl9tYW5pZmVzdC5jc3YiKSwNCiAgbmEgPSAiIg0KKQ0KDQpwYWlyX3RleF9saW5lcyA8LSBjKA0KICAiJSBHZW5lcmF0ZWQgYXV0b21hdGljYWxseS4gUnVuIEx1YUxhVGVYIGZyb20gdGhlIHN1cHBsZW1lbnQgZGlyZWN0b3J5LiIsDQogICJcXHByb3ZpZGVjb21tYW5ke1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdH17Ln0iLA0KICAiXFxzZWN0aW9ue+aomeacrOani+evieODu+ODh+ODvOOCv+WTgeizquODu+WIhuaekOe1kOaenH0iDQopDQoNCmZvciAoc3R1ZHlfaWQgaW4gbmFtZXMoc3R1ZHlfc3BlY3MpKSB7DQogIHN0dWR5X2xhYmVsIDwtIHN0dWR5X3NwZWNzW1tzdHVkeV9pZF1dJHN0dWR5X2xhYmVsDQogIHBhaXJfdGV4X2xpbmVzIDwtIGMoDQogICAgcGFpcl90ZXhfbGluZXMsDQogICAgcGFzdGUwKCJcXHNlY3Rpb257IiwgbGF0ZXhfZXNjYXBlKHN0dWR5X2xhYmVsKSwgIn0iKSwNCiAgICAiXFxzdWJzZWN0aW9ue+aomeacrOani+evieOBqOOCueOCr+ODquODvOODi+ODs+OCsH0iLA0KICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgc3R1ZHlfaWQsICIvdGFibGVzX3RleC90YWJsZV9zYW1wbGVfYXR0cml0aW9uLnRleH0iKSwNCiAgICBwYXN0ZTAoIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIHN0dWR5X2lkLCAiL3RhYmxlc190ZXgvdGFibGVfc2FtcGxlX2F0dHJpdGlvbl9ieV9jb25kaXRpb24udGV4fSIpLA0KICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgc3R1ZHlfaWQsICIvdGFibGVzX3RleC90YWJsZV9tYW5pcHVsYXRpb25fY2hlY2sudGV4fSIpLA0KICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgc3R1ZHlfaWQsICIvdGFibGVzX3RleC90YWJsZV9hdHRlbnRpb25fY2hlY2sudGV4fSIpLA0KICAgICJcXGNsZWFycGFnZSIsDQogICAgIlxcc3Vic2VjdGlvbnvlm57nrZTogIXlibLku5jjga7jg5Djg6njg7Pjgrl9IiwNCiAgICAiXFxiZWdpbntmaWd1cmV9W3BdIiwNCiAgICAiXFxjZW50ZXJpbmciLA0KICAgIHBhc3RlMCgNCiAgICAgICJcXGluY2x1ZGVncmFwaGljc1t3aWR0aD0wLjkyXFxsaW5ld2lkdGhde1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC8uLi9kaWFnbm9zdGljcy8iLA0KICAgICAgc3R1ZHlfaWQsDQogICAgICAiL2JhbGFuY2UvIiwNCiAgICAgIHN0dWR5X2lkLA0KICAgICAgIl9hc3NpZ25tZW50X2JhbGFuY2VfbG92ZV9wbG90LnBuZ30iDQogICAgKSwNCiAgICBwYXN0ZTAoIlxcY2FwdGlvbnsiLCBsYXRleF9lc2NhcGUoc3R1ZHlfbGFiZWwpLCAi77ya5Zue562U6ICF5Ymy5LuY44GuTG92ZSBwbG90fSIpLA0KICAgICJcXGVuZHtmaWd1cmV9IiwNCiAgICBwYXN0ZTAoIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIHN0dWR5X2lkLCAiL3RhYmxlc190ZXgvdGFibGVfYXNzaWdubWVudF9iYWxhbmNlX3BhaXJ3aXNlX3NtZC50ZXh9IiksDQogICAgIlxcYmVnaW57ZmlndXJlfVtwXSIsDQogICAgIlxcY2VudGVyaW5nIiwNCiAgICBwYXN0ZTAoDQogICAgICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvLi4vZGlhZ25vc3RpY3MvIiwNCiAgICAgIHN0dWR5X2lkLA0KICAgICAgIi9iYWxhbmNlLyIsDQogICAgICBzdHVkeV9pZCwNCiAgICAgICJfYXNzaWdubWVudF9iYWxhbmNlX2RpYWdvbmFsX3Bsb3QucG5nfSINCiAgICApLA0KICAgIHBhc3RlMCgiXFxjYXB0aW9ueyIsIGxhdGV4X2VzY2FwZShzdHVkeV9sYWJlbCksICLvvJrmnaHku7bliKXlhbHlpInph4/lubPlnYfjga40NeW6pue3muiouuaWrX0iKSwNCiAgICAiXFxlbmR7ZmlndXJlfSIsDQogICAgcGFzdGUwKCJcXGlucHV0e1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC8iLCBzdHVkeV9pZCwgIi90YWJsZXNfdGV4L3RhYmxlX2Fzc2lnbm1lbnRfYmFsYW5jZV9zdW1tYXJ5LnRleH0iKSwNCiAgICAiXFxjbGVhcnBhZ2UiLA0KICAgICJcXHN1YnNlY3Rpb25744Kz44Oz44K444On44Kk44Oz44OI5bGe5oCn5o+Q56S644Gu54Sh5L2c54K65YyW6Ki65patfSIsDQogICAgIlxcYmVnaW57ZmlndXJlfVtwXSIsDQogICAgIlxcY2VudGVyaW5nIiwNCiAgICBwYXN0ZTAoDQogICAgICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvLi4vZGlhZ25vc3RpY3MvIiwNCiAgICAgIHN0dWR5X2lkLA0KICAgICAgIi9yYW5kb21pemF0aW9uLyIsDQogICAgICBzdHVkeV9pZCwNCiAgICAgICJfcHJvZmlsZV9yYW5kb21pemF0aW9uX2RpYWdvbmFsX3Bsb3QucG5nfSINCiAgICApLA0KICAgIHBhc3RlMCgiXFxjYXB0aW9ueyIsIGxhdGV4X2VzY2FwZShzdHVkeV9sYWJlbCksICLvvJrlsZ7mgKfmsLTmupbjga7oprPmuKzmr5TnjofjgajmnJ/lvoXmr5Tnjod9IiksDQogICAgIlxcZW5ke2ZpZ3VyZX0iLA0KICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgc3R1ZHlfaWQsICIvdGFibGVzX3RleC90YWJsZV9wcm9maWxlX3JhbmRvbWl6YXRpb25fdGVzdHMudGV4fSIpLA0KICAgIHBhc3RlMCgiXFxpbnB1dHtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvIiwgc3R1ZHlfaWQsICIvdGFibGVzX3RleC90YWJsZV9wcm9maWxlX3JhbmRvbWl6YXRpb25fZnJlcXVlbmN5LnRleH0iKSwNCiAgICAiXFxjbGVhcnBhZ2UiLA0KICAgICJcXHN1YnNlY3Rpb2575o6o5a6a57WQ5p6c77ya5Zuz44Go5a++5b+c44GZ44KL6KGofSINCiAgKQ0KICANCiAgc3R1ZHlfcGFpcnMgPC0gcGFpcl9tYW5pZmVzdCAlPiUgZHBseXI6OmZpbHRlciguZGF0YSRzdHVkeV9pZCA9PSBzdHVkeV9pZCkNCiAgZm9yIChpIGluIHNlcV9sZW4obnJvdyhzdHVkeV9wYWlycykpKSB7DQogICAgcm93IDwtIHN0dWR5X3BhaXJzW2ksIF0NCiAgICBmaWd1cmVfcGF0aCA8LSBmaWxlLnBhdGgocm93JHN0dWR5X2lkLCAiZmlndXJlcyIsIHJvdyRmaWd1cmVfZmlsZSkNCiAgICB0YWJsZXMgPC0gdW5saXN0KHN0cnNwbGl0KHJvdyR0YWJsZV9maWxlcywgIjsiLCBmaXhlZCA9IFRSVUUpKQ0KICAgIHBhaXJfdGV4X2xpbmVzIDwtIGMoDQogICAgICBwYWlyX3RleF9saW5lcywNCiAgICAgIHBhc3RlMCgiXFxzdWJzdWJzZWN0aW9ueyIsIGxhdGV4X2VzY2FwZShyb3ckc2VjdGlvbl90aXRsZSksICJ9IiksDQogICAgICAiXFxiZWdpbntmaWd1cmV9W3BdIiwNCiAgICAgICJcXGNlbnRlcmluZyIsDQogICAgICBwYXN0ZTAoIlxcaW5jbHVkZWdyYXBoaWNzW3dpZHRoPTAuOTZcXGxpbmV3aWR0aF17XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIGdzdWIoIlxcXFwiLCAiLyIsIGZpZ3VyZV9wYXRoKSwgIn0iKSwNCiAgICAgIHBhc3RlMCgiXFxjYXB0aW9ueyIsIGxhdGV4X2VzY2FwZShyb3ckc2VjdGlvbl90aXRsZSksICJ9IiksDQogICAgICAiXFxlbmR7ZmlndXJlfSINCiAgICApDQogICAgZm9yICh0YWJsZV9maWxlIGluIHRhYmxlcykgew0KICAgICAgdGFibGVfcGF0aCA8LSBmaWxlLnBhdGgocm93JHN0dWR5X2lkLCAidGFibGVzX3RleCIsIHRhYmxlX2ZpbGUpDQogICAgICBpZiAoZmlsZS5leGlzdHMoZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCB0YWJsZV9wYXRoKSkpIHsNCiAgICAgICAgcGFpcl90ZXhfbGluZXMgPC0gYygNCiAgICAgICAgICBwYWlyX3RleF9saW5lcywNCiAgICAgICAgICBwYXN0ZTAoIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290LyIsIGdzdWIoIlxcXFwiLCAiLyIsIHRhYmxlX3BhdGgpLCAifSIpDQogICAgICAgICkNCiAgICAgIH0NCiAgICB9DQogICAgcGFpcl90ZXhfbGluZXMgPC0gYyhwYWlyX3RleF9saW5lcywgIlxcY2xlYXJwYWdlIikNCiAgfQ0KfQ0KDQpwYWlyX3RleF9saW5lcyA8LSBjKA0KICBwYWlyX3RleF9saW5lcywNCiAgIlxcc2VjdGlvbnsz5a6f6aiT5qiq5pat44Gu5YiG5p6QfSIsDQogICJcXHN1YnNlY3Rpb2575Li76KaB5Luu6Kqs44Gu57ea5b2i5YK+5ZCR5qSc5a6afSIsDQogICJcXGJlZ2lue2ZpZ3VyZX1bcF0iLA0KICAiXFxjZW50ZXJpbmciLA0KICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvY3Jvc3Nfc3R1ZHkvZmlndXJlcy9maWdfc3VwcF9oeXBvdGhlc2lzX2xpbmVhcl90cmVuZF90ZXN0cy5wbmd9IiwNCiAgIlxcY2FwdGlvbnsz5a6f6aiT44Gu5Li76KaB5Luu6Kqs44Gr5a++5b+c44GZ44KL57ea5b2i5YK+5ZCR5qSc5a6afSIsDQogICJcXGVuZHtmaWd1cmV9IiwNCiAgIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290L2Nyb3NzX3N0dWR5L3RhYmxlc190ZXgvdGFibGVfaHlwb3RoZXNpcy50ZXh9IiwNCiAgIlxcY2xlYXJwYWdlIiwNCiAgIlxcc3Vic2VjdGlvbnvpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbjga7nt5rlvaLlgr7lkJF9IiwNCiAgIlxcYmVnaW57ZmlndXJlfVtwXSIsDQogICJcXGNlbnRlcmluZyIsDQogICJcXGluY2x1ZGVncmFwaGljc1t3aWR0aD0wLjkyXFxsaW5ld2lkdGhde1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC9jcm9zc19zdHVkeS9maWd1cmVzL2ZpZ19zdXBwX2Nob2ljZV9zZXRfYWRqdXN0ZWRfaW1wb3J0YW5jZV9zbG9wZXMucG5nfSIsDQogICJcXGNhcHRpb257M+Wun+mok+OBrumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOBrue3muW9ouWCvuWQkX0iLA0KICAiXFxlbmR7ZmlndXJlfSIsDQogICJcXGlucHV0e1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC9jcm9zc19zdHVkeS90YWJsZXNfdGV4L3RhYmxlX2FkanVzdGVkX3Nsb3Blcy50ZXh9IiwNCiAgIlxcY2xlYXJwYWdlIiwNCiAgIlxcc3Vic2VjdGlvbnsz5a6f6aiT5qiq5pat44Gu5pS/5YWa5omL44GM44GL44KK55u45a++5q+U6YeNfSIsDQogICJcXGJlZ2lue2ZpZ3VyZX1bcF0iLA0KICAiXFxjZW50ZXJpbmciLA0KICAiXFxpbmNsdWRlZ3JhcGhpY3Nbd2lkdGg9MC45MlxcbGluZXdpZHRoXXtcXENvbmpvaW50U3VwcGxlbWVudFJvb3QvY3Jvc3Nfc3R1ZHkvZmlndXJlcy9maWdfc3VwcF9jcm9zc19zdHVkeV9yZWxhdGl2ZV9wYXJ0eV93ZWlnaHQucG5nfSIsDQogICJcXGNhcHRpb257M+Wun+mok+aoquaWreOBruaUv+WFmuaJi+OBjOOBi+OCiuebuOWvvuavlOmHjX0iLA0KICAiXFxlbmR7ZmlndXJlfSIsDQogICJcXGlucHV0e1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC9jcm9zc19zdHVkeS90YWJsZXNfdGV4L3RhYmxlX2Nyb3NzX3JlbGF0aXZlLnRleH0iLA0KICAiXFxjbGVhcnBhZ2UiDQopDQoNCmlmIChmaWxlLmV4aXN0cyhmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X2Nyb3NzLCAiZmlndXJlcyIsICJwYXJ0eV9tYXRjaF9hbGxfcGFydGllcy5wbmciKSkpIHsNCiAgcGFpcl90ZXhfbGluZXMgPC0gYygNCiAgICBwYWlyX3RleF9saW5lcywNCiAgICAiXFxzdWJzZWN0aW9ue1N0dWR5IDPvvJrjgZnjgbnjgabjga7lr77osaHmlK/mjIHmlL/lhZrjgavjgYrjgZHjgovkuIDoh7Tlirnmnpx9IiwNCiAgICAiXFxiZWdpbntmaWd1cmV9W3BdIiwNCiAgICAiXFxjZW50ZXJpbmciLA0KICAgICJcXGluY2x1ZGVncmFwaGljc1t3aWR0aD0wLjkyXFxsaW5ld2lkdGhde1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC9jcm9zc19zdHVkeS9maWd1cmVzL3BhcnR5X21hdGNoX2FsbF9wYXJ0aWVzLnBuZ30iLA0KICAgICJcXGNhcHRpb25744GZ44G544Gm44Gu5a++6LGh5pSv5oyB5pS/5YWa44Gr44GK44GR44KL5pSv5oyB5pS/5YWa5ZCN5LiA6Ie05Yq55p6cfSIsDQogICAgIlxcZW5ke2ZpZ3VyZX0iLA0KICAgICJcXGlucHV0e1xcQ29uam9pbnRTdXBwbGVtZW50Um9vdC9jcm9zc19zdHVkeS90YWJsZXNfdGV4L3RhYmxlX2FsbF9wYXJ0eV9tYXRjaF9jb2VmZmljaWVudHMudGV4fSIsDQogICAgIlxcaW5wdXR7XFxDb25qb2ludFN1cHBsZW1lbnRSb290L2Nyb3NzX3N0dWR5L3RhYmxlc190ZXgvdGFibGVfYWxsX3BhcnR5X21hdGNoX3RyZW5kcy50ZXh9IiwNCiAgICAiXFxjbGVhcnBhZ2UiDQogICkNCn0NCg0Kd3JpdGVMaW5lcygNCiAgcGFpcl90ZXhfbGluZXMsDQogIGNvbiA9IGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgImFsbF9zdHVkaWVzX2ZpZ3VyZV90YWJsZV9wYWlycy50ZXgiKSwNCiAgdXNlQnl0ZXMgPSBUUlVFDQopDQoNCnByZWFtYmxlX2xpbmVzIDwtIGMoDQogICIlIEFkZCB0aGVzZSBwYWNrYWdlcyB0byB0aGUgcHJlYW1ibGUgb2YgYXBwZW5kaXgudGV4LiIsDQogICJcXHVzZXBhY2thZ2V7Z3JhcGhpY3h9IiwNCiAgIlxcdXNlcGFja2FnZXtib29rdGFic30iLA0KICAiXFx1c2VwYWNrYWdle2xvbmd0YWJsZX0iLA0KICAiXFx1c2VwYWNrYWdle2FycmF5fSIsDQogICJcXHVzZXBhY2thZ2V7cGRmbHNjYXBlfSIsDQogICJcXHVzZXBhY2thZ2V7Y2FwdGlvbn0iLA0KICAiJSBDb21waWxlIHdpdGggTHVhTGFUZVggYmVjYXVzZSB0aGUgZ2VuZXJhdGVkIGNhcHRpb25zIGFuZCB0YWJsZXMgY29udGFpbiBKYXBhbmVzZS4iDQopDQp3cml0ZUxpbmVzKA0KICBwcmVhbWJsZV9saW5lcywNCiAgY29uID0gZmlsZS5wYXRoKGZpbmFsX2RpcnMkc3VwcGxlbWVudF9yb290LCAibGF0ZXhfcHJlYW1ibGVfc25pcHBldC50ZXgiKSwNCiAgdXNlQnl0ZXMgPSBUUlVFDQopDQoNCnN0YW5kYWxvbmVfbGluZXMgPC0gYygNCiAgIiUgIVRlWCBwcm9ncmFtID0gbHVhbGF0ZXgiLA0KICAiXFxkb2N1bWVudGNsYXNzW2E0cGFwZXIsMTFwdF17bHRqc2FydGljbGV9IiwNCiAgIlxcdXNlcGFja2FnZVttYXJnaW49MjJtbV17Z2VvbWV0cnl9IiwNCiAgIlxcdXNlcGFja2FnZXtncmFwaGljeH0iLA0KICAiXFx1c2VwYWNrYWdle2Jvb2t0YWJzfSIsDQogICJcXHVzZXBhY2thZ2V7bG9uZ3RhYmxlfSIsDQogICJcXHVzZXBhY2thZ2V7YXJyYXl9IiwNCiAgIlxcdXNlcGFja2FnZXtwZGZsc2NhcGV9IiwNCiAgIlxcdXNlcGFja2FnZXtjYXB0aW9ufSIsDQogICJcXGJlZ2lue2RvY3VtZW50fSIsDQogICJcXHRhYmxlb2Zjb250ZW50cyIsDQogICJcXGNsZWFycGFnZSIsDQogICJcXGlucHV0e2FsbF9zdHVkaWVzX2ZpZ3VyZV90YWJsZV9wYWlycy50ZXh9IiwNCiAgIlxcZW5ke2RvY3VtZW50fSINCikNCndyaXRlTGluZXMoDQogIHN0YW5kYWxvbmVfbGluZXMsDQogIGNvbiA9IGZpbGUucGF0aChmaW5hbF9kaXJzJHN1cHBsZW1lbnRfcm9vdCwgInN1cHBsZW1lbnRfdGFibGVzX2ZpZ3VyZXNfbWFzdGVyLnRleCIpLA0KICB1c2VCeXRlcyA9IFRSVUUNCikNCg0KbGF5b3V0X2xpbmVzIDwtIGMoDQogICJPVVRQVVQgRElSRUNUT1JZIFNUUlVDVFVSRSIsDQogICI9PT09PT09PT09PT09PT09PT09PT09PT09PSIsDQogICJtYWluX3RleHQvZmlndXJlcyAgICAgIDogbWFudXNjcmlwdCBmaWd1cmVzIiwNCiAgIm1haW5fdGV4dC90YWJsZXMgICAgICAgOiBMYVRlWCB0YWJsZXMgY29ycmVzcG9uZGluZyB0byBtYW51c2NyaXB0IGZpZ3VyZXMiLA0KICAic3VwcGxlbWVudC9zdHVkeTEtMyAgICA6IHBlci1zdHVkeSBmaWd1cmVzLCBDU1YgdGFibGVzLCBhbmQgTGFUZVggdGFibGVzIiwNCiAgInN1cHBsZW1lbnQvY3Jvc3Nfc3R1ZHkgOiBjcm9zcy1zdHVkeSBmaWd1cmVzIGFuZCB0YWJsZXMiLA0KICAiZGlhZ25vc3RpY3Mvc3R1ZHkxLTMgICA6IHJlc3BvbmRlbnQgc2NyZWVuaW5nLCBiYWxhbmNlLCBhbmQgcmFuZG9taXphdGlvbiBkaWFnbm9zdGljcyIsDQogICJtb2RlbF9vYmplY3RzICAgICAgICAgIDogUkRTIG1vZGVsIGFuZCBhbmFseXNpcyBvYmplY3RzIiwNCiAgImxvZ3MgICAgICAgICAgICAgICAgICAgOiB0ZXh0IG1vZGVsIHN1bW1hcmllcyBhbmQgc2Vzc2lvbiBpbmZvcm1hdGlvbiIsDQogICJfd29ya2luZyAgICAgICAgICAgICAgIDogb3JpZ2luYWwgaW50ZXJtZWRpYXRlIG91dHB1dHMgcHJvZHVjZWQgYnkgZWFjaCBhbmFseXNpcyBtb2R1bGUiLA0KICAiIiwNCiAgIkxBVEVYIiwNCiAgIi0tLS0tIiwNCiAgIkFkZCB0aGUgcGFja2FnZXMgaW4gc3VwcGxlbWVudC9sYXRleF9wcmVhbWJsZV9zbmlwcGV0LnRleCB0byBhcHBlbmRpeC50ZXguIiwNCiAgIlRoZW4gaW5wdXQgc3VwcGxlbWVudC9hbGxfc3R1ZGllc19maWd1cmVfdGFibGVfcGFpcnMudGV4LCBvciBjb21waWxlIiwNCiAgInN1cHBsZW1lbnQvc3VwcGxlbWVudF90YWJsZXNfZmlndXJlc19tYXN0ZXIudGV4IHdpdGggTHVhTGFUZVguIg0KKQ0Kd3JpdGVMaW5lcygNCiAgbGF5b3V0X2xpbmVzLA0KICBjb24gPSBmaWxlLnBhdGgoZmluYWxfb3V0cHV0X3Jvb3QsICJPVVRQVVRfU1RSVUNUVVJFX0FORF9MQVRFWF9SRUFETUUudHh0IiksDQogIHVzZUJ5dGVzID0gVFJVRQ0KKQ0KDQpzYXZlUkRTKA0KICBsaXN0KA0KICAgIHNjcmVlbmluZyA9IHNjcmVlbmluZ19yZXN1bHRzLA0KICAgIHBhaXJfbWFuaWZlc3QgPSBwYWlyX21hbmlmZXN0LA0KICAgIGZpbmFsX2RpcnMgPSBmaW5hbF9kaXJzDQogICksDQogIGZpbGUgPSBmaWxlLnBhdGgoZmluYWxfZGlycyRtb2RlbF9vYmplY3RzX3Jvb3QsICJzY3JlZW5pbmdfYW5kX2xhdGV4X2V4cG9ydF9vYmplY3RzLnJkcyIpDQopDQoNCmNhdCgNCiAgIlxuU2NyZWVuZWQtc2FtcGxlIGF1ZGl0LCBMYVRlWCB0YWJsZXMsIGZpZ3VyZS10YWJsZSBwYWlycywgYW5kIGZpbmFsIG91dHB1dCBvcmdhbml6YXRpb24gY29tcGxldGVkLlxuIiwNCiAgIkZpbmFsIG91dHB1dCByb290OiAiLCBub3JtYWxpemVQYXRoKGZpbmFsX291dHB1dF9yb290KSwgIlxuIiwNCiAgIkxhVGVYIG1hc3RlcjogIiwNCiAgbm9ybWFsaXplUGF0aChmaWxlLnBhdGgoZmluYWxfZGlycyRzdXBwbGVtZW50X3Jvb3QsICJzdXBwbGVtZW50X3RhYmxlc19maWd1cmVzX21hc3Rlci50ZXgiKSksDQogICJcbiIsDQogIHNlcCA9ICIiDQopDQpgYGANCg0KIyBCLiDmjqjlrprmlrnms5XjgajliIbmnpDmqJnmnKzjga7lrprnvqkNCg0KIyMgQi4xIOWIhuaekOaomeacrA0KDQrlkITlm57nrZTogIXjga8y44CBM+OAgTTjgIE144Gu44GE44Ga44KM44GL44Gu6YG45oqe6IKi5pWw5p2h5Lu244Gr5Ymy44KK5b2T44Gm44KJ44KM44CBNeOBpOOBrumBuOaKnuiqsumhjOOBq+WbnuetlOOBl+OBn+OAguW+k+WxnuWkieaVsOOBr+OAgeWQhOiqsumhjOOBq+aPkOekuuOBleOCjOOBn+ODl+ODreODleOCo+ODvOODq+OBjOmBuOaKnuOBleOCjOOBn+WgtOWQiOOBqzHjgIHpgbjmip7jgZXjgozjgarjgYvjgaPjgZ/loLTlkIjjgasw44KS44Go44KL5LqM5YCk5aSJ5pWw44Gn44GC44KL44CCDQoNCuWun+mokzHjgafjga/jgIHliJ3lm57lkIzmhI/jgIHmnIDntYLpgIHkv6HlkIzmhI/jgIHjgYrjgojjgbPlibLjgorlvZPjgabjgonjgozjgZ/mnaHku7bjgavjgYrjgZHjgos16Kqy6aGM44Gu5pyJ5Yq55Zue562U44KS5rqA44Gf44GZ5Zue562U6ICF44KS5YiG5p6Q5a++6LGh44Go44GX44Gf44CC5a6f6aiTMuODuzPjgafjga/jgIHjgZPjgozjgonjgavliqDjgYjjgabjgIHjgqTjg4fjgqrjg63jgq7jg7zooYzliJfkuK3jga7mjIfnpLrpoIXnm67jgajpgbjmip7ogqLmlbDjga7mk43kvZznorroqo3os6rllY/jgavmraPnrZTjgZfjgZ/lm57nrZTogIXjgavpmZDlrprjgZfjgZ/jgIINCg0KIyMgQi4yIEFNQ0UNCg0K5Zue562U6ICF44KSICRpJOOAgemBuOaKnuiqsumhjOOCkiAkdCTjgIHjg5fjg63jg5XjgqPjg7zjg6vjgpIgJGok44CB6YG45oqe6IKi5pWw5p2h5Lu244KSICRrXGluXHsyLDMsNCw1XH0kIOOBqOOBmeOCi+OAguW+k+WxnuWkieaVsOOCkg0KDQokJA0KWV97aXRqfQ0KPQ0KXG1hdGhiZnsxfVx7XHRleHR744OX44Ot44OV44Kj44O844OrIH1qXHRleHR7IOOBjOmBuOaKnuOBleOCjOOBn31cfQ0KJCQNCg0K44Go5a6a576p44GZ44KL44CC5ZCE6YG45oqe6IKi5pWw5p2h5Lu244Gr44Gk44GE44Gm44CB57ea5b2i56K6546H44Oi44OH44Or44KS5Yil44CF44Gr5o6o5a6a44GZ44KL44CCDQoNCiQkDQpZX3tpdGp9DQo9DQpcYWxwaGFeeyhrKX0NCisNClxzdW1fe2F9DQpcc3VtX3tcZWxsXG5lcSBcZWxsX3thMH19DQpcYmV0YV97YVxlbGx9Xnsoayl9RF97aXRqLGFcZWxsfQ0KKw0KXGJvbGRzeW1ib2x7XGdhbW1hfV57KGspXHByaW1lfVxib2xkc3ltYm9se1p9X3tpfQ0KKw0KXHZhcmVwc2lsb25fe2l0an1eeyhrKX0uDQokJA0KDQokXGJldGFfe2FcZWxsfV57KGspfSQg44Gv44CBJGskIOmBuOaKnuiCouadoeS7tuOBq+OBiuOBhOOBpuOAgeWxnuaApyAkYSQg44KS5Z+65rqW5rC05rqWICRcZWxsX3thMH0kIOOBi+OCieawtOa6liAkXGVsbCQg44Gr5aSJ5pu044GX44Gf44Go44GN44Gu5bmz5Z2H6ZmQ55WM6KaB57Sg5Yq55p6c77yIQU1DRe+8ieOBp+OBguOCi+OAguaomea6luiqpOW3ruOBr+WbnuetlOiAheWNmOS9jeOBp+OCr+ODqeOCueOCv+WMluOBl+OBn+OAgg0KDQrlrp/pqJMx44O7MuOBp+OBr+OAgeaUv+etluS9jee9ruOBruWfuua6luOCkuS4remBk+OAgeS4jumHjuWFmuWcsOS9jeOBruWfuua6luOCkumHjuWFmuOAgeitsOW4reaVsOOBruWfuua6luOCkjEw5Lul5LiL44Go44GX44CBR0RQ5oiQ6ZW3546H44CB5pel57WM5bmz5Z2H5qCq5L6h44CBQ1BJ44CB5aSx5qWt546H44Gv44GE44Ga44KM44KC5aSJ5YyW44Gq44GX44KS5Z+65rqW44Go44GX44Gf44CC5a6f6aiTM+OBp+OBr+aUv+WFmuWQjeOBruWfuua6luOCkuiHqueUseawkeS4u+WFmuOBqOOBl+OBn+OAgg0KDQoNCiMjIEIuMyDpmZDnlYzlubPlnYfjgajlsZ7mgKfph43opoHluqYNCg0KJGskIOmBuOaKnuiCouadoeS7tuOBq+OBiuOBkeOCi+WxnuaApyAkYSQg44Gu5rC05rqWICRcZWxsJCDjga7pmZDnlYzlubPlnYfjgpLjgIENCg0KJCQNClx3aWRlaGF0e1xtdX1fe2FcZWxsfV57KGspfQ0KPQ0KXGZyYWN7DQpcc3VtX3tpLHQsan0NClxtYXRoYmZ7MX1ce1hfe2l0aixhfT1cZWxsXH1ZX3tpdGp9DQp9ew0KXHN1bV97aSx0LGp9DQpcbWF0aGJmezF9XHtYX3tpdGosYX09XGVsbFx9DQp9DQokJA0KDQrjgajjgZnjgovjgIINCg0K5bGe5oCnICRhJCDjgYwgJExfYSQg5YCL44Gu5rC05rqW44KS44KC44Gk44Go44GN44CB5bGe5oCn6YeN6KaB5bqm44KS5YWo5rC05rqW44Oa44Ki44Gu6ZmQ55WM5bmz5Z2H5beu44Gu57W25a++5YCk44Gu5bmz5Z2H44Go44GX44Gm44CBDQoNCiQkDQpcd2lkZWhhdHtJfV97YX1eeyhrKX0NCj0NClxiaW5vbXtMX2F9ezJ9XnstMX0NClxzdW1fe1xlbGw8XGVsbCd9DQpcbGVmdHwNClx3aWRlaGF0e1xtdX1fe2FcZWxsfV57KGspfQ0KLQ0KXHdpZGVoYXR7XG11fV97YVxlbGwnfV57KGspfQ0KXHJpZ2h0fA0KJCQNCg0K44Go5a6a576p44GX44Gf44CCDQoNCuWun+mokzHjg7sy44Gu5pS/5YWa5omL44GM44GL44KK44Gu6YeN6KaB5bqm44Gv44CB5pS/562W5L2N572u44CB5LiO6YeO5YWa5Zyw5L2N44CB6K2w5bit5pWw44GuM+WxnuaAp+OBrumHjeimgeW6puOCkuetieOBl+OBhOWKoOmHjeOBp+W5s+Wdh+OBl+OBn+OAguWun+mokzPjgafjga/mlL/lhZrlkI3lsZ7mgKfjga7ph43opoHluqbjgpLmlL/lhZrmiYvjgYzjgYvjgorjga7ph43opoHluqbjgajjgZfjgZ/jgILntYzmuIjmiYvjgYzjgYvjgorjga/jgIEz5a6f6aiT44Go44KCR0RQ5oiQ6ZW3546H44CB5pel57WM5bmz5Z2H5qCq5L6h44CBQ1BJ44CB5aSx5qWt546H44GuNOWxnuaAp+OBrumHjeimgeW6puOCkuetieOBl+OBhOWKoOmHjeOBp+W5s+Wdh+OBl+OBn+OAgg0KDQojIyBCLjQg6YG45oqe6IKi5pWw6Kq/5pW05riI44G/6YeN6KaB5bqm44Go55u45a++5q+U6YeNDQoNCiRrJCDlgIvjga7jg5fjg63jg5XjgqPjg7zjg6vjgYvjgonlv4XjgZox44Gk44KS6YG45oqe44GZ44KL44Gf44KB44CB44OX44Ot44OV44Kj44O844OrMeS7tuOBguOBn+OCiuOBruW5s+Wdh+mBuOaKnueiuueOh+OBryAkMS9rJCDjgajjgarjgovjgILmnaHku7bplpPmr5TovIPjga7jgZ/jgoHjgIHlsZ7mgKcgJGEkIOOBrumBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOCkuOAgQ0KDQokJA0KXHdpZGVoYXR7SX1fe2F9XntcbWF0aHJte2Fkan0sKGspfQ0KPQ0KXGZyYWN7XHdpZGVoYXR7SX1fe2F9Xnsoayl9fXsxL2t9DQo9DQprXHdpZGVoYXR7SX1fe2F9Xnsoayl9DQokJA0KDQrjgajjgZfjgZ/jgIINCg0K5pS/5YWa5omL44GM44GL44KK44Gu6YeN6KaB5bqm44KSICRcd2lkZWhhdHtQfV57KGspfSTjgIHntYzmuIjmiYvjgYzjgYvjgorjga7ph43opoHluqbjgpIgJFx3aWRlaGF0e0V9Xnsoayl9JCDjgajjgZnjgovjgajjgIHmlL/lhZrmiYvjgYzjgYvjgorjga7nm7jlr77mr5Tph43jga/jgIENCg0KJCQNClx3aWRlaGF0e1d9Xnsoayl9DQo9DQpcZnJhY3tcd2lkZWhhdHtQfV57KGspfX0NCntcd2lkZWhhdHtQfV57KGspfStcd2lkZWhhdHtFfV57KGspfX0NCiQkDQoNCuOBp+OBguOCi+OAguaUv+WFmuODu+e1jOa4iOOBruS4oemHjeimgeW6puOBq+WQjOOBmCAkayQg44KS5LmX44GY44Gm44KC55u45a++5q+U6YeN44Gv5aSJ5YyW44GX44Gq44GE44CCDQoNCiMjIEIuNSDjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5fjgajnt5rlvaLjg4jjg6zjg7Pjg4kNCg0K6YeN6KaB5bqm44Go55u45a++5q+U6YeN44GuOTUl5L+h6aC85Yy66ZaT44Gv44CB5ZCE6YG45oqe6IKi5pWw5p2h5Lu25YaF44Gn5Zue562U6ICF44KS5Y2Y5L2N44Go44GX44Gm5b6p5YWD5oq95Ye644GX44CB5ZCE5Zue562U6ICF44GuNeiqsumhjOODu+WFqOODl+ODreODleOCo+ODvOODq+OBq+asoOaQjeOBruOBquOBhOWbnuetlOiAheOCr+ODqeOCueOCv+ODvOODu+ODluODvOODiOOCueODiOODqeODg+ODl+OBi+OCieeul+WHuuOBl+OBn+OAguS4u+imgeWIhuaekOOBp+OBrzIsMDAw5Zue5Y+N5b6p44GV44Gb44Gf44CCDQoNCuWQhOaMh+aomSAkUV57KGspfSQg44Gu6YG45oqe6IKi5pWw44Gr5a++44GZ44KL57ea5b2i5YK+5ZCR44Gv44CBDQoNCiQkDQpRXnsoayl9PVxldGErXGRlbHRhIGsrdV57KGspfQ0KJCQNCg0K44Go44GX44GmNOadoeS7tuOBrueCueaOqOWumuWApOOBq09MU+OCkuW9k+OBpuOBr+OCgeOAgeWCvuOBjSAkXGRlbHRhJCDjgpLmsYLjgoHjgZ/jgILlkITjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5flj43lvqnjgafjgoLlkIzjgZjlgr7jgY3jgpLlho3mjqjlrprjgZfjgIE5NSXkv6HpoLzljLrplpPjgajkuKHlgbTjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5cgJHAkIOWApOOCkueul+WHuuOBl+OBn+OAgkgxYeOAgUgxYuOAgUgyYeOAgUgyYuOBruW9ouW8j+eahOOBquWIpOWumuOBq+OBr+acquiqv+aVtOmHjeimgeW6puOBrue3muW9ouODiOODrOODs+ODieOCkueUqOOBhOOAgemBuOaKnuiCouaVsOiqv+aVtOa4iOOBv+mHjeimgeW6puOBrue3muW9ouODiOODrOODs+ODieOBr+adoeS7tumWk+avlOi8g+OBruaEn+W6puWIhuaekOOBqOOBl+OBpuS9teeUqOOBl+OBn+OAgg0KDQojIyBCLjYg5p2h5Lu25LuY44GN44Ot44K444OD44OIDQoNCuW8t+WItumBuOaKnuiqsumhjOOBruani+mAoOOCkuiAg+aFruOBmeOCi+mgkeWBpeaAp+WIhuaekOOBqOOBl+OBpuOAgeWQhOmBuOaKnuiCouaVsOadoeS7tuOBq+OBpOOBhOOBpuadoeS7tuS7mOOBjeODreOCuOODg+ODiOOCkuaOqOWumuOBl+OBn+OAgg0KDQokJA0KXFByKFlfe2l0an09MVxtaWQgXG1hdGhjYWx7Q31fe2l0fSkNCj0NClxmcmFje1xleHAoXGJvbGRzeW1ib2x7WH1fe2l0an1ee1xwcmltZX1cYm9sZHN5bWJvbHtcYmV0YX1eeyhrKX0pfQ0Ke1xzdW1fe3JcaW5cbWF0aGNhbHtDfV97aXR9fVxleHAoXGJvbGRzeW1ib2x7WH1fe2l0cn1ee1xwcmltZX1cYm9sZHN5bWJvbHtcYmV0YX1eeyhrKX0pfS4NCiQkDQoNCuOBk+OBk+OBp+OAgSRyJCDjga/lkIzkuIDpgbjmip7oqrLpoYzlhoXjga7jg5fjg63jg5XjgqPjg7zjg6vjgpLotbDjgovmt7vlrZfjgafjgYLjgorjgIEkayQg44Gv6YG45oqe6IKi5pWw5p2h5Lu244KS6KGo44GZ44CC6Kqy6aGM44KS5bGk77yIc3RyYXR1be+8ieOBqOOBl+OAgeWbnuetlOiAheWNmOS9jeOBp+OCr+ODqeOCueOCv+WMluOBl+OBn+OAguWbnuetlOiAheODrOODmeODq+WFseWkiemHj+OBr+WQjOS4gOmBuOaKnuiqsumhjOWGheOBp+S4gOWumuOBp+OBguOCi+OBn+OCgeOAgeadoeS7tuS7mOOBjeODreOCuOODg+ODiOOBq+OBr+ODl+ODreODleOCo+ODvOODq+WxnuaAp+OBruOBv+OCkuaKleWFpeOBl+OBn+OAgg0KDQojIyBCLjcg5pSv5oyB5pS/5YWa5ZCN44Go44Gu5LiA6Ie05Yq55p6cDQoNCuWun+mokzPjgafjga/jgIENCg0KJCQNCk1fe2l0an0NCj0NClxtYXRoYmZ7MX1ce1x0ZXh0e+aPkOekuuaUv+WFmuWQjX1fe2l0an09XHRleHR75pSv5oyB5pS/5YWafV97aX1cfQ0KJCQNCg0K44KS5L2c5oiQ44GX44Gf44CC5YWo5L2T44Oi44OH44Or44Gn44Gv44CB5pSv5oyB5pS/5YWa5ZCN5LiA6Ie044CB5o+Q56S65pS/5YWa5ZCN44CBNOOBpOOBrue1jOa4iOWxnuaAp+OCkuaKleWFpeOBl+OAgemBuOaKnuiCouaVsOadoeS7tuOBlOOBqOOBq+aOqOWumuOBl+OBn+OAguOBquOBiuOAgeaUr+aMgeaUv+WFmuWIpeOBruWIhuaekOOBp+OBr+OAgeaUv+WFmuWQjeOBqOS4gOiHtOaMh+aomeOBjOWujOWFqOOBq+WvvuW/nOOBl+OBpuOBl+OBvuOBhuOBn+OCgeOAgeaUv+WFmuWQjeS4u+WKueaenOOCkumZpOOBjeOAgeS4gOiHtOaMh+aomeOBqOe1jOa4iOWxnuaAp+OCkueUqOOBhOOBn+OAgg0KDQojIyBCLjgg44OQ44Op44Oz44K544Go54Sh5L2c54K65YyW6Ki65patDQoNCuWbnuetlOiAheWJsuS7mOOBruODkOODqeODs+OCueOBr+OAgTLjgIEz44CBNOOAgTXmnaHku7bjga7lhajmnaHku7bjg5rjgqLjgavjgaTjgYTjgabmqJnmupbljJblubPlnYflt67jgpLnrpflh7rjgZfjgZ/jgILnlKjjgYTjgZ/lm57nrZTogIXlsZ7mgKfjga/jgIHlkITlrp/pqJPjgafliKnnlKjlj6/og73jgarmgKfliKXjgIHlubTpvaLjgIE05bm05Yi25aSn5a2m5Lul5LiK44CB5a++5pWw5LiW5biv5bm05Y+O44CB6Ieq5bex44Kk44OH44Kq44Ot44Ku44O844CB44GK44KI44Gz44Gd44KM44KJ44Gu5qyg5pCN5oyH5qiZ44Go5pSv5oyB5pS/5YWa44Gn44GC44KL44CC5Zyw5Z+f44O76YO96YGT5bqc55yM44Gv44GT44Gu5Ymy5LuY44OQ44Op44Oz44K56Ki65pat44Gr44Gv55So44GE44Gm44GE44Gq44GE44CCTG92ZSBwbG90IOOBr+WFqDbmnaHku7bjg5rjgqLjga7ntbblr75TTUTjgpLnpLrjgZfjgIHlr77op5Lnt5rlm7Pjga/lkIzjgZjlm57nrZTogIXlhbHlpInph4/jgavjgaTjgYTjgablkITmnaHku7blubPlnYfjgpLmqJnmupbljJbjgZfjgIHkuozmnaHku7bjgZrjgaQ0NeW6pue3muOBqOavlOi8g+OBmeOCi+ijnOWKqeeahOOBquWPr+imluWMluOBp+OBguOCi+OAgg0KDQokJA0KXG1hdGhybXtTTUR9X3thYn0NCj0NClxmcmFje1xvdmVybGluZXt4fV9hLVxvdmVybGluZXt4fV9ifQ0Ke1xzcXJ0eyhzX2FeMitzX2JeMikvMn19Lg0KJCQNCg0K44OX44Ot44OV44Kj44O844Or5bGe5oCn44Gu5o+Q56S644Gr44Gk44GE44Gm44Gv44CB6YG45oqe6IKi5pWw5p2h5Lu2w5flsZ7mgKfDl+awtOa6luOBlOOBqOOBq+ims+a4rOavlOeOh+OCkuaxguOCgeOAgeawtOa6luaVsOOCkiAkTF9hJCDjgajjgZfjgZ/oqK3oqIjkuIrjga7mnJ/lvoXmr5TnjocgJDEvTF9hJCDjgajmr5TovIPjgZfjgZ/jgILlsZ7mgKfDl+adoeS7tuOBlOOBqOOBq+S4gOanmOWIhuW4g+OCkuW4sOeEoeS7ruiqrOOBqOOBmeOCi+OCq+OCpOS6jOS5l+aknOWumuOCkuihjOOBhOOAgUhvbG3ms5Xjgavjgojjgovoo5zmraPlgKTjgoLloLHlkYrjgZfjgZ/jgIINCg0KDQpgYGB7ciBkaXNwbGF5LWhlbHBlcnMsIGluY2x1ZGU9RkFMU0V9DQrlsZ7mgKfml6XmnKzoqp4gPC0gZnVuY3Rpb24oeCkgew0KICBkcGx5cjo6Y2FzZV93aGVuKA0KICAgIHggPT0gInBvbGljeV9wb3NpdGlvbiIgfiAi5pS/562W5L2N572uIiwNCiAgICB4ID09ICJnb3Zlcm5tZW50X3N0YXR1cyIgfiAi5LiO6YeO5YWa5Zyw5L2NIiwNCiAgICB4ID09ICJzZWF0cyIgfiAi6KGG6K2w6Zmi6K2w5bit5pWwIiwNCiAgICB4ID09ICJnZHBfZ3Jvd3RoIiB+ICJHRFDmiJDplbfnjociLA0KICAgIHggPT0gIm5pa2tlaSIgfiAi5pel57WM5bmz5Z2H5qCq5L6hIiwNCiAgICB4ID09ICJjcGkiIH4gIua2iOiyu+iAheeJqeS+oeaMh+aVsO+8iENQSe+8iSIsDQogICAgeCA9PSAidW5lbXBsb3ltZW50IiB+ICLlpLHmpa3njociLA0KICAgIHggPT0gInBhcnR5X25hbWUiIH4gIuaUv+WFmuWQjSIsDQogICAgVFJVRSB+IGFzLmNoYXJhY3Rlcih4KQ0KICApDQp9DQoNCuadoeS7tuaXpeacrOiqniA8LSBmdW5jdGlvbih4LCBzdHVkeV9pZCkgew0KICBzdWZmaXggPC0gaWYgKHN0dWR5X2lkID09ICJzdHVkeTMiKSAi6YG45oqe6IKi5p2h5Lu2IiBlbHNlICLmlL/lhZrmnaHku7YiDQogIHhfY2hyIDwtIGFzLmNoYXJhY3Rlcih4KQ0KICBkcGx5cjo6aWZfZWxzZSgNCiAgICB4X2NociAlaW4lIGFzLmNoYXJhY3RlcigyOjUpLA0KICAgIHBhc3RlMCh4X2Nociwgc3VmZml4KSwNCiAgICB4X2Nocg0KICApDQp9DQoNCue1seioiOmHj+aXpeacrOiqniA8LSBmdW5jdGlvbih4LCBzdHVkeV9pZCkgew0KICBwYXJ0eV9uYW1lIDwtIGlmIChzdHVkeV9pZCA9PSAic3R1ZHkzIikgIuaUv+WFmuWQjemHjeimgeW6piIgZWxzZSAi5pS/5YWa6YeN6KaB5bqmIg0KICBkcGx5cjo6Y2FzZV93aGVuKA0KICAgIHggPT0gInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2UiIH4gcGFydHlfbmFtZSwNCiAgICB4ID09ICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlIiB+ICLntYzmuIjph43opoHluqYiLA0KICAgIHggPT0gInBhcnR5X2ltcG9ydGFuY2VfcGFpcndpc2VfYWRqdXN0ZWQiIH4gcGFzdGUwKHBhcnR5X25hbWUsICLvvIjpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/vvIkiKSwNCiAgICB4ID09ICJlY29ub21pY19pbXBvcnRhbmNlX3BhaXJ3aXNlX2FkanVzdGVkIiB+ICLntYzmuIjph43opoHluqbvvIjpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/vvIkiLA0KICAgIHggPT0gInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIgfiAi5pS/5YWa5omL44GM44GL44KK55u45a++5q+U6YeNIiwNCiAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKHgpDQogICkNCn0NCg0K5pWw5YCk5YiXIDwtIGZ1bmN0aW9uKHgpIHsNCiAgc3VwcHJlc3NXYXJuaW5ncyhyZWFkcjo6cGFyc2VfbnVtYmVyKGFzLmNoYXJhY3Rlcih4KSkpDQp9DQoNCuWIl+WQjeaXpeacrOiqniA8LSBmdW5jdGlvbih4KSB7DQogIOWvvuW/nCA8LSBjKA0KICAgIHZhcmlhYmxlID0gIuWkieaVsCIsDQogICAgbGFiZWwgPSAi5rC05rqW44O76KGo56S65ZCNIiwNCiAgICBwYXJ0eV9uID0gIuadoeS7tiIsDQogICAgcGFydHlfbl9sYWJlbCA9ICLmnaHku7YiLA0KICAgIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLA0KICAgIGxldmVsID0gIuawtOa6liIsDQogICAgdGVybSA9ICLjg6Ljg4fjg6vpoIUiLA0KICAgIGVzdGltYXRlID0gIuaOqOWumuWApCIsDQogICAgYHN0ZC5lcnJvcmAgPSAi5qiZ5rqW6Kqk5beuIiwNCiAgICBzdGF0aXN0aWMgPSAi5oyH5qiZIiwNCiAgICBgcC52YWx1ZWAgPSAicOWApCIsDQogICAgYGNvbmYubG93YCA9ICI5NSVDSeS4i+mZkCIsDQogICAgYGNvbmYuaGlnaGAgPSAiOTUlQ0nkuIrpmZAiLA0KICAgIGVzdGltYXRlX3BwID0gIuaOqOWumuWApO+8iHBw77yJIiwNCiAgICBjb25mLmxvd19wcCA9ICI5NSVDSeS4i+mZkO+8iHBw77yJIiwNCiAgICBjb25mLmhpZ2hfcHAgPSAiOTUlQ0nkuIrpmZDvvIhwcO+8iSIsDQogICAgbl9pZHMgPSAi5Zue562U6ICF5pWwIiwNCiAgICBzdGF0dXMgPSAi5o6o5a6a54q25oWLIiwNCiAgICBvcmRlciA9ICLooajnpLrpoIYiLA0KICAgIHBhcnR5X3N1cHBvcnRfaCA9ICLmlK/mjIHmlL/lhZoiLA0KICAgIHN1cHBvcnRfcGFydHlfdmFsaWQgPSAi5pSv5oyB5pS/5YWaIiwNCiAgICBzdHVkeV9pZCA9ICLlrp/pqJNJRCIsDQogICAgc3R1ZHlfbGFiZWwgPSAi5a6f6aiTIiwNCiAgICBzdHVkeSA9ICLlrp/pqJMiLA0KICAgIGNvbXBhcmlzb24gPSAi5q+U6LyDIiwNCiAgICBjb25kaXRpb25fYSA9ICLmnaHku7ZBIiwNCiAgICBjb25kaXRpb25fYiA9ICLmnaHku7ZCIiwNCiAgICBtZWFuX2EgPSAi5p2h5Lu2QeW5s+WdhyIsDQogICAgbWVhbl9iID0gIuadoeS7tkLlubPlnYciLA0KICAgIHNkX2EgPSAi5p2h5Lu2Qeaomea6luWBj+W3riIsDQogICAgc2RfYiA9ICLmnaHku7ZC5qiZ5rqW5YGP5beuIiwNCiAgICBuX2EgPSAi5p2h5Lu2QeWbnuetlOiAheaVsCIsDQogICAgbl9iID0gIuadoeS7tkLlm57nrZTogIXmlbAiLA0KICAgIHBvb2xlZF9zZCA9ICLjg5fjg7zjg6vmqJnmupblgY/lt64iLA0KICAgIHNtZCA9ICJTTUQiLA0KICAgIGFic19zbWQgPSAifFNNRHwiLA0KICAgIG1heF9hYnNfc21kID0gIuacgOWkp3xTTUR8IiwNCiAgICBtZWFuX2Fic19zbWQgPSAi5bmz5Z2HfFNNRHwiLA0KICAgIGNoaV9zcXVhcmUgPSAi44Kr44Kk5LqM5LmX5YCkIiwNCiAgICBkZiA9ICLoh6rnlLHluqYiLA0KICAgIHBfdmFsdWUgPSAicOWApCIsDQogICAgcF9ob2xtID0gIkhvbG3oo5zmraNw5YCkIiwNCiAgICBvYnNlcnZlZF9uID0gIuims+a4rOaVsCIsDQogICAgdG90YWxfbiA9ICLnt4/mlbAiLA0KICAgIG5fbGV2ZWxzID0gIuawtOa6luaVsCIsDQogICAgb2JzZXJ2ZWRfc2hhcmUgPSAi6Kaz5ris5q+U546HIiwNCiAgICBleHBlY3RlZF9zaGFyZSA9ICLmnJ/lvoXmr5TnjociLA0KICAgIGRldmlhdGlvbiA9ICLoprPmuKzvvI3mnJ/lvoUiLA0KICAgIGFic19kZXZpYXRpb24gPSAi57W25a++5beuIiwNCiAgICBtYXhfYWJzX3NoYXJlX2RldmlhdGlvbiA9ICLmnIDlpKfntbblr77mr5Tnjoflt64iLA0KICAgIGh5cG90aGVzaXMgPSAi5Luu6KqsIiwNCiAgICBleHBlY3RlZF9kaXJlY3Rpb24gPSAi5LqI5ris5pa55ZCRIiwNCiAgICBjb25jbHVzaW9uID0gIuWIpOWumiIsDQogICAgcF92YWx1ZV90d29fc2lkZWQgPSAi5Lih5YG0cOWApCIsDQogICAgY3VlX2ZhbWlseSA9ICLmiYvjgYzjgYvjgornvqQiLA0KICAgIHN0YXRpc3RpY19sYWJlbCA9ICLmjIfmqJkiLA0KICAgIGFuYWx5c2lzX3JvbGUgPSAi5YiG5p6Q5LiK44Gu5L2N572u44Gl44GRIiwNCiAgICBtZXRyaWNfc2NhbGUgPSAi5bC65bqmIiwNCiAgICBlc3RpbWF0ZV9iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9ICLlgr7jgY3vvIgl77yJIiwNCiAgICBjb25mX2xvd19iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9ICI5NSVDSeS4i+mZkO+8iCXvvIkiLA0KICAgIGNvbmZfaGlnaF9iYXNlbGluZV9wY3RfcGVyX29wdGlvbiA9ICI5NSVDSeS4iumZkO+8iCXvvIkiLA0KICAgIGVzdGltYXRlX3BwX3Blcl9vcHRpb24gPSAi5YK+44GN77yIcHDvvIkiLA0KICAgIGNvbmZfbG93X3BwX3Blcl9vcHRpb24gPSAiOTUlQ0nkuIvpmZDvvIhwcO+8iSIsDQogICAgY29uZl9oaWdoX3BwX3Blcl9vcHRpb24gPSAiOTUlQ0nkuIrpmZDvvIhwcO+8iSIsDQogICAgZXN0aW1hdGVfcGN0ID0gIuaOqOWumuWApO+8iCXvvIkiLA0KICAgIGNvbmZfbG93X3BjdCA9ICI5NSVDSeS4i+mZkO+8iCXvvIkiLA0KICAgIGNvbmZfaGlnaF9wY3QgPSAiOTUlQ0nkuIrpmZDvvIgl77yJIg0KICApDQogIGRwbHlyOjppZl9lbHNlKHggJWluJSBuYW1lcyjlr77lv5wpLCB1bm5hbWUo5a++5b+cW3hdKSwgeCkNCn0NCg0K6KGo5pel5pys6KqeIDwtIGZ1bmN0aW9uKHgpIHsNCiAgeCAlPiUNCiAgICBkcGx5cjo6cmVuYW1lX3dpdGgo5YiX5ZCN5pel5pys6KqeKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAgZHBseXI6OmFjcm9zcygNCiAgICAgICAgZHBseXI6OmV2ZXJ5dGhpbmcoKSwNCiAgICAgICAgfiBpZiAoaXMubnVtZXJpYygueCkpIHsNCiAgICAgICAgICBkcGx5cjo6aWZfZWxzZShpcy5uYSgueCksICLigJQiLCBmb3JtYXQoLngsIHRyaW0gPSBUUlVFLCBzY2llbnRpZmljID0gRkFMU0UpKQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKQ0KICAgICAgICB9DQogICAgICApDQogICAgKQ0KfQ0KDQrmsLTmupbml6XmnKzoqp4gPC0gZnVuY3Rpb24odGVybSwgbGFiZWwsIGF0dHJpYnV0ZSkgew0KICBkcGx5cjo6Y2FzZV93aGVuKA0KICAgIGF0dHJpYnV0ZSA9PSAicG9saWN5X3Bvc2l0aW9uIiB+IHN0cmluZ3I6OnN0cl9yZW1vdmUodGVybSwgIl5wb2xpY3lfcG9zaXRpb24iKSwNCiAgICBhdHRyaWJ1dGUgPT0gImdvdmVybm1lbnRfc3RhdHVzIiB+IHN0cmluZ3I6OnN0cl9yZW1vdmUodGVybSwgIl5nb3Zlcm5tZW50X3N0YXR1cyIpLA0KICAgIGF0dHJpYnV0ZSA9PSAic2VhdHMiIH4gc3RyaW5ncjo6c3RyX3JlbW92ZSh0ZXJtLCAiXnNlYXRzIiksDQogICAgYXR0cmlidXRlID09ICJnZHBfZ3Jvd3RoIiB+IHBhc3RlMCgiR0RQ77yaIiwgc3RyaW5ncjo6c3RyX3JlbW92ZSh0ZXJtLCAiXmdkcF9ncm93dGhHRFDmiJDplbfnjociKSksDQogICAgYXR0cmlidXRlID09ICJuaWtrZWkiIH4gcGFzdGUwKCLml6XntYzlubPlnYfvvJoiLCBzdHJpbmdyOjpzdHJfcmVtb3ZlKHRlcm0sICJebmlra2Vp5pel57WM5bmz5Z2H5YmN5pyI5ZCM5pyf5q+UIikpLA0KICAgIGF0dHJpYnV0ZSA9PSAiY3BpIiB+IHBhc3RlMCgiQ1BJ77yaIiwgc3RyaW5ncjo6c3RyX3JlbW92ZSh0ZXJtLCAiXmNwaUNQSeWJjeacn+avlCIpKSwNCiAgICBhdHRyaWJ1dGUgPT0gInVuZW1wbG95bWVudCIgfiBwYXN0ZTAoIuWksealreeOh++8miIsIHN0cmluZ3I6OnN0cl9yZW1vdmUodGVybSwgIl51bmVtcGxveW1lbnTlpLHmpa3njofliY3mnJ/mr5QiKSksDQogICAgYXR0cmlidXRlID09ICJwYXJ0eV9uYW1lIiB+IHN0cmluZ3I6OnN0cl9yZW1vdmUodGVybSwgIl5wYXJ0eV9uYW1lIiksDQogICAgIWlzLm5hKGxhYmVsKSAmIGxhYmVsICE9ICIiIH4gYXMuY2hhcmFjdGVyKGxhYmVsKSwNCiAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKHRlcm0pDQogICkNCn0NCmBgYA0KDQojIEMuIOeEoeS9nOeCuuWMluOBq+OBpOOBhOOBpuOBruWQhOeoruaknOiojg0KDQrku6XkuIvjgafjgIHlm57nrZTogIXjg6zjg5njg6vjga7libLku5jjg5Djg6njg7Pjgrnjgajjg5fjg63jg5XjgqPjg7zjg6vlsZ7mgKfjga7nhKHkvZzngrrmj5DnpLrjga/liKXjgIXjgavnorroqo3jgZnjgovjgILlm57nrZTogIXjg6zjg5njg6vjgafjga9Mb3ZlIHBsb3Tjgag0NeW6pue3muiouuaWreOCkuS9teeUqOOBl+OAgeODl+ODreODleOCo+ODvOODq+ODrOODmeODq+OBp+OBr+WQhOWxnuaAp+awtOa6luOBruims+a4rOavlOeOh+OCkuioreioiOS4iuOBruacn+W+heavlOeOh+OBqOavlOi8g+OBmeOCi+OAgg0KDQoqKkIuMSDlrp/pqJMx77yIMjAyM+W5tO+8iSoqDQoNCiMjIOWbs0Mx77ya5Zue562U6ICF5Ymy5LuY44GuTG92ZSBwbG90DQoNCmBgYHtyIGIxLWxvdmUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5a6f6aiTMeS7leanmCA8LSBzdHVkeV9zcGVjcyRzdHVkeTENCuWun+mokzHlibLku5joqK3oqIggPC0gbWFrZV9iYWxhbmNlX2Rlc2lnbijlrp/pqJMx5LuV5qeYKQ0K5a6f6aiTMVNNRCA8LSBwYWlyd2lzZV9zbWRfbXVsdGlhcm0o5a6f6aiTMeWJsuS7mOioreioiCRsb25nKQ0K5a6f6aiTMeacgOWkp1NNRCA8LSDlrp/pqJMxU01EICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkodmFyaWFibGUsIGxhYmVsKSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZShtYXhfYWJzX3NtZCA9IG1heChhYnNfc21kLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQ0KDQpMb3Zl44OH44O844K/IDwtIOWun+mokzFTTUQgJT4lDQogIGRwbHlyOjpsZWZ0X2pvaW4o5a6f6aiTMeacgOWkp1NNRCwgYnkgPSBjKCJ2YXJpYWJsZSIsICJsYWJlbCIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjooajnpLrlkI0gPSBzdGF0czo6cmVvcmRlcihsYWJlbCwgbWF4X2Fic19zbWQpKQ0KDQrlm7NDMSA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoTG92ZeODh+ODvOOCvywgZ2dwbG90Mjo6YWVzKHggPSBhYnNfc21kLCB5ID0g6KGo56S65ZCNKSkgKw0KICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjEwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjU1KSArDQogIGdncGxvdDI6Omdlb21fcG9pbnQoYWxwaGEgPSAwLjMwLCBzaXplID0gMS40LCBwb3NpdGlvbiA9IGdncGxvdDI6OnBvc2l0aW9uX2ppdHRlcihoZWlnaHQgPSAwLjEwLCB3aWR0aCA9IDApKSArDQogIGdncGxvdDI6Omdlb21fcG9pbnQoDQogICAgZGF0YSA9IOWun+mokzHmnIDlpKdTTUQgJT4lIGRwbHlyOjptdXRhdGUo6KGo56S65ZCNID0gc3RhdHM6OnJlb3JkZXIobGFiZWwsIG1heF9hYnNfc21kKSksDQogICAgZ2dwbG90Mjo6YWVzKHggPSBtYXhfYWJzX3NtZCwgeSA9IOihqOekuuWQjSksDQogICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwgc2hhcGUgPSAyMSwgZmlsbCA9ICJ3aGl0ZSIsIHNpemUgPSAyLjUsIHN0cm9rZSA9IDAuOA0KICApICsNCiAgZ2dwbG90Mjo6bGFicyh4ID0gIuadoeS7tumWk+OBrue1tuWvvuaomea6luWMluW5s+Wdh+W3ru+8iHxTTUR877yJIiwgeSA9IE5VTEwsDQogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAi5a6f6aiTMe+8iDIwMjPlubTvvInvvJrlkITngrnjga/mnaHku7bjg5rjgqLjgIHnmb3mipzjgY3ngrnjga/mnIDlpKfntbblr75TTUQiKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDExKSArDQogIGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkpDQrlm7NDMQ0KYGBgDQoNCuihqEMx44Gr44Gv5ZuzQzHjga7lkITngrnjgavlr77lv5zjgZnjgovjgILlkITooYzjgavjga/mr5TovIPjgZnjgosy5p2h5Lu244Gu5bmz5Z2H44GoU01E44KS56S644GZ44CCDQoNCmBgYHtyIGIxLXNtZC10YWJsZSwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrooahDMSA8LSDlrp/pqJMxU01EICU+JQ0KICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgIOWkieaVsCA9IGxhYmVsLA0KICAgIOavlOi8gyA9IHBhc3RlMChjb25kaXRpb25fYSwgIuaUv+WFmuadoeS7tu+8jSIsIGNvbmRpdGlvbl9iLCAi5pS/5YWa5p2h5Lu2IiksDQogICAgYOWJjeiAheOBruW5s+Wdh2AgPSByb3VuZChtZWFuX2EsIDMpLA0KICAgIGDlvozogIXjga7lubPlnYdgID0gcm91bmQobWVhbl9iLCAzKSwNCiAgICBg5YmN6ICFTmAgPSBuX2EsDQogICAgYOW+jOiAhU5gID0gbl9iLA0KICAgIFNNRCA9IHJvdW5kKHNtZCwgMyksDQogICAgYHxTTUR8YCA9IHJvdW5kKGFic19zbWQsIDMpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOWbs0My77ya5p2h5Lu25bmz5Z2H44GuNDXluqbnt5roqLrmlq0NCg0K5ZuzQzLjga/lm7NDMeOBqOWQjOOBmOWbnuetlOiAheODrOODmeODq+OBruWJsuS7mOODkOODqeODs+OCueOCkuOAgeWQhOWFseWkiemHj+OBruadoeS7tuW5s+Wdh+OCkuaomea6luWMluOBl+OBn+OBhuOBiOOBp+S6jOadoeS7tuOBmuOBpDQ15bqm57ea44Go5q+U6LyD44GX44Gf44KC44Gu44Gn44GC44KL44CCDQoNCmBgYHtyIGIxLWRpYWdvbmFsLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuWvvuinkue3muODh+ODvOOCvyA8LSBhc3NpZ25tZW50X2JhbGFuY2VfcmVzdWx0cyRzdHVkeTEkZGlhZ29uYWxfZGF0YSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDmr5TovIMgPSBwYXN0ZTAoY29uZGl0aW9uX2EsICLmlL/lhZrmnaHku7bvvI0iLCBjb25kaXRpb25fYiwgIuaUv+WFmuadoeS7tiIpDQogICkNCg0K44Op44OZ44Or5a++6LGhIDwtIOWvvuinkue3muODh+ODvOOCvyAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KOavlOi8gykgJT4lDQogIGRwbHlyOjpzbGljZV9tYXgoYWJzX2RpYWdvbmFsX2RldmlhdGlvbiwgbiA9IDMsIHdpdGhfdGllcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnVuZ3JvdXAoKQ0KDQrou7jnr4Tlm7IgPC0gbWF4KGFicyhjKOWvvuinkue3muODh+ODvOOCvyR4X21lYW4sIOWvvuinkue3muODh+ODvOOCvyR5X21lYW4pKSwgbmEucm0gPSBUUlVFKQ0K6Lu456+E5ZuyIDwtIG1heCgwLjEwLCDou7jnr4Tlm7IgKiAxLjE1KQ0KDQrlm7NDMiA8LSBnZ3Bsb3QyOjpnZ3Bsb3Qo5a++6KeS57ea44OH44O844K/LCBnZ3Bsb3QyOjphZXMoeCA9IHhfbWVhbiwgeSA9IHlfbWVhbikpICsNCiAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjYwKSArDQogIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuMjUpICsNCiAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC4yNSkgKw0KICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAid2hpdGUiLCBzaXplID0gMi4yKSArDQogIGdncGxvdDI6Omdlb21fdGV4dChkYXRhID0g44Op44OZ44Or5a++6LGhLCBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsYWJlbCksIHNpemUgPSAyLjYsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCB2anVzdCA9IC0wLjcpICsNCiAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IOavlOi8gywgbmNvbCA9IDMpICsNCiAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoeGxpbSA9IGMoLei7uOevhOWbsiwg6Lu456+E5ZuyKSwgeWxpbSA9IGMoLei7uOevhOWbsiwg6Lu456+E5ZuyKSkgKw0KICBnZ3Bsb3QyOjpsYWJzKHggPSAi5bem5YG05p2h5Lu244Gu5qiZ5rqW5YyW5YWx5aSJ6YeP5bmz5Z2HIiwgeSA9ICLlj7PlgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsNCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkNCuWbs0MyDQpgYGANCg0KYGBge3IgYjEtYmFsYW5jZS1zdW1tYXJ5LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuihqEMyIDwtIGFzc2lnbm1lbnRfYmFsYW5jZV9yZXN1bHRzJHN0dWR5MSRzdW1tYXJ5ICU+JQ0KICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgIOWkieaVsCA9IGxhYmVsLA0KICAgIGAy5pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzIsIDMpLA0KICAgIGAz5pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzMsIDMpLA0KICAgIGA05pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzQsIDMpLA0KICAgIGA15pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzUsIDMpLA0KICAgIGDmnIDlpKd8U01EfGAgPSByb3VuZChtYXhfYWJzX3NtZCwgMyksDQogICAgYEhvbG3oo5zmraNw5YCkYCA9IHNpZ25pZihwX2hvbG0sIDMpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOWbs0Mz77ya44OX44Ot44OV44Kj44O844Or5bGe5oCn5rC05rqW44Gu54Sh5L2c54K65o+Q56S6DQoNCuWbs0Mz44Gv5Zue562U6ICF44Gu5p2h5Lu25Ymy5LuY44Gn44Gv44Gq44GP44CB5ZCE44Kz44Oz44K444On44Kk44Oz44OI6Kqy6aGM5YaF44Gn5bGe5oCn5rC05rqW44GM6Kit6KiI44Gp44GK44KK5LiA5qeY44Gr5o+Q56S644GV44KM44Gm44GE44KL44GL44KS56K66KqN44GX44Gf44KC44Gu44Gn44GC44KL44CCDQoNCmBgYHtyIGIxLXByb2ZpbGUtcmFuZG9taXphdGlvbiwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrlsZ7mgKfpoLvluqYgPC0gcHJvZmlsZV9yYW5kb21pemF0aW9uX3Jlc3VsdHMkc3R1ZHkxJGZyZXF1ZW5jeSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4oYXR0cmlidXRlKSwNCiAgICDmnaHku7YgPSDmnaHku7bml6XmnKzoqp4ocGFydHlfbiwgInN0dWR5MSIpDQogICkNCg0K6KGo56S644Op44OZ44OrIDwtIOWxnuaAp+mgu+W6piAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KOWxnuaApywg5p2h5Lu2KSAlPiUNCiAgZHBseXI6OnNsaWNlX21heChhYnNfZGV2aWF0aW9uLCBuID0gMiwgd2l0aF90aWVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6dW5ncm91cCgpDQoNCuWbs0MzIDwtIGdncGxvdDI6OmdncGxvdCjlsZ7mgKfpoLvluqYsIGdncGxvdDI6OmFlcyh4ID0gZXhwZWN0ZWRfc2hhcmUsIHkgPSBvYnNlcnZlZF9zaGFyZSwgc2hhcGUgPSDmnaHku7YpKSArDQogIGdncGxvdDI6Omdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbGluZXdpZHRoID0gMC42NSkgKw0KICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNpemUgPSAyLjIsIGZpbGwgPSAid2hpdGUiKSArDQogIGdncGxvdDI6Omdlb21fdGV4dChkYXRhID0g6KGo56S644Op44OZ44OrLCBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsZXZlbCksIHNpemUgPSAyLjQsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCB2anVzdCA9IC0wLjcpICsNCiAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IOWxnuaApywgbmNvbCA9IDMpICsNCiAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoKSArDQogIGdncGxvdDI6OmxhYnMoeCA9ICLoqK3oqIjkuIrjga7mnJ/lvoXmr5TnjociLCB5ID0gIuims+a4rOavlOeOhyIsIHNoYXBlID0gIuadoeS7tiIpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKw0KICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCuWbs0MzDQpgYGANCg0KYGBge3IgYjEtcmFuZG9taXphdGlvbi10YWJsZXMsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6KGoQzMgPC0gcHJvZmlsZV9yYW5kb21pemF0aW9uX3Jlc3VsdHMkc3R1ZHkxJHVuaWZvcm1pdHlfdGVzdHMgJT4lDQogIGRwbHlyOjp0cmFuc211dGUoDQogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTEiKSwNCiAgICDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4oYXR0cmlidXRlKSwNCiAgICBg44Kr44Kk5LqM5LmX5YCkYCA9IHJvdW5kKGNoaV9zcXVhcmUsIDMpLA0KICAgIOiHqueUseW6piA9IGRmLA0KICAgIHDlgKQgPSBzaWduaWYocF92YWx1ZSwgMyksDQogICAgYEhvbG3oo5zmraNw5YCkYCA9IHNpZ25pZihwX2hvbG0sIDMpLA0KICAgIGDmnIDlpKfntbblr77mr5Tnjoflt65gID0gcm91bmQobWF4X2Fic19zaGFyZV9kZXZpYXRpb24sIDQpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzMpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQrooahDNCA8LSDlsZ7mgKfpoLvluqYgJT4lDQogIGRwbHlyOjp0cmFuc211dGUoDQogICAg5p2h5Lu2LA0KICAgIOWxnuaApywNCiAgICDmsLTmupYgPSBsZXZlbCwNCiAgICDoprPmuKzmlbAgPSBvYnNlcnZlZF9uLA0KICAgIOe3j+aVsCA9IHRvdGFsX24sDQogICAg6Kaz5ris5q+U546HID0gcm91bmQob2JzZXJ2ZWRfc2hhcmUsIDQpLA0KICAgIOacn+W+heavlOeOhyA9IHJvdW5kKGV4cGVjdGVkX3NoYXJlLCA0KSwNCiAgICDlt64gPSByb3VuZChkZXZpYXRpb24sIDQpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzQpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCioqQi4yIOWun+mokzLvvIgyMDI25bm077yJKioNCg0KIyMg5ZuzQzTvvJrlm57nrZTogIXlibLku5jjga5Mb3ZlIHBsb3QNCg0KYGBge3IgYjItbG92ZSwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrlrp/pqJMy5LuV5qeYIDwtIHN0dWR5X3NwZWNzJHN0dWR5Mg0K5a6f6aiTMuWJsuS7mOioreioiCA8LSBtYWtlX2JhbGFuY2VfZGVzaWduKOWun+mokzLku5Xmp5gpDQrlrp/pqJMyU01EIDwtIHBhaXJ3aXNlX3NtZF9tdWx0aWFybSjlrp/pqJMy5Ymy5LuY6Kit6KiIJGxvbmcpDQrlrp/pqJMy5pyA5aSnU01EIDwtIOWun+mokzJTTUQgJT4lDQogIGRwbHlyOjpncm91cF9ieSh2YXJpYWJsZSwgbGFiZWwpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKG1heF9hYnNfc21kID0gbWF4KGFic19zbWQsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpDQoNCkxvdmXjg4fjg7zjgr8gPC0g5a6f6aiTMlNNRCAlPiUNCiAgZHBseXI6OmxlZnRfam9pbijlrp/pqJMy5pyA5aSnU01ELCBieSA9IGMoInZhcmlhYmxlIiwgImxhYmVsIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOihqOekuuWQjSA9IHN0YXRzOjpyZW9yZGVyKGxhYmVsLCBtYXhfYWJzX3NtZCkpDQoNCuWbs0M0IDwtIGdncGxvdDI6OmdncGxvdChMb3Zl44OH44O844K/LCBnZ3Bsb3QyOjphZXMoeCA9IGFic19zbWQsIHkgPSDooajnpLrlkI0pKSArDQogIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMTAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNTUpICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChhbHBoYSA9IDAuMzAsIHNpemUgPSAxLjQsIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25faml0dGVyKGhlaWdodCA9IDAuMTAsIHdpZHRoID0gMCkpICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgNCiAgICBkYXRhID0g5a6f6aiTMuacgOWkp1NNRCAlPiUgZHBseXI6Om11dGF0ZSjooajnpLrlkI0gPSBzdGF0czo6cmVvcmRlcihsYWJlbCwgbWF4X2Fic19zbWQpKSwNCiAgICBnZ3Bsb3QyOjphZXMoeCA9IG1heF9hYnNfc21kLCB5ID0g6KGo56S65ZCNKSwNCiAgICBpbmhlcml0LmFlcyA9IEZBTFNFLCBzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc2l6ZSA9IDIuNSwgc3Ryb2tlID0gMC44DQogICkgKw0KICBnZ3Bsb3QyOjpsYWJzKHggPSAi5p2h5Lu26ZaT44Gu57W25a++5qiZ5rqW5YyW5bmz5Z2H5beu77yIfFNNRHzvvIkiLCB5ID0gTlVMTCwNCiAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICLlrp/pqJMy77yIMjAyNuW5tO+8ie+8muWQhOeCueOBr+adoeS7tuODmuOCouOAgeeZveaKnOOBjeeCueOBr+acgOWkp+e1tuWvvlNNRCIpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEpICsNCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkNCuWbs0M0DQpgYGANCg0K6KGoQzXjga/lm7NDNOOBruWQhOeCueOBq+WvvuW/nOOBmeOCi+OAguWQhOihjOOBq+OBr+avlOi8g+OBmeOCizLmnaHku7bjga7lubPlnYfjgahTTUTjgaDjgZHjgpLmrovjgZfjgIHku5bmnaHku7bjgavnlLHmnaXjgZnjgovmp4vpgKDnmoTjgarmrKDmkI3lgKTjga/ooajnpLrjgZfjgarjgYTjgIINCg0KYGBge3IgYjItc21kLXRhYmxlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuihqEM1IDwtIOWun+mokzJTTUQgJT4lDQogIGRwbHlyOjp0cmFuc211dGUoDQogICAg5aSJ5pWwID0gbGFiZWwsDQogICAg5q+U6LyDID0gcGFzdGUwKGNvbmRpdGlvbl9hLCAi5pS/5YWa5p2h5Lu277yNIiwgY29uZGl0aW9uX2IsICLmlL/lhZrmnaHku7YiKSwNCiAgICBg5YmN6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYSwgMyksDQogICAgYOW+jOiAheOBruW5s+Wdh2AgPSByb3VuZChtZWFuX2IsIDMpLA0KICAgIGDliY3ogIVOYCA9IG5fYSwNCiAgICBg5b6M6ICFTmAgPSBuX2IsDQogICAgU01EID0gcm91bmQoc21kLCAzKSwNCiAgICBgfFNNRHxgID0gcm91bmQoYWJzX3NtZCwgMykNCiAgKQ0Ka25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahDNSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMg5ZuzQzXvvJrmnaHku7blubPlnYfjga40NeW6pue3muiouuaWrQ0KDQrlm7NDNeOBr+Wbs0M044Go5ZCM44GY5Zue562U6ICF44Os44OZ44Or44Gu5Ymy5LuY44OQ44Op44Oz44K544KS44CB5ZCE5YWx5aSJ6YeP44Gu5p2h5Lu25bmz5Z2H44KS5qiZ5rqW5YyW44GX44Gf44GG44GI44GnMuadoeS7tuOBmuOBpDQ15bqm57ea44Go5q+U6LyD44GX44Gf44KC44Gu44Gn44GC44KL44CCDQoNCmBgYHtyIGIyLWRpYWdvbmFsLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuWvvuinkue3muODh+ODvOOCvyA8LSBhc3NpZ25tZW50X2JhbGFuY2VfcmVzdWx0cyRzdHVkeTIkZGlhZ29uYWxfZGF0YSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDmr5TovIMgPSBwYXN0ZTAoY29uZGl0aW9uX2EsICLmlL/lhZrmnaHku7bvvI0iLCBjb25kaXRpb25fYiwgIuaUv+WFmuadoeS7tiIpDQogICkNCg0K44Op44OZ44Or5a++6LGhIDwtIOWvvuinkue3muODh+ODvOOCvyAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KOavlOi8gykgJT4lDQogIGRwbHlyOjpzbGljZV9tYXgoYWJzX2RpYWdvbmFsX2RldmlhdGlvbiwgbiA9IDMsIHdpdGhfdGllcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnVuZ3JvdXAoKQ0KDQrou7jnr4Tlm7IgPC0gbWF4KGFicyhjKOWvvuinkue3muODh+ODvOOCvyR4X21lYW4sIOWvvuinkue3muODh+ODvOOCvyR5X21lYW4pKSwgbmEucm0gPSBUUlVFKQ0K6Lu456+E5ZuyIDwtIG1heCgwLjEwLCDou7jnr4Tlm7IgKiAxLjE1KQ0KDQrlm7NDNSA8LSBnZ3Bsb3QyOjpnZ3Bsb3Qo5a++6KeS57ea44OH44O844K/LCBnZ3Bsb3QyOjphZXMoeCA9IHhfbWVhbiwgeSA9IHlfbWVhbikpICsNCiAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjYwKSArDQogIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuMjUpICsNCiAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC4yNSkgKw0KICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAid2hpdGUiLCBzaXplID0gMi4yKSArDQogIGdncGxvdDI6Omdlb21fdGV4dChkYXRhID0g44Op44OZ44Or5a++6LGhLCBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsYWJlbCksIHNpemUgPSAyLjYsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCB2anVzdCA9IC0wLjcpICsNCiAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IOavlOi8gywgbmNvbCA9IDMpICsNCiAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoeGxpbSA9IGMoLei7uOevhOWbsiwg6Lu456+E5ZuyKSwgeWxpbSA9IGMoLei7uOevhOWbsiwg6Lu456+E5ZuyKSkgKw0KICBnZ3Bsb3QyOjpsYWJzKHggPSAi5bem5YG05p2h5Lu244Gu5qiZ5rqW5YyW5YWx5aSJ6YeP5bmz5Z2HIiwgeSA9ICLlj7PlgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsNCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkNCuWbs0M1DQpgYGANCg0KYGBge3IgYjItYmFsYW5jZS1zdW1tYXJ5LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuihqEM2IDwtIGFzc2lnbm1lbnRfYmFsYW5jZV9yZXN1bHRzJHN0dWR5MiRzdW1tYXJ5ICU+JQ0KICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgIOWkieaVsCA9IGxhYmVsLA0KICAgIGAy5pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzIsIDMpLA0KICAgIGAz5pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzMsIDMpLA0KICAgIGA05pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzQsIDMpLA0KICAgIGA15pS/5YWa5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzUsIDMpLA0KICAgIGDmnIDlpKd8U01EfGAgPSByb3VuZChtYXhfYWJzX3NtZCwgMyksDQogICAgYEhvbG3oo5zmraNw5YCkYCA9IHNpZ25pZihwX2hvbG0sIDMpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzYpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOWbs0M277ya44OX44Ot44OV44Kj44O844Or5bGe5oCn5rC05rqW44Gu54Sh5L2c54K65o+Q56S6DQoNCuWbs0M25Lul6ZmN44Gv5Zue562U6ICF44Gu5p2h5Lu25Ymy5LuY44Gn44Gv44Gq44GP44CB5ZCE44Kz44Oz44K444On44Kk44Oz44OI6Kqy6aGM5YaF44Gn5bGe5oCn5rC05rqW44GM6Kit6KiI44Gp44GK44KK5LiA5qeY44Gr5o+Q56S644GV44KM44Gm44GE44KL44GL44KS56K66KqN44GZ44KL44KC44Gu44Gn44GC44KL44CCDQoNCmBgYHtyIGIyLXByb2ZpbGUtcmFuZG9taXphdGlvbiwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrlsZ7mgKfpoLvluqYgPC0gcHJvZmlsZV9yYW5kb21pemF0aW9uX3Jlc3VsdHMkc3R1ZHkyJGZyZXF1ZW5jeSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4oYXR0cmlidXRlKSwNCiAgICDmnaHku7YgPSDmnaHku7bml6XmnKzoqp4ocGFydHlfbiwgInN0dWR5MiIpDQogICkNCg0K6KGo56S644Op44OZ44OrIDwtIOWxnuaAp+mgu+W6piAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KOWxnuaApywg5p2h5Lu2KSAlPiUNCiAgZHBseXI6OnNsaWNlX21heChhYnNfZGV2aWF0aW9uLCBuID0gMiwgd2l0aF90aWVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6dW5ncm91cCgpDQoNCuWbs0M2IDwtIGdncGxvdDI6OmdncGxvdCjlsZ7mgKfpoLvluqYsIGdncGxvdDI6OmFlcyh4ID0gZXhwZWN0ZWRfc2hhcmUsIHkgPSBvYnNlcnZlZF9zaGFyZSwgc2hhcGUgPSDmnaHku7YpKSArDQogIGdncGxvdDI6Omdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbGluZXdpZHRoID0gMC42NSkgKw0KICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHNpemUgPSAyLjIsIGZpbGwgPSAid2hpdGUiKSArDQogIGdncGxvdDI6Omdlb21fdGV4dChkYXRhID0g6KGo56S644Op44OZ44OrLCBnZ3Bsb3QyOjphZXMobGFiZWwgPSBsZXZlbCksIHNpemUgPSAyLjQsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCB2anVzdCA9IC0wLjcpICsNCiAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+IOWxnuaApywgbmNvbCA9IDMpICsNCiAgZ2dwbG90Mjo6Y29vcmRfZXF1YWwoKSArDQogIGdncGxvdDI6OmxhYnMoeCA9ICLoqK3oqIjkuIrjga7mnJ/lvoXmr5TnjociLCB5ID0gIuims+a4rOavlOeOhyIsIHNoYXBlID0gIuadoeS7tiIpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKw0KICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCuWbs0M2DQpgYGANCg0KYGBge3IgYjItcmFuZG9taXphdGlvbi10YWJsZXMsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6KGoQzcgPC0gcHJvZmlsZV9yYW5kb21pemF0aW9uX3Jlc3VsdHMkc3R1ZHkyJHVuaWZvcm1pdHlfdGVzdHMgJT4lDQogIGRwbHlyOjp0cmFuc211dGUoDQogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTIiKSwNCiAgICDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4oYXR0cmlidXRlKSwNCiAgICBg44Kr44Kk5LqM5LmX5YCkYCA9IHJvdW5kKGNoaV9zcXVhcmUsIDMpLA0KICAgIOiHqueUseW6piA9IGRmLA0KICAgIHDlgKQgPSBzaWduaWYocF92YWx1ZSwgMyksDQogICAgYEhvbG3oo5zmraNw5YCkYCA9IHNpZ25pZihwX2hvbG0sIDMpLA0KICAgIGDmnIDlpKfntbblr77mr5Tnjoflt65gID0gcm91bmQobWF4X2Fic19zaGFyZV9kZXZpYXRpb24sIDQpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzcpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQrooahDOCA8LSDlsZ7mgKfpoLvluqYgJT4lDQogIGRwbHlyOjp0cmFuc211dGUoDQogICAg5p2h5Lu2LA0KICAgIOWxnuaApywNCiAgICDmsLTmupYgPSBsZXZlbCwNCiAgICDoprPmuKzmlbAgPSBvYnNlcnZlZF9uLA0KICAgIOe3j+aVsCA9IHRvdGFsX24sDQogICAg6Kaz5ris5q+U546HID0gcm91bmQob2JzZXJ2ZWRfc2hhcmUsIDQpLA0KICAgIOacn+W+heavlOeOhyA9IHJvdW5kKGV4cGVjdGVkX3NoYXJlLCA0KSwNCiAgICDlt64gPSByb3VuZChkZXZpYXRpb24sIDQpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzgpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCioqQi4zIOWun+mokzPvvIgyMDI25bm077yJKioNCg0KIyMg5ZuzQzfvvJrlm57nrZTogIXlibLku5jjga5Mb3ZlIHBsb3QNCg0KYGBge3IgYjMtbG92ZSwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrlrp/pqJMz5LuV5qeYIDwtIHN0dWR5X3NwZWNzJHN0dWR5Mw0K5a6f6aiTM+WJsuS7mOioreioiCA8LSBtYWtlX2JhbGFuY2VfZGVzaWduKOWun+mokzPku5Xmp5gpDQrlrp/pqJMzU01EIDwtIHBhaXJ3aXNlX3NtZF9tdWx0aWFybSjlrp/pqJMz5Ymy5LuY6Kit6KiIJGxvbmcpDQrlrp/pqJMz5pyA5aSnU01EIDwtIOWun+mokzNTTUQgJT4lDQogIGRwbHlyOjpncm91cF9ieSh2YXJpYWJsZSwgbGFiZWwpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKG1heF9hYnNfc21kID0gbWF4KGFic19zbWQsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpDQoNCkxvdmXjg4fjg7zjgr8gPC0g5a6f6aiTM1NNRCAlPiUNCiAgZHBseXI6OmxlZnRfam9pbijlrp/pqJMz5pyA5aSnU01ELCBieSA9IGMoInZhcmlhYmxlIiwgImxhYmVsIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOihqOekuuWQjSA9IHN0YXRzOjpyZW9yZGVyKGxhYmVsLCBtYXhfYWJzX3NtZCkpDQoNCuWbs0M3IDwtIGdncGxvdDI6OmdncGxvdChMb3Zl44OH44O844K/LCBnZ3Bsb3QyOjphZXMoeCA9IGFic19zbWQsIHkgPSDooajnpLrlkI0pKSArDQogIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMTAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNTUpICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChhbHBoYSA9IDAuMzAsIHNpemUgPSAxLjQsIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25faml0dGVyKGhlaWdodCA9IDAuMTAsIHdpZHRoID0gMCkpICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgNCiAgICBkYXRhID0g5a6f6aiTM+acgOWkp1NNRCAlPiUgZHBseXI6Om11dGF0ZSjooajnpLrlkI0gPSBzdGF0czo6cmVvcmRlcihsYWJlbCwgbWF4X2Fic19zbWQpKSwNCiAgICBnZ3Bsb3QyOjphZXMoeCA9IG1heF9hYnNfc21kLCB5ID0g6KGo56S65ZCNKSwNCiAgICBpbmhlcml0LmFlcyA9IEZBTFNFLCBzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc2l6ZSA9IDIuNSwgc3Ryb2tlID0gMC44DQogICkgKw0KICBnZ3Bsb3QyOjpsYWJzKHggPSAi5p2h5Lu26ZaT44Gu57W25a++5qiZ5rqW5YyW5bmz5Z2H5beu77yIfFNNRHzvvIkiLCB5ID0gTlVMTCwNCiAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICLlrp/pqJMz77yIMjAyNuW5tO+8ie+8muWQhOeCueOBr+adoeS7tuODmuOCouOAgeeZveaKnOOBjeeCueOBr+acgOWkp+e1tuWvvlNNRCIpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEpICsNCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkNCuWbs0M3DQpgYGANCg0K6KGoQznjga/lm7NDN+OBruWQhOeCueOBq+WvvuW/nOOBmeOCi+OAgg0KDQpgYGB7ciBiMy1zbWQtdGFibGUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6KGoQzkgPC0g5a6f6aiTM1NNRCAlPiUNCiAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICDlpInmlbAgPSBsYWJlbCwNCiAgICDmr5TovIMgPSBwYXN0ZTAoY29uZGl0aW9uX2EsICLpgbjmip7ogqLmnaHku7bvvI0iLCBjb25kaXRpb25fYiwgIumBuOaKnuiCouadoeS7tiIpLA0KICAgIGDliY3ogIXjga7lubPlnYdgID0gcm91bmQobWVhbl9hLCAzKSwNCiAgICBg5b6M6ICF44Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fYiwgMyksDQogICAgYOWJjeiAhU5gID0gbl9hLA0KICAgIGDlvozogIVOYCA9IG5fYiwNCiAgICBTTUQgPSByb3VuZChzbWQsIDMpLA0KICAgIGB8U01EfGAgPSByb3VuZChhYnNfc21kLCAzKQ0KICApDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEM5KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIyDlm7NDOO+8muadoeS7tuW5s+Wdh+OBrjQ15bqm57ea6Ki65patDQoNCuWbs0M444Gv5ZuzQzfjgajlkIzjgZjlm57nrZTogIXjg6zjg5njg6vjga7libLku5jjg5Djg6njg7PjgrnjgpLjgIHlkITlhbHlpInph4/jga7mnaHku7blubPlnYfjgpLmqJnmupbljJbjgZfjgZ/jgYbjgYjjgacy5p2h5Lu244Ga44GkNDXluqbnt5rjgajmr5TovIPjgZfjgZ/jgoLjga7jgafjgYLjgovjgIINCg0KYGBge3IgYjMtZGlhZ29uYWwsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5a++6KeS57ea44OH44O844K/IDwtIGFzc2lnbm1lbnRfYmFsYW5jZV9yZXN1bHRzJHN0dWR5MyRkaWFnb25hbF9kYXRhICU+JQ0KICBkcGx5cjo6bXV0YXRlKA0KICAgIOavlOi8gyA9IHBhc3RlMChjb25kaXRpb25fYSwgIumBuOaKnuiCouadoeS7tu+8jSIsIGNvbmRpdGlvbl9iLCAi6YG45oqe6IKi5p2h5Lu2IikNCiAgKQ0KDQrjg6njg5njg6vlr77osaEgPC0g5a++6KeS57ea44OH44O844K/ICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnko5q+U6LyDKSAlPiUNCiAgZHBseXI6OnNsaWNlX21heChhYnNfZGlhZ29uYWxfZGV2aWF0aW9uLCBuID0gMywgd2l0aF90aWVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6dW5ncm91cCgpDQoNCui7uOevhOWbsiA8LSBtYXgoYWJzKGMo5a++6KeS57ea44OH44O844K/JHhfbWVhbiwg5a++6KeS57ea44OH44O844K/JHlfbWVhbikpLCBuYS5ybSA9IFRSVUUpDQrou7jnr4Tlm7IgPC0gbWF4KDAuMTAsIOi7uOevhOWbsiAqIDEuMTUpDQoNCuWbs0M4IDwtIGdncGxvdDI6OmdncGxvdCjlr77op5Lnt5rjg4fjg7zjgr8sIGdncGxvdDI6OmFlcyh4ID0geF9tZWFuLCB5ID0geV9tZWFuKSkgKw0KICBnZ3Bsb3QyOjpnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNjApICsNCiAgZ2dwbG90Mjo6Z2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC4yNSkgKw0KICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjI1KSArDQogIGdncGxvdDI6Omdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZmlsbCA9ICJ3aGl0ZSIsIHNpemUgPSAyLjIpICsNCiAgZ2dwbG90Mjo6Z2VvbV90ZXh0KGRhdGEgPSDjg6njg5njg6vlr77osaEsIGdncGxvdDI6OmFlcyhsYWJlbCA9IGxhYmVsKSwgc2l6ZSA9IDIuNiwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIHZqdXN0ID0gLTAuNykgKw0KICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4g5q+U6LyDLCBuY29sID0gMykgKw0KICBnZ3Bsb3QyOjpjb29yZF9lcXVhbCh4bGltID0gYygt6Lu456+E5ZuyLCDou7jnr4Tlm7IpLCB5bGltID0gYygt6Lu456+E5ZuyLCDou7jnr4Tlm7IpKSArDQogIGdncGxvdDI6OmxhYnMoeCA9ICLlt6blgbTmnaHku7bjga7mqJnmupbljJblhbHlpInph4/lubPlnYciLCB5ID0gIuWPs+WBtOadoeS7tuOBruaomea6luWMluWFseWkiemHj+W5s+WdhyIpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKw0KICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpKQ0K5ZuzQzgNCmBgYA0KDQpgYGB7ciBiMy1iYWxhbmNlLXN1bW1hcnksIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6KGoQzEwIDwtIGFzc2lnbm1lbnRfYmFsYW5jZV9yZXN1bHRzJHN0dWR5MyRzdW1tYXJ5ICU+JQ0KICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgIOWkieaVsCA9IGxhYmVsLA0KICAgIGAy6YG45oqe6IKi5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzIsIDMpLA0KICAgIGAz6YG45oqe6IKi5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzMsIDMpLA0KICAgIGA06YG45oqe6IKi5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzQsIDMpLA0KICAgIGA16YG45oqe6IKi5p2h5Lu244Gu5bmz5Z2HYCA9IHJvdW5kKG1lYW5fY29uZGl0aW9uXzUsIDMpLA0KICAgIGDmnIDlpKd8U01EfGAgPSByb3VuZChtYXhfYWJzX3NtZCwgMyksDQogICAgYEhvbG3oo5zmraNw5YCkYCA9IHNpZ25pZihwX2hvbG0sIDMpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoQzEwKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIyDlm7NDOe+8muODl+ODreODleOCo+ODvOODq+WxnuaAp+awtOa6luOBrueEoeS9nOeCuuaPkOekug0KDQrlm7NDOeOBr+WbnuetlOiAheOBruadoeS7tuWJsuS7mOOBp+OBr+OBquOBj+OAgeWQhOOCs+ODs+OCuOODp+OCpOODs+ODiOiqsumhjOWGheOBp+WxnuaAp+awtOa6luOBjOioreioiOOBqeOBiuOCiuS4gOanmOOBq+aPkOekuuOBleOCjOOBpuOBhOOCi+OBi+OCkueiuuiqjeOBmeOCi+OCguOBruOBp+OBguOCi+OAgg0KDQpgYGB7ciBiMy1wcm9maWxlLXJhbmRvbWl6YXRpb24sIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5bGe5oCn6aC75bqmIDwtIHByb2ZpbGVfcmFuZG9taXphdGlvbl9yZXN1bHRzJHN0dWR5MyRmcmVxdWVuY3kgJT4lDQogIGRwbHlyOjptdXRhdGUoDQogICAg5bGe5oCnID0g5bGe5oCn5pel5pys6KqeKGF0dHJpYnV0ZSksDQogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTMiKQ0KICApDQoNCuihqOekuuODqeODmeODqyA8LSDlsZ7mgKfpoLvluqYgJT4lDQogIGRwbHlyOjpncm91cF9ieSjlsZ7mgKcsIOadoeS7tikgJT4lDQogIGRwbHlyOjpzbGljZV9tYXgoYWJzX2RldmlhdGlvbiwgbiA9IDIsIHdpdGhfdGllcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnVuZ3JvdXAoKQ0KDQrlm7NDOSA8LSBnZ3Bsb3QyOjpnZ3Bsb3Qo5bGe5oCn6aC75bqmLCBnZ3Bsb3QyOjphZXMoeCA9IGV4cGVjdGVkX3NoYXJlLCB5ID0gb2JzZXJ2ZWRfc2hhcmUsIHNoYXBlID0g5p2h5Lu2KSkgKw0KICBnZ3Bsb3QyOjpnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IDAuNjUpICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzaXplID0gMi4yLCBmaWxsID0gIndoaXRlIikgKw0KICBnZ3Bsb3QyOjpnZW9tX3RleHQoZGF0YSA9IOihqOekuuODqeODmeODqywgZ2dwbG90Mjo6YWVzKGxhYmVsID0gbGV2ZWwpLCBzaXplID0gMi40LCBjaGVja19vdmVybGFwID0gVFJVRSwgdmp1c3QgPSAtMC43KSArDQogIGdncGxvdDI6OmZhY2V0X3dyYXAofiDlsZ7mgKcsIG5jb2wgPSAzKSArDQogIGdncGxvdDI6OmNvb3JkX2VxdWFsKCkgKw0KICBnZ3Bsb3QyOjpsYWJzKHggPSAi6Kit6KiI5LiK44Gu5pyf5b6F5q+U546HIiwgeSA9ICLoprPmuKzmr5TnjociLCBzaGFwZSA9ICLmnaHku7YiKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwLjUpICsNCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQrlm7NDOQ0KYGBgDQoNCmBgYHtyIGIzLXJhbmRvbWl6YXRpb24tdGFibGVzLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuihqEMxMSA8LSBwcm9maWxlX3JhbmRvbWl6YXRpb25fcmVzdWx0cyRzdHVkeTMkdW5pZm9ybWl0eV90ZXN0cyAlPiUNCiAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICDmnaHku7YgPSDmnaHku7bml6XmnKzoqp4ocGFydHlfbiwgInN0dWR5MyIpLA0KICAgIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnihhdHRyaWJ1dGUpLA0KICAgIGDjgqvjgqTkuozkuZflgKRgID0gcm91bmQoY2hpX3NxdWFyZSwgMyksDQogICAg6Ieq55Sx5bqmID0gZGYsDQogICAgcOWApCA9IHNpZ25pZihwX3ZhbHVlLCAzKSwNCiAgICBgSG9sbeijnOato3DlgKRgID0gc2lnbmlmKHBfaG9sbSwgMyksDQogICAgYOacgOWkp+e1tuWvvuavlOeOh+W3rmAgPSByb3VuZChtYXhfYWJzX3NoYXJlX2RldmlhdGlvbiwgNCkNCiAgKQ0Ka25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahDMTEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQrooahDMTIgPC0g5bGe5oCn6aC75bqmICU+JQ0KICBkcGx5cjo6dHJhbnNtdXRlKA0KICAgIOadoeS7tiwNCiAgICDlsZ7mgKcsDQogICAg5rC05rqWID0gbGV2ZWwsDQogICAg6Kaz5ris5pWwID0gb2JzZXJ2ZWRfbiwNCiAgICDnt4/mlbAgPSB0b3RhbF9uLA0KICAgIOims+a4rOavlOeOhyA9IHJvdW5kKG9ic2VydmVkX3NoYXJlLCA0KSwNCiAgICDmnJ/lvoXmr5TnjocgPSByb3VuZChleHBlY3RlZF9zaGFyZSwgNCksDQogICAg5beuID0gcm91bmQoZGV2aWF0aW9uLCA0KQ0KICApDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEMxMiksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMgQy40IOaomeacrOa4m+WwkeOBqOOCueOCr+ODquODvOODi+ODs+OCsA0KDQrku6XkuIvjga7mqJnmnKzmuJvlsJHooajjgafjga/jgIHlkITjgrnjgq/jg6rjg7zjg4vjg7PjgrDmrrXpmo7jgavlr77lv5zjgZnjgosqKuiqv+afu+elqOS4iuOBruizquWVj+aWh++8iOimgee0hO+8iSoq44KS5L216KiY44GZ44KL44CC6LOq5ZWP5paH44Gv6KGo44Gu5Y+v6Kqt5oCn44KS5L+d44Gk44Gf44KB57Ch5r2U44Gr56S644GX44CB5Y6f5paH44Gu5a6M5YWo44Gq6LOq5ZWP5paH44O75Zue562U6YG45oqe6IKi44O744Kz44Oz44K444On44Kk44Oz44OI6Kqy6aGM44Gu5o+Q56S65b2i5byP44GvKiroo5zpgbpK44CM6Kq/5p+756Wo44CNKirjgavjgb7jgajjgoHjgabmjrLovInjgZnjgovjgIINCg0KIyMjIOWun+mokzHvvIgyMDIz5bm077yJDQoNCmBgYHtyIGI0LXN0dWR5MS1zY3JlZW5pbmcsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5a6f6aiTMeaomeacrOa4m+WwkSA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfc2FtcGxlX2F0dHJpdGlvbi5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjptdXRhdGUoDQogICAg5q616ZqOID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKOautemajiwgYygiY2hvaWNlX3Rhc2soWzEtNV0pIiA9ICLpgbjmip7oqrLpoYxcXDEiLCAiQ2hvaWNlIHRhc2sgKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIikpDQogICkgJT4lDQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6ZXZlcnl0aGluZygpLCB+IHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKSkpDQprbml0cjo6a2FibGUo5a6f6aiTMeaomeacrOa4m+WwkSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahDMTPvvJrlrp/pqJMx44Gu5qiZ5pys5rib5bCRIikNCg0K5a6f6aiTMeadoeS7tuWIpeaomeacrCA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfc2FtcGxlX2F0dHJpdGlvbl9ieV9jb25kaXRpb24uY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6bXV0YXRlKA0KICAgIOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTEiKSwNCiAgICDmrrXpmo4gPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwo5q616ZqOLCBjKCJjaG9pY2VfdGFzayhbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIsICJDaG9pY2UgdGFzayAoWzEtNV0pIiA9ICLpgbjmip7oqrLpoYxcXDEiKSkNCiAgKSAlPiUNCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkNCmtuaXRyOjprYWJsZSjlrp/pqJMx5p2h5Lu25Yil5qiZ5pysLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEMxNO+8muWun+mokzHjga7mnaHku7bliKXmqJnmnKzmuJvlsJEiKQ0KYGBgDQoNCg0KDQojIyMg5a6f6aiTMu+8iDIwMjblubTvvIkNCg0KYGBge3IgYjQtc3R1ZHkyLXNjcmVlbmluZywgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrlrp/pqJMy5qiZ5pys5rib5bCRIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9zYW1wbGVfYXR0cml0aW9uLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmrrXpmo4gPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwo5q616ZqOLCBjKCJjaG9pY2VfdGFzayhbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIsICJDaG9pY2UgdGFzayAoWzEtNV0pIiA9ICLpgbjmip7oqrLpoYxcXDEiKSkpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmV2ZXJ5dGhpbmcoKSwgfiB0aWR5cjo6cmVwbGFjZV9uYShhcy5jaGFyYWN0ZXIoLngpLCAi4oCUIikpKQ0Ka25pdHI6OmthYmxlKOWun+mokzLmqJnmnKzmuJvlsJEsIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzE377ya5a6f6aiTMuOBruaomeacrOa4m+WwkSIpDQoNCuWun+mokzLmnaHku7bliKXmqJnmnKwgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkyIiwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb25fYnlfY29uZGl0aW9uLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkyIiksIOautemajiA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCjmrrXpmo4sIGMoImNob2ljZV90YXNrKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIiwgIkNob2ljZSB0YXNrIChbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIpKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6ZXZlcnl0aGluZygpLCB+IHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKSkpDQprbml0cjo6a2FibGUo5a6f6aiTMuadoeS7tuWIpeaomeacrCwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahDMTjvvJrlrp/pqJMy44Gu5p2h5Lu25Yil5qiZ5pys5rib5bCRIikNCg0K5a6f6aiTMuaTjeS9nOeiuuiqjSA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTIiLCAidGFibGVfbWFuaXB1bGF0aW9uX2NoZWNrLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCByZXNwb25zZSA9ICLlm57nrZQiLCBzdGF0dXMgPSAi5Yik5a6aIiwgbiA9ICJOIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTIiKSwgZHBseXI6OmFjcm9zcyhkcGx5cjo6ZXZlcnl0aGluZygpLCB+IHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKSkpDQprbml0cjo6a2FibGUo5a6f6aiTMuaTjeS9nOeiuuiqjSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahDMTnvvJrlrp/pqJMy44Gu6YG45oqe6IKi5pWw5pON5L2c56K66KqNIikNCg0K5a6f6aiTMuaMh+ekuumgheebriA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTIiLCAidGFibGVfYXR0ZW50aW9uX2NoZWNrLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcmVzcG9uc2UgPSAi5Zue562U44Kz44O844OJIiwgc3RhdHVzID0gIuWIpOWumiIsIG4gPSAiTiIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkNCmtuaXRyOjprYWJsZSjlrp/pqJMy5oyH56S66aCF55uuLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEMyMO+8muWun+mokzLjga7mjIfnpLrpoIXnm64iKQ0KYGBgDQoNCiMjIyDlrp/pqJMz77yIMjAyNuW5tO+8iQ0KDQpgYGB7ciBiNC1zdHVkeTMtc2NyZWVuaW5nLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuWun+mokzPmqJnmnKzmuJvlsJEgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX3NhbXBsZV9hdHRyaXRpb24uY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOautemajiA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCjmrrXpmo4sIGMoImNob2ljZV90YXNrKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIiwgIkNob2ljZSB0YXNrIChbMS01XSkiID0gIumBuOaKnuiqsumhjFxcMSIpKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6ZXZlcnl0aGluZygpLCB+IHRpZHlyOjpyZXBsYWNlX25hKGFzLmNoYXJhY3RlcigueCksICLigJQiKSkpDQprbml0cjo6a2FibGUo5a6f6aiTM+aomeacrOa4m+WwkSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahDMjHvvJrlrp/pqJMz44Gu5qiZ5pys5rib5bCRIikNCg0K5a6f6aiTM+adoeS7tuWIpeaomeacrCA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTMiLCAidGFibGVfc2FtcGxlX2F0dHJpdGlvbl9ieV9jb25kaXRpb24uY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTMiKSwg5q616ZqOID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKOautemajiwgYygiY2hvaWNlX3Rhc2soWzEtNV0pIiA9ICLpgbjmip7oqrLpoYxcXDEiLCAiQ2hvaWNlIHRhc2sgKFsxLTVdKSIgPSAi6YG45oqe6Kqy6aGMXFwxIikpKSAlPiUNCiAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkNCmtuaXRyOjprYWJsZSjlrp/pqJMz5p2h5Lu25Yil5qiZ5pysLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEMyMu+8muWun+mokzPjga7mnaHku7bliKXmqJnmnKzmuJvlsJEiKQ0KDQrlrp/pqJMz5pON5L2c56K66KqNIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9tYW5pcHVsYXRpb25fY2hlY2suY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIHJlc3BvbnNlID0gIuWbnuetlCIsIHN0YXR1cyA9ICLliKTlrpoiLCBuID0gIk4iKSkgJT4lDQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MyIpLCBkcGx5cjo6YWNyb3NzKGRwbHlyOjpldmVyeXRoaW5nKCksIH4gdGlkeXI6OnJlcGxhY2VfbmEoYXMuY2hhcmFjdGVyKC54KSwgIuKAlCIpKSkNCmtuaXRyOjprYWJsZSjlrp/pqJMz5pON5L2c56K66KqNLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEMyM++8muWun+mokzPjga7pgbjmip7ogqLmlbDmk43kvZznorroqo0iKQ0KDQrlrp/pqJMz5oyH56S66aCF55uuIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9hdHRlbnRpb25fY2hlY2suY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCByZXNwb25zZSA9ICLlm57nrZTjgrPjg7zjg4kiLCBzdGF0dXMgPSAi5Yik5a6aIiwgbiA9ICJOIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmV2ZXJ5dGhpbmcoKSwgfiB0aWR5cjo6cmVwbGFjZV9uYShhcy5jaGFyYWN0ZXIoLngpLCAi4oCUIikpKQ0Ka25pdHI6OmthYmxlKOWun+mokzPmjIfnpLrpoIXnm64sIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoQzI077ya5a6f6aiTM+OBruaMh+ekuumgheebriIpDQpgYGANCg0KIyBELiDmnKzmloflm7Pjga7lho3nj74NCg0K44GT44Gu56+A44Gu5Zuz77yI6KGo77yJ55Wq5Y+344Gv5pys5paH44Go5LiA6Ie044GX44Gf44KC44Gu44Gn44GC44KL44CC5pys5paH44Gu5YiG5p6Q57WQ5p6c44Gn55So44GE44KL5Zuz44Gv5ZuzNOOBi+OCieWbsznjgb7jgafjgafjgYLjgorjgIHlrp/pqJMy44GuQU1DReOBr+acrOaWh+Wbs+OBq+OBr+ihqOekuuOBm+OBmuOAgeijnOmBukXjgavmjrLnpLrjgZXjgozjgabjgYTjgovjgIINCg0KIyMg5ZuzNO+8muWun+mokzHvvIgyMDIz5bm077yJ44Gu5YWx5aSJ6YeP6Kq/5pW05riI44G/QU1DRQ0KDQpgYGB7ciBjLWZpZzQsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5ZuzNOODh+ODvOOCvyA8LSBzdHVkeTFfZW52JGFtY2VfcGxvdF9kZl9jb3ZfZmFjZXQNCuWbszQgPC0gZ2dwbG90Mjo6Z2dwbG90KA0KICDlm7M044OH44O844K/LA0KICBnZ3Bsb3QyOjphZXMoeCA9IGVzdGltYXRlX3BwLCB5ID0gbGFiZWwsIHNoYXBlID0gcGFydHlfbiwgbGluZXR5cGUgPSBwYXJ0eV9uLCBncm91cCA9IHBhcnR5X24pDQopICsNCiAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC40NSwgY29sb3IgPSAiZ3JleTM1IikgKw0KICBnZ3Bsb3QyOjpnZW9tX2Vycm9yYmFyaCgNCiAgICBnZ3Bsb3QyOjphZXMoeG1pbiA9IGNvbmYubG93X3BwLCB4bWF4ID0gY29uZi5oaWdoX3BwKSwNCiAgICBwb3NpdGlvbiA9IGdncGxvdDI6OnBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksIGhlaWdodCA9IDAuMTYsIGxpbmV3aWR0aCA9IDAuNTUNCiAgKSArDQogIGdncGxvdDI6Omdlb21fcG9pbnQocG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLCBzaXplID0gMi41LCBmaWxsID0gIndoaXRlIiwgc3Ryb2tlID0gMC44KSArDQogIGdncGxvdDI6OmZhY2V0X2dyaWQoYXR0cmlidXRlX2ZhY2V0IH4gLiwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlID0gImZyZWVfeSIsIHN3aXRjaCA9ICJ5IikgKw0KICBnZ3Bsb3QyOjpzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygiMuaUv+WFmiIgPSAxNiwgIjPmlL/lhZoiID0gMTcsICI05pS/5YWaIiA9IDE1LCAiNeaUv+WFmiIgPSAxKSkgKw0KICBnZ3Bsb3QyOjpzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygiMuaUv+WFmiIgPSAic29saWQiLCAiM+aUv+WFmiIgPSAiZGFzaGVkIiwgIjTmlL/lhZoiID0gImRvdHRlZCIsICI15pS/5YWaIiA9ICJkb3RkYXNoIikpICsNCiAgZ2dwbG90Mjo6bGFicyh4ID0gIumBuOaKnueiuueOh+OBruWkieWMliIsIHkgPSBOVUxMLCBzaGFwZSA9ICLmlL/lhZrmlbDmnaHku7YiLCBsaW5ldHlwZSA9ICLmlL/lhZrmlbDmnaHku7YiKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSArDQogIGdncGxvdDI6OnRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCBwYW5lbC5ncmlkLm1ham9yLnkgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkpDQrlm7M0DQoNCuihqEQxIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MSIsICJ0YWJsZV9hbWNlX2NvdmFyaWF0ZV9hZGp1c3RlZC5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0gcGFzdGUwKHN0cmluZ3I6OnN0cl9yZW1vdmUo5p2h5Lu2LCAi5p2h5Lu2JCIpLCAi5p2h5Lu2IikpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQxKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahEMe+8muWbszTjgavlr77lv5zjgZnjgovlhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFIikNCmBgYA0KDQojIyDlm7M177ya5a6f6aiTMe+8iDIwMjPlubTvvInjga7mlL/lhZrjg7vntYzmuIjmiYvjgYzjgYvjgorjga7ph43opoHluqbjgajnm7jlr77mr5Tph40NCg0KYGBge3IgYy1maWc1LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuWbszXph43opoHluqbjg4fjg7zjgr8gPC0gc3R1ZHkxX2VudiRyZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhDQrlm7M155u45a++5q+U6YeN44OH44O844K/IDwtIHN0dWR5MV9lbnYkcmVsYXRpdmVfcGFuZWxfYl9kYXRhDQrlm7M144OR44ON44OrQSA8LSBzdHVkeTFfZW52JHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkDQrlm7M144OR44ON44OrQiA8LSBzdHVkeTFfZW52JHJlbGF0aXZlX3BhbmVsX2MNCuWbszUgPC0gKOWbszXjg5Hjg43jg6tBIHwg5ZuzNeODkeODjeODq0IpICsgcGF0Y2h3b3JrOjpwbG90X2xheW91dCh3aWR0aHMgPSBjKDEsIDEpKQ0K5ZuzNQ0KDQrooahEMiA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfbWFyZ2luYWxfbWVhbnMuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLCBsZXZlbCA9ICLmsLTmupYiKSkgJT4lDQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MSIpLCDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4o5bGe5oCnKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQy77ya6ZmQ55WM5bmz5Z2HIikNCg0K6KGoRDMgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkxIiwgInRhYmxlX2F0dHJpYnV0ZV9pbXBvcnRhbmNlLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBhdHRyaWJ1dGUgPSAi5bGe5oCnIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTEiKSwg5bGe5oCnID0g5bGe5oCn5pel5pys6KqeKOWxnuaApykpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQzKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahEM++8muWxnuaAp+mHjeimgeW6piIpDQoNCuihqEQ0IDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MSIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2Iiwgc3RhdGlzdGljID0gIuaMh+aomSIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkxIiksIOaMh+aomSA9IOe1seioiOmHj+aXpeacrOiqnijmjIfmqJksICJzdHVkeTEiKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDQpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQ077ya5pS/5YWa44O757WM5riI5omL44GM44GL44KK44Gu6YeN6KaB5bqm44Go55u45a++5q+U6YeNIikNCmBgYA0KDQojIyDlm7M277ya5a6f6aiTMu+8iDIwMjblubTvvInjga7mlL/lhZrjg7vntYzmuIjmiYvjgYzjgYvjgorjga7ph43opoHluqbjgajnm7jlr77mr5Tph40NCg0KYGBge3IgYy1maWc2LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuWbszbph43opoHluqbjg4fjg7zjgr8gPC0gc3R1ZHkyX2VudiRyZWxhdGl2ZV9wYW5lbF9hZGp1c3RlZF9kYXRhDQrlm7M255u45a++5q+U6YeN44OH44O844K/IDwtIHN0dWR5Ml9lbnYkcmVsYXRpdmVfcGFuZWxfYl9kYXRhDQrlm7M244OR44ON44OrQSA8LSBzdHVkeTJfZW52JHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkDQrlm7M244OR44ON44OrQiA8LSBzdHVkeTJfZW52JHJlbGF0aXZlX3BhbmVsX2MNCuWbszYgPC0gKOWbszbjg5Hjg43jg6tBIHwg5ZuzNuODkeODjeODq0IpICsgcGF0Y2h3b3JrOjpwbG90X2xheW91dCh3aWR0aHMgPSBjKDEsIDEpKQ0K5ZuzNg0KDQrooahENSA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTIiLCAidGFibGVfbWFyZ2luYWxfbWVhbnMuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLCBsZXZlbCA9ICLmsLTmupYiKSkgJT4lDQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MiIpLCDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4o5bGe5oCnKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDUpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQ177ya6ZmQ55WM5bmz5Z2HIikNCg0K6KGoRDYgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkyIiwgInRhYmxlX2F0dHJpYnV0ZV9pbXBvcnRhbmNlLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBhdHRyaWJ1dGUgPSAi5bGe5oCnIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTIiKSwg5bGe5oCnID0g5bGe5oCn5pel5pys6KqeKOWxnuaApykpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQ2KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahENu+8muWxnuaAp+mHjeimgeW6piIpDQoNCuihqEQ3IDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2Iiwgc3RhdGlzdGljID0gIuaMh+aomSIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkyIiksIOaMh+aomSA9IOe1seioiOmHj+aXpeacrOiqnijmjIfmqJksICJzdHVkeTIiKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDcpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQ377ya5pS/5YWa44O757WM5riI5omL44GM44GL44KK44Gu6YeN6KaB5bqm44Go55u45a++5q+U6YeNIikNCmBgYA0KDQojIyDlm7M377ya5a6f6aiTM++8iDIwMjblubTvvInjga7lhbHlpInph4/oqr/mlbTmuIjjgb9BTUNFDQoNCmBgYHtyIGMtZmlnNywgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrlm7M344OH44O844K/IDwtIHN0dWR5M19lbnYkYW1jZV9wbG90X2Nvdg0K5ZuzNyA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoDQogIOWbszfjg4fjg7zjgr8sDQogIGdncGxvdDI6OmFlcyh4ID0gZXN0aW1hdGVfcHAsIHkgPSBsYWJlbCwgc2hhcGUgPSBwYXJ0eV9uLCBsaW5ldHlwZSA9IHBhcnR5X24sIGdyb3VwID0gcGFydHlfbikNCikgKw0KICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ld2lkdGggPSAwLjQ1LCBjb2xvciA9ICJncmV5MzUiKSArDQogIGdncGxvdDI6Omdlb21fZXJyb3JiYXJoKA0KICAgIGdncGxvdDI6OmFlcyh4bWluID0gY29uZi5sb3dfcHAsIHhtYXggPSBjb25mLmhpZ2hfcHApLA0KICAgIHBvc2l0aW9uID0gZ2dwbG90Mjo6cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwgaGVpZ2h0ID0gMC4xNiwgbGluZXdpZHRoID0gMC41NQ0KICApICsNCiAgZ2dwbG90Mjo6Z2VvbV9wb2ludChwb3NpdGlvbiA9IGdncGxvdDI6OnBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksIHNpemUgPSAyLjUsIGZpbGwgPSAid2hpdGUiLCBzdHJva2UgPSAwLjgpICsNCiAgZ2dwbG90Mjo6ZmFjZXRfZ3JpZChhdHRyaWJ1dGUgfiAuLCBzY2FsZXMgPSAiZnJlZV95Iiwgc3BhY2UgPSAiZnJlZV95Iiwgc3dpdGNoID0gInkiKSArDQogIGdncGxvdDI6OnNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKCIy6YG45oqe6IKiIiA9IDE2LCAiM+mBuOaKnuiCoiIgPSAxNywgIjTpgbjmip7ogqIiID0gMTUsICI16YG45oqe6IKiIiA9IDEpKSArDQogIGdncGxvdDI6OnNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKCIy6YG45oqe6IKiIiA9ICJzb2xpZCIsICIz6YG45oqe6IKiIiA9ICJkYXNoZWQiLCAiNOmBuOaKnuiCoiIgPSAiZG90dGVkIiwgIjXpgbjmip7ogqIiID0gImRvdGRhc2giKSkgKw0KICBnZ3Bsb3QyOjpsYWJzKHggPSAi6YG45oqe56K6546H44Gu5aSJ5YyWIiwgeSA9IE5VTEwsIHNoYXBlID0gIumBuOaKnuiCouaVsCIsIGxpbmV0eXBlID0gIumBuOaKnuiCouaVsCIpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpICsNCiAgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIHBhbmVsLmdyaWQubWFqb3IueSA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkNCuWbszcNCg0K6KGoRDggPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSBwYXN0ZTAoc3RyaW5ncjo6c3RyX3JlbW92ZSjmnaHku7YsICLmnaHku7YkIiksICLmnaHku7YiKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDgpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIuihqEQ477ya5ZuzN+OBq+WvvuW/nOOBmeOCi+WFseWkiemHj+iqv+aVtOa4iOOBv0FNQ0UiKQ0KYGBgDQoNCiMjIOWbszjvvJrlrp/pqJMz77yIMjAyNuW5tO+8ieOBruaUv+WFmuWQjeODu+e1jOa4iOaJi+OBjOOBi+OCiuOBrumHjeimgeW6puOBqOebuOWvvuavlOmHjQ0KDQpgYGB7ciBjLWZpZzgsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5ZuzOOmHjeimgeW6puODh+ODvOOCvyA8LSBzdHVkeTNfZW52JHJlbGF0aXZlX3BhbmVsX2FkanVzdGVkX2RhdGENCuWbszjnm7jlr77mr5Tph43jg4fjg7zjgr8gPC0gc3R1ZHkzX2VudiRyZWxhdGl2ZV9wYW5lbF9iX2RhdGENCuWbszjjg5Hjg43jg6tBIDwtIHN0dWR5M19lbnYkcmVsYXRpdmVfcGFuZWxfYWRqdXN0ZWQNCuWbszjjg5Hjg43jg6tCIDwtIHN0dWR5M19lbnYkcmVsYXRpdmVfcGFuZWxfYw0K5ZuzOCA8LSAo5ZuzOOODkeODjeODq0EgfCDlm7M444OR44ON44OrQikgKyBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMSwgMSkpDQrlm7M4DQoNCuihqEQ5IDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9tYXJnaW5hbF9tZWFucy5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2IiwgYXR0cmlidXRlID0gIuWxnuaApyIsIGxldmVsID0gIuawtOa6liIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkzIiksIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnijlsZ7mgKcpKQ0Ka25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahEOSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoRDnvvJrpmZDnlYzlubPlnYciKQ0KDQrooahEMTAgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX2F0dHJpYnV0ZV9pbXBvcnRhbmNlLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6OnJlbmFtZV93aXRoKH4gZHBseXI6OnJlY29kZSgueCwgcGFydHlfbiA9ICLmnaHku7YiLCBhdHRyaWJ1dGUgPSAi5bGe5oCnIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IOadoeS7tuaXpeacrOiqnijmnaHku7YsICJzdHVkeTMiKSwg5bGe5oCnID0g5bGe5oCn5pel5pys6KqeKOWxnuaApykpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEQxMCksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoRDEw77ya5bGe5oCn6YeN6KaB5bqmIikNCg0K6KGoRDExIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9jdWVfaW1wb3J0YW5jZS5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2Iiwgc3RhdGlzdGljID0gIuaMh+aomSIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkzIiksIOaMh+aomSA9IOe1seioiOmHj+aXpeacrOiqnijmjIfmqJksICJzdHVkeTMiKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRDExKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICLooahEMTHvvJrmlL/lhZrlkI3jg7vntYzmuIjmiYvjgYzjgYvjgorjga7ph43opoHluqbjgajnm7jlr77mr5Tph40iKQ0KYGBgDQoNCiMjIOWbsznvvJrlrp/pqJMz77yIMjAyNuW5tO+8ieOBruaUr+aMgeaUv+WFmuOBqOaPkOekuuaUv+WFmuWQjeOBruS4gOiHtOWKueaenA0KDQpgYGB7ciBjLWZpZzksIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5ZuzOSA8LSBzdHVkeTNfZW52JHBfcGFydHlfbWF0Y2gNCuWbszkNCg0K6KGoRDEy5YWDIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MyIsICJ0YWJsZV9wYXJ0eV9tYXRjaC5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkNCg0K6KGoRDEy5p2h5Lu25YiXIDwtIGludGVyc2VjdChjKCLpgbjmip7ogqLmlbAiLCAi5p2h5Lu2IiwgInBhcnR5X24iKSwgbmFtZXMo6KGoRDEy5YWDKSkNCmlmIChsZW5ndGgo6KGoRDEy5p2h5Lu25YiXKSA9PSAwKSBzdG9wKCJDaGVjayBjb25kaXRpb24gY29sdW1uIikNCuihqEQxMuadoeS7tuWIlyA8LSDooahEMTLmnaHku7bliJdbWzFdXQ0KDQppZiAoISLlm57nrZTogIXmlbAiICVpbiUgbmFtZXMo6KGoRDEy5YWDKSkgew0KICDooahEMTLlhYMk5Zue562U6ICF5pWwIDwtIE5BX2NoYXJhY3Rlcl8NCn0NCg0K5a6f6aiTM+adoeS7tuS6uuaVsCA8LSBzdHVkeTNfZW52JGNvbmpvaW50X2FsbF9tICU+JQ0KICBkcGx5cjo6ZGlzdGluY3QoSUQsIHBhcnR5X24pICU+JQ0KICBkcGx5cjo6Y291bnQocGFydHlfbiwgbmFtZSA9ICLlm57nrZTogIXmlbDoo5zlrowiKQ0KDQrooahEMTIgPC0g6KGoRDEy5YWDICU+JQ0KICBkcGx5cjo6bXV0YXRlKOadoeS7tuaVsCA9IOaVsOWApOWIlyguZGF0YVtb6KGoRDEy5p2h5Lu25YiXXV0pKSAlPiUNCiAgZHBseXI6OnNlbGVjdCgtZHBseXI6OmFsbF9vZijooahEMTLmnaHku7bliJcpKSAlPiUNCiAgZHBseXI6OmxlZnRfam9pbijlrp/pqJMz5p2h5Lu25Lq65pWwLCBieSA9IGMoIuadoeS7tuaVsCIgPSAicGFydHlfbiIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDlm57nrZTogIXmlbAgPSBkcGx5cjo6Y29hbGVzY2Uo5pWw5YCk5YiXKOWbnuetlOiAheaVsCksIOWbnuetlOiAheaVsOijnOWujCksDQogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tuaVsCwgInN0dWR5MyIpDQogICkgJT4lDQogIGRwbHlyOjpzZWxlY3QoLeadoeS7tuaVsCwgLeWbnuetlOiAheaVsOijnOWujCkgJT4lDQogIGRwbHlyOjpyZWxvY2F0ZSjmnaHku7YsIC5hZnRlciA9IOWvvuixoSkNCg0Ka25pdHI6OmthYmxlKA0KICDooajml6XmnKzoqp4o6KGoRDEyKSwNCiAgZm9ybWF0ID0gImh0bWwiLA0KICByb3cubmFtZXMgPSBGQUxTRSwNCiAgY2FwdGlvbiA9ICLooahEMTLvvJrmlK/mjIHmlL/lhZrjgajmj5DnpLrmlL/lhZrlkI3jga7kuIDoh7TlirnmnpwiDQopDQpgYGANCg0KIyBFLiDlrp/pqJMx77yIMjAyM+W5tO+8ieOBruijnOi2s+WIhuaekA0KDQojIyDoo5zlm7NFMe+8muWFseWkiemHj+OCkuWQq+OCgeOBquOBhEFNQ0UNCg0KYGBge3IgZDEsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6KOc5ZuzRTHjg4fjg7zjgr8gPC0gc3R1ZHkxX2VudiRhbWNlX3Bsb3RfZGZfbm9jb3ZfZmFjZXQNCuijnOWbs0UxIDwtIHN0dWR5MV9lbnYkcF9hbWNlX2ZhY2V0X25vY292DQroo5zlm7NFMQ0KDQrooahFMSA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfYW1jZV91bmFkanVzdGVkLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSBwYXN0ZTAoc3RyaW5ncjo6c3RyX3JlbW92ZSjmnaHku7YsICLmnaHku7YkIiksICLmnaHku7YiKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRTEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOijnOWbs0Uy77yaMuaUv+WFmuadoeS7tuOBqOOBruW3rg0KDQpgYGB7ciBkMiwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQroo5zlm7NFMuODh+ODvOOCvyA8LSBzdHVkeTFfZW52JGludGVyYWN0aW9uX3Bsb3RfZGYNCuijnOWbs0UyIDwtIHN0dWR5MV9lbnYkcF9pbnRlcmFjdGlvbg0K6KOc5ZuzRTINCg0K6KGoRTIgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkxIiwgInRhYmxlX2FtY2VfaW50ZXJhY3Rpb24uY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBhdHRyaWJ1dGUgPSAi5bGe5oCnIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmFueV9vZigi5bGe5oCnIiksIOWxnuaAp+aXpeacrOiqnikpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEUyKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIyDoo5zlm7NFM++8muadoeS7tuS7mOOBjeODreOCuOODg+ODiA0KDQpgYGB7ciBkMywgZWNobz1UUlVFLCBldmFsPVRSVUV9DQroo5zlm7NFMyA8LSBzdHVkeTFfZW52JHBfY2xvZ2l0X29yDQroo5zlm7NFMw0KDQrooahFMyA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTEiLCAidGFibGVfY29uZGl0aW9uYWxfbG9naXQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLCBsYWJlbCA9ICLmsLTmupYiKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoDQogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MSIpLA0KICAgIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnijlsZ7mgKcpDQogICkgJT4lDQogIGRwbHlyOjpzZWxlY3QoLWRwbHlyOjphbnlfb2YoYygidGVybSIsICJ2YXJpYWJsZSIsICJwb2xpY3lfcG9zaXRpb24iLCAiZ292ZXJubWVudF9zdGF0dXMiKSkpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEUzKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIEYuIOWun+mokzLvvIgyMDI25bm077yJ44Gu6KOc6Laz5YiG5p6QDQoNCuacrOaWh+OBp+OBr+Wun+mokzLjga5BTUNF44Gu5pa55ZCR5oCn44KS6KiY6L+w44GX44CB6Kmz57Sw44KS6KOc6YG644Gr5Zue44GX44Gm44GE44KL44Gf44KB44CB5YWx5aSJ6YeP6Kq/5pW05riI44G/QU1DReOCkuijnOWbs0Yx44Go44GX44Gm5pyA5Yid44Gr56S644GZ44CCDQoNCiMjIOijnOWbs0Yx77ya5YWx5aSJ6YeP6Kq/5pW05riI44G/QU1DRQ0KDQpgYGB7ciBlMSwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQroo5zlm7NGMeODh+ODvOOCvyA8LSBzdHVkeTJfZW52JGFtY2VfcGxvdF9kZl9jb3ZfZmFjZXQNCuijnOWbs0YxIDwtIHN0dWR5Ml9lbnYkcF9hbWNlX2Nvdl9mYWNldA0K6KOc5ZuzRjENCg0K6KGoRjEgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkyIiwgInRhYmxlX2FtY2VfY292YXJpYXRlX2FkanVzdGVkLmNzdiIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSBwYXN0ZTAoc3RyaW5ncjo6c3RyX3JlbW92ZSjmnaHku7YsICLmnaHku7YkIiksICLmnaHku7YiKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRjEpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOijnOWbs0Yy77ya5YWx5aSJ6YeP44KS5ZCr44KB44Gq44GEQU1DRQ0KDQpgYGB7ciBlMiwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQroo5zlm7NGMuODh+ODvOOCvyA8LSBzdHVkeTJfZW52JGFtY2VfcGxvdF9kZl9ub2Nvdl9mYWNldA0K6KOc5ZuzRjIgPC0gc3R1ZHkyX2VudiRwX2FtY2VfZmFjZXRfbm9jb3YNCuijnOWbs0YyDQoNCuihqEYyIDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9hbWNlX3VuYWRqdXN0ZWQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOadoeS7tiA9IHBhc3RlMChzdHJpbmdyOjpzdHJfcmVtb3ZlKOadoeS7tiwgIuadoeS7tiQiKSwgIuadoeS7tiIpKQ0Ka25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahGMiksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMg6KOc5ZuzRjPvvJoy5pS/5YWa5p2h5Lu244Go44Gu5beuDQoNCmBgYHtyIGUzLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuijnOWbs0Yz44OH44O844K/IDwtIHN0dWR5Ml9lbnYkaW50ZXJhY3Rpb25fcGxvdF9kZg0K6KOc5ZuzRjMgPC0gc3R1ZHkyX2VudiRwX2ludGVyYWN0aW9uDQroo5zlm7NGMw0KDQrooahGMyA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTIiLCAidGFibGVfYW1jZV9pbnRlcmFjdGlvbi5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6YW55X29mKCLlsZ7mgKciKSwg5bGe5oCn5pel5pys6KqeKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRjMpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOijnOWbs0Y077ya5p2h5Lu25LuY44GN44Ot44K444OD44OIDQoNCmBgYHtyIGU0LCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuijnOWbs0Y0IDwtIHN0dWR5Ml9lbnYkcF9jbG9naXRfb3INCuijnOWbs0Y0DQoNCuihqEY0IDwtIHJlYWRyOjpyZWFkX2NzdihzdHVkeV9jc3YoInN0dWR5MiIsICJ0YWJsZV9jb25kaXRpb25hbF9sb2dpdC5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIHBhcnR5X24gPSAi5p2h5Lu2IiwgYXR0cmlidXRlID0gIuWxnuaApyIsIGxhYmVsID0gIuawtOa6liIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSjmnaHku7YgPSDmnaHku7bml6XmnKzoqp4o5p2h5Lu2LCAic3R1ZHkyIiksIOWxnuaApyA9IOWxnuaAp+aXpeacrOiqnijlsZ7mgKcpKSAlPiUNCiAgZHBseXI6OnNlbGVjdCgtZHBseXI6OmFueV9vZihjKCJ0ZXJtIiwgInZhcmlhYmxlIiwgInBvbGljeV9wb3NpdGlvbiIsICJnb3Zlcm5tZW50X3N0YXR1cyIpKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRjQpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMgRy4g5a6f6aiTM++8iDIwMjblubTvvInjga7oo5zotrPliIbmnpANCg0KIyMg6KOc5ZuzRzHvvJrlhbHlpInph4/jgpLlkKvjgoHjgarjgYRBTUNFDQoNCmBgYHtyIGYxLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuijnOWbs0cx44OH44O844K/IDwtIHN0dWR5M19lbnYkYW1jZV9wbG90X25vY292DQroo5zlm7NHMSA8LSBzdHVkeTNfZW52JHBfYW1jZV9ub2Nvdg0K6KOc5ZuzRzENCg0K6KGoRzEgPC0gcmVhZHI6OnJlYWRfY3N2KHN0dWR5X2Nzdigic3R1ZHkzIiwgInRhYmxlX2FtY2VfdW5hZGp1c3RlZC5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0gcGFzdGUwKHN0cmluZ3I6OnN0cl9yZW1vdmUo5p2h5Lu2LCAi5p2h5Lu2JCIpLCAi5p2h5Lu2IikpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEcxKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIyDoo5zlm7NHMu+8mjLpgbjmip7ogqLmnaHku7bjgajjga7lt64NCg0KYGBge3IgZjIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6KOc5ZuzRzIgPC0gc3R1ZHkzX2VudiRwX2ludGVyYWN0aW9uDQroo5zlm7NHMg0KDQrooahHMiA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTMiLCAidGFibGVfYW1jZV9pbnRlcmFjdGlvbi5jc3YiKSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjpyZW5hbWVfd2l0aCh+IGRwbHlyOjpyZWNvZGUoLngsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcyhkcGx5cjo6YW55X29mKCLlsZ7mgKciKSwg5bGe5oCn5pel5pys6KqeKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRzIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOijnOWbs0cz77yaQU1DReOBrue3muW9ouODiOODrOODs+ODiQ0KDQpgYGB7ciBmMywgZWNobz1UUlVFLCBldmFsPVRSVUV9DQroo5zlm7NHMyA8LSBzdHVkeTNfZW52JHBfbGluZWFyX3RyZW5kDQroo5zlm7NHMw0KDQrooahHMyA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTMiLCAidGFibGVfYW1jZV9saW5lYXJfdHJlbmQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBhdHRyaWJ1dGUgPSAi5bGe5oCnIiwgbGFiZWwgPSAi5rC05rqWIikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoZHBseXI6OmFueV9vZigi5bGe5oCnIiksIOWxnuaAp+aXpeacrOiqnikpICU+JQ0KICBkcGx5cjo6c2VsZWN0KC1kcGx5cjo6YW55X29mKGMoInRlcm0iLCAidmFyaWFibGUiKSkpDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEczKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIyDoo5zlm7NHNO+8muadoeS7tuS7mOOBjeODreOCuOODg+ODiA0KDQpgYGB7ciBmNCwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQroo5zlm7NHNCA8LSBzdHVkeTNfZW52JHBfY2xvZ2l0X29yDQroo5zlm7NHNA0KDQrooahHNCA8LSByZWFkcjo6cmVhZF9jc3Yoc3R1ZHlfY3N2KCJzdHVkeTMiLCAidGFibGVfY29uZGl0aW9uYWxfbG9naXQuY3N2IiksIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JQ0KICBkcGx5cjo6cmVuYW1lX3dpdGgofiBkcGx5cjo6cmVjb2RlKC54LCBwYXJ0eV9uID0gIuadoeS7tiIsIGF0dHJpYnV0ZSA9ICLlsZ7mgKciLCBsYWJlbCA9ICLmsLTmupYiKSkgJT4lDQogIGRwbHlyOjptdXRhdGUo5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKOadoeS7tiwgInN0dWR5MyIpLCDlsZ7mgKcgPSDlsZ7mgKfml6XmnKzoqp4o5bGe5oCnKSkgJT4lDQogIGRwbHlyOjpzZWxlY3QoLWRwbHlyOjphbnlfb2YoYygidGVybSIsICJ2YXJpYWJsZSIpKSkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoRzQpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMgSC4g5pS/5YWa5pSv5oyB44Gr44KI44KL55Ww6LOq5oCnDQoNCuaUr+aMgeaUv+WFmuWIpUFNQ0Xjgafjga/jgIHlkITmnaHku7bjgavoqbLlvZPjgZnjgovlm57nrZTogIXmlbDjgYw0MOS6uuacqua6gOOBruOCu+ODq+OBr+aOqOWumuWvvuixoeWkluOBqOOBl+OBpuOBhOOCi+OAguOBl+OBn+OBjOOBo+OBpuOAgeS7peS4i+OBp+OBryBgaW5zdWZmaWNpZW50X2NlbGxfbmAg44KSTkHjga7jgb7jgb7ooajnpLrjgZvjgZrjgIHmjqjlrprlj6/og73jgafjgYLjgaPjgZ/mlK/mjIHmlL/lhZrDl+mBuOaKnuiCouaVsOadoeS7tuOBruOBv+OCkuaOsui8ieOBmeOCi+OAgg0KDQojIyDoo5zlm7NIMe+8muaUr+aMgeaUv+WFmuWIpUFNQ0UNCg0K6KOc5ZuzSDHjga/jgIHmlK/mjIHmlL/lhZrjgavjgojjgotBTUNF44Gu55Ww6LOq5oCn44KS5a6f6aiT44GU44Go44Gr56S644GZ44CC5Y+v6Kqt5oCn44Gu44Gf44KB44CB57WQ5p6c44Gv5a6f6aiTMeODuzLjg7sz44Gr5YiG44GR44CBKiox44Gk44Gu44OR44ON44Or44KSMeOBpOOBruaUr+aMgeaUv+WFmuOBq+WvvuW/nOOBleOBm+OCiyoq44CC57im6Lu444Gr44Gv5bGe5oCn5ZCN44Go5rC05rqW5ZCN44KS5LiA5L2T44Go44GX44Gm6KGo56S644GX44CB5ZCM5LiA44Gu5pSv5oyB5pS/5YWa44Gr44Gk44GE44Gm5ZCE5bGe5oCn44O75rC05rqW44Gu5o6o5a6a57WQ5p6c44KS5LiK44GL44KJ6aCG44Gr56K66KqN44Gn44GN44KL44KI44GG44Gr44GX44Gf44CC54K544GvQU1DReOAgeaoque3muOBrzk1JeS/oemgvOWMuumWk+OCkuekuuOBl+OAgeeCueOBruW9ouOBp+mBuOaKnuiCouaVsOadoeS7tuOCkuWMuuWIpeOBmeOCi+OAgg0KDQrlr77lv5zooajjgoLlrp/pqJPjgZTjgajjgavliIbjgZHjgIHpgbjmip7ogqLmlbDmnaHku7bjgpLliJfmlrnlkJHjgavlsZXplovjgZnjgovjgILlkITjgrvjg6vjga8gKipBTUNFIFs5NSUgQ0ld77yIcHDvvIkqKiDjgpLnpLrjgZfjgIHlm57nrZTogIXmlbDjga/mlK/mjIHmlL/lhZrDl+mBuOaKnuiCouaVsOadoeS7tuOBlOOBqOOBruWwj+ihqOOBqOOBl+OBpuWIpeOBq+ekuuOBmeOAguOBk+OBruW9ouW8j+OBq+OCiOOCiuOAgeWQjOOBmOWxnuaAp+ODu+awtOa6luOBq+OBpOOBhOOBpjLjg7sz44O7NOODuzXpgbjmip7ogqLmnaHku7bjgpLmqKrmlrnlkJHjgavnm7TmjqXmr5TovIPjgafjgY3jgovjgILooajnpLrooajjgafjga/mg4XloLHjgpLngrnmjqjlrprlgKTjgag5NSXkv6HpoLzljLrplpPjgavpm4bntITjgZfjgIFw5YCk44KS5ZCr44KA5a6M5YWo44Gq5L+C5pWw6KGo44Gv5ZCE5a6f6aiT44GuQ1NW5Ye65YqbIGB0YWJsZV9wYXJ0eV9zdXBwb3J0X2FtY2UuY3N2YCDjgavkv53lrZjjgZnjgovjgIINCg0KYGBge3IgZzEtcHJlcGFyZSwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrmlK/mjIFBTUNF5LiA6KanIDwtIGRwbHlyOjpiaW5kX3Jvd3MoDQogIHBhcnR5X3N1cHBvcnRfYW1jZV9yZXN1bHRzJHN0dWR5MSRzdWJncm91cF9jb2VmZmljaWVudHMgJT4lDQogICAgZHBseXI6Om11dGF0ZSjlrp/pqJMgPSAi5a6f6aiTMe+8iDIwMjPlubTvvIkiLCBzdHVkeV9pZCA9ICJzdHVkeTEiKSwNCiAgcGFydHlfc3VwcG9ydF9hbWNlX3Jlc3VsdHMkc3R1ZHkyJHN1Ymdyb3VwX2NvZWZmaWNpZW50cyAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKOWun+mokyA9ICLlrp/pqJMy77yIMjAyNuW5tO+8iSIsIHN0dWR5X2lkID0gInN0dWR5MiIpLA0KICBwYXJ0eV9zdXBwb3J0X2FtY2VfcmVzdWx0cyRzdHVkeTMkc3ViZ3JvdXBfY29lZmZpY2llbnRzICU+JQ0KICAgIGRwbHlyOjptdXRhdGUo5a6f6aiTID0gIuWun+mokzPvvIgyMDI25bm077yJIiwgc3R1ZHlfaWQgPSAic3R1ZHkzIikNCikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoDQogICAgc3RhdHVzID09ICJlc3RpbWF0ZWQiLA0KICAgICFpcy5uYSh0ZXJtKSwNCiAgICB0ZXJtICE9ICIoSW50ZXJjZXB0KSIsDQogICAgIWlzLm5hKGVzdGltYXRlKQ0KICApICU+JQ0KICBkcGx5cjo6bXV0YXRlKA0KICAgIOWxnuaAp+ihqOekuiA9IOWxnuaAp+aXpeacrOiqnihhdHRyaWJ1dGUpLA0KICAgIOadoeS7tuihqOekuiA9IHB1cnJyOjptYXAyX2NocihwYXJ0eV9uLCBzdHVkeV9pZCwg5p2h5Lu25pel5pys6KqeKSwNCiAgICDmsLTmupbooajnpLogPSDmsLTmupbml6XmnKzoqp4odGVybSwgbGFiZWwsIGF0dHJpYnV0ZSksDQogICAg6KGo56S66aCF55uuID0gcGFzdGUwKOWxnuaAp+ihqOekuiwgIu+8miIsIOawtOa6luihqOekuikNCiAgKQ0KDQroo5zlm7NIMeS9nOaIkCA8LSBmdW5jdGlvbijmj4/nlLvjg4fjg7zjgr8sIOWun+mok+WQjSkgew0KICDpoIXnm67poIYgPC0g5o+P55S744OH44O844K/ICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdCjlsZ7mgKfooajnpLosIOawtOa6luihqOekuiwg6KGo56S66aCF55uuKSAlPiUNCiAgICBkcGx5cjo6cHVsbCjooajnpLrpoIXnm64pDQoNCiAg5p2h5Lu26aCGIDwtIOaPj+eUu+ODh+ODvOOCvyAlPiUNCiAgICBkcGx5cjo6ZGlzdGluY3QocGFydHlfbiwg5p2h5Lu26KGo56S6KSAlPiUNCiAgICBkcGx5cjo6YXJyYW5nZShwYXJ0eV9uKSAlPiUNCiAgICBkcGx5cjo6cHVsbCjmnaHku7booajnpLopDQoNCiAg5o+P55S744OH44O844K/IDwtIOaPj+eUu+ODh+ODvOOCvyAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKA0KICAgICAg6KGo56S66aCF55uuID0gZmFjdG9yKOihqOekuumgheebriwgbGV2ZWxzID0gcmV2KOmgheebrumghikpLA0KICAgICAg5p2h5Lu26KGo56S6ID0gZmFjdG9yKOadoeS7tuihqOekuiwgbGV2ZWxzID0g5p2h5Lu26aCGKQ0KICAgICkNCg0KICBkb2RnZSA8LSBnZ3Bsb3QyOjpwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNTIpDQoNCiAgZ2dwbG90Mjo6Z2dwbG90KA0KICAgIOaPj+eUu+ODh+ODvOOCvywNCiAgICBnZ3Bsb3QyOjphZXMoDQogICAgICB4ID0gZXN0aW1hdGVfcHAsDQogICAgICB5ID0g6KGo56S66aCF55uuLA0KICAgICAgc2hhcGUgPSDmnaHku7booajnpLoNCiAgICApDQogICkgKw0KICAgIGdncGxvdDI6Omdlb21fdmxpbmUoDQogICAgICB4aW50ZXJjZXB0ID0gMCwNCiAgICAgIGxpbmV3aWR0aCA9IDAuNDUNCiAgICApICsNCiAgICBnZ3Bsb3QyOjpnZW9tX2Vycm9yYmFyaCgNCiAgICAgIGdncGxvdDI6OmFlcygNCiAgICAgICAgeG1pbiA9IGNvbmYubG93X3BwLA0KICAgICAgICB4bWF4ID0gY29uZi5oaWdoX3BwDQogICAgICApLA0KICAgICAgaGVpZ2h0ID0gMC4xMiwNCiAgICAgIHBvc2l0aW9uID0gZG9kZ2UsDQogICAgICBsaW5ld2lkdGggPSAwLjU1DQogICAgKSArDQogICAgZ2dwbG90Mjo6Z2VvbV9wb2ludCgNCiAgICAgIHBvc2l0aW9uID0gZG9kZ2UsDQogICAgICBzaXplID0gMi4yNSwNCiAgICAgIGZpbGwgPSAid2hpdGUiDQogICAgKSArDQogICAgZ2dwbG90Mjo6ZmFjZXRfd3JhcCgNCiAgICAgIH4gcGFydHlfc3VwcG9ydF9oLA0KICAgICAgbmNvbCA9IDIsDQogICAgICBzY2FsZXMgPSAiZnJlZV95Ig0KICAgICkgKw0KICAgIGdncGxvdDI6OmxhYnMoDQogICAgICB0aXRsZSA9IOWun+mok+WQjSwNCiAgICAgIHN1YnRpdGxlID0gIuWQhOODkeODjeODq+OBr+aUr+aMgeaUv+WFmuWIpeOBruaOqOWumue1kOaenOOAgueCueOBr0FNQ0XjgIHmqKrnt5rjga85NSXkv6HpoLzljLrplpPjgIIiLA0KICAgICAgeCA9ICLpgbjmip7norrnjofjgbjjga7lirnmnpzvvIhwcO+8iSIsDQogICAgICB5ID0gTlVMTCwNCiAgICAgIHNoYXBlID0gIumBuOaKnuiCouaVsOadoeS7tiIsDQogICAgICBjYXB0aW9uID0gIuWbnuetlOiAheaVsOOBjDQw5Lq65pyq5rqA44Gu5pSv5oyB5pS/5YWaw5fpgbjmip7ogqLmlbDmnaHku7bjga/mjqjlrprlr77osaHlpJbjgIIiDQogICAgKSArDQogICAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTAuNSkgKw0KICAgIGdncGxvdDI6OnRoZW1lKA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJjZW50ZXIiLA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBnZ3Bsb3QyOjplbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgICAgc3RyaXAudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTAuNSksDQogICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gOC42LCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwNCiAgICAgIHBsb3QudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgICBwbG90LnN1YnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSA5LjUpLA0KICAgICAgcGxvdC5jYXB0aW9uID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDguNSksDQogICAgICBwYW5lbC5zcGFjaW5nID0gZ3JpZDo6dW5pdCgxLjAsICJsaW5lcyIpDQogICAgKQ0KfQ0KDQrooahIMeS9nOaIkCA8LSBmdW5jdGlvbijooajjg4fjg7zjgr8pIHsNCiAg5pSv5oyB6aCGIDwtIHVuaXF1ZSjooajjg4fjg7zjgr8kcGFydHlfc3VwcG9ydF9oKQ0KICDpoIXnm67poIYgPC0gdW5pcXVlKOihqOODh+ODvOOCvyTooajnpLrpoIXnm64pDQoNCiAg6KGo44OH44O844K/ICU+JQ0KICAgIGRwbHlyOjptdXRhdGUoDQogICAgICDmlK/mjIHmlL/lhZogPSBmYWN0b3IocGFydHlfc3VwcG9ydF9oLCBsZXZlbHMgPSDmlK/mjIHpoIYpLA0KICAgICAgYOWxnuaAp+ODu+awtOa6lmAgPSBmYWN0b3Io6KGo56S66aCF55uuLCBsZXZlbHMgPSDpoIXnm67poIYpLA0KICAgICAg57WQ5p6cID0gc3ByaW50ZigNCiAgICAgICAgIiUuMmYgWyUuMmYsICUuMmZdIiwNCiAgICAgICAgZXN0aW1hdGVfcHAsDQogICAgICAgIGNvbmYubG93X3BwLA0KICAgICAgICBjb25mLmhpZ2hfcHANCiAgICAgICkNCiAgICApICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoDQogICAgICDmlK/mjIHmlL/lhZosDQogICAgICBg5bGe5oCn44O75rC05rqWYCwNCiAgICAgIOadoeS7tiA9IOadoeS7tuihqOekuiwNCiAgICAgIOe1kOaenA0KICAgICkgJT4lDQogICAgdGlkeXI6OnBpdm90X3dpZGVyKA0KICAgICAgbmFtZXNfZnJvbSA9IOadoeS7tiwNCiAgICAgIHZhbHVlc19mcm9tID0g57WQ5p6cLA0KICAgICAgdmFsdWVzX2ZpbGwgPSAi4oCUIg0KICAgICkgJT4lDQogICAgZHBseXI6OmFycmFuZ2Uo5pSv5oyB5pS/5YWaLCBg5bGe5oCn44O75rC05rqWYCkgJT4lDQogICAgZHBseXI6Om11dGF0ZSgNCiAgICAgIOaUr+aMgeaUv+WFmiA9IGFzLmNoYXJhY3RlcijmlK/mjIHmlL/lhZopLA0KICAgICAgYOWxnuaAp+ODu+awtOa6lmAgPSBhcy5jaGFyYWN0ZXIoYOWxnuaAp+ODu+awtOa6lmApDQogICAgKQ0KfQ0KDQrooahIMeWbnuetlOiAheaVsOS9nOaIkCA8LSBmdW5jdGlvbijooajjg4fjg7zjgr8pIHsNCiAg6KGo44OH44O844K/ICU+JQ0KICAgIGRwbHlyOjpkaXN0aW5jdCgNCiAgICAgIOaUr+aMgeaUv+WFmiA9IHBhcnR5X3N1cHBvcnRfaCwNCiAgICAgIOadoeS7tiA9IOadoeS7tuihqOekuiwNCiAgICAgIOWbnuetlOiAheaVsCA9IG5faWRzDQogICAgKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKOWbnuetlOiAheaVsCA9IGFzLmNoYXJhY3Rlcijlm57nrZTogIXmlbApKSAlPiUNCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIoDQogICAgICBuYW1lc19mcm9tID0g5p2h5Lu2LA0KICAgICAgdmFsdWVzX2Zyb20gPSDlm57nrZTogIXmlbAsDQogICAgICB2YWx1ZXNfZmlsbCA9ICLigJQiDQogICAgKSAlPiUNCiAgICBkcGx5cjo6YXJyYW5nZSjmlK/mjIHmlL/lhZopDQp9DQpgYGANCg0KIyMjIOijnOWbs0gxYe+8muWun+mokzHvvIgyMDIz5bm077yJDQoNCuWun+mokzHjgavjgaTjgYTjgabjgIHmjqjlrprlj6/og73jgafjgYLjgaPjgZ/mlK/mjIHmlL/lhZrliKXjgatBTUNF44KS56S644GZ44CC5ZCE44OR44ON44Or5YaF44Gn44Gv44CB5ZCM5LiA44Gu5bGe5oCn44O75rC05rqW44Gr44Gk44GE44GmNOOBpOOBruaUv+WFmuaVsOadoeS7tuOCkuavlOi8g+OBp+OBjeOCi+OAgg0KDQpgYGB7ciBnMS1zdHVkeTEtZmlndXJlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRSwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTkuNSwgb3V0LndpZHRoPScxMDAlJ30NCkgxX+Wun+mokzEgPC0g5pSv5oyBQU1DReS4gOimpyAlPiUNCiAgZHBseXI6OmZpbHRlcihzdHVkeV9pZCA9PSAic3R1ZHkxIikNCg0K6KOc5ZuzSDFhIDwtIOijnOWbs0gx5L2c5oiQKA0KICBIMV/lrp/pqJMxLA0KICAi6KOc5ZuzSDFh77ya5a6f6aiTMe+8iDIwMjPlubTvvInjga7mlK/mjIHmlL/lhZrliKVBTUNFIg0KKQ0K6KOc5ZuzSDFhDQpgYGANCg0K5a++5b+c44GZ44KL5Zue562U6ICF5pWw44GoQU1DReOCkuS7peS4i+OBq+ekuuOBmeOAgkFNQ0Xooajjgafjga/jgIHlkITmnaHku7bjga7ngrnmjqjlrprlgKTjgag5NSXkv6HpoLzljLrplpPjgpIx44K744Or44Gr44G+44Go44KB44Gm44GE44KL44CCDQoNCmBgYHtyIGcxLXN0dWR5MS10YWJsZSwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrooahIMWHlm57nrZTogIXmlbAgPC0g6KGoSDHlm57nrZTogIXmlbDkvZzmiJAoSDFf5a6f6aiTMSkNCmtuaXRyOjprYWJsZSgNCiAg6KGoSDFh5Zue562U6ICF5pWwLA0KICBmb3JtYXQgPSAiaHRtbCIsDQogIHJvdy5uYW1lcyA9IEZBTFNFLA0KICB0YWJsZS5hdHRyID0gJ2NsYXNzPSJ0YWJsZSB0YWJsZS1jb25kZW5zZWQiIHN0eWxlPSJmb250LXNpemU6OTAlOyInLA0KICBjYXB0aW9uID0gIuihqEgxYS0x77ya5a6f6aiTMe+8iDIwMjPlubTvvInjga7mlK/mjIHmlL/lhZrliKXlm57nrZTogIXmlbAiDQopDQoNCuihqEgxYSA8LSDooahIMeS9nOaIkChIMV/lrp/pqJMxKQ0Ka25pdHI6OmthYmxlKA0KICDooahIMWEsDQogIGZvcm1hdCA9ICJodG1sIiwNCiAgcm93Lm5hbWVzID0gRkFMU0UsDQogIHRhYmxlLmF0dHIgPSAnY2xhc3M9InRhYmxlIHRhYmxlLWNvbmRlbnNlZCIgc3R5bGU9ImZvbnQtc2l6ZTo5MCU7IicsDQogIGNhcHRpb24gPSAi6KGoSDFhLTLvvJrlrp/pqJMx77yIMjAyM+W5tO+8ieOBruaUr+aMgeaUv+WFmuWIpUFNQ0XvvLvngrnmjqjlrprlgKQgWzk1JSBDSV3jgIFwcO+8vSINCikNCmBgYA0KDQojIyMg6KOc5ZuzSDFi77ya5a6f6aiTMu+8iDIwMjblubTvvIkNCg0K5a6f6aiTMuOBq+OBpOOBhOOBpuOCguWQjOOBmOW9ouW8j+OBp+ekuuOBmeOAguaUr+aMgeaUv+WFmuOBrueorumhnuOBjOWun+mokzHjgojjgorlpJrjgYTjgZ/jgoHjgIHmlK/mjIHmlL/lhZrjgpIy5YiX44Gu44OV44Kh44K744OD44OI44Gr5YiG44GR44CB5ZCE44OR44ON44Or44Gn5bGe5oCn44O75rC05rqW44KS57im5pa55ZCR44Gr6L+944GI44KL44KI44GG44Gr44GX44Gf44CCDQoNCmBgYHtyIGcxLXN0dWR5Mi1maWd1cmUsIGVjaG89VFJVRSwgZXZhbD1UUlVFLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTYsIG91dC53aWR0aD0nMTAwJSd9DQpIMV/lrp/pqJMyIDwtIOaUr+aMgUFNQ0XkuIDopqcgJT4lDQogIGRwbHlyOjpmaWx0ZXIoc3R1ZHlfaWQgPT0gInN0dWR5MiIpDQoNCuijnOWbs0gxYiA8LSDoo5zlm7NIMeS9nOaIkCgNCiAgSDFf5a6f6aiTMiwNCiAgIuijnOWbs0gxYu+8muWun+mokzLvvIgyMDI25bm077yJ44Gu5pSv5oyB5pS/5YWa5YilQU1DRSINCikNCuijnOWbs0gxYg0KYGBgDQoNCmBgYHtyIGcxLXN0dWR5Mi10YWJsZSwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrooahIMWLlm57nrZTogIXmlbAgPC0g6KGoSDHlm57nrZTogIXmlbDkvZzmiJAoSDFf5a6f6aiTMikNCmtuaXRyOjprYWJsZSgNCiAg6KGoSDFi5Zue562U6ICF5pWwLA0KICBmb3JtYXQgPSAiaHRtbCIsDQogIHJvdy5uYW1lcyA9IEZBTFNFLA0KICB0YWJsZS5hdHRyID0gJ2NsYXNzPSJ0YWJsZSB0YWJsZS1jb25kZW5zZWQiIHN0eWxlPSJmb250LXNpemU6OTAlOyInLA0KICBjYXB0aW9uID0gIuihqEgxYi0x77ya5a6f6aiTMu+8iDIwMjblubTvvInjga7mlK/mjIHmlL/lhZrliKXlm57nrZTogIXmlbAiDQopDQoNCuihqEgxYiA8LSDooahIMeS9nOaIkChIMV/lrp/pqJMyKQ0Ka25pdHI6OmthYmxlKA0KICDooahIMWIsDQogIGZvcm1hdCA9ICJodG1sIiwNCiAgcm93Lm5hbWVzID0gRkFMU0UsDQogIHRhYmxlLmF0dHIgPSAnY2xhc3M9InRhYmxlIHRhYmxlLWNvbmRlbnNlZCIgc3R5bGU9ImZvbnQtc2l6ZTo5MCU7IicsDQogIGNhcHRpb24gPSAi6KGoSDFiLTLvvJrlrp/pqJMy77yIMjAyNuW5tO+8ieOBruaUr+aMgeaUv+WFmuWIpUFNQ0XvvLvngrnmjqjlrprlgKQgWzk1JSBDSV3jgIFwcO+8vSINCikNCmBgYA0KDQojIyMg6KOc5ZuzSDFj77ya5a6f6aiTM++8iDIwMjblubTvvIkNCg0K5a6f6aiTM+OBp+OBr+OAgeaUv+WFmuWxnuaAp+OBjOaUv+WFmuWQjeOBqOOBl+OBpuaPkOekuuOBleOCjOOCi+OAguWbs+OBruani+aIkOOBr+Wun+mokzHjg7sy44Go5o+D44GI44CB5pSv5oyB5pS/5YWa44GU44Go44Gr44CB5pS/5YWa5ZCN44GK44KI44Gz57WM5riI5bGe5oCn44Gu5ZCE5rC05rqW44Gr5a++44GZ44KLQU1DReOCkuavlOi8g+OBp+OBjeOCi+OCiOOBhuOBq+OBl+OBn+OAgg0KDQpgYGB7ciBnMS1zdHVkeTMtZmlndXJlLCBlY2hvPVRSVUUsIGV2YWw9VFJVRSwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTE2LCBvdXQud2lkdGg9JzEwMCUnfQ0KSDFf5a6f6aiTMyA8LSDmlK/mjIFBTUNF5LiA6KanICU+JQ0KICBkcGx5cjo6ZmlsdGVyKHN0dWR5X2lkID09ICJzdHVkeTMiKQ0KDQroo5zlm7NIMWMgPC0g6KOc5ZuzSDHkvZzmiJAoDQogIEgxX+Wun+mokzMsDQogICLoo5zlm7NIMWPvvJrlrp/pqJMz77yIMjAyNuW5tO+8ieOBruaUr+aMgeaUv+WFmuWIpUFNQ0UiDQopDQroo5zlm7NIMWMNCmBgYA0KDQpgYGB7ciBnMS1zdHVkeTMtdGFibGUsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6KGoSDFj5Zue562U6ICF5pWwIDwtIOihqEgx5Zue562U6ICF5pWw5L2c5oiQKEgxX+Wun+mokzMpDQprbml0cjo6a2FibGUoDQogIOihqEgxY+WbnuetlOiAheaVsCwNCiAgZm9ybWF0ID0gImh0bWwiLA0KICByb3cubmFtZXMgPSBGQUxTRSwNCiAgdGFibGUuYXR0ciA9ICdjbGFzcz0idGFibGUgdGFibGUtY29uZGVuc2VkIiBzdHlsZT0iZm9udC1zaXplOjkwJTsiJywNCiAgY2FwdGlvbiA9ICLooahIMWMtMe+8muWun+mokzPvvIgyMDI25bm077yJ44Gu5pSv5oyB5pS/5YWa5Yil5Zue562U6ICF5pWwIg0KKQ0KDQrooahIMWMgPC0g6KGoSDHkvZzmiJAoSDFf5a6f6aiTMykNCmtuaXRyOjprYWJsZSgNCiAg6KGoSDFjLA0KICBmb3JtYXQgPSAiaHRtbCIsDQogIHJvdy5uYW1lcyA9IEZBTFNFLA0KICB0YWJsZS5hdHRyID0gJ2NsYXNzPSJ0YWJsZSB0YWJsZS1jb25kZW5zZWQiIHN0eWxlPSJmb250LXNpemU6OTAlOyInLA0KICBjYXB0aW9uID0gIuihqEgxYy0y77ya5a6f6aiTM++8iDIwMjblubTvvInjga7mlK/mjIHmlL/lhZrliKVBTUNF77y754K55o6o5a6a5YCkIFs5NSUgQ0ld44CBcHDvvL0iDQopDQpgYGANCg0KIyMg6KOc5ZuzSDLvvJrmlK/mjIHmlL/lhZrliKXjga7miYvjgYzjgYvjgorph43opoHluqbjgajnm7jlr77mr5Tph40NCg0KYGBge3IgZzIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5pSv5oyB5omL44GM44GL44KK5LiA6KanIDwtIGRwbHlyOjpiaW5kX3Jvd3MoDQogIHBhcnR5X3N1cHBvcnRfcmVsYXRpdmVfY3VlX3Jlc3VsdHMkc3R1ZHkxJGludGVydmFscyAlPiUgZHBseXI6Om11dGF0ZSjlrp/pqJMgPSAi5a6f6aiTMe+8iDIwMjPlubTvvIkiLCBzdHVkeV9pZCA9ICJzdHVkeTEiKSwNCiAgcGFydHlfc3VwcG9ydF9yZWxhdGl2ZV9jdWVfcmVzdWx0cyRzdHVkeTIkaW50ZXJ2YWxzICU+JSBkcGx5cjo6bXV0YXRlKOWun+mokyA9ICLlrp/pqJMy77yIMjAyNuW5tO+8iSIsIHN0dWR5X2lkID0gInN0dWR5MiIpLA0KICBwYXJ0eV9zdXBwb3J0X3JlbGF0aXZlX2N1ZV9yZXN1bHRzJHN0dWR5MyRpbnRlcnZhbHMgJT4lIGRwbHlyOjptdXRhdGUo5a6f6aiTID0gIuWun+mokzPvvIgyMDI25bm077yJIiwgc3R1ZHlfaWQgPSAic3R1ZHkzIikNCikgJT4lDQogIGRwbHlyOjptdXRhdGUoDQogICAg5p2h5Lu2ID0gcHVycnI6Om1hcDJfY2hyKHBhcnR5X24sIHN0dWR5X2lkLCDmnaHku7bml6XmnKzoqp4pLA0KICAgIOaMh+aomSA9IHB1cnJyOjptYXAyX2NocihzdGF0aXN0aWMsIHN0dWR5X2lkLCDntbHoqIjph4/ml6XmnKzoqp4pLA0KICAgIOihqOekuuWApCA9IGRwbHlyOjppZl9lbHNlKHN0YXRpc3RpYyA9PSAicmVsYXRpdmVfcGFydHlfd2VpZ2h0X3BhaXJ3aXNlIiwgMTAwICogZXN0aW1hdGUsIDEwMCAqIGVzdGltYXRlKSwNCiAgICDkuIvpmZAgPSAxMDAgKiBjb25mX2xvdywNCiAgICDkuIrpmZAgPSAxMDAgKiBjb25mX2hpZ2gsDQogICAg5Y2Y5L2NID0gZHBseXI6OmlmX2Vsc2Uoc3RhdGlzdGljID09ICJyZWxhdGl2ZV9wYXJ0eV93ZWlnaHRfcGFpcndpc2UiLCAiJSIsICJwcCIpDQogICkNCg0K55u45a++5q+U6YeN44OH44O844K/IDwtIOaUr+aMgeaJi+OBjOOBi+OCiuS4gOimpyAlPiUNCiAgZHBseXI6OmZpbHRlcihzdGF0aXN0aWMgPT0gInJlbGF0aXZlX3BhcnR5X3dlaWdodF9wYWlyd2lzZSIpICU+JQ0KICBkcGx5cjo6bXV0YXRlKOaVsOWApOODqeODmeODqyA9IHNwcmludGYoIiUuMWYlJSIsIOihqOekuuWApCkpDQoNCmZvciAo5a6f6aiT5ZCNIGluIHVuaXF1ZSjnm7jlr77mr5Tph43jg4fjg7zjgr8k5a6f6aiTKSkgew0KICDmj4/nlLvjg4fjg7zjgr8gPC0g55u45a++5q+U6YeN44OH44O844K/ICU+JSBkcGx5cjo6ZmlsdGVyKOWun+mokyA9PSDlrp/pqJPlkI0pDQogIOWbsyA8LSBnZ3Bsb3QyOjpnZ3Bsb3Qo5o+P55S744OH44O844K/LCBnZ3Bsb3QyOjphZXMoeCA9IHBhcnR5X24sIHkgPSDooajnpLrlgKQsIGdyb3VwID0gcGFydHlfc3VwcG9ydF9oKSkgKw0KICAgIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjQpICsNCiAgICBnZ3Bsb3QyOjpnZW9tX2xpbmUobGluZXdpZHRoID0gMC42NSkgKw0KICAgIGdncGxvdDI6Omdlb21fZXJyb3JiYXIoZ2dwbG90Mjo6YWVzKHltaW4gPSDkuIvpmZAsIHltYXggPSDkuIrpmZApLCB3aWR0aCA9IDAuMDgsIGxpbmV3aWR0aCA9IDAuNDUpICsNCiAgICBnZ3Bsb3QyOjpnZW9tX2xhYmVsKGdncGxvdDI6OmFlcyhsYWJlbCA9IOaVsOWApOODqeODmeODqyksIHNpemUgPSAzLjAsIGxhYmVsLnNpemUgPSAwLCBmaWxsID0gIndoaXRlIikgKw0KICAgIGdncGxvdDI6OmZhY2V0X3dyYXAofiBwYXJ0eV9zdXBwb3J0X2gsIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogICAgZ2dwbG90Mjo6c2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDI6NSwgbGFiZWxzID0g5p2h5Lu25pel5pys6KqeKDI6NSwgaWZlbHNlKHVuaXF1ZSjmj4/nlLvjg4fjg7zjgr8kc3R1ZHlfaWQpID09ICJzdHVkeTMiLCAic3R1ZHkzIiwgInN0dWR5MSIpKSkgKw0KICAgIGdncGxvdDI6OmxhYnMoeCA9IE5VTEwsIHkgPSAi5pS/5YWa5omL44GM44GL44KK55u45a++5q+U6YeN77yIJe+8iSIsIHN1YnRpdGxlID0g5a6f6aiT5ZCNKSArDQogICAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTApICsNCiAgICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpKQ0KICBwcmludCjlm7MpDQp9DQoNCuihqEgyIDwtIOaUr+aMgeaJi+OBjOOBi+OCiuS4gOimpyAlPiUNCiAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICDlrp/pqJMsDQogICAg5pSv5oyB5pS/5YWaID0gcGFydHlfc3VwcG9ydF9oLA0KICAgIGDmnaHku7bjg7vmjIfmqJlgID0gcGFzdGUwKOadoeS7tiwgIu+8miIsIOaMh+aomSksDQogICAg5o6o5a6a5YCkID0gcm91bmQo6KGo56S65YCkLCAyKSwNCiAgICBgOTUlQ0nkuIvpmZBgID0gcm91bmQo5LiL6ZmQLCAyKSwNCiAgICBgOTUlQ0nkuIrpmZBgID0gcm91bmQo5LiK6ZmQLCAyKSwNCiAgICDljZjkvY0NCiAgKQ0Ka25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahIMiksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAi6KGoSDLvvJrmlK/mjIHmlL/lhZrliKXjga7miYvjgYzjgYvjgorph43opoHluqbjgajnm7jlr77mr5Tph40iKQ0KYGBgDQoNCiMjIOijnOWbs0gz77ya5a++6LGh44Go44Gq44KL5pSv5oyB5pS/5YWa5Yil44Gu5LiA6Ie05Yq55p6cDQoNCmBgYHtyIGczLCBlY2hvPVRSVUUsIGV2YWw9VFJVRX0NCuS4gOiHtOWKueaenCA8LSBzdHVkeTNfYWxsX3BhcnR5X21hdGNoX3Jlc3VsdHMkY29lZmZpY2llbnRzICU+JQ0KICBkcGx5cjo6ZmlsdGVyKHN0YXR1cyA9PSAiZXN0aW1hdGVkIiwgIWlzLm5hKGVzdGltYXRlKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoDQogICAg5p2h5Lu2ID0g5p2h5Lu25pel5pys6KqeKHBhcnR5X24sICJzdHVkeTMiKSwNCiAgICDmlbDlgKTjg6njg5njg6sgPSBzcHJpbnRmKCIlLjFmIiwgZXN0aW1hdGVfcHApDQogICkNCg0K6KOc5ZuzSDMgPC0gZ2dwbG90Mjo6Z2dwbG90KOS4gOiHtOWKueaenCwgZ2dwbG90Mjo6YWVzKHggPSBwYXJ0eV9uLCB5ID0gZXN0aW1hdGVfcHAsIGdyb3VwID0gMSkpICsNCiAgZ2dwbG90Mjo6Z2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC40KSArDQogIGdncGxvdDI6Omdlb21fbGluZShsaW5ld2lkdGggPSAwLjY1KSArDQogIGdncGxvdDI6Omdlb21fZXJyb3JiYXIoZ2dwbG90Mjo6YWVzKHltaW4gPSBjb25mLmxvd19wcCwgeW1heCA9IGNvbmYuaGlnaF9wcCksIHdpZHRoID0gMC4wOCwgbGluZXdpZHRoID0gMC40NSkgKw0KICBnZ3Bsb3QyOjpnZW9tX2xhYmVsKGdncGxvdDI6OmFlcyhsYWJlbCA9IOaVsOWApOODqeODmeODqyksIHNpemUgPSAzLjAsIGxhYmVsLnNpemUgPSAwLCBmaWxsID0gIndoaXRlIikgKw0KICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4gc3VwcG9ydF9wYXJ0eV92YWxpZCkgKw0KICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMjo1LCBsYWJlbHMgPSBwYXN0ZTAoMjo1LCAi6YG45oqe6IKiIikpICsNCiAgZ2dwbG90Mjo6bGFicyh4ID0gIumBuOaKnuiCouaVsCIsIHkgPSAi5LiA6Ie05Yq55p6c77yIcHDvvIkiKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwKSArDQogIGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCkpDQroo5zlm7NIMw0KDQrooahIMyA8LSDkuIDoh7TlirnmnpwgJT4lDQogIGRwbHlyOjp0cmFuc211dGUoDQogICAg5pSv5oyB5pS/5YWaID0gc3VwcG9ydF9wYXJ0eV92YWxpZCwNCiAgICDmnaHku7YsDQogICAg5Zue562U6ICF5pWwID0gbl9pZHMsDQogICAgYOS4gOiHtOWKueaenO+8iHBw77yJYCA9IHJvdW5kKGVzdGltYXRlX3BwLCAyKSwNCiAgICBgOTUlQ0nkuIvpmZBgID0gcm91bmQoY29uZi5sb3dfcHAsIDIpLA0KICAgIGA5NSVDSeS4iumZkGAgPSByb3VuZChjb25mLmhpZ2hfcHAsIDIpLA0KICAgIHDlgKQgPSBzaWduaWYocC52YWx1ZSwgMykNCiAgKQ0Ka25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahIMyksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpDQoNCuihqEg0IDwtIHN0dWR5M19hbGxfcGFydHlfbWF0Y2hfcmVzdWx0cyR0cmVuZHMgJT4lDQogIGRwbHlyOjpmaWx0ZXIoc3RhdHVzID09ICJlc3RpbWF0ZWQiKSAlPiUNCiAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICDmlK/mjIHmlL/lhZogPSBzdXBwb3J0X3BhcnR5X3ZhbGlkLA0KICAgIGAx6YG45oqe6IKi5aKX5Yqg44GC44Gf44KK44Gu5aSJ5YyW77yIcHDvvIlgID0gcm91bmQoZXN0aW1hdGUgKiAxMDAsIDIpLA0KICAgIGA5NSVDSeS4i+mZkGAgPSByb3VuZChjb25mLmxvdyAqIDEwMCwgMiksDQogICAgYDk1JUNJ5LiK6ZmQYCA9IHJvdW5kKGNvbmYuaGlnaCAqIDEwMCwgMiksDQogICAgcOWApCA9IHNpZ25pZihwLnZhbHVlLCAzKQ0KICApDQprbml0cjo6a2FibGUo6KGo5pel5pys6KqeKOihqEg0KSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIEkuIDPlrp/pqJPmqKrmlq3liIbmnpANCg0KIyMg6KOc5ZuzSTHvvJrkuLvopoHku67oqqzjga7nt5rlvaLlgr7lkJENCg0KYGBge3IgaDEsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K5Li76KaB5Luu6KqsIDwtIGh5cG90aGVzaXNfdGVzdF9zdW1tYXJ5ICU+JQ0KICBkcGx5cjo6bXV0YXRlKA0KICAgIOWun+mokyA9IGRwbHlyOjpyZWNvZGUoc3R1ZHlfaWQsIHN0dWR5MSA9ICLlrp/pqJMx77yIMjAyM+W5tO+8iSIsIHN0dWR5MiA9ICLlrp/pqJMy77yIMjAyNuW5tO+8iSIsIHN0dWR5MyA9ICLlrp/pqJMz77yIMjAyNuW5tO+8iSIpLA0KICAgIOaMh+aomSA9IGRwbHlyOjpjYXNlX3doZW4oDQogICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YXRpc3RpYywgInBhcnR5IikgfiAi5pS/5YWa5omL44GM44GL44KK6YeN6KaB5bqmIiwNCiAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3Qoc3RhdGlzdGljLCAiZWNvbm9taWMiKSB+ICLntYzmuIjmiYvjgYzjgYvjgorph43opoHluqYiLA0KICAgICAgVFJVRSB+IHN0YXRpc3RpYw0KICAgICksDQogICAg5LqI5ris5pa55ZCRID0gZHBseXI6OnJlY29kZShleHBlY3RlZF9kaXJlY3Rpb24sIHBvc2l0aXZlID0gIuatoyIsIG5lZ2F0aXZlID0gIuiyoCIpDQogICkNCg0K5Li76KaB5Luu6KqsIDwtIOS4u+imgeS7ruiqrCAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDlgr7jgY1wcCA9IDEwMCAqIGVzdGltYXRlLA0KICAgIOS4i+mZkHBwID0gMTAwICogY29uZl9sb3csDQogICAg5LiK6ZmQcHAgPSAxMDAgKiBjb25mX2hpZ2gsDQogICAg6KGo56S66KGMID0gcGFzdGUwKGh5cG90aGVzaXMsICLvvJoiLCDmjIfmqJkpLA0KICAgIOaVsOWApOODqeODmeODqyA9IHNwcmludGYoIiUuMmYiLCDlgr7jgY1wcCkNCiAgKQ0KDQroo5zlm7NJMSA8LSBnZ3Bsb3QyOjpnZ3Bsb3Qo5Li76KaB5Luu6KqsLCBnZ3Bsb3QyOjphZXMoeCA9IOWCvuOBjXBwLCB5ID0gc3RhdHM6OnJlb3JkZXIo6KGo56S66KGMLCDlgr7jgY1wcCkpKSArDQogIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV3aWR0aCA9IDAuNDUpICsNCiAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcmgoZ2dwbG90Mjo6YWVzKHhtaW4gPSDkuIvpmZBwcCwgeG1heCA9IOS4iumZkHBwKSwgaGVpZ2h0ID0gMC4xMiwgbGluZXdpZHRoID0gMC41NSkgKw0KICBnZ3Bsb3QyOjpnZW9tX2xhYmVsKGdncGxvdDI6OmFlcyhsYWJlbCA9IOaVsOWApOODqeODmeODqyksIHNpemUgPSAzLjEsIGxhYmVsLnNpemUgPSAwLCBmaWxsID0gIndoaXRlIikgKw0KICBnZ3Bsb3QyOjpsYWJzKHggPSAi6YG45oqe6IKi44GMMeOBpOWil+OBiOOCi+OBqOOBjeOBrumHjeimgeW6puOBruWkieWMlu+8iHBw77yJIiwgeSA9IE5VTEwpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEpICsNCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkNCuijnOWbs0kxDQoNCuihqEkxIDwtIOS4u+imgeS7ruiqrCAlPiUNCiAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICDlrp/pqJMsDQogICAg5Luu6KqsID0gaHlwb3RoZXNpcywNCiAgICDmjIfmqJksDQogICAg5LqI5ris5pa55ZCRLA0KICAgIOWCvuOBjSA9IHJvdW5kKGVzdGltYXRlLCA0KSwNCiAgICBgOTUlQ0nkuIvpmZBgID0gcm91bmQoY29uZl9sb3csIDQpLA0KICAgIGA5NSVDSeS4iumZkGAgPSByb3VuZChjb25mX2hpZ2gsIDQpLA0KICAgIHDlgKQgPSBzaWduaWYocF92YWx1ZV90d29fc2lkZWQsIDMpLA0KICAgIOWIpOWumiA9IGNvbmNsdXNpb24NCiAgKQ0Ka25pdHI6OmthYmxlKOihqOaXpeacrOiqnijooahJMSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMg6KOc5ZuzSTLvvJrpgbjmip7ogqLmlbDoqr/mlbTmuIjjgb/ph43opoHluqbjga7nt5rlvaLlgr7lkJENCg0KYGBge3IgaDIsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQ0K6Kq/5pW05riI44G/5YK+5ZCRIDwtIGNob2ljZV9zZXRfYWRqdXN0ZWRfc2xvcGVfc3VtbWFyeSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDlrp/pqJMgPSBkcGx5cjo6cmVjb2RlKHN0dWR5X2lkLCBzdHVkeTEgPSAi5a6f6aiTMe+8iDIwMjPlubTvvIkiLCBzdHVkeTIgPSAi5a6f6aiTMu+8iDIwMjblubTvvIkiLCBzdHVkeTMgPSAi5a6f6aiTM++8iDIwMjblubTvvIkiKSwNCiAgICDmjIfmqJkgPSBkcGx5cjo6Y2FzZV93aGVuKA0KICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdChzdGF0aXN0aWMsICJwYXJ0eSIpIH4gIuaUv+WFmuaJi+OBjOOBi+OCiumHjeimgeW6pu+8iOmBuOaKnuiCouaVsOiqv+aVtOa4iOOBv++8iSIsDQogICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KHN0YXRpc3RpYywgImVjb25vbWljIikgfiAi57WM5riI5omL44GM44GL44KK6YeN6KaB5bqm77yI6YG45oqe6IKi5pWw6Kq/5pW05riI44G/77yJIiwNCiAgICAgIFRSVUUgfiBzdGF0aXN0aWMNCiAgICApDQogICkNCg0K6Kq/5pW05riI44G/5YK+5ZCRIDwtIOiqv+aVtOa4iOOBv+WCvuWQkSAlPiUNCiAgZHBseXI6Om11dGF0ZSgNCiAgICDlgr7jgY3ooajnpLogPSAxMDAgKiBlc3RpbWF0ZSwNCiAgICDkuIvpmZDooajnpLogPSAxMDAgKiBjb25mX2xvdywNCiAgICDkuIrpmZDooajnpLogPSAxMDAgKiBjb25mX2hpZ2gsDQogICAg6KGo56S66KGMID0gcGFzdGUwKOWun+mokywgIu+8miIsIOaMh+aomSksDQogICAg5pWw5YCk44Op44OZ44OrID0gc3ByaW50ZigiJS4yZiIsIOWCvuOBjeihqOekuikNCiAgKQ0KDQroo5zlm7NJMiA8LSBnZ3Bsb3QyOjpnZ3Bsb3Qo6Kq/5pW05riI44G/5YK+5ZCRLCBnZ3Bsb3QyOjphZXMoeCA9IOWCvuOBjeihqOekuiwgeSA9IHN0YXRzOjpyZW9yZGVyKOihqOekuuihjCwg5YK+44GN6KGo56S6KSkpICsNCiAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXdpZHRoID0gMC40NSkgKw0KICBnZ3Bsb3QyOjpnZW9tX2Vycm9yYmFyaChnZ3Bsb3QyOjphZXMoeG1pbiA9IOS4i+mZkOihqOekuiwgeG1heCA9IOS4iumZkOihqOekuiksIGhlaWdodCA9IDAuMTIsIGxpbmV3aWR0aCA9IDAuNTUpICsNCiAgZ2dwbG90Mjo6Z2VvbV9sYWJlbChnZ3Bsb3QyOjphZXMobGFiZWwgPSDmlbDlgKTjg6njg5njg6spLCBzaXplID0gMy4xLCBsYWJlbC5zaXplID0gMCwgZmlsbCA9ICJ3aGl0ZSIpICsNCiAgZ2dwbG90Mjo6bGFicyh4ID0gIumBuOaKnuiCouOBjDHjgaTlopfjgYjjgovjgajjgY3jga7oqr/mlbTmuIjjgb/ph43opoHluqbjga7lpInljJbvvIgl77yJIiwgeSA9IE5VTEwpICsNCiAgZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTEpICsNCiAgZ2dwbG90Mjo6dGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSkNCuijnOWbs0kyDQoNCuihqEkyIDwtIOiqv+aVtOa4iOOBv+WCvuWQkSAlPiUNCiAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICDlrp/pqJMsDQogICAg5oyH5qiZLA0KICAgIOWCvuOBjSA9IHJvdW5kKGVzdGltYXRlLCA0KSwNCiAgICBgOTUlQ0nkuIvpmZBgID0gcm91bmQoY29uZl9sb3csIDQpLA0KICAgIGA5NSVDSeS4iumZkGAgPSByb3VuZChjb25mX2hpZ2gsIDQpLA0KICAgIHDlgKQgPSBzaWduaWYocF92YWx1ZV90d29fc2lkZWQsIDMpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoSTIpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIOijnOWbs0kz77ya5pS/5YWa5omL44GM44GL44KK55u45a++5q+U6YeN44GuM+Wun+mok+avlOi8gw0KDQpgYGB7ciBoMywgZWNobz1UUlVFLCBldmFsPVRSVUV9DQrmqKrmlq3nm7jlr77mr5Tph40gPC0gY3Jvc3Nfc3R1ZHlfcmVsYXRpdmVfd2VpZ2h0ICU+JQ0KICBkcGx5cjo6bXV0YXRlKA0KICAgIOWun+mokyA9IGRwbHlyOjpyZWNvZGUoc3R1ZHlfaWQsIHN0dWR5MSA9ICLlrp/pqJMx77yIMjAyM+W5tO+8iSIsIHN0dWR5MiA9ICLlrp/pqJMy77yIMjAyNuW5tO+8iSIsIHN0dWR5MyA9ICLlrp/pqJMz77yIMjAyNuW5tO+8iSIpLA0KICAgIOebuOWvvuavlOmHjSA9IDEwMCAqIGVzdGltYXRlLA0KICAgIOS4i+mZkCA9IDEwMCAqIGNvbmZfbG93LA0KICAgIOS4iumZkCA9IDEwMCAqIGNvbmZfaGlnaCwNCiAgICDmlbDlgKTjg6njg5njg6sgPSBzcHJpbnRmKCIlLjFmJSUiLCDnm7jlr77mr5Tph40pDQogICkNCg0K6KOc5ZuzSTMgPC0gZ2dwbG90Mjo6Z2dwbG90KOaoquaWreebuOWvvuavlOmHjSwgZ2dwbG90Mjo6YWVzKHggPSBwYXJ0eV9uLCB5ID0g55u45a++5q+U6YeNLCBncm91cCA9IOWun+mokywgbGluZXR5cGUgPSDlrp/pqJMpKSArDQogIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAwLjQpICsNCiAgZ2dwbG90Mjo6Z2VvbV9saW5lKGxpbmV3aWR0aCA9IDAuNzUpICsNCiAgZ2dwbG90Mjo6Z2VvbV9lcnJvcmJhcihnZ3Bsb3QyOjphZXMoeW1pbiA9IOS4i+mZkCwgeW1heCA9IOS4iumZkCksIHdpZHRoID0gMC4wNywgbGluZXdpZHRoID0gMC40NSkgKw0KICBnZ3Bsb3QyOjpnZW9tX2xhYmVsKGdncGxvdDI6OmFlcyhsYWJlbCA9IOaVsOWApOODqeODmeODqyksIHNpemUgPSAzLjAsIGxhYmVsLnNpemUgPSAwLCBmaWxsID0gIndoaXRlIikgKw0KICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMjo1LCBsYWJlbHMgPSBwYXN0ZTAoMjo1LCAi6YG45oqe6IKiIikpICsNCiAgZ2dwbG90Mjo6bGFicyh4ID0gIumBuOaKnuiCouaVsCIsIHkgPSAi5pS/5YWa5omL44GM44GL44KK55u45a++5q+U6YeN77yIJe+8iSIsIGxpbmV0eXBlID0gTlVMTCkgKw0KICBnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMSkgKw0KICBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAidG9wIikNCuijnOWbs0kzDQoNCuihqEkzIDwtIOaoquaWreebuOWvvuavlOmHjSAlPiUNCiAgZHBseXI6OnRyYW5zbXV0ZSgNCiAgICDlrp/pqJMsDQogICAg5p2h5Lu2ID0gcGFzdGUwKHBhcnR5X24sICLpgbjmip7ogqLmnaHku7YiKSwNCiAgICBg5pS/5YWa5omL44GM44GL44KK55u45a++5q+U6YeN77yIJe+8iWAgPSByb3VuZCjnm7jlr77mr5Tph40sIDEpLA0KICAgIGA5NSVDSeS4i+mZkGAgPSByb3VuZCjkuIvpmZAsIDEpLA0KICAgIGA5NSVDSeS4iumZkGAgPSByb3VuZCjkuIrpmZAsIDEpDQogICkNCmtuaXRyOjprYWJsZSjooajml6XmnKzoqp4o6KGoSTMpLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMgSi4g6Kq/5p+756WoDQrmnKznr4Djgafjga/jgIHlrp/pqJMx77yIMjAyM+W5tO+8ieOAgeWun+mokzLvvIgyMDI25bm077yJ44CB5a6f6aiTM++8iDIwMjblubTvvInjgaflm57nrZTogIXjgavmj5DnpLrjgZfjgZ/oqr/mn7vnpajjgpLjgb7jgajjgoHjgablho3mjrLjgZnjgovjgILos6rllY/mlofjgajlm57nrZTpgbjmip7ogqLjga/jgIHlkIRRdWFsdHJpY3Poqr/mn7vnpajjga7jgqjjgq/jgrnjg53jg7zjg4jjgavln7rjgaXjgY3jgIHljp/mlofjga7ooajoqJjjgpLljp/liYfjgajjgZfjgabntq3mjIHjgZfjgZ/jgILjgrPjg7Pjgrjjg6fjgqTjg7Pjg4joqrLpoYzjga/lkITmnaHku7bjgac15Zue57mw44KK6L+U44GV44KM44KL44Gf44KB44CB5ZCM5LiA44Gu6LOq5ZWP5paH44KSNeWbnumHjeikh+aOsui8ieOBmeOCi+S7o+OCj+OCiuOBq+OAgSoq44GZ44G544Gm44Gu6LOq5ZWPSUTjgpLliJfmjJnjgZfjgZ/jgYbjgYjjgaflhbHpgJrjga7os6rllY/mlofjgpIx5Zue56S644GZKirjgILlkIToqrLpoYzjgafjg6njg7Pjg4Djg6Djgavlt67jgZfovrzjgb7jgozjgotRdWFsdHJpY3Pjga5FbWJlZGRlZCBEYXRh44Kz44O844OJ44Gv44CB5Zue562U6ICF44Gr44Go44Gj44Gm44Gu5a6f6LOq55qE44Gq6LOq5ZWP5paH44Gn44Gv44Gq44GE44Gf44KB55yB55Wl44GX44CB44Gd44Gu5Luj44KP44KK44Gr54Sh5L2c54K65YyW44GV44KM44Gf5bGe5oCn44Go5rC05rqW44KS6KGo44Go44GX44Gm56S644GZ44CCUXVhbHRyaWNz44Gu44OV44Ot44O85Yi25b6h44CBV2ViU2VydmljZeOAgeODmuODvOOCuOWMuuWIh+OCiuetieOBruaKgOihk+eahOODoeOCv+ODh+ODvOOCv+OCguecgeeVpeOBmeOCi+OAgg0KDQoNCiMjIEouMSDlrp/pqJMx77yIMjAyM+W5tO+8iQ0KDQojIyMgSi4xLjEg6Kq/5p+76ZaL5aeL5pmC44Gu6Kqs5piO44Go5ZCM5oSPDQoNCjxkZXRhaWxzPg0KPHN1bW1hcnk+PHN0cm9uZz5RMS4xIOiqv+afu+iqrOaYju+8iOOCr+ODquODg+OCr+OBl+OBpuWFqOaWh+OCkuihqOekuu+8iTwvc3Ryb25nPjwvc3VtbWFyeT4NCg0KPHA+44CM57WM5riI6KmV5L6h44Go5pS/5qip5Lqk5Luj44KS44KB44GQ44KL5oSP6K2Y6Kq/5p+744CNIOOBlOWNlOWKm+OBruOBiumhmOOBhCDplqLopb/lrabpmaLlpKflraYg57eP5ZCI5pS/562W5a2m6YOoIOaVmeaOiCDlpKfmnZEg6I+v5a2QIO+8iOOBiuOBiuOCgOOCiSDjga/jgarjgZPvvIkg4peGIOOBk+OBruOCouODs+OCseODvOODiOiqv+afu+OBr+OAgeaWh+mDqOenkeWtpuecgeOBq+OCiOOCi+eglOeptuWKqeaIkO+8iOeglOeptuiqsumhjOeVquWPt++8mjIySzAxMzIwIOOAjCDntYzmuIjjgajmlL/msrvnmoTmlK/mjIHjga7plqLkv4Ljg7zjgI7kuI3lubPjga7pnZ7lr77np7DmgKfjgI/ku67oqqzjgYvjgonopovjgovml6XmnKzjga7mnInmqKnogIXjgI3vvInjgavln7rjgaXjgY3lrp/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+744KS6ZaL5aeL44GX44Gm44GP44Gg44GV44GE44CCPC9wPg0KDQo8L2RldGFpbHM+DQoNCioq5Zue562U6YG45oqe6IKiKioNCg0KLSDmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZfjgabjgIHmnKzoqr/mn7vjgavljZTlipvjgZnjgosgKDEpDQotIOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBquOBhOOBruOBp+OAgeacrOiqv+afu+OBq+WNlOWKm+OBl+OBquOBhCAoMikNCg0KIyMjIEouMS4yIOODleOCp+OCpOOCueOCt+ODvOODiOOAgeaUv+WFmuaUr+aMgeOAgeaJgOW+lw0KDQp8IOizquWVj0lEIHwg6LOq5ZWP5paHIHwg5Zue562U5b2i5byP44O76YG45oqe6IKiIHwNCnwtLS18LS0tfC0tLXwNCnwgUTIuMSB8IOOBguOBquOBn+OBruaAp+WIpeOBr+OAgeS7peS4i+OBruOBhuOBoeOBqeOBoeOCieOBq+ipsuW9k+OBl+OBvuOBmeOBp+OBl+OCh+OBhuOBi+OAgiB8IOWls+aApyAoMSnvvI/nlLfmgKcgKDIp77yP44Gp44Gh44KJ44Gn44KC44Gq44GEICgzKe+8j+etlOOBiOOBquOBhCAoNCkgfA0KfCBRMi4yIHwg44GC44Gq44Gf44Gu54++5Zyo44Gu44GU5bm06b2i44KS6KiY5YWl44GX44Gm44GP44Gg44GV44GE44CCIOKAu+iomOWFpeOBq+mam+OBl+OBpuOBr+OAgeWNiuinkuaVsOWtl+OBp+WFpeWKm+OBl+OBpuOBj+OBoOOBleOBhOOAgiB8IDE4772eODDmrbPvvIhRdWFsdHJpY3Pjga7jg4njg63jg4Pjg5fjg4Djgqbjg7PvvIkgfA0KfCBRMi40IHwg44GC44Gq44Gf44GM5pyA5b6M44Gr5Y2S5qWt44GX44Gf5a2m5qCh44Gv5qyh44Gu44GG44Gh44Gp44KM44Gn44GX44KH44GG44GL44CCIO+8iuS4remAgOOBl+OBn+aWueOChOWcqOexjeS4reOBruaWueOCguWNkualreOBqOOBv+OBquOBl+OBpuOBj+OBoOOBleOBhOOAgiB8IOWwj+Wtpuagoe+8iOaXp+Wwj+ODu+aXp+mrmOWwj++8ieWNkualrSAoMSnvvI/pq5jmoKHvvIjml6fkuK3vvInljZLmpa0gKDIp77yP6auY562J5bCC6ZaA44O755+t5pyf5aSn5a2m44O75bCC5L+u5a2m5qCh5Y2S5qWtICgzKe+8jzTlubTliLblpKflrabljZLmpa0gKDQp77yP5aSn5a2m6Zmi5Y2S5qWtICg1Ke+8j+OCj+OBi+OCieOBquOBhCAoNinvvI/jgZPjgZ/jgYjjgarjgYQgKDcpIHwNCnwgUTIuNyB8IOOBguOBquOBn+OBr+OBqeOBruaUv+WFmuOCkuaUr+aMgeOBl+OBpuOBiuOCieOCjOOBvuOBmeOBi+OAgiB8IOiHqueUseawkeS4u+WFmiAoMSnvvI/nq4vmhrLmsJHkuLvlhZogKDIp77yP5YWs5piO5YWaICgzKe+8j+aXpeacrOe2reaWsOOBruS8miAoNCnvvI/ml6XmnKzlhbHnlKPlhZogKDUp77yP5Zu95rCR5rCR5Li75YWaICg2Ke+8j+ekvuS8muawkeS4u+WFmiAoNynvvI/jgozjgYTjgo/mlrDpgbjntYQgKDgp77yP44Gd44Gu5LuWICgxMSnvvI/mlK/mjIHjgZnjgovmlL/lhZrjga/jgarjgYQgKDEyKe+8j+OCj+OBi+OCieOBquOBhCAoMTMp77yP562U44GI44Gq44GEICgxNCkgfA0KfCBRMy4xIHwg44GC44Gq44Gf44Gu5LiW5biv44Gu56iO5byV44GN5YmN44Gu5LiW5biv5bm05Y+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+8iSB8DQoNCiMjIyBKLjEuMyDjgrPjg7Pjgrjjg6fjgqTjg7Pjg4joqrLpoYwNCuWbnuetlOiAheOBr+OAgTLjg7sz44O7NOODuzXmlL/lhZrjga7jgYTjgZrjgozjgYsx5p2h5Lu244Gr54Sh5L2c54K644Gr5Ymy44KK5b2T44Gm44KJ44KM44CB5ZCM44GY6YG45oqe6IKi5pWw44Gu6Kqy6aGM44GrNeWbnuetlOOBiOOBn+OAguWQhOiqsumhjOOBp+OBr+OAgeS4i+ihqOOBrjflsZ7mgKfjga7msLTmupbjgYzjg5fjg63jg5XjgqPjg7zjg6vjgZTjgajjgavnhKHkvZzngrrjgavmj5DnpLrjgZXjgozjgZ/jgIINCnwg5bGe5oCnIHwg5rC05rqWIHwNCnwtLS18LS0tfA0KfCDmlL/nrZbkvY3nva4gfCDlj7PmtL7jg7vkv53lrojnmoTvvI/kuK3pgZPvvI/lt6bmtL7jg7vpnanmlrDnmoQgfA0KfCDkuI7ph47lhZrlnLDkvY0gfCDkuI7lhZrvvI/ph47lhZogfA0KfCDorbDluK3mlbAgfCAxMOS7peS4i++8jzEw772eNDnvvI81MO+9njk577yPMTAw772eMTk577yPMjAw5Lul5LiKIHwNCnwgR0RQ5oiQ6ZW3546HIHwgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfA0KfCDml6XntYzlubPlnYfmoKrkvqEgfCDliY3mnIjlkIzmnJ/mr5Qg5aSJ44KP44KJ44Ga77yP44OX44Op44K5MTAwMOWGhu+8j+ODnuOCpOODiuOCuTEwMDDlhoYgfA0KfCBDUEkgfCDliY3mnJ/mr5QgwrEw44Od44Kk44Oz44OI77yP44OX44Op44K5MeODneOCpOODs+ODiO+8j+ODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4ggfA0KfCDlpLHmpa3njocgfCDliY3mnJ/mr5QgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfA0KDQoqKuadoeS7tuWIpeOBruiqrOaYjuaWh+ODu+mBuOaKnuiqsumhjCoqDQoNCiMjIyMgMuaUv+WFmuadoeS7tu+8iCRrPTIk77yJDQoqKuWwjuWFpeizquWVjyoqICANCuS7iuOBi+OCieOAgeaXpeacrOOBruaUv+WFmuOCgeOBkOOCi++8kuOBpOOBrumBuOaKnuiCouOCkumghuOBq+aPkOekuuOBl+OBpuOBhOOBjeOBvuOBmeOAgiDjgZ3jgZfjgabjgIHooYborbDpmaLnt4/pgbjmjJnjgYzjgYLjgovjgajjgYrogIPjgYjkuIvjgZXjgYTjgILjgZ3jga7mmYLjgIHjgYLjgarjgZ/jga/vvJPjgaTjga7pgbjmip7ogqLjga7kuK3jgYvjgonjganjga7mlL/lhZrjgpLpgbjmip7jgZXjgozjgovjgYvjgIHvvJHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgIIg5L2c5qWt44Gv77yV5Zue57mw44KK6L+U44GV44KM44G+44GZ44CCDQoNCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0NCg0KKirpgbjmip7oqrLpoYzvvIg15Zue77yJKiogIA0K5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLMuOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jganjgaHjgonjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIg5pS/5YWaMSDmlL/lhZoyICR7ZTovL0ZpZWxkL0YtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMi0xfSAke2U6Ly9GaWVsZC9GLTEtMn0gJHtlOi8vRmllbGQvRi0xLTEtMn0gJHtlOi8vRmllbGQvRi0xLTItMn0gJHtlOi8vRmllbGQvRi0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0yLTN9ICR7ZTovL0ZpZWxkL0YtMS00fSAke2U6Ly9GaWVsZC9GLTEtMS00fSAke2U6Ly9GaWVsZC9GLTEtMi00fSAke2U6Ly9GaWVsZC9GLTEtNX0gJHtlOi8vRmllbGQvRi0xLTEtNX0gJHtlOi8vRmllbGQvRi0xLTItNX0gJHtlOi8vRmllbGQvRi0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0yLTZ9ICR7ZTovL0ZpZWxkL0YtMS03fSAke2U6Ly9GaWVsZC9GLTEtMS03fSAke2U6Ly9GaWVsZC9GLTEtMi03fQ0KDQrlm57nrZTpgbjmip7ogqLvvJrmlL/lhZoxICgxKe+8j+aUv+WFmjIgKDIpDQoNCiMjIyMgM+aUv+WFmuadoeS7tu+8iCRrPTMk77yJDQoqKuWwjuWFpeizquWVjyBRMjU3KiogIA0K5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yT44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBr++8k+OBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIINCg0K5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQ0KDQoqKumBuOaKnuiqsumhjO+8iDXlm57vvIkqKiAgDQrku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgovvvJPjgaTjga7pgbjmip7ogqLjgpLmj5DnpLrjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgIIg44GC44Gq44Gf44Gv44CB6KGG6K2w6Zmi6K2w5ZOh57eP6YG45oyZ44Gr44GK44GE44Gm44CB5Lul5LiL44Gu44Gp44Gh44KJ44Gu5pS/5YWa44KS44GK6YG444Gz44Gr44Gq44KK44G+44GZ44GL44CCIOaUv+WFmjEg5pS/5YWaMiDmlL/lhZozICR7ZTovL0ZpZWxkL0YtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMi0xfSAke2U6Ly9GaWVsZC9GLTEtMy0xfSAke2U6Ly9GaWVsZC9GLTEtMn0gJHtlOi8vRmllbGQvRi0xLTEtMn0gJHtlOi8vRmllbGQvRi0xLTItMn0gJHtlOi8vRmllbGQvRi0xLTMtMn0gJHtlOi8vRmllbGQvRi0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0yLTN9ICR7ZTovL0ZpZWxkL0YtMS0zLTN9ICR7ZTovL0ZpZWxkL0YtMS00fSAke2U6Ly9GaWVsZC9GLTEtMS00fSAke2U6Ly9GaWVsZC9GLTEtMi00fSAke2U6Ly9GaWVsZC9GLTEtMy00fSAke2U6Ly9GaWVsZC9GLTEtNX0gJHtlOi8vRmllbGQvRi0xLTEtNX0gJHtlOi8vRmllbGQvRi0xLTItNX0gJHtlOi8vRmllbGQvRi0xLTMtNX0gJHtlOi8vRmllbGQvRi0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0yLTZ9ICR7ZTovL0ZpZWxkL0YtMS0zLTZ9ICR7ZTovL0ZpZWxkL0YtMS03fSAke2U6Ly9GaWVsZC9GLTEtMS03fSAke2U6Ly9GaWVsZC9GLTEtMi03fSAke2U6Ly9GaWVsZC9GLTEtMy03fQ0KDQrlm57nrZTpgbjmip7ogqLvvJrmlL/lhZoxICgxKe+8j+aUv+WFmjIgKDIp77yP5pS/5YWaMyAoMykNCg0KIyMjIyA05pS/5YWa5p2h5Lu277yIJGs9NCTvvIkNCioq5bCO5YWl6LOq5ZWPIFEyNTgqKiAgDQrku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJTjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44Gv77yT44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu5pS/5YWa44KS6YG45oqe44GV44KM44KL44GL44CB77yR44Gk6YG444KT44Gn44GK562U44GI44GP44Gg44GV44GE44CCIOS9nOalreOBr++8leWbnue5sOOCiui/lOOBleOCjOOBvuOBmeOAgg0KDQrlm57nrZTvvJrjgIzkuIroqJjjga7mlofnq6DjgpLoqq3jgpPjgaDjgIIgKDEp44CNDQoNCioq6YG45oqe6Kqy6aGM77yINeWbnu+8iSoqICANCuS7peS4i+OBq+OAgeaXpeacrOOBruaUv+WFmuOCkuOCgeOBkOOCi++8lOOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jganjgaHjgonjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIg5pS/5YWaMSDmlL/lhZoyIOaUv+WFmjMg5pS/5YWaNCAke2U6Ly9GaWVsZC9GLTEtMX0gJHtlOi8vRmllbGQvRi0xLTEtMX0gJHtlOi8vRmllbGQvRi0xLTItMX0gJHtlOi8vRmllbGQvRi0xLTMtMX0gJHtlOi8vRmllbGQvRi0xLTQtMX0gJHtlOi8vRmllbGQvRi0xLTJ9ICR7ZTovL0ZpZWxkL0YtMS0xLTJ9ICR7ZTovL0ZpZWxkL0YtMS0yLTJ9ICR7ZTovL0ZpZWxkL0YtMS0zLTJ9ICR7ZTovL0ZpZWxkL0YtMS00LTJ9ICR7ZTovL0ZpZWxkL0YtMS0zfSAke2U6Ly9GaWVsZC9GLTEtMS0zfSAke2U6Ly9GaWVsZC9GLTEtMi0zfSAke2U6Ly9GaWVsZC9GLTEtMy0zfSAke2U6Ly9GaWVsZC9GLTEtNC0zfSAke2U6Ly9GaWVsZC9GLTEtNH0gJHtlOi8vRmllbGQvRi0xLTEtNH0gJHtlOi8vRmllbGQvRi0xLTItNH0gJHtlOi8vRmllbGQvRi0xLTMtNH0gJHtlOi8vRmllbGQvRi0xLTQtNH0gJHtlOi8vRmllbGQvRi0xLTV9ICR7ZTovL0ZpZWxkL0YtMS0xLTV9ICR7ZTovL0ZpZWxkL0YtMS0yLTV9ICR7ZTovL0ZpZWxkL0YtMS0zLTV9ICR7ZTovL0ZpZWxkL0YtMS00LTV9ICR7ZTovL0ZpZWxkL0YtMS02fSAke2U6Ly9GaWVsZC9GLTEtMS02fSAke2U6Ly9GaWVsZC9GLTEtMi02fSAke2U6Ly9GaWVsZC9GLTEtMy02fSAke2U6Ly9GaWVsZC9GLTEtNC02fSAke2U6Ly9GaWVsZC9GLTEtN30gJHtlOi8vRmllbGQvRi0xLTEtN30gJHtlOi8vRmllbGQvRi0xLTItN30gJHtlOi8vRmllbGQvRi0xLTMtN30gJHtlOi8vRmllbGQvRi0xLTQtN30NCg0K5Zue562U6YG45oqe6IKi77ya5pS/5YWaMSAoMSnvvI/mlL/lhZoyICgyKe+8j+aUv+WFmjMgKDMp77yP5pS/5YWaNCAoNCkNCg0KIyMjIyA15pS/5YWa5p2h5Lu277yIJGs9NSTvvIkNCioq5bCO5YWl6LOq5ZWPIFEyNTkqKiAgDQrku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJXjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44Gv77yT44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu5pS/5YWa44KS6YG45oqe44GV44KM44KL44GL44CB77yR44Gk6YG444KT44Gn44GK562U44GI44GP44Gg44GV44GE44CCIOS9nOalreOBr++8leWbnue5sOOCiui/lOOBleOCjOOBvuOBmeOAgg0KDQrlm57nrZTvvJrjgIzkuIroqJjjga7mlofnq6DjgpLoqq3jgpPjgaDjgIIgKDEp44CNDQoNCioq6YG45oqe6Kqy6aGM77yINeWbnu+8iSoqICANCuS7peS4i+OBq+OAgeaXpeacrOOBruaUv+WFmuOCkuOCgeOBkOOCi++8leOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jganjgaHjgonjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIIg5pS/5YWaMSDmlL/lhZoyIOaUv+WFmjMg5pS/5YWaNCDmlL/lhZo1ICR7ZTovL0ZpZWxkL0YtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMS0xfSAke2U6Ly9GaWVsZC9GLTEtMi0xfSAke2U6Ly9GaWVsZC9GLTEtMy0xfSAke2U6Ly9GaWVsZC9GLTEtNC0xfSAke2U6Ly9GaWVsZC9GLTEtNS0xfSAke2U6Ly9GaWVsZC9GLTEtMn0gJHtlOi8vRmllbGQvRi0xLTEtMn0gJHtlOi8vRmllbGQvRi0xLTItMn0gJHtlOi8vRmllbGQvRi0xLTMtMn0gJHtlOi8vRmllbGQvRi0xLTQtMn0gJHtlOi8vRmllbGQvRi0xLTUtMn0gJHtlOi8vRmllbGQvRi0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0xLTN9ICR7ZTovL0ZpZWxkL0YtMS0yLTN9ICR7ZTovL0ZpZWxkL0YtMS0zLTN9ICR7ZTovL0ZpZWxkL0YtMS00LTN9ICR7ZTovL0ZpZWxkL0YtMS01LTN9ICR7ZTovL0ZpZWxkL0YtMS00fSAke2U6Ly9GaWVsZC9GLTEtMS00fSAke2U6Ly9GaWVsZC9GLTEtMi00fSAke2U6Ly9GaWVsZC9GLTEtMy00fSAke2U6Ly9GaWVsZC9GLTEtNC00fSAke2U6Ly9GaWVsZC9GLTEtNS00fSAke2U6Ly9GaWVsZC9GLTEtNX0gJHtlOi8vRmllbGQvRi0xLTEtNX0gJHtlOi8vRmllbGQvRi0xLTItNX0gJHtlOi8vRmllbGQvRi0xLTMtNX0gJHtlOi8vRmllbGQvRi0xLTQtNX0gJHtlOi8vRmllbGQvRi0xLTUtNX0gJHtlOi8vRmllbGQvRi0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0xLTZ9ICR7ZTovL0ZpZWxkL0YtMS0yLTZ9ICR7ZTovL0ZpZWxkL0YtMS0zLTZ9ICR7ZTovL0ZpZWxkL0YtMS00LTZ9ICR7ZTovL0ZpZWxkL0YtMS01LTZ9ICR7ZTovL0ZpZWxkL0YtMS03fSAke2U6Ly9GaWVsZC9GLTEtMS03fSAke2U6Ly9GaWVsZC9GLTEtMi03fSAke2U6Ly9GaWVsZC9GLTEtMy03fSAke2U6Ly9GaWVsZC9GLTEtNC03fSAke2U6Ly9GaWVsZC9GLTEtNS03fQ0KDQrlm57nrZTpgbjmip7ogqLvvJrmlL/lhZoxICgxKe+8j+aUv+WFmjIgKDIp77yP5pS/5YWaMyAoMynvvI/mlL/lhZo0ICg0Ke+8j+aUv+WFmjUgKDUpDQoNCuWun+mokzHjgavjga/jgIHlrp/pqJMy44O7M+OBp+eUqOOBhOOBn+mBuOaKnuiCouaVsOOBruaTjeS9nOeiuuiqjeizquWVj+OBiuOCiOOBs+OCpOODh+OCquODreOCruODvOihjOWIl+S4reOBruaMh+ekuumgheebruOBr+ioreOBkeOCieOCjOOBpuOBhOOBquOBhOOAgg0KDQojIyMgSi4xLjQg6Kq/5p+76Laj5peo44Gu5YaN6Kqs5piO44Go5pyA57WC6YCB5L+h5ZCM5oSPDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxzdHJvbmc+UTEwLjEg44OH44OW44Oq44O844OV44Kj44Oz44Kw44O75pyA57WC5oSP5oCd56K66KqN77yI44Kv44Oq44OD44Kv44GX44Gm5YWo5paH44KS6KGo56S677yJPC9zdHJvbmc+PC9zdW1tYXJ5Pg0KDQo8cD7jgZPjgaHjgonjgYzoqr/mn7vjga7mnIDlvozjga7nlLvpnaLjgafjgYLjgovjgIzoqr/mn7votqPml6jjga7lho3oqqzmmI7jgI3jgajjgIzlm57nrZTntZDmnpzjga7pgIHkv6HjgavplqLjgZnjgovmnIDntYLmhI/mgJ3norroqo3jgI3jga7jg5rjg7zjgrjjgavjgarjgorjgb7jgZnjgIIg44O75pys6Kq/5p+744Gn44Gv44CB5pS/5rK744CB57WM5riI44Gr6Zai44GZ44KL5oSP6K2Y44Gq44Gp44KS44GK5Ly644GE44GV44Gb44Gm44GE44Gf44Gg44GN44G+44GX44Gf44CC6Kq/5p+744Gr44GU5Y2U5Yqb44GE44Gf44Gg44GN44G+44GX44Gf44GT44Go44Gr44CB5rex44GP5oSf6Kyd55Sz44GX5LiK44GS44G+44GZ44CCIOODu+acrOiqv+afu+OBq+mWouOBl+OBpuOBlOS4jeaYjuOBqueCueetieOBjOOBlOOBluOBhOOBvuOBl+OBn+OCieOAgeS4i+iomOODoeODvOODq+OCouODieODrOOCueOBvuOBp+OBiuWVj+OBhOWQiOOCj+OBm+OBj+OBoOOBleOBhOOAgiBlLW1haWw6IGhhbmFrb29obXVyYTYxMDMxQGdtYWlsLmNvbSDjg7sg57mw44KK6L+U44GX44Go44Gq44KK44G+44GZ44GM44CB5b6X44KJ44KM44Gf5Zue562U44Gv44GZ44G544Gm57Wx6KiI55qE44Gr5Yem55CG44GX44CB5Zue562U6ICF44Gu5bGe5oCn44Gq44Gp44GM44KP44GL44KJ44Gq44GE44KI44GG44Gr44GX44G+44GZ44CC5YCL5Lq644Gu5oOF5aCx44GM54m55a6a44GV44KM44KL44GT44Go44Gv44GC44KK44G+44Gb44KT44Gu44Gn44CB44GU5a6J5b+D44GP44Gg44GV44GE44CC44Gd44KM44Gn44KC5YCL5Lq65oOF5aCx44Gu5L+d6K23562J44Gr6Zai44GX44Gm44CB5Zue562U6ICF44Gn44GC44KL44GC44Gq44Gf44GM44GU5LiN5a6J44KS5oSf44GY44KJ44KM44KL5aC05ZCI44Gr44Gv44CM5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5Zue562U44KS6YCB5L+h44GX44Gq44GE44CN44Go44GE44GG6YG45oqe44KS44GZ44KL44GT44Go44KC5Y+v6IO944Gn44GZ44CCIOS7peS4i+OBp+OBr+OAgeacrOiqv+afu+OBq+OBiuOBkeOCi+OBhOOBj+OBpOOBi+OBruWHpue9ruODu+aTjeS9nOOBq+OBpOOBjeOBvuOBl+OBpuOAgeOBneOBruebrueahOODu+iDjOaZr+ODu+S7lee1hOOBv+OCkuOAgeOCiOOCiuips+OBl+OBj+ino+iqrOOCkuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAguWPr+iDveOBqumZkOOCiuOBlOS4gOiqreOBhOOBn+OBoOOBjeOAgeOAjOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBmeOCi+OBruOBp+OAgeWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCi+OAjeOBi+OAjOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBquOBhOOBruOBp+OAgeWbnuetlOe1kOaenOOCkumAgeS/oeOBl+OBquOBhOOAjeOCkuOBlOmBuOaKnuOBj+OBoOOBleOBhOOBvuOBmeOCiOOBhuOCiOOCjeOBl+OBj+OBiumhmOOBhOOBhOOBn+OBl+OBvuOBmeOAgiDkuIroqJjjga7lhoXlrrnjgpLjgZTnorroqo3jgYTjgZ/jgaDjgYTjgZ/kuIrjgafjgIHmlLnjgoHjgabjgIzmnKzoqr/mn7vjga7otqPml6jjgavlkIzmhI/jgZfjgarjgYTjga7jgafjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZfjgarjgYTjgI3jgajjgYTjgYbpgbjmip7jgpLjgZnjgovjgZPjgajjgoLlj6/og73jgafjgZnjga7jgafjgIHku6XkuIvjgafjgZTpgbjmip7jgY/jgaDjgZXjgYTjgII8L3A+DQoNCjwvZGV0YWlscz4NCg0KKirlm57nrZTpgbjmip7ogqIqKg0KDQotIOacrOiqv+afu+OBruS4u+aXqOOBq+WQjOaEj+OBl+OAgeWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCi+OAgiAoMSkNCi0g5pys6Kq/5p+744Gu5Li75peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5Zue562U57WQ5p6c44KS6YCB5L+h44GX44Gq44GE44CCICgyKQ0KDQroqr/mn7vnpajmnKvlsL7jgavjga9RMjYx44CM44GT44GT44KS44Kv44Oq44OD44Kv44GX44Gm6LOq5ZWP5paH44KS5YWl5Yqb44CN44Go44GE44GGUXVhbHRyaWNz5LiK44Gu5pyq5L2/55So44OX44Os44O844K544Ob44Or44OA44O844GM5q6L44Gj44Gm44GE44KL44GM44CBIOWun+izqueahOOBquiqv+afu+mgheebruOBp+OBr+OBquOBhOOBn+OCgeOAgeacrOevgOOBruizquWVj+S4gOimp+OBi+OCieOBr+mZpOWkluOBl+OBn+OAgg0KDQojIyBKLjIg5a6f6aiTMu+8iDIwMjblubTvvIkNCg0KIyMjIEouMi4xIOiqv+afu+mWi+Wni+aZguOBruiqrOaYjuOBqOWQjOaEjw0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxzdHJvbmc+UTEuMSDoqr/mn7voqqzmmI7vvIjjgq/jg6rjg4Pjgq/jgZfjgablhajmlofjgpLooajnpLrvvIk8L3N0cm9uZz48L3N1bW1hcnk+DQoNCjxwPuOAjOe1jOa4iOipleS+oeOBqOaUv+aoqemBi+WWtuOCkuOCgeOBkOOCi+aEj+itmOiqv+afu+OAjSDjgZTljZTlipvjga7jgYrpoZjjgYQg5Lqs6YO95aSn5a2mIOWFrOWFseaUv+etlumAo+aQuueglOeptumDqCDmlZnmjogg5aSn5p2RIOiPr+WtkCDvvIjjgYrjgYrjgoDjgokg44Gv44Gq44GT77yJIOKXhiDjgZPjga7jgqLjg7PjgrHjg7zjg4joqr/mn7vjga/jgIHmlofpg6jnp5HlrabnnIHjgavjgojjgovnoJTnqbbliqnmiJDvvIjnoJTnqbboqrLpoYznlarlj7fvvJoyNkswNDc1MeOAjOaUv+etlualree4vuipleS+oeOBrueglOeptu+8jeaUv+ayu+ihjOWLleirluOBqOihjOWLleWFrOWFseaUv+etluirluOBruaetuapi+OAje+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+DQoNCjwvZGV0YWlscz4NCg0KKirlm57nrZTpgbjmip7ogqIqKg0KDQotIOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBpuOAgeacrOiqv+afu+OBq+WNlOWKm+OBmeOCiyAoMSkNCi0g5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5pys6Kq/5p+744Gr5Y2U5Yqb44GX44Gq44GEICgyKQ0KDQojIyMgSi4yLjIg44OV44Kn44Kk44K544K344O844OIDQoNCnwg6LOq5ZWPSUQgfCDos6rllY/mlocgfCDlm57nrZTlvaLlvI/jg7vpgbjmip7ogqIgfA0KfC0tLXwtLS18LS0tfA0KfCBRMi4xIHwg44GC44Gq44Gf44Gu5oCn5Yil44KS6YG444KT44Gn44GP44Gg44GV44GE44CCIHwg55S35oCnICgxKe+8j+Wls+aApyAoMinvvI/jgZ3jga7ku5YgKDMp77yP44GT44Gf44GI44Gf44GP44Gq44GEICg0KSB8DQp8IFEyLjIgfCDjgYLjgarjgZ/jga7lubTpvaLljLrliIbjgajnj77lnKjjga7lubTpvaLjgpLpgbjjgpPjgafjgY/jgaDjgZXjgYTjgIIgfCDjgIzlubTku6PjgI3jgajjgIzlubTpvaLjgI3jga7pgKPli5Xjg4njg63jg4Pjg5fjg4Djgqbjg7PjgILoqr/mn7vnpajjgqjjgq/jgrnjg53jg7zjg4jkuIrjgafjga/pgbjmip7ogqLkuIDopqfjgYznnIHnlaXooajnpLrjgZXjgozjgabjgYTjgovjgIIgfA0KfCBRMi4zIHwg44GC44Gq44Gf44GM54++5Zyo44GK5L2P44G+44GE44Gu5Zyw5Z+f44Go6YO96YGT5bqc55yM44KS6YG444KT44Gn44GP44Gg44GV44GEIHwg44CM5Zyw5Z+f44CN44Go44CM6YO96YGT5bqc55yM44CN44Gu6YCj5YuV44OJ44Ot44OD44OX44OA44Km44Oz44CC6Kq/5p+756Wo44Ko44Kv44K544Od44O844OI5LiK44Gn44Gv6YG45oqe6IKi5LiA6Kan44GM55yB55Wl6KGo56S644GV44KM44Gm44GE44KL44CCIHwNCnwgUTIuNCB8IOOBguOBquOBn+OBruS4luW4r+OBrueojuW8leOBjeWJjeOBruS4luW4r+W5tOWPjuOBqOaJi+WPluOCiuOBruW5tOWPjuOBr+OAgeOBoOOBhOOBn+OBhOOBiuOBhOOBj+OCieOBkOOCieOBhOOBp+OBl+OCh+OBhuOBi+OAgiDnqI7lvJXjgY3liY3jga7lj47lhaXjgajjga/jgIHkuIDoiKznmoTjgavjgIzpoY3pnaLjga7lj47lhaXjgI3jgajoqIDjgo/jgozjgovjgoLjga7jgafjgZnjgILjgZ3jga7poY3pnaLjga7lj47lhaXjgYvjgonjgIHnqI7ph5HjgoTnpL7kvJrkv53pmbrmlpnjgpLlvJXjgYTjgZ/mrovjgorjgYzjgIzmiYvlj5bjgorjga7lj47lhaXjgI3jgajoqIDjgo/jgozjgovjgoLjga7jgafjgZnjgIIg44GC44Gq44Gf44Gu5Y+O5YWl44CB6YWN5YG26ICF44Gu5Y+O5YWl44KS44GZ44G544Gm5ZCr44KB44Gf44KC44Gu44KS44CB5Lul5LiL44Gu54mp5beu44GX44KS44K544Op44Kk44OJ44GV44Gb44Gq44GM44KJ44CB44GK44GK44G+44GL44Gr5oyH5a6a44GX44Gm44GP44Gg44GV44GE44CCIOOBhOOBmuOCjOOCguOBjOOAjDMwMDDkuIflhobku6XkuIrjgI3jga7kurrjga/jgIHjgIwzMDAw44CN44KS6YG45oqe44GX44Gm44GP44Gg44GV44GE44CCIHwg56iO5byV44GN5YmN5LiW5biv5bm05Y+O44O75omL5Y+W44KK5bm05Y+O44GuMumgheebruOAgjDvvZ4zMDAw5LiH5YaG44Gu44K544Op44Kk44OA44O877yIMzAwMO+8nTMwMDDkuIflhobku6XkuIrvvIkgfA0KDQojIyMgSi4yLjMg44Kz44Oz44K444On44Kk44Oz44OI6Kqy6aGMDQoNCuWbnuetlOiAheOBrzLjg7sz44O7NOODuzXmlL/lhZrjga7jgYTjgZrjgozjgYsx5p2h5Lu244Gr54Sh5L2c54K644Gr5Ymy44KK5b2T44Gm44KJ44KM44CBNeOBpOOBrumBuOaKnuiqsumhjOOBq+WbnuetlOOBl+OBn+OAguODl+ODreODleOCo+ODvOODq+OBq+OBr+asoeOBrjflsZ7mgKfjgYzmj5DnpLrjgZXjgozjgZ/jgIINCnwg5bGe5oCnIHwg5rC05rqWIHwNCnwtLS18LS0tfA0KfCDmlL/nrZbkvY3nva4gfCDlj7PmtL7jg7vkv53lrojnmoTvvI/kuK3pgZPvvI/lt6bmtL7jg7vpnanmlrDnmoQgfA0KfCDkuI7ph47lhZrlnLDkvY0gfCDkuI7lhZrvvI/ph47lhZogfA0KfCDorbDluK3mlbAgfCAxMOS7peS4i++8jzEw772eNDnvvI81MO+9njk577yPMTAw772eMTk577yPMjAw5Lul5LiKIHwNCnwgR0RQ5oiQ6ZW3546HIHwgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfA0KfCDml6XntYzlubPlnYfmoKrkvqEgfCDliY3mnIjlkIzmnJ/mr5Qg5aSJ44KP44KJ44Ga77yP44OX44Op44K5MTAwMOWGhu+8j+ODnuOCpOODiuOCuTEwMDDlhoYgfA0KfCBDUEkgfCDliY3mnJ/mr5QgwrEw44Od44Kk44Oz44OI77yP44OX44Op44K5MeODneOCpOODs+ODiO+8j+ODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4ggfA0KfCDlpLHmpa3njocgfCDliY3mnJ/mr5QgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfA0KDQoqKuadoeS7tuWIpeOBruiqrOaYjuaWh+ODu+mBuOaKnuiqsumhjOODu+aTjeS9nOeiuuiqjSoqDQoNCiMjIyMgMuaUv+WFmuadoeS7tu+8iCRrPTIk77yJDQoqKuWwjuWFpeizquWVjyBRNi4xKiogIA0K5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yS44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBrzLjgaTjga7pgbjmip7ogqLjga7kuK3jgYvjgonjganjga7mlL/lhZrjgpLpgbjmip7jgZXjgozjgovjgYvjgIHvvJHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgIIg5L2c5qWt44Gv77yV5Zue57mw44KK6L+U44GV44KM44G+44GZ44CCDQoNCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0NCg0KKirpgbjmip7oqrLpoYwgUTYuMuKAk1E2LjbvvIg15Zue77yJKiogIA0K5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLMuOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDjgYLjgarjgZ/jga/jgIHooYborbDpmaLorbDlk6Hnt4/pgbjmjJnjgavjgYrjgYTjgabjgIHku6XkuIvjga7jgYTjgZrjgozjga7mlL/lhZrjgpLjgYrpgbjjgbPjgavjgarjgorjgb7jgZnjgYvjgIINCg0K5Zue562U6YG45oqe6IKi77ya5pS/5YWaMSAoMSnvvI/mlL/lhZoyICgyKQ0KDQoqKuaTjeS9nOeiuuiqjSBRNi43KiogIA0K44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/mlL/lhZrjga7pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIINCg0K5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikNCg0KIyMjIyAz5pS/5YWa5p2h5Lu277yIJGs9MyTvvIkNCioq5bCO5YWl6LOq5ZWPIFEzLjEqKiAgDQrku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJPjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44Gv77yT44Gk44Gu6YG45oqe6IKi44Gu5Lit44GL44KJ44Gp44Gu5pS/5YWa44KS6YG45oqe44GV44KM44KL44GL44CB77yR44Gk6YG444KT44Gn44GK562U44GI44GP44Gg44GV44GE44CCIOS9nOalreOBr++8leWbnue5sOOCiui/lOOBleOCjOOBvuOBmeOAgg0KDQrlm57nrZTvvJrjgIzkuIroqJjjga7mlofnq6DjgpLoqq3jgpPjgaDjgIIgKDEp44CNDQoNCioq6YG45oqe6Kqy6aGMIFEzLjLigJNRMy4277yINeWbnu+8iSoqICANCuS7peS4i+OBq+OAgeaXpeacrOOBruaUv+WFmuOCkuOCgeOBkOOCizPjgaTjga7pgbjmip7ogqLjgpLmj5DnpLrjgZXjgZvjgabjgYTjgZ/jgaDjgY3jgb7jgZnjgIIg44GC44Gq44Gf44Gv44CB6KGG6K2w6Zmi6K2w5ZOh57eP6YG45oyZ44Gr44GK44GE44Gm44CB5Lul5LiL44Gu44GE44Ga44KM44Gu5pS/5YWa44KS44GK6YG444Gz44Gr44Gq44KK44G+44GZ44GL44CCDQoNCuWbnuetlOmBuOaKnuiCou+8muaUv+WFmjEgKDEp77yP5pS/5YWaMiAoMinvvI/mlL/lhZozICgzKQ0KDQoqKuaTjeS9nOeiuuiqjSBRMy43KiogIA0K44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/mlL/lhZrjga7pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIINCg0K5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikNCg0KIyMjIyA05pS/5YWa5p2h5Lu277yIJGs9NCTvvIkNCioq5bCO5YWl6LOq5ZWPIFE0LjEqKiAgDQrku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJTjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44GvNOOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIINCg0K5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQ0KDQoqKumBuOaKnuiqsumhjCBRNC4y4oCTUTQuNu+8iDXlm57vvIkqKiAgDQrku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgos044Gk44Gu6YG45oqe6IKi44KS5o+Q56S644GV44Gb44Gm44GE44Gf44Gg44GN44G+44GZ44CCIOOBguOBquOBn+OBr+OAgeihhuitsOmZouitsOWToee3j+mBuOaMmeOBq+OBiuOBhOOBpuOAgeS7peS4i+OBruOBhOOBmuOCjOOBruaUv+WFmuOCkuOBiumBuOOBs+OBq+OBquOCiuOBvuOBmeOBi+OAgg0KDQrlm57nrZTpgbjmip7ogqLvvJrmlL/lhZoxICgxKe+8j+aUv+WFmjIgKDIp77yP5pS/5YWaMyAoMynvvI/mlL/lhZo0ICg0KQ0KDQoqKuaTjeS9nOeiuuiqjSBRNC43KiogIA0K44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/mlL/lhZrjga7pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIINCg0K5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikNCg0KIyMjIyA15pS/5YWa5p2h5Lu277yIJGs9NSTvvIkNCioq5bCO5YWl6LOq5ZWPIFE1LjEqKiAgDQrku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJXjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44GvNeOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBruaUv+WFmuOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIINCg0K5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQ0KDQoqKumBuOaKnuiqsumhjCBRNS4y4oCTUTUuNu+8iDXlm57vvIkqKiAgDQrku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgos144Gk44Gu6YG45oqe6IKi44KS5o+Q56S644GV44Gb44Gm44GE44Gf44Gg44GN44G+44GZ44CCIOOBguOBquOBn+OBr+OAgeihhuitsOmZouitsOWToee3j+mBuOaMmeOBq+OBiuOBhOOBpuOAgeS7peS4i+OBruOBhOOBmuOCjOOBruaUv+WFmuOCkuOBiumBuOOBs+OBq+OBquOCiuOBvuOBmeOBi+OAgg0KDQrlm57nrZTpgbjmip7ogqLvvJrmlL/lhZoxICgxKe+8j+aUv+WFmjIgKDIp77yP5pS/5YWaMyAoMynvvI/mlL/lhZo0ICg0Ke+8j+aUv+WFmjUgKDUpDQoNCioq5pON5L2c56K66KqNIFE1LjcqKiAgDQrjgYLjgarjgZ/jgavjga/jgIHopIfmlbDjga7pgbjmip7ogqLjga7kuK3jgYvjgokx44Gk44Gu54q25rOB44KS6YG444KT44Gn44KC44KJ44GG5L2c5qWt44KS6KGM44Gj44Gm44GE44Gf44Gg44GN44G+44GX44Gf44CCIOOBguOBquOBn+OBq+aPkOekuuOBleOCjOOBn+aUv+WFmuOBrumBuOaKnuiCouOBruaVsOOBr+OAgeOBhOOBj+OBpOOBp+OBl+OBn+OBi+OAgg0KDQrlm57nrZTpgbjmip7ogqLvvJoxICgxKe+8jzIgKDIp77yPMyAoMynvvI80ICg0Ke+8jzUgKDUp77yP44GK44G844GI44Gm44GE44Gq44GEICg2KQ0KDQojIyMgSi4yLjQg5pS/5rK76LOq5ZWPDQoNCioqUTcuMSoqICANCuaUv+ayu+eahOeri+WgtOOCkuihqOOBmeOBruOBq+OAgeOCiOOBj+OAjOWPs+a0vuOAjeOAjOW3pua0vuOAjeOBqOOBhOOBhuiogOiRieOBjOS9v+OCj+OCjOOBvuOBmeOAgjHjgYzlj7PmtL7nmoTjgIE244GM5Lit6ZaT44CBMTHjgYzlt6bmtL7nmoTjgaDjgajjgZnjgovjgajjgIHjgYLjgarjgZ/jgoTkuLvopoHmlL/lhZrjga/jganjga7jgYLjgZ/jgorjgavkvY3nva7ku5jjgZHjgonjgozjgovjgajjgYrogIPjgYjjgafjgZfjgofjgYbjgYvjgIINCg0K5Zue562U5bC65bqm77yaMe+8iOWPs+a0vueahO+8ie+8jzLvvI8z77yPNO+8jzXvvI8277yI5Lit6ZaT77yJ77yPN++8jzjvvI8577yPMTDvvI8xMe+8iOW3pua0vueahO+8ie+8j+OCj+OBi+OCieOBquOBhO+8j+OBk+OBn+OBiOOBn+OBj+OBquOBhOOAgg0KDQroqZXkvqHlr77osaHvvJrjgYLjgarjgZ/oh6rouqvvvIhRMjUuMV8x77yJ44CB6Ieq55Sx5rCR5Li75YWa77yIUTI1LjFfMu+8ieOAgeeri+aGsuawkeS4u+WFmu+8iFEyNS4xXzPvvInjgIHml6XmnKzntq3mlrDjga7kvJrvvIhRMjUuMV8077yJ44CB5YWs5piO5YWa77yIUTI1LjFfMTDvvInjgIHlm73msJHmsJHkuLvlhZrvvIhRMjUuMV8177yJ44CB44KM44GE44KP5paw6YG457WE77yIUTI1LjFfNu+8ieOAgeWPguaUv+WFmu+8iFEyNS4xXzfvvInjgIHlhbHnlKPlhZrvvIhRMjUuMV8477yJ44CB5Lit6YGT5pS56Z2p6YCj5ZCI77yIUTI1LjFfOe+8ieOAgSoq44CM77yB44GT44Gu6aCF55uu44Gv5b+F44Ga44COM+OAj+OCkumBuOOCk+OBp+OBj+OBoOOBleOBhO+8geOAje+8iFEyNS4xXzEx77yJKirjgIINCg0KKipRNy4yKiogIA0K6YG45oyZ44Gn44Gp44GT44Gr5oqV56Wo44GZ44KL44GL44Gv5Yil44Gr44GX44Gm44CB5Zu944Gu5pS/5rK744Gn44CB44GC44Gq44Gf44Gv44Gp44Gu5pS/5YWa44GC44KL44GE44Gv5pS/5rK75Zuj5L2T44KS5pSv5oyB44GX44Gm44GE44G+44GZ44GL44CCDQoNCi0g6Ieq55Sx5rCR5Li75YWaICgxKQ0KLSDkuK3pgZPmlLnpnanpgKPlkIggKDIpDQotIOeri+aGsuawkeS4u+WFmiAoMTgpDQotIOWFrOaYjuWFmiAoMTkpDQotIOaXpeacrOe2reaWsOOBruS8miAoMykNCi0g5Zu95rCR5rCR5Li75YWaICg0KQ0KLSDjgozjgYTjgo/mlrDpgbjntYQgKDUpDQotIOWFseeUo+WFmiAoNikNCi0g5Y+C5pS/5YWaICg3KQ0KLSDml6XmnKzkv53lrojlhZogKDgpDQotIOekvuawkeWFmiAoOSkNCi0g44OB44O844Og44G/44KJ44GEICgxMCkNCi0g44Gd44Gu5LuW44Gu5pS/5YWa44O75pS/5rK75Zuj5L2T77yI5YW35L2T55qE44Gr77yJICgxMikgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18NCi0g44Gd44Gu44KI44GG44Gq5pS/5YWa44Gv44Gq44GEICgxMykNCi0g44KP44GL44KJ44Gq44GEICgxNCkNCi0g44GT44Gf44GI44Gf44GP44Gq44GEICgxNSkNCg0KKipRNy4zKiogIA0K44GC44Gq44Gf44GM5pmu5q6144CB5pS/5rK744Gr6Zai44GZ44KL5oOF5aCx44KS6KaL44Gf44KK44CB6IGe44GE44Gf44KK44GZ44KL44Gf44KB44Gr5L2/44GG5aqS5L2T44Gv44CB44Gp44KM44Gn44GX44KH44GG44GL44CC44GC44KL44Gg44GR6YG444KT44Gn44GP44Gg44GV44GE44CCDQoNCi0g5paw6IGe77yI5pyd5YiK77yJICgxKQ0KLSDjgrnjg53jg7zjg4TmlrDogZ4gKDIpDQotIOmAseWIiuiqjCAoMykNCi0g5pS/6KaL5pS+6YCBICg0KQ0KLSDjg4bjg6zjg5Pjga7jg4vjg6Xjg7zjgrkgKDUpDQotIOODr+OCpOODieOCt+ODp+ODvOOChOiojuirlueVque1hCAoNikNCi0g44Oe44OL44OV44Kn44K544OI44O76YG45oyZ5YWs5aCxICg3KQ0KLSDjgqTjg7Pjgr/jg7zjg43jg4Pjg4jkuIrjga7jg4vjg6Xjg7zjgrnoqJjkuosoU05T5ZCr44KAKSAoOCkNCi0g5pS/5YWa44KE5YCZ6KOc6ICF44Gu44Ob44O844Og44Oa44O844K444Gq44GpKFNOU+WQq+OCgCkgKDkpDQotIOOBneOBruS7lu+8iOWFt+S9k+eahOOBq++8iSAoMTApIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQotIOKKl+imi+iBnuOBjeOBl+OBpuOBhOOBquOBhCAoMTEpDQotIOKKl+OCj+OBi+OCieOBquOBhCAoMTIpDQotIOKKl+OBk+OBn+OBiOOBn+OBj+OBquOBhCAoMTMpDQoNCiMjIyBKLjIuNSDoqr/mn7votqPml6jjga7lho3oqqzmmI7jgajmnIDntYLpgIHkv6HlkIzmhI8NCg0KPGRldGFpbHM+DQo8c3VtbWFyeT48c3Ryb25nPlE4LjEg44OH44OW44Oq44O844OV44Kj44Oz44Kw44O75pyA57WC5oSP5oCd56K66KqN77yI44Kv44Oq44OD44Kv44GX44Gm5YWo5paH44KS6KGo56S677yJPC9zdHJvbmc+PC9zdW1tYXJ5Pg0KDQo8cD7jgZPjgaHjgonjgYzoqr/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+44GX44Gf44CC55qG5qeY44Gr44Gv44CBIDLjgaTjga7mlL/lhZrjga7kuK3jgYvjgokx44Gk44KS6YG444G2IDPjgaTjga7mlL/lhZrjga7kuK3jgYvjgokx44Gk44KS6YG444G2IDTjgaTjga7mlL/lhZrjga7kuK3jgYvjgokx44Gk44KS6YG444G2IDXjgaTjga7mlL/lhZrjga7kuK3jgYvjgokx44Gk44KS6YG444G2IOOBqOOBhOOBhuS9nOalreOBruOBhuOBoeOBrjHjgaTjgpLjgIHnubDjgorov5TjgZfjgaY15Zue6KGM44Gj44Gm44GE44Gf44Gg44GN44G+44GX44Gf44CCIOODu+ihqOOBruS4reOBq+OBn+OBj+OBleOCk+OBruaDheWgseOBjOe1hOOBv+i+vOOBvuOCjOOBpuOBhOOCi+OBhuOBiOOBq+OAgeOBleOCieOBq+izquWVj+OCkumHjeOBreOBn+OBk+OBqOOBp+OAgeeahuOBleOBvuOBruS4reOBq+OBr+OAgeWbnuetlOOBjOOCj+OBmuOCieOCj+OBl+OBj+OAgeS9leOBi+OCkuiAg+OBiOOBn+OCiumBuOOCk+OBoOOCiuOBmeOCi+S9nOalreOCkumdouWAkuOBoOOBqOaEn+OBmOOAgeWbnuetlOOCkuS4jeW/q+OBq+aAneOCj+OCjOOBn+aWueOBjOOBiuOCieOCjOOBn+OBi+OCguOBl+OCjOOBvuOBm+OCk+OAguOBneOBruOCiOOBhuOBquS4reOAgeacgOW+jOOBvuOBp+OBlOWbnuetlOOBj+OBoOOBleOBo+OBn+OBk+OBqOOBq+OAgeS9leOCiOOCiuaEn+isneeUs+OBl+S4iuOBkuOBvuOBmeOAgiDjg7vmnKzoqr/mn7vjga/jgIHmlL/lhZrlkI3jgajntYzmuIjnirbms4HjgYznpLrjgZXjgozjgZ/mmYLjgavjgIHnp4HjgZ/jgaHjga/jganjgaHjgonjgavjgoLjgajjgaXjgYTjgabmlL/lhZrjgpLpgbjjgbzjgYbjgajjgZnjgovjga7jgYvjgpLmmI7jgonjgYvjgavjgZnjgovjgZ/jgoHjga7jgoLjga7jgafjgZfjgZ/jgIIg44O744Gd44Gu44Gf44KB44Gr55qG5qeY44Gr44Gv44CB5pS/5rK76ZuG5Zuj44CB44Kk44OH44Kq44Ot44Ku44O844CB5YWa5rS+5oCn44Gr6Zai44KP44KL44GT44Go44KS44GK562U44GI44GE44Gf44Gg44GE44Gf44KK44CB44Gd44KM44KJ44Gr5a++44GZ44KL55qG5qeY44Gu44GK6ICD44GI44O744GU5oSP5ZCR44KS44GK5Ly644GE44GZ44KL44GT44Go44Gr44Gq44KK44G+44GX44Gf44CCIOODu+OBk+OBruOCiOOBhuOBquiDjOaZr+OCkuOCguOBpOiqv+afu+OBp+OBr+OBguOCiuOBvuOBmeOBjOOAgeWbnuetlOOBq+OBlOWNlOWKm+OBj+OBoOOBleOBo+OBn+eahuanmOOBruS4reOBq+OBr+OAgeS4jeW/q+aEn+OCkuaKseOBi+OCjOOBn+aWueOBjOOBiuOCieOCjOOCi+OBi+OCguOBl+OCjOOBvuOBm+OCk+OAguOBneOBruOCiOOBhuOBquaWueOBr+OAgeS7peS4i+OBruOAjOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBm+OBmuOAgeWbnuetlOe1kOaenOOCkumAgeS/oeOBl+OBquOBhOOAjeODnOOCv+ODs+OCkuaKvOOBl+OBpuOAgeacrOiqv+afu+OCkue1guS6huOBl+OBpuOBj+OBoOOBleOBhOOAguOBneOBruWgtOWQiOOBq+OAgeacrOiqv+afu+OBuOOBruWbnuetlOOCkuWIhuaekOOBq+S9v+eUqOOBleOBm+OBpuOBhOOBn+OBoOOBj+OBk+OBqOOBr+iHtOOBl+OBvuOBm+OCk+OAguOBneOBruWgtOWQiOOBp+OBguOBo+OBpuOCguOAgeODneOCpOODs+ODiOOBr+S7mOS4juOBleOCjOOBvuOBmeOBruOBp+OAgeOBqeOBhuOBi+OBlOWuieW/g+OBj+OBoOOBleOBhOOAgiDjg7vjgb7jgZ/mnKzoqr/mn7vjgavjga/jgIHnoJTnqbbogIXjgYzni6zoh6rjgavlj47pm4bjg7vkvZzmiJDjgZfjgZ/jg4fjg7zjgr/jgYzlkKvjgb7jgozjgb7jgZnjgILjgZ3jgozjgonjgpLnhKHmlq3jgafou6LoqJjjgIHou6LlhpnjgIHjgrnjgq/jg6rjg7zjg7Pjgrfjg6fjg4Pjg4jjgarjganjgavjgojjgaPjgabjgIHjgZXjgb7jgZbjgb7jgarlqpLkvZPjgavphY3luIPjgZnjgovjgZPjgajjga/jgIHokZfkvZzmqKnjgavmirXop6bjgZnjgovmgZDjgozjgYzjgYLjgorjgb7jgZnjgILoqr/mn7vnlLvpnaLjga7nhKHmlq3jgafjga7ou6LoqJjjgIHou6LlhpnjgIHjgrnjgq/jg6rjg7zjg7Pjgrfjg6fjg4Pjg4jnrYnjgavjgojjgorlhazplovjg7vlhbHmnInjgZnjgovjgajjgYTjgaPjgZ/ooYzngrrjga/jgYrmjqfjgYjjgYTjgZ/jgaDjgY3jgb7jgZnjgojjgYbjgojjgo3jgZfjgY/jgYrpoZjjgYToh7TjgZfjgb7jgZnjgII8L3A+DQoNCjwvZGV0YWlscz4NCg0KKirlm57nrZTpgbjmip7ogqIqKg0KDQotIOacrOiqv+afu+OBruS4u+aXqOOBq+WQjOaEj+OBl+OAgeWbnuetlOe1kOaenOOCkumAgeS/oeOBmeOCi+OAgiAoMSkNCi0g5pys6Kq/5p+744Gu5Li75peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5Zue562U57WQ5p6c44KS6YCB5L+h44GX44Gq44GE44CCICgyKQ0KDQojIyBKLjMg5a6f6aiTM++8iDIwMjblubTvvIkNCg0KIyMjIEouMy4xIOiqv+afu+mWi+Wni+aZguOBruiqrOaYjuOBqOWQjOaEjw0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxzdHJvbmc+UTEuMSDoqr/mn7voqqzmmI7vvIjjgq/jg6rjg4Pjgq/jgZfjgablhajmlofjgpLooajnpLrvvIk8L3N0cm9uZz48L3N1bW1hcnk+DQoNCjxwPuOAjOe1jOa4iOipleS+oeOBqOaUv+aoqemBi+WWtuOCkuOCgeOBkOOCi+aEj+itmOiqv+afu+OAjSDjgZTljZTlipvjga7jgYrpoZjjgYQg5Lqs6YO95aSn5a2mIOWFrOWFseaUv+etlumAo+aQuueglOeptumDqCDmlZnmjogg5aSn5p2RIOiPr+WtkCDvvIjjgYrjgYrjgoDjgokg44Gv44Gq44GT77yJIOKXhiDjgZPjga7jgqLjg7PjgrHjg7zjg4joqr/mn7vjga/jgIHmlofpg6jnp5HlrabnnIHjgavjgojjgovnoJTnqbbliqnmiJDvvIjnoJTnqbboqrLpoYznlarlj7fvvJoyNkswNDc1MeOAjOaUv+etlualree4vuipleS+oeOBrueglOeptu+8jeaUv+ayu+ihjOWLleirluOBqOihjOWLleWFrOWFseaUv+etluirluOBruaetuapi+OAje+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+DQoNCjwvZGV0YWlscz4NCg0KKirlm57nrZTpgbjmip7ogqIqKg0KDQotIOacrOiqv+afu+OBrui2o+aXqOOBq+WQjOaEj+OBl+OBpuOAgeacrOiqv+afu+OBq+WNlOWKm+OBmeOCiyAoMSkNCi0g5pys6Kq/5p+744Gu6Laj5peo44Gr5ZCM5oSP44GX44Gq44GE44Gu44Gn44CB5pys6Kq/5p+744Gr5Y2U5Yqb44GX44Gq44GEICgyKQ0KDQojIyMgSi4zLjIg44OV44Kn44Kk44K544K344O844OIDQrlrp/pqJMz44GuUTIuMe+9nlEyLjTjga/lrp/pqJMy44Go5ZCM44GY6LOq5ZWP5paH44O75Zue562U5b2i5byP44Gn44GC44KL44CC5YaN54++5oCn44Gu44Gf44KB44CB6LOq5ZWPSUTjgajlhoXlrrnjgpLlho3mjrLjgZnjgovjgIINCg0KfCDos6rllY9JRCB8IOizquWVj+aWhyB8IOWbnuetlOW9ouW8j+ODu+mBuOaKnuiCoiB8DQp8LS0tfC0tLXwtLS18DQp8IFEyLjEgfCDjgYLjgarjgZ/jga7mgKfliKXjgpLpgbjjgpPjgafjgY/jgaDjgZXjgYTjgIIgfCDnlLfmgKcgKDEp77yP5aWz5oCnICgyKe+8j+OBneOBruS7liAoMynvvI/jgZPjgZ/jgYjjgZ/jgY/jgarjgYQgKDQpIHwNCnwgUTIuMiB8IOOBguOBquOBn+OBruW5tOm9ouWMuuWIhuOBqOePvuWcqOOBruW5tOm9ouOCkumBuOOCk+OBp+OBj+OBoOOBleOBhOOAgiB8IOOAjOW5tOS7o+OAjeOBqOOAjOW5tOm9ouOAjeOBrumAo+WLleODieODreODg+ODl+ODgOOCpuODs+OAguiqv+afu+elqOOCqOOCr+OCueODneODvOODiOS4iuOBp+OBr+mBuOaKnuiCouS4gOimp+OBjOecgeeVpeihqOekuuOBleOCjOOBpuOBhOOCi+OAgiB8DQp8IFEyLjMgfCDjgYLjgarjgZ/jgYznj77lnKjjgYrkvY/jgb7jgYTjga7lnLDln5/jgajpg73pgZPlupznnIzjgpLpgbjjgpPjgafjgY/jgaDjgZXjgYQgfCDjgIzlnLDln5/jgI3jgajjgIzpg73pgZPlupznnIzjgI3jga7pgKPli5Xjg4njg63jg4Pjg5fjg4Djgqbjg7PjgILoqr/mn7vnpajjgqjjgq/jgrnjg53jg7zjg4jkuIrjgafjga/pgbjmip7ogqLkuIDopqfjgYznnIHnlaXooajnpLrjgZXjgozjgabjgYTjgovjgIIgfA0KfCBRMi40IHwg44GC44Gq44Gf44Gu5LiW5biv44Gu56iO5byV44GN5YmN44Gu5LiW5biv5bm05Y+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+8iSB8DQoNCiMjIyBKLjMuMyDjgrPjg7Pjgrjjg6fjgqTjg7Pjg4joqrLpoYwNCuWun+mokzPjgafjga/jgIHmlL/lhZrlkI3jgag044Gk44Gu57WM5riI5bGe5oCn44GL44KJ44Gq44KL44OX44Ot44OV44Kj44O844Or44KS5o+Q56S644GX44Gf44CC5Zue562U6ICF44GvMuODuzPjg7s044O7NemBuOaKnuiCouOBruOBhOOBmuOCjOOBizHmnaHku7bjgavnhKHkvZzngrrjgavlibLjgorlvZPjgabjgonjgozjgIE16Kqy6aGM44Gr5Zue562U44GX44Gf44CCDQp8IOWxnuaApyB8IOawtOa6liB8DQp8LS0tfC0tLXwNCnwg5pS/5YWa5ZCNIHwg6Ieq55Sx5rCR5Li75YWa77yP56uL5oay5rCR5Li75YWa77yP5pel5pys57at5paw44Gu5Lya77yP5YWs5piO5YWa77yP5Zu95rCR5rCR5Li75YWa77yP44KM44GE44KP5paw6YG457WE77yP5Y+C5pS/5YWa77yP5pel5pys5YWx55Sj5YWa77yP5Lit6YGT5pS56Z2p6YCj5ZCIIHwNCnwgR0RQ5oiQ6ZW3546HIHwgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfA0KfCDml6XntYzlubPlnYfmoKrkvqEgfCDliY3mnIjlkIzmnJ/mr5Qg5aSJ44KP44KJ44Ga77yP44OX44Op44K5MTAwMOWGhu+8j+ODnuOCpOODiuOCuTEwMDDlhoYgfA0KfCBDUEkgfCDliY3mnJ/mr5QgwrEw44Od44Kk44Oz44OI77yP44OX44Op44K5MeODneOCpOODs+ODiO+8j+ODnuOCpOODiuOCuTHjg53jgqTjg7Pjg4ggfA0KfCDlpLHmpa3njocgfCDliY3mnJ/mr5QgwrEw77yF77yP44OX44Op44K5Me+8he+8j+ODnuOCpOODiuOCuTHvvIUgfA0KDQoqKuadoeS7tuWIpeOBruiqrOaYjuaWh+ODu+mBuOaKnuiqsumhjOODu+aTjeS9nOeiuuiqjSoqDQoNCiMjIyMgMumBuOaKnuiCouadoeS7tu+8iCRrPTIk77yJDQoqKuWwjuWFpeizquWVjyBRNi4xKiogIA0K5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yS44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBrzLjgaTjga7pgbjmip7ogqLjga7kuK3jgYvjgonjganjga7nirbms4HjgpLpgbjmip7jgZXjgozjgovjgYvjgIHvvJHjgaTpgbjjgpPjgafjgYrnrZTjgYjjgY/jgaDjgZXjgYTjgIIg5L2c5qWt44Gv77yV5Zue57mw44KK6L+U44GV44KM44G+44GZ44CCDQoNCuWbnuetlO+8muOAjOS4iuiomOOBruaWh+eroOOCkuiqreOCk+OBoOOAgiAoMSnjgI0NCg0KKirpgbjmip7oqrLpoYwgUTYuMuKAk1E2LjbvvIg15Zue77yJKiogIA0K5Lul5LiL44Gr44CB5pel5pys44Gu5pS/5YWa44KS44KB44GQ44KLMuOBpOOBrumBuOaKnuiCouOCkuaPkOekuuOBleOBm+OBpuOBhOOBn+OBoOOBjeOBvuOBmeOAgiDooajjga7kuIDnlarkuIrjgavkuIrjgYzjgaPjgabjgYTjgovmlL/lhZrjgYzmlL/mqKnkuI7lhZrjgafjgYLjgaPjgZ/jgorjgIHpgKPnq4vmlL/mqKnjgajjgZfjgabkuI7lhZrjgavliqDjgo/jgaPjgabjgYTjgovjgajjgZfjgb7jgZnjgILjgZ3jgZfjgabooYborbDpmaLnt4/pgbjmjJnjgYzjgYLjgovjgajjgYrogIPjgYjkuIvjgZXjgYTjgIIg5pS/5qip5LiO5YWa44Gr44GC44KL5pS/5YWa44Go57WM5riI54q25rOB44Gu57WE44G/5ZCI44KP44Gb44Gu44GG44Gh44CB44GC44Gq44Gf44Gv44Gp44Gu54q25rOB44Gn44GC44KM44Gw44CB5pS/5qip5LiO5YWa44Gr5oqV56Wo44GX44G+44GZ44GL44CCIOmBuOaKnuiCouOBrumghuOBr+OAgeW3puOBi+OCieeKtuazgTHjgIHnirbms4Ey44Go44GX44G+44GZ44CCDQoNCuWbnuetlOmBuOaKnuiCou+8mueKtuazgTEgKDEp77yP54q25rOBMiAoMikNCg0KKirmk43kvZznorroqo0gUTYuNyoqICANCuOBguOBquOBn+OBq+OBr+OAgeikh+aVsOOBrumBuOaKnuiCouOBruS4reOBi+OCiTHjgaTjga7nirbms4HjgpLpgbjjgpPjgafjgoLjgonjgYbkvZzmpa3jgpLooYzjgaPjgabjgYTjgZ/jgaDjgY3jgb7jgZfjgZ/jgIIg44GC44Gq44Gf44Gr5o+Q56S644GV44KM44Gf6YG45oqe6IKi44Gu5pWw44Gv44CB44GE44GP44Gk44Gn44GX44Gf44GL44CCDQoNCuWbnuetlOmBuOaKnuiCou+8mjEgKDEp77yPMiAoMinvvI8zICgzKe+8jzQgKDQp77yPNSAoNSnvvI/jgYrjgbzjgYjjgabjgYTjgarjgYQgKDYpDQoNCiMjIyMgM+mBuOaKnuiCouadoeS7tu+8iCRrPTMk77yJDQoqKuWwjuWFpeizquWVjyBRMy4xKiogIA0K5LuK44GL44KJ44CB5pel5pys44Gu5pS/5YWa44KB44GQ44KL77yT44Gk44Gu6YG45oqe6IKi44KS6aCG44Gr5o+Q56S644GX44Gm44GE44GN44G+44GZ44CCIOOBneOBl+OBpuOAgeihhuitsOmZoue3j+mBuOaMmeOBjOOBguOCi+OBqOOBiuiAg+OBiOS4i+OBleOBhOOAguOBneOBruaZguOAgeOBguOBquOBn+OBr++8k+OBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBrueKtuazgeOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIINCg0K5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQ0KDQoqKumBuOaKnuiqsumhjCBRMy4y4oCTUTMuNu+8iDXlm57vvIkqKiAgDQrku6XkuIvjgavjgIHml6XmnKzjga7mlL/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+44GZ44CCDQoNCuWbnuetlOmBuOaKnuiCou+8mueKtuazgTEgKDEp77yP54q25rOBMiAoMinvvI/nirbms4EzICgzKQ0KDQoqKuaTjeS9nOeiuuiqjSBRMy43KiogIA0K44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIINCg0K5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikNCg0KIyMjIyA06YG45oqe6IKi5p2h5Lu277yIJGs9NCTvvIkNCioq5bCO5YWl6LOq5ZWPIFE0LjEqKiAgDQrku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJTjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44GvNOOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBrueKtuazgeOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIINCg0K5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQ0KDQoqKumBuOaKnuiqsumhjCBRNC4y4oCTUTQuNu+8iDXlm57vvIkqKiAgDQrku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgos044Gk44Gu6YG45oqe6IKi44KS5o+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/mqKnkuI7lhZrjgavmipXnpajjgZfjgb7jgZnjgYvjgIIg6YG45oqe6IKi44Gu6aCG44Gv44CB5bem44GL44KJ54q25rOBMeOAgeeKtuazgTLjgIHnirbms4Ez44CB54q25rOBNOOBqOOBl+OBvuOBmeOAgg0KDQrlm57nrZTpgbjmip7ogqLvvJrnirbms4ExICgxKe+8j+eKtuazgTIgKDIp77yP54q25rOBMyAoMynvvI/nirbms4E0ICg0KQ0KDQoqKuaTjeS9nOeiuuiqjSBRNC43KiogIA0K44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIINCg0K5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikNCg0KIyMjIyA16YG45oqe6IKi5p2h5Lu277yIJGs9NSTvvIkNCioq5bCO5YWl6LOq5ZWPIFE1LjEqKiAgDQrku4rjgYvjgonjgIHml6XmnKzjga7mlL/lhZrjgoHjgZDjgovvvJXjgaTjga7pgbjmip7ogqLjgpLpoIbjgavmj5DnpLrjgZfjgabjgYTjgY3jgb7jgZnjgIIg44Gd44GX44Gm44CB6KGG6K2w6Zmi57eP6YG45oyZ44GM44GC44KL44Go44GK6ICD44GI5LiL44GV44GE44CC44Gd44Gu5pmC44CB44GC44Gq44Gf44GvNeOBpOOBrumBuOaKnuiCouOBruS4reOBi+OCieOBqeOBrueKtuazgeOCkumBuOaKnuOBleOCjOOCi+OBi+OAge+8keOBpOmBuOOCk+OBp+OBiuetlOOBiOOBj+OBoOOBleOBhOOAgiDkvZzmpa3jga/vvJXlm57nubDjgorov5TjgZXjgozjgb7jgZnjgIINCg0K5Zue562U77ya44CM5LiK6KiY44Gu5paH56ug44KS6Kqt44KT44Gg44CCICgxKeOAjQ0KDQoqKumBuOaKnuiqsumhjCBRNS4y4oCTUTUuNu+8iDXlm57vvIkqKiAgDQrku6XkuIvjgavjgIHml6XmnKzjga7mlL/lhZrjgpLjgoHjgZDjgos144Gk44Gu6YG45oqe6IKi44KS5o+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/mqKnkuI7lhZrjgavmipXnpajjgZfjgb7jgZnjgYvjgIIg6YG45oqe6IKi44Gu6aCG44Gv44CB5bem44GL44KJ54q25rOBMeOAgeeKtuazgTLjgIHnirbms4Ez44CB54q25rOBNOOAgeeKtuazgTXjgajjgZfjgb7jgZnjgIINCg0K5Zue562U6YG45oqe6IKi77ya54q25rOBMSAoMSnvvI/nirbms4EyICgyKe+8j+eKtuazgTMgKDMp77yP54q25rOBNCAoNCnvvI/nirbms4E1ICg1KQ0KDQoqKuaTjeS9nOeiuuiqjSBRNS43KiogIA0K44GC44Gq44Gf44Gr44Gv44CB6KSH5pWw44Gu6YG45oqe6IKi44Gu5Lit44GL44KJMeOBpOOBrueKtuazgeOCkumBuOOCk+OBp+OCguOCieOBhuS9nOalreOCkuihjOOBo+OBpuOBhOOBn+OBoOOBjeOBvuOBl+OBn+OAgiDjgYLjgarjgZ/jgavmj5DnpLrjgZXjgozjgZ/pgbjmip7ogqLjga7mlbDjga/jgIHjgYTjgY/jgaTjgafjgZfjgZ/jgYvjgIINCg0K5Zue562U6YG45oqe6IKi77yaMSAoMSnvvI8yICgyKe+8jzMgKDMp77yPNCAoNCnvvI81ICg1Ke+8j+OBiuOBvOOBiOOBpuOBhOOBquOBhCAoNikNCg0KIyMjIEouMy40IOaUv+ayu+izquWVjw0KKipRNy4xKiogIA0K5pS/5rK755qE56uL5aC044KS6KGo44GZ44Gu44Gr44CB44KI44GP44CM5Y+z5rS+44CN44CM5bem5rS+44CN44Go44GE44GG6KiA6JGJ44GM5L2/44KP44KM44G+44GZ44CCMeOBjOWPs+a0vueahOOAgTbjgYzkuK3plpPjgIExMeOBjOW3pua0vueahOOBoOOBqOOBmeOCi+OBqOOAgeOBguOBquOBn+OChOS4u+imgeaUv+WFmuOBr+OBqeOBruOBguOBn+OCiuOBq+S9jee9ruS7mOOBkeOCieOCjOOCi+OBqOOBiuiAg+OBiOOBp+OBl+OCh+OBhuOBi+OAgg0KDQrlm57nrZTlsLrluqbvvJox77yI5Y+z5rS+55qE77yJ77yPMu+8jzPvvI8077yPNe+8jzbvvIjkuK3plpPvvInvvI8377yPOO+8jznvvI8xMO+8jzEx77yI5bem5rS+55qE77yJ77yP44KP44GL44KJ44Gq44GE77yP44GT44Gf44GI44Gf44GP44Gq44GE44CCDQoNCuipleS+oeWvvuixoe+8muOBguOBquOBn+iHqui6q++8iFEyNS4xXzHvvInjgIHoh6rnlLHmsJHkuLvlhZrvvIhRMjUuMV8y77yJ44CB56uL5oay5rCR5Li75YWa77yIUTI1LjFfM++8ieOAgeaXpeacrOe2reaWsOOBruS8mu+8iFEyNS4xXzTvvInjgIHlhazmmI7lhZrvvIhRMjUuMV8xMO+8ieOAgeWbveawkeawkeS4u+WFmu+8iFEyNS4xXzXvvInjgIHjgozjgYTjgo/mlrDpgbjntYTvvIhRMjUuMV8277yJ44CB5Y+C5pS/5YWa77yIUTI1LjFfN++8ieOAgeWFseeUo+WFmu+8iFEyNS4xXzjvvInjgIHkuK3pgZPmlLnpnanpgKPlkIjvvIhRMjUuMV8577yJ44CBKirjgIzvvIHjgZPjga7poIXnm67jga/lv4XjgZrjgI4z44CP44KS6YG444KT44Gn44GP44Gg44GV44GE77yB44CN77yIUTI1LjFfMTHvvIkqKuOAgg0KDQoqKlE3LjIqKiAgDQrpgbjmjJnjgafjganjgZPjgavmipXnpajjgZnjgovjgYvjga/liKXjgavjgZfjgabjgIHlm73jga7mlL/msrvjgafjgIHjgYLjgarjgZ/jga/jganjga7mlL/lhZrjgYLjgovjgYTjga/mlL/msrvlm6PkvZPjgpLmlK/mjIHjgZfjgabjgYTjgb7jgZnjgYvjgIINCg0KLSDoh6rnlLHmsJHkuLvlhZogKDEpDQotIOS4remBk+aUuemdqemAo+WQiCAoMikNCi0g56uL5oay5rCR5Li75YWaICgxOCkNCi0g5YWs5piO5YWaICgxOSkNCi0g5pel5pys57at5paw44Gu5LyaICgzKQ0KLSDlm73msJHmsJHkuLvlhZogKDQpDQotIOOCjOOBhOOCj+aWsOmBuOe1hCAoNSkNCi0g5YWx55Sj5YWaICg2KQ0KLSDlj4LmlL/lhZogKDcpDQotIOaXpeacrOS/neWuiOWFmiAoOCkNCi0g56S+5rCR5YWaICg5KQ0KLSDjg4Hjg7zjg6Djgb/jgonjgYQgKDEwKQ0KLSDjgZ3jga7ku5bjga7mlL/lhZrjg7vmlL/msrvlm6PkvZPvvIjlhbfkvZPnmoTjgavvvIkgKDEyKSBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KLSDjgZ3jga7jgojjgYbjgarmlL/lhZrjga/jgarjgYQgKDEzKQ0KLSDjgo/jgYvjgonjgarjgYQgKDE0KQ0KLSDjgZPjgZ/jgYjjgZ/jgY/jgarjgYQgKDE1KQ0KDQoqKlE3LjMqKiAgDQrjgYLjgarjgZ/jgYzmma7mrrXjgIHmlL/msrvjgavplqLjgZnjgovmg4XloLHjgpLopovjgZ/jgorjgIHogZ7jgYTjgZ/jgorjgZnjgovjgZ/jgoHjgavkvb/jgYblqpLkvZPjga/jgIHjganjgozjgafjgZfjgofjgYbjgYvjgILjgYLjgovjgaDjgZHpgbjjgpPjgafjgY/jgaDjgZXjgYTjgIINCg0KLSDmlrDogZ7vvIjmnJ3liIrvvIkgKDEpDQotIOOCueODneODvOODhOaWsOiBniAoMikNCi0g6YCx5YiK6KqMICgzKQ0KLSDmlL/opovmlL7pgIEgKDQpDQotIOODhuODrOODk+OBruODi+ODpeODvOOCuSAoNSkNCi0g44Ov44Kk44OJ44K344On44O844KE6KiO6KuW55Wq57WEICg2KQ0KLSDjg57jg4vjg5Xjgqfjgrnjg4jjg7vpgbjmjJnlhazloLEgKDcpDQotIOOCpOODs+OCv+ODvOODjeODg+ODiOS4iuOBruODi+ODpeODvOOCueiomOS6iyhTTlPlkKvjgoApICg4KQ0KLSDmlL/lhZrjgoTlgJnoo5zogIXjga7jg5vjg7zjg6Djg5rjg7zjgrjjgarjgakoU05T5ZCr44KAKSAoOSkNCi0g44Gd44Gu5LuW77yI5YW35L2T55qE44Gr77yJICgxMCkgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18NCi0g4oqX6KaL6IGe44GN44GX44Gm44GE44Gq44GEICgxMSkNCi0g4oqX44KP44GL44KJ44Gq44GEICgxMikNCi0g4oqX44GT44Gf44GI44Gf44GP44Gq44GEICgxMykNCg0KIyMjIEouMy41IOiqv+afu+i2o+aXqOOBruWGjeiqrOaYjuOBqOacgOe1gumAgeS/oeWQjOaEjw0KPGRldGFpbHM+DQo8c3VtbWFyeT48c3Ryb25nPlE4LjEg44OH44OW44Oq44O844OV44Kj44Oz44Kw44O75pyA57WC5oSP5oCd56K66KqN77yI44Kv44Oq44OD44Kv44GX44Gm5YWo5paH44KS6KGo56S677yJPC9zdHJvbmc+PC9zdW1tYXJ5Pg0KDQo8cD7jgZPjgaHjgonjgYzoqr/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+44GZ44CCPC9wPg0KDQo8L2RldGFpbHM+DQoNCioq5Zue562U6YG45oqe6IKiKioNCg0KLSDmnKzoqr/mn7vjga7kuLvml6jjgavlkIzmhI/jgZfjgIHlm57nrZTntZDmnpzjgpLpgIHkv6HjgZnjgovjgIIgKDEpDQotIOacrOiqv+afu+OBruS4u+aXqOOBq+WQjOaEj+OBl+OBquOBhOOBruOBp+OAgeWbnuetlOe1kOaenOOCkumAgeS/oeOBl+OBquOBhOOAgiAoMikNCg0KIyMgSi40IOiqv+afu+elqOOBqOWGjeePvuOCs+ODvOODieOBruWvvuW/nA0KQy4044Gu5qiZ5pys5rib5bCR44O744K544Kv44Oq44O844OL44Oz44Kw6KGo44Gn44Gv44CB5LiK6KiY44Gu6LOq5ZWP5paH44Gu44GG44Gh5YiG5p6Q5qiZ5pys44Gu5Yik5a6a44Gr55u05o6l55So44GE44KL6aCF55uu44KS55+t44GP6KaB57SE44GX44Gm5L216KiY44GX44Gm44GE44KL44CC5a6f6aiTMeOBp+OBr+WIneWbnuWQjOaEj+OAgTXjgaTjga7pgbjmip7oqrLpoYzjgIHmnIDntYLpgIHkv6HlkIzmhI/jgpLkuLvjgarliKTlrprpoIXnm67jgajjgZnjgovjgILlrp/pqJMy44O7M+OBp+OBr+OBk+OCjOOCieOBq+WKoOOBiOOAgeWQhOmBuOaKnuiCouaVsOadoeS7tuOBruaTjeS9nOeiuuiqje+8iFEzLjfvvI9RNC4377yPUTUuN++8j1E2LjfvvInjgajjgIHjgqTjg4fjgqrjg63jgq7jg7zooYzliJfjga7mjIfnpLrpoIXnm65RMjUuMV8xMeOCkueUqOOBhOOCi+OAguOBl+OBn+OBjOOBo+OBpuOAgUMuNOOBruOAjOizquWVj+aWh++8iOiqv+afu+elqOODu+imgee0hO+8ieOAjeWIl+OBqOOAgeacrOevgOOBruWujOWFqOOBquizquWVj+aWh+OCkuWvvuW/nOOBleOBm+OBpueiuuiqjeOBp+OBjeOCi+OAgg0KDQo=