Loading Uber Data
setwd("D:/imarticus/1/Uber-dataset")
apr_data <- read.csv("uber-raw-data-apr14.csv")
may_data <- read.csv("uber-raw-data-may14.csv")
jun_data <- read.csv("uber-raw-data-jun14.csv")
jul_data <- read.csv("uber-raw-data-jul14.csv")
aug_data <- read.csv("uber-raw-data-aug14.csv")
sep_data <- read.csv("uber-raw-data-sep14.csv")
#now binding all the data in one table
apr_data=apr_data[1:100000,]
may_data=may_data[1:100000,]
jun_data=jun_data[1:100000,]
jul_data=jul_data[1:100000,]
aug_data=aug_data[1:100000,]
sep_data=sep_data[1:100000,]
data_uber=rbind(apr_data,may_data,jun_data,jul_data,aug_data,sep_data)
str(data_uber)
'data.frame': 600000 obs. of 4 variables:
$ Date.Time: Factor w/ 260093 levels "4/1/2014 0:00:00",..: 11 17 21 28 33 33 38 44 54 58 ...
$ Lat : num 40.8 40.7 40.7 40.8 40.8 ...
$ Lon : num -74 -74 -74 -74 -74 ...
$ Base : Factor w/ 5 levels "B02512","B02598",..: 1 1 1 1 1 1 1 1 1 1 ...
Now we have combined uber data of 6 months with 600000 observation of 4 variables.
But as dvariable data.time is in factor format we have to convert it in time format.
#converting time from m/d/y format to y/m/d
data_uber$Date.Time <- as.POSIXct(data_uber$Date.Time, format = "%m/%d/%Y %H:%M:%S")
head(data_uber)
NA
Now as the data is in time format we can a new variable for time format in Hour-Min-Sec only
#making time as adifferent coloumn
data_uber$Time <- format(as.POSIXct(data_uber$Date.Time, format = "%m/%d/%Y %H:%M:%S"), format="%H:%M:%S")
head(data_uber)
Now we have made a seperate coloumn for time for analysis.
For ggplot we need to convert each time format individually as a factor.
data_uber$Date.Time <- ymd_hms(data_uber$Date.Time)
head(data_uber)
Now we can pullout individual time and covert it into factor.
data_uber$day <- factor(day(data_uber$Date.Time))
data_uber$month <- factor(month(data_uber$Date.Time, label = TRUE))
head(data_uber)
In the above table we have made day and month a different variable as a factor
#making tine as a factor in seperate coloumn
data_uber$hour <- factor(hour(hms(data_uber$Time)))
data_uber$minute <- factor(minute(hms(data_uber$Time)))
data_uber$second <- factor(second(hms(data_uber$Time)))
head(data_uber)
Similarily all the time value as a adifferent variable in a fator form. Now for ploting we are creating a new data grouped by hour.
hour_data <- data_uber %>%
group_by(hour) %>%
dplyr::summarize(Total = n())
head(hour_data)
NA
NA
Now in order in determine the peak hour at which maximum customer uses uber we will ggplot graph.
ggplot(hour_data, aes(hour, Total)) +
geom_bar( stat = "identity", fill = "steelblue", color = "red") +
ggtitle("Trips Every Hour") +
theme(legend.position = "none")

NA
Now from the above plot we can clearly state that rush hour is between 16.5hrs to 17.5hrs (4:30pm - 5:30pm).
#Grouping data by month and hour to determine peak hour monthwise
month_hour <- data_uber %>%
group_by(month, hour)%>%
dplyr::summarize(Total = n())
head(month_hour)
View(month_hour)
Now in order to determine peak hour time monthwise we have to plot another graph using the above data.
ggplot(month_hour, aes(hour, Total, fill = month)) +
geom_bar( stat = "identity") +
ggtitle("Trips by Hour and Month")

Now here we can see that out of all the days in every month rate of higher rides are in between 16 to 17 or 17 to 18.
ggplot(month_hour, aes(month, Total)) +
geom_bar( stat = "identity",fill="steelblue") +
ggtitle("Trips by Hour and Month")

As it is very clear from the graph that number of rides in every month is same.
#making a group data on the basis of day
day_group <- data_uber %>%
group_by(day) %>%
dplyr::summarize(Total = n())
head(day_group)
Now in order to determine the day with maximum number of rides we havew to make a plot using the above data.
ggplot(day_group, aes(day, Total)) +
geom_bar( stat = "identity", fill = "steelblue",col="green") +
ggtitle("Trips Every Day") +
theme(legend.position = "none")

Here we can see that the first week of the month is having max number of rides.
day_month_group <- data_uber %>%
group_by(month, day) %>%
dplyr:: summarize(Total = n())
head(day_month_group)
Ploting the graph to determine the day with highest number of rides monthwise.
ggplot(day_month_group,aes(day,Total,fill=month))+geom_bar(stat = "identity")+ scale_fill_manual(values = colors)

Now moving over weekly rides in every month.
data_month_week=data_uber %>%
group_by(month,dayofweek) %>%
dplyr:: summarise(Total=n())
head(data_month_week)
NA
ggplot(data_uber,aes(month,fill=dayofweek))+geom_bar(position = "dodge")+scale_fill_manual(values = colors)

ggplot(data_month_week,aes(month,Total,fill=dayofweek))+geom_bar(stat = "identity",position = "dodge")

From the above graph we can easily determine the day of week with maximum rides monthwise.
Now in order to determine the hourly rides of each day we have to make another data grouped by day and hour.
day_and_hour <- data_uber %>%
group_by(day, hour) %>%
dplyr::summarize(Total = n())
head(day_and_hour)
Now we can determine the number of rides on hourly basis of each day usiing heatmap.
colo="red"
ggplot(day_and_hour, aes(day, hour, fill = Total)) +
geom_tile(color = "black") +
ggtitle("Heat Map by Hour and Day")+scale_color_manual(values = colo,aesthetics = colo )

As we can clearly see in the above graph that on the very first week the numbers of rides are more in between 4pm to 8pm.
ggplot(day_month_group, aes(day, month, fill = Total)) +
geom_tile(color = "darkgrey") +
ggtitle("Heat Map by Month and Day")

From the above graph we can determine the day of month with more number of rides,which in most of the cases are the first 9days of the month.
We can also plot the heatmap to determine the day of week in a month with max number rides.
ggplot(data_month_week, aes(dayofweek, month, fill = Total)) +
geom_tile(color = "black") +
ggtitle("Heat Map by Month and Day of Week")

So from the above heatmap we can clearly determine the busiest day week of each month.
Now we have to determine the base with maximum number of rides each month and for that we are creating the new data.
month_base <- data_uber %>%
group_by(Base, month) %>%
dplyr::summarize(Total = n())
head(month_base)
NA
Now we can plot this data to show determine the busiest base of each month.
ggplot(month_base, aes(Base, month, fill = Total)) +
geom_tile(color = "white") +
ggtitle("Heat Map by Month and Bases")

So we can clearly see the busiest base of each month is B02598.
min_lat <- 40.5774
max_lat <- 40.9176
min_long <- -74.15
max_long <- -73.7004
ggplot(data_uber, aes(x=Lon, y=Lat, color = Base)) +
geom_point(size=1) +
scale_x_continuous(limits=c(min_long, max_long)) +
scale_y_continuous(limits=c(min_lat, max_lat)) +
theme_map() +
ggtitle("NYC MAP BASED ON UBER RIDES DURING 2014 (APR-SEP) by BASE")

The above show is the map plot the location showing the number of rides for both of the bases.
This how we can transform the uber data into usefull information from using ggplot2 which gives the insights of the busiest time of month ,week,day,hour and the busiest base.
Conclusion: So from the help of above analysis we can get the important insights of the data for decision taking like Where and When to avail the uber cabs more.
LS0tDQp0aXRsZTogIlViZXIgQW5hbHlzaXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KVWJlciBBbmFseXNpcyBieSBEYXRhIHZpc3VhbGl6YXRpb24NCmBgYHtyfQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShTY2FsZSkNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KDQpgYGANCg0KDQojIyBNYWtpbmcgY29sb3IgdmVjdG9ycw0KDQoNCmBgYHtyfQ0KY29sb3JzID0gYygiI0NDMTAxMSIsICIjNjY1NTU1IiwgIiMwNWEzOTkiLCAiI2NmY2FjYSIsICIjZjVlODQwIiwgIiMwNjgzYzkiLCAiI2UwNzViMCIpDQpjb2xvcnMNCg0KYGBgDQoNCiMjIExvYWRpbmcgVWJlciBEYXRhDQoNCg0KYGBge3J9DQpzZXR3ZCgiRDovaW1hcnRpY3VzLzEvVWJlci1kYXRhc2V0IikNCmFwcl9kYXRhIDwtIHJlYWQuY3N2KCJ1YmVyLXJhdy1kYXRhLWFwcjE0LmNzdiIpDQptYXlfZGF0YSA8LSByZWFkLmNzdigidWJlci1yYXctZGF0YS1tYXkxNC5jc3YiKQ0KanVuX2RhdGEgPC0gcmVhZC5jc3YoInViZXItcmF3LWRhdGEtanVuMTQuY3N2IikNCmp1bF9kYXRhIDwtIHJlYWQuY3N2KCJ1YmVyLXJhdy1kYXRhLWp1bDE0LmNzdiIpDQphdWdfZGF0YSA8LSByZWFkLmNzdigidWJlci1yYXctZGF0YS1hdWcxNC5jc3YiKQ0Kc2VwX2RhdGEgPC0gcmVhZC5jc3YoInViZXItcmF3LWRhdGEtc2VwMTQuY3N2IikNCmBgYA0KDQpgYGB7cn0NCiNub3cgYmluZGluZyBhbGwgdGhlIGRhdGEgaW4gb25lIHRhYmxlDQphcHJfZGF0YT1hcHJfZGF0YVsxOjEwMDAwMCxdDQptYXlfZGF0YT1tYXlfZGF0YVsxOjEwMDAwMCxdDQpqdW5fZGF0YT1qdW5fZGF0YVsxOjEwMDAwMCxdDQpqdWxfZGF0YT1qdWxfZGF0YVsxOjEwMDAwMCxdDQphdWdfZGF0YT1hdWdfZGF0YVsxOjEwMDAwMCxdDQpzZXBfZGF0YT1zZXBfZGF0YVsxOjEwMDAwMCxdDQoNCmRhdGFfdWJlcj1yYmluZChhcHJfZGF0YSxtYXlfZGF0YSxqdW5fZGF0YSxqdWxfZGF0YSxhdWdfZGF0YSxzZXBfZGF0YSkNCnN0cihkYXRhX3ViZXIpDQpgYGANCk5vdyB3ZSBoYXZlICBjb21iaW5lZCB1YmVyIGRhdGEgb2YgNiBtb250aHMgd2l0aCA2MDAwMDAgb2JzZXJ2YXRpb24gb2YgNCB2YXJpYWJsZXMuDQoNCkJ1dCBhcyBkdmFyaWFibGUgZGF0YS50aW1lIGlzIGluIGZhY3RvciAgZm9ybWF0IHdlIGhhdmUgdG8gY29udmVydCBpdCBpbiB0aW1lIGZvcm1hdC4NCmBgYHtyfQ0KI2NvbnZlcnRpbmcgdGltZSBmcm9tIG0vZC95IGZvcm1hdCB0byB5L20vZA0KZGF0YV91YmVyJERhdGUuVGltZSA8LSBhcy5QT1NJWGN0KGRhdGFfdWJlciREYXRlLlRpbWUsIGZvcm1hdCA9ICIlbS8lZC8lWSAlSDolTTolUyIpDQpoZWFkKGRhdGFfdWJlcikNCg0KYGBgDQpOb3cgYXMgdGhlIGRhdGEgaXMgaW4gdGltZSBmb3JtYXQgd2UgY2FuIGEgbmV3IHZhcmlhYmxlIGZvciB0aW1lIGZvcm1hdCBpbiBIb3VyLU1pbi1TZWMgb25seSANCmBgYHtyfQ0KI21ha2luZyB0aW1lIGFzIGEgZGlmZmVyZW50IGNvbG91bW4NCmRhdGFfdWJlciRUaW1lIDwtIGZvcm1hdChhcy5QT1NJWGN0KGRhdGFfdWJlciREYXRlLlRpbWUsIGZvcm1hdCA9ICIlbS8lZC8lWSAlSDolTTolUyIpLCBmb3JtYXQ9IiVIOiVNOiVTIikNCmhlYWQoZGF0YV91YmVyKQ0KYGBgDQpOb3cgd2UgaGF2ZSBtYWRlIGEgc2VwZXJhdGUgY29sb3VtbiBmb3IgdGltZSBmb3IgYW5hbHlzaXMuDQoNCkZvciBnZ3Bsb3Qgd2UgbmVlZCB0byBjb252ZXJ0IGVhY2ggdGltZSBmb3JtYXQgIGluZGl2aWR1YWxseSBhcyBhIGZhY3Rvci4NCmBgYHtyfQ0KZGF0YV91YmVyJERhdGUuVGltZSA8LSB5bWRfaG1zKGRhdGFfdWJlciREYXRlLlRpbWUpDQpoZWFkKGRhdGFfdWJlcikNCmBgYA0KTm93IHdlIGNhbiBwdWxsb3V0IGluZGl2aWR1YWwgdGltZSAgYW5kIGNvdmVydCBpdCBpbnRvIGZhY3Rvci4NCmBgYHtyfQ0KZGF0YV91YmVyJGRheSA8LSBmYWN0b3IoZGF5KGRhdGFfdWJlciREYXRlLlRpbWUpKQ0KZGF0YV91YmVyJG1vbnRoIDwtIGZhY3Rvcihtb250aChkYXRhX3ViZXIkRGF0ZS5UaW1lLCBsYWJlbCA9IFRSVUUpKQ0KaGVhZChkYXRhX3ViZXIpDQpgYGANCkluIHRoZSBhYm92ZSB0YWJsZSB3ZSBoYXZlIG1hZGUgZGF5IGFuZCBtb250aCBhIGRpZmZlcmVudCB2YXJpYWJsZSBhcyBhIGZhY3Rvcg0KYGBge3J9DQojbWFraW5nIGRhdGUsbW9udGggeWVhciBhbmQgZGF5IG9mIHdlZWsgYXMgYSBmYWN0b3IgaW4gc2VwZXJhdGUgY29sb3Vtbg0KZGF0YV91YmVyJHllYXIgPC0gZmFjdG9yKHllYXIoZGF0YV91YmVyJERhdGUuVGltZSkpDQpkYXRhX3ViZXIkZGF5b2Z3ZWVrIDwtIGZhY3Rvcih3ZGF5KGRhdGFfdWJlciREYXRlLlRpbWUsIGxhYmVsID0gVFJVRSkpDQpoZWFkKGRhdGFfdWJlcikNCmBgYA0KDQpgYGB7cn0NCiNtYWtpbmcgdGluZSBhcyBhIGZhY3RvciBpbiBzZXBlcmF0ZSBjb2xvdW1uDQpkYXRhX3ViZXIkaG91ciA8LSBmYWN0b3IoaG91cihobXMoZGF0YV91YmVyJFRpbWUpKSkNCmRhdGFfdWJlciRtaW51dGUgPC0gZmFjdG9yKG1pbnV0ZShobXMoZGF0YV91YmVyJFRpbWUpKSkNCmRhdGFfdWJlciRzZWNvbmQgPC0gZmFjdG9yKHNlY29uZChobXMoZGF0YV91YmVyJFRpbWUpKSkNCmhlYWQoZGF0YV91YmVyKQ0KYGBgDQpTaW1pbGFyaWx5IGFsbCB0aGUgdGltZSB2YWx1ZSBhcyBhIGFkaWZmZXJlbnQgdmFyaWFibGUgaW4gYSBmYXRvciBmb3JtLiANCk5vdyBmb3IgcGxvdGluZyB3ZSBhcmUgY3JlYXRpbmcgYSBuZXcgZGF0YSBncm91cGVkIGJ5IGhvdXIuDQpgYGB7cn0NCmhvdXJfZGF0YSA8LSBkYXRhX3ViZXIgJT4lDQogICAgICAgICAgIGdyb3VwX2J5KGhvdXIpICU+JQ0KICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcml6ZShUb3RhbCA9IG4oKSkgDQpoZWFkKGhvdXJfZGF0YSkNCg0KDQpgYGANCk5vdyBpbiBvcmRlciBpbiBkZXRlcm1pbmUgdGhlIHBlYWsgaG91ciBhdCB3aGljaCAgbWF4aW11bSBjdXN0b21lciB1c2VzIHViZXIgd2Ugd2lsbCBnZ3Bsb3QgZ3JhcGguDQpgYGB7cn0NCmdncGxvdChob3VyX2RhdGEsIGFlcyhob3VyLCBUb3RhbCkpICsgDQogICAgICAgIGdlb21fYmFyKCBzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJyZWQiKSArDQogICAgICAgICAgIGdndGl0bGUoIlRyaXBzIEV2ZXJ5IEhvdXIiKSArDQogICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIA0KICAgICAgICAgIA0KYGBgDQpOb3cgZnJvbSB0aGUgYWJvdmUgcGxvdCB3ZSBjYW4gY2xlYXJseSBzdGF0ZSB0aGF0ICBydXNoIGhvdXIgaXMgYmV0d2VlbiAxNi41aHJzIHRvIDE3LjVocnMgKDQ6MzBwbSAtIDU6MzBwbSkuDQpgYGB7cn0NCiNHcm91cGluZyBkYXRhIGJ5IG1vbnRoIGFuZCBob3VyIHRvIGRldGVybWluZSBwZWFrIGhvdXIgbW9udGh3aXNlIA0KbW9udGhfaG91ciA8LSBkYXRhX3ViZXIgJT4lDQogICAgICAgICAgZ3JvdXBfYnkobW9udGgsIGhvdXIpJT4lDQogICAgICAgICAgICAgZHBseXI6OnN1bW1hcml6ZShUb3RhbCA9IG4oKSkNCmhlYWQobW9udGhfaG91cikNClZpZXcobW9udGhfaG91cikNCmBgYA0KTm93IGluIG9yZGVyIHRvIGRldGVybWluZSBwZWFrIGhvdXIgdGltZSBtb250aHdpc2Ugd2UgaGF2ZSB0byBwbG90IGFub3RoZXIgZ3JhcGggdXNpbmcgdGhlIGFib3ZlIGRhdGEuDQpgYGB7cn0NCmdncGxvdChtb250aF9ob3VyLCBhZXMoaG91ciwgVG90YWwsIGZpbGwgPSBtb250aCkpICsgDQogICAgICAgZ2VvbV9iYXIoIHN0YXQgPSAiaWRlbnRpdHkiKSArDQogICAgICAgICAgZ2d0aXRsZSgiVHJpcHMgYnkgSG91ciBhbmQgTW9udGgiKSANCmBgYA0KTm93IGhlcmUgd2UgY2FuIHNlZSB0aGF0IG91dCBvZiBhbGwgdGhlIGRheXMgaW4gZXZlcnkgbW9udGggcmF0ZSBvZiBoaWdoZXIgcmlkZXMgYXJlIGluIGJldHdlZW4gMTYgdG8gMTcgb3IgMTcgdG8gMTguDQpgYGB7cn0NCmdncGxvdChtb250aF9ob3VyLCBhZXMobW9udGgsIFRvdGFsKSkgKyANCiAgICAgICBnZW9tX2Jhciggc3RhdCA9ICJpZGVudGl0eSIsZmlsbD0ic3RlZWxibHVlIikgKw0KICAgICAgICAgIGdndGl0bGUoIlRyaXBzIGJ5IEhvdXIgYW5kIE1vbnRoIikgDQpgYGANCkFzIGl0IGlzIHZlcnkgY2xlYXIgZnJvbSB0aGUgZ3JhcGggdGhhdCBudW1iZXIgb2YgcmlkZXMgaW4gZXZlcnkgbW9udGggaXMgc2FtZS4NCmBgYHtyfQ0KI21ha2luZyBhIGdyb3VwIGRhdGEgb24gdGhlIGJhc2lzIG9mIGRheQ0KZGF5X2dyb3VwIDwtIGRhdGFfdWJlciAlPiUNCiAgICAgICAgICBncm91cF9ieShkYXkpICU+JQ0KICAgICAgICAgICAgIGRwbHlyOjpzdW1tYXJpemUoVG90YWwgPSBuKCkpIA0KaGVhZChkYXlfZ3JvdXApDQpgYGANCk5vdyBpbiBvcmRlciB0byBkZXRlcm1pbmUgdGhlIGRheSB3aXRoIG1heGltdW0gbnVtYmVyIG9mIHJpZGVzIHdlIGhhdmV3IHRvIG1ha2UgYSBwbG90IHVzaW5nIHRoZSBhYm92ZSBkYXRhLg0KYGBge3J9DQpnZ3Bsb3QoZGF5X2dyb3VwLCBhZXMoZGF5LCBUb3RhbCkpICsgDQogICAgICAgIGdlb21fYmFyKCBzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJzdGVlbGJsdWUiLGNvbD0iZ3JlZW4iKSArDQogICAgICAgICAgIGdndGl0bGUoIlRyaXBzIEV2ZXJ5IERheSIpICsNCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KSGVyZSB3ZSBjYW4gc2VlIHRoYXQgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIG1vbnRoIGlzIGhhdmluZyBtYXggbnVtYmVyIG9mIHJpZGVzLg0KYGBge3J9DQpkYXlfbW9udGhfZ3JvdXAgPC0gZGF0YV91YmVyICU+JQ0KICAgICAgICAgZ3JvdXBfYnkobW9udGgsIGRheSkgJT4lDQogICAgICAgICAgICBkcGx5cjo6IHN1bW1hcml6ZShUb3RhbCA9IG4oKSkNCmhlYWQoZGF5X21vbnRoX2dyb3VwKQ0KYGBgDQpQbG90aW5nIHRoZSBncmFwaCB0byBkZXRlcm1pbmUgdGhlIGRheSB3aXRoIGhpZ2hlc3QgbnVtYmVyIG9mIHJpZGVzIG1vbnRod2lzZS4NCmBgYHtyfQ0KZ2dwbG90KGRheV9tb250aF9ncm91cCxhZXMoZGF5LFRvdGFsLGZpbGw9bW9udGgpKStnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikrIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykNCmBgYA0KTm93IG1vdmluZyBvdmVyIHdlZWtseSByaWRlcyBpbiBldmVyeSBtb250aC4NCmBgYHtyfQ0KZGF0YV9tb250aF93ZWVrPWRhdGFfdWJlciAlPiUNCiAgZ3JvdXBfYnkobW9udGgsZGF5b2Z3ZWVrKSAlPiUNCiBkcGx5cjo6IHN1bW1hcmlzZShUb3RhbD1uKCkpDQpoZWFkKGRhdGFfbW9udGhfd2VlaykNCiAgDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YV91YmVyLGFlcyhtb250aCxmaWxsPWRheW9md2VlaykpK2dlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikrc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JzKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGFfbW9udGhfd2VlayxhZXMobW9udGgsVG90YWwsZmlsbD1kYXlvZndlZWspKStnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iixwb3NpdGlvbiA9ICJkb2RnZSIpDQpgYGANCkZyb20gdGhlIGFib3ZlIGdyYXBoIHdlIGNhbiBlYXNpbHkgZGV0ZXJtaW5lIHRoZSBkYXkgb2Ygd2VlayB3aXRoIG1heGltdW0gcmlkZXMgbW9udGh3aXNlLg0KDQpOb3cgaW4gb3JkZXIgdG8gZGV0ZXJtaW5lIHRoZSBob3VybHkgcmlkZXMgb2YgZWFjaCBkYXkgd2UgaGF2ZSB0byBtYWtlIGFub3RoZXIgZGF0YSBncm91cGVkIGJ5IGRheSBhbmQgaG91ci4NCmBgYHtyfQ0KZGF5X2FuZF9ob3VyIDwtIGRhdGFfdWJlciAlPiUNCiAgICAgICAgIGdyb3VwX2J5KGRheSwgaG91cikgJT4lDQogICAgICAgICAgICBkcGx5cjo6c3VtbWFyaXplKFRvdGFsID0gbigpKQ0KaGVhZChkYXlfYW5kX2hvdXIpDQpgYGANCk5vdyB3ZSBjYW4gZGV0ZXJtaW5lIHRoZSBudW1iZXIgb2YgcmlkZXMgb24gaG91cmx5IGJhc2lzIG9mIGVhY2ggZGF5IHVzaWluZyBoZWF0bWFwLg0KYGBge3J9DQpjb2xvPSJyZWQiDQpnZ3Bsb3QoZGF5X2FuZF9ob3VyLCBhZXMoZGF5LCBob3VyLCBmaWxsID0gVG90YWwpKSArDQogICAgICAgICAgICBnZW9tX3RpbGUoY29sb3IgPSAiYmxhY2siKSArDQogICAgICAgICAgICAgIGdndGl0bGUoIkhlYXQgTWFwIGJ5IEhvdXIgYW5kIERheSIpK3NjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvLGFlc3RoZXRpY3MgPSBjb2xvICkNCmBgYA0KQXMgd2UgY2FuIGNsZWFybHkgc2VlIGluIHRoZSBhYm92ZSBncmFwaCB0aGF0IG9uIHRoZSB2ZXJ5IGZpcnN0IHdlZWsgdGhlIG51bWJlcnMgb2YgcmlkZXMgYXJlIG1vcmUgaW4gYmV0d2VlbiA0cG0gdG8gOHBtLg0KDQpgYGB7cn0NCmdncGxvdChkYXlfbW9udGhfZ3JvdXAsIGFlcyhkYXksIG1vbnRoLCBmaWxsID0gVG90YWwpKSArDQogICAgICAgICAgICBnZW9tX3RpbGUoY29sb3IgPSAiZGFya2dyZXkiKSArDQogICAgICAgICAgICAgIGdndGl0bGUoIkhlYXQgTWFwIGJ5IE1vbnRoIGFuZCBEYXkiKQ0KYGBgDQpGcm9tIHRoZSBhYm92ZSBncmFwaCB3ZSBjYW4gZGV0ZXJtaW5lIHRoZSBkYXkgb2YgbW9udGggd2l0aCBtb3JlIG51bWJlciBvZiByaWRlcyx3aGljaCBpbiBtb3N0IG9mIHRoZSBjYXNlcyBhcmUgdGhlIGZpcnN0IDlkYXlzIG9mIHRoZSBtb250aC4NCg0KV2UgY2FuIGFsc28gcGxvdCB0aGUgaGVhdG1hcCB0byBkZXRlcm1pbmUgdGhlIGRheSBvZiB3ZWVrIGluIGEgbW9udGggd2l0aCBtYXggbnVtYmVyIHJpZGVzLg0KYGBge3J9DQpnZ3Bsb3QoZGF0YV9tb250aF93ZWVrLCBhZXMoZGF5b2Z3ZWVrLCBtb250aCwgZmlsbCA9IFRvdGFsKSkgKw0KICAgICAgICAgICAgZ2VvbV90aWxlKGNvbG9yID0gImJsYWNrIikgKw0KICAgICAgICAgICAgICBnZ3RpdGxlKCJIZWF0IE1hcCBieSBNb250aCBhbmQgRGF5IG9mIFdlZWsiKQ0KYGBgDQpTbyBmcm9tIHRoZSBhYm92ZSAgaGVhdG1hcCB3ZSBjYW4gY2xlYXJseSBkZXRlcm1pbmUgdGhlIGJ1c2llc3QgZGF5IHdlZWsgb2YgZWFjaCBtb250aC4NCg0KTm93IHdlIGhhdmUgdG8gZGV0ZXJtaW5lIHRoZSBiYXNlIHdpdGggbWF4aW11bSBudW1iZXIgb2YgcmlkZXMgZWFjaCBtb250aCBhbmQgZm9yIHRoYXQgd2UgYXJlIGNyZWF0aW5nIHRoZSBuZXcgZGF0YS4NCmBgYHtyfQ0KbW9udGhfYmFzZSA8LSAgZGF0YV91YmVyICU+JQ0KICAgICAgICAgICAgICAgICAgICBncm91cF9ieShCYXNlLCBtb250aCkgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c3VtbWFyaXplKFRvdGFsID0gbigpKQ0KaGVhZChtb250aF9iYXNlKQ0KDQpgYGANCk5vdyB3ZSBjYW4gcGxvdCB0aGlzIGRhdGEgdG8gc2hvdyBkZXRlcm1pbmUgdGhlIGJ1c2llc3QgYmFzZSBvZiBlYWNoIG1vbnRoLg0KYGBge3J9DQpnZ3Bsb3QobW9udGhfYmFzZSwgYWVzKEJhc2UsIG1vbnRoLCBmaWxsID0gVG90YWwpKSArDQogICAgICAgICAgICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArDQogICAgICAgICAgICAgIGdndGl0bGUoIkhlYXQgTWFwIGJ5IE1vbnRoIGFuZCBCYXNlcyIpDQpgYGANClNvIHdlIGNhbiBjbGVhcmx5IHNlZSB0aGUgYnVzaWVzdCBiYXNlIG9mIGVhY2ggbW9udGggaXMgQjAyNTk4Lg0KYGBge3J9DQptaW5fbGF0IDwtIDQwLjU3NzQNCm1heF9sYXQgPC0gNDAuOTE3Ng0KbWluX2xvbmcgPC0gLTc0LjE1DQptYXhfbG9uZyA8LSAtNzMuNzAwNA0KDQpnZ3Bsb3QoZGF0YV91YmVyLCBhZXMoeD1Mb24sIHk9TGF0LCBjb2xvciA9IEJhc2UpKSArDQogIGdlb21fcG9pbnQoc2l6ZT0xKSArDQogICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YyhtaW5fbG9uZywgbWF4X2xvbmcpKSArDQogICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMobWluX2xhdCwgbWF4X2xhdCkpICsNCiAgICAgICB0aGVtZV9tYXAoKSArDQogICAgICAgICAgZ2d0aXRsZSgiTllDIE1BUCBCQVNFRCBPTiBVQkVSIFJJREVTIERVUklORyAyMDE0IChBUFItU0VQKSBieSBCQVNFIikNCmBgYA0KVGhlIGFib3ZlIHNob3cgaXMgdGhlIG1hcCBwbG90IHRoZSBsb2NhdGlvbiBzaG93aW5nIHRoZSBudW1iZXIgb2YgcmlkZXMgZm9yIGJvdGggb2YgdGhlIGJhc2VzLg0KDQpUaGlzIGhvdyB3ZSBjYW4gdHJhbnNmb3JtIHRoZSB1YmVyIGRhdGEgaW50byB1c2VmdWxsIGluZm9ybWF0aW9uIGZyb20gdXNpbmcgZ2dwbG90MiB3aGljaCBnaXZlcyB0aGUgaW5zaWdodHMgb2YgdGhlIGJ1c2llc3QgdGltZSBvZiBtb250aCAsd2VlayxkYXksaG91ciBhbmQgdGhlIGJ1c2llc3QgYmFzZS4NCg0KQ29uY2x1c2lvbjoNClNvIGZyb20gdGhlIGhlbHAgb2YgYWJvdmUgYW5hbHlzaXMgd2UgY2FuIGdldCB0aGUgaW1wb3J0YW50IGluc2lnaHRzIG9mIHRoZSBkYXRhIGZvciBkZWNpc2lvbiB0YWtpbmcgbGlrZSBXaGVyZSBhbmQgV2hlbiB0byBhdmFpbCB0aGUgdWJlciBjYWJzDQptb3JlLg0KDQo=