
Operasi dan Tipe Data
Dasar
Buat program sederhana dalam R yang melakukan hal berikut:
Menerima dua bilangan dari pengguna
Menghitung dan menampilkan hasil:
- Penjumlahan
- Perkalian
- Pembagian
- Bilangan pertama pangkat bilangan kedua
- Menampilkan tipe data masing-masing hasil operasi
# Fungsi untuk masing-masing operasi
penjumlahan <- function(a, b) {
return(a + b)
}
perkalian <- function(a, b) {
return(a * b)
}
pembagian <- function(a, b) {
if (is.na(b) || b == 0) {
return("Tidak bisa dibagi dengan nol atau input tidak valid")
} else {
return(a / b)
}
}
pangkat <- function(a, b) {
return(a ^ b)
}
# Minta input dari pengguna
a <- as.numeric(readline(prompt = "Masukkan bilangan pertama: "))
## Masukkan bilangan pertama:
b <- as.numeric(readline(prompt = "Masukkan bilangan kedua: "))
## Masukkan bilangan kedua:
# Lakukan operasi
hasil_tambah <- penjumlahan(a, b)
hasil_kali <- perkalian(a, b)
hasil_bagi <- pembagian(a, b)
hasil_pangkat <- pangkat(a, b)
# Tampilkan hasil dan tipe datanya
cat("\n=== HASIL OPERASI ===\n")
##
## === HASIL OPERASI ===
cat("Penjumlahan:", hasil_tambah, "| Tipe:", class(hasil_tambah), "\n")
## Penjumlahan: NA | Tipe: numeric
cat("Perkalian:", hasil_kali, "| Tipe:", class(hasil_kali), "\n")
## Perkalian: NA | Tipe: numeric
cat("Pembagian:", hasil_bagi, "| Tipe:", class(hasil_bagi), "\n")
## Pembagian: Tidak bisa dibagi dengan nol atau input tidak valid | Tipe: character
cat("Pangkat:", hasil_pangkat, "| Tipe:", class(hasil_pangkat), "\n")
## Pangkat: NA | Tipe: numeric
Struktur Kendali
(Control Flow)
Tulislah program dalam R yang:
Menerima input nilai ujian dari pengguna (0–100)
Menampilkan keterangan berdasarkan ketentuan berikut:
- Nilai ≥ 85: “Sangat Baik”
- Nilai 70–84: “Baik”
- Nilai 60–69: “Cukup”
- Nilai < 60: “Perlu Perbaikan”
# Menerima input dari pengguna
nilai <- as.numeric(readline(prompt = "Masukkan nilai ujian (0-100): "))
## Masukkan nilai ujian (0-100):
# Mengecek apakah input valid
if (is.na(nilai) || nilai < 0 || nilai > 100) {
cat("Input tidak valid. Harap masukkan angka antara 0 dan 100.\n")
} else {
# Menentukan keterangan berdasarkan nilai
if (nilai >= 85) {
keterangan <- "Sangat Baik"
} else if (nilai >= 70) {
keterangan <- "Baik"
} else if (nilai >= 60) {
keterangan <- "Cukup"
} else {
keterangan <- "Perlu Perbaikan"
}
# Menampilkan hasil
cat("Nilai:", nilai, "\n")
cat("Keterangan:", keterangan, "\n")
}
## Input tidak valid. Harap masukkan angka antara 0 dan 100.
Fungsi dan
Perulangan
Buatlah fungsi dalam R bernama kelipatan_genap(n) yang:
Menerima input integer n
Menggunakan loop untuk mencetak semua bilangan genap kelipatan 4
dari 1 hingga n
Contoh output jika n = 20: 4, 8, 12, 16, 20
kelipatan_genap <- function(n) {
# Validasi input: harus bilangan bulat positif
if (is.na(n) || !is.numeric(n) || n <= 0 || n != floor(n)) {
cat("Input harus berupa bilangan bulat positif.\n")
return()
}
cat("Bilangan genap kelipatan 4 dari 1 hingga", n, ":\n")
hasil <- c() # vektor penampung hasil
for (i in 1:n) {
if (i %% 4 == 0) {
hasil <- c(hasil, i)
}
}
# Tampilkan hasil sebagai daftar angka yang dipisah koma
cat(paste(hasil, collapse = ", "), "\n")
}
Studi Kasus
Sebuah perusahaan e-commerce ingin menganalisis performa penjualannya
berdasarkan data transaksi selama 3 bulan terakhir. Namun, data yang
tersedia berasal dari berbagai sumber dan memiliki kualitas yang
beragam. Anda diminta untuk melakukan Data Wrangling sebelum dianalisis
lebih lanjut.
Bagian 1: Data Collection
Asumsikan data berasal dari 3 file CSV berbeda (januari.csv,
februari.csv, maret.csv).
Tugas Anda:
Gabungkan ketiga file menjadi satu dataset.
Tampilkan jumlah total baris dan kolom setelah digabung.
## Jumlah Baris: 150
## Jumlah Kolom: 9
Interpretasi
Setelah proses penggabungan data dari tiga file transaksi bulanan
(Januari, Februari, dan Maret), diperoleh total 150 entri transaksi atau
baris data. Ini menunjukkan bahwa masing-masing file kemungkinan berisi
sekitar 50 transaksi. Sementara itu, terdapat 9 kolom pada dataset
gabungan, yang mengindikasikan bahwa setiap transaksi tercatat dengan 9
atribut atau variabel — seperti tanggal transaksi, nama produk, jumlah,
harga, kota, dan kategori.
Bagian 2: Data Cleaning
Lakukan pembersihan data berikut:
Standarkan format tanggal ke bentuk YYYY-MM-DD.
Ubah kolom Harga dan Jumlah menjadi format numerik.
Hitung ulang nilai kolom Total = Harga * Jumlah.
Ganti nilai yang tidak valid (contoh: -, “dua”, “Rp”,
“anonymous”) dengan nilai yang sesuai atau NA.
Hapus baris yang tidak memiliki nama produk (Produk kosong atau
-).
Interpretasi
Pada tahap ini, dilakukan proses pembersihan data untuk memastikan
kualitas dan konsistensi dataset sebelum dianalisis lebih lanjut.
Pertama, format tanggal diseragamkan ke bentuk standar YYYY-MM-DD, agar
mudah diolah dalam analisis waktu. Kedua, kolom Harga dan Jumlah yang
sebelumnya mengandung teks atau simbol tidak valid seperti “Rp”, “dua”,
atau “-” dikonversi ke format numerik menggunakan fungsi pembersih
khusus. Kemudian, nilai pada kolom Total dihitung ulang sebagai hasil
perkalian antara Harga dan Jumlah, memastikan akurasi data transaksi.
Selanjutnya, entri dengan nilai tidak valid secara otomatis diganti
dengan NA, sehingga tidak mengganggu perhitungan statistik. Terakhir,
baris-baris yang tidak memiliki nama produk (misalnya Produk kosong atau
tanda “-”) dihapus agar hanya data yang relevan yang dipertahankan.
Hasilnya, dataset menjadi lebih bersih, rapi, dan siap untuk dianalisis
lebih lanjut.
Bagian 3: Data Transformation
Lakukan transformasi data sebagai berikut:
Buat kolom baru Bulan berdasarkan tanggal transaksi.
Hitung total penjualan (Total) per kategori produk.
Hitung jumlah transaksi dari setiap kota.
Buat ringkasan jumlah total penjualan per bulan.
Output yang Diharapkan:
Dataset yang sudah bersih dan rapi.
Tabel agregat: total penjualan per kategori, kota, dan
bulan.
Visualisasi opsional: grafik batang, grafik lingkaran dan grafik
garis penjualan per kategori.
Total Penjualan per Kategori
|
123009750 |
| Aksesoris |
331762000 |
| Elektronik |
167006750 |
| Fashion |
225006750 |
Jumlah Transaksi per Kota
| - |
30 |
| Bandung |
33 |
| Jakarta |
29 |
| Surabaya |
30 |
Ringkasan Penjualan per Bulan
| 2024-01 |
195757500 |
| 2024-02 |
286761250 |
| 2024-03 |
318008250 |
| 2024-04 |
46258250 |
Visualisasi
Interpretasi
Berdasarkan output yang didapatkan, dapat disimpulkan beberapa hal
penting terkait performa penjualan dan distribusi transaksi:
Kategori Produk: Kategori Aksesoris mencatat total penjualan
tertinggi sebesar Rp331.762.000, disusul oleh Fashion sebesar
Rp225.006.750, dan Elektronik sebesar Rp167.006.750. Terdapat pula data
penjualan sebesar Rp123.009.750 yang tidak tercatat dalam kategori
tertentu (kemungkinan akibat data tidak lengkap atau kategori kosong).
Hal ini menunjukkan bahwa produk Aksesoris paling mendominasi dalam
penjualan selama periode yang dianalisis.
Distribusi Kota: Kota dengan jumlah transaksi terbanyak adalah
Bandung (33 transaksi), diikuti oleh Surabaya (30 transaksi) dan Jakarta
(29 transaksi). Namun, terdapat pula 30 transaksi yang tidak memiliki
informasi kota (dilambangkan dengan tanda “-”), yang perlu ditelusuri
lebih lanjut karena bisa memengaruhi analisis geografis secara
akurat.
Tren Penjualan Bulanan: Penjualan tertinggi terjadi pada bulan
Maret 2024 dengan total Rp318.008.250, diikuti oleh Februari
(Rp286.761.250) dan Januari (Rp195.757.500). Namun, terjadi penurunan
tajam pada April 2024, di mana total penjualan hanya mencapai
Rp46.258.250. Penurunan ini dapat menjadi perhatian, apakah disebabkan
oleh musim, promosi yang berkurang, atau faktor eksternal
lainnya.
LS0tDQp0aXRsZTogIlVqaWFuIFRlbmdhaCBTZW1lc3RlciAyIg0Kc3VidGl0bGU6ICJEYXRhIFNjaWVuY2UgUHJvZ3JhbW1pbmciDQphdXRob3I6IA0KICAiSXNuYWluaSBOdXIgSGFzYW5haCAoNTIyNDAwMDUpIg0KZGF0ZTogICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6ZG93bmN1dGU6ICAgIyBodHRwczovL2dpdGh1Yi5jb20vanViYS9ybWRmb3JtYXRzDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgbGliX2RpcjogbGlicw0KICAgIGRmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjc3M6ICJzdHlsZSAoMSkuY3NzIg0KICAgIHBhcmFtczoNCiAgZWNobzogZmFsc2UNCmVkaXRvcl9vcHRpb25zOiANCiAgbWFya2Rvd246IA0KICAgIHdyYXA6IDcyDQotLS0NCg0KPGltZyBpZD0iSXNuYSIgc3JjPSJDOlxVc2Vyc1xBU1VTXERlc2t0b3BcU3RhdGlzdGlrYSBEYXNhclxJc25hLnBuZyIgYWx0PSJMb2dvIiBzdHlsZT0id2lkdGg6MjAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ij4NCg0KIyBPcGVyYXNpIGRhbiBUaXBlIERhdGEgRGFzYXINCg0KQnVhdCBwcm9ncmFtIHNlZGVyaGFuYSBkYWxhbSBSIHlhbmcgbWVsYWt1a2FuIGhhbCBiZXJpa3V0Og0KDQphLiBNZW5lcmltYSBkdWEgYmlsYW5nYW4gZGFyaSBwZW5nZ3VuYQ0KDQpiLiBNZW5naGl0dW5nIGRhbiBtZW5hbXBpbGthbiBoYXNpbDoNCi0gUGVuanVtbGFoYW4NCi0gUGVya2FsaWFuDQotIFBlbWJhZ2lhbg0KLSBCaWxhbmdhbiBwZXJ0YW1hIHBhbmdrYXQgYmlsYW5nYW4ga2VkdWENCg0KYy4gTWVuYW1waWxrYW4gdGlwZSBkYXRhIG1hc2luZy1tYXNpbmcgaGFzaWwgb3BlcmFzaQ0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBGdW5nc2kgdW50dWsgbWFzaW5nLW1hc2luZyBvcGVyYXNpDQpwZW5qdW1sYWhhbiA8LSBmdW5jdGlvbihhLCBiKSB7DQogIHJldHVybihhICsgYikNCn0NCg0KcGVya2FsaWFuIDwtIGZ1bmN0aW9uKGEsIGIpIHsNCiAgcmV0dXJuKGEgKiBiKQ0KfQ0KDQpwZW1iYWdpYW4gPC0gZnVuY3Rpb24oYSwgYikgew0KICBpZiAoaXMubmEoYikgfHwgYiA9PSAwKSB7DQogICAgcmV0dXJuKCJUaWRhayBiaXNhIGRpYmFnaSBkZW5nYW4gbm9sIGF0YXUgaW5wdXQgdGlkYWsgdmFsaWQiKQ0KICB9IGVsc2Ugew0KICAgIHJldHVybihhIC8gYikNCiAgfQ0KfQ0KDQpwYW5na2F0IDwtIGZ1bmN0aW9uKGEsIGIpIHsNCiAgcmV0dXJuKGEgXiBiKQ0KfQ0KDQojIE1pbnRhIGlucHV0IGRhcmkgcGVuZ2d1bmENCmEgPC0gYXMubnVtZXJpYyhyZWFkbGluZShwcm9tcHQgPSAiTWFzdWtrYW4gYmlsYW5nYW4gcGVydGFtYTogIikpDQpiIDwtIGFzLm51bWVyaWMocmVhZGxpbmUocHJvbXB0ID0gIk1hc3Vra2FuIGJpbGFuZ2FuIGtlZHVhOiAiKSkNCg0KIyBMYWt1a2FuIG9wZXJhc2kNCmhhc2lsX3RhbWJhaCA8LSBwZW5qdW1sYWhhbihhLCBiKQ0KaGFzaWxfa2FsaSA8LSBwZXJrYWxpYW4oYSwgYikNCmhhc2lsX2JhZ2kgPC0gcGVtYmFnaWFuKGEsIGIpDQpoYXNpbF9wYW5na2F0IDwtIHBhbmdrYXQoYSwgYikNCg0KIyBUYW1waWxrYW4gaGFzaWwgZGFuIHRpcGUgZGF0YW55YQ0KY2F0KCJcbj09PSBIQVNJTCBPUEVSQVNJID09PVxuIikNCmNhdCgiUGVuanVtbGFoYW46IiwgaGFzaWxfdGFtYmFoLCAifCBUaXBlOiIsIGNsYXNzKGhhc2lsX3RhbWJhaCksICJcbiIpDQpjYXQoIlBlcmthbGlhbjoiLCBoYXNpbF9rYWxpLCAifCBUaXBlOiIsIGNsYXNzKGhhc2lsX2thbGkpLCAiXG4iKQ0KY2F0KCJQZW1iYWdpYW46IiwgaGFzaWxfYmFnaSwgInwgVGlwZToiLCBjbGFzcyhoYXNpbF9iYWdpKSwgIlxuIikNCmNhdCgiUGFuZ2thdDoiLCBoYXNpbF9wYW5na2F0LCAifCBUaXBlOiIsIGNsYXNzKGhhc2lsX3BhbmdrYXQpLCAiXG4iKQ0KYGBgDQoNCiMgU3RydWt0dXIgS2VuZGFsaSAoQ29udHJvbCBGbG93KQ0KDQpUdWxpc2xhaCBwcm9ncmFtIGRhbGFtIFIgeWFuZzoNCg0KYS4gTWVuZXJpbWEgaW5wdXQgbmlsYWkgdWppYW4gZGFyaSBwZW5nZ3VuYSAoMOKAkzEwMCkNCg0KYi4gTWVuYW1waWxrYW4ga2V0ZXJhbmdhbiBiZXJkYXNhcmthbiBrZXRlbnR1YW4gYmVyaWt1dDoNCi0gTmlsYWkg4omlIDg1OiDigJxTYW5nYXQgQmFpa+KAnQ0KLSBOaWxhaSA3MOKAkzg0OiDigJxCYWlr4oCdDQotIE5pbGFpIDYw4oCTNjk6IOKAnEN1a3Vw4oCdDQotIE5pbGFpIDwgNjA6IOKAnFBlcmx1IFBlcmJhaWthbuKAnQ0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBNZW5lcmltYSBpbnB1dCBkYXJpIHBlbmdndW5hDQpuaWxhaSA8LSBhcy5udW1lcmljKHJlYWRsaW5lKHByb21wdCA9ICJNYXN1a2thbiBuaWxhaSB1amlhbiAoMC0xMDApOiAiKSkNCg0KIyBNZW5nZWNlayBhcGFrYWggaW5wdXQgdmFsaWQNCmlmIChpcy5uYShuaWxhaSkgfHwgbmlsYWkgPCAwIHx8IG5pbGFpID4gMTAwKSB7DQogIGNhdCgiSW5wdXQgdGlkYWsgdmFsaWQuIEhhcmFwIG1hc3Vra2FuIGFuZ2thIGFudGFyYSAwIGRhbiAxMDAuXG4iKQ0KfSBlbHNlIHsNCiAgIyBNZW5lbnR1a2FuIGtldGVyYW5nYW4gYmVyZGFzYXJrYW4gbmlsYWkNCiAgaWYgKG5pbGFpID49IDg1KSB7DQogICAga2V0ZXJhbmdhbiA8LSAiU2FuZ2F0IEJhaWsiDQogIH0gZWxzZSBpZiAobmlsYWkgPj0gNzApIHsNCiAgICBrZXRlcmFuZ2FuIDwtICJCYWlrIg0KICB9IGVsc2UgaWYgKG5pbGFpID49IDYwKSB7DQogICAga2V0ZXJhbmdhbiA8LSAiQ3VrdXAiDQogIH0gZWxzZSB7DQogICAga2V0ZXJhbmdhbiA8LSAiUGVybHUgUGVyYmFpa2FuIg0KICB9DQoNCiAgIyBNZW5hbXBpbGthbiBoYXNpbA0KICBjYXQoIk5pbGFpOiIsIG5pbGFpLCAiXG4iKQ0KICBjYXQoIktldGVyYW5nYW46Iiwga2V0ZXJhbmdhbiwgIlxuIikNCn0NCmBgYA0KDQojIEZ1bmdzaSBkYW4gUGVydWxhbmdhbg0KDQpCdWF0bGFoIGZ1bmdzaSBkYWxhbSBSIGJlcm5hbWEga2VsaXBhdGFuX2dlbmFwKG4pIHlhbmc6DQoNCmEuIE1lbmVyaW1hIGlucHV0IGludGVnZXIgbg0KDQpiLiBNZW5nZ3VuYWthbiBsb29wIHVudHVrIG1lbmNldGFrIHNlbXVhIGJpbGFuZ2FuIGdlbmFwIGtlbGlwYXRhbiA0IGRhcmkgMQ0KaGluZ2dhIG4NCg0KYy4gQ29udG9oIG91dHB1dCBqaWthIG4gPSAyMDogNCwgOCwgMTIsIDE2LCAyMA0KDQpgYGB7ciBrZWxpcGF0YW4tNCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0Ka2VsaXBhdGFuX2dlbmFwIDwtIGZ1bmN0aW9uKG4pIHsNCiAgIyBWYWxpZGFzaSBpbnB1dDogaGFydXMgYmlsYW5nYW4gYnVsYXQgcG9zaXRpZg0KICBpZiAoaXMubmEobikgfHwgIWlzLm51bWVyaWMobikgfHwgbiA8PSAwIHx8IG4gIT0gZmxvb3IobikpIHsNCiAgICBjYXQoIklucHV0IGhhcnVzIGJlcnVwYSBiaWxhbmdhbiBidWxhdCBwb3NpdGlmLlxuIikNCiAgICByZXR1cm4oKQ0KICB9DQoNCiAgY2F0KCJCaWxhbmdhbiBnZW5hcCBrZWxpcGF0YW4gNCBkYXJpIDEgaGluZ2dhIiwgbiwgIjpcbiIpDQogIA0KICBoYXNpbCA8LSBjKCkgICMgdmVrdG9yIHBlbmFtcHVuZyBoYXNpbA0KICBmb3IgKGkgaW4gMTpuKSB7DQogICAgaWYgKGkgJSUgNCA9PSAwKSB7DQogICAgICBoYXNpbCA8LSBjKGhhc2lsLCBpKQ0KICAgIH0NCiAgfQ0KICANCiAgIyBUYW1waWxrYW4gaGFzaWwgc2ViYWdhaSBkYWZ0YXIgYW5na2EgeWFuZyBkaXBpc2FoIGtvbWENCiAgY2F0KHBhc3RlKGhhc2lsLCBjb2xsYXBzZSA9ICIsICIpLCAiXG4iKQ0KfQ0KYGBgDQoNCiMgU3R1ZGkgS2FzdXMNCg0KU2VidWFoIHBlcnVzYWhhYW4gZS1jb21tZXJjZSBpbmdpbiBtZW5nYW5hbGlzaXMgcGVyZm9ybWEgcGVuanVhbGFubnlhIGJlcmRhc2Fya2FuDQpkYXRhIHRyYW5zYWtzaSBzZWxhbWEgMyBidWxhbiB0ZXJha2hpci4gTmFtdW4sIGRhdGEgeWFuZyB0ZXJzZWRpYSBiZXJhc2FsIGRhcmkgYmVyYmFnYWkNCnN1bWJlciBkYW4gbWVtaWxpa2kga3VhbGl0YXMgeWFuZyBiZXJhZ2FtLiBBbmRhIGRpbWludGEgdW50dWsgbWVsYWt1a2FuIERhdGENCldyYW5nbGluZyBzZWJlbHVtIGRpYW5hbGlzaXMgbGViaWggbGFuanV0Lg0KDQoqKkJhZ2lhbiAxOiBEYXRhIENvbGxlY3Rpb24qKg0KDQpBc3Vtc2lrYW4gZGF0YSBiZXJhc2FsIGRhcmkgMyBmaWxlIENTViBiZXJiZWRhIChqYW51YXJpLmNzdiwgZmVicnVhcmkuY3N2LCBtYXJldC5jc3YpLg0KDQpUdWdhcyBBbmRhOg0KDQphLiBHYWJ1bmdrYW4ga2V0aWdhIGZpbGUgbWVuamFkaSBzYXR1IGRhdGFzZXQuDQoNCmIuIFRhbXBpbGthbiBqdW1sYWggdG90YWwgYmFyaXMgZGFuIGtvbG9tIHNldGVsYWggZGlnYWJ1bmcuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQ0KIyBhLiBNZW1iYWNhIGRhbiBtZW5nZ2FidW5na2FuIGtldGlnYSBmaWxlDQpkYXRhX2phbnVhcmkgPC0gcmVhZC5jc3YoIkphbnVhcmkuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KZGF0YV9mZWJydWFyaSA8LSByZWFkLmNzdigiRmVicnVhcmkuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KZGF0YV9tYXJldCA8LSByZWFkLmNzdigiTWFyZXQuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KDQojIEdhYnVuZ2thbiBzZW11YSBkYXRhIG1lbmdndW5ha2FuIHJiaW5kDQpkYXRhX2dhYnVuZ2FuIDwtIHJiaW5kKGRhdGFfamFudWFyaSwgZGF0YV9mZWJydWFyaSwgZGF0YV9tYXJldCkNCg0KIyBiLiBNZW5hbXBpbGthbiBqdW1sYWggdG90YWwgYmFyaXMgZGFuIGtvbG9tDQpjYXQoIkp1bWxhaCBCYXJpczoiLCBucm93KGRhdGFfZ2FidW5nYW4pLCAiXG4iKQ0KY2F0KCJKdW1sYWggS29sb206IiwgbmNvbChkYXRhX2dhYnVuZ2FuKSwgIlxuIikNCg0KIyBNZW5hbXBpbGthbiBkYXRhDQpoZWFkKGRhdGFfZ2FidW5nYW4sMTApDQpgYGANCg0KKipJbnRlcnByZXRhc2kqKg0KDQpTZXRlbGFoIHByb3NlcyBwZW5nZ2FidW5nYW4gZGF0YSBkYXJpIHRpZ2EgZmlsZSB0cmFuc2Frc2kgYnVsYW5hbiAoSmFudWFyaSwgRmVicnVhcmksIGRhbiBNYXJldCksIGRpcGVyb2xlaCB0b3RhbCAxNTAgZW50cmkgdHJhbnNha3NpIGF0YXUgYmFyaXMgZGF0YS4gSW5pIG1lbnVuanVra2FuIGJhaHdhIG1hc2luZy1tYXNpbmcgZmlsZSBrZW11bmdraW5hbiBiZXJpc2kgc2VraXRhciA1MCB0cmFuc2Frc2kuIFNlbWVudGFyYSBpdHUsIHRlcmRhcGF0IDkga29sb20gcGFkYSBkYXRhc2V0IGdhYnVuZ2FuLCB5YW5nIG1lbmdpbmRpa2FzaWthbiBiYWh3YSBzZXRpYXAgdHJhbnNha3NpIHRlcmNhdGF0IGRlbmdhbiA5IGF0cmlidXQgYXRhdSB2YXJpYWJlbCDigJQgc2VwZXJ0aSB0YW5nZ2FsIHRyYW5zYWtzaSwgbmFtYSBwcm9kdWssIGp1bWxhaCwgaGFyZ2EsIGtvdGEsIGRhbiBrYXRlZ29yaS4gDQoNCioqQmFnaWFuIDI6IERhdGEgQ2xlYW5pbmcqKg0KDQpMYWt1a2FuIHBlbWJlcnNpaGFuIGRhdGEgYmVyaWt1dDoNCg0KYS4gU3RhbmRhcmthbiBmb3JtYXQgdGFuZ2dhbCBrZSBiZW50dWsgWVlZWS1NTS1ERC4NCg0KYi4gVWJhaCBrb2xvbSBIYXJnYSBkYW4gSnVtbGFoIG1lbmphZGkgZm9ybWF0IG51bWVyaWsuDQoNCmMuIEhpdHVuZyB1bGFuZyBuaWxhaSBrb2xvbSBUb3RhbCA9IEhhcmdhICogSnVtbGFoLg0KDQpkLiBHYW50aSBuaWxhaSB5YW5nIHRpZGFrIHZhbGlkIChjb250b2g6IC0sICJkdWEiLCAiUnAiLCAiX2Fub255bW91c18iKSBkZW5nYW4gbmlsYWkNCnlhbmcgc2VzdWFpIGF0YXUgTkEuDQoNCmUuIEhhcHVzIGJhcmlzIHlhbmcgdGlkYWsgbWVtaWxpa2kgbmFtYSBwcm9kdWsgKFByb2R1ayBrb3NvbmcgYXRhdSAtKS4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShEVCkNCg0KIyBhLiBTdGFuZGFya2FuIGZvcm1hdCB0YW5nZ2FsIGtlIFlZWVktTU0tREQNCmRhdGFfZ2FidW5nYW4kVGFuZ2dhbCA8LSBhcy5EYXRlKGRhdGFfZ2FidW5nYW4kVGFuZ2dhbCwgZm9ybWF0ID0gIiVkLSVtLSVZIikNCg0KIyBiLiBVYmFoIGtvbG9tIEhhcmdhIGRhbiBKdW1sYWggbWVuamFkaSBudW1lcmlrDQojIEZ1bmdzaSB1bnR1ayBtZW1iZXJzaWhrYW4gZGF0YSBudW1lcmlrDQpjbGVhbl9udW1lcmljIDwtIGZ1bmN0aW9uKHgpIHsNCiAgeCA8LSBhcy5jaGFyYWN0ZXIoeCkNCiAgeCA8LSBzdHJfcmVwbGFjZV9hbGwoeCwgIlJwfCx8XFwtfGR1YXxhbm9ueW1vdXN8X2Fub255bW91c198ICIsICIiKQ0KICBpZiAodG9sb3dlcih4KSAlaW4lIGMoIiIsICJuYSIsICJuYW4iKSkgcmV0dXJuKE5BX3JlYWxfKQ0KICBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoeCkpDQp9DQoNCmRhdGFfZ2FidW5nYW4gPC0gZGF0YV9nYWJ1bmdhbiAlPiUNCiAgbXV0YXRlKA0KICAgIEhhcmdhID0gc2FwcGx5KEhhcmdhLCBjbGVhbl9udW1lcmljKSwNCiAgICBKdW1sYWggPSBzYXBwbHkoSnVtbGFoLCBjbGVhbl9udW1lcmljKQ0KICApDQoNCiMgYy4gSGl0dW5nIHVsYW5nIG5pbGFpIGtvbG9tIFRvdGFsID0gSGFyZ2EgKiBKdW1sYWgNCmRhdGFfZ2FidW5nYW4gPC0gZGF0YV9nYWJ1bmdhbiAlPiUNCiAgbXV0YXRlKFRvdGFsID0gSGFyZ2EgKiBKdW1sYWgpDQoNCiMgZC4gR2FudGkgbmlsYWkgeWFuZyB0aWRhayB2YWxpZCAoLSwgImR1YSIsICJScCIsICJfYW5vbnltb3VzXyIpIHN1ZGFoIGRpdGFuZ2FuaSBkaSBmdW5nc2kgY2xlYW5fbnVtZXJpYw0KDQojIGUuIEhhcHVzIGJhcmlzIHlhbmcgdGlkYWsgbWVtaWxpa2kgbmFtYSBwcm9kdWsgKFByb2R1ayBrb3NvbmcgYXRhdSAiLSIpDQpkYXRhX2dhYnVuZ2FuIDwtIGRhdGFfZ2FidW5nYW4gJT4lDQogIGZpbHRlcighKFByb2R1ayAlaW4lIGMoIiIsICItIiwgTkEpKSkNCg0KIyBUYW1waWxrYW4gaGFzaWwgc2ViYWdhaSB0YWJlbCBpbnRlcmFrdGlmDQpkYXRhdGFibGUoaGVhZChkYXRhX2dhYnVuZ2FuLCAxMCksIGNhcHRpb24gPSAiVGFiZWwgSW50ZXJha3RpZjogMTAgQmFyaXMgUGVydGFtYSBEYXRhIFNldGVsYWggUGVtYmVyc2loYW4iKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXNpKioNCg0KUGFkYSB0YWhhcCBpbmksIGRpbGFrdWthbiBwcm9zZXMgcGVtYmVyc2loYW4gZGF0YSB1bnR1ayBtZW1hc3Rpa2FuIGt1YWxpdGFzIGRhbiBrb25zaXN0ZW5zaSBkYXRhc2V0IHNlYmVsdW0gZGlhbmFsaXNpcyBsZWJpaCBsYW5qdXQuIFBlcnRhbWEsIGZvcm1hdCB0YW5nZ2FsIGRpc2VyYWdhbWthbiBrZSBiZW50dWsgc3RhbmRhciBZWVlZLU1NLURELCBhZ2FyIG11ZGFoIGRpb2xhaCBkYWxhbSBhbmFsaXNpcyB3YWt0dS4gS2VkdWEsIGtvbG9tIEhhcmdhIGRhbiBKdW1sYWggeWFuZyBzZWJlbHVtbnlhIG1lbmdhbmR1bmcgdGVrcyBhdGF1IHNpbWJvbCB0aWRhayB2YWxpZCBzZXBlcnRpICJScCIsICJkdWEiLCBhdGF1ICItIiBkaWtvbnZlcnNpIGtlIGZvcm1hdCBudW1lcmlrIG1lbmdndW5ha2FuIGZ1bmdzaSBwZW1iZXJzaWgga2h1c3VzLiBLZW11ZGlhbiwgbmlsYWkgcGFkYSBrb2xvbSBUb3RhbCBkaWhpdHVuZyB1bGFuZyBzZWJhZ2FpIGhhc2lsIHBlcmthbGlhbiBhbnRhcmEgSGFyZ2EgZGFuIEp1bWxhaCwgbWVtYXN0aWthbiBha3VyYXNpIGRhdGEgdHJhbnNha3NpLiBTZWxhbmp1dG55YSwgZW50cmkgZGVuZ2FuIG5pbGFpIHRpZGFrIHZhbGlkIHNlY2FyYSBvdG9tYXRpcyBkaWdhbnRpIGRlbmdhbiBOQSwgc2VoaW5nZ2EgdGlkYWsgbWVuZ2dhbmdndSBwZXJoaXR1bmdhbiBzdGF0aXN0aWsuIFRlcmFraGlyLCBiYXJpcy1iYXJpcyB5YW5nIHRpZGFrIG1lbWlsaWtpIG5hbWEgcHJvZHVrIChtaXNhbG55YSBQcm9kdWsga29zb25nIGF0YXUgdGFuZGEgIi0iKSBkaWhhcHVzIGFnYXIgaGFueWEgZGF0YSB5YW5nIHJlbGV2YW4geWFuZyBkaXBlcnRhaGFua2FuLiBIYXNpbG55YSwgZGF0YXNldCBtZW5qYWRpIGxlYmloIGJlcnNpaCwgcmFwaSwgZGFuIHNpYXAgdW50dWsgZGlhbmFsaXNpcyBsZWJpaCBsYW5qdXQuDQoNCioqQmFnaWFuIDM6IERhdGEgVHJhbnNmb3JtYXRpb24qKg0KDQpMYWt1a2FuIHRyYW5zZm9ybWFzaSBkYXRhIHNlYmFnYWkgYmVyaWt1dDoNCg0KYS4gQnVhdCBrb2xvbSBiYXJ1IEJ1bGFuIGJlcmRhc2Fya2FuIHRhbmdnYWwgdHJhbnNha3NpLg0KDQpiLiBIaXR1bmcgdG90YWwgcGVuanVhbGFuIChUb3RhbCkgcGVyIGthdGVnb3JpIHByb2R1ay4NCg0KYy4gSGl0dW5nIGp1bWxhaCB0cmFuc2Frc2kgZGFyaSBzZXRpYXAga290YS4NCg0KZC4gQnVhdCByaW5na2FzYW4ganVtbGFoIHRvdGFsIHBlbmp1YWxhbiBwZXIgYnVsYW4uDQoNCioqT3V0cHV0IHlhbmcgRGloYXJhcGthbjoqKg0KDQphLiBEYXRhc2V0IHlhbmcgc3VkYWggYmVyc2loIGRhbiByYXBpLg0KDQpiLiBUYWJlbCBhZ3JlZ2F0OiB0b3RhbCBwZW5qdWFsYW4gcGVyIGthdGVnb3JpLCBrb3RhLCBkYW4gYnVsYW4uDQoNCmMuIFZpc3VhbGlzYXNpIG9wc2lvbmFsOiBncmFmaWsgYmF0YW5nLCBncmFmaWsgbGluZ2thcmFuIGRhbiBncmFmaWsgZ2FyaXMgcGVuanVhbGFuIHBlcg0Ka2F0ZWdvcmkuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KERUKQ0KDQojIFBhc3Rpa2FuIGtvbG9tICdUYW5nZ2FsJyBzdWRhaCBkYWxhbSBmb3JtYXQgRGF0ZQ0KZGF0YV9nYWJ1bmdhbiRUYW5nZ2FsIDwtIGFzLkRhdGUoZGF0YV9nYWJ1bmdhbiRUYW5nZ2FsKQ0KDQojIGEuIEJ1YXQga29sb20gQnVsYW4NCmRhdGFfZ2FidW5nYW4kQnVsYW4gPC0gZm9ybWF0KGRhdGFfZ2FidW5nYW4kVGFuZ2dhbCwgIiVZLSVtIikNCg0KIyBiLiBUb3RhbCBwZW5qdWFsYW4gcGVyIGthdGVnb3JpDQppZiAoYWxsKGMoIkthdGVnb3JpIiwgIlRvdGFsIikgJWluJSBuYW1lcyhkYXRhX2dhYnVuZ2FuKSkpIHsNCiAgdG90YWxfcGVyX2thdGVnb3JpIDwtIGRhdGFfZ2FidW5nYW4gJT4lDQogICAgZ3JvdXBfYnkoS2F0ZWdvcmkpICU+JQ0KICAgIHN1bW1hcmlzZShgVG90YWwgUGVuanVhbGFuYCA9IHN1bShUb3RhbCwgbmEucm0gPSBUUlVFKSkNCn0gZWxzZSB7DQogIHRvdGFsX3Blcl9rYXRlZ29yaSA8LSBkYXRhLmZyYW1lKCkNCn0NCg0KIyBjLiBKdW1sYWggdHJhbnNha3NpIHBlciBrb3RhDQppZiAoIktvdGEiICVpbiUgbmFtZXMoZGF0YV9nYWJ1bmdhbikpIHsNCiAgdHJhbnNha3NpX3Blcl9rb3RhIDwtIGRhdGFfZ2FidW5nYW4gJT4lDQogICAgY291bnQoS290YSwgbmFtZSA9ICJKdW1sYWggVHJhbnNha3NpIikNCn0gZWxzZSB7DQogIHRyYW5zYWtzaV9wZXJfa290YSA8LSBkYXRhLmZyYW1lKCkNCn0NCg0KIyBkLiBSaW5na2FzYW4gcGVuanVhbGFuIHBlciBidWxhbg0KaWYgKGFsbChjKCJCdWxhbiIsICJUb3RhbCIpICVpbiUgbmFtZXMoZGF0YV9nYWJ1bmdhbikpKSB7DQogIHBlbmp1YWxhbl9wZXJfYnVsYW4gPC0gZGF0YV9nYWJ1bmdhbiAlPiUNCiAgICBncm91cF9ieShCdWxhbikgJT4lDQogICAgc3VtbWFyaXNlKGBUb3RhbCBQZW5qdWFsYW5gID0gc3VtKFRvdGFsLCBuYS5ybSA9IFRSVUUpKQ0KfSBlbHNlIHsNCiAgcGVuanVhbGFuX3Blcl9idWxhbiA8LSBkYXRhLmZyYW1lKCkNCn0NCg0KIyBUYW1waWxrYW4gc2ViYWdhaSB0YWJlbCBzdGF0aXMNCmthYmxlKHRvdGFsX3Blcl9rYXRlZ29yaSwgY2FwdGlvbiA9ICJUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIikNCmthYmxlKHRyYW5zYWtzaV9wZXJfa290YSwgY2FwdGlvbiA9ICJKdW1sYWggVHJhbnNha3NpIHBlciBLb3RhIikNCmthYmxlKHBlbmp1YWxhbl9wZXJfYnVsYW4sIGNhcHRpb24gPSAiUmluZ2thc2FuIFBlbmp1YWxhbiBwZXIgQnVsYW4iKQ0KYGBgDQoNCioqVmlzdWFsaXNhc2kqKg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0NCmxpYnJhcnkocGxvdGx5KQ0KDQojIGEuIEdyYWZpayBiYXRhbmcgaW50ZXJha3RpZiAtIFBlbmp1YWxhbiBwZXIga2F0ZWdvcmkNCmlmIChucm93KHRvdGFsX3Blcl9rYXRlZ29yaSkgPiAwKSB7DQogIGZpZzEgPC0gcGxvdF9seSgNCiAgICB0b3RhbF9wZXJfa2F0ZWdvcmksDQogICAgeCA9IH5LYXRlZ29yaSwNCiAgICB5ID0gfmBUb3RhbCBQZW5qdWFsYW5gLA0KICAgIHR5cGUgPSAnYmFyJywNCiAgICBjb2xvciA9IH5LYXRlZ29yaQ0KICApICU+JQ0KICAgIGxheW91dCh0aXRsZSA9ICJUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIFByb2R1ayIpDQogIGZpZzENCn0NCg0KIyBiLiBHcmFmaWsgcGllIChkb251dCkgaW50ZXJha3RpZiAtIFRyYW5zYWtzaSBwZXIga290YQ0KaWYgKG5yb3codHJhbnNha3NpX3Blcl9rb3RhKSA+IDApIHsNCiAgZmlnMiA8LSBwbG90X2x5KA0KICAgIHRyYW5zYWtzaV9wZXJfa290YSwNCiAgICBsYWJlbHMgPSB+S290YSwNCiAgICB2YWx1ZXMgPSB+YEp1bWxhaCBUcmFuc2Frc2lgLA0KICAgIHR5cGUgPSAncGllJywNCiAgICBob2xlID0gMC40DQogICkgJT4lDQogICAgbGF5b3V0KHRpdGxlID0gIkRpc3RyaWJ1c2kgVHJhbnNha3NpIHBlciBLb3RhIikNCiAgZmlnMg0KfQ0KDQojIGMuIEdyYWZpayBnYXJpcyBpbnRlcmFrdGlmIC0gUGVuanVhbGFuIHBlciBidWxhbg0KaWYgKG5yb3cocGVuanVhbGFuX3Blcl9idWxhbikgPiAwKSB7DQogIGZpZzMgPC0gcGxvdF9seSgNCiAgICBwZW5qdWFsYW5fcGVyX2J1bGFuLA0KICAgIHggPSB+QnVsYW4sDQogICAgeSA9IH5gVG90YWwgUGVuanVhbGFuYCwNCiAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgIG1vZGUgPSAnbGluZXMrbWFya2VycycsDQogICAgbGluZSA9IGxpc3QoY29sb3IgPSAnZ3JlZW4nKQ0KICApICU+JQ0KICAgIGxheW91dCh0aXRsZSA9ICJUcmVuIFRvdGFsIFBlbmp1YWxhbiBwZXIgQnVsYW4iKQ0KICBmaWczDQp9DQpgYGANCg0KKipJbnRlcnByZXRhc2kqKg0KDQpCZXJkYXNhcmthbiBvdXRwdXQgeWFuZyBkaWRhcGF0a2FuLCBkYXBhdCBkaXNpbXB1bGthbiBiZWJlcmFwYSBoYWwgcGVudGluZyB0ZXJrYWl0IHBlcmZvcm1hIHBlbmp1YWxhbiBkYW4gZGlzdHJpYnVzaSB0cmFuc2Frc2k6DQoNCjEuIEthdGVnb3JpIFByb2R1azogS2F0ZWdvcmkgQWtzZXNvcmlzIG1lbmNhdGF0IHRvdGFsIHBlbmp1YWxhbiB0ZXJ0aW5nZ2kgc2ViZXNhciBScDMzMS43NjIuMDAwLCBkaXN1c3VsIG9sZWggRmFzaGlvbiBzZWJlc2FyIFJwMjI1LjAwNi43NTAsIGRhbiBFbGVrdHJvbmlrIHNlYmVzYXIgUnAxNjcuMDA2Ljc1MC4gVGVyZGFwYXQgcHVsYSBkYXRhIHBlbmp1YWxhbiBzZWJlc2FyIFJwMTIzLjAwOS43NTAgeWFuZyB0aWRhayB0ZXJjYXRhdCBkYWxhbSBrYXRlZ29yaSB0ZXJ0ZW50dSAoa2VtdW5na2luYW4gYWtpYmF0IGRhdGEgdGlkYWsgbGVuZ2thcCBhdGF1IGthdGVnb3JpIGtvc29uZykuIEhhbCBpbmkgbWVudW5qdWtrYW4gYmFod2EgcHJvZHVrIEFrc2Vzb3JpcyBwYWxpbmcgbWVuZG9taW5hc2kgZGFsYW0gcGVuanVhbGFuIHNlbGFtYSBwZXJpb2RlIHlhbmcgZGlhbmFsaXNpcy4NCg0KMi4gRGlzdHJpYnVzaSBLb3RhOiBLb3RhIGRlbmdhbiBqdW1sYWggdHJhbnNha3NpIHRlcmJhbnlhayBhZGFsYWggQmFuZHVuZyAoMzMgdHJhbnNha3NpKSwgZGlpa3V0aSBvbGVoIFN1cmFiYXlhICgzMCB0cmFuc2Frc2kpIGRhbiBKYWthcnRhICgyOSB0cmFuc2Frc2kpLiBOYW11biwgdGVyZGFwYXQgcHVsYSAzMCB0cmFuc2Frc2kgeWFuZyB0aWRhayBtZW1pbGlraSBpbmZvcm1hc2kga290YSAoZGlsYW1iYW5na2FuIGRlbmdhbiB0YW5kYSAiLSIpLCB5YW5nIHBlcmx1IGRpdGVsdXN1cmkgbGViaWggbGFuanV0IGthcmVuYSBiaXNhIG1lbWVuZ2FydWhpIGFuYWxpc2lzIGdlb2dyYWZpcyBzZWNhcmEgYWt1cmF0Lg0KDQozLiBUcmVuIFBlbmp1YWxhbiBCdWxhbmFuOiBQZW5qdWFsYW4gdGVydGluZ2dpIHRlcmphZGkgcGFkYSBidWxhbiBNYXJldCAyMDI0IGRlbmdhbiB0b3RhbCBScDMxOC4wMDguMjUwLCBkaWlrdXRpIG9sZWggRmVicnVhcmkgKFJwMjg2Ljc2MS4yNTApIGRhbiBKYW51YXJpIChScDE5NS43NTcuNTAwKS4gTmFtdW4sIHRlcmphZGkgcGVudXJ1bmFuIHRhamFtIHBhZGEgQXByaWwgMjAyNCwgZGkgbWFuYSB0b3RhbCBwZW5qdWFsYW4gaGFueWEgbWVuY2FwYWkgUnA0Ni4yNTguMjUwLiBQZW51cnVuYW4gaW5pIGRhcGF0IG1lbmphZGkgcGVyaGF0aWFuLCBhcGFrYWggZGlzZWJhYmthbiBvbGVoIG11c2ltLCBwcm9tb3NpIHlhbmcgYmVya3VyYW5nLCBhdGF1IGZha3RvciBla3N0ZXJuYWwgbGFpbm55YS4=