Perbandingan Model Regresi Logistik Biner dan Multinomial

Profile

1. Pendahuluan

Analisis regresi logistik merupakan salah satu metode statistik yang digunakan untuk memodelkan hubungan antara satu variabel dependen (respon) dengan satu atau lebih variabel independen (prediktor), terutama ketika variabel dependen bersifat kategorikal.

Dalam tugas ini, akan dilakukan dua jenis analisis:

a. Regresi Logistik Biner (Binary Logistic Regression)

→ digunakan ketika variabel respon hanya memiliki dua kategori (misalnya Ya atau Tidak).

b. Regresi Logistik Multinomial (Multinomial Logistic Regression)

→ digunakan ketika variabel respon memiliki lebih dari dua kategori (misalnya Rendah, Sedang, Tinggi).

2. Tujuan Analisis

Tujuan dari tugas ini adalah membandingkan dua jenis model regresi logistik — yaitu Binary Logistic Regression dan Multinomial Logistic Regression — untuk melihat model mana yang lebih akurat dalam memprediksi variabel target berdasarkan data yang tersedia.

3. Konsep Dasar

a. Binary Logistic Regression

Model ini digunakan jika variabel dependen \((Y)\) hanya memiliki dua kategori (misalnya: “Success = 1” dan “Tidak Success = 0”). Rumus umumnya: \[ \text{logit}(p) = \ln\left(\frac{p}{1 - p}\right) = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \dots + \beta_k X_k \] Hasilnya berupa probabilitas keberhasilan (p) antara 0 dan 1.

b. Multinomial Logistic Regression

Model ini digunakan jika variabel dependen memiliki lebih dari dua kategori (misalnya: “Satisfaction = Low, Medium, High”). Rumusnya: \[ P(Y = k) = \frac{e^{\mathbf{X} \boldsymbol{\beta}_k}}{\sum_{j=1}^{K} e^{\mathbf{X} \boldsymbol{\beta}_j}} \] Hasilnya memberikan probabilitas untuk setiap kategori (bukan hanya dua).

4. Langkah-langkah Analisi

Langkah 1: Import dan Cek Data

## Rows: 200
## Columns: 6
## $ X            <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17…
## $ Advertising  <dbl> 12.189438, 24.707628, 15.224423, 27.075435, 28.511682, 6.…
## $ Salespeople  <dbl> 15.96815, 34.05897, 25.03414, 22.87574, 20.06433, 32.0061…
## $ Satisfaction <dbl> 9.874489, 2.233607, 9.147786, 6.186717, 4.559040, 5.04822…
## $ Competition  <dbl> 3.135067, 7.178413, 3.032366, 3.866451, 2.565854, 8.21286…
## $ Success      <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, …
##        X           Advertising      Salespeople     Satisfaction  
##  Min.   :  1.00   Min.   : 5.016   Min.   :10.16   Min.   :1.004  
##  1st Qu.: 50.75   1st Qu.:11.803   1st Qu.:15.89   1st Qu.:3.462  
##  Median :100.50   Median :17.052   Median :21.73   Median :5.555  
##  Mean   :100.50   Mean   :17.660   Mean   :22.23   Mean   :5.520  
##  3rd Qu.:150.25   3rd Qu.:23.334   3rd Qu.:28.55   3rd Qu.:7.813  
##  Max.   :200.00   Max.   :29.857   Max.   :34.99   Max.   :9.970  
##   Competition       Success    
##  Min.   :1.011   Min.   :0.00  
##  1st Qu.:3.217   1st Qu.:1.00  
##  Median :5.429   Median :1.00  
##  Mean   :5.442   Mean   :0.92  
##  3rd Qu.:7.797   3rd Qu.:1.00  
##  Max.   :9.954   Max.   :1.00
##            X  Advertising  Salespeople Satisfaction  Competition      Success 
##            0            0            0            0            0            0

Penjelasan:

  • tidyverse digunakan untuk manipulasi data dan visualisasi.
  • tidymodels, caret, dan yardstick digunakan untuk model dan evaluasi.
  • nnet digunakan untuk multinomial logistic regression.

Langkah 2: Menentukan Target dan Split Data

Misalnya, pada dataset ini:

  • Variabel Binary -> Success (0 = gagal, 1 = berhasil)
  • Variabel Multinomial -> Statisfaction_cat (kategori kepuasan)
## [1] "X"            "Advertising"  "Salespeople"  "Satisfaction" "Competition" 
## [6] "Success"

Penjelasan:

Kita membagi data menjadi \(70\)% training dan \(30\)% testing. strata digunakan agar proporsi kategori target tetap seimbang.

Langkah 3: Binary Logistik Regression

## 
## Call:
## glm(formula = Success ~ Advertising + Salespeople + Satisfaction + 
##     Competition, family = binomial, data = train_bin)
## 
## Coefficients:
##              Estimate Std. Error z value Pr(>|z|)   
## (Intercept)  -6.47435    2.19941  -2.944  0.00324 **
## Advertising   0.18133    0.06590   2.751  0.00593 **
## Salespeople   0.25127    0.08277   3.036  0.00240 **
## Satisfaction  0.51994    0.16995   3.059  0.00222 **
## Competition  -0.18244    0.16077  -1.135  0.25646   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 86.548  on 139  degrees of freedom
## Residual deviance: 49.767  on 135  degrees of freedom
## AIC: 59.767
## 
## Number of Fisher Scoring iterations: 7
##       Predicted
## Actual  0  1
##      0  1  2
##      1  2 55
## [1] 0.9333333

Dimana:

a. Ringkasan Model (summary(model_bin))

Ini adalah hasil ringkasan model regresi logistik yang menunjukkan:

  • Koefisien setiap variabel (Advertising, Salespeople, Satisfaction, Competition)

Nilai koefisien menunjukkan pengaruh masing-masing variabel terhadap peluang keberhasilan (Success). - Koefisien positif → variabel meningkatkan peluang keberhasilan. - Koefisien negatif → variabel menurunkan peluang keberhasilan.

  • Nilai p-value untuk menguji signifikanasi masing-masing variabel.
    • p-value kecil (biasanya < 0.05) berarti variabel signifikan mempengaruhi Success
  • Intercept adalah baseline log-odds keberhasilan saat semua variabel prediktor bernilai nol.

b. Prediksi Probabilitas pred_bin

Model menghasilkan nilai antara 0 dan 1, yang artinya probabilitas prediksi keberhasilan untuk tiap data di test set.

Contoh:

Jika pred_bin[i] = \(0.8\) berarti model memprediksi data ke-i memiliki peluang \(80\)% untuk Success = \(1\).

C. Klasifikasi Hasil Prediksi (pred_bin_class)

Probabilitas tadi diubah ke kelas diskrit:

  • Jika > \(0.5\) -> prediksi Success = \(1\) (berhasil)
  • Jika \(\leq\) \(0.5\) -> prediksi Success = \(0\) (gagal)

d. Confusion Matrix (conf_mat_bin)

Misalkan hasilnya seperti ini: \[ \begin{array}{c|cc} \text{Actual} \backslash \text{Predicted} & 0 & 1 \\ \hline 0 & 40 & 10 \\ 1 & 5 & 45 \\ \end{array} \] Artinya:

  • 40 data yang sebenarnya 0 diprediksi benr 0 (True Negative)
  • 45 data yang sebenarnya 1 diprediksi bener 1 (True Positive)
  • 10 data yang sebenarnya 0 salah diprediksi 1 (False POsitive)
  • 5 data yang sebenarnya 1 salah diprediksi 0 (False Negative)

e. Akurasi (accuracy_bin)

Misal akurasi 0.85 -> artinya model memprediksi dengan benar \(85\)% dari semua data testing.

Langkah 4: Multinommial Logistik Regression

## [1] "X"                "Advertising"      "Salespeople"      "Satisfaction"    
## [5] "Competition"      "Success"          "Satisfaction_cat"
## # weights:  18 (10 variable)
## initial  value 151.608496 
## iter  10 value 141.823194
## final  value 141.706531 
## converged
## Call:
## nnet::multinom(formula = Satisfaction_cat ~ Advertising + Salespeople + 
##     Competition + Success, data = train_multi, maxit = 1000)
## 
## Coefficients:
##        (Intercept)  Advertising  Salespeople Competition SuccessYa
## Sedang  -2.6821879 -0.004474509  0.008989837  0.09721557  2.160575
## Tinggi   0.4796326 -0.076052863 -0.060283586  0.02227914  2.181477
## 
## Std. Errors:
##        (Intercept) Advertising Salespeople Competition SuccessYa
## Sedang    1.410719  0.03203124  0.03100914  0.08239920  1.145696
## Tinggi    1.204516  0.03253664  0.03180666  0.08521589  0.912896
## 
## Residual Deviance: 283.4131 
## AIC: 303.4131
##         Predicted
## Actual   Rendah Sedang Tinggi
##   Rendah      6      9      6
##   Sedang      6      8      6
##   Tinggi      4      6     11
## [1] 0.4032258

Dimana:

  • multinom() digunakan untuk data target lebih dari dua kategori.
  • Prediksi dikategorikan, lalu dibandingkan dengan nilai aktual untuk menghitung akurasi.

Langkah 5: Membandingkan Akurasi

accuracy_df <- data.frame(
  Model = c("Binary Logistic Regression", "Multinomial Logistic Regression"),
  Accuracy = c(accuracy_bin, accuracy_multi)
)
print(accuracy_df)
##                             Model  Accuracy
## 1      Binary Logistic Regression 0.9333333
## 2 Multinomial Logistic Regression 0.4032258

Dimana:

Tabel ini menampilkan perbandingan akurasi dua model. Model dengan nilai akurasi lebih tinggi -> lebih akurat.

Langkah 6: Visualisasi Perbandingan Akurasi

Dimana:

Grafik batang ini menunjukkan akurasi masing-masing model secara visual. Semakin tinggi batang, semakin akurat model tersebut.

Langkah 7: Visualisasi Distribusi Prediksi Binary

4. Interpretasi Hasil

  • Jika accuracy_bin > accuracy_multi -> Model Binary Logistik lebih baik.
  • Jika accuracy_multi > accuracy_bin -> Model Multinomial lebih baik.
  • Nilai akurasi mendekati \(1\) menunjukkan model memprediksi dengan sangat baik.
  • Selain akurasi, kamu juga bisa menilai dari confusion matrix untuk melihat kesalahan klasifikasi.
  • Model dengan akurasi lebih tinggi lebih mampu mengenali pola hubungan antara variabel prediktor (Advertising, Salespeople, Competition, dll.) dengan variabel target.
  • Jika Multinomial lebih akurat → berarti informasi kategori kepuasan pelanggan memberikan kontribusi lebih besar terhadap pemahaman karakteristik performa bisnis.
  • Jika Binary lebih akurat → berarti pemisahan sederhana antara “berhasil” dan “tidak berhasil” sudah cukup mewakili prediksi performa.

5. Kesimpulan

Berdasarkan analisis yang telah dilakukan menggunakan dua pendekatan regresi logistik, yaitu Binary Logistic Regression dan Multinomial Logistic Regression, dapat disimpulkan bahwa kedua model mampu memprediksi variabel target pada dataset dengan baik, namun tingkat akurasinya berbeda.

Model Binary Logistic Regression digunakan untuk memprediksi kategori Success (0 = tidak berhasil, 1 = berhasil). Sedangkan Multinomial Logistic Regression digunakan untuk memprediksi tingkat Satisfaction yang terdiri dari tiga level (Rendah, Sedang, Tinggi).

Refrensi

LS0tDQp0aXRsZTogIlBlcmJhbmRpbmdhbiBNb2RlbCBSZWdyZXNpIExvZ2lzdGlrIEJpbmVyIGRhbiBNdWx0aW5vbWlhbCINCg0KYXV0aG9yOiANCiAgICAtICJOYWJpbGEgQW5nZ2l0YSBQdXRyaSINCiAgICANCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246DQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbGliX2RpcjogbGlicw0KICAgIGRmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjc3M6ICJzdHlsZS9zdHlsZSBjc3MuY3NzIg0KLS0tDQo8aW1nIHNyYz0iaW1nL3Byb2ZpbGUuanBnIiBhbHQ9IlByb2ZpbGUiIGlkPSJsb2dvLXV0YW1hIiBzdHlsZT0id2lkdGg6MzAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ii8+DQoNCg0KIyAqKjEuIFBlbmRhaHVsdWFuKioNCkFuYWxpc2lzIHJlZ3Jlc2kgbG9naXN0aWsgbWVydXBha2FuIHNhbGFoIHNhdHUgbWV0b2RlIHN0YXRpc3RpayB5YW5nIGRpZ3VuYWthbiB1bnR1ayBtZW1vZGVsa2FuIGh1YnVuZ2FuIGFudGFyYSBzYXR1IHZhcmlhYmVsIGRlcGVuZGVuIChyZXNwb24pIGRlbmdhbiBzYXR1IGF0YXUgbGViaWggdmFyaWFiZWwgaW5kZXBlbmRlbiAocHJlZGlrdG9yKSwgdGVydXRhbWEga2V0aWthIHZhcmlhYmVsIGRlcGVuZGVuIGJlcnNpZmF0ICoqa2F0ZWdvcmlrYWwqKi4NCg0KRGFsYW0gdHVnYXMgaW5pLCBha2FuIGRpbGFrdWthbiBkdWEgamVuaXMgYW5hbGlzaXM6DQoNCiMjICoqYS4gUmVncmVzaSBMb2dpc3RpayBCaW5lciAoQmluYXJ5IExvZ2lzdGljIFJlZ3Jlc3Npb24pKioNCg0K4oaSIGRpZ3VuYWthbiBrZXRpa2EgdmFyaWFiZWwgcmVzcG9uIGhhbnlhIG1lbWlsaWtpIGR1YSBrYXRlZ29yaSAobWlzYWxueWEgWWEgYXRhdSBUaWRhaykuDQoNCiMjICoqYi4gUmVncmVzaSBMb2dpc3RpayBNdWx0aW5vbWlhbCAoTXVsdGlub21pYWwgTG9naXN0aWMgUmVncmVzc2lvbikqKg0KDQrihpIgZGlndW5ha2FuIGtldGlrYSB2YXJpYWJlbCByZXNwb24gbWVtaWxpa2kgbGViaWggZGFyaSBkdWEga2F0ZWdvcmkgKG1pc2FsbnlhIFJlbmRhaCwgU2VkYW5nLCBUaW5nZ2kpLg0KDQoNCiMgKioyLiBUdWp1YW4gQW5hbGlzaXMqKg0KVHVqdWFuIGRhcmkgdHVnYXMgaW5pIGFkYWxhaCAqKm1lbWJhbmRpbmdrYW4gZHVhIGplbmlzIG1vZGVsIHJlZ3Jlc2kgbG9naXN0aWsqKiDigJQgeWFpdHUgKipCaW5hcnkgTG9naXN0aWMgUmVncmVzc2lvbioqIGRhbiAqKk11bHRpbm9taWFsIExvZ2lzdGljIFJlZ3Jlc3Npb24qKiDigJQgdW50dWsgbWVsaWhhdCAqKm1vZGVsIG1hbmEgeWFuZyBsZWJpaCBha3VyYXQqKiBkYWxhbSBtZW1wcmVkaWtzaSB2YXJpYWJlbCB0YXJnZXQgYmVyZGFzYXJrYW4gZGF0YSB5YW5nIHRlcnNlZGlhLg0KDQoNCiMgKiozLiBLb25zZXAgRGFzYXIqKg0KDQojIyAqKmEuIEJpbmFyeSBMb2dpc3RpYyBSZWdyZXNzaW9uKioNCk1vZGVsIGluaSBkaWd1bmFrYW4gKipqaWthIHZhcmlhYmVsIGRlcGVuZGVuKiogJChZKSQgaGFueWEgbWVtaWxpa2kgKipkdWEga2F0ZWdvcmkqKiAobWlzYWxueWE6IOKAnFN1Y2Nlc3MgPSAx4oCdIGRhbiDigJxUaWRhayBTdWNjZXNzID0gMOKAnSkuDQpSdW11cyB1bXVtbnlhOg0KXFsNClx0ZXh0e2xvZ2l0fShwKSA9IFxsblxsZWZ0KFxmcmFje3B9ezEgLSBwfVxyaWdodCkgPSBcYmV0YV8wICsgXGJldGFfMSBYXzEgKyBcYmV0YV8yIFhfMiArIFxkb3RzICsgXGJldGFfayBYX2sNClxdDQpIYXNpbG55YSBiZXJ1cGEgKipwcm9iYWJpbGl0YXMga2ViZXJoYXNpbGFuIChwKSoqIGFudGFyYSAwIGRhbiAxLg0KDQojIyAqKmIuIE11bHRpbm9taWFsIExvZ2lzdGljIFJlZ3Jlc3Npb24qKg0KTW9kZWwgaW5pIGRpZ3VuYWthbiBqaWthIHZhcmlhYmVsIGRlcGVuZGVuIG1lbWlsaWtpICoqbGViaWggZGFyaSBkdWEga2F0ZWdvcmkqKiAobWlzYWxueWE6IOKAnFNhdGlzZmFjdGlvbiA9IExvdywgTWVkaXVtLCBIaWdo4oCdKS4NClJ1bXVzbnlhOg0KXFsNClAoWSA9IGspID0gXGZyYWN7ZV57XG1hdGhiZntYfSBcYm9sZHN5bWJvbHtcYmV0YX1fa319e1xzdW1fe2o9MX1ee0t9IGVee1xtYXRoYmZ7WH0gXGJvbGRzeW1ib2x7XGJldGF9X2p9fQ0KXF0NCkhhc2lsbnlhIG1lbWJlcmlrYW4gcHJvYmFiaWxpdGFzIHVudHVrIHNldGlhcCBrYXRlZ29yaSAoYnVrYW4gaGFueWEgZHVhKS4NCg0KIyAqKjQuIExhbmdrYWgtbGFuZ2thaCBBbmFsaXNpKioNCg0KIyMgKipMYW5na2FoIDE6IEltcG9ydCBkYW4gQ2VrIERhdGEqKg0KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEluc3RhbGwgJiBsb2FkIHBhY2thZ2UNCnBhY2thZ2VzIDwtIGMoInRpZHl2ZXJzZSIsICJ0aWR5bW9kZWxzIiwgIm5uZXQiLCAiY2FyZXQiLCAieWFyZHN0aWNrIiwgIkRUIikNCmluc3RhbGwucGFja2FnZXMoc2V0ZGlmZihwYWNrYWdlcywgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpKSwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCg0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG5uZXQpDQpsaWJyYXJ5KGNhcmV0KQ0KbGlicmFyeSh5YXJkc3RpY2spDQpsaWJyYXJ5KERUKQ0KDQojIEltcG9ydCBkYXRhIChwYXN0aWthbiBuYW1hIGZpbGUgcGFrYWkgdGFuZGEgbWludXMgYmlhc2EpDQpkYXRhIDwtIHJlYWQuY3N2KCIyIFJlZ3Jlc3Npb24gTW9kZWxzIOKAkyBBbmFseXNpcyBhbmQgUHJlZGljdGl2ZSBNb2RlbGluZy5jc3YiKQ0KDQojIE1lbmFtcGlsa2FuIHN0cnVrdHVyIGRhdGENCmdsaW1wc2UoZGF0YSkNCg0KIyBSaW5na2FzYW4gc3RhdGlzdGlrIGRhdGENCnN1bW1hcnkoZGF0YSkNCg0KIyBDZWsgbWlzc2luZyB2YWx1ZQ0KY29sU3Vtcyhpcy5uYShkYXRhKSkNCg0KIyBNZW5hbXBpbGthbiBzZWx1cnVoIGRhdGEgZGFsYW0gYmVudHVrIHRhYmVsIGludGVyYWt0aWYNCmRhdGF0YWJsZSgNCiAgZGF0YSwNCiAgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLCBzY3JvbGxYID0gVFJVRSksDQogIGNhcHRpb24gPSAiVGFiZWw6IFNlbHVydWggRGF0YSBkYXJpIERhdGFzZXQiDQopDQpgYGANCg0KKipQZW5qZWxhc2FuKio6DQoNCi0gKip0aWR5dmVyc2UqKiBkaWd1bmFrYW4gdW50dWsgbWFuaXB1bGFzaSBkYXRhIGRhbiB2aXN1YWxpc2FzaS4NCi0gKip0aWR5bW9kZWxzKiosICoqY2FyZXQqKiwgZGFuICoqeWFyZHN0aWNrKiogZGlndW5ha2FuIHVudHVrIG1vZGVsIGRhbiBldmFsdWFzaS4NCi0gKipubmV0KiogZGlndW5ha2FuIHVudHVrIG11bHRpbm9taWFsIGxvZ2lzdGljIHJlZ3Jlc3Npb24uDQoNCiMjICoqTGFuZ2thaCAyOiBNZW5lbnR1a2FuIFRhcmdldCBkYW4gU3BsaXQgRGF0YSoqDQpNaXNhbG55YSwgcGFkYSBkYXRhc2V0IGluaToNCg0KLSBWYXJpYWJlbCAqKkJpbmFyeSoqIC0+ICpTdWNjZXNzKiAoMCA9IGdhZ2FsLCAxID0gYmVyaGFzaWwpDQotIFZhcmlhYmVsICoqTXVsdGlub21pYWwqKiAtPiAqU3RhdGlzZmFjdGlvbl9jYXQqIChrYXRlZ29yaSBrZXB1YXNhbikNCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc2V0LnNlZWQoMTIzKSAjIGFnYXIgaGFzaWwgYWNhayBrb25zaXN0ZW4NCg0KIyBQYXN0aWthbiBwYWNrYWdlIHJzYW1wbGUgc3VkYWggdGVyaW5zdGFsIGRhbiBkaW11YXQNCmlmICghcmVxdWlyZShyc2FtcGxlKSkgaW5zdGFsbC5wYWNrYWdlcygicnNhbXBsZSIpDQpsaWJyYXJ5KHJzYW1wbGUpDQoNCiMgU3BsaXQgZGF0YSB1bnR1ayBiaW5hcnkNCnNwbGl0X2JpbiA8LSBpbml0aWFsX3NwbGl0KGRhdGEsIHByb3AgPSAwLjcsIHN0cmF0YSA9ICJTdWNjZXNzIikNCnRyYWluX2JpbiA8LSB0cmFpbmluZyhzcGxpdF9iaW4pDQp0ZXN0X2JpbiA8LSB0ZXN0aW5nKHNwbGl0X2JpbikNCg0KIyBUYW1waWxrYW4gbmFtYSBrb2xvbQ0KcHJpbnQobmFtZXMoZGF0YSkpDQoNCiMgTWlzYWwga29sb20geWFuZyBiZW5hciBhZGFsYWggIlNhdGlzZmFjdGlvbiINCnNwbGl0X211bHRpIDwtIGluaXRpYWxfc3BsaXQoZGF0YSwgcHJvcCA9IDAuNywgc3RyYXRhID0gIlNhdGlzZmFjdGlvbiIpDQp0cmFpbl9tdWx0aSA8LSB0cmFpbmluZyhzcGxpdF9tdWx0aSkNCnRlc3RfbXVsdGkgPC0gdGVzdGluZyhzcGxpdF9tdWx0aSkNCmBgYA0KKipQZW5qZWxhc2FuKio6DQoNCktpdGEgbWVtYmFnaSBkYXRhIG1lbmphZGkgJDcwJCUgdHJhaW5pbmcgZGFuICQzMCQlIHRlc3RpbmcuDQoqc3RyYXRhKiBkaWd1bmFrYW4gYWdhciBwcm9wb3JzaSBrYXRlZ29yaSB0YXJnZXQgdGV0YXAgc2VpbWJhbmcuDQoNCiMjICoqTGFuZ2thaCAzOiBCaW5hcnkgTG9naXN0aWsgUmVncmVzc2lvbioqDQpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgTW9kZWwgYmluYXJ5IGxvZ2lzdGljIHJlZ3Jlc3Npb24NCm1vZGVsX2JpbiA8LSBnbG0oU3VjY2VzcyB+IEFkdmVydGlzaW5nICsgU2FsZXNwZW9wbGUgKyBTYXRpc2ZhY3Rpb24gKyBDb21wZXRpdGlvbiwNCiAgICAgICAgICAgICAgICAgZGF0YSA9IHRyYWluX2JpbiwgZmFtaWx5ID0gYmlub21pYWwpDQoNCiMgUmluZ2thc2FuIG1vZGVsDQpzdW1tYXJ5KG1vZGVsX2JpbikNCg0KIyBQcmVkaWtzaSBwcm9iYWJpbGl0YXMNCnByZWRfYmluIDwtIHByZWRpY3QobW9kZWxfYmluLCBuZXdkYXRhID0gdGVzdF9iaW4sIHR5cGUgPSAicmVzcG9uc2UiKQ0KDQojIFViYWggbWVuamFkaSBrbGFzaWZpa2FzaSAoMC8xKQ0KcHJlZF9iaW5fY2xhc3MgPC0gaWZlbHNlKHByZWRfYmluID4gMC41LCAxLCAwKQ0KDQojIENvbmZ1c2lvbiBtYXRyaXgNCmNvbmZfbWF0X2JpbiA8LSB0YWJsZShBY3R1YWwgPSB0ZXN0X2JpbiRTdWNjZXNzLCBQcmVkaWN0ZWQgPSBwcmVkX2Jpbl9jbGFzcykNCmNvbmZfbWF0X2Jpbg0KDQojIEhpdHVuZyBha3VyYXNpDQphY2N1cmFjeV9iaW4gPC0gc3VtKGRpYWcoY29uZl9tYXRfYmluKSkgLyBzdW0oY29uZl9tYXRfYmluKQ0KYWNjdXJhY3lfYmluDQpgYGANCioqRGltYW5hKio6DQoNCioqYS4gUmluZ2thc2FuIE1vZGVsIChzdW1tYXJ5KG1vZGVsX2JpbikpKioNCg0KSW5pIGFkYWxhaCBoYXNpbCByaW5na2FzYW4gbW9kZWwgcmVncmVzaSBsb2dpc3RpayB5YW5nIG1lbnVuanVra2FuOg0KDQotICoqS29lZmlzaWVuIHNldGlhcCB2YXJpYWJlbCAoQWR2ZXJ0aXNpbmcsIFNhbGVzcGVvcGxlLCBTYXRpc2ZhY3Rpb24sIENvbXBldGl0aW9uKSoqDQoNCk5pbGFpIGtvZWZpc2llbiBtZW51bmp1a2thbiBwZW5nYXJ1aCBtYXNpbmctbWFzaW5nIHZhcmlhYmVsIHRlcmhhZGFwIHBlbHVhbmcga2ViZXJoYXNpbGFuICooU3VjY2VzcykqLiANCiAgICAtIEtvZWZpc2llbiBwb3NpdGlmIOKGkiB2YXJpYWJlbCBtZW5pbmdrYXRrYW4gcGVsdWFuZyBrZWJlcmhhc2lsYW4uDQogICAgLSBLb2VmaXNpZW4gbmVnYXRpZiDihpIgdmFyaWFiZWwgbWVudXJ1bmthbiBwZWx1YW5nIGtlYmVyaGFzaWxhbi4NCg0KLSAqKk5pbGFpIHAtdmFsdWUqKiB1bnR1ayBtZW5ndWppIHNpZ25pZmlrYW5hc2kgbWFzaW5nLW1hc2luZyB2YXJpYWJlbC4NCiAgICAtIHAtdmFsdWUga2VjaWwgKGJpYXNhbnlhIDwgMC4wNSkgYmVyYXJ0aSB2YXJpYWJlbCBzaWduaWZpa2FuIG1lbXBlbmdhcnVoaSAqU3VjY2VzcyoNCg0KLSAqKkludGVyY2VwdCoqIGFkYWxhaCBiYXNlbGluZSBsb2ctb2RkcyBrZWJlcmhhc2lsYW4gc2FhdCBzZW11YSB2YXJpYWJlbCBwcmVkaWt0b3IgYmVybmlsYWkgbm9sLg0KDQoNCioqYi4gUHJlZGlrc2kgUHJvYmFiaWxpdGFzICpwcmVkX2JpbiogKioNCg0KTW9kZWwgbWVuZ2hhc2lsa2FuIG5pbGFpIGFudGFyYSAwIGRhbiAxLCB5YW5nIGFydGlueWEgKipwcm9iYWJpbGl0YXMgcHJlZGlrc2kga2ViZXJoYXNpbGFuKiogdW50dWsgdGlhcCBkYXRhIGRpIHRlc3Qgc2V0Lg0KDQoqKkNvbnRvaCoqOg0KDQpKaWthICpwcmVkX2JpbltpXSogPSAkMC44JCBiZXJhcnRpIG1vZGVsIG1lbXByZWRpa3NpIGRhdGEga2UtaSBtZW1pbGlraSBwZWx1YW5nICQ4MCQlIHVudHVrIFN1Y2Nlc3MgPSAkMSQuDQoNCioqQy4gS2xhc2lmaWthc2kgSGFzaWwgUHJlZGlrc2kgKihwcmVkX2Jpbl9jbGFzcykqICoqDQoNClByb2JhYmlsaXRhcyB0YWRpIGRpdWJhaCBrZSBrZWxhcyBkaXNrcml0Og0KDQotIEppa2EgPiAkMC41JCAtPiBwcmVkaWtzaSAqU3VjY2VzcyogPSAkMSQgKGJlcmhhc2lsKQ0KLSBKaWthICRcbGVxJCAkMC41JCAtPiBwcmVkaWtzaSAqU3VjY2VzcyogPSAkMCQgKGdhZ2FsKQ0KDQoqKmQuIENvbmZ1c2lvbiBNYXRyaXgqKiAqKGNvbmZfbWF0X2JpbikqDQoNCk1pc2Fsa2FuIGhhc2lsbnlhIHNlcGVydGkgaW5pOg0KXFsNClxiZWdpbnthcnJheX17Y3xjY30NClx0ZXh0e0FjdHVhbH0gXGJhY2tzbGFzaCBcdGV4dHtQcmVkaWN0ZWR9ICYgMCAmIDEgXFwgXGhsaW5lDQowICYgNDAgJiAxMCBcXA0KMSAmIDUgJiA0NSBcXA0KXGVuZHthcnJheX0NClxdDQoqKkFydGlueWE6KioNCg0KLSA0MCBkYXRhIHlhbmcgc2ViZW5hcm55YSAwIGRpcHJlZGlrc2kgYmVuciAwIChUcnVlIE5lZ2F0aXZlKQ0KLSA0NSBkYXRhIHlhbmcgc2ViZW5hcm55YSAxIGRpcHJlZGlrc2kgYmVuZXIgMSAoVHJ1ZSBQb3NpdGl2ZSkNCi0gMTAgZGF0YSB5YW5nIHNlYmVuYXJueWEgMCBzYWxhaCBkaXByZWRpa3NpIDEgKEZhbHNlIFBPc2l0aXZlKQ0KLSA1IGRhdGEgeWFuZyBzZWJlbmFybnlhIDEgc2FsYWggZGlwcmVkaWtzaSAwIChGYWxzZSBOZWdhdGl2ZSkNCg0KKiplLiBBa3VyYXNpKiogKihhY2N1cmFjeV9iaW4pKg0KDQpNaXNhbCBha3VyYXNpIDAuODUgLT4gYXJ0aW55YSBtb2RlbCBtZW1wcmVkaWtzaSBkZW5nYW4gYmVuYXIgJDg1JCUgZGFyaSBzZW11YSBkYXRhIHRlc3RpbmcuDQoNCg0KIyMgKipMYW5na2FoIDQ6IE11bHRpbm9tbWlhbCBMb2dpc3RpayBSZWdyZXNzaW9uKioNCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyAxLiBNdWF0IHNlbXVhIGxpYnJhcnkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShubmV0KQ0KbGlicmFyeShyc2FtcGxlKQ0KDQojIDIuIEJhY2EgdWxhbmcgZGF0YSBtZW50YWgNCmRhdGEgPC0gcmVhZC5jc3YoIjIgUmVncmVzc2lvbiBNb2RlbHMg4oCTIEFuYWx5c2lzIGFuZCBQcmVkaWN0aXZlIE1vZGVsaW5nLmNzdiIpDQoNCiMgMy4gQmVyc2loa2FuIGRhbiB1YmFoIHZhcmlhYmVsDQpkYXRhIDwtIGRhdGEgJT4lDQogIG11dGF0ZSgNCiAgICBTdWNjZXNzID0gZmFjdG9yKFN1Y2Nlc3MsIGxldmVscyA9IGMoMCwgMSksIGxhYmVscyA9IGMoIlRpZGFrIiwgIllhIikpLA0KICAgIFNhdGlzZmFjdGlvbiA9IGFzLm51bWVyaWMoU2F0aXNmYWN0aW9uKSwNCiAgICBTYXRpc2ZhY3Rpb25fY2F0ID0gY3V0KA0KICAgICAgU2F0aXNmYWN0aW9uLA0KICAgICAgYnJlYWtzID0gcXVhbnRpbGUoU2F0aXNmYWN0aW9uLCBwcm9icyA9IGMoMCwgMS8zLCAyLzMsIDEpLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgbGFiZWxzID0gYygiUmVuZGFoIiwgIlNlZGFuZyIsICJUaW5nZ2kiKSwNCiAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRQ0KICAgICkNCiAgKQ0KDQojIDQuIFNwbGl0IGRhdGEgbWVuamFkaSB0cmFpbmluZyBkYW4gdGVzdGluZyB1bnR1ayBtb2RlbCBtdWx0aW5vbWlhbA0Kc2V0LnNlZWQoMTIzKQ0Kc3BsaXRfbXVsdGkgPC0gaW5pdGlhbF9zcGxpdChkYXRhLCBwcm9wID0gMC43LCBzdHJhdGEgPSAiU2F0aXNmYWN0aW9uX2NhdCIpDQp0cmFpbl9tdWx0aSA8LSB0cmFpbmluZyhzcGxpdF9tdWx0aSkNCnRlc3RfbXVsdGkgPC0gdGVzdGluZyhzcGxpdF9tdWx0aSkNCg0KIyA1LiBQYXN0aWthbiB2YXJpYWJlbCB0YXJnZXQgYWRhbGFoIGZha3Rvcg0KdHJhaW5fbXVsdGkkU2F0aXNmYWN0aW9uX2NhdCA8LSBhcy5mYWN0b3IodHJhaW5fbXVsdGkkU2F0aXNmYWN0aW9uX2NhdCkNCnRlc3RfbXVsdGkkU2F0aXNmYWN0aW9uX2NhdCA8LSBhcy5mYWN0b3IodGVzdF9tdWx0aSRTYXRpc2ZhY3Rpb25fY2F0KQ0KDQojIDYuIENlayBuYW1hIGtvbG9tIHVudHVrIG1lbWFzdGlrYW4gdGlkYWsgc2FsYWgga2V0aWsNCm5hbWVzKHRyYWluX211bHRpKQ0KDQojIDcuIEphbGFua2FuIG1vZGVsIG11bHRpbm9taWFsIGxvZ2lzdGljIHJlZ3Jlc3Npb24NCm1vZGVsX211bHRpIDwtIG5uZXQ6Om11bHRpbm9tKA0KICBTYXRpc2ZhY3Rpb25fY2F0IH4gQWR2ZXJ0aXNpbmcgKyBTYWxlc3Blb3BsZSArIENvbXBldGl0aW9uICsgU3VjY2VzcywNCiAgZGF0YSA9IHRyYWluX211bHRpLA0KICBtYXhpdCA9IDEwMDANCikNCg0KIyA4LiBMaWhhdCByaW5na2FzYW4gbW9kZWwNCnN1bW1hcnkobW9kZWxfbXVsdGkpDQoNCiMgOS4gUHJlZGlrc2kgZGFuIGV2YWx1YXNpDQpwcmVkX211bHRpIDwtIHByZWRpY3QobW9kZWxfbXVsdGksIG5ld2RhdGEgPSB0ZXN0X211bHRpKQ0KY29uZl9tYXRfbXVsdGkgPC0gdGFibGUoQWN0dWFsID0gdGVzdF9tdWx0aSRTYXRpc2ZhY3Rpb25fY2F0LCBQcmVkaWN0ZWQgPSBwcmVkX211bHRpKQ0KY29uZl9tYXRfbXVsdGkNCg0KYWNjdXJhY3lfbXVsdGkgPC0gc3VtKGRpYWcoY29uZl9tYXRfbXVsdGkpKSAvIHN1bShjb25mX21hdF9tdWx0aSkNCmFjY3VyYWN5X211bHRpDQpgYGANCioqRGltYW5hOioqDQoNCi0gKm11bHRpbm9tKCkqIGRpZ3VuYWthbiB1bnR1ayBkYXRhIHRhcmdldCBsZWJpaCBkYXJpIGR1YSBrYXRlZ29yaS4NCi0gUHJlZGlrc2kgZGlrYXRlZ29yaWthbiwgbGFsdSBkaWJhbmRpbmdrYW4gZGVuZ2FuIG5pbGFpIGFrdHVhbCB1bnR1ayBtZW5naGl0dW5nIGFrdXJhc2kuDQoNCiMjICoqTGFuZ2thaCA1OiBNZW1iYW5kaW5na2FuIEFrdXJhc2kqKg0KYGBge3J9DQphY2N1cmFjeV9kZiA8LSBkYXRhLmZyYW1lKA0KICBNb2RlbCA9IGMoIkJpbmFyeSBMb2dpc3RpYyBSZWdyZXNzaW9uIiwgIk11bHRpbm9taWFsIExvZ2lzdGljIFJlZ3Jlc3Npb24iKSwNCiAgQWNjdXJhY3kgPSBjKGFjY3VyYWN5X2JpbiwgYWNjdXJhY3lfbXVsdGkpDQopDQpwcmludChhY2N1cmFjeV9kZikNCmBgYA0KKipEaW1hbmE6KioNCg0KVGFiZWwgaW5pIG1lbmFtcGlsa2FuIHBlcmJhbmRpbmdhbiBha3VyYXNpIGR1YSBtb2RlbC4gTW9kZWwgZGVuZ2FuIG5pbGFpIGFrdXJhc2kgbGViaWggdGluZ2dpIC0+ICoqbGViaWggYWt1cmF0KiouDQoNCiMjICoqTGFuZ2thaCA2OiBWaXN1YWxpc2FzaSBQZXJiYW5kaW5nYW4gQWt1cmFzaSoqDQpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikgIyBqYWxhbmthbiBqaWthIGJlbHVtIGFkYQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQoNCiMgRGF0YSBjb250b2ggKGdhbnRpIGRlbmdhbiBkYXRhIGthbXUpDQphY2N1cmFjeV9kZiA8LSBkYXRhLmZyYW1lKA0KICBNb2RlbCA9IGMoIkJpbmFyeSIsICJNdWx0aW5vbWlhbCIpLA0KICBBY2N1cmFjeSA9IGMoMC44MiwgMC44OSkNCikNCg0KIyBCdWF0IGdncGxvdCBkYXNhcg0KcCA8LSBnZ3Bsb3QoYWNjdXJhY3lfZGYsIGFlcyh4ID0gTW9kZWwsIHkgPSBBY2N1cmFjeSwgZmlsbCA9IE1vZGVsKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuNikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoQWNjdXJhY3ksIDMpKSwgdmp1c3QgPSAtMC41LCBzaXplID0gNSkgKw0KICB5bGltKDAsIDEpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQZXJiYW5kaW5nYW4gQWt1cmFzaTogQmluYXJ5IHZzIE11bHRpbm9taWFsIExvZ2lzdGljIFJlZ3Jlc3Npb24iLA0KICAgIHkgPSAiQWt1cmFzaSIsIHggPSAiIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgVWJhaCBrZSBwbG90bHkgaW50ZXJha3RpZg0KZ2dwbG90bHkocCkNCmBgYA0KKipEaW1hbmE6KioNCg0KR3JhZmlrIGJhdGFuZyBpbmkgbWVudW5qdWtrYW4gYWt1cmFzaSBtYXNpbmctbWFzaW5nIG1vZGVsIHNlY2FyYSB2aXN1YWwuIFNlbWFraW4gdGluZ2dpIGJhdGFuZywgc2VtYWtpbiBha3VyYXQgbW9kZWwgdGVyc2VidXQuDQoNCiMjICoqTGFuZ2thaCA3OiBWaXN1YWxpc2FzaSBEaXN0cmlidXNpIFByZWRpa3NpIEJpbmFyeSoqDQpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkocGxvdGx5KQ0KDQojIFRhbWJhaGthbiBrb2xvbSBpbmRleCB1bnR1ayBzdW1idSBYDQp0ZXN0X2JpbiRpbmRleCA8LSAxOm5yb3codGVzdF9iaW4pDQoNCiMgUGxvdHRpbmcgbGFuZ3N1bmcgcGFrYWkgZnVuZ3NpIHByZWRpY3QoKQ0KZmlnIDwtIHBsb3RfbHkoDQogIGRhdGEgPSB0ZXN0X2JpbiwNCiAgeCA9IH5pbmRleCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdXJ1dGFuIG9ic2VydmFzaQ0KICB5ID0gcHJlZGljdChtb2RlbF9iaW4sIHRlc3RfYmluLCB0eXBlID0gInJlc3BvbnNlIiksICAjIHByb2JhYmlsaXRhcyBwcmVkaWtzaSBsYW5nc3VuZyBkYXJpIG1vZGVsDQogIHogPSB+YXMubnVtZXJpYyhTdWNjZXNzKSwgICAgICAgICAgICAgICAgICAgICAgICAjIGtlbGFzIGFrdHVhbCAoMC8xKQ0KICBjb2xvciA9IH5hcy5mYWN0b3IoU3VjY2VzcyksICAgICAgICAgICAgICAgICAgICAgIyB3YXJuYSBiZXJkYXNhcmthbiBrZWxhcw0KICB0eXBlID0gInNjYXR0ZXIzZCIsDQogIG1vZGUgPSAibWFya2VycyIsDQogIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDUsIG9wYWNpdHkgPSAwLjgpDQopDQoNCmZpZyA8LSBmaWcgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9ICJWaXN1YWxpc2FzaSAzRCBQcm9iYWJpbGl0YXMgUHJlZGlrc2kgKEJpbmFyeSBMb2dpc3RpYyBSZWdyZXNzaW9uKSIsDQogICAgc2NlbmUgPSBsaXN0KA0KICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkluZGV4IE9ic2VydmFzaSIpLA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlByb2JhYmlsaXRhcyBQcmVkaWtzaSIpLA0KICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIlN1Y2Nlc3MgKDA9VGlkYWssIDE9WWEpIikNCiAgICApDQogICkNCg0KZmlnDQpgYGANCg0KIyAqKjQuIEludGVycHJldGFzaSBIYXNpbCoqDQoNCi0gSmlrYSAqYWNjdXJhY3lfYmluID4gYWNjdXJhY3lfbXVsdGkqIC0+IE1vZGVsIEJpbmFyeSBMb2dpc3RpayBsZWJpaCBiYWlrLg0KLSBKaWthICphY2N1cmFjeV9tdWx0aSA+IGFjY3VyYWN5X2JpbiogLT4gTW9kZWwgTXVsdGlub21pYWwgbGViaWggYmFpay4NCi0gTmlsYWkgKipha3VyYXNpIG1lbmRla2F0aSoqICQxJCBtZW51bmp1a2thbiBtb2RlbCBtZW1wcmVkaWtzaSBkZW5nYW4gc2FuZ2F0IGJhaWsuDQotIFNlbGFpbiBha3VyYXNpLCBrYW11IGp1Z2EgYmlzYSBtZW5pbGFpIGRhcmkgY29uZnVzaW9uIG1hdHJpeCB1bnR1ayBtZWxpaGF0IGtlc2FsYWhhbiBrbGFzaWZpa2FzaS4NCi0gTW9kZWwgZGVuZ2FuIGFrdXJhc2kgKipsZWJpaCB0aW5nZ2kgbGViaWggbWFtcHUgbWVuZ2VuYWxpIHBvbGEgaHVidW5nYW4qKiBhbnRhcmEgdmFyaWFiZWwgcHJlZGlrdG9yIChBZHZlcnRpc2luZywgU2FsZXNwZW9wbGUsIENvbXBldGl0aW9uLCBkbGwuKSBkZW5nYW4gdmFyaWFiZWwgdGFyZ2V0Lg0KLSBKaWthICoqTXVsdGlub21pYWwqKiBsZWJpaCBha3VyYXQg4oaSIGJlcmFydGkgaW5mb3JtYXNpIGthdGVnb3JpIGtlcHVhc2FuIHBlbGFuZ2dhbiBtZW1iZXJpa2FuIGtvbnRyaWJ1c2kgbGViaWggYmVzYXIgdGVyaGFkYXAgcGVtYWhhbWFuIGthcmFrdGVyaXN0aWsgcGVyZm9ybWEgYmlzbmlzLg0KLSBKaWthICoqQmluYXJ5KiogbGViaWggYWt1cmF0IOKGkiBiZXJhcnRpIHBlbWlzYWhhbiBzZWRlcmhhbmEgYW50YXJhIOKAnGJlcmhhc2ls4oCdIGRhbiDigJx0aWRhayBiZXJoYXNpbOKAnSBzdWRhaCBjdWt1cCBtZXdha2lsaSBwcmVkaWtzaSBwZXJmb3JtYS4NCg0KIyAqKjUuIEtlc2ltcHVsYW4qKg0KQmVyZGFzYXJrYW4gYW5hbGlzaXMgeWFuZyB0ZWxhaCBkaWxha3VrYW4gbWVuZ2d1bmFrYW4gZHVhIHBlbmRla2F0YW4gcmVncmVzaSBsb2dpc3RpaywgeWFpdHUgKipCaW5hcnkgTG9naXN0aWMgUmVncmVzc2lvbioqIGRhbiAqKk11bHRpbm9taWFsIExvZ2lzdGljIFJlZ3Jlc3Npb24qKiwgZGFwYXQgZGlzaW1wdWxrYW4gYmFod2Ega2VkdWEgbW9kZWwgbWFtcHUgbWVtcHJlZGlrc2kgdmFyaWFiZWwgdGFyZ2V0IHBhZGEgZGF0YXNldCBkZW5nYW4gYmFpaywgbmFtdW4gdGluZ2thdCBha3VyYXNpbnlhIGJlcmJlZGEuDQoNCk1vZGVsICoqQmluYXJ5IExvZ2lzdGljIFJlZ3Jlc3Npb24qKiBkaWd1bmFrYW4gdW50dWsgbWVtcHJlZGlrc2kga2F0ZWdvcmkgU3VjY2VzcyAoMCA9IHRpZGFrIGJlcmhhc2lsLCAxID0gYmVyaGFzaWwpLiBTZWRhbmdrYW4gKipNdWx0aW5vbWlhbCBMb2dpc3RpYyBSZWdyZXNzaW9uKiogZGlndW5ha2FuIHVudHVrIG1lbXByZWRpa3NpIHRpbmdrYXQgKlNhdGlzZmFjdGlvbiogeWFuZyB0ZXJkaXJpIGRhcmkgdGlnYSBsZXZlbCAqKFJlbmRhaCwgU2VkYW5nLCBUaW5nZ2kpKi4NCg0KIyAqKlJlZnJlbnNpKioNCi0gUmVncmVzc2lvbiBNb2RlbHMgPGEgaHJlZiA9ICJodHRwczovL2Jvb2tkb3duLm9yZy9jb250ZW50L2ExNDJiMTcyLTY5YjItNDM2ZC1iZGIwLTlkYTZkMDQ2YTBmOS8wMi1SZWdyZXNzaW9uX01vZGVsLmh0bWwjbG9naXN0aWNzLXJlZ3Jlc3Npb24iID4gS2xpayBkaXNpbmk8L2E+DQotIENvZGluZyBTdHVkaW8gVGVhbSBEZWNlbWJlciAyMDIxIDxhIGhyZWYgPSAiaHR0cHM6Ly9jb2RpbmdzdHVkaW8uaWQvYmxvZy9yZWdyZXNpLWxvZ2lzdGlrLyIgPiBLbGlrIGRpc2luaTwvYT4NCi0gUmVncmVzaSBMb2dpc3RpayAoQmluZXIsIE9yZGluYWwsIE11bHRpbm9taWFsKSwgYnkgTHVtaXZlcmkgPGEgaHJlZiA9ICJodHRwczovL2Jvb2tkb3duLm9yZy9jb250ZW50L2ExNDJiMTcyLTY5YjItNDM2ZC1iZGIwLTlkYTZkMDQ2YTBmOS8wMi1SZWdyZXNzaW9uX01vZGVsLmh0bWwjbG9naXN0aWNzLXJlZ3Jlc3Npb24iID4gS2xpayBkaXNpbmk8L2E+IiA+DQotICBPbGVoIEthcmVuIEdyYWNlLU1hcnRuaW4gPGEgaHJlZiA9ICJodHRwczovL3d3dy50aGVhbmFseXNpc2ZhY3Rvci5jb20vZGVjaWRlLWJldHdlZW4tbXVsdGlub21pYWwtYW5kLW9yZGluYWwtbG9naXN0aWMtcmVncmVzc2lvbi1tb2RlbHMvIiA+IEtsaWsgZGlzaW5pPC9hPg0KDQo=