# Load necessary libraries
library(readxl) # For reading Excel files
library(dplyr) # For data manipulation
library(irr) # For Kappa statistic
library(writexl)
# Count Pos/Neg for each column
freq_table <- sapply(data[, -1], function(x) table(x))
freq_df <- as.data.frame(t(freq_table))
freq_df
# Function to calculate prevalence and CI
calculate_prevalence <- function(test_column) {
positives <- sum(test_column == "Pos") # Count the number of positives
total <- length(test_column) # Total number of participants
prevalence <- positives / total # Prevalence
# Calculate 95% CI for prevalence
ci <- prop.test(positives, total, conf.level = 0.95)
return(c(Prevalence = prevalence, CI_Lower = ci$conf.int[1], CI_Upper = ci$conf.int[2]))
}
# Apply the function to each diagnostic method
prevalence_combined_EV <- calculate_prevalence(data$Combined_EV)
prevalence_kk_EV <- calculate_prevalence(data$KK_EV)
prevalence_snf_EV <- calculate_prevalence(data$SNF_EV)
prevalence_combined_TT <- calculate_prevalence(data$Combined_TT)
prevalence_kk_TT <- calculate_prevalence(data$KK_TT)
prevalence_snf_TT <- calculate_prevalence(data$SNF_TT)
prevalence_combined_AL <- calculate_prevalence(data$Combined_AL)
prevalence_kk_AL <- calculate_prevalence(data$KK_AL)
prevalence_snf_AL <- calculate_prevalence(data$SNF_AL)
prevalence_combined_HW <- calculate_prevalence(data$Combined_HW)
prevalence_kk_HW <- calculate_prevalence(data$KK_HW)
prevalence_snf_HW <- calculate_prevalence(data$SNF_HW)
prevalence_baermann_HW_SG <- calculate_prevalence(data$Baermann_HW_SG)
prevalence_combined_STHs <- calculate_prevalence(data$STHs_CombiNeged)
prevalence_kk_STHs <- calculate_prevalence(data$STHs_KK)
prevalence_snf_STHs <- calculate_prevalence(data$STHs_SNF)
prevalence_STHs_baermann <- calculate_prevalence(data$STHs_Baermann)
prevalence_table <- data.frame(
Diagnostic_Technique = c(
"Combined_EV", "KK_EV", "SNF_EV",
"Combined_TT", "KK_TT", "SNF_TT",
"Combined_AL", "KK_AL", "SNF_AL",
"Combined_HW", "KK_HW", "SNF_HW",
"Baermann_HW_SG",
"Combined_STHs", "KK_STHs", "SNF_STHs", "STHs_Baermann"
),
Prevalence = c(
prevalence_combined_EV[1], prevalence_kk_EV[1], prevalence_snf_EV[1],
prevalence_combined_TT[1], prevalence_kk_TT[1], prevalence_snf_TT[1],
prevalence_combined_AL[1], prevalence_kk_AL[1], prevalence_snf_AL[1],
prevalence_combined_HW[1], prevalence_kk_HW[1], prevalence_snf_HW[1],
prevalence_baermann_HW_SG[1],
prevalence_combined_STHs[1], prevalence_kk_STHs[1], prevalence_snf_STHs[1],
prevalence_STHs_baermann[1]
),
CI_Lower = c(
prevalence_combined_EV[2], prevalence_kk_EV[2], prevalence_snf_EV[2],
prevalence_combined_TT[2], prevalence_kk_TT[2], prevalence_snf_TT[2],
prevalence_combined_AL[2], prevalence_kk_AL[2], prevalence_snf_AL[2],
prevalence_combined_HW[2], prevalence_kk_HW[2], prevalence_snf_HW[2],
prevalence_baermann_HW_SG[2],
prevalence_combined_STHs[2], prevalence_kk_STHs[2], prevalence_snf_STHs[2],
prevalence_STHs_baermann[2]
),
CI_Upper = c(
prevalence_combined_EV[3], prevalence_kk_EV[3], prevalence_snf_EV[3],
prevalence_combined_TT[3], prevalence_kk_TT[3], prevalence_snf_TT[3],
prevalence_combined_AL[3], prevalence_kk_AL[3], prevalence_snf_AL[3],
prevalence_combined_HW[3], prevalence_kk_HW[3], prevalence_snf_HW[3],
prevalence_baermann_HW_SG[3],
prevalence_combined_STHs[3], prevalence_kk_STHs[3], prevalence_snf_STHs[3],
prevalence_STHs_baermann[3]
)
)
print(prevalence_table)
# Function to calculate sensitivity, specificity, PPV, and NPV
calculate_metrics <- function(conf_matrix) {
TP <- conf_matrix[2, 2] # True Positive
FP <- conf_matrix[1, 2] # False Positive
TN <- conf_matrix[1, 1] # True Negative
FN <- conf_matrix[2, 1] # False Negative
# Sensitivity = TP / (TP + FN)
sensitivity <- TP / (TP + FN)
# Specificity = TN / (TN + FP)
specificity <- TN / (TN + FP)
# PPV = TP / (TP + FP)
ppv <- TP / (TP + FP)
# NPV = TN / (TN + FN)
npv <- TN / (TN + FN)
# Calculate 95% CI for each metric using prop.test
sensitivity_ci <- prop.test(TP, TP + FN, conf.level = 0.95)$conf.int
specificity_ci <- prop.test(TN, TN + FP, conf.level = 0.95)$conf.int
ppv_ci <- prop.test(TP, TP + FP, conf.level = 0.95)$conf.int
npv_ci <- prop.test(TN, TN + FN, conf.level = 0.95)$conf.int
return(data.frame(
Sensitivity = round(sensitivity * 100, 2),
Sensitivity_Lower_CI = round(sensitivity_ci[1] * 100, 2),
Sensitivity_Upper_CI = round(sensitivity_ci[2] * 100, 2),
Specificity = round(specificity * 100, 2),
Specificity_Lower_CI = round(specificity_ci[1] * 100, 2),
Specificity_Upper_CI = round(specificity_ci[2] * 100, 2),
PPV = round(ppv * 100, 2),
PPV_Lower_CI = round(ppv_ci[1] * 100, 2),
PPV_Upper_CI = round(ppv_ci[2] * 100, 2),
NPV = round(npv * 100, 2),
NPV_Lower_CI = round(npv_ci[1] * 100, 2),
NPV_Upper_CI = round(npv_ci[2] * 100, 2)
))
}
# Gold standards for each species
gold_standards <- list(
AL = "Combined_AL", # A. lumbricoides uses Combined_AL as the gold standard
HW = "Combined_HW", # Hookworm uses Combined_HW as the gold standard
TT = "Combined_TT", # T. trichiura uses Combined_TT as the gold standard
EV = "Combined_EV", # E. vermicularis uses Combined_EV as the gold standard
STHs = "STHs_CombiNeged" # STHs (all species combined) uses STHs_CombiNeged as the gold standard
)
# List of diagnostic methods (your actual diagnostic test columns in your dataset)
diagnostic_methods <- c("STHs_KK", "KK_EV", "KK_TT", "KK_AL", "KK_HW",
"STHs_SNF", "SNF_EV", "SNF_TT", "SNF_AL", "SNF_HW",
"STHs_Baermann", "Baermann_HW_SG")
# Create an empty data frame to store results
results_table <- data.frame()
# Loop through each diagnostic method and calculate metrics
for (test in diagnostic_methods) {
# Get the species corresponding to each test method
if (grepl("KK_", test)) {
species <- sub("KK_", "", test) # Extract the species name from the test (e.g., KK_AL -> AL)
} else if (grepl("SNF_", test)) {
species <- sub("SNF_", "", test) # Extract the species name from the test (e.g., SNF_EV -> EV)
} else if (grepl("Baermann", test)) {
species <- "STHs" # Baermann methods will use STHs combined data
} else {
species <- "STHs" # Other tests like STHs_KK use combined data
}
# Define the gold standard for this species
gold_standard <- gold_standards[[species]]
# Create confusion matrix for each test vs the gold standard (species-specific gold standard)
conf_matrix <- table(data[[gold_standard]], data[[test]])
# Calculate sensitivity, specificity, PPV, and NPV for each method
metrics <- calculate_metrics(conf_matrix)
# Add results to the results table
results_table <- rbind(results_table, data.frame(
Diagnostic_Technique = test,
Species = species,
Sensitivity = metrics$Sensitivity,
Sensitivity_Lower_CI = metrics$Sensitivity_Lower_CI,
Sensitivity_Upper_CI = metrics$Sensitivity_Upper_CI,
Specificity = metrics$Specificity,
Specificity_Lower_CI = metrics$Specificity_Lower_CI,
Specificity_Upper_CI = metrics$Specificity_Upper_CI,
PPV = metrics$PPV,
PPV_Lower_CI = metrics$PPV_Lower_CI,
PPV_Upper_CI = metrics$PPV_Upper_CI,
NPV = metrics$NPV,
NPV_Lower_CI = metrics$NPV_Lower_CI,
NPV_Upper_CI = metrics$NPV_Upper_CI
))
}
# Print the results table
print(results_table)
# Function to calculate frequencies of positive and negative cases for each diagnostic method
calculate_frequencies <- function(test_column, species_column) {
# Create a contingency table for the species and the diagnostic method
freq_table <- table(species_column, test_column)
return(freq_table)
}
# Create an empty data frame to store results
frequencies_table <- data.frame()
# List of diagnostic methods (your actual diagnostic test columns in your dataset)
diagnostic_methods <- c("STHs_KK", "KK_EV", "KK_TT", "KK_AL", "KK_HW",
"STHs_SNF", "SNF_EV", "SNF_TT", "SNF_AL", "SNF_HW",
"STHs_Baermann", "Baermann_HW_SG")
# Loop through each diagnostic method and calculate frequencies
for (test in diagnostic_methods) {
# Get the species corresponding to each test method
if (grepl("KK_", test)) {
species <- sub("KK_", "", test) # Extract the species name from the test (e.g., KK_AL -> AL)
} else if (grepl("SNF_", test)) {
species <- sub("SNF_", "", test) # Extract the species name from the test (e.g., SNF_EV -> EV)
} else if (grepl("Baermann", test)) {
species <- "STHs" # Baermann methods will use STHs combined data
} else {
species <- "STHs" # Other tests like STHs_KK use combined data
}
# Define the gold standard for this species
gold_standard <- gold_standards[[species]]
# Calculate frequencies for each diagnostic method and species
freq_table <- calculate_frequencies(data[[test]], data[[gold_standard]])
# Add the frequencies table to the results
frequencies_table <- rbind(frequencies_table, data.frame(
Diagnostic_Technique = test,
Species = species,
Positives = freq_table["Pos", "Pos"], # Positive cases
Negatives = freq_table["Neg", "Neg"] # Negative cases
))
}
# Print the frequencies table
print(frequencies_table)
# Function to calculate prevalence and 95% CI
calculate_prevalence <- function(test_column, total_participants) {
positives <- sum(test_column == "Pos") # Count the number of positives
prevalence <- positives / total_participants * 100 # Prevalence in percentage
# Calculate 95% CI for prevalence using prop.test
ci <- prop.test(positives, total_participants, conf.level = 0.95)
return(c(Prevalence = prevalence, CI_Lower = ci$conf.int[1] * 100, CI_Upper = ci$conf.int[2] * 100))
}
# Total participants
total_participants <- 333
# Assuming 'data' contains your dataset and "KK" and "SNF" are the respective columns
# Prevalence for KK method
prevalence_KK <- calculate_prevalence(data$STHs_KK, total_participants)
# Prevalence for SNF method
prevalence_SNF <- calculate_prevalence(data$STHs_SNF, total_participants)
# Prevalence for combined KK and SNF method (i.e., any positive result in either KK or SNF)
combined_KK_SNF <- calculate_prevalence((data$STHs_KK == "Pos" | data$STHs_SNF == "Pos"), total_participants)
# Prepare the results table
results <- data.frame(
Method = c("KK", "SNF", "KK + SNF"),
Total_Examined = rep(total_participants, 3),
Positives = c(sum(data$STHs_KK == "Pos"), sum(data$STHs_SNF == "Pos"), sum(data$STHs_KK == "Pos" | data$STHs_SNF == "Pos")),
Prevalence = c(prevalence_KK[1], prevalence_SNF[1], combined_KK_SNF[1]),
CI_Lower = c(prevalence_KK[2], prevalence_SNF[2], combined_KK_SNF[2]),
CI_Upper = c(prevalence_KK[3], prevalence_SNF[3], combined_KK_SNF[3])
)
# Print the results
print(results)
positives <- 176
total_participants <- 333
# Use prop.test to calculate the 95% confidence interval for the proportion of positives
ci_result <- prop.test(positives, total_participants, conf.level = 0.95)
# Print the result
ci_result$conf.int
[1] 0.4734004 0.5829878
attr(,"conf.level")
[1] 0.95
################################################
# Function to calculate manual Cohen's Kappa
manual_kappa <- function(conf_matrix) {
TP <- conf_matrix[2, 2] # True Positives
FP <- conf_matrix[1, 2] # False Positives
TN <- conf_matrix[1, 1] # True Negatives
FN <- conf_matrix[2, 1] # False Negatives
P_o <- (TP + TN) / sum(conf_matrix) # Observed Agreement
P_e <- ((TP + FP) / sum(conf_matrix)) * ((TP + FN) / sum(conf_matrix)) +
((TN + FN) / sum(conf_matrix)) * ((TN + FP) / sum(conf_matrix)) # Expected Agreement
kappa <- (P_o - P_e) / (1 - P_e)
return(kappa)
}
# Example confusion matrix for KK_AL vs Combined_AL
kk_al_table <- table(data$KK_AL, data$Combined_AL)
# Calculate manual Kappa for each comparison
kappa_kk_al <- manual_kappa(kk_al_table)
kappa_kk_al
[1] 0.9552651
#Calculate for snf_al,kk_ev,snf_ev
kappa_snf_al <- manual_kappa(table(data$SNF_AL, data$Combined_AL))
kappa_kk_ev <- manual_kappa(table(data$KK_EV, data$Combined_EV))
kappa_snf_ev <- manual_kappa(table(data$SNF_EV, data$Combined_EV))
kappa_kk_tt <- manual_kappa(table(data$KK_TT, data$Combined_TT))
kappa_snf_tt <- manual_kappa(table(data$SNF_TT, data$Combined_TT))
kappa_kk_hw <- manual_kappa(table(data$KK_HW, data$Combined_HW))
kappa_snf_hw <- manual_kappa(table(data$SNF_HW, data$Combined_HW))
kappa_kk_STHs <- manual_kappa(table(data$STHs_KK, data$STHs_CombiNeged))
kappa_snf_STHs <- manual_kappa(table(data$STHs_SNF, data$STHs_CombiNeged))
kappa_bm_hw <- manual_kappa(table(data$Baermann_HW_SG, data$Combined_HW))
kappa_bm_STH <- manual_kappa(table(data$STHs_Baermann, data$STHs_CombiNeged))
print(kappa_snf_al)
[1] 0.2362215
print(kappa_kk_ev)
[1] 0.5457026
print(kappa_snf_ev)
[1] 0.9135738
print(kappa_kk_tt)
[1] 0.9596999
print(kappa_snf_tt)
[1] 0.6788337
print(kappa_kk_hw)
[1] 0.4547615
print(kappa_snf_hw)
[1] 0.7283604
print(kappa_kk_STHs)
[1] 0.8388045
print(kappa_snf_STHs)
[1] 0.39979
print(kappa_bm_hw)
[1] 0.6723516
print(kappa_bm_STH)
[1] 0.1235787
##########################
###########################
# Function to calculate manual Cohen's Kappa and p-value
manual_kappa_with_pvalue <- function(conf_matrix, n) {
TP <- conf_matrix[2, 2] # True Positives
FP <- conf_matrix[1, 2] # False Positives
TN <- conf_matrix[1, 1] # True Negatives
FN <- conf_matrix[2, 1] # False Negatives
P_o <- (TP + TN) / sum(conf_matrix) # Observed Agreement
P_e <- ((TP + FP) / sum(conf_matrix)) * ((TP + FN) / sum(conf_matrix)) +
((TN + FN) / sum(conf_matrix)) * ((TN + FP) / sum(conf_matrix)) # Expected Agreement
kappa <- (P_o - P_e) / (1 - P_e)
# Calculate the z-score for Cohen's Kappa
z <- kappa / sqrt((1 - kappa^2) / (n - 1))
# Calculate the p-value using the z-score
p_value <- 2 * (1 - pnorm(abs(z))) # Two-tailed p-value
return(list(Kappa = kappa, p_value = p_value))
}
# Example for KK_AL vs Combined_AL (confusion matrix already given)
kk_al_table <- table(data$KK_AL, data$Combined_AL)
# Total number of subjects (replace with your actual n)
n <- sum(kk_al_table) # Total number of subjects
# Calculate manual Kappa and p-value
kappa_kk_al_result <- manual_kappa_with_pvalue(kk_al_table, n)
# Print Kappa and p-value
print(paste("Kappa: ", kappa_kk_al_result$Kappa))
[1] "Kappa: 0.955265127526052"
print(paste("p-value: ", kappa_kk_al_result$p_value))
[1] "p-value: 0"
# Repeat for other comparisons
kappa_snf_al_result <- manual_kappa_with_pvalue(table(data$SNF_AL, data$Combined_AL), n)
kappa_kk_ev_result <- manual_kappa_with_pvalue(table(data$KK_EV, data$Combined_EV), n)
kappa_snf_ev_result <- manual_kappa_with_pvalue(table(data$SNF_EV, data$Combined_EV), n)
kappa_kk_tt_result <- manual_kappa_with_pvalue(table(data$KK_TT, data$Combined_TT), n)
kappa_snf_tt_result <- manual_kappa_with_pvalue(table(data$SNF_TT, data$Combined_TT), n)
kappa_kk_hw_result <- manual_kappa_with_pvalue(table(data$KK_HW, data$Combined_HW), n)
kappa_snf_hw_result <- manual_kappa_with_pvalue(table(data$SNF_HW, data$Combined_HW), n)
kappa_kk_sths_result <- manual_kappa_with_pvalue(table(data$STHs_KK, data$STHs_CombiNeged), n)
kappa_snf_sths_result <- manual_kappa_with_pvalue(table(data$STHs_SNF, data$STHs_CombiNeged), n)
kappa_bm_hw_result <- manual_kappa_with_pvalue(table(data$Baermann_HW_SG, data$Combined_HW), n)
kappa_bm_sth_result <- manual_kappa_with_pvalue(table(data$STHs_Baermann, data$STHs_CombiNeged), n)
# Print results
print(kappa_snf_al_result)
$Kappa
[1] 0.2362215
$p_value
[1] 9.444312e-06
print(kappa_kk_ev_result)
$Kappa
[1] 0.5457026
$p_value
[1] 0
print(kappa_snf_ev_result)
$Kappa
[1] 0.9135738
$p_value
[1] 0
print(kappa_kk_tt_result)
$Kappa
[1] 0.9596999
$p_value
[1] 0
print(kappa_snf_tt_result)
$Kappa
[1] 0.6788337
$p_value
[1] 0
print(kappa_kk_hw_result)
$Kappa
[1] 0.4547615
$p_value
[1] 0
print(kappa_snf_hw_result)
$Kappa
[1] 0.7283604
$p_value
[1] 0
print(kappa_kk_sths_result)
$Kappa
[1] 0.8388045
$p_value
[1] 0
print(kappa_snf_sths_result)
$Kappa
[1] 0.39979
$p_value
[1] 1.998401e-15
print(kappa_bm_hw_result)
$Kappa
[1] 0.6723516
$p_value
[1] 0
print(kappa_bm_sth_result)
$Kappa
[1] 0.1235787
$p_value
[1] 0.023262
#95% CI of kappa
# Function to calculate manual Cohen's Kappa, p-value, and 95% CI
manual_kappa_with_ci <- function(conf_matrix, n) {
TP <- conf_matrix[2, 2] # True Positives
FP <- conf_matrix[1, 2] # False Positives
TN <- conf_matrix[1, 1] # True Negatives
FN <- conf_matrix[2, 1] # False Negatives
P_o <- (TP + TN) / sum(conf_matrix) # Observed Agreement
P_e <- ((TP + FP) / sum(conf_matrix)) * ((TP + FN) / sum(conf_matrix)) +
((TN + FN) / sum(conf_matrix)) * ((TN + FP) / sum(conf_matrix)) # Expected Agreement
kappa <- (P_o - P_e) / (1 - P_e)
# Calculate the standard error (SE) of Cohen's Kappa
se_kappa <- sqrt((1 - kappa^2) / (n - 1))
# Calculate the z-score for Cohen's Kappa
z <- kappa / se_kappa
# Calculate the p-value using the z-score
p_value <- 2 * (1 - pnorm(abs(z))) # Two-tailed p-value
# Calculate the 95% Confidence Interval for Cohen's Kappa
lower_ci <- kappa - 1.96 * se_kappa
upper_ci <- kappa + 1.96 * se_kappa
return(list(Kappa = kappa, p_value = p_value, Lower_CI = lower_ci, Upper_CI = upper_ci))
}
# Example for KK_AL vs Combined_AL (confusion matrix already given)
kk_al_table <- table(data$KK_AL, data$Combined_AL)
# Total number of subjects (replace with your actual n)
n <- sum(kk_al_table) # Total number of subjects
# Calculate manual Kappa, p-value, and 95% CI
kk_al_result <- manual_kappa_with_ci(kk_al_table, n)
# Print Kappa, p-value, and 95% CI
print(paste("Kappa: ", kk_al_result$Kappa))
[1] "Kappa: 0.955265127526052"
print(paste("p-value: ", kk_al_result$p_value))
[1] "p-value: 0"
print(paste("95% CI: ", round(kk_al_result$Lower_CI, 3), " to ", round(kk_al_result$Upper_CI, 3)))
[1] "95% CI: 0.923 to 0.987"
# Repeat for other comparisons
kappa_snf_al_result <- manual_kappa_with_ci(table(data$SNF_AL, data$Combined_AL), n)
kappa_kk_ev_result <- manual_kappa_with_ci(table(data$KK_EV, data$Combined_EV), n)
kappa_snf_ev_result <- manual_kappa_with_ci(table(data$SNF_EV, data$Combined_EV), n)
kappa_kk_tt_result <- manual_kappa_with_ci(table(data$KK_TT, data$Combined_TT), n)
kappa_snf_tt_result <- manual_kappa_with_ci(table(data$SNF_TT, data$Combined_TT), n)
kappa_kk_hw_result <- manual_kappa_with_ci(table(data$KK_HW, data$Combined_HW), n)
kappa_snf_hw_result <- manual_kappa_with_ci(table(data$SNF_HW, data$Combined_HW), n)
kappa_kk_sths_result <- manual_kappa_with_ci(table(data$STHs_KK, data$STHs_CombiNeged), n)
kappa_snf_sths_result <- manual_kappa_with_ci(table(data$STHs_SNF, data$STHs_CombiNeged), n)
kappa_bm_hw_result <- manual_kappa_with_ci(table(data$Baermann_HW_SG, data$Combined_HW), n)
kappa_bm_sth_result <- manual_kappa_with_ci(table(data$STHs_Baermann, data$STHs_CombiNeged), n)
# Print results
print(kk_al_result)
$Kappa
[1] 0.9552651
$p_value
[1] 0
$Lower_CI
[1] 0.9234515
$Upper_CI
[1] 0.9870787
print(kappa_snf_al_result)
$Kappa
[1] 0.2362215
$p_value
[1] 9.444312e-06
$Lower_CI
[1] 0.1316968
$Upper_CI
[1] 0.3407462
print(kappa_kk_ev_result)
$Kappa
[1] 0.5457026
$p_value
[1] 0
$Lower_CI
[1] 0.4555621
$Upper_CI
[1] 0.6358431
print(kappa_snf_ev_result)
$Kappa
[1] 0.9135738
$p_value
[1] 0
$Lower_CI
[1] 0.8698285
$Upper_CI
[1] 0.9573192
print(kappa_kk_tt_result)
$Kappa
[1] 0.9596999
$p_value
[1] 0
$Lower_CI
[1] 0.9294701
$Upper_CI
[1] 0.9899297
print(kappa_snf_tt_result)
$Kappa
[1] 0.6788337
$p_value
[1] 0
$Lower_CI
[1] 0.5998467
$Upper_CI
[1] 0.7578208
print(kappa_kk_hw_result)
$Kappa
[1] 0.4547615
$p_value
[1] 0
$Lower_CI
[1] 0.3589592
$Upper_CI
[1] 0.5505639
print(kappa_snf_hw_result)
$Kappa
[1] 0.7283604
$p_value
[1] 0
$Lower_CI
[1] 0.6546547
$Upper_CI
[1] 0.802066
print(kappa_kk_sths_result)
$Kappa
[1] 0.8388045
$p_value
[1] 0
$Lower_CI
[1] 0.7802405
$Upper_CI
[1] 0.8973686
print(kappa_snf_sths_result)
$Kappa
[1] 0.39979
$p_value
[1] 1.998401e-15
$Lower_CI
[1] 0.3011916
$Upper_CI
[1] 0.4983885
print(kappa_bm_hw_result)
$Kappa
[1] 0.6723516
$p_value
[1] 0
$Lower_CI
[1] 0.5927256
$Upper_CI
[1] 0.7519776
print(kappa_bm_sth_result)
$Kappa
[1] 0.1235787
$p_value
[1] 0.023262
$Lower_CI
[1] 0.01683426
$Upper_CI
[1] 0.2303231
###
# Function to calculate manual Cohen's Kappa, p-value, and 95% CI
manual_kappa_with_ci <- function(conf_matrix, n) {
TP <- conf_matrix[2, 2] # True Positives
FP <- conf_matrix[1, 2] # False Positives
TN <- conf_matrix[1, 1] # True Negatives
FN <- conf_matrix[2, 1] # False Negatives
P_o <- (TP + TN) / sum(conf_matrix) # Observed Agreement
P_e <- ((TP + FP) / sum(conf_matrix)) * ((TP + FN) / sum(conf_matrix)) +
((TN + FN) / sum(conf_matrix)) * ((TN + FP) / sum(conf_matrix)) # Expected Agreement
kappa <- (P_o - P_e) / (1 - P_e)
# Calculate the standard error (SE) of Cohen's Kappa
se_kappa <- sqrt((1 - kappa^2) / (n - 1))
# Calculate the z-score for Cohen's Kappa
z <- kappa / se_kappa
# Calculate the p-value using the z-score
p_value <- 2 * (1 - pnorm(abs(z))) # Two-tailed p-value
# Calculate the 95% Confidence Interval for Cohen's Kappa
lower_ci <- kappa - 1.96 * se_kappa
upper_ci <- kappa + 1.96 * se_kappa
# Format the 95% CI in the required style
ci_str <- paste("95% CI: ", round(lower_ci, 3), " to ", round(upper_ci, 3))
return(list(Kappa = kappa, p_value = p_value, CI = ci_str))
}
# Example for KK_AL vs Combined_AL (confusion matrix already given)
kk_al_table <- table(data$KK_AL, data$Combined_AL)
# Total number of subjects (replace with your actual n)
n <- sum(kk_al_table) # Total number of subjects
# Calculate manual Kappa, p-value, and 95% CI
kk_al_result <- manual_kappa_with_ci(kk_al_table, n)
# Print Kappa, p-value, and formatted 95% CI
print(paste("Kappa: ", round(kk_al_result$Kappa, 3)))
[1] "Kappa: 0.955"
print(paste("p-value: ", round(kk_al_result$p_value, 5)))
[1] "p-value: 0"
print(kk_al_result$CI)
[1] "95% CI: 0.923 to 0.987"
# Repeat for other comparisons
kappa_snf_al_result <- manual_kappa_with_ci(table(data$SNF_AL, data$Combined_AL), n)
kappa_kk_ev_result <- manual_kappa_with_ci(table(data$KK_EV, data$Combined_EV), n)
kappa_snf_ev_result <- manual_kappa_with_ci(table(data$SNF_EV, data$Combined_EV), n)
kappa_kk_tt_result <- manual_kappa_with_ci(table(data$KK_TT, data$Combined_TT), n)
kappa_snf_tt_result <- manual_kappa_with_ci(table(data$SNF_TT, data$Combined_TT), n)
kappa_kk_hw_result <- manual_kappa_with_ci(table(data$KK_HW, data$Combined_HW), n)
kappa_snf_hw_result <- manual_kappa_with_ci(table(data$SNF_HW, data$Combined_HW), n)
kappa_kk_sths_result <- manual_kappa_with_ci(table(data$STHs_KK, data$STHs_CombiNeged), n)
kappa_snf_sths_result <- manual_kappa_with_ci(table(data$STHs_SNF, data$STHs_CombiNeged), n)
kappa_bm_hw_result <- manual_kappa_with_ci(table(data$Baermann_HW_SG, data$Combined_HW), n)
kappa_bm_sth_result <- manual_kappa_with_ci(table(data$STHs_Baermann, data$STHs_CombiNeged), n)
# Print results
print(kk_al_result)
$Kappa
[1] 0.9552651
$p_value
[1] 0
$CI
[1] "95% CI: 0.923 to 0.987"
print(kappa_snf_al_result)
$Kappa
[1] 0.2362215
$p_value
[1] 9.444312e-06
$CI
[1] "95% CI: 0.132 to 0.341"
print(kappa_kk_ev_result)
$Kappa
[1] 0.5457026
$p_value
[1] 0
$CI
[1] "95% CI: 0.456 to 0.636"
print(kappa_snf_ev_result)
$Kappa
[1] 0.9135738
$p_value
[1] 0
$CI
[1] "95% CI: 0.87 to 0.957"
print(kappa_kk_tt_result)
$Kappa
[1] 0.9596999
$p_value
[1] 0
$CI
[1] "95% CI: 0.929 to 0.99"
print(kappa_snf_tt_result)
$Kappa
[1] 0.6788337
$p_value
[1] 0
$CI
[1] "95% CI: 0.6 to 0.758"
print(kappa_kk_hw_result)
$Kappa
[1] 0.4547615
$p_value
[1] 0
$CI
[1] "95% CI: 0.359 to 0.551"
print(kappa_snf_hw_result)
$Kappa
[1] 0.7283604
$p_value
[1] 0
$CI
[1] "95% CI: 0.655 to 0.802"
print(kappa_kk_sths_result)
$Kappa
[1] 0.8388045
$p_value
[1] 0
$CI
[1] "95% CI: 0.78 to 0.897"
print(kappa_snf_sths_result)
$Kappa
[1] 0.39979
$p_value
[1] 1.998401e-15
$CI
[1] "95% CI: 0.301 to 0.498"
print(kappa_bm_hw_result)
$Kappa
[1] 0.6723516
$p_value
[1] 0
$CI
[1] "95% CI: 0.593 to 0.752"
print(kappa_bm_sth_result)
$Kappa
[1] 0.1235787
$p_value
[1] 0.023262
$CI
[1] "95% CI: 0.017 to 0.23"
###########
# Function to calculate manual Cohen's Kappa, p-value, 95% CI, P_o, and P_e
manual_kappa_with_details <- function(conf_matrix, n) {
TP <- conf_matrix[2, 2] # True Positives
FP <- conf_matrix[1, 2] # False Positives
TN <- conf_matrix[1, 1] # True Negatives
FN <- conf_matrix[2, 1] # False Negatives
# Calculate Observed Agreement (P_o)
P_o <- (TP + TN) / sum(conf_matrix)
# Calculate Expected Agreement (P_e)
P_e <- ((TP + FP) / sum(conf_matrix)) * ((TP + FN) / sum(conf_matrix)) +
((TN + FN) / sum(conf_matrix)) * ((TN + FP) / sum(conf_matrix))
# Calculate Cohen's Kappa
kappa <- (P_o - P_e) / (1 - P_e)
# Calculate the standard error (SE) of Cohen's Kappa
se_kappa <- sqrt((1 - kappa^2) / (n - 1))
# Calculate the z-score for Cohen's Kappa
z <- kappa / se_kappa
# Calculate the p-value using the z-score
p_value <- 2 * (1 - pnorm(abs(z))) # Two-tailed p-value
# Calculate the 95% Confidence Interval for Cohen's Kappa
lower_ci <- kappa - 1.96 * se_kappa
upper_ci <- kappa + 1.96 * se_kappa
# Format the 95% CI in the required style
ci_str <- paste("95% CI: ", round(lower_ci, 3), " to ", round(upper_ci, 3))
# Return the results
return(list(Kappa = kappa, p_value = p_value, P_o = P_o, P_e = P_e, CI = ci_str))
}
# Example for KK_AL vs Combined_AL (confusion matrix already given)
kk_al_table <- table(data$KK_AL, data$Combined_AL)
# Total number of subjects (replace with your actual n)
n <- sum(kk_al_table) # Total number of subjects
# Calculate manual Kappa, p-value, 95% CI, P_o, and P_e
kk_al_result <- manual_kappa_with_details(kk_al_table, n)
# Print Kappa, p-value, P_o, P_e, and formatted 95% CI
print(paste("Kappa: ", round(kk_al_result$Kappa, 3)))
[1] "Kappa: 0.955"
print(paste("p-value: ", round(kk_al_result$p_value, 5)))
[1] "p-value: 0"
print(paste("P_o (Observed Agreement): ", round(kk_al_result$P_o, 3)))
[1] "P_o (Observed Agreement): 0.979"
print(paste("P_e (Expected Agreement): ", round(kk_al_result$P_e, 3)))
[1] "P_e (Expected Agreement): 0.53"
print(kk_al_result$CI)
[1] "95% CI: 0.923 to 0.987"
# Repeat for other comparisons
kappa_snf_al_result <- manual_kappa_with_details(table(data$SNF_AL, data$Combined_AL), n)
kappa_kk_ev_result <- manual_kappa_with_details(table(data$KK_EV, data$Combined_EV), n)
kappa_snf_ev_result <- manual_kappa_with_details(table(data$SNF_EV, data$Combined_EV), n)
kappa_kk_tt_result <- manual_kappa_with_details(table(data$KK_TT, data$Combined_TT), n)
kappa_snf_tt_result <- manual_kappa_with_details(table(data$SNF_TT, data$Combined_TT), n)
kappa_kk_hw_result <- manual_kappa_with_details(table(data$KK_HW, data$Combined_HW), n)
kappa_snf_hw_result <- manual_kappa_with_details(table(data$SNF_HW, data$Combined_HW), n)
kappa_kk_sths_result <- manual_kappa_with_details(table(data$STHs_KK, data$STHs_CombiNeged), n)
kappa_snf_sths_result <- manual_kappa_with_details(table(data$STHs_SNF, data$STHs_CombiNeged), n)
kappa_bm_hw_result <- manual_kappa_with_details(table(data$Baermann_HW_SG, data$Combined_HW), n)
kappa_bm_sth_result <- manual_kappa_with_details(table(data$STHs_Baermann, data$STHs_CombiNeged), n)
# Print results
print(kk_al_result)
$Kappa
[1] 0.9552651
$p_value
[1] 0
$P_o
[1] 0.978979
$P_e
[1] 0.5300977
$CI
[1] "95% CI: 0.923 to 0.987"
print(kappa_snf_al_result)
$Kappa
[1] 0.2362215
$p_value
[1] 9.444312e-06
$P_o
[1] 0.6906907
$P_e
[1] 0.5950275
$CI
[1] "95% CI: 0.132 to 0.341"
print(kappa_kk_ev_result)
$Kappa
[1] 0.5457026
$p_value
[1] 0
$P_o
[1] 0.975976
$P_e
[1] 0.9471183
$CI
[1] "95% CI: 0.456 to 0.636"
print(kappa_snf_ev_result)
$Kappa
[1] 0.9135738
$p_value
[1] 0
$P_o
[1] 0.993994
$P_e
[1] 0.9305071
$CI
[1] "95% CI: 0.87 to 0.957"
print(kappa_kk_tt_result)
$Kappa
[1] 0.9596999
$p_value
[1] 0
$P_o
[1] 0.993994
$P_e
[1] 0.8509681
$CI
[1] "95% CI: 0.929 to 0.99"
print(kappa_snf_tt_result)
$Kappa
[1] 0.6788337
$p_value
[1] 0
$P_o
[1] 0.960961
$P_e
[1] 0.878446
$CI
[1] "95% CI: 0.6 to 0.758"
print(kappa_kk_hw_result)
$Kappa
[1] 0.4547615
$p_value
[1] 0
$P_o
[1] 0.9069069
$P_e
[1] 0.8292617
$CI
[1] "95% CI: 0.359 to 0.551"
print(kappa_snf_hw_result)
$Kappa
[1] 0.7283604
$p_value
[1] 0
$P_o
[1] 0.9459459
$P_e
[1] 0.8010082
$CI
[1] "95% CI: 0.655 to 0.802"
print(kappa_kk_sths_result)
$Kappa
[1] 0.8388045
$p_value
[1] 0
$P_o
[1] 0.9189189
$P_e
[1] 0.4970015
$CI
[1] "95% CI: 0.78 to 0.897"
print(kappa_snf_sths_result)
$Kappa
[1] 0.39979
$p_value
[1] 1.998401e-15
$P_o
[1] 0.6906907
$P_e
[1] 0.4846648
$CI
[1] "95% CI: 0.301 to 0.498"
print(kappa_bm_hw_result)
$Kappa
[1] 0.6723516
$p_value
[1] 0
$P_o
[1] 0.9369369
$P_e
[1] 0.8075282
$CI
[1] "95% CI: 0.593 to 0.752"
print(kappa_bm_sth_result)
$Kappa
[1] 0.1235787
$p_value
[1] 0.023262
$P_o
[1] 0.5405405
$P_e
[1] 0.475755
$CI
[1] "95% CI: 0.017 to 0.23"
LS0tDQp0aXRsZTogIkV2YWx1YXRpb24gb2YgcGVyZm9ybWFuY2Ugb2YgRGlhZ25pb3N0aWMgVGVzdCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KYGBge3J9DQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcw0KbGlicmFyeShyZWFkeGwpICAjIEZvciByZWFkaW5nIEV4Y2VsIGZpbGVzDQpsaWJyYXJ5KGRwbHlyKSAgICMgRm9yIGRhdGEgbWFuaXB1bGF0aW9uDQpsaWJyYXJ5KGlycikgICAgICMgRm9yIEthcHBhIHN0YXRpc3RpYw0KbGlicmFyeSh3cml0ZXhsKQ0KDQojIENvdW50IFBvcy9OZWcgZm9yIGVhY2ggY29sdW1uDQpmcmVxX3RhYmxlIDwtIHNhcHBseShkYXRhWywgLTFdLCBmdW5jdGlvbih4KSB0YWJsZSh4KSkNCmZyZXFfZGYgPC0gYXMuZGF0YS5mcmFtZSh0KGZyZXFfdGFibGUpKQ0KZnJlcV9kZg0KDQojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBwcmV2YWxlbmNlIGFuZCBDSQ0KY2FsY3VsYXRlX3ByZXZhbGVuY2UgPC0gZnVuY3Rpb24odGVzdF9jb2x1bW4pIHsNCiAgcG9zaXRpdmVzIDwtIHN1bSh0ZXN0X2NvbHVtbiA9PSAiUG9zIikgICMgQ291bnQgdGhlIG51bWJlciBvZiBwb3NpdGl2ZXMNCiAgdG90YWwgPC0gbGVuZ3RoKHRlc3RfY29sdW1uKSAgICAgICAgICAgICMgVG90YWwgbnVtYmVyIG9mIHBhcnRpY2lwYW50cw0KICANCiAgcHJldmFsZW5jZSA8LSBwb3NpdGl2ZXMgLyB0b3RhbCAgICAgICAgIyBQcmV2YWxlbmNlDQogIA0KIyBDYWxjdWxhdGUgOTUlIENJIGZvciBwcmV2YWxlbmNlDQogIGNpIDwtIHByb3AudGVzdChwb3NpdGl2ZXMsIHRvdGFsLCBjb25mLmxldmVsID0gMC45NSkNCiAgDQogIHJldHVybihjKFByZXZhbGVuY2UgPSBwcmV2YWxlbmNlLCBDSV9Mb3dlciA9IGNpJGNvbmYuaW50WzFdLCBDSV9VcHBlciA9IGNpJGNvbmYuaW50WzJdKSkNCn0NCg0KIyBBcHBseSB0aGUgZnVuY3Rpb24gdG8gZWFjaCBkaWFnbm9zdGljIG1ldGhvZA0KcHJldmFsZW5jZV9jb21iaW5lZF9FViA8LSBjYWxjdWxhdGVfcHJldmFsZW5jZShkYXRhJENvbWJpbmVkX0VWKQ0KcHJldmFsZW5jZV9ra19FViA8LSBjYWxjdWxhdGVfcHJldmFsZW5jZShkYXRhJEtLX0VWKQ0KcHJldmFsZW5jZV9zbmZfRVYgPC0gY2FsY3VsYXRlX3ByZXZhbGVuY2UoZGF0YSRTTkZfRVYpDQoNCnByZXZhbGVuY2VfY29tYmluZWRfVFQgPC0gY2FsY3VsYXRlX3ByZXZhbGVuY2UoZGF0YSRDb21iaW5lZF9UVCkNCnByZXZhbGVuY2Vfa2tfVFQgPC0gY2FsY3VsYXRlX3ByZXZhbGVuY2UoZGF0YSRLS19UVCkNCnByZXZhbGVuY2Vfc25mX1RUIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKGRhdGEkU05GX1RUKQ0KDQpwcmV2YWxlbmNlX2NvbWJpbmVkX0FMIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKGRhdGEkQ29tYmluZWRfQUwpDQpwcmV2YWxlbmNlX2trX0FMIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKGRhdGEkS0tfQUwpDQpwcmV2YWxlbmNlX3NuZl9BTCA8LSBjYWxjdWxhdGVfcHJldmFsZW5jZShkYXRhJFNORl9BTCkNCg0KcHJldmFsZW5jZV9jb21iaW5lZF9IVyA8LSBjYWxjdWxhdGVfcHJldmFsZW5jZShkYXRhJENvbWJpbmVkX0hXKQ0KcHJldmFsZW5jZV9ra19IVyA8LSBjYWxjdWxhdGVfcHJldmFsZW5jZShkYXRhJEtLX0hXKQ0KcHJldmFsZW5jZV9zbmZfSFcgPC0gY2FsY3VsYXRlX3ByZXZhbGVuY2UoZGF0YSRTTkZfSFcpDQpwcmV2YWxlbmNlX2JhZXJtYW5uX0hXX1NHIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKGRhdGEkQmFlcm1hbm5fSFdfU0cpDQoNCnByZXZhbGVuY2VfY29tYmluZWRfU1RIcyA8LSBjYWxjdWxhdGVfcHJldmFsZW5jZShkYXRhJFNUSHNfQ29tYmlOZWdlZCkNCnByZXZhbGVuY2Vfa2tfU1RIcyA8LSBjYWxjdWxhdGVfcHJldmFsZW5jZShkYXRhJFNUSHNfS0spDQpwcmV2YWxlbmNlX3NuZl9TVEhzIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKGRhdGEkU1RIc19TTkYpDQpwcmV2YWxlbmNlX1NUSHNfYmFlcm1hbm4gPC0gY2FsY3VsYXRlX3ByZXZhbGVuY2UoZGF0YSRTVEhzX0JhZXJtYW5uKQ0KDQoNCnByZXZhbGVuY2VfdGFibGUgPC0gZGF0YS5mcmFtZSgNCiAgRGlhZ25vc3RpY19UZWNobmlxdWUgPSBjKA0KICAgICJDb21iaW5lZF9FViIsICJLS19FViIsICJTTkZfRVYiLA0KICAgICJDb21iaW5lZF9UVCIsICJLS19UVCIsICJTTkZfVFQiLA0KICAgICJDb21iaW5lZF9BTCIsICJLS19BTCIsICJTTkZfQUwiLA0KICAgICJDb21iaW5lZF9IVyIsICJLS19IVyIsICJTTkZfSFciLA0KICAgICJCYWVybWFubl9IV19TRyIsDQogICAgIkNvbWJpbmVkX1NUSHMiLCAiS0tfU1RIcyIsICJTTkZfU1RIcyIsICJTVEhzX0JhZXJtYW5uIg0KICApLA0KICBQcmV2YWxlbmNlID0gYygNCiAgICBwcmV2YWxlbmNlX2NvbWJpbmVkX0VWWzFdLCBwcmV2YWxlbmNlX2trX0VWWzFdLCBwcmV2YWxlbmNlX3NuZl9FVlsxXSwNCiAgICBwcmV2YWxlbmNlX2NvbWJpbmVkX1RUWzFdLCBwcmV2YWxlbmNlX2trX1RUWzFdLCBwcmV2YWxlbmNlX3NuZl9UVFsxXSwNCiAgICBwcmV2YWxlbmNlX2NvbWJpbmVkX0FMWzFdLCBwcmV2YWxlbmNlX2trX0FMWzFdLCBwcmV2YWxlbmNlX3NuZl9BTFsxXSwNCiAgICBwcmV2YWxlbmNlX2NvbWJpbmVkX0hXWzFdLCBwcmV2YWxlbmNlX2trX0hXWzFdLCBwcmV2YWxlbmNlX3NuZl9IV1sxXSwNCiAgICBwcmV2YWxlbmNlX2JhZXJtYW5uX0hXX1NHWzFdLA0KICAgIHByZXZhbGVuY2VfY29tYmluZWRfU1RIc1sxXSwgcHJldmFsZW5jZV9ra19TVEhzWzFdLCBwcmV2YWxlbmNlX3NuZl9TVEhzWzFdLA0KICAgIHByZXZhbGVuY2VfU1RIc19iYWVybWFublsxXQ0KICApLA0KICBDSV9Mb3dlciA9IGMoDQogICAgcHJldmFsZW5jZV9jb21iaW5lZF9FVlsyXSwgcHJldmFsZW5jZV9ra19FVlsyXSwgcHJldmFsZW5jZV9zbmZfRVZbMl0sDQogICAgcHJldmFsZW5jZV9jb21iaW5lZF9UVFsyXSwgcHJldmFsZW5jZV9ra19UVFsyXSwgcHJldmFsZW5jZV9zbmZfVFRbMl0sDQogICAgcHJldmFsZW5jZV9jb21iaW5lZF9BTFsyXSwgcHJldmFsZW5jZV9ra19BTFsyXSwgcHJldmFsZW5jZV9zbmZfQUxbMl0sDQogICAgcHJldmFsZW5jZV9jb21iaW5lZF9IV1syXSwgcHJldmFsZW5jZV9ra19IV1syXSwgcHJldmFsZW5jZV9zbmZfSFdbMl0sDQogICAgcHJldmFsZW5jZV9iYWVybWFubl9IV19TR1syXSwNCiAgICBwcmV2YWxlbmNlX2NvbWJpbmVkX1NUSHNbMl0sIHByZXZhbGVuY2Vfa2tfU1RIc1syXSwgcHJldmFsZW5jZV9zbmZfU1RIc1syXSwNCiAgICBwcmV2YWxlbmNlX1NUSHNfYmFlcm1hbm5bMl0NCiAgKSwNCiAgQ0lfVXBwZXIgPSBjKA0KICAgIHByZXZhbGVuY2VfY29tYmluZWRfRVZbM10sIHByZXZhbGVuY2Vfa2tfRVZbM10sIHByZXZhbGVuY2Vfc25mX0VWWzNdLA0KICAgIHByZXZhbGVuY2VfY29tYmluZWRfVFRbM10sIHByZXZhbGVuY2Vfa2tfVFRbM10sIHByZXZhbGVuY2Vfc25mX1RUWzNdLA0KICAgIHByZXZhbGVuY2VfY29tYmluZWRfQUxbM10sIHByZXZhbGVuY2Vfa2tfQUxbM10sIHByZXZhbGVuY2Vfc25mX0FMWzNdLA0KICAgIHByZXZhbGVuY2VfY29tYmluZWRfSFdbM10sIHByZXZhbGVuY2Vfa2tfSFdbM10sIHByZXZhbGVuY2Vfc25mX0hXWzNdLA0KICAgIHByZXZhbGVuY2VfYmFlcm1hbm5fSFdfU0dbM10sDQogICAgcHJldmFsZW5jZV9jb21iaW5lZF9TVEhzWzNdLCBwcmV2YWxlbmNlX2trX1NUSHNbM10sIHByZXZhbGVuY2Vfc25mX1NUSHNbM10sDQogICAgcHJldmFsZW5jZV9TVEhzX2JhZXJtYW5uWzNdDQogICkNCikNCg0KcHJpbnQocHJldmFsZW5jZV90YWJsZSkNCg0KDQojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBzZW5zaXRpdml0eSwgc3BlY2lmaWNpdHksIFBQViwgYW5kIE5QVg0KY2FsY3VsYXRlX21ldHJpY3MgPC0gZnVuY3Rpb24oY29uZl9tYXRyaXgpIHsNCiAgVFAgPC0gY29uZl9tYXRyaXhbMiwgMl0gICMgVHJ1ZSBQb3NpdGl2ZQ0KICBGUCA8LSBjb25mX21hdHJpeFsxLCAyXSAgIyBGYWxzZSBQb3NpdGl2ZQ0KICBUTiA8LSBjb25mX21hdHJpeFsxLCAxXSAgIyBUcnVlIE5lZ2F0aXZlDQogIEZOIDwtIGNvbmZfbWF0cml4WzIsIDFdICAjIEZhbHNlIE5lZ2F0aXZlDQogIA0KICAjIFNlbnNpdGl2aXR5ID0gVFAgLyAoVFAgKyBGTikNCiAgc2Vuc2l0aXZpdHkgPC0gVFAgLyAoVFAgKyBGTikNCiAgDQogICMgU3BlY2lmaWNpdHkgPSBUTiAvIChUTiArIEZQKQ0KICBzcGVjaWZpY2l0eSA8LSBUTiAvIChUTiArIEZQKQ0KICANCiAgIyBQUFYgPSBUUCAvIChUUCArIEZQKQ0KICBwcHYgPC0gVFAgLyAoVFAgKyBGUCkNCiAgDQogICMgTlBWID0gVE4gLyAoVE4gKyBGTikNCiAgbnB2IDwtIFROIC8gKFROICsgRk4pDQogIA0KICAjIENhbGN1bGF0ZSA5NSUgQ0kgZm9yIGVhY2ggbWV0cmljIHVzaW5nIHByb3AudGVzdA0KICBzZW5zaXRpdml0eV9jaSA8LSBwcm9wLnRlc3QoVFAsIFRQICsgRk4sIGNvbmYubGV2ZWwgPSAwLjk1KSRjb25mLmludA0KICBzcGVjaWZpY2l0eV9jaSA8LSBwcm9wLnRlc3QoVE4sIFROICsgRlAsIGNvbmYubGV2ZWwgPSAwLjk1KSRjb25mLmludA0KICBwcHZfY2kgPC0gcHJvcC50ZXN0KFRQLCBUUCArIEZQLCBjb25mLmxldmVsID0gMC45NSkkY29uZi5pbnQNCiAgbnB2X2NpIDwtIHByb3AudGVzdChUTiwgVE4gKyBGTiwgY29uZi5sZXZlbCA9IDAuOTUpJGNvbmYuaW50DQogIA0KICByZXR1cm4oZGF0YS5mcmFtZSgNCiAgICBTZW5zaXRpdml0eSA9IHJvdW5kKHNlbnNpdGl2aXR5ICogMTAwLCAyKSwNCiAgICBTZW5zaXRpdml0eV9Mb3dlcl9DSSA9IHJvdW5kKHNlbnNpdGl2aXR5X2NpWzFdICogMTAwLCAyKSwNCiAgICBTZW5zaXRpdml0eV9VcHBlcl9DSSA9IHJvdW5kKHNlbnNpdGl2aXR5X2NpWzJdICogMTAwLCAyKSwNCiAgICBTcGVjaWZpY2l0eSA9IHJvdW5kKHNwZWNpZmljaXR5ICogMTAwLCAyKSwNCiAgICBTcGVjaWZpY2l0eV9Mb3dlcl9DSSA9IHJvdW5kKHNwZWNpZmljaXR5X2NpWzFdICogMTAwLCAyKSwNCiAgICBTcGVjaWZpY2l0eV9VcHBlcl9DSSA9IHJvdW5kKHNwZWNpZmljaXR5X2NpWzJdICogMTAwLCAyKSwNCiAgICBQUFYgPSByb3VuZChwcHYgKiAxMDAsIDIpLA0KICAgIFBQVl9Mb3dlcl9DSSA9IHJvdW5kKHBwdl9jaVsxXSAqIDEwMCwgMiksDQogICAgUFBWX1VwcGVyX0NJID0gcm91bmQocHB2X2NpWzJdICogMTAwLCAyKSwNCiAgICBOUFYgPSByb3VuZChucHYgKiAxMDAsIDIpLA0KICAgIE5QVl9Mb3dlcl9DSSA9IHJvdW5kKG5wdl9jaVsxXSAqIDEwMCwgMiksDQogICAgTlBWX1VwcGVyX0NJID0gcm91bmQobnB2X2NpWzJdICogMTAwLCAyKQ0KICApKQ0KfQ0KDQojIEdvbGQgc3RhbmRhcmRzIGZvciBlYWNoIHNwZWNpZXMNCmdvbGRfc3RhbmRhcmRzIDwtIGxpc3QoDQogIEFMID0gIkNvbWJpbmVkX0FMIiwgICAgICAgICMgQS4gbHVtYnJpY29pZGVzIHVzZXMgQ29tYmluZWRfQUwgYXMgdGhlIGdvbGQgc3RhbmRhcmQNCiAgSFcgPSAiQ29tYmluZWRfSFciLCAgICAgICAgIyBIb29rd29ybSB1c2VzIENvbWJpbmVkX0hXIGFzIHRoZSBnb2xkIHN0YW5kYXJkDQogIFRUID0gIkNvbWJpbmVkX1RUIiwgICAgICAgICMgVC4gdHJpY2hpdXJhIHVzZXMgQ29tYmluZWRfVFQgYXMgdGhlIGdvbGQgc3RhbmRhcmQNCiAgRVYgPSAiQ29tYmluZWRfRVYiLCAgICAgICAgIyBFLiB2ZXJtaWN1bGFyaXMgdXNlcyBDb21iaW5lZF9FViBhcyB0aGUgZ29sZCBzdGFuZGFyZA0KICBTVEhzID0gIlNUSHNfQ29tYmlOZWdlZCIgICAjIFNUSHMgKGFsbCBzcGVjaWVzIGNvbWJpbmVkKSB1c2VzIFNUSHNfQ29tYmlOZWdlZCBhcyB0aGUgZ29sZCBzdGFuZGFyZA0KKQ0KDQojIExpc3Qgb2YgZGlhZ25vc3RpYyBtZXRob2RzICh5b3VyIGFjdHVhbCBkaWFnbm9zdGljIHRlc3QgY29sdW1ucyBpbiB5b3VyIGRhdGFzZXQpDQpkaWFnbm9zdGljX21ldGhvZHMgPC0gYygiU1RIc19LSyIsICJLS19FViIsICJLS19UVCIsICJLS19BTCIsICJLS19IVyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIlNUSHNfU05GIiwgIlNORl9FViIsICJTTkZfVFQiLCAiU05GX0FMIiwgIlNORl9IVyIsDQogICAgICAgICAgICAgICAgICAgICAgICAiU1RIc19CYWVybWFubiIsICJCYWVybWFubl9IV19TRyIpDQoNCiMgQ3JlYXRlIGFuIGVtcHR5IGRhdGEgZnJhbWUgdG8gc3RvcmUgcmVzdWx0cw0KcmVzdWx0c190YWJsZSA8LSBkYXRhLmZyYW1lKCkNCg0KIyBMb29wIHRocm91Z2ggZWFjaCBkaWFnbm9zdGljIG1ldGhvZCBhbmQgY2FsY3VsYXRlIG1ldHJpY3MNCmZvciAodGVzdCBpbiBkaWFnbm9zdGljX21ldGhvZHMpIHsNCiAgDQogICMgR2V0IHRoZSBzcGVjaWVzIGNvcnJlc3BvbmRpbmcgdG8gZWFjaCB0ZXN0IG1ldGhvZA0KICBpZiAoZ3JlcGwoIktLXyIsIHRlc3QpKSB7DQogICAgc3BlY2llcyA8LSBzdWIoIktLXyIsICIiLCB0ZXN0KSAgIyBFeHRyYWN0IHRoZSBzcGVjaWVzIG5hbWUgZnJvbSB0aGUgdGVzdCAoZS5nLiwgS0tfQUwgLT4gQUwpDQogIH0gZWxzZSBpZiAoZ3JlcGwoIlNORl8iLCB0ZXN0KSkgew0KICAgIHNwZWNpZXMgPC0gc3ViKCJTTkZfIiwgIiIsIHRlc3QpICMgRXh0cmFjdCB0aGUgc3BlY2llcyBuYW1lIGZyb20gdGhlIHRlc3QgKGUuZy4sIFNORl9FViAtPiBFVikNCiAgfSBlbHNlIGlmIChncmVwbCgiQmFlcm1hbm4iLCB0ZXN0KSkgew0KICAgIHNwZWNpZXMgPC0gIlNUSHMiICAjIEJhZXJtYW5uIG1ldGhvZHMgd2lsbCB1c2UgU1RIcyBjb21iaW5lZCBkYXRhDQogIH0gZWxzZSB7DQogICAgc3BlY2llcyA8LSAiU1RIcyIgICMgT3RoZXIgdGVzdHMgbGlrZSBTVEhzX0tLIHVzZSBjb21iaW5lZCBkYXRhDQogIH0NCiAgDQogICMgRGVmaW5lIHRoZSBnb2xkIHN0YW5kYXJkIGZvciB0aGlzIHNwZWNpZXMNCiAgZ29sZF9zdGFuZGFyZCA8LSBnb2xkX3N0YW5kYXJkc1tbc3BlY2llc11dDQogIA0KICAjIENyZWF0ZSBjb25mdXNpb24gbWF0cml4IGZvciBlYWNoIHRlc3QgdnMgdGhlIGdvbGQgc3RhbmRhcmQgKHNwZWNpZXMtc3BlY2lmaWMgZ29sZCBzdGFuZGFyZCkNCiAgY29uZl9tYXRyaXggPC0gdGFibGUoZGF0YVtbZ29sZF9zdGFuZGFyZF1dLCBkYXRhW1t0ZXN0XV0pDQogIA0KICAjIENhbGN1bGF0ZSBzZW5zaXRpdml0eSwgc3BlY2lmaWNpdHksIFBQViwgYW5kIE5QViBmb3IgZWFjaCBtZXRob2QNCiAgbWV0cmljcyA8LSBjYWxjdWxhdGVfbWV0cmljcyhjb25mX21hdHJpeCkNCiAgDQogICMgQWRkIHJlc3VsdHMgdG8gdGhlIHJlc3VsdHMgdGFibGUNCiAgcmVzdWx0c190YWJsZSA8LSByYmluZChyZXN1bHRzX3RhYmxlLCBkYXRhLmZyYW1lKA0KICAgIERpYWdub3N0aWNfVGVjaG5pcXVlID0gdGVzdCwNCiAgICBTcGVjaWVzID0gc3BlY2llcywNCiAgICBTZW5zaXRpdml0eSA9IG1ldHJpY3MkU2Vuc2l0aXZpdHksDQogICAgU2Vuc2l0aXZpdHlfTG93ZXJfQ0kgPSBtZXRyaWNzJFNlbnNpdGl2aXR5X0xvd2VyX0NJLA0KICAgIFNlbnNpdGl2aXR5X1VwcGVyX0NJID0gbWV0cmljcyRTZW5zaXRpdml0eV9VcHBlcl9DSSwNCiAgICBTcGVjaWZpY2l0eSA9IG1ldHJpY3MkU3BlY2lmaWNpdHksDQogICAgU3BlY2lmaWNpdHlfTG93ZXJfQ0kgPSBtZXRyaWNzJFNwZWNpZmljaXR5X0xvd2VyX0NJLA0KICAgIFNwZWNpZmljaXR5X1VwcGVyX0NJID0gbWV0cmljcyRTcGVjaWZpY2l0eV9VcHBlcl9DSSwNCiAgICBQUFYgPSBtZXRyaWNzJFBQViwNCiAgICBQUFZfTG93ZXJfQ0kgPSBtZXRyaWNzJFBQVl9Mb3dlcl9DSSwNCiAgICBQUFZfVXBwZXJfQ0kgPSBtZXRyaWNzJFBQVl9VcHBlcl9DSSwNCiAgICBOUFYgPSBtZXRyaWNzJE5QViwNCiAgICBOUFZfTG93ZXJfQ0kgPSBtZXRyaWNzJE5QVl9Mb3dlcl9DSSwNCiAgICBOUFZfVXBwZXJfQ0kgPSBtZXRyaWNzJE5QVl9VcHBlcl9DSQ0KICApKQ0KfQ0KDQojIFByaW50IHRoZSByZXN1bHRzIHRhYmxlDQpwcmludChyZXN1bHRzX3RhYmxlKQ0KDQoNCiMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIGZyZXF1ZW5jaWVzIG9mIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBjYXNlcyBmb3IgZWFjaCBkaWFnbm9zdGljIG1ldGhvZA0KY2FsY3VsYXRlX2ZyZXF1ZW5jaWVzIDwtIGZ1bmN0aW9uKHRlc3RfY29sdW1uLCBzcGVjaWVzX2NvbHVtbikgew0KICAjIENyZWF0ZSBhIGNvbnRpbmdlbmN5IHRhYmxlIGZvciB0aGUgc3BlY2llcyBhbmQgdGhlIGRpYWdub3N0aWMgbWV0aG9kDQogIGZyZXFfdGFibGUgPC0gdGFibGUoc3BlY2llc19jb2x1bW4sIHRlc3RfY29sdW1uKQ0KICANCiAgcmV0dXJuKGZyZXFfdGFibGUpDQp9DQoNCiMgQ3JlYXRlIGFuIGVtcHR5IGRhdGEgZnJhbWUgdG8gc3RvcmUgcmVzdWx0cw0KZnJlcXVlbmNpZXNfdGFibGUgPC0gZGF0YS5mcmFtZSgpDQoNCiMgTGlzdCBvZiBkaWFnbm9zdGljIG1ldGhvZHMgKHlvdXIgYWN0dWFsIGRpYWdub3N0aWMgdGVzdCBjb2x1bW5zIGluIHlvdXIgZGF0YXNldCkNCmRpYWdub3N0aWNfbWV0aG9kcyA8LSBjKCJTVEhzX0tLIiwgIktLX0VWIiwgIktLX1RUIiwgIktLX0FMIiwgIktLX0hXIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAiU1RIc19TTkYiLCAiU05GX0VWIiwgIlNORl9UVCIsICJTTkZfQUwiLCAiU05GX0hXIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJTVEhzX0JhZXJtYW5uIiwgIkJhZXJtYW5uX0hXX1NHIikNCg0KIyBMb29wIHRocm91Z2ggZWFjaCBkaWFnbm9zdGljIG1ldGhvZCBhbmQgY2FsY3VsYXRlIGZyZXF1ZW5jaWVzDQpmb3IgKHRlc3QgaW4gZGlhZ25vc3RpY19tZXRob2RzKSB7DQogIA0KICAjIEdldCB0aGUgc3BlY2llcyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggdGVzdCBtZXRob2QNCiAgaWYgKGdyZXBsKCJLS18iLCB0ZXN0KSkgew0KICAgIHNwZWNpZXMgPC0gc3ViKCJLS18iLCAiIiwgdGVzdCkgICMgRXh0cmFjdCB0aGUgc3BlY2llcyBuYW1lIGZyb20gdGhlIHRlc3QgKGUuZy4sIEtLX0FMIC0+IEFMKQ0KICB9IGVsc2UgaWYgKGdyZXBsKCJTTkZfIiwgdGVzdCkpIHsNCiAgICBzcGVjaWVzIDwtIHN1YigiU05GXyIsICIiLCB0ZXN0KSAjIEV4dHJhY3QgdGhlIHNwZWNpZXMgbmFtZSBmcm9tIHRoZSB0ZXN0IChlLmcuLCBTTkZfRVYgLT4gRVYpDQogIH0gZWxzZSBpZiAoZ3JlcGwoIkJhZXJtYW5uIiwgdGVzdCkpIHsNCiAgICBzcGVjaWVzIDwtICJTVEhzIiAgIyBCYWVybWFubiBtZXRob2RzIHdpbGwgdXNlIFNUSHMgY29tYmluZWQgZGF0YQ0KICB9IGVsc2Ugew0KICAgIHNwZWNpZXMgPC0gIlNUSHMiICAjIE90aGVyIHRlc3RzIGxpa2UgU1RIc19LSyB1c2UgY29tYmluZWQgZGF0YQ0KICB9DQogIA0KICAjIERlZmluZSB0aGUgZ29sZCBzdGFuZGFyZCBmb3IgdGhpcyBzcGVjaWVzDQogIGdvbGRfc3RhbmRhcmQgPC0gZ29sZF9zdGFuZGFyZHNbW3NwZWNpZXNdXQ0KICANCiAgIyBDYWxjdWxhdGUgZnJlcXVlbmNpZXMgZm9yIGVhY2ggZGlhZ25vc3RpYyBtZXRob2QgYW5kIHNwZWNpZXMNCiAgZnJlcV90YWJsZSA8LSBjYWxjdWxhdGVfZnJlcXVlbmNpZXMoZGF0YVtbdGVzdF1dLCBkYXRhW1tnb2xkX3N0YW5kYXJkXV0pDQogIA0KICAjIEFkZCB0aGUgZnJlcXVlbmNpZXMgdGFibGUgdG8gdGhlIHJlc3VsdHMNCiAgZnJlcXVlbmNpZXNfdGFibGUgPC0gcmJpbmQoZnJlcXVlbmNpZXNfdGFibGUsIGRhdGEuZnJhbWUoDQogICAgRGlhZ25vc3RpY19UZWNobmlxdWUgPSB0ZXN0LA0KICAgIFNwZWNpZXMgPSBzcGVjaWVzLA0KICAgIFBvc2l0aXZlcyA9IGZyZXFfdGFibGVbIlBvcyIsICJQb3MiXSwgICMgUG9zaXRpdmUgY2FzZXMNCiAgICBOZWdhdGl2ZXMgPSBmcmVxX3RhYmxlWyJOZWciLCAiTmVnIl0gICAjIE5lZ2F0aXZlIGNhc2VzDQogICkpDQp9DQoNCiMgUHJpbnQgdGhlIGZyZXF1ZW5jaWVzIHRhYmxlDQpwcmludChmcmVxdWVuY2llc190YWJsZSkNCg0KDQojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBwcmV2YWxlbmNlIGFuZCA5NSUgQ0kNCmNhbGN1bGF0ZV9wcmV2YWxlbmNlIDwtIGZ1bmN0aW9uKHRlc3RfY29sdW1uLCB0b3RhbF9wYXJ0aWNpcGFudHMpIHsNCiAgcG9zaXRpdmVzIDwtIHN1bSh0ZXN0X2NvbHVtbiA9PSAiUG9zIikgICMgQ291bnQgdGhlIG51bWJlciBvZiBwb3NpdGl2ZXMNCiAgcHJldmFsZW5jZSA8LSBwb3NpdGl2ZXMgLyB0b3RhbF9wYXJ0aWNpcGFudHMgKiAxMDAgICMgUHJldmFsZW5jZSBpbiBwZXJjZW50YWdlDQogIA0KICAjIENhbGN1bGF0ZSA5NSUgQ0kgZm9yIHByZXZhbGVuY2UgdXNpbmcgcHJvcC50ZXN0DQogIGNpIDwtIHByb3AudGVzdChwb3NpdGl2ZXMsIHRvdGFsX3BhcnRpY2lwYW50cywgY29uZi5sZXZlbCA9IDAuOTUpDQogIA0KICByZXR1cm4oYyhQcmV2YWxlbmNlID0gcHJldmFsZW5jZSwgQ0lfTG93ZXIgPSBjaSRjb25mLmludFsxXSAqIDEwMCwgQ0lfVXBwZXIgPSBjaSRjb25mLmludFsyXSAqIDEwMCkpDQp9DQoNCiMgVG90YWwgcGFydGljaXBhbnRzDQp0b3RhbF9wYXJ0aWNpcGFudHMgPC0gMzMzDQoNCiMgQXNzdW1pbmcgJ2RhdGEnIGNvbnRhaW5zIHlvdXIgZGF0YXNldCBhbmQgIktLIiBhbmQgIlNORiIgYXJlIHRoZSByZXNwZWN0aXZlIGNvbHVtbnMNCiMgUHJldmFsZW5jZSBmb3IgS0sgbWV0aG9kDQpwcmV2YWxlbmNlX0tLIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKGRhdGEkU1RIc19LSywgdG90YWxfcGFydGljaXBhbnRzKQ0KDQojIFByZXZhbGVuY2UgZm9yIFNORiBtZXRob2QNCnByZXZhbGVuY2VfU05GIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKGRhdGEkU1RIc19TTkYsIHRvdGFsX3BhcnRpY2lwYW50cykNCg0KIyBQcmV2YWxlbmNlIGZvciBjb21iaW5lZCBLSyBhbmQgU05GIG1ldGhvZCAoaS5lLiwgYW55IHBvc2l0aXZlIHJlc3VsdCBpbiBlaXRoZXIgS0sgb3IgU05GKQ0KY29tYmluZWRfS0tfU05GIDwtIGNhbGN1bGF0ZV9wcmV2YWxlbmNlKChkYXRhJFNUSHNfS0sgPT0gIlBvcyIgfCBkYXRhJFNUSHNfU05GID09ICJQb3MiKSwgdG90YWxfcGFydGljaXBhbnRzKQ0KDQojIFByZXBhcmUgdGhlIHJlc3VsdHMgdGFibGUNCnJlc3VsdHMgPC0gZGF0YS5mcmFtZSgNCiAgTWV0aG9kID0gYygiS0siLCAiU05GIiwgIktLICsgU05GIiksDQogIFRvdGFsX0V4YW1pbmVkID0gcmVwKHRvdGFsX3BhcnRpY2lwYW50cywgMyksDQogIFBvc2l0aXZlcyA9IGMoc3VtKGRhdGEkU1RIc19LSyA9PSAiUG9zIiksIHN1bShkYXRhJFNUSHNfU05GID09ICJQb3MiKSwgc3VtKGRhdGEkU1RIc19LSyA9PSAiUG9zIiB8IGRhdGEkU1RIc19TTkYgPT0gIlBvcyIpKSwNCiAgUHJldmFsZW5jZSA9IGMocHJldmFsZW5jZV9LS1sxXSwgcHJldmFsZW5jZV9TTkZbMV0sIGNvbWJpbmVkX0tLX1NORlsxXSksDQogIENJX0xvd2VyID0gYyhwcmV2YWxlbmNlX0tLWzJdLCBwcmV2YWxlbmNlX1NORlsyXSwgY29tYmluZWRfS0tfU05GWzJdKSwNCiAgQ0lfVXBwZXIgPSBjKHByZXZhbGVuY2VfS0tbM10sIHByZXZhbGVuY2VfU05GWzNdLCBjb21iaW5lZF9LS19TTkZbM10pDQopDQoNCiMgUHJpbnQgdGhlIHJlc3VsdHMNCnByaW50KHJlc3VsdHMpDQoNCnBvc2l0aXZlcyA8LSAxNzYNCnRvdGFsX3BhcnRpY2lwYW50cyA8LSAzMzMNCiMgVXNlIHByb3AudGVzdCB0byBjYWxjdWxhdGUgdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgcHJvcG9ydGlvbiBvZiBwb3NpdGl2ZXMNCmNpX3Jlc3VsdCA8LSBwcm9wLnRlc3QocG9zaXRpdmVzLCB0b3RhbF9wYXJ0aWNpcGFudHMsIGNvbmYubGV2ZWwgPSAwLjk1KQ0KIyBQcmludCB0aGUgcmVzdWx0DQpjaV9yZXN1bHQkY29uZi5pbnQNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgbWFudWFsIENvaGVuJ3MgS2FwcGENCm1hbnVhbF9rYXBwYSA8LSBmdW5jdGlvbihjb25mX21hdHJpeCkgew0KICBUUCA8LSBjb25mX21hdHJpeFsyLCAyXSAgIyBUcnVlIFBvc2l0aXZlcw0KICBGUCA8LSBjb25mX21hdHJpeFsxLCAyXSAgIyBGYWxzZSBQb3NpdGl2ZXMNCiAgVE4gPC0gY29uZl9tYXRyaXhbMSwgMV0gICMgVHJ1ZSBOZWdhdGl2ZXMNCiAgRk4gPC0gY29uZl9tYXRyaXhbMiwgMV0gICMgRmFsc2UgTmVnYXRpdmVzDQogIA0KICBQX28gPC0gKFRQICsgVE4pIC8gc3VtKGNvbmZfbWF0cml4KSAgIyBPYnNlcnZlZCBBZ3JlZW1lbnQNCiAgUF9lIDwtICgoVFAgKyBGUCkgLyBzdW0oY29uZl9tYXRyaXgpKSAqICgoVFAgKyBGTikgLyBzdW0oY29uZl9tYXRyaXgpKSArDQogICAgKChUTiArIEZOKSAvIHN1bShjb25mX21hdHJpeCkpICogKChUTiArIEZQKSAvIHN1bShjb25mX21hdHJpeCkpICAjIEV4cGVjdGVkIEFncmVlbWVudA0KICANCiAga2FwcGEgPC0gKFBfbyAtIFBfZSkgLyAoMSAtIFBfZSkNCiAgcmV0dXJuKGthcHBhKQ0KfQ0KIyBFeGFtcGxlIGNvbmZ1c2lvbiBtYXRyaXggZm9yIEtLX0FMIHZzIENvbWJpbmVkX0FMDQpra19hbF90YWJsZSA8LSB0YWJsZShkYXRhJEtLX0FMLCBkYXRhJENvbWJpbmVkX0FMKQ0KIyBDYWxjdWxhdGUgbWFudWFsIEthcHBhIGZvciBlYWNoIGNvbXBhcmlzb24NCmthcHBhX2trX2FsIDwtIG1hbnVhbF9rYXBwYShra19hbF90YWJsZSkNCmthcHBhX2trX2FsDQoNCg0KI0NhbGN1bGF0ZSBmb3Igc25mX2FsLGtrX2V2LHNuZl9ldg0Ka2FwcGFfc25mX2FsIDwtIG1hbnVhbF9rYXBwYSh0YWJsZShkYXRhJFNORl9BTCwgZGF0YSRDb21iaW5lZF9BTCkpDQprYXBwYV9ra19ldiA8LSBtYW51YWxfa2FwcGEodGFibGUoZGF0YSRLS19FViwgZGF0YSRDb21iaW5lZF9FVikpDQprYXBwYV9zbmZfZXYgPC0gbWFudWFsX2thcHBhKHRhYmxlKGRhdGEkU05GX0VWLCBkYXRhJENvbWJpbmVkX0VWKSkNCmthcHBhX2trX3R0IDwtIG1hbnVhbF9rYXBwYSh0YWJsZShkYXRhJEtLX1RULCBkYXRhJENvbWJpbmVkX1RUKSkNCmthcHBhX3NuZl90dCA8LSBtYW51YWxfa2FwcGEodGFibGUoZGF0YSRTTkZfVFQsIGRhdGEkQ29tYmluZWRfVFQpKQ0Ka2FwcGFfa2tfaHcgPC0gbWFudWFsX2thcHBhKHRhYmxlKGRhdGEkS0tfSFcsIGRhdGEkQ29tYmluZWRfSFcpKQ0Ka2FwcGFfc25mX2h3IDwtIG1hbnVhbF9rYXBwYSh0YWJsZShkYXRhJFNORl9IVywgZGF0YSRDb21iaW5lZF9IVykpDQoNCmthcHBhX2trX1NUSHMgPC0gbWFudWFsX2thcHBhKHRhYmxlKGRhdGEkU1RIc19LSywgZGF0YSRTVEhzX0NvbWJpTmVnZWQpKQ0Ka2FwcGFfc25mX1NUSHMgPC0gbWFudWFsX2thcHBhKHRhYmxlKGRhdGEkU1RIc19TTkYsIGRhdGEkU1RIc19Db21iaU5lZ2VkKSkNCg0Ka2FwcGFfYm1faHcgPC0gbWFudWFsX2thcHBhKHRhYmxlKGRhdGEkQmFlcm1hbm5fSFdfU0csIGRhdGEkQ29tYmluZWRfSFcpKQ0Ka2FwcGFfYm1fU1RIIDwtIG1hbnVhbF9rYXBwYSh0YWJsZShkYXRhJFNUSHNfQmFlcm1hbm4sIGRhdGEkU1RIc19Db21iaU5lZ2VkKSkNCg0KDQoNCnByaW50KGthcHBhX3NuZl9hbCkNCnByaW50KGthcHBhX2trX2V2KQ0KcHJpbnQoa2FwcGFfc25mX2V2KQ0KcHJpbnQoa2FwcGFfa2tfdHQpDQpwcmludChrYXBwYV9zbmZfdHQpDQpwcmludChrYXBwYV9ra19odykNCnByaW50KGthcHBhX3NuZl9odykNCnByaW50KGthcHBhX2trX1NUSHMpDQpwcmludChrYXBwYV9zbmZfU1RIcykNCnByaW50KGthcHBhX2JtX2h3KQ0KcHJpbnQoa2FwcGFfYm1fU1RIKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgbWFudWFsIENvaGVuJ3MgS2FwcGEsIHAtdmFsdWUsIDk1JSBDSSwgUF9vLCBhbmQgUF9lDQptYW51YWxfa2FwcGFfd2l0aF9kZXRhaWxzIDwtIGZ1bmN0aW9uKGNvbmZfbWF0cml4LCBuKSB7DQogIFRQIDwtIGNvbmZfbWF0cml4WzIsIDJdICAjIFRydWUgUG9zaXRpdmVzDQogIEZQIDwtIGNvbmZfbWF0cml4WzEsIDJdICAjIEZhbHNlIFBvc2l0aXZlcw0KICBUTiA8LSBjb25mX21hdHJpeFsxLCAxXSAgIyBUcnVlIE5lZ2F0aXZlcw0KICBGTiA8LSBjb25mX21hdHJpeFsyLCAxXSAgIyBGYWxzZSBOZWdhdGl2ZXMNCiAgDQogICMgQ2FsY3VsYXRlIE9ic2VydmVkIEFncmVlbWVudCAoUF9vKQ0KICBQX28gPC0gKFRQICsgVE4pIC8gc3VtKGNvbmZfbWF0cml4KQ0KICANCiAgIyBDYWxjdWxhdGUgRXhwZWN0ZWQgQWdyZWVtZW50IChQX2UpDQogIFBfZSA8LSAoKFRQICsgRlApIC8gc3VtKGNvbmZfbWF0cml4KSkgKiAoKFRQICsgRk4pIC8gc3VtKGNvbmZfbWF0cml4KSkgKw0KICAgICgoVE4gKyBGTikgLyBzdW0oY29uZl9tYXRyaXgpKSAqICgoVE4gKyBGUCkgLyBzdW0oY29uZl9tYXRyaXgpKQ0KICANCiAgIyBDYWxjdWxhdGUgQ29oZW4ncyBLYXBwYQ0KICBrYXBwYSA8LSAoUF9vIC0gUF9lKSAvICgxIC0gUF9lKQ0KICANCiAgIyBDYWxjdWxhdGUgdGhlIHN0YW5kYXJkIGVycm9yIChTRSkgb2YgQ29oZW4ncyBLYXBwYQ0KICBzZV9rYXBwYSA8LSBzcXJ0KCgxIC0ga2FwcGFeMikgLyAobiAtIDEpKQ0KICANCiAgIyBDYWxjdWxhdGUgdGhlIHotc2NvcmUgZm9yIENvaGVuJ3MgS2FwcGENCiAgeiA8LSBrYXBwYSAvIHNlX2thcHBhDQogIA0KICAjIENhbGN1bGF0ZSB0aGUgcC12YWx1ZSB1c2luZyB0aGUgei1zY29yZQ0KICBwX3ZhbHVlIDwtIDIgKiAoMSAtIHBub3JtKGFicyh6KSkpICAjIFR3by10YWlsZWQgcC12YWx1ZQ0KICANCiAgIyBDYWxjdWxhdGUgdGhlIDk1JSBDb25maWRlbmNlIEludGVydmFsIGZvciBDb2hlbidzIEthcHBhDQogIGxvd2VyX2NpIDwtIGthcHBhIC0gMS45NiAqIHNlX2thcHBhDQogIHVwcGVyX2NpIDwtIGthcHBhICsgMS45NiAqIHNlX2thcHBhDQogIA0KICAjIEZvcm1hdCB0aGUgOTUlIENJIGluIHRoZSByZXF1aXJlZCBzdHlsZQ0KICBjaV9zdHIgPC0gcGFzdGUoIjk1JSBDSTogIiwgcm91bmQobG93ZXJfY2ksIDMpLCAiIHRvICIsIHJvdW5kKHVwcGVyX2NpLCAzKSkNCiAgDQogICMgUmV0dXJuIHRoZSByZXN1bHRzDQogIHJldHVybihsaXN0KEthcHBhID0ga2FwcGEsIHBfdmFsdWUgPSBwX3ZhbHVlLCBQX28gPSBQX28sIFBfZSA9IFBfZSwgQ0kgPSBjaV9zdHIpKQ0KfQ0KDQojIEV4YW1wbGUgZm9yIEtLX0FMIHZzIENvbWJpbmVkX0FMIChjb25mdXNpb24gbWF0cml4IGFscmVhZHkgZ2l2ZW4pDQpra19hbF90YWJsZSA8LSB0YWJsZShkYXRhJEtLX0FMLCBkYXRhJENvbWJpbmVkX0FMKQ0KDQojIFRvdGFsIG51bWJlciBvZiBzdWJqZWN0cyAocmVwbGFjZSB3aXRoIHlvdXIgYWN0dWFsIG4pDQpuIDwtIHN1bShra19hbF90YWJsZSkgICMgVG90YWwgbnVtYmVyIG9mIHN1YmplY3RzDQoNCiMgQ2FsY3VsYXRlIG1hbnVhbCBLYXBwYSwgcC12YWx1ZSwgOTUlIENJLCBQX28sIGFuZCBQX2UNCmtrX2FsX3Jlc3VsdCA8LSBtYW51YWxfa2FwcGFfd2l0aF9kZXRhaWxzKGtrX2FsX3RhYmxlLCBuKQ0KDQojIFByaW50IEthcHBhLCBwLXZhbHVlLCBQX28sIFBfZSwgYW5kIGZvcm1hdHRlZCA5NSUgQ0kNCnByaW50KHBhc3RlKCJLYXBwYTogIiwgcm91bmQoa2tfYWxfcmVzdWx0JEthcHBhLCAzKSkpDQpwcmludChwYXN0ZSgicC12YWx1ZTogIiwgcm91bmQoa2tfYWxfcmVzdWx0JHBfdmFsdWUsIDUpKSkNCnByaW50KHBhc3RlKCJQX28gKE9ic2VydmVkIEFncmVlbWVudCk6ICIsIHJvdW5kKGtrX2FsX3Jlc3VsdCRQX28sIDMpKSkNCnByaW50KHBhc3RlKCJQX2UgKEV4cGVjdGVkIEFncmVlbWVudCk6ICIsIHJvdW5kKGtrX2FsX3Jlc3VsdCRQX2UsIDMpKSkNCnByaW50KGtrX2FsX3Jlc3VsdCRDSSkNCg0KIyBSZXBlYXQgZm9yIG90aGVyIGNvbXBhcmlzb25zDQprYXBwYV9zbmZfYWxfcmVzdWx0IDwtIG1hbnVhbF9rYXBwYV93aXRoX2RldGFpbHModGFibGUoZGF0YSRTTkZfQUwsIGRhdGEkQ29tYmluZWRfQUwpLCBuKQ0Ka2FwcGFfa2tfZXZfcmVzdWx0IDwtIG1hbnVhbF9rYXBwYV93aXRoX2RldGFpbHModGFibGUoZGF0YSRLS19FViwgZGF0YSRDb21iaW5lZF9FViksIG4pDQprYXBwYV9zbmZfZXZfcmVzdWx0IDwtIG1hbnVhbF9rYXBwYV93aXRoX2RldGFpbHModGFibGUoZGF0YSRTTkZfRVYsIGRhdGEkQ29tYmluZWRfRVYpLCBuKQ0Ka2FwcGFfa2tfdHRfcmVzdWx0IDwtIG1hbnVhbF9rYXBwYV93aXRoX2RldGFpbHModGFibGUoZGF0YSRLS19UVCwgZGF0YSRDb21iaW5lZF9UVCksIG4pDQprYXBwYV9zbmZfdHRfcmVzdWx0IDwtIG1hbnVhbF9rYXBwYV93aXRoX2RldGFpbHModGFibGUoZGF0YSRTTkZfVFQsIGRhdGEkQ29tYmluZWRfVFQpLCBuKQ0Ka2FwcGFfa2tfaHdfcmVzdWx0IDwtIG1hbnVhbF9rYXBwYV93aXRoX2RldGFpbHModGFibGUoZGF0YSRLS19IVywgZGF0YSRDb21iaW5lZF9IVyksIG4pDQprYXBwYV9zbmZfaHdfcmVzdWx0IDwtIG1hbnVhbF9rYXBwYV93aXRoX2RldGFpbHModGFibGUoZGF0YSRTTkZfSFcsIGRhdGEkQ29tYmluZWRfSFcpLCBuKQ0Ka2FwcGFfa2tfc3Roc19yZXN1bHQgPC0gbWFudWFsX2thcHBhX3dpdGhfZGV0YWlscyh0YWJsZShkYXRhJFNUSHNfS0ssIGRhdGEkU1RIc19Db21iaU5lZ2VkKSwgbikNCmthcHBhX3NuZl9zdGhzX3Jlc3VsdCA8LSBtYW51YWxfa2FwcGFfd2l0aF9kZXRhaWxzKHRhYmxlKGRhdGEkU1RIc19TTkYsIGRhdGEkU1RIc19Db21iaU5lZ2VkKSwgbikNCmthcHBhX2JtX2h3X3Jlc3VsdCA8LSBtYW51YWxfa2FwcGFfd2l0aF9kZXRhaWxzKHRhYmxlKGRhdGEkQmFlcm1hbm5fSFdfU0csIGRhdGEkQ29tYmluZWRfSFcpLCBuKQ0Ka2FwcGFfYm1fc3RoX3Jlc3VsdCA8LSBtYW51YWxfa2FwcGFfd2l0aF9kZXRhaWxzKHRhYmxlKGRhdGEkU1RIc19CYWVybWFubiwgZGF0YSRTVEhzX0NvbWJpTmVnZWQpLCBuKQ0KDQojIFByaW50IHJlc3VsdHMNCnByaW50KGtrX2FsX3Jlc3VsdCkNCnByaW50KGthcHBhX3NuZl9hbF9yZXN1bHQpDQpwcmludChrYXBwYV9ra19ldl9yZXN1bHQpDQpwcmludChrYXBwYV9zbmZfZXZfcmVzdWx0KQ0KcHJpbnQoa2FwcGFfa2tfdHRfcmVzdWx0KQ0KcHJpbnQoa2FwcGFfc25mX3R0X3Jlc3VsdCkNCnByaW50KGthcHBhX2trX2h3X3Jlc3VsdCkNCnByaW50KGthcHBhX3NuZl9od19yZXN1bHQpDQpwcmludChrYXBwYV9ra19zdGhzX3Jlc3VsdCkNCnByaW50KGthcHBhX3NuZl9zdGhzX3Jlc3VsdCkNCnByaW50KGthcHBhX2JtX2h3X3Jlc3VsdCkNCnByaW50KGthcHBhX2JtX3N0aF9yZXN1bHQpDQpgYGANCg0K