Notebook Setup

setwd("~/Documents/Via")
library(readr)
library(data.table)
library(magrittr)
library(dplyr)
library(ff)
library(ggplot2)
library(scales)
library(RColorBrewer)
library(extrafont)
library(hexbin)
library(lubridate)

Load in fare and ride data of 2013

fare <- read_csv('trip_fare_1.csv')
ride <- read_csv('trip_data_1.csv')
# ride <- fread('trip_data_1.csv')

Source functions and parameters

Airport Coordinates Definition

* JFK: 40.6413° N, 73.7781° W

* LaGuardia: 40.7769° N, 73.8740° W

jfk <- data.frame(x=c(-73.81,-73.77), y=c(40.635,40.67))
laguardia <- data.frame(x=c(-73.88,-73.858), y=c(40.764,40.779))

Tag airports and manipulate dataframe (details in codes)

Pickups

Visulization — Pickups by Count

Warning: Removed 716 rows containing missing values (geom_point).

  • The bright highlights of the airports and midtown Times Square show the most taxi ride counts.
  • Yellow dots are placed to pinpoint airports coordinates.

Visulization — Pickups by Fare Revenue

Warning: Removed 720 rows containing non-finite values (stat_summary_hex).
Warning: Removed 720 rows containing missing values (geom_point).

  • The bright highlights of the airports, midtown Times Square and Financial District show the most fare revenue from taxi rides.

Visualization — Pickups by Fare Per Second

Warning: Removed 808 rows containing non-finite values (stat_summary_hex).
Warning: Removed 720 rows containing missing values (geom_point).

  • The bright highlights of the airports, and midtown Times Square show the most efficient taxi rides.

Dropoffs

Manipulate dataframe

map2 <- only_airport %>% select(dropoff_longitude, dropoff_latitude, fare_amount, trip_time_in_secs) %>% 
  round(4) %>% group_by(dropoff_longitude, dropoff_latitude) %>% 
  summarise(count=n(), fare = sum(fare_amount), time=mean(trip_time_in_secs)) 

Visulization — Dropoffs by Count

Warning: Removed 485 rows containing missing values (geom_point).

Visulization — Dropoffs by Fare Revenue

Warning: Removed 485 rows containing non-finite values (stat_summary_hex).
Warning: Removed 485 rows containing missing values (geom_point).

Visualization — Dropoffs by Fare Per Second

Warning: Removed 485 rows containing non-finite values (stat_summary_hex).
Warning: Removed 485 rows containing missing values (geom_point).

  • Interestingly, for dropoff rides, midtown Times Square actually show more efficiency than airports, which means taxi drivers earn more fare revenue per one unit of time in second.

Analysis Questions:

• How would you assess the efficiency of aggregating rides to/from each airport?

I would use fare revenue/trip_time_in_secscost per second to assess efficiency of aggregating rides to/from airports. Because the idea is that the higher fare revenue earned by one unit of time (second), the more efficient the ride is in economic sense.

• How does this compare to our current area of service (e.g. the Upper East Side)?

From graph, it shows UES generate similar fare revenue compared with to/from airports. Two other area of service worth noting are Mid-town (Times Square), and Financial District. The Upper West Side has potential too.

• Which of the airport expansion options is most beneficial and why?

LaGuardia airport expansion is most beneficial compared with JFK. It has relative less pickup and dropoff points but demand is not low. Plus rides to/from LaGuardia are economicly efficient.

Manipulate dataframe

map3 <- only_airport %>% select(pickup_longitude,pickup_latitude, surcharge) %>% round(4) %>%
  group_by(pickup_longitude,pickup_latitude)%>% summarise(count=n(), surcharge = sum(surcharge)) 

Visualizataion — Pickups by Surcharge

Warning: Removed 720 rows containing non-finite values (stat_summary_hex).
Warning: Removed 720 rows containing missing values (geom_point).

  • Pickups from airports rides collect most surcharges per ride.

Manipulate dataframe

map4 <- only_airport %>% select(dropoff_longitude,dropoff_latitude, surcharge) %>% round(4) %>%
  group_by(dropoff_longitude,dropoff_latitude)%>% summarise(count=n(), surcharge = sum(surcharge)) 

Visualization — Dropoffs by Surcharge

Warning: Removed 485 rows containing non-finite values (stat_summary_hex).
Warning: Removed 485 rows containing missing values (geom_point).

  • Another insight shows from dropoff map that La Guardia actually incur more surcharge than JFK. Hence expanding to LaGuardia may be more beneficial economicly.

• Would you launch airports as a separate service or as a new service? Why?

My thought process of whether to launch airports as a separate service is to look at demand and revenue relations. Based on graphs above, both metrics exhibit favorable signal for such consideration. In addition, people are inclined to request airport ride in advance on their phones, which fits Via’s operating business well.

Visualization — Ride Time Analysis

  • By package definition, Sunday is 1.

• Would you launch airport rides during all our hours of service (6am-12am on weekdays and 10am-12am on Saturdays) or only for certain hours? Which hours?

As shown in graph above, the current hours of service seem to almost cover most high demand time. That said, I would allocate more resources around mid afternoon, especially on Wednesday and Thursday.

Visualization — Fare Per Passenger Analysis

• How would you price airport rides and why (our current model is a $5.00 flat fee weekdays before 9pm and $5.95 weeknights after 9pm and all day Saturdays)?

According to taxi ride fare, discounted by number of passenger, I still think $5 flat fee is quite low, compared with almost $30 dollar normal rate. If it is Via’s initial strategy to use advantageous price incentive to start the business, it makes sense. However, as Via establishes itself, it may not be optimal anymore to lay too much money on the table. Hence, I would suggest a different price tier. In order to make profit and alleviate traffic congestion, I will charge $10 to $15 flat fee, including tax (the exact amount can vary according to model accuracy) for regular operating hours, and $1 to $5 surcharge for rush hours between 6am to 7am and 18pm to 19pm.

Qualitative Questions:

• What additional data would you like to see in order to answer questions 1-5 more confidently and how would you incorporate it?

I would want to see through what channel are those taxi rides are requested. For example, we may see growing usage of mobile application for airports rides as people may feel more assured to request ride in advance on their mobile phones, versas traditionally getting cabs on the street. This will also provide more information if we need to launch airport rides as separate service.

• How might your answer change over time? What Via data would you monitor to ensure the proposed expansion was a good business decision?

My answer might change along with the change of competitive landscape of On-demand transportation. Therefore, I would monitor Via’s competitors’ data to assess the efficiency of the proposed expansion.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKYXV0aG9yOiAiQ3ludGhpYSBMaSwgQ0ZBIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2UgPSBGKQpgYGAKIyBOb3RlYm9vayBTZXR1cApgYGB7cn0Kc2V0d2QoIn4vRG9jdW1lbnRzL1ZpYSIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShkcGx5cikKbGlicmFyeShmZikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoZXh0cmFmb250KQpsaWJyYXJ5KGhleGJpbikKbGlicmFyeShsdWJyaWRhdGUpCmBgYAoKIyMgTG9hZCBpbiBmYXJlIGFuZCByaWRlIGRhdGEgb2YgMjAxMwpgYGB7ciwgY2FjaGU9VH0KZmFyZSA8LSByZWFkX2NzdigndHJpcF9mYXJlXzEuY3N2JykKcmlkZSA8LSByZWFkX2NzdigndHJpcF9kYXRhXzEuY3N2JykKIyByaWRlIDwtIGZyZWFkKCd0cmlwX2RhdGFfMS5jc3YnKQpgYGAKCiMjIFNvdXJjZSBmdW5jdGlvbnMgYW5kIHBhcmFtZXRlcnMKYGBge3IsIGluY2x1ZGU9RkFMU0V9CnRoZW1lX21hcF9kYXJrIDwtIGZ1bmN0aW9uKHBhbGF0ZV9jb2xvciA9ICJHcmV5cyIpIHsKICAKICBwYWxhdGUgPC0gYnJld2VyLnBhbChwYWxhdGVfY29sb3IsIG49OSkKICBjb2xvci5iYWNrZ3JvdW5kID0gImJsYWNrIgogIGNvbG9yLmdyaWQubWlub3IgPSAiYmxhY2siCiAgY29sb3IuZ3JpZC5tYWpvciA9ICJibGFjayIKICBjb2xvci5heGlzLnRleHQgPSBwYWxhdGVbMV0KICBjb2xvci5heGlzLnRpdGxlID0gcGFsYXRlWzFdCiAgY29sb3IudGl0bGUgPSBwYWxhdGVbMV0KICAKICBmb250LnRpdGxlIDwtICJDb21pYyBTYW5zIE1TIgogIGZvbnQuYXhpcyA8LSAiQXJpYWwgUm91bmRlZCBNVCBCb2xkIgogIAogIHRoZW1lX2J3KGJhc2Vfc2l6ZT01KSArCiAgICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kPWVsZW1lbnRfcmVjdChmaWxsPWNvbG9yLmJhY2tncm91bmQsIGNvbG9yPWNvbG9yLmJhY2tncm91bmQpKSArCiAgICB0aGVtZShwbG90LmJhY2tncm91bmQ9ZWxlbWVudF9yZWN0KGZpbGw9Y29sb3IuYmFja2dyb3VuZCwgY29sb3I9Y29sb3IuYmFja2dyb3VuZCkpICsKICAgIHRoZW1lKHBhbmVsLmJvcmRlcj1lbGVtZW50X3JlY3QoY29sb3I9Y29sb3IuYmFja2dyb3VuZCkpICsKICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3I9ZWxlbWVudF9ibGFuaygpKSArCiAgICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yPWVsZW1lbnRfYmxhbmsoKSkgKwogICAgdGhlbWUoYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCkpICsKICAgIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9Y29sb3IuYmFja2dyb3VuZCkpICsKICAgIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9Myxjb2xvdXI9Y29sb3IuYXhpcy50aXRsZSxmYW1pbHk9Zm9udC5heGlzKSkgKwogICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb249InRvcCIsIGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgICB0aGVtZShsZWdlbmQua2V5LndpZHRoPXVuaXQoMSwgImNtIiksIGxlZ2VuZC5rZXkuaGVpZ2h0PXVuaXQoMC4yNSwgImNtIiksIGxlZ2VuZC5tYXJnaW49dW5pdCgtMC41LCJjbSIpKSArCiAgICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChjb2xvdXI9Y29sb3IudGl0bGUsZmFtaWx5PWZvbnQudGl0bGUsIHNpemU9MTApKSArCiAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCkpICsKICAgIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSkgKwogICAgdGhlbWUoYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSkgKwogICAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgKwogICAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMC4wLCAtMC41LCAtMSwgLTAuNzUpLCAiY20iKSkgKwogICAgdGhlbWUoc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPWNvbG9yLmJhY2tncm91bmQsIGNvbG9yPWNvbG9yLmJhY2tncm91bmQpLHN0cmlwLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Nyxjb2xvdXI9Y29sb3IuYXhpcy50aXRsZSxmYW1pbHk9Zm9udC50aXRsZSkpCn0KYGBgCgojIyBBaXJwb3J0IENvb3JkaW5hdGVzIERlZmluaXRpb24KIyMjICogSkZLOiA0MC42NDEzwrAgTiwgNzMuNzc4McKwIFcKIyMjICogTGFHdWFyZGlhOiA0MC43NzY5wrAgTiwgNzMuODc0MMKwIFcKCmBgYHtyLCBpbmNsdWRlPVR9CmpmayA8LSBkYXRhLmZyYW1lKHg9YygtNzMuODEsLTczLjc3KSwgeT1jKDQwLjYzNSw0MC42NykpCmxhZ3VhcmRpYSA8LSBkYXRhLmZyYW1lKHg9YygtNzMuODgsLTczLjg1OCksIHk9Yyg0MC43NjQsNDAuNzc5KSkKYGBgCgojIyBgVGFnYCBfX2FpcnBvcnRzX18gYW5kIG1hbmlwdWxhdGUgZGF0YWZyYW1lIChkZXRhaWxzIGluIGNvZGVzKQpgYGB7ciwgaW5jbHVkZT1GfQphaXJwb3J0IDwtIGNiaW5kKGZhcmVbLGMoInBpY2t1cF9kYXRldGltZSIsICJmYXJlX2Ftb3VudCIsICJzdXJjaGFyZ2UiKV0sIAogICAgICAgICAgICAgICAgIHJpZGVbLGMoInRyaXBfdGltZV9pbl9zZWNzIiwgInBhc3Nlbmdlcl9jb3VudCIsICJwaWNrdXBfbG9uZ2l0dWRlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAicGlja3VwX2xhdGl0dWRlIiwgImRyb3BvZmZfbG9uZ2l0dWRlIiwgImRyb3BvZmZfbGF0aXR1ZGUiKV0pIAoKYWlycG9ydCRmcm9tX2pmayA8LSBpZmVsc2UoKGFpcnBvcnQkcGlja3VwX2xvbmdpdHVkZSA+IC03My44MSkgJiAoYWlycG9ydCRwaWNrdXBfbG9uZ2l0dWRlIDwgLTczLjc3KSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGFpcnBvcnQkcGlja3VwX2xhdGl0dWRlID4gNDAuNjM1KSAmIChhaXJwb3J0JHBpY2t1cF9sYXRpdHVkZSA8IDQwLjY3KSwgMSwgMCkKCmFpcnBvcnQkZnJvbV9sYWd1YXJkaWEgPC0gaWZlbHNlKChhaXJwb3J0JHBpY2t1cF9sb25naXR1ZGUgPiAtNzMuODgpICYgKGFpcnBvcnQkcGlja3VwX2xvbmdpdHVkZSA8IC03My44NTgpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYWlycG9ydCRwaWNrdXBfbGF0aXR1ZGUgPiA0MC43NjQpICYgKGFpcnBvcnQkcGlja3VwX2xhdGl0dWRlIDwgNDAuNzc5KSwgMSwgMCkKCmFpcnBvcnQkdG9famZrIDwtIGlmZWxzZSgoYWlycG9ydCRkcm9wb2ZmX2xvbmdpdHVkZSA+IC03My44MSkgJiAoYWlycG9ydCRkcm9wb2ZmX2xvbmdpdHVkZSA8IC03My43NykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhaXJwb3J0JGRyb3BvZmZfbGF0aXR1ZGUgPiA0MC42MzUpICYgKGFpcnBvcnQkZHJvcG9mZl9sYXRpdHVkZSA8IDQwLjY3KSwgMSwgMCkKCmFpcnBvcnQkdG9fbGFndWFyZGlhIDwtIGlmZWxzZSgoYWlycG9ydCRkcm9wb2ZmX2xvbmdpdHVkZSA+IC03My44OCkgJiAoYWlycG9ydCRkcm9wb2ZmX2xvbmdpdHVkZSA8IC03My44NTgpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYWlycG9ydCRkcm9wb2ZmX2xhdGl0dWRlID4gNDAuNzY0KSAmIChhaXJwb3J0JGRyb3BvZmZfbGF0aXR1ZGUgPCA0MC43NzkpLCAxLCAwKQoKYWlycG9ydCRhaXJwb3J0IDwtIGFpcnBvcnQkdG9famZrK2FpcnBvcnQkdG9fbGFndWFyZGlhK2FpcnBvcnQkZnJvbV9qZmsrYWlycG9ydCRmcm9tX2xhZ3VhcmRpYQoKb25seV9haXJwb3J0IDwtIGFpcnBvcnQgJT4lIGZpbHRlcihhaXJwb3J0ID09IDEgfCBhaXJwb3J0ID09MikKCm1hcDEgPC0gb25seV9haXJwb3J0ICU+JSBzZWxlY3QocGlja3VwX2xvbmdpdHVkZSwgcGlja3VwX2xhdGl0dWRlLCBmYXJlX2Ftb3VudCwgdHJpcF90aW1lX2luX3NlY3MpICU+JSAKICByb3VuZCg0KSAlPiUgZ3JvdXBfYnkocGlja3VwX2xvbmdpdHVkZSxwaWNrdXBfbGF0aXR1ZGUpICU+JSAKICBzdW1tYXJpc2UoY291bnQ9bigpLCBmYXJlID0gc3VtKGZhcmVfYW1vdW50KSwgdGltZT1tZWFuKHRyaXBfdGltZV9pbl9zZWNzKSkgCmBgYAoKIyBQaWNrdXBzCgojIyBWaXN1bGl6YXRpb24gLS0tIFBpY2t1cHMgYnkgX19Db3VudF9fCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9RkFMU0UsIGVjaG89Rn0KZ2dwbG90KG1hcDEsIGFlcyh4PXBpY2t1cF9sb25naXR1ZGUseT1waWNrdXBfbGF0aXR1ZGUsIGNvbG9yPWNvdW50KSkgKyBnZW9tX3BvaW50KHNpemU9MC44KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC03NC4wMzI0LCAtNzMuNzYyMSkpICsgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDQwLjYyNSwgNDAuODMwKSkgKwogIHRoZW1lX21hcF9kYXJrKCkgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChoaWdoPSd5ZWxsb3cnLCBsb3c9ImJsdWUiLCB0cmFucz0ibG9nIikgKwogIGxhYnModGl0bGUgPSAiVGF4aSBQaWNrdXBzIG9uIE5ZQyBNYXAiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBjb29yZF9lcXVhbCgpICsgZ2VvbV9wb2ludChkYXRhPWpmaywgYWVzKHg9eCwgeT15KSxjb2xvcj0neWVsbG93Jywgc2l6ZT0xKSArIGdlb21fcG9pbnQoZGF0YT1sYWd1YXJkaWEsIGFlcyh4PXgsIHk9eSksY29sb3I9J3llbGxvdycsc2l6ZT0xKQpgYGAKCgoqIF9fVGhlIGJyaWdodCBoaWdobGlnaHRzIG9mIHRoZSBhaXJwb3J0cyBhbmQgbWlkdG93biBUaW1lcyBTcXVhcmUgc2hvdyB0aGUgbW9zdCB0YXhpIHJpZGUgY291bnRzLl9fCiogX19ZZWxsb3cgZG90cyBhcmUgcGxhY2VkIHRvIHBpbnBvaW50IGFpcnBvcnRzIGNvb3JkaW5hdGVzLl9fICAKCiMjIFZpc3VsaXphdGlvbiAtLS0gUGlja3VwcyBieSBfX0ZhcmUgUmV2ZW51ZV9fCmBgYHtyLCBlY2hvPUZ9CnRvdGFsX3JldiA8LSBmdW5jdGlvbih4LCB0aHJlc2hvbGQgPSAxMF40KSB7CiAgaWYgKHN1bSh4KSA8IHRocmVzaG9sZCkge3JldHVybiAoTkEpfQogIGVsc2Uge3JldHVybiAoc3VtKHgpKX0KfQoKZ2dwbG90KG1hcDEsIGFlcyh4PXBpY2t1cF9sb25naXR1ZGUseT1waWNrdXBfbGF0aXR1ZGUsIHo9ZmFyZSkpICsKICBnZW9tX3BvaW50KHNpemU9MC40LCBjb2xvcj0iZGFya2dyZXkiKSArCiAgc3RhdF9zdW1tYXJ5X2hleChmdW4gPSB0b3RhbF9yZXYsIGJpbnM9MTAwLCBhbHBoYT0wLjkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTc0LjAzMjQsIC03My43NjIxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9Yyg0MC42MjgsIDQwLjgzMCkpICsKICB0aGVtZV9tYXBfZGFyaygpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdz0icGluayIsIGhpZ2g9InJlZCIsIGxhYmVscz1kb2xsYXIsIHRyYW5zPSJsb2ciLCBicmVha3M9YygxMF4oMToyKSkpICsKICBsYWJzKHRpdGxlID0gIk5ZQyBUYXhpcyBUb3RhbCBSZXZlbnVlIC0tIFBpY2t1cCBMb2NhdGlvbiAyMDEzIikgKwogIGNvb3JkX2VxdWFsKCkKYGBgCgoqIF9fVGhlIGJyaWdodCBoaWdobGlnaHRzIG9mIHRoZSBhaXJwb3J0cywgbWlkdG93biBUaW1lcyBTcXVhcmUgYW5kIEZpbmFuY2lhbCBEaXN0cmljdCBzaG93IHRoZSBtb3N0IGZhcmUgcmV2ZW51ZSBmcm9tIHRheGkgcmlkZXMuX18gIAoKIyMgVmlzdWFsaXphdGlvbiAtLS0gUGlja3VwcyBieSBfX0ZhcmUgUGVyIFNlY29uZF9fCmBgYHtyLCBlY2hvPUZ9CnRvdGFsX3JldiA8LSBmdW5jdGlvbih4LCB0aHJlc2hvbGQgPSAxMCkgewogIGlmIChzdW0oeCkgPCB0aHJlc2hvbGQpIHtyZXR1cm4gKE5BKX0KICBlbHNlIHtyZXR1cm4gKHN1bSh4KSl9Cn0KZ2dwbG90KG1hcDEsIGFlcyh4PXBpY2t1cF9sb25naXR1ZGUseT1waWNrdXBfbGF0aXR1ZGUsIHo9ZmFyZS90aW1lKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjA2LCBjb2xvcj0iZGFya2dyZXkiKSArCiAgc3RhdF9zdW1tYXJ5X2hleChmdW4gPSB0b3RhbF9yZXYsIGJpbnM9MTAwLCBhbHBoYT0wLjgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTc0LjAzMjQsIC03My43NjIxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9Yyg0MC42MjgsIDQwLjgzMCkpICsKICB0aGVtZV9tYXBfZGFyaygpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdz0icGluayIsIGhpZ2g9InJlZCIsIGxhYmVscz1kb2xsYXIsIHRyYW5zPSJsb2ciLCBicmVha3M9YygxMF4oMTo1KSkpICsKICBsYWJzKHRpdGxlID0gIk5ZQyBUYXhpcyBSaWRlIEVmZmljaWVuY3kgLS0gUGlja3VwIExvY2F0aW9uIDIwMTMiKSArCiAgY29vcmRfZXF1YWwoKQpgYGAKCiogX19UaGUgYnJpZ2h0IGhpZ2hsaWdodHMgb2YgdGhlIGFpcnBvcnRzLCBhbmQgbWlkdG93biBUaW1lcyBTcXVhcmUgc2hvdyB0aGUgbW9zdCBlZmZpY2llbnQgdGF4aSByaWRlcy5fXyAgCgojIERyb3BvZmZzCgojIyBNYW5pcHVsYXRlIGRhdGFmcmFtZSAKYGBge3J9Cm1hcDIgPC0gb25seV9haXJwb3J0ICU+JSBzZWxlY3QoZHJvcG9mZl9sb25naXR1ZGUsIGRyb3BvZmZfbGF0aXR1ZGUsIGZhcmVfYW1vdW50LCB0cmlwX3RpbWVfaW5fc2VjcykgJT4lIAogIHJvdW5kKDQpICU+JSBncm91cF9ieShkcm9wb2ZmX2xvbmdpdHVkZSwgZHJvcG9mZl9sYXRpdHVkZSkgJT4lIAogIHN1bW1hcmlzZShjb3VudD1uKCksIGZhcmUgPSBzdW0oZmFyZV9hbW91bnQpLCB0aW1lPW1lYW4odHJpcF90aW1lX2luX3NlY3MpKSAKYGBgCgojIyBWaXN1bGl6YXRpb24gLS0tIERyb3BvZmZzIGJ5IF9fQ291bnRfXwpgYGB7ciwgZWNobz1GfQpnZ3Bsb3QobWFwMiAlPiUgZmlsdGVyKGNvdW50ID4gMiksIGFlcyh4PWRyb3BvZmZfbG9uZ2l0dWRlLHk9ZHJvcG9mZl9sYXRpdHVkZSwgY29sb3I9Y291bnQpKSArIGdlb21fcG9pbnQoc2l6ZT0wLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTc0LjAzMjQsIC03My43NjIxKSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoNDAuNjI4LCA0MC44MzApKSArCiAgdGhlbWVfbWFwX2RhcmsoKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0iYmx1ZSIsIGhpZ2g9J3llbGxvdycsIHRyYW5zPSJsb2ciKSArCiAgbGFicyh0aXRsZSA9ICJUYXhpIERyb3BvZmYgb24gTllDIE1hcCIpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyBjb29yZF9lcXVhbCgpCmBgYAoKIyMgVmlzdWxpemF0aW9uIC0tLSBEcm9wb2ZmcyBieSBfX0ZhcmUgUmV2ZW51ZV9fCmBgYHtyLCBlY2hvPUZ9CnRvdGFsX3JldiA8LSBmdW5jdGlvbih4LCB0aHJlc2hvbGQgPSAxMF40KSB7CiAgaWYgKHN1bSh4KSA8IHRocmVzaG9sZCkge3JldHVybiAoTkEpfQogIGVsc2Uge3JldHVybiAoc3VtKHgpKX0KfQpnZ3Bsb3QobWFwMiAlPiUgZmlsdGVyKGNvdW50PjIpLCBhZXMoeD1kcm9wb2ZmX2xvbmdpdHVkZSx5PWRyb3BvZmZfbGF0aXR1ZGUsIHo9ZmFyZSkpICsKICBnZW9tX3BvaW50KHNpemU9MC4zLCBjb2xvcj0iZGFya2dyZXkiKSArCiAgc3RhdF9zdW1tYXJ5X2hleChmdW4gPSB0b3RhbF9yZXYsIGJpbnM9MTAwLCBhbHBoYT0wLjkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTc0LjAzMjQsIC03My43NjIxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9Yyg0MC42MjgsIDQwLjgzMCkpICsKICB0aGVtZV9tYXBfZGFyaygpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdz0icGluayIsIGhpZ2g9InJlZCIsIGxhYmVscz1kb2xsYXIsIHRyYW5zPSJsb2ciLCBicmVha3M9YygxMF4oMjo2KSkpICsKICBsYWJzKHRpdGxlID0gIk5ZQyBUYXhpcyBUb3RhbCBSZXZlbnVlIC0tIERyb3BvZmYgTG9jYXRpb24gMjAxMyIpICsKICBjb29yZF9lcXVhbCgpCmBgYAoKIyMgVmlzdWFsaXphdGlvbiAtLS0gRHJvcG9mZnMgYnkgX19GYXJlIFBlciBTZWNvbmRfXwpgYGB7ciwgZWNobz1GfQp0b3RhbF9yZXYgPC0gZnVuY3Rpb24oeCwgdGhyZXNob2xkID0gMTBeMykgewogIGlmIChzdW0oeCkgPCB0aHJlc2hvbGQpIHtyZXR1cm4gKE5BKX0KICBlbHNlIHtyZXR1cm4gKHN1bSh4KSl9Cn0KZ2dwbG90KG1hcDIgJT4lIGZpbHRlcihjb3VudCA+IDIpLCBhZXMoeD1kcm9wb2ZmX2xvbmdpdHVkZSx5PWRyb3BvZmZfbGF0aXR1ZGUsIHo9ZmFyZS9jb3VudCkpICsKICBnZW9tX3BvaW50KHNpemU9MC4zLCBjb2xvcj0iZGFya2dyZXkiKSArCiAgc3RhdF9zdW1tYXJ5X2hleChmdW4gPSB0b3RhbF9yZXYsIGJpbnM9MTAwLCBhbHBoYT0wLjgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTc0LjAzMjQsIC03My43NjIxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9Yyg0MC42MjgsIDQwLjgzMCkpICsKICB0aGVtZV9tYXBfZGFyaygpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdz0icGluayIsIGhpZ2g9InJlZCIsIGxhYmVscz1kb2xsYXIsIHRyYW5zPSJsb2ciLCBicmVha3M9YygxMF4oMzo1KSkpICsKICBsYWJzKHRpdGxlID0gIk5ZQyBUYXhpcyBSaWRlIEVmZmljaWVuY3kgLS0gRHJvcG9mZiBMb2NhdGlvbiAyMDEzIikgKwogIGNvb3JkX2VxdWFsKCkKYGBgCgoqIF9fSW50ZXJlc3RpbmdseSwgZm9yIGRyb3BvZmYgcmlkZXMsIG1pZHRvd24gVGltZXMgU3F1YXJlIGFjdHVhbGx5IHNob3cgbW9yZSBlZmZpY2llbmN5IHRoYW4gYWlycG9ydHMsIHdoaWNoIG1lYW5zIHRheGkgZHJpdmVycyBlYXJuIG1vcmUgZmFyZSByZXZlbnVlIHBlciBvbmUgdW5pdCBvZiB0aW1lIGluIHNlY29uZC5fXyAgCgojIEFuYWx5c2lzIFF1ZXN0aW9uczogCgrigKIJSG93IHdvdWxkIHlvdSBhc3Nlc3MgdGhlIGVmZmljaWVuY3kgb2YgYWdncmVnYXRpbmcgcmlkZXMgdG8vZnJvbSBlYWNoIGFpcnBvcnQ/Cgo+IEkgd291bGQgdXNlIGBmYXJlIHJldmVudWVgL2B0cmlwX3RpbWVfaW5fc2Vjc2AgLS0tIF9fY29zdCBwZXIgc2Vjb25kX18gdG8gYXNzZXNzIGVmZmljaWVuY3kgb2YgYWdncmVnYXRpbmcgcmlkZXMgdG8vZnJvbSBhaXJwb3J0cy4gQmVjYXVzZSB0aGUgaWRlYSBpcyB0aGF0IHRoZSBoaWdoZXIgZmFyZSByZXZlbnVlIGVhcm5lZCBieSBvbmUgdW5pdCBvZiB0aW1lIChzZWNvbmQpLCB0aGUgbW9yZSBlZmZpY2llbnQgdGhlIHJpZGUgaXMgaW4gZWNvbm9taWMgc2Vuc2UuCgrigKIJSG93IGRvZXMgdGhpcyBjb21wYXJlIHRvIG91ciBjdXJyZW50IGFyZWEgb2Ygc2VydmljZSAoZS5nLiB0aGUgVXBwZXIgRWFzdCBTaWRlKT8KCj4gRnJvbSBncmFwaCwgaXQgc2hvd3MgVUVTIGdlbmVyYXRlIHNpbWlsYXIgZmFyZSByZXZlbnVlIGNvbXBhcmVkIHdpdGggdG8vZnJvbSBhaXJwb3J0cy4gVHdvIG90aGVyIGFyZWEgb2Ygc2VydmljZSB3b3J0aCBub3RpbmcgYXJlIE1pZC10b3duIChUaW1lcyBTcXVhcmUpLCBhbmQgRmluYW5jaWFsIERpc3RyaWN0LiBUaGUgVXBwZXIgV2VzdCBTaWRlIGhhcyBwb3RlbnRpYWwgdG9vLiAgCgrigKIJV2hpY2ggb2YgdGhlIGFpcnBvcnQgZXhwYW5zaW9uIG9wdGlvbnMgaXMgbW9zdCBiZW5lZmljaWFsIGFuZCB3aHk/IAoKPiBMYUd1YXJkaWEgYWlycG9ydCBleHBhbnNpb24gaXMgbW9zdCBiZW5lZmljaWFsIGNvbXBhcmVkIHdpdGggSkZLLiBJdCBoYXMgcmVsYXRpdmUgbGVzcyBwaWNrdXAgYW5kIGRyb3BvZmYgcG9pbnRzIGJ1dCBkZW1hbmQgaXMgbm90IGxvdy4gUGx1cyByaWRlcyB0by9mcm9tIExhR3VhcmRpYSBhcmUgZWNvbm9taWNseSBlZmZpY2llbnQuICAKCiMjIE1hbmlwdWxhdGUgZGF0YWZyYW1lCmBgYHtyfQptYXAzIDwtIG9ubHlfYWlycG9ydCAlPiUgc2VsZWN0KHBpY2t1cF9sb25naXR1ZGUscGlja3VwX2xhdGl0dWRlLCBzdXJjaGFyZ2UpICU+JSByb3VuZCg0KSAlPiUKICBncm91cF9ieShwaWNrdXBfbG9uZ2l0dWRlLHBpY2t1cF9sYXRpdHVkZSklPiUgc3VtbWFyaXNlKGNvdW50PW4oKSwgc3VyY2hhcmdlID0gc3VtKHN1cmNoYXJnZSkpIApgYGAKCiMjIFZpc3VhbGl6YXRhaW9uIC0tLSBQaWNrdXBzIGJ5IF9fU3VyY2hhcmdlX18KYGBge3IsIGVjaG89Rn0KdG90YWxfcmV2IDwtIGZ1bmN0aW9uKHgsIHRocmVzaG9sZCA9IDUwKSB7CiAgaWYgKHN1bSh4KSA8IHRocmVzaG9sZCkge3JldHVybiAoTkEpfQogIGVsc2Uge3JldHVybiAoc3VtKHgpKX0KfQpnZ3Bsb3QobWFwMywgYWVzKHg9cGlja3VwX2xvbmdpdHVkZSx5PXBpY2t1cF9sYXRpdHVkZSwgej1zdXJjaGFyZ2UpKSArCiAgZ2VvbV9wb2ludChzaXplPTAuNSwgY29sb3I9ImRhcmtncmV5IikgKwogIHN0YXRfc3VtbWFyeV9oZXgoZnVuID0gdG90YWxfcmV2LCBiaW5zPTEwMCwgYWxwaGE9MC45KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC03NC4wMzI0LCAtNzMuNzYyMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoNDAuNjI4LCA0MC44MzApKSArCiAgdGhlbWVfbWFwX2RhcmsoKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9InBpbmsiLCBoaWdoPSJyZWQiLCBsYWJlbHM9ZG9sbGFyLCB0cmFucz0ibG9nIiwgYnJlYWtzPWMoMTBeKDQ6NikpKSArCiAgbGFicyh0aXRsZSA9ICJOWUMgVGF4aXMgU3VyY2hhcmdlIC0tIFBpY2t1cCBMb2NhdGlvbiAyMDEzIikgKwogIGNvb3JkX2VxdWFsKCkKYGBgCgoqIF9fUGlja3VwcyBmcm9tIGFpcnBvcnRzIHJpZGVzIGNvbGxlY3QgbW9zdCBzdXJjaGFyZ2VzIHBlciByaWRlLl9fCgojIyBNYW5pcHVsYXRlIGRhdGFmcmFtZQpgYGB7cn0KbWFwNCA8LSBvbmx5X2FpcnBvcnQgJT4lIHNlbGVjdChkcm9wb2ZmX2xvbmdpdHVkZSxkcm9wb2ZmX2xhdGl0dWRlLCBzdXJjaGFyZ2UpICU+JSByb3VuZCg0KSAlPiUKICBncm91cF9ieShkcm9wb2ZmX2xvbmdpdHVkZSxkcm9wb2ZmX2xhdGl0dWRlKSU+JSBzdW1tYXJpc2UoY291bnQ9bigpLCBzdXJjaGFyZ2UgPSBzdW0oc3VyY2hhcmdlKSkgCmBgYAoKIyMgVmlzdWFsaXphdGlvbiAtLS0gRHJvcG9mZnMgYnkgX19TdXJjaGFyZ2VfXwpgYGB7ciwgZWNobz1GfQp0b3RhbF9yZXYgPC0gZnVuY3Rpb24oeCwgdGhyZXNob2xkID0gNTApIHsKICBpZiAoc3VtKHgpIDwgdGhyZXNob2xkKSB7cmV0dXJuIChOQSl9CiAgZWxzZSB7cmV0dXJuIChzdW0oeCkpfQp9CmdncGxvdChtYXA0ICU+JSBmaWx0ZXIoY291bnQgPiAyKSwgYWVzKHg9ZHJvcG9mZl9sb25naXR1ZGUseT1kcm9wb2ZmX2xhdGl0dWRlLCB6PXN1cmNoYXJnZSkpICsKICBnZW9tX3BvaW50KHNpemU9MC41LCBjb2xvcj0iZGFya2dyZXkiKSArCiAgc3RhdF9zdW1tYXJ5X2hleChmdW4gPSB0b3RhbF9yZXYsIGJpbnM9MTAwLCBhbHBoYT0wLjkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTc0LjAzMjQsIC03My43NjIxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9Yyg0MC42MjgsIDQwLjgzMCkpICsKICB0aGVtZV9tYXBfZGFyaygpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdz0icGluayIsIGhpZ2g9InJlZCIsIGxhYmVscz1kb2xsYXIsIHRyYW5zPSJsb2ciLCBicmVha3M9YygxMF4oMzo1KSkpICsKICBsYWJzKHRpdGxlID0gIk5ZQyBUYXhpcyBTdXJjaGFyZ2UgLS0gRHJvcG9mZiBMb2NhdGlvbiAyMDEzIikgKwogIGNvb3JkX2VxdWFsKCkKYGBgCgoqIF9fQW5vdGhlciBpbnNpZ2h0IHNob3dzIGZyb20gZHJvcG9mZiBtYXAgdGhhdCBMYSBHdWFyZGlhIGFjdHVhbGx5IGluY3VyIG1vcmUgc3VyY2hhcmdlIHRoYW4gSkZLLiBIZW5jZSBleHBhbmRpbmcgdG8gTGFHdWFyZGlhIG1heSBiZSBtb3JlIGJlbmVmaWNpYWwgZWNvbm9taWNseS5fXyAKCuKAoglXb3VsZCB5b3UgbGF1bmNoIGFpcnBvcnRzIGFzIGEgc2VwYXJhdGUgc2VydmljZSBvciBhcyBhIG5ldyBzZXJ2aWNlPyBXaHk/Cgo+IE15IHRob3VnaHQgcHJvY2VzcyBvZiB3aGV0aGVyIHRvIGxhdW5jaCBhaXJwb3J0cyBhcyBhIHNlcGFyYXRlIHNlcnZpY2UgaXMgdG8gbG9vayBhdCBkZW1hbmQgYW5kIHJldmVudWUgcmVsYXRpb25zLiBCYXNlZCBvbiBncmFwaHMgYWJvdmUsIGJvdGggbWV0cmljcyBleGhpYml0IGZhdm9yYWJsZSBzaWduYWwgZm9yIHN1Y2ggY29uc2lkZXJhdGlvbi4gSW4gYWRkaXRpb24sIHBlb3BsZSBhcmUgaW5jbGluZWQgdG8gcmVxdWVzdCBhaXJwb3J0IHJpZGUgaW4gYWR2YW5jZSBvbiB0aGVpciBwaG9uZXMsIHdoaWNoIGZpdHMgVmlhJ3Mgb3BlcmF0aW5nIGJ1c2luZXNzIHdlbGwuIAoKIyMgVmlzdWFsaXphdGlvbiAtLS0gUmlkZSBfX1RpbWVfXyBBbmFseXNpcwpgYGB7ciwgZWNobz1GfQpvbmx5X2FpcnBvcnQkcGlja3VwX2RhdGV0aW1lIDwtIHltZF9obXMob25seV9haXJwb3J0JHBpY2t1cF9kYXRldGltZSkKb25seV9haXJwb3J0JGhvdXIgPC0gaG91cihvbmx5X2FpcnBvcnQkcGlja3VwX2RhdGV0aW1lKQpvbmx5X2FpcnBvcnQkd2RheSA8LSB3ZGF5KG9ubHlfYWlycG9ydCRwaWNrdXBfZGF0ZXRpbWUpCgpvbmx5X2FpcnBvcnQgJT4lIGdncGxvdChhZXMoaG91cikpICsgZ2VvbV9iYXIoYWVzKGZpbGwgPSBmYWN0b3IoaG91cikpKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKCJOWUMgVGF4aSBSaWRlIENvdW50cyBieSBIb3VyIGZvciBFYWNoIFdlZWtkYXkiKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIpKSArIGZhY2V0X2dyaWQofiB3ZGF5KQpgYGAKCiogX19CeSBwYWNrYWdlIGRlZmluaXRpb24sIFN1bmRheSBpcyAxLl9fCgrigKIJV291bGQgeW91IGxhdW5jaCBhaXJwb3J0IHJpZGVzIGR1cmluZyBhbGwgb3VyIGhvdXJzIG9mIHNlcnZpY2UgKDZhbS0xMmFtIG9uIHdlZWtkYXlzIGFuZCAxMGFtLTEyYW0gb24gU2F0dXJkYXlzKSBvciBvbmx5IGZvciBjZXJ0YWluIGhvdXJzPyBXaGljaCBob3Vycz8KCj4gQXMgc2hvd24gaW4gZ3JhcGggYWJvdmUsIHRoZSBjdXJyZW50IGhvdXJzIG9mIHNlcnZpY2Ugc2VlbSB0byBhbG1vc3QgY292ZXIgbW9zdCBoaWdoIGRlbWFuZCB0aW1lLiBUaGF0IHNhaWQsIEkgd291bGQgYWxsb2NhdGUgbW9yZSByZXNvdXJjZXMgYXJvdW5kIG1pZCBhZnRlcm5vb24sIGVzcGVjaWFsbHkgb24gV2VkbmVzZGF5IGFuZCBUaHVyc2RheS4gCgojIyBWaXN1YWxpemF0aW9uIC0tLSBGYXJlIF9fUGVyIFBhc3Nlbmdlcl9fIEFuYWx5c2lzCmBgYHtyLCBlY2hvPUZ9Cm9ubHlfYWlycG9ydCAlPiUgZ2dwbG90KGFlcyhmYWN0b3IoaG91ciksIGZpbGw9ZmFjdG9yKGhvdXIpKSkgKyBzdGF0X3N1bW1hcnlfYmluKGFlcyh5ID0gZmFyZV9hbW91bnQvcGFzc2VuZ2VyX2NvdW50KSwgZnVuLnkgPSJtZWFuIiwgZ2VvbSA9ImJhciIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsgZ2d0aXRsZSgiTllDIFRheGkgUmlkZSBGYXJlIFBlciBQYXNzZW5nZXIgYnkgSG91ciBhbmQgYnkgV2Vla2RheSIpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIikpICsgZmFjZXRfd3JhcCh+d2RheSkgKyB4bGFiKCJob3VyIikgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiwgc2l6ZT0xMiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLCB2anVzdD0wLjUsIHNpemU9NykpCgpgYGAKCuKAoglIb3cgd291bGQgeW91IHByaWNlIGFpcnBvcnQgcmlkZXMgYW5kIHdoeSAob3VyIGN1cnJlbnQgbW9kZWwgaXMgYSAkNS4wMCBmbGF0IGZlZSB3ZWVrZGF5cyBiZWZvcmUgOXBtIGFuZCAkNS45NSB3ZWVrbmlnaHRzIGFmdGVyIDlwbSBhbmQgYWxsIGRheSBTYXR1cmRheXMpPwoKPiBBY2NvcmRpbmcgdG8gdGF4aSByaWRlIGZhcmUsIGRpc2NvdW50ZWQgYnkgbnVtYmVyIG9mIHBhc3NlbmdlciwgSSBzdGlsbCB0aGluayAkNSBmbGF0IGZlZSBpcyBxdWl0ZSBsb3csIGNvbXBhcmVkIHdpdGggYWxtb3N0ICQzMCBkb2xsYXIgbm9ybWFsIHJhdGUuIElmIGl0IGlzIFZpYSdzIGluaXRpYWwgc3RyYXRlZ3kgdG8gdXNlIGFkdmFudGFnZW91cyBwcmljZSBpbmNlbnRpdmUgdG8gc3RhcnQgdGhlIGJ1c2luZXNzLCBpdCBtYWtlcyBzZW5zZS4gSG93ZXZlciwgYXMgVmlhIGVzdGFibGlzaGVzIGl0c2VsZiwgaXQgbWF5IG5vdCBiZSBvcHRpbWFsIGFueW1vcmUgdG8gbGF5IHRvbyBtdWNoIG1vbmV5IG9uIHRoZSB0YWJsZS4gSGVuY2UsIEkgd291bGQgc3VnZ2VzdCBhIGRpZmZlcmVudCBwcmljZSB0aWVyLiBJbiBvcmRlciB0byBtYWtlIHByb2ZpdCBhbmQgYWxsZXZpYXRlIHRyYWZmaWMgY29uZ2VzdGlvbiwgSSB3aWxsIGNoYXJnZSAkMTAgdG8gJDE1IGZsYXQgZmVlLCBpbmNsdWRpbmcgdGF4ICh0aGUgZXhhY3QgYW1vdW50IGNhbiB2YXJ5IGFjY29yZGluZyB0byBtb2RlbCBhY2N1cmFjeSkgZm9yIHJlZ3VsYXIgb3BlcmF0aW5nIGhvdXJzLCBhbmQgJDEgdG8gJDUgc3VyY2hhcmdlIGZvciBydXNoIGhvdXJzIGJldHdlZW4gNmFtIHRvIDdhbSBhbmQgMThwbSB0byAxOXBtLiAgCgojIFF1YWxpdGF0aXZlIFF1ZXN0aW9uczogCgrigKIJV2hhdCBhZGRpdGlvbmFsIGRhdGEgd291bGQgeW91IGxpa2UgdG8gc2VlIGluIG9yZGVyIHRvIGFuc3dlciBxdWVzdGlvbnMgMS01IG1vcmUgY29uZmlkZW50bHkgYW5kIGhvdyB3b3VsZCB5b3UgaW5jb3Jwb3JhdGUgaXQ/Cgo+IEkgd291bGQgd2FudCB0byBzZWUgdGhyb3VnaCB3aGF0IGNoYW5uZWwgYXJlIHRob3NlIHRheGkgcmlkZXMgYXJlIHJlcXVlc3RlZC4gRm9yIGV4YW1wbGUsIHdlIG1heSBzZWUgZ3Jvd2luZyB1c2FnZSBvZiBtb2JpbGUgYXBwbGljYXRpb24gZm9yIGFpcnBvcnRzIHJpZGVzIGFzIHBlb3BsZSBtYXkgZmVlbCBtb3JlIGFzc3VyZWQgdG8gcmVxdWVzdCByaWRlIGluIGFkdmFuY2Ugb24gdGhlaXIgbW9iaWxlIHBob25lcywgdmVyc2FzIHRyYWRpdGlvbmFsbHkgZ2V0dGluZyBjYWJzIG9uIHRoZSBzdHJlZXQuIFRoaXMgd2lsbCBhbHNvIHByb3ZpZGUgbW9yZSBpbmZvcm1hdGlvbiBpZiB3ZSBuZWVkIHRvIGxhdW5jaCBhaXJwb3J0IHJpZGVzIGFzIHNlcGFyYXRlIHNlcnZpY2UuIAoK4oCiCUhvdyBtaWdodCB5b3VyIGFuc3dlciBjaGFuZ2Ugb3ZlciB0aW1lPyBXaGF0IFZpYSBkYXRhIHdvdWxkIHlvdSBtb25pdG9yIHRvIGVuc3VyZSB0aGUgcHJvcG9zZWQgZXhwYW5zaW9uIHdhcyBhIGdvb2QgYnVzaW5lc3MgZGVjaXNpb24/Cgo+IE15IGFuc3dlciBtaWdodCBjaGFuZ2UgYWxvbmcgd2l0aCB0aGUgY2hhbmdlIG9mIGNvbXBldGl0aXZlIGxhbmRzY2FwZSBvZiBPbi1kZW1hbmQgdHJhbnNwb3J0YXRpb24uIFRoZXJlZm9yZSwgSSB3b3VsZCBtb25pdG9yIFZpYSdzIGNvbXBldGl0b3JzJyBkYXRhIHRvIGFzc2VzcyB0aGUgZWZmaWNpZW5jeSBvZiB0aGUgcHJvcG9zZWQgZXhwYW5zaW9uLiAK