Introduction

Policing in recent times in regarded as a multi-dimensional problem, where law enforcement agencies initiate efforts to utilize scarce resources to minimize crime occurrence across various geographies.This study tend to utilize Chicago crime data set which is publicly made available via criminal data of Chicago. The study employs various statistical techniques to visual occurrence of crime which include looking at the data set from spatial point of view. The primary interest in this study is to identify hot spots areas of assault crime that happened within the period of Aug 1st 2020- Aug 1st 2021.

Required Libraries

library(sp)
library(spdep)
library(tidyr)
library(tidyverse)
library(lubridate)
library(ggplot2)
library(dplyr)
library(plotly)
library(TSstudio)
library(forecast)
library(MLmetrics)
library(viridisLite)
library(viridis)
library(padr)
library(rmdformats)
library(recipes)
library(rgdal)
library(raster)
library(rgeos)

Data Extraction For the purpose of this study , we utilize the crime data for the city of Chicago which is publicly available on the city’s open data portal. The dataset is loaded using the R statistical software. —

setwd("C:/Users/charl/OneDrive/Desktop/Data Science Projects")
Warning: The working directory was changed to C:/Users/charl/OneDrive/Desktop/Data Science Projects inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
library(readr)
Threeyears_18_19_20_21Aug_1 <- read_csv("R Projects/Threeyears_18_19_20_21Aug-1.csv")
Rows: 700810 Columns: 30── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr   (9): Case.Number, Block, IUCR, Primary.Type, Description, Location.Description, FBI.Code, Updated.On, Location
dbl  (18): ï..ID, Beat, District, Ward, Community.Area, X.Coordinate, Y.Coordinate, Year, Latitude, Longitude, Historical.Wards.2003.2015, Zip.Codes, Com...
lgl   (2): Arrest, Domestic
dttm  (1): Date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#View(Threeyears_18_19_20_21Aug_1)
data<-Threeyears_18_19_20_21Aug_1

Data Description

The data for this study as labelled Crime data is from the Chicago Data Portal. For the purpose of this study, the initial dataset employed in R statistical software is from 2018-2021 which consisted of 700810 observations and 30 columns. However a subset dataset from Aug 01 2020 to Aug 01 2021 is taken for the final analysis on the new crime data. The new subset data however consisted of 200810 observations and 30 variables.The dataset however consisted of both qualitative and quantitative variables.Below shows all the process enaged in R to describe the dataset and subset the new data from the required dataset for further analysis.

names(data)
 [1] "ï..ID"                      "Case.Number"                "Date"                       "Block"                      "IUCR"                      
 [6] "Primary.Type"               "Description"                "Location.Description"       "Arrest"                     "Domestic"                  
[11] "Beat"                       "District"                   "Ward"                       "Community.Area"             "FBI.Code"                  
[16] "X.Coordinate"               "Y.Coordinate"               "Year"                       "Updated.On"                 "Latitude"                  
[21] "Longitude"                  "Location"                   "Historical.Wards.2003.2015" "Zip.Codes"                  "Community.Areas"           
[26] "Census.Tracts"              "Wards"                      "Boundaries...ZIP.Codes"     "Police.Districts"           "Police.Beats"              
skim(data)
── Data Summary ────────────────────────
                           Values
Name                       data  
Number of rows             700810
Number of columns          30    
_______________________          
Column type frequency:           
  character                9     
  logical                  2     
  numeric                  18    
  POSIXct                  1     
________________________         
Group variables            None  

Data Cleaning

The subset dataset for this study is taken from the initial dataset which covers the period of Aug 01 2020 to Aug 01 2021.

##subset dataset
newdata<- data %>%
filter(Date > "2020-08-01" & Date< "2021-08-01")
head(newdata)

Converting to Numbers

For this purpose of this lab work variables longitude and latitude are both coverted into numeric variables using the function “as.numeric”.

newdata$Latitude = as.numeric (newdata$Latitude)
newdata$Longitude = as.numeric(newdata$Longitude)
class(newdata$Latitude)
[1] "numeric"

Removing Missing Values

The dataset is preprocessed to remove all incidents without any latitude and longitude

newdata = newdata[!is.na(newdata$Latitude),]

Analysis Methods

The subset data is preprocessed for the purpose of removing all incidents with no latitude and longitude from the data.Spatial points object is further created from the subset dataset, which is over layed with the neighborhood polygons data using world geodetic system. The shape file is further read into R. Aggregation of assault by area within the neighborhood is further conducted to enhance our understanding on crime patterns in neighborhoods. The points are converted into raster which helps in generating a heat map using the focal function in R. The Getis-Ord GI is also employed conduct the hot spots analysis, which provides us with z-values to illustrate the presence of clustering in the used dataset. Open Street Map is also utilized in generating the hot maps.Below details the analysis conducted on the crime data.

###Convert to an object##
wgs84 = CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
crime_spt= SpatialPointsDataFrame(newdata[,c('Longitude','Latitude')], newdata, proj4string = wgs84)
plot(crime_spt)

## SHAPEFILE LOADING
neighborhoods = readOGR(dsn='.', layer='geo_export_b4cc3c31-7809-42e5-a88f-292b52d17cd9', stringsAsFactors = F)
Warning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among others
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\charl\OneDrive\Desktop\Data Science Projects\R Projects", layer: "geo_export_b4cc3c31-7809-42e5-a88f-292b52d17cd9"
with 61 features
It has 4 fields
neighborhoods = spTransform(neighborhoods, wgs84)
plot(neighborhoods, col=terrain.colors(nrow(neighborhoods)))

####overlaying the points######
crime_spt$zip= over(crime_spt, neighborhoods)$zip
crime_spt= crime_spt[!is.na(crime_spt$zip),]
plot(crime_spt,col= '#00000010')
plot(neighborhoods, border= 'gray', add= T)

chicago <- readOGR(dsn='.', layer= 'cityboundary', stringsAsFactors = F)
Warning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among othersWarning: OGR support is provided by the sf and terra packages among others
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\charl\OneDrive\Desktop\Data Science Projects\R Projects", layer: "cityboundary"
with 1 features
It has 4 fields
Integer64 fields read as strings:  OBJECTID 
##Chicago_prj<-st_crs(chicago)
chicago_prj <- crs(chicago)
chicago_prj
Coordinate Reference System:
Deprecated Proj.4 representation:
 +proj=tmerc +lat_0=36.6666666666667 +lon_0=-88.3333333333333 +k=0.999975 +x_0=300000 +y_0=0 +datum=NAD83 +units=us-ft +no_defs 
WKT2 2019 representation:
PROJCRS["NAD83 / Illinois East (ftUS)",
    BASEGEOGCRS["NAD83",
        DATUM["North American Datum 1983",
            ELLIPSOID["GRS 1980",6378137,298.257222101,
                LENGTHUNIT["metre",1]]],
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433]],
        ID["EPSG",4269]],
    CONVERSION["SPCS83 Illinois East zone (US Survey feet)",
        METHOD["Transverse Mercator",
            ID["EPSG",9807]],
        PARAMETER["Latitude of natural origin",36.6666666666667,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8801]],
        PARAMETER["Longitude of natural origin",-88.3333333333333,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8802]],
        PARAMETER["Scale factor at natural origin",0.999975,
            SCALEUNIT["unity",1],
            ID["EPSG",8805]],
        PARAMETER["False easting",984250,
            LENGTHUNIT["US survey foot",0.304800609601219],
            ID["EPSG",8806]],
        PARAMETER["False northing",0,
            LENGTHUNIT["US survey foot",0.304800609601219],
            ID["EPSG",8807]]],
    CS[Cartesian,2],
        AXIS["easting (X)",east,
            ORDER[1],
            LENGTHUNIT["US survey foot",0.304800609601219]],
        AXIS["northing (Y)",north,
            ORDER[2],
            LENGTHUNIT["US survey foot",0.304800609601219]],
    USAGE[
        SCOPE["Engineering survey, topographic mapping."],
        AREA["United States (USA) - Illinois - counties of Boone; Champaign; Clark; Clay; Coles; Cook; Crawford; Cumberland; De Kalb; De Witt; Douglas; Du Page; Edgar; Edwards; Effingham; Fayette; Ford; Franklin; Gallatin; Grundy; Hamilton; Hardin; Iroquois; Jasper; Jefferson; Johnson; Kane; Kankakee; Kendall; La Salle; Lake; Lawrence; Livingston; Macon; Marion; Massac; McHenry; McLean; Moultrie; Piatt; Pope; Richland; Saline; Shelby; Vermilion; Wabash; Wayne; White; Will; Williamson."],
        BBOX[37.06,-89.28,42.5,-87.02]],
    ID["EPSG",3435]] 
crime1 = spTransform(crime_spt, chicago_prj)
neighborhoods1 = spTransform(neighborhoods, chicago_prj)
assault2020= crime1[crime1$Primary.Type == 'ASSAULT',]
plot(assault2020, col= "#00000040")
plot(neighborhoods1, border= 'gray',add= T)

Neighborhood Analysis

##Aggregating by Area
names(assault2020)
 [1] "ï..ID"                      "Case.Number"                "Date"                       "Block"                      "IUCR"                      
 [6] "Primary.Type"               "Description"                "Location.Description"       "Arrest"                     "Domestic"                  
[11] "Beat"                       "District"                   "Ward"                       "Community.Area"             "FBI.Code"                  
[16] "X.Coordinate"               "Y.Coordinate"               "Year"                       "Updated.On"                 "Latitude"                  
[21] "Longitude"                  "Location"                   "Historical.Wards.2003.2015" "Zip.Codes"                  "Community.Areas"           
[26] "Census.Tracts"              "Wards"                      "Boundaries...ZIP.Codes"     "Police.Districts"           "Police.Beats"              
[31] "zip"                       
neighborhoods1$ASSAULT2020 = over(neighborhoods1, assault2020, fn= length)$ï..ID
spplot(neighborhoods1, zcol= 'ASSAULT2020',main=list(label= "2020 Assault crime by Neighborhood in the City of Chicago", cex= 1))

Heat Map

##To create a heat map you have to convert the points to a raster
pixelsize= 1000
box = round(extent(neighborhoods1) / pixelsize) * pixelsize
template= raster(box,crs = chicago_prj,
nrows = (box@ymax - box@ymin) / pixelsize,
ncols = (box@xmax - box@xmin) / pixelsize)
assault2020$PRESENT = 1
names(assault2020)
 [1] "ï..ID"                      "Case.Number"                "Date"                       "Block"                      "IUCR"                      
 [6] "Primary.Type"               "Description"                "Location.Description"       "Arrest"                     "Domestic"                  
[11] "Beat"                       "District"                   "Ward"                       "Community.Area"             "FBI.Code"                  
[16] "X.Coordinate"               "Y.Coordinate"               "Year"                       "Updated.On"                 "Latitude"                  
[21] "Longitude"                  "Location"                   "Historical.Wards.2003.2015" "Zip.Codes"                  "Community.Areas"           
[26] "Census.Tracts"              "Wards"                      "Boundaries...ZIP.Codes"     "Police.Districts"           "Police.Beats"              
[31] "zip"                        "PRESENT"                   
raster2020 = rasterize(assault2020, template, field = 'PRESENT', fun = sum)
plot(raster2020, xlim=c(1091131, 1205198), ylim=c(1813892, 1951669))
plot(neighborhoods1, border = '#00000040', add= T)

#####Next we use the focal function to run a gaussian smoothing kernel
kernel= focalWeight(raster2020, d=264, type ='Gauss')
heat2020= focal(raster2020, kernel, fun = sum, na.rm= T)
plot(heat2020, xlim=c(1091131, 1205199), ylim=c(1813892, 1951669))

###Getis-Ord GI
##one major issue with knrnel density estimation is that the choice of a threshold for what it is
##create a regular grid of 1/8-mile-square crime areas via a raster
pixelsize= 500
box = round(extent(neighborhoods1) / pixelsize) * pixelsize
template= raster(box,crs = chicago_prj,
nrows = (box@ymax - box@ymin) / pixelsize,
ncols = (box@xmax - box@xmin) / pixelsize)
assault2020$PRESENT = 1
#names(assault2020)
getisraster= rasterize(assault2020, template, field = 'PRESENT', fun = sum)
getisgrid = rasterToPolygons(getisraster)

##create the list of neighbors
#install.packages("spdep")
#library(spdep)
neighbors = poly2nb(getisgrid) ##construct neighbours list from polygon list
weighted_neighbors = nb2listw(neighbors, zero.policy = T) ## spatial weights for neighbours list
##perform the local G analysis
getisgrid$HOTSPOT = as.vector(localG(getisgrid$layer, weighted_neighbors))
Warning: NAs in lagged values
names(getisgrid)
[1] "layer"   "HOTSPOT"
### color the grid cells based on the z-score
min(getisgrid$HOTSPOT,na.rm= TRUE)
[1] -1.651486
max(getisgrid$HOTSPOT,na.rm= TRUE)
[1] 11.05128
breaks= c(-20, -1.96, -1, 1, 1.96, 20)
palette= c("#0000FF80","#8080FF80", "#FFFFFF80","#FF808080", "#FF000080")
col= palette[cut(getisgrid$HOTSPOT, breaks)]
###plot
plot(getisgrid, col=col, border= NA, xlim=c(1091131,1205199), ylim=c(1813892,1951669) )
plot(neighborhoods1, border= "gray", add= T)

#############OPEN STREET MAP#########
#install.packages("OpenStreetMap",dependencies = TRUE)
library(OpenStreetMap)
Warning: package ‘OpenStreetMap’ was built under R version 4.2.3
extent(neighborhoods)
class      : Extent 
xmin       : -87.94011 
xmax       : -87.52414 
ymin       : 41.64454 
ymax       : 42.02304 
basemap = openmap(upperLeft = c(42.02304 , -87.94011), lowerRight = c(41.64454 , -87.52414 ), type="osm")
basemap = openproj(basemap, chicago_prj)
plot(basemap)
plot(getisgrid, col=col, border= NA, add= T)

basemap = openmap(upperLeft = c(42.02304 , -87.94011), lowerRight = c(41.64454 , -87.52414 ), type="osm")
basemap = openproj(basemap, chicago_prj)
plot(basemap)
plot(getisgrid, col=col, border= NA, add= T)
legend(x= 'bottomleft', inset= 0.05, bg= "white", col=palette, pch=15,
legend = c('cold spot >99% confidence','cold spot 68-95% confidence',
'Not Significant', 'Hot Spot 68-95% confidence', 'Hot spot >95% confidence'))

Findings

From the above crime data analysis, there is the development of spatial plot on Assault crime in the city of Chicago from the period of August 01,2020 to August,01 2021. The plots as displayed above showed spatial locations of assault data in the city of Chicago. There is however the identification of both hot spot and cold spot areas of assault crime in the city of Chicago. As shown, there is high occurrence of assault crime (hot spot) in the central part of Chicago city. These are areas centered around the central business areas of the city which constitute more than 95% significance confidence level whiles 65-95% confidence hot-spot traces can be seen in the north and south part of the city. The significant cold spot of assault crime of more than 95% confidence level can be found in north and eastern part of Chicago, with suburbs of the city displaying cold spots of assault crime as defined with 65-95% confidence level.

Conclusion

In conclusion, it can be suggested that the streets of Chicago during the period of 2020-2021 was considered unsafe for its residents, with high occurrence of assault crime. This however does not rule out the occurrence of other crimes in the city. Most of these crimes(assault) occurred in the downtown area of the city. However with more precautionary measures and collaborative efforts by the city police, community leaders and other state agencies, the streets of Chicago will become more safer for its residents.

LS0tDQp0aXRsZTogIkhvdHNwb3QgQW5hbHlzaXMgVXNpbmcgQ2hpY2FnbyBjcmltZSBkYXRhICINCmF1dGhvcjogIkNIQVJMRVMgV0lSRURVIg0KZGF0ZTogIjIwMjMtMDMtMjciDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KSW50cm9kdWN0aW9uDQotLS0NClBvbGljaW5nIGluIHJlY2VudCB0aW1lcyBpbiByZWdhcmRlZCAgYXMgYSBtdWx0aS1kaW1lbnNpb25hbCBwcm9ibGVtLCB3aGVyZSBsYXcgZW5mb3JjZW1lbnQgYWdlbmNpZXMgaW5pdGlhdGUgZWZmb3J0cyB0byB1dGlsaXplIHNjYXJjZSByZXNvdXJjZXMgdG8gbWluaW1pemUgY3JpbWUgb2NjdXJyZW5jZSBhY3Jvc3MgdmFyaW91cyBnZW9ncmFwaGllcy5UaGlzIHN0dWR5IHRlbmQgdG8gdXRpbGl6ZSBDaGljYWdvIGNyaW1lIGRhdGEgc2V0IHdoaWNoIGlzIHB1YmxpY2x5IG1hZGUgYXZhaWxhYmxlIHZpYSBjcmltaW5hbCBkYXRhIG9mIENoaWNhZ28uIFRoZSBzdHVkeSBlbXBsb3lzIHZhcmlvdXMgc3RhdGlzdGljYWwgdGVjaG5pcXVlcyB0byB2aXN1YWwgb2NjdXJyZW5jZSBvZiBjcmltZSB3aGljaCBpbmNsdWRlIGxvb2tpbmcgYXQgdGhlIGRhdGEgc2V0IGZyb20gc3BhdGlhbCBwb2ludCBvZiB2aWV3LiBUaGUgcHJpbWFyeSBpbnRlcmVzdCBpbiB0aGlzIHN0dWR5IGlzIHRvIGlkZW50aWZ5IGhvdCBzcG90cyBhcmVhcyBvZiBhc3NhdWx0IGNyaW1lICB0aGF0IGhhcHBlbmVkIHdpdGhpbiB0aGUgcGVyaW9kIG9mIEF1ZyAxc3QgMjAyMC0gQXVnIDFzdCAyMDIxLg0KDQoNClJlcXVpcmVkIExpYnJhcmllcw0KLS0tDQpgYGB7cn0NCmxpYnJhcnkoc3ApDQpsaWJyYXJ5KHNwZGVwKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KFRTc3R1ZGlvKQ0KbGlicmFyeShmb3JlY2FzdCkNCmxpYnJhcnkoTUxtZXRyaWNzKQ0KbGlicmFyeSh2aXJpZGlzTGl0ZSkNCmxpYnJhcnkodmlyaWRpcykNCmxpYnJhcnkocGFkcikNCmxpYnJhcnkocm1kZm9ybWF0cykNCmxpYnJhcnkocmVjaXBlcykNCmxpYnJhcnkocmdkYWwpDQpsaWJyYXJ5KHJhc3RlcikNCmxpYnJhcnkocmdlb3MpDQpgYGANCg0KRGF0YSBFeHRyYWN0aW9uDQpGb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBzdHVkeSAsIHdlIHV0aWxpemUgdGhlIGNyaW1lIGRhdGEgZm9yIHRoZSBjaXR5IG9mIENoaWNhZ28gd2hpY2ggaXMgcHVibGljbHkgYXZhaWxhYmxlIG9uIHRoZSBjaXR5J3Mgb3BlbiBkYXRhIHBvcnRhbC4gVGhlIGRhdGFzZXQgaXMgbG9hZGVkIHVzaW5nIHRoZSBSIHN0YXRpc3RpY2FsIHNvZnR3YXJlLg0KLS0tDQpgYGB7cn0NCnNldHdkKCJDOi9Vc2Vycy9jaGFybC9PbmVEcml2ZS9EZXNrdG9wL0RhdGEgU2NpZW5jZSBQcm9qZWN0cyIpDQpsaWJyYXJ5KHJlYWRyKQ0KVGhyZWV5ZWFyc18xOF8xOV8yMF8yMUF1Z18xIDwtIHJlYWRfY3N2KCJSIFByb2plY3RzL1RocmVleWVhcnNfMThfMTlfMjBfMjFBdWctMS5jc3YiKQ0KI1ZpZXcoVGhyZWV5ZWFyc18xOF8xOV8yMF8yMUF1Z18xKQ0KZGF0YTwtVGhyZWV5ZWFyc18xOF8xOV8yMF8yMUF1Z18xDQpgYGANCkRhdGEgRGVzY3JpcHRpb24NCi0tLQ0KVGhlIGRhdGEgZm9yIHRoaXMgc3R1ZHkgYXMgbGFiZWxsZWQgQ3JpbWUgZGF0YSBpcyBmcm9tIHRoZSBDaGljYWdvIERhdGEgUG9ydGFsLiBGb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBzdHVkeSwgdGhlIGluaXRpYWwgZGF0YXNldCBlbXBsb3llZCBpbiBSIHN0YXRpc3RpY2FsIHNvZnR3YXJlIGlzIGZyb20gMjAxOC0yMDIxIHdoaWNoIGNvbnNpc3RlZCBvZiA3MDA4MTAgb2JzZXJ2YXRpb25zIGFuZCAzMCBjb2x1bW5zLiBIb3dldmVyIGEgc3Vic2V0IGRhdGFzZXQgZnJvbSBBdWcgMDEgMjAyMCB0byBBdWcgMDEgMjAyMSBpcyB0YWtlbiBmb3IgdGhlDQpmaW5hbCBhbmFseXNpcyBvbiB0aGUgbmV3IGNyaW1lIGRhdGEuIFRoZSBuZXcgc3Vic2V0IGRhdGEgaG93ZXZlciBjb25zaXN0ZWQgb2YgMjAwODEwIG9ic2VydmF0aW9ucyBhbmQgMzAgdmFyaWFibGVzLlRoZSBkYXRhc2V0IGhvd2V2ZXIgY29uc2lzdGVkIG9mIGJvdGggcXVhbGl0YXRpdmUgYW5kIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMuQmVsb3cgc2hvd3MgYWxsIHRoZSBwcm9jZXNzIGVuYWdlZCBpbiBSIHRvIGRlc2NyaWJlIHRoZSBkYXRhc2V0IGFuZCBzdWJzZXQgdGhlIG5ldyBkYXRhIGZyb20gdGhlIHJlcXVpcmVkIGRhdGFzZXQgZm9yIGZ1cnRoZXIgYW5hbHlzaXMuDQoNCmBgYHtyfQ0KbmFtZXMoZGF0YSkNCnNraW0oZGF0YSkNCmBgYA0KDQpEYXRhIENsZWFuaW5nDQotLS0NClRoZSBzdWJzZXQgZGF0YXNldCAgZm9yIHRoaXMgc3R1ZHkgaXMgdGFrZW4gZnJvbSB0aGUgaW5pdGlhbCBkYXRhc2V0IHdoaWNoIGNvdmVycyB0aGUgcGVyaW9kIG9mIEF1ZyAwMSAyMDIwIHRvIEF1ZyAwMSAyMDIxLg0KYGBge3J9DQojI3N1YnNldCBkYXRhc2V0DQpuZXdkYXRhPC0gZGF0YSAlPiUNCmZpbHRlcihEYXRlID4gIjIwMjAtMDgtMDEiICYgRGF0ZTwgIjIwMjEtMDgtMDEiKQ0KaGVhZChuZXdkYXRhKQ0KYGBgDQojIyBDb252ZXJ0aW5nIHRvIE51bWJlcnMNCkZvciB0aGlzIHB1cnBvc2Ugb2YgdGhpcyBsYWIgd29yayB2YXJpYWJsZXMgbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSBhcmUgYm90aCBjb3ZlcnRlZCBpbnRvIG51bWVyaWMgdmFyaWFibGVzDQp1c2luZyB0aGUgZnVuY3Rpb24g4oCcYXMubnVtZXJpY+KAnS4NCmBgYHtyfQ0KbmV3ZGF0YSRMYXRpdHVkZSA9IGFzLm51bWVyaWMgKG5ld2RhdGEkTGF0aXR1ZGUpDQpuZXdkYXRhJExvbmdpdHVkZSA9IGFzLm51bWVyaWMobmV3ZGF0YSRMb25naXR1ZGUpDQpjbGFzcyhuZXdkYXRhJExhdGl0dWRlKQ0KDQpgYGANCiMjIFJlbW92aW5nIE1pc3NpbmcgVmFsdWVzDQpUaGUgZGF0YXNldCBpcyBwcmVwcm9jZXNzZWQgdG8gcmVtb3ZlIGFsbCBpbmNpZGVudHMgd2l0aG91dCBhbnkgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZQ0KYGBge3J9DQpuZXdkYXRhID0gbmV3ZGF0YVshaXMubmEobmV3ZGF0YSRMYXRpdHVkZSksXQ0KYGBgDQoNCiMjIEFuYWx5c2lzIE1ldGhvZHMNCg0KVGhlIHN1YnNldCBkYXRhIGlzIHByZXByb2Nlc3NlZCBmb3IgdGhlIHB1cnBvc2Ugb2YgcmVtb3ZpbmcgYWxsIGluY2lkZW50cyB3aXRoIG5vIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgZnJvbSB0aGUgZGF0YS5TcGF0aWFsIHBvaW50cyBvYmplY3QgaXMgZnVydGhlciBjcmVhdGVkIGZyb20gdGhlIHN1YnNldCBkYXRhc2V0LCB3aGljaCBpcyBvdmVyIGxheWVkIHdpdGggdGhlIG5laWdoYm9yaG9vZCBwb2x5Z29ucyBkYXRhIHVzaW5nIHdvcmxkIGdlb2RldGljIHN5c3RlbS4gVGhlIHNoYXBlIGZpbGUgaXMgZnVydGhlciByZWFkIGludG8gUi4gQWdncmVnYXRpb24gb2YgYXNzYXVsdCBieSBhcmVhIHdpdGhpbiB0aGUgbmVpZ2hib3Job29kIGlzIGZ1cnRoZXIgY29uZHVjdGVkIHRvIGVuaGFuY2Ugb3VyIHVuZGVyc3RhbmRpbmcgb24gY3JpbWUgcGF0dGVybnMgaW4gbmVpZ2hib3Job29kcy4gVGhlIHBvaW50cyBhcmUgY29udmVydGVkIGludG8gcmFzdGVyIHdoaWNoIGhlbHBzIGluIGdlbmVyYXRpbmcgYSBoZWF0IG1hcCB1c2luZyB0aGUgZm9jYWwgZnVuY3Rpb24gaW4gUi4gVGhlIEdldGlzLU9yZCBHSSBpcyBhbHNvIGVtcGxveWVkIGNvbmR1Y3QgdGhlIGhvdCBzcG90cyBhbmFseXNpcywgd2hpY2ggcHJvdmlkZXMNCnVzIHdpdGggei12YWx1ZXMgdG8gaWxsdXN0cmF0ZSB0aGUgcHJlc2VuY2Ugb2YgY2x1c3RlcmluZyBpbiB0aGUgdXNlZCBkYXRhc2V0LiBPcGVuIFN0cmVldCBNYXAgaXMgYWxzbyB1dGlsaXplZCBpbiBnZW5lcmF0aW5nIHRoZSBob3QgbWFwcy5CZWxvdyBkZXRhaWxzIHRoZSBhbmFseXNpcyBjb25kdWN0ZWQgb24gdGhlIGNyaW1lIGRhdGEuDQoNCmBgYHtyfQ0KIyMjQ29udmVydCB0byBhbiBvYmplY3QjIw0Kd2dzODQgPSBDUlMoIitwcm9qPWxvbmdsYXQgK2VsbHBzPVdHUzg0ICtkYXR1bT1XR1M4NCArbm9fZGVmcyIpDQpjcmltZV9zcHQ9IFNwYXRpYWxQb2ludHNEYXRhRnJhbWUobmV3ZGF0YVssYygnTG9uZ2l0dWRlJywnTGF0aXR1ZGUnKV0sIG5ld2RhdGEsIHByb2o0c3RyaW5nID0gd2dzODQpDQpwbG90KGNyaW1lX3NwdCkNCmBgYA0KYGBge3J9DQojIyBTSEFQRUZJTEUgTE9BRElORw0KbmVpZ2hib3Job29kcyA9IHJlYWRPR1IoZHNuPScuJywgbGF5ZXI9J2dlb19leHBvcnRfYjRjYzNjMzEtNzgwOS00MmU1LWE4OGYtMjkyYjUyZDE3Y2Q5Jywgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQpuZWlnaGJvcmhvb2RzID0gc3BUcmFuc2Zvcm0obmVpZ2hib3Job29kcywgd2dzODQpDQpwbG90KG5laWdoYm9yaG9vZHMsIGNvbD10ZXJyYWluLmNvbG9ycyhucm93KG5laWdoYm9yaG9vZHMpKSkNCmBgYA0KYGBge3J9DQojIyMjb3ZlcmxheWluZyB0aGUgcG9pbnRzIyMjIyMjDQpjcmltZV9zcHQkemlwPSBvdmVyKGNyaW1lX3NwdCwgbmVpZ2hib3Job29kcykkemlwDQpjcmltZV9zcHQ9IGNyaW1lX3NwdFshaXMubmEoY3JpbWVfc3B0JHppcCksXQ0KcGxvdChjcmltZV9zcHQsY29sPSAnIzAwMDAwMDEwJykNCnBsb3QobmVpZ2hib3Job29kcywgYm9yZGVyPSAnZ3JheScsIGFkZD0gVCkNCmBgYA0KDQpgYGB7cn0NCmNoaWNhZ28gPC0gcmVhZE9HUihkc249Jy4nLCBsYXllcj0gJ2NpdHlib3VuZGFyeScsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQ0KIyNDaGljYWdvX3Byajwtc3RfY3JzKGNoaWNhZ28pDQpjaGljYWdvX3ByaiA8LSBjcnMoY2hpY2FnbykNCmNoaWNhZ29fcHJqDQoNCmNyaW1lMSA9IHNwVHJhbnNmb3JtKGNyaW1lX3NwdCwgY2hpY2Fnb19wcmopDQpuZWlnaGJvcmhvb2RzMSA9IHNwVHJhbnNmb3JtKG5laWdoYm9yaG9vZHMsIGNoaWNhZ29fcHJqKQ0KYXNzYXVsdDIwMjA9IGNyaW1lMVtjcmltZTEkUHJpbWFyeS5UeXBlID09ICdBU1NBVUxUJyxdDQpwbG90KGFzc2F1bHQyMDIwLCBjb2w9ICIjMDAwMDAwNDAiKQ0KcGxvdChuZWlnaGJvcmhvb2RzMSwgYm9yZGVyPSAnZ3JheScsYWRkPSBUKQ0KYGBgDQoNCiMjIE5laWdoYm9yaG9vZCBBbmFseXNpcw0KYGBge3J9DQojI0FnZ3JlZ2F0aW5nIGJ5IEFyZWENCm5hbWVzKGFzc2F1bHQyMDIwKQ0KDQpuZWlnaGJvcmhvb2RzMSRBU1NBVUxUMjAyMCA9IG92ZXIobmVpZ2hib3Job29kczEsIGFzc2F1bHQyMDIwLCBmbj0gbGVuZ3RoKSTDry4uSUQNCnNwcGxvdChuZWlnaGJvcmhvb2RzMSwgemNvbD0gJ0FTU0FVTFQyMDIwJyxtYWluPWxpc3QobGFiZWw9ICIyMDIwIEFzc2F1bHQgY3JpbWUgYnkgTmVpZ2hib3Job29kIGluIHRoZSBDaXR5IG9mIENoaWNhZ28iLCBjZXg9IDEpKQ0KYGBgDQoNCiMjIEhlYXQgTWFwDQpgYGB7cn0NCiMjVG8gY3JlYXRlIGEgaGVhdCBtYXAgeW91IGhhdmUgdG8gY29udmVydCB0aGUgcG9pbnRzIHRvIGEgcmFzdGVyDQpwaXhlbHNpemU9IDEwMDANCmJveCA9IHJvdW5kKGV4dGVudChuZWlnaGJvcmhvb2RzMSkgLyBwaXhlbHNpemUpICogcGl4ZWxzaXplDQp0ZW1wbGF0ZT0gcmFzdGVyKGJveCxjcnMgPSBjaGljYWdvX3ByaiwNCm5yb3dzID0gKGJveEB5bWF4IC0gYm94QHltaW4pIC8gcGl4ZWxzaXplLA0KbmNvbHMgPSAoYm94QHhtYXggLSBib3hAeG1pbikgLyBwaXhlbHNpemUpDQphc3NhdWx0MjAyMCRQUkVTRU5UID0gMQ0KbmFtZXMoYXNzYXVsdDIwMjApDQoNCmBgYA0KDQpgYGB7cn0NCnJhc3RlcjIwMjAgPSByYXN0ZXJpemUoYXNzYXVsdDIwMjAsIHRlbXBsYXRlLCBmaWVsZCA9ICdQUkVTRU5UJywgZnVuID0gc3VtKQ0KcGxvdChyYXN0ZXIyMDIwLCB4bGltPWMoMTA5MTEzMSwgMTIwNTE5OCksIHlsaW09YygxODEzODkyLCAxOTUxNjY5KSkNCnBsb3QobmVpZ2hib3Job29kczEsIGJvcmRlciA9ICcjMDAwMDAwNDAnLCBhZGQ9IFQpDQoNCmBgYA0KYGBge3J9DQojIyMjI05leHQgd2UgdXNlIHRoZSBmb2NhbCBmdW5jdGlvbiB0byBydW4gYSBnYXVzc2lhbiBzbW9vdGhpbmcga2VybmVsDQprZXJuZWw9IGZvY2FsV2VpZ2h0KHJhc3RlcjIwMjAsIGQ9MjY0LCB0eXBlID0nR2F1c3MnKQ0KaGVhdDIwMjA9IGZvY2FsKHJhc3RlcjIwMjAsIGtlcm5lbCwgZnVuID0gc3VtLCBuYS5ybT0gVCkNCnBsb3QoaGVhdDIwMjAsIHhsaW09YygxMDkxMTMxLCAxMjA1MTk5KSwgeWxpbT1jKDE4MTM4OTIsIDE5NTE2NjkpKQ0KYGBgDQpgYGB7cn0NCiMjI0dldGlzLU9yZCBHSQ0KIyNvbmUgbWFqb3IgaXNzdWUgd2l0aCBrbnJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIGlzIHRoYXQgdGhlIGNob2ljZSBvZiBhIHRocmVzaG9sZCBmb3Igd2hhdCBpdCBpcw0KIyNjcmVhdGUgYSByZWd1bGFyIGdyaWQgb2YgMS84LW1pbGUtc3F1YXJlIGNyaW1lIGFyZWFzIHZpYSBhIHJhc3Rlcg0KcGl4ZWxzaXplPSA1MDANCmJveCA9IHJvdW5kKGV4dGVudChuZWlnaGJvcmhvb2RzMSkgLyBwaXhlbHNpemUpICogcGl4ZWxzaXplDQp0ZW1wbGF0ZT0gcmFzdGVyKGJveCxjcnMgPSBjaGljYWdvX3ByaiwNCm5yb3dzID0gKGJveEB5bWF4IC0gYm94QHltaW4pIC8gcGl4ZWxzaXplLA0KbmNvbHMgPSAoYm94QHhtYXggLSBib3hAeG1pbikgLyBwaXhlbHNpemUpDQphc3NhdWx0MjAyMCRQUkVTRU5UID0gMQ0KI25hbWVzKGFzc2F1bHQyMDIwKQ0KYGBgDQoNCmBgYHtyfQ0KZ2V0aXNyYXN0ZXI9IHJhc3Rlcml6ZShhc3NhdWx0MjAyMCwgdGVtcGxhdGUsIGZpZWxkID0gJ1BSRVNFTlQnLCBmdW4gPSBzdW0pDQpnZXRpc2dyaWQgPSByYXN0ZXJUb1BvbHlnb25zKGdldGlzcmFzdGVyKQ0KDQojI2NyZWF0ZSB0aGUgbGlzdCBvZiBuZWlnaGJvcnMNCiNpbnN0YWxsLnBhY2thZ2VzKCJzcGRlcCIpDQojbGlicmFyeShzcGRlcCkNCm5laWdoYm9ycyA9IHBvbHkybmIoZ2V0aXNncmlkKSAjI2NvbnN0cnVjdCBuZWlnaGJvdXJzIGxpc3QgZnJvbSBwb2x5Z29uIGxpc3QNCndlaWdodGVkX25laWdoYm9ycyA9IG5iMmxpc3R3KG5laWdoYm9ycywgemVyby5wb2xpY3kgPSBUKSAjIyBzcGF0aWFsIHdlaWdodHMgZm9yIG5laWdoYm91cnMgbGlzdA0KYGBgDQoNCmBgYHtyfQ0KIyNwZXJmb3JtIHRoZSBsb2NhbCBHIGFuYWx5c2lzDQpnZXRpc2dyaWQkSE9UU1BPVCA9IGFzLnZlY3Rvcihsb2NhbEcoZ2V0aXNncmlkJGxheWVyLCB3ZWlnaHRlZF9uZWlnaGJvcnMpKQ0KDQpuYW1lcyhnZXRpc2dyaWQpDQoNCiMjIyBjb2xvciB0aGUgZ3JpZCBjZWxscyBiYXNlZCBvbiB0aGUgei1zY29yZQ0KbWluKGdldGlzZ3JpZCRIT1RTUE9ULG5hLnJtPSBUUlVFKQ0KDQptYXgoZ2V0aXNncmlkJEhPVFNQT1QsbmEucm09IFRSVUUpDQpgYGANCg0KYGBge3J9DQpicmVha3M9IGMoLTIwLCAtMS45NiwgLTEsIDEsIDEuOTYsIDIwKQ0KcGFsZXR0ZT0gYygiIzAwMDBGRjgwIiwiIzgwODBGRjgwIiwgIiNGRkZGRkY4MCIsIiNGRjgwODA4MCIsICIjRkYwMDAwODAiKQ0KY29sPSBwYWxldHRlW2N1dChnZXRpc2dyaWQkSE9UU1BPVCwgYnJlYWtzKV0NCiMjI3Bsb3QNCnBsb3QoZ2V0aXNncmlkLCBjb2w9Y29sLCBib3JkZXI9IE5BLCB4bGltPWMoMTA5MTEzMSwxMjA1MTk5KSwgeWxpbT1jKDE4MTM4OTIsMTk1MTY2OSkgKQ0KcGxvdChuZWlnaGJvcmhvb2RzMSwgYm9yZGVyPSAiZ3JheSIsIGFkZD0gVCkNCmBgYA0KYGBge3J9DQojIyMjIyMjIyMjIyMjT1BFTiBTVFJFRVQgTUFQIyMjIyMjIyMjDQojaW5zdGFsbC5wYWNrYWdlcygiT3BlblN0cmVldE1hcCIsZGVwZW5kZW5jaWVzID0gVFJVRSkNCmxpYnJhcnkoT3BlblN0cmVldE1hcCkNCmV4dGVudChuZWlnaGJvcmhvb2RzKQ0KYGBgDQpgYGB7cn0NCmJhc2VtYXAgPSBvcGVubWFwKHVwcGVyTGVmdCA9IGMoNDIuMDIzMDQgLCAtODcuOTQwMTEpLCBsb3dlclJpZ2h0ID0gYyg0MS42NDQ1NCAsIC04Ny41MjQxNCApLCB0eXBlPSJvc20iKQ0KYmFzZW1hcCA9IG9wZW5wcm9qKGJhc2VtYXAsIGNoaWNhZ29fcHJqKQ0KcGxvdChiYXNlbWFwKQ0KcGxvdChnZXRpc2dyaWQsIGNvbD1jb2wsIGJvcmRlcj0gTkEsIGFkZD0gVCkNCmBgYA0KDQpgYGB7cn0NCmJhc2VtYXAgPSBvcGVubWFwKHVwcGVyTGVmdCA9IGMoNDIuMDIzMDQgLCAtODcuOTQwMTEpLCBsb3dlclJpZ2h0ID0gYyg0MS42NDQ1NCAsIC04Ny41MjQxNCApLCB0eXBlPSJvc20iKQ0KYmFzZW1hcCA9IG9wZW5wcm9qKGJhc2VtYXAsIGNoaWNhZ29fcHJqKQ0KcGxvdChiYXNlbWFwKQ0KcGxvdChnZXRpc2dyaWQsIGNvbD1jb2wsIGJvcmRlcj0gTkEsIGFkZD0gVCkNCmxlZ2VuZCh4PSAnYm90dG9tbGVmdCcsIGluc2V0PSAwLjA1LCBiZz0gIndoaXRlIiwgY29sPXBhbGV0dGUsIHBjaD0xNSwNCmxlZ2VuZCA9IGMoJ2NvbGQgc3BvdCA+OTklIGNvbmZpZGVuY2UnLCdjb2xkIHNwb3QgNjgtOTUlIGNvbmZpZGVuY2UnLA0KJ05vdCBTaWduaWZpY2FudCcsICdIb3QgU3BvdCA2OC05NSUgY29uZmlkZW5jZScsICdIb3Qgc3BvdCA+OTUlIGNvbmZpZGVuY2UnKSkNCmBgYA0KRmluZGluZ3MNCi0tLQ0KRnJvbSB0aGUgYWJvdmUgY3JpbWUgZGF0YSBhbmFseXNpcywgdGhlcmUgaXMgdGhlIGRldmVsb3BtZW50IG9mIHNwYXRpYWwgcGxvdCBvbiBBc3NhdWx0IGNyaW1lIGluIHRoZSBjaXR5IG9mIENoaWNhZ28gZnJvbSB0aGUgcGVyaW9kIG9mIEF1Z3VzdCAwMSwyMDIwIHRvIEF1Z3VzdCwwMSAyMDIxLiBUaGUgcGxvdHMgYXMgZGlzcGxheWVkIGFib3ZlIHNob3dlZCBzcGF0aWFsIGxvY2F0aW9ucyBvZiBhc3NhdWx0IGRhdGEgaW4gdGhlIGNpdHkgb2YgQ2hpY2Fnby4gVGhlcmUgaXMgaG93ZXZlciB0aGUgaWRlbnRpZmljYXRpb24gb2YgYm90aCBob3Qgc3BvdCBhbmQgY29sZCBzcG90IGFyZWFzIG9mIGFzc2F1bHQgY3JpbWUgaW4gdGhlIGNpdHkgb2YgQ2hpY2Fnby4gQXMgc2hvd24sIHRoZXJlIGlzIGhpZ2ggb2NjdXJyZW5jZSBvZiBhc3NhdWx0IGNyaW1lIChob3Qgc3BvdCkgaW4gdGhlIGNlbnRyYWwgcGFydCBvZiBDaGljYWdvIGNpdHkuIFRoZXNlIGFyZSBhcmVhcyBjZW50ZXJlZCBhcm91bmQgdGhlIGNlbnRyYWwgYnVzaW5lc3MgYXJlYXMgb2YgdGhlIGNpdHkgd2hpY2ggY29uc3RpdHV0ZSBtb3JlIHRoYW4gOTUlIHNpZ25pZmljYW5jZSBjb25maWRlbmNlIGxldmVsIHdoaWxlcyA2NS05NSUgY29uZmlkZW5jZSBob3Qtc3BvdCB0cmFjZXMgY2FuIGJlIHNlZW4gaW4gdGhlIG5vcnRoIGFuZCBzb3V0aCBwYXJ0IG9mIHRoZSBjaXR5LiBUaGUgc2lnbmlmaWNhbnQgY29sZCBzcG90IG9mIGFzc2F1bHQgY3JpbWUgb2YgbW9yZSB0aGFuIDk1JSBjb25maWRlbmNlIGxldmVsIGNhbiBiZSBmb3VuZCBpbiBub3J0aCBhbmQgZWFzdGVybiBwYXJ0IG9mIENoaWNhZ28sIHdpdGggc3VidXJicyBvZiB0aGUgY2l0eSBkaXNwbGF5aW5nIGNvbGQgc3BvdHMgb2YgYXNzYXVsdCBjcmltZSBhcyBkZWZpbmVkIHdpdGggNjUtOTUlIGNvbmZpZGVuY2UgbGV2ZWwuDQoNCkNvbmNsdXNpb24NCi0tLQ0KSW4gY29uY2x1c2lvbiwgaXQgY2FuIGJlIHN1Z2dlc3RlZCB0aGF0IHRoZSBzdHJlZXRzIG9mIENoaWNhZ28gZHVyaW5nIHRoZSBwZXJpb2Qgb2YgMjAyMC0yMDIxIHdhcyBjb25zaWRlcmVkIHVuc2FmZSBmb3IgaXRzIHJlc2lkZW50cywgd2l0aCBoaWdoIG9jY3VycmVuY2Ugb2YgYXNzYXVsdCBjcmltZS4gVGhpcyBob3dldmVyIGRvZXMgbm90IHJ1bGUgb3V0IHRoZSBvY2N1cnJlbmNlIG9mIG90aGVyIGNyaW1lcyBpbiB0aGUgY2l0eS4gTW9zdCBvZiB0aGVzZSBjcmltZXMoYXNzYXVsdCkgb2NjdXJyZWQgaW4gdGhlIGRvd250b3duIGFyZWEgb2YgdGhlIGNpdHkuIEhvd2V2ZXIgd2l0aCBtb3JlIHByZWNhdXRpb25hcnkgbWVhc3VyZXMgYW5kIGNvbGxhYm9yYXRpdmUgZWZmb3J0cyBieSB0aGUgY2l0eSBwb2xpY2UsIGNvbW11bml0eSBsZWFkZXJzIGFuZCBvdGhlciBzdGF0ZSBhZ2VuY2llcywgdGhlIHN0cmVldHMgb2YgQ2hpY2FnbyB3aWxsIGJlY29tZSBtb3JlIHNhZmVyIGZvciBpdHMgcmVzaWRlbnRzLg==