Source and descriptions of datasets
Ontario Community Health Profiles Partnership (OCHPP)
http://www.ontariohealthprofiles.ca/
Data — LHIN 7 (Toronto Central and City of Toronto) Neighbourhoods, Ontario Sub-Regions and LHINs
We use three datasets:
- Primary Care: Enrolment and Continuity of Care 2011/13
1_pc_Continuity_NonRostered_Rostered_Patients_neighb_2013_LHIN_7.xlsx
- Adult Health and Disease 2016/17
1_AHD_2017_RPDB_Neighb_LHIN_7.xlsx
- Sexual Health: Chlamydia cases, Gonorrhea cases 2013/16
2_sh_neighb_chlam_gonor_2013-2016_LHIN_7.xls
We quote from the description of the data:
The Registered Persons Database (RPDB) as the source of population
http://www.ontariohealthprofiles.ca/o_documents/aboutTheDataON/RPDB_vs_Census_Oct_26_2018.pdf
Two main population sources
There are two main sources that provide the most reliable estimates of Ontario’s population. For purposes of OCHPP reporting, we use the Registered Persons Database (RPDB) as the source (denominator) for all of our health-related indicators. While another major source for identifying the population (denominator) is Statistics Canada’s Census counts (Census), the OCHPP has determined that the RPDB provides a more consistent measure for the calculation of rates for health indicators and conditions. We explain why and provide examples to illustrate.
RPDB
The RPDB (database) provides basic demographic information about anyone who has ever received an Ontario Health Insurance Plan (OHIP) card. OHIP cards include a unique Health Card Number (HCN) to identify a person’s age, sex and address, including postal code. The postal codes used at ICES come mainly from HCNs. Information from the health card is stored in the RPDB. Health cards are usually renewed every 5 years, a process that helps to ensure that information in the system is periodically refreshed, such as address, for example, should a person move and update the card within that time frame. The system may also be updated more frequently if an individual interacts with the healthcare system between renewal periods. This allows for a more current source of location-based data for health reporting.
Census
Another source of data on where people live can come from Statistics Canada (Stats Can). Stats Can collects data on individuals living in Canada through the Census, a survey conducted every 5 years. Stats Can reports who lives in a given area at one point in time – i.e. based on the information an individual provides when completing the Census
RPDB vs. Census
While at the provincial level, the number of people we identify in the RPDB as living in Ontario does not differ much from Census estimates, differences are more pronounced at smaller areas such as neighbourhoods or local areas. This particular issue is most evident in areas of high migration where we have observed large differences in rates using RPDB vs. the Census in part due to population mobility.
For example, in some areas of Ontario, particularly in larger urban centres, newcomers to the area often settle first “downtown” but over time, may move from downtown to outlying areas. The majority of people who move do not change or update their health card until renewal time so they stay in the RPDB with their original health card information including the address and postal code of their “downtown” address.
The same is true of Census population counts: when someone moves, they are still considered living at their original address and comprise the population of that area until the next Census is taken (every 5 years).
Shapefile for City of Toronto’s 140 neighbourhoods
We now import and process a shapefile for Toronto’s 140 neighbourhoods.
https://www.toronto.ca/city-government/data-research-maps/open-data/open-data-catalogue/#a45bd45a-ede8-730e-1abc-93105b2c439f
http://opendata.toronto.ca/gcc/neighbourhoods_planning_areas_wgs84.zip
Neighbourhoods
Owner: Social Development, Finance & Administration
Currency: June 2014
Neighbourhoods (WGS84)
library(data.table) #fread
library(plyr) #join
library(ggplot2) #ggplot, fortify
library(sp) #used by rgdal
library(rgdal) #readOGR
library(rgeos) #gCentroid
library(scales) #scale_fill_distiller, percent_format
library(ggmap) #theme_nothing
library(Hmisc) #rcorr
Input shapefile
nbds.sh <- readOGR("C:/Users/14165/Desktop/ArcGIS/SHAPEFILES/neighbourhoods_planning_areas_wgs84", "NEIGHBORHOODS_WGS84")
OGR data source with driver: ESRI Shapefile
Source: "C:\Users\14165\Desktop\ArcGIS\SHAPEFILES\neighbourhoods_planning_areas_wgs84", layer: "NEIGHBORHOODS_WGS84"
with 140 features
It has 2 fields
Add “id” column
nbds.sh@data$id <- as.integer(nbds.sh@data$AREA_S_CD)
Make centroids of each neighbourhood, for placing labels when plotting
nbds.sh.centroids <- as.data.frame(gCentroid(nbds.sh, byid = TRUE))
Add “id” column
nbds.sh.centroids$id <- nbds.sh@data$id
Shapefile processing
nbds.sh.points = fortify(nbds.sh, region = "id")
nbds.sh.df = join(nbds.sh.points, nbds.sh@data, by = "id")
We are now done with shapefile processing.
We copied selected columns from sheets of the .xls/.xlsx files to new sheets, renamed columns by changing spaces and hyphens to underscores and spelling symbols, and exported these to .csv files.
We shall visualize selected data from these tables on a map. Then we compute correlations.
Primary Care: Enrolment and Continuity of Care 2011/13
1_pc_Continuity_NonRostered_Rostered_Patients_neighb_2013_LHIN_7.xlsx!Continuity_Enrolled_NonEnrolled:
Primary Care: Enrolment and Continuity of Care (Both sexes, Ages 19+) for Toronto Neighbourhoods and Toronto Central LHIN, 2011/12 to 2012/13 (April 1, 2011-March 31, 2013)
Data sources: Population - Ontario Heath Insurance Plan (OHIP) physician claims, Client Agency Provider Enrolment (CAPE) tables, Registered Persons’ Database, Community Health Centre client encounter data.
Population Enrolled: rostered with a Patient Enrolment Model (PEM) or registered with a Community Health Centre (CHC).
Population Non-Enrolled: not rostered with a Patient Enrolment Model (PEM) or registered with a Community Health Centre (CHC).
“id”, “Population_19_plus”, “Enrolled_Population”, “Enrolled_Population_with_No_Visits”, “Enrolled_Population_with_1_or_2_Visits”, “Enrolled_Population_with_3_plus_Visits”, “Non_Enrolled_Population”, “Non_Enrolled_Population_with_No_Visits”, “Non_Enrolled_Population_with_1_or_2_Visits”, “Non_Enrolled_Population_with_3_plus_Visits”, “Total_Population_Enrolled_and_Non_Enrolled”, “Total_Population_with_No_Visits”, “Total_Population_with_1_or_2_Visits”, “Total_Population_with_3_plus_Visits”
1_pc_Continuity_NonRostered_Rostered_Patients_neighb_2013_LHIN_7.csv
patients <- fread("1_pc_Continuity_NonRostered_Rostered_Patients_neighb_2013_LHIN_7.csv")
str(patients)
Classes ‘data.table’ and 'data.frame': 140 obs. of 14 variables:
$ id : int 1 2 3 4 5 6 7 8 9 10 ...
$ Population_19_plus : int 27552 25140 8548 8497 7834 17733 16996 9076 12298 8922 ...
$ Enrolled_Population : int 20095 17636 5982 6593 5748 13110 13037 6728 8856 6695 ...
$ Enrolled_Population_with_No_Visits : int 1030 775 285 356 290 640 655 364 530 405 ...
$ Enrolled_Population_with_1_or_2_Visits : int 2145 1723 697 855 735 1492 1632 864 1346 1047 ...
$ Enrolled_Population_with_3_plus_Visits : int 16920 15138 5000 5382 4723 10978 10750 5500 6980 5243 ...
$ Non_Enrolled_Population : int 7457 7504 2566 1904 2086 4623 3959 2348 3442 2227 ...
$ Non_Enrolled_Population_with_No_Visits : int 1258 1232 411 405 365 900 771 430 652 434 ...
$ Non_Enrolled_Population_with_1_or_2_Visits: int 1509 1483 485 411 411 1005 862 515 772 552 ...
$ Non_Enrolled_Population_with_3_plus_Visits: int 4690 4789 1670 1088 1310 2718 2326 1403 2018 1241 ...
$ Total_Population_Enrolled_and_Non_Enrolled: int 27552 25140 8548 8497 7834 17733 16996 9076 12298 8922 ...
$ Total_Population_with_No_Visits : int 2288 2007 696 761 655 1540 1426 794 1182 839 ...
$ Total_Population_with_1_or_2_Visits : int 3654 3206 1182 1266 1146 2497 2494 1379 2118 1599 ...
$ Total_Population_with_3_plus_Visits : int 21610 19927 6670 6470 6033 13696 13076 6903 8998 6484 ...
- attr(*, ".internal.selfref")=<externalptr>
Create ratio columns for selected variables
patients$Ratio_Non_Enrolled_Population <- patients$Non_Enrolled_Population/patients$Population_19_plus
patients$Ratio_Total_Population_with_No_Visits <- patients$Total_Population_with_No_Visits/patients$Population_19_plus
patients$Ratio_Total_Population_with_3_plus_Visits <- patients$Total_Population_with_3_plus_Visits/patients$Population_19_plus
patients_ratios <- patients[,.(id,Ratio_Non_Enrolled_Population,Ratio_Total_Population_with_No_Visits,Ratio_Total_Population_with_3_plus_Visits)]
Ratio_Non_Enrolled_Population
Ratio_Non_Enrolled_Population <- patients_ratios[, .(id,Ratio_Non_Enrolled_Population)]
Ratio_Non_Enrolled_Population.sh <- merge(nbds.sh.df, Ratio_Non_Enrolled_Population, by = "id")
Make graphics object
p.Ratio_Non_Enrolled_Population <- ggplot() +
geom_polygon(data = Ratio_Non_Enrolled_Population.sh,
aes(x = long, y = lat, group = group, fill = Ratio_Non_Enrolled_Population),
color = "black", size = 0.2) +
coord_map() +
scale_fill_distiller(name="Ratio", labels=percent_format(accuracy=1), palette = "PuRd", trans = "reverse", breaks = pretty_breaks(n = 8))+
theme_nothing(legend = TRUE) +
labs(title="Ratio of total population non-enrolled") +
geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.sh.centroids, size = 2)
Plot graphics object
p.Ratio_Non_Enrolled_Population + guides(fill = guide_legend(reverse=TRUE))
Ratio_Total_Population_with_No_Visits
Ratio_Total_Population_with_No_Visits <- patients_ratios[, .(id,Ratio_Total_Population_with_No_Visits)]
Ratio_Total_Population_with_No_Visits.sh <- merge(nbds.sh.df, Ratio_Total_Population_with_No_Visits, by = "id")
Make graphics object
p.Ratio_Total_Population_with_No_Visits <- ggplot() +
geom_polygon(data = Ratio_Total_Population_with_No_Visits.sh,
aes(x = long, y = lat, group = group, fill = Ratio_Total_Population_with_No_Visits),
color = "black", size = 0.2) +
coord_map() +
scale_fill_distiller(name="Ratio", labels=percent_format(accuracy=1), palette = "PuRd", trans = "reverse", breaks = pretty_breaks(n = 8)) +
theme_nothing(legend = TRUE) +
labs(title="Ratio of total population with no visits") +
geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.sh.centroids, size = 2)
Plot graphics object
p.Ratio_Total_Population_with_No_Visits + guides(fill = guide_legend(reverse=TRUE))
Ratio_Total_Population_with_3_plus_Visits
Ratio_Total_Population_with_3_plus_Visits <- patients_ratios[, .(id,Ratio_Total_Population_with_3_plus_Visits)]
Ratio_Total_Population_with_3_plus_Visits.sh <- merge(nbds.sh.df, Ratio_Total_Population_with_3_plus_Visits, by = "id")
Make graphics object
p.Ratio_Total_Population_with_3_plus_Visits <- ggplot() +
geom_polygon(data = Ratio_Total_Population_with_3_plus_Visits.sh,
aes(x = long, y = lat, group = group, fill = Ratio_Total_Population_with_3_plus_Visits),
color = "black", size = 0.2) +
coord_map() +
scale_fill_distiller(name="Ratio", labels=percent_format(accuracy=1), palette = "Greens", trans = "reverse", breaks = pretty_breaks(n = 8))+
theme_nothing(legend = TRUE) +
labs(title="Ratio of total population with 3+ visits") +
geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.sh.centroids, size = 2)
Plot graphics object
p.Ratio_Total_Population_with_3_plus_Visits + guides(fill = guide_legend(reverse=TRUE))
Adult Health and Disease 2016/17
1_AHD_2017_RPDB_Neighb_LHIN_7.xlsx!Diabetes_Neighb_Toronto:
Demographics - Denominator: Ontario Ministry of Health and Long-Term Care Registered Persons Database (RPDB), population aged 20+ who were alive and living in the Ontario on April 1st, 2016
Numerator: derived from validated, disease registries maintained by the Institute for Clinical Evaluative Sciences (ICES)
1_AHD_2017_RPDB_Neighb_LHIN_7.xlsx!COPD_Neighb_Toronto:
Demographics - Denominator: Ontario Ministry of Health and Long-Term Care Registered Persons Database (RPDB), population aged 35+ who were alive and living in the Ontario on April 1st, 2016
Numerator: derived from validated, disease registries maintained by the Institute for Clinical Evaluative Sciences (ICES)
“id”, “People_with_Diabetes_20_plus”, “Total_Population_2016_RPDB_20_plus”, “Prevalence_per_hundred_Diabetes_20_plus”, “People_with_COPD_35_plus”, “Total_Population_2016_RPDB_35_plus”, “Prevalence_per_hundred_COPD_35_plus”
1_AHD_2017_RPDB_Neighb_LHIN_7.csv
chronic <- fread("1_AHD_2017_RPDB_Neighb_LHIN_7.csv")
chronic$Ratio_People_with_Diabetes_20_plus <- chronic$People_with_Diabetes_20_plus/chronic$Total_Population_2016_RPDB_20_plus
chronic$Ratio_People_with_COPD_35_plus <- chronic$People_with_COPD_35_plus/chronic$Total_Population_2016_RPDB_35_plus
chronic_ratios <- chronic[,.(id,Ratio_People_with_Diabetes_20_plus,Ratio_People_with_COPD_35_plus)]
Ratio_People_with_Diabetes_20_plus <- chronic_ratios[, .(id,Ratio_People_with_Diabetes_20_plus)]
Ratio_People_with_Diabetes_20_plus.sh <- merge(nbds.sh.df, Ratio_People_with_Diabetes_20_plus, by = "id")
Make and plot graphics object
p.Ratio_People_with_Diabetes_20_plus <- ggplot() +
geom_polygon(data = Ratio_People_with_Diabetes_20_plus.sh,
aes(x = long, y = lat, group = group, fill = Ratio_People_with_Diabetes_20_plus),
color = "black", size = 0.2) +
coord_map() +
scale_fill_distiller(name="Ratio", labels=percent_format(accuracy=1), palette = "PuRd", trans = "reverse",
breaks = pretty_breaks(n = 8)) +
theme_nothing(legend = TRUE)+
labs(title="Ratio of people with diabetes, 20+") +
geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.sh.centroids, size = 2)
p.Ratio_People_with_Diabetes_20_plus + guides(fill = guide_legend(reverse=TRUE))
Ratio_People_with_COPD_35_plus <- chronic_ratios[, .(id,Ratio_People_with_COPD_35_plus)]
Ratio_People_with_COPD_35_plus.sh <- merge(nbds.sh.df, Ratio_People_with_COPD_35_plus, by = "id")
Make and plot graphics object
p.Ratio_People_with_COPD_35_plus <- ggplot() +
geom_polygon(data = Ratio_People_with_COPD_35_plus.sh,
aes(x = long, y = lat, group = group, fill = Ratio_People_with_COPD_35_plus),
color = "black", size = 0.2) +
coord_map() +
scale_fill_distiller(name="Ratio", labels=percent_format(accuracy=1), palette = "PuRd", trans = "reverse",
breaks = pretty_breaks(n = 8))+
theme_nothing(legend = TRUE) +
labs(title="Ratio of people with COPD, 35+") +
geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.sh.centroids, size = 2)
p.Ratio_People_with_COPD_35_plus + guides(fill = guide_legend(reverse=TRUE))
Sexual Health: Chlamydia cases, Gonorrhea cases 2013/16
2_sh_neighb_chlam_gonor_2013-2016_LHIN_7.xlsx!Chlamydia_Male_Female_Tor_neigh:
Number of Chlamydia Cases for Age 15 years and over by Gender (Male, Female), Toronto Neighbourhoods, 2013 to 2016 Calendar Years Combined
Demographics - Denominator: Based on 2011 Census population estimates. (Statistics Canada, 2011 Census of Population).
Numerator: Number of Chlamydia cases for 4 year (2013 to 2016) observation period. Data source: Data as of July 20, 2017, Toronto Public Health integrated Public Health Information System [iPHIS].
Average annual rate of Chlamydia cases (/100,000) Males (2013 to 2016), All Ages 15+
Average annual rate of Chlamydia cases (/100,000) Females (2013 to 2016), All Ages 15+
“id”, “Chlamydia_cases_male”, “Population_male”, “Chlamydia_cases_female”, “Population_female”
2_sh_neighb_chlam_gonor_2013-2016_LHIN_7.csv
chlamydia <- fread("2_sh_neighb_chlam_gonor_2013-2016_LHIN_7.csv")
chlamydia$Ratio_Chlamydia_cases_male <- chlamydia$Chlamydia_cases_male/chlamydia$Population_male
chlamydia$Ratio_Chlamydia_cases_female <- chlamydia$Chlamydia_cases_female/chlamydia$Population_female
chlamydia_ratios <- chlamydia[,.(id,Ratio_Chlamydia_cases_male,Ratio_Chlamydia_cases_female)]
Ratio_Chlamydia_cases_male <- chlamydia_ratios[, .(id,Ratio_Chlamydia_cases_male)]
Ratio_Chlamydia_cases_male.sh <- merge(nbds.sh.df, Ratio_Chlamydia_cases_male, by = "id")
Make and plot graphics object
p.Ratio_Chlamydia_cases_male <- ggplot() +
geom_polygon(data = Ratio_Chlamydia_cases_male.sh,
aes(x = long, y = lat, group = group, fill = Ratio_Chlamydia_cases_male),
color = "black", size = 0.2) +
coord_map() +
scale_fill_distiller(name="Cases/population", labels=percent_format(accuracy=1), palette = "YlOrBr", trans = "reverse", breaks = pretty_breaks(n = 8)) +
theme_nothing(legend = TRUE) +
labs(title="Number of male chlamydia cases/male population") +
geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.sh.centroids, size = 2)
p.Ratio_Chlamydia_cases_male + guides(fill = guide_legend(reverse=TRUE))
Correlations
OCHPP_ratios <- merge(merge(patients_ratios, chronic_ratios), chlamydia_ratios)
Structure of data table:
str(OCHPP_ratios)
Classes ‘data.table’ and 'data.frame': 140 obs. of 8 variables:
$ id : int 1 2 3 4 5 6 7 8 9 10 ...
$ Ratio_Non_Enrolled_Population : num 0.271 0.298 0.3 0.224 0.266 ...
$ Ratio_Total_Population_with_No_Visits : num 0.083 0.0798 0.0814 0.0896 0.0836 ...
$ Ratio_Total_Population_with_3_plus_Visits: num 0.784 0.793 0.78 0.761 0.77 ...
$ Ratio_People_with_Diabetes_20_plus : num 0.182 0.184 0.177 0.175 0.17 ...
$ Ratio_People_with_COPD_35_plus : num 0.0684 0.0658 0.0926 0.1047 0.097 ...
$ Ratio_Chlamydia_cases_male : num 0.0199 0.0199 0.0125 0.0114 0.0181 ...
$ Ratio_Chlamydia_cases_female : num 0.0232 0.0277 0.023 0.0263 0.0289 ...
- attr(*, ".internal.selfref")=<externalptr>
- attr(*, "sorted")= chr "id"
Drop “id” column
OCHPP_ratios_noid <- OCHPP_ratios[,-c("id")]
str(OCHPP_ratios_noid)
Classes ‘data.table’ and 'data.frame': 140 obs. of 7 variables:
$ Ratio_Non_Enrolled_Population : num 0.271 0.298 0.3 0.224 0.266 ...
$ Ratio_Total_Population_with_No_Visits : num 0.083 0.0798 0.0814 0.0896 0.0836 ...
$ Ratio_Total_Population_with_3_plus_Visits: num 0.784 0.793 0.78 0.761 0.77 ...
$ Ratio_People_with_Diabetes_20_plus : num 0.182 0.184 0.177 0.175 0.17 ...
$ Ratio_People_with_COPD_35_plus : num 0.0684 0.0658 0.0926 0.1047 0.097 ...
$ Ratio_Chlamydia_cases_male : num 0.0199 0.0199 0.0125 0.0114 0.0181 ...
$ Ratio_Chlamydia_cases_female : num 0.0232 0.0277 0.023 0.0263 0.0289 ...
- attr(*, ".internal.selfref")=<externalptr>
Compute correlations
rcorr(as.matrix(OCHPP_ratios_noid), type="pearson")
Ratio_Non_Enrolled_Population
Ratio_Non_Enrolled_Population 1.00
Ratio_Total_Population_with_No_Visits 0.45
Ratio_Total_Population_with_3_plus_Visits -0.32
Ratio_People_with_Diabetes_20_plus -0.12
Ratio_People_with_COPD_35_plus 0.14
Ratio_Chlamydia_cases_male 0.53
Ratio_Chlamydia_cases_female 0.51
Ratio_Total_Population_with_No_Visits
Ratio_Non_Enrolled_Population 0.45
Ratio_Total_Population_with_No_Visits 1.00
Ratio_Total_Population_with_3_plus_Visits -0.94
Ratio_People_with_Diabetes_20_plus -0.77
Ratio_People_with_COPD_35_plus -0.27
Ratio_Chlamydia_cases_male 0.39
Ratio_Chlamydia_cases_female 0.08
Ratio_Total_Population_with_3_plus_Visits
Ratio_Non_Enrolled_Population -0.32
Ratio_Total_Population_with_No_Visits -0.94
Ratio_Total_Population_with_3_plus_Visits 1.00
Ratio_People_with_Diabetes_20_plus 0.91
Ratio_People_with_COPD_35_plus 0.34
Ratio_Chlamydia_cases_male -0.23
Ratio_Chlamydia_cases_female 0.10
Ratio_People_with_Diabetes_20_plus
Ratio_Non_Enrolled_Population -0.12
Ratio_Total_Population_with_No_Visits -0.77
Ratio_Total_Population_with_3_plus_Visits 0.91
Ratio_People_with_Diabetes_20_plus 1.00
Ratio_People_with_COPD_35_plus 0.38
Ratio_Chlamydia_cases_male -0.05
Ratio_Chlamydia_cases_female 0.31
Ratio_People_with_COPD_35_plus Ratio_Chlamydia_cases_male
Ratio_Non_Enrolled_Population 0.14 0.53
Ratio_Total_Population_with_No_Visits -0.27 0.39
Ratio_Total_Population_with_3_plus_Visits 0.34 -0.23
Ratio_People_with_Diabetes_20_plus 0.38 -0.05
Ratio_People_with_COPD_35_plus 1.00 0.13
Ratio_Chlamydia_cases_male 0.13 1.00
Ratio_Chlamydia_cases_female 0.23 0.75
Ratio_Chlamydia_cases_female
Ratio_Non_Enrolled_Population 0.51
Ratio_Total_Population_with_No_Visits 0.08
Ratio_Total_Population_with_3_plus_Visits 0.10
Ratio_People_with_Diabetes_20_plus 0.31
Ratio_People_with_COPD_35_plus 0.23
Ratio_Chlamydia_cases_male 0.75
Ratio_Chlamydia_cases_female 1.00
n= 140
P
Ratio_Non_Enrolled_Population
Ratio_Non_Enrolled_Population
Ratio_Total_Population_with_No_Visits 0.0000
Ratio_Total_Population_with_3_plus_Visits 0.0001
Ratio_People_with_Diabetes_20_plus 0.1670
Ratio_People_with_COPD_35_plus 0.0889
Ratio_Chlamydia_cases_male 0.0000
Ratio_Chlamydia_cases_female 0.0000
Ratio_Total_Population_with_No_Visits
Ratio_Non_Enrolled_Population 0.0000
Ratio_Total_Population_with_No_Visits
Ratio_Total_Population_with_3_plus_Visits 0.0000
Ratio_People_with_Diabetes_20_plus 0.0000
Ratio_People_with_COPD_35_plus 0.0014
Ratio_Chlamydia_cases_male 0.0000
Ratio_Chlamydia_cases_female 0.3191
Ratio_Total_Population_with_3_plus_Visits
Ratio_Non_Enrolled_Population 0.0001
Ratio_Total_Population_with_No_Visits 0.0000
Ratio_Total_Population_with_3_plus_Visits
Ratio_People_with_Diabetes_20_plus 0.0000
Ratio_People_with_COPD_35_plus 0.0000
Ratio_Chlamydia_cases_male 0.0054
Ratio_Chlamydia_cases_female 0.2544
Ratio_People_with_Diabetes_20_plus
Ratio_Non_Enrolled_Population 0.1670
Ratio_Total_Population_with_No_Visits 0.0000
Ratio_Total_Population_with_3_plus_Visits 0.0000
Ratio_People_with_Diabetes_20_plus
Ratio_People_with_COPD_35_plus 0.0000
Ratio_Chlamydia_cases_male 0.5450
Ratio_Chlamydia_cases_female 0.0002
Ratio_People_with_COPD_35_plus Ratio_Chlamydia_cases_male
Ratio_Non_Enrolled_Population 0.0889 0.0000
Ratio_Total_Population_with_No_Visits 0.0014 0.0000
Ratio_Total_Population_with_3_plus_Visits 0.0000 0.0054
Ratio_People_with_Diabetes_20_plus 0.0000 0.5450
Ratio_People_with_COPD_35_plus 0.1224
Ratio_Chlamydia_cases_male 0.1224
Ratio_Chlamydia_cases_female 0.0054 0.0000
Ratio_Chlamydia_cases_female
Ratio_Non_Enrolled_Population 0.0000
Ratio_Total_Population_with_No_Visits 0.3191
Ratio_Total_Population_with_3_plus_Visits 0.2544
Ratio_People_with_Diabetes_20_plus 0.0002
Ratio_People_with_COPD_35_plus 0.0054
Ratio_Chlamydia_cases_male 0.0000
Ratio_Chlamydia_cases_female
Linear regression
lm_chlam <- lm(Ratio_Chlamydia_cases_male ~ Ratio_Chlamydia_cases_female, data = OCHPP_ratios_noid)
summary(lm_chlam)
Call:
lm(formula = Ratio_Chlamydia_cases_male ~ Ratio_Chlamydia_cases_female,
data = OCHPP_ratios_noid)
Residuals:
Min 1Q Median 3Q Max
-0.0095561 -0.0027092 -0.0006196 0.0014847 0.0314658
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.0003589 0.0012921 -0.278 0.782
Ratio_Chlamydia_cases_female 0.8114156 0.0611285 13.274 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.005647 on 138 degrees of freedom
Multiple R-squared: 0.5608, Adjusted R-squared: 0.5576
F-statistic: 176.2 on 1 and 138 DF, p-value: < 2.2e-16
plot(lm_chlam)
Choropleth of residuals
str(lm_chlam$residuals)
Named num [1:140] 0.00145 -0.00222 -0.00587 -0.00956 -0.005 ...
- attr(*, "names")= chr [1:140] "1" "2" "3" "4" ...
Make dataframe of residuals with “id” column
lm_chlam_df <- data.frame(id = c(1:140), residual = lm_chlam$residuals)
head(lm_chlam_df)
lm_chlam_df.sh <- merge(nbds.sh.df, lm_chlam_df, by = "id")
Make and plot graphics object
p.lm_chlam_df <- ggplot() +
geom_polygon(data = lm_chlam_df.sh,
aes(x = long, y = lat, group = group, fill = residual),
color = "black", size = 0.2) +
coord_map() +
scale_fill_distiller(name="Residuals", palette = "Blues", trans = "reverse", breaks = pretty_breaks(n = 8)) +
theme_nothing(legend = TRUE) +
labs(title="Residuals of male chlamydia cases ~ female chlamydia cases") +
geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.sh.centroids, size = 2)
p.lm_chlam_df + guides(fill = guide_legend(reverse=TRUE))
LS0tDQp0aXRsZTogIk9DSFBQIFRvcm9udG8gUHVibGljIEhlYWx0aCBEYXRhc2V0cyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogeWVzDQotLS0NCg0KIyBBdXRob3INCg0KKiBKb3JkYW4gQmVsbA0KKiBKdWx5IDEsIDIwMTkNCiogPGh0dHBzOi8vam9yZGFuYmVsbDIzNTcuZ2l0aHViLmlvL09DSFBQLm5iLmh0bWw+DQoNCiMgU291cmNlIGFuZCBkZXNjcmlwdGlvbnMgb2YgZGF0YXNldHMNCg0KKipPbnRhcmlvIENvbW11bml0eSBIZWFsdGggUHJvZmlsZXMgUGFydG5lcnNoaXAgKE9DSFBQKSoqICAgIA0KPGh0dHA6Ly93d3cub250YXJpb2hlYWx0aHByb2ZpbGVzLmNhLz4NCg0KKipEYXRhIOKAlCBMSElOIDcgKFRvcm9udG8gQ2VudHJhbCBhbmQgQ2l0eSBvZiBUb3JvbnRvKSBOZWlnaGJvdXJob29kcywgT250YXJpbyBTdWItUmVnaW9ucyBhbmQgTEhJTnMqKg0KDQpXZSB1c2UgdGhyZWUgZGF0YXNldHM6DQoNCiogKipQcmltYXJ5IENhcmU6IEVucm9sbWVudCBhbmQgQ29udGludWl0eSBvZiBDYXJlIDIwMTEvMTMqKiAgDQoxX3BjX0NvbnRpbnVpdHlfTm9uUm9zdGVyZWRfUm9zdGVyZWRfUGF0aWVudHNfbmVpZ2hiXzIwMTNfTEhJTl83Lnhsc3gNCiogKipBZHVsdCBIZWFsdGggYW5kIERpc2Vhc2UgMjAxNi8xNyoqICANCjFfQUhEXzIwMTdfUlBEQl9OZWlnaGJfTEhJTl83Lnhsc3gNCiogKipTZXh1YWwgSGVhbHRoOiBDaGxhbXlkaWEgY2FzZXMsIEdvbm9ycmhlYSBjYXNlcyAyMDEzLzE2KiogIA0KMl9zaF9uZWlnaGJfY2hsYW1fZ29ub3JfMjAxMy0yMDE2X0xISU5fNy54bHMNCg0KV2UgcXVvdGUgZnJvbSB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGRhdGE6DQoNCioqVGhlIFJlZ2lzdGVyZWQgUGVyc29ucyBEYXRhYmFzZSAoUlBEQikgYXMgdGhlIHNvdXJjZSBvZiBwb3B1bGF0aW9uKiogIA0KPGh0dHA6Ly93d3cub250YXJpb2hlYWx0aHByb2ZpbGVzLmNhL29fZG9jdW1lbnRzL2Fib3V0VGhlRGF0YU9OL1JQREJfdnNfQ2Vuc3VzX09jdF8yNl8yMDE4LnBkZj4NCg0KPiAqKlR3byBtYWluIHBvcHVsYXRpb24gc291cmNlcyoqDQo+DQo+VGhlcmUgYXJlIHR3byBtYWluIHNvdXJjZXMgdGhhdCBwcm92aWRlIHRoZSBtb3N0IHJlbGlhYmxlIGVzdGltYXRlcyBvZiBPbnRhcmlvJ3MgcG9wdWxhdGlvbi4gRm9yDQpwdXJwb3NlcyBvZiBPQ0hQUCByZXBvcnRpbmcsIHdlIHVzZSB0aGUgUmVnaXN0ZXJlZCBQZXJzb25zIERhdGFiYXNlIChSUERCKSBhcyB0aGUgc291cmNlDQooZGVub21pbmF0b3IpIGZvciBhbGwgb2Ygb3VyIGhlYWx0aC1yZWxhdGVkIGluZGljYXRvcnMuIFdoaWxlIGFub3RoZXIgbWFqb3Igc291cmNlIGZvciBpZGVudGlmeWluZyB0aGUNCnBvcHVsYXRpb24gKGRlbm9taW5hdG9yKSBpcyBTdGF0aXN0aWNzIENhbmFkYeKAmXMgQ2Vuc3VzIGNvdW50cyAoQ2Vuc3VzKSwgdGhlIE9DSFBQIGhhcyBkZXRlcm1pbmVkIHRoYXQNCnRoZSBSUERCIHByb3ZpZGVzIGEgbW9yZSBjb25zaXN0ZW50IG1lYXN1cmUgZm9yIHRoZSBjYWxjdWxhdGlvbiBvZiByYXRlcyBmb3IgaGVhbHRoIGluZGljYXRvcnMgYW5kDQpjb25kaXRpb25zLiBXZSBleHBsYWluIHdoeSBhbmQgcHJvdmlkZSBleGFtcGxlcyB0byBpbGx1c3RyYXRlLg0KPg0KPiAqKlJQREIqKg0KPg0KPlRoZSBSUERCIChkYXRhYmFzZSkgcHJvdmlkZXMgYmFzaWMgZGVtb2dyYXBoaWMgaW5mb3JtYXRpb24gYWJvdXQgYW55b25lIHdobyBoYXMgZXZlciByZWNlaXZlZCBhbg0KT250YXJpbyBIZWFsdGggSW5zdXJhbmNlIFBsYW4gKE9ISVApIGNhcmQuIE9ISVAgY2FyZHMgaW5jbHVkZSBhIHVuaXF1ZSBIZWFsdGggQ2FyZCBOdW1iZXIgKEhDTikgdG8NCmlkZW50aWZ5IGEgcGVyc29uJ3MgYWdlLCBzZXggYW5kIGFkZHJlc3MsIGluY2x1ZGluZyBwb3N0YWwgY29kZS4gVGhlIHBvc3RhbCBjb2RlcyB1c2VkIGF0IElDRVMgY29tZQ0KbWFpbmx5IGZyb20gSENOcy4gSW5mb3JtYXRpb24gZnJvbSB0aGUgaGVhbHRoIGNhcmQgaXMgc3RvcmVkIGluIHRoZSBSUERCLiBIZWFsdGggY2FyZHMgYXJlIHVzdWFsbHkNCnJlbmV3ZWQgZXZlcnkgNSB5ZWFycywgYSBwcm9jZXNzIHRoYXQgaGVscHMgdG8gZW5zdXJlIHRoYXQgaW5mb3JtYXRpb24gaW4gdGhlIHN5c3RlbSBpcyBwZXJpb2RpY2FsbHkNCnJlZnJlc2hlZCwgc3VjaCBhcyBhZGRyZXNzLCBmb3IgZXhhbXBsZSwgc2hvdWxkIGEgcGVyc29uIG1vdmUgYW5kIHVwZGF0ZSB0aGUgY2FyZCB3aXRoaW4gdGhhdCB0aW1lDQpmcmFtZS4gVGhlIHN5c3RlbSBtYXkgYWxzbyBiZSB1cGRhdGVkIG1vcmUgZnJlcXVlbnRseSBpZiBhbiBpbmRpdmlkdWFsIGludGVyYWN0cyB3aXRoIHRoZSBoZWFsdGhjYXJlDQpzeXN0ZW0gYmV0d2VlbiByZW5ld2FsIHBlcmlvZHMuIFRoaXMgYWxsb3dzIGZvciBhIG1vcmUgY3VycmVudCBzb3VyY2Ugb2YgbG9jYXRpb24tYmFzZWQgZGF0YSBmb3INCmhlYWx0aCByZXBvcnRpbmcuDQo+DQo+ICoqQ2Vuc3VzKioNCj4NCj5Bbm90aGVyIHNvdXJjZSBvZiBkYXRhIG9uIHdoZXJlIHBlb3BsZSBsaXZlIGNhbiBjb21lIGZyb20gU3RhdGlzdGljcyBDYW5hZGEgKFN0YXRzIENhbikuIFN0YXRzIENhbg0KY29sbGVjdHMgZGF0YSBvbiBpbmRpdmlkdWFscyBsaXZpbmcgaW4gQ2FuYWRhIHRocm91Z2ggdGhlIENlbnN1cywgYSBzdXJ2ZXkgY29uZHVjdGVkIGV2ZXJ5IDUgeWVhcnMuIFN0YXRzIENhbg0KcmVwb3J0cyB3aG8gbGl2ZXMgaW4gYSBnaXZlbiBhcmVhIGF0IG9uZSBwb2ludCBpbiB0aW1lIOKAkyBpLmUuIGJhc2VkIG9uIHRoZSBpbmZvcm1hdGlvbiBhbiBpbmRpdmlkdWFsIHByb3ZpZGVzIHdoZW4NCmNvbXBsZXRpbmcgdGhlIENlbnN1cw0KPg0KPiAqKlJQREIgdnMuIENlbnN1cyoqDQo+DQo+V2hpbGUgYXQgdGhlIHByb3ZpbmNpYWwgbGV2ZWwsIHRoZSBudW1iZXIgb2YgcGVvcGxlIHdlIGlkZW50aWZ5IGluIHRoZSBSUERCIGFzIGxpdmluZyBpbiBPbnRhcmlvIGRvZXMgbm90DQpkaWZmZXIgbXVjaCBmcm9tIENlbnN1cyBlc3RpbWF0ZXMsIGRpZmZlcmVuY2VzIGFyZSBtb3JlIHByb25vdW5jZWQgYXQgc21hbGxlciBhcmVhcyBzdWNoIGFzDQpuZWlnaGJvdXJob29kcyBvciBsb2NhbCBhcmVhcy4gVGhpcyBwYXJ0aWN1bGFyIGlzc3VlIGlzIG1vc3QgZXZpZGVudCBpbiBhcmVhcyBvZiBoaWdoIG1pZ3JhdGlvbiB3aGVyZSB3ZQ0KaGF2ZSBvYnNlcnZlZCBsYXJnZSBkaWZmZXJlbmNlcyBpbiByYXRlcyB1c2luZyBSUERCIHZzLiB0aGUgQ2Vuc3VzIGluIHBhcnQgZHVlIHRvIHBvcHVsYXRpb24gbW9iaWxpdHkuICANCj5Gb3IgZXhhbXBsZSwgaW4gc29tZSBhcmVhcyBvZiBPbnRhcmlvLCBwYXJ0aWN1bGFybHkgaW4gbGFyZ2VyIHVyYmFuIGNlbnRyZXMsIG5ld2NvbWVycyB0byB0aGUgYXJlYSBvZnRlbg0Kc2V0dGxlIGZpcnN0IOKAnGRvd250b3du4oCdIGJ1dCBvdmVyIHRpbWUsIG1heSBtb3ZlIGZyb20gZG93bnRvd24gdG8gb3V0bHlpbmcgYXJlYXMuIFRoZSBtYWpvcml0eSBvZg0KcGVvcGxlIHdobyBtb3ZlIGRvIG5vdCBjaGFuZ2Ugb3IgdXBkYXRlIHRoZWlyIGhlYWx0aCBjYXJkIHVudGlsIHJlbmV3YWwgdGltZSBzbyB0aGV5IHN0YXkgaW4gdGhlIFJQREINCndpdGggdGhlaXIgb3JpZ2luYWwgaGVhbHRoIGNhcmQgaW5mb3JtYXRpb24gaW5jbHVkaW5nIHRoZSBhZGRyZXNzIGFuZCBwb3N0YWwgY29kZSBvZiB0aGVpciDigJxkb3dudG93buKAnQ0KYWRkcmVzcy4gIA0KPlRoZSBzYW1lIGlzIHRydWUgb2YgQ2Vuc3VzIHBvcHVsYXRpb24gY291bnRzOiB3aGVuIHNvbWVvbmUgbW92ZXMsIHRoZXkgYXJlIHN0aWxsIGNvbnNpZGVyZWQgbGl2aW5nIGF0DQp0aGVpciBvcmlnaW5hbCBhZGRyZXNzIGFuZCBjb21wcmlzZSB0aGUgcG9wdWxhdGlvbiBvZiB0aGF0IGFyZWEgdW50aWwgdGhlIG5leHQgQ2Vuc3VzIGlzIHRha2VuIChldmVyeSA1DQp5ZWFycykuDQoNCiMgU2hhcGVmaWxlIGZvciBDaXR5IG9mIFRvcm9udG8ncyAxNDAgbmVpZ2hib3VyaG9vZHMNCg0KV2Ugbm93IGltcG9ydCBhbmQgcHJvY2VzcyBhIHNoYXBlZmlsZSBmb3IgVG9yb250bydzIDE0MCBuZWlnaGJvdXJob29kcy4NCg0KPGh0dHBzOi8vd3d3LnRvcm9udG8uY2EvY2l0eS1nb3Zlcm5tZW50L2RhdGEtcmVzZWFyY2gtbWFwcy9vcGVuLWRhdGEvb3Blbi1kYXRhLWNhdGFsb2d1ZS8jYTQ1YmQ0NWEtZWRlOC03MzBlLTFhYmMtOTMxMDViMmM0MzlmPg0KDQo8aHR0cDovL29wZW5kYXRhLnRvcm9udG8uY2EvZ2NjL25laWdoYm91cmhvb2RzX3BsYW5uaW5nX2FyZWFzX3dnczg0LnppcD4NCg0KKipOZWlnaGJvdXJob29kcyoqDQoNCj4gT3duZXI6IFNvY2lhbCBEZXZlbG9wbWVudCwgRmluYW5jZSAmIEFkbWluaXN0cmF0aW9uDQo+DQo+IEN1cnJlbmN5OiBKdW5lIDIwMTQNCg0KKipOZWlnaGJvdXJob29kcyAoV0dTODQpKioNCg0KYGBge3J9DQpsaWJyYXJ5KGRhdGEudGFibGUpICNmcmVhZA0KbGlicmFyeShwbHlyKSAjam9pbg0KbGlicmFyeShnZ3Bsb3QyKSAjZ2dwbG90LCBmb3J0aWZ5DQpsaWJyYXJ5KHNwKSAjdXNlZCBieSByZ2RhbA0KbGlicmFyeShyZ2RhbCkgI3JlYWRPR1INCmxpYnJhcnkocmdlb3MpICNnQ2VudHJvaWQNCmxpYnJhcnkoc2NhbGVzKSAjc2NhbGVfZmlsbF9kaXN0aWxsZXIsIHBlcmNlbnRfZm9ybWF0DQpsaWJyYXJ5KGdnbWFwKSAjdGhlbWVfbm90aGluZw0KbGlicmFyeShIbWlzYykgI3Jjb3JyDQpgYGANCklucHV0IHNoYXBlZmlsZQ0KYGBge3J9DQpuYmRzLnNoIDwtIHJlYWRPR1IoIkM6L1VzZXJzLzE0MTY1L0Rlc2t0b3AvQXJjR0lTL1NIQVBFRklMRVMvbmVpZ2hib3VyaG9vZHNfcGxhbm5pbmdfYXJlYXNfd2dzODQiLCAiTkVJR0hCT1JIT09EU19XR1M4NCIpDQpgYGANCkFkZCAiaWQiIGNvbHVtbg0KYGBge3J9DQpuYmRzLnNoQGRhdGEkaWQgPC0gYXMuaW50ZWdlcihuYmRzLnNoQGRhdGEkQVJFQV9TX0NEKQ0KYGBgDQpNYWtlIGNlbnRyb2lkcyBvZiBlYWNoIG5laWdoYm91cmhvb2QsIGZvciBwbGFjaW5nIGxhYmVscyB3aGVuIHBsb3R0aW5nDQpgYGB7cn0NCm5iZHMuc2guY2VudHJvaWRzICA8LSBhcy5kYXRhLmZyYW1lKGdDZW50cm9pZChuYmRzLnNoLCBieWlkID0gVFJVRSkpDQpgYGANCkFkZCAiaWQiIGNvbHVtbg0KYGBge3J9DQpuYmRzLnNoLmNlbnRyb2lkcyRpZCA8LSBuYmRzLnNoQGRhdGEkaWQNCmBgYA0KU2hhcGVmaWxlIHByb2Nlc3NpbmcNCmBgYHtyfQ0KbmJkcy5zaC5wb2ludHMgPSBmb3J0aWZ5KG5iZHMuc2gsIHJlZ2lvbiA9ICJpZCIpDQoNCm5iZHMuc2guZGYgPSBqb2luKG5iZHMuc2gucG9pbnRzLCBuYmRzLnNoQGRhdGEsIGJ5ID0gImlkIikNCmBgYA0KV2UgYXJlIG5vdyBkb25lIHdpdGggc2hhcGVmaWxlIHByb2Nlc3NpbmcuDQoNCldlIGNvcGllZCBzZWxlY3RlZCBjb2x1bW5zIGZyb20gc2hlZXRzIG9mIHRoZSAueGxzLy54bHN4IGZpbGVzIHRvIG5ldyBzaGVldHMsIHJlbmFtZWQgY29sdW1ucyBieSBjaGFuZ2luZyBzcGFjZXMgYW5kIGh5cGhlbnMgdG8gdW5kZXJzY29yZXMgYW5kIHNwZWxsaW5nIHN5bWJvbHMsIGFuZCBleHBvcnRlZCB0aGVzZSB0byAuY3N2IGZpbGVzLg0KDQpXZSBzaGFsbCB2aXN1YWxpemUgc2VsZWN0ZWQgZGF0YSBmcm9tIHRoZXNlIHRhYmxlcyBvbiBhIG1hcC4gVGhlbiB3ZSBjb21wdXRlIGNvcnJlbGF0aW9ucy4NCg0KIyBQcmltYXJ5IENhcmU6IEVucm9sbWVudCBhbmQgQ29udGludWl0eSBvZiBDYXJlIDIwMTEvMTMNCg0KMV9wY19Db250aW51aXR5X05vblJvc3RlcmVkX1Jvc3RlcmVkX1BhdGllbnRzX25laWdoYl8yMDEzX0xISU5fNy54bHN4IUNvbnRpbnVpdHlfRW5yb2xsZWRfTm9uRW5yb2xsZWQ6DQoNCj4gUHJpbWFyeSBDYXJlOiBFbnJvbG1lbnQgYW5kIENvbnRpbnVpdHkgb2YgQ2FyZSAoQm90aCBzZXhlcywgQWdlcyAxOSspIGZvciBUb3JvbnRvIE5laWdoYm91cmhvb2RzIGFuZCBUb3JvbnRvIENlbnRyYWwgTEhJTiwgMjAxMS8xMiB0byAyMDEyLzEzIChBcHJpbCAxLCAyMDExLU1hcmNoIDMxLCAyMDEzKQ0KPg0KPiBEYXRhIHNvdXJjZXM6IFBvcHVsYXRpb24gLSBPbnRhcmlvIEhlYXRoIEluc3VyYW5jZSBQbGFuIChPSElQKSBwaHlzaWNpYW4gY2xhaW1zLCBDbGllbnQgQWdlbmN5IFByb3ZpZGVyIEVucm9sbWVudCAoQ0FQRSkgdGFibGVzLCBSZWdpc3RlcmVkIFBlcnNvbnMnIERhdGFiYXNlLCBDb21tdW5pdHkgSGVhbHRoIENlbnRyZSBjbGllbnQgZW5jb3VudGVyIGRhdGEuDQo+DQo+IFBvcHVsYXRpb24gRW5yb2xsZWQ6IHJvc3RlcmVkIHdpdGggYSBQYXRpZW50IEVucm9sbWVudCBNb2RlbCAoUEVNKSBvciByZWdpc3RlcmVkIHdpdGggYSBDb21tdW5pdHkgSGVhbHRoIENlbnRyZSAoQ0hDKS4JDQo+DQo+IFBvcHVsYXRpb24gTm9uLUVucm9sbGVkOiBub3Qgcm9zdGVyZWQgd2l0aCBhIFBhdGllbnQgRW5yb2xtZW50IE1vZGVsIChQRU0pIG9yIHJlZ2lzdGVyZWQgd2l0aCBhIENvbW11bml0eSBIZWFsdGggQ2VudHJlIChDSEMpLgkJCQ0KDQoiaWQiLCAiUG9wdWxhdGlvbl8xOV9wbHVzIiwgIkVucm9sbGVkX1BvcHVsYXRpb24iLCAiRW5yb2xsZWRfUG9wdWxhdGlvbl93aXRoX05vX1Zpc2l0cyIsICJFbnJvbGxlZF9Qb3B1bGF0aW9uX3dpdGhfMV9vcl8yX1Zpc2l0cyIsICJFbnJvbGxlZF9Qb3B1bGF0aW9uX3dpdGhfM19wbHVzX1Zpc2l0cyIsICJOb25fRW5yb2xsZWRfUG9wdWxhdGlvbiIsICJOb25fRW5yb2xsZWRfUG9wdWxhdGlvbl93aXRoX05vX1Zpc2l0cyIsICJOb25fRW5yb2xsZWRfUG9wdWxhdGlvbl93aXRoXzFfb3JfMl9WaXNpdHMiLCAiTm9uX0Vucm9sbGVkX1BvcHVsYXRpb25fd2l0aF8zX3BsdXNfVmlzaXRzIiwgIlRvdGFsX1BvcHVsYXRpb25fRW5yb2xsZWRfYW5kX05vbl9FbnJvbGxlZCIsICJUb3RhbF9Qb3B1bGF0aW9uX3dpdGhfTm9fVmlzaXRzIiwgIlRvdGFsX1BvcHVsYXRpb25fd2l0aF8xX29yXzJfVmlzaXRzIiwgIlRvdGFsX1BvcHVsYXRpb25fd2l0aF8zX3BsdXNfVmlzaXRzIg0KDQoqKjFfcGNfQ29udGludWl0eV9Ob25Sb3N0ZXJlZF9Sb3N0ZXJlZF9QYXRpZW50c19uZWlnaGJfMjAxM19MSElOXzcuY3N2KioNCg0KYGBge3J9DQpwYXRpZW50cyA8LSBmcmVhZCgiMV9wY19Db250aW51aXR5X05vblJvc3RlcmVkX1Jvc3RlcmVkX1BhdGllbnRzX25laWdoYl8yMDEzX0xISU5fNy5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0Kc3RyKHBhdGllbnRzKQ0KYGBgDQoNCg0KQ3JlYXRlIHJhdGlvIGNvbHVtbnMgZm9yIHNlbGVjdGVkIHZhcmlhYmxlcw0KYGBge3J9DQpwYXRpZW50cyRSYXRpb19Ob25fRW5yb2xsZWRfUG9wdWxhdGlvbiA8LSBwYXRpZW50cyROb25fRW5yb2xsZWRfUG9wdWxhdGlvbi9wYXRpZW50cyRQb3B1bGF0aW9uXzE5X3BsdXMNCg0KcGF0aWVudHMkUmF0aW9fVG90YWxfUG9wdWxhdGlvbl93aXRoX05vX1Zpc2l0cyA8LSBwYXRpZW50cyRUb3RhbF9Qb3B1bGF0aW9uX3dpdGhfTm9fVmlzaXRzL3BhdGllbnRzJFBvcHVsYXRpb25fMTlfcGx1cw0KDQpwYXRpZW50cyRSYXRpb19Ub3RhbF9Qb3B1bGF0aW9uX3dpdGhfM19wbHVzX1Zpc2l0cyA8LSBwYXRpZW50cyRUb3RhbF9Qb3B1bGF0aW9uX3dpdGhfM19wbHVzX1Zpc2l0cy9wYXRpZW50cyRQb3B1bGF0aW9uXzE5X3BsdXMNCg0KcGF0aWVudHNfcmF0aW9zIDwtIHBhdGllbnRzWywuKGlkLFJhdGlvX05vbl9FbnJvbGxlZF9Qb3B1bGF0aW9uLFJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF9Ob19WaXNpdHMsUmF0aW9fVG90YWxfUG9wdWxhdGlvbl93aXRoXzNfcGx1c19WaXNpdHMpXQ0KYGBgDQoNCiMjIFJhdGlvX05vbl9FbnJvbGxlZF9Qb3B1bGF0aW9uDQpgYGB7cn0NClJhdGlvX05vbl9FbnJvbGxlZF9Qb3B1bGF0aW9uIDwtIHBhdGllbnRzX3JhdGlvc1ssIC4oaWQsUmF0aW9fTm9uX0Vucm9sbGVkX1BvcHVsYXRpb24pXQ0KDQpSYXRpb19Ob25fRW5yb2xsZWRfUG9wdWxhdGlvbi5zaCA8LSBtZXJnZShuYmRzLnNoLmRmLCBSYXRpb19Ob25fRW5yb2xsZWRfUG9wdWxhdGlvbiwgYnkgPSAiaWQiKQ0KYGBgDQpNYWtlIGdyYXBoaWNzIG9iamVjdA0KYGBge3J9DQpwLlJhdGlvX05vbl9FbnJvbGxlZF9Qb3B1bGF0aW9uIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBSYXRpb19Ob25fRW5yb2xsZWRfUG9wdWxhdGlvbi5zaCwgDQogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBSYXRpb19Ob25fRW5yb2xsZWRfUG9wdWxhdGlvbiksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yKSArIA0KICBjb29yZF9tYXAoKSArIA0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJSYXRpbyIsIGxhYmVscz1wZXJjZW50X2Zvcm1hdChhY2N1cmFjeT0xKSwgcGFsZXR0ZSA9ICJQdVJkIiwgdHJhbnMgPSAicmV2ZXJzZSIsIGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDgpKSsNCiAgdGhlbWVfbm90aGluZyhsZWdlbmQgPSBUUlVFKSArIA0KICBsYWJzKHRpdGxlPSJSYXRpbyBvZiB0b3RhbCBwb3B1bGF0aW9uIG5vbi1lbnJvbGxlZCIpICsNCiAgZ2VvbV90ZXh0KGFlcyh4PXgseT15LCBncm91cD1OVUxMLCBsYWJlbD1pZCksIGRhdGEgPSBuYmRzLnNoLmNlbnRyb2lkcywgc2l6ZSA9IDIpDQpgYGANClBsb3QgZ3JhcGhpY3Mgb2JqZWN0DQpgYGB7cn0NCnAuUmF0aW9fTm9uX0Vucm9sbGVkX1BvcHVsYXRpb24gKyBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKQ0KYGBgDQoNCiMjIFJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF9Ob19WaXNpdHMNCmBgYHtyfQ0KUmF0aW9fVG90YWxfUG9wdWxhdGlvbl93aXRoX05vX1Zpc2l0cyA8LSBwYXRpZW50c19yYXRpb3NbLCAuKGlkLFJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF9Ob19WaXNpdHMpXQ0KDQpSYXRpb19Ub3RhbF9Qb3B1bGF0aW9uX3dpdGhfTm9fVmlzaXRzLnNoIDwtIG1lcmdlKG5iZHMuc2guZGYsIFJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF9Ob19WaXNpdHMsIGJ5ID0gImlkIikNCmBgYA0KDQpNYWtlIGdyYXBoaWNzIG9iamVjdA0KYGBge3J9DQpwLlJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF9Ob19WaXNpdHMgPC0gZ2dwbG90KCkgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IFJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF9Ob19WaXNpdHMuc2gsIA0KICAgICAgICAgICAgICAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gUmF0aW9fVG90YWxfUG9wdWxhdGlvbl93aXRoX05vX1Zpc2l0cyksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yKSArIA0KICBjb29yZF9tYXAoKSArIA0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJSYXRpbyIsIGxhYmVscz1wZXJjZW50X2Zvcm1hdChhY2N1cmFjeT0xKSwgcGFsZXR0ZSA9ICJQdVJkIiwgdHJhbnMgPSAicmV2ZXJzZSIsIGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDgpKSArIA0KICB0aGVtZV9ub3RoaW5nKGxlZ2VuZCA9IFRSVUUpICsgDQogIGxhYnModGl0bGU9IlJhdGlvIG9mIHRvdGFsIHBvcHVsYXRpb24gd2l0aCBubyB2aXNpdHMiKSArDQogIGdlb21fdGV4dChhZXMoeD14LHk9eSwgZ3JvdXA9TlVMTCwgbGFiZWw9aWQpLCBkYXRhID0gbmJkcy5zaC5jZW50cm9pZHMsIHNpemUgPSAyKQ0KYGBgDQpQbG90IGdyYXBoaWNzIG9iamVjdA0KYGBge3J9DQpwLlJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF9Ob19WaXNpdHMgKyBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKQ0KYGBgDQoNCiMjIFJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF8zX3BsdXNfVmlzaXRzDQpgYGB7cn0NClJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF8zX3BsdXNfVmlzaXRzIDwtIHBhdGllbnRzX3JhdGlvc1ssIC4oaWQsUmF0aW9fVG90YWxfUG9wdWxhdGlvbl93aXRoXzNfcGx1c19WaXNpdHMpXQ0KDQpSYXRpb19Ub3RhbF9Qb3B1bGF0aW9uX3dpdGhfM19wbHVzX1Zpc2l0cy5zaCA8LSBtZXJnZShuYmRzLnNoLmRmLCBSYXRpb19Ub3RhbF9Qb3B1bGF0aW9uX3dpdGhfM19wbHVzX1Zpc2l0cywgYnkgPSAiaWQiKQ0KYGBgDQpNYWtlIGdyYXBoaWNzIG9iamVjdA0KYGBge3J9DQpwLlJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF8zX3BsdXNfVmlzaXRzIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBSYXRpb19Ub3RhbF9Qb3B1bGF0aW9uX3dpdGhfM19wbHVzX1Zpc2l0cy5zaCwgDQogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBSYXRpb19Ub3RhbF9Qb3B1bGF0aW9uX3dpdGhfM19wbHVzX1Zpc2l0cyksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yKSArIA0KICBjb29yZF9tYXAoKSArIA0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJSYXRpbyIsIGxhYmVscz1wZXJjZW50X2Zvcm1hdChhY2N1cmFjeT0xKSwgcGFsZXR0ZSA9ICJHcmVlbnMiLCB0cmFucyA9ICJyZXZlcnNlIiwgYnJlYWtzID0gcHJldHR5X2JyZWFrcyhuID0gOCkpKw0KICB0aGVtZV9ub3RoaW5nKGxlZ2VuZCA9IFRSVUUpICsgDQogIGxhYnModGl0bGU9IlJhdGlvIG9mIHRvdGFsIHBvcHVsYXRpb24gd2l0aCAzKyB2aXNpdHMiKSArDQogIGdlb21fdGV4dChhZXMoeD14LHk9eSwgZ3JvdXA9TlVMTCwgbGFiZWw9aWQpLCBkYXRhID0gbmJkcy5zaC5jZW50cm9pZHMsIHNpemUgPSAyKQ0KYGBgDQpQbG90IGdyYXBoaWNzIG9iamVjdA0KYGBge3J9DQpwLlJhdGlvX1RvdGFsX1BvcHVsYXRpb25fd2l0aF8zX3BsdXNfVmlzaXRzICsgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZT1UUlVFKSkNCmBgYA0KDQojIEFkdWx0IEhlYWx0aCBhbmQgRGlzZWFzZSAyMDE2LzE3DQoNCjFfQUhEXzIwMTdfUlBEQl9OZWlnaGJfTEhJTl83Lnhsc3ghRGlhYmV0ZXNfTmVpZ2hiX1Rvcm9udG86DQoNCj4gRGVtb2dyYXBoaWNzIC0gRGVub21pbmF0b3I6IE9udGFyaW8gTWluaXN0cnkgb2YgSGVhbHRoIGFuZCBMb25nLVRlcm0gQ2FyZSBSZWdpc3RlcmVkIFBlcnNvbnMgRGF0YWJhc2UgKFJQREIpLCBwb3B1bGF0aW9uIGFnZWQgMjArIHdobyB3ZXJlIGFsaXZlIGFuZCBsaXZpbmcgaW4gdGhlIE9udGFyaW8gb24gQXByaWwgMXN0LCAyMDE2IA0KPg0KPiBOdW1lcmF0b3I6IGRlcml2ZWQgZnJvbSB2YWxpZGF0ZWQsIGRpc2Vhc2UgcmVnaXN0cmllcyBtYWludGFpbmVkIGJ5IHRoZSBJbnN0aXR1dGUgZm9yIENsaW5pY2FsIEV2YWx1YXRpdmUgU2NpZW5jZXMgKElDRVMpDQoNCjFfQUhEXzIwMTdfUlBEQl9OZWlnaGJfTEhJTl83Lnhsc3ghQ09QRF9OZWlnaGJfVG9yb250bzoNCg0KPiBEZW1vZ3JhcGhpY3MgLSBEZW5vbWluYXRvcjogT250YXJpbyBNaW5pc3RyeSBvZiBIZWFsdGggYW5kIExvbmctVGVybSBDYXJlIFJlZ2lzdGVyZWQgUGVyc29ucyBEYXRhYmFzZSAoUlBEQiksIHBvcHVsYXRpb24gYWdlZCAzNSsgd2hvIHdlcmUgYWxpdmUgYW5kIGxpdmluZyBpbiB0aGUgT250YXJpbyBvbiBBcHJpbCAxc3QsIDIwMTYgDQo+DQo+IE51bWVyYXRvcjogZGVyaXZlZCBmcm9tIHZhbGlkYXRlZCwgZGlzZWFzZSByZWdpc3RyaWVzIG1haW50YWluZWQgYnkgdGhlIEluc3RpdHV0ZSBmb3IgQ2xpbmljYWwgRXZhbHVhdGl2ZSBTY2llbmNlcyAoSUNFUykNCg0KImlkIiwgIlBlb3BsZV93aXRoX0RpYWJldGVzXzIwX3BsdXMiLCAiVG90YWxfUG9wdWxhdGlvbl8yMDE2X1JQREJfMjBfcGx1cyIsICJQcmV2YWxlbmNlX3Blcl9odW5kcmVkX0RpYWJldGVzXzIwX3BsdXMiLCAiUGVvcGxlX3dpdGhfQ09QRF8zNV9wbHVzIiwgIlRvdGFsX1BvcHVsYXRpb25fMjAxNl9SUERCXzM1X3BsdXMiLCAiUHJldmFsZW5jZV9wZXJfaHVuZHJlZF9DT1BEXzM1X3BsdXMiDQoNCioqMV9BSERfMjAxN19SUERCX05laWdoYl9MSElOXzcuY3N2KioNCg0KYGBge3J9DQpjaHJvbmljIDwtIGZyZWFkKCIxX0FIRF8yMDE3X1JQREJfTmVpZ2hiX0xISU5fNy5jc3YiKQ0KDQpjaHJvbmljJFJhdGlvX1Blb3BsZV93aXRoX0RpYWJldGVzXzIwX3BsdXMgPC0gY2hyb25pYyRQZW9wbGVfd2l0aF9EaWFiZXRlc18yMF9wbHVzL2Nocm9uaWMkVG90YWxfUG9wdWxhdGlvbl8yMDE2X1JQREJfMjBfcGx1cw0KDQpjaHJvbmljJFJhdGlvX1Blb3BsZV93aXRoX0NPUERfMzVfcGx1cyA8LSBjaHJvbmljJFBlb3BsZV93aXRoX0NPUERfMzVfcGx1cy9jaHJvbmljJFRvdGFsX1BvcHVsYXRpb25fMjAxNl9SUERCXzM1X3BsdXMNCg0KY2hyb25pY19yYXRpb3MgPC0gY2hyb25pY1ssLihpZCxSYXRpb19QZW9wbGVfd2l0aF9EaWFiZXRlc18yMF9wbHVzLFJhdGlvX1Blb3BsZV93aXRoX0NPUERfMzVfcGx1cyldDQpgYGANCg0KYGBge3J9DQpSYXRpb19QZW9wbGVfd2l0aF9EaWFiZXRlc18yMF9wbHVzIDwtIGNocm9uaWNfcmF0aW9zWywgLihpZCxSYXRpb19QZW9wbGVfd2l0aF9EaWFiZXRlc18yMF9wbHVzKV0NCg0KUmF0aW9fUGVvcGxlX3dpdGhfRGlhYmV0ZXNfMjBfcGx1cy5zaCA8LSBtZXJnZShuYmRzLnNoLmRmLCBSYXRpb19QZW9wbGVfd2l0aF9EaWFiZXRlc18yMF9wbHVzLCBieSA9ICJpZCIpDQpgYGANCg0KTWFrZSBhbmQgcGxvdCBncmFwaGljcyBvYmplY3QNCmBgYHtyfQ0KcC5SYXRpb19QZW9wbGVfd2l0aF9EaWFiZXRlc18yMF9wbHVzIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBSYXRpb19QZW9wbGVfd2l0aF9EaWFiZXRlc18yMF9wbHVzLnNoLCANCiAgICAgICAgICAgICAgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IFJhdGlvX1Blb3BsZV93aXRoX0RpYWJldGVzXzIwX3BsdXMpLCANCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuMikgKyANCiAgY29vcmRfbWFwKCkgKyANCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIobmFtZT0iUmF0aW8iLCBsYWJlbHM9cGVyY2VudF9mb3JtYXQoYWNjdXJhY3k9MSksIHBhbGV0dGUgPSAiUHVSZCIsIHRyYW5zID0gInJldmVyc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBwcmV0dHlfYnJlYWtzKG4gPSA4KSkgKyANCiAgdGhlbWVfbm90aGluZyhsZWdlbmQgPSBUUlVFKSsNCiAgbGFicyh0aXRsZT0iUmF0aW8gb2YgcGVvcGxlIHdpdGggZGlhYmV0ZXMsIDIwKyIpICsNCiAgZ2VvbV90ZXh0KGFlcyh4PXgseT15LCBncm91cD1OVUxMLCBsYWJlbD1pZCksIGRhdGEgPSBuYmRzLnNoLmNlbnRyb2lkcywgc2l6ZSA9IDIpDQoNCnAuUmF0aW9fUGVvcGxlX3dpdGhfRGlhYmV0ZXNfMjBfcGx1cyArIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHJldmVyc2U9VFJVRSkpDQpgYGANCg0KYGBge3J9DQpSYXRpb19QZW9wbGVfd2l0aF9DT1BEXzM1X3BsdXMgPC0gY2hyb25pY19yYXRpb3NbLCAuKGlkLFJhdGlvX1Blb3BsZV93aXRoX0NPUERfMzVfcGx1cyldDQoNClJhdGlvX1Blb3BsZV93aXRoX0NPUERfMzVfcGx1cy5zaCA8LSBtZXJnZShuYmRzLnNoLmRmLCBSYXRpb19QZW9wbGVfd2l0aF9DT1BEXzM1X3BsdXMsIGJ5ID0gImlkIikNCmBgYA0KTWFrZSBhbmQgcGxvdCBncmFwaGljcyBvYmplY3QNCmBgYHtyfQ0KcC5SYXRpb19QZW9wbGVfd2l0aF9DT1BEXzM1X3BsdXMgPC0gZ2dwbG90KCkgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IFJhdGlvX1Blb3BsZV93aXRoX0NPUERfMzVfcGx1cy5zaCwgDQogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBSYXRpb19QZW9wbGVfd2l0aF9DT1BEXzM1X3BsdXMpLCANCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuMikgKyANCiAgY29vcmRfbWFwKCkgKyANCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIobmFtZT0iUmF0aW8iLCBsYWJlbHM9cGVyY2VudF9mb3JtYXQoYWNjdXJhY3k9MSksIHBhbGV0dGUgPSAiUHVSZCIsIHRyYW5zID0gInJldmVyc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBwcmV0dHlfYnJlYWtzKG4gPSA4KSkrDQogIHRoZW1lX25vdGhpbmcobGVnZW5kID0gVFJVRSkgKyANCiAgbGFicyh0aXRsZT0iUmF0aW8gb2YgcGVvcGxlIHdpdGggQ09QRCwgMzUrIikgKw0KICBnZW9tX3RleHQoYWVzKHg9eCx5PXksIGdyb3VwPU5VTEwsIGxhYmVsPWlkKSwgZGF0YSA9IG5iZHMuc2guY2VudHJvaWRzLCBzaXplID0gMikNCg0KcC5SYXRpb19QZW9wbGVfd2l0aF9DT1BEXzM1X3BsdXMgKyBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKQ0KYGBgDQoNCiMgU2V4dWFsIEhlYWx0aDogQ2hsYW15ZGlhIGNhc2VzLCBHb25vcnJoZWEgY2FzZXMgMjAxMy8xNg0KDQoyX3NoX25laWdoYl9jaGxhbV9nb25vcl8yMDEzLTIwMTZfTEhJTl83Lnhsc3ghQ2hsYW15ZGlhX01hbGVfRmVtYWxlX1Rvcl9uZWlnaDoNCg0KPiAgTnVtYmVyIG9mIENobGFteWRpYSBDYXNlcyBmb3IgQWdlIDE1IHllYXJzIGFuZCBvdmVyIGJ5IEdlbmRlciAoTWFsZSwgRmVtYWxlKSwgVG9yb250byBOZWlnaGJvdXJob29kcywgMjAxMyB0byAyMDE2IENhbGVuZGFyIFllYXJzIENvbWJpbmVkDQo+DQo+ICBEZW1vZ3JhcGhpY3MgLSBEZW5vbWluYXRvcjogQmFzZWQgb24gMjAxMSBDZW5zdXMgcG9wdWxhdGlvbiBlc3RpbWF0ZXMuIChTdGF0aXN0aWNzIENhbmFkYSwgMjAxMSBDZW5zdXMgb2YgUG9wdWxhdGlvbikuDQo+DQo+ICBOdW1lcmF0b3I6IE51bWJlciBvZiBDaGxhbXlkaWEgY2FzZXMgZm9yIDQgeWVhciAoMjAxMyB0byAyMDE2KSBvYnNlcnZhdGlvbiBwZXJpb2QuICAgICAgICBEYXRhIHNvdXJjZTogRGF0YSBhcyBvZiBKdWx5IDIwLCAyMDE3LCBUb3JvbnRvIFB1YmxpYyBIZWFsdGggaW50ZWdyYXRlZCBQdWJsaWMgSGVhbHRoIEluZm9ybWF0aW9uIFN5c3RlbSBbaVBISVNdLiANCj4NCj4gKiBBdmVyYWdlIGFubnVhbCByYXRlIG9mIENobGFteWRpYSBjYXNlcyAoLzEwMCwwMDApIE1hbGVzICgyMDEzIHRvIDIwMTYpLCBBbGwgQWdlcyAxNSsNCj4NCj4gKiBBdmVyYWdlIGFubnVhbCByYXRlIG9mIENobGFteWRpYSBjYXNlcyAoLzEwMCwwMDApIEZlbWFsZXMgKDIwMTMgdG8gMjAxNiksIEFsbCBBZ2VzIDE1Kw0KDQoiaWQiLCAiQ2hsYW15ZGlhX2Nhc2VzX21hbGUiLCAiUG9wdWxhdGlvbl9tYWxlIiwgIkNobGFteWRpYV9jYXNlc19mZW1hbGUiLCAiUG9wdWxhdGlvbl9mZW1hbGUiDQoNCioqMl9zaF9uZWlnaGJfY2hsYW1fZ29ub3JfMjAxMy0yMDE2X0xISU5fNy5jc3YqKg0KDQpgYGB7cn0NCmNobGFteWRpYSA8LSBmcmVhZCgiMl9zaF9uZWlnaGJfY2hsYW1fZ29ub3JfMjAxMy0yMDE2X0xISU5fNy5jc3YiKQ0KDQpjaGxhbXlkaWEkUmF0aW9fQ2hsYW15ZGlhX2Nhc2VzX21hbGUgPC0gY2hsYW15ZGlhJENobGFteWRpYV9jYXNlc19tYWxlL2NobGFteWRpYSRQb3B1bGF0aW9uX21hbGUNCg0KY2hsYW15ZGlhJFJhdGlvX0NobGFteWRpYV9jYXNlc19mZW1hbGUgPC0gY2hsYW15ZGlhJENobGFteWRpYV9jYXNlc19mZW1hbGUvY2hsYW15ZGlhJFBvcHVsYXRpb25fZmVtYWxlDQoNCmNobGFteWRpYV9yYXRpb3MgPC0gY2hsYW15ZGlhWywuKGlkLFJhdGlvX0NobGFteWRpYV9jYXNlc19tYWxlLFJhdGlvX0NobGFteWRpYV9jYXNlc19mZW1hbGUpXQ0KYGBgDQoNCmBgYHtyfQ0KUmF0aW9fQ2hsYW15ZGlhX2Nhc2VzX21hbGUgPC0gY2hsYW15ZGlhX3JhdGlvc1ssIC4oaWQsUmF0aW9fQ2hsYW15ZGlhX2Nhc2VzX21hbGUpXQ0KDQpSYXRpb19DaGxhbXlkaWFfY2FzZXNfbWFsZS5zaCA8LSBtZXJnZShuYmRzLnNoLmRmLCBSYXRpb19DaGxhbXlkaWFfY2FzZXNfbWFsZSwgYnkgPSAiaWQiKQ0KYGBgDQpNYWtlIGFuZCBwbG90IGdyYXBoaWNzIG9iamVjdA0KYGBge3J9DQpwLlJhdGlvX0NobGFteWRpYV9jYXNlc19tYWxlIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBSYXRpb19DaGxhbXlkaWFfY2FzZXNfbWFsZS5zaCwgDQogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBSYXRpb19DaGxhbXlkaWFfY2FzZXNfbWFsZSksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yKSArIA0KICBjb29yZF9tYXAoKSArIA0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJDYXNlcy9wb3B1bGF0aW9uIiwgbGFiZWxzPXBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5PTEpLCBwYWxldHRlID0gIllsT3JCciIsIHRyYW5zID0gInJldmVyc2UiLCBicmVha3MgPSBwcmV0dHlfYnJlYWtzKG4gPSA4KSkgKyANCiAgdGhlbWVfbm90aGluZyhsZWdlbmQgPSBUUlVFKSArIA0KICBsYWJzKHRpdGxlPSJOdW1iZXIgb2YgbWFsZSBjaGxhbXlkaWEgY2FzZXMvbWFsZSBwb3B1bGF0aW9uIikgKw0KICBnZW9tX3RleHQoYWVzKHg9eCx5PXksIGdyb3VwPU5VTEwsIGxhYmVsPWlkKSwgZGF0YSA9IG5iZHMuc2guY2VudHJvaWRzLCBzaXplID0gMikNCg0KcC5SYXRpb19DaGxhbXlkaWFfY2FzZXNfbWFsZSArIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHJldmVyc2U9VFJVRSkpDQpgYGANCg0KIyBDb3JyZWxhdGlvbnMNCmBgYHtyfQ0KT0NIUFBfcmF0aW9zIDwtIG1lcmdlKG1lcmdlKHBhdGllbnRzX3JhdGlvcywgY2hyb25pY19yYXRpb3MpLCBjaGxhbXlkaWFfcmF0aW9zKQ0KYGBgDQpTdHJ1Y3R1cmUgb2YgZGF0YSB0YWJsZToNCmBgYHtyfQ0Kc3RyKE9DSFBQX3JhdGlvcykNCmBgYA0KRHJvcCAiaWQiIGNvbHVtbg0KYGBge3J9DQpPQ0hQUF9yYXRpb3Nfbm9pZCA8LSBPQ0hQUF9yYXRpb3NbLC1jKCJpZCIpXQ0KDQpzdHIoT0NIUFBfcmF0aW9zX25vaWQpDQpgYGANCg0KQ29tcHV0ZSBjb3JyZWxhdGlvbnMNCmBgYHtyfQ0KcmNvcnIoYXMubWF0cml4KE9DSFBQX3JhdGlvc19ub2lkKSwgdHlwZT0icGVhcnNvbiIpDQpgYGANCg0KIyMgTGluZWFyIHJlZ3Jlc3Npb24NCmBgYHtyfQ0KbG1fY2hsYW0gPC0gbG0oUmF0aW9fQ2hsYW15ZGlhX2Nhc2VzX21hbGUgfiBSYXRpb19DaGxhbXlkaWFfY2FzZXNfZmVtYWxlLCBkYXRhID0gT0NIUFBfcmF0aW9zX25vaWQpDQpzdW1tYXJ5KGxtX2NobGFtKQ0KYGBgDQoNCg0KYGBge3J9DQpwbG90KGxtX2NobGFtKQ0KYGBgDQoNCiMjIENob3JvcGxldGggb2YgcmVzaWR1YWxzIA0KDQpgYGB7cn0NCnN0cihsbV9jaGxhbSRyZXNpZHVhbHMpDQpgYGANCk1ha2UgZGF0YWZyYW1lIG9mIHJlc2lkdWFscyB3aXRoICJpZCIgY29sdW1uDQpgYGB7cn0NCmxtX2NobGFtX2RmIDwtIGRhdGEuZnJhbWUoaWQgPSBjKDE6MTQwKSwgcmVzaWR1YWwgPSBsbV9jaGxhbSRyZXNpZHVhbHMpDQpoZWFkKGxtX2NobGFtX2RmKQ0KYGBgDQoNCg0KYGBge3J9DQpsbV9jaGxhbV9kZi5zaCA8LSBtZXJnZShuYmRzLnNoLmRmLCBsbV9jaGxhbV9kZiwgYnkgPSAiaWQiKQ0KYGBgDQpNYWtlIGFuZCBwbG90IGdyYXBoaWNzIG9iamVjdA0KYGBge3J9DQpwLmxtX2NobGFtX2RmIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBsbV9jaGxhbV9kZi5zaCwgDQogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSByZXNpZHVhbCksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yKSArIA0KICBjb29yZF9tYXAoKSArIA0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJSZXNpZHVhbHMiLCBwYWxldHRlID0gIkJsdWVzIiwgdHJhbnMgPSAicmV2ZXJzZSIsIGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDgpKSArIA0KICB0aGVtZV9ub3RoaW5nKGxlZ2VuZCA9IFRSVUUpICsgDQogIGxhYnModGl0bGU9IlJlc2lkdWFscyBvZiBtYWxlIGNobGFteWRpYSBjYXNlcyB+IGZlbWFsZSBjaGxhbXlkaWEgY2FzZXMiKSArDQogIGdlb21fdGV4dChhZXMoeD14LHk9eSwgZ3JvdXA9TlVMTCwgbGFiZWw9aWQpLCBkYXRhID0gbmJkcy5zaC5jZW50cm9pZHMsIHNpemUgPSAyKQ0KDQpwLmxtX2NobGFtX2RmICsgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZT1UUlVFKSkNCmBgYA==