Tugas Ke 13 Pemrograman Sains Data

Profile

A. Combo

Ini menggabungkan data kategoris dan numerik untuk menunjukkan bagaimana variabel numerik berperilaku di berbagai kategori. Contohnya adalah diagram batang yang dikelompokkan, diagram kotak menurut kategori, diagram garis hubungan, diagram lolipop, diagram titik, dan peta panas.

1. Heatmap

Heatmap adalah representasi grafis data dimana nilai-nilai individual yang terdapat dalam matriks direpresentasikan sebagai warna. Heatmap banyak digunakan untuk memvisualisasikan data yang kompleks dengan mengodekan nilai-nilai data sebagai warna yang bervariasi, sehingga pola, korelasi, dan outlier lebih mudah dideteksi.

Karakteristik Utama Heatmap:

  • Nilai Kode Warna: Intensitas warna setiap sel sesuai dengan besarnya nilai yang diwakilinya, sering kali menggunakan gradien dari rendah ke tinggi.
  • Format Matriks: Biasanya ditampilkan sebagai kotak di mana baris kolom sesuai dengan variabel kategoris atau dimensi.
  • Pengenalan Pola: Membantu mengidentifikasi klaster, tren, dan anomali dalam kumpulan data besar dengan cepat.
  • Aplikasi Fleksibel: Umumnya digunakan dalam bidang seperti genomik, keuangan, pemasaran, dan analisis bisnis untuk memvisualisasikan korelasi, kinerja penjualan, atau tingkat aktivitas.
  • Varian Interaktif: Sering dipasangkan dengan interaktivitas (zoom, detail hover) di dasbor untuk eksplorasi yang lebih mendalam.
  • Kustomisasi: Palet warna, skala, dan metode penglompokan dapat disesuikan untuk kejelasan dan penekanan.
  • Berfokus pada Hubungan: Tidak seperti diagram batang sederhana, heatmap menunjukkan hubungan antara dua variabel kategoris berdasarkan nilai agregatnya.

Kode R (Heatmap)

library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
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(readr)
## Warning: package 'readr' was built under R version 4.4.3
# Baca data
df <- read_csv("Descriptive Visualizations.csv")
## New names:
## • `` -> `...1`
## Rows: 500 Columns: 25
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr   (8): Transaction_ID, Customer_ID, Product_Category, Product_ID, Region...
## dbl  (15): ...1, Quantity, Unit_Price, Discount, Delivery_Time, Total_Price,...
## lgl   (1): ID_HasPattern
## date  (1): Transaction_Date
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Agregasi data
agg_data <- df %>%
  group_by(Region, Product_Category) %>%
  summarise(TotalSales = sum(Total_Price, na.rm = TRUE))
## `summarise()` has grouped output by 'Region'. You can override using the
## `.groups` argument.
# Heatmap
ggplot(agg_data, aes(x = Region, y = Product_Category, fill = TotalSales)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  labs(title = "Heatmap Total Sales per Region & Product Category",
       x = "Region", y = "Product Category") +
  theme_minimal()

B. Hubungan

Visualisasi data relasi mengacu pada metode grafis yang dirancang untuk mengeksplorasi dan menyajikan koneksi, asosiasi, atau interaksi antara dua atau lebih variabel atau entitas. Visualisasi ini membantu mengungkap pola, tren, korelasi, atau jaringan yang mungkin tidak terlihat jelas dari data mentah saja.

1. Diagram Pencar

Diagram sebar adalah alat visualisasi data mendasar yang digunakan untuk menampilkan hubungan antara dua variabel kontinu. Setiap titik pada diagram mewakili suatu pengamatan dengan posisi yang ditentukan oleh nilai kedua variabel.

Karakteristik Utama dari Scatter Plot:

  • Hubungan bivariat: Menunjukkan bagaimana satu variabel berubah terhadap variabel lainnya.
  • Mendeteksi korelasi: Membantu mengidentifikasi korelasi positif, negatif, atau tidak ada korelasi.
  • Deteksi outlier: Mengungkapkan titik data yang tidak biasa.
  • Mendukung estetika tambahan: Warna, ukuran, dan bentuk dapat mewakili lebih banyak variabel untuk wawasan multidimensi
  • Umum dalam analisis data eksploratori (EDA): Menyediakan ringkasan visual cepat tentang hubungan data.

Kode R (Diagram Pencar)

library(ggplot2)
data <- read.csv("Descriptive Visualizations.csv")

ggplot(data, aes(x = Quantity, y = Unit_Price)) +
  geom_point(alpha = 0.6, color = "steelblue") +
  labs(title = "Scatter Plot: Quantity vs Unit Price",
       x = "Quantity",
       y = "Unit Price") +
  theme_minimal()

2. Bagan Gelembung

Bagan Gelembung merupakan perluasan dari diagram sebar yang memvisualisasikan tiga dimensi data. Diagram ini memplot titik-titik seperti diagram sebar tetapi menggunakan ukuran setiap gelembung untuk mewakili variabel ketiga, sehingga memungkinkan wawasan yang lebih kaya tentang hubungan.

Kode R (Bagan Gelembung)

library(ggplot2)
data <- read.csv("Descriptive Visualizations.csv")

ggplot(data, aes(x = Quantity, y = Unit_Price, size = Total_Price, color = Product_Category)) +
  geom_point(alpha = 0.6) +
  scale_size_continuous(range = c(2, 12)) +
  labs(title = "Bubble Chart: Quantity vs Unit Price (size = Total Price)",
       x = "Quantity",
       y = "Unit Price",
       size = "Total Price") +
  theme_minimal()

3.Matriks Korelasi

Matriks Korelasi adalah tabel yang menunjukkan koefisien korelasi antara banyak variabel. Setiap sel dalam matriks mewakili korelasi antara dua variabel, yang biasanya diukur dengan koefisien korelasi Pearson. Matriks ini membantu Anda memahami hubungan, pola, dan ketergantungan dalam data multivariat dengan cepat.

Karakteristik Utama:

  • Nilai berkisar dari-1 hingga +1:
  • +1 berarti korelasi positif sempurna,
  • -1 berarti korelasi negatif sempurna,
  • O berarti tidak ada korelasi linear.
  • Berguna untuk mendeteksi multikolinearitas dan hubungan fitur dalam analisis data.
  • Sering divisualisasikan dengan peta panas atau matriks berwarna, di mana warna menunjukkan kekuatan dan arah korelasi.
  • Penting dalam bidang seperti keuangan, ilmu kesehatan, dan pemilihan fitur pembelajaran mesin.

Kode R (Matriks Korelasi)

# Load libraries
library(ggplot2)
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.4.3
# Baca data
df <- read.csv("Descriptive Visualizations.csv", stringsAsFactors = FALSE)

# Konversi ke numerik
df$Total_Price <- as.numeric(df$Total_Price)
df$Quantity <- as.numeric(df$Quantity)
df$Price_per_Unit <- as.numeric(df$Price_per_Unit)

# Pilih kolom numerik dan hitung korelasi
df_num <- na.omit(df[, c("Total_Price", "Quantity", "Price_per_Unit")])
cor_matrix <- cor(df_num, use = "complete.obs")

# Reshape untuk ggplot
cor_melted <- melt(cor_matrix)

# Plot korelasi
ggplot(cor_melted, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(value, 2)), size = 5) +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", 
                       midpoint = 0, limit = c(-1, 1), space = "Lab", 
                       name = "Correlation") +
  labs(title = "Correlation Matrix") +
  theme_minimal(base_size = 15)

C. Seri Waktu

Visualisasi Deret Waktu adalah representasi grafis dari titik data yang dikumpulkan atau direkam pada interval waktu yang berurutan. Visualisasi ini penting untuk mengidentifikasi tren, pola musiman, siklus, dan anomali dari waktu ke waktu.

Karakteristik Utama:

  • Pengurutan Temporal: Titik data diurutkan berdasarkan waktu (detik, menit, hari, bulan, tahun).
  • Deteksi Tren: Membantu mengidentifikasi peningkatan atau penurunan data jangka panjang.
  • Musiman: Mengungkapkan pola atau siklus berulang dalam periode tertentu.
  • Anomali: Mendeteksi outlier atau perubahan yang tidak biasa.
  • Plot Umum: Bagan garis, bagan area, dan grafik bertumpuk.
  • Deret Waktu Multivariat: Beberapa deret waktu terkait dapat diplot menggunakan aspek atau warna untuk dibandingkan.

1. Grafik Garis

Bagan Garis adalah salah satu vcara palingumum dan intuitif untuk memvisualisasikan titik-titik data yang dihubungkan dengan garis lurus, terutama efektif untuk menunjukkan dari waktu ke waktu.

Kode R (Grafik Garis)

library(ggplot2)
library(dplyr)
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
library(readr)

# Membaca data
df <- read_csv("Descriptive Visualizations.csv")
## New names:
## • `` -> `...1`
## Rows: 500 Columns: 25
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr   (8): Transaction_ID, Customer_ID, Product_Category, Product_ID, Region...
## dbl  (15): ...1, Quantity, Unit_Price, Discount, Delivery_Time, Total_Price,...
## lgl   (1): ID_HasPattern
## date  (1): Transaction_Date
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Mengolah data
df <- df %>%
  mutate(Transaction_Date = as.Date(Transaction_Date),
         Month = floor_date(Transaction_Date, "month")) %>%
  group_by(Month) %>%
  summarise(Avg_Discount = mean(Discount, na.rm = TRUE))

# Membuat grafik garis
ggplot(df, aes(x = Month, y = Avg_Discount)) +
  geom_line(color = "darkred", size = 1) +
  labs(title = "Rata-Rata Diskon per Bulan",
       x = "Bulan",
       y = "Rata-Rata Diskon") +
  theme_minimal()
## 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.

2. Bagan Area

Bagan Area adalah variasi bagan garis di mana area antara garus dan sumbu diisi dengan warna. Bagan ini menekankan besarnya nilai dari waktu ke wakaktu dan berguna untuk memvisualisasikan kuantitas atau proporsi kumulatif.

Kode R (Bagan Area)

library(ggplot2)
library(dplyr)
library(lubridate)
library(readr)

# Membaca data
df <- read_csv("Descriptive Visualizations.csv")
## New names:
## Rows: 500 Columns: 25
## ── Column specification
## ──────────────────────────────────────────────────────── Delimiter: "," chr
## (8): Transaction_ID, Customer_ID, Product_Category, Product_ID, Region... dbl
## (15): ...1, Quantity, Unit_Price, Discount, Delivery_Time, Total_Price,... lgl
## (1): ID_HasPattern date (1): Transaction_Date
## ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
## Specify the column types or set `show_col_types = FALSE` to quiet this message.
## • `` -> `...1`
# Mengolah data
df <- df %>%
  mutate(Transaction_Date = as.Date(Transaction_Date),
         Month = floor_date(Transaction_Date, "month"),
         Sales = Quantity * Unit_Price) %>%
  group_by(Month, Product_Category) %>%
  summarise(Total_Sales = sum(Sales, na.rm = TRUE)) %>%
  ungroup()
## `summarise()` has grouped output by 'Month'. You can override using the
## `.groups` argument.
# Membuat bagan area
ggplot(df, aes(x = Month, y = Total_Sales, fill = Product_Category)) +
  geom_area(alpha = 0.8) +
  labs(title = "Bagan Area Penjualan per Kategori Produk",
       x = "Bulan",
       y = "Total Penjualan") +
  theme_minimal()

LS0tDQp0aXRsZTogIlR1Z2FzIEtlIDEzIFBlbXJvZ3JhbWFuIFNhaW5zIERhdGEiDQoNCmF1dGhvcjogDQogICAgLSAiTmFiaWxhIEFuZ2dpdGEgUHV0cmkiDQogICAgDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOg0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdGh1bWJuYWlsczogdHJ1ZQ0KICAgIGxpZ2h0Ym94OiB0cnVlDQogICAgZ2FsbGVyeTogdHJ1ZQ0KICAgIGxpYl9kaXI6IGxpYnMNCiAgICBkZl9wcmludDogInBhZ2VkIg0KICAgIGNvZGVfZm9sZGluZzogInNob3ciDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgY3NzOiAic3R5bGUvU3R5bGUuY3NzIg0KLS0tDQo8aW1nIHNyYz0iaW1nL3Byb2ZpbGUuanBnIiBhbHQ9IlByb2ZpbGUiIGlkPSJsb2dvLXV0YW1hIiBzdHlsZT0id2lkdGg6MzAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ii8+DQoNCg0KIyAqKkEuIENvbWJvKioNCg0KSW5pIG1lbmdnYWJ1bmdrYW4gZGF0YSBrYXRlZ29yaXMgZGFuIG51bWVyaWsgdW50dWsgbWVudW5qdWtrYW4gYmFnYWltYW5hIHZhcmlhYmVsIG51bWVyaWsgYmVycGVyaWxha3UgZGkgYmVyYmFnYWkga2F0ZWdvcmkuIENvbnRvaG55YSBhZGFsYWggZGlhZ3JhbSBiYXRhbmcgeWFuZyBkaWtlbG9tcG9ra2FuLCBkaWFncmFtIGtvdGFrIG1lbnVydXQga2F0ZWdvcmksIGRpYWdyYW0gZ2FyaXMgaHVidW5nYW4sIGRpYWdyYW0gbG9saXBvcCwgZGlhZ3JhbSB0aXRpaywgZGFuIHBldGEgcGFuYXMuDQoNCiMjICoqMS4gSGVhdG1hcCoqDQoNCkhlYXRtYXAgYWRhbGFoIHJlcHJlc2VudGFzaSBncmFmaXMgZGF0YSBkaW1hbmEgbmlsYWktbmlsYWkgaW5kaXZpZHVhbCB5YW5nIHRlcmRhcGF0IGRhbGFtIG1hdHJpa3MgZGlyZXByZXNlbnRhc2lrYW4gc2ViYWdhaSB3YXJuYS4gSGVhdG1hcCBiYW55YWsgZGlndW5ha2FuIHVudHVrIG1lbXZpc3VhbGlzYXNpa2FuIGRhdGEgeWFuZyBrb21wbGVrcyBkZW5nYW4gbWVuZ29kZWthbiBuaWxhaS1uaWxhaSBkYXRhIHNlYmFnYWkgd2FybmEgeWFuZyBiZXJ2YXJpYXNpLCBzZWhpbmdnYSBwb2xhLCBrb3JlbGFzaSwgZGFuIG91dGxpZXIgbGViaWggbXVkYWggZGlkZXRla3NpLg0KDQoqKkthcmFrdGVyaXN0aWsgVXRhbWEgSGVhdG1hcCoqOg0KDQotIE5pbGFpIEtvZGUgV2FybmE6IEludGVuc2l0YXMgd2FybmEgc2V0aWFwIHNlbCBzZXN1YWkgZGVuZ2FuIGJlc2FybnlhIG5pbGFpIHlhbmcgZGl3YWtpbGlueWEsIHNlcmluZyBrYWxpIG1lbmdndW5ha2FuIGdyYWRpZW4gZGFyaSByZW5kYWgga2UgdGluZ2dpLg0KLSBGb3JtYXQgTWF0cmlrczogQmlhc2FueWEgZGl0YW1waWxrYW4gc2ViYWdhaSBrb3RhayBkaSBtYW5hIGJhcmlzIGtvbG9tIHNlc3VhaSBkZW5nYW4gdmFyaWFiZWwga2F0ZWdvcmlzIGF0YXUgZGltZW5zaS4gDQotIFBlbmdlbmFsYW4gUG9sYTogTWVtYmFudHUgbWVuZ2lkZW50aWZpa2FzaSBrbGFzdGVyLCB0cmVuLCBkYW4gYW5vbWFsaSBkYWxhbSBrdW1wdWxhbiBkYXRhIGJlc2FyIGRlbmdhbiBjZXBhdC4NCi0gQXBsaWthc2kgRmxla3NpYmVsOiBVbXVtbnlhIGRpZ3VuYWthbiBkYWxhbSBiaWRhbmcgc2VwZXJ0aSBnZW5vbWlrLCBrZXVhbmdhbiwgcGVtYXNhcmFuLCBkYW4gYW5hbGlzaXMgYmlzbmlzIHVudHVrIG1lbXZpc3VhbGlzYXNpa2FuIGtvcmVsYXNpLCBraW5lcmphIHBlbmp1YWxhbiwgYXRhdSB0aW5na2F0IGFrdGl2aXRhcy4NCi0gVmFyaWFuIEludGVyYWt0aWY6IFNlcmluZyBkaXBhc2FuZ2thbiBkZW5nYW4gaW50ZXJha3Rpdml0YXMgKHpvb20sIGRldGFpbCBob3ZlcikgZGkgZGFzYm9yIHVudHVrIGVrc3Bsb3Jhc2kgeWFuZyBsZWJpaCBtZW5kYWxhbS4NCi0gS3VzdG9taXNhc2k6IFBhbGV0IHdhcm5hLCBza2FsYSwgZGFuIG1ldG9kZSBwZW5nbG9tcG9rYW4gZGFwYXQgZGlzZXN1aWthbiB1bnR1ayBrZWplbGFzYW4gZGFuIHBlbmVrYW5hbi4NCi0gQmVyZm9rdXMgcGFkYSBIdWJ1bmdhbjogVGlkYWsgc2VwZXJ0aSBkaWFncmFtIGJhdGFuZyBzZWRlcmhhbmEsIGhlYXRtYXAgbWVudW5qdWtrYW4gaHVidW5nYW4gYW50YXJhIGR1YSB2YXJpYWJlbCBrYXRlZ29yaXMgYmVyZGFzYXJrYW4gbmlsYWkgYWdyZWdhdG55YS4NCg0KIyMjICoqS29kZSBSIChIZWF0bWFwKSoqDQpgYGB7ciwgZWNobz1UUlVFLH0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWRyKQ0KDQojIEJhY2EgZGF0YQ0KZGYgPC0gcmVhZF9jc3YoIkRlc2NyaXB0aXZlIFZpc3VhbGl6YXRpb25zLmNzdiIpDQoNCiMgQWdyZWdhc2kgZGF0YQ0KYWdnX2RhdGEgPC0gZGYgJT4lDQogIGdyb3VwX2J5KFJlZ2lvbiwgUHJvZHVjdF9DYXRlZ29yeSkgJT4lDQogIHN1bW1hcmlzZShUb3RhbFNhbGVzID0gc3VtKFRvdGFsX1ByaWNlLCBuYS5ybSA9IFRSVUUpKQ0KDQojIEhlYXRtYXANCmdncGxvdChhZ2dfZGF0YSwgYWVzKHggPSBSZWdpb24sIHkgPSBQcm9kdWN0X0NhdGVnb3J5LCBmaWxsID0gVG90YWxTYWxlcykpICsNCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJsaWdodGJsdWUiLCBoaWdoID0gImRhcmtibHVlIikgKw0KICBsYWJzKHRpdGxlID0gIkhlYXRtYXAgVG90YWwgU2FsZXMgcGVyIFJlZ2lvbiAmIFByb2R1Y3QgQ2F0ZWdvcnkiLA0KICAgICAgIHggPSAiUmVnaW9uIiwgeSA9ICJQcm9kdWN0IENhdGVnb3J5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojICoqQi4gSHVidW5nYW4qKg0KDQpWaXN1YWxpc2FzaSBkYXRhIHJlbGFzaSBtZW5nYWN1IHBhZGEgbWV0b2RlIGdyYWZpcyB5YW5nIGRpcmFuY2FuZyB1bnR1ayBtZW5nZWtzcGxvcmFzaSBkYW4gbWVueWFqaWthbiBrb25la3NpLCBhc29zaWFzaSwgYXRhdSBpbnRlcmFrc2kgYW50YXJhIGR1YSBhdGF1IGxlYmloIHZhcmlhYmVsIGF0YXUgZW50aXRhcy4gVmlzdWFsaXNhc2kgaW5pIG1lbWJhbnR1IG1lbmd1bmdrYXAgcG9sYSwgdHJlbiwga29yZWxhc2ksIGF0YXUgamFyaW5nYW4geWFuZyBtdW5na2luIHRpZGFrIHRlcmxpaGF0IGplbGFzIGRhcmkgZGF0YSBtZW50YWggc2FqYS4NCg0KIyMgKioxLiBEaWFncmFtIFBlbmNhcioqDQoNCkRpYWdyYW0gc2ViYXIgYWRhbGFoIGFsYXQgdmlzdWFsaXNhc2kgZGF0YSBtZW5kYXNhciB5YW5nIGRpZ3VuYWthbiB1bnR1ayBtZW5hbXBpbGthbiBodWJ1bmdhbiBhbnRhcmEgZHVhIHZhcmlhYmVsIGtvbnRpbnUuIFNldGlhcCB0aXRpayBwYWRhIGRpYWdyYW0gbWV3YWtpbGkgc3VhdHUgcGVuZ2FtYXRhbiBkZW5nYW4gcG9zaXNpIHlhbmcgZGl0ZW50dWthbiBvbGVoIG5pbGFpIGtlZHVhIHZhcmlhYmVsLg0KDQoqKkthcmFrdGVyaXN0aWsgVXRhbWEgZGFyaSBTY2F0dGVyIFBsb3QqKjoNCg0KLSBIdWJ1bmdhbiBiaXZhcmlhdDogTWVudW5qdWtrYW4gYmFnYWltYW5hIHNhdHUgdmFyaWFiZWwgYmVydWJhaCB0ZXJoYWRhcCB2YXJpYWJlbCBsYWlubnlhLg0KLSBNZW5kZXRla3NpIGtvcmVsYXNpOiBNZW1iYW50dSBtZW5naWRlbnRpZmlrYXNpIGtvcmVsYXNpIHBvc2l0aWYsIG5lZ2F0aWYsIGF0YXUgdGlkYWsgYWRhIGtvcmVsYXNpLg0KLSBEZXRla3NpIG91dGxpZXI6IE1lbmd1bmdrYXBrYW4gdGl0aWsgZGF0YSB5YW5nIHRpZGFrIGJpYXNhLg0KLSBNZW5kdWt1bmcgZXN0ZXRpa2EgdGFtYmFoYW46IFdhcm5hLCB1a3VyYW4sIGRhbiBiZW50dWsgZGFwYXQgbWV3YWtpbGkgbGViaWggYmFueWFrIHZhcmlhYmVsIHVudHVrIHdhd2FzYW4gbXVsdGlkaW1lbnNpDQotIFVtdW0gZGFsYW0gYW5hbGlzaXMgZGF0YSBla3NwbG9yYXRvcmkgKEVEQSk6IE1lbnllZGlha2FuIHJpbmdrYXNhbiB2aXN1YWwgY2VwYXQgdGVudGFuZ8KgaHVidW5nYW7CoGRhdGEuDQoNCiMjIyAqKktvZGUgUiAoRGlhZ3JhbSBQZW5jYXIpKioNCmBgYHtyLCBlY2hvPVRSVUUsfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGF0YSA8LSByZWFkLmNzdigiRGVzY3JpcHRpdmUgVmlzdWFsaXphdGlvbnMuY3N2IikNCg0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gUXVhbnRpdHksIHkgPSBVbml0X1ByaWNlKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC42LCBjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGxhYnModGl0bGUgPSAiU2NhdHRlciBQbG90OiBRdWFudGl0eSB2cyBVbml0IFByaWNlIiwNCiAgICAgICB4ID0gIlF1YW50aXR5IiwNCiAgICAgICB5ID0gIlVuaXQgUHJpY2UiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KIyMgKioyLiBCYWdhbiBHZWxlbWJ1bmcqKg0KDQpCYWdhbiBHZWxlbWJ1bmcgbWVydXBha2FuIHBlcmx1YXNhbiBkYXJpIGRpYWdyYW0gc2ViYXIgeWFuZyBtZW12aXN1YWxpc2FzaWthbiB0aWdhIGRpbWVuc2kgZGF0YS4gRGlhZ3JhbSBpbmkgbWVtcGxvdCB0aXRpay10aXRpayBzZXBlcnRpIGRpYWdyYW0gc2ViYXIgdGV0YXBpIG1lbmdndW5ha2FuIHVrdXJhbiBzZXRpYXAgZ2VsZW1idW5nIHVudHVrIG1ld2FraWxpIHZhcmlhYmVsIGtldGlnYSwgc2VoaW5nZ2EgbWVtdW5na2lua2FuIHdhd2FzYW4geWFuZyBsZWJpaCBrYXlhIHRlbnRhbmcgaHVidW5nYW4uDQoNCiMjIyAqKktvZGUgUiAoQmFnYW4gR2VsZW1idW5nKSoqDQpgYGB7ciwgZWNobz1UUlVFLH0NCmxpYnJhcnkoZ2dwbG90MikNCmRhdGEgPC0gcmVhZC5jc3YoIkRlc2NyaXB0aXZlIFZpc3VhbGl6YXRpb25zLmNzdiIpDQoNCmdncGxvdChkYXRhLCBhZXMoeCA9IFF1YW50aXR5LCB5ID0gVW5pdF9QcmljZSwgc2l6ZSA9IFRvdGFsX1ByaWNlLCBjb2xvciA9IFByb2R1Y3RfQ2F0ZWdvcnkpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsNCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCAxMikpICsNCiAgbGFicyh0aXRsZSA9ICJCdWJibGUgQ2hhcnQ6IFF1YW50aXR5IHZzIFVuaXQgUHJpY2UgKHNpemUgPSBUb3RhbCBQcmljZSkiLA0KICAgICAgIHggPSAiUXVhbnRpdHkiLA0KICAgICAgIHkgPSAiVW5pdCBQcmljZSIsDQogICAgICAgc2l6ZSA9ICJUb3RhbCBQcmljZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KIyMgKiozLk1hdHJpa3MgS29yZWxhc2kqKg0KDQpNYXRyaWtzIEtvcmVsYXNpIGFkYWxhaCB0YWJlbCB5YW5nIG1lbnVuanVra2FuIGtvZWZpc2llbiBrb3JlbGFzaSBhbnRhcmEgYmFueWFrIHZhcmlhYmVsLiBTZXRpYXAgc2VsIGRhbGFtIG1hdHJpa3MgbWV3YWtpbGkga29yZWxhc2kgYW50YXJhIGR1YSB2YXJpYWJlbCwgeWFuZyBiaWFzYW55YSBkaXVrdXIgZGVuZ2FuIGtvZWZpc2llbiBrb3JlbGFzaSBQZWFyc29uLiBNYXRyaWtzIGluaSBtZW1iYW50dSBBbmRhIG1lbWFoYW1pIGh1YnVuZ2FuLCBwb2xhLCBkYW4ga2V0ZXJnYW50dW5nYW4gZGFsYW0gZGF0YSBtdWx0aXZhcmlhdCBkZW5nYW4gY2VwYXQuDQoNCioqS2FyYWt0ZXJpc3RpayBVdGFtYSoqOg0KDQotIE5pbGFpIGJlcmtpc2FyIGRhcmktMSBoaW5nZ2EgKzE6DQotICsxIGJlcmFydGkga29yZWxhc2kgcG9zaXRpZiBzZW1wdXJuYSwNCi0gLTEgYmVyYXJ0aSBrb3JlbGFzaSBuZWdhdGlmIHNlbXB1cm5hLA0KLSBPIGJlcmFydGkgdGlkYWsgYWRhIGtvcmVsYXNpIGxpbmVhci4NCi0gQmVyZ3VuYSB1bnR1ayBtZW5kZXRla3NpIG11bHRpa29saW5lYXJpdGFzIGRhbiBodWJ1bmdhbiBmaXR1ciBkYWxhbSBhbmFsaXNpcyBkYXRhLg0KLSBTZXJpbmcgZGl2aXN1YWxpc2FzaWthbiBkZW5nYW4gcGV0YSBwYW5hcyBhdGF1IG1hdHJpa3MgYmVyd2FybmEsIGRpIG1hbmEgd2FybmEgbWVudW5qdWtrYW4ga2VrdWF0YW4gZGFuIGFyYWgga29yZWxhc2kuDQotIFBlbnRpbmcgZGFsYW0gYmlkYW5nIHNlcGVydGkga2V1YW5nYW4sIGlsbXUga2VzZWhhdGFuLCBkYW4gcGVtaWxpaGFuIGZpdHVyIHBlbWJlbGFqYXJhbsKgbWVzaW4uDQoNCiMjIyAqKktvZGUgUiAoTWF0cmlrcyBLb3JlbGFzaSkqKg0KYGBge3IsIGVjaG89VFJVRSx9DQojIExvYWQgbGlicmFyaWVzDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KDQojIEJhY2EgZGF0YQ0KZGYgPC0gcmVhZC5jc3YoIkRlc2NyaXB0aXZlIFZpc3VhbGl6YXRpb25zLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCg0KIyBLb252ZXJzaSBrZSBudW1lcmlrDQpkZiRUb3RhbF9QcmljZSA8LSBhcy5udW1lcmljKGRmJFRvdGFsX1ByaWNlKQ0KZGYkUXVhbnRpdHkgPC0gYXMubnVtZXJpYyhkZiRRdWFudGl0eSkNCmRmJFByaWNlX3Blcl9Vbml0IDwtIGFzLm51bWVyaWMoZGYkUHJpY2VfcGVyX1VuaXQpDQoNCiMgUGlsaWgga29sb20gbnVtZXJpayBkYW4gaGl0dW5nIGtvcmVsYXNpDQpkZl9udW0gPC0gbmEub21pdChkZlssIGMoIlRvdGFsX1ByaWNlIiwgIlF1YW50aXR5IiwgIlByaWNlX3Blcl9Vbml0IildKQ0KY29yX21hdHJpeCA8LSBjb3IoZGZfbnVtLCB1c2UgPSAiY29tcGxldGUub2JzIikNCg0KIyBSZXNoYXBlIHVudHVrIGdncGxvdA0KY29yX21lbHRlZCA8LSBtZWx0KGNvcl9tYXRyaXgpDQoNCiMgUGxvdCBrb3JlbGFzaQ0KZ2dwbG90KGNvcl9tZWx0ZWQsIGFlcyh4ID0gVmFyMSwgeSA9IFZhcjIsIGZpbGwgPSB2YWx1ZSkpICsNCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQodmFsdWUsIDIpKSwgc2l6ZSA9IDUpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBoaWdoID0gInJlZCIsIG1pZCA9ICJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICBtaWRwb2ludCA9IDAsIGxpbWl0ID0gYygtMSwgMSksIHNwYWNlID0gIkxhYiIsIA0KICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkNvcnJlbGF0aW9uIikgKw0KICBsYWJzKHRpdGxlID0gIkNvcnJlbGF0aW9uIE1hdHJpeCIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNSkNCmBgYA0KDQoNCiMgKipDLiBTZXJpIFdha3R1KioNCg0KVmlzdWFsaXNhc2kgRGVyZXQgV2FrdHUgYWRhbGFoIHJlcHJlc2VudGFzaSBncmFmaXMgZGFyaSB0aXRpayBkYXRhIHlhbmcgZGlrdW1wdWxrYW4gYXRhdSBkaXJla2FtIHBhZGEgaW50ZXJ2YWwgd2FrdHUgeWFuZyBiZXJ1cnV0YW4uIFZpc3VhbGlzYXNpIGluaSBwZW50aW5nIHVudHVrIG1lbmdpZGVudGlmaWthc2kgdHJlbiwgcG9sYSBtdXNpbWFuLCBzaWtsdXMsIGRhbiBhbm9tYWxpIGRhcmkgd2FrdHUga2Ugd2FrdHUuDQoNCioqS2FyYWt0ZXJpc3RpayBVdGFtYSoqOg0KDQotIFBlbmd1cnV0YW4gVGVtcG9yYWw6IFRpdGlrIGRhdGEgZGl1cnV0a2FuIGJlcmRhc2Fya2FuIHdha3R1IChkZXRpaywgbWVuaXQsIGhhcmksIGJ1bGFuLCB0YWh1bikuDQotIERldGVrc2kgVHJlbjogTWVtYmFudHUgbWVuZ2lkZW50aWZpa2FzaSBwZW5pbmdrYXRhbiBhdGF1IHBlbnVydW5hbiBkYXRhIGphbmdrYSBwYW5qYW5nLg0KLSBNdXNpbWFuOiBNZW5ndW5na2Fwa2FuIHBvbGEgYXRhdSBzaWtsdXMgYmVydWxhbmcgZGFsYW0gcGVyaW9kZSB0ZXJ0ZW50dS4NCi0gQW5vbWFsaTogTWVuZGV0ZWtzaSBvdXRsaWVyIGF0YXUgcGVydWJhaGFuIHlhbmcgdGlkYWsgYmlhc2EuDQotIFBsb3QgVW11bTogQmFnYW4gZ2FyaXMsIGJhZ2FuIGFyZWEsIGRhbiBncmFmaWsgYmVydHVtcHVrLg0KLSBEZXJldCBXYWt0dSBNdWx0aXZhcmlhdDogQmViZXJhcGEgZGVyZXQgd2FrdHUgdGVya2FpdCBkYXBhdCBkaXBsb3QgbWVuZ2d1bmFrYW4gYXNwZWsgYXRhdSB3YXJuYSB1bnR1a8KgZGliYW5kaW5na2FuLg0KDQojIyAqKjEuIEdyYWZpayBHYXJpcyoqDQoNCkJhZ2FuIEdhcmlzIGFkYWxhaCBzYWxhaCBzYXR1IHZjYXJhIHBhbGluZ3VtdW0gZGFuIGludHVpdGlmIHVudHVrIG1lbXZpc3VhbGlzYXNpa2FuIHRpdGlrLXRpdGlrIGRhdGEgeWFuZyBkaWh1YnVuZ2thbiBkZW5nYW4gZ2FyaXMgbHVydXMsIHRlcnV0YW1hIGVmZWt0aWYgdW50dWsgbWVudW5qdWtrYW4gZGFyaSB3YWt0dSBrZSB3YWt0dS4NCg0KIyMjICoqS29kZSBSIChHcmFmaWsgR2FyaXMpKioNCmBgYHtyLCBlY2hvPVRSVUUsfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShyZWFkcikNCg0KIyBNZW1iYWNhIGRhdGENCmRmIDwtIHJlYWRfY3N2KCJEZXNjcmlwdGl2ZSBWaXN1YWxpemF0aW9ucy5jc3YiKQ0KDQojIE1lbmdvbGFoIGRhdGENCmRmIDwtIGRmICU+JQ0KICBtdXRhdGUoVHJhbnNhY3Rpb25fRGF0ZSA9IGFzLkRhdGUoVHJhbnNhY3Rpb25fRGF0ZSksDQogICAgICAgICBNb250aCA9IGZsb29yX2RhdGUoVHJhbnNhY3Rpb25fRGF0ZSwgIm1vbnRoIikpICU+JQ0KICBncm91cF9ieShNb250aCkgJT4lDQogIHN1bW1hcmlzZShBdmdfRGlzY291bnQgPSBtZWFuKERpc2NvdW50LCBuYS5ybSA9IFRSVUUpKQ0KDQojIE1lbWJ1YXQgZ3JhZmlrIGdhcmlzDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gTW9udGgsIHkgPSBBdmdfRGlzY291bnQpKSArDQogIGdlb21fbGluZShjb2xvciA9ICJkYXJrcmVkIiwgc2l6ZSA9IDEpICsNCiAgbGFicyh0aXRsZSA9ICJSYXRhLVJhdGEgRGlza29uIHBlciBCdWxhbiIsDQogICAgICAgeCA9ICJCdWxhbiIsDQogICAgICAgeSA9ICJSYXRhLVJhdGEgRGlza29uIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCiMjICoqMi4gQmFnYW4gQXJlYSoqDQoNCkJhZ2FuIEFyZWEgYWRhbGFoIHZhcmlhc2kgYmFnYW4gZ2FyaXMgZGkgbWFuYSBhcmVhIGFudGFyYSBnYXJ1cyBkYW4gc3VtYnUgZGlpc2kgZGVuZ2FuIHdhcm5hLiBCYWdhbiBpbmkgbWVuZWthbmthbiBiZXNhcm55YSBuaWxhaSBkYXJpIHdha3R1IGtlIHdha2FrdHUgZGFuIGJlcmd1bmEgdW50dWsgbWVtdmlzdWFsaXNhc2lrYW4ga3VhbnRpdGFzIGF0YXUgcHJvcG9yc2kga3VtdWxhdGlmLg0KDQojIyMgKipLb2RlIFIgKEJhZ2FuIEFyZWEpKioNCmBgYHtyLCBlY2hvPVRSVUUsfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShyZWFkcikNCg0KIyBNZW1iYWNhIGRhdGENCmRmIDwtIHJlYWRfY3N2KCJEZXNjcmlwdGl2ZSBWaXN1YWxpemF0aW9ucy5jc3YiKQ0KDQojIE1lbmdvbGFoIGRhdGENCmRmIDwtIGRmICU+JQ0KICBtdXRhdGUoVHJhbnNhY3Rpb25fRGF0ZSA9IGFzLkRhdGUoVHJhbnNhY3Rpb25fRGF0ZSksDQogICAgICAgICBNb250aCA9IGZsb29yX2RhdGUoVHJhbnNhY3Rpb25fRGF0ZSwgIm1vbnRoIiksDQogICAgICAgICBTYWxlcyA9IFF1YW50aXR5ICogVW5pdF9QcmljZSkgJT4lDQogIGdyb3VwX2J5KE1vbnRoLCBQcm9kdWN0X0NhdGVnb3J5KSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX1NhbGVzID0gc3VtKFNhbGVzLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgTWVtYnVhdCBiYWdhbiBhcmVhDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gTW9udGgsIHkgPSBUb3RhbF9TYWxlcywgZmlsbCA9IFByb2R1Y3RfQ2F0ZWdvcnkpKSArDQogIGdlb21fYXJlYShhbHBoYSA9IDAuOCkgKw0KICBsYWJzKHRpdGxlID0gIkJhZ2FuIEFyZWEgUGVuanVhbGFuIHBlciBLYXRlZ29yaSBQcm9kdWsiLA0KICAgICAgIHggPSAiQnVsYW4iLA0KICAgICAgIHkgPSAiVG90YWwgUGVuanVhbGFuIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA==