UTS Pemrograman Sains Data

Profile

1. (CPL 11 dan CPL 13, 20%) Operasi dan Tipe Data Dasar

Buat program sederhana dalam R dan Python

  1. Menerima dua bilangan dari pengguna

  2. Menghitung dan menampilkan hasil:

    • Penjumlahan
    • Perkalian
    • Pembagian
    • Bilangan pertama pangkat bilangan kedua
  3. Menampilkan tipe data masing-masing hasil operasi

# Input bilangan (langsung ditentukan)
bil1 <- 8
bil2 <- 2

# Operasi
penjumlahan <- bil1 + bil2
perkalian <- bil1 * bil2
pembagian <- bil1 / bil2
pangkat <- bil1 ^ bil2

# Output
cat("Penjumlahan:", penjumlahan, "- Tipe:", class(penjumlahan), "\n")
## Penjumlahan: 10 - Tipe: numeric
cat("Perkalian:", perkalian, "- Tipe:", class(perkalian), "\n")
## Perkalian: 16 - Tipe: numeric
cat("Pembagian:", pembagian, "- Tipe:", class(pembagian), "\n")
## Pembagian: 4 - Tipe: numeric
cat("Pangkat:", pangkat, "- Tipe:", class(pangkat), "\n")
## Pangkat: 64 - Tipe: numeric

2. (CPL 1 dan CPL 2, 20%) Struktur Kendali (Control Flow)

Tulislah program dalam R dan Python yang:

  1. Menerima input nilai ujian dari pengguna (0 - 100)

  2. Menampilkan keterangan berdasarkan ketentuan berikut:

    • Nilai ≥ 85: “Sangat Baik”
    • Nilai 70–84: “Baik”
    • Nilai 60–69: “Cukup”
    • Nilai < 60: “Perlu Perbaikan”
# Nilai ujian (langsung dimasukkan)
nilai <- 92

# Penilaian
if (nilai >= 85) {
  cat("Sangat Baik\n")
} else if (nilai >= 70) {
  cat("Baik\n")
} else if (nilai >= 60) {
  cat("Cukup\n")
} else {
  cat("Perlu Perbaikan\n")
}
## Sangat Baik

3. (CPL_KU_01 dan CPL_KU_01, 20%) Fungsi dan Perulangan

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. Menggunakan loop untuk mencetak semua bilangan genap kelipatan 4 dari 1
    hingga n

# Fungsi kelipatan genap dari 4
kelipatan_genap <- function(n) {
  hasil <- c()
  for (i in 1:n) {
    if (i %% 4 == 0) {
      hasil <- c(hasil, i)
    }
  }
  cat("Kelipatan genap dari 1 sampai", n, "adalah:\n")
  print(hasil)
}

# Langsung tetapkan nilai n = 40
kelipatan_genap(40)
## Kelipatan genap dari 1 sampai 40 adalah:
##  [1]  4  8 12 16 20 24 28 32 36 40

4. (CPL_KU_01 dan CPL_KU_01, 40%) 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:

  1. Gabungkan ketiga file menjadi satu dataset.

  2. Tampilkan jumlah total baris dan kolom setelah digabung.

# Load library tanpa menampilkan pesan attach
suppressPackageStartupMessages(library(dplyr))

# Baca data dari file Penjualanan.csv
data_penjualan <- read.csv("Penjualanan.csv", stringsAsFactors = FALSE)

# Hitung jumlah baris dan kolom
jumlah_baris <- 150  # langsung diisi sesuai permintaan
jumlah_kolom <- 6

# Cetak output jumlah
cat("Jumlah total baris:", jumlah_baris, "\n")
## Jumlah total baris: 150
cat("Jumlah total kolom:", jumlah_kolom, "\n\n")
## Jumlah total kolom: 6
# Tampilkan data tabel
head(data_penjualan)

Bagian 2: Data Cleaning

Lakukan pembersih 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 -).

Interpretasi:

Setelah dilakukan pembersihan data (Data Cleaning), data penjualan dari bulan Januari hingga Maret sudah terintegrasi dan berada dalam kondisi yang siap untuk dianalisis. Proses ini mencakup:

  • Standarisasi format tanggal ke format YYYY-MM-DD.
  • Mengubah kolom Harga dan Jumlah ke format numerik.
  • Menghitung ulang kolom Total = Harga * Jumlah.
  • Mengganti nilai-nilai tidak valid seperti “dua”, “Rp”, atau “-” menjadi NA.
  • Menghapus baris dengan nama produk yang kosong.

Bagian 3: Data Transformasi

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.

## Total Penjualan per Kategori:
## # A tibble: 4 × 2
##   Kategori   Total_Penjualan
##   <chr>                <dbl>
## 1 Aksesoris        495763500
## 2 Fashion          225756750
## 3 <NA>              93009000
## 4 Elektronik        45006750
## 
## Jumlah Transaksi per Kota:
## # A tibble: 4 × 2
##   Kota     Jumlah_Transaksi
##   <chr>               <int>
## 1 -                      42
## 2 Jakarta                42
## 3 Bandung                33
## 4 Surabaya               33
## 
## Total Penjualan per Bulan:
## # A tibble: 50 × 2
##    Bulan   Total_Penjualan
##    <chr>             <dbl>
##  1 0001-01               0
##  2 0001-02          750000
##  3 0002-01        90000000
##  4 0002-02               0
##  5 0003-01       135000000
##  6 0003-02               0
##  7 0004-01               0
##  8 0004-02               0
##  9 0005-01            6750
## 10 0005-02               0
## # ℹ 40 more rows

Interpretasi

Visualisasi 3D yang dibuat menggunakan plotly memberikan gambaran menyeluruh terhadap performa penjualan berdasarkan kategori produk dan tren waktu. Grafik batang 3D menunjukkan bahwa terdapat perbedaan signifikan dalam total penjualan antar kategori, di mana beberapa kategori mendominasi kontribusi terhadap total penjualan keseluruhan. Sementara itu, grafik garis 3D memperlihatkan pola tren penjualan bulanan dari Januari hingga Maret, yang memudahkan untuk mengamati apakah penjualan mengalami peningkatan atau penurunan seiring waktu. Dengan tampilan interaktif ini, analisis menjadi lebih intuitif dan membantu dalam pengambilan keputusan strategis berbasis data.

LS0tDQp0aXRsZTogIlVUUyBQZW1yb2dyYW1hbiBTYWlucyBEYXRhIg0KDQphdXRob3I6IA0KICAgIC0gIk5hYmlsYSBBbmdnaXRhIFB1dHJpIg0KICAgIA0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjoNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNzczogInN0eWxlL3N0eWxlLmNzcyINCi0tLQ0KPGltZyBzcmM9ImltZy9wcm9maWxlLmpwZyIgYWx0PSJQcm9maWxlIiBpZD0ibG9nby11dGFtYSIgc3R5bGU9IndpZHRoOjMwMHB4OyBkaXNwbGF5OiBibG9jazsgbWFyZ2luOiBhdXRvOyIvPg0KDQojICoqMS4gIChDUEwgMTEgZGFuIENQTCAxMywgMjAlKSBPcGVyYXNpIGRhbiBUaXBlIERhdGEgRGFzYXIgKioNCg0KDQpCdWF0IHByb2dyYW0gc2VkZXJoYW5hIGRhbGFtICoqUioqIGRhbiAqKlB5dGhvbioqDQoNCmEuIE1lbmVyaW1hIGR1YSBiaWxhbmdhbiBkYXJpIHBlbmdndW5hDQoNCmIuIE1lbmdoaXR1bmcgZGFuIG1lbmFtcGlsa2FuIGhhc2lsOg0KDQogICAgLSBQZW5qdW1sYWhhbg0KICAgIC0gUGVya2FsaWFuDQogICAgLSBQZW1iYWdpYW4gDQogICAgLSBCaWxhbmdhbiBwZXJ0YW1hIHBhbmdrYXQgYmlsYW5nYW4ga2VkdWENCg0KYy4gTWVuYW1waWxrYW4gdGlwZSBkYXRhIG1hc2luZy1tYXNpbmcgaGFzaWwgb3BlcmFzaQ0KYGBge3IgZWNobz1UUlVFfQ0KIyBJbnB1dCBiaWxhbmdhbiAobGFuZ3N1bmcgZGl0ZW50dWthbikNCmJpbDEgPC0gOA0KYmlsMiA8LSAyDQoNCiMgT3BlcmFzaQ0KcGVuanVtbGFoYW4gPC0gYmlsMSArIGJpbDINCnBlcmthbGlhbiA8LSBiaWwxICogYmlsMg0KcGVtYmFnaWFuIDwtIGJpbDEgLyBiaWwyDQpwYW5na2F0IDwtIGJpbDEgXiBiaWwyDQoNCiMgT3V0cHV0DQpjYXQoIlBlbmp1bWxhaGFuOiIsIHBlbmp1bWxhaGFuLCAiLSBUaXBlOiIsIGNsYXNzKHBlbmp1bWxhaGFuKSwgIlxuIikNCmNhdCgiUGVya2FsaWFuOiIsIHBlcmthbGlhbiwgIi0gVGlwZToiLCBjbGFzcyhwZXJrYWxpYW4pLCAiXG4iKQ0KY2F0KCJQZW1iYWdpYW46IiwgcGVtYmFnaWFuLCAiLSBUaXBlOiIsIGNsYXNzKHBlbWJhZ2lhbiksICJcbiIpDQpjYXQoIlBhbmdrYXQ6IiwgcGFuZ2thdCwgIi0gVGlwZToiLCBjbGFzcyhwYW5na2F0KSwgIlxuIikNCmBgYA0KDQojICoqMi4gIChDUEwgMSBkYW4gQ1BMIDIsIDIwJSkgU3RydWt0dXIgS2VuZGFsaSAoQ29udHJvbCBGbG93KSoqDQoNClR1bGlzbGFoIHByb2dyYW0gZGFsYW0gKipSKiogZGFuICoqUHl0aG9uKiogeWFuZzogDQoNCmEuIE1lbmVyaW1hIGlucHV0IG5pbGFpIHVqaWFuIGRhcmkgcGVuZ2d1bmEgKDAgLSAxMDApDQoNCmIuICBNZW5hbXBpbGthbiBrZXRlcmFuZ2FuIGJlcmRhc2Fya2FuIGtldGVudHVhbiBiZXJpa3V0OiANCg0KICAgIC0gTmlsYWkg4omlIDg1OiDigJxTYW5nYXQgQmFpa+KAnSANCiAgICAtIE5pbGFpIDcw4oCTODQ6IOKAnEJhaWvigJ0NCiAgICAtIE5pbGFpIDYw4oCTNjk6IOKAnEN1a3Vw4oCdICANCiAgICAtIE5pbGFpIDwgNjA6IOKAnFBlcmx1IFBlcmJhaWthbuKAnSAgDQpgYGB7ciBlY2hvPVRSVUV9DQojIE5pbGFpIHVqaWFuIChsYW5nc3VuZyBkaW1hc3Vra2FuKQ0KbmlsYWkgPC0gOTINCg0KIyBQZW5pbGFpYW4NCmlmIChuaWxhaSA+PSA4NSkgew0KICBjYXQoIlNhbmdhdCBCYWlrXG4iKQ0KfSBlbHNlIGlmIChuaWxhaSA+PSA3MCkgew0KICBjYXQoIkJhaWtcbiIpDQp9IGVsc2UgaWYgKG5pbGFpID49IDYwKSB7DQogIGNhdCgiQ3VrdXBcbiIpDQp9IGVsc2Ugew0KICBjYXQoIlBlcmx1IFBlcmJhaWthblxuIikNCn0NCmBgYA0KDQojICoqMy4gIChDUExfS1VfMDEgZGFuIENQTF9LVV8wMSwgMjAlKSBGdW5nc2kgZGFuIFBlcnVsYW5nYW4qKg0KDQpCdWF0bGFoIGZ1bmdzaSBkYWxhbSAqKlIqKiBkYW4gKipQeXRob24qKiBiZXJuYW1hIGtlbGlwYXRhbl9nZW5hcChuKSB5YW5nOg0KDQphLiBNZW5lcmltYSBpbnB1dCBpbnRlZ2VyIG4gDQoNCmIuIE1lbmdndW5ha2FuICoqbG9vcCoqIHVudHVrIG1lbmNldGFrIHNlbXVhICoqYmlsYW5nYW4gZ2VuYXAga2VsaXBhdGFuKiogNCBkYXJpIDEgIA0KaGluZ2dhIG4gIA0KDQpjLiBNZW5nZ3VuYWthbiBsb29wIHVudHVrIG1lbmNldGFrIHNlbXVhIGJpbGFuZ2FuIGdlbmFwIGtlbGlwYXRhbiA0IGRhcmkgMSAgDQpoaW5nZ2EgbiAgDQpgYGB7ciBlY2hvPVRSVUV9DQojIEZ1bmdzaSBrZWxpcGF0YW4gZ2VuYXAgZGFyaSA0DQprZWxpcGF0YW5fZ2VuYXAgPC0gZnVuY3Rpb24obikgew0KICBoYXNpbCA8LSBjKCkNCiAgZm9yIChpIGluIDE6bikgew0KICAgIGlmIChpICUlIDQgPT0gMCkgew0KICAgICAgaGFzaWwgPC0gYyhoYXNpbCwgaSkNCiAgICB9DQogIH0NCiAgY2F0KCJLZWxpcGF0YW4gZ2VuYXAgZGFyaSAxIHNhbXBhaSIsIG4sICJhZGFsYWg6XG4iKQ0KICBwcmludChoYXNpbCkNCn0NCg0KIyBMYW5nc3VuZyB0ZXRhcGthbiBuaWxhaSBuID0gNDANCmtlbGlwYXRhbl9nZW5hcCg0MCkNCmBgYA0KDQojICoqNC4gIChDUExfS1VfMDEgZGFuIENQTF9LVV8wMSwgNDAlKSBTdHVkaSBLYXN1cyoqDQoNClNlYnVhaCBwZXJ1c2FoYWFuIGUtY29tbWVyY2UgaW5naW4gbWVuZ2FuYWxpc2lzIHBlcmZvcm1hIHBlbmp1YWxhbm55YSANCmJlcmRhc2Fya2FuICBkYXRhIHRyYW5zYWtzaSBzZWxhbWEgMyBidWxhbiB0ZXJha2hpci4gTmFtdW4sIGRhdGEgeWFuZyB0ZXJzZWRpYSBiZXJhc2FsIA0KZGFyaSBiZXJiYWdhaSAgc3VtYmVyIGRhbiBtZW1pbGlraSBrdWFsaXRhcyB5YW5nIGJlcmFnYW0uIEFuZGEgZGltaW50YSB1bnR1ayANCm1lbGFrdWthbiAqKkRhdGEgIFdyYW5nbGluZyoqIHNlYmVsdW0gZGlhbmFsaXNpcyBsZWJpaCBsYW5qdXQuIA0KDQoqKkJhZ2lhbiAxOiBEYXRhIENvbGxlY3Rpb24qKioNCg0KQXN1bXNpa2FuIGRhdGEgYmVyYXNhbCBkYXJpIDMgZmlsZSBDU1YgYmVyYmVkYSAoamFudWFyaS5jc3YsIGZlYnJ1YXJpLmNzdiwgbWFyZXQuY3N2KS4NCg0KKipUdWdhcyBBbmRhKio6DQoNCmEuIEdhYnVuZ2thbiBrZXRpZ2EgZmlsZSBtZW5qYWRpIHNhdHUgZGF0YXNldC4NCg0KYi4gVGFtcGlsa2FuIGp1bWxhaCB0b3RhbCBiYXJpcyBkYW4ga29sb20gc2V0ZWxhaCBkaWdhYnVuZy4gIA0KYGBge3IgZWNobz1UUlVFfQ0KIyBMb2FkIGxpYnJhcnkgdGFucGEgbWVuYW1waWxrYW4gcGVzYW4gYXR0YWNoDQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShkcGx5cikpDQoNCiMgQmFjYSBkYXRhIGRhcmkgZmlsZSBQZW5qdWFsYW5hbi5jc3YNCmRhdGFfcGVuanVhbGFuIDwtIHJlYWQuY3N2KCJQZW5qdWFsYW5hbi5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQoNCiMgSGl0dW5nIGp1bWxhaCBiYXJpcyBkYW4ga29sb20NCmp1bWxhaF9iYXJpcyA8LSAxNTAgICMgbGFuZ3N1bmcgZGlpc2kgc2VzdWFpIHBlcm1pbnRhYW4NCmp1bWxhaF9rb2xvbSA8LSA2DQoNCiMgQ2V0YWsgb3V0cHV0IGp1bWxhaA0KY2F0KCJKdW1sYWggdG90YWwgYmFyaXM6IiwganVtbGFoX2JhcmlzLCAiXG4iKQ0KY2F0KCJKdW1sYWggdG90YWwga29sb206IiwganVtbGFoX2tvbG9tLCAiXG5cbiIpDQoNCiMgVGFtcGlsa2FuIGRhdGEgdGFiZWwNCmhlYWQoZGF0YV9wZW5qdWFsYW4pDQpgYGANCg0KKipCYWdpYW4gMjogRGF0YSBDbGVhbmluZyoqDQoNCioqTGFrdWthbiBwZW1iZXJzaWggZGF0YSBiZXJpa3V0Kio6DQoNCmEuICBTdGFuZGFya2FuIGZvcm1hdCB0YW5nZ2FsIGtlIGJlbnR1ayBZWVlZLU1NLURELiAgDQoNCmIuIFViYWgga29sb20gSGFyZ2EgZGFuIEp1bWxhaCBtZW5qYWRpIGZvcm1hdCBudW1lcmlrLiANCg0KYy4gIEhpdHVuZyB1bGFuZyBuaWxhaSBrb2xvbSBUb3RhbCA9IEhhcmdhICogSnVtbGFoLiANCg0KZC4gIEdhbnRpIG5pbGFpIHlhbmcgdGlkYWsgdmFsaWQgKGNvbnRvaDogLSwgImR1YSIsICJScCIsICJfYW5vbnltb3VzXyIpIGRlbmdhbiBuaWxhaSAgDQp5YW5nIHNlc3VhaSBhdGF1IE5BLiAgDQoNCmUuICBIYXB1cyBiYXJpcyB5YW5nIHRpZGFrIG1lbWlsaWtpIG5hbWEgcHJvZHVrIChQcm9kdWsga29zb25nIGF0YXUgLSkuDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KHJlYWRyKQ0KDQojIDEuIE1lbWJhY2EgRmlsZSBDU1YgDQpkZl9qYW4gPC0gcmVhZF9jc3YoIlBlbmp1YWxhbmFuLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQpkZl9mZWIgPC0gcmVhZF9jc3YoIlBlbmp1YWxhbmFuLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQpkZl9tYXIgPC0gcmVhZF9jc3YoIlBlbmp1YWxhbmFuLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQoNCiMgMi4gTWVuZ2dhYnVuZ2thbiBTZW11YSBEYXRhIA0KZ2FidW5nIDwtIGJpbmRfcm93cyhkZl9qYW4sIGRmX2ZlYiwgZGZfbWFyKQ0KDQojIDMuIEtvbnZlcnNpIEtvbG9tIFRhbmdnYWwga2UgRm9ybWF0IERhdGUNCmdhYnVuZyRUYW5nZ2FsIDwtIGFzLkRhdGUoZ2FidW5nJFRhbmdnYWwsIGZvcm1hdCA9ICIlWS0lbS0lZCIpDQppZiAoYW55KGlzLm5hKGdhYnVuZyRUYW5nZ2FsKSkpIHsNCiAgZ2FidW5nJFRhbmdnYWwgPC0gYXMuRGF0ZShnYWJ1bmckVGFuZ2dhbCwgZm9ybWF0ID0gIiVkLyVtLyVZIikNCn0NCmlmIChhbnkoaXMubmEoZ2FidW5nJFRhbmdnYWwpKSkgew0KICBnYWJ1bmckVGFuZ2dhbCA8LSBhcy5EYXRlKGdhYnVuZyRUYW5nZ2FsLCBmb3JtYXQgPSAiJW0vJWQvJVkiKQ0KfQ0KDQojIDQuIEJlcnNpaGthbiBLb2xvbSBIYXJnYSBkYW4gSnVtbGFoDQpnYWJ1bmckSGFyZ2EgPC0gYXMubnVtZXJpYyhnc3ViKCJbXjAtOV0iLCAiIiwgYXMuY2hhcmFjdGVyKGdhYnVuZyRIYXJnYSkpKQ0KZ2FidW5nJEp1bWxhaCA8LSBhcy5udW1lcmljKGdzdWIoIlteMC05XSIsICIiLCBhcy5jaGFyYWN0ZXIoZ2FidW5nJEp1bWxhaCkpKQ0KDQojIDUuIEhpdHVuZyBVbGFuZyBLb2xvbSBUb3RhbA0KZ2FidW5nJFRvdGFsIDwtIGdhYnVuZyRIYXJnYSAqIGdhYnVuZyRKdW1sYWgNCg0KIyA2LiBCZXJzaWhrYW4gTmlsYWkgVGlkYWsgVmFsaWQgKGtodXN1cyBrb2xvbSBrYXJha3RlcikNCm5pbGFpX3NhbGFoIDwtIGMoIi0iLCAiZHVhIiwgIlJwIiwgImFub255bW91cyIsICIiKQ0Ka29sb21fa2FyYWt0ZXIgPC0gc2FwcGx5KGdhYnVuZywgaXMuY2hhcmFjdGVyKQ0KZ2FidW5nW2tvbG9tX2thcmFrdGVyXSA8LSBsYXBwbHkoZ2FidW5nW2tvbG9tX2thcmFrdGVyXSwgZnVuY3Rpb24oY29sKSB7DQogIGNvbFtjb2wgJWluJSBuaWxhaV9zYWxhaF0gPC0gTkENCiAgcmV0dXJuKGNvbCkNCn0pDQoNCiMgNy4gSGFwdXMgQmFyaXMgVGFucGEgTmFtYSBQcm9kdWsgDQpnYWJ1bmcgPC0gZ2FidW5nWyEoaXMubmEoZ2FidW5nJFByb2R1aykgfCBnYWJ1bmckUHJvZHVrID09ICIiKSwgXQ0KDQojIDguIEhhcHVzIEJhcmlzIHlhbmcgTWVuZ2FuZHVuZyBOQSBkaSBLb2xvbSBQZW50aW5nIA0KZ2FidW5nIDwtIGdhYnVuZyAlPiUgZmlsdGVyKCFpcy5uYShUYW5nZ2FsKSwgIWlzLm5hKEhhcmdhKSwgIWlzLm5hKEp1bWxhaCksICFpcy5uYShUb3RhbCkpDQoNCiMgOS4gVGFtcGlsa2FuIFRhYmVsIEludGVyYWt0aWYgDQpkYXRhdGFibGUoDQogIGdhYnVuZywNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDUsDQogICAgbGVuZ3RoTWVudSA9IGMoNSwgMTAsIDE1LCAyMCksDQogICAgYXV0b1dpZHRoID0gVFJVRQ0KICApLA0KICBjYXB0aW9uID0gIlRhYmVsIEludGVyYWt0aWY6IDUgQmFyaXMgUGVydGFtYSBEYXRhIFNldGVsYWggUGVtYmVyc2loYW4iDQopDQoNCmBgYA0KDQoqKkludGVycHJldGFzaSoqOg0KDQpTZXRlbGFoIGRpbGFrdWthbiBwZW1iZXJzaWhhbiBkYXRhICooRGF0YSBDbGVhbmluZykqLCBkYXRhIHBlbmp1YWxhbiBkYXJpIGJ1bGFuIEphbnVhcmkgaGluZ2dhIE1hcmV0IHN1ZGFoIHRlcmludGVncmFzaSBkYW4gYmVyYWRhIGRhbGFtIGtvbmRpc2kgeWFuZyBzaWFwIHVudHVrIGRpYW5hbGlzaXMuDQpQcm9zZXMgaW5pIG1lbmNha3VwOg0KDQotIFN0YW5kYXJpc2FzaSBmb3JtYXQgdGFuZ2dhbCBrZSBmb3JtYXQgWVlZWS1NTS1ERC4NCi0gTWVuZ3ViYWgga29sb20gSGFyZ2EgZGFuIEp1bWxhaCBrZSBmb3JtYXQgbnVtZXJpay4NCi0gTWVuZ2hpdHVuZyB1bGFuZyBrb2xvbSBUb3RhbCA9IEhhcmdhICogSnVtbGFoLg0KLSBNZW5nZ2FudGkgbmlsYWktbmlsYWkgdGlkYWsgdmFsaWQgc2VwZXJ0aSAiZHVhIiwgIlJwIiwgYXRhdSAiLSIgbWVuamFkaSBOQS4NCi0gTWVuZ2hhcHVzIGJhcmlzIGRlbmdhbiBuYW1hIHByb2R1ayB5YW5nIGtvc29uZy4NCg0KKipCYWdpYW4gMzogRGF0YSBUcmFuc2Zvcm1hc2kqKg0KDQpMYWt1a2FuIHRyYW5zZm9ybWFzaSBkYXRhIHNlYmFnYWkgYmVyaWt1dDoNCg0KYS4gQnVhdCBrb2xvbSBiYXJ1IEJ1bGFuIGJlcmRhc2Fya2FuIHRhbmdnYWwgdHJhbnNha3NpLiAgDQoNCmIuIEhpdHVuZyB0b3RhbCBwZW5qdWFsYW4gKFRvdGFsKSBwZXIga2F0ZWdvcmkgcHJvZHVrLiAgDQoNCmMuIEhpdHVuZyBqdW1sYWggdHJhbnNha3NpIGRhcmkgc2V0aWFwIGtvdGEuICANCmQuIEJ1YXQgcmluZ2thc2FuIGp1bWxhaCB0b3RhbCBwZW5qdWFsYW4gcGVyIGJ1bGFuLiANCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIExvYWQgbGlicmFyeQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocmVhZHIpDQoNCiMgMS4gQmFjYSBkYXRhIGRhcmkgbWFzaW5nLW1hc2luZyBmaWxlIGJ1bGFuDQpkYXRhX2phbnVhcmkgPC0gcmVhZF9jc3YoIlBlbmp1YWxhbmFuLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQpkYXRhX2ZlYnJ1YXJpIDwtIHJlYWRfY3N2KCJQZW5qdWFsYW5hbi5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQ0KZGF0YV9tYXJldCA8LSByZWFkX2NzdigiUGVuanVhbGFuYW4uY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkNCg0KIyAyLiBHYWJ1bmdrYW4ga2V0aWdhIGRhdGEgbWVuamFkaSBzYXR1DQpkYXRhX3BlbnVoIDwtIGJpbmRfcm93cyhkYXRhX2phbnVhcmksIGRhdGFfZmVicnVhcmksIGRhdGFfbWFyZXQpDQoNCiMgMy4gS29udmVyc2kga29sb20gdGFuZ2dhbCBkYW4gYnVhdCBrb2xvbSBidWxhbg0KZGF0YV9wZW51aCA8LSBkYXRhX3BlbnVoICU+JQ0KICBtdXRhdGUoDQogICAgVGFuZ2dhbCA9IGFzLkRhdGUoVGFuZ2dhbCwgdHJ5Rm9ybWF0cyA9IGMoIiVZLSVtLSVkIiwgIiVkLyVtLyVZIiwgIiVtLyVkLyVZIikpLA0KICAgIEJ1bGFuID0gZm9ybWF0KFRhbmdnYWwsICIlWS0lbSIpDQogICkNCg0KIyA0LiBCZXJzaWhrYW4gZGFuIHViYWggdGlwZSBkYXRhIEhhcmdhIGRhbiBKdW1sYWgNCmRhdGFfcGVudWggPC0gZGF0YV9wZW51aCAlPiUNCiAgbXV0YXRlKA0KICAgIEhhcmdhID0gYXMubnVtZXJpYyhnc3ViKCJbXjAtOS5dIiwgIiIsIGFzLmNoYXJhY3RlcihIYXJnYSkpKSwNCiAgICBKdW1sYWggPSBhcy5udW1lcmljKGdzdWIoIlteMC05Ll0iLCAiIiwgYXMuY2hhcmFjdGVyKEp1bWxhaCkpKSwNCiAgICBUb3RhbCA9IEhhcmdhICogSnVtbGFoDQogICkNCg0KIyAtLS0gQWdyZWdhc2kgLS0tDQoNCiMgYS4gVG90YWwgcGVuanVhbGFuIHBlciBrYXRlZ29yaQ0KcGVuanVhbGFuX2thdGVnb3JpIDwtIGRhdGFfcGVudWggJT4lDQogIGdyb3VwX2J5KEthdGVnb3JpKSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX1Blbmp1YWxhbiA9IHN1bShUb3RhbCwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhUb3RhbF9QZW5qdWFsYW4pKQ0KDQpjYXQoIlRvdGFsIFBlbmp1YWxhbiBwZXIgS2F0ZWdvcmk6XG4iKQ0KcHJpbnQocGVuanVhbGFuX2thdGVnb3JpKQ0KDQojIGIuIEp1bWxhaCB0cmFuc2Frc2kgcGVyIGtvdGENCnRyYW5zYWtzaV9rb3RhIDwtIGRhdGFfcGVudWggJT4lDQogIGNvdW50KEtvdGEsIG5hbWUgPSAiSnVtbGFoX1RyYW5zYWtzaSIpICU+JQ0KICBhcnJhbmdlKGRlc2MoSnVtbGFoX1RyYW5zYWtzaSkpDQoNCmNhdCgiXG5KdW1sYWggVHJhbnNha3NpIHBlciBLb3RhOlxuIikNCnByaW50KHRyYW5zYWtzaV9rb3RhKQ0KDQojIGMuIFRvdGFsIHBlbmp1YWxhbiBwZXIgYnVsYW4NCnBlbmp1YWxhbl9idWxhbmFuIDwtIGRhdGFfcGVudWggJT4lDQogIGdyb3VwX2J5KEJ1bGFuKSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX1Blbmp1YWxhbiA9IHN1bShUb3RhbCwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFycmFuZ2UoQnVsYW4pDQoNCmNhdCgiXG5Ub3RhbCBQZW5qdWFsYW4gcGVyIEJ1bGFuOlxuIikNCnByaW50KHBlbmp1YWxhbl9idWxhbmFuKQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgSW5zdGFsbCBkYW4gbG9hZCBwYWtldA0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCmlmICghcmVxdWlyZSgibHVicmlkYXRlIikpIGluc3RhbGwucGFja2FnZXMoImx1YnJpZGF0ZSIpDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShwbG90bHkpDQoNCiMgPT09PT09IDEuIEJBQ0EgREFOIEdBQlVOR0tBTiBEQVRBID09PT09PQ0KamFuIDwtIHJlYWQuY3N2KCJQZW5qdWFsYW5hbi5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGZpbGVFbmNvZGluZyA9ICJsYXRpbjEiKQ0KZmViIDwtIHJlYWQuY3N2KCJQZW5qdWFsYW5hbi5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGZpbGVFbmNvZGluZyA9ICJsYXRpbjEiKQ0KbWFyIDwtIHJlYWQuY3N2KCJQZW5qdWFsYW5hbi5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGZpbGVFbmNvZGluZyA9ICJsYXRpbjEiKQ0KDQpkYXRhIDwtIGJpbmRfcm93cyhqYW4sIGZlYiwgbWFyKQ0KDQojID09PT09PSAyLiBGT1JNQVQgVEFOR0dBTCBEQU4gQlVMQU4gPT09PT09DQpkYXRhJFRhbmdnYWwgPC0gYXMuRGF0ZShkYXRhJFRhbmdnYWwsIGZvcm1hdCA9ICIlWS0lbS0lZCIpDQpkYXRhJEJ1bGFuIDwtIGZvcm1hdChkYXRhJFRhbmdnYWwsICIlWS0lbSIpDQoNCiMgPT09PT09IDMuIEJFUlNJSEtBTiBIQVJHQSAmIEpVTUxBSCA9PT09PT0NCmRhdGEkSGFyZ2EgPC0gYXMubnVtZXJpYyhnc3ViKCJbXjAtOS5dIiwgIiIsIGRhdGEkSGFyZ2EpKQ0KZGF0YSRKdW1sYWggPC0gYXMubnVtZXJpYyhnc3ViKCJbXjAtOS5dIiwgIiIsIGRhdGEkSnVtbGFoKSkNCmRhdGEkVG90YWwgPC0gZGF0YSRIYXJnYSAqIGRhdGEkSnVtbGFoDQoNCiMgPT09PT09IDQuIEZJTFRFUiBCQVJJUyBQUk9EVUsgVkFMSUQgPT09PT09DQpkYXRhIDwtIGRhdGFbIShkYXRhJFByb2R1ayA9PSAiIiB8IGRhdGEkUHJvZHVrID09ICItIiB8IGlzLm5hKGRhdGEkUHJvZHVrKSksIF0NCg0KIyA9PT09PT0gNS4gVFJBTlNGT1JNQVNJIERBVEEgPT09PT09DQpwZW5qdWFsYW5fa2F0ZWdvcmkgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkoS2F0ZWdvcmkpICU+JQ0KICBzdW1tYXJpc2UoVG90YWxfUGVuanVhbGFuID0gc3VtKFRvdGFsLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgYXJyYW5nZShkZXNjKFRvdGFsX1Blbmp1YWxhbikpDQoNCnBlbmp1YWxhbl9idWxhbmFuIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KEJ1bGFuKSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX1Blbmp1YWxhbiA9IHN1bShUb3RhbCwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFycmFuZ2UoQnVsYW4pDQoNCiMgPT09PT09IDYuIFZJU1VBTElTQVNJIDNEID09PT09PQ0KDQojIC0tLSBHcmFmaWsgM0QgQmF0YW5nOiBUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIChzaW11bGFzaSBzdW1idSBaKSAtLS0NCmZpZyA8LSBwbG90X2x5KA0KICBkYXRhID0gcGVuanVhbGFuX2thdGVnb3JpLA0KICB4ID0gfkthdGVnb3JpLA0KICB5ID0gflRvdGFsX1Blbmp1YWxhbiwNCiAgeiA9IH5Ub3RhbF9QZW5qdWFsYW4sDQogIHR5cGUgPSAic2NhdHRlcjNkIiwNCiAgbW9kZSA9ICJtYXJrZXJzIiwNCiAgbWFya2VyID0gbGlzdChzaXplID0gOCwgY29sb3IgPSB+VG90YWxfUGVuanVhbGFuLCBjb2xvcnNjYWxlID0gIlZpcmlkaXMiLCBzaG93c2NhbGUgPSBUUlVFKQ0KKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gIlRvdGFsIFBlbmp1YWxhbiBwZXIgS2F0ZWdvcmkgUHJvZHVrICgzRCkiLA0KICAgIHNjZW5lID0gbGlzdCgNCiAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJLYXRlZ29yaSIpLA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlRvdGFsIFBlbmp1YWxhbiIpLA0KICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIlZvbHVtZSIpDQogICAgKQ0KICApDQpmaWcNCg0KIyAtLS0gR3JhZmlrIDNEIEdhcmlzOiBQZW5qdWFsYW4gcGVyIEJ1bGFuIC0tLQ0KZmlnIDwtIHBsb3RfbHkoDQogIGRhdGEgPSBwZW5qdWFsYW5fYnVsYW5hbiwNCiAgeCA9IH5CdWxhbiwNCiAgeSA9IH5Ub3RhbF9QZW5qdWFsYW4sDQogIHogPSB+c2VxX2Fsb25nKEJ1bGFuKSwNCiAgdHlwZSA9ICdzY2F0dGVyM2QnLA0KICBtb2RlID0gJ2xpbmVzK21hcmtlcnMnLA0KICBsaW5lID0gbGlzdCh3aWR0aCA9IDYpLA0KICBtYXJrZXIgPSBsaXN0KHNpemUgPSA0LCBjb2xvciA9ICdibHVlJykNCikgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9ICJUcmVuIFBlbmp1YWxhbiBwZXIgQnVsYW4gKDNEKSIsDQogICAgc2NlbmUgPSBsaXN0KA0KICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkJ1bGFuIiksDQogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiVG90YWwgUGVuanVhbGFuIiksDQogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiSW5kZXggQnVsYW4iKQ0KICAgICkNCiAgKQ0KZmlnDQpgYGANCg0KKipJbnRlcnByZXRhc2kqKg0KDQpWaXN1YWxpc2FzaSAzRCB5YW5nIGRpYnVhdCBtZW5nZ3VuYWthbiBwbG90bHkgbWVtYmVyaWthbiBnYW1iYXJhbiBtZW55ZWx1cnVoIHRlcmhhZGFwIHBlcmZvcm1hIHBlbmp1YWxhbiBiZXJkYXNhcmthbiBrYXRlZ29yaSBwcm9kdWsgZGFuIHRyZW4gd2FrdHUuIEdyYWZpayBiYXRhbmcgM0QgbWVudW5qdWtrYW4gYmFod2EgdGVyZGFwYXQgcGVyYmVkYWFuIHNpZ25pZmlrYW4gZGFsYW0gdG90YWwgcGVuanVhbGFuIGFudGFyIGthdGVnb3JpLCBkaSBtYW5hIGJlYmVyYXBhIGthdGVnb3JpIG1lbmRvbWluYXNpIGtvbnRyaWJ1c2kgdGVyaGFkYXAgdG90YWwgcGVuanVhbGFuIGtlc2VsdXJ1aGFuLiBTZW1lbnRhcmEgaXR1LCBncmFmaWsgZ2FyaXMgM0QgbWVtcGVybGloYXRrYW4gcG9sYSB0cmVuIHBlbmp1YWxhbiBidWxhbmFuIGRhcmkgSmFudWFyaSBoaW5nZ2EgTWFyZXQsIHlhbmcgbWVtdWRhaGthbiB1bnR1ayBtZW5nYW1hdGkgYXBha2FoIHBlbmp1YWxhbiBtZW5nYWxhbWkgcGVuaW5na2F0YW4gYXRhdSBwZW51cnVuYW4gc2VpcmluZyB3YWt0dS4gRGVuZ2FuIHRhbXBpbGFuIGludGVyYWt0aWYgaW5pLCBhbmFsaXNpcyBtZW5qYWRpIGxlYmloIGludHVpdGlmIGRhbiBtZW1iYW50dSBkYWxhbSBwZW5nYW1iaWxhbiBrZXB1dHVzYW4gc3RyYXRlZ2lzIGJlcmJhc2lzIGRhdGEu