Pratikum PEMOGRAMAN SAINS DATA
Pratikum PEMOGRAMAN SAINS DATA
1. Check Sheet
1.1 Dataset
1.2 Tabel Frekuensi
# Count frequency
library(dplyr)
library(DT)
Household_summary <- Household %>%
count(Pengeluaran, sort = TRUE) %>%
rename(Frequency = n)
# Display summary table
datatable(
Household_summary,
options = list(
scrollCollapse = TRUE,
searching = FALSE, # Remove search box
paging = FALSE # Remove pagination
),
rownames = FALSE,
caption = htmltools::tags$caption(
style = 'caption-side: top; text-align: left;
font-size: 18px; font-weight: bold;',
'Frekuensi Pengeluaran Rumah Tangga'
),
class = 'stripe hover compact'
)1.3 Visualisasi
library(plotly)
# Interactive bar chart using plotly
plot_ly(Household_summary,
x = ~Frequency,
y = ~reorder(Pengeluaran, Frequency),
type = 'bar',
orientation = 'h',
marker = list(
color = ~Frequency,
colorscale = 'Viridis', # Can also try: 'Bluered', 'Cividis', 'YlOrRd'
showscale = TRUE
)
) %>%
layout(
title = list(text = "Frekuensi Pengeluaran Rumah", font = list(size = 18)),
xaxis = list(title = "Frequency"),
yaxis = list(title = "Pengeluaran"),
margin = list(l = 120)
)2. Histogram
1. Dataset
# Ensure all required packages are installed
packages <- c("dplyr", "stringi", "lubridate", "DT")
new_packages <- packages[!(packages %in% installed.packages()[, "Package"])]
if(length(new_packages)) install.packages(new_packages)
# Load libraries
library(dplyr)
library(stringi)
library(lubridate)
library(DT)
## Create a complex dummy health dataset for data transformation
set.seed(42)
n <- 31
# Simulate location and health condition
Jenis <- sample(c("Nasi Goreng", "Soto", "Sayur Asem", "Spageti", "Ayam Goreng"), n, replace = TRUE)
# Simulate cooking times (in minutes) for each food type
waktu_masak <- c("Nasi Goreng" = 15, "Soto" = 60, "Sayur Asem" = 45, "Spageti" = 20, "Ayam Goreng" = 30)
Waktu_Masak <- sapply(Jenis, function(x) waktu_masak[x])
# Create the dataset
Household_2 <- tibble(
Jenis_Makanan = Jenis,
Waktu_Masak = Waktu_Masak
)
# Show interactive table with download buttons
datatable(
Household_2,
extensions = 'Buttons',
options = list(
dom = 'Bfrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
scrollY = "400px",
scrollCollapse = TRUE,
paging = FALSE
),
caption = htmltools::tags$caption(
style = 'caption-side: top; text-align: left;
font-size: 18px; font-weight: bold;'
),
class = 'stripe hover compact'
)1.3 Visualisasi
# Install and load necessary libraries
library(plotly)
library(DT)
# Gunakan kolom Listrik sebagai data normal
normal_data <- Household_2$Waktu_Masak
# Calculate the density of the normal data
density_data <- density(normal_data)
# Create a histogram of the normal data using plotly
histogram_plot <- plot_ly(
x = normal_data,
type = 'histogram',
marker = list(color = 'lightblue', line = list(color = 'black', width = 1)),
name = 'Histogram of Normal Data',
nbinsx = 30,
opacity = 0.6,
showlegend = TRUE
) %>%
# Add the density curve
add_trace(
x = density_data$x,
y = density_data$y * length(normal_data) * diff(range(normal_data)) / 30, # Scale density to histogram
type = 'scatter',
mode = 'lines',
name = 'Density Curve',
line = list(color = 'black', width = 3),
showlegend = TRUE
) %>%
layout(
title = 'Histogram of Normal Distribution with Density Curve',
xaxis = list(title = 'Value', showgrid = FALSE),
yaxis = list(title = 'Frequency / Density', showgrid = FALSE),
bargap = 0.1,
plot_bgcolor = 'white',
paper_bgcolor = 'white',
showlegend = TRUE,
legend = list(
orientation = 'v', # vertical legend
x = 0.98, # almost at the right edge
xanchor = 'right',
y = 0.98, # almost at the top
yanchor = 'top',
bgcolor = 'rgba(255,255,255,0.8)', # semi-transparent background
bordercolor = 'black',
borderwidth = 0.3
)
)
# Show the plot
histogram_plot3. Pareto Chart
# Load libraries
library(dplyr)
library(plotly)
library(RColorBrewer)
# Create the dataset
set.seed(42)
n <- 31
dates <- seq.Date(from = as.Date("2025-05-01"), to = as.Date("2025-05-31"), by = "day")
sample_dates <- sample(dates, n, replace = TRUE)
Pengeluaran <- sample(c("Listrik", "Belanja Mingguan", "Gas LPG", "Transportasi", "Makan di luar", "Internet", "Pengeluaran darurat", "PDAM"), n, replace = TRUE)
Household <- tibble(
Tanggal = sample_dates,
Pengeluaran = Pengeluaran
)
# Summarize the number of delays by reason
pareto_data <- Household %>%
count(Pengeluaran, sort = TRUE) %>%
mutate(
cum_freq = cumsum(n) / sum(n) * 100 # cumulative percentage
)
# Create different colors for each Reason (adjusted for the length of reasons)
colors <- RColorBrewer::brewer.pal(n = min(12, length(pareto_data$Pengeluaran)), name = "Set3")
# Create Plotly Pareto Chart
fig <- plot_ly()
# Add Bar Chart (Count) - with different colors
fig <- fig %>% add_bars(
x = ~reorder(pareto_data$Pengeluaran, -pareto_data$n),
y = ~pareto_data$n,
name = 'Number of Delays',
marker = list(color = colors),
yaxis = "y1"
)
# Add Cumulative Line
fig <- fig %>% add_lines(
x = ~reorder(pareto_data$Pengeluaran, -pareto_data$n),
y = ~pareto_data$cum_freq,
name = 'Cumulative (%)',
yaxis = "y2",
line = list(color = 'red', dash = 'dash')
)
# Add Cut-off Line at 80%
fig <- fig %>% add_lines(
x = ~reorder(pareto_data$Pengeluaran, -pareto_data$n),
y = rep(80, length(pareto_data$Pengeluaran)),
name = 'Cut-off 80%',
yaxis = "y2",
line = list(color = 'green', dash = 'dot')
)
# Adjust layout
fig <- fig %>% layout(
title = "Pareto Chart - Delay Reasons",
xaxis = list(
title = "Delay Reasons",
tickangle = -45 # tilt 45 degrees
),
yaxis = list(title = "Number of Delays"),
yaxis2 = list(
title = "Cumulative (%)",
overlaying = "y",
side = "right",
range = c(0, 100)
),
legend = list(x = 0.8, y = 0.75),
shapes = list(
list(
type = "line",
x0 = -0.5,
x1 = length(pareto_data$Pengeluaran) - 0.5,
y0 = 80,
y1 = 80,
yref = "y2",
line = list(color = "green", width = 2, dash = "dot")
)
)
)
# Show chart
fig4. Fishbone
library(DiagrammeR)
library(rsvg)
grViz("
digraph fishbone {
graph [layout = dot, rankdir = LR]
# Default node styles
node [fontname=Helvetica, fontsize=25, style=filled]
# Central problem
Problem [label='Delayed \\n Goods Delivery', shape=ellipse, fillcolor=lightcoral, width=5.0, height=1.2]
# Category nodes (shared style)
node [shape=diamond, width=2.5, height=1.0, fillcolor='#FFD700']
A1 [label='Ekonomi']
A2 [label='Komunikasi']
A3 [label='Pembagian Tugas']
A4 [label='Waktu']
A5 [label='Pola asuh']
# Reset node style for sub-categories
node [shape=ellipse, width=2.5, height=0.6, fillcolor='#90EE90']
A1a [label='Pengeluaran berlebih']
A1b [label='Penghasilan tidak tetap']
A1c [label='Tidak ada tabungan darurat']
A2a [label='Kurang terbuka']
A2b [label='Salah Paham']
A3a [label='Tidak Adil']
A3b [label='Tidak sesuai kesepakatan']
A4a [label='Kurangnya waktu bersama']
A4b [label='Terlalu sibuk bekerja']
A5a [label='Perbedaan gaya asuh']
A5b [label='Kesepakatan dalam disiplin']
# Relationships
A1 -> Problem
A2 -> Problem
A3 -> Problem
A4 -> Problem
A5 -> Problem
A1a -> A1
A1b -> A1
A1c -> A1
A2a -> A2
A2b -> A2
A3a -> A3
A3b -> A3
A4a -> A4
A4b -> A4
A5a -> A5
A5b -> A5
}
")5. Scatter Diagram
# Load the plotly package
library(plotly)
# Create a dataset: sleep hours vs mood level
set.seed(42) # For reproducibility
data <- data.frame(
Sleep_Hours = seq(4, 10, length.out = 20), # dari 4 hingga 10 jam tidur
Mood_Level = seq(30, 90, length.out = 20) # asumsi mood level antara 30-90
)
# Tambahkan noise agar korelasi mendekati 0.9
data$Mood_Level <- data$Mood_Level + rnorm(n = 20, mean = 0, sd = 5)
# Hitung koefisien korelasi
correlation_value <- cor(data$Sleep_Hours, data$Mood_Level)
# Buat scatter plot menggunakan Plotly dengan garis regresi linier
fig <- plot_ly(data,
x = ~Sleep_Hours,
y = ~Mood_Level,
type = 'scatter',
mode = 'markers',
marker = list(color = 'blue', size = 10)) %>%
add_lines(x = data$Sleep_Hours,
y = predict(lm(Mood_Level ~ Sleep_Hours, data = data)),
line = list(color = 'red', dash = 'solid', width = 2)) %>%
layout(title = paste("Scatter Plot: Hubungan antara Jam Tidur dan Suasana Hati\nKorelasi: ", round(correlation_value, 2)),
xaxis = list(title = "Jam Tidur"),
yaxis = list(title = "Suasana Hati"))
# Tampilkan plot
fig6. Control Chart
# Load libraries
library(plotly)
library(dplyr)
# Simulasi data berat kemasan per hari (contoh)
set.seed(1)
df <- tibble(
Hari = 1:30,
Berat = round(rnorm(30, mean = 500, sd = 5), 1)
)
# Tentukan batas kendali (CL, UCL, LCL)
CL <- mean(df$Berat, na.rm = TRUE)
UCL <- CL + 3 * sd(df$Berat, na.rm = TRUE)
LCL <- CL - 3 * sd(df$Berat, na.rm = TRUE)
# Tandai outlier
df <- df %>%
mutate(Outlier = ifelse(Berat > UCL | Berat < LCL, "Ya", "Tidak"))
# Buat plot
plot_ly(df, x = ~Hari, y = ~Berat, type = 'scatter', mode = 'lines+markers',
line = list(color = 'blue'),
marker = list(size = 8, color = ifelse(df$Outlier == "Ya", "red", "blue")),
hoverinfo = 'text',
text = ~paste("Hari:", Hari, "<br>Berat:", Berat, "gram")) %>%
add_lines(y = rep(CL, nrow(df)), name = "CL", line = list(color = 'green', dash = 'dot')) %>%
add_lines(y = rep(UCL, nrow(df)), name = "UCL", line = list(color = 'red', dash = 'dot')) %>%
add_lines(y = rep(LCL, nrow(df)), name = "LCL", line = list(color = 'red', dash = 'dot')) %>%
layout(title = "Control Chart – Berat Kemasan Produk",
xaxis = list(title = "Hari"),
yaxis = list(title = "Berat (gram)"),
legend = list(orientation = 'h', x = 0.3, y = -0.2))7. Flowchart
library(DiagrammeR)
grViz("
digraph sistem_kegiatan_rumah_tangga {
graph [layout = dot, rankdir = TB]
node [shape = box, style = filled, fontsize = 12]
# Node definisi
label1 [label = 'Mulai', shape = ellipse, color = lightgreen]
label2 [label = 'Ingin langsung\nmasak?', shape = diamond, color = orange]
label3 [label = 'Masak', shape = box, color = pink]
label4 [label = 'Bangun Tidur', shape = parallelogram, color = lightblue]
label5 [label = 'Sudah selesai\nsemua?', shape = diamond, color = orange]
label6 [label = 'Istirahat', shape = trapezium, color = thistle]
label7 [label = 'Selesai', shape = ellipse, color = lightgreen]
# Edge (alur)
label1 -> label2
label2 -> label3 [label = 'Ya']
label2 -> label4 [label = 'Tidak']
label3 -> label5
label4 -> label5
label5 -> label7 [label = 'Ya']
label5 -> label6 [label = 'Tidak']
label6 -> label7
}
")LS0tDQp0aXRsZTogIlByYXRpa3VtICBQRU1PR1JBTUFOIFNBSU5TIERBVEEiDQoNCnN1YnRpdGxlOiAiUHJhdGlrdW0gUEVNT0dSQU1BTiBTQUlOUyBEQVRBICINCg0KYXV0aG9yOiANCiAgLSAiIEZpa2EgSXJzYW5kaSBEZXN2eWFudGkgKDUyMjQwMDAxMykiDQogIC0gIiBTeWlmYSBOdXJ1bGZhanJpIFJ1c3RpbiAoNTIyNDAwMDEpIg0KICANCmRhdGU6ICAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOg0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdGh1bWJuYWlsczogdHJ1ZQ0KICAgIGxpZ2h0Ym94OiB0cnVlDQogICAgZ2FsbGVyeTogdHJ1ZQ0KICAgIGxpYl9kaXI6IGxpYnMNCiAgICBkZl9wcmludDogInBhZ2VkIg0KICAgIGNvZGVfZm9sZGluZzogInNob3ciDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgY3NzOiAiU3R5bGUuY3NzIg0KICAgIA0KLS0tDQoNCjxpbWcgc3JjPSJQb3Rvby5qcGciIGFsdD0iYXdva3dvd2siIGlkPSJsb2dvLXV0YW1hIiBzdHlsZT0id2lkdGg6NTAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ii8+DQoNCi0tLQ0KDQojIDEuIENoZWNrIFNoZWV0DQoNCiMjIDEuMSBEYXRhc2V0DQoNCmBgYHtyIGVjaG89VFJVRSwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KIyBFbnN1cmUgYWxsIHJlcXVpcmVkIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQNCnBhY2thZ2VzIDwtIGMoImRwbHlyIiwgInN0cmluZ2kiLCAibHVicmlkYXRlIiwgIkRUIikNCm5ld19wYWNrYWdlcyA8LSBwYWNrYWdlc1shKHBhY2thZ2VzICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKClbLCAiUGFja2FnZSJdKV0NCmlmKGxlbmd0aChuZXdfcGFja2FnZXMpKSBpbnN0YWxsLnBhY2thZ2VzKG5ld19wYWNrYWdlcykNCg0KIyBMb2FkIGxpYnJhcmllcw0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoc3RyaW5naSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShEVCkNCg0KIyBDcmVhdGUgYSBjb21wbGV4IGR1bW15IGhlYWx0aCBkYXRhc2V0IGZvciBkYXRhIHRyYW5zZm9ybWF0aW9uDQpzZXQuc2VlZCg0MikNCm4gPC0gMzENCg0KZGF0ZXMgPC0gc2VxLkRhdGUoZnJvbSA9IGFzLkRhdGUoIjIwMjUtMDUtMDEiKSwgdG8gPSBhcy5EYXRlKCIyMDI1LTA1LTMxIiksIGJ5ID0gImRheSIpDQpzYW1wbGVfZGF0ZXMgPC0gc2FtcGxlKGRhdGVzLCBuLCByZXBsYWNlID0gVFJVRSkNCg0KDQojIFNpbXVsYXRlIGxvY2F0aW9uIGFuZCBoZWFsdGggY29uZGl0aW9uDQpQZW5nZWx1YXJhbiA8LSBzYW1wbGUoYygiTGlzdHJpayIsICJCZWxhbmphIE1pbmdndWFuIiwgIkdhcyBMUEciLCAiVHJhbnNwb3J0YXNpIiwgIk1ha2FuIGRpIGx1YXIiLCAiSW50ZXJuZXQiLCAiUGVuZ2VsdWFyYW4gZGFydXJhdCIsICJQREFNIiApLCBuLCByZXBsYWNlID0gVFJVRSkNCg0KIyBDcmVhdGUgdGhlICBkYXRhc2V0DQpIb3VzZWhvbGQgPC0gdGliYmxlKA0KICBUYW5nZ2FsID0gc2FtcGxlX2RhdGVzLA0KICBQZW5nZWx1YXJhbiA9IFBlbmdlbHVhcmFuDQopDQoNCiMgU2hvdyBpbnRlcmFjdGl2ZSB0YWJsZSB3aXRoIGRvd25sb2FkIGJ1dHRvbnMNCmRhdGF0YWJsZSgNCiAgSG91c2Vob2xkLA0KICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLA0KICBvcHRpb25zID0gbGlzdCgNCiAgICBkb20gPSAnQmZydGlwJywNCiAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnLCAncGRmJywgJ3ByaW50JyksDQogICAgc2Nyb2xsWSA9ICI0MDBweCIsDQogICAgc2Nyb2xsQ29sbGFwc2UgPSBUUlVFLA0KICAgIHBhZ2luZyA9IEZBTFNFDQogICksDQogIGNhcHRpb24gPSBodG1sdG9vbHM6OnRhZ3MkY2FwdGlvbigNCiAgICBzdHlsZSA9ICdjYXB0aW9uLXNpZGU6IHRvcDsgdGV4dC1hbGlnbjogbGVmdDsgDQogICAgICAgICAgICAgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsnDQogICksDQogIGNsYXNzID0gJ3N0cmlwZSBob3ZlciBjb21wYWN0Jw0KKQ0KYGBgDQoNCg0KIyMgMS4yIFRhYmVsIEZyZWt1ZW5zaSANCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIENvdW50IGZyZXF1ZW5jeQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoRFQpDQoNCkhvdXNlaG9sZF9zdW1tYXJ5IDwtIEhvdXNlaG9sZCAlPiUNCiAgY291bnQoUGVuZ2VsdWFyYW4sIHNvcnQgPSBUUlVFKSAlPiUNCiAgcmVuYW1lKEZyZXF1ZW5jeSA9IG4pDQoNCiMgRGlzcGxheSBzdW1tYXJ5IHRhYmxlDQpkYXRhdGFibGUoDQogIEhvdXNlaG9sZF9zdW1tYXJ5LA0KICBvcHRpb25zID0gbGlzdCgNCiAgICBzY3JvbGxDb2xsYXBzZSA9IFRSVUUsDQogICAgc2VhcmNoaW5nID0gRkFMU0UsICAgIyBSZW1vdmUgc2VhcmNoIGJveA0KICAgIHBhZ2luZyA9IEZBTFNFICAgICAgICMgUmVtb3ZlIHBhZ2luYXRpb24NCiAgKSwNCiAgcm93bmFtZXMgPSBGQUxTRSwNCiAgY2FwdGlvbiA9IGh0bWx0b29sczo6dGFncyRjYXB0aW9uKA0KICAgIHN0eWxlID0gJ2NhcHRpb24tc2lkZTogdG9wOyB0ZXh0LWFsaWduOiBsZWZ0OyANCiAgICAgICAgICAgICBmb250LXNpemU6IDE4cHg7IGZvbnQtd2VpZ2h0OiBib2xkOycsDQogICAgJ0ZyZWt1ZW5zaSBQZW5nZWx1YXJhbiBSdW1haCBUYW5nZ2EnDQogICksDQogIGNsYXNzID0gJ3N0cmlwZSBob3ZlciBjb21wYWN0Jw0KKQ0KDQpgYGANCg0KIyMgMS4zIFZpc3VhbGlzYXNpIA0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEludGVyYWN0aXZlIGJhciBjaGFydCB1c2luZyBwbG90bHkNCnBsb3RfbHkoSG91c2Vob2xkX3N1bW1hcnksDQogICAgICAgIHggPSB+RnJlcXVlbmN5LA0KICAgICAgICB5ID0gfnJlb3JkZXIoUGVuZ2VsdWFyYW4sIEZyZXF1ZW5jeSksDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgb3JpZW50YXRpb24gPSAnaCcsDQogICAgICAgIG1hcmtlciA9IGxpc3QoDQogICAgICAgICAgY29sb3IgPSB+RnJlcXVlbmN5LA0KICAgICAgICAgIGNvbG9yc2NhbGUgPSAnVmlyaWRpcycsICAjIENhbiBhbHNvIHRyeTogJ0JsdWVyZWQnLCAnQ2l2aWRpcycsICdZbE9yUmQnDQogICAgICAgICAgc2hvd3NjYWxlID0gVFJVRQ0KICAgICAgICApDQopICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KHRleHQgPSAiRnJla3VlbnNpIFBlbmdlbHVhcmFuIFJ1bWFoIiwgZm9udCA9IGxpc3Qoc2l6ZSA9IDE4KSksDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkZyZXF1ZW5jeSIpLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJQZW5nZWx1YXJhbiIpLA0KICAgIG1hcmdpbiA9IGxpc3QobCA9IDEyMCkNCiAgKQ0KDQpgYGANCg0KDQotLS0NCg0KIyAyLiBIaXN0b2dyYW0gDQoNCiMjIDEuIERhdGFzZXQNCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIEVuc3VyZSBhbGwgcmVxdWlyZWQgcGFja2FnZXMgYXJlIGluc3RhbGxlZA0KcGFja2FnZXMgPC0gYygiZHBseXIiLCAic3RyaW5naSIsICJsdWJyaWRhdGUiLCAiRFQiKQ0KbmV3X3BhY2thZ2VzIDwtIHBhY2thZ2VzWyEocGFja2FnZXMgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssICJQYWNrYWdlIl0pXQ0KaWYobGVuZ3RoKG5ld19wYWNrYWdlcykpIGluc3RhbGwucGFja2FnZXMobmV3X3BhY2thZ2VzKQ0KDQojIExvYWQgbGlicmFyaWVzDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzdHJpbmdpKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KERUKQ0KDQojIyBDcmVhdGUgYSBjb21wbGV4IGR1bW15IGhlYWx0aCBkYXRhc2V0IGZvciBkYXRhIHRyYW5zZm9ybWF0aW9uDQpzZXQuc2VlZCg0MikNCm4gPC0gMzENCg0KIyBTaW11bGF0ZSBsb2NhdGlvbiBhbmQgaGVhbHRoIGNvbmRpdGlvbg0KSmVuaXMgPC0gc2FtcGxlKGMoIk5hc2kgR29yZW5nIiwgIlNvdG8iLCAiU2F5dXIgQXNlbSIsICJTcGFnZXRpIiwgIkF5YW0gR29yZW5nIiksIG4sIHJlcGxhY2UgPSBUUlVFKQ0KDQojIFNpbXVsYXRlIGNvb2tpbmcgdGltZXMgKGluIG1pbnV0ZXMpIGZvciBlYWNoIGZvb2QgdHlwZQ0Kd2FrdHVfbWFzYWsgPC0gYygiTmFzaSBHb3JlbmciID0gMTUsICJTb3RvIiA9IDYwLCAiU2F5dXIgQXNlbSIgPSA0NSwgIlNwYWdldGkiID0gMjAsICJBeWFtIEdvcmVuZyIgPSAzMCkNCldha3R1X01hc2FrIDwtIHNhcHBseShKZW5pcywgZnVuY3Rpb24oeCkgd2FrdHVfbWFzYWtbeF0pDQoNCiMgQ3JlYXRlIHRoZSBkYXRhc2V0DQpIb3VzZWhvbGRfMiA8LSB0aWJibGUoDQogIEplbmlzX01ha2FuYW4gPSBKZW5pcywNCiAgV2FrdHVfTWFzYWsgPSBXYWt0dV9NYXNhaw0KKQ0KDQojIFNob3cgaW50ZXJhY3RpdmUgdGFibGUgd2l0aCBkb3dubG9hZCBidXR0b25zDQpkYXRhdGFibGUoDQogIEhvdXNlaG9sZF8yLA0KICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLA0KICBvcHRpb25zID0gbGlzdCgNCiAgICBkb20gPSAnQmZydGlwJywNCiAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnLCAncGRmJywgJ3ByaW50JyksDQogICAgc2Nyb2xsWSA9ICI0MDBweCIsDQogICAgc2Nyb2xsQ29sbGFwc2UgPSBUUlVFLA0KICAgIHBhZ2luZyA9IEZBTFNFDQogICksDQogIGNhcHRpb24gPSBodG1sdG9vbHM6OnRhZ3MkY2FwdGlvbigNCiAgICBzdHlsZSA9ICdjYXB0aW9uLXNpZGU6IHRvcDsgdGV4dC1hbGlnbjogbGVmdDsgDQogICAgICAgICAgICAgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsnDQogICksDQogIGNsYXNzID0gJ3N0cmlwZSBob3ZlciBjb21wYWN0Jw0KKQ0KDQoNCg0KYGBgDQoNCg0KIyMgMS4zIFZpc3VhbGlzYXNpDQoNCmBgYHtyIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KIyBJbnN0YWxsIGFuZCBsb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShEVCkNCg0KIyBHdW5ha2FuIGtvbG9tIExpc3RyaWsgc2ViYWdhaSBkYXRhIG5vcm1hbA0Kbm9ybWFsX2RhdGEgPC0gSG91c2Vob2xkXzIkV2FrdHVfTWFzYWsNCg0KIyBDYWxjdWxhdGUgdGhlIGRlbnNpdHkgb2YgdGhlIG5vcm1hbCBkYXRhDQpkZW5zaXR5X2RhdGEgPC0gZGVuc2l0eShub3JtYWxfZGF0YSkNCg0KIyBDcmVhdGUgYSBoaXN0b2dyYW0gb2YgdGhlIG5vcm1hbCBkYXRhIHVzaW5nIHBsb3RseQ0KaGlzdG9ncmFtX3Bsb3QgPC0gcGxvdF9seSgNCiAgeCA9IG5vcm1hbF9kYXRhLA0KICB0eXBlID0gJ2hpc3RvZ3JhbScsDQogIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnbGlnaHRibHVlJywgbGluZSA9IGxpc3QoY29sb3IgPSAnYmxhY2snLCB3aWR0aCA9IDEpKSwNCiAgbmFtZSA9ICdIaXN0b2dyYW0gb2YgTm9ybWFsIERhdGEnLA0KICBuYmluc3ggPSAzMCwNCiAgb3BhY2l0eSA9IDAuNiwNCiAgc2hvd2xlZ2VuZCA9IFRSVUUNCikgJT4lDQogICMgQWRkIHRoZSBkZW5zaXR5IGN1cnZlDQogIGFkZF90cmFjZSgNCiAgICB4ID0gZGVuc2l0eV9kYXRhJHgsIA0KICAgIHkgPSBkZW5zaXR5X2RhdGEkeSAqIGxlbmd0aChub3JtYWxfZGF0YSkgKiBkaWZmKHJhbmdlKG5vcm1hbF9kYXRhKSkgLyAzMCwgICMgU2NhbGUgZGVuc2l0eSB0byBoaXN0b2dyYW0NCiAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgIG1vZGUgPSAnbGluZXMnLA0KICAgIG5hbWUgPSAnRGVuc2l0eSBDdXJ2ZScsDQogICAgbGluZSA9IGxpc3QoY29sb3IgPSAnYmxhY2snLCB3aWR0aCA9IDMpLA0KICAgIHNob3dsZWdlbmQgPSBUUlVFDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9ICdIaXN0b2dyYW0gb2YgTm9ybWFsIERpc3RyaWJ1dGlvbiB3aXRoIERlbnNpdHkgQ3VydmUnLA0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICdWYWx1ZScsIHNob3dncmlkID0gRkFMU0UpLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdGcmVxdWVuY3kgLyBEZW5zaXR5Jywgc2hvd2dyaWQgPSBGQUxTRSksDQogICAgYmFyZ2FwID0gMC4xLA0KICAgIHBsb3RfYmdjb2xvciA9ICd3aGl0ZScsDQogICAgcGFwZXJfYmdjb2xvciA9ICd3aGl0ZScsDQogICAgc2hvd2xlZ2VuZCA9IFRSVUUsDQogICAgbGVnZW5kID0gbGlzdCgNCiAgICAgIG9yaWVudGF0aW9uID0gJ3YnLCAgICAjIHZlcnRpY2FsIGxlZ2VuZA0KICAgICAgeCA9IDAuOTgsICAgICAgICAgICAgICMgYWxtb3N0IGF0IHRoZSByaWdodCBlZGdlDQogICAgICB4YW5jaG9yID0gJ3JpZ2h0JywNCiAgICAgIHkgPSAwLjk4LCAgICAgICAgICAgICAjIGFsbW9zdCBhdCB0aGUgdG9wDQogICAgICB5YW5jaG9yID0gJ3RvcCcsDQogICAgICBiZ2NvbG9yID0gJ3JnYmEoMjU1LDI1NSwyNTUsMC44KScsICAjIHNlbWktdHJhbnNwYXJlbnQgYmFja2dyb3VuZA0KICAgICAgYm9yZGVyY29sb3IgPSAnYmxhY2snLA0KICAgICAgYm9yZGVyd2lkdGggPSAwLjMNCiAgICApDQogICkNCg0KIyBTaG93IHRoZSBwbG90DQpoaXN0b2dyYW1fcGxvdA0KDQoNCmBgYA0KDQoNCi0tLQ0KDQojIDMuIFBhcmV0byBDaGFydA0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQoNCiMgTG9hZCBsaWJyYXJpZXMNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KDQojIENyZWF0ZSB0aGUgZGF0YXNldA0Kc2V0LnNlZWQoNDIpDQpuIDwtIDMxDQoNCmRhdGVzIDwtIHNlcS5EYXRlKGZyb20gPSBhcy5EYXRlKCIyMDI1LTA1LTAxIiksIHRvID0gYXMuRGF0ZSgiMjAyNS0wNS0zMSIpLCBieSA9ICJkYXkiKQ0Kc2FtcGxlX2RhdGVzIDwtIHNhbXBsZShkYXRlcywgbiwgcmVwbGFjZSA9IFRSVUUpDQoNClBlbmdlbHVhcmFuIDwtIHNhbXBsZShjKCJMaXN0cmlrIiwgIkJlbGFuamEgTWluZ2d1YW4iLCAiR2FzIExQRyIsICJUcmFuc3BvcnRhc2kiLCAiTWFrYW4gZGkgbHVhciIsICJJbnRlcm5ldCIsICJQZW5nZWx1YXJhbiBkYXJ1cmF0IiwgIlBEQU0iKSwgbiwgcmVwbGFjZSA9IFRSVUUpDQoNCkhvdXNlaG9sZCA8LSB0aWJibGUoDQogIFRhbmdnYWwgPSBzYW1wbGVfZGF0ZXMsDQogIFBlbmdlbHVhcmFuID0gUGVuZ2VsdWFyYW4NCikNCg0KIyBTdW1tYXJpemUgdGhlIG51bWJlciBvZiBkZWxheXMgYnkgcmVhc29uDQpwYXJldG9fZGF0YSA8LSBIb3VzZWhvbGQgJT4lDQogIGNvdW50KFBlbmdlbHVhcmFuLCBzb3J0ID0gVFJVRSkgJT4lDQogIG11dGF0ZSgNCiAgICBjdW1fZnJlcSA9IGN1bXN1bShuKSAvIHN1bShuKSAqIDEwMCAgIyBjdW11bGF0aXZlIHBlcmNlbnRhZ2UNCiAgKQ0KDQojIENyZWF0ZSBkaWZmZXJlbnQgY29sb3JzIGZvciBlYWNoIFJlYXNvbiAoYWRqdXN0ZWQgZm9yIHRoZSBsZW5ndGggb2YgcmVhc29ucykNCmNvbG9ycyA8LSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwobiA9IG1pbigxMiwgbGVuZ3RoKHBhcmV0b19kYXRhJFBlbmdlbHVhcmFuKSksIG5hbWUgPSAiU2V0MyIpDQoNCiMgQ3JlYXRlIFBsb3RseSBQYXJldG8gQ2hhcnQNCmZpZyA8LSBwbG90X2x5KCkNCg0KIyBBZGQgQmFyIENoYXJ0IChDb3VudCkgLSB3aXRoIGRpZmZlcmVudCBjb2xvcnMNCmZpZyA8LSBmaWcgJT4lIGFkZF9iYXJzKA0KICB4ID0gfnJlb3JkZXIocGFyZXRvX2RhdGEkUGVuZ2VsdWFyYW4sIC1wYXJldG9fZGF0YSRuKSwNCiAgeSA9IH5wYXJldG9fZGF0YSRuLA0KICBuYW1lID0gJ051bWJlciBvZiBEZWxheXMnLA0KICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gY29sb3JzKSwNCiAgeWF4aXMgPSAieTEiDQopDQoNCiMgQWRkIEN1bXVsYXRpdmUgTGluZQ0KZmlnIDwtIGZpZyAlPiUgYWRkX2xpbmVzKA0KICB4ID0gfnJlb3JkZXIocGFyZXRvX2RhdGEkUGVuZ2VsdWFyYW4sIC1wYXJldG9fZGF0YSRuKSwNCiAgeSA9IH5wYXJldG9fZGF0YSRjdW1fZnJlcSwNCiAgbmFtZSA9ICdDdW11bGF0aXZlICglKScsDQogIHlheGlzID0gInkyIiwNCiAgbGluZSA9IGxpc3QoY29sb3IgPSAncmVkJywgZGFzaCA9ICdkYXNoJykNCikNCg0KIyBBZGQgQ3V0LW9mZiBMaW5lIGF0IDgwJQ0KZmlnIDwtIGZpZyAlPiUgYWRkX2xpbmVzKA0KICB4ID0gfnJlb3JkZXIocGFyZXRvX2RhdGEkUGVuZ2VsdWFyYW4sIC1wYXJldG9fZGF0YSRuKSwNCiAgeSA9IHJlcCg4MCwgbGVuZ3RoKHBhcmV0b19kYXRhJFBlbmdlbHVhcmFuKSksDQogIG5hbWUgPSAnQ3V0LW9mZiA4MCUnLA0KICB5YXhpcyA9ICJ5MiIsDQogIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2dyZWVuJywgZGFzaCA9ICdkb3QnKQ0KKQ0KDQojIEFkanVzdCBsYXlvdXQNCmZpZyA8LSBmaWcgJT4lIGxheW91dCgNCiAgdGl0bGUgPSAiUGFyZXRvIENoYXJ0IC0gRGVsYXkgUmVhc29ucyIsDQogIHhheGlzID0gbGlzdCgNCiAgICB0aXRsZSA9ICJEZWxheSBSZWFzb25zIiwNCiAgICB0aWNrYW5nbGUgPSAtNDUgICAjIHRpbHQgNDUgZGVncmVlcw0KICApLA0KICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiTnVtYmVyIG9mIERlbGF5cyIpLA0KICB5YXhpczIgPSBsaXN0KA0KICAgIHRpdGxlID0gIkN1bXVsYXRpdmUgKCUpIiwNCiAgICBvdmVybGF5aW5nID0gInkiLA0KICAgIHNpZGUgPSAicmlnaHQiLA0KICAgIHJhbmdlID0gYygwLCAxMDApDQogICksDQogIGxlZ2VuZCA9IGxpc3QoeCA9IDAuOCwgeSA9IDAuNzUpLA0KICBzaGFwZXMgPSBsaXN0KA0KICAgIGxpc3QoDQogICAgICB0eXBlID0gImxpbmUiLA0KICAgICAgeDAgPSAtMC41LA0KICAgICAgeDEgPSBsZW5ndGgocGFyZXRvX2RhdGEkUGVuZ2VsdWFyYW4pIC0gMC41LA0KICAgICAgeTAgPSA4MCwNCiAgICAgIHkxID0gODAsDQogICAgICB5cmVmID0gInkyIiwNCiAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gImdyZWVuIiwgd2lkdGggPSAyLCBkYXNoID0gImRvdCIpDQogICAgKQ0KICApDQopDQoNCiMgU2hvdyBjaGFydA0KZmlnDQoNCg0KYGBgDQoNCi0tLQ0KDQojIDQuIEZpc2hib25lDQoNCmBgYHtyIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KbGlicmFyeShEaWFncmFtbWVSKQ0KbGlicmFyeShyc3ZnKQ0KDQoNCmdyVml6KCINCmRpZ3JhcGggZmlzaGJvbmUgew0KICBncmFwaCBbbGF5b3V0ID0gZG90LCByYW5rZGlyID0gTFJdDQoNCiAgIyBEZWZhdWx0IG5vZGUgc3R5bGVzDQogIG5vZGUgW2ZvbnRuYW1lPUhlbHZldGljYSwgZm9udHNpemU9MjUsIHN0eWxlPWZpbGxlZF0NCg0KICAjIENlbnRyYWwgcHJvYmxlbQ0KICBQcm9ibGVtIFtsYWJlbD0nRGVsYXllZCBcXG4gR29vZHMgRGVsaXZlcnknLCBzaGFwZT1lbGxpcHNlLCBmaWxsY29sb3I9bGlnaHRjb3JhbCwgd2lkdGg9NS4wLCBoZWlnaHQ9MS4yXQ0KDQogICMgQ2F0ZWdvcnkgbm9kZXMgKHNoYXJlZCBzdHlsZSkNCiAgbm9kZSBbc2hhcGU9ZGlhbW9uZCwgd2lkdGg9Mi41LCBoZWlnaHQ9MS4wLCBmaWxsY29sb3I9JyNGRkQ3MDAnXQ0KICBBMSBbbGFiZWw9J0Vrb25vbWknXQ0KICBBMiBbbGFiZWw9J0tvbXVuaWthc2knXQ0KICBBMyBbbGFiZWw9J1BlbWJhZ2lhbiBUdWdhcyddDQogIEE0IFtsYWJlbD0nV2FrdHUnXQ0KICBBNSBbbGFiZWw9J1BvbGEgYXN1aCddDQogDQoNCiAgIyBSZXNldCBub2RlIHN0eWxlIGZvciBzdWItY2F0ZWdvcmllcw0KICBub2RlIFtzaGFwZT1lbGxpcHNlLCB3aWR0aD0yLjUsIGhlaWdodD0wLjYsIGZpbGxjb2xvcj0nIzkwRUU5MCddDQogIEExYSBbbGFiZWw9J1BlbmdlbHVhcmFuIGJlcmxlYmloJ10NCiAgQTFiIFtsYWJlbD0nUGVuZ2hhc2lsYW4gdGlkYWsgdGV0YXAnXQ0KICBBMWMgW2xhYmVsPSdUaWRhayBhZGEgdGFidW5nYW4gZGFydXJhdCddDQoNCiAgQTJhIFtsYWJlbD0nS3VyYW5nIHRlcmJ1a2EnXQ0KICBBMmIgW2xhYmVsPSdTYWxhaCBQYWhhbSddDQoNCiAgQTNhIFtsYWJlbD0nVGlkYWsgQWRpbCddDQogIEEzYiBbbGFiZWw9J1RpZGFrIHNlc3VhaSBrZXNlcGFrYXRhbiddDQoNCiAgQTRhIFtsYWJlbD0nS3VyYW5nbnlhIHdha3R1IGJlcnNhbWEnXQ0KICBBNGIgW2xhYmVsPSdUZXJsYWx1IHNpYnVrIGJla2VyamEnXQ0KDQogIEE1YSBbbGFiZWw9J1BlcmJlZGFhbiBnYXlhIGFzdWgnXQ0KICBBNWIgW2xhYmVsPSdLZXNlcGFrYXRhbiBkYWxhbSBkaXNpcGxpbiddDQoNCg0KICAjIFJlbGF0aW9uc2hpcHMNCiAgQTEgLT4gUHJvYmxlbQ0KICBBMiAtPiBQcm9ibGVtDQogIEEzIC0+IFByb2JsZW0NCiAgQTQgLT4gUHJvYmxlbQ0KICBBNSAtPiBQcm9ibGVtDQoNCiAgQTFhIC0+IEExDQogIEExYiAtPiBBMQ0KICBBMWMgLT4gQTENCg0KICBBMmEgLT4gQTINCiAgQTJiIC0+IEEyDQoNCiAgQTNhIC0+IEEzDQogIEEzYiAtPiBBMw0KDQogIEE0YSAtPiBBNA0KICBBNGIgLT4gQTQNCg0KICBBNWEgLT4gQTUNCiAgQTViIC0+IEE1DQp9DQoiKQ0KDQoNCmBgYA0KDQotLS0NCg0KIyA1LiBTY2F0dGVyIERpYWdyYW0NCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIExvYWQgdGhlIHBsb3RseSBwYWNrYWdlDQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBDcmVhdGUgYSBkYXRhc2V0OiBzbGVlcCBob3VycyB2cyBtb29kIGxldmVsDQpzZXQuc2VlZCg0MikgICMgRm9yIHJlcHJvZHVjaWJpbGl0eQ0KZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBTbGVlcF9Ib3VycyA9IHNlcSg0LCAxMCwgbGVuZ3RoLm91dCA9IDIwKSwgICMgZGFyaSA0IGhpbmdnYSAxMCBqYW0gdGlkdXINCiAgTW9vZF9MZXZlbCA9IHNlcSgzMCwgOTAsIGxlbmd0aC5vdXQgPSAyMCkgICAjIGFzdW1zaSBtb29kIGxldmVsIGFudGFyYSAzMC05MA0KKQ0KDQojIFRhbWJhaGthbiBub2lzZSBhZ2FyIGtvcmVsYXNpIG1lbmRla2F0aSAwLjkNCmRhdGEkTW9vZF9MZXZlbCA8LSBkYXRhJE1vb2RfTGV2ZWwgKyBybm9ybShuID0gMjAsIG1lYW4gPSAwLCBzZCA9IDUpDQoNCiMgSGl0dW5nIGtvZWZpc2llbiBrb3JlbGFzaQ0KY29ycmVsYXRpb25fdmFsdWUgPC0gY29yKGRhdGEkU2xlZXBfSG91cnMsIGRhdGEkTW9vZF9MZXZlbCkNCg0KIyBCdWF0IHNjYXR0ZXIgcGxvdCBtZW5nZ3VuYWthbiBQbG90bHkgZGVuZ2FuIGdhcmlzIHJlZ3Jlc2kgbGluaWVyDQpmaWcgPC0gcGxvdF9seShkYXRhLCANCiAgICAgICAgICAgICAgIHggPSB+U2xlZXBfSG91cnMsIA0KICAgICAgICAgICAgICAgeSA9IH5Nb29kX0xldmVsLCANCiAgICAgICAgICAgICAgIHR5cGUgPSAnc2NhdHRlcicsIA0KICAgICAgICAgICAgICAgbW9kZSA9ICdtYXJrZXJzJywNCiAgICAgICAgICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnYmx1ZScsIHNpemUgPSAxMCkpICU+JQ0KICBhZGRfbGluZXMoeCA9IGRhdGEkU2xlZXBfSG91cnMsIA0KICAgICAgICAgICAgeSA9IHByZWRpY3QobG0oTW9vZF9MZXZlbCB+IFNsZWVwX0hvdXJzLCBkYXRhID0gZGF0YSkpLCANCiAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JlZCcsIGRhc2ggPSAnc29saWQnLCB3aWR0aCA9IDIpKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gcGFzdGUoIlNjYXR0ZXIgUGxvdDogSHVidW5nYW4gYW50YXJhIEphbSBUaWR1ciBkYW4gU3Vhc2FuYSBIYXRpXG5Lb3JlbGFzaTogIiwgcm91bmQoY29ycmVsYXRpb25fdmFsdWUsIDIpKSwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJKYW0gVGlkdXIiKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJTdWFzYW5hIEhhdGkiKSkNCg0KIyBUYW1waWxrYW4gcGxvdA0KZmlnDQoNCmBgYA0KDQotLS0NCg0KIyA2LiBDb250cm9sIENoYXJ0IA0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgTG9hZCBsaWJyYXJpZXMNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShkcGx5cikNCg0KIyBTaW11bGFzaSBkYXRhIGJlcmF0IGtlbWFzYW4gcGVyIGhhcmkgKGNvbnRvaCkNCnNldC5zZWVkKDEpDQpkZiA8LSB0aWJibGUoDQogIEhhcmkgPSAxOjMwLA0KICBCZXJhdCA9IHJvdW5kKHJub3JtKDMwLCBtZWFuID0gNTAwLCBzZCA9IDUpLCAxKQ0KKQ0KDQojIFRlbnR1a2FuIGJhdGFzIGtlbmRhbGkgKENMLCBVQ0wsIExDTCkNCkNMIDwtIG1lYW4oZGYkQmVyYXQsIG5hLnJtID0gVFJVRSkNClVDTCA8LSBDTCArIDMgKiBzZChkZiRCZXJhdCwgbmEucm0gPSBUUlVFKQ0KTENMIDwtIENMIC0gMyAqIHNkKGRmJEJlcmF0LCBuYS5ybSA9IFRSVUUpDQoNCiMgVGFuZGFpIG91dGxpZXINCmRmIDwtIGRmICU+JQ0KICBtdXRhdGUoT3V0bGllciA9IGlmZWxzZShCZXJhdCA+IFVDTCB8IEJlcmF0IDwgTENMLCAiWWEiLCAiVGlkYWsiKSkNCg0KIyBCdWF0IHBsb3QNCnBsb3RfbHkoZGYsIHggPSB+SGFyaSwgeSA9IH5CZXJhdCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnYmx1ZScpLCANCiAgICAgICAgbWFya2VyID0gbGlzdChzaXplID0gOCwgY29sb3IgPSBpZmVsc2UoZGYkT3V0bGllciA9PSAiWWEiLCAicmVkIiwgImJsdWUiKSksDQogICAgICAgIGhvdmVyaW5mbyA9ICd0ZXh0JywNCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgiSGFyaToiLCBIYXJpLCAiPGJyPkJlcmF0OiIsIEJlcmF0LCAiZ3JhbSIpKSAlPiUNCiAgYWRkX2xpbmVzKHkgPSByZXAoQ0wsIG5yb3coZGYpKSwgbmFtZSA9ICJDTCIsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2dyZWVuJywgZGFzaCA9ICdkb3QnKSkgJT4lDQogIGFkZF9saW5lcyh5ID0gcmVwKFVDTCwgbnJvdyhkZikpLCBuYW1lID0gIlVDTCIsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JlZCcsIGRhc2ggPSAnZG90JykpICU+JQ0KICBhZGRfbGluZXMoeSA9IHJlcChMQ0wsIG5yb3coZGYpKSwgbmFtZSA9ICJMQ0wiLCBsaW5lID0gbGlzdChjb2xvciA9ICdyZWQnLCBkYXNoID0gJ2RvdCcpKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIkNvbnRyb2wgQ2hhcnQg4oCTIEJlcmF0IEtlbWFzYW4gUHJvZHVrIiwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJIYXJpIiksDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQmVyYXQgKGdyYW0pIiksDQogICAgICAgICBsZWdlbmQgPSBsaXN0KG9yaWVudGF0aW9uID0gJ2gnLCB4ID0gMC4zLCB5ID0gLTAuMikpDQpgYGANCg0KDQoNCi0tLQ0KDQojIDcuIEZsb3djaGFydA0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmxpYnJhcnkoRGlhZ3JhbW1lUikNCg0KZ3JWaXooIg0KZGlncmFwaCBzaXN0ZW1fa2VnaWF0YW5fcnVtYWhfdGFuZ2dhIHsNCg0KICBncmFwaCBbbGF5b3V0ID0gZG90LCByYW5rZGlyID0gVEJdDQoNCiAgbm9kZSBbc2hhcGUgPSBib3gsIHN0eWxlID0gZmlsbGVkLCBmb250c2l6ZSA9IDEyXQ0KDQogICMgTm9kZSBkZWZpbmlzaQ0KICBsYWJlbDEgW2xhYmVsID0gJ011bGFpJywgc2hhcGUgPSBlbGxpcHNlLCBjb2xvciA9IGxpZ2h0Z3JlZW5dDQogIGxhYmVsMiBbbGFiZWwgPSAnSW5naW4gbGFuZ3N1bmdcbm1hc2FrPycsIHNoYXBlID0gZGlhbW9uZCwgY29sb3IgPSBvcmFuZ2VdDQogIGxhYmVsMyBbbGFiZWwgPSAnTWFzYWsnLCBzaGFwZSA9IGJveCwgY29sb3IgPSBwaW5rXQ0KICBsYWJlbDQgW2xhYmVsID0gJ0Jhbmd1biBUaWR1cicsIHNoYXBlID0gcGFyYWxsZWxvZ3JhbSwgY29sb3IgPSBsaWdodGJsdWVdDQogIGxhYmVsNSBbbGFiZWwgPSAnU3VkYWggc2VsZXNhaVxuc2VtdWE/Jywgc2hhcGUgPSBkaWFtb25kLCBjb2xvciA9IG9yYW5nZV0NCiAgbGFiZWw2IFtsYWJlbCA9ICdJc3RpcmFoYXQnLCBzaGFwZSA9IHRyYXBleml1bSwgY29sb3IgPSB0aGlzdGxlXQ0KICBsYWJlbDcgW2xhYmVsID0gJ1NlbGVzYWknLCBzaGFwZSA9IGVsbGlwc2UsIGNvbG9yID0gbGlnaHRncmVlbl0NCg0KICAjIEVkZ2UgKGFsdXIpDQogIGxhYmVsMSAtPiBsYWJlbDINCiAgbGFiZWwyIC0+IGxhYmVsMyBbbGFiZWwgPSAnWWEnXQ0KICBsYWJlbDIgLT4gbGFiZWw0IFtsYWJlbCA9ICdUaWRhayddDQogIGxhYmVsMyAtPiBsYWJlbDUNCiAgbGFiZWw0IC0+IGxhYmVsNQ0KICBsYWJlbDUgLT4gbGFiZWw3IFtsYWJlbCA9ICdZYSddDQogIGxhYmVsNSAtPiBsYWJlbDYgW2xhYmVsID0gJ1RpZGFrJ10NCiAgbGFiZWw2IC0+IGxhYmVsNw0KfQ0KIikNCg0KDQpgYGANCg0K