Algoritma & Struktur Data

~ Antarmuka Data dengan R ~


Kontak : \(\downarrow\)
Email
Instagram https://www.instagram.com/novia_labola/
RPubs https://rpubs.com/noviaanita/

Pendahuluan

R (juga dikenal sebagai GNU S) adalah bahasa pemrograman dan perangkat lunak untuk analisis statistika dan grafik. Terhubung dengan sebuah data merupakan hal paling mendasar dalam proses olah data (Data Science). Dibawah ini akan di jelaskan bagaimana proses antarmuka data yang paling sederhana menggunakan R. Secara singkatnya, R dapat membaca data dari file yang disimpan didalam ataupun diluar direktorinya.Sistem operasi R juga dapat menyimpan dan membaca data dalam berbagai format file seperti csv, excel, txt, rds, xml, json, dan lain-lain.

Impor/Ekspor csv

Beikut ini adalah beberapa cara yang dapat dilakukan dalam impor/ekspor data menggunakan R.

Cara 1

Menggunakan fungsi getwd() untuk mengetahui direktori yang sedang digunakan.

print(getwd())
## [1] "C:/Users/MASTER/Documents/Algoritmabaru"
getwd()
## [1] "C:/Users/MASTER/Documents/Algoritmabaru"

setwd() digunakan untuk mengatur direktori kerja baru.

setwd(getwd())

Kemudian, mengimpor data CSV menggunakan fungsi read.csv().

# impor data
df1 <-read.csv("INPUT/input1.csv",sep = ",") # format pemisah koma 
df2 <-read.csv("INPUT/input2.csv",sep = ";") # format pemisah titik koma

write.csv() fungsi yang digunakan untuk mengekspor data yang diinginkan ke direktori.

# ekspor data
write.csv(df1,"OUTPUT/output1.csv", row.names = FALSE)
write.csv(df2,"OUTPUT/output2.csv", row.names = FALSE)

Cara 2

Menggunakan koneksi direktori secara otomatis.

(WD <- getwd())
## [1] "C:/Users/MASTER/Documents/Algoritmabaru"
if (!is.null(WD)) setwd(WD)
# impor data
df1 <- read.csv(file.path(WD, "INPUT", 'input1.csv'))
df2 <- read.csv(file.path(WD, "INPUT", 'input2.csv'))
# ekspor data 
write.csv(df1, file.path(WD, "OUTPUT", "output1"))
write.csv(df1, file.path(WD, "OUTPUT", "output2"))

Cara 3

Cara terakhir tidak perlu melakukan pengaturan direktori terlebih dahulu sebelum melakukan proses mengimpor data hanya perlu memilih data yang tersimpan di pc.

# digunakan untuk memilih data
df3 <- read.csv(file.choose())

Impor/Ekspor Exel

Fungsi readxl dapat membaca langsung file data dari exel yang tersimpan dalam format xls/xlsl.

# untuk menginstall packages readxl, writexl, dan pacman 
pacman::p_load(readxl, writexl)                  
# impor data
df3<-read_excel('INPUT/input4.xls')         # impor data xls (97-2003)
df4<-read_excel("INPUT/input3.xlsx",sheet=1)# impor data xlsx (2003-up)
# ekspor data
write_xlsx(df3,"OUTPUT/output3.xls") 
write_xlsx(df4,"OUTPUT/output4.xlsx")

Impor/Ekspor TXT and RDS

Saat melakukan impor/ekspor disarankan menggunakan format TXT atau RDS karena ukuran file lebih kecil dibandingkan CSV atau XLSX. Sehingga dapat dengan cepat melakukan impor/ekspor data.

# cara untuk mengimpor data 
df5 <- read.table("INPUT/input5.txt")       # format TXT (notepad)
df6 <- source("INPUT/input6.Rdmpd")         # format TXT (Rdmp)
df7 <- readRDS("INPUT/input7.rds")          # format binary RDS
df8 <- readRDS("INPUT/input8.ascii")        # format binary ASCII
# cara untuk mengekspor data
write.table(df5,"OUTPUT/output5.txt")
dump("df6", "OUTPUT/output6.Rdmp")
saveRDS(df7, "OUTPUT/output7.rds")
saveRDS(df8, "OUTPUT/output8.ascii", ascii = TRUE)

Impor/Ekspor XML

XML merupakan kumpulan dari berbagai format file dan data di World Wide Web, intranet menggunakan teks ASCII standar.

Sebelum melakukan impor/ekspor data Install packages terlebih dahulu seperti dibawah ini.

library("XML")
library("kulife")
library("methods")
# impor data ke XML
df9 <- xmlParse("INPUT/input9.xml")
# konversi ke data frame
xml_df <- xmlToDataFrame(df9)
# ekspor data ke XML
write.xml(xml_df, "OUTPUT/output9.xml")

Impor/Ekspor JSON

JSON adalah singkatan dari JavaScript Object Notation. Fungsi jsonlite di R dapat membaca file JSON.

# install library jsonlite terlebih dahulu
library("jsonlite")
# cara untuk mengimpor data JSON
df10 <- fromJSON("INPUT/input10.json")
# mengubah data menjadi data frame
json_df <- as.data.frame(df10)
# cara untuk mengekspor data JSON
write_json(json_df, "OUTPUT/output10.json")

Impor Data dari Web

Mengimpor data dari suatu situs web.

CSV

Impor data Web menggunakan CSV.

web_csv <- read.csv("https://www.liputan6.com/global/read/4625845/pohon-hantu-ini-5-hal-menakjubkan-di-alam-yang-sulit-dipercaya/csv1.csv")

XLSX

Impor data web menggunakan XLSX.Jika mengimpor data dari repositori GitHub. Maka terlebih dahulu menginstall packages rio.

library(rio)
install_formats()
## [1] TRUE
web_xlsx <- rio::import("https://github.com/Bakti-Siregar/dataset/blob/master/Bookdown-Data-Science-for-Beginners/xlsx1.xlsx?raw=true")

Dan jika tidak dari repositori GitHub maka langsung saja menggunakan read.csv()

read.csv("https://www.liputan6.com/global/read/4625845/pohon-hantu-ini-5-hal-menakjubkan-di-alam-yang-sulit-dipercaya/xlsx1.xlsx?raw=true")

Basis Data R

Sistem basis data merupakan sebuah data yang di relasional dan disimpan dalam format yang dinormalisasi. R bisa terhubung dengan mudah ke banyak database relasional seperti MySql, Oracle, SQL Server, dan lain-lain.

Menambang Data Web

Menambang data web atau Webscraping Data merupakan sebuah proses menggunakan bot untuk mengekstrak konten dan data dari suatu situs web. Web Scraping dapat mengekstrak suatu kode HTML dasar yang pada dasarnya disimpan dalam database.

LS0tDQp0aXRsZTogIkFsZ29yaXRtYSAmIFN0cnVrdHVyIERhdGEiDQpzdWJ0aXRsZTogIn4gQW50YXJtdWthIERhdGEgZGVuZ2FuIFIgfiINCmF1dGhvcjogIk5vdmlhIEFuaXRhICgyMDIxNDUyMDAwOCkiDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyb2JvYm9vazogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNzczogInN0eWxlLmNzcyINCg0KLS0tDQoNCg0KPGJyPg0KDQo8aW1nIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbjogLTUwcHggNTBweCAwcHggNTBweDsgd2lkdGg6MjUlIiBzcmM9Im5vdmlhLkpQRyIvPiANCg0KfA0KOi0tLS0gfDotLS0tDQoqKktvbnRhayoqfCAqKjogJFxkb3duYXJyb3ckKioNCkVtYWlsfCBub3ZpYWFsYmwwMkBnbWFpbC5jb20NCkluc3RhZ3JhbSB8IGh0dHBzOi8vd3d3Lmluc3RhZ3JhbS5jb20vbm92aWFfbGFib2xhLyANClJQdWJzICB8IGh0dHBzOi8vcnB1YnMuY29tL25vdmlhYW5pdGEvIA0KDQoqKioNCg0KDQojIFBlbmRhaHVsdWFuIA0KDQpSIChqdWdhIGRpa2VuYWwgc2ViYWdhaSBHTlUgUykgYWRhbGFoIGJhaGFzYSBwZW1yb2dyYW1hbiBkYW4gcGVyYW5na2F0IGx1bmFrIHVudHVrIGFuYWxpc2lzIHN0YXRpc3Rpa2EgZGFuIGdyYWZpay4gVGVyaHVidW5nIGRlbmdhbiBzZWJ1YWggZGF0YSBtZXJ1cGFrYW4gaGFsIHBhbGluZyBtZW5kYXNhciBkYWxhbSBwcm9zZXMgb2xhaCBkYXRhIChEYXRhIFNjaWVuY2UpLiBEaWJhd2FoIGluaSBha2FuIGRpIGplbGFza2FuIGJhZ2FpbWFuYSBwcm9zZXMgYW50YXJtdWthIGRhdGEgeWFuZyBwYWxpbmcgc2VkZXJoYW5hIG1lbmdndW5ha2FuIFIuIFNlY2FyYSBzaW5na2F0bnlhLCBSIGRhcGF0IG1lbWJhY2EgZGF0YSBkYXJpIGZpbGUgeWFuZyBkaXNpbXBhbiBkaWRhbGFtIGF0YXVwdW4gZGlsdWFyIGRpcmVrdG9yaW55YS5TaXN0ZW0gb3BlcmFzaSBSIGp1Z2EgZGFwYXQgbWVueWltcGFuIGRhbiBtZW1iYWNhIGRhdGEgZGFsYW0gYmVyYmFnYWkgZm9ybWF0IGZpbGUgc2VwZXJ0aSBjc3YsIGV4Y2VsLCB0eHQsIHJkcywgeG1sLCBqc29uLCBkYW4gbGFpbi1sYWluLg0KDQpgYGB7ciBpbWFnZTEsIGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnMTAwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyAoImRvd25sb2FkLlBORyIpDQpgYGANCg0KDQojIEltcG9yL0Vrc3BvciBjc3YgIA0KDQpCZWlrdXQgaW5pIGFkYWxhaCBiZWJlcmFwYSBjYXJhIHlhbmcgZGFwYXQgZGlsYWt1a2FuIGRhbGFtIGltcG9yL2Vrc3BvciBkYXRhIG1lbmdndW5ha2FuIFIuDQoNCiMjIENhcmEgMSAgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KTWVuZ2d1bmFrYW4gZnVuZ3NpIGdldHdkKCkgdW50dWsgbWVuZ2V0YWh1aSBkaXJla3RvcmkgeWFuZyBzZWRhbmcgZGlndW5ha2FuLg0KYGBge3J9DQpwcmludChnZXR3ZCgpKQ0KZ2V0d2QoKQ0KYGBgDQpzZXR3ZCgpIGRpZ3VuYWthbiB1bnR1ayBtZW5nYXR1ciBkaXJla3Rvcmkga2VyamEgYmFydS4NCmBgYHtyfQ0Kc2V0d2QoZ2V0d2QoKSkNCmBgYA0KDQpLZW11ZGlhbiwgbWVuZ2ltcG9yIGRhdGEgQ1NWIG1lbmdndW5ha2FuIGZ1bmdzaSByZWFkLmNzdigpLg0KYGBge3J9DQojIGltcG9yIGRhdGENCmRmMSA8LXJlYWQuY3N2KCJJTlBVVC9pbnB1dDEuY3N2IixzZXAgPSAiLCIpICMgZm9ybWF0IHBlbWlzYWgga29tYSANCmRmMiA8LXJlYWQuY3N2KCJJTlBVVC9pbnB1dDIuY3N2IixzZXAgPSAiOyIpICMgZm9ybWF0IHBlbWlzYWggdGl0aWsga29tYQ0KYGBgDQoNCndyaXRlLmNzdigpIGZ1bmdzaSB5YW5nIGRpZ3VuYWthbiB1bnR1ayBtZW5nZWtzcG9yIGRhdGEgeWFuZyBkaWluZ2lua2FuIGtlIGRpcmVrdG9yaS4gDQpgYGB7cn0NCiMgZWtzcG9yIGRhdGENCndyaXRlLmNzdihkZjEsIk9VVFBVVC9vdXRwdXQxLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0Kd3JpdGUuY3N2KGRmMiwiT1VUUFVUL291dHB1dDIuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMgQ2FyYSAyDQoNCk1lbmdndW5ha2FuIGtvbmVrc2kgZGlyZWt0b3JpIHNlY2FyYSBvdG9tYXRpcy4NCmBgYHtyfQ0KKFdEIDwtIGdldHdkKCkpDQppZiAoIWlzLm51bGwoV0QpKSBzZXR3ZChXRCkNCmBgYA0KDQpgYGB7cn0NCiMgaW1wb3IgZGF0YQ0KZGYxIDwtIHJlYWQuY3N2KGZpbGUucGF0aChXRCwgIklOUFVUIiwgJ2lucHV0MS5jc3YnKSkNCmRmMiA8LSByZWFkLmNzdihmaWxlLnBhdGgoV0QsICJJTlBVVCIsICdpbnB1dDIuY3N2JykpDQpgYGANCg0KYGBge3J9DQojIGVrc3BvciBkYXRhIA0Kd3JpdGUuY3N2KGRmMSwgZmlsZS5wYXRoKFdELCAiT1VUUFVUIiwgIm91dHB1dDEiKSkNCndyaXRlLmNzdihkZjEsIGZpbGUucGF0aChXRCwgIk9VVFBVVCIsICJvdXRwdXQyIikpDQpgYGANCg0KIyMgQ2FyYSAzDQoNCkNhcmEgdGVyYWtoaXIgdGlkYWsgcGVybHUgbWVsYWt1a2FuIHBlbmdhdHVyYW4gZGlyZWt0b3JpIHRlcmxlYmloIGRhaHVsdSBzZWJlbHVtIG1lbGFrdWthbiBwcm9zZXMgbWVuZ2ltcG9yIGRhdGEgaGFueWEgcGVybHUgbWVtaWxpaCBkYXRhIHlhbmcgdGVyc2ltcGFuIGRpIHBjLg0KYGBge3J9DQojIGRpZ3VuYWthbiB1bnR1ayBtZW1pbGloIGRhdGENCmRmMyA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpKQ0KYGBgDQoNCiMgSW1wb3IvRWtzcG9yIEV4ZWwgDQoNCkZ1bmdzaSByZWFkeGwgZGFwYXQgbWVtYmFjYSBsYW5nc3VuZyBmaWxlIGRhdGEgZGFyaSBleGVsIHlhbmcgdGVyc2ltcGFuIGRhbGFtIGZvcm1hdCB4bHMveGxzbC4gIA0KDQpgYGB7cn0NCiMgdW50dWsgbWVuZ2luc3RhbGwgcGFja2FnZXMgcmVhZHhsLCB3cml0ZXhsLCBkYW4gcGFjbWFuIA0KcGFjbWFuOjpwX2xvYWQocmVhZHhsLCB3cml0ZXhsKSAgICAgICAgICAgICAgICAgIA0KYGBgDQoNCmBgYHtyfQ0KIyBpbXBvciBkYXRhDQpkZjM8LXJlYWRfZXhjZWwoJ0lOUFVUL2lucHV0NC54bHMnKSAgICAgICAgICMgaW1wb3IgZGF0YSB4bHMgKDk3LTIwMDMpDQpkZjQ8LXJlYWRfZXhjZWwoIklOUFVUL2lucHV0My54bHN4IixzaGVldD0xKSMgaW1wb3IgZGF0YSB4bHN4ICgyMDAzLXVwKQ0KYGBgDQoNCg0KYGBge3J9DQojIGVrc3BvciBkYXRhDQp3cml0ZV94bHN4KGRmMywiT1VUUFVUL291dHB1dDMueGxzIikgDQp3cml0ZV94bHN4KGRmNCwiT1VUUFVUL291dHB1dDQueGxzeCIpDQpgYGANCg0KDQojIEltcG9yL0Vrc3BvciBUWFQgYW5kIFJEUyANCg0KU2FhdCBtZWxha3VrYW4gaW1wb3IvZWtzcG9yIGRpc2FyYW5rYW4gbWVuZ2d1bmFrYW4gZm9ybWF0IFRYVCBhdGF1IFJEUyBrYXJlbmEgdWt1cmFuIGZpbGUgbGViaWgga2VjaWwgZGliYW5kaW5na2FuIENTViBhdGF1IFhMU1guIFNlaGluZ2dhIGRhcGF0IGRlbmdhbiBjZXBhdCBtZWxha3VrYW4gaW1wb3IvZWtzcG9yIGRhdGEuDQpgYGB7cn0NCiMgY2FyYSB1bnR1ayBtZW5naW1wb3IgZGF0YSANCmRmNSA8LSByZWFkLnRhYmxlKCJJTlBVVC9pbnB1dDUudHh0IikgICAgICAgIyBmb3JtYXQgVFhUIChub3RlcGFkKQ0KZGY2IDwtIHNvdXJjZSgiSU5QVVQvaW5wdXQ2LlJkbXBkIikgICAgICAgICAjIGZvcm1hdCBUWFQgKFJkbXApDQpkZjcgPC0gcmVhZFJEUygiSU5QVVQvaW5wdXQ3LnJkcyIpICAgICAgICAgICMgZm9ybWF0IGJpbmFyeSBSRFMNCmRmOCA8LSByZWFkUkRTKCJJTlBVVC9pbnB1dDguYXNjaWkiKSAgICAgICAgIyBmb3JtYXQgYmluYXJ5IEFTQ0lJDQpgYGANCg0KYGBge3J9DQojIGNhcmEgdW50dWsgbWVuZ2Vrc3BvciBkYXRhDQp3cml0ZS50YWJsZShkZjUsIk9VVFBVVC9vdXRwdXQ1LnR4dCIpDQpkdW1wKCJkZjYiLCAiT1VUUFVUL291dHB1dDYuUmRtcCIpDQpzYXZlUkRTKGRmNywgIk9VVFBVVC9vdXRwdXQ3LnJkcyIpDQpzYXZlUkRTKGRmOCwgIk9VVFBVVC9vdXRwdXQ4LmFzY2lpIiwgYXNjaWkgPSBUUlVFKQ0KYGBgDQoNCg0KIyBJbXBvci9Fa3Nwb3IgWE1MDQoNClhNTCBtZXJ1cGFrYW4ga3VtcHVsYW4gZGFyaSBiZXJiYWdhaSBmb3JtYXQgZmlsZSBkYW4gZGF0YSBkaSBXb3JsZCBXaWRlIFdlYiwgaW50cmFuZXQgbWVuZ2d1bmFrYW4gdGVrcyBBU0NJSSBzdGFuZGFyLg0KDQpTZWJlbHVtIG1lbGFrdWthbiBpbXBvci9la3Nwb3IgZGF0YSBJbnN0YWxsIHBhY2thZ2VzIHRlcmxlYmloIGRhaHVsdSBzZXBlcnRpIGRpYmF3YWggaW5pLg0KYGBge3J9DQpsaWJyYXJ5KCJYTUwiKQ0KbGlicmFyeSgia3VsaWZlIikNCmxpYnJhcnkoIm1ldGhvZHMiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBpbXBvciBkYXRhIGtlIFhNTA0KZGY5IDwtIHhtbFBhcnNlKCJJTlBVVC9pbnB1dDkueG1sIikNCmBgYA0KDQpgYGB7cn0NCiMga29udmVyc2kga2UgZGF0YSBmcmFtZQ0KeG1sX2RmIDwtIHhtbFRvRGF0YUZyYW1lKGRmOSkNCmBgYA0KDQpgYGB7cn0NCiMgZWtzcG9yIGRhdGEga2UgWE1MDQp3cml0ZS54bWwoeG1sX2RmLCAiT1VUUFVUL291dHB1dDkueG1sIikNCmBgYA0KDQoNCiMgSW1wb3IvRWtzcG9yIEpTT04gDQoNCkpTT04gYWRhbGFoIHNpbmdrYXRhbiBkYXJpIEphdmFTY3JpcHQgT2JqZWN0IE5vdGF0aW9uLiBGdW5nc2kganNvbmxpdGUgZGkgUiBkYXBhdCBtZW1iYWNhIGZpbGUgSlNPTi4NCmBgYHtyfQ0KIyBpbnN0YWxsIGxpYnJhcnkganNvbmxpdGUgdGVybGViaWggZGFodWx1DQpsaWJyYXJ5KCJqc29ubGl0ZSIpDQpgYGANCg0KYGBge3J9DQojIGNhcmEgdW50dWsgbWVuZ2ltcG9yIGRhdGEgSlNPTg0KZGYxMCA8LSBmcm9tSlNPTigiSU5QVVQvaW5wdXQxMC5qc29uIikNCmBgYA0KDQpgYGB7cn0NCiMgbWVuZ3ViYWggZGF0YSBtZW5qYWRpIGRhdGEgZnJhbWUNCmpzb25fZGYgPC0gYXMuZGF0YS5mcmFtZShkZjEwKQ0KYGBgDQoNCmBgYHtyfQ0KIyBjYXJhIHVudHVrIG1lbmdla3Nwb3IgZGF0YSBKU09ODQp3cml0ZV9qc29uKGpzb25fZGYsICJPVVRQVVQvb3V0cHV0MTAuanNvbiIpDQpgYGANCg0KIyBJbXBvciBEYXRhIGRhcmkgV2ViDQoNCk1lbmdpbXBvciBkYXRhIGRhcmkgc3VhdHUgc2l0dXMgd2ViLg0KDQojIyBDU1YgIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQpJbXBvciBkYXRhIFdlYiBtZW5nZ3VuYWthbiBDU1YuDQpgYGB7cn0NCndlYl9jc3YgPC0gcmVhZC5jc3YoImh0dHBzOi8vd3d3LmxpcHV0YW42LmNvbS9nbG9iYWwvcmVhZC80NjI1ODQ1L3BvaG9uLWhhbnR1LWluaS01LWhhbC1tZW5ha2p1Ymthbi1kaS1hbGFtLXlhbmctc3VsaXQtZGlwZXJjYXlhL2NzdjEuY3N2IikNCmBgYA0KDQojIyBYTFNYDQpJbXBvciBkYXRhIHdlYiBtZW5nZ3VuYWthbiBYTFNYLkppa2EgbWVuZ2ltcG9yIGRhdGEgZGFyaSByZXBvc2l0b3JpIEdpdEh1Yi4gTWFrYSB0ZXJsZWJpaCBkYWh1bHUgbWVuZ2luc3RhbGwgcGFja2FnZXMgcmlvLg0KYGBge3J9DQpsaWJyYXJ5KHJpbykNCmluc3RhbGxfZm9ybWF0cygpDQpgYGANCmBgYHtyfQ0Kd2ViX3hsc3ggPC0gcmlvOjppbXBvcnQoImh0dHBzOi8vZ2l0aHViLmNvbS9CYWt0aS1TaXJlZ2FyL2RhdGFzZXQvYmxvYi9tYXN0ZXIvQm9va2Rvd24tRGF0YS1TY2llbmNlLWZvci1CZWdpbm5lcnMveGxzeDEueGxzeD9yYXc9dHJ1ZSIpDQpgYGANCg0KRGFuIGppa2EgdGlkYWsgZGFyaSByZXBvc2l0b3JpIEdpdEh1YiBtYWthIGxhbmdzdW5nIHNhamEgbWVuZ2d1bmFrYW4gcmVhZC5jc3YoKQ0KYGBge3J9DQpyZWFkLmNzdigiaHR0cHM6Ly93d3cubGlwdXRhbjYuY29tL2dsb2JhbC9yZWFkLzQ2MjU4NDUvcG9ob24taGFudHUtaW5pLTUtaGFsLW1lbmFranVia2FuLWRpLWFsYW0teWFuZy1zdWxpdC1kaXBlcmNheWEveGxzeDEueGxzeD9yYXc9dHJ1ZSIpDQpgYGANCg0KIyBCYXNpcyBEYXRhIFINCg0KU2lzdGVtIGJhc2lzIGRhdGEgbWVydXBha2FuIHNlYnVhaCBkYXRhIHlhbmcgZGkgcmVsYXNpb25hbCBkYW4gZGlzaW1wYW4gZGFsYW0gZm9ybWF0IHlhbmcgZGlub3JtYWxpc2FzaS4gUiBiaXNhIHRlcmh1YnVuZyBkZW5nYW4gbXVkYWgga2UgYmFueWFrIGRhdGFiYXNlIHJlbGFzaW9uYWwgc2VwZXJ0aSBNeVNxbCwgT3JhY2xlLCBTUUwgU2VydmVyLCBkYW4gbGFpbi1sYWluLg0KDQoNCiMgTWVuYW1iYW5nIERhdGEgV2ViDQoNCk1lbmFtYmFuZyBkYXRhIHdlYiBhdGF1IFdlYnNjcmFwaW5nIERhdGEgbWVydXBha2FuIHNlYnVhaCBwcm9zZXMgbWVuZ2d1bmFrYW4gYm90IHVudHVrIG1lbmdla3N0cmFrIGtvbnRlbiBkYW4gZGF0YSBkYXJpIHN1YXR1IHNpdHVzIHdlYi4gV2ViIFNjcmFwaW5nIGRhcGF0IG1lbmdla3N0cmFrIHN1YXR1IGtvZGUgSFRNTCBkYXNhciB5YW5nIHBhZGEgZGFzYXJueWEgZGlzaW1wYW4gZGFsYW0gZGF0YWJhc2UuIA0KDQoNCiMgUmVmZXJlbnNpIA0KDQoxLiBodHRwczovL2lkLndpa2lwZWRpYS5vcmcvd2lraS9SXyhiYWhhc2FfcGVtcm9ncmFtYW4pIA0KMi4gaHR0cHM6Ly9kYXJ5dXNtYW4ud29yZHByZXNzLmNvbS8yMDE4LzA0LzI1L3dvcmtpbmctZGlyZWN0b3J5LWRpLXBlbXJvZ3JhbWFuLXIvDQoNCg==