Introduction

Alvin Tan created interesting Noteboook, which is partly used in this presentation. The Investopedia information source is also used. In addition, a Bookdown of Technical Analysis with R (second edition) from Ko Chiu Yu and ChatGPT were helpful with the coding in R.

Technical analysis is a method to predict price movement in the financial markets. Unlike the usual balance sheet analysis (fundamental investing), technical analysis estimates the value of a given stock using underlying trends of the price movement. The core assumption behind this method is that the fundamentals (information from financial statements) were factored into the price fluctuation, hence, detecting the patterns and signals from the fluctuation should provide sufficient indicator for future performance.

For this project, we are going to explore some of the common technical indicators using the TQQQ Exchange trade fund (ETF) stock. Among leveraged ETFs, ProShares UltraPro QQQ (TQQQ) is one of the largest with assets under management of \(\$18.56\) billion as of July 2022. TQQQ is also one of the more heavily traded leveraged ETFs in the U.S. with an average daily volume of \(\$5.29\) billion (compared with QQQ’s \(\$21\) billion).

TQQQ carries an expense ratio of 0.95%.

#install.packages("quantmod")
Warning message:
In unloadNamespace(package) :
  namespace ‘htmltools’ is imported by ‘rmarkdown’ so cannot be unloaded
#install.packages("data.table")
#install.packages("ggplot2")
#install.packages("tidyquant")
library(quantmod)
Loading required package: xts
Loading required package: zoo

Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

Loading required package: TTR
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
library(data.table)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
data.table 1.14.8 using 8 threads (see ?getDTthreads).  Latest news: r-datatable.com

Attaching package: ‘data.table’

The following objects are masked from ‘package:xts’:

    first, last
library(ggplot2)
library(tidyquant)  
Loading required package: lubridate

Attaching package: ‘lubridate’

The following objects are masked from ‘package:data.table’:

    hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union

Loading required package: PerformanceAnalytics

Attaching package: ‘PerformanceAnalytics’

The following object is masked from ‘package:graphics’:

    legend

Data Extraction & Manipulation, Data structure

TQQQ data is extracted using the getSymbols function from Yahoo Finance. Alternatively, the source can be replaced with FRED, MySQL, Google, or others. The data extracted should be in an ‘xts’ object - a format commonly used in time series analysis where observations are recorded in a matrix structure with an index of corresponding time.

Technically, analysis can be done in xts format alone, but for the sake of simplicity, data is converted into a standard dataframe and index column is renamed as “Date’. The end result is shown as below:

getSymbols('TSLA',src = 'yahoo')       ## change TQQQ ticker to Your ticker symbol
[1] "TSLA"

structure of the stock data

stock <<- as.data.table(TSLA)        ###### change TQQQ ticker to Your ticker symbol  #########
names(stock)[1] <- c('Date')

tail(stock)

Interpretation of the HLCO graph

In finance, HLCO graph is a type of financial chart that plots the high, low, close, and open prices for a given period of time. The HLCO chart is similar to a candlestick chart, but it includes the open price in addition to the high, low, and close prices.

The interpretation of an HLCO chart can provide insights into the price action of a security during a given period of time. Here is a brief explanation of how to interpret each component of an HLCO chart:

  1. High: The top of the vertical line represents the highest price reached during the given period. This shows the highest price that buyers were willing to pay for the security during the period.

  2. Low: The bottom of the vertical line represents the lowest price reached during the given period. This shows the lowest price that sellers were willing to accept for the security during the period.

  3. Close: The horizontal line to the right of the vertical line represents the closing price for the period. This shows the final price at which the security traded during the period.

  4. Open: The horizontal line to the left of the vertical line represents the opening price for the period. This shows the initial price at which the security traded during the period.

By looking at the patterns of the high, low, close, and open prices in an HLCO chart, traders and investors can gain insight into the overall trend and sentiment of the market for the given security. For example, a long green candlestick with a high close and low open may indicate bullish sentiment, while a long red candlestick with a low close and high open may indicate bearish sentiment.

# feel free to change "HLCO" to "candlestick" or to some other types ("lines", "auto"). 
chartSeries(stock, subset='2020-01-01::2020-09-23', type = "candlesticks", bar.type = "ohlc",theme=chartTheme('white'))

HLCO graph is a type of financial chart that plots the high, low, close, and open prices for a given period of time. Early 2020: Tesla’s stock price showed a strong uptrend, rising from around $430 to over $900. The HLCO graph indicated a bullish trend with higher highs and higher lows. February - March: Global market correction due to COVID-19 impacted Tesla’s stock price, leading to a sharp pullback. The HLCO graph showed significant price declines with larger red candlesticks. March - April: Tesla’s stock price began to recover, transitioning from predominantly red candlesticks to a mix of green and red. Higher volatility and wider price swings were observed. Mid-2020: Tesla’s stock price entered a consolidation phase, trading within a narrow range. The HLCO graph showed smaller candlesticks as the stock price consolidated. Late 2020: Tesla’s stock price experienced a strong bull run, reaching new all-time highs. The HLCO graph indicated significant price gains with large green candlesticks. Tesla’s inclusion in the S&P 500 index further fueled investor optimism.

Volume

One of the most common basic indicators traders examine is the trading volume. Trading volume is an indication for the ‘activeness’ of a financial instrument. Depending on the financial instruments, trading volume can be measured either using the number of stocks traded or number of contracts with changed ownerships. To put this in practice, if an increase in volume is observed with a steady increase in price, the instrument can be viewed as steady and strong. However, if volume and price are changing in different directions, a reversal might be happened.

You can analyze it in the previous picture.

Price - Moving Average

In terms of trading price, traders often observed the trends based on the charts shape and cross in ways that form shapes - often times with weird names like ‘head and shoulder’, ’ reverse head and sholder’, ‘double top’, ‘golden cross’, etc. A golden cross indicates a long term bull market going forward, whereas the death cross is the exact opposite, indicating a potential long term bear market. Both of these refer to the confirmation of long term trend by the occurance of the overlapping of moving average lines as shown below.

In the quantmod package in R, the addMA function can be used to add moving averages to a financial time series chart. There are various methods of calculating moving averages that can be used in this function, which I will describe below:

  1. Simple Moving Average (SMA): This is the most basic type of moving average and is calculated by taking the average of a set number of periods of data. For example, a 20-day SMA would be the average of the closing prices for the last 20 days. This method gives equal weight to all periods in the moving average. \[SMA_t = \frac{P_t + \dots + P_{t-n+1}}{n}\] Buy signal arises when a short-run SMA crosses from below to above a long-run SMA. Sell signal arrises when a short-run SMA crosses from above to below a long-run SMA.

  2. Weighted Moving Average (WMA): This method assigns a weight to each data point in the moving average, with more recent data points given greater weight. The weights can be calculated in various ways, such as linear or exponential.

  3. Exponential Moving Average (EMA): This method is similar to the WMA, but it gives greater weight to more recent data points using an exponential decay formula. The formula used to calculate the EMA involves a smoothing factor, which determines the weight given to each data point. \[EMA_t = \beta P_t + (1-\beta) EMA_{t-1}\] where the smoothing coefficient is usually defined \(\beta = \frac{2}{n+1} \in (0;1)\).

  4. Double Exponential Moving Average (DEMA): This method is similar to the EMA, but it uses a second EMA to smooth the first EMA. This results in a smoother moving average that is less sensitive to short-term fluctuations.

  5. Triple Exponential Moving Average (TEMA): This method is similar to the DEMA, but it uses a third EMA to further smooth the moving average. This method is even less sensitive to short-term fluctuations than the DEMA.

These are the main types of moving averages that can be used in the addMA function in quantmod. Each method has its own advantages and disadvantages, and the choice of method will depend on the specific needs of the analysis being performed.

chartSeries(stock,
            subset='2020-01-01::2020-09-23', type = "candlestick",
            theme=chartTheme('white'))

addSMA(n = 12, on = 1, with.col = Cl, overlay = TRUE, col = "brown")

addSMA(n = 24, on = 1, with.col = Cl, overlay = TRUE, col = "blue")

NA
NA

The chart of Moving Average provides us with helpful information about the buy and sell signals of the company. Through out form January to March: In the month February Tesla’s stock price began a powerful uptrend, supported by positive news regarding its delivery numbers and profitability. This crossover signaled a buy opportunity for traders, aligning with the stock’s upward movement. From April to June the MA began to converge towards the signal line as Tesla’s price entered a consolidation phase. From July to August till September Tesla’s stock price continued its upward, reaching new all-time highs. Finally from September the MA has dropped for a shorter period, it wasn’t that significant.

Moving Average Convergence Divergence (MACD)

MACD stands for Moving Average Convergence Divergence. It is a popular technical analysis indicator that is used to identify changes in trend direction, momentum, and potential buy and sell signals in financial markets.

The MACD is calculated by subtracting the 26-period Exponential Moving Average (EMA) from the 12-period EMA. The result of this calculation is then plotted on a chart along with a 9-period EMA, which is often referred to as the “signal line”.

\[MACD(S=12,L=26)_t = EMA(t,S) - EMA(t,L)\]

The MACD line oscillates above and below the signal line, indicating changes in momentum and trend direction. When the MACD line crosses above the signal line, it is considered a bullish signal, indicating a potential buy opportunity. Conversely, when the MACD line crosses below the signal line, it is considered a bearish signal, indicating a potential sell opportunity. In other words Buy signal arises when MACD crosses from below to above the signal line, and Sell signal arises when MACD crosses from above to below the signal line.

The MACD can also be used to identify divergences between the MACD line and the price of the security being analyzed. When the MACD line diverges from the price, it can be an indication that a trend reversal may be imminent.

Traders and investors often use the MACD in conjunction with other technical analysis tools, such as support and resistance levels, to make informed trading decisions. It is important to note that while the MACD can be a useful indicator, it is not infallible and should be used in conjunction with other forms of analysis to make informed trading decisions.

chartSeries(stock,
            subset='2020-01-01::2020-09-23', type = "bars",
            theme=chartTheme('white'))

addMACD(fast=12,slow=26,signal=9,type="EMA")

The chart of Moving Average Convergence Divergence pis a popular technical analysis indicator that is used to identify changes in trend direction, momentum, and potential buy and sell signals in financial markets. Through out form January to February: In the month February Tesla’s stock price began a powerful uptrend, supported by positive news regarding its delivery numbers and profitability. This crossover signaled a buy opportunity for traders, aligning with the stock’s upward movement. From March to May the MACD began to deacrease significantly. From May to August Tesla’s stock price continued its upward, reaching new all-time highs. Finally from August to September the MACD has dropped for a shorter period, it wasn’t that significant, then started to reach highs, expecially in the month September.Throughout 2020, Tesla’s Moving Average Convergence Divergence (MACD) indicator provided valuable insights into the stock’s price momentum and trend reversals. Despite periods of volatility and uncertainty, the MACD effectively identified buy and sell opportunities for traders, aligning with Tesla’s price movements.

Bollinger Band

Apart from the death and golden crosses, the moving average lines can be used to compute the Bollinger Band. A Bollinger Band is made up of 3 lines, the simple moving average, an upper boundary and a lower boundary. Simply put, this is a measure to tell if a financial instrument is overbought or oversold. The closer the prices move to the upper band, the more likely the financial instrument is overbought, which may lead to a reversal (market correction). Likewise, if the price is moving to the lower band, the market has a higher probability of being oversold, which will lead to a upward reversal.

For Bollinger band, channel is drawn over a trend line plus/minus 2 standard deviation (SD). Trend line: SMA or EMA of price (price can be closing price or average of high, low, and close).

Bandwidth: determined by the asset volatility \[B_{t,n} = k*sdev(P_t,n)\] where usually we have \(k=2\) and \(n=20\). The lower and upper bands are defined \[up_t = P_t + B_{t,n} \quad \text{and} \quad down_t = P_t - B_{t,n} \]

Bollinger Bands are a popular technical analysis tool used by traders to measure the volatility and potential price movements of a financial instrument. They are comprised of three lines: a simple moving average (SMA), an upper band, and a lower band.

The SMA is typically calculated using a 20-day moving average, but can be adjusted to fit the specific time frame being analyzed. The upper band is calculated by adding two standard deviations to the SMA, while the lower band is calculated by subtracting two standard deviations from the SMA.

The bands are plotted on a chart, with the SMA as the center line and the upper and lower bands representing two standard deviations away from the SMA. As the volatility of the financial instrument increases or decreases, the bands expand or contract accordingly.

Traders use Bollinger Bands to identify potential buying and selling opportunities. When the price of the financial instrument touches or crosses the upper band, it is considered overbought, and a sell signal may be generated. When the price touches or crosses the lower band, it is considered oversold, and a buy signal may be generated. Ko Chiu Yu says that Buy signal arises when price is above the band and Sell signal arises when price is below the band, which is in fact the same.

It is important to note that Bollinger Bands should not be used in isolation and should be used in conjunction with other technical analysis tools to make informed trading decisions. Additionally, the bands may not be effective in all market conditions, and traders should adjust their strategies accordingly.

chartSeries(stock,
            subset='2020-01-01::2020-09-23', type = "bars",
            theme=chartTheme('white'))

addBBands(n = 20, sd = 2, maType = "SMA", draw = 'bands', on = -1)

Bollinger Bands are a popular technical analysis tool used by traders to measure the volatility and potential price movements of a financial instrument. Bollinger Bands consist of three lines: the middle band, which is a 20-day simple moving average (SMA), and an upper and lower band that are two standard deviations away from the middle band.In early 2020, Tesla’s stock price fluctuated within the Bollinger Bands, with the upper band serving as a resistance level and the lower band as a support level. The widening of the Bollinger Bands indicated increased price volatility. By mid-2020, Tesla’s stock price had rebounded and consistently traded above the middle Bollinger Band, indicating strong bullish momentum. There were occasional breaches of the upper band, suggesting an upward trend in the stock price.Throughout July to September, Tesla’s stock price continued to climb with heightened volatility, leading to further widening of the Bollinger Bands. Despite this, the stock price mostly remained above the middle band, signaling ongoing bullish sentiment. In the latter part of 2020 (October-December), Tesla’s stock price continued to rise due to positive market sentiment regarding the company’s performance and future prospects. Despite some minor setbacks, the stock price generally stayed above the middle Bollinger Band, indicating sustained bullish momentum.

Relative Strength Index (RSI)

Similar to the Bollinger Band, RSI is a momentum indicator that evaluate the overbought and oversold condition of a financial instrument. The only major difference between these is the method of display. RSI is plotted as an oscillator with a range between 0 to 100 whereas the Bollinger Band are plotted along the moving average line of the price. Hence, a huge advantage of RSI over Bollinger Band is the ability to do cross comparison across multiple instruments.

Usually, RSI is evaluated using a 30-70 cutoffs. An RSI reading of 70 or above indicates an overbought or overvalued condition whereas an RSI of below 30 indicates a undervalued condition.

Relative Strength Index (RSI) is a popular technical analysis indicator used to measure the strength of price movements in financial markets. It was developed by J. Welles Wilder Jr. and is used to identify overbought and oversold conditions.

The calculation of RSI requires several steps:

  1. Whether price has gone up or down each day

  2. Relative strength (RS): the ratio of the (simple or exponential) average numbers of up day to the average of down day

  3. Relative strength index (RSI): normalize RS to the scale from 0 to 100.

Step 1. Calculate

\[U_t = 1 \quad \text{if} \quad P_t > P_{t-1}, \quad \text{otherwise} \quad U_t=0\]

\[D_t = 1 \quad \text{if} \quad P_t < P_{t-1}, \quad \text{otherwise} \quad D_t= 0\] Step 2: \[RS_{t,n} = \frac{\frac{U_t + U_{t-1} + \dots + U_{t-n+1}}{n}}{\frac{D_t + D_{t-1} + \dots + D_{t-n+1}}{n}}\]

and, finally

\[RSI_{t,n} = 100 \frac{RS_{t,n}}{1+RS_{t,n}}\]

The RSI oscillates between 0 and 100, with readings above 70 indicating that the asset is overbought, and readings below 30 indicating that the asset is oversold.

Traders and investors use the RSI to identify potential trend reversals and generate buy and sell signals. For example, when the RSI crosses above 70, it is considered overbought, and a sell signal may be generated. Conversely, when the RSI crosses below 30, it is considered oversold, and a buy signal may be generated.

The RSI can also be used to identify divergences between the RSI line and the price of the asset being analyzed. When the RSI line diverges from the price, it can be an indication that a trend reversal may be imminent.

It is important to note that like any technical analysis tool, the RSI is not infallible and should be used in conjunction with other indicators and analysis methods to make informed trading decisions. Additionally, traders should adjust their strategies and parameters to fit the specific market conditions being analyzed.

chartSeries(stock,
            subset='2020-01-01::2020-09-23', type = "bars",
            theme=chartTheme('white'))

addRSI(n = 14, maType = "EMA", wilder = TRUE)

SI is a momentum indicator that evaluate the overbought and oversold condition of a financial instrument. In the first two months of 2020, Tesla’s stock price experienced a surge due to positive news and investor optimism surrounding electric vehicles and the company’s growth prospects. However, the stock became overbought, indicating a possible pullback or consolidation. From February to March 2020, Tesla, along with many other companies, faced a sharp decline in its stock price due to the global financial market downturn. This caused the stock to enter oversold territory, suggesting excessive selling pressure and a potential buying opportunity for traders. Between March and June 2020, Tesla’s stock price gradually recovered as investor sentiment improved and the company’s fundamentals remained strong. During this period, the stock entered a phase of consolidation and indecision, with its RSI fluctuating between 30 and 70. The second half of 2020 witnessed a remarkable rally in Tesla’s stock price, driven by strong quarterly earnings, positive business developments, and increased investor interest in electric vehicles. Once again, the stock became overbought, indicating a potential vulnerability to a pullback.

Parabolic stop and reversal

The Parabolic Stop and Reversal (SAR) is a technical analysis tool used by traders to determine potential trend reversals in price movements. It was developed by J. Welles Wilder Jr. and is used to set trailing stop-loss orders in order to limit potential losses in a trade.

The SAR uses a series of dots placed above or below the price of the asset being analyzed to indicate potential reversals in the direction of the trend. When the price is moving upwards, the SAR dots are placed below the price, and when the price is moving downwards, the SAR dots are placed above the price.

The Parabolic Stop and Reversal (SAR) is a technical analysis tool used by traders to determine potential trend reversals in price movements. It was developed by J. Welles Wilder Jr. and is used to set trailing stop-loss orders in order to limit potential losses in a trade.

The SAR uses a series of dots placed above or below the price of the asset being analyzed to indicate potential reversals in the direction of the trend. When the price is moving upwards, the SAR dots are placed below the price, and when the price is moving downwards, the SAR dots are placed above the price.

As the price moves in the direction of the trend, the distance between the price and the SAR dots increases. When the price reaches a certain distance from the SAR dots, the dots begin to move closer to the price, indicating that a potential reversal in the trend may be imminent. When the price crosses the SAR dots, it is considered a signal to exit a trade and potentially enter a new trade in the opposite direction.

The Parabolic Stop and Reverse (SAR) is a technical analysis tool used to identify potential reversal points in a price trend. The formula for calculating the Parabolic SAR is as follows:

For an uptrend:

\[SAR_{n+1} = SAR_n + AF * (EP - SAR_n)\]

For a downtrend:

\[SAR_{n+1} = SAR_n - AF * (SAR_n - EP)\]

Where:

\(SAR_n\) is the current period’s \(SAR\) value

\(SAR_{n+1}\) is the next period’s \(SAR\) value

\(AF\) is the acceleration factor, which starts at 0.02 and increases by 0.02 each time a new extreme point (EP) is reached, up to a maximum of 0.20

\(EP\) is the highest high or lowest low of the current trend, depending on the direction of the trend

The initial SAR value is set to the lowest low for an uptrend, and the highest high for a downtrend. The SAR value is then calculated for each subsequent period using the above formula.

The SAR can be used in conjunction with other technical analysis tools, such as moving averages or trend lines, to confirm potential trend reversals and identify potential entry or exit points for trades.

It is important to note that the SAR should not be used in isolation and should be used in conjunction with other analysis methods to make informed trading decisions. Additionally, traders should adjust the parameters of the SAR to fit the specific market conditions being analyzed.

chartSeries(stock,
            subset='2020-01-01::2020-09-23', type = "bars",
            theme=chartTheme('white'))

addSAR(accel = c(0.02, 0.2), col = "blue")

NA
NA

Parabolic Stop and Reversal (SAR) is a technical analysis tool to identify possible trend reversals in price movements.Tesla’s stock saw a significant price increase and bullish trend from January to February 2020, with the Parabolic SAR consistently below the price. Throughout February to mid-March 2020, Tesla’s stock continued to rise, reaching new all-time highs, and the SAR dots remained below the price, indicating support for the bullish momentum. From late March to April 2020, Tesla’s price fluctuated due to market volatility, and the SAR dots above the price acted as resistance, reflecting bearish sentiment. Between May and August 2020, Tesla entered a consolidation phase, with the stock price stabilizing. The SAR dots closely aligned with the price, indicating market indecision. From September to November 2020, Tesla’s stock gradually regained its upward momentum due to positive news about its business operations and future prospects. The SAR dots remained below the price, supporting the renewed bullish trend.Towards the end of 2020, Tesla’s stock price surged to new highs, driven by investor optimism and strong demand for electric vehicles. The Parabolic SAR continued to stay below the price, suggesting a sustained bullish bias.

Summary graphs

Apart from the few that was mentioned above, other indicators include rate of change, money flow index (MFI), MACD and etc.

Chart Series

ChartSeries provides an alternative way to summarise the plot. Instead of one plot for each indicator, all of them can now be compiled into a single figure, where indicators can be added to the bottom of the existing plot.

chartSeries(stock,
            subset='2020-01-01::2020-09-23', type = "bars",
            theme=chartTheme('white'))

addBBands(n=20,sd=2)

addRSI(n=14,maType="EMA")

addMACD(fast=12,slow=26,signal=9,type="EMA")

LS0tCnRpdGxlOiAiVGVjaG5pY2FsIGFuYWx5c2lzIGluIFIiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKIyMgSW50cm9kdWN0aW9uCgpBbHZpbiBUYW4gY3JlYXRlZCBpbnRlcmVzdGluZyBbTm90ZWJvb29rXShodHRwOi8vcnB1YnMuY29tL3poZXNodWVuLzY2NTYxNiksIHdoaWNoIGlzIHBhcnRseSB1c2VkIGluIHRoaXMgcHJlc2VudGF0aW9uLiBUaGUgW0ludmVzdG9wZWRpYV0oaHR0cHM6Ly93d3cuaW52ZXN0b3BlZGlhLmNvbS8pIGluZm9ybWF0aW9uIHNvdXJjZSBpcyBhbHNvIHVzZWQuIEluIGFkZGl0aW9uLCBhIEJvb2tkb3duIG9mIFtUZWNobmljYWwgQW5hbHlzaXMgd2l0aCBSIChzZWNvbmQgZWRpdGlvbikgZnJvbSBLbyBDaGl1IFl1XShodHRwczovL2Jvb2tkb3duLm9yZy9rb2NoaXV5dS90ZWNobmljYWwtYW5hbHlzaXMtd2l0aC1yLXNlY29uZC1lZGl0aW9uMi8pICBhbmQgQ2hhdEdQVCB3ZXJlIGhlbHBmdWwgd2l0aCB0aGUgY29kaW5nIGluIFIuCgpUZWNobmljYWwgYW5hbHlzaXMgaXMgYSBtZXRob2QgdG8gcHJlZGljdCBwcmljZSBtb3ZlbWVudCBpbiB0aGUgZmluYW5jaWFsIG1hcmtldHMuIFVubGlrZSB0aGUgdXN1YWwgYmFsYW5jZSBzaGVldCBhbmFseXNpcyAoZnVuZGFtZW50YWwgaW52ZXN0aW5nKSwgdGVjaG5pY2FsIGFuYWx5c2lzIGVzdGltYXRlcyB0aGUgdmFsdWUgb2YgYSBnaXZlbiBzdG9jayB1c2luZyB1bmRlcmx5aW5nIHRyZW5kcyBvZiB0aGUgcHJpY2UgbW92ZW1lbnQuIFRoZSBjb3JlIGFzc3VtcHRpb24gYmVoaW5kIHRoaXMgbWV0aG9kIGlzIHRoYXQgdGhlIGZ1bmRhbWVudGFscyAoaW5mb3JtYXRpb24gZnJvbSBmaW5hbmNpYWwgc3RhdGVtZW50cykgd2VyZSBmYWN0b3JlZCBpbnRvIHRoZSBwcmljZSBmbHVjdHVhdGlvbiwgaGVuY2UsIGRldGVjdGluZyB0aGUgcGF0dGVybnMgYW5kIHNpZ25hbHMgZnJvbSB0aGUgZmx1Y3R1YXRpb24gc2hvdWxkIHByb3ZpZGUgc3VmZmljaWVudCBpbmRpY2F0b3IgZm9yIGZ1dHVyZSBwZXJmb3JtYW5jZS4KCkZvciB0aGlzIHByb2plY3QsIHdlIGFyZSBnb2luZyB0byBleHBsb3JlIHNvbWUgb2YgdGhlIGNvbW1vbiB0ZWNobmljYWwgaW5kaWNhdG9ycyB1c2luZyB0aGUgVFFRUSBFeGNoYW5nZSB0cmFkZSBmdW5kIChFVEYpIHN0b2NrLiBBbW9uZyBsZXZlcmFnZWQgRVRGcywgUHJvU2hhcmVzIFVsdHJhUHJvIFFRUSAoVFFRUSkgaXMgb25lIG9mIHRoZSBsYXJnZXN0IHdpdGggYXNzZXRzIHVuZGVyIG1hbmFnZW1lbnQgb2YgJFwkMTguNTYkIGJpbGxpb24gYXMgb2YgSnVseSAyMDIyLiBUUVFRIGlzIGFsc28gb25lIG9mIHRoZSBtb3JlIGhlYXZpbHkgdHJhZGVkIGxldmVyYWdlZCBFVEZzIGluIHRoZSBVLlMuIHdpdGggYW4gYXZlcmFnZSBkYWlseSB2b2x1bWUgb2YgJFwkNS4yOSQgYmlsbGlvbiAoY29tcGFyZWQgd2l0aCBRUVEncyAkXCQyMSQgYmlsbGlvbikuCgpUUVFRIGNhcnJpZXMgYW4gW2V4cGVuc2UgcmF0aW9dKGh0dHBzOi8vd3d3LmludmVzdG9wZWRpYS5jb20vdGVybXMvZS9leHBlbnNlcmF0aW8uYXNwKSBvZiAwLjk1JS4KCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygicXVhbnRtb2QiKQojaW5zdGFsbC5wYWNrYWdlcygiZGF0YS50YWJsZSIpCiNpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKI2luc3RhbGwucGFja2FnZXMoInRpZHlxdWFudCIpCmxpYnJhcnkocXVhbnRtb2QpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHlxdWFudCkgIApgYGAKCiMjIERhdGEgRXh0cmFjdGlvbiAmIE1hbmlwdWxhdGlvbiwgRGF0YSBzdHJ1Y3R1cmUKClRRUVEgZGF0YSBpcyBleHRyYWN0ZWQgdXNpbmcgdGhlIGdldFN5bWJvbHMgZnVuY3Rpb24gZnJvbSBZYWhvbyBGaW5hbmNlLiBBbHRlcm5hdGl2ZWx5LCB0aGUgc291cmNlIGNhbiBiZSByZXBsYWNlZCB3aXRoIEZSRUQsIE15U1FMLCBHb29nbGUsIG9yIG90aGVycy4gVGhlIGRhdGEgZXh0cmFjdGVkIHNob3VsZCBiZSBpbiBhbiDigJh4dHPigJkgb2JqZWN0IC0gYSBmb3JtYXQgY29tbW9ubHkgdXNlZCBpbiB0aW1lIHNlcmllcyBhbmFseXNpcyB3aGVyZSBvYnNlcnZhdGlvbnMgYXJlIHJlY29yZGVkIGluIGEgbWF0cml4IHN0cnVjdHVyZSB3aXRoIGFuIGluZGV4IG9mIGNvcnJlc3BvbmRpbmcgdGltZS4KClRlY2huaWNhbGx5LCBhbmFseXNpcyBjYW4gYmUgZG9uZSBpbiB4dHMgZm9ybWF0IGFsb25lLCBidXQgZm9yIHRoZSBzYWtlIG9mIHNpbXBsaWNpdHksIGRhdGEgaXMgY29udmVydGVkIGludG8gYSBzdGFuZGFyZCBkYXRhZnJhbWUgYW5kIGluZGV4IGNvbHVtbiBpcyByZW5hbWVkIGFzICJEYXRl4oCZLiBUaGUgZW5kIHJlc3VsdCBpcyBzaG93biBhcyBiZWxvdzoKCmBgYHtyIGRvd25sb2FkX3N0b2NrX2hpc3Rvcnl9CmdldFN5bWJvbHMoJ1RTTEEnLHNyYyA9ICd5YWhvbycpICAgICAgICMjIGNoYW5nZSBUUVFRIHRpY2tlciB0byBZb3VyIHRpY2tlciBzeW1ib2wKYGBgCgojIyBzdHJ1Y3R1cmUgb2YgdGhlICpzdG9jayogZGF0YQoKYGBge3J9CnN0b2NrIDw8LSBhcy5kYXRhLnRhYmxlKFRTTEEpICAgICAgICAjIyMjIyMgY2hhbmdlIFRRUVEgdGlja2VyIHRvIFlvdXIgdGlja2VyIHN5bWJvbCAgIyMjIyMjIyMjCm5hbWVzKHN0b2NrKVsxXSA8LSBjKCdEYXRlJykKCnRhaWwoc3RvY2spCmBgYAoKCiMjIEludGVycHJldGF0aW9uIG9mIHRoZSBITENPIGdyYXBoCgpJbiBmaW5hbmNlLCBITENPIGdyYXBoIGlzIGEgdHlwZSBvZiBmaW5hbmNpYWwgY2hhcnQgdGhhdCBwbG90cyB0aGUgaGlnaCwgbG93LCBjbG9zZSwgYW5kIG9wZW4gcHJpY2VzIGZvciBhIGdpdmVuIHBlcmlvZCBvZiB0aW1lLiBUaGUgSExDTyBjaGFydCBpcyBzaW1pbGFyIHRvIGEgY2FuZGxlc3RpY2sgY2hhcnQsIGJ1dCBpdCBpbmNsdWRlcyB0aGUgb3BlbiBwcmljZSBpbiBhZGRpdGlvbiB0byB0aGUgaGlnaCwgbG93LCBhbmQgY2xvc2UgcHJpY2VzLgoKVGhlIGludGVycHJldGF0aW9uIG9mIGFuIEhMQ08gY2hhcnQgY2FuIHByb3ZpZGUgaW5zaWdodHMgaW50byB0aGUgcHJpY2UgYWN0aW9uIG9mIGEgc2VjdXJpdHkgZHVyaW5nIGEgZ2l2ZW4gcGVyaW9kIG9mIHRpbWUuIEhlcmUgaXMgYSBicmllZiBleHBsYW5hdGlvbiBvZiBob3cgdG8gaW50ZXJwcmV0IGVhY2ggY29tcG9uZW50IG9mIGFuIEhMQ08gY2hhcnQ6CgoxLiBIaWdoOiBUaGUgdG9wIG9mIHRoZSB2ZXJ0aWNhbCBsaW5lIHJlcHJlc2VudHMgdGhlIGhpZ2hlc3QgcHJpY2UgcmVhY2hlZCBkdXJpbmcgdGhlIGdpdmVuIHBlcmlvZC4gVGhpcyBzaG93cyB0aGUgaGlnaGVzdCBwcmljZSB0aGF0IGJ1eWVycyB3ZXJlIHdpbGxpbmcgdG8gcGF5IGZvciB0aGUgc2VjdXJpdHkgZHVyaW5nIHRoZSBwZXJpb2QuCgoyLiBMb3c6IFRoZSBib3R0b20gb2YgdGhlIHZlcnRpY2FsIGxpbmUgcmVwcmVzZW50cyB0aGUgbG93ZXN0IHByaWNlIHJlYWNoZWQgZHVyaW5nIHRoZSBnaXZlbiBwZXJpb2QuIFRoaXMgc2hvd3MgdGhlIGxvd2VzdCBwcmljZSB0aGF0IHNlbGxlcnMgd2VyZSB3aWxsaW5nIHRvIGFjY2VwdCBmb3IgdGhlIHNlY3VyaXR5IGR1cmluZyB0aGUgcGVyaW9kLgoKMy4gQ2xvc2U6IFRoZSBob3Jpem9udGFsIGxpbmUgdG8gdGhlIHJpZ2h0IG9mIHRoZSB2ZXJ0aWNhbCBsaW5lIHJlcHJlc2VudHMgdGhlIGNsb3NpbmcgcHJpY2UgZm9yIHRoZSBwZXJpb2QuIFRoaXMgc2hvd3MgdGhlIGZpbmFsIHByaWNlIGF0IHdoaWNoIHRoZSBzZWN1cml0eSB0cmFkZWQgZHVyaW5nIHRoZSBwZXJpb2QuCgo0LiBPcGVuOiBUaGUgaG9yaXpvbnRhbCBsaW5lIHRvIHRoZSBsZWZ0IG9mIHRoZSB2ZXJ0aWNhbCBsaW5lIHJlcHJlc2VudHMgdGhlIG9wZW5pbmcgcHJpY2UgZm9yIHRoZSBwZXJpb2QuIFRoaXMgc2hvd3MgdGhlIGluaXRpYWwgcHJpY2UgYXQgd2hpY2ggdGhlIHNlY3VyaXR5IHRyYWRlZCBkdXJpbmcgdGhlIHBlcmlvZC4KCkJ5IGxvb2tpbmcgYXQgdGhlIHBhdHRlcm5zIG9mIHRoZSBoaWdoLCBsb3csIGNsb3NlLCBhbmQgb3BlbiBwcmljZXMgaW4gYW4gSExDTyBjaGFydCwgdHJhZGVycyBhbmQgaW52ZXN0b3JzIGNhbiBnYWluIGluc2lnaHQgaW50byB0aGUgb3ZlcmFsbCB0cmVuZCBhbmQgc2VudGltZW50IG9mIHRoZSBtYXJrZXQgZm9yIHRoZSBnaXZlbiBzZWN1cml0eS4gRm9yIGV4YW1wbGUsIGEgbG9uZyBncmVlbiBjYW5kbGVzdGljayB3aXRoIGEgaGlnaCBjbG9zZSBhbmQgbG93IG9wZW4gbWF5IGluZGljYXRlIGJ1bGxpc2ggc2VudGltZW50LCB3aGlsZSBhIGxvbmcgcmVkIGNhbmRsZXN0aWNrIHdpdGggYSBsb3cgY2xvc2UgYW5kIGhpZ2ggb3BlbiBtYXkgaW5kaWNhdGUgYmVhcmlzaCBzZW50aW1lbnQuCgpgYGB7cn0KIyBmZWVsIGZyZWUgdG8gY2hhbmdlICJITENPIiB0byAiY2FuZGxlc3RpY2siIG9yIHRvIHNvbWUgb3RoZXIgdHlwZXMgKCJsaW5lcyIsICJhdXRvIikuIApjaGFydFNlcmllcyhzdG9jaywgc3Vic2V0PScyMDIwLTAxLTAxOjoyMDIwLTA5LTIzJywgdHlwZSA9ICJjYW5kbGVzdGlja3MiLCBiYXIudHlwZSA9ICJvaGxjIix0aGVtZT1jaGFydFRoZW1lKCd3aGl0ZScpKQpgYGAKSExDTyBncmFwaCBpcyBhIHR5cGUgb2YgZmluYW5jaWFsIGNoYXJ0IHRoYXQgcGxvdHMgdGhlIGhpZ2gsIGxvdywgY2xvc2UsIGFuZCBvcGVuIHByaWNlcyBmb3IgYSBnaXZlbiBwZXJpb2Qgb2YgdGltZS4KRWFybHkgMjAyMDogVGVzbGEncyBzdG9jayBwcmljZSBzaG93ZWQgYSBzdHJvbmcgdXB0cmVuZCwgcmlzaW5nIGZyb20gYXJvdW5kICQ0MzAgdG8gb3ZlciAkOTAwLiBUaGUgSExDTyBncmFwaCBpbmRpY2F0ZWQgYSBidWxsaXNoIHRyZW5kIHdpdGggaGlnaGVyIGhpZ2hzIGFuZCBoaWdoZXIgbG93cy4gRmVicnVhcnkgLSBNYXJjaDogR2xvYmFsIG1hcmtldCBjb3JyZWN0aW9uIGR1ZSB0byBDT1ZJRC0xOSBpbXBhY3RlZCBUZXNsYSdzIHN0b2NrIHByaWNlLCBsZWFkaW5nIHRvIGEgc2hhcnAgcHVsbGJhY2suIFRoZSBITENPIGdyYXBoIHNob3dlZCBzaWduaWZpY2FudCBwcmljZSBkZWNsaW5lcyB3aXRoIGxhcmdlciByZWQgY2FuZGxlc3RpY2tzLiBNYXJjaCAtIEFwcmlsOiBUZXNsYSdzIHN0b2NrIHByaWNlIGJlZ2FuIHRvIHJlY292ZXIsIHRyYW5zaXRpb25pbmcgZnJvbSBwcmVkb21pbmFudGx5IHJlZCBjYW5kbGVzdGlja3MgdG8gYSBtaXggb2YgZ3JlZW4gYW5kIHJlZC4gSGlnaGVyIHZvbGF0aWxpdHkgYW5kIHdpZGVyIHByaWNlIHN3aW5ncyB3ZXJlIG9ic2VydmVkLiBNaWQtMjAyMDogVGVzbGEncyBzdG9jayBwcmljZSBlbnRlcmVkIGEgY29uc29saWRhdGlvbiBwaGFzZSwgdHJhZGluZyB3aXRoaW4gYSBuYXJyb3cgcmFuZ2UuIFRoZSBITENPIGdyYXBoIHNob3dlZCBzbWFsbGVyIGNhbmRsZXN0aWNrcyBhcyB0aGUgc3RvY2sgcHJpY2UgY29uc29saWRhdGVkLgpMYXRlIDIwMjA6IFRlc2xhJ3Mgc3RvY2sgcHJpY2UgZXhwZXJpZW5jZWQgYSBzdHJvbmcgYnVsbCBydW4sIHJlYWNoaW5nIG5ldyBhbGwtdGltZSBoaWdocy4gVGhlIEhMQ08gZ3JhcGggaW5kaWNhdGVkIHNpZ25pZmljYW50IHByaWNlIGdhaW5zIHdpdGggbGFyZ2UgZ3JlZW4gY2FuZGxlc3RpY2tzLiBUZXNsYSdzIGluY2x1c2lvbiBpbiB0aGUgUyZQIDUwMCBpbmRleCBmdXJ0aGVyIGZ1ZWxlZCBpbnZlc3RvciBvcHRpbWlzbS4KCgojIyBWb2x1bWUgCgpPbmUgb2YgdGhlIG1vc3QgY29tbW9uIGJhc2ljIGluZGljYXRvcnMgdHJhZGVycyBleGFtaW5lIGlzIHRoZSB0cmFkaW5nIHZvbHVtZS4gVHJhZGluZyB2b2x1bWUgaXMgYW4gaW5kaWNhdGlvbiBmb3IgdGhlIOKAmGFjdGl2ZW5lc3PigJkgb2YgYSBmaW5hbmNpYWwgaW5zdHJ1bWVudC4gRGVwZW5kaW5nIG9uIHRoZSBmaW5hbmNpYWwgaW5zdHJ1bWVudHMsIHRyYWRpbmcgdm9sdW1lIGNhbiBiZSBtZWFzdXJlZCBlaXRoZXIgdXNpbmcgdGhlIG51bWJlciBvZiBzdG9ja3MgdHJhZGVkIG9yIG51bWJlciBvZiBjb250cmFjdHMgd2l0aCBjaGFuZ2VkIG93bmVyc2hpcHMuIFRvIHB1dCB0aGlzIGluIHByYWN0aWNlLCBpZiBhbiBpbmNyZWFzZSBpbiB2b2x1bWUgaXMgb2JzZXJ2ZWQgd2l0aCBhIHN0ZWFkeSBpbmNyZWFzZSBpbiBwcmljZSwgdGhlIGluc3RydW1lbnQgY2FuIGJlIHZpZXdlZCBhcyBzdGVhZHkgYW5kIHN0cm9uZy4gSG93ZXZlciwgaWYgdm9sdW1lIGFuZCBwcmljZSBhcmUgY2hhbmdpbmcgaW4gZGlmZmVyZW50IGRpcmVjdGlvbnMsIGEgcmV2ZXJzYWwgbWlnaHQgYmUgaGFwcGVuZWQuCgpZb3UgY2FuIGFuYWx5emUgaXQgaW4gdGhlIHByZXZpb3VzIHBpY3R1cmUuCgoKIyMgUHJpY2UgLSBNb3ZpbmcgQXZlcmFnZQoKSW4gdGVybXMgb2YgdHJhZGluZyBwcmljZSwgdHJhZGVycyBvZnRlbiBvYnNlcnZlZCB0aGUgdHJlbmRzIGJhc2VkIG9uIHRoZSBjaGFydHMgc2hhcGUgYW5kIGNyb3NzIGluIHdheXMgdGhhdCBmb3JtIHNoYXBlcyAtIG9mdGVuIHRpbWVzIHdpdGggd2VpcmQgbmFtZXMgbGlrZSDigJhoZWFkIGFuZCBzaG91bGRlcuKAmSwg4oCZIHJldmVyc2UgaGVhZCBhbmQgc2hvbGRlcuKAmSwg4oCYZG91YmxlIHRvcOKAmSwg4oCYZ29sZGVuIGNyb3Nz4oCZLCBldGMuIEEgZ29sZGVuIGNyb3NzIGluZGljYXRlcyBhIGxvbmcgdGVybSBidWxsIG1hcmtldCBnb2luZyBmb3J3YXJkLCB3aGVyZWFzIHRoZSBkZWF0aCBjcm9zcyBpcyB0aGUgZXhhY3Qgb3Bwb3NpdGUsIGluZGljYXRpbmcgYSBwb3RlbnRpYWwgbG9uZyB0ZXJtIGJlYXIgbWFya2V0LiBCb3RoIG9mIHRoZXNlIHJlZmVyIHRvIHRoZSBjb25maXJtYXRpb24gb2YgbG9uZyB0ZXJtIHRyZW5kIGJ5IHRoZSBvY2N1cmFuY2Ugb2YgdGhlIG92ZXJsYXBwaW5nIG9mIG1vdmluZyBhdmVyYWdlIGxpbmVzIGFzIHNob3duIGJlbG93LgoKSW4gdGhlIHF1YW50bW9kIHBhY2thZ2UgaW4gUiwgdGhlIGFkZE1BIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGFkZCBtb3ZpbmcgYXZlcmFnZXMgdG8gYSBmaW5hbmNpYWwgdGltZSBzZXJpZXMgY2hhcnQuIFRoZXJlIGFyZSB2YXJpb3VzIG1ldGhvZHMgb2YgY2FsY3VsYXRpbmcgbW92aW5nIGF2ZXJhZ2VzIHRoYXQgY2FuIGJlIHVzZWQgaW4gdGhpcyBmdW5jdGlvbiwgd2hpY2ggSSB3aWxsIGRlc2NyaWJlIGJlbG93OgoKMS4gU2ltcGxlIE1vdmluZyBBdmVyYWdlIChTTUEpOiBUaGlzIGlzIHRoZSBtb3N0IGJhc2ljIHR5cGUgb2YgbW92aW5nIGF2ZXJhZ2UgYW5kIGlzIGNhbGN1bGF0ZWQgYnkgdGFraW5nIHRoZSBhdmVyYWdlIG9mIGEgc2V0IG51bWJlciBvZiBwZXJpb2RzIG9mIGRhdGEuIEZvciBleGFtcGxlLCBhIDIwLWRheSBTTUEgd291bGQgYmUgdGhlIGF2ZXJhZ2Ugb2YgdGhlIGNsb3NpbmcgcHJpY2VzIGZvciB0aGUgbGFzdCAyMCBkYXlzLiBUaGlzIG1ldGhvZCBnaXZlcyBlcXVhbCB3ZWlnaHQgdG8gYWxsIHBlcmlvZHMgaW4gdGhlIG1vdmluZyBhdmVyYWdlLgogJCRTTUFfdCA9IFxmcmFje1BfdCArIFxkb3RzICsgUF97dC1uKzF9fXtufSQkCipCdXkgc2lnbmFsKiBhcmlzZXMgd2hlbiBhIHNob3J0LXJ1biBTTUEgY3Jvc3NlcyBmcm9tIGJlbG93IHRvIGFib3ZlIGEgbG9uZy1ydW4gU01BLiAqU2VsbCBzaWduYWwqIGFycmlzZXMgd2hlbiBhIHNob3J0LXJ1biBTTUEgY3Jvc3NlcyBmcm9tIGFib3ZlIHRvIGJlbG93IGEgbG9uZy1ydW4gU01BLgoKMi4gV2VpZ2h0ZWQgTW92aW5nIEF2ZXJhZ2UgKFdNQSk6IFRoaXMgbWV0aG9kIGFzc2lnbnMgYSB3ZWlnaHQgdG8gZWFjaCBkYXRhIHBvaW50IGluIHRoZSBtb3ZpbmcgYXZlcmFnZSwgd2l0aCBtb3JlIHJlY2VudCBkYXRhIHBvaW50cyBnaXZlbiBncmVhdGVyIHdlaWdodC4gVGhlIHdlaWdodHMgY2FuIGJlIGNhbGN1bGF0ZWQgaW4gdmFyaW91cyB3YXlzLCBzdWNoIGFzIGxpbmVhciBvciBleHBvbmVudGlhbC4KCjMuIEV4cG9uZW50aWFsIE1vdmluZyBBdmVyYWdlIChFTUEpOiBUaGlzIG1ldGhvZCBpcyBzaW1pbGFyIHRvIHRoZSBXTUEsIGJ1dCBpdCBnaXZlcyBncmVhdGVyIHdlaWdodCB0byBtb3JlIHJlY2VudCBkYXRhIHBvaW50cyB1c2luZyBhbiBleHBvbmVudGlhbCBkZWNheSBmb3JtdWxhLiBUaGUgZm9ybXVsYSB1c2VkIHRvIGNhbGN1bGF0ZSB0aGUgRU1BIGludm9sdmVzIGEgc21vb3RoaW5nIGZhY3Rvciwgd2hpY2ggZGV0ZXJtaW5lcyB0aGUgd2VpZ2h0IGdpdmVuIHRvIGVhY2ggZGF0YSBwb2ludC4KJCRFTUFfdCA9IFxiZXRhIFBfdCArICgxLVxiZXRhKSBFTUFfe3QtMX0kJAp3aGVyZSB0aGUgc21vb3RoaW5nIGNvZWZmaWNpZW50IGlzIHVzdWFsbHkgZGVmaW5lZCAkXGJldGEgPSBcZnJhY3syfXtuKzF9IFxpbiAoMDsxKSQuCgo0LiBEb3VibGUgRXhwb25lbnRpYWwgTW92aW5nIEF2ZXJhZ2UgKERFTUEpOiBUaGlzIG1ldGhvZCBpcyBzaW1pbGFyIHRvIHRoZSBFTUEsIGJ1dCBpdCB1c2VzIGEgc2Vjb25kIEVNQSB0byBzbW9vdGggdGhlIGZpcnN0IEVNQS4gVGhpcyByZXN1bHRzIGluIGEgc21vb3RoZXIgbW92aW5nIGF2ZXJhZ2UgdGhhdCBpcyBsZXNzIHNlbnNpdGl2ZSB0byBzaG9ydC10ZXJtIGZsdWN0dWF0aW9ucy4KCjUuIFRyaXBsZSBFeHBvbmVudGlhbCBNb3ZpbmcgQXZlcmFnZSAoVEVNQSk6IFRoaXMgbWV0aG9kIGlzIHNpbWlsYXIgdG8gdGhlIERFTUEsIGJ1dCBpdCB1c2VzIGEgdGhpcmQgRU1BIHRvIGZ1cnRoZXIgc21vb3RoIHRoZSBtb3ZpbmcgYXZlcmFnZS4gVGhpcyBtZXRob2QgaXMgZXZlbiBsZXNzIHNlbnNpdGl2ZSB0byBzaG9ydC10ZXJtIGZsdWN0dWF0aW9ucyB0aGFuIHRoZSBERU1BLgoKVGhlc2UgYXJlIHRoZSBtYWluIHR5cGVzIG9mIG1vdmluZyBhdmVyYWdlcyB0aGF0IGNhbiBiZSB1c2VkIGluIHRoZSBhZGRNQSBmdW5jdGlvbiBpbiBxdWFudG1vZC4gRWFjaCBtZXRob2QgaGFzIGl0cyBvd24gYWR2YW50YWdlcyBhbmQgZGlzYWR2YW50YWdlcywgYW5kIHRoZSBjaG9pY2Ugb2YgbWV0aG9kIHdpbGwgZGVwZW5kIG9uIHRoZSBzcGVjaWZpYyBuZWVkcyBvZiB0aGUgYW5hbHlzaXMgYmVpbmcgcGVyZm9ybWVkLgoKYGBge3J9CmNoYXJ0U2VyaWVzKHN0b2NrLAogICAgICAgICAgICBzdWJzZXQ9JzIwMjAtMDEtMDE6OjIwMjAtMDktMjMnLCB0eXBlID0gImNhbmRsZXN0aWNrIiwKICAgICAgICAgICAgdGhlbWU9Y2hhcnRUaGVtZSgnd2hpdGUnKSkKYWRkU01BKG4gPSAxMiwgb24gPSAxLCB3aXRoLmNvbCA9IENsLCBvdmVybGF5ID0gVFJVRSwgY29sID0gImJyb3duIikKYWRkU01BKG4gPSAyNCwgb24gPSAxLCB3aXRoLmNvbCA9IENsLCBvdmVybGF5ID0gVFJVRSwgY29sID0gImJsdWUiKQoKCmBgYApUaGUgY2hhcnQgb2YgTW92aW5nIEF2ZXJhZ2UgcHJvdmlkZXMgdXMgd2l0aCBoZWxwZnVsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBidXkgYW5kIHNlbGwgc2lnbmFscyBvZiB0aGUgY29tcGFueS4gVGhyb3VnaCBvdXQgZm9ybSBKYW51YXJ5IHRvIE1hcmNoOiBJbiB0aGUgbW9udGggRmVicnVhcnkgVGVzbGEncyBzdG9jayBwcmljZSBiZWdhbiBhIHBvd2VyZnVsIHVwdHJlbmQsIHN1cHBvcnRlZCBieSBwb3NpdGl2ZSBuZXdzIHJlZ2FyZGluZyBpdHMgZGVsaXZlcnkgbnVtYmVycyBhbmQgcHJvZml0YWJpbGl0eS4gVGhpcyBjcm9zc292ZXIgc2lnbmFsZWQgYSBidXkgb3Bwb3J0dW5pdHkgZm9yIHRyYWRlcnMsIGFsaWduaW5nIHdpdGggdGhlIHN0b2NrJ3MgdXB3YXJkIG1vdmVtZW50LiBGcm9tIEFwcmlsIHRvIEp1bmUgdGhlIE1BIGJlZ2FuIHRvIGNvbnZlcmdlIHRvd2FyZHMgdGhlIHNpZ25hbCBsaW5lIGFzIFRlc2xhJ3MgcHJpY2UgZW50ZXJlZCBhIGNvbnNvbGlkYXRpb24gcGhhc2UuIEZyb20gSnVseSB0byBBdWd1c3QgdGlsbCBTZXB0ZW1iZXIgVGVzbGEncyBzdG9jayBwcmljZSBjb250aW51ZWQgaXRzIHVwd2FyZCwgcmVhY2hpbmcgbmV3IGFsbC10aW1lIGhpZ2hzLiBGaW5hbGx5IGZyb20gU2VwdGVtYmVyIHRoZSBNQSBoYXMgZHJvcHBlZCBmb3IgYSBzaG9ydGVyIHBlcmlvZCwgaXQgd2Fzbid0IHRoYXQgc2lnbmlmaWNhbnQuCgojIyBNb3ZpbmcgQXZlcmFnZSBDb252ZXJnZW5jZSBEaXZlcmdlbmNlIChNQUNEKQoKTUFDRCBzdGFuZHMgZm9yIE1vdmluZyBBdmVyYWdlIENvbnZlcmdlbmNlIERpdmVyZ2VuY2UuIEl0IGlzIGEgcG9wdWxhciB0ZWNobmljYWwgYW5hbHlzaXMgaW5kaWNhdG9yIHRoYXQgaXMgdXNlZCB0byBpZGVudGlmeSBjaGFuZ2VzIGluIHRyZW5kIGRpcmVjdGlvbiwgbW9tZW50dW0sIGFuZCBwb3RlbnRpYWwgYnV5IGFuZCBzZWxsIHNpZ25hbHMgaW4gZmluYW5jaWFsIG1hcmtldHMuCgpUaGUgTUFDRCBpcyBjYWxjdWxhdGVkIGJ5IHN1YnRyYWN0aW5nIHRoZSAyNi1wZXJpb2QgRXhwb25lbnRpYWwgTW92aW5nIEF2ZXJhZ2UgKEVNQSkgZnJvbSB0aGUgMTItcGVyaW9kIEVNQS4gVGhlIHJlc3VsdCBvZiB0aGlzIGNhbGN1bGF0aW9uIGlzIHRoZW4gcGxvdHRlZCBvbiBhIGNoYXJ0IGFsb25nIHdpdGggYSA5LXBlcmlvZCBFTUEsIHdoaWNoIGlzIG9mdGVuIHJlZmVycmVkIHRvIGFzIHRoZSAic2lnbmFsIGxpbmUiLgoKJCRNQUNEKFM9MTIsTD0yNilfdCA9IEVNQSh0LFMpIC0gRU1BKHQsTCkkJAoKVGhlIE1BQ0QgbGluZSBvc2NpbGxhdGVzIGFib3ZlIGFuZCBiZWxvdyB0aGUgc2lnbmFsIGxpbmUsIGluZGljYXRpbmcgY2hhbmdlcyBpbiBtb21lbnR1bSBhbmQgdHJlbmQgZGlyZWN0aW9uLiBXaGVuIHRoZSBNQUNEIGxpbmUgY3Jvc3NlcyBhYm92ZSB0aGUgc2lnbmFsIGxpbmUsIGl0IGlzIGNvbnNpZGVyZWQgYSBidWxsaXNoIHNpZ25hbCwgaW5kaWNhdGluZyBhIHBvdGVudGlhbCBidXkgb3Bwb3J0dW5pdHkuIENvbnZlcnNlbHksIHdoZW4gdGhlIE1BQ0QgbGluZSBjcm9zc2VzIGJlbG93IHRoZSBzaWduYWwgbGluZSwgaXQgaXMgY29uc2lkZXJlZCBhIGJlYXJpc2ggc2lnbmFsLCBpbmRpY2F0aW5nIGEgcG90ZW50aWFsIHNlbGwgb3Bwb3J0dW5pdHkuIEluIG90aGVyIHdvcmRzICpCdXkgc2lnbmFsKiBhcmlzZXMgd2hlbiBNQUNEIGNyb3NzZXMgZnJvbSBiZWxvdyB0byBhYm92ZSB0aGUgc2lnbmFsIGxpbmUsIGFuZCAqU2VsbCBzaWduYWwqIGFyaXNlcyB3aGVuIE1BQ0QgY3Jvc3NlcyBmcm9tIGFib3ZlIHRvIGJlbG93IHRoZSBzaWduYWwgbGluZS4KClRoZSBNQUNEIGNhbiBhbHNvIGJlIHVzZWQgdG8gaWRlbnRpZnkgZGl2ZXJnZW5jZXMgYmV0d2VlbiB0aGUgTUFDRCBsaW5lIGFuZCB0aGUgcHJpY2Ugb2YgdGhlIHNlY3VyaXR5IGJlaW5nIGFuYWx5emVkLiBXaGVuIHRoZSBNQUNEIGxpbmUgZGl2ZXJnZXMgZnJvbSB0aGUgcHJpY2UsIGl0IGNhbiBiZSBhbiBpbmRpY2F0aW9uIHRoYXQgYSB0cmVuZCByZXZlcnNhbCBtYXkgYmUgaW1taW5lbnQuCgpUcmFkZXJzIGFuZCBpbnZlc3RvcnMgb2Z0ZW4gdXNlIHRoZSBNQUNEIGluIGNvbmp1bmN0aW9uIHdpdGggb3RoZXIgdGVjaG5pY2FsIGFuYWx5c2lzIHRvb2xzLCBzdWNoIGFzIHN1cHBvcnQgYW5kIHJlc2lzdGFuY2UgbGV2ZWxzLCB0byBtYWtlIGluZm9ybWVkIHRyYWRpbmcgZGVjaXNpb25zLiBJdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHdoaWxlIHRoZSBNQUNEIGNhbiBiZSBhIHVzZWZ1bCBpbmRpY2F0b3IsIGl0IGlzIG5vdCBpbmZhbGxpYmxlIGFuZCBzaG91bGQgYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIG90aGVyIGZvcm1zIG9mIGFuYWx5c2lzIHRvIG1ha2UgaW5mb3JtZWQgdHJhZGluZyBkZWNpc2lvbnMuCgpgYGB7cn0KY2hhcnRTZXJpZXMoc3RvY2ssCiAgICAgICAgICAgIHN1YnNldD0nMjAyMC0wMS0wMTo6MjAyMC0wOS0yMycsIHR5cGUgPSAiYmFycyIsCiAgICAgICAgICAgIHRoZW1lPWNoYXJ0VGhlbWUoJ3doaXRlJykpCmFkZE1BQ0QoZmFzdD0xMixzbG93PTI2LHNpZ25hbD05LHR5cGU9IkVNQSIpCgpgYGAKVGhlIGNoYXJ0IG9mIE1vdmluZyBBdmVyYWdlIENvbnZlcmdlbmNlIERpdmVyZ2VuY2UgcGlzIGEgcG9wdWxhciB0ZWNobmljYWwgYW5hbHlzaXMgaW5kaWNhdG9yIHRoYXQgaXMgdXNlZCB0byBpZGVudGlmeSBjaGFuZ2VzIGluIHRyZW5kIGRpcmVjdGlvbiwgbW9tZW50dW0sIGFuZCBwb3RlbnRpYWwgYnV5IGFuZCBzZWxsIHNpZ25hbHMgaW4gZmluYW5jaWFsIG1hcmtldHMuIFRocm91Z2ggb3V0IGZvcm0gSmFudWFyeSB0byBGZWJydWFyeTogSW4gdGhlIG1vbnRoIEZlYnJ1YXJ5IFRlc2xhJ3Mgc3RvY2sgcHJpY2UgYmVnYW4gYSBwb3dlcmZ1bCB1cHRyZW5kLCBzdXBwb3J0ZWQgYnkgcG9zaXRpdmUgbmV3cyByZWdhcmRpbmcgaXRzIGRlbGl2ZXJ5IG51bWJlcnMgYW5kIHByb2ZpdGFiaWxpdHkuIFRoaXMgY3Jvc3NvdmVyIHNpZ25hbGVkIGEgYnV5IG9wcG9ydHVuaXR5IGZvciB0cmFkZXJzLCBhbGlnbmluZyB3aXRoIHRoZSBzdG9jaydzIHVwd2FyZCBtb3ZlbWVudC4gRnJvbSBNYXJjaCB0byBNYXkgdGhlIE1BQ0QgYmVnYW4gdG8gZGVhY3JlYXNlIHNpZ25pZmljYW50bHkuIEZyb20gTWF5IHRvIEF1Z3VzdCBUZXNsYSdzIHN0b2NrIHByaWNlIGNvbnRpbnVlZCBpdHMgdXB3YXJkLCByZWFjaGluZyBuZXcgYWxsLXRpbWUgaGlnaHMuIEZpbmFsbHkgZnJvbSBBdWd1c3QgdG8gU2VwdGVtYmVyIHRoZSBNQUNEIGhhcyBkcm9wcGVkIGZvciBhIHNob3J0ZXIgcGVyaW9kLCBpdCB3YXNuJ3QgdGhhdCBzaWduaWZpY2FudCwgdGhlbiBzdGFydGVkIHRvIHJlYWNoIGhpZ2hzLCBleHBlY2lhbGx5IGluIHRoZSBtb250aCBTZXB0ZW1iZXIuVGhyb3VnaG91dCAyMDIwLCBUZXNsYSdzIE1vdmluZyBBdmVyYWdlIENvbnZlcmdlbmNlIERpdmVyZ2VuY2UgKE1BQ0QpIGluZGljYXRvciBwcm92aWRlZCB2YWx1YWJsZSBpbnNpZ2h0cyBpbnRvIHRoZSBzdG9jaydzIHByaWNlIG1vbWVudHVtIGFuZCB0cmVuZCByZXZlcnNhbHMuIERlc3BpdGUgcGVyaW9kcyBvZiB2b2xhdGlsaXR5IGFuZCB1bmNlcnRhaW50eSwgdGhlIE1BQ0QgZWZmZWN0aXZlbHkgaWRlbnRpZmllZCBidXkgYW5kIHNlbGwgb3Bwb3J0dW5pdGllcyBmb3IgdHJhZGVycywgYWxpZ25pbmcgd2l0aCBUZXNsYSdzIHByaWNlIG1vdmVtZW50cy4KCiMjIEJvbGxpbmdlciBCYW5kCgpBcGFydCBmcm9tIHRoZSBkZWF0aCBhbmQgZ29sZGVuIGNyb3NzZXMsIHRoZSBtb3ZpbmcgYXZlcmFnZSBsaW5lcyBjYW4gYmUgdXNlZCB0byBjb21wdXRlIHRoZSBCb2xsaW5nZXIgQmFuZC4gQSBCb2xsaW5nZXIgQmFuZCBpcyBtYWRlIHVwIG9mIDMgbGluZXMsIHRoZSBzaW1wbGUgbW92aW5nIGF2ZXJhZ2UsIGFuIHVwcGVyIGJvdW5kYXJ5IGFuZCBhIGxvd2VyIGJvdW5kYXJ5LiBTaW1wbHkgcHV0LCB0aGlzIGlzIGEgbWVhc3VyZSB0byB0ZWxsIGlmIGEgZmluYW5jaWFsIGluc3RydW1lbnQgaXMgb3ZlcmJvdWdodCBvciBvdmVyc29sZC4gVGhlIGNsb3NlciB0aGUgcHJpY2VzIG1vdmUgdG8gdGhlIHVwcGVyIGJhbmQsIHRoZSBtb3JlIGxpa2VseSB0aGUgZmluYW5jaWFsIGluc3RydW1lbnQgaXMgb3ZlcmJvdWdodCwgd2hpY2ggbWF5IGxlYWQgdG8gYSByZXZlcnNhbCAobWFya2V0IGNvcnJlY3Rpb24pLiBMaWtld2lzZSwgaWYgdGhlIHByaWNlIGlzIG1vdmluZyB0byB0aGUgbG93ZXIgYmFuZCwgdGhlIG1hcmtldCBoYXMgYSBoaWdoZXIgcHJvYmFiaWxpdHkgb2YgYmVpbmcgb3ZlcnNvbGQsIHdoaWNoIHdpbGwgbGVhZCB0byBhIHVwd2FyZCByZXZlcnNhbC4KCkZvciBCb2xsaW5nZXIgYmFuZCwgY2hhbm5lbCBpcyBkcmF3biBvdmVyIGEgdHJlbmQgbGluZSBwbHVzL21pbnVzIDIgc3RhbmRhcmQgZGV2aWF0aW9uIChTRCkuIFRyZW5kIGxpbmU6IFNNQSBvciBFTUEgb2YgcHJpY2UgKHByaWNlIGNhbiBiZSBjbG9zaW5nIHByaWNlIG9yIGF2ZXJhZ2Ugb2YgaGlnaCwgbG93LCBhbmQgY2xvc2UpLgoKQmFuZHdpZHRoOiBkZXRlcm1pbmVkIGJ5IHRoZSBhc3NldCB2b2xhdGlsaXR5CiQkQl97dCxufSA9IGsqc2RldihQX3QsbikkJAp3aGVyZSB1c3VhbGx5IHdlIGhhdmUgJGs9MiQgYW5kICRuPTIwJC4gVGhlIGxvd2VyIGFuZCB1cHBlciBiYW5kcyBhcmUgZGVmaW5lZAokJHVwX3QgPSBQX3QgKyBCX3t0LG59IFxxdWFkIFx0ZXh0e2FuZH0gXHF1YWQgZG93bl90ID0gUF90IC0gQl97dCxufSAkJAoKQm9sbGluZ2VyIEJhbmRzIGFyZSBhIHBvcHVsYXIgdGVjaG5pY2FsIGFuYWx5c2lzIHRvb2wgdXNlZCBieSB0cmFkZXJzIHRvIG1lYXN1cmUgdGhlIHZvbGF0aWxpdHkgYW5kIHBvdGVudGlhbCBwcmljZSBtb3ZlbWVudHMgb2YgYSBmaW5hbmNpYWwgaW5zdHJ1bWVudC4gVGhleSBhcmUgY29tcHJpc2VkIG9mIHRocmVlIGxpbmVzOiBhIHNpbXBsZSBtb3ZpbmcgYXZlcmFnZSAoU01BKSwgYW4gdXBwZXIgYmFuZCwgYW5kIGEgbG93ZXIgYmFuZC4KClRoZSBTTUEgaXMgdHlwaWNhbGx5IGNhbGN1bGF0ZWQgdXNpbmcgYSAyMC1kYXkgbW92aW5nIGF2ZXJhZ2UsIGJ1dCBjYW4gYmUgYWRqdXN0ZWQgdG8gZml0IHRoZSBzcGVjaWZpYyB0aW1lIGZyYW1lIGJlaW5nIGFuYWx5emVkLiBUaGUgdXBwZXIgYmFuZCBpcyBjYWxjdWxhdGVkIGJ5IGFkZGluZyB0d28gc3RhbmRhcmQgZGV2aWF0aW9ucyB0byB0aGUgU01BLCB3aGlsZSB0aGUgbG93ZXIgYmFuZCBpcyBjYWxjdWxhdGVkIGJ5IHN1YnRyYWN0aW5nIHR3byBzdGFuZGFyZCBkZXZpYXRpb25zIGZyb20gdGhlIFNNQS4KClRoZSBiYW5kcyBhcmUgcGxvdHRlZCBvbiBhIGNoYXJ0LCB3aXRoIHRoZSBTTUEgYXMgdGhlIGNlbnRlciBsaW5lIGFuZCB0aGUgdXBwZXIgYW5kIGxvd2VyIGJhbmRzIHJlcHJlc2VudGluZyB0d28gc3RhbmRhcmQgZGV2aWF0aW9ucyBhd2F5IGZyb20gdGhlIFNNQS4gQXMgdGhlIHZvbGF0aWxpdHkgb2YgdGhlIGZpbmFuY2lhbCBpbnN0cnVtZW50IGluY3JlYXNlcyBvciBkZWNyZWFzZXMsIHRoZSBiYW5kcyBleHBhbmQgb3IgY29udHJhY3QgYWNjb3JkaW5nbHkuCgpUcmFkZXJzIHVzZSBCb2xsaW5nZXIgQmFuZHMgdG8gaWRlbnRpZnkgcG90ZW50aWFsIGJ1eWluZyBhbmQgc2VsbGluZyBvcHBvcnR1bml0aWVzLiBXaGVuIHRoZSBwcmljZSBvZiB0aGUgZmluYW5jaWFsIGluc3RydW1lbnQgdG91Y2hlcyBvciBjcm9zc2VzIHRoZSB1cHBlciBiYW5kLCBpdCBpcyBjb25zaWRlcmVkIG92ZXJib3VnaHQsIGFuZCBhIHNlbGwgc2lnbmFsIG1heSBiZSBnZW5lcmF0ZWQuIFdoZW4gdGhlIHByaWNlIHRvdWNoZXMgb3IgY3Jvc3NlcyB0aGUgbG93ZXIgYmFuZCwgaXQgaXMgY29uc2lkZXJlZCBvdmVyc29sZCwgYW5kIGEgYnV5IHNpZ25hbCBtYXkgYmUgZ2VuZXJhdGVkLiBbS28gQ2hpdSBZdV0oaHR0cHM6Ly9ib29rZG93bi5vcmcva29jaGl1eXUvdGVjaG5pY2FsLWFuYWx5c2lzLXdpdGgtci1zZWNvbmQtZWRpdGlvbjIvYm9sbGluZ2VyLWJhbmQuaHRtbCkgc2F5cyB0aGF0ICpCdXkgc2lnbmFsKiBhcmlzZXMgd2hlbiBwcmljZSBpcyBhYm92ZSB0aGUgYmFuZCBhbmQgKlNlbGwgc2lnbmFsKiBhcmlzZXMgd2hlbiBwcmljZSBpcyBiZWxvdyB0aGUgYmFuZCwgd2hpY2ggaXMgaW4gZmFjdCB0aGUgc2FtZS4KCkl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgQm9sbGluZ2VyIEJhbmRzIHNob3VsZCBub3QgYmUgdXNlZCBpbiBpc29sYXRpb24gYW5kIHNob3VsZCBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggb3RoZXIgdGVjaG5pY2FsIGFuYWx5c2lzIHRvb2xzIHRvIG1ha2UgaW5mb3JtZWQgdHJhZGluZyBkZWNpc2lvbnMuIEFkZGl0aW9uYWxseSwgdGhlIGJhbmRzIG1heSBub3QgYmUgZWZmZWN0aXZlIGluIGFsbCBtYXJrZXQgY29uZGl0aW9ucywgYW5kIHRyYWRlcnMgc2hvdWxkIGFkanVzdCB0aGVpciBzdHJhdGVnaWVzIGFjY29yZGluZ2x5LgoKCmBgYHtyfQpjaGFydFNlcmllcyhzdG9jaywKICAgICAgICAgICAgc3Vic2V0PScyMDIwLTAxLTAxOjoyMDIwLTA5LTIzJywgdHlwZSA9ICJiYXJzIiwKICAgICAgICAgICAgdGhlbWU9Y2hhcnRUaGVtZSgnd2hpdGUnKSkKYWRkQkJhbmRzKG4gPSAyMCwgc2QgPSAyLCBtYVR5cGUgPSAiU01BIiwgZHJhdyA9ICdiYW5kcycsIG9uID0gLTEpCmBgYApCb2xsaW5nZXIgQmFuZHMgYXJlIGEgcG9wdWxhciB0ZWNobmljYWwgYW5hbHlzaXMgdG9vbCB1c2VkIGJ5IHRyYWRlcnMgdG8gbWVhc3VyZSB0aGUgdm9sYXRpbGl0eSBhbmQgcG90ZW50aWFsIHByaWNlIG1vdmVtZW50cyBvZiBhIGZpbmFuY2lhbCBpbnN0cnVtZW50LgpCb2xsaW5nZXIgQmFuZHMgY29uc2lzdCBvZiB0aHJlZSBsaW5lczogdGhlIG1pZGRsZSBiYW5kLCB3aGljaCBpcyBhIDIwLWRheSBzaW1wbGUgbW92aW5nIGF2ZXJhZ2UgKFNNQSksIGFuZCBhbiB1cHBlciBhbmQgbG93ZXIgYmFuZCB0aGF0IGFyZSB0d28gc3RhbmRhcmQgZGV2aWF0aW9ucyBhd2F5IGZyb20gdGhlIG1pZGRsZSBiYW5kLkluIGVhcmx5IDIwMjAsIFRlc2xhJ3Mgc3RvY2sgcHJpY2UgZmx1Y3R1YXRlZCB3aXRoaW4gdGhlIEJvbGxpbmdlciBCYW5kcywgd2l0aCB0aGUgdXBwZXIgYmFuZCBzZXJ2aW5nIGFzIGEgcmVzaXN0YW5jZSBsZXZlbCBhbmQgdGhlIGxvd2VyIGJhbmQgYXMgYSBzdXBwb3J0IGxldmVsLiBUaGUgd2lkZW5pbmcgb2YgdGhlIEJvbGxpbmdlciBCYW5kcyBpbmRpY2F0ZWQgaW5jcmVhc2VkIHByaWNlIHZvbGF0aWxpdHkuIEJ5IG1pZC0yMDIwLCBUZXNsYSdzIHN0b2NrIHByaWNlIGhhZCByZWJvdW5kZWQgYW5kIGNvbnNpc3RlbnRseSB0cmFkZWQgYWJvdmUgdGhlIG1pZGRsZSBCb2xsaW5nZXIgQmFuZCwgaW5kaWNhdGluZyBzdHJvbmcgYnVsbGlzaCBtb21lbnR1bS4gVGhlcmUgd2VyZSBvY2Nhc2lvbmFsIGJyZWFjaGVzIG9mIHRoZSB1cHBlciBiYW5kLCBzdWdnZXN0aW5nIGFuIHVwd2FyZCB0cmVuZCBpbiB0aGUgc3RvY2sgcHJpY2UuVGhyb3VnaG91dCBKdWx5IHRvIFNlcHRlbWJlciwgVGVzbGEncyBzdG9jayBwcmljZSBjb250aW51ZWQgdG8gY2xpbWIgd2l0aCBoZWlnaHRlbmVkIHZvbGF0aWxpdHksIGxlYWRpbmcgdG8gZnVydGhlciB3aWRlbmluZyBvZiB0aGUgQm9sbGluZ2VyIEJhbmRzLiBEZXNwaXRlIHRoaXMsIHRoZSBzdG9jayBwcmljZSBtb3N0bHkgcmVtYWluZWQgYWJvdmUgdGhlIG1pZGRsZSBiYW5kLCBzaWduYWxpbmcgb25nb2luZyBidWxsaXNoIHNlbnRpbWVudC4KSW4gdGhlIGxhdHRlciBwYXJ0IG9mIDIwMjAgKE9jdG9iZXItRGVjZW1iZXIpLCBUZXNsYSdzIHN0b2NrIHByaWNlIGNvbnRpbnVlZCB0byByaXNlIGR1ZSB0byBwb3NpdGl2ZSBtYXJrZXQgc2VudGltZW50IHJlZ2FyZGluZyB0aGUgY29tcGFueSdzIHBlcmZvcm1hbmNlIGFuZCBmdXR1cmUgcHJvc3BlY3RzLiBEZXNwaXRlIHNvbWUgbWlub3Igc2V0YmFja3MsIHRoZSBzdG9jayBwcmljZSBnZW5lcmFsbHkgc3RheWVkIGFib3ZlIHRoZSBtaWRkbGUgQm9sbGluZ2VyIEJhbmQsIGluZGljYXRpbmcgc3VzdGFpbmVkIGJ1bGxpc2ggbW9tZW50dW0uCgojIyBSZWxhdGl2ZSBTdHJlbmd0aCBJbmRleCAoUlNJKQoKU2ltaWxhciB0byB0aGUgQm9sbGluZ2VyIEJhbmQsIFJTSSBpcyBhIG1vbWVudHVtIGluZGljYXRvciB0aGF0IGV2YWx1YXRlIHRoZSBvdmVyYm91Z2h0IGFuZCBvdmVyc29sZCBjb25kaXRpb24gb2YgYSBmaW5hbmNpYWwgaW5zdHJ1bWVudC4gVGhlIG9ubHkgbWFqb3IgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZXNlIGlzIHRoZSBtZXRob2Qgb2YgZGlzcGxheS4gUlNJIGlzIHBsb3R0ZWQgYXMgYW4gb3NjaWxsYXRvciB3aXRoIGEgcmFuZ2UgYmV0d2VlbiAwIHRvIDEwMCB3aGVyZWFzIHRoZSBCb2xsaW5nZXIgQmFuZCBhcmUgcGxvdHRlZCBhbG9uZyB0aGUgbW92aW5nIGF2ZXJhZ2UgbGluZSBvZiB0aGUgcHJpY2UuIEhlbmNlLCBhIGh1Z2UgYWR2YW50YWdlIG9mIFJTSSBvdmVyIEJvbGxpbmdlciBCYW5kIGlzIHRoZSBhYmlsaXR5IHRvIGRvIGNyb3NzIGNvbXBhcmlzb24gYWNyb3NzIG11bHRpcGxlIGluc3RydW1lbnRzLgoKVXN1YWxseSwgUlNJIGlzIGV2YWx1YXRlZCB1c2luZyBhIDMwLTcwIGN1dG9mZnMuIEFuIFJTSSByZWFkaW5nIG9mIDcwIG9yIGFib3ZlIGluZGljYXRlcyBhbiBvdmVyYm91Z2h0IG9yIG92ZXJ2YWx1ZWQgY29uZGl0aW9uIHdoZXJlYXMgYW4gUlNJIG9mIGJlbG93IDMwIGluZGljYXRlcyBhIHVuZGVydmFsdWVkIGNvbmRpdGlvbi4KClJlbGF0aXZlIFN0cmVuZ3RoIEluZGV4IChSU0kpIGlzIGEgcG9wdWxhciB0ZWNobmljYWwgYW5hbHlzaXMgaW5kaWNhdG9yIHVzZWQgdG8gbWVhc3VyZSB0aGUgc3RyZW5ndGggb2YgcHJpY2UgbW92ZW1lbnRzIGluIGZpbmFuY2lhbCBtYXJrZXRzLiBJdCB3YXMgZGV2ZWxvcGVkIGJ5IEouIFdlbGxlcyBXaWxkZXIgSnIuIGFuZCBpcyB1c2VkIHRvIGlkZW50aWZ5IG92ZXJib3VnaHQgYW5kIG92ZXJzb2xkIGNvbmRpdGlvbnMuCgpUaGUgY2FsY3VsYXRpb24gb2YgUlNJIHJlcXVpcmVzIHNldmVyYWwgc3RlcHM6CgoxLiBXaGV0aGVyIHByaWNlIGhhcyBnb25lIHVwIG9yIGRvd24gZWFjaCBkYXkKCjIuIFJlbGF0aXZlIHN0cmVuZ3RoIChSUyk6IHRoZSByYXRpbyBvZiB0aGUgKHNpbXBsZSBvciBleHBvbmVudGlhbCkgYXZlcmFnZSBudW1iZXJzIG9mIHVwIGRheSB0byB0aGUgYXZlcmFnZSBvZiBkb3duIGRheQoKMy4gUmVsYXRpdmUgc3RyZW5ndGggaW5kZXggKFJTSSk6IG5vcm1hbGl6ZSBSUyB0byB0aGUgc2NhbGUgZnJvbSAwIHRvIDEwMC4KClN0ZXAgMS4gQ2FsY3VsYXRlCgogJCRVX3QgPSAxIFxxdWFkIFx0ZXh0e2lmfSBccXVhZCBQX3QgPiBQX3t0LTF9LCBccXVhZCBcdGV4dHtvdGhlcndpc2V9IFxxdWFkIFVfdD0wJCQKCiQkRF90ID0gMSBccXVhZCBcdGV4dHtpZn0gXHF1YWQgUF90IDwgUF97dC0xfSwgXHF1YWQgXHRleHR7b3RoZXJ3aXNlfSBccXVhZCBEX3Q9IDAkJApTdGVwIDI6CiQkUlNfe3Qsbn0gPSBcZnJhY3tcZnJhY3tVX3QgKyBVX3t0LTF9ICsgXGRvdHMgKyBVX3t0LW4rMX19e259fXtcZnJhY3tEX3QgKyBEX3t0LTF9ICsgXGRvdHMgKyBEX3t0LW4rMX19e259fSQkCgphbmQsIGZpbmFsbHkKCiQkUlNJX3t0LG59ID0gMTAwIFxmcmFje1JTX3t0LG59fXsxK1JTX3t0LG59fSQkCgpUaGUgUlNJIG9zY2lsbGF0ZXMgYmV0d2VlbiAwIGFuZCAxMDAsIHdpdGggcmVhZGluZ3MgYWJvdmUgNzAgaW5kaWNhdGluZyB0aGF0IHRoZSBhc3NldCBpcyBvdmVyYm91Z2h0LCBhbmQgcmVhZGluZ3MgYmVsb3cgMzAgaW5kaWNhdGluZyB0aGF0IHRoZSBhc3NldCBpcyBvdmVyc29sZC4KClRyYWRlcnMgYW5kIGludmVzdG9ycyB1c2UgdGhlIFJTSSB0byBpZGVudGlmeSBwb3RlbnRpYWwgdHJlbmQgcmV2ZXJzYWxzIGFuZCBnZW5lcmF0ZSBidXkgYW5kIHNlbGwgc2lnbmFscy4gRm9yIGV4YW1wbGUsIHdoZW4gdGhlIFJTSSBjcm9zc2VzIGFib3ZlIDcwLCBpdCBpcyBjb25zaWRlcmVkIG92ZXJib3VnaHQsIGFuZCBhIHNlbGwgc2lnbmFsIG1heSBiZSBnZW5lcmF0ZWQuIENvbnZlcnNlbHksIHdoZW4gdGhlIFJTSSBjcm9zc2VzIGJlbG93IDMwLCBpdCBpcyBjb25zaWRlcmVkIG92ZXJzb2xkLCBhbmQgYSBidXkgc2lnbmFsIG1heSBiZSBnZW5lcmF0ZWQuCgpUaGUgUlNJIGNhbiBhbHNvIGJlIHVzZWQgdG8gaWRlbnRpZnkgZGl2ZXJnZW5jZXMgYmV0d2VlbiB0aGUgUlNJIGxpbmUgYW5kIHRoZSBwcmljZSBvZiB0aGUgYXNzZXQgYmVpbmcgYW5hbHl6ZWQuIFdoZW4gdGhlIFJTSSBsaW5lIGRpdmVyZ2VzIGZyb20gdGhlIHByaWNlLCBpdCBjYW4gYmUgYW4gaW5kaWNhdGlvbiB0aGF0IGEgdHJlbmQgcmV2ZXJzYWwgbWF5IGJlIGltbWluZW50LgoKSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBsaWtlIGFueSB0ZWNobmljYWwgYW5hbHlzaXMgdG9vbCwgdGhlIFJTSSBpcyBub3QgaW5mYWxsaWJsZSBhbmQgc2hvdWxkIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBvdGhlciBpbmRpY2F0b3JzIGFuZCBhbmFseXNpcyBtZXRob2RzIHRvIG1ha2UgaW5mb3JtZWQgdHJhZGluZyBkZWNpc2lvbnMuIEFkZGl0aW9uYWxseSwgdHJhZGVycyBzaG91bGQgYWRqdXN0IHRoZWlyIHN0cmF0ZWdpZXMgYW5kIHBhcmFtZXRlcnMgdG8gZml0IHRoZSBzcGVjaWZpYyBtYXJrZXQgY29uZGl0aW9ucyBiZWluZyBhbmFseXplZC4KCmBgYHtyfQpjaGFydFNlcmllcyhzdG9jaywKICAgICAgICAgICAgc3Vic2V0PScyMDIwLTAxLTAxOjoyMDIwLTA5LTIzJywgdHlwZSA9ICJiYXJzIiwKICAgICAgICAgICAgdGhlbWU9Y2hhcnRUaGVtZSgnd2hpdGUnKSkKYWRkUlNJKG4gPSAxNCwgbWFUeXBlID0gIkVNQSIsIHdpbGRlciA9IFRSVUUpCgpgYGAKU0kgaXMgYSBtb21lbnR1bSBpbmRpY2F0b3IgdGhhdCBldmFsdWF0ZSB0aGUgb3ZlcmJvdWdodCBhbmQgb3ZlcnNvbGQgY29uZGl0aW9uIG9mIGEgZmluYW5jaWFsIGluc3RydW1lbnQuCkluIHRoZSBmaXJzdCB0d28gbW9udGhzIG9mIDIwMjAsIFRlc2xhJ3Mgc3RvY2sgcHJpY2UgZXhwZXJpZW5jZWQgYSBzdXJnZSBkdWUgdG8gcG9zaXRpdmUgbmV3cyBhbmQgaW52ZXN0b3Igb3B0aW1pc20gc3Vycm91bmRpbmcgZWxlY3RyaWMgdmVoaWNsZXMgYW5kIHRoZSBjb21wYW55J3MgZ3Jvd3RoIHByb3NwZWN0cy4gSG93ZXZlciwgdGhlIHN0b2NrIGJlY2FtZSBvdmVyYm91Z2h0LCBpbmRpY2F0aW5nIGEgcG9zc2libGUgcHVsbGJhY2sgb3IgY29uc29saWRhdGlvbi4gRnJvbSBGZWJydWFyeSB0byBNYXJjaCAyMDIwLCBUZXNsYSwgYWxvbmcgd2l0aCBtYW55IG90aGVyIGNvbXBhbmllcywgZmFjZWQgYSBzaGFycCBkZWNsaW5lIGluIGl0cyBzdG9jayBwcmljZSBkdWUgdG8gdGhlIGdsb2JhbCBmaW5hbmNpYWwgbWFya2V0IGRvd250dXJuLiBUaGlzIGNhdXNlZCB0aGUgc3RvY2sgdG8gZW50ZXIgb3ZlcnNvbGQgdGVycml0b3J5LCBzdWdnZXN0aW5nIGV4Y2Vzc2l2ZSBzZWxsaW5nIHByZXNzdXJlIGFuZCBhIHBvdGVudGlhbCBidXlpbmcgb3Bwb3J0dW5pdHkgZm9yIHRyYWRlcnMuIEJldHdlZW4gTWFyY2ggYW5kIEp1bmUgMjAyMCwgVGVzbGEncyBzdG9jayBwcmljZSBncmFkdWFsbHkgcmVjb3ZlcmVkIGFzIGludmVzdG9yIHNlbnRpbWVudCBpbXByb3ZlZCBhbmQgdGhlIGNvbXBhbnkncyBmdW5kYW1lbnRhbHMgcmVtYWluZWQgc3Ryb25nLiBEdXJpbmcgdGhpcyBwZXJpb2QsIHRoZSBzdG9jayBlbnRlcmVkIGEgcGhhc2Ugb2YgY29uc29saWRhdGlvbiBhbmQgaW5kZWNpc2lvbiwgd2l0aCBpdHMgUlNJIGZsdWN0dWF0aW5nIGJldHdlZW4gMzAgYW5kIDcwLiBUaGUgc2Vjb25kIGhhbGYgb2YgMjAyMCB3aXRuZXNzZWQgYSByZW1hcmthYmxlIHJhbGx5IGluIFRlc2xhJ3Mgc3RvY2sgcHJpY2UsIGRyaXZlbiBieSBzdHJvbmcgcXVhcnRlcmx5IGVhcm5pbmdzLCBwb3NpdGl2ZSBidXNpbmVzcyBkZXZlbG9wbWVudHMsIGFuZCBpbmNyZWFzZWQgaW52ZXN0b3IgaW50ZXJlc3QgaW4gZWxlY3RyaWMgdmVoaWNsZXMuIE9uY2UgYWdhaW4sIHRoZSBzdG9jayBiZWNhbWUgb3ZlcmJvdWdodCwgaW5kaWNhdGluZyBhIHBvdGVudGlhbCB2dWxuZXJhYmlsaXR5IHRvIGEgcHVsbGJhY2suCgoKIyMgUGFyYWJvbGljIHN0b3AgYW5kIHJldmVyc2FsCgpUaGUgUGFyYWJvbGljIFN0b3AgYW5kIFJldmVyc2FsIChTQVIpIGlzIGEgdGVjaG5pY2FsIGFuYWx5c2lzIHRvb2wgdXNlZCBieSB0cmFkZXJzIHRvIGRldGVybWluZSBwb3RlbnRpYWwgdHJlbmQgcmV2ZXJzYWxzIGluIHByaWNlIG1vdmVtZW50cy4gSXQgd2FzIGRldmVsb3BlZCBieSBKLiBXZWxsZXMgV2lsZGVyIEpyLiBhbmQgaXMgdXNlZCB0byBzZXQgdHJhaWxpbmcgc3RvcC1sb3NzIG9yZGVycyBpbiBvcmRlciB0byBsaW1pdCBwb3RlbnRpYWwgbG9zc2VzIGluIGEgdHJhZGUuCgpUaGUgU0FSIHVzZXMgYSBzZXJpZXMgb2YgZG90cyBwbGFjZWQgYWJvdmUgb3IgYmVsb3cgdGhlIHByaWNlIG9mIHRoZSBhc3NldCBiZWluZyBhbmFseXplZCB0byBpbmRpY2F0ZSBwb3RlbnRpYWwgcmV2ZXJzYWxzIGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHRyZW5kLiBXaGVuIHRoZSBwcmljZSBpcyBtb3ZpbmcgdXB3YXJkcywgdGhlIFNBUiBkb3RzIGFyZSBwbGFjZWQgYmVsb3cgdGhlIHByaWNlLCBhbmQgd2hlbiB0aGUgcHJpY2UgaXMgbW92aW5nIGRvd253YXJkcywgdGhlIFNBUiBkb3RzIGFyZSBwbGFjZWQgYWJvdmUgdGhlIHByaWNlLgoKVGhlIFBhcmFib2xpYyBTdG9wIGFuZCBSZXZlcnNhbCAoU0FSKSBpcyBhIHRlY2huaWNhbCBhbmFseXNpcyB0b29sIHVzZWQgYnkgdHJhZGVycyB0byBkZXRlcm1pbmUgcG90ZW50aWFsIHRyZW5kIHJldmVyc2FscyBpbiBwcmljZSBtb3ZlbWVudHMuIEl0IHdhcyBkZXZlbG9wZWQgYnkgSi4gV2VsbGVzIFdpbGRlciBKci4gYW5kIGlzIHVzZWQgdG8gc2V0IHRyYWlsaW5nIHN0b3AtbG9zcyBvcmRlcnMgaW4gb3JkZXIgdG8gbGltaXQgcG90ZW50aWFsIGxvc3NlcyBpbiBhIHRyYWRlLgoKVGhlIFNBUiB1c2VzIGEgc2VyaWVzIG9mIGRvdHMgcGxhY2VkIGFib3ZlIG9yIGJlbG93IHRoZSBwcmljZSBvZiB0aGUgYXNzZXQgYmVpbmcgYW5hbHl6ZWQgdG8gaW5kaWNhdGUgcG90ZW50aWFsIHJldmVyc2FscyBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSB0cmVuZC4gV2hlbiB0aGUgcHJpY2UgaXMgbW92aW5nIHVwd2FyZHMsIHRoZSBTQVIgZG90cyBhcmUgcGxhY2VkIGJlbG93IHRoZSBwcmljZSwgYW5kIHdoZW4gdGhlIHByaWNlIGlzIG1vdmluZyBkb3dud2FyZHMsIHRoZSBTQVIgZG90cyBhcmUgcGxhY2VkIGFib3ZlIHRoZSBwcmljZS4KCkFzIHRoZSBwcmljZSBtb3ZlcyBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSB0cmVuZCwgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlIHByaWNlIGFuZCB0aGUgU0FSIGRvdHMgaW5jcmVhc2VzLiBXaGVuIHRoZSBwcmljZSByZWFjaGVzIGEgY2VydGFpbiBkaXN0YW5jZSBmcm9tIHRoZSBTQVIgZG90cywgdGhlIGRvdHMgYmVnaW4gdG8gbW92ZSBjbG9zZXIgdG8gdGhlIHByaWNlLCBpbmRpY2F0aW5nIHRoYXQgYSBwb3RlbnRpYWwgcmV2ZXJzYWwgaW4gdGhlIHRyZW5kIG1heSBiZSBpbW1pbmVudC4gV2hlbiB0aGUgcHJpY2UgY3Jvc3NlcyB0aGUgU0FSIGRvdHMsIGl0IGlzIGNvbnNpZGVyZWQgYSBzaWduYWwgdG8gZXhpdCBhIHRyYWRlIGFuZCBwb3RlbnRpYWxseSBlbnRlciBhIG5ldyB0cmFkZSBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uLgoKVGhlIFBhcmFib2xpYyBTdG9wIGFuZCBSZXZlcnNlIChTQVIpIGlzIGEgdGVjaG5pY2FsIGFuYWx5c2lzIHRvb2wgdXNlZCB0byBpZGVudGlmeSBwb3RlbnRpYWwgcmV2ZXJzYWwgcG9pbnRzIGluIGEgcHJpY2UgdHJlbmQuIFRoZSBmb3JtdWxhIGZvciBjYWxjdWxhdGluZyB0aGUgUGFyYWJvbGljIFNBUiBpcyBhcyBmb2xsb3dzOgoKRm9yIGFuIHVwdHJlbmQ6CgokJFNBUl97bisxfSA9IFNBUl9uICsgQUYgKiAoRVAgLSBTQVJfbikkJAoKRm9yIGEgZG93bnRyZW5kOgoKJCRTQVJfe24rMX0gPSBTQVJfbiAtIEFGICogKFNBUl9uIC0gRVApJCQKCldoZXJlOgoKJFNBUl9uJCBpcyB0aGUgY3VycmVudCBwZXJpb2QncyAkU0FSJCB2YWx1ZQoKJFNBUl97bisxfSQgaXMgdGhlIG5leHQgcGVyaW9kJ3MgJFNBUiQgdmFsdWUKCiRBRiQgaXMgdGhlIGFjY2VsZXJhdGlvbiBmYWN0b3IsIHdoaWNoIHN0YXJ0cyBhdCAwLjAyIGFuZCBpbmNyZWFzZXMgYnkgMC4wMiBlYWNoIHRpbWUgYSBuZXcgZXh0cmVtZSBwb2ludCAoRVApIGlzIHJlYWNoZWQsIHVwIHRvIGEgbWF4aW11bSBvZiAwLjIwCgokRVAkIGlzIHRoZSBoaWdoZXN0IGhpZ2ggb3IgbG93ZXN0IGxvdyBvZiB0aGUgY3VycmVudCB0cmVuZCwgZGVwZW5kaW5nIG9uIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHRyZW5kCgpUaGUgaW5pdGlhbCBTQVIgdmFsdWUgaXMgc2V0IHRvIHRoZSBsb3dlc3QgbG93IGZvciBhbiB1cHRyZW5kLCBhbmQgdGhlIGhpZ2hlc3QgaGlnaCBmb3IgYSBkb3dudHJlbmQuIFRoZSBTQVIgdmFsdWUgaXMgdGhlbiBjYWxjdWxhdGVkIGZvciBlYWNoIHN1YnNlcXVlbnQgcGVyaW9kIHVzaW5nIHRoZSBhYm92ZSBmb3JtdWxhLgoKVGhlIFNBUiBjYW4gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIG90aGVyIHRlY2huaWNhbCBhbmFseXNpcyB0b29scywgc3VjaCBhcyBtb3ZpbmcgYXZlcmFnZXMgb3IgdHJlbmQgbGluZXMsIHRvIGNvbmZpcm0gcG90ZW50aWFsIHRyZW5kIHJldmVyc2FscyBhbmQgaWRlbnRpZnkgcG90ZW50aWFsIGVudHJ5IG9yIGV4aXQgcG9pbnRzIGZvciB0cmFkZXMuCgpJdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHRoZSBTQVIgc2hvdWxkIG5vdCBiZSB1c2VkIGluIGlzb2xhdGlvbiBhbmQgc2hvdWxkIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBvdGhlciBhbmFseXNpcyBtZXRob2RzIHRvIG1ha2UgaW5mb3JtZWQgdHJhZGluZyBkZWNpc2lvbnMuIEFkZGl0aW9uYWxseSwgdHJhZGVycyBzaG91bGQgYWRqdXN0IHRoZSBwYXJhbWV0ZXJzIG9mIHRoZSBTQVIgdG8gZml0IHRoZSBzcGVjaWZpYyBtYXJrZXQgY29uZGl0aW9ucyBiZWluZyBhbmFseXplZC4KCgoKCmBgYHtyfQpjaGFydFNlcmllcyhzdG9jaywKICAgICAgICAgICAgc3Vic2V0PScyMDIwLTAxLTAxOjoyMDIwLTA5LTIzJywgdHlwZSA9ICJiYXJzIiwKICAgICAgICAgICAgdGhlbWU9Y2hhcnRUaGVtZSgnd2hpdGUnKSkKYWRkU0FSKGFjY2VsID0gYygwLjAyLCAwLjIpLCBjb2wgPSAiYmx1ZSIpCgoKYGBgClBhcmFib2xpYyBTdG9wIGFuZCBSZXZlcnNhbCAoU0FSKSBpcyBhIHRlY2huaWNhbCBhbmFseXNpcyB0b29sIHRvIGlkZW50aWZ5IHBvc3NpYmxlIHRyZW5kIHJldmVyc2FscyBpbiBwcmljZSBtb3ZlbWVudHMuVGVzbGEncyBzdG9jayBzYXcgYSBzaWduaWZpY2FudCBwcmljZSBpbmNyZWFzZSBhbmQgYnVsbGlzaCB0cmVuZCBmcm9tIEphbnVhcnkgdG8gRmVicnVhcnkgMjAyMCwgd2l0aCB0aGUgUGFyYWJvbGljIFNBUiBjb25zaXN0ZW50bHkgYmVsb3cgdGhlIHByaWNlLiBUaHJvdWdob3V0IEZlYnJ1YXJ5IHRvIG1pZC1NYXJjaCAyMDIwLCBUZXNsYSdzIHN0b2NrIGNvbnRpbnVlZCB0byByaXNlLCByZWFjaGluZyBuZXcgYWxsLXRpbWUgaGlnaHMsIGFuZCB0aGUgU0FSIGRvdHMgcmVtYWluZWQgYmVsb3cgdGhlIHByaWNlLCBpbmRpY2F0aW5nIHN1cHBvcnQgZm9yIHRoZSBidWxsaXNoIG1vbWVudHVtLgpGcm9tIGxhdGUgTWFyY2ggdG8gQXByaWwgMjAyMCwgVGVzbGEncyBwcmljZSBmbHVjdHVhdGVkIGR1ZSB0byBtYXJrZXQgdm9sYXRpbGl0eSwgYW5kIHRoZSBTQVIgZG90cyBhYm92ZSB0aGUgcHJpY2UgYWN0ZWQgYXMgcmVzaXN0YW5jZSwgcmVmbGVjdGluZyBiZWFyaXNoIHNlbnRpbWVudC4gQmV0d2VlbiBNYXkgYW5kIEF1Z3VzdCAyMDIwLCBUZXNsYSBlbnRlcmVkIGEgY29uc29saWRhdGlvbiBwaGFzZSwgd2l0aCB0aGUgc3RvY2sgcHJpY2Ugc3RhYmlsaXppbmcuIFRoZSBTQVIgZG90cyBjbG9zZWx5IGFsaWduZWQgd2l0aCB0aGUgcHJpY2UsIGluZGljYXRpbmcgbWFya2V0IGluZGVjaXNpb24uIEZyb20gU2VwdGVtYmVyIHRvIE5vdmVtYmVyIDIwMjAsIFRlc2xhJ3Mgc3RvY2sgZ3JhZHVhbGx5IHJlZ2FpbmVkIGl0cyB1cHdhcmQgbW9tZW50dW0gZHVlIHRvIHBvc2l0aXZlIG5ld3MgYWJvdXQgaXRzIGJ1c2luZXNzIG9wZXJhdGlvbnMgYW5kIGZ1dHVyZSBwcm9zcGVjdHMuIFRoZSBTQVIgZG90cyByZW1haW5lZCBiZWxvdyB0aGUgcHJpY2UsIHN1cHBvcnRpbmcgdGhlIHJlbmV3ZWQgYnVsbGlzaCB0cmVuZC5Ub3dhcmRzIHRoZSBlbmQgb2YgMjAyMCwgVGVzbGEncyBzdG9jayBwcmljZSBzdXJnZWQgdG8gbmV3IGhpZ2hzLCBkcml2ZW4gYnkgaW52ZXN0b3Igb3B0aW1pc20gYW5kIHN0cm9uZyBkZW1hbmQgZm9yIGVsZWN0cmljIHZlaGljbGVzLiBUaGUgUGFyYWJvbGljIFNBUiBjb250aW51ZWQgdG8gc3RheSBiZWxvdyB0aGUgcHJpY2UsIHN1Z2dlc3RpbmcgYSBzdXN0YWluZWQgYnVsbGlzaCBiaWFzLgoKIyMgU3VtbWFyeSBncmFwaHMKCkFwYXJ0IGZyb20gdGhlIGZldyB0aGF0IHdhcyBtZW50aW9uZWQgYWJvdmUsIG90aGVyIGluZGljYXRvcnMgaW5jbHVkZSByYXRlIG9mIGNoYW5nZSwgbW9uZXkgZmxvdyBpbmRleCAoTUZJKSwgTUFDRCBhbmQgZXRjLgoKIyMgQ2hhcnQgU2VyaWVzCgpDaGFydFNlcmllcyBwcm92aWRlcyBhbiBhbHRlcm5hdGl2ZSB3YXkgdG8gc3VtbWFyaXNlIHRoZSBwbG90LiBJbnN0ZWFkIG9mIG9uZSBwbG90IGZvciBlYWNoIGluZGljYXRvciwgYWxsIG9mIHRoZW0gY2FuIG5vdyBiZSBjb21waWxlZCBpbnRvIGEgc2luZ2xlIGZpZ3VyZSwgd2hlcmUgaW5kaWNhdG9ycyBjYW4gYmUgYWRkZWQgdG8gdGhlIGJvdHRvbSBvZiB0aGUgZXhpc3RpbmcgcGxvdC4KCmBgYHtyfQpjaGFydFNlcmllcyhzdG9jaywKICAgICAgICAgICAgc3Vic2V0PScyMDIwLTAxLTAxOjoyMDIwLTA5LTIzJywgdHlwZSA9ICJiYXJzIiwKICAgICAgICAgICAgdGhlbWU9Y2hhcnRUaGVtZSgnd2hpdGUnKSkKYWRkQkJhbmRzKG49MjAsc2Q9MikKYWRkUlNJKG49MTQsbWFUeXBlPSJFTUEiKQphZGRNQUNEKGZhc3Q9MTIsc2xvdz0yNixzaWduYWw9OSx0eXBlPSJFTUEiKQoKYGBgCgoK