UTS Pemrograman Sains Data

Pemrograman Sains Data I

Soal 1

# Menerima dua bilangan dari pengguna
cat("Masukkan bilangan pertama: \n")
## Masukkan bilangan pertama:
a <- 5
cat("Masukkan bilangan kedua: \n")
## Masukkan bilangan kedua:
b <- 4

# Penjumlahan
hasil_penjumlahan <- a + b
cat(sprintf("Penjumlahan antara %.2f dan %.2f adalah %.2f, tipe data: %s\n", a, b, hasil_penjumlahan, class(hasil_penjumlahan)))
## Penjumlahan antara 5.00 dan 4.00 adalah 9.00, tipe data: numeric
# Perkalian
hasil_perkalian <- a * b
cat(sprintf("Perkalian antara %.2f dan %.2f adalah %.2f, tipe data: %s\n", a, b, hasil_perkalian, class(hasil_perkalian)))
## Perkalian antara 5.00 dan 4.00 adalah 20.00, tipe data: numeric
# Pembagian
hasil_pembagian <- a / b
cat(sprintf("Pembagian antara %.2f dan %.2f adalah %.2f, tipe data: %s\n", a, b, hasil_pembagian, class(hasil_pembagian)))
## Pembagian antara 5.00 dan 4.00 adalah 1.25, tipe data: numeric
# Bilangan pertama pangkat bilangan kedua
hasil_pangkat <- a ^ b
cat(sprintf("Hasil Perpangkatan bilangan %.2f dipangkatkan %.2f adalah %.2f, tipe data: %s\n", a, b, hasil_pangkat, class(hasil_pangkat)))
## Hasil Perpangkatan bilangan 5.00 dipangkatkan 4.00 adalah 625.00, tipe data: numeric

Soal 2

# Menerima input nilai ujian dari pengguna
cat("Masukkan nilai ujian (0-100): \n")
## Masukkan nilai ujian (0-100):
nilai <- 80

# Memberikan 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(sprintf("Nilai Anda: %.0f, Keterangan: %s\n", nilai, keterangan))
## Nilai Anda: 80, Keterangan: Baik

Soal 3

# Menerima input dari pengguna
cat("Masukkan batas atas (n): \n")
## Masukkan batas atas (n):
n <- 20

# Loop melalui angka kelipatan 4 dari 4 hingga n
hasil <- c()  # Inisialisasi vektor untuk menyimpan hasil
for (i in seq(4, n, by = 4)) {  # seq(start, end, by) untuk langkah 4
  # Memastikan angka adalah bilangan genap (opsional karena kelipatan 4 selalu genap)
  if (i %% 2 == 0) {
    hasil <- c(hasil, i)  # Tambahkan angka ke dalam vektor hasil
  }
}

# Menampilkan hasil dengan koma, tanpa koma terakhir
cat("Jika batas atas (n):", n,";", paste(hasil, collapse = ", "), "\n")
## Jika batas atas (n): 20 ; 4, 8, 12, 16, 20

Soal 4

Bagian 1: Data Collection

# Library yang diperlukan
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)

# Membaca file CSV
januari <- read.csv("januari.csv")
februari <- read.csv("februari.csv")
maret <- read.csv("maret.csv")

# Menggabungkan dataset
combined_data <- bind_rows(januari, februari, maret)

# Menampilkan jumlah baris dan kolom
total_rows <- nrow(combined_data)
total_columns <- ncol(combined_data)
cat(sprintf("Total rows: %d, Total columns: %d\n", total_rows, total_columns))
## Total rows: 150, Total columns: 9
print(head(combined_data))
##   OrderID    Tanggal       Produk  Kategori     Harga Jumlah Total     Pembeli
## 1    1001 01-01-2024     Laptop A            15000000  empat    NA       Budi@
## 2    1002 02-01-2024  Tas Branded   Fashion  15000000      2    NA       Budi@
## 3    1003 03-01-2024  Tas Branded Aksesoris  15000000      3    NA _anonymous_
## 4    1004 04-01-2024       Kemeja            15000000    dua    NA     Andi123
## 5    1005 05-01-2024            -   Fashion Rp750.000      3    NA _anonymous_
## 6    1006 06-01-2024 Smartphone X   Fashion  15000000  empat    NA     Sinta99
##       Kota
## 1  Bandung
## 2 Surabaya
## 3  Bandung
## 4  Bandung
## 5  Jakarta
## 6  Bandung

Bagian 2: Data Cleaning

# a. Standarkan format tanggal ke bentuk YYYY-MM-DD
combined_data$Tanggal <- as.Date(combined_data$Tanggal, format = "%Y-%m-%d")

# b. Ubah kolom Harga dan Jumlah menjadi format numerik
combined_data$Harga <- as.numeric(as.character(combined_data$Harga))
## Warning: NAs introduced by coercion
combined_data$Jumlah <- as.numeric(as.character(combined_data$Jumlah))
## Warning: NAs introduced by coercion
# c. Hitung ulang kolom Total
combined_data$Total <- combined_data$Harga * combined_data$Jumlah

# d. Ganti nilai tidak valid dengan NA
invalid_values <- c("-", "dua", "Rp", "_anonymous_")
combined_data <- combined_data %>%
  mutate(across(everything(), ~replace(., . %in% invalid_values, NA)))

# e. Hapus baris yang tidak memiliki nama produk
combined_data_cleaned <- combined_data %>%
  filter(!is.na(Produk) & Produk != "-")

# Melihat dataset yang telah dibersihkan
head(combined_data_cleaned)

Bagian 3: Data Transformation

# Pastikan kolom Tanggal bertipe Date
combined_data_cleaned$Tanggal <- as.Date(combined_data_cleaned$Tanggal, format = "%Y-%m-%d")

# a. Tambah kolom Bulan berdasarkan tanggal transaksi
combined_data_cleaned$Bulan <- format(combined_data_cleaned$Tanggal, "%B")

# b. Hitung total penjualan per kategori (tanpa NA atau kategori kosong)
total_penjualan_per_kategori <- combined_data_cleaned %>%
  filter(!is.na(Kategori) & Kategori != "") %>%  # Hanya kategori valid
  group_by(Kategori) %>%
  summarise(Total_Penjualan = sum(Total, na.rm = TRUE), .groups = "drop")

# c. Hitung jumlah transaksi per kota (tanpa NA atau kota kosong)
jumlah_transaksi_per_kota <- combined_data_cleaned %>%
  filter(!is.na(Kota) & Kota != "") %>%  # Hanya kota valid
  count(Kota, name = "Jumlah_Transaksi") %>%
  ungroup()

# d. Hitung total penjualan per bulan dan urutkan Jan–Apr
month_order <- c("January", "February", "March", "April")
total_penjualan_per_bulan <- combined_data_cleaned %>%
  group_by(Bulan) %>%
  summarise(`Total Penjualan` = sum(Total, na.rm = TRUE), .groups = "drop") %>%
  mutate(Bulan = factor(Bulan, levels = month_order, ordered = TRUE)) %>%
  filter(!is.na(Bulan)) %>%  # Pastikan hanya bulan valid
  arrange(Bulan)

# Menampilkan tabel agregat
cat("Total Penjualan per Kategori:\n")
## Total Penjualan per Kategori:
print(total_penjualan_per_kategori)
## # A tibble: 3 × 2
##   Kategori   Total_Penjualan
##   <chr>                <dbl>
## 1 Aksesoris        331750000
## 2 Elektronik       167000000
## 3 Fashion          225000000
cat("\nJumlah Transaksi per Kota:\n")
## 
## Jumlah Transaksi per Kota:
print(jumlah_transaksi_per_kota)
##       Kota Jumlah_Transaksi
## 1  Bandung               33
## 2  Jakarta               29
## 3 Surabaya               30
cat("\nTotal Penjualan per Bulan (Jan–Apr):\n")
## 
## Total Penjualan per Bulan (Jan–Apr):
print(total_penjualan_per_bulan)
## # A tibble: 4 × 2
##   Bulan    `Total Penjualan`
##   <ord>                <dbl>
## 1 January          195750000
## 2 February         286750000
## 3 March            318000000
## 4 April             46250000

Bagian 4: Visualisasi Data

library(ggplot2)
library(scales) # Untuk format angka dan persentase

# Grafik batang - Total penjualan per kategori (dengan angka di atas batang)
ggplot(total_penjualan_per_kategori, aes(x = reorder(Kategori, -Total_Penjualan), y = Total_Penjualan)) +
  geom_bar(stat = "identity", fill = "skyblue", width = 0.7) +
  geom_text(aes(label = scales::comma(Total_Penjualan)), vjust = -0.5, size = 3.5) +
  labs(
    title = "Total Penjualan per Kategori",
    x = "Kategori",
    y = "Total Penjualan"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

# Grafik lingkaran - Persentase transaksi per kota (dengan persentase pada tiap bagian)
jumlah_transaksi_per_kota <- jumlah_transaksi_per_kota %>%
  mutate(Percentage = Jumlah_Transaksi / sum(Jumlah_Transaksi) * 100)

ggplot(jumlah_transaksi_per_kota, aes(x = "", y = Percentage, fill = Kota)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar("y") +
  geom_text(aes(
    label = paste0(round(Percentage, 1), "%"),
    x = 1.3
  ), position = position_stack(vjust = 0.5), size = 3.5) +
  labs(
    title = "Persentase Transaksi per Kota",
    x = NULL,
    y = NULL
  ) +
  scale_fill_brewer(palette = "Set3") +
  theme_void() +
  theme(
    legend.title = element_blank(),
    legend.position = "right"
  )

# Grafik garis - Total penjualan per bulan (dengan angka pada tiap titik)
ggplot(total_penjualan_per_bulan, aes(x = Bulan, y = `Total Penjualan`, group = 1)) +
  geom_line(color = "green", size = 1.2) +
  geom_point(color = "red", size = 3) +
  geom_text(aes(label = scales::comma(`Total Penjualan`)), vjust = -0.5, size = 3.5) +
  labs(
    title = "Total Penjualan per Bulan",
    x = "Bulan",
    y = "Total Penjualan"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

LS0tDQp0aXRsZTogIlVUUyBQZW1yb2dyYW1hbiBTYWlucyBEYXRhIg0Kc3VidGl0bGU6ICJQZW1yb2dyYW1hbiBTYWlucyBEYXRhIEkiDQphdXRob3I6ICJKT0FOUyBIRU5LWSBTRVJWQVRJVVMgU0lNQU5VTExBTkciDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOg0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdGh1bWJuYWlsczogdHJ1ZQ0KICAgIGxpZ2h0Ym94OiB0cnVlDQogICAgZ2FsbGVyeTogdHJ1ZQ0KICAgIGxpYl9kaXI6IGxpYnMNCiAgICBkZl9wcmludDogInBhZ2VkIg0KICAgIGNvZGVfZm9sZGluZzogInNob3ciDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgY3NzOiAic3R5bGUxLmNzcyINCi0tLQ0KPGltZyBzcmM9ImZvdG8uanBlZyIgc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87IHdpZHRoOiAzNjBweDsgaGVpZ2h0OiA0ODBweDsiIGFsdD0iIj4NCg0KIyBTb2FsIDENCmBgYHtyfQ0KIyBNZW5lcmltYSBkdWEgYmlsYW5nYW4gZGFyaSBwZW5nZ3VuYQ0KY2F0KCJNYXN1a2thbiBiaWxhbmdhbiBwZXJ0YW1hOiBcbiIpDQphIDwtIDUNCmNhdCgiTWFzdWtrYW4gYmlsYW5nYW4ga2VkdWE6IFxuIikNCmIgPC0gNA0KDQojIFBlbmp1bWxhaGFuDQpoYXNpbF9wZW5qdW1sYWhhbiA8LSBhICsgYg0KY2F0KHNwcmludGYoIlBlbmp1bWxhaGFuIGFudGFyYSAlLjJmIGRhbiAlLjJmIGFkYWxhaCAlLjJmLCB0aXBlIGRhdGE6ICVzXG4iLCBhLCBiLCBoYXNpbF9wZW5qdW1sYWhhbiwgY2xhc3MoaGFzaWxfcGVuanVtbGFoYW4pKSkNCg0KIyBQZXJrYWxpYW4NCmhhc2lsX3BlcmthbGlhbiA8LSBhICogYg0KY2F0KHNwcmludGYoIlBlcmthbGlhbiBhbnRhcmEgJS4yZiBkYW4gJS4yZiBhZGFsYWggJS4yZiwgdGlwZSBkYXRhOiAlc1xuIiwgYSwgYiwgaGFzaWxfcGVya2FsaWFuLCBjbGFzcyhoYXNpbF9wZXJrYWxpYW4pKSkNCg0KIyBQZW1iYWdpYW4NCmhhc2lsX3BlbWJhZ2lhbiA8LSBhIC8gYg0KY2F0KHNwcmludGYoIlBlbWJhZ2lhbiBhbnRhcmEgJS4yZiBkYW4gJS4yZiBhZGFsYWggJS4yZiwgdGlwZSBkYXRhOiAlc1xuIiwgYSwgYiwgaGFzaWxfcGVtYmFnaWFuLCBjbGFzcyhoYXNpbF9wZW1iYWdpYW4pKSkNCg0KIyBCaWxhbmdhbiBwZXJ0YW1hIHBhbmdrYXQgYmlsYW5nYW4ga2VkdWENCmhhc2lsX3BhbmdrYXQgPC0gYSBeIGINCmNhdChzcHJpbnRmKCJIYXNpbCBQZXJwYW5na2F0YW4gYmlsYW5nYW4gJS4yZiBkaXBhbmdrYXRrYW4gJS4yZiBhZGFsYWggJS4yZiwgdGlwZSBkYXRhOiAlc1xuIiwgYSwgYiwgaGFzaWxfcGFuZ2thdCwgY2xhc3MoaGFzaWxfcGFuZ2thdCkpKQ0KYGBgDQoNCiMgU29hbCAyDQpgYGB7cn0NCiMgTWVuZXJpbWEgaW5wdXQgbmlsYWkgdWppYW4gZGFyaSBwZW5nZ3VuYQ0KY2F0KCJNYXN1a2thbiBuaWxhaSB1amlhbiAoMC0xMDApOiBcbiIpDQpuaWxhaSA8LSA4MA0KDQojIE1lbWJlcmlrYW4ga2V0ZXJhbmdhbiBiZXJkYXNhcmthbiBuaWxhaQ0KaWYgKG5pbGFpID49IDg1KSB7DQogIGtldGVyYW5nYW4gPC0gIlNhbmdhdCBCYWlrIg0KfSBlbHNlIGlmIChuaWxhaSA+PSA3MCkgew0KICBrZXRlcmFuZ2FuIDwtICJCYWlrIg0KfSBlbHNlIGlmIChuaWxhaSA+PSA2MCkgew0KICBrZXRlcmFuZ2FuIDwtICJDdWt1cCINCn0gZWxzZSB7DQogIGtldGVyYW5nYW4gPC0gIlBlcmx1IFBlcmJhaWthbiINCn0NCg0KIyBNZW5hbXBpbGthbiBoYXNpbA0KY2F0KHNwcmludGYoIk5pbGFpIEFuZGE6ICUuMGYsIEtldGVyYW5nYW46ICVzXG4iLCBuaWxhaSwga2V0ZXJhbmdhbikpDQpgYGANCg0KIyBTb2FsIDMNCmBgYHtyfQ0KIyBNZW5lcmltYSBpbnB1dCBkYXJpIHBlbmdndW5hDQpjYXQoIk1hc3Vra2FuIGJhdGFzIGF0YXMgKG4pOiBcbiIpDQpuIDwtIDIwDQoNCiMgTG9vcCBtZWxhbHVpIGFuZ2thIGtlbGlwYXRhbiA0IGRhcmkgNCBoaW5nZ2Egbg0KaGFzaWwgPC0gYygpICAjIEluaXNpYWxpc2FzaSB2ZWt0b3IgdW50dWsgbWVueWltcGFuIGhhc2lsDQpmb3IgKGkgaW4gc2VxKDQsIG4sIGJ5ID0gNCkpIHsgICMgc2VxKHN0YXJ0LCBlbmQsIGJ5KSB1bnR1ayBsYW5na2FoIDQNCiAgIyBNZW1hc3Rpa2FuIGFuZ2thIGFkYWxhaCBiaWxhbmdhbiBnZW5hcCAob3BzaW9uYWwga2FyZW5hIGtlbGlwYXRhbiA0IHNlbGFsdSBnZW5hcCkNCiAgaWYgKGkgJSUgMiA9PSAwKSB7DQogICAgaGFzaWwgPC0gYyhoYXNpbCwgaSkgICMgVGFtYmFoa2FuIGFuZ2thIGtlIGRhbGFtIHZla3RvciBoYXNpbA0KICB9DQp9DQoNCiMgTWVuYW1waWxrYW4gaGFzaWwgZGVuZ2FuIGtvbWEsIHRhbnBhIGtvbWEgdGVyYWtoaXINCmNhdCgiSmlrYSBiYXRhcyBhdGFzIChuKToiLCBuLCI7IiwgcGFzdGUoaGFzaWwsIGNvbGxhcHNlID0gIiwgIiksICJcbiIpDQpgYGANCg0KIyBTb2FsIDQNCg0KIyMgQmFnaWFuIDE6IERhdGEgQ29sbGVjdGlvbg0KYGBge3J9DQojIExpYnJhcnkgeWFuZyBkaXBlcmx1a2FuDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIE1lbWJhY2EgZmlsZSBDU1YNCmphbnVhcmkgPC0gcmVhZC5jc3YoImphbnVhcmkuY3N2IikNCmZlYnJ1YXJpIDwtIHJlYWQuY3N2KCJmZWJydWFyaS5jc3YiKQ0KbWFyZXQgPC0gcmVhZC5jc3YoIm1hcmV0LmNzdiIpDQoNCiMgTWVuZ2dhYnVuZ2thbiBkYXRhc2V0DQpjb21iaW5lZF9kYXRhIDwtIGJpbmRfcm93cyhqYW51YXJpLCBmZWJydWFyaSwgbWFyZXQpDQoNCiMgTWVuYW1waWxrYW4ganVtbGFoIGJhcmlzIGRhbiBrb2xvbQ0KdG90YWxfcm93cyA8LSBucm93KGNvbWJpbmVkX2RhdGEpDQp0b3RhbF9jb2x1bW5zIDwtIG5jb2woY29tYmluZWRfZGF0YSkNCmNhdChzcHJpbnRmKCJUb3RhbCByb3dzOiAlZCwgVG90YWwgY29sdW1uczogJWRcbiIsIHRvdGFsX3Jvd3MsIHRvdGFsX2NvbHVtbnMpKQ0KDQpwcmludChoZWFkKGNvbWJpbmVkX2RhdGEpKQ0KYGBgDQoNCiMjIEJhZ2lhbiAyOiBEYXRhIENsZWFuaW5nDQpgYGB7cn0NCiMgYS4gU3RhbmRhcmthbiBmb3JtYXQgdGFuZ2dhbCBrZSBiZW50dWsgWVlZWS1NTS1ERA0KY29tYmluZWRfZGF0YSRUYW5nZ2FsIDwtIGFzLkRhdGUoY29tYmluZWRfZGF0YSRUYW5nZ2FsLCBmb3JtYXQgPSAiJVktJW0tJWQiKQ0KDQojIGIuIFViYWgga29sb20gSGFyZ2EgZGFuIEp1bWxhaCBtZW5qYWRpIGZvcm1hdCBudW1lcmlrDQpjb21iaW5lZF9kYXRhJEhhcmdhIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGNvbWJpbmVkX2RhdGEkSGFyZ2EpKQ0KY29tYmluZWRfZGF0YSRKdW1sYWggPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoY29tYmluZWRfZGF0YSRKdW1sYWgpKQ0KDQojIGMuIEhpdHVuZyB1bGFuZyBrb2xvbSBUb3RhbA0KY29tYmluZWRfZGF0YSRUb3RhbCA8LSBjb21iaW5lZF9kYXRhJEhhcmdhICogY29tYmluZWRfZGF0YSRKdW1sYWgNCg0KIyBkLiBHYW50aSBuaWxhaSB0aWRhayB2YWxpZCBkZW5nYW4gTkENCmludmFsaWRfdmFsdWVzIDwtIGMoIi0iLCAiZHVhIiwgIlJwIiwgIl9hbm9ueW1vdXNfIikNCmNvbWJpbmVkX2RhdGEgPC0gY29tYmluZWRfZGF0YSAlPiUNCiAgbXV0YXRlKGFjcm9zcyhldmVyeXRoaW5nKCksIH5yZXBsYWNlKC4sIC4gJWluJSBpbnZhbGlkX3ZhbHVlcywgTkEpKSkNCg0KIyBlLiBIYXB1cyBiYXJpcyB5YW5nIHRpZGFrIG1lbWlsaWtpIG5hbWEgcHJvZHVrDQpjb21iaW5lZF9kYXRhX2NsZWFuZWQgPC0gY29tYmluZWRfZGF0YSAlPiUNCiAgZmlsdGVyKCFpcy5uYShQcm9kdWspICYgUHJvZHVrICE9ICItIikNCg0KIyBNZWxpaGF0IGRhdGFzZXQgeWFuZyB0ZWxhaCBkaWJlcnNpaGthbg0KaGVhZChjb21iaW5lZF9kYXRhX2NsZWFuZWQpDQpgYGANCg0KIyMgQmFnaWFuIDM6IERhdGEgVHJhbnNmb3JtYXRpb24NCmBgYHtyfQ0KIyBQYXN0aWthbiBrb2xvbSBUYW5nZ2FsIGJlcnRpcGUgRGF0ZQ0KY29tYmluZWRfZGF0YV9jbGVhbmVkJFRhbmdnYWwgPC0gYXMuRGF0ZShjb21iaW5lZF9kYXRhX2NsZWFuZWQkVGFuZ2dhbCwgZm9ybWF0ID0gIiVZLSVtLSVkIikNCg0KIyBhLiBUYW1iYWgga29sb20gQnVsYW4gYmVyZGFzYXJrYW4gdGFuZ2dhbCB0cmFuc2Frc2kNCmNvbWJpbmVkX2RhdGFfY2xlYW5lZCRCdWxhbiA8LSBmb3JtYXQoY29tYmluZWRfZGF0YV9jbGVhbmVkJFRhbmdnYWwsICIlQiIpDQoNCiMgYi4gSGl0dW5nIHRvdGFsIHBlbmp1YWxhbiBwZXIga2F0ZWdvcmkgKHRhbnBhIE5BIGF0YXUga2F0ZWdvcmkga29zb25nKQ0KdG90YWxfcGVuanVhbGFuX3Blcl9rYXRlZ29yaSA8LSBjb21iaW5lZF9kYXRhX2NsZWFuZWQgJT4lDQogIGZpbHRlcighaXMubmEoS2F0ZWdvcmkpICYgS2F0ZWdvcmkgIT0gIiIpICU+JSAgIyBIYW55YSBrYXRlZ29yaSB2YWxpZA0KICBncm91cF9ieShLYXRlZ29yaSkgJT4lDQogIHN1bW1hcmlzZShUb3RhbF9QZW5qdWFsYW4gPSBzdW0oVG90YWwsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpDQoNCiMgYy4gSGl0dW5nIGp1bWxhaCB0cmFuc2Frc2kgcGVyIGtvdGEgKHRhbnBhIE5BIGF0YXUga290YSBrb3NvbmcpDQpqdW1sYWhfdHJhbnNha3NpX3Blcl9rb3RhIDwtIGNvbWJpbmVkX2RhdGFfY2xlYW5lZCAlPiUNCiAgZmlsdGVyKCFpcy5uYShLb3RhKSAmIEtvdGEgIT0gIiIpICU+JSAgIyBIYW55YSBrb3RhIHZhbGlkDQogIGNvdW50KEtvdGEsIG5hbWUgPSAiSnVtbGFoX1RyYW5zYWtzaSIpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyBkLiBIaXR1bmcgdG90YWwgcGVuanVhbGFuIHBlciBidWxhbiBkYW4gdXJ1dGthbiBKYW7igJNBcHINCm1vbnRoX29yZGVyIDwtIGMoIkphbnVhcnkiLCAiRmVicnVhcnkiLCAiTWFyY2giLCAiQXByaWwiKQ0KdG90YWxfcGVuanVhbGFuX3Blcl9idWxhbiA8LSBjb21iaW5lZF9kYXRhX2NsZWFuZWQgJT4lDQogIGdyb3VwX2J5KEJ1bGFuKSAlPiUNCiAgc3VtbWFyaXNlKGBUb3RhbCBQZW5qdWFsYW5gID0gc3VtKFRvdGFsLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgbXV0YXRlKEJ1bGFuID0gZmFjdG9yKEJ1bGFuLCBsZXZlbHMgPSBtb250aF9vcmRlciwgb3JkZXJlZCA9IFRSVUUpKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShCdWxhbikpICU+JSAgIyBQYXN0aWthbiBoYW55YSBidWxhbiB2YWxpZA0KICBhcnJhbmdlKEJ1bGFuKQ0KDQojIE1lbmFtcGlsa2FuIHRhYmVsIGFncmVnYXQNCmNhdCgiVG90YWwgUGVuanVhbGFuIHBlciBLYXRlZ29yaTpcbiIpDQpwcmludCh0b3RhbF9wZW5qdWFsYW5fcGVyX2thdGVnb3JpKQ0KDQpjYXQoIlxuSnVtbGFoIFRyYW5zYWtzaSBwZXIgS290YTpcbiIpDQpwcmludChqdW1sYWhfdHJhbnNha3NpX3Blcl9rb3RhKQ0KDQpjYXQoIlxuVG90YWwgUGVuanVhbGFuIHBlciBCdWxhbiAoSmFu4oCTQXByKTpcbiIpDQpwcmludCh0b3RhbF9wZW5qdWFsYW5fcGVyX2J1bGFuKQ0KYGBgDQoNCiMjIEJhZ2lhbiA0OiBWaXN1YWxpc2FzaSBEYXRhDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoc2NhbGVzKSAjIFVudHVrIGZvcm1hdCBhbmdrYSBkYW4gcGVyc2VudGFzZQ0KDQojIEdyYWZpayBiYXRhbmcgLSBUb3RhbCBwZW5qdWFsYW4gcGVyIGthdGVnb3JpIChkZW5nYW4gYW5na2EgZGkgYXRhcyBiYXRhbmcpDQpnZ3Bsb3QodG90YWxfcGVuanVhbGFuX3Blcl9rYXRlZ29yaSwgYWVzKHggPSByZW9yZGVyKEthdGVnb3JpLCAtVG90YWxfUGVuanVhbGFuKSwgeSA9IFRvdGFsX1Blbmp1YWxhbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIsIHdpZHRoID0gMC43KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzY2FsZXM6OmNvbW1hKFRvdGFsX1Blbmp1YWxhbikpLCB2anVzdCA9IC0wLjUsIHNpemUgPSAzLjUpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIiwNCiAgICB4ID0gIkthdGVnb3JpIiwNCiAgICB5ID0gIlRvdGFsIFBlbmp1YWxhbiINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQoNCiMgR3JhZmlrIGxpbmdrYXJhbiAtIFBlcnNlbnRhc2UgdHJhbnNha3NpIHBlciBrb3RhIChkZW5nYW4gcGVyc2VudGFzZSBwYWRhIHRpYXAgYmFnaWFuKQ0KanVtbGFoX3RyYW5zYWtzaV9wZXJfa290YSA8LSBqdW1sYWhfdHJhbnNha3NpX3Blcl9rb3RhICU+JQ0KICBtdXRhdGUoUGVyY2VudGFnZSA9IEp1bWxhaF9UcmFuc2Frc2kgLyBzdW0oSnVtbGFoX1RyYW5zYWtzaSkgKiAxMDApDQoNCmdncGxvdChqdW1sYWhfdHJhbnNha3NpX3Blcl9rb3RhLCBhZXMoeCA9ICIiLCB5ID0gUGVyY2VudGFnZSwgZmlsbCA9IEtvdGEpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEsIGNvbG9yID0gIndoaXRlIikgKw0KICBjb29yZF9wb2xhcigieSIpICsNCiAgZ2VvbV90ZXh0KGFlcygNCiAgICBsYWJlbCA9IHBhc3RlMChyb3VuZChQZXJjZW50YWdlLCAxKSwgIiUiKSwNCiAgICB4ID0gMS4zDQogICksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBzaXplID0gMy41KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUGVyc2VudGFzZSBUcmFuc2Frc2kgcGVyIEtvdGEiLA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSBOVUxMDQogICkgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDMiKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIHRoZW1lKA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkNCg0KIyBHcmFmaWsgZ2FyaXMgLSBUb3RhbCBwZW5qdWFsYW4gcGVyIGJ1bGFuIChkZW5nYW4gYW5na2EgcGFkYSB0aWFwIHRpdGlrKQ0KZ2dwbG90KHRvdGFsX3Blbmp1YWxhbl9wZXJfYnVsYW4sIGFlcyh4ID0gQnVsYW4sIHkgPSBgVG90YWwgUGVuanVhbGFuYCwgZ3JvdXAgPSAxKSkgKw0KICBnZW9tX2xpbmUoY29sb3IgPSAiZ3JlZW4iLCBzaXplID0gMS4yKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAicmVkIiwgc2l6ZSA9IDMpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNjYWxlczo6Y29tbWEoYFRvdGFsIFBlbmp1YWxhbmApKSwgdmp1c3QgPSAtMC41LCBzaXplID0gMy41KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVG90YWwgUGVuanVhbGFuIHBlciBCdWxhbiIsDQogICAgeCA9ICJCdWxhbiIsDQogICAgeSA9ICJUb3RhbCBQZW5qdWFsYW4iDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQpgYGANCg0KDQo=