Author

Sources and descriptions of datasets

TPS MCI 2014 to 2018

Major Crime Indicators (MCI)

Toronto Police Service Public Safety Data Portal

“MCI_2014_to_2018.csv”

http://data.torontopolice.on.ca/pages/glossary:

For the most part, the statistics on the following pages use an incident-based counting method. Generally, each type of major crime that occurred during an incident will be counted. For example, if an assault and a break and enter took place in the same incident, they would be counted once in each category. Statistics Canada also presents incident-based crime statistics, but generally counts only the most serious offence per incident. Some other police services present their crime statistics using the offence-based method, which counts all offences in each incident. It is important to note these differences when comparing our crime statistics to those provided by Statistics Canada or by other police agencies.

Assault. The direct or indirect application of force to another person, or the attempt or threat to apply force to another person, without that person’s consent.

Robbery. The act of taking property from another person or business by the use of force or intimidation in the presence of the victim.

Break and Enter. The act of entering a place with the intent to commit an indictable offence therein.

Auto Theft. The act of taking or another person’s vehicle (not including attempts). Auto Theft figures represent the number of vehicles stolen.

Theft Over. The act of stealing property in excess of $5,000 (excluding auto theft).

City of Toronto Neighbourhood Profiles

Neighbourhood Profiles

Statistics Canada does not release data at the level of Toronto’s social planning neighbourhoods. Neighbourhood level data for 2016 are initially calculated by summing data for the Census Tracts which comprise each neighbourhood.

“neighbourhood-profiles-2016-csv.csv”

Loading, understanding and cleaning datasets

library(data.table) #fread, setcolorder, rbindlist
library(sp) #used by rgdal
library(rgdal) #readOGR
library(ggplot2) #fortify
library(plyr) #join
library(scales) #scale_fill_distiller
library(ggmap) #theme_nothing
library(rgeos) #gCentroid
library(forecast) #autoplot ts, auto.arima

MCI dataset and definitions of UCR codes

MCI_dt <- fread("MCI_2014_to_2018.csv")
str(MCI_dt)
Classes ‘data.table’ and 'data.frame':  167525 obs. of  29 variables:
 $ X                  : num  -79.3 -79.5 -79.5 -79.6 -79.5 ...
 $ Y                  : num  43.7 43.8 43.7 43.7 43.7 ...
 $ Index_             : int  214 215 216 217 218 219 220 221 222 223 ...
 $ event_unique_id    : chr  "GO-20141948968" "GO-20141950728" "GO-20141956416" "GO-20141956867" ...
 $ occurrencedate     : chr  "2014-04-24T11:29:00.000Z" "2014-04-24T13:00:00.000Z" "2014-04-25T13:20:00.000Z" "2014-04-24T17:00:00.000Z" ...
 $ reporteddate       : chr  "2014-04-24T12:46:00.000Z" "2014-04-24T15:58:00.000Z" "2014-04-25T13:52:00.000Z" "2014-04-25T10:30:00.000Z" ...
 $ premisetype        : chr  "Commercial" "House" "Apartment" "Outside" ...
 $ ucr_code           : int  1610 2120 1430 1430 1430 1430 1430 1420 1420 1420 ...
 $ ucr_ext            : int  200 200 100 100 100 100 100 100 100 100 ...
 $ offence            : chr  "Robbery - Mugging" "B&E" "Assault" "Assault" ...
 $ reportedyear       : int  2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 ...
 $ reportedmonth      : chr  "April" "April" "April" "April" ...
 $ reportedday        : int  24 24 25 25 25 25 3 3 3 3 ...
 $ reporteddayofyear  : int  114 114 115 115 115 115 123 123 123 123 ...
 $ reporteddayofweek  : chr  "Thursday" "Thursday" "Friday" "Friday" ...
 $ reportedhour       : int  12 15 13 10 16 22 3 4 4 4 ...
 $ occurrenceyear     : int  2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 ...
 $ occurrencemonth    : chr  "April" "April" "April" "April" ...
 $ occurrenceday      : int  24 24 25 24 25 25 3 3 3 3 ...
 $ occurrencedayofyear: int  114 114 115 114 115 115 123 123 123 123 ...
 $ occurrencedayofweek: chr  "Thursday" "Thursday" "Friday" "Thursday" ...
 $ occurrencehour     : int  11 13 13 17 16 22 1 4 4 4 ...
 $ MCI                : chr  "Robbery" "Break and Enter" "Assault" "Assault" ...
 $ Division           : chr  "D55" "D31" "D12" "D23" ...
 $ Hood_ID            : int  68 24 30 4 114 73 64 79 79 79 ...
 $ Neighbourhood      : chr  "North Riverdale (68)" "Black Creek (24)" "Brookhaven-Amesbury (30)" "Rexdale-Kipling (4)" ...
 $ Lat                : num  43.7 43.8 43.7 43.7 43.7 ...
 $ Long               : num  -79.3 -79.5 -79.5 -79.6 -79.5 ...
 $ ObjectId           : int  1 2 3 4 5 6 7 8 9 10 ...
 - attr(*, ".internal.selfref")=<externalptr> 
unique(MCI_dt$premisetype)
[1] "Commercial" "House"      "Apartment"  "Outside"    "Other"     
sort(unique(MCI_dt$ucr_code))
 [1] 1410 1420 1430 1440 1450 1455 1457 1460 1461 1462 1470 1475 1480 1610 2120 2121 2125 2130 2132
[20] 2133 2135
sort(unique(MCI_dt$Hood_ID))
  [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24
 [25]  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48
 [49]  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
 [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96
 [97]  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
[121] 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
unique(MCI_dt$MCI)
[1] "Robbery"         "Break and Enter" "Assault"         "Theft Over"      "Auto Theft"     

Uniform Crime Reporting Survey (UCR). UCR Incident-Based Survey: RDC User Manual:

  • 1410 - Aggravated Assault – Level 3
  • 1420 - Assault with Weapon or Causing Bodily Harm – Level 2
  • 1430 - Assault – Level 1
  • 1440 - Unlawfully Causing Bodily Harm
  • 1450 - Discharge Firearm with Intent
  • 1455 - Using Firearm/Imitation of Firearm in commission of offence
  • 1457 - Pointing a Firearm
  • 1460 - Assault Against Peace-Public Officer
  • 1461 – Assault against Peace Officer with a Weapon or Causing Bodily Harm
  • 1462 – Aggravated Assault against Peace Officer
  • 1470 - Criminal Negligence Causing Bodily Harm
  • 1475 – Trap Likely To or Causing Bodily Harm
  • 1480 - Other Assaults
  • 1610 - Robbery
  • 2120 - Break and Enter
  • 2121 – Break and Enter to Steal Firearm
  • 2125 – Break and Enter of a Motor Vehicle to obtain a Firearm
  • 2130 – Theft over $5,000
  • 2132 – Theft over $5,000 from a Motor Vehicle
  • 2133 – Shoplifting over $5,000
  • 2135 – Theft of a Motor Vehicle

Statistics Canada:

Assault refers to three levels of physical assaults which include the following categories:

Common assault, (section 265). This includes the Criminal Code category assault (level 1). This is the least serious form of assault and includes pushing, slapping, punching, and face-to-face verbal threats.

Major assault levels 2 and 3, (sections 267, 268). This includes more serious forms of assault, i.e. assault with a weapon or causing bodily harm (level 2) and aggravated assault (level 3). Assault level 2 involves carrying, using or threatening to use a weapon against someone or causing someone bodily harm. Assault level 3 involves wounding, maiming, disfiguring or endangering the life of someone.

Criminal Code (R.S.C., 1985, c. C-46)

bodily harm means any hurt or injury to a person that interferes with the health or comfort of the person and that is more than merely transient or trifling in nature; (lésions corporelles)

Criminal negligence
219 (1) Every one is criminally negligent who
(a) in doing anything, or
(b) in omitting to do anything that it is his duty to do,
shows wanton or reckless disregard for the lives or safety
of other persons.

Assault
265 (1) A person commits an assault when
(a) without the consent of another person, he applies force intentionally to that other person, directly or indirectly;
(b) he attempts or threatens, by an act or a gesture, to apply force to another person, if he has, or causes that other person to believe on reasonable grounds that he has, present ability to effect his purpose; or
(c) while openly wearing or carrying a weapon or an imitation thereof, he accosts or impedes another person or begs.

Breaking and entering with intent, committing offence or breaking out
348 (1) Every one who
(a) breaks and enters a place with intent to commit an indictable offence therein,
(b) breaks and enters a place and commits an indictable offence therein, or
(c) breaks out of a place after
(i) committing an indictable offence therein, or
(ii) entering the place with intent to commit an indictable offence therein, is guilty (d) if the offence is committed in relation to a dwelling-house, of an indictable offence and liable to imprisonment for life, and
(e) if the offence is committed in relation to a place other than a dwelling-house, of an indictable offence and liable to imprisonment for a term not exceeding ten years or of an offence punishable on summary conviction.

Robbery
343 Every one commits robbery who
(a) steals, and for the purpose of extorting whatever is stolen or to prevent or overcome resistance to the stealing, uses violence or threats of violence to a person or property;
(b) steals from any person and, at the time he steals or immediately before or immediately thereafter, wounds, beats, strikes or uses any personal violence to that person;
(c) assaults any person with intent to steal from him; or
(d) steals from any person while armed with an offensive weapon or imitation thereof.

Breaking and Entering in Canada - 2002, Juristat, Statistics Canada – Catalogue no. 85-002-XPE, Vol. 24, no. 5, page 1: > In 2002, over 31,000 persons were charged with B&E, the vast majority of whom were male (91%). Four in ten persons charged with B&E were youths. For property and violent crimes overall, youths represented 26% and 16% of persons charged, respectively.

Mathieu Charron, Neighbourhood Characteristics and the Distribution of Police-reported Crime in the City of Toronto, Canadian Centre For Justice Statistics, Statistics Canada, Catalogue no. 85-561-M, no. 18.
p. 11:

Crimes reported to the police are not randomly distributed throughout Toronto, but are concentrated in certain areas. An examination of local crime rates (the relationship between the number of crimes and the population at a local level) shows that the rates of violent crime are higher near the downtown core and in the east and northwest areas of the city (Map 5; See ‘Mapping techniques’ in the Methodology section for technical details.), which correspond roughly to the neighbourhoods along the Canadian National railway and to the areas where residents earn the lowest individual incomes (Map 3). There are some hot spots within these areas that have higher rates.Some of these are Danforth, downtown east side and the intersections of Lawrence and Morningside, Jane and Finch, and Jane and Eglinton.

p. 12:

In contrast, in the north area along Yonge Street, where residents earn a higher income, the violent crime rate is much lower than average. The business district—the Bay Street area where most of the workers in the finance and insurance industry are employed—has a violent crime rate well below the average for the city of Toronto. This differs from most of the other Canadian cities that have been the focus of studies, where the violent crime rate in the centre was high (Fitzgerald et al. 2004; Wallace et al. 2006; Kitchen 2006; Charron 2008). A similar situation was noted in Montréal, where the crime hot spots were spread out in many areas of the city (Savoie et al. 2006). The results suggest that the complex social geography of large cities like Toronto and Montréal is related to the spatial organization of crime.

pp. 12-13:

Several neighbourhood characteristics vary according to the local police-reported crime rate. Neighbourhoods with a high rate of violent crime are more densely populated and have a higher percentage of residents living in multi-unit dwellings.They also have the highest percentages of children (under the age of 15), renters, single-parent families and visible minorities. The residents of these neighbourhoods are also less likely to have a university degree, more likely to earn a lower wage, and more likely to live in low-income households.

p. 23:

As for demographic characteristics, rates of harassment and common assault increase with the proportion of children (under 15) and of young men (aged 20 to 29). Rates of sexual assaults, threats, major assaults and robberies decrease as the proportion of people aged 65 and older increases.

p. 24:

Motor vehicle theft rates are higher in neighbourhoods with higher proportions of children (under 15) and young men aged 20 to 29. They are also higher in neighbourhoods where access to socio-economic resources is limited or where there is a subway or train station, as well as in clusters of commercial and manufacturing activity.

p. 25:

The spatial structure of breaking and entering varies essentially with urban and economic activity characteristics. More specifically, results show that breaking and entering is relatively more frequent in central neighbourhoods, with high commercial activity, but less so in areas with high numbers of office jobs (Table 9).

p. 26:

Uttering threats, major assault and drug offences showed the closest association with access to socio-economic resources. Other strong links were noted for mischief, motor vehicle theft, robbery, sexual assault and common assault. Only other thefts (which exclude shoplifting, theft from a motor vehicle and motor vehicle theft) and breaking and entering were not significantly associated with access to socio-economic resources. Economic vulnerability was associated with generally serious violent crimes: robbery, major assault, sexual assault and uttering threats. It was not related to common assault, harassment or any type of property crime.

City of Toronto Neighbourhood Profiles

Neighbourhoods are aggregated from census tracts.

neighbourhoods_dt <- fread("neighbourhood-profiles-2016-csv.csv")

neighbourhoods_dt <- neighbourhoods_dt[, -c("_id", "Category", "Topic", "Data Source", "City of Toronto")]

Select census variables.

v <- c("Neighbourhood Number",
       "Population, 2016",
       "Land area in square kilometres",
       "Children (0-14 years)",
       "Seniors (65+ years)",
       "Private households by household size",
       "Average household size",
       "In low income based on the Low-income cut-offs, after tax (LICO-AT)",
       "Prevalence of low income based on the Low-income cut-offs, after tax (LICO-AT) (%)",
       "Renter",
       "Spending 30% or more of income on shelter costs",
       "University certificate, diploma or degree at bachelor level or above",
       "Unemployed (Males)",
       "Unemployment rate (Males)",
       "Public transit",
       "Walked",
       "Employment income: Average amount ($)",
       "Social assistance benefits: Population with an amount")

Assuring myself that “Renter” only occurs once, and therefore is not counted both for households and persons but only for households.

length(grep("Renter", neighbourhoods_dt$Characteristic))
[1] 1
neighbourhoods_v <-
neighbourhoods_dt[Characteristic %in% v,]

neighbourhoods_v <- transpose(neighbourhoods_v)

head(neighbourhoods_v)

Land area is in square kilometers. Children are children 0 to 14. Households_unaffordable is the number of households spending 30% or more of income on shelter costs: see Canada Mortgage and Housing Corporation, About Affordable Housing in Canada.

neighbourhoods_census <- neighbourhoods_v[!1,.(id=V1, Population=V2, Land_area=V3, Children=V4,
                                              Seniors=V5, Households=V6, Average_household_size=V7,
                                              LICO=V8, LICO_prevalence=V9, Renters=V10,
                                              Households_unaffordable=V11,
                                              Unemployed_males=V12, Unemployment_rate_males=V13,
                                              Public_transit_to_work=V14, Walk_to_work=V15,
                                              Average_employment_income=V16,
                                              Social_assistance_recipients=V17)]

head(neighbourhoods_census) 
neighbourhoods_census$id <- as.integer(neighbourhoods_census$id)

neighbourhoods_census$Population <- as.integer(gsub(",", "", neighbourhoods_census$Population))

neighbourhoods_census$Land_area <- as.numeric(neighbourhoods_census$Land_area)

neighbourhoods_census$Children <- as.integer(gsub(",", "", neighbourhoods_census$Children))

neighbourhoods_census$Seniors <- as.integer(gsub(",", "", neighbourhoods_census$Seniors))

neighbourhoods_census$Households <- as.integer(neighbourhoods_census$Households)

neighbourhoods_census$Average_household_size <- as.numeric(neighbourhoods_census$Average_household_size)

neighbourhoods_census$LICO <- as.integer(gsub(",", "", neighbourhoods_census$LICO))

neighbourhoods_census$LICO_prevalence <- as.numeric(neighbourhoods_census$LICO_prevalence)

neighbourhoods_census$Renters <- as.integer(gsub(",", "", neighbourhoods_census$Renters))

neighbourhoods_census$Households_unaffordable <- as.integer(gsub(",", "", neighbourhoods_census$Households_unaffordable))

neighbourhoods_census$Unemployed_males <- as.integer(gsub(",", "", neighbourhoods_census$Unemployed_males))

neighbourhoods_census$Unemployment_rate_males <- as.numeric(neighbourhoods_census$Unemployment_rate_males)

neighbourhoods_census$Public_transit_to_work <- as.integer(gsub(",", "", neighbourhoods_census$Public_transit_to_work))

neighbourhoods_census$Walk_to_work <- as.integer(gsub(",", "", neighbourhoods_census$Walk_to_work))

neighbourhoods_census$Average_employment_income <- as.numeric(gsub(",", "", neighbourhoods_census$Average_employment_income))

neighbourhoods_census$Social_assistance_recipients <- as.integer(gsub(",", "", neighbourhoods_census$Social_assistance_recipients))

neighbourhoods_census <- neighbourhoods_census[order(id)]

str(neighbourhoods_census)
Classes ‘data.table’ and 'data.frame':  140 obs. of  17 variables:
 $ id                          : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Population                  : int  33312 32954 10360 10529 9456 22000 22156 10948 15535 11051 ...
 $ Land_area                   : num  29.81 4.52 3.31 2.49 2.86 ...
 $ Children                    : int  5060 7090 1730 1640 1805 4240 3555 1450 2120 1770 ...
 $ Seniors                     : int  4980 3560 1880 1730 1275 3585 4905 3045 3290 2025 ...
 $ Households                  : int  10280 9880 3280 3845 3220 7785 8510 4135 6260 3865 ...
 $ Average_household_size      : num  3.2 3.32 3.09 2.69 2.93 2.82 2.6 2.45 2.43 2.86 ...
 $ LICO                        : int  4550 7140 1485 1640 1695 4340 2470 1090 1250 660 ...
 $ LICO_prevalence             : num  13.8 21.8 14.7 15.8 17.9 19.7 11.2 10.8 8.2 6 ...
 $ Renters                     : int  3275 5455 1245 1685 1470 3735 3925 1620 2745 595 ...
 $ Households_unaffordable     : int  3270 3715 1065 1185 1080 2730 2645 1325 1900 750 ...
 $ Unemployed_males            : int  870 890 260 290 245 475 440 215 250 205 ...
 $ Unemployment_rate_males     : num  9.2 11.4 9.8 10.4 10.5 8.8 7.8 8.4 5.7 6.7 ...
 $ Public_transit_to_work      : int  4380 4110 1030 1345 1330 2665 2380 1200 2010 950 ...
 $ Walk_to_work                : int  425 385 110 150 70 270 140 65 175 75 ...
 $ Average_employment_income   : num  33340 28126 34385 35988 33188 ...
 $ Social_assistance_recipients: int  1290 2915 650 720 705 1710 840 410 370 145 ...
 - attr(*, ".internal.selfref")=<externalptr> 

Data manipulation

MCI

MCI_2018 <- MCI_dt[reportedyear==2018]

MCI_2018_nbd <- MCI_2018[, c("MCI", "Hood_ID")]

str(MCI_2018_nbd)
Classes ‘data.table’ and 'data.frame':  36303 obs. of  2 variables:
 $ MCI    : chr  "Assault" "Robbery" "Break and Enter" "Break and Enter" ...
 $ Hood_ID: int  75 86 132 121 121 1 122 77 86 31 ...
 - attr(*, ".internal.selfref")=<externalptr> 

The MCI dataset classifies reports as Assault, Auto Theft, Break and Enter, Robbery, and Theft Over.

MCI_2018_grouped <- MCI_2018_nbd[,.(Number_of_reports=.N),by=.(id=Hood_ID, category=MCI)]

MCI_2018_grouped <- MCI_2018_grouped[order(id)]
Assault_MCI <- MCI_2018_grouped[category=="Assault", .(Assault_reports=sum(Number_of_reports)), by=.(id)]

Auto_theft_MCI <- MCI_2018_grouped[category=="Auto Theft", .(Auto_theft_reports=sum(Number_of_reports)), by=.(id)]

BE_MCI <- MCI_2018_grouped[category=="Break and Enter", .(BE_reports=sum(Number_of_reports)), by=.(id)]

Robbery_MCI <- MCI_2018_grouped[category=="Robbery", .(Robbery_reports=sum(Number_of_reports)), by=.(id)]

Theft_over_MCI <- MCI_2018_grouped[category=="Theft Over", .(Theft_over_reports=sum(Number_of_reports)), by=.(id)]

Merge demographic table and MCI table

neighbourhoods_merged <- neighbourhoods_census

neighbourhoods_merged <- merge(neighbourhoods_merged, Assault_MCI, by="id", all=TRUE)

neighbourhoods_merged <- merge(neighbourhoods_merged, Robbery_MCI, by="id", all=TRUE)

neighbourhoods_merged <- merge(neighbourhoods_merged, BE_MCI, by="id", all=TRUE)

neighbourhoods_merged <- merge(neighbourhoods_merged, Theft_over_MCI, by="id", all=TRUE)

neighbourhoods_merged <- merge(neighbourhoods_merged, Auto_theft_MCI, by="id", all=TRUE)

#Robbery and Theft Over have missing values
neighbourhoods_merged[is.na(neighbourhoods_merged)] <- 0

str(neighbourhoods_merged)
Classes ‘data.table’ and 'data.frame':  140 obs. of  22 variables:
 $ id                          : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Population                  : int  33312 32954 10360 10529 9456 22000 22156 10948 15535 11051 ...
 $ Land_area                   : num  29.81 4.52 3.31 2.49 2.86 ...
 $ Children                    : int  5060 7090 1730 1640 1805 4240 3555 1450 2120 1770 ...
 $ Seniors                     : int  4980 3560 1880 1730 1275 3585 4905 3045 3290 2025 ...
 $ Households                  : int  10280 9880 3280 3845 3220 7785 8510 4135 6260 3865 ...
 $ Average_household_size      : num  3.2 3.32 3.09 2.69 2.93 2.82 2.6 2.45 2.43 2.86 ...
 $ LICO                        : int  4550 7140 1485 1640 1695 4340 2470 1090 1250 660 ...
 $ LICO_prevalence             : num  13.8 21.8 14.7 15.8 17.9 19.7 11.2 10.8 8.2 6 ...
 $ Renters                     : int  3275 5455 1245 1685 1470 3735 3925 1620 2745 595 ...
 $ Households_unaffordable     : int  3270 3715 1065 1185 1080 2730 2645 1325 1900 750 ...
 $ Unemployed_males            : int  870 890 260 290 245 475 440 215 250 205 ...
 $ Unemployment_rate_males     : num  9.2 11.4 9.8 10.4 10.5 8.8 7.8 8.4 5.7 6.7 ...
 $ Public_transit_to_work      : int  4380 4110 1030 1345 1330 2665 2380 1200 2010 950 ...
 $ Walk_to_work                : int  425 385 110 150 70 270 140 65 175 75 ...
 $ Average_employment_income   : num  33340 28126 34385 35988 33188 ...
 $ Social_assistance_recipients: int  1290 2915 650 720 705 1710 840 410 370 145 ...
 $ Assault_reports             : int  284 259 56 72 75 101 75 46 18 17 ...
 $ Robbery_reports             : num  69 73 11 25 15 18 16 6 7 2 ...
 $ BE_reports                  : int  154 28 18 28 7 40 65 31 44 22 ...
 $ Theft_over_reports          : num  50 3 2 4 1 3 4 3 5 5 ...
 $ Auto_theft_reports          : int  495 73 46 54 37 57 51 16 18 20 ...
 - attr(*, ".internal.selfref")=<externalptr> 
 - attr(*, "sorted")= chr "id"

Calculate ratios of MCI to population

neighbourhoods_merged$Assault_ratio <- neighbourhoods_merged$Assault_reports/neighbourhoods_merged$Population

neighbourhoods_merged$Auto_theft_ratio <- neighbourhoods_merged$Auto_theft_reports/neighbourhoods_merged$Population

neighbourhoods_merged$BE_ratio <- neighbourhoods_merged$BE_reports/neighbourhoods_merged$Population

neighbourhoods_merged$Robbery_ratio <- neighbourhoods_merged$Robbery_reports/neighbourhoods_merged$Population

neighbourhoods_merged$Theft_over_ratio <- neighbourhoods_merged$Theft_over_reports/neighbourhoods_merged$Population

Calculate ratios of census variables to population

toronto_avg_household_size <- neighbourhoods_merged[, mean(Average_household_size)]

toronto_avg_employment_income <- neighbourhoods_merged[, mean(Average_employment_income)]

toronto_avg_unemployment_rate_males <- neighbourhoods_merged[, mean(Unemployment_rate_males)]

toronto_avg_household_size
[1] 2.491643
toronto_avg_employment_income
[1] 55698.18
toronto_avg_unemployment_rate_males
[1] 8.108571
neighbourhoods_merged$Children_ratio <- neighbourhoods_merged$Children/neighbourhoods_merged$Population

neighbourhoods_merged$Seniors_ratio <- neighbourhoods_merged$Seniors/neighbourhoods_merged$Population

neighbourhoods_merged$Renters_ratio <- neighbourhoods_merged$Renters/neighbourhoods_merged$Households

neighbourhoods_merged$Households_unaffordable_ratio <- neighbourhoods_merged$Households_unaffordable/neighbourhoods_merged$Households

neighbourhoods_merged$Public_transit_to_work_ratio <- neighbourhoods_merged$Public_transit_to_work/neighbourhoods_merged$Population

neighbourhoods_merged$Social_assistance_recipients_ratio <- neighbourhoods_merged$Social_assistance_recipients/neighbourhoods_merged$Population

neighbourhoods_merged$Average_household_size_ratio <- neighbourhoods_merged$Average_household_size/toronto_avg_household_size

neighbourhoods_merged$Average_employment_income_ratio <- neighbourhoods_merged$Average_employment_income/toronto_avg_employment_income

neighbourhoods_merged$Unemployment_rate_males_ratio <- neighbourhoods_merged$Unemployment_rate_males/toronto_avg_unemployment_rate_males

Choropleths by neighbourhood

Shapefile

Neighbourhoods (WGS84). City of Toronto, Social Development, Finance & Administration

https://www.toronto.ca/city-government/data-research-maps/open-data/open-data-catalogue/#a45bd45a-ede8-730e-1abc-93105b2c439f

“neighbourhoods_planning_areas_wgs84.zip”

nbds <- readOGR("C:/Users/14165/Desktop/Shapefiles/neighbourhoods_planning_areas_wgs84", "NEIGHBORHOODS_WGS84")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\14165\Desktop\Shapefiles\neighbourhoods_planning_areas_wgs84", layer: "NEIGHBORHOODS_WGS84"
with 140 features
It has 2 fields

Add “id” column

nbds@data$id <- as.integer(nbds@data$AREA_S_CD)

Make centroids of each neighbourhood, for placing labels when plotting

nbds.centroids  <- as.data.frame(gCentroid(nbds, byid = TRUE))

Add “id” column

nbds.centroids$id <- nbds@data$id

Shapefile processing

nbds.points = fortify(nbds, region = "id")

nbds.df = join(nbds.points, nbds@data, by = "id")

Merge neighbourhood shapefile and dataframe

nbds_MCI <- merge(nbds.df, neighbourhoods_merged, by = "id")

Low income cut-off (LICO) prevalence

Make and plot choropleth

p.LICO_percent <- ggplot() +
  geom_polygon(data = nbds_MCI, 
               aes(x = long, y = lat, group = group, fill = LICO_prevalence/100), 
               color = "black", size = 0.2) + 
  coord_map() + 
  scale_fill_distiller(name="LICO prevalence", labels=percent_format(accuracy=1), palette = "RdPu", trans = "reverse", breaks = pretty_breaks(n = 10)) + 
  theme_nothing(legend = TRUE) + 
  labs(title="LICO households/total households, 2018") + 
  geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.centroids, size = 2)

p.LICO_percent + guides(fill = guide_legend(reverse = TRUE))

Assaults

Make and plot choropleth

p.assaults <- ggplot() +
  geom_polygon(data = nbds_MCI, 
               aes(x = long, y = lat, group = group, fill = Assault_reports), 
               color = "black", size = 0.2) + 
  coord_map() + 
  scale_fill_distiller(name="Assaults", palette = "YlOrRd", trans = "reverse", breaks = pretty_breaks(n = 8)) + 
  theme_nothing(legend = TRUE) + 
  labs(title="Number of assault reports in Toronto by neighbourhood, 2018") + 
  geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.centroids, size = 2)

p.assaults + guides(fill = guide_legend(reverse = TRUE))

p.assaults_ratio <- ggplot() +
  geom_polygon(data = nbds_MCI, 
               aes(x = long, y = lat, group = group, fill = Assault_ratio), 
               color = "black", size = 0.2) + 
  coord_map() + 
  scale_fill_distiller(name="Assaults/Population", palette = "Reds", trans = "reverse", breaks = pretty_breaks(n = 8)) + 
  theme_nothing(legend = TRUE) + 
  labs(title="Number of assault reports/population count in Toronto by neighbourhood, 2018") + 
  geom_text(aes(x=x,y=y, group=NULL, label=id), data = nbds.centroids, size = 2)

p.assaults_ratio + guides(fill = guide_legend(reverse = TRUE))

Density Maps of MCI Using stat_density2d

https://stats.stackexchange.com/questions/31726/scatterplot-with-contour-heat-overlay

https://gist.github.com/lmullen/8375785

https://gis.stackexchange.com/questions/165974/r-fortify-causing-polygons-to-tear

MCI_Assault_XY <- MCI_dt[MCI=="Assault",.(X,Y)]

MCI_Auto_Theft_XY <- MCI_dt[MCI=="Auto Theft",.(X,Y)]

MCI_BE_XY <- MCI_dt[MCI=="Break and Enter",.(X,Y)]

MCI_Robbery_XY <- MCI_dt[MCI=="Robbery", .(X,Y)]

MCI_Theft_Over_XY <- MCI_dt[MCI=="Theft Over", .(X,Y)]

Shapefiles

Read shapefiles

torontoBoundary_wgs84 <- readOGR("C:/Users/14165/Desktop/Shapefiles/torontoBoundary_wgs84", "citygcs_regional_mun_wgs84")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\14165\Desktop\Shapefiles\torontoBoundary_wgs84", layer: "citygcs_regional_mun_wgs84"
with 1 features
It has 3 fields
Integer64 fields read as strings:  AREA_ID OBJECTID 
TTC_subway_lines_wgs84 <- readOGR("C:/Users/14165/Desktop/Shapefiles/TTC_subway_lines_wgs84", "TTC_SUBWAY_LINES_WGS84")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\14165\Desktop\Shapefiles\TTC_subway_lines_wgs84", layer: "TTC_SUBWAY_LINES_WGS84"
with 4 features
It has 3 fields
Integer64 fields read as strings:  RID 
centreline_wgs84 <- readOGR("C:/Users/14165/Desktop/Shapefiles/centreline_wgs84", "CENTRELINE_WGS84")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\14165\Desktop\Shapefiles\centreline_wgs84", layer: "CENTRELINE_WGS84"
with 69378 features
It has 17 fields
Integer64 fields read as strings:  GEO_ID LFN_ID FNODE TNODE 

Every linear feature has feature code (FCODE) defined as follow:

201100 Highway
201101 Highway Ramp
201200 Major Arterial Road
201201 Major Arterial Road Ramp
201300 Minor Arterial Road
201301 Minor Arterial Road Ramp
201400 Collector Road
201401 Collector Road Ramp
201500 Local Road
201600 Other Road
201601 Other Ramp
201700 Laneways
201800 Pending
201803 Access Road
201801 Busway
202001 Major Railway
202002 Minor Railway
202003 Railway under construction/proposed
203001 River
203002 Creek/Tributary
204001 Trail
204002 Walkway
205001 Hydro Line
206001 Major Shoreline
206002 Minor Shoreline (Land locked)

centreline_wgs84_major <- centreline_wgs84[centreline_wgs84@data$FCODE %in% c(201100, 201200, 201300, 201400),]
torontoBoundary_wgs84.df <- fortify(torontoBoundary_wgs84)
Regions defined for each Polygons
TTC_subway_lines_wgs84.df <- fortify(TTC_subway_lines_wgs84)

centreline_wgs84_major.df <- fortify(centreline_wgs84_major)
ggplot()+geom_path(data = centreline_wgs84_major.df, aes(x = long, y = lat, group = group),
          color = 'black', size = .2)

Assault Reports in Toronto, 2014-2018

ggplot() + 
  geom_polygon(data = torontoBoundary_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'black', size = 1, fill=NA) +
  geom_path(data = TTC_subway_lines_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'red', size = 1) +
  geom_path(data = centreline_wgs84_major.df, aes(x = long, y = lat, group = group),
          color = 'black', size = .1) +
  stat_density2d(data=MCI_Assault_XY, aes(x=X, y=Y, fill=..level..), alpha=0.2, geom = 'polygon', colour = 'black', contour=TRUE) +
  scale_fill_continuous(low="yellow",high="red")+
 theme_nothing(legend = TRUE) + 
  labs(title="Assault Reports in Toronto, 2014-2018")

Auto Theft Reports in Toronto, 2014-2018

ggplot() + 
  geom_polygon(data = torontoBoundary_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'black', size = 1, fill=NA) +
  geom_path(data = TTC_subway_lines_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'red', size = 1) +
  geom_path(data = centreline_wgs84_major.df, aes(x = long, y = lat, group = group),
          color = 'black', size = .1) +
  stat_density2d(data=MCI_Auto_Theft_XY, aes(x=X, y=Y, fill=..level..), alpha=0.2, geom = 'polygon', colour = 'black', contour=TRUE) +
  scale_fill_continuous(low="yellow",high="red") +
 theme_nothing(legend = TRUE) + 
  labs(title="Auto Theft Reports in Toronto, 2014-2018")

Change bandwidth parameter h

ggplot() + 
  geom_polygon(data = torontoBoundary_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'black', size = 1, fill=NA) +
  geom_path(data = TTC_subway_lines_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'red', size = 1) +
  geom_path(data = centreline_wgs84_major.df, aes(x = long, y = lat, group = group),
          color = 'black', size = .1) +
  stat_density2d(data=MCI_Auto_Theft_XY, aes(x=X, y=Y, fill=..level..), alpha=0.2, h=0.05, n=300, geom = 'polygon', colour = 'black', contour=TRUE) +
  scale_fill_continuous(low="yellow",high="red") +
 theme_nothing(legend = TRUE) + 
  labs(title="Auto Theft Reports in Toronto, 2014-2018. h=0.05")

Break and Enter Reports in Toronto, 2014-2018

ggplot() + 
  geom_polygon(data = torontoBoundary_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'black', size = 1, fill=NA) +
  geom_path(data = TTC_subway_lines_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'red', size = 1) +
  geom_path(data = centreline_wgs84_major.df, aes(x = long, y = lat, group = group),
          color = 'black', size = .1) +
  stat_density2d(data=MCI_BE_XY, aes(x=X, y=Y, fill=..level..), alpha=0.2, geom = 'polygon', colour = 'black', contour=TRUE) +
  scale_fill_continuous(low="yellow",high="red") +
 theme_nothing(legend = TRUE) + 
  labs(title="Break and Enter Reports in Toronto, 2014-2018")

Robbery Reports in Toronto, 2014-2018

ggplot() + 
  geom_polygon(data = torontoBoundary_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'black', size = 1, fill=NA) +
  geom_path(data = TTC_subway_lines_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'red', size = 1) +
  geom_path(data = centreline_wgs84_major.df, aes(x = long, y = lat, group = group),
          color = 'black', size = .1) +
  stat_density2d(data=MCI_Robbery_XY, aes(x=X, y=Y, fill=..level..), alpha=0.2, geom = 'polygon', colour = 'black', contour=TRUE) +
  scale_fill_continuous(low="yellow",high="red") +
 theme_nothing(legend = TRUE) + 
  labs(title="Robbery Reports in Toronto, 2014-2018")

Theft Over $5000 Reports in Toronto, 2014-2018

ggplot() + 
  geom_polygon(data = torontoBoundary_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'black', size = 1, fill=NA) +
  geom_path(data = TTC_subway_lines_wgs84.df, aes(x = long, y = lat, group = group),
          color = 'red', size = 1) +
  geom_path(data = centreline_wgs84_major.df, aes(x = long, y = lat, group = group),
          color = 'black', size = .1) +
  stat_density2d(data=MCI_Theft_Over_XY, aes(x=X, y=Y, fill=..level..), alpha=0.2, geom = 'polygon', colour = 'black', contour=TRUE) +
  scale_fill_continuous(low="yellow",high="red") +
 theme_nothing(legend = TRUE) + 
  labs(title="Theft Over $5000 Reports in Toronto, 2014-2018")

Correlations Between MCI and Demographics

str(neighbourhoods_merged)
Classes ‘data.table’ and 'data.frame':  140 obs. of  36 variables:
 $ id                                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Population                        : int  33312 32954 10360 10529 9456 22000 22156 10948 15535 11051 ...
 $ Land_area                         : num  29.81 4.52 3.31 2.49 2.86 ...
 $ Children                          : int  5060 7090 1730 1640 1805 4240 3555 1450 2120 1770 ...
 $ Seniors                           : int  4980 3560 1880 1730 1275 3585 4905 3045 3290 2025 ...
 $ Households                        : int  10280 9880 3280 3845 3220 7785 8510 4135 6260 3865 ...
 $ Average_household_size            : num  3.2 3.32 3.09 2.69 2.93 2.82 2.6 2.45 2.43 2.86 ...
 $ LICO                              : int  4550 7140 1485 1640 1695 4340 2470 1090 1250 660 ...
 $ LICO_prevalence                   : num  13.8 21.8 14.7 15.8 17.9 19.7 11.2 10.8 8.2 6 ...
 $ Renters                           : int  3275 5455 1245 1685 1470 3735 3925 1620 2745 595 ...
 $ Households_unaffordable           : int  3270 3715 1065 1185 1080 2730 2645 1325 1900 750 ...
 $ Unemployed_males                  : int  870 890 260 290 245 475 440 215 250 205 ...
 $ Unemployment_rate_males           : num  9.2 11.4 9.8 10.4 10.5 8.8 7.8 8.4 5.7 6.7 ...
 $ Public_transit_to_work            : int  4380 4110 1030 1345 1330 2665 2380 1200 2010 950 ...
 $ Walk_to_work                      : int  425 385 110 150 70 270 140 65 175 75 ...
 $ Average_employment_income         : num  33340 28126 34385 35988 33188 ...
 $ Social_assistance_recipients      : int  1290 2915 650 720 705 1710 840 410 370 145 ...
 $ Assault_reports                   : int  284 259 56 72 75 101 75 46 18 17 ...
 $ Robbery_reports                   : num  69 73 11 25 15 18 16 6 7 2 ...
 $ BE_reports                        : int  154 28 18 28 7 40 65 31 44 22 ...
 $ Theft_over_reports                : num  50 3 2 4 1 3 4 3 5 5 ...
 $ Auto_theft_reports                : int  495 73 46 54 37 57 51 16 18 20 ...
 $ Assault_ratio                     : num  0.00853 0.00786 0.00541 0.00684 0.00793 ...
 $ Auto_theft_ratio                  : num  0.01486 0.00222 0.00444 0.00513 0.00391 ...
 $ BE_ratio                          : num  0.00462 0.00085 0.00174 0.00266 0.00074 ...
 $ Robbery_ratio                     : num  0.00207 0.00222 0.00106 0.00237 0.00159 ...
 $ Theft_over_ratio                  : num  0.001501 0.000091 0.000193 0.00038 0.000106 ...
 $ Children_ratio                    : num  0.152 0.215 0.167 0.156 0.191 ...
 $ Seniors_ratio                     : num  0.149 0.108 0.181 0.164 0.135 ...
 $ Renters_ratio                     : num  0.319 0.552 0.38 0.438 0.457 ...
 $ Households_unaffordable_ratio     : num  0.318 0.376 0.325 0.308 0.335 ...
 $ Public_transit_to_work_ratio      : num  0.1315 0.1247 0.0994 0.1277 0.1407 ...
 $ Social_assistance_recipients_ratio: num  0.0387 0.0885 0.0627 0.0684 0.0746 ...
 $ Average_household_size_ratio      : num  1.28 1.33 1.24 1.08 1.18 ...
 $ Average_employment_income_ratio   : num  0.599 0.505 0.617 0.646 0.596 ...
 $ Unemployment_rate_males_ratio     : num  1.13 1.41 1.21 1.28 1.29 ...
 - attr(*, ".internal.selfref")=<externalptr> 
 - attr(*, "sorted")= chr "id"
neighbourhoods_ratios <-
  neighbourhoods_merged[, c("Assault_ratio",
                            "Auto_theft_ratio",
                            "BE_ratio",
                            "Robbery_ratio",
                            "Theft_over_ratio",
                            "Average_household_size",
                            "LICO_prevalence",
                            "Children_ratio",
                            "Seniors_ratio",
                            "Renters_ratio",
                            "Public_transit_to_work_ratio",
                            "Social_assistance_recipients_ratio",
                            "Average_household_size_ratio",
                            "Average_employment_income_ratio",
                            "Unemployment_rate_males_ratio")]

Compute correlations; there are only weak correlations between the MCI and demographic ratios I have selected.

cor(as.matrix(neighbourhoods_ratios))
                                   Assault_ratio Auto_theft_ratio     BE_ratio Robbery_ratio
Assault_ratio                          1.0000000      0.123934572  0.644161811     0.8466125
Auto_theft_ratio                       0.1239346      1.000000000  0.177476235     0.2621782
BE_ratio                               0.6441618      0.177476235  1.000000000     0.5913394
Robbery_ratio                          0.8466125      0.262178218  0.591339393     1.0000000
Theft_over_ratio                       0.6465254      0.356012795  0.692406847     0.5872684
Average_household_size                -0.3220854      0.337037837 -0.318775580    -0.2446828
LICO_prevalence                        0.5444735     -0.115264927  0.273804880     0.4082138
Children_ratio                        -0.3295457      0.127253992 -0.454609155    -0.2649427
Seniors_ratio                         -0.3511057      0.028090974 -0.050108996    -0.2796248
Renters_ratio                          0.3868284     -0.194433863  0.179501393     0.2721201
Public_transit_to_work_ratio           0.1356827     -0.260180807 -0.026893672     0.1262704
Social_assistance_recipients_ratio     0.4263891      0.003831698  0.002276327     0.3276343
Average_household_size_ratio          -0.3220854      0.337037837 -0.318775580    -0.2446828
Average_employment_income_ratio       -0.1899689     -0.095820295  0.158920915    -0.1389625
Unemployment_rate_males_ratio          0.1713490      0.118402893 -0.067685554     0.1195029
                                   Theft_over_ratio Average_household_size LICO_prevalence
Assault_ratio                            0.64652538            -0.32208540       0.5444735
Auto_theft_ratio                         0.35601280             0.33703784      -0.1152649
BE_ratio                                 0.69240685            -0.31877558       0.2738049
Robbery_ratio                            0.58726840            -0.24468277       0.4082138
Theft_over_ratio                         1.00000000            -0.25953552       0.2641209
Average_household_size                  -0.25953552             1.00000000      -0.1531719
LICO_prevalence                          0.26412090            -0.15317188       1.0000000
Children_ratio                          -0.42530132             0.62537285      -0.1074141
Seniors_ratio                           -0.12776436             0.20648236      -0.3889159
Renters_ratio                            0.13890737            -0.55429267       0.6618480
Public_transit_to_work_ratio            -0.01837898            -0.55228205       0.2120016
Social_assistance_recipients_ratio      -0.01122991             0.05802879       0.6612614
Average_household_size_ratio            -0.25953552             1.00000000      -0.1531719
Average_employment_income_ratio          0.03930987            -0.24239320      -0.4525759
Unemployment_rate_males_ratio           -0.05914277             0.46818268       0.5901170
                                   Children_ratio Seniors_ratio Renters_ratio
Assault_ratio                         -0.32954565   -0.35110573     0.3868284
Auto_theft_ratio                       0.12725399    0.02809097    -0.1944339
BE_ratio                              -0.45460916   -0.05010900     0.1795014
Robbery_ratio                         -0.26494269   -0.27962482     0.2721201
Theft_over_ratio                      -0.42530132   -0.12776436     0.1389074
Average_household_size                 0.62537285    0.20648236    -0.5542927
LICO_prevalence                       -0.10741409   -0.38891587     0.6618480
Children_ratio                         1.00000000   -0.14210117    -0.1488113
Seniors_ratio                         -0.14210117    1.00000000    -0.4107354
Renters_ratio                         -0.14881132   -0.41073539     1.0000000
Public_transit_to_work_ratio          -0.18119889   -0.45232803     0.5736128
Social_assistance_recipients_ratio     0.29844040   -0.42513857     0.5328017
Average_household_size_ratio           0.62537285    0.20648236    -0.5542927
Average_employment_income_ratio       -0.06997932    0.18820202    -0.2084157
Unemployment_rate_males_ratio          0.38403635   -0.11106102     0.2099765
                                   Public_transit_to_work_ratio Social_assistance_recipients_ratio
Assault_ratio                                        0.13568268                        0.426389126
Auto_theft_ratio                                    -0.26018081                        0.003831698
BE_ratio                                            -0.02689367                        0.002276327
Robbery_ratio                                        0.12627040                        0.327634301
Theft_over_ratio                                    -0.01837898                       -0.011229909
Average_household_size                              -0.55228205                        0.058028794
LICO_prevalence                                      0.21200157                        0.661261447
Children_ratio                                      -0.18119889                        0.298440398
Seniors_ratio                                       -0.45232803                       -0.425138569
Renters_ratio                                        0.57361284                        0.532801690
Public_transit_to_work_ratio                         1.00000000                        0.189770279
Social_assistance_recipients_ratio                   0.18977028                        1.000000000
Average_household_size_ratio                        -0.55228205                        0.058028794
Average_employment_income_ratio                     -0.11905638                       -0.514634851
Unemployment_rate_males_ratio                       -0.16862450                        0.604488407
                                   Average_household_size_ratio Average_employment_income_ratio
Assault_ratio                                       -0.32208540                     -0.18996891
Auto_theft_ratio                                     0.33703784                     -0.09582029
BE_ratio                                            -0.31877558                      0.15892091
Robbery_ratio                                       -0.24468277                     -0.13896248
Theft_over_ratio                                    -0.25953552                      0.03930987
Average_household_size                               1.00000000                     -0.24239320
LICO_prevalence                                     -0.15317188                     -0.45257594
Children_ratio                                       0.62537285                     -0.06997932
Seniors_ratio                                        0.20648236                      0.18820202
Renters_ratio                                       -0.55429267                     -0.20841573
Public_transit_to_work_ratio                        -0.55228205                     -0.11905638
Social_assistance_recipients_ratio                   0.05802879                     -0.51463485
Average_household_size_ratio                         1.00000000                     -0.24239320
Average_employment_income_ratio                     -0.24239320                      1.00000000
Unemployment_rate_males_ratio                        0.46818268                     -0.43807384
                                   Unemployment_rate_males_ratio
Assault_ratio                                         0.17134895
Auto_theft_ratio                                      0.11840289
BE_ratio                                             -0.06768555
Robbery_ratio                                         0.11950289
Theft_over_ratio                                     -0.05914277
Average_household_size                                0.46818268
LICO_prevalence                                       0.59011703
Children_ratio                                        0.38403635
Seniors_ratio                                        -0.11106102
Renters_ratio                                         0.20997653
Public_transit_to_work_ratio                         -0.16862450
Social_assistance_recipients_ratio                    0.60448841
Average_household_size_ratio                          0.46818268
Average_employment_income_ratio                      -0.43807384
Unemployment_rate_males_ratio                         1.00000000

Time Series

str(MCI_dt)
Classes ‘data.table’ and 'data.frame':  167525 obs. of  29 variables:
 $ X                  : num  -79.3 -79.5 -79.5 -79.6 -79.5 ...
 $ Y                  : num  43.7 43.8 43.7 43.7 43.7 ...
 $ Index_             : int  214 215 216 217 218 219 220 221 222 223 ...
 $ event_unique_id    : chr  "GO-20141948968" "GO-20141950728" "GO-20141956416" "GO-20141956867" ...
 $ occurrencedate     : chr  "2014-04-24T11:29:00.000Z" "2014-04-24T13:00:00.000Z" "2014-04-25T13:20:00.000Z" "2014-04-24T17:00:00.000Z" ...
 $ reporteddate       : chr  "2014-04-24T12:46:00.000Z" "2014-04-24T15:58:00.000Z" "2014-04-25T13:52:00.000Z" "2014-04-25T10:30:00.000Z" ...
 $ premisetype        : chr  "Commercial" "House" "Apartment" "Outside" ...
 $ ucr_code           : int  1610 2120 1430 1430 1430 1430 1430 1420 1420 1420 ...
 $ ucr_ext            : int  200 200 100 100 100 100 100 100 100 100 ...
 $ offence            : chr  "Robbery - Mugging" "B&E" "Assault" "Assault" ...
 $ reportedyear       : int  2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 ...
 $ reportedmonth      : chr  "April" "April" "April" "April" ...
 $ reportedday        : int  24 24 25 25 25 25 3 3 3 3 ...
 $ reporteddayofyear  : int  114 114 115 115 115 115 123 123 123 123 ...
 $ reporteddayofweek  : chr  "Thursday" "Thursday" "Friday" "Friday" ...
 $ reportedhour       : int  12 15 13 10 16 22 3 4 4 4 ...
 $ occurrenceyear     : int  2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 ...
 $ occurrencemonth    : chr  "April" "April" "April" "April" ...
 $ occurrenceday      : int  24 24 25 24 25 25 3 3 3 3 ...
 $ occurrencedayofyear: int  114 114 115 114 115 115 123 123 123 123 ...
 $ occurrencedayofweek: chr  "Thursday" "Thursday" "Friday" "Thursday" ...
 $ occurrencehour     : int  11 13 13 17 16 22 1 4 4 4 ...
 $ MCI                : chr  "Robbery" "Break and Enter" "Assault" "Assault" ...
 $ Division           : chr  "D55" "D31" "D12" "D23" ...
 $ Hood_ID            : int  68 24 30 4 114 73 64 79 79 79 ...
 $ Neighbourhood      : chr  "North Riverdale (68)" "Black Creek (24)" "Brookhaven-Amesbury (30)" "Rexdale-Kipling (4)" ...
 $ Lat                : num  43.7 43.8 43.7 43.7 43.7 ...
 $ Long               : num  -79.3 -79.5 -79.5 -79.6 -79.5 ...
 $ ObjectId           : int  1 2 3 4 5 6 7 8 9 10 ...
 - attr(*, ".internal.selfref")=<externalptr> 
 - attr(*, "index")= int 
  ..- attr(*, "__reportedyear")= int  1 2 3 4 5 6 7 8 9 10 ...
  ..- attr(*, "__MCI")= int  3 4 5 6 7 8 9 10 11 12 ...
MCI_dt_dates <- MCI_dt[,.(reportedyear,reportedmonth,MCI)]

MCI_dt_dates$reportedmonth <- match(MCI_dt_dates$reportedmonth, month.name)

str(MCI_dt_dates)
Classes ‘data.table’ and 'data.frame':  167525 obs. of  3 variables:
 $ reportedyear : int  2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 ...
 $ reportedmonth: int  4 4 4 4 4 4 5 5 5 5 ...
 $ MCI          : chr  "Robbery" "Break and Enter" "Assault" "Assault" ...
 - attr(*, ".internal.selfref")=<externalptr> 

Assault Reports Time Series

Assault_dt <- MCI_dt_dates[MCI=="Assault",.N, by = .(reportedyear,reportedmonth)]

Assault_dt <- Assault_dt[order(reportedyear,reportedmonth)]

str(Assault_dt)
Classes ‘data.table’ and 'data.frame':  60 obs. of  3 variables:
 $ reportedyear : int  2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 ...
 $ reportedmonth: int  1 2 3 4 5 6 7 8 9 10 ...
 $ N            : int  1188 1162 1228 1232 1502 1556 1377 1469 1490 1409 ...
 - attr(*, ".internal.selfref")=<externalptr> 
Assault.ts <- ts(Assault_dt$N, start = 2014, frequency = 12)
autoplot(Assault.ts)

Assault.ts.components <- decompose(Assault.ts)
autoplot(Assault.ts.components)

Assault.ts.stl <- stl(Assault.ts, s.window = "periodic")
autoplot(Assault.ts.stl)

Assault.ts.arima <- auto.arima(Assault.ts)

Assault.ts.arima
Series: Assault.ts 
ARIMA(0,1,2)(1,1,0)[12] 

Coefficients:
          ma1     ma2     sar1
      -1.1118  0.3465  -0.5257
s.e.   0.1713  0.1833   0.1308

sigma^2 estimated as 5311:  log likelihood=-269.35
AIC=546.7   AICc=547.65   BIC=554.1
Assault.ts.arima.forecast <- forecast(Assault.ts.arima, level = c(95), h = 12)

autoplot(Assault.ts.arima.forecast)

Theft Over $5000 Time Series

Theft_Over_dt <- MCI_dt_dates[MCI=="Theft Over",.N, by = .(reportedyear,reportedmonth)]

Theft_Over_dt <- Theft_Over_dt[order(reportedyear,reportedmonth)]

Theft_Over.ts <- ts(Theft_Over_dt$N, start = 2014, frequency = 12)

Theft_Over.ts.components <- decompose(Theft_Over.ts)

Theft_Over.ts.stl <- stl(Theft_Over.ts, s.window = "periodic")
autoplot(Theft_Over.ts.components)

autoplot(Theft_Over.ts.stl)

Theft_Over.ts.arima <- auto.arima(Theft_Over.ts)

Theft_Over.ts.arima
Series: Theft_Over.ts 
ARIMA(1,1,1) 

Coefficients:
         ar1      ma1
      0.3119  -0.8859
s.e.  0.1429   0.0635

sigma^2 estimated as 176.4:  log likelihood=-235.79
AIC=477.58   AICc=478.02   BIC=483.81
LS0tDQp0aXRsZTogIlRvcm9udG8gUG9saWNlIFNlcnZpY2UgTWFqb3IgQ3JpbWUgSW5kaWNhdG9ycyAyMDE0IHRvIDIwMTgiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICB0b2M6IHllcw0KLS0tDQoNCiMgQXV0aG9yDQoNCiogSm9yZGFuIEJlbGwNCiogSnVseSAxMCwgMjAxOQ0KKiA8aHR0cHM6Ly9qb3JkYW5iZWxsMjM1Ny5naXRodWIuaW8vTUNJLm5iLmh0bWw+DQoNCiMgU291cmNlcyBhbmQgZGVzY3JpcHRpb25zIG9mIGRhdGFzZXRzDQoNCiMjIFRQUyBNQ0kgMjAxNCB0byAyMDE4DQoNCk1ham9yIENyaW1lIEluZGljYXRvcnMgKE1DSSkNCg0KW1Rvcm9udG8gUG9saWNlIFNlcnZpY2UgUHVibGljIFNhZmV0eSBEYXRhIFBvcnRhbF0oaHR0cDovL2RhdGEudG9yb250b3BvbGljZS5vbi5jYS8pDQoNCiJNQ0lfMjAxNF90b18yMDE4LmNzdiINCg0KPGh0dHA6Ly9kYXRhLnRvcm9udG9wb2xpY2Uub24uY2EvcGFnZXMvZ2xvc3Nhcnk+Og0KDQo+IEZvciB0aGUgbW9zdCBwYXJ0LCB0aGUgc3RhdGlzdGljcyBvbiB0aGUgZm9sbG93aW5nIHBhZ2VzIHVzZSBhbiBpbmNpZGVudC1iYXNlZCBjb3VudGluZyBtZXRob2QuIEdlbmVyYWxseSwgZWFjaCB0eXBlIG9mIG1ham9yIGNyaW1lIHRoYXQgb2NjdXJyZWQgZHVyaW5nIGFuIGluY2lkZW50IHdpbGwgYmUgY291bnRlZC4gRm9yIGV4YW1wbGUsIGlmIGFuIGFzc2F1bHQgYW5kIGEgYnJlYWsgYW5kIGVudGVyIHRvb2sgcGxhY2UgaW4gdGhlIHNhbWUgaW5jaWRlbnQsIHRoZXkgd291bGQgYmUgY291bnRlZCBvbmNlIGluIGVhY2ggY2F0ZWdvcnkuIFN0YXRpc3RpY3MgQ2FuYWRhIGFsc28gcHJlc2VudHMgaW5jaWRlbnQtYmFzZWQgY3JpbWUgc3RhdGlzdGljcywgYnV0IGdlbmVyYWxseSBjb3VudHMgb25seSB0aGUgbW9zdCBzZXJpb3VzIG9mZmVuY2UgcGVyIGluY2lkZW50LiBTb21lIG90aGVyIHBvbGljZSBzZXJ2aWNlcyBwcmVzZW50IHRoZWlyIGNyaW1lIHN0YXRpc3RpY3MgdXNpbmcgdGhlIG9mZmVuY2UtYmFzZWQgbWV0aG9kLCB3aGljaCBjb3VudHMgYWxsIG9mZmVuY2VzIGluIGVhY2ggaW5jaWRlbnQuIEl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoZXNlIGRpZmZlcmVuY2VzIHdoZW4gY29tcGFyaW5nIG91ciBjcmltZSBzdGF0aXN0aWNzIHRvIHRob3NlIHByb3ZpZGVkIGJ5IFN0YXRpc3RpY3MgQ2FuYWRhIG9yIGJ5IG90aGVyIHBvbGljZSBhZ2VuY2llcy4NCg0KPiAqKkFzc2F1bHQqKi4gVGhlIGRpcmVjdCBvciBpbmRpcmVjdCBhcHBsaWNhdGlvbiBvZiBmb3JjZSB0byBhbm90aGVyIHBlcnNvbiwgb3IgdGhlIGF0dGVtcHQgb3IgdGhyZWF0IHRvIGFwcGx5IGZvcmNlIHRvIGFub3RoZXIgcGVyc29uLCB3aXRob3V0IHRoYXQgcGVyc29u4oCZcyBjb25zZW50Lg0KPg0KPiAqKlJvYmJlcnkqKi4gVGhlIGFjdCBvZiB0YWtpbmcgcHJvcGVydHkgZnJvbSBhbm90aGVyIHBlcnNvbiBvciBidXNpbmVzcyBieSB0aGUgdXNlIG9mIGZvcmNlIG9yIGludGltaWRhdGlvbiBpbiB0aGUgcHJlc2VuY2Ugb2YgdGhlIHZpY3RpbS4NCj4NCj4gKipCcmVhayBhbmQgRW50ZXIqKi4gVGhlIGFjdCBvZiBlbnRlcmluZyBhIHBsYWNlIHdpdGggdGhlIGludGVudCB0byBjb21taXQgYW4gaW5kaWN0YWJsZSBvZmZlbmNlIHRoZXJlaW4uDQo+DQo+ICoqQXV0byBUaGVmdCoqLiBUaGUgYWN0IG9mIHRha2luZyBvciBhbm90aGVyIHBlcnNvbidzIHZlaGljbGUgKG5vdCBpbmNsdWRpbmcgYXR0ZW1wdHMpLiBBdXRvIFRoZWZ0IGZpZ3VyZXMgcmVwcmVzZW50IHRoZSBudW1iZXIgb2YgdmVoaWNsZXMgc3RvbGVuLg0KPg0KPiAqKlRoZWZ0IE92ZXIqKi4gVGhlIGFjdCBvZiBzdGVhbGluZyBwcm9wZXJ0eSBpbiBleGNlc3Mgb2YgJDUsMDAwIChleGNsdWRpbmcgYXV0byB0aGVmdCkuDQoNCg0KIyMgQ2l0eSBvZiBUb3JvbnRvIE5laWdoYm91cmhvb2QgUHJvZmlsZXMNCg0KW05laWdoYm91cmhvb2QgUHJvZmlsZXNdKGh0dHBzOi8vcG9ydGFsMC5jZi5vcGVuZGF0YS5pbnRlci5zYW5kYm94LXRvcm9udG8uY2EvZGF0YXNldC9uZWlnaGJvdXJob29kLXByb2ZpbGVzLykNCg0KPiBTdGF0aXN0aWNzIENhbmFkYSBkb2VzIG5vdCByZWxlYXNlIGRhdGEgYXQgdGhlIGxldmVsIG9mIFRvcm9udG8ncyBzb2NpYWwgcGxhbm5pbmcgbmVpZ2hib3VyaG9vZHMuIE5laWdoYm91cmhvb2QgbGV2ZWwgZGF0YSBmb3IgMjAxNiBhcmUgaW5pdGlhbGx5IGNhbGN1bGF0ZWQgYnkgc3VtbWluZyBkYXRhIGZvciB0aGUgQ2Vuc3VzIFRyYWN0cyB3aGljaCBjb21wcmlzZSBlYWNoIG5laWdoYm91cmhvb2QuDQoNCiJuZWlnaGJvdXJob29kLXByb2ZpbGVzLTIwMTYtY3N2LmNzdiINCg0KDQoNCiMgTG9hZGluZywgdW5kZXJzdGFuZGluZyBhbmQgY2xlYW5pbmcgZGF0YXNldHMNCg0KYGBge3J9DQpsaWJyYXJ5KGRhdGEudGFibGUpICNmcmVhZCwgc2V0Y29sb3JkZXIsIHJiaW5kbGlzdA0KbGlicmFyeShzcCkgI3VzZWQgYnkgcmdkYWwNCmxpYnJhcnkocmdkYWwpICNyZWFkT0dSDQpsaWJyYXJ5KGdncGxvdDIpICNmb3J0aWZ5DQpsaWJyYXJ5KHBseXIpICNqb2luDQpsaWJyYXJ5KHNjYWxlcykgI3NjYWxlX2ZpbGxfZGlzdGlsbGVyDQpsaWJyYXJ5KGdnbWFwKSAjdGhlbWVfbm90aGluZw0KbGlicmFyeShyZ2VvcykgI2dDZW50cm9pZA0KbGlicmFyeShmb3JlY2FzdCkgI2F1dG9wbG90IHRzLCBhdXRvLmFyaW1hDQpgYGANCg0KDQojIyBNQ0kgZGF0YXNldCBhbmQgZGVmaW5pdGlvbnMgb2YgVUNSIGNvZGVzDQoNCmBgYHtyfQ0KTUNJX2R0IDwtIGZyZWFkKCJNQ0lfMjAxNF90b18yMDE4LmNzdiIpDQpgYGANCg0KYGBge3J9DQpzdHIoTUNJX2R0KQ0KYGBgDQoNCmBgYHtyfQ0KdW5pcXVlKE1DSV9kdCRwcmVtaXNldHlwZSkNCg0Kc29ydCh1bmlxdWUoTUNJX2R0JHVjcl9jb2RlKSkNCg0Kc29ydCh1bmlxdWUoTUNJX2R0JEhvb2RfSUQpKQ0KDQp1bmlxdWUoTUNJX2R0JE1DSSkNCmBgYA0KDQpVbmlmb3JtIENyaW1lIFJlcG9ydGluZyBTdXJ2ZXkgKFVDUikuIFtVQ1IgSW5jaWRlbnQtQmFzZWQgU3VydmV5OiBSREMgVXNlciBNYW51YWxdKGh0dHBzOi8vZ3NnLnVvdHRhd2EuY2EvZGF0YS90ZWFjaGluZy9jcm0vcmRjX3VzZXJzX25hbnVhbF9maW5hbF8yMDEzX2ZlYl83cnZkLnBkZik6DQoNCj4qIDE0MTAgLSBBZ2dyYXZhdGVkIEFzc2F1bHQg4oCTIExldmVsIDMNCj4qIDE0MjAJLSBBc3NhdWx0IHdpdGggV2VhcG9uIG9yIENhdXNpbmcgQm9kaWx5IEhhcm0g4oCTIExldmVsIDINCj4qIDE0MzAJLSBBc3NhdWx0IOKAkyBMZXZlbCAxDQo+KiAxNDQwCS0gVW5sYXdmdWxseSBDYXVzaW5nIEJvZGlseSBIYXJtDQo+KiAxNDUwCS0gRGlzY2hhcmdlIEZpcmVhcm0gd2l0aCBJbnRlbnQNCj4qIDE0NTUgLSBVc2luZyBGaXJlYXJtL0ltaXRhdGlvbiBvZiBGaXJlYXJtIGluIGNvbW1pc3Npb24gb2Ygb2ZmZW5jZSANCj4qIDE0NTcgLSBQb2ludGluZyBhIEZpcmVhcm0NCj4qIDE0NjAgLQlBc3NhdWx0IEFnYWluc3QgUGVhY2UtUHVibGljIE9mZmljZXINCj4qIDE0NjEg4oCTIEFzc2F1bHQgYWdhaW5zdCBQZWFjZSBPZmZpY2VyIHdpdGggYSBXZWFwb24gb3IgQ2F1c2luZyBCb2RpbHkgSGFybSANCj4qIDE0NjIg4oCTIEFnZ3JhdmF0ZWQgQXNzYXVsdCBhZ2FpbnN0IFBlYWNlIE9mZmljZXINCj4qIDE0NzAgLQlDcmltaW5hbCBOZWdsaWdlbmNlIENhdXNpbmcgQm9kaWx5IEhhcm0NCj4qIDE0NzUg4oCTIFRyYXAgTGlrZWx5IFRvIG9yIENhdXNpbmcgQm9kaWx5IEhhcm0NCj4qIDE0ODAgLQlPdGhlciBBc3NhdWx0cw0KPiogMTYxMCAtIFJvYmJlcnkNCj4qIDIxMjAgLQlCcmVhayBhbmQgRW50ZXINCj4qIDIxMjEg4oCTIEJyZWFrIGFuZCBFbnRlciB0byBTdGVhbCBGaXJlYXJtIA0KPiogMjEyNSDigJMgQnJlYWsgYW5kIEVudGVyIG9mIGEgTW90b3IgVmVoaWNsZSB0byBvYnRhaW4gYSBGaXJlYXJtDQo+KiAyMTMwIOKAkyBUaGVmdCBvdmVyICQ1LDAwMA0KPiogMjEzMiDigJMgVGhlZnQgb3ZlciAkNSwwMDAgZnJvbSBhIE1vdG9yIFZlaGljbGUNCj4qIDIxMzMg4oCTIFNob3BsaWZ0aW5nIG92ZXIgJDUsMDAwIA0KPiogMjEzNSDigJMgVGhlZnQgb2YgYSBNb3RvciBWZWhpY2xlDQoNCltTdGF0aXN0aWNzIENhbmFkYV0oaHR0cHM6Ly93d3cxNTAuc3RhdGNhbi5nYy5jYS9uMS9wdWIvODUtMjI0LXgvMjAwODAwMC9kZC1lbmcuaHRtKToNCg0KPkFzc2F1bHQgcmVmZXJzIHRvIHRocmVlIGxldmVscyBvZiBwaHlzaWNhbCBhc3NhdWx0cyB3aGljaCBpbmNsdWRlIHRoZSBmb2xsb3dpbmcgY2F0ZWdvcmllczoNCj4NCj5Db21tb24gYXNzYXVsdCwgKHNlY3Rpb24gMjY1KS4gVGhpcyBpbmNsdWRlcyB0aGUgQ3JpbWluYWwgQ29kZSBjYXRlZ29yeSBhc3NhdWx0IChsZXZlbCAxKS4gVGhpcyBpcyB0aGUgbGVhc3Qgc2VyaW91cyBmb3JtIG9mIGFzc2F1bHQgYW5kIGluY2x1ZGVzIHB1c2hpbmcsIHNsYXBwaW5nLCBwdW5jaGluZywgYW5kIGZhY2UtdG8tZmFjZSB2ZXJiYWwgdGhyZWF0cy4NCj4NCj5NYWpvciBhc3NhdWx0IGxldmVscyAyIGFuZCAzLCAoc2VjdGlvbnMgMjY3LCAyNjgpLiBUaGlzIGluY2x1ZGVzIG1vcmUgc2VyaW91cyBmb3JtcyBvZiBhc3NhdWx0LCBpLmUuIGFzc2F1bHQgd2l0aCBhIHdlYXBvbiBvciBjYXVzaW5nIGJvZGlseSBoYXJtIChsZXZlbCAyKSBhbmQgYWdncmF2YXRlZCBhc3NhdWx0IChsZXZlbCAzKS4gQXNzYXVsdCBsZXZlbCAyIGludm9sdmVzIGNhcnJ5aW5nLCB1c2luZyBvciB0aHJlYXRlbmluZyB0byB1c2UgYSB3ZWFwb24gYWdhaW5zdCBzb21lb25lIG9yIGNhdXNpbmcgc29tZW9uZSBib2RpbHkgaGFybS4gQXNzYXVsdCBsZXZlbCAzIGludm9sdmVzIHdvdW5kaW5nLCBtYWltaW5nLCBkaXNmaWd1cmluZyBvciBlbmRhbmdlcmluZyB0aGUgbGlmZSBvZiBzb21lb25lLg0KDQpbQ3JpbWluYWwgQ29kZSAoUi5TLkMuLCAxOTg1LCBjLiBDLTQ2KV0oaHR0cHM6Ly9sYXdzLWxvaXMuanVzdGljZS5nYy5jYS9QREYvQy00Ni5wZGYpDQoNCj4gKipib2RpbHkgaGFybSoqIG1lYW5zIGFueSBodXJ0IG9yIGluanVyeSB0byBhIHBlcnNvbiB0aGF0DQppbnRlcmZlcmVzIHdpdGggdGhlIGhlYWx0aCBvciBjb21mb3J0IG9mIHRoZSBwZXJzb24gYW5kDQp0aGF0IGlzIG1vcmUgdGhhbiBtZXJlbHkgdHJhbnNpZW50IG9yIHRyaWZsaW5nIGluIG5hdHVyZTsgKCpsw6lzaW9ucyBjb3Jwb3JlbGxlcyopDQoNCj4gKipDcmltaW5hbCBuZWdsaWdlbmNlKiogIA0KPiAyMTkgKDEpIEV2ZXJ5IG9uZSBpcyBjcmltaW5hbGx5IG5lZ2xpZ2VudCB3aG8gIA0KPiAoYSkgaW4gZG9pbmcgYW55dGhpbmcsIG9yICANCj4gKGIpIGluIG9taXR0aW5nIHRvIGRvIGFueXRoaW5nIHRoYXQgaXQgaXMgaGlzIGR1dHkgdG8gZG8sICANCj4gc2hvd3Mgd2FudG9uIG9yIHJlY2tsZXNzIGRpc3JlZ2FyZCBmb3IgdGhlIGxpdmVzIG9yIHNhZmV0eSAgDQo+IG9mIG90aGVyIHBlcnNvbnMuDQoNCj4gKipBc3NhdWx0KiogIA0KPiAyNjUgKDEpIEEgcGVyc29uIGNvbW1pdHMgYW4gYXNzYXVsdCB3aGVuICANCj4gKGEpIHdpdGhvdXQgdGhlIGNvbnNlbnQgb2YgYW5vdGhlciBwZXJzb24sIGhlIGFwcGxpZXMNCmZvcmNlIGludGVudGlvbmFsbHkgdG8gdGhhdCBvdGhlciBwZXJzb24sIGRpcmVjdGx5IG9yIGluZGlyZWN0bHk7ICANCj4gKGIpIGhlIGF0dGVtcHRzIG9yIHRocmVhdGVucywgYnkgYW4gYWN0IG9yIGEgZ2VzdHVyZSwgdG8NCmFwcGx5IGZvcmNlIHRvIGFub3RoZXIgcGVyc29uLCBpZiBoZSBoYXMsIG9yIGNhdXNlcyB0aGF0DQpvdGhlciBwZXJzb24gdG8gYmVsaWV2ZSBvbiByZWFzb25hYmxlIGdyb3VuZHMgdGhhdCBoZQ0KaGFzLCBwcmVzZW50IGFiaWxpdHkgdG8gZWZmZWN0IGhpcyBwdXJwb3NlOyBvciAgDQo+IChjKSB3aGlsZSBvcGVubHkgd2VhcmluZyBvciBjYXJyeWluZyBhIHdlYXBvbiBvciBhbg0KaW1pdGF0aW9uIHRoZXJlb2YsIGhlIGFjY29zdHMgb3IgaW1wZWRlcyBhbm90aGVyIHBlcnNvbiBvciBiZWdzLg0KDQo+ICoqQnJlYWtpbmcgYW5kIGVudGVyaW5nIHdpdGggaW50ZW50LCBjb21taXR0aW5nIG9mZmVuY2Ugb3IgYnJlYWtpbmcgb3V0KiogIA0KPiAzNDggKDEpIEV2ZXJ5IG9uZSB3aG8gIA0KPiAoYSkgYnJlYWtzIGFuZCBlbnRlcnMgYSBwbGFjZSB3aXRoIGludGVudCB0byBjb21taXQgYW4gaW5kaWN0YWJsZSBvZmZlbmNlIHRoZXJlaW4sICANCj4gKGIpIGJyZWFrcyBhbmQgZW50ZXJzIGEgcGxhY2UgYW5kIGNvbW1pdHMgYW4gaW5kaWN0YWJsZSBvZmZlbmNlIHRoZXJlaW4sIG9yICANCj4gKGMpIGJyZWFrcyBvdXQgb2YgYSBwbGFjZSBhZnRlciAgDQo+IChpKSBjb21taXR0aW5nIGFuIGluZGljdGFibGUgb2ZmZW5jZSB0aGVyZWluLCBvciAgDQo+IChpaSkgZW50ZXJpbmcgdGhlIHBsYWNlIHdpdGggaW50ZW50IHRvIGNvbW1pdCBhbiBpbmRpY3RhYmxlIG9mZmVuY2UgdGhlcmVpbiwNCmlzIGd1aWx0eQ0KPiAoZCkgaWYgdGhlIG9mZmVuY2UgaXMgY29tbWl0dGVkIGluIHJlbGF0aW9uIHRvIGENCmR3ZWxsaW5nLWhvdXNlLCBvZiBhbiBpbmRpY3RhYmxlIG9mZmVuY2UgYW5kIGxpYWJsZSB0bw0KaW1wcmlzb25tZW50IGZvciBsaWZlLCBhbmQgIA0KPiAoZSkgaWYgdGhlIG9mZmVuY2UgaXMgY29tbWl0dGVkIGluIHJlbGF0aW9uIHRvIGEgcGxhY2UNCm90aGVyIHRoYW4gYSBkd2VsbGluZy1ob3VzZSwgb2YgYW4gaW5kaWN0YWJsZSBvZmZlbmNlDQphbmQgbGlhYmxlIHRvIGltcHJpc29ubWVudCBmb3IgYSB0ZXJtIG5vdCBleGNlZWRpbmcNCnRlbiB5ZWFycyBvciBvZiBhbiBvZmZlbmNlIHB1bmlzaGFibGUgb24gc3VtbWFyeQ0KY29udmljdGlvbi4NCg0KPiAqKlJvYmJlcnkqKiAgDQo+IDM0MyBFdmVyeSBvbmUgY29tbWl0cyByb2JiZXJ5IHdobyAgDQo+IChhKSBzdGVhbHMsIGFuZCBmb3IgdGhlIHB1cnBvc2Ugb2YgZXh0b3J0aW5nIHdoYXRldmVyIGlzDQpzdG9sZW4gb3IgdG8gcHJldmVudCBvciBvdmVyY29tZSByZXNpc3RhbmNlIHRvIHRoZQ0Kc3RlYWxpbmcsIHVzZXMgdmlvbGVuY2Ugb3IgdGhyZWF0cyBvZiB2aW9sZW5jZSB0byBhIHBlcnNvbiBvciBwcm9wZXJ0eTsgIA0KPiAoYikgc3RlYWxzIGZyb20gYW55IHBlcnNvbiBhbmQsIGF0IHRoZSB0aW1lIGhlIHN0ZWFscyBvcg0KaW1tZWRpYXRlbHkgYmVmb3JlIG9yIGltbWVkaWF0ZWx5IHRoZXJlYWZ0ZXIsDQp3b3VuZHMsIGJlYXRzLCBzdHJpa2VzIG9yIHVzZXMgYW55IHBlcnNvbmFsIHZpb2xlbmNlIHRvDQp0aGF0IHBlcnNvbjsgIA0KPiAoYykgYXNzYXVsdHMgYW55IHBlcnNvbiB3aXRoIGludGVudCB0byBzdGVhbCBmcm9tIGhpbTsgb3IgIA0KPiAoZCkgc3RlYWxzIGZyb20gYW55IHBlcnNvbiB3aGlsZSBhcm1lZCB3aXRoIGFuIG9mZmVuc2l2ZSB3ZWFwb24gb3IgaW1pdGF0aW9uIHRoZXJlb2YuDQoNCg0KW0JyZWFraW5nIGFuZCBFbnRlcmluZyBpbiBDYW5hZGEgLSAyMDAyXShodHRwOi8vd3d3LnB1YmxpY2F0aW9ucy5nYy5jYS9Db2xsZWN0aW9uLVIvU3RhdGNhbi84NS0wMDItWElFLzAwNTA0ODUtMDAyLVhJRS5wZGYpLCBKdXJpc3RhdCwNClN0YXRpc3RpY3MgQ2FuYWRhIOKAkyBDYXRhbG9ndWUgbm8uIDg1LTAwMi1YUEUsIFZvbC4gMjQsIG5vLiA1LCBwYWdlIDE6DQo+IEluIDIwMDIsIG92ZXIgMzEsMDAwIHBlcnNvbnMgd2VyZSBjaGFyZ2VkIHdpdGggQiZFLCB0aGUgdmFzdCBtYWpvcml0eSBvZiB3aG9tIHdlcmUgbWFsZSAoOTElKS4gRm91ciBpbiB0ZW4gcGVyc29ucw0KY2hhcmdlZCB3aXRoIEImRSB3ZXJlIHlvdXRocy4gRm9yIHByb3BlcnR5IGFuZCB2aW9sZW50IGNyaW1lcyBvdmVyYWxsLCB5b3V0aHMgcmVwcmVzZW50ZWQgMjYlIGFuZCAxNiUgb2YgcGVyc29ucw0KY2hhcmdlZCwgcmVzcGVjdGl2ZWx5Lg0KDQpNYXRoaWV1IENoYXJyb24sIFtOZWlnaGJvdXJob29kIENoYXJhY3RlcmlzdGljcw0KYW5kIHRoZSBEaXN0cmlidXRpb24gb2YNClBvbGljZS1yZXBvcnRlZCBDcmltZSBpbiB0aGUgQ2l0eQ0Kb2YgVG9yb250b10oaHR0cHM6Ly93d3cxNTAuc3RhdGNhbi5nYy5jYS9uMS9lbi9wdWIvODUtNTYxLW0vODUtNTYxLW0yMDA5MDE4LWVuZy5wZGY/c3Q9S09sc0Vhb0spLA0KQ2FuYWRpYW4gQ2VudHJlIEZvciBKdXN0aWNlIFN0YXRpc3RpY3MsIFN0YXRpc3RpY3MgQ2FuYWRhLA0KQ2F0YWxvZ3VlIG5vLiA4NS01NjEtTSwgbm8uIDE4LiAgDQpwLiAxMToNCg0KPiBDcmltZXMgcmVwb3J0ZWQgdG8gdGhlIHBvbGljZSBhcmUgbm90IHJhbmRvbWx5IGRpc3RyaWJ1dGVkIHRocm91Z2hvdXQgVG9yb250bywgYnV0IGFyZSBjb25jZW50cmF0ZWQgaW4gY2VydGFpbg0KYXJlYXMuIEFuIGV4YW1pbmF0aW9uIG9mIGxvY2FsIGNyaW1lIHJhdGVzICh0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIG51bWJlciBvZiBjcmltZXMgYW5kIHRoZSBwb3B1bGF0aW9uDQphdCBhIGxvY2FsIGxldmVsKSBzaG93cyB0aGF0IHRoZSByYXRlcyBvZiB2aW9sZW50IGNyaW1lIGFyZSBoaWdoZXIgbmVhciB0aGUgZG93bnRvd24gY29yZSBhbmQgaW4gdGhlIGVhc3QgYW5kDQpub3J0aHdlc3QgYXJlYXMgb2YgdGhlIGNpdHkgKE1hcCA1OyBTZWUgJ01hcHBpbmcgdGVjaG5pcXVlcycgaW4gdGhlIE1ldGhvZG9sb2d5IHNlY3Rpb24gZm9yIHRlY2huaWNhbCBkZXRhaWxzLiksDQp3aGljaCBjb3JyZXNwb25kIHJvdWdobHkgdG8gdGhlIG5laWdoYm91cmhvb2RzIGFsb25nIHRoZSBDYW5hZGlhbiBOYXRpb25hbCByYWlsd2F5IGFuZCB0byB0aGUgYXJlYXMgd2hlcmUNCnJlc2lkZW50cyBlYXJuIHRoZSBsb3dlc3QgaW5kaXZpZHVhbCBpbmNvbWVzIChNYXAgMykuIFRoZXJlIGFyZSBzb21lIGhvdCBzcG90cyB3aXRoaW4gdGhlc2UgYXJlYXMgdGhhdCBoYXZlDQpoaWdoZXIgcmF0ZXMuU29tZSBvZiB0aGVzZSBhcmUgRGFuZm9ydGgsIGRvd250b3duIGVhc3Qgc2lkZSBhbmQgdGhlIGludGVyc2VjdGlvbnMgb2YgTGF3cmVuY2UgYW5kIE1vcm5pbmdzaWRlLA0KSmFuZSBhbmQgRmluY2gsIGFuZCBKYW5lIGFuZCBFZ2xpbnRvbi4NCg0KcC4gMTI6ICANCg0KPiBJbiBjb250cmFzdCwgaW4gdGhlIG5vcnRoIGFyZWEgYWxvbmcgWW9uZ2UgU3RyZWV0LCB3aGVyZSByZXNpZGVudHMgZWFybiBhIGhpZ2hlciBpbmNvbWUsIHRoZSB2aW9sZW50IGNyaW1lIHJhdGUgaXMNCm11Y2ggbG93ZXIgdGhhbiBhdmVyYWdlLiBUaGUgYnVzaW5lc3MgZGlzdHJpY3TigJR0aGUgQmF5IFN0cmVldCBhcmVhIHdoZXJlIG1vc3Qgb2YgdGhlIHdvcmtlcnMgaW4gdGhlIGZpbmFuY2UNCmFuZCBpbnN1cmFuY2UgaW5kdXN0cnkgYXJlIGVtcGxveWVk4oCUaGFzIGEgdmlvbGVudCBjcmltZSByYXRlIHdlbGwgYmVsb3cgdGhlIGF2ZXJhZ2UgZm9yIHRoZSBjaXR5IG9mIFRvcm9udG8uIFRoaXMNCmRpZmZlcnMgZnJvbSBtb3N0IG9mIHRoZSBvdGhlciBDYW5hZGlhbiBjaXRpZXMgdGhhdCBoYXZlIGJlZW4gdGhlIGZvY3VzIG9mIHN0dWRpZXMsIHdoZXJlIHRoZSB2aW9sZW50IGNyaW1lIHJhdGUgaW4gdGhlDQpjZW50cmUgd2FzIGhpZ2ggKEZpdHpnZXJhbGQgZXQgYWwuIDIwMDQ7IFdhbGxhY2UgZXQgYWwuIDIwMDY7IEtpdGNoZW4gMjAwNjsgQ2hhcnJvbiAyMDA4KS4gQSBzaW1pbGFyIHNpdHVhdGlvbiB3YXMNCm5vdGVkIGluIE1vbnRyw6lhbCwgd2hlcmUgdGhlIGNyaW1lIGhvdCBzcG90cyB3ZXJlIHNwcmVhZCBvdXQgaW4gbWFueSBhcmVhcyBvZiB0aGUgY2l0eSAoU2F2b2llIGV0IGFsLiAyMDA2KS4gVGhlDQpyZXN1bHRzIHN1Z2dlc3QgdGhhdCB0aGUgY29tcGxleCBzb2NpYWwgZ2VvZ3JhcGh5IG9mIGxhcmdlIGNpdGllcyBsaWtlIFRvcm9udG8gYW5kIE1vbnRyw6lhbCBpcyByZWxhdGVkIHRvIHRoZSBzcGF0aWFsDQpvcmdhbml6YXRpb24gb2YgY3JpbWUuDQoNCnBwLiAxMi0xMzoNCg0KPiBTZXZlcmFsIG5laWdoYm91cmhvb2QgY2hhcmFjdGVyaXN0aWNzIHZhcnkgYWNjb3JkaW5nIHRvIHRoZSBsb2NhbCBwb2xpY2UtcmVwb3J0ZWQgY3JpbWUgcmF0ZS4gTmVpZ2hib3VyaG9vZHMgd2l0aCBhDQpoaWdoIHJhdGUgb2YgdmlvbGVudCBjcmltZSBhcmUgbW9yZSBkZW5zZWx5IHBvcHVsYXRlZCBhbmQgaGF2ZSBhIGhpZ2hlciBwZXJjZW50YWdlIG9mIHJlc2lkZW50cyBsaXZpbmcgaW4gbXVsdGktdW5pdA0KZHdlbGxpbmdzLlRoZXkgYWxzbyBoYXZlIHRoZSBoaWdoZXN0IHBlcmNlbnRhZ2VzIG9mIGNoaWxkcmVuICh1bmRlciB0aGUgYWdlIG9mIDE1KSwgcmVudGVycywgc2luZ2xlLXBhcmVudCBmYW1pbGllcw0KYW5kIHZpc2libGUgbWlub3JpdGllcy4gVGhlIHJlc2lkZW50cyBvZiB0aGVzZSBuZWlnaGJvdXJob29kcyBhcmUgYWxzbyBsZXNzIGxpa2VseSB0byBoYXZlIGEgdW5pdmVyc2l0eSBkZWdyZWUsIG1vcmUNCmxpa2VseSB0byBlYXJuIGEgbG93ZXIgd2FnZSwgYW5kIG1vcmUgbGlrZWx5IHRvIGxpdmUgaW4gbG93LWluY29tZSBob3VzZWhvbGRzLg0KDQpwLiAyMzoNCg0KPiBBcyBmb3IgZGVtb2dyYXBoaWMgY2hhcmFjdGVyaXN0aWNzLCByYXRlcyBvZiBoYXJhc3NtZW50IGFuZCBjb21tb24gYXNzYXVsdCBpbmNyZWFzZSB3aXRoIHRoZSBwcm9wb3J0aW9uIG9mIGNoaWxkcmVuICh1bmRlciAxNSkgYW5kIG9mIHlvdW5nIG1lbiAoYWdlZCAyMCB0byAyOSkuIFJhdGVzIG9mIHNleHVhbCBhc3NhdWx0cywgdGhyZWF0cywgbWFqb3IgYXNzYXVsdHMgYW5kIHJvYmJlcmllcw0KZGVjcmVhc2UgYXMgdGhlIHByb3BvcnRpb24gb2YgcGVvcGxlIGFnZWQgNjUgYW5kIG9sZGVyIGluY3JlYXNlcy4NCg0KcC4gMjQ6ICANCg0KPiBNb3RvciB2ZWhpY2xlIHRoZWZ0IHJhdGVzIGFyZSBoaWdoZXIgaW4gbmVpZ2hib3VyaG9vZHMgd2l0aCBoaWdoZXIgcHJvcG9ydGlvbnMgb2YgY2hpbGRyZW4gKHVuZGVyIDE1KSBhbmQgeW91bmcgbWVuDQphZ2VkIDIwIHRvIDI5LiBUaGV5IGFyZSBhbHNvIGhpZ2hlciBpbiBuZWlnaGJvdXJob29kcyB3aGVyZSBhY2Nlc3MgdG8gc29jaW8tZWNvbm9taWMgcmVzb3VyY2VzIGlzIGxpbWl0ZWQgb3INCndoZXJlIHRoZXJlIGlzIGEgc3Vid2F5IG9yIHRyYWluIHN0YXRpb24sIGFzIHdlbGwgYXMgaW4gY2x1c3RlcnMgb2YgY29tbWVyY2lhbCBhbmQgbWFudWZhY3R1cmluZyBhY3Rpdml0eS4NCg0KcC4gMjU6DQoNCj4gVGhlIHNwYXRpYWwgc3RydWN0dXJlIG9mIGJyZWFraW5nIGFuZCBlbnRlcmluZyB2YXJpZXMgZXNzZW50aWFsbHkgd2l0aCB1cmJhbiBhbmQgZWNvbm9taWMgYWN0aXZpdHkgY2hhcmFjdGVyaXN0aWNzLiBNb3JlIHNwZWNpZmljYWxseSwgcmVzdWx0cyBzaG93IHRoYXQgYnJlYWtpbmcgYW5kIGVudGVyaW5nIGlzIHJlbGF0aXZlbHkgbW9yZSBmcmVxdWVudCBpbiBjZW50cmFsIG5laWdoYm91cmhvb2RzLCB3aXRoDQpoaWdoIGNvbW1lcmNpYWwgYWN0aXZpdHksIGJ1dCBsZXNzIHNvIGluIGFyZWFzIHdpdGggaGlnaCBudW1iZXJzIG9mIG9mZmljZSBqb2JzIChUYWJsZSA5KS4NCg0KcC4gMjY6DQoNCj4gVXR0ZXJpbmcgdGhyZWF0cywgbWFqb3IgYXNzYXVsdCBhbmQgZHJ1ZyBvZmZlbmNlcyBzaG93ZWQgdGhlIGNsb3Nlc3QgYXNzb2NpYXRpb24gd2l0aCBhY2Nlc3MgdG8gc29jaW8tZWNvbm9taWMNCnJlc291cmNlcy4gT3RoZXIgc3Ryb25nIGxpbmtzIHdlcmUgbm90ZWQgZm9yIG1pc2NoaWVmLCBtb3RvciB2ZWhpY2xlIHRoZWZ0LCByb2JiZXJ5LCBzZXh1YWwgYXNzYXVsdCBhbmQgY29tbW9uDQphc3NhdWx0LiBPbmx5IG90aGVyIHRoZWZ0cyAod2hpY2ggZXhjbHVkZSBzaG9wbGlmdGluZywgdGhlZnQgZnJvbSBhIG1vdG9yIHZlaGljbGUgYW5kIG1vdG9yIHZlaGljbGUgdGhlZnQpIGFuZCBicmVha2luZw0KYW5kIGVudGVyaW5nIHdlcmUgbm90IHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGFjY2VzcyB0byBzb2Npby1lY29ub21pYyByZXNvdXJjZXMuDQpFY29ub21pYyB2dWxuZXJhYmlsaXR5IHdhcyBhc3NvY2lhdGVkIHdpdGggZ2VuZXJhbGx5IHNlcmlvdXMgdmlvbGVudCBjcmltZXM6IHJvYmJlcnksIG1ham9yIGFzc2F1bHQsIHNleHVhbCBhc3NhdWx0DQphbmQgdXR0ZXJpbmcgdGhyZWF0cy4gSXQgd2FzIG5vdCByZWxhdGVkIHRvIGNvbW1vbiBhc3NhdWx0LCBoYXJhc3NtZW50IG9yIGFueSB0eXBlIG9mIHByb3BlcnR5IGNyaW1lLg0KDQoNCiMjIENpdHkgb2YgVG9yb250byBOZWlnaGJvdXJob29kIFByb2ZpbGVzDQoNCk5laWdoYm91cmhvb2RzIGFyZSBhZ2dyZWdhdGVkIGZyb20gY2Vuc3VzIHRyYWN0cy4NCg0KYGBge3J9DQpuZWlnaGJvdXJob29kc19kdCA8LSBmcmVhZCgibmVpZ2hib3VyaG9vZC1wcm9maWxlcy0yMDE2LWNzdi5jc3YiKQ0KDQpuZWlnaGJvdXJob29kc19kdCA8LSBuZWlnaGJvdXJob29kc19kdFssIC1jKCJfaWQiLCAiQ2F0ZWdvcnkiLCAiVG9waWMiLCAiRGF0YSBTb3VyY2UiLCAiQ2l0eSBvZiBUb3JvbnRvIildDQpgYGANCg0KU2VsZWN0IGNlbnN1cyB2YXJpYWJsZXMuDQpgYGB7cn0NCnYgPC0gYygiTmVpZ2hib3VyaG9vZCBOdW1iZXIiLA0KICAgICAgICJQb3B1bGF0aW9uLCAyMDE2IiwNCiAgICAgICAiTGFuZCBhcmVhIGluIHNxdWFyZSBraWxvbWV0cmVzIiwNCiAgICAgICAiQ2hpbGRyZW4gKDAtMTQgeWVhcnMpIiwNCiAgICAgICAiU2VuaW9ycyAoNjUrIHllYXJzKSIsDQogICAgICAgIlByaXZhdGUgaG91c2Vob2xkcyBieSBob3VzZWhvbGQgc2l6ZSIsDQogICAgICAgIkF2ZXJhZ2UgaG91c2Vob2xkIHNpemUiLA0KICAgICAgICJJbiBsb3cgaW5jb21lIGJhc2VkIG9uIHRoZSBMb3ctaW5jb21lIGN1dC1vZmZzLCBhZnRlciB0YXggKExJQ08tQVQpIiwNCiAgICAgICAiUHJldmFsZW5jZSBvZiBsb3cgaW5jb21lIGJhc2VkIG9uIHRoZSBMb3ctaW5jb21lIGN1dC1vZmZzLCBhZnRlciB0YXggKExJQ08tQVQpICglKSIsDQogICAgICAgIlJlbnRlciIsDQogICAgICAgIlNwZW5kaW5nIDMwJSBvciBtb3JlIG9mIGluY29tZSBvbiBzaGVsdGVyIGNvc3RzIiwNCiAgICAgICAiVW5pdmVyc2l0eSBjZXJ0aWZpY2F0ZSwgZGlwbG9tYSBvciBkZWdyZWUgYXQgYmFjaGVsb3IgbGV2ZWwgb3IgYWJvdmUiLA0KICAgICAgICJVbmVtcGxveWVkIChNYWxlcykiLA0KICAgICAgICJVbmVtcGxveW1lbnQgcmF0ZSAoTWFsZXMpIiwNCiAgICAgICAiUHVibGljIHRyYW5zaXQiLA0KICAgICAgICJXYWxrZWQiLA0KICAgICAgICJFbXBsb3ltZW50IGluY29tZTogQXZlcmFnZSBhbW91bnQgKCQpIiwNCiAgICAgICAiU29jaWFsIGFzc2lzdGFuY2UgYmVuZWZpdHM6IFBvcHVsYXRpb24gd2l0aCBhbiBhbW91bnQiKQ0KYGBgDQoNCkFzc3VyaW5nIG15c2VsZiB0aGF0ICJSZW50ZXIiIG9ubHkgb2NjdXJzIG9uY2UsIGFuZCB0aGVyZWZvcmUgaXMgbm90IGNvdW50ZWQgYm90aCBmb3IgaG91c2Vob2xkcw0KYW5kIHBlcnNvbnMgYnV0IG9ubHkgZm9yIGhvdXNlaG9sZHMuDQoNCmBgYHtyfQ0KbGVuZ3RoKGdyZXAoIlJlbnRlciIsIG5laWdoYm91cmhvb2RzX2R0JENoYXJhY3RlcmlzdGljKSkNCmBgYA0KDQpgYGB7cn0NCm5laWdoYm91cmhvb2RzX3YgPC0NCm5laWdoYm91cmhvb2RzX2R0W0NoYXJhY3RlcmlzdGljICVpbiUgdixdDQoNCm5laWdoYm91cmhvb2RzX3YgPC0gdHJhbnNwb3NlKG5laWdoYm91cmhvb2RzX3YpDQoNCmhlYWQobmVpZ2hib3VyaG9vZHNfdikNCmBgYA0KDQpMYW5kIGFyZWEgaXMgaW4gc3F1YXJlIGtpbG9tZXRlcnMuDQpDaGlsZHJlbiBhcmUgY2hpbGRyZW4gMCB0byAxNC4NCkhvdXNlaG9sZHNfdW5hZmZvcmRhYmxlIGlzIHRoZSBudW1iZXIgb2YgaG91c2Vob2xkcyBzcGVuZGluZyAzMCUgb3IgbW9yZSBvZiBpbmNvbWUgb24gc2hlbHRlcg0KY29zdHM6IHNlZSBDYW5hZGEgTW9ydGdhZ2UgYW5kIEhvdXNpbmcgQ29ycG9yYXRpb24sIFtBYm91dCBBZmZvcmRhYmxlIEhvdXNpbmcgaW4gQ2FuYWRhXShodHRwczovL3d3dy5jbWhjLXNjaGwuZ2MuY2EvZW4vZGV2ZWxvcGluZy1hbmQtcmVub3ZhdGluZy9kZXZlbG9wLW5ldy1hZmZvcmRhYmxlLWhvdXNpbmcvcHJvZ3JhbXMtYW5kLWluZm9ybWF0aW9uL2Fib3V0LWFmZm9yZGFibGUtaG91c2luZy1pbi1jYW5hZGEpLg0KDQpgYGB7cn0NCm5laWdoYm91cmhvb2RzX2NlbnN1cyA8LSBuZWlnaGJvdXJob29kc192WyExLC4oaWQ9VjEsIFBvcHVsYXRpb249VjIsIExhbmRfYXJlYT1WMywgQ2hpbGRyZW49VjQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2VuaW9ycz1WNSwgSG91c2Vob2xkcz1WNiwgQXZlcmFnZV9ob3VzZWhvbGRfc2l6ZT1WNywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMSUNPPVY4LCBMSUNPX3ByZXZhbGVuY2U9VjksIFJlbnRlcnM9VjEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhvdXNlaG9sZHNfdW5hZmZvcmRhYmxlPVYxMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVbmVtcGxveWVkX21hbGVzPVYxMiwgVW5lbXBsb3ltZW50X3JhdGVfbWFsZXM9VjEzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFB1YmxpY190cmFuc2l0X3RvX3dvcms9VjE0LCBXYWxrX3RvX3dvcms9VjE1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF2ZXJhZ2VfZW1wbG95bWVudF9pbmNvbWU9VjE2LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNvY2lhbF9hc3Npc3RhbmNlX3JlY2lwaWVudHM9VjE3KV0NCg0KaGVhZChuZWlnaGJvdXJob29kc19jZW5zdXMpIA0KYGBgDQoNCmBgYHtyfQ0KbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJGlkIDwtIGFzLmludGVnZXIobmVpZ2hib3VyaG9vZHNfY2Vuc3VzJGlkKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkUG9wdWxhdGlvbiA8LSBhcy5pbnRlZ2VyKGdzdWIoIiwiLCAiIiwgbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJFBvcHVsYXRpb24pKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkTGFuZF9hcmVhIDwtIGFzLm51bWVyaWMobmVpZ2hib3VyaG9vZHNfY2Vuc3VzJExhbmRfYXJlYSkNCg0KbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJENoaWxkcmVuIDwtIGFzLmludGVnZXIoZ3N1YigiLCIsICIiLCBuZWlnaGJvdXJob29kc19jZW5zdXMkQ2hpbGRyZW4pKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkU2VuaW9ycyA8LSBhcy5pbnRlZ2VyKGdzdWIoIiwiLCAiIiwgbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJFNlbmlvcnMpKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkSG91c2Vob2xkcyA8LSBhcy5pbnRlZ2VyKG5laWdoYm91cmhvb2RzX2NlbnN1cyRIb3VzZWhvbGRzKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkQXZlcmFnZV9ob3VzZWhvbGRfc2l6ZSA8LSBhcy5udW1lcmljKG5laWdoYm91cmhvb2RzX2NlbnN1cyRBdmVyYWdlX2hvdXNlaG9sZF9zaXplKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkTElDTyA8LSBhcy5pbnRlZ2VyKGdzdWIoIiwiLCAiIiwgbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJExJQ08pKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkTElDT19wcmV2YWxlbmNlIDwtIGFzLm51bWVyaWMobmVpZ2hib3VyaG9vZHNfY2Vuc3VzJExJQ09fcHJldmFsZW5jZSkNCg0KbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJFJlbnRlcnMgPC0gYXMuaW50ZWdlcihnc3ViKCIsIiwgIiIsIG5laWdoYm91cmhvb2RzX2NlbnN1cyRSZW50ZXJzKSkNCg0KbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJEhvdXNlaG9sZHNfdW5hZmZvcmRhYmxlIDwtIGFzLmludGVnZXIoZ3N1YigiLCIsICIiLCBuZWlnaGJvdXJob29kc19jZW5zdXMkSG91c2Vob2xkc191bmFmZm9yZGFibGUpKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkVW5lbXBsb3llZF9tYWxlcyA8LSBhcy5pbnRlZ2VyKGdzdWIoIiwiLCAiIiwgbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJFVuZW1wbG95ZWRfbWFsZXMpKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkVW5lbXBsb3ltZW50X3JhdGVfbWFsZXMgPC0gYXMubnVtZXJpYyhuZWlnaGJvdXJob29kc19jZW5zdXMkVW5lbXBsb3ltZW50X3JhdGVfbWFsZXMpDQoNCm5laWdoYm91cmhvb2RzX2NlbnN1cyRQdWJsaWNfdHJhbnNpdF90b193b3JrIDwtIGFzLmludGVnZXIoZ3N1YigiLCIsICIiLCBuZWlnaGJvdXJob29kc19jZW5zdXMkUHVibGljX3RyYW5zaXRfdG9fd29yaykpDQoNCm5laWdoYm91cmhvb2RzX2NlbnN1cyRXYWxrX3RvX3dvcmsgPC0gYXMuaW50ZWdlcihnc3ViKCIsIiwgIiIsIG5laWdoYm91cmhvb2RzX2NlbnN1cyRXYWxrX3RvX3dvcmspKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkQXZlcmFnZV9lbXBsb3ltZW50X2luY29tZSA8LSBhcy5udW1lcmljKGdzdWIoIiwiLCAiIiwgbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJEF2ZXJhZ2VfZW1wbG95bWVudF9pbmNvbWUpKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMkU29jaWFsX2Fzc2lzdGFuY2VfcmVjaXBpZW50cyA8LSBhcy5pbnRlZ2VyKGdzdWIoIiwiLCAiIiwgbmVpZ2hib3VyaG9vZHNfY2Vuc3VzJFNvY2lhbF9hc3Npc3RhbmNlX3JlY2lwaWVudHMpKQ0KDQpuZWlnaGJvdXJob29kc19jZW5zdXMgPC0gbmVpZ2hib3VyaG9vZHNfY2Vuc3VzW29yZGVyKGlkKV0NCg0Kc3RyKG5laWdoYm91cmhvb2RzX2NlbnN1cykNCmBgYA0KDQoNCiMgRGF0YSBtYW5pcHVsYXRpb24NCg0KIyMgTUNJDQoNCmBgYHtyfQ0KTUNJXzIwMTggPC0gTUNJX2R0W3JlcG9ydGVkeWVhcj09MjAxOF0NCg0KTUNJXzIwMThfbmJkIDwtIE1DSV8yMDE4WywgYygiTUNJIiwgIkhvb2RfSUQiKV0NCg0Kc3RyKE1DSV8yMDE4X25iZCkNCmBgYA0KDQpUaGUgTUNJIGRhdGFzZXQgY2xhc3NpZmllcyByZXBvcnRzIGFzDQpBc3NhdWx0LCBBdXRvIFRoZWZ0LCBCcmVhayBhbmQgRW50ZXIsIFJvYmJlcnksIGFuZCBUaGVmdCBPdmVyLg0KDQpgYGB7cn0NCk1DSV8yMDE4X2dyb3VwZWQgPC0gTUNJXzIwMThfbmJkWywuKE51bWJlcl9vZl9yZXBvcnRzPS5OKSxieT0uKGlkPUhvb2RfSUQsIGNhdGVnb3J5PU1DSSldDQoNCk1DSV8yMDE4X2dyb3VwZWQgPC0gTUNJXzIwMThfZ3JvdXBlZFtvcmRlcihpZCldDQpgYGANCg0KYGBge3J9DQpBc3NhdWx0X01DSSA8LSBNQ0lfMjAxOF9ncm91cGVkW2NhdGVnb3J5PT0iQXNzYXVsdCIsIC4oQXNzYXVsdF9yZXBvcnRzPXN1bShOdW1iZXJfb2ZfcmVwb3J0cykpLCBieT0uKGlkKV0NCg0KQXV0b190aGVmdF9NQ0kgPC0gTUNJXzIwMThfZ3JvdXBlZFtjYXRlZ29yeT09IkF1dG8gVGhlZnQiLCAuKEF1dG9fdGhlZnRfcmVwb3J0cz1zdW0oTnVtYmVyX29mX3JlcG9ydHMpKSwgYnk9LihpZCldDQoNCkJFX01DSSA8LSBNQ0lfMjAxOF9ncm91cGVkW2NhdGVnb3J5PT0iQnJlYWsgYW5kIEVudGVyIiwgLihCRV9yZXBvcnRzPXN1bShOdW1iZXJfb2ZfcmVwb3J0cykpLCBieT0uKGlkKV0NCg0KUm9iYmVyeV9NQ0kgPC0gTUNJXzIwMThfZ3JvdXBlZFtjYXRlZ29yeT09IlJvYmJlcnkiLCAuKFJvYmJlcnlfcmVwb3J0cz1zdW0oTnVtYmVyX29mX3JlcG9ydHMpKSwgYnk9LihpZCldDQoNClRoZWZ0X292ZXJfTUNJIDwtIE1DSV8yMDE4X2dyb3VwZWRbY2F0ZWdvcnk9PSJUaGVmdCBPdmVyIiwgLihUaGVmdF9vdmVyX3JlcG9ydHM9c3VtKE51bWJlcl9vZl9yZXBvcnRzKSksIGJ5PS4oaWQpXQ0KYGBgDQoNCg0KIyMgTWVyZ2UgZGVtb2dyYXBoaWMgdGFibGUgYW5kIE1DSSB0YWJsZQ0KDQpgYGB7cn0NCm5laWdoYm91cmhvb2RzX21lcmdlZCA8LSBuZWlnaGJvdXJob29kc19jZW5zdXMNCg0KbmVpZ2hib3VyaG9vZHNfbWVyZ2VkIDwtIG1lcmdlKG5laWdoYm91cmhvb2RzX21lcmdlZCwgQXNzYXVsdF9NQ0ksIGJ5PSJpZCIsIGFsbD1UUlVFKQ0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQgPC0gbWVyZ2UobmVpZ2hib3VyaG9vZHNfbWVyZ2VkLCBSb2JiZXJ5X01DSSwgYnk9ImlkIiwgYWxsPVRSVUUpDQoNCm5laWdoYm91cmhvb2RzX21lcmdlZCA8LSBtZXJnZShuZWlnaGJvdXJob29kc19tZXJnZWQsIEJFX01DSSwgYnk9ImlkIiwgYWxsPVRSVUUpDQoNCm5laWdoYm91cmhvb2RzX21lcmdlZCA8LSBtZXJnZShuZWlnaGJvdXJob29kc19tZXJnZWQsIFRoZWZ0X292ZXJfTUNJLCBieT0iaWQiLCBhbGw9VFJVRSkNCg0KbmVpZ2hib3VyaG9vZHNfbWVyZ2VkIDwtIG1lcmdlKG5laWdoYm91cmhvb2RzX21lcmdlZCwgQXV0b190aGVmdF9NQ0ksIGJ5PSJpZCIsIGFsbD1UUlVFKQ0KDQojUm9iYmVyeSBhbmQgVGhlZnQgT3ZlciBoYXZlIG1pc3NpbmcgdmFsdWVzDQpuZWlnaGJvdXJob29kc19tZXJnZWRbaXMubmEobmVpZ2hib3VyaG9vZHNfbWVyZ2VkKV0gPC0gMA0KDQpzdHIobmVpZ2hib3VyaG9vZHNfbWVyZ2VkKQ0KYGBgDQpDYWxjdWxhdGUgcmF0aW9zIG9mIE1DSSB0byBwb3B1bGF0aW9uDQpgYGB7cn0NCm5laWdoYm91cmhvb2RzX21lcmdlZCRBc3NhdWx0X3JhdGlvIDwtIG5laWdoYm91cmhvb2RzX21lcmdlZCRBc3NhdWx0X3JlcG9ydHMvbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFBvcHVsYXRpb24NCg0KbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJEF1dG9fdGhlZnRfcmF0aW8gPC0gbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJEF1dG9fdGhlZnRfcmVwb3J0cy9uZWlnaGJvdXJob29kc19tZXJnZWQkUG9wdWxhdGlvbg0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQkQkVfcmF0aW8gPC0gbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJEJFX3JlcG9ydHMvbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFBvcHVsYXRpb24NCg0KbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFJvYmJlcnlfcmF0aW8gPC0gbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFJvYmJlcnlfcmVwb3J0cy9uZWlnaGJvdXJob29kc19tZXJnZWQkUG9wdWxhdGlvbg0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQkVGhlZnRfb3Zlcl9yYXRpbyA8LSBuZWlnaGJvdXJob29kc19tZXJnZWQkVGhlZnRfb3Zlcl9yZXBvcnRzL25laWdoYm91cmhvb2RzX21lcmdlZCRQb3B1bGF0aW9uDQpgYGANCg0KQ2FsY3VsYXRlIHJhdGlvcyBvZiBjZW5zdXMgdmFyaWFibGVzIHRvIHBvcHVsYXRpb24NCg0KYGBge3J9DQp0b3JvbnRvX2F2Z19ob3VzZWhvbGRfc2l6ZSA8LSBuZWlnaGJvdXJob29kc19tZXJnZWRbLCBtZWFuKEF2ZXJhZ2VfaG91c2Vob2xkX3NpemUpXQ0KDQp0b3JvbnRvX2F2Z19lbXBsb3ltZW50X2luY29tZSA8LSBuZWlnaGJvdXJob29kc19tZXJnZWRbLCBtZWFuKEF2ZXJhZ2VfZW1wbG95bWVudF9pbmNvbWUpXQ0KDQp0b3JvbnRvX2F2Z191bmVtcGxveW1lbnRfcmF0ZV9tYWxlcyA8LSBuZWlnaGJvdXJob29kc19tZXJnZWRbLCBtZWFuKFVuZW1wbG95bWVudF9yYXRlX21hbGVzKV0NCg0KdG9yb250b19hdmdfaG91c2Vob2xkX3NpemUNCg0KdG9yb250b19hdmdfZW1wbG95bWVudF9pbmNvbWUNCg0KdG9yb250b19hdmdfdW5lbXBsb3ltZW50X3JhdGVfbWFsZXMNCmBgYA0KDQpgYGB7cn0NCm5laWdoYm91cmhvb2RzX21lcmdlZCRDaGlsZHJlbl9yYXRpbyA8LSBuZWlnaGJvdXJob29kc19tZXJnZWQkQ2hpbGRyZW4vbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFBvcHVsYXRpb24NCg0KbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFNlbmlvcnNfcmF0aW8gPC0gbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFNlbmlvcnMvbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFBvcHVsYXRpb24NCg0KbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFJlbnRlcnNfcmF0aW8gPC0gbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFJlbnRlcnMvbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJEhvdXNlaG9sZHMNCg0KbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJEhvdXNlaG9sZHNfdW5hZmZvcmRhYmxlX3JhdGlvIDwtIG5laWdoYm91cmhvb2RzX21lcmdlZCRIb3VzZWhvbGRzX3VuYWZmb3JkYWJsZS9uZWlnaGJvdXJob29kc19tZXJnZWQkSG91c2Vob2xkcw0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQkUHVibGljX3RyYW5zaXRfdG9fd29ya19yYXRpbyA8LSBuZWlnaGJvdXJob29kc19tZXJnZWQkUHVibGljX3RyYW5zaXRfdG9fd29yay9uZWlnaGJvdXJob29kc19tZXJnZWQkUG9wdWxhdGlvbg0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQkU29jaWFsX2Fzc2lzdGFuY2VfcmVjaXBpZW50c19yYXRpbyA8LSBuZWlnaGJvdXJob29kc19tZXJnZWQkU29jaWFsX2Fzc2lzdGFuY2VfcmVjaXBpZW50cy9uZWlnaGJvdXJob29kc19tZXJnZWQkUG9wdWxhdGlvbg0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQkQXZlcmFnZV9ob3VzZWhvbGRfc2l6ZV9yYXRpbyA8LSBuZWlnaGJvdXJob29kc19tZXJnZWQkQXZlcmFnZV9ob3VzZWhvbGRfc2l6ZS90b3JvbnRvX2F2Z19ob3VzZWhvbGRfc2l6ZQ0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQkQXZlcmFnZV9lbXBsb3ltZW50X2luY29tZV9yYXRpbyA8LSBuZWlnaGJvdXJob29kc19tZXJnZWQkQXZlcmFnZV9lbXBsb3ltZW50X2luY29tZS90b3JvbnRvX2F2Z19lbXBsb3ltZW50X2luY29tZQ0KDQpuZWlnaGJvdXJob29kc19tZXJnZWQkVW5lbXBsb3ltZW50X3JhdGVfbWFsZXNfcmF0aW8gPC0gbmVpZ2hib3VyaG9vZHNfbWVyZ2VkJFVuZW1wbG95bWVudF9yYXRlX21hbGVzL3Rvcm9udG9fYXZnX3VuZW1wbG95bWVudF9yYXRlX21hbGVzDQpgYGANCg0KDQojIENob3JvcGxldGhzIGJ5IG5laWdoYm91cmhvb2QNCg0KIyMgU2hhcGVmaWxlDQoNCioqTmVpZ2hib3VyaG9vZHMgKFdHUzg0KSoqLiBDaXR5IG9mIFRvcm9udG8sIFNvY2lhbCBEZXZlbG9wbWVudCwgRmluYW5jZSAmIEFkbWluaXN0cmF0aW9uICAgDQoNCjxodHRwczovL3d3dy50b3JvbnRvLmNhL2NpdHktZ292ZXJubWVudC9kYXRhLXJlc2VhcmNoLW1hcHMvb3Blbi1kYXRhL29wZW4tZGF0YS1jYXRhbG9ndWUvI2E0NWJkNDVhLWVkZTgtNzMwZS0xYWJjLTkzMTA1YjJjNDM5Zj4gIA0KDQoibmVpZ2hib3VyaG9vZHNfcGxhbm5pbmdfYXJlYXNfd2dzODQuemlwIg0KDQpgYGB7cn0NCm5iZHMgPC0gcmVhZE9HUigiQzovVXNlcnMvMTQxNjUvRGVza3RvcC9TaGFwZWZpbGVzL25laWdoYm91cmhvb2RzX3BsYW5uaW5nX2FyZWFzX3dnczg0IiwgIk5FSUdIQk9SSE9PRFNfV0dTODQiKQ0KYGBgDQpBZGQgImlkIiBjb2x1bW4NCmBgYHtyfQ0KbmJkc0BkYXRhJGlkIDwtIGFzLmludGVnZXIobmJkc0BkYXRhJEFSRUFfU19DRCkNCmBgYA0KTWFrZSBjZW50cm9pZHMgb2YgZWFjaCBuZWlnaGJvdXJob29kLCBmb3IgcGxhY2luZyBsYWJlbHMgd2hlbiBwbG90dGluZw0KYGBge3J9DQpuYmRzLmNlbnRyb2lkcyAgPC0gYXMuZGF0YS5mcmFtZShnQ2VudHJvaWQobmJkcywgYnlpZCA9IFRSVUUpKQ0KYGBgDQpBZGQgImlkIiBjb2x1bW4NCmBgYHtyfQ0KbmJkcy5jZW50cm9pZHMkaWQgPC0gbmJkc0BkYXRhJGlkDQpgYGANClNoYXBlZmlsZSBwcm9jZXNzaW5nDQpgYGB7cn0NCm5iZHMucG9pbnRzID0gZm9ydGlmeShuYmRzLCByZWdpb24gPSAiaWQiKQ0KDQpuYmRzLmRmID0gam9pbihuYmRzLnBvaW50cywgbmJkc0BkYXRhLCBieSA9ICJpZCIpDQpgYGANCg0KIyMgTWVyZ2UgbmVpZ2hib3VyaG9vZCBzaGFwZWZpbGUgYW5kIGRhdGFmcmFtZQ0KDQpgYGB7cn0NCm5iZHNfTUNJIDwtIG1lcmdlKG5iZHMuZGYsIG5laWdoYm91cmhvb2RzX21lcmdlZCwgYnkgPSAiaWQiKQ0KYGBgDQoNCiMjIExvdyBpbmNvbWUgY3V0LW9mZiAoTElDTykgcHJldmFsZW5jZQ0KDQpNYWtlIGFuZCBwbG90IGNob3JvcGxldGgNCg0KYGBge3J9DQpwLkxJQ09fcGVyY2VudCA8LSBnZ3Bsb3QoKSArDQogIGdlb21fcG9seWdvbihkYXRhID0gbmJkc19NQ0ksIA0KICAgICAgICAgICAgICAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gTElDT19wcmV2YWxlbmNlLzEwMCksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yKSArIA0KICBjb29yZF9tYXAoKSArIA0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJMSUNPIHByZXZhbGVuY2UiLCBsYWJlbHM9cGVyY2VudF9mb3JtYXQoYWNjdXJhY3k9MSksIHBhbGV0dGUgPSAiUmRQdSIsIHRyYW5zID0gInJldmVyc2UiLCBicmVha3MgPSBwcmV0dHlfYnJlYWtzKG4gPSAxMCkpICsgDQogIHRoZW1lX25vdGhpbmcobGVnZW5kID0gVFJVRSkgKyANCiAgbGFicyh0aXRsZT0iTElDTyBob3VzZWhvbGRzL3RvdGFsIGhvdXNlaG9sZHMsIDIwMTgiKSArIA0KICBnZW9tX3RleHQoYWVzKHg9eCx5PXksIGdyb3VwPU5VTEwsIGxhYmVsPWlkKSwgZGF0YSA9IG5iZHMuY2VudHJvaWRzLCBzaXplID0gMikNCg0KcC5MSUNPX3BlcmNlbnQgKyBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSkpDQpgYGANCg0KIyMgQXNzYXVsdHMNCg0KTWFrZSBhbmQgcGxvdCBjaG9yb3BsZXRoDQpgYGB7cn0NCnAuYXNzYXVsdHMgPC0gZ2dwbG90KCkgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IG5iZHNfTUNJLCANCiAgICAgICAgICAgICAgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IEFzc2F1bHRfcmVwb3J0cyksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yKSArIA0KICBjb29yZF9tYXAoKSArIA0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJBc3NhdWx0cyIsIHBhbGV0dGUgPSAiWWxPclJkIiwgdHJhbnMgPSAicmV2ZXJzZSIsIGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDgpKSArIA0KICB0aGVtZV9ub3RoaW5nKGxlZ2VuZCA9IFRSVUUpICsgDQogIGxhYnModGl0bGU9Ik51bWJlciBvZiBhc3NhdWx0IHJlcG9ydHMgaW4gVG9yb250byBieSBuZWlnaGJvdXJob29kLCAyMDE4IikgKyANCiAgZ2VvbV90ZXh0KGFlcyh4PXgseT15LCBncm91cD1OVUxMLCBsYWJlbD1pZCksIGRhdGEgPSBuYmRzLmNlbnRyb2lkcywgc2l6ZSA9IDIpDQoNCnAuYXNzYXVsdHMgKyBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSkpDQpgYGANCg0KYGBge3J9DQpwLmFzc2F1bHRzX3JhdGlvIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBuYmRzX01DSSwgDQogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBBc3NhdWx0X3JhdGlvKSwgDQogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjIpICsgDQogIGNvb3JkX21hcCgpICsgDQogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKG5hbWU9IkFzc2F1bHRzL1BvcHVsYXRpb24iLCBwYWxldHRlID0gIlJlZHMiLCB0cmFucyA9ICJyZXZlcnNlIiwgYnJlYWtzID0gcHJldHR5X2JyZWFrcyhuID0gOCkpICsgDQogIHRoZW1lX25vdGhpbmcobGVnZW5kID0gVFJVRSkgKyANCiAgbGFicyh0aXRsZT0iTnVtYmVyIG9mIGFzc2F1bHQgcmVwb3J0cy9wb3B1bGF0aW9uIGNvdW50IGluIFRvcm9udG8gYnkgbmVpZ2hib3VyaG9vZCwgMjAxOCIpICsgDQogIGdlb21fdGV4dChhZXMoeD14LHk9eSwgZ3JvdXA9TlVMTCwgbGFiZWw9aWQpLCBkYXRhID0gbmJkcy5jZW50cm9pZHMsIHNpemUgPSAyKQ0KDQpwLmFzc2F1bHRzX3JhdGlvICsgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKQ0KYGBgDQoNCg0KDQojIERlbnNpdHkgTWFwcyBvZiBNQ0kgVXNpbmcgc3RhdF9kZW5zaXR5MmQNCg0KPGh0dHBzOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzMxNzI2L3NjYXR0ZXJwbG90LXdpdGgtY29udG91ci1oZWF0LW92ZXJsYXk+DQoNCjxodHRwczovL2dpc3QuZ2l0aHViLmNvbS9sbXVsbGVuLzgzNzU3ODU+DQoNCjxodHRwczovL2dpcy5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMTY1OTc0L3ItZm9ydGlmeS1jYXVzaW5nLXBvbHlnb25zLXRvLXRlYXI+DQoNCmBgYHtyfQ0KTUNJX0Fzc2F1bHRfWFkgPC0gTUNJX2R0W01DST09IkFzc2F1bHQiLC4oWCxZKV0NCg0KTUNJX0F1dG9fVGhlZnRfWFkgPC0gTUNJX2R0W01DST09IkF1dG8gVGhlZnQiLC4oWCxZKV0NCg0KTUNJX0JFX1hZIDwtIE1DSV9kdFtNQ0k9PSJCcmVhayBhbmQgRW50ZXIiLC4oWCxZKV0NCg0KTUNJX1JvYmJlcnlfWFkgPC0gTUNJX2R0W01DST09IlJvYmJlcnkiLCAuKFgsWSldDQoNCk1DSV9UaGVmdF9PdmVyX1hZIDwtIE1DSV9kdFtNQ0k9PSJUaGVmdCBPdmVyIiwgLihYLFkpXQ0KYGBgDQoNCiMjIFNoYXBlZmlsZXMNCg0KUmVhZCBzaGFwZWZpbGVzDQoNCmBgYHtyfQ0KdG9yb250b0JvdW5kYXJ5X3dnczg0IDwtIHJlYWRPR1IoIkM6L1VzZXJzLzE0MTY1L0Rlc2t0b3AvU2hhcGVmaWxlcy90b3JvbnRvQm91bmRhcnlfd2dzODQiLCAiY2l0eWdjc19yZWdpb25hbF9tdW5fd2dzODQiKQ0KDQpUVENfc3Vid2F5X2xpbmVzX3dnczg0IDwtIHJlYWRPR1IoIkM6L1VzZXJzLzE0MTY1L0Rlc2t0b3AvU2hhcGVmaWxlcy9UVENfc3Vid2F5X2xpbmVzX3dnczg0IiwgIlRUQ19TVUJXQVlfTElORVNfV0dTODQiKQ0KDQpjZW50cmVsaW5lX3dnczg0IDwtIHJlYWRPR1IoIkM6L1VzZXJzLzE0MTY1L0Rlc2t0b3AvU2hhcGVmaWxlcy9jZW50cmVsaW5lX3dnczg0IiwgIkNFTlRSRUxJTkVfV0dTODQiKQ0KYGBgDQoNCj4gRXZlcnkgbGluZWFyIGZlYXR1cmUgaGFzIGZlYXR1cmUgY29kZSAoRkNPREUpIGRlZmluZWQgYXMgZm9sbG93Og0KPg0KPiAyMDExMDAJSGlnaHdheSAgDQo+IDIwMTEwMQlIaWdod2F5IFJhbXAgIA0KPiAyMDEyMDAJTWFqb3IgQXJ0ZXJpYWwgUm9hZCAgDQo+IDIwMTIwMQlNYWpvciBBcnRlcmlhbCBSb2FkIFJhbXAgIA0KPiAyMDEzMDAJTWlub3IgQXJ0ZXJpYWwgUm9hZCAgDQo+IDIwMTMwMQlNaW5vciBBcnRlcmlhbCBSb2FkIFJhbXAgIA0KPiAyMDE0MDAJQ29sbGVjdG9yIFJvYWQgIA0KPiAyMDE0MDEJQ29sbGVjdG9yIFJvYWQgUmFtcCAgDQo+IDIwMTUwMAlMb2NhbCBSb2FkICANCj4gMjAxNjAwCU90aGVyIFJvYWQgIA0KPiAyMDE2MDEJT3RoZXIgUmFtcCAgDQo+IDIwMTcwMAlMYW5ld2F5cyAgDQo+IDIwMTgwMAlQZW5kaW5nICANCj4gMjAxODAzICBBY2Nlc3MgUm9hZCAgDQo+IDIwMTgwMSAgQnVzd2F5ICANCj4gMjAyMDAxCU1ham9yIFJhaWx3YXkgIA0KPiAyMDIwMDIJTWlub3IgUmFpbHdheSAgDQo+IDIwMjAwMwlSYWlsd2F5IHVuZGVyIGNvbnN0cnVjdGlvbi9wcm9wb3NlZCAgDQo+IDIwMzAwMQlSaXZlciAgDQo+IDIwMzAwMglDcmVlay9UcmlidXRhcnkgIA0KPiAyMDQwMDEJVHJhaWwgIA0KPiAyMDQwMDIJV2Fsa3dheSAgDQo+IDIwNTAwMQlIeWRybyBMaW5lICANCj4gMjA2MDAxCU1ham9yIFNob3JlbGluZSAgDQo+IDIwNjAwMglNaW5vciBTaG9yZWxpbmUgKExhbmQgbG9ja2VkKSAgDQoNCg0KYGBge3J9DQpjZW50cmVsaW5lX3dnczg0X21ham9yIDwtIGNlbnRyZWxpbmVfd2dzODRbY2VudHJlbGluZV93Z3M4NEBkYXRhJEZDT0RFICVpbiUgYygyMDExMDAsIDIwMTIwMCwgMjAxMzAwLCAyMDE0MDApLF0NCmBgYA0KDQpgYGB7cn0NCnRvcm9udG9Cb3VuZGFyeV93Z3M4NC5kZiA8LSBmb3J0aWZ5KHRvcm9udG9Cb3VuZGFyeV93Z3M4NCkNCg0KVFRDX3N1YndheV9saW5lc193Z3M4NC5kZiA8LSBmb3J0aWZ5KFRUQ19zdWJ3YXlfbGluZXNfd2dzODQpDQoNCmNlbnRyZWxpbmVfd2dzODRfbWFqb3IuZGYgPC0gZm9ydGlmeShjZW50cmVsaW5lX3dnczg0X21ham9yKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KCkrZ2VvbV9wYXRoKGRhdGEgPSBjZW50cmVsaW5lX3dnczg0X21ham9yLmRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywgc2l6ZSA9IC4yKQ0KYGBgDQoNCiMjIEFzc2F1bHQgUmVwb3J0cyBpbiBUb3JvbnRvLCAyMDE0LTIwMTgNCg0KYGBge3J9DQpnZ3Bsb3QoKSArIA0KICBnZW9tX3BvbHlnb24oZGF0YSA9IHRvcm9udG9Cb3VuZGFyeV93Z3M4NC5kZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICBjb2xvciA9ICdibGFjaycsIHNpemUgPSAxLCBmaWxsPU5BKSArDQogIGdlb21fcGF0aChkYXRhID0gVFRDX3N1YndheV9saW5lc193Z3M4NC5kZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICBjb2xvciA9ICdyZWQnLCBzaXplID0gMSkgKw0KICBnZW9tX3BhdGgoZGF0YSA9IGNlbnRyZWxpbmVfd2dzODRfbWFqb3IuZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCBzaXplID0gLjEpICsNCiAgc3RhdF9kZW5zaXR5MmQoZGF0YT1NQ0lfQXNzYXVsdF9YWSwgYWVzKHg9WCwgeT1ZLCBmaWxsPS4ubGV2ZWwuLiksIGFscGhhPTAuMiwgZ2VvbSA9ICdwb2x5Z29uJywgY29sb3VyID0gJ2JsYWNrJywgY29udG91cj1UUlVFKSArDQogIHNjYWxlX2ZpbGxfY29udGludW91cyhsb3c9InllbGxvdyIsaGlnaD0icmVkIikrDQogdGhlbWVfbm90aGluZyhsZWdlbmQgPSBUUlVFKSArIA0KICBsYWJzKHRpdGxlPSJBc3NhdWx0IFJlcG9ydHMgaW4gVG9yb250bywgMjAxNC0yMDE4IikNCmBgYA0KDQojIyBBdXRvIFRoZWZ0IFJlcG9ydHMgaW4gVG9yb250bywgMjAxNC0yMDE4DQoNCmBgYHtyfQ0KZ2dwbG90KCkgKyANCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB0b3JvbnRvQm91bmRhcnlfd2dzODQuZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCBzaXplID0gMSwgZmlsbD1OQSkgKw0KICBnZW9tX3BhdGgoZGF0YSA9IFRUQ19zdWJ3YXlfbGluZXNfd2dzODQuZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgY29sb3IgPSAncmVkJywgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wYXRoKGRhdGEgPSBjZW50cmVsaW5lX3dnczg0X21ham9yLmRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywgc2l6ZSA9IC4xKSArDQogIHN0YXRfZGVuc2l0eTJkKGRhdGE9TUNJX0F1dG9fVGhlZnRfWFksIGFlcyh4PVgsIHk9WSwgZmlsbD0uLmxldmVsLi4pLCBhbHBoYT0wLjIsIGdlb20gPSAncG9seWdvbicsIGNvbG91ciA9ICdibGFjaycsIGNvbnRvdXI9VFJVRSkgKw0KICBzY2FsZV9maWxsX2NvbnRpbnVvdXMobG93PSJ5ZWxsb3ciLGhpZ2g9InJlZCIpICsNCiB0aGVtZV9ub3RoaW5nKGxlZ2VuZCA9IFRSVUUpICsgDQogIGxhYnModGl0bGU9IkF1dG8gVGhlZnQgUmVwb3J0cyBpbiBUb3JvbnRvLCAyMDE0LTIwMTgiKQ0KYGBgDQoNCkNoYW5nZSBiYW5kd2lkdGggcGFyYW1ldGVyIGgNCg0KYGBge3J9DQpnZ3Bsb3QoKSArIA0KICBnZW9tX3BvbHlnb24oZGF0YSA9IHRvcm9udG9Cb3VuZGFyeV93Z3M4NC5kZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICBjb2xvciA9ICdibGFjaycsIHNpemUgPSAxLCBmaWxsPU5BKSArDQogIGdlb21fcGF0aChkYXRhID0gVFRDX3N1YndheV9saW5lc193Z3M4NC5kZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICBjb2xvciA9ICdyZWQnLCBzaXplID0gMSkgKw0KICBnZW9tX3BhdGgoZGF0YSA9IGNlbnRyZWxpbmVfd2dzODRfbWFqb3IuZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCBzaXplID0gLjEpICsNCiAgc3RhdF9kZW5zaXR5MmQoZGF0YT1NQ0lfQXV0b19UaGVmdF9YWSwgYWVzKHg9WCwgeT1ZLCBmaWxsPS4ubGV2ZWwuLiksIGFscGhhPTAuMiwgaD0wLjA1LCBuPTMwMCwgZ2VvbSA9ICdwb2x5Z29uJywgY29sb3VyID0gJ2JsYWNrJywgY29udG91cj1UUlVFKSArDQogIHNjYWxlX2ZpbGxfY29udGludW91cyhsb3c9InllbGxvdyIsaGlnaD0icmVkIikgKw0KIHRoZW1lX25vdGhpbmcobGVnZW5kID0gVFJVRSkgKyANCiAgbGFicyh0aXRsZT0iQXV0byBUaGVmdCBSZXBvcnRzIGluIFRvcm9udG8sIDIwMTQtMjAxOC4gaD0wLjA1IikNCmBgYA0KDQoNCiMjIEJyZWFrIGFuZCBFbnRlciBSZXBvcnRzIGluIFRvcm9udG8sIDIwMTQtMjAxOA0KDQpgYGB7cn0NCmdncGxvdCgpICsgDQogIGdlb21fcG9seWdvbihkYXRhID0gdG9yb250b0JvdW5kYXJ5X3dnczg0LmRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywgc2l6ZSA9IDEsIGZpbGw9TkEpICsNCiAgZ2VvbV9wYXRoKGRhdGEgPSBUVENfc3Vid2F5X2xpbmVzX3dnczg0LmRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgICAgICAgIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAxKSArDQogIGdlb21fcGF0aChkYXRhID0gY2VudHJlbGluZV93Z3M4NF9tYWpvci5kZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICBjb2xvciA9ICdibGFjaycsIHNpemUgPSAuMSkgKw0KICBzdGF0X2RlbnNpdHkyZChkYXRhPU1DSV9CRV9YWSwgYWVzKHg9WCwgeT1ZLCBmaWxsPS4ubGV2ZWwuLiksIGFscGhhPTAuMiwgZ2VvbSA9ICdwb2x5Z29uJywgY29sb3VyID0gJ2JsYWNrJywgY29udG91cj1UUlVFKSArDQogIHNjYWxlX2ZpbGxfY29udGludW91cyhsb3c9InllbGxvdyIsaGlnaD0icmVkIikgKw0KIHRoZW1lX25vdGhpbmcobGVnZW5kID0gVFJVRSkgKyANCiAgbGFicyh0aXRsZT0iQnJlYWsgYW5kIEVudGVyIFJlcG9ydHMgaW4gVG9yb250bywgMjAxNC0yMDE4IikNCmBgYA0KDQojIyBSb2JiZXJ5IFJlcG9ydHMgaW4gVG9yb250bywgMjAxNC0yMDE4DQoNCmBgYHtyfQ0KZ2dwbG90KCkgKyANCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB0b3JvbnRvQm91bmRhcnlfd2dzODQuZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCBzaXplID0gMSwgZmlsbD1OQSkgKw0KICBnZW9tX3BhdGgoZGF0YSA9IFRUQ19zdWJ3YXlfbGluZXNfd2dzODQuZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgY29sb3IgPSAncmVkJywgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wYXRoKGRhdGEgPSBjZW50cmVsaW5lX3dnczg0X21ham9yLmRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywgc2l6ZSA9IC4xKSArDQogIHN0YXRfZGVuc2l0eTJkKGRhdGE9TUNJX1JvYmJlcnlfWFksIGFlcyh4PVgsIHk9WSwgZmlsbD0uLmxldmVsLi4pLCBhbHBoYT0wLjIsIGdlb20gPSAncG9seWdvbicsIGNvbG91ciA9ICdibGFjaycsIGNvbnRvdXI9VFJVRSkgKw0KICBzY2FsZV9maWxsX2NvbnRpbnVvdXMobG93PSJ5ZWxsb3ciLGhpZ2g9InJlZCIpICsNCiB0aGVtZV9ub3RoaW5nKGxlZ2VuZCA9IFRSVUUpICsgDQogIGxhYnModGl0bGU9IlJvYmJlcnkgUmVwb3J0cyBpbiBUb3JvbnRvLCAyMDE0LTIwMTgiKQ0KYGBgDQoNCiMjIFRoZWZ0IE92ZXIgJDUwMDAgUmVwb3J0cyBpbiBUb3JvbnRvLCAyMDE0LTIwMTgNCg0KYGBge3J9DQpnZ3Bsb3QoKSArIA0KICBnZW9tX3BvbHlnb24oZGF0YSA9IHRvcm9udG9Cb3VuZGFyeV93Z3M4NC5kZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICBjb2xvciA9ICdibGFjaycsIHNpemUgPSAxLCBmaWxsPU5BKSArDQogIGdlb21fcGF0aChkYXRhID0gVFRDX3N1YndheV9saW5lc193Z3M4NC5kZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICBjb2xvciA9ICdyZWQnLCBzaXplID0gMSkgKw0KICBnZW9tX3BhdGgoZGF0YSA9IGNlbnRyZWxpbmVfd2dzODRfbWFqb3IuZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCBzaXplID0gLjEpICsNCiAgc3RhdF9kZW5zaXR5MmQoZGF0YT1NQ0lfVGhlZnRfT3Zlcl9YWSwgYWVzKHg9WCwgeT1ZLCBmaWxsPS4ubGV2ZWwuLiksIGFscGhhPTAuMiwgZ2VvbSA9ICdwb2x5Z29uJywgY29sb3VyID0gJ2JsYWNrJywgY29udG91cj1UUlVFKSArDQogIHNjYWxlX2ZpbGxfY29udGludW91cyhsb3c9InllbGxvdyIsaGlnaD0icmVkIikgKw0KIHRoZW1lX25vdGhpbmcobGVnZW5kID0gVFJVRSkgKyANCiAgbGFicyh0aXRsZT0iVGhlZnQgT3ZlciAkNTAwMCBSZXBvcnRzIGluIFRvcm9udG8sIDIwMTQtMjAxOCIpDQpgYGANCg0KDQojIENvcnJlbGF0aW9ucyBCZXR3ZWVuIE1DSSBhbmQgRGVtb2dyYXBoaWNzDQoNCmBgYHtyfQ0Kc3RyKG5laWdoYm91cmhvb2RzX21lcmdlZCkNCmBgYA0KDQpgYGB7cn0NCm5laWdoYm91cmhvb2RzX3JhdGlvcyA8LQ0KICBuZWlnaGJvdXJob29kc19tZXJnZWRbLCBjKCJBc3NhdWx0X3JhdGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXV0b190aGVmdF9yYXRpbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJFX3JhdGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUm9iYmVyeV9yYXRpbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRoZWZ0X292ZXJfcmF0aW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBdmVyYWdlX2hvdXNlaG9sZF9zaXplIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTElDT19wcmV2YWxlbmNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hpbGRyZW5fcmF0aW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZW5pb3JzX3JhdGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVudGVyc19yYXRpbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlB1YmxpY190cmFuc2l0X3RvX3dvcmtfcmF0aW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTb2NpYWxfYXNzaXN0YW5jZV9yZWNpcGllbnRzX3JhdGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXZlcmFnZV9ob3VzZWhvbGRfc2l6ZV9yYXRpbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkF2ZXJhZ2VfZW1wbG95bWVudF9pbmNvbWVfcmF0aW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbmVtcGxveW1lbnRfcmF0ZV9tYWxlc19yYXRpbyIpXQ0KYGBgDQoNCkNvbXB1dGUgY29ycmVsYXRpb25zOyB0aGVyZSBhcmUgb25seSB3ZWFrIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRoZSBNQ0kgYW5kIGRlbW9ncmFwaGljIHJhdGlvcyBJIGhhdmUgc2VsZWN0ZWQuDQoNCmBgYHtyfQ0KY29yKGFzLm1hdHJpeChuZWlnaGJvdXJob29kc19yYXRpb3MpKQ0KYGBgDQoNCg0KIyBUaW1lIFNlcmllcw0KDQpgYGB7cn0NCnN0cihNQ0lfZHQpDQpgYGANCg0KYGBge3J9DQpNQ0lfZHRfZGF0ZXMgPC0gTUNJX2R0WywuKHJlcG9ydGVkeWVhcixyZXBvcnRlZG1vbnRoLE1DSSldDQoNCk1DSV9kdF9kYXRlcyRyZXBvcnRlZG1vbnRoIDwtIG1hdGNoKE1DSV9kdF9kYXRlcyRyZXBvcnRlZG1vbnRoLCBtb250aC5uYW1lKQ0KDQpzdHIoTUNJX2R0X2RhdGVzKQ0KYGBgDQoNCiMjIEFzc2F1bHQgUmVwb3J0cyBUaW1lIFNlcmllcw0KDQpgYGB7cn0NCkFzc2F1bHRfZHQgPC0gTUNJX2R0X2RhdGVzW01DST09IkFzc2F1bHQiLC5OLCBieSA9IC4ocmVwb3J0ZWR5ZWFyLHJlcG9ydGVkbW9udGgpXQ0KDQpBc3NhdWx0X2R0IDwtIEFzc2F1bHRfZHRbb3JkZXIocmVwb3J0ZWR5ZWFyLHJlcG9ydGVkbW9udGgpXQ0KDQpzdHIoQXNzYXVsdF9kdCkNCmBgYA0KDQpgYGB7cn0NCkFzc2F1bHQudHMgPC0gdHMoQXNzYXVsdF9kdCROLCBzdGFydCA9IDIwMTQsIGZyZXF1ZW5jeSA9IDEyKQ0KYGBgDQoNCmBgYHtyfQ0KYXV0b3Bsb3QoQXNzYXVsdC50cykNCmBgYA0KDQpgYGB7cn0NCkFzc2F1bHQudHMuY29tcG9uZW50cyA8LSBkZWNvbXBvc2UoQXNzYXVsdC50cykNCmBgYA0KDQpgYGB7cn0NCmF1dG9wbG90KEFzc2F1bHQudHMuY29tcG9uZW50cykNCmBgYA0KDQpgYGB7cn0NCkFzc2F1bHQudHMuc3RsIDwtIHN0bChBc3NhdWx0LnRzLCBzLndpbmRvdyA9ICJwZXJpb2RpYyIpDQpgYGANCg0KYGBge3J9DQphdXRvcGxvdChBc3NhdWx0LnRzLnN0bCkNCmBgYA0KDQpgYGB7cn0NCkFzc2F1bHQudHMuYXJpbWEgPC0gYXV0by5hcmltYShBc3NhdWx0LnRzKQ0KDQpBc3NhdWx0LnRzLmFyaW1hDQpgYGANCg0KYGBge3J9DQpBc3NhdWx0LnRzLmFyaW1hLmZvcmVjYXN0IDwtIGZvcmVjYXN0KEFzc2F1bHQudHMuYXJpbWEsIGxldmVsID0gYyg5NSksIGggPSAxMikNCg0KYXV0b3Bsb3QoQXNzYXVsdC50cy5hcmltYS5mb3JlY2FzdCkNCmBgYA0KDQojIyBUaGVmdCBPdmVyICQ1MDAwIFRpbWUgU2VyaWVzDQoNCmBgYHtyfQ0KVGhlZnRfT3Zlcl9kdCA8LSBNQ0lfZHRfZGF0ZXNbTUNJPT0iVGhlZnQgT3ZlciIsLk4sIGJ5ID0gLihyZXBvcnRlZHllYXIscmVwb3J0ZWRtb250aCldDQoNClRoZWZ0X092ZXJfZHQgPC0gVGhlZnRfT3Zlcl9kdFtvcmRlcihyZXBvcnRlZHllYXIscmVwb3J0ZWRtb250aCldDQoNClRoZWZ0X092ZXIudHMgPC0gdHMoVGhlZnRfT3Zlcl9kdCROLCBzdGFydCA9IDIwMTQsIGZyZXF1ZW5jeSA9IDEyKQ0KDQpUaGVmdF9PdmVyLnRzLmNvbXBvbmVudHMgPC0gZGVjb21wb3NlKFRoZWZ0X092ZXIudHMpDQoNClRoZWZ0X092ZXIudHMuc3RsIDwtIHN0bChUaGVmdF9PdmVyLnRzLCBzLndpbmRvdyA9ICJwZXJpb2RpYyIpDQpgYGANCg0KYGBge3J9DQphdXRvcGxvdChUaGVmdF9PdmVyLnRzLmNvbXBvbmVudHMpDQpgYGANCg0KYGBge3J9DQphdXRvcGxvdChUaGVmdF9PdmVyLnRzLnN0bCkNCmBgYA0KDQoNCmBgYHtyfQ0KVGhlZnRfT3Zlci50cy5hcmltYSA8LSBhdXRvLmFyaW1hKFRoZWZ0X092ZXIudHMpDQoNClRoZWZ0X092ZXIudHMuYXJpbWENCmBgYA0K