Pendahuluan

Kemarin saya sudah menuliskan tentang dasar-dasar regresi namun hanya 3 materi saja, yaitu : Regresi linear sederhana, Regresi linear berganda & Regresi logistik. Materi ini akan saya coba jelaskan yang saya tau lebih dulu dari sampean. ohiya klik di sini untuk materi sebelumnya. kita akan mencoba membuat contoh data set untuk membuat model Regresi.

ohh iya literatur lain bisa di cek di sini

  • Regresi Linear
Jambelajar= round(runif(50, min = 5, max = 20))
Nilai = round(Jambelajar*2+rnorm(50, mean = 0, sd = 1))
data_Regsed = data.frame(Jambelajar, Nilai)

str(data_Regsed)
## 'data.frame':    50 obs. of  2 variables:
##  $ Jambelajar: num  10 9 9 6 11 14 5 11 11 19 ...
##  $ Nilai     : num  22 18 18 13 22 27 10 23 22 38 ...
  • Regresi logistik
set.seed(123)
Jmlh_jam_bljr = round(runif(100, min = 10, max = 40))
Jmlh_prsn_bljr = round(runif(100, min = 5, max = 20))
prob_lulus = plogis(-5 + 0.1 * Jmlh_jam_bljr + 0.2 * Jmlh_prsn_bljr)
Keterangann = ifelse(runif(100) < prob_lulus, "lulus", "tidak lulus")
# Data set
data_reglog =data.frame(Jmlh_jam_bljr, Jmlh_prsn_bljr, Keterangann)
data_reglog$Keterangann = ifelse(data_reglog$Keterangann == "lulus", 1, 0)
str(data_reglog)
## '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 ...
##  $ Keterangann   : num  1 0 0 1 1 0 1 1 1 1 ...

Regresi

Sebelum di lakukan Regresi berikut adalah beberapa hal yang harus di persiapkan.

Package

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
library(cowplot)
## 
## Attaching package: 'cowplot'
## 
## The following object is masked from 'package:lubridate':
## 
##     stamp
library(corrplot)
library(lattice)

Pemilihan Jenis Regresi

Nah ini adalah hal pertama yang harus di lakukan, jenis regresi di pilih sesuai dengan jenis datanya. saya tulis sebelumnya klik di sini. ku coba ringkas lagi.

Regresi linear Sederhana

Di gunakan ketika data yang di miliki hanya terdapat satu variabel independen dan satu variabel dependen.

Regresi linear Berganda

Analisis regresi yang melibatkan lebih dari satu variabel independen untuk memprediksi variabel dependen.

Regreli Logistik

Digunakan ketika data yang digunakan adalah data berbentuk Biner.Regresi untuk memprediksi probabilitas kejadian suatu kejadian tertentu (biasanya diwakili oleh kategori 1) berdasarkan nilai-nilai variabel independen.


Data Eksprolation

Kedua adalah Data eksplorasi data, ini bertujuan untuk membersihkan data dan memahami data secara menyeluruh.

Data preparation

Mencari data set, sudah ada di pendahuluan.

Data cleaning

Data cleaning bisa di cek di sini

  • Cek Missing value

  • Data duplicate

  • Check data type

Exploration

Sebaran data

plots = lapply(names(data_Regsed), function(var_x){
  p <- 
    ggplot(data_Regsed)+
    aes_string(var_x)+
    geom_density(lwd = 1, color = "darkorange")
})
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
plot_grid(plotlist = plots)

Korelasi

# Menghitung korelasi antar kolom
cor_matrix = round(cor(data_Regsed),2)
cor_matrix
##            Jambelajar Nilai
## Jambelajar       1.00  0.99
## Nilai            0.99  1.00
# Membuat plot antar korelasi
corrplot(cor_matrix,
         type = "lower",
         method = "color",
         tl.cex = 0.5,
         tl.col = "black",
)

corrplot(cor(data_reglog), method = "circle", type = "lower", number.cex = 0.5, tl.cex = 0.7, tl.col = "black", diag = FALSE)

Di tahap ini adalah tahap melihat beberapa asumsi yang harus di penuhi model regresi, yaitu : Multikolinearitas.

Membuat Model

Model Regresi linear

membuat model regresi linier

model_regresi_linear = lm(Nilai ~ ., data = data)

Model Regresi linear

Model_regresi_logistik <- glm(Nilai ~ ., family = binomial, data_Regsed) step(Model_regresi_logistik)

Evaluasi Model

Confusion Matrix

Evaluasi terhadap model klasifikasi dilakukan dengan membuat tabel klasifikasi antara kelas sebenarnya dengan kelas hasil prediksi dari model klasifikasi. Tabel klasifikasi ini biasa disebut dengan Confusion Matrix.

Confusion matrix dapat diartikan sebagai suatu alat yang memiliki fungsi untuk melakukan analisis apakah classifier tersebut baik dalam mengenali tuple dari kelas yang berbeda. Nilai dari True-Positive (TP) dan True-Negative (TN) memberikan informasi ketika classifier dalam melakukan klasifikasi data bernilai benar, sedangkan False-Positive (FP) dan False-Negative (FN) memberikan informasi ketika classifier salah dalam melakukan klasifikasi data (Han dan Kamber, 2011).

Pada performa klasifikasi akan dihitung akurasi, spesifisitas, sensitivitas dan AUC. Akurasi merupakan persentase classifier benar melakukan prediksi. Sensitivitas merupakan Persentase data positif yang diprediksi sebagai positif. Dan Spesifisitas merupakan Persentase data negatif diprediksi sebagai negatif (Faisal dan Nugrahadi, 2019).Sedangkan AUC adalah kinerja dari model klasifikasi.

ROC Plot

library(ROCR) pred<- prediction(predict.glm(credit.glm.final,german.credit.test),german.credit.test$class) perf <- performance(pred,“tpr”,“fpr”) plot(perf)

Penutup

Selanjutnya jika model sudah baik asumasi terpenuhi. maka model itu bisa kita jadikan sebagai alat prediksi, dengan menggunakan data set baru yang berisi variable yang sama dengan data set model. caranya adalah :

membuat prediksi dengan data baru dari model

predicted_values <- predict(model_reglog, newdata = new_data)

Evaluasi model

residuals <- true_values - predicted_values mse <- mean(residuals^2)

Plot model

plot(new_data\(X1, predicted_values, col = "red", pch = 16, xlab = "X1", ylab = "Predicted Y", main = "Model Regression Plot") points(new_data\)X1, true_values, col = “blue”, pch = 16) legend(“topleft”, legend = c(“Predicted Values”, “True Values”), col = c(“red”, “blue”), pch = 16)


LS0tDQp0aXRsZTogIlJFR1JFU0kgTEFOSlVUQU4iDQphdXRob3I6ICJBbGJhbmkiDQpkYXRlOiAiMjAyNC0wMy0xOSINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdGhlbWUgOiB1bml0ZWQNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBsaWdodGJveDogeWVzDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHRydWUNCi0tLQ0KDQojIFBlbmRhaHVsdWFuDQoNCktlbWFyaW4gc2F5YSBzdWRhaCBtZW51bGlza2FuIHRlbnRhbmcgZGFzYXItZGFzYXIgcmVncmVzaSBuYW11biBoYW55YSAzIG1hdGVyaSBzYWphLCB5YWl0dSA6IGBSZWdyZXNpIGxpbmVhciBzZWRlcmhhbmFgLCBgUmVncmVzaSBsaW5lYXIgYmVyZ2FuZGFgICYgYFJlZ3Jlc2kgbG9naXN0aWtgLiBNYXRlcmkgaW5pIGFrYW4gc2F5YSBjb2JhIGplbGFza2FuIHlhbmcgc2F5YSB0YXUgbGViaWggZHVsdSBkYXJpIHNhbXBlYW4uIG9oaXlhIFtrbGlrIGRpIHNpbmldKGh0dHBzOi8vcnB1YnMuY29tL2FsYmFuaTg4L1JlZ3Jlc2kpIHVudHVrIG1hdGVyaSBzZWJlbHVtbnlhLiBraXRhIGFrYW4gbWVuY29iYSBtZW1idWF0IGNvbnRvaCBkYXRhIHNldCB1bnR1ayBtZW1idWF0IG1vZGVsIFJlZ3Jlc2kuDQoNCm9oaCBpeWEgbGl0ZXJhdHVyIGxhaW4gYmlzYSBkaSBjZWsgW2RpIHNpbmldKGh0dHBzOi8vcnB1YnMuY29tL3JpemtpYS9zdGExMzgyLWFuYWxpc2lzLXJlZ3Jlc2kpDQoNCi0gUmVncmVzaSBMaW5lYXINCg0KYGBge3J9DQpKYW1iZWxhamFyPSByb3VuZChydW5pZig1MCwgbWluID0gNSwgbWF4ID0gMjApKQ0KTmlsYWkgPSByb3VuZChKYW1iZWxhamFyKjIrcm5vcm0oNTAsIG1lYW4gPSAwLCBzZCA9IDEpKQ0KZGF0YV9SZWdzZWQgPSBkYXRhLmZyYW1lKEphbWJlbGFqYXIsIE5pbGFpKQ0KDQpzdHIoZGF0YV9SZWdzZWQpDQpgYGANCg0KLSBSZWdyZXNpIGxvZ2lzdGlrDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0KSm1saF9qYW1fYmxqciA9IHJvdW5kKHJ1bmlmKDEwMCwgbWluID0gMTAsIG1heCA9IDQwKSkNCkptbGhfcHJzbl9ibGpyID0gcm91bmQocnVuaWYoMTAwLCBtaW4gPSA1LCBtYXggPSAyMCkpDQpwcm9iX2x1bHVzID0gcGxvZ2lzKC01ICsgMC4xICogSm1saF9qYW1fYmxqciArIDAuMiAqIEptbGhfcHJzbl9ibGpyKQ0KS2V0ZXJhbmdhbm4gPSBpZmVsc2UocnVuaWYoMTAwKSA8IHByb2JfbHVsdXMsICJsdWx1cyIsICJ0aWRhayBsdWx1cyIpDQojIERhdGEgc2V0DQpkYXRhX3JlZ2xvZyA9ZGF0YS5mcmFtZShKbWxoX2phbV9ibGpyLCBKbWxoX3Byc25fYmxqciwgS2V0ZXJhbmdhbm4pDQpkYXRhX3JlZ2xvZyRLZXRlcmFuZ2FubiA9IGlmZWxzZShkYXRhX3JlZ2xvZyRLZXRlcmFuZ2FubiA9PSAibHVsdXMiLCAxLCAwKQ0Kc3RyKGRhdGFfcmVnbG9nKQ0KYGBgDQoNCiMgUmVncmVzaQ0KDQpTZWJlbHVtIGRpIGxha3VrYW4gUmVncmVzaSBiZXJpa3V0IGFkYWxhaCBiZWJlcmFwYSBoYWwgeWFuZyBoYXJ1cyBkaSBwZXJzaWFwa2FuLg0KDQojIyBQYWNrYWdlDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShzdGF0cykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShsbXRlc3QpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShsbXRlc3QpDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeShNTG1ldHJpY3MpDQpsaWJyYXJ5KGNvd3Bsb3QpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShsYXR0aWNlKQ0KYGBgDQoNCiMjIFBlbWlsaWhhbiBKZW5pcyBSZWdyZXNpDQoNCk5haCBpbmkgYWRhbGFoIGhhbCBwZXJ0YW1hIHlhbmcgaGFydXMgZGkgbGFrdWthbiwgamVuaXMgcmVncmVzaSBkaSBwaWxpaCBzZXN1YWkgZGVuZ2FuIGplbmlzIGRhdGFueWEuIHNheWEgdHVsaXMgc2ViZWx1bW55YSBba2xpayBkaSBzaW5pXShodHRwczovL3JwdWJzLmNvbS9hbGJhbmk4OC9SZWdyZXNpKS4ga3UgY29iYSByaW5na2FzIGxhZ2kuDQoNCiMjIyBSZWdyZXNpIGxpbmVhciBTZWRlcmhhbmENCg0KRGkgZ3VuYWthbiBrZXRpa2EgZGF0YSB5YW5nIGRpIG1pbGlraSBoYW55YSB0ZXJkYXBhdCBzYXR1IHZhcmlhYmVsIGluZGVwZW5kZW4gZGFuIHNhdHUgdmFyaWFiZWwgZGVwZW5kZW4uDQoNCiMjIyBSZWdyZXNpIGxpbmVhciBCZXJnYW5kYQ0KDQpBbmFsaXNpcyByZWdyZXNpIHlhbmcgbWVsaWJhdGthbiBsZWJpaCBkYXJpIHNhdHUgdmFyaWFiZWwgaW5kZXBlbmRlbiB1bnR1ayBtZW1wcmVkaWtzaSB2YXJpYWJlbCBkZXBlbmRlbi4NCg0KIyMjIFJlZ3JlbGkgTG9naXN0aWsNCg0KRGlndW5ha2FuIGtldGlrYSBkYXRhIHlhbmcgZGlndW5ha2FuIGFkYWxhaCBkYXRhIGJlcmJlbnR1ayBCaW5lci5SZWdyZXNpIHVudHVrIG1lbXByZWRpa3NpIHByb2JhYmlsaXRhcyBrZWphZGlhbiBzdWF0dSBrZWphZGlhbiB0ZXJ0ZW50dSAoYmlhc2FueWEgZGl3YWtpbGkgb2xlaCBrYXRlZ29yaSAxKSBiZXJkYXNhcmthbiBuaWxhaS1uaWxhaSB2YXJpYWJlbCBpbmRlcGVuZGVuLg0KDQotLS0NCg0KIyMgRGF0YSBFa3Nwcm9sYXRpb24NCg0KS2VkdWEgYWRhbGFoIERhdGEgZWtzcGxvcmFzaSBkYXRhLCBpbmkgYmVydHVqdWFuIHVudHVrIG1lbWJlcnNpaGthbiBkYXRhIGRhbiBtZW1haGFtaSBkYXRhIHNlY2FyYSBtZW55ZWx1cnVoLg0KDQojIyMgRGF0YSBwcmVwYXJhdGlvbg0KDQpNZW5jYXJpIGRhdGEgc2V0LCBzdWRhaCBhZGEgZGkgcGVuZGFodWx1YW4uDQoNCiMjIyBEYXRhIGNsZWFuaW5nDQoNCkRhdGEgY2xlYW5pbmcgYmlzYSBkaSBjZWsgW2RpIHNpbmldKCJodHRwczovL3JwdWJzLmNvbS9hbGJhbmk4OC9kYXRhLWVrcGxvcmF0aW8tZmxvdyIpDQoNCi0gQ2VrIE1pc3NpbmcgdmFsdWUNCg0KLSBEYXRhIGR1cGxpY2F0ZQ0KDQotIENoZWNrIGRhdGEgdHlwZQ0KDQojIyBFeHBsb3JhdGlvbg0KDQojIyMgU2ViYXJhbiBkYXRhDQoNCmBgYHtyfQ0KcGxvdHMgPSBsYXBwbHkobmFtZXMoZGF0YV9SZWdzZWQpLCBmdW5jdGlvbih2YXJfeCl7DQogIHAgPC0gDQogICAgZ2dwbG90KGRhdGFfUmVnc2VkKSsNCiAgICBhZXNfc3RyaW5nKHZhcl94KSsNCiAgICBnZW9tX2RlbnNpdHkobHdkID0gMSwgY29sb3IgPSAiZGFya29yYW5nZSIpDQp9KQ0KDQpwbG90X2dyaWQocGxvdGxpc3QgPSBwbG90cykNCmBgYA0KDQojIyMgS29yZWxhc2kNCg0KYGBge3J9DQojIE1lbmdoaXR1bmcga29yZWxhc2kgYW50YXIga29sb20NCmNvcl9tYXRyaXggPSByb3VuZChjb3IoZGF0YV9SZWdzZWQpLDIpDQpjb3JfbWF0cml4DQpgYGANCmBgYHtyfQ0KIyBNZW1idWF0IHBsb3QgYW50YXIga29yZWxhc2kNCmNvcnJwbG90KGNvcl9tYXRyaXgsDQogICAgICAgICB0eXBlID0gImxvd2VyIiwNCiAgICAgICAgIG1ldGhvZCA9ICJjb2xvciIsDQogICAgICAgICB0bC5jZXggPSAwLjUsDQogICAgICAgICB0bC5jb2wgPSAiYmxhY2siLA0KKQ0KYGBgDQpgYGB7cn0NCmNvcnJwbG90KGNvcihkYXRhX3JlZ2xvZyksIG1ldGhvZCA9ICJjaXJjbGUiLCB0eXBlID0gImxvd2VyIiwgbnVtYmVyLmNleCA9IDAuNSwgdGwuY2V4ID0gMC43LCB0bC5jb2wgPSAiYmxhY2siLCBkaWFnID0gRkFMU0UpDQpgYGANCg0KRGkgdGFoYXAgaW5pIGFkYWxhaCB0YWhhcCBtZWxpaGF0IGJlYmVyYXBhIGFzdW1zaSB5YW5nIGhhcnVzIGRpIHBlbnVoaSBtb2RlbCByZWdyZXNpLCB5YWl0dSA6IGBNdWx0aWtvbGluZWFyaXRhc2AuDQoNCiMjIE1lbWJ1YXQgTW9kZWwNCg0KIyMjIE1vZGVsIFJlZ3Jlc2kgbGluZWFyDQoNCm1lbWJ1YXQgbW9kZWwgcmVncmVzaSBsaW5pZXINCg0KbW9kZWxfcmVncmVzaV9saW5lYXIgPSBsbShOaWxhaSB+IC4sIGRhdGEgPSBkYXRhKQ0KDQojIyMgTW9kZWwgUmVncmVzaSBsaW5lYXINCg0KTW9kZWxfcmVncmVzaV9sb2dpc3RpayA8LSBnbG0oTmlsYWkgfiAuLCBmYW1pbHkgPSBiaW5vbWlhbCwgZGF0YV9SZWdzZWQpDQpzdGVwKE1vZGVsX3JlZ3Jlc2lfbG9naXN0aWspDQoNCg0KIyMgRXZhbHVhc2kgTW9kZWwNCg0KIyMjIENvbmZ1c2lvbiBNYXRyaXgNCg0KRXZhbHVhc2kgdGVyaGFkYXAgbW9kZWwga2xhc2lmaWthc2kgZGlsYWt1a2FuIGRlbmdhbiBtZW1idWF0IHRhYmVsIGtsYXNpZmlrYXNpIGFudGFyYSBrZWxhcyBzZWJlbmFybnlhIGRlbmdhbiBrZWxhcyBoYXNpbCBwcmVkaWtzaSBkYXJpIG1vZGVsIGtsYXNpZmlrYXNpLiBUYWJlbCBrbGFzaWZpa2FzaSBpbmkgYmlhc2EgZGlzZWJ1dCBkZW5nYW4gQ29uZnVzaW9uIE1hdHJpeC4NCg0KQ29uZnVzaW9uIG1hdHJpeCBkYXBhdCBkaWFydGlrYW4gc2ViYWdhaSBzdWF0dSBhbGF0IHlhbmcgbWVtaWxpa2kgZnVuZ3NpIHVudHVrIG1lbGFrdWthbiBhbmFsaXNpcyBhcGFrYWggY2xhc3NpZmllciB0ZXJzZWJ1dCBiYWlrIGRhbGFtIG1lbmdlbmFsaSB0dXBsZSBkYXJpIGtlbGFzIHlhbmcgYmVyYmVkYS4gTmlsYWkgZGFyaSBUcnVlLVBvc2l0aXZlIChUUCkgZGFuIFRydWUtTmVnYXRpdmUgKFROKSBtZW1iZXJpa2FuIGluZm9ybWFzaSBrZXRpa2EgY2xhc3NpZmllciBkYWxhbSBtZWxha3VrYW4ga2xhc2lmaWthc2kgZGF0YSBiZXJuaWxhaSBiZW5hciwgc2VkYW5na2FuIEZhbHNlLVBvc2l0aXZlIChGUCkgZGFuIEZhbHNlLU5lZ2F0aXZlIChGTikgbWVtYmVyaWthbiBpbmZvcm1hc2kga2V0aWthIGNsYXNzaWZpZXIgc2FsYWggZGFsYW0gbWVsYWt1a2FuIGtsYXNpZmlrYXNpIGRhdGEgKEhhbiBkYW4gS2FtYmVyLCAyMDExKS4NCg0KUGFkYSBwZXJmb3JtYSBrbGFzaWZpa2FzaSBha2FuIGRpaGl0dW5nIGFrdXJhc2ksIHNwZXNpZmlzaXRhcywgc2Vuc2l0aXZpdGFzIGRhbiBBVUMuIEFrdXJhc2kgbWVydXBha2FuIHBlcnNlbnRhc2UgY2xhc3NpZmllciBiZW5hciBtZWxha3VrYW4gcHJlZGlrc2kuIFNlbnNpdGl2aXRhcyBtZXJ1cGFrYW4gUGVyc2VudGFzZSBkYXRhIHBvc2l0aWYgeWFuZyBkaXByZWRpa3NpIHNlYmFnYWkgcG9zaXRpZi4gRGFuIFNwZXNpZmlzaXRhcyBtZXJ1cGFrYW4gUGVyc2VudGFzZSBkYXRhIG5lZ2F0aWYgZGlwcmVkaWtzaSBzZWJhZ2FpIG5lZ2F0aWYgKEZhaXNhbCBkYW4gTnVncmFoYWRpLCAyMDE5KS5TZWRhbmdrYW4gQVVDIGFkYWxhaCBraW5lcmphIGRhcmkgbW9kZWwga2xhc2lmaWthc2kuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL0FkbWluaXN0cmF0b3IvRG93bmxvYWRzL1doYXRzQXBwIEltYWdlIDIwMjQtMDMtMjAgYXQgMDUuMjMuMTAuanBlZyIpDQpgYGANCg0KIyMjIFJPQyBQbG90DQoNCmxpYnJhcnkoUk9DUikNCnByZWQ8LQ0KcHJlZGljdGlvbihwcmVkaWN0LmdsbShjcmVkaXQuZ2xtLmZpbmFsLGdlcm1hbi5jcmVkaXQudGVzdCksZ2VybWFuLmNyZWRpdC50ZXN0JGNsYXNzKQ0KcGVyZiA8LSBwZXJmb3JtYW5jZShwcmVkLCJ0cHIiLCJmcHIiKQ0KcGxvdChwZXJmKQ0KDQpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9BZG1pbmlzdHJhdG9yL0Rvd25sb2Fkcy9yb2MgcGxvdC5wbmciKQ0KYGBgDQoNCiMgUGVudXR1cA0KDQpTZWxhbmp1dG55YSBqaWthIG1vZGVsIHN1ZGFoIGJhaWsgYXN1bWFzaSB0ZXJwZW51aGkuIG1ha2EgbW9kZWwgaXR1IGJpc2Ega2l0YSBqYWRpa2FuIHNlYmFnYWkgYWxhdCBwcmVkaWtzaSwgZGVuZ2FuIG1lbmdndW5ha2FuIGRhdGEgc2V0IGJhcnUgeWFuZyBiZXJpc2kgdmFyaWFibGUgeWFuZyBzYW1hIGRlbmdhbiBkYXRhIHNldCBtb2RlbC4gY2FyYW55YSBhZGFsYWggOg0KDQoNCm1lbWJ1YXQgcHJlZGlrc2kgZGVuZ2FuIGRhdGEgYmFydSBkYXJpIG1vZGVsDQoNCnByZWRpY3RlZF92YWx1ZXMgPC0gcHJlZGljdChtb2RlbF9yZWdsb2csIG5ld2RhdGEgPSBuZXdfZGF0YSkNCg0KIyMgRXZhbHVhc2kgbW9kZWwNCg0KcmVzaWR1YWxzIDwtIHRydWVfdmFsdWVzIC0gcHJlZGljdGVkX3ZhbHVlcw0KbXNlIDwtIG1lYW4ocmVzaWR1YWxzXjIpDQoNCiMjIFBsb3QgbW9kZWwNCg0KcGxvdChuZXdfZGF0YSRYMSwgcHJlZGljdGVkX3ZhbHVlcywgY29sID0gInJlZCIsIHBjaCA9IDE2LCB4bGFiID0gIlgxIiwgeWxhYiA9ICJQcmVkaWN0ZWQgWSIsIG1haW4gPSAiTW9kZWwgUmVncmVzc2lvbiBQbG90IikNCnBvaW50cyhuZXdfZGF0YSRYMSwgdHJ1ZV92YWx1ZXMsIGNvbCA9ICJibHVlIiwgcGNoID0gMTYpDQpsZWdlbmQoInRvcGxlZnQiLCBsZWdlbmQgPSBjKCJQcmVkaWN0ZWQgVmFsdWVzIiwgIlRydWUgVmFsdWVzIiksIGNvbCA9IGMoInJlZCIsICJibHVlIiksIHBjaCA9IDE2KQ0KDQotLS0=