Script
Barcode Alignments
barcodes <- imap(seqruns, ~ {
map(.x, ~ read_table(barcode_alignments[[.x]]) %>% mutate(seqrun = .x))
}) %>%
bind_rows() %>%
as_tibble() %>%
filter(barcode != "unclassified") %>%
mutate(SeqDateTime = as_datetime(started)) %>%
mutate(SeqDate = floor_date(SeqDateTime, unit = "day")) %>%
mutate(SeqRunID = str_replace_all(sample_id, "pool1", "PL001")) %>%
mutate(LibraryCode = str_squish(str_trim(seqrun , "both")),
FlowCellSerial = str_squish(str_trim(flow_cell_id, "both"))
) %>%
mutate(LibraryBarcode = as.numeric(str_remove_all(barcode, "16S|barcode0|barcode"))) %>%
select(LibraryCode,
LibraryBarcode,
reads_unclassified = target_unclassified,
FlowCellSerial,
protocol_group_id,
flow_cell_id,
SeqRunID,
SeqDate,
SeqDateTime)
write.table(barcodes, barcode_alignments$compilations[[paste0(params$sampleset)]],
row.names = F,
sep = "\t")
Sequencing Runs
seqrun.tbl <- read_csv(path$inventories$seqruns) %>%
rename_with(~str_replace_all(., "\\s", "_")) %>%
mutate(SampleSet = case_when(
str_detect(Pooled_Library_Code, "CM") ~ "marmoset",
str_detect(Pooled_Library_Code, "PL") ~ "loris",
str_detect(Pooled_Library_Code, "NWR") ~ "bats", .default = "unknown"),
LibraryCode = str_to_lower(Pooled_Library_Code),
LibPrepWorkflow = case_when(
str_detect(Kit, "LSK") & Pipeline == "16S" ~ "lsk16s",
Pipeline == "Host mtDNA" ~ "lskadaptive",
str_detect(Kit, "SQK-16S") & Pipeline == "16S" ~ "rapid16s"),
LibPrepDate = mdy(Run_Date),
SeqRunDate = ymd(str_remove_all(str_trim(Run_ID, "both"), "MIN_16_|MIN_16-|MIN_MT_"))) %>%
mutate(LibraryCode = str_replace_all(LibraryCode, "pl00|pl0", "hdz"),
strands = 2,
fragment_type = if_else(Pipeline == "16S", 3, 1),
Length = if_else(Pipeline == "16S", 1500, 10000),
InputMassStart = if_else(Pipeline == "16S", 10, 1000),
TemplateVolPrep = if_else(LibPrepWorkflow == "rapid16s", 15, 47),
PoolSamples = if_else(Pipeline == "16S", "yes", "no"),
InputMassFinal = 50
) %>%
filter(SampleSet == params$sampleset) %>%
select(
SampleSet,
LibraryCode,
LibPrepDate,
LibPrepWorkflow,
LibPrepKit = Kit,
FlowCellSerial = Flow_Cell_ID,
FlowCellType = Flow_Cell_Type,
FlongleAdapter = Flongle_Adapter,
SeqDevice = Sequencer,
strands,
fragment_type,
Length,
InputMassStart,
TemplateVolPrep,
PoolSamples,
InputMassFinal)
Sample Records
samples <- read_csv(path$inventories$collection) %>%
rename_with(~str_replace_all(., "\\s", "_")) %>%
filter(str_starts(SampleID, "\\w+")) %>%
select(-SampleBox) %>%
mutate(SampleID = str_squish(str_trim(SampleID, "both"))) %>% distinct() %>%
mutate(CollectionDate = mdy(SampleDate),
Subject = str_squish(str_trim(SampleSubject)),
.keep = "unused") %>% distinct() %>%
mutate(Subj_Certainty = if_else(Subject %in% subject_list, "yes", "no")) %>%
mutate(Subject = str_remove_all(Subject, "\\?"))
Libraries and Combining all Records
compilation <- read_csv(path$inventories$libraries, show_col_types = FALSE, col_types = list(LibraryBarcode = col_character())) %>%
rename_with(~str_replace_all(., "\\s", "_")) %>%
rename_with(~str_remove_all(., "\\(|\\)")) %>%
filter(str_starts(SequenceID, "\\w+") & Seq_ID != "#N/A") %>%
mutate(LibraryCode = str_to_lower(Seq_ID)) %>%
mutate(LibraryCode = str_replace_all(LibraryCode, "pl00|pl0" , "hdz"),
SampVolPool = round(as.numeric(Volume_Added_to_Pool_uL), 0),
LibraryBarcode = as.numeric(str_remove_all(LibraryBarcode, "16S|barcode0|barcode"))) %>%
mutate(TotalPoolVol = sum(SampVolPool), .by = LibraryCode) %>%
mutate(BeadVol = TotalPoolVol * 0.6) %>%
select(SequenceID,
LibraryCode,
LibraryTube,
LibraryBarcode,
ExtractID,
SampVolPool,
TotalPoolVol,
BeadVol,
Conc_QC2 = Final_Library_Concentration) %>%
full_join(extracts, by = join_by(ExtractID)) %>%
mutate(SampleID = if_else(is.na(SampleID) & !is.na(ExtractID), "NTC", SampleID)) %>%
full_join(barcodes, by = join_by(LibraryCode, LibraryBarcode)) %>%
select(-FlowCellSerial) %>%
left_join(seqrun.tbl, by = join_by(LibraryCode)) %>% distinct() %>%
mutate(steps_remaining = case_when(
is.na(ExtractID) ~ "sample not extracted",
is.na(SequenceID) ~ "extract not sequenced",
!is.na(ExtractID) & !is.na(SequenceID) & !is.na(SampleID) ~ "sample extracted and sequenced"
)) %>%
relocate(SampleID, ExtractID, SequenceID, steps_remaining) %>%
arrange(CollectionDate, Subject)
Exporting a Spreadsheet with Records
We will use this spreadsheet for building the metadata table but also
for calling up sample info in our protocol apps.
write.table(compilation,
path$inventories$all_stages,
row.names = F,
sep = "\t")
Counting Replicates
count.extracts <- extracts %>% select(ExtractID, SampleID) %>% distinct() %>%
group_by(SampleID) %>%
mutate(n_dna_extracts = n_distinct(ExtractID)) %>% ungroup() %>% select(-ExtractID)
count.libraries <- compilation %>% select(SequenceID, ExtractID, SampleID) %>% distinct() %>%
group_by(ExtractID) %>% mutate(n_16s_extract = n_distinct(SequenceID)) %>% ungroup() %>%
group_by(SampleID) %>% mutate(n_16s_sample = n_distinct(SequenceID)) %>% ungroup() %>% select(-SequenceID)
LS0tCnRpdGxlOiAiU2FtcGxlIEludmVudG9yeSIKYXV0aG9yOiAiQWxpY2lhIFJpY2giCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZToKICAgICAgYnNsaWI6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY3NzOiBqb3VybmFsLmNzcwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQpwYXJhbXM6CiAgc2FtcGxlc2V0OiAibG9yaXMiCiAgc2VxcnVuOiAiaGR6MTgiCiAgICAgICAgICAgICAgICAgICAgIAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRn0KCmxpYnJhcnkoYnNsaWIpCmxpYnJhcnkoY29uZmxpY3RlZCkKbGlicmFyeShodG1sdG9vbHMpCmxpYnJhcnkoaHRtbHdpZGdldHMpCmxpYnJhcnkodGlkeXZlcnNlKQoKc291cmNlKCJzZXR1cC9jb25mbGljdGVkLlIiKQpzb3VyY2UoInNldHVwL2tuaXRfZW5naW5lc19zaW1wbGUuUiIpCnNvdXJjZSgic2V0dXAvaW5wdXRzX3JlYWRfcHJvY2Vzc2luZy5SIikKCgprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgbWVzc2FnZSAgICAgICA9IEZBTFNFLAogIHdhcm5pbmcgICAgICAgPSBGQUxTRSwKICBlY2hvICAgICAgICAgID0gVFJVRSwKICBpbmNsdWRlICAgICAgID0gVFJVRSwKICBldmFsICAgICAgICAgID0gVFJVRSwKICBjb21tZW50ICAgICAgID0gIiIgICwKICBkZl9wcmludCAgICAgID0gImthYmxlIiwKICBza2ltcl9kaWdpdHMgID0gMiAgICAgICAgKQoKa25pdHI6Om9wdHNfa25pdCRzZXQoCiAgbWVzc2FnZSAgICAgICA9IEZBTFNFLAogIHdhcm5pbmcgICAgICAgPSBGQUxTRSwKICBlY2hvICAgICAgICAgID0gVFJVRSwKICBpbmNsdWRlICAgICAgID0gVFJVRSwKICBldmFsICAgICAgICAgID0gVFJVRSwKICBjb21tZW50ICAgICAgID0gIiIgICwKICBkZl9wcmludCAgICAgID0gImthYmxlIiwKICBza2ltcl9kaWdpdHMgID0gMiAgICAgICAgCiAgKQoKc2VxcnVucyA8LSBzZXFydW5zICU+JSBrZWVwX2F0KHBhcmFtcyRzYW1wbGVzZXQpICAlPiUgbGlzdF9mbGF0dGVuKG5hbWVfc3BlYyA9ICIiKQoKZ2xvYmFsICAgICAgICAgICAgPC0gY29uZmlnOjpnZXQoY29uZmlnID0gImRlZmF1bHQiKQpsb3JpcyAgICAgICAgICAgICA8LSBjb25maWc6OmdldChjb25maWcgPSAibG9yaXMiKQpiYXJjb2RlX2FsaWdubWVudHM8LSBjb25maWc6OmdldChjb25maWcgPSAiYmFyY29kZV9hbGlnbm1lbnRzIikKc2FtcGxlX3NoZWV0cyAgICAgPC0gY29uZmlnOjpnZXQoY29uZmlnID0gInNhbXBsZV9zaGVldHMiKQpwYXRoICAgICAgICAgICAgICA8LSBjb25maWc6OmdldChjb25maWcgPSBwYXN0ZTAocGFyYW1zJHNhbXBsZXNldCkpCgpzdWJqZWN0X2xpc3QgPC0ga2VlcF9hdChzdWJqZWN0cywgcGFzdGUwKHBhcmFtcyRzYW1wbGVzZXQpKSAlPiUgbGlzdF9mbGF0dGVuKG5hbWVfc3BlYyA9ICJ7aW5uZXJ9IikKCmBgYAoKCiMgSW50cm8KClRoaXMgc2NyaXB0IHN0cmVhbWxpbmVzIGFuZCBzdGFuZGFyZGl6ZXMgb3VyIGhhbmRsaW5nIG9mIHRoZSBzdGVwcyB0YWtlbiB0byByZWFjaCBlYWNoIGRhdGFzZXQgZnJvbSBhbiBvcmlnaW5hbCBzYW1wbGVzZXQuIFlvdSB3aWxsIGV4cG9ydCBzb21lIHN0YW5kYXJkaXplZCBjc3YgYW5kIHRzdiB0YWJsZXMgZm9yIGVhc3kgaW1wb3J0aW5nIGFuZCBtYW5pcHVsYXRpb24gd2l0aCBvdXIgb3RoZXIgd29ya2Zsb3dzLgoKIyMgRmlsZXMgTmVlZGVkCgpUbyBzdGFydCwgeW91IHNob3VsZCBoYXZlIGZvdXIgY2F0ZWdvcmllcyBvZiBjc3YgZmlsZXMgKEkgZG93bmxvYWQgdGhlIGZpcnN0IHRocmVlIGZyb20gd29ya2luZyBnb29nbGUgc3ByZWFkc2hlZXRzLCBhbmQgdGhlIGZvdXJ0aCBjYXRlZ29yeSBpcyBhIHNlcmllcyBvZiBmaWxlcyBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBieSBlYWNoIE1pbklPTiBzZXF1ZW5jaW5nIHJ1bikuIFRob3NlIGZpbGVzIGFuZCB0aGVpciBsaXN0IG9mIGNvbHVtbiBoZWFkZXJzIHRvIGJlIHVzZWQgYXJlIGFzIGZvbGxvd3MgKG5vdGU6IGl0IGlzIGZpbmUgdG8gaGF2ZSBleHRyYSBjb2x1bW5zLCBidXQgeW91IG11c3QgYXQgbGVhc3QgaGF2ZSB0aGVzZSB0byBydW4gdGhlIHNjcmlwdCBhcyBpcyk6ICAKCmBgYHtyLCBlY2hvID0gRkFMU0V9CnBhZ2VfZmx1aWQoCiAgICBhY2NvcmRpb24oCiAgICAgIG9wZW4gPSBGQUxTRSwKICAgICAgYWNjb3JkaW9uX3BhbmVsKAogICAgICAgICJTaG93L0hpZGUgRmlsZSBMaXN0IiwKICAgICAgICB0YWdMaXN0KHRhZ0xpc3QoCiAgICB3aXRoVGFncygKICAgICAgb2woCiAgICAgICAgbGkoIkxpYnJhcmllcyIpLAogICAgICAgICAgdWwoCiAgICAgICAgICAgIGxpKCJTZXF1ZW5jZUlEIiksCiAgICAgICAgICAgIGxpKCJQaXBlbGluZSIpLAogICAgICAgICAgICBsaSgiTGlicmFyeVR1YmUiKSwKICAgICAgICAgICAgbGkoIkxpYnJhcnlCYXJjb2RlIiksCiAgICAgICAgICAgIGxpKCJFeHRyYWN0SUQiKSwKICAgICAgICAgICAgbGkoIkZpbmFsX0xpYnJhcnlfQ29uY2VudHJhdGlvbiIpLAogICAgICAgICAgICBsaSgiVm9sdW1lLkFkZGVkLnRvLlBvb2wuKHVMKSIpLAogICAgICAgICAgICBsaSgiU2VxX0lEIiksCiAgICAgICAgICAgIGxpKCJSdW5fSUQiKSwKICAgICAgICAgICAgbGkoIkxpYnJhcnlUdWJlSUQiKQogICAgICAgICAgKSwKICAgICAgICBsaSgiRXh0cmFjdHMiKSwKICAgICAgICAgIHVsKAogICAgICAgICAgICBsaSgiRXh0cmFjdElEIiksCiAgICAgICAgICAgIGxpKCJFeHRyYWN0RGF0ZSIpLAogICAgICAgICAgICBsaSgiRXh0cmFjdGVkQnkiKSwKICAgICAgICAgICAgbGkoIkV4dHJhY3RUeXBlIiksCiAgICAgICAgICAgIGxpKCJFeHRyYWN0S2l0IiksCiAgICAgICAgICAgIGxpKCJTYW1wbGVJRCIpLAogICAgICAgICAgICBsaSgiRXh0cmFjdENvbmNlbnRyYXRpb24iKSwKICAgICAgICAgICAgbGkoIkV4dHJhY3RCb3giKSwKICAgICAgICAgICAgbGkoIkV4dHJhY3ROb3RlcyIpCiAgICAgICAgICAgICksCiAgICAgICAgbGkoIlNhbXBsZXMiKSwKICAgICAgICAgIHVsKCAgCiAgICAgICAgICAgIGxpKCJTYW1wbGVJRCIpLAogICAgICAgICAgICBsaSgiU2FtcGxlU3ViamVjdCIpLAogICAgICAgICAgICBsaSgiU2FtcGxlRGF0ZSIpLAogICAgICAgICAgICBsaSgiU2FtcGxlQ29sbGVjdGVkQnkiKSwKICAgICAgICAgICAgbGkoIlNhbXBsZU5vdGVzIikKICAgICAgICAgICAgKSwKICAgICAgICBsaSgiQmFyY29kZSBBbGlnbm1lbnRzICgxIGZpbGUgcGVyIFJ1bl9JRCkiKSwKICAgICAgICAgIHVsKAogICAgICAgICAgICBsaSgiYmFyY29kZSIpLAogICAgICAgICAgICBsaSgiYWxpYXMiKSwKICAgICAgICAgICAgbGkoInR5cGUiKSwKICAgICAgICAgICAgbGkoInRhcmdldF91bmNsYXNzaWZpZWQiKSwKICAgICAgICAgICAgbGkoInFjcXVpc2l0aW9uX3J1bl9pZCIpLAogICAgICAgICAgICBsaSgicHJvdG9jb2xfZ3JvdXBfaWQiKSwKICAgICAgICAgICAgbGkoInNhbXBsZV9pZCIpLAogICAgICAgICAgICBsaSgiZmxvd19jZWxsX2lkIiksCiAgICAgICAgICAgIGxpKCJzdGFydGVkIikKICAgICAgICAgICAgKQogICAgICAgICkKICAgICAgKQogICAgKQogICAgKQogICAgKQogICAgKQogICAgKQoKYGBgCgoKIyMgT3RoZXIgQ29uZmlndXJhdGlvbiBTZXR0aW5ncwoKIyMjIFNhbXBsZXNldCBpbiBQYXJhbXMKCllvdSBjYW4gdXNlIHRoZSBzYW1wbGVzZXQgc2V0dGluZyB1bmRlciBwYXJhbXMgaW4gdGhlIGhlYWRlciBvZiB0aGlzIHNjcmlwdCB0byBzZWxlY3Qgd2hpY2ggc2FtcGxlc2V0IHlvdSB3aWxsIGJlIHdvcmtpbmcgd2l0aC4gU28gbG9uZyBhcyB0aGUgc2FtZSBuYW1lIGlzIHVzZWQgY29uc2lzdGVudGx5LCB0aGlzIHNob3VsZCBhdXRvbWF0aWNhbGx5IGZpbHRlciBmb3IgdGhhdCBuYW1lIChlLmcuLCBsb3JpcyBvciBtYXJtb3NldCkuIAoKIyMjIFNlcXVlbmNpbmcgUnVuIExpc3RzCgpUaGUgY29kZSBpbiB0aGUgY2h1bmsgYWJvdmUgYWxzbyBnZW5lcmF0ZWQgYSBsaXN0IG9mIGZvcm1hdHRlZCBjb2RlcyBmb3IgZWFjaCBhdmFpbGFibGUgc2VxdWVuY2luZyBydW4gdG8gZGF0ZSwgc2VwYXJhdGVkIGJ5IHRheGEvc2FtcGxlc2V0cyAoY3VycmVudGx5IGp1c3QgZm9yIGxvcmlzIGFuZCBtYXJtb3NldCkuIE1ha2Ugc3VyZSB0aGUgZW5kIG51bWJlciBtYXRjaGVzIHRoZSBoaWdoZXN0IGludGVnZXIgd2UgaGF2ZSBmb3IgdGhhdCBzYW1wbGVzZXQgdG8gZGF0ZS4KCiMgU2NyaXB0CgojIyBCYXJjb2RlIEFsaWdubWVudHMKCmBgYHtyfQpiYXJjb2RlcyA8LSBpbWFwKHNlcXJ1bnMsIH4gewogIG1hcCgueCwgfiByZWFkX3RhYmxlKGJhcmNvZGVfYWxpZ25tZW50c1tbLnhdXSkgJT4lIG11dGF0ZShzZXFydW4gPSAueCkpIAp9KSAlPiUKICAgIGJpbmRfcm93cygpICU+JQogICAgICAgICAgICAgICAgICAgICAgICBhc190aWJibGUoKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKGJhcmNvZGUgICAgICE9ICJ1bmNsYXNzaWZpZWQiKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKFNlcURhdGVUaW1lICA9IGFzX2RhdGV0aW1lKHN0YXJ0ZWQpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKFNlcURhdGUgICAgICA9IGZsb29yX2RhdGUoU2VxRGF0ZVRpbWUsIHVuaXQgPSAiZGF5IikpICU+JQogICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoU2VxUnVuSUQgICAgID0gc3RyX3JlcGxhY2VfYWxsKHNhbXBsZV9pZCwgInBvb2wxIiwgIlBMMDAxIikpICU+JQogICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKExpYnJhcnlDb2RlICAgID0gc3RyX3NxdWlzaChzdHJfdHJpbShzZXFydW4gICAgICAsICJib3RoIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZsb3dDZWxsU2VyaWFsID0gc3RyX3NxdWlzaChzdHJfdHJpbShmbG93X2NlbGxfaWQsICJib3RoIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShMaWJyYXJ5QmFyY29kZSAgPSBhcy5udW1lcmljKHN0cl9yZW1vdmVfYWxsKGJhcmNvZGUsICIxNlN8YmFyY29kZTB8YmFyY29kZSIpKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChMaWJyYXJ5Q29kZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExpYnJhcnlCYXJjb2RlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZHNfdW5jbGFzc2lmaWVkID0gdGFyZ2V0X3VuY2xhc3NpZmllZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZsb3dDZWxsU2VyaWFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdG9jb2xfZ3JvdXBfaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbG93X2NlbGxfaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZXFSdW5JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNlcURhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZXFEYXRlVGltZSkKCndyaXRlLnRhYmxlKGJhcmNvZGVzLCBiYXJjb2RlX2FsaWdubWVudHMkY29tcGlsYXRpb25zW1twYXN0ZTAocGFyYW1zJHNhbXBsZXNldCldXSwKICAgICAgICAgICAgcm93Lm5hbWVzID0gRiwKICAgICAgICAgICAgc2VwID0gIlx0IikKYGBgCgojIyBTZXF1ZW5jaW5nIFJ1bnMKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzZXFydW4udGJsIDwtIHJlYWRfY3N2KHBhdGgkaW52ZW50b3JpZXMkc2VxcnVucykgJT4lIAogIHJlbmFtZV93aXRoKH5zdHJfcmVwbGFjZV9hbGwoLiwgIlxccyIsICJfIikpICU+JQogIG11dGF0ZShTYW1wbGVTZXQgICAgICAgPSBjYXNlX3doZW4oCiAgICBzdHJfZGV0ZWN0KFBvb2xlZF9MaWJyYXJ5X0NvZGUsICJDTSIpICB+ICJtYXJtb3NldCIsIAogICAgc3RyX2RldGVjdChQb29sZWRfTGlicmFyeV9Db2RlLCAiUEwiKSAgfiAibG9yaXMiLAogICAgc3RyX2RldGVjdChQb29sZWRfTGlicmFyeV9Db2RlLCAiTldSIikgfiAiYmF0cyIsIC5kZWZhdWx0ID0gInVua25vd24iKSwKICAgICAgICAgTGlicmFyeUNvZGUgICAgID0gc3RyX3RvX2xvd2VyKFBvb2xlZF9MaWJyYXJ5X0NvZGUpLAogICAgICAgICBMaWJQcmVwV29ya2Zsb3cgPSBjYXNlX3doZW4oCiAgICAgICAgICAgc3RyX2RldGVjdChLaXQsICJMU0siKSAmIFBpcGVsaW5lID09ICIxNlMiIH4gImxzazE2cyIsCiAgICAgICAgICAgUGlwZWxpbmUgPT0gIkhvc3QgbXRETkEiICAgICAgICAgICAgICAgICAgIH4gImxza2FkYXB0aXZlIiwKICAgICAgICAgICBzdHJfZGV0ZWN0KEtpdCwgIlNRSy0xNlMiKSAmIFBpcGVsaW5lID09ICIxNlMiIH4gInJhcGlkMTZzIiksCiAgICAgICAgIExpYlByZXBEYXRlICAgICA9IG1keShSdW5fRGF0ZSksCiAgICAgICAgIFNlcVJ1bkRhdGUgICAgICA9IHltZChzdHJfcmVtb3ZlX2FsbChzdHJfdHJpbShSdW5fSUQsICJib3RoIiksICJNSU5fMTZffE1JTl8xNi18TUlOX01UXyIpKSkgJT4lCiAgbXV0YXRlKExpYnJhcnlDb2RlICAgICA9IHN0cl9yZXBsYWNlX2FsbChMaWJyYXJ5Q29kZSwgInBsMDB8cGwwIiwgImhkeiIpLAogICAgICAgICBzdHJhbmRzICAgICAgICAgPSAyLAogICAgICAgICBmcmFnbWVudF90eXBlICAgPSBpZl9lbHNlKFBpcGVsaW5lID09ICIxNlMiLCAzLCAxKSwKICAgICAgICAgTGVuZ3RoICAgICAgICAgID0gaWZfZWxzZShQaXBlbGluZSA9PSAiMTZTIiwgMTUwMCwgMTAwMDApLAogICAgICAgICBJbnB1dE1hc3NTdGFydCAgPSBpZl9lbHNlKFBpcGVsaW5lID09ICIxNlMiLCAxMCwgMTAwMCksCiAgICAgICAgIFRlbXBsYXRlVm9sUHJlcCA9IGlmX2Vsc2UoTGliUHJlcFdvcmtmbG93ID09ICJyYXBpZDE2cyIsIDE1LCA0NyksCiAgICAgICAgIFBvb2xTYW1wbGVzICAgICA9IGlmX2Vsc2UoUGlwZWxpbmUgPT0gIjE2UyIsICJ5ZXMiLCAibm8iKSwKICAgICAgICAgSW5wdXRNYXNzRmluYWwgID0gNTAKICAgICAgICAgKSAlPiUKICBmaWx0ZXIoU2FtcGxlU2V0ID09IHBhcmFtcyRzYW1wbGVzZXQpICU+JQogIHNlbGVjdCgKICAgICAgICAgU2FtcGxlU2V0LAogICAgICAgICBMaWJyYXJ5Q29kZSwKICAgICAgICAgTGliUHJlcERhdGUsCiAgICAgICAgIExpYlByZXBXb3JrZmxvdywKICAgICAgICAgTGliUHJlcEtpdCAgICAgID0gS2l0LAogICAgICAgICBGbG93Q2VsbFNlcmlhbCAgPSBGbG93X0NlbGxfSUQsCiAgICAgICAgIEZsb3dDZWxsVHlwZSAgICA9IEZsb3dfQ2VsbF9UeXBlLAogICAgICAgICBGbG9uZ2xlQWRhcHRlciAgPSBGbG9uZ2xlX0FkYXB0ZXIsCiAgICAgICAgIFNlcURldmljZSAgICAgICA9IFNlcXVlbmNlciwKICAgICAgICAgc3RyYW5kcywKICAgICAgICAgZnJhZ21lbnRfdHlwZSwKICAgICAgICAgTGVuZ3RoLAogICAgICAgICBJbnB1dE1hc3NTdGFydCwKICAgICAgICAgVGVtcGxhdGVWb2xQcmVwLAogICAgICAgICBQb29sU2FtcGxlcywKICAgICAgICAgSW5wdXRNYXNzRmluYWwpCmBgYAoKCiMjIFNhbXBsZSBSZWNvcmRzCgpgYGB7ciwgd2FybmluZyA9IEZBTFNFfQpzYW1wbGVzICAgICA8LSByZWFkX2NzdihwYXRoJGludmVudG9yaWVzJGNvbGxlY3Rpb24pICU+JSAKICByZW5hbWVfd2l0aCh+c3RyX3JlcGxhY2VfYWxsKC4sICJcXHMiLCAiXyIpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihzdHJfc3RhcnRzKFNhbXBsZUlELCAiXFx3KyIpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoLVNhbXBsZUJveCkgICU+JQogICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKFNhbXBsZUlEID0gc3RyX3NxdWlzaChzdHJfdHJpbShTYW1wbGVJRCwgImJvdGgiKSkpICU+JSBkaXN0aW5jdCgpICU+JQogICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKENvbGxlY3Rpb25EYXRlICAgICA9IG1keShTYW1wbGVEYXRlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdWJqZWN0ICAgICAgICAgICAgPSBzdHJfc3F1aXNoKHN0cl90cmltKFNhbXBsZVN1YmplY3QpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAua2VlcCA9ICJ1bnVzZWQiKSAlPiUgZGlzdGluY3QoKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShTdWJqX0NlcnRhaW50eSA9IGlmX2Vsc2UoU3ViamVjdCAlaW4lIHN1YmplY3RfbGlzdCwgInllcyIsICJubyIpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShTdWJqZWN0ICAgICAgICA9IHN0cl9yZW1vdmVfYWxsKFN1YmplY3QsICJcXD8iKSkKYGBgCgojIyBETkEgRXh0cmFjdCBSZWNvcmRzCgpXZSB3aWxsIGFsc28gam9pbiB0aGUgcHJldmlvdXMgc2FtcGxlIHJlY29yZHMgdG8gdGhpcyB0YWJsZSBhdCB0aGUgZW5kIG9mIHRoZSBjaHVuay4KCmBgYHtyfQpleHRyYWN0cyA8LSByZWFkX2NzdihwYXRoJGludmVudG9yaWVzJGV4dHJhY3Rpb24pICU+JSAKICByZW5hbWVfd2l0aCh+c3RyX3JlcGxhY2VfYWxsKC4sICJcXHMiLCAiXyIpKSAlPiUKICBmaWx0ZXIoc3RyX3N0YXJ0cyhTYW1wbGVJRCwgIlxcdysiKSkgJT4lCiAgbXV0YXRlKFNhbXBsZUlEICAgICAgICA9IGlmX2Vsc2Uoc3RyX2RldGVjdChTYW1wbGVJRCwgIiNOL0EiKSB8IGlzLm5hKFNhbXBsZUlEKSwgIkV4dHJhY3RDb250cm9sIiwgU2FtcGxlSUQpKSAlPiUKICBtdXRhdGUoU2FtcGxlSUQgPSBzdHJfc3F1aXNoKHN0cl90cmltKFNhbXBsZUlELCAiYm90aCIpKSwKICAgICAgICAgRXh0cmFjdElEPSBzdHJfc3F1aXNoKHN0cl90cmltKEV4dHJhY3RJRCwgImJvdGgiKSksCiAgICAgICAgIEV4dHJhY3REYXRlICAgICAgID0gbWR5KEV4dHJhY3REYXRlKSkgJT4lCiAgbXV0YXRlKEV4dHJhY3RDb25jICAgICAgID0gc3RyX3JlbW92ZV9hbGwoRXh0cmFjdENvbmNlbnRyYXRpb24sICI+IiksIC5rZWVwID0gInVudXNlZCIpICU+JQogIG11dGF0ZShFeHRyYWN0Q29uYyA9IGlmX2Vsc2Uoc3RyX2RldGVjdChFeHRyYWN0Q29uYywgIkhpZ2hlciIpLCAiMTAwIiwgRXh0cmFjdENvbmMpLAogICAgICAgICBFeHRyYWN0Q29uYyA9IGlmX2Vsc2Uoc3RyX2RldGVjdChFeHRyYWN0Q29uYywgIkhJR0hFUiIpLCAiMTAwIiwgRXh0cmFjdENvbmMpLAogICAgICAgICBFeHRyYWN0Q29uYyA9IGlmX2Vsc2UoRXh0cmFjdENvbmMgPT0gIkxPVyIsICIwIiwgRXh0cmFjdENvbmMpLAogICAgICAgICBFeHRyYWN0Q29uYyA9IGlmX2Vsc2UoRXh0cmFjdENvbmMgPT0gIiIsIE5BLCBFeHRyYWN0Q29uYykpICU+JQogIG11dGF0ZShFeHRyYWN0Q29uYyA9IHJvdW5kKGFzLm51bWVyaWMoRXh0cmFjdENvbmMpLCAxKSkgICU+JSBmaWx0ZXIoRXh0cmFjdFR5cGUgPT0gIkROQSIgfCBFeHRyYWN0VHlwZSA9PSAiZG5hIikgJT4lCiAgc2VsZWN0KC1FeHRyYWN0VHlwZSkgJT4lCiAgcmlnaHRfam9pbihzYW1wbGVzKSAlPiUgZGlzdGluY3QoKQpgYGAKCiMjIExpYnJhcmllcyBhbmQgQ29tYmluaW5nIGFsbCBSZWNvcmRzCgoKYGBge3J9CmNvbXBpbGF0aW9uIDwtIHJlYWRfY3N2KHBhdGgkaW52ZW50b3JpZXMkbGlicmFyaWVzLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFLCBjb2xfdHlwZXMgPSBsaXN0KExpYnJhcnlCYXJjb2RlID0gY29sX2NoYXJhY3RlcigpKSkgICU+JSAKICByZW5hbWVfd2l0aCh+c3RyX3JlcGxhY2VfYWxsKC4sICJcXHMiLCAiXyIpKSAlPiUKICByZW5hbWVfd2l0aCh+c3RyX3JlbW92ZV9hbGwoLiwgIlxcKHxcXCkiKSkgJT4lCiAgZmlsdGVyKHN0cl9zdGFydHMoU2VxdWVuY2VJRCwgIlxcdysiKSAmIFNlcV9JRCAhPSAiI04vQSIpICU+JQogIG11dGF0ZShMaWJyYXJ5Q29kZSAgICAgPSBzdHJfdG9fbG93ZXIoU2VxX0lEKSkgJT4lCiAgbXV0YXRlKExpYnJhcnlDb2RlICAgICA9IHN0cl9yZXBsYWNlX2FsbChMaWJyYXJ5Q29kZSwgInBsMDB8cGwwIiAsICJoZHoiKSwKICAgICAgICAgU2FtcFZvbFBvb2wgICAgID0gcm91bmQoYXMubnVtZXJpYyhWb2x1bWVfQWRkZWRfdG9fUG9vbF91TCksIDApLAogICAgICAgICBMaWJyYXJ5QmFyY29kZSAgPSBhcy5udW1lcmljKHN0cl9yZW1vdmVfYWxsKExpYnJhcnlCYXJjb2RlLCAiMTZTfGJhcmNvZGUwfGJhcmNvZGUiKSkpICU+JQogIG11dGF0ZShUb3RhbFBvb2xWb2wgICAgPSBzdW0oU2FtcFZvbFBvb2wpLCAuYnkgPSBMaWJyYXJ5Q29kZSkgJT4lCiAgbXV0YXRlKEJlYWRWb2wgICAgICAgICA9IFRvdGFsUG9vbFZvbCAqIDAuNikgJT4lCiAgc2VsZWN0KFNlcXVlbmNlSUQsCiAgICAgICAgIExpYnJhcnlDb2RlLAogICAgICAgICBMaWJyYXJ5VHViZSwKICAgICAgICAgTGlicmFyeUJhcmNvZGUsCiAgICAgICAgIEV4dHJhY3RJRCwKICAgICAgICAgU2FtcFZvbFBvb2wsCiAgICAgICAgIFRvdGFsUG9vbFZvbCwKICAgICAgICAgQmVhZFZvbCwKICAgICAgICAgQ29uY19RQzIgICAgPSBGaW5hbF9MaWJyYXJ5X0NvbmNlbnRyYXRpb24pICU+JQogIGZ1bGxfam9pbihleHRyYWN0cywgYnkgPSBqb2luX2J5KEV4dHJhY3RJRCkpICU+JSAKICBtdXRhdGUoU2FtcGxlSUQgPSBpZl9lbHNlKGlzLm5hKFNhbXBsZUlEKSAmICFpcy5uYShFeHRyYWN0SUQpLCAiTlRDIiwgU2FtcGxlSUQpKSAlPiUKICBmdWxsX2pvaW4oYmFyY29kZXMsIGJ5ID0gam9pbl9ieShMaWJyYXJ5Q29kZSwgTGlicmFyeUJhcmNvZGUpKSAlPiUKICBzZWxlY3QoLUZsb3dDZWxsU2VyaWFsKSAlPiUKICBsZWZ0X2pvaW4oc2VxcnVuLnRibCwgYnkgPSBqb2luX2J5KExpYnJhcnlDb2RlKSkgJT4lIGRpc3RpbmN0KCkgJT4lCiAgbXV0YXRlKHN0ZXBzX3JlbWFpbmluZyA9IGNhc2Vfd2hlbigKICAgIGlzLm5hKEV4dHJhY3RJRCkgfiAic2FtcGxlIG5vdCBleHRyYWN0ZWQiLAogICAgaXMubmEoU2VxdWVuY2VJRCkgfiAiZXh0cmFjdCBub3Qgc2VxdWVuY2VkIiwKICAgICFpcy5uYShFeHRyYWN0SUQpICYgIWlzLm5hKFNlcXVlbmNlSUQpICYgIWlzLm5hKFNhbXBsZUlEKSB+ICJzYW1wbGUgZXh0cmFjdGVkIGFuZCBzZXF1ZW5jZWQiCiAgKSkgJT4lCiAgcmVsb2NhdGUoU2FtcGxlSUQsIEV4dHJhY3RJRCwgU2VxdWVuY2VJRCwgc3RlcHNfcmVtYWluaW5nKSAlPiUKICBhcnJhbmdlKENvbGxlY3Rpb25EYXRlLCBTdWJqZWN0KQpgYGAKCiMjIyBFeHBvcnRpbmcgYSBTcHJlYWRzaGVldCB3aXRoIFJlY29yZHMKCldlIHdpbGwgdXNlIHRoaXMgc3ByZWFkc2hlZXQgZm9yIGJ1aWxkaW5nIHRoZSBtZXRhZGF0YSB0YWJsZSBidXQgYWxzbyBmb3IgY2FsbGluZyB1cCBzYW1wbGUgaW5mbyBpbiBvdXIgcHJvdG9jb2wgYXBwcy4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp3cml0ZS50YWJsZShjb21waWxhdGlvbiwKICAgICAgICAgICAgcGF0aCRpbnZlbnRvcmllcyRhbGxfc3RhZ2VzLAogICAgICAgICAgICByb3cubmFtZXMgPSBGLAogICAgICAgICAgICBzZXAgPSAiXHQiKQpgYGAKCgojIyBDb3VudGluZyBSZXBsaWNhdGVzCgpgYGB7cn0KY291bnQuZXh0cmFjdHMgICAgPC0gZXh0cmFjdHMgJT4lIHNlbGVjdChFeHRyYWN0SUQsIFNhbXBsZUlEKSAlPiUgZGlzdGluY3QoKSAlPiUgCiAgZ3JvdXBfYnkoU2FtcGxlSUQpICAlPiUgCiAgbXV0YXRlKG5fZG5hX2V4dHJhY3RzID0gbl9kaXN0aW5jdChFeHRyYWN0SUQpKSAlPiUgdW5ncm91cCgpICU+JSBzZWxlY3QoLUV4dHJhY3RJRCkKCmNvdW50LmxpYnJhcmllcyA8LSBjb21waWxhdGlvbiAlPiUgc2VsZWN0KFNlcXVlbmNlSUQsIEV4dHJhY3RJRCwgU2FtcGxlSUQpICU+JSBkaXN0aW5jdCgpICU+JSAKICBncm91cF9ieShFeHRyYWN0SUQpICU+JSBtdXRhdGUobl8xNnNfZXh0cmFjdCA9IG5fZGlzdGluY3QoU2VxdWVuY2VJRCkpICU+JSB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoU2FtcGxlSUQpICAlPiUgbXV0YXRlKG5fMTZzX3NhbXBsZSAgPSBuX2Rpc3RpbmN0KFNlcXVlbmNlSUQpKSAlPiUgdW5ncm91cCgpICU+JSBzZWxlY3QoLVNlcXVlbmNlSUQpCmBgYAoKIyMgRXhwb3J0aW5nIFNhbXBsZVNoZWV0cyBmb3JtYXR0ZWQgZm9yIERvcmFkbwoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNhbXBsZXNoZWV0IDwtIGNvbXBpbGF0aW9uICU+JQogIGZpbHRlcihzdGVwc19yZW1haW5pbmcgPT0gInNhbXBsZSBleHRyYWN0ZWQgYW5kIHNlcXVlbmNlZCIpICU+JQogICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGJhcmNvZGUgPSBpZl9lbHNlKExpYnJhcnlCYXJjb2RlIDwgMTAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcihzdHJfZ2x1ZSgiYmFyY29kZTAiLCAie0xpYnJhcnlCYXJjb2RlfSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5jaGFyYWN0ZXIoc3RyX2dsdWUoImJhcmNvZGUiICwgIntMaWJyYXJ5QmFyY29kZX0iKSkpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChmbG93X2NlbGxfaWQgID0gRmxvd0NlbGxTZXJpYWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwZXJpbWVudF9pZCA9IHByb3RvY29sX2dyb3VwX2lkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtpdCAgICAgICAgICAgPSBMaWJQcmVwS2l0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcmNvZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpYXMgICAgICAgICA9IFNlcXVlbmNlSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VxcnVuICAgICAgICA9IExpYnJhcnlDb2RlKQoKd3JpdGUudGFibGUoc2FtcGxlc2hlZXQsIAogICAgICAgICAgc2FtcGxlX3NoZWV0cyRjb21waWxhdGlvbnNbW3Bhc3RlMChwYXJhbXMkc2FtcGxlc2V0KV1dLAogICAgICAgICAgcm93Lm5hbWVzID0gRiwKICAgICAgICAgIHF1b3RlICAgICA9IEYsCiAgICAgICAgICBzZXAgICAgICAgPSAiLCIpCmBgYAoKIyMjIFNwbGl0dGluZyBTYW1wbGVzaGVldCB0byBJbmRpdmlkdWFsIEZpbGVzIGZvciBFYWNoIFJ1bgoKCmBgYHtyfQpzYW1wbGVzaGVldC5uZXN0ZWQgPC0gc2FtcGxlc2hlZXQgJT4lIG5lc3QoLmJ5ID0gc2VxcnVuKSAlPiUKICBkZWZyYW1lKCkKYGBgCgoKYGBge3IsIGluY2x1ZGUgPSBGQUxTRX0KaW1hcChzYW1wbGVzaGVldC5uZXN0ZWQsIH4gewogIHdyaXRlLnRhYmxlKC54LCAoc2FtcGxlX3NoZWV0c1tbLnldXSksCiAgICAgICAgICByb3cubmFtZXMgPSBGLAogICAgICAgICAgcXVvdGUgICAgID0gRiwKICAgICAgICAgIHNlcCAgICAgICA9ICIsIikKfSkKYGBgCgoKCiMgTmV4dCBTdGVwCgo+Tm93IHlvdSBzaG91bGQgcHJvY2VlZCB0byB0aGUgUmVhZCBQcm9jZXNzaW5nIHdvcmtmbG93IHRvIGJlZ2luIGJhc2VjYWxsaW5nIHRoZSBzZXF1ZW5jaW5nIHJ1bi4K