Tugas Individu

Ujian Tengah Semester - Pemrograman Sains Data

Foto Diri


1.Operasi dan Tipe Data Dasar

a.) Menerima dua bilangan dari pengguna

# Menerima input dari pengguna
# x <- as.numeric(readline(prompt="Masukkan bilangan pertama: "))
# y <- as.numeric(readline(prompt="Masukkan bilangan kedua: "))

X<-1 
Y<-2

b.) Menghitung dan menampilkan hasil:

  • Penjumlahan

  • Perkalian

  • Pembagian

  • Bilangan pertama pangkat bilangan kedua

# Misalnya Pengguna Memasukan 2 variable x=1 dan y=2
X<-1 
Y<-2

# Penjumlahan
penjumlahan <- X + Y
cat("Hasil penjumlahan:", penjumlahan, "\n")
## Hasil penjumlahan: 3
# Perkalian
perkalian <- X * Y
cat("Hasil perkalian:", perkalian, "\n")
## Hasil perkalian: 2
# Pembagian
pembagian <- X / Y
cat("Hasil pembagian:", pembagian, "\n")
## Hasil pembagian: 0.5
# Pangkat
pangkat <- X ^ Y
cat("Hasil pangkat:", pangkat, "\n")
## Hasil pangkat: 1

c.) Menampilkan tipe data masing-masing hasil operasi

# Menampilkan tipe data dari hasil operasi
cat("Tipe data hasil penjumlahan:", class(penjumlahan), "\n")
## Tipe data hasil penjumlahan: numeric
cat("Tipe data hasil perkalian:", class(perkalian), "\n")
## Tipe data hasil perkalian: numeric
cat("Tipe data hasil pembagian:", class(pembagian), "\n")
## Tipe data hasil pembagian: numeric
cat("Tipe data hasil pangkat:", class(pangkat), "\n")
## Tipe data hasil pangkat: numeric

2.Struktur Kendali (Control Flow)

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

# Menerima input nilai ujian dari pengguna
# nilai <- as.numeric(readline(prompt = "Masukkan nilai ujian (0-100): "))
nilai<-82

b.) Menampilkan keterangan berdasarkan ketentuan berikut:

# Misalnya Pengguna Memasukan nilai ujian dengan nilai 82
nilai <-82

# Menampilkan keterangan berdasarkan ketentuan
if (nilai >= 85) {
  cat("Sangat Baik\n")
} else if (nilai >= 70 && nilai <= 84) {
  cat("Baik\n")
} else if (nilai >= 60 && nilai <= 69) {
  cat("Cukup\n")
} else {
  cat("Perlu Perbaikan\n")
}
## Baik

3.Fungsi dan Perulangan

a.) Menerima input integer n dari pengguna

# Menerima input dari pengguna (bisa pakai readline atau langsung input nilai)
# n <- as.integer(readline(prompt = "Masukkan angka n: "))

n <- 30 

b.) Menggunakan loop untuk mencetak semua bilangan genap kelipatan 4 dari 1 hingga n

# Misal menerima input dari pengguna 30

n <-30


# Fungsi untuk mencetak bilangan genap kelipatan 4
kelipatan_genap <- function(n) {
  cat("Bilangan genap kelipatan 4 dari 1 sampai", n, ":\n")
  for (i in 1:n) {
    if (i %% 4 == 0) {
      cat(i, "\n")
    }
  }
}

# Memanggil fungsi
kelipatan_genap(n)
## Bilangan genap kelipatan 4 dari 1 sampai 30 :
## 4 
## 8 
## 12 
## 16 
## 20 
## 24 
## 28

4. Simulasi dan Analisis Penjualan E-Commerce 3 Bulan Terakhir

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.

a.) Data Collection

  1. Gabungkan ketiga file menjadi satu dataset.

  2. Tampilkan jumlah total baris dan kolom setelah digabung.

# 1. Baca (ambil) data dari file CSV untuk bulan Januari, Februari, dan Maret
data_jan <- read.csv("data_penjualan_kuartal1_full - Januari.csv")
data_feb <- read.csv("data_penjualan_kuartal1_full - Februari.csv")
data_mar <- read.csv("data_penjualan_kuartal1_full - Maret.csv")

# 2. Tampilkan 5 data teratas dari masing-masing bulan, untuk melihat isi datanya

# Menampilkan isi masing-masing file
cat(" Data Januari:\n")
##  Data Januari:
print(head(data_jan))
##   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
cat("\n")
cat(" Data Februari:\n")
##  Data Februari:
print(head(data_feb))
##   OrderID    Tanggal       Produk  Kategori     Harga Jumlah Total     Pembeli
## 1    1101 01-02-2024  Tas Branded Aksesoris 1.200.000    dua    NA       Budi@
## 2    1102 02-02-2024 Smartphone X   Fashion Rp750.000      2    NA _anonymous_
## 3    1103 03-02-2024       Kemeja   Fashion  15000000      1    NA       Budi@
## 4    1104 04-02-2024       Kemeja   Fashion  15000000  empat    NA _anonymous_
## 5    1105 05-02-2024 Smartphone X            15000000  empat    NA _anonymous_
## 6    1106 06-02-2024            - Aksesoris Rp750.000      3    NA _anonymous_
##       Kota
## 1  Bandung
## 2        -
## 3 Surabaya
## 4  Bandung
## 5 Surabaya
## 6  Bandung
cat("\n")
cat(" Data Maret:\n")
##  Data Maret:
print(head(data_mar))
##   OrderID    Tanggal        Produk   Kategori     Harga Jumlah Total
## 1    1201 01-03-2024 Sepatu 'Nike'    Fashion 1.200.000  empat    NA
## 2    1202 02-03-2024             - Elektronik  15000000      3    NA
## 3    1203 03-03-2024             -    Fashion 1.200.000    dua    NA
## 4    1204 04-03-2024             -            Rp750.000      3    NA
## 5    1205 05-03-2024   Tas Branded            Rp750.000    dua    NA
## 6    1206 06-03-2024        Kemeja  Aksesoris  15000000      2    NA
##       Pembeli     Kota
## 1     Andi123 Surabaya
## 2 _anonymous_  Jakarta
## 3     Sinta99 Surabaya
## 4       Budi@ Surabaya
## 5     Andi123  Jakarta
## 6     Andi123 Surabaya
cat("\n")
library(dplyr)
## 
## 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(readr)
## Warning: package 'readr' was built under R version 4.4.3
# 1. Baca data
data_januari <- read_csv("data_penjualan_kuartal1_full - Januari.csv", show_col_types = FALSE)
data_februari <- read_csv("data_penjualan_kuartal1_full - Februari.csv", show_col_types = FALSE)
data_maret <- read_csv("data_penjualan_kuartal1_full - Maret.csv", show_col_types = FALSE)

# 2. Samakan nama & urutan kolom berdasarkan Januari
kolom_standar <- names(data_januari)

data_februari <- data_februari %>% select(all_of(kolom_standar))
data_maret    <- data_maret %>% select(all_of(kolom_standar))

# 3. Gabungkan data
data_penjualan_kuartal1 <- bind_rows(data_januari, data_februari, data_maret)

# 4. Cek jumlah baris dan kolom
data_penjualan_kuartal1 %>%
  summarise(
    total_baris = n(),
    total_kolom = ncol(.)
  ) %>%
  print()
## # A tibble: 1 × 2
##   total_baris total_kolom
##         <int>       <int>
## 1         150           9

b.) Data Cleaning

Melakukan 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 -).

library(dplyr)
library(readr)
library(stringr)
library(lubridate)
## Warning: package 'lubridate' was built under R version 4.4.3
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
# Menggunakan data hasil penggabungan
df <- data_penjualan_kuartal1

# a,Konversi tanggal ke format YYYY-MM-DD
df <- df %>%
  mutate(Tanggal = dmy(Tanggal))

# b1,Bersihkan kolom Harga (hapus simbol selain angka)
df <- df %>%
  mutate(
    Harga = str_remove_all(as.character(Harga), "[^0-9]"),
    Harga = as.numeric(Harga)
  )

# b2,Ubah teks menjadi angka di kolom Jumlah
df <- df %>%
  mutate(
    Jumlah = tolower(Jumlah),
    Jumlah = recode(Jumlah,
                    "satu" = "1",
                    "dua" = "2",
                    "tiga" = "3",
                    "empat" = "4",
                    "lima" = "5",
                    .default = as.character(Jumlah)),
    Jumlah = as.numeric(Jumlah)
  )

# c,Hitung kolom Total
df <- df %>%
  mutate(Total = Harga * Jumlah)

# d,Ganti nilai tidak valid di semua kolom karakter
invalid_values <- c("-", "Rp", "anonymous", "anonymous")
df <- df %>%
  mutate(across(where(is.character), ~replace(., . %in% invalid_values, NA)))

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

# Tampilkan hasil akhir
cat("Data setelah dibersihkan:\n")
## Data setelah dibersihkan:
print(head(df))
## # A tibble: 6 × 9
##   OrderID Tanggal    Produk        Kategori    Harga Jumlah  Total Pembeli Kota 
##     <dbl> <date>     <chr>         <chr>       <dbl>  <dbl>  <dbl> <chr>   <chr>
## 1    1001 2024-01-01 Laptop A      <NA>       1.5 e7      4 6   e7 Budi@   Band…
## 2    1002 2024-01-02 Tas Branded   Fashion    1.5 e7      2 3   e7 Budi@   Sura…
## 3    1003 2024-01-03 Tas Branded   Aksesoris  1.5 e7      3 4.50e7 _anony… Band…
## 4    1004 2024-01-04 Kemeja        <NA>       1.5 e7      2 3   e7 Andi123 Band…
## 5    1006 2024-01-06 Smartphone X  Fashion    1.5 e7      4 6   e7 Sinta99 Band…
## 6    1007 2024-01-07 Sepatu 'Nike' Elektronik 1.20e6      3 3.60e6 _anony… Band…

c.) Data Transformation

Lakukan transformasi data sebagai berikut: a. Buat kolom baru Bulan berdasarkan tanggal transaksi. b. Hitung total penjualan (Total) per kategori produk. c. Hitung jumlah transaksi dari setiap kota. d. Buat ringkasan jumlah total penjualan per bulan.

library(dplyr)
library(lubridate)

# a. Buat kolom baru bernama 'Bulan' berdasarkan tanggal transaksi
bulan_map <- c("Januari", "Februari", "Maret")
df$Bulan <- bulan_map[month(df$Tanggal)]

# b. Hitung total penjualan untuk setiap kategori produk
penjualan_per_kategori <- df %>%
  group_by(Kategori) %>%
  summarise(Total = sum(Total, na.rm = TRUE)) %>%
  arrange(desc(Total))

# c. Hitung jumlah transaksi dari setiap kota
penjualan_per_kota <- df %>%
  count(Kota, name = "Jumlah_Transaksi") %>%
  arrange(desc(Jumlah_Transaksi))

# d. Buat ringkasan total penjualan per bulan
penjualan_per_bulan <- df %>%
  group_by(Bulan) %>%
  summarise(Total = sum(Total, na.rm = TRUE)) %>%
  arrange(desc(Total))

# Tampilkan hasil
cat("Total Penjualan per Kategori Produk:\n")
## Total Penjualan per Kategori Produk:
print(penjualan_per_kategori)
## # A tibble: 4 × 2
##   Kategori       Total
##   <chr>          <dbl>
## 1 Fashion    440150000
## 2 Elektronik 419350000
## 3 <NA>       393350000
## 4 Aksesoris  380850000
cat("\nJumlah Transaksi per Kota:\n")
## 
## Jumlah Transaksi per Kota:
print(penjualan_per_kota)
## # A tibble: 4 × 2
##   Kota     Jumlah_Transaksi
##   <chr>               <int>
## 1 Bandung                33
## 2 Surabaya               30
## 3 <NA>                   30
## 4 Jakarta                29
cat("\nTotal Penjualan per Bulan:\n")
## 
## Total Penjualan per Bulan:
print(penjualan_per_bulan)
## # A tibble: 4 × 2
##   Bulan        Total
##   <chr>        <dbl>
## 1 Februari 494400000
## 2 Januari  489150000
## 3 Maret    458950000
## 4 <NA>     191200000

d.) Visualisasi

Grafik Total Penjualan per Kategori

# Pastikan library ggplot2 sudah dipanggil
library(ggplot2)

# 1. Urutkan data dari yang totalnya paling besar ke paling kecil
penjualan_per_kategori <- penjualan_per_kategori %>%
  arrange(desc(Total))

# 2. Buat grafik batang horizontal
ggplot(penjualan_per_kategori, aes(x = reorder(Kategori, Total), y = Total)) +
  
  # 3. Buat batangnya
  geom_bar(stat = "identity", fill = "darkolivegreen3") +

  # 4. Bikin sumbu Y jadi Kategori dan sumbu X jadi Total (dengan posisi horizontal)
  coord_flip() +

  # 5. Tambahkan judul grafik
  labs(title = "Total Penjualan per Kategori",
       x = "Kategori Produk",
       y = "Total Penjualan") +

  # 6. Bikin tampilan grafik jadi rapi dan simpel
  theme_minimal()

# Jumlah transaksi per kota sesuai data kamu
bandung <- 33
surabaya <- 30
jakarta <- 29

# Total seluruh transaksi
total <- bandung + surabaya + jakarta

# Hitung persentasenya (dibulatkan 1 angka desimal)
persen_bandung <- round(bandung / total * 100, 1)
persen_surabaya <- round(surabaya / total * 100, 1)
persen_jakarta <- round(jakarta / total * 100, 1)

# Tampilkan hasil
cat("Persentase Bandung :", persen_bandung, "%\n")
## Persentase Bandung : 35.9 %
cat("Persentase Surabaya:", persen_surabaya, "%\n")
## Persentase Surabaya: 32.6 %
cat("Persentase Jakarta :", persen_jakarta, "%\n")
## Persentase Jakarta : 31.5 %
# Data transaksi per kota
kota_transaksi <- c(33, 30, 29)
kota_nama <- c("Bandung", "Surabaya", "Jakarta")

# Hitung total transaksi
total_transaksi <- sum(kota_transaksi)

# Hitung persentase untuk masing-masing kota
persen_bandung <- round(kota_transaksi[1] / total_transaksi * 100, 1)
persen_surabaya <- round(kota_transaksi[2] / total_transaksi * 100, 1)
persen_jakarta <- round(kota_transaksi[3] / total_transaksi * 100, 1)

# Buat vector persentase
persen <- c(persen_bandung, persen_surabaya, persen_jakarta)

# Visualisasi dengan pie chart
pie(kota_transaksi, 
    labels = paste(kota_nama, "\n", persen, "%"),  # Menambahkan label dengan nama kota dan persentase
    col = c("lightblue", "lightgreen", "lightcoral"),  # Warna pie chart
    main = "Persentase Transaksi per Kota",          # Judul grafik
    radius = 1)                                      # Ukuran pie chart

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

# Buat kolom BulanAngka dan BulanNama dari kolom Tanggal
df$BulanAngka <- as.numeric(format(df$Tanggal, "%m"))
df$BulanNama <- format(df$Tanggal, "%B")

# Filter hanya untuk bulan Januari (1), Februari (2), dan Maret (3)
df_bulan123 <- df[df$BulanAngka %in% c(1, 2, 3), ]

# Hitung total penjualan per bulan
library(dplyr)
penjualan_bulanan <- df_bulan123 %>%
  group_by(BulanAngka, BulanNama) %>%
  summarise(Total = sum(Total, na.rm = TRUE)) %>%
  arrange(BulanAngka)
## `summarise()` has grouped output by 'BulanAngka'. You can override using the
## `.groups` argument.
# Plot grafik garis
library(ggplot2)
ggplot(penjualan_bulanan, aes(x=BulanNama, y=Total, group=1)) +
  geom_line(color='red', size=1) +
  geom_point(color='red', size=3) +
  ggtitle("Total Penjualan per Bulan (Jan - Mar)") +
  xlab("Bulan") +
  ylab("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.

LS0tDQp0aXRsZTogIlR1Z2FzIEluZGl2aWR1ICINCnN1YnRpdGxlOiAiVWppYW4gVGVuZ2FoIFNlbWVzdGVyIC0gUGVtcm9ncmFtYW4gU2FpbnMgRGF0YSINCmF1dGhvcjogIk9saXZpYSBNZWlsaW5kYSBEYXZ0aW4gUGVzaXJlcm9uIg0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcyANCiAgICBjc3M6ICJzdHlsZS5jc3MiDQotLS0NCg0KPGltZyBzcmM9ImxpdmlrYXRhbnlhLmpwZyIgd2lkdGg9IjMwMCIgc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87IiBhbHQ9IkZvdG8gRGlyaSI+DQoNCi0tLQ0KDQojIyAxLk9wZXJhc2kgZGFuIFRpcGUgRGF0YSBEYXNhcg0KDQojIyMgYS4pIE1lbmVyaW1hIGR1YSBiaWxhbmdhbiBkYXJpIHBlbmdndW5hDQoNCmBgYHtyfQ0KIyBNZW5lcmltYSBpbnB1dCBkYXJpIHBlbmdndW5hDQojIHggPC0gYXMubnVtZXJpYyhyZWFkbGluZShwcm9tcHQ9Ik1hc3Vra2FuIGJpbGFuZ2FuIHBlcnRhbWE6ICIpKQ0KIyB5IDwtIGFzLm51bWVyaWMocmVhZGxpbmUocHJvbXB0PSJNYXN1a2thbiBiaWxhbmdhbiBrZWR1YTogIikpDQoNClg8LTEgDQpZPC0yDQoNCmBgYA0KDQojIyMgYi4pIE1lbmdoaXR1bmcgZGFuIG1lbmFtcGlsa2FuIGhhc2lsOg0KDQotIFBlbmp1bWxhaGFuDQoNCi0gUGVya2FsaWFuDQoNCi0gUGVtYmFnaWFuDQoNCi0gQmlsYW5nYW4gcGVydGFtYSBwYW5na2F0IGJpbGFuZ2FuIGtlZHVhDQoNCmBgYHtyfQ0KIyBNaXNhbG55YSBQZW5nZ3VuYSBNZW1hc3VrYW4gMiB2YXJpYWJsZSB4PTEgZGFuIHk9Mg0KWDwtMSANClk8LTINCg0KIyBQZW5qdW1sYWhhbg0KcGVuanVtbGFoYW4gPC0gWCArIFkNCmNhdCgiSGFzaWwgcGVuanVtbGFoYW46IiwgcGVuanVtbGFoYW4sICJcbiIpDQoNCiMgUGVya2FsaWFuDQpwZXJrYWxpYW4gPC0gWCAqIFkNCmNhdCgiSGFzaWwgcGVya2FsaWFuOiIsIHBlcmthbGlhbiwgIlxuIikNCg0KIyBQZW1iYWdpYW4NCnBlbWJhZ2lhbiA8LSBYIC8gWQ0KY2F0KCJIYXNpbCBwZW1iYWdpYW46IiwgcGVtYmFnaWFuLCAiXG4iKQ0KDQojIFBhbmdrYXQNCnBhbmdrYXQgPC0gWCBeIFkNCmNhdCgiSGFzaWwgcGFuZ2thdDoiLCBwYW5na2F0LCAiXG4iKQ0KDQpgYGANCg0KIyMjIGMuKSBNZW5hbXBpbGthbiB0aXBlIGRhdGEgbWFzaW5nLW1hc2luZyBoYXNpbCBvcGVyYXNpDQoNCg0KYGBge3J9DQoNCiMgTWVuYW1waWxrYW4gdGlwZSBkYXRhIGRhcmkgaGFzaWwgb3BlcmFzaQ0KY2F0KCJUaXBlIGRhdGEgaGFzaWwgcGVuanVtbGFoYW46IiwgY2xhc3MocGVuanVtbGFoYW4pLCAiXG4iKQ0KY2F0KCJUaXBlIGRhdGEgaGFzaWwgcGVya2FsaWFuOiIsIGNsYXNzKHBlcmthbGlhbiksICJcbiIpDQpjYXQoIlRpcGUgZGF0YSBoYXNpbCBwZW1iYWdpYW46IiwgY2xhc3MocGVtYmFnaWFuKSwgIlxuIikNCmNhdCgiVGlwZSBkYXRhIGhhc2lsIHBhbmdrYXQ6IiwgY2xhc3MocGFuZ2thdCksICJcbiIpDQpgYGANCg0KLS0tDQotLS0NCg0KIyMgMi5TdHJ1a3R1ciBLZW5kYWxpIChDb250cm9sIEZsb3cpDQoNCiMjIyBhLikgTWVuZXJpbWEgaW5wdXQgbmlsYWkgdWppYW4gZGFyaSBwZW5nZ3VuYSAoMC0xMDApDQoNCg0KYGBge3J9DQojIE1lbmVyaW1hIGlucHV0IG5pbGFpIHVqaWFuIGRhcmkgcGVuZ2d1bmENCiMgbmlsYWkgPC0gYXMubnVtZXJpYyhyZWFkbGluZShwcm9tcHQgPSAiTWFzdWtrYW4gbmlsYWkgdWppYW4gKDAtMTAwKTogIikpDQpuaWxhaTwtODINCg0KYGBgDQoNCiMjIyBiLikgTWVuYW1waWxrYW4ga2V0ZXJhbmdhbiBiZXJkYXNhcmthbiBrZXRlbnR1YW4gYmVyaWt1dDoNCg0KDQpgYGB7cn0NCiMgTWlzYWxueWEgUGVuZ2d1bmEgTWVtYXN1a2FuIG5pbGFpIHVqaWFuIGRlbmdhbiBuaWxhaSA4Mg0KbmlsYWkgPC04Mg0KDQojIE1lbmFtcGlsa2FuIGtldGVyYW5nYW4gYmVyZGFzYXJrYW4ga2V0ZW50dWFuDQppZiAobmlsYWkgPj0gODUpIHsNCiAgY2F0KCJTYW5nYXQgQmFpa1xuIikNCn0gZWxzZSBpZiAobmlsYWkgPj0gNzAgJiYgbmlsYWkgPD0gODQpIHsNCiAgY2F0KCJCYWlrXG4iKQ0KfSBlbHNlIGlmIChuaWxhaSA+PSA2MCAmJiBuaWxhaSA8PSA2OSkgew0KICBjYXQoIkN1a3VwXG4iKQ0KfSBlbHNlIHsNCiAgY2F0KCJQZXJsdSBQZXJiYWlrYW5cbiIpDQp9DQoNCmBgYA0KDQotLS0NCg0KLS0tDQotLS0NCg0KIyMgMy5GdW5nc2kgZGFuIFBlcnVsYW5nYW4NCg0KIyMjIGEuKSBNZW5lcmltYSBpbnB1dCBpbnRlZ2VyIG4gZGFyaSBwZW5nZ3VuYSANCg0KYGBge3J9DQojIE1lbmVyaW1hIGlucHV0IGRhcmkgcGVuZ2d1bmEgKGJpc2EgcGFrYWkgcmVhZGxpbmUgYXRhdSBsYW5nc3VuZyBpbnB1dCBuaWxhaSkNCiMgbiA8LSBhcy5pbnRlZ2VyKHJlYWRsaW5lKHByb21wdCA9ICJNYXN1a2thbiBhbmdrYSBuOiAiKSkNCg0KbiA8LSAzMCANCg0KYGBgDQoNCiMjIyBiLikgTWVuZ2d1bmFrYW4gbG9vcCB1bnR1ayBtZW5jZXRhayBzZW11YSBiaWxhbmdhbiBnZW5hcCBrZWxpcGF0YW4gNCBkYXJpIDEgaGluZ2dhIG4NCg0KYGBge3J9DQoNCiMgTWlzYWwgbWVuZXJpbWEgaW5wdXQgZGFyaSBwZW5nZ3VuYSAzMA0KDQpuIDwtMzANCg0KDQojIEZ1bmdzaSB1bnR1ayBtZW5jZXRhayBiaWxhbmdhbiBnZW5hcCBrZWxpcGF0YW4gNA0Ka2VsaXBhdGFuX2dlbmFwIDwtIGZ1bmN0aW9uKG4pIHsNCiAgY2F0KCJCaWxhbmdhbiBnZW5hcCBrZWxpcGF0YW4gNCBkYXJpIDEgc2FtcGFpIiwgbiwgIjpcbiIpDQogIGZvciAoaSBpbiAxOm4pIHsNCiAgICBpZiAoaSAlJSA0ID09IDApIHsNCiAgICAgIGNhdChpLCAiXG4iKQ0KICAgIH0NCiAgfQ0KfQ0KDQojIE1lbWFuZ2dpbCBmdW5nc2kNCmtlbGlwYXRhbl9nZW5hcChuKQ0KDQpgYGANCi0tLQ0KLS0tDQoNCiMjIDQuIFNpbXVsYXNpIGRhbiBBbmFsaXNpcyBQZW5qdWFsYW4gRS1Db21tZXJjZSAzIEJ1bGFuIFRlcmFraGlyDQoNClNlYnVhaCBwZXJ1c2FoYWFuIGUtY29tbWVyY2UgaW5naW4gbWVuZ2FuYWxpc2lzIHBlcmZvcm1hIHBlbmp1YWxhbm55YSBiZXJkYXNhcmthbiBkYXRhIHRyYW5zYWtzaSBzZWxhbWEgMyBidWxhbiB0ZXJha2hpci4gTmFtdW4sIGRhdGEgeWFuZyB0ZXJzZWRpYSBiZXJhc2FsIGRhcmkgYmVyYmFnYWkgc3VtYmVyIGRhbiBtZW1pbGlraSBrdWFsaXRhcyB5YW5nIGJlcmFnYW0uIEFuZGEgZGltaW50YSB1bnR1ayBtZWxha3VrYW4gRGF0YSBXcmFuZ2xpbmcgc2ViZWx1bSBkaWFuYWxpc2lzIGxlYmloIGxhbmp1dC4NCg0KIyMjIGEuKSBEYXRhIENvbGxlY3Rpb24NCg0KYS4gR2FidW5na2FuIGtldGlnYSBmaWxlIG1lbmphZGkgc2F0dSBkYXRhc2V0Lg0KDQpiLiBUYW1waWxrYW4ganVtbGFoIHRvdGFsIGJhcmlzIGRhbiBrb2xvbSBzZXRlbGFoIGRpZ2FidW5nLg0KDQpgYGB7cn0NCiMgMS4gQmFjYSAoYW1iaWwpIGRhdGEgZGFyaSBmaWxlIENTViB1bnR1ayBidWxhbiBKYW51YXJpLCBGZWJydWFyaSwgZGFuIE1hcmV0DQpkYXRhX2phbiA8LSByZWFkLmNzdigiZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDFfZnVsbCAtIEphbnVhcmkuY3N2IikNCmRhdGFfZmViIDwtIHJlYWQuY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gRmVicnVhcmkuY3N2IikNCmRhdGFfbWFyIDwtIHJlYWQuY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gTWFyZXQuY3N2IikNCg0KIyAyLiBUYW1waWxrYW4gNSBkYXRhIHRlcmF0YXMgZGFyaSBtYXNpbmctbWFzaW5nIGJ1bGFuLCB1bnR1ayBtZWxpaGF0IGlzaSBkYXRhbnlhDQoNCiMgTWVuYW1waWxrYW4gaXNpIG1hc2luZy1tYXNpbmcgZmlsZQ0KY2F0KCIgRGF0YSBKYW51YXJpOlxuIikNCnByaW50KGhlYWQoZGF0YV9qYW4pKQ0KY2F0KCJcbiIpDQoNCmNhdCgiIERhdGEgRmVicnVhcmk6XG4iKQ0KcHJpbnQoaGVhZChkYXRhX2ZlYikpDQpjYXQoIlxuIikNCg0KY2F0KCIgRGF0YSBNYXJldDpcbiIpDQpwcmludChoZWFkKGRhdGFfbWFyKSkNCmNhdCgiXG4iKQ0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KYGBge3J9DQoNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWRyKQ0KDQojIDEuIEJhY2EgZGF0YQ0KZGF0YV9qYW51YXJpIDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gSmFudWFyaS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQ0KZGF0YV9mZWJydWFyaSA8LSByZWFkX2NzdigiZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDFfZnVsbCAtIEZlYnJ1YXJpLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQpkYXRhX21hcmV0IDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gTWFyZXQuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkNCg0KIyAyLiBTYW1ha2FuIG5hbWEgJiB1cnV0YW4ga29sb20gYmVyZGFzYXJrYW4gSmFudWFyaQ0Ka29sb21fc3RhbmRhciA8LSBuYW1lcyhkYXRhX2phbnVhcmkpDQoNCmRhdGFfZmVicnVhcmkgPC0gZGF0YV9mZWJydWFyaSAlPiUgc2VsZWN0KGFsbF9vZihrb2xvbV9zdGFuZGFyKSkNCmRhdGFfbWFyZXQgICAgPC0gZGF0YV9tYXJldCAlPiUgc2VsZWN0KGFsbF9vZihrb2xvbV9zdGFuZGFyKSkNCg0KIyAzLiBHYWJ1bmdrYW4gZGF0YQ0KZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDEgPC0gYmluZF9yb3dzKGRhdGFfamFudWFyaSwgZGF0YV9mZWJydWFyaSwgZGF0YV9tYXJldCkNCg0KIyA0LiBDZWsganVtbGFoIGJhcmlzIGRhbiBrb2xvbQ0KZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDEgJT4lDQogIHN1bW1hcmlzZSgNCiAgICB0b3RhbF9iYXJpcyA9IG4oKSwNCiAgICB0b3RhbF9rb2xvbSA9IG5jb2woLikNCiAgKSAlPiUNCiAgcHJpbnQoKQ0KYGBgDQojIyMgYi4pIERhdGEgQ2xlYW5pbmcNCg0KTWVsYWt1a2FuIHBlbWJlcnNpaGFuIGRhdGEgYmVyaWt1dDoNCg0KYS4gU3RhbmRhcmthbiBmb3JtYXQgdGFuZ2dhbCBrZSBiZW50dWsgWVlZWS1NTS1ERC4NCg0KYi4gVWJhaCBrb2xvbSBIYXJnYSBkYW4gSnVtbGFoIG1lbmphZGkgZm9ybWF0IG51bWVyaWsuDQoNCmMuIEhpdHVuZyB1bGFuZyBuaWxhaSBrb2xvbSBUb3RhbCA9IEhhcmdhICogSnVtbGFoLg0KDQpkLiBHYW50aSBuaWxhaSB5YW5nIHRpZGFrIHZhbGlkIChjb250b2g6IC0sICJkdWEiLCAiUnAiLCAiX2Fub255bW91c18iKSBkZW5nYW4gbmlsYWkgeWFuZyBzZXN1YWkgYXRhdSBOQS4NCg0KZS4gSGFwdXMgYmFyaXMgeWFuZyB0aWRhayBtZW1pbGlraSBuYW1hIHByb2R1ayAoUHJvZHVrIGtvc29uZyBhdGF1IC0pLg0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQoNCiMgTWVuZ2d1bmFrYW4gZGF0YSBoYXNpbCBwZW5nZ2FidW5nYW4NCmRmIDwtIGRhdGFfcGVuanVhbGFuX2t1YXJ0YWwxDQoNCiMgYSxLb252ZXJzaSB0YW5nZ2FsIGtlIGZvcm1hdCBZWVlZLU1NLUREDQpkZiA8LSBkZiAlPiUNCiAgbXV0YXRlKFRhbmdnYWwgPSBkbXkoVGFuZ2dhbCkpDQoNCiMgYjEsQmVyc2loa2FuIGtvbG9tIEhhcmdhIChoYXB1cyBzaW1ib2wgc2VsYWluIGFuZ2thKQ0KZGYgPC0gZGYgJT4lDQogIG11dGF0ZSgNCiAgICBIYXJnYSA9IHN0cl9yZW1vdmVfYWxsKGFzLmNoYXJhY3RlcihIYXJnYSksICJbXjAtOV0iKSwNCiAgICBIYXJnYSA9IGFzLm51bWVyaWMoSGFyZ2EpDQogICkNCg0KIyBiMixVYmFoIHRla3MgbWVuamFkaSBhbmdrYSBkaSBrb2xvbSBKdW1sYWgNCmRmIDwtIGRmICU+JQ0KICBtdXRhdGUoDQogICAgSnVtbGFoID0gdG9sb3dlcihKdW1sYWgpLA0KICAgIEp1bWxhaCA9IHJlY29kZShKdW1sYWgsDQogICAgICAgICAgICAgICAgICAgICJzYXR1IiA9ICIxIiwNCiAgICAgICAgICAgICAgICAgICAgImR1YSIgPSAiMiIsDQogICAgICAgICAgICAgICAgICAgICJ0aWdhIiA9ICIzIiwNCiAgICAgICAgICAgICAgICAgICAgImVtcGF0IiA9ICI0IiwNCiAgICAgICAgICAgICAgICAgICAgImxpbWEiID0gIjUiLA0KICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IGFzLmNoYXJhY3RlcihKdW1sYWgpKSwNCiAgICBKdW1sYWggPSBhcy5udW1lcmljKEp1bWxhaCkNCiAgKQ0KDQojIGMsSGl0dW5nIGtvbG9tIFRvdGFsDQpkZiA8LSBkZiAlPiUNCiAgbXV0YXRlKFRvdGFsID0gSGFyZ2EgKiBKdW1sYWgpDQoNCiMgZCxHYW50aSBuaWxhaSB0aWRhayB2YWxpZCBkaSBzZW11YSBrb2xvbSBrYXJha3Rlcg0KaW52YWxpZF92YWx1ZXMgPC0gYygiLSIsICJScCIsICJhbm9ueW1vdXMiLCAiYW5vbnltb3VzIikNCmRmIDwtIGRmICU+JQ0KICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIH5yZXBsYWNlKC4sIC4gJWluJSBpbnZhbGlkX3ZhbHVlcywgTkEpKSkNCg0KIyBlLEhhcHVzIGJhcmlzIHlhbmcgdGlkYWsgbWVtaWxpa2kgbmFtYSBwcm9kdWsNCmRmIDwtIGRmICU+JQ0KICBmaWx0ZXIoIWlzLm5hKFByb2R1ayksIFByb2R1ayAhPSAiIikNCg0KIyBUYW1waWxrYW4gaGFzaWwgYWtoaXINCmNhdCgiRGF0YSBzZXRlbGFoIGRpYmVyc2loa2FuOlxuIikNCnByaW50KGhlYWQoZGYpKQ0KYGBgDQojIyMgYy4pIERhdGEgVHJhbnNmb3JtYXRpb24NCg0KTGFrdWthbiB0cmFuc2Zvcm1hc2kgZGF0YSBzZWJhZ2FpIGJlcmlrdXQ6DQphLiBCdWF0IGtvbG9tIGJhcnUgQnVsYW4gYmVyZGFzYXJrYW4gdGFuZ2dhbCB0cmFuc2Frc2kuDQpiLiBIaXR1bmcgdG90YWwgcGVuanVhbGFuIChUb3RhbCkgcGVyIGthdGVnb3JpIHByb2R1ay4NCmMuIEhpdHVuZyBqdW1sYWggdHJhbnNha3NpIGRhcmkgc2V0aWFwIGtvdGEuDQpkLiBCdWF0IHJpbmdrYXNhbiBqdW1sYWggdG90YWwgcGVuanVhbGFuIHBlciBidWxhbi4NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQoNCiMgYS4gQnVhdCBrb2xvbSBiYXJ1IGJlcm5hbWEgJ0J1bGFuJyBiZXJkYXNhcmthbiB0YW5nZ2FsIHRyYW5zYWtzaQ0KYnVsYW5fbWFwIDwtIGMoIkphbnVhcmkiLCAiRmVicnVhcmkiLCAiTWFyZXQiKQ0KZGYkQnVsYW4gPC0gYnVsYW5fbWFwW21vbnRoKGRmJFRhbmdnYWwpXQ0KDQojIGIuIEhpdHVuZyB0b3RhbCBwZW5qdWFsYW4gdW50dWsgc2V0aWFwIGthdGVnb3JpIHByb2R1aw0KcGVuanVhbGFuX3Blcl9rYXRlZ29yaSA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoS2F0ZWdvcmkpICU+JQ0KICBzdW1tYXJpc2UoVG90YWwgPSBzdW0oVG90YWwsIG5hLnJtID0gVFJVRSkpICU+JQ0KICBhcnJhbmdlKGRlc2MoVG90YWwpKQ0KDQojIGMuIEhpdHVuZyBqdW1sYWggdHJhbnNha3NpIGRhcmkgc2V0aWFwIGtvdGENCnBlbmp1YWxhbl9wZXJfa290YSA8LSBkZiAlPiUNCiAgY291bnQoS290YSwgbmFtZSA9ICJKdW1sYWhfVHJhbnNha3NpIikgJT4lDQogIGFycmFuZ2UoZGVzYyhKdW1sYWhfVHJhbnNha3NpKSkNCg0KIyBkLiBCdWF0IHJpbmdrYXNhbiB0b3RhbCBwZW5qdWFsYW4gcGVyIGJ1bGFuDQpwZW5qdWFsYW5fcGVyX2J1bGFuIDwtIGRmICU+JQ0KICBncm91cF9ieShCdWxhbikgJT4lDQogIHN1bW1hcmlzZShUb3RhbCA9IHN1bShUb3RhbCwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhUb3RhbCkpDQoNCiMgVGFtcGlsa2FuIGhhc2lsDQpjYXQoIlRvdGFsIFBlbmp1YWxhbiBwZXIgS2F0ZWdvcmkgUHJvZHVrOlxuIikNCnByaW50KHBlbmp1YWxhbl9wZXJfa2F0ZWdvcmkpDQoNCmNhdCgiXG5KdW1sYWggVHJhbnNha3NpIHBlciBLb3RhOlxuIikNCnByaW50KHBlbmp1YWxhbl9wZXJfa290YSkNCg0KY2F0KCJcblRvdGFsIFBlbmp1YWxhbiBwZXIgQnVsYW46XG4iKQ0KcHJpbnQocGVuanVhbGFuX3Blcl9idWxhbikNCg0KYGBgDQojIyMgZC4pIFZpc3VhbGlzYXNpDQoNCioqR3JhZmlrIFRvdGFsIFBlbmp1YWxhbiBwZXIgS2F0ZWdvcmkqKg0KDQpgYGB7cn0NCiMgUGFzdGlrYW4gbGlicmFyeSBnZ3Bsb3QyIHN1ZGFoIGRpcGFuZ2dpbA0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIDEuIFVydXRrYW4gZGF0YSBkYXJpIHlhbmcgdG90YWxueWEgcGFsaW5nIGJlc2FyIGtlIHBhbGluZyBrZWNpbA0KcGVuanVhbGFuX3Blcl9rYXRlZ29yaSA8LSBwZW5qdWFsYW5fcGVyX2thdGVnb3JpICU+JQ0KICBhcnJhbmdlKGRlc2MoVG90YWwpKQ0KDQojIDIuIEJ1YXQgZ3JhZmlrIGJhdGFuZyBob3Jpem9udGFsDQpnZ3Bsb3QocGVuanVhbGFuX3Blcl9rYXRlZ29yaSwgYWVzKHggPSByZW9yZGVyKEthdGVnb3JpLCBUb3RhbCksIHkgPSBUb3RhbCkpICsNCiAgDQogICMgMy4gQnVhdCBiYXRhbmdueWENCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiZGFya29saXZlZ3JlZW4zIikgKw0KDQogICMgNC4gQmlraW4gc3VtYnUgWSBqYWRpIEthdGVnb3JpIGRhbiBzdW1idSBYIGphZGkgVG90YWwgKGRlbmdhbiBwb3Npc2kgaG9yaXpvbnRhbCkNCiAgY29vcmRfZmxpcCgpICsNCg0KICAjIDUuIFRhbWJhaGthbiBqdWR1bCBncmFmaWsNCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIiwNCiAgICAgICB4ID0gIkthdGVnb3JpIFByb2R1ayIsDQogICAgICAgeSA9ICJUb3RhbCBQZW5qdWFsYW4iKSArDQoNCiAgIyA2LiBCaWtpbiB0YW1waWxhbiBncmFmaWsgamFkaSByYXBpIGRhbiBzaW1wZWwNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpgYGB7cn0NCiMgSnVtbGFoIHRyYW5zYWtzaSBwZXIga290YSBzZXN1YWkgZGF0YSBrYW11DQpiYW5kdW5nIDwtIDMzDQpzdXJhYmF5YSA8LSAzMA0KamFrYXJ0YSA8LSAyOQ0KDQojIFRvdGFsIHNlbHVydWggdHJhbnNha3NpDQp0b3RhbCA8LSBiYW5kdW5nICsgc3VyYWJheWEgKyBqYWthcnRhDQoNCiMgSGl0dW5nIHBlcnNlbnRhc2VueWEgKGRpYnVsYXRrYW4gMSBhbmdrYSBkZXNpbWFsKQ0KcGVyc2VuX2JhbmR1bmcgPC0gcm91bmQoYmFuZHVuZyAvIHRvdGFsICogMTAwLCAxKQ0KcGVyc2VuX3N1cmFiYXlhIDwtIHJvdW5kKHN1cmFiYXlhIC8gdG90YWwgKiAxMDAsIDEpDQpwZXJzZW5famFrYXJ0YSA8LSByb3VuZChqYWthcnRhIC8gdG90YWwgKiAxMDAsIDEpDQoNCiMgVGFtcGlsa2FuIGhhc2lsDQpjYXQoIlBlcnNlbnRhc2UgQmFuZHVuZyA6IiwgcGVyc2VuX2JhbmR1bmcsICIlXG4iKQ0KY2F0KCJQZXJzZW50YXNlIFN1cmFiYXlhOiIsIHBlcnNlbl9zdXJhYmF5YSwgIiVcbiIpDQpjYXQoIlBlcnNlbnRhc2UgSmFrYXJ0YSA6IiwgcGVyc2VuX2pha2FydGEsICIlXG4iKQ0KDQpgYGANCg0KYGBge3J9DQojIERhdGEgdHJhbnNha3NpIHBlciBrb3RhDQprb3RhX3RyYW5zYWtzaSA8LSBjKDMzLCAzMCwgMjkpDQprb3RhX25hbWEgPC0gYygiQmFuZHVuZyIsICJTdXJhYmF5YSIsICJKYWthcnRhIikNCg0KIyBIaXR1bmcgdG90YWwgdHJhbnNha3NpDQp0b3RhbF90cmFuc2Frc2kgPC0gc3VtKGtvdGFfdHJhbnNha3NpKQ0KDQojIEhpdHVuZyBwZXJzZW50YXNlIHVudHVrIG1hc2luZy1tYXNpbmcga290YQ0KcGVyc2VuX2JhbmR1bmcgPC0gcm91bmQoa290YV90cmFuc2Frc2lbMV0gLyB0b3RhbF90cmFuc2Frc2kgKiAxMDAsIDEpDQpwZXJzZW5fc3VyYWJheWEgPC0gcm91bmQoa290YV90cmFuc2Frc2lbMl0gLyB0b3RhbF90cmFuc2Frc2kgKiAxMDAsIDEpDQpwZXJzZW5famFrYXJ0YSA8LSByb3VuZChrb3RhX3RyYW5zYWtzaVszXSAvIHRvdGFsX3RyYW5zYWtzaSAqIDEwMCwgMSkNCg0KIyBCdWF0IHZlY3RvciBwZXJzZW50YXNlDQpwZXJzZW4gPC0gYyhwZXJzZW5fYmFuZHVuZywgcGVyc2VuX3N1cmFiYXlhLCBwZXJzZW5famFrYXJ0YSkNCg0KIyBWaXN1YWxpc2FzaSBkZW5nYW4gcGllIGNoYXJ0DQpwaWUoa290YV90cmFuc2Frc2ksIA0KICAgIGxhYmVscyA9IHBhc3RlKGtvdGFfbmFtYSwgIlxuIiwgcGVyc2VuLCAiJSIpLCAgIyBNZW5hbWJhaGthbiBsYWJlbCBkZW5nYW4gbmFtYSBrb3RhIGRhbiBwZXJzZW50YXNlDQogICAgY29sID0gYygibGlnaHRibHVlIiwgImxpZ2h0Z3JlZW4iLCAibGlnaHRjb3JhbCIpLCAgIyBXYXJuYSBwaWUgY2hhcnQNCiAgICBtYWluID0gIlBlcnNlbnRhc2UgVHJhbnNha3NpIHBlciBLb3RhIiwgICAgICAgICAgIyBKdWR1bCBncmFmaWsNCiAgICByYWRpdXMgPSAxKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBVa3VyYW4gcGllIGNoYXJ0DQoNCmBgYA0KDQpgYGB7cn0NCiMgUGFzdGlrYW4ga29sb20gVGFuZ2dhbCBkYWxhbSBmb3JtYXQgRGF0ZQ0KZGYkVGFuZ2dhbCA8LSBhcy5EYXRlKGRmJFRhbmdnYWwsIGZvcm1hdD0iJVktJW0tJWQiKQ0KDQojIEJ1YXQga29sb20gQnVsYW5BbmdrYSBkYW4gQnVsYW5OYW1hIGRhcmkga29sb20gVGFuZ2dhbA0KZGYkQnVsYW5BbmdrYSA8LSBhcy5udW1lcmljKGZvcm1hdChkZiRUYW5nZ2FsLCAiJW0iKSkNCmRmJEJ1bGFuTmFtYSA8LSBmb3JtYXQoZGYkVGFuZ2dhbCwgIiVCIikNCg0KIyBGaWx0ZXIgaGFueWEgdW50dWsgYnVsYW4gSmFudWFyaSAoMSksIEZlYnJ1YXJpICgyKSwgZGFuIE1hcmV0ICgzKQ0KZGZfYnVsYW4xMjMgPC0gZGZbZGYkQnVsYW5BbmdrYSAlaW4lIGMoMSwgMiwgMyksIF0NCg0KIyBIaXR1bmcgdG90YWwgcGVuanVhbGFuIHBlciBidWxhbg0KbGlicmFyeShkcGx5cikNCnBlbmp1YWxhbl9idWxhbmFuIDwtIGRmX2J1bGFuMTIzICU+JQ0KICBncm91cF9ieShCdWxhbkFuZ2thLCBCdWxhbk5hbWEpICU+JQ0KICBzdW1tYXJpc2UoVG90YWwgPSBzdW0oVG90YWwsIG5hLnJtID0gVFJVRSkpICU+JQ0KICBhcnJhbmdlKEJ1bGFuQW5na2EpDQoNCiMgUGxvdCBncmFmaWsgZ2FyaXMNCmxpYnJhcnkoZ2dwbG90MikNCmdncGxvdChwZW5qdWFsYW5fYnVsYW5hbiwgYWVzKHg9QnVsYW5OYW1hLCB5PVRvdGFsLCBncm91cD0xKSkgKw0KICBnZW9tX2xpbmUoY29sb3I9J3JlZCcsIHNpemU9MSkgKw0KICBnZW9tX3BvaW50KGNvbG9yPSdyZWQnLCBzaXplPTMpICsNCiAgZ2d0aXRsZSgiVG90YWwgUGVuanVhbGFuIHBlciBCdWxhbiAoSmFuIC0gTWFyKSIpICsNCiAgeGxhYigiQnVsYW4iKSArDQogIHlsYWIoIlRvdGFsIFBlbmp1YWxhbiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQoNCg==