Have you ever wanted to have a collection of something? It could be trading cards, board games, art pieces, or whatever you want them to be. In this project, we’ll suppose you collect something with a lot of data - cars!

Your car collection is almost complete - it’s just missing one thing. You think about it for a while, then it comes to you - you don’t have a car from 1985! But there are so many cars from 1985 available for you to collect! How will you know which 1985 car you will buy for your collection?

Luckily for you, we have a dataset that stores precisely that information. This dataset comes from the UCI Machine Learning Repository and is linked here. This dataset has been adapted so that the variable names are along the first rows.

As you’ll notice in this project, though, this dataset isn’t ready for analysis yet. You will have to make some changes along the way to clean and tidy up the dataset. Do that, and you’ll have the ability to perform a great analysis!

Loading and Inspecting the Data

1.What good is an analysis if we don’t even have the tools to perform the said analysis? Some of the tools you will need for this analysis are the readr and dplyr tidyverse packages. Load the libraries at the top of the notebook.Rmd file so you can access the functions you will need later on.

Task 1

# load libraries

library(readr)
library(dplyr)

2.The last tool we need is the data itself! The file cars85.csv stores the data that comes from the UCI Machine Learning Repository. Load the file into a dataframe called cars to get started.

Task 2

# load data
cars <- read_csv('cars85.csv')
cars

3.It’s always a good idea to inspect the data you load into R. It helps you to know what you are working with. Inspect cars with head() and summary().

What kind of information do you have? What can you do with this information?

Each row in this dataframe is a single car, and each column stores some characteristic about that car. You want to get the best value for your collection, so you want to analyze as much as you can before buying. Doing so will help you make your choice easier!

Task 3

# inspect data
head(cars)
summary()
錯誤發生在 summary.default(): 缺少引數 "object",也沒有預設值

Clean the Data

4.After inspecting the dataframe, you notice something odd about the normalized_losses column. This column has a lot of entries that are question marks (?). This variable is not worth looking at since we don’t have all the cars’ expected losses.

Let’s remove this column from the dataset. Select all columns from cars but normalized_losses. Save your new dataframe to cars.

Task 4

# select columns
cars <- cars %>%
  select(-normalized_losses)
cars

5.Print the column names of cars. Are they clear and descriptive?

Task 5

# view columns
colnames(cars)
 [1] "symboling"         "make"              "fuel_type"         "aspiration"        "num_of_doors"     
 [6] "body_style"        "drive_wheels"      "engine_location"   "wheel_base"        "length"           
[11] "width"             "height"            "curb_weight"       "engine_type"       "num_of_cylinders" 
[16] "engine_size"       "fuel_system"       "bore"              "stroke"            "compression_ratio"
[21] "horsepower"        "peak_rpm"          "city_mpg"          "highway_mpg"       "price"            

6.You know, symboling doesn’t say anything to you at first glance. According to the UCI webpage, the symboling variable represents the car’s risk factor. That variable name doesn’t seem to go with the description. You should simplify this variable name to have it make more sense.

Update that column name in cars as follows:

symboling -> risk_factor Print the column names of cars to confirm the names of the columns have changed.

Task 6

# rename column
cars <- cars %>%
  rename(risk_factor = symboling)
colnames(cars)
 [1] "risk_factor"       "make"              "fuel_type"         "aspiration"        "num_of_doors"     
 [6] "body_style"        "drive_wheels"      "engine_location"   "wheel_base"        "length"           
[11] "width"             "height"            "curb_weight"       "engine_type"       "num_of_cylinders" 
[16] "engine_size"       "fuel_system"       "bore"              "stroke"            "compression_ratio"
[21] "horsepower"        "peak_rpm"          "city_mpg"          "highway_mpg"       "price"            

7.Your car collection means a lot to you. You want each car to be of value to you. What better way to do that than to buy a car with a lot of miles-per-gallon on the highways? To determine this, first, suppose only cars exceeding 30 mpg on the highways interest you. You seek to measure how different each car’s highway mpg is from your 30 mpg threshold. Create a variable called mpg_threshold with the value 30.

Task 7

# define threshold
mpg_threshold <- 30
mpg_threshold
[1] 30

8.Add a new column to cars called mpg_diff_from_threshold. This will measure how far each car’s highway mpg is from 30 mpg. View the updated cars dataframe.

Task 8

# add column
cars <- cars %>%
  mutate(mpg_diff_from_threshold = highway_mpg - mpg_threshold)
cars

Filter and Arrange Rows

9.You’ll add a car to your collection only if it gets more than 30 miles per gallon on the highways. Filter the rows of cars to find all the cars where mpg_diff_from_threshold is greater than 0. Save this new dataframe to mpg_exceeds_threshold and view it.

Task 9

# filter rows
mpg_exceeds_threshold <- cars %>%
  filter(mpg_diff_from_threshold > 0)
mpg_exceeds_threshold

10.Which cars have the highest miles per gallon on the highways? To find this, arrange the rows of mpg_exceeds_threshold by mpg_diff_from_threshold descending. Save this new dataframe as mpg_exceeds_threshold.

Task 10

# arrange rows
mpg_exceeds_threshold <- cars %>%
  arrange(desc(mpg_diff_from_threshold))
mpg_exceeds_threshold

11.Now suppose you want your next car to have a large engine. Order the rows of cars by engine_size descending. Save the new data frame to ordered_by_engine_size. View ordered_by_engine_size.

Task 11

# order rows by engine size
ordered_by_engine_size <- cars %>%
  arrange(desc(engine_size))
ordered_by_engine_size

Specifying the Make of the Car

12.There’s a lot of makes of cars to choose from, but you may prefer one over the others. Which make do you prefer the most? Create a variable called chosen_make that contains the make you want to check. The hint below provides the list of makes to choose from.

*Hint : The list below provides the makes for you to choose from. Pick a make and assign it to chosen_make. alfa-romero, audi, bmw, chevrolet, dodge, honda, isuzu, jaguar, mazda, mercedes-benz, mercury, mitsubishi, nissan, peugot, plymouth, porsche, renault, saab, subaru, toyota, volkswagen, volvo

Task 12

# choose make
chosen_make <- "mercedes-benz"
chosen_make
[1] "mercedes-benz"

13.Filter cars to only include rows where the make column is equal to chosen_make. Save the new dataframe to chosen_make_details.

Task 13

# filter rows by make
chosen_make_details <- cars %>%
  filter(make == chosen_make)
chosen_make_details

14.Order the rows of chosen_make_details by engine_size descending and save the new dataframe to chosen_make_details. View chosen_make_details.

How large are the engines in each of the cars from that make that you chose? You can change the make stored in chosen_make to check out the engine sizes for other makes.

Task 14

# order filtered rows by engine size
chosen_make_details <- cars %>%
  arrange(desc(engine_size))
chosen_make_details

15.The process of buying a new car can cause a lot of stress - you don’t want to buy a car you won’t like! You’ve now seen how performing an analysis can ease some of the stress of making the decision of which car to buy. You also get to add a nice new car to your collection! Great work!

LS0tDQp0aXRsZTogIkV4cGxvcmUgdGhlIDE5ODUgQ2FycyBEYXRhc2V0Ig0KYXV0aG9yOiAiQW5uYWJlbCBLdW8iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclWS0lbS0lZCAlSDolTScpYCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQpIYXZlIHlvdSBldmVyIHdhbnRlZCB0byBoYXZlIGEgY29sbGVjdGlvbiBvZiBzb21ldGhpbmc/IEl0IGNvdWxkIGJlIHRyYWRpbmcgY2FyZHMsIGJvYXJkIGdhbWVzLCBhcnQgcGllY2VzLCBvciB3aGF0ZXZlciB5b3Ugd2FudCB0aGVtIHRvIGJlLiBJbiB0aGlzIHByb2plY3QsIHdl4oCZbGwgc3VwcG9zZSB5b3UgY29sbGVjdCBzb21ldGhpbmcgd2l0aCBhIGxvdCBvZiBkYXRhIC0gY2FycyENCg0KWW91ciBjYXIgY29sbGVjdGlvbiBpcyBhbG1vc3QgY29tcGxldGUgLSBpdOKAmXMganVzdCBtaXNzaW5nIG9uZSB0aGluZy4gWW91IHRoaW5rIGFib3V0IGl0IGZvciBhIHdoaWxlLCB0aGVuIGl0IGNvbWVzIHRvIHlvdSAtIHlvdSBkb27igJl0IGhhdmUgYSBjYXIgZnJvbSAxOTg1ISBCdXQgdGhlcmUgYXJlIHNvIG1hbnkgY2FycyBmcm9tIDE5ODUgYXZhaWxhYmxlIGZvciB5b3UgdG8gY29sbGVjdCEgSG93IHdpbGwgeW91IGtub3cgd2hpY2ggMTk4NSBjYXIgeW91IHdpbGwgYnV5IGZvciB5b3VyIGNvbGxlY3Rpb24/DQoNCkx1Y2tpbHkgZm9yIHlvdSwgd2UgaGF2ZSBhIGRhdGFzZXQgdGhhdCBzdG9yZXMgcHJlY2lzZWx5IHRoYXQgaW5mb3JtYXRpb24uIFRoaXMgZGF0YXNldCBjb21lcyBmcm9tIHRoZSBVQ0kgTWFjaGluZSBMZWFybmluZyBSZXBvc2l0b3J5IGFuZCBpcyBsaW5rZWQgaGVyZS4gVGhpcyBkYXRhc2V0IGhhcyBiZWVuIGFkYXB0ZWQgc28gdGhhdCB0aGUgdmFyaWFibGUgbmFtZXMgYXJlIGFsb25nIHRoZSBmaXJzdCByb3dzLg0KDQpBcyB5b3XigJlsbCBub3RpY2UgaW4gdGhpcyBwcm9qZWN0LCB0aG91Z2gsIHRoaXMgZGF0YXNldCBpc27igJl0IHJlYWR5IGZvciBhbmFseXNpcyB5ZXQuIFlvdSB3aWxsIGhhdmUgdG8gbWFrZSBzb21lIGNoYW5nZXMgYWxvbmcgdGhlIHdheSB0byBjbGVhbiBhbmQgdGlkeSB1cCB0aGUgZGF0YXNldC4gRG8gdGhhdCwgYW5kIHlvdeKAmWxsIGhhdmUgdGhlIGFiaWxpdHkgdG8gcGVyZm9ybSBhIGdyZWF0IGFuYWx5c2lzIQ0KDQojIExvYWRpbmcgYW5kIEluc3BlY3RpbmcgdGhlIERhdGENCg0KMS5XaGF0IGdvb2QgaXMgYW4gYW5hbHlzaXMgaWYgd2UgZG9u4oCZdCBldmVuIGhhdmUgdGhlIHRvb2xzIHRvIHBlcmZvcm0gdGhlIHNhaWQgYW5hbHlzaXM/IFNvbWUgb2YgdGhlIHRvb2xzIHlvdSB3aWxsIG5lZWQgZm9yIHRoaXMgYW5hbHlzaXMgYXJlIHRoZSByZWFkciBhbmQgZHBseXIgdGlkeXZlcnNlIHBhY2thZ2VzLiBMb2FkIHRoZSBsaWJyYXJpZXMgYXQgdGhlIHRvcCBvZiB0aGUgbm90ZWJvb2suUm1kIGZpbGUgc28geW91IGNhbiBhY2Nlc3MgdGhlIGZ1bmN0aW9ucyB5b3Ugd2lsbCBuZWVkIGxhdGVyIG9uLg0KDQojIyBUYXNrIDENCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPVRSVUV9DQojIGxvYWQgbGlicmFyaWVzDQoNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KYGBgDQoNCjIuVGhlIGxhc3QgdG9vbCB3ZSBuZWVkIGlzIHRoZSBkYXRhIGl0c2VsZiEgVGhlIGZpbGUgY2Fyczg1LmNzdiBzdG9yZXMgdGhlIGRhdGEgdGhhdCBjb21lcyBmcm9tIHRoZSBVQ0kgTWFjaGluZSBMZWFybmluZyBSZXBvc2l0b3J5LiBMb2FkIHRoZSBmaWxlIGludG8gYSBkYXRhZnJhbWUgY2FsbGVkIGNhcnMgdG8gZ2V0IHN0YXJ0ZWQuDQoNCiMjIFRhc2sgMg0KYGBge3IgZXJyb3I9VFJVRX0NCiMgbG9hZCBkYXRhDQpjYXJzIDwtIHJlYWRfY3N2KCdjYXJzODUuY3N2JykNCmNhcnMNCmBgYA0KDQozLkl04oCZcyBhbHdheXMgYSBnb29kIGlkZWEgdG8gaW5zcGVjdCB0aGUgZGF0YSB5b3UgbG9hZCBpbnRvIFIuIEl0IGhlbHBzIHlvdSB0byBrbm93IHdoYXQgeW91IGFyZSB3b3JraW5nIHdpdGguIEluc3BlY3QgY2FycyB3aXRoIGhlYWQoKSBhbmQgc3VtbWFyeSgpLg0KDQpXaGF0IGtpbmQgb2YgaW5mb3JtYXRpb24gZG8geW91IGhhdmU/IFdoYXQgY2FuIHlvdSBkbyB3aXRoIHRoaXMgaW5mb3JtYXRpb24/DQoNCkVhY2ggcm93IGluIHRoaXMgZGF0YWZyYW1lIGlzIGEgc2luZ2xlIGNhciwgYW5kIGVhY2ggY29sdW1uIHN0b3JlcyBzb21lIGNoYXJhY3RlcmlzdGljIGFib3V0IHRoYXQgY2FyLiBZb3Ugd2FudCB0byBnZXQgdGhlIGJlc3QgdmFsdWUgZm9yIHlvdXIgY29sbGVjdGlvbiwgc28geW91IHdhbnQgdG8gYW5hbHl6ZSBhcyBtdWNoIGFzIHlvdSBjYW4gYmVmb3JlIGJ1eWluZy4gRG9pbmcgc28gd2lsbCBoZWxwIHlvdSBtYWtlIHlvdXIgY2hvaWNlIGVhc2llciENCg0KIyMgVGFzayAzDQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBpbnNwZWN0IGRhdGENCmhlYWQoY2FycykNCnN1bW1hcnkoKQ0KYGBgDQoNCiMgQ2xlYW4gdGhlIERhdGENCg0KNC5BZnRlciBpbnNwZWN0aW5nIHRoZSBkYXRhZnJhbWUsIHlvdSBub3RpY2Ugc29tZXRoaW5nIG9kZCBhYm91dCB0aGUgbm9ybWFsaXplZF9sb3NzZXMgY29sdW1uLiBUaGlzIGNvbHVtbiBoYXMgYSBsb3Qgb2YgZW50cmllcyB0aGF0IGFyZSBxdWVzdGlvbiBtYXJrcyAoPykuIFRoaXMgdmFyaWFibGUgaXMgbm90IHdvcnRoIGxvb2tpbmcgYXQgc2luY2Ugd2UgZG9u4oCZdCBoYXZlIGFsbCB0aGUgY2Fyc+KAmSBleHBlY3RlZCBsb3NzZXMuDQoNCkxldOKAmXMgcmVtb3ZlIHRoaXMgY29sdW1uIGZyb20gdGhlIGRhdGFzZXQuIFNlbGVjdCBhbGwgY29sdW1ucyBmcm9tIGNhcnMgYnV0IG5vcm1hbGl6ZWRfbG9zc2VzLiBTYXZlIHlvdXIgbmV3IGRhdGFmcmFtZSB0byBjYXJzLg0KDQojIyBUYXNrIDQNCmBgYHtyIGVycm9yPVRSVUV9DQojIHNlbGVjdCBjb2x1bW5zDQpjYXJzIDwtIGNhcnMgJT4lDQogIHNlbGVjdCgtbm9ybWFsaXplZF9sb3NzZXMpDQpjYXJzDQpgYGANCg0KNS5QcmludCB0aGUgY29sdW1uIG5hbWVzIG9mIGNhcnMuIEFyZSB0aGV5IGNsZWFyIGFuZCBkZXNjcmlwdGl2ZT8NCg0KIyMgVGFzayA1DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyB2aWV3IGNvbHVtbnMNCmNvbG5hbWVzKGNhcnMpDQpgYGANCg0KNi5Zb3Uga25vdywgc3ltYm9saW5nIGRvZXNu4oCZdCBzYXkgYW55dGhpbmcgdG8geW91IGF0IGZpcnN0IGdsYW5jZS4gQWNjb3JkaW5nIHRvIHRoZSBVQ0kgd2VicGFnZSwgdGhlIHN5bWJvbGluZyB2YXJpYWJsZSByZXByZXNlbnRzIHRoZSBjYXLigJlzIHJpc2sgZmFjdG9yLiBUaGF0IHZhcmlhYmxlIG5hbWUgZG9lc27igJl0IHNlZW0gdG8gZ28gd2l0aCB0aGUgZGVzY3JpcHRpb24uIFlvdSBzaG91bGQgc2ltcGxpZnkgdGhpcyB2YXJpYWJsZSBuYW1lIHRvIGhhdmUgaXQgbWFrZSBtb3JlIHNlbnNlLg0KDQpVcGRhdGUgdGhhdCBjb2x1bW4gbmFtZSBpbiBjYXJzIGFzIGZvbGxvd3M6DQoNCnN5bWJvbGluZyAtPiByaXNrX2ZhY3Rvcg0KUHJpbnQgdGhlIGNvbHVtbiBuYW1lcyBvZiBjYXJzIHRvIGNvbmZpcm0gdGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zIGhhdmUgY2hhbmdlZC4NCg0KIyMgVGFzayA2DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyByZW5hbWUgY29sdW1uDQpjYXJzIDwtIGNhcnMgJT4lDQogIHJlbmFtZShyaXNrX2ZhY3RvciA9IHN5bWJvbGluZykNCmNvbG5hbWVzKGNhcnMpDQpgYGANCg0KNy5Zb3VyIGNhciBjb2xsZWN0aW9uIG1lYW5zIGEgbG90IHRvIHlvdS4gWW91IHdhbnQgZWFjaCBjYXIgdG8gYmUgb2YgdmFsdWUgdG8geW91LiBXaGF0IGJldHRlciB3YXkgdG8gZG8gdGhhdCB0aGFuIHRvIGJ1eSBhIGNhciB3aXRoIGEgbG90IG9mIG1pbGVzLXBlci1nYWxsb24gb24gdGhlIGhpZ2h3YXlzPyBUbyBkZXRlcm1pbmUgdGhpcywgZmlyc3QsIHN1cHBvc2Ugb25seSBjYXJzIGV4Y2VlZGluZyAzMCBtcGcgb24gdGhlIGhpZ2h3YXlzIGludGVyZXN0IHlvdS4gWW91IHNlZWsgdG8gbWVhc3VyZSBob3cgZGlmZmVyZW50IGVhY2ggY2Fy4oCZcyBoaWdod2F5IG1wZyBpcyBmcm9tIHlvdXIgMzAgbXBnIHRocmVzaG9sZC4gQ3JlYXRlIGEgdmFyaWFibGUgY2FsbGVkIG1wZ190aHJlc2hvbGQgd2l0aCB0aGUgdmFsdWUgMzAuDQoNCiMjIFRhc2sgNw0KYGBge3IgZXJyb3I9VFJVRX0NCiMgZGVmaW5lIHRocmVzaG9sZA0KbXBnX3RocmVzaG9sZCA8LSAzMA0KbXBnX3RocmVzaG9sZA0KYGBgDQoNCjguQWRkIGEgbmV3IGNvbHVtbiB0byBjYXJzIGNhbGxlZCBtcGdfZGlmZl9mcm9tX3RocmVzaG9sZC4gVGhpcyB3aWxsIG1lYXN1cmUgaG93IGZhciBlYWNoIGNhcuKAmXMgaGlnaHdheSBtcGcgaXMgZnJvbSAzMCBtcGcuIFZpZXcgdGhlIHVwZGF0ZWQgY2FycyBkYXRhZnJhbWUuDQoNCiMjIFRhc2sgOA0KYGBge3IgZXJyb3I9VFJVRX0NCiMgYWRkIGNvbHVtbg0KY2FycyA8LSBjYXJzICU+JQ0KICBtdXRhdGUobXBnX2RpZmZfZnJvbV90aHJlc2hvbGQgPSBoaWdod2F5X21wZyAtIG1wZ190aHJlc2hvbGQpDQpjYXJzDQpgYGANCg0KIyBGaWx0ZXIgYW5kIEFycmFuZ2UgUm93cw0KDQo5LllvdeKAmWxsIGFkZCBhIGNhciB0byB5b3VyIGNvbGxlY3Rpb24gb25seSBpZiBpdCBnZXRzIG1vcmUgdGhhbiAzMCBtaWxlcyBwZXIgZ2FsbG9uIG9uIHRoZSBoaWdod2F5cy4gRmlsdGVyIHRoZSByb3dzIG9mIGNhcnMgdG8gZmluZCBhbGwgdGhlIGNhcnMgd2hlcmUgbXBnX2RpZmZfZnJvbV90aHJlc2hvbGQgaXMgZ3JlYXRlciB0aGFuIDAuIFNhdmUgdGhpcyBuZXcgZGF0YWZyYW1lIHRvIG1wZ19leGNlZWRzX3RocmVzaG9sZCBhbmQgdmlldyBpdC4NCg0KIyMgVGFzayA5DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBmaWx0ZXIgcm93cw0KbXBnX2V4Y2VlZHNfdGhyZXNob2xkIDwtIGNhcnMgJT4lDQogIGZpbHRlcihtcGdfZGlmZl9mcm9tX3RocmVzaG9sZCA+IDApDQptcGdfZXhjZWVkc190aHJlc2hvbGQNCmBgYA0KDQoxMC5XaGljaCBjYXJzIGhhdmUgdGhlIGhpZ2hlc3QgbWlsZXMgcGVyIGdhbGxvbiBvbiB0aGUgaGlnaHdheXM/IFRvIGZpbmQgdGhpcywgYXJyYW5nZSB0aGUgcm93cyBvZiBtcGdfZXhjZWVkc190aHJlc2hvbGQgYnkgbXBnX2RpZmZfZnJvbV90aHJlc2hvbGQgZGVzY2VuZGluZy4gU2F2ZSB0aGlzIG5ldyBkYXRhZnJhbWUgYXMgbXBnX2V4Y2VlZHNfdGhyZXNob2xkLg0KDQojIyBUYXNrIDEwDQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBhcnJhbmdlIHJvd3MNCm1wZ19leGNlZWRzX3RocmVzaG9sZCA8LSBjYXJzICU+JQ0KICBhcnJhbmdlKGRlc2MobXBnX2RpZmZfZnJvbV90aHJlc2hvbGQpKQ0KbXBnX2V4Y2VlZHNfdGhyZXNob2xkDQpgYGANCg0KMTEuTm93IHN1cHBvc2UgeW91IHdhbnQgeW91ciBuZXh0IGNhciB0byBoYXZlIGEgbGFyZ2UgZW5naW5lLiBPcmRlciB0aGUgcm93cyBvZiBjYXJzIGJ5IGVuZ2luZV9zaXplIGRlc2NlbmRpbmcuIFNhdmUgdGhlIG5ldyBkYXRhIGZyYW1lIHRvIG9yZGVyZWRfYnlfZW5naW5lX3NpemUuIFZpZXcgb3JkZXJlZF9ieV9lbmdpbmVfc2l6ZS4NCg0KIyMgVGFzayAxMQ0KYGBge3IgZXJyb3I9VFJVRX0NCiMgb3JkZXIgcm93cyBieSBlbmdpbmUgc2l6ZQ0Kb3JkZXJlZF9ieV9lbmdpbmVfc2l6ZSA8LSBjYXJzICU+JQ0KICBhcnJhbmdlKGRlc2MoZW5naW5lX3NpemUpKQ0Kb3JkZXJlZF9ieV9lbmdpbmVfc2l6ZQ0KYGBgDQoNCiMgU3BlY2lmeWluZyB0aGUgTWFrZSBvZiB0aGUgQ2FyDQoNCjEyLlRoZXJl4oCZcyBhIGxvdCBvZiBtYWtlcyBvZiBjYXJzIHRvIGNob29zZSBmcm9tLCBidXQgeW91IG1heSBwcmVmZXIgb25lIG92ZXIgdGhlIG90aGVycy4gV2hpY2ggbWFrZSBkbyB5b3UgcHJlZmVyIHRoZSBtb3N0PyBDcmVhdGUgYSB2YXJpYWJsZSBjYWxsZWQgY2hvc2VuX21ha2UgdGhhdCBjb250YWlucyB0aGUgbWFrZSB5b3Ugd2FudCB0byBjaGVjay4gVGhlIGhpbnQgYmVsb3cgcHJvdmlkZXMgdGhlIGxpc3Qgb2YgbWFrZXMgdG8gY2hvb3NlIGZyb20uDQoNCipIaW50IDogVGhlIGxpc3QgYmVsb3cgcHJvdmlkZXMgdGhlIG1ha2VzIGZvciB5b3UgdG8gY2hvb3NlIGZyb20uIFBpY2sgYSBtYWtlIGFuZCBhc3NpZ24gaXQgdG8gY2hvc2VuX21ha2UuDQphbGZhLXJvbWVybywgYXVkaSwgYm13LCBjaGV2cm9sZXQsIGRvZGdlLCBob25kYSwgaXN1enUsIGphZ3VhciwgbWF6ZGEsIG1lcmNlZGVzLWJlbnosIG1lcmN1cnksIG1pdHN1YmlzaGksIG5pc3NhbiwgcGV1Z290LCBwbHltb3V0aCwgcG9yc2NoZSwgcmVuYXVsdCwgc2FhYiwgc3ViYXJ1LCB0b3lvdGEsIHZvbGtzd2FnZW4sIHZvbHZvDQoNCiMjIFRhc2sgMTINCmBgYHtyIGVycm9yPVRSVUV9DQojIGNob29zZSBtYWtlDQpjaG9zZW5fbWFrZSA8LSAibWVyY2VkZXMtYmVueiINCmNob3Nlbl9tYWtlDQpgYGANCg0KMTMuRmlsdGVyIGNhcnMgdG8gb25seSBpbmNsdWRlIHJvd3Mgd2hlcmUgdGhlIG1ha2UgY29sdW1uIGlzIGVxdWFsIHRvIGNob3Nlbl9tYWtlLiBTYXZlIHRoZSBuZXcgZGF0YWZyYW1lIHRvIGNob3Nlbl9tYWtlX2RldGFpbHMuDQoNCiMjIFRhc2sgMTMNCmBgYHtyIGVycm9yPVRSVUV9DQojIGZpbHRlciByb3dzIGJ5IG1ha2UNCmNob3Nlbl9tYWtlX2RldGFpbHMgPC0gY2FycyAlPiUNCiAgZmlsdGVyKG1ha2UgPT0gY2hvc2VuX21ha2UpDQpjaG9zZW5fbWFrZV9kZXRhaWxzDQpgYGANCg0KMTQuT3JkZXIgdGhlIHJvd3Mgb2YgY2hvc2VuX21ha2VfZGV0YWlscyBieSBlbmdpbmVfc2l6ZSBkZXNjZW5kaW5nIGFuZCBzYXZlIHRoZSBuZXcgZGF0YWZyYW1lIHRvIGNob3Nlbl9tYWtlX2RldGFpbHMuIFZpZXcgY2hvc2VuX21ha2VfZGV0YWlscy4NCg0KSG93IGxhcmdlIGFyZSB0aGUgZW5naW5lcyBpbiBlYWNoIG9mIHRoZSBjYXJzIGZyb20gdGhhdCBtYWtlIHRoYXQgeW91IGNob3NlPyBZb3UgY2FuIGNoYW5nZSB0aGUgbWFrZSBzdG9yZWQgaW4gY2hvc2VuX21ha2UgdG8gY2hlY2sgb3V0IHRoZSBlbmdpbmUgc2l6ZXMgZm9yIG90aGVyIG1ha2VzLg0KDQojIyBUYXNrIDE0DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBvcmRlciBmaWx0ZXJlZCByb3dzIGJ5IGVuZ2luZSBzaXplDQpjaG9zZW5fbWFrZV9kZXRhaWxzIDwtIGNhcnMgJT4lDQogIGFycmFuZ2UoZGVzYyhlbmdpbmVfc2l6ZSkpDQpjaG9zZW5fbWFrZV9kZXRhaWxzDQpgYGANCg0KMTUuVGhlIHByb2Nlc3Mgb2YgYnV5aW5nIGEgbmV3IGNhciBjYW4gY2F1c2UgYSBsb3Qgb2Ygc3RyZXNzIC0geW91IGRvbuKAmXQgd2FudCB0byBidXkgYSBjYXIgeW91IHdvbuKAmXQgbGlrZSEgWW914oCZdmUgbm93IHNlZW4gaG93IHBlcmZvcm1pbmcgYW4gYW5hbHlzaXMgY2FuIGVhc2Ugc29tZSBvZiB0aGUgc3RyZXNzIG9mIG1ha2luZyB0aGUgZGVjaXNpb24gb2Ygd2hpY2ggY2FyIHRvIGJ1eS4gWW91IGFsc28gZ2V0IHRvIGFkZCBhIG5pY2UgbmV3IGNhciB0byB5b3VyIGNvbGxlY3Rpb24hIEdyZWF0IHdvcmsh