Data Science Programming
Sub-Bab 09
## X Transaction_ID Transaction_Date Customer_ID Product_Category Product_ID
## 1 1 7zmPHxF7XfN9 2021-07-14 BAl3Y7yxev Clothing P0370
## 2 2 y4bCY9pKTBWU 2020-11-16 TYY0h5C190 Electronics P0185
## 3 3 8k0B7XX19Ykf 2023-03-22 nUX640AaXg Home P0443
## 4 4 l8ahQz5YNOKz 2023-01-02 sBZyUSJLEP Home P0035
## 5 5 kmufgw8wx5qk 2023-06-05 GMfVH2ZWNX Groceries P0375
## 6 6 aI0KADT0mn7C 2023-03-15 YxqAmfTU9M Clothing P0447
## Quantity Unit_Price Discount Region Sales_Channel Delivery_Time Total_Price
## 1 2 15.18 0.00 North Online 5 30.36
## 2 5 10.22 0.15 West Offline 2 43.44
## 3 3 17.74 0.05 West Online 8 50.56
## 4 6 28.30 0.22 North Offline 8 132.44
## 5 3 11.91 0.13 North Offline 7 31.09
## 6 1 5.43 0.07 North Offline 9 5.05
## Price_per_Unit Efficiency Feature_Interaction Cross_Term ID_Prefix
## 1 15.18000 0.4000000 0.00 Clothing_North P0
## 2 8.68800 2.5000000 0.75 Electronics_West P0
## 3 16.85333 0.3750000 0.15 Home_West P0
## 4 22.07333 0.7500000 1.32 Home_North P0
## 5 10.36333 0.4285714 0.39 Groceries_North P0
## 6 5.05000 0.1111111 0.07 Clothing_North P0
## ID_Length ID_HasPattern Discount_Level Sales_Rank Avg_Quantity_Region
## 1 5 true 1 253 2.992908
## 2 5 true 2 157 3.116667
## 3 5 true 1 121 3.116667
## 4 5 true 3 4 2.992908
## 5 5 true 2 246 2.992908
## 6 5 true 1 466 2.992908
## Sum_Sales_Region Count_Product_Region
## 1 4864.94 141
## 2 4169.72 120
## 3 4169.72 120
## 4 4864.94 141
## 5 4864.94 141
## 6 4864.94 141
HeadMap
# Impor Data
data_bisnis <- read.csv("data_bisnis.csv")
# Data untuk membuat HeadMap
# Gunakan Region sebagai dan Product_Category
tasks <- unique(data_bisnis$Region)
models <- unique(data_bisnis$Product_Category)
# Buat matriks performa berdasarkan rata-rata Total_Price
performance <- matrix(0, nrow = length(models), ncol = length(tasks))
rownames(performance) <- models
colnames(performance) <- tasks
# Isi matriks dengan rata-rata Total_Price
for (i in seq_along(models)) {
for (j in seq_along(tasks)) {
subset <- data_bisnis[data_bisnis$Product_Category == models[i] & data_bisnis$Region == tasks[j], ]
if (nrow(subset) > 0) {
performance[i, j] <- mean(subset$Total_Price, na.rm = TRUE)
} else {
performance[i, j] <- 0
}
}
}
# Normalisasi ke rentang 0-100
min_val <- min(performance, na.rm = TRUE)
max_val <- max(performance, na.rm = TRUE)
performance <- ((performance - min_val) / (max_val - min_val)) * 100
# Ubah ke format long untuk ggplot
performance_df <- as.data.frame(performance)
performance_df$Product_Category <- rownames(performance_df)
performance_long <- melt(performance_df, id.vars = "Product_Category", variable.name = "Region", value.name = "Score")
# Pastikan kolom adalah tipe yang tepat
performance_long$Product_Category <- as.factor(performance_long$Product_Category)
performance_long$Region <- as.factor(performance_long$Region)
performance_long$Score <- as.numeric(performance_long$Score)
# Membuat HeadMap
ggplot(performance_long, aes(x = Region, y = Product_Category, fill = Score)) +
geom_tile(color = "white") +
geom_text(aes(label = sprintf("%.1f", Score)), color = "black", size = 3) +
scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 50,
limits = c(0, 100), name = "Skor (%)") +
labs(title = "Rata-rata Total Price per Region dan Kategori Produk",
x = "Region (Tugas)", y = "Kategori Produk (Model)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(size = 16, face = "bold"))Scatter Plot
# Impor Data
data_bisnis <- read.csv("data_bisnis.csv")
# Membuat Scatter Plot
ggplot(data_bisnis, aes(x = Quantity, y = Total_Price, color = Product_Category)) +
geom_point(alpha = 0.6) +
labs(title = "Quantity vs Total Price by Product Category",
x = "Quantity", y = "Total Price") +
theme_minimal() +
theme(plot.title = element_text(size = 16, face = "bold"),
axis.title = element_text(size = 12)) +
scale_color_discrete(name = "Product Category")Bubble Chart
# Impor Data
data_bisnis <- read.csv("data_bisnis.csv")
# Membuat Bubble Chart
ggplot(data_bisnis, aes(x = Quantity, y = Total_Price, size = Discount, color = Region)) +
geom_point(alpha = 0.6) +
scale_size(range = c(2, 10)) +
labs(title = "Quantity vs Total Price by Region",
x = "Quantity", y = "Total Price") +
theme_minimal() +
theme(plot.title = element_text(size = 16, face = "bold"),
axis.title = element_text(size = 12)) +
scale_color_discrete(name = "Region")Correlation Matriks
# Impor Data
data_bisnis <- read.csv("data_bisnis.csv")
# Membuat Correlation Matriks
numeric_cols <- data_bisnis[, c("Quantity", "Unit_Price", "Discount", "Delivery_Time", "Total_Price")]
cor_matrix <- cor(numeric_cols, use = "complete.obs")
# Ubah ke format long untuk ggplot
cor_matrix_melted <- melt(cor_matrix)
ggplot(cor_matrix_melted, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
geom_text(aes(label = sprintf("%.2f", value)), color = "black", size = 4) +
scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0, limits = c(-1, 1), name = "Correlation") +
labs(title = "Correlation Matrix of Numeric Variables",
x = "", y = "") +
theme_minimal() +
theme(plot.title = element_text(size = 16, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))Line Chart
# Impor Data
data_bisnis <- read.csv("data_bisnis.csv")
# Pastikan kolom tanggal dalam format datetime
data_bisnis$Transaction_Date <- as.Date(data_bisnis$Transaction_Date, format = "%Y-%m-%d")
# Hitung Total_Price
data_bisnis$Total_Price <- data_bisnis$Quantity * data_bisnis$Unit_Price * (1 - data_bisnis$Discount)
# Filter data untuk 5 tahun terakhir (Mei 2020 - Mei 2025)
start_date <- as.Date("2020-05-01")
end_date <- as.Date("2025-05-31")
filtered_data <- data_bisnis %>%
filter(Transaction_Date >= start_date & Transaction_Date <= end_date)
# Buat kolom periode 6 bulan
filtered_data <- filtered_data %>%
mutate(Half_Year = ifelse(month(Transaction_Date) <= 6, year(Transaction_Date), year(Transaction_Date)))
# Rata - rata total price
half_yearly_category_sales <- filtered_data %>%
group_by(Product_Category, Half_Year) %>%
summarise(Avg_Total_Price = mean(Total_Price, na.rm = TRUE))
# Membuat Line Chart
ggplot(half_yearly_category_sales, aes(x = Half_Year, y = Avg_Total_Price, color = Product_Category, group = Product_Category)) +
geom_line(size = 1) +
geom_point(size = 2) +
labs(title = "Half-Yearly Average Sales by Product Category (2020-2025)",
x = "Half Year", y = "Average Total Price") +
theme_minimal() +
theme(plot.title = element_text(size = 16, face = "bold"),
axis.title = element_text(size = 14),
axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_color_discrete(name = "Product Category") +
scale_x_continuous(breaks = unique(half_yearly_category_sales$Half_Year))Area Chart
# Impor Data
data_bisnis <- read.csv("data_bisnis.csv")
# Pastikan kolom tanggal dalam format datetime
data_bisnis$Transaction_Date <- as.Date(data_bisnis$Transaction_Date, format = "%Y-%m-%d")
# Hitung Total_Price
data_bisnis$Total_Price <- data_bisnis$Quantity * data_bisnis$Unit_Price * (1 - data_bisnis$Discount)
# Filter data untuk 5 tahun terakhir (Mei 2020 - Mei 2025)
start_date <- as.Date("2020-05-01")
end_date <- as.Date("2025-05-31")
filtered_data <- data_bisnis %>%
filter(Transaction_Date >= start_date & Transaction_Date <= end_date)
# Buat kolom periode 6 bulan
filtered_data <- filtered_data %>%
mutate(Half_Year = ifelse(month(Transaction_Date) <= 6, year(Transaction_Date), year(Transaction_Date)))
# Rata - rata total price
half_yearly_category_sales <- filtered_data %>%
group_by(Product_Category, Half_Year) %>%
summarise(Avg_Total_Price = mean(Total_Price, na.rm = TRUE))
# Area Chart
ggplot(half_yearly_category_sales, aes(x = Half_Year, y = Avg_Total_Price, fill = Product_Category, group = Product_Category)) +
geom_area(alpha = 0.6, position = "stack") +
labs(title = "Half-Yearly Average Sales by Product Category (2020-2025)",
x = "Half Year", y = "Average Total Price") +
theme_minimal() +
theme(plot.title = element_text(size = 16, face = "bold"),
axis.title = element_text(size = 14),
axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_fill_discrete(name = "Product Category") +
scale_x_continuous(breaks = unique(half_yearly_category_sales$Half_Year))LS0tDQp0aXRsZTogIkRhdGEgU2NpZW5jZSBQcm9ncmFtbWluZyINCnN1YnRpdGxlOiAiU3ViLUJhYiAwOSINCmF1dGhvcjogDQogIC0gIlphaW4gSXFiYWwgU2FwdXRyYV81MjI0MDAxOCINCmRhdGU6ICAiU2VuaW4sIDIzLzA1LzIwMjUiDQpvdXRwdXQ6DQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOiAgIA0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdGh1bWJuYWlsczogdHJ1ZQ0KICAgIGxpZ2h0Ym94OiB0cnVlDQogICAgZ2FsbGVyeTogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgM2RmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCi0tLQ0KDQpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHZpcmlkaXMpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgSW1wb3J0aW5nIERhdGENCmRhdGEgPC0gcmVhZC5jc3YoJ2RhdGFfYmlzbmlzLmNzdicpDQoNCiMgUGFuZ2dpbA0KaGVhZChkYXRhKQ0KYGBgDQoNCiMgSGVhZE1hcA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgSW1wb3IgRGF0YQ0KZGF0YV9iaXNuaXMgPC0gcmVhZC5jc3YoImRhdGFfYmlzbmlzLmNzdiIpDQoNCiMgRGF0YSB1bnR1ayBtZW1idWF0IEhlYWRNYXANCiMgR3VuYWthbiBSZWdpb24gc2ViYWdhaSBkYW4gUHJvZHVjdF9DYXRlZ29yeSANCnRhc2tzIDwtIHVuaXF1ZShkYXRhX2Jpc25pcyRSZWdpb24pDQptb2RlbHMgPC0gdW5pcXVlKGRhdGFfYmlzbmlzJFByb2R1Y3RfQ2F0ZWdvcnkpDQoNCiMgQnVhdCBtYXRyaWtzIHBlcmZvcm1hIGJlcmRhc2Fya2FuIHJhdGEtcmF0YSBUb3RhbF9QcmljZQ0KcGVyZm9ybWFuY2UgPC0gbWF0cml4KDAsIG5yb3cgPSBsZW5ndGgobW9kZWxzKSwgbmNvbCA9IGxlbmd0aCh0YXNrcykpDQpyb3duYW1lcyhwZXJmb3JtYW5jZSkgPC0gbW9kZWxzDQpjb2xuYW1lcyhwZXJmb3JtYW5jZSkgPC0gdGFza3MNCg0KIyBJc2kgbWF0cmlrcyBkZW5nYW4gcmF0YS1yYXRhIFRvdGFsX1ByaWNlDQpmb3IgKGkgaW4gc2VxX2Fsb25nKG1vZGVscykpIHsNCiAgZm9yIChqIGluIHNlcV9hbG9uZyh0YXNrcykpIHsNCiAgICBzdWJzZXQgPC0gZGF0YV9iaXNuaXNbZGF0YV9iaXNuaXMkUHJvZHVjdF9DYXRlZ29yeSA9PSBtb2RlbHNbaV0gJiBkYXRhX2Jpc25pcyRSZWdpb24gPT0gdGFza3Nbal0sIF0NCiAgICBpZiAobnJvdyhzdWJzZXQpID4gMCkgew0KICAgICAgcGVyZm9ybWFuY2VbaSwgal0gPC0gbWVhbihzdWJzZXQkVG90YWxfUHJpY2UsIG5hLnJtID0gVFJVRSkNCiAgICB9IGVsc2Ugew0KICAgICAgcGVyZm9ybWFuY2VbaSwgal0gPC0gMA0KICAgIH0NCiAgfQ0KfQ0KDQojIE5vcm1hbGlzYXNpIGtlIHJlbnRhbmcgMC0xMDANCm1pbl92YWwgPC0gbWluKHBlcmZvcm1hbmNlLCBuYS5ybSA9IFRSVUUpDQptYXhfdmFsIDwtIG1heChwZXJmb3JtYW5jZSwgbmEucm0gPSBUUlVFKQ0KcGVyZm9ybWFuY2UgPC0gKChwZXJmb3JtYW5jZSAtIG1pbl92YWwpIC8gKG1heF92YWwgLSBtaW5fdmFsKSkgKiAxMDANCg0KIyBVYmFoIGtlIGZvcm1hdCBsb25nIHVudHVrIGdncGxvdA0KcGVyZm9ybWFuY2VfZGYgPC0gYXMuZGF0YS5mcmFtZShwZXJmb3JtYW5jZSkNCnBlcmZvcm1hbmNlX2RmJFByb2R1Y3RfQ2F0ZWdvcnkgPC0gcm93bmFtZXMocGVyZm9ybWFuY2VfZGYpDQpwZXJmb3JtYW5jZV9sb25nIDwtIG1lbHQocGVyZm9ybWFuY2VfZGYsIGlkLnZhcnMgPSAiUHJvZHVjdF9DYXRlZ29yeSIsIHZhcmlhYmxlLm5hbWUgPSAiUmVnaW9uIiwgdmFsdWUubmFtZSA9ICJTY29yZSIpDQoNCiMgUGFzdGlrYW4ga29sb20gYWRhbGFoIHRpcGUgeWFuZyB0ZXBhdA0KcGVyZm9ybWFuY2VfbG9uZyRQcm9kdWN0X0NhdGVnb3J5IDwtIGFzLmZhY3RvcihwZXJmb3JtYW5jZV9sb25nJFByb2R1Y3RfQ2F0ZWdvcnkpDQpwZXJmb3JtYW5jZV9sb25nJFJlZ2lvbiA8LSBhcy5mYWN0b3IocGVyZm9ybWFuY2VfbG9uZyRSZWdpb24pDQpwZXJmb3JtYW5jZV9sb25nJFNjb3JlIDwtIGFzLm51bWVyaWMocGVyZm9ybWFuY2VfbG9uZyRTY29yZSkNCg0KIyBNZW1idWF0IEhlYWRNYXANCmdncGxvdChwZXJmb3JtYW5jZV9sb25nLCBhZXMoeCA9IFJlZ2lvbiwgeSA9IFByb2R1Y3RfQ2F0ZWdvcnksIGZpbGwgPSBTY29yZSkpICsNCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc3ByaW50ZigiJS4xZiIsIFNjb3JlKSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBtaWQgPSAid2hpdGUiLCBoaWdoID0gInJlZCIsIG1pZHBvaW50ID0gNTAsIA0KICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsIDEwMCksIG5hbWUgPSAiU2tvciAoJSkiKSArDQogIGxhYnModGl0bGUgPSAiUmF0YS1yYXRhIFRvdGFsIFByaWNlIHBlciBSZWdpb24gZGFuIEthdGVnb3JpIFByb2R1ayIsDQogICAgICAgeCA9ICJSZWdpb24gKFR1Z2FzKSIsIHkgPSAiS2F0ZWdvcmkgUHJvZHVrIChNb2RlbCkiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSkNCmBgYA0KDQojIFNjYXR0ZXIgUGxvdA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgSW1wb3IgRGF0YQ0KZGF0YV9iaXNuaXMgPC0gcmVhZC5jc3YoImRhdGFfYmlzbmlzLmNzdiIpDQoNCiMgTWVtYnVhdCBTY2F0dGVyIFBsb3QNCmdncGxvdChkYXRhX2Jpc25pcywgYWVzKHggPSBRdWFudGl0eSwgeSA9IFRvdGFsX1ByaWNlLCBjb2xvciA9IFByb2R1Y3RfQ2F0ZWdvcnkpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsNCiAgbGFicyh0aXRsZSA9ICJRdWFudGl0eSB2cyBUb3RhbCBQcmljZSBieSBQcm9kdWN0IENhdGVnb3J5IiwNCiAgICAgICB4ID0gIlF1YW50aXR5IiwgeSA9ICJUb3RhbCBQcmljZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpICsNCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZSA9ICJQcm9kdWN0IENhdGVnb3J5IikNCmBgYA0KDQojIEJ1YmJsZSBDaGFydA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgSW1wb3IgRGF0YQ0KZGF0YV9iaXNuaXMgPC0gcmVhZC5jc3YoImRhdGFfYmlzbmlzLmNzdiIpDQoNCiMgTWVtYnVhdCBCdWJibGUgQ2hhcnQNCmdncGxvdChkYXRhX2Jpc25pcywgYWVzKHggPSBRdWFudGl0eSwgeSA9IFRvdGFsX1ByaWNlLCBzaXplID0gRGlzY291bnQsIGNvbG9yID0gUmVnaW9uKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArDQogIHNjYWxlX3NpemUocmFuZ2UgPSBjKDIsIDEwKSkgKw0KICBsYWJzKHRpdGxlID0gIlF1YW50aXR5IHZzIFRvdGFsIFByaWNlIGJ5IFJlZ2lvbiIsDQogICAgICAgeCA9ICJRdWFudGl0eSIsIHkgPSAiVG90YWwgUHJpY2UiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKSArDQogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiUmVnaW9uIikNCmBgYA0KDQojIENvcnJlbGF0aW9uIE1hdHJpa3MNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEltcG9yIERhdGENCmRhdGFfYmlzbmlzIDwtIHJlYWQuY3N2KCJkYXRhX2Jpc25pcy5jc3YiKQ0KDQojIE1lbWJ1YXQgQ29ycmVsYXRpb24gTWF0cmlrcw0KbnVtZXJpY19jb2xzIDwtIGRhdGFfYmlzbmlzWywgYygiUXVhbnRpdHkiLCAiVW5pdF9QcmljZSIsICJEaXNjb3VudCIsICJEZWxpdmVyeV9UaW1lIiwgIlRvdGFsX1ByaWNlIildDQpjb3JfbWF0cml4IDwtIGNvcihudW1lcmljX2NvbHMsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQ0KDQojIFViYWgga2UgZm9ybWF0IGxvbmcgdW50dWsgZ2dwbG90DQpjb3JfbWF0cml4X21lbHRlZCA8LSBtZWx0KGNvcl9tYXRyaXgpDQoNCmdncGxvdChjb3JfbWF0cml4X21lbHRlZCwgYWVzKHggPSBWYXIxLCB5ID0gVmFyMiwgZmlsbCA9IHZhbHVlKSkgKw0KICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzcHJpbnRmKCIlLjJmIiwgdmFsdWUpKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNCkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIG1pZCA9ICJ3aGl0ZSIsIGhpZ2ggPSAicmVkIiwgbWlkcG9pbnQgPSAwLCBsaW1pdHMgPSBjKC0xLCAxKSwgbmFtZSA9ICJDb3JyZWxhdGlvbiIpICsNCiAgbGFicyh0aXRsZSA9ICJDb3JyZWxhdGlvbiBNYXRyaXggb2YgTnVtZXJpYyBWYXJpYWJsZXMiLA0KICAgICAgIHggPSAiIiwgeSA9ICIiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQojIExpbmUgQ2hhcnQNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEltcG9yIERhdGENCmRhdGFfYmlzbmlzIDwtIHJlYWQuY3N2KCJkYXRhX2Jpc25pcy5jc3YiKQ0KDQojIFBhc3Rpa2FuIGtvbG9tIHRhbmdnYWwgZGFsYW0gZm9ybWF0IGRhdGV0aW1lDQpkYXRhX2Jpc25pcyRUcmFuc2FjdGlvbl9EYXRlIDwtIGFzLkRhdGUoZGF0YV9iaXNuaXMkVHJhbnNhY3Rpb25fRGF0ZSwgZm9ybWF0ID0gIiVZLSVtLSVkIikNCg0KIyBIaXR1bmcgVG90YWxfUHJpY2UNCmRhdGFfYmlzbmlzJFRvdGFsX1ByaWNlIDwtIGRhdGFfYmlzbmlzJFF1YW50aXR5ICogZGF0YV9iaXNuaXMkVW5pdF9QcmljZSAqICgxIC0gZGF0YV9iaXNuaXMkRGlzY291bnQpDQoNCiMgRmlsdGVyIGRhdGEgdW50dWsgNSB0YWh1biB0ZXJha2hpciAoTWVpIDIwMjAgLSBNZWkgMjAyNSkNCnN0YXJ0X2RhdGUgPC0gYXMuRGF0ZSgiMjAyMC0wNS0wMSIpDQplbmRfZGF0ZSA8LSBhcy5EYXRlKCIyMDI1LTA1LTMxIikNCmZpbHRlcmVkX2RhdGEgPC0gZGF0YV9iaXNuaXMgJT4lDQogIGZpbHRlcihUcmFuc2FjdGlvbl9EYXRlID49IHN0YXJ0X2RhdGUgJiBUcmFuc2FjdGlvbl9EYXRlIDw9IGVuZF9kYXRlKQ0KDQojIEJ1YXQga29sb20gcGVyaW9kZSA2IGJ1bGFuIA0KZmlsdGVyZWRfZGF0YSA8LSBmaWx0ZXJlZF9kYXRhICU+JQ0KICBtdXRhdGUoSGFsZl9ZZWFyID0gaWZlbHNlKG1vbnRoKFRyYW5zYWN0aW9uX0RhdGUpIDw9IDYsIHllYXIoVHJhbnNhY3Rpb25fRGF0ZSksIHllYXIoVHJhbnNhY3Rpb25fRGF0ZSkpKQ0KDQojIFJhdGEgLSByYXRhIHRvdGFsIHByaWNlDQpoYWxmX3llYXJseV9jYXRlZ29yeV9zYWxlcyA8LSBmaWx0ZXJlZF9kYXRhICU+JQ0KICBncm91cF9ieShQcm9kdWN0X0NhdGVnb3J5LCBIYWxmX1llYXIpICU+JQ0KICBzdW1tYXJpc2UoQXZnX1RvdGFsX1ByaWNlID0gbWVhbihUb3RhbF9QcmljZSwgbmEucm0gPSBUUlVFKSkNCg0KIyBNZW1idWF0IExpbmUgQ2hhcnQNCmdncGxvdChoYWxmX3llYXJseV9jYXRlZ29yeV9zYWxlcywgYWVzKHggPSBIYWxmX1llYXIsIHkgPSBBdmdfVG90YWxfUHJpY2UsIGNvbG9yID0gUHJvZHVjdF9DYXRlZ29yeSwgZ3JvdXAgPSBQcm9kdWN0X0NhdGVnb3J5KSkgKw0KICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikgKw0KICBsYWJzKHRpdGxlID0gIkhhbGYtWWVhcmx5IEF2ZXJhZ2UgU2FsZXMgYnkgUHJvZHVjdCBDYXRlZ29yeSAoMjAyMC0yMDI1KSIsDQogICAgICAgeCA9ICJIYWxmIFllYXIiLCB5ID0gIkF2ZXJhZ2UgVG90YWwgUHJpY2UiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArDQogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiUHJvZHVjdCBDYXRlZ29yeSIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHVuaXF1ZShoYWxmX3llYXJseV9jYXRlZ29yeV9zYWxlcyRIYWxmX1llYXIpKQ0KYGBgDQoNCiMgQXJlYSBDaGFydA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgSW1wb3IgRGF0YQ0KZGF0YV9iaXNuaXMgPC0gcmVhZC5jc3YoImRhdGFfYmlzbmlzLmNzdiIpDQoNCiMgUGFzdGlrYW4ga29sb20gdGFuZ2dhbCBkYWxhbSBmb3JtYXQgZGF0ZXRpbWUNCmRhdGFfYmlzbmlzJFRyYW5zYWN0aW9uX0RhdGUgPC0gYXMuRGF0ZShkYXRhX2Jpc25pcyRUcmFuc2FjdGlvbl9EYXRlLCBmb3JtYXQgPSAiJVktJW0tJWQiKQ0KDQojIEhpdHVuZyBUb3RhbF9QcmljZQ0KZGF0YV9iaXNuaXMkVG90YWxfUHJpY2UgPC0gZGF0YV9iaXNuaXMkUXVhbnRpdHkgKiBkYXRhX2Jpc25pcyRVbml0X1ByaWNlICogKDEgLSBkYXRhX2Jpc25pcyREaXNjb3VudCkNCg0KIyBGaWx0ZXIgZGF0YSB1bnR1ayA1IHRhaHVuIHRlcmFraGlyIChNZWkgMjAyMCAtIE1laSAyMDI1KQ0Kc3RhcnRfZGF0ZSA8LSBhcy5EYXRlKCIyMDIwLTA1LTAxIikNCmVuZF9kYXRlIDwtIGFzLkRhdGUoIjIwMjUtMDUtMzEiKQ0KZmlsdGVyZWRfZGF0YSA8LSBkYXRhX2Jpc25pcyAlPiUNCiAgZmlsdGVyKFRyYW5zYWN0aW9uX0RhdGUgPj0gc3RhcnRfZGF0ZSAmIFRyYW5zYWN0aW9uX0RhdGUgPD0gZW5kX2RhdGUpDQoNCiMgQnVhdCBrb2xvbSBwZXJpb2RlIDYgYnVsYW4gDQpmaWx0ZXJlZF9kYXRhIDwtIGZpbHRlcmVkX2RhdGEgJT4lDQogIG11dGF0ZShIYWxmX1llYXIgPSBpZmVsc2UobW9udGgoVHJhbnNhY3Rpb25fRGF0ZSkgPD0gNiwgeWVhcihUcmFuc2FjdGlvbl9EYXRlKSwgeWVhcihUcmFuc2FjdGlvbl9EYXRlKSkpDQoNCiMgUmF0YSAtIHJhdGEgdG90YWwgcHJpY2UNCmhhbGZfeWVhcmx5X2NhdGVnb3J5X3NhbGVzIDwtIGZpbHRlcmVkX2RhdGEgJT4lDQogIGdyb3VwX2J5KFByb2R1Y3RfQ2F0ZWdvcnksIEhhbGZfWWVhcikgJT4lDQogIHN1bW1hcmlzZShBdmdfVG90YWxfUHJpY2UgPSBtZWFuKFRvdGFsX1ByaWNlLCBuYS5ybSA9IFRSVUUpKQ0KDQojIEFyZWEgQ2hhcnQNCmdncGxvdChoYWxmX3llYXJseV9jYXRlZ29yeV9zYWxlcywgYWVzKHggPSBIYWxmX1llYXIsIHkgPSBBdmdfVG90YWxfUHJpY2UsIGZpbGwgPSBQcm9kdWN0X0NhdGVnb3J5LCBncm91cCA9IFByb2R1Y3RfQ2F0ZWdvcnkpKSArDQogIGdlb21fYXJlYShhbHBoYSA9IDAuNiwgcG9zaXRpb24gPSAic3RhY2siKSArDQogIGxhYnModGl0bGUgPSAiSGFsZi1ZZWFybHkgQXZlcmFnZSBTYWxlcyBieSBQcm9kdWN0IENhdGVnb3J5ICgyMDIwLTIwMjUpIiwNCiAgICAgICB4ID0gIkhhbGYgWWVhciIsIHkgPSAiQXZlcmFnZSBUb3RhbCBQcmljZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsNCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIlByb2R1Y3QgQ2F0ZWdvcnkiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSB1bmlxdWUoaGFsZl95ZWFybHlfY2F0ZWdvcnlfc2FsZXMkSGFsZl9ZZWFyKSkNCmBgYA0KDQo=