Algoritma & Struktur Data

~ Antarmuka Data dengan R ~


Kontak : \(\downarrow\)
Email
RPubs https://rpubs.com/kentzend03/

Pendahuluan

Terhubung dengan data adalah hal paling mendasar dalam proses olah data (Data Science). Pada bagian ini akan dibahas bagaimana proses antarmuka data yang paling sederhana dengan menggunakan R. Secara garis besar R dapat membaca data dari file yang disimpan di dalam maupun di luar direktorinya. Selain itu, sistem operasi R juga dapat menyimpan dan membaca data dalam format file seperti csv, excel, txt, rds, xml, json, dll.

Impor/Ekspor CSV

Terdapat beberapa cara yang dapat dilakukan untuk impor/ekspor data dengan R. Berikut ini diperlihatkan 3 cara yang paling sering digunakan dalam proses antarmuka data.

Cara 1

Pertama - tama, pastikan direktori kerja anda dalam koneksi yang benar, periksalah dengan menggunakan fungsi getwd(). Kemudian anda dapat mengaturdirektori baru menggunakan fungsi setwd().

print(getwd())
## [1] "D:/Fisika Medis/Algoritma dan Struktur Data/Tugas 10"
getwd()
## [1] "D:/Fisika Medis/Algoritma dan Struktur Data/Tugas 10"
setwd(getwd())

# Impor Data csv
df1 <-read.csv("Input/input1.csv",sep = ",") # format pemisah koma
df2 <-read.csv("Input/input2.csv",sep = ";") # format pemisah titik koma

# Ekpor Data csv
write.csv(df1,"Output/output1.csv", row.names = FALSE)
write.csv(df2,"Output/output2.csv", row.names = FALSE) 

Cara 2

Bagi anda yang lebih menyukai koneksi direktori secara otomatis, cara ini adalah pilihan yang lebih bijak dan praktis

(Ya <- getwd())
## [1] "D:/Fisika Medis/Algoritma dan Struktur Data/Tugas 10"
if (!is.null(Ya)) setwd(Ya)

# Impor Data
df1 <- read.csv(file.path(Ya,'Input', 'input1.csv'))
df2 <- read.csv(file.path(Ya,'Input', 'input2.csv'))

#Ekspor Data
write.csv(df1, file.path(Ya, 'Output', 'File1.csv'), row.names = FALSE)
write.csv(df2, file.path(Ya, 'Output', 'File2.csv'), row.names = FALSE)

Cara 3

Cara ini adalah cara alternatif bagi anda yang lebih nyaman untuk memilih data yang tersimpan di komputer (PC) tanpa harus melakukan pengaturan direktori terlebih dahulu sebelum melakukan proses impor data.

df<-read.csv(file.choose())

Impor/Ekspor Excel

Microsoft Excel adalah program spreadsheet yang paling banyak digunakan yang mwnyimpan data dalam format .xls atau .xlsx. R dapat membaca langsung dari file-file ini menggunakan paket readxl

# install.packages(c("readxl", "writexl"))   # install `readxl & writexl` 
pacman::p_load(readxl, writexl)              # 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

Format data paling umum yang sering digunakan untuk impor/ekspor data adalah file csv dan xlsx. Namun ukuran file CSV dan XLSX cenderung lebih besar dibandingkan format yang lainnya seperti TXT atau file binEr R (RDS). Sehingga ini akan membutuhkan tambahan waktu pada saat anda melakukan impor/ekspor data. Tips yang sangat saya rekomendasikan dalam hal ini adalah mengimpor dan eksper data tersebut dengan dengan format TXT atau binary

# Impor Data
df5<-read.table('input/input5.txt')
df6<-source('input/input6.Rdmpd')
df7<-readRDS('input/input7.rds')
df8<-readRDS('input/input8.ascii')

# Ekspor Data
write.table(df5,'output/output5.txt')
dump('df6','output/output6.Rdmpd')
saveRDS(df7,'output/output7.rds')
saveRDS(df8,'output/output8.ascii',ascii=TRUE)

Impor/Ekspor XML

XML adalah kumpulan berbagai format file dan data di World Wide Web, internet, dan di tempat lain menggunakan teks ASCII standar. XML adalah singkatan dari eXtensible Markup Language.

Sebenarnya XML sangat mirip dengan HTML, dimana sintak-sintaknya berisi markup. Tetapi, perlu dicatat bahwa XML tidak sama dengan hal tag markup HTML yang menjelaskan laman struktur datanya terdapat dalam file tersebut.

Selanjutnya, mari kita lakukan impor/ekspor data dengan format XML

pacman::p_load(XML,kulife,methods)        # Load packages

library("XML")          # load paket XML
library("kulife")       # load paket kulife
library("methods")      # paket kondisional

df9<-xmlParse('Input/input9.xml')          # Impor data XML
xml_df<-xmlToDataFrame(df9)                # Konversi dataframe
write.xml(xml_df,'Output/File9.xml')     # Ekspor data XML

Impor/Ekspor JSON

File JSON menyimpan data sebagai text dalam format yang dapat dibaca oleh manusia. JSON adalah singkatan dari JavaScript Object Notation. R dapat membaca file JSON menggunakan paket jsonlite

library("jsonlite")

df10<-fromJSON('Input/input10.json')          # Impor data JSON
json_df<-as.data.frame(df10)                # Konversi dataframe
write_json(json_df,'Output/File10.json')     # Ekspor data JSON

Impor Data dari Web

Ada banyak website menyediakan data untuk dikonsumsi oleh penggunanya. Dengan menggunakan program R, kita dapat mengekstrak data spesifik dari situs web tersebut secara terprogram. Dibagian ini saya memberi contoh cara mengimpor data dari repositori GitHub, tetapi, anda dapat melakukan hal yang sama ke situs web atau repositori lain.

# CSV
web_csv<-read.csv("https://github.com/Bakti-Siregar/dataset/raw/master/Bookdown-Data-Science-for-Beginners/csv1.csv")

# XLSX
pacman::p_load(rio)           # Instal Package
library(rio)                  # Import Data dari GitHub
install_formats()             # Periksa auto paket yang di sarankan
## [1] TRUE
web_xlsx<-rio::import('https://github.com/Bakti-Siregar/dataset/blob/master/Bookdown-Data-Science-for-Beginners/xlsx1.xlsx?raw=true')

Basis Data R

Sistem basis data adalah data relasional yang disimpan dalam format yang dinormalisasi. Untuk melakukan komputasi statistik dibutuhkan query SQL yang sangat canggih dan kompleks. Tetapi R dapat dengan mudah terhubung ke banyak database relasional seperti MySql, Oracle, SQL, Server, dll. Selanjutnya biasanya, kita akan mengubah basis data tersebut menjadi bingkai data (Data Frame). Setelah data tersedia di lingkungan R, kemudian dimanipulasi atau dilakukan analisis lebih lanjut.

Menambang Data Web

Pengikisan dari data web (Webscraping Data) adalah proses menggunakan bot yang mengesktrak konten dan data dari situs web. Tidak seperti screen scraping, yang hanya menyalin piksel yang ditampilkan di layar, web scraping mengekstrak kode HTML yang mendasarinya yang pada dasarnya di simpan dalam data base. Pengikisan data ini dapat mereplikasi seluruh konten dari berbagai situs web yang ditargetkan.

LS0tDQp0aXRsZTogIkFsZ29yaXRtYSAmIFN0cnVrdHVyIERhdGEiDQpzdWJ0aXRsZTogIn4gQW50YXJtdWthIERhdGEgZGVuZ2FuIFIgfiINCmF1dGhvcjogIktlbnQgSnVhbiBOYXRhbmllbCBZYW9pc29raGkgWmVuZHJhdG8gKDIwMjE0NTIwMDA0KSINCmRhdGU6ICAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIHJtZGZvcm1hdHM6OnJvYm9ib29rOiAgICMgaHR0cHM6Ly9naXRodWIuY29tL2p1YmEvcm1kZm9ybWF0cw0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdGh1bWJuYWlsczogdHJ1ZQ0KICAgIGxpZ2h0Ym94OiB0cnVlDQogICAgZ2FsbGVyeTogdHJ1ZQ0KICAgIGxpYl9kaXI6IGxpYnMNCiAgICBkZl9wcmludDogInBhZ2VkIg0KICAgIGNvZGVfZm9sZGluZzogInNob3ciDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgY3NzOiAic3R5bGUuY3NzIg0KDQotLS0NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChjbGFzcy5zb3VyY2UgPSAibm9jb3B5IiwNCiAgICAgICAgICAgICAgICAgICAgICBjbGFzcy5vdXRwdXQgPSAibm9jb3B5IiwNCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRiwNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRikNCg0KbGlicmFyeShyZXRpY3VsYXRlKQ0KbGlicmFyeShSY3BwKQ0KDQpgYGANCg0KPGJyPg0KDQo8aW1nIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbjogLTgwcHggNTBweCAwcHggNTBweDsgd2lkdGg6MjUlIiBzcmM9IkZvdG8ucG5nIi8+IA0KDQp8DQo6LS0tLSB8Oi0tLS0NCioqS29udGFrKip8ICoqOiAkXGRvd25hcnJvdyQqKg0KRW1haWx8IGtlbnQuemVuZHJhdG9Ac3R1ZGVudC5tYXRhbmF1bml2ZXJzaXR5LmFjLmlkDQpSUHVicyAgfCBodHRwczovL3JwdWJzLmNvbS9rZW50emVuZDAzLw0KDQoqKioNCg0KIyBQZW5kYWh1bHVhbg0KDQpUZXJodWJ1bmcgZGVuZ2FuIGRhdGEgYWRhbGFoIGhhbCBwYWxpbmcgbWVuZGFzYXIgZGFsYW0gcHJvc2VzIG9sYWggZGF0YSAoRGF0YSBTY2llbmNlKS4gUGFkYSBiYWdpYW4gaW5pIGFrYW4gZGliYWhhcyBiYWdhaW1hbmEgcHJvc2VzIGFudGFybXVrYSBkYXRhIHlhbmcgcGFsaW5nIHNlZGVyaGFuYSBkZW5nYW4gbWVuZ2d1bmFrYW4gUi4gU2VjYXJhIGdhcmlzIGJlc2FyIFIgZGFwYXQgbWVtYmFjYSBkYXRhIGRhcmkgZmlsZSB5YW5nIGRpc2ltcGFuIGRpIGRhbGFtIG1hdXB1biBkaSBsdWFyIGRpcmVrdG9yaW55YS4gU2VsYWluIGl0dSwgc2lzdGVtIG9wZXJhc2kgUiBqdWdhIGRhcGF0IG1lbnlpbXBhbiBkYW4gbWVtYmFjYSBkYXRhIGRhbGFtIGZvcm1hdCBmaWxlIHNlcGVydGkgY3N2LCBleGNlbCwgdHh0LCByZHMsIHhtbCwganNvbiwgZGxsLg0KDQo8aW1nIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbjogMHB4IDBweCAwcHggMHB4OyB3aWR0aDoxMDAlIiBzcmM9Ik9rLnBuZyIvPg0KDQojIEltcG9yL0Vrc3BvciBDU1YNCg0KVGVyZGFwYXQgYmViZXJhcGEgY2FyYSB5YW5nIGRhcGF0IGRpbGFrdWthbiB1bnR1ayBpbXBvci9la3Nwb3IgZGF0YSBkZW5nYW4gUi4gQmVyaWt1dCBpbmkgZGlwZXJsaWhhdGthbiAzIGNhcmEgeWFuZyBwYWxpbmcgc2VyaW5nIGRpZ3VuYWthbiBkYWxhbSBwcm9zZXMgYW50YXJtdWthIGRhdGEuDQoNCiMjIENhcmEgMQ0KDQpQZXJ0YW1hIC0gdGFtYSwgcGFzdGlrYW4gZGlyZWt0b3JpIGtlcmphIGFuZGEgZGFsYW0ga29uZWtzaSB5YW5nIGJlbmFyLCBwZXJpa3NhbGFoIGRlbmdhbiBtZW5nZ3VuYWthbiBmdW5nc2kgZ2V0d2QoKS4gS2VtdWRpYW4gYW5kYSBkYXBhdCBtZW5nYXR1cmRpcmVrdG9yaSBiYXJ1IG1lbmdndW5ha2FuIGZ1bmdzaSBzZXR3ZCgpLg0KDQpgYGB7cn0NCnByaW50KGdldHdkKCkpDQpnZXR3ZCgpDQpzZXR3ZChnZXR3ZCgpKQ0KDQojIEltcG9yIERhdGEgY3N2DQpkZjEgPC1yZWFkLmNzdigiSW5wdXQvaW5wdXQxLmNzdiIsc2VwID0gIiwiKSAjIGZvcm1hdCBwZW1pc2FoIGtvbWENCmRmMiA8LXJlYWQuY3N2KCJJbnB1dC9pbnB1dDIuY3N2IixzZXAgPSAiOyIpICMgZm9ybWF0IHBlbWlzYWggdGl0aWsga29tYQ0KDQojIEVrcG9yIERhdGEgY3N2DQp3cml0ZS5jc3YoZGYxLCJPdXRwdXQvb3V0cHV0MS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCndyaXRlLmNzdihkZjIsIk91dHB1dC9vdXRwdXQyLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKSANCmBgYA0KDQojIyBDYXJhIDINCg0KQmFnaSBhbmRhIHlhbmcgbGViaWggbWVueXVrYWkga29uZWtzaSBkaXJla3Rvcmkgc2VjYXJhIG90b21hdGlzLCBjYXJhIGluaSBhZGFsYWggcGlsaWhhbiB5YW5nIGxlYmloIGJpamFrIGRhbiBwcmFrdGlzDQoNCmBgYHtyfQ0KKFlhIDwtIGdldHdkKCkpDQppZiAoIWlzLm51bGwoWWEpKSBzZXR3ZChZYSkNCg0KIyBJbXBvciBEYXRhDQpkZjEgPC0gcmVhZC5jc3YoZmlsZS5wYXRoKFlhLCdJbnB1dCcsICdpbnB1dDEuY3N2JykpDQpkZjIgPC0gcmVhZC5jc3YoZmlsZS5wYXRoKFlhLCdJbnB1dCcsICdpbnB1dDIuY3N2JykpDQoNCiNFa3Nwb3IgRGF0YQ0Kd3JpdGUuY3N2KGRmMSwgZmlsZS5wYXRoKFlhLCAnT3V0cHV0JywgJ0ZpbGUxLmNzdicpLCByb3cubmFtZXMgPSBGQUxTRSkNCndyaXRlLmNzdihkZjIsIGZpbGUucGF0aChZYSwgJ091dHB1dCcsICdGaWxlMi5jc3YnKSwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMgQ2FyYSAzDQoNCkNhcmEgaW5pIGFkYWxhaCBjYXJhIGFsdGVybmF0aWYgYmFnaSBhbmRhIHlhbmcgbGViaWggbnlhbWFuIHVudHVrIG1lbWlsaWggZGF0YSB5YW5nIHRlcnNpbXBhbiBkaSBrb21wdXRlciAoUEMpIHRhbnBhIGhhcnVzIG1lbGFrdWthbiBwZW5nYXR1cmFuIGRpcmVrdG9yaSB0ZXJsZWJpaCBkYWh1bHUgc2ViZWx1bSBtZWxha3VrYW4gcHJvc2VzIGltcG9yIGRhdGEuDQoNCmBgYHtyfQ0KZGY8LXJlYWQuY3N2KGZpbGUuY2hvb3NlKCkpDQpgYGANCg0KIyBJbXBvci9Fa3Nwb3IgRXhjZWwNCg0KTWljcm9zb2Z0IEV4Y2VsIGFkYWxhaCBwcm9ncmFtIHNwcmVhZHNoZWV0IHlhbmcgcGFsaW5nIGJhbnlhayBkaWd1bmFrYW4geWFuZyBtd255aW1wYW4gZGF0YSBkYWxhbSBmb3JtYXQgLnhscyBhdGF1IC54bHN4LiBSIGRhcGF0IG1lbWJhY2EgbGFuZ3N1bmcgZGFyaSBmaWxlLWZpbGUgaW5pIG1lbmdndW5ha2FuIHBha2V0IHJlYWR4bA0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcyhjKCJyZWFkeGwiLCAid3JpdGV4bCIpKSAgICMgaW5zdGFsbCBgcmVhZHhsICYgd3JpdGV4bGAgDQpwYWNtYW46OnBfbG9hZChyZWFkeGwsIHdyaXRleGwpICAgICAgICAgICAgICAjIGxvYWQgYHJlYWR4bCAmIHdyaXRleGxgDQoNCiMgSW1wb3IgRGF0YQ0KZGYzPC1yZWFkX2V4Y2VsKCJJbnB1dC9pbnB1dDQueGxzIikgICAgICAgICAgIyBpbXBvciBkYXRhIHhscyAoOTctMjAwMykNCmRmNDwtcmVhZF9leGNlbCgiSW5wdXQvaW5wdXQzLnhsc3giLHNoZWV0PTEpICMgaW1wb3IgZGF0YSB4bHN4ICgyMDAzLXVwKQ0KDQojIEVrc3BvciBEYXRhDQp3cml0ZV94bHN4KGRmMywiT3V0cHV0L291dHB1dDMueGxzIikgDQp3cml0ZV94bHN4KGRmNCwiT3V0cHV0L291dHB1dDQueGxzeCIpDQpgYGANCg0KIyBJbXBvci9Fa3Nwb3IgVFhUIGFuZCBSRFMNCg0KRm9ybWF0IGRhdGEgcGFsaW5nIHVtdW0geWFuZyBzZXJpbmcgZGlndW5ha2FuIHVudHVrIGltcG9yL2Vrc3BvciBkYXRhIGFkYWxhaCBmaWxlIGNzdiBkYW4geGxzeC4gTmFtdW4gdWt1cmFuIGZpbGUgQ1NWIGRhbiBYTFNYIGNlbmRlcnVuZyBsZWJpaCBiZXNhciBkaWJhbmRpbmdrYW4gZm9ybWF0IHlhbmcgbGFpbm55YSBzZXBlcnRpIFRYVCBhdGF1IGZpbGUgYmluRXIgUiAoUkRTKS4gU2VoaW5nZ2EgaW5pIGFrYW4gbWVtYnV0dWhrYW4gdGFtYmFoYW4gd2FrdHUgcGFkYSBzYWF0IGFuZGEgbWVsYWt1a2FuIGltcG9yL2Vrc3BvciBkYXRhLiBUaXBzIHlhbmcgc2FuZ2F0IHNheWEgcmVrb21lbmRhc2lrYW4gZGFsYW0gaGFsIGluaSBhZGFsYWggbWVuZ2ltcG9yIGRhbiBla3NwZXIgZGF0YSB0ZXJzZWJ1dCBkZW5nYW4gZGVuZ2FuIGZvcm1hdCBUWFQgYXRhdSBiaW5hcnkNCg0KYGBge3J9DQojIEltcG9yIERhdGENCmRmNTwtcmVhZC50YWJsZSgnaW5wdXQvaW5wdXQ1LnR4dCcpDQpkZjY8LXNvdXJjZSgnaW5wdXQvaW5wdXQ2LlJkbXBkJykNCmRmNzwtcmVhZFJEUygnaW5wdXQvaW5wdXQ3LnJkcycpDQpkZjg8LXJlYWRSRFMoJ2lucHV0L2lucHV0OC5hc2NpaScpDQoNCiMgRWtzcG9yIERhdGENCndyaXRlLnRhYmxlKGRmNSwnb3V0cHV0L291dHB1dDUudHh0JykNCmR1bXAoJ2RmNicsJ291dHB1dC9vdXRwdXQ2LlJkbXBkJykNCnNhdmVSRFMoZGY3LCdvdXRwdXQvb3V0cHV0Ny5yZHMnKQ0Kc2F2ZVJEUyhkZjgsJ291dHB1dC9vdXRwdXQ4LmFzY2lpJyxhc2NpaT1UUlVFKQ0KYGBgDQoNCiMgSW1wb3IvRWtzcG9yIFhNTA0KDQpYTUwgYWRhbGFoIGt1bXB1bGFuIGJlcmJhZ2FpIGZvcm1hdCBmaWxlIGRhbiBkYXRhIGRpIFdvcmxkIFdpZGUgV2ViLCBpbnRlcm5ldCwgZGFuIGRpIHRlbXBhdCBsYWluIG1lbmdndW5ha2FuIHRla3MgQVNDSUkgc3RhbmRhci4gWE1MIGFkYWxhaCBzaW5na2F0YW4gZGFyaSBlWHRlbnNpYmxlIE1hcmt1cCBMYW5ndWFnZS4NCg0KU2ViZW5hcm55YSBYTUwgc2FuZ2F0IG1pcmlwIGRlbmdhbiBIVE1MLCBkaW1hbmEgc2ludGFrLXNpbnRha255YSBiZXJpc2kgbWFya3VwLiBUZXRhcGksIHBlcmx1IGRpY2F0YXQgYmFod2EgWE1MIHRpZGFrIHNhbWEgZGVuZ2FuIGhhbCB0YWcgbWFya3VwIEhUTUwgeWFuZyBtZW5qZWxhc2thbiBsYW1hbiBzdHJ1a3R1ciBkYXRhbnlhIHRlcmRhcGF0IGRhbGFtIGZpbGUgdGVyc2VidXQuDQoNClNlbGFuanV0bnlhLCBtYXJpIGtpdGEgbGFrdWthbiBpbXBvci9la3Nwb3IgZGF0YSBkZW5nYW4gZm9ybWF0IFhNTA0KDQpgYGB7cn0NCnBhY21hbjo6cF9sb2FkKFhNTCxrdWxpZmUsbWV0aG9kcykgICAgICAgICMgTG9hZCBwYWNrYWdlcw0KDQpsaWJyYXJ5KCJYTUwiKSAgICAgICAgICAjIGxvYWQgcGFrZXQgWE1MDQpsaWJyYXJ5KCJrdWxpZmUiKSAgICAgICAjIGxvYWQgcGFrZXQga3VsaWZlDQpsaWJyYXJ5KCJtZXRob2RzIikgICAgICAjIHBha2V0IGtvbmRpc2lvbmFsDQoNCmRmOTwteG1sUGFyc2UoJ0lucHV0L2lucHV0OS54bWwnKSAgICAgICAgICAjIEltcG9yIGRhdGEgWE1MDQp4bWxfZGY8LXhtbFRvRGF0YUZyYW1lKGRmOSkgICAgICAgICAgICAgICAgIyBLb252ZXJzaSBkYXRhZnJhbWUNCndyaXRlLnhtbCh4bWxfZGYsJ091dHB1dC9GaWxlOS54bWwnKSAgICAgIyBFa3Nwb3IgZGF0YSBYTUwNCmBgYA0KDQojIEltcG9yL0Vrc3BvciBKU09ODQoNCkZpbGUgSlNPTiBtZW55aW1wYW4gZGF0YSBzZWJhZ2FpIHRleHQgZGFsYW0gZm9ybWF0IHlhbmcgZGFwYXQgZGliYWNhIG9sZWggbWFudXNpYS4gSlNPTiBhZGFsYWggc2luZ2thdGFuIGRhcmkgSmF2YVNjcmlwdCBPYmplY3QgTm90YXRpb24uIFIgZGFwYXQgbWVtYmFjYSBmaWxlIEpTT04gbWVuZ2d1bmFrYW4gcGFrZXQganNvbmxpdGUNCg0KYGBge3J9DQpsaWJyYXJ5KCJqc29ubGl0ZSIpDQoNCmRmMTA8LWZyb21KU09OKCdJbnB1dC9pbnB1dDEwLmpzb24nKSAgICAgICAgICAjIEltcG9yIGRhdGEgSlNPTg0KanNvbl9kZjwtYXMuZGF0YS5mcmFtZShkZjEwKSAgICAgICAgICAgICAgICAjIEtvbnZlcnNpIGRhdGFmcmFtZQ0Kd3JpdGVfanNvbihqc29uX2RmLCdPdXRwdXQvRmlsZTEwLmpzb24nKSAgICAgIyBFa3Nwb3IgZGF0YSBKU09ODQpgYGANCg0KIyBJbXBvciBEYXRhIGRhcmkgV2ViDQoNCkFkYSBiYW55YWsgd2Vic2l0ZSBtZW55ZWRpYWthbiBkYXRhIHVudHVrIGRpa29uc3Vtc2kgb2xlaCBwZW5nZ3VuYW55YS4gRGVuZ2FuIG1lbmdndW5ha2FuIHByb2dyYW0gUiwga2l0YSBkYXBhdCBtZW5nZWtzdHJhayBkYXRhIHNwZXNpZmlrIGRhcmkgc2l0dXMgd2ViIHRlcnNlYnV0IHNlY2FyYSB0ZXJwcm9ncmFtLiBEaWJhZ2lhbiBpbmkgc2F5YSBtZW1iZXJpIGNvbnRvaCBjYXJhIG1lbmdpbXBvciBkYXRhIGRhcmkgcmVwb3NpdG9yaSBHaXRIdWIsIHRldGFwaSwgYW5kYSBkYXBhdCBtZWxha3VrYW4gaGFsIHlhbmcgc2FtYSBrZSBzaXR1cyB3ZWIgYXRhdSByZXBvc2l0b3JpIGxhaW4uDQoNCmBgYHtyfQ0KIyBDU1YNCndlYl9jc3Y8LXJlYWQuY3N2KCJodHRwczovL2dpdGh1Yi5jb20vQmFrdGktU2lyZWdhci9kYXRhc2V0L3Jhdy9tYXN0ZXIvQm9va2Rvd24tRGF0YS1TY2llbmNlLWZvci1CZWdpbm5lcnMvY3N2MS5jc3YiKQ0KDQojIFhMU1gNCnBhY21hbjo6cF9sb2FkKHJpbykgICAgICAgICAgICMgSW5zdGFsIFBhY2thZ2UNCmxpYnJhcnkocmlvKSAgICAgICAgICAgICAgICAgICMgSW1wb3J0IERhdGEgZGFyaSBHaXRIdWINCmluc3RhbGxfZm9ybWF0cygpICAgICAgICAgICAgICMgUGVyaWtzYSBhdXRvIHBha2V0IHlhbmcgZGkgc2FyYW5rYW4NCg0Kd2ViX3hsc3g8LXJpbzo6aW1wb3J0KCdodHRwczovL2dpdGh1Yi5jb20vQmFrdGktU2lyZWdhci9kYXRhc2V0L2Jsb2IvbWFzdGVyL0Jvb2tkb3duLURhdGEtU2NpZW5jZS1mb3ItQmVnaW5uZXJzL3hsc3gxLnhsc3g/cmF3PXRydWUnKQ0KYGBgDQoNCiMgQmFzaXMgRGF0YSBSDQoNClNpc3RlbSBiYXNpcyBkYXRhIGFkYWxhaCBkYXRhIHJlbGFzaW9uYWwgeWFuZyBkaXNpbXBhbiBkYWxhbSBmb3JtYXQgeWFuZyBkaW5vcm1hbGlzYXNpLiBVbnR1ayBtZWxha3VrYW4ga29tcHV0YXNpIHN0YXRpc3RpayBkaWJ1dHVoa2FuIHF1ZXJ5IFNRTCB5YW5nIHNhbmdhdCBjYW5nZ2loIGRhbiBrb21wbGVrcy4gVGV0YXBpIFIgZGFwYXQgZGVuZ2FuIG11ZGFoIHRlcmh1YnVuZyBrZSBiYW55YWsgZGF0YWJhc2UgcmVsYXNpb25hbCBzZXBlcnRpIE15U3FsLCBPcmFjbGUsIFNRTCwgU2VydmVyLCBkbGwuIFNlbGFuanV0bnlhIGJpYXNhbnlhLCBraXRhIGFrYW4gbWVuZ3ViYWggYmFzaXMgZGF0YSB0ZXJzZWJ1dCBtZW5qYWRpIGJpbmdrYWkgZGF0YSAoRGF0YSBGcmFtZSkuIFNldGVsYWggZGF0YSB0ZXJzZWRpYSBkaSBsaW5na3VuZ2FuIFIsIGtlbXVkaWFuIGRpbWFuaXB1bGFzaSBhdGF1IGRpbGFrdWthbiBhbmFsaXNpcyBsZWJpaCBsYW5qdXQuDQoNCiMgTWVuYW1iYW5nIERhdGEgV2ViDQoNClBlbmdpa2lzYW4gZGFyaSBkYXRhIHdlYiAoV2Vic2NyYXBpbmcgRGF0YSkgYWRhbGFoIHByb3NlcyBtZW5nZ3VuYWthbiBib3QgeWFuZyBtZW5nZXNrdHJhayBrb250ZW4gZGFuIGRhdGEgZGFyaSBzaXR1cyB3ZWIuIFRpZGFrIHNlcGVydGkgc2NyZWVuIHNjcmFwaW5nLCB5YW5nIGhhbnlhIG1lbnlhbGluIHBpa3NlbCB5YW5nIGRpdGFtcGlsa2FuIGRpIGxheWFyLCB3ZWIgc2NyYXBpbmcgbWVuZ2Vrc3RyYWsga29kZSBIVE1MIHlhbmcgbWVuZGFzYXJpbnlhIHlhbmcgcGFkYSBkYXNhcm55YSBkaSBzaW1wYW4gZGFsYW0gZGF0YSBiYXNlLiBQZW5naWtpc2FuIGRhdGEgaW5pIGRhcGF0IG1lcmVwbGlrYXNpIHNlbHVydWgga29udGVuIGRhcmkgYmVyYmFnYWkgc2l0dXMgd2ViIHlhbmcgZGl0YXJnZXRrYW4uDQoNCg==