Introduction and Rationale of Project

This project is spearheaded by Lily Moreno, Director of Marketing, to understand the differences between the cycling uses of casual riders and annual members. By using data analysis tools and techniques, the team is going to discover patterns and behavior and other factors that will:

For the sake of reference, the following definition applies.


Business Task

The marketing analyst team has to find answers to the following questions:

  1. How do annual members and casual riders use Cyclistic bikes differently?
  2. Why would casual riders buy Cyclistic annual memberships?
  3. How can Cyclistic use digital media to influence casual riders to become members?

I am tasked with using all data available to answer question 1.

My deliverables

I will be producing the following deliverables for my part in the project:

  • Executive summary of business task and analysis
  • Documentation of cleaning and manipulation of data
  • Supporting visualizations and key findings
  • Main analysis and top three recommendations
  • An appendix of all data sources used

Expectations of key stakeholders

After company meetings, the expectations of key stakeholders are as follows:

Company executives - Data needs to be fully analyzed and presented to convince company executives that a marketing strategy targeting casual riders would result in greater profits.

Director of marketing - Data and analysis supporting or questioning the market strategy of targeting casual riders needs to be presented.

Marketing analyst members - Data and analysis on how casual riders differ in bike usage from annual members needs to be presented to other members.


Data Analysis Process

Key question: How do annual members and casual riders use Cyclistic bikes differently

To answer the above question, data from 12 months of trip data for the year 2022 is extracted. For a review of the data used in this analysis, please click this link. Data is provided by Motivate International Inc under a license from divvybikes. As we do not have first hand access to data, we need to check for integrity, accuracy, consistency and completeness during the data cleaning process.

There is also a need to check on how members and casual riders are charged for their rides. (Is it based on time spent on the bike, distance traveled, type of bike used etc?) According to my own research, members and casual riders are charged based on the information from divvybikes.

Information about data used

The set of data from Motivational Inc. provides monthly information about usage of bikes with parameters:

  • ride_id
  • start and end time
  • start station and end station
  • start and end latitude and longtitude
  • member types (casual or member)

To get an idea on the difference in behavior, data will be analyzed in the following aspects among members and casual riders:

  1. How frequently each type of bike is used
    1. number of rides per type of bike grouped by member type
    2. how number of rides per type of bike vary by month and week of days grouped by member type
  2. Time spent on each type of bike
    1. total and average duration per type of bike grouped by member type
    2. how total and average duration per type of bike varies by month grouped by member type

Based on pricing information provided by divvybikes, the revenue by customer type are calculated as follows:

Members Pricing

Classic bike

  • $10 per month for 45 minutes/ride
  • An extra $0.16/min beyond 45 minutes

Electric bike

  • $0.16/min per ride

Scooters

  • $0.25/min per ride

Casual Riders Pricing

Classic bike single rides

  • $1 per unlock
  • $0.16/min per ride

Classic bike day rides

  • $15 per day for 3 hours/ride
  • $0.16/min per ride beyond 3 hours

Electric bike/scooters rides

  • $1 per unlock
  • $0.39/min per ride

Limitations of data

Limitations of data includes not being able to link trip behavior to actual users as they are personally identifiable information, not being able to determine if riders live in the Cyclistic service area (and therefore how that impacts rider behavior) and whether each user made multiple trips with different ride_id. This impacts calculating revenue for member and full day pass rides as each member and full day pass rider may be tied to multiple ride_ids.

Assumptions about data

Since we cannot know what kind of plan each rider subscribed to for each ride, we assume the following:

  1. For casual riders, any classic bike trip duration above 93 minutes each ride are subscribers to day rides as the day ride of $15 dollars per day are more economic. I assume casual riders will go for the most economic option.

  2. Since we cannot attribute multiple ride_id to one rider from the trip data, only the revenue from trip duration charged by minutes is calculated. I assume there are member and day ride subscription lists which will give a straightforward calculation of total monthly revenues from membership fees and day ride subscribers.


Data Cleaning Worklog

The original data are kept intact and stored in a different folder from the cleansed and processed data to allow other teams to work with the original data.

The directory for the original data is %user%/desktop/bike_trips_data_raw.

The directory for the cleansed and processed data is %user%/desktop/bike_trips_data_processed.

Data sorting and filtering in Excel

Step 1. Since the distance traveled and location of bike riders are not important for determining the profitability of rides, the following columns of data are removed from the tables:

  • start_station_name
  • start_station_id
  • end_station_name
  • end_station_id
  • start_lat
  • start_lng
  • end_lat
  • end_lng

Step 2. To better analyse the difference in riding habits between members and casual riders, the table for each month of data is separated into data for members and casual riders. Any blank rows are also deleted in Excel using Home -> Find & Select -> Go to Special, select “Blanks” and then “Delete Sheet Rows”.

Step 3. Ensure columns started_at and ended_at are formatted as d/m/yyyy h:mm. Ensure the other columns are formatted as text.

Step 4. Set up another column called duration and format it as h:mm. Then use ended at - started at to get duration elapsed. Filter duration for any abnormalities and correct data that sorts ended at as started as and vice versa.

Step 5. To prevent accidental deletion of data, the sheet is protected with Review -> Protect Sheet. The following items are checked:

  • Select locked cells
  • Select unlocked cells
  • Format cells
  • Format columns
  • Format rows
  • Sort
  • Use PivotTable and PivotChart

Repeat all the steps 1 to 5 above for all member and casual data.

Data Analysis in SQL

Step 1. Upload all the data into SQL.

Casual riders data

Step 2. To determine the day of week spent on each ride, I extracted the start and end dates of the rides. For the casual riders, I used the following SQL query on each table:

SELECT  

ride_id,
rideable_type AS bike_type,
EXTRACT(DATE FROM started_at) AS start_date,
FORMAT_DATE("%A", EXTRACT(DATE FROM started_at)) AS start_day,
EXTRACT(DATE FROM ended_at) AS end_date,
FORMAT_DATE("%A", EXTRACT(DATE FROM ended_at)) AS end_day,
type_of_rider

FROM `case-study-divvybikes.2022_biketripdata_casual.2022-xx-biketripdata-c`

WHERE rideable_type = "classic_bike"

ORDER BY started_at

Then I choose “Save Results” another BigQuery table and name it “2022_xx_cclassicbikedata_dayofweek”. I repeat this step for electric_bike (2022_xx_celectricbikedata_dayofweek) and docked_bike (2022_xx_cdockedbikedata_dayofweek).

To determine number of classic bike rides from casual riders for every day of each month, I used the following SQL query on each table:

SELECT 

start_day,
COUNT(ride_id) AS number_of_rides,

 FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_xx_cclassicbikedata_dayofweek` 

 GROUP BY start_day

Then I choose “Save Results” as local CSV file and name it “2022_xx_cclassicbikedata_bydays”.I repeat this step for electric_bike (2022_xx_celectricbikedata_bydays) and docked_bike (2022_xx_cdockedbikedata_bydays).

Step 3. To determine the time spent on each ride, columns are separated into date and time. For the casual riders, I used the following SQL query on each table:

SELECT  

  rideable_type AS bike_type,
  DATETIME_DIFF(ended_at, started_at, MINUTE) AS duration_of_trip_mins,
  type_of_rider

FROM `case-study-divvybikes.2022_biketripdata_casual.2022-xx-biketripdata-c` 

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_biketripedatawithduration_c

Step 4. To determine the duration of time spent on classic bikes by casual riders, I run the following query:

SELECT  

*

FROM `case-study-divvybikes.2022_biketripdata_casual.2022_xx_biketripedatawithduration_c` 

WHERE bike_type = "classic_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_cclassicbikedata_duration”.

Step 5. To determine the duration of time spent on electric bikes by casual riders, I run the following query:

SELECT  

*

FROM `case-study-divvybikes.2022_biketripdata_casual.2022_xx_biketripedatawithduration_c` 

WHERE bike_type = "electric_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_celectricbikedata_duration”.

Step 6. To determine the duration of time spent on docked bikes by casual riders, I run the following query:

SELECT  

*

FROM `case-study-divvybikes.2022_biketripdata_casual.2022_xx_biketripedatawithduration_c` 

WHERE bike_type = "docked_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_cdockedbikedata_duration”.

To determine minimum, maximum, average and total duration of classic bike rides from casual riders for each month, I used the following SQL query on each table:

SELECT  

bike_type,
MIN(duration_of_trip_mins) AS min_duration_of_trips_mins,
MAX(duration_of_trip_mins) AS max_duration_of_trips_mins,
AVG(duration_of_trip_mins) AS average_duration_of_trips_mins,
SUM(duration_of_trip_mins) AS total_duration_of_trips_mins

FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_xx_cclassicbikedata_duration` 

GROUP BY bike_type

Then I choose “Save Results” as local CSV file and name it “2022_xx_cclassicbikedata_bymins”.I repeat this step for electric_bike (2022_xx_celectricbikedata_bymins) and docked_bike (2022_xx_cdockedbikedata_bymins).

Step 7: Then based on our assumption of classic bike day rides, I created the following query to filter out a table for day rides on classic bikes based on duration of trips above 93 minutes:

SELECT  

bike_type,
duration_of_trip_mins,
type_of_rider 

FROM `case-study-divvybikes.2022_biketripdata_casual.2022_xx_biketripedatawithduration_c` 

WHERE duration_of_trip_mins > 93
and bike_type= "classic_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_biketripdatadayrides_c

Step 8. Next I create another table for classic bike single rides for all duration of trips equal or less than 93 minutes.

SELECT  

bike_type,
duration_of_trip_mins,
type_of_rider 

FROM `case-study-divvybikes.2022_biketripdata_casual.2022_xx_biketripedatawithduration_c` 

WHERE duration_of_trip_mins <= 93 
and bike_type="classic_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_biketripdatasinglerides_c

Step 9. Finally I create a third table for all ride durations for non classic bikes.

SELECT  

bike_type,
duration_of_trip_mins,
type_of_rider 

FROM `case-study-divvybikes.2022_biketripdata_casual.2022_xx_biketripedatawithduration_c` 

WHERE bike_type!="classic_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_biketripdata_nonclassicbikes_c

Step 10. Now to sort out a table of classic bike day rides who pay no more than $15, I used the following query:

SELECT  

bike_type,
duration_of_trip_mins,
type_of_rider 

 FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_xx_biketripdatadayrides_c` 

WHERE duration_of_trip_mins <= 180 

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_dayridesnotmorethan3hours_c”.

Step 11. To further organise the classic bike day rides, a table is created to filter out the results for day rides with trip duration above 180 minutes (3 hours) but not more than 1440 minutes (a day).

SELECT  

bike_type,
duration_of_trip_mins,
duration_of_trip_mins - 180 AS trip_duration_charged_by_min,
type_of_rider 

 FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_xx_biketripdatadayrides_c` 

WHERE duration_of_trip_mins > 180 and duration_of_trip_mins <= 1440

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_dayrideswithinoneday_c

Step 12. Finally, a table for classic bike day rides that exceed 1 day is created with the following query:

SELECT  

bike_type,
duration_of_trip_mins,
1440 - 180 AS day1_trip_of_duration_charged_by_min,
CASE
  WHEN duration_of_trip_mins > 1620 
  THEN "duration_of_trips_mins - 1620"
  ELSE NULL 
  END AS day2_trip_of_duration_charged_by_min,
type_of_rider,

 FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_xx_biketripdatadayrides_c` 

WHERE duration_of_trip_mins > 1440

ORDER BY duration_of_trip_mins

This creates two extra columns which calculates the trip duration charged by minutes for day 1 as well as day 2 if the trip duration for day 2 exceeds 3 hours. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_dayridesaboveoneday_c”.

The above steps 1 to 12 are repeated for all 12 months of casual riders data.

Member riders data

Step 2. To determine the day of week spent on each ride, I extracted the start and end dates of the rides. For the members, I used the following SQL query on each table:

SELECT  

ride_id,
rideable_type AS bike_type,
EXTRACT(DATE FROM started_at) AS start_date,
FORMAT_DATE("%A", EXTRACT(DATE FROM started_at)) AS start_day,
EXTRACT(DATE FROM ended_at) AS end_date,
FORMAT_DATE("%A", EXTRACT(DATE FROM ended_at)) AS end_day,
type_of_rider

FROM `case-study-divvybikes.2022_biketripdata_member.2022-xx-biketripdata-m`

WHERE rideable_type = "classic_bike"

ORDER BY started_at

Then I choose “Save Results” another BigQuery table and name it “2022_xx_mclassicbikedata_dayofweek”. I repeat this step for rideable_type = “electric_bike” (2022_xx_melectricbikedata_dayofweek).

To determine number of classic bike rides from members for every day of each month, I used the following SQL query on each table:

SELECT 

start_day,
COUNT(ride_id) AS number_of_rides,

 FROM `case-study-divvybikes.2022_classicbiketripdata_member.2022_xx_mclassicbikedata_dayofweek` 

 GROUP BY start_day

Then I choose “Save Results” as local CSV file and name it “2022_xx_mclassicbikedata_bydays”.I repeat this step for electric_bike (2022_xx_melectricbikedata_bydays).

Step 3. To determine the time spent on each ride, columns are separated into date and time. For the member riders, I used the following SQL query on each table:

SELECT  

  rideable_type AS bike_type,
  DATETIME_DIFF(ended_at, started_at, MINUTE) AS duration_of_trip_mins,
  type_of_rider

FROM `case-study-divvybikes.2022_biketripdata_member.2022-xx-biketripdata-m` 

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_biketripedatawithduration_m”.

Step 4. To determine the duration of time spent on classic bikes by members, I run the following query:

SELECT  

*

FROM `case-study-divvybikes.2022_biketripdata_member.2022_xx_biketripedatawithduration_m` 

WHERE bike_type = "classic_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_mclassicbikedata_duration”.

Step 5. To determine the duration of time spent on electric bikes by members, I run the following query:

SELECT  

*

FROM `case-study-divvybikes.2022_biketripdata_member.2022_xx_biketripedatawithduration_m` 

WHERE bike_type = "electric_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_melectricbikedata_duration”.

To determine minimum, maximum, average and total duration of classic bike rides from members for each month, I used the following SQL query on each table:

SELECT  

bike_type,
MIN(duration_of_trip_mins) AS min_duration_of_trips_mins,
MAX(duration_of_trip_mins) AS max_duration_of_trips_mins,
AVG(duration_of_trip_mins) AS average_duration_of_trips_mins,
SUM(duration_of_trip_mins) AS total_duration_od_trips_mins

FROM `case-study-divvybikes.2022_classicbiketripdata_member.2022_xx_mclassicbikedata_duration` 

GROUP BY bike_type

Then I choose “Save Results” as local CSV file and name it “2022_xx_mclassicbikedata_bymins”.I repeat this step for electric_bike (2022_xx_melectricbikedata_bymins).

Step 6. Next, I filter out members who travel for less than 45 minutes each ride using classic bikes.

SELECT  

bike_type,
duration_of_trip_mins,
type_of_rider 

FROM `case-study-divvybikes.2022_biketripdata_member.2022_xx_biketripedatawithduration_m` 

WHERE duration_of_trip_mins <= 45
and bike_type= "classic_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikeridesnotabove45mins_m”.

Step 7. Next, I filter out members who travel for more than 45 minutes each ride using classic bikes. I also calculate a new column of trip duration charged by minutes.

SELECT  

bike_type,
duration_of_trip_mins,
duration_of_trip_mins - 45 AS trip_duration_charged_by_min,
type_of_rider 

FROM `case-study-divvybikes.2022_biketripdata_member.2022_xx_biketripedatawithduration_m` 

WHERE duration_of_trip_mins > 45
and bike_type= "classic_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikeridesabove45mins_m”.

Step 8. Next, I filter out members who travel using electric bikes.

SELECT  

bike_type,
duration_of_trip_mins,
type_of_rider 

FROM `case-study-divvybikes.2022_biketripdata_member.2022_xx_biketripedatawithduration_m` 

WHERE bike_type = "electric_bike"

ORDER BY duration_of_trip_mins

Then I choose “Save Results” as another BigQuery table and name it “2022_xx_electricbikerides_m”.

Step 9. Finally as a safety check, I query for all results that are neither classic bike or electric bike.

SELECT  

bike_type,
duration_of_trip_mins,
type_of_rider 

FROM `case-study-divvybikes.2022_biketripdata_member.2022_xx_biketripedatawithduration_m` 

WHERE bike_type!="electric_bike" AND bike_type!="classic_bike"

ORDER BY duration_of_trip_mins

If there is a table for this query, I choose “Save Results” as another BigQuery table and name it “2022_xx_otherbikerides_m”.

The above steps 1 to 9 are repeated for all 12 months of member riders data.

Summarized Data For Revenue Calculation (SQL)

Casual riders data

Step 1. For ease of calculating revenues, I query the table about classic bike single rides for casual riders using the following SQL query:

SELECT 

bike_type,
COUNT(bike_type) AS no_of_rides,
SUM(duration_of_trip_mins) AS total_duration_mins

FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_xx_biketripdatasinglerides_c`

GROUP BY bike_type

This counts the total number of rides on classic bikes for single ride subscribers and also the total duration of all single rides on classic rides. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikesinglerides_c”.

Step 2. Then I create a table that summarises number of one day rides not above 3 hours.

SELECT  

bike_type,
COUNT(bike_type) AS number_of_rides

FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_01_dayridesnotmorethan3hours_c` 

GROUP BY bike_type

This counts the total number of rides on classic bikes for day ride subscribers with rides not exceeding 3 hours. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikesonedayrides_notabove3hours_c”.

Step 3. Next , I create a table that summarises number of one day rides and total duration charged by minutes.

SELECT  

bike_type,
COUNT(bike_type) AS no_of_oneday_rides,
SUM(trip_duration_charged_by_min) AS total_duration_charged_by_min

FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_01_dayrideswithinoneday_c`

GROUP BY bike_type

This counts the total number of rides on classic bikes for one day ride subscribers and total duration charged by minutes. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikesonedayrides_notabove1day_c”.

Step 4. Next, I create a table that summarises number of two day rides and total duration charged by minutes for first day.

SELECT  

bike_type,
COUNT(bike_type) AS no_of_twoday_rides,
SUM(day1_trip_of_duration_charged_by_min) AS total_day1_trip_duration_charged_by_min

FROM `case-study-divvybikes.2022_classicbiketripdata_casual.2022_01_dayridesaboveoneday_c`

GROUP BY bike_type

This counts the total number of rides on classic bikes for two day ride subscribers and total duration charged by minutes for first day. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikestwodayrides_c”.

Step 5. Finally, I create a table that summarizes number of rides and total duration of rides charged by other bike types.

SELECT  

bike_type,
COUNT(bike_type) AS no_of_rides,
SUM(duration_of_trip_mins) AS total_duration_charged

FROM `case-study-divvybikes.2022_nonclassicbiketripdata_casual.2022_xx_biketripdata_nonclassicbikes_c`

GROUP BY bike_type

This counts the total number of rides on other bikes for casual riders and total duration charged by minutes. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_otherbikerides_c”.

The above steps 1 to 5 are repeated for all 12 months of casual riders data.

Member riders data

Step 1. For ease of calculating revenues, I query the table about classic bike rides not above 45 minutes for members using the following SQL query:

SELECT 

bike_type,
COUNT(bike_type) AS no_of_rides,
SUM(duration_of_trip_mins) AS total_trip_duration

`case-study-divvybikes.2022_classicbiketripdata_member.2022_xx_classicbikeridesnotabove45mins_m`

GROUP BY bike_type

This counts the total number of rides on classic bikes for members whose rides do not exceed 45 minutes. In other words, each ride is only charged monthly. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikerideschargedmonthly_m”.

Step 2. Then I create a table that summarises number of classic bike rides above 45 minutes for members.

SELECT  

bike_type,
COUNT(bike_type) AS no_of_rides,
SUM(trip_duration_charged_by_min) AS total_trip_duration_charged

FROM `case-study-divvybikes.2022_classicbiketripdata_member.2022_xx_classicbikeridesabove45mins_m` 

GROUP BY bike_type

This counts the total number of classic bike rides for members and total duration charged by minutes. In other words, each ride has a monthly charge as well as a charge per minute exceeding 45 minutes. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_classicbikerideswithminutecharges_m”.

Step 3.

SELECT 

bike_type,
COUNT(bike_type) AS no_of_rides,
SUM(duration_of_trip_mins) AS total_duration_charged

FROM `case-study-divvybikes.2022_nonclassicbiketripdata_member.2022_xx_electricbikerides_m`

GROUP BY bike_type

This counts the total number of classic bike rides for members and total duration charged by minutes. In other words, each ride has a monthly charge as well as a charge per minute exceeding 45 minutes. Then I choose “Save Results” as another BigQuery table and name it “2022_xx_electricbikerideschargedbymin_m”.

The above steps 1 to 3 are repeated for all 12 months of member riders data.


Data Visualization in Excel, Tableau and R

Excel

After creating all those monthly tables in SQL BigQuery, I downloaded them into Excel and put them together into annual tables of data to compare trends across months. The following Excel tables are assembled:

  • 2022_annual_classicbikedata_bydays_casual
  • 2022_annual_classicbikedata_bydays_member
  • 2022_annual_classicbikedata_bymins_casual
  • 2022_annual_classicbikedata_bymins_member
  • 2022_annual_dockedbikedata_bydays_casual
  • 2022_annual_dockedbikedata_bymins_casual
  • 2022_annual_electricbikedata_bydays_casual
  • 2022_annual_electricbikedata_bydays_member
  • 2022_annual_electricbikedata_bymins_casual
  • 2022_annual_electricbikedata_bymins_member
  • 2022rev_classicbikeonedayrides_notabove1day_c
  • 2022rev_classicbikeonedayrides_notabove3hoursperride_c
  • 2022rev_classicbikerideswithmonthly&mincharges_m
  • 2022rev_classicbikerideswithonlymonthlycharge_m
  • 2022rev_classicbikesinglerides_c
  • 2022rev_classicbiketwodayrides_c
  • 2022rev_dockedbikerides_c
  • 2022rev_electricbikerides_c
  • 2022rev_electricbikechargedbymin_m

Based on these tables, I used Excel to draw up charts to visualize bike usage and revenue patterns throughout the year.

R

I also attempted to draw line plot on one data table of the classic bike riding data for casual users using the following code in R.

library(tidyverse)
library(dplyr)
library(ggplot2)
library(data.table)
library(readr)
X2022_annual_classicbikedata_bymonth_casual <- read_csv("bike_trips_data_processed/2022_annual_classicbikedata_bymonth_casual.csv")

## Setting a data frame as data table
setDT(X2022_annual_classicbikedata_bymonth_casual) 

## Sorts table into long form 
df1 <- melt(X2022_annual_classicbikedata_bymonth_casual,"Months")
print(df1) 

## Reorders Months from Jan to Dec
df1$Months = factor(df1$Months, levels = month.abb) 

## Actual plot
ggplot(df1, aes(x=Months, y=value, group=variable, colour=variable)) +
  geom_line()+
  geom_point()+
  ylab("Number of Rides")+
  labs(colour="Days of Week")+
  labs(title="Classic Bike Rides - Casual")

I drew a bar chart on another data table of the electric bike riding data for members using the following code in R.

library(tidyverse)
library(dplyr)
library(ggplot2)
library(data.table)
library(readr)
X2022_annual_electricbikedata_byduration_member <- read_csv("bike_trips_data_processed/2022_annual_electricbikedata_byduration_member.csv")
X2022_annual_electricbikedata_byavgduration_member <- read_csv("bike_trips_data_processed/2022_annual_electricbikedata_byavgduration_member.csv")

## Setting data frames as data tables
setDT(X2022_annual_electricbikedata_byduration_member)
setDT(X2022_annual_electricbikedata_byavgduration_member)

## Sorts table into long form 
df2 <- melt(X2022_annual_electricbikedata_byduration_member,"month")
print(df2) 
df3 <- melt(X2022_annual_electricbikedata_byavgduration_member,"month")
print(df3)

## Reorders Months from Jan to Dec
df2$month = factor(df2$month, levels = month.abb)
df3$month = factor(df3$month, levels = month.abb) 

## Actual plots
ggplot(df2, aes(month, value, fill=variable, label=value)) +
  geom_bar(stat="identity", position = "dodge")+
  geom_text(vjust=-0.5, size=1.5)+
  ylab("Duration (Days)")+
  labs(fill="")+
  labs(title="Electric Bike Rides - Member")

ggplot(df3, aes(month, value, fill=variable, label=value)) +
  geom_bar(stat="identity", position = "dodge")+
  geom_text(vjust=-0.5, size=1.5)+
  ylab("Duration (Mins)")+
  labs(fill="")+
  labs(title="Electric Bike Rides - Member")

Tableau

I used Tableau to give better visualisations on the starting location of bike usage by casual riders as well as trip revenue from classic bike for members in 2022.

Viz 1: Trip Revenue of Classic Bike Rides for Members

Viz 2: Starting Location for Casual Riders


Analysis & Recommendations

Riding patterns of casual riders and members

The following comparisons were made between casual riders and members:

  1. Riding patterns every day of the week by each month of 2022
  2. Riding patterns every month of 2022 by each day of week
  3. Revenue patterns for 2022 for classic and electric bikes

Since we cannot trace each ride id to each rider, it is impossible to determine the true revenue from casual riders and members unless we are given more information about membership subscription revenue and day pass revenues. Alternatively, it is better to compare trip revenue charged by minute for each type of bike.

Classic bikes

For both casual riders and members, number of rides for classic bikes seem to peak around the middle of the year and decline by the end of the year. For casual riders, the peak is in July on Saturdays, reaching 40k rides. For members, the peak is in Jun on Thursdays, reaching 42k rides. For both casual riders and members, number of rides for classic bikes are lowest in January and February. For casual riders, number of rides are generally higher in June and July while that for members is in June. In general, members have higher number of rides for classic bikes than casual riders.

Number of classic bike rides of causal riders by days

Number of classic bike rides of members by days

Number of classic bike rides of casual riders by month

Number of classic bike rides of members by month

However, if we look at duration of rides, casual riders have higher total duration of rides at its peak compared to members. This could be due to the greater number of casual riders than members of classic bikes or due to the longer time casual riders spend on classic bike rides during the peak month (June). This is answered partly by looking at the average duration of each ride on classic bikes by casual riders and members. In general, casual riders spend a longer average time on classic bikes (over 20 minutes per ride every month) with the highest average duration being 32 minutes in March. Members, on the other hand, spend less than 20 minutes per ride every month with highest average duration being 15 minutes in July.

Total duration on classic bikes by casual riders

Total duration on classic bikes by members

Average duration each ride on classic bikes by casual riders

Average duration each ride on classic bikes by members

If we look at the total number of rides by each day of the week or by month, similar patterns occur. The total number of rides for members are generally higher than casual riders. The total number of rides for casual members tend to peak on Saturday whilst that of members tend to be on Tuesdays. This could be due to the fact that casual riders tend to use classic bikes for leisure while members tend to use classic bikes for work travel.

Total classic bike rides of casual riders by days

Total classic bike rides of members by days

Total classic bike rides of casual riders by months

Total classic bike rides of members by months

This all makes sense as casual riders would want to spend more time on each ride due to the unlock cost of 1 dollar per ride they incur for single rides. Thus they may choose to ride lesser number of times but extend the duration of each ride since the cost of $0.16 per minute is the same as members for classic bikes. On the other hand, the number of rides is irrelevant to members who do not have to pay unlock costs per ride but they may want to save money by limiting each ride duration to no more than 45 minutes as much as possible.

For classic bikes, trip revenues for both members and casual riders tend to peak in June. Trip revenue for members are only more profitable than casual riders who buy the full day pass for one day. Trip revenue is highest for casual riders who buy single rides.

Trip revenue of classic bike for members

Trip revenue of classic bike full day pass for casual riders

Trip revenue of classic bike single rides for casual riders

Trip revenue of classic bike two full day passes for casual riders

Electric bikes

For casual riders, number of rides for electric bikes seem to peak around July while for members, the peak happens in September and decline by the end of the year. For casual riders, the peak is on Saturdays, reaching 47k rides. For members, the peak is on Thursdays, reaching 39k rides. For both casual riders and members, number of rides for electric bikes are lowest in January and February. For casual riders, number of rides are generally higher in July while that for members is in August. In general, members have higher number of rides for electric bikes than casual riders.

Number of electric bike rides of causal riders by days

Number of electric bike rides of members by days

Number of electric bike rides of casual riders by month

Number of electric bike rides of members by month

However, if we look at duration of rides, casual riders have higher total duration of rides at its peak compared to members. This could be due to the greater number of casual riders than members of electric bikes or due to the longer time casual riders spend on electric bike rides during the peak month. This is answered partly by looking at the average duration of each ride on electric bikes by casual riders and members. In general, casual riders spend a longer average time on electric bikes with the highest average duration being 19 minutes per ride in May. Members, on the other hand, spend less than 15 minutes every month with highest average duration being 13 minutes per ride in June.

Total duration on electric bikes by casual riders

Total duration on electric bikes by members

Average duration each ride on electric bikes by casual riders

Average duration each ride on electric bikes by members

If we look at the total number of rides by each day of the week or by month, similar patterns occur. The total number of rides for members are generally higher than casual riders. The total number of rides for casual members tend to peak on Saturday whilst that of members tend to be on Thursdays. This could be due to the fact that casual riders tend to use electric bikes for leisure while members tend to use electric bikes for work travel.

Total electric bike rides of casual riders by days

Total electric bike rides of members by days

Total electric bike rides of casual riders by months

Total electric bike rides of members by months

This all makes sense as casual riders would want to spend more time on each ride due to the unlock cost of 1 dollar per ride they incur. Thus they may choose to ride lesser number of times but extend the duration of each ride. But since the charges on classic bikes are cheaper per minute, they would spend more time on average riding classic bikes than electric bikes. On the other hand, the number of rides is irrelevant to members who do not have to pay unlock costs per ride but they may want to save costs by spending more time on average on classic bikes since there are no charges for the first 45 minutes per ride.

For electric bikes, trip revenues for casual riders tend to peak in July whilst that for members tend to peak in August. Trip revenue for casual riders are always more profitable than members.

Trip revenue of electric bike for members

Trip revenue of classic bike for casual riders

Docked bikes

Since we do not have data for members who ride docked bikes, we look at riding patterns for casual riders instead. For casual riders, number of rides for docked bikes seem to peak at 8k rides around July on Saturdays and decline by the end of the year. Number of rides for docked bikes are lowest in December, January and February. Number of rides are generally higher in June. In general, casual riders have lowest number of rides for docked bikes.

Number of docked bike rides of causal riders by days

Number of classic bike rides of causal riders by days

Number of docked bike rides of causal riders by days

Number of docked bike rides of casual riders by month

Number of classic bike rides of casual riders by month

Number of electric bike rides of casual riders by month

However, if we look at duration of rides, docked bikes have second highest total duration of rides at its peak compared to other bike types. This could be due to the longer time casual riders spend on docked bike rides during the peak month since the number of rides are very low. This is answered by looking at the average duration of each ride on docked bikes by casual riders. In general, casual riders spend the longest average time on docked bikes compared to other bikes with the highest average duration being 223 minutes in Jan.

Total duration on docked bikes by casual riders

Total duration on classic bikes by casual riders

Total duration on electric bikes by casual riders

Average duration each ride on docked bikes by casual riders

Average duration each ride on classic bikes by casual riders

Average duration each ride on electric bikes by casual riders

If we look at the total number of rides by each day of the week or by month, similar patterns occur. The total number of rides for casual riders tend to peak on Saturday and in June and July. This could be due to the fact that casual riders tend to use docked bikes for leisure.

Total docked bike rides of casual riders by days

Total classic bike rides of casual riders by days

Total electric bike rides of casual riders by days

Total docked bike rides of casual riders by months

Total classic bike rides of casual riders by months

Total electric bike rides of casual riders by months

This all makes sense as casual riders would want to spend more time on each ride due to the unlock cost of 1 dollar per ride they incur. Thus they may choose to ride lesser number of times but extend the duration of each ride. But it is unclear why docked bikes have the highest average duration of rides compared to other bikes for casual riders.

For docked bikes, trip revenues for casual riders tend to peak in June. Trip revenue for casual riders are second most profitable compared to other bikes (after electric bikes) assuming a $0.39 charge per minute.

Trip revenue of electric bike for members

Solutions to business task

Q1. Who should we target for membership marketing?

Classic bikes

For frequent casual riders of classic bikes, we need to look at how much they will spend if they switch from casual riding plans to membership to determine whether membership subscription yields higher profits.

We assume that casual riders will always go for the cheapest options available to them without membership. Let us examine some scenarios.

For every member who rides no more than 45 minutes per ride, annual revenue from this member is only the annual membership fee of 120 dollars. But for casual riders who rides no more than 45 minutes per ride, annual revenue per rider is at least 123 dollars if the number of rides each year is above 14. The calculation of annual revenues are as follows:

  • Annual revenue (casual rider) = (45 (mins) x 0.16 (/min) + 1 (unlock cost)) x 15 (rides/year) = $123

  • Annual revenue (member) = 10 (/mth) x 12 (mths) = $120

For every member who rides for 3 hours per ride, annual revenue from each member is around 8,000 dollars since rides above 45 minutes are charged at $0.16 per minute. But for casual riders who rides no more than 3 hours per ride, annual revenue per rider is 5,475 dollars as they will choose the day plan of 15 dollars each day as the cheaper option. The calculation of annual revenues are as follows:

  • Annual revenue (casual rider) = 365 (days) x 15 (/day) = $5,475

  • Annual revenue (member) = ((180-45) (mins) x 0.16 (/min) x 365 (days) + 120 (membership fee) = $8,004

For every member and rider who rides more than 3 hours per ride, the cost per ride after 3 hours is the same, so which plan is more profitable depends on the revenue for the first 3 hours. Thus it is similar to the scenario above. The calculation of annual revenues are as follows:

  • Annual revenue (casual rider) = 365 (days) x 15 (/day) = $5,475

  • Annual revenue (member) = ((180-45) (mins) x 0.16 (/min) x 365 (days) + 120 (membership fee) = $8,004

Thus, I propose the following recommendations to maximize revenue:

  • For casual riders who ride no more than 45 minutes per ride, only promote membership to them if they ride for less than 15 rides each year on classic bikes.

  • For casual rider who ride more than 45 minutes per ride, always promote membership to them. Membership will always bring in more revenue regardless of the number of rides each year.

Electric bikes and docked bikes

For frequent casual riders of electric bikes, we need to look at how much they will spend if they switch from casual riding plans to membership to determine whether membership subscription yields higher profits. Let us examine some scenarios.

For every member who rides 1 minute per ride and only once per day, annual revenue from this member is 178 dollars given the $0.16 per min charge. But for casual riders who ride the same frequency, annual revenue per rider is at least 507 dollars. The calculation of annual revenues are as follows:

  • Annual revenue (casual rider) = (0.39 (/min) x 1 (min) + 1 (unlock cost)) x 365 (days) = $507

  • Annual revenue (member) = (0.16 (/min) x 1 (min) x 365 (days)) + 120 (membership fee) = $178

Membership only becomes more profitable under this revenue calculation:

  • Annual revenue (member) = (0.35 (/min) x 1 (min) x 365 (days)) + 380 (membership fee) = $508

Similarly for scooters, revenue from casual riders are higher.

The calculation of annual revenues are as follows:

  • Annual revenue (casual rider) = (0.39 (/min) x 1 (min) + 1 (unlock cost)) x 365 (days) = $507

  • Annual revenue (member) = (0.25 (/min) x 1 (min) x 365 (days)) + 120 (membership fee) = $211

Membership only becomes more profitable under this revenue calculation:

  • Annual revenue (member) = (0.35 (/min) x1 (min) x 365 (days)) + 380 (membership fee) = $508

Thus, I propose the following recommendations to maximise revenue:

  • Raise membership fees to minimum 380 dollars per year or 32 dollars per month and cost per minute to $0.35 for all new members and promote membership to casual riders who ride electric bikes and scooters only once per day and 1 min per ride.

Q2. How should we target casual riders based on their riding patterns?

Since casual riders prefer to use all types of bikes for leisure from the preliminary data we have, we can promote membership subscription by months ($32 per month) during peak periods to maximise revenue for electric and docked bikes.

For classic bikes, the original membership fee of 120 dollars per year can be promoted to casual riders who meet the criteria of riding above 45 minutes per ride.

Q3. What other data do we need to gather or collect?

To better access the profitability of our membership subscription, full day passes and better promote membership based on preferences of casual riders, we need to gather or collect the following information:

  1. Survey on the kind of bikes casual riders prefer to use and the purpose (for work or leisure)
  2. Current total revenue from membership subscriptions
  3. Total revenue from full days passes
  4. Number of casual riders who fit into the profile to promote membership to
  5. Information on why docked bikes have highest ride duration

Appendix

Sources of data

  1. Original trip data by divvybikes: https://divvy-tripdata.s3.amazonaws.com/index.html
  2. Pricing information by divvybikes: https://divvybikes.com/
LS0tDQp0aXRsZTogIkhvdyBDYXN1YWwgUmlkZXJzIENhbiBCZSBDb252ZXJ0ZWQgVG8gTWVtYmVycyINCmF1dGhvcjogIllpbmluZyBTaGkiDQpkYXRlOiAiNyBKYW4gMjAyMyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQojIEludHJvZHVjdGlvbiBhbmQgUmF0aW9uYWxlIG9mIFByb2plY3QNCg0KVGhpcyBwcm9qZWN0IGlzIHNwZWFyaGVhZGVkIGJ5IExpbHkgTW9yZW5vLCBEaXJlY3RvciBvZiBNYXJrZXRpbmcsIHRvIHVuZGVyc3RhbmQgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGN5Y2xpbmcgdXNlcyBvZiBjYXN1YWwgcmlkZXJzIGFuZCBhbm51YWwgbWVtYmVycy4gQnkgdXNpbmcgZGF0YSBhbmFseXNpcyB0b29scyBhbmQgdGVjaG5pcXVlcywgdGhlIHRlYW0gaXMgZ29pbmcgdG8gZGlzY292ZXIgcGF0dGVybnMgYW5kIGJlaGF2aW9yIGFuZCBvdGhlciBmYWN0b3JzIHRoYXQgd2lsbDoNCg0KKiAqTW90aXZhdGUgY2FzdWFsIHVzZXJzIHRvIHNpZ24gdXAgYXMgYW5udWFsIG1lbWJlcnMqLCBhbmQNCiogKkhvdyBkaWdpdGFsIG1lZGlhIGNhbiBiZSB1c2VkIHRvIHRhcmdldCBtYXJrZXRpbmcgdG93YXJkcyBjYXN1YWwgdXNlcnMqDQoNCkZvciB0aGUgc2FrZSBvZiByZWZlcmVuY2UsIHRoZSBmb2xsb3dpbmcgZGVmaW5pdGlvbiBhcHBsaWVzLg0KDQoqICoqQ2FzdWFsIHJpZGVycyoqOiBDdXN0b21lcnMgd2hvIHB1cmNoYXNlIHNpbmdsZSBvciBmdWxsIGRheSBwYXNzZXMNCiogKipBbm51YWwgbWVtYmVycyoqOiBDdXN0b21lcnMgd2hvIHB1cmNoYXNlIGFubnVhbCBtZW1iZXJzaGlwcw0KDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQojIEJ1c2luZXNzIFRhc2sNCg0KVGhlIG1hcmtldGluZyBhbmFseXN0IHRlYW0gaGFzIHRvIGZpbmQgYW5zd2VycyB0byB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczoNCg0KMS4gSG93IGRvIGFubnVhbCBtZW1iZXJzIGFuZCBjYXN1YWwgcmlkZXJzIHVzZSBDeWNsaXN0aWMgYmlrZXMgZGlmZmVyZW50bHk/DQoyLiBXaHkgd291bGQgY2FzdWFsIHJpZGVycyBidXkgQ3ljbGlzdGljIGFubnVhbCBtZW1iZXJzaGlwcz8NCjMuIEhvdyBjYW4gQ3ljbGlzdGljIHVzZSBkaWdpdGFsIG1lZGlhIHRvIGluZmx1ZW5jZSBjYXN1YWwgcmlkZXJzIHRvIGJlY29tZSBtZW1iZXJzPw0KDQpJIGFtIHRhc2tlZCB3aXRoIHVzaW5nIGFsbCBkYXRhIGF2YWlsYWJsZSB0byBhbnN3ZXIgcXVlc3Rpb24gMS4NCg0KIyMgTXkgZGVsaXZlcmFibGVzDQoNCkkgd2lsbCBiZSBwcm9kdWNpbmcgdGhlIGZvbGxvd2luZyBkZWxpdmVyYWJsZXMgZm9yIG15IHBhcnQgaW4gdGhlIHByb2plY3Q6DQoNCiogRXhlY3V0aXZlIHN1bW1hcnkgb2YgYnVzaW5lc3MgdGFzayBhbmQgYW5hbHlzaXMNCiogRG9jdW1lbnRhdGlvbiBvZiBjbGVhbmluZyBhbmQgbWFuaXB1bGF0aW9uIG9mIGRhdGENCiogU3VwcG9ydGluZyB2aXN1YWxpemF0aW9ucyBhbmQga2V5IGZpbmRpbmdzDQoqIE1haW4gYW5hbHlzaXMgYW5kIHRvcCB0aHJlZSByZWNvbW1lbmRhdGlvbnMNCiogQW4gYXBwZW5kaXggb2YgYWxsIGRhdGEgc291cmNlcyB1c2VkDQoNCiMjIEV4cGVjdGF0aW9ucyBvZiBrZXkgc3Rha2Vob2xkZXJzDQoNCkFmdGVyIGNvbXBhbnkgbWVldGluZ3MsIHRoZSBleHBlY3RhdGlvbnMgb2Yga2V5IHN0YWtlaG9sZGVycyBhcmUgYXMgZm9sbG93czoNCg0KQ29tcGFueSBleGVjdXRpdmVzIC0gRGF0YSBuZWVkcyB0byBiZSBmdWxseSBhbmFseXplZCBhbmQgcHJlc2VudGVkIHRvIGNvbnZpbmNlIGNvbXBhbnkgZXhlY3V0aXZlcyB0aGF0IGEgbWFya2V0aW5nIHN0cmF0ZWd5IHRhcmdldGluZyBjYXN1YWwgcmlkZXJzIHdvdWxkIHJlc3VsdCBpbiBncmVhdGVyIHByb2ZpdHMuDQoNCkRpcmVjdG9yIG9mIG1hcmtldGluZyAtIERhdGEgYW5kIGFuYWx5c2lzIHN1cHBvcnRpbmcgb3IgcXVlc3Rpb25pbmcgdGhlIG1hcmtldCBzdHJhdGVneSBvZiB0YXJnZXRpbmcgY2FzdWFsIHJpZGVycyBuZWVkcyB0byBiZSBwcmVzZW50ZWQuDQoNCk1hcmtldGluZyBhbmFseXN0IG1lbWJlcnMgLSBEYXRhIGFuZCBhbmFseXNpcyBvbiBob3cgY2FzdWFsIHJpZGVycyBkaWZmZXIgaW4gYmlrZSB1c2FnZSBmcm9tIGFubnVhbCBtZW1iZXJzIG5lZWRzIHRvIGJlIHByZXNlbnRlZCB0byBvdGhlciBtZW1iZXJzLg0KDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQojIERhdGEgQW5hbHlzaXMgUHJvY2Vzcw0KDQpLZXkgcXVlc3Rpb246ICoqSG93IGRvIGFubnVhbCBtZW1iZXJzIGFuZCBjYXN1YWwgcmlkZXJzIHVzZSBDeWNsaXN0aWMgYmlrZXMgZGlmZmVyZW50bHkqKg0KDQpUbyBhbnN3ZXIgdGhlIGFib3ZlIHF1ZXN0aW9uLCBkYXRhIGZyb20gMTIgbW9udGhzIG9mIHRyaXAgZGF0YSBmb3IgdGhlIHllYXIgMjAyMiBpcyBleHRyYWN0ZWQuIEZvciBhIHJldmlldyBvZiB0aGUgZGF0YSB1c2VkIGluIHRoaXMgYW5hbHlzaXMsIHBsZWFzZSBjbGljayBbdGhpcyBsaW5rXShodHRwczovL2RpdnZ5LXRyaXBkYXRhLnMzLmFtYXpvbmF3cy5jb20vaW5kZXguaHRtbCkuIERhdGEgaXMgcHJvdmlkZWQgYnkgKipNb3RpdmF0ZSBJbnRlcm5hdGlvbmFsIEluYyoqIHVuZGVyIGEgW2xpY2Vuc2VdKGh0dHBzOi8vcmlkZS5kaXZ2eWJpa2VzLmNvbS9kYXRhLWxpY2Vuc2UtYWdyZWVtZW50KSBmcm9tIGRpdnZ5YmlrZXMuIEFzIHdlIGRvIG5vdCBoYXZlIGZpcnN0IGhhbmQgYWNjZXNzIHRvIGRhdGEsIHdlIG5lZWQgdG8gY2hlY2sgZm9yICppbnRlZ3JpdHksIGFjY3VyYWN5LCBjb25zaXN0ZW5jeSBhbmQgY29tcGxldGVuZXNzKiBkdXJpbmcgdGhlIGRhdGEgY2xlYW5pbmcgcHJvY2Vzcy4NCg0KVGhlcmUgaXMgYWxzbyBhIG5lZWQgdG8gY2hlY2sgb24gaG93IG1lbWJlcnMgYW5kIGNhc3VhbCByaWRlcnMgYXJlIGNoYXJnZWQgZm9yIHRoZWlyIHJpZGVzLiAoSXMgaXQgYmFzZWQgb24gdGltZSBzcGVudCBvbiB0aGUgYmlrZSwgZGlzdGFuY2UgdHJhdmVsZWQsIHR5cGUgb2YgYmlrZSB1c2VkIGV0Yz8pIEFjY29yZGluZyB0byBteSBvd24gcmVzZWFyY2gsIG1lbWJlcnMgYW5kIGNhc3VhbCByaWRlcnMgYXJlIGNoYXJnZWQgYmFzZWQgb24gdGhlIGluZm9ybWF0aW9uIGZyb20gW2RpdnZ5YmlrZXNdKGh0dHBzOi8vZGl2dnliaWtlcy5jb20vKS4NCg0KIyMgSW5mb3JtYXRpb24gYWJvdXQgZGF0YSB1c2VkDQoNClRoZSBzZXQgb2YgZGF0YSBmcm9tIE1vdGl2YXRpb25hbCBJbmMuIHByb3ZpZGVzIG1vbnRobHkgaW5mb3JtYXRpb24gYWJvdXQgdXNhZ2Ugb2YgYmlrZXMgd2l0aCBwYXJhbWV0ZXJzOg0KICAgIA0KKiByaWRlX2lkDQoqIHN0YXJ0IGFuZCBlbmQgdGltZQ0KKiBzdGFydCBzdGF0aW9uIGFuZCBlbmQgc3RhdGlvbg0KKiBzdGFydCBhbmQgZW5kIGxhdGl0dWRlIGFuZCBsb25ndGl0dWRlDQoqIG1lbWJlciB0eXBlcyAoKmNhc3VhbCogb3IgKm1lbWJlciopDQoNClRvIGdldCBhbiBpZGVhIG9uIHRoZSBkaWZmZXJlbmNlIGluIGJlaGF2aW9yLCBkYXRhIHdpbGwgYmUgYW5hbHl6ZWQgaW4gdGhlIGZvbGxvd2luZyBhc3BlY3RzIGFtb25nIG1lbWJlcnMgYW5kIGNhc3VhbCByaWRlcnM6DQoNCjEpICoqSG93IGZyZXF1ZW50bHkgZWFjaCB0eXBlIG9mIGJpa2UgaXMgdXNlZCoqDQogICAgYSkgbnVtYmVyIG9mIHJpZGVzIHBlciB0eXBlIG9mIGJpa2UgZ3JvdXBlZCBieSBtZW1iZXIgdHlwZQ0KICAgIGIpIGhvdyBudW1iZXIgb2YgcmlkZXMgcGVyIHR5cGUgb2YgYmlrZSB2YXJ5IGJ5IG1vbnRoIGFuZCB3ZWVrIG9mIGRheXMgZ3JvdXBlZCBieSBtZW1iZXIgdHlwZQ0KMikgKipUaW1lIHNwZW50IG9uIGVhY2ggdHlwZSBvZiBiaWtlKioNCiAgICBhKSB0b3RhbCBhbmQgYXZlcmFnZSBkdXJhdGlvbiBwZXIgdHlwZSBvZiBiaWtlIGdyb3VwZWQgYnkgbWVtYmVyIHR5cGUNCiAgICBiKSBob3cgdG90YWwgYW5kIGF2ZXJhZ2UgZHVyYXRpb24gcGVyIHR5cGUgb2YgYmlrZSB2YXJpZXMgYnkgbW9udGggZ3JvdXBlZCBieSBtZW1iZXIgdHlwZQ0KDQpCYXNlZCBvbiBwcmljaW5nIGluZm9ybWF0aW9uIHByb3ZpZGVkIGJ5IGRpdnZ5YmlrZXMsIHRoZSByZXZlbnVlIGJ5IGN1c3RvbWVyIHR5cGUgYXJlIGNhbGN1bGF0ZWQgYXMgZm9sbG93czoNCg0KIyMjIyBNZW1iZXJzIFByaWNpbmcNCg0KKipDbGFzc2ljIGJpa2UqKg0KDQoqICQxMCBwZXIgbW9udGggZm9yIDQ1IG1pbnV0ZXMvcmlkZSANCiogQW4gZXh0cmEgJDAuMTYvbWluIGJleW9uZCA0NSBtaW51dGVzDQoNCioqRWxlY3RyaWMgYmlrZSoqDQoNCiogJDAuMTYvbWluIHBlciByaWRlDQoNCioqU2Nvb3RlcnMqKg0KDQoqICQwLjI1L21pbiBwZXIgcmlkZQ0KDQojIyMjIENhc3VhbCBSaWRlcnMgUHJpY2luZw0KDQoqKkNsYXNzaWMgYmlrZSBzaW5nbGUgcmlkZXMqKg0KDQoqICQxIHBlciB1bmxvY2sNCiogJDAuMTYvbWluIHBlciByaWRlDQoNCioqQ2xhc3NpYyBiaWtlIGRheSByaWRlcyoqDQoNCg0KKiAkMTUgcGVyIGRheSBmb3IgMyBob3Vycy9yaWRlDQoqICQwLjE2L21pbiBwZXIgcmlkZSBiZXlvbmQgMyBob3Vycw0KDQoNCioqRWxlY3RyaWMgYmlrZS9zY29vdGVycyByaWRlcyoqDQoNCiogJDEgcGVyIHVubG9jaw0KKiAkMC4zOS9taW4gcGVyIHJpZGUNCg0KIyMgTGltaXRhdGlvbnMgb2YgZGF0YQ0KDQpMaW1pdGF0aW9ucyBvZiBkYXRhIGluY2x1ZGVzIG5vdCBiZWluZyBhYmxlIHRvIGxpbmsgdHJpcCBiZWhhdmlvciB0byBhY3R1YWwgdXNlcnMgYXMgdGhleSBhcmUgcGVyc29uYWxseSBpZGVudGlmaWFibGUgaW5mb3JtYXRpb24sIG5vdCBiZWluZyBhYmxlIHRvIGRldGVybWluZSBpZiByaWRlcnMgbGl2ZSBpbiB0aGUgQ3ljbGlzdGljIHNlcnZpY2UgYXJlYSAoYW5kIHRoZXJlZm9yZSBob3cgdGhhdCBpbXBhY3RzIHJpZGVyIGJlaGF2aW9yKSBhbmQgd2hldGhlciBlYWNoIHVzZXIgbWFkZSBtdWx0aXBsZSB0cmlwcyB3aXRoIGRpZmZlcmVudCByaWRlX2lkLiBUaGlzIGltcGFjdHMgY2FsY3VsYXRpbmcgcmV2ZW51ZSBmb3IgbWVtYmVyIGFuZCBmdWxsIGRheSBwYXNzIHJpZGVzIGFzIGVhY2ggbWVtYmVyIGFuZCBmdWxsIGRheSBwYXNzIHJpZGVyIG1heSBiZSB0aWVkIHRvIG11bHRpcGxlIHJpZGVfaWRzLg0KDQojIyBBc3N1bXB0aW9ucyBhYm91dCBkYXRhDQoNClNpbmNlIHdlIGNhbm5vdCBrbm93IHdoYXQga2luZCBvZiBwbGFuIGVhY2ggcmlkZXIgc3Vic2NyaWJlZCB0byBmb3IgZWFjaCByaWRlLCB3ZSBhc3N1bWUgdGhlIGZvbGxvd2luZzoNCg0KMS4gRm9yIGNhc3VhbCByaWRlcnMsIGFueSBjbGFzc2ljIGJpa2UgdHJpcCBkdXJhdGlvbiBhYm92ZSA5MyBtaW51dGVzIGVhY2ggcmlkZSBhcmUgc3Vic2NyaWJlcnMgdG8gZGF5IHJpZGVzIGFzIHRoZSBkYXkgcmlkZSBvZiAkMTUgZG9sbGFycyBwZXIgZGF5IGFyZSBtb3JlIGVjb25vbWljLiBJIGFzc3VtZSBjYXN1YWwgcmlkZXJzIHdpbGwgZ28gZm9yIHRoZSBtb3N0IGVjb25vbWljIG9wdGlvbi4NCg0KMi4gU2luY2Ugd2UgY2Fubm90IGF0dHJpYnV0ZSBtdWx0aXBsZSByaWRlX2lkIHRvIG9uZSByaWRlciBmcm9tIHRoZSB0cmlwIGRhdGEsIG9ubHkgdGhlIHJldmVudWUgZnJvbSB0cmlwIGR1cmF0aW9uIGNoYXJnZWQgYnkgbWludXRlcyBpcyBjYWxjdWxhdGVkLiBJIGFzc3VtZSB0aGVyZSBhcmUgbWVtYmVyIGFuZCBkYXkgcmlkZSBzdWJzY3JpcHRpb24gbGlzdHMgd2hpY2ggd2lsbCBnaXZlIGEgc3RyYWlnaHRmb3J3YXJkIGNhbGN1bGF0aW9uIG9mIHRvdGFsIG1vbnRobHkgcmV2ZW51ZXMgZnJvbSBtZW1iZXJzaGlwIGZlZXMgYW5kIGRheSByaWRlIHN1YnNjcmliZXJzLiANCg0KX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KIyBEYXRhIENsZWFuaW5nIFdvcmtsb2cNCg0KVGhlIG9yaWdpbmFsIGRhdGEgYXJlIGtlcHQgaW50YWN0IGFuZCBzdG9yZWQgaW4gYSBkaWZmZXJlbnQgZm9sZGVyIGZyb20gdGhlIGNsZWFuc2VkIGFuZCBwcm9jZXNzZWQgZGF0YSB0byBhbGxvdyBvdGhlciB0ZWFtcyB0byB3b3JrIHdpdGggdGhlIG9yaWdpbmFsIGRhdGEuIA0KDQpUaGUgZGlyZWN0b3J5IGZvciB0aGUgb3JpZ2luYWwgZGF0YSBpcyAqJXVzZXIlL2Rlc2t0b3AvYmlrZV90cmlwc19kYXRhX3JhdyouDQoNClRoZSBkaXJlY3RvcnkgZm9yIHRoZSBjbGVhbnNlZCBhbmQgcHJvY2Vzc2VkIGRhdGEgaXMgKiV1c2VyJS9kZXNrdG9wL2Jpa2VfdHJpcHNfZGF0YV9wcm9jZXNzZWQqLg0KDQojIyBEYXRhIHNvcnRpbmcgYW5kIGZpbHRlcmluZyBpbiBFeGNlbA0KDQpTdGVwIDEuIFNpbmNlIHRoZSBkaXN0YW5jZSB0cmF2ZWxlZCBhbmQgbG9jYXRpb24gb2YgYmlrZSByaWRlcnMgYXJlIG5vdCBpbXBvcnRhbnQgZm9yIGRldGVybWluaW5nIHRoZSBwcm9maXRhYmlsaXR5IG9mIHJpZGVzLCB0aGUgZm9sbG93aW5nIGNvbHVtbnMgb2YgZGF0YSBhcmUgcmVtb3ZlZCBmcm9tIHRoZSB0YWJsZXM6DQoNCiogKipzdGFydF9zdGF0aW9uX25hbWUqKg0KKiAqKnN0YXJ0X3N0YXRpb25faWQqKg0KKiAqKmVuZF9zdGF0aW9uX25hbWUqKg0KKiAqKmVuZF9zdGF0aW9uX2lkKioNCiogKipzdGFydF9sYXQqKg0KKiAqKnN0YXJ0X2xuZyoqDQoqICoqZW5kX2xhdCoqDQoqICoqZW5kX2xuZyoqDQoNClN0ZXAgMi4gVG8gYmV0dGVyIGFuYWx5c2UgdGhlIGRpZmZlcmVuY2UgaW4gcmlkaW5nIGhhYml0cyBiZXR3ZWVuIG1lbWJlcnMgYW5kIGNhc3VhbCByaWRlcnMsIHRoZSB0YWJsZSBmb3IgZWFjaCBtb250aCBvZiBkYXRhIGlzIHNlcGFyYXRlZCBpbnRvIGRhdGEgZm9yIG1lbWJlcnMgYW5kIGNhc3VhbCByaWRlcnMuIEFueSBibGFuayByb3dzIGFyZSBhbHNvIGRlbGV0ZWQgaW4gRXhjZWwgdXNpbmcgSG9tZSAtPiBGaW5kICYgU2VsZWN0IC0+IEdvIHRvIFNwZWNpYWwsIHNlbGVjdCAiQmxhbmtzIiBhbmQgdGhlbiAiRGVsZXRlIFNoZWV0IFJvd3MiLg0KDQpTdGVwIDMuIEVuc3VyZSBjb2x1bW5zICoqc3RhcnRlZF9hdCoqIGFuZCAqKmVuZGVkX2F0KiogYXJlIGZvcm1hdHRlZCBhcyAqZC9tL3l5eXkgaDptbSouIEVuc3VyZSB0aGUgb3RoZXIgY29sdW1ucyBhcmUgZm9ybWF0dGVkIGFzICp0ZXh0Ki4NCg0KU3RlcCA0LiBTZXQgdXAgYW5vdGhlciBjb2x1bW4gY2FsbGVkIGR1cmF0aW9uIGFuZCBmb3JtYXQgaXQgYXMgKmg6bW0qLiBUaGVuIHVzZSBlbmRlZCBhdCAtIHN0YXJ0ZWQgYXQgdG8gZ2V0IGR1cmF0aW9uIGVsYXBzZWQuIEZpbHRlciBkdXJhdGlvbiBmb3IgYW55IGFibm9ybWFsaXRpZXMgYW5kIGNvcnJlY3QgZGF0YSB0aGF0IHNvcnRzIGVuZGVkIGF0IGFzIHN0YXJ0ZWQgYXMgYW5kIHZpY2UgdmVyc2EuDQoNClN0ZXAgNS4gVG8gcHJldmVudCBhY2NpZGVudGFsIGRlbGV0aW9uIG9mIGRhdGEsIHRoZSBzaGVldCBpcyBwcm90ZWN0ZWQgd2l0aCBSZXZpZXcgLT4gUHJvdGVjdCBTaGVldC4gVGhlIGZvbGxvd2luZyBpdGVtcyBhcmUgY2hlY2tlZDoNCg0KKiBTZWxlY3QgbG9ja2VkIGNlbGxzDQoqIFNlbGVjdCB1bmxvY2tlZCBjZWxscw0KKiBGb3JtYXQgY2VsbHMNCiogRm9ybWF0IGNvbHVtbnMNCiogRm9ybWF0IHJvd3MNCiogU29ydA0KKiBVc2UgUGl2b3RUYWJsZSBhbmQgUGl2b3RDaGFydA0KDQpSZXBlYXQgYWxsIHRoZSBzdGVwcyAxIHRvIDUgYWJvdmUgZm9yIGFsbCBtZW1iZXIgYW5kIGNhc3VhbCBkYXRhLg0KDQojIyBEYXRhIEFuYWx5c2lzIGluIFNRTA0KDQpTdGVwIDEuIFVwbG9hZCBhbGwgdGhlIGRhdGEgaW50byBTUUwuDQoNCiMjIyBDYXN1YWwgcmlkZXJzIGRhdGENCg0KU3RlcCAyLiBUbyBkZXRlcm1pbmUgdGhlIGRheSBvZiB3ZWVrIHNwZW50IG9uIGVhY2ggcmlkZSwgSSBleHRyYWN0ZWQgdGhlIHN0YXJ0IGFuZCBlbmQgZGF0ZXMgb2YgdGhlIHJpZGVzLiBGb3IgdGhlIGNhc3VhbCByaWRlcnMsIEkgdXNlZCB0aGUgZm9sbG93aW5nIFNRTCBxdWVyeSBvbiBlYWNoIHRhYmxlOg0KDQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NCg0KU0VMRUNUICANCg0KcmlkZV9pZCwNCnJpZGVhYmxlX3R5cGUgQVMgYmlrZV90eXBlLA0KRVhUUkFDVChEQVRFIEZST00gc3RhcnRlZF9hdCkgQVMgc3RhcnRfZGF0ZSwNCkZPUk1BVF9EQVRFKCIlQSIsIEVYVFJBQ1QoREFURSBGUk9NIHN0YXJ0ZWRfYXQpKSBBUyBzdGFydF9kYXksDQpFWFRSQUNUKERBVEUgRlJPTSBlbmRlZF9hdCkgQVMgZW5kX2RhdGUsDQpGT1JNQVRfREFURSgiJUEiLCBFWFRSQUNUKERBVEUgRlJPTSBlbmRlZF9hdCkpIEFTIGVuZF9kYXksDQp0eXBlX29mX3JpZGVyDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2Jpa2V0cmlwZGF0YV9jYXN1YWwuMjAyMi14eC1iaWtldHJpcGRhdGEtY2ANCg0KV0hFUkUgcmlkZWFibGVfdHlwZSA9ICJjbGFzc2ljX2Jpa2UiDQoNCk9SREVSIEJZIHN0YXJ0ZWRfYXQNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9jY2xhc3NpY2Jpa2VkYXRhX2RheW9md2VlayoqIi4gSSByZXBlYXQgdGhpcyBzdGVwIGZvciBlbGVjdHJpY19iaWtlICgqKjIwMjJfeHhfY2VsZWN0cmljYmlrZWRhdGFfZGF5b2Z3ZWVrKiopIGFuZCBkb2NrZWRfYmlrZSAoKioyMDIyX3h4X2Nkb2NrZWRiaWtlZGF0YV9kYXlvZndlZWsqKikuDQoNClRvIGRldGVybWluZSBudW1iZXIgb2YgY2xhc3NpYyBiaWtlIHJpZGVzIGZyb20gY2FzdWFsIHJpZGVycyBmb3IgZXZlcnkgZGF5IG9mIGVhY2ggbW9udGgsIEkgdXNlZCB0aGUgZm9sbG93aW5nIFNRTCBxdWVyeSBvbiBlYWNoIHRhYmxlOg0KDQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NClNFTEVDVCANCg0Kc3RhcnRfZGF5LA0KQ09VTlQocmlkZV9pZCkgQVMgbnVtYmVyX29mX3JpZGVzLA0KDQogRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfY2xhc3NpY2Jpa2V0cmlwZGF0YV9jYXN1YWwuMjAyMl94eF9jY2xhc3NpY2Jpa2VkYXRhX2RheW9md2Vla2AgDQoNCiBHUk9VUCBCWSBzdGFydF9kYXkNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGxvY2FsIENTViBmaWxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfY2NsYXNzaWNiaWtlZGF0YV9ieWRheXMqKiIuSSByZXBlYXQgdGhpcyBzdGVwIGZvciBlbGVjdHJpY19iaWtlICgqKjIwMjJfeHhfY2VsZWN0cmljYmlrZWRhdGFfYnlkYXlzKiopIGFuZCBkb2NrZWRfYmlrZSAoKioyMDIyX3h4X2Nkb2NrZWRiaWtlZGF0YV9ieWRheXMqKikuDQoNClN0ZXAgMy4gVG8gZGV0ZXJtaW5lIHRoZSB0aW1lIHNwZW50IG9uIGVhY2ggcmlkZSwgY29sdW1ucyBhcmUgc2VwYXJhdGVkIGludG8gZGF0ZSBhbmQgdGltZS4gRm9yIHRoZSBjYXN1YWwgcmlkZXJzLCBJIHVzZWQgdGhlIGZvbGxvd2luZyBTUUwgcXVlcnkgb24gZWFjaCB0YWJsZToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQogIHJpZGVhYmxlX3R5cGUgQVMgYmlrZV90eXBlLA0KICBEQVRFVElNRV9ESUZGKGVuZGVkX2F0LCBzdGFydGVkX2F0LCBNSU5VVEUpIEFTIGR1cmF0aW9uX29mX3RyaXBfbWlucywNCiAgdHlwZV9vZl9yaWRlcg0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9iaWtldHJpcGRhdGFfY2FzdWFsLjIwMjIteHgtYmlrZXRyaXBkYXRhLWNgIA0KYGBgDQoNClRoZW4gSSBjaG9vc2UgIlNhdmUgUmVzdWx0cyIgYXMgYW5vdGhlciBCaWdRdWVyeSB0YWJsZSBhbmQgbmFtZSBpdCAiKioyMDIyX3h4X2Jpa2V0cmlwZWRhdGF3aXRoZHVyYXRpb25fYyoqIg0KDQpTdGVwIDQuIFRvIGRldGVybWluZSB0aGUgZHVyYXRpb24gb2YgdGltZSBzcGVudCBvbiBjbGFzc2ljIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMsIEkgcnVuIHRoZSBmb2xsb3dpbmcgcXVlcnk6DQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KKg0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9iaWtldHJpcGRhdGFfY2FzdWFsLjIwMjJfeHhfYmlrZXRyaXBlZGF0YXdpdGhkdXJhdGlvbl9jYCANCg0KV0hFUkUgYmlrZV90eXBlID0gImNsYXNzaWNfYmlrZSINCg0KT1JERVIgQlkgZHVyYXRpb25fb2ZfdHJpcF9taW5zDQpgYGANCg0KVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfY2NsYXNzaWNiaWtlZGF0YV9kdXJhdGlvbioqIi4NCg0KU3RlcCA1LiBUbyBkZXRlcm1pbmUgdGhlIGR1cmF0aW9uIG9mIHRpbWUgc3BlbnQgb24gZWxlY3RyaWMgYmlrZXMgYnkgY2FzdWFsIHJpZGVycywgSSBydW4gdGhlIGZvbGxvd2luZyBxdWVyeToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQoqDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2Jpa2V0cmlwZGF0YV9jYXN1YWwuMjAyMl94eF9iaWtldHJpcGVkYXRhd2l0aGR1cmF0aW9uX2NgIA0KDQpXSEVSRSBiaWtlX3R5cGUgPSAiZWxlY3RyaWNfYmlrZSINCg0KT1JERVIgQlkgZHVyYXRpb25fb2ZfdHJpcF9taW5zDQoNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9jZWxlY3RyaWNiaWtlZGF0YV9kdXJhdGlvbioqIi4NCg0KU3RlcCA2LiBUbyBkZXRlcm1pbmUgdGhlIGR1cmF0aW9uIG9mIHRpbWUgc3BlbnQgb24gZG9ja2VkIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMsIEkgcnVuIHRoZSBmb2xsb3dpbmcgcXVlcnk6DQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KKg0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9iaWtldHJpcGRhdGFfY2FzdWFsLjIwMjJfeHhfYmlrZXRyaXBlZGF0YXdpdGhkdXJhdGlvbl9jYCANCg0KV0hFUkUgYmlrZV90eXBlID0gImRvY2tlZF9iaWtlIg0KDQpPUkRFUiBCWSBkdXJhdGlvbl9vZl90cmlwX21pbnMNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9jZG9ja2VkYmlrZWRhdGFfZHVyYXRpb24qKiIuDQoNClRvIGRldGVybWluZSBtaW5pbXVtLCBtYXhpbXVtLCBhdmVyYWdlIGFuZCB0b3RhbCBkdXJhdGlvbiBvZiBjbGFzc2ljIGJpa2UgcmlkZXMgZnJvbSBjYXN1YWwgcmlkZXJzIGZvciBlYWNoIG1vbnRoLCBJIHVzZWQgdGhlIGZvbGxvd2luZyBTUUwgcXVlcnkgb24gZWFjaCB0YWJsZToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQpiaWtlX3R5cGUsDQpNSU4oZHVyYXRpb25fb2ZfdHJpcF9taW5zKSBBUyBtaW5fZHVyYXRpb25fb2ZfdHJpcHNfbWlucywNCk1BWChkdXJhdGlvbl9vZl90cmlwX21pbnMpIEFTIG1heF9kdXJhdGlvbl9vZl90cmlwc19taW5zLA0KQVZHKGR1cmF0aW9uX29mX3RyaXBfbWlucykgQVMgYXZlcmFnZV9kdXJhdGlvbl9vZl90cmlwc19taW5zLA0KU1VNKGR1cmF0aW9uX29mX3RyaXBfbWlucykgQVMgdG90YWxfZHVyYXRpb25fb2ZfdHJpcHNfbWlucw0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9jbGFzc2ljYmlrZXRyaXBkYXRhX2Nhc3VhbC4yMDIyX3h4X2NjbGFzc2ljYmlrZWRhdGFfZHVyYXRpb25gIA0KDQpHUk9VUCBCWSBiaWtlX3R5cGUNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGxvY2FsIENTViBmaWxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfY2NsYXNzaWNiaWtlZGF0YV9ieW1pbnMqKiIuSSByZXBlYXQgdGhpcyBzdGVwIGZvciBlbGVjdHJpY19iaWtlICgqKjIwMjJfeHhfY2VsZWN0cmljYmlrZWRhdGFfYnltaW5zKiopIGFuZCBkb2NrZWRfYmlrZSAoKioyMDIyX3h4X2Nkb2NrZWRiaWtlZGF0YV9ieW1pbnMqKikuDQoNClN0ZXAgNzogVGhlbiBiYXNlZCBvbiBvdXIgYXNzdW1wdGlvbiBvZiBjbGFzc2ljIGJpa2UgZGF5IHJpZGVzLCBJIGNyZWF0ZWQgdGhlIGZvbGxvd2luZyBxdWVyeSB0byBmaWx0ZXIgb3V0IGEgdGFibGUgZm9yIGRheSByaWRlcyBvbiBjbGFzc2ljIGJpa2VzIGJhc2VkIG9uIGR1cmF0aW9uIG9mIHRyaXBzIGFib3ZlIDkzIG1pbnV0ZXM6DQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KYmlrZV90eXBlLA0KZHVyYXRpb25fb2ZfdHJpcF9taW5zLA0KdHlwZV9vZl9yaWRlciANCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfYmlrZXRyaXBkYXRhX2Nhc3VhbC4yMDIyX3h4X2Jpa2V0cmlwZWRhdGF3aXRoZHVyYXRpb25fY2AgDQoNCldIRVJFIGR1cmF0aW9uX29mX3RyaXBfbWlucyA+IDkzDQphbmQgYmlrZV90eXBlPSAiY2xhc3NpY19iaWtlIg0KDQpPUkRFUiBCWSBkdXJhdGlvbl9vZl90cmlwX21pbnMNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9iaWtldHJpcGRhdGFkYXlyaWRlc19jKioiDQoNClN0ZXAgOC4gTmV4dCBJIGNyZWF0ZSBhbm90aGVyIHRhYmxlIGZvciBjbGFzc2ljIGJpa2Ugc2luZ2xlIHJpZGVzIGZvciBhbGwgZHVyYXRpb24gb2YgdHJpcHMgZXF1YWwgb3IgbGVzcyB0aGFuIDkzIG1pbnV0ZXMuDQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KYmlrZV90eXBlLA0KZHVyYXRpb25fb2ZfdHJpcF9taW5zLA0KdHlwZV9vZl9yaWRlciANCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfYmlrZXRyaXBkYXRhX2Nhc3VhbC4yMDIyX3h4X2Jpa2V0cmlwZWRhdGF3aXRoZHVyYXRpb25fY2AgDQoNCldIRVJFIGR1cmF0aW9uX29mX3RyaXBfbWlucyA8PSA5MyANCmFuZCBiaWtlX3R5cGU9ImNsYXNzaWNfYmlrZSINCg0KT1JERVIgQlkgZHVyYXRpb25fb2ZfdHJpcF9taW5zDQoNCg0KYGBgDQoNClRoZW4gSSBjaG9vc2UgIlNhdmUgUmVzdWx0cyIgYXMgYW5vdGhlciBCaWdRdWVyeSB0YWJsZSBhbmQgbmFtZSBpdCAiKioyMDIyX3h4X2Jpa2V0cmlwZGF0YXNpbmdsZXJpZGVzX2MqKiINCg0KU3RlcCA5LiBGaW5hbGx5IEkgY3JlYXRlIGEgdGhpcmQgdGFibGUgZm9yIGFsbCByaWRlIGR1cmF0aW9ucyBmb3Igbm9uIGNsYXNzaWMgYmlrZXMuDQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KYmlrZV90eXBlLA0KZHVyYXRpb25fb2ZfdHJpcF9taW5zLA0KdHlwZV9vZl9yaWRlciANCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfYmlrZXRyaXBkYXRhX2Nhc3VhbC4yMDIyX3h4X2Jpa2V0cmlwZWRhdGF3aXRoZHVyYXRpb25fY2AgDQoNCldIRVJFIGJpa2VfdHlwZSE9ImNsYXNzaWNfYmlrZSINCg0KT1JERVIgQlkgZHVyYXRpb25fb2ZfdHJpcF9taW5zDQpgYGANCg0KVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfYmlrZXRyaXBkYXRhX25vbmNsYXNzaWNiaWtlc19jKioiDQoNClN0ZXAgMTAuIE5vdyB0byBzb3J0IG91dCBhIHRhYmxlIG9mIGNsYXNzaWMgYmlrZSBkYXkgcmlkZXMgd2hvIHBheSBubyBtb3JlIHRoYW4gJDE1LCBJIHVzZWQgdGhlIGZvbGxvd2luZyBxdWVyeToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQpiaWtlX3R5cGUsDQpkdXJhdGlvbl9vZl90cmlwX21pbnMsDQp0eXBlX29mX3JpZGVyIA0KDQogRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfY2xhc3NpY2Jpa2V0cmlwZGF0YV9jYXN1YWwuMjAyMl94eF9iaWtldHJpcGRhdGFkYXlyaWRlc19jYCANCg0KV0hFUkUgZHVyYXRpb25fb2ZfdHJpcF9taW5zIDw9IDE4MCANCg0KT1JERVIgQlkgZHVyYXRpb25fb2ZfdHJpcF9taW5zDQpgYGANCg0KVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfZGF5cmlkZXNub3Rtb3JldGhhbjNob3Vyc19jKioiLg0KDQpTdGVwIDExLiBUbyBmdXJ0aGVyIG9yZ2FuaXNlIHRoZSBjbGFzc2ljIGJpa2UgZGF5IHJpZGVzLCBhIHRhYmxlIGlzIGNyZWF0ZWQgdG8gZmlsdGVyIG91dCB0aGUgcmVzdWx0cyBmb3IgZGF5IHJpZGVzIHdpdGggdHJpcCBkdXJhdGlvbiBhYm92ZSAxODAgbWludXRlcyAoMyBob3VycykgYnV0IG5vdCBtb3JlIHRoYW4gMTQ0MCBtaW51dGVzIChhIGRheSkuDQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KYmlrZV90eXBlLA0KZHVyYXRpb25fb2ZfdHJpcF9taW5zLA0KZHVyYXRpb25fb2ZfdHJpcF9taW5zIC0gMTgwIEFTIHRyaXBfZHVyYXRpb25fY2hhcmdlZF9ieV9taW4sDQp0eXBlX29mX3JpZGVyIA0KDQogRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfY2xhc3NpY2Jpa2V0cmlwZGF0YV9jYXN1YWwuMjAyMl94eF9iaWtldHJpcGRhdGFkYXlyaWRlc19jYCANCg0KV0hFUkUgZHVyYXRpb25fb2ZfdHJpcF9taW5zID4gMTgwIGFuZCBkdXJhdGlvbl9vZl90cmlwX21pbnMgPD0gMTQ0MA0KDQpPUkRFUiBCWSBkdXJhdGlvbl9vZl90cmlwX21pbnMNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9kYXlyaWRlc3dpdGhpbm9uZWRheV9jKioiDQoNClN0ZXAgMTIuIEZpbmFsbHksIGEgdGFibGUgZm9yIGNsYXNzaWMgYmlrZSBkYXkgcmlkZXMgdGhhdCBleGNlZWQgMSBkYXkgaXMgY3JlYXRlZCB3aXRoIHRoZSBmb2xsb3dpbmcgcXVlcnk6DQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KYmlrZV90eXBlLA0KZHVyYXRpb25fb2ZfdHJpcF9taW5zLA0KMTQ0MCAtIDE4MCBBUyBkYXkxX3RyaXBfb2ZfZHVyYXRpb25fY2hhcmdlZF9ieV9taW4sDQpDQVNFDQogIFdIRU4gZHVyYXRpb25fb2ZfdHJpcF9taW5zID4gMTYyMCANCiAgVEhFTiAiZHVyYXRpb25fb2ZfdHJpcHNfbWlucyAtIDE2MjAiDQogIEVMU0UgTlVMTCANCiAgRU5EIEFTIGRheTJfdHJpcF9vZl9kdXJhdGlvbl9jaGFyZ2VkX2J5X21pbiwNCnR5cGVfb2ZfcmlkZXIsDQoNCiBGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9jbGFzc2ljYmlrZXRyaXBkYXRhX2Nhc3VhbC4yMDIyX3h4X2Jpa2V0cmlwZGF0YWRheXJpZGVzX2NgIA0KDQpXSEVSRSBkdXJhdGlvbl9vZl90cmlwX21pbnMgPiAxNDQwDQoNCk9SREVSIEJZIGR1cmF0aW9uX29mX3RyaXBfbWlucw0KYGBgDQoNClRoaXMgY3JlYXRlcyB0d28gZXh0cmEgY29sdW1ucyB3aGljaCBjYWxjdWxhdGVzIHRoZSB0cmlwIGR1cmF0aW9uIGNoYXJnZWQgYnkgbWludXRlcyBmb3IgZGF5IDEgYXMgd2VsbCBhcyBkYXkgMiBpZiB0aGUgdHJpcCBkdXJhdGlvbiBmb3IgZGF5IDIgZXhjZWVkcyAzIGhvdXJzLiBUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9kYXlyaWRlc2Fib3Zlb25lZGF5X2MqKiIuDQoNClRoZSBhYm92ZSBzdGVwcyAxIHRvIDEyIGFyZSByZXBlYXRlZCBmb3IgYWxsIDEyIG1vbnRocyBvZiBjYXN1YWwgcmlkZXJzIGRhdGEuDQoNCiMjIyBNZW1iZXIgcmlkZXJzIGRhdGENCg0KU3RlcCAyLiBUbyBkZXRlcm1pbmUgdGhlIGRheSBvZiB3ZWVrIHNwZW50IG9uIGVhY2ggcmlkZSwgSSBleHRyYWN0ZWQgdGhlIHN0YXJ0IGFuZCBlbmQgZGF0ZXMgb2YgdGhlIHJpZGVzLiBGb3IgdGhlIG1lbWJlcnMsIEkgdXNlZCB0aGUgZm9sbG93aW5nIFNRTCBxdWVyeSBvbiBlYWNoIHRhYmxlOg0KDQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NClNFTEVDVCAgDQoNCnJpZGVfaWQsDQpyaWRlYWJsZV90eXBlIEFTIGJpa2VfdHlwZSwNCkVYVFJBQ1QoREFURSBGUk9NIHN0YXJ0ZWRfYXQpIEFTIHN0YXJ0X2RhdGUsDQpGT1JNQVRfREFURSgiJUEiLCBFWFRSQUNUKERBVEUgRlJPTSBzdGFydGVkX2F0KSkgQVMgc3RhcnRfZGF5LA0KRVhUUkFDVChEQVRFIEZST00gZW5kZWRfYXQpIEFTIGVuZF9kYXRlLA0KRk9STUFUX0RBVEUoIiVBIiwgRVhUUkFDVChEQVRFIEZST00gZW5kZWRfYXQpKSBBUyBlbmRfZGF5LA0KdHlwZV9vZl9yaWRlcg0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9iaWtldHJpcGRhdGFfbWVtYmVyLjIwMjIteHgtYmlrZXRyaXBkYXRhLW1gDQoNCldIRVJFIHJpZGVhYmxlX3R5cGUgPSAiY2xhc3NpY19iaWtlIg0KDQpPUkRFUiBCWSBzdGFydGVkX2F0DQpgYGANCg0KVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfbWNsYXNzaWNiaWtlZGF0YV9kYXlvZndlZWsqKiIuIEkgcmVwZWF0IHRoaXMgc3RlcCBmb3IgcmlkZWFibGVfdHlwZSA9ICJlbGVjdHJpY19iaWtlIiAoKioyMDIyX3h4X21lbGVjdHJpY2Jpa2VkYXRhX2RheW9md2VlayoqKS4NCg0KVG8gZGV0ZXJtaW5lIG51bWJlciBvZiBjbGFzc2ljIGJpa2UgcmlkZXMgZnJvbSBtZW1iZXJzIGZvciBldmVyeSBkYXkgb2YgZWFjaCBtb250aCwgSSB1c2VkIHRoZSBmb2xsb3dpbmcgU1FMIHF1ZXJ5IG9uIGVhY2ggdGFibGU6DQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NClNFTEVDVCANCg0Kc3RhcnRfZGF5LA0KQ09VTlQocmlkZV9pZCkgQVMgbnVtYmVyX29mX3JpZGVzLA0KDQogRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfY2xhc3NpY2Jpa2V0cmlwZGF0YV9tZW1iZXIuMjAyMl94eF9tY2xhc3NpY2Jpa2VkYXRhX2RheW9md2Vla2AgDQoNCiBHUk9VUCBCWSBzdGFydF9kYXkNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGxvY2FsIENTViBmaWxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfbWNsYXNzaWNiaWtlZGF0YV9ieWRheXMqKiIuSSByZXBlYXQgdGhpcyBzdGVwIGZvciBlbGVjdHJpY19iaWtlICgqKjIwMjJfeHhfbWVsZWN0cmljYmlrZWRhdGFfYnlkYXlzKiopLg0KDQpTdGVwIDMuIFRvIGRldGVybWluZSB0aGUgdGltZSBzcGVudCBvbiBlYWNoIHJpZGUsIGNvbHVtbnMgYXJlIHNlcGFyYXRlZCBpbnRvIGRhdGUgYW5kIHRpbWUuIEZvciB0aGUgbWVtYmVyIHJpZGVycywgSSB1c2VkIHRoZSBmb2xsb3dpbmcgU1FMIHF1ZXJ5IG9uIGVhY2ggdGFibGU6DQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KICByaWRlYWJsZV90eXBlIEFTIGJpa2VfdHlwZSwNCiAgREFURVRJTUVfRElGRihlbmRlZF9hdCwgc3RhcnRlZF9hdCwgTUlOVVRFKSBBUyBkdXJhdGlvbl9vZl90cmlwX21pbnMsDQogIHR5cGVfb2ZfcmlkZXINCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfYmlrZXRyaXBkYXRhX21lbWJlci4yMDIyLXh4LWJpa2V0cmlwZGF0YS1tYCANCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9iaWtldHJpcGVkYXRhd2l0aGR1cmF0aW9uX20qKiIuDQoNClN0ZXAgNC4gVG8gZGV0ZXJtaW5lIHRoZSBkdXJhdGlvbiBvZiB0aW1lIHNwZW50IG9uIGNsYXNzaWMgYmlrZXMgYnkgbWVtYmVycywgSSBydW4gdGhlIGZvbGxvd2luZyBxdWVyeToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQoqDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2Jpa2V0cmlwZGF0YV9tZW1iZXIuMjAyMl94eF9iaWtldHJpcGVkYXRhd2l0aGR1cmF0aW9uX21gIA0KDQpXSEVSRSBiaWtlX3R5cGUgPSAiY2xhc3NpY19iaWtlIg0KDQpPUkRFUiBCWSBkdXJhdGlvbl9vZl90cmlwX21pbnMNCmBgYA0KDQpUaGVuIEkgY2hvb3NlIOKAnFNhdmUgUmVzdWx0c+KAnSBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0IOKAnCoqMjAyMl94eF9tY2xhc3NpY2Jpa2VkYXRhX2R1cmF0aW9uKirigJ0uDQoNClN0ZXAgNS4gVG8gZGV0ZXJtaW5lIHRoZSBkdXJhdGlvbiBvZiB0aW1lIHNwZW50IG9uIGVsZWN0cmljIGJpa2VzIGJ5IG1lbWJlcnMsIEkgcnVuIHRoZSBmb2xsb3dpbmcgcXVlcnk6DQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KKg0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9iaWtldHJpcGRhdGFfbWVtYmVyLjIwMjJfeHhfYmlrZXRyaXBlZGF0YXdpdGhkdXJhdGlvbl9tYCANCg0KV0hFUkUgYmlrZV90eXBlID0gImVsZWN0cmljX2Jpa2UiDQoNCk9SREVSIEJZIGR1cmF0aW9uX29mX3RyaXBfbWlucw0KYGBgDQoNClRoZW4gSSBjaG9vc2Ug4oCcU2F2ZSBSZXN1bHRz4oCdIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQg4oCcKioyMDIyX3h4X21lbGVjdHJpY2Jpa2VkYXRhX2R1cmF0aW9uKirigJ0uDQoNClRvIGRldGVybWluZSBtaW5pbXVtLCBtYXhpbXVtLCBhdmVyYWdlIGFuZCB0b3RhbCBkdXJhdGlvbiBvZiBjbGFzc2ljIGJpa2UgcmlkZXMgZnJvbSBtZW1iZXJzIGZvciBlYWNoIG1vbnRoLCBJIHVzZWQgdGhlIGZvbGxvd2luZyBTUUwgcXVlcnkgb24gZWFjaCB0YWJsZToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQpiaWtlX3R5cGUsDQpNSU4oZHVyYXRpb25fb2ZfdHJpcF9taW5zKSBBUyBtaW5fZHVyYXRpb25fb2ZfdHJpcHNfbWlucywNCk1BWChkdXJhdGlvbl9vZl90cmlwX21pbnMpIEFTIG1heF9kdXJhdGlvbl9vZl90cmlwc19taW5zLA0KQVZHKGR1cmF0aW9uX29mX3RyaXBfbWlucykgQVMgYXZlcmFnZV9kdXJhdGlvbl9vZl90cmlwc19taW5zLA0KU1VNKGR1cmF0aW9uX29mX3RyaXBfbWlucykgQVMgdG90YWxfZHVyYXRpb25fb2RfdHJpcHNfbWlucw0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9jbGFzc2ljYmlrZXRyaXBkYXRhX21lbWJlci4yMDIyX3h4X21jbGFzc2ljYmlrZWRhdGFfZHVyYXRpb25gIA0KDQpHUk9VUCBCWSBiaWtlX3R5cGUNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGxvY2FsIENTViBmaWxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfbWNsYXNzaWNiaWtlZGF0YV9ieW1pbnMqKiIuSSByZXBlYXQgdGhpcyBzdGVwIGZvciBlbGVjdHJpY19iaWtlICgqKjIwMjJfeHhfbWVsZWN0cmljYmlrZWRhdGFfYnltaW5zKiopLg0KDQpTdGVwIDYuIE5leHQsIEkgZmlsdGVyIG91dCBtZW1iZXJzIHdobyB0cmF2ZWwgZm9yIGxlc3MgdGhhbiA0NSBtaW51dGVzIGVhY2ggcmlkZSB1c2luZyBjbGFzc2ljIGJpa2VzLg0KDQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NClNFTEVDVCAgDQoNCmJpa2VfdHlwZSwNCmR1cmF0aW9uX29mX3RyaXBfbWlucywNCnR5cGVfb2ZfcmlkZXIgDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2Jpa2V0cmlwZGF0YV9tZW1iZXIuMjAyMl94eF9iaWtldHJpcGVkYXRhd2l0aGR1cmF0aW9uX21gIA0KDQpXSEVSRSBkdXJhdGlvbl9vZl90cmlwX21pbnMgPD0gNDUNCmFuZCBiaWtlX3R5cGU9ICJjbGFzc2ljX2Jpa2UiDQoNCk9SREVSIEJZIGR1cmF0aW9uX29mX3RyaXBfbWlucw0KYGBgDQoNClRoZW4gSSBjaG9vc2UgIlNhdmUgUmVzdWx0cyIgYXMgYW5vdGhlciBCaWdRdWVyeSB0YWJsZSBhbmQgbmFtZSBpdCAiKioyMDIyX3h4X2NsYXNzaWNiaWtlcmlkZXNub3RhYm92ZTQ1bWluc19tKioiLg0KDQpTdGVwIDcuIE5leHQsIEkgZmlsdGVyIG91dCBtZW1iZXJzIHdobyB0cmF2ZWwgZm9yIG1vcmUgdGhhbiA0NSBtaW51dGVzIGVhY2ggcmlkZSB1c2luZyBjbGFzc2ljIGJpa2VzLiBJIGFsc28gY2FsY3VsYXRlIGEgbmV3IGNvbHVtbiBvZiB0cmlwIGR1cmF0aW9uIGNoYXJnZWQgYnkgbWludXRlcy4NCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQpiaWtlX3R5cGUsDQpkdXJhdGlvbl9vZl90cmlwX21pbnMsDQpkdXJhdGlvbl9vZl90cmlwX21pbnMgLSA0NSBBUyB0cmlwX2R1cmF0aW9uX2NoYXJnZWRfYnlfbWluLA0KdHlwZV9vZl9yaWRlciANCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfYmlrZXRyaXBkYXRhX21lbWJlci4yMDIyX3h4X2Jpa2V0cmlwZWRhdGF3aXRoZHVyYXRpb25fbWAgDQoNCldIRVJFIGR1cmF0aW9uX29mX3RyaXBfbWlucyA+IDQ1DQphbmQgYmlrZV90eXBlPSAiY2xhc3NpY19iaWtlIg0KDQpPUkRFUiBCWSBkdXJhdGlvbl9vZl90cmlwX21pbnMNCmBgYA0KDQpUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9jbGFzc2ljYmlrZXJpZGVzYWJvdmU0NW1pbnNfbSoqIi4NCg0KU3RlcCA4LiBOZXh0LCBJIGZpbHRlciBvdXQgbWVtYmVycyB3aG8gdHJhdmVsIHVzaW5nIGVsZWN0cmljIGJpa2VzLg0KDQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NClNFTEVDVCAgDQoNCmJpa2VfdHlwZSwNCmR1cmF0aW9uX29mX3RyaXBfbWlucywNCnR5cGVfb2ZfcmlkZXIgDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2Jpa2V0cmlwZGF0YV9tZW1iZXIuMjAyMl94eF9iaWtldHJpcGVkYXRhd2l0aGR1cmF0aW9uX21gIA0KDQpXSEVSRSBiaWtlX3R5cGUgPSAiZWxlY3RyaWNfYmlrZSINCg0KT1JERVIgQlkgZHVyYXRpb25fb2ZfdHJpcF9taW5zDQpgYGANCg0KVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfZWxlY3RyaWNiaWtlcmlkZXNfbSoqIi4NCg0KU3RlcCA5LiBGaW5hbGx5IGFzIGEgc2FmZXR5IGNoZWNrLCBJIHF1ZXJ5IGZvciBhbGwgcmVzdWx0cyB0aGF0IGFyZSBuZWl0aGVyIGNsYXNzaWMgYmlrZSBvciBlbGVjdHJpYyBiaWtlLg0KDQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NClNFTEVDVCAgDQoNCmJpa2VfdHlwZSwNCmR1cmF0aW9uX29mX3RyaXBfbWlucywNCnR5cGVfb2ZfcmlkZXIgDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2Jpa2V0cmlwZGF0YV9tZW1iZXIuMjAyMl94eF9iaWtldHJpcGVkYXRhd2l0aGR1cmF0aW9uX21gIA0KDQpXSEVSRSBiaWtlX3R5cGUhPSJlbGVjdHJpY19iaWtlIiBBTkQgYmlrZV90eXBlIT0iY2xhc3NpY19iaWtlIg0KDQpPUkRFUiBCWSBkdXJhdGlvbl9vZl90cmlwX21pbnMNCmBgYA0KDQpJZiB0aGVyZSBpcyBhIHRhYmxlIGZvciB0aGlzIHF1ZXJ5LCBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfb3RoZXJiaWtlcmlkZXNfbSoqIi4NCg0KVGhlIGFib3ZlIHN0ZXBzIDEgdG8gOSBhcmUgcmVwZWF0ZWQgZm9yIGFsbCAxMiBtb250aHMgb2YgbWVtYmVyIHJpZGVycyBkYXRhLg0KDQojIyBTdW1tYXJpemVkIERhdGEgRm9yIFJldmVudWUgQ2FsY3VsYXRpb24gKFNRTCkNCg0KIyMjIENhc3VhbCByaWRlcnMgZGF0YQ0KU3RlcCAxLiBGb3IgZWFzZSBvZiBjYWxjdWxhdGluZyByZXZlbnVlcywgSSBxdWVyeSB0aGUgdGFibGUgYWJvdXQgY2xhc3NpYyBiaWtlIHNpbmdsZSByaWRlcyBmb3IgY2FzdWFsIHJpZGVycyB1c2luZyB0aGUgZm9sbG93aW5nIFNRTCBxdWVyeToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgDQoNCmJpa2VfdHlwZSwNCkNPVU5UKGJpa2VfdHlwZSkgQVMgbm9fb2ZfcmlkZXMsDQpTVU0oZHVyYXRpb25fb2ZfdHJpcF9taW5zKSBBUyB0b3RhbF9kdXJhdGlvbl9taW5zDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2NsYXNzaWNiaWtldHJpcGRhdGFfY2FzdWFsLjIwMjJfeHhfYmlrZXRyaXBkYXRhc2luZ2xlcmlkZXNfY2ANCg0KR1JPVVAgQlkgYmlrZV90eXBlDQpgYGANCg0KVGhpcyBjb3VudHMgdGhlIHRvdGFsIG51bWJlciBvZiByaWRlcyBvbiBjbGFzc2ljIGJpa2VzIGZvciBzaW5nbGUgcmlkZSBzdWJzY3JpYmVycyBhbmQgYWxzbyB0aGUgdG90YWwgZHVyYXRpb24gb2YgYWxsIHNpbmdsZSByaWRlcyBvbiBjbGFzc2ljIHJpZGVzLiBUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9jbGFzc2ljYmlrZXNpbmdsZXJpZGVzX2MqKiIuDQoNClN0ZXAgMi4gVGhlbiBJIGNyZWF0ZSBhIHRhYmxlIHRoYXQgc3VtbWFyaXNlcyBudW1iZXIgb2Ygb25lIGRheSByaWRlcyBub3QgYWJvdmUgMyBob3Vycy4NCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgIA0KDQpiaWtlX3R5cGUsDQpDT1VOVChiaWtlX3R5cGUpIEFTIG51bWJlcl9vZl9yaWRlcw0KDQpGUk9NIGBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9jbGFzc2ljYmlrZXRyaXBkYXRhX2Nhc3VhbC4yMDIyXzAxX2RheXJpZGVzbm90bW9yZXRoYW4zaG91cnNfY2AgDQoNCkdST1VQIEJZIGJpa2VfdHlwZQ0KYGBgDQoNClRoaXMgY291bnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgcmlkZXMgb24gY2xhc3NpYyBiaWtlcyBmb3IgZGF5IHJpZGUgc3Vic2NyaWJlcnMgd2l0aCByaWRlcyBub3QgZXhjZWVkaW5nIDMgaG91cnMuIFRoZW4gSSBjaG9vc2UgIlNhdmUgUmVzdWx0cyIgYXMgYW5vdGhlciBCaWdRdWVyeSB0YWJsZSBhbmQgbmFtZSBpdCAiKioyMDIyX3h4X2NsYXNzaWNiaWtlc29uZWRheXJpZGVzX25vdGFib3ZlM2hvdXJzX2MqKiIuDQoNClN0ZXAgMy4gTmV4dCAsIEkgY3JlYXRlIGEgdGFibGUgdGhhdCBzdW1tYXJpc2VzIG51bWJlciBvZiBvbmUgZGF5IHJpZGVzIGFuZCB0b3RhbCBkdXJhdGlvbiBjaGFyZ2VkIGJ5IG1pbnV0ZXMuDQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KYmlrZV90eXBlLA0KQ09VTlQoYmlrZV90eXBlKSBBUyBub19vZl9vbmVkYXlfcmlkZXMsDQpTVU0odHJpcF9kdXJhdGlvbl9jaGFyZ2VkX2J5X21pbikgQVMgdG90YWxfZHVyYXRpb25fY2hhcmdlZF9ieV9taW4NCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfY2xhc3NpY2Jpa2V0cmlwZGF0YV9jYXN1YWwuMjAyMl8wMV9kYXlyaWRlc3dpdGhpbm9uZWRheV9jYA0KDQpHUk9VUCBCWSBiaWtlX3R5cGUNCmBgYA0KDQpUaGlzIGNvdW50cyB0aGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIG9uIGNsYXNzaWMgYmlrZXMgZm9yIG9uZSBkYXkgcmlkZSBzdWJzY3JpYmVycyBhbmQgdG90YWwgZHVyYXRpb24gY2hhcmdlZCBieSBtaW51dGVzLiBUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9jbGFzc2ljYmlrZXNvbmVkYXlyaWRlc19ub3RhYm92ZTFkYXlfYyoqIi4NCg0KU3RlcCA0LiBOZXh0LCBJIGNyZWF0ZSBhIHRhYmxlIHRoYXQgc3VtbWFyaXNlcyBudW1iZXIgb2YgdHdvIGRheSByaWRlcyBhbmQgdG90YWwgZHVyYXRpb24gY2hhcmdlZCBieSBtaW51dGVzIGZvciBmaXJzdCBkYXkuDQpgYGB7bXlzcWwgZXZhbD1GQUxTRX0NClNFTEVDVCAgDQoNCmJpa2VfdHlwZSwNCkNPVU5UKGJpa2VfdHlwZSkgQVMgbm9fb2ZfdHdvZGF5X3JpZGVzLA0KU1VNKGRheTFfdHJpcF9vZl9kdXJhdGlvbl9jaGFyZ2VkX2J5X21pbikgQVMgdG90YWxfZGF5MV90cmlwX2R1cmF0aW9uX2NoYXJnZWRfYnlfbWluDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2NsYXNzaWNiaWtldHJpcGRhdGFfY2FzdWFsLjIwMjJfMDFfZGF5cmlkZXNhYm92ZW9uZWRheV9jYA0KDQpHUk9VUCBCWSBiaWtlX3R5cGUNCmBgYA0KDQpUaGlzIGNvdW50cyB0aGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIG9uIGNsYXNzaWMgYmlrZXMgZm9yIHR3byBkYXkgcmlkZSBzdWJzY3JpYmVycyBhbmQgdG90YWwgZHVyYXRpb24gY2hhcmdlZCBieSBtaW51dGVzIGZvciBmaXJzdCBkYXkuIFRoZW4gSSBjaG9vc2UgIlNhdmUgUmVzdWx0cyIgYXMgYW5vdGhlciBCaWdRdWVyeSB0YWJsZSBhbmQgbmFtZSBpdCAiKioyMDIyX3h4X2NsYXNzaWNiaWtlc3R3b2RheXJpZGVzX2MqKiIuDQoNClN0ZXAgNS4gRmluYWxseSwgSSBjcmVhdGUgYSB0YWJsZSB0aGF0IHN1bW1hcml6ZXMgbnVtYmVyIG9mIHJpZGVzIGFuZCB0b3RhbCBkdXJhdGlvbiBvZiByaWRlcyBjaGFyZ2VkIGJ5IG90aGVyIGJpa2UgdHlwZXMuDQoNCmBgYHtteXNxbCBldmFsPUZBTFNFfQ0KU0VMRUNUICANCg0KYmlrZV90eXBlLA0KQ09VTlQoYmlrZV90eXBlKSBBUyBub19vZl9yaWRlcywNClNVTShkdXJhdGlvbl9vZl90cmlwX21pbnMpIEFTIHRvdGFsX2R1cmF0aW9uX2NoYXJnZWQNCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfbm9uY2xhc3NpY2Jpa2V0cmlwZGF0YV9jYXN1YWwuMjAyMl94eF9iaWtldHJpcGRhdGFfbm9uY2xhc3NpY2Jpa2VzX2NgDQoNCkdST1VQIEJZIGJpa2VfdHlwZQ0KYGBgDQoNClRoaXMgY291bnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgcmlkZXMgb24gb3RoZXIgYmlrZXMgZm9yIGNhc3VhbCByaWRlcnMgYW5kIHRvdGFsIGR1cmF0aW9uIGNoYXJnZWQgYnkgbWludXRlcy4gVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfb3RoZXJiaWtlcmlkZXNfYyoqIi4NCg0KVGhlIGFib3ZlIHN0ZXBzIDEgdG8gNSBhcmUgcmVwZWF0ZWQgZm9yIGFsbCAxMiBtb250aHMgb2YgY2FzdWFsIHJpZGVycyBkYXRhLg0KDQojIyMgTWVtYmVyIHJpZGVycyBkYXRhDQoNClN0ZXAgMS4gRm9yIGVhc2Ugb2YgY2FsY3VsYXRpbmcgcmV2ZW51ZXMsIEkgcXVlcnkgdGhlIHRhYmxlIGFib3V0IGNsYXNzaWMgYmlrZSByaWRlcyBub3QgYWJvdmUgNDUgbWludXRlcyBmb3IgbWVtYmVycyB1c2luZyB0aGUgZm9sbG93aW5nIFNRTCBxdWVyeToNCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQpTRUxFQ1QgDQoNCmJpa2VfdHlwZSwNCkNPVU5UKGJpa2VfdHlwZSkgQVMgbm9fb2ZfcmlkZXMsDQpTVU0oZHVyYXRpb25fb2ZfdHJpcF9taW5zKSBBUyB0b3RhbF90cmlwX2R1cmF0aW9uDQoNCmBjYXNlLXN0dWR5LWRpdnZ5YmlrZXMuMjAyMl9jbGFzc2ljYmlrZXRyaXBkYXRhX21lbWJlci4yMDIyX3h4X2NsYXNzaWNiaWtlcmlkZXNub3RhYm92ZTQ1bWluc19tYA0KDQpHUk9VUCBCWSBiaWtlX3R5cGUNCmBgYA0KDQpUaGlzIGNvdW50cyB0aGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIG9uIGNsYXNzaWMgYmlrZXMgZm9yIG1lbWJlcnMgd2hvc2UgcmlkZXMgZG8gbm90IGV4Y2VlZCA0NSBtaW51dGVzLiBJbiBvdGhlciB3b3JkcywgZWFjaCByaWRlIGlzIG9ubHkgY2hhcmdlZCBtb250aGx5LiBUaGVuIEkgY2hvb3NlICJTYXZlIFJlc3VsdHMiIGFzIGFub3RoZXIgQmlnUXVlcnkgdGFibGUgYW5kIG5hbWUgaXQgIioqMjAyMl94eF9jbGFzc2ljYmlrZXJpZGVzY2hhcmdlZG1vbnRobHlfbSoqIi4NCg0KU3RlcCAyLiBUaGVuIEkgY3JlYXRlIGEgdGFibGUgdGhhdCBzdW1tYXJpc2VzIG51bWJlciBvZiBjbGFzc2ljIGJpa2UgcmlkZXMgYWJvdmUgNDUgbWludXRlcyBmb3IgbWVtYmVycy4NCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQoNClNFTEVDVCAgDQoNCmJpa2VfdHlwZSwNCkNPVU5UKGJpa2VfdHlwZSkgQVMgbm9fb2ZfcmlkZXMsDQpTVU0odHJpcF9kdXJhdGlvbl9jaGFyZ2VkX2J5X21pbikgQVMgdG90YWxfdHJpcF9kdXJhdGlvbl9jaGFyZ2VkDQoNCkZST00gYGNhc2Utc3R1ZHktZGl2dnliaWtlcy4yMDIyX2NsYXNzaWNiaWtldHJpcGRhdGFfbWVtYmVyLjIwMjJfeHhfY2xhc3NpY2Jpa2VyaWRlc2Fib3ZlNDVtaW5zX21gIA0KDQpHUk9VUCBCWSBiaWtlX3R5cGUNCmBgYA0KDQpUaGlzIGNvdW50cyB0aGUgdG90YWwgbnVtYmVyIG9mIGNsYXNzaWMgYmlrZSByaWRlcyBmb3IgbWVtYmVycyBhbmQgdG90YWwgZHVyYXRpb24gY2hhcmdlZCBieSBtaW51dGVzLiBJbiBvdGhlciB3b3JkcywgZWFjaCByaWRlIGhhcyBhIG1vbnRobHkgY2hhcmdlIGFzIHdlbGwgYXMgYSBjaGFyZ2UgcGVyIG1pbnV0ZSBleGNlZWRpbmcgNDUgbWludXRlcy4gVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfY2xhc3NpY2Jpa2VyaWRlc3dpdGhtaW51dGVjaGFyZ2VzX20qKiIuDQoNClN0ZXAgMy4NCg0KYGBge215c3FsIGV2YWw9RkFMU0V9DQoNClNFTEVDVCANCg0KYmlrZV90eXBlLA0KQ09VTlQoYmlrZV90eXBlKSBBUyBub19vZl9yaWRlcywNClNVTShkdXJhdGlvbl9vZl90cmlwX21pbnMpIEFTIHRvdGFsX2R1cmF0aW9uX2NoYXJnZWQNCg0KRlJPTSBgY2FzZS1zdHVkeS1kaXZ2eWJpa2VzLjIwMjJfbm9uY2xhc3NpY2Jpa2V0cmlwZGF0YV9tZW1iZXIuMjAyMl94eF9lbGVjdHJpY2Jpa2VyaWRlc19tYA0KDQpHUk9VUCBCWSBiaWtlX3R5cGUNCmBgYA0KDQpUaGlzIGNvdW50cyB0aGUgdG90YWwgbnVtYmVyIG9mIGNsYXNzaWMgYmlrZSByaWRlcyBmb3IgbWVtYmVycyBhbmQgdG90YWwgZHVyYXRpb24gY2hhcmdlZCBieSBtaW51dGVzLiBJbiBvdGhlciB3b3JkcywgZWFjaCByaWRlIGhhcyBhIG1vbnRobHkgY2hhcmdlIGFzIHdlbGwgYXMgYSBjaGFyZ2UgcGVyIG1pbnV0ZSBleGNlZWRpbmcgNDUgbWludXRlcy4gVGhlbiBJIGNob29zZSAiU2F2ZSBSZXN1bHRzIiBhcyBhbm90aGVyIEJpZ1F1ZXJ5IHRhYmxlIGFuZCBuYW1lIGl0ICIqKjIwMjJfeHhfZWxlY3RyaWNiaWtlcmlkZXNjaGFyZ2VkYnltaW5fbSoqIi4NCg0KVGhlIGFib3ZlIHN0ZXBzIDEgdG8gMyBhcmUgcmVwZWF0ZWQgZm9yIGFsbCAxMiBtb250aHMgb2YgbWVtYmVyIHJpZGVycyBkYXRhLg0KDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQojIERhdGEgVmlzdWFsaXphdGlvbiBpbiBFeGNlbCwgVGFibGVhdSBhbmQgUg0KDQojIyBFeGNlbA0KDQpBZnRlciBjcmVhdGluZyBhbGwgdGhvc2UgbW9udGhseSB0YWJsZXMgaW4gU1FMIEJpZ1F1ZXJ5LCBJIGRvd25sb2FkZWQgdGhlbSBpbnRvIEV4Y2VsIGFuZCBwdXQgdGhlbSB0b2dldGhlciBpbnRvIGFubnVhbCB0YWJsZXMgb2YgZGF0YSB0byBjb21wYXJlIHRyZW5kcyBhY3Jvc3MgbW9udGhzLiBUaGUgZm9sbG93aW5nIEV4Y2VsIHRhYmxlcyBhcmUgYXNzZW1ibGVkOg0KDQoqIDIwMjJfYW5udWFsX2NsYXNzaWNiaWtlZGF0YV9ieWRheXNfY2FzdWFsDQoqIDIwMjJfYW5udWFsX2NsYXNzaWNiaWtlZGF0YV9ieWRheXNfbWVtYmVyDQoqIDIwMjJfYW5udWFsX2NsYXNzaWNiaWtlZGF0YV9ieW1pbnNfY2FzdWFsDQoqIDIwMjJfYW5udWFsX2NsYXNzaWNiaWtlZGF0YV9ieW1pbnNfbWVtYmVyDQoqIDIwMjJfYW5udWFsX2RvY2tlZGJpa2VkYXRhX2J5ZGF5c19jYXN1YWwNCiogMjAyMl9hbm51YWxfZG9ja2VkYmlrZWRhdGFfYnltaW5zX2Nhc3VhbA0KKiAyMDIyX2FubnVhbF9lbGVjdHJpY2Jpa2VkYXRhX2J5ZGF5c19jYXN1YWwNCiogMjAyMl9hbm51YWxfZWxlY3RyaWNiaWtlZGF0YV9ieWRheXNfbWVtYmVyDQoqIDIwMjJfYW5udWFsX2VsZWN0cmljYmlrZWRhdGFfYnltaW5zX2Nhc3VhbA0KKiAyMDIyX2FubnVhbF9lbGVjdHJpY2Jpa2VkYXRhX2J5bWluc19tZW1iZXINCiogMjAyMnJldl9jbGFzc2ljYmlrZW9uZWRheXJpZGVzX25vdGFib3ZlMWRheV9jDQoqIDIwMjJyZXZfY2xhc3NpY2Jpa2VvbmVkYXlyaWRlc19ub3RhYm92ZTNob3Vyc3BlcnJpZGVfYw0KKiAyMDIycmV2X2NsYXNzaWNiaWtlcmlkZXN3aXRobW9udGhseSZtaW5jaGFyZ2VzX20NCiogMjAyMnJldl9jbGFzc2ljYmlrZXJpZGVzd2l0aG9ubHltb250aGx5Y2hhcmdlX20NCiogMjAyMnJldl9jbGFzc2ljYmlrZXNpbmdsZXJpZGVzX2MNCiogMjAyMnJldl9jbGFzc2ljYmlrZXR3b2RheXJpZGVzX2MNCiogMjAyMnJldl9kb2NrZWRiaWtlcmlkZXNfYw0KKiAyMDIycmV2X2VsZWN0cmljYmlrZXJpZGVzX2MNCiogMjAyMnJldl9lbGVjdHJpY2Jpa2VjaGFyZ2VkYnltaW5fbQ0KDQpCYXNlZCBvbiB0aGVzZSB0YWJsZXMsIEkgdXNlZCBFeGNlbCB0byBkcmF3IHVwIGNoYXJ0cyB0byB2aXN1YWxpemUgYmlrZSB1c2FnZSBhbmQgcmV2ZW51ZSBwYXR0ZXJucyB0aHJvdWdob3V0IHRoZSB5ZWFyLg0KDQojIyBSDQoNCkkgYWxzbyBhdHRlbXB0ZWQgdG8gZHJhdyBsaW5lIHBsb3Qgb24gb25lIGRhdGEgdGFibGUgb2YgdGhlIGNsYXNzaWMgYmlrZSByaWRpbmcgZGF0YSBmb3IgY2FzdWFsIHVzZXJzIHVzaW5nIHRoZSBmb2xsb3dpbmcgY29kZSBpbiBSLg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkocmVhZHIpDQpYMjAyMl9hbm51YWxfY2xhc3NpY2Jpa2VkYXRhX2J5bW9udGhfY2FzdWFsIDwtIHJlYWRfY3N2KCJiaWtlX3RyaXBzX2RhdGFfcHJvY2Vzc2VkLzIwMjJfYW5udWFsX2NsYXNzaWNiaWtlZGF0YV9ieW1vbnRoX2Nhc3VhbC5jc3YiKQ0KDQojIyBTZXR0aW5nIGEgZGF0YSBmcmFtZSBhcyBkYXRhIHRhYmxlDQpzZXREVChYMjAyMl9hbm51YWxfY2xhc3NpY2Jpa2VkYXRhX2J5bW9udGhfY2FzdWFsKSANCg0KIyMgU29ydHMgdGFibGUgaW50byBsb25nIGZvcm0gDQpkZjEgPC0gbWVsdChYMjAyMl9hbm51YWxfY2xhc3NpY2Jpa2VkYXRhX2J5bW9udGhfY2FzdWFsLCJNb250aHMiKQ0KcHJpbnQoZGYxKSANCg0KIyMgUmVvcmRlcnMgTW9udGhzIGZyb20gSmFuIHRvIERlYw0KZGYxJE1vbnRocyA9IGZhY3RvcihkZjEkTW9udGhzLCBsZXZlbHMgPSBtb250aC5hYmIpIA0KDQojIyBBY3R1YWwgcGxvdA0KZ2dwbG90KGRmMSwgYWVzKHg9TW9udGhzLCB5PXZhbHVlLCBncm91cD12YXJpYWJsZSwgY29sb3VyPXZhcmlhYmxlKSkgKw0KICBnZW9tX2xpbmUoKSsNCiAgZ2VvbV9wb2ludCgpKw0KICB5bGFiKCJOdW1iZXIgb2YgUmlkZXMiKSsNCiAgbGFicyhjb2xvdXI9IkRheXMgb2YgV2VlayIpKw0KICBsYWJzKHRpdGxlPSJDbGFzc2ljIEJpa2UgUmlkZXMgLSBDYXN1YWwiKQ0KYGBgDQoNCkkgZHJldyBhIGJhciBjaGFydCBvbiBhbm90aGVyIGRhdGEgdGFibGUgb2YgdGhlIGVsZWN0cmljIGJpa2UgcmlkaW5nIGRhdGEgZm9yIG1lbWJlcnMgdXNpbmcgdGhlIGZvbGxvd2luZyBjb2RlIGluIFIuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShyZWFkcikNClgyMDIyX2FubnVhbF9lbGVjdHJpY2Jpa2VkYXRhX2J5ZHVyYXRpb25fbWVtYmVyIDwtIHJlYWRfY3N2KCJiaWtlX3RyaXBzX2RhdGFfcHJvY2Vzc2VkLzIwMjJfYW5udWFsX2VsZWN0cmljYmlrZWRhdGFfYnlkdXJhdGlvbl9tZW1iZXIuY3N2IikNClgyMDIyX2FubnVhbF9lbGVjdHJpY2Jpa2VkYXRhX2J5YXZnZHVyYXRpb25fbWVtYmVyIDwtIHJlYWRfY3N2KCJiaWtlX3RyaXBzX2RhdGFfcHJvY2Vzc2VkLzIwMjJfYW5udWFsX2VsZWN0cmljYmlrZWRhdGFfYnlhdmdkdXJhdGlvbl9tZW1iZXIuY3N2IikNCg0KIyMgU2V0dGluZyBkYXRhIGZyYW1lcyBhcyBkYXRhIHRhYmxlcw0Kc2V0RFQoWDIwMjJfYW5udWFsX2VsZWN0cmljYmlrZWRhdGFfYnlkdXJhdGlvbl9tZW1iZXIpDQpzZXREVChYMjAyMl9hbm51YWxfZWxlY3RyaWNiaWtlZGF0YV9ieWF2Z2R1cmF0aW9uX21lbWJlcikNCg0KIyMgU29ydHMgdGFibGUgaW50byBsb25nIGZvcm0gDQpkZjIgPC0gbWVsdChYMjAyMl9hbm51YWxfZWxlY3RyaWNiaWtlZGF0YV9ieWR1cmF0aW9uX21lbWJlciwibW9udGgiKQ0KcHJpbnQoZGYyKSANCmRmMyA8LSBtZWx0KFgyMDIyX2FubnVhbF9lbGVjdHJpY2Jpa2VkYXRhX2J5YXZnZHVyYXRpb25fbWVtYmVyLCJtb250aCIpDQpwcmludChkZjMpDQoNCiMjIFJlb3JkZXJzIE1vbnRocyBmcm9tIEphbiB0byBEZWMNCmRmMiRtb250aCA9IGZhY3RvcihkZjIkbW9udGgsIGxldmVscyA9IG1vbnRoLmFiYikNCmRmMyRtb250aCA9IGZhY3RvcihkZjMkbW9udGgsIGxldmVscyA9IG1vbnRoLmFiYikgDQoNCiMjIEFjdHVhbCBwbG90cw0KZ2dwbG90KGRmMiwgYWVzKG1vbnRoLCB2YWx1ZSwgZmlsbD12YXJpYWJsZSwgbGFiZWw9dmFsdWUpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSsNCiAgZ2VvbV90ZXh0KHZqdXN0PS0wLjUsIHNpemU9MS41KSsNCiAgeWxhYigiRHVyYXRpb24gKERheXMpIikrDQogIGxhYnMoZmlsbD0iIikrDQogIGxhYnModGl0bGU9IkVsZWN0cmljIEJpa2UgUmlkZXMgLSBNZW1iZXIiKQ0KDQpnZ3Bsb3QoZGYzLCBhZXMobW9udGgsIHZhbHVlLCBmaWxsPXZhcmlhYmxlLCBsYWJlbD12YWx1ZSkpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpKw0KICBnZW9tX3RleHQodmp1c3Q9LTAuNSwgc2l6ZT0xLjUpKw0KICB5bGFiKCJEdXJhdGlvbiAoTWlucykiKSsNCiAgbGFicyhmaWxsPSIiKSsNCiAgbGFicyh0aXRsZT0iRWxlY3RyaWMgQmlrZSBSaWRlcyAtIE1lbWJlciIpDQpgYGANCg0KDQojIyBUYWJsZWF1DQoNCkkgdXNlZCBUYWJsZWF1IHRvIGdpdmUgYmV0dGVyIHZpc3VhbGlzYXRpb25zIG9uIHRoZSBzdGFydGluZyBsb2NhdGlvbiBvZiBiaWtlIHVzYWdlIGJ5IGNhc3VhbCByaWRlcnMgYXMgd2VsbCBhcyB0cmlwIHJldmVudWUgZnJvbSBjbGFzc2ljIGJpa2UgZm9yIG1lbWJlcnMgaW4gMjAyMi4NCg0KWyoqVml6IDE6IFRyaXAgUmV2ZW51ZSBvZiBDbGFzc2ljIEJpa2UgUmlkZXMgZm9yIE1lbWJlcnMqKl0oaHR0cHM6Ly9wdWJsaWMudGFibGVhdS5jb20vdmlld3MvQmlrZVNoYXJpbmdDYXNlU3R1ZHlfMTY3MzQzMTYwNTM4NDAvU2hlZXQxPzpsYW5ndWFnZT1lbi1VUyY6ZGlzcGxheV9jb3VudD1uJjpvcmlnaW49dml6X3NoYXJlX2xpbmspIA0KDQoNClsqKlZpeiAyOiBTdGFydGluZyBMb2NhdGlvbiBmb3IgQ2FzdWFsIFJpZGVycyoqXShodHRwczovL3B1YmxpYy50YWJsZWF1LmNvbS92aWV3cy9CaWtlU2hhcmluZ0Nhc2VTdHVkeVZpejIvU2hlZXQyPzpsYW5ndWFnZT1lbi1VUyY6ZGlzcGxheV9jb3VudD1uJjpvcmlnaW49dml6X3NoYXJlX2xpbmspDQoNCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18NCiMgQW5hbHlzaXMgJiBSZWNvbW1lbmRhdGlvbnMNCg0KIyMgUmlkaW5nIHBhdHRlcm5zIG9mIGNhc3VhbCByaWRlcnMgYW5kIG1lbWJlcnMNCg0KVGhlIGZvbGxvd2luZyBjb21wYXJpc29ucyB3ZXJlIG1hZGUgYmV0d2VlbiBjYXN1YWwgcmlkZXJzIGFuZCBtZW1iZXJzOg0KDQoxLiBSaWRpbmcgcGF0dGVybnMgZXZlcnkgZGF5IG9mIHRoZSB3ZWVrIGJ5IGVhY2ggbW9udGggb2YgMjAyMg0KMi4gUmlkaW5nIHBhdHRlcm5zIGV2ZXJ5IG1vbnRoIG9mIDIwMjIgYnkgZWFjaCBkYXkgb2Ygd2Vlaw0KMy4gUmV2ZW51ZSBwYXR0ZXJucyBmb3IgMjAyMiBmb3IgY2xhc3NpYyBhbmQgZWxlY3RyaWMgYmlrZXMNCg0KU2luY2Ugd2UgY2Fubm90IHRyYWNlIGVhY2ggcmlkZSBpZCB0byBlYWNoIHJpZGVyLCBpdCBpcyBpbXBvc3NpYmxlIHRvIGRldGVybWluZSB0aGUgdHJ1ZSByZXZlbnVlIGZyb20gY2FzdWFsIHJpZGVycyBhbmQgbWVtYmVycyB1bmxlc3Mgd2UgYXJlIGdpdmVuIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgbWVtYmVyc2hpcCBzdWJzY3JpcHRpb24gcmV2ZW51ZSBhbmQgZGF5IHBhc3MgcmV2ZW51ZXMuIEFsdGVybmF0aXZlbHksIGl0IGlzIGJldHRlciB0byBjb21wYXJlIHRyaXAgcmV2ZW51ZSBjaGFyZ2VkIGJ5IG1pbnV0ZSBmb3IgZWFjaCB0eXBlIG9mIGJpa2UuIA0KDQojIyMgQ2xhc3NpYyBiaWtlcw0KDQpGb3IgYm90aCBjYXN1YWwgcmlkZXJzIGFuZCBtZW1iZXJzLCBudW1iZXIgb2YgcmlkZXMgZm9yIGNsYXNzaWMgYmlrZXMgc2VlbSB0byBwZWFrIGFyb3VuZCB0aGUgbWlkZGxlIG9mIHRoZSB5ZWFyIGFuZCBkZWNsaW5lIGJ5IHRoZSBlbmQgb2YgdGhlIHllYXIuIEZvciBjYXN1YWwgcmlkZXJzLCB0aGUgcGVhayBpcyBpbiBKdWx5IG9uIFNhdHVyZGF5cywgcmVhY2hpbmcgNDBrIHJpZGVzLiBGb3IgbWVtYmVycywgdGhlIHBlYWsgaXMgaW4gSnVuIG9uIFRodXJzZGF5cywgcmVhY2hpbmcgNDJrIHJpZGVzLiBGb3IgYm90aCBjYXN1YWwgcmlkZXJzIGFuZCBtZW1iZXJzLCBudW1iZXIgb2YgcmlkZXMgZm9yIGNsYXNzaWMgYmlrZXMgYXJlIGxvd2VzdCBpbiBKYW51YXJ5IGFuZCBGZWJydWFyeS4gRm9yIGNhc3VhbCByaWRlcnMsIG51bWJlciBvZiByaWRlcyBhcmUgZ2VuZXJhbGx5IGhpZ2hlciBpbiBKdW5lIGFuZCBKdWx5IHdoaWxlIHRoYXQgZm9yIG1lbWJlcnMgaXMgaW4gSnVuZS4gKipJbiBnZW5lcmFsLCBtZW1iZXJzIGhhdmUgaGlnaGVyIG51bWJlciBvZiByaWRlcyBmb3IgY2xhc3NpYyBiaWtlcyB0aGFuIGNhc3VhbCByaWRlcnMuKioNCg0KIVsqKk51bWJlciBvZiBjbGFzc2ljIGJpa2UgcmlkZXMgb2YgY2F1c2FsIHJpZGVycyBieSBkYXlzKipdKGNhc3VhbF9ncmFwaGljcy9jbGFzc2ljYmlrZXJpZGVzX2Nhc3VhbF9ieWRheXNvZndlZWsuanBnKQ0KDQohWyoqTnVtYmVyIG9mIGNsYXNzaWMgYmlrZSByaWRlcyBvZiBtZW1iZXJzIGJ5IGRheXMqKl0obWVtYmVyX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfbWVtYmVyX2J5ZGF5c29md2Vlay5qcGcpDQoNCiFbKipOdW1iZXIgb2YgY2xhc3NpYyBiaWtlIHJpZGVzIG9mIGNhc3VhbCByaWRlcnMgYnkgbW9udGgqKl0oY2FzdWFsX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfY2FzdWFsX2J5bW9udGguanBnKQ0KDQohWyoqTnVtYmVyIG9mIGNsYXNzaWMgYmlrZSByaWRlcyBvZiBtZW1iZXJzIGJ5IG1vbnRoKipdKG1lbWJlcl9ncmFwaGljcy9jbGFzc2ljYmlrZXJpZGVzX21lbWJlcl9ieW1vbnRoLmpwZykNCg0KDQpIb3dldmVyLCBpZiB3ZSBsb29rIGF0IGR1cmF0aW9uIG9mIHJpZGVzLCAqKmNhc3VhbCByaWRlcnMgaGF2ZSBoaWdoZXIgdG90YWwgZHVyYXRpb24gb2YgcmlkZXMgYXQgaXRzIHBlYWsgY29tcGFyZWQgdG8gbWVtYmVycy4qKiBUaGlzIGNvdWxkIGJlIGR1ZSB0byB0aGUgZ3JlYXRlciBudW1iZXIgb2YgY2FzdWFsIHJpZGVycyB0aGFuIG1lbWJlcnMgb2YgY2xhc3NpYyBiaWtlcyBvciBkdWUgdG8gdGhlIGxvbmdlciB0aW1lIGNhc3VhbCByaWRlcnMgc3BlbmQgb24gY2xhc3NpYyBiaWtlIHJpZGVzIGR1cmluZyB0aGUgcGVhayBtb250aCAoSnVuZSkuIFRoaXMgaXMgYW5zd2VyZWQgcGFydGx5IGJ5IGxvb2tpbmcgYXQgdGhlIGF2ZXJhZ2UgZHVyYXRpb24gb2YgZWFjaCByaWRlIG9uIGNsYXNzaWMgYmlrZXMgYnkgY2FzdWFsIHJpZGVycyBhbmQgbWVtYmVycy4gKipJbiBnZW5lcmFsLCBjYXN1YWwgcmlkZXJzIHNwZW5kIGEgbG9uZ2VyIGF2ZXJhZ2UgdGltZSBvbiBjbGFzc2ljIGJpa2VzKiogKG92ZXIgMjAgbWludXRlcyBwZXIgcmlkZSBldmVyeSBtb250aCkgd2l0aCB0aGUgaGlnaGVzdCBhdmVyYWdlIGR1cmF0aW9uIGJlaW5nIDMyIG1pbnV0ZXMgaW4gTWFyY2guIE1lbWJlcnMsIG9uIHRoZSBvdGhlciBoYW5kLCBzcGVuZCBsZXNzIHRoYW4gMjAgbWludXRlcyBwZXIgcmlkZSBldmVyeSBtb250aCB3aXRoIGhpZ2hlc3QgYXZlcmFnZSBkdXJhdGlvbiBiZWluZyAxNSBtaW51dGVzIGluIEp1bHkuDQoNCiFbKipUb3RhbCBkdXJhdGlvbiBvbiBjbGFzc2ljIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfY2FzdWFsX2J5dG90YWxkdXJhdGlvbi5qcGcpDQoNCiFbKipUb3RhbCBkdXJhdGlvbiBvbiBjbGFzc2ljIGJpa2VzIGJ5IG1lbWJlcnMqKl0obWVtYmVyX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfbWVtYmVyX2J5dG90YWxkdXJhdGlvbi5qcGcpDQoNCiFbKipBdmVyYWdlIGR1cmF0aW9uIGVhY2ggcmlkZSBvbiBjbGFzc2ljIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfY2FzdWFsX2J5YXZnZHVyYXRpb24uanBnKQ0KDQohWyoqQXZlcmFnZSBkdXJhdGlvbiBlYWNoIHJpZGUgb24gY2xhc3NpYyBiaWtlcyBieSBtZW1iZXJzKipdKG1lbWJlcl9ncmFwaGljcy9jbGFzc2ljYmlrZXJpZGVzX21lbWJlcl9ieWF2Z2R1cmF0aW9uLmpwZykNCg0KSWYgd2UgbG9vayBhdCB0aGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIGJ5IGVhY2ggZGF5IG9mIHRoZSB3ZWVrIG9yIGJ5IG1vbnRoLCBzaW1pbGFyIHBhdHRlcm5zIG9jY3VyLiBUaGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIGZvciBtZW1iZXJzIGFyZSBnZW5lcmFsbHkgaGlnaGVyIHRoYW4gY2FzdWFsIHJpZGVycy4gVGhlIHRvdGFsIG51bWJlciBvZiByaWRlcyBmb3IgY2FzdWFsIG1lbWJlcnMgdGVuZCB0byBwZWFrIG9uIFNhdHVyZGF5IHdoaWxzdCB0aGF0IG9mIG1lbWJlcnMgdGVuZCB0byBiZSBvbiBUdWVzZGF5cy4gKipUaGlzIGNvdWxkIGJlIGR1ZSB0byB0aGUgZmFjdCB0aGF0IGNhc3VhbCByaWRlcnMgdGVuZCB0byB1c2UgY2xhc3NpYyBiaWtlcyBmb3IgbGVpc3VyZSB3aGlsZSBtZW1iZXJzIHRlbmQgdG8gdXNlIGNsYXNzaWMgYmlrZXMgZm9yIHdvcmsgdHJhdmVsLioqDQoNCiFbKipUb3RhbCBjbGFzc2ljIGJpa2UgcmlkZXMgb2YgY2FzdWFsIHJpZGVycyBieSBkYXlzKipdKGNhc3VhbF9ncmFwaGljcy9jbGFzc2ljYmlrZXJpZGVzX2Nhc3VhbF90b3RhbHNieWRheXNvZndlZWsuanBnKQ0KDQohWyoqVG90YWwgY2xhc3NpYyBiaWtlIHJpZGVzIG9mIG1lbWJlcnMgYnkgZGF5cyoqXShtZW1iZXJfZ3JhcGhpY3MvY2xhc3NpY2Jpa2VyaWRlc19tZW1iZXJfdG90YWxzYnlkYXlzb2Z3ZWVrLmpwZykNCg0KIVsqKlRvdGFsIGNsYXNzaWMgYmlrZSByaWRlcyBvZiBjYXN1YWwgcmlkZXJzIGJ5IG1vbnRocyoqXShjYXN1YWxfZ3JhcGhpY3MvY2xhc3NpY2Jpa2VyaWRlc19jYXN1YWxfdG90YWxzYnltb250aC5qcGcpDQoNCiFbKipUb3RhbCBjbGFzc2ljIGJpa2UgcmlkZXMgb2YgbWVtYmVycyBieSBtb250aHMqKl0obWVtYmVyX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfbWVtYmVyX3RvdGFsc2J5bW9udGguanBnKQ0KDQpUaGlzIGFsbCBtYWtlcyBzZW5zZSBhcyBjYXN1YWwgcmlkZXJzIHdvdWxkIHdhbnQgdG8gc3BlbmQgbW9yZSB0aW1lIG9uIGVhY2ggcmlkZSBkdWUgdG8gdGhlIHVubG9jayBjb3N0IG9mIDEgZG9sbGFyIHBlciByaWRlIHRoZXkgaW5jdXIgZm9yIHNpbmdsZSByaWRlcy4gVGh1cyB0aGV5IG1heSBjaG9vc2UgdG8gcmlkZSBsZXNzZXIgbnVtYmVyIG9mIHRpbWVzIGJ1dCBleHRlbmQgdGhlIGR1cmF0aW9uIG9mIGVhY2ggcmlkZSBzaW5jZSB0aGUgY29zdCBvZiAkMC4xNiBwZXIgbWludXRlIGlzIHRoZSBzYW1lIGFzIG1lbWJlcnMgZm9yIGNsYXNzaWMgYmlrZXMuIE9uIHRoZSBvdGhlciBoYW5kLCB0aGUgbnVtYmVyIG9mIHJpZGVzIGlzIGlycmVsZXZhbnQgdG8gbWVtYmVycyB3aG8gZG8gbm90IGhhdmUgdG8gcGF5IHVubG9jayBjb3N0cyBwZXIgcmlkZSBidXQgdGhleSBtYXkgd2FudCB0byBzYXZlIG1vbmV5IGJ5IGxpbWl0aW5nIGVhY2ggcmlkZSBkdXJhdGlvbiB0byBubyBtb3JlIHRoYW4gNDUgbWludXRlcyBhcyBtdWNoIGFzIHBvc3NpYmxlLiANCg0KRm9yIGNsYXNzaWMgYmlrZXMsIHRyaXAgcmV2ZW51ZXMgZm9yIGJvdGggbWVtYmVycyBhbmQgY2FzdWFsIHJpZGVycyB0ZW5kIHRvIHBlYWsgaW4gSnVuZS4gVHJpcCByZXZlbnVlIGZvciBtZW1iZXJzIGFyZSBvbmx5IG1vcmUgcHJvZml0YWJsZSB0aGFuIGNhc3VhbCByaWRlcnMgd2hvIGJ1eSB0aGUgZnVsbCBkYXkgcGFzcyBmb3Igb25lIGRheS4gVHJpcCByZXZlbnVlIGlzIGhpZ2hlc3QgZm9yIGNhc3VhbCByaWRlcnMgd2hvIGJ1eSBzaW5nbGUgcmlkZXMuDQoNCiFbKipUcmlwIHJldmVudWUgb2YgY2xhc3NpYyBiaWtlIGZvciBtZW1iZXJzKipdKG1lbWJlcl9ncmFwaGljcy90cmlwcmV2ZW51ZWNsYXNzaWNiaWtlX21lbWJlci5qcGcpDQoNCiFbKipUcmlwIHJldmVudWUgb2YgY2xhc3NpYyBiaWtlIGZ1bGwgZGF5IHBhc3MgZm9yIGNhc3VhbCByaWRlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL3RyaXByZXZlbnVlY2xhc3NpY2Jpa2VmdWxsZGF5cGFzc19jYXN1YWwuanBnKQ0KDQohWyoqVHJpcCByZXZlbnVlIG9mIGNsYXNzaWMgYmlrZSBzaW5nbGUgcmlkZXMgZm9yIGNhc3VhbCByaWRlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL3RyaXByZXZlbnVlY2xhc3NpY2Jpa2VzaW5nbGVyaWRlcGFzc19jYXN1YWwuanBnKQ0KDQohWyoqVHJpcCByZXZlbnVlIG9mIGNsYXNzaWMgYmlrZSB0d28gZnVsbCBkYXkgcGFzc2VzIGZvciBjYXN1YWwgcmlkZXJzKipdKGNhc3VhbF9ncmFwaGljcy90cmlwcmV2ZW51ZWNsYXNzaWNiaWtldHdvZnVsbGRheXBhc3NfY2FzdWFsLmpwZykNCg0KIyMjIEVsZWN0cmljIGJpa2VzDQoNCkZvciBjYXN1YWwgcmlkZXJzLCBudW1iZXIgb2YgcmlkZXMgZm9yIGVsZWN0cmljIGJpa2VzIHNlZW0gdG8gcGVhayBhcm91bmQgSnVseSB3aGlsZSBmb3IgbWVtYmVycywgdGhlIHBlYWsgaGFwcGVucyBpbiBTZXB0ZW1iZXIgYW5kIGRlY2xpbmUgYnkgdGhlIGVuZCBvZiB0aGUgeWVhci4gRm9yIGNhc3VhbCByaWRlcnMsIHRoZSBwZWFrIGlzIG9uIFNhdHVyZGF5cywgcmVhY2hpbmcgNDdrIHJpZGVzLiBGb3IgbWVtYmVycywgdGhlIHBlYWsgaXMgb24gVGh1cnNkYXlzLCByZWFjaGluZyAzOWsgcmlkZXMuIEZvciBib3RoIGNhc3VhbCByaWRlcnMgYW5kIG1lbWJlcnMsIG51bWJlciBvZiByaWRlcyBmb3IgZWxlY3RyaWMgYmlrZXMgYXJlIGxvd2VzdCBpbiBKYW51YXJ5IGFuZCBGZWJydWFyeS4gRm9yIGNhc3VhbCByaWRlcnMsIG51bWJlciBvZiByaWRlcyBhcmUgZ2VuZXJhbGx5IGhpZ2hlciBpbiBKdWx5IHdoaWxlIHRoYXQgZm9yIG1lbWJlcnMgaXMgaW4gQXVndXN0LiAqKkluIGdlbmVyYWwsIG1lbWJlcnMgaGF2ZSBoaWdoZXIgbnVtYmVyIG9mIHJpZGVzIGZvciBlbGVjdHJpYyBiaWtlcyB0aGFuIGNhc3VhbCByaWRlcnMuKioNCg0KIVsqKk51bWJlciBvZiBlbGVjdHJpYyBiaWtlIHJpZGVzIG9mIGNhdXNhbCByaWRlcnMgYnkgZGF5cyoqXShjYXN1YWxfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfY2FzdWFsX2J5ZGF5c29md2Vlay5qcGcpDQoNCiFbKipOdW1iZXIgb2YgZWxlY3RyaWMgYmlrZSByaWRlcyBvZiBtZW1iZXJzIGJ5IGRheXMqKl0obWVtYmVyX2dyYXBoaWNzL2VsZWN0cmljYmlrZXJpZGVzX21lbWJlcl9ieWRheXNvZndlZWsuanBnKQ0KDQohWyoqTnVtYmVyIG9mIGVsZWN0cmljIGJpa2UgcmlkZXMgb2YgY2FzdWFsIHJpZGVycyBieSBtb250aCoqXShjYXN1YWxfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfY2FzdWFsX2J5bW9udGguanBnKQ0KDQohWyoqTnVtYmVyIG9mIGVsZWN0cmljIGJpa2UgcmlkZXMgb2YgbWVtYmVycyBieSBtb250aCoqXShtZW1iZXJfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfbWVtYmVyX2J5bW9udGguanBnKQ0KDQpIb3dldmVyLCBpZiB3ZSBsb29rIGF0IGR1cmF0aW9uIG9mIHJpZGVzLCAqKmNhc3VhbCByaWRlcnMgaGF2ZSBoaWdoZXIgdG90YWwgZHVyYXRpb24gb2YgcmlkZXMgYXQgaXRzIHBlYWsgY29tcGFyZWQgdG8gbWVtYmVycy4qKiBUaGlzIGNvdWxkIGJlIGR1ZSB0byB0aGUgZ3JlYXRlciBudW1iZXIgb2YgY2FzdWFsIHJpZGVycyB0aGFuIG1lbWJlcnMgb2YgZWxlY3RyaWMgYmlrZXMgb3IgZHVlIHRvIHRoZSBsb25nZXIgdGltZSBjYXN1YWwgcmlkZXJzIHNwZW5kIG9uIGVsZWN0cmljIGJpa2UgcmlkZXMgZHVyaW5nIHRoZSBwZWFrIG1vbnRoLiBUaGlzIGlzIGFuc3dlcmVkIHBhcnRseSBieSBsb29raW5nIGF0IHRoZSBhdmVyYWdlIGR1cmF0aW9uIG9mIGVhY2ggcmlkZSBvbiBlbGVjdHJpYyBiaWtlcyBieSBjYXN1YWwgcmlkZXJzIGFuZCBtZW1iZXJzLiAqKkluIGdlbmVyYWwsIGNhc3VhbCByaWRlcnMgc3BlbmQgYSBsb25nZXIgYXZlcmFnZSB0aW1lIG9uIGVsZWN0cmljIGJpa2VzKiogd2l0aCB0aGUgaGlnaGVzdCBhdmVyYWdlIGR1cmF0aW9uIGJlaW5nIDE5IG1pbnV0ZXMgcGVyIHJpZGUgaW4gTWF5LiBNZW1iZXJzLCBvbiB0aGUgb3RoZXIgaGFuZCwgc3BlbmQgbGVzcyB0aGFuIDE1IG1pbnV0ZXMgZXZlcnkgbW9udGggd2l0aCBoaWdoZXN0IGF2ZXJhZ2UgZHVyYXRpb24gYmVpbmcgMTMgbWludXRlcyBwZXIgcmlkZSBpbiBKdW5lLg0KDQohWyoqVG90YWwgZHVyYXRpb24gb24gZWxlY3RyaWMgYmlrZXMgYnkgY2FzdWFsIHJpZGVycyoqXShjYXN1YWxfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfY2FzdWFsX2J5dG90YWxkdXJhdGlvbi5qcGcpDQoNCiFbKipUb3RhbCBkdXJhdGlvbiBvbiBlbGVjdHJpYyBiaWtlcyBieSBtZW1iZXJzKipdKG1lbWJlcl9ncmFwaGljcy9lbGVjdHJpY2Jpa2VyaWRlc19tZW1iZXJfYnl0b3RhbGR1cmF0aW9uLmpwZykNCg0KIVsqKkF2ZXJhZ2UgZHVyYXRpb24gZWFjaCByaWRlIG9uIGVsZWN0cmljIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL2VsZWN0cmljYmlrZXJpZGVzX2Nhc3VhbF9ieWF2Z2R1cmF0aW9uLmpwZykNCg0KIVsqKkF2ZXJhZ2UgZHVyYXRpb24gZWFjaCByaWRlIG9uIGVsZWN0cmljIGJpa2VzIGJ5IG1lbWJlcnMqKl0obWVtYmVyX2dyYXBoaWNzL2VsZWN0cmljYmlrZXJpZGVzX21lbWJlcl9ieWF2Z2R1cmF0aW9uLmpwZykNCg0KSWYgd2UgbG9vayBhdCB0aGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIGJ5IGVhY2ggZGF5IG9mIHRoZSB3ZWVrIG9yIGJ5IG1vbnRoLCBzaW1pbGFyIHBhdHRlcm5zIG9jY3VyLiBUaGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIGZvciBtZW1iZXJzIGFyZSBnZW5lcmFsbHkgaGlnaGVyIHRoYW4gY2FzdWFsIHJpZGVycy4gVGhlIHRvdGFsIG51bWJlciBvZiByaWRlcyBmb3IgY2FzdWFsIG1lbWJlcnMgdGVuZCB0byBwZWFrIG9uIFNhdHVyZGF5IHdoaWxzdCB0aGF0IG9mIG1lbWJlcnMgdGVuZCB0byBiZSBvbiBUaHVyc2RheXMuICoqVGhpcyBjb3VsZCBiZSBkdWUgdG8gdGhlIGZhY3QgdGhhdCBjYXN1YWwgcmlkZXJzIHRlbmQgdG8gdXNlIGVsZWN0cmljIGJpa2VzIGZvciBsZWlzdXJlIHdoaWxlIG1lbWJlcnMgdGVuZCB0byB1c2UgZWxlY3RyaWMgYmlrZXMgZm9yIHdvcmsgdHJhdmVsLioqDQoNCiFbKipUb3RhbCBlbGVjdHJpYyBiaWtlIHJpZGVzIG9mIGNhc3VhbCByaWRlcnMgYnkgZGF5cyoqXShjYXN1YWxfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfY2FzdWFsX3RvdGFsc2J5ZGF5c29md2Vlay5qcGcpDQoNCiFbKipUb3RhbCBlbGVjdHJpYyBiaWtlIHJpZGVzIG9mIG1lbWJlcnMgYnkgZGF5cyoqXShtZW1iZXJfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfbWVtYmVyX3RvdGFsc2J5ZGF5c29md2Vlay5qcGcpDQoNCiFbKipUb3RhbCBlbGVjdHJpYyBiaWtlIHJpZGVzIG9mIGNhc3VhbCByaWRlcnMgYnkgbW9udGhzKipdKGNhc3VhbF9ncmFwaGljcy9lbGVjdHJpY2Jpa2VyaWRlc19jYXN1YWxfdG90YWxzYnltb250aC5qcGcpDQoNCiFbKipUb3RhbCBlbGVjdHJpYyBiaWtlIHJpZGVzIG9mIG1lbWJlcnMgYnkgbW9udGhzKipdKG1lbWJlcl9ncmFwaGljcy9lbGVjdHJpY2Jpa2VyaWRlc19tZW1iZXJfdG90YWxzYnltb250aC5qcGcpDQoNClRoaXMgYWxsIG1ha2VzIHNlbnNlIGFzIGNhc3VhbCByaWRlcnMgd291bGQgd2FudCB0byBzcGVuZCBtb3JlIHRpbWUgb24gZWFjaCByaWRlIGR1ZSB0byB0aGUgdW5sb2NrIGNvc3Qgb2YgMSBkb2xsYXIgcGVyIHJpZGUgdGhleSBpbmN1ci4gVGh1cyB0aGV5IG1heSBjaG9vc2UgdG8gcmlkZSBsZXNzZXIgbnVtYmVyIG9mIHRpbWVzIGJ1dCBleHRlbmQgdGhlIGR1cmF0aW9uIG9mIGVhY2ggcmlkZS4gQnV0IHNpbmNlIHRoZSBjaGFyZ2VzIG9uIGNsYXNzaWMgYmlrZXMgYXJlIGNoZWFwZXIgcGVyIG1pbnV0ZSwgdGhleSB3b3VsZCBzcGVuZCBtb3JlIHRpbWUgb24gYXZlcmFnZSByaWRpbmcgY2xhc3NpYyBiaWtlcyB0aGFuIGVsZWN0cmljIGJpa2VzLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlIG51bWJlciBvZiByaWRlcyBpcyBpcnJlbGV2YW50IHRvIG1lbWJlcnMgd2hvIGRvIG5vdCBoYXZlIHRvIHBheSB1bmxvY2sgY29zdHMgcGVyIHJpZGUgYnV0IHRoZXkgbWF5IHdhbnQgdG8gc2F2ZSBjb3N0cyBieSBzcGVuZGluZyBtb3JlIHRpbWUgb24gYXZlcmFnZSBvbiBjbGFzc2ljIGJpa2VzIHNpbmNlIHRoZXJlIGFyZSBubyBjaGFyZ2VzIGZvciB0aGUgZmlyc3QgNDUgbWludXRlcyBwZXIgcmlkZS4gDQoNCkZvciBlbGVjdHJpYyBiaWtlcywgdHJpcCByZXZlbnVlcyBmb3IgY2FzdWFsIHJpZGVycyB0ZW5kIHRvIHBlYWsgaW4gSnVseSB3aGlsc3QgdGhhdCBmb3IgbWVtYmVycyB0ZW5kIHRvIHBlYWsgaW4gQXVndXN0LiBUcmlwIHJldmVudWUgZm9yIGNhc3VhbCByaWRlcnMgYXJlIGFsd2F5cyBtb3JlIHByb2ZpdGFibGUgdGhhbiBtZW1iZXJzLg0KDQohWyoqVHJpcCByZXZlbnVlIG9mIGVsZWN0cmljIGJpa2UgZm9yIG1lbWJlcnMqKl0obWVtYmVyX2dyYXBoaWNzL3RyaXByZXZlbnVlZWxlY3RyaWNiaWtlX21lbWJlci5qcGcpDQoNCiFbKipUcmlwIHJldmVudWUgb2YgY2xhc3NpYyBiaWtlIGZvciBjYXN1YWwgcmlkZXJzKipdKGNhc3VhbF9ncmFwaGljcy90cmlwcmV2ZW51ZWVsZWN0cmljYmlrZXNfY2FzdWFsLmpwZykNCg0KIyMjIERvY2tlZCBiaWtlcw0KDQpTaW5jZSB3ZSBkbyBub3QgaGF2ZSBkYXRhIGZvciBtZW1iZXJzIHdobyByaWRlIGRvY2tlZCBiaWtlcywgd2UgbG9vayBhdCByaWRpbmcgcGF0dGVybnMgZm9yIGNhc3VhbCByaWRlcnMgaW5zdGVhZC4gRm9yIGNhc3VhbCByaWRlcnMsIG51bWJlciBvZiByaWRlcyBmb3IgZG9ja2VkIGJpa2VzIHNlZW0gdG8gcGVhayBhdCA4ayByaWRlcyBhcm91bmQgSnVseSBvbiBTYXR1cmRheXMgYW5kIGRlY2xpbmUgYnkgdGhlIGVuZCBvZiB0aGUgeWVhci4gTnVtYmVyIG9mIHJpZGVzIGZvciBkb2NrZWQgYmlrZXMgYXJlIGxvd2VzdCBpbiBEZWNlbWJlciwgSmFudWFyeSBhbmQgRmVicnVhcnkuIE51bWJlciBvZiByaWRlcyBhcmUgZ2VuZXJhbGx5IGhpZ2hlciBpbiBKdW5lLiAqKkluIGdlbmVyYWwsIGNhc3VhbCByaWRlcnMgaGF2ZSBsb3dlc3QgbnVtYmVyIG9mIHJpZGVzIGZvciBkb2NrZWQgYmlrZXMuKioNCg0KIVsqKk51bWJlciBvZiBkb2NrZWQgYmlrZSByaWRlcyBvZiBjYXVzYWwgcmlkZXJzIGJ5IGRheXMqKl0oY2FzdWFsX2dyYXBoaWNzL2RvY2tlZGJpa2VyaWRlc19jYXN1YWxfYnlkYXlzb2Z3ZWVrLmpwZykNCg0KIVsqKk51bWJlciBvZiBjbGFzc2ljIGJpa2UgcmlkZXMgb2YgY2F1c2FsIHJpZGVycyBieSBkYXlzKipdKGNhc3VhbF9ncmFwaGljcy9jbGFzc2ljYmlrZXJpZGVzX2Nhc3VhbF9ieWRheXNvZndlZWsuanBnKQ0KDQohWyoqTnVtYmVyIG9mIGRvY2tlZCBiaWtlIHJpZGVzIG9mIGNhdXNhbCByaWRlcnMgYnkgZGF5cyoqXShjYXN1YWxfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfY2FzdWFsX2J5ZGF5c29md2Vlay5qcGcpDQoNCiFbKipOdW1iZXIgb2YgZG9ja2VkIGJpa2UgcmlkZXMgb2YgY2FzdWFsIHJpZGVycyBieSBtb250aCoqXShjYXN1YWxfZ3JhcGhpY3MvZG9ja2VkYmlrZXJpZGVzX2Nhc3VhbF9ieW1vbnRoLmpwZykNCg0KIVsqKk51bWJlciBvZiBjbGFzc2ljIGJpa2UgcmlkZXMgb2YgY2FzdWFsIHJpZGVycyBieSBtb250aCoqXShjYXN1YWxfZ3JhcGhpY3MvY2xhc3NpY2Jpa2VyaWRlc19jYXN1YWxfYnltb250aC5qcGcpDQoNCiFbKipOdW1iZXIgb2YgZWxlY3RyaWMgYmlrZSByaWRlcyBvZiBjYXN1YWwgcmlkZXJzIGJ5IG1vbnRoKipdKGNhc3VhbF9ncmFwaGljcy9lbGVjdHJpY2Jpa2VyaWRlc19jYXN1YWxfYnltb250aC5qcGcpDQoNCkhvd2V2ZXIsIGlmIHdlIGxvb2sgYXQgZHVyYXRpb24gb2YgcmlkZXMsICoqZG9ja2VkIGJpa2VzIGhhdmUgc2Vjb25kIGhpZ2hlc3QgdG90YWwgZHVyYXRpb24gb2YgcmlkZXMgYXQgaXRzIHBlYWsgY29tcGFyZWQgdG8gb3RoZXIgYmlrZSB0eXBlcy4qKiBUaGlzIGNvdWxkIGJlIGR1ZSB0byB0aGUgbG9uZ2VyIHRpbWUgY2FzdWFsIHJpZGVycyBzcGVuZCBvbiBkb2NrZWQgYmlrZSByaWRlcyBkdXJpbmcgdGhlIHBlYWsgbW9udGggc2luY2UgdGhlIG51bWJlciBvZiByaWRlcyBhcmUgdmVyeSBsb3cuIFRoaXMgaXMgYW5zd2VyZWQgYnkgbG9va2luZyBhdCB0aGUgYXZlcmFnZSBkdXJhdGlvbiBvZiBlYWNoIHJpZGUgb24gZG9ja2VkIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMuICoqSW4gZ2VuZXJhbCwgY2FzdWFsIHJpZGVycyBzcGVuZCB0aGUgbG9uZ2VzdCBhdmVyYWdlIHRpbWUgb24gZG9ja2VkIGJpa2VzIGNvbXBhcmVkIHRvIG90aGVyIGJpa2VzKiogd2l0aCB0aGUgaGlnaGVzdCBhdmVyYWdlIGR1cmF0aW9uIGJlaW5nIDIyMyBtaW51dGVzIGluIEphbi4NCg0KIVsqKlRvdGFsIGR1cmF0aW9uIG9uIGRvY2tlZCBiaWtlcyBieSBjYXN1YWwgcmlkZXJzKipdKGNhc3VhbF9ncmFwaGljcy9kb2NrZWRiaWtlcmlkZXNfY2FzdWFsX2J5dG90YWxkdXJhdGlvbi5qcGcpDQoNCiFbKipUb3RhbCBkdXJhdGlvbiBvbiBjbGFzc2ljIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfY2FzdWFsX2J5dG90YWxkdXJhdGlvbi5qcGcpDQoNCiFbKipUb3RhbCBkdXJhdGlvbiBvbiBlbGVjdHJpYyBiaWtlcyBieSBjYXN1YWwgcmlkZXJzKipdKGNhc3VhbF9ncmFwaGljcy9lbGVjdHJpY2Jpa2VyaWRlc19jYXN1YWxfYnl0b3RhbGR1cmF0aW9uLmpwZykNCg0KIVsqKkF2ZXJhZ2UgZHVyYXRpb24gZWFjaCByaWRlIG9uIGRvY2tlZCBiaWtlcyBieSBjYXN1YWwgcmlkZXJzKipdKGNhc3VhbF9ncmFwaGljcy9kb2NrZWRiaWtlcmlkZXNfY2FzdWFsX2J5YXZnZHVyYXRpb24uanBnKQ0KDQohWyoqQXZlcmFnZSBkdXJhdGlvbiBlYWNoIHJpZGUgb24gY2xhc3NpYyBiaWtlcyBieSBjYXN1YWwgcmlkZXJzKipdKGNhc3VhbF9ncmFwaGljcy9jbGFzc2ljYmlrZXJpZGVzX2Nhc3VhbF9ieWF2Z2R1cmF0aW9uLmpwZykNCg0KIVsqKkF2ZXJhZ2UgZHVyYXRpb24gZWFjaCByaWRlIG9uIGVsZWN0cmljIGJpa2VzIGJ5IGNhc3VhbCByaWRlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL2VsZWN0cmljYmlrZXJpZGVzX2Nhc3VhbF9ieWF2Z2R1cmF0aW9uLmpwZykNCg0KSWYgd2UgbG9vayBhdCB0aGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIGJ5IGVhY2ggZGF5IG9mIHRoZSB3ZWVrIG9yIGJ5IG1vbnRoLCBzaW1pbGFyIHBhdHRlcm5zIG9jY3VyLiBUaGUgdG90YWwgbnVtYmVyIG9mIHJpZGVzIGZvciBjYXN1YWwgcmlkZXJzIHRlbmQgdG8gcGVhayBvbiBTYXR1cmRheSBhbmQgaW4gSnVuZSBhbmQgSnVseS4gKipUaGlzIGNvdWxkIGJlIGR1ZSB0byB0aGUgZmFjdCB0aGF0IGNhc3VhbCByaWRlcnMgdGVuZCB0byB1c2UgZG9ja2VkIGJpa2VzIGZvciBsZWlzdXJlLioqDQoNCiFbKipUb3RhbCBkb2NrZWQgYmlrZSByaWRlcyBvZiBjYXN1YWwgcmlkZXJzIGJ5IGRheXMqKl0oY2FzdWFsX2dyYXBoaWNzL2RvY2tlZGJpa2VyaWRlc19jYXN1YWxfdG90YWxzYnlkYXlzb2Z3ZWVrLmpwZykNCg0KIVsqKlRvdGFsIGNsYXNzaWMgYmlrZSByaWRlcyBvZiBjYXN1YWwgcmlkZXJzIGJ5IGRheXMqKl0oY2FzdWFsX2dyYXBoaWNzL2NsYXNzaWNiaWtlcmlkZXNfY2FzdWFsX3RvdGFsc2J5ZGF5c29md2Vlay5qcGcpDQoNCiFbKipUb3RhbCBlbGVjdHJpYyBiaWtlIHJpZGVzIG9mIGNhc3VhbCByaWRlcnMgYnkgZGF5cyoqXShjYXN1YWxfZ3JhcGhpY3MvZWxlY3RyaWNiaWtlcmlkZXNfY2FzdWFsX3RvdGFsc2J5ZGF5c29md2Vlay5qcGcpDQoNCiFbKipUb3RhbCBkb2NrZWQgYmlrZSByaWRlcyBvZiBjYXN1YWwgcmlkZXJzIGJ5IG1vbnRocyoqXShjYXN1YWxfZ3JhcGhpY3MvZG9ja2VkYmlrZXJpZGVzX2Nhc3VhbF90b3RhbHNieW1vbnRoLmpwZykNCg0KIVsqKlRvdGFsIGNsYXNzaWMgYmlrZSByaWRlcyBvZiBjYXN1YWwgcmlkZXJzIGJ5IG1vbnRocyoqXShjYXN1YWxfZ3JhcGhpY3MvY2xhc3NpY2Jpa2VyaWRlc19jYXN1YWxfdG90YWxzYnltb250aC5qcGcpDQoNCiFbKipUb3RhbCBlbGVjdHJpYyBiaWtlIHJpZGVzIG9mIGNhc3VhbCByaWRlcnMgYnkgbW9udGhzKipdKGNhc3VhbF9ncmFwaGljcy9lbGVjdHJpY2Jpa2VyaWRlc19jYXN1YWxfdG90YWxzYnltb250aC5qcGcpDQoNClRoaXMgYWxsIG1ha2VzIHNlbnNlIGFzIGNhc3VhbCByaWRlcnMgd291bGQgd2FudCB0byBzcGVuZCBtb3JlIHRpbWUgb24gZWFjaCByaWRlIGR1ZSB0byB0aGUgdW5sb2NrIGNvc3Qgb2YgMSBkb2xsYXIgcGVyIHJpZGUgdGhleSBpbmN1ci4gVGh1cyB0aGV5IG1heSBjaG9vc2UgdG8gcmlkZSBsZXNzZXIgbnVtYmVyIG9mIHRpbWVzIGJ1dCBleHRlbmQgdGhlIGR1cmF0aW9uIG9mIGVhY2ggcmlkZS4gKipCdXQgaXQgaXMgdW5jbGVhciB3aHkgZG9ja2VkIGJpa2VzIGhhdmUgdGhlIGhpZ2hlc3QgYXZlcmFnZSBkdXJhdGlvbiBvZiByaWRlcyBjb21wYXJlZCB0byBvdGhlciBiaWtlcyBmb3IgY2FzdWFsIHJpZGVycy4qKg0KDQpGb3IgZG9ja2VkIGJpa2VzLCB0cmlwIHJldmVudWVzIGZvciBjYXN1YWwgcmlkZXJzIHRlbmQgdG8gcGVhayBpbiBKdW5lLiBUcmlwIHJldmVudWUgZm9yIGNhc3VhbCByaWRlcnMgYXJlIHNlY29uZCBtb3N0IHByb2ZpdGFibGUgY29tcGFyZWQgdG8gb3RoZXIgYmlrZXMgKGFmdGVyIGVsZWN0cmljIGJpa2VzKSBhc3N1bWluZyBhICQwLjM5IGNoYXJnZSBwZXIgbWludXRlLg0KDQohWyoqVHJpcCByZXZlbnVlIG9mIGVsZWN0cmljIGJpa2UgZm9yIG1lbWJlcnMqKl0oY2FzdWFsX2dyYXBoaWNzL3RyaXByZXZlbnVlZG9ja2VkYmlrZXNfY2FzdWFsLmpwZykNCg0KDQojIyBTb2x1dGlvbnMgdG8gYnVzaW5lc3MgdGFzaw0KDQojIyMjICoqUTEuIFdobyBzaG91bGQgd2UgdGFyZ2V0IGZvciBtZW1iZXJzaGlwIG1hcmtldGluZz8qKg0KDQojIyMjIENsYXNzaWMgYmlrZXMNCg0KRm9yIGZyZXF1ZW50IGNhc3VhbCByaWRlcnMgb2YgY2xhc3NpYyBiaWtlcywgd2UgbmVlZCB0byBsb29rIGF0IGhvdyBtdWNoIHRoZXkgd2lsbCBzcGVuZCBpZiB0aGV5IHN3aXRjaCBmcm9tIGNhc3VhbCByaWRpbmcgcGxhbnMgdG8gbWVtYmVyc2hpcCB0byBkZXRlcm1pbmUgd2hldGhlciBtZW1iZXJzaGlwIHN1YnNjcmlwdGlvbiB5aWVsZHMgaGlnaGVyIHByb2ZpdHMuIA0KDQpXZSBhc3N1bWUgdGhhdCBjYXN1YWwgcmlkZXJzIHdpbGwgYWx3YXlzIGdvIGZvciB0aGUgY2hlYXBlc3Qgb3B0aW9ucyBhdmFpbGFibGUgdG8gdGhlbSB3aXRob3V0IG1lbWJlcnNoaXAuIExldCB1cyBleGFtaW5lIHNvbWUgc2NlbmFyaW9zLg0KDQpGb3IgZXZlcnkgbWVtYmVyIHdobyByaWRlcyBubyBtb3JlIHRoYW4gNDUgbWludXRlcyBwZXIgcmlkZSwgYW5udWFsIHJldmVudWUgZnJvbSB0aGlzIG1lbWJlciBpcyBvbmx5IHRoZSBhbm51YWwgbWVtYmVyc2hpcCBmZWUgb2YgMTIwIGRvbGxhcnMuIEJ1dCBmb3IgY2FzdWFsIHJpZGVycyB3aG8gcmlkZXMgbm8gbW9yZSB0aGFuIDQ1IG1pbnV0ZXMgcGVyIHJpZGUsIGFubnVhbCByZXZlbnVlIHBlciByaWRlciBpcyBhdCBsZWFzdCAxMjMgZG9sbGFycyBpZiB0aGUgbnVtYmVyIG9mIHJpZGVzIGVhY2ggeWVhciBpcyBhYm92ZSAxNC4gVGhlIGNhbGN1bGF0aW9uIG9mIGFubnVhbCByZXZlbnVlcyBhcmUgYXMgZm9sbG93czoNCg0KKiBBbm51YWwgcmV2ZW51ZSAoY2FzdWFsIHJpZGVyKSA9ICg0NSAobWlucykgeCAwLjE2ICgvbWluKSArIDEgKHVubG9jayBjb3N0KSkgeCAxNSAocmlkZXMveWVhcikgPSAkMTIzDQoNCiogQW5udWFsIHJldmVudWUgKG1lbWJlcikgPSAxMCAoL210aCkgeCAxMiAobXRocykgPSAkMTIwDQoNCkZvciBldmVyeSBtZW1iZXIgd2hvIHJpZGVzIGZvciAzIGhvdXJzIHBlciByaWRlLCBhbm51YWwgcmV2ZW51ZSBmcm9tIGVhY2ggbWVtYmVyIGlzIGFyb3VuZCA4LDAwMCBkb2xsYXJzIHNpbmNlIHJpZGVzIGFib3ZlIDQ1IG1pbnV0ZXMgYXJlIGNoYXJnZWQgYXQgJDAuMTYgcGVyIG1pbnV0ZS4gQnV0IGZvciBjYXN1YWwgcmlkZXJzIHdobyByaWRlcyBubyBtb3JlIHRoYW4gMyBob3VycyBwZXIgcmlkZSwgYW5udWFsIHJldmVudWUgcGVyIHJpZGVyIGlzIDUsNDc1IGRvbGxhcnMgYXMgdGhleSB3aWxsIGNob29zZSB0aGUgZGF5IHBsYW4gb2YgMTUgZG9sbGFycyBlYWNoIGRheSBhcyB0aGUgY2hlYXBlciBvcHRpb24uIFRoZSBjYWxjdWxhdGlvbiBvZiBhbm51YWwgcmV2ZW51ZXMgYXJlIGFzIGZvbGxvd3M6DQoNCiogQW5udWFsIHJldmVudWUgKGNhc3VhbCByaWRlcikgPSAzNjUgKGRheXMpIHggMTUgKC9kYXkpID0gJDUsNDc1DQoNCiogQW5udWFsIHJldmVudWUgKG1lbWJlcikgPSAoKDE4MC00NSkgKG1pbnMpIHggMC4xNiAoL21pbikgeCAzNjUgKGRheXMpICsgMTIwIChtZW1iZXJzaGlwIGZlZSkgPSAkOCwwMDQNCg0KRm9yIGV2ZXJ5IG1lbWJlciBhbmQgcmlkZXIgd2hvIHJpZGVzIG1vcmUgdGhhbiAzIGhvdXJzIHBlciByaWRlLCB0aGUgY29zdCBwZXIgcmlkZSBhZnRlciAzIGhvdXJzIGlzIHRoZSBzYW1lLCBzbyB3aGljaCBwbGFuIGlzIG1vcmUgcHJvZml0YWJsZSBkZXBlbmRzIG9uIHRoZSByZXZlbnVlIGZvciB0aGUgZmlyc3QgMyBob3Vycy4gVGh1cyBpdCBpcyBzaW1pbGFyIHRvIHRoZSBzY2VuYXJpbyBhYm92ZS4gVGhlIGNhbGN1bGF0aW9uIG9mIGFubnVhbCByZXZlbnVlcyBhcmUgYXMgZm9sbG93czoNCg0KKiBBbm51YWwgcmV2ZW51ZSAoY2FzdWFsIHJpZGVyKSA9IDM2NSAoZGF5cykgeCAxNSAoL2RheSkgPSAkNSw0NzUNCg0KKiBBbm51YWwgcmV2ZW51ZSAobWVtYmVyKSA9ICgoMTgwLTQ1KSAobWlucykgeCAwLjE2ICgvbWluKSB4IDM2NSAoZGF5cykgKyAxMjAgKG1lbWJlcnNoaXAgZmVlKSA9ICQ4LDAwNA0KDQpUaHVzLCBJIHByb3Bvc2UgdGhlIGZvbGxvd2luZyByZWNvbW1lbmRhdGlvbnMgdG8gbWF4aW1pemUgcmV2ZW51ZToNCg0KKiAqKkZvciBjYXN1YWwgcmlkZXJzIHdobyByaWRlIG5vIG1vcmUgdGhhbiA0NSBtaW51dGVzIHBlciByaWRlLCBvbmx5IHByb21vdGUgbWVtYmVyc2hpcCB0byB0aGVtIGlmIHRoZXkgcmlkZSBmb3IgbGVzcyB0aGFuIDE1IHJpZGVzIGVhY2ggeWVhciBvbiBjbGFzc2ljIGJpa2VzLioqDQoNCiogKipGb3IgY2FzdWFsIHJpZGVyIHdobyByaWRlIG1vcmUgdGhhbiA0NSBtaW51dGVzIHBlciByaWRlLCBhbHdheXMgcHJvbW90ZSBtZW1iZXJzaGlwIHRvIHRoZW0uIE1lbWJlcnNoaXAgd2lsbCBhbHdheXMgYnJpbmcgaW4gbW9yZSByZXZlbnVlIHJlZ2FyZGxlc3Mgb2YgdGhlIG51bWJlciBvZiByaWRlcyBlYWNoIHllYXIuKioNCg0KIyMjIyBFbGVjdHJpYyBiaWtlcyBhbmQgZG9ja2VkIGJpa2VzDQoNCkZvciBmcmVxdWVudCBjYXN1YWwgcmlkZXJzIG9mIGVsZWN0cmljIGJpa2VzLCB3ZSBuZWVkIHRvIGxvb2sgYXQgaG93IG11Y2ggdGhleSB3aWxsIHNwZW5kIGlmIHRoZXkgc3dpdGNoIGZyb20gY2FzdWFsIHJpZGluZyBwbGFucyB0byBtZW1iZXJzaGlwIHRvIGRldGVybWluZSB3aGV0aGVyIG1lbWJlcnNoaXAgc3Vic2NyaXB0aW9uIHlpZWxkcyBoaWdoZXIgcHJvZml0cy4gTGV0IHVzIGV4YW1pbmUgc29tZSBzY2VuYXJpb3MuDQoNCkZvciBldmVyeSBtZW1iZXIgd2hvIHJpZGVzIDEgbWludXRlIHBlciByaWRlIGFuZCBvbmx5IG9uY2UgcGVyIGRheSwgYW5udWFsIHJldmVudWUgZnJvbSB0aGlzIG1lbWJlciBpcyAxNzggZG9sbGFycyBnaXZlbiB0aGUgJDAuMTYgcGVyIG1pbiBjaGFyZ2UuIEJ1dCBmb3IgY2FzdWFsIHJpZGVycyB3aG8gcmlkZSB0aGUgc2FtZSBmcmVxdWVuY3ksIGFubnVhbCByZXZlbnVlIHBlciByaWRlciBpcyBhdCBsZWFzdCA1MDcgZG9sbGFycy4gVGhlIGNhbGN1bGF0aW9uIG9mIGFubnVhbCByZXZlbnVlcyBhcmUgYXMgZm9sbG93czoNCg0KKiBBbm51YWwgcmV2ZW51ZSAoY2FzdWFsIHJpZGVyKSA9ICgwLjM5ICgvbWluKSB4IDEgKG1pbikgKyAxICh1bmxvY2sgY29zdCkpIHggMzY1IChkYXlzKSA9ICQ1MDcgDQoNCiogQW5udWFsIHJldmVudWUgKG1lbWJlcikgPSAoMC4xNiAoL21pbikgeCAxIChtaW4pIHggMzY1IChkYXlzKSkgKyAxMjAgKG1lbWJlcnNoaXAgZmVlKSA9ICQxNzgNCg0KTWVtYmVyc2hpcCBvbmx5IGJlY29tZXMgbW9yZSBwcm9maXRhYmxlIHVuZGVyIHRoaXMgcmV2ZW51ZSBjYWxjdWxhdGlvbjoNCg0KKiBBbm51YWwgcmV2ZW51ZSAobWVtYmVyKSA9ICgwLjM1ICgvbWluKSB4IDEgKG1pbikgeCAzNjUgKGRheXMpKSArIDM4MCAobWVtYmVyc2hpcCBmZWUpID0gJDUwOA0KDQoNClNpbWlsYXJseSBmb3Igc2Nvb3RlcnMsIHJldmVudWUgZnJvbSBjYXN1YWwgcmlkZXJzIGFyZSBoaWdoZXIuDQoNClRoZSBjYWxjdWxhdGlvbiBvZiBhbm51YWwgcmV2ZW51ZXMgYXJlIGFzIGZvbGxvd3M6DQoNCiogQW5udWFsIHJldmVudWUgKGNhc3VhbCByaWRlcikgPSAoMC4zOSAoL21pbikgeCAxIChtaW4pICsgMSAodW5sb2NrIGNvc3QpKSB4IDM2NSAoZGF5cykgPSAkNTA3IA0KDQoqIEFubnVhbCByZXZlbnVlIChtZW1iZXIpID0gKDAuMjUgKC9taW4pIHggMSAobWluKSB4IDM2NSAoZGF5cykpICsgMTIwIChtZW1iZXJzaGlwIGZlZSkgPSAkMjExDQoNCk1lbWJlcnNoaXAgb25seSBiZWNvbWVzIG1vcmUgcHJvZml0YWJsZSB1bmRlciB0aGlzIHJldmVudWUgY2FsY3VsYXRpb246DQoNCiogQW5udWFsIHJldmVudWUgKG1lbWJlcikgPSAoMC4zNSAoL21pbikgeDEgKG1pbikgeCAzNjUgKGRheXMpKSArIDM4MCAobWVtYmVyc2hpcCBmZWUpID0gJDUwOA0KDQpUaHVzLCBJIHByb3Bvc2UgdGhlIGZvbGxvd2luZyByZWNvbW1lbmRhdGlvbnMgdG8gbWF4aW1pc2UgcmV2ZW51ZToNCg0KKiAqKlJhaXNlIG1lbWJlcnNoaXAgZmVlcyB0byBtaW5pbXVtIDM4MCBkb2xsYXJzIHBlciB5ZWFyIG9yIDMyIGRvbGxhcnMgcGVyIG1vbnRoIGFuZCBjb3N0IHBlciBtaW51dGUgdG8gJDAuMzUgZm9yIGFsbCBuZXcgbWVtYmVycyBhbmQgcHJvbW90ZSBtZW1iZXJzaGlwIHRvIGNhc3VhbCByaWRlcnMgd2hvIHJpZGUgZWxlY3RyaWMgYmlrZXMgYW5kIHNjb290ZXJzIG9ubHkgb25jZSBwZXIgZGF5IGFuZCAxIG1pbiBwZXIgcmlkZS4qKiANCg0KIyMjIyAqKlEyLiBIb3cgc2hvdWxkIHdlIHRhcmdldCBjYXN1YWwgcmlkZXJzIGJhc2VkIG9uIHRoZWlyIHJpZGluZyBwYXR0ZXJucz8qKg0KDQpTaW5jZSBjYXN1YWwgcmlkZXJzIHByZWZlciB0byB1c2UgYWxsIHR5cGVzIG9mIGJpa2VzIGZvciBsZWlzdXJlIGZyb20gdGhlIHByZWxpbWluYXJ5IGRhdGEgd2UgaGF2ZSwgd2UgY2FuIHByb21vdGUgbWVtYmVyc2hpcCBzdWJzY3JpcHRpb24gYnkgbW9udGhzICgkMzIgcGVyIG1vbnRoKSBkdXJpbmcgcGVhayBwZXJpb2RzIHRvIG1heGltaXNlIHJldmVudWUgZm9yIGVsZWN0cmljIGFuZCBkb2NrZWQgYmlrZXMuIA0KDQpGb3IgY2xhc3NpYyBiaWtlcywgdGhlIG9yaWdpbmFsIG1lbWJlcnNoaXAgZmVlIG9mIDEyMCBkb2xsYXJzIHBlciB5ZWFyIGNhbiBiZSBwcm9tb3RlZCB0byBjYXN1YWwgcmlkZXJzIHdobyBtZWV0IHRoZSBjcml0ZXJpYSBvZiByaWRpbmcgYWJvdmUgNDUgbWludXRlcyBwZXIgcmlkZS4NCg0KIyMjIyAqKlEzLiBXaGF0IG90aGVyIGRhdGEgZG8gd2UgbmVlZCB0byBnYXRoZXIgb3IgY29sbGVjdD8qKg0KDQpUbyBiZXR0ZXIgYWNjZXNzIHRoZSBwcm9maXRhYmlsaXR5IG9mIG91ciBtZW1iZXJzaGlwIHN1YnNjcmlwdGlvbiwgZnVsbCBkYXkgcGFzc2VzIGFuZCBiZXR0ZXIgcHJvbW90ZSBtZW1iZXJzaGlwIGJhc2VkIG9uIHByZWZlcmVuY2VzIG9mIGNhc3VhbCByaWRlcnMsIHdlIG5lZWQgdG8gZ2F0aGVyIG9yIGNvbGxlY3QgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbjoNCg0KMSkgU3VydmV5IG9uIHRoZSBraW5kIG9mIGJpa2VzIGNhc3VhbCByaWRlcnMgcHJlZmVyIHRvIHVzZSBhbmQgdGhlIHB1cnBvc2UgKGZvciB3b3JrIG9yIGxlaXN1cmUpDQoyKSBDdXJyZW50IHRvdGFsIHJldmVudWUgZnJvbSBtZW1iZXJzaGlwIHN1YnNjcmlwdGlvbnMNCjMpIFRvdGFsIHJldmVudWUgZnJvbSBmdWxsIGRheXMgcGFzc2VzDQo0KSBOdW1iZXIgb2YgY2FzdWFsIHJpZGVycyB3aG8gZml0IGludG8gdGhlIHByb2ZpbGUgdG8gcHJvbW90ZSBtZW1iZXJzaGlwIHRvIA0KNSkgSW5mb3JtYXRpb24gb24gd2h5IGRvY2tlZCBiaWtlcyBoYXZlIGhpZ2hlc3QgcmlkZSBkdXJhdGlvbg0KDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQojIEFwcGVuZGl4IA0KDQojIyBTb3VyY2VzIG9mIGRhdGENCg0KMS4gT3JpZ2luYWwgdHJpcCBkYXRhIGJ5IGRpdnZ5YmlrZXM6IGh0dHBzOi8vZGl2dnktdHJpcGRhdGEuczMuYW1hem9uYXdzLmNvbS9pbmRleC5odG1sDQoyLiBQcmljaW5nIGluZm9ybWF0aW9uIGJ5IGRpdnZ5YmlrZXM6IGh0dHBzOi8vZGl2dnliaWtlcy5jb20vDQoNCg==