Primary endpoint
APACHE II
- Mean and median score for each comorbidity set
scores <- ls(pattern = "score_apache2")
all_scores <- map(scores, ~mutate(get(.x), score = .x)) %>%
map(~select(.x, pie.id, score, apache2)) %>%
map_df(~semi_join(.x, manual_patients, by = "pie.id")) %>%
arrange(pie.id, score) %>%
dmap_at("score", str_replace_all, pattern = "score_apache2_", replacement = "")
man <- filter(all_scores, score == "manual")$apache2
result <- all_scores %>%
select(-pie.id) %>%
group_by(score) %>%
summarize_all(funs(mean, sd, median, IQR_low = quantile(., 0.25), IQR_high = quantile(., 0.75)))
knitr::kable(result)
| ahrq |
20.80000 |
7.161100 |
20 |
15 |
24 |
| ahrq_drg |
20.43333 |
7.291431 |
20 |
15 |
24 |
| ek |
20.73333 |
7.182527 |
20 |
15 |
24 |
| ek_drg |
20.40000 |
7.279411 |
20 |
15 |
24 |
| elixhauser |
20.76667 |
7.150600 |
20 |
15 |
24 |
| elixhauser_drg |
20.40000 |
7.279411 |
20 |
15 |
24 |
| manual |
20.36667 |
7.097306 |
20 |
15 |
24 |
| quan |
20.76667 |
7.150600 |
20 |
15 |
24 |
| quan_drg |
20.43333 |
7.249469 |
20 |
15 |
24 |
- Comparison of scores
- Results run using both the t-test and Wilcoxon signed rank test (assumes non-parametric data, is more difficult to achieve significance)
t <- all_scores[, -1] %>%
filter(score != "manual") %>%
group_by(score) %>%
do(tidy(t.test(.$apache2, man, paired = TRUE)))
knitr::kable(t)
| ahrq |
0.4333333 |
1.5669418 |
0.1224765 |
59 |
-0.1200363 |
0.9867030 |
Paired t-test |
two.sided |
| ahrq_drg |
0.0666667 |
0.2380106 |
0.8126975 |
59 |
-0.4938112 |
0.6271445 |
Paired t-test |
two.sided |
| ek |
0.3666667 |
1.3181069 |
0.1925626 |
59 |
-0.1899637 |
0.9232970 |
Paired t-test |
two.sided |
| ek_drg |
0.0333333 |
0.1181156 |
0.9063773 |
59 |
-0.5313665 |
0.5980332 |
Paired t-test |
two.sided |
| elixhauser |
0.4000000 |
1.4315041 |
0.1575620 |
59 |
-0.1591309 |
0.9591309 |
Paired t-test |
two.sided |
| elixhauser_drg |
0.0333333 |
0.1181156 |
0.9063773 |
59 |
-0.5313665 |
0.5980332 |
Paired t-test |
two.sided |
| quan |
0.4000000 |
1.4315041 |
0.1575620 |
59 |
-0.1591309 |
0.9591309 |
Paired t-test |
two.sided |
| quan_drg |
0.0666667 |
0.2346551 |
0.8152889 |
59 |
-0.5018261 |
0.6351594 |
Paired t-test |
two.sided |
mw <- all_scores[, -1] %>%
filter(score != "manual") %>%
group_by(score) %>%
do(tidy(wilcox.test(.$apache2, man, paired = TRUE, conf.int = TRUE, exact = FALSE)))
knitr::kable(mw)
| ahrq |
2.0000007 |
117.0 |
0.1639934 |
-1.499960 |
3.500034 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ahrq_drg |
0.0000427 |
78.0 |
0.9610189 |
-1.500066 |
3.499924 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ek |
1.9999973 |
112.5 |
0.2341505 |
-1.499999 |
3.500062 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ek_drg |
-0.0000623 |
85.5 |
1.0000000 |
-1.500016 |
2.000013 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| elixhauser |
1.9999404 |
127.0 |
0.1916011 |
-1.499995 |
3.499992 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| elixhauser_drg |
-0.0000623 |
85.5 |
1.0000000 |
-1.500016 |
2.000013 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| quan |
1.9999404 |
127.0 |
0.1916011 |
-1.499995 |
3.499992 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| quan_drg |
0.0000360 |
98.0 |
0.9174555 |
-1.500032 |
2.000026 |
Wilcoxon signed rank test with continuity correction |
two.sided |
- Compare differences in score from comorbidity sets vs. manual
- Column num_diff indicates the number of patients with a score that differed from manual
- Mean and median indicate the difference from the manual score
- These were only calculated for those patients whose score was different from manual
- If all patients were included, the number is skewed towards 0 by all the patients with the same scores
diff <- all_scores %>%
spread(score, apache2) %>%
mutate_at(vars(-pie.id, -manual), funs(abs(. - manual))) %>%
gather(score, apache2, -pie.id, -manual) %>%
select(-pie.id, -manual) %>%
filter(apache2 > 0) %>%
group_by(score) %>%
summarize_all(funs(num_diff = length, mean, sd, median, IQR_low = quantile(., 0.25), IQR_high = quantile(., 0.75)))
knitr::kable(diff, caption = "Differences in APACHE II Scores")
| ahrq |
18 |
3.666667 |
1.533930 |
5 |
2 |
5 |
| ahrq_drg |
17 |
3.764706 |
1.521899 |
5 |
2 |
5 |
| ek |
18 |
3.666667 |
1.533930 |
5 |
2 |
5 |
| ek_drg |
18 |
3.666667 |
1.533930 |
5 |
2 |
5 |
| elixhauser |
19 |
3.578947 |
1.538968 |
5 |
2 |
5 |
| elixhauser_drg |
18 |
3.666667 |
1.533930 |
5 |
2 |
5 |
| quan |
19 |
3.578947 |
1.538968 |
5 |
2 |
5 |
| quan_drg |
19 |
3.578947 |
1.538968 |
5 |
2 |
5 |
APACHE III
- There were 10 patients with different comorbidities identified by ICD code vs. manual
- Of these, only 6 had a different APACHE III score; the other 4 were all “elective” admissions where comorbidity score is ignored
- 1 person was identified as being chronic HD by ICD code but not by manual review, accounting for the 7 patients where the APACHE III score by ICD varied from manual
scores <- ls(pattern = "score_apache3")
all_scores <- map(scores, ~mutate(get(.x), score = .x)) %>%
map(~select(.x, pie.id, score, apache3)) %>%
map_df(~semi_join(.x, manual_patients, by = "pie.id")) %>%
arrange(pie.id, score) %>%
dmap_at("score", str_replace_all, pattern = "score_apache3_", replacement = "")
man <- filter(all_scores, score == "manual")$apache3
result <- all_scores %>%
select(-pie.id) %>%
group_by(score) %>%
summarize_all(funs(mean, sd, median, IQR_low = quantile(., 0.25), IQR_high = quantile(., 0.75)))
knitr::kable(result)
| ahrq |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
| ahrq_drg |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
| ek |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
| ek_drg |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
| elixhauser |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
| elixhauser_drg |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
| manual |
84.08333 |
29.02383 |
77.5 |
66.75 |
98.25 |
| quan |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
| quan_drg |
85.26667 |
29.43414 |
77.5 |
68.00 |
103.00 |
t <- all_scores[, -1] %>%
filter(score != "manual") %>%
group_by(score) %>%
do(tidy(t.test(.$apache3, man, paired = TRUE)))
knitr::kable(t)
| ahrq |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
| ahrq_drg |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
| ek |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
| ek_drg |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
| elixhauser |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
| elixhauser_drg |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
| quan |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
| quan_drg |
1.183333 |
2.487694 |
0.0157028 |
59 |
0.2315103 |
2.135156 |
Paired t-test |
two.sided |
mw <- all_scores[, -1] %>%
filter(score != "manual") %>%
group_by(score) %>%
do(tidy(wilcox.test(.$apache3, man, paired = TRUE, conf.int = TRUE, exact = FALSE)))
requested conf.level not achievablerequested conf.level not achievablerequested conf.level not achievablerequested conf.level not achievablerequested conf.level not achievablerequested conf.level not achievablerequested conf.level not achievablerequested conf.level not achievable
knitr::kable(mw)
| ahrq |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ahrq_drg |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ek |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ek_drg |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| elixhauser |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| elixhauser_drg |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| quan |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| quan_drg |
10.99996 |
28 |
0.0220149 |
6.999939 |
13.99999 |
Wilcoxon signed rank test with continuity correction |
two.sided |
diff <- all_scores %>%
spread(score, apache3) %>%
mutate_at(vars(-pie.id, -manual), funs(abs(. - manual))) %>%
gather(score, apache3, -pie.id, -manual) %>%
select(-pie.id, -manual) %>%
filter(apache3 > 0) %>%
group_by(score) %>%
summarize_all(funs(num_diff = length, mean, sd, median, IQR_low = quantile(., 0.25), IQR_high = quantile(., 0.75)))
knitr::kable(diff, caption = "Difference in APACHE III Scores")
| ahrq |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
| ahrq_drg |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
| ek |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
| ek_drg |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
| elixhauser |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
| elixhauser_drg |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
| quan |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
| quan_drg |
7 |
10.14286 |
5.241774 |
11 |
7 |
13.5 |
SAPS II
scores <- ls(pattern = "score_saps2")
all_scores <- map(scores, ~mutate(get(.x), score = .x)) %>%
map(~select(.x, pie.id, score, saps2)) %>%
map_df(~semi_join(.x, manual_patients, by = "pie.id")) %>%
arrange(pie.id, score) %>%
dmap_at("score", str_replace_all, pattern = "score_saps2_", replacement = "")
man <- filter(all_scores, score == "manual")$saps2
result <- all_scores %>%
select(-pie.id) %>%
group_by(score) %>%
summarize_all(funs(mean, sd, median, IQR_low = quantile(., 0.25), IQR_high = quantile(., 0.75)))
knitr::kable(result)
| ahrq |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
| ahrq_drg |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
| ek |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
| ek_drg |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
| elixhauser |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
| elixhauser_drg |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
| manual |
37.06667 |
13.76666 |
34.0 |
27.00 |
45 |
| quan |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
| quan_drg |
37.53333 |
13.60018 |
36.5 |
27.75 |
45 |
t <- all_scores[, -1] %>%
filter(score != "manual") %>%
group_by(score) %>%
do(tidy(t.test(.$saps2, man, paired = TRUE)))
knitr::kable(t)
| ahrq |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
| ahrq_drg |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
| ek |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
| ek_drg |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
| elixhauser |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
| elixhauser_drg |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
| quan |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
| quan_drg |
0.4666667 |
1.759815 |
0.0836229 |
59 |
-0.0639562 |
0.9972896 |
Paired t-test |
two.sided |
- Confidence interval was unable to be calculated for Wilcoxon analysis here
mw <- all_scores[, -1] %>%
filter(score != "manual") %>%
group_by(score) %>%
do(tidy(wilcox.test(.$saps2, man, paired = TRUE, exact = FALSE)))
knitr::kable(mw)
| ahrq |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ahrq_drg |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ek |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| ek_drg |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| elixhauser |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| elixhauser_drg |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| quan |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
| quan_drg |
6 |
0.1735682 |
Wilcoxon signed rank test with continuity correction |
two.sided |
diff <- all_scores %>%
spread(score, saps2) %>%
mutate_at(vars(-pie.id, -manual), funs(abs(. - manual))) %>%
gather(score, saps2, -pie.id, -manual) %>%
select(-pie.id, -manual) %>%
filter(saps2 > 0) %>%
group_by(score) %>%
summarize_all(funs(num_diff = length, mean, sd, median, IQR_low = quantile(., 0.25), IQR_high = quantile(., 0.75)))
knitr::kable(diff, caption = "Difference in SAPS II Scores")
| ahrq |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
| ahrq_drg |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
| ek |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
| ek_drg |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
| elixhauser |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
| elixhauser_drg |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
| quan |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
| quan_drg |
3 |
9.333333 |
0.5773503 |
9 |
9 |
9.5 |
LS0tDQp0aXRsZTogVmFsaWRhdGlvbiBvZiBJQ0QtOS1DTS9JQ0QtMTAtQ00gQ29kZXMgZm9yIEF1dG9tYXRlZCBFbGVjdHJvbmljIFNjb3Jpbmcgb2YNCiAgQVBBQ0hFIElJLCBBUEFDSEUgSUlJLCBhbmQgU0FQUyBJSQ0Kc3VidGl0bGU6IFByZWxpbWluYXJ5IEFuYWx5c2lzIGZvciBBU0hQIEFic3RyYWN0IFN1Ym1pc3Npb24NCmRhdGU6ICdVcGRhdGVkOiBgciBmb3JtYXQoU3lzLkRhdGUoKSwgIiVCICVkLCAlWSIpYCcNCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc3RyaW5ncikNCiMgbGlicmFyeSh0YWJsZW9uZSkNCmxpYnJhcnkoYnJvb20pDQoNCmRpcnI6OmdldF9yZHMoIi4uL2RhdGEvZmluYWwiKQ0KYGBgDQoNCiMjIFBhdGllbnQgU2VsZWN0aW9uDQoNCiogUGF0aWVudHMgbWVldGluZyBpbmNsdXNpb24gY3JpdGVyaWE6IGByIGV4Y2x1ZGUkc2NyZWVuYA0KKiBSZWFzb25zIGZvciBleGNsdXNpb246DQogICAgLSBQcmVnbmFudDogYHIgZXhjbHVkZSRwcmVnbmFudGANCiAgICAtIFByaXNvbmVyOiBgciBleGNsdWRlJHByaXNvbmVyc2ANCiAgICAtIElDVSBzdGF5IDwgMTIgaG91cnM6IGByIGV4Y2x1ZGUkaWN1X3Nob3J0YA0KICAgIC0gRGlhZ25vc2lzIGNvZGluZyBjb250YWluZWQgYm90aCBJQ0QtOS1DTSBhbmQgSUNELTEwLUNNOiBgciBleGNsdWRlJG11bHRfaWNkX3R5cGVzYA0KICAgIC0gTWlzc2luZyBkYXRhIG5lZWRlZCB0byBjYWxjdWxhdGUgcmlzayBzY29yZXM6IGByIGV4Y2x1ZGUkbGFic19taXNzaW5nYA0KICAgIC0gUmUtZW5jb3VudGVycyAob25seSBpbmNsdWRlZCBlYWNoIHBhdGllbnQgb25jZSkgOiBgciBleGNsdWRlJHJlZW5jb3VudGVyYA0KKiBUb3RhbCBudW1iZXIgb2YgZWxpZ2libGUgcGF0aWVudHMgcmVtYWluaW5nIHRvIHNhbXBsZSBmcm9tOiBgciBmbGF0dGVuX2ludChleGNsdWRlKVsxXSAtIHN1bShmbGF0dGVuX2ludChleGNsdWRlKVstMV0pYA0KDQojIyBQcmltYXJ5IGVuZHBvaW50DQoNCiMjIyBBUEFDSEUgSUkNCg0KKiBNZWFuIGFuZCBtZWRpYW4gc2NvcmUgZm9yIGVhY2ggY29tb3JiaWRpdHkgc2V0DQoNCmBgYHtyfQ0Kc2NvcmVzIDwtIGxzKHBhdHRlcm4gPSAic2NvcmVfYXBhY2hlMiIpDQoNCmFsbF9zY29yZXMgPC0gbWFwKHNjb3Jlcywgfm11dGF0ZShnZXQoLngpLCBzY29yZSA9IC54KSkgJT4lDQogICAgbWFwKH5zZWxlY3QoLngsIHBpZS5pZCwgc2NvcmUsIGFwYWNoZTIpKSAlPiUNCiAgICBtYXBfZGYofnNlbWlfam9pbigueCwgbWFudWFsX3BhdGllbnRzLCBieSA9ICJwaWUuaWQiKSkgJT4lDQogICAgYXJyYW5nZShwaWUuaWQsIHNjb3JlKSAlPiUNCiAgICBkbWFwX2F0KCJzY29yZSIsIHN0cl9yZXBsYWNlX2FsbCwgcGF0dGVybiA9ICJzY29yZV9hcGFjaGUyXyIsIHJlcGxhY2VtZW50ID0gIiIpIA0KDQptYW4gPC0gZmlsdGVyKGFsbF9zY29yZXMsIHNjb3JlID09ICJtYW51YWwiKSRhcGFjaGUyDQoNCnJlc3VsdCA8LSBhbGxfc2NvcmVzICU+JQ0KICAgIHNlbGVjdCgtcGllLmlkKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgc3VtbWFyaXplX2FsbChmdW5zKG1lYW4sIHNkLCBtZWRpYW4sIElRUl9sb3cgPSBxdWFudGlsZSguLCAwLjI1KSwgSVFSX2hpZ2ggPSBxdWFudGlsZSguLCAwLjc1KSkpDQoNCmtuaXRyOjprYWJsZShyZXN1bHQpDQpgYGANCg0KKiBDb21wYXJpc29uIG9mIHNjb3Jlcw0KICAgIC0gUmVzdWx0cyBydW4gdXNpbmcgYm90aCB0aGUgdC10ZXN0IGFuZCBXaWxjb3hvbiBzaWduZWQgcmFuayB0ZXN0IChhc3N1bWVzIG5vbi1wYXJhbWV0cmljIGRhdGEsIGlzIG1vcmUgZGlmZmljdWx0IHRvIGFjaGlldmUgc2lnbmlmaWNhbmNlKQ0KDQpgYGB7cn0NCnQgPC0gYWxsX3Njb3Jlc1ssIC0xXSAlPiUNCiAgICBmaWx0ZXIoc2NvcmUgIT0gIm1hbnVhbCIpICU+JQ0KICAgIGdyb3VwX2J5KHNjb3JlKSAlPiUNCiAgICBkbyh0aWR5KHQudGVzdCguJGFwYWNoZTIsIG1hbiwgcGFpcmVkID0gVFJVRSkpKQ0KDQprbml0cjo6a2FibGUodCkNCmBgYA0KDQpgYGB7cn0NCm13IDwtIGFsbF9zY29yZXNbLCAtMV0gJT4lDQogICAgZmlsdGVyKHNjb3JlICE9ICJtYW51YWwiKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgZG8odGlkeSh3aWxjb3gudGVzdCguJGFwYWNoZTIsIG1hbiwgcGFpcmVkID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFLCBleGFjdCA9IEZBTFNFKSkpDQoNCmtuaXRyOjprYWJsZShtdykNCmBgYA0KDQoqIENvbXBhcmUgZGlmZmVyZW5jZXMgaW4gc2NvcmUgZnJvbSBjb21vcmJpZGl0eSBzZXRzIHZzLiBtYW51YWwNCiAgICAtIENvbHVtbiAqbnVtX2RpZmYqIGluZGljYXRlcyB0aGUgbnVtYmVyIG9mIHBhdGllbnRzIHdpdGggYSBzY29yZSB0aGF0IGRpZmZlcmVkIGZyb20gbWFudWFsDQogICAgLSBNZWFuIGFuZCBtZWRpYW4gaW5kaWNhdGUgdGhlIGRpZmZlcmVuY2UgZnJvbSB0aGUgbWFudWFsIHNjb3JlDQogICAgICAgICsgVGhlc2Ugd2VyZSBvbmx5IGNhbGN1bGF0ZWQgZm9yIHRob3NlIHBhdGllbnRzIHdob3NlIHNjb3JlIHdhcyBkaWZmZXJlbnQgZnJvbSBtYW51YWwNCiAgICAgICAgKyBJZiBhbGwgcGF0aWVudHMgd2VyZSBpbmNsdWRlZCwgdGhlIG51bWJlciBpcyBza2V3ZWQgdG93YXJkcyAwIGJ5IGFsbCB0aGUgcGF0aWVudHMgd2l0aCB0aGUgc2FtZSBzY29yZXMNCg0KYGBge3J9DQpkaWZmIDwtIGFsbF9zY29yZXMgJT4lDQogICAgc3ByZWFkKHNjb3JlLCBhcGFjaGUyKSAlPiUNCiAgICBtdXRhdGVfYXQodmFycygtcGllLmlkLCAtbWFudWFsKSwgZnVucyhhYnMoLiAtIG1hbnVhbCkpKSAlPiUNCiAgICBnYXRoZXIoc2NvcmUsIGFwYWNoZTIsIC1waWUuaWQsIC1tYW51YWwpICU+JQ0KICAgIHNlbGVjdCgtcGllLmlkLCAtbWFudWFsKSAlPiUNCiAgICBmaWx0ZXIoYXBhY2hlMiA+IDApICU+JQ0KICAgIGdyb3VwX2J5KHNjb3JlKSAlPiUNCiAgICBzdW1tYXJpemVfYWxsKGZ1bnMobnVtX2RpZmYgPSBsZW5ndGgsIG1lYW4sIHNkLCBtZWRpYW4sIElRUl9sb3cgPSBxdWFudGlsZSguLCAwLjI1KSwgSVFSX2hpZ2ggPSBxdWFudGlsZSguLCAwLjc1KSkpDQoNCmtuaXRyOjprYWJsZShkaWZmLCBjYXB0aW9uID0gIkRpZmZlcmVuY2VzIGluIEFQQUNIRSBJSSBTY29yZXMiKQ0KYGBgDQoNCiMjIyBBUEFDSEUgSUlJDQoNCiogVGhlcmUgd2VyZSAxMCBwYXRpZW50cyB3aXRoIGRpZmZlcmVudCBjb21vcmJpZGl0aWVzIGlkZW50aWZpZWQgYnkgSUNEIGNvZGUgdnMuIG1hbnVhbA0KICAgIC0gT2YgdGhlc2UsIG9ubHkgNiBoYWQgYSBkaWZmZXJlbnQgQVBBQ0hFIElJSSBzY29yZTsgdGhlIG90aGVyIDQgd2VyZSBhbGwgImVsZWN0aXZlIiBhZG1pc3Npb25zIHdoZXJlIGNvbW9yYmlkaXR5IHNjb3JlIGlzIGlnbm9yZWQNCiAgICAtIDEgcGVyc29uIHdhcyBpZGVudGlmaWVkIGFzIGJlaW5nIGNocm9uaWMgSEQgYnkgSUNEIGNvZGUgYnV0IG5vdCBieSBtYW51YWwgcmV2aWV3LCBhY2NvdW50aW5nIGZvciB0aGUgNyBwYXRpZW50cyB3aGVyZSB0aGUgQVBBQ0hFIElJSSBzY29yZSBieSBJQ0QgdmFyaWVkIGZyb20gbWFudWFsDQoNCmBgYHtyfQ0Kc2NvcmVzIDwtIGxzKHBhdHRlcm4gPSAic2NvcmVfYXBhY2hlMyIpDQoNCmFsbF9zY29yZXMgPC0gbWFwKHNjb3Jlcywgfm11dGF0ZShnZXQoLngpLCBzY29yZSA9IC54KSkgJT4lDQogICAgbWFwKH5zZWxlY3QoLngsIHBpZS5pZCwgc2NvcmUsIGFwYWNoZTMpKSAlPiUNCiAgICBtYXBfZGYofnNlbWlfam9pbigueCwgbWFudWFsX3BhdGllbnRzLCBieSA9ICJwaWUuaWQiKSkgJT4lDQogICAgYXJyYW5nZShwaWUuaWQsIHNjb3JlKSAlPiUNCiAgICBkbWFwX2F0KCJzY29yZSIsIHN0cl9yZXBsYWNlX2FsbCwgcGF0dGVybiA9ICJzY29yZV9hcGFjaGUzXyIsIHJlcGxhY2VtZW50ID0gIiIpIA0KDQptYW4gPC0gZmlsdGVyKGFsbF9zY29yZXMsIHNjb3JlID09ICJtYW51YWwiKSRhcGFjaGUzDQoNCnJlc3VsdCA8LSBhbGxfc2NvcmVzICU+JQ0KICAgIHNlbGVjdCgtcGllLmlkKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgc3VtbWFyaXplX2FsbChmdW5zKG1lYW4sIHNkLCBtZWRpYW4sIElRUl9sb3cgPSBxdWFudGlsZSguLCAwLjI1KSwgSVFSX2hpZ2ggPSBxdWFudGlsZSguLCAwLjc1KSkpDQoNCmtuaXRyOjprYWJsZShyZXN1bHQpDQpgYGANCg0KKiBDb21wYXJpc29uIG9mIHNjb3Jlcw0KDQpgYGB7cn0NCnQgPC0gYWxsX3Njb3Jlc1ssIC0xXSAlPiUNCiAgICBmaWx0ZXIoc2NvcmUgIT0gIm1hbnVhbCIpICU+JQ0KICAgIGdyb3VwX2J5KHNjb3JlKSAlPiUNCiAgICBkbyh0aWR5KHQudGVzdCguJGFwYWNoZTMsIG1hbiwgcGFpcmVkID0gVFJVRSkpKQ0KDQprbml0cjo6a2FibGUodCkNCmBgYA0KDQpgYGB7cn0NCm13IDwtIGFsbF9zY29yZXNbLCAtMV0gJT4lDQogICAgZmlsdGVyKHNjb3JlICE9ICJtYW51YWwiKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgZG8odGlkeSh3aWxjb3gudGVzdCguJGFwYWNoZTMsIG1hbiwgcGFpcmVkID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFLCBleGFjdCA9IEZBTFNFKSkpDQoNCmtuaXRyOjprYWJsZShtdykNCmBgYA0KDQoqIERpZmZlcmVuY2VzIGluIHNjb3JlDQoNCmBgYHtyfQ0KZGlmZiA8LSBhbGxfc2NvcmVzICU+JQ0KICAgIHNwcmVhZChzY29yZSwgYXBhY2hlMykgJT4lDQogICAgbXV0YXRlX2F0KHZhcnMoLXBpZS5pZCwgLW1hbnVhbCksIGZ1bnMoYWJzKC4gLSBtYW51YWwpKSkgJT4lDQogICAgZ2F0aGVyKHNjb3JlLCBhcGFjaGUzLCAtcGllLmlkLCAtbWFudWFsKSAlPiUNCiAgICBzZWxlY3QoLXBpZS5pZCwgLW1hbnVhbCkgJT4lDQogICAgZmlsdGVyKGFwYWNoZTMgPiAwKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgc3VtbWFyaXplX2FsbChmdW5zKG51bV9kaWZmID0gbGVuZ3RoLCBtZWFuLCBzZCwgbWVkaWFuLCBJUVJfbG93ID0gcXVhbnRpbGUoLiwgMC4yNSksIElRUl9oaWdoID0gcXVhbnRpbGUoLiwgMC43NSkpKQ0KDQprbml0cjo6a2FibGUoZGlmZiwgY2FwdGlvbiA9ICJEaWZmZXJlbmNlIGluIEFQQUNIRSBJSUkgU2NvcmVzIikNCmBgYA0KDQojIyMgU0FQUyBJSQ0KDQpgYGB7cn0NCnNjb3JlcyA8LSBscyhwYXR0ZXJuID0gInNjb3JlX3NhcHMyIikNCg0KYWxsX3Njb3JlcyA8LSBtYXAoc2NvcmVzLCB+bXV0YXRlKGdldCgueCksIHNjb3JlID0gLngpKSAlPiUNCiAgICBtYXAofnNlbGVjdCgueCwgcGllLmlkLCBzY29yZSwgc2FwczIpKSAlPiUNCiAgICBtYXBfZGYofnNlbWlfam9pbigueCwgbWFudWFsX3BhdGllbnRzLCBieSA9ICJwaWUuaWQiKSkgJT4lDQogICAgYXJyYW5nZShwaWUuaWQsIHNjb3JlKSAlPiUNCiAgICBkbWFwX2F0KCJzY29yZSIsIHN0cl9yZXBsYWNlX2FsbCwgcGF0dGVybiA9ICJzY29yZV9zYXBzMl8iLCByZXBsYWNlbWVudCA9ICIiKSANCg0KbWFuIDwtIGZpbHRlcihhbGxfc2NvcmVzLCBzY29yZSA9PSAibWFudWFsIikkc2FwczINCg0KcmVzdWx0IDwtIGFsbF9zY29yZXMgJT4lDQogICAgc2VsZWN0KC1waWUuaWQpICU+JQ0KICAgIGdyb3VwX2J5KHNjb3JlKSAlPiUNCiAgICBzdW1tYXJpemVfYWxsKGZ1bnMobWVhbiwgc2QsIG1lZGlhbiwgSVFSX2xvdyA9IHF1YW50aWxlKC4sIDAuMjUpLCBJUVJfaGlnaCA9IHF1YW50aWxlKC4sIDAuNzUpKSkNCg0Ka25pdHI6OmthYmxlKHJlc3VsdCkNCmBgYA0KDQoqIENvbXBhcmlzb24gb2Ygc2NvcmVzDQoNCmBgYHtyfQ0KdCA8LSBhbGxfc2NvcmVzWywgLTFdICU+JQ0KICAgIGZpbHRlcihzY29yZSAhPSAibWFudWFsIikgJT4lDQogICAgZ3JvdXBfYnkoc2NvcmUpICU+JQ0KICAgIGRvKHRpZHkodC50ZXN0KC4kc2FwczIsIG1hbiwgcGFpcmVkID0gVFJVRSkpKQ0KDQprbml0cjo6a2FibGUodCkNCmBgYA0KDQoqIENvbmZpZGVuY2UgaW50ZXJ2YWwgd2FzIHVuYWJsZSB0byBiZSBjYWxjdWxhdGVkIGZvciBXaWxjb3hvbiBhbmFseXNpcyBoZXJlDQoNCmBgYHtyfQ0KbXcgPC0gYWxsX3Njb3Jlc1ssIC0xXSAlPiUNCiAgICBmaWx0ZXIoc2NvcmUgIT0gIm1hbnVhbCIpICU+JQ0KICAgIGdyb3VwX2J5KHNjb3JlKSAlPiUNCiAgICBkbyh0aWR5KHdpbGNveC50ZXN0KC4kc2FwczIsIG1hbiwgcGFpcmVkID0gVFJVRSwgZXhhY3QgPSBGQUxTRSkpKQ0KDQprbml0cjo6a2FibGUobXcpDQpgYGANCg0KKiBEaWZmZXJlbmNlcyBpbiBzY29yZQ0KDQpgYGB7cn0NCmRpZmYgPC0gYWxsX3Njb3JlcyAlPiUNCiAgICBzcHJlYWQoc2NvcmUsIHNhcHMyKSAlPiUNCiAgICBtdXRhdGVfYXQodmFycygtcGllLmlkLCAtbWFudWFsKSwgZnVucyhhYnMoLiAtIG1hbnVhbCkpKSAlPiUNCiAgICBnYXRoZXIoc2NvcmUsIHNhcHMyLCAtcGllLmlkLCAtbWFudWFsKSAlPiUNCiAgICBzZWxlY3QoLXBpZS5pZCwgLW1hbnVhbCkgJT4lDQogICAgZmlsdGVyKHNhcHMyID4gMCkgJT4lDQogICAgZ3JvdXBfYnkoc2NvcmUpICU+JQ0KICAgIHN1bW1hcml6ZV9hbGwoZnVucyhudW1fZGlmZiA9IGxlbmd0aCwgbWVhbiwgc2QsIG1lZGlhbiwgSVFSX2xvdyA9IHF1YW50aWxlKC4sIDAuMjUpLCBJUVJfaGlnaCA9IHF1YW50aWxlKC4sIDAuNzUpKSkNCg0Ka25pdHI6OmthYmxlKGRpZmYsIGNhcHRpb24gPSAiRGlmZmVyZW5jZSBpbiBTQVBTIElJIFNjb3JlcyIpDQpgYGANCg0KIyMgU2Vjb25kYXJ5IGVuZHBvaW50cw0KDQojIyMgUHJlZGljdGVkIG1vcnRhbGl0eQ0KDQojIyMjIFNBUFMgSUkNCg0KKiBNZWFuIGFuZCBtZWRpYW4gcmlzayBvZiBtb3J0YWxpdHkgKGFzIGEgcGVyY2VudCkgZm9yIGVhY2ggY29tb3JiaWRpdHkgc2V0DQoNCmBgYHtyfQ0KY29tb3JiaWQgPC0gbHMocGF0dGVybiA9ICJzY29yZV9zYXBzMl8iKQ0KDQphbGxfZGYgPC0gbWFwKGNvbW9yYmlkLCB+bXV0YXRlKGdldCgueCksIHNjb3JlID0gLngpKSAlPiUNCiAgICBtYXAofnNlbGVjdCgueCwgcGllLmlkLCBzY29yZSwgc2FwczIpKSAlPiUNCiAgICBtYXBfZGYofnNlbWlfam9pbigueCwgbWFudWFsX3BhdGllbnRzLCBieSA9ICJwaWUuaWQiKSkgJT4lDQogICAgYXJyYW5nZShwaWUuaWQsIHNjb3JlKSAlPiUNCiAgICBkbWFwX2F0KCJzY29yZSIsIHN0cl9yZXBsYWNlX2FsbCwgcGF0dGVybiA9ICJzY29yZV9zYXBzMl8iLCByZXBsYWNlbWVudCA9ICIiKSAlPiUNCiAgICBkaXN0aW5jdChwaWUuaWQsIHNjb3JlLCAua2VlcF9hbGwgPSBUUlVFKSAlPiUNCiAgICBtdXRhdGUobG9naXQgPSAtNy43NjMgKyAwLjA3MzcgKiBzYXBzMiArIDAuOTk3MSAqIGxvZyhzYXBzMiArIDEpLA0KICAgICAgICAgICBtb3J0YWxpdHkgPSBleHAobG9naXQpIC8gKDEgKyBleHAobG9naXQpKSkgJT4lDQogICAgc2VsZWN0KHBpZS5pZCwgc2NvcmUsIG1vcnRhbGl0eSkgDQoNCm1hbiA8LSBmaWx0ZXIoYWxsX2RmLCBzY29yZSA9PSAibWFudWFsIikkbW9ydGFsaXR5DQoNCnJlc3VsdCA8LSBhbGxfZGYgJT4lDQogICAgc2VsZWN0KC1waWUuaWQpICU+JQ0KICAgIGdyb3VwX2J5KHNjb3JlKSAlPiUNCiAgICBzdW1tYXJpemVfYWxsKGZ1bnMobWVhbiwgc2QsIG1lZGlhbiwgSVFSX2xvdyA9IHF1YW50aWxlKC4sIDAuMjUpLCBJUVJfaGlnaCA9IHF1YW50aWxlKC4sIDAuNzUpKSkNCg0Ka25pdHI6OmthYmxlKHJlc3VsdCkNCmBgYA0KDQpgYGB7cn0NCnQgPC0gYWxsX2RmWywgLTFdICU+JQ0KICAgIGZpbHRlcihzY29yZSAhPSAibWFudWFsIikgJT4lDQogICAgZ3JvdXBfYnkoc2NvcmUpICU+JQ0KICAgIGRvKHRpZHkodC50ZXN0KC4kbW9ydGFsaXR5LCBtYW4sIHBhaXJlZCA9IFRSVUUpKSkNCg0Ka25pdHI6OmthYmxlKHQpDQpgYGANCg0KYGBge3J9DQptdyA8LSBhbGxfZGZbLCAtMV0gJT4lDQogICAgZmlsdGVyKHNjb3JlICE9ICJtYW51YWwiKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgZG8odGlkeSh3aWxjb3gudGVzdCguJG1vcnRhbGl0eSwgbWFuLCBwYWlyZWQgPSBUUlVFLCBjb25mLmludCA9IFRSVUUsIGV4YWN0ID0gRkFMU0UpKSkNCg0Ka25pdHI6OmthYmxlKG13KQ0KYGBgDQoNCiogRGlmZmVyZW5jZSBpbiByaXNrIG9mIG1vcnRhbGl0eQ0KICAgIC0gTWVhbiBhbmQgbWVkaWFuIGNhbGN1bGF0ZWQgdXNpbmcgb25seSB0aG9zZSBwYXRpZW50cyB3aG9zZSBwcmVkaWN0ZWQgbW9ydGFsaXR5IHNjb3JlIHdhcyBkaWZmZXJlbnQgZnJvbSBtYW51YWwNCiAgICANCmBgYHtyfQ0KZGlmZiA8LSBhbGxfZGYgJT4lDQogICAgc3ByZWFkKHNjb3JlLCBtb3J0YWxpdHkpICU+JQ0KICAgIG11dGF0ZV9hdCh2YXJzKC1waWUuaWQsIC1tYW51YWwpLCBmdW5zKGFicyguIC0gbWFudWFsKSkpICU+JQ0KICAgIGdhdGhlcihzY29yZSwgc2FwczIsIC1waWUuaWQsIC1tYW51YWwpICU+JQ0KICAgIHNlbGVjdCgtcGllLmlkLCAtbWFudWFsKSAlPiUNCiAgICBmaWx0ZXIoc2FwczIgPiAwKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgc3VtbWFyaXplX2FsbChmdW5zKG51bV9kaWZmID0gbGVuZ3RoLCBtZWFuLCBzZCwgbWVkaWFuLCBJUVJfbG93ID0gcXVhbnRpbGUoLiwgMC4yNSksIElRUl9oaWdoID0gcXVhbnRpbGUoLiwgMC43NSkpKQ0KDQprbml0cjo6a2FibGUoZGlmZiwgY2FwdGlvbiA9ICJEaWZmZXJlbmNlIGluIFByZWRpY3RlZCBNb3J0YWxpdHkgdXNpbmcgU0FQUyBJSSIpDQpgYGANCg0KIyMjIE51bWJlciBvZiBjb21vcmJpZGl0aWVzDQoNCiMjIyMgQVBBQ0hFIElJDQoNCiogTWVhbiByZXByZXNlbnRzIHRoZSBhdmVyYWdlIG51bWJlciBvZiBjb21vcmJpZGl0aWVzIHBlciBwYXRpZW50DQoNCmBgYHtyfQ0KY29tb3JiaWQgPC0gbHMocGF0dGVybiA9ICJkYXRhX2FwYWNoZTJfIikNCg0KYWxsX2RmIDwtIG1hcChjb21vcmJpZCwgfm11dGF0ZShnZXQoLngpLCBzY29yZSA9IC54KSkgJT4lDQogICAgbWFwKH5kaXN0aW5jdCgueCwgcGllLmlkLCBzY29yZSwgbGl2ZXIsIGNhcmRpb3Zhc2MsIHJlc3BpcmF0b3J5LCByZW5hbCwgaW1tdW5vY29tcCwgY29tb3JiaWRpdHkpKSAlPiUNCiAgICBtYXBfZGYofnNlbWlfam9pbigueCwgbWFudWFsX3BhdGllbnRzLCBieSA9ICJwaWUuaWQiKSkgJT4lDQogICAgYXJyYW5nZShwaWUuaWQsIHNjb3JlKSAlPiUNCiAgICBkbWFwX2F0KCJzY29yZSIsIHN0cl9yZXBsYWNlX2FsbCwgcGF0dGVybiA9ICJkYXRhX2FwYWNoZTJfIiwgcmVwbGFjZW1lbnQgPSAiIikgJT4lDQogICAgbXV0YXRlX2lmKGlzLmxvZ2ljYWwsIGFzLm51bWVyaWMpICU+JQ0KICAgIGJ5X3JvdyhmdW5jdGlvbih4KSBzdW0oeFssIDM6N10sIG5hLnJtID0gVFJVRSksIC5jb2xsYXRlID0gInJvd3MiLCAudG8gPSAibnVtX2NvbW9yYmlkIikgJT4lDQogICAgc2VsZWN0KHBpZS5pZCwgc2NvcmUsIG51bV9jb21vcmJpZCkgDQoNCm1hbiA8LSBmaWx0ZXIoYWxsX2RmLCBzY29yZSA9PSAibWFudWFsIikkbnVtX2NvbW9yYmlkDQoNCnJlc3VsdCA8LSBhbGxfZGYgJT4lDQogICAgc2VsZWN0KC1waWUuaWQpICU+JQ0KICAgIGdyb3VwX2J5KHNjb3JlKSAlPiUNCiAgICBzdW1tYXJpemVfYWxsKGZ1bnMobWVhbiwgc2QsIG1lZGlhbiwgSVFSX2xvdyA9IHF1YW50aWxlKC4sIDAuMjUpLCBJUVJfaGlnaCA9IHF1YW50aWxlKC4sIDAuNzUpKSkNCg0Ka25pdHI6OmthYmxlKHJlc3VsdCkNCmBgYA0KDQpgYGB7cn0NCnQgPC0gYWxsX2RmWywgLTFdICU+JQ0KICAgIGZpbHRlcihzY29yZSAhPSAibWFudWFsIikgJT4lDQogICAgZ3JvdXBfYnkoc2NvcmUpICU+JQ0KICAgIGRvKHRpZHkodC50ZXN0KC4kbnVtX2NvbW9yYmlkLCBtYW4sIHBhaXJlZCA9IFRSVUUpKSkNCg0Ka25pdHI6OmthYmxlKHQpDQpgYGANCg0KYGBge3J9DQptdyA8LSBhbGxfZGZbLCAtMV0gJT4lDQogICAgZmlsdGVyKHNjb3JlICE9ICJtYW51YWwiKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgZG8odGlkeSh3aWxjb3gudGVzdCguJG51bV9jb21vcmJpZCwgbWFuLCBwYWlyZWQgPSBUUlVFLCBjb25mLmludCA9IFRSVUUsIGV4YWN0ID0gRkFMU0UpKSkNCg0Ka25pdHI6OmthYmxlKG13KQ0KYGBgDQoNCiMjIyBQcm9wb3J0aW9uIHdpdGggZGlmZmVyaW5nIGNvbW9yYmlkaXR5DQoNCiMjIyMgQVBBQ0hFIElJDQoNCiogUHJvcG9ydGlvbiBvZiBwYXRpZW50cyB3aGVyZSBhIGNvbW9yYmlkaXR5IHdhcyBpZGVudGlmaWVkIGJ5IElDRCBvciBieSBtYW51YWwsIGJ1dCBub3QgYm90aA0KDQpgYGB7cn0NCmNvbW9yYmlkIDwtIGxzKHBhdHRlcm4gPSAiZGF0YV9hcGFjaGUyXyIpDQoNCmFsbF9kZiA8LSBtYXAoY29tb3JiaWQsIH5tdXRhdGUoZ2V0KC54KSwgc2NvcmUgPSAueCkpICU+JQ0KICAgIG1hcCh+ZGlzdGluY3QoLngsIHBpZS5pZCwgc2NvcmUsIGNvbW9yYmlkaXR5KSkgJT4lDQogICAgbWFwX2RmKH5zZW1pX2pvaW4oLngsIG1hbnVhbF9wYXRpZW50cywgYnkgPSAicGllLmlkIikpICU+JQ0KICAgIGFycmFuZ2UocGllLmlkLCBzY29yZSkgJT4lDQogICAgZG1hcF9hdCgic2NvcmUiLCBzdHJfcmVwbGFjZV9hbGwsIHBhdHRlcm4gPSAiZGF0YV9hcGFjaGUyXyIsIHJlcGxhY2VtZW50ID0gIiIpICU+JQ0KICAgIHNwcmVhZChzY29yZSwgY29tb3JiaWRpdHkpICU+JQ0KICAgIG11dGF0ZV9hdCh2YXJzKC1waWUuaWQsIC1tYW51YWwpLCBmdW5zKC4gIT0gbWFudWFsKSkgJT4lDQogICAgbXV0YXRlX2lmKGlzLmxvZ2ljYWwsIGFzLm51bWVyaWMpICU+JQ0KICAgIHVuZ3JvdXAoKSAlPiUNCiAgICBnYXRoZXIoc2NvcmUsIGNvbW9yYmlkaXR5LCAtcGllLmlkLCAtbWFudWFsKSAlPiUNCiAgICBzZWxlY3QoLXBpZS5pZCwgLW1hbnVhbCkgJT4lDQogICAgZ3JvdXBfYnkoc2NvcmUpICU+JQ0KICAgIHN1bW1hcml6ZV9hbGwoZnVucyhudW1fZGlmZiA9IHN1bSguID4gMCksIHByb3BvcnRpb24gPSBtZWFuKSkNCg0Ka25pdHI6OmthYmxlKGFsbF9kZikNCmBgYA0KDQojIyMjIEFQQUNIRSBJSUkNCg0KKiBQcm9wb3J0aW9uIG9mIHBhdGllbnRzIHdoZXJlIHRoZSBwcmltYXJ5IGNvbW9yYmlkaXR5IGlkZW50aWZpZWQgYnkgSUNEIHZhcmllZCBmcm9tIHByaW1hcnkgY29tb3JiaWRpdHkgaWRlbnRpZmllZCBieSBtYW51YWwNCg0KYGBge3J9DQpjb21vcmJpZCA8LSBscyhwYXR0ZXJuID0gImRhdGFfYXBhY2hlM18iKQ0KDQphbGxfZGYgPC0gbWFwKGNvbW9yYmlkLCB+bXV0YXRlKGdldCgueCksIHNjb3JlID0gLngpKSAlPiUNCiAgICBtYXAofmRpc3RpbmN0KC54LCBwaWUuaWQsIHNjb3JlLCBjb21vcmJpZGl0eSkpICU+JQ0KICAgIG1hcF9kZih+c2VtaV9qb2luKC54LCBtYW51YWxfcGF0aWVudHMsIGJ5ID0gInBpZS5pZCIpKSAlPiUNCiAgICBhcnJhbmdlKHBpZS5pZCwgc2NvcmUpICU+JQ0KICAgIGRtYXBfYXQoInNjb3JlIiwgc3RyX3JlcGxhY2VfYWxsLCBwYXR0ZXJuID0gImRhdGFfYXBhY2hlM18iLCByZXBsYWNlbWVudCA9ICIiKSAlPiUNCiAgICBzcHJlYWQoc2NvcmUsIGNvbW9yYmlkaXR5LCBmaWxsID0gIiIpICU+JQ0KICAgIGRtYXAoc3RyX3JlcGxhY2VfYWxsLCBwYXR0ZXJuID0gIm5vbmUiLCByZXBsYWNlbWVudCA9ICIiKSAlPiUNCiAgICBtdXRhdGVfYXQodmFycygtcGllLmlkLCAtbWFudWFsKSwgZnVucyguICE9IG1hbnVhbCkpICU+JQ0KICAgIG11dGF0ZV9pZihpcy5sb2dpY2FsLCBhcy5udW1lcmljKSAlPiUNCiAgICBnYXRoZXIoc2NvcmUsIGNvbW9yYmlkaXR5LCAtcGllLmlkLCAtbWFudWFsKSAlPiUNCiAgICBzZWxlY3QoLXBpZS5pZCwgLW1hbnVhbCkgJT4lDQogICAgZ3JvdXBfYnkoc2NvcmUpICU+JQ0KICAgIHN1bW1hcml6ZV9hbGwoZnVucyhudW1fZGlmZiA9IHN1bSguID4gMCksIHByb3BvcnRpb24gPSBtZWFuKSkNCg0Ka25pdHI6OmthYmxlKGFsbF9kZikNCmBgYA0KDQojIyMjIFNBUFMgSUkNCg0KKiBQcm9wb3J0aW9uIG9mIHBhdGllbnRzIHdoZXJlIHRoZSBwcmltYXJ5IGNvbW9yYmlkaXR5IGlkZW50aWZpZWQgYnkgSUNEIHZhcmllZCBmcm9tIHByaW1hcnkgY29tb3JiaWRpdHkgaWRlbnRpZmllZCBieSBtYW51YWwNCg0KYGBge3J9DQpjb21vcmJpZCA8LSBscyhwYXR0ZXJuID0gImRhdGFfc2FwczJfIikNCg0KYWxsX2RmIDwtIG1hcChjb21vcmJpZCwgfm11dGF0ZShnZXQoLngpLCBzY29yZSA9IC54KSkgJT4lDQogICAgbWFwKH5kaXN0aW5jdCgueCwgcGllLmlkLCBzY29yZSwgY29tb3JiaWRpdHkpKSAlPiUNCiAgICBtYXBfZGYofnNlbWlfam9pbigueCwgbWFudWFsX3BhdGllbnRzLCBieSA9ICJwaWUuaWQiKSkgJT4lDQogICAgYXJyYW5nZShwaWUuaWQsIHNjb3JlKSAlPiUNCiAgICBkbWFwX2F0KCJzY29yZSIsIHN0cl9yZXBsYWNlX2FsbCwgcGF0dGVybiA9ICJkYXRhX3NhcHMyXyIsIHJlcGxhY2VtZW50ID0gIiIpICU+JQ0KICAgIHNwcmVhZChzY29yZSwgY29tb3JiaWRpdHksIGZpbGwgPSAiIikgJT4lDQogICAgZG1hcChzdHJfcmVwbGFjZV9hbGwsIHBhdHRlcm4gPSAibm9uZSIsIHJlcGxhY2VtZW50ID0gIiIpICU+JQ0KICAgIG11dGF0ZV9hdCh2YXJzKC1waWUuaWQsIC1tYW51YWwpLCBmdW5zKC4gIT0gbWFudWFsKSkgJT4lDQogICAgbXV0YXRlX2lmKGlzLmxvZ2ljYWwsIGFzLm51bWVyaWMpICU+JQ0KICAgIGdhdGhlcihzY29yZSwgY29tb3JiaWRpdHksIC1waWUuaWQsIC1tYW51YWwpICU+JQ0KICAgIHNlbGVjdCgtcGllLmlkLCAtbWFudWFsKSAlPiUNCiAgICBncm91cF9ieShzY29yZSkgJT4lDQogICAgc3VtbWFyaXplX2FsbChmdW5zKG51bV9kaWZmID0gc3VtKC4gPiAwKSwgcHJvcG9ydGlvbiA9IG1lYW4pKQ0KDQprbml0cjo6a2FibGUoYWxsX2RmKQ0KYGBgDQo=