Статистическая значимость
Односторонний тест Кокрана-Армитажа на тренд:
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