Introduction
This is a classroom exercise of PYU CS424 Course on Big Data Anaylsis. The aim of this exercise is to demonstrate data wrangling techniques useful for converting raw datasets into a tidy dataframe that can be easily analyzed using Tidyverse running on R.
Background
Tuberculosis claims approximately 4000 lives each day and remains the top infectious killer in the world. Each year millions of people fall ill to this preventable and curable disease. WHO publishes annually The Global Tuberculosis Report to provide a comprehensive and up-to-date assessment of the TB epidemic, and progress arising fromabatement efforts at global, regional and country levels. However, data gathering and verification in this reporting is a slow process. To provide early warnings of changes, the WHO has invited health officials around the globe to submit provisional TB notifications monthly or quarterly to WHO on an voluntary basis.[^WHOTB] Although the numbers are not official, nor complete, they do provide early indications of changes in the pattern of tuberculosis infections. The dynamic state of this database is useful exercise to demonstrate techniques in data wrangling.
TB is caused by microbaterium that is able to creates holes and absesses in lungs and brain tissue. It is rapidly spread in overcrowded conditions and among those would are malnourished. Although is curable, treatment can take months and requires drugs that are not available or affordable by thoses infected.

Research Question
Does the provisional database of tuberculosis infections have any hint of the impact of COVID-19 pandemic on tuberculosis infections?
Methodology
The WHO Global Tuberculosis Programme receives provisional data voluntarily from countries worldwide on either a monthly or quarterly basis. These numbers are not final and are subject to change but they do provide early indications of any changes in the infection pattern of tuberculosis.
The data was downloaded from the WHO website as a CSV file that was loaded into R. Analysis was done with the Tidyverse library.
library(tidyverse)
library(lubridate)
tbdat = read_csv("datasets/TB_provisional_notifications_2021-08-09.csv")
Rows: 215 Columns: 24
── Column specification ────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): country, iso2, iso3, iso_numeric, g_whoregion
dbl (19): year, report_frequency, report_coverage, m_01, m_02, m_03, m_04, m_05, m_06, m_07, m_0...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Data dictionary
Meaning of the data fields:
- country = col_character() : Country name
- iso2 = col_character() : ISO 3066 2-digit country code
- iso3 = col_character() : ISO 3066 3-digit country code
- iso_numeric = col_character() : Country ID num
- g_whoregion = col_character() : Region
- year = col_double() : Calendar year
- report_frequency = col_double() : Monthly or Quarterly reporting
- report_coverage = col_double() : Completeness of the report
- m_01 = col_double() : Jan infection data
- m_02 = col_double() : Feb infection data
- m_03 = col_double() : Mar infection data
- m_04 = col_double() : Apr infection data
- m_05 = col_double() : May infection data
- m_06 = col_double() : Jun infection data
- m_07 = col_double() : Jul infection data
- m_08 = col_double() : Aug infection data
- m_09 = col_double() : Sep infection data
- m_10 = col_double() : Oct infection data
- m_11 = col_double() : Nov infection data
- m_12 = col_double() : Dec infection data
- q_1 = col_double() : 1st quarter infection data
- q_2 = col_double() : 2nd quarter infection data
- q_3 = col_double() : 3rd quarter infection data
- q_4 = col_double() : 4th quarter infection data
Selecting the countries of interest
Two methods were attempted and timed.
timefunc <- function(func) {
dat = rep(0,5)
for (rpt in c(1:5)) {
dat[rpt] = Sys.time()
for (i in c(1:1000)) {
func()
}
dat[rpt] = Sys.time() - dat[rpt]
print(dat[rpt])
}
return(dat)
}
- Selection by multiple logic expression
multiselect <- function() {
tbdat %>%
filter(iso2 == "TH" | iso2 == "IN" | iso2 == "CN" |
iso2 == "US" | iso2 == "PH" | iso2 == "ID")
}
dat = timefunc(multiselect)
[1] 9.601976
[1] 8.056268
[1] 8.619806
[1] 8.674143
[1] 8.488425
Mean 8.6881237 +/- 0.5654888
- Selection by grepl() patterns
greplselect <- function() {
tbdat %>%
filter(grepl("CN|IN|ID|LA|TH|US",iso2))
}
dat2 = timefunc(greplselect)
[1] 8.251768
[1] 8.402063
[1] 8.514668
[1] 9.502662
[1] 9.095228
Mean 8.7532777 +/- 0.5268549
Welch Two Sample t-test
data: dat and dat2
t = -0.1885, df = 7.9603, p-value = 0.8552
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-0.8629067 0.7325987
sample estimates:
mean of x mean of y
8.688124 8.753278
There is no statistically significant difference in the performance of the two methods.
Reshaping the dataset
tbdat2 = tbdat %>%
filter(iso2 == "TH" | iso2 == "IN" | iso2 == "CN" |
iso2 == "US" | iso2 == "LA" | iso2 == "ID") %>%
gather(m_01, m_02, m_03, m_04, m_05, m_06,
m_07, m_08, m_09, m_10, m_11, m_12,
key="mon",value="infmon") %>%
gather(q_1, q_2, q_3, q_4,
key="qrt", value="infqrt") %>%
separate(qrt, into =c("q","quarter"), sep="_") %>%
separate(mon, into =c("s","month"), sep="_") %>%
mutate(yrmon = ymd(year * 10000 + as.integer(month) * 100 + 1)) %>%
select(iso2,yrmon,infmon,quarter,infqrt)
- Sample of the Polished Data
Plot the data
tbdat2 %>%
filter(!is.na(infmon)) %>%
ggplot(aes(x=yrmon,y=infmon,color=iso2)) +
geom_smooth(method="loess",formula="y~x") +
geom_point()

Alternative plot
tbdat2 %>%
filter(!is.na(infmon)) %>%
ggplot(aes(x=yrmon,y=infmon,color=iso2)) +
geom_smooth(method="loess",formula="y~x") +
geom_point() +
facet_grid(rows=vars(iso2),scales="free_y")

Results
The greatest decrease in the number of the TB case was seen at the peak of the waves of COVID19.
Summary and Conclusion
Our prelimary findings are consistent with those reported by WHO. Althought the data is provisional, they provide an early indication of how the disruption caused by the COVID-19 pandemic may be affecting essential TB services. At the same time, the antiCOVID-19 measures also By mid-March 2021, 84 countries with more than 80% of global TB incidence and almost 90% of global TB notifications in 2019 had reported complete monthly or quarterly data for 2020. These showed a 21% drop in TB notifications between 2019 and 2020 overall, with much larger reductions in some high TB burden countries, notably India, Indonesia, the Philippines and South Africa.
References
LS0tCnRpdGxlOiAiUHJvdmlzaW9uYWwgV0hPIFR1YmVyY3Vsb3NpcyBEYXRhIGZvciAyMDIwLTIwMjEiCmF1dGhvcjogIkRyIFJvYmVydCBCYXR6aW5nZXIsIFBheWFwIFVuaXZlcnNpdHkgRGVwdC4gb2YgQ29tcHV0ZXIgU2NpZW5jZSIKZGF0ZTogIjIwIEp1bHkgMjAyMSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgbnVtYmVyX3NlY3Rpb246IHRydWUKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRoZW1lOiB1bml0ZWQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKYWJzdHJhY3Q6ICJUaGlzIGV4ZXJjaXNlIGlzIGFuIGF0dGVtcHQgdG8gdXNlIFRpZHl2ZXJzZSB0byBjb252ZXJ0IHRoZSBwcm92aXNpb25hbCB0dWJlcmN1bG9zaXMgZGF0YSBzdWJtaXR0ZWQgbW9udGhseSB0byB0aGUgV29ybGQgSGVhbHRoIE9yZ2FuaXphdGlvbiBpbnRvIGEgZGF0YWZyYW1lIGRlc3BpdGUgdGhlIGluY29uc2lzdGVuY2llcyBhbmQgb21pc3Npb25zLiBJbiBhZGRpdGlvbiwgdGhlIHJlc3VsdGluZyBkYXRhZnJhbWUgY2FuIGJlIGFuYWx5emVkIHRvIGxvb2sgZm9yIGFueSBldmlkZW5jZSBvZiBDT1ZJRDE5IGVmZmVjdHMgb24gdHViZXJjdWxvc2lzIGluZmVjdGlvbnMuXG5cbiIKLS0tCgojIEludHJvZHVjdGlvbgoKVGhpcyBpcyBhIGNsYXNzcm9vbSBleGVyY2lzZSBvZiBQWVUgQ1M0MjQgQ291cnNlIG9uIEJpZyBEYXRhIEFuYXlsc2lzLiBUaGUgYWltIG9mIHRoaXMgZXhlcmNpc2UgaXMgdG8gZGVtb25zdHJhdGUgZGF0YSB3cmFuZ2xpbmcgdGVjaG5pcXVlcyB1c2VmdWwgZm9yIGNvbnZlcnRpbmcgcmF3IGRhdGFzZXRzIGludG8gYSB0aWR5IGRhdGFmcmFtZSB0aGF0IGNhbiBiZSBlYXNpbHkgYW5hbHl6ZWQgdXNpbmcgVGlkeXZlcnNlW15XaWNraGFtXSBydW5uaW5nIG9uIFIuCgoKW15XaWNraGFtXTogV2lja2hhbSBldCBhbC4sICgyMDE5KS4gV2VsY29tZSB0byB0aGUgdGlkeXZlcnNlLiBKb3VybmFsIG9mIE9wZW4gU291cmNlIFNvZnR3YXJlLCA0KDQzKSwgMTY4NiwKICBodHRwczovL2RvaS5vcmcvMTAuMjExMDUvam9zcy4wMTY4NgogIAojIyBCYWNrZ3JvdW5kCgpUdWJlcmN1bG9zaXMgY2xhaW1zIGFwcHJveGltYXRlbHkgNDAwMCBsaXZlcyBlYWNoIGRheSBhbmQgcmVtYWlucyB0aGUgdG9wIGluZmVjdGlvdXMga2lsbGVyIGluIHRoZSB3b3JsZC4gRWFjaCB5ZWFyIG1pbGxpb25zIG9mIHBlb3BsZSBmYWxsIGlsbCB0byB0aGlzIHByZXZlbnRhYmxlIGFuZCBjdXJhYmxlIGRpc2Vhc2UuIFdITyBwdWJsaXNoZXMgYW5udWFsbHkgVGhlIEdsb2JhbCBUdWJlcmN1bG9zaXMgUmVwb3J0IHRvIHByb3ZpZGUgYSBjb21wcmVoZW5zaXZlIGFuZCB1cC10by1kYXRlIGFzc2Vzc21lbnQgb2YgdGhlIFRCIGVwaWRlbWljLCBhbmQgcHJvZ3Jlc3MgYXJpc2luZyBmcm9tYWJhdGVtZW50IGVmZm9ydHMgYXQgZ2xvYmFsLCByZWdpb25hbCBhbmQgY291bnRyeSBsZXZlbHMuW15XSE8yMDIwXSBIb3dldmVyLCBkYXRhIGdhdGhlcmluZyBhbmQgdmVyaWZpY2F0aW9uIGluIHRoaXMgcmVwb3J0aW5nIGlzIGEgc2xvdyBwcm9jZXNzLiBUbyBwcm92aWRlIGVhcmx5IHdhcm5pbmdzIG9mIGNoYW5nZXMsIHRoZSBXSE8gaGFzIGludml0ZWQgaGVhbHRoIG9mZmljaWFscyBhcm91bmQgdGhlIGdsb2JlIHRvIHN1Ym1pdCBwcm92aXNpb25hbCBUQiBub3RpZmljYXRpb25zIG1vbnRobHkgb3IgcXVhcnRlcmx5IHRvIFdITyBvbiBhbiB2b2x1bnRhcnkgYmFzaXMuW15XSE9UQl0gQWx0aG91Z2ggdGhlIG51bWJlcnMgYXJlIG5vdCBvZmZpY2lhbCwgbm9yIGNvbXBsZXRlLCB0aGV5IGRvIHByb3ZpZGUgZWFybHkgaW5kaWNhdGlvbnMgb2YgY2hhbmdlcyBpbiB0aGUgcGF0dGVybiBvZiB0dWJlcmN1bG9zaXMgaW5mZWN0aW9ucy4gVGhlIGR5bmFtaWMgc3RhdGUgb2YgdGhpcyBkYXRhYmFzZSBpcyB1c2VmdWwgZXhlcmNpc2UgdG8gZGVtb25zdHJhdGUgdGVjaG5pcXVlcyBpbiBkYXRhIHdyYW5nbGluZy4KClteV0hPMjAyMF06IFdITywgMjAyMC4gR2xvYmFsIFR1YmVyY3Vsb3NpcyBSZXBvcnQgMjAyMCBBdmFpbGFibGUgb25saW5lCmh0dHBzOi8vd3d3Lndoby5pbnQvdGVhbXMvZ2xvYmFsLXR1YmVyY3Vsb3Npcy1wcm9ncmFtbWUvdGItcmVwb3J0cy9nbG9iYWwtdHViZXJjdWxvc2lzLXJlcG9ydC0yMDIwCgoKW15XSE9UQkRhdGFdOiBXSE8sIDIwMjEuIFByb3Zpc2lvbmFsIFRCIG5vdGlmaWNhdGlvbnMgYnkgbW9udGggb3IgcXVhcnRlci4gQXZhaWxhYmxlIG9ubGluZSBhdCBodHRwczovL3d3dy53aG8uaW50L3RlYW1zL2dsb2JhbC10dWJlcmN1bG9zaXMtcHJvZ3JhbW1lL2RhdGEKCgpUQiBpcyBjYXVzZWQgYnkgbWljcm9iYXRlcml1bSB0aGF0IGlzIGFibGUgdG8gY3JlYXRlcyBob2xlcyBhbmQgYWJzZXNzZXMgaW4gbHVuZ3MgYW5kIGJyYWluIHRpc3N1ZS4gSXQgaXMgcmFwaWRseSBzcHJlYWQgaW4gb3ZlcmNyb3dkZWQgY29uZGl0aW9ucyBhbmQgYW1vbmcgdGhvc2Ugd291bGQgYXJlIG1hbG5vdXJpc2hlZC4gQWx0aG91Z2ggaXMgY3VyYWJsZSwgdHJlYXRtZW50IGNhbiB0YWtlIG1vbnRocyBhbmQgcmVxdWlyZXMgZHJ1Z3MgdGhhdCBhcmUgbm90IGF2YWlsYWJsZSBvciBhZmZvcmRhYmxlIGJ5IHRob3NlcyBpbmZlY3RlZC4KCmBgYHtyLGVjaG89RkFMU0Usb3V0LndpZHRoPSI0MCUifQpsaWJyYXJ5KGtuaXRyKQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygidGJ4LmpwZyIpCmBgYAoKCgoKIyMgUmVzZWFyY2ggUXVlc3Rpb24KCj4gRG9lcyB0aGUgcHJvdmlzaW9uYWwgZGF0YWJhc2Ugb2YgdHViZXJjdWxvc2lzIGluZmVjdGlvbnMgaGF2ZSBhbnkgaGludCBvZiB0aGUgaW1wYWN0IG9mIENPVklELTE5IHBhbmRlbWljIG9uIHR1YmVyY3Vsb3NpcyBpbmZlY3Rpb25zPwoKIyBNZXRob2RvbG9neQoKVGhlIFdITyBHbG9iYWwgVHViZXJjdWxvc2lzIFByb2dyYW1tZVteV0hPVEJEYXRhXSByZWNlaXZlcyBwcm92aXNpb25hbCBkYXRhIHZvbHVudGFyaWx5IGZyb20gY291bnRyaWVzIHdvcmxkd2lkZSBvbiBlaXRoZXIgYSBtb250aGx5IG9yIHF1YXJ0ZXJseSBiYXNpcy4gVGhlc2UgbnVtYmVycyBhcmUgbm90IGZpbmFsIGFuZCBhcmUgc3ViamVjdCB0byBjaGFuZ2UgYnV0IHRoZXkgZG8gcHJvdmlkZSBlYXJseSBpbmRpY2F0aW9ucyBvZiBhbnkgY2hhbmdlcyBpbiB0aGUgaW5mZWN0aW9uIHBhdHRlcm4gb2YgdHViZXJjdWxvc2lzLgoKClRoZSBkYXRhIHdhcyBkb3dubG9hZGVkIGZyb20gdGhlIFdITyB3ZWJzaXRlIGFzIGEgQ1NWIGZpbGUgdGhhdCB3YXMgbG9hZGVkIGludG8gUi4gQW5hbHlzaXMgd2FzIGRvbmUgd2l0aCB0aGUgVGlkeXZlcnNlIGxpYnJhcnkuCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKCmBgYHtyfQp0YmRhdCA9IHJlYWRfY3N2KCJkYXRhc2V0cy9UQl9wcm92aXNpb25hbF9ub3RpZmljYXRpb25zXzIwMjEtMDgtMDkuY3N2IikKIyBzcGVjKHRiZGF0KQpgYGAKIyMgRGF0YSBkaWN0aW9uYXJ5CgoqKk1lYW5pbmcgb2YgdGhlIGRhdGEgZmllbGRzOioqCgoqICBjb3VudHJ5ID0gY29sX2NoYXJhY3RlcigpIDogQ291bnRyeSBuYW1lCiogIGlzbzIgPSBjb2xfY2hhcmFjdGVyKCkgOiBJU08gMzA2NiAyLWRpZ2l0IGNvdW50cnkgY29kZQoqICBpc28zID0gY29sX2NoYXJhY3RlcigpIDogSVNPIDMwNjYgMy1kaWdpdCBjb3VudHJ5IGNvZGUKKiAgaXNvX251bWVyaWMgPSBjb2xfY2hhcmFjdGVyKCkgOiBDb3VudHJ5IElEIG51bQoqICBnX3dob3JlZ2lvbiA9IGNvbF9jaGFyYWN0ZXIoKSA6IFJlZ2lvbgoqICB5ZWFyID0gY29sX2RvdWJsZSgpIDogQ2FsZW5kYXIgeWVhcgoqICByZXBvcnRfZnJlcXVlbmN5ID0gY29sX2RvdWJsZSgpIDogTW9udGhseSBvciBRdWFydGVybHkgcmVwb3J0aW5nCiogIHJlcG9ydF9jb3ZlcmFnZSA9IGNvbF9kb3VibGUoKSA6IENvbXBsZXRlbmVzcyBvZiB0aGUgcmVwb3J0CiogIG1fMDEgPSBjb2xfZG91YmxlKCkgOiBKYW4gaW5mZWN0aW9uIGRhdGEKKiAgbV8wMiA9IGNvbF9kb3VibGUoKSA6IEZlYiBpbmZlY3Rpb24gZGF0YQoqICBtXzAzID0gY29sX2RvdWJsZSgpIDogTWFyIGluZmVjdGlvbiBkYXRhCiogIG1fMDQgPSBjb2xfZG91YmxlKCkgOiBBcHIgaW5mZWN0aW9uIGRhdGEKKiAgbV8wNSA9IGNvbF9kb3VibGUoKSA6IE1heSBpbmZlY3Rpb24gZGF0YQoqICBtXzA2ID0gY29sX2RvdWJsZSgpIDogSnVuIGluZmVjdGlvbiBkYXRhCiogIG1fMDcgPSBjb2xfZG91YmxlKCkgOiBKdWwgaW5mZWN0aW9uIGRhdGEKKiAgbV8wOCA9IGNvbF9kb3VibGUoKSA6IEF1ZyBpbmZlY3Rpb24gZGF0YQoqICBtXzA5ID0gY29sX2RvdWJsZSgpIDogU2VwIGluZmVjdGlvbiBkYXRhCiogIG1fMTAgPSBjb2xfZG91YmxlKCkgOiBPY3QgaW5mZWN0aW9uIGRhdGEKKiAgbV8xMSA9IGNvbF9kb3VibGUoKSA6IE5vdiBpbmZlY3Rpb24gZGF0YQoqICBtXzEyID0gY29sX2RvdWJsZSgpIDogRGVjIGluZmVjdGlvbiBkYXRhCiogIHFfMSA9IGNvbF9kb3VibGUoKSA6IDFzdCBxdWFydGVyIGluZmVjdGlvbiBkYXRhCiogIHFfMiA9IGNvbF9kb3VibGUoKSA6IDJuZCBxdWFydGVyIGluZmVjdGlvbiBkYXRhCiogIHFfMyA9IGNvbF9kb3VibGUoKSA6IDNyZCBxdWFydGVyIGluZmVjdGlvbiBkYXRhCiogIHFfNCA9IGNvbF9kb3VibGUoKSA6IDR0aCBxdWFydGVyIGluZmVjdGlvbiBkYXRhCgoKIyMgU2VsZWN0aW5nIHRoZSBjb3VudHJpZXMgb2YgaW50ZXJlc3QKClR3byBtZXRob2RzIHdlcmUgYXR0ZW1wdGVkIGFuZCB0aW1lZC4gCgoqIFRpbWluZyB0aGUgZnVuY3Rpb25zCgpgYGB7cn0KdGltZWZ1bmMgPC0gZnVuY3Rpb24oZnVuYykgewogIGRhdCA9IHJlcCgwLDUpCiAgZm9yIChycHQgaW4gYygxOjUpKSB7CiAgICBkYXRbcnB0XSA9IFN5cy50aW1lKCkKICAgIGZvciAoaSBpbiBjKDE6MTAwMCkpIHsKICAgICAgZnVuYygpCiAgICB9ICAKICAgIGRhdFtycHRdID0gU3lzLnRpbWUoKSAtIGRhdFtycHRdCiAgICBwcmludChkYXRbcnB0XSkKICB9CiAgcmV0dXJuKGRhdCkKfQpgYGAKCiogU2VsZWN0aW9uIGJ5IG11bHRpcGxlIGxvZ2ljIGV4cHJlc3Npb24KCmBgYHtyfQptdWx0aXNlbGVjdCA8LSBmdW5jdGlvbigpIHsKICB0YmRhdCAgJT4lIAogICAgIGZpbHRlcihpc28yID09ICJUSCIgfCBpc28yID09ICJJTiIgfCBpc28yID09ICJDTiIgfAogICAgICAgICAgIGlzbzIgPT0gIlVTIiB8IGlzbzIgPT0gIlBIIiB8IGlzbzIgPT0gIklEIikKfQoKZGF0ID0gdGltZWZ1bmMobXVsdGlzZWxlY3QpCmBgYAoKTWVhbiBgciBtZWFuKGRhdClgICsvLSBgciBzZChkYXQpYAoKKiBTZWxlY3Rpb24gYnkgZ3JlcGwoKSBwYXR0ZXJucwoKYGBge3J9CmdyZXBsc2VsZWN0IDwtIGZ1bmN0aW9uKCkgewogIHRiZGF0ICU+JSAKICAgIGZpbHRlcihncmVwbCgiQ058SU58SUR8TEF8VEh8VVMiLGlzbzIpKQp9CgpkYXQyID0gdGltZWZ1bmMoZ3JlcGxzZWxlY3QpCgpgYGAKTWVhbiBgciBtZWFuKGRhdDIpYCArLy0gYHIgc2QoZGF0MilgCgpgYGB7cn0KdC50ZXN0KGRhdCxkYXQyKQpgYGAKVGhlcmUgaXMgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgdHdvIG1ldGhvZHMuCgoKIyMgUmVzaGFwaW5nIHRoZSBkYXRhc2V0CgpgYGB7cn0KdGJkYXQyID0gdGJkYXQgJT4lIAogIGZpbHRlcihpc28yID09ICJUSCIgfCBpc28yID09ICJJTiIgfCBpc28yID09ICJDTiIgfAogICAgICAgICAgIGlzbzIgPT0gIlVTIiB8IGlzbzIgPT0gIkxBIiB8IGlzbzIgPT0gIklEIikgJT4lCiAgZ2F0aGVyKG1fMDEsIG1fMDIsIG1fMDMsIG1fMDQsIG1fMDUsIG1fMDYsCiAgICAgICAgIG1fMDcsIG1fMDgsIG1fMDksIG1fMTAsIG1fMTEsIG1fMTIsCiAgICAgICAgIGtleT0ibW9uIix2YWx1ZT0iaW5mbW9uIikgJT4lCiAgZ2F0aGVyKHFfMSwgcV8yLCBxXzMsIHFfNCwKICAgICAgICAga2V5PSJxcnQiLCB2YWx1ZT0iaW5mcXJ0IikgJT4lCiAgc2VwYXJhdGUocXJ0LCBpbnRvID1jKCJxIiwicXVhcnRlciIpLCBzZXA9Il8iKSAlPiUKICBzZXBhcmF0ZShtb24sIGludG8gPWMoInMiLCJtb250aCIpLCBzZXA9Il8iKSAlPiUKICBtdXRhdGUoeXJtb24gPSB5bWQoeWVhciAqIDEwMDAwICsgYXMuaW50ZWdlcihtb250aCkgKiAxMDAgKyAxKSkgJT4lCiAgc2VsZWN0KGlzbzIseXJtb24saW5mbW9uLHF1YXJ0ZXIsaW5mcXJ0KSAKYGBgCgoqIFNhbXBsZSBvZiB0aGUgUG9saXNoZWQgRGF0YQoKYGBge3J9CmhlYWQodGJkYXQyLDIwKQpgYGAKCiMjIFBsb3QgdGhlIGRhdGEKCmBgYHtyfQp0YmRhdDIgJT4lIAogIGZpbHRlcighaXMubmEoaW5mbW9uKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXlybW9uLHk9aW5mbW9uLGNvbG9yPWlzbzIpKSArCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIixmb3JtdWxhPSJ5fngiKSArCiAgICAgZ2VvbV9wb2ludCgpCmBgYAoKCiMjIEFsdGVybmF0aXZlIHBsb3QKCgpgYGB7cixmaWcud2lkdGg9NSxmaWcuaGVpZ2h0PTd9CnRiZGF0MiAlPiUgCiAgZmlsdGVyKCFpcy5uYShpbmZtb24pKSAlPiUKICBnZ3Bsb3QoYWVzKHg9eXJtb24seT1pbmZtb24sY29sb3I9aXNvMikpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLGZvcm11bGE9Inl+eCIpICsKICAgICBnZW9tX3BvaW50KCkgKyAKICAgICBmYWNldF9ncmlkKHJvd3M9dmFycyhpc28yKSxzY2FsZXM9ImZyZWVfeSIpCgpgYGAKCiMgUmVzdWx0cwoKVGhlIGdyZWF0ZXN0IGRlY3JlYXNlIGluIHRoZSBudW1iZXIgb2YgdGhlIFRCIGNhc2Ugd2FzIHNlZW4gYXQgdGhlIHBlYWsgb2YgdGhlIHdhdmVzIG9mIENPVklEMTkuCgojIFN1bW1hcnkgYW5kIENvbmNsdXNpb24KCk91ciBwcmVsaW1hcnkgZmluZGluZ3MgYXJlIGNvbnNpc3RlbnQgd2l0aCB0aG9zZSByZXBvcnRlZCBieSBXSE8uIEFsdGhvdWdodCB0aGUgZGF0YSBpcyBwcm92aXNpb25hbCwgdGhleSBwcm92aWRlIGFuIGVhcmx5IGluZGljYXRpb24gb2YgaG93IHRoZSBkaXNydXB0aW9uIGNhdXNlZCBieSB0aGUgQ09WSUQtMTkgcGFuZGVtaWMgbWF5IGJlIGFmZmVjdGluZyBlc3NlbnRpYWwgVEIgc2VydmljZXMuIEF0IHRoZSBzYW1lIHRpbWUsIHRoZSBhbnRpQ09WSUQtMTkgbWVhc3VyZXMgYWxzbyAKQnkgbWlkLU1hcmNoIDIwMjEsIDg0IGNvdW50cmllcyB3aXRoIG1vcmUgdGhhbiA4MCUgb2YgZ2xvYmFsIFRCIGluY2lkZW5jZSBhbmQgYWxtb3N0IDkwJSBvZiBnbG9iYWwgVEIgbm90aWZpY2F0aW9ucyBpbiAyMDE5IGhhZCByZXBvcnRlZCBjb21wbGV0ZSBtb250aGx5IG9yIHF1YXJ0ZXJseSBkYXRhIGZvciAyMDIwLiBUaGVzZSBzaG93ZWQgYSAyMSUgZHJvcCBpbiBUQiBub3RpZmljYXRpb25zIGJldHdlZW4gMjAxOSBhbmQgMjAyMCBvdmVyYWxsLCB3aXRoIG11Y2ggbGFyZ2VyIHJlZHVjdGlvbnMgaW4gc29tZSBoaWdoIFRCIGJ1cmRlbiBjb3VudHJpZXMsIG5vdGFibHkgSW5kaWEsIEluZG9uZXNpYSwgdGhlIFBoaWxpcHBpbmVzIGFuZCBTb3V0aCBBZnJpY2EuCgojIFJlZmVyZW5jZXMK