Regresi Linear

Mari kita mencoba memahami materi ini dengan beberapa pertanyaan

Pendahuluan

  • Apasih regresi itu?

Regresi adalah metode yang digunakan untuk memahami dan memodelkan hubungan antara satu atau lebih variabel independen (variabel prediktor) dan satu variabel dependen (variabel respons).

  • Kapan Regresi itu di temukan?

“Eh buset nanya udah kek pertanyaan ayang selingkuh apa nggak,, klao bisa nanya yang penting penting aja dah kwkkwk..”

  • Bisa kasih contoh Regresi dalam kehidupan sehari hari?

“oke ini cukup ber bobot”

Contohnya adalah ketika kita ingin memodelkan apakah semakin tinggi duid jajan semaakin tinggi pula kasih sayang?

Nah ini contoh aja sih ya kwkwk yang jomblo harap bersabar.

  • Kapan Regresi itu di gunakan?

Regresi ini jenisnya ada beberapa dan digunakan ketika variable nya berbeda,,


Jenis Jenis Regresi dan COntohnya

Pada materi ini kita akan fokus di 3 jenis yaitu Regresi Liniar Sederhana, Regresi Liniar Berganda dan Regresi Logistik

Regresi Liniar Sederhana

Dalam regresi linear sederhana, terdapat satu variabel independen dan satu variabel dependen. Model regresi linear sederhana diwakili oleh persamaan garis lurus (linear), seperti

y=mx+c

y=mx+c, di mana y adalah variabel dependen, x adalah variabel independen, m adalah koefisien kemiringan, dan c adalah intercept.

Contohnya adalah :

  • Misalkan kita bekerja di sebuah perusahaan dan ingin memahami hubungan antara biaya iklan yang dihabiskan dalam suatu periode dengan jumlah penjualan produk Anda.

  • Kita ingin melihat hubungan antara budget film MCU mempengaruhi dan mengakibatkan box_office secara positif dan kuat

  • Ingin memprediksi Qty penjualan dari kenaikan harga. Apakah semakin tinggi harganya maka akan semakin sedikit yang beli?

Regresi Liniar Berganda

Regresi linear berganda adalah jenis analisis regresi yang melibatkan lebih dari satu variabel independen untuk memprediksi variabel dependen. Dalam regresi linear berganda, kita mencoba memodelkan hubungan antara satu variabel dependen dengan dua atau lebih variabel independen. Model regresi linear berganda umumnya diwakili oleh persamaan berikut:

y=b0+b1x1+b2x2+…+bnxn+𝜀

y=b0 +b1 x1 +b2 x2 +…+bn xn +ε

Contohnya :

  • Sebuah perusahaan minuman ingin memahami faktor-faktor apa yang mempengaruhi penjualan produk mereka di pasar tertentu. Mereka memiliki data penjualan (variabel dependen), harga produk, promosi iklan, dan cuaca (variabel independen).

  • Perusahaan menggunakan regresi linear berganda untuk memodelkan hubungan antara penjualan produk dengan harga, promosi iklan, dan cuaca.

  • Seorang peneliti ingin memahami faktor-faktor yang mempengaruhi tekanan darah seseorang. Dia memiliki data tekanan darah (variabel dependen), tingkat aktivitas fisik, pola makan, dan usia (variabel independen).

  • Peneliti menggunakan regresi linear berganda untuk memodelkan hubungan antara tekanan darah dengan tingkat aktivitas fisik, pola makan, dan usia.

Penting : Regresi linear sederhana vs berganda di bedakan dari jumalh variablenya.

Regresi Logistik

Regresi logistik adalah metode statistik yang digunakan untuk memodelkan hubungan antara satu atau lebih variabel independen (prediktor) dengan variabel dependen biner (dichotomous), yang memiliki dua kategori atau hasil. Tujuannya adalah untuk memprediksi probabilitas kejadian suatu kejadian tertentu (biasanya diwakili oleh kategori 1) berdasarkan nilai-nilai variabel independen. Regresi logistik adalah alat yang umum digunakan dalam analisis data di berbagai bidang, termasuk ilmu sosial, kedokteran, epidemiologi, dan bisnis.

Contoh penerapan regresi logistik termasuk prediksi probabilitas seseorang mengembangkan penyakit tertentu berdasarkan faktor-faktor risiko seperti usia, jenis kelamin, dan riwayat merokok; atau memprediksi probabilitas pelanggan membeli produk tertentu berdasarkan karakteristik demografis mereka dan perilaku pembelian sebelumnya. (stroke prediction)

Regresi NonLinear

Regresi non-linear adalah jenis analisis regresi di mana hubungan antara variabel independen dan variabel dependen tidak dapat dijelaskan dengan persamaan garis lurus. Sebaliknya, hubungan tersebut dijelaskan dengan fungsi matematika yang lebih kompleks, seperti polinomial, eksponensial, logaritmik, sigmoid, atau fungsi lainnya yang tidak linear.

Contoh: Prediksi Pertumbuhan Pengguna Aplikasi Seluler

Deskripsi Kasus: Sebuah perusahaan pengembang aplikasi seluler ingin memprediksi pertumbuhan pengguna aplikasi mereka seiring dengan waktu. Mereka memiliki data historis tentang jumlah pengguna aktif harian (variabel dependen) selama beberapa bulan.

Model Regresi Non-linear: Perusahaan menggunakan regresi non-linear untuk memodelkan pertumbuhan pengguna aplikasi. Mereka memilih model pertumbuhan logistik yang umum digunakan dalam kasus seperti ini.

Interpretasi: Dengan menggunakan model regresi non-linear logistik, perusahaan dapat memprediksi pertumbuhan pengguna aplikasi mereka seiring waktu. Mereka dapat memperkirakan puncak pertumbuhan (L), laju pertumbuhan (k), dan titik tengah pertumbuhan (t0). Informasi ini dapat membantu perusahaan untuk mengatur strategi pemasaran, alokasi sumber daya, dan pengambilan keputusan bisnis lainnya.

ini tidak akan di bahas kembalike topik sayang kuh, kita akan bahas 3 jenis Regresi saja

Regresi Time Series

Regresi time series adalah teknik analisis yang digunakan untuk memodelkan hubungan antara satu atau lebih variabel dengan waktu (variabel independen) dan variabel yang diamati sepanjang periode waktu tertentu (variabel dependen). Tujuannya adalah untuk memahami dan memprediksi perilaku atau tren dari data time series berdasarkan informasi waktu sebelumnya.

Ini akan di bahas dalam materi time series analysis.

Regresi Ridge dan Lasso

Regresi Ridge dan Lasso adalah dua metode regularisasi yang digunakan dalam regresi linear untuk mengatasi masalah overfitting dan meningkatkan kinerja model dengan mengontrol kompleksitasnya.

ini tidak akan di bahas kembalike topik sayang kuh, kita akan bahas 3 jenis Regresi saja


Asumsi Regresi

Asumsi Regresi adalah paramater yang harus kita lalui untuk mengukur sebaikmana Regresi kita dan apakah model kita sudah cukup memuaskan?

jalur ini harus di pastikan memnuhi asumsi agar model kita??

Yesss, Model kita baik. sebaik akhlak Rasul.

Goodness of fit dari model

Parameter Goodness of fit dari model berupa:

R-Squared

  • R-Squared adalah ukuran statistik yang menggambarkan seberapa baik model regresi linear cocok dengan data yang diamati.

  • Nilai R-Squared berkisar antara 0 hingga 1, di mana semakin tinggi nilainya, semakin baik modelnya.

  • R-Squared mengukur seberapa besar variasi dalam variabel dependen yang dapat dijelaskan oleh variabel independen dalam model. Dengan kata lain, R-Squared menunjukkan persentase variasi dalam variabel dependen yang dapat dijelaskan oleh model regresi. Misalnya, jika R-Squared adalah 0,5, ini berarti 50% dari variasi dalam variabel dependen dapat dijelaskan oleh model.

  • Namun, penting untuk diingat bahwa R-Squared tidak menunjukkan sebab dan akibat, dan nilainya bisa meningkat hanya karena menambahkan variabel independen, bahkan jika variabel tersebut tidak memiliki hubungan kausal dengan variabel dependen.

P-value

  • P-value adalah ukuran yang digunakan untuk menentukan signifikansi statistik dari koefisien dalam model regresi atau efek variabel independen terhadap variabel dependen.

  • Nilai P-value menunjukkan probabilitas bahwa koefisien nol atau tidak ada efek.

  • Secara umum, jika P-value kurang dari nilai alpha yang telah ditetapkan (biasanya 0,05), maka koefisien dianggap signifikan secara statistik dan kita dapat menolak hipotesis nol (hipotesis bahwa koefisien adalah nol).

  • Jika P-value lebih besar dari nilai alpha, maka koefisien dianggap tidak signifikan secara statistik, yang berarti kita gagal menolak hipotesis nol.

  • Dalam konteks goodness of fit, P-value juga dapat digunakan untuk menilai signifikansi keseluruhan model. Sebuah P-value yang kecil menunjukkan bahwa model secara keseluruhan signifikan secara statistik.

Mean Squared Error (MSE)

  • Mean Squared Error (MSE) adalah ukuran statistik yang mengukur rata-rata dari kuadrat perbedaan antara nilai yang diprediksi oleh model regresi dan nilai yang diamati dari variabel dependen.

  • MSE digunakan untuk mengevaluasi seberapa baik model regresi memperkirakan nilai yang sebenarnya. Semakin kecil nilai MSE, semakin baik modelnya.

  • Dalam beberapa kasus, akar kuadrat dari MSE (Root Mean Squared Error, RMSE) sering digunakan sebagai ukuran yang lebih intuitif karena memiliki unit yang sama dengan variabel dependen.

Cara liatnya bisa dengan summary(nama model regresi).

Normality of Residual

Mengecek apakah erornya berdistribusi normal?

Uji hipotesisnya adalah :

H0 : residual berdistribusi normal.

H1 : residual tidak berdistribusi normal

Jika P value < 0.05 tolak H0 (uji dengan shapiro atau kolmogorov) kapan menggunakan salah satu dari kedua uji ini? tergantung dari jumlah n atau sample uji, <50 gunakan shapiro dan >50 gunakan kolmogorov sudah saya bahas di sini

Asumsi Ini harus normal ya, kenapa?

Asumsi distribusi normal dari residual penting karena memungkinkan kita untuk melakukan inferensi statistik yang akurat, seperti menghitung interval kepercayaan dan melakukan pengujian hipotesis. Ketika residual berdistribusi normal, kita dapat yakin bahwa estimasi koefisien dan statistik inferensial lainnya beroperasi dengan benar.

Linearity Check

cek linearity dengan plot dengan sintaksmelihat plot residual dan fitted values dari model

plot(model,1)

Uji hipotesis:

H0 : Tidak linear

H1 : Linear

Jika P value < 0.05, tolak H0

Uji korelasi menggunakan cor.test() untuk variabel prediktor

Asumsinya atau hasil dari Uji korelasi harus baik, meskipun idealnya kita ingin hubungan antara variabel dalam model regresi bersifat linear, adanya sedikit ketidaklinieran tidak selalu membuat model tersebut buruk. Penting untuk mempertimbangkan konteks analisis, tujuan, dan keterbatasan data ketika mengevaluasi linearitas dalam model regresi.

Uji Homoscedascity

Apa maksud dari homoscedasticity? Artinya error tidak memiliki pola. Sedangkan jika heteroscedasticity artinya error-nya berpola. Kalau terdapat heteroscedasticity, kemungkinan ada outlier yang harus dibuang.

Uji hipotesis:

H0 : model homoscedasticity

H1 : model heteroscedasticity

Jika P value < 0.05, tolak H0

Uji statistiknya dengan function bptest() dari library(lmtest).

Bptest(model)

Kenapa uji ini harus di lakukan? Masih bingung euy,,

Oke gan.. Jadi gini bayang kan jika residualny amemiliki pola, artinya baraible erornya punya pola linearitas. Nah kan artinya residual kita malah jadi prediktor yang baru kan? Lalu apa gunanya model kita sebelumnya? nah kebayang ngga? That’s why Eror atau Residual harus homosedasicity.

Uji Multicollinearity

Nah, uji yang ini baru bisa akan kita lakukan jika kita melakukan multiple linear regression, yakni saat variabel prediktornya lebih dari satu. Kita tidak mau kalau variabel prediktor di model kita itu saling berpengaruh (dependen) oh iya bahas tentang Dependen dan Independen variable sudah pernah saya tulis Di sini.

Untuk melakukannya, kita perlu mengujinya menggunakan nilai vif.

Cek dengan fungsi vif() dari library(car) untuk mengetahui variabel-variabel mana yang tidak bisa ditoleransi menjadi sebuah prediktor.

vif(model)

Nilai vif yang baik harus < 10 ketika vif > 10 maka harus ada variable yang di eliminasi atau di lakukan feature engineering (membuat variabel baru dari variabel-variabel yang ada).

Sebentarrrrrr

Ini saya bingung say,, maksud dari Multicolinearitas bagaimana??

Argghhhhhhh

Nah maksud dari Multicolinearitas adalah variable variable saling bertannga korelasi. Contoh variable A berkorelsi dengan B, B dengan C, A dengan C. nah bingungkan? Makanya Model juga jadi bingung mau ngebaca gimana ini prediksi. Kwkwkkwk

Masih gak ngarti juga? klik di sini untuk study casenya ya saya sudah tulis materinya secara terpisah.

Penting

**Jika model linear yang kita buat ternyata lolos semua `uji asumsi`, maka model tersebut cukup baik. Kita tinggal menimbang angka-angka parameter goodness of fit dari model untuk menentukan apakah model ini sudah cukup baik dalam membuat prediksi.**

Study case

Study case ini akan kita ambil contoh dari kehidupan sehari hari. data set di ambil dari sini

Package yang di gunakan adalah :

library(readxl)
library(readr)
library(stats)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.3     ✔ purrr     1.0.2
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dplyr)
library(car)
## Loading required package: carData
## 
## Attaching package: 'car'
## 
## The following object is masked from 'package:dplyr':
## 
##     recode
## 
## The following object is masked from 'package:purrr':
## 
##     some
library(lmtest)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## 
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(MASS)
## 
## Attaching package: 'MASS'
## 
## The following object is masked from 'package:dplyr':
## 
##     select
library(ggplot2)
library(corrplot)
## corrplot 0.92 loaded
library(lmtest)
library(broom)
library(MLmetrics)
## 
## Attaching package: 'MLmetrics'
## 
## The following object is masked from 'package:base':
## 
##     Recall

Regresi Linear Sederhana

Laporan Analisis Regresi Linear Sederhana: Pengaruh Jumlah Jam Belajar Terhadap Nilai Ujian

Pendahuluan

Regresi linear sederhana adalah teknik statistik yang digunakan untuk memahami hubungan antara satu variabel independen dengan satu variabel dependen. Dalam laporan ini, kami akan menganalisis apakah ada hubungan antara jumlah jam belajar dengan nilai ujian mahasiswa. Variabel independen dalam analisis ini adalah jumlah jam belajar (X), sedangkan variabel dependen adalah nilai ujian (Y).

Data set

#membuat contoh data set
set.seed(123)
Jambelajar= round(runif(50, min = 5, max = 20))
Nilai = round(Jambelajar*2+rnorm(50, mean = 0, sd = 1))
data_regresi = data.frame(Jambelajar, Nilai)
str(data_regresi)
## 'data.frame':    50 obs. of  2 variables:
##  $ Jambelajar: num  9 17 11 18 19 6 13 18 13 12 ...
##  $ Nilai     : num  16 35 22 35 39 12 26 37 27 25 ...

Model

Model_regsed = lm(Nilai~Jambelajar, data = data_regresi)
summary(Model_regsed)
## 
## Call:
## lm(formula = Nilai ~ Jambelajar, data = data_regresi)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.23982 -0.18238 -0.03558  0.76018  2.06654 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -0.24526    0.42499  -0.577    0.567    
## Jambelajar   2.02553    0.03158  64.146   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.969 on 48 degrees of freedom
## Multiple R-squared:  0.9885, Adjusted R-squared:  0.9882 
## F-statistic:  4115 on 1 and 48 DF,  p-value: < 2.2e-16

dari hasil summary di atas menunjukan bahwa B0 = Intercept, dan B1=jambelajar artinya dapat kita bentuk model persamaan sebagai berikut :

**Nilai = 0.37+1.97*Jambelajar**

ggplot(data_regresi, aes(x = Jambelajar, y= Nilai))+
         geom_point()+
         geom_smooth(method = "lm", se = FALSE, color = "red")+
         labs(x = "Jam Belajar", y = "Nilai")+
  theme_minimal()+
  theme(plot.background = element_rect(fill = "lightblue") )+
  theme(plot.title = element_text(hjust = 0.5))+
        ggtitle("Scatter Plot with Linear Regression Line")
## `geom_smooth()` using formula = 'y ~ x'

dari plot di atas ngeri kali regresinya kek benar. mari kita buktikan.

Asumsi Model

apakah model kita sudah bagus???

summary(Model_regsed)
## 
## Call:
## lm(formula = Nilai ~ Jambelajar, data = data_regresi)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.23982 -0.18238 -0.03558  0.76018  2.06654 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -0.24526    0.42499  -0.577    0.567    
## Jambelajar   2.02553    0.03158  64.146   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.969 on 48 degrees of freedom
## Multiple R-squared:  0.9885, Adjusted R-squared:  0.9882 
## F-statistic:  4115 on 1 and 48 DF,  p-value: < 2.2e-16

Goodness of fit dari model

  • R-Square

0.989 ini adalah angka yang fantastis, sangat ngeri regresinya sangat kuat.

  • P-Value

2.2 artinya > 0.05, maka bisa kita asumsikan bahwa model kita cukup signifikan.

  • MSE
MSE(Model_regsed$fitted.values, data_regresi$Nilai)
## [1] 0.901325

Nilainya cukup fantastis, mendekati angka 0, sehingga bisa di pastikan data kita akurat.

Normality of redusial

hist(Model_regsed$residuals)

Sekarang saya lakukan uji kenormalan dengan uji shapiro.test():

shapiro.test(Model_regsed$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  Model_regsed$residuals
## W = 0.95064, p-value = 0.03625

Residual dari model regresi linear berdistribusi normal. nilai p value > 0.05.

kenapa pakai Shapiro?? yes benar karna sampelnya hanya 50. kalau lebih dari 50 maka? ya menggunakan kolmogorof.

# pakai ini kalau sample > 50
ks.test(Model_regsed$residuals, "pnorm", mean = mean(Model_regsed$residuals), sd =sd(Model_regsed$residuals))
## Warning in ks.test.default(Model_regsed$residuals, "pnorm", mean =
## mean(Model_regsed$residuals), : ties should not be present for the
## Kolmogorov-Smirnov test
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  Model_regsed$residuals
## D = 0.18198, p-value = 0.0729
## alternative hypothesis: two-sided

itu ada warningnya,, kwkkwk tidak untuk Kolmogorov kwkwkkw

Liniarity cek

plot(Model_regsed)

Plot 1 di atas terlihat bentuk dari liniearitasnya.

kita gunakan uji korelasi untuk cek.

cor.test(data_regresi$Jambelajar, data_regresi$Nilai)
## 
##  Pearson's product-moment correlation
## 
## data:  data_regresi$Jambelajar and data_regresi$Nilai
## t = 64.146, df = 48, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9897802 0.9967318
## sample estimates:
##       cor 
## 0.9942179
hipotesis 1 di terima, artinya uji liniarity lolos uji.. yeyyyyy

homoscedacity

Apa maksud dari homoscedasticity? Artinya error tidak memiliki pola. Sedangkan jika heteroscedasticity artinya error-nya berpola. Kalau terdapat heteroscedasticity, kemungkinan ada outlier yang harus dibuang.

Plot error dan nilai aktualnya:

plot(Model_regsed$residuals, data_regresi$Nilai)

Uji statistiknya dengan function bptest() dari library(lmtest).

bptest(Model_regsed)
## 
##  studentized Breusch-Pagan test
## 
## data:  Model_regsed
## BP = 0.19338, df = 1, p-value = 0.6601

H0 di terima : Kesimpulan:

Lolos uji homoscedasticity!

Multicoloniarity

#multico = vif(Model_regsed)

eror tuh nah loh, gimna dah itu, karena ini menggunakan Regresi linier sederhana, maka uji multikolinearits ga perlu di uji gaes.. why? ya kan hanya ada 1 varaible dependen dan Independen. jadi VIP di gunakan ketika data lebih dari 3 variable yak..

FINAL

Karena smua uji berhasil di lewati dengan baik, maka model kita siap di gunakangaes.. akowkaowkaow


Regresi Liniar Berganda

Contoh study case adalah tentang :

Laporan Analisis Regresi Linear Berganda: Pengaruh Jumlah Jam Belajar dan Jumlah Persiapan Ujian Terhadap Nilai Ujian

Dataset

Data di buat hanya sebagai contoh saja.

set.seed(57)
# Membuat contoh variable random
Jumlah_jam_belajar = round(runif(50, min = 10, max = 40))
Jumlah_persiapan_ujian = round(runif(50, min = 5, max = 20))
Nilai_ujian = 50 + 1.5* Jumlah_jam_belajar + 2*Jumlah_persiapan_ujian + rnorm(50, mean = 0, sd = 5)

# Menggabungkan data
regresi_berganda = data.frame(Jumlah_jam_belajar, Jumlah_persiapan_ujian, Nilai_ujian)
str(regresi_berganda)
## 'data.frame':    50 obs. of  3 variables:
##  $ Jumlah_jam_belajar    : num  17 25 11 15 32 30 39 21 27 20 ...
##  $ Jumlah_persiapan_ujian: num  10 16 13 6 13 16 20 6 18 9 ...
##  $ Nilai_ujian           : num  100.5 120.4 92.4 91.7 132.3 ...

Model

head(regresi_berganda, 5)
##   Jumlah_jam_belajar Jumlah_persiapan_ujian Nilai_ujian
## 1                 17                     10   100.52802
## 2                 25                     16   120.38593
## 3                 11                     13    92.36010
## 4                 15                      6    91.66238
## 5                 32                     13   132.26191
Model_reggan = lm(Nilai_ujian ~ Jumlah_jam_belajar+Jumlah_persiapan_ujian, data = regresi_berganda)
summary(Model_reggan)
## 
## Call:
## lm(formula = Nilai_ujian ~ Jumlah_jam_belajar + Jumlah_persiapan_ujian, 
##     data = regresi_berganda)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -9.0652 -3.8078  0.2333  3.1430 11.1449 
## 
## Coefficients:
##                        Estimate Std. Error t value Pr(>|t|)    
## (Intercept)            49.02666    2.71244   18.07   <2e-16 ***
## Jumlah_jam_belajar      1.55951    0.07219   21.60   <2e-16 ***
## Jumlah_persiapan_ujian  1.98753    0.14995   13.26   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.921 on 47 degrees of freedom
## Multiple R-squared:  0.9302, Adjusted R-squared:  0.9273 
## F-statistic: 313.3 on 2 and 47 DF,  p-value: < 2.2e-16
ggplot(data = regresi_berganda, aes(x = Jumlah_jam_belajar, y = Nilai_ujian))+
  geom_point(aes(color = Jumlah_persiapan_ujian), size = 3, alpha = 0.7)+
  geom_smooth(method = "lm", formula = y ~ x, se = FALSE, color = "lightgreen")+
  labs(title = "Regresi Linear Berganda", x = "Variable belajar", y = "Nilai")+
  annotate("text", x = max(regresi_berganda$Jumlah_jam_belajar), y = min(regresi_berganda$Nilai_ujian), label = "Nilai Ujian = 49.02 + 1.56 * jam belajar + 1.99 * persiapan", hjust = 1, vjust =0)

Persamaan Regresinya adalah : Nilai Ujian = 49.02 + 1.56 * jam belajar + 1.99 * persiapan

Asumsi Model

apakah model kita sudah bagus???

Goodness of fit dari model

  • R-Square

Multiple R-squared: 0.9302, nilainya gege brokkk

  • P-Value

P-value > 0.05, heu heu heu cukup signifikan.

  • MSE
MSE(Model_reggan$fitted.values, regresi_berganda$Nilai_ujian)
## [1] 22.76646

angkanya agak besar ya gan jdi model kita so so gitu kyaknya..

Normality of redusial

hist(Model_reggan$residuals)

shapiro.test(Model_reggan$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  Model_reggan$residuals
## W = 0.98106, p-value = 0.5976

Residual berdistribusi normal.

Liniarity cek

plot(Model_reggan,1)

dari plot di atas sebenarnya sudah terlihat bahwa plot residual menunjukkan pola acak yang homogen sepanjang garis horizontal, itu menunjukkan bahwa asumsi linearity terpenuhi. Namun, jika terdapat pola atau struktur dalam plot residual, itu menunjukkan ketidaklinearan dalam hubungan.

kita juga bisa menguji dengan uji korelasi antara

corrplot(cor(regresi_berganda, method = "pearson"), method = "circle", type = "full", bg = "lightblue")

terlihat bahwa corelasinya cukup buruk sehingga uji linearity bisa di asumsikan lulus uji.

homoscedacity

Apa maksud dari homoscedasticity? Artinya error tidak memiliki pola. Sedangkan jika heteroscedasticity artinya error-nya berpola. Kalau terdapat heteroscedasticity, kemungkinan ada outlier yang harus dibuang.

Plot error dan nilai aktualnya:

plot(Model_reggan$residuals, regresi_berganda$Nilai_ujian)

statistiknya dengan function bptest() dari library(lmtest).

bptest(Model_reggan)
## 
##  studentized Breusch-Pagan test
## 
## data:  Model_reggan
## BP = 1.4442, df = 2, p-value = 0.4857

H0 di terima : Kesimpulan:

Lolos uji homoscedasticity!

Multicoloniarity

vif(Model_reggan)
##     Jumlah_jam_belajar Jumlah_persiapan_ujian 
##               1.000807               1.000807

Nilai vif yang baik harus < 10 ketika vif > 10 maka harus ada variable yang di eliminasi atau di lakukan feature engineering (membuat variabel baru dari variabel-variabel yang ada).

Karena nilai vif nya < 10 maka Multico aman.

Kesimpulan

Model cukp baik

Regresi Logistik

Laporan Analisis Regresi Logistik: Prediksi Kategori Kelulusan Berdasarkan Jumlah Jam Belajar dan Jumlah Persiapan Ujian

Dataset

set.seed(123)
Jmlh_jam_bljr = round(runif(100, min = 10, max = 40))
Jmlh_prsn_bljr = round(runif(100, min = 5, max = 20))
Prob_kelulusan = plogis(-5+0.1*Jmlh_jam_bljr+0.2*Jmlh_prsn_bljr)
kategori = ifelse(runif(100) < Prob_kelulusan, "lulus", "Tidak lulus")

regresi_logistik = data.frame(Jmlh_jam_bljr, Jmlh_prsn_bljr, kategori)
regresi_logistik$kategori = ifelse(regresi_logistik$kategori == "lulus", 1, 0)
str(regresi_logistik)
## 'data.frame':    100 obs. of  3 variables:
##  $ Jmlh_jam_bljr : num  19 34 22 36 38 11 26 37 27 24 ...
##  $ Jmlh_prsn_bljr: num  14 10 12 19 12 18 19 14 11 7 ...
##  $ kategori      : num  1 0 0 1 1 0 1 1 1 1 ...

Model

Model_reglog = glm(kategori ~ Jmlh_jam_bljr+Jmlh_prsn_bljr, family = binomial, data = regresi_logistik)
summary(Model_reglog)
## 
## Call:
## glm(formula = kategori ~ Jmlh_jam_bljr + Jmlh_prsn_bljr, family = binomial, 
##     data = regresi_logistik)
## 
## Coefficients:
##                Estimate Std. Error z value Pr(>|z|)    
## (Intercept)    -5.91846    1.34775  -4.391 1.13e-05 ***
## Jmlh_jam_bljr   0.11743    0.03063   3.834 0.000126 ***
## Jmlh_prsn_bljr  0.24596    0.06784   3.625 0.000288 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 138.47  on 99  degrees of freedom
## Residual deviance: 109.18  on 97  degrees of freedom
## AIC: 115.18
## 
## Number of Fisher Scoring iterations: 4

LS0tDQp0aXRsZTogIlJlZ3Jlc2kgTGluZWFyIg0KYXV0aG9yOiAiQWxiYW5pIg0KZGF0ZTogIjIwMjQtMDMtMTciDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGxpZ2h0Ym94OiB0cnVlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHRydWUNCi0tLQ0KDQojIFJlZ3Jlc2kgTGluZWFyDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMvQWRtaW5pc3RyYXRvci9Eb3dubG9hZHMvbGluZWFyLXJlZ3Jlc3Npb24ucG5nIikNCmBgYA0KDQoqKk1hcmkga2l0YSBtZW5jb2JhIG1lbWFoYW1pIG1hdGVyaSBpbmkgZGVuZ2FuIGJlYmVyYXBhIHBlcnRhbnlhYW4qKg0KDQojIyBQZW5kYWh1bHVhbg0KDQotIEFwYXNpaCByZWdyZXNpIGl0dT8gDQoNClJlZ3Jlc2kgYWRhbGFoIG1ldG9kZSB5YW5nIGRpZ3VuYWthbiB1bnR1ayBtZW1haGFtaSBkYW4gbWVtb2RlbGthbiBodWJ1bmdhbiBhbnRhcmEgc2F0dSBhdGF1IGxlYmloIHZhcmlhYmVsIGluZGVwZW5kZW4gKHZhcmlhYmVsIHByZWRpa3RvcikgZGFuIHNhdHUgdmFyaWFiZWwgZGVwZW5kZW4gKHZhcmlhYmVsIHJlc3BvbnMpLiAgDQoNCi0gS2FwYW4gUmVncmVzaSBpdHUgZGkgdGVtdWthbj8gDQoNCioiRWggYnVzZXQgbmFueWEgdWRhaCBrZWsgcGVydGFueWFhbiBheWFuZyBzZWxpbmdrdWggYXBhIG5nZ2FrLCwga2xhbyBiaXNhIG5hbnlhIHlhbmcgcGVudGluZyBwZW50aW5nIGFqYSBkYWgga3dra3drLi4iKg0KDQotIEJpc2Ega2FzaWggY29udG9oIFJlZ3Jlc2kgZGFsYW0ga2VoaWR1cGFuIHNlaGFyaSBoYXJpPw0KDQoqIm9rZSBpbmkgY3VrdXAgYmVyIGJvYm90IioNCg0KQ29udG9obnlhIGFkYWxhaCBrZXRpa2Ega2l0YSBpbmdpbiBtZW1vZGVsa2FuIGFwYWthaCBzZW1ha2luIGB0aW5nZ2kgZHVpZCBqYWphbmAgc2VtYWFraW4gdGluZ2dpIHB1bGEgYGthc2loIHNheWFuZ2A/DQoNCk5haCBpbmkgY29udG9oIGFqYSBzaWggeWEga3drd2sgeWFuZyBqb21ibG8gaGFyYXAgYmVyc2FiYXIuDQoNCi0gS2FwYW4gUmVncmVzaSBpdHUgZGkgZ3VuYWthbj8NCg0KUmVncmVzaSBpbmkgamVuaXNueWEgYWRhIGJlYmVyYXBhIGRhbiBkaWd1bmFrYW4ga2V0aWthIHZhcmlhYmxlIG55YSBiZXJiZWRhLCwNCg0KLS0tDQoNCiMjIEplbmlzIEplbmlzIFJlZ3Jlc2kgZGFuIENPbnRvaG55YQ0KDQpQYWRhIG1hdGVyaSBpbmkga2l0YSBha2FuIGZva3VzIGRpIDMgamVuaXMgeWFpdHUgYFJlZ3Jlc2kgTGluaWFyIFNlZGVyaGFuYWAsIGBSZWdyZXNpIExpbmlhciBCZXJnYW5kYWAgZGFuIGBSZWdyZXNpIExvZ2lzdGlrYA0KDQojIyMgUmVncmVzaSBMaW5pYXIgU2VkZXJoYW5hDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL0FkbWluaXN0cmF0b3IvRG93bmxvYWRzL0dhbWJhci01MS1BbmFsaXNpcy1yZWdyZXNpLWxpbmllci1zZWRlcmhhbmEtYmVyZGFzYXJrYW4tZGF0YS1wZW5lbGl0aWFuLVdpYm93by0yMDEzLnBuZyIpDQpgYGANCg0KRGFsYW0gcmVncmVzaSBsaW5lYXIgc2VkZXJoYW5hLCB0ZXJkYXBhdCBzYXR1IHZhcmlhYmVsIGluZGVwZW5kZW4gZGFuIHNhdHUgdmFyaWFiZWwgZGVwZW5kZW4uIE1vZGVsIHJlZ3Jlc2kgbGluZWFyIHNlZGVyaGFuYSBkaXdha2lsaSBvbGVoIHBlcnNhbWFhbiBnYXJpcyBsdXJ1cyAobGluZWFyKSwgc2VwZXJ0aQ0KDQpgeT1teCtjYA0KDQp5PW14K2MsIGRpIG1hbmEgeSBhZGFsYWggdmFyaWFiZWwgZGVwZW5kZW4sIHggYWRhbGFoIHZhcmlhYmVsIGluZGVwZW5kZW4sIG0gYWRhbGFoIGtvZWZpc2llbiBrZW1pcmluZ2FuLCBkYW4gYyBhZGFsYWggaW50ZXJjZXB0LiANCg0KQ29udG9obnlhIGFkYWxhaCA6IA0KDQotIE1pc2Fsa2FuIGtpdGEgYmVrZXJqYSBkaSBzZWJ1YWggcGVydXNhaGFhbiBkYW4gaW5naW4gbWVtYWhhbWkgaHVidW5nYW4gYW50YXJhIGJpYXlhIGlrbGFuIHlhbmcgZGloYWJpc2thbiBkYWxhbSBzdWF0dSBwZXJpb2RlIGRlbmdhbiBqdW1sYWggcGVuanVhbGFuIHByb2R1ayBBbmRhLiAgDQoNCi0gS2l0YSBpbmdpbiBtZWxpaGF0IGh1YnVuZ2FuIGFudGFyYSBidWRnZXQgZmlsbSBNQ1UgbWVtcGVuZ2FydWhpIGRhbiBtZW5nYWtpYmF0a2FuIGJveF9vZmZpY2Ugc2VjYXJhIHBvc2l0aWYgZGFuIGt1YXQgDQoNCi0gSW5naW4gbWVtcHJlZGlrc2kgUXR5IHBlbmp1YWxhbiBkYXJpIGtlbmFpa2FuIGhhcmdhLiBBcGFrYWggc2VtYWtpbiB0aW5nZ2kgaGFyZ2FueWEgbWFrYSBha2FuIHNlbWFraW4gc2VkaWtpdCB5YW5nIGJlbGk/IA0KDQojIyMgUmVncmVzaSBMaW5pYXIgQmVyZ2FuZGENCg0KYGBge3IsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMvQWRtaW5pc3RyYXRvci9Eb3dubG9hZHMvbXVsdGlwbGUtcmVncmVzc2lvbi1pbi1yLWdyYXBoLTEud2VicCIpDQpgYGANCg0KUmVncmVzaSBsaW5lYXIgYmVyZ2FuZGEgYWRhbGFoIGplbmlzIGFuYWxpc2lzIHJlZ3Jlc2kgeWFuZyBtZWxpYmF0a2FuIGxlYmloIGRhcmkgc2F0dSB2YXJpYWJlbCBpbmRlcGVuZGVuIHVudHVrIG1lbXByZWRpa3NpIHZhcmlhYmVsIGRlcGVuZGVuLiBEYWxhbSByZWdyZXNpIGxpbmVhciBiZXJnYW5kYSwga2l0YSBtZW5jb2JhIG1lbW9kZWxrYW4gaHVidW5nYW4gYW50YXJhIHNhdHUgdmFyaWFiZWwgZGVwZW5kZW4gZGVuZ2FuIGR1YSBhdGF1IGxlYmloIHZhcmlhYmVsIGluZGVwZW5kZW4uIE1vZGVsIHJlZ3Jlc2kgbGluZWFyIGJlcmdhbmRhIHVtdW1ueWEgZGl3YWtpbGkgb2xlaCBwZXJzYW1hYW4gYmVyaWt1dDogDQoNCnk9YjArYjF4MStiMngyK+KApitibnhuK/CdnIANCg0KeT1iMCArYjEgeDEgK2IyIHgyICvigKYrYm4geG4gK861IA0KDQpDb250b2hueWEgOiAgDQoNCi0gU2VidWFoIHBlcnVzYWhhYW4gbWludW1hbiBpbmdpbiBtZW1haGFtaSBmYWt0b3ItZmFrdG9yIGFwYSB5YW5nIG1lbXBlbmdhcnVoaSBwZW5qdWFsYW4gcHJvZHVrIG1lcmVrYSBkaSBwYXNhciB0ZXJ0ZW50dS4gTWVyZWthIG1lbWlsaWtpIGRhdGEgcGVuanVhbGFuICh2YXJpYWJlbCBkZXBlbmRlbiksIGhhcmdhIHByb2R1aywgcHJvbW9zaSBpa2xhbiwgZGFuIGN1YWNhICh2YXJpYWJlbCBpbmRlcGVuZGVuKS4gDQoNCi0gUGVydXNhaGFhbiBtZW5nZ3VuYWthbiByZWdyZXNpIGxpbmVhciBiZXJnYW5kYSB1bnR1ayBtZW1vZGVsa2FuIGh1YnVuZ2FuIGFudGFyYSBwZW5qdWFsYW4gcHJvZHVrIGRlbmdhbiBoYXJnYSwgcHJvbW9zaSBpa2xhbiwgZGFuIGN1YWNhLiAgDQoNCi0gU2VvcmFuZyBwZW5lbGl0aSBpbmdpbiBtZW1haGFtaSBmYWt0b3ItZmFrdG9yIHlhbmcgbWVtcGVuZ2FydWhpIHRla2FuYW4gZGFyYWggc2VzZW9yYW5nLiBEaWEgbWVtaWxpa2kgZGF0YSB0ZWthbmFuIGRhcmFoICh2YXJpYWJlbCBkZXBlbmRlbiksIHRpbmdrYXQgYWt0aXZpdGFzIGZpc2lrLCBwb2xhIG1ha2FuLCBkYW4gdXNpYSAodmFyaWFiZWwgaW5kZXBlbmRlbikuIA0KDQotIFBlbmVsaXRpIG1lbmdndW5ha2FuIHJlZ3Jlc2kgbGluZWFyIGJlcmdhbmRhIHVudHVrIG1lbW9kZWxrYW4gaHVidW5nYW4gYW50YXJhIHRla2FuYW4gZGFyYWggZGVuZ2FuIHRpbmdrYXQgYWt0aXZpdGFzIGZpc2lrLCBwb2xhIG1ha2FuLCBkYW4gdXNpYS4gIA0KDQoNCioqKlBlbnRpbmcgOiBSZWdyZXNpIGxpbmVhciBzZWRlcmhhbmEgdnMgYmVyZ2FuZGEgZGkgYmVkYWthbiBkYXJpIGp1bWFsaCB2YXJpYWJsZW55YSoqKi4NCg0KDQojIyMgUmVncmVzaSBMb2dpc3Rpaw0KDQpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9BZG1pbmlzdHJhdG9yL0Rvd25sb2Fkcy9TLWN1cnZlLjM2ZGUzYzY5NGNhZmU5N2VmNGUzOTFlZDI2YTVjYjBiMzU3ZjYzMTYucG5nIikNCmBgYA0KDQpSZWdyZXNpIGxvZ2lzdGlrIGFkYWxhaCBtZXRvZGUgc3RhdGlzdGlrIHlhbmcgZGlndW5ha2FuIHVudHVrIG1lbW9kZWxrYW4gaHVidW5nYW4gYW50YXJhIHNhdHUgYXRhdSBsZWJpaCB2YXJpYWJlbCBpbmRlcGVuZGVuIChwcmVkaWt0b3IpIGRlbmdhbiB2YXJpYWJlbCBkZXBlbmRlbiBiaW5lciAoZGljaG90b21vdXMpLCB5YW5nIG1lbWlsaWtpIGR1YSBrYXRlZ29yaSBhdGF1IGhhc2lsLiBUdWp1YW5ueWEgYWRhbGFoIHVudHVrIG1lbXByZWRpa3NpIHByb2JhYmlsaXRhcyBrZWphZGlhbiBzdWF0dSBrZWphZGlhbiB0ZXJ0ZW50dSAoYmlhc2FueWEgZGl3YWtpbGkgb2xlaCBrYXRlZ29yaSAxKSBiZXJkYXNhcmthbiBuaWxhaS1uaWxhaSB2YXJpYWJlbCBpbmRlcGVuZGVuLiBSZWdyZXNpIGxvZ2lzdGlrIGFkYWxhaCBhbGF0IHlhbmcgdW11bSBkaWd1bmFrYW4gZGFsYW0gYW5hbGlzaXMgZGF0YSBkaSBiZXJiYWdhaSBiaWRhbmcsIHRlcm1hc3VrIGlsbXUgc29zaWFsLCBrZWRva3RlcmFuLCBlcGlkZW1pb2xvZ2ksIGRhbiBiaXNuaXMuIA0KDQpDb250b2ggcGVuZXJhcGFuIHJlZ3Jlc2kgbG9naXN0aWsgdGVybWFzdWsgcHJlZGlrc2kgcHJvYmFiaWxpdGFzIHNlc2VvcmFuZyBtZW5nZW1iYW5na2FuIHBlbnlha2l0IHRlcnRlbnR1IGJlcmRhc2Fya2FuIGZha3Rvci1mYWt0b3IgcmlzaWtvIHNlcGVydGkgdXNpYSwgamVuaXMga2VsYW1pbiwgZGFuIHJpd2F5YXQgbWVyb2tvazsgYXRhdSBtZW1wcmVkaWtzaSBwcm9iYWJpbGl0YXMgcGVsYW5nZ2FuIG1lbWJlbGkgcHJvZHVrIHRlcnRlbnR1IGJlcmRhc2Fya2FuIGthcmFrdGVyaXN0aWsgZGVtb2dyYWZpcyBtZXJla2EgZGFuIHBlcmlsYWt1IHBlbWJlbGlhbiBzZWJlbHVtbnlhLiAoc3Ryb2tlIHByZWRpY3Rpb24pIA0KDQojIyMgUmVncmVzaSBOb25MaW5lYXINCg0KUmVncmVzaSBub24tbGluZWFyIGFkYWxhaCBqZW5pcyBhbmFsaXNpcyByZWdyZXNpIGRpIG1hbmEgaHVidW5nYW4gYW50YXJhIHZhcmlhYmVsIGluZGVwZW5kZW4gZGFuIHZhcmlhYmVsIGRlcGVuZGVuIHRpZGFrIGRhcGF0IGRpamVsYXNrYW4gZGVuZ2FuIHBlcnNhbWFhbiBnYXJpcyBsdXJ1cy4gU2ViYWxpa255YSwgaHVidW5nYW4gdGVyc2VidXQgZGlqZWxhc2thbiBkZW5nYW4gZnVuZ3NpIG1hdGVtYXRpa2EgeWFuZyBsZWJpaCBrb21wbGVrcywgc2VwZXJ0aSBwb2xpbm9taWFsLCBla3Nwb25lbnNpYWwsIGxvZ2FyaXRtaWssIHNpZ21vaWQsIGF0YXUgZnVuZ3NpIGxhaW5ueWEgeWFuZyB0aWRhayBsaW5lYXIuIA0KDQpDb250b2g6IFByZWRpa3NpIFBlcnR1bWJ1aGFuIFBlbmdndW5hIEFwbGlrYXNpIFNlbHVsZXIgDQoNCkRlc2tyaXBzaSBLYXN1czogU2VidWFoIHBlcnVzYWhhYW4gcGVuZ2VtYmFuZyBhcGxpa2FzaSBzZWx1bGVyIGluZ2luIG1lbXByZWRpa3NpIHBlcnR1bWJ1aGFuIHBlbmdndW5hIGFwbGlrYXNpIG1lcmVrYSBzZWlyaW5nIGRlbmdhbiB3YWt0dS4gTWVyZWthIG1lbWlsaWtpIGRhdGEgaGlzdG9yaXMgdGVudGFuZyBqdW1sYWggcGVuZ2d1bmEgYWt0aWYgaGFyaWFuICh2YXJpYWJlbCBkZXBlbmRlbikgc2VsYW1hIGJlYmVyYXBhIGJ1bGFuLiANCg0KTW9kZWwgUmVncmVzaSBOb24tbGluZWFyOiBQZXJ1c2FoYWFuIG1lbmdndW5ha2FuIHJlZ3Jlc2kgbm9uLWxpbmVhciB1bnR1ayBtZW1vZGVsa2FuIHBlcnR1bWJ1aGFuIHBlbmdndW5hIGFwbGlrYXNpLiBNZXJla2EgbWVtaWxpaCBtb2RlbCBwZXJ0dW1idWhhbiBsb2dpc3RpayB5YW5nIHVtdW0gZGlndW5ha2FuIGRhbGFtIGthc3VzIHNlcGVydGkgaW5pLiANCg0KSW50ZXJwcmV0YXNpOiBEZW5nYW4gbWVuZ2d1bmFrYW4gbW9kZWwgcmVncmVzaSBub24tbGluZWFyIGxvZ2lzdGlrLCBwZXJ1c2FoYWFuIGRhcGF0IG1lbXByZWRpa3NpIHBlcnR1bWJ1aGFuIHBlbmdndW5hIGFwbGlrYXNpIG1lcmVrYSBzZWlyaW5nIHdha3R1LiBNZXJla2EgZGFwYXQgbWVtcGVya2lyYWthbiBwdW5jYWsgcGVydHVtYnVoYW4gKEwpLCBsYWp1IHBlcnR1bWJ1aGFuIChrKSwgZGFuIHRpdGlrIHRlbmdhaCBwZXJ0dW1idWhhbiAodDApLiBJbmZvcm1hc2kgaW5pIGRhcGF0IG1lbWJhbnR1IHBlcnVzYWhhYW4gdW50dWsgbWVuZ2F0dXIgc3RyYXRlZ2kgcGVtYXNhcmFuLCBhbG9rYXNpIHN1bWJlciBkYXlhLCBkYW4gcGVuZ2FtYmlsYW4ga2VwdXR1c2FuIGJpc25pcyBsYWlubnlhLiANCg0KKioqaW5pIHRpZGFrIGFrYW4gZGkgYmFoYXMga2VtYmFsaWtlIHRvcGlrIHNheWFuZyBrdWgsIGtpdGEgYWthbiBiYWhhcyAzIGplbmlzIFJlZ3Jlc2kgc2FqYSoqKg0KDQojIyMgUmVncmVzaSBUaW1lIFNlcmllcyANCg0KUmVncmVzaSB0aW1lIHNlcmllcyBhZGFsYWggdGVrbmlrIGFuYWxpc2lzIHlhbmcgZGlndW5ha2FuIHVudHVrIG1lbW9kZWxrYW4gaHVidW5nYW4gYW50YXJhIHNhdHUgYXRhdSBsZWJpaCB2YXJpYWJlbCBkZW5nYW4gd2FrdHUgKHZhcmlhYmVsIGluZGVwZW5kZW4pIGRhbiB2YXJpYWJlbCB5YW5nIGRpYW1hdGkgc2VwYW5qYW5nIHBlcmlvZGUgd2FrdHUgdGVydGVudHUgKHZhcmlhYmVsIGRlcGVuZGVuKS4gVHVqdWFubnlhIGFkYWxhaCB1bnR1ayBtZW1haGFtaSBkYW4gbWVtcHJlZGlrc2kgcGVyaWxha3UgYXRhdSB0cmVuIGRhcmkgZGF0YSB0aW1lIHNlcmllcyBiZXJkYXNhcmthbiBpbmZvcm1hc2kgd2FrdHUgc2ViZWx1bW55YS4gDQoNCioqKkluaSBha2FuIGRpIGJhaGFzIGRhbGFtIG1hdGVyaSB0aW1lIHNlcmllcyBhbmFseXNpcyoqKi4gDQoNCiMjIyBSZWdyZXNpIFJpZGdlIGRhbiBMYXNzbyANCg0KUmVncmVzaSBSaWRnZSBkYW4gTGFzc28gYWRhbGFoIGR1YSBtZXRvZGUgcmVndWxhcmlzYXNpIHlhbmcgZGlndW5ha2FuIGRhbGFtIHJlZ3Jlc2kgbGluZWFyIHVudHVrIG1lbmdhdGFzaSBtYXNhbGFoIG92ZXJmaXR0aW5nIGRhbiBtZW5pbmdrYXRrYW4ga2luZXJqYSBtb2RlbCBkZW5nYW4gbWVuZ29udHJvbCBrb21wbGVrc2l0YXNueWEuIA0KDQoqKippbmkgdGlkYWsgYWthbiBkaSBiYWhhcyBrZW1iYWxpa2UgdG9waWsgc2F5YW5nIGt1aCwga2l0YSBha2FuIGJhaGFzIDMgamVuaXMgUmVncmVzaSBzYWphKioqDQoNCi0tLQ0KDQojIyBBc3Vtc2kgUmVncmVzaQ0KDQpBc3Vtc2kgUmVncmVzaSBhZGFsYWggcGFyYW1hdGVyIHlhbmcgaGFydXMga2l0YSBsYWx1aSB1bnR1ayAgbWVuZ3VrdXIgc2ViYWlrbWFuYSBSZWdyZXNpIGtpdGEgZGFuIGFwYWthaCBtb2RlbCBraXRhIHN1ZGFoIGN1a3VwIG1lbXVhc2thbj8gDQoNCmphbHVyIGluaSBoYXJ1cyBkaSBwYXN0aWthbiBtZW1udWhpIGFzdW1zaSBhZ2FyIG1vZGVsIGtpdGE/Pw0KDQpZZXNzcywgTW9kZWwga2l0YSBiYWlrLiBzZWJhaWsgYWtobGFrIFJhc3VsLg0KDQojIyMgR29vZG5lc3Mgb2YgZml0IGRhcmkgbW9kZWwgDQoNClBhcmFtZXRlciBgR29vZG5lc3Mgb2YgZml0YCBkYXJpIG1vZGVsIGJlcnVwYTogIA0KDQojIyMjIFItU3F1YXJlZCANCg0KLSBSLVNxdWFyZWQgYWRhbGFoIHVrdXJhbiBzdGF0aXN0aWsgeWFuZyBtZW5nZ2FtYmFya2FuIHNlYmVyYXBhIGJhaWsgbW9kZWwgcmVncmVzaSBsaW5lYXIgY29jb2sgZGVuZ2FuIGRhdGEgeWFuZyBkaWFtYXRpLiANCg0KLSBOaWxhaSBSLVNxdWFyZWQgYmVya2lzYXIgYW50YXJhIDAgaGluZ2dhIDEsIGRpIG1hbmEgc2VtYWtpbiB0aW5nZ2kgbmlsYWlueWEsIHNlbWFraW4gYmFpayBtb2RlbG55YS4gDQoNCi0gUi1TcXVhcmVkIG1lbmd1a3VyIHNlYmVyYXBhIGJlc2FyIHZhcmlhc2kgZGFsYW0gdmFyaWFiZWwgZGVwZW5kZW4geWFuZyBkYXBhdCBkaWplbGFza2FuIG9sZWggdmFyaWFiZWwgaW5kZXBlbmRlbiBkYWxhbSBtb2RlbC4gRGVuZ2FuIGthdGEgbGFpbiwgUi1TcXVhcmVkIG1lbnVuanVra2FuIHBlcnNlbnRhc2UgdmFyaWFzaSBkYWxhbSB2YXJpYWJlbCBkZXBlbmRlbiB5YW5nIGRhcGF0IGRpamVsYXNrYW4gb2xlaCBtb2RlbCByZWdyZXNpLiBNaXNhbG55YSwgamlrYSBSLVNxdWFyZWQgYWRhbGFoIDAsNSwgaW5pIGJlcmFydGkgNTAlIGRhcmkgdmFyaWFzaSBkYWxhbSB2YXJpYWJlbCBkZXBlbmRlbiBkYXBhdCBkaWplbGFza2FuIG9sZWggbW9kZWwuIA0KDQotIE5hbXVuLCBwZW50aW5nIHVudHVrIGRpaW5nYXQgYmFod2EgUi1TcXVhcmVkIHRpZGFrIG1lbnVuanVra2FuIHNlYmFiIGRhbiBha2liYXQsIGRhbiBuaWxhaW55YSBiaXNhIG1lbmluZ2thdCBoYW55YSBrYXJlbmEgbWVuYW1iYWhrYW4gdmFyaWFiZWwgaW5kZXBlbmRlbiwgYmFoa2FuIGppa2EgdmFyaWFiZWwgdGVyc2VidXQgdGlkYWsgbWVtaWxpa2kgaHVidW5nYW4ga2F1c2FsIGRlbmdhbiB2YXJpYWJlbCBkZXBlbmRlbi4gDQoNCg0KIyMjIyBQLXZhbHVlIA0KDQotIFAtdmFsdWUgYWRhbGFoIHVrdXJhbiB5YW5nIGRpZ3VuYWthbiB1bnR1ayBtZW5lbnR1a2FuIHNpZ25pZmlrYW5zaSBzdGF0aXN0aWsgZGFyaSBrb2VmaXNpZW4gZGFsYW0gbW9kZWwgcmVncmVzaSBhdGF1IGVmZWsgdmFyaWFiZWwgaW5kZXBlbmRlbiB0ZXJoYWRhcCB2YXJpYWJlbCBkZXBlbmRlbi4gDQoNCi0gTmlsYWkgUC12YWx1ZSBtZW51bmp1a2thbiBwcm9iYWJpbGl0YXMgYmFod2Ega29lZmlzaWVuIG5vbCBhdGF1IHRpZGFrIGFkYSBlZmVrLiANCg0KLSBTZWNhcmEgdW11bSwgamlrYSBQLXZhbHVlIGt1cmFuZyBkYXJpIG5pbGFpIGFscGhhIHlhbmcgdGVsYWggZGl0ZXRhcGthbiAoYmlhc2FueWEgMCwwNSksIG1ha2Ega29lZmlzaWVuIGRpYW5nZ2FwIHNpZ25pZmlrYW4gc2VjYXJhIHN0YXRpc3RpayBkYW4ga2l0YSBkYXBhdCBtZW5vbGFrIGhpcG90ZXNpcyBub2wgKGhpcG90ZXNpcyBiYWh3YSBrb2VmaXNpZW4gYWRhbGFoIG5vbCkuIA0KDQotIEppa2EgUC12YWx1ZSBsZWJpaCBiZXNhciBkYXJpIG5pbGFpIGFscGhhLCBtYWthIGtvZWZpc2llbiBkaWFuZ2dhcCB0aWRhayBzaWduaWZpa2FuIHNlY2FyYSBzdGF0aXN0aWssIHlhbmcgYmVyYXJ0aSBraXRhIGdhZ2FsIG1lbm9sYWsgaGlwb3Rlc2lzIG5vbC4gDQoNCi0gRGFsYW0ga29udGVrcyBnb29kbmVzcyBvZiBmaXQsIFAtdmFsdWUganVnYSBkYXBhdCBkaWd1bmFrYW4gdW50dWsgbWVuaWxhaSBzaWduaWZpa2Fuc2kga2VzZWx1cnVoYW4gbW9kZWwuIFNlYnVhaCBQLXZhbHVlIHlhbmcga2VjaWwgbWVudW5qdWtrYW4gYmFod2EgbW9kZWwgc2VjYXJhIGtlc2VsdXJ1aGFuIHNpZ25pZmlrYW4gc2VjYXJhIHN0YXRpc3Rpay4gDQoNCiMjIyMgTWVhbiBTcXVhcmVkIEVycm9yIChNU0UpIA0KDQotIE1lYW4gU3F1YXJlZCBFcnJvciAoTVNFKSBhZGFsYWggdWt1cmFuIHN0YXRpc3RpayB5YW5nIG1lbmd1a3VyIHJhdGEtcmF0YSBkYXJpIGt1YWRyYXQgcGVyYmVkYWFuIGFudGFyYSBuaWxhaSB5YW5nIGRpcHJlZGlrc2kgb2xlaCBtb2RlbCByZWdyZXNpIGRhbiBuaWxhaSB5YW5nIGRpYW1hdGkgZGFyaSB2YXJpYWJlbCBkZXBlbmRlbi4gDQoNCi0gTVNFIGRpZ3VuYWthbiB1bnR1ayBtZW5nZXZhbHVhc2kgc2ViZXJhcGEgYmFpayBtb2RlbCByZWdyZXNpIG1lbXBlcmtpcmFrYW4gbmlsYWkgeWFuZyBzZWJlbmFybnlhLiBTZW1ha2luIGtlY2lsIG5pbGFpIE1TRSwgc2VtYWtpbiBiYWlrIG1vZGVsbnlhLiANCg0KLSBEYWxhbSBiZWJlcmFwYSBrYXN1cywgYWthciBrdWFkcmF0IGRhcmkgTVNFIChSb290IE1lYW4gU3F1YXJlZCBFcnJvciwgUk1TRSkgc2VyaW5nIGRpZ3VuYWthbiBzZWJhZ2FpIHVrdXJhbiB5YW5nIGxlYmloIGludHVpdGlmIGthcmVuYSBtZW1pbGlraSB1bml0IHlhbmcgc2FtYSBkZW5nYW4gdmFyaWFiZWwgZGVwZW5kZW4uIA0KDQoNCkNhcmEgbGlhdG55YSBiaXNhIGRlbmdhbiBgc3VtbWFyeShuYW1hIG1vZGVsIHJlZ3Jlc2kpYC4gDQoNCiMjIyBOb3JtYWxpdHkgb2YgUmVzaWR1YWwgDQoNCk1lbmdlY2VrIGFwYWthaCBlcm9ybnlhIGJlcmRpc3RyaWJ1c2kgbm9ybWFsPyANCg0KVWppIGhpcG90ZXNpc255YSBhZGFsYWggOiANCg0KSDAgOiByZXNpZHVhbCBiZXJkaXN0cmlidXNpIG5vcm1hbC4gDQoNCkgxIDogcmVzaWR1YWwgdGlkYWsgYmVyZGlzdHJpYnVzaSBub3JtYWwgDQoNCkppa2EgUCB2YWx1ZSA8IDAuMDUgdG9sYWsgSDAgKHVqaSBkZW5nYW4gc2hhcGlybyBhdGF1IGtvbG1vZ29yb3YpIGthcGFuIG1lbmdndW5ha2FuIHNhbGFoIHNhdHUgZGFyaSBrZWR1YSB1amkgaW5pPyB0ZXJnYW50dW5nIGRhcmkganVtbGFoIG4gYXRhdSBzYW1wbGUgdWppLCA8NTAgZ3VuYWthbiBzaGFwaXJvIGRhbiA+NTAgZ3VuYWthbiBrb2xtb2dvcm92IHN1ZGFoIHNheWEgYmFoYXMgW2RpIHNpbmldKGh0dHBzOi8vcnB1YnMuY29tL2FsYmFuaTg4L05vcm1hbGl0eV9jaGVjaykNCg0KQXN1bXNpIEluaSBoYXJ1cyBub3JtYWwgeWEsIGtlbmFwYT8gDQoNCkFzdW1zaSBkaXN0cmlidXNpIG5vcm1hbCBkYXJpIHJlc2lkdWFsIHBlbnRpbmcga2FyZW5hIG1lbXVuZ2tpbmthbiBraXRhIHVudHVrIG1lbGFrdWthbiBpbmZlcmVuc2kgc3RhdGlzdGlrIHlhbmcgYWt1cmF0LCBzZXBlcnRpIG1lbmdoaXR1bmcgaW50ZXJ2YWwga2VwZXJjYXlhYW4gZGFuIG1lbGFrdWthbiBwZW5ndWppYW4gaGlwb3Rlc2lzLiBLZXRpa2EgcmVzaWR1YWwgYmVyZGlzdHJpYnVzaSBub3JtYWwsIGtpdGEgZGFwYXQgeWFraW4gYmFod2EgZXN0aW1hc2kga29lZmlzaWVuIGRhbiBzdGF0aXN0aWsgaW5mZXJlbnNpYWwgbGFpbm55YSBiZXJvcGVyYXNpIGRlbmdhbiBiZW5hci4gDQoNCiMjIyBMaW5lYXJpdHkgQ2hlY2sgDQoNCmNlayBsaW5lYXJpdHkgZGVuZ2FuIHBsb3QgZGVuZ2FuIHNpbnRha3NtZWxpaGF0IHBsb3QgcmVzaWR1YWwgZGFuIGZpdHRlZCB2YWx1ZXMgZGFyaSBtb2RlbCANCiANCmBwbG90KG1vZGVsLDEpYA0KDQpVamkgaGlwb3Rlc2lzOiANCg0KYEgwYCA6IFRpZGFrIGxpbmVhciANCg0KYEgxYCA6IExpbmVhciANCg0KSmlrYSBgUCB2YWx1ZWAgYDwgMC4wNWAsIHRvbGFrIEgwIA0KDQpVamkga29yZWxhc2kgbWVuZ2d1bmFrYW4gYGNvci50ZXN0KClgIHVudHVrIHZhcmlhYmVsIHByZWRpa3RvciANCg0KQXN1bXNpbnlhIGF0YXUgaGFzaWwgZGFyaSBVamkga29yZWxhc2kgaGFydXMgYmFpaywgbWVza2lwdW4gaWRlYWxueWEga2l0YSBpbmdpbiBodWJ1bmdhbiBhbnRhcmEgdmFyaWFiZWwgZGFsYW0gbW9kZWwgcmVncmVzaSBiZXJzaWZhdCBsaW5lYXIsIGFkYW55YSBzZWRpa2l0IGtldGlkYWtsaW5pZXJhbiB0aWRhayBzZWxhbHUgbWVtYnVhdCBtb2RlbCB0ZXJzZWJ1dCBidXJ1ay4gUGVudGluZyB1bnR1ayBtZW1wZXJ0aW1iYW5na2FuIGtvbnRla3MgYW5hbGlzaXMsIHR1anVhbiwgZGFuIGtldGVyYmF0YXNhbiBkYXRhIGtldGlrYSBtZW5nZXZhbHVhc2kgbGluZWFyaXRhcyBkYWxhbSBtb2RlbCByZWdyZXNpLg0KDQojIyMgVWppIEhvbW9zY2VkYXNjaXR5IA0KDQpBcGEgbWFrc3VkIGRhcmkgaG9tb3NjZWRhc3RpY2l0eT8gQXJ0aW55YSBlcnJvciB0aWRhayBtZW1pbGlraSBwb2xhLiBTZWRhbmdrYW4gamlrYSBoZXRlcm9zY2VkYXN0aWNpdHkgYXJ0aW55YSBlcnJvci1ueWEgYmVycG9sYS4gS2FsYXUgdGVyZGFwYXQgaGV0ZXJvc2NlZGFzdGljaXR5LCBrZW11bmdraW5hbiBhZGEgb3V0bGllciB5YW5nIGhhcnVzIGRpYnVhbmcuIA0KDQpVamkgaGlwb3Rlc2lzOiANCg0KSDAgOiBtb2RlbCBob21vc2NlZGFzdGljaXR5IA0KDQpIMSA6IG1vZGVsIGhldGVyb3NjZWRhc3RpY2l0eSANCg0KSmlrYSBQIHZhbHVlIDwgMC4wNSwgdG9sYWsgSDAgDQoNCiANCg0KVWppIHN0YXRpc3Rpa255YSBkZW5nYW4gZnVuY3Rpb24gYGJwdGVzdCgpYCBkYXJpIGBsaWJyYXJ5KGxtdGVzdClgLiANCg0KYEJwdGVzdChtb2RlbClgDQoNCktlbmFwYSB1amkgaW5pIGhhcnVzIGRpIGxha3VrYW4/IE1hc2loIGJpbmd1bmcgZXV5LCwgDQoNCk9rZSBnYW4uLiBKYWRpIGdpbmkgYmF5YW5nIGthbiBqaWthIHJlc2lkdWFsbnkgYW1lbWlsaWtpIHBvbGEsIGFydGlueWEgYmFyYWlibGUgZXJvcm55YSBwdW55YSBwb2xhIGxpbmVhcml0YXMuIE5haCBrYW4gYXJ0aW55YSByZXNpZHVhbCBraXRhIG1hbGFoIGphZGkgcHJlZGlrdG9yIHlhbmcgYmFydSBrYW4/IExhbHUgYXBhIGd1bmFueWEgbW9kZWwga2l0YSBzZWJlbHVtbnlhPyAgbmFoIGtlYmF5YW5nIG5nZ2E/IFRoYXTigJlzIHdoeSBFcm9yIGF0YXUgUmVzaWR1YWwgaGFydXMgaG9tb3NlZGFzaWNpdHkuIA0KDQojIyMgVWppIE11bHRpY29sbGluZWFyaXR5IA0KDQpOYWgsIHVqaSB5YW5nIGluaSBiYXJ1IGJpc2EgYWthbiBraXRhIGxha3VrYW4gamlrYSBraXRhIG1lbGFrdWthbiBgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb25gLCB5YWtuaSBzYWF0IHZhcmlhYmVsIHByZWRpa3Rvcm55YSBsZWJpaCBkYXJpIHNhdHUuIEtpdGEgdGlkYWsgbWF1IGthbGF1IHZhcmlhYmVsIHByZWRpa3RvciBkaSBtb2RlbCBraXRhIGl0dSBzYWxpbmcgYmVycGVuZ2FydWggKGRlcGVuZGVuKSBvaCBpeWEgYmFoYXMgdGVudGFuZyBEZXBlbmRlbiBkYW4gSW5kZXBlbmRlbiB2YXJpYWJsZSBzdWRhaCBwZXJuYWggc2F5YSB0dWxpcyBbRGkgc2luaV0oaHR0cHM6Ly9ycHVicy5jb20vYWxiYW5pODgvRGVwZW5kZW4tZGFuLUluZGVwZW5kZW4pLiANCg0KVW50dWsgbWVsYWt1a2FubnlhLCBraXRhIHBlcmx1IG1lbmd1amlueWEgbWVuZ2d1bmFrYW4gbmlsYWkgdmlmLiANCg0KQ2VrIGRlbmdhbiBmdW5nc2kgYHZpZigpYCBkYXJpIGBsaWJyYXJ5KGNhcilgIHVudHVrIG1lbmdldGFodWkgdmFyaWFiZWwtdmFyaWFiZWwgbWFuYSB5YW5nIHRpZGFrIGJpc2EgZGl0b2xlcmFuc2kgbWVuamFkaSBzZWJ1YWggcHJlZGlrdG9yLiANCg0KICBgdmlmKG1vZGVsKWAgDQoNCk5pbGFpIHZpZiB5YW5nIGJhaWsgaGFydXMgYDwgMTBgIGtldGlrYSB2aWYgYD4gMTBgIG1ha2EgaGFydXMgYWRhIHZhcmlhYmxlIHlhbmcgZGkgZWxpbWluYXNpIGF0YXUgZGkgbGFrdWthbiBmZWF0dXJlIGVuZ2luZWVyaW5nIChtZW1idWF0IHZhcmlhYmVsIGJhcnUgZGFyaSB2YXJpYWJlbC12YXJpYWJlbCB5YW5nIGFkYSkuIA0KDQpTZWJlbnRhcnJycnJyIA0KDQpJbmkgc2F5YSBiaW5ndW5nIHNheSwsIG1ha3N1ZCBkYXJpIE11bHRpY29saW5lYXJpdGFzIGJhZ2FpbWFuYT8/IA0KDQpBcmdnaGhoaGhoaCANCg0KTmFoIG1ha3N1ZCBkYXJpIE11bHRpY29saW5lYXJpdGFzIGFkYWxhaCB2YXJpYWJsZSB2YXJpYWJsZSBzYWxpbmcgYmVydGFubmdhIGtvcmVsYXNpLiBDb250b2ggdmFyaWFibGUgQSBiZXJrb3JlbHNpIGRlbmdhbiBCLCBCIGRlbmdhbiBDLCBBIGRlbmdhbiBDLiBuYWggYmluZ3VuZ2thbj8gTWFrYW55YSBNb2RlbCBqdWdhIGphZGkgYmluZ3VuZyBtYXUgbmdlYmFjYSBnaW1hbmEgaW5pIHByZWRpa3NpLiBLd2t3a2t3ayANCg0KTWFzaWggZ2FrIG5nYXJ0aSBqdWdhPyBrbGlrIFtkaSBzaW5pXShodHRwczovL3JwdWJzLmNvbS9hbGJhbmk4OC9NdWx0aWtvbGluaWFyaXRhcykgdW50dWsgc3R1ZHkgY2FzZW55YSB5YSBzYXlhIHN1ZGFoIHR1bGlzIG1hdGVyaW55YSBzZWNhcmEgdGVycGlzYWguDQoNCiMjIyBQZW50aW5nDQoNCiAgICAqKkppa2EgbW9kZWwgbGluZWFyIHlhbmcga2l0YSBidWF0IHRlcm55YXRhIGxvbG9zIHNlbXVhIGB1amkgYXN1bXNpYCwgbWFrYSBtb2RlbCB0ZXJzZWJ1dCBjdWt1cCBiYWlrLiBLaXRhIHRpbmdnYWwgbWVuaW1iYW5nIGFuZ2thLWFuZ2thIHBhcmFtZXRlciBnb29kbmVzcyBvZiBmaXQgZGFyaSBtb2RlbCB1bnR1ayBtZW5lbnR1a2FuIGFwYWthaCBtb2RlbCBpbmkgc3VkYWggY3VrdXAgYmFpayBkYWxhbSBtZW1idWF0IHByZWRpa3NpLioqDQoNCi0tLQ0KDQojIFN0dWR5IGNhc2UNCg0KU3R1ZHkgY2FzZSBpbmkgYWthbiBraXRhIGFtYmlsIGNvbnRvaCBkYXJpIGtlaGlkdXBhbiBzZWhhcmkgaGFyaS4gZGF0YSBzZXQgZGkgYW1iaWwgW2Rhcmkgc2luaV0oKQ0KDQpQYWNrYWdlIHlhbmcgZGkgZ3VuYWthbiBhZGFsYWggOg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoc3RhdHMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGNhcikNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShNQVNTKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkoTUxtZXRyaWNzKQ0KYGBgDQoNCi0tLQ0KDQojIyBSZWdyZXNpIExpbmVhciBTZWRlcmhhbmENCg0KTGFwb3JhbiBBbmFsaXNpcyBSZWdyZXNpIExpbmVhciBTZWRlcmhhbmE6ICoqUGVuZ2FydWggSnVtbGFoIEphbSBCZWxhamFyIFRlcmhhZGFwIE5pbGFpIFVqaWFuKioNCg0KIyMjIFBlbmRhaHVsdWFuDQoNClJlZ3Jlc2kgbGluZWFyIHNlZGVyaGFuYSBhZGFsYWggdGVrbmlrIHN0YXRpc3RpayB5YW5nIGRpZ3VuYWthbiB1bnR1ayBtZW1haGFtaSBodWJ1bmdhbiBhbnRhcmEgc2F0dSB2YXJpYWJlbCBpbmRlcGVuZGVuIGRlbmdhbiBzYXR1IHZhcmlhYmVsIGRlcGVuZGVuLiBEYWxhbSBsYXBvcmFuIGluaSwga2FtaSBha2FuIG1lbmdhbmFsaXNpcyBhcGFrYWggYWRhIGh1YnVuZ2FuIGFudGFyYSBqdW1sYWggamFtIGJlbGFqYXIgZGVuZ2FuIG5pbGFpIHVqaWFuIG1haGFzaXN3YS4gVmFyaWFiZWwgaW5kZXBlbmRlbiBkYWxhbSBhbmFsaXNpcyBpbmkgYWRhbGFoIGp1bWxhaCBqYW0gYmVsYWphciAoWCksIHNlZGFuZ2thbiB2YXJpYWJlbCBkZXBlbmRlbiBhZGFsYWggbmlsYWkgdWppYW4gKFkpLg0KDQojIyMgRGF0YSBzZXQNCg0KYGBge3J9DQojbWVtYnVhdCBjb250b2ggZGF0YSBzZXQNCnNldC5zZWVkKDEyMykNCkphbWJlbGFqYXI9IHJvdW5kKHJ1bmlmKDUwLCBtaW4gPSA1LCBtYXggPSAyMCkpDQpOaWxhaSA9IHJvdW5kKEphbWJlbGFqYXIqMitybm9ybSg1MCwgbWVhbiA9IDAsIHNkID0gMSkpDQpkYXRhX3JlZ3Jlc2kgPSBkYXRhLmZyYW1lKEphbWJlbGFqYXIsIE5pbGFpKQ0Kc3RyKGRhdGFfcmVncmVzaSkNCmBgYA0KDQojIyMgTW9kZWwNCg0KYGBge3J9DQpNb2RlbF9yZWdzZWQgPSBsbShOaWxhaX5KYW1iZWxhamFyLCBkYXRhID0gZGF0YV9yZWdyZXNpKQ0Kc3VtbWFyeShNb2RlbF9yZWdzZWQpDQpgYGANCmRhcmkgaGFzaWwgc3VtbWFyeSBkaSBhdGFzIG1lbnVuanVrYW4gYmFod2EgYEIwYCA9IEludGVyY2VwdCwgZGFuIGBCMWA9amFtYmVsYWphciBhcnRpbnlhIGRhcGF0IGtpdGEgYmVudHVrIG1vZGVsIHBlcnNhbWFhbiBzZWJhZ2FpIGJlcmlrdXQgOg0KDQoqKk5pbGFpID0gMC4zNysxLjk3KmBKYW1iZWxhamFyYCoqDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGFfcmVncmVzaSwgYWVzKHggPSBKYW1iZWxhamFyLCB5PSBOaWxhaSkpKw0KICAgICAgICAgZ2VvbV9wb2ludCgpKw0KICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikrDQogICAgICAgICBsYWJzKHggPSAiSmFtIEJlbGFqYXIiLCB5ID0gIk5pbGFpIikrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAibGlnaHRibHVlIikgKSsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpKw0KICAgICAgICBnZ3RpdGxlKCJTY2F0dGVyIFBsb3Qgd2l0aCBMaW5lYXIgUmVncmVzc2lvbiBMaW5lIikNCmBgYA0KDQpkYXJpIHBsb3QgZGkgYXRhcyBuZ2VyaSBrYWxpIHJlZ3Jlc2lueWEga2VrIGJlbmFyLiBtYXJpIGtpdGEgYnVrdGlrYW4uDQoNCiMjIyBBc3Vtc2kgTW9kZWwNCmFwYWthaCBtb2RlbCBraXRhIHN1ZGFoIGJhZ3VzPz8/DQoNCmBgYHtyfQ0Kc3VtbWFyeShNb2RlbF9yZWdzZWQpDQpgYGANCg0KIyMjIyBHb29kbmVzcyBvZiBmaXQgZGFyaSBtb2RlbCANCg0KLSBSLVNxdWFyZQ0KDQowLjk4OSBpbmkgYWRhbGFoIGFuZ2thIHlhbmcgZmFudGFzdGlzLCBzYW5nYXQgbmdlcmkgcmVncmVzaW55YSBzYW5nYXQga3VhdC4NCg0KLSBQLVZhbHVlDQoNCjIuMiBhcnRpbnlhID4gMC4wNSwgbWFrYSBiaXNhIGtpdGEgYXN1bXNpa2FuIGJhaHdhIG1vZGVsIGtpdGEgY3VrdXAgc2lnbmlmaWthbi4NCg0KLSBNU0UNCg0KYGBge3J9DQpNU0UoTW9kZWxfcmVnc2VkJGZpdHRlZC52YWx1ZXMsIGRhdGFfcmVncmVzaSROaWxhaSkNCmBgYA0KDQpOaWxhaW55YSBjdWt1cCBmYW50YXN0aXMsIG1lbmRla2F0aSBhbmdrYSAwLCBzZWhpbmdnYSBiaXNhIGRpIHBhc3Rpa2FuIGRhdGEga2l0YSBha3VyYXQuDQoNCiMjIyMgTm9ybWFsaXR5IG9mIHJlZHVzaWFsDQoNCmBgYHtyfQ0KaGlzdChNb2RlbF9yZWdzZWQkcmVzaWR1YWxzKQ0KYGBgDQoNClNla2FyYW5nIHNheWEgbGFrdWthbiB1amkga2Vub3JtYWxhbiBkZW5nYW4gdWppIHNoYXBpcm8udGVzdCgpOg0KDQpgYGB7cn0NCnNoYXBpcm8udGVzdChNb2RlbF9yZWdzZWQkcmVzaWR1YWxzKQ0KYGBgDQpSZXNpZHVhbCBkYXJpIG1vZGVsIHJlZ3Jlc2kgbGluZWFyIGJlcmRpc3RyaWJ1c2kgbm9ybWFsLiBuaWxhaSBwIHZhbHVlID4gMC4wNS4NCg0Ka2VuYXBhIHBha2FpIFNoYXBpcm8/PyB5ZXMgYmVuYXIga2FybmEgIHNhbXBlbG55YSBoYW55YSA1MC4ga2FsYXUgbGViaWggZGFyaSA1MCBtYWthPyB5YSBtZW5nZ3VuYWthbiBrb2xtb2dvcm9mLg0KDQpgYGB7cn0NCiMgcGFrYWkgaW5pIGthbGF1IHNhbXBsZSA+IDUwDQprcy50ZXN0KE1vZGVsX3JlZ3NlZCRyZXNpZHVhbHMsICJwbm9ybSIsIG1lYW4gPSBtZWFuKE1vZGVsX3JlZ3NlZCRyZXNpZHVhbHMpLCBzZCA9c2QoTW9kZWxfcmVnc2VkJHJlc2lkdWFscykpDQpgYGANCml0dSBhZGEgd2FybmluZ255YSwsIGt3a2t3ayB0aWRhayB1bnR1ayBLb2xtb2dvcm92IGt3a3dra3cNCg0KIyMjIyBMaW5pYXJpdHkgY2VrDQoNCmBgYHtyfQ0KcGxvdChNb2RlbF9yZWdzZWQpDQpgYGANCg0KUGxvdCAxIGRpIGF0YXMgdGVybGloYXQgYmVudHVrIGRhcmkgbGluaWVhcml0YXNueWEuDQoNCmtpdGEgZ3VuYWthbiB1amkga29yZWxhc2kgdW50dWsgY2VrLg0KDQpgYGB7cn0NCmNvci50ZXN0KGRhdGFfcmVncmVzaSRKYW1iZWxhamFyLCBkYXRhX3JlZ3Jlc2kkTmlsYWkpDQpgYGANCg0KICAgIGhpcG90ZXNpcyAxIGRpIHRlcmltYSwgYXJ0aW55YSB1amkgbGluaWFyaXR5IGxvbG9zIHVqaS4uIHlleXl5eXkNCg0KIyMjIyBob21vc2NlZGFjaXR5DQoNCkFwYSBtYWtzdWQgZGFyaSBob21vc2NlZGFzdGljaXR5PyBBcnRpbnlhIGVycm9yIHRpZGFrIG1lbWlsaWtpIHBvbGEuIFNlZGFuZ2thbiBqaWthIGhldGVyb3NjZWRhc3RpY2l0eSBhcnRpbnlhIGVycm9yLW55YSBiZXJwb2xhLiBLYWxhdSB0ZXJkYXBhdCBoZXRlcm9zY2VkYXN0aWNpdHksIGtlbXVuZ2tpbmFuIGFkYSBvdXRsaWVyIHlhbmcgaGFydXMgZGlidWFuZy4NCg0KUGxvdCBlcnJvciBkYW4gbmlsYWkgYWt0dWFsbnlhOg0KDQpgYGB7cn0NCnBsb3QoTW9kZWxfcmVnc2VkJHJlc2lkdWFscywgZGF0YV9yZWdyZXNpJE5pbGFpKQ0KYGBgDQpVamkgc3RhdGlzdGlrbnlhIGRlbmdhbiBmdW5jdGlvbiBicHRlc3QoKSBkYXJpIGxpYnJhcnkobG10ZXN0KS4NCg0KYGBge3J9DQpicHRlc3QoTW9kZWxfcmVnc2VkKQ0KYGBgDQpIMCBkaSB0ZXJpbWEgOg0KS2VzaW1wdWxhbjoNCg0KICAgIExvbG9zIHVqaSBob21vc2NlZGFzdGljaXR5IQ0KDQoNCiMjIyMgTXVsdGljb2xvbmlhcml0eQ0KDQpgYGB7cn0NCiNtdWx0aWNvID0gdmlmKE1vZGVsX3JlZ3NlZCkNCmBgYA0KDQplcm9yIHR1aCBuYWggbG9oLCBnaW1uYSBkYWggaXR1LCBrYXJlbmEgaW5pIG1lbmdndW5ha2FuIFJlZ3Jlc2kgbGluaWVyIHNlZGVyaGFuYSwgbWFrYSB1amkgbXVsdGlrb2xpbmVhcml0cyBnYSBwZXJsdSBkaSB1amkgZ2Flcy4uIHdoeT8geWEga2FuIGhhbnlhIGFkYSAxIHZhcmFpYmxlIGRlcGVuZGVuIGRhbiBJbmRlcGVuZGVuLiBqYWRpIFZJUCBkaSBndW5ha2FuIGtldGlrYSBkYXRhIGxlYmloIGRhcmkgMyB2YXJpYWJsZSB5YWsuLg0KDQoNCiMjIyMgRklOQUwNCg0KS2FyZW5hIHNtdWEgdWppIGJlcmhhc2lsIGRpIGxld2F0aSBkZW5nYW4gYmFpaywgbWFrYSBtb2RlbCBraXRhIHNpYXAgZGkgZ3VuYWthbmdhZXMuLiBha293a2Fvd2thb3cgDQoNCi0tLQ0KDQojIyBSZWdyZXNpIExpbmlhciBCZXJnYW5kYQ0KDQpDb250b2ggc3R1ZHkgY2FzZSBhZGFsYWggdGVudGFuZyA6DQoNCkxhcG9yYW4gQW5hbGlzaXMgUmVncmVzaSBMaW5lYXIgQmVyZ2FuZGE6ICoqUGVuZ2FydWggSnVtbGFoIEphbSBCZWxhamFyIGRhbiBKdW1sYWggUGVyc2lhcGFuIFVqaWFuIFRlcmhhZGFwIE5pbGFpIFVqaWFuKioNCg0KIyMjIERhdGFzZXQNCkRhdGEgZGkgYnVhdCBoYW55YSBzZWJhZ2FpIGNvbnRvaCBzYWphLg0KDQpgYGB7cn0NCnNldC5zZWVkKDU3KQ0KIyBNZW1idWF0IGNvbnRvaCB2YXJpYWJsZSByYW5kb20NCkp1bWxhaF9qYW1fYmVsYWphciA9IHJvdW5kKHJ1bmlmKDUwLCBtaW4gPSAxMCwgbWF4ID0gNDApKQ0KSnVtbGFoX3BlcnNpYXBhbl91amlhbiA9IHJvdW5kKHJ1bmlmKDUwLCBtaW4gPSA1LCBtYXggPSAyMCkpDQpOaWxhaV91amlhbiA9IDUwICsgMS41KiBKdW1sYWhfamFtX2JlbGFqYXIgKyAyKkp1bWxhaF9wZXJzaWFwYW5fdWppYW4gKyBybm9ybSg1MCwgbWVhbiA9IDAsIHNkID0gNSkNCg0KIyBNZW5nZ2FidW5na2FuIGRhdGENCnJlZ3Jlc2lfYmVyZ2FuZGEgPSBkYXRhLmZyYW1lKEp1bWxhaF9qYW1fYmVsYWphciwgSnVtbGFoX3BlcnNpYXBhbl91amlhbiwgTmlsYWlfdWppYW4pDQpzdHIocmVncmVzaV9iZXJnYW5kYSkNCmBgYA0KDQojIyMgTW9kZWwNCg0KYGBge3J9DQpoZWFkKHJlZ3Jlc2lfYmVyZ2FuZGEsIDUpDQpgYGANCmBgYHtyfQ0KTW9kZWxfcmVnZ2FuID0gbG0oTmlsYWlfdWppYW4gfiBKdW1sYWhfamFtX2JlbGFqYXIrSnVtbGFoX3BlcnNpYXBhbl91amlhbiwgZGF0YSA9IHJlZ3Jlc2lfYmVyZ2FuZGEpDQpzdW1tYXJ5KE1vZGVsX3JlZ2dhbikNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IHJlZ3Jlc2lfYmVyZ2FuZGEsIGFlcyh4ID0gSnVtbGFoX2phbV9iZWxhamFyLCB5ID0gTmlsYWlfdWppYW4pKSsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBKdW1sYWhfcGVyc2lhcGFuX3VqaWFuKSwgc2l6ZSA9IDMsIGFscGhhID0gMC43KSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9IHkgfiB4LCBzZSA9IEZBTFNFLCBjb2xvciA9ICJsaWdodGdyZWVuIikrDQogIGxhYnModGl0bGUgPSAiUmVncmVzaSBMaW5lYXIgQmVyZ2FuZGEiLCB4ID0gIlZhcmlhYmxlIGJlbGFqYXIiLCB5ID0gIk5pbGFpIikrDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IG1heChyZWdyZXNpX2JlcmdhbmRhJEp1bWxhaF9qYW1fYmVsYWphciksIHkgPSBtaW4ocmVncmVzaV9iZXJnYW5kYSROaWxhaV91amlhbiksIGxhYmVsID0gIk5pbGFpIFVqaWFuID0gNDkuMDIgKyAxLjU2ICogamFtIGJlbGFqYXIgKyAxLjk5ICogcGVyc2lhcGFuIiwgaGp1c3QgPSAxLCB2anVzdCA9MCkNCmBgYA0KUGVyc2FtYWFuIFJlZ3Jlc2lueWEgYWRhbGFoIDoNCioqTmlsYWkgVWppYW4qKiBgPSA0OS4wMiArIDEuNTYgKiBqYW0gYmVsYWphciArIDEuOTkgKiBwZXJzaWFwYW5gDQoNCiMjIyBBc3Vtc2kgTW9kZWwNCmFwYWthaCBtb2RlbCBraXRhIHN1ZGFoIGJhZ3VzPz8/DQoNCiMjIyMgR29vZG5lc3Mgb2YgZml0IGRhcmkgbW9kZWwgDQoNCi0gUi1TcXVhcmUNCg0KTXVsdGlwbGUgUi1zcXVhcmVkOiAgMC45MzAyLCBuaWxhaW55YSBnZWdlIGJyb2traw0KDQotIFAtVmFsdWUNCg0KUC12YWx1ZSA+IDAuMDUsIGhldSBoZXUgaGV1IGN1a3VwIHNpZ25pZmlrYW4uDQoNCi0gTVNFDQoNCmBgYHtyfQ0KTVNFKE1vZGVsX3JlZ2dhbiRmaXR0ZWQudmFsdWVzLCByZWdyZXNpX2JlcmdhbmRhJE5pbGFpX3VqaWFuKQ0KYGBgDQphbmdrYW55YSBhZ2FrIGJlc2FyIHlhIGdhbiBqZGkgbW9kZWwga2l0YSBzbyBzbyBnaXR1IGt5YWtueWEuLg0KDQojIyMjIE5vcm1hbGl0eSBvZiByZWR1c2lhbA0KDQpgYGB7cn0NCmhpc3QoTW9kZWxfcmVnZ2FuJHJlc2lkdWFscykNCmBgYA0KYGBge3J9DQpzaGFwaXJvLnRlc3QoTW9kZWxfcmVnZ2FuJHJlc2lkdWFscykNCmBgYA0KUmVzaWR1YWwgYmVyZGlzdHJpYnVzaSBub3JtYWwuDQoNCiMjIyMgTGluaWFyaXR5IGNlaw0KDQpgYGB7cn0NCnBsb3QoTW9kZWxfcmVnZ2FuLDEpDQpgYGANCmRhcmkgcGxvdCBkaSBhdGFzIHNlYmVuYXJueWEgc3VkYWggdGVybGloYXQgYmFod2EgcGxvdCByZXNpZHVhbCBtZW51bmp1a2thbiBwb2xhIGFjYWsgeWFuZyBob21vZ2VuIHNlcGFuamFuZyBnYXJpcyBob3Jpem9udGFsLCBpdHUgbWVudW5qdWtrYW4gYmFod2EgYXN1bXNpIGxpbmVhcml0eSB0ZXJwZW51aGkuIE5hbXVuLCBqaWthIHRlcmRhcGF0IHBvbGEgYXRhdSBzdHJ1a3R1ciBkYWxhbSBwbG90IHJlc2lkdWFsLCBpdHUgbWVudW5qdWtrYW4ga2V0aWRha2xpbmVhcmFuIGRhbGFtIGh1YnVuZ2FuLg0KDQpraXRhIGp1Z2EgYmlzYSBtZW5ndWppIGRlbmdhbiB1amkga29yZWxhc2kgYW50YXJhIA0KDQpgYGB7cn0NCmNvcnJwbG90KGNvcihyZWdyZXNpX2JlcmdhbmRhLCBtZXRob2QgPSAicGVhcnNvbiIpLCBtZXRob2QgPSAiY2lyY2xlIiwgdHlwZSA9ICJmdWxsIiwgYmcgPSAibGlnaHRibHVlIikNCmBgYA0KDQp0ZXJsaWhhdCBiYWh3YSBjb3JlbGFzaW55YSBjdWt1cCBidXJ1ayBzZWhpbmdnYSB1amkgbGluZWFyaXR5IGJpc2EgZGkgYXN1bXNpa2FuIGx1bHVzIHVqaS4NCg0KIyMjIyBob21vc2NlZGFjaXR5DQoNCkFwYSBtYWtzdWQgZGFyaSBob21vc2NlZGFzdGljaXR5PyBBcnRpbnlhIGVycm9yIHRpZGFrIG1lbWlsaWtpIHBvbGEuIFNlZGFuZ2thbiBqaWthIGhldGVyb3NjZWRhc3RpY2l0eSBhcnRpbnlhIGVycm9yLW55YSBiZXJwb2xhLiBLYWxhdSB0ZXJkYXBhdCBoZXRlcm9zY2VkYXN0aWNpdHksIGtlbXVuZ2tpbmFuIGFkYSBvdXRsaWVyIHlhbmcgaGFydXMgZGlidWFuZy4NCg0KUGxvdCBlcnJvciBkYW4gbmlsYWkgYWt0dWFsbnlhOg0KYGBge3J9DQpwbG90KE1vZGVsX3JlZ2dhbiRyZXNpZHVhbHMsIHJlZ3Jlc2lfYmVyZ2FuZGEkTmlsYWlfdWppYW4pDQpgYGANCiBzdGF0aXN0aWtueWEgZGVuZ2FuIGZ1bmN0aW9uIGJwdGVzdCgpIGRhcmkgbGlicmFyeShsbXRlc3QpLg0KYGBge3J9DQpicHRlc3QoTW9kZWxfcmVnZ2FuKQ0KYGBgDQogSDAgZGkgdGVyaW1hIDoNCktlc2ltcHVsYW46DQoNCiAgICBMb2xvcyB1amkgaG9tb3NjZWRhc3RpY2l0eSENCg0KIyMjIyBNdWx0aWNvbG9uaWFyaXR5DQoNCmBgYHtyfQ0KdmlmKE1vZGVsX3JlZ2dhbikNCmBgYA0KTmlsYWkgdmlmIHlhbmcgYmFpayBoYXJ1cyBgPCAxMGAga2V0aWthIHZpZiBgPiAxMGAgbWFrYSBoYXJ1cyBhZGEgdmFyaWFibGUgeWFuZyBkaSBlbGltaW5hc2kgYXRhdSBkaSBsYWt1a2FuIGZlYXR1cmUgZW5naW5lZXJpbmcgKG1lbWJ1YXQgdmFyaWFiZWwgYmFydSBkYXJpIHZhcmlhYmVsLXZhcmlhYmVsIHlhbmcgYWRhKS4gDQoNCiAgICBLYXJlbmEgbmlsYWkgdmlmIG55YSA8IDEwIG1ha2EgTXVsdGljbyBhbWFuLg0KDQojIyMjIEtlc2ltcHVsYW4NCg0KICAgIE1vZGVsIGN1a3AgYmFpaw0KDQotLS0NCg0KIyMgUmVncmVzaSBMb2dpc3Rpaw0KDQpMYXBvcmFuIEFuYWxpc2lzIFJlZ3Jlc2kgTG9naXN0aWs6ICoqUHJlZGlrc2kgS2F0ZWdvcmkgS2VsdWx1c2FuIEJlcmRhc2Fya2FuIEp1bWxhaCBKYW0gQmVsYWphciBkYW4gSnVtbGFoIFBlcnNpYXBhbiBVamlhbioqDQoNCg0KIyMjIERhdGFzZXQNCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpKbWxoX2phbV9ibGpyID0gcm91bmQocnVuaWYoMTAwLCBtaW4gPSAxMCwgbWF4ID0gNDApKQ0KSm1saF9wcnNuX2JsanIgPSByb3VuZChydW5pZigxMDAsIG1pbiA9IDUsIG1heCA9IDIwKSkNClByb2Jfa2VsdWx1c2FuID0gcGxvZ2lzKC01KzAuMSpKbWxoX2phbV9ibGpyKzAuMipKbWxoX3Byc25fYmxqcikNCmthdGVnb3JpID0gaWZlbHNlKHJ1bmlmKDEwMCkgPCBQcm9iX2tlbHVsdXNhbiwgImx1bHVzIiwgIlRpZGFrIGx1bHVzIikNCg0KcmVncmVzaV9sb2dpc3RpayA9IGRhdGEuZnJhbWUoSm1saF9qYW1fYmxqciwgSm1saF9wcnNuX2JsanIsIGthdGVnb3JpKQ0KcmVncmVzaV9sb2dpc3RpayRrYXRlZ29yaSA9IGlmZWxzZShyZWdyZXNpX2xvZ2lzdGlrJGthdGVnb3JpID09ICJsdWx1cyIsIDEsIDApDQpzdHIocmVncmVzaV9sb2dpc3RpaykNCmBgYA0KDQojIyMgTW9kZWwNCg0KYGBge3J9DQpNb2RlbF9yZWdsb2cgPSBnbG0oa2F0ZWdvcmkgfiBKbWxoX2phbV9ibGpyK0ptbGhfcHJzbl9ibGpyLCBmYW1pbHkgPSBiaW5vbWlhbCwgZGF0YSA9IHJlZ3Jlc2lfbG9naXN0aWspDQpzdW1tYXJ5KE1vZGVsX3JlZ2xvZykNCmBgYA0KDQoNCi0tLS0NCg0K