Статистическая значимость

Односторонний тест Кокрана-Армитажа на тренд:

library(DescTools)

data_table <- matrix(
  c(
    63, 57, 57, 51, # Строка неправильных ответов
    13, 19, 19, 25 # Строка правильных ответов
  ),
  nrow = 2,
  byrow = TRUE
)

colnames(data_table) <- c("Difficult_1", "Difficult_2", "Difficult_3", "Difficult_4")
rownames(data_table) <- c("False", "True")

CochranArmitageTest(data_table, alternative = "one.sided")

    Cochran-Armitage test for trend

data:  data_table
Z = -2.1325, dim = 4, p-value = 0.01648
alternative hypothesis: one.sided

Размер эффекта

График вероятностей, предсказанных логистической регрессией (наглядный способ оценить размер эффекта):

library(dplyr)
library(ggplot2)
library(marginaleffects)

# Данные
data <- data.frame(
  detail_level = c(rep(1, 76), rep(2, 76), rep(3, 76), rep(4, 76)),
  correct = c(
    rep(1, 13), rep(0, 63), # Уровень 1
    rep(1, 19), rep(0, 57), # Уровень 2
    rep(1, 19), rep(0, 57), # Уровень 3
    rep(1, 25), rep(0, 51) # Уровень 4
  )
)

# Строим логистическую регрессия
model <- glm(correct ~ detail_level, data = data, family = binomial)

# Предсказываем вероятности на каждом уровне детализации
all_levels <- predictions(
  model,
  newdata = datagrid(detail_level = 1:4)
)

# Строим график
ggplot(all_levels, aes(x = factor(detail_level), y = estimate)) +
  # Пунктирная линия случайного угадывания
  geom_hline(yintercept = 0.25, linetype = "dashed", color = "gray50") +
  # Доверительные интервалы
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width = 0.1, color = "gray30", linewidth = 0.8) +
  # Точки предсказанных вероятностей
  geom_point(size = 4, color = "gray30") +
  # Добавим тонкую линию, соединяющую точки, чтобы подчеркнуть тренд
  geom_line(aes(group = 1), linetype = "dotted", color = "gray30") +
  # Настройка осей
  scale_y_continuous(
    labels = scales::percent_format(accuracy = 1),
    breaks = seq(0.1, 0.5, by = 0.05),
    limits = c(0.1, 0.45)
  ) +
  theme_minimal() +
  labs(
    x = "Уровень детализации варианта ответа",
    y = "Вероятность ответить правильно",
  ) +
  theme(text = element_text(size = 16, family = "serif"))

print(all_levels)

 detail_level Estimate Pr(>|z|)    S 2.5 % 97.5 %
            1    0.182   <0.001 31.1 0.122  0.263
            2    0.223   <0.001 49.8 0.175  0.280
            3    0.271   <0.001 39.5 0.220  0.328
            4    0.324   <0.001 11.1 0.241  0.420

Type: invlink(link)

Практически интересный размера эффекта (стратегия выбора наиболее детализированного варианта ответа позволяет угадывать с вероятностью на 0.0741 выше):

library(marginaleffects)

# Данные
data <- data.frame(
  detail_level = c(rep(1, 76), rep(2, 76), rep(3, 76), rep(4, 76)),
  correct = c(
    rep(1, 13), rep(0, 63), # Уровень 1
    rep(1, 19), rep(0, 57), # Уровень 2
    rep(1, 19), rep(0, 57), # Уровень 3
    rep(1, 25), rep(0, 51) # Уровень 4
  )
)

# Строим логистическую регрессию
model <- glm(correct ~ detail_level, data = data, family = binomial)

# Считаем разницу вероятностей
results <- predictions(
  model,
  newdata = datagrid(detail_level = 4),
  hypothesis = "b1 - 0.25 = 0",
  type = "response"
)

print(results)

 Hypothesis Estimate Std. Error    z Pr(>|z|)   S  2.5 % 97.5 %
  b1-0.25=0   0.0741      0.046 1.61    0.107 3.2 -0.016  0.164

Type: response

Анализ мощности

Апостериорные анализы мощности

Апостериорный анализ мощности для теста Кокрана-Армитажа:

library(multiCA)

power.CA.test(
  N = 304, # Размер выборки (количество вариантов ответа)
  n.prop = c(0.25, 0.25, 0.25, 0.25), # Пропорция размеров групп на каждом уровне
  pvec = c(0.1711, 0.25, 0.25, 0.3289), # Фактические пропорции правильных ответов на каждом уровне
  sig.level = 0.05, # Уровень значимости альфа
  alternative = "greater" # Направление проверки
)

     Cochran-Armitage trend test 

              n = 304
         n.prop = 0.25, 0.25, 0.25, 0.25
              p = 0.1711, 0.2500, 0.2500, 0.3289
    alternative = greater
      sig.level = 0.05
          power = 0.6892607

Априорные анализы мощности

Априорный анализ мощности для теста Кокрана-Армитажа:

library(multiCA)

power.CA.test(
  n.prop = c(0.25, 0.25, 0.25, 0.25), # Пропорция размеров групп на каждом уровне
  pvec = c(0.1711, 0.25, 0.25, 0.3289), # Фактические пропорции правильных ответов на каждом уровне
  sig.level = 0.05, # Уровень значимости альфа
  alternative = "greater", # Направление проверки
  power = 0.8 # Необходимая мощность
)

     Cochran-Armitage trend test 

              n = 409.6055
         n.prop = 0.25, 0.25, 0.25, 0.25
              p = 0.1711, 0.2500, 0.2500, 0.3289
    alternative = greater
      sig.level = 0.05
          power = 0.8

Априорный анализ мощности для практически интересного размера эффекта методом Монте-Карло. Расчёт статистической мощности для выборки размером 172 вопроса (688 вариантов ответа):

library(marginaleffects)

# Функция расчёта статистической мощность по размеру выборки n_per_level
simulate_power_exact <- function(n_per_level, b0, b1, n_sim, alpha) {
  success_count <- 0

  for (i in 1:n_sim) {
    # 1. Генерируем данные
    sim_detail_level <- rep(1:4, each = n_per_level)
    sim_log_odds <- b0 + b1 * sim_detail_level
    sim_probs <- 1 / (1 + exp(-sim_log_odds))
    sim_correct <- rbinom(length(sim_detail_level), size = 1, prob = sim_probs)

    sim_data <- data.frame(detail_level = sim_detail_level, correct = sim_correct)

    # 2. Обучаем модель
    fit <- glm(correct ~ detail_level, data = sim_data, family = binomial)

    # 3. Используем marginaleffects для проверки значимости эффекта
    results <- predictions(
      fit,
      newdata = datagrid(detail_level = 4),
      hypothesis = "b1 - 0.25 = 0",
      type = "response"
    )

    # 4. Извлекаем одностороннее p-значение
    # Делим на 2, если эффект направлен в ожидаемую сторону (Estimate > 0)
    if (results$estimate > 0) {
      p_val_one_sided <- results$p.value / 2
    } else {
      p_val_one_sided <- 1 - (results$p.value / 2)
    }

    if (p_val_one_sided < alpha) {
      success_count <- success_count + 1
    }
  }

  return(success_count / n_sim)
}

# Расчитываем статистическую мощность
set.seed(42)
estimated_power <- simulate_power_exact(
  n_per_level = 172, # Размер выборки на каждый уровень (количество вопросов)
  b0 = coef(model)[1], # Константа (intercept) в регрессии
  b1 = coef(model)[2], # Коэффициент для переменной detail_level
  n_sim = 100, # Количество симуляций
  alpha = 0.05 # Уровень значимости α
)

print(estimated_power)
[1] 0.84
LS0tDQp0aXRsZTogItCi0LXRgdGC0Ysg0L/QviDQuNGB0YLQvtGA0LjQuCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyLCBtYXJrZG93bl9zZXR0aW5ncywgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gRkFMU0UpDQpgYGANCg0KYGBge3IsIGluc3RhbGxpbmctbGlicmFyaWVzLCBpbmNsdWRlID0gRkFMU0V9DQojaW5zdGFsbC5wYWNrYWdlcyhjKCJEZXNjVG9vbHMiLCAibXVsdGlDQSIsICJsbXRlc3QiLCAiZHBseXIiLCAibWFyZ2luYWxlZmZlY3RzIiwgInJzdGFuYXJtIiwgImNvbGxhcHNlIiwgIlJjcHAiLCAiem9vIikpDQpgYGANCg0KIyMg0KHRgtCw0YLQuNGB0YLQuNGH0LXRgdC60LDRjyDQt9C90LDRh9C40LzQvtGB0YLRjA0KDQrQntC00L3QvtGB0YLQvtGA0L7QvdC90LjQuSDRgtC10YHRgiDQmtC+0LrRgNCw0L3QsC3QkNGA0LzQuNGC0LDQttCwINC90LAg0YLRgNC10L3QtDoNCg0KYGBge3IsIGNvY2hyYW5lX2FybWl0YWdlLXRlc3R9DQpsaWJyYXJ5KERlc2NUb29scykNCg0KZGF0YV90YWJsZSA8LSBtYXRyaXgoDQogIGMoDQogICAgNjMsIDU3LCA1NywgNTEsICMg0KHRgtGA0L7QutCwINC90LXQv9GA0LDQstC40LvRjNC90YvRhSDQvtGC0LLQtdGC0L7Qsg0KICAgIDEzLCAxOSwgMTksIDI1ICMg0KHRgtGA0L7QutCwINC/0YDQsNCy0LjQu9GM0L3Ri9GFINC+0YLQstC10YLQvtCyDQogICksDQogIG5yb3cgPSAyLA0KICBieXJvdyA9IFRSVUUNCikNCg0KY29sbmFtZXMoZGF0YV90YWJsZSkgPC0gYygiRGlmZmljdWx0XzEiLCAiRGlmZmljdWx0XzIiLCAiRGlmZmljdWx0XzMiLCAiRGlmZmljdWx0XzQiKQ0Kcm93bmFtZXMoZGF0YV90YWJsZSkgPC0gYygiRmFsc2UiLCAiVHJ1ZSIpDQoNCkNvY2hyYW5Bcm1pdGFnZVRlc3QoZGF0YV90YWJsZSwgYWx0ZXJuYXRpdmUgPSAib25lLnNpZGVkIikNCmBgYA0KDQojIyDQoNCw0LfQvNC10YAg0Y3RhNGE0LXQutGC0LANCg0K0JPRgNCw0YTQuNC6INCy0LXRgNC+0Y/RgtC90L7RgdGC0LXQuSwg0L/RgNC10LTRgdC60LDQt9Cw0L3QvdGL0YUg0LvQvtCz0LjRgdGC0LjRh9C10YHQutC+0Lkg0YDQtdCz0YDQtdGB0YHQuNC10LkgKNC90LDQs9C70Y/QtNC90YvQuSDRgdC/0L7RgdC+0LEg0L7RhtC10L3QuNGC0Ywg0YDQsNC30LzQtdGAINGN0YTRhNC10LrRgtCwKToNCg0KYGBge3IsIGVmZmVjdF9zaXplLWdyYXBoLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gNSwgbWVzc2FnZSA9IEZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobWFyZ2luYWxlZmZlY3RzKQ0KDQojINCU0LDQvdC90YvQtQ0KZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBkZXRhaWxfbGV2ZWwgPSBjKHJlcCgxLCA3NiksIHJlcCgyLCA3NiksIHJlcCgzLCA3NiksIHJlcCg0LCA3NikpLA0KICBjb3JyZWN0ID0gYygNCiAgICByZXAoMSwgMTMpLCByZXAoMCwgNjMpLCAjINCj0YDQvtCy0LXQvdGMIDENCiAgICByZXAoMSwgMTkpLCByZXAoMCwgNTcpLCAjINCj0YDQvtCy0LXQvdGMIDINCiAgICByZXAoMSwgMTkpLCByZXAoMCwgNTcpLCAjINCj0YDQvtCy0LXQvdGMIDMNCiAgICByZXAoMSwgMjUpLCByZXAoMCwgNTEpICMg0KPRgNC+0LLQtdC90YwgNA0KICApDQopDQoNCiMg0KHRgtGA0L7QuNC8INC70L7Qs9C40YHRgtC40YfQtdGB0LrRg9GOINGA0LXQs9GA0LXRgdGB0LjRjw0KbW9kZWwgPC0gZ2xtKGNvcnJlY3QgfiBkZXRhaWxfbGV2ZWwsIGRhdGEgPSBkYXRhLCBmYW1pbHkgPSBiaW5vbWlhbCkNCg0KIyDQn9GA0LXQtNGB0LrQsNC30YvQstCw0LXQvCDQstC10YDQvtGP0YLQvdC+0YHRgtC4INC90LAg0LrQsNC20LTQvtC8INGD0YDQvtCy0L3QtSDQtNC10YLQsNC70LjQt9Cw0YbQuNC4DQphbGxfbGV2ZWxzIDwtIHByZWRpY3Rpb25zKA0KICBtb2RlbCwNCiAgbmV3ZGF0YSA9IGRhdGFncmlkKGRldGFpbF9sZXZlbCA9IDE6NCkNCikNCg0KIyDQodGC0YDQvtC40Lwg0LPRgNCw0YTQuNC6DQpnZ3Bsb3QoYWxsX2xldmVscywgYWVzKHggPSBmYWN0b3IoZGV0YWlsX2xldmVsKSwgeSA9IGVzdGltYXRlKSkgKw0KICAjINCf0YPQvdC60YLQuNGA0L3QsNGPINC70LjQvdC40Y8g0YHQu9GD0YfQsNC50L3QvtCz0L4g0YPQs9Cw0LTRi9Cy0LDQvdC40Y8NCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4yNSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JheTUwIikgKw0KICAjINCU0L7QstC10YDQuNGC0LXQu9GM0L3Ri9C1INC40L3RgtC10YDQstCw0LvRiw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gpLCB3aWR0aCA9IDAuMSwgY29sb3IgPSAiZ3JheTMwIiwgbGluZXdpZHRoID0gMC44KSArDQogICMg0KLQvtGH0LrQuCDQv9GA0LXQtNGB0LrQsNC30LDQvdC90YvRhSDQstC10YDQvtGP0YLQvdC+0YHRgtC10LkNCiAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSAiZ3JheTMwIikgKw0KICAjINCU0L7QsdCw0LLQuNC8INGC0L7QvdC60YPRjiDQu9C40L3QuNGOLCDRgdC+0LXQtNC40L3Rj9GO0YnRg9GOINGC0L7Rh9C60LgsINGH0YLQvtCx0Ysg0L/QvtC00YfQtdGA0LrQvdGD0YLRjCDRgtGA0LXQvdC0DQogIGdlb21fbGluZShhZXMoZ3JvdXAgPSAxKSwgbGluZXR5cGUgPSAiZG90dGVkIiwgY29sb3IgPSAiZ3JheTMwIikgKw0KICAjINCd0LDRgdGC0YDQvtC50LrQsCDQvtGB0LXQuQ0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLA0KICAgIGJyZWFrcyA9IHNlcSgwLjEsIDAuNSwgYnkgPSAwLjA1KSwNCiAgICBsaW1pdHMgPSBjKDAuMSwgMC40NSkNCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoDQogICAgeCA9ICLQo9GA0L7QstC10L3RjCDQtNC10YLQsNC70LjQt9Cw0YbQuNC4INCy0LDRgNC40LDQvdGC0LAg0L7RgtCy0LXRgtCwIiwNCiAgICB5ID0gItCS0LXRgNC+0Y/RgtC90L7RgdGC0Ywg0L7RgtCy0LXRgtC40YLRjCDQv9GA0LDQstC40LvRjNC90L4iLA0KICApICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhbWlseSA9ICJzZXJpZiIpKQ0KDQpwcmludChhbGxfbGV2ZWxzKQ0KYGBgDQoNCtCf0YDQsNC60YLQuNGH0LXRgdC60Lgg0LjQvdGC0LXRgNC10YHQvdGL0Lkg0YDQsNC30LzQtdGA0LAg0Y3RhNGE0LXQutGC0LAgKNGB0YLRgNCw0YLQtdCz0LjRjyDQstGL0LHQvtGA0LAg0L3QsNC40LHQvtC70LXQtSDQtNC10YLQsNC70LjQt9C40YDQvtCy0LDQvdC90L7Qs9C+INCy0LDRgNC40LDQvdGC0LAg0L7RgtCy0LXRgtCwINC/0L7Qt9Cy0L7Qu9GP0LXRgiDRg9Cz0LDQtNGL0LLQsNGC0Ywg0YEg0LLQtdGA0L7Rj9GC0L3QvtGB0YLRjNGOINC90LAgMC4wNzQxINCy0YvRiNC1KToNCg0KYGBge3IsIHByYWN0aWNhbF9lZmZlY3Qtc2l6ZX0NCmxpYnJhcnkobWFyZ2luYWxlZmZlY3RzKQ0KDQojINCU0LDQvdC90YvQtQ0KZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBkZXRhaWxfbGV2ZWwgPSBjKHJlcCgxLCA3NiksIHJlcCgyLCA3NiksIHJlcCgzLCA3NiksIHJlcCg0LCA3NikpLA0KICBjb3JyZWN0ID0gYygNCiAgICByZXAoMSwgMTMpLCByZXAoMCwgNjMpLCAjINCj0YDQvtCy0LXQvdGMIDENCiAgICByZXAoMSwgMTkpLCByZXAoMCwgNTcpLCAjINCj0YDQvtCy0LXQvdGMIDINCiAgICByZXAoMSwgMTkpLCByZXAoMCwgNTcpLCAjINCj0YDQvtCy0LXQvdGMIDMNCiAgICByZXAoMSwgMjUpLCByZXAoMCwgNTEpICMg0KPRgNC+0LLQtdC90YwgNA0KICApDQopDQoNCiMg0KHRgtGA0L7QuNC8INC70L7Qs9C40YHRgtC40YfQtdGB0LrRg9GOINGA0LXQs9GA0LXRgdGB0LjRjg0KbW9kZWwgPC0gZ2xtKGNvcnJlY3QgfiBkZXRhaWxfbGV2ZWwsIGRhdGEgPSBkYXRhLCBmYW1pbHkgPSBiaW5vbWlhbCkNCg0KIyDQodGH0LjRgtCw0LXQvCDRgNCw0LfQvdC40YbRgyDQstC10YDQvtGP0YLQvdC+0YHRgtC10LkNCnJlc3VsdHMgPC0gcHJlZGljdGlvbnMoDQogIG1vZGVsLA0KICBuZXdkYXRhID0gZGF0YWdyaWQoZGV0YWlsX2xldmVsID0gNCksDQogIGh5cG90aGVzaXMgPSAiYjEgLSAwLjI1ID0gMCIsDQogIHR5cGUgPSAicmVzcG9uc2UiDQopDQoNCnByaW50KHJlc3VsdHMpDQpgYGANCg0KIyMg0JDQvdCw0LvQuNC3INC80L7RidC90L7RgdGC0LgNCg0KIyMjINCQ0L/QvtGB0YLQtdGA0LjQvtGA0L3Ri9C1INCw0L3QsNC70LjQt9GLINC80L7RidC90L7RgdGC0LgNCg0K0JDQv9C+0YHRgtC10YDQuNC+0YDQvdGL0Lkg0LDQvdCw0LvQuNC3INC80L7RidC90L7RgdGC0Lgg0LTQu9GPINGC0LXRgdGC0LAg0JrQvtC60YDQsNC90LAt0JDRgNC80LjRgtCw0LbQsDoNCg0KYGBge3IsIHBvc3Rlcmlvcl9jb2NocmFuZV9hcm1pdGFnZV9wb3dlcl9hbmFseXNpc30NCmxpYnJhcnkobXVsdGlDQSkNCg0KcG93ZXIuQ0EudGVzdCgNCiAgTiA9IDMwNCwgIyDQoNCw0LfQvNC10YAg0LLRi9Cx0L7RgNC60LggKNC60L7Qu9C40YfQtdGB0YLQstC+INCy0LDRgNC40LDQvdGC0L7QsiDQvtGC0LLQtdGC0LApDQogIG4ucHJvcCA9IGMoMC4yNSwgMC4yNSwgMC4yNSwgMC4yNSksICMg0J/RgNC+0L/QvtGA0YbQuNGPINGA0LDQt9C80LXRgNC+0LIg0LPRgNGD0L/QvyDQvdCwINC60LDQttC00L7QvCDRg9GA0L7QstC90LUNCiAgcHZlYyA9IGMoMC4xNzExLCAwLjI1LCAwLjI1LCAwLjMyODkpLCAjINCk0LDQutGC0LjRh9C10YHQutC40LUg0L/RgNC+0L/QvtGA0YbQuNC4INC/0YDQsNCy0LjQu9GM0L3Ri9GFINC+0YLQstC10YLQvtCyINC90LAg0LrQsNC20LTQvtC8INGD0YDQvtCy0L3QtQ0KICBzaWcubGV2ZWwgPSAwLjA1LCAjINCj0YDQvtCy0LXQvdGMINC30L3QsNGH0LjQvNC+0YHRgtC4INCw0LvRjNGE0LANCiAgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIgIyDQndCw0L/RgNCw0LLQu9C10L3QuNC1INC/0YDQvtCy0LXRgNC60LgNCikNCmBgYA0KDQojIyMg0JDQv9GA0LjQvtGA0L3Ri9C1INCw0L3QsNC70LjQt9GLINC80L7RidC90L7RgdGC0LgNCg0K0JDQv9GA0LjQvtGA0L3Ri9C5INCw0L3QsNC70LjQtyDQvNC+0YnQvdC+0YHRgtC4INC00LvRjyDRgtC10YHRgtCwINCa0L7QutGA0LDQvdCwLdCQ0YDQvNC40YLQsNC20LA6DQoNCmBgYHtyLCBwcmlvcl9jb2NocmFuZV9hcm1pdGFnZV9wb3dlcl9hbmFseXNpc30NCmxpYnJhcnkobXVsdGlDQSkNCg0KcG93ZXIuQ0EudGVzdCgNCiAgbi5wcm9wID0gYygwLjI1LCAwLjI1LCAwLjI1LCAwLjI1KSwgIyDQn9GA0L7Qv9C+0YDRhtC40Y8g0YDQsNC30LzQtdGA0L7QsiDQs9GA0YPQv9C/INC90LAg0LrQsNC20LTQvtC8INGD0YDQvtCy0L3QtQ0KICBwdmVjID0gYygwLjE3MTEsIDAuMjUsIDAuMjUsIDAuMzI4OSksICMg0KTQsNC60YLQuNGH0LXRgdC60LjQtSDQv9GA0L7Qv9C+0YDRhtC40Lgg0L/RgNCw0LLQuNC70YzQvdGL0YUg0L7RgtCy0LXRgtC+0LIg0L3QsCDQutCw0LbQtNC+0Lwg0YPRgNC+0LLQvdC1DQogIHNpZy5sZXZlbCA9IDAuMDUsICMg0KPRgNC+0LLQtdC90Ywg0LfQvdCw0YfQuNC80L7RgdGC0Lgg0LDQu9GM0YTQsA0KICBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIiwgIyDQndCw0L/RgNCw0LLQu9C10L3QuNC1INC/0YDQvtCy0LXRgNC60LgNCiAgcG93ZXIgPSAwLjggIyDQndC10L7QsdGF0L7QtNC40LzQsNGPINC80L7RidC90L7RgdGC0YwNCikNCmBgYA0KDQrQkNC/0YDQuNC+0YDQvdGL0Lkg0LDQvdCw0LvQuNC3INC80L7RidC90L7RgdGC0Lgg0LTQu9GPINC/0YDQsNC60YLQuNGH0LXRgdC60Lgg0LjQvdGC0LXRgNC10YHQvdC+0LPQviDRgNCw0LfQvNC10YDQsCDRjdGE0YTQtdC60YLQsCDQvNC10YLQvtC00L7QvCDQnNC+0L3RgtC1LdCa0LDRgNC70L4uINCg0LDRgdGH0ZHRgiDRgdGC0LDRgtC40YHRgtC40YfQtdGB0LrQvtC5INC80L7RidC90L7RgdGC0Lgg0LTQu9GPINCy0YvQsdC+0YDQutC4INGA0LDQt9C80LXRgNC+0LwgMTcyINCy0L7Qv9GA0L7RgdCwICg2ODgg0LLQsNGA0LjQsNC90YLQvtCyINC+0YLQstC10YLQsCk6DQoNCmBgYHtyLCBwcmlvcl9wcmFjdGljYWxfcG93ZXJfYW5hbHlzaXN9DQpsaWJyYXJ5KG1hcmdpbmFsZWZmZWN0cykNCg0KIyDQpNGD0L3QutGG0LjRjyDRgNCw0YHRh9GR0YLQsCDRgdGC0LDRgtC40YHRgtC40YfQtdGB0LrQvtC5INC80L7RidC90L7RgdGC0Ywg0L/QviDRgNCw0LfQvNC10YDRgyDQstGL0LHQvtGA0LrQuCBuX3Blcl9sZXZlbA0Kc2ltdWxhdGVfcG93ZXJfZXhhY3QgPC0gZnVuY3Rpb24obl9wZXJfbGV2ZWwsIGIwLCBiMSwgbl9zaW0sIGFscGhhKSB7DQogIHN1Y2Nlc3NfY291bnQgPC0gMA0KDQogIGZvciAoaSBpbiAxOm5fc2ltKSB7DQogICAgIyAxLiDQk9C10L3QtdGA0LjRgNGD0LXQvCDQtNCw0L3QvdGL0LUNCiAgICBzaW1fZGV0YWlsX2xldmVsIDwtIHJlcCgxOjQsIGVhY2ggPSBuX3Blcl9sZXZlbCkNCiAgICBzaW1fbG9nX29kZHMgPC0gYjAgKyBiMSAqIHNpbV9kZXRhaWxfbGV2ZWwNCiAgICBzaW1fcHJvYnMgPC0gMSAvICgxICsgZXhwKC1zaW1fbG9nX29kZHMpKQ0KICAgIHNpbV9jb3JyZWN0IDwtIHJiaW5vbShsZW5ndGgoc2ltX2RldGFpbF9sZXZlbCksIHNpemUgPSAxLCBwcm9iID0gc2ltX3Byb2JzKQ0KDQogICAgc2ltX2RhdGEgPC0gZGF0YS5mcmFtZShkZXRhaWxfbGV2ZWwgPSBzaW1fZGV0YWlsX2xldmVsLCBjb3JyZWN0ID0gc2ltX2NvcnJlY3QpDQoNCiAgICAjIDIuINCe0LHRg9GH0LDQtdC8INC80L7QtNC10LvRjA0KICAgIGZpdCA8LSBnbG0oY29ycmVjdCB+IGRldGFpbF9sZXZlbCwgZGF0YSA9IHNpbV9kYXRhLCBmYW1pbHkgPSBiaW5vbWlhbCkNCg0KICAgICMgMy4g0JjRgdC/0L7Qu9GM0LfRg9C10LwgbWFyZ2luYWxlZmZlY3RzINC00LvRjyDQv9GA0L7QstC10YDQutC4INC30L3QsNGH0LjQvNC+0YHRgtC4INGN0YTRhNC10LrRgtCwDQogICAgcmVzdWx0cyA8LSBwcmVkaWN0aW9ucygNCiAgICAgIGZpdCwNCiAgICAgIG5ld2RhdGEgPSBkYXRhZ3JpZChkZXRhaWxfbGV2ZWwgPSA0KSwNCiAgICAgIGh5cG90aGVzaXMgPSAiYjEgLSAwLjI1ID0gMCIsDQogICAgICB0eXBlID0gInJlc3BvbnNlIg0KICAgICkNCg0KICAgICMgNC4g0JjQt9Cy0LvQtdC60LDQtdC8INC+0LTQvdC+0YHRgtC+0YDQvtC90L3QtdC1IHAt0LfQvdCw0YfQtdC90LjQtQ0KICAgICMg0JTQtdC70LjQvCDQvdCwIDIsINC10YHQu9C4INGN0YTRhNC10LrRgiDQvdCw0L/RgNCw0LLQu9C10L0g0LIg0L7QttC40LTQsNC10LzRg9GOINGB0YLQvtGA0L7QvdGDIChFc3RpbWF0ZSA+IDApDQogICAgaWYgKHJlc3VsdHMkZXN0aW1hdGUgPiAwKSB7DQogICAgICBwX3ZhbF9vbmVfc2lkZWQgPC0gcmVzdWx0cyRwLnZhbHVlIC8gMg0KICAgIH0gZWxzZSB7DQogICAgICBwX3ZhbF9vbmVfc2lkZWQgPC0gMSAtIChyZXN1bHRzJHAudmFsdWUgLyAyKQ0KICAgIH0NCg0KICAgIGlmIChwX3ZhbF9vbmVfc2lkZWQgPCBhbHBoYSkgew0KICAgICAgc3VjY2Vzc19jb3VudCA8LSBzdWNjZXNzX2NvdW50ICsgMQ0KICAgIH0NCiAgfQ0KDQogIHJldHVybihzdWNjZXNzX2NvdW50IC8gbl9zaW0pDQp9DQoNCiMg0KDQsNGB0YfQuNGC0YvQstCw0LXQvCDRgdGC0LDRgtC40YHRgtC40YfQtdGB0LrRg9GOINC80L7RidC90L7RgdGC0YwNCnNldC5zZWVkKDQyKQ0KZXN0aW1hdGVkX3Bvd2VyIDwtIHNpbXVsYXRlX3Bvd2VyX2V4YWN0KA0KICBuX3Blcl9sZXZlbCA9IDE3MiwgIyDQoNCw0LfQvNC10YAg0LLRi9Cx0L7RgNC60Lgg0L3QsCDQutCw0LbQtNGL0Lkg0YPRgNC+0LLQtdC90YwgKNC60L7Qu9C40YfQtdGB0YLQstC+INCy0L7Qv9GA0L7RgdC+0LIpDQogIGIwID0gY29lZihtb2RlbClbMV0sICMg0JrQvtC90YHRgtCw0L3RgtCwIChpbnRlcmNlcHQpINCyINGA0LXQs9GA0LXRgdGB0LjQuA0KICBiMSA9IGNvZWYobW9kZWwpWzJdLCAjINCa0L7RjdGE0YTQuNGG0LjQtdC90YIg0LTQu9GPINC/0LXRgNC10LzQtdC90L3QvtC5IGRldGFpbF9sZXZlbA0KICBuX3NpbSA9IDEwMCwgIyDQmtC+0LvQuNGH0LXRgdGC0LLQviDRgdC40LzRg9C70Y/RhtC40LkNCiAgYWxwaGEgPSAwLjA1ICMg0KPRgNC+0LLQtdC90Ywg0LfQvdCw0YfQuNC80L7RgdGC0LggzrENCikNCg0KcHJpbnQoZXN0aW1hdGVkX3Bvd2VyKQ0KYGBg