Pratikum PEMOGRAMAN SAINS DATA

Pratikum PEMOGRAMAN SAINS DATA

awokwowk


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_plot

3. 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
fig

4. 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
fig

6. 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