Lab Overview
Analyzing Crime in Chicago
Crime is an international concern, but it is documented and handled in very different ways in different countries. In the United States, violent crimes and property crimes are recorded by the Federal Bureau of Investigation (FBI). Additionally, each city documents crime, and some cities release data regarding crime rates. The city of Chicago, Illinois releases crime data from 2001 onward online.
Chicago is the third most populous city in the United States, with a population of over 2.7 million people. The city of Chicago is shown in the map below, with the state of Illinois highlighted in red.
There are two main types of crimes: violent crimes, and property crimes. In this problem, we’ll focus on one specific type of property crime, called “motor vehicle theft” (sometimes referred to as grand theft auto). This is the act of stealing, or attempting to steal, a car. In this problem, we’ll use some basic data analysis in R to understand the motor vehicle thefts in Chicago.
Crime Data
Please download the file mvtWeek1.csv for this problem (do not open this file in any spreadsheet software before completing this problem because it might change the format of the Date field).
Here is a list of descriptions of the variables:
- ID: a unique identifier for each observation
- Date: the date the crime occurred
- LocationDescription: the location where the crime occurred
- Arrest: whether or not an arrest was made for the crime (
TRUE if an arrest was made, and FALSE if an arrest was not made)
- Domestic: whether or not the crime was a domestic crime, meaning that it was committed against a family member (
TRUE if it was domestic, and FALSE if it was not domestic)
- Beat: the area, or “beat” in which the crime occurred. This is the smallest regional division defined by the Chicago police department.
- District: the police district in which the crime occured. Each district is composed of many beats, and are defined by the Chicago Police Department.
- CommunityArea: the community area in which the crime occurred. Since the 1920s, Chicago has been divided into what are called “community areas”, of which there are now 77. The community areas were devised in an attempt to create socially homogeneous regions.
- Year: the year in which the crime occurred.
- Latitude: the latitude of the location at which the crime occurred.
- Longitude: the longitude of the location at which the crime occurred.
My Solutions
Problem 1
Problem 1: Loading the Data
1.1)
Read the dataset mvtWeek1.csv into R, using the read.csv function, and call the data frame mvt. Remember to navigate to the directory on your computer containing the file mvtWeek1.csv first. It may take a few minutes to read in the data, since it is pretty large. Then, use the str and summary functions to answer the following questions.
mvt <- read.csv('./Data/mvtWeek1.csv') %>% tbl_df()
summary(mvt)
str(mvt)
Question:
How many rows of data (observations) are in this dataset?
Answer:
There are 191641 observations in the mvt dataset.
1.2)
Question:
How many variables are in this dataset?
Answer:
There are 13 variable in the mvt dataset.
1.3)
Question:
Using the max function, what is the maximum value of the variable ID?
Answer:
The maximum value of the variable ID is 9181151.
1.4)
Question:
What is the minimum value of the variable Beat?
Answer:
The minimum value of the variable Beat is 111.
1.5)
Question:
How many observations have value TRUE in the Arrest variable (this is the number of crimes for which an arrest was made)?
Answer:
There are 15536 observations where mvt$Arrest == TRUE.
1.6)
Question:
How many observations have a LocationDescription value of “ALLEY”?
Answer:
There are 2308 observations where mvt$LocationDescription == 'ALLEY'.
Problem 2
Problem 2: Understanding Dates in R
2.1)
In many datasets, like this one, you have a date field. Unfortunately, R does not automatically recognize entries that look like dates. We need to use a function in R to extract the date and time. Take a look at the first entry of Date. Use square brackets when looking at a certain entry of a variable.
Question:
In what format are the entries in the variable Date?
- Month/Day/Year Hour:Minute - Day/Month/Year Hour:Minute - Hour:Minute Month/Day/Year - Hour:Minute Day/Month/Year
Answer:
mvt$Date is formatted as Month/Day/Year Hour:Minute
2.2)
Now, let’s convert the mvt$Date character vector into Date objects in R.
Take a look at the variable DateConvert using the summary() function.
Question:
What is the month and year of the median date in our dataset? Enter your answer as “Month Year”, without the quotes. (Ex: if the answer was 2008-03-28, you would give the answer “March 2008”, without the quotes.)
medianDate <- median(DateConvert)
answerMonthYear <- paste(months(medianDate), format(medianDate, '%Y'))
paste(medianDate, '->', answerMonthYear)
Answer:
The median date in the mvt dataset is May 2006.
2.3)
Now, let’s extract the month and the day of the week, and add these variables to mvt. We can do this with two simple functions.
This creates two new variables in our data frame, Month and Weekday, and sets them equal to the month and weekday values that we can extract from the Date object. Lastly, replace the old Date variable with DateConvert by typing:
Using the table() function, answer the following questions.
Question:
In which month did the fewest motor vehicle thefts occur?
Answer:
The fewest motor vehicle thefts occured in February.
2.4)
Question:
On which weekday did the most motor vehicle thefts occur?
Answer:
Most motor vehicle thefts occured on Friday.
2.5)
Each observation in the dataset represents a motor vehicle theft, and the Arrest variable indicates whether an arrest was later made for this theft.
Question:
Which month has the largest number of motor vehicle thefts for which an arrest was made?
Answer:
The greatest number of arrests made for motor vehicle thefts occured in January.
Problem 3
Problem 3: Visualizing Crime Trends
3.1)
Now, let’s make some plots to help us better understand how crime has changed over time in Chicago. Throughout this problem, and in general, you can save your plot to a file. For more information, this website very clearly explains the process.
First, let’s make a histogram of the variable Date. We’ll add an extra argument, to specify the number of bars we want in our histogram. In your R console, type:
hist(mvt$Date, breaks=100)
Looking at the histogram, answer the following questions.
Question:
In general, does it look like crime increases or decreases from 2002 - 2012?
Answer:
Crime appears to decrease from 2002 - 2012.
Question:
In general, does it look like crime increases or decreases from 2005 - 2008?
Answer:
Crime appears to decrease from 2005 - 2008.
Question:
In general, does it look like crime increases or decreases from 2009 - 2011?
Answer:
Crime appears to increase from 2009 - 2011.
3.2)
Now, let’s see how arrests have changed over time. Create a boxplot of the variable Date, sorted by the variable Arrest (if you are not familiar with boxplots and would like to learn more, check out this tutorial).
mvt %>%
ggplot(aes(x=Arrest, y=Date, fill=Arrest)) +
coord_flip() +
scale_fill_brewer(palette="Dark2") +
theme(legend.position="none") +
labs(title='Frequency of Arrests Over Time', x='Arrest Made', y='Year') +
geom_boxplot()
In a boxplot, the bold horizontal line is the median value of the data, the box shows the range of values between the first quartile and third quartile, and the whiskers (the dotted lines extending outside the box) show the minimum and maximum values, excluding any outliers (which are plotted as circles). Outliers are defined by first computing the difference between the first and third quartile values, or the height of the box. This number is called the Inter-Quartile Range (IQR). Any point that is greater than the third quartile plus the IQR or less than the first quartile minus the IQR is considered an outlier.
Question:
Does it look like there were more crimes for which arrests were made in the first half of the time period or the second half of the time period? (Note that the time period is from 2001 to 2012, so the middle of the time period is the beginning of 2007.)
Answer:
From the boxplot, we can deduce that there were more crimes for which arrests were made in the first half of the time period between 2001 to 2012.
3.3)
Let’s investigate this further. Use the table() function for the next few questions.
Note: in this question and many others in the course, we are asking for an answer as a proportion. Therefore, your answer should take a value between 0 and 1.
Question:
For what proportion of motor vehicle thefts in 2001 was an arrest made?
Answer:
An arrest was made in 0.1041173 of motor vehicle thefts during 2001.
3.4)
Question:
For what proportion of motor vehicle thefts in 2007 was an arrest made?
Answer:
An arrest was made in 0.0848739 of motor vehicle thefts during 2007.
3.5)
Question:
For what proportion of motor vehicle thefts in 2012 was an arrest made?
Answer:
An arrest was made in 0.0390292 of motor vehicle thefts during 2012.
Note: Since there may still be open investigations for recent crimes, this could explain the trend we are seeing in the data. There could also be other factors at play, and this trend should be investigated further. However, since we don’t know when the arrests were actually made, our detective work in this area has reached a dead end.
Problem 4
Problem 4: Popular Locations
4.1)
Analyzing this data could be useful to the Chicago Police Department when deciding where to allocate resources. If they want to increase the number of arrests that are made for motor vehicle thefts, where should they focus their efforts?
We want to find the top five locations where motor vehicle thefts occur. If you create a table of the LocationDescription variable, it is unfortunately very hard to read since there are 78 different locations in the data set. By using the sort function, we can view this same table, but sorted by the number of observations in each category. In your R console, type:
Question:
Which locations are the top five locations for motor vehicle thefts, excluding the “Other” category?
Answer:
Top five locations for motor vehicle theft (excluding “Other”):
1. STREET
2. PARKING LOT/GARAGE(NON.RESID.)
3. ALLEY
4. GAS STATION
5. DRIVEWAY - RESIDENTIAL
4.2)
Create a subset of your data, only taking observations for which the theft happened in one of these five locations, and call this new data set Top5.
Question:
How many observations are in Top5?
Answer:
There are 177510 observations in Top5.
4.3)
R will remember the other categories of the LocationDescription variable from the original dataset, so running table(Top5$LocationDescription) will have a lot of unnecessary output. To make our tables a bit nicer to read, we can refresh this factor variable. In your R console, type:
If you run the str() or table() function on Top5 now, you should see that LocationDescription now only has 5 values, as we expect.
Use the Top5 data frame to answer the remaining questions.
Question:
One of the locations has a much higher arrest rate than the other locations. Which is it?
Answer:
The LocationDescription of GAS STATION has a much higher arrest rate than the other locations.
4.4)
Question:
On which day of the week do the most motor vehicle thefts at gas stations happen?
Answer:
Most motor vehicle thefts at gas stations happen on Saturday.
4.5)
Question:
On which day of the week do the fewest motor vehicle thefts in residential driveways happen?
Answer:
The fewest instances of motor vehicle theft in residential driveways occur on Saturday.
LS0tDQp0aXRsZTogJ0Fzc2lnbm1lbnQgMUE6IEFuYWx5dGljcyBVc2luZyBSJw0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZm9sZGluZzogbm9uZQ0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIGhpZ2hsaWdodDogcHlnbWVudHMNCiAgICB0aGVtZTogZmxhdGx5DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoDQoJZWNobyA9IFRSVUUsDQoJbWVzc2FnZSA9IEZBTFNFLA0KCXdhcm5pbmcgPSBGQUxTRQ0KKQ0KcmVxdWlyZShnckRldmljZXMpDQpyZXF1aXJlKGdyYXBoaWNzKQ0KbGlicmFyeShybWFya2Rvd24pDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkoZ2dwbG90MikNCnRvVmFyIDwtIGZ1bmN0aW9uKHgsIG5hbWUpIHthc3NpZ24oYXMuY2hhcmFjdGVyKHN1YnN0aXR1dGUobmFtZSkpLCB4LCBwb3MgPSAxKX0NCmBgYA0KIyB7LnRhYnNldCAudGFic2V0LWZhZGV9ICANCg0KIyMgTGFiIE92ZXJ2aWV3DQojIyMgQW5hbHl6aW5nIENyaW1lIGluIENoaWNhZ28NCg0KQ3JpbWUgaXMgYW4gaW50ZXJuYXRpb25hbCBjb25jZXJuLCBidXQgaXQgaXMgZG9jdW1lbnRlZCBhbmQgaGFuZGxlZCBpbiB2ZXJ5IGRpZmZlcmVudCB3YXlzIGluIGRpZmZlcmVudCBjb3VudHJpZXMuIEluIHRoZSBVbml0ZWQgU3RhdGVzLCB2aW9sZW50IGNyaW1lcyBhbmQgcHJvcGVydHkgY3JpbWVzIGFyZSByZWNvcmRlZCBieSB0aGUgRmVkZXJhbCBCdXJlYXUgb2YgSW52ZXN0aWdhdGlvbiAoRkJJKS4gQWRkaXRpb25hbGx5LCBlYWNoIGNpdHkgZG9jdW1lbnRzIGNyaW1lLCBhbmQgc29tZSBjaXRpZXMgcmVsZWFzZSBkYXRhIHJlZ2FyZGluZyBjcmltZSByYXRlcy4gVGhlIGNpdHkgb2YgQ2hpY2FnbywgSWxsaW5vaXMgcmVsZWFzZXMgY3JpbWUgZGF0YSBmcm9tIDIwMDEgb253YXJkIFtvbmxpbmUuXShodHRwczovL2RhdGEuY2l0eW9mY2hpY2Fnby5vcmcvUHVibGljLVNhZmV0eS9DcmltZXMtMjAwMS10by1wcmVzZW50L2lqenAtcTh0MikNCg0KQ2hpY2FnbyBpcyB0aGUgdGhpcmQgbW9zdCBwb3B1bG91cyBjaXR5IGluIHRoZSBVbml0ZWQgU3RhdGVzLCB3aXRoIGEgcG9wdWxhdGlvbiBvZiBvdmVyIDIuNyBtaWxsaW9uIHBlb3BsZS4gVGhlIGNpdHkgb2YgQ2hpY2FnbyBpcyBzaG93biBpbiB0aGUgbWFwIGJlbG93LCB3aXRoIHRoZSBzdGF0ZSBvZiBJbGxpbm9pcyBoaWdobGlnaHRlZCBpbiByZWQuIA0KDQohW10oLi9JbWFnZXMvQ2hpY2Fnb01hcC5wbmcpDQoNClRoZXJlIGFyZSB0d28gbWFpbiB0eXBlcyBvZiBjcmltZXM6IHZpb2xlbnQgY3JpbWVzLCBhbmQgcHJvcGVydHkgY3JpbWVzLiBJbiB0aGlzIHByb2JsZW0sIHdlJ2xsIGZvY3VzIG9uIG9uZSBzcGVjaWZpYyB0eXBlIG9mIHByb3BlcnR5IGNyaW1lLCBjYWxsZWQgIm1vdG9yIHZlaGljbGUgdGhlZnQiIChzb21ldGltZXMgcmVmZXJyZWQgdG8gYXMgZ3JhbmQgdGhlZnQgYXV0bykuIFRoaXMgaXMgdGhlIGFjdCBvZiBzdGVhbGluZywgb3IgYXR0ZW1wdGluZyB0byBzdGVhbCwgYSBjYXIuIEluIHRoaXMgcHJvYmxlbSwgd2UnbGwgdXNlIHNvbWUgYmFzaWMgZGF0YSBhbmFseXNpcyBpbiBSIHRvIHVuZGVyc3RhbmQgdGhlIG1vdG9yIHZlaGljbGUgdGhlZnRzIGluIENoaWNhZ28uIA0KDQojIyMgQ3JpbWUgRGF0YQ0KDQpQbGVhc2UgZG93bmxvYWQgdGhlIGZpbGUgW212dFdlZWsxLmNzdl0oLi9EYXRhL212dFdlZWsxLmNzdikgZm9yIHRoaXMgcHJvYmxlbSAoZG8gbm90IG9wZW4gdGhpcyBmaWxlIGluIGFueSBzcHJlYWRzaGVldCBzb2Z0d2FyZSBiZWZvcmUgY29tcGxldGluZyB0aGlzIHByb2JsZW0gYmVjYXVzZSBpdCBtaWdodCBjaGFuZ2UgdGhlIGZvcm1hdCBvZiB0aGUgRGF0ZSBmaWVsZCkuIA0KDQpIZXJlIGlzIGEgbGlzdCBvZiBkZXNjcmlwdGlvbnMgb2YgdGhlIHZhcmlhYmxlczoNCg0KLSAqKklEKio6IGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIGVhY2ggb2JzZXJ2YXRpb24NCi0gKipEYXRlKio6IHRoZSBkYXRlIHRoZSBjcmltZSBvY2N1cnJlZA0KLSAqKkxvY2F0aW9uRGVzY3JpcHRpb24qKjogdGhlIGxvY2F0aW9uIHdoZXJlIHRoZSBjcmltZSBvY2N1cnJlZA0KLSAqKkFycmVzdCoqOiB3aGV0aGVyIG9yIG5vdCBhbiBhcnJlc3Qgd2FzIG1hZGUgZm9yIHRoZSBjcmltZSAoYFRSVUVgIGlmIGFuIGFycmVzdCB3YXMgbWFkZSwgYW5kIGBGQUxTRWAgaWYgYW4gYXJyZXN0IHdhcyBub3QgbWFkZSkNCi0gKipEb21lc3RpYyoqOiB3aGV0aGVyIG9yIG5vdCB0aGUgY3JpbWUgd2FzIGEgZG9tZXN0aWMgY3JpbWUsIG1lYW5pbmcgdGhhdCBpdCB3YXMgY29tbWl0dGVkIGFnYWluc3QgYSBmYW1pbHkgbWVtYmVyIChgVFJVRWAgaWYgaXQgd2FzIGRvbWVzdGljLCBhbmQgYEZBTFNFYCBpZiBpdCB3YXMgbm90IGRvbWVzdGljKQ0KLSAqKkJlYXQqKjogdGhlIGFyZWEsIG9yICJiZWF0IiBpbiB3aGljaCB0aGUgY3JpbWUgb2NjdXJyZWQuIFRoaXMgaXMgdGhlIHNtYWxsZXN0IHJlZ2lvbmFsIGRpdmlzaW9uIGRlZmluZWQgYnkgdGhlIENoaWNhZ28gcG9saWNlIGRlcGFydG1lbnQuDQotICoqRGlzdHJpY3QqKjogdGhlIHBvbGljZSBkaXN0cmljdCBpbiB3aGljaCB0aGUgY3JpbWUgb2NjdXJlZC4gRWFjaCBkaXN0cmljdCBpcyBjb21wb3NlZCBvZiBtYW55IGJlYXRzLCBhbmQgYXJlIGRlZmluZWQgYnkgdGhlIENoaWNhZ28gUG9saWNlIERlcGFydG1lbnQuDQotICoqQ29tbXVuaXR5QXJlYSoqOiB0aGUgY29tbXVuaXR5IGFyZWEgaW4gd2hpY2ggdGhlIGNyaW1lIG9jY3VycmVkLiBTaW5jZSB0aGUgMTkyMHMsIENoaWNhZ28gaGFzIGJlZW4gZGl2aWRlZCBpbnRvIHdoYXQgYXJlIGNhbGxlZCAiY29tbXVuaXR5IGFyZWFzIiwgb2Ygd2hpY2ggdGhlcmUgYXJlIG5vdyA3Ny4gVGhlIGNvbW11bml0eSBhcmVhcyB3ZXJlIGRldmlzZWQgaW4gYW4gYXR0ZW1wdCB0byBjcmVhdGUgc29jaWFsbHkgaG9tb2dlbmVvdXMgcmVnaW9ucy4NCi0gKipZZWFyKio6IHRoZSB5ZWFyIGluIHdoaWNoIHRoZSBjcmltZSBvY2N1cnJlZC4NCi0gKipMYXRpdHVkZSoqOiB0aGUgbGF0aXR1ZGUgb2YgdGhlIGxvY2F0aW9uIGF0IHdoaWNoIHRoZSBjcmltZSBvY2N1cnJlZC4NCi0gKipMb25naXR1ZGUqKjogdGhlIGxvbmdpdHVkZSBvZiB0aGUgbG9jYXRpb24gYXQgd2hpY2ggdGhlIGNyaW1lIG9jY3VycmVkLg0KDQojIyBNeSBTb2x1dGlvbnMgIHsudGFic2V0IC50YWJzZXQtZmFkZX0gIA0KDQojIyMgUHJvYmxlbSAxICANCg0KIyMjIyAqKlByb2JsZW0gMTogTG9hZGluZyB0aGUgRGF0YSoqIA0KDQojIyMjICoqMS4xKSoqIA0KUmVhZCB0aGUgZGF0YXNldCBbbXZ0V2VlazEuY3N2XSguL0RhdGEvbXZ0V2VlazEuY3N2KSBpbnRvIFIsIHVzaW5nIHRoZSByZWFkLmNzdiBmdW5jdGlvbiwgYW5kIGNhbGwgdGhlIGRhdGEgZnJhbWUgYG12dGAuIFJlbWVtYmVyIHRvIG5hdmlnYXRlIHRvIHRoZSBkaXJlY3Rvcnkgb24geW91ciBjb21wdXRlciBjb250YWluaW5nIHRoZSBmaWxlIGBtdnRXZWVrMS5jc3ZgIGZpcnN0LiBJdCBtYXkgdGFrZSBhIGZldyBtaW51dGVzIHRvIHJlYWQgaW4gdGhlIGRhdGEsIHNpbmNlIGl0IGlzIHByZXR0eSBsYXJnZS4gVGhlbiwgdXNlIHRoZSBzdHIgYW5kIHN1bW1hcnkgZnVuY3Rpb25zIHRvIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9ucy4gIA0KYGBge3IgcmVzdWx0cz0naGlkZSd9DQptdnQgIDwtIHJlYWQuY3N2KCcuL0RhdGEvbXZ0V2VlazEuY3N2JykgJT4lIHRibF9kZigpDQpzdW1tYXJ5KG12dCkNCnN0cihtdnQpDQpgYGANCg0KIyMjIyMgKipRdWVzdGlvbjoqKiANCkhvdyBtYW55IHJvd3Mgb2YgZGF0YSAob2JzZXJ2YXRpb25zKSBhcmUgaW4gdGhpcyBkYXRhc2V0PyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm5yb3cobXZ0KQ0KYGBgICANCg0KIyMjIyMgKipBbnN3ZXI6KiogIA0KVGhlcmUgYXJlICoqYHIgbnJvdyhtdnQpYCoqIG9ic2VydmF0aW9ucyBpbiB0aGUgYG12dGAgZGF0YXNldC4NCg0KKioqICANCg0KIyMjIyAqKjEuMikqKiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpIb3cgbWFueSB2YXJpYWJsZXMgYXJlIGluIHRoaXMgZGF0YXNldD8gIA0KYGBge3IgcmVzdWx0cz0naGlkZSd9DQpuY29sKG12dCkNCmBgYCAgDQojIyMjIyAqKkFuc3dlcjoqKiAgDQpUaGVyZSBhcmUgKipgciBuY29sKG12dClgKiogdmFyaWFibGUgaW4gdGhlIGBtdnRgIGRhdGFzZXQuDQoNCioqKiAgDQoNCiMjIyMgKioxLjMpKiogIA0KDQojIyMjIyAqKlF1ZXN0aW9uOioqIA0KVXNpbmcgdGhlIGBtYXhgIGZ1bmN0aW9uLCB3aGF0IGlzIHRoZSBtYXhpbXVtIHZhbHVlIG9mIHRoZSB2YXJpYWJsZSBgSURgPyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm1heChtdnQkSUQpDQpgYGAgIA0KIyMjIyMgKipBbnN3ZXI6KiogIA0KVGhlIG1heGltdW0gdmFsdWUgb2YgdGhlIHZhcmlhYmxlIGBJRGAgaXMgKipgciBtYXgobXZ0JElEKWAqKi4gIA0KDQoqKiogIA0KDQojIyMjICoqMS40KSoqICANCg0KIyMjIyMgKipRdWVzdGlvbjoqKiANCldoYXQgaXMgdGhlIG1pbmltdW0gdmFsdWUgb2YgdGhlIHZhcmlhYmxlIGBCZWF0YD8gIA0KYGBge3IgcmVzdWx0cz0naGlkZSd9DQptaW4obXZ0JEJlYXQpDQpgYGAgIA0KIyMjIyMgKipBbnN3ZXI6KiogIA0KVGhlIG1pbmltdW0gdmFsdWUgb2YgdGhlIHZhcmlhYmxlIGBCZWF0YCBpcyAqKmByIG1pbihtdnQkQmVhdClgKiouICANCg0KKioqICANCg0KIyMjIyAqKjEuNSkqKiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpIb3cgbWFueSBvYnNlcnZhdGlvbnMgaGF2ZSB2YWx1ZSBgVFJVRWAgaW4gdGhlIGBBcnJlc3RgIHZhcmlhYmxlICh0aGlzIGlzIHRoZSBudW1iZXIgb2YgY3JpbWVzIGZvciB3aGljaCBhbiBhcnJlc3Qgd2FzIG1hZGUpPyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCnN1bShtdnQkQXJyZXN0PT1UUlVFKQ0KYGBgICANCiMjIyMjICoqQW5zd2VyOioqICANClRoZXJlIGFyZSAqKmByIHN1bShtdnQkQXJyZXN0PT1UUlVFKWAqKiBvYnNlcnZhdGlvbnMgd2hlcmUgYG12dCRBcnJlc3QgPT0gVFJVRWAuICANCg0KKioqICANCg0KIyMjIyAqKjEuNikqKiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpIb3cgbWFueSBvYnNlcnZhdGlvbnMgaGF2ZSBhIGBMb2NhdGlvbkRlc2NyaXB0aW9uYCB2YWx1ZSBvZiAiQUxMRVkiPyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCnN1bShtdnQkTG9jYXRpb25EZXNjcmlwdGlvbj09J0FMTEVZJykNCmBgYCAgDQojIyMjIyAqKkFuc3dlcjoqKiAgDQpUaGVyZSBhcmUgKipgciBzdW0obXZ0JExvY2F0aW9uRGVzY3JpcHRpb249PSdBTExFWScpYCoqIG9ic2VydmF0aW9ucyB3aGVyZSBgbXZ0JExvY2F0aW9uRGVzY3JpcHRpb24gPT0gJ0FMTEVZJ2AuICANCg0KKioqICANCiMjIyBQcm9ibGVtIDIgIA0KIyMjIyAqKlByb2JsZW0gMjogVW5kZXJzdGFuZGluZyBEYXRlcyBpbiBSKiogIA0KIyMjIyAqKjIuMSkqKiAgDQpJbiBtYW55IGRhdGFzZXRzLCBsaWtlIHRoaXMgb25lLCB5b3UgaGF2ZSBhIGRhdGUgZmllbGQuIFVuZm9ydHVuYXRlbHksIFIgZG9lcyBub3QgYXV0b21hdGljYWxseSByZWNvZ25pemUgZW50cmllcyB0aGF0IGxvb2sgbGlrZSBkYXRlcy4gV2UgbmVlZCB0byB1c2UgYSBmdW5jdGlvbiBpbiBSIHRvIGV4dHJhY3QgdGhlIGRhdGUgYW5kIHRpbWUuIFRha2UgYSBsb29rIGF0IHRoZSBmaXJzdCBlbnRyeSBvZiBgRGF0ZWAuIFVzZSBzcXVhcmUgYnJhY2tldHMgd2hlbiBsb29raW5nIGF0IGEgY2VydGFpbiBlbnRyeSBvZiBhIHZhcmlhYmxlLiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpJbiB3aGF0IGZvcm1hdCBhcmUgdGhlIGVudHJpZXMgaW4gdGhlIHZhcmlhYmxlIERhdGU/ICANCi0gKipNb250aC9EYXkvWWVhciBIb3VyOk1pbnV0ZSoqDQotIERheS9Nb250aC9ZZWFyIEhvdXI6TWludXRlDQotIEhvdXI6TWludXRlIE1vbnRoL0RheS9ZZWFyDQotIEhvdXI6TWludXRlIERheS9Nb250aC9ZZWFyICANCg0KIyMjIyMgKipBbnN3ZXI6KiogIA0KbXZ0JERhdGUgaXMgZm9ybWF0dGVkIGFzICoqTW9udGgvRGF5L1llYXIgSG91cjpNaW51dGUqKiAgDQoNCioqKiAgDQoNCiMjIyMgKioyLjIpKiogIA0KTm93LCBsZXQncyBjb252ZXJ0IHRoZSBgbXZ0JERhdGVgIGNoYXJhY3RlciB2ZWN0b3IgaW50byBgRGF0ZWAgb2JqZWN0cyBpbiBSLiAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCkRhdGVDb252ZXJ0ICA8LSAgYXMuRGF0ZShzdHJwdGltZShtdnQkRGF0ZSwgIiVtLyVkLyV5ICVIOiVNIikpDQpgYGANCg0KVGFrZSBhIGxvb2sgYXQgdGhlIHZhcmlhYmxlIGBEYXRlQ29udmVydGAgdXNpbmcgdGhlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uLiAgDQpgYGB7ciByZXN1bHRzPSdtYXJrdXAnfQ0Kc3VtbWFyeShEYXRlQ29udmVydCkNCmBgYA0KDQojIyMjIyAqKlF1ZXN0aW9uOioqIA0KV2hhdCBpcyB0aGUgbW9udGggYW5kIHllYXIgb2YgdGhlIG1lZGlhbiBkYXRlIGluIG91ciBkYXRhc2V0PyBFbnRlciB5b3VyIGFuc3dlciBhcyAiTW9udGggWWVhciIsIHdpdGhvdXQgdGhlIHF1b3Rlcy4gKEV4OiBpZiB0aGUgYW5zd2VyIHdhcyAyMDA4LTAzLTI4LCB5b3Ugd291bGQgZ2l2ZSB0aGUgYW5zd2VyICJNYXJjaCAyMDA4Iiwgd2l0aG91dCB0aGUgcXVvdGVzLikgIA0KYGBge3IgcmVzdWx0cz0nbWFya3VwJ30NCm1lZGlhbkRhdGUgPC0gbWVkaWFuKERhdGVDb252ZXJ0KQ0KYW5zd2VyTW9udGhZZWFyIDwtIHBhc3RlKG1vbnRocyhtZWRpYW5EYXRlKSwgZm9ybWF0KG1lZGlhbkRhdGUsICclWScpKQ0KcGFzdGUobWVkaWFuRGF0ZSwgJy0+JywgYW5zd2VyTW9udGhZZWFyKQ0KYGBgICANCiMjIyMjICoqQW5zd2VyOioqICANClRoZSBtZWRpYW4gZGF0ZSBpbiB0aGUgYG12dGAgZGF0YXNldCBpcyAqKmByIGFuc3dlck1vbnRoWWVhcmAqKi4gIA0KDQoqKiogIA0KDQojIyMjICoqMi4zKSoqICANCk5vdywgbGV0J3MgZXh0cmFjdCB0aGUgbW9udGggYW5kIHRoZSBkYXkgb2YgdGhlIHdlZWssIGFuZCBhZGQgdGhlc2UgdmFyaWFibGVzIHRvIGBtdnRgLiBXZSBjYW4gZG8gdGhpcyB3aXRoIHR3byBzaW1wbGUgZnVuY3Rpb25zLg0KDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm12dCRNb250aCA8LSBtb250aHMoRGF0ZUNvbnZlcnQpDQptdnQkV2Vla2RheSA8LSB3ZWVrZGF5cyhEYXRlQ29udmVydCkNCmBgYA0KDQpUaGlzIGNyZWF0ZXMgdHdvIG5ldyB2YXJpYWJsZXMgaW4gb3VyIGRhdGEgZnJhbWUsIGBNb250aGAgYW5kIGBXZWVrZGF5YCwgYW5kIHNldHMgdGhlbSBlcXVhbCB0byB0aGUgbW9udGggYW5kIHdlZWtkYXkgdmFsdWVzIHRoYXQgd2UgY2FuIGV4dHJhY3QgZnJvbSB0aGUgRGF0ZSBvYmplY3QuIExhc3RseSwgcmVwbGFjZSB0aGUgb2xkIGBEYXRlYCB2YXJpYWJsZSB3aXRoIGBEYXRlQ29udmVydGAgYnkgdHlwaW5nOg0KDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm12dCREYXRlIDwtIERhdGVDb252ZXJ0DQpgYGANCg0KVXNpbmcgdGhlIGB0YWJsZSgpYCBmdW5jdGlvbiwgYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zLiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpJbiB3aGljaCBtb250aCBkaWQgdGhlIGZld2VzdCBtb3RvciB2ZWhpY2xlIHRoZWZ0cyBvY2N1cj8NCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQ0KbXZ0JE1vbnRoICU+JQ0KICB0YWJsZSgpICU+JSANCiAgd2hpY2gubWluKCkgJT4lIA0KICBuYW1lcygpIC0+IEFuc3dlcl8yLjMgDQpgYGAgIA0KIyMjIyMgKipBbnN3ZXI6KiogIA0KVGhlIGZld2VzdCBtb3RvciB2ZWhpY2xlIHRoZWZ0cyBvY2N1cmVkIGluICoqYHIgQW5zd2VyXzIuM2AqKi4gIA0KDQoqKiogIA0KDQojIyMjICoqMi40KSoqICANCg0KIyMjIyMgKipRdWVzdGlvbjoqKiANCk9uIHdoaWNoIHdlZWtkYXkgZGlkIHRoZSBtb3N0IG1vdG9yIHZlaGljbGUgdGhlZnRzIG9jY3VyPyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm12dCRXZWVrZGF5ICU+JQ0KICB0YWJsZSgpICU+JQ0KICB3aGljaC5tYXgoKSAlPiUNCiAgbmFtZXMoKSAtPiBBbnN3ZXJfMi40DQpgYGAgIA0KIyMjIyMgKipBbnN3ZXI6KiogIA0KTW9zdCBtb3RvciB2ZWhpY2xlIHRoZWZ0cyBvY2N1cmVkIG9uICoqYHIgQW5zd2VyXzIuNGAqKi4gIA0KDQoqKiogIA0KDQojIyMjICoqMi41KSoqICANCkVhY2ggb2JzZXJ2YXRpb24gaW4gdGhlIGRhdGFzZXQgcmVwcmVzZW50cyBhIG1vdG9yIHZlaGljbGUgdGhlZnQsIGFuZCB0aGUgQXJyZXN0IHZhcmlhYmxlIGluZGljYXRlcyB3aGV0aGVyIGFuIGFycmVzdCB3YXMgbGF0ZXIgbWFkZSBmb3IgdGhpcyB0aGVmdC4gIA0KDQojIyMjIyAqKlF1ZXN0aW9uOioqIA0KV2hpY2ggbW9udGggaGFzIHRoZSBsYXJnZXN0IG51bWJlciBvZiBtb3RvciB2ZWhpY2xlIHRoZWZ0cyBmb3Igd2hpY2ggYW4gYXJyZXN0IHdhcyBtYWRlPyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm12dCAlPiUNCiAgZmlsdGVyKEFycmVzdD09VCkgJT4lDQogIHNlbGVjdChNb250aCkgJT4lDQogIHRhYmxlKCkgJT4lDQogIHdoaWNoLm1heCgpICU+JSBuYW1lcygpIC0+IEFuc3dlcl8yLjUgDQpgYGAgIA0KIyMjIyMgKipBbnN3ZXI6KiogIA0KVGhlIGdyZWF0ZXN0IG51bWJlciBvZiBhcnJlc3RzIG1hZGUgZm9yIG1vdG9yIHZlaGljbGUgdGhlZnRzIG9jY3VyZWQgaW4gKipgciBBbnN3ZXJfMi41YCoqLiAgDQoNCioqKiAgDQojIyMgUHJvYmxlbSAzICANCiMjIyMgKipQcm9ibGVtIDM6IFZpc3VhbGl6aW5nIENyaW1lIFRyZW5kcyoqDQoNCiMjIyMgKiozLjEpKiogIA0KTm93LCBsZXQncyBtYWtlIHNvbWUgcGxvdHMgdG8gaGVscCB1cyBiZXR0ZXIgdW5kZXJzdGFuZCBob3cgY3JpbWUgaGFzIGNoYW5nZWQgb3ZlciB0aW1lIGluIENoaWNhZ28uIFRocm91Z2hvdXQgdGhpcyBwcm9ibGVtLCBhbmQgaW4gZ2VuZXJhbCwgeW91IGNhbiBzYXZlIHlvdXIgcGxvdCB0byBhIGZpbGUuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBbdGhpcyB3ZWJzaXRlXShodHRwOi8vd3d3LnN0YXQuYmVya2VsZXkuZWR1L35zMTMzL3NhdmluZy5odG1sKSB2ZXJ5IGNsZWFybHkgZXhwbGFpbnMgdGhlIHByb2Nlc3MuDQoNCkZpcnN0LCBsZXQncyBtYWtlIGEgaGlzdG9ncmFtIG9mIHRoZSB2YXJpYWJsZSBEYXRlLiBXZSdsbCBhZGQgYW4gZXh0cmEgYXJndW1lbnQsIHRvIHNwZWNpZnkgdGhlIG51bWJlciBvZiBiYXJzIHdlIHdhbnQgaW4gb3VyIGhpc3RvZ3JhbS4gSW4geW91ciBSIGNvbnNvbGUsIHR5cGU6DQoNCmBgYHtyfQ0KaGlzdChtdnQkRGF0ZSwgYnJlYWtzPTEwMCkNCmBgYA0KDQpMb29raW5nIGF0IHRoZSBoaXN0b2dyYW0sIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9ucy4gIA0KDQojIyMjIyAqKlF1ZXN0aW9uOioqIA0KSW4gZ2VuZXJhbCwgZG9lcyBpdCBsb29rIGxpa2UgY3JpbWUgaW5jcmVhc2VzIG9yIGRlY3JlYXNlcyBmcm9tIDIwMDIgLSAyMDEyPyAgDQoNCiMjIyMjICoqQW5zd2VyOioqICANCkNyaW1lIGFwcGVhcnMgdG8gKipkZWNyZWFzZSoqIGZyb20gMjAwMiAtIDIwMTIuDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpJbiBnZW5lcmFsLCBkb2VzIGl0IGxvb2sgbGlrZSBjcmltZSBpbmNyZWFzZXMgb3IgZGVjcmVhc2VzIGZyb20gMjAwNSAtIDIwMDg/ICANCg0KIyMjIyMgKipBbnN3ZXI6KiogIA0KQ3JpbWUgYXBwZWFycyB0byAqKmRlY3JlYXNlKiogZnJvbSAyMDA1IC0gMjAwOC4gIA0KDQojIyMjIyAqKlF1ZXN0aW9uOioqIA0KSW4gZ2VuZXJhbCwgZG9lcyBpdCBsb29rIGxpa2UgY3JpbWUgaW5jcmVhc2VzIG9yIGRlY3JlYXNlcyBmcm9tIDIwMDkgLSAyMDExPyAgDQoNCiMjIyMjICoqQW5zd2VyOioqICANCkNyaW1lIGFwcGVhcnMgdG8gKippbmNyZWFzZSoqIGZyb20gMjAwOSAtIDIwMTEuICANCg0KKioqICANCg0KIyMjIyAqKjMuMikqKiAgDQpOb3csIGxldCdzIHNlZSBob3cgYXJyZXN0cyBoYXZlIGNoYW5nZWQgb3ZlciB0aW1lLiBDcmVhdGUgYSBib3hwbG90IG9mIHRoZSB2YXJpYWJsZSBgRGF0ZWAsIHNvcnRlZCBieSB0aGUgdmFyaWFibGUgYEFycmVzdGAgKGlmIHlvdSBhcmUgbm90IGZhbWlsaWFyIHdpdGggYm94cGxvdHMgYW5kIHdvdWxkIGxpa2UgdG8gbGVhcm4gbW9yZSwgY2hlY2sgb3V0IHRoaXMgW3R1dG9yaWFsXShodHRwOi8vd3d3LnItYmxvZ2dlcnMuY29tL2JveC1wbG90LXdpdGgtci10dXRvcmlhbC8pKS4gDQoNCmBgYHtyfQ0KbXZ0ICU+JQ0KICBnZ3Bsb3QoYWVzKHg9QXJyZXN0LCB5PURhdGUsIGZpbGw9QXJyZXN0KSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKw0KICBsYWJzKHRpdGxlPSdGcmVxdWVuY3kgb2YgQXJyZXN0cyBPdmVyIFRpbWUnLCB4PSdBcnJlc3QgTWFkZScsIHk9J1llYXInKSArDQogIGdlb21fYm94cGxvdCgpDQpgYGANCg0KSW4gYSBib3hwbG90LCB0aGUgYm9sZCBob3Jpem9udGFsIGxpbmUgaXMgdGhlIG1lZGlhbiB2YWx1ZSBvZiB0aGUgZGF0YSwgdGhlIGJveCBzaG93cyB0aGUgcmFuZ2Ugb2YgdmFsdWVzIGJldHdlZW4gdGhlIGZpcnN0IHF1YXJ0aWxlIGFuZCB0aGlyZCBxdWFydGlsZSwgYW5kIHRoZSB3aGlza2VycyAodGhlIGRvdHRlZCBsaW5lcyBleHRlbmRpbmcgb3V0c2lkZSB0aGUgYm94KSBzaG93IHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlcywgZXhjbHVkaW5nIGFueSBvdXRsaWVycyAod2hpY2ggYXJlIHBsb3R0ZWQgYXMgY2lyY2xlcykuIE91dGxpZXJzIGFyZSBkZWZpbmVkIGJ5IGZpcnN0IGNvbXB1dGluZyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBmaXJzdCBhbmQgdGhpcmQgcXVhcnRpbGUgdmFsdWVzLCBvciB0aGUgaGVpZ2h0IG9mIHRoZSBib3guIFRoaXMgbnVtYmVyIGlzIGNhbGxlZCB0aGUgSW50ZXItUXVhcnRpbGUgUmFuZ2UgKElRUikuIEFueSBwb2ludCB0aGF0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgdGhpcmQgcXVhcnRpbGUgcGx1cyB0aGUgSVFSIG9yIGxlc3MgdGhhbiB0aGUgZmlyc3QgcXVhcnRpbGUgbWludXMgdGhlIElRUiBpcyBjb25zaWRlcmVkIGFuIG91dGxpZXIuICANCg0KIyMjIyMgKipRdWVzdGlvbjoqKiANCkRvZXMgaXQgbG9vayBsaWtlIHRoZXJlIHdlcmUgbW9yZSBjcmltZXMgZm9yIHdoaWNoIGFycmVzdHMgd2VyZSBtYWRlIGluIHRoZSBmaXJzdCBoYWxmIG9mIHRoZSB0aW1lIHBlcmlvZCBvciB0aGUgc2Vjb25kIGhhbGYgb2YgdGhlIHRpbWUgcGVyaW9kPyAoTm90ZSB0aGF0IHRoZSB0aW1lIHBlcmlvZCBpcyBmcm9tIDIwMDEgdG8gMjAxMiwgc28gdGhlIG1pZGRsZSBvZiB0aGUgdGltZSBwZXJpb2QgaXMgdGhlIGJlZ2lubmluZyBvZiAyMDA3LikgIA0KDQojIyMjIyAqKkFuc3dlcjoqKiAgDQpGcm9tIHRoZSBib3hwbG90LCB3ZSBjYW4gZGVkdWNlIHRoYXQgdGhlcmUgd2VyZSBtb3JlIGNyaW1lcyBmb3Igd2hpY2ggYXJyZXN0cyB3ZXJlIG1hZGUgaW4gdGhlICoqZmlyc3QgaGFsZiBvZiB0aGUgdGltZSBwZXJpb2QqKiBiZXR3ZWVuIDIwMDEgdG8gMjAxMi4NCg0KKioqICANCg0KIyMjIyAqKjMuMykqKiAgDQpMZXQncyBpbnZlc3RpZ2F0ZSB0aGlzIGZ1cnRoZXIuIFVzZSB0aGUgYHRhYmxlKClgIGZ1bmN0aW9uIGZvciB0aGUgbmV4dCBmZXcgcXVlc3Rpb25zLiANCg0KTm90ZTogaW4gdGhpcyBxdWVzdGlvbiBhbmQgbWFueSBvdGhlcnMgaW4gdGhlIGNvdXJzZSwgd2UgYXJlIGFza2luZyBmb3IgYW4gYW5zd2VyIGFzIGEgcHJvcG9ydGlvbi4gVGhlcmVmb3JlLCB5b3VyIGFuc3dlciBzaG91bGQgdGFrZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMS4NCg0KIyMjIyMgKipRdWVzdGlvbjoqKiANCkZvciB3aGF0IHByb3BvcnRpb24gb2YgbW90b3IgdmVoaWNsZSB0aGVmdHMgaW4gMjAwMSB3YXMgYW4gYXJyZXN0IG1hZGU/ICANCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQ0KQW5zd2VyXzMuMyA8LSANCiAgKHRhYmxlKG12dCRZZWFyW212dCRBcnJlc3Q9PVRdKS90YWJsZShtdnQkWWVhcikpWycyMDAxJ10NCmBgYCAgDQojIyMjIyAqKkFuc3dlcjoqKiAgDQpBbiBhcnJlc3Qgd2FzIG1hZGUgaW4gKipgciBBbnN3ZXJfMy4zYCoqIG9mIG1vdG9yIHZlaGljbGUgdGhlZnRzIGR1cmluZyAyMDAxLg0KDQoqKiogIA0KDQojIyMjICoqMy40KSoqICANCg0KIyMjIyMgKipRdWVzdGlvbjoqKiANCkZvciB3aGF0IHByb3BvcnRpb24gb2YgbW90b3IgdmVoaWNsZSB0aGVmdHMgaW4gMjAwNyB3YXMgYW4gYXJyZXN0IG1hZGU/ICANCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQ0KQW5zd2VyXzMuNCA8LSANCiAgKHRhYmxlKG12dCRZZWFyW212dCRBcnJlc3Q9PVRdKS90YWJsZShtdnQkWWVhcikpWycyMDA3J10NCmBgYCAgDQojIyMjIyAqKkFuc3dlcjoqKiAgDQpBbiBhcnJlc3Qgd2FzIG1hZGUgaW4gKipgciBBbnN3ZXJfMy40YCoqIG9mIG1vdG9yIHZlaGljbGUgdGhlZnRzIGR1cmluZyAyMDA3LiAgDQoNCioqKiAgDQoNCiMjIyMgKiozLjUpKiogIA0KDQojIyMjIyAqKlF1ZXN0aW9uOioqIA0KRm9yIHdoYXQgcHJvcG9ydGlvbiBvZiBtb3RvciB2ZWhpY2xlIHRoZWZ0cyBpbiAyMDEyIHdhcyBhbiBhcnJlc3QgbWFkZT8gIA0KYGBge3IgcmVzdWx0cz0naGlkZSd9DQpBbnN3ZXJfMy41IDwtIA0KICAodGFibGUobXZ0JFllYXJbbXZ0JEFycmVzdD09VF0pL3RhYmxlKG12dCRZZWFyKSlbJzIwMTInXQ0KYGBgICANCiMjIyMjICoqQW5zd2VyOioqICANCkFuIGFycmVzdCB3YXMgbWFkZSBpbiAqKmByIEFuc3dlcl8zLjVgKiogb2YgbW90b3IgdmVoaWNsZSB0aGVmdHMgZHVyaW5nIDIwMTIuICANCg0KTm90ZTogU2luY2UgdGhlcmUgbWF5IHN0aWxsIGJlIG9wZW4gaW52ZXN0aWdhdGlvbnMgZm9yIHJlY2VudCBjcmltZXMsIHRoaXMgY291bGQgZXhwbGFpbiB0aGUgdHJlbmQgd2UgYXJlIHNlZWluZyBpbiB0aGUgZGF0YS4gVGhlcmUgY291bGQgYWxzbyBiZSBvdGhlciBmYWN0b3JzIGF0IHBsYXksIGFuZCB0aGlzIHRyZW5kIHNob3VsZCBiZSBpbnZlc3RpZ2F0ZWQgZnVydGhlci4gSG93ZXZlciwgc2luY2Ugd2UgZG9uJ3Qga25vdyB3aGVuIHRoZSBhcnJlc3RzIHdlcmUgYWN0dWFsbHkgbWFkZSwgb3VyIGRldGVjdGl2ZSB3b3JrIGluIHRoaXMgYXJlYSBoYXMgcmVhY2hlZCBhIGRlYWQgZW5kLg0KDQoqKiogIA0KIyMjIFByb2JsZW0gNCAgDQojIyMjICoqUHJvYmxlbSA0OiBQb3B1bGFyIExvY2F0aW9ucyoqDQoNCiMjIyMgKio0LjEpKiogIA0KQW5hbHl6aW5nIHRoaXMgZGF0YSBjb3VsZCBiZSB1c2VmdWwgdG8gdGhlIENoaWNhZ28gUG9saWNlIERlcGFydG1lbnQgd2hlbiBkZWNpZGluZyB3aGVyZSB0byBhbGxvY2F0ZSByZXNvdXJjZXMuIElmIHRoZXkgd2FudCB0byBpbmNyZWFzZSB0aGUgbnVtYmVyIG9mIGFycmVzdHMgdGhhdCBhcmUgbWFkZSBmb3IgbW90b3IgdmVoaWNsZSB0aGVmdHMsIHdoZXJlIHNob3VsZCB0aGV5IGZvY3VzIHRoZWlyIGVmZm9ydHM/DQoNCldlIHdhbnQgdG8gZmluZCB0aGUgdG9wIGZpdmUgbG9jYXRpb25zIHdoZXJlIG1vdG9yIHZlaGljbGUgdGhlZnRzIG9jY3VyLiBJZiB5b3UgY3JlYXRlIGEgdGFibGUgb2YgdGhlIGBMb2NhdGlvbkRlc2NyaXB0aW9uYCB2YXJpYWJsZSwgaXQgaXMgdW5mb3J0dW5hdGVseSB2ZXJ5IGhhcmQgdG8gcmVhZCBzaW5jZSB0aGVyZSBhcmUgNzggZGlmZmVyZW50IGxvY2F0aW9ucyBpbiB0aGUgZGF0YSBzZXQuIEJ5IHVzaW5nIHRoZSBzb3J0IGZ1bmN0aW9uLCB3ZSBjYW4gdmlldyB0aGlzIHNhbWUgdGFibGUsIGJ1dCBzb3J0ZWQgYnkgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgaW4gZWFjaCBjYXRlZ29yeS4gSW4geW91ciBSIGNvbnNvbGUsIHR5cGU6DQoNCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQ0KbXZ0JExvY2F0aW9uRGVzY3JpcHRpb24gJT4lDQogIHRhYmxlKCkgJT4lIHNvcnQoKQ0KYGBgICANCg0KIyMjIyMgKipRdWVzdGlvbjoqKiANCldoaWNoIGxvY2F0aW9ucyBhcmUgdGhlIHRvcCBmaXZlIGxvY2F0aW9ucyBmb3IgbW90b3IgdmVoaWNsZSB0aGVmdHMsIGV4Y2x1ZGluZyB0aGUgIk90aGVyIiBjYXRlZ29yeT8gDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm12dCAlPiUNCiAgZmlsdGVyKExvY2F0aW9uRGVzY3JpcHRpb24hPSdPVEhFUicpICU+JQ0KICBzZWxlY3QoTG9jYXRpb25EZXNjcmlwdGlvbikgJT4lDQogIHRhYmxlKCkgJT4lIHNvcnQoZGVjcmVhc2luZz1UKSAlPiUgDQogIGhlYWQoNSkgJT4lIG5hbWVzKCkgLT4gQW5zd2VyXzQuMQ0KYGBgIA0KDQojIyMjIyAqKkFuc3dlcjoqKiAgDQpUb3AgZml2ZSBsb2NhdGlvbnMgZm9yIG1vdG9yIHZlaGljbGUgdGhlZnQgKGV4Y2x1ZGluZyAiT3RoZXIiKTogIA0KJm5ic3A7ICZuYnNwOyAxLiBgciBBbnN3ZXJfNC4xWzFdYCAgDQombmJzcDsgJm5ic3A7IDIuIGByIEFuc3dlcl80LjFbMl1gICANCiZuYnNwOyAmbmJzcDsgMy4gYHIgQW5zd2VyXzQuMVszXWAgIA0KJm5ic3A7ICZuYnNwOyA0LiBgciBBbnN3ZXJfNC4xWzRdYCAgDQombmJzcDsgJm5ic3A7IDUuIGByIEFuc3dlcl80LjFbNV1gICANCg0KKioqICANCg0KIyMjIyAqKjQuMikqKiAgDQpDcmVhdGUgYSBzdWJzZXQgb2YgeW91ciBkYXRhLCBvbmx5IHRha2luZyBvYnNlcnZhdGlvbnMgZm9yIHdoaWNoIHRoZSB0aGVmdCBoYXBwZW5lZCBpbiBvbmUgb2YgdGhlc2UgZml2ZSBsb2NhdGlvbnMsIGFuZCBjYWxsIHRoaXMgbmV3IGRhdGEgc2V0IGBUb3A1YC4gDQoNCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQ0KVG9wNSA8LSBmaWx0ZXIobXZ0LCBMb2NhdGlvbkRlc2NyaXB0aW9uICVpbiUgQW5zd2VyXzQuMSkNCmBgYA0KDQojIyMjIyAqKlF1ZXN0aW9uOioqIA0KSG93IG1hbnkgb2JzZXJ2YXRpb25zIGFyZSBpbiBUb3A1PyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCm5yb3coVG9wNSkNCmBgYCAgDQoNCiMjIyMjICoqQW5zd2VyOioqICANClRoZXJlIGFyZSAqKmByIG5yb3coVG9wNSlgKiogb2JzZXJ2YXRpb25zIGluIGBUb3A1YC4NCg0KKioqICANCg0KIyMjIyAqKjQuMykqKiAgDQpSIHdpbGwgcmVtZW1iZXIgdGhlIG90aGVyIGNhdGVnb3JpZXMgb2YgdGhlIGBMb2NhdGlvbkRlc2NyaXB0aW9uYCB2YXJpYWJsZSBmcm9tIHRoZSBvcmlnaW5hbCBkYXRhc2V0LCBzbyBydW5uaW5nIGB0YWJsZShUb3A1JExvY2F0aW9uRGVzY3JpcHRpb24pYCB3aWxsIGhhdmUgYSBsb3Qgb2YgdW5uZWNlc3Nhcnkgb3V0cHV0LiBUbyBtYWtlIG91ciB0YWJsZXMgYSBiaXQgbmljZXIgdG8gcmVhZCwgd2UgY2FuIHJlZnJlc2ggdGhpcyBmYWN0b3IgdmFyaWFibGUuIEluIHlvdXIgUiBjb25zb2xlLCB0eXBlOg0KDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NClRvcDUkTG9jYXRpb25EZXNjcmlwdGlvbiAlPD4lIGZhY3RvcigpDQpgYGANCg0KSWYgeW91IHJ1biB0aGUgYHN0cigpYCBvciBgdGFibGUoKWAgZnVuY3Rpb24gb24gYFRvcDVgIG5vdywgeW91IHNob3VsZCBzZWUgdGhhdCBgTG9jYXRpb25EZXNjcmlwdGlvbmAgbm93IG9ubHkgaGFzIDUgdmFsdWVzLCBhcyB3ZSBleHBlY3QuDQoNClVzZSB0aGUgYFRvcDVgIGRhdGEgZnJhbWUgdG8gYW5zd2VyIHRoZSByZW1haW5pbmcgcXVlc3Rpb25zLiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpPbmUgb2YgdGhlIGxvY2F0aW9ucyBoYXMgYSBtdWNoIGhpZ2hlciBhcnJlc3QgcmF0ZSB0aGFuIHRoZSBvdGhlciBsb2NhdGlvbnMuIFdoaWNoIGlzIGl0PyAgIA0KYGBge3IgcmVzdWx0cz0naGlkZSd9DQpUb3A1ICU+JQ0KICBmaWx0ZXIoQXJyZXN0PT1UKSAlJCUNCiAgc29ydCgNCiAgICB0YWJsZShMb2NhdGlvbkRlc2NyaXB0aW9uKS90YWJsZShUb3A1JExvY2F0aW9uRGVzY3JpcHRpb24pLCBkZWNyZWFzaW5nPVQpICU+JQ0KICBuYW1lcygpICU+JSBoZWFkKDEpIC0+IEFuc3dlcl80LjMNCmBgYCAgDQojIyMjIyAqKkFuc3dlcjoqKiAgDQpUaGUgYExvY2F0aW9uRGVzY3JpcHRpb25gIG9mICoqYHIgQW5zd2VyXzQuM2AqKiBoYXMgYSBtdWNoIGhpZ2hlciBhcnJlc3QgcmF0ZSB0aGFuIHRoZSBvdGhlciBsb2NhdGlvbnMuICANCg0KKioqICANCg0KIyMjIyAqKjQuNCkqKiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpPbiB3aGljaCBkYXkgb2YgdGhlIHdlZWsgZG8gdGhlIG1vc3QgbW90b3IgdmVoaWNsZSB0aGVmdHMgYXQgZ2FzIHN0YXRpb25zIGhhcHBlbj8gIA0KYGBge3IgcmVzdWx0cz0naGlkZSd9DQpUb3A1ICU+JQ0KICBmaWx0ZXIoTG9jYXRpb25EZXNjcmlwdGlvbj09J0dBUyBTVEFUSU9OJykgJSQlDQogIHRhYmxlKFdlZWtkYXkpICU+JQ0KICB3aGljaC5tYXgoKSAlPiUgDQogIG5hbWVzKCkgLT4gQW5zd2VyXzQuNA0KYGBgICANCiMjIyMjICoqQW5zd2VyOioqICANCk1vc3QgbW90b3IgdmVoaWNsZSB0aGVmdHMgYXQgZ2FzIHN0YXRpb25zIGhhcHBlbiBvbiAqKmByIEFuc3dlcl80LjRgKiouICANCg0KKioqICANCg0KIyMjIyAqKjQuNSkqKiAgDQoNCiMjIyMjICoqUXVlc3Rpb246KiogDQpPbiB3aGljaCBkYXkgb2YgdGhlIHdlZWsgZG8gdGhlIGZld2VzdCBtb3RvciB2ZWhpY2xlIHRoZWZ0cyBpbiByZXNpZGVudGlhbCBkcml2ZXdheXMgaGFwcGVuPyAgDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NClRvcDUgJT4lDQogIGZpbHRlcihMb2NhdGlvbkRlc2NyaXB0aW9uPT0nRFJJVkVXQVkgLSBSRVNJREVOVElBTCcpICUkJQ0KICB0YWJsZShXZWVrZGF5KSAlPiUNCiAgd2hpY2gubWluKCkgJT4lIG5hbWVzKCkgJVQ+JSANCiAgdG9WYXIoQW5zd2VyXzQuNSkNCiN0b1ZhcihBbnN3ZXJfNC41KQ0KYGBgICANCiMjIyMjICoqQW5zd2VyOioqICANClRoZSBmZXdlc3QgaW5zdGFuY2VzIG9mIG1vdG9yIHZlaGljbGUgdGhlZnQgaW4gcmVzaWRlbnRpYWwgZHJpdmV3YXlzIG9jY3VyIG9uICoqYHIgQW5zd2VyXzQuNWAqKi4gIA0KDQoqKiogIA0K