Exclusions
d <- upData(d,
subjid = 1 : n,
pend = rbinom(n, 1, .1),
e1 = rbinom(n, 1, .02),
e2 = rbinom(n, 1, .02),
e3 = rbinom(n, 1, .02),
e4 = ifelse(runif(n) < 0.25, NA, rbinom(n, 1, .10)),
tested = rbinom(n, 1, .75),
e5 = ifelse(tested, rbinom(n, 1, .04), NA),
e6 = rbinom(n, 1, .02),
e7 = rbinom(n, 1, .02),
rndz = rbinom(n, 1, .75),
labels=c(e1='Prior MI', e2='History of Asthma',
e3='History of Upper GI Bleeding',
e4='No Significant CAD', e5='Inadequate Renal Function',
e6='Pneumonia within 6 weeks', e7='Prior cardiac surgery'),
print=FALSE)
erd <- data.frame(subjid = 1 : 50,
loc = sample(c('gastric', 'lung', 'trachea'), 50, TRUE))
# To check warning messages, greportOption denom does not match pend, e1-e7
exReport(~ pending(pend) + e1 + e2 + e3 + e4 + e5 + e6 + e7 +
randomized(rndz) + id(subjid) + cond(e5, 'Tested', tested),
erdata = erd,
whenapp= c(e4='CCTA done'), data=d) #, hc=3.75, h=4)
∟ Cumulative exclusions
Cumulative number of exclusions (\(y\)-axis) and number of additional exclusions after exclusions placed higher, for participants not actually randomized. Exclusions are sorted by descending number of incremental exclusions. 550 participants were enrolled, 12 non-excluded participants are pending randomization, and 20 participants were excluded. 371 participants were randomized. Note: Number of observations (500) does not equal number officially enrolled (550). Note: Number of enrolled (488) minus number excluded (20) does not match official number randomized (270).
◫ Exclusions
Incremental exclusions are those in addition to exclusions in earlier rows. Marginal exclusions are numbers of participants excluded for the indicated reason whether or not she was excluded for other reasons. The three Fractions are based on incremental exclusions.
Exclusions
|
Incremental Exclusions
|
Marginal Exclusions
|
Fraction of Enrolled
|
Fraction of Exclusions
|
Fraction Remaining
|
|
No Significant CAD (CCTA done, n=386)
|
6
|
6
|
0.012
|
0.30
|
0.988
|
Prior Cardiac Surgery
|
4
|
4
|
0.008
|
0.20
|
0.980
|
Inadequate Renal Function / 373
|
3
|
3
|
0.006
|
0.15
|
0.973
|
3⁄367 = 0.008 of Tested
|
Prior MI
|
2
|
3
|
0.004
|
0.10
|
0.969
|
History of Upper GI Bleeding
|
2
|
2
|
0.004
|
0.10
|
0.965
|
Pneumonia within 6 Weeks
|
2
|
2
|
0.004
|
0.10
|
0.961
|
History of Asthma
|
1
|
1
|
0.002
|
0.05
|
0.959
|
Total
|
20
|
|
0.041
|
1.00
|
0.959
|
◫ Exclusions in randomized participants
Frequency of exclusions for participants marked as randomized
Exclusion
|
Frequency
|
Prior MI
|
8
|
History of Asthma
|
7
|
History of Upper GI Bleeding
|
7
|
No Significant CAD
|
42
|
Inadequate Renal Function
|
15
|
Pneumonia within 6 Weeks
|
7
|
Prior Cardiac Surgery
|
8
|
Total Partcipants with Any Exclusion
|
84
|
▼Click arrow at left to show participant IDs:
Exclusion
|
IDs
|
Prior MI
|
87, 127, 209, 250, 274, 321, 442, 448
|
History of Asthma
|
17, 62, 68, 121, 122, 127, 462
|
History of Upper GI Bleeding
|
64, 202, 307, 310, 330, 449, 462
|
No Significant CAD
|
6, 7, 10, 22, 27, 37, 39, 53, 67, 112, 113, 118, 122, 143, 145, 175, 179, 184, 226, 227, 249, 255, 278, 282, 289, 291, 297, 321, 330, 344, 359, 361, 371, 377, 385, 402, 438, 451, 455, 471, 482, 499
|
Inadequate Renal Function
|
24, 37, 46, 70, 88, 154, 183, 194, 226, 234, 242, 292, 295, 322, 484
|
Pneumonia within 6 Weeks
|
29, 166, 230, 235, 313, 447, 473
|
Prior Cardiac Surgery
|
171, 191, 344, 377, 388, 389, 477, 482
|
▼Click arrow at left to see more information about those participants:
subjid
|
loc
|
6
|
gastric
|
7
|
gastric
|
10
|
trachea
|
17
|
lung
|
22
|
trachea
|
24
|
gastric
|
27
|
lung
|
29
|
trachea
|
37
|
trachea
|
39
|
lung
|
46
|
gastric
|
# Show exclusions in original variable order
if(FALSE) exReport(~ pending(pend) + e1 + e2 + e3 + e4 + e5 + e6 + e7 +
randomized(rndz) + id(subjid) + cond(e5, 'Tested', tested),
erdata=erd,
whenapp=c(e4='CCTA done'), data=d, #hc=3.75, h=4,
sort=FALSE, app=FALSE)
Adverse Events
For this example, the denominators for the two treatments in the pop-up needles will be incorrect because the dataset did not have subject IDs.
# Original source of aeanonym: HH package
# aeanonym <- read.table(hh("datasets/aedotplot.dat"), header=TRUE, sep=",")
# Modified to remove denominators from data and to generate raw data
# (one record per event per subject)
ae <-
structure(list(RAND = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L,
2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L,
2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L,
2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L,
2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), .Label = c("a",
"b"), class = "factor"), PREF = structure(c(12L, 12L,
18L, 18L, 26L, 26L, 33L, 33L, 5L, 5L, 27L, 27L, 6L, 6L, 15L,
15L, 22L, 22L, 23L, 23L, 31L, 31L, 17L, 17L, 2L, 2L, 3L, 3L,
13L, 13L, 25L, 25L, 28L, 28L, 14L, 14L, 4L, 4L, 8L, 8L, 19L,
19L, 21L, 21L, 29L, 29L, 10L, 10L, 20L, 20L, 16L, 16L, 32L, 32L,
11L, 11L, 1L, 1L, 30L, 30L, 24L, 24L, 9L, 9L, 7L, 7L),
.Label = tolower(c("ABDOMINAL PAIN",
"ANOREXIA", "ARTHRALGIA", "BACK PAIN", "BRONCHITIS", "CHEST PAIN",
"CHRONIC OBSTRUCTIVE AIRWAY", "COUGHING", "DIARRHEA", "DIZZINESS",
"DYSPEPSIA", "DYSPNEA", "FATIGUE", "FLATULENCE", "GASTROESOPHAGEAL REFLUX",
"HEADACHE", "HEMATURIA", "HYPERKALEMIA", "INFECTION VIRAL", "INJURY",
"INSOMNIA", "MELENA", "MYALGIA", "NAUSEA", "PAIN", "RASH", "RESPIRATORY DISORDER",
"RHINITIS", "SINUSITIS", "UPPER RESP TRACT INFECTION", "URINARY TRACT INFECTION",
"VOMITING", "WEIGHT DECREASE")), class = "factor"), SAE = c(15L,
9L, 4L, 9L, 4L, 9L, 2L, 9L, 8L, 11L, 4L, 11L, 9L, 12L, 5L, 12L,
7L, 12L, 6L, 12L, 6L, 12L, 2L, 14L, 2L, 15L, 1L, 15L, 4L, 16L,
4L, 17L, 11L, 17L, 6L, 20L, 10L, 23L, 13L, 26L, 12L, 26L, 4L,
26L, 13L, 28L, 9L, 29L, 12L, 30L, 14L, 36L, 6L, 37L, 8L, 42L,
20L, 61L, 33L, 68L, 10L, 82L, 23L, 90L, 76L, 95L)), .Names = c("RAND",
"PREF", "SAE"), class = "data.frame", row.names = c(NA,
-66L))
subs <- rep(1 : nrow(ae), ae$SAE)
ae <- ae[subs, c('RAND', 'PREF')]
names(ae) <- c('treat', 'event')
label(ae$treat) <- 'Treatment'
denom <- c(enrolled=1000,
randomized=400,
a=212, b=188)
sethreportOption(tx.var='treat', denom=denom)
eReport(event ~ treat, data=ae, minincidence=.05)
∟ Proportion of adverse events by Treatment
Proportion of adverse events by Treatment sorted by descending risk difference. 3 events with less than 0.05 incidence in all groups are not shown (Hyperkalemia, Rash, Weight Decrease).
|
Category
|
N
|
Used
|
Enrolled
|
1000
|
400
|
Randomized
|
400
|
400
|
A
|
212
|
212
|
B
|
188
|
188
|
|
|
LS0tCnRpdGxlOiAiRFNNQiBSZXBvcnQgZm9yIEVYQU1QTEUgVHJpYWwiCmF1dGhvcjogIkZFIEhhcnJlbGwiCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCiAgaHRtdWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQpgYGB7ciBzZXR1cCxyZXN1bHRzPSdoaWRlJ30KcmVxdWlyZShIbWlzYykKcmVxdWlyZShwbG90bHkpCnJlcXVpcmUoaHRtbFRhYmxlKQpzb3VyY2UoJ34vUi9ocmVwb3J0L1IvTWlzYy5yJykKc291cmNlKCd+L1IvaHJlcG9ydC9SL2FjY3J1YWxSZXBvcnQucicpCnNvdXJjZSgnfi9SL2hyZXBvcnQvUi9leFJlcG9ydC5yJykKc291cmNlKCd+L1IvaHJlcG9ydC9SL2VSZXBvcnQucicpCm11IDwtIG1hcmt1cFNwZWNzJGh0bWwgICAjIGluIEhtaXNjIC0gSFRNTCBtYXJrdXBzCmZyYWMgPC0gbXUkZnJhYwpgYGAKYGBge3Igc2V0dXAyfQptdSRzdHlsZXMoKSAgICAgICAgICAgICAgIyBkZWZpbmUgSFRNTCBzdHlsZXMsIGZ1bmN0aW9ucwpgYGAKPCEtLSBNYXkgbmVlZCB0byBydW4gdGhlIGZvbGxvd2luZyBzeXN0ZW0gY29tbWFuZHMgb25lIHRpbWU6CmNkIC91c3IvbG9jYWwvYmluCnN1ZG8gbG4gLXMgL3Vzci9saWIvcnN0dWRpby9iaW4vcGFuZG9jL3BhbmRvYy1jaXRlcHJvYwotLT4KCmBgYHtyIGdlbmRhdGF9CiMjIEdlbmVyYXRlIHRlc3QgZGF0YQpzZXQuc2VlZCgxKQpuIDwtIDUwMApkIDwtIGRhdGEuZnJhbWUoY291bnRyeT1zYW1wbGUoYygnVVMnLCAnQ2FuYWRhJywgJ1NwYWluJywgJ0ZyYW5jZScsCiAgICAgICAgICAgICAgICAgICdHZXJtYW55JyksIG4sIFRSVUUpLAogICAgICAgICAgICAgICAgc2l0ZT1zYW1wbGUoMToxMCwgbiwgVFJVRSkpCmQkc2l0ZSAgIDwtIHBhc3RlKHN1YnN0cmluZyhkJGNvdW50cnksIDEsIDIpLCBkJHNpdGUsIHNlcD0nJykKZCRyZWdpb24gPC0gZmFjdG9yKGlmZWxzZShkJGNvdW50cnkgJWluJSBjKCdVUycsICdDYW5hZGEnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAnTm9ydGggQW1lcmljYScsICdFdXJvcGUnKSkKCmQgPC0gdXBEYXRhKGQsIGVkYXRlID0gYXMuRGF0ZSgnMjAwNS0wMS0wMScpICsKICAgICAgICAgICAgcm91bmQocmdhbW1hKG4sIDIsIC4wMSkpIC0gNjAwICogKGNvdW50cnkgPT0gJ1VTJyksCiAgICAgICAgICAgIHJkYXRlID0gZWRhdGUgKyByb3VuZChydW5pZihuLCAxLCAzMCkpLCBwcmludD1GQUxTRSkKZCRyZGF0ZVtydW5pZihucm93KGQpKSA8IDAuNV0gPC0gTkEgICMgbm9uLXJhbmRvbWl6ZWQgc3ViamVjdHMgKQoKIyB3aXRoKGQsIHRhYmxlKHJlZ2lvbiwgY291bnRyeSkpCgojIEZvciBVUyBtYW51YWxseSBjb21wdXRlICMgcmFuZG9taXplZCBwZXIgbW9udGgKdXMgICA8LSBzdWJzZXQoZCwgY291bnRyeSA9PSAnVVMnKQpzaXRlIDwtIHVzJHNpdGUKZWQgICA8LSB1cyRlZGF0ZQpyZCAgIDwtIHVzJHJkYXRlCm1vbnRocyA8LSBkaWZmdGltZShhcy5EYXRlKCcyMDA3LTEyLTMxJyksIGVkLCB1bml0cz0nZGF5cycpIC8KICAoMzY1LjI1IC8gMTIpCm0gPC0gbWF4KG1vbnRocykKYSA8LSBzdW0oIWlzLm5hKHJkKSkgLyBhcy5udW1lcmljKG0pICAgIyAuODU0NTc3NCAoYWdyZWVzIHdpdGggY2hhcnQpCiMgQ29tcHV0ZSBtYXhpbXVtIG1vbnRocyBlbGFwc2VkIGZvciBlYWNoIHNpdGUgdGhlbiBzdW0gb3ZlciBzaXRlcwptYXhwZXJzaXRlIDwtIHRhcHBseShtb250aHMsIHNpdGUsIG1heCkKYiA8LSBzdW0oIWlzLm5hKHJkKSkgLyBzdW0obWF4cGVyc2l0ZSkKIyMgMC4wODY0NDI5ID0gNDcgLyA1NDMuNjcxNSBjaGFydDogLjA4NjQ1IChyb3VuZGVkKQoKIyMgU3VwcG9zZSB0aGVyZSBhcmUgbW9yZSBzdWJqZWN0cyBlbnJvbGxlZCBhbmQgcmFuZG9taXplZCB0aGFuIHJlYWxseQojIyBtYWRlIHRoZWlyIHdheSBpbnRvIHRoZSBkYXRhc2V0CmRlbm9tIDwtIGMoZW5yb2xsZWQ9bnJvdyhkKSAqIDEuMSwKICAgICAgICAgICByYW5kb21pemVkPXN1bSghaXMubmEoZCRyZGF0ZSkpICsgMTApCgpzZXRocmVwb3J0T3B0aW9uKHR4LnZhcj0ndHJlYXQnLCBkZW5vbT1kZW5vbSkKIyMgSW5pdGlhbGl6ZSBmaWxlIHRvIGhvbGQgYXBwZW5kaXggaW5mb3JtYXRpb24gc3VjaCBhcyBzdWJqZWN0IElEcwojIyBzbyBhbGwgbGF0ZXIgd3JpdGluZyB0byB0aGlzIGZpbGUgY2FuIHVzZSBhcHBlbmQ9VFJVRQphcHBmaWxlIDwtIGdldGhyZXBvcnRPcHRpb24oJ2FwcGZpbGUnKQpjYXQoJycsIGZpbGU9YXBwZmlsZSkKYGBgIAoKIyBJbnRyb2R1Y3Rpb24KIyMgSW50ZXJhY3RpdmUgR3JhcGhzCk1vc3Qgb2YgdGhlIGdyYXBocyBwcm9kdWNlZCBoZXJlIGFyZSBzZW1pLWludGVyYWN0aXZlLiAgT25lIGNhbiBob3ZlciBvdmVyIGVsZW1lbnRzIG9mIGdyYXBocyB3aXRoIHRoZSBtb3VzZSB0byBoYXZlIGRldGFpbGVkIGluZm9ybWF0aW9uIHBvcCB1cC4KCiMjIEZpZ3VyZSBDYXB0aW9ucwpOZWVkbGVzIHJlcHJlc2VudCB0aGUgZnJhY3Rpb24gb2Ygb2JzZXJ2YXRpb25zIHVzZWQgaW4gdGhlIGN1cnJlbnQKYW5hbHlzaXMuICBUaGUgZmlyc3QgbmVlZGxlIChyZWQpIHNob3dzIHRoZSBmcmFjdGlvbiBvZiBlbnJvbGxlZApwYXRpZW50cyB1c2VkLiAgSWYgcmFuZG9taXphdGlvbiB3YXMgdGFrZW4gaW50byBhY2NvdW50LCBhIHNlY29uZApuZWVkbGUgKGdyZWVuKSByZXByZXNlbnRzIHRoZSBmcmFjdGlvbiBvZiByYW5kb21pemVkIHN1YmplY3RzIGluY2x1ZGVkCmluIHRoZSBhbmFseXNpcy4gIFdoZW4gdGhlIGFuYWx5c2VzIGNvbnNpZGVyIHRyZWF0bWVudCBhc3NpZ25tZW50LCB0d28KbW9yZSBuZWVkbGVzIG1heSBiZSBhZGRlZCB0byB0aGUgZGlzcGxheSwgc2hvd2luZywgcmVzcGVjdGl2ZWx5LCB0aGUKZnJhY3Rpb24gb2Ygc3ViamVjdHMgcmFuZG9taXplZCB0byB0cmVhdG1lbnQgQSB1c2VkIGluIHRoZSBhbmFseXNpcwphbmQgdGhlIGZyYWN0aW9uIG9mIHN1YmplY3RzIG9uIHRyZWF0bWVudCBCIHdobyB3ZXJlIGFuYWx5emVkLiAgVGhlCmNvbG9ycyBvZiB0aGVzZSBsYXN0IHR3byBuZWVkbGVzIGFyZSB0aGUgY29sb3JzIHVzZWQgZm9yIHRoZSB0d28KdHJlYXRtZW50cyB0aHJvdWdob3V0IHRoZSByZXBvcnQuICBUaGUgZm9sbG93aW5nIHRhYmxlIHNob3dzIHNvbWUKZXhhbXBsZXMuICBgZE5lZWRsZWAgdXNlcyBjb2xvcnMgaW4gYHNldGhyZXBvcnRPcHRpb24odHguY29sPSwgZXIuY29sPSlgLgoKYGBge3IgbmVlZGxlZGVmc30KIyBTdG9yZSB1c2luZyBzaG9ydCB2YXJpYWJsZSBuYW1lcyBzbyBSbWFya2Rvd24gdGFibGUgY29sdW1uCiMgd2lkdGggd2lsbCBub3QgYmUgd2lkZXIgdGhhbiBhY3R1YWxseSBuZWVkZWQKZDEgPC0gZE5lZWRsZSgxKQpkMiA8LSBkTmVlZGxlKCgzOjQpLzQpCmQzIDwtIGROZWVkbGUoKDE6MikvNCkKZDQgPC0gZE5lZWRsZShjKDEsMiwzLDEpLzQpCmBgYAoKfFNpZ25wb3N0ICAgfCBJbnRlcnByZXRhdGlvbiB8CnwtLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKfCBgciBkMWAgfCBBbGwgZW5yb2xsZWQgc3ViamVjdHMgYW5hbHl6ZWQsIHJhbmRvbWl6YXRpb24gbm90IGNvbnNpZGVyZWR8CnwgYHIgZDJgIHwgQW5hbHlzaXMgdXNlcyBgciBmcmFjKDMsNClgIG9mIGVucm9sbGVkIHN1YmplY3RzLCBhbmQgYWxsIHJhbmRvbWl6ZWQgc3ViamVjdHN8CnwgYHIgZDNgIHwgQW5hbHlzaXMgdXNlcyBgciBmcmFjKDEsNClgIG9mIGVucm9sbGVkIHN1YmplY3RzLCBhbmQgYHIgZnJhYygxLDIpYCBvZiByYW5kb21pemVkIHN1YmplY3RzfAp8IGByIGQ0YCB8IFNhbWUgYXMgcHJldmlvdXMgZXhhbXBsZSwgYW5kIGluIGFkZGl0aW9uIHRoZSBhbmFseXNpcyB1dGlsaXplZCB0cmVhdG1lbnQgYXNzaWdubWVudCwgYW5hbHl6aW5nIGByIGZyYWMoMyw0KWAgb2YgdGhvc2UgcmFuZG9taXplZCB0byBBIGFuZCBgciBmcmFjKDEsNClgIG9mIHRob3NlIHJhbmRvbWl6ZWQgdG8gQnwKCiMgRXh0ZW5kZWQgQm94IFBsb3RzCkZvciBkZXBpY3RpbmcgZGlzdHJpYnV0aW9ucyBvZiBjb250aW51b3VzIHZhcmlhYmxlcywgbWFueSBvZiB0aGUKZm9sbG93aW5nIGRpc3BsYXlzIHVzZSBleHRlbmRlZCBib3ggcGxvdHMsIGFsc28gY2FsbGVkCmJveC0tcGVyY2VudGlsZSBwbG90cy4gIEEgcHJvdG90eXBlLCB3aXRoIGV4cGxhbmF0aW9ucywgaXMgYmVsb3cuCmBgYHtyIGJwcGx0fQpicHBsdCgpCmBgYAoKIyMgRG90IENoYXJ0cwpEb3QgY2hhcnRzIGFyZSB1c2VkIHRvIHByZXNlbnQgc3RyYXRpZmllZCBwcm9wb3J0aW9ucy4gIEluIHRoZXNlCmNoYXJ0cyB0aGUgYXJlYSBvZiB0aGUgc3ltYm9scyBpcyBwcm9wb3J0aW9uYWwgdG8gdGhlIHNxdWFyZSByb290IG9mCnRoZSBkZW5vbWluYXRvci4gIFRoZSBsZWdlbmQgc2hvd3MgcmVwcmVzZW50YXRpdmUgZGVub21pbmF0b3JzIGFuZAp0aGVpciBjb3JyZXNwb25kaW5nIHN5bWJvbCBhcmVhcywgdXNpbmcgZGVub21pbmF0b3JzIHRoYXQgYWN0dWFsbHkKb2NjdXJyZWQgaW4gdGhlIGRhdGEgYW5kIGV4dGVuZGVkIGZyb20gdGhlIG1pbmltdW0gb2JzZXJ2ZWQgdG8gdGhlCm1heGltdW0gb2JzZXJ2ZWQgc2FtcGxlIHNpemUuPz8/CgoKIyMgU3Vydml2YWwgQ3VydmVzCkdyYXBocyBjb250YWluaW5nIHBhaXJzIG9mIEthcGxhbi1NZWllciBzdXJ2aXZhbCBjdXJ2ZXMgc2hvdyBhIHNoYWRlZApyZWdpb24gY2VudGVyZWQgYXQgdGhlIG1pZHBvaW50IG9mIHRoZSB0d28gc3Vydml2YWwgZXN0aW1hdGVzIGFuZApoYXZpbmcgYSBoZWlnaHQgZXF1YWwgdG8gdGhlIGhhbGYtd2lkdGggb2YgdGhlIGFwcHJveGltYXRlIDAuOTUgcG9pbnR3aXNlCmNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSBkaWZmZXJlbmNlIG9mIHRoZSB0d28gc3Vydml2YWwKcHJvYmFiaWxpdGllcy4gIFRpbWUgcG9pbnRzIGF0IHdoaWNoIHRoZSB0d28gc3Vydml2YWwgZXN0aW1hdGVzIGRvIG5vdAp0b3VjaCB0aGUgc2hhZGVkIHJlZ2lvbiBkZW5vdGUgYXBwcm94aW1hdGVseSBzaWduaWZpY2FudGx5IGRpZmZlcmVudApzdXJ2aXZhbCBlc3RpbWF0ZXMsIHdpdGhvdXQgYW55IG11bHRpcGxpY2l0eSBjb3JyZWN0aW9uLgoKIyBBY2NydWFsCgpgYGB7ciBhY2NydWFsLHJlc3VsdHM9J2FzaXMnfQphY2NydWFsUmVwb3J0KGVucm9sbChlZGF0ZSkgKyByYW5kb21pemUocmRhdGUpIH4KICAgICAgICAgICAgICByZWdpb24ocmVnaW9uKSArIGNvdW50cnkoY291bnRyeSkgKyBzaXRlKHNpdGUpLAogICAgICAgICAgICAgIGRhdGE9ZCwKICAgICAgICAgICAgICBkYXRlUmFuZ2U9YygnMjAwNS0wMS0wMScsICcyMDA3LTEyLTMxJyksCiAgICAgICAgICAgICAgdGFyZ2V0Tj0KICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoZWRhdGU9Yyg1MDAsIDEwMDApLCByZGF0ZT1jKDI1MCwgNTAwKSksCiAgICAgICAgICAgICAgdGFyZ2V0RGF0ZT1jKCcyMDA2LTAxLTAxJywgJzIwMDctMTItMzEnKSwKICAgICAgICAgICAgICBjbG9zZURhdGU9JzIwMDctMTItMzEnKQpgYGAKCiMgRXhjbHVzaW9ucwpgYGB7ciBleGNsLHJlc3VsdHM9J2FzaXMnfQpkIDwtIHVwRGF0YShkLAogICAgICAgICAgICBzdWJqaWQgPSAxIDogbiwKICAgICAgICAgICAgcGVuZCAgID0gcmJpbm9tKG4sIDEsIC4xKSwKICAgICAgICAgICAgZTEgICAgID0gcmJpbm9tKG4sIDEsIC4wMiksCiAgICAgICAgICAgIGUyICAgICA9IHJiaW5vbShuLCAxLCAuMDIpLAogICAgICAgICAgICBlMyAgICAgPSByYmlub20obiwgMSwgLjAyKSwKICAgICAgICAgICAgZTQgICAgID0gaWZlbHNlKHJ1bmlmKG4pIDwgMC4yNSwgTkEsIHJiaW5vbShuLCAxLCAuMTApKSwKICAgICAgICAgICAgdGVzdGVkID0gcmJpbm9tKG4sIDEsIC43NSksCiAgICAgICAgICAgIGU1ICAgICA9IGlmZWxzZSh0ZXN0ZWQsIHJiaW5vbShuLCAxLCAuMDQpLCBOQSksCiAgICAgICAgICAgIGU2ICAgICA9IHJiaW5vbShuLCAxLCAuMDIpLAogICAgICAgICAgICBlNyAgICAgPSByYmlub20obiwgMSwgLjAyKSwKICAgICAgICAgICAgcm5keiAgID0gcmJpbm9tKG4sIDEsIC43NSksCiAgICAgICAgICAgIGxhYmVscz1jKGUxPSdQcmlvciBNSScsIGUyPSdIaXN0b3J5IG9mIEFzdGhtYScsCiAgICAgICAgICAgICAgZTM9J0hpc3Rvcnkgb2YgVXBwZXIgR0kgQmxlZWRpbmcnLAogICAgICAgICAgICAgIGU0PSdObyBTaWduaWZpY2FudCBDQUQnLCBlNT0nSW5hZGVxdWF0ZSBSZW5hbCBGdW5jdGlvbicsCiAgICAgICAgICAgICAgZTY9J1BuZXVtb25pYSB3aXRoaW4gNiB3ZWVrcycsIGU3PSdQcmlvciBjYXJkaWFjIHN1cmdlcnknKSwKICAgICAgICAgICAgcHJpbnQ9RkFMU0UpCgplcmQgPC0gZGF0YS5mcmFtZShzdWJqaWQgPSAxIDogNTAsCiAgICAgICAgICAgICAgICAgIGxvYyAgID0gc2FtcGxlKGMoJ2dhc3RyaWMnLCAnbHVuZycsICd0cmFjaGVhJyksIDUwLCBUUlVFKSkKCiMgVG8gY2hlY2sgd2FybmluZyBtZXNzYWdlcywgZ3JlcG9ydE9wdGlvbiBkZW5vbSBkb2VzIG5vdCBtYXRjaCBwZW5kLCBlMS1lNwpleFJlcG9ydCh+IHBlbmRpbmcocGVuZCkgKyBlMSArIGUyICsgZTMgKyBlNCArIGU1ICsgZTYgKyBlNyArCiAgICAgICAgIHJhbmRvbWl6ZWQocm5keikgKyBpZChzdWJqaWQpICsgY29uZChlNSwgJ1Rlc3RlZCcsIHRlc3RlZCksCiAgICAgICAgIGVyZGF0YSA9IGVyZCwKICAgICAgICAgd2hlbmFwcD0gYyhlND0nQ0NUQSBkb25lJyksIGRhdGE9ZCkgIywgaGM9My43NSwgaD00KQoKIyBTaG93IGV4Y2x1c2lvbnMgaW4gb3JpZ2luYWwgdmFyaWFibGUgb3JkZXIKaWYoRkFMU0UpIGV4UmVwb3J0KH4gcGVuZGluZyhwZW5kKSArIGUxICsgZTIgKyBlMyArIGU0ICsgZTUgKyBlNiArIGU3ICsKICAgICAgICAgcmFuZG9taXplZChybmR6KSArIGlkKHN1YmppZCkgKyBjb25kKGU1LCAnVGVzdGVkJywgdGVzdGVkKSwKICAgICAgICAgZXJkYXRhPWVyZCwKICAgICAgICAgd2hlbmFwcD1jKGU0PSdDQ1RBIGRvbmUnKSwgZGF0YT1kLCAjaGM9My43NSwgaD00LAogICAgICAgICBzb3J0PUZBTFNFLCBhcHA9RkFMU0UpCmBgYAoKIyBBZHZlcnNlIEV2ZW50cwpGb3IgdGhpcyBleGFtcGxlLCB0aGUgZGVub21pbmF0b3JzIGZvciB0aGUgdHdvIHRyZWF0bWVudHMgaW4gdGhlCnBvcC11cCBuZWVkbGVzIHdpbGwgYmUgaW5jb3JyZWN0IGJlY2F1c2UgdGhlIGRhdGFzZXQgZGlkIG5vdCBoYXZlCnN1YmplY3QgSURzLgpgYGB7ciBhZXMscmVzdWx0cz0nYXNpcyd9CiMgT3JpZ2luYWwgc291cmNlIG9mIGFlYW5vbnltOiBISCBwYWNrYWdlCiMgYWVhbm9ueW0gPC0gcmVhZC50YWJsZShoaCgiZGF0YXNldHMvYWVkb3RwbG90LmRhdCIpLCBoZWFkZXI9VFJVRSwgc2VwPSIsIikKIyBNb2RpZmllZCB0byByZW1vdmUgZGVub21pbmF0b3JzIGZyb20gZGF0YSBhbmQgdG8gZ2VuZXJhdGUgcmF3IGRhdGEKIyAob25lIHJlY29yZCBwZXIgZXZlbnQgcGVyIHN1YmplY3QpCgphZSA8LQpzdHJ1Y3R1cmUobGlzdChSQU5EID0gc3RydWN0dXJlKGMoMUwsIDJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIAoyTCwgMUwsIDJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIDJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIDJMLCAxTCwgCjJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIDJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIDJMLCAxTCwgMkwsIDFMLCAKMkwsIDFMLCAyTCwgMUwsIDJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIDJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIAoyTCwgMUwsIDJMLCAxTCwgMkwsIDFMLCAyTCwgMUwsIDJMLCAxTCwgMkwpLCAuTGFiZWwgPSBjKCJhIiwgCiJiIiksIGNsYXNzID0gImZhY3RvciIpLCBQUkVGID0gc3RydWN0dXJlKGMoMTJMLCAxMkwsIAoxOEwsIDE4TCwgMjZMLCAyNkwsIDMzTCwgMzNMLCA1TCwgNUwsIDI3TCwgMjdMLCA2TCwgNkwsIDE1TCwgCjE1TCwgMjJMLCAyMkwsIDIzTCwgMjNMLCAzMUwsIDMxTCwgMTdMLCAxN0wsIDJMLCAyTCwgM0wsIDNMLCAKMTNMLCAxM0wsIDI1TCwgMjVMLCAyOEwsIDI4TCwgMTRMLCAxNEwsIDRMLCA0TCwgOEwsIDhMLCAxOUwsIAoxOUwsIDIxTCwgMjFMLCAyOUwsIDI5TCwgMTBMLCAxMEwsIDIwTCwgMjBMLCAxNkwsIDE2TCwgMzJMLCAzMkwsIAoxMUwsIDExTCwgMUwsIDFMLCAzMEwsIDMwTCwgMjRMLCAyNEwsIDlMLCA5TCwgN0wsIDdMKSwKICAuTGFiZWwgPSB0b2xvd2VyKGMoIkFCRE9NSU5BTCBQQUlOIiwgCiJBTk9SRVhJQSIsICJBUlRIUkFMR0lBIiwgIkJBQ0sgUEFJTiIsICJCUk9OQ0hJVElTIiwgIkNIRVNUIFBBSU4iLCAKIkNIUk9OSUMgT0JTVFJVQ1RJVkUgQUlSV0FZIiwgIkNPVUdISU5HIiwgIkRJQVJSSEVBIiwgIkRJWlpJTkVTUyIsIAoiRFlTUEVQU0lBIiwgIkRZU1BORUEiLCAiRkFUSUdVRSIsICJGTEFUVUxFTkNFIiwgIkdBU1RST0VTT1BIQUdFQUwgUkVGTFVYIiwgCiJIRUFEQUNIRSIsICJIRU1BVFVSSUEiLCAiSFlQRVJLQUxFTUlBIiwgIklORkVDVElPTiBWSVJBTCIsICJJTkpVUlkiLCAKIklOU09NTklBIiwgIk1FTEVOQSIsICJNWUFMR0lBIiwgIk5BVVNFQSIsICJQQUlOIiwgIlJBU0giLCAiUkVTUElSQVRPUlkgRElTT1JERVIiLCAKIlJISU5JVElTIiwgIlNJTlVTSVRJUyIsICJVUFBFUiBSRVNQIFRSQUNUIElORkVDVElPTiIsICJVUklOQVJZIFRSQUNUIElORkVDVElPTiIsIAoiVk9NSVRJTkciLCAiV0VJR0hUIERFQ1JFQVNFIikpLCBjbGFzcyA9ICJmYWN0b3IiKSwgU0FFID0gYygxNUwsIAo5TCwgNEwsIDlMLCA0TCwgOUwsIDJMLCA5TCwgOEwsIDExTCwgNEwsIDExTCwgOUwsIDEyTCwgNUwsIDEyTCwgCjdMLCAxMkwsIDZMLCAxMkwsIDZMLCAxMkwsIDJMLCAxNEwsIDJMLCAxNUwsIDFMLCAxNUwsIDRMLCAxNkwsIAo0TCwgMTdMLCAxMUwsIDE3TCwgNkwsIDIwTCwgMTBMLCAyM0wsIDEzTCwgMjZMLCAxMkwsIDI2TCwgNEwsIAoyNkwsIDEzTCwgMjhMLCA5TCwgMjlMLCAxMkwsIDMwTCwgMTRMLCAzNkwsIDZMLCAzN0wsIDhMLCA0MkwsIAoyMEwsIDYxTCwgMzNMLCA2OEwsIDEwTCwgODJMLCAyM0wsIDkwTCwgNzZMLCA5NUwpKSwgLk5hbWVzID0gYygiUkFORCIsIAoiUFJFRiIsICJTQUUiKSwgY2xhc3MgPSAiZGF0YS5mcmFtZSIsIHJvdy5uYW1lcyA9IGMoTkEsIAotNjZMKSkKCnN1YnMgPC0gcmVwKDEgOiBucm93KGFlKSwgYWUkU0FFKQphZSA8LSBhZVtzdWJzLCBjKCdSQU5EJywgJ1BSRUYnKV0KbmFtZXMoYWUpIDwtIGMoJ3RyZWF0JywgJ2V2ZW50JykKbGFiZWwoYWUkdHJlYXQpIDwtICdUcmVhdG1lbnQnCgpkZW5vbSA8LSBjKGVucm9sbGVkPTEwMDAsCiAgICAgICAgICAgcmFuZG9taXplZD00MDAsCgkJCQkJIGE9MjEyLCBiPTE4OCkKCnNldGhyZXBvcnRPcHRpb24odHgudmFyPSd0cmVhdCcsIGRlbm9tPWRlbm9tKQoKZVJlcG9ydChldmVudCB+IHRyZWF0LCBkYXRhPWFlLCBtaW5pbmNpZGVuY2U9LjA1KQpgYGAK