Pemprogram Sains Data
UTS Pemprograman Sains Data
1 Check Sheet
- Data Check Sheet
- Frequency Tabulation
# Hitung frekuensi tiap jenis cacat produk
library(dplyr)
library(DT)
# Asumsikan data dummy sebelumnya sudah dibuat dan bernama 'bread_data'
defect_summary <- bread_data %>%
count(Jenis_Cacat, sort = TRUE) %>%
rename(Frekuensi = n)
# Tampilkan tabel ringkasan
datatable(
defect_summary,
options = list(
scrollCollapse = TRUE,
searching = FALSE,
paging = FALSE
),
rownames = FALSE,
caption = htmltools::tags$caption(
style = 'caption-side: top; text-align: left;
font-size: 18px; font-weight: bold;',
'Check Sheet: Frekuensi Jenis Cacat Produk'
),
class = 'stripe hover compact'
)- Visualisasi
library(dplyr)
reason_summary <- bread_data %>%
group_by(Jenis_Cacat) %>%
summarise(Frequency = sum(Jumlah_Cacat, na.rm = TRUE)) %>%
arrange(desc(Frequency)) %>%
rename(Reason = Jenis_Cacat)
library(plotly)## Loading required package: ggplot2
## Warning: package 'ggplot2' was built under R version 4.4.3
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
# Visualisasi horizontal bar chart
plot_ly(reason_summary,
x = ~Frequency,
y = ~reorder(Reason, Frequency),
type = 'bar',
orientation = 'h',
marker = list(
color = ~Frequency,
colorscale = 'Viridis',
showscale = TRUE
)
) %>%
layout(
title = list(text = "Check Sheet: Frekuensi Jenis Cacat Produk Roti", font = list(size = 18)),
xaxis = list(title = "Frekuensi"),
yaxis = list(title = "Jenis Cacat"),
margin = list(l = 120)
)2 Histogram
# Install and load necessary libraries
if (!require("plotly")) install.packages("plotly")
library(plotly)
# Gunakan data aktual dari bread_data
actual_data <- bread_data$Berat_Batch_kg
# Hitung kurva densitas
density_data <- density(actual_data)
# Buat histogram menggunakan plotly
histogram_plot <- plot_ly(
x = actual_data,
type = 'histogram',
marker = list(color = 'lightblue', line = list(color = 'black', width = 1)),
name = 'Histogram Berat Batch (kg)',
nbinsx = 30,
opacity = 0.6,
showlegend = TRUE
) %>%
# Tambahkan kurva densitas
add_trace(
x = density_data$x,
y = density_data$y * length(actual_data) * diff(range(actual_data)) / 30,
type = 'scatter',
mode = 'lines',
name = 'Kurva Densitas',
line = list(color = 'black', width = 3),
showlegend = TRUE
) %>%
layout(
title = 'Histogram Berat Batch (kg) dengan Kurva Densitas',
xaxis = list(title = 'Berat Batch (kg)', showgrid = FALSE),
yaxis = list(title = 'Frekuensi / Densitas', showgrid = FALSE),
bargap = 0.1,
plot_bgcolor = 'white',
paper_bgcolor = 'white',
showlegend = TRUE,
legend = list(
orientation = 'v',
x = 0.98,
xanchor = 'right',
y = 0.98,
yanchor = 'top',
bgcolor = 'rgba(255,255,255,0.8)',
bordercolor = 'black',
borderwidth = 0.3
)
)
# Tampilkan plot
histogram_plot## A marker object has been specified, but markers is not in the mode
## Adding markers to the mode...
## Warning: 'scatter' objects don't have these attributes: 'nbinsx'
## Valid attributes include:
## 'cliponaxis', 'connectgaps', 'customdata', 'customdatasrc', 'dx', 'dy', 'error_x', 'error_y', 'fill', 'fillcolor', 'fillpattern', 'groupnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hoveron', 'hovertemplate', 'hovertemplatesrc', 'hovertext', 'hovertextsrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'line', 'marker', 'meta', 'metasrc', 'mode', 'name', 'opacity', 'orientation', 'selected', 'selectedpoints', 'showlegend', 'stackgaps', 'stackgroup', 'stream', 'text', 'textfont', 'textposition', 'textpositionsrc', 'textsrc', 'texttemplate', 'texttemplatesrc', 'transforms', 'type', 'uid', 'uirevision', 'unselected', 'visible', 'x', 'x0', 'xaxis', 'xcalendar', 'xhoverformat', 'xperiod', 'xperiod0', 'xperiodalignment', 'xsrc', 'y', 'y0', 'yaxis', 'ycalendar', 'yhoverformat', 'yperiod', 'yperiod0', 'yperiodalignment', 'ysrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
3 Pareto Chart
# Load libraries
library(dplyr)
library(plotly)
library(RColorBrewer)
# Filter data hanya untuk produk cacat
defective_data <- bread_data %>%
filter(Jumlah_Cacat > 0)
# Summarize frekuensi jenis cacat
pareto_data <- defective_data %>%
count(Jenis_Cacat, sort = TRUE) %>%
mutate(
cum_freq = cumsum(n) / sum(n) * 100 # persentase kumulatif
)
# Generate warna berbeda untuk setiap jenis cacat
colors <- RColorBrewer::brewer.pal(n = max(3, min(12, nrow(pareto_data))), name = "Set3")
# Buat objek plotly
fig <- plot_ly()
# Tambahkan Bar Chart (jumlah cacat)
fig <- fig %>% add_bars(
x = ~reorder(pareto_data$Jenis_Cacat, -pareto_data$n),
y = ~pareto_data$n,
name = 'Jumlah Cacat',
marker = list(color = colors),
yaxis = "y1"
)
# Tambahkan garis kumulatif
fig <- fig %>% add_lines(
x = ~reorder(pareto_data$Jenis_Cacat, -pareto_data$n),
y = ~pareto_data$cum_freq,
name = 'Kumulatif (%)',
yaxis = "y2",
line = list(color = 'red', dash = 'dash')
)
# Tambahkan garis cutoff 80%
fig <- fig %>% add_lines(
x = ~reorder(pareto_data$Jenis_Cacat, -pareto_data$n),
y = rep(80, nrow(pareto_data)),
name = 'Cut-off 80%',
yaxis = "y2",
line = list(color = 'green', dash = 'dot')
)
# Layout akhir
fig <- fig %>% layout(
title = "Pareto Chart - Jenis Cacat Produk",
xaxis = list(
title = "Jenis Cacat",
tickangle = -45
),
yaxis = list(title = "Jumlah Cacat"),
yaxis2 = list(
title = "Kumulatif (%)",
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 = nrow(pareto_data) - 0.5,
y0 = 80,
y1 = 80,
yref = "y2",
line = list(color = "green", width = 2, dash = "dot")
)
)
)
# Tampilkan chart
fig4 Fishbone
## Warning: package 'DiagrammeR' was built under R version 4.4.3
## Warning: package 'DiagrammeRsvg' was built under R version 4.4.3
## Warning: package 'rsvg' was built under R version 4.4.3
## Linking to librsvg 2.57.0
library(knitr)
graph <- grViz("
digraph fishbone {
graph [layout = dot, rankdir = LR]
node [fontname=Helvetica, fontsize=25, style=filled]
Problem [label='Cacat Produk Roti', shape=ellipse, fillcolor=lightcoral, width=5.0, height=1.2]
# Kategori utama
node [shape=diamond, width=2.5, height=1.0, fillcolor='#FFD700']
Man [label='Man']
Machine [label='Machine']
Method [label='Method']
Material [label='Material']
Environment [label='Environment']
Measurement [label='Measurement']
# Subkategori
node [shape=ellipse, width=2.5, height=0.6, fillcolor='#90EE90']
# Man
Man1 [label='Kurangnya pelatihan operator']
Man2 [label='Kelelahan saat shift malam']
# Machine
Machine1 [label='Suhu mesin tidak stabil']
Machine2 [label='Mesin sering rusak']
# Method
Method1 [label='Prosedur standar tidak diikuti']
Method2 [label='Kontrol kualitas tidak konsisten']
# Material
Material1 [label='Bahan baku tidak segar']
Material2 [label='Komposisi adonan tidak tepat']
# Environment
Environment1 [label='Kelembaban tinggi di musim hujan']
Environment2 [label='Ventilasi pabrik buruk']
# Measurement
Measurement1 [label='Alat ukur kalibrasi buruk']
Measurement2 [label='Data produksi tidak akurat']
# Hubungkan kategori ke masalah
Man -> Problem
Machine -> Problem
Method -> Problem
Material -> Problem
Environment -> Problem
Measurement -> Problem
# Hubungkan subkategori ke kategori
Man1 -> Man
Man2 -> Man
Machine1 -> Machine
Machine2 -> Machine
Method1 -> Method
Method2 -> Method
Material1 -> Material
Material2 -> Material
Environment1 -> Environment
Environment2 -> Environment
Measurement1 -> Measurement
Measurement2 -> Measurement
}
")
# Simpan sebagai gambar
dir.create("images/bab8", recursive = TRUE, showWarnings = FALSE)
svg_code <- export_svg(graph)
rsvg_png(charToRaw(svg_code), file = "images/bab8/fishbone_roti_qc.png", width = 3000, height = 3000)
rsvg_pdf(charToRaw(svg_code), file = "images/bab8/fishbone_roti_qc.pdf")
# Tampilkan dalam laporan
knitr::include_graphics("images/bab8/fishbone_roti_qc.png")5 Scatter Diagram
# Pastikan package sudah terinstal
# install.packages("plotly") # Jika belum terinstal
library(plotly)
# Scatter plot suhu mesin vs jumlah cacat
correlation_value <- cor(bread_data$Suhu_Mesin_C, bread_data$Jumlah_Cacat)
fig <- plot_ly(
data = bread_data,
x = ~Suhu_Mesin_C,
y = ~Jumlah_Cacat,
type = 'scatter',
mode = 'markers',
marker = list(color = 'black', size = 7)
) %>%
add_lines(
x = bread_data$Suhu_Mesin_C,
y = predict(lm(Jumlah_Cacat ~ Suhu_Mesin_C, data = bread_data)),
line = list(color = 'red', dash = 'solid')
) %>%
layout(
title = paste("Scatter Plot: Suhu Mesin vs Jumlah Cacat\nKorelasi:", round(correlation_value, 2)),
xaxis = list(title = "Suhu Mesin (°C)"),
yaxis = list(title = "Jumlah Cacat")
)
# Tampilkan plot
fig## A marker object has been specified, but markers is not in the mode
## Adding markers to the mode...
6 Control Chart
library(plotly)
library(dplyr)
# Ambil data berat batch dan urutkan berdasarkan tanggal
berat_data <- bread_data %>%
arrange(Tanggal) %>%
mutate(Hari = row_number()) %>%
select(Hari, Tanggal, Berat = Berat_Batch_kg)
# Tentukan batas kendali berdasarkan rata-rata dan standar deviasi
CL <- mean(berat_data$Berat)
SD <- sd(berat_data$Berat)
UCL <- CL + 3 * SD
LCL <- CL - 3 * SD
# Tandai outlier
berat_data <- berat_data %>%
mutate(Outlier = ifelse(Berat > UCL | Berat < LCL, "Ya", "Tidak"))
# Buat plot kontrol chart
plot_ly(berat_data, x = ~Hari, y = ~Berat, type = 'scatter', mode = 'lines+markers',
line = list(color = 'red'),
marker = list(size = 8, color = ifelse(berat_data$Outlier == "Ya", "red", "blue")),
hoverinfo = 'text',
text = ~paste("Tanggal:", Tanggal, "<br>Berat:", Berat, "kg")) %>%
add_lines(y = rep(CL, nrow(berat_data)), name = "CL", line = list(color = 'green', dash = 'dot')) %>%
add_lines(y = rep(UCL, nrow(berat_data)), name = "UCL", line = list(color = 'red', dash = 'dot')) %>%
add_lines(y = rep(LCL, nrow(berat_data)), name = "LCL", line = list(color = 'red', dash = 'dot')) %>%
layout(title = "Control Chart – Konsistensi Berat Batch Produk Roti",
xaxis = list(title = "Urutan Batch (Hari Produksi)"),
yaxis = list(title = "Berat Batch (kg)"),
legend = list(orientation = 'h', x = 0.3, y = -0.2))## A marker object has been specified, but markers is not in the mode
## Adding markers to the mode...
## A marker object has been specified, but markers is not in the mode
## Adding markers to the mode...
## A marker object has been specified, but markers is not in the mode
## Adding markers to the mode...
7 Flowchart
LS0tDQp0aXRsZTogIlBlbXByb2dyYW0gU2FpbnMgRGF0YSINCnN1YnRpdGxlOiAiVVRTIFBlbXByb2dyYW1hbiBTYWlucyBEYXRhIg0KYXV0aG9yOiANCiAgLSAiTm92YSBTaXRvcnVzIDUyMjQwMDIzIg0KICAtICJPbGl2aWEiDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNzczogInN0eWxlL3N0eWxlIGNzcy5jc3MiDQotLS0NCg0KIyBDaGVjayBTaGVldA0KDQoxLiBEYXRhIENoZWNrIFNoZWV0DQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyBQYXN0aWthbiBzZW11YSBwYWNrYWdlIHRlcmluc3RhbA0KcGFja2FnZXMgPC0gYygiZHBseXIiLCAic3RyaW5naSIsICJsdWJyaWRhdGUiLCAiRFQiKQ0KbmV3X3BhY2thZ2VzIDwtIHBhY2thZ2VzWyEocGFja2FnZXMgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssICJQYWNrYWdlIl0pXQ0KaWYobGVuZ3RoKG5ld19wYWNrYWdlcykpIGluc3RhbGwucGFja2FnZXMobmV3X3BhY2thZ2VzKQ0KDQojIFBhbmdnaWwgbGlicmFyeSB5YW5nIGRpYnV0dWhrYW4NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHN0cmluZ2kpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoRFQpDQoNCiMgQnVhdCBkYXRhIGR1bW15IHByb2R1a3NpIHJvdGkNCnNldC5zZWVkKDQyKQ0KbiA8LSAzMDANCg0KZGF0ZXMgPC0gc2VxLkRhdGUoZnJvbSA9IGFzLkRhdGUoIjIwMjQtMDEtMDEiKSwgdG8gPSBhcy5EYXRlKCIyMDI0LTEyLTMxIiksIGJ5ID0gImRheSIpDQpzYW1wbGVfZGF0ZXMgPC0gc2FtcGxlKGRhdGVzLCBuLCByZXBsYWNlID0gVFJVRSkNCg0KIyBTaW11bGFzaSBkYXRhIHByb2R1a3NpIHJvdGkNCmJyZWFkX3R5cGVzIDwtIGMoIlJvdGkgVGF3YXIiLCAiUm90aSBNYW5pcyIsICJSb3RpIEdhbmR1bSIsICJSb3RpIElzaSBDb2tsYXQiLCAiUm90aSBJc2kgS2VqdSIpDQpkZWZlY3RfdHlwZXMgPC0gYygiR29zb25nIiwgIlRpZGFrIE1lbmdlbWJhbmciLCAiSXNpIFRpZGFrIE1lcmF0YSIsICJCZW50dWsgVGlkYWsgTm9ybWFsIiwgIktlbWFzIFJ1c2FrIiwgIlRpZGFrIEFkYSBDYWNhdCIpDQpsb2NhdGlvbnMgPC0gYygiSmFrYXJ0YSIsICJCYW5kdW5nIiwgIlN1cmFiYXlhIiwgIk1lZGFuIiwgIk1ha2Fzc2FyIikNCnNoaWZ0cyA8LSBjKCJQYWdpIiwgIlNpYW5nIiwgIk1hbGFtIikNCm1hY2hpbmVzIDwtIHBhc3RlMCgiTUMtIiwgc3ByaW50ZigiJTAzZCIsIDE6MjApKQ0KDQojIFRhbWJhaGFuIHZhcmlhYmVsIHVudHVrIFFDDQpiYXRjaF93ZWlnaHRzIDwtIHJvdW5kKHJub3JtKG4sIG1lYW4gPSA1MCwgc2QgPSA1KSwgMSkgICMgQmVyYXQgcGVyIGJhdGNoIChrZykNCmRlZmVjdF9xdHkgPC0gc2FtcGxlKDA6MzAsIG4sIHJlcGxhY2UgPSBUUlVFKQ0KcHJvZF9xdHkgPC0gc2FtcGxlKDk1MDoxMDUwLCBuLCByZXBsYWNlID0gVFJVRSkNCnByb2Nlc3NfdGltZSA8LSByb3VuZChybm9ybShuLCBtZWFuID0gNDUsIHNkID0gNyksIDEpICAjIFdha3R1IHByb3NlcyAobWVuaXQpDQp0ZW1wX21hY2hpbmUgPC0gcm91bmQocm5vcm0obiwgbWVhbiA9IDE4MCwgc2QgPSAxMCksIDEpICAjIFN1aHUgbWVzaW4gKMKwQykNCg0KIyBNdXNpbSBwcm9kdWtzaQ0Kc2Vhc29uIDwtIGNhc2Vfd2hlbigNCiAgbW9udGgoc2FtcGxlX2RhdGVzKSAlaW4lIGMoMTEsIDEyLCAxLCAyKSB+ICJNdXNpbSBIdWphbiIsDQogIG1vbnRoKHNhbXBsZV9kYXRlcykgJWluJSBjKDYsIDcsIDgsIDkpIH4gIk11c2ltIEtlbWFyYXUiLA0KICBUUlVFIH4gIk11c2ltIFBlcmFsaWhhbiINCikNCg0KIyBEYXRhc2V0IHByb2R1a3NpIHJvdGkNCmJyZWFkX2RhdGEgPC0gdGliYmxlKA0KICBCYXRjaF9JRCA9IHN0cmlfcmFuZF9zdHJpbmdzKG4sIDEwKSwNCiAgVGFuZ2dhbCA9IHNhbXBsZV9kYXRlcywNCiAgTG9rYXNpID0gc2FtcGxlKGxvY2F0aW9ucywgbiwgcmVwbGFjZSA9IFRSVUUpLA0KICBTaGlmdCA9IHNhbXBsZShzaGlmdHMsIG4sIHJlcGxhY2UgPSBUUlVFKSwNCiAgSmVuaXNfUm90aSA9IHNhbXBsZShicmVhZF90eXBlcywgbiwgcmVwbGFjZSA9IFRSVUUpLA0KICBJRF9NZXNpbiA9IHNhbXBsZShtYWNoaW5lcywgbiwgcmVwbGFjZSA9IFRSVUUpLA0KICBCZXJhdF9CYXRjaF9rZyA9IGJhdGNoX3dlaWdodHMsDQogIEp1bWxhaF9Qcm9kdWtzaSA9IHByb2RfcXR5LA0KICBKZW5pc19DYWNhdCA9IHNhbXBsZShkZWZlY3RfdHlwZXMsIG4sIHJlcGxhY2UgPSBUUlVFKSwNCiAgSnVtbGFoX0NhY2F0ID0gZGVmZWN0X3F0eSwNCiAgV2FrdHVfUHJvc2VzX21lbml0ID0gcHJvY2Vzc190aW1lLA0KICBTdWh1X01lc2luX0MgPSB0ZW1wX21hY2hpbmUsDQogIE11c2ltID0gc2Vhc29uDQopDQoNCiMgVGFtcGlsa2FuIHRhYmVsIGludGVyYWt0aWYNCmRhdGF0YWJsZSgNCiAgYnJlYWRfZGF0YSwNCiAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgZG9tID0gJ0JmcnRpcCcsDQogICAgYnV0dG9ucyA9IGMoJ2NvcHknLCAnY3N2JywgJ2V4Y2VsJywgJ3BkZicsICdwcmludCcpLA0KICAgIHNjcm9sbFkgPSAiNDAwcHgiLA0KICAgIHNjcm9sbENvbGxhcHNlID0gVFJVRSwNCiAgICBwYWdpbmcgPSBGQUxTRQ0KICApLA0KICBjYXB0aW9uID0gaHRtbHRvb2xzOjp0YWdzJGNhcHRpb24oDQogICAgc3R5bGUgPSAnY2FwdGlvbi1zaWRlOiB0b3A7IHRleHQtYWxpZ246IGxlZnQ7IGZvbnQtc2l6ZTogMThweDsgZm9udC13ZWlnaHQ6IGJvbGQ7JywNCiAgICAiRGF0YSBEdW1teSBQcm9kdWtzaSBSb3RpICYgS2VjYWNhdGFuIFByb2R1ayINCiAgKSwNCiAgY2xhc3MgPSAnc3RyaXBlIGhvdmVywqBjb21wYWN0Jw0KKQ0KYGBgDQoNCjIuIEZyZXF1ZW5jeSBUYWJ1bGF0aW9uDQpgYGB7ciBlY2hvPVRSVUV9DQojIEhpdHVuZyBmcmVrdWVuc2kgdGlhcCBqZW5pcyBjYWNhdCBwcm9kdWsNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KERUKQ0KDQojIEFzdW1zaWthbiBkYXRhIGR1bW15IHNlYmVsdW1ueWEgc3VkYWggZGlidWF0IGRhbiBiZXJuYW1hICdicmVhZF9kYXRhJw0KDQpkZWZlY3Rfc3VtbWFyeSA8LSBicmVhZF9kYXRhICU+JQ0KICBjb3VudChKZW5pc19DYWNhdCwgc29ydCA9IFRSVUUpICU+JQ0KICByZW5hbWUoRnJla3VlbnNpID0gbikNCg0KIyBUYW1waWxrYW4gdGFiZWwgcmluZ2thc2FuDQpkYXRhdGFibGUoDQogIGRlZmVjdF9zdW1tYXJ5LA0KICBvcHRpb25zID0gbGlzdCgNCiAgICBzY3JvbGxDb2xsYXBzZSA9IFRSVUUsDQogICAgc2VhcmNoaW5nID0gRkFMU0UsDQogICAgcGFnaW5nID0gRkFMU0UNCiAgKSwNCiAgcm93bmFtZXMgPSBGQUxTRSwNCiAgY2FwdGlvbiA9IGh0bWx0b29sczo6dGFncyRjYXB0aW9uKA0KICAgIHN0eWxlID0gJ2NhcHRpb24tc2lkZTogdG9wOyB0ZXh0LWFsaWduOiBsZWZ0Ow0KICAgICAgICAgICAgIGZvbnQtc2l6ZTogMThweDsgZm9udC13ZWlnaHQ6IGJvbGQ7JywNCiAgICAnQ2hlY2sgU2hlZXQ6IEZyZWt1ZW5zaSBKZW5pcyBDYWNhdCBQcm9kdWsnDQogICksDQogIGNsYXNzID0gJ3N0cmlwZSBob3ZlcsKgY29tcGFjdCcNCikNCmBgYA0KDQozLiBWaXN1YWxpc2FzaQ0KDQpgYGB7ciBlY2hvPVRSVUV9DQpsaWJyYXJ5KGRwbHlyKQ0KDQpyZWFzb25fc3VtbWFyeSA8LSBicmVhZF9kYXRhICU+JQ0KICBncm91cF9ieShKZW5pc19DYWNhdCkgJT4lDQogIHN1bW1hcmlzZShGcmVxdWVuY3kgPSBzdW0oSnVtbGFoX0NhY2F0LCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgYXJyYW5nZShkZXNjKEZyZXF1ZW5jeSkpICU+JQ0KICByZW5hbWUoUmVhc29uID0gSmVuaXNfQ2FjYXQpDQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBWaXN1YWxpc2FzaSBob3Jpem9udGFsIGJhciBjaGFydA0KcGxvdF9seShyZWFzb25fc3VtbWFyeSwNCiAgICAgICAgeCA9IH5GcmVxdWVuY3ksDQogICAgICAgIHkgPSB+cmVvcmRlcihSZWFzb24sIEZyZXF1ZW5jeSksDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgb3JpZW50YXRpb24gPSAnaCcsDQogICAgICAgIG1hcmtlciA9IGxpc3QoDQogICAgICAgICAgY29sb3IgPSB+RnJlcXVlbmN5LA0KICAgICAgICAgIGNvbG9yc2NhbGUgPSAnVmlyaWRpcycsDQogICAgICAgICAgc2hvd3NjYWxlID0gVFJVRQ0KICAgICAgICApDQopICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KHRleHQgPSAiQ2hlY2sgU2hlZXQ6IEZyZWt1ZW5zaSBKZW5pcyBDYWNhdCBQcm9kdWsgUm90aSIsIGZvbnQgPSBsaXN0KHNpemUgPSAxOCkpLA0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJGcmVrdWVuc2kiKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSmVuaXMgQ2FjYXQiKSwNCiAgICBtYXJnaW4gPSBsaXN0KGwgPSAxMjApDQogICkNCg0KYGBgDQoNCiMgSGlzdG9ncmFtDQpgYGB7ciBlY2hvPVRSVUV9DQojIEluc3RhbGwgYW5kIGxvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcw0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEd1bmFrYW4gZGF0YSBha3R1YWwgZGFyaSBicmVhZF9kYXRhDQphY3R1YWxfZGF0YSA8LSBicmVhZF9kYXRhJEJlcmF0X0JhdGNoX2tnDQoNCiMgSGl0dW5nIGt1cnZhIGRlbnNpdGFzDQpkZW5zaXR5X2RhdGEgPC0gZGVuc2l0eShhY3R1YWxfZGF0YSkNCg0KIyBCdWF0IGhpc3RvZ3JhbSBtZW5nZ3VuYWthbiBwbG90bHkNCmhpc3RvZ3JhbV9wbG90IDwtIHBsb3RfbHkoDQogIHggPSBhY3R1YWxfZGF0YSwNCiAgdHlwZSA9ICdoaXN0b2dyYW0nLA0KICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ2xpZ2h0Ymx1ZScsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2JsYWNrJywgd2lkdGggPSAxKSksDQogIG5hbWUgPSAnSGlzdG9ncmFtIEJlcmF0IEJhdGNoIChrZyknLA0KICBuYmluc3ggPSAzMCwNCiAgb3BhY2l0eSA9IDAuNiwNCiAgc2hvd2xlZ2VuZCA9IFRSVUUNCikgJT4lDQogICMgVGFtYmFoa2FuIGt1cnZhIGRlbnNpdGFzDQogIGFkZF90cmFjZSgNCiAgICB4ID0gZGVuc2l0eV9kYXRhJHgsDQogICAgeSA9IGRlbnNpdHlfZGF0YSR5ICogbGVuZ3RoKGFjdHVhbF9kYXRhKSAqIGRpZmYocmFuZ2UoYWN0dWFsX2RhdGEpKSAvIDMwLA0KICAgIHR5cGUgPSAnc2NhdHRlcicsDQogICAgbW9kZSA9ICdsaW5lcycsDQogICAgbmFtZSA9ICdLdXJ2YSBEZW5zaXRhcycsDQogICAgbGluZSA9IGxpc3QoY29sb3IgPSAnYmxhY2snLCB3aWR0aCA9IDMpLA0KICAgIHNob3dsZWdlbmQgPSBUUlVFDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9ICdIaXN0b2dyYW0gQmVyYXQgQmF0Y2ggKGtnKSBkZW5nYW4gS3VydmEgRGVuc2l0YXMnLA0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICdCZXJhdCBCYXRjaCAoa2cpJywgc2hvd2dyaWQgPSBGQUxTRSksDQogICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ0ZyZWt1ZW5zaSAvIERlbnNpdGFzJywgc2hvd2dyaWQgPSBGQUxTRSksDQogICAgYmFyZ2FwID0gMC4xLA0KICAgIHBsb3RfYmdjb2xvciA9ICd3aGl0ZScsDQogICAgcGFwZXJfYmdjb2xvciA9ICd3aGl0ZScsDQogICAgc2hvd2xlZ2VuZCA9IFRSVUUsDQogICAgbGVnZW5kID0gbGlzdCgNCiAgICAgIG9yaWVudGF0aW9uID0gJ3YnLA0KICAgICAgeCA9IDAuOTgsDQogICAgICB4YW5jaG9yID0gJ3JpZ2h0JywNCiAgICAgIHkgPSAwLjk4LA0KICAgICAgeWFuY2hvciA9ICd0b3AnLA0KICAgICAgYmdjb2xvciA9ICdyZ2JhKDI1NSwyNTUsMjU1LDAuOCknLA0KICAgICAgYm9yZGVyY29sb3IgPSAnYmxhY2snLA0KICAgICAgYm9yZGVyd2lkdGggPSAwLjMNCiAgICApDQogICkNCg0KIyBUYW1waWxrYW4gcGxvdA0KaGlzdG9ncmFtX3Bsb3QNCmBgYA0KDQojIFBhcmV0byBDaGFydA0KYGBge3IgZWNobz1UUlVFfQ0KIyBMb2FkIGxpYnJhcmllcw0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQoNCiMgRmlsdGVyIGRhdGEgaGFueWEgdW50dWsgcHJvZHVrIGNhY2F0DQpkZWZlY3RpdmVfZGF0YSA8LSBicmVhZF9kYXRhICU+JQ0KICBmaWx0ZXIoSnVtbGFoX0NhY2F0ID4gMCkNCg0KIyBTdW1tYXJpemUgZnJla3VlbnNpIGplbmlzIGNhY2F0DQpwYXJldG9fZGF0YSA8LSBkZWZlY3RpdmVfZGF0YSAlPiUNCiAgY291bnQoSmVuaXNfQ2FjYXQsIHNvcnQgPSBUUlVFKSAlPiUNCiAgbXV0YXRlKA0KICAgIGN1bV9mcmVxID0gY3Vtc3VtKG4pIC8gc3VtKG4pICogMTAwICAjIHBlcnNlbnRhc2Uga3VtdWxhdGlmDQogICkNCg0KIyBHZW5lcmF0ZSB3YXJuYSBiZXJiZWRhIHVudHVrIHNldGlhcCBqZW5pcyBjYWNhdA0KY29sb3JzIDwtIFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbChuID0gbWF4KDMsIG1pbigxMiwgbnJvdyhwYXJldG9fZGF0YSkpKSwgbmFtZSA9ICJTZXQzIikNCg0KIyBCdWF0IG9iamVrIHBsb3RseQ0KZmlnIDwtIHBsb3RfbHkoKQ0KDQojIFRhbWJhaGthbiBCYXIgQ2hhcnQgKGp1bWxhaCBjYWNhdCkNCmZpZyA8LSBmaWcgJT4lIGFkZF9iYXJzKA0KICB4ID0gfnJlb3JkZXIocGFyZXRvX2RhdGEkSmVuaXNfQ2FjYXQsIC1wYXJldG9fZGF0YSRuKSwNCiAgeSA9IH5wYXJldG9fZGF0YSRuLA0KICBuYW1lID0gJ0p1bWxhaCBDYWNhdCcsDQogIG1hcmtlciA9IGxpc3QoY29sb3IgPSBjb2xvcnMpLA0KICB5YXhpcyA9ICJ5MSINCikNCg0KIyBUYW1iYWhrYW4gZ2FyaXMga3VtdWxhdGlmDQpmaWcgPC0gZmlnICU+JSBhZGRfbGluZXMoDQogIHggPSB+cmVvcmRlcihwYXJldG9fZGF0YSRKZW5pc19DYWNhdCwgLXBhcmV0b19kYXRhJG4pLA0KICB5ID0gfnBhcmV0b19kYXRhJGN1bV9mcmVxLA0KICBuYW1lID0gJ0t1bXVsYXRpZiAoJSknLA0KICB5YXhpcyA9ICJ5MiIsDQogIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JlZCcsIGRhc2ggPSAnZGFzaCcpDQopDQoNCiMgVGFtYmFoa2FuIGdhcmlzIGN1dG9mZiA4MCUNCmZpZyA8LSBmaWcgJT4lIGFkZF9saW5lcygNCiAgeCA9IH5yZW9yZGVyKHBhcmV0b19kYXRhJEplbmlzX0NhY2F0LCAtcGFyZXRvX2RhdGEkbiksDQogIHkgPSByZXAoODAsIG5yb3cocGFyZXRvX2RhdGEpKSwNCiAgbmFtZSA9ICdDdXQtb2ZmIDgwJScsDQogIHlheGlzID0gInkyIiwNCiAgbGluZSA9IGxpc3QoY29sb3IgPSAnZ3JlZW4nLCBkYXNoID0gJ2RvdCcpDQopDQoNCiMgTGF5b3V0IGFraGlyDQpmaWcgPC0gZmlnICU+JSBsYXlvdXQoDQogIHRpdGxlID0gIlBhcmV0byBDaGFydCAtIEplbmlzIENhY2F0IFByb2R1ayIsDQogIHhheGlzID0gbGlzdCgNCiAgICB0aXRsZSA9ICJKZW5pcyBDYWNhdCIsDQogICAgdGlja2FuZ2xlID0gLTQ1DQogICksDQogIHlheGlzID0gbGlzdCh0aXRsZSA9ICJKdW1sYWggQ2FjYXQiKSwNCiAgeWF4aXMyID0gbGlzdCgNCiAgICB0aXRsZSA9ICJLdW11bGF0aWYgKCUpIiwNCiAgICBvdmVybGF5aW5nID0gInkiLA0KICAgIHNpZGUgPSAicmlnaHQiLA0KICAgIHJhbmdlID0gYygwLCAxMDApDQogICksDQogIGxlZ2VuZCA9IGxpc3QoeCA9IDAuOCwgeSA9IDAuNzUpLA0KICBzaGFwZXMgPSBsaXN0KA0KICAgIGxpc3QoDQogICAgICB0eXBlID0gImxpbmUiLA0KICAgICAgeDAgPSAtMC41LA0KICAgICAgeDEgPSBucm93KHBhcmV0b19kYXRhKSAtIDAuNSwNCiAgICAgIHkwID0gODAsDQogICAgICB5MSA9IDgwLA0KICAgICAgeXJlZiA9ICJ5MiIsDQogICAgICBsaW5lID0gbGlzdChjb2xvciA9ICJncmVlbiIsIHdpZHRoID0gMiwgZGFzaCA9ICJkb3QiKQ0KICAgICkNCiAgKQ0KKQ0KDQojIFRhbXBpbGthbiBjaGFydA0KZmlnDQoNCmBgYA0KDQoNCiMgRmlzaGJvbmUNCmBgYHtyIGVjaG89VFJVRX0NCmxpYnJhcnkoRGlhZ3JhbW1lUikNCmxpYnJhcnkoRGlhZ3JhbW1lUnN2ZykNCmxpYnJhcnkocnN2ZykNCmxpYnJhcnkoa25pdHIpDQoNCmdyYXBoIDwtIGdyVml6KCINCmRpZ3JhcGggZmlzaGJvbmUgew0KICBncmFwaCBbbGF5b3V0ID0gZG90LCByYW5rZGlyID0gTFJdDQogIG5vZGUgW2ZvbnRuYW1lPUhlbHZldGljYSwgZm9udHNpemU9MjUsIHN0eWxlPWZpbGxlZF0NCg0KICBQcm9ibGVtIFtsYWJlbD0nQ2FjYXQgUHJvZHVrIFJvdGknLCBzaGFwZT1lbGxpcHNlLCBmaWxsY29sb3I9bGlnaHRjb3JhbCwgd2lkdGg9NS4wLCBoZWlnaHQ9MS4yXQ0KDQogICMgS2F0ZWdvcmkgdXRhbWENCiAgbm9kZSBbc2hhcGU9ZGlhbW9uZCwgd2lkdGg9Mi41LCBoZWlnaHQ9MS4wLCBmaWxsY29sb3I9JyNGRkQ3MDAnXQ0KICBNYW4gW2xhYmVsPSdNYW4nXQ0KICBNYWNoaW5lIFtsYWJlbD0nTWFjaGluZSddDQogIE1ldGhvZCBbbGFiZWw9J01ldGhvZCddDQogIE1hdGVyaWFsIFtsYWJlbD0nTWF0ZXJpYWwnXQ0KICBFbnZpcm9ubWVudCBbbGFiZWw9J0Vudmlyb25tZW50J10NCiAgTWVhc3VyZW1lbnQgW2xhYmVsPSdNZWFzdXJlbWVudCddDQoNCiAgIyBTdWJrYXRlZ29yaQ0KICBub2RlIFtzaGFwZT1lbGxpcHNlLCB3aWR0aD0yLjUsIGhlaWdodD0wLjYsIGZpbGxjb2xvcj0nIzkwRUU5MCddDQogIA0KICAjIE1hbg0KICBNYW4xIFtsYWJlbD0nS3VyYW5nbnlhIHBlbGF0aWhhbiBvcGVyYXRvciddDQogIE1hbjIgW2xhYmVsPSdLZWxlbGFoYW4gc2FhdCBzaGlmdCBtYWxhbSddDQoNCiAgIyBNYWNoaW5lDQogIE1hY2hpbmUxIFtsYWJlbD0nU3VodSBtZXNpbiB0aWRhayBzdGFiaWwnXQ0KICBNYWNoaW5lMiBbbGFiZWw9J01lc2luIHNlcmluZyBydXNhayddDQoNCiAgIyBNZXRob2QNCiAgTWV0aG9kMSBbbGFiZWw9J1Byb3NlZHVyIHN0YW5kYXIgdGlkYWsgZGlpa3V0aSddDQogIE1ldGhvZDIgW2xhYmVsPSdLb250cm9sIGt1YWxpdGFzIHRpZGFrIGtvbnNpc3RlbiddDQoNCiAgIyBNYXRlcmlhbA0KICBNYXRlcmlhbDEgW2xhYmVsPSdCYWhhbiBiYWt1IHRpZGFrIHNlZ2FyJ10NCiAgTWF0ZXJpYWwyIFtsYWJlbD0nS29tcG9zaXNpIGFkb25hbiB0aWRhayB0ZXBhdCddDQoNCiAgIyBFbnZpcm9ubWVudA0KICBFbnZpcm9ubWVudDEgW2xhYmVsPSdLZWxlbWJhYmFuIHRpbmdnaSBkaSBtdXNpbSBodWphbiddDQogIEVudmlyb25tZW50MiBbbGFiZWw9J1ZlbnRpbGFzaSBwYWJyaWsgYnVydWsnXQ0KDQogICMgTWVhc3VyZW1lbnQNCiAgTWVhc3VyZW1lbnQxIFtsYWJlbD0nQWxhdCB1a3VyIGthbGlicmFzaSBidXJ1ayddDQogIE1lYXN1cmVtZW50MiBbbGFiZWw9J0RhdGEgcHJvZHVrc2kgdGlkYWsgYWt1cmF0J10NCg0KICAjIEh1YnVuZ2thbiBrYXRlZ29yaSBrZSBtYXNhbGFoDQogIE1hbiAtPiBQcm9ibGVtDQogIE1hY2hpbmUgLT4gUHJvYmxlbQ0KICBNZXRob2QgLT4gUHJvYmxlbQ0KICBNYXRlcmlhbCAtPiBQcm9ibGVtDQogIEVudmlyb25tZW50IC0+IFByb2JsZW0NCiAgTWVhc3VyZW1lbnQgLT4gUHJvYmxlbQ0KDQogICMgSHVidW5na2FuIHN1YmthdGVnb3JpIGtlIGthdGVnb3JpDQogIE1hbjEgLT4gTWFuDQogIE1hbjIgLT4gTWFuDQoNCiAgTWFjaGluZTEgLT4gTWFjaGluZQ0KICBNYWNoaW5lMiAtPiBNYWNoaW5lDQoNCiAgTWV0aG9kMSAtPiBNZXRob2QNCiAgTWV0aG9kMiAtPiBNZXRob2QNCg0KICBNYXRlcmlhbDEgLT4gTWF0ZXJpYWwNCiAgTWF0ZXJpYWwyIC0+IE1hdGVyaWFsDQoNCiAgRW52aXJvbm1lbnQxIC0+IEVudmlyb25tZW50DQogIEVudmlyb25tZW50MiAtPiBFbnZpcm9ubWVudA0KDQogIE1lYXN1cmVtZW50MSAtPiBNZWFzdXJlbWVudA0KICBNZWFzdXJlbWVudDIgLT4gTWVhc3VyZW1lbnQNCn0NCiIpDQoNCiMgU2ltcGFuIHNlYmFnYWkgZ2FtYmFyDQpkaXIuY3JlYXRlKCJpbWFnZXMvYmFiOCIsIHJlY3Vyc2l2ZSA9IFRSVUUsIHNob3dXYXJuaW5ncyA9IEZBTFNFKQ0Kc3ZnX2NvZGUgPC0gZXhwb3J0X3N2ZyhncmFwaCkNCnJzdmdfcG5nKGNoYXJUb1JhdyhzdmdfY29kZSksIGZpbGUgPSAiaW1hZ2VzL2JhYjgvZmlzaGJvbmVfcm90aV9xYy5wbmciLCB3aWR0aCA9IDMwMDAsIGhlaWdodCA9IDMwMDApDQpyc3ZnX3BkZihjaGFyVG9SYXcoc3ZnX2NvZGUpLCBmaWxlID0gImltYWdlcy9iYWI4L2Zpc2hib25lX3JvdGlfcWMucGRmIikNCg0KIyBUYW1waWxrYW4gZGFsYW0gbGFwb3Jhbg0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy9iYWI4L2Zpc2hib25lX3JvdGlfcWMucG5nIikNCg0KYGBgDQoNCiMgU2NhdHRlciBEaWFncmFtDQoNCmBgYHtyIGVjaG89VFJVRX0NCiMgUGFzdGlrYW4gcGFja2FnZSBzdWRhaCB0ZXJpbnN0YWwNCiMgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikgIyBKaWthIGJlbHVtIHRlcmluc3RhbA0KDQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBTY2F0dGVyIHBsb3Qgc3VodSBtZXNpbiB2cyBqdW1sYWggY2FjYXQNCmNvcnJlbGF0aW9uX3ZhbHVlIDwtIGNvcihicmVhZF9kYXRhJFN1aHVfTWVzaW5fQywgYnJlYWRfZGF0YSRKdW1sYWhfQ2FjYXQpDQoNCmZpZyA8LSBwbG90X2x5KA0KICBkYXRhID0gYnJlYWRfZGF0YSwNCiAgeCA9IH5TdWh1X01lc2luX0MsDQogIHkgPSB+SnVtbGFoX0NhY2F0LA0KICB0eXBlID0gJ3NjYXR0ZXInLA0KICBtb2RlID0gJ21hcmtlcnMnLA0KICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ2JsYWNrJywgc2l6ZSA9IDcpDQopICU+JQ0KICBhZGRfbGluZXMoDQogICAgeCA9IGJyZWFkX2RhdGEkU3VodV9NZXNpbl9DLA0KICAgIHkgPSBwcmVkaWN0KGxtKEp1bWxhaF9DYWNhdCB+IFN1aHVfTWVzaW5fQywgZGF0YSA9IGJyZWFkX2RhdGEpKSwNCiAgICBsaW5lID0gbGlzdChjb2xvciA9ICdyZWQnLCBkYXNoID0gJ3NvbGlkJykNCiAgKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gcGFzdGUoIlNjYXR0ZXIgUGxvdDogU3VodSBNZXNpbiB2cyBKdW1sYWggQ2FjYXRcbktvcmVsYXNpOiIsIHJvdW5kKGNvcnJlbGF0aW9uX3ZhbHVlLCAyKSksDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlN1aHUgTWVzaW4gKMKwQykiKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSnVtbGFoIENhY2F0IikNCiAgKQ0KDQojIFRhbXBpbGthbsKgcGxvdA0KZmlnDQpgYGANCg0KIyBDb250cm9sIENoYXJ0DQpgYGB7ciBlY2hvPVRSVUV9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZHBseXIpDQoNCiMgQW1iaWwgZGF0YSBiZXJhdCBiYXRjaCBkYW4gdXJ1dGthbiBiZXJkYXNhcmthbiB0YW5nZ2FsDQpiZXJhdF9kYXRhIDwtIGJyZWFkX2RhdGEgJT4lDQogIGFycmFuZ2UoVGFuZ2dhbCkgJT4lDQogIG11dGF0ZShIYXJpID0gcm93X251bWJlcigpKSAlPiUNCiAgc2VsZWN0KEhhcmksIFRhbmdnYWwsIEJlcmF0ID0gQmVyYXRfQmF0Y2hfa2cpDQoNCiMgVGVudHVrYW4gYmF0YXMga2VuZGFsaSBiZXJkYXNhcmthbiByYXRhLXJhdGEgZGFuIHN0YW5kYXIgZGV2aWFzaQ0KQ0wgPC0gbWVhbihiZXJhdF9kYXRhJEJlcmF0KQ0KU0QgPC0gc2QoYmVyYXRfZGF0YSRCZXJhdCkNClVDTCA8LSBDTCArIDMgKiBTRA0KTENMIDwtIENMIC0gMyAqIFNEDQoNCiMgVGFuZGFpIG91dGxpZXINCmJlcmF0X2RhdGEgPC0gYmVyYXRfZGF0YSAlPiUNCiAgbXV0YXRlKE91dGxpZXIgPSBpZmVsc2UoQmVyYXQgPiBVQ0wgfCBCZXJhdCA8IExDTCwgIllhIiwgIlRpZGFrIikpDQoNCiMgQnVhdCBwbG90IGtvbnRyb2wgY2hhcnQNCnBsb3RfbHkoYmVyYXRfZGF0YSwgeCA9IH5IYXJpLCB5ID0gfkJlcmF0LCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzK21hcmtlcnMnLA0KICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICdyZWQnKSwgDQogICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDgsIGNvbG9yID0gaWZlbHNlKGJlcmF0X2RhdGEkT3V0bGllciA9PSAiWWEiLCAicmVkIiwgImJsdWUiKSksDQogICAgICAgIGhvdmVyaW5mbyA9ICd0ZXh0JywNCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgiVGFuZ2dhbDoiLCBUYW5nZ2FsLCAiPGJyPkJlcmF0OiIsIEJlcmF0LCAia2ciKSkgJT4lDQogIGFkZF9saW5lcyh5ID0gcmVwKENMLCBucm93KGJlcmF0X2RhdGEpKSwgbmFtZSA9ICJDTCIsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2dyZWVuJywgZGFzaCA9ICdkb3QnKSkgJT4lDQogIGFkZF9saW5lcyh5ID0gcmVwKFVDTCwgbnJvdyhiZXJhdF9kYXRhKSksIG5hbWUgPSAiVUNMIiwgbGluZSA9IGxpc3QoY29sb3IgPSAncmVkJywgZGFzaCA9ICdkb3QnKSkgJT4lDQogIGFkZF9saW5lcyh5ID0gcmVwKExDTCwgbnJvdyhiZXJhdF9kYXRhKSksIG5hbWUgPSAiTENMIiwgbGluZSA9IGxpc3QoY29sb3IgPSAncmVkJywgZGFzaCA9ICdkb3QnKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICJDb250cm9sIENoYXJ0IOKAkyBLb25zaXN0ZW5zaSBCZXJhdCBCYXRjaCBQcm9kdWsgUm90aSIsDQogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiVXJ1dGFuIEJhdGNoIChIYXJpIFByb2R1a3NpKSIpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkJlcmF0IEJhdGNoIChrZykiKSwNCiAgICAgICAgIGxlZ2VuZCA9IGxpc3Qob3JpZW50YXRpb24gPSAnaCcsIHggPSAwLjMsIHkgPSAtMC4yKSkNCg0KYGBgDQoNCg0KIyBGbG93Y2hhcnQNCjxpbWcgc3JjPSJmbG93Y2hhcnQuanBnIiBhbHQ9IkxvZ28iIHN0eWxlPSJ3aWR0aDo1MDBweDsgZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiLz4NCg==