** I decided to work with 500 Cities: Local Data for Better Health, 2021 and 2019 release.This is the complete dataset for the 500 Cities project model-based small area estimates for 27 measures of chronic disease related to unhealthy behaviors (5), health outcomes (13), and use of preventive services (9). Data were provided by the Centers for Disease Control and Prevention (CDC), Division of Population Health, Epidemiology and Surveillance Branch. The 2021 dataset includes 2018 and 2019 year. And 2019 release has data from 2016 and 2017. **
Load Library
library(readr)
library(tidyr) #To clean data
library(readxl) #To import data
library(tidyverse) #To manipulate data
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5 v dplyr 1.0.7
## v tibble 3.1.6 v stringr 1.4.0
## v purrr 0.3.4 v forcats 0.5.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(maps) #To get the U.S. map
## Warning: package 'maps' was built under R version 4.1.3
##
## Attaching package: 'maps'
## The following object is masked from 'package:purrr':
##
## map
library(mapdata) #To be able to map latitude and longitude on the map graph
## Warning: package 'mapdata' was built under R version 4.1.3
library(ggmap) #Another package to create the map
## Warning: package 'ggmap' was built under R version 4.1.3
## Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
## Please cite ggmap if you use it! See citation("ggmap") for details.
library(dplyr) #To manipulate data
library(ggplot2) #To create graphs
library(DT) #To create tables
## Warning: package 'DT' was built under R version 4.1.3
library(ggcorrplot) #To create the correlation plot
## Warning: package 'ggcorrplot' was built under R version 4.1.3
library(outliers) #To find outliers in the data
## Warning: package 'outliers' was built under R version 4.1.3
Data Cleaning
** At first, I imported the dataset. Then I filter to include the information for city on the geographic level and exclude all census tract to lower the size of dataset. I focussed on Age_Adjusted Prevalence, so I filtered the data by Data ValueTypeID filter to work with Mental Health among adult whose mental health not god for 14 or more than 14 days. I will filter it by Measure = “Mental health not good for >=14 days among adults aged >=18 Years” **
Data_2021 <- read.csv("C:/Users/shahi/Desktop/blogpost/PLACES__Local_Data_for_Better_Health__County_Data_2021_release.csv")
Filter_Data_2021 <- Data_2021
Filter_Data_2021 <- Filter_Data_2021 %>% filter(DataValueTypeID=="AgeAdjPrv")
Data_Mental_Health_2021 <- Filter_Data_2021 %>% filter(Measure=="Mental health not good for >=14 days among adults aged >=18 years")
head(Data_Mental_Health_2021)
** Here I filter the data to create new column for different Data_ValueTypeID_Value so we can calculate the average valuetypid and also for the total of the population whcih will sum the number of population for all cities. I will also do some data aggregation and mutate so I can have a final dataset with only state with TotalPopulation, state name, datasource, category, and geolocation. **
Filter_Data_2021_2 <- Data_Mental_Health_2021 %>% select(StateAbbr,StateDesc,DataSource,Category,
Measure,Data_Value_Type,Data_Value,TotalPopulation,Geolocation,CategoryID)
Filter_Data_2021_2 <- na.omit(Filter_Data_2021_2)
sv_21 <- aggregate(TotalPopulation~StateAbbr+StateDesc+DataSource+Category+Measure+Data_Value_Type, data=Filter_Data_2021_2, FUN=sum)
sv2_21 <- aggregate(Data_Value~StateAbbr+StateDesc+DataSource+Category+Measure+Data_Value_Type, data=Filter_Data_2021_2, FUN=mean)
sv5_21 <- Filter_Data_2021_2 %>% distinct(StateDesc, .keep_all = TRUE)
sv5_21 <- sv5_21 %>% select(StateAbbr,StateDesc,DataSource,Category,Measure,Data_Value_Type,Geolocation)
sv5_21 <- na.omit(sv5_21)
sv5_21 <- sv5_21[order(sv5_21$StateDesc),]
combined_data_21 <- cbind(sv_21,sv2_21,sv5_21)
combined_data2_21 <- combined_data_21[ -c(8:13,15:20,22:27,29:34) ]
combined_data2_21 <- combined_data2_21 %>% mutate_if(is.numeric, ~round(., 1))
head(combined_data2_21)
** I have already dropped a lot of unwanted variables from the dataset and keep only those variable that I need for analysis. **
** I downloaeded the shapefile from the United Census Bureau to read the US state boundaries shapefile and to plot the choropleth **
Drawing Plot
library(rgdal)
## Warning: package 'rgdal' was built under R version 4.1.3
## Loading required package: sp
## Please note that rgdal will be retired by the end of 2023,
## plan transition to sf/stars/terra functions using GDAL and PROJ
## at your earliest convenience.
##
## rgdal: version: 1.5-30, (SVN revision 1171)
## Geospatial Data Abstraction Library extensions to R successfully loaded
## Loaded GDAL runtime: GDAL 3.4.1, released 2021/12/27
## Path to GDAL shared files: C:/Users/shahi/Documents/R/win-library/4.1/rgdal/gdal
## GDAL binary built with GEOS: TRUE
## Loaded PROJ runtime: Rel. 7.2.1, January 1st, 2021, [PJ_VERSION: 721]
## Path to PROJ shared files: C:/Users/shahi/Documents/R/win-library/4.1/rgdal/proj
## PROJ CDN enabled: FALSE
## Linking to sp version:1.4-6
## To mute warnings of possible GDAL/OSR exportToProj4() degradation,
## use options("rgdal_show_exportToProj4_warnings"="none") before loading sp or rgdal.
setwd("C:/Users/shahi/Desktop/blogpost")
State_boundaries_21 <- readOGR('C:/Users/shahi/Desktop/blogpost/cb_2017_us_state_500k.shp')
## OGR data source with driver: ESRI Shapefile
## Source: "C:\Users\shahi\Desktop\blogpost\cb_2017_us_state_500k.shp", layer: "cb_2017_us_state_500k"
## with 56 features
## It has 9 fields
## Integer64 fields read as strings: ALAND AWATER
** Now, I will organize the final dataset that I will use in my choropleth. After I did all the data manipulation, I will merge the dataset with polygons data to have a polygons where all values are included and also the name of state. I will have here a LargeSpatialPolygon, where I will merge the dataset here and I will use it to map. **
Joint_Data_21 <- full_join(State_boundaries_21@data, combined_data2_21, by = c("STUSPS" = "StateAbbr"))
tmp.l2 <- na.omit(Joint_Data_21)
test_21 <- tmp.l2 %>% distinct(STATENS, .keep_all = TRUE)
head(test_21)
** Here I will draw plots for specific leaflet such as name of the state, population, source of data, measure and measure category,age-adjusted prevalence.I also added popup display which will show information about specific dataset. When clicked on the specific state, it will show the population count and other information. **
library(leaflet)
## Warning: package 'leaflet' was built under R version 4.1.3
library(RColorBrewer)
library(classInt)
bins <- c(1000000, 300000, 500000, 900000, 2000000, 3000000, 4000000, 50000000, 60000000, 70000000, Inf)
#breaks_qt <- classIntervals(test_21$TotalPopulation, n = 5, style = "quantile")
pal <- colorBin("YlOrRd", domain = test_21$TotalPopulation, bins = bins)
labels <- sprintf("<strong>%s</strong>",State_boundaries_21$NAME) %>% lapply(htmltools::HTML)
leaflet(State_boundaries_21) %>%
setView(-96, 37.8, 4) %>%
addProviderTiles("OpenStreetMap") %>%
addPolygons(data = State_boundaries_21,
fillColor = ~pal(test_21$TotalPopulation),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlightOptions = highlightOptions(
weight = 5,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
label = labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto"),
popup = ~paste("<strong>State: </strong>",NAME, paste("<br><strong>Measure: </strong>", test_21$Measure), paste("<br><strong>Data Source: </strong>", test_21$DataSource),paste("<br><strong>Category: </strong>", test_21$Category),paste("<br><strong>Population (Measure): </strong>", test_21$TotalPopulation), paste("<br><strong>Data Value Type : </strong>", test_21$Data_Value_Type),paste("<br><strong>Age-Adjusted Prevalence % : </strong>", test_21$Data_Value))) %>%
addLegend(pal = pal, values = ~test_21$TotalPopulation, opacity = 0.7, title = "Population Count",
position = "bottomright")
## Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette YlOrRd is 9
## Returning the palette you asked for with that many colors
## Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette YlOrRd is 9
## Returning the palette you asked for with that many colors
** Among them Florida and West Virginia have the highest prevalence rate (28.8%), Ohio – 27.8%, North Dakota – 27%, Nevada (25.4%), Wyoming (25.3%), California (25.1%), Wisconsin (24.8%), Mississippi (24.7%), Oregon (24.6%) in 2018-2019. Comparing to 2016-2017, the states North Carolina and Utah (16.8%) which had the highest prevalence rate in USA is replaced by Florida and West Virginia (28,8%). The overall age-adjusted prevalence rate is increasing rapidly, and mental health condition has also changed in these states. North Dakota, Wyoming, California, Nevada, Wisconsin, Ohio, Tennessee has added newly in high prevalence rate of poor mental health. So, there may be some reasons behind this poor mental health outcome. **
Analysis of 2019 Data
Data <- read.csv("C:/Users/shahi/Desktop/blogpost/500_Cities__Local_Data_for_Better_Health__2019_release.csv")
Filter_Data <- Data
Filter_Data <- Filter_Data %>% filter(DataValueTypeID=="AgeAdjPrv")
Data_Mental_Health <- Filter_Data %>% filter(Measure=="Mental health not good for >=14 days among adults aged >=18 Years")
head(Data_Mental_Health)
Filter_Data_2 <- Data_Mental_Health %>% select(StateAbbr,StateDesc,DataSource,Category,
Measure,Data_Value_Type,Data_Value,PopulationCount,GeoLocation,CategoryID)
Filter_Data_2 <- na.omit(Filter_Data_2)
sv <- aggregate(PopulationCount~StateAbbr+StateDesc+DataSource+Category+Measure+Data_Value_Type, data=Filter_Data_2, FUN=sum)
sv2 <- aggregate(Data_Value~StateAbbr+StateDesc+DataSource+Category+Measure+Data_Value_Type, data=Filter_Data_2, FUN=mean)
sv5 <- Filter_Data_2 %>% distinct(StateDesc, .keep_all = TRUE)
sv5 <- sv5 %>% select(StateAbbr,StateDesc,DataSource,Category,Measure,Data_Value_Type,GeoLocation)
sv5 <- na.omit(sv5)
sv5 <- sv5[order(sv5$StateDesc),]
combined_data <- cbind(sv,sv2,sv5)
combined_data2 <- combined_data[ -c(8:13,15:20,22:27,29:34) ]
combined_data2 <- combined_data2 %>% mutate_if(is.numeric, ~round(., 1))
head(combined_data2)
library(rgdal)
setwd("C:/Users/shahi/Desktop/blogpost")
State_boundaries <- readOGR('C:/Users/shahi/Desktop/blogpost/cb_2017_us_state_500k.shp')
## OGR data source with driver: ESRI Shapefile
## Source: "C:\Users\shahi\Desktop\blogpost\cb_2017_us_state_500k.shp", layer: "cb_2017_us_state_500k"
## with 56 features
## It has 9 fields
## Integer64 fields read as strings: ALAND AWATER
Joint_Data <- full_join(State_boundaries@data, combined_data2, by = c("STUSPS" = "StateAbbr"))
tmp.l2 <- na.omit(Joint_Data)
test <- tmp.l2 %>% distinct(STATENS, .keep_all = TRUE)
head(test)
library(leaflet)
library(RColorBrewer)
library(classInt)
bin19 <- c(10000, 100000, 200000, 400000, 900000, 1000000, 3000000, 4000000, 50000000, 60000000, Inf)
#breaks_qt <- classIntervals(test_21$TotalPopulation, n = 5, style = "quantile")
pal <- colorBin("YlOrRd", domain = test$PopulationCount, bins = bin19)
labels <- sprintf("<strong>%s</strong>",State_boundaries$NAME) %>% lapply(htmltools::HTML)
leaflet(State_boundaries) %>%
setView(-96, 37.8, 4) %>%
addProviderTiles("OpenStreetMap") %>%
addPolygons(data = State_boundaries,
fillColor = ~pal(test$PopulationCount),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlightOptions = highlightOptions(
weight = 5,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
label = labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto"),
popup = ~paste("<strong>State: </strong>",NAME, paste("<br><strong>Measure: </strong>", test$Measure), paste("<br><strong>Data Source: </strong>", test$DataSource),paste("<br><strong>Category: </strong>", test$Category),paste("<br><strong>Population (Measure): </strong>", test$PopulationCount), paste("<br><strong>Data Value Type : </strong>", test$Data_Value_Type),paste("<br><strong>Age-Adjusted Prevalence % : </strong>", test$Data_Value))) %>%
addLegend(pal = pal, values = ~test$PopulationCount, opacity = 0.7, title = "Population Count",
position = "bottomright")
## Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette YlOrRd is 9
## Returning the palette you asked for with that many colors
## Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette YlOrRd is 9
## Returning the palette you asked for with that many colors
** I found North Carolina & Utah (16.8%), Pennsylvania & West Virginia (16.5%), Washington (16.2%), New Jersey(15.9%), Alabama & Maryland (15.7%), Arizona (15.5%), Mississippi (15.3%), and Texas (15%) have high age-adjusted prevalence rate for mental health than other states of USA in 2016-2017 period. **
REPORT
** In this project, I wanted to know how people are suffering from mental stress in different states of USA. I got results for all the states. I used 2021 release and 2019 release to observe the differences of mental stress over the year. The percentage of depression is changing over the time in different states. For example, in TEXAS, the population count was 1836343 and 15% of them were suffering from mental stress. However, in 2021 release, the total population count was 19453561 and among them 14.7% are suffering from mental stress. So, the mental stress rate is increasing but varies from state to state. **
** Limitation: I wanted to observe geographic hotspot of mental stress before pandemic, during pandemic. But due to unavailability of the recent data, I could not do the analysis. I could not control the analysis for SES variable. **
** Future Direction: After publishing data for 2020-2022, I will compare the pre-pandemic and pandemic period mental stress over the states, and if possible to cities. Also, I want to know how Pandemic had an effect geographically over the United States. **
LS0tDQp0aXRsZTogICJibG9nIHBvc3QgNCINCmF1dGhvcjogIk1haG11ZGEgU3VsdGFuYSINCmRhdGU6ICAgIjUvNC8yMDIyIg0Kb3V0cHV0OiANCiAgIGh0bWxfZG9jdW1lbnQ6DQogICAgIGRmX3ByaW50OiBwYWdlZA0KICAgICBmaWdfaGVpZ2h0OiA3DQogICAgIGZpZ193aWR0aDogNw0KICAgICB0b2M6IHllcw0KICAgICB0b2NfZmxvYXQ6IHllcw0KICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KDQoqKiBJIGRlY2lkZWQgdG8gd29yayB3aXRoIDUwMCBDaXRpZXM6IExvY2FsIERhdGEgZm9yIEJldHRlciBIZWFsdGgsIDIwMjEgYW5kIDIwMTkgcmVsZWFzZS5UaGlzIGlzIHRoZSBjb21wbGV0ZSBkYXRhc2V0IGZvciB0aGUgNTAwIENpdGllcyBwcm9qZWN0IG1vZGVsLWJhc2VkIHNtYWxsIGFyZWEgZXN0aW1hdGVzIGZvciAyNyBtZWFzdXJlcyBvZiBjaHJvbmljIGRpc2Vhc2UgcmVsYXRlZCB0byB1bmhlYWx0aHkgYmVoYXZpb3JzICg1KSwgaGVhbHRoIG91dGNvbWVzICgxMyksIGFuZCB1c2Ugb2YgcHJldmVudGl2ZSBzZXJ2aWNlcyAoOSkuIERhdGEgd2VyZSBwcm92aWRlZCBieSB0aGUgQ2VudGVycyBmb3IgRGlzZWFzZSBDb250cm9sIGFuZCBQcmV2ZW50aW9uIChDREMpLCBEaXZpc2lvbiBvZiBQb3B1bGF0aW9uIEhlYWx0aCwgRXBpZGVtaW9sb2d5IGFuZCBTdXJ2ZWlsbGFuY2UgQnJhbmNoLiBUaGUgMjAyMSBkYXRhc2V0IGluY2x1ZGVzIDIwMTggYW5kIDIwMTkgeWVhci4gQW5kIDIwMTkgcmVsZWFzZSBoYXMgZGF0YSBmcm9tIDIwMTYgYW5kIDIwMTcuICoqDQoNCg0KIyMjIExvYWQgTGlicmFyeQ0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHRpZHlyKSAjVG8gY2xlYW4gZGF0YQ0KbGlicmFyeShyZWFkeGwpICNUbyBpbXBvcnQgZGF0YQ0KbGlicmFyeSh0aWR5dmVyc2UpICNUbyBtYW5pcHVsYXRlIGRhdGENCmxpYnJhcnkobWFwcykgI1RvIGdldCB0aGUgVS5TLiBtYXANCmxpYnJhcnkobWFwZGF0YSkgI1RvIGJlIGFibGUgdG8gbWFwIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgb24gdGhlIG1hcCBncmFwaA0KbGlicmFyeShnZ21hcCkgI0Fub3RoZXIgcGFja2FnZSB0byBjcmVhdGUgdGhlIG1hcA0KbGlicmFyeShkcGx5cikgI1RvIG1hbmlwdWxhdGUgZGF0YQ0KbGlicmFyeShnZ3Bsb3QyKSAjVG8gY3JlYXRlIGdyYXBocw0KbGlicmFyeShEVCkgI1RvIGNyZWF0ZSB0YWJsZXMNCmxpYnJhcnkoZ2djb3JycGxvdCkgI1RvIGNyZWF0ZSB0aGUgY29ycmVsYXRpb24gcGxvdA0KbGlicmFyeShvdXRsaWVycykgI1RvIGZpbmQgb3V0bGllcnMgaW4gdGhlIGRhdGENCmBgYA0KDQoNCiMjIyBEYXRhIENsZWFuaW5nDQoNCioqIEF0IGZpcnN0LCBJIGltcG9ydGVkIHRoZSBkYXRhc2V0LiBUaGVuIEkgZmlsdGVyIHRvIGluY2x1ZGUgdGhlIGluZm9ybWF0aW9uIGZvciBjaXR5IG9uIHRoZSBnZW9ncmFwaGljIGxldmVsIGFuZCBleGNsdWRlIGFsbCBjZW5zdXMgdHJhY3QgdG8gbG93ZXIgdGhlIHNpemUgb2YgZGF0YXNldC4gSSBmb2N1c3NlZCBvbiBBZ2VfQWRqdXN0ZWQgUHJldmFsZW5jZSwgc28gSSBmaWx0ZXJlZCB0aGUgZGF0YSBieSBEYXRhIFZhbHVlVHlwZUlEIGZpbHRlciB0byB3b3JrIHdpdGggTWVudGFsIEhlYWx0aCBhbW9uZyBhZHVsdCB3aG9zZSBtZW50YWwgaGVhbHRoIG5vdCBnb2QgZm9yIDE0IG9yIG1vcmUgdGhhbiAxNCBkYXlzLiBJIHdpbGwgZmlsdGVyIGl0IGJ5IE1lYXN1cmUgPSAiTWVudGFsIGhlYWx0aCBub3QgZ29vZCBmb3IgPj0xNCBkYXlzIGFtb25nIGFkdWx0cyBhZ2VkID49MTggWWVhcnMiICoqDQoNCmBgYHtyfQ0KRGF0YV8yMDIxIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9zaGFoaS9EZXNrdG9wL2Jsb2dwb3N0L1BMQUNFU19fTG9jYWxfRGF0YV9mb3JfQmV0dGVyX0hlYWx0aF9fQ291bnR5X0RhdGFfMjAyMV9yZWxlYXNlLmNzdiIpDQpgYGANCg0KDQpgYGB7cn0NCkZpbHRlcl9EYXRhXzIwMjEgPC0gRGF0YV8yMDIxDQpGaWx0ZXJfRGF0YV8yMDIxIDwtIEZpbHRlcl9EYXRhXzIwMjEgJT4lIGZpbHRlcihEYXRhVmFsdWVUeXBlSUQ9PSJBZ2VBZGpQcnYiKQ0KRGF0YV9NZW50YWxfSGVhbHRoXzIwMjEgPC0gRmlsdGVyX0RhdGFfMjAyMSAlPiUgZmlsdGVyKE1lYXN1cmU9PSJNZW50YWwgaGVhbHRoIG5vdCBnb29kIGZvciA+PTE0IGRheXMgYW1vbmcgYWR1bHRzIGFnZWQgPj0xOCB5ZWFycyIpDQoNCmhlYWQoRGF0YV9NZW50YWxfSGVhbHRoXzIwMjEpDQpgYGANCg0KDQoqKiBIZXJlIEkgZmlsdGVyIHRoZSBkYXRhIHRvIGNyZWF0ZSBuZXcgY29sdW1uIGZvciBkaWZmZXJlbnQgRGF0YV9WYWx1ZVR5cGVJRF9WYWx1ZSBzbyB3ZSBjYW4gY2FsY3VsYXRlIHRoZSBhdmVyYWdlIHZhbHVldHlwaWQgYW5kIGFsc28gZm9yIHRoZSB0b3RhbCBvZiB0aGUgcG9wdWxhdGlvbiB3aGNpaCB3aWxsIHN1bSB0aGUgbnVtYmVyIG9mIHBvcHVsYXRpb24gZm9yIGFsbCBjaXRpZXMuIEkgd2lsbCBhbHNvIGRvIHNvbWUgZGF0YSBhZ2dyZWdhdGlvbiBhbmQgbXV0YXRlIHNvIEkgY2FuIGhhdmUgYSBmaW5hbCBkYXRhc2V0IHdpdGggb25seSBzdGF0ZSB3aXRoIFRvdGFsUG9wdWxhdGlvbiwgc3RhdGUgbmFtZSwgZGF0YXNvdXJjZSwgY2F0ZWdvcnksIGFuZCBnZW9sb2NhdGlvbi4gKioNCg0KDQpgYGB7cn0NCg0KRmlsdGVyX0RhdGFfMjAyMV8yIDwtIERhdGFfTWVudGFsX0hlYWx0aF8yMDIxICU+JSBzZWxlY3QoU3RhdGVBYmJyLFN0YXRlRGVzYyxEYXRhU291cmNlLENhdGVnb3J5LA0KTWVhc3VyZSxEYXRhX1ZhbHVlX1R5cGUsRGF0YV9WYWx1ZSxUb3RhbFBvcHVsYXRpb24sR2VvbG9jYXRpb24sQ2F0ZWdvcnlJRCkgDQpGaWx0ZXJfRGF0YV8yMDIxXzIgPC0gbmEub21pdChGaWx0ZXJfRGF0YV8yMDIxXzIpDQoNCnN2XzIxIDwtIGFnZ3JlZ2F0ZShUb3RhbFBvcHVsYXRpb25+U3RhdGVBYmJyK1N0YXRlRGVzYytEYXRhU291cmNlK0NhdGVnb3J5K01lYXN1cmUrRGF0YV9WYWx1ZV9UeXBlLCBkYXRhPUZpbHRlcl9EYXRhXzIwMjFfMiwgRlVOPXN1bSkNCg0Kc3YyXzIxIDwtIGFnZ3JlZ2F0ZShEYXRhX1ZhbHVlflN0YXRlQWJicitTdGF0ZURlc2MrRGF0YVNvdXJjZStDYXRlZ29yeStNZWFzdXJlK0RhdGFfVmFsdWVfVHlwZSwgZGF0YT1GaWx0ZXJfRGF0YV8yMDIxXzIsIEZVTj1tZWFuKQ0KDQoNCnN2NV8yMSA8LSBGaWx0ZXJfRGF0YV8yMDIxXzIgJT4lIGRpc3RpbmN0KFN0YXRlRGVzYywgLmtlZXBfYWxsID0gVFJVRSkNCg0Kc3Y1XzIxIDwtIHN2NV8yMSAlPiUgc2VsZWN0KFN0YXRlQWJicixTdGF0ZURlc2MsRGF0YVNvdXJjZSxDYXRlZ29yeSxNZWFzdXJlLERhdGFfVmFsdWVfVHlwZSxHZW9sb2NhdGlvbikgDQoNCnN2NV8yMSA8LSBuYS5vbWl0KHN2NV8yMSkNCg0Kc3Y1XzIxIDwtIHN2NV8yMVtvcmRlcihzdjVfMjEkU3RhdGVEZXNjKSxdDQoNCmNvbWJpbmVkX2RhdGFfMjEgPC0gY2JpbmQoc3ZfMjEsc3YyXzIxLHN2NV8yMSkNCmNvbWJpbmVkX2RhdGEyXzIxIDwtIGNvbWJpbmVkX2RhdGFfMjFbIC1jKDg6MTMsMTU6MjAsMjI6MjcsMjk6MzQpIF0NCmNvbWJpbmVkX2RhdGEyXzIxIDwtIGNvbWJpbmVkX2RhdGEyXzIxICU+JSBtdXRhdGVfaWYoaXMubnVtZXJpYywgfnJvdW5kKC4sIDEpKQ0KaGVhZChjb21iaW5lZF9kYXRhMl8yMSkNCg0KYGBgDQoNCg0KDQoqKiBJIGhhdmUgYWxyZWFkeSBkcm9wcGVkIGEgbG90IG9mIHVud2FudGVkIHZhcmlhYmxlcyBmcm9tIHRoZSBkYXRhc2V0IGFuZCBrZWVwIG9ubHkgdGhvc2UgdmFyaWFibGUgdGhhdCBJIG5lZWQgZm9yIGFuYWx5c2lzLiAqKg0KDQoNCioqIEkgZG93bmxvYWVkZWQgdGhlIHNoYXBlZmlsZSBmcm9tIHRoZSBVbml0ZWQgQ2Vuc3VzIEJ1cmVhdSB0byByZWFkIHRoZSBVUyBzdGF0ZSBib3VuZGFyaWVzIHNoYXBlZmlsZSBhbmQgdG8gcGxvdCB0aGUgY2hvcm9wbGV0aCAqKg0KDQoNCiMjIyBEcmF3aW5nIFBsb3QNCg0KYGBge3J9DQpsaWJyYXJ5KHJnZGFsKQ0Kc2V0d2QoIkM6L1VzZXJzL3NoYWhpL0Rlc2t0b3AvYmxvZ3Bvc3QiKQ0KU3RhdGVfYm91bmRhcmllc18yMSA8LSByZWFkT0dSKCdDOi9Vc2Vycy9zaGFoaS9EZXNrdG9wL2Jsb2dwb3N0L2NiXzIwMTdfdXNfc3RhdGVfNTAway5zaHAnKQ0KDQpgYGANCg0KDQoNCg0KKiogTm93LCBJIHdpbGwgb3JnYW5pemUgdGhlIGZpbmFsIGRhdGFzZXQgdGhhdCBJIHdpbGwgdXNlIGluIG15IGNob3JvcGxldGguIEFmdGVyIEkgZGlkIGFsbCB0aGUgZGF0YSBtYW5pcHVsYXRpb24sIEkgd2lsbCBtZXJnZSB0aGUgZGF0YXNldCB3aXRoIHBvbHlnb25zIGRhdGEgdG8gaGF2ZSBhIHBvbHlnb25zIHdoZXJlIGFsbCB2YWx1ZXMgYXJlIGluY2x1ZGVkIGFuZCBhbHNvIHRoZSBuYW1lIG9mIHN0YXRlLiBJIHdpbGwgaGF2ZSBoZXJlIGEgTGFyZ2VTcGF0aWFsUG9seWdvbiwgd2hlcmUgSSB3aWxsIG1lcmdlIHRoZSBkYXRhc2V0IGhlcmUgYW5kIEkgd2lsbCB1c2UgaXQgdG8gbWFwLiAqKg0KDQoNCmBgYHtyfQ0KDQpKb2ludF9EYXRhXzIxIDwtIGZ1bGxfam9pbihTdGF0ZV9ib3VuZGFyaWVzXzIxQGRhdGEsIGNvbWJpbmVkX2RhdGEyXzIxLCAgYnkgPSBjKCJTVFVTUFMiID0gIlN0YXRlQWJiciIpKQ0KdG1wLmwyIDwtIG5hLm9taXQoSm9pbnRfRGF0YV8yMSkNCnRlc3RfMjEgPC0gdG1wLmwyICU+JSBkaXN0aW5jdChTVEFURU5TLCAua2VlcF9hbGwgPSBUUlVFKQ0KaGVhZCh0ZXN0XzIxKQ0KDQpgYGANCg0KDQoqKiBIZXJlIEkgd2lsbCBkcmF3IHBsb3RzIGZvciBzcGVjaWZpYyBsZWFmbGV0IHN1Y2ggYXMgbmFtZSBvZiB0aGUgc3RhdGUsIHBvcHVsYXRpb24sIHNvdXJjZSBvZiBkYXRhLCBtZWFzdXJlIGFuZCBtZWFzdXJlIGNhdGVnb3J5LGFnZS1hZGp1c3RlZCBwcmV2YWxlbmNlLkkgYWxzbyBhZGRlZCBwb3B1cCBkaXNwbGF5IHdoaWNoIHdpbGwgc2hvdyBpbmZvcm1hdGlvbiBhYm91dCBzcGVjaWZpYyBkYXRhc2V0LiBXaGVuIGNsaWNrZWQgb24gdGhlIHNwZWNpZmljIHN0YXRlLCBpdCB3aWxsIHNob3cgdGhlIHBvcHVsYXRpb24gY291bnQgYW5kIG90aGVyIGluZm9ybWF0aW9uLiAqKg0KDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoY2xhc3NJbnQpDQoNCmJpbnMgPC0gYygxMDAwMDAwLCAzMDAwMDAsIDUwMDAwMCwgOTAwMDAwLCAyMDAwMDAwLCAzMDAwMDAwLCA0MDAwMDAwLCA1MDAwMDAwMCwgNjAwMDAwMDAsIDcwMDAwMDAwLCBJbmYpDQojYnJlYWtzX3F0IDwtIGNsYXNzSW50ZXJ2YWxzKHRlc3RfMjEkVG90YWxQb3B1bGF0aW9uLCBuID0gNSwgc3R5bGUgPSAicXVhbnRpbGUiKQ0KcGFsIDwtIGNvbG9yQmluKCJZbE9yUmQiLCBkb21haW4gPSB0ZXN0XzIxJFRvdGFsUG9wdWxhdGlvbiwgYmlucyA9IGJpbnMpDQoNCmxhYmVscyA8LSBzcHJpbnRmKCI8c3Ryb25nPiVzPC9zdHJvbmc+IixTdGF0ZV9ib3VuZGFyaWVzXzIxJE5BTUUpICU+JSBsYXBwbHkoaHRtbHRvb2xzOjpIVE1MKQ0KDQogbGVhZmxldChTdGF0ZV9ib3VuZGFyaWVzXzIxKSAlPiUgDQogIHNldFZpZXcoLTk2LCAzNy44LCA0KSAlPiUgDQogIGFkZFByb3ZpZGVyVGlsZXMoIk9wZW5TdHJlZXRNYXAiKSAlPiUNCiAgYWRkUG9seWdvbnMoZGF0YSA9IFN0YXRlX2JvdW5kYXJpZXNfMjEsDQogICAgZmlsbENvbG9yID0gfnBhbCh0ZXN0XzIxJFRvdGFsUG9wdWxhdGlvbiksDQogICAgd2VpZ2h0ID0gMiwNCiAgICBvcGFjaXR5ID0gMSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgZGFzaEFycmF5ID0gIjMiLA0KICAgIGZpbGxPcGFjaXR5ID0gMC43LA0KICAgIA0KICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKA0KICAgICAgd2VpZ2h0ID0gNSwNCiAgICAgIGNvbG9yID0gIiM2NjYiLA0KICAgICAgZGFzaEFycmF5ID0gIiIsDQogICAgICBmaWxsT3BhY2l0eSA9IDAuNywNCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpLA0KICAgIGxhYmVsID0gbGFiZWxzLA0KICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucygNCiAgICAgIHN0eWxlID0gbGlzdCgiZm9udC13ZWlnaHQiID0gIm5vcm1hbCIsIHBhZGRpbmcgPSAiM3B4IDhweCIpLA0KICAgICAgdGV4dHNpemUgPSAiMTVweCIsDQogICAgICBkaXJlY3Rpb24gPSAiYXV0byIpLA0KICAgIHBvcHVwID0gfnBhc3RlKCI8c3Ryb25nPlN0YXRlOiA8L3N0cm9uZz4iLE5BTUUsIHBhc3RlKCI8YnI+PHN0cm9uZz5NZWFzdXJlOiA8L3N0cm9uZz4iLCB0ZXN0XzIxJE1lYXN1cmUpLCBwYXN0ZSgiPGJyPjxzdHJvbmc+RGF0YSBTb3VyY2U6IDwvc3Ryb25nPiIsIHRlc3RfMjEkRGF0YVNvdXJjZSkscGFzdGUoIjxicj48c3Ryb25nPkNhdGVnb3J5OiA8L3N0cm9uZz4iLCB0ZXN0XzIxJENhdGVnb3J5KSxwYXN0ZSgiPGJyPjxzdHJvbmc+UG9wdWxhdGlvbiAoTWVhc3VyZSk6IDwvc3Ryb25nPiIsIHRlc3RfMjEkVG90YWxQb3B1bGF0aW9uKSwgcGFzdGUoIjxicj48c3Ryb25nPkRhdGEgVmFsdWUgVHlwZSA6IDwvc3Ryb25nPiIsIHRlc3RfMjEkRGF0YV9WYWx1ZV9UeXBlKSxwYXN0ZSgiPGJyPjxzdHJvbmc+QWdlLUFkanVzdGVkIFByZXZhbGVuY2UgJSA6IDwvc3Ryb25nPiIsIHRlc3RfMjEkRGF0YV9WYWx1ZSkpKSAlPiUNCiAgYWRkTGVnZW5kKHBhbCA9IHBhbCwgdmFsdWVzID0gfnRlc3RfMjEkVG90YWxQb3B1bGF0aW9uLCBvcGFjaXR5ID0gMC43LCB0aXRsZSA9ICJQb3B1bGF0aW9uIENvdW50IiwNCiAgICBwb3NpdGlvbiA9ICJib3R0b21yaWdodCIpDQoNCmBgYA0KDQoNCioqIEFtb25nIHRoZW0gRmxvcmlkYSBhbmQgV2VzdCBWaXJnaW5pYSBoYXZlIHRoZSBoaWdoZXN0IHByZXZhbGVuY2UgcmF0ZSAoMjguOCUpLCBPaGlvIOKAkyAyNy44JSwgTm9ydGggRGFrb3RhIOKAkyAyNyUsIE5ldmFkYSAoMjUuNCUpLCBXeW9taW5nICgyNS4zJSksIENhbGlmb3JuaWEgKDI1LjElKSwgV2lzY29uc2luICgyNC44JSksIE1pc3Npc3NpcHBpICgyNC43JSksIE9yZWdvbiAoMjQuNiUpIGluIDIwMTgtMjAxOS4gQ29tcGFyaW5nIHRvIDIwMTYtMjAxNywgdGhlIHN0YXRlcyBOb3J0aCBDYXJvbGluYSBhbmQgVXRhaCAoMTYuOCUpIHdoaWNoIGhhZCB0aGUgaGlnaGVzdCBwcmV2YWxlbmNlIHJhdGUgaW4gVVNBIGlzIHJlcGxhY2VkIGJ5IEZsb3JpZGEgYW5kIFdlc3QgVmlyZ2luaWEgKDI4LDglKS4gVGhlIG92ZXJhbGwgYWdlLWFkanVzdGVkIHByZXZhbGVuY2UgcmF0ZSBpcyBpbmNyZWFzaW5nIHJhcGlkbHksIGFuZCBtZW50YWwgaGVhbHRoIGNvbmRpdGlvbiBoYXMgYWxzbyBjaGFuZ2VkIGluIHRoZXNlIHN0YXRlcy4gTm9ydGggRGFrb3RhLCBXeW9taW5nLCBDYWxpZm9ybmlhLCBOZXZhZGEsIFdpc2NvbnNpbiwgT2hpbywgVGVubmVzc2VlIGhhcyBhZGRlZCBuZXdseSBpbiBoaWdoIHByZXZhbGVuY2UgcmF0ZSBvZiBwb29yIG1lbnRhbCBoZWFsdGguIFNvLCB0aGVyZSBtYXkgYmUgc29tZSByZWFzb25zIGJlaGluZCB0aGlzIHBvb3IgbWVudGFsIGhlYWx0aCBvdXRjb21lLiAqKg0KDQoNCg0KDQoNCg0KIyMjIyBBbmFseXNpcyBvZiAyMDE5IERhdGENCg0KDQpgYGB7cn0NCkRhdGEgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL3NoYWhpL0Rlc2t0b3AvYmxvZ3Bvc3QvNTAwX0NpdGllc19fTG9jYWxfRGF0YV9mb3JfQmV0dGVyX0hlYWx0aF9fMjAxOV9yZWxlYXNlLmNzdiIpDQpgYGANCg0KDQpgYGB7cn0NCkZpbHRlcl9EYXRhIDwtIERhdGENCkZpbHRlcl9EYXRhIDwtIEZpbHRlcl9EYXRhICU+JSBmaWx0ZXIoRGF0YVZhbHVlVHlwZUlEPT0iQWdlQWRqUHJ2IikNCkRhdGFfTWVudGFsX0hlYWx0aCA8LSBGaWx0ZXJfRGF0YSAlPiUgZmlsdGVyKE1lYXN1cmU9PSJNZW50YWwgaGVhbHRoIG5vdCBnb29kIGZvciA+PTE0IGRheXMgYW1vbmcgYWR1bHRzIGFnZWQgPj0xOCBZZWFycyIpDQoNCmhlYWQoRGF0YV9NZW50YWxfSGVhbHRoKQ0KDQpgYGANCg0KDQoNCg0KYGBge3J9DQoNCkZpbHRlcl9EYXRhXzIgPC0gRGF0YV9NZW50YWxfSGVhbHRoICU+JSBzZWxlY3QoU3RhdGVBYmJyLFN0YXRlRGVzYyxEYXRhU291cmNlLENhdGVnb3J5LA0KTWVhc3VyZSxEYXRhX1ZhbHVlX1R5cGUsRGF0YV9WYWx1ZSxQb3B1bGF0aW9uQ291bnQsR2VvTG9jYXRpb24sQ2F0ZWdvcnlJRCkgDQpGaWx0ZXJfRGF0YV8yIDwtIG5hLm9taXQoRmlsdGVyX0RhdGFfMikNCg0Kc3YgPC0gYWdncmVnYXRlKFBvcHVsYXRpb25Db3VudH5TdGF0ZUFiYnIrU3RhdGVEZXNjK0RhdGFTb3VyY2UrQ2F0ZWdvcnkrTWVhc3VyZStEYXRhX1ZhbHVlX1R5cGUsIGRhdGE9RmlsdGVyX0RhdGFfMiwgRlVOPXN1bSkNCg0Kc3YyIDwtIGFnZ3JlZ2F0ZShEYXRhX1ZhbHVlflN0YXRlQWJicitTdGF0ZURlc2MrRGF0YVNvdXJjZStDYXRlZ29yeStNZWFzdXJlK0RhdGFfVmFsdWVfVHlwZSwgZGF0YT1GaWx0ZXJfRGF0YV8yLCBGVU49bWVhbikNCg0KDQpzdjUgPC0gRmlsdGVyX0RhdGFfMiAlPiUgZGlzdGluY3QoU3RhdGVEZXNjLCAua2VlcF9hbGwgPSBUUlVFKQ0KDQpzdjUgPC0gc3Y1ICU+JSBzZWxlY3QoU3RhdGVBYmJyLFN0YXRlRGVzYyxEYXRhU291cmNlLENhdGVnb3J5LE1lYXN1cmUsRGF0YV9WYWx1ZV9UeXBlLEdlb0xvY2F0aW9uKSANCg0Kc3Y1IDwtIG5hLm9taXQoc3Y1KQ0KDQpzdjUgPC0gc3Y1W29yZGVyKHN2NSRTdGF0ZURlc2MpLF0NCg0KY29tYmluZWRfZGF0YSA8LSBjYmluZChzdixzdjIsc3Y1KQ0KY29tYmluZWRfZGF0YTIgPC0gY29tYmluZWRfZGF0YVsgLWMoODoxMywxNToyMCwyMjoyNywyOTozNCkgXQ0KY29tYmluZWRfZGF0YTIgPC0gY29tYmluZWRfZGF0YTIgJT4lIG11dGF0ZV9pZihpcy5udW1lcmljLCB+cm91bmQoLiwgMSkpDQpoZWFkKGNvbWJpbmVkX2RhdGEyKQ0KDQpgYGANCg0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KHJnZGFsKQ0Kc2V0d2QoIkM6L1VzZXJzL3NoYWhpL0Rlc2t0b3AvYmxvZ3Bvc3QiKQ0KU3RhdGVfYm91bmRhcmllcyA8LSByZWFkT0dSKCdDOi9Vc2Vycy9zaGFoaS9EZXNrdG9wL2Jsb2dwb3N0L2NiXzIwMTdfdXNfc3RhdGVfNTAway5zaHAnKQ0KDQpgYGANCg0KDQoNCg0KDQpgYGB7cn0NCg0KSm9pbnRfRGF0YSA8LSBmdWxsX2pvaW4oU3RhdGVfYm91bmRhcmllc0BkYXRhLCBjb21iaW5lZF9kYXRhMiwgIGJ5ID0gYygiU1RVU1BTIiA9ICJTdGF0ZUFiYnIiKSkNCnRtcC5sMiA8LSBuYS5vbWl0KEpvaW50X0RhdGEpDQp0ZXN0IDwtIHRtcC5sMiAlPiUgZGlzdGluY3QoU1RBVEVOUywgLmtlZXBfYWxsID0gVFJVRSkNCmhlYWQodGVzdCkNCg0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoY2xhc3NJbnQpDQoNCmJpbjE5IDwtIGMoMTAwMDAsIDEwMDAwMCwgMjAwMDAwLCA0MDAwMDAsIDkwMDAwMCwgMTAwMDAwMCwgMzAwMDAwMCwgNDAwMDAwMCwgNTAwMDAwMDAsIDYwMDAwMDAwLCBJbmYpDQojYnJlYWtzX3F0IDwtIGNsYXNzSW50ZXJ2YWxzKHRlc3RfMjEkVG90YWxQb3B1bGF0aW9uLCBuID0gNSwgc3R5bGUgPSAicXVhbnRpbGUiKQ0KcGFsIDwtIGNvbG9yQmluKCJZbE9yUmQiLCBkb21haW4gPSB0ZXN0JFBvcHVsYXRpb25Db3VudCwgYmlucyA9IGJpbjE5KQ0KDQpsYWJlbHMgPC0gc3ByaW50ZigiPHN0cm9uZz4lczwvc3Ryb25nPiIsU3RhdGVfYm91bmRhcmllcyROQU1FKSAlPiUgbGFwcGx5KGh0bWx0b29sczo6SFRNTCkNCg0KIGxlYWZsZXQoU3RhdGVfYm91bmRhcmllcykgJT4lIA0KICBzZXRWaWV3KC05NiwgMzcuOCwgNCkgJT4lIA0KICBhZGRQcm92aWRlclRpbGVzKCJPcGVuU3RyZWV0TWFwIikgJT4lDQogIGFkZFBvbHlnb25zKGRhdGEgPSBTdGF0ZV9ib3VuZGFyaWVzLA0KICAgIGZpbGxDb2xvciA9IH5wYWwodGVzdCRQb3B1bGF0aW9uQ291bnQpLA0KICAgIHdlaWdodCA9IDIsDQogICAgb3BhY2l0eSA9IDEsDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGRhc2hBcnJheSA9ICIzIiwNCiAgICBmaWxsT3BhY2l0eSA9IDAuNywNCiAgICANCiAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucygNCiAgICAgIHdlaWdodCA9IDUsDQogICAgICBjb2xvciA9ICIjNjY2IiwNCiAgICAgIGRhc2hBcnJheSA9ICIiLA0KICAgICAgZmlsbE9wYWNpdHkgPSAwLjcsDQogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSwNCiAgICBsYWJlbCA9IGxhYmVscywNCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMoDQogICAgICBzdHlsZSA9IGxpc3QoImZvbnQtd2VpZ2h0IiA9ICJub3JtYWwiLCBwYWRkaW5nID0gIjNweCA4cHgiKSwNCiAgICAgIHRleHRzaXplID0gIjE1cHgiLA0KICAgICAgZGlyZWN0aW9uID0gImF1dG8iKSwNCiAgICBwb3B1cCA9IH5wYXN0ZSgiPHN0cm9uZz5TdGF0ZTogPC9zdHJvbmc+IixOQU1FLCBwYXN0ZSgiPGJyPjxzdHJvbmc+TWVhc3VyZTogPC9zdHJvbmc+IiwgdGVzdCRNZWFzdXJlKSwgcGFzdGUoIjxicj48c3Ryb25nPkRhdGEgU291cmNlOiA8L3N0cm9uZz4iLCB0ZXN0JERhdGFTb3VyY2UpLHBhc3RlKCI8YnI+PHN0cm9uZz5DYXRlZ29yeTogPC9zdHJvbmc+IiwgdGVzdCRDYXRlZ29yeSkscGFzdGUoIjxicj48c3Ryb25nPlBvcHVsYXRpb24gKE1lYXN1cmUpOiA8L3N0cm9uZz4iLCB0ZXN0JFBvcHVsYXRpb25Db3VudCksIHBhc3RlKCI8YnI+PHN0cm9uZz5EYXRhIFZhbHVlIFR5cGUgOiA8L3N0cm9uZz4iLCB0ZXN0JERhdGFfVmFsdWVfVHlwZSkscGFzdGUoIjxicj48c3Ryb25nPkFnZS1BZGp1c3RlZCBQcmV2YWxlbmNlICUgOiA8L3N0cm9uZz4iLCB0ZXN0JERhdGFfVmFsdWUpKSkgJT4lDQogIGFkZExlZ2VuZChwYWwgPSBwYWwsIHZhbHVlcyA9IH50ZXN0JFBvcHVsYXRpb25Db3VudCwgb3BhY2l0eSA9IDAuNywgdGl0bGUgPSAiUG9wdWxhdGlvbiBDb3VudCIsDQogICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiKQ0KDQoNCmBgYA0KDQoNCg0KKiogSSBmb3VuZCBOb3J0aCBDYXJvbGluYSAmIFV0YWggKDE2LjglKSwgUGVubnN5bHZhbmlhICYgV2VzdCBWaXJnaW5pYSAoMTYuNSUpLCBXYXNoaW5ndG9uICgxNi4yJSksIE5ldyBKZXJzZXkoMTUuOSUpLCBBbGFiYW1hICYgTWFyeWxhbmQgKDE1LjclKSwgQXJpem9uYSAoMTUuNSUpLCBNaXNzaXNzaXBwaSAoMTUuMyUpLCBhbmQgVGV4YXMgKDE1JSkgaGF2ZSBoaWdoIGFnZS1hZGp1c3RlZCBwcmV2YWxlbmNlIHJhdGUgZm9yIG1lbnRhbCBoZWFsdGggdGhhbiBvdGhlciBzdGF0ZXMgb2YgVVNBIGluIDIwMTYtMjAxNyBwZXJpb2QuICoqDQoNCg0KDQoNCg0KDQoNCg0KDQoNCiMjIyMjIyBSRVBPUlQgIA0KDQoNCioqIEluIHRoaXMgcHJvamVjdCwgSSB3YW50ZWQgdG8ga25vdyBob3cgcGVvcGxlIGFyZSBzdWZmZXJpbmcgZnJvbSBtZW50YWwgc3RyZXNzIGluIGRpZmZlcmVudCBzdGF0ZXMgb2YgVVNBLiBJIGdvdCByZXN1bHRzIGZvciBhbGwgdGhlIHN0YXRlcy4gSSB1c2VkIDIwMjEgcmVsZWFzZSBhbmQgMjAxOSByZWxlYXNlIHRvIG9ic2VydmUgdGhlIGRpZmZlcmVuY2VzIG9mIG1lbnRhbCBzdHJlc3Mgb3ZlciB0aGUgeWVhci4gVGhlIHBlcmNlbnRhZ2Ugb2YgZGVwcmVzc2lvbiBpcyBjaGFuZ2luZyBvdmVyIHRoZSB0aW1lIGluIGRpZmZlcmVudCBzdGF0ZXMuIEZvciBleGFtcGxlLCBpbiBURVhBUywgdGhlIHBvcHVsYXRpb24gY291bnQgd2FzIDE4MzYzNDMgYW5kIDE1JSBvZiB0aGVtIHdlcmUgc3VmZmVyaW5nIGZyb20gbWVudGFsIHN0cmVzcy4gSG93ZXZlciwgaW4gMjAyMSByZWxlYXNlLCB0aGUgdG90YWwgcG9wdWxhdGlvbiBjb3VudCB3YXMgMTk0NTM1NjEgYW5kIGFtb25nIHRoZW0gMTQuNyUgYXJlIHN1ZmZlcmluZyBmcm9tIG1lbnRhbCBzdHJlc3MuIFNvLCB0aGUgbWVudGFsIHN0cmVzcyByYXRlIGlzIGluY3JlYXNpbmcgYnV0IHZhcmllcyBmcm9tIHN0YXRlIHRvIHN0YXRlLiAgKioNCg0KDQoqKiBMaW1pdGF0aW9uOiBJIHdhbnRlZCB0byBvYnNlcnZlIGdlb2dyYXBoaWMgaG90c3BvdCBvZiBtZW50YWwgc3RyZXNzIGJlZm9yZSBwYW5kZW1pYywgZHVyaW5nIHBhbmRlbWljLiBCdXQgZHVlIHRvIHVuYXZhaWxhYmlsaXR5IG9mIHRoZSByZWNlbnQgZGF0YSwgSSBjb3VsZCBub3QgZG8gdGhlIGFuYWx5c2lzLiBJIGNvdWxkIG5vdCBjb250cm9sIHRoZSBhbmFseXNpcyBmb3IgU0VTIHZhcmlhYmxlLiAqKg0KDQoNCioqIEZ1dHVyZSBEaXJlY3Rpb246IEFmdGVyIHB1Ymxpc2hpbmcgZGF0YSBmb3IgMjAyMC0yMDIyLCBJIHdpbGwgY29tcGFyZSB0aGUgcHJlLXBhbmRlbWljIGFuZCBwYW5kZW1pYyBwZXJpb2QgbWVudGFsIHN0cmVzcyBvdmVyIHRoZSBzdGF0ZXMsIGFuZCBpZiBwb3NzaWJsZSB0byBjaXRpZXMuIEFsc28sIEkgd2FudCB0byBrbm93IGhvdyBQYW5kZW1pYyBoYWQgYW4gZWZmZWN0IGdlb2dyYXBoaWNhbGx5IG92ZXIgdGhlIFVuaXRlZCBTdGF0ZXMuICoqDQoNCg0KDQoNCg0KDQo=