Turkish Natural Gas Market


Introduction


Turkish natural gas market sees different types of economic activities for almost over 60 years, since Turkish Petroleum Corporation was founded in 1954. It contains a variety of economic categories, such as production, import, export, storage, consumption, and distribution. Since the beginning of 2020, a global pandemic has changed in various and unforeseen ways of economic principles and cast a shadow on actionable insights that were considered straightforward in the previous years. Now, we have to take a much closer look at our data to generate rigid results that can be considered safe-for-action. We tried to keep an open mind about the results we found that could be caused by unknown effects, but also did our best to come up with a simple explanation for each graph you can find below. Two simple things need further clarification before moving forward with the analysis:


Key Takeaways


This report shares some insights about Natural Gas Market in Turkey and you may find our results below.


Preparation and Exploration of the Data


We have obtained both of our datasets from EPIAS’ Transparency Platform. Raw data consists of 1188 observations of 8 variables.

Objectives of this part of the project are as follows:

Click the code button if you want to see the libraries we have used:

library(tidyr)
library(dplyr)
library(stringr)
library(lubridate)
library(ggplot2)
library(readxl)
library(tibble)
options(ggplot2.continuous.colour="viridis")
options(ggplot2.continuous.fill = "viridis")


Pre-processing the Data


For this report, we will include the code for pre-processing phase below. However, the whole pre-processing phase is explained in detail on the pre-processing the data page click here for more details.

Initial Gas Reference Price Data

Previously, gas reference price data included the wrong data format and number separators. We have fixed all the issues considering that we need clean and properly formatted data for our analysis.

Click the code button if you want to see code chunk for pre-processing the GRP data:

gas_prices <- read_excel("GRP.xls")

str(gas_prices)
tibble [1,188 x 2] (S3: tbl_df/tbl/data.frame)
 $ Gaz Gunu: chr [1:1188] "01/09/2018" "02/09/2018" "03/09/2018" "04/09/2018" ...
 $ GRF     : chr [1:1188] "1.650,00" "1.650,00" "1.656,45" "1.644,23" ...
names(gas_prices) <- c('Date',
                       'Gas_Reference_Price')

gas_prices$Gas_Reference_Price <- gsub('.',
                                       '',
                                       gas_prices$Gas_Reference_Price,
                                       fixed = TRUE)
gas_prices$Gas_Reference_Price <- as.numeric(gsub(',',
                                                  '.',
                                                  gas_prices$Gas_Reference_Price,
                                                  fixed = TRUE))
gas_prices$Date <- dmy(gas_prices$Date)

head(gas_prices)

Initial Total Trade Volume Data

As well as gas reference price data, total trade volume also carried out some problems that we need to fix. That as well is done in our pre-processing phase.

Click the code button if you want to see code chunk for pre-processing TTV the data:

trade_volume <- read_excel("TTV.xls")

str(trade_volume)
tibble [1,188 x 2] (S3: tbl_df/tbl/data.frame)
 $ Gaz Günü          : chr [1:1188] "01.09.2018" "02.09.2018" "03.09.2018" "04.09.2018" ...
 $ Toplam Islem Hacmi: chr [1:1188] "378.501,00" "680.025,00" "1.371.846,25" "1.018.608,25" ...
names(trade_volume) <- c('Date',
                         'Total_Trade_Volume')

trade_volume$Total_Trade_Volume <- gsub('.',
                                       '',
                                       trade_volume$Total_Trade_Volume,
                                       fixed = TRUE)
trade_volume$Total_Trade_Volume <- as.numeric(gsub(',',
                                                  '.',
                                                  trade_volume$Total_Trade_Volume,
                                                  fixed = TRUE))
trade_volume$Date <- dmy(trade_volume$Date)

head(trade_volume)
trade_volume$week_num <- strftime((trade_volume$Date), format = "%V")
trade_volume$week_num <- as.numeric(trade_volume$week_num)

trade_volume$year_num <- isoyear(trade_volume$Date)
trade_volume$year_num <- as.numeric(trade_volume$year_num)

trade_volume$month_num <- month(trade_volume$Date)
trade_volume$month_num <- as.numeric(trade_volume$month_num)

trade_volume$day_of_week <- wday(trade_volume$Date, label = TRUE, abbr = TRUE)

seasons <- NULL
for(row in seq_len(nrow(trade_volume["Date"]))){
  if((trade_volume["month_num"][row, 1] == 12) | (trade_volume["month_num"][row, 1] == 1) | (trade_volume["month_num"][row, 1] == 2)){
    seasons <- append(seasons,"Winter")
  }
  else if((trade_volume["month_num"][row, 1] == 3) | (trade_volume["month_num"][row, 1] == 4) | (trade_volume["month_num"][row, 1] == 5)){
    seasons <- append(seasons,"Spring")
  }
  else if((trade_volume["month_num"][row, 1] == 6) | (trade_volume["month_num"][row, 1] == 7) | (trade_volume["month_num"][row, 1] == 8)){
    seasons <- append(seasons,"Summer")
  }
  else {
    seasons <- append(seasons,"Fall")
  }
}
trade_volume["season"] <- seasons

Final Natural Gas RDS

Finally, as seen below we have obtained clean and ready-to-analyze data and saved it as a .rds file. That helped us a lot when we are conducting our exploratory data analysis and final analysis.

Click the code button if you want to see code chunk for pre-processing the data:

df <- merge(x=trade_volume, y=gas_prices, by='Date')
head(df)
saveRDS(df, "natural_gas_data.rds")


Exploratory Data Analysis Report


As before, we will include the code for the exploratory data analysis phase below. However, the whole exploratory data analysis phase is explained in detail on the exploratory data analysis report page click here for more details.

Click the code button if you want to see code chunk for exploratory data analysis:

Overview of Natural Gas Data RDS

Click the code button if you want to see code chunk for overview the RDS file:

df <- readRDS("natural_gas_data.rds")

str(df)
'data.frame':   1188 obs. of  8 variables:
 $ Date               : Date, format: "2018-09-01" "2018-09-02" ...
 $ Total_Trade_Volume : num  378501 680025 1371846 1018608 1317451 ...
 $ week_num           : num  35 35 36 36 36 36 36 36 36 37 ...
 $ year_num           : num  2018 2018 2018 2018 2018 ...
 $ month_num          : num  9 9 9 9 9 9 9 9 9 9 ...
 $ day_of_week        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tue"<..: 7 1 2 3 4 5 6 7 1 2 ...
 $ season             : chr  "Fall" "Fall" "Fall" "Fall" ...
 $ Gas_Reference_Price: num  1650 1650 1656 1644 1656 ...
summary(df)
      Date            Total_Trade_Volume    week_num        year_num   
 Min.   :2018-09-01   Min.   :  176662   Min.   : 1.00   Min.   :2018  
 1st Qu.:2019-06-24   1st Qu.: 3641882   1st Qu.:15.00   1st Qu.:2019  
 Median :2020-04-16   Median : 5310350   Median :29.00   Median :2020  
 Mean   :2020-04-16   Mean   : 6653710   Mean   :27.79   Mean   :2020  
 3rd Qu.:2021-02-07   3rd Qu.: 8139018   3rd Qu.:41.00   3rd Qu.:2021  
 Max.   :2021-12-01   Max.   :40030842   Max.   :53.00   Max.   :2021  
                                                                       
   month_num      day_of_week    season          Gas_Reference_Price
 Min.   : 1.000   Sun:170     Length:1188        Min.   :1205       
 1st Qu.: 4.000   Mon:170     Class :character   1st Qu.:1409       
 Median : 7.000   Tue:170     Mode  :character   Median :1471       
 Mean   : 6.793   Wed:170                        Mean   :1645       
 3rd Qu.:10.000   Thu:169                        3rd Qu.:1571       
 Max.   :12.000   Fri:169                        Max.   :6903       
                  Sat:170                                           

Visualization of Natural Gas Data


Even though this is just a simple overlook, the daily gas reference prices plot shows us how prices were stable in the first years then suddenly started to rise in the last quarter of 2021. The Red line, the average of our whole data, has shifted up so suddenly that left all the prices in the last years under it.

Click the code button if you want to see code chunk for visualization of the data:

ggplot(df,
       aes(x=Date,
           y=Gas_Reference_Price)) +
  geom_bar(stat = "identity",
           aes(color=year_num)) +
  geom_hline(yintercept = mean(df$Gas_Reference_Price),
             size=1,
             color="red") +
  labs(title="Daily Gas Reference Prices",
       x="Years",
       y="Gas Reference Price",
       color='Years')


The daily total trade volume plot clearly shows us it is much more volatile than gas reference price data.

ggplot(df,
       aes(x=Date,
           y=Total_Trade_Volume/1000000)) +
  geom_bar(stat = "identity",
           aes(color=year_num)) +
  geom_hline(yintercept = mean(df$Total_Trade_Volume)/1000000,
             size=1,
             color="red") +
  labs(title="Daily Total Trade Volume in Millions",
       x="Years",
       y="Total Trade Volume(mil)",
       color='Years')


We went ahead and checked their standard deviation, and it is, as expected, enormous in the total trade volume dataset, compared to the standard deviation of the gas reference price.


Here is the standard deviation of Total Trade Volume:

sd(df$Total_Trade_Volume)
[1] 4872730


And here is the standard deviation of Gas Reference Price:

round(sd(df$Gas_Reference_Price), 2)
[1] 616.17


Final Analysis


We started to our final analysis by further processing columns in order to frankly visualize them grouped by certain time periods.

Click the code button if you want to see code chunk for grouping the data:

df <- readRDS("natural_gas_data.rds")
weekly_grouped <- df %>%
  group_by(year_num, week_num) %>%
  summarise(Weekly_Average_GRP = mean(Gas_Reference_Price),
            Weekly_Average_TTV = mean(Total_Trade_Volume)) %>%
  ungroup()
monthly_grouped <- df %>%
  group_by(year_num, month_num) %>%
  summarise(Monthly_Average_GRP = mean(Gas_Reference_Price),
            Monthly_Average_TTV = mean(Total_Trade_Volume)) %>%
  ungroup()
change_weekly <- weekly_grouped %>%
  mutate(change_GRP =  ifelse((year_num - lag(year_num)) > 1,
                              NA,
                              (Weekly_Average_GRP - lag(Weekly_Average_GRP)) / lag(Weekly_Average_GRP) * 100),
  change_TTV =  ifelse((year_num - lag(year_num)) > 1,
                              NA,
                              (Weekly_Average_TTV - lag(Weekly_Average_TTV)) / lag(Weekly_Average_TTV) * 100))
change_monthly <- monthly_grouped %>%
  mutate(change_GRP =  ifelse((year_num - lag(year_num)) > 1,
                              NA,
                              (Monthly_Average_GRP - lag(Monthly_Average_GRP)) / lag(Monthly_Average_GRP) * 100),
  change_TTV =  ifelse((year_num - lag(year_num)) > 1,
                              NA,
                              (Monthly_Average_TTV - lag(Monthly_Average_TTV)) / lag(Monthly_Average_TTV) * 100))


Our first output is the weekly percentage change in our Gas Reference Prices throughout 3 years. When we look at our data on weekly basis, we can see that throughout a year prices mostly change as expected and lines fit each other.

However, starting from the 36th week of 2021 our line chart greatly deviates from the previous years. According to this news article, prices are rising due to the decrease in Europe’s gas production over the last two decades and the increase in demand as economies get back to business and consumers return to pre-pandemic activities.

Not all of this news happened in one week instead they were accumulating over the summer. But there was one thing that happened in only a week. That was a decrease in the country’s political interest rate which ultimately led to a decrease in the Turkish Lira’s valuation. As seen in the graph starting from September 2021 percentage change in prices did not decrease once.

The global market may get to an equilibrium point considering supply and demand in our next analysis we will see if these sudden price changes affected the total trade volume, demand.


Click the code button if you want to see code chunk for creating the plot below:

ggplot(change_weekly, aes(x=week_num, y=change_GRP, group=year_num, color=year_num)) +
  geom_line(size=1) +
  scale_x_continuous(breaks = seq(0, 52, by = 2)) +
  scale_y_continuous(breaks = seq(-100, 100, by = 5)) +
  labs(title = "Weekly Change Percentage of GRP",
       caption="source: TRANSPARENCY PLATFORM - EPIAS",
       color = "Year") +
  geom_hline(yintercept = 0, color = "red") +
  xlab("Week") + ylab("Weekly Change(%)") +
  theme(legend.justification=c("left", "top"),
           legend.position=c(0.01, 0.99),
           legend.background = element_blank(),
           legend.key = element_blank())


As seen below, the demand for natural gas did not increase until the 38th week of 2021. Therefore, we can not conclude that prices have risen due to high trade volume or demand. Total trade volume was fairly in line with the previous year until week 44 which is the beginning of November.


Click the code button if you want to see code chunk for creating the plot below:

ggplot(change_weekly, aes(x=week_num, y=change_TTV, group=year_num, color=year_num)) +
  geom_line(size=1) +
  scale_x_continuous(breaks = seq(0, 52, by = 2)) +
  scale_y_continuous(breaks = seq(-100, 500, by = 25)) +
  labs(title = "Weekly Change Percentage of TTV",
       caption="source: TRANSPARENCY PLATFORM - EPIAS",
       color = "Year") +
  geom_hline(yintercept = 0, color = "red") +
  xlab("Week") + ylab("Weekly Change(%)") +
  theme(legend.justification=c("left", "top"),
           legend.position=c(0.01, 0.99),
           legend.background = element_blank(),
           legend.key = element_blank())


We also analyzed the monthly change in both Gas Reference Price (GRP) and Total Trade Volume (TTV). According to this analysis;

The 3 highest changes in GRP in terms of months are in October, November, and December. On the other hand, the highest change in GRP in terms of years is in 2021.


Click the code button if you want to see code chunk for creating the plot below:

change_monthly$MonthAbb <- month.abb[change_monthly$month_num]
change_monthly$MonthAbb <- factor(change_monthly$MonthAbb, levels = c("Jan","Feb","Mar", "Apr", "May","Jun", "Jul","Aug","Sep", "Oct","Nov","Dec"))
ggplot(change_monthly, aes(x=MonthAbb, y=change_GRP, fill=year_num)) +
  geom_col() +
  coord_flip() +
  scale_y_continuous(breaks = seq(-100, 100, by = 5)) +
  labs(title = "Monthly Change Percentage of GRP",
       caption="source: TRANSPARENCY PLATFORM - EPIAS",
       fill = "Year") +
  geom_hline(yintercept = 0, color = "red") +
  xlab("Month") + ylab("Monthly Change(%)") +
  theme(legend.justification=c(1,0),
           legend.position=c(0.95, 0.35),
           legend.background = element_blank(),
           legend.key = element_blank())


The 3 highest changes in TTV in terms of months are in February, June, and October. On the other hand, the highest change in TTV in terms of years is in 2021.


Click the code button if you want to see code chunk for creating the plot below:

ggplot(change_monthly, aes(x=MonthAbb, y=change_TTV, fill=year_num)) +
  geom_col() +
  coord_flip() +
  scale_y_continuous(breaks = seq(-100, 400, by = 25)) +
  labs(title = "Monthly Change Percentage of TTV",
       caption="source: TRANSPARENCY PLATFORM - EPIAS",
       fill = "Year") +
  geom_hline(yintercept = 0, color = "red") +
  xlab("Month") + ylab("Monthly Change(%)") +
  theme(legend.justification=c(1,0),
           legend.position=c(0.95, 0.3),
           legend.background = element_blank(),
           legend.key = element_blank())


It is no surprise for us to see maximum prices throughout 3 years is in the last quarter of 2021.


daymax_GRP <- df %>%
  arrange(desc(df$Gas_Reference_Price)) %>%
  slice(1:5)
daymax_GRP <- subset(daymax_GRP, select = c('Date', 'Gas_Reference_Price' , 'season', 'Total_Trade_Volume'))
daymax_GRP


The highest total trade volume dates can be explained with really low prices and the season being winter at that time.


daymax_TTV <- df %>%
  arrange(desc(df$Total_Trade_Volume)) %>%
  slice(1:5)
daymax_TTV <- subset(daymax_TTV, select = c('Date', 'Total_Trade_Volume' , 'season', 'Gas_Reference_Price'))
daymax_TTV


As seen in the previous total trade volume, now we have a better understanding of why the volume was that high. The lowest prices were actually achieved in February 2021.


daymin_GRP <- df %>%
  arrange(df$Gas_Reference_Price) %>%
  slice(1:5)
daymin_GRP <- subset(daymin_GRP, select = c('Date', 'Gas_Reference_Price' , 'season', 'Total_Trade_Volume'))
daymin_GRP


Explaining the minimum total trade volume days is harder than the previous parts since the relation between price and season did not really give us any correlation. We expect it to be a result of high demand in the previous weeks or days then incurring a surplus.


daymin_TTV <- df %>%
  arrange(df$Total_Trade_Volume) %>%
  slice(1:5)
daymin_TTV <- subset(daymin_TTV, select = c('Date', 'Total_Trade_Volume' , 'season', 'Gas_Reference_Price'))
daymin_TTV


Average monthly changes draws the picture clearly since all the top values are from 2021. Energy prices rising more than %25 monthly eventually results increase in prices of everything.


maxchangemonthly_GRP <- change_monthly %>%
  arrange(desc(change_monthly$change_GRP)) %>%
  slice(1:5)
maxchangemonthly_GRP <- subset(maxchangemonthly_GRP, select = c('year_num', 'month_num' , 'Monthly_Average_GRP', 'change_GRP'))
maxchangemonthly_GRP


This analysis clearly points us how prices declined following the decrease in demand due to Covid-19 and beginning of the summer.


minchangemonthly_GRP <- change_monthly %>%
  arrange(change_monthly$change_GRP) %>%
  slice(1:1)
minchangemonthly_GRP <- subset(minchangemonthly_GRP, select = c('year_num', 'MonthAbb' , 'Monthly_Average_GRP', 'change_GRP', 'Monthly_Average_TTV', 'change_TTV'))
minchangemonthly_GRP


In the analysis below, we created a moving average of percentage change of weekly prices. In order to clarify the point that the prices start to gain a pattern of rising.


Click the code button if you want to see code chunk for the moving average:

change_weekly_movavg <- na.omit(change_weekly)
change_weekly_movavg <- change_weekly_movavg %>%
  mutate(csum = cumsum(change_GRP),
         row_num = seq.int(nrow(change_weekly_movavg)),
         moving_avg = csum / row_num)


The plot answers our question perfectly, after the 13th week of 2021 weekly average of the gas reference prices tend to change positively. Even though the change in prices sometimes goes negatively, overall the prices were rising since the start of 2021, and finally, at the end of the first quarter, the weekly average became positive.

So we can say prices earned weekly increasing tendency at the end of the first quarter of 2021.


Click the code button if you want to see code chunk for creating the plot below:

ggplot(change_weekly_movavg, aes(x = week_num, y = moving_avg, fill = year_num)) +
  geom_col(position = "identity") +
  scale_x_continuous(breaks = seq(0, 52, by = 2)) +
  scale_y_continuous(breaks = seq(-5, 5, by = 0.5)) +
  labs(title = "Weekly Moving Average of Change of GRP in Percentage",
       caption="source: TRANSPARENCY PLATFORM - EPIAS",
       fill = "Year") +
  geom_hline(yintercept = 0, color = "red") +
  xlab("Week") + ylab("Weekly Change(%)") +
  theme(legend.justification=c(1,0),
           legend.position=c(0.15, 0.15),
           legend.background = element_blank(),
           legend.key = element_blank())


Our next output can be classified as more of a breakdown comparison of our dataset. One of the most important outcome shows itself when we look at the graph below.

It shows a significant raise in average gas prices in the year 2021 when compared to other years. This has been the result of many things, according to different sources, but one reason stands out in every article online, which mentions Gazprom’s suspicious behaviour which can be understood as market manipulation.


Click the code button if you want to see code chunk for creating the plot below:

tv_average_2018 <- mean(as.list(df[df['year_num'] == 2018, ])$Total_Trade_Volume)
tv_average_2019 <- mean(as.list(df[df['year_num'] == 2019, ])$Total_Trade_Volume)
tv_average_2020 <- mean(as.list(df[df['year_num'] == 2020, ])$Total_Trade_Volume)
tv_average_2021 <- mean(as.list(df[df['year_num'] == 2021, ])$Total_Trade_Volume)

gp_average_2018 <- mean(as.list(df[df['year_num'] == 2018, ])$Gas_Reference_Price)
gp_average_2019 <- mean(as.list(df[df['year_num'] == 2019, ])$Gas_Reference_Price)
gp_average_2020 <- mean(as.list(df[df['year_num'] == 2020, ])$Gas_Reference_Price)
gp_average_2021 <- mean(as.list(df[df['year_num'] == 2021, ])$Gas_Reference_Price)

gp_years_average <- df %>%
  group_by(year_num) %>%
  summarise(mean_yearly_gp = mean(Gas_Reference_Price)) %>%
  ggplot(aes(x=year_num, y=mean_yearly_gp, fill=mean_yearly_gp)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = mean(df$Gas_Reference_Price),
             size=1,
             color="red") +
  labs(
    x="Years",
    y="Average Yearly Gas Reference Price",
    title="Average Gas Reference Price over the Years"
  )
gp_years_average


If we look at the total trade volume averages we see a somewhat different picture. Notice that even though the prices were about the same for 2018 till 2020, 2019 had the lowest trade volume values. This is particularly interesting where when we compare it to the high prices of 2020, which we actually expect it to be lower than others.


Click the code button if you want to see code chunk for creating the plot below:

tv_years_average <- df %>%
  group_by(year_num) %>%
  summarise(mean_yearly_tv = mean(Total_Trade_Volume)) %>%
  ggplot(aes(x=year_num, y=mean_yearly_tv, fill=mean_yearly_tv)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = mean(df$Total_Trade_Volume),
             size=1,
             color="red") +
  labs(
    x="Years",
    y="Average Yearly Total Trade Volume",
    title="Average Trade Volume over the Years"
  )

tv_years_average


If we look at the average gas prices in a monthly fashion, we get to see an expected result. According to the article here, whenever the demand for CGN increases, its price will generally increase as well. When we think of cold winter months starting from October, we expect to see high levels of average GRP, and we do. But, an interesting result can also be found from the graph below. December, January and February have actually very low average gas prices. Also, when we compare these prices to the overall average in respective years, we get to see that 2021 has a very high average compared to other years. And also important to note that even though the average gas prices are high in 2021, November average still beats it by a small margin with its ridiculously high average gas prices.


Click the code button if you want to see code chunk for creating the plot below:

df$MonthAbb <- month.abb[df$month_num]
df$MonthAbb <- factor(df$MonthAbb, levels = c("Jan","Feb","Mar", "Apr", "May","Jun", "Jul","Aug","Sep", "Oct","Nov","Dec"))
gp_months_average <- df %>%
  group_by(MonthAbb) %>%
  summarise(mean_monthly_gp = mean(Gas_Reference_Price)) %>%
  ggplot(aes(x=MonthAbb, y=mean_monthly_gp, fill=mean_monthly_gp)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = gp_average_2018,
             size=1,
             color="red") +
    geom_text(aes(0, gp_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, gp_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, gp_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, gp_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Months",
    y="Average Monthly Gas Reference Price",
    title="Average Gas Reference Price over the Months"
  )
gp_months_average


Our prior analysis is further confirmed by this graph also. We can deduce that even though the prices were high in November, because people and industry needed heating, they still had to consume CGN luxuriously. But, we can also note that even though the prices were low in summer compared to winter, June has a considerable amount of CGN usage with February. If we also look at the yearly averages, we get to see that 2021 has actually a very low average trade volume. This can be caused by several different factors, but high gas prices is probably the main cause of this issue. 2019 also has a different behaviour than other years, this can be further analysed to see what caused low trade volume values that year.


Click the code button if you want to see code chunk for creating the plot below:

tv_months_average <- df %>%
  group_by(MonthAbb) %>%
  summarise(mean_monthly_tv = mean(Total_Trade_Volume)) %>%
  ggplot(aes(x=MonthAbb, y=mean_monthly_tv, fill=mean_monthly_tv)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = tv_average_2018,
           size=1,
           color="red") +
  geom_text(aes(0, tv_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, tv_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, tv_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, tv_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Months",
    y="Average Monthly Total Trade Volume",
    title="Average Trade Volume over the Months"
  )
tv_months_average


A further analysis can be applied with the same logic to weekly aggregation as well. We can see clearly the same results with the monthly aggregation. Weeks around the start of winter have the highest average gas reference prices. Moving in the year a sharp drop happens right around December, and continues to build up from there up until October.


Click the code button if you want to see code chunk for creating the plot below:

gp_weeks_average <- df %>%
  group_by(week_num) %>%
  summarise(mean_weekly_gp = mean(Gas_Reference_Price)) %>%
  ggplot(aes(x=week_num, y=mean_weekly_gp, fill=mean_weekly_gp)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = gp_average_2018,
           size=1,
           color="red") +
  geom_text(aes(0, gp_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, gp_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, gp_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, gp_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Weeks",
    y="Average Weekly GRP",
    title="Average GRP over the Weeks"
  )
gp_weeks_average


Same with the monthly trade volume graph, we see the same pattern happening here also. Two spikes are happening around week 7 and 42. By using only our intuition, we can safely say that these two months are when an unexpected cold weather happens most of the time, so this might an underlying cause of why these two specific weeks have a significant higher average than other weeks.


Click the code button if you want to see code chunk for creating the plot below:

tv_weeks_average <- df %>%
  group_by(week_num) %>%
  summarise(mean_weekly_tv = mean(Total_Trade_Volume)) %>%
  ggplot(aes(x=week_num, y=mean_weekly_tv, fill=mean_weekly_tv)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = tv_average_2018,
         size=1,
         color="red") +
  geom_text(aes(0, tv_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, tv_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, tv_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, tv_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Weeks",
    y="Average Weekly Total TV",
    title="Average TV over the Weeks"
  )
tv_weeks_average


Moving on to the weekday analysis, we can clearly see that there is almost no change between any given weekday.


Click the code button if you want to see code chunk for creating the plot below:

gp_days_average <- df %>%
  group_by(day_of_week) %>%
  summarise(mean_daily_gp = mean(Gas_Reference_Price)) %>%
  ggplot(aes(x=day_of_week, y=mean_daily_gp, fill=mean_daily_gp)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = gp_average_2018,
           size=1,
           color="red") +
  geom_text(aes(0, gp_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, gp_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, gp_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, gp_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Days of the Week",
    y="Average Daily GRP",
    title="Average GRP over the Weekdays"
  )
gp_days_average


But if we look at trade volume averages, we can clearly see that mid-weekdays actually have a higher trade volume average than other days. This insight can be further analysed using deep domain knowledge by identifying underlying factors happening on those days. It can also be said that average trade volume values was so high in 2020 that no weekday can come close to it. On the other hand 2019 actually have been surpassed by each weekday.


Click the code button if you want to see code chunk for creating the plot below:

tv_days_average <- df %>%
  group_by(day_of_week) %>%
  summarise(mean_daily_tv = mean(Total_Trade_Volume)) %>%
  ggplot(aes(x=day_of_week, y=mean_daily_tv, fill=mean_daily_tv)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = tv_average_2018,
         size=1,
         color="red") +
  geom_text(aes(0, tv_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, tv_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, tv_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, tv_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Days of the Week",
    y="Average Daily Total TV",
    title="Average TV over the Weekdays"
  )
tv_days_average


As our last analysis, we can take a look at the seasonal averages. Interesting insights can be retrieved from this graph. For example, we expect it to have high average gas prices in winter, but we can clearly see that actually fall season has the highest average value by a large margin. Actually, winter season has the lowest gas reference overall. This can be the effect of the steep decrease of average gas prices going from November to January. There is also a clear difference for the year 2021 when compared to seasonal averages.


Click the code button if you want to see code chunk for creating the plot below:

gp_seasons_average <- df %>%
  group_by(season) %>%
  summarise(mean_seasonal_gp = mean(Gas_Reference_Price)) %>%
  ggplot(aes(x=season, y=mean_seasonal_gp, fill=mean_seasonal_gp)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = gp_average_2018,
           size=1,
           color="red") +
  geom_text(aes(0, gp_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, gp_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, gp_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = gp_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, gp_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Seasons",
    y="Average Seasonal GRP",
    title="Average GRP over the Seasons",
    fill="Average Seasonal GRP"
  )
gp_seasons_average


If we take a look at total trade volume averages over the seasons, we see the same trend happening again.


Click the code button if you want to see code chunk for creating the plot below:

tv_seasons_average <- df %>%
  group_by(season) %>%
  summarise(mean_seasonal_tv = mean(Total_Trade_Volume)) %>%
  ggplot(aes(x=season, y=mean_seasonal_tv, fill=mean_seasonal_tv)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = tv_average_2018,
         size=1,
         color="red") +
  geom_text(aes(0, tv_average_2018, label = "2018 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2019,
         size=1,
         color="green") +
  geom_text(aes(0, tv_average_2019, label = "2019 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2020,
         size=1,
         color="blue") +
  geom_text(aes(0, tv_average_2020, label = "2020 Average", vjust = - 1, hjust=0)) +
  geom_hline(yintercept = tv_average_2021,
         size=1,
         color="yellow") +
  geom_text(aes(0, tv_average_2021, label = "2021 Average", vjust = - 1, hjust=0)) +
  labs(
    x="Seasons",
    y="Average Seasonal TV",
    title="Average TV over the Seasons",
    fill="Average Seasonal TV"
  )
tv_seasons_average


Conclusion



LS0tDQp0aXRsZTogIioqQkRBLTUwMyBEaXZpc2lvbiBCZWxsIEdyb3VwIFByb2plY3QgJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IEZpbmFsIFJlcG9ydCoqIg0KYXV0aG9yOiAiIF9NdXJhdCBDYW4gVGHFn2FyXywgX05lamF0IFXEn3VyIEFrxLFuXywgX1l1bnVzIEVtcmUgRG/En2FuXywgX0VtaXJoYW4gxZ5haGluXyINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgICBodG1sX25vdGVib29rOg0KICAgICAgICB0b2M6IHRydWUNCiAgICAgICAgdG9jX2RlcHRoOiAyDQogICAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KLS0tDQo8YnI+DQo8c3R5bGU+DQojVE9DIHsNCiAgICBjb2xvcjogIzQwNDA0MDsNCiAgICBmb250LXNpemU6IDEzcHg7DQogICAgYm9yZGVyLWNvbG9yOiAjMDAwMDAwOw0KICAgIGZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLCBzeXN0ZW0tdWksIEJsaW5rTWFjU3lzdGVtRm9udCwgIlNlZ29lIFVJIiwgUm9ib3RvLCBVYnVudHU7DQp9DQpoMS50aXRsZSB7DQogICAgY29sb3I6ICM0MDQwNDA7DQogICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCBSb2JvdG8sIFVidW50dTsNCn0NCmg0LmF1dGhvciB7DQogICAgY29sb3I6ICM0MDQwNDA7DQogICAgZm9udC1zaXplOiAxMnB4Ow0KICAgIGZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLCBzeXN0ZW0tdWksIEJsaW5rTWFjU3lzdGVtRm9udCwgIlNlZ29lIFVJIiwgUm9ib3RvLCBVYnVudHU7DQp9DQpoNC5kYXRlIHsNCiAgICBjb2xvcjogIzQwNDA0MDsNCiAgICBmb250LXNpemU6IDEycHg7DQogICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCBSb2JvdG8sIFVidW50dTsNCn0NCmJvZHkgew0KICAgIGNvbG9yOiAjNjk2OTY5Ow0KICAgIGZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLCBzeXN0ZW0tdWksIEJsaW5rTWFjU3lzdGVtRm9udCwgIlNlZ29lIFVJIiwgUm9ib3RvLCBVYnVudHU7DQogICAgYmFja2dyb3VuZC1jb2xvcjogI0Y1RjVGNTsNCiAgICBmb250LXNpemU6IDE2cHg7DQo8L3N0eWxlPg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgPGZvbnQgc2l6ZT0iNjkiIGNvbG9yPSIjNDA0MDQwIj4gKipUdXJraXNoIE5hdHVyYWwgR2FzIE1hcmtldCoqIDwvZm9udD4NCg0KPGJyPg0KDQojICoqSW50cm9kdWN0aW9uKioNCg0KPGJyPg0KDQpUdXJraXNoIG5hdHVyYWwgZ2FzIG1hcmtldCBzZWVzIGRpZmZlcmVudCB0eXBlcyBvZiBlY29ub21pYyBhY3Rpdml0aWVzIGZvciBhbG1vc3Qgb3ZlciA2MCB5ZWFycywgc2luY2UgVHVya2lzaCBQZXRyb2xldW0gQ29ycG9yYXRpb24gd2FzIGZvdW5kZWQgaW4gMTk1NC4gSXQgY29udGFpbnMgYSB2YXJpZXR5IG9mIGVjb25vbWljIGNhdGVnb3JpZXMsIHN1Y2ggYXMgcHJvZHVjdGlvbiwgaW1wb3J0LCBleHBvcnQsIHN0b3JhZ2UsIGNvbnN1bXB0aW9uLCBhbmQgZGlzdHJpYnV0aW9uLg0KU2luY2UgdGhlIGJlZ2lubmluZyBvZiAyMDIwLCBhIGdsb2JhbCBwYW5kZW1pYyBoYXMgY2hhbmdlZCBpbiB2YXJpb3VzIGFuZCB1bmZvcmVzZWVuIHdheXMgb2YgZWNvbm9taWMgcHJpbmNpcGxlcyBhbmQgY2FzdCBhIHNoYWRvdyBvbiBhY3Rpb25hYmxlIGluc2lnaHRzIHRoYXQgd2VyZSBjb25zaWRlcmVkIHN0cmFpZ2h0Zm9yd2FyZCBpbiB0aGUgcHJldmlvdXMgeWVhcnMuIE5vdywgd2UgaGF2ZSB0byB0YWtlIGEgbXVjaCBjbG9zZXIgbG9vayBhdCBvdXIgZGF0YSB0byBnZW5lcmF0ZSByaWdpZCByZXN1bHRzIHRoYXQgY2FuIGJlIGNvbnNpZGVyZWQgc2FmZS1mb3ItYWN0aW9uLiBXZSB0cmllZCB0byBrZWVwIGFuIG9wZW4gbWluZCBhYm91dCB0aGUgcmVzdWx0cyB3ZSBmb3VuZCB0aGF0IGNvdWxkIGJlIGNhdXNlZCBieSB1bmtub3duIGVmZmVjdHMsIGJ1dCBhbHNvIGRpZCBvdXIgYmVzdCB0byBjb21lIHVwIHdpdGggYSBzaW1wbGUgZXhwbGFuYXRpb24gZm9yIGVhY2ggZ3JhcGggeW91IGNhbiBmaW5kIGJlbG93LiBUd28gc2ltcGxlIHRoaW5ncyBuZWVkIGZ1cnRoZXIgY2xhcmlmaWNhdGlvbiBiZWZvcmUgbW92aW5nIGZvcndhcmQgd2l0aCB0aGUgYW5hbHlzaXM6DQoNCi0gR2FzIFJlZmVyZW5jZSBQcmljZSAoVEwvMTAwMCBTbV4zKTogU2hvd3MgdGhlIG92ZXJhbGwgYXZlcmFnZSB2YWx1ZSBvZiBnYXMgcHJpY2VzIGJldHdlZW4gdHdvIDggQU0ncy4NCi0gVG90YWwgVHJhZGUgVm9sdW1lIChUTCk6IFNob3dzIHRoZSB0b3RhbCBhbW91bnQgb2YgcHJpY2Ugb2YgZGFpbHkgYW5kIHdlZWtseSBjb250cmFjdHMuDQoNCjxicj4NCg0KIyAqKktleSBUYWtlYXdheXMqKg0KDQo8YnI+DQoNClRoaXMgcmVwb3J0IHNoYXJlcyBzb21lIGluc2lnaHRzIGFib3V0ICoqTmF0dXJhbCBHYXMgTWFya2V0IGluIFR1cmtleSoqIGFuZCB5b3UgbWF5IGZpbmQgb3VyIHJlc3VsdHMgYmVsb3cuDQoNCiogT3VyIG1haW4gZ29hbCBpcyB0byBleHByZXNzIGN1cnJlbnQgdmFsdWVzIGFuZCBjaGFuZ2VzIGluIGJvdGggZGF0YXNldHMgd2hpY2ggaW5jbHVkZSBHYXMgUmVmZXJlbmNlIFByaWNlcyBhbmQgVG90YWwgVHJhZGUgVm9sdW1lcyBmb3IgdGhlIHllYXJzIDIwMTgsIDIwMTksIDIwMjAsIGFuZCAyMDIxLg0KDQoqIEluIG91ciBwcmV2aW91cyByZWxlYXNlIG5vdGVzLCB3ZSBoYXZlIGV4cGxhaW5lZCBvdXIgZGF0YSBnYXRoZXJpbmcsIGNsZWFuaW5nIGFuZCBwcm9jZXNzaW5nIHByb2NlZHVyZXMgaW4gZGV0YWlsLiBFdmVuIHRob3VnaCwgdGhlIGRhdGFzZXRzIHdlIGhhdmUgdXNlZCB3ZXJlIGZhaXJseSBzdHJ1Y3R1cmVkIHdlIHN0aWxsIG5lZWRlZCBzb21lIGVmZm9ydCBpbnRvIHRoZW0uIEZvciBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGNoZWNrIG91dCBvdXIgKipQcmUtcHJvY2Vzc2luZyBwaGFzZSoqIFtoZXJlXShodHRwczovL3Bqb3VybmFsLmdpdGh1Yi5pby9tZWYwNWctZGl2aXNpb24tYmVsbC9wcmVfcHJvY2Vzc2VkLm5iLmh0bWwpIG9yIHRoZSAqKkV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgcmVwb3J0KiogW2hlcmVdKGh0dHBzOi8vcGpvdXJuYWwuZ2l0aHViLmlvL21lZjA1Zy1kaXZpc2lvbi1iZWxsL2VkYS5uYi5odG1sKS4NCg0KKiBXZSB2aXN1YWxpemVkIHZhbHVlcyBvZiBHYXMgUmVmZXJlbmNlIFByaWNlIGFuZCBUb3RhbCBUcmFkZSBWb2x1bWUgb2YgeWVhcnMgMjAxOCwgMjAxOSwgMjAyMCwgYW5kIDIwMjEgYXMgd2VsbCBhcyB0aGVpciBhdmVyYWdlIGFuZCBjaGFuZ2UgZGVwZW5kaW5nIG9uIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMuDQoNCiogV2UgYWxzbyBhbmFseXplZCBzb21lIGNyaXRpY2FsIHBvaW50cyB0aGF0IGNhcnJ5IGFub21hbGllcyBzdWNoIGFzIGRhaWx5IGFuZCBtb250aGx5IG1heGltdW1zIGFuZCBtaW5pbXVtcy4NCg0KPGJyPg0KDQojICoqUHJlcGFyYXRpb24gYW5kIEV4cGxvcmF0aW9uIG9mIHRoZSBEYXRhKioNCg0KPGJyPg0KDQpXZSBoYXZlIG9idGFpbmVkIGJvdGggb2Ygb3VyIGRhdGFzZXRzIGZyb20gW0VQSUFTJyBUcmFuc3BhcmVuY3kgUGxhdGZvcm1dKGh0dHBzOi8vc2VmZmFmbGlrLmVwaWFzLmNvbS50ci90cmFuc3BhcmVuY3kvKS4gUmF3IGRhdGEgY29uc2lzdHMgb2YgMTE4OCBvYnNlcnZhdGlvbnMgb2YgOCB2YXJpYWJsZXMuDQoNCk9iamVjdGl2ZXMgb2YgdGhpcyBwYXJ0IG9mIHRoZSBwcm9qZWN0IGFyZSBhcyBmb2xsb3dzOg0KDQoqIENsZWFuaW5nIGRpcnR5IGRhdGEgYW5kIGFuYWx5emluZy4NCiogUHJvY2Vzc2luZyBjb2x1bW5zIHRvIGFjaGlldmUgaG9tb2dlbmVvdXMgZGF0YSBmb3JtYXQgYW5kIG51bWJlcnMuDQoqIFZpc3VhbGl6aW5nIHRoZSBkYXRhIGluIG9yZGVyIHRvIGV4cHJlc3Mgb3ZlcnZpZXcgaW5mb3JtYXRpb24uDQoqIENyZWF0aW5nIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMuDQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIHRoZSBsaWJyYXJpZXMgd2UgaGF2ZSB1c2VkOioNCg0KYGBge3IsICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkodGliYmxlKQ0Kb3B0aW9ucyhnZ3Bsb3QyLmNvbnRpbnVvdXMuY29sb3VyPSJ2aXJpZGlzIikNCm9wdGlvbnMoZ2dwbG90Mi5jb250aW51b3VzLmZpbGwgPSAidmlyaWRpcyIpDQpgYGANCg0KPGJyPg0KDQojIyAqKlByZS1wcm9jZXNzaW5nIHRoZSBEYXRhKioNCg0KPGJyPg0KDQpGb3IgdGhpcyByZXBvcnQsIHdlIHdpbGwgaW5jbHVkZSB0aGUgY29kZSBmb3IgcHJlLXByb2Nlc3NpbmcgcGhhc2UgYmVsb3cuIEhvd2V2ZXIsIHRoZSB3aG9sZSBwcmUtcHJvY2Vzc2luZyBwaGFzZSBpcyBleHBsYWluZWQgaW4gZGV0YWlsIG9uIHRoZSBwcmUtcHJvY2Vzc2luZyB0aGUgZGF0YSBwYWdlIGNsaWNrIFtoZXJlXShodHRwczovL3Bqb3VybmFsLmdpdGh1Yi5pby9tZWYwNWctZGl2aXNpb24tYmVsbC9wcmVfcHJvY2Vzc2VkLm5iLmh0bWwpIGZvciBtb3JlIGRldGFpbHMuDQoNCiMjIyBJbml0aWFsIEdhcyBSZWZlcmVuY2UgUHJpY2UgRGF0YQ0KDQpQcmV2aW91c2x5LCBnYXMgcmVmZXJlbmNlIHByaWNlIGRhdGEgaW5jbHVkZWQgdGhlIHdyb25nIGRhdGEgZm9ybWF0IGFuZCBudW1iZXIgc2VwYXJhdG9ycy4gV2UgaGF2ZSBmaXhlZCBhbGwgdGhlIGlzc3VlcyBjb25zaWRlcmluZyB0aGF0IHdlIG5lZWQgY2xlYW4gYW5kIHByb3Blcmx5IGZvcm1hdHRlZCBkYXRhIGZvciBvdXIgYW5hbHlzaXMuDQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIHByZS1wcm9jZXNzaW5nIHRoZSBHUlAgZGF0YToqDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0V9DQpnYXNfcHJpY2VzIDwtIHJlYWRfZXhjZWwoIkdSUC54bHMiKQ0KDQpzdHIoZ2FzX3ByaWNlcykNCg0KbmFtZXMoZ2FzX3ByaWNlcykgPC0gYygnRGF0ZScsDQogICAgICAgICAgICAgICAgICAgICAgICdHYXNfUmVmZXJlbmNlX1ByaWNlJykNCg0KZ2FzX3ByaWNlcyRHYXNfUmVmZXJlbmNlX1ByaWNlIDwtIGdzdWIoJy4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnYXNfcHJpY2VzJEdhc19SZWZlcmVuY2VfUHJpY2UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhlZCA9IFRSVUUpDQpnYXNfcHJpY2VzJEdhc19SZWZlcmVuY2VfUHJpY2UgPC0gYXMubnVtZXJpYyhnc3ViKCcsJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJy4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnYXNfcHJpY2VzJEdhc19SZWZlcmVuY2VfUHJpY2UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVkID0gVFJVRSkpDQpnYXNfcHJpY2VzJERhdGUgPC0gZG15KGdhc19wcmljZXMkRGF0ZSkNCg0KaGVhZChnYXNfcHJpY2VzKQ0KYGBgDQoNCiMjIyBJbml0aWFsIFRvdGFsIFRyYWRlIFZvbHVtZSBEYXRhDQoNCkFzIHdlbGwgYXMgZ2FzIHJlZmVyZW5jZSBwcmljZSBkYXRhLCB0b3RhbCB0cmFkZSB2b2x1bWUgYWxzbyBjYXJyaWVkIG91dCBzb21lIHByb2JsZW1zIHRoYXQgd2UgbmVlZCB0byBmaXguIFRoYXQgYXMgd2VsbCBpcyBkb25lIGluIG91ciBwcmUtcHJvY2Vzc2luZyBwaGFzZS4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgcHJlLXByb2Nlc3NpbmcgVFRWIHRoZSBkYXRhOioNCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRX0NCnRyYWRlX3ZvbHVtZSA8LSByZWFkX2V4Y2VsKCJUVFYueGxzIikNCg0Kc3RyKHRyYWRlX3ZvbHVtZSkNCg0KbmFtZXModHJhZGVfdm9sdW1lKSA8LSBjKCdEYXRlJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAnVG90YWxfVHJhZGVfVm9sdW1lJykNCg0KdHJhZGVfdm9sdW1lJFRvdGFsX1RyYWRlX1ZvbHVtZSA8LSBnc3ViKCcuJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhZGVfdm9sdW1lJFRvdGFsX1RyYWRlX1ZvbHVtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVkID0gVFJVRSkNCnRyYWRlX3ZvbHVtZSRUb3RhbF9UcmFkZV9Wb2x1bWUgPC0gYXMubnVtZXJpYyhnc3ViKCcsJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJy4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFkZV92b2x1bWUkVG90YWxfVHJhZGVfVm9sdW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhlZCA9IFRSVUUpKQ0KdHJhZGVfdm9sdW1lJERhdGUgPC0gZG15KHRyYWRlX3ZvbHVtZSREYXRlKQ0KDQpoZWFkKHRyYWRlX3ZvbHVtZSkNCg0KdHJhZGVfdm9sdW1lJHdlZWtfbnVtIDwtIHN0cmZ0aW1lKCh0cmFkZV92b2x1bWUkRGF0ZSksIGZvcm1hdCA9ICIlViIpDQp0cmFkZV92b2x1bWUkd2Vla19udW0gPC0gYXMubnVtZXJpYyh0cmFkZV92b2x1bWUkd2Vla19udW0pDQoNCnRyYWRlX3ZvbHVtZSR5ZWFyX251bSA8LSBpc295ZWFyKHRyYWRlX3ZvbHVtZSREYXRlKQ0KdHJhZGVfdm9sdW1lJHllYXJfbnVtIDwtIGFzLm51bWVyaWModHJhZGVfdm9sdW1lJHllYXJfbnVtKQ0KDQp0cmFkZV92b2x1bWUkbW9udGhfbnVtIDwtIG1vbnRoKHRyYWRlX3ZvbHVtZSREYXRlKQ0KdHJhZGVfdm9sdW1lJG1vbnRoX251bSA8LSBhcy5udW1lcmljKHRyYWRlX3ZvbHVtZSRtb250aF9udW0pDQoNCnRyYWRlX3ZvbHVtZSRkYXlfb2Zfd2VlayA8LSB3ZGF5KHRyYWRlX3ZvbHVtZSREYXRlLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBUUlVFKQ0KDQpzZWFzb25zIDwtIE5VTEwNCmZvcihyb3cgaW4gc2VxX2xlbihucm93KHRyYWRlX3ZvbHVtZVsiRGF0ZSJdKSkpew0KICBpZigodHJhZGVfdm9sdW1lWyJtb250aF9udW0iXVtyb3csIDFdID09IDEyKSB8ICh0cmFkZV92b2x1bWVbIm1vbnRoX251bSJdW3JvdywgMV0gPT0gMSkgfCAodHJhZGVfdm9sdW1lWyJtb250aF9udW0iXVtyb3csIDFdID09IDIpKXsNCiAgICBzZWFzb25zIDwtIGFwcGVuZChzZWFzb25zLCJXaW50ZXIiKQ0KICB9DQogIGVsc2UgaWYoKHRyYWRlX3ZvbHVtZVsibW9udGhfbnVtIl1bcm93LCAxXSA9PSAzKSB8ICh0cmFkZV92b2x1bWVbIm1vbnRoX251bSJdW3JvdywgMV0gPT0gNCkgfCAodHJhZGVfdm9sdW1lWyJtb250aF9udW0iXVtyb3csIDFdID09IDUpKXsNCiAgICBzZWFzb25zIDwtIGFwcGVuZChzZWFzb25zLCJTcHJpbmciKQ0KICB9DQogIGVsc2UgaWYoKHRyYWRlX3ZvbHVtZVsibW9udGhfbnVtIl1bcm93LCAxXSA9PSA2KSB8ICh0cmFkZV92b2x1bWVbIm1vbnRoX251bSJdW3JvdywgMV0gPT0gNykgfCAodHJhZGVfdm9sdW1lWyJtb250aF9udW0iXVtyb3csIDFdID09IDgpKXsNCiAgICBzZWFzb25zIDwtIGFwcGVuZChzZWFzb25zLCJTdW1tZXIiKQ0KICB9DQogIGVsc2Ugew0KICAgIHNlYXNvbnMgPC0gYXBwZW5kKHNlYXNvbnMsIkZhbGwiKQ0KICB9DQp9DQp0cmFkZV92b2x1bWVbInNlYXNvbiJdIDwtIHNlYXNvbnMNCmBgYA0KDQojIyMgRmluYWwgTmF0dXJhbCBHYXMgUkRTDQoNCkZpbmFsbHksIGFzIHNlZW4gYmVsb3cgd2UgaGF2ZSBvYnRhaW5lZCBjbGVhbiBhbmQgcmVhZHktdG8tYW5hbHl6ZSBkYXRhIGFuZCBzYXZlZCBpdCBhcyBhIC5yZHMgZmlsZS4gVGhhdCBoZWxwZWQgdXMgYSBsb3Qgd2hlbiB3ZSBhcmUgY29uZHVjdGluZyBvdXIgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyBhbmQgZmluYWwgYW5hbHlzaXMuDQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIHByZS1wcm9jZXNzaW5nIHRoZSBkYXRhOioNCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRX0NCmRmIDwtIG1lcmdlKHg9dHJhZGVfdm9sdW1lLCB5PWdhc19wcmljZXMsIGJ5PSdEYXRlJykNCmhlYWQoZGYpDQpzYXZlUkRTKGRmLCAibmF0dXJhbF9nYXNfZGF0YS5yZHMiKQ0KYGBgDQoNCjxicj4NCg0KIyMgKipFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIFJlcG9ydCoqDQoNCjxicj4NCg0KQXMgYmVmb3JlLCB3ZSB3aWxsIGluY2x1ZGUgdGhlIGNvZGUgZm9yIHRoZSBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHBoYXNlIGJlbG93LiBIb3dldmVyLCB0aGUgd2hvbGUgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyBwaGFzZSBpcyBleHBsYWluZWQgaW4gZGV0YWlsIG9uIHRoZSBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHJlcG9ydCBwYWdlIGNsaWNrIFtoZXJlXShodHRwczovL3Bqb3VybmFsLmdpdGh1Yi5pby9tZWYwNWctZGl2aXNpb24tYmVsbC9lZGEubmIuaHRtbCkgZm9yIG1vcmUgZGV0YWlscy4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpczoqDQoNCiMjIyBPdmVydmlldyBvZiBOYXR1cmFsIEdhcyBEYXRhIFJEUw0KDQoqQ2xpY2sgdGhlIGNvZGUgYnV0dG9uIGlmIHlvdSB3YW50IHRvIHNlZSBjb2RlIGNodW5rIGZvciBvdmVydmlldyB0aGUgUkRTIGZpbGU6Kg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFfQ0KZGYgPC0gcmVhZFJEUygibmF0dXJhbF9nYXNfZGF0YS5yZHMiKQ0KDQpzdHIoZGYpDQoNCnN1bW1hcnkoZGYpDQpgYGANCg0KIyMjIFZpc3VhbGl6YXRpb24gb2YgTmF0dXJhbCBHYXMgRGF0YQ0KDQo8YnI+DQoNCkV2ZW4gdGhvdWdoIHRoaXMgaXMganVzdCBhIHNpbXBsZSBvdmVybG9vaywgdGhlIGRhaWx5IGdhcyByZWZlcmVuY2UgcHJpY2VzIHBsb3Qgc2hvd3MgdXMgaG93IHByaWNlcyB3ZXJlIHN0YWJsZSBpbiB0aGUgZmlyc3QgeWVhcnMgdGhlbiBzdWRkZW5seSBzdGFydGVkIHRvIHJpc2UgaW4gdGhlIGxhc3QgcXVhcnRlciBvZiAyMDIxLiBUaGUgUmVkIGxpbmUsIHRoZSBhdmVyYWdlIG9mIG91ciB3aG9sZSBkYXRhLCBoYXMgc2hpZnRlZCB1cCBzbyBzdWRkZW5seSB0aGF0IGxlZnQgYWxsIHRoZSBwcmljZXMgaW4gdGhlIGxhc3QgeWVhcnMgdW5kZXIgaXQuDQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIHZpc3VhbGl6YXRpb24gb2YgdGhlIGRhdGE6Kg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFfQ0KZ2dwbG90KGRmLA0KICAgICAgIGFlcyh4PURhdGUsDQogICAgICAgICAgIHk9R2FzX1JlZmVyZW5jZV9QcmljZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsDQogICAgICAgICAgIGFlcyhjb2xvcj15ZWFyX251bSkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihkZiRHYXNfUmVmZXJlbmNlX1ByaWNlKSwNCiAgICAgICAgICAgICBzaXplPTEsDQogICAgICAgICAgICAgY29sb3I9InJlZCIpICsNCiAgbGFicyh0aXRsZT0iRGFpbHkgR2FzIFJlZmVyZW5jZSBQcmljZXMiLA0KICAgICAgIHg9IlllYXJzIiwNCiAgICAgICB5PSJHYXMgUmVmZXJlbmNlIFByaWNlIiwNCiAgICAgICBjb2xvcj0nWWVhcnMnKQ0KYGBgDQoNCjxicj4NCg0KVGhlIGRhaWx5IHRvdGFsIHRyYWRlIHZvbHVtZSBwbG90IGNsZWFybHkgc2hvd3MgdXMgaXQgaXMgbXVjaCBtb3JlIHZvbGF0aWxlIHRoYW4gZ2FzIHJlZmVyZW5jZSBwcmljZSBkYXRhLg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFfQ0KZ2dwbG90KGRmLA0KICAgICAgIGFlcyh4PURhdGUsDQogICAgICAgICAgIHk9VG90YWxfVHJhZGVfVm9sdW1lLzEwMDAwMDApKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLA0KICAgICAgICAgICBhZXMoY29sb3I9eWVhcl9udW0pKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1lYW4oZGYkVG90YWxfVHJhZGVfVm9sdW1lKS8xMDAwMDAwLA0KICAgICAgICAgICAgIHNpemU9MSwNCiAgICAgICAgICAgICBjb2xvcj0icmVkIikgKw0KICBsYWJzKHRpdGxlPSJEYWlseSBUb3RhbCBUcmFkZSBWb2x1bWUgaW4gTWlsbGlvbnMiLA0KICAgICAgIHg9IlllYXJzIiwNCiAgICAgICB5PSJUb3RhbCBUcmFkZSBWb2x1bWUobWlsKSIsDQogICAgICAgY29sb3I9J1llYXJzJykNCmBgYA0KDQoNCjxicj4NCg0KV2Ugd2VudCBhaGVhZCBhbmQgY2hlY2tlZCB0aGVpciBzdGFuZGFyZCBkZXZpYXRpb24sIGFuZCBpdCBpcywgYXMgZXhwZWN0ZWQsIGVub3Jtb3VzIGluIHRoZSB0b3RhbCB0cmFkZSB2b2x1bWUgZGF0YXNldCwgY29tcGFyZWQgdG8gdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgZ2FzIHJlZmVyZW5jZSBwcmljZS4NCg0KPGJyPg0KDQpIZXJlIGlzIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgVG90YWwgVHJhZGUgVm9sdW1lOg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRX0NCnNkKGRmJFRvdGFsX1RyYWRlX1ZvbHVtZSkNCmBgYA0KPGJyPg0KQW5kIGhlcmUgaXMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBHYXMgUmVmZXJlbmNlIFByaWNlOg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRX0NCnJvdW5kKHNkKGRmJEdhc19SZWZlcmVuY2VfUHJpY2UpLCAyKQ0KYGBgDQoNCjxicj4NCg0KIyAqKkZpbmFsIEFuYWx5c2lzKioNCg0KPGJyPg0KDQpXZSBzdGFydGVkIHRvIG91ciBmaW5hbCBhbmFseXNpcyBieSBmdXJ0aGVyIHByb2Nlc3NpbmcgY29sdW1ucyBpbiBvcmRlciB0byBmcmFua2x5IHZpc3VhbGl6ZSB0aGVtIGdyb3VwZWQgYnkgY2VydGFpbiB0aW1lIHBlcmlvZHMuDQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIGdyb3VwaW5nIHRoZSBkYXRhOioNCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRX0NCmRmIDwtIHJlYWRSRFMoIm5hdHVyYWxfZ2FzX2RhdGEucmRzIikNCndlZWtseV9ncm91cGVkIDwtIGRmICU+JQ0KICBncm91cF9ieSh5ZWFyX251bSwgd2Vla19udW0pICU+JQ0KICBzdW1tYXJpc2UoV2Vla2x5X0F2ZXJhZ2VfR1JQID0gbWVhbihHYXNfUmVmZXJlbmNlX1ByaWNlKSwNCiAgICAgICAgICAgIFdlZWtseV9BdmVyYWdlX1RUViA9IG1lYW4oVG90YWxfVHJhZGVfVm9sdW1lKSkgJT4lDQogIHVuZ3JvdXAoKQ0KbW9udGhseV9ncm91cGVkIDwtIGRmICU+JQ0KICBncm91cF9ieSh5ZWFyX251bSwgbW9udGhfbnVtKSAlPiUNCiAgc3VtbWFyaXNlKE1vbnRobHlfQXZlcmFnZV9HUlAgPSBtZWFuKEdhc19SZWZlcmVuY2VfUHJpY2UpLA0KICAgICAgICAgICAgTW9udGhseV9BdmVyYWdlX1RUViA9IG1lYW4oVG90YWxfVHJhZGVfVm9sdW1lKSkgJT4lDQogIHVuZ3JvdXAoKQ0KY2hhbmdlX3dlZWtseSA8LSB3ZWVrbHlfZ3JvdXBlZCAlPiUNCiAgbXV0YXRlKGNoYW5nZV9HUlAgPSAgaWZlbHNlKCh5ZWFyX251bSAtIGxhZyh5ZWFyX251bSkpID4gMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFdlZWtseV9BdmVyYWdlX0dSUCAtIGxhZyhXZWVrbHlfQXZlcmFnZV9HUlApKSAvIGxhZyhXZWVrbHlfQXZlcmFnZV9HUlApICogMTAwKSwNCiAgY2hhbmdlX1RUViA9ICBpZmVsc2UoKHllYXJfbnVtIC0gbGFnKHllYXJfbnVtKSkgPiAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoV2Vla2x5X0F2ZXJhZ2VfVFRWIC0gbGFnKFdlZWtseV9BdmVyYWdlX1RUVikpIC8gbGFnKFdlZWtseV9BdmVyYWdlX1RUVikgKiAxMDApKQ0KY2hhbmdlX21vbnRobHkgPC0gbW9udGhseV9ncm91cGVkICU+JQ0KICBtdXRhdGUoY2hhbmdlX0dSUCA9ICBpZmVsc2UoKHllYXJfbnVtIC0gbGFnKHllYXJfbnVtKSkgPiAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoTW9udGhseV9BdmVyYWdlX0dSUCAtIGxhZyhNb250aGx5X0F2ZXJhZ2VfR1JQKSkgLyBsYWcoTW9udGhseV9BdmVyYWdlX0dSUCkgKiAxMDApLA0KICBjaGFuZ2VfVFRWID0gIGlmZWxzZSgoeWVhcl9udW0gLSBsYWcoeWVhcl9udW0pKSA+IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChNb250aGx5X0F2ZXJhZ2VfVFRWIC0gbGFnKE1vbnRobHlfQXZlcmFnZV9UVFYpKSAvIGxhZyhNb250aGx5X0F2ZXJhZ2VfVFRWKSAqIDEwMCkpDQpgYGANCg0KPGJyPg0KDQpPdXIgZmlyc3Qgb3V0cHV0IGlzIHRoZSB3ZWVrbHkgcGVyY2VudGFnZSBjaGFuZ2UgaW4gb3VyIEdhcyBSZWZlcmVuY2UgUHJpY2VzIHRocm91Z2hvdXQgMyB5ZWFycy4gV2hlbiB3ZSBsb29rIGF0IG91ciBkYXRhIG9uIHdlZWtseSBiYXNpcywgd2UgY2FuIHNlZSB0aGF0IHRocm91Z2hvdXQgYSB5ZWFyIHByaWNlcyBtb3N0bHkgY2hhbmdlIGFzIGV4cGVjdGVkIGFuZCBsaW5lcyBmaXQgZWFjaCBvdGhlci4NCg0KSG93ZXZlciwgc3RhcnRpbmcgZnJvbSB0aGUgMzZ0aCB3ZWVrIG9mIDIwMjEgb3VyIGxpbmUgY2hhcnQgZ3JlYXRseSBkZXZpYXRlcyBmcm9tIHRoZSBwcmV2aW91cyB5ZWFycy4gQWNjb3JkaW5nIHRvIFt0aGlzIG5ld3MgYXJ0aWNsZV0oaHR0cHM6Ly93d3cuY25iYy5jb20vMjAyMS8xMC8wOC9uYXR1cmFsLWdhcy1wcmljZXMtYXJlLXNreXJvY2tldGluZy1nbG9iYWxseS13aGF0LWl0LW1lYW5zLWZvci10aGUtdXMuaHRtbCksIHByaWNlcyBhcmUgcmlzaW5nIGR1ZSB0byB0aGUgZGVjcmVhc2UgaW4gRXVyb3Bl4oCZcyBnYXMgcHJvZHVjdGlvbiBvdmVyIHRoZSBsYXN0IHR3byBkZWNhZGVzIGFuZCB0aGUgaW5jcmVhc2UgaW4gZGVtYW5kIGFzIGVjb25vbWllcyBnZXQgYmFjayB0byBidXNpbmVzcyBhbmQgY29uc3VtZXJzIHJldHVybiB0byBwcmUtcGFuZGVtaWMgYWN0aXZpdGllcy4NCg0KTm90IGFsbCBvZiB0aGlzIG5ld3MgaGFwcGVuZWQgaW4gb25lIHdlZWsgaW5zdGVhZCB0aGV5IHdlcmUgYWNjdW11bGF0aW5nIG92ZXIgdGhlIHN1bW1lci4gQnV0IHRoZXJlIHdhcyBvbmUgdGhpbmcgdGhhdCBoYXBwZW5lZCBpbiBvbmx5IGEgd2Vlay4gVGhhdCB3YXMgYSBkZWNyZWFzZSBpbiB0aGUgY291bnRyeSdzIHBvbGl0aWNhbCBpbnRlcmVzdCByYXRlIHdoaWNoIHVsdGltYXRlbHkgbGVkIHRvIGEgZGVjcmVhc2UgaW4gdGhlIFR1cmtpc2ggTGlyYSdzIHZhbHVhdGlvbi4gQXMgc2VlbiBpbiB0aGUgZ3JhcGggc3RhcnRpbmcgZnJvbSBTZXB0ZW1iZXIgMjAyMSBwZXJjZW50YWdlIGNoYW5nZSBpbiBwcmljZXMgZGlkIG5vdCBkZWNyZWFzZSBvbmNlLg0KDQpUaGUgZ2xvYmFsIG1hcmtldCBtYXkgZ2V0IHRvIGFuIGVxdWlsaWJyaXVtIHBvaW50IGNvbnNpZGVyaW5nIHN1cHBseSBhbmQgZGVtYW5kIGluIG91ciBuZXh0IGFuYWx5c2lzIHdlIHdpbGwgc2VlIGlmIHRoZXNlIHN1ZGRlbiBwcmljZSBjaGFuZ2VzIGFmZmVjdGVkIHRoZSB0b3RhbCB0cmFkZSB2b2x1bWUsIGRlbWFuZC4NCg0KPGJyPg0KDQoqQ2xpY2sgdGhlIGNvZGUgYnV0dG9uIGlmIHlvdSB3YW50IHRvIHNlZSBjb2RlIGNodW5rIGZvciBjcmVhdGluZyB0aGUgcGxvdCBiZWxvdzoqDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCmdncGxvdChjaGFuZ2Vfd2Vla2x5LCBhZXMoeD13ZWVrX251bSwgeT1jaGFuZ2VfR1JQLCBncm91cD15ZWFyX251bSwgY29sb3I9eWVhcl9udW0pKSArDQogIGdlb21fbGluZShzaXplPTEpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA1MiwgYnkgPSAyKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0xMDAsIDEwMCwgYnkgPSA1KSkgKw0KICBsYWJzKHRpdGxlID0gIldlZWtseSBDaGFuZ2UgUGVyY2VudGFnZSBvZiBHUlAiLA0KICAgICAgIGNhcHRpb249InNvdXJjZTogVFJBTlNQQVJFTkNZIFBMQVRGT1JNIC0gRVBJQVMiLA0KICAgICAgIGNvbG9yID0gIlllYXIiKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gInJlZCIpICsNCiAgeGxhYigiV2VlayIpICsgeWxhYigiV2Vla2x5IENoYW5nZSglKSIpICsNCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb249YygibGVmdCIsICJ0b3AiKSwNCiAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uPWMoMC4wMSwgMC45OSksDQogICAgICAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCjxicj4NCg0KQXMgc2VlbiBiZWxvdywgdGhlIGRlbWFuZCBmb3IgbmF0dXJhbCBnYXMgZGlkIG5vdCBpbmNyZWFzZSB1bnRpbCB0aGUgMzh0aCB3ZWVrIG9mIDIwMjEuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCBjb25jbHVkZSB0aGF0IHByaWNlcyBoYXZlIHJpc2VuIGR1ZSB0byBoaWdoIHRyYWRlIHZvbHVtZSBvciBkZW1hbmQuIFRvdGFsIHRyYWRlIHZvbHVtZSB3YXMgZmFpcmx5IGluIGxpbmUgd2l0aCB0aGUgcHJldmlvdXMgeWVhciB1bnRpbCB3ZWVrIDQ0IHdoaWNoIGlzIHRoZSBiZWdpbm5pbmcgb2YgTm92ZW1iZXIuDQoNCjxicj4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgY3JlYXRpbmcgdGhlIHBsb3QgYmVsb3c6Kg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpnZ3Bsb3QoY2hhbmdlX3dlZWtseSwgYWVzKHg9d2Vla19udW0sIHk9Y2hhbmdlX1RUViwgZ3JvdXA9eWVhcl9udW0sIGNvbG9yPXllYXJfbnVtKSkgKw0KICBnZW9tX2xpbmUoc2l6ZT0xKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNTIsIGJ5ID0gMikpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMTAwLCA1MDAsIGJ5ID0gMjUpKSArDQogIGxhYnModGl0bGUgPSAiV2Vla2x5IENoYW5nZSBQZXJjZW50YWdlIG9mIFRUViIsDQogICAgICAgY2FwdGlvbj0ic291cmNlOiBUUkFOU1BBUkVOQ1kgUExBVEZPUk0gLSBFUElBUyIsDQogICAgICAgY29sb3IgPSAiWWVhciIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAicmVkIikgKw0KICB4bGFiKCJXZWVrIikgKyB5bGFiKCJXZWVrbHkgQ2hhbmdlKCUpIikgKw0KICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbj1jKCJsZWZ0IiwgInRvcCIpLA0KICAgICAgICAgICBsZWdlbmQucG9zaXRpb249YygwLjAxLCAwLjk5KSwNCiAgICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KPGJyPg0KDQpXZSBhbHNvIGFuYWx5emVkIHRoZSBtb250aGx5IGNoYW5nZSBpbiBib3RoIEdhcyBSZWZlcmVuY2UgUHJpY2UgKEdSUCkgYW5kIFRvdGFsIFRyYWRlIFZvbHVtZSAoVFRWKS4gQWNjb3JkaW5nIHRvIHRoaXMgYW5hbHlzaXM7DQoNClRoZSAzIGhpZ2hlc3QgY2hhbmdlcyBpbiBHUlAgaW4gdGVybXMgb2YgbW9udGhzIGFyZSBpbiBPY3RvYmVyLCBOb3ZlbWJlciwgYW5kIERlY2VtYmVyLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlIGhpZ2hlc3QgY2hhbmdlIGluIEdSUCBpbiB0ZXJtcyBvZiB5ZWFycyBpcyBpbiAyMDIxLg0KDQo8YnI+DQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIGNyZWF0aW5nIHRoZSBwbG90IGJlbG93OioNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCmNoYW5nZV9tb250aGx5JE1vbnRoQWJiIDwtIG1vbnRoLmFiYltjaGFuZ2VfbW9udGhseSRtb250aF9udW1dDQpjaGFuZ2VfbW9udGhseSRNb250aEFiYiA8LSBmYWN0b3IoY2hhbmdlX21vbnRobHkkTW9udGhBYmIsIGxldmVscyA9IGMoIkphbiIsIkZlYiIsIk1hciIsICJBcHIiLCAiTWF5IiwiSnVuIiwgIkp1bCIsIkF1ZyIsIlNlcCIsICJPY3QiLCJOb3YiLCJEZWMiKSkNCmdncGxvdChjaGFuZ2VfbW9udGhseSwgYWVzKHg9TW9udGhBYmIsIHk9Y2hhbmdlX0dSUCwgZmlsbD15ZWFyX251bSkpICsNCiAgZ2VvbV9jb2woKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTEwMCwgMTAwLCBieSA9IDUpKSArDQogIGxhYnModGl0bGUgPSAiTW9udGhseSBDaGFuZ2UgUGVyY2VudGFnZSBvZiBHUlAiLA0KICAgICAgIGNhcHRpb249InNvdXJjZTogVFJBTlNQQVJFTkNZIFBMQVRGT1JNIC0gRVBJQVMiLA0KICAgICAgIGZpbGwgPSAiWWVhciIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAicmVkIikgKw0KICB4bGFiKCJNb250aCIpICsgeWxhYigiTW9udGhseSBDaGFuZ2UoJSkiKSArDQogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uPWMoMSwwKSwNCiAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uPWMoMC45NSwgMC4zNSksDQogICAgICAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCjxicj4NCg0KVGhlIDMgaGlnaGVzdCBjaGFuZ2VzIGluIFRUViBpbiB0ZXJtcyBvZiBtb250aHMgYXJlIGluIEZlYnJ1YXJ5LCBKdW5lLCBhbmQgT2N0b2Jlci4gT24gdGhlIG90aGVyIGhhbmQsIHRoZSBoaWdoZXN0IGNoYW5nZSBpbiBUVFYgaW4gdGVybXMgb2YgeWVhcnMgaXMgaW4gMjAyMS4NCg0KPGJyPg0KDQoqQ2xpY2sgdGhlIGNvZGUgYnV0dG9uIGlmIHlvdSB3YW50IHRvIHNlZSBjb2RlIGNodW5rIGZvciBjcmVhdGluZyB0aGUgcGxvdCBiZWxvdzoqDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpnZ3Bsb3QoY2hhbmdlX21vbnRobHksIGFlcyh4PU1vbnRoQWJiLCB5PWNoYW5nZV9UVFYsIGZpbGw9eWVhcl9udW0pKSArDQogIGdlb21fY29sKCkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0xMDAsIDQwMCwgYnkgPSAyNSkpICsNCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IENoYW5nZSBQZXJjZW50YWdlIG9mIFRUViIsDQogICAgICAgY2FwdGlvbj0ic291cmNlOiBUUkFOU1BBUkVOQ1kgUExBVEZPUk0gLSBFUElBUyIsDQogICAgICAgZmlsbCA9ICJZZWFyIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICJyZWQiKSArDQogIHhsYWIoIk1vbnRoIikgKyB5bGFiKCJNb250aGx5IENoYW5nZSglKSIpICsNCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb249YygxLDApLA0KICAgICAgICAgICBsZWdlbmQucG9zaXRpb249YygwLjk1LCAwLjMpLA0KICAgICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKSkNCmBgYA0KDQo8YnI+DQoNCkl0IGlzIG5vIHN1cnByaXNlIGZvciB1cyB0byBzZWUgbWF4aW11bSBwcmljZXMgdGhyb3VnaG91dCAzIHllYXJzIGlzIGluIHRoZSBsYXN0IHF1YXJ0ZXIgb2YgMjAyMS4NCg0KPGJyPg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpkYXltYXhfR1JQIDwtIGRmICU+JQ0KICBhcnJhbmdlKGRlc2MoZGYkR2FzX1JlZmVyZW5jZV9QcmljZSkpICU+JQ0KICBzbGljZSgxOjUpDQpkYXltYXhfR1JQIDwtIHN1YnNldChkYXltYXhfR1JQLCBzZWxlY3QgPSBjKCdEYXRlJywgJ0dhc19SZWZlcmVuY2VfUHJpY2UnICwgJ3NlYXNvbicsICdUb3RhbF9UcmFkZV9Wb2x1bWUnKSkNCmRheW1heF9HUlANCmBgYA0KDQo8YnI+DQoNClRoZSBoaWdoZXN0IHRvdGFsIHRyYWRlIHZvbHVtZSBkYXRlcyBjYW4gYmUgZXhwbGFpbmVkIHdpdGggcmVhbGx5IGxvdyBwcmljZXMgYW5kIHRoZSBzZWFzb24gYmVpbmcgd2ludGVyIGF0IHRoYXQgdGltZS4NCg0KPGJyPg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpkYXltYXhfVFRWIDwtIGRmICU+JQ0KICBhcnJhbmdlKGRlc2MoZGYkVG90YWxfVHJhZGVfVm9sdW1lKSkgJT4lDQogIHNsaWNlKDE6NSkNCmRheW1heF9UVFYgPC0gc3Vic2V0KGRheW1heF9UVFYsIHNlbGVjdCA9IGMoJ0RhdGUnLCAnVG90YWxfVHJhZGVfVm9sdW1lJyAsICdzZWFzb24nLCAnR2FzX1JlZmVyZW5jZV9QcmljZScpKQ0KZGF5bWF4X1RUVg0KYGBgDQoNCjxicj4NCg0KQXMgc2VlbiBpbiB0aGUgcHJldmlvdXMgdG90YWwgdHJhZGUgdm9sdW1lLCBub3cgd2UgaGF2ZSBhIGJldHRlciB1bmRlcnN0YW5kaW5nIG9mIHdoeSB0aGUgdm9sdW1lIHdhcyB0aGF0IGhpZ2guIFRoZSBsb3dlc3QgcHJpY2VzIHdlcmUgYWN0dWFsbHkgYWNoaWV2ZWQgaW4gRmVicnVhcnkgMjAyMS4NCg0KPGJyPg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpkYXltaW5fR1JQIDwtIGRmICU+JQ0KICBhcnJhbmdlKGRmJEdhc19SZWZlcmVuY2VfUHJpY2UpICU+JQ0KICBzbGljZSgxOjUpDQpkYXltaW5fR1JQIDwtIHN1YnNldChkYXltaW5fR1JQLCBzZWxlY3QgPSBjKCdEYXRlJywgJ0dhc19SZWZlcmVuY2VfUHJpY2UnICwgJ3NlYXNvbicsICdUb3RhbF9UcmFkZV9Wb2x1bWUnKSkNCmRheW1pbl9HUlANCmBgYA0KDQo8YnI+DQoNCkV4cGxhaW5pbmcgdGhlIG1pbmltdW0gdG90YWwgdHJhZGUgdm9sdW1lIGRheXMgaXMgaGFyZGVyIHRoYW4gdGhlIHByZXZpb3VzIHBhcnRzIHNpbmNlIHRoZSByZWxhdGlvbiBiZXR3ZWVuIHByaWNlIGFuZCBzZWFzb24gZGlkIG5vdCByZWFsbHkgZ2l2ZSB1cyBhbnkgY29ycmVsYXRpb24uIFdlIGV4cGVjdCBpdCB0byBiZSBhIHJlc3VsdCBvZiBoaWdoIGRlbWFuZCBpbiB0aGUgcHJldmlvdXMgd2Vla3Mgb3IgZGF5cyB0aGVuIGluY3VycmluZyBhIHN1cnBsdXMuDQoNCjxicj4NCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KZGF5bWluX1RUViA8LSBkZiAlPiUNCiAgYXJyYW5nZShkZiRUb3RhbF9UcmFkZV9Wb2x1bWUpICU+JQ0KICBzbGljZSgxOjUpDQpkYXltaW5fVFRWIDwtIHN1YnNldChkYXltaW5fVFRWLCBzZWxlY3QgPSBjKCdEYXRlJywgJ1RvdGFsX1RyYWRlX1ZvbHVtZScgLCAnc2Vhc29uJywgJ0dhc19SZWZlcmVuY2VfUHJpY2UnKSkNCmRheW1pbl9UVFYNCmBgYA0KDQo8YnI+DQoNCkF2ZXJhZ2UgbW9udGhseSBjaGFuZ2VzIGRyYXdzIHRoZSBwaWN0dXJlIGNsZWFybHkgc2luY2UgYWxsIHRoZSB0b3AgdmFsdWVzIGFyZSBmcm9tIDIwMjEuIEVuZXJneSBwcmljZXMgcmlzaW5nIG1vcmUgdGhhbiAlMjUgbW9udGhseSBldmVudHVhbGx5IHJlc3VsdHMgaW5jcmVhc2UgaW4gcHJpY2VzIG9mIGV2ZXJ5dGhpbmcuDQoNCjxicj4NCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KbWF4Y2hhbmdlbW9udGhseV9HUlAgPC0gY2hhbmdlX21vbnRobHkgJT4lDQogIGFycmFuZ2UoZGVzYyhjaGFuZ2VfbW9udGhseSRjaGFuZ2VfR1JQKSkgJT4lDQogIHNsaWNlKDE6NSkNCm1heGNoYW5nZW1vbnRobHlfR1JQIDwtIHN1YnNldChtYXhjaGFuZ2Vtb250aGx5X0dSUCwgc2VsZWN0ID0gYygneWVhcl9udW0nLCAnbW9udGhfbnVtJyAsICdNb250aGx5X0F2ZXJhZ2VfR1JQJywgJ2NoYW5nZV9HUlAnKSkNCm1heGNoYW5nZW1vbnRobHlfR1JQDQpgYGANCg0KPGJyPg0KDQpUaGlzIGFuYWx5c2lzIGNsZWFybHkgcG9pbnRzIHVzIGhvdyBwcmljZXMgZGVjbGluZWQgZm9sbG93aW5nIHRoZSBkZWNyZWFzZSBpbiBkZW1hbmQgZHVlIHRvIENvdmlkLTE5IGFuZCBiZWdpbm5pbmcgb2YgdGhlIHN1bW1lci4NCg0KPGJyPg0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQptaW5jaGFuZ2Vtb250aGx5X0dSUCA8LSBjaGFuZ2VfbW9udGhseSAlPiUNCiAgYXJyYW5nZShjaGFuZ2VfbW9udGhseSRjaGFuZ2VfR1JQKSAlPiUNCiAgc2xpY2UoMToxKQ0KbWluY2hhbmdlbW9udGhseV9HUlAgPC0gc3Vic2V0KG1pbmNoYW5nZW1vbnRobHlfR1JQLCBzZWxlY3QgPSBjKCd5ZWFyX251bScsICdNb250aEFiYicgLCAnTW9udGhseV9BdmVyYWdlX0dSUCcsICdjaGFuZ2VfR1JQJywgJ01vbnRobHlfQXZlcmFnZV9UVFYnLCAnY2hhbmdlX1RUVicpKQ0KbWluY2hhbmdlbW9udGhseV9HUlANCmBgYA0KDQo8YnI+DQoNCkluIHRoZSBhbmFseXNpcyBiZWxvdywgd2UgY3JlYXRlZCBhIG1vdmluZyBhdmVyYWdlIG9mIHBlcmNlbnRhZ2UgY2hhbmdlIG9mIHdlZWtseSBwcmljZXMuIEluIG9yZGVyIHRvIGNsYXJpZnkgdGhlIHBvaW50IHRoYXQgdGhlIHByaWNlcyBzdGFydCB0byBnYWluIGEgcGF0dGVybiBvZiByaXNpbmcuDQoNCjxicj4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgdGhlIG1vdmluZyBhdmVyYWdlOioNCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KY2hhbmdlX3dlZWtseV9tb3ZhdmcgPC0gbmEub21pdChjaGFuZ2Vfd2Vla2x5KQ0KY2hhbmdlX3dlZWtseV9tb3ZhdmcgPC0gY2hhbmdlX3dlZWtseV9tb3ZhdmcgJT4lDQogIG11dGF0ZShjc3VtID0gY3Vtc3VtKGNoYW5nZV9HUlApLA0KICAgICAgICAgcm93X251bSA9IHNlcS5pbnQobnJvdyhjaGFuZ2Vfd2Vla2x5X21vdmF2ZykpLA0KICAgICAgICAgbW92aW5nX2F2ZyA9IGNzdW0gLyByb3dfbnVtKQ0KYGBgDQoNCjxicj4NCg0KVGhlIHBsb3QgYW5zd2VycyBvdXIgcXVlc3Rpb24gcGVyZmVjdGx5LCBhZnRlciB0aGUgMTN0aCB3ZWVrIG9mIDIwMjEgd2Vla2x5IGF2ZXJhZ2Ugb2YgdGhlIGdhcyByZWZlcmVuY2UgcHJpY2VzIHRlbmQgdG8gY2hhbmdlIHBvc2l0aXZlbHkuIEV2ZW4gdGhvdWdoIHRoZSBjaGFuZ2UgaW4gcHJpY2VzIHNvbWV0aW1lcyBnb2VzIG5lZ2F0aXZlbHksIG92ZXJhbGwgdGhlIHByaWNlcyB3ZXJlIHJpc2luZyBzaW5jZSB0aGUgc3RhcnQgb2YgMjAyMSwgYW5kIGZpbmFsbHksIGF0IHRoZSBlbmQgb2YgdGhlIGZpcnN0IHF1YXJ0ZXIsIHRoZSB3ZWVrbHkgYXZlcmFnZSBiZWNhbWUgcG9zaXRpdmUuDQoNClNvIHdlIGNhbiBzYXkgcHJpY2VzIGVhcm5lZCB3ZWVrbHkgaW5jcmVhc2luZyB0ZW5kZW5jeSBhdCB0aGUgZW5kIG9mIHRoZSBmaXJzdCBxdWFydGVyIG9mIDIwMjEuDQoNCjxicj4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgY3JlYXRpbmcgdGhlIHBsb3QgYmVsb3c6Kg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KZ2dwbG90KGNoYW5nZV93ZWVrbHlfbW92YXZnLCBhZXMoeCA9IHdlZWtfbnVtLCB5ID0gbW92aW5nX2F2ZywgZmlsbCA9IHllYXJfbnVtKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA1MiwgYnkgPSAyKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC01LCA1LCBieSA9IDAuNSkpICsNCiAgbGFicyh0aXRsZSA9ICJXZWVrbHkgTW92aW5nIEF2ZXJhZ2Ugb2YgQ2hhbmdlIG9mIEdSUCBpbiBQZXJjZW50YWdlIiwNCiAgICAgICBjYXB0aW9uPSJzb3VyY2U6IFRSQU5TUEFSRU5DWSBQTEFURk9STSAtIEVQSUFTIiwNCiAgICAgICBmaWxsID0gIlllYXIiKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gInJlZCIpICsNCiAgeGxhYigiV2VlayIpICsgeWxhYigiV2Vla2x5IENoYW5nZSglKSIpICsNCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb249YygxLDApLA0KICAgICAgICAgICBsZWdlbmQucG9zaXRpb249YygwLjE1LCAwLjE1KSwNCiAgICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KPGJyPg0KDQpPdXIgbmV4dCBvdXRwdXQgY2FuIGJlIGNsYXNzaWZpZWQgYXMgbW9yZSBvZiBhIGJyZWFrZG93biBjb21wYXJpc29uIG9mIG91ciBkYXRhc2V0LiBPbmUgb2YgdGhlIG1vc3QgaW1wb3J0YW50IG91dGNvbWUgc2hvd3MgaXRzZWxmIHdoZW4gd2UgbG9vayBhdCB0aGUgZ3JhcGggYmVsb3cuDQoNCkl0IHNob3dzIGEgc2lnbmlmaWNhbnQgcmFpc2UgaW4gYXZlcmFnZSBnYXMgcHJpY2VzIGluIHRoZSB5ZWFyIDIwMjEgd2hlbiBjb21wYXJlZCB0byBvdGhlciB5ZWFycy4gVGhpcyBoYXMgYmVlbiB0aGUgcmVzdWx0IG9mIG1hbnkgdGhpbmdzLCBhY2NvcmRpbmcgdG8gZGlmZmVyZW50IHNvdXJjZXMsIGJ1dCBvbmUgcmVhc29uIHN0YW5kcyBvdXQgaW4gZXZlcnkgYXJ0aWNsZSBvbmxpbmUsIHdoaWNoIG1lbnRpb25zIFtHYXpwcm9tJ3Mgc3VzcGljaW91cyBiZWhhdmlvdXIgd2hpY2ggY2FuIGJlIHVuZGVyc3Rvb2QgYXMgbWFya2V0IG1hbmlwdWxhdGlvbl0oaHR0cHM6Ly93d3cucmV1dGVycy5jb20vYnVzaW5lc3MvZW5lcmd5L2dyb3VwLWV1LWxhd21ha2Vycy1zZWVrcy1wcm9iZS1nYXpwcm9tcy1yb2xlLWdhcy1wcmljZS1zdXJnZS0yMDIxLTA5LTE3LykuDQoNCjxicj4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgY3JlYXRpbmcgdGhlIHBsb3QgYmVsb3c6Kg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KDQp0dl9hdmVyYWdlXzIwMTggPC0gbWVhbihhcy5saXN0KGRmW2RmWyd5ZWFyX251bSddID09IDIwMTgsIF0pJFRvdGFsX1RyYWRlX1ZvbHVtZSkNCnR2X2F2ZXJhZ2VfMjAxOSA8LSBtZWFuKGFzLmxpc3QoZGZbZGZbJ3llYXJfbnVtJ10gPT0gMjAxOSwgXSkkVG90YWxfVHJhZGVfVm9sdW1lKQ0KdHZfYXZlcmFnZV8yMDIwIDwtIG1lYW4oYXMubGlzdChkZltkZlsneWVhcl9udW0nXSA9PSAyMDIwLCBdKSRUb3RhbF9UcmFkZV9Wb2x1bWUpDQp0dl9hdmVyYWdlXzIwMjEgPC0gbWVhbihhcy5saXN0KGRmW2RmWyd5ZWFyX251bSddID09IDIwMjEsIF0pJFRvdGFsX1RyYWRlX1ZvbHVtZSkNCg0KZ3BfYXZlcmFnZV8yMDE4IDwtIG1lYW4oYXMubGlzdChkZltkZlsneWVhcl9udW0nXSA9PSAyMDE4LCBdKSRHYXNfUmVmZXJlbmNlX1ByaWNlKQ0KZ3BfYXZlcmFnZV8yMDE5IDwtIG1lYW4oYXMubGlzdChkZltkZlsneWVhcl9udW0nXSA9PSAyMDE5LCBdKSRHYXNfUmVmZXJlbmNlX1ByaWNlKQ0KZ3BfYXZlcmFnZV8yMDIwIDwtIG1lYW4oYXMubGlzdChkZltkZlsneWVhcl9udW0nXSA9PSAyMDIwLCBdKSRHYXNfUmVmZXJlbmNlX1ByaWNlKQ0KZ3BfYXZlcmFnZV8yMDIxIDwtIG1lYW4oYXMubGlzdChkZltkZlsneWVhcl9udW0nXSA9PSAyMDIxLCBdKSRHYXNfUmVmZXJlbmNlX1ByaWNlKQ0KDQpncF95ZWFyc19hdmVyYWdlIDwtIGRmICU+JQ0KICBncm91cF9ieSh5ZWFyX251bSkgJT4lDQogIHN1bW1hcmlzZShtZWFuX3llYXJseV9ncCA9IG1lYW4oR2FzX1JlZmVyZW5jZV9QcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9eWVhcl9udW0sIHk9bWVhbl95ZWFybHlfZ3AsIGZpbGw9bWVhbl95ZWFybHlfZ3ApKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKGRmJEdhc19SZWZlcmVuY2VfUHJpY2UpLA0KICAgICAgICAgICAgIHNpemU9MSwNCiAgICAgICAgICAgICBjb2xvcj0icmVkIikgKw0KICBsYWJzKA0KICAgIHg9IlllYXJzIiwNCiAgICB5PSJBdmVyYWdlIFllYXJseSBHYXMgUmVmZXJlbmNlIFByaWNlIiwNCiAgICB0aXRsZT0iQXZlcmFnZSBHYXMgUmVmZXJlbmNlIFByaWNlIG92ZXIgdGhlIFllYXJzIg0KICApDQpncF95ZWFyc19hdmVyYWdlDQpgYGANCg0KPGJyPg0KDQpJZiB3ZSBsb29rIGF0IHRoZSB0b3RhbCB0cmFkZSB2b2x1bWUgYXZlcmFnZXMgd2Ugc2VlIGEgc29tZXdoYXQgZGlmZmVyZW50IHBpY3R1cmUuIE5vdGljZSB0aGF0IGV2ZW4gdGhvdWdoIHRoZSBwcmljZXMgd2VyZSBhYm91dCB0aGUgc2FtZSBmb3IgMjAxOCB0aWxsIDIwMjAsIDIwMTkgaGFkIHRoZSBsb3dlc3QgdHJhZGUgdm9sdW1lIHZhbHVlcy4gVGhpcyBpcyBwYXJ0aWN1bGFybHkgaW50ZXJlc3Rpbmcgd2hlcmUgd2hlbiB3ZSBjb21wYXJlIGl0IHRvIHRoZSBoaWdoIHByaWNlcyBvZiAyMDIwLCB3aGljaCB3ZSBhY3R1YWxseSBleHBlY3QgaXQgdG8gYmUgbG93ZXIgdGhhbiBvdGhlcnMuDQoNCjxicj4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgY3JlYXRpbmcgdGhlIHBsb3QgYmVsb3c6Kg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KdHZfeWVhcnNfYXZlcmFnZSA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoeWVhcl9udW0pICU+JQ0KICBzdW1tYXJpc2UobWVhbl95ZWFybHlfdHYgPSBtZWFuKFRvdGFsX1RyYWRlX1ZvbHVtZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9eWVhcl9udW0sIHk9bWVhbl95ZWFybHlfdHYsIGZpbGw9bWVhbl95ZWFybHlfdHYpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKGRmJFRvdGFsX1RyYWRlX1ZvbHVtZSksDQogICAgICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgICAgIGNvbG9yPSJyZWQiKSArDQogIGxhYnMoDQogICAgeD0iWWVhcnMiLA0KICAgIHk9IkF2ZXJhZ2UgWWVhcmx5IFRvdGFsIFRyYWRlIFZvbHVtZSIsDQogICAgdGl0bGU9IkF2ZXJhZ2UgVHJhZGUgVm9sdW1lIG92ZXIgdGhlIFllYXJzIg0KICApDQoNCnR2X3llYXJzX2F2ZXJhZ2UNCmBgYA0KDQoNCjxicj4NCg0KSWYgd2UgbG9vayBhdCB0aGUgYXZlcmFnZSBnYXMgcHJpY2VzIGluIGEgbW9udGhseSBmYXNoaW9uLCB3ZSBnZXQgdG8gc2VlIGFuIGV4cGVjdGVkIHJlc3VsdC4gQWNjb3JkaW5nIHRvIHRoZSBhcnRpY2xlIFtoZXJlXShodHRwczovL3d3dy5laWEuZ292L2VuZXJneWV4cGxhaW5lZC9uYXR1cmFsLWdhcy9mYWN0b3JzLWFmZmVjdGluZy1uYXR1cmFsLWdhcy1wcmljZXMucGhwKSwgd2hlbmV2ZXIgdGhlIGRlbWFuZCBmb3IgQ0dOIGluY3JlYXNlcywgaXRzIHByaWNlIHdpbGwgZ2VuZXJhbGx5IGluY3JlYXNlIGFzIHdlbGwuIFdoZW4gd2UgdGhpbmsgb2YgY29sZCB3aW50ZXIgbW9udGhzIHN0YXJ0aW5nIGZyb20gT2N0b2Jlciwgd2UgZXhwZWN0IHRvIHNlZSBoaWdoIGxldmVscyBvZiBhdmVyYWdlIEdSUCwgYW5kIHdlIGRvLiBCdXQsIGFuIGludGVyZXN0aW5nIHJlc3VsdCBjYW4gYWxzbyBiZSBmb3VuZCBmcm9tIHRoZSBncmFwaCBiZWxvdy4gRGVjZW1iZXIsIEphbnVhcnkgYW5kIEZlYnJ1YXJ5IGhhdmUgYWN0dWFsbHkgdmVyeSBsb3cgYXZlcmFnZSBnYXMgcHJpY2VzLiBBbHNvLCB3aGVuIHdlIGNvbXBhcmUgdGhlc2UgcHJpY2VzIHRvIHRoZSBvdmVyYWxsIGF2ZXJhZ2UgaW4gcmVzcGVjdGl2ZSB5ZWFycywgd2UgZ2V0IHRvIHNlZSB0aGF0IDIwMjEgaGFzIGEgdmVyeSBoaWdoIGF2ZXJhZ2UgY29tcGFyZWQgdG8gb3RoZXIgeWVhcnMuIEFuZCBhbHNvIGltcG9ydGFudCB0byBub3RlIHRoYXQgZXZlbiB0aG91Z2ggdGhlIGF2ZXJhZ2UgZ2FzIHByaWNlcyBhcmUgaGlnaCBpbiAyMDIxLCBOb3ZlbWJlciBhdmVyYWdlIHN0aWxsIGJlYXRzIGl0IGJ5IGEgc21hbGwgbWFyZ2luIHdpdGggaXRzIHJpZGljdWxvdXNseSBoaWdoIGF2ZXJhZ2UgZ2FzIHByaWNlcy4NCg0KPGJyPg0KDQoqQ2xpY2sgdGhlIGNvZGUgYnV0dG9uIGlmIHlvdSB3YW50IHRvIHNlZSBjb2RlIGNodW5rIGZvciBjcmVhdGluZyB0aGUgcGxvdCBiZWxvdzoqDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpkZiRNb250aEFiYiA8LSBtb250aC5hYmJbZGYkbW9udGhfbnVtXQ0KZGYkTW9udGhBYmIgPC0gZmFjdG9yKGRmJE1vbnRoQWJiLCBsZXZlbHMgPSBjKCJKYW4iLCJGZWIiLCJNYXIiLCAiQXByIiwgIk1heSIsIkp1biIsICJKdWwiLCJBdWciLCJTZXAiLCAiT2N0IiwiTm92IiwiRGVjIikpDQpncF9tb250aHNfYXZlcmFnZSA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoTW9udGhBYmIpICU+JQ0KICBzdW1tYXJpc2UobWVhbl9tb250aGx5X2dwID0gbWVhbihHYXNfUmVmZXJlbmNlX1ByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeD1Nb250aEFiYiwgeT1tZWFuX21vbnRobHlfZ3AsIGZpbGw9bWVhbl9tb250aGx5X2dwKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZ3BfYXZlcmFnZV8yMDE4LA0KICAgICAgICAgICAgIHNpemU9MSwNCiAgICAgICAgICAgICBjb2xvcj0icmVkIikgKw0KICAgIGdlb21fdGV4dChhZXMoMCwgZ3BfYXZlcmFnZV8yMDE4LCBsYWJlbCA9ICIyMDE4IEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZ3BfYXZlcmFnZV8yMDE5LA0KICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgY29sb3I9ImdyZWVuIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIGdwX2F2ZXJhZ2VfMjAxOSwgbGFiZWwgPSAiMjAxOSBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGdwX2F2ZXJhZ2VfMjAyMCwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJibHVlIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIGdwX2F2ZXJhZ2VfMjAyMCwgbGFiZWwgPSAiMjAyMCBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGdwX2F2ZXJhZ2VfMjAyMSwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJ5ZWxsb3ciKSArDQogIGdlb21fdGV4dChhZXMoMCwgZ3BfYXZlcmFnZV8yMDIxLCBsYWJlbCA9ICIyMDIxIEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgbGFicygNCiAgICB4PSJNb250aHMiLA0KICAgIHk9IkF2ZXJhZ2UgTW9udGhseSBHYXMgUmVmZXJlbmNlIFByaWNlIiwNCiAgICB0aXRsZT0iQXZlcmFnZSBHYXMgUmVmZXJlbmNlIFByaWNlIG92ZXIgdGhlIE1vbnRocyINCiAgKQ0KZ3BfbW9udGhzX2F2ZXJhZ2UNCmBgYA0KDQo8YnI+DQoNCk91ciBwcmlvciBhbmFseXNpcyBpcyBmdXJ0aGVyIGNvbmZpcm1lZCBieSB0aGlzIGdyYXBoIGFsc28uIFdlIGNhbiBkZWR1Y2UgdGhhdCBldmVuIHRob3VnaCB0aGUgcHJpY2VzIHdlcmUgaGlnaCBpbiBOb3ZlbWJlciwgYmVjYXVzZSBwZW9wbGUgYW5kIGluZHVzdHJ5IG5lZWRlZCBoZWF0aW5nLCB0aGV5IHN0aWxsIGhhZCB0byBjb25zdW1lIENHTiBsdXh1cmlvdXNseS4gQnV0LCB3ZSBjYW4gYWxzbyBub3RlIHRoYXQgZXZlbiB0aG91Z2ggdGhlIHByaWNlcyB3ZXJlIGxvdyBpbiBzdW1tZXIgY29tcGFyZWQgdG8gd2ludGVyLCBKdW5lIGhhcyBhIGNvbnNpZGVyYWJsZSBhbW91bnQgb2YgQ0dOIHVzYWdlIHdpdGggRmVicnVhcnkuIElmIHdlIGFsc28gbG9vayBhdCB0aGUgeWVhcmx5IGF2ZXJhZ2VzLCB3ZSBnZXQgdG8gc2VlIHRoYXQgMjAyMSBoYXMgYWN0dWFsbHkgYSB2ZXJ5IGxvdyBhdmVyYWdlIHRyYWRlIHZvbHVtZS4gVGhpcyBjYW4gYmUgY2F1c2VkIGJ5IHNldmVyYWwgZGlmZmVyZW50IGZhY3RvcnMsIGJ1dCBoaWdoIGdhcyBwcmljZXMgaXMgcHJvYmFibHkgdGhlIG1haW4gY2F1c2Ugb2YgdGhpcyBpc3N1ZS4gMjAxOSBhbHNvIGhhcyBhIGRpZmZlcmVudCBiZWhhdmlvdXIgdGhhbiBvdGhlciB5ZWFycywgdGhpcyBjYW4gYmUgZnVydGhlciBhbmFseXNlZCB0byBzZWUgd2hhdCBjYXVzZWQgbG93IHRyYWRlIHZvbHVtZSB2YWx1ZXMgdGhhdCB5ZWFyLg0KDQo8YnI+DQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIGNyZWF0aW5nIHRoZSBwbG90IGJlbG93OioNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KdHZfbW9udGhzX2F2ZXJhZ2UgPC0gZGYgJT4lDQogIGdyb3VwX2J5KE1vbnRoQWJiKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fbW9udGhseV90diA9IG1lYW4oVG90YWxfVHJhZGVfVm9sdW1lKSkgJT4lDQogIGdncGxvdChhZXMoeD1Nb250aEFiYiwgeT1tZWFuX21vbnRobHlfdHYsIGZpbGw9bWVhbl9tb250aGx5X3R2KSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gdHZfYXZlcmFnZV8yMDE4LA0KICAgICAgICAgICBzaXplPTEsDQogICAgICAgICAgIGNvbG9yPSJyZWQiKSArDQogIGdlb21fdGV4dChhZXMoMCwgdHZfYXZlcmFnZV8yMDE4LCBsYWJlbCA9ICIyMDE4IEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gdHZfYXZlcmFnZV8yMDE5LA0KICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgY29sb3I9ImdyZWVuIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAxOSwgbGFiZWwgPSAiMjAxOSBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHR2X2F2ZXJhZ2VfMjAyMCwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJibHVlIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAyMCwgbGFiZWwgPSAiMjAyMCBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHR2X2F2ZXJhZ2VfMjAyMSwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJ5ZWxsb3ciKSArDQogIGdlb21fdGV4dChhZXMoMCwgdHZfYXZlcmFnZV8yMDIxLCBsYWJlbCA9ICIyMDIxIEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgbGFicygNCiAgICB4PSJNb250aHMiLA0KICAgIHk9IkF2ZXJhZ2UgTW9udGhseSBUb3RhbCBUcmFkZSBWb2x1bWUiLA0KICAgIHRpdGxlPSJBdmVyYWdlIFRyYWRlIFZvbHVtZSBvdmVyIHRoZSBNb250aHMiDQogICkNCnR2X21vbnRoc19hdmVyYWdlDQpgYGANCg0KPGJyPg0KDQpBIGZ1cnRoZXIgYW5hbHlzaXMgY2FuIGJlIGFwcGxpZWQgd2l0aCB0aGUgc2FtZSBsb2dpYyB0byB3ZWVrbHkgYWdncmVnYXRpb24gYXMgd2VsbC4gV2UgY2FuIHNlZSBjbGVhcmx5IHRoZSBzYW1lIHJlc3VsdHMgd2l0aCB0aGUgbW9udGhseSBhZ2dyZWdhdGlvbi4gV2Vla3MgYXJvdW5kIHRoZSBzdGFydCBvZiB3aW50ZXIgaGF2ZSB0aGUgaGlnaGVzdCBhdmVyYWdlIGdhcyByZWZlcmVuY2UgcHJpY2VzLiBNb3ZpbmcgaW4gdGhlIHllYXIgYSBzaGFycCBkcm9wIGhhcHBlbnMgcmlnaHQgYXJvdW5kIERlY2VtYmVyLCBhbmQgY29udGludWVzIHRvIGJ1aWxkIHVwIGZyb20gdGhlcmUgdXAgdW50aWwgT2N0b2Jlci4NCg0KPGJyPg0KDQoqQ2xpY2sgdGhlIGNvZGUgYnV0dG9uIGlmIHlvdSB3YW50IHRvIHNlZSBjb2RlIGNodW5rIGZvciBjcmVhdGluZyB0aGUgcGxvdCBiZWxvdzoqDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQoNCmdwX3dlZWtzX2F2ZXJhZ2UgPC0gZGYgJT4lDQogIGdyb3VwX2J5KHdlZWtfbnVtKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fd2Vla2x5X2dwID0gbWVhbihHYXNfUmVmZXJlbmNlX1ByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeD13ZWVrX251bSwgeT1tZWFuX3dlZWtseV9ncCwgZmlsbD1tZWFuX3dlZWtseV9ncCkpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGdwX2F2ZXJhZ2VfMjAxOCwNCiAgICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgICBjb2xvcj0icmVkIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIGdwX2F2ZXJhZ2VfMjAxOCwgbGFiZWwgPSAiMjAxOCBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGdwX2F2ZXJhZ2VfMjAxOSwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJncmVlbiIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCBncF9hdmVyYWdlXzIwMTksIGxhYmVsID0gIjIwMTkgQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBncF9hdmVyYWdlXzIwMjAsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0iYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCBncF9hdmVyYWdlXzIwMjAsIGxhYmVsID0gIjIwMjAgQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBncF9hdmVyYWdlXzIwMjEsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0ieWVsbG93IikgKw0KICBnZW9tX3RleHQoYWVzKDAsIGdwX2F2ZXJhZ2VfMjAyMSwgbGFiZWwgPSAiMjAyMSBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGxhYnMoDQogICAgeD0iV2Vla3MiLA0KICAgIHk9IkF2ZXJhZ2UgV2Vla2x5IEdSUCIsDQogICAgdGl0bGU9IkF2ZXJhZ2UgR1JQIG92ZXIgdGhlIFdlZWtzIg0KICApDQpncF93ZWVrc19hdmVyYWdlDQpgYGANCg0KPGJyPg0KDQpTYW1lIHdpdGggdGhlIG1vbnRobHkgdHJhZGUgdm9sdW1lIGdyYXBoLCB3ZSBzZWUgdGhlIHNhbWUgcGF0dGVybiBoYXBwZW5pbmcgaGVyZSBhbHNvLiBUd28gc3Bpa2VzIGFyZSBoYXBwZW5pbmcgYXJvdW5kIHdlZWsgNyBhbmQgNDIuIEJ5IHVzaW5nIG9ubHkgb3VyIGludHVpdGlvbiwgd2UgY2FuIHNhZmVseSBzYXkgdGhhdCB0aGVzZSB0d28gbW9udGhzIGFyZSB3aGVuIGFuIHVuZXhwZWN0ZWQgY29sZCB3ZWF0aGVyIGhhcHBlbnMgbW9zdCBvZiB0aGUgdGltZSwgc28gdGhpcyBtaWdodCBhbiB1bmRlcmx5aW5nIGNhdXNlIG9mIHdoeSB0aGVzZSB0d28gc3BlY2lmaWMgd2Vla3MgaGF2ZSBhIHNpZ25pZmljYW50IGhpZ2hlciBhdmVyYWdlIHRoYW4gb3RoZXIgd2Vla3MuDQoNCjxicj4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgY3JlYXRpbmcgdGhlIHBsb3QgYmVsb3c6Kg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KdHZfd2Vla3NfYXZlcmFnZSA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkod2Vla19udW0pICU+JQ0KICBzdW1tYXJpc2UobWVhbl93ZWVrbHlfdHYgPSBtZWFuKFRvdGFsX1RyYWRlX1ZvbHVtZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9d2Vla19udW0sIHk9bWVhbl93ZWVrbHlfdHYsIGZpbGw9bWVhbl93ZWVrbHlfdHYpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSB0dl9hdmVyYWdlXzIwMTgsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0icmVkIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAxOCwgbGFiZWwgPSAiMjAxOCBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHR2X2F2ZXJhZ2VfMjAxOSwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJncmVlbiIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCB0dl9hdmVyYWdlXzIwMTksIGxhYmVsID0gIjIwMTkgQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSB0dl9hdmVyYWdlXzIwMjAsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0iYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCB0dl9hdmVyYWdlXzIwMjAsIGxhYmVsID0gIjIwMjAgQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSB0dl9hdmVyYWdlXzIwMjEsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0ieWVsbG93IikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAyMSwgbGFiZWwgPSAiMjAyMSBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGxhYnMoDQogICAgeD0iV2Vla3MiLA0KICAgIHk9IkF2ZXJhZ2UgV2Vla2x5IFRvdGFsIFRWIiwNCiAgICB0aXRsZT0iQXZlcmFnZSBUViBvdmVyIHRoZSBXZWVrcyINCiAgKQ0KdHZfd2Vla3NfYXZlcmFnZQ0KYGBgDQoNCjxicj4NCg0KTW92aW5nIG9uIHRvIHRoZSB3ZWVrZGF5IGFuYWx5c2lzLCB3ZSBjYW4gY2xlYXJseSBzZWUgdGhhdCB0aGVyZSBpcyBhbG1vc3Qgbm8gY2hhbmdlIGJldHdlZW4gYW55IGdpdmVuIHdlZWtkYXkuDQoNCjxicj4NCg0KKkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiBpZiB5b3Ugd2FudCB0byBzZWUgY29kZSBjaHVuayBmb3IgY3JlYXRpbmcgdGhlIHBsb3QgYmVsb3c6Kg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KZ3BfZGF5c19hdmVyYWdlIDwtIGRmICU+JQ0KICBncm91cF9ieShkYXlfb2Zfd2VlaykgJT4lDQogIHN1bW1hcmlzZShtZWFuX2RhaWx5X2dwID0gbWVhbihHYXNfUmVmZXJlbmNlX1ByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeD1kYXlfb2Zfd2VlaywgeT1tZWFuX2RhaWx5X2dwLCBmaWxsPW1lYW5fZGFpbHlfZ3ApKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBncF9hdmVyYWdlXzIwMTgsDQogICAgICAgICAgIHNpemU9MSwNCiAgICAgICAgICAgY29sb3I9InJlZCIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCBncF9hdmVyYWdlXzIwMTgsIGxhYmVsID0gIjIwMTggQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBncF9hdmVyYWdlXzIwMTksDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0iZ3JlZW4iKSArDQogIGdlb21fdGV4dChhZXMoMCwgZ3BfYXZlcmFnZV8yMDE5LCBsYWJlbCA9ICIyMDE5IEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZ3BfYXZlcmFnZV8yMDIwLA0KICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgY29sb3I9ImJsdWUiKSArDQogIGdlb21fdGV4dChhZXMoMCwgZ3BfYXZlcmFnZV8yMDIwLCBsYWJlbCA9ICIyMDIwIEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZ3BfYXZlcmFnZV8yMDIxLA0KICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgY29sb3I9InllbGxvdyIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCBncF9hdmVyYWdlXzIwMjEsIGxhYmVsID0gIjIwMjEgQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBsYWJzKA0KICAgIHg9IkRheXMgb2YgdGhlIFdlZWsiLA0KICAgIHk9IkF2ZXJhZ2UgRGFpbHkgR1JQIiwNCiAgICB0aXRsZT0iQXZlcmFnZSBHUlAgb3ZlciB0aGUgV2Vla2RheXMiDQogICkNCmdwX2RheXNfYXZlcmFnZQ0KYGBgDQoNCjxicj4NCg0KQnV0IGlmIHdlIGxvb2sgYXQgdHJhZGUgdm9sdW1lIGF2ZXJhZ2VzLCB3ZSBjYW4gY2xlYXJseSBzZWUgdGhhdCBtaWQtd2Vla2RheXMgYWN0dWFsbHkgaGF2ZSBhIGhpZ2hlciB0cmFkZSB2b2x1bWUgYXZlcmFnZSB0aGFuIG90aGVyIGRheXMuIFRoaXMgaW5zaWdodCBjYW4gYmUgZnVydGhlciBhbmFseXNlZCB1c2luZyBkZWVwIGRvbWFpbiBrbm93bGVkZ2UgYnkgaWRlbnRpZnlpbmcgdW5kZXJseWluZyBmYWN0b3JzIGhhcHBlbmluZyBvbiB0aG9zZSBkYXlzLiBJdCBjYW4gYWxzbyBiZSBzYWlkIHRoYXQgYXZlcmFnZSB0cmFkZSB2b2x1bWUgdmFsdWVzIHdhcyBzbyBoaWdoIGluIDIwMjAgdGhhdCBubyB3ZWVrZGF5IGNhbiBjb21lIGNsb3NlIHRvIGl0LiBPbiB0aGUgb3RoZXIgaGFuZCAyMDE5IGFjdHVhbGx5IGhhdmUgYmVlbiBzdXJwYXNzZWQgYnkgZWFjaCB3ZWVrZGF5Lg0KDQo8YnI+DQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIGNyZWF0aW5nIHRoZSBwbG90IGJlbG93OioNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCnR2X2RheXNfYXZlcmFnZSA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoZGF5X29mX3dlZWspICU+JQ0KICBzdW1tYXJpc2UobWVhbl9kYWlseV90diA9IG1lYW4oVG90YWxfVHJhZGVfVm9sdW1lKSkgJT4lDQogIGdncGxvdChhZXMoeD1kYXlfb2Zfd2VlaywgeT1tZWFuX2RhaWx5X3R2LCBmaWxsPW1lYW5fZGFpbHlfdHYpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSB0dl9hdmVyYWdlXzIwMTgsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0icmVkIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAxOCwgbGFiZWwgPSAiMjAxOCBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHR2X2F2ZXJhZ2VfMjAxOSwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJncmVlbiIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCB0dl9hdmVyYWdlXzIwMTksIGxhYmVsID0gIjIwMTkgQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSB0dl9hdmVyYWdlXzIwMjAsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0iYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcygwLCB0dl9hdmVyYWdlXzIwMjAsIGxhYmVsID0gIjIwMjAgQXZlcmFnZSIsIHZqdXN0ID0gLSAxLCBoanVzdD0wKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSB0dl9hdmVyYWdlXzIwMjEsDQogICAgICAgICBzaXplPTEsDQogICAgICAgICBjb2xvcj0ieWVsbG93IikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAyMSwgbGFiZWwgPSAiMjAyMSBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGxhYnMoDQogICAgeD0iRGF5cyBvZiB0aGUgV2VlayIsDQogICAgeT0iQXZlcmFnZSBEYWlseSBUb3RhbCBUViIsDQogICAgdGl0bGU9IkF2ZXJhZ2UgVFYgb3ZlciB0aGUgV2Vla2RheXMiDQogICkNCnR2X2RheXNfYXZlcmFnZQ0KYGBgDQoNCjxicj4NCg0KQXMgb3VyIGxhc3QgYW5hbHlzaXMsIHdlIGNhbiB0YWtlIGEgbG9vayBhdCB0aGUgc2Vhc29uYWwgYXZlcmFnZXMuIEludGVyZXN0aW5nIGluc2lnaHRzIGNhbiBiZSByZXRyaWV2ZWQgZnJvbSB0aGlzIGdyYXBoLiBGb3IgZXhhbXBsZSwgd2UgZXhwZWN0IGl0IHRvIGhhdmUgaGlnaCBhdmVyYWdlIGdhcyBwcmljZXMgaW4gd2ludGVyLCBidXQgd2UgY2FuIGNsZWFybHkgc2VlIHRoYXQgYWN0dWFsbHkgZmFsbCBzZWFzb24gaGFzIHRoZSBoaWdoZXN0IGF2ZXJhZ2UgdmFsdWUgYnkgYSBsYXJnZSBtYXJnaW4uIEFjdHVhbGx5LCB3aW50ZXIgc2Vhc29uIGhhcyB0aGUgbG93ZXN0IGdhcyByZWZlcmVuY2Ugb3ZlcmFsbC4gVGhpcyBjYW4gYmUgdGhlIGVmZmVjdCBvZiB0aGUgc3RlZXAgZGVjcmVhc2Ugb2YgYXZlcmFnZSBnYXMgcHJpY2VzIGdvaW5nIGZyb20gTm92ZW1iZXIgdG8gSmFudWFyeS4gVGhlcmUgaXMgYWxzbyBhIGNsZWFyIGRpZmZlcmVuY2UgZm9yIHRoZSB5ZWFyIDIwMjEgd2hlbiBjb21wYXJlZCB0byBzZWFzb25hbCBhdmVyYWdlcy4NCg0KPGJyPg0KDQoqQ2xpY2sgdGhlIGNvZGUgYnV0dG9uIGlmIHlvdSB3YW50IHRvIHNlZSBjb2RlIGNodW5rIGZvciBjcmVhdGluZyB0aGUgcGxvdCBiZWxvdzoqDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpncF9zZWFzb25zX2F2ZXJhZ2UgPC0gZGYgJT4lDQogIGdyb3VwX2J5KHNlYXNvbikgJT4lDQogIHN1bW1hcmlzZShtZWFuX3NlYXNvbmFsX2dwID0gbWVhbihHYXNfUmVmZXJlbmNlX1ByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeD1zZWFzb24sIHk9bWVhbl9zZWFzb25hbF9ncCwgZmlsbD1tZWFuX3NlYXNvbmFsX2dwKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZ3BfYXZlcmFnZV8yMDE4LA0KICAgICAgICAgICBzaXplPTEsDQogICAgICAgICAgIGNvbG9yPSJyZWQiKSArDQogIGdlb21fdGV4dChhZXMoMCwgZ3BfYXZlcmFnZV8yMDE4LCBsYWJlbCA9ICIyMDE4IEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZ3BfYXZlcmFnZV8yMDE5LA0KICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgY29sb3I9ImdyZWVuIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIGdwX2F2ZXJhZ2VfMjAxOSwgbGFiZWwgPSAiMjAxOSBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGdwX2F2ZXJhZ2VfMjAyMCwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJibHVlIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIGdwX2F2ZXJhZ2VfMjAyMCwgbGFiZWwgPSAiMjAyMCBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGdwX2F2ZXJhZ2VfMjAyMSwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJ5ZWxsb3ciKSArDQogIGdlb21fdGV4dChhZXMoMCwgZ3BfYXZlcmFnZV8yMDIxLCBsYWJlbCA9ICIyMDIxIEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgbGFicygNCiAgICB4PSJTZWFzb25zIiwNCiAgICB5PSJBdmVyYWdlIFNlYXNvbmFsIEdSUCIsDQogICAgdGl0bGU9IkF2ZXJhZ2UgR1JQIG92ZXIgdGhlIFNlYXNvbnMiLA0KICAgIGZpbGw9IkF2ZXJhZ2UgU2Vhc29uYWwgR1JQIg0KICApDQpncF9zZWFzb25zX2F2ZXJhZ2UNCmBgYA0KDQo8YnI+DQoNCklmIHdlIHRha2UgYSBsb29rIGF0IHRvdGFsIHRyYWRlIHZvbHVtZSBhdmVyYWdlcyBvdmVyIHRoZSBzZWFzb25zLCB3ZSBzZWUgdGhlIHNhbWUgdHJlbmQgaGFwcGVuaW5nIGFnYWluLg0KDQo8YnI+DQoNCipDbGljayB0aGUgY29kZSBidXR0b24gaWYgeW91IHdhbnQgdG8gc2VlIGNvZGUgY2h1bmsgZm9yIGNyZWF0aW5nIHRoZSBwbG90IGJlbG93OioNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCnR2X3NlYXNvbnNfYXZlcmFnZSA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoc2Vhc29uKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fc2Vhc29uYWxfdHYgPSBtZWFuKFRvdGFsX1RyYWRlX1ZvbHVtZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9c2Vhc29uLCB5PW1lYW5fc2Vhc29uYWxfdHYsIGZpbGw9bWVhbl9zZWFzb25hbF90dikpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHR2X2F2ZXJhZ2VfMjAxOCwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJyZWQiKSArDQogIGdlb21fdGV4dChhZXMoMCwgdHZfYXZlcmFnZV8yMDE4LCBsYWJlbCA9ICIyMDE4IEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gdHZfYXZlcmFnZV8yMDE5LA0KICAgICAgICAgc2l6ZT0xLA0KICAgICAgICAgY29sb3I9ImdyZWVuIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAxOSwgbGFiZWwgPSAiMjAxOSBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHR2X2F2ZXJhZ2VfMjAyMCwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJibHVlIikgKw0KICBnZW9tX3RleHQoYWVzKDAsIHR2X2F2ZXJhZ2VfMjAyMCwgbGFiZWwgPSAiMjAyMCBBdmVyYWdlIiwgdmp1c3QgPSAtIDEsIGhqdXN0PTApKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHR2X2F2ZXJhZ2VfMjAyMSwNCiAgICAgICAgIHNpemU9MSwNCiAgICAgICAgIGNvbG9yPSJ5ZWxsb3ciKSArDQogIGdlb21fdGV4dChhZXMoMCwgdHZfYXZlcmFnZV8yMDIxLCBsYWJlbCA9ICIyMDIxIEF2ZXJhZ2UiLCB2anVzdCA9IC0gMSwgaGp1c3Q9MCkpICsNCiAgbGFicygNCiAgICB4PSJTZWFzb25zIiwNCiAgICB5PSJBdmVyYWdlIFNlYXNvbmFsIFRWIiwNCiAgICB0aXRsZT0iQXZlcmFnZSBUViBvdmVyIHRoZSBTZWFzb25zIiwNCiAgICBmaWxsPSJBdmVyYWdlIFNlYXNvbmFsIFRWIg0KICApDQp0dl9zZWFzb25zX2F2ZXJhZ2UNCmBgYA0KDQo8YnI+DQoNCiMgKipDb25jbHVzaW9uKioNCg0KPGJyPg0KDQoqIFdlIGNhbiBjbGVhcmx5IHNlZSBhIHJpc2UgaW4gZ2FzIHJlZmVyZW5jZSBwcmljZXMgaW4gMjAyMSB3aGVuIGNvbXBhcmVkIHRvIG90aGVyIHllYXJzLiBUaGlzIGNhbiBiZSByZWxhdGVkIHRvIHRoZSBmYWN0IHRoYXQgR2F6cHJvbSdzIGFsbGVnZWQgbWFya2V0IG1hbmlwdWxhdGlvbiwgZGVjcmVhc2UgaW4gVHVya2lzaCBMaXJhJ3MgdmFsdWUsIGFuZCBhcyB3ZWxsIGFzIG90aGVyIHNpZGUgZmFjdG9ycy4gT24gdGhlIG90aGVyIGhhbmQsIHRvdGFsIHRyYWRlIHZvbHVtZSBiZWhhdmVzIGFsbW9zdCB0aGUgc2FtZSB3YXkgd2UgZXhwZWN0IGl0IHRvIGJlLCBleGNlcHQgaW4gY2VydGFpbiB0aW1lIHBlcmlvZHMsIHdlIGNhbiBzZWUgdGhhdCBpdCBpcyBsb3dlciBvciBoaWdoZXIgdGhhbiBwcmV2aW91cyB2YWx1ZXMuIE92ZXJhbGwgd2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhlIGRlbWFuZCBmb3IgbmF0dXJhbCBnYXMgZGlkIG5vdCBoYXZlIGEgZHJhc3RpYyBjaGFuZ2UgdG8gYWZmZWN0IHRoZSBnbG9iYWwgbWFya2V0IHByaWNlcy4NCiogTW9udGhseSBhbmQgd2Vla2x5IGFnZ3JlZ2F0aW9uIGdyYXBocyBzaG93IHVzIHRoYXQgTm92ZW1iZXIgYW5kIE9jdG9iZXIgaW4gMjAyMSBoYXZlIHRoZSBoaWdoZXN0IGdhcyByZWZlcmVuY2UgcHJpY2VzIGFuZCB0b3RhbCB0cmFkZSB2b2x1bWUgYXZlcmFnZXMgcmVzcGVjdGl2ZWx5Lg0KKiBUaGUgZmFsbCBzZWFzb24gdW5leHBlY3RlZGx5IGhhcyB0aGUgaGlnaGVzdCBnYXMgcHJpY2UgYW5kIHRyYWRlIHZvbHVtZSBhdmVyYWdlcy4gT24gdGhlIG90aGVyIGhhbmQsIHdpbnRlciBhY3R1YWxseSBoYXMgdGhlIGxvd2VzdCBhdmVyYWdlcy4NCiogRXZlbiB0aG91Z2ggdGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgY2hhbmdlIGluIGF2ZXJhZ2UgZ2FzIHByaWNlcyBiZXR3ZWVuIGVhY2ggd2Vla2RheSwgdHJhZGUgdm9sdW1lIGF2ZXJhZ2VzIGNoYW5nZSBvdmVyIHdlZWtkYXlzLiBUaGlzIGFsc28gbWF5IGJlIGRlcGVuZGluZyBvbiB0aGUgZGVtYW5kaW5nIGNvbXBhbnkncyBwb2xpY3kuDQoNCjxicj4NCg0KIyMjICoqUmVmZXJlbmNlcyoqDQoNCjxicj4NCg0KKiBbRVBJQVMgVHJhbnNwYXJlbmN5IFBsYXRmb3JtXShodHRwczovL3NlZmZhZmxpay5lcGlhcy5jb20udHIvdHJhbnNwYXJlbmN5LykNCiogW0NOQkMsIE5hdHVyYWwgZ2FzIHByaWNlcyBhcmUgc2t5cm9ja2V0aW5nIGFyb3VuZCB0aGUgd29ybGQuIEhlcmXigJlzIHdoeSB0aGUgVS5TLiBtYXkgbm90IHN1ZmZlciBhcyBtdWNoLCBGUkksIE9DVCA4IDIwMjEyOjA2IFBNIEVEVCwgUGlwcGEgU3RldmVuc10oaHR0cHM6Ly93d3cuY25iYy5jb20vMjAyMS8xMC8wOC9uYXR1cmFsLWdhcy1wcmljZXMtYXJlLXNreXJvY2tldGluZy1nbG9iYWxseS13aGF0LWl0LW1lYW5zLWZvci10aGUtdXMuaHRtbCkNCiogW1VTRFRSWSBFeGNoYW5nZSBSYXRlIExpdmUgR3JhcGhdKGh0dHBzOi8vZmluYW5jZS55YWhvby5jb20vcXVvdGUvVVNEVFJZPVgvKQ0KKiBbUmV1dGVycywgVHVya2V5IGhpa2VzIG5hdHVyYWwgZ2FzIHByaWNlcyBmb3IgcG93ZXIgcGxhbnRzLCBpbmR1c3RyeSBieSA0Ny00OCUsIE5vdmVtYmVyIDEsIDIwMjENCjc6MzAgQU0gKzAzLCBSZXBvcnRpbmcgYnkgT3JoYW4gQ29za3VuIEVkaXRpbmcgYnkgRGFyZW4gQnV0bGVyXShodHRwczovL3d3dy5yZXV0ZXJzLmNvbS93b3JsZC9taWRkbGUtZWFzdC90dXJrZXktaGlrZXMtbmF0dXJhbC1nYXMtcHJpY2VzLXBvd2VyLXBsYW50cy1pbmR1c3RyeS1ieS00Ny00OC0yMDIxLTExLTAxLykNCiogW0JyaXRpc2ggQ29sdW1iaWEsIEdhcyByZWZlcmVuY2UgcHJpY2VzXShodHRwczovL3d3dzIuZ292LmJjLmNhL2dvdi9jb250ZW50L3RheGVzL25hdHVyYWwtcmVzb3VyY2UtdGF4ZXMvb2lsLW5hdHVyYWwtZ2FzL29pbC1nYXMtcm95YWx0eS9yZWZlcmVuY2UtcHJpY2UjOn46dGV4dD1UaGUlMjBnYXMlMjByZWZlcmVuY2UlMjBwcmljZSUyMGlzLHBvc3RlZCUyMG1pbmltdW0lMjBwcmljZSUyMChQTVApKQ0KKiBbVGhlIE5hdGlvbmFsIExhdyBSZXZpZXcsIERlY2VtYmVyIDE1LCAyMDIxIFZvbHVtZSBYSSwgTnVtYmVyIDM0OSwgR3JlZyBMZW9uYXJkLCBOaWNvbGUgTS4gTW9yYW4sIExhdXJlbnQgU2FtdWVsXShodHRwczovL3d3dy5uYXRsYXdyZXZpZXcuY29tL2FydGljbGUvdXMtbmF0dXJhbC1nYXMtcGh5c2ljYWwtdHJhZGluZy12b2x1bWUtYW5kLW1hcmtldGVkLXByb2R1Y3Rpb24tcmVtYWluLWhpZ2gpDQoqIFtFUERLLCBOYXR1cmFsIEdhcyBNYXJrZXQgQW5udWFsIFNlY3RvciBSZXBvcnQgTGlzdF0oaHR0cHM6Ly93d3cuZXBkay5nb3YudHIvRGV0YXkvSWNlcmlrLzMtMC05NC95aWxsaWstc2VrdG9yLXJhcG9ydSkNCiogW1UuUy4gRW5lcmd5IEluZm9ybWF0aW9uIEFkbWluaXN0cmF0aW9uLCBOYXR1cmFsIGdhcyBleHBsYWluZWQgRmFjdG9ycyBhZmZlY3RpbmcgbmF0dXJhbCBnYXMgcHJpY2VzLCBPY3RvYmVyIDUsIDIwMjFdKGh0dHBzOi8vd3d3LmVpYS5nb3YvZW5lcmd5ZXhwbGFpbmVkL25hdHVyYWwtZ2FzL2ZhY3RvcnMtYWZmZWN0aW5nLW5hdHVyYWwtZ2FzLXByaWNlcy5waHApDQoqIFtSZXV0ZXJzLCBHcm91cCBvZiBFVSBsYXdtYWtlcnMgc2Vla3MgcHJvYmUgb2YgR2F6cHJvbSdzIHJvbGUgaW4gZ2FzIHByaWNlIHN1cmdlLCBTZXB0ZW1iZXIgMTcsIDIwMjEgODoxNSBQTSArMDMsIFJlcG9ydGluZyBieSBLYXRlIEFibmV0dDsgYWRkaXRpb25hbCByZXBvcnRpbmcgYnkgVmxhZGltaXIgU29sZGF0a2luLCBUaG9tYXMgQmFsbWVzOyBFZGl0aW5nIGJ5IExvdWlzZSBIZWF2ZW5zXShodHRwczovL3d3dy5yZXV0ZXJzLmNvbS9idXNpbmVzcy9lbmVyZ3kvZ3JvdXAtZXUtbGF3bWFrZXJzLXNlZWtzLXByb2JlLWdhenByb21zLXJvbGUtZ2FzLXByaWNlLXN1cmdlLTIwMjEtMDktMTcvKQ==