library(ggbeeswarm)
Loading required package: ggplot2
library(gt)
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
library(tictoc)
source(here::here("src/common_basis.R"))
here() starts at /Users/jiemakel/tyo/disc-analysis
── Attaching core tidyverse packages ────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.2 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ lubridate 1.9.2 ✔ tibble 3.2.1
✔ purrr 1.0.1 ✔ tidyr 1.3.0── Conflicts ──────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errorsRegistered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
centiles <- seq(0,1,by=0.1)
percentiles <- seq(0,1,by=0.01)
Fetal personhood
abortion_tweets_c %>%
count(reply_count) %>%
ggplot(aes(x=reply_count,y=n)) +
geom_point(size=0.5) +
scale_y_log10() +
scale_x_log10() +
theme_hsci_discrete() +
ggtitle("Reply count distribution")

abortion_tweets_c %>%
count(retweet_count) %>%
ggplot(aes(x=retweet_count,y=n)) +
geom_point(size=0.5) +
scale_y_log10() +
scale_x_log10() +
theme_hsci_discrete() +
ggtitle("Retweet count distribution")

abortion_tweets_c %>%
count(like_count) %>%
ggplot(aes(x=like_count,y=n)) +
geom_point(size=0.5) +
scale_y_log10() +
scale_x_log10() +
theme_hsci_discrete() +
ggtitle("Like count distribution")

Incels
incel_threads_c %>%
count(thread_label, posts) %>%
group_by(thread_label) %>%
mutate(prop=n/sum(n)) %>%
ungroup() %>%
ggplot(aes(x=posts,y=prop, color=thread_label)) +
geom_line() +
scale_y_log10() +
scale_x_log10() +
theme_hsci_discrete() +
ggtitle("Thread length distribution by label")

incel_quotes_c %>%
filter(quoted_post_id != 0, quoted_post_id!=quoting_post_id) %>%
count(quoted_post_id) %>%
count(n) %>%
arrange(desc(nn)) %>%
ggplot(aes(x=n,y=nn)) +
geom_point() +
theme_hsci_discrete() +
scale_y_log10() +
ggtitle("Distribution of the number of times a message has been quoted")
Storing counts in nn, as n already present in input
ℹ Use `name = "new_name"` to pick a new name.

incel_quote_tree_a <- incel_quotes_a %>%
inner_join(incel_posts_a %>% select(quoting_post_id=post_id,quoting_post_poster_id=poster_id)) %>%
inner_join(incel_posts_a %>% select(quoted_post_id=post_id,quoted_post_poster_id=poster_id)) %>%
distinct(quoting_post_id,quoted_post_id,quoting_post_poster_id,quoted_post_poster_id) %>%
filter(quoted_post_id!=0,quoted_post_id!=quoting_post_id) %>%
compute_a(name="incel_quote_tree_a", unique_indexes=list(c("quoting_post_id","quoted_post_id"),c("quoted_post_id","quoting_post_id")), temporary=FALSE, overwrite=TRUE)
ancestors_q <- tbl(con,sql('
WITH RECURSIVE ancestors AS (
SELECT quoting_post_id AS descendant_post_id, quoted_post_id AS ancestor_post_id, 1 AS length
FROM incel_quote_tree_a
UNION
SELECT a.descendant_post_id, qt.quoted_post_id AS ancestor_post_id, length+1 AS length
FROM incel_quote_tree_a qt, ancestors a
WHERE qt.quoting_post_id = a.ancestor_post_id
)
SELECT * FROM ancestors'))
descendants_q <- tbl(con,sql('
WITH RECURSIVE descendants AS (
SELECT quoting_post_id AS descendant_post_id, quoted_post_id AS ancestor_post_id, 1 AS length
FROM incel_quote_tree_a
UNION
SELECT qt.quoting_post_id AS descendant_post_id, ancestor_post_id, length+1 AS length
FROM incel_quote_tree_a qt, descendants d
WHERE qt.quoted_post_id = d.descendant_post_id
)
SELECT * FROM descendants'))
tic()
reply_depth_a <- descendants_q %>%
group_by(descendant_post_id) %>%
filter(length==max(length)) %>%
ungroup() %>%
compute_a(name="reply_depth_a",unique_indexes=list(c("descendant_post_id","ancestor_post_id"),c("ancestor_post_id","descendant_post_id")),temporary=FALSE,overwrite=TRUE)
toc()
reply_depth_a %>%
group_by(ancestor_post_id) %>%
filter(length==max(length)) %>%
ungroup() %>%
count(length) %>%
ggplot(aes(x=length,y=n)) +
geom_point(size=0.5) +
scale_y_log10() +
theme_hsci_discrete() +
ggtitle("Quote chain (~discussion) length distribution")

grandparent_q <- tbl(con,sql("
WITH three_posts AS (
SELECT DISTINCT q1.quoting_post_id AS child_post_id, p1.poster_id AS child_user_id, q2.quoting_post_id AS parent_post_id, p2.poster_id AS parent_user_id, q2.quoted_post_id AS grandparent_post_id, p3.poster_id AS grandparent_user_id
FROM incel_quotes_a q1
INNER JOIN incel_quotes_a q2 ON (q1.quoted_post_id=q2.quoting_post_id)
INNER JOIN incel_posts_a p1 ON (q1.quoting_post_id=p1.post_id)
INNER JOIN incel_posts_a p2 ON (q1.quoted_post_id=p2.post_id)
INNER JOIN incel_posts_a p3 ON (q2.quoted_post_id=p3.post_id)
WHERE
q2.quoted_post_id!=0 AND
q2.quoting_post_id!=q2.quoted_post_id
)
SELECT * FROM three_posts"))
incel_quote_triplets_a <- grandparent_q %>%
compute_a("incel_quote_triplets_a", temporary=FALSE, overwrite=TRUE)
ifqtriplets_a <- incel_quote_triplets_a %>%
filter(child_user_id==grandparent_user_id) %>%
compute_a("ifqtriplets_a", temporary=FALSE, overwrite=TRUE, unique_indexes=list(c("child_post_id","grandparent_post_id", "parent_post_id")))
paired_tree_q <- tbl(con,sql("
WITH RECURSIVE ancestors AS (
SELECT child_post_id, child_user_id, parent_post_id AS ancestor_post_id, parent_user_id AS ancestor_user_id, 1 AS length
FROM ifqtriplets_a
UNION
SELECT a.child_post_id, a.child_user_id, t.parent_post_id AS ancestor_post_id, t.parent_user_id AS ancestor_user_id, length + 1 AS length
FROM ancestors a, ifqtriplets_a t
WHERE a.ancestor_post_id = t.child_post_id
)
SELECT * FROM ancestors
"))
tic()
paired_depth_a <- paired_tree_q %>%
group_by(child_post_id) %>%
filter(length==max(length)) %>%
ungroup() %>%
compute_a(name="reply_depth_a",unique_indexes=list(c("child_post_id","ancestor_post_id"),c("ancestor_post_id","child_post_id")),temporary=FALSE,overwrite=TRUE)
toc()
paired_depth_a %>%
group_by(ancestor_post_id) %>%
filter(length==max(length)) %>%
ungroup() %>%
count(length) %>%
ggplot(aes(x=length,y=n)) +
geom_point(size=0.5) +
scale_y_log10() +
theme_hsci_discrete() +
ggtitle("Distribution of the length of discussion between two participants")

Sample threads by their lengths
paired_depth_a %>%
group_by(ancestor_post_id) %>%
filter(length==max(length)) %>%
ungroup() %>%
mutate(bucket=floor(length/10)*10) %>%
group_by(bucket) %>%
slice_sample(n=5) %>%
ungroup() %>%
select(bucket, post_id=child_post_id, length) %>%
inner_join(incel_posts_a, join_by(post_id)) %>%
mutate(url=str_c("https://incels.is/goto/post?id=",str_sub(post_id_str,6))) %>%
select(bucket, length, url) %>%
arrange(bucket, length) %>%
gt(groupname_col = "bucket",rowname_col="length") %>%
fmt_url(url)
LS0tCnRpdGxlOiAiRGlzY3Vzc2lvbiBzdHJ1Y3R1cmUgYW5hbHlzaXMiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQotLS0KCmBgYHtyIHNldHVwfQpsaWJyYXJ5KGdnYmVlc3dhcm0pCmxpYnJhcnkoZ3QpCmxpYnJhcnkodGljdG9jKQpzb3VyY2UoaGVyZTo6aGVyZSgic3JjL2NvbW1vbl9iYXNpcy5SIikpCmBgYAoKYGBge3J9CmNlbnRpbGVzIDwtIHNlcSgwLDEsYnk9MC4xKQpwZXJjZW50aWxlcyA8LSBzZXEoMCwxLGJ5PTAuMDEpCmBgYAoKIyBGZXRhbCBwZXJzb25ob29kCgpgYGB7cn0KYWJvcnRpb25fdHdlZXRzX2MgJT4lIAogIGNvdW50KHJlcGx5X2NvdW50KSAlPiUKICBnZ3Bsb3QoYWVzKHg9cmVwbHlfY291bnQseT1uKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjUpICsKICBzY2FsZV95X2xvZzEwKCkgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBnZ3RpdGxlKCJSZXBseSBjb3VudCBkaXN0cmlidXRpb24iKQpgYGAKCmBgYHtyfQphYm9ydGlvbl90d2VldHNfYyAlPiUgCiAgY291bnQocmV0d2VldF9jb3VudCkgJT4lCiAgZ2dwbG90KGFlcyh4PXJldHdlZXRfY291bnQseT1uKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjUpICsKICBzY2FsZV95X2xvZzEwKCkgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBnZ3RpdGxlKCJSZXR3ZWV0IGNvdW50IGRpc3RyaWJ1dGlvbiIpCmBgYAoKYGBge3J9CmFib3J0aW9uX3R3ZWV0c19jICU+JSAKICBjb3VudChsaWtlX2NvdW50KSAlPiUKICBnZ3Bsb3QoYWVzKHg9bGlrZV9jb3VudCx5PW4pKSArCiAgZ2VvbV9wb2ludChzaXplPTAuNSkgKwogIHNjYWxlX3lfbG9nMTAoKSArCiAgc2NhbGVfeF9sb2cxMCgpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIGdndGl0bGUoIkxpa2UgY291bnQgZGlzdHJpYnV0aW9uIikKYGBgCgojIEluY2VscwoKYGBge3J9CmluY2VsX3RocmVhZHNfYyAlPiUgCiAgY291bnQodGhyZWFkX2xhYmVsLCBwb3N0cykgJT4lCiAgZ3JvdXBfYnkodGhyZWFkX2xhYmVsKSAlPiUKICBtdXRhdGUocHJvcD1uL3N1bShuKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGdncGxvdChhZXMoeD1wb3N0cyx5PXByb3AsIGNvbG9yPXRocmVhZF9sYWJlbCkpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeV9sb2cxMCgpICsKICBzY2FsZV94X2xvZzEwKCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgZ2d0aXRsZSgiVGhyZWFkIGxlbmd0aCBkaXN0cmlidXRpb24gYnkgbGFiZWwiKQpgYGAKCmBgYHtyfQppbmNlbF9xdW90ZXNfYyAlPiUgCiAgZmlsdGVyKHF1b3RlZF9wb3N0X2lkICE9IDAsIHF1b3RlZF9wb3N0X2lkIT1xdW90aW5nX3Bvc3RfaWQpICU+JQogIGNvdW50KHF1b3RlZF9wb3N0X2lkKSAlPiUKICBjb3VudChuKSAlPiUKICBhcnJhbmdlKGRlc2Mobm4pKSAlPiUKICBnZ3Bsb3QoYWVzKHg9bix5PW5uKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgc2NhbGVfeV9sb2cxMCgpICsKICBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2YgdGhlIG51bWJlciBvZiB0aW1lcyBhIG1lc3NhZ2UgaGFzIGJlZW4gcXVvdGVkIikKYGBgCgpgYGB7ciwgZXZhbD1GQUxTRX0KaW5jZWxfcXVvdGVfdHJlZV9hIDwtIGluY2VsX3F1b3Rlc19hICU+JQogIGlubmVyX2pvaW4oaW5jZWxfcG9zdHNfYSAlPiUgc2VsZWN0KHF1b3RpbmdfcG9zdF9pZD1wb3N0X2lkLHF1b3RpbmdfcG9zdF9wb3N0ZXJfaWQ9cG9zdGVyX2lkKSkgJT4lCiAgICBpbm5lcl9qb2luKGluY2VsX3Bvc3RzX2EgJT4lIHNlbGVjdChxdW90ZWRfcG9zdF9pZD1wb3N0X2lkLHF1b3RlZF9wb3N0X3Bvc3Rlcl9pZD1wb3N0ZXJfaWQpKSAlPiUKICBkaXN0aW5jdChxdW90aW5nX3Bvc3RfaWQscXVvdGVkX3Bvc3RfaWQscXVvdGluZ19wb3N0X3Bvc3Rlcl9pZCxxdW90ZWRfcG9zdF9wb3N0ZXJfaWQpICU+JQogIGZpbHRlcihxdW90ZWRfcG9zdF9pZCE9MCxxdW90ZWRfcG9zdF9pZCE9cXVvdGluZ19wb3N0X2lkKSAlPiUKICBjb21wdXRlX2EobmFtZT0iaW5jZWxfcXVvdGVfdHJlZV9hIiwgdW5pcXVlX2luZGV4ZXM9bGlzdChjKCJxdW90aW5nX3Bvc3RfaWQiLCJxdW90ZWRfcG9zdF9pZCIpLGMoInF1b3RlZF9wb3N0X2lkIiwicXVvdGluZ19wb3N0X2lkIikpLCB0ZW1wb3Jhcnk9RkFMU0UsIG92ZXJ3cml0ZT1UUlVFKQpgYGAKCmBgYHtyfQphbmNlc3RvcnNfcSA8LSB0YmwoY29uLHNxbCgnCldJVEggUkVDVVJTSVZFIGFuY2VzdG9ycyBBUyAoIAogIFNFTEVDVCBxdW90aW5nX3Bvc3RfaWQgQVMgZGVzY2VuZGFudF9wb3N0X2lkLCBxdW90ZWRfcG9zdF9pZCBBUyBhbmNlc3Rvcl9wb3N0X2lkLCAxIEFTIGxlbmd0aAogIEZST00gaW5jZWxfcXVvdGVfdHJlZV9hCiAgVU5JT04gCiAgU0VMRUNUIGEuZGVzY2VuZGFudF9wb3N0X2lkLCBxdC5xdW90ZWRfcG9zdF9pZCBBUyBhbmNlc3Rvcl9wb3N0X2lkLCBsZW5ndGgrMSBBUyBsZW5ndGgKICBGUk9NIGluY2VsX3F1b3RlX3RyZWVfYSBxdCwgYW5jZXN0b3JzIGEKICBXSEVSRSBxdC5xdW90aW5nX3Bvc3RfaWQgPSBhLmFuY2VzdG9yX3Bvc3RfaWQKKSAKU0VMRUNUICogRlJPTSBhbmNlc3RvcnMnKSkKZGVzY2VuZGFudHNfcSA8LSB0YmwoY29uLHNxbCgnCldJVEggUkVDVVJTSVZFIGRlc2NlbmRhbnRzIEFTICggCiAgU0VMRUNUIHF1b3RpbmdfcG9zdF9pZCBBUyBkZXNjZW5kYW50X3Bvc3RfaWQsIHF1b3RlZF9wb3N0X2lkIEFTIGFuY2VzdG9yX3Bvc3RfaWQsIDEgQVMgbGVuZ3RoCiAgRlJPTSBpbmNlbF9xdW90ZV90cmVlX2EKICBVTklPTiAKICBTRUxFQ1QgcXQucXVvdGluZ19wb3N0X2lkIEFTIGRlc2NlbmRhbnRfcG9zdF9pZCwgYW5jZXN0b3JfcG9zdF9pZCwgbGVuZ3RoKzEgQVMgbGVuZ3RoCiAgRlJPTSBpbmNlbF9xdW90ZV90cmVlX2EgcXQsIGRlc2NlbmRhbnRzIGQKICBXSEVSRSBxdC5xdW90ZWRfcG9zdF9pZCA9IGQuZGVzY2VuZGFudF9wb3N0X2lkCikgClNFTEVDVCAqIEZST00gZGVzY2VuZGFudHMnKSkKYGBgCgpgYGB7ciwgZXZhbD1GQUxTRX0KdGljKCkKcmVwbHlfZGVwdGhfYSA8LSBkZXNjZW5kYW50c19xICU+JSAKICBncm91cF9ieShkZXNjZW5kYW50X3Bvc3RfaWQpICU+JQogIGZpbHRlcihsZW5ndGg9PW1heChsZW5ndGgpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgY29tcHV0ZV9hKG5hbWU9InJlcGx5X2RlcHRoX2EiLHVuaXF1ZV9pbmRleGVzPWxpc3QoYygiZGVzY2VuZGFudF9wb3N0X2lkIiwiYW5jZXN0b3JfcG9zdF9pZCIpLGMoImFuY2VzdG9yX3Bvc3RfaWQiLCJkZXNjZW5kYW50X3Bvc3RfaWQiKSksdGVtcG9yYXJ5PUZBTFNFLG92ZXJ3cml0ZT1UUlVFKQp0b2MoKQpgYGAKCmBgYHtyfQpyZXBseV9kZXB0aF9hICU+JSAKICBncm91cF9ieShhbmNlc3Rvcl9wb3N0X2lkKSAlPiUKICBmaWx0ZXIobGVuZ3RoPT1tYXgobGVuZ3RoKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGNvdW50KGxlbmd0aCkgJT4lIAogIGdncGxvdChhZXMoeD1sZW5ndGgseT1uKSkgKyAKICBnZW9tX3BvaW50KHNpemU9MC41KSArCiAgc2NhbGVfeV9sb2cxMCgpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIGdndGl0bGUoIlF1b3RlIGNoYWluICh+ZGlzY3Vzc2lvbikgbGVuZ3RoIGRpc3RyaWJ1dGlvbiIpCmBgYAoKYGBge3IsIGV2YWw9RkFMU0V9CmdyYW5kcGFyZW50X3EgPC0gdGJsKGNvbixzcWwoIgpXSVRIIHRocmVlX3Bvc3RzIEFTICgKICBTRUxFQ1QgRElTVElOQ1QgcTEucXVvdGluZ19wb3N0X2lkIEFTIGNoaWxkX3Bvc3RfaWQsIHAxLnBvc3Rlcl9pZCBBUyBjaGlsZF91c2VyX2lkLCBxMi5xdW90aW5nX3Bvc3RfaWQgQVMgcGFyZW50X3Bvc3RfaWQsIHAyLnBvc3Rlcl9pZCBBUyBwYXJlbnRfdXNlcl9pZCwgcTIucXVvdGVkX3Bvc3RfaWQgQVMgZ3JhbmRwYXJlbnRfcG9zdF9pZCwgcDMucG9zdGVyX2lkIEFTIGdyYW5kcGFyZW50X3VzZXJfaWQKICBGUk9NIGluY2VsX3F1b3Rlc19hIHExCiAgSU5ORVIgSk9JTiBpbmNlbF9xdW90ZXNfYSBxMiBPTiAocTEucXVvdGVkX3Bvc3RfaWQ9cTIucXVvdGluZ19wb3N0X2lkKQogIElOTkVSIEpPSU4gaW5jZWxfcG9zdHNfYSBwMSBPTiAocTEucXVvdGluZ19wb3N0X2lkPXAxLnBvc3RfaWQpCiAgSU5ORVIgSk9JTiBpbmNlbF9wb3N0c19hIHAyIE9OIChxMS5xdW90ZWRfcG9zdF9pZD1wMi5wb3N0X2lkKQogIElOTkVSIEpPSU4gaW5jZWxfcG9zdHNfYSBwMyBPTiAocTIucXVvdGVkX3Bvc3RfaWQ9cDMucG9zdF9pZCkKICBXSEVSRQogICBxMi5xdW90ZWRfcG9zdF9pZCE9MCBBTkQKICAgcTIucXVvdGluZ19wb3N0X2lkIT1xMi5xdW90ZWRfcG9zdF9pZAopClNFTEVDVCAqIEZST00gdGhyZWVfcG9zdHMiKSkKaW5jZWxfcXVvdGVfdHJpcGxldHNfYSA8LSBncmFuZHBhcmVudF9xICU+JQogIGNvbXB1dGVfYSgiaW5jZWxfcXVvdGVfdHJpcGxldHNfYSIsIHRlbXBvcmFyeT1GQUxTRSwgb3ZlcndyaXRlPVRSVUUpCmBgYAoKYGBge3IsIGV2YWw9RkFMU0V9CmlmcXRyaXBsZXRzX2EgPC0gaW5jZWxfcXVvdGVfdHJpcGxldHNfYSAlPiUKICBmaWx0ZXIoY2hpbGRfdXNlcl9pZD09Z3JhbmRwYXJlbnRfdXNlcl9pZCkgJT4lCiAgY29tcHV0ZV9hKCJpZnF0cmlwbGV0c19hIiwgdGVtcG9yYXJ5PUZBTFNFLCBvdmVyd3JpdGU9VFJVRSwgdW5pcXVlX2luZGV4ZXM9bGlzdChjKCJjaGlsZF9wb3N0X2lkIiwiZ3JhbmRwYXJlbnRfcG9zdF9pZCIsICJwYXJlbnRfcG9zdF9pZCIpKSkKYGBgCgoKYGBge3IsIGV2YWw9RkFMU0V9CnBhaXJlZF90cmVlX3EgPC0gdGJsKGNvbixzcWwoIgpXSVRIIFJFQ1VSU0lWRSBhbmNlc3RvcnMgQVMgKCAKICBTRUxFQ1QgY2hpbGRfcG9zdF9pZCwgY2hpbGRfdXNlcl9pZCwgcGFyZW50X3Bvc3RfaWQgQVMgYW5jZXN0b3JfcG9zdF9pZCwgcGFyZW50X3VzZXJfaWQgQVMgYW5jZXN0b3JfdXNlcl9pZCwgMSBBUyBsZW5ndGgKICBGUk9NIGlmcXRyaXBsZXRzX2EKICBVTklPTiAKICBTRUxFQ1QgYS5jaGlsZF9wb3N0X2lkLCBhLmNoaWxkX3VzZXJfaWQsIHQucGFyZW50X3Bvc3RfaWQgQVMgYW5jZXN0b3JfcG9zdF9pZCwgdC5wYXJlbnRfdXNlcl9pZCBBUyBhbmNlc3Rvcl91c2VyX2lkLCBsZW5ndGggKyAxIEFTIGxlbmd0aAogIEZST00gYW5jZXN0b3JzIGEsIGlmcXRyaXBsZXRzX2EgdAogIFdIRVJFIGEuYW5jZXN0b3JfcG9zdF9pZCA9IHQuY2hpbGRfcG9zdF9pZAopClNFTEVDVCAqIEZST00gYW5jZXN0b3JzCiIpKQp0aWMoKQpwYWlyZWRfZGVwdGhfYSA8LSBwYWlyZWRfdHJlZV9xICU+JSAKICBncm91cF9ieShjaGlsZF9wb3N0X2lkKSAlPiUKICBmaWx0ZXIobGVuZ3RoPT1tYXgobGVuZ3RoKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGNvbXB1dGVfYShuYW1lPSJyZXBseV9kZXB0aF9hIix1bmlxdWVfaW5kZXhlcz1saXN0KGMoImNoaWxkX3Bvc3RfaWQiLCJhbmNlc3Rvcl9wb3N0X2lkIiksYygiYW5jZXN0b3JfcG9zdF9pZCIsImNoaWxkX3Bvc3RfaWQiKSksdGVtcG9yYXJ5PUZBTFNFLG92ZXJ3cml0ZT1UUlVFKQp0b2MoKQpgYGAKCmBgYHtyfQpwYWlyZWRfZGVwdGhfYSAlPiUgCiAgZ3JvdXBfYnkoYW5jZXN0b3JfcG9zdF9pZCkgJT4lCiAgZmlsdGVyKGxlbmd0aD09bWF4KGxlbmd0aCkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBjb3VudChsZW5ndGgpICU+JSAKICBnZ3Bsb3QoYWVzKHg9bGVuZ3RoLHk9bikpICsgCiAgZ2VvbV9wb2ludChzaXplPTAuNSkgKwogIHNjYWxlX3lfbG9nMTAoKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2YgdGhlIGxlbmd0aCBvZiBkaXNjdXNzaW9uIGJldHdlZW4gdHdvIHBhcnRpY2lwYW50cyIpCmBgYAoKIyMgU2FtcGxlIHRocmVhZHMgYnkgdGhlaXIgbGVuZ3RocwoKYGBge3J9CnBhaXJlZF9kZXB0aF9hICU+JSAKICBncm91cF9ieShhbmNlc3Rvcl9wb3N0X2lkKSAlPiUKICBmaWx0ZXIobGVuZ3RoPT1tYXgobGVuZ3RoKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShidWNrZXQ9Zmxvb3IobGVuZ3RoLzEwKSoxMCkgJT4lCiAgZ3JvdXBfYnkoYnVja2V0KSAlPiUKICBzbGljZV9zYW1wbGUobj01KSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgc2VsZWN0KGJ1Y2tldCwgcG9zdF9pZD1jaGlsZF9wb3N0X2lkLCBsZW5ndGgpICU+JQogIGlubmVyX2pvaW4oaW5jZWxfcG9zdHNfYSwgam9pbl9ieShwb3N0X2lkKSkgJT4lCiAgbXV0YXRlKHVybD1zdHJfYygiaHR0cHM6Ly9pbmNlbHMuaXMvZ290by9wb3N0P2lkPSIsc3RyX3N1Yihwb3N0X2lkX3N0ciw2KSkpICU+JQogIHNlbGVjdChidWNrZXQsIGxlbmd0aCwgdXJsKSAlPiUKICBhcnJhbmdlKGJ1Y2tldCwgbGVuZ3RoKSAlPiUKICBndChncm91cG5hbWVfY29sID0gImJ1Y2tldCIscm93bmFtZV9jb2w9Imxlbmd0aCIpICU+JQogIGZtdF91cmwodXJsKQpgYGAKCg==