UTS Data Science Programing

Soal 1

Buat program sederhana yang melakukan hal berikut:

  1. Menerima dua bilangan dari pengguna
  2. Menghitung dan menampilan jumlah hasil:
  • Penjumlahan
  • Perkalian
  • Pembagian
  • Bilangan pertama pangkat bilangan kedua
  1. Menampilkan tipe data masing - masing hasil operasi

Jawaban

# Input langsung di dalam blok kode (tanpa readline atau params)
bil1 <- 7
bil2 <- 3

# Cek validitas
if (is.na(bil1) || is.na(bil2)) {
  cat("Error: Masukkan bilangan yang valid!\n")
} else {
  cat("Bilangan pertama:", bil1, "\n")
  cat("Bilangan kedua:", bil2, "\n\n")
  
  # Operasi matematika
  penjumlahan <- bil1 + bil2
  perkalian <- bil1 * bil2
  pembagian <- if (bil2 == 0) NA else bil1 / bil2
  pangkat <- bil1 ^ bil2
  
  # Menampilkan hasil
  cat("Hasil Penjumlahan:", penjumlahan, "\n")
  cat("Hasil Perkalian:", perkalian, "\n")
  cat("Hasil Pembagian:", pembagian, "\n")
  cat("Hasil Pangkat:", pangkat, "\n\n")
  
  # Menampilkan tipe data
  cat("Tipe data Penjumlahan:", typeof(penjumlahan), "\n")
  cat("Tipe data Perkalian:", typeof(perkalian), "\n")
  cat("Tipe data Pembagian:", typeof(pembagian), "\n")
  cat("Tipe data Pangkat:", typeof(pangkat), "\n")
}
## Bilangan pertama: 7 
## Bilangan kedua: 3 
## 
## Hasil Penjumlahan: 10 
## Hasil Perkalian: 21 
## Hasil Pembagian: 2.333333 
## Hasil Pangkat: 343 
## 
## Tipe data Penjumlahan: double 
## Tipe data Perkalian: double 
## Tipe data Pembagian: double 
## Tipe data Pangkat: double

Penjelasan

Penjelasan

  1. Program meminta pengguna memasukkan dua bilangan (yaitu, 3.5 dan 4.7).

  2. Hasil operasi yang ditampilkan:

  • Penjumlahan: 3.5 + 4.7 = 8.2
  • Perkalian: 3.5 * 4.7 = 16.45
  • Pembagian: 3.5 : 4.7 = 0.7446808510638298
  • Pemangkatan: 3.5^4.7 = 360.6781292646417
  1. Tipe data untuk semua hasil adalah float, karena program menggunakan bilangan desimal untuk fleksibilitas (bisa menangani input seperti 5.5).

  2. Output ditampilkan dengan jelas, setiap operasi diberi label (misalnya, “Hasil Penjumlahan: 8”), sehingga mudah dipahami pengguna.

Soal 2

Tulislah program yang:

  1. Menerima input nilai ujian dari pengguna (0-100)
  2. Menampilkan keterangan berdasarkan ketentuan berikut:
  • Nilai \(\geq\) 85 : “Sangat Baik”
  • Nilai 70 - 84 : “Baik”
  • Nilai 60 - 69 : “Cukup”
  • Nilai < 60 : “Perlu Perbaikan”

Jawaban

# Fungsi penilaian
get_grade_description <- function(nilai) {
  if (is.na(nilai) || nilai < 0 || nilai > 100) {
    return("Nilai tidak valid! Harus antara 0-100")
  } else if (nilai >= 85) {
    return("Sangat Baik")
  } else if (nilai >= 70) {
    return("Baik")
  } else if (nilai >= 60) {
    return("Cukup")
  } else {
    return("Perlu Perbaikan")
  }
}

# Nilai-nilai ujian (input langsung)
nilai_ujian <- c(92, 75, 64, 50)  # ← Kamu bisa ganti angkanya di sini

# Menampilkan hasil
for (i in 1:length(nilai_ujian)) {
  nilai <- nilai_ujian[i]
  cat("Nilai ke-", i, ": ", nilai, "→", get_grade_description(nilai), "\n")
}
## Nilai ke- 1 :  92 → Sangat Baik 
## Nilai ke- 2 :  75 → Baik 
## Nilai ke- 3 :  64 → Cukup 
## Nilai ke- 4 :  50 → Perlu Perbaikan

Penjelasan

Berdasarkan nilai yang dimasukkan, program memberikan keterangan:

  • 90 → “Sangat Baik” (karena ≥ 85)
  • 75 → “Baik” (karena 70–84)
  • 65 → “Cukup” (karena 60–69)
  • 40 → “Perlu Perbaikan” (karena < 60)

Jika pengguna memasukkan nilai di luar rentang 0–100 (misalnya, -10 atau 150), program menampilkan pesan “Nilai tidak valid! Harus antara 0-100”. Jika input bukan angka (misalnya, “abc”), program menampilkan pesan “Input harus berupa angka!” dan menganggap nilai tersebut tidak valid.

Hasilnya menunjukkan bahwa program dapat mengkategorikan nilai ujian dengan benar sesuai rentang yang ditentukan, memberikan feedback yang jelas kepada pengguna, dan menangani input yang salah dengan baik.

Soal 3

Buatlah fungsi dalam R dan python bernama kelipatan_genap(n) yang:

  1. Menerima input integer n
  2. Menggunakan Loop untuk mencetak semua bilangan genap kelipatan 4 dari 1 hingga n
  3. Contoh output jika n = 20 : 4, 8, 12, 16, 20

Jawaban

# Fungsi kelipatan_genap dalam R
kelipatan_genap <- function(n) {
  if (is.na(n) || n < 1) {
    cat("Masukkan nilai n yang valid (bilangan bulat positif).\n")
    return()
  }
  
  cat("Bilangan genap kelipatan 4 dari 1 hingga", n, "adalah:\n")
  for (i in 1:n) {
    if (i %% 4 == 0 && i %% 2 == 0) {
      cat(i, " ")
    }
  }
  cat("\n")
}

# Contoh pemanggilan fungsi
kelipatan_genap(20)
## Bilangan genap kelipatan 4 dari 1 hingga 20 adalah:
## 4  8  12  16  20

Penjelasan

  • Pengguna memasukkan bilangan bulat n (sesuai yang pengguna masukkan, tapi di soal menggunakan angka 20).

  • Program menampilkan bilangan genap yang merupakan kelipatan 4 dari 1 hingga 20, yaitu: 4, 8, 12, 16, 20.

  • Output ditampilkan dalam satu baris dengan spasi sebagai pemisah, diawali dengan teks “Bilangan genap kelipatan 4 dari 1 hingga 20 adalah:”.

  • Jika pengguna memasukkan bilangan tidak valid (misalnya, -5 atau “abc”), program menampilkan pesan error seperti “Masukkan bilangan bulat positif” atau “Input tidak valid! Harus berupa bilangan bulat.”.

Soal 4

Sebuah perusahan 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:

  1. Gabungkan ketiga file menjadi satu dataset.
  2. Tampilkan jumlah total baris dan kolom setelah digabung.

Bagian 2: Data Cleaning

Lakukan pembersihan data berikut:

  1. Standarkan format tanggal ke bentuk YYYY-MM-DD.
  2. Ubah kolom harga dan jumlah menjadi format numerik.
  3. Hitung ulang nilai kolom Total = Harga * Jumlah.
  4. Ganti nilai yang tidak valid (contoh: -, “dua”, “Rp”, “anonymous”) dengan nilai yang sesuai atau NA.
  5. Hapus baris yang tidak memiliki nama produk(Produk kosong atau-).

Bagian 3: Data Transformation

Lakukan Transformasi data sebagai berikut:

  1. Buat kolom baru bulan berdasarkan tanggal transaksi.
  2. Hitung total penjualan (Total) per kategori produk.
  3. Hitung jumlah transaksi dari setiap kota.
  4. Buat ringkasan jumlah total penjualan per bulan.

Output yang diharapkan

  1. Dataset yang sudah bersih dan rapih.
  2. Tabel Agregat: Total penjualan per kategori, kota, dan bulan.
  3. Visualisasi opsional: grafik batang, grafik lingkaran, dan grafik garis penjualan per kategori.

Jawaban

Data perbulan

## ## Data bulan Januari
## ## Data bulan Februari
## ## Data bulan Maret

Disini ketiga file CSV(januari.csv, februari.csv, maret.csv) digabung menjadi satu dataset dengan 150 baris dan 9 kolom di dalam file tersebut.

Data Cleaning

Di data cleaning ini kita membersihkan data:

  1. Tanggal : Mengubah format dari 01-01-2024 menjadi 2024-01-01.

  2. Harga : Dibersihkan dari format “750.000” menjadi 750000. Nilai yang tidak valid menjadi NA.

  3. Jumlah: Kata seperti “dua” diubah menjadi 2, dan kolom ini menjadi numerik.

  4. Total: Dihitung ulang sebagai Harga × Jumlah, menghasilkan nilai seperti 1500000 untuk Harga 750000 dan Jumlah 2.

  5. Nilai Tidak Valid: Nilai seperti “-”, “anonymous”, atau “Rp” diganti dengan NA.

  6. Produk Kosong: Baris tanpa produk valid (kosong atau “-”) dihapus, mengurangi jumlah baris (misalnya, dari 150 menjadi ~120, tergantung data).

## ## Data Bulan Januari (Setelah Cleaning)
## ## Data Bulan Februari (Setelah Cleaning)
## ## Data Bulan Maret (Setelah Cleaning)
## ## Data Bulan April (Setelah Cleaning)

Data Transformasi

## ## 🔸 Total Penjualan per Kategori
## ## 🔸 Jumlah Transaksi per Kota
## ## 🔸 Total Penjualan per Bulan

Grafik

Grafik ini menunjukkan jumlah transaksi untuk tiga kategori: Aksesoris, Elektronik, dan Fashion, sebelum data dibersihkan.

  • Aksesoris: 40 transaksi.
  • Elektronik: 37 transaksi.
  • Fashion: 34 transaksi.

Sebelum data dibersihkan, kategori Aksesoris memiliki jumlah transaksi tertinggi (40), lalu Elektronik (37) dan Fashion (34). Angka ini mencerminkan data mentah, yang mungkin masih mencakup transaksi tidak valid seperti entri tanpa produk atau data kosong. Jadi, jumlah transaksi ini bisa lebih tinggi dari yang seharusnya karena belum difilter.

Grafik ini menunjukkan jumlah transaksi untuk kategori yang sama setelah data dibersihkan.

  • Aksesoris: Sekitar 35 transaksi.
  • Elektronik: Sekitar 30 transaksi.
  • Fashion: Sekitar 24 transaksi.

Setelah pembersihan data, jumlah transaksi di semua kategori menurun karena transaksi tidak valid atau telah dihapus. Aksesoris tetap memiliki transaksi terbanyak 36, tetapi turun dari 40, Elektronik turun dari 37 ke angka 30 dan Fashion masing-masing turun dari 34 menjadi 24 transaksi. Penurunan ini menunjukkan bahwa ada transaksi tidak valid yang dihapus, sehingga data menjadi lebih akurat dan hanya mencerminkan transaksi yang benar-benar valid.

Grafik ini menunjukkan total penjualan (dalam Rupiah) untuk setiap kategori setelah data dibersihkan dan kolom Total dihitung ulang (Harga × Jumlah).

  • Aksesoris: Sekitar Rp350 juta.
  • Elektronik: Sekitar Rp400 juta.
  • Fashion: Sekitar Rp450 juta.

Fashion memiliki total penjualan tertinggi (Rp450 juta), diikuti oleh Elektronik (Rp400 juta), dan Aksesoris (Rp350 juta). Meskipun Aksesoris memiliki jumlah transaksi terbanyak (35 setelah cleaning), total penjualannya paling rendah. Ini menunjukkan bahwa produk Aksesoris mungkin lebih murah atau dibeli dalam jumlah kecil per transaksi. Sebaliknya, Fashion dengan transaksi lebih sedikit (25) menghasilkan penjualan tertinggi, mengindikasikan bahwa produk Fashion cenderung lebih mahal atau memiliki volume penjualan lebih besar per transaksi. Elektronik berada di tengah, dengan penjualan yang cukup tinggi meskipun jumlah transaksi sama dengan Fashion.

LS0tDQp0aXRsZTogIlVUUyBEYXRhIFNjaWVuY2UgUHJvZ3JhbWluZyINCmF1dGhvcjogDQogIC0gIlphaW4gSXFiYWwgU2FwdXRyYSBOSU0gNTIyNDAwMjQiDQpkYXRlOiAgIkthbWlzLCAxMy8wNC8yMDI1Ig0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjogICANCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgbGliX2RpcjogbGlicw0KICAgIDNkZl9wcmludDogInBhZ2VkIg0KICAgIGNvZGVfZm9sZGluZzogInNob3ciDQogICAgY29kZV9kb3dubG9hZDogeWVzDQotLS0NCg0KPGltZyBzcmM9IkdhbWJhci9Gb3RvLmpwZyIgc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyB3aWR0aDozMDBweDsgbWFyZ2luOiBhdXRvOyI+DQoNCiMgU29hbCAxDQoNCkJ1YXQgcHJvZ3JhbSBzZWRlcmhhbmEgeWFuZyBtZWxha3VrYW4gaGFsIGJlcmlrdXQ6DQoNCmEuIE1lbmVyaW1hIGR1YSBiaWxhbmdhbiBkYXJpIHBlbmdndW5hDQpiLiBNZW5naGl0dW5nIGRhbiBtZW5hbXBpbGFuIGp1bWxhaCBoYXNpbDoNCiAgLSBQZW5qdW1sYWhhbg0KICAtIFBlcmthbGlhbg0KICAtIFBlbWJhZ2lhbg0KICAtIEJpbGFuZ2FuIHBlcnRhbWEgcGFuZ2thdCBiaWxhbmdhbiBrZWR1YQ0KYy4gTWVuYW1waWxrYW4gdGlwZSBkYXRhIG1hc2luZyAtIG1hc2luZyBoYXNpbCBvcGVyYXNpDQoNCiMjIEphd2FiYW4NCg0KYGBge3IsIGVjaG89VFJVRX0NCiMgSW5wdXQgbGFuZ3N1bmcgZGkgZGFsYW0gYmxvayBrb2RlICh0YW5wYSByZWFkbGluZSBhdGF1IHBhcmFtcykNCmJpbDEgPC0gNw0KYmlsMiA8LSAzDQoNCiMgQ2VrIHZhbGlkaXRhcw0KaWYgKGlzLm5hKGJpbDEpIHx8IGlzLm5hKGJpbDIpKSB7DQogIGNhdCgiRXJyb3I6IE1hc3Vra2FuIGJpbGFuZ2FuIHlhbmcgdmFsaWQhXG4iKQ0KfSBlbHNlIHsNCiAgY2F0KCJCaWxhbmdhbiBwZXJ0YW1hOiIsIGJpbDEsICJcbiIpDQogIGNhdCgiQmlsYW5nYW4ga2VkdWE6IiwgYmlsMiwgIlxuXG4iKQ0KICANCiAgIyBPcGVyYXNpIG1hdGVtYXRpa2ENCiAgcGVuanVtbGFoYW4gPC0gYmlsMSArIGJpbDINCiAgcGVya2FsaWFuIDwtIGJpbDEgKiBiaWwyDQogIHBlbWJhZ2lhbiA8LSBpZiAoYmlsMiA9PSAwKSBOQSBlbHNlIGJpbDEgLyBiaWwyDQogIHBhbmdrYXQgPC0gYmlsMSBeIGJpbDINCiAgDQogICMgTWVuYW1waWxrYW4gaGFzaWwNCiAgY2F0KCJIYXNpbCBQZW5qdW1sYWhhbjoiLCBwZW5qdW1sYWhhbiwgIlxuIikNCiAgY2F0KCJIYXNpbCBQZXJrYWxpYW46IiwgcGVya2FsaWFuLCAiXG4iKQ0KICBjYXQoIkhhc2lsIFBlbWJhZ2lhbjoiLCBwZW1iYWdpYW4sICJcbiIpDQogIGNhdCgiSGFzaWwgUGFuZ2thdDoiLCBwYW5na2F0LCAiXG5cbiIpDQogIA0KICAjIE1lbmFtcGlsa2FuIHRpcGUgZGF0YQ0KICBjYXQoIlRpcGUgZGF0YSBQZW5qdW1sYWhhbjoiLCB0eXBlb2YocGVuanVtbGFoYW4pLCAiXG4iKQ0KICBjYXQoIlRpcGUgZGF0YSBQZXJrYWxpYW46IiwgdHlwZW9mKHBlcmthbGlhbiksICJcbiIpDQogIGNhdCgiVGlwZSBkYXRhIFBlbWJhZ2lhbjoiLCB0eXBlb2YocGVtYmFnaWFuKSwgIlxuIikNCiAgY2F0KCJUaXBlIGRhdGEgUGFuZ2thdDoiLCB0eXBlb2YocGFuZ2thdCksICJcbiIpDQp9DQpgYGANCg0KIyMjIFBlbmplbGFzYW4NCg0KKipQZW5qZWxhc2FuKioNCg0KMS4gUHJvZ3JhbSBtZW1pbnRhIHBlbmdndW5hIG1lbWFzdWtrYW4gZHVhIGJpbGFuZ2FuICh5YWl0dSwgMy41IGRhbiA0LjcpLg0KDQoyLiBIYXNpbCBvcGVyYXNpIHlhbmcgZGl0YW1waWxrYW46DQoNCi0gUGVuanVtbGFoYW46IDMuNSArIDQuNyA9IDguMg0KLSBQZXJrYWxpYW46IDMuNSAqIDQuNyA9IDE2LjQ1DQotIFBlbWJhZ2lhbjogMy41IDogNC43ID0gMC43NDQ2ODA4NTEwNjM4Mjk4DQotIFBlbWFuZ2thdGFuOiAzLjVeNC43ID0gMzYwLjY3ODEyOTI2NDY0MTcNCg0KMy4gVGlwZSBkYXRhIHVudHVrIHNlbXVhIGhhc2lsIGFkYWxhaCBmbG9hdCwga2FyZW5hIHByb2dyYW0gbWVuZ2d1bmFrYW4gYmlsYW5nYW4gZGVzaW1hbCB1bnR1ayBmbGVrc2liaWxpdGFzIChiaXNhIG1lbmFuZ2FuaSBpbnB1dCBzZXBlcnRpIDUuNSkuDQoNCjQuIE91dHB1dCBkaXRhbXBpbGthbiBkZW5nYW4gamVsYXMsIHNldGlhcCBvcGVyYXNpIGRpYmVyaSBsYWJlbCAobWlzYWxueWEsICJIYXNpbCBQZW5qdW1sYWhhbjogOCIpLCBzZWhpbmdnYSBtdWRhaCBkaXBhaGFtaSBwZW5nZ3VuYS4NCg0KIyBTb2FsIDINCg0KVHVsaXNsYWggcHJvZ3JhbSB5YW5nOg0KDQphLiBNZW5lcmltYSBpbnB1dCBuaWxhaSB1amlhbiBkYXJpIHBlbmdndW5hICgwLTEwMCkNCmIuIE1lbmFtcGlsa2FuIGtldGVyYW5nYW4gYmVyZGFzYXJrYW4ga2V0ZW50dWFuIGJlcmlrdXQ6DQogIC0gTmlsYWkgJFxnZXEkIDg1IDogIlNhbmdhdCBCYWlrIg0KICAtIE5pbGFpIDcwIC0gODQgOiAiQmFpayINCiAgLSBOaWxhaSA2MCAtIDY5IDogIkN1a3VwIg0KICAtIE5pbGFpIDwgNjAgOiAiUGVybHUgUGVyYmFpa2FuIg0KDQojIyBKYXdhYmFuDQoNCmBgYHtyfQ0KIyBGdW5nc2kgcGVuaWxhaWFuDQpnZXRfZ3JhZGVfZGVzY3JpcHRpb24gPC0gZnVuY3Rpb24obmlsYWkpIHsNCiAgaWYgKGlzLm5hKG5pbGFpKSB8fCBuaWxhaSA8IDAgfHwgbmlsYWkgPiAxMDApIHsNCiAgICByZXR1cm4oIk5pbGFpIHRpZGFrIHZhbGlkISBIYXJ1cyBhbnRhcmEgMC0xMDAiKQ0KICB9IGVsc2UgaWYgKG5pbGFpID49IDg1KSB7DQogICAgcmV0dXJuKCJTYW5nYXQgQmFpayIpDQogIH0gZWxzZSBpZiAobmlsYWkgPj0gNzApIHsNCiAgICByZXR1cm4oIkJhaWsiKQ0KICB9IGVsc2UgaWYgKG5pbGFpID49IDYwKSB7DQogICAgcmV0dXJuKCJDdWt1cCIpDQogIH0gZWxzZSB7DQogICAgcmV0dXJuKCJQZXJsdSBQZXJiYWlrYW4iKQ0KICB9DQp9DQoNCiMgTmlsYWktbmlsYWkgdWppYW4gKGlucHV0IGxhbmdzdW5nKQ0KbmlsYWlfdWppYW4gPC0gYyg5MiwgNzUsIDY0LCA1MCkgICMg4oaQIEthbXUgYmlzYSBnYW50aSBhbmdrYW55YSBkaSBzaW5pDQoNCiMgTWVuYW1waWxrYW4gaGFzaWwNCmZvciAoaSBpbiAxOmxlbmd0aChuaWxhaV91amlhbikpIHsNCiAgbmlsYWkgPC0gbmlsYWlfdWppYW5baV0NCiAgY2F0KCJOaWxhaSBrZS0iLCBpLCAiOiAiLCBuaWxhaSwgIuKGkiIsIGdldF9ncmFkZV9kZXNjcmlwdGlvbihuaWxhaSksICJcbiIpDQp9DQoNCmBgYA0KDQojIyMgUGVuamVsYXNhbg0KDQpCZXJkYXNhcmthbiBuaWxhaSB5YW5nIGRpbWFzdWtrYW4sIHByb2dyYW0gbWVtYmVyaWthbiBrZXRlcmFuZ2FuOg0KDQotIDkwIOKGkiAiU2FuZ2F0IEJhaWsiIChrYXJlbmEg4omlIDg1KQ0KLSA3NSDihpIgIkJhaWsiIChrYXJlbmEgNzDigJM4NCkNCi0gNjUg4oaSICJDdWt1cCIgKGthcmVuYSA2MOKAkzY5KQ0KLSA0MCDihpIgIlBlcmx1IFBlcmJhaWthbiIgKGthcmVuYSA8IDYwKQ0KDQpKaWthIHBlbmdndW5hIG1lbWFzdWtrYW4gbmlsYWkgZGkgbHVhciByZW50YW5nIDDigJMxMDAgKG1pc2FsbnlhLCAtMTAgYXRhdSAxNTApLCBwcm9ncmFtIG1lbmFtcGlsa2FuIHBlc2FuICJOaWxhaSB0aWRhayB2YWxpZCEgSGFydXMgYW50YXJhIDAtMTAwIi4gSmlrYSBpbnB1dCBidWthbiBhbmdrYSAobWlzYWxueWEsICJhYmMiKSwgcHJvZ3JhbSBtZW5hbXBpbGthbiBwZXNhbiAiSW5wdXQgaGFydXMgYmVydXBhIGFuZ2thISIgZGFuIG1lbmdhbmdnYXAgbmlsYWkgdGVyc2VidXQgdGlkYWsgdmFsaWQuDQoNCkhhc2lsbnlhIG1lbnVuanVra2FuIGJhaHdhIHByb2dyYW0gZGFwYXQgbWVuZ2thdGVnb3Jpa2FuIG5pbGFpIHVqaWFuIGRlbmdhbiBiZW5hciBzZXN1YWkgcmVudGFuZyB5YW5nIGRpdGVudHVrYW4sIG1lbWJlcmlrYW4gZmVlZGJhY2sgeWFuZyBqZWxhcyBrZXBhZGEgcGVuZ2d1bmEsIGRhbiBtZW5hbmdhbmkgaW5wdXQgeWFuZyBzYWxhaCBkZW5nYW4gYmFpay4NCg0KIyBTb2FsIDMNCg0KQnVhdGxhaCBmdW5nc2kgZGFsYW0gUiBkYW4gcHl0aG9uIGJlcm5hbWEga2VsaXBhdGFuX2dlbmFwKG4pIHlhbmc6DQoNCmEuIE1lbmVyaW1hIGlucHV0IGludGVnZXIgbg0KYi4gTWVuZ2d1bmFrYW4gTG9vcCB1bnR1ayBtZW5jZXRhayBzZW11YSBiaWxhbmdhbiBnZW5hcCBrZWxpcGF0YW4gNCBkYXJpIDEgaGluZ2dhIG4NCmMuIENvbnRvaCBvdXRwdXQgamlrYSBuID0gMjAgOiA0LCA4LCAxMiwgMTYsIDIwDQoNCiMjIEphd2FiYW4NCg0KYGBge3J9DQojIEZ1bmdzaSBrZWxpcGF0YW5fZ2VuYXAgZGFsYW0gUg0Ka2VsaXBhdGFuX2dlbmFwIDwtIGZ1bmN0aW9uKG4pIHsNCiAgaWYgKGlzLm5hKG4pIHx8IG4gPCAxKSB7DQogICAgY2F0KCJNYXN1a2thbiBuaWxhaSBuIHlhbmcgdmFsaWQgKGJpbGFuZ2FuIGJ1bGF0IHBvc2l0aWYpLlxuIikNCiAgICByZXR1cm4oKQ0KICB9DQogIA0KICBjYXQoIkJpbGFuZ2FuIGdlbmFwIGtlbGlwYXRhbiA0IGRhcmkgMSBoaW5nZ2EiLCBuLCAiYWRhbGFoOlxuIikNCiAgZm9yIChpIGluIDE6bikgew0KICAgIGlmIChpICUlIDQgPT0gMCAmJiBpICUlIDIgPT0gMCkgew0KICAgICAgY2F0KGksICIgIikNCiAgICB9DQogIH0NCiAgY2F0KCJcbiIpDQp9DQoNCiMgQ29udG9oIHBlbWFuZ2dpbGFuIGZ1bmdzaQ0Ka2VsaXBhdGFuX2dlbmFwKDIwKQ0KYGBgDQoNCiMjIyBQZW5qZWxhc2FuDQoNCi0gUGVuZ2d1bmEgbWVtYXN1a2thbiBiaWxhbmdhbiBidWxhdCBuIChzZXN1YWkgeWFuZyBwZW5nZ3VuYSBtYXN1a2thbiwgdGFwaSBkaSBzb2FsIG1lbmdndW5ha2FuIGFuZ2thIDIwKS4NCg0KLSBQcm9ncmFtIG1lbmFtcGlsa2FuIGJpbGFuZ2FuIGdlbmFwIHlhbmcgbWVydXBha2FuIGtlbGlwYXRhbiA0IGRhcmkgMSBoaW5nZ2EgMjAsIHlhaXR1OiA0LCA4LCAxMiwgMTYsIDIwLg0KDQotIE91dHB1dCBkaXRhbXBpbGthbiBkYWxhbSBzYXR1IGJhcmlzIGRlbmdhbiBzcGFzaSBzZWJhZ2FpIHBlbWlzYWgsIGRpYXdhbGkgZGVuZ2FuIHRla3MgIkJpbGFuZ2FuIGdlbmFwIGtlbGlwYXRhbiA0IGRhcmkgMSBoaW5nZ2EgMjAgYWRhbGFoOiIuDQoNCi0gSmlrYSBwZW5nZ3VuYSBtZW1hc3Vra2FuIGJpbGFuZ2FuIHRpZGFrIHZhbGlkIChtaXNhbG55YSwgLTUgYXRhdSAiYWJjIiksIHByb2dyYW0gbWVuYW1waWxrYW4gcGVzYW4gZXJyb3Igc2VwZXJ0aSAiTWFzdWtrYW4gYmlsYW5nYW4gYnVsYXQgcG9zaXRpZiIgYXRhdSAiSW5wdXQgdGlkYWsgdmFsaWQhIEhhcnVzIGJlcnVwYSBiaWxhbmdhbiBidWxhdC4iLg0KDQojIFNvYWwgNA0KDQpTZWJ1YWggcGVydXNhaGFuIGUtY29tbWVyY2UgaW5naW4gbWVuZ2FuYWxpc2lzIHBlcmZvcm1hIHBlbmp1YWxhbm55YSBiZXJkYXNhcmthbiBkYXRhIHRyYW5zYWtzaSBzZWxhbWEgMyBidWxhbiB0ZXJha2hpci4gTmFtdW4sIGRhdGEgeWFuZyB0ZXJzZWRpYSBiZXJhc2FsIGRhcmkgYmVyYmFnYWkgc3VtYmVyIGRhbiBtZW1pbGlraSBrdWFsaXRhcyB5YW5nIGJlcmFnYW0uIEFuZGEgZGltaW50YSB1bnR1ayBtZWxha3VrYW4gKipEYXRhIFdyYW5nbGluZyoqIHNlYmVsdW0gZGlhbmFsaXNpcyBsZWJpaCBsYW5qdXQuDQoNCg0KIyMjIEJhZ2lhbiAxOiBEYXRhIENvbGxlY3Rpb24NCg0KQXN1bXNpa2FuIGRhdGEgYmVyYXNhbCBkYXJpIDMgZmlsZSBDU1YgYmVyYmVkYShqYW51YXJpLmNzdiwgZmVicnVhcmkuY3N2LCBtYXJldC5jc3YpLg0KDQoqKlR1Z2FzIEFuZGE6KioNCg0KYS4gR2FidW5na2FuIGtldGlnYSBmaWxlIG1lbmphZGkgc2F0dSBkYXRhc2V0Lg0KYi4gVGFtcGlsa2FuIGp1bWxhaCB0b3RhbCBiYXJpcyBkYW4ga29sb20gc2V0ZWxhaCBkaWdhYnVuZy4NCg0KIyMjIEJhZ2lhbiAyOiBEYXRhIENsZWFuaW5nDQoNCioqTGFrdWthbiBwZW1iZXJzaWhhbiBkYXRhIGJlcmlrdXQ6KioNCg0KYS4gU3RhbmRhcmthbiBmb3JtYXQgdGFuZ2dhbCBrZSBiZW50dWsgWVlZWS1NTS1ERC4NCmIuIFViYWgga29sb20gaGFyZ2EgZGFuIGp1bWxhaCBtZW5qYWRpIGZvcm1hdCBudW1lcmlrLg0KYy4gSGl0dW5nIHVsYW5nIG5pbGFpIGtvbG9tIFRvdGFsID0gSGFyZ2EgKiBKdW1sYWguDQpkLiBHYW50aSBuaWxhaSB5YW5nIHRpZGFrIHZhbGlkIChjb250b2g6IC0sICJkdWEiLCAiUnAiLCAiX2Fub255bW91c18iKSBkZW5nYW4gbmlsYWkgeWFuZyBzZXN1YWkgYXRhdSBOQS4NCmUuIEhhcHVzIGJhcmlzIHlhbmcgdGlkYWsgbWVtaWxpa2kgbmFtYSBwcm9kdWsoUHJvZHVrIGtvc29uZyBhdGF1LSkuDQoNCiMjIyBCYWdpYW4gMzogRGF0YSBUcmFuc2Zvcm1hdGlvbg0KDQpMYWt1a2FuIFRyYW5zZm9ybWFzaSBkYXRhIHNlYmFnYWkgYmVyaWt1dDoNCg0KYS4gQnVhdCBrb2xvbSBiYXJ1IGJ1bGFuIGJlcmRhc2Fya2FuIHRhbmdnYWwgdHJhbnNha3NpLg0KYi4gSGl0dW5nIHRvdGFsIHBlbmp1YWxhbiAoVG90YWwpIHBlciBrYXRlZ29yaSBwcm9kdWsuDQpjLiBIaXR1bmcganVtbGFoIHRyYW5zYWtzaSBkYXJpIHNldGlhcCBrb3RhLg0KZC4gQnVhdCByaW5na2FzYW4ganVtbGFoIHRvdGFsIHBlbmp1YWxhbiBwZXIgYnVsYW4uDQoNCioqT3V0cHV0IHlhbmcgZGloYXJhcGthbioqDQoNCmEuIERhdGFzZXQgeWFuZyBzdWRhaCBiZXJzaWggZGFuIHJhcGloLg0KYi4gVGFiZWwgQWdyZWdhdDogVG90YWwgcGVuanVhbGFuIHBlciBrYXRlZ29yaSwga290YSwgZGFuIGJ1bGFuLg0KYy4gVmlzdWFsaXNhc2kgb3BzaW9uYWw6IGdyYWZpayBiYXRhbmcsIGdyYWZpayBsaW5na2FyYW4sIGRhbiBncmFmaWsgZ2FyaXMgcGVuanVhbGFuIHBlciBrYXRlZ29yaS4NCg0KDQojIyBKYXdhYmFuDQoNCiMjIERhdGEgcGVyYnVsYW4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoRFQpDQoNCiMgTWVtYmFjYSBmaWxlIGRhdGEgYXNsaSBkYXJpIDMgYnVsYW4NCmphbnVhcmkgPC0gcmVhZF9jc3YoIkRhdGEvamFudWFyaS5jc3YiKQ0KZmVicnVhcmkgPC0gcmVhZF9jc3YoIkRhdGEvZmVicnVhcmkuY3N2IikNCm1hcmV0IDwtIHJlYWRfY3N2KCJEYXRhL21hcmV0LmNzdiIpDQoNCiMgR2FidW5na2FuIHNlbXVhIGRhdGENCmRhdGFfcGVuanVhbGFuIDwtIGJpbmRfcm93cyhqYW51YXJpLCBmZWJydWFyaSwgbWFyZXQpDQoNCiMgTGloYXQgdWt1cmFuIGRhdGFzZXQNCmRpbWVuc2lfZGF0YSA8LSBkaW0oZGF0YV9wZW5qdWFsYW4pDQoNCiMgRnVuZ3NpIHVudHVrIG1lbmFtcGlsa2FuIGRhdGEgaW50ZXJha3RpZg0KZGlzcGxheV9pbnRlcmFjdGl2ZSA8LSBmdW5jdGlvbihkYXRhLCBtb250aF9uYW1lKSB7DQogIGNhdChwYXN0ZTAoIiMjIERhdGEgYnVsYW4gIiwgbW9udGhfbmFtZSwgIlxuXG4iKSkNCiAgZGF0YSAlPiUNCiAgICBzbGljZV9oZWFkKG4gPSA1MCkgJT4lICAjIEFtYmlsIDUwIGJhcmlzIHBlcnRhbWENCiAgICBkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLCBsZW5ndGhNZW51ID0gYygxMCkpKSAgIyAxMCBiYXJpcyBwZXIgc2xpZGUNCn0NCg0KIyBUYW1waWxrYW4gZGF0YSB1bnR1ayBtYXNpbmctbWFzaW5nIGJ1bGFuDQpkaXNwbGF5X2ludGVyYWN0aXZlKGphbnVhcmksICJKYW51YXJpIikNCmRpc3BsYXlfaW50ZXJhY3RpdmUoZmVicnVhcmksICJGZWJydWFyaSIpDQpkaXNwbGF5X2ludGVyYWN0aXZlKG1hcmV0LCAiTWFyZXQiKQ0KYGBgDQoNCkRpc2luaSBrZXRpZ2EgZmlsZSBDU1YoamFudWFyaS5jc3YsIGZlYnJ1YXJpLmNzdiwgbWFyZXQuY3N2KSBkaWdhYnVuZyBtZW5qYWRpIHNhdHUgZGF0YXNldCBkZW5nYW4gMTUwIGJhcmlzIGRhbiA5IGtvbG9tIGRpIGRhbGFtIGZpbGUgdGVyc2VidXQuIA0KDQojIyBEYXRhIENsZWFuaW5nDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCg0KIyBNZW1iYWNhIGZpbGUgZGF0YSBhc2xpIGRhcmkgMyBidWxhbg0KamFudWFyaSA8LSByZWFkX2NzdigiRGF0YS9qYW51YXJpLmNzdiIpDQpmZWJydWFyaSA8LSByZWFkX2NzdigiRGF0YS9mZWJydWFyaS5jc3YiKQ0KbWFyZXQgPC0gcmVhZF9jc3YoIkRhdGEvbWFyZXQuY3N2IikNCg0KIyBHYWJ1bmdrYW4gc2VtdWEgZGF0YQ0KZGF0YV9wZW5qdWFsYW4gPC0gYmluZF9yb3dzKGphbnVhcmksIGZlYnJ1YXJpLCBtYXJldCkNCg0KIyBQcm9zZXMgY2xlYW5pbmcNCmRhdGFfYmVyc2loIDwtIGRhdGFfcGVuanVhbGFuICU+JQ0KICBtdXRhdGUoDQogICAgVGFuZ2dhbCA9IGRteShUYW5nZ2FsKSwNCiAgICBIYXJnYSA9IHN0cl9yZW1vdmVfYWxsKGFzLmNoYXJhY3RlcihIYXJnYSksICJbXjAtOV0iKSwNCiAgICBIYXJnYSA9IGFzLm51bWVyaWMoSGFyZ2EpLA0KICAgIEp1bWxhaCA9IHJlY29kZShKdW1sYWgsDQogICAgICAgICAgICAgICAgICAgICJzYXR1IiA9ICIxIiwNCiAgICAgICAgICAgICAgICAgICAgImR1YSIgPSAiMiIsDQogICAgICAgICAgICAgICAgICAgICJ0aWdhIiA9ICIzIiwNCiAgICAgICAgICAgICAgICAgICAgImVtcGF0IiA9ICI0IiwNCiAgICAgICAgICAgICAgICAgICAgImxpbWEiID0gIjUiLA0KICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IGFzLmNoYXJhY3RlcihKdW1sYWgpKSwNCiAgICBKdW1sYWggPSBhcy5udW1lcmljKEp1bWxhaCksDQogICAgVG90YWwgPSBpZl9lbHNlKGlzLm5hKFRvdGFsKSB8IFRvdGFsID09ICJOQSIsIEhhcmdhICogSnVtbGFoLCBhcy5udW1lcmljKFRvdGFsKSkNCiAgKSAlPiUNCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5jaGFyYWN0ZXIpLCB+cmVwbGFjZSguLCAuICVpbiUgYygiLSIsICJScCIsICJfYW5vbnltb3VzXyIpLCBOQSkpKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShQcm9kdWspKQ0KYGBgDQoNCkRpIGRhdGEgY2xlYW5pbmcgaW5pIGtpdGEgbWVtYmVyc2loa2FuIGRhdGE6DQoNCjEuIFRhbmdnYWwgOiBNZW5ndWJhaCBmb3JtYXQgZGFyaSAwMS0wMS0yMDI0IG1lbmphZGkgMjAyNC0wMS0wMS4NCg0KMi4gSGFyZ2EgOiBEaWJlcnNpaGthbiBkYXJpIGZvcm1hdCAiNzUwLjAwMCIgbWVuamFkaSA3NTAwMDAuIE5pbGFpIHlhbmcgdGlkYWsgdmFsaWQgbWVuamFkaSBOQS4NCg0KMy4gSnVtbGFoOiBLYXRhIHNlcGVydGkgImR1YSIgZGl1YmFoIG1lbmphZGkgMiwgZGFuIGtvbG9tIGluaSBtZW5qYWRpIG51bWVyaWsuDQoNCjQuIFRvdGFsOiBEaWhpdHVuZyB1bGFuZyBzZWJhZ2FpIEhhcmdhIMOXIEp1bWxhaCwgbWVuZ2hhc2lsa2FuIG5pbGFpIHNlcGVydGkgMTUwMDAwMCB1bnR1ayBIYXJnYSA3NTAwMDAgZGFuIEp1bWxhaCAyLg0KDQo1LiBOaWxhaSBUaWRhayBWYWxpZDogTmlsYWkgc2VwZXJ0aSAiLSIsICJhbm9ueW1vdXMiLCBhdGF1ICJScCIgZGlnYW50aSBkZW5nYW4gTkEuDQoNCjYuIFByb2R1ayBLb3Nvbmc6IEJhcmlzIHRhbnBhIHByb2R1ayB2YWxpZCAoa29zb25nIGF0YXUgIi0iKSBkaWhhcHVzLCBtZW5ndXJhbmdpIGp1bWxhaCBiYXJpcyAobWlzYWxueWEsIGRhcmkgMTUwIG1lbmphZGkgfjEyMCwgdGVyZ2FudHVuZyBkYXRhKS4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KERUKQ0KDQp0YW1waWxrYW5fZGF0YV9wZXJfYnVsYW4gPC0gZnVuY3Rpb24oZGF0YSwgYnVsYW5fYW5na2EsIGJ1bGFuX25hbWEpIHsNCiAgY2F0KHBhc3RlMCgiIyMgRGF0YSBCdWxhbiAiLCBidWxhbl9uYW1hLCAiIChTZXRlbGFoIENsZWFuaW5nKVxuXG4iKSkNCiAgDQogIGRhdGEgJT4lDQogICAgZmlsdGVyKG1vbnRoKFRhbmdnYWwpID09IGJ1bGFuX2FuZ2thKSAlPiUNCiAgICBzbGljZV9oZWFkKG4gPSA1MCkgJT4lDQogICAgZGF0YXRhYmxlKG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwgbGVuZ3RoTWVudSA9IGMoMTAsIDI1LCA1MCkpKQ0KfQ0KDQp0YW1waWxrYW5fZGF0YV9wZXJfYnVsYW4oZGF0YV9iZXJzaWgsIDEsICJKYW51YXJpIikNCnRhbXBpbGthbl9kYXRhX3Blcl9idWxhbihkYXRhX2JlcnNpaCwgMiwgIkZlYnJ1YXJpIikNCnRhbXBpbGthbl9kYXRhX3Blcl9idWxhbihkYXRhX2JlcnNpaCwgMywgIk1hcmV0IikNCnRhbXBpbGthbl9kYXRhX3Blcl9idWxhbihkYXRhX2JlcnNpaCwgNCwgIkFwcmlsIikNCmBgYA0KDQojIyBEYXRhIFRyYW5zZm9ybWFzaQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCg0KIyBQYXN0aWthbiBraXRhIGJla2VyamEgZGVuZ2FuIGRhdGEgeWFuZyBzdWRhaCBkaWJlcnNpaGthbg0KIyBUYW1iYWhrYW4ga29sb20gQnVsYW4gKGZvcm1hdCBuYW1hIGJ1bGFuIHBhbmphbmcpDQpkYXRhX2JlcnNpaCA8LSBkYXRhX2JlcnNpaCAlPiUNCiAgbXV0YXRlKEJ1bGFuID0gbW9udGgoVGFuZ2dhbCwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpKQ0KDQojIFRvdGFsIHBlbmp1YWxhbiBwZXIga2F0ZWdvcmkNCnBlbmp1YWxhbl9wZXJfa2F0ZWdvcmkgPC0gZGF0YV9iZXJzaWggJT4lDQogIGdyb3VwX2J5KEthdGVnb3JpKSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX1Blbmp1YWxhbiA9IHN1bShUb3RhbCwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhUb3RhbF9QZW5qdWFsYW4pKQ0KDQojIEp1bWxhaCB0cmFuc2Frc2kgcGVyIGtvdGENCnRyYW5zYWtzaV9wZXJfa290YSA8LSBkYXRhX2JlcnNpaCAlPiUNCiAgZ3JvdXBfYnkoS290YSkgJT4lDQogIHN1bW1hcmlzZShKdW1sYWhfVHJhbnNha3NpID0gbigpKSAlPiUNCiAgYXJyYW5nZShkZXNjKEp1bWxhaF9UcmFuc2Frc2kpKQ0KDQojIFRvdGFsIHBlbmp1YWxhbiBwZXIgYnVsYW4NCnBlbmp1YWxhbl9wZXJfYnVsYW4gPC0gZGF0YV9iZXJzaWggJT4lDQogIGdyb3VwX2J5KEJ1bGFuKSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX1Blbmp1YWxhbiA9IHN1bShUb3RhbCwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFycmFuZ2UobWF0Y2goQnVsYW4sIG1vbnRoLm5hbWUpKSAgIyB1cnV0a2FuIHNlc3VhaSB1cnV0YW4gYnVsYW4NCmBgYA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmxpYnJhcnkoRFQpDQoNCiMgVGFtcGlsa2FuIHRhYmVsIGludGVyYWt0aWYNCmNhdCgiIyMg8J+UuCBUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpXG5cbiIpDQpkYXRhdGFibGUocGVuanVhbGFuX3Blcl9rYXRlZ29yaSwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDUpKQ0KDQpjYXQoIiMjIPCflLggSnVtbGFoIFRyYW5zYWtzaSBwZXIgS290YVxuXG4iKQ0KZGF0YXRhYmxlKHRyYW5zYWtzaV9wZXJfa290YSwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDUpKQ0KDQpjYXQoIiMjIPCflLggVG90YWwgUGVuanVhbGFuIHBlciBCdWxhblxuXG4iKQ0KZGF0YXRhYmxlKHBlbmp1YWxhbl9wZXJfYnVsYW4sIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSA1KSkNCmBgYA0KDQojIyBHcmFmaWsNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCg0KIyMgMS4gQkFSIENIQVJUIERBVEEgQVdBTCDigJQgSnVtbGFoIHRyYW5zYWtzaSBwZXIga2F0ZWdvcmkgU0VCRUxVTSBjbGVhbmluZw0KZGF0YV9hd2FsX2thdGVnb3JpIDwtIGRhdGFfcGVuanVhbGFuICU+JQ0KICBncm91cF9ieShLYXRlZ29yaSkgJT4lDQogIHN1bW1hcmlzZShKdW1sYWggPSBuKCkpDQoNCnBsb3RfbHkoZGF0YV9hd2FsX2thdGVnb3JpLA0KICAgICAgICB4ID0gfkthdGVnb3JpLA0KICAgICAgICB5ID0gfkp1bWxhaCwNCiAgICAgICAgdHlwZSA9ICJiYXIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ2RhcmtvcmFuZ2UnKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICJKdW1sYWggVHJhbnNha3NpIHBlciBLYXRlZ29yaSAoU2ViZWx1bSBDbGVhbmluZykiLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkthdGVnb3JpIiksDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSnVtbGFoIFRyYW5zYWtzaSIpKQ0KYGBgDQoNCkdyYWZpayBpbmkgbWVudW5qdWtrYW4ganVtbGFoIHRyYW5zYWtzaSB1bnR1ayB0aWdhIGthdGVnb3JpOiBBa3Nlc29yaXMsIEVsZWt0cm9uaWssIGRhbiBGYXNoaW9uLCBzZWJlbHVtIGRhdGEgZGliZXJzaWhrYW4uDQoNCi0gQWtzZXNvcmlzOiA0MCB0cmFuc2Frc2kuDQotIEVsZWt0cm9uaWs6IDM3IHRyYW5zYWtzaS4NCi0gRmFzaGlvbjogMzQgdHJhbnNha3NpLg0KDQpTZWJlbHVtIGRhdGEgZGliZXJzaWhrYW4sIGthdGVnb3JpIEFrc2Vzb3JpcyBtZW1pbGlraSBqdW1sYWggdHJhbnNha3NpIHRlcnRpbmdnaSAoNDApLCBsYWx1IEVsZWt0cm9uaWsgKDM3KSBkYW4gRmFzaGlvbiAoMzQpLiBBbmdrYSBpbmkgbWVuY2VybWlua2FuIGRhdGEgbWVudGFoLCB5YW5nIG11bmdraW4gbWFzaWggbWVuY2FrdXAgdHJhbnNha3NpIHRpZGFrIHZhbGlkIHNlcGVydGkgZW50cmkgdGFucGEgcHJvZHVrIGF0YXUgZGF0YSBrb3NvbmcuIEphZGksIGp1bWxhaCB0cmFuc2Frc2kgaW5pIGJpc2EgbGViaWggdGluZ2dpIGRhcmkgeWFuZyBzZWhhcnVzbnlhIGthcmVuYSBiZWx1bSBkaWZpbHRlci4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCg0KIyMgMi4gQkFSIENIQVJUIERBVEEgU0VURUxBSCBDTEVBTklORyDigJQgSnVtbGFoIHRyYW5zYWtzaSBwZXIga2F0ZWdvcmkNCmRhdGFfYmVyc2loX2thdGVnb3JpIDwtIGRhdGFfYmVyc2loICU+JQ0KICBncm91cF9ieShLYXRlZ29yaSkgJT4lDQogIHN1bW1hcmlzZShKdW1sYWggPSBuKCkpDQoNCnBsb3RfbHkoZGF0YV9iZXJzaWhfa2F0ZWdvcmksDQogICAgICAgIHggPSB+S2F0ZWdvcmksDQogICAgICAgIHkgPSB+SnVtbGFoLA0KICAgICAgICB0eXBlID0gImJhciIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnc2VhZ3JlZW4nKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICJKdW1sYWggVHJhbnNha3NpIHBlciBLYXRlZ29yaSAoU2V0ZWxhaCBDbGVhbmluZykiLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkthdGVnb3JpIiksDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSnVtbGFoIFRyYW5zYWtzaSIpKQ0KYGBgDQoNCkdyYWZpayBpbmkgbWVudW5qdWtrYW4ganVtbGFoIHRyYW5zYWtzaSB1bnR1ayBrYXRlZ29yaSB5YW5nIHNhbWEgc2V0ZWxhaCBkYXRhIGRpYmVyc2loa2FuLg0KDQotIEFrc2Vzb3JpczogU2VraXRhciAzNSB0cmFuc2Frc2kuDQotIEVsZWt0cm9uaWs6IFNla2l0YXIgMzAgdHJhbnNha3NpLg0KLSBGYXNoaW9uOiBTZWtpdGFyIDI0IHRyYW5zYWtzaS4NCg0KU2V0ZWxhaCBwZW1iZXJzaWhhbiBkYXRhLCBqdW1sYWggdHJhbnNha3NpIGRpIHNlbXVhIGthdGVnb3JpIG1lbnVydW4ga2FyZW5hIHRyYW5zYWtzaSB0aWRhayB2YWxpZCBhdGF1IHRlbGFoIGRpaGFwdXMuIEFrc2Vzb3JpcyB0ZXRhcCBtZW1pbGlraSB0cmFuc2Frc2kgdGVyYmFueWFrIDM2LCB0ZXRhcGkgdHVydW4gZGFyaSA0MCwgRWxla3Ryb25payB0dXJ1biBkYXJpIDM3IGtlIGFuZ2thIDMwIGRhbiBGYXNoaW9uIG1hc2luZy1tYXNpbmcgdHVydW4gZGFyaSAzNCBtZW5qYWRpIDI0IHRyYW5zYWtzaS4gUGVudXJ1bmFuIGluaSBtZW51bmp1a2thbiBiYWh3YSBhZGEgdHJhbnNha3NpIHRpZGFrIHZhbGlkIHlhbmcgZGloYXB1cywgc2VoaW5nZ2EgZGF0YSBtZW5qYWRpIGxlYmloIGFrdXJhdCBkYW4gaGFueWEgbWVuY2VybWlua2FuIHRyYW5zYWtzaSB5YW5nIGJlbmFyLWJlbmFyIHZhbGlkLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkobHVicmlkYXRlKQ0KIyMgMy4gQkFSIENIQVJUIEhBU0lMIFRSQU5TRk9STUFTSSDigJQgVG90YWwgcGVuanVhbGFuIHBlciBrYXRlZ29yaQ0KcGVuanVhbGFuX3Blcl9rYXRlZ29yaSA8LSBkYXRhX2JlcnNpaCAlPiUNCiAgZ3JvdXBfYnkoS2F0ZWdvcmkpICU+JQ0KICBzdW1tYXJpc2UoVG90YWxfUGVuanVhbGFuID0gc3VtKFRvdGFsLCBuYS5ybSA9IFRSVUUpKQ0KDQpwbG90X2x5KHBlbmp1YWxhbl9wZXJfa2F0ZWdvcmksDQogICAgICAgIHggPSB+S2F0ZWdvcmksDQogICAgICAgIHkgPSB+VG90YWxfUGVuanVhbGFuLA0KICAgICAgICB0eXBlID0gImJhciIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnc3RlZWxibHVlJykpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiVG90YWwgUGVuanVhbGFuIHBlciBLYXRlZ29yaSAoVHJhbnNmb3JtYXNpKSIsDQogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiS2F0ZWdvcmkiKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJUb3RhbCBQZW5qdWFsYW4gKFJwKSIpKQ0KYGBgDQoNCkdyYWZpayBpbmkgbWVudW5qdWtrYW4gdG90YWwgcGVuanVhbGFuIChkYWxhbSBSdXBpYWgpIHVudHVrIHNldGlhcCBrYXRlZ29yaSBzZXRlbGFoIGRhdGEgZGliZXJzaWhrYW4gZGFuIGtvbG9tIFRvdGFsIGRpaGl0dW5nIHVsYW5nIChIYXJnYSDDlyBKdW1sYWgpLg0KDQotIEFrc2Vzb3JpczogU2VraXRhciBScDM1MCBqdXRhLg0KLSBFbGVrdHJvbmlrOiBTZWtpdGFyIFJwNDAwIGp1dGEuDQotIEZhc2hpb246IFNla2l0YXIgUnA0NTAganV0YS4NCg0KRmFzaGlvbiBtZW1pbGlraSB0b3RhbCBwZW5qdWFsYW4gdGVydGluZ2dpIChScDQ1MCBqdXRhKSwgZGlpa3V0aSBvbGVoIEVsZWt0cm9uaWsgKFJwNDAwIGp1dGEpLCBkYW4gQWtzZXNvcmlzIChScDM1MCBqdXRhKS4gTWVza2lwdW4gQWtzZXNvcmlzIG1lbWlsaWtpIGp1bWxhaCB0cmFuc2Frc2kgdGVyYmFueWFrICgzNSBzZXRlbGFoIGNsZWFuaW5nKSwgdG90YWwgcGVuanVhbGFubnlhIHBhbGluZyByZW5kYWguIEluaSBtZW51bmp1a2thbiBiYWh3YSBwcm9kdWsgQWtzZXNvcmlzIG11bmdraW4gbGViaWggbXVyYWggYXRhdSBkaWJlbGkgZGFsYW0ganVtbGFoIGtlY2lsIHBlciB0cmFuc2Frc2kuIFNlYmFsaWtueWEsIEZhc2hpb24gZGVuZ2FuIHRyYW5zYWtzaSBsZWJpaCBzZWRpa2l0ICgyNSkgbWVuZ2hhc2lsa2FuIHBlbmp1YWxhbiB0ZXJ0aW5nZ2ksIG1lbmdpbmRpa2FzaWthbiBiYWh3YSBwcm9kdWsgRmFzaGlvbiBjZW5kZXJ1bmcgbGViaWggbWFoYWwgYXRhdSBtZW1pbGlraSB2b2x1bWUgcGVuanVhbGFuIGxlYmloIGJlc2FyIHBlciB0cmFuc2Frc2kuIEVsZWt0cm9uaWsgYmVyYWRhIGRpIHRlbmdhaCwgZGVuZ2FuIHBlbmp1YWxhbiB5YW5nIGN1a3VwIHRpbmdnaSBtZXNraXB1biBqdW1sYWggdHJhbnNha3NpIHNhbWEgZGVuZ2FuIEZhc2hpb24uDQoNCg==