Email             :
Instagram     : https://www.instagram.com/nikitaindriyni
RPubs            : https://rpubs.com/nikitaindriyani/
Address         : ARA Center, Matana University Tower
                         Jl. CBD Barat Kav, RT.1, Curug Sangereng, Kelapa Dua, Tangerang, Banten 15810.



1 Introduction

Seperti yang telah saya sebutkan sebelumnya, Regression Models digunakan untuk menggambarkan hubungan antara variabel dengan memasang garis ke data yang diamati. Model regresi linear menggunakan garis lurus, sementara model regresi logistik dan nonlinear menggunakan garis melengkung. Regresi memungkinkan Anda untuk memperkirakan bagaimana variabel dependen berubah saat variabel independen berubah.

Di bagian ini kita akan memfokuskan cara menggunakan Simple Linear Regression (SLR) untuk memperkirakan hubungan antara dua variabel kuantitatif. Kita juga dapat menggunakan regresi linier sederhana untuk mengetahui:

  • Seberapa kuat hubungan antara dua variabel.
  • Nilai variabel dependen pada nilai tertentu dari variabel independen



Contoh:

Asumsikan Anda adalah peneliti sosial yang tertarik pada hubungan antara pendapatan dan kebahagiaan. Anda mensurvei 500 orang yang pendapatannya berkisar dari $15k hingga $75k dan meminta mereka untuk memberi peringkat kebahagiaan mereka dalam skala 1 hingga 10. Variabel independen (pendapatan) dan variabel dependen (kebahagiaan) Anda berdua kuantitatif, sehingga Anda dapat melakukan analisis regresi untuk melihat apakah ada hubungan linier di antara mereka.


2 Model Umum

Model regresi linear sederhana mengasumsikan bahwa hubungan linier ada antara ekspektasi bersyarat dari dua variabel kuantitatif:

Dimana,

  • \(Y\) dianggap sebagai variabel prediktor, penjelasan, atau dependen.
  • $X $ dianggap sebagai respons, hasil, atau variabel independen.
  • \(beta_1\) adalah parameter penyadapan atau koefisien
  • \(beta_2\) adalah parameter kemiringan atau koefisien
  • \(hat{Y}\) adalah perkiraan nilai \(Y\) yang diberikan \(X\)
  • \(b_1\) dan \(b_2\) adalah nilai perkiraan koefisien

3 Regresi Linear Sederhana di R

Data untuk contoh ini disimpan dalam paket R ‘PoEdata’. Pertama, Anda harus menginstal paket “PoEdata”, ketik baris skrip berikut di jendela Konsol RStudio:

#install.packages("devtools")                         # if not already installed
library(devtools)                                    # load the library
#install_git("https://github.com/ccolonescu/PoEdata") # install `PoEdata`

Kemudian, pertimbangkan kumpulan data:

library(PoEdata)                                     # load the library PoEdata
library(DT)                                          # use for datatable fuction 
data("food", package="PoEdata")
datatable(food)

Selalu merupakan ide yang baik untuk secara visual memeriksa data dalam diagram sebar, yang dapat dibuat menggunakan fungsi plot(). Angka di bawah ini adalah diagram pengeluaran makanan yang tersebar pada pendapatan, menunjukkan bahwa ada hubungan positif antara pendapatan dan pengeluaran makanan.

plot(food$income, food$food_exp, 
     ylim=c(0, max(food$food_exp)),
     xlim=c(0, max(food$income)),
     xlab="weekly income in $100", 
     ylab="weekly food expenditure in $", 
     type = "p")

About \(R^2\)


3.1 Memperkirakan Regresi Linear

Untuk data pengeluaran makanan, model regresi akan

\[ \begin{align} \tag{1} Y&=\beta_1+\beta_2 *X+e \\ food_{exp}&=\beta_1+\beta_2*income+e \end{align} \]

fungsi R untuk memperkirakan model regresi linear adalahlm(y~x, data) yang, digunakan hanya dengan sendirinya tidak menunjukkan output apa pun; Berguna untuk memberi nama model, seperti mod1, lalu menunjukkan hasilnya menggunakan summary(mod1).

mod1 <- lm(food_exp ~ income, data = food)           # linear model
smod1<- summary(mod1)                                # get summary 
smod1
## 
## Call:
## lm(formula = food_exp ~ income, data = food)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -223.025  -50.816   -6.324   67.879  212.044 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   83.416     43.410   1.922   0.0622 .  
## income        10.210      2.093   4.877 1.95e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 89.52 on 38 degrees of freedom
## Multiple R-squared:  0.385,  Adjusted R-squared:  0.3688 
## F-statistic: 23.79 on 1 and 38 DF,  p-value: 1.946e-05

Jika Anda hanya tertarik pada beberapa hasil regresi, seperti koefisien yang diperkirakan, Anda dapat mengambilnya menggunakan fungsi tertentu, seperti fungsi coef().

b1 <- coef(mod1)[[1]]                                # the estimated value of  β1
b2 <- coef(mod1)[[2]]                                # the estimated value of  β2
b1
## [1] 83.416
b2
## [1] 10.20964

Dari hasilnya, kita dapat menulis regresi linier kami yang memperkirakan sebagai:

\[ \begin{align} \tag{2} \hat{Y}&=b_1+b_2*X \\ \hat{food_{exp}}&=83.416+10.20964*income \end{align} \]

Parameter penyadapan, \(\beta_1\) , biasanya sedikit penting dalam model ekonometrik; kami sebagian besar tertarik pada parameter kemiringan, \(\beta_2\). Perkiraan nilai \(\beta_2\) menunjukkan bahwa pengeluaran makanan untuk keluarga rata-rata meningkat sebesar 10,209643 ketika pendapatan keluarga meningkat sebesar 1 unit, yang dalam hal ini adalah $100. Fungsi R abline() menambahkan garis regfression’ ke diagram yang sebelumnya diplot untuk menyebarkan di bawah ini:

plot(food$income, food$food_exp, 
     xlab="weekly income in $100", 
     ylab="weekly food expenditure in $", 
     type = "p")
abline(b1,b2)

Bagaimana seseorang dapat mengambil berbagai hasil regresi? Untuk mengambil hasil tertentu, Anda cukup merujuknya dengan nama objek, diikuti dengan tanda $ dan nama hasil yang ingin Anda ambil. Misalnya, jika kita ingin vektor koefisien dari ‘mod1’, kami menyebutnya sebagai mod1\$coefficients dan smod1\$coefficients:

mod1$coefficients
## (Intercept)      income 
##    83.41600    10.20964
smod1$coefficients
##             Estimate Std. Error  t value     Pr(>|t|)
## (Intercept) 83.41600  43.410163 1.921578 6.218242e-02
## income      10.20964   2.093264 4.877381 1.945862e-05
names(mod1)                                          # for more
names(smod1)                                         # for more

Seperti yang telah kita lihat sebelumnya, namun, beberapa hasil ini dapat diambil menggunakan fungsi tertentu, seperti coef(mod1), resid(mod1), fitted(mod1), and vcov(mod1).


3.2 Prediksi dengan Model SLR

Perkiraan parameter regresi, \(b_1\) dan \(b_2\) memungkinkan kami untuk memprediksi pengeluaran makanan yang diharapkan untuk pendapatan tertentu. Yang perlu kita lakukan adalah menyambungkan nilai parameter yang diperkirakan dan pendapatan yang diberikan ke dalam persamaan seperti Persamaan 2. Misalnya, nilai yang diharapkan dari food_exp untuk pendapatan $2000 dihitung dalam Persamaan 3 . (Ingatlah untuk membagi pendapatan sebesar 100, karena data untuk pendapatan variabel adalah dalam ratusan dolar.)

\[ \begin{align} \tag{3} \hat{food_{exp}}&=83.416+10.20964*20\\ & = $ 287.608861 \end{align} \]

3.3 Prediksi dengan Model SLR

R, bagaimanapun, melakukan perhitungan ini untuk kita dengan fungsinya yang disebut predict(). Mari kita memperluas sedikit contoh untuk lebih dari satu pendapatan yang kita prediksi pengeluaran makanan, katakanlah pendapatan = $2000, $2500, dan $2700. Fungsi predict() dalam R mengharuskan nilai baru dari variabel independen diatur di bawah formulir tertentu, yang disebut bingkai data. Bahkan ketika kita hanya ingin memprediksi untuk satu pendapatan, kita membutuhkan struktur bingkai data yang sama. Dalam R, satu set angka disatukan menggunakan struktur c(). Urutan berikut menunjukkan contoh ini.

mod1 <- lm(food_exp~income, data=food)
newx <- data.frame(income = c(20, 25, 27))
yhat <- predict(mod1, newx)
yhat                                                 # prints the result
##        1        2        3 
## 287.6089 338.6571 359.0764

3.4 Menilai Koefisien Regresi

Koefisien regresi \(b_1\) dan \(b_2\) adalah variabel acak karena tergantung pada sampel. Dalam hal ini, kami mengulangi sampel untuk menilai koefisien regresi. Mari kita membangun sejumlah subsample acak dari data makanan dan menghitung ulang $b_1 $ dan $b_2 $ . Subsample acak dapat dibangun menggunakan fungsi sample(), karena contoh berikut hanya menggambarkan untuk \(b_2\).

N <- nrow(food)   # returns the number of observations in the dataset
C <- 50           # desired number of subsamples
S <- 38           # desired sample size

sumb2 <- 0
for (i in 1:C){   # a loop over the number of subsamples
  set.seed(3*i)   # a different seed for each subsample  
  subsample <- food[sample(1:N, size=S, replace=TRUE), ]
  mod2 <- lm(food_exp~income, data=subsample)
  #sum b2 for all subsamples:
  sumb2 <- sumb2 + coef(mod2)[[2]]
}
print(sumb2/C, digits = 3)
## [1] 9.89

Hasilnya, \(b_2=9,88\), adalah rata-rata 50 estimasi \(b_2\).


3.5 (Tugas 1) Perkiraan Var dan Cov

Banyak aplikasi memerlukan perkiraan varians dan kovarians koefisien regresi. R menyimpannya dalam matriks vcov():

(varb1 <- vcov(mod1)[1, 1])
## [1] 1884.442

Variansi dari b1 nilainya sangat besar. Itu berarti nilai nyata dari b1 menyimpang jauh dari rata-rata (ekspektasi) b1 dalam rentang 1884.442 dimana nilai rata-ratanya sebagai pusat rentang.

(varb2 <- vcov(mod1)[2, 2])
## [1] 4.381752

Variansi dari b2 nilainya kecil yang berarti nilai nyata dari b2 hanya sedikit menyimpang dari nilai rata-rata (ekspektasi) b2 dalam rentang 4.381752 dimana nilai rata-ratanya sebagai pusat rentang

(covb1b2 <- vcov(mod1)[1,2])
## [1] -85.90316

Kovariansi bernilai negatif berarti variabel b1 dan b2 memiliki hubungan yang berlawanan, dimana saat salah satu variabel meningkat, variabel lainnya akan menurun.

Dengan kata lain, apabila kovariansinya positif berarti hubungannya searah atau relasinya positif.


4 Hubungan Non-Linear

Kadang-kadang diagram plot sebar atau beberapa pertimbangan teoritis menunjukkan hubungan non-linear. Hubungan non-linear yang paling populer melibatkan logaritma dari variabel dependen atau independen dan fungsi polinomial. Model kuadrat membutuhkan kuadrat dari variabel independen.

\[ \begin{align} \tag{4} Y=\beta_1+\beta_2*X^2+e\\ \end{align} \] Dalam R, variabel independen yang melibatkan operator matematika dapat dimasukkan dalam persamaan regresi dengan fungsi I(). Contoh berikut menggunakan dataset br dari paket PoEdata, yang mencakup harga jual dan atribut 1080 rumah di Baton Rouge, LA. harga adalah harga jual dalam dolar, dan sqft adalah area permukaan di kaki persegi.

data(br)
mod2 <- lm(price~I(sqft^2), data=br)
b1 <- coef(mod2)[[1]]
b2 <- coef(mod2)[[2]]
sqftx=c(2000, 4000, 6000)            # given values for sqft
pricex=b1+b2*sqftx^2                 # prices corresponding to given sqft 
DpriceDsqft <- 2*b2*sqftx            # marginal effect of sqft on price
elasticity=DpriceDsqft*sqftx/pricex 
b1; b2; DpriceDsqft; elasticity      # prints results
## [1] 55776.57
## [1] 0.0154213
## [1]  61.68521 123.37041 185.05562
## [1] 1.050303 1.631251 1.817408

Kami sekarang ingin menggambar diagram sebar dan melihat bagaimana fungsi kuadrat sesuai dengan data. Potongan kode berikutnya menyediakan dua alternatif untuk membangun grafik seperti itu. Yang pertama hanya menggambar fungsi kuadrat pada diagram sebar, menggunakan fungsi R curve(); yang kedua menggunakan garis fungsi, yang mengharuskan pemesanan kumpulan data dalam meningkatkan nilai sqft sebelum model regresi dievaluasi, sedemikian rupa sehingga nilai yang sesuai yang dihasilkan juga akan keluar dalam urutan yang sama.

plot(br$sqft, br$price, xlab="Total square feet", 
     ylab="Sale price, $", col="grey")
#add the quadratic curve to the scatter plot:
curve(b1+b2*x^2, col="red", add=TRUE) 

Cara alternatif untuk menggambar kurva yang dipasang:

ordat <- br[order(br$sqft), ] #sorts the dataset after `sqft`
mod2 <- lm(price~I(sqft^2), data=ordat)
plot(br$sqft, br$price, 
     main="Dataset ordered after 'sqft' ", 
     xlab="Total square feet", 
     ylab="Sale price, $", col="grey")
lines(fitted(mod31)~ordat$sqft, col="red")

Model log-linear meregresi log variabel dependen pada ekspresi linear dari variabel independen (kecuali ditentukan lain, notasi log adalah singkatan dari logaritma alami, mengikuti konvensi yang biasa dalam ekonomi):

\[ \begin{align} \tag{5} Log(Y)=\beta_1+\beta_2*X+e\\ \end{align} \]

Salah satu alasan untuk menggunakan log variabel independen adalah untuk membuat distribusinya lebih dekat ke distribusi normal. Mari kita menggambar histogram harga dan log (harga) untuk membandingkannya

hist(br$price, col='grey')

hist(log(br$price), col='grey')

Kami tertarik, seperti sebelumnya, dalam perkiraan koefisien dan interpretasinya, dalam nilai harga yang sesuai, dan dalam efek marginal dari peningkatan sqft pada harga.

mod3 <- lm(log(price)~sqft, data=br)
mod3$coefficients
##  (Intercept)         sqft 
## 1.083860e+01 4.112689e-04

Koefisiennya adalah \(b_1= 10,84\) dan \(b_2= 0,00041\), menunjukkan bahwa peningkatan luas permukaan (sqft) apartemen sebesar satu unit (1 sqft) meningkatkan harga apartemen sebesar 0,041 persen. Dengan demikian, untuk harga rumah sebesar $100.000, kenaikan sqft sebesar 100 sqft akan meningkatkan harga sekitar 100∗0.041 persen, yang sama dengan $4112,7. Secara umum, efek marjinal dari peningkatan \(X\) pada \(Y\) dalam Persamaan 5 adalah

\[ \begin{align} \tag{6} {dy\over dx}=\beta_2 * Y \end{align} \]

dan elastisitasnya adalah

\[ \begin{align} \tag{7} e= {dy\over dx} {X\over Y}=\beta_2 * X \end{align} \]

Baris kode berikutnya menunjukkan cara menggambar kurva nilai yang dipasang dari model log-linear dan cara menghitung efek marginal dan elastisitas untuk harga median dalam set data. Nilai yang dipasang di sini dihitung menggunakan rumus

\[ \begin{align} \tag{8} \hat{Y}= e^{b_1+b_2*X} \end{align} \]

ordat <- br[order(br$sqft), ] #order the dataset
mod4 <- lm(log(price)~sqft, data=ordat)
plot(br$sqft, br$price, col="grey")
lines(exp(fitted(mod4))~ordat$sqft, 
      col="blue", main="Log-linear Model")

Penjelasan: Dari grafik dapat dilihat perbandingannya bahwa grafik logaritma (garis biru) lebih sesuai dengan data-data yang ada dibandingkan grafik regresi sederhana (garis hitam) hanya pas dengan beberapa data. Begitu data menyebar lebih luas, outliernya semakin banyak di grafik regresi sederhana. Sedangkan pada grafik logaritma, outliernya akan lebih sedikit karena bentuknya lebih mengikuti penyebaran data.

Dengan kata lain, dengan transformasi menggunakan logaritma, data yang awalnya tidak berdistribusi normal menjadi mendekati distribusi normal. Jadi kita bisa meminimalkan pelanggaran asumsi normalitas dan asumsi klasik regresi.

pricex<- median(br$price)
sqftx <- (log(pricex)-coef(mod4)[[1]])/coef(mod4)[[2]]
(DyDx <- pricex*coef(mod4)[[2]])
## [1] 53.46495
(elasticity <- sqftx*coef(mod4)[[2]])
## [1] 0.9366934

R memungkinkan kita untuk menghitung jumlah yang sama untuk beberapa pasangan (sqft, harga) pada satu waktu, seperti yang ditunjukkan dalam urutan berikut:

b1 <- coef(mod4)[[1]]
b2 <- coef(mod4)[[2]]
#pick a few values for sqft:
sqftx <- c(2000, 3000, 4000) 
#estimate prices for those and add one more:
pricex <- c(100000, exp(b1+b2*sqftx)) 
#re-calculate sqft for all prices:
sqftx <- (log(pricex)-b1)/b2 
#calculate and print elasticities:
(elasticities <- b2*sqftx) 
## [1] 0.6743291 0.8225377 1.2338066 1.6450754

5 Variabel Indikator

Indikator atau variabel biner menandai keberadaan atau tidak adanya beberapa atribut unit observasional, seperti jenis kelamin atau ras jika unit observasional adalah individu, atau lokasi jika unit observasional adalah rumah. Dalam kumpulan data utown, variabel utown adalah 1 jika rumah dekat dengan universitas dan 0 sebaliknya. Berikut adalah model regresi linier sederhana yang melibatkan variabel utown:

\[ \begin{align} \tag{9} price_i= \beta_1+\beta_2*utwon_i \end{align} \]

Koefisien variabel seperti itu dalam model linier sederhana sama dengan perbedaan antara harga rata-rata dari dua kategori; koefisien penyadapan model dalam Persamaan 9 sama dengan harga rata-rata rumah yang tidak dekat dengan universitas. Mari kita hitung terlebih dahulu harga rata-rata untuk setiap kategori, yang ditandai dalam urutan kode berikut price0bar dan price1bar:’:

data(utown)
price0bar <- mean(utown$price[which(utown$utown==0)])
price1bar <- mean(utown$price[which(utown$utown==1)])

Hasilnya adalah: \(\bar{price}=\) 277.2416012 dekat dengan universitas, dan \(\bar{price}=\) 215.7324948bagi mereka yang tidak tutup. Saya sekarang menunjukkan bahwa hasil yang sama menghasilkan koefisien model regresi dalam Persamaan 9 :

mod4 <- lm(price~utown, data=utown)
b1 <- coef(mod4)[[1]] 
b2 <- coef(mod4)[[2]]
b1
## [1] 215.7325
b2
## [1] 61.50911

Hasilnya adalah: \(\bar{price}=b_1=\) 215.7324948 untuk rumah non-universitas, dan \(\bar{price}=b_1+b_2=\) 277.2416012 untuk rumah universitas.

6 Monte Carlo Simulasi

Simulasi Monte Carlo menghasilkan nilai acak untuk variabel dependen ketika koefisien regresi dan distribusi istilah acak diberikan. Contoh berikut berusaha untuk menentukan distribusi variabel independen dalam model pengeluaran makanan dalam Persamaan 2,

N <- 40
x1 <- 10
x2 <- 20
b1 <- 100
b2 <- 10
mu <- 0
sig2e <- 2500
sde <- sqrt(sig2e)
yhat1 <- b1+b2*x1
yhat2 <- b1+b2*x2
curve(dnorm(x, mean=yhat1, sd=sde), 0, 500, col="blue")
curve(dnorm(x, yhat2, sde), 0,500, add=TRUE, col="red")
abline(v=yhat1, col="blue", lty=2)
abline(v=yhat2, col="red", lty=2)
legend("topright", legend=c("f(y|x=10)", 
                            "f(y|x=20)"), lty=1,
       col=c("blue", "red"))

Selanjutnya, kita menghitung varians \(b_2\) dan memplot fungsi kepadatan yang sesuai.

\[ \begin{align} \tag{10} var(b_2)={\sigma^2 \over \sum(x_i−\bar{x})} \end{align} \]

x <- c(rep(x1, N/2), rep(x2,N/2))
xbar <- mean(x)
sumx2 <- sum((x-xbar)^2)
varb2 <- sig2e/sumx2
sdb2 <- sqrt(varb2)
leftlim <- b2-3*sdb2
rightlim <- b2+3*sdb2
curve(dnorm(x, mean=b2, sd=sdb2), leftlim, rightlim)
abline(v=b2, lty=2)

Sekarang, dengan nilai yang sama dari $b_1 $ , $b_2 $ , dan simpangan baku kesalahan, kita dapat menghasilkan serangkaian nilai untuk $Y $ , regresi \(Y\) pada \(X\) , dan menghitung nilai perkiraan untuk koefisien $b_2 $ dan kesalahan standarnya.

set.seed(12345)
y <- b1+b2*x+rnorm(N, mean=0, sd=sde)
mod6 <- lm(y~x)
b1hat <- coef(mod6)[[1]]
b2hat <- coef(mod6)[[2]]
mod6summary <- summary(mod6) #the summary contains the standard errors
seb2hat <- coef(mod6summary)[2,2]

Hasilnya adalah \(b_2=11,64\) dan \(s_e(b_2)=1,64\). Kekuatan simulasi Monte Carlo adalah, bagaimanapun, kemungkinan mengulangi estimasi parameter regresi untuk sejumlah besar sampel yang dihasilkan secara otomatis. Dengan demikian, kita dapat memperoleh sejumlah besar nilai untuk parameter, katakanlah $b_2 $ , dan kemudian menentukan karakteristik pengambilan sampelnya. Misalnya, jika nilai rata-rata ini mendekati nilai yang diasumsikan awalnya \(b_2= 10\), kami menyimpulkan bahwa estimator kami (metode memperkirakan parameter) tidak bias.

Kita akan menggunakan waktu ini nilai $X $ dalam kumpulan data makanan, dan menghasilkan $ $Y menggunakan model linear dengan $b_1 = 100 $ dan \(b_2 = 10.\)

data("food")
N <- 40
sde <- 50
x <- food$income
nrsim <- 1000
b1 <- 100
b2 <- 10
vb2 <- numeric(nrsim) #stores the estimates of b2
for (i in 1:nrsim){
  set.seed(12345+10*i)
  y <- b1+b2*x+rnorm(N, mean=0, sd=sde)
  mod7 <- lm(y~x)
  vb2[i] <- coef(mod7)[[2]]
}
mb2 <- mean(vb2)
seb2 <- sd(vb2)

Rata-rata dan simpangan baku dari perkiraan 40 nilai \(b_2\) masing-masing adalah, 9,974985 dan 1,152632. Gambar bellow menunjukkan simulasi distribusi $b_2 $ dan yang teoritis.

plot(density(vb2))
curve(dnorm(x, mb2, seb2), col="red", add=TRUE)
legend("topright", legend=c("true", "simulated"), 
       lty=1, col=c("red", "black"))

hist(vb2, prob=TRUE, ylim=c(0,.4))
curve(dnorm(x, mean=mb2, sd=seb2), col="red", add=TRUE)

rm(list=ls()) # Caution: this clears the Environment
LS0tDQp0aXRsZTogIkVjb25vbWV0cmljcyINCnN1YnRpdGxlOiAiU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uIg0KYXV0aG9yOiAiTmlraXRhIEluZHJpeWFuaSINCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGh0bWxfZG9jdW1lbnQ6IG51bGwNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IHNhbmRzdG9uZQ0KICAgIGNzczogc3R5bGUuY3NzDQogICAgaGlnaGxpZ2h0OiBtb25vY2hyb21lDQotLS0NCg0KYGBge3IgbWUsIGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnMzAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJsb2dvLnBuZyIpDQpgYGANCg0KRW1haWwgJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7Jm5ic3A7OiAgbmlraXRhaW5kcml5bmlAZ21haWwuY29tIDxicj4NCkluc3RhZ3JhbSAmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDs6IGh0dHBzOi8vd3d3Lmluc3RhZ3JhbS5jb20vbmlraXRhaW5kcml5bmkgPGJyPg0KUlB1YnMgICZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOzogaHR0cHM6Ly9ycHVicy5jb20vbmlraXRhaW5kcml5YW5pLyA8YnI+DQpBZGRyZXNzICAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgOiBBUkEgQ2VudGVyLCBNYXRhbmEgVW5pdmVyc2l0eSBUb3dlciA8YnI+DQombmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyZuYnNwOyBKbC4gQ0JEIEJhcmF0IEthdiwgUlQuMSwgQ3VydWcgU2FuZ2VyZW5nLCBLZWxhcGEgRHVhLCBUYW5nZXJhbmcsIEJhbnRlbiAxNTgxMC4NCg0KPGJyPg0KDQoqKioNCg0KIyB7LX0NCg0KDQojIEludHJvZHVjdGlvbg0KDQpTZXBlcnRpIHlhbmcgdGVsYWggc2F5YSBzZWJ1dGthbiBzZWJlbHVtbnlhLCAqUmVncmVzc2lvbiBNb2RlbHMqIGRpZ3VuYWthbiB1bnR1ayBtZW5nZ2FtYmFya2FuIGh1YnVuZ2FuIGFudGFyYSB2YXJpYWJlbCBkZW5nYW4gbWVtYXNhbmcgZ2FyaXMga2UgZGF0YSB5YW5nIGRpYW1hdGkuIE1vZGVsIHJlZ3Jlc2kgbGluZWFyIG1lbmdndW5ha2FuIGdhcmlzIGx1cnVzLCBzZW1lbnRhcmEgbW9kZWwgcmVncmVzaSBsb2dpc3RpayBkYW4gbm9ubGluZWFyIG1lbmdndW5ha2FuIGdhcmlzIG1lbGVuZ2t1bmcuIFJlZ3Jlc2kgbWVtdW5na2lua2FuIEFuZGEgdW50dWsgbWVtcGVya2lyYWthbiBiYWdhaW1hbmEgdmFyaWFiZWwgZGVwZW5kZW4gYmVydWJhaCBzYWF0IHZhcmlhYmVsIGluZGVwZW5kZW4gYmVydWJhaC4NCg0KRGkgYmFnaWFuIGluaSBraXRhIGFrYW4gbWVtZm9rdXNrYW4gY2FyYSBtZW5nZ3VuYWthbiAqKlNpbXBsZSBMaW5lYXIgUmVncmVzc2lvbiAoU0xSKSoqIHVudHVrIG1lbXBlcmtpcmFrYW4gaHVidW5nYW4gYW50YXJhIGR1YSB2YXJpYWJlbCBrdWFudGl0YXRpZi4gS2l0YSBqdWdhIGRhcGF0IG1lbmdndW5ha2FuIHJlZ3Jlc2kgbGluaWVyIHNlZGVyaGFuYSB1bnR1ayBtZW5nZXRhaHVpOg0KDQoqIFNlYmVyYXBhIGt1YXQgaHVidW5nYW4gYW50YXJhIGR1YSB2YXJpYWJlbC4NCiogTmlsYWkgdmFyaWFiZWwgZGVwZW5kZW4gcGFkYSBuaWxhaSB0ZXJ0ZW50dSBkYXJpIHZhcmlhYmVsIGluZGVwZW5kZW4gDQoNCjxicj4NCg0KDQpgYGB7ciBjb3JyZWxhdGlvbiwgZWNobz1GQUxTRSxmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICcxMDAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJjb3JyZWxhdGlvbi53ZWJwIikNCmBgYA0KDQo8YnI+DQoNCg0KKipDb250b2g6KioNCg0KQXN1bXNpa2FuIEFuZGEgYWRhbGFoIHBlbmVsaXRpIHNvc2lhbCB5YW5nIHRlcnRhcmlrIHBhZGEgaHVidW5nYW4gYW50YXJhIHBlbmRhcGF0YW4gZGFuIGtlYmFoYWdpYWFuLiBBbmRhIG1lbnN1cnZlaSA1MDAgb3JhbmcgeWFuZyBwZW5kYXBhdGFubnlhIGJlcmtpc2FyIGRhcmkgJDE1ayBoaW5nZ2EgJDc1ayBkYW4gbWVtaW50YSBtZXJla2EgdW50dWsgbWVtYmVyaSBwZXJpbmdrYXQga2ViYWhhZ2lhYW4gbWVyZWthIGRhbGFtIHNrYWxhIDEgaGluZ2dhIDEwLg0KVmFyaWFiZWwgaW5kZXBlbmRlbiAocGVuZGFwYXRhbikgZGFuIHZhcmlhYmVsIGRlcGVuZGVuIChrZWJhaGFnaWFhbikgQW5kYSBiZXJkdWEga3VhbnRpdGF0aWYsIHNlaGluZ2dhIEFuZGEgZGFwYXQgbWVsYWt1a2FuIGFuYWxpc2lzIHJlZ3Jlc2kgdW50dWsgbWVsaWhhdCBhcGFrYWggYWRhIGh1YnVuZ2FuIGxpbmllciBkaSBhbnRhcmEgbWVyZWthLg0KDQoqKioNCg0KIyBNb2RlbCBVbXVtDQoNCk1vZGVsIHJlZ3Jlc2kgbGluZWFyIHNlZGVyaGFuYSBtZW5nYXN1bXNpa2FuIGJhaHdhIGh1YnVuZ2FuIGxpbmllciBhZGEgYW50YXJhIGVrc3Bla3Rhc2kgYmVyc3lhcmF0IGRhcmkgZHVhIHZhcmlhYmVsIGt1YW50aXRhdGlmOiANCg0KYGBge3IgbGluZWFyLCBlY2hvPUZBTFNFLGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzgwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygibGluZWFyLndlYnAiKQ0KYGBgDQoNCkRpbWFuYSwNCg0KKiAkWSQgZGlhbmdnYXAgc2ViYWdhaSB2YXJpYWJlbCBwcmVkaWt0b3IsIHBlbmplbGFzYW4sIGF0YXUgZGVwZW5kZW4uDQoqICRYICQgZGlhbmdnYXAgc2ViYWdhaSByZXNwb25zLCBoYXNpbCwgYXRhdSB2YXJpYWJlbCBpbmRlcGVuZGVuLg0KKiAkYmV0YV8xJCBhZGFsYWggcGFyYW1ldGVyIHBlbnlhZGFwYW4gYXRhdSBrb2VmaXNpZW4NCiogJGJldGFfMiQgYWRhbGFoIHBhcmFtZXRlciBrZW1pcmluZ2FuIGF0YXUga29lZmlzaWVuDQoqICRoYXR7WX0kIGFkYWxhaCBwZXJraXJhYW4gbmlsYWkgJFkkIHlhbmcgZGliZXJpa2FuICRYJA0KKiAkYl8xJCBkYW4gJGJfMiQgYWRhbGFoIG5pbGFpIHBlcmtpcmFhbiBrb2VmaXNpZW4gDQoNCioqKg0KDQojIFJlZ3Jlc2kgTGluZWFyIFNlZGVyaGFuYSBkaSBSDQoNCkRhdGEgdW50dWsgY29udG9oIGluaSBkaXNpbXBhbiBkYWxhbSBwYWtldCBSICdQb0VkYXRhJy4gUGVydGFtYSwgQW5kYSBoYXJ1cyBtZW5naW5zdGFsIHBha2V0ICJQb0VkYXRhIiwga2V0aWsgYmFyaXMgc2tyaXAgYmVyaWt1dCBkaSBqZW5kZWxhIEtvbnNvbCBSU3R1ZGlvOg0KDQoNCmBgYHtyIGxpYnJhcnksIGV2YWw9RkFMU0V9DQojaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKSAgICAgICAgICAgICAgICAgICAgICAgICAjIGlmIG5vdCBhbHJlYWR5IGluc3RhbGxlZA0KbGlicmFyeShkZXZ0b29scykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgdGhlIGxpYnJhcnkNCiNpbnN0YWxsX2dpdCgiaHR0cHM6Ly9naXRodWIuY29tL2Njb2xvbmVzY3UvUG9FZGF0YSIpICMgaW5zdGFsbCBgUG9FZGF0YWANCmBgYA0KDQpLZW11ZGlhbiwgcGVydGltYmFuZ2thbiBrdW1wdWxhbiBkYXRhOg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoUG9FZGF0YSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBsb2FkIHRoZSBsaWJyYXJ5IFBvRWRhdGENCmxpYnJhcnkoRFQpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1c2UgZm9yIGRhdGF0YWJsZSBmdWN0aW9uIA0KZGF0YSgiZm9vZCIsIHBhY2thZ2U9IlBvRWRhdGEiKQ0KZGF0YXRhYmxlKGZvb2QpDQpgYGANCg0KU2VsYWx1IG1lcnVwYWthbiBpZGUgeWFuZyBiYWlrIHVudHVrIHNlY2FyYSB2aXN1YWwgbWVtZXJpa3NhIGRhdGEgZGFsYW0gZGlhZ3JhbSBzZWJhciwgeWFuZyBkYXBhdCBkaWJ1YXQgbWVuZ2d1bmFrYW4gZnVuZ3NpIGBwbG90KClgLiBBbmdrYSBkaSBiYXdhaCBpbmkgYWRhbGFoIGRpYWdyYW0gcGVuZ2VsdWFyYW4gbWFrYW5hbiB5YW5nIHRlcnNlYmFyIHBhZGEgcGVuZGFwYXRhbiwgbWVudW5qdWtrYW4gYmFod2EgYWRhIGh1YnVuZ2FuIHBvc2l0aWYgYW50YXJhIHBlbmRhcGF0YW4gZGFuIHBlbmdlbHVhcmFuIG1ha2FuYW4uDQoNCg0KYGBge3J9DQpwbG90KGZvb2QkaW5jb21lLCBmb29kJGZvb2RfZXhwLCANCiAgICAgeWxpbT1jKDAsIG1heChmb29kJGZvb2RfZXhwKSksDQogICAgIHhsaW09YygwLCBtYXgoZm9vZCRpbmNvbWUpKSwNCiAgICAgeGxhYj0id2Vla2x5IGluY29tZSBpbiAkMTAwIiwgDQogICAgIHlsYWI9IndlZWtseSBmb29kIGV4cGVuZGl0dXJlIGluICQiLCANCiAgICAgdHlwZSA9ICJwIikNCmBgYA0KDQpbQWJvdXQgJFJeMiRdKGh0dHBzOi8vd3d3LmludmVzdG9wZWRpYS5jb20vdGVybXMvci9yLXNxdWFyZWQuYXNwKQ0KDQoNCioqKg0KDQojIyBNZW1wZXJraXJha2FuIFJlZ3Jlc2kgTGluZWFyDQoNClVudHVrIGRhdGEgcGVuZ2VsdWFyYW4gbWFrYW5hbiwgbW9kZWwgcmVncmVzaSBha2FuDQoNCg0KJCQNClxiZWdpbnthbGlnbn0NClx0YWd7MX0NClkmPVxiZXRhXzErXGJldGFfMiAqWCtlIFxcDQpmb29kX3tleHB9Jj1cYmV0YV8xK1xiZXRhXzIqaW5jb21lK2UNClxlbmR7YWxpZ259DQokJA0KDQpmdW5nc2kgUiB1bnR1ayBtZW1wZXJraXJha2FuIG1vZGVsIHJlZ3Jlc2kgbGluZWFyIGFkYWxhaGBsbSh5fngsIGRhdGEpYCB5YW5nLCBkaWd1bmFrYW4gaGFueWEgZGVuZ2FuIHNlbmRpcmlueWEgdGlkYWsgbWVudW5qdWtrYW4gb3V0cHV0IGFwYSBwdW47IEJlcmd1bmEgdW50dWsgbWVtYmVyaSBuYW1hIG1vZGVsLCBzZXBlcnRpIGBtb2QxYCwgbGFsdSBtZW51bmp1a2thbiBoYXNpbG55YSBtZW5nZ3VuYWthbiBgc3VtbWFyeShtb2QxKWAuIA0KDQpgYGB7cn0NCm1vZDEgPC0gbG0oZm9vZF9leHAgfiBpbmNvbWUsIGRhdGEgPSBmb29kKSAgICAgICAgICAgIyBsaW5lYXIgbW9kZWwNCnNtb2QxPC0gc3VtbWFyeShtb2QxKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBnZXQgc3VtbWFyeSANCnNtb2QxDQpgYGANCg0KSmlrYSBBbmRhIGhhbnlhIHRlcnRhcmlrIHBhZGEgYmViZXJhcGEgaGFzaWwgcmVncmVzaSwgc2VwZXJ0aSBrb2VmaXNpZW4geWFuZyBkaXBlcmtpcmFrYW4sIEFuZGEgZGFwYXQgbWVuZ2FtYmlsbnlhIG1lbmdndW5ha2FuIGZ1bmdzaSB0ZXJ0ZW50dSwgc2VwZXJ0aSBmdW5nc2kgYGNvZWYoKWAuDQoNCmBgYHtyfQ0KYjEgPC0gY29lZihtb2QxKVtbMV1dICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBlc3RpbWF0ZWQgdmFsdWUgb2YgIM6yMQ0KYjIgPC0gY29lZihtb2QxKVtbMl1dICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBlc3RpbWF0ZWQgdmFsdWUgb2YgIM6yMg0KYjENCmIyDQpgYGANCg0KRGFyaSBoYXNpbG55YSwga2l0YSBkYXBhdCBtZW51bGlzIHJlZ3Jlc2kgbGluaWVyIGthbWkgeWFuZyBtZW1wZXJraXJha2FuIHNlYmFnYWk6DQoNCiQkDQpcYmVnaW57YWxpZ259DQpcdGFnezJ9DQpcaGF0e1l9Jj1iXzErYl8yKlggXFwNClxoYXR7Zm9vZF97ZXhwfX0mPTgzLjQxNisxMC4yMDk2NCppbmNvbWUNClxlbmR7YWxpZ259DQokJA0KDQpQYXJhbWV0ZXIgcGVueWFkYXBhbiwgJFxiZXRhXzEkICwgYmlhc2FueWEgc2VkaWtpdCBwZW50aW5nIGRhbGFtIG1vZGVsIGVrb25vbWV0cmlrOyBrYW1pIHNlYmFnaWFuIGJlc2FyIHRlcnRhcmlrIHBhZGEgcGFyYW1ldGVyIGtlbWlyaW5nYW4sICRcYmV0YV8yJC4gIFBlcmtpcmFhbiBuaWxhaSAkXGJldGFfMiQgbWVudW5qdWtrYW4gYmFod2EgcGVuZ2VsdWFyYW4gbWFrYW5hbiB1bnR1ayBrZWx1YXJnYSByYXRhLXJhdGEgbWVuaW5na2F0IHNlYmVzYXIgMTAsMjA5NjQzIGtldGlrYSBwZW5kYXBhdGFuIGtlbHVhcmdhIG1lbmluZ2thdCBzZWJlc2FyIDEgdW5pdCwgeWFuZyBkYWxhbSBoYWwgaW5pIGFkYWxhaCAkMTAwLiBGdW5nc2kgUiBgYWJsaW5lKClgIG1lbmFtYmFoa2FuIGdhcmlzIGByZWdmcmVzc2lvbmAnIGtlIGRpYWdyYW0geWFuZyBzZWJlbHVtbnlhIGRpcGxvdCB1bnR1ayBtZW55ZWJhcmthbiBkaSBiYXdhaCBpbmk6DQoNCmBgYHtyfQ0KcGxvdChmb29kJGluY29tZSwgZm9vZCRmb29kX2V4cCwgDQogICAgIHhsYWI9IndlZWtseSBpbmNvbWUgaW4gJDEwMCIsIA0KICAgICB5bGFiPSJ3ZWVrbHkgZm9vZCBleHBlbmRpdHVyZSBpbiAkIiwgDQogICAgIHR5cGUgPSAicCIpDQphYmxpbmUoYjEsYjIpDQpgYGANCg0KQmFnYWltYW5hIHNlc2VvcmFuZyBkYXBhdCBtZW5nYW1iaWwgYmVyYmFnYWkgaGFzaWwgcmVncmVzaT8gVW50dWsgbWVuZ2FtYmlsIGhhc2lsIHRlcnRlbnR1LCBBbmRhIGN1a3VwIG1lcnVqdWtueWEgZGVuZ2FuIG5hbWEgb2JqZWssIGRpaWt1dGkgZGVuZ2FuIHRhbmRhIFwkIGRhbiBuYW1hIGhhc2lsIHlhbmcgaW5naW4gQW5kYSBhbWJpbC4gTWlzYWxueWEsIGppa2Ega2l0YSBpbmdpbiB2ZWt0b3Iga29lZmlzaWVuIGRhcmkgJ21vZDEnLCBrYW1pIG1lbnllYnV0bnlhIHNlYmFnYWkgYG1vZDFcJGNvZWZmaWNpZW50c2AgZGFuIGBzbW9kMVwkY29lZmZpY2llbnRzYDoNCg0KYGBge3J9DQptb2QxJGNvZWZmaWNpZW50cw0KYGBgDQoNCmBgYHtyfQ0Kc21vZDEkY29lZmZpY2llbnRzDQpgYGANCg0KYGBge3IsZXZhbD1GfQ0KbmFtZXMobW9kMSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGZvciBtb3JlDQpuYW1lcyhzbW9kMSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZm9yIG1vcmUNCmBgYA0KDQoNClNlcGVydGkgeWFuZyB0ZWxhaCBraXRhIGxpaGF0IHNlYmVsdW1ueWEsIG5hbXVuLCBiZWJlcmFwYSBoYXNpbCBpbmkgZGFwYXQgZGlhbWJpbCBtZW5nZ3VuYWthbiBmdW5nc2kgdGVydGVudHUsIHNlcGVydGkgYGNvZWYobW9kMSksIHJlc2lkKG1vZDEpLCBmaXR0ZWQobW9kMSksIGFuZCB2Y292KG1vZDEpYC4NCg0KKioqDQoNCiMjIFByZWRpa3NpIGRlbmdhbiBNb2RlbCBTTFINCg0KUGVya2lyYWFuIHBhcmFtZXRlciByZWdyZXNpLCAkYl8xJCBkYW4gJGJfMiQgbWVtdW5na2lua2FuIGthbWkgdW50dWsgbWVtcHJlZGlrc2kgcGVuZ2VsdWFyYW4gbWFrYW5hbiB5YW5nIGRpaGFyYXBrYW4gdW50dWsgcGVuZGFwYXRhbiB0ZXJ0ZW50dS4gWWFuZyBwZXJsdSBraXRhIGxha3VrYW4gYWRhbGFoIG1lbnlhbWJ1bmdrYW4gbmlsYWkgcGFyYW1ldGVyIHlhbmcgZGlwZXJraXJha2FuIGRhbiBwZW5kYXBhdGFuIHlhbmcgZGliZXJpa2FuIGtlIGRhbGFtIHBlcnNhbWFhbiBzZXBlcnRpIFBlcnNhbWFhbiAyLiBNaXNhbG55YSwgbmlsYWkgeWFuZyBkaWhhcmFwa2FuIGRhcmkgYGZvb2RfZXhwYCB1bnR1ayBwZW5kYXBhdGFuIFwkMjAwMCBkaWhpdHVuZyBkYWxhbSBQZXJzYW1hYW4gMyAuIChJbmdhdGxhaCB1bnR1ayBtZW1iYWdpIHBlbmRhcGF0YW4gc2ViZXNhciAxMDAsIGthcmVuYSBkYXRhIHVudHVrIHBlbmRhcGF0YW4gdmFyaWFiZWwgYWRhbGFoIGRhbGFtIHJhdHVzYW4gZG9sYXIuKQ0KDQoNCiQkDQpcYmVnaW57YWxpZ259DQpcdGFnezN9DQpcaGF0e2Zvb2Rfe2V4cH19Jj04My40MTYrMTAuMjA5NjQqMjBcXA0KJiA9ICQgMjg3LjYwODg2MQ0KXGVuZHthbGlnbn0NCiQkDQoNCiMjIFByZWRpa3NpIGRlbmdhbiBNb2RlbCBTTFINCg0KUiwgYmFnYWltYW5hcHVuLCBtZWxha3VrYW4gcGVyaGl0dW5nYW4gaW5pIHVudHVrIGtpdGEgZGVuZ2FuIGZ1bmdzaW55YSB5YW5nIGRpc2VidXQgYHByZWRpY3QoKWAuIE1hcmkga2l0YSBtZW1wZXJsdWFzIHNlZGlraXQgY29udG9oIHVudHVrIGxlYmloIGRhcmkgc2F0dSBwZW5kYXBhdGFuIHlhbmcga2l0YSBwcmVkaWtzaSBwZW5nZWx1YXJhbiBtYWthbmFuLCBrYXRha2FubGFoIHBlbmRhcGF0YW4gPSBcJDIwMDAsIFwkMjUwMCwgZGFuIFwkMjcwMC4gRnVuZ3NpIGBwcmVkaWN0KClgIGRhbGFtIFIgbWVuZ2hhcnVza2FuIG5pbGFpIGJhcnUgZGFyaSB2YXJpYWJlbCBpbmRlcGVuZGVuIGRpYXR1ciBkaSBiYXdhaCBmb3JtdWxpciB0ZXJ0ZW50dSwgeWFuZyBkaXNlYnV0IGJpbmdrYWkgZGF0YS4gQmFoa2FuIGtldGlrYSBraXRhIGhhbnlhIGluZ2luIG1lbXByZWRpa3NpIHVudHVrIHNhdHUgcGVuZGFwYXRhbiwga2l0YSBtZW1idXR1aGthbiBzdHJ1a3R1ciBiaW5na2FpIGRhdGEgeWFuZyBzYW1hLiBEYWxhbSBSLCBzYXR1IHNldCBhbmdrYSBkaXNhdHVrYW4gbWVuZ2d1bmFrYW4gc3RydWt0dXIgYGMoKWAuIFVydXRhbiBiZXJpa3V0IG1lbnVuanVra2FuIGNvbnRvaCBpbmkuDQoNCmBgYHtyfQ0KbW9kMSA8LSBsbShmb29kX2V4cH5pbmNvbWUsIGRhdGE9Zm9vZCkNCm5ld3ggPC0gZGF0YS5mcmFtZShpbmNvbWUgPSBjKDIwLCAyNSwgMjcpKQ0KeWhhdCA8LSBwcmVkaWN0KG1vZDEsIG5ld3gpDQp5aGF0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcHJpbnRzIHRoZSByZXN1bHQNCmBgYA0KDQoqKioNCg0KIyMgTWVuaWxhaSBLb2VmaXNpZW4gUmVncmVzaQ0KDQpLb2VmaXNpZW4gcmVncmVzaSAkYl8xJCBkYW4gJGJfMiQgYWRhbGFoIHZhcmlhYmVsIGFjYWsga2FyZW5hIHRlcmdhbnR1bmcgcGFkYSBzYW1wZWwuIERhbGFtIGhhbCBpbmksIGthbWkgbWVuZ3VsYW5naSBzYW1wZWwgdW50dWsgbWVuaWxhaSBrb2VmaXNpZW4gcmVncmVzaS4gTWFyaSBraXRhIG1lbWJhbmd1biBzZWp1bWxhaCBzdWJzYW1wbGUgYWNhayBkYXJpIGRhdGEgbWFrYW5hbiBkYW4gbWVuZ2hpdHVuZyB1bGFuZyAkYl8xICQgZGFuICRiXzIgJCAuIFN1YnNhbXBsZSBhY2FrIGRhcGF0IGRpYmFuZ3VuIG1lbmdndW5ha2FuIGZ1bmdzaSBgc2FtcGxlKClgLCBrYXJlbmEgY29udG9oIGJlcmlrdXQgaGFueWEgbWVuZ2dhbWJhcmthbiB1bnR1ayAkYl8yJC4NCg0KYGBge3J9DQpOIDwtIG5yb3coZm9vZCkgICAjIHJldHVybnMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgaW4gdGhlIGRhdGFzZXQNCkMgPC0gNTAgICAgICAgICAgICMgZGVzaXJlZCBudW1iZXIgb2Ygc3Vic2FtcGxlcw0KUyA8LSAzOCAgICAgICAgICAgIyBkZXNpcmVkIHNhbXBsZSBzaXplDQoNCnN1bWIyIDwtIDANCmZvciAoaSBpbiAxOkMpeyAgICMgYSBsb29wIG92ZXIgdGhlIG51bWJlciBvZiBzdWJzYW1wbGVzDQogIHNldC5zZWVkKDMqaSkgICAjIGEgZGlmZmVyZW50IHNlZWQgZm9yIGVhY2ggc3Vic2FtcGxlICANCiAgc3Vic2FtcGxlIDwtIGZvb2Rbc2FtcGxlKDE6Tiwgc2l6ZT1TLCByZXBsYWNlPVRSVUUpLCBdDQogIG1vZDIgPC0gbG0oZm9vZF9leHB+aW5jb21lLCBkYXRhPXN1YnNhbXBsZSkNCiAgI3N1bSBiMiBmb3IgYWxsIHN1YnNhbXBsZXM6DQogIHN1bWIyIDwtIHN1bWIyICsgY29lZihtb2QyKVtbMl1dDQp9DQpwcmludChzdW1iMi9DLCBkaWdpdHMgPSAzKQ0KYGBgDQoNCkhhc2lsbnlhLCAkYl8yPTksODgkLCBhZGFsYWggcmF0YS1yYXRhIDUwIGVzdGltYXNpICRiXzIkLg0KDQoqKioNCg0KIyMgKFR1Z2FzIDEpIFBlcmtpcmFhbiBWYXIgZGFuIENvdg0KDQpCYW55YWsgYXBsaWthc2kgbWVtZXJsdWthbiBwZXJraXJhYW4gdmFyaWFucyBkYW4ga292YXJpYW5zIGtvZWZpc2llbiByZWdyZXNpLiBSIG1lbnlpbXBhbm55YSBkYWxhbSBtYXRyaWtzIGB2Y292KClgOg0KDQpgYGB7cn0NCih2YXJiMSA8LSB2Y292KG1vZDEpWzEsIDFdKQ0KDQpgYGANCg0KVmFyaWFuc2kgZGFyaSBiMSBuaWxhaW55YSBzYW5nYXQgYmVzYXIuIEl0dSBiZXJhcnRpIG5pbGFpIG55YXRhIGRhcmkgYjEgbWVueWltcGFuZyBqYXVoIGRhcmkgcmF0YS1yYXRhIChla3NwZWt0YXNpKSBiMSBkYWxhbSByZW50YW5nIDE4ODQuNDQyIGRpbWFuYSBuaWxhaSByYXRhLXJhdGFueWEgc2ViYWdhaSBwdXNhdCByZW50YW5nLg0KDQpgYGB7cn0NCih2YXJiMiA8LSB2Y292KG1vZDEpWzIsIDJdKQ0KYGBgDQoNClZhcmlhbnNpIGRhcmkgYjIgbmlsYWlueWEga2VjaWwgeWFuZyBiZXJhcnRpIG5pbGFpIG55YXRhIGRhcmkgYjIgaGFueWEgc2VkaWtpdCBtZW55aW1wYW5nIGRhcmkgbmlsYWkgcmF0YS1yYXRhIChla3NwZWt0YXNpKSBiMiBkYWxhbSByZW50YW5nIDQuMzgxNzUyIGRpbWFuYSBuaWxhaSByYXRhLXJhdGFueWEgc2ViYWdhaSBwdXNhdCByZW50YW5nDQoNCmBgYHtyfQ0KKGNvdmIxYjIgPC0gdmNvdihtb2QxKVsxLDJdKQ0KYGBgDQoNCktvdmFyaWFuc2kgYmVybmlsYWkgbmVnYXRpZiBiZXJhcnRpIHZhcmlhYmVsIGIxIGRhbiBiMiBtZW1pbGlraSBodWJ1bmdhbiB5YW5nIGJlcmxhd2FuYW4sIGRpbWFuYSBzYWF0IHNhbGFoIHNhdHUgdmFyaWFiZWwgbWVuaW5na2F0LCB2YXJpYWJlbCBsYWlubnlhIGFrYW4gbWVudXJ1bi4NCg0KRGVuZ2FuIGthdGEgbGFpbiwgYXBhYmlsYSBrb3ZhcmlhbnNpbnlhIHBvc2l0aWYgYmVyYXJ0aSBodWJ1bmdhbm55YSBzZWFyYWggYXRhdSByZWxhc2lueWEgcG9zaXRpZi4NCg0KKioqDQoNCiMgSHVidW5nYW4gTm9uLUxpbmVhcg0KDQpLYWRhbmcta2FkYW5nIGRpYWdyYW0gcGxvdCBzZWJhciBhdGF1IGJlYmVyYXBhIHBlcnRpbWJhbmdhbiB0ZW9yaXRpcyBtZW51bmp1a2thbiBodWJ1bmdhbiBub24tbGluZWFyLiBIdWJ1bmdhbiBub24tbGluZWFyIHlhbmcgcGFsaW5nIHBvcHVsZXIgbWVsaWJhdGthbiBsb2dhcml0bWEgZGFyaSB2YXJpYWJlbCBkZXBlbmRlbiBhdGF1IGluZGVwZW5kZW4gZGFuIGZ1bmdzaSBwb2xpbm9taWFsLiBNb2RlbCBrdWFkcmF0IG1lbWJ1dHVoa2FuIGt1YWRyYXQgZGFyaSB2YXJpYWJlbCBpbmRlcGVuZGVuLg0KDQoNCiQkDQpcYmVnaW57YWxpZ259DQpcdGFnezR9DQpZPVxiZXRhXzErXGJldGFfMipYXjIrZVxcDQpcZW5ke2FsaWdufQ0KJCQNCkRhbGFtIFIsIHZhcmlhYmVsIGluZGVwZW5kZW4geWFuZyBtZWxpYmF0a2FuIG9wZXJhdG9yIG1hdGVtYXRpa2EgZGFwYXQgZGltYXN1a2thbiBkYWxhbSBwZXJzYW1hYW4gcmVncmVzaSBkZW5nYW4gZnVuZ3NpIGBJKClgLiBDb250b2ggYmVyaWt1dCBtZW5nZ3VuYWthbiBkYXRhc2V0IGJyIGRhcmkgcGFrZXQgYFBvRWRhdGFgLCB5YW5nIG1lbmNha3VwIGhhcmdhIGp1YWwgZGFuIGF0cmlidXQgMTA4MCBydW1haCBkaSBCYXRvbiBSb3VnZSwgTEEuIGhhcmdhIGFkYWxhaCBoYXJnYSBqdWFsIGRhbGFtIGRvbGFyLCBkYW4gc3FmdCBhZGFsYWggYXJlYSBwZXJtdWthYW4gZGkga2FraSBwZXJzZWdpLg0KDQpgYGB7cn0NCmRhdGEoYnIpDQptb2QyIDwtIGxtKHByaWNlfkkoc3FmdF4yKSwgZGF0YT1icikNCmIxIDwtIGNvZWYobW9kMilbWzFdXQ0KYjIgPC0gY29lZihtb2QyKVtbMl1dDQpzcWZ0eD1jKDIwMDAsIDQwMDAsIDYwMDApICAgICAgICAgICAgIyBnaXZlbiB2YWx1ZXMgZm9yIHNxZnQNCnByaWNleD1iMStiMipzcWZ0eF4yICAgICAgICAgICAgICAgICAjIHByaWNlcyBjb3JyZXNwb25kaW5nIHRvIGdpdmVuIHNxZnQgDQpEcHJpY2VEc3FmdCA8LSAyKmIyKnNxZnR4ICAgICAgICAgICAgIyBtYXJnaW5hbCBlZmZlY3Qgb2Ygc3FmdCBvbiBwcmljZQ0KZWxhc3RpY2l0eT1EcHJpY2VEc3FmdCpzcWZ0eC9wcmljZXggDQpiMTsgYjI7IERwcmljZURzcWZ0OyBlbGFzdGljaXR5ICAgICAgIyBwcmludHMgcmVzdWx0cw0KYGBgDQoNCkthbWkgc2VrYXJhbmcgaW5naW4gbWVuZ2dhbWJhciBkaWFncmFtIHNlYmFyIGRhbiBtZWxpaGF0IGJhZ2FpbWFuYSBmdW5nc2kga3VhZHJhdCBzZXN1YWkgZGVuZ2FuIGRhdGEuIFBvdG9uZ2FuIGtvZGUgYmVyaWt1dG55YSBtZW55ZWRpYWthbiBkdWEgYWx0ZXJuYXRpZiB1bnR1ayBtZW1iYW5ndW4gZ3JhZmlrIHNlcGVydGkgaXR1LiBZYW5nIHBlcnRhbWEgaGFueWEgbWVuZ2dhbWJhciBmdW5nc2kga3VhZHJhdCBwYWRhIGRpYWdyYW0gc2ViYXIsIG1lbmdndW5ha2FuIGZ1bmdzaSBSIGBjdXJ2ZSgpYDsgeWFuZyBrZWR1YSBtZW5nZ3VuYWthbiBnYXJpcyBmdW5nc2ksIHlhbmcgbWVuZ2hhcnVza2FuIHBlbWVzYW5hbiBrdW1wdWxhbiBkYXRhIGRhbGFtIG1lbmluZ2thdGthbiBuaWxhaSBgc3FmdGAgc2ViZWx1bSBtb2RlbCByZWdyZXNpIGRpZXZhbHVhc2ksIHNlZGVtaWtpYW4gcnVwYSBzZWhpbmdnYSBuaWxhaSB5YW5nIHNlc3VhaSB5YW5nIGRpaGFzaWxrYW4ganVnYSBha2FuIGtlbHVhciBkYWxhbSB1cnV0YW4geWFuZyBzYW1hLg0KDQpgYGB7cn0NCnBsb3QoYnIkc3FmdCwgYnIkcHJpY2UsIHhsYWI9IlRvdGFsIHNxdWFyZSBmZWV0IiwgDQogICAgIHlsYWI9IlNhbGUgcHJpY2UsICQiLCBjb2w9ImdyZXkiKQ0KI2FkZCB0aGUgcXVhZHJhdGljIGN1cnZlIHRvIHRoZSBzY2F0dGVyIHBsb3Q6DQpjdXJ2ZShiMStiMip4XjIsIGNvbD0icmVkIiwgYWRkPVRSVUUpIA0KYGBgDQoNCkNhcmEgYWx0ZXJuYXRpZiB1bnR1ayBtZW5nZ2FtYmFyIGt1cnZhIHlhbmcgZGlwYXNhbmc6DQoNCmBgYHtyLCBldmFsPUZ9DQpvcmRhdCA8LSBicltvcmRlcihiciRzcWZ0KSwgXSAjc29ydHMgdGhlIGRhdGFzZXQgYWZ0ZXIgYHNxZnRgDQptb2QyIDwtIGxtKHByaWNlfkkoc3FmdF4yKSwgZGF0YT1vcmRhdCkNCnBsb3QoYnIkc3FmdCwgYnIkcHJpY2UsIA0KICAgICBtYWluPSJEYXRhc2V0IG9yZGVyZWQgYWZ0ZXIgJ3NxZnQnICIsIA0KICAgICB4bGFiPSJUb3RhbCBzcXVhcmUgZmVldCIsIA0KICAgICB5bGFiPSJTYWxlIHByaWNlLCAkIiwgY29sPSJncmV5IikNCmxpbmVzKGZpdHRlZChtb2QzMSl+b3JkYXQkc3FmdCwgY29sPSJyZWQiKQ0KYGBgDQoNCk1vZGVsIGxvZy1saW5lYXIgbWVyZWdyZXNpIGxvZyB2YXJpYWJlbCBkZXBlbmRlbiBwYWRhIGVrc3ByZXNpIGxpbmVhciBkYXJpIHZhcmlhYmVsIGluZGVwZW5kZW4gKGtlY3VhbGkgZGl0ZW50dWthbiBsYWluLCBub3Rhc2kgbG9nIGFkYWxhaCBzaW5na2F0YW4gZGFyaSBsb2dhcml0bWEgYWxhbWksIG1lbmdpa3V0aSBrb252ZW5zaSB5YW5nIGJpYXNhIGRhbGFtIGVrb25vbWkpOg0KDQokJA0KXGJlZ2lue2FsaWdufQ0KXHRhZ3s1fQ0KTG9nKFkpPVxiZXRhXzErXGJldGFfMipYK2VcXA0KXGVuZHthbGlnbn0NCiQkDQoNClNhbGFoIHNhdHUgYWxhc2FuIHVudHVrIG1lbmdndW5ha2FuIGxvZyB2YXJpYWJlbCBpbmRlcGVuZGVuIGFkYWxhaCB1bnR1ayBtZW1idWF0IGRpc3RyaWJ1c2lueWEgbGViaWggZGVrYXQga2UgZGlzdHJpYnVzaSBub3JtYWwuIE1hcmkga2l0YSBtZW5nZ2FtYmFyIGhpc3RvZ3JhbSBoYXJnYSBkYW4gbG9nIChoYXJnYSkgdW50dWsgbWVtYmFuZGluZ2thbm55YQ0KDQpgYGB7cn0NCmhpc3QoYnIkcHJpY2UsIGNvbD0nZ3JleScpDQpoaXN0KGxvZyhiciRwcmljZSksIGNvbD0nZ3JleScpDQpgYGANCg0KS2FtaSB0ZXJ0YXJpaywgc2VwZXJ0aSBzZWJlbHVtbnlhLCBkYWxhbSBwZXJraXJhYW4ga29lZmlzaWVuIGRhbiBpbnRlcnByZXRhc2lueWEsIGRhbGFtIG5pbGFpIGhhcmdhIHlhbmcgc2VzdWFpLCBkYW4gZGFsYW0gZWZlayBtYXJnaW5hbCBkYXJpIHBlbmluZ2thdGFuIHNxZnQgcGFkYSBoYXJnYS4NCg0KYGBge3J9DQptb2QzIDwtIGxtKGxvZyhwcmljZSl+c3FmdCwgZGF0YT1icikNCm1vZDMkY29lZmZpY2llbnRzDQpgYGANCg0KDQpLb2VmaXNpZW5ueWEgYWRhbGFoICRiXzE9IDEwLDg0JCBkYW4gJGJfMj0gMCwwMDA0MSQsIG1lbnVuanVra2FuIGJhaHdhIHBlbmluZ2thdGFuIGx1YXMgcGVybXVrYWFuIChzcWZ0KSBhcGFydGVtZW4gc2ViZXNhciBzYXR1IHVuaXQgKDEgc3FmdCkgbWVuaW5na2F0a2FuIGhhcmdhIGFwYXJ0ZW1lbiBzZWJlc2FyIDAsMDQxIHBlcnNlbi4gRGVuZ2FuIGRlbWlraWFuLCB1bnR1ayBoYXJnYSBydW1haCBzZWJlc2FyIFwkMTAwLjAwMCwga2VuYWlrYW4gc3FmdCBzZWJlc2FyIDEwMCBzcWZ0IGFrYW4gbWVuaW5na2F0a2FuIGhhcmdhIHNla2l0YXIgMTAw4oiXMC4wNDEgcGVyc2VuLCB5YW5nIHNhbWEgZGVuZ2FuIFwkNDExMiw3LiBTZWNhcmEgdW11bSwgZWZlayBtYXJqaW5hbCBkYXJpIHBlbmluZ2thdGFuICRYJCBwYWRhICRZJCBkYWxhbSBQZXJzYW1hYW4gNSBhZGFsYWgNCg0KDQokJA0KXGJlZ2lue2FsaWdufQ0KXHRhZ3s2fQ0Ke2R5XG92ZXIgZHh9PVxiZXRhXzIgKiBZDQpcZW5ke2FsaWdufQ0KJCQNCg0KZGFuIGVsYXN0aXNpdGFzbnlhIGFkYWxhaA0KDQoNCiQkDQpcYmVnaW57YWxpZ259DQpcdGFnezd9DQplPSB7ZHlcb3ZlciBkeH0ge1hcb3ZlciBZfT1cYmV0YV8yICogWA0KXGVuZHthbGlnbn0NCiQkDQoNCkJhcmlzIGtvZGUgYmVyaWt1dG55YSBtZW51bmp1a2thbiBjYXJhIG1lbmdnYW1iYXIga3VydmEgbmlsYWkgeWFuZyBkaXBhc2FuZyBkYXJpIG1vZGVsIGxvZy1saW5lYXIgZGFuIGNhcmEgbWVuZ2hpdHVuZyBlZmVrIG1hcmdpbmFsIGRhbiBlbGFzdGlzaXRhcyB1bnR1ayBoYXJnYSBtZWRpYW4gZGFsYW0gc2V0IGRhdGEuIE5pbGFpIHlhbmcgZGlwYXNhbmcgZGkgc2luaSBkaWhpdHVuZyBtZW5nZ3VuYWthbiBydW11cw0KDQokJA0KXGJlZ2lue2FsaWdufQ0KXHRhZ3s4fQ0KXGhhdHtZfT0gZV57Yl8xK2JfMipYfQ0KXGVuZHthbGlnbn0NCiQkDQoNCmBgYHtyfQ0Kb3JkYXQgPC0gYnJbb3JkZXIoYnIkc3FmdCksIF0gI29yZGVyIHRoZSBkYXRhc2V0DQptb2Q0IDwtIGxtKGxvZyhwcmljZSl+c3FmdCwgZGF0YT1vcmRhdCkNCnBsb3QoYnIkc3FmdCwgYnIkcHJpY2UsIGNvbD0iZ3JleSIpDQpsaW5lcyhleHAoZml0dGVkKG1vZDQpKX5vcmRhdCRzcWZ0LCANCiAgICAgIGNvbD0iYmx1ZSIsIG1haW49IkxvZy1saW5lYXIgTW9kZWwiKQ0KYGBgDQoNClBlbmplbGFzYW46DQpEYXJpIGdyYWZpayBkYXBhdCBkaWxpaGF0IHBlcmJhbmRpbmdhbm55YSBiYWh3YSBncmFmaWsgbG9nYXJpdG1hIChnYXJpcyBiaXJ1KSBsZWJpaCBzZXN1YWkgZGVuZ2FuIGRhdGEtZGF0YSB5YW5nIGFkYSBkaWJhbmRpbmdrYW4gZ3JhZmlrIHJlZ3Jlc2kgc2VkZXJoYW5hIChnYXJpcyBoaXRhbSkgaGFueWEgcGFzIGRlbmdhbiBiZWJlcmFwYSBkYXRhLiBCZWdpdHUgZGF0YSBtZW55ZWJhciBsZWJpaCBsdWFzLCBvdXRsaWVybnlhIHNlbWFraW4gYmFueWFrIGRpIGdyYWZpayByZWdyZXNpIHNlZGVyaGFuYS4gU2VkYW5na2FuIHBhZGEgZ3JhZmlrIGxvZ2FyaXRtYSwgb3V0bGllcm55YSBha2FuIGxlYmloIHNlZGlraXQga2FyZW5hIGJlbnR1a255YSBsZWJpaCBtZW5naWt1dGkgcGVueWViYXJhbiBkYXRhLg0KDQpEZW5nYW4ga2F0YSBsYWluLCBkZW5nYW4gdHJhbnNmb3JtYXNpIG1lbmdndW5ha2FuIGxvZ2FyaXRtYSwgZGF0YSB5YW5nIGF3YWxueWEgdGlkYWsgYmVyZGlzdHJpYnVzaSBub3JtYWwgbWVuamFkaSBtZW5kZWthdGkgZGlzdHJpYnVzaSBub3JtYWwuIEphZGkga2l0YSBiaXNhIG1lbWluaW1hbGthbiBwZWxhbmdnYXJhbiBhc3Vtc2kgbm9ybWFsaXRhcyBkYW4gYXN1bXNpIGtsYXNpayByZWdyZXNpLg0KDQpgYGB7cn0NCnByaWNleDwtIG1lZGlhbihiciRwcmljZSkNCnNxZnR4IDwtIChsb2cocHJpY2V4KS1jb2VmKG1vZDQpW1sxXV0pL2NvZWYobW9kNClbWzJdXQ0KKER5RHggPC0gcHJpY2V4KmNvZWYobW9kNClbWzJdXSkNCmBgYA0KDQpgYGB7cn0NCihlbGFzdGljaXR5IDwtIHNxZnR4KmNvZWYobW9kNClbWzJdXSkNCmBgYA0KDQpSIG1lbXVuZ2tpbmthbiBraXRhIHVudHVrIG1lbmdoaXR1bmcganVtbGFoIHlhbmcgc2FtYSB1bnR1ayBiZWJlcmFwYSBwYXNhbmdhbiAoc3FmdCwgaGFyZ2EpIHBhZGEgc2F0dSB3YWt0dSwgc2VwZXJ0aSB5YW5nIGRpdHVuanVra2FuIGRhbGFtIHVydXRhbiBiZXJpa3V0Og0KDQoNCmBgYHtyfQ0KYjEgPC0gY29lZihtb2Q0KVtbMV1dDQpiMiA8LSBjb2VmKG1vZDQpW1syXV0NCiNwaWNrIGEgZmV3IHZhbHVlcyBmb3Igc3FmdDoNCnNxZnR4IDwtIGMoMjAwMCwgMzAwMCwgNDAwMCkgDQojZXN0aW1hdGUgcHJpY2VzIGZvciB0aG9zZSBhbmQgYWRkIG9uZSBtb3JlOg0KcHJpY2V4IDwtIGMoMTAwMDAwLCBleHAoYjErYjIqc3FmdHgpKSANCiNyZS1jYWxjdWxhdGUgc3FmdCBmb3IgYWxsIHByaWNlczoNCnNxZnR4IDwtIChsb2cocHJpY2V4KS1iMSkvYjIgDQojY2FsY3VsYXRlIGFuZCBwcmludCBlbGFzdGljaXRpZXM6DQooZWxhc3RpY2l0aWVzIDwtIGIyKnNxZnR4KSANCmBgYA0KKioqDQoNCiMgVmFyaWFiZWwgSW5kaWthdG9yDQoNCkluZGlrYXRvciBhdGF1IHZhcmlhYmVsIGJpbmVyIG1lbmFuZGFpIGtlYmVyYWRhYW4gYXRhdSB0aWRhayBhZGFueWEgYmViZXJhcGEgYXRyaWJ1dCB1bml0IG9ic2VydmFzaW9uYWwsIHNlcGVydGkgamVuaXMga2VsYW1pbiBhdGF1IHJhcyBqaWthIHVuaXQgb2JzZXJ2YXNpb25hbCBhZGFsYWggaW5kaXZpZHUsIGF0YXUgbG9rYXNpIGppa2EgdW5pdCBvYnNlcnZhc2lvbmFsIGFkYWxhaCBydW1haC4gRGFsYW0ga3VtcHVsYW4gZGF0YSBgdXRvd25gLCB2YXJpYWJlbCBgdXRvd25gIGFkYWxhaCAxIGppa2EgcnVtYWggZGVrYXQgZGVuZ2FuIHVuaXZlcnNpdGFzIGRhbiAwIHNlYmFsaWtueWEuIEJlcmlrdXQgYWRhbGFoIG1vZGVsIHJlZ3Jlc2kgbGluaWVyIHNlZGVyaGFuYSB5YW5nIG1lbGliYXRrYW4gdmFyaWFiZWwgdWB0b3duYDoNCg0KJCQNClxiZWdpbnthbGlnbn0NClx0YWd7OX0NCnByaWNlX2k9IFxiZXRhXzErXGJldGFfMip1dHdvbl9pDQpcZW5ke2FsaWdufQ0KJCQNCg0KS29lZmlzaWVuIHZhcmlhYmVsIHNlcGVydGkgaXR1IGRhbGFtIG1vZGVsIGxpbmllciBzZWRlcmhhbmEgc2FtYSBkZW5nYW4gcGVyYmVkYWFuIGFudGFyYSBoYXJnYSByYXRhLXJhdGEgZGFyaSBkdWEga2F0ZWdvcmk7IGtvZWZpc2llbiBwZW55YWRhcGFuIG1vZGVsIGRhbGFtIFBlcnNhbWFhbiA5IHNhbWEgZGVuZ2FuIGhhcmdhIHJhdGEtcmF0YSBydW1haCB5YW5nIHRpZGFrIGRla2F0IGRlbmdhbiB1bml2ZXJzaXRhcy4gTWFyaSBraXRhIGhpdHVuZyB0ZXJsZWJpaCBkYWh1bHUgaGFyZ2EgcmF0YS1yYXRhIHVudHVrIHNldGlhcCBrYXRlZ29yaSwgeWFuZyBkaXRhbmRhaSBkYWxhbSB1cnV0YW4ga29kZSBiZXJpa3V0IGBwcmljZTBiYXJgIGRhbiBgcHJpY2UxYmFyYDonOg0KDQoNCmBgYHtyfQ0KZGF0YSh1dG93bikNCnByaWNlMGJhciA8LSBtZWFuKHV0b3duJHByaWNlW3doaWNoKHV0b3duJHV0b3duPT0wKV0pDQpwcmljZTFiYXIgPC0gbWVhbih1dG93biRwcmljZVt3aGljaCh1dG93biR1dG93bj09MSldKQ0KYGBgDQoNCkhhc2lsbnlhIGFkYWxhaDogJFxiYXJ7cHJpY2V9PSQgYHIgcHJpY2UxYmFyYCBkZWthdCBkZW5nYW4gdW5pdmVyc2l0YXMsIGRhbiAkXGJhcntwcmljZX09JCBgciBwcmljZTBiYXJgYmFnaSBtZXJla2EgeWFuZyB0aWRhayB0dXR1cC4gU2F5YSBzZWthcmFuZyBtZW51bmp1a2thbiBiYWh3YSBoYXNpbCB5YW5nIHNhbWEgbWVuZ2hhc2lsa2FuIGtvZWZpc2llbiBtb2RlbCByZWdyZXNpIGRhbGFtIFBlcnNhbWFhbiA5IDoNCg0KYGBge3J9DQptb2Q0IDwtIGxtKHByaWNlfnV0b3duLCBkYXRhPXV0b3duKQ0KYjEgPC0gY29lZihtb2Q0KVtbMV1dIA0KYjIgPC0gY29lZihtb2Q0KVtbMl1dDQpiMQ0KYjINCmBgYA0KDQpIYXNpbG55YSBhZGFsYWg6ICRcYmFye3ByaWNlfT1iXzE9JCBgciBiMWAgdW50dWsgcnVtYWggbm9uLXVuaXZlcnNpdGFzLCBkYW4gJFxiYXJ7cHJpY2V9PWJfMStiXzI9JCBgciBiMStiMmAgdW50dWsgcnVtYWggdW5pdmVyc2l0YXMuDQoNCg0KIyBNb250ZSBDYXJsbyBTaW11bGFzaQ0KDQpTaW11bGFzaSBNb250ZSBDYXJsbyBtZW5naGFzaWxrYW4gbmlsYWkgYWNhayB1bnR1ayB2YXJpYWJlbCBkZXBlbmRlbiBrZXRpa2Ega29lZmlzaWVuIHJlZ3Jlc2kgZGFuIGRpc3RyaWJ1c2kgaXN0aWxhaCBhY2FrIGRpYmVyaWthbi4gQ29udG9oIGJlcmlrdXQgYmVydXNhaGEgdW50dWsgbWVuZW50dWthbiBkaXN0cmlidXNpIHZhcmlhYmVsIGluZGVwZW5kZW4gZGFsYW0gbW9kZWwgcGVuZ2VsdWFyYW4gbWFrYW5hbiBkYWxhbSBQZXJzYW1hYW4gMiwNCg0KYGBge3J9DQpOIDwtIDQwDQp4MSA8LSAxMA0KeDIgPC0gMjANCmIxIDwtIDEwMA0KYjIgPC0gMTANCm11IDwtIDANCnNpZzJlIDwtIDI1MDANCnNkZSA8LSBzcXJ0KHNpZzJlKQ0KeWhhdDEgPC0gYjErYjIqeDENCnloYXQyIDwtIGIxK2IyKngyDQpjdXJ2ZShkbm9ybSh4LCBtZWFuPXloYXQxLCBzZD1zZGUpLCAwLCA1MDAsIGNvbD0iYmx1ZSIpDQpjdXJ2ZShkbm9ybSh4LCB5aGF0Miwgc2RlKSwgMCw1MDAsIGFkZD1UUlVFLCBjb2w9InJlZCIpDQphYmxpbmUodj15aGF0MSwgY29sPSJibHVlIiwgbHR5PTIpDQphYmxpbmUodj15aGF0MiwgY29sPSJyZWQiLCBsdHk9MikNCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQ9YygiZih5fHg9MTApIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgImYoeXx4PTIwKSIpLCBsdHk9MSwNCiAgICAgICBjb2w9YygiYmx1ZSIsICJyZWQiKSkNCmBgYA0KDQpTZWxhbmp1dG55YSwga2l0YSBtZW5naGl0dW5nIHZhcmlhbnMgJGJfMiQgZGFuIG1lbXBsb3QgZnVuZ3NpIGtlcGFkYXRhbiB5YW5nIHNlc3VhaS4NCg0KJCQNClxiZWdpbnthbGlnbn0NClx0YWd7MTB9DQp2YXIoYl8yKT17XHNpZ21hXjIgXG92ZXIgXHN1bSh4X2niiJJcYmFye3h9KX0NClxlbmR7YWxpZ259DQokJA0KDQpgYGB7cn0NCnggPC0gYyhyZXAoeDEsIE4vMiksIHJlcCh4MixOLzIpKQ0KeGJhciA8LSBtZWFuKHgpDQpzdW14MiA8LSBzdW0oKHgteGJhcileMikNCnZhcmIyIDwtIHNpZzJlL3N1bXgyDQpzZGIyIDwtIHNxcnQodmFyYjIpDQpsZWZ0bGltIDwtIGIyLTMqc2RiMg0KcmlnaHRsaW0gPC0gYjIrMypzZGIyDQpjdXJ2ZShkbm9ybSh4LCBtZWFuPWIyLCBzZD1zZGIyKSwgbGVmdGxpbSwgcmlnaHRsaW0pDQphYmxpbmUodj1iMiwgbHR5PTIpDQpgYGANCg0KU2VrYXJhbmcsIGRlbmdhbiBuaWxhaSB5YW5nIHNhbWEgZGFyaSAkYl8xICQgLCAkYl8yICQgLCBkYW4gc2ltcGFuZ2FuIGJha3Uga2VzYWxhaGFuLCBraXRhIGRhcGF0IG1lbmdoYXNpbGthbiBzZXJhbmdrYWlhbiBuaWxhaSB1bnR1ayAkWSAkICwgcmVncmVzaSAkWSQgcGFkYSAkWCQgLCBkYW4gbWVuZ2hpdHVuZyBuaWxhaSBwZXJraXJhYW4gdW50dWsga29lZmlzaWVuICRiXzIgJCBkYW4ga2VzYWxhaGFuIHN0YW5kYXJueWEuDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzNDUpDQp5IDwtIGIxK2IyKngrcm5vcm0oTiwgbWVhbj0wLCBzZD1zZGUpDQptb2Q2IDwtIGxtKHl+eCkNCmIxaGF0IDwtIGNvZWYobW9kNilbWzFdXQ0KYjJoYXQgPC0gY29lZihtb2Q2KVtbMl1dDQptb2Q2c3VtbWFyeSA8LSBzdW1tYXJ5KG1vZDYpICN0aGUgc3VtbWFyeSBjb250YWlucyB0aGUgc3RhbmRhcmQgZXJyb3JzDQpzZWIyaGF0IDwtIGNvZWYobW9kNnN1bW1hcnkpWzIsMl0NCmBgYA0KDQpIYXNpbG55YSBhZGFsYWggJGJfMj0xMSw2NCQgZGFuICRzX2UoYl8yKT0xLDY0JC4gS2VrdWF0YW4gc2ltdWxhc2kgTW9udGUgQ2FybG8gYWRhbGFoLCBiYWdhaW1hbmFwdW4sIGtlbXVuZ2tpbmFuIG1lbmd1bGFuZ2kgZXN0aW1hc2kgcGFyYW1ldGVyIHJlZ3Jlc2kgdW50dWsgc2VqdW1sYWggYmVzYXIgc2FtcGVsIHlhbmcgZGloYXNpbGthbiBzZWNhcmEgb3RvbWF0aXMuIERlbmdhbiBkZW1pa2lhbiwga2l0YSBkYXBhdCBtZW1wZXJvbGVoIHNlanVtbGFoIGJlc2FyIG5pbGFpIHVudHVrIHBhcmFtZXRlciwga2F0YWthbmxhaCAkYl8yICQgLCBkYW4ga2VtdWRpYW4gbWVuZW50dWthbiBrYXJha3RlcmlzdGlrIHBlbmdhbWJpbGFuIHNhbXBlbG55YS4gTWlzYWxueWEsIGppa2EgbmlsYWkgcmF0YS1yYXRhIGluaSBtZW5kZWthdGkgbmlsYWkgeWFuZyBkaWFzdW1zaWthbiBhd2FsbnlhICRiXzI9IDEwJCwga2FtaSBtZW55aW1wdWxrYW4gYmFod2EgZXN0aW1hdG9yIGthbWkgKG1ldG9kZSBtZW1wZXJraXJha2FuIHBhcmFtZXRlcikgdGlkYWsgYmlhcy4NCg0KS2l0YSBha2FuIG1lbmdndW5ha2FuIHdha3R1IGluaSBuaWxhaSAkWCAkIGRhbGFtIGt1bXB1bGFuIGRhdGEgbWFrYW5hbiwgZGFuIG1lbmdoYXNpbGthbiAkICRZIG1lbmdndW5ha2FuIG1vZGVsIGxpbmVhciBkZW5nYW4gJGJfMSA9IDEwMCAkIGRhbiAkYl8yID0gMTAuJA0KDQpgYGB7cn0NCmRhdGEoImZvb2QiKQ0KTiA8LSA0MA0Kc2RlIDwtIDUwDQp4IDwtIGZvb2QkaW5jb21lDQpucnNpbSA8LSAxMDAwDQpiMSA8LSAxMDANCmIyIDwtIDEwDQp2YjIgPC0gbnVtZXJpYyhucnNpbSkgI3N0b3JlcyB0aGUgZXN0aW1hdGVzIG9mIGIyDQpmb3IgKGkgaW4gMTpucnNpbSl7DQogIHNldC5zZWVkKDEyMzQ1KzEwKmkpDQogIHkgPC0gYjErYjIqeCtybm9ybShOLCBtZWFuPTAsIHNkPXNkZSkNCiAgbW9kNyA8LSBsbSh5fngpDQogIHZiMltpXSA8LSBjb2VmKG1vZDcpW1syXV0NCn0NCm1iMiA8LSBtZWFuKHZiMikNCnNlYjIgPC0gc2QodmIyKQ0KYGBgDQoNClJhdGEtcmF0YSBkYW4gc2ltcGFuZ2FuIGJha3UgZGFyaSBwZXJraXJhYW4gNDAgbmlsYWkgJGJfMiQgbWFzaW5nLW1hc2luZyBhZGFsYWgsIDksOTc0OTg1IGRhbiAxLDE1MjYzMi4gR2FtYmFyIGJlbGxvdyBtZW51bmp1a2thbiBzaW11bGFzaSBkaXN0cmlidXNpICRiXzIgJCBkYW4geWFuZyB0ZW9yaXRpcy4gDQoNCg0KYGBge3J9DQpwbG90KGRlbnNpdHkodmIyKSkNCmN1cnZlKGRub3JtKHgsIG1iMiwgc2ViMiksIGNvbD0icmVkIiwgYWRkPVRSVUUpDQpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kPWMoInRydWUiLCAic2ltdWxhdGVkIiksIA0KICAgICAgIGx0eT0xLCBjb2w9YygicmVkIiwgImJsYWNrIikpDQpoaXN0KHZiMiwgcHJvYj1UUlVFLCB5bGltPWMoMCwuNCkpDQpjdXJ2ZShkbm9ybSh4LCBtZWFuPW1iMiwgc2Q9c2ViMiksIGNvbD0icmVkIiwgYWRkPVRSVUUpDQpgYGANCg0KYGBge3J9DQpybShsaXN0PWxzKCkpICMgQ2F1dGlvbjogdGhpcyBjbGVhcnMgdGhlIEVudmlyb25tZW50DQpgYGANCg0K