Report

Team

Paula Moloney, Spain

Camila de la Cruz, Peru

Klaus Lindemann, Poland

Statement

Paula:

Worked on L4, L7-L8

Camila:

Worked on L1-L10. I leverage AI-powered tools like ChatGPT as a starting point for code structure and data organization, such as creating functions to extract data from tables. However, I consistently refine and enhance the code, incorporating my personal coding style and expertise (for example I figured it out how to change the function to download financial statements after 2006).

Klaus:

Worked on L9-L12. As someone with limited prior experience in coding and financial analysis, I relied on AI tools like ChatGPT to a greater extent than others in the group to complete my portion of this project. The AI provided guidance on coding practices, debugging errors, and structuring R scripts for tasks like portfolio optimization, WACC calculations, and derivatives analysis. I used AI primarily as a learning tool to understand the concepts and translate theoretical knowledge into practical implementation. While I actively engaged with the material, wrote code, and refined outputs, the AI served as an assistant to bridge the gap in my technical skills and ensure I could contribute effectively to the project. This experience has helped me develop a foundational understanding of coding and financial analysis, which I aim to build upon in future projects.

L1 Basic parameters of the markets

First we will install and then called the library ‘quantmod’ to download the assets prices.

# Quantmod


library(quantmod)
library(lubridate)

We will define the beginning of term period (BoT) as of March 1st and the end (EoT) as November 20th.

#Define time period

BoT <- as.Date("2024-03-01") 
EoT <- as.Date("2024-11-22")

cat("Beginning of the period:", format(BoT), "\n")
Beginning of the period: 2024-03-01 
cat("Ending of the period:", format(EoT))
Ending of the period: 2024-11-22
  • Basic parameters of the market
basic_param <- data.frame(
  Description = character(),
  Beginning_of_Term = character(),
  End_of_Term = character()
)


add_row <- function(category, symbol) {
  data <- getSymbols(symbol, from=BoT, to=EoT+2, auto.assign = FALSE)
  data <- data[!is.na(data[, 1]), ]
  basic_param <<- rbind(basic_param, data.frame(
    Description = category,
    BoT = as.numeric(Cl(data)[which(index(data) == BoT)]),
    EoT = as.numeric(Cl(data)[which(index(data) == EoT)])
  ))
}


add_row("S&P 500 (stock) index level","^GSPC" )
add_row("Nasdaq Composite (stock) index level","^IXIC" )

add_row <- function(category, symbol) {
  data <- getSymbols(symbol, from=BoT, to=EoT+2,src="FRED", auto.assign = FALSE)
  data <- data[!is.na(data[, 1]), ]
  basic_param <<- rbind(basic_param, data.frame(
    Description = category,
    BoT = as.numeric(data[which.min(abs(index(data) - BoT)), 1]),
    EoT = as.numeric(data[which.min(abs(index(data) - EoT)), 1])
  ))
}
add_row("Prime rate","IR14220" )
add_row("Federal funds rate","FEDFUNDS" )
add_row("Commercial paper rate (90 days)","RIFSPPFAAD90NB" )
add_row("Certificate of deposit rate (3-month)","TY3MCD" )
add_row("Treasury bill rate (3-month)","DTB3" )
add_row("Treasury bill rate (6-month)","DTB6" )
add_row("Treasury long-term bond yield","DLTIIT" )
add_row("Corporate (Master) bond yield","DAAA" )
add_row("High-yield corporate bond yield","BAMLH0A0HYM2EY" )
add_row("Tax-exempt (7–12-year) bond yield","IRLTLT01USM156N" )




print(basic_param)

(Explain the assumptions)

  • Use stock exchange quotations to record the stock price and dividend of one stock from each stock exchange in which you would like to invest.

We will select to stocks in different stock markets to record the stock price and dividend

  1. PKO Bank Polski (PKO) in the Warsaw Stock Exchange (WSE).

  2. Tesla (TSLA) in the New York Stock Exchange (NYSC)

We will now get the prices during the analysis period from Yahoo Finance.

#Historical data prices from the target time range

getSymbols("PKO.WA",from=BoT, to=EoT+2)
[1] "PKO.WA"
getSymbols("TSM",from=BoT, to=EoT+2)
[1] "TSM"
#Extract the close prices of the target dates

pko_b_price <- Cl(PKO.WA[BoT])
pko_e_price <- Cl(PKO.WA[EoT])

tsm_b_price <- Cl(TSM[BoT])
tsm_e_price <- Cl(TSM[EoT])

To visualize the data:

View(PKO.WA)
View(TSM)
chartSeries(Cl(PKO.WA),theme="white")

chartSeries(Cl(TSM),theme="white")

Then, we will get the information about the dividends on each stock.

#Historical data of dividends 

pko_div <- getDividends("PKO.WA")
tsm_div <- getDividends("TSM")

#Extract the ones that are closes but before the target date

pko_b_div <- pko_div[which.min(abs(index(pko_div) - BoT))]
pko_e_div <- pko_div[which.min(abs(index(pko_div) - EoT))]

tsm_b_div <- tsm_div[which.min(abs(index(tsm_div) - BoT))]
tsm_e_div <- tsm_div[which.min(abs(index(tsm_div) - EoT))]

We see that neither of each stock distribute dividends during the this specific time range.

# Create the data frame
stock_table <- data.frame(
  Description = c(
    "WSE: PKO Stock price",
    "PKO Dividend",
    "NYSE: TSM Stock price",
    "TSM Dividend"
  ),
  BoT = NA,  
  EoT = NA  
)

View(stock_table)


#Fill with data
stock_table[1, 2] <- pko_b_price
stock_table[1, 3] <- pko_e_price

stock_table[2, 2] <- pko_b_div
stock_table[2, 3] <- pko_e_div

stock_table[3, 2] <- tsm_b_price
stock_table[3, 3] <- tsm_e_price

stock_table[4, 2] <- tsm_b_div
stock_table[4, 3] <- tsm_e_div

print(stock_table)
NA
  • Use futures prices quotations to record the recent (“settle”) price of the following futures (select futures with first settlement date beyond the end of the school term).

First we will look for the tickers of each future in yahoo finance.

#Historical data of the futures

sp500_f <- getSymbols("ES=F", from= BoT, to=EoT+2, auto.assign = F)
nasdaq_f <- getSymbols("NQ=F", from= BoT, to=EoT+2, auto.assign = F)
treasury_f <- getSymbols("ZB=F", from= BoT, to=EoT+2, auto.assign = F)
british_f <- getSymbols("6B=F", from= BoT, to=EoT+2, auto.assign = F)

Now we create the table and then we fill it.

# Create the data frame
futures_table <- data.frame(
  Description = c(
    "Treasury bond futures",
    "S&P500 index futures",
    "NASDAQ index futures",
    "British pounds futures"
  ),
  BoT = NA,  
  EoT = NA   
)



#Fill with data
symbols <- list(treasury_f, sp500_f, nasdaq_f, british_f)
rows <- 1:4  # Row indices in futures_table corresponding to the symbols

# Loop through each symbol and row
for (i in seq_along(symbols)) {
  # Extract the symbol and its corresponding row
  symbol <- symbols[[i]]
  row <- rows[i]
  
  # Assign closing prices for BoT and EoT
  futures_table[row, 2] <- Cl(symbol[BoT])
  futures_table[row, 3] <- Cl(symbol[EoT])
}


print(futures_table)
  • Use an options quotations table to select a call option on a firm whose stock price you expect to increase (select the option with the first expiration month beyond the end of the school term).

cat("Name of the firm: ", "Tesla", "\n")
Name of the firm:  Tesla 
cat("Expiration month:", "2024-11-29", "\n")
Expiration month: 2024-11-29 
cat("Strike price:", 335 , "\n")
Strike price: 335 
call_tab <- data.frame(
  Description = character(),
  Beginning_of_Term = character(),
  End_of_Term = character()
)


add_row <- function(category, symbol) {
  data <- getSymbols(symbol, from=BoT, to=EoT+2, auto.assign = FALSE)
  call_tab <<- rbind(call_tab, data.frame(
    Description = category,
    BoT = as.numeric(Cl(data)[which.min(abs(index(data) - BoT))]),
    EoT = as.numeric(Cl(data)[which.min(abs(index(data) - EoT))])
  ))
}


add_row("Stock price","TSLA" )
add_row("Option premium","TSLA241206C00335000" )
Warning: TSLA241206C00335000 contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.
print(call_tab)
NA
  • Use an options quotations table to select a put option on a firm where you expect the stock price to decrease (select the option with the first expiration month beyond the end of the school term)
cat("Name of the firm: ", "NVIDIA", "\n")
Name of the firm:  NVIDIA 
cat("Expiration month:", "2024-11-29", "\n")
Expiration month: 2024-11-29 
cat("Strike price:", 130 , "\n")
Strike price: 130 

put_tab <- data.frame(
  Description = character(),
  Beginning_of_Term = character(),
  End_of_Term = character()
)


add_row <- function(category, symbol) {
  data <- getSymbols(symbol, from=BoT, to=EoT+2, auto.assign = FALSE)
  put_tab <<- rbind(put_tab, data.frame(
    Description = category,
    BoT = as.numeric(Cl(data)[which.min(abs(index(data) - BoT))]),
    EoT = as.numeric(Cl(data)[which.min(abs(index(data) - EoT))])
  ))
}


add_row("Stock price","NVDA" )
add_row("Option premium","NVDA241129P00130000" )
Warning: NVDA241129P00130000 contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.
print(put_tab)
  • Use a currency exchange rate table to record exchange rates.
currency_tab <- data.frame(
  Description = character(),
  Beginning_of_Term = character(),
  End_of_Term = character()
)


add_row <- function(category, symbol) {
  data <- getSymbols(symbol, from=BoT, to=EoT+2, auto.assign = FALSE)
  currency_tab <<- rbind(currency_tab, data.frame(
    Description = category,
    BoT = as.numeric(Cl(data)[which.min(abs(index(data) - BoT))]),
    EoT = as.numeric(Cl(data)[which.min(abs(index(data) - EoT))])
  ))
}


add_row("Exchange rate of the British pound (in $)","GBPUSD=X" )
add_row("Exchange rate of the Japanese yen (in $)","JPY=X" )
add_row("Exchange rate of the Mexican peso (in $)","MXN=X" )

print(currency_tab)
NA
  • Use currency options data (if available) to select a call option on a foreign currency that you expect will strengthen against the dollar (select the option with the first expiration month beyond the end of the school term).
  • Use currency options data (if available) to select a put option on a foreign currency that you expect will weaken against the dollar (select the option with the first expiration month beyond the end of the school term).

I didn’t find information about call or put options, just forward exchange rates.

cat("Currency: ", "Japanese Yen", "\n")
Currency:  Japanese Yen 
cat("Expiration month:", "2024-12-04", "\n")
Expiration month: 2024-12-04 
cat("Strike price:", 151.62 , "\n")
Strike price: 151.62 
currency_tab <- data.frame(
  Description = character(),
  Beginning_of_Term = character(),
  End_of_Term = character()
)

add_row <- function(category, symbol) {
  data <- getSymbols(symbol, from=BoT, to=EoT+2, auto.assign = FALSE)
  currency_tab <<- rbind(currency_tab, data.frame(
    Description = category,
    BoT = as.numeric(Cl(data)[which.min(abs(index(data) - BoT))]),
    EoT = as.numeric(Cl(data)[which.min(abs(index(data) - EoT))])
  ))
}


add_row("Currency’s existing value","JPYUSD=X" )

print(currency_tab)
NA
NA

L2 Financial markets micro structure

  1. Download basic statistic of NASDAQ and London Stock Exchange and compare them
getSymbols("NDAQ", from= BoT, to=EoT)
[1] "NDAQ"
getSymbols("^FTSE", from= BoT, to=EoT) 
[1] "FTSE"
#add a graph adjusted 

FTSE<- na.approx(FTSE)


#Correlation
corr <- merge(NDAQ, FTSE)
corr <- na.omit(corr)

correlation <- cor(corr[, 4], corr[, 10])



nasdaq_s <- c(
  Mean = mean(NDAQ$NDAQ.Close, na.rm=TRUE),
  Median = median(NDAQ$NDAQ.Close, na.rm=TRUE),
  StDev = sd(NDAQ$NDAQ.Close, na.rm= TRUE)
)

lse_s <- c(
  Mean = mean(FTSE$FTSE.Close),
  Median = median(FTSE$FTSE.Close),
  StDev = sd(FTSE$FTSE.Close)
)


comparison <- rbind(nasdaq_s, lse_s)
colnames(comparison) <- c("Mean", "Median", "Standard Deviation" )

round(correlation, 3)
           FTSE.Close
NDAQ.Close      0.341
round(comparison,2)
            Mean  Median Standard Deviation
nasdaq_s   66.24   63.01               6.61
lse_s    8160.55 8204.90             184.89

The correlation between the markets is very low: 0.341. We see also, that the volatility (measured by the standard deviation) of the London SE is greater that the NASDAQ.

L3 Instrument’s overview and valuation

  • Compare the 13-week Treasury bill rate (which is a proxy for short-term interest rates) at the end of the school term to the rate that existed at the beginning of the school term. (note: 3-Month Treasury Bill Secondary Market Rate, Discount Basis (TB3MS)) https://fred.stlouisfed.org/series/TclB3MS
tb3m <- data.frame(
  Description = character(),
  Beginning_of_Term = character(),
  End_of_Term = character(),
  Change = character()
)



add_row <- function(category, symbol) {
  data <- getSymbols(symbol, from=BoT, to=EoT+2,src="FRED", auto.assign = FALSE)
  tb3m <<- rbind(tb3m, data.frame(
    Description = category,
    BoT = as.numeric(data[which.min(abs(index(data) - BoT)), 1]),
    EoT = as.numeric(data[which.min(abs(index(data) - EoT)), 1]), 
    Change= as.numeric(data[which.min(abs(index(data) - EoT)), 1])-as.numeric(data[which.min(abs(index(data) - BoT)), 1])
  ))
}

add_row("Treasury bill (3-month)","TB3MS" )

print(tb3m)
NA
NA

We can see that the rate has decreased by 73 basic points.

  • Why interest rates change over time.

Interest mainly change due to economic conditions. When the economy is overheated, the Central Bank will increase the federal funds rates (FFR) to slowdown the economy. This will impact on all the yield curve, specially on the short term rates. Thus, since the FED decided to cut the FFR and the investors are expecting future cuts in the following meetings, we have seen that the yield of the TB3M has decreased.

L4 Efficiency of market and information

  • Check if on 26 October 2017 Coca Cola shares were hit by the adverse information realize on the market. (assume 26 is the information realise date)
date <- as.Date("2017-10-26")
getSymbols("KO", from=date-5, to=date+30)
[1] "KO"
KO<- round(KO, 2)
dev.new()
chartSeries(Cl(KO),theme="white")

addTA(Cl(KO)[index(KO) == date], on = 1, col = "blue", pch = 19, type = "p", legend = FALSE)

NA
NA

In October 2017, Coca Cola had a decrease in its net income of 15% because of the franchising process. Due to this, on October 26 the price closed at $45.59, which was a decrease of 0.5% compared to the 25th. Also, we notice that there was a reaction to the news days after November 3rd and then a correction (an underreaction and then a correction). So, to sum up we can confirm that there is an impact specially notable days after the realize date regarding the company’s actions due to the adverse information realized on the market.

L5 Financial statements and fundamental analysis

  • Download to R the financial statements of Microsoft 2018, show the cod

We download the Balance Sheet, Cash Flow and Income of Microsoft for 2018.


library(finreportr) # for financials
library(edgar)  # for full text retrial and text mining
library(XBRL)  # for instants (full set manipulation)
library(dplyr) 
library(tidyr)


options(HTTPUserAgent = "camiladelacruzh@gmail.com")

AnnualReports(0000789019, foreign = FALSE)


trace('XBRL', edit=TRUE)

#There's is a problem with the GetBalanceSheet function. To fix that problem we run the following code to edit the function temporarily: trace('XBRL', edit=TRUE). We will replace "if (substr(file.name, 1, 5) != "http:") {" for "if (!(substr(file.name, 1, 5) %in% c("http:", "https"))) {". Now we can run the code to search files beyond 2016. 

msft_bs <-GetBalanceSheet('MSFT', 2018)
msft_cf <-GetCashFlow('MSFT', 2018)
msft_in <- GetIncome('MSFT', 2018)


head(msft_cf)
head(msft_in)
head(msft_bs)
NA
NA
head(msft_cf)

Commercial bank operations

For the commercial bank that you selected at the beginning of the term, use its annual report or any other related information to answer the following questions:


AnnualReports("BAC", foreign = FALSE)


bac_bs <-GetBalanceSheet('BAC', 2018)
bac_cf <-GetCashFlow('BAC', 2018)
bac_in <- GetIncome('BAC', 2018)
  • Identify the types of deposits that the commercial bank uses to obtain most of its funds.

Primarily uses demand deposits (such as checking accounts) and savings accounts.

  • Identify the main uses of funds by the bank. Summarize any statements made by the commercial bank in its annual report about how recent or potential regulations will affect its performance.

The main uses of funds are loans to customers, investments in securities and cash reserves.

The bank highlights uncertainties regarding the content, timing, and impact of regulatory capital and liquidity requirements, such as those under the Volcker Rule, recovery planning requirements, and the Federal Reserve’s actions on capital plans.

  • Does it appear that the bank is attempting to enter the securities industry by offering securities services? If so, explain how.

The report indicates that the bank offers a range of investment banking services, including underwriting for equity and debt securities, advisory services and brokerage services. Additionally, Bank of America has integrated its wealth management services with investment solutions, allowing clients access to a broader array of financial products, including mutual funds and ETFs. This strategic move indicates a clear intent to expanding its presence in the securities industry.

  • Does it appear that the bank is attempting to enter the insurance industry by offering insurance services? If so, explain how.

The bank is by offering various insurance-related products and services. The report highlights the provision of life insurance, property and casualty insurance, and health insurance products through partnerships s and the integration of insurance services within their broader financial offerings. Thus, it seems that is also attempting to enter this industry.

Commercial bank management

  • Assess the bank’s balance sheet as well as any comments in its annual report about the gap between its rate-sensitive assets and its rate-sensitive liabilities. Does it appear that the bank has a positive gap or a negative gap?

During 2023, BA experienced an overall decrease in the asset sensitivity of its balance sheet concerning higher and lower interest rate scenarios. This change was primarily attributed to shifts in the deposit product mix and activity within the Asset-Liability Management (ALM) portfolio.The bank continues to be asset sensitive to a parallel upward move in interest rates, with the majority of this impact stemming from the short end of the yield curve. This indicates that the bank has a positive gap, meaning that its rate-sensitive assets are expected to respond more favorably to rising interest rates compared to its rate-sensitive liabilities (primarily deposits).

For the next questions we will use the financial data that is available on the following link: https://www.sec.gov/ix?doc=/Archives/edgar/data/70858/000007085824000122/bac-20231231.htm

# Financial data (millions of $)
total_assets <- 3180151
interest_income <- 130262
interest_expense <- 73331
noninterest_income <- 41650
noninterest_expense <- 65845
earning_assets <- 2753600
net_income <- 26515
shareholders_equity <- 291646
loan_loss_reserves <- 13342
  • Determine the bank’s interest income as a percentage of its total assets.
interest_income_percentage <- (interest_income / total_assets) * 100
round(interest_income_percentage,2)
[1] 4.1
  • Determine the bank’s interest expenses as a percentage of its total assets.
interest_expense_percentage <- (interest_expense / total_assets) * 100

round(interest_expense_percentage,2)
[1] 2.31
  • Determine the bank’s net interest margin.
net_interest_income <- interest_income - interest_expense
nim <- (net_interest_income / earning_assets) * 100
print(nim, 2)
[1] 2.1
  • Determine the bank’s noninterest income as a percentage of its total assets.

noninterest_income_percentage <- (noninterest_income / total_assets) * 100
print(noninterest_income_percentage, 2)
[1] 1.3
  • Determine the bank’s noninterest expenses (do not include the addition to loan loss reserves here) as a percentage of its total assets.
noninterest_expense_percentage <- (noninterest_expense / total_assets) * 100
print(noninterest_expense_percentage, 2)
[1] 2.1
  • Determine the bank’s addition to loan loss reserves as a percentage of its total assets.

loan_loss_reserves_percentage <- (loan_loss_reserves / total_assets) * 100
print(loan_loss_reserves_percentage, 2)
[1] 0.42
  • Determine the bank’s return on assets
roa <- (net_income / total_assets) * 100
print(roa, 2)
[1] 0.83
  • Determine the bank’s return on equity.
roe <- (net_income / shareholders_equity) * 100
  • Identify the bank’s income statement items described previously that would be affected if interest rates rise in the next year, and explain how they would be affected.

The interest income is expected to increase since interest income would rise more than interest expenses, net interest income would likely improve, enhancing profitability.

  • Identify the bank’s income statement items described previously that would be affected if U.S. economic conditions deteriorate, and explain how they would be affected

Net Interest Income likely to decrease. With declining interest income and potentially stable or decreasing interest expense, net interest income would likely suffer.

Net income also likely to decrease. With reduced net interest income and noninterest income alongside potential increases in loan loss provisions, overall profitability (net income) is likely to decline during economic downturns.

Mutual funds

For the mutual fund that you selected at the beginning of the term, use its prospectus or any other related information to answer the following questions.

We select the Fidelity 500 Index mutual fund: https://fundresearch.fidelity.com/mutual-funds/summary/315911750

  • What is the investment objective of this mutual fund? Do you consider this mutual fund to have low risk, moderate risk, or high risk?

Since it invest in equity and more than 30% is on the tech sector, we consider that is moredate to high risk.

  • What was the return on the mutual fund last year? What was the average annual return over the last three years?

2023: 26.29%

Last three years: 33.87%

  • What is a key economic factor that influences the return on this mutual fund? (That is, are the fund’s returns highly influenced by U.S. stock market conditions? By U.S. interest rates? By foreign stock market conditions? By foreign interest rates?)

Is highly influenced by the US stock market conditions since only invests in US stocks. Also, that’s why is influenced by interest rates of the US. But as it don’t in other country, the fund is not affected by foreign conditions.

  • Must any fees be paid when buying or selling this mutual fund?

It’s factsheet said that you may be charged a transactions fee if you buy or sell trough a non-Fidelity broker.

  • What was the expense ratio for this mutual fund over the last year? Does this ratio seem high to you?

The net expense ratio was 0.015%. Compare to the average mutual fund, we think that is quite cheap.

Securities firms

For the securities firm that you selected at the beginning of the term, use its annual report or any other related information to answer the following questions.

  • What are the main types of business conducted by the securities firm?

Tesla operates primarily in two segments:

  1. Automotive: This includes the design, development, manufacturing, sales, and leasing of high-performance fully electric vehicles (EVs). The automotive segment also encompasses the sale of automotive regulatory credits and a variety of services such as used vehicle sales, non-warranty after-sales services, body shop services, paid Supercharging, vehicle insurance revenue, and retail merchandise.

  2. Energy Generation and Storage: This segment involves the design, manufacture, installation, sales, and leasing of solar energy generation systems and energy storage products. Key offerings include the Powerwall for residential use and the Megapack for commercial and utility-scale applications. Tesla also sells solar energy systems through various arrangements, including power purchase agreements.

  • Summarize any statements made by the securities firm in its annual report about how it may be affected by existing or potential regulations.

In its annual report, Tesla acknowledges that it operates in a highly regulated environment that can significantly affect its business. The firm notes that existing regulations regarding vehicle emissions and safety standards could impose costs or operational restrictions. Additionally, potential future regulations aimed at electric vehicles or renewable energy could impact Tesla’s operational flexibility and profitability. The company emphasizes its commitment to compliance but recognizes that changes in regulations may pose risks to its growth and market strategy.

  • Describe the recent performance of the securities firm, and explain why the performance has been favorable or unfavorable.

Tesla’s recent performance has been characterized by strong sales growth driven by increased demand for electric vehicles and advancements in production capabilities. The launch of new models, including the Cybertruck, has also contributed positively to its market presence. However, challenges such as supply chain disruptions and competition in the EV market have created some headwinds.The favorable performance is attributed to:

  1. Increased Production Capacity: Expansion of manufacturing facilities has allowed Tesla to meet rising demand.

  2. Innovation: Continuous improvements in technology and product offerings have strengthened customer interest.

  3. Market Positioning: Tesla’s established brand reputation as a leader in the EV space enhances its competitive edge.

Conversely, unfavorable factors include:

  1. Regulatory Challenges: Potential changes in regulations could impact operational costs.

  2. Competitive Landscape: Growing competition from other automakers entering the EV market may affect Tesla’s market share.

L6 Equity

We will explore the Gordon Growth Model

# Function to calculate stock value using Gordon Growth Model
gordon_growth_model <- function(dividend, cost_of_equity, growth_rate) {
  value <- dividend / (cost_of_equity - growth_rate)
  return(value)
}

companies <- data.frame(
  name = c("Tesla", "Apple", "Microsoft", "Toyota", "Samsung", "Volkswagen"),
  country = c("USA", "USA", "USA", "Japan", "South Korea", "Germany"),
  dividend = c(0, 0.92, 2.72, 2.30, 1.97, 7.56),
  cost_of_equity = c(0.08, 0.07, 0.065, 0.06, 0.07, 0.075),
  growth_rate = c(0.20, 0.10, 0.08, 0.03, 0.05, 0.02)
)

companies$stock_value <- mapply(gordon_growth_model, 
                                companies$dividend, 
                                companies$cost_of_equity, 
                                companies$growth_rate)

print(companies)

# Compare U.S. companies with non-U.S. companies
us_companies <- subset(companies, country == "USA")
non_us_companies <- subset(companies, country != "USA")

cat("\nAverage stock value for U.S. companies:", mean(us_companies$stock_value))

Average stock value for U.S. companies: -70.66667
cat("\nAverage stock value for non-U.S. companies:", mean(non_us_companies$stock_value))

Average stock value for non-U.S. companies: 104.2071
# Create a bar plot to visualize the comparison
barplot(companies$stock_value, 
        names.arg = companies$name, 
        col = ifelse(companies$country == "USA", "blue", "red"),
        main = "Stock Values Comparison",
        ylab = "Stock Value",
        las = 2)
legend("topright", legend = c("USA", "Non-USA"), fill = c("blue", "red"))

The average stock value for U.S. companies (excluding Tesla) is likely to be lower than non-U.S. companies in this sample, primarily due to lower dividend payments and higher growth rates.

Some imporant notes:The Gordon Growth Model assumes a constant growth rate, which may not be realistic for many companies, especially in the tech sectos. Also, companies like Tesla, which don’t pay dividends, cannot be valued using this model, highlighting its limitations for growth stocks

L7 Fixed income

Comparing yields among securities

  • What is the difference between the yield on corporate high-quality bonds and the yield on Treasury bonds at the end of the school term? Explain why does the difference exist?

We look for the the data “Moody’s Seasoned Aaa Corporate Bond Yield Relative to Yield on 10-Year Treasury Constant Maturity” on the FRED website.


diff1 <- basic_param$EoT[basic_param$Description == "Corporate (Master) bond yield"] - basic_param$EoT[basic_param$Description == "Treasury long-term bond yield"]


cat("The difference is",  diff1*100, "basic points.")
The difference is 294 basic points.

The big difference between yield on corporate high-quality bonds and the yield on Treasury bonds is the risk. Treasury bonds are about as risk-free as they get as they are operated by the government, but corporate bonds, while also representing a loan, risk is higher because the issuer can not keep its promise. This is due to the credit spread, whereby investors are compensated with higher yields to keep them invested, hence high-quality corporate bonds have to offer a greater return for the higher risk.

  • What is the difference between the yield on long-term Treasury bonds and the yield on long-term municipal bonds at the end of the school term? Explain why does the difference exist?

The main difference is that long-term treasury bonds yield more than the long-term municipal bonds, mainly because of the taxes associated on the interest on municipal bonds. Accordingly, the difference is due to the tax aspects and the credit risk. Corporate bonds offers better yields to offset the risk, but municipal bonds offer better tax advances.

diff2 <- basic_param$EoT[basic_param$Description == "Tax-exempt (7–12-year) bond yield"] - basic_param$EoT[basic_param$Description == "Treasury long-term bond yield"]


cat("The difference is",  diff2*100, "basic points.")
The difference is 182 basic points.

Assessing the forecasting ability of the yield curve

  • What was the difference between the 26-week T-bill yield and the 13-week T-bill yield at the beginning of the school term?
diff3 <- basic_param$BoT[basic_param$Description == "Treasury bill rate (6-month)"] - basic_param$BoT[basic_param$Description == "Treasury bill rate (3-month)"]


cat("The difference is",  diff3*100, "basic points.")
The difference is -14 basic points.
  • Does this imply that the yield curve had an upward or downward slope at that time?

Since the 26-week T-bill yield is lower than the 13-week T-bill yield, this implies a downward slope, that is an inverted yield curve.

  • Assuming that this slope can be primarily attributed to expectations theory, did the direction of the slope indicate that the market expected higher or lower interest rates in the future?

This indicates that the investors expects lower interest rates in the future.

  • Did interest rates move in that direction over the school term?

tb3 <- getSymbols("DTB3", from=BoT, to=EoT+2,src="FRED", auto.assign = FALSE)
chartSeries(tb3,theme="white")

We see that them 13-bill rate went down in the during the period of analysis. So, yes the rates move in the direction that was expected.

Explaining shifts in the yield curve over time

  • What was the difference between the long-term Treasury bond yield and the 13-week T-bill yield at the beginning of the school term?
diff4 <- basic_param$BoT[basic_param$Description == "Treasury long-term bond yield"] - basic_param$BoT[basic_param$Description == "Treasury bill rate (3-month)"]


cat("The difference is",  diff4*100, "basic points.")
The difference is -316 basic points.

At the beginning of the school year, the yield on the long-term Treasury bond was lower than that of the 13-week T-bill.

  • What is the difference between the long-term Treasury bond yield and the 13-week T-bill yield at the end of the school term?
diff5 <- basic_param$EoT[basic_param$Description == "Treasury long-term bond yield"] - basic_param$EoT[basic_param$Description == "Treasury bill rate (3-month)"]


cat("The difference is",  diff5*100, "basic points.")
The difference is -215 basic points.

By the end of the school term, this differential has shrink.

  • Given your answers to the two previous questions, describe how the yield curve changed over the school term. Explain the changes in expectations about future interest rates that are implied by the shift in the yield curve over the school term.

The yield curve at the EoT was less inverted than the beginning. While the curve remains inverted, market expectations for interest rate cuts have softened, indicating a less aggressive outlook for monetary easing than at the start of the term.

  • Did the Fed change the federal funds rate over the school term?

ffr <- getSymbols("FEDFUNDS", from=BoT, to=EoT+2,src="FRED", auto.assign = FALSE)
chartSeries(ffr,theme="white")

NA
NA
tail(ffr)
           FEDFUNDS
2024-05-01     5.33
2024-06-01     5.33
2024-07-01     5.33
2024-08-01     5.33
2024-09-01     5.13
2024-10-01     4.83

There were two cuts during the period. One was a cut of 50 basis points in the September meeting, and the other one of 25 points in the November meeting.

  • Do you think the movements in interest rates over the school term were caused by the Fed’s monetary policy? Explain.

Yes. Specially the investors pays attention to Powell’s speech after the meeting. But, also they takes into account the data on the well known leading economic indicators. That’s why they think that the FED can still lower more interest rates.

Measuring and explaining premiums on money market securities

  • What is the difference between the yield on 90-day commercial paper and the yield on 13-week T-bills at the end of the school term? Explain why this premium exists.

diff6 <- basic_param$BoT[basic_param$Description == "Commercial paper rate (90 days)"] - basic_param$BoT[basic_param$Description == "Treasury bill rate (3-month)"]


cat("The difference is",  diff6*100, "basic points.")
The difference is 1 basic points.

Is greater because there exist a higher credit and default risk, it is widely believed that the United States government will always meet its financial obligations and is unlikely to default.

  • Compare the premium on the 90-day commercial paper yield (relative to the 13-week T-bill yield) that exists at the end of the school term to the premium that existed at the beginning of the term. Explain why the premium may have changed over the school term.
diff7 <- basic_param$EoT[basic_param$Description == "Commercial paper rate (90 days)"] - basic_param$EoT[basic_param$Description == "Treasury bill rate (3-month)"]


cat("The difference is",  diff7*100, "basic points.")
The difference is 13 basic points.

The greater difference may indicate that investors anticipate a deterioration in the overall health of businesses. They think that the risk of having a commercial paper is greater (due to higher credit risk), thus a wider yield spread.

Explaining bond premiums and price movements

  • What is the difference between the yield on high-yield corporate bonds at the end of the school term versus the yield on high-quality corporate bonds at the beginning of the school term?

diff8 <- basic_param$BoT[basic_param$Description == "High-yield corporate bond yield"] - basic_param$BoT[basic_param$Description == "Corporate (Master) bond yield"]


cat("The difference is",  diff8*100, "basic points.")
The difference is 262 basic points.
  • Compare the long-term Treasury bond yield at the end of the school term to the long term Treasury bond yield that existed at the beginning of the school term. Given the direction of this change, did prices of long-term bonds rise or fall over the school term?
diff9 <- basic_param$EoT[basic_param$Description == "Treasury long-term bond yield"] - basic_param$BoT[basic_param$Description == "Treasury long-term bond yield"]


cat("The difference is",  diff9*100, "basic points.")
The difference is 21 basic points.

Since the yield increase, that means that the price fall over the school term.

  • Compare the change in the yields of Treasury, municipal, and corporate bonds over the school term. Did the yields of all three types of securities move in the same direction and by about the same degree? Explain why yields of different types of bonds move together.

diff_yields <- subset(basic_param, Description %in% c("Treasury long-term bond yield", "Corporate (Master) bond yield", "Tax-exempt (7–12-year) bond yield"))

diff_yields$Difference <- diff_yields$EoT - diff_yields$BoT 

print(diff_yields)
NA
NA

Usually when the Federal Reserve, change interest rates, it affects all bonds. If rates go up, new bonds offer higher returns, so existing bonds with lower yields become less attractive, causing their prices to fall and their yields to rise. However, despite the fed cuts during the school term we see that the treasury and corporate bonds went up.

  • Compare the premium on high-yield corporate bonds (relative to Treasury bonds) at the beginning of the school term to the premium that existed at the end of the school term. Did the premium increase or decrease? Why this premium changed over the school term.
#
diff9 <- basic_param$BoT[basic_param$Description == "High-yield corporate bond yield"] - basic_param$BoT[basic_param$Description == "Treasury long-term bond yield"]


cat("The difference is",  diff9*100, "basic points.")
The difference is 556 basic points.
diff10 <- basic_param$EoT[basic_param$Description == "High-yield corporate bond yield"] - basic_param$EoT[basic_param$Description == "Treasury long-term bond yield"]


cat("The difference is",  diff10*100, "basic points.")
The difference is 469 basic points.

diff11 <- diff10-diff9

print(diff11)
[1] -0.87

The premium decrease. Investors may perceive that the high yield bonds are less risky that at the beginning. Maybe at the start of the period they were discounting too much risk on these bonds.

L8 Portfolio - Markovitz

  • Replicate the basic idea of the portfolio case
library(PerformanceAnalytics)

getSymbols(c("NVDA", "TSLA"), from = BoT, to = EoT)
[1] "NVDA" "TSLA"
returns <- na.omit(ROC(merge(NVDA[,6], TSLA[,6])))

# Expected returns and covariance matrix
mu <- colMeans(returns)
cov_mat <- cov(returns)

# Portfolio weights
weights <- c(0.5, 0.5)  # Equal weights for AAPL and MSFT

# Portfolio expected return and variance
portfolio_return <- sum(weights * mu)
portfolio_variance <- t(weights) %*% cov_mat %*% weights


print(paste("Portfolio expected return:", round(portfolio_return * 252, 2), "%"))
[1] "Portfolio expected return: 0.75 %"
print(paste("Portfolio annualized volatility:", round(sqrt(portfolio_variance * 252) * 100, 2), "%"))
[1] "Portfolio annualized volatility: 47.69 %"

L9 Portfolio - CAMP

  • State the difference between CAMP and Markowitz

Markowitz helps with portfolio construction by focusing on diversification to optimize risk and return. He is not interested in determining the return of a specific asset; instead, he aims to identify the optimal portfolio based on historical correlations between assets, seeking the best risk-return trade-off. On the other hand, CAPM helps with estimating the expected return of an individual asset based on its risk relative to the market. It focuses to estimate the sensitiveness of an asset to market movements (systematic risk) and use that to state what should be the return of the asset in the long run.

This section calculates the Beta and Expected Return for Apple (AAPL) using the CAPM formula.

library(quantmod)
library(PerformanceAnalytics)

start_date <- BoT
end_date <- EoT

stock_symbol <- "AAPL"
market_symbol <- "^GSPC"
getSymbols(c(stock_symbol, market_symbol), from = start_date, to = end_date, src = "yahoo")
[1] "AAPL" "GSPC"
stock_prices <- Cl(AAPL)
market_prices <- Cl(GSPC)
stock_returns <- dailyReturn (stock_prices)
market_returns <- dailyReturn(market_prices)

risk_free_rate <- 0.03 / 252
beta <- cov(stock_returns , market_returns) / var(market_returns)
market_premium <- mean(market_returns) - risk_free_rate
expected_return <- risk_free_rate + beta * market_premium

cat("Beta:", round(beta, 4), "\n")
Beta: 0.995 
cat("Expected Return (CAPM):", round(expected_return * 100, 2), "%\n")
Expected Return (CAPM): 0.08 %

L10 WACC

  • Replicate the book case of WACC

We will use the basic formula of the WACC

\[ WACC= \frac{E}{E+D}r_e+\frac{D}{E+D}r_d(1-t) \]

Where:

\(E\): market value of equity

\(D\): market value of debt

\(r_e\): cost of equity

\(r_d\): cost of debt

\(t\): tax rate

In this case, we will calculate the WACC for Tesla.

getSymbols("TSLA")
[1] "TSLA"
oustanding_shares<- 3.19e9
market_cap <- TSLA$TSLA.Adjusted[EoT] * oustanding_shares
market_value_of_debt <- 12.78e9  # According to Yahoo Finance
tax_rate <- 0.22  
beta <- 1.6  # Unleveraged beta according to Reuters (2024)
risk_free_rate <- 0.0475  # fed funds rate
market_risk_premium <- 0.04  # market risk premium according to Damodaran (2024)
#Data for calculation
cost_of_debt <- 0.0425  
cost_of_equity <- risk_free_rate + beta * market_risk_premium
total_market_value <- market_cap + market_value_of_debt
weight_of_debt <- market_value_of_debt / total_market_value
weight_of_equity <- market_cap / total_market_value

cat("cost of debt:",cost_of_debt, "\n")
cost of debt: 0.0425 
cat("cost of equity",cost_of_equity, "\n")
cost of equity 0.1115 
cat("weight of debt:",weight_of_debt, "\n")
weight of debt: 0.01123569 
cat("weight of equity:",weight_of_equity)
weight of equity: 0.9887643
wacc <- (weight_of_debt * cost_of_debt * (1 - tax_rate)) + (weight_of_equity * cost_of_equity)
cat("WACC for Tesla:", wacc * 100, "%")
WACC for Tesla: 11.06197 %

L11 Derivatives

  • Assume that you purchased an S&P 500 futures contract at the beginning of the school term, with the first settlement date beyond the end of the school term. Also assume that you sold an S&P 500 futures contract with this same settlement date at the end of the school term. Given that this contract has a value of the futures price times $250, determine the difference between the dollar value of the contract you sold and the dollar amount of the contract that you purchased.
buy_price <- 4000
sell_price <- 4200
contract_multiplier <- 250
inital_margin <- 0.20 * (buy_price * contract_multiplier)
months_in_term <- 5

gain_loss <- (sell_price - buy_price) * contract_multiplier
print(gain_loss)
[1] 50000
  • Assume that you invested an initial margin of 20 percent of the amount that you would owe to purchase the S&P 500 index at the settlement date. Measure your return from taking a position in the S&P 500 index futures as follows. Take the difference determined in the previous question (which represents the dollar amount of the gain on the futures position) and divide it by the amount you originally invested (the amount you originally invested is 20 percent of the dollar value of the futures contract that you purchased).

return <- gain_loss / inital_margin
print(return)
[1] 0.25
  • The return that you just derived in the previous question is not annualized. To annualize your return, multiply it by 12/m, where m is the number of months in your school term.

We calculate the gain/ loss, return, and annualized return for S&P 500 futures contract.



annualized_return <- return * (12 / months_in_term)

cat("Gain/Loss on Futures Contract : $", gain_loss, "\n")
Gain/Loss on Futures Contract : $ 50000 
cat("Return: ", round(return * 100, 2), "%\n")
Return:  25 %
cat("Annualized Return: ", round(annualized_return * 100, 2), "%\n")
Annualized Return:  60 %
  • Assume that you purchased a call option (representing 100 shares) on the specific stock that you identified of this project. What was your return from purchasing this option? If the premium for this option is not quoted at the end of the school term, measure the return as if you had exercised the call option at the end of the school term (assuming that it is feasible to exercise the option at that time). That is, the return is based on purchasing the stock at the option’s strike price and then selling the stock at its market price at the end of the school term.

  • Annualize the return on your option by multiplying the return you derived in the previous question by 12/m, where m represents the number of months in your school term

  • Compare the return on your call option to the return that you would have earned if you had simply invested in the stock itself. Notice how the magnitude of the return on the call option is much larger than the magnitude of the return on the stock itself. That is, the gains are larger and the losses are larger when investing in call options on a stock instead of the stock itself.

We calculate the return on a call option and analyze the results.

buy_premium <- 20
sell_premium <- 30
strike_price <- 400
stock_price_end <- 450
months_in_term <- 5 

call_return <- (sell_premium - buy_premium) / buy_premium

exercise_return <- (stock_price_end - strike_price) / buy_premium

annualized_call_return <- call_return * (12 / months_in_term)

cat("Call Option Return: ", round(call_return * 100, 2), "%\n")
Call Option Return:  50 %
cat("Exercise Return: ", round(annualized_call_return * 100, 2), "%\n")
Exercise Return:  120 %
cat("Annualized Call Return: ", round(annualized_call_return * 100, 2), "%\n")
Annualized Call Return:  120 %

Determining swap payments

  • Assume that, at the beginning of the school term, you engaged in a fixed-for-floating rate swap in which you agreed to pay 6 percent in exchange for the prevailing 26-week T-bill rate that exists at the end of the school term. Assume that your swap agreement specifies the end of the school term as the only time at which a swap will occur and that the notional amount is $10 million. Determine the amount that you owe on the swap, the amount you are owed on the swap, and the difference. Did you gain or lose as a result of the swap?

We calculate the fixed and floating payments for a swap agreement.

notional_amount <- 10e6
fixed_rate <- 0.06
floating_rate_end <- 0.055

fixed_payment <- notional_amount * fixed_rate
floating_payment <- notional_amount * floating_rate_end
net_payment <- fixed_payment - floating_payment

cat("Fixed Payment: $", fixed_payment, "\n")
Fixed Payment: $ 6e+05 
cat("Floating Payment: $", floating_payment, "\n")
Floating Payment: $ 550000 
cat("Net Payment: $", net_payment, "\n")
Net Payment: $ 50000 

Measuring and explaining exchange rate movements

  • Determine the percentage change in the value of the British pound over the school term. Did the pound appreciate or depreciate against the dollar?

  • Determine the percentage change in the value of the Japanese yen over the school term. Did the yen appreciate or depreciate against the dollar?

  • Determine the percentage change in the value of the Mexican peso over the school term. Did the peso appreciate or depreciate against the dollar?

  • Determine the per unit gain or loss if you had purchased British pound futures at the beginning of the term and sold British pound futures at the end of the term.

  • Given that a single futures contract on British pounds represents 62,500 pounds, determine the dollar amount of your gain or loss.

We calculate the percentage change and gain/ loss for GBP/ USD futures.

start_rate_gpd <- 1.2
end_rate_gpd <- 1.25
contract_size_gbp <- 62500

percent_change_gpd <- ((end_rate_gpd - start_rate_gpd) / start_rate_gpd) * 100

gain_loss_per_unit_gpd <- end_rate_gpd - start_rate_gpd
total_gain_loss_gpd <- gain_loss_per_unit_gpd * contract_size_gbp

cat("GBP Percantage Change: ", round(percent_change_gpd,2), "%\n")
GBP Percantage Change:  4.17 %
cat("Total Gain/Loss on GBP Futures Contract: $", round(total_gain_loss_gpd,2), "%\n")
Total Gain/Loss on GBP Futures Contract: $ 3125 %

L12 Capital requirements

Operational Risk

We calculate the operational risk capital for Bank of America (BoA) and Deutsche Bank (DB) using the Basic Indicator Approach under Basel III:


alpha <- 0.15
gross_income_boa <- 90e9 
gross_income_db <- 25e9 * 1.1 

operational_risk_boa <- alpha * gross_income_boa
operational_risk_db <- alpha * gross_income_db


cat("Operational Risk Capital (BoA): $", format(operational_risk_boa, big.mark = ","), "\n")
Operational Risk Capital (BoA): $ 1.35e+10 
cat("Operational Risk Capital (DB): $", format(operational_risk_db, big.mark = ","), "\n")
Operational Risk Capital (DB): $ 4.125e+09 

We calculate the market risk capital using the Value at risk (VaR) approach:

k <- 3 
var_boa <- 5e9
var_db <- 3e9 * 1.1 

market_risk_boa <- k * var_boa
market_risk_db <- k * var_db

cat("Market Risk Capital (BoA): $", format(market_risk_boa, big.mark = ","), "\n")
Market Risk Capital (BoA): $ 1.5e+10 
cat("Market Risk Capital (DB): $", format(market_risk_db, big.mark = ","), "\n")
Market Risk Capital (DB): $ 9.9e+09 

We calculate credit risk capital based on the exposure amounts, risk weights, and regulatory capital requirements

regulatory_capital_requirement <- 0.08 


loan_exposure_boa <- 200e9
gov_securities_boa <- 50e9
loan_exposure_db <- 150e9 * 1.1 
gov_securities_db <- 40e9 * 1.1

loan_risk_weight <- 1.00 
gov_risk_weight <- 0.00  

credit_risk_boa <- regulatory_capital_requirement * (loan_exposure_boa * loan_risk_weight + gov_securities_boa * gov_risk_weight)
credit_risk_db <- regulatory_capital_requirement * (loan_exposure_db * loan_risk_weight + gov_securities_db * gov_risk_weight)

cat("Credit Risk Capital (BoA): $", format(credit_risk_boa, big.mark = ","), "\n")
Credit Risk Capital (BoA): $ 1.6e+10 
cat("Credit Risk Capital (DB): $", format(credit_risk_db, big.mark = ","), "\n")
Credit Risk Capital (DB): $ 1.32e+10 

We calculate the total capital requirements for each bank by summing operational, market, and credit risk capitals.

total_capital_boa <- operational_risk_boa + market_risk_boa + credit_risk_boa
total_capital_db <- operational_risk_db + market_risk_db + credit_risk_db

cat("Total Capital Requirement (BoA): $", format(total_capital_boa, big.mark = ","), "\n")
Total Capital Requirement (BoA): $ 4.45e+10 
cat("Total Capital Requirement (DB): $", format(total_capital_db, big.mark = ","),"\n")
Total Capital Requirement (DB): $ 2.7225e+10 
LS0tCnRpdGxlOiAiRmluYW5jaWFsIE1hcmtldHM6IE9ibGlnYXRvcnkgZXhlcmNpc2UiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBSZXBvcnQKCiMjIFRlYW0KClBhdWxhIE1vbG9uZXksIFNwYWluCgpDYW1pbGEgZGUgbGEgQ3J1eiwgUGVydQoKS2xhdXMgTGluZGVtYW5uLCBQb2xhbmQKCiMjIFN0YXRlbWVudAoKUGF1bGE6CgpXb3JrZWQgb24gTDQsIEw3LUw4CgpDYW1pbGE6CgpXb3JrZWQgb24gTDEtTDEwLiBJIGxldmVyYWdlIEFJLXBvd2VyZWQgdG9vbHMgbGlrZSBDaGF0R1BUIGFzIGEgc3RhcnRpbmcgcG9pbnQgZm9yIGNvZGUgc3RydWN0dXJlIGFuZCBkYXRhIG9yZ2FuaXphdGlvbiwgc3VjaCBhcyBjcmVhdGluZyBmdW5jdGlvbnMgdG8gZXh0cmFjdCBkYXRhIGZyb20gdGFibGVzLiBIb3dldmVyLCBJIGNvbnNpc3RlbnRseSByZWZpbmUgYW5kIGVuaGFuY2UgdGhlIGNvZGUsIGluY29ycG9yYXRpbmcgbXkgcGVyc29uYWwgY29kaW5nIHN0eWxlIGFuZCBleHBlcnRpc2UgKGZvciBleGFtcGxlIEkgZmlndXJlZCBpdCBvdXQgaG93IHRvIGNoYW5nZSB0aGUgZnVuY3Rpb24gdG8gZG93bmxvYWQgZmluYW5jaWFsIHN0YXRlbWVudHMgYWZ0ZXIgMjAwNikuCgpLbGF1czoKCldvcmtlZCBvbiBMOS1MMTIuIEFzIHNvbWVvbmUgd2l0aCBsaW1pdGVkIHByaW9yIGV4cGVyaWVuY2UgaW4gY29kaW5nIGFuZCBmaW5hbmNpYWwgYW5hbHlzaXMsIEkgcmVsaWVkIG9uIEFJIHRvb2xzIGxpa2UgQ2hhdEdQVCB0byBhIGdyZWF0ZXIgZXh0ZW50IHRoYW4gb3RoZXJzIGluIHRoZSBncm91cCB0byBjb21wbGV0ZSBteSBwb3J0aW9uIG9mIHRoaXMgcHJvamVjdC4gVGhlIEFJIHByb3ZpZGVkIGd1aWRhbmNlIG9uIGNvZGluZyBwcmFjdGljZXMsIGRlYnVnZ2luZyBlcnJvcnMsIGFuZCBzdHJ1Y3R1cmluZyBSIHNjcmlwdHMgZm9yIHRhc2tzIGxpa2UgcG9ydGZvbGlvIG9wdGltaXphdGlvbiwgV0FDQyBjYWxjdWxhdGlvbnMsIGFuZCBkZXJpdmF0aXZlcyBhbmFseXNpcy4gSSB1c2VkIEFJIHByaW1hcmlseSBhcyBhIGxlYXJuaW5nIHRvb2wgdG8gdW5kZXJzdGFuZCB0aGUgY29uY2VwdHMgYW5kIHRyYW5zbGF0ZSB0aGVvcmV0aWNhbCBrbm93bGVkZ2UgaW50byBwcmFjdGljYWwgaW1wbGVtZW50YXRpb24uIFdoaWxlIEkgYWN0aXZlbHkgZW5nYWdlZCB3aXRoIHRoZSBtYXRlcmlhbCwgd3JvdGUgY29kZSwgYW5kIHJlZmluZWQgb3V0cHV0cywgdGhlIEFJIHNlcnZlZCBhcyBhbiBhc3Npc3RhbnQgdG8gYnJpZGdlIHRoZSBnYXAgaW4gbXkgdGVjaG5pY2FsIHNraWxscyBhbmQgZW5zdXJlIEkgY291bGQgY29udHJpYnV0ZSBlZmZlY3RpdmVseSB0byB0aGUgcHJvamVjdC4gVGhpcyBleHBlcmllbmNlIGhhcyBoZWxwZWQgbWUgZGV2ZWxvcCBhIGZvdW5kYXRpb25hbCB1bmRlcnN0YW5kaW5nIG9mIGNvZGluZyBhbmQgZmluYW5jaWFsIGFuYWx5c2lzLCB3aGljaCBJIGFpbSB0byBidWlsZCB1cG9uIGluIGZ1dHVyZcKgcHJvamVjdHMuCgojIyBMMSBCYXNpYyBwYXJhbWV0ZXJzIG9mIHRoZSBtYXJrZXRzCgpGaXJzdCB3ZSB3aWxsIGluc3RhbGwgYW5kIHRoZW4gY2FsbGVkIHRoZSBsaWJyYXJ5ICdxdWFudG1vZCcgdG8gZG93bmxvYWQgdGhlIGFzc2V0cyBwcmljZXMuCgpgYGB7cn0KIyBRdWFudG1vZAoKCmxpYnJhcnkocXVhbnRtb2QpCmxpYnJhcnkobHVicmlkYXRlKQoKYGBgCgpXZSB3aWxsIGRlZmluZSB0aGUgYmVnaW5uaW5nIG9mIHRlcm0gcGVyaW9kIChCb1QpIGFzIG9mIE1hcmNoIDFzdCBhbmQgdGhlIGVuZCAoRW9UKSBhcyBOb3ZlbWJlciAyMHRoLgoKYGBge3J9CiNEZWZpbmUgdGltZSBwZXJpb2QKCkJvVCA8LSBhcy5EYXRlKCIyMDI0LTAzLTAxIikgCkVvVCA8LSBhcy5EYXRlKCIyMDI0LTExLTIyIikKCmNhdCgiQmVnaW5uaW5nIG9mIHRoZSBwZXJpb2Q6IiwgZm9ybWF0KEJvVCksICJcbiIpCmNhdCgiRW5kaW5nIG9mIHRoZSBwZXJpb2Q6IiwgZm9ybWF0KEVvVCkpCgpgYGAKCi0gICAqQmFzaWMgcGFyYW1ldGVycyBvZiB0aGUgbWFya2V0KgoKYGBge3J9CmJhc2ljX3BhcmFtIDwtIGRhdGEuZnJhbWUoCiAgRGVzY3JpcHRpb24gPSBjaGFyYWN0ZXIoKSwKICBCZWdpbm5pbmdfb2ZfVGVybSA9IGNoYXJhY3RlcigpLAogIEVuZF9vZl9UZXJtID0gY2hhcmFjdGVyKCkKKQoKCmFkZF9yb3cgPC0gZnVuY3Rpb24oY2F0ZWdvcnksIHN5bWJvbCkgewogIGRhdGEgPC0gZ2V0U3ltYm9scyhzeW1ib2wsIGZyb209Qm9ULCB0bz1Fb1QrMiwgYXV0by5hc3NpZ24gPSBGQUxTRSkKICBkYXRhIDwtIGRhdGFbIWlzLm5hKGRhdGFbLCAxXSksIF0KICBiYXNpY19wYXJhbSA8PC0gcmJpbmQoYmFzaWNfcGFyYW0sIGRhdGEuZnJhbWUoCiAgICBEZXNjcmlwdGlvbiA9IGNhdGVnb3J5LAogICAgQm9UID0gYXMubnVtZXJpYyhDbChkYXRhKVt3aGljaChpbmRleChkYXRhKSA9PSBCb1QpXSksCiAgICBFb1QgPSBhcy5udW1lcmljKENsKGRhdGEpW3doaWNoKGluZGV4KGRhdGEpID09IEVvVCldKQogICkpCn0KCgphZGRfcm93KCJTJlAgNTAwIChzdG9jaykgaW5kZXggbGV2ZWwiLCJeR1NQQyIgKQphZGRfcm93KCJOYXNkYXEgQ29tcG9zaXRlIChzdG9jaykgaW5kZXggbGV2ZWwiLCJeSVhJQyIgKQoKYWRkX3JvdyA8LSBmdW5jdGlvbihjYXRlZ29yeSwgc3ltYm9sKSB7CiAgZGF0YSA8LSBnZXRTeW1ib2xzKHN5bWJvbCwgZnJvbT1Cb1QsIHRvPUVvVCsyLHNyYz0iRlJFRCIsIGF1dG8uYXNzaWduID0gRkFMU0UpCiAgZGF0YSA8LSBkYXRhWyFpcy5uYShkYXRhWywgMV0pLCBdCiAgYmFzaWNfcGFyYW0gPDwtIHJiaW5kKGJhc2ljX3BhcmFtLCBkYXRhLmZyYW1lKAogICAgRGVzY3JpcHRpb24gPSBjYXRlZ29yeSwKICAgIEJvVCA9IGFzLm51bWVyaWMoZGF0YVt3aGljaC5taW4oYWJzKGluZGV4KGRhdGEpIC0gQm9UKSksIDFdKSwKICAgIEVvVCA9IGFzLm51bWVyaWMoZGF0YVt3aGljaC5taW4oYWJzKGluZGV4KGRhdGEpIC0gRW9UKSksIDFdKQogICkpCn0KYWRkX3JvdygiUHJpbWUgcmF0ZSIsIklSMTQyMjAiICkKYWRkX3JvdygiRmVkZXJhbCBmdW5kcyByYXRlIiwiRkVERlVORFMiICkKYWRkX3JvdygiQ29tbWVyY2lhbCBwYXBlciByYXRlICg5MCBkYXlzKSIsIlJJRlNQUEZBQUQ5ME5CIiApCmFkZF9yb3coIkNlcnRpZmljYXRlIG9mIGRlcG9zaXQgcmF0ZSAoMy1tb250aCkiLCJUWTNNQ0QiICkKYWRkX3JvdygiVHJlYXN1cnkgYmlsbCByYXRlICgzLW1vbnRoKSIsIkRUQjMiICkKYWRkX3JvdygiVHJlYXN1cnkgYmlsbCByYXRlICg2LW1vbnRoKSIsIkRUQjYiICkKYWRkX3JvdygiVHJlYXN1cnkgbG9uZy10ZXJtIGJvbmQgeWllbGQiLCJETFRJSVQiICkKYWRkX3JvdygiQ29ycG9yYXRlIChNYXN0ZXIpIGJvbmQgeWllbGQiLCJEQUFBIiApCmFkZF9yb3coIkhpZ2gteWllbGQgY29ycG9yYXRlIGJvbmQgeWllbGQiLCJCQU1MSDBBMEhZTTJFWSIgKQphZGRfcm93KCJUYXgtZXhlbXB0ICg34oCTMTIteWVhcikgYm9uZCB5aWVsZCIsIklSTFRMVDAxVVNNMTU2TiIgKQoKCgoKcHJpbnQoYmFzaWNfcGFyYW0pCmBgYAoKKEV4cGxhaW4gdGhlIGFzc3VtcHRpb25zKQoKLSAgICpVc2Ugc3RvY2sgZXhjaGFuZ2UgcXVvdGF0aW9ucyB0byByZWNvcmQgdGhlIHN0b2NrIHByaWNlIGFuZCBkaXZpZGVuZCBvZiBvbmUgc3RvY2sgZnJvbSBlYWNoIHN0b2NrIGV4Y2hhbmdlIGluIHdoaWNoIHlvdSB3b3VsZCBsaWtlIHRvIGludmVzdC4qCgpXZSB3aWxsIHNlbGVjdCB0byBzdG9ja3MgaW4gZGlmZmVyZW50IHN0b2NrIG1hcmtldHMgdG8gcmVjb3JkIHRoZSBzdG9jayBwcmljZSBhbmQgZGl2aWRlbmQKCjEpICBQS08gQmFuayBQb2xza2kgKFBLTykgaW4gdGhlIFdhcnNhdyBTdG9jayBFeGNoYW5nZSAoV1NFKS4KCjIpICBUZXNsYSAoVFNMQSkgaW4gdGhlIE5ldyBZb3JrIFN0b2NrIEV4Y2hhbmdlIChOWVNDKQoKV2Ugd2lsbCBub3cgZ2V0IHRoZSBwcmljZXMgZHVyaW5nIHRoZSBhbmFseXNpcyBwZXJpb2QgZnJvbSBZYWhvbyBGaW5hbmNlLgoKYGBge3J9CiNIaXN0b3JpY2FsIGRhdGEgcHJpY2VzIGZyb20gdGhlIHRhcmdldCB0aW1lIHJhbmdlCgpnZXRTeW1ib2xzKCJQS08uV0EiLGZyb209Qm9ULCB0bz1Fb1QrMikKZ2V0U3ltYm9scygiVFNNIixmcm9tPUJvVCwgdG89RW9UKzIpCgoKI0V4dHJhY3QgdGhlIGNsb3NlIHByaWNlcyBvZiB0aGUgdGFyZ2V0IGRhdGVzCgpwa29fYl9wcmljZSA8LSBDbChQS08uV0FbQm9UXSkKcGtvX2VfcHJpY2UgPC0gQ2woUEtPLldBW0VvVF0pCgp0c21fYl9wcmljZSA8LSBDbChUU01bQm9UXSkKdHNtX2VfcHJpY2UgPC0gQ2woVFNNW0VvVF0pCgpgYGAKClRvIHZpc3VhbGl6ZSB0aGUgZGF0YToKCmBgYHtyfQpWaWV3KFBLTy5XQSkKVmlldyhUU00pCmBgYAoKYGBge3J9CmNoYXJ0U2VyaWVzKENsKFBLTy5XQSksdGhlbWU9IndoaXRlIikKY2hhcnRTZXJpZXMoQ2woVFNNKSx0aGVtZT0id2hpdGUiKQpgYGAKClRoZW4sIHdlIHdpbGwgZ2V0IHRoZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGl2aWRlbmRzIG9uIGVhY2ggc3RvY2suCgpgYGB7cn0KI0hpc3RvcmljYWwgZGF0YSBvZiBkaXZpZGVuZHMgCgpwa29fZGl2IDwtIGdldERpdmlkZW5kcygiUEtPLldBIikKdHNtX2RpdiA8LSBnZXREaXZpZGVuZHMoIlRTTSIpCgojRXh0cmFjdCB0aGUgb25lcyB0aGF0IGFyZSBjbG9zZXMgYnV0IGJlZm9yZSB0aGUgdGFyZ2V0IGRhdGUKCnBrb19iX2RpdiA8LSBwa29fZGl2W3doaWNoLm1pbihhYnMoaW5kZXgocGtvX2RpdikgLSBCb1QpKV0KcGtvX2VfZGl2IDwtIHBrb19kaXZbd2hpY2gubWluKGFicyhpbmRleChwa29fZGl2KSAtIEVvVCkpXQoKdHNtX2JfZGl2IDwtIHRzbV9kaXZbd2hpY2gubWluKGFicyhpbmRleCh0c21fZGl2KSAtIEJvVCkpXQp0c21fZV9kaXYgPC0gdHNtX2Rpdlt3aGljaC5taW4oYWJzKGluZGV4KHRzbV9kaXYpIC0gRW9UKSldCgpgYGAKCldlIHNlZSB0aGF0IG5laXRoZXIgb2YgZWFjaCBzdG9jayBkaXN0cmlidXRlIGRpdmlkZW5kcyBkdXJpbmcgdGhlIHRoaXMgc3BlY2lmaWMgdGltZSByYW5nZS4KCmBgYHtyfQojIENyZWF0ZSB0aGUgZGF0YSBmcmFtZQpzdG9ja190YWJsZSA8LSBkYXRhLmZyYW1lKAogIERlc2NyaXB0aW9uID0gYygKICAgICJXU0U6IFBLTyBTdG9jayBwcmljZSIsCiAgICAiUEtPIERpdmlkZW5kIiwKICAgICJOWVNFOiBUU00gU3RvY2sgcHJpY2UiLAogICAgIlRTTSBEaXZpZGVuZCIKICApLAogIEJvVCA9IE5BLCAgCiAgRW9UID0gTkEgIAopCgpWaWV3KHN0b2NrX3RhYmxlKQoKCiNGaWxsIHdpdGggZGF0YQpzdG9ja190YWJsZVsxLCAyXSA8LSBwa29fYl9wcmljZQpzdG9ja190YWJsZVsxLCAzXSA8LSBwa29fZV9wcmljZQoKc3RvY2tfdGFibGVbMiwgMl0gPC0gcGtvX2JfZGl2CnN0b2NrX3RhYmxlWzIsIDNdIDwtIHBrb19lX2RpdgoKc3RvY2tfdGFibGVbMywgMl0gPC0gdHNtX2JfcHJpY2UKc3RvY2tfdGFibGVbMywgM10gPC0gdHNtX2VfcHJpY2UKCnN0b2NrX3RhYmxlWzQsIDJdIDwtIHRzbV9iX2RpdgpzdG9ja190YWJsZVs0LCAzXSA8LSB0c21fZV9kaXYKCnByaW50KHN0b2NrX3RhYmxlKQoKYGBgCgotICAgKlVzZSBmdXR1cmVzIHByaWNlcyBxdW90YXRpb25zIHRvIHJlY29yZCB0aGUgcmVjZW50ICjigJxzZXR0bGXigJ0pIHByaWNlIG9mIHRoZSBmb2xsb3dpbmcgZnV0dXJlcyAoc2VsZWN0IGZ1dHVyZXMgd2l0aCBmaXJzdCBzZXR0bGVtZW50IGRhdGUgYmV5b25kIHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtKS4qCgpGaXJzdCB3ZSB3aWxsIGxvb2sgZm9yIHRoZSB0aWNrZXJzIG9mIGVhY2ggZnV0dXJlIGluIHlhaG9vIGZpbmFuY2UuCgpgYGB7cn0KI0hpc3RvcmljYWwgZGF0YSBvZiB0aGUgZnV0dXJlcwoKc3A1MDBfZiA8LSBnZXRTeW1ib2xzKCJFUz1GIiwgZnJvbT0gQm9ULCB0bz1Fb1QrMiwgYXV0by5hc3NpZ24gPSBGKQpuYXNkYXFfZiA8LSBnZXRTeW1ib2xzKCJOUT1GIiwgZnJvbT0gQm9ULCB0bz1Fb1QrMiwgYXV0by5hc3NpZ24gPSBGKQp0cmVhc3VyeV9mIDwtIGdldFN5bWJvbHMoIlpCPUYiLCBmcm9tPSBCb1QsIHRvPUVvVCsyLCBhdXRvLmFzc2lnbiA9IEYpCmJyaXRpc2hfZiA8LSBnZXRTeW1ib2xzKCI2Qj1GIiwgZnJvbT0gQm9ULCB0bz1Fb1QrMiwgYXV0by5hc3NpZ24gPSBGKQoKYGBgCgpOb3cgd2UgY3JlYXRlIHRoZSB0YWJsZSBhbmQgdGhlbiB3ZSBmaWxsIGl0LgoKYGBge3J9CiMgQ3JlYXRlIHRoZSBkYXRhIGZyYW1lCmZ1dHVyZXNfdGFibGUgPC0gZGF0YS5mcmFtZSgKICBEZXNjcmlwdGlvbiA9IGMoCiAgICAiVHJlYXN1cnkgYm9uZCBmdXR1cmVzIiwKICAgICJTJlA1MDAgaW5kZXggZnV0dXJlcyIsCiAgICAiTkFTREFRIGluZGV4IGZ1dHVyZXMiLAogICAgIkJyaXRpc2ggcG91bmRzIGZ1dHVyZXMiCiAgKSwKICBCb1QgPSBOQSwgIAogIEVvVCA9IE5BICAgCikKCgoKI0ZpbGwgd2l0aCBkYXRhCnN5bWJvbHMgPC0gbGlzdCh0cmVhc3VyeV9mLCBzcDUwMF9mLCBuYXNkYXFfZiwgYnJpdGlzaF9mKQpyb3dzIDwtIDE6NCAgIyBSb3cgaW5kaWNlcyBpbiBmdXR1cmVzX3RhYmxlIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHN5bWJvbHMKCiMgTG9vcCB0aHJvdWdoIGVhY2ggc3ltYm9sIGFuZCByb3cKZm9yIChpIGluIHNlcV9hbG9uZyhzeW1ib2xzKSkgewogICMgRXh0cmFjdCB0aGUgc3ltYm9sIGFuZCBpdHMgY29ycmVzcG9uZGluZyByb3cKICBzeW1ib2wgPC0gc3ltYm9sc1tbaV1dCiAgcm93IDwtIHJvd3NbaV0KICAKICAjIEFzc2lnbiBjbG9zaW5nIHByaWNlcyBmb3IgQm9UIGFuZCBFb1QKICBmdXR1cmVzX3RhYmxlW3JvdywgMl0gPC0gQ2woc3ltYm9sW0JvVF0pCiAgZnV0dXJlc190YWJsZVtyb3csIDNdIDwtIENsKHN5bWJvbFtFb1RdKQp9CgoKcHJpbnQoZnV0dXJlc190YWJsZSkKYGBgCgotICAgKlVzZSBhbiBvcHRpb25zIHF1b3RhdGlvbnMgdGFibGUgdG8gc2VsZWN0IGEgY2FsbCBvcHRpb24gb24gYSBmaXJtIHdob3NlIHN0b2NrIHByaWNlIHlvdSBleHBlY3QgdG8gaW5jcmVhc2UgKHNlbGVjdCB0aGUgb3B0aW9uIHdpdGggdGhlIGZpcnN0IGV4cGlyYXRpb24gbW9udGggYmV5b25kIHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtKS4qCgpgYGB7cn0KCmNhdCgiTmFtZSBvZiB0aGUgZmlybTogIiwgIlRlc2xhIiwgIlxuIikKY2F0KCJFeHBpcmF0aW9uIG1vbnRoOiIsICIyMDI0LTExLTI5IiwgIlxuIikKY2F0KCJTdHJpa2UgcHJpY2U6IiwgMzM1ICwgIlxuIikKCmNhbGxfdGFiIDwtIGRhdGEuZnJhbWUoCiAgRGVzY3JpcHRpb24gPSBjaGFyYWN0ZXIoKSwKICBCZWdpbm5pbmdfb2ZfVGVybSA9IGNoYXJhY3RlcigpLAogIEVuZF9vZl9UZXJtID0gY2hhcmFjdGVyKCkKKQoKCmFkZF9yb3cgPC0gZnVuY3Rpb24oY2F0ZWdvcnksIHN5bWJvbCkgewogIGRhdGEgPC0gZ2V0U3ltYm9scyhzeW1ib2wsIGZyb209Qm9ULCB0bz1Fb1QrMiwgYXV0by5hc3NpZ24gPSBGQUxTRSkKICBjYWxsX3RhYiA8PC0gcmJpbmQoY2FsbF90YWIsIGRhdGEuZnJhbWUoCiAgICBEZXNjcmlwdGlvbiA9IGNhdGVnb3J5LAogICAgQm9UID0gYXMubnVtZXJpYyhDbChkYXRhKVt3aGljaC5taW4oYWJzKGluZGV4KGRhdGEpIC0gQm9UKSldKSwKICAgIEVvVCA9IGFzLm51bWVyaWMoQ2woZGF0YSlbd2hpY2gubWluKGFicyhpbmRleChkYXRhKSAtIEVvVCkpXSkKICApKQp9CgoKYWRkX3JvdygiU3RvY2sgcHJpY2UiLCJUU0xBIiApCmFkZF9yb3coIk9wdGlvbiBwcmVtaXVtIiwiVFNMQTI0MTIwNkMwMDMzNTAwMCIgKQoKcHJpbnQoY2FsbF90YWIpCgpgYGAKCi0gICAqVXNlIGFuIG9wdGlvbnMgcXVvdGF0aW9ucyB0YWJsZSB0byBzZWxlY3QgYSBwdXQgb3B0aW9uIG9uIGEgZmlybSB3aGVyZSB5b3UgZXhwZWN0IHRoZSBzdG9jayBwcmljZSB0byBkZWNyZWFzZSAoc2VsZWN0IHRoZSBvcHRpb24gd2l0aCB0aGUgZmlyc3QgZXhwaXJhdGlvbiBtb250aCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0pKgoKYGBge3J9CmNhdCgiTmFtZSBvZiB0aGUgZmlybTogIiwgIk5WSURJQSIsICJcbiIpCmNhdCgiRXhwaXJhdGlvbiBtb250aDoiLCAiMjAyNC0xMS0yOSIsICJcbiIpCmNhdCgiU3RyaWtlIHByaWNlOiIsIDEzMCAsICJcbiIpCmBgYAoKYGBge3J9CgpwdXRfdGFiIDwtIGRhdGEuZnJhbWUoCiAgRGVzY3JpcHRpb24gPSBjaGFyYWN0ZXIoKSwKICBCZWdpbm5pbmdfb2ZfVGVybSA9IGNoYXJhY3RlcigpLAogIEVuZF9vZl9UZXJtID0gY2hhcmFjdGVyKCkKKQoKCmFkZF9yb3cgPC0gZnVuY3Rpb24oY2F0ZWdvcnksIHN5bWJvbCkgewogIGRhdGEgPC0gZ2V0U3ltYm9scyhzeW1ib2wsIGZyb209Qm9ULCB0bz1Fb1QrMiwgYXV0by5hc3NpZ24gPSBGQUxTRSkKICBwdXRfdGFiIDw8LSByYmluZChwdXRfdGFiLCBkYXRhLmZyYW1lKAogICAgRGVzY3JpcHRpb24gPSBjYXRlZ29yeSwKICAgIEJvVCA9IGFzLm51bWVyaWMoQ2woZGF0YSlbd2hpY2gubWluKGFicyhpbmRleChkYXRhKSAtIEJvVCkpXSksCiAgICBFb1QgPSBhcy5udW1lcmljKENsKGRhdGEpW3doaWNoLm1pbihhYnMoaW5kZXgoZGF0YSkgLSBFb1QpKV0pCiAgKSkKfQoKCmFkZF9yb3coIlN0b2NrIHByaWNlIiwiTlZEQSIgKQphZGRfcm93KCJPcHRpb24gcHJlbWl1bSIsIk5WREEyNDExMjlQMDAxMzAwMDAiICkKCnByaW50KHB1dF90YWIpCmBgYAoKLSAgICpVc2UgYSBjdXJyZW5jeSBleGNoYW5nZSByYXRlIHRhYmxlIHRvIHJlY29yZCBleGNoYW5nZSByYXRlcy4qCgpgYGB7cn0KY3VycmVuY3lfdGFiIDwtIGRhdGEuZnJhbWUoCiAgRGVzY3JpcHRpb24gPSBjaGFyYWN0ZXIoKSwKICBCZWdpbm5pbmdfb2ZfVGVybSA9IGNoYXJhY3RlcigpLAogIEVuZF9vZl9UZXJtID0gY2hhcmFjdGVyKCkKKQoKCmFkZF9yb3cgPC0gZnVuY3Rpb24oY2F0ZWdvcnksIHN5bWJvbCkgewogIGRhdGEgPC0gZ2V0U3ltYm9scyhzeW1ib2wsIGZyb209Qm9ULCB0bz1Fb1QrMiwgYXV0by5hc3NpZ24gPSBGQUxTRSkKICBjdXJyZW5jeV90YWIgPDwtIHJiaW5kKGN1cnJlbmN5X3RhYiwgZGF0YS5mcmFtZSgKICAgIERlc2NyaXB0aW9uID0gY2F0ZWdvcnksCiAgICBCb1QgPSBhcy5udW1lcmljKENsKGRhdGEpW3doaWNoLm1pbihhYnMoaW5kZXgoZGF0YSkgLSBCb1QpKV0pLAogICAgRW9UID0gYXMubnVtZXJpYyhDbChkYXRhKVt3aGljaC5taW4oYWJzKGluZGV4KGRhdGEpIC0gRW9UKSldKQogICkpCn0KCgphZGRfcm93KCJFeGNoYW5nZSByYXRlIG9mIHRoZSBCcml0aXNoIHBvdW5kIChpbiAkKSIsIkdCUFVTRD1YIiApCmFkZF9yb3coIkV4Y2hhbmdlIHJhdGUgb2YgdGhlIEphcGFuZXNlIHllbiAoaW4gJCkiLCJKUFk9WCIgKQphZGRfcm93KCJFeGNoYW5nZSByYXRlIG9mIHRoZSBNZXhpY2FuIHBlc28gKGluICQpIiwiTVhOPVgiICkKCnByaW50KGN1cnJlbmN5X3RhYikKCmBgYAoKLSAgICpVc2UgY3VycmVuY3kgb3B0aW9ucyBkYXRhIChpZiBhdmFpbGFibGUpIHRvIHNlbGVjdCBhIGNhbGwgb3B0aW9uIG9uIGEgZm9yZWlnbiBjdXJyZW5jeSB0aGF0IHlvdSBleHBlY3Qgd2lsbCBzdHJlbmd0aGVuIGFnYWluc3QgdGhlIGRvbGxhciAoc2VsZWN0IHRoZSBvcHRpb24gd2l0aCB0aGUgZmlyc3QgZXhwaXJhdGlvbiBtb250aCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0pLioKCjwhLS0gLS0+CgotICAgKlVzZSBjdXJyZW5jeSBvcHRpb25zIGRhdGEgKGlmIGF2YWlsYWJsZSkgdG8gc2VsZWN0IGEgcHV0IG9wdGlvbiBvbiBhIGZvcmVpZ24gY3VycmVuY3kgdGhhdCB5b3UgZXhwZWN0IHdpbGwgd2Vha2VuIGFnYWluc3QgdGhlIGRvbGxhciAoc2VsZWN0IHRoZSBvcHRpb24gd2l0aCB0aGUgZmlyc3QgZXhwaXJhdGlvbiBtb250aCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0pLioKCkkgZGlkbid0IGZpbmQgaW5mb3JtYXRpb24gYWJvdXQgY2FsbCBvciBwdXQgb3B0aW9ucywganVzdCBmb3J3YXJkIGV4Y2hhbmdlIHJhdGVzLgoKYGBge3J9CmNhdCgiQ3VycmVuY3k6ICIsICJKYXBhbmVzZSBZZW4iLCAiXG4iKQpjYXQoIkV4cGlyYXRpb24gbW9udGg6IiwgIjIwMjQtMTItMDQiLCAiXG4iKQpjYXQoIlN0cmlrZSBwcmljZToiLCAxNTEuNjIgLCAiXG4iKQoKY3VycmVuY3lfdGFiIDwtIGRhdGEuZnJhbWUoCiAgRGVzY3JpcHRpb24gPSBjaGFyYWN0ZXIoKSwKICBCZWdpbm5pbmdfb2ZfVGVybSA9IGNoYXJhY3RlcigpLAogIEVuZF9vZl9UZXJtID0gY2hhcmFjdGVyKCkKKQoKYWRkX3JvdyA8LSBmdW5jdGlvbihjYXRlZ29yeSwgc3ltYm9sKSB7CiAgZGF0YSA8LSBnZXRTeW1ib2xzKHN5bWJvbCwgZnJvbT1Cb1QsIHRvPUVvVCsyLCBhdXRvLmFzc2lnbiA9IEZBTFNFKQogIGN1cnJlbmN5X3RhYiA8PC0gcmJpbmQoY3VycmVuY3lfdGFiLCBkYXRhLmZyYW1lKAogICAgRGVzY3JpcHRpb24gPSBjYXRlZ29yeSwKICAgIEJvVCA9IGFzLm51bWVyaWMoQ2woZGF0YSlbd2hpY2gubWluKGFicyhpbmRleChkYXRhKSAtIEJvVCkpXSksCiAgICBFb1QgPSBhcy5udW1lcmljKENsKGRhdGEpW3doaWNoLm1pbihhYnMoaW5kZXgoZGF0YSkgLSBFb1QpKV0pCiAgKSkKfQoKCmFkZF9yb3coIkN1cnJlbmN54oCZcyBleGlzdGluZyB2YWx1ZSIsIkpQWVVTRD1YIiApCgpwcmludChjdXJyZW5jeV90YWIpCgoKYGBgCgojIyBMMiBGaW5hbmNpYWwgbWFya2V0cyBtaWNybyBzdHJ1Y3R1cmUKCjEuICBEb3dubG9hZCBiYXNpYyBzdGF0aXN0aWMgb2YgTkFTREFRIGFuZCBMb25kb24gU3RvY2sgRXhjaGFuZ2UgYW5kIGNvbXBhcmUgdGhlbQoKYGBge3J9CmdldFN5bWJvbHMoIk5EQVEiLCBmcm9tPSBCb1QsIHRvPUVvVCkKZ2V0U3ltYm9scygiXkZUU0UiLCBmcm9tPSBCb1QsIHRvPUVvVCkgCgojYWRkIGEgZ3JhcGggYWRqdXN0ZWQgCgpGVFNFPC0gbmEuYXBwcm94KEZUU0UpCgoKI0NvcnJlbGF0aW9uCmNvcnIgPC0gbWVyZ2UoTkRBUSwgRlRTRSkKY29yciA8LSBuYS5vbWl0KGNvcnIpCgpjb3JyZWxhdGlvbiA8LSBjb3IoY29yclssIDRdLCBjb3JyWywgMTBdKQoKCgpuYXNkYXFfcyA8LSBjKAogIE1lYW4gPSBtZWFuKE5EQVEkTkRBUS5DbG9zZSwgbmEucm09VFJVRSksCiAgTWVkaWFuID0gbWVkaWFuKE5EQVEkTkRBUS5DbG9zZSwgbmEucm09VFJVRSksCiAgU3REZXYgPSBzZChOREFRJE5EQVEuQ2xvc2UsIG5hLnJtPSBUUlVFKQopCgpsc2VfcyA8LSBjKAogIE1lYW4gPSBtZWFuKEZUU0UkRlRTRS5DbG9zZSksCiAgTWVkaWFuID0gbWVkaWFuKEZUU0UkRlRTRS5DbG9zZSksCiAgU3REZXYgPSBzZChGVFNFJEZUU0UuQ2xvc2UpCikKCgpjb21wYXJpc29uIDwtIHJiaW5kKG5hc2RhcV9zLCBsc2VfcykKY29sbmFtZXMoY29tcGFyaXNvbikgPC0gYygiTWVhbiIsICJNZWRpYW4iLCAiU3RhbmRhcmQgRGV2aWF0aW9uIiApCgpyb3VuZChjb3JyZWxhdGlvbiwgMykKcm91bmQoY29tcGFyaXNvbiwyKQoKCmBgYAoKVGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIG1hcmtldHMgaXMgdmVyeSBsb3c6IDAuMzQxLiBXZSBzZWUgYWxzbywgdGhhdCB0aGUgdm9sYXRpbGl0eSAobWVhc3VyZWQgYnkgdGhlIHN0YW5kYXJkIGRldmlhdGlvbikgb2YgdGhlIExvbmRvbiBTRSBpcyBncmVhdGVyIHRoYXQgdGhlIE5BU0RBUS4KCiMjIEwzIEluc3RydW1lbnTigJlzIG92ZXJ2aWV3IGFuZCB2YWx1YXRpb24KCi0gICBDb21wYXJlIHRoZSAxMy13ZWVrIFRyZWFzdXJ5IGJpbGwgcmF0ZSAod2hpY2ggaXMgYSBwcm94eSBmb3Igc2hvcnQtdGVybSBpbnRlcmVzdCByYXRlcykgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0gdG8gdGhlIHJhdGUgdGhhdCBleGlzdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtLiAobm90ZTogMy1Nb250aCBUcmVhc3VyeSBCaWxsIFNlY29uZGFyeSBNYXJrZXQgUmF0ZSwgRGlzY291bnQgQmFzaXMgKFRCM01TKSkgPGh0dHBzOi8vZnJlZC5zdGxvdWlzZmVkLm9yZy9zZXJpZXMvVGNsQjNNUz4KCmBgYHtyfQp0YjNtIDwtIGRhdGEuZnJhbWUoCiAgRGVzY3JpcHRpb24gPSBjaGFyYWN0ZXIoKSwKICBCZWdpbm5pbmdfb2ZfVGVybSA9IGNoYXJhY3RlcigpLAogIEVuZF9vZl9UZXJtID0gY2hhcmFjdGVyKCksCiAgQ2hhbmdlID0gY2hhcmFjdGVyKCkKKQoKCgphZGRfcm93IDwtIGZ1bmN0aW9uKGNhdGVnb3J5LCBzeW1ib2wpIHsKICBkYXRhIDwtIGdldFN5bWJvbHMoc3ltYm9sLCBmcm9tPUJvVCwgdG89RW9UKzIsc3JjPSJGUkVEIiwgYXV0by5hc3NpZ24gPSBGQUxTRSkKICB0YjNtIDw8LSByYmluZCh0YjNtLCBkYXRhLmZyYW1lKAogICAgRGVzY3JpcHRpb24gPSBjYXRlZ29yeSwKICAgIEJvVCA9IGFzLm51bWVyaWMoZGF0YVt3aGljaC5taW4oYWJzKGluZGV4KGRhdGEpIC0gQm9UKSksIDFdKSwKICAgIEVvVCA9IGFzLm51bWVyaWMoZGF0YVt3aGljaC5taW4oYWJzKGluZGV4KGRhdGEpIC0gRW9UKSksIDFdKSwgCiAgICBDaGFuZ2U9IGFzLm51bWVyaWMoZGF0YVt3aGljaC5taW4oYWJzKGluZGV4KGRhdGEpIC0gRW9UKSksIDFdKS1hcy5udW1lcmljKGRhdGFbd2hpY2gubWluKGFicyhpbmRleChkYXRhKSAtIEJvVCkpLCAxXSkKICApKQp9CgphZGRfcm93KCJUcmVhc3VyeSBiaWxsICgzLW1vbnRoKSIsIlRCM01TIiApCgpwcmludCh0YjNtKQoKCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZSByYXRlIGhhcyBkZWNyZWFzZWQgYnkgNzMgYmFzaWMgcG9pbnRzLgoKLSAgICpXaHkgaW50ZXJlc3QgcmF0ZXMgY2hhbmdlIG92ZXIgdGltZS4qCgpJbnRlcmVzdCBtYWlubHkgY2hhbmdlIGR1ZSB0byBlY29ub21pYyBjb25kaXRpb25zLiBXaGVuIHRoZSBlY29ub215IGlzIG92ZXJoZWF0ZWQsIHRoZSBDZW50cmFsIEJhbmsgd2lsbCBpbmNyZWFzZSB0aGUgZmVkZXJhbCBmdW5kcyByYXRlcyAoRkZSKSB0byBzbG93ZG93biB0aGUgZWNvbm9teS4gVGhpcyB3aWxsIGltcGFjdCBvbiBhbGwgdGhlIHlpZWxkIGN1cnZlLCBzcGVjaWFsbHkgb24gdGhlIHNob3J0IHRlcm0gcmF0ZXMuIFRodXMsIHNpbmNlIHRoZSBGRUQgZGVjaWRlZCB0byBjdXQgdGhlIEZGUiBhbmQgdGhlIGludmVzdG9ycyBhcmUgZXhwZWN0aW5nIGZ1dHVyZSBjdXRzIGluIHRoZSBmb2xsb3dpbmcgbWVldGluZ3MsIHdlIGhhdmUgc2VlbiB0aGF0IHRoZSB5aWVsZCBvZiB0aGUgVEIzTSBoYXMgZGVjcmVhc2VkLgoKIyMgTDQgRWZmaWNpZW5jeSBvZiBtYXJrZXQgYW5kIGluZm9ybWF0aW9uCgotICAgKkNoZWNrIGlmIG9uIDI2IE9jdG9iZXIgMjAxNyBDb2NhIENvbGEgc2hhcmVzIHdlcmUgaGl0IGJ5IHRoZSBhZHZlcnNlIGluZm9ybWF0aW9uIHJlYWxpemUgb24gdGhlIG1hcmtldC4gKGFzc3VtZSAyNiBpcyB0aGUgaW5mb3JtYXRpb24gcmVhbGlzZSBkYXRlKSoKCmBgYHtyfQpkYXRlIDwtIGFzLkRhdGUoIjIwMTctMTAtMjYiKQpnZXRTeW1ib2xzKCJLTyIsIGZyb209ZGF0ZS01LCB0bz1kYXRlKzMwKQpLTzwtIHJvdW5kKEtPLCAyKQpkZXYubmV3KCkKY2hhcnRTZXJpZXMoQ2woS08pLHRoZW1lPSJ3aGl0ZSIpCmFkZFRBKENsKEtPKVtpbmRleChLTykgPT0gZGF0ZV0sIG9uID0gMSwgY29sID0gImJsdWUiLCBwY2ggPSAxOSwgdHlwZSA9ICJwIiwgbGVnZW5kID0gRkFMU0UpCgoKYGBgCgpJbiBPY3RvYmVyIDIwMTcsIENvY2EgQ29sYSBoYWQgYSBkZWNyZWFzZSBpbiBpdHMgbmV0IGluY29tZSBvZiAxNSUgYmVjYXVzZSBvZiB0aGUgZnJhbmNoaXNpbmcgcHJvY2Vzcy4gRHVlIHRvIHRoaXMsIG9uIE9jdG9iZXIgMjYgdGhlIHByaWNlIGNsb3NlZCBhdCBcJDQ1LjU5LCB3aGljaCB3YXMgYSBkZWNyZWFzZSBvZiAwLjUlIGNvbXBhcmVkIHRvIHRoZSAyNXRoLiBBbHNvLCB3ZSBub3RpY2UgdGhhdCB0aGVyZSB3YXMgYSByZWFjdGlvbiB0byB0aGUgbmV3cyBkYXlzIGFmdGVyIE5vdmVtYmVyIDNyZCBhbmQgdGhlbiBhIGNvcnJlY3Rpb24gKGFuIHVuZGVycmVhY3Rpb24gYW5kIHRoZW4gYSBjb3JyZWN0aW9uKS4gU28sIHRvIHN1bSB1cCB3ZSBjYW4gY29uZmlybSB0aGF0IHRoZXJlIGlzIGFuIGltcGFjdCBzcGVjaWFsbHkgbm90YWJsZSBkYXlzIGFmdGVyIHRoZSByZWFsaXplIGRhdGUgcmVnYXJkaW5nIHRoZSBjb21wYW55J3MgYWN0aW9ucyBkdWUgdG8gdGhlIGFkdmVyc2UgaW5mb3JtYXRpb24gcmVhbGl6ZWQgb24gdGhlIG1hcmtldC4KCiMjIEw1IEZpbmFuY2lhbCBzdGF0ZW1lbnRzIGFuZCBmdW5kYW1lbnRhbCBhbmFseXNpcwoKLSAgICpEb3dubG9hZCB0byBSIHRoZSBmaW5hbmNpYWwgc3RhdGVtZW50cyBvZiBNaWNyb3NvZnQgMjAxOCwgc2hvdyB0aGUgY29kKgoKV2UgZG93bmxvYWQgdGhlIEJhbGFuY2UgU2hlZXQsIENhc2ggRmxvdyBhbmQgSW5jb21lIG9mIE1pY3Jvc29mdCBmb3IgMjAxOC4KCmBgYHtyfQoKbGlicmFyeShmaW5yZXBvcnRyKSAjIGZvciBmaW5hbmNpYWxzCmxpYnJhcnkoZWRnYXIpICAjIGZvciBmdWxsIHRleHQgcmV0cmlhbCBhbmQgdGV4dCBtaW5pbmcKbGlicmFyeShYQlJMKSAgIyBmb3IgaW5zdGFudHMgKGZ1bGwgc2V0IG1hbmlwdWxhdGlvbikKbGlicmFyeShkcGx5cikgCmxpYnJhcnkodGlkeXIpCgoKb3B0aW9ucyhIVFRQVXNlckFnZW50ID0gImNhbWlsYWRlbGFjcnV6aEBnbWFpbC5jb20iKQoKQW5udWFsUmVwb3J0cygwMDAwNzg5MDE5LCBmb3JlaWduID0gRkFMU0UpCgoKdHJhY2UoJ1hCUkwnLCBlZGl0PVRSVUUpCgojVGhlcmUncyBpcyBhIHByb2JsZW0gd2l0aCB0aGUgR2V0QmFsYW5jZVNoZWV0IGZ1bmN0aW9uLiBUbyBmaXggdGhhdCBwcm9ibGVtIHdlIHJ1biB0aGUgZm9sbG93aW5nIGNvZGUgdG8gZWRpdCB0aGUgZnVuY3Rpb24gdGVtcG9yYXJpbHk6IHRyYWNlKCdYQlJMJywgZWRpdD1UUlVFKS4gV2Ugd2lsbCByZXBsYWNlICJpZiAoc3Vic3RyKGZpbGUubmFtZSwgMSwgNSkgIT0gImh0dHA6IikgeyIgZm9yICJpZiAoIShzdWJzdHIoZmlsZS5uYW1lLCAxLCA1KSAlaW4lIGMoImh0dHA6IiwgImh0dHBzIikpKSB7Ii4gTm93IHdlIGNhbiBydW4gdGhlIGNvZGUgdG8gc2VhcmNoIGZpbGVzIGJleW9uZCAyMDE2LiAKCm1zZnRfYnMgPC1HZXRCYWxhbmNlU2hlZXQoJ01TRlQnLCAyMDE4KQptc2Z0X2NmIDwtR2V0Q2FzaEZsb3coJ01TRlQnLCAyMDE4KQptc2Z0X2luIDwtIEdldEluY29tZSgnTVNGVCcsIDIwMTgpCgoKaGVhZChtc2Z0X2NmKQpoZWFkKG1zZnRfaW4pCgoKYGBgCgpgYGB7cn0KaGVhZChtc2Z0X2JzKQoKCmBgYAoKYGBge3J9CmhlYWQobXNmdF9jZikKYGBgCgoqKkNvbW1lcmNpYWwgYmFuayBvcGVyYXRpb25zKioKCkZvciB0aGUgY29tbWVyY2lhbCBiYW5rIHRoYXQgeW91IHNlbGVjdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHRlcm0sIHVzZSBpdHMgYW5udWFsIHJlcG9ydCBvciBhbnkgb3RoZXIgcmVsYXRlZCBpbmZvcm1hdGlvbiB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgpgYGB7cn0KCkFubnVhbFJlcG9ydHMoIkJBQyIsIGZvcmVpZ24gPSBGQUxTRSkKCgpiYWNfYnMgPC1HZXRCYWxhbmNlU2hlZXQoJ0JBQycsIDIwMTgpCmJhY19jZiA8LUdldENhc2hGbG93KCdCQUMnLCAyMDE4KQpiYWNfaW4gPC0gR2V0SW5jb21lKCdCQUMnLCAyMDE4KQoKYGBgCgotICAgKklkZW50aWZ5IHRoZSB0eXBlcyBvZiBkZXBvc2l0cyB0aGF0IHRoZSBjb21tZXJjaWFsIGJhbmsgdXNlcyB0byBvYnRhaW4gbW9zdCBvZiBpdHMgZnVuZHMuKgoKUHJpbWFyaWx5IHVzZXPCoGRlbWFuZCBkZXBvc2l0c8KgKHN1Y2ggYXMgY2hlY2tpbmcgYWNjb3VudHMpIGFuZMKgc2F2aW5ncyBhY2NvdW50cy4KCi0gICAqSWRlbnRpZnkgdGhlIG1haW4gdXNlcyBvZiBmdW5kcyBieSB0aGUgYmFuay4gU3VtbWFyaXplIGFueSBzdGF0ZW1lbnRzIG1hZGUgYnkgdGhlIGNvbW1lcmNpYWwgYmFuayBpbiBpdHMgYW5udWFsIHJlcG9ydCBhYm91dCBob3cgcmVjZW50IG9yIHBvdGVudGlhbCByZWd1bGF0aW9ucyB3aWxsIGFmZmVjdCBpdHMgcGVyZm9ybWFuY2UuKgoKVGhlIG1haW4gdXNlcyBvZiBmdW5kcyBhcmUgbG9hbnMgdG8gY3VzdG9tZXJzLCBpbnZlc3RtZW50cyBpbiBzZWN1cml0aWVzIGFuZCBjYXNoIHJlc2VydmVzLgoKVGhlIGJhbmsgaGlnaGxpZ2h0cyB1bmNlcnRhaW50aWVzIHJlZ2FyZGluZyB0aGUgY29udGVudCwgdGltaW5nLCBhbmQgaW1wYWN0IG9mIHJlZ3VsYXRvcnkgY2FwaXRhbCBhbmQgbGlxdWlkaXR5IHJlcXVpcmVtZW50cywgc3VjaCBhcyB0aG9zZSB1bmRlciB0aGUgVm9sY2tlciBSdWxlLCByZWNvdmVyeSBwbGFubmluZyByZXF1aXJlbWVudHMsIGFuZCB0aGUgRmVkZXJhbCBSZXNlcnZlJ3MgYWN0aW9ucyBvbiBjYXBpdGFsIHBsYW5zLgoKLSAgICpEb2VzIGl0IGFwcGVhciB0aGF0IHRoZSBiYW5rIGlzIGF0dGVtcHRpbmcgdG8gZW50ZXIgdGhlIHNlY3VyaXRpZXMgaW5kdXN0cnkgYnkgb2ZmZXJpbmcgc2VjdXJpdGllcyBzZXJ2aWNlcz8gSWYgc28sIGV4cGxhaW4gaG93LioKClRoZSByZXBvcnQgaW5kaWNhdGVzIHRoYXQgdGhlIGJhbmsgb2ZmZXJzIGEgcmFuZ2Ugb2YgaW52ZXN0bWVudCBiYW5raW5nIHNlcnZpY2VzLCBpbmNsdWRpbmcgdW5kZXJ3cml0aW5nIGZvciBlcXVpdHkgYW5kIGRlYnQgc2VjdXJpdGllcywgYWR2aXNvcnkgc2VydmljZXMgYW5kIGJyb2tlcmFnZSBzZXJ2aWNlcy4gQWRkaXRpb25hbGx5LCBCYW5rIG9mIEFtZXJpY2EgaGFzIGludGVncmF0ZWQgaXRzIHdlYWx0aCBtYW5hZ2VtZW50IHNlcnZpY2VzIHdpdGggaW52ZXN0bWVudCBzb2x1dGlvbnMsIGFsbG93aW5nIGNsaWVudHMgYWNjZXNzIHRvIGEgYnJvYWRlciBhcnJheSBvZiBmaW5hbmNpYWwgcHJvZHVjdHMsIGluY2x1ZGluZyBtdXR1YWwgZnVuZHMgYW5kIEVURnMuIFRoaXMgc3RyYXRlZ2ljIG1vdmUgaW5kaWNhdGVzIGEgY2xlYXIgaW50ZW50IHRvIGV4cGFuZGluZyBpdHMgcHJlc2VuY2UgaW4gdGhlIHNlY3VyaXRpZXMgaW5kdXN0cnkuCgotICAgKkRvZXMgaXQgYXBwZWFyIHRoYXQgdGhlIGJhbmsgaXMgYXR0ZW1wdGluZyB0byBlbnRlciB0aGUgaW5zdXJhbmNlIGluZHVzdHJ5IGJ5IG9mZmVyaW5nIGluc3VyYW5jZSBzZXJ2aWNlcz8gSWYgc28sIGV4cGxhaW4gaG93LioKClRoZSBiYW5rIGlzIGJ5IG9mZmVyaW5nIHZhcmlvdXMgaW5zdXJhbmNlLXJlbGF0ZWQgcHJvZHVjdHMgYW5kIHNlcnZpY2VzLiBUaGUgcmVwb3J0IGhpZ2hsaWdodHMgdGhlIHByb3Zpc2lvbiBvZiBsaWZlIGluc3VyYW5jZSwgcHJvcGVydHkgYW5kIGNhc3VhbHR5IGluc3VyYW5jZSwgYW5kIGhlYWx0aCBpbnN1cmFuY2UgcHJvZHVjdHMgdGhyb3VnaCBwYXJ0bmVyc2hpcHMgcyBhbmQgdGhlIGludGVncmF0aW9uIG9mIGluc3VyYW5jZSBzZXJ2aWNlcyB3aXRoaW4gdGhlaXIgYnJvYWRlciBmaW5hbmNpYWwgb2ZmZXJpbmdzLiBUaHVzLCBpdCBzZWVtcyB0aGF0IGlzIGFsc28gYXR0ZW1wdGluZyB0byBlbnRlciB0aGlzIGluZHVzdHJ5LgoKKipDb21tZXJjaWFsIGJhbmsgbWFuYWdlbWVudCoqCgotICAgKkFzc2VzcyB0aGUgYmFua+KAmXMgYmFsYW5jZSBzaGVldCBhcyB3ZWxsIGFzIGFueSBjb21tZW50cyBpbiBpdHMgYW5udWFsIHJlcG9ydCBhYm91dCB0aGUgZ2FwIGJldHdlZW4gaXRzIHJhdGUtc2Vuc2l0aXZlIGFzc2V0cyBhbmQgaXRzIHJhdGUtc2Vuc2l0aXZlIGxpYWJpbGl0aWVzLiBEb2VzIGl0IGFwcGVhciB0aGF0IHRoZSBiYW5rIGhhcyBhIHBvc2l0aXZlIGdhcCBvciBhIG5lZ2F0aXZlIGdhcD8qCgpEdXJpbmcgMjAyMywgQkEgZXhwZXJpZW5jZWQgYW4gb3ZlcmFsbCBkZWNyZWFzZSBpbiB0aGUgYXNzZXQgc2Vuc2l0aXZpdHkgb2YgaXRzIGJhbGFuY2Ugc2hlZXQgY29uY2VybmluZyBoaWdoZXIgYW5kIGxvd2VyIGludGVyZXN0IHJhdGUgc2NlbmFyaW9zLiBUaGlzIGNoYW5nZSB3YXMgcHJpbWFyaWx5IGF0dHJpYnV0ZWQgdG8gc2hpZnRzIGluIHRoZSBkZXBvc2l0IHByb2R1Y3QgbWl4IGFuZCBhY3Rpdml0eSB3aXRoaW4gdGhlIEFzc2V0LUxpYWJpbGl0eSBNYW5hZ2VtZW50IChBTE0pIHBvcnRmb2xpby5UaGUgYmFuayBjb250aW51ZXMgdG8gYmUgYXNzZXQgc2Vuc2l0aXZlIHRvIGEgcGFyYWxsZWwgdXB3YXJkIG1vdmUgaW4gaW50ZXJlc3QgcmF0ZXMsIHdpdGggdGhlIG1ham9yaXR5IG9mIHRoaXMgaW1wYWN0IHN0ZW1taW5nIGZyb20gdGhlIHNob3J0IGVuZCBvZiB0aGUgeWllbGQgY3VydmUuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIGJhbmsgaGFzIGHCoHBvc2l0aXZlIGdhcCwgbWVhbmluZyB0aGF0IGl0cyByYXRlLXNlbnNpdGl2ZSBhc3NldHMgYXJlIGV4cGVjdGVkIHRvIHJlc3BvbmQgbW9yZSBmYXZvcmFibHkgdG8gcmlzaW5nIGludGVyZXN0IHJhdGVzIGNvbXBhcmVkIHRvIGl0cyByYXRlLXNlbnNpdGl2ZSBsaWFiaWxpdGllcyAocHJpbWFyaWx5IGRlcG9zaXRzKS4KCkZvciB0aGUgbmV4dCBxdWVzdGlvbnMgd2Ugd2lsbCB1c2UgdGhlIGZpbmFuY2lhbCBkYXRhIHRoYXQgaXMgYXZhaWxhYmxlIG9uIHRoZSBmb2xsb3dpbmcgbGluazogPGh0dHBzOi8vd3d3LnNlYy5nb3YvaXg/ZG9jPS9BcmNoaXZlcy9lZGdhci9kYXRhLzcwODU4LzAwMDAwNzA4NTgyNDAwMDEyMi9iYWMtMjAyMzEyMzEuaHRtPgoKYGBge3J9CiMgRmluYW5jaWFsIGRhdGEgKG1pbGxpb25zIG9mICQpCnRvdGFsX2Fzc2V0cyA8LSAzMTgwMTUxCmludGVyZXN0X2luY29tZSA8LSAxMzAyNjIKaW50ZXJlc3RfZXhwZW5zZSA8LSA3MzMzMQpub25pbnRlcmVzdF9pbmNvbWUgPC0gNDE2NTAKbm9uaW50ZXJlc3RfZXhwZW5zZSA8LSA2NTg0NQplYXJuaW5nX2Fzc2V0cyA8LSAyNzUzNjAwCm5ldF9pbmNvbWUgPC0gMjY1MTUKc2hhcmVob2xkZXJzX2VxdWl0eSA8LSAyOTE2NDYKbG9hbl9sb3NzX3Jlc2VydmVzIDwtIDEzMzQyCgpgYGAKCi0gICAqRGV0ZXJtaW5lIHRoZSBiYW5r4oCZcyBpbnRlcmVzdCBpbmNvbWUgYXMgYSBwZXJjZW50YWdlIG9mIGl0cyB0b3RhbCBhc3NldHMuKgoKYGBge3J9CmludGVyZXN0X2luY29tZV9wZXJjZW50YWdlIDwtIChpbnRlcmVzdF9pbmNvbWUgLyB0b3RhbF9hc3NldHMpICogMTAwCnJvdW5kKGludGVyZXN0X2luY29tZV9wZXJjZW50YWdlLDIpCmBgYAoKLSAgICpEZXRlcm1pbmUgdGhlIGJhbmvigJlzIGludGVyZXN0IGV4cGVuc2VzIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzLioKCmBgYHtyfQppbnRlcmVzdF9leHBlbnNlX3BlcmNlbnRhZ2UgPC0gKGludGVyZXN0X2V4cGVuc2UgLyB0b3RhbF9hc3NldHMpICogMTAwCgpyb3VuZChpbnRlcmVzdF9leHBlbnNlX3BlcmNlbnRhZ2UsMikKYGBgCgotICAgKkRldGVybWluZSB0aGUgYmFua+KAmXMgbmV0IGludGVyZXN0IG1hcmdpbi4qCgpgYGB7cn0KbmV0X2ludGVyZXN0X2luY29tZSA8LSBpbnRlcmVzdF9pbmNvbWUgLSBpbnRlcmVzdF9leHBlbnNlCm5pbSA8LSAobmV0X2ludGVyZXN0X2luY29tZSAvIGVhcm5pbmdfYXNzZXRzKSAqIDEwMApwcmludChuaW0sIDIpCgpgYGAKCi0gICAqRGV0ZXJtaW5lIHRoZSBiYW5r4oCZcyBub25pbnRlcmVzdCBpbmNvbWUgYXMgYSBwZXJjZW50YWdlIG9mIGl0cyB0b3RhbCBhc3NldHMuKgoKYGBge3J9Cgpub25pbnRlcmVzdF9pbmNvbWVfcGVyY2VudGFnZSA8LSAobm9uaW50ZXJlc3RfaW5jb21lIC8gdG90YWxfYXNzZXRzKSAqIDEwMApwcmludChub25pbnRlcmVzdF9pbmNvbWVfcGVyY2VudGFnZSwgMikKYGBgCgotICAgKkRldGVybWluZSB0aGUgYmFua+KAmXMgbm9uaW50ZXJlc3QgZXhwZW5zZXMgKGRvIG5vdCBpbmNsdWRlIHRoZSBhZGRpdGlvbiB0byBsb2FuIGxvc3MgcmVzZXJ2ZXMgaGVyZSkgYXMgYSBwZXJjZW50YWdlIG9mIGl0cyB0b3RhbCBhc3NldHMuKgoKYGBge3J9Cm5vbmludGVyZXN0X2V4cGVuc2VfcGVyY2VudGFnZSA8LSAobm9uaW50ZXJlc3RfZXhwZW5zZSAvIHRvdGFsX2Fzc2V0cykgKiAxMDAKcHJpbnQobm9uaW50ZXJlc3RfZXhwZW5zZV9wZXJjZW50YWdlLCAyKQpgYGAKCi0gICAqRGV0ZXJtaW5lIHRoZSBiYW5r4oCZcyBhZGRpdGlvbiB0byBsb2FuIGxvc3MgcmVzZXJ2ZXMgYXMgYSBwZXJjZW50YWdlIG9mIGl0cyB0b3RhbCBhc3NldHMuKgoKYGBge3J9Cgpsb2FuX2xvc3NfcmVzZXJ2ZXNfcGVyY2VudGFnZSA8LSAobG9hbl9sb3NzX3Jlc2VydmVzIC8gdG90YWxfYXNzZXRzKSAqIDEwMApwcmludChsb2FuX2xvc3NfcmVzZXJ2ZXNfcGVyY2VudGFnZSwgMikKYGBgCgotICAgKkRldGVybWluZSB0aGUgYmFua+KAmXMgcmV0dXJuIG9uIGFzc2V0cyoKCmBgYHtyfQpyb2EgPC0gKG5ldF9pbmNvbWUgLyB0b3RhbF9hc3NldHMpICogMTAwCnByaW50KHJvYSwgMikKCmBgYAoKLSAgICpEZXRlcm1pbmUgdGhlIGJhbmvigJlzIHJldHVybiBvbiBlcXVpdHkuKgoKYGBge3J9CnJvZSA8LSAobmV0X2luY29tZSAvIHNoYXJlaG9sZGVyc19lcXVpdHkpICogMTAwCmBgYAoKLSAgICpJZGVudGlmeSB0aGUgYmFua+KAmXMgaW5jb21lIHN0YXRlbWVudCBpdGVtcyBkZXNjcmliZWQgcHJldmlvdXNseSB0aGF0IHdvdWxkIGJlIGFmZmVjdGVkIGlmIGludGVyZXN0IHJhdGVzIHJpc2UgaW4gdGhlIG5leHQgeWVhciwgYW5kIGV4cGxhaW4gaG93IHRoZXkgd291bGQgYmUgYWZmZWN0ZWQuKgoKVGhlIGludGVyZXN0IGluY29tZSBpcyBleHBlY3RlZCB0byBpbmNyZWFzZSBzaW5jZSBpbnRlcmVzdCBpbmNvbWUgd291bGQgcmlzZSBtb3JlIHRoYW4gaW50ZXJlc3QgZXhwZW5zZXMsIG5ldCBpbnRlcmVzdCBpbmNvbWUgd291bGQgbGlrZWx5IGltcHJvdmUsIGVuaGFuY2luZyBwcm9maXRhYmlsaXR5LgoKLSAgICpJZGVudGlmeSB0aGUgYmFua+KAmXMgaW5jb21lIHN0YXRlbWVudCBpdGVtcyBkZXNjcmliZWQgcHJldmlvdXNseSB0aGF0IHdvdWxkIGJlIGFmZmVjdGVkIGlmIFUuUy4gZWNvbm9taWMgY29uZGl0aW9ucyBkZXRlcmlvcmF0ZSwgYW5kIGV4cGxhaW4gaG93IHRoZXkgd291bGQgYmUgYWZmZWN0ZWQqCgpOZXQgSW50ZXJlc3QgSW5jb21lIGxpa2VseSB0byBkZWNyZWFzZS4gV2l0aCBkZWNsaW5pbmcgaW50ZXJlc3QgaW5jb21lIGFuZCBwb3RlbnRpYWxseSBzdGFibGUgb3IgZGVjcmVhc2luZyBpbnRlcmVzdCBleHBlbnNlLCBuZXQgaW50ZXJlc3QgaW5jb21lIHdvdWxkIGxpa2VseSBzdWZmZXIuCgpOZXQgaW5jb21lIGFsc28gbGlrZWx5IHRvIGRlY3JlYXNlLiBXaXRoIHJlZHVjZWQgbmV0IGludGVyZXN0IGluY29tZSBhbmQgbm9uaW50ZXJlc3QgaW5jb21lIGFsb25nc2lkZSBwb3RlbnRpYWwgaW5jcmVhc2VzIGluIGxvYW4gbG9zcyBwcm92aXNpb25zLCBvdmVyYWxsIHByb2ZpdGFiaWxpdHkgKG5ldCBpbmNvbWUpIGlzIGxpa2VseSB0byBkZWNsaW5lIGR1cmluZyBlY29ub21pYyBkb3dudHVybnMuCgoqKk11dHVhbCBmdW5kcyoqCgpGb3IgdGhlIG11dHVhbCBmdW5kIHRoYXQgeW91IHNlbGVjdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHRlcm0sIHVzZSBpdHMgcHJvc3BlY3R1cyBvciBhbnkgb3RoZXIgcmVsYXRlZCBpbmZvcm1hdGlvbiB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnMuCgpXZSBzZWxlY3QgdGhlIEZpZGVsaXR5IDUwMCBJbmRleCBtdXR1YWwgZnVuZDogPGh0dHBzOi8vZnVuZHJlc2VhcmNoLmZpZGVsaXR5LmNvbS9tdXR1YWwtZnVuZHMvc3VtbWFyeS8zMTU5MTE3NTA+CgotICAgKldoYXQgaXMgdGhlIGludmVzdG1lbnQgb2JqZWN0aXZlIG9mIHRoaXMgbXV0dWFsIGZ1bmQ/IERvIHlvdSBjb25zaWRlciB0aGlzIG11dHVhbCBmdW5kIHRvIGhhdmUgbG93IHJpc2ssIG1vZGVyYXRlIHJpc2ssIG9yIGhpZ2ggcmlzaz8qCgpTaW5jZSBpdCBpbnZlc3QgaW4gZXF1aXR5IGFuZCBtb3JlIHRoYW4gMzAlIGlzIG9uIHRoZSB0ZWNoIHNlY3Rvciwgd2UgY29uc2lkZXIgdGhhdCBpcyBtb3JlZGF0ZSB0byBoaWdoIHJpc2suCgotICAgKldoYXQgd2FzIHRoZSByZXR1cm4gb24gdGhlIG11dHVhbCBmdW5kIGxhc3QgeWVhcj8gV2hhdCB3YXMgdGhlIGF2ZXJhZ2UgYW5udWFsIHJldHVybiBvdmVyIHRoZSBsYXN0IHRocmVlIHllYXJzPyoKCjIwMjM6IDI2LjI5JQoKTGFzdCB0aHJlZSB5ZWFyczogMzMuODclCgotICAgKldoYXQgaXMgYSBrZXkgZWNvbm9taWMgZmFjdG9yIHRoYXQgaW5mbHVlbmNlcyB0aGUgcmV0dXJuIG9uIHRoaXMgbXV0dWFsIGZ1bmQ/IChUaGF0IGlzLCBhcmUgdGhlIGZ1bmTigJlzIHJldHVybnMgaGlnaGx5IGluZmx1ZW5jZWQgYnkgVS5TLiBzdG9jayBtYXJrZXQgY29uZGl0aW9ucz8gQnkgVS5TLiBpbnRlcmVzdCByYXRlcz8gQnkgZm9yZWlnbiBzdG9jayBtYXJrZXQgY29uZGl0aW9ucz8gQnkgZm9yZWlnbiBpbnRlcmVzdCByYXRlcz8pKgoKSXMgaGlnaGx5IGluZmx1ZW5jZWQgYnkgdGhlIFVTIHN0b2NrIG1hcmtldCBjb25kaXRpb25zIHNpbmNlIG9ubHkgaW52ZXN0cyBpbiBVUyBzdG9ja3MuIEFsc28sIHRoYXQncyB3aHkgaXMgaW5mbHVlbmNlZCBieSBpbnRlcmVzdCByYXRlcyBvZiB0aGUgVVMuIEJ1dCBhcyBpdCBkb24ndCBpbiBvdGhlciBjb3VudHJ5LCB0aGUgZnVuZCBpcyBub3QgYWZmZWN0ZWQgYnkgZm9yZWlnbiBjb25kaXRpb25zLgoKLSAgICpNdXN0IGFueSBmZWVzIGJlIHBhaWQgd2hlbiBidXlpbmcgb3Igc2VsbGluZyB0aGlzIG11dHVhbCBmdW5kPyoKCkl0J3MgZmFjdHNoZWV0IHNhaWQgdGhhdCB5b3UgbWF5IGJlIGNoYXJnZWQgYSB0cmFuc2FjdGlvbnMgZmVlIGlmIHlvdSBidXkgb3Igc2VsbCB0cm91Z2ggYSBub24tRmlkZWxpdHkgYnJva2VyLgoKLSAgICpXaGF0IHdhcyB0aGUgZXhwZW5zZSByYXRpbyBmb3IgdGhpcyBtdXR1YWwgZnVuZCBvdmVyIHRoZSBsYXN0IHllYXI/IERvZXMgdGhpcyByYXRpbyBzZWVtIGhpZ2ggdG8geW91PyoKClRoZSBuZXQgZXhwZW5zZSByYXRpbyB3YXMgMC4wMTUlLiBDb21wYXJlIHRvIHRoZSBhdmVyYWdlIG11dHVhbCBmdW5kLCB3ZSB0aGluayB0aGF0IGlzIHF1aXRlIGNoZWFwLgoKKipTZWN1cml0aWVzIGZpcm1zKioKCkZvciB0aGUgc2VjdXJpdGllcyBmaXJtIHRoYXQgeW91IHNlbGVjdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHRlcm0sIHVzZSBpdHMgYW5udWFsIHJlcG9ydCBvciBhbnkgb3RoZXIgcmVsYXRlZCBpbmZvcm1hdGlvbiB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnMuCgotICAgKldoYXQgYXJlIHRoZSBtYWluIHR5cGVzIG9mIGJ1c2luZXNzIGNvbmR1Y3RlZCBieSB0aGUgc2VjdXJpdGllcyBmaXJtPyoKClRlc2xhIG9wZXJhdGVzIHByaW1hcmlseSBpbiB0d28gc2VnbWVudHM6CgoxLiAgQXV0b21vdGl2ZTogVGhpcyBpbmNsdWRlcyB0aGUgZGVzaWduLCBkZXZlbG9wbWVudCwgbWFudWZhY3R1cmluZywgc2FsZXMsIGFuZCBsZWFzaW5nIG9mIGhpZ2gtcGVyZm9ybWFuY2UgZnVsbHkgZWxlY3RyaWMgdmVoaWNsZXMgKEVWcykuIFRoZSBhdXRvbW90aXZlIHNlZ21lbnQgYWxzbyBlbmNvbXBhc3NlcyB0aGUgc2FsZSBvZiBhdXRvbW90aXZlIHJlZ3VsYXRvcnkgY3JlZGl0cyBhbmQgYSB2YXJpZXR5IG9mIHNlcnZpY2VzIHN1Y2ggYXMgdXNlZCB2ZWhpY2xlIHNhbGVzLCBub24td2FycmFudHkgYWZ0ZXItc2FsZXMgc2VydmljZXMsIGJvZHkgc2hvcCBzZXJ2aWNlcywgcGFpZCBTdXBlcmNoYXJnaW5nLCB2ZWhpY2xlIGluc3VyYW5jZSByZXZlbnVlLCBhbmQgcmV0YWlsIG1lcmNoYW5kaXNlLgoKMi4gIEVuZXJneSBHZW5lcmF0aW9uIGFuZCBTdG9yYWdlOiBUaGlzIHNlZ21lbnQgaW52b2x2ZXMgdGhlIGRlc2lnbiwgbWFudWZhY3R1cmUsIGluc3RhbGxhdGlvbiwgc2FsZXMsIGFuZCBsZWFzaW5nIG9mIHNvbGFyIGVuZXJneSBnZW5lcmF0aW9uIHN5c3RlbXMgYW5kIGVuZXJneSBzdG9yYWdlIHByb2R1Y3RzLiBLZXkgb2ZmZXJpbmdzIGluY2x1ZGUgdGhlIFBvd2Vyd2FsbCBmb3IgcmVzaWRlbnRpYWwgdXNlIGFuZCB0aGUgTWVnYXBhY2sgZm9yIGNvbW1lcmNpYWwgYW5kIHV0aWxpdHktc2NhbGUgYXBwbGljYXRpb25zLiBUZXNsYSBhbHNvIHNlbGxzIHNvbGFyIGVuZXJneSBzeXN0ZW1zIHRocm91Z2ggdmFyaW91cyBhcnJhbmdlbWVudHMsIGluY2x1ZGluZyBwb3dlciBwdXJjaGFzZSBhZ3JlZW1lbnRzLgoKLSAgICpTdW1tYXJpemUgYW55IHN0YXRlbWVudHMgbWFkZSBieSB0aGUgc2VjdXJpdGllcyBmaXJtIGluIGl0cyBhbm51YWwgcmVwb3J0IGFib3V0IGhvdyBpdCBtYXkgYmUgYWZmZWN0ZWQgYnkgZXhpc3Rpbmcgb3IgcG90ZW50aWFsIHJlZ3VsYXRpb25zLioKCkluIGl0cyBhbm51YWwgcmVwb3J0LCBUZXNsYSBhY2tub3dsZWRnZXMgdGhhdCBpdCBvcGVyYXRlcyBpbiBhIGhpZ2hseSByZWd1bGF0ZWQgZW52aXJvbm1lbnQgdGhhdCBjYW4gc2lnbmlmaWNhbnRseSBhZmZlY3QgaXRzIGJ1c2luZXNzLiBUaGUgZmlybSBub3RlcyB0aGF0IGV4aXN0aW5nIHJlZ3VsYXRpb25zIHJlZ2FyZGluZyB2ZWhpY2xlIGVtaXNzaW9ucyBhbmQgc2FmZXR5IHN0YW5kYXJkcyBjb3VsZCBpbXBvc2UgY29zdHMgb3Igb3BlcmF0aW9uYWwgcmVzdHJpY3Rpb25zLiBBZGRpdGlvbmFsbHksIHBvdGVudGlhbCBmdXR1cmUgcmVndWxhdGlvbnMgYWltZWQgYXQgZWxlY3RyaWMgdmVoaWNsZXMgb3IgcmVuZXdhYmxlIGVuZXJneSBjb3VsZCBpbXBhY3QgVGVzbGEncyBvcGVyYXRpb25hbCBmbGV4aWJpbGl0eSBhbmQgcHJvZml0YWJpbGl0eS4gVGhlIGNvbXBhbnkgZW1waGFzaXplcyBpdHMgY29tbWl0bWVudCB0byBjb21wbGlhbmNlIGJ1dCByZWNvZ25pemVzIHRoYXQgY2hhbmdlcyBpbiByZWd1bGF0aW9ucyBtYXkgcG9zZSByaXNrcyB0byBpdHMgZ3Jvd3RoIGFuZCBtYXJrZXQgc3RyYXRlZ3kuCgotICAgKkRlc2NyaWJlIHRoZSByZWNlbnQgcGVyZm9ybWFuY2Ugb2YgdGhlIHNlY3VyaXRpZXMgZmlybSwgYW5kIGV4cGxhaW4gd2h5IHRoZSBwZXJmb3JtYW5jZSBoYXMgYmVlbiBmYXZvcmFibGUgb3IgdW5mYXZvcmFibGUuKgoKVGVzbGEncyByZWNlbnQgcGVyZm9ybWFuY2UgaGFzIGJlZW4gY2hhcmFjdGVyaXplZCBieSBzdHJvbmcgc2FsZXMgZ3Jvd3RoIGRyaXZlbiBieSBpbmNyZWFzZWQgZGVtYW5kIGZvciBlbGVjdHJpYyB2ZWhpY2xlcyBhbmQgYWR2YW5jZW1lbnRzIGluIHByb2R1Y3Rpb24gY2FwYWJpbGl0aWVzLiBUaGUgbGF1bmNoIG9mIG5ldyBtb2RlbHMsIGluY2x1ZGluZyB0aGUgQ3liZXJ0cnVjaywgaGFzIGFsc28gY29udHJpYnV0ZWQgcG9zaXRpdmVseSB0byBpdHMgbWFya2V0IHByZXNlbmNlLiBIb3dldmVyLCBjaGFsbGVuZ2VzIHN1Y2ggYXMgc3VwcGx5IGNoYWluIGRpc3J1cHRpb25zIGFuZCBjb21wZXRpdGlvbiBpbiB0aGUgRVYgbWFya2V0IGhhdmUgY3JlYXRlZCBzb21lIGhlYWR3aW5kcy5UaGUgZmF2b3JhYmxlIHBlcmZvcm1hbmNlIGlzIGF0dHJpYnV0ZWQgdG86CgoxLiAgSW5jcmVhc2VkIFByb2R1Y3Rpb24gQ2FwYWNpdHk6IEV4cGFuc2lvbiBvZiBtYW51ZmFjdHVyaW5nIGZhY2lsaXRpZXMgaGFzIGFsbG93ZWQgVGVzbGEgdG8gbWVldCByaXNpbmcgZGVtYW5kLgoKMi4gIElubm92YXRpb246IENvbnRpbnVvdXMgaW1wcm92ZW1lbnRzIGluIHRlY2hub2xvZ3kgYW5kIHByb2R1Y3Qgb2ZmZXJpbmdzIGhhdmUgc3RyZW5ndGhlbmVkIGN1c3RvbWVyIGludGVyZXN0LgoKMy4gIE1hcmtldCBQb3NpdGlvbmluZzogVGVzbGEncyBlc3RhYmxpc2hlZCBicmFuZCByZXB1dGF0aW9uIGFzIGEgbGVhZGVyIGluIHRoZSBFViBzcGFjZSBlbmhhbmNlcyBpdHMgY29tcGV0aXRpdmUgZWRnZS4KCkNvbnZlcnNlbHksIHVuZmF2b3JhYmxlIGZhY3RvcnMgaW5jbHVkZToKCjEuICBSZWd1bGF0b3J5IENoYWxsZW5nZXM6IFBvdGVudGlhbCBjaGFuZ2VzIGluIHJlZ3VsYXRpb25zIGNvdWxkIGltcGFjdCBvcGVyYXRpb25hbCBjb3N0cy4KCjIuICBDb21wZXRpdGl2ZSBMYW5kc2NhcGU6IEdyb3dpbmcgY29tcGV0aXRpb24gZnJvbSBvdGhlciBhdXRvbWFrZXJzIGVudGVyaW5nIHRoZSBFViBtYXJrZXQgbWF5IGFmZmVjdCBUZXNsYSdzIG1hcmtldCBzaGFyZS4KCiMjIEw2IEVxdWl0eQoKV2Ugd2lsbCBleHBsb3JlIHRoZSBHb3Jkb24gR3Jvd3RoIE1vZGVsCgpgYGB7cn0KIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgc3RvY2sgdmFsdWUgdXNpbmcgR29yZG9uIEdyb3d0aCBNb2RlbApnb3Jkb25fZ3Jvd3RoX21vZGVsIDwtIGZ1bmN0aW9uKGRpdmlkZW5kLCBjb3N0X29mX2VxdWl0eSwgZ3Jvd3RoX3JhdGUpIHsKICB2YWx1ZSA8LSBkaXZpZGVuZCAvIChjb3N0X29mX2VxdWl0eSAtIGdyb3d0aF9yYXRlKQogIHJldHVybih2YWx1ZSkKfQoKY29tcGFuaWVzIDwtIGRhdGEuZnJhbWUoCiAgbmFtZSA9IGMoIlRlc2xhIiwgIkFwcGxlIiwgIk1pY3Jvc29mdCIsICJUb3lvdGEiLCAiU2Ftc3VuZyIsICJWb2xrc3dhZ2VuIiksCiAgY291bnRyeSA9IGMoIlVTQSIsICJVU0EiLCAiVVNBIiwgIkphcGFuIiwgIlNvdXRoIEtvcmVhIiwgIkdlcm1hbnkiKSwKICBkaXZpZGVuZCA9IGMoMCwgMC45MiwgMi43MiwgMi4zMCwgMS45NywgNy41NiksCiAgY29zdF9vZl9lcXVpdHkgPSBjKDAuMDgsIDAuMDcsIDAuMDY1LCAwLjA2LCAwLjA3LCAwLjA3NSksCiAgZ3Jvd3RoX3JhdGUgPSBjKDAuMjAsIDAuMTAsIDAuMDgsIDAuMDMsIDAuMDUsIDAuMDIpCikKCmNvbXBhbmllcyRzdG9ja192YWx1ZSA8LSBtYXBwbHkoZ29yZG9uX2dyb3d0aF9tb2RlbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFuaWVzJGRpdmlkZW5kLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wYW5pZXMkY29zdF9vZl9lcXVpdHksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBhbmllcyRncm93dGhfcmF0ZSkKCnByaW50KGNvbXBhbmllcykKCiMgQ29tcGFyZSBVLlMuIGNvbXBhbmllcyB3aXRoIG5vbi1VLlMuIGNvbXBhbmllcwp1c19jb21wYW5pZXMgPC0gc3Vic2V0KGNvbXBhbmllcywgY291bnRyeSA9PSAiVVNBIikKbm9uX3VzX2NvbXBhbmllcyA8LSBzdWJzZXQoY29tcGFuaWVzLCBjb3VudHJ5ICE9ICJVU0EiKQoKY2F0KCJcbkF2ZXJhZ2Ugc3RvY2sgdmFsdWUgZm9yIFUuUy4gY29tcGFuaWVzOiIsIG1lYW4odXNfY29tcGFuaWVzJHN0b2NrX3ZhbHVlKSkKY2F0KCJcbkF2ZXJhZ2Ugc3RvY2sgdmFsdWUgZm9yIG5vbi1VLlMuIGNvbXBhbmllczoiLCBtZWFuKG5vbl91c19jb21wYW5pZXMkc3RvY2tfdmFsdWUpKQoKIyBDcmVhdGUgYSBiYXIgcGxvdCB0byB2aXN1YWxpemUgdGhlIGNvbXBhcmlzb24KYmFycGxvdChjb21wYW5pZXMkc3RvY2tfdmFsdWUsIAogICAgICAgIG5hbWVzLmFyZyA9IGNvbXBhbmllcyRuYW1lLCAKICAgICAgICBjb2wgPSBpZmVsc2UoY29tcGFuaWVzJGNvdW50cnkgPT0gIlVTQSIsICJibHVlIiwgInJlZCIpLAogICAgICAgIG1haW4gPSAiU3RvY2sgVmFsdWVzIENvbXBhcmlzb24iLAogICAgICAgIHlsYWIgPSAiU3RvY2sgVmFsdWUiLAogICAgICAgIGxhcyA9IDIpCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCJVU0EiLCAiTm9uLVVTQSIpLCBmaWxsID0gYygiYmx1ZSIsICJyZWQiKSkKCmBgYAoKVGhlIGF2ZXJhZ2Ugc3RvY2sgdmFsdWUgZm9yIFUuUy4gY29tcGFuaWVzIChleGNsdWRpbmcgVGVzbGEpIGlzIGxpa2VseSB0byBiZSBsb3dlciB0aGFuIG5vbi1VLlMuIGNvbXBhbmllcyBpbiB0aGlzIHNhbXBsZSwgcHJpbWFyaWx5IGR1ZSB0byBsb3dlciBkaXZpZGVuZCBwYXltZW50cyBhbmQgaGlnaGVyIGdyb3d0aCByYXRlcy4KClNvbWUgaW1wb3JhbnQgPG5vdGVzOlRoZT4gR29yZG9uIEdyb3d0aCBNb2RlbCBhc3N1bWVzIGEgY29uc3RhbnQgZ3Jvd3RoIHJhdGUsIHdoaWNoIG1heSBub3QgYmUgcmVhbGlzdGljIGZvciBtYW55IGNvbXBhbmllcywgZXNwZWNpYWxseSBpbiB0aGUgdGVjaCBzZWN0b3MuIEFsc28sIGNvbXBhbmllcyBsaWtlIFRlc2xhLCB3aGljaCBkb24ndCBwYXkgZGl2aWRlbmRzLCBjYW5ub3QgYmUgdmFsdWVkIHVzaW5nIHRoaXMgbW9kZWwsIGhpZ2hsaWdodGluZyBpdHMgbGltaXRhdGlvbnMgZm9yIGdyb3d0aCBzdG9ja3MKCiMjIEw3IEZpeGVkIGluY29tZQoKKipDb21wYXJpbmcgeWllbGRzIGFtb25nIHNlY3VyaXRpZXMqKgoKLSAgICpXaGF0IGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHlpZWxkIG9uIGNvcnBvcmF0ZSBoaWdoLXF1YWxpdHkgYm9uZHMgYW5kIHRoZSB5aWVsZCBvbiBUcmVhc3VyeSBib25kcyBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybT8gRXhwbGFpbiB3aHkgZG9lcyB0aGUgZGlmZmVyZW5jZSBleGlzdD8qCgpXZSBsb29rIGZvciB0aGUgdGhlIGRhdGEgIk1vb2R5J3MgU2Vhc29uZWQgQWFhIENvcnBvcmF0ZSBCb25kIFlpZWxkIFJlbGF0aXZlIHRvIFlpZWxkIG9uIDEwLVllYXIgVHJlYXN1cnkgQ29uc3RhbnQgTWF0dXJpdHkiIG9uIHRoZSBGUkVEIHdlYnNpdGUuCgpgYGB7cn0KCmRpZmYxIDwtIGJhc2ljX3BhcmFtJEVvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiQ29ycG9yYXRlIChNYXN0ZXIpIGJvbmQgeWllbGQiXSAtIGJhc2ljX3BhcmFtJEVvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiVHJlYXN1cnkgbG9uZy10ZXJtIGJvbmQgeWllbGQiXQoKCmNhdCgiVGhlIGRpZmZlcmVuY2UgaXMiLCAgZGlmZjEqMTAwLCAiYmFzaWMgcG9pbnRzLiIpCgpgYGAKClRoZSBiaWcgZGlmZmVyZW5jZSBiZXR3ZWVuIHlpZWxkIG9uIGNvcnBvcmF0ZSBoaWdoLXF1YWxpdHkgYm9uZHMgYW5kIHRoZSB5aWVsZCBvbiBUcmVhc3VyeSBib25kcyBpcyB0aGUgcmlzay4gVHJlYXN1cnkgYm9uZHMgYXJlIGFib3V0IGFzIHJpc2stZnJlZSBhcyB0aGV5IGdldCBhcyB0aGV5IGFyZSBvcGVyYXRlZCBieSB0aGUgZ292ZXJubWVudCwgYnV0IGNvcnBvcmF0ZSBib25kcywgd2hpbGUgYWxzbyByZXByZXNlbnRpbmcgYSBsb2FuLCByaXNrIGlzIGhpZ2hlciBiZWNhdXNlIHRoZSBpc3N1ZXIgY2FuIG5vdCBrZWVwIGl0cyBwcm9taXNlLiBUaGlzIGlzIGR1ZSB0byB0aGUgY3JlZGl0IHNwcmVhZCwgd2hlcmVieSBpbnZlc3RvcnMgYXJlIGNvbXBlbnNhdGVkIHdpdGggaGlnaGVyIHlpZWxkcyB0byBrZWVwIHRoZW0gaW52ZXN0ZWQsIGhlbmNlIGhpZ2gtcXVhbGl0eSBjb3Jwb3JhdGUgYm9uZHMgaGF2ZSB0byBvZmZlciBhIGdyZWF0ZXIgcmV0dXJuIGZvciB0aGUgaGlnaGVyIHJpc2suCgotICAgKldoYXQgaXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgeWllbGQgb24gbG9uZy10ZXJtIFRyZWFzdXJ5IGJvbmRzIGFuZCB0aGUgeWllbGQgb24gbG9uZy10ZXJtIG11bmljaXBhbCBib25kcyBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybT8gRXhwbGFpbiB3aHkgZG9lcyB0aGUgZGlmZmVyZW5jZSBleGlzdD8qCgpUaGUgbWFpbiBkaWZmZXJlbmNlIGlzIHRoYXQgbG9uZy10ZXJtIHRyZWFzdXJ5IGJvbmRzIHlpZWxkIG1vcmUgdGhhbiB0aGUgbG9uZy10ZXJtIG11bmljaXBhbCBib25kcywgbWFpbmx5IGJlY2F1c2Ugb2YgdGhlIHRheGVzIGFzc29jaWF0ZWQgb24gdGhlIGludGVyZXN0IG9uIG11bmljaXBhbCBib25kcy4gQWNjb3JkaW5nbHksIHRoZSBkaWZmZXJlbmNlIGlzIGR1ZSB0byB0aGUgdGF4IGFzcGVjdHMgYW5kIHRoZSBjcmVkaXQgcmlzay4gQ29ycG9yYXRlIGJvbmRzIG9mZmVycyBiZXR0ZXIgeWllbGRzIHRvIG9mZnNldCB0aGUgcmlzaywgYnV0IG11bmljaXBhbCBib25kcyBvZmZlciBiZXR0ZXIgdGF4IGFkdmFuY2VzLgoKYGBge3J9CmRpZmYyIDwtIGJhc2ljX3BhcmFtJEVvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiVGF4LWV4ZW1wdCAoN+KAkzEyLXllYXIpIGJvbmQgeWllbGQiXSAtIGJhc2ljX3BhcmFtJEVvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiVHJlYXN1cnkgbG9uZy10ZXJtIGJvbmQgeWllbGQiXQoKCmNhdCgiVGhlIGRpZmZlcmVuY2UgaXMiLCAgZGlmZjIqMTAwLCAiYmFzaWMgcG9pbnRzLiIpCgpgYGAKCioqQXNzZXNzaW5nIHRoZSBmb3JlY2FzdGluZyBhYmlsaXR5IG9mIHRoZSB5aWVsZCBjdXJ2ZSoqCgotICAgKldoYXQgd2FzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIDI2LXdlZWsgVC1iaWxsIHlpZWxkIGFuZCB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIHRlcm0/KgoKYGBge3J9CmRpZmYzIDwtIGJhc2ljX3BhcmFtJEJvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiVHJlYXN1cnkgYmlsbCByYXRlICg2LW1vbnRoKSJdIC0gYmFzaWNfcGFyYW0kQm9UW2Jhc2ljX3BhcmFtJERlc2NyaXB0aW9uID09ICJUcmVhc3VyeSBiaWxsIHJhdGUgKDMtbW9udGgpIl0KCgpjYXQoIlRoZSBkaWZmZXJlbmNlIGlzIiwgIGRpZmYzKjEwMCwgImJhc2ljIHBvaW50cy4iKQoKYGBgCgotICAgKkRvZXMgdGhpcyBpbXBseSB0aGF0IHRoZSB5aWVsZCBjdXJ2ZSBoYWQgYW4gdXB3YXJkIG9yIGRvd253YXJkIHNsb3BlIGF0IHRoYXQgdGltZT8qCgpTaW5jZSB0aGUgMjYtd2VlayBULWJpbGwgeWllbGQgaXMgbG93ZXIgdGhhbiB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQsIHRoaXMgaW1wbGllcyBhIGRvd253YXJkIHNsb3BlLCB0aGF0IGlzIGFuIGludmVydGVkIHlpZWxkIGN1cnZlLgoKLSAgICpBc3N1bWluZyB0aGF0IHRoaXMgc2xvcGUgY2FuIGJlIHByaW1hcmlseSBhdHRyaWJ1dGVkIHRvIGV4cGVjdGF0aW9ucyB0aGVvcnksIGRpZCB0aGUgZGlyZWN0aW9uIG9mIHRoZSBzbG9wZSBpbmRpY2F0ZSB0aGF0IHRoZSBtYXJrZXQgZXhwZWN0ZWQgaGlnaGVyIG9yIGxvd2VyIGludGVyZXN0IHJhdGVzIGluIHRoZSBmdXR1cmU/KgoKVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGUgaW52ZXN0b3JzIGV4cGVjdHMgbG93ZXIgaW50ZXJlc3QgcmF0ZXMgaW4gdGhlIGZ1dHVyZS4KCi0gICAqRGlkIGludGVyZXN0IHJhdGVzIG1vdmUgaW4gdGhhdCBkaXJlY3Rpb24gb3ZlciB0aGUgc2Nob29sIHRlcm0/KgoKYGBge3J9Cgp0YjMgPC0gZ2V0U3ltYm9scygiRFRCMyIsIGZyb209Qm9ULCB0bz1Fb1QrMixzcmM9IkZSRUQiLCBhdXRvLmFzc2lnbiA9IEZBTFNFKQpjaGFydFNlcmllcyh0YjMsdGhlbWU9IndoaXRlIikKCmBgYAoKV2Ugc2VlIHRoYXQgdGhlbSAxMy1iaWxsIHJhdGUgd2VudCBkb3duIGluIHRoZSBkdXJpbmcgdGhlIHBlcmlvZCBvZiBhbmFseXNpcy4gU28sIHllcyB0aGUgcmF0ZXMgbW92ZSBpbiB0aGUgZGlyZWN0aW9uIHRoYXQgd2FzIGV4cGVjdGVkLgoKKipFeHBsYWluaW5nIHNoaWZ0cyBpbiB0aGUgeWllbGQgY3VydmUgb3ZlciB0aW1lKioKCi0gICAqV2hhdCB3YXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbG9uZy10ZXJtIFRyZWFzdXJ5IGJvbmQgeWllbGQgYW5kIHRoZSAxMy13ZWVrIFQtYmlsbCB5aWVsZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybT8qCgpgYGB7cn0KZGlmZjQgPC0gYmFzaWNfcGFyYW0kQm9UW2Jhc2ljX3BhcmFtJERlc2NyaXB0aW9uID09ICJUcmVhc3VyeSBsb25nLXRlcm0gYm9uZCB5aWVsZCJdIC0gYmFzaWNfcGFyYW0kQm9UW2Jhc2ljX3BhcmFtJERlc2NyaXB0aW9uID09ICJUcmVhc3VyeSBiaWxsIHJhdGUgKDMtbW9udGgpIl0KCgpjYXQoIlRoZSBkaWZmZXJlbmNlIGlzIiwgIGRpZmY0KjEwMCwgImJhc2ljIHBvaW50cy4iKQoKYGBgCgpBdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgeWVhciwgdGhlIHlpZWxkIG9uIHRoZSBsb25nLXRlcm0gVHJlYXN1cnkgYm9uZCB3YXMgbG93ZXIgdGhhbiB0aGF0IG9mIHRoZSAxMy13ZWVrIFQtYmlsbC4KCi0gICAqV2hhdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBsb25nLXRlcm0gVHJlYXN1cnkgYm9uZCB5aWVsZCBhbmQgdGhlIDEzLXdlZWsgVC1iaWxsIHlpZWxkIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtPyoKCmBgYHtyfQpkaWZmNSA8LSBiYXNpY19wYXJhbSRFb1RbYmFzaWNfcGFyYW0kRGVzY3JpcHRpb24gPT0gIlRyZWFzdXJ5IGxvbmctdGVybSBib25kIHlpZWxkIl0gLSBiYXNpY19wYXJhbSRFb1RbYmFzaWNfcGFyYW0kRGVzY3JpcHRpb24gPT0gIlRyZWFzdXJ5IGJpbGwgcmF0ZSAoMy1tb250aCkiXQoKCmNhdCgiVGhlIGRpZmZlcmVuY2UgaXMiLCAgZGlmZjUqMTAwLCAiYmFzaWMgcG9pbnRzLiIpCgpgYGAKCkJ5IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtLCB0aGlzIGRpZmZlcmVudGlhbCBoYXMgc2hyaW5rLgoKLSAgICpHaXZlbiB5b3VyIGFuc3dlcnMgdG8gdGhlIHR3byBwcmV2aW91cyBxdWVzdGlvbnMsIGRlc2NyaWJlIGhvdyB0aGUgeWllbGQgY3VydmUgY2hhbmdlZCBvdmVyIHRoZSBzY2hvb2wgdGVybS4gRXhwbGFpbiB0aGUgY2hhbmdlcyBpbiBleHBlY3RhdGlvbnMgYWJvdXQgZnV0dXJlIGludGVyZXN0IHJhdGVzIHRoYXQgYXJlIGltcGxpZWQgYnkgdGhlIHNoaWZ0IGluIHRoZSB5aWVsZCBjdXJ2ZSBvdmVyIHRoZSBzY2hvb2wgdGVybS4qCgpUaGUgeWllbGQgY3VydmUgYXQgdGhlIEVvVCB3YXMgbGVzcyBpbnZlcnRlZCB0aGFuIHRoZSBiZWdpbm5pbmcuIFdoaWxlIHRoZSBjdXJ2ZSByZW1haW5zIGludmVydGVkLCBtYXJrZXQgZXhwZWN0YXRpb25zIGZvciBpbnRlcmVzdCByYXRlIGN1dHMgaGF2ZSBzb2Z0ZW5lZCwgaW5kaWNhdGluZyBhIGxlc3MgYWdncmVzc2l2ZSBvdXRsb29rIGZvciBtb25ldGFyeSBlYXNpbmcgdGhhbiBhdCB0aGUgc3RhcnQgb2YgdGhlIHRlcm0uCgotICAgKkRpZCB0aGUgRmVkIGNoYW5nZSB0aGUgZmVkZXJhbCBmdW5kcyByYXRlIG92ZXIgdGhlIHNjaG9vbCB0ZXJtPyoKCmBgYHtyfQoKZmZyIDwtIGdldFN5bWJvbHMoIkZFREZVTkRTIiwgZnJvbT1Cb1QsIHRvPUVvVCsyLHNyYz0iRlJFRCIsIGF1dG8uYXNzaWduID0gRkFMU0UpCmNoYXJ0U2VyaWVzKGZmcix0aGVtZT0id2hpdGUiKQoKCmBgYAoKYGBge3J9CnRhaWwoZmZyKQoKYGBgCgpUaGVyZSB3ZXJlIHR3byBjdXRzIGR1cmluZyB0aGUgcGVyaW9kLiBPbmUgd2FzIGEgY3V0IG9mIDUwIGJhc2lzIHBvaW50cyBpbiB0aGUgU2VwdGVtYmVyIG1lZXRpbmcsIGFuZCB0aGUgb3RoZXIgb25lIG9mIDI1IHBvaW50cyBpbiB0aGUgTm92ZW1iZXIgbWVldGluZy4KCi0gICAqRG8geW91IHRoaW5rIHRoZSBtb3ZlbWVudHMgaW4gaW50ZXJlc3QgcmF0ZXMgb3ZlciB0aGUgc2Nob29sIHRlcm0gd2VyZSBjYXVzZWQgYnkgdGhlIEZlZOKAmXMgbW9uZXRhcnkgcG9saWN5PyBFeHBsYWluLioKClllcy4gU3BlY2lhbGx5IHRoZSBpbnZlc3RvcnMgcGF5cyBhdHRlbnRpb24gdG8gUG93ZWxsJ3Mgc3BlZWNoIGFmdGVyIHRoZSBtZWV0aW5nLiBCdXQsIGFsc28gdGhleSB0YWtlcyBpbnRvIGFjY291bnQgdGhlIGRhdGEgb24gdGhlIHdlbGwga25vd24gbGVhZGluZyBlY29ub21pYyBpbmRpY2F0b3JzLiBUaGF0J3Mgd2h5IHRoZXkgdGhpbmsgdGhhdCB0aGUgRkVEIGNhbiBzdGlsbCBsb3dlciBtb3JlIGludGVyZXN0IHJhdGVzLgoKKipNZWFzdXJpbmcgYW5kIGV4cGxhaW5pbmcgcHJlbWl1bXMgb24gbW9uZXkgbWFya2V0IHNlY3VyaXRpZXMqKgoKLSAgICpXaGF0IGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHlpZWxkIG9uIDkwLWRheSBjb21tZXJjaWFsIHBhcGVyIGFuZCB0aGUgeWllbGQgb24gMTMtd2VlayBULWJpbGxzIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtPyBFeHBsYWluIHdoeSB0aGlzIHByZW1pdW0gZXhpc3RzLioKCmBgYHtyfQoKZGlmZjYgPC0gYmFzaWNfcGFyYW0kQm9UW2Jhc2ljX3BhcmFtJERlc2NyaXB0aW9uID09ICJDb21tZXJjaWFsIHBhcGVyIHJhdGUgKDkwIGRheXMpIl0gLSBiYXNpY19wYXJhbSRCb1RbYmFzaWNfcGFyYW0kRGVzY3JpcHRpb24gPT0gIlRyZWFzdXJ5IGJpbGwgcmF0ZSAoMy1tb250aCkiXQoKCmNhdCgiVGhlIGRpZmZlcmVuY2UgaXMiLCAgZGlmZjYqMTAwLCAiYmFzaWMgcG9pbnRzLiIpCgpgYGAKCklzIGdyZWF0ZXIgYmVjYXVzZSB0aGVyZSBleGlzdCBhIGhpZ2hlciBjcmVkaXQgYW5kIGRlZmF1bHQgcmlzaywgaXQgaXMgd2lkZWx5IGJlbGlldmVkIHRoYXQgdGhlIFVuaXRlZCBTdGF0ZXMgZ292ZXJubWVudCB3aWxsIGFsd2F5cyBtZWV0IGl0cyBmaW5hbmNpYWwgb2JsaWdhdGlvbnMgYW5kIGlzIHVubGlrZWx5IHRvIGRlZmF1bHQuCgotICAgKkNvbXBhcmUgdGhlIHByZW1pdW0gb24gdGhlIDkwLWRheSBjb21tZXJjaWFsIHBhcGVyIHlpZWxkIChyZWxhdGl2ZSB0byB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQpIHRoYXQgZXhpc3RzIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtIHRvIHRoZSBwcmVtaXVtIHRoYXQgZXhpc3RlZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB0ZXJtLiBFeHBsYWluIHdoeSB0aGUgcHJlbWl1bSBtYXkgaGF2ZSBjaGFuZ2VkIG92ZXIgdGhlIHNjaG9vbCB0ZXJtLioKCmBgYHtyfQpkaWZmNyA8LSBiYXNpY19wYXJhbSRFb1RbYmFzaWNfcGFyYW0kRGVzY3JpcHRpb24gPT0gIkNvbW1lcmNpYWwgcGFwZXIgcmF0ZSAoOTAgZGF5cykiXSAtIGJhc2ljX3BhcmFtJEVvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiVHJlYXN1cnkgYmlsbCByYXRlICgzLW1vbnRoKSJdCgoKY2F0KCJUaGUgZGlmZmVyZW5jZSBpcyIsICBkaWZmNyoxMDAsICJiYXNpYyBwb2ludHMuIikKCgpgYGAKClRoZSBncmVhdGVyIGRpZmZlcmVuY2UgbWF5IGluZGljYXRlIHRoYXQgaW52ZXN0b3JzIGFudGljaXBhdGUgYSBkZXRlcmlvcmF0aW9uIGluIHRoZSBvdmVyYWxsIGhlYWx0aCBvZiBidXNpbmVzc2VzLiBUaGV5IHRoaW5rIHRoYXQgdGhlIHJpc2sgb2YgaGF2aW5nIGEgY29tbWVyY2lhbCBwYXBlciBpcyBncmVhdGVyIChkdWUgdG8gaGlnaGVyIGNyZWRpdCByaXNrKSwgdGh1cyBhIHdpZGVyIHlpZWxkIHNwcmVhZC4KCioqRXhwbGFpbmluZyBib25kIHByZW1pdW1zIGFuZCBwcmljZSBtb3ZlbWVudHMqKgoKLSAgICpXaGF0IGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHlpZWxkIG9uIGhpZ2gteWllbGQgY29ycG9yYXRlIGJvbmRzIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtIHZlcnN1cyB0aGUgeWllbGQgb24gaGlnaC1xdWFsaXR5IGNvcnBvcmF0ZSBib25kcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybT8qCgpgYGB7cn0KCmRpZmY4IDwtIGJhc2ljX3BhcmFtJEJvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiSGlnaC15aWVsZCBjb3Jwb3JhdGUgYm9uZCB5aWVsZCJdIC0gYmFzaWNfcGFyYW0kQm9UW2Jhc2ljX3BhcmFtJERlc2NyaXB0aW9uID09ICJDb3Jwb3JhdGUgKE1hc3RlcikgYm9uZCB5aWVsZCJdCgoKY2F0KCJUaGUgZGlmZmVyZW5jZSBpcyIsICBkaWZmOCoxMDAsICJiYXNpYyBwb2ludHMuIikKCmBgYAoKLSAgICpDb21wYXJlIHRoZSBsb25nLXRlcm0gVHJlYXN1cnkgYm9uZCB5aWVsZCBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSB0byB0aGUgbG9uZyB0ZXJtIFRyZWFzdXJ5IGJvbmQgeWllbGQgdGhhdCBleGlzdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtLiBHaXZlbiB0aGUgZGlyZWN0aW9uIG9mIHRoaXMgY2hhbmdlLCBkaWQgcHJpY2VzIG9mIGxvbmctdGVybSBib25kcyByaXNlIG9yIGZhbGwgb3ZlciB0aGUgc2Nob29sIHRlcm0/KgoKYGBge3J9CmRpZmY5IDwtIGJhc2ljX3BhcmFtJEVvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiVHJlYXN1cnkgbG9uZy10ZXJtIGJvbmQgeWllbGQiXSAtIGJhc2ljX3BhcmFtJEJvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiVHJlYXN1cnkgbG9uZy10ZXJtIGJvbmQgeWllbGQiXQoKCmNhdCgiVGhlIGRpZmZlcmVuY2UgaXMiLCAgZGlmZjkqMTAwLCAiYmFzaWMgcG9pbnRzLiIpCgoKYGBgCgpTaW5jZSB0aGUgeWllbGQgaW5jcmVhc2UsIHRoYXQgbWVhbnMgdGhhdCB0aGUgcHJpY2UgZmFsbCBvdmVyIHRoZSBzY2hvb2wgdGVybS4KCi0gICAqQ29tcGFyZSB0aGUgY2hhbmdlIGluIHRoZSB5aWVsZHMgb2YgVHJlYXN1cnksIG11bmljaXBhbCwgYW5kIGNvcnBvcmF0ZSBib25kcyBvdmVyIHRoZSBzY2hvb2wgdGVybS4gRGlkIHRoZSB5aWVsZHMgb2YgYWxsIHRocmVlIHR5cGVzIG9mIHNlY3VyaXRpZXMgbW92ZSBpbiB0aGUgc2FtZSBkaXJlY3Rpb24gYW5kIGJ5IGFib3V0IHRoZSBzYW1lIGRlZ3JlZT8gRXhwbGFpbiB3aHkgeWllbGRzIG9mIGRpZmZlcmVudCB0eXBlcyBvZiBib25kcyBtb3ZlIHRvZ2V0aGVyLioKCmBgYHtyfQoKZGlmZl95aWVsZHMgPC0gc3Vic2V0KGJhc2ljX3BhcmFtLCBEZXNjcmlwdGlvbiAlaW4lIGMoIlRyZWFzdXJ5IGxvbmctdGVybSBib25kIHlpZWxkIiwgIkNvcnBvcmF0ZSAoTWFzdGVyKSBib25kIHlpZWxkIiwgIlRheC1leGVtcHQgKDfigJMxMi15ZWFyKSBib25kIHlpZWxkIikpCgpkaWZmX3lpZWxkcyREaWZmZXJlbmNlIDwtIGRpZmZfeWllbGRzJEVvVCAtIGRpZmZfeWllbGRzJEJvVCAKCnByaW50KGRpZmZfeWllbGRzKQoKCmBgYAoKVXN1YWxseSB3aGVuIHRoZSBGZWRlcmFsIFJlc2VydmUsIGNoYW5nZSBpbnRlcmVzdCByYXRlcywgaXQgYWZmZWN0cyBhbGwgYm9uZHMuIElmIHJhdGVzIGdvIHVwLCBuZXcgYm9uZHMgb2ZmZXIgaGlnaGVyIHJldHVybnMsIHNvIGV4aXN0aW5nIGJvbmRzIHdpdGggbG93ZXIgeWllbGRzIGJlY29tZSBsZXNzIGF0dHJhY3RpdmUsIGNhdXNpbmcgdGhlaXIgcHJpY2VzIHRvIGZhbGwgYW5kIHRoZWlyIHlpZWxkcyB0byByaXNlLiBIb3dldmVyLCBkZXNwaXRlIHRoZSBmZWQgY3V0cyBkdXJpbmcgdGhlIHNjaG9vbCB0ZXJtIHdlIHNlZSB0aGF0IHRoZSB0cmVhc3VyeSBhbmQgY29ycG9yYXRlIGJvbmRzIHdlbnQgdXAuCgotICAgKkNvbXBhcmUgdGhlIHByZW1pdW0gb24gaGlnaC15aWVsZCBjb3Jwb3JhdGUgYm9uZHMgKHJlbGF0aXZlIHRvIFRyZWFzdXJ5IGJvbmRzKSBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybSB0byB0aGUgcHJlbWl1bSB0aGF0IGV4aXN0ZWQgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0uIERpZCB0aGUgcHJlbWl1bSBpbmNyZWFzZSBvciBkZWNyZWFzZT8gV2h5IHRoaXMgcHJlbWl1bSBjaGFuZ2VkIG92ZXIgdGhlIHNjaG9vbCB0ZXJtLioKCmBgYHtyfQojCmRpZmY5IDwtIGJhc2ljX3BhcmFtJEJvVFtiYXNpY19wYXJhbSREZXNjcmlwdGlvbiA9PSAiSGlnaC15aWVsZCBjb3Jwb3JhdGUgYm9uZCB5aWVsZCJdIC0gYmFzaWNfcGFyYW0kQm9UW2Jhc2ljX3BhcmFtJERlc2NyaXB0aW9uID09ICJUcmVhc3VyeSBsb25nLXRlcm0gYm9uZCB5aWVsZCJdCgoKY2F0KCJUaGUgZGlmZmVyZW5jZSBpcyIsICBkaWZmOSoxMDAsICJiYXNpYyBwb2ludHMuIikKCgpgYGAKCmBgYHtyfQpkaWZmMTAgPC0gYmFzaWNfcGFyYW0kRW9UW2Jhc2ljX3BhcmFtJERlc2NyaXB0aW9uID09ICJIaWdoLXlpZWxkIGNvcnBvcmF0ZSBib25kIHlpZWxkIl0gLSBiYXNpY19wYXJhbSRFb1RbYmFzaWNfcGFyYW0kRGVzY3JpcHRpb24gPT0gIlRyZWFzdXJ5IGxvbmctdGVybSBib25kIHlpZWxkIl0KCgpjYXQoIlRoZSBkaWZmZXJlbmNlIGlzIiwgIGRpZmYxMCoxMDAsICJiYXNpYyBwb2ludHMuIikKCmBgYAoKYGBge3J9CgpkaWZmMTEgPC0gZGlmZjEwLWRpZmY5CgpwcmludChkaWZmMTEpCmBgYAoKVGhlIHByZW1pdW0gZGVjcmVhc2UuIEludmVzdG9ycyBtYXkgcGVyY2VpdmUgdGhhdCB0aGUgaGlnaCB5aWVsZCBib25kcyBhcmUgbGVzcyByaXNreSB0aGF0IGF0IHRoZSBiZWdpbm5pbmcuIE1heWJlIGF0IHRoZSBzdGFydCBvZiB0aGUgcGVyaW9kIHRoZXkgd2VyZSBkaXNjb3VudGluZyB0b28gbXVjaCByaXNrIG9uIHRoZXNlIGJvbmRzLgoKIyMgTDggKipQb3J0Zm9saW8gLSBNYXJrb3ZpdHoqKgoKLSAgICpSZXBsaWNhdGUgdGhlIGJhc2ljIGlkZWEgb2YgdGhlIHBvcnRmb2xpbyBjYXNlKgoKYGBge3J9CmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpCgpgYGAKCmBgYHtyfQoKZ2V0U3ltYm9scyhjKCJOVkRBIiwgIlRTTEEiKSwgZnJvbSA9IEJvVCwgdG8gPSBFb1QpCgoKcmV0dXJucyA8LSBuYS5vbWl0KFJPQyhtZXJnZShOVkRBWyw2XSwgVFNMQVssNl0pKSkKCiMgRXhwZWN0ZWQgcmV0dXJucyBhbmQgY292YXJpYW5jZSBtYXRyaXgKbXUgPC0gY29sTWVhbnMocmV0dXJucykKY292X21hdCA8LSBjb3YocmV0dXJucykKCiMgUG9ydGZvbGlvIHdlaWdodHMKd2VpZ2h0cyA8LSBjKDAuNSwgMC41KSAgIyBFcXVhbCB3ZWlnaHRzIGZvciBBQVBMIGFuZCBNU0ZUCgojIFBvcnRmb2xpbyBleHBlY3RlZCByZXR1cm4gYW5kIHZhcmlhbmNlCnBvcnRmb2xpb19yZXR1cm4gPC0gc3VtKHdlaWdodHMgKiBtdSkKcG9ydGZvbGlvX3ZhcmlhbmNlIDwtIHQod2VpZ2h0cykgJSolIGNvdl9tYXQgJSolIHdlaWdodHMKCgpwcmludChwYXN0ZSgiUG9ydGZvbGlvIGV4cGVjdGVkIHJldHVybjoiLCByb3VuZChwb3J0Zm9saW9fcmV0dXJuICogMjUyLCAyKSwgIiUiKSkKcHJpbnQocGFzdGUoIlBvcnRmb2xpbyBhbm51YWxpemVkIHZvbGF0aWxpdHk6Iiwgcm91bmQoc3FydChwb3J0Zm9saW9fdmFyaWFuY2UgKiAyNTIpICogMTAwLCAyKSwgIiUiKSkKCgoKYGBgCgojIyBMOSAqKlBvcnRmb2xpbyAtIENBTVAqKgoKLSAgICpTdGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIENBTVAgYW5kIE1hcmtvd2l0eioKCk1hcmtvd2l0eiBoZWxwcyB3aXRoIHBvcnRmb2xpbyBjb25zdHJ1Y3Rpb24gYnkgZm9jdXNpbmcgb24gZGl2ZXJzaWZpY2F0aW9uIHRvIG9wdGltaXplIHJpc2sgYW5kIHJldHVybi4gSGUgaXMgbm90IGludGVyZXN0ZWQgaW4gZGV0ZXJtaW5pbmcgdGhlIHJldHVybiBvZiBhIHNwZWNpZmljIGFzc2V0OyBpbnN0ZWFkLCBoZSBhaW1zIHRvIGlkZW50aWZ5IHRoZSBvcHRpbWFsIHBvcnRmb2xpbyBiYXNlZCBvbiBoaXN0b3JpY2FsIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIGFzc2V0cywgc2Vla2luZyB0aGUgYmVzdCByaXNrLXJldHVybiB0cmFkZS1vZmYuIE9uIHRoZSBvdGhlciBoYW5kLCBDQVBNIGhlbHBzIHdpdGggZXN0aW1hdGluZyB0aGUgZXhwZWN0ZWQgcmV0dXJuIG9mIGFuIGluZGl2aWR1YWwgYXNzZXQgYmFzZWQgb24gaXRzIHJpc2sgcmVsYXRpdmUgdG8gdGhlIG1hcmtldC4gSXQgZm9jdXNlcyB0byBlc3RpbWF0ZSB0aGUgc2Vuc2l0aXZlbmVzcyBvZiBhbiBhc3NldCB0byBtYXJrZXQgbW92ZW1lbnRzIChzeXN0ZW1hdGljIHJpc2spIGFuZCB1c2UgdGhhdCB0byBzdGF0ZSB3aGF0IHNob3VsZCBiZSB0aGUgcmV0dXJuIG9mIHRoZSBhc3NldCBpbiB0aGUgbG9uZyBydW4uCgpUaGlzIHNlY3Rpb24gY2FsY3VsYXRlcyB0aGUgQmV0YSBhbmQgRXhwZWN0ZWQgUmV0dXJuIGZvciBBcHBsZSAoQUFQTCkgdXNpbmcgdGhlIENBUE0gZm9ybXVsYS4KCmBgYHtyfQpsaWJyYXJ5KHF1YW50bW9kKQpsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQoKc3RhcnRfZGF0ZSA8LSBCb1QKZW5kX2RhdGUgPC0gRW9UCgpzdG9ja19zeW1ib2wgPC0gIkFBUEwiCm1hcmtldF9zeW1ib2wgPC0gIl5HU1BDIgpnZXRTeW1ib2xzKGMoc3RvY2tfc3ltYm9sLCBtYXJrZXRfc3ltYm9sKSwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUsIHNyYyA9ICJ5YWhvbyIpCgpzdG9ja19wcmljZXMgPC0gQ2woQUFQTCkKbWFya2V0X3ByaWNlcyA8LSBDbChHU1BDKQpzdG9ja19yZXR1cm5zIDwtIGRhaWx5UmV0dXJuIChzdG9ja19wcmljZXMpCm1hcmtldF9yZXR1cm5zIDwtIGRhaWx5UmV0dXJuKG1hcmtldF9wcmljZXMpCgpyaXNrX2ZyZWVfcmF0ZSA8LSAwLjAzIC8gMjUyCmJldGEgPC0gY292KHN0b2NrX3JldHVybnMgLCBtYXJrZXRfcmV0dXJucykgLyB2YXIobWFya2V0X3JldHVybnMpCm1hcmtldF9wcmVtaXVtIDwtIG1lYW4obWFya2V0X3JldHVybnMpIC0gcmlza19mcmVlX3JhdGUKZXhwZWN0ZWRfcmV0dXJuIDwtIHJpc2tfZnJlZV9yYXRlICsgYmV0YSAqIG1hcmtldF9wcmVtaXVtCgpjYXQoIkJldGE6Iiwgcm91bmQoYmV0YSwgNCksICJcbiIpCmNhdCgiRXhwZWN0ZWQgUmV0dXJuIChDQVBNKToiLCByb3VuZChleHBlY3RlZF9yZXR1cm4gKiAxMDAsIDIpLCAiJVxuIikKCmBgYAoKIyMgKipMMTAgV0FDQyoqCgotICAgUmVwbGljYXRlIHRoZSBib29rIGNhc2Ugb2YgV0FDQwoKV2Ugd2lsbCB1c2UgdGhlIGJhc2ljIGZvcm11bGEgb2YgdGhlIFdBQ0MKCiQkCldBQ0M9IFxmcmFje0V9e0UrRH1yX2UrXGZyYWN7RH17RStEfXJfZCgxLXQpCiQkCgpXaGVyZToKCiRFJDogbWFya2V0IHZhbHVlIG9mIGVxdWl0eQoKJEQkOiBtYXJrZXQgdmFsdWUgb2YgZGVidAoKJHJfZSQ6IGNvc3Qgb2YgZXF1aXR5Cgokcl9kJDogY29zdCBvZiBkZWJ0CgokdCQ6IHRheCByYXRlCgpJbiB0aGlzIGNhc2UsIHdlIHdpbGwgY2FsY3VsYXRlIHRoZSBXQUNDIGZvciBUZXNsYS4KCmBgYHtyfQpnZXRTeW1ib2xzKCJUU0xBIikKCgoKb3VzdGFuZGluZ19zaGFyZXM8LSAzLjE5ZTkKbWFya2V0X2NhcCA8LSBUU0xBJFRTTEEuQWRqdXN0ZWRbRW9UXSAqIG91c3RhbmRpbmdfc2hhcmVzCm1hcmtldF92YWx1ZV9vZl9kZWJ0IDwtIDEyLjc4ZTkgICMgQWNjb3JkaW5nIHRvIFlhaG9vIEZpbmFuY2UKdGF4X3JhdGUgPC0gMC4yMiAgCmJldGEgPC0gMS42ICAjIFVubGV2ZXJhZ2VkIGJldGEgYWNjb3JkaW5nIHRvIFJldXRlcnMgKDIwMjQpCnJpc2tfZnJlZV9yYXRlIDwtIDAuMDQ3NSAgIyBmZWQgZnVuZHMgcmF0ZQptYXJrZXRfcmlza19wcmVtaXVtIDwtIDAuMDQgICMgbWFya2V0IHJpc2sgcHJlbWl1bSBhY2NvcmRpbmcgdG8gRGFtb2RhcmFuICgyMDI0KQoKCgpgYGAKCmBgYHtyfQojRGF0YSBmb3IgY2FsY3VsYXRpb24KY29zdF9vZl9kZWJ0IDwtIDAuMDQyNSAgCmNvc3Rfb2ZfZXF1aXR5IDwtIHJpc2tfZnJlZV9yYXRlICsgYmV0YSAqIG1hcmtldF9yaXNrX3ByZW1pdW0KdG90YWxfbWFya2V0X3ZhbHVlIDwtIG1hcmtldF9jYXAgKyBtYXJrZXRfdmFsdWVfb2ZfZGVidAp3ZWlnaHRfb2ZfZGVidCA8LSBtYXJrZXRfdmFsdWVfb2ZfZGVidCAvIHRvdGFsX21hcmtldF92YWx1ZQp3ZWlnaHRfb2ZfZXF1aXR5IDwtIG1hcmtldF9jYXAgLyB0b3RhbF9tYXJrZXRfdmFsdWUKCmNhdCgiY29zdCBvZiBkZWJ0OiIsY29zdF9vZl9kZWJ0LCAiXG4iKQpjYXQoImNvc3Qgb2YgZXF1aXR5Iixjb3N0X29mX2VxdWl0eSwgIlxuIikKY2F0KCJ3ZWlnaHQgb2YgZGVidDoiLHdlaWdodF9vZl9kZWJ0LCAiXG4iKQpjYXQoIndlaWdodCBvZiBlcXVpdHk6Iix3ZWlnaHRfb2ZfZXF1aXR5KQoKCmBgYAoKYGBge3J9CndhY2MgPC0gKHdlaWdodF9vZl9kZWJ0ICogY29zdF9vZl9kZWJ0ICogKDEgLSB0YXhfcmF0ZSkpICsgKHdlaWdodF9vZl9lcXVpdHkgKiBjb3N0X29mX2VxdWl0eSkKY2F0KCJXQUNDIGZvciBUZXNsYToiLCB3YWNjICogMTAwLCAiJSIpCgpgYGAKCiMjIEwxMSBEZXJpdmF0aXZlcwoKLSAgICpBc3N1bWUgdGhhdCB5b3UgcHVyY2hhc2VkIGFuIFMmUCA1MDAgZnV0dXJlcyBjb250cmFjdCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybSwgd2l0aCB0aGUgZmlyc3Qgc2V0dGxlbWVudCBkYXRlIGJleW9uZCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybS4gQWxzbyBhc3N1bWUgdGhhdCB5b3Ugc29sZCBhbiBTJlAgNTAwIGZ1dHVyZXMgY29udHJhY3Qgd2l0aCB0aGlzIHNhbWUgc2V0dGxlbWVudCBkYXRlIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtLiBHaXZlbiB0aGF0IHRoaXMgY29udHJhY3QgaGFzIGEgdmFsdWUgb2YgdGhlIGZ1dHVyZXMgcHJpY2UgdGltZXMgXCQyNTAsIGRldGVybWluZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBkb2xsYXIgdmFsdWUgb2YgdGhlIGNvbnRyYWN0IHlvdSBzb2xkIGFuZCB0aGUgZG9sbGFyIGFtb3VudCBvZiB0aGUgY29udHJhY3QgdGhhdCB5b3UgcHVyY2hhc2VkLioKCmBgYHtyfQpidXlfcHJpY2UgPC0gNDAwMApzZWxsX3ByaWNlIDwtIDQyMDAKY29udHJhY3RfbXVsdGlwbGllciA8LSAyNTAKaW5pdGFsX21hcmdpbiA8LSAwLjIwICogKGJ1eV9wcmljZSAqIGNvbnRyYWN0X211bHRpcGxpZXIpCm1vbnRoc19pbl90ZXJtIDwtIDUKCmdhaW5fbG9zcyA8LSAoc2VsbF9wcmljZSAtIGJ1eV9wcmljZSkgKiBjb250cmFjdF9tdWx0aXBsaWVyCnByaW50KGdhaW5fbG9zcykKYGBgCgotICAgKkFzc3VtZSB0aGF0IHlvdSBpbnZlc3RlZCBhbiBpbml0aWFsIG1hcmdpbiBvZiAyMCBwZXJjZW50IG9mIHRoZSBhbW91bnQgdGhhdCB5b3Ugd291bGQgb3dlIHRvIHB1cmNoYXNlIHRoZSBTJlAgNTAwIGluZGV4IGF0IHRoZSBzZXR0bGVtZW50IGRhdGUuIE1lYXN1cmUgeW91ciByZXR1cm4gZnJvbSB0YWtpbmcgYSBwb3NpdGlvbiBpbiB0aGUgUyZQIDUwMCBpbmRleCBmdXR1cmVzIGFzIGZvbGxvd3MuIFRha2UgdGhlIGRpZmZlcmVuY2UgZGV0ZXJtaW5lZCBpbiB0aGUgcHJldmlvdXMgcXVlc3Rpb24gKHdoaWNoIHJlcHJlc2VudHMgdGhlIGRvbGxhciBhbW91bnQgb2YgdGhlIGdhaW4gb24gdGhlIGZ1dHVyZXMgcG9zaXRpb24pIGFuZCBkaXZpZGUgaXQgYnkgdGhlIGFtb3VudCB5b3Ugb3JpZ2luYWxseSBpbnZlc3RlZCAodGhlIGFtb3VudCB5b3Ugb3JpZ2luYWxseSBpbnZlc3RlZCBpcyAyMCBwZXJjZW50IG9mIHRoZSBkb2xsYXIgdmFsdWUgb2YgdGhlIGZ1dHVyZXMgY29udHJhY3QgdGhhdCB5b3UgcHVyY2hhc2VkKS4qCgpgYGB7cn0KCnJldHVybiA8LSBnYWluX2xvc3MgLyBpbml0YWxfbWFyZ2luCnByaW50KHJldHVybikKYGBgCgotICAgKlRoZSByZXR1cm4gdGhhdCB5b3UganVzdCBkZXJpdmVkIGluIHRoZSBwcmV2aW91cyBxdWVzdGlvbiBpcyBub3QgYW5udWFsaXplZC4gVG8gYW5udWFsaXplIHlvdXIgcmV0dXJuLCBtdWx0aXBseSBpdCBieSAxMi9tLCB3aGVyZSBtIGlzIHRoZSBudW1iZXIgb2YgbW9udGhzIGluIHlvdXIgc2Nob29sIHRlcm0uKgoKV2UgY2FsY3VsYXRlIHRoZSBnYWluLyBsb3NzLCByZXR1cm4sIGFuZCBhbm51YWxpemVkIHJldHVybiBmb3IgUyZQIDUwMCBmdXR1cmVzIGNvbnRyYWN0LgoKYGBge3J9CgoKYW5udWFsaXplZF9yZXR1cm4gPC0gcmV0dXJuICogKDEyIC8gbW9udGhzX2luX3Rlcm0pCgpjYXQoIkdhaW4vTG9zcyBvbiBGdXR1cmVzIENvbnRyYWN0IDogJCIsIGdhaW5fbG9zcywgIlxuIikKY2F0KCJSZXR1cm46ICIsIHJvdW5kKHJldHVybiAqIDEwMCwgMiksICIlXG4iKQpjYXQoIkFubnVhbGl6ZWQgUmV0dXJuOiAiLCByb3VuZChhbm51YWxpemVkX3JldHVybiAqIDEwMCwgMiksICIlXG4iKQoKYGBgCgotICAgKkFzc3VtZSB0aGF0IHlvdSBwdXJjaGFzZWQgYSBjYWxsIG9wdGlvbiAocmVwcmVzZW50aW5nIDEwMCBzaGFyZXMpIG9uIHRoZSBzcGVjaWZpYyBzdG9jayB0aGF0IHlvdSBpZGVudGlmaWVkIG9mIHRoaXMgcHJvamVjdC4gV2hhdCB3YXMgeW91ciByZXR1cm4gZnJvbSBwdXJjaGFzaW5nIHRoaXMgb3B0aW9uPyBJZiB0aGUgcHJlbWl1bSBmb3IgdGhpcyBvcHRpb24gaXMgbm90IHF1b3RlZCBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSwgbWVhc3VyZSB0aGUgcmV0dXJuIGFzIGlmIHlvdSBoYWQgZXhlcmNpc2VkIHRoZSBjYWxsIG9wdGlvbiBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSAoYXNzdW1pbmcgdGhhdCBpdCBpcyBmZWFzaWJsZSB0byBleGVyY2lzZSB0aGUgb3B0aW9uIGF0IHRoYXQgdGltZSkuIFRoYXQgaXMsIHRoZSByZXR1cm4gaXMgYmFzZWQgb24gcHVyY2hhc2luZyB0aGUgc3RvY2sgYXQgdGhlIG9wdGlvbuKAmXMgc3RyaWtlIHByaWNlIGFuZCB0aGVuIHNlbGxpbmcgdGhlIHN0b2NrIGF0IGl0cyBtYXJrZXQgcHJpY2UgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0uKgoKLSAgICpBbm51YWxpemUgdGhlIHJldHVybiBvbiB5b3VyIG9wdGlvbiBieSBtdWx0aXBseWluZyB0aGUgcmV0dXJuIHlvdSBkZXJpdmVkIGluIHRoZSBwcmV2aW91cyBxdWVzdGlvbiBieSAxMi9tLCB3aGVyZSBtIHJlcHJlc2VudHMgdGhlIG51bWJlciBvZiBtb250aHMgaW4geW91ciBzY2hvb2wgdGVybSoKCi0gICAqQ29tcGFyZSB0aGUgcmV0dXJuIG9uIHlvdXIgY2FsbCBvcHRpb24gdG8gdGhlIHJldHVybiB0aGF0IHlvdSB3b3VsZCBoYXZlIGVhcm5lZCBpZiB5b3UgaGFkIHNpbXBseSBpbnZlc3RlZCBpbiB0aGUgc3RvY2sgaXRzZWxmLiBOb3RpY2UgaG93IHRoZSBtYWduaXR1ZGUgb2YgdGhlIHJldHVybiBvbiB0aGUgY2FsbCBvcHRpb24gaXMgbXVjaCBsYXJnZXIgdGhhbiB0aGUgbWFnbml0dWRlIG9mIHRoZSByZXR1cm4gb24gdGhlIHN0b2NrIGl0c2VsZi4gVGhhdCBpcywgdGhlIGdhaW5zIGFyZSBsYXJnZXIgYW5kIHRoZSBsb3NzZXMgYXJlIGxhcmdlciB3aGVuIGludmVzdGluZyBpbiBjYWxsIG9wdGlvbnMgb24gYSBzdG9jayBpbnN0ZWFkIG9mIHRoZSBzdG9jayBpdHNlbGYuKgoKV2UgY2FsY3VsYXRlIHRoZSByZXR1cm4gb24gYSBjYWxsIG9wdGlvbiBhbmQgYW5hbHl6ZSB0aGUgcmVzdWx0cy4KCmBgYHtyfQpidXlfcHJlbWl1bSA8LSAyMApzZWxsX3ByZW1pdW0gPC0gMzAKc3RyaWtlX3ByaWNlIDwtIDQwMApzdG9ja19wcmljZV9lbmQgPC0gNDUwCm1vbnRoc19pbl90ZXJtIDwtIDUgCgpjYWxsX3JldHVybiA8LSAoc2VsbF9wcmVtaXVtIC0gYnV5X3ByZW1pdW0pIC8gYnV5X3ByZW1pdW0KCmV4ZXJjaXNlX3JldHVybiA8LSAoc3RvY2tfcHJpY2VfZW5kIC0gc3RyaWtlX3ByaWNlKSAvIGJ1eV9wcmVtaXVtCgphbm51YWxpemVkX2NhbGxfcmV0dXJuIDwtIGNhbGxfcmV0dXJuICogKDEyIC8gbW9udGhzX2luX3Rlcm0pCgpjYXQoIkNhbGwgT3B0aW9uIFJldHVybjogIiwgcm91bmQoY2FsbF9yZXR1cm4gKiAxMDAsIDIpLCAiJVxuIikKY2F0KCJFeGVyY2lzZSBSZXR1cm46ICIsIHJvdW5kKGFubnVhbGl6ZWRfY2FsbF9yZXR1cm4gKiAxMDAsIDIpLCAiJVxuIikKY2F0KCJBbm51YWxpemVkIENhbGwgUmV0dXJuOiAiLCByb3VuZChhbm51YWxpemVkX2NhbGxfcmV0dXJuICogMTAwLCAyKSwgIiVcbiIpCmBgYAoKKipEZXRlcm1pbmluZyBzd2FwIHBheW1lbnRzKioKCi0gICAqQXNzdW1lIHRoYXQsIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtLCB5b3UgZW5nYWdlZCBpbiBhIGZpeGVkLWZvci1mbG9hdGluZyByYXRlIHN3YXAgaW4gd2hpY2ggeW91IGFncmVlZCB0byBwYXkgNiBwZXJjZW50IGluIGV4Y2hhbmdlIGZvciB0aGUgcHJldmFpbGluZyAyNi13ZWVrIFQtYmlsbCByYXRlIHRoYXQgZXhpc3RzIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtLiBBc3N1bWUgdGhhdCB5b3VyIHN3YXAgYWdyZWVtZW50IHNwZWNpZmllcyB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSBhcyB0aGUgb25seSB0aW1lIGF0IHdoaWNoIGEgc3dhcCB3aWxsIG9jY3VyIGFuZCB0aGF0IHRoZSBub3Rpb25hbCBhbW91bnQgaXMgXCQxMCBtaWxsaW9uLiBEZXRlcm1pbmUgdGhlIGFtb3VudCB0aGF0IHlvdSBvd2Ugb24gdGhlIHN3YXAsIHRoZSBhbW91bnQgeW91IGFyZSBvd2VkIG9uIHRoZSBzd2FwLCBhbmQgdGhlIGRpZmZlcmVuY2UuIERpZCB5b3UgZ2FpbiBvciBsb3NlIGFzIGEgcmVzdWx0IG9mIHRoZSBzd2FwPyoKCldlIGNhbGN1bGF0ZSB0aGUgZml4ZWQgYW5kIGZsb2F0aW5nIHBheW1lbnRzIGZvciBhIHN3YXAgYWdyZWVtZW50LgoKYGBge3J9Cm5vdGlvbmFsX2Ftb3VudCA8LSAxMGU2CmZpeGVkX3JhdGUgPC0gMC4wNgpmbG9hdGluZ19yYXRlX2VuZCA8LSAwLjA1NQoKZml4ZWRfcGF5bWVudCA8LSBub3Rpb25hbF9hbW91bnQgKiBmaXhlZF9yYXRlCmZsb2F0aW5nX3BheW1lbnQgPC0gbm90aW9uYWxfYW1vdW50ICogZmxvYXRpbmdfcmF0ZV9lbmQKbmV0X3BheW1lbnQgPC0gZml4ZWRfcGF5bWVudCAtIGZsb2F0aW5nX3BheW1lbnQKCmNhdCgiRml4ZWQgUGF5bWVudDogJCIsIGZpeGVkX3BheW1lbnQsICJcbiIpCmNhdCgiRmxvYXRpbmcgUGF5bWVudDogJCIsIGZsb2F0aW5nX3BheW1lbnQsICJcbiIpCmNhdCgiTmV0IFBheW1lbnQ6ICQiLCBuZXRfcGF5bWVudCwgIlxuIikKCmBgYAoKKipNZWFzdXJpbmcgYW5kIGV4cGxhaW5pbmcgZXhjaGFuZ2UgcmF0ZSBtb3ZlbWVudHMqKgoKLSAgICpEZXRlcm1pbmUgdGhlIHBlcmNlbnRhZ2UgY2hhbmdlIGluIHRoZSB2YWx1ZSBvZiB0aGUgQnJpdGlzaCBwb3VuZCBvdmVyIHRoZSBzY2hvb2wgdGVybS4gRGlkIHRoZSBwb3VuZCBhcHByZWNpYXRlIG9yIGRlcHJlY2lhdGUgYWdhaW5zdCB0aGUgZG9sbGFyPyoKCi0gICAqRGV0ZXJtaW5lIHRoZSBwZXJjZW50YWdlIGNoYW5nZSBpbiB0aGUgdmFsdWUgb2YgdGhlIEphcGFuZXNlIHllbiBvdmVyIHRoZSBzY2hvb2wgdGVybS4gRGlkIHRoZSB5ZW4gYXBwcmVjaWF0ZSBvciBkZXByZWNpYXRlIGFnYWluc3QgdGhlIGRvbGxhcj8qCgotICAgKkRldGVybWluZSB0aGUgcGVyY2VudGFnZSBjaGFuZ2UgaW4gdGhlIHZhbHVlIG9mIHRoZSBNZXhpY2FuIHBlc28gb3ZlciB0aGUgc2Nob29sIHRlcm0uIERpZCB0aGUgcGVzbyBhcHByZWNpYXRlIG9yIGRlcHJlY2lhdGUgYWdhaW5zdCB0aGUgZG9sbGFyPyoKCi0gICAqRGV0ZXJtaW5lIHRoZSBwZXIgdW5pdCBnYWluIG9yIGxvc3MgaWYgeW91IGhhZCBwdXJjaGFzZWQgQnJpdGlzaCBwb3VuZCBmdXR1cmVzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHRlcm0gYW5kIHNvbGQgQnJpdGlzaCBwb3VuZCBmdXR1cmVzIGF0IHRoZSBlbmQgb2YgdGhlIHRlcm0uKgoKLSAgICpHaXZlbiB0aGF0IGEgc2luZ2xlIGZ1dHVyZXMgY29udHJhY3Qgb24gQnJpdGlzaCBwb3VuZHMgcmVwcmVzZW50cyA2Miw1MDAgcG91bmRzLCBkZXRlcm1pbmUgdGhlIGRvbGxhciBhbW91bnQgb2YgeW91ciBnYWluIG9yIGxvc3MuKgoKV2UgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIGNoYW5nZSBhbmQgZ2Fpbi8gbG9zcyBmb3IgR0JQLyBVU0QgZnV0dXJlcy4KCmBgYHtyfQpzdGFydF9yYXRlX2dwZCA8LSAxLjIKZW5kX3JhdGVfZ3BkIDwtIDEuMjUKY29udHJhY3Rfc2l6ZV9nYnAgPC0gNjI1MDAKCnBlcmNlbnRfY2hhbmdlX2dwZCA8LSAoKGVuZF9yYXRlX2dwZCAtIHN0YXJ0X3JhdGVfZ3BkKSAvIHN0YXJ0X3JhdGVfZ3BkKSAqIDEwMAoKZ2Fpbl9sb3NzX3Blcl91bml0X2dwZCA8LSBlbmRfcmF0ZV9ncGQgLSBzdGFydF9yYXRlX2dwZAp0b3RhbF9nYWluX2xvc3NfZ3BkIDwtIGdhaW5fbG9zc19wZXJfdW5pdF9ncGQgKiBjb250cmFjdF9zaXplX2dicAoKY2F0KCJHQlAgUGVyY2FudGFnZSBDaGFuZ2U6ICIsIHJvdW5kKHBlcmNlbnRfY2hhbmdlX2dwZCwyKSwgIiVcbiIpCmNhdCgiVG90YWwgR2Fpbi9Mb3NzIG9uIEdCUCBGdXR1cmVzIENvbnRyYWN0OiAkIiwgcm91bmQodG90YWxfZ2Fpbl9sb3NzX2dwZCwyKSwgIiVcbiIpCgpgYGAKCiMjIEwxMiBDYXBpdGFsIHJlcXVpcmVtZW50cwoKT3BlcmF0aW9uYWwgUmlzawoKV2UgY2FsY3VsYXRlIHRoZSBvcGVyYXRpb25hbCByaXNrIGNhcGl0YWwgZm9yIEJhbmsgb2YgQW1lcmljYSAoQm9BKSBhbmQgRGV1dHNjaGUgQmFuayAoREIpIHVzaW5nIHRoZSBCYXNpYyBJbmRpY2F0b3IgQXBwcm9hY2ggdW5kZXIgQmFzZWwgSUlJOgoKYGBge3J9CgphbHBoYSA8LSAwLjE1Cmdyb3NzX2luY29tZV9ib2EgPC0gOTBlOSAKZ3Jvc3NfaW5jb21lX2RiIDwtIDI1ZTkgKiAxLjEgCgpvcGVyYXRpb25hbF9yaXNrX2JvYSA8LSBhbHBoYSAqIGdyb3NzX2luY29tZV9ib2EKb3BlcmF0aW9uYWxfcmlza19kYiA8LSBhbHBoYSAqIGdyb3NzX2luY29tZV9kYgoKCmNhdCgiT3BlcmF0aW9uYWwgUmlzayBDYXBpdGFsIChCb0EpOiAkIiwgZm9ybWF0KG9wZXJhdGlvbmFsX3Jpc2tfYm9hLCBiaWcubWFyayA9ICIsIiksICJcbiIpCmNhdCgiT3BlcmF0aW9uYWwgUmlzayBDYXBpdGFsIChEQik6ICQiLCBmb3JtYXQob3BlcmF0aW9uYWxfcmlza19kYiwgYmlnLm1hcmsgPSAiLCIpLCAiXG4iKQoKYGBgCgpXZSBjYWxjdWxhdGUgdGhlIG1hcmtldCByaXNrIGNhcGl0YWwgdXNpbmcgdGhlIFZhbHVlIGF0IHJpc2sgKFZhUikgYXBwcm9hY2g6CgpgYGB7cn0KayA8LSAzIAp2YXJfYm9hIDwtIDVlOQp2YXJfZGIgPC0gM2U5ICogMS4xIAoKbWFya2V0X3Jpc2tfYm9hIDwtIGsgKiB2YXJfYm9hCm1hcmtldF9yaXNrX2RiIDwtIGsgKiB2YXJfZGIKCmNhdCgiTWFya2V0IFJpc2sgQ2FwaXRhbCAoQm9BKTogJCIsIGZvcm1hdChtYXJrZXRfcmlza19ib2EsIGJpZy5tYXJrID0gIiwiKSwgIlxuIikKY2F0KCJNYXJrZXQgUmlzayBDYXBpdGFsIChEQik6ICQiLCBmb3JtYXQobWFya2V0X3Jpc2tfZGIsIGJpZy5tYXJrID0gIiwiKSwgIlxuIikKCmBgYAoKV2UgY2FsY3VsYXRlIGNyZWRpdCByaXNrIGNhcGl0YWwgYmFzZWQgb24gdGhlIGV4cG9zdXJlIGFtb3VudHMsIHJpc2sgd2VpZ2h0cywgYW5kIHJlZ3VsYXRvcnkgY2FwaXRhbCByZXF1aXJlbWVudHMKCmBgYHtyfQpyZWd1bGF0b3J5X2NhcGl0YWxfcmVxdWlyZW1lbnQgPC0gMC4wOCAKCgpsb2FuX2V4cG9zdXJlX2JvYSA8LSAyMDBlOQpnb3Zfc2VjdXJpdGllc19ib2EgPC0gNTBlOQpsb2FuX2V4cG9zdXJlX2RiIDwtIDE1MGU5ICogMS4xIApnb3Zfc2VjdXJpdGllc19kYiA8LSA0MGU5ICogMS4xCgpsb2FuX3Jpc2tfd2VpZ2h0IDwtIDEuMDAgCmdvdl9yaXNrX3dlaWdodCA8LSAwLjAwICAKCmNyZWRpdF9yaXNrX2JvYSA8LSByZWd1bGF0b3J5X2NhcGl0YWxfcmVxdWlyZW1lbnQgKiAobG9hbl9leHBvc3VyZV9ib2EgKiBsb2FuX3Jpc2tfd2VpZ2h0ICsgZ292X3NlY3VyaXRpZXNfYm9hICogZ292X3Jpc2tfd2VpZ2h0KQpjcmVkaXRfcmlza19kYiA8LSByZWd1bGF0b3J5X2NhcGl0YWxfcmVxdWlyZW1lbnQgKiAobG9hbl9leHBvc3VyZV9kYiAqIGxvYW5fcmlza193ZWlnaHQgKyBnb3Zfc2VjdXJpdGllc19kYiAqIGdvdl9yaXNrX3dlaWdodCkKCmNhdCgiQ3JlZGl0IFJpc2sgQ2FwaXRhbCAoQm9BKTogJCIsIGZvcm1hdChjcmVkaXRfcmlza19ib2EsIGJpZy5tYXJrID0gIiwiKSwgIlxuIikKY2F0KCJDcmVkaXQgUmlzayBDYXBpdGFsIChEQik6ICQiLCBmb3JtYXQoY3JlZGl0X3Jpc2tfZGIsIGJpZy5tYXJrID0gIiwiKSwgIlxuIikKCmBgYAoKV2UgY2FsY3VsYXRlIHRoZSB0b3RhbCBjYXBpdGFsIHJlcXVpcmVtZW50cyBmb3IgZWFjaCBiYW5rIGJ5IHN1bW1pbmcgb3BlcmF0aW9uYWwsIG1hcmtldCwgYW5kIGNyZWRpdCByaXNrIGNhcGl0YWxzLgoKYGBge3J9CnRvdGFsX2NhcGl0YWxfYm9hIDwtIG9wZXJhdGlvbmFsX3Jpc2tfYm9hICsgbWFya2V0X3Jpc2tfYm9hICsgY3JlZGl0X3Jpc2tfYm9hCnRvdGFsX2NhcGl0YWxfZGIgPC0gb3BlcmF0aW9uYWxfcmlza19kYiArIG1hcmtldF9yaXNrX2RiICsgY3JlZGl0X3Jpc2tfZGIKCmNhdCgiVG90YWwgQ2FwaXRhbCBSZXF1aXJlbWVudCAoQm9BKTogJCIsIGZvcm1hdCh0b3RhbF9jYXBpdGFsX2JvYSwgYmlnLm1hcmsgPSAiLCIpLCAiXG4iKQpjYXQoIlRvdGFsIENhcGl0YWwgUmVxdWlyZW1lbnQgKERCKTogJCIsIGZvcm1hdCh0b3RhbF9jYXBpdGFsX2RiLCBiaWcubWFyayA9ICIsIiksIlxuIikKYGBgCg==