• 1 Getting started
    • 1.1 clean up
    • 1.2 general custom functions
    • 1.3 necessary packages
  • 2 Download data
  • 3 Import data
  • 4 data wrangling
    • 4.1 save data
  • References

The following scripts can be used to replicate the data-set of Franken, Bekhuis, and Tolsma (2024). It may also be obtained by downloading: Download conjoint.RDa


To copy the code, click the button in the upper right corner of the code-chunks.

1 Getting started

1.1 clean up

rm(list = ls())
gc()


1.2 general custom functions

  • fpackage.check: Check if packages are installed (and install if not) in R
  • fsave: Function to save data with time stamp in correct directory
  • fload: Load R-objects under new names
  • fshowdf: Print objects (tibble / data.frame) nicely on screen in .Rmd.
fpackage.check <- function(packages) {
    lapply(packages, FUN = function(x) {
        if (!require(x, character.only = TRUE)) {
            install.packages(x, dependencies = TRUE)
            library(x, character.only = TRUE)
        }
    })
}

fsave <- function(x, file, location = "./data/processed/", ...) {
    if (!dir.exists(location))
        dir.create(location)
    datename <- substr(gsub("[:-]", "", Sys.time()), 1, 8)
    totalname <- paste(location, datename, file, sep = "")
    print(paste("SAVED: ", totalname, sep = ""))
    save(x, file = totalname)
}


fload <- function(fileName) {
    load(fileName)
    get(ls()[ls() != "fileName"])
}

fshowdf <- function(x, digits = 2, ...) {
    knitr::kable(x, digits = digits, "html", ...) %>%
        kableExtra::kable_styling(bootstrap_options = c("striped", "hover")) %>%
        kableExtra::scroll_box(width = "100%", height = "300px")
}


1.3 necessary packages

  • tidyverse: data wrangling
  • reshape2: reshaping data
  • haven: read and write various data formats
  • sjlabelled: work with labelled (SPSS) data
packages = c("tidyverse", "haven", "sjlabelled", "reshape2")
fpackage.check(packages)
rm(packages)



2 Download data

All data from the ‘Transition Into Active Living’ (TRIAL) study will be deposited in DANS Data Station SSH at a later time (Bekhuis et al. 2021).

For now, we share parts of the data (i.e., conjoint data, important background/moderator variables): Download trial_part.Rda

Download the data-file, and put it in the ./data/ folder. But first, make a ./data/ folder:

ifelse(!dir.exists("data"), dir.create("data"), FALSE)


3 Import data

Load in the downloaded data file.

df <- fload("./data shared/trial_part.Rda")


4 data wrangling

# interaction variables current involvement df$V5
df$activeW2 <- ifelse(df$V5 == 1, "no", "yes")
# prop.table(table(df$activeW2, useNA = 'always')) #64 percent currently active, at w2

# self report sports frequency
sport1 <- ifelse(df$V6a == 1, 7, ifelse(df$V6a == 2, 4, ifelse(df$V6a == 3, 1.5, ifelse(df$V6a == 4,
    0.5, NA))))
sport2 <- ifelse(df$V6b == 1, 7, ifelse(df$V6b == 2, 4, ifelse(df$V6b == 3, 1.5, ifelse(df$V6b == 4,
    0.5, NA))))
sport3 <- ifelse(df$V6c == 1, 7, ifelse(df$V6c == 2, 4, ifelse(df$V6c == 3, 1.5, ifelse(df$V6c == 4,
    0.5, NA))))

df$sportsfreq <- NA
df$sportsfreq[which(df$activeW2 == "yes")] <- rowSums(cbind(sport1, sport2, sport3)[which(df$activeW2 ==
    "yes"), ], na.rm = TRUE)

# table(df$sportsfreq) cap at 14, only 1 higher.
df$sportsfreq <- ifelse(df$sportsfreq > 14, 14, df$sportsfreq)
# psych::describe(df$sportsfreq)

# gender
df$gender <- ifelse(df$GESLACHT2 == 1, "man", ifelse(df$GESLACHT2 == 2, "woman", "other"))

# attach id
df$id <- 1:nrow(df)

# remove columns we won't need:
df %>%
    select(-c(V5:GESLACHT2)) -> df
names(df)

# to long format

# each list element contains the choices for each set. thus presatielist[[2]][3] is the
# 'presatie'-attribute of person 3, in choice set 2

prestatielist <- list()
prestatielist[[1]] <- c("LoopKeuzesets_1_LoopAlternatieven_1_Prestaties", "LoopKeuzesets_1_LoopAlternatieven_2_Prestaties",
    "LoopKeuzesets_1_LoopAlternatieven_3_Prestaties")
prestatielist[[2]] <- c("LoopKeuzesets_2_LoopAlternatieven_1_Prestaties", "LoopKeuzesets_2_LoopAlternatieven_2_Prestaties",
    "LoopKeuzesets_2_LoopAlternatieven_3_Prestaties")
prestatielist[[3]] <- c("LoopKeuzesets_3_LoopAlternatieven_1_Prestaties", "LoopKeuzesets_3_LoopAlternatieven_2_Prestaties",
    "LoopKeuzesets_3_LoopAlternatieven_3_Prestaties")

kennislist <- list()
kennislist[[1]] <- c("LoopKeuzesets_1_LoopAlternatieven_1_Kennis", "LoopKeuzesets_1_LoopAlternatieven_2_Kennis",
    "LoopKeuzesets_1_LoopAlternatieven_3_Kennis")
kennislist[[2]] <- c("LoopKeuzesets_2_LoopAlternatieven_1_Kennis", "LoopKeuzesets_2_LoopAlternatieven_2_Kennis",
    "LoopKeuzesets_2_LoopAlternatieven_3_Kennis")
kennislist[[3]] <- c("LoopKeuzesets_3_LoopAlternatieven_1_Kennis", "LoopKeuzesets_3_LoopAlternatieven_2_Kennis",
    "LoopKeuzesets_3_LoopAlternatieven_3_Kennis")

gezelliglist <- list()
gezelliglist[[1]] <- c("LoopKeuzesets_1_LoopAlternatieven_1_Gezellig", "LoopKeuzesets_1_LoopAlternatieven_2_Gezellig",
    "LoopKeuzesets_1_LoopAlternatieven_3_Gezellig")
gezelliglist[[2]] <- c("LoopKeuzesets_2_LoopAlternatieven_1_Gezellig", "LoopKeuzesets_2_LoopAlternatieven_2_Gezellig",
    "LoopKeuzesets_2_LoopAlternatieven_3_Gezellig")
gezelliglist[[3]] <- c("LoopKeuzesets_3_LoopAlternatieven_1_Gezellig", "LoopKeuzesets_3_LoopAlternatieven_2_Gezellig",
    "LoopKeuzesets_3_LoopAlternatieven_3_Gezellig")

esteemlist <- list()
esteemlist[[1]] <- c("LoopKeuzesets_1_LoopAlternatieven_1_Aanmoediging", "LoopKeuzesets_1_LoopAlternatieven_2_Aanmoediging",
    "LoopKeuzesets_1_LoopAlternatieven_3_Aanmoediging")
esteemlist[[2]] <- c("LoopKeuzesets_2_LoopAlternatieven_1_Aanmoediging", "LoopKeuzesets_2_LoopAlternatieven_2_Aanmoediging",
    "LoopKeuzesets_2_LoopAlternatieven_3_Aanmoediging")
esteemlist[[3]] <- c("LoopKeuzesets_3_LoopAlternatieven_1_Aanmoediging", "LoopKeuzesets_3_LoopAlternatieven_2_Aanmoediging",
    "LoopKeuzesets_3_LoopAlternatieven_3_Aanmoediging")

chosen <- c("V84_LoopKeuzesets_1", "V85_LoopKeuzesets_2", "V86_LoopKeuzesets_3")

for (set in 1:3) {

    # to long format

    for (choice in 1:3) {

        data <- as.data.frame(df)
        data$set <- set
        data$options <- choice
        data$comparison <- data[, names(data) == prestatielist[[set]][choice]]
        data$knowledge <- data[, names(data) == kennislist[[set]][choice]]
        data$companionship <- data[, names(data) == gezelliglist[[set]][choice]]
        data$encouragement <- data[, names(data) == esteemlist[[set]][choice]]
        data$chosen <- data[, names(data) == chosen[set]]

        data <- data[, names(data) %in% c("id", "gender", "activeW2", "sportsfreq", "set", "options",
            "comparison", "knowledge", "companionship", "encouragement", "chosen")]

        if (set == 1 & choice == 1) {
            df_long <- data
        } else {
            df_long <- rbind(df_long, data)
        }
    }
}

# order
df_long <- df_long[order(df_long$id, df_long$set, df_long$options), ]

# define the choice
df_long$choice <- (df_long$chosen == c(1, 2, 3)[df_long$options])

# recode number into answer
df_long$comparison <- ifelse(df_long$comparison == 1, "really likes to compare sports performances",
    ifelse(df_long$comparison == 2, "somewhat likes to compare sports performances", ifelse(df_long$comparison ==
        3, "does not like to compare sports performances", NA)))

df_long$knowledge <- ifelse(df_long$knowledge == 1, "knows more than you about effective training and the right technique",
    ifelse(df_long$knowledge == 2, "knows as much as you about effective training and the right technique",
        ifelse(df_long$knowledge == 3, "knows less than you about effective training and the right technique",
            NA)))

df_long$companionship <- ifelse(df_long$companionship == 1, "exercises to socially engage", ifelse(df_long$companionship ==
    2, "wants a combination of social interaction and purposeful training", ifelse(df_long$companionship ==
    3, "exercises purposefully and seriously", NA)))

df_long$encouragement <- ifelse(df_long$encouragement == 1, "always encourages you", ifelse(df_long$encouragement ==
    2, "sometimes encourages you", ifelse(df_long$encouragement == 3, "never encourages you", NA)))

row.names(df_long) <- 1:nrow(df_long)

# remove 'chosen' and 'options' variable
data <- df_long[, -c(6, 11)]

# recode Y
data$choice <- ifelse(data$choice == TRUE, 1, 0)

# convert features to factor level names(data)
cols_to_convert <- c("comparison", "knowledge", "companionship", "encouragement", "activeW2", "gender",
    "set")
data[cols_to_convert] <- lapply(data[cols_to_convert], as.factor)

# re-order
data$comparison <- factor(data$comparison, levels = c("really likes to compare sports performances",
    "somewhat likes to compare sports performances", "does not like to compare sports performances"))

data$knowledge <- factor(data$knowledge, levels = c("knows more than you about effective training and the right technique",
    "knows as much as you about effective training and the right technique", "knows less than you about effective training and the right technique"))

data$companionship <- factor(data$companionship, levels = c("exercises to socially engage", "wants a combination of social interaction and purposeful training",
    "exercises purposefully and seriously"))

data$encouragement <- factor(data$encouragement, levels = c("always encourages you", "sometimes encourages you",
    "never encourages you"))

# fix(data)


4.1 save data

fsave(data, "conjoint.Rda")



References

Bekhuis, Hidde, Sara Wiertsema, Rob Franken, Gerbert Kraaykamp, Remco Hoekman, Debby Beckers, Jochem Tolsma, and Bert Steenbergen. 2021. TRansitions Into Active Living 2021-2023.” DANS Data Station Social Sciences; Humanities. https://doi.org/10.17026/dans-26k-ztw7.
Franken, Rob, Hidde Bekhuis, and Jochem Tolsma. 2024. “Choosing Your Sports Partners: Assessing Selection Preferences Through Observational and Experimental Studies.” Research Quarterly for Exercise and Sports. https://doi.org/10.1080/02701367.2024.2389907.
LS0tDQp0aXRsZTogIkRhdGEgcHJlcGFyYXRpb24iDQpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliDQpsaW5rLWNpdGF0aW9uczogdHJ1ZQ0KZGF0ZTogIkxhc3QgY29tcGlsZWQgb24gYHIgZm9ybWF0KFN5cy50aW1lKCksICclQiwgJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNzczogdHdlYWtzLmNzcw0KICAgIHRvYzogIHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICB0b2NfZGVwdGg6IDINCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCi0tLQ0KDQpgYGB7ciwgZ2xvYmFsc2V0dGluZ3MsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Kb3B0c19jaHVuayRzZXQodGlkeS5vcHRzPWxpc3Qod2lkdGguY3V0b2ZmPTEwMCksdGlkeT1UUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSxjb21tZW50ID0gIiM+IiwgY2FjaGU9VFJVRSwgY2xhc3Muc291cmNlPWMoInRlc3QiKSwgY2xhc3Mub3V0cHV0PWMoInRlc3QzIikpDQpvcHRpb25zKHdpZHRoID0gMTAwKQ0KcmdsOjpzZXR1cEtuaXRyKCkNCg0KY29sb3JpemUgPC0gZnVuY3Rpb24oeCwgY29sb3IpIHtzcHJpbnRmKCI8c3BhbiBzdHlsZT0nY29sb3I6ICVzOyc+JXM8L3NwYW4+IiwgY29sb3IsIHgpIH0NCmBgYA0KDQoNCmBgYHtyIGtsaXBweSwgZWNobz1GQUxTRSwgaW5jbHVkZT1UUlVFfQ0Ka2xpcHB5OjprbGlwcHkocG9zaXRpb24gPSBjKCd0b3AnLCAncmlnaHQnKSkNCiNrbGlwcHk6OmtsaXBweShjb2xvciA9ICdkYXJrcmVkJykNCiNrbGlwcHk6OmtsaXBweSh0b29sdGlwX21lc3NhZ2UgPSAnQ2xpY2sgdG8gY29weScsIHRvb2x0aXBfc3VjY2VzcyA9ICdEb25lJykNCmBgYA0KDQoNCi0tLSAgDQoNClRoZSBmb2xsb3dpbmcgc2NyaXB0cyBjYW4gYmUgdXNlZCB0byByZXBsaWNhdGUgdGhlIGRhdGEtc2V0IG9mIEBGcmFua2VuMjAyMi4gSXQgbWF5IGFsc28gYmUgb2J0YWluZWQgYnkgZG93bmxvYWRpbmc6IGByIHhmdW46OmVtYmVkX2ZpbGUoIi4vZGF0YSBzaGFyZWQvY29uam9pbnQuUkRhIilgDQoNCg0KDQotLS0tIA0KDQoNClRvIGNvcHkgdGhlIGNvZGUsIGNsaWNrIHRoZSBidXR0b24gaW4gdGhlIHVwcGVyIHJpZ2h0IGNvcm5lciBvZiB0aGUgY29kZS1jaHVua3MuDQoNCiMgR2V0dGluZyBzdGFydGVkDQoNCiMjIGNsZWFuIHVwDQoNCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30NCnJtKGxpc3Q9bHMoKSkNCmdjKCkNCmBgYA0KDQo8YnI+DQoNCiMjIGdlbmVyYWwgY3VzdG9tIGZ1bmN0aW9ucw0KDQotIGBmcGFja2FnZS5jaGVja2A6IENoZWNrIGlmIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQgKGFuZCBpbnN0YWxsIGlmIG5vdCkgaW4gUg0KLSBgZnNhdmVgOiBGdW5jdGlvbiB0byBzYXZlIGRhdGEgd2l0aCB0aW1lIHN0YW1wIGluIGNvcnJlY3QgZGlyZWN0b3J5DQotIGBmbG9hZGA6IExvYWQgUi1vYmplY3RzIHVuZGVyIG5ldyBuYW1lcw0KLSBgZnNob3dkZmA6IFByaW50IG9iamVjdHMgKGB0aWJibGVgIC8gYGRhdGEuZnJhbWVgKSBuaWNlbHkgb24gc2NyZWVuIGluIGAuUm1kYC4NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpmcGFja2FnZS5jaGVjayA8LSBmdW5jdGlvbihwYWNrYWdlcykgew0KICAgIGxhcHBseShwYWNrYWdlcywgRlVOID0gZnVuY3Rpb24oeCkgew0KICAgICAgICBpZiAoIXJlcXVpcmUoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcyh4LCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KICAgICAgICAgICAgbGlicmFyeSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpDQogICAgICAgIH0NCiAgICB9KQ0KfQ0KDQpmc2F2ZSA8LSBmdW5jdGlvbih4LCBmaWxlLCBsb2NhdGlvbiA9ICIuL2RhdGEvcHJvY2Vzc2VkLyIsIC4uLikgew0KICAgIGlmICghZGlyLmV4aXN0cyhsb2NhdGlvbikpDQogICAgICAgIGRpci5jcmVhdGUobG9jYXRpb24pDQogICAgZGF0ZW5hbWUgPC0gc3Vic3RyKGdzdWIoIls6LV0iLCAiIiwgU3lzLnRpbWUoKSksIDEsIDgpDQogICAgdG90YWxuYW1lIDwtIHBhc3RlKGxvY2F0aW9uLCBkYXRlbmFtZSwgZmlsZSwgc2VwID0gIiIpDQogICAgcHJpbnQocGFzdGUoIlNBVkVEOiAiLCB0b3RhbG5hbWUsIHNlcCA9ICIiKSkNCiAgICBzYXZlKHgsIGZpbGUgPSB0b3RhbG5hbWUpDQp9DQoNCg0KZmxvYWQgIDwtIGZ1bmN0aW9uKGZpbGVOYW1lKXsNCiAgbG9hZChmaWxlTmFtZSkNCiAgZ2V0KGxzKClbbHMoKSAhPSAiZmlsZU5hbWUiXSkNCn0NCg0KZnNob3dkZiA8LSBmdW5jdGlvbih4LCBkaWdpdHMgPSAyLCAuLi4pIHsNCiAgICBrbml0cjo6a2FibGUoeCwgZGlnaXRzID0gZGlnaXRzLCAiaHRtbCIsIC4uLikgJT4lDQogICAgICAgIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpICU+JQ0KICAgICAgICBrYWJsZUV4dHJhOjpzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiMzAwcHgiKQ0KfQ0KYGBgDQoNCjxicj4NCg0KIyMgbmVjZXNzYXJ5IHBhY2thZ2VzDQoNCi0gYHRpZHl2ZXJzZWA6IGRhdGEgd3JhbmdsaW5nDQotIGByZXNoYXBlMmA6IHJlc2hhcGluZyBkYXRhDQotIGBoYXZlbmA6IHJlYWQgYW5kIHdyaXRlIHZhcmlvdXMgZGF0YSBmb3JtYXRzDQotIGBzamxhYmVsbGVkYDogd29yayB3aXRoIGxhYmVsbGVkIChTUFNTKSBkYXRhDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KcGFja2FnZXMgPSBjKCJ0aWR5dmVyc2UiLCAiaGF2ZW4iLCAic2psYWJlbGxlZCIsICJyZXNoYXBlMiIpDQpmcGFja2FnZS5jaGVjayhwYWNrYWdlcykNCnJtKHBhY2thZ2VzKQ0KYGBgDQoNCjxicj4NCg0KDQotLS0NCg0KIyBEb3dubG9hZCBkYXRhDQoNCg0KQWxsIGRhdGEgZnJvbSB0aGUgJ1RyYW5zaXRpb24gSW50byBBY3RpdmUgTGl2aW5nJyAoVFJJQUwpIHN0dWR5IHdpbGwgYmUgZGVwb3NpdGVkIGluIERBTlMgRGF0YSBTdGF0aW9uIFNTSCBhdCBhIGxhdGVyIHRpbWUgW0B0cmlhbF0uDQoNCkZvciBub3csIHdlIHNoYXJlIHBhcnRzIG9mIHRoZSBkYXRhIChpLmUuLCBjb25qb2ludCBkYXRhLCBpbXBvcnRhbnQgYmFja2dyb3VuZC9tb2RlcmF0b3IgdmFyaWFibGVzKTogYHIgeGZ1bjo6ZW1iZWRfZmlsZSgiLi9kYXRhIHNoYXJlZC90cmlhbF9wYXJ0LlJkYSIpYA0KDQpEb3dubG9hZCB0aGUgZGF0YS1maWxlLCBhbmQgcHV0IGl0IGluIHRoZSBgLi9kYXRhL2AgZm9sZGVyLiBCdXQgZmlyc3QsIG1ha2UgYSBgLi9kYXRhL2AgZm9sZGVyOiANCg0KYGBge3IsIGV2YWw9RkFMU0V9DQppZmVsc2UoIWRpci5leGlzdHMoImRhdGEiKSwgZGlyLmNyZWF0ZSgiZGF0YSIpLCBGQUxTRSkNCmBgYA0KDQoNCjxicj4NCg0KIyBJbXBvcnQgZGF0YQ0KDQpMb2FkIGluIHRoZSBkb3dubG9hZGVkIGRhdGEgZmlsZS4NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpkZiA8LSBmbG9hZCgiLi9kYXRhIHNoYXJlZC90cmlhbF9wYXJ0LlJkYSIpDQpgYGANCg0KPGJyPiANCg0KIyBkYXRhIHdyYW5nbGluZw0KDQoNCmBgYHtyLCBldmFsPUZ9DQojIGludGVyYWN0aW9uIHZhcmlhYmxlcw0KIyBjdXJyZW50IGludm9sdmVtZW50DQojZGYkVjUNCmRmJGFjdGl2ZVcyIDwtIGlmZWxzZShkZiRWNSA9PSAxLCAibm8iLCAieWVzIikNCiNwcm9wLnRhYmxlKHRhYmxlKGRmJGFjdGl2ZVcyLCB1c2VOQSA9ICJhbHdheXMiKSkgIzY0IHBlcmNlbnQgY3VycmVudGx5IGFjdGl2ZSwgYXQgdzINCg0KI3NlbGYgcmVwb3J0IHNwb3J0cyBmcmVxdWVuY3kNCnNwb3J0MSA8LSBpZmVsc2UoZGYkVjZhPT0xLCA3LCBpZmVsc2UoZGYkVjZhPT0yLCA0LCBpZmVsc2UoZGYkVjZhPT0zLCAxLjUsIGlmZWxzZShkZiRWNmE9PTQsIDAuNSwgTkEpKSkpDQpzcG9ydDIgPC0gaWZlbHNlKGRmJFY2Yj09MSwgNywgaWZlbHNlKGRmJFY2Yj09MiwgNCwgaWZlbHNlKGRmJFY2Yj09MywgMS41LCBpZmVsc2UoZGYkVjZiPT00LCAwLjUsIE5BKSkpKQ0Kc3BvcnQzIDwtIGlmZWxzZShkZiRWNmM9PTEsIDcsIGlmZWxzZShkZiRWNmM9PTIsIDQsIGlmZWxzZShkZiRWNmM9PTMsIDEuNSwgaWZlbHNlKGRmJFY2Yz09NCwgMC41LCBOQSkpKSkNCg0KZGYkc3BvcnRzZnJlcSA8LSBOQQ0KZGYkc3BvcnRzZnJlcVt3aGljaChkZiRhY3RpdmVXMj09InllcyIpXSA8LSByb3dTdW1zKGNiaW5kKHNwb3J0MSxzcG9ydDIsc3BvcnQzKVt3aGljaChkZiRhY3RpdmVXMj09InllcyIpLF0sIG5hLnJtPVRSVUUpDQoNCiN0YWJsZShkZiRzcG9ydHNmcmVxKQ0KI2NhcCBhdCAxNCwgb25seSAxIGhpZ2hlci4NCmRmJHNwb3J0c2ZyZXEgPC0gaWZlbHNlKGRmJHNwb3J0c2ZyZXE+MTQsIDE0LCBkZiRzcG9ydHNmcmVxKQ0KI3BzeWNoOjpkZXNjcmliZShkZiRzcG9ydHNmcmVxKQ0KDQojZ2VuZGVyDQpkZiRnZW5kZXIgPC0gaWZlbHNlKGRmJEdFU0xBQ0hUMj09MSwibWFuIixpZmVsc2UoZGYkR0VTTEFDSFQyPT0yLCJ3b21hbiIsICJvdGhlciIpKQ0KDQojYXR0YWNoIGlkDQpkZiRpZCA8LSAxOm5yb3coZGYpDQoNCiNyZW1vdmUgY29sdW1ucyB3ZSB3b24ndCBuZWVkOg0KZGYgJT4lDQogIHNlbGVjdCgtYyhWNTpHRVNMQUNIVDIpKSAtPiBkZg0KbmFtZXMoZGYpDQoNCiMgdG8gbG9uZyBmb3JtYXQNCg0KIyBlYWNoIGxpc3QgZWxlbWVudCBjb250YWlucyB0aGUgY2hvaWNlcyBmb3IgZWFjaCBzZXQuIHRodXMgcHJlc2F0aWVsaXN0W1syXV1bM10gaXMgdGhlDQojICdwcmVzYXRpZSctYXR0cmlidXRlIG9mIHBlcnNvbiAzLCBpbiBjaG9pY2Ugc2V0IDINCg0KcHJlc3RhdGllbGlzdCA8LSBsaXN0KCkNCnByZXN0YXRpZWxpc3RbWzFdXSA8LSBjKCJMb29wS2V1emVzZXRzXzFfTG9vcEFsdGVybmF0aWV2ZW5fMV9QcmVzdGF0aWVzIiwgIkxvb3BLZXV6ZXNldHNfMV9Mb29wQWx0ZXJuYXRpZXZlbl8yX1ByZXN0YXRpZXMiLCAiTG9vcEtldXplc2V0c18xX0xvb3BBbHRlcm5hdGlldmVuXzNfUHJlc3RhdGllcyIpDQpwcmVzdGF0aWVsaXN0W1syXV0gPC0gYygiTG9vcEtldXplc2V0c18yX0xvb3BBbHRlcm5hdGlldmVuXzFfUHJlc3RhdGllcyIsICJMb29wS2V1emVzZXRzXzJfTG9vcEFsdGVybmF0aWV2ZW5fMl9QcmVzdGF0aWVzIiwgIkxvb3BLZXV6ZXNldHNfMl9Mb29wQWx0ZXJuYXRpZXZlbl8zX1ByZXN0YXRpZXMiKQ0KcHJlc3RhdGllbGlzdFtbM11dIDwtIGMoIkxvb3BLZXV6ZXNldHNfM19Mb29wQWx0ZXJuYXRpZXZlbl8xX1ByZXN0YXRpZXMiLCAiTG9vcEtldXplc2V0c18zX0xvb3BBbHRlcm5hdGlldmVuXzJfUHJlc3RhdGllcyIsICJMb29wS2V1emVzZXRzXzNfTG9vcEFsdGVybmF0aWV2ZW5fM19QcmVzdGF0aWVzIikNCg0Ka2VubmlzbGlzdCA8LSBsaXN0KCkNCmtlbm5pc2xpc3RbWzFdXSA8LSBjKCJMb29wS2V1emVzZXRzXzFfTG9vcEFsdGVybmF0aWV2ZW5fMV9LZW5uaXMiLCAiTG9vcEtldXplc2V0c18xX0xvb3BBbHRlcm5hdGlldmVuXzJfS2VubmlzIiwgIkxvb3BLZXV6ZXNldHNfMV9Mb29wQWx0ZXJuYXRpZXZlbl8zX0tlbm5pcyIpDQprZW5uaXNsaXN0W1syXV0gPC0gYygiTG9vcEtldXplc2V0c18yX0xvb3BBbHRlcm5hdGlldmVuXzFfS2VubmlzIiwgIkxvb3BLZXV6ZXNldHNfMl9Mb29wQWx0ZXJuYXRpZXZlbl8yX0tlbm5pcyIsICJMb29wS2V1emVzZXRzXzJfTG9vcEFsdGVybmF0aWV2ZW5fM19LZW5uaXMiKQ0Ka2VubmlzbGlzdFtbM11dIDwtIGMoIkxvb3BLZXV6ZXNldHNfM19Mb29wQWx0ZXJuYXRpZXZlbl8xX0tlbm5pcyIsICJMb29wS2V1emVzZXRzXzNfTG9vcEFsdGVybmF0aWV2ZW5fMl9LZW5uaXMiLCAiTG9vcEtldXplc2V0c18zX0xvb3BBbHRlcm5hdGlldmVuXzNfS2VubmlzIikNCg0KZ2V6ZWxsaWdsaXN0IDwtIGxpc3QoKQ0KZ2V6ZWxsaWdsaXN0W1sxXV0gPC0gYygiTG9vcEtldXplc2V0c18xX0xvb3BBbHRlcm5hdGlldmVuXzFfR2V6ZWxsaWciLCAiTG9vcEtldXplc2V0c18xX0xvb3BBbHRlcm5hdGlldmVuXzJfR2V6ZWxsaWciLCAiTG9vcEtldXplc2V0c18xX0xvb3BBbHRlcm5hdGlldmVuXzNfR2V6ZWxsaWciKQ0KZ2V6ZWxsaWdsaXN0W1syXV0gPC0gYygiTG9vcEtldXplc2V0c18yX0xvb3BBbHRlcm5hdGlldmVuXzFfR2V6ZWxsaWciLCAiTG9vcEtldXplc2V0c18yX0xvb3BBbHRlcm5hdGlldmVuXzJfR2V6ZWxsaWciLCAiTG9vcEtldXplc2V0c18yX0xvb3BBbHRlcm5hdGlldmVuXzNfR2V6ZWxsaWciKQ0KZ2V6ZWxsaWdsaXN0W1szXV0gPC0gYygiTG9vcEtldXplc2V0c18zX0xvb3BBbHRlcm5hdGlldmVuXzFfR2V6ZWxsaWciLCAiTG9vcEtldXplc2V0c18zX0xvb3BBbHRlcm5hdGlldmVuXzJfR2V6ZWxsaWciLCAiTG9vcEtldXplc2V0c18zX0xvb3BBbHRlcm5hdGlldmVuXzNfR2V6ZWxsaWciKQ0KDQplc3RlZW1saXN0IDwtIGxpc3QoKQ0KZXN0ZWVtbGlzdFtbMV1dIDwtIGMoIkxvb3BLZXV6ZXNldHNfMV9Mb29wQWx0ZXJuYXRpZXZlbl8xX0Fhbm1vZWRpZ2luZyIsICJMb29wS2V1emVzZXRzXzFfTG9vcEFsdGVybmF0aWV2ZW5fMl9BYW5tb2VkaWdpbmciLCAiTG9vcEtldXplc2V0c18xX0xvb3BBbHRlcm5hdGlldmVuXzNfQWFubW9lZGlnaW5nIikNCmVzdGVlbWxpc3RbWzJdXSA8LSBjKCJMb29wS2V1emVzZXRzXzJfTG9vcEFsdGVybmF0aWV2ZW5fMV9BYW5tb2VkaWdpbmciLCAiTG9vcEtldXplc2V0c18yX0xvb3BBbHRlcm5hdGlldmVuXzJfQWFubW9lZGlnaW5nIiwgIkxvb3BLZXV6ZXNldHNfMl9Mb29wQWx0ZXJuYXRpZXZlbl8zX0Fhbm1vZWRpZ2luZyIpDQplc3RlZW1saXN0W1szXV0gPC0gYygiTG9vcEtldXplc2V0c18zX0xvb3BBbHRlcm5hdGlldmVuXzFfQWFubW9lZGlnaW5nIiwgIkxvb3BLZXV6ZXNldHNfM19Mb29wQWx0ZXJuYXRpZXZlbl8yX0Fhbm1vZWRpZ2luZyIsICJMb29wS2V1emVzZXRzXzNfTG9vcEFsdGVybmF0aWV2ZW5fM19BYW5tb2VkaWdpbmciKQ0KDQpjaG9zZW4gPC0gYygiVjg0X0xvb3BLZXV6ZXNldHNfMSIsICJWODVfTG9vcEtldXplc2V0c18yIiwgIlY4Nl9Mb29wS2V1emVzZXRzXzMiKQ0KDQpmb3IgKHNldCBpbiAxOjMpIHsNCg0KICAjIHRvIGxvbmcgZm9ybWF0DQogICAgDQogIGZvciAoY2hvaWNlIGluIDE6Mykgew0KICAgIA0KICAgICAgICBkYXRhIDwtIGFzLmRhdGEuZnJhbWUoZGYpDQogICAgICAgIGRhdGEkc2V0IDwtIHNldA0KICAgICAgICBkYXRhJG9wdGlvbnMgPC0gY2hvaWNlIA0KICAgICAgICBkYXRhJGNvbXBhcmlzb24gPC0gZGF0YVssIG5hbWVzKGRhdGEpID09IHByZXN0YXRpZWxpc3RbW3NldF1dW2Nob2ljZV1dDQogICAgICAgIGRhdGEka25vd2xlZGdlIDwtIGRhdGFbLCBuYW1lcyhkYXRhKSA9PSBrZW5uaXNsaXN0W1tzZXRdXVtjaG9pY2VdXQ0KICAgICAgICBkYXRhJGNvbXBhbmlvbnNoaXAgPC0gZGF0YVssIG5hbWVzKGRhdGEpID09IGdlemVsbGlnbGlzdFtbc2V0XV1bY2hvaWNlXV0NCiAgICAgICAgZGF0YSRlbmNvdXJhZ2VtZW50IDwtIGRhdGFbLCBuYW1lcyhkYXRhKSA9PSBlc3RlZW1saXN0W1tzZXRdXVtjaG9pY2VdXQ0KICAgICAgICBkYXRhJGNob3NlbiA8LSBkYXRhWywgbmFtZXMoZGF0YSkgPT0gY2hvc2VuW3NldF1dDQogICAgICAgIA0KICAgICAgICBkYXRhIDwtIGRhdGFbLCBuYW1lcyhkYXRhKSAlaW4lIGMoImlkIiwgImdlbmRlciIsICJhY3RpdmVXMiIsICJzcG9ydHNmcmVxIiwgInNldCIsICJvcHRpb25zIiwgImNvbXBhcmlzb24iLCAia25vd2xlZGdlIiwgImNvbXBhbmlvbnNoaXAiLCAiZW5jb3VyYWdlbWVudCIsICJjaG9zZW4iKV0NCiAgICAgICAgDQogICAgICAgIGlmIChzZXQgPT0gMSAmIGNob2ljZSA9PSAxKSB7DQogICAgICAgICAgICBkZl9sb25nIDwtIGRhdGENCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGRmX2xvbmcgPC0gcmJpbmQoZGZfbG9uZywgZGF0YSkNCiAgICAgICAgfQ0KICAgIH0NCn0NCg0KIyBvcmRlcg0KZGZfbG9uZyA8LSBkZl9sb25nW29yZGVyKGRmX2xvbmckaWQsIGRmX2xvbmckc2V0LCBkZl9sb25nJG9wdGlvbnMpLCBdDQoNCiMgZGVmaW5lIHRoZSBjaG9pY2UNCmRmX2xvbmckY2hvaWNlIDwtIChkZl9sb25nJGNob3NlbiA9PSBjKDEsIDIsIDMpW2RmX2xvbmckb3B0aW9uc10pDQoNCiNyZWNvZGUgbnVtYmVyIGludG8gYW5zd2VyDQpkZl9sb25nJGNvbXBhcmlzb24gPC0gaWZlbHNlKGRmX2xvbmckY29tcGFyaXNvbiA9PSAxLCAicmVhbGx5IGxpa2VzIHRvIGNvbXBhcmUgc3BvcnRzIHBlcmZvcm1hbmNlcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkZl9sb25nJGNvbXBhcmlzb24gPT0gMiwgInNvbWV3aGF0IGxpa2VzIHRvIGNvbXBhcmUgc3BvcnRzIHBlcmZvcm1hbmNlcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkZl9sb25nJGNvbXBhcmlzb24gPT0gMywgImRvZXMgbm90IGxpa2UgdG8gY29tcGFyZSBzcG9ydHMgcGVyZm9ybWFuY2VzIiwgTkEpKSkNCg0KZGZfbG9uZyRrbm93bGVkZ2UgPC0gaWZlbHNlKGRmX2xvbmcka25vd2xlZGdlID09IDEsICJrbm93cyBtb3JlIHRoYW4geW91IGFib3V0IGVmZmVjdGl2ZSB0cmFpbmluZyBhbmQgdGhlIHJpZ2h0IHRlY2huaXF1ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkZl9sb25nJGtub3dsZWRnZSA9PSAyLCAia25vd3MgYXMgbXVjaCBhcyB5b3UgYWJvdXQgZWZmZWN0aXZlIHRyYWluaW5nIGFuZCB0aGUgcmlnaHQgdGVjaG5pcXVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGRmX2xvbmcka25vd2xlZGdlID09IDMsICJrbm93cyBsZXNzIHRoYW4geW91IGFib3V0IGVmZmVjdGl2ZSB0cmFpbmluZyBhbmQgdGhlIHJpZ2h0IHRlY2huaXF1ZSIsIE5BKSkpIA0KDQpkZl9sb25nJGNvbXBhbmlvbnNoaXAgPC0gaWZlbHNlKGRmX2xvbmckY29tcGFuaW9uc2hpcCA9PSAxLCAiZXhlcmNpc2VzIHRvIHNvY2lhbGx5IGVuZ2FnZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkZl9sb25nJGNvbXBhbmlvbnNoaXAgPT0gMiwgIndhbnRzIGEgY29tYmluYXRpb24gb2Ygc29jaWFsIGludGVyYWN0aW9uIGFuZCBwdXJwb3NlZnVsIHRyYWluaW5nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGRmX2xvbmckY29tcGFuaW9uc2hpcCA9PSAzLCAiZXhlcmNpc2VzIHB1cnBvc2VmdWxseSBhbmQgc2VyaW91c2x5IiwgTkEpKSkNCg0KZGZfbG9uZyRlbmNvdXJhZ2VtZW50IDwtIGlmZWxzZShkZl9sb25nJGVuY291cmFnZW1lbnQgPT0gMSwgImFsd2F5cyBlbmNvdXJhZ2VzIHlvdSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkZl9sb25nJGVuY291cmFnZW1lbnQgPT0gMiwgInNvbWV0aW1lcyBlbmNvdXJhZ2VzIHlvdSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkZl9sb25nJGVuY291cmFnZW1lbnQgPT0gMywgIm5ldmVyIGVuY291cmFnZXMgeW91IiwgTkEpKSkNCg0Kcm93Lm5hbWVzKGRmX2xvbmcpIDwtIDE6bnJvdyhkZl9sb25nKQ0KDQojcmVtb3ZlICJjaG9zZW4iIGFuZCAib3B0aW9ucyIgdmFyaWFibGUNCmRhdGEgPC0gZGZfbG9uZ1ssLWMoNiwxMSldDQoNCiNyZWNvZGUgWQ0KZGF0YSRjaG9pY2UgPC0gaWZlbHNlKGRhdGEkY2hvaWNlPT1UUlVFLDEsMCkNCg0KI2NvbnZlcnQgZmVhdHVyZXMgdG8gZmFjdG9yIGxldmVsDQojbmFtZXMoZGF0YSkNCmNvbHNfdG9fY29udmVydCA8LSBjKCJjb21wYXJpc29uIiwgImtub3dsZWRnZSIsICJjb21wYW5pb25zaGlwIiwgImVuY291cmFnZW1lbnQiLCJhY3RpdmVXMiIsImdlbmRlciIsICJzZXQiKQ0KZGF0YVtjb2xzX3RvX2NvbnZlcnRdIDwtIGxhcHBseShkYXRhW2NvbHNfdG9fY29udmVydF0sIGFzLmZhY3RvcikNCg0KI3JlLW9yZGVyDQpkYXRhJGNvbXBhcmlzb24gPC0gZmFjdG9yKGRhdGEkY29tcGFyaXNvbiwgbGV2ZWxzID0gYygicmVhbGx5IGxpa2VzIHRvIGNvbXBhcmUgc3BvcnRzIHBlcmZvcm1hbmNlcyIsInNvbWV3aGF0IGxpa2VzIHRvIGNvbXBhcmUgc3BvcnRzIHBlcmZvcm1hbmNlcyIsImRvZXMgbm90IGxpa2UgdG8gY29tcGFyZSBzcG9ydHMgcGVyZm9ybWFuY2VzIikpDQoNCmRhdGEka25vd2xlZGdlIDwtIGZhY3RvcihkYXRhJGtub3dsZWRnZSwgbGV2ZWxzID0gYygia25vd3MgbW9yZSB0aGFuIHlvdSBhYm91dCBlZmZlY3RpdmUgdHJhaW5pbmcgYW5kIHRoZSByaWdodCB0ZWNobmlxdWUiLCJrbm93cyBhcyBtdWNoIGFzIHlvdSBhYm91dCBlZmZlY3RpdmUgdHJhaW5pbmcgYW5kIHRoZSByaWdodCB0ZWNobmlxdWUiLCJrbm93cyBsZXNzIHRoYW4geW91IGFib3V0IGVmZmVjdGl2ZSB0cmFpbmluZyBhbmQgdGhlIHJpZ2h0IHRlY2huaXF1ZSIpKQ0KDQpkYXRhJGNvbXBhbmlvbnNoaXAgPC0gZmFjdG9yKGRhdGEkY29tcGFuaW9uc2hpcCwgbGV2ZWxzID0gYygiZXhlcmNpc2VzIHRvIHNvY2lhbGx5IGVuZ2FnZSIsIndhbnRzIGEgY29tYmluYXRpb24gb2Ygc29jaWFsIGludGVyYWN0aW9uIGFuZCBwdXJwb3NlZnVsIHRyYWluaW5nIiwiZXhlcmNpc2VzIHB1cnBvc2VmdWxseSBhbmQgc2VyaW91c2x5IikpDQoNCmRhdGEkZW5jb3VyYWdlbWVudCA8LSBmYWN0b3IoZGF0YSRlbmNvdXJhZ2VtZW50LCBsZXZlbHMgPSBjKCJhbHdheXMgZW5jb3VyYWdlcyB5b3UiLCAic29tZXRpbWVzIGVuY291cmFnZXMgeW91IiwgIm5ldmVyIGVuY291cmFnZXMgeW91IikpDQoNCiNmaXgoZGF0YSkNCmBgYA0KDQo8YnI+DQoNCiMjIHNhdmUgZGF0YQ0KYGBge3IsZXZhbD1GQUxTRX0NCmZzYXZlKGRhdGEsICJjb25qb2ludC5SZGEiKQ0KYGBgDQoNCjxicj4NCg0KLS0tLQ0KDQoNCiMgUmVmZXJlbmNlcw==


Copyright © 2025 Rob Franken