Continue your shiny app
At this point, we are going to add text to the front interface of our Shiny app considering the issues that are not addressed in each of our calculations or plots. Follow the instructions below to fill your text into comment boxes on the front page of the app.
We won’t be touching the input variables this week. First copy and paste your input variables from lab 7.
#======================
#COPY AND PASTE THE INPUT VARIABLES SECTION FROM LAB 7 BELOW
#======================
geo_input_choices <-
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE BELOW WITH YOUR OWN GEOGRAPHIC VARIABLE
select(STATE) %>%
distinct() %>%
#REPLACE STATE BELOW WITH YOUR OWN GEOGRAPHIC VARIABLE
arrange(STATE)
#COMMENT LINES BELOW IF YOU DO NOT HAVE A TEMPORAL VARIABLE IN YOUR DATAFRAME
date_input_start <-
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE SOURCEDATE BELOW WITH YOUR OWN TEMPORAL VARIABLE
summarize(date = min(SOURCEDATE))
date_input_end <-
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE SOURCEDATE BELOW WITH YOUR OWN TEMPORAL VARIABLE
summarize(date = max(SOURCEDATE))
#COMMENT LINES ABOVE IF YOU DO NOT HAVE A TEMPORAL VARIABLE IN YOUR DATAFRAME
#======================
#COPY AND PASTE THE INPUT VARIABLES SECTION FROM LAB 7 ABOVE
#======================
In the UI function below, you are going to complete the 7 statements following the commented instruction “#COMPLETE THE STATEMENT BELOW FOR…” Once you’ve completed these statements, copy and paste the rest of the UI function from lab 8 where I’ve indicated.
ui <- dashboardPage(
#REPLACE 'TITLE HERE' BELOW WITH YOUR OWN TITLE
dashboardHeader(title = "TITLE HERE"),
#REPLACE 'TITLE HERE' ABOVE WITH YOUR OWN TITLE
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("About the Data", tabName = "about", icon = icon("info-sign"))
),
selectInput(inputId = "geo_val", label = "Select an geography:", choices = geo_input_choices, selected = geo_input_choices[1]),
#COMMENT LINE BELOW IF YOU DO NOT HAVE A TEMPORAL VARIABLE IN YOUR DATAFRAME
dateRangeInput(inputId = "date_val", label = "Select a date range:", start = date_input_start$date, end = date_input_end$date)
#COMMENT LINE ABOVE IF YOU DO NOT HAVE A TEMPORAL VARIABLE IN YOUR DATAFRAME
),
dashboardBody(
tags$head(tags$style(HTML('.content-wrapper { overflow: auto; }'))),
tabItems(
tabItem(tabName = "dashboard",
infoBoxOutput("value1", width = 4),
infoBoxOutput("value2", width = 4),
infoBoxOutput("value3", width = 4),
#COMPLETE THE STATEMENT BELOW FOR VALUEBOX 1
box(tags$p("The number above does not account for..."), width = 4),
#COMPLETE THE STATEMENT BELOW FOR VALUEBOX 2
box(tags$p("The number above does not account for..."), width = 4),
#COMPLETE THE STATEMENT BELOW FOR VALUEBOX 3
box(tags$p("The number above does not account for git, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam ei"), width = 4),
box(plotOutput("plot1")),
box(plotOutput("plot2")),
#COMPLETE THE STATEMENT BELOW FOR PLOT 1
box(tags$p("The plot above does not account for..."), width = 6),
#COMPLETE THE STATEMENT BELOW FOR PLOT 2
box(tags$p("The plot above does not account for..."), width = 6),
box(plotOutput("plot3")),
box(plotOutput("plot4")),
#COMPLETE THE STATEMENT BELOW FOR PLOT 3
box(tags$p("The plot above does not account for..."), width = 6),
#COMPLETE THE STATEMENT BELOW FOR PLOT 4
box(tags$p("The plot above does not account for..."), width = 6)
),
#======================
#COPY AND PASTE THE REMAINDER OF THE UI FUNCTION FROM LAB 8 BELOW
#======================
tabItem(tabName = "about",
tags$h1("Data Source"),
#REPLACE TEXT IN QUOTATIONS BELOW WITH YOUR OWN TEXT ABOUT YOUR DATA'S SOURCE
tags$p("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"),
#REPLACE TEXT IN QUOTATIONS ABOVE WITH YOUR OWN TEXT ABOUT YOUR DATA'S SOURCE
tags$h1("Data Context"),
#REPLACE TEXT IN QUOTATIONS BELOW WITH YOUR OWN TEXT ABOUT YOUR DATA'S CONTEXT
tags$p("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"),
#REPLACE TEXT IN QUOTATIONS ABOVE WITH YOUR OWN TEXT ABOUT YOUR DATA'S SOURCE
tags$h1("Insights"),
#REPLACE TEXT IN QUOTATIONS BELOW WITH YOUR OWN TEXT ABOUT YOUR INSIGHTS
tags$p("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"),
#REPLACE TEXT IN QUOTATIONS ABOVE WITH YOUR OWN TEXT ABOUT YOUR INSIGHTS
tags$h1("Knowledge Gaps"),
#REPLACE TEXT IN QUOTATIONS BELOW WITH YOUR OWN TEXT ABOUT YOUR KNOWLEDGE GAPS
tags$p("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?")
#REPLACE TEXT IN QUOTATIONS ABOVE WITH YOUR OWN TEXT ABOUT YOUR KNOWLEDGE GAPS
)
)
)
)
#======================
#COPY AND PASTE THE REMAINDER OF THE UI FUNCTION FROM LAB 8 ABOVE
#======================
We won’t be touching the server function this week. You can copy and paste yours from Lab 7 to replace my code below.
#======================
#COPY AND PASTE THE SERVER FUNCTION FROM LAB 7 BELOW
#======================
server <- function(input, output) {
output$value1 <- renderInfoBox({
quant_insight1 <-
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE WITH YOUR OWN GEOGRAPHIC VARIABLE AND SOURCEDATE WITH YOUR OWN TEMPORAL VARIABLE
filter(
STATE == input$geo_val &
SOURCEDATE > input$date_val[1] &
SOURCEDATE < input$date_val[2]
) %>%
#COPY AND PASTE YOUR FUNCTION HERE FROM LAB 6
filter(STATUS == "OPEN" & TYPE == "GENERAL ACUTE CARE") %>%
summarize(median_value = median(BEDS, na.rm = TRUE))
#REPLACE 'FILL DESCRIPTION HERE' BELOW WITH YOUR OWN DESCRIPTION
infoBox(quant_insight1,'FILL DESCRIPTION HERE', icon = icon("stats", lib='glyphicon'), color = "purple")
})
output$value2 <- renderInfoBox({
quant_insight2 <-
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE WITH YOUR OWN GEOGRAPHIC VARIABLE AND SOURCEDATE WITH YOUR OWN TEMPORAL VARIABLE
filter(
STATE == input$geo_val &
SOURCEDATE > input$date_val[1] &
SOURCEDATE < input$date_val[2]
) %>%
#COPY AND PASTE YOUR FUNCTION HERE FROM LAB 6
filter(STATUS == "OPEN" & TYPE == "GENERAL ACUTE CARE") %>%
summarize(median_value = median(BEDS, na.rm = TRUE))
#REPLACE 'FILL DESCRIPTION HERE' BELOW WITH YOUR OWN DESCRIPTION
infoBox(quant_insight2,'FILL DESCRIPTION HERE', icon = icon("stats", lib='glyphicon'), color = "purple")
})
output$value3 <- renderInfoBox({
quant_insight3 <-
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE WITH YOUR OWN GEOGRAPHIC VARIABLE AND SOURCEDATE WITH YOUR OWN TEMPORAL VARIABLE
filter(
STATE == input$geo_val &
SOURCEDATE > input$date_val[1] &
SOURCEDATE < input$date_val[2]
) %>%
#COPY AND PASTE YOUR FUNCTION HERE FROM LAB 6
filter(STATUS == "OPEN" & TYPE == "GENERAL ACUTE CARE") %>%
summarize(median_value = median(BEDS, na.rm = TRUE))
#REPLACE 'FILL DESCRIPTION HERE' BELOW WITH YOUR OWN DESCRIPTION
infoBox(quant_insight3,'FILL DESCRIPTION HERE', icon = icon("stats", lib='glyphicon'), color = "purple")
})
output$plot1 <- renderPlot({
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE WITH YOUR OWN GEOGRAPHIC VARIABLE AND SOURCEDATE WITH YOUR OWN TEMPORAL VARIABLE
filter(
STATE == input$geo_val &
SOURCEDATE > input$date_val[1] &
SOURCEDATE < input$date_val[2]
) %>%
#COPY AND PASTE YOUR PLOT HERE FROM LAB 6
filter(STATUS == "OPEN") %>%
ggplot(aes(x = TYPE)) +
geom_bar() +
labs(title = "Number of Hospitals in the US that are Open by Type", x = "Type", y = "Count of Hospitals") +
theme_bw() +
theme(axis.text.x = element_text(angle = 90, hjust=1))
})
output$plot2 <- renderPlot({
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE WITH YOUR OWN GEOGRAPHIC VARIABLE AND SOURCEDATE WITH YOUR OWN TEMPORAL VARIABLE
filter(
STATE == input$geo_val &
SOURCEDATE > input$date_val[1] &
SOURCEDATE < input$date_val[2]
) %>%
#COPY AND PASTE YOUR PLOT HERE FROM LAB 6
filter(STATUS == "OPEN") %>%
ggplot(aes(x = TYPE)) +
geom_bar() +
labs(title = "Number of Hospitals in the US that are Open by Type", x = "Type", y = "Count of Hospitals") +
theme_bw() +
theme(axis.text.x = element_text(angle = 90, hjust=1))
})
output$plot3 <- renderPlot({
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE WITH YOUR OWN GEOGRAPHIC VARIABLE AND SOURCEDATE WITH YOUR OWN TEMPORAL VARIABLE
filter(
STATE == input$geo_val &
SOURCEDATE > input$date_val[1] &
SOURCEDATE < input$date_val[2]
) %>%
#COPY AND PASTE YOUR PLOT HERE FROM LAB 6
filter(STATUS == "OPEN") %>%
ggplot(aes(x = TYPE)) +
geom_bar() +
labs(title = "Number of Hospitals in the US that are Open by Type", x = "Type", y = "Count of Hospitals") +
theme_bw() +
theme(axis.text.x = element_text(angle = 90, hjust=1))
})
output$plot4 <- renderPlot({
#REPLACE hospitals BELOW WITH YOUR OWN DATAFRAME
hospitals %>%
#REPLACE STATE WITH YOUR OWN GEOGRAPHIC VARIABLE AND SOURCEDATE WITH YOUR OWN TEMPORAL VARIABLE
filter(
STATE == input$geo_val &
SOURCEDATE > input$date_val[1] &
SOURCEDATE < input$date_val[2]
) %>%
#COPY AND PASTE YOUR PLOT HERE FROM LAB 6
filter(STATUS == "OPEN") %>%
ggplot(aes(x = TYPE)) +
geom_bar() +
labs(title = "Number of Hospitals in the US that are Open by Type", x = "Type", y = "Count of Hospitals") +
theme_bw() +
theme(axis.text.x = element_text(angle = 90, hjust=1))
})
}
#======================
#COPY AND PASTE THE SERVER FUNCTION FROM LAB 7 ABOVE
#======================
shinyApp(ui, server)
Listening on http://127.0.0.1:6574
NA
LS0tCnRpdGxlOiAiTGFiIDkgLSBQcmVzZW50aW5nIERhdGEiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnMycKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCiMjIEluc3RydWN0aW9ucyBhbmQgT3ZlcnZpZXcKClRoaXMgd2VlaywgSSdkIGxpa2UgeW91IHRvIHByaW1hcmlseSBmb2N1cyBvbiBwcmVwYXJpbmcgeW91ciBmaW5hbCBwcmVzZW50YXRpb24uIEhvd2V2ZXIsIHdlIHdpbGwgYWxzbyBzcGVuZCBqdXN0IGEgYml0IG9mIHRpbWUgZG9jdW1lbnRpbmcgdGhlIHVuY2VydGFpbnR5IGluIGVhY2ggb2YgdGhlIG51bWJlcnMgYW5kIHBsb3RzIG9uIG91ciBkYXNoYm9hcmRzLiAKCiMjIEdldHRpbmcgU3RhcnRlZAoKIyMjIExvYWQgdGhlIHJlbGV2YW50IGxpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShzaGlueSkKbGlicmFyeShzaGlueWRhc2hib2FyZCkKbGlicmFyeShzaGlueVdpZGdldHMpCmBgYAoKIyMjIEltcG9ydCBhbmQgY2xlYW4gZXhhbXBsZSBkYXRhc2V0cyAKCmBgYHtyfQpob3NwaXRhbHMgPC0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9saW5kc2F5cG9pcmllci9TVFMtMTE1L21hc3Rlci9kYXRhc2V0cy9Ib3NwaXRhbHMuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKY2FzZXMgPC0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DU1NFR0lTYW5kRGF0YS9DT1ZJRC0xOS9tYXN0ZXIvY3NzZV9jb3ZpZF8xOV9kYXRhL2Nzc2VfY292aWRfMTlfdGltZV9zZXJpZXMvdGltZV9zZXJpZXNfY292aWQxOV9jb25maXJtZWRfZ2xvYmFsLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiNEbyBub3Qgd29ycnkgYWJvdXQgdGhpcyBsaW5lIG9mIGNvZGUgZm9yIG5vdy4gU2luY2UgdGhlIGNhc2VzIGRhdGEgZ2V0cyBhcHBlbmRlZCBldmVyeSBkYXkgd2l0aCBhIG5ldyBjb2x1bW4gcmVwcmVzZW50aW5nIHRoYXQgZGF5J3MgY2FzZSBjb3VudHMsIGlmIHdlIHdhbnQgdGhlIHRvdGFsIGNhc2VzIHBlciBjb3VudHJ5LCB3ZSBuZWVkIHRvIGFkZCB1cCBhbGwgb2YgdGhlIHByZXZpb3VzIGRheSdzIGNvdW50cyBpbnRvIGEgbmV3IGNvbHVtbi4gVGhlIGNvbHVtbiBiZWxvdyBkb2VzIHRoaXMgZm9yIHVzLiAKY2FzZXMgPC0gCiAgY2FzZXMgJT4lIAogIG11dGF0ZShUb3RhbC5DYXNlcyA9IAogICAgICAgICAgIGNhc2VzICU+JSAKICAgICAgICAgICBzZWxlY3Qoc3RhcnRzX3dpdGgoIlgiKSkgJT4lIAogICAgICAgICAgIHJvd1N1bXMoKQogICAgICAgICApICU+JQogIHNlbGVjdChQcm92aW5jZS5TdGF0ZSwgQ291bnRyeS5SZWdpb24sIFRvdGFsLkNhc2VzKQoKaG9zcGl0YWxzJFpJUCA8LSBhcy5jaGFyYWN0ZXIoaG9zcGl0YWxzJFpJUCkKCmhvc3BpdGFscyRaSVAgPC0gc3RyX3BhZChob3NwaXRhbHMkWklQLCA1LCBwYWQgPSAiMCIpIAoKaXMubmEoaG9zcGl0YWxzKSA8LSBob3NwaXRhbHMgPT0gIk5PVCBBVkFJTEFCTEUiCmlzLm5hKGhvc3BpdGFscykgPC0gaG9zcGl0YWxzID09IC05OTkKaXMubmEoY2FzZXMpIDwtIGNhc2VzID09ICIiCgpob3NwaXRhbHMkU09VUkNFREFURSA8LSB5bWRfaG1zKGhvc3BpdGFscyRTT1VSQ0VEQVRFKQpob3NwaXRhbHMkVkFMX0RBVEUgPC0geW1kX2htcyhob3NwaXRhbHMkVkFMX0RBVEUpCmBgYAoKIyMjIEltcG9ydCBhbmQgY2xlYW4geW91ciBkYXRhc2V0CgpgYGB7cn0KI0NvcHkgYW5kIHBhc3RlIHJlbGV2YW50IGNvZGUgZnJvbSBMYWIgNCB0byBpbXBvcnQgeW91ciBkYXRhIGhlcmUuIAoKI0NvcHkgYW5kIHBhc3RlIHJlbGV2YW50IGNvZGUgZnJvbSBMYWIgNCB0byBjbGVhbiB5b3VyIGRhdGEgaGVyZS4gVGhpcyBpbmNsdWRlcyBhbnkgcm93IGJpbmRpbmcsIGNoYXJhY3RlciByZW1vdmFscywgY29udmVyaW9ucyBpbiB2YXJpYWJsZSB0eXBlLCBkYXRlIGZvcm1hdHRpbmcsIG9yIE5BIGNvbnZlcnNpb25zLiAKYGBgCgojIyBDb250aW51ZSB5b3VyIHNoaW55IGFwcAoKQXQgdGhpcyBwb2ludCwgd2UgYXJlIGdvaW5nIHRvIGFkZCB0ZXh0IHRvIHRoZSBmcm9udCBpbnRlcmZhY2Ugb2Ygb3VyIFNoaW55IGFwcCBjb25zaWRlcmluZyB0aGUgaXNzdWVzIHRoYXQgYXJlIG5vdCBhZGRyZXNzZWQgaW4gZWFjaCBvZiBvdXIgY2FsY3VsYXRpb25zIG9yIHBsb3RzLiBGb2xsb3cgdGhlIGluc3RydWN0aW9ucyBiZWxvdyB0byBmaWxsIHlvdXIgdGV4dCBpbnRvIGNvbW1lbnQgYm94ZXMgb24gdGhlIGZyb250IHBhZ2Ugb2YgdGhlIGFwcC4KCldlIHdvbid0IGJlIHRvdWNoaW5nIHRoZSBpbnB1dCB2YXJpYWJsZXMgdGhpcyB3ZWVrLiBGaXJzdCBjb3B5IGFuZCBwYXN0ZSB5b3VyIGlucHV0IHZhcmlhYmxlcyBmcm9tIGxhYiA3LgoKYGBge3J9CiM9PT09PT09PT09PT09PT09PT09PT09CiNDT1BZIEFORCBQQVNURSBUSEUgSU5QVVQgVkFSSUFCTEVTIFNFQ1RJT04gRlJPTSBMQUIgNyBCRUxPVwojPT09PT09PT09PT09PT09PT09PT09PQpnZW9faW5wdXRfY2hvaWNlcyA8LSAKICAjUkVQTEFDRSBob3NwaXRhbHMgQkVMT1cgV0lUSCBZT1VSIE9XTiBEQVRBRlJBTUUKICBob3NwaXRhbHMgJT4lIAogICNSRVBMQUNFIFNUQVRFIEJFTE9XIFdJVEggWU9VUiBPV04gR0VPR1JBUEhJQyBWQVJJQUJMRQogIHNlbGVjdChTVEFURSkgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogICNSRVBMQUNFIFNUQVRFIEJFTE9XIFdJVEggWU9VUiBPV04gR0VPR1JBUEhJQyBWQVJJQUJMRQogIGFycmFuZ2UoU1RBVEUpCgojQ09NTUVOVCBMSU5FUyBCRUxPVyBJRiBZT1UgRE8gTk9UIEhBVkUgQSBURU1QT1JBTCBWQVJJQUJMRSBJTiBZT1VSIERBVEFGUkFNRQpkYXRlX2lucHV0X3N0YXJ0IDwtIAogICNSRVBMQUNFIGhvc3BpdGFscyBCRUxPVyBXSVRIIFlPVVIgT1dOIERBVEFGUkFNRQogIGhvc3BpdGFscyAlPiUgCiAgI1JFUExBQ0UgU09VUkNFREFURSBCRUxPVyBXSVRIIFlPVVIgT1dOIFRFTVBPUkFMIFZBUklBQkxFCiAgc3VtbWFyaXplKGRhdGUgPSBtaW4oU09VUkNFREFURSkpCgpkYXRlX2lucHV0X2VuZCA8LSAKICAjUkVQTEFDRSBob3NwaXRhbHMgQkVMT1cgV0lUSCBZT1VSIE9XTiBEQVRBRlJBTUUKICBob3NwaXRhbHMgJT4lIAogICNSRVBMQUNFIFNPVVJDRURBVEUgQkVMT1cgV0lUSCBZT1VSIE9XTiBURU1QT1JBTCBWQVJJQUJMRQogIHN1bW1hcml6ZShkYXRlID0gbWF4KFNPVVJDRURBVEUpKQojQ09NTUVOVCBMSU5FUyBBQk9WRSBJRiBZT1UgRE8gTk9UIEhBVkUgQSBURU1QT1JBTCBWQVJJQUJMRSBJTiBZT1VSIERBVEFGUkFNRQoKIz09PT09PT09PT09PT09PT09PT09PT0KI0NPUFkgQU5EIFBBU1RFIFRIRSBJTlBVVCBWQVJJQUJMRVMgU0VDVElPTiBGUk9NIExBQiA3IEFCT1ZFCiM9PT09PT09PT09PT09PT09PT09PT09CmBgYAoKSW4gdGhlIFVJIGZ1bmN0aW9uIGJlbG93LCB5b3UgYXJlIGdvaW5nIHRvIGNvbXBsZXRlIHRoZSA3IHN0YXRlbWVudHMgZm9sbG93aW5nIHRoZSBjb21tZW50ZWQgaW5zdHJ1Y3Rpb24gIiNDT01QTEVURSBUSEUgU1RBVEVNRU5UIEJFTE9XIEZPUi4uLiIgT25jZSB5b3UndmUgY29tcGxldGVkIHRoZXNlIHN0YXRlbWVudHMsIGNvcHkgYW5kIHBhc3RlIHRoZSByZXN0IG9mIHRoZSBVSSBmdW5jdGlvbiBmcm9tIGxhYiA4IHdoZXJlIEkndmUgaW5kaWNhdGVkLiAKCmBgYHtyfQp1aSA8LSBkYXNoYm9hcmRQYWdlKAogIAogICNSRVBMQUNFICdUSVRMRSBIRVJFJyBCRUxPVyBXSVRIIFlPVVIgT1dOIFRJVExFCiAgZGFzaGJvYXJkSGVhZGVyKHRpdGxlID0gIlRJVExFIEhFUkUiKSwKICAjUkVQTEFDRSAnVElUTEUgSEVSRScgQUJPVkUgV0lUSCBZT1VSIE9XTiBUSVRMRQogIAogIGRhc2hib2FyZFNpZGViYXIoCiAgICAgIHNpZGViYXJNZW51KAogICAgICAgIG1lbnVJdGVtKCJEYXNoYm9hcmQiLCB0YWJOYW1lID0gImRhc2hib2FyZCIsIGljb24gPSBpY29uKCJkYXNoYm9hcmQiKSksCiAgICAgICAgbWVudUl0ZW0oIkFib3V0IHRoZSBEYXRhIiwgdGFiTmFtZSA9ICJhYm91dCIsIGljb24gPSBpY29uKCJpbmZvLXNpZ24iKSkKICAgICAgKSwKICAgICAgc2VsZWN0SW5wdXQoaW5wdXRJZCA9ICJnZW9fdmFsIiwgbGFiZWwgPSAiU2VsZWN0IGFuIGdlb2dyYXBoeToiLCBjaG9pY2VzID0gZ2VvX2lucHV0X2Nob2ljZXMsIHNlbGVjdGVkID0gZ2VvX2lucHV0X2Nob2ljZXNbMV0pLAogICAgICAjQ09NTUVOVCBMSU5FIEJFTE9XIElGIFlPVSBETyBOT1QgSEFWRSBBIFRFTVBPUkFMIFZBUklBQkxFIElOIFlPVVIgREFUQUZSQU1FCiAgICAgIGRhdGVSYW5nZUlucHV0KGlucHV0SWQgPSAiZGF0ZV92YWwiLCBsYWJlbCA9ICJTZWxlY3QgYSBkYXRlIHJhbmdlOiIsIHN0YXJ0ID0gZGF0ZV9pbnB1dF9zdGFydCRkYXRlLCBlbmQgPSBkYXRlX2lucHV0X2VuZCRkYXRlKQogICAgICAjQ09NTUVOVCBMSU5FIEFCT1ZFIElGIFlPVSBETyBOT1QgSEFWRSBBIFRFTVBPUkFMIFZBUklBQkxFIElOIFlPVVIgREFUQUZSQU1FCiAgKSwKICAKICBkYXNoYm9hcmRCb2R5KAogICAgdGFncyRoZWFkKHRhZ3Mkc3R5bGUoSFRNTCgnLmNvbnRlbnQtd3JhcHBlciB7IG92ZXJmbG93OiBhdXRvOyB9JykpKSwKICAgIHRhYkl0ZW1zKAogICAgICB0YWJJdGVtKHRhYk5hbWUgPSAiZGFzaGJvYXJkIiwKICAgICAgICBpbmZvQm94T3V0cHV0KCJ2YWx1ZTEiLCB3aWR0aCA9IDQpLAogICAgICAgIGluZm9Cb3hPdXRwdXQoInZhbHVlMiIsIHdpZHRoID0gNCksCiAgICAgICAgaW5mb0JveE91dHB1dCgidmFsdWUzIiwgd2lkdGggPSA0KSwKICAgICAgICAKICAgICAgICAjQ09NUExFVEUgVEhFIFNUQVRFTUVOVCBCRUxPVyBGT1IgVkFMVUVCT1ggMSAKICAgICAgICBib3godGFncyRwKCJUaGUgbnVtYmVyIGFib3ZlIGRvZXMgbm90IGFjY291bnQgZm9yLi4uIiksIHdpZHRoID0gNCksCiAgICAgICAgCiAgICAgICAgI0NPTVBMRVRFIFRIRSBTVEFURU1FTlQgQkVMT1cgRk9SIFZBTFVFQk9YIDIgCiAgICAgICAgYm94KHRhZ3MkcCgiVGhlIG51bWJlciBhYm92ZSBkb2VzIG5vdCBhY2NvdW50IGZvci4uLiIpLCB3aWR0aCA9IDQpLAogICAgICAgCiAgICAgICAgI0NPTVBMRVRFIFRIRSBTVEFURU1FTlQgQkVMT1cgRk9SIFZBTFVFQk9YIDMgCiAgICAgICAgYm94KHRhZ3MkcCgiVGhlIG51bWJlciBhYm92ZSBkb2VzIG5vdCBhY2NvdW50IGZvciBnaXQsIHNlZCBxdWlhIGNvbnNlcXV1bnR1ciBtYWduaSBkb2xvcmVzIGVvcyBxdWkgcmF0aW9uZSB2b2x1cHRhdGVtIHNlcXVpIG5lc2NpdW50LiBOZXF1ZSBwb3JybyBxdWlzcXVhbSBlc3QsIHF1aSBkb2xvcmVtIGlwc3VtIHF1aWEgZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyLCBhZGlwaXNjaSB2ZWxpdCwgc2VkIHF1aWEgbm9uIG51bXF1YW0gZWkiKSwgd2lkdGggPSA0KSwKICAgICAKICAgICAgICBib3gocGxvdE91dHB1dCgicGxvdDEiKSksCiAgICAgICAgYm94KHBsb3RPdXRwdXQoInBsb3QyIikpLAogICAgICAgIAogICAgICAgICNDT01QTEVURSBUSEUgU1RBVEVNRU5UIEJFTE9XIEZPUiBQTE9UIDEgICAgICAgIAogICAgICAgIGJveCh0YWdzJHAoIlRoZSBwbG90IGFib3ZlIGRvZXMgbm90IGFjY291bnQgZm9yLi4uIiksIHdpZHRoID0gNiksCiAgICAgICAgCiAgICAgICAgI0NPTVBMRVRFIFRIRSBTVEFURU1FTlQgQkVMT1cgRk9SIFBMT1QgMiAgCiAgICAgICAgYm94KHRhZ3MkcCgiVGhlIHBsb3QgYWJvdmUgZG9lcyBub3QgYWNjb3VudCBmb3IuLi4iKSwgd2lkdGggPSA2KSwKICAgICAgICAKICAgICAgICBib3gocGxvdE91dHB1dCgicGxvdDMiKSksCiAgICAgICAgYm94KHBsb3RPdXRwdXQoInBsb3Q0IikpLAogICAgICAgIAogICAgICAgICNDT01QTEVURSBUSEUgU1RBVEVNRU5UIEJFTE9XIEZPUiBQTE9UIDMKICAgICAgICBib3godGFncyRwKCJUaGUgcGxvdCBhYm92ZSBkb2VzIG5vdCBhY2NvdW50IGZvci4uLiIpLCB3aWR0aCA9IDYpLAogICAgICAgIAogICAgICAgICNDT01QTEVURSBUSEUgU1RBVEVNRU5UIEJFTE9XIEZPUiBQTE9UIDQKICAgICAgICBib3godGFncyRwKCJUaGUgcGxvdCBhYm92ZSBkb2VzIG5vdCBhY2NvdW50IGZvci4uLiIpLCB3aWR0aCA9IDYpCiAgICAgICksCiAgICAgIAojPT09PT09PT09PT09PT09PT09PT09PQojQ09QWSBBTkQgUEFTVEUgVEhFIFJFTUFJTkRFUiBPRiBUSEUgVUkgRlVOQ1RJT04gRlJPTSBMQUIgOCBCRUxPVwojPT09PT09PT09PT09PT09PT09PT09PQogICAgICB0YWJJdGVtKHRhYk5hbWUgPSAiYWJvdXQiLAogICAgICAgICAgICAgIHRhZ3MkaDEoIkRhdGEgU291cmNlIiksCiAgICAgICAgICAgICAgICAjUkVQTEFDRSBURVhUIElOIFFVT1RBVElPTlMgQkVMT1cgV0lUSCBZT1VSIE9XTiBURVhUIEFCT1VUIFlPVVIgREFUQSdTIFNPVVJDRQogICAgICAgICAgICAgIHRhZ3MkcCgiU2VkIHV0IHBlcnNwaWNpYXRpcyB1bmRlIG9tbmlzIGlzdGUgbmF0dXMgZXJyb3Igc2l0IHZvbHVwdGF0ZW0gYWNjdXNhbnRpdW0gZG9sb3JlbXF1ZSBsYXVkYW50aXVtLCB0b3RhbSByZW0gYXBlcmlhbSwgZWFxdWUgaXBzYSBxdWFlIGFiIGlsbG8gaW52ZW50b3JlIHZlcml0YXRpcyBldCBxdWFzaSBhcmNoaXRlY3RvIGJlYXRhZSB2aXRhZSBkaWN0YSBzdW50IGV4cGxpY2Fiby4gTmVtbyBlbmltIGlwc2FtIHZvbHVwdGF0ZW0gcXVpYSB2b2x1cHRhcyBzaXQgYXNwZXJuYXR1ciBhdXQgb2RpdCBhdXQgZnVnaXQsIHNlZCBxdWlhIGNvbnNlcXV1bnR1ciBtYWduaSBkb2xvcmVzIGVvcyBxdWkgcmF0aW9uZSB2b2x1cHRhdGVtIHNlcXVpIG5lc2NpdW50LiBOZXF1ZSBwb3JybyBxdWlzcXVhbSBlc3QsIHF1aSBkb2xvcmVtIGlwc3VtIHF1aWEgZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyLCBhZGlwaXNjaSB2ZWxpdCwgc2VkIHF1aWEgbm9uIG51bXF1YW0gZWl1cyBtb2RpIHRlbXBvcmEgaW5jaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYW0gYWxpcXVhbSBxdWFlcmF0IHZvbHVwdGF0ZW0uIFV0IGVuaW0gYWQgbWluaW1hIHZlbmlhbSwgcXVpcyBub3N0cnVtIGV4ZXJjaXRhdGlvbmVtIHVsbGFtIGNvcnBvcmlzIHN1c2NpcGl0IGxhYm9yaW9zYW0sIG5pc2kgdXQgYWxpcXVpZCBleCBlYSBjb21tb2RpIGNvbnNlcXVhdHVyPyBRdWlzIGF1dGVtIHZlbCBldW0gaXVyZSByZXByZWhlbmRlcml0IHF1aSBpbiBlYSB2b2x1cHRhdGUgdmVsaXQgZXNzZSBxdWFtIG5paGlsIG1vbGVzdGlhZSBjb25zZXF1YXR1ciwgdmVsIGlsbHVtIHF1aSBkb2xvcmVtIGV1bSBmdWdpYXQgcXVvIHZvbHVwdGFzIG51bGxhIHBhcmlhdHVyPyIpLAogICAgICAgICAgICAgICNSRVBMQUNFIFRFWFQgSU4gUVVPVEFUSU9OUyBBQk9WRSBXSVRIIFlPVVIgT1dOIFRFWFQgQUJPVVQgWU9VUiBEQVRBJ1MgU09VUkNFCiAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgdGFncyRoMSgiRGF0YSBDb250ZXh0IiksCiAgICAgICAgICAgICAgI1JFUExBQ0UgVEVYVCBJTiBRVU9UQVRJT05TIEJFTE9XIFdJVEggWU9VUiBPV04gVEVYVCBBQk9VVCBZT1VSIERBVEEnUyBDT05URVhUCiAgICAgICAgICAgICAgdGFncyRwKCJTZWQgdXQgcGVyc3BpY2lhdGlzIHVuZGUgb21uaXMgaXN0ZSBuYXR1cyBlcnJvciBzaXQgdm9sdXB0YXRlbSBhY2N1c2FudGl1bSBkb2xvcmVtcXVlIGxhdWRhbnRpdW0sIHRvdGFtIHJlbSBhcGVyaWFtLCBlYXF1ZSBpcHNhIHF1YWUgYWIgaWxsbyBpbnZlbnRvcmUgdmVyaXRhdGlzIGV0IHF1YXNpIGFyY2hpdGVjdG8gYmVhdGFlIHZpdGFlIGRpY3RhIHN1bnQgZXhwbGljYWJvLiBOZW1vIGVuaW0gaXBzYW0gdm9sdXB0YXRlbSBxdWlhIHZvbHVwdGFzIHNpdCBhc3Blcm5hdHVyIGF1dCBvZGl0IGF1dCBmdWdpdCwgc2VkIHF1aWEgY29uc2VxdXVudHVyIG1hZ25pIGRvbG9yZXMgZW9zIHF1aSByYXRpb25lIHZvbHVwdGF0ZW0gc2VxdWkgbmVzY2l1bnQuIE5lcXVlIHBvcnJvIHF1aXNxdWFtIGVzdCwgcXVpIGRvbG9yZW0gaXBzdW0gcXVpYSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0dXIsIGFkaXBpc2NpIHZlbGl0LCBzZWQgcXVpYSBub24gbnVtcXVhbSBlaXVzIG1vZGkgdGVtcG9yYSBpbmNpZHVudCB1dCBsYWJvcmUgZXQgZG9sb3JlIG1hZ25hbSBhbGlxdWFtIHF1YWVyYXQgdm9sdXB0YXRlbS4gVXQgZW5pbSBhZCBtaW5pbWEgdmVuaWFtLCBxdWlzIG5vc3RydW0gZXhlcmNpdGF0aW9uZW0gdWxsYW0gY29ycG9yaXMgc3VzY2lwaXQgbGFib3Jpb3NhbSwgbmlzaSB1dCBhbGlxdWlkIGV4IGVhIGNvbW1vZGkgY29uc2VxdWF0dXI/IFF1aXMgYXV0ZW0gdmVsIGV1bSBpdXJlIHJlcHJlaGVuZGVyaXQgcXVpIGluIGVhIHZvbHVwdGF0ZSB2ZWxpdCBlc3NlIHF1YW0gbmloaWwgbW9sZXN0aWFlIGNvbnNlcXVhdHVyLCB2ZWwgaWxsdW0gcXVpIGRvbG9yZW0gZXVtIGZ1Z2lhdCBxdW8gdm9sdXB0YXMgbnVsbGEgcGFyaWF0dXI/IiksCiAgICAgICAgICAgICAgI1JFUExBQ0UgVEVYVCBJTiBRVU9UQVRJT05TIEFCT1ZFIFdJVEggWU9VUiBPV04gVEVYVCBBQk9VVCBZT1VSIERBVEEnUyBTT1VSQ0UKICAgICAgICAgICAgICAKICAgICAgICAgICAgICB0YWdzJGgxKCJJbnNpZ2h0cyIpLAogICAgICAgICAgICAgICNSRVBMQUNFIFRFWFQgSU4gUVVPVEFUSU9OUyBCRUxPVyBXSVRIIFlPVVIgT1dOIFRFWFQgQUJPVVQgWU9VUiBJTlNJR0hUUwogICAgICAgICAgICAgIHRhZ3MkcCgiU2VkIHV0IHBlcnNwaWNpYXRpcyB1bmRlIG9tbmlzIGlzdGUgbmF0dXMgZXJyb3Igc2l0IHZvbHVwdGF0ZW0gYWNjdXNhbnRpdW0gZG9sb3JlbXF1ZSBsYXVkYW50aXVtLCB0b3RhbSByZW0gYXBlcmlhbSwgZWFxdWUgaXBzYSBxdWFlIGFiIGlsbG8gaW52ZW50b3JlIHZlcml0YXRpcyBldCBxdWFzaSBhcmNoaXRlY3RvIGJlYXRhZSB2aXRhZSBkaWN0YSBzdW50IGV4cGxpY2Fiby4gTmVtbyBlbmltIGlwc2FtIHZvbHVwdGF0ZW0gcXVpYSB2b2x1cHRhcyBzaXQgYXNwZXJuYXR1ciBhdXQgb2RpdCBhdXQgZnVnaXQsIHNlZCBxdWlhIGNvbnNlcXV1bnR1ciBtYWduaSBkb2xvcmVzIGVvcyBxdWkgcmF0aW9uZSB2b2x1cHRhdGVtIHNlcXVpIG5lc2NpdW50LiBOZXF1ZSBwb3JybyBxdWlzcXVhbSBlc3QsIHF1aSBkb2xvcmVtIGlwc3VtIHF1aWEgZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyLCBhZGlwaXNjaSB2ZWxpdCwgc2VkIHF1aWEgbm9uIG51bXF1YW0gZWl1cyBtb2RpIHRlbXBvcmEgaW5jaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYW0gYWxpcXVhbSBxdWFlcmF0IHZvbHVwdGF0ZW0uIFV0IGVuaW0gYWQgbWluaW1hIHZlbmlhbSwgcXVpcyBub3N0cnVtIGV4ZXJjaXRhdGlvbmVtIHVsbGFtIGNvcnBvcmlzIHN1c2NpcGl0IGxhYm9yaW9zYW0sIG5pc2kgdXQgYWxpcXVpZCBleCBlYSBjb21tb2RpIGNvbnNlcXVhdHVyPyBRdWlzIGF1dGVtIHZlbCBldW0gaXVyZSByZXByZWhlbmRlcml0IHF1aSBpbiBlYSB2b2x1cHRhdGUgdmVsaXQgZXNzZSBxdWFtIG5paGlsIG1vbGVzdGlhZSBjb25zZXF1YXR1ciwgdmVsIGlsbHVtIHF1aSBkb2xvcmVtIGV1bSBmdWdpYXQgcXVvIHZvbHVwdGFzIG51bGxhIHBhcmlhdHVyPyIpLAogICAgICAgICAgICAgICNSRVBMQUNFIFRFWFQgSU4gUVVPVEFUSU9OUyBBQk9WRSBXSVRIIFlPVVIgT1dOIFRFWFQgQUJPVVQgWU9VUiBJTlNJR0hUUwogICAgICAgICAgICAgIAogICAgICAgICAgICAgIHRhZ3MkaDEoIktub3dsZWRnZSBHYXBzIiksCiAgICAgICAgICAgICAgI1JFUExBQ0UgVEVYVCBJTiBRVU9UQVRJT05TIEJFTE9XIFdJVEggWU9VUiBPV04gVEVYVCBBQk9VVCBZT1VSIEtOT1dMRURHRSBHQVBTCiAgICAgICAgICAgICAgdGFncyRwKCJTZWQgdXQgcGVyc3BpY2lhdGlzIHVuZGUgb21uaXMgaXN0ZSBuYXR1cyBlcnJvciBzaXQgdm9sdXB0YXRlbSBhY2N1c2FudGl1bSBkb2xvcmVtcXVlIGxhdWRhbnRpdW0sIHRvdGFtIHJlbSBhcGVyaWFtLCBlYXF1ZSBpcHNhIHF1YWUgYWIgaWxsbyBpbnZlbnRvcmUgdmVyaXRhdGlzIGV0IHF1YXNpIGFyY2hpdGVjdG8gYmVhdGFlIHZpdGFlIGRpY3RhIHN1bnQgZXhwbGljYWJvLiBOZW1vIGVuaW0gaXBzYW0gdm9sdXB0YXRlbSBxdWlhIHZvbHVwdGFzIHNpdCBhc3Blcm5hdHVyIGF1dCBvZGl0IGF1dCBmdWdpdCwgc2VkIHF1aWEgY29uc2VxdXVudHVyIG1hZ25pIGRvbG9yZXMgZW9zIHF1aSByYXRpb25lIHZvbHVwdGF0ZW0gc2VxdWkgbmVzY2l1bnQuIE5lcXVlIHBvcnJvIHF1aXNxdWFtIGVzdCwgcXVpIGRvbG9yZW0gaXBzdW0gcXVpYSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0dXIsIGFkaXBpc2NpIHZlbGl0LCBzZWQgcXVpYSBub24gbnVtcXVhbSBlaXVzIG1vZGkgdGVtcG9yYSBpbmNpZHVudCB1dCBsYWJvcmUgZXQgZG9sb3JlIG1hZ25hbSBhbGlxdWFtIHF1YWVyYXQgdm9sdXB0YXRlbS4gVXQgZW5pbSBhZCBtaW5pbWEgdmVuaWFtLCBxdWlzIG5vc3RydW0gZXhlcmNpdGF0aW9uZW0gdWxsYW0gY29ycG9yaXMgc3VzY2lwaXQgbGFib3Jpb3NhbSwgbmlzaSB1dCBhbGlxdWlkIGV4IGVhIGNvbW1vZGkgY29uc2VxdWF0dXI/IFF1aXMgYXV0ZW0gdmVsIGV1bSBpdXJlIHJlcHJlaGVuZGVyaXQgcXVpIGluIGVhIHZvbHVwdGF0ZSB2ZWxpdCBlc3NlIHF1YW0gbmloaWwgbW9sZXN0aWFlIGNvbnNlcXVhdHVyLCB2ZWwgaWxsdW0gcXVpIGRvbG9yZW0gZXVtIGZ1Z2lhdCBxdW8gdm9sdXB0YXMgbnVsbGEgcGFyaWF0dXI/IikKICAgICAgICAgICAgICAjUkVQTEFDRSBURVhUIElOIFFVT1RBVElPTlMgQUJPVkUgV0lUSCBZT1VSIE9XTiBURVhUIEFCT1VUIFlPVVIgS05PV0xFREdFIEdBUFMKICAgICAgKQogICAgKQogICkKKQogIAojPT09PT09PT09PT09PT09PT09PT09PQojQ09QWSBBTkQgUEFTVEUgVEhFIFJFTUFJTkRFUiBPRiBUSEUgVUkgRlVOQ1RJT04gRlJPTSBMQUIgOCBBQk9WRQojPT09PT09PT09PT09PT09PT09PT09PQpgYGAKCldlIHdvbid0IGJlIHRvdWNoaW5nIHRoZSBzZXJ2ZXIgZnVuY3Rpb24gdGhpcyB3ZWVrLiBZb3UgY2FuIGNvcHkgYW5kIHBhc3RlIHlvdXJzIGZyb20gTGFiIDcgdG8gcmVwbGFjZSBteSBjb2RlIGJlbG93LiAKCmBgYHtyfQojPT09PT09PT09PT09PT09PT09PT09PQojQ09QWSBBTkQgUEFTVEUgVEhFIFNFUlZFUiBGVU5DVElPTiBGUk9NIExBQiA3IEJFTE9XCiM9PT09PT09PT09PT09PT09PT09PT09CgpzZXJ2ZXIgPC0gZnVuY3Rpb24oaW5wdXQsIG91dHB1dCkgewogIAogIG91dHB1dCR2YWx1ZTEgPC0gcmVuZGVySW5mb0JveCh7CiAgICBxdWFudF9pbnNpZ2h0MSA8LQogICAgI1JFUExBQ0UgaG9zcGl0YWxzIEJFTE9XIFdJVEggWU9VUiBPV04gREFUQUZSQU1FCiAgICBob3NwaXRhbHMgJT4lIAogICAgI1JFUExBQ0UgU1RBVEUgV0lUSCBZT1VSIE9XTiBHRU9HUkFQSElDIFZBUklBQkxFIEFORCBTT1VSQ0VEQVRFIFdJVEggWU9VUiBPV04gVEVNUE9SQUwgVkFSSUFCTEUKICAgICAgZmlsdGVyKAogICAgICAgIFNUQVRFID09IGlucHV0JGdlb192YWwgJiAKICAgICAgICBTT1VSQ0VEQVRFID4gaW5wdXQkZGF0ZV92YWxbMV0gJgogICAgICAgIFNPVVJDRURBVEUgPCBpbnB1dCRkYXRlX3ZhbFsyXQogICAgICAgICkgJT4lICAgICAgCiAgICAjQ09QWSBBTkQgUEFTVEUgWU9VUiBGVU5DVElPTiBIRVJFIEZST00gTEFCIDYKICAgICAgZmlsdGVyKFNUQVRVUyA9PSAiT1BFTiIgJiBUWVBFID09ICJHRU5FUkFMIEFDVVRFIENBUkUiKSAlPiUKICAgICAgc3VtbWFyaXplKG1lZGlhbl92YWx1ZSA9IG1lZGlhbihCRURTLCBuYS5ybSA9IFRSVUUpKQogICAgCiAgICAjUkVQTEFDRSAnRklMTCBERVNDUklQVElPTiBIRVJFJyBCRUxPVyBXSVRIIFlPVVIgT1dOIERFU0NSSVBUSU9OCiAgICBpbmZvQm94KHF1YW50X2luc2lnaHQxLCdGSUxMIERFU0NSSVBUSU9OIEhFUkUnLCBpY29uID0gaWNvbigic3RhdHMiLCBsaWI9J2dseXBoaWNvbicpLCBjb2xvciA9ICJwdXJwbGUiKQogIH0pCiAgCiAgb3V0cHV0JHZhbHVlMiA8LSByZW5kZXJJbmZvQm94KHsKICAgIHF1YW50X2luc2lnaHQyIDwtIAogICAgI1JFUExBQ0UgaG9zcGl0YWxzIEJFTE9XIFdJVEggWU9VUiBPV04gREFUQUZSQU1FCiAgICBob3NwaXRhbHMgJT4lIAogICAgI1JFUExBQ0UgU1RBVEUgV0lUSCBZT1VSIE9XTiBHRU9HUkFQSElDIFZBUklBQkxFIEFORCBTT1VSQ0VEQVRFIFdJVEggWU9VUiBPV04gVEVNUE9SQUwgVkFSSUFCTEUKICAgICAgZmlsdGVyKAogICAgICAgIFNUQVRFID09IGlucHV0JGdlb192YWwgJiAKICAgICAgICBTT1VSQ0VEQVRFID4gaW5wdXQkZGF0ZV92YWxbMV0gJgogICAgICAgIFNPVVJDRURBVEUgPCBpbnB1dCRkYXRlX3ZhbFsyXQogICAgICAgICkgJT4lCiAgICAjQ09QWSBBTkQgUEFTVEUgWU9VUiBGVU5DVElPTiBIRVJFIEZST00gTEFCIDYKICAgICAgZmlsdGVyKFNUQVRVUyA9PSAiT1BFTiIgJiBUWVBFID09ICJHRU5FUkFMIEFDVVRFIENBUkUiKSAlPiUKICAgICAgc3VtbWFyaXplKG1lZGlhbl92YWx1ZSA9IG1lZGlhbihCRURTLCBuYS5ybSA9IFRSVUUpKQogICAgCiAgICAjUkVQTEFDRSAnRklMTCBERVNDUklQVElPTiBIRVJFJyBCRUxPVyBXSVRIIFlPVVIgT1dOIERFU0NSSVBUSU9OCiAgICBpbmZvQm94KHF1YW50X2luc2lnaHQyLCdGSUxMIERFU0NSSVBUSU9OIEhFUkUnLCBpY29uID0gaWNvbigic3RhdHMiLCBsaWI9J2dseXBoaWNvbicpLCBjb2xvciA9ICJwdXJwbGUiKQogIH0pCiAgCiAgb3V0cHV0JHZhbHVlMyA8LSByZW5kZXJJbmZvQm94KHsKICAgIHF1YW50X2luc2lnaHQzIDwtIAogICAgI1JFUExBQ0UgaG9zcGl0YWxzIEJFTE9XIFdJVEggWU9VUiBPV04gREFUQUZSQU1FCiAgICBob3NwaXRhbHMgJT4lIAogICAgI1JFUExBQ0UgU1RBVEUgV0lUSCBZT1VSIE9XTiBHRU9HUkFQSElDIFZBUklBQkxFIEFORCBTT1VSQ0VEQVRFIFdJVEggWU9VUiBPV04gVEVNUE9SQUwgVkFSSUFCTEUKICAgICAgZmlsdGVyKAogICAgICAgIFNUQVRFID09IGlucHV0JGdlb192YWwgJiAKICAgICAgICBTT1VSQ0VEQVRFID4gaW5wdXQkZGF0ZV92YWxbMV0gJgogICAgICAgIFNPVVJDRURBVEUgPCBpbnB1dCRkYXRlX3ZhbFsyXQogICAgICAgICkgJT4lCiAgICAjQ09QWSBBTkQgUEFTVEUgWU9VUiBGVU5DVElPTiBIRVJFIEZST00gTEFCIDYKICAgICAgZmlsdGVyKFNUQVRVUyA9PSAiT1BFTiIgJiBUWVBFID09ICJHRU5FUkFMIEFDVVRFIENBUkUiKSAlPiUKICAgICAgc3VtbWFyaXplKG1lZGlhbl92YWx1ZSA9IG1lZGlhbihCRURTLCBuYS5ybSA9IFRSVUUpKQoKICAgICNSRVBMQUNFICdGSUxMIERFU0NSSVBUSU9OIEhFUkUnIEJFTE9XIFdJVEggWU9VUiBPV04gREVTQ1JJUFRJT04KICAgIGluZm9Cb3gocXVhbnRfaW5zaWdodDMsJ0ZJTEwgREVTQ1JJUFRJT04gSEVSRScsIGljb24gPSBpY29uKCJzdGF0cyIsIGxpYj0nZ2x5cGhpY29uJyksIGNvbG9yID0gInB1cnBsZSIpCiAgfSkKICAKICBvdXRwdXQkcGxvdDEgPC0gcmVuZGVyUGxvdCh7CiAgICAjUkVQTEFDRSBob3NwaXRhbHMgQkVMT1cgV0lUSCBZT1VSIE9XTiBEQVRBRlJBTUUKICAgIGhvc3BpdGFscyAlPiUgCiAgICAjUkVQTEFDRSBTVEFURSBXSVRIIFlPVVIgT1dOIEdFT0dSQVBISUMgVkFSSUFCTEUgQU5EIFNPVVJDRURBVEUgV0lUSCBZT1VSIE9XTiBURU1QT1JBTCBWQVJJQUJMRQogICAgICBmaWx0ZXIoCiAgICAgICAgU1RBVEUgPT0gaW5wdXQkZ2VvX3ZhbCAmIAogICAgICAgIFNPVVJDRURBVEUgPiBpbnB1dCRkYXRlX3ZhbFsxXSAmCiAgICAgICAgU09VUkNFREFURSA8IGlucHV0JGRhdGVfdmFsWzJdCiAgICAgICAgKSAlPiUKICAgICNDT1BZIEFORCBQQVNURSBZT1VSIFBMT1QgSEVSRSBGUk9NIExBQiA2CiAgICAgIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICAgICAgZ2dwbG90KGFlcyh4ID0gVFlQRSkpICsgCiAgICAgIGdlb21fYmFyKCkgKwogICAgICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBIb3NwaXRhbHMgaW4gdGhlIFVTIHRoYXQgYXJlIE9wZW4gYnkgVHlwZSIsIHggPSAiVHlwZSIsIHkgPSAiQ291bnQgb2YgSG9zcGl0YWxzIikgKyAKICAgICAgdGhlbWVfYncoKSArCiAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0PTEpKSAKICB9KQogIAogIG91dHB1dCRwbG90MiA8LSByZW5kZXJQbG90KHsKICAgICNSRVBMQUNFIGhvc3BpdGFscyBCRUxPVyBXSVRIIFlPVVIgT1dOIERBVEFGUkFNRQogICAgaG9zcGl0YWxzICU+JSAKICAgICNSRVBMQUNFIFNUQVRFIFdJVEggWU9VUiBPV04gR0VPR1JBUEhJQyBWQVJJQUJMRSBBTkQgU09VUkNFREFURSBXSVRIIFlPVVIgT1dOIFRFTVBPUkFMIFZBUklBQkxFCiAgICAgIGZpbHRlcigKICAgICAgICBTVEFURSA9PSBpbnB1dCRnZW9fdmFsICYgCiAgICAgICAgU09VUkNFREFURSA+IGlucHV0JGRhdGVfdmFsWzFdICYKICAgICAgICBTT1VSQ0VEQVRFIDwgaW5wdXQkZGF0ZV92YWxbMl0KICAgICAgICApICU+JQogICAgI0NPUFkgQU5EIFBBU1RFIFlPVVIgUExPVCBIRVJFIEZST00gTEFCIDYKICAgICAgZmlsdGVyKFNUQVRVUyA9PSAiT1BFTiIpICU+JQogICAgICBnZ3Bsb3QoYWVzKHggPSBUWVBFKSkgKyAKICAgICAgZ2VvbV9iYXIoKSArCiAgICAgIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIEhvc3BpdGFscyBpbiB0aGUgVVMgdGhhdCBhcmUgT3BlbiBieSBUeXBlIiwgeCA9ICJUeXBlIiwgeSA9ICJDb3VudCBvZiBIb3NwaXRhbHMiKSArIAogICAgICB0aGVtZV9idygpICsKICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3Q9MSkpIAogIH0pCiAgCiAgb3V0cHV0JHBsb3QzIDwtIHJlbmRlclBsb3QoewogICAgI1JFUExBQ0UgaG9zcGl0YWxzIEJFTE9XIFdJVEggWU9VUiBPV04gREFUQUZSQU1FCiAgICBob3NwaXRhbHMgJT4lIAogICAgI1JFUExBQ0UgU1RBVEUgV0lUSCBZT1VSIE9XTiBHRU9HUkFQSElDIFZBUklBQkxFIEFORCBTT1VSQ0VEQVRFIFdJVEggWU9VUiBPV04gVEVNUE9SQUwgVkFSSUFCTEUKICAgICAgZmlsdGVyKAogICAgICAgIFNUQVRFID09IGlucHV0JGdlb192YWwgJiAKICAgICAgICBTT1VSQ0VEQVRFID4gaW5wdXQkZGF0ZV92YWxbMV0gJgogICAgICAgIFNPVVJDRURBVEUgPCBpbnB1dCRkYXRlX3ZhbFsyXQogICAgICAgICkgJT4lCiAgICAjQ09QWSBBTkQgUEFTVEUgWU9VUiBQTE9UIEhFUkUgRlJPTSBMQUIgNgogICAgICBmaWx0ZXIoU1RBVFVTID09ICJPUEVOIikgJT4lCiAgICAgIGdncGxvdChhZXMoeCA9IFRZUEUpKSArIAogICAgICBnZW9tX2JhcigpICsKICAgICAgbGFicyh0aXRsZSA9ICJOdW1iZXIgb2YgSG9zcGl0YWxzIGluIHRoZSBVUyB0aGF0IGFyZSBPcGVuIGJ5IFR5cGUiLCB4ID0gIlR5cGUiLCB5ID0gIkNvdW50IG9mIEhvc3BpdGFscyIpICsgCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdD0xKSkgCiAgfSkKICAKICBvdXRwdXQkcGxvdDQgPC0gcmVuZGVyUGxvdCh7CiAgICAjUkVQTEFDRSBob3NwaXRhbHMgQkVMT1cgV0lUSCBZT1VSIE9XTiBEQVRBRlJBTUUKICAgIGhvc3BpdGFscyAlPiUgCiAgICAjUkVQTEFDRSBTVEFURSBXSVRIIFlPVVIgT1dOIEdFT0dSQVBISUMgVkFSSUFCTEUgQU5EIFNPVVJDRURBVEUgV0lUSCBZT1VSIE9XTiBURU1QT1JBTCBWQVJJQUJMRQogICAgICBmaWx0ZXIoCiAgICAgICAgU1RBVEUgPT0gaW5wdXQkZ2VvX3ZhbCAmIAogICAgICAgIFNPVVJDRURBVEUgPiBpbnB1dCRkYXRlX3ZhbFsxXSAmCiAgICAgICAgU09VUkNFREFURSA8IGlucHV0JGRhdGVfdmFsWzJdCiAgICAgICAgKSAlPiUKICAgICNDT1BZIEFORCBQQVNURSBZT1VSIFBMT1QgSEVSRSBGUk9NIExBQiA2CiAgICAgIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICAgICAgZ2dwbG90KGFlcyh4ID0gVFlQRSkpICsgCiAgICAgIGdlb21fYmFyKCkgKwogICAgICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBIb3NwaXRhbHMgaW4gdGhlIFVTIHRoYXQgYXJlIE9wZW4gYnkgVHlwZSIsIHggPSAiVHlwZSIsIHkgPSAiQ291bnQgb2YgSG9zcGl0YWxzIikgKyAKICAgICAgdGhlbWVfYncoKSArCiAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0PTEpKSAKICB9KQp9IAojPT09PT09PT09PT09PT09PT09PT09PQojQ09QWSBBTkQgUEFTVEUgVEhFIFNFUlZFUiBGVU5DVElPTiBGUk9NIExBQiA3IEFCT1ZFCiM9PT09PT09PT09PT09PT09PT09PT09CmBgYAoKYGBge3J9CnNoaW55QXBwKHVpLCBzZXJ2ZXIpCmBgYAoK