Seketika boss saya memberikan data, and he said :

tolong cek apakah ada pengaruh antara variable yang 1 dan yang lainnya? saya mau lihat ini ada korelasi apa nggak, seberapa kuat variablenya.

Baik pak, Itulah jawaban budak korporat, baik pak baik pak baik pak doang.

lalu mikir dong, ini mau di gimanakan yak, terlintas uji dalam statistik, namanya Uji Korelasi Mari kita bahas.


PENDAHULUAN

What is Corelation Test ?

Jiah JAKSEL kwkwkk

Korelasi adalah suatu ukuran statistik yang digunakan untuk mengevaluasi sejauh mana dua variabel berkaitan satu sama lain. Dalam statistika, korelasi mengukur kekuatan dan arah hubungan antara dua variabel.

Ada tiga keywords yang penting pada definisi tersebut, yakni:

Variables, yakni dua variabel yang ingin dicek hubungannya. 

Linear Strengh, menandakan seberapa kuat kedua variabel tersebut secara linear. 

Direction, menandakan arah dari hubungan kedua variabel tersebut. 

Keywords

  1. Varieble

Ada hal penting yang perlu diperhatikan saat kita hendak melakukan analisa korelasi. Apa itu?

Pastikan kedua variabel yang akan kita uji secara logis dapat dihubungkan. 

Kedua variabel tersebut harus berupa numerik. 

Jadi, hanya data kuantitatif saja yang bisa dihitung korelasinya.

  1. Linear Strength

Korelasi adalah suatu nilai yang berada di selang angka -1 hingga 1. Nilai mutlak dari korelasi menandakan seberapa kuat hubungan kedua variabel secara linear.

Apa sih maksudnya?

Jika kita buat grafik sumbu x vs sumbu y, kekuatan kedua variabel (x,y) secara visual dapat dilihat dari seberapa mudah titik-titik yang ditimbulkan dibuat garis lurus. Semakin membentuk garis lurus sempurna, kita bisa katakan bahwa kedua variabel memiliki korelasi kuat. Begitupun sebaliknya.

Coba lihat kembali gambar di awal halaman!

Semakin menuju ke angka 1 atau -1 (ingat, yang dilihat nilai mutlaknya yah!), kedua variabel dalam sumbu kartesian membentuk garis lurus sempurna.

Pengelompokan kekuatan korelasi:

Low : 0.1 - 0.3 

Medium : 0.3 - 0.5 

High : 0.5 - 1.0 
  1. Direction

Kalau kita lihat kembali, nilai korelasi bisa bernilai positif atau negatif. +/- itu menunjukan arah hubungan kedua variabel tersebut.

Jika bernilai positif maka hubungan kedua variabel tersebut itu berbanding lurus. Contoh: x naik maka y juga naik. 

Jika bernilai negatif maka hubungan kedua variabel tersebut itu berbanding lurus. Contoh: x naik maka y juga turun. 

Jenis Jenis Uji Korelasi

Ada beberapa uji Korelasi yang harus kita ketahui dan syaratnya bagaimana.

1. Korelasi Pearson

Korelasi ini digunakan jika data yang di gunakan jika data yang akan di uji Berdistribusi normal.

2. Korelasi Spearman

Kebalikan dari Pearson, Distribusi dari Spearman ini di gunakan ketika datanya yang akan kita cek Tidak Berdistribusi normal.

3. Korelasi Kendal

Mengukuar antara dara Ordinal.Misalnya, variabel “frekuensi latihan fisik” dapat dibagi dalam beberapa kategori, seperti tidak pernah, jarang, kadang-kadang, sering, dan selalu.

4. Korelasi Pointbeserial

Mengukur antara 1 variable Biner dan 1 variable Numerik.

5. Korelasi Phi

Mengukur antara 2 varaible Biner ****

Menghitung korelasi

Package

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.3     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2     
## ── 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(stats)
library(corrplot)
## corrplot 0.92 loaded
library(readr)

Data Set Preparation

Data yang akan di gunakana adalah data set yang saya buat buat sendiri. klik di sini jika ingin mengambil ya..

Data_corelation = read.csv("D:/R/1 DATA SET/Korelatio test/Uji Korelasi.csv", header = T, sep = ";")
Data_corelation = Data_corelation %>% mutate(No = row_number())
Data_corelation = Data_corelation %>% select(No, everything())
head(Data_corelation, 6)
##   No       ID Store_id Store_Type Location_Type Region_Code       Date Holiday
## 1  1 T1188341      171         S4            L2          R3 01/06/2019       0
## 2  2 T1188342      172         S1            L1          R1 01/06/2019       0
## 3  3 T1188343      173         S4            L2          R1 01/06/2019       0
## 4  4 T1188344      174         S1            L1          R4 01/06/2019       0
## 5  5 T1188345      170         S1            L1          R2 01/06/2019       0
## 6  6 T1188346      175         S4            L2          R1 01/06/2019       0
##   Discount    sales qty
## 1       No  12,605  195
## 2       No  19,279  118
## 3       No  16,480  119
## 4       No  16,742  181
## 5       No  12,233  174
## 6       No  12,007  165

Di atas saya coba otak atik datanyam biar keren, ada nomor tiap baris.

Selanjutnya memilih data yang akan kita korelasikan. ingat syarat korealsi tidak boleh ada data yang menggunakan teks. mari lihat data yang di gunakan.

str(Data_corelation)
## 'data.frame':    22265 obs. of  11 variables:
##  $ No           : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ ID           : chr  "T1188341" "T1188342" "T1188343" "T1188344" ...
##  $ Store_id     : int  171 172 173 174 170 175 176 169 14 177 ...
##  $ Store_Type   : chr  "S4" "S1" "S4" "S1" ...
##  $ Location_Type: chr  "L2" "L1" "L2" "L1" ...
##  $ Region_Code  : chr  "R3" "R1" "R1" "R4" ...
##  $ Date         : chr  "01/06/2019" "01/06/2019" "01/06/2019" "01/06/2019" ...
##  $ Holiday      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Discount     : chr  "No" "No" "No" "No" ...
##  $ sales        : chr  " 12,605 " " 19,279 " " 16,480 " " 16,742 " ...
##  $ qty          : int  195 118 119 181 174 165 112 143 100 148 ...

Data di atas banyak sekali yang bertype character, sehingga akan kita ubah dulu menjadi data yang sesuai.

Data_corelation$Store_Type = as.factor(Data_corelation$Store_Type)
Data_corelation$Region_Code = as.factor(Data_corelation$Region_Code)
Data_corelation$Store_Type = as.factor(Data_corelation$Location_Type)
Data_corelation$Date = as.Date(Data_corelation$Date, format = "%m/%d/%y")
Data_corelation$Discount = as.factor(Data_corelation$Discount)
Data_corelation$Location_Type = as.factor(Data_corelation$Location_Type)
Data_corelation$sales = as.numeric(gsub(",", "", Data_corelation$sales))

Data setelah di edit

str(Data_corelation)
## 'data.frame':    22265 obs. of  11 variables:
##  $ No           : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ ID           : chr  "T1188341" "T1188342" "T1188343" "T1188344" ...
##  $ Store_id     : int  171 172 173 174 170 175 176 169 14 177 ...
##  $ Store_Type   : Factor w/ 5 levels "L1","L2","L3",..: 2 1 2 1 1 2 2 2 2 1 ...
##  $ Location_Type: Factor w/ 5 levels "L1","L2","L3",..: 2 1 2 1 1 2 2 2 2 1 ...
##  $ Region_Code  : Factor w/ 4 levels "R1","R2","R3",..: 3 1 1 4 2 1 3 4 4 4 ...
##  $ Date         : Date, format: "2020-01-06" "2020-01-06" ...
##  $ Holiday      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Discount     : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ sales        : num  12605 19279 16480 16742 12233 ...
##  $ qty          : int  195 118 119 181 174 165 112 143 100 148 ...

Data sudah oke, namun kita akan mengambil beberapa variable saja yang di butuhkan, sebap untuk menguji korelasi tidak semua data akan di uji. contoh nya adalah No dan ID ini sudah pasti independen, tidak ada pengaruh terhadap varible lainnya.

Data_corelation_final = Data_corelation %>% select(-No, -ID, -Date, -Store_id)
str(Data_corelation_final)
## 'data.frame':    22265 obs. of  7 variables:
##  $ Store_Type   : Factor w/ 5 levels "L1","L2","L3",..: 2 1 2 1 1 2 2 2 2 1 ...
##  $ Location_Type: Factor w/ 5 levels "L1","L2","L3",..: 2 1 2 1 1 2 2 2 2 1 ...
##  $ Region_Code  : Factor w/ 4 levels "R1","R2","R3",..: 3 1 1 4 2 1 3 4 4 4 ...
##  $ Holiday      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Discount     : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ sales        : num  12605 19279 16480 16742 12233 ...
##  $ qty          : int  195 118 119 181 174 165 112 143 100 148 ...
Data_corelation_final_sekali <- mutate_all(Data_corelation_final, as.numeric)
str(Data_corelation_final_sekali)
## 'data.frame':    22265 obs. of  7 variables:
##  $ Store_Type   : num  2 1 2 1 1 2 2 2 2 1 ...
##  $ Location_Type: num  2 1 2 1 1 2 2 2 2 1 ...
##  $ Region_Code  : num  3 1 1 4 2 1 3 4 4 4 ...
##  $ Holiday      : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ Discount     : num  1 1 1 1 1 1 1 1 1 1 ...
##  $ sales        : num  12605 19279 16480 16742 12233 ...
##  $ qty          : num  195 118 119 181 174 165 112 143 100 148 ...

Korelation test

Selanjutnya adalah melihat korelasi dengan menggunakan berbagai methode Korelasi yang mana setiap methode penggunaanya tergantung setiap data.

1. Korelasi Pearson

pearson <- cor(Data_corelation_final_sekali, method = "pearson")
corrplot(pearson, method = "circle", type = "full", bg = "blue")

2. Korelasi Spearman

Spearman = cor(Data_corelation_final_sekali, method = "spearman")
corrplot(Spearman, method = "number", bg = "black", type = "full")

3. Korelasi Kendal

kendall = cor(Data_corelation_final_sekali, method = "kendall")
corrplot(kendall, method = "square", bg = "lightgreen")

4. Korelasi Pointbeserial

library(polycor)
Pointbeserial = polyserial(Data_corelation_final_sekali$Discount, Data_corelation_final_sekali$Region_Code)
print(Pointbeserial)
## [1] -0.001916166

sangat kecil korelasinya.

5. Korelasi Phi

Data_corelation_final_sekali_phi = table(Data_corelation_final$Discount, Data_corelation_final$Location_Type)
phi = chisq.test(Data_corelation_final_sekali_phi)
print(phi)
## 
##  Pearson's Chi-squared test
## 
## data:  Data_corelation_final_sekali_phi
## X-squared = 0.67629, df = 4, p-value = 0.9542

Jika nilai p sangat tinggi, dapat diartikan bahwa tidak ada bukti yang cukup untuk mendukung adanya hubungan antara variabel-variabel yang diuji.

6, Plot Corelation

library(PerformanceAnalytics)
## Loading required package: xts
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## 
## ######################### Warning from 'xts' package ##########################
## #                                                                             #
## # The dplyr lag() function breaks how base R's lag() function is supposed to  #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
## # source() into this session won't work correctly.                            #
## #                                                                             #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
## # dplyr from breaking base R's lag() function.                                #
## #                                                                             #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
## #                                                                             #
## ###############################################################################
## 
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
## 
##     first, last
## 
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
## 
##     legend
chart.Correlation(Spearman, histogram = TRUE, pch = 19)
## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter

## Warning in par(usr): argument 1 does not name a graphical parameter


Contact

Kontak
Name Albani
E-mail
LinkedIn Profil LinkedIn Al Bani
Rpubs

LS0tDQp0aXRsZTogIkNPUkVMQVRJT04gVEVTVCINCmF1dGhvcjogIkFsYmFuaSINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkIDogeWVzDQogICAgdGhlbWU6IGpvdXJuYWwNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogdHJ1ZQ0KLS0tDQoNCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGp1c3RpZnk7Ij4NCg0KU2VrZXRpa2EgYm9zcyBzYXlhIG1lbWJlcmlrYW4gZGF0YSwgYW5kIGhlIHNhaWQgOg0KDQpfdG9sb25nIGNlayBhcGFrYWggYWRhIHBlbmdhcnVoIGFudGFyYSB2YXJpYWJsZSB5YW5nIDEgZGFuIHlhbmcgbGFpbm55YT8gc2F5YSBtYXUgbGloYXQgaW5pIGFkYSBrb3JlbGFzaSBhcGEgbmdnYWssIHNlYmVyYXBhIGt1YXQgdmFyaWFibGVueWEuXw0KDQoqQmFpayBwYWsqLCBJdHVsYWggamF3YWJhbiBidWRhayBrb3Jwb3JhdCwgYmFpayBwYWsgYmFpayBwYWsgYmFpayBwYWsgZG9hbmcuDQoNCmxhbHUgbWlraXIgZG9uZywgaW5pIG1hdSBkaSBnaW1hbmFrYW4geWFrLCB0ZXJsaW50YXMgdWppIGRhbGFtIHN0YXRpc3RpaywgbmFtYW55YSAqKlVqaSBLb3JlbGFzaSoqIE1hcmkga2l0YSBiYWhhcy4NCg0KKioqDQojIFBFTkRBSFVMVUFODQoNCiMjIFdoYXQgaXMgQ29yZWxhdGlvbiBUZXN0ID8gDQoNCkppYWggSkFLU0VMIGt3a3drayANCg0KS29yZWxhc2kgYWRhbGFoIHN1YXR1IHVrdXJhbiBzdGF0aXN0aWsgeWFuZyBkaWd1bmFrYW4gdW50dWsgbWVuZ2V2YWx1YXNpIHNlamF1aCBtYW5hIGR1YSB2YXJpYWJlbCBiZXJrYWl0YW4gc2F0dSBzYW1hIGxhaW4uIERhbGFtIHN0YXRpc3Rpa2EsIGtvcmVsYXNpIG1lbmd1a3VyIGtla3VhdGFuIGRhbiBhcmFoIGh1YnVuZ2FuIGFudGFyYSBkdWEgdmFyaWFiZWwuDQoNCkFkYSB0aWdhIGtleXdvcmRzIHlhbmcgcGVudGluZyBwYWRhIGRlZmluaXNpIHRlcnNlYnV0LCB5YWtuaTogDQoNCiAgICBWYXJpYWJsZXMsIHlha25pIGR1YSB2YXJpYWJlbCB5YW5nIGluZ2luIGRpY2VrIGh1YnVuZ2FubnlhLiANCg0KICAgIExpbmVhciBTdHJlbmdoLCBtZW5hbmRha2FuIHNlYmVyYXBhIGt1YXQga2VkdWEgdmFyaWFiZWwgdGVyc2VidXQgc2VjYXJhIGxpbmVhci4gDQoNCiAgICBEaXJlY3Rpb24sIG1lbmFuZGFrYW4gYXJhaCBkYXJpIGh1YnVuZ2FuIGtlZHVhIHZhcmlhYmVsIHRlcnNlYnV0LiANCiAgICANCiMjIEtleXdvcmRzDQoNCjEuIFZhcmllYmxlDQoNCkFkYSBoYWwgcGVudGluZyB5YW5nIHBlcmx1IGRpcGVyaGF0aWthbiBzYWF0IGtpdGEgaGVuZGFrIG1lbGFrdWthbiBhbmFsaXNhIGtvcmVsYXNpLiBBcGEgaXR1PyANCg0KICAgIFBhc3Rpa2FuIGtlZHVhIHZhcmlhYmVsIHlhbmcgYWthbiBraXRhIHVqaSBzZWNhcmEgbG9naXMgZGFwYXQgZGlodWJ1bmdrYW4uIA0KDQogICAgS2VkdWEgdmFyaWFiZWwgdGVyc2VidXQgaGFydXMgYmVydXBhIG51bWVyaWsuIA0KDQpKYWRpLCBoYW55YSBkYXRhIGt1YW50aXRhdGlmIHNhamEgeWFuZyBiaXNhIGRpaGl0dW5nIGtvcmVsYXNpbnlhLiANCg0KMi4gTGluZWFyIFN0cmVuZ3RoDQoNCktvcmVsYXNpIGFkYWxhaCBzdWF0dSBuaWxhaSB5YW5nIGJlcmFkYSBkaSBzZWxhbmcgYW5na2EgLTEgaGluZ2dhIDEuIE5pbGFpIG11dGxhayBkYXJpIGtvcmVsYXNpIG1lbmFuZGFrYW4gc2ViZXJhcGEga3VhdCBodWJ1bmdhbiBrZWR1YSB2YXJpYWJlbCBzZWNhcmEgbGluZWFyLiANCg0KQXBhIHNpaCBtYWtzdWRueWE/IA0KDQpKaWthIGtpdGEgYnVhdCBncmFmaWsgc3VtYnUgeCB2cyBzdW1idSB5LCBrZWt1YXRhbiBrZWR1YSB2YXJpYWJlbCAoeCx5KSBzZWNhcmEgdmlzdWFsIGRhcGF0IGRpbGloYXQgZGFyaSBzZWJlcmFwYSBtdWRhaCB0aXRpay10aXRpayB5YW5nIGRpdGltYnVsa2FuIGRpYnVhdCBnYXJpcyBsdXJ1cy4gU2VtYWtpbiBtZW1iZW50dWsgZ2FyaXMgbHVydXMgc2VtcHVybmEsIGtpdGEgYmlzYSBrYXRha2FuIGJhaHdhIGtlZHVhIHZhcmlhYmVsIG1lbWlsaWtpIGtvcmVsYXNpIGt1YXQuIEJlZ2l0dXB1biBzZWJhbGlrbnlhLiANCg0KQ29iYSBsaWhhdCBrZW1iYWxpIGdhbWJhciBkaSBhd2FsIGhhbGFtYW4hIA0KDQpTZW1ha2luIG1lbnVqdSBrZSBhbmdrYSAxIGF0YXUgLTEgKGluZ2F0LCB5YW5nIGRpbGloYXQgbmlsYWkgbXV0bGFrbnlhIHlhaCEpLCBrZWR1YSB2YXJpYWJlbCBkYWxhbSBzdW1idSBrYXJ0ZXNpYW4gbWVtYmVudHVrIGdhcmlzIGx1cnVzIHNlbXB1cm5hLiANCg0KUGVuZ2Vsb21wb2thbiBrZWt1YXRhbiBrb3JlbGFzaTogDQoNCiAgICBMb3cgOiAwLjEgLSAwLjMgDQoNCiAgICBNZWRpdW0gOiAwLjMgLSAwLjUgDQoNCiAgICBIaWdoIDogMC41IC0gMS4wIA0KDQozLiBEaXJlY3Rpb24NCg0KS2FsYXUga2l0YSBsaWhhdCBrZW1iYWxpLCBuaWxhaSBrb3JlbGFzaSBiaXNhIGJlcm5pbGFpIHBvc2l0aWYgYXRhdSBuZWdhdGlmLiArLy0gaXR1IG1lbnVuanVrYW4gYXJhaCBodWJ1bmdhbiBrZWR1YSB2YXJpYWJlbCB0ZXJzZWJ1dC4gDQoNCiAgICBKaWthIGJlcm5pbGFpIHBvc2l0aWYgbWFrYSBodWJ1bmdhbiBrZWR1YSB2YXJpYWJlbCB0ZXJzZWJ1dCBpdHUgYmVyYmFuZGluZyBsdXJ1cy4gQ29udG9oOiB4IG5haWsgbWFrYSB5IGp1Z2EgbmFpay4gDQoNCiAgICBKaWthIGJlcm5pbGFpIG5lZ2F0aWYgbWFrYSBodWJ1bmdhbiBrZWR1YSB2YXJpYWJlbCB0ZXJzZWJ1dCBpdHUgYmVyYmFuZGluZyBsdXJ1cy4gQ29udG9oOiB4IG5haWsgbWFrYSB5IGp1Z2EgdHVydW4uIA0KDQojIyBKZW5pcyBKZW5pcyBVamkgS29yZWxhc2kNCg0KQWRhIGJlYmVyYXBhIHVqaSBLb3JlbGFzaSB5YW5nIGhhcnVzIGtpdGEga2V0YWh1aSBkYW4gc3lhcmF0bnlhIGJhZ2FpbWFuYS4NCg0KIyMjIDEuIEtvcmVsYXNpIFBlYXJzb24NCg0KS29yZWxhc2kgaW5pIGRpZ3VuYWthbiBqaWthIGRhdGEgeWFuZyBkaSBndW5ha2FuIGppa2EgZGF0YSB5YW5nIGFrYW4gZGkgdWppIGBCZXJkaXN0cmlidXNpIG5vcm1hbGAuDQoNCiMjIyAyLiBLb3JlbGFzaSBTcGVhcm1hbg0KDQpLZWJhbGlrYW4gZGFyaSBgUGVhcnNvbmAsIERpc3RyaWJ1c2kgZGFyaSBgU3BlYXJtYW5gIGluaSBkaSBndW5ha2FuIGtldGlrYSBkYXRhbnlhIHlhbmcgYWthbiBraXRhIGNlayBgVGlkYWsgQmVyZGlzdHJpYnVzaSBub3JtYWxgLg0KDQojIyMgMy4gS29yZWxhc2kgS2VuZGFsDQoNCk1lbmd1a3VhciBhbnRhcmEgZGFyYSBPcmRpbmFsLk1pc2FsbnlhLCB2YXJpYWJlbCDigJxmcmVrdWVuc2kgbGF0aWhhbiBmaXNpa+KAnSBkYXBhdCBkaWJhZ2kgZGFsYW0gYmViZXJhcGEga2F0ZWdvcmksIHNlcGVydGkgdGlkYWsgcGVybmFoLCBqYXJhbmcsIGthZGFuZy1rYWRhbmcsIHNlcmluZywgZGFuIHNlbGFsdS4gDQoNCiMjIyA0LiBLb3JlbGFzaSBQb2ludGJlc2VyaWFsDQoNCk1lbmd1a3VyIGFudGFyYSAxIHZhcmlhYmxlIEJpbmVyIGRhbiAxIHZhcmlhYmxlIE51bWVyaWsuDQoNCiMjIyA1LiBLb3JlbGFzaSBQaGkNCg0KTWVuZ3VrdXIgYW50YXJhIDIgdmFyYWlibGUgQmluZXINCioqKioNCg0KIyBNZW5naGl0dW5nIGtvcmVsYXNpDQoNCiMjIFBhY2thZ2UNCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHN0YXRzKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkocmVhZHIpDQpgYGANCg0KDQojIyBEYXRhIFNldCBQcmVwYXJhdGlvbg0KDQpEYXRhIHlhbmcgYWthbiBkaSBndW5ha2FuYSBhZGFsYWggZGF0YSBzZXQgeWFuZyBzYXlhIGJ1YXQgYnVhdCBzZW5kaXJpLiBrbGlrIFtkaSBzaW5pXShodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL2I0bjg4OS9leGVyY2lzZS1jb3JlbGF0aW9uLXRlc3Q/c2VsZWN0PVVqaStLb3JlbGFzaS5jc3YpIGppa2EgaW5naW4gbWVuZ2FtYmlsIHlhLi4NCg0KYGBge3J9DQpEYXRhX2NvcmVsYXRpb24gPSByZWFkLmNzdigiRDovUi8xIERBVEEgU0VUL0tvcmVsYXRpbyB0ZXN0L1VqaSBLb3JlbGFzaS5jc3YiLCBoZWFkZXIgPSBULCBzZXAgPSAiOyIpDQpEYXRhX2NvcmVsYXRpb24gPSBEYXRhX2NvcmVsYXRpb24gJT4lIG11dGF0ZShObyA9IHJvd19udW1iZXIoKSkNCkRhdGFfY29yZWxhdGlvbiA9IERhdGFfY29yZWxhdGlvbiAlPiUgc2VsZWN0KE5vLCBldmVyeXRoaW5nKCkpDQpoZWFkKERhdGFfY29yZWxhdGlvbiwgNikNCmBgYA0KRGkgYXRhcyBzYXlhIGNvYmEgb3RhayBhdGlrIGRhdGFueWFtIGJpYXIga2VyZW4sIGFkYSBub21vciB0aWFwIGJhcmlzLg0KDQpTZWxhbmp1dG55YSBtZW1pbGloIGRhdGEgeWFuZyBha2FuIGtpdGEga29yZWxhc2lrYW4uIGluZ2F0IHN5YXJhdCBrb3JlYWxzaSB0aWRhayBib2xlaCBhZGEgZGF0YSB5YW5nIG1lbmdndW5ha2FuIHRla3MuIG1hcmkgbGloYXQgZGF0YSB5YW5nIGRpIGd1bmFrYW4uDQoNCmBgYHtyfQ0Kc3RyKERhdGFfY29yZWxhdGlvbikNCmBgYA0KRGF0YSBkaSBhdGFzIGJhbnlhayBzZWthbGkgeWFuZyBiZXJ0eXBlIGNoYXJhY3Rlciwgc2VoaW5nZ2EgYWthbiBraXRhIHViYWggZHVsdSBtZW5qYWRpIGRhdGEgeWFuZyBzZXN1YWkuDQpgYGB7cn0NCkRhdGFfY29yZWxhdGlvbiRTdG9yZV9UeXBlID0gYXMuZmFjdG9yKERhdGFfY29yZWxhdGlvbiRTdG9yZV9UeXBlKQ0KRGF0YV9jb3JlbGF0aW9uJFJlZ2lvbl9Db2RlID0gYXMuZmFjdG9yKERhdGFfY29yZWxhdGlvbiRSZWdpb25fQ29kZSkNCkRhdGFfY29yZWxhdGlvbiRTdG9yZV9UeXBlID0gYXMuZmFjdG9yKERhdGFfY29yZWxhdGlvbiRMb2NhdGlvbl9UeXBlKQ0KRGF0YV9jb3JlbGF0aW9uJERhdGUgPSBhcy5EYXRlKERhdGFfY29yZWxhdGlvbiREYXRlLCBmb3JtYXQgPSAiJW0vJWQvJXkiKQ0KRGF0YV9jb3JlbGF0aW9uJERpc2NvdW50ID0gYXMuZmFjdG9yKERhdGFfY29yZWxhdGlvbiREaXNjb3VudCkNCkRhdGFfY29yZWxhdGlvbiRMb2NhdGlvbl9UeXBlID0gYXMuZmFjdG9yKERhdGFfY29yZWxhdGlvbiRMb2NhdGlvbl9UeXBlKQ0KRGF0YV9jb3JlbGF0aW9uJHNhbGVzID0gYXMubnVtZXJpYyhnc3ViKCIsIiwgIiIsIERhdGFfY29yZWxhdGlvbiRzYWxlcykpDQpgYGANCkRhdGEgc2V0ZWxhaCBkaSBlZGl0DQpgYGB7cn0NCnN0cihEYXRhX2NvcmVsYXRpb24pDQpgYGANCkRhdGEgc3VkYWggb2tlLCBuYW11biBraXRhIGFrYW4gbWVuZ2FtYmlsIGJlYmVyYXBhIHZhcmlhYmxlIHNhamEgeWFuZyBkaSBidXR1aGthbiwgc2ViYXAgdW50dWsgbWVuZ3VqaSBrb3JlbGFzaSB0aWRhayBzZW11YSBkYXRhIGFrYW4gZGkgdWppLiBjb250b2ggbnlhIGFkYWxhaCBObyBkYW4gSUQgaW5pIHN1ZGFoIHBhc3RpIGluZGVwZW5kZW4sIHRpZGFrIGFkYSBwZW5nYXJ1aCB0ZXJoYWRhcCB2YXJpYmxlIGxhaW5ueWEuDQoNCmBgYHtyfQ0KRGF0YV9jb3JlbGF0aW9uX2ZpbmFsID0gRGF0YV9jb3JlbGF0aW9uICU+JSBzZWxlY3QoLU5vLCAtSUQsIC1EYXRlLCAtU3RvcmVfaWQpDQpzdHIoRGF0YV9jb3JlbGF0aW9uX2ZpbmFsKQ0KYGBgDQoNCmBgYHtyfQ0KRGF0YV9jb3JlbGF0aW9uX2ZpbmFsX3Nla2FsaSA8LSBtdXRhdGVfYWxsKERhdGFfY29yZWxhdGlvbl9maW5hbCwgYXMubnVtZXJpYykNCmBgYA0KYGBge3J9DQpzdHIoRGF0YV9jb3JlbGF0aW9uX2ZpbmFsX3Nla2FsaSkNCmBgYA0KDQoNCiMjIEtvcmVsYXRpb24gdGVzdA0KDQpTZWxhbmp1dG55YSBhZGFsYWggbWVsaWhhdCBrb3JlbGFzaSBkZW5nYW4gbWVuZ2d1bmFrYW4gYmVyYmFnYWkgbWV0aG9kZSBgS29yZWxhc2lgIHlhbmcgbWFuYSBzZXRpYXAgbWV0aG9kZSBwZW5nZ3VuYWFueWEgdGVyZ2FudHVuZyBzZXRpYXAgZGF0YS4NCg0KIyMjIDEuIEtvcmVsYXNpIFBlYXJzb24NCmBgYHtyfQ0KcGVhcnNvbiA8LSBjb3IoRGF0YV9jb3JlbGF0aW9uX2ZpbmFsX3Nla2FsaSwgbWV0aG9kID0gInBlYXJzb24iKQ0KYGBgDQpgYGB7cn0NCmNvcnJwbG90KHBlYXJzb24sIG1ldGhvZCA9ICJjaXJjbGUiLCB0eXBlID0gImZ1bGwiLCBiZyA9ICJibHVlIikNCmBgYA0KDQojIyMgMi4gS29yZWxhc2kgU3BlYXJtYW4NCmBgYHtyfQ0KU3BlYXJtYW4gPSBjb3IoRGF0YV9jb3JlbGF0aW9uX2ZpbmFsX3Nla2FsaSwgbWV0aG9kID0gInNwZWFybWFuIikNCmNvcnJwbG90KFNwZWFybWFuLCBtZXRob2QgPSAibnVtYmVyIiwgYmcgPSAiYmxhY2siLCB0eXBlID0gImZ1bGwiKQ0KYGBgDQoNCiMjIyAzLiBLb3JlbGFzaSBLZW5kYWwNCmBgYHtyfQ0Ka2VuZGFsbCA9IGNvcihEYXRhX2NvcmVsYXRpb25fZmluYWxfc2VrYWxpLCBtZXRob2QgPSAia2VuZGFsbCIpDQpjb3JycGxvdChrZW5kYWxsLCBtZXRob2QgPSAic3F1YXJlIiwgYmcgPSAibGlnaHRncmVlbiIpDQpgYGANCg0KIyMjIDQuIEtvcmVsYXNpIFBvaW50YmVzZXJpYWwNCmBgYHtyfQ0KbGlicmFyeShwb2x5Y29yKQ0KUG9pbnRiZXNlcmlhbCA9IHBvbHlzZXJpYWwoRGF0YV9jb3JlbGF0aW9uX2ZpbmFsX3Nla2FsaSREaXNjb3VudCwgRGF0YV9jb3JlbGF0aW9uX2ZpbmFsX3Nla2FsaSRSZWdpb25fQ29kZSkNCnByaW50KFBvaW50YmVzZXJpYWwpDQpgYGANCnNhbmdhdCBrZWNpbCBrb3JlbGFzaW55YS4NCg0KIyMjIDUuIEtvcmVsYXNpIFBoaQ0KYGBge3J9DQpEYXRhX2NvcmVsYXRpb25fZmluYWxfc2VrYWxpX3BoaSA9IHRhYmxlKERhdGFfY29yZWxhdGlvbl9maW5hbCREaXNjb3VudCwgRGF0YV9jb3JlbGF0aW9uX2ZpbmFsJExvY2F0aW9uX1R5cGUpDQpwaGkgPSBjaGlzcS50ZXN0KERhdGFfY29yZWxhdGlvbl9maW5hbF9zZWthbGlfcGhpKQ0KcHJpbnQocGhpKQ0KYGBgDQpKaWthIG5pbGFpIHAgc2FuZ2F0IHRpbmdnaSwgZGFwYXQgZGlhcnRpa2FuIGJhaHdhIHRpZGFrIGFkYSBidWt0aSB5YW5nIGN1a3VwIHVudHVrIG1lbmR1a3VuZyBhZGFueWEgaHVidW5nYW4gYW50YXJhIHZhcmlhYmVsLXZhcmlhYmVsIHlhbmcgZGl1amkuDQoNCiMjIyA2LCBQbG90IENvcmVsYXRpb24NCg0KYGBge3J9DQpsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQ0KYGBgDQoNCmBgYHtyfQ0KY2hhcnQuQ29ycmVsYXRpb24oU3BlYXJtYW4sIGhpc3RvZ3JhbSA9IFRSVUUsIHBjaCA9IDE5KQ0KYGBgDQoNCg0KDQoNCjwvZGl2Pg0KDQoqKioqDQoNCiMgQ29udGFjdA0KfCAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfA0KfCA6LS0tICAgICB8IDotLS0gICAgICAgICAgICAgICAgfA0KfCAqKktvbnRhayoqICAgfCAgICAgICAgICAgICAgICAgICAgfA0KfCBOYW1lICAgICB8IEFsYmFuaSAgICAgICAgICAgICAgfA0KfCBFLW1haWwgICB8IGFsLmJhbmkxMjMwMEBnbWFpbC5jb20gICB8DQp8IExpbmtlZEluIHwgW1Byb2ZpbCBMaW5rZWRJbiBBbCBCYW5pXShodHRwczovL3d3dy5saW5rZWRpbi5jb20vaW4vYWwtYmFuaS01MzJiMDYyOTQvKSB8DQp8IFJwdWJzICAgIHwgICB8DQoNCioqKioNCg==