Event Organizer (Kelompok 2)

7 QC Tools

1 Dataset Event Organizer

library(dplyr)
library(DT)

# Set seed untuk hasil acak yang konsisten
set.seed(42)

# Vektor pilihan
request_types <- c("Vegetarian Meals", "Special Lighting", "Extra Security", "Custom Decorations", "VIP Seating")
request_statuses <- c("Fulfilled", "Not Fulfilled")

# Buat dataset
check_sheet <- data.frame(
  Event_ID = paste0("EVT", sprintf("%03d", 1:100)),
  Client_Name = paste0("Client_", 1:100),
  Request_Type = sample(request_types, 100, replace = TRUE),
  Request_Status = sample(request_statuses, 100, replace = TRUE),
  stringsAsFactors = FALSE
)

# Menambahkan kolom Problem dengan variasi berdasarkan jenis permintaan
check_sheet$Problem <- case_when(
  check_sheet$Request_Status == "Not Fulfilled" & check_sheet$Request_Type == "Vegetarian Meals" ~ "Vegetarian Meals not provided on time",
  check_sheet$Request_Status == "Not Fulfilled" & check_sheet$Request_Type == "Special Lighting" ~ "Special Lighting not set up",
  check_sheet$Request_Status == "Not Fulfilled" & check_sheet$Request_Type == "Extra Security" ~ "Lack of Extra Security",
  check_sheet$Request_Status == "Not Fulfilled" & check_sheet$Request_Type == "Custom Decorations" ~ "Decorations not delivered",
  check_sheet$Request_Status == "Not Fulfilled" & check_sheet$Request_Type == "VIP Seating" ~ "VIP seating arrangement missed",
  
  check_sheet$Request_Status == "Fulfilled" & check_sheet$Request_Type == "Vegetarian Meals" ~ "Vegetarian Meals delivered",
  check_sheet$Request_Status == "Fulfilled" & check_sheet$Request_Type == "Special Lighting" ~ "Special Lighting set up",
  check_sheet$Request_Status == "Fulfilled" & check_sheet$Request_Type == "Extra Security" ~ "Extra Security in place",
  check_sheet$Request_Status == "Fulfilled" & check_sheet$Request_Type == "Custom Decorations" ~ "Decorations in place",
  check_sheet$Request_Status == "Fulfilled" & check_sheet$Request_Type == "VIP Seating" ~ "VIP seating arranged",
  
  TRUE ~ "Other Issue"
)

# Tampilkan tabel interaktif dengan kolom Problem yang bervariasi
datatable(
  check_sheet,
  options = list(
    pageLength = 10,
    scrollCollapse = TRUE,
    autoWidth = TRUE
  ),
  rownames = FALSE,
  caption = htmltools::tags$caption(
    style = 'caption-side: top; text-align: left; 
             font-size: 18px; font-weight: bold;',
    'Check Sheet: Client Special Requests at Events with Detailed Problem Status'
  ),
  class = 'stripe hover compact'
)

2 Check Sheet

library(dplyr)
library(DT)

# Hitung frekuensi masing-masing jenis permintaan khusus klien
request_summary <- check_sheet %>%
  count(Request_Type, sort = TRUE) %>%
  rename(Frequency = n)

# Tampilkan dalam tabel interaktif
datatable(
  request_summary,
  options = list(
    scrollCollapse = TRUE,
    searching = FALSE,   # Hilangkan kotak pencarian
    paging = FALSE       # Hilangkan pagination
  ),
  rownames = FALSE,
  caption = htmltools::tags$caption(
    style = 'caption-side: top; text-align: left; 
             font-size: 18px; font-weight: bold;',
    'Check Sheet: Summary of Client Special Requests'
  ),
  class = 'stripe hover compact'
)

Visualization

library(dplyr)
library(plotly)

# Hitung frekuensi tiap jenis permintaan
request_summary <- check_sheet %>%
  count(Request_Type, sort = TRUE) %>%
  rename(Frequency = n)

# Buat bar chart interaktif horizontal
plot_ly(request_summary,
        x = ~Frequency,
        y = ~reorder(Request_Type, Frequency),
        type = 'bar',
        orientation = 'h',
        marker = list(
          color = ~Frequency,
          colorscale = 'Viridis',
          showscale = TRUE
        )
) %>%
  layout(
    title = list(text = "Check Sheet: Frequency of Client Special Requests", font = list(size = 18)),
    xaxis = list(title = "Frequency"),
    yaxis = list(title = "Request Type"),
    margin = list(l = 120)
  )

3 Control Chart

library(plotly)
library(dplyr)

# Buat data kehadiran
set.seed(42)
attendance_data <- data.frame(
  Event = 1:30,
  Invitations = sample(90:110, 30, replace = TRUE),
  Attendees = sample(85:115, 30, replace = TRUE)
)

# Hitung rasio kehadiran (%)
attendance_data <- attendance_data %>%
  mutate(AttendanceRate = round(Attendees / Invitations * 100, 1))

# Tentukan batas kendali
CL <- 100
UCL <- 110
LCL <- 90

# Tandai outliers
attendance_data <- attendance_data %>%
  mutate(Outlier = ifelse(AttendanceRate > UCL | AttendanceRate < LCL, "Ya", "Tidak"))

# Buat control chart
plot_ly(attendance_data, x = ~Event, y = ~AttendanceRate, type = 'scatter', mode = 'lines+markers',
        line = list(color = 'blue'),
        marker = list(size = 8, color = ifelse(attendance_data$Outlier == "Ya", "red", "blue")),
        hoverinfo = 'text',
        text = ~paste("Event:", Event,
                      "<br>Undangan:", Invitations,
                      "<br>Hadir:", Attendees,
                      "<br>Rasio Kehadiran:", AttendanceRate, "%")) %>%
  add_lines(y = rep(CL, 30), name = "CL (100%)", line = list(color = 'green', dash = 'dot')) %>%
  add_lines(y = rep(UCL, 30), name = "UCL (110%)", line = list(color = 'red', dash = 'dot')) %>%
  add_lines(y = rep(LCL, 30), name = "LCL (90%)", line = list(color = 'red', dash = 'dot')) %>%
  layout(title = "Control Chart – Attendance Rate vs Invitations",
         xaxis = list(title = "Event Ke-"),
         yaxis = list(title = "Rasio Kehadiran (%)"),
         legend = list(orientation = 'h', x = 0.3, y = -0.2))

4 Fishbone Diagram

if (!requireNamespace("DiagrammeRsvg", quietly = TRUE)) {
  install.packages("DiagrammeRsvg")
}

library(DiagrammeR)
library(DiagrammeRsvg)
library(rsvg)

graph <- grViz("
digraph fishbone {
  graph [layout = dot, rankdir = LR]

  # Default node styles
  node [fontname=Helvetica, fontsize=25, style=filled]

  # Central problem
  Problem [label='Delayed Event Start', 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='People']
  A2 [label='Process']
  A3 [label='Equipment']
  A4 [label='Venue']
  A5 [label='External Factors']
  A6 [label='Communication']

  # Reset node style for sub-categories
  node [shape=ellipse, width=2.5, height=0.6, fillcolor='#90EE90']
  A1a [label='Late arrival of key personnel']
  A1b [label='Lack of trained staff']
  A1c [label='Unprepared staff']

  A2a [label='Unclear event timeline']
  A2b [label='Inadequate event planning']
  A2c [label='Last minute changes in schedule']

  A3a [label='Equipment malfunction']
  A3b [label='Late delivery of equipment']

  A4a [label='Venue unavailability']
  A4b [label='Venue setup issues']

  A5a [label='Traffic congestion']
  A5b [label='Bad weather']

  A6a [label='Miscommunication between event planners']
  A6b [label='Inaccurate communication of event details']

  # Relationships
  A1 -> Problem
  A2 -> Problem
  A3 -> Problem
  A4 -> Problem
  A5 -> Problem
  A6 -> Problem

  A1a -> A1
  A1b -> A1
  A1c -> A1

  A2a -> A2
  A2b -> A2
  A2c -> A2

  A3a -> A3
  A3b -> A3

  A4a -> A4
  A4b -> A4

  A5a -> A5
  A5b -> A5

  A6a -> A6
  A6b -> A6
}
")

# Output directory and saving
dir.create("images/event_delays", recursive = TRUE, showWarnings = FALSE)

# Menggunakan export_svg dari DiagrammeRsvg
svg_code <- DiagrammeRsvg::export_svg(graph)
rsvg_png(charToRaw(svg_code), file = "images/event_delays/fishbone_event_start_delay.png", width = 3000, height = 3000)
rsvg_pdf(charToRaw(svg_code), file = "images/event_delays/fishbone_event_start_delay.pdf")

knitr::include_graphics("images/event_delays/fishbone_event_start_delay.png")

5 Flowchart

library(DiagrammeR)

# Create the flowchart diagram using DiagrammeR's grViz function
flowchart <- grViz("digraph event_process {
  graph [layout = dot, rankdir = TB]

  # Default node style for steps
  node [fontname = Helvetica, fontsize = 16, shape = rectangle, style = filled, fillcolor = lightblue]
  
  # Define the flowchart stages with appropriate symbols
  Start [label = 'Start', shape = ellipse, fillcolor = lightcoral]
  Plan [label = 'Plan: Identify objectives, create budget, set date', shape = rectangle]
  Decision1 [label = 'Budget approved?', shape = diamond, width = 2.5]
  Prepare [label = 'Prepare: Finalize details, book vendors, send invites', shape = rectangle]
  Decision2 [label = 'Vendors booked?', shape = diamond, width = 2.5]
  Execute [label = 'Execute: Manage the event, coordinate staff', shape = rectangle]
  Decision3 [label = 'Event successful?', shape = diamond, width = 2.5]
  Evaluate [label = 'Evaluate: Collect feedback, assess outcomes, review budget', shape = rectangle]
  End [label = 'End', shape = ellipse, fillcolor = lightcoral]
  
  # Define the flow connections between the steps
  Start -> Plan
  Plan -> Decision1
  Decision1 -> Prepare [label = 'Yes']
  Decision1 -> End [label = 'No']
  Prepare -> Decision2
  Decision2 -> Execute [label = 'Yes']
  Decision2 -> End [label = 'No']
  Execute -> Decision3
  Decision3 -> Evaluate [label = 'Yes']
  Decision3 -> End [label = 'No']
  Evaluate -> End
  
  # Add arrows for flow
  edge [arrowhead = vee]
}
")

# Display the flowchart
flowchart

6 Histogram

library(plotly)

# Generate synthetic guest arrival times data
set.seed(123)
arrival_times <- rnorm(1000, mean = 60, sd = 15)  # 1000 random arrival times (mean = 60 minutes, SD = 15 minutes)

# Calculate the density of the arrival time data
density_data <- density(arrival_times)

# Create a histogram of guest arrival times using plotly
arrival_times_plot <- plot_ly(
  x = arrival_times,
  type = 'histogram',
  marker = list(color = 'lightgreen', line = list(color = 'black', width = 1)),
  name = 'Histogram of Guest Arrival Times',
  nbinsx = 30,  # Number of bins
  opacity = 0.6,
  showlegend = TRUE
) %>%
  # Add the density curve
  add_trace(
    x = density_data$x, 
    y = density_data$y * length(arrival_times) * diff(range(arrival_times)) / 30,
    type = 'scatter',
    mode = 'lines',
    name = 'Density Curve',
    line = list(color = 'black', width = 3),
    showlegend = TRUE
  ) %>%
  layout(
    title = 'Histogram of Guest Arrival Times at Several Events',
    xaxis = list(title = 'Arrival Time (minutes)', 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
arrival_times_plot

7 Pareto Chart

library(dplyr)
library(plotly)
library(RColorBrewer)

# Summarize the number of problems by type
pareto_data <- check_sheet %>%
  count(Problem, sort = TRUE) %>%
  mutate(
    cum_freq = cumsum(n) / sum(n) * 100  # cumulative percentage
  )

# Create different colors for each Problem
colors <- brewer.pal(n = length(pareto_data$Problem), name = "Set3")

# Create Plotly Pareto Chart
fig <- plot_ly()

# Add Bar Chart (Count) - with different colors
fig <- fig %>% add_bars(
  x = ~reorder(pareto_data$Problem, -pareto_data$n),
  y = ~pareto_data$n,
  name = 'Number of Problems',
  marker = list(color = colors),
  yaxis = "y1"
)

# Add Cumulative Line
fig <- fig %>% add_lines(
  x = ~reorder(pareto_data$Problem, -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$Problem, -pareto_data$n),
  y = rep(80, length(pareto_data$Problem)),
  name = 'Cut-off 80%',
  yaxis = "y2",
  line = list(color = 'green', dash = 'dot')
)

# Adjust layout
fig <- fig %>% layout(
  title = "Pareto Chart - Most Common Problems During Event Execution",
  xaxis = list(
    title = "Event Problems",
    tickangle = -45   # tilt 45 degrees
  ),
  yaxis = list(title = "Number of Problems"),
  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$Problem) - 0.5,
      y0 = 80,
      y1 = 80,
      yref = "y2",
      line = list(color = "green", width = 2, dash = "dot")
    )
  )
)

# Show chart
fig

8 Scatter Diagram

library(plotly)

# Create a dataset with event size (number of guests) and staff number
set.seed(42)
event_data <- data.frame(
  Event_Size = c(50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 
                 300, 325, 350, 375, 400, 425, 450, 475, 500, 525),
  Staff_Number = c(10, 14, 18, 21, 25, 28, 32, 35, 38, 41, 
                   44, 48, 51, 55, 58, 62, 65, 69, 72, 75)
)

# Introduce some noise to get a correlation of around 0.9
event_data$Staff_Number <- event_data$Staff_Number + rnorm(n = 20, mean = 0, sd = 2)

# Calculate the correlation coefficient between the event size and staff number
correlation_value <- cor(event_data$Event_Size, event_data$Staff_Number)

# Create a scatter plot using Plotly with a linear regression line
fig <- plot_ly(event_data, 
               x = ~Event_Size, 
               y = ~Staff_Number, 
               type = 'scatter', 
               mode = 'markers',
               marker = list(color = 'blue', size = 10)) %>%
  add_lines(x = event_data$Event_Size, 
            y = predict(lm(Staff_Number ~ Event_Size, data = event_data)), 
            line = list(color = 'red', dash = 'solid', width = 2)) %>%
  layout(title = paste("Scatter Plot: Relationship Between Event Size and Staff Number\nCorrelation: ", round(correlation_value, 2)),
         xaxis = list(title = "Event Size (Number of Guests)"),
         yaxis = list(title = "Staff Number"))

# Show the plot
fig
LS0tDQp0aXRsZTogIkV2ZW50IE9yZ2FuaXplciAoS2Vsb21wb2sgMikiDQpzdWJ0aXRsZTogIjcgUUMgVG9vbHMiDQphdXRob3I6IA0KICAtICJJc25haW5pIE51ciBIYXNhbmFoICg1MjI0MDAwNSkiDQogIC0gIk5hYmlsYSBBc3dhICg1MjI0MDAxMikiDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KLS0tDQo8cCBhbGlnbj0iY2VudGVyIj4NCiAgPGltZyBzcmM9IkM6L1VzZXJzL05BQklMQSBBU1dBIEhJREFZQVRJL0Rvd25sb2Fkcy9LRUwuMi5qcGciIC8+DQo8L3A+DQoNCiMgRGF0YXNldCBFdmVudCBPcmdhbml6ZXINCg0KYGBge3IsIGVjaG89IFRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShEVCkNCg0KIyBTZXQgc2VlZCB1bnR1ayBoYXNpbCBhY2FrIHlhbmcga29uc2lzdGVuDQpzZXQuc2VlZCg0MikNCg0KIyBWZWt0b3IgcGlsaWhhbg0KcmVxdWVzdF90eXBlcyA8LSBjKCJWZWdldGFyaWFuIE1lYWxzIiwgIlNwZWNpYWwgTGlnaHRpbmciLCAiRXh0cmEgU2VjdXJpdHkiLCAiQ3VzdG9tIERlY29yYXRpb25zIiwgIlZJUCBTZWF0aW5nIikNCnJlcXVlc3Rfc3RhdHVzZXMgPC0gYygiRnVsZmlsbGVkIiwgIk5vdCBGdWxmaWxsZWQiKQ0KDQojIEJ1YXQgZGF0YXNldA0KY2hlY2tfc2hlZXQgPC0gZGF0YS5mcmFtZSgNCiAgRXZlbnRfSUQgPSBwYXN0ZTAoIkVWVCIsIHNwcmludGYoIiUwM2QiLCAxOjEwMCkpLA0KICBDbGllbnRfTmFtZSA9IHBhc3RlMCgiQ2xpZW50XyIsIDE6MTAwKSwNCiAgUmVxdWVzdF9UeXBlID0gc2FtcGxlKHJlcXVlc3RfdHlwZXMsIDEwMCwgcmVwbGFjZSA9IFRSVUUpLA0KICBSZXF1ZXN0X1N0YXR1cyA9IHNhbXBsZShyZXF1ZXN0X3N0YXR1c2VzLCAxMDAsIHJlcGxhY2UgPSBUUlVFKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgTWVuYW1iYWhrYW4ga29sb20gUHJvYmxlbSBkZW5nYW4gdmFyaWFzaSBiZXJkYXNhcmthbiBqZW5pcyBwZXJtaW50YWFuDQpjaGVja19zaGVldCRQcm9ibGVtIDwtIGNhc2Vfd2hlbigNCiAgY2hlY2tfc2hlZXQkUmVxdWVzdF9TdGF0dXMgPT0gIk5vdCBGdWxmaWxsZWQiICYgY2hlY2tfc2hlZXQkUmVxdWVzdF9UeXBlID09ICJWZWdldGFyaWFuIE1lYWxzIiB+ICJWZWdldGFyaWFuIE1lYWxzIG5vdCBwcm92aWRlZCBvbiB0aW1lIiwNCiAgY2hlY2tfc2hlZXQkUmVxdWVzdF9TdGF0dXMgPT0gIk5vdCBGdWxmaWxsZWQiICYgY2hlY2tfc2hlZXQkUmVxdWVzdF9UeXBlID09ICJTcGVjaWFsIExpZ2h0aW5nIiB+ICJTcGVjaWFsIExpZ2h0aW5nIG5vdCBzZXQgdXAiLA0KICBjaGVja19zaGVldCRSZXF1ZXN0X1N0YXR1cyA9PSAiTm90IEZ1bGZpbGxlZCIgJiBjaGVja19zaGVldCRSZXF1ZXN0X1R5cGUgPT0gIkV4dHJhIFNlY3VyaXR5IiB+ICJMYWNrIG9mIEV4dHJhIFNlY3VyaXR5IiwNCiAgY2hlY2tfc2hlZXQkUmVxdWVzdF9TdGF0dXMgPT0gIk5vdCBGdWxmaWxsZWQiICYgY2hlY2tfc2hlZXQkUmVxdWVzdF9UeXBlID09ICJDdXN0b20gRGVjb3JhdGlvbnMiIH4gIkRlY29yYXRpb25zIG5vdCBkZWxpdmVyZWQiLA0KICBjaGVja19zaGVldCRSZXF1ZXN0X1N0YXR1cyA9PSAiTm90IEZ1bGZpbGxlZCIgJiBjaGVja19zaGVldCRSZXF1ZXN0X1R5cGUgPT0gIlZJUCBTZWF0aW5nIiB+ICJWSVAgc2VhdGluZyBhcnJhbmdlbWVudCBtaXNzZWQiLA0KICANCiAgY2hlY2tfc2hlZXQkUmVxdWVzdF9TdGF0dXMgPT0gIkZ1bGZpbGxlZCIgJiBjaGVja19zaGVldCRSZXF1ZXN0X1R5cGUgPT0gIlZlZ2V0YXJpYW4gTWVhbHMiIH4gIlZlZ2V0YXJpYW4gTWVhbHMgZGVsaXZlcmVkIiwNCiAgY2hlY2tfc2hlZXQkUmVxdWVzdF9TdGF0dXMgPT0gIkZ1bGZpbGxlZCIgJiBjaGVja19zaGVldCRSZXF1ZXN0X1R5cGUgPT0gIlNwZWNpYWwgTGlnaHRpbmciIH4gIlNwZWNpYWwgTGlnaHRpbmcgc2V0IHVwIiwNCiAgY2hlY2tfc2hlZXQkUmVxdWVzdF9TdGF0dXMgPT0gIkZ1bGZpbGxlZCIgJiBjaGVja19zaGVldCRSZXF1ZXN0X1R5cGUgPT0gIkV4dHJhIFNlY3VyaXR5IiB+ICJFeHRyYSBTZWN1cml0eSBpbiBwbGFjZSIsDQogIGNoZWNrX3NoZWV0JFJlcXVlc3RfU3RhdHVzID09ICJGdWxmaWxsZWQiICYgY2hlY2tfc2hlZXQkUmVxdWVzdF9UeXBlID09ICJDdXN0b20gRGVjb3JhdGlvbnMiIH4gIkRlY29yYXRpb25zIGluIHBsYWNlIiwNCiAgY2hlY2tfc2hlZXQkUmVxdWVzdF9TdGF0dXMgPT0gIkZ1bGZpbGxlZCIgJiBjaGVja19zaGVldCRSZXF1ZXN0X1R5cGUgPT0gIlZJUCBTZWF0aW5nIiB+ICJWSVAgc2VhdGluZyBhcnJhbmdlZCIsDQogIA0KICBUUlVFIH4gIk90aGVyIElzc3VlIg0KKQ0KDQojIFRhbXBpbGthbiB0YWJlbCBpbnRlcmFrdGlmIGRlbmdhbiBrb2xvbSBQcm9ibGVtIHlhbmcgYmVydmFyaWFzaQ0KZGF0YXRhYmxlKA0KICBjaGVja19zaGVldCwNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDEwLA0KICAgIHNjcm9sbENvbGxhcHNlID0gVFJVRSwNCiAgICBhdXRvV2lkdGggPSBUUlVFDQogICksDQogIHJvd25hbWVzID0gRkFMU0UsDQogIGNhcHRpb24gPSBodG1sdG9vbHM6OnRhZ3MkY2FwdGlvbigNCiAgICBzdHlsZSA9ICdjYXB0aW9uLXNpZGU6IHRvcDsgdGV4dC1hbGlnbjogbGVmdDsgDQogICAgICAgICAgICAgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsnLA0KICAgICdDaGVjayBTaGVldDogQ2xpZW50IFNwZWNpYWwgUmVxdWVzdHMgYXQgRXZlbnRzIHdpdGggRGV0YWlsZWQgUHJvYmxlbSBTdGF0dXMnDQogICksDQogIGNsYXNzID0gJ3N0cmlwZSBob3ZlciBjb21wYWN0Jw0KKQ0KYGBgDQoNCiMgQ2hlY2sgU2hlZXQNCg0KYGBge3IsZWNobz0gVFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KERUKQ0KDQojIEhpdHVuZyBmcmVrdWVuc2kgbWFzaW5nLW1hc2luZyBqZW5pcyBwZXJtaW50YWFuIGtodXN1cyBrbGllbg0KcmVxdWVzdF9zdW1tYXJ5IDwtIGNoZWNrX3NoZWV0ICU+JQ0KICBjb3VudChSZXF1ZXN0X1R5cGUsIHNvcnQgPSBUUlVFKSAlPiUNCiAgcmVuYW1lKEZyZXF1ZW5jeSA9IG4pDQoNCiMgVGFtcGlsa2FuIGRhbGFtIHRhYmVsIGludGVyYWt0aWYNCmRhdGF0YWJsZSgNCiAgcmVxdWVzdF9zdW1tYXJ5LA0KICBvcHRpb25zID0gbGlzdCgNCiAgICBzY3JvbGxDb2xsYXBzZSA9IFRSVUUsDQogICAgc2VhcmNoaW5nID0gRkFMU0UsICAgIyBIaWxhbmdrYW4ga290YWsgcGVuY2FyaWFuDQogICAgcGFnaW5nID0gRkFMU0UgICAgICAgIyBIaWxhbmdrYW4gcGFnaW5hdGlvbg0KICApLA0KICByb3duYW1lcyA9IEZBTFNFLA0KICBjYXB0aW9uID0gaHRtbHRvb2xzOjp0YWdzJGNhcHRpb24oDQogICAgc3R5bGUgPSAnY2FwdGlvbi1zaWRlOiB0b3A7IHRleHQtYWxpZ246IGxlZnQ7IA0KICAgICAgICAgICAgIGZvbnQtc2l6ZTogMThweDsgZm9udC13ZWlnaHQ6IGJvbGQ7JywNCiAgICAnQ2hlY2sgU2hlZXQ6IFN1bW1hcnkgb2YgQ2xpZW50IFNwZWNpYWwgUmVxdWVzdHMnDQogICksDQogIGNsYXNzID0gJ3N0cmlwZSBob3ZlciBjb21wYWN0Jw0KKQ0KYGBgDQoNCioqVmlzdWFsaXphdGlvbioqDQoNCmBgYHtyLCBlY2hvPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEhpdHVuZyBmcmVrdWVuc2kgdGlhcCBqZW5pcyBwZXJtaW50YWFuDQpyZXF1ZXN0X3N1bW1hcnkgPC0gY2hlY2tfc2hlZXQgJT4lDQogIGNvdW50KFJlcXVlc3RfVHlwZSwgc29ydCA9IFRSVUUpICU+JQ0KICByZW5hbWUoRnJlcXVlbmN5ID0gbikNCg0KIyBCdWF0IGJhciBjaGFydCBpbnRlcmFrdGlmIGhvcml6b250YWwNCnBsb3RfbHkocmVxdWVzdF9zdW1tYXJ5LA0KICAgICAgICB4ID0gfkZyZXF1ZW5jeSwNCiAgICAgICAgeSA9IH5yZW9yZGVyKFJlcXVlc3RfVHlwZSwgRnJlcXVlbmN5KSwNCiAgICAgICAgdHlwZSA9ICdiYXInLA0KICAgICAgICBvcmllbnRhdGlvbiA9ICdoJywNCiAgICAgICAgbWFya2VyID0gbGlzdCgNCiAgICAgICAgICBjb2xvciA9IH5GcmVxdWVuY3ksDQogICAgICAgICAgY29sb3JzY2FsZSA9ICdWaXJpZGlzJywNCiAgICAgICAgICBzaG93c2NhbGUgPSBUUlVFDQogICAgICAgICkNCikgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QodGV4dCA9ICJDaGVjayBTaGVldDogRnJlcXVlbmN5IG9mIENsaWVudCBTcGVjaWFsIFJlcXVlc3RzIiwgZm9udCA9IGxpc3Qoc2l6ZSA9IDE4KSksDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkZyZXF1ZW5jeSIpLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJSZXF1ZXN0IFR5cGUiKSwNCiAgICBtYXJnaW4gPSBsaXN0KGwgPSAxMjApDQogICkNCmBgYA0KDQojIENvbnRyb2wgQ2hhcnQNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGRwbHlyKQ0KDQojIEJ1YXQgZGF0YSBrZWhhZGlyYW4NCnNldC5zZWVkKDQyKQ0KYXR0ZW5kYW5jZV9kYXRhIDwtIGRhdGEuZnJhbWUoDQogIEV2ZW50ID0gMTozMCwNCiAgSW52aXRhdGlvbnMgPSBzYW1wbGUoOTA6MTEwLCAzMCwgcmVwbGFjZSA9IFRSVUUpLA0KICBBdHRlbmRlZXMgPSBzYW1wbGUoODU6MTE1LCAzMCwgcmVwbGFjZSA9IFRSVUUpDQopDQoNCiMgSGl0dW5nIHJhc2lvIGtlaGFkaXJhbiAoJSkNCmF0dGVuZGFuY2VfZGF0YSA8LSBhdHRlbmRhbmNlX2RhdGEgJT4lDQogIG11dGF0ZShBdHRlbmRhbmNlUmF0ZSA9IHJvdW5kKEF0dGVuZGVlcyAvIEludml0YXRpb25zICogMTAwLCAxKSkNCg0KIyBUZW50dWthbiBiYXRhcyBrZW5kYWxpDQpDTCA8LSAxMDANClVDTCA8LSAxMTANCkxDTCA8LSA5MA0KDQojIFRhbmRhaSBvdXRsaWVycw0KYXR0ZW5kYW5jZV9kYXRhIDwtIGF0dGVuZGFuY2VfZGF0YSAlPiUNCiAgbXV0YXRlKE91dGxpZXIgPSBpZmVsc2UoQXR0ZW5kYW5jZVJhdGUgPiBVQ0wgfCBBdHRlbmRhbmNlUmF0ZSA8IExDTCwgIllhIiwgIlRpZGFrIikpDQoNCiMgQnVhdCBjb250cm9sIGNoYXJ0DQpwbG90X2x5KGF0dGVuZGFuY2VfZGF0YSwgeCA9IH5FdmVudCwgeSA9IH5BdHRlbmRhbmNlUmF0ZSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnYmx1ZScpLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KHNpemUgPSA4LCBjb2xvciA9IGlmZWxzZShhdHRlbmRhbmNlX2RhdGEkT3V0bGllciA9PSAiWWEiLCAicmVkIiwgImJsdWUiKSksDQogICAgICAgIGhvdmVyaW5mbyA9ICd0ZXh0JywNCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgiRXZlbnQ6IiwgRXZlbnQsDQogICAgICAgICAgICAgICAgICAgICAgIjxicj5VbmRhbmdhbjoiLCBJbnZpdGF0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAiPGJyPkhhZGlyOiIsIEF0dGVuZGVlcywNCiAgICAgICAgICAgICAgICAgICAgICAiPGJyPlJhc2lvIEtlaGFkaXJhbjoiLCBBdHRlbmRhbmNlUmF0ZSwgIiUiKSkgJT4lDQogIGFkZF9saW5lcyh5ID0gcmVwKENMLCAzMCksIG5hbWUgPSAiQ0wgKDEwMCUpIiwgbGluZSA9IGxpc3QoY29sb3IgPSAnZ3JlZW4nLCBkYXNoID0gJ2RvdCcpKSAlPiUNCiAgYWRkX2xpbmVzKHkgPSByZXAoVUNMLCAzMCksIG5hbWUgPSAiVUNMICgxMTAlKSIsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JlZCcsIGRhc2ggPSAnZG90JykpICU+JQ0KICBhZGRfbGluZXMoeSA9IHJlcChMQ0wsIDMwKSwgbmFtZSA9ICJMQ0wgKDkwJSkiLCBsaW5lID0gbGlzdChjb2xvciA9ICdyZWQnLCBkYXNoID0gJ2RvdCcpKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIkNvbnRyb2wgQ2hhcnQg4oCTIEF0dGVuZGFuY2UgUmF0ZSB2cyBJbnZpdGF0aW9ucyIsDQogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiRXZlbnQgS2UtIiksDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUmFzaW8gS2VoYWRpcmFuICglKSIpLA0KICAgICAgICAgbGVnZW5kID0gbGlzdChvcmllbnRhdGlvbiA9ICdoJywgeCA9IDAuMywgeSA9IC0wLjIpKQ0KYGBgDQoNCiMgRmlzaGJvbmUgRGlhZ3JhbQ0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkRpYWdyYW1tZVJzdmciLCBxdWlldGx5ID0gVFJVRSkpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiRGlhZ3JhbW1lUnN2ZyIpDQp9DQoNCmxpYnJhcnkoRGlhZ3JhbW1lUikNCmxpYnJhcnkoRGlhZ3JhbW1lUnN2ZykNCmxpYnJhcnkocnN2ZykNCg0KZ3JhcGggPC0gZ3JWaXooIg0KZGlncmFwaCBmaXNoYm9uZSB7DQogIGdyYXBoIFtsYXlvdXQgPSBkb3QsIHJhbmtkaXIgPSBMUl0NCg0KICAjIERlZmF1bHQgbm9kZSBzdHlsZXMNCiAgbm9kZSBbZm9udG5hbWU9SGVsdmV0aWNhLCBmb250c2l6ZT0yNSwgc3R5bGU9ZmlsbGVkXQ0KDQogICMgQ2VudHJhbCBwcm9ibGVtDQogIFByb2JsZW0gW2xhYmVsPSdEZWxheWVkIEV2ZW50IFN0YXJ0Jywgc2hhcGU9ZWxsaXBzZSwgZmlsbGNvbG9yPWxpZ2h0Y29yYWwsIHdpZHRoPTUuMCwgaGVpZ2h0PTEuMl0NCg0KICAjIENhdGVnb3J5IG5vZGVzIChzaGFyZWQgc3R5bGUpDQogIG5vZGUgW3NoYXBlPWRpYW1vbmQsIHdpZHRoPTIuNSwgaGVpZ2h0PTEuMCwgZmlsbGNvbG9yPScjRkZENzAwJ10NCiAgQTEgW2xhYmVsPSdQZW9wbGUnXQ0KICBBMiBbbGFiZWw9J1Byb2Nlc3MnXQ0KICBBMyBbbGFiZWw9J0VxdWlwbWVudCddDQogIEE0IFtsYWJlbD0nVmVudWUnXQ0KICBBNSBbbGFiZWw9J0V4dGVybmFsIEZhY3RvcnMnXQ0KICBBNiBbbGFiZWw9J0NvbW11bmljYXRpb24nXQ0KDQogICMgUmVzZXQgbm9kZSBzdHlsZSBmb3Igc3ViLWNhdGVnb3JpZXMNCiAgbm9kZSBbc2hhcGU9ZWxsaXBzZSwgd2lkdGg9Mi41LCBoZWlnaHQ9MC42LCBmaWxsY29sb3I9JyM5MEVFOTAnXQ0KICBBMWEgW2xhYmVsPSdMYXRlIGFycml2YWwgb2Yga2V5IHBlcnNvbm5lbCddDQogIEExYiBbbGFiZWw9J0xhY2sgb2YgdHJhaW5lZCBzdGFmZiddDQogIEExYyBbbGFiZWw9J1VucHJlcGFyZWQgc3RhZmYnXQ0KDQogIEEyYSBbbGFiZWw9J1VuY2xlYXIgZXZlbnQgdGltZWxpbmUnXQ0KICBBMmIgW2xhYmVsPSdJbmFkZXF1YXRlIGV2ZW50IHBsYW5uaW5nJ10NCiAgQTJjIFtsYWJlbD0nTGFzdCBtaW51dGUgY2hhbmdlcyBpbiBzY2hlZHVsZSddDQoNCiAgQTNhIFtsYWJlbD0nRXF1aXBtZW50IG1hbGZ1bmN0aW9uJ10NCiAgQTNiIFtsYWJlbD0nTGF0ZSBkZWxpdmVyeSBvZiBlcXVpcG1lbnQnXQ0KDQogIEE0YSBbbGFiZWw9J1ZlbnVlIHVuYXZhaWxhYmlsaXR5J10NCiAgQTRiIFtsYWJlbD0nVmVudWUgc2V0dXAgaXNzdWVzJ10NCg0KICBBNWEgW2xhYmVsPSdUcmFmZmljIGNvbmdlc3Rpb24nXQ0KICBBNWIgW2xhYmVsPSdCYWQgd2VhdGhlciddDQoNCiAgQTZhIFtsYWJlbD0nTWlzY29tbXVuaWNhdGlvbiBiZXR3ZWVuIGV2ZW50IHBsYW5uZXJzJ10NCiAgQTZiIFtsYWJlbD0nSW5hY2N1cmF0ZSBjb21tdW5pY2F0aW9uIG9mIGV2ZW50IGRldGFpbHMnXQ0KDQogICMgUmVsYXRpb25zaGlwcw0KICBBMSAtPiBQcm9ibGVtDQogIEEyIC0+IFByb2JsZW0NCiAgQTMgLT4gUHJvYmxlbQ0KICBBNCAtPiBQcm9ibGVtDQogIEE1IC0+IFByb2JsZW0NCiAgQTYgLT4gUHJvYmxlbQ0KDQogIEExYSAtPiBBMQ0KICBBMWIgLT4gQTENCiAgQTFjIC0+IEExDQoNCiAgQTJhIC0+IEEyDQogIEEyYiAtPiBBMg0KICBBMmMgLT4gQTINCg0KICBBM2EgLT4gQTMNCiAgQTNiIC0+IEEzDQoNCiAgQTRhIC0+IEE0DQogIEE0YiAtPiBBNA0KDQogIEE1YSAtPiBBNQ0KICBBNWIgLT4gQTUNCg0KICBBNmEgLT4gQTYNCiAgQTZiIC0+IEE2DQp9DQoiKQ0KDQojIE91dHB1dCBkaXJlY3RvcnkgYW5kIHNhdmluZw0KZGlyLmNyZWF0ZSgiaW1hZ2VzL2V2ZW50X2RlbGF5cyIsIHJlY3Vyc2l2ZSA9IFRSVUUsIHNob3dXYXJuaW5ncyA9IEZBTFNFKQ0KDQojIE1lbmdndW5ha2FuIGV4cG9ydF9zdmcgZGFyaSBEaWFncmFtbWVSc3ZnDQpzdmdfY29kZSA8LSBEaWFncmFtbWVSc3ZnOjpleHBvcnRfc3ZnKGdyYXBoKQ0KcnN2Z19wbmcoY2hhclRvUmF3KHN2Z19jb2RlKSwgZmlsZSA9ICJpbWFnZXMvZXZlbnRfZGVsYXlzL2Zpc2hib25lX2V2ZW50X3N0YXJ0X2RlbGF5LnBuZyIsIHdpZHRoID0gMzAwMCwgaGVpZ2h0ID0gMzAwMCkNCnJzdmdfcGRmKGNoYXJUb1JhdyhzdmdfY29kZSksIGZpbGUgPSAiaW1hZ2VzL2V2ZW50X2RlbGF5cy9maXNoYm9uZV9ldmVudF9zdGFydF9kZWxheS5wZGYiKQ0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzL2V2ZW50X2RlbGF5cy9maXNoYm9uZV9ldmVudF9zdGFydF9kZWxheS5wbmciKQ0KYGBgDQoNCiMgRmxvd2NoYXJ0DQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQoNCmxpYnJhcnkoRGlhZ3JhbW1lUikNCg0KIyBDcmVhdGUgdGhlIGZsb3djaGFydCBkaWFncmFtIHVzaW5nIERpYWdyYW1tZVIncyBnclZpeiBmdW5jdGlvbg0KZmxvd2NoYXJ0IDwtIGdyVml6KCJkaWdyYXBoIGV2ZW50X3Byb2Nlc3Mgew0KICBncmFwaCBbbGF5b3V0ID0gZG90LCByYW5rZGlyID0gVEJdDQoNCiAgIyBEZWZhdWx0IG5vZGUgc3R5bGUgZm9yIHN0ZXBzDQogIG5vZGUgW2ZvbnRuYW1lID0gSGVsdmV0aWNhLCBmb250c2l6ZSA9IDE2LCBzaGFwZSA9IHJlY3RhbmdsZSwgc3R5bGUgPSBmaWxsZWQsIGZpbGxjb2xvciA9IGxpZ2h0Ymx1ZV0NCiAgDQogICMgRGVmaW5lIHRoZSBmbG93Y2hhcnQgc3RhZ2VzIHdpdGggYXBwcm9wcmlhdGUgc3ltYm9scw0KICBTdGFydCBbbGFiZWwgPSAnU3RhcnQnLCBzaGFwZSA9IGVsbGlwc2UsIGZpbGxjb2xvciA9IGxpZ2h0Y29yYWxdDQogIFBsYW4gW2xhYmVsID0gJ1BsYW46IElkZW50aWZ5IG9iamVjdGl2ZXMsIGNyZWF0ZSBidWRnZXQsIHNldCBkYXRlJywgc2hhcGUgPSByZWN0YW5nbGVdDQogIERlY2lzaW9uMSBbbGFiZWwgPSAnQnVkZ2V0IGFwcHJvdmVkPycsIHNoYXBlID0gZGlhbW9uZCwgd2lkdGggPSAyLjVdDQogIFByZXBhcmUgW2xhYmVsID0gJ1ByZXBhcmU6IEZpbmFsaXplIGRldGFpbHMsIGJvb2sgdmVuZG9ycywgc2VuZCBpbnZpdGVzJywgc2hhcGUgPSByZWN0YW5nbGVdDQogIERlY2lzaW9uMiBbbGFiZWwgPSAnVmVuZG9ycyBib29rZWQ/Jywgc2hhcGUgPSBkaWFtb25kLCB3aWR0aCA9IDIuNV0NCiAgRXhlY3V0ZSBbbGFiZWwgPSAnRXhlY3V0ZTogTWFuYWdlIHRoZSBldmVudCwgY29vcmRpbmF0ZSBzdGFmZicsIHNoYXBlID0gcmVjdGFuZ2xlXQ0KICBEZWNpc2lvbjMgW2xhYmVsID0gJ0V2ZW50IHN1Y2Nlc3NmdWw/Jywgc2hhcGUgPSBkaWFtb25kLCB3aWR0aCA9IDIuNV0NCiAgRXZhbHVhdGUgW2xhYmVsID0gJ0V2YWx1YXRlOiBDb2xsZWN0IGZlZWRiYWNrLCBhc3Nlc3Mgb3V0Y29tZXMsIHJldmlldyBidWRnZXQnLCBzaGFwZSA9IHJlY3RhbmdsZV0NCiAgRW5kIFtsYWJlbCA9ICdFbmQnLCBzaGFwZSA9IGVsbGlwc2UsIGZpbGxjb2xvciA9IGxpZ2h0Y29yYWxdDQogIA0KICAjIERlZmluZSB0aGUgZmxvdyBjb25uZWN0aW9ucyBiZXR3ZWVuIHRoZSBzdGVwcw0KICBTdGFydCAtPiBQbGFuDQogIFBsYW4gLT4gRGVjaXNpb24xDQogIERlY2lzaW9uMSAtPiBQcmVwYXJlIFtsYWJlbCA9ICdZZXMnXQ0KICBEZWNpc2lvbjEgLT4gRW5kIFtsYWJlbCA9ICdObyddDQogIFByZXBhcmUgLT4gRGVjaXNpb24yDQogIERlY2lzaW9uMiAtPiBFeGVjdXRlIFtsYWJlbCA9ICdZZXMnXQ0KICBEZWNpc2lvbjIgLT4gRW5kIFtsYWJlbCA9ICdObyddDQogIEV4ZWN1dGUgLT4gRGVjaXNpb24zDQogIERlY2lzaW9uMyAtPiBFdmFsdWF0ZSBbbGFiZWwgPSAnWWVzJ10NCiAgRGVjaXNpb24zIC0+IEVuZCBbbGFiZWwgPSAnTm8nXQ0KICBFdmFsdWF0ZSAtPiBFbmQNCiAgDQogICMgQWRkIGFycm93cyBmb3IgZmxvdw0KICBlZGdlIFthcnJvd2hlYWQgPSB2ZWVdDQp9DQoiKQ0KDQojIERpc3BsYXkgdGhlIGZsb3djaGFydA0KZmxvd2NoYXJ0DQpgYGANCg0KIyBIaXN0b2dyYW0NCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KbGlicmFyeShwbG90bHkpDQoNCiMgR2VuZXJhdGUgc3ludGhldGljIGd1ZXN0IGFycml2YWwgdGltZXMgZGF0YQ0Kc2V0LnNlZWQoMTIzKQ0KYXJyaXZhbF90aW1lcyA8LSBybm9ybSgxMDAwLCBtZWFuID0gNjAsIHNkID0gMTUpICAjIDEwMDAgcmFuZG9tIGFycml2YWwgdGltZXMgKG1lYW4gPSA2MCBtaW51dGVzLCBTRCA9IDE1IG1pbnV0ZXMpDQoNCiMgQ2FsY3VsYXRlIHRoZSBkZW5zaXR5IG9mIHRoZSBhcnJpdmFsIHRpbWUgZGF0YQ0KZGVuc2l0eV9kYXRhIDwtIGRlbnNpdHkoYXJyaXZhbF90aW1lcykNCg0KIyBDcmVhdGUgYSBoaXN0b2dyYW0gb2YgZ3Vlc3QgYXJyaXZhbCB0aW1lcyB1c2luZyBwbG90bHkNCmFycml2YWxfdGltZXNfcGxvdCA8LSBwbG90X2x5KA0KICB4ID0gYXJyaXZhbF90aW1lcywNCiAgdHlwZSA9ICdoaXN0b2dyYW0nLA0KICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ2xpZ2h0Z3JlZW4nLCBsaW5lID0gbGlzdChjb2xvciA9ICdibGFjaycsIHdpZHRoID0gMSkpLA0KICBuYW1lID0gJ0hpc3RvZ3JhbSBvZiBHdWVzdCBBcnJpdmFsIFRpbWVzJywNCiAgbmJpbnN4ID0gMzAsICAjIE51bWJlciBvZiBiaW5zDQogIG9wYWNpdHkgPSAwLjYsDQogIHNob3dsZWdlbmQgPSBUUlVFDQopICU+JQ0KICAjIEFkZCB0aGUgZGVuc2l0eSBjdXJ2ZQ0KICBhZGRfdHJhY2UoDQogICAgeCA9IGRlbnNpdHlfZGF0YSR4LCANCiAgICB5ID0gZGVuc2l0eV9kYXRhJHkgKiBsZW5ndGgoYXJyaXZhbF90aW1lcykgKiBkaWZmKHJhbmdlKGFycml2YWxfdGltZXMpKSAvIDMwLA0KICAgIHR5cGUgPSAnc2NhdHRlcicsDQogICAgbW9kZSA9ICdsaW5lcycsDQogICAgbmFtZSA9ICdEZW5zaXR5IEN1cnZlJywNCiAgICBsaW5lID0gbGlzdChjb2xvciA9ICdibGFjaycsIHdpZHRoID0gMyksDQogICAgc2hvd2xlZ2VuZCA9IFRSVUUNCiAgKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gJ0hpc3RvZ3JhbSBvZiBHdWVzdCBBcnJpdmFsIFRpbWVzIGF0IFNldmVyYWwgRXZlbnRzJywNCiAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAnQXJyaXZhbCBUaW1lIChtaW51dGVzKScsIHNob3dncmlkID0gRkFMU0UpLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdGcmVxdWVuY3kgLyBEZW5zaXR5Jywgc2hvd2dyaWQgPSBGQUxTRSksDQogICAgYmFyZ2FwID0gMC4xLA0KICAgIHBsb3RfYmdjb2xvciA9ICd3aGl0ZScsDQogICAgcGFwZXJfYmdjb2xvciA9ICd3aGl0ZScsDQogICAgc2hvd2xlZ2VuZCA9IFRSVUUsDQogICAgbGVnZW5kID0gbGlzdCgNCiAgICAgIG9yaWVudGF0aW9uID0gJ3YnLCAgICAjIHZlcnRpY2FsIGxlZ2VuZA0KICAgICAgeCA9IDAuOTgsICAgICAgICAgICAgICMgYWxtb3N0IGF0IHRoZSByaWdodCBlZGdlDQogICAgICB4YW5jaG9yID0gJ3JpZ2h0JywNCiAgICAgIHkgPSAwLjk4LCAgICAgICAgICAgICAjIGFsbW9zdCBhdCB0aGUgdG9wDQogICAgICB5YW5jaG9yID0gJ3RvcCcsDQogICAgICBiZ2NvbG9yID0gJ3JnYmEoMjU1LDI1NSwyNTUsMC44KScsICAjIHNlbWktdHJhbnNwYXJlbnQgYmFja2dyb3VuZA0KICAgICAgYm9yZGVyY29sb3IgPSAnYmxhY2snLA0KICAgICAgYm9yZGVyd2lkdGggPSAwLjMNCiAgICApDQogICkNCg0KIyBTaG93IHRoZSBwbG90DQphcnJpdmFsX3RpbWVzX3Bsb3QNCmBgYA0KDQojIFBhcmV0byBDaGFydA0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCg0KIyBTdW1tYXJpemUgdGhlIG51bWJlciBvZiBwcm9ibGVtcyBieSB0eXBlDQpwYXJldG9fZGF0YSA8LSBjaGVja19zaGVldCAlPiUNCiAgY291bnQoUHJvYmxlbSwgc29ydCA9IFRSVUUpICU+JQ0KICBtdXRhdGUoDQogICAgY3VtX2ZyZXEgPSBjdW1zdW0obikgLyBzdW0obikgKiAxMDAgICMgY3VtdWxhdGl2ZSBwZXJjZW50YWdlDQogICkNCg0KIyBDcmVhdGUgZGlmZmVyZW50IGNvbG9ycyBmb3IgZWFjaCBQcm9ibGVtDQpjb2xvcnMgPC0gYnJld2VyLnBhbChuID0gbGVuZ3RoKHBhcmV0b19kYXRhJFByb2JsZW0pLCBuYW1lID0gIlNldDMiKQ0KDQojIENyZWF0ZSBQbG90bHkgUGFyZXRvIENoYXJ0DQpmaWcgPC0gcGxvdF9seSgpDQoNCiMgQWRkIEJhciBDaGFydCAoQ291bnQpIC0gd2l0aCBkaWZmZXJlbnQgY29sb3JzDQpmaWcgPC0gZmlnICU+JSBhZGRfYmFycygNCiAgeCA9IH5yZW9yZGVyKHBhcmV0b19kYXRhJFByb2JsZW0sIC1wYXJldG9fZGF0YSRuKSwNCiAgeSA9IH5wYXJldG9fZGF0YSRuLA0KICBuYW1lID0gJ051bWJlciBvZiBQcm9ibGVtcycsDQogIG1hcmtlciA9IGxpc3QoY29sb3IgPSBjb2xvcnMpLA0KICB5YXhpcyA9ICJ5MSINCikNCg0KIyBBZGQgQ3VtdWxhdGl2ZSBMaW5lDQpmaWcgPC0gZmlnICU+JSBhZGRfbGluZXMoDQogIHggPSB+cmVvcmRlcihwYXJldG9fZGF0YSRQcm9ibGVtLCAtcGFyZXRvX2RhdGEkbiksDQogIHkgPSB+cGFyZXRvX2RhdGEkY3VtX2ZyZXEsDQogIG5hbWUgPSAnQ3VtdWxhdGl2ZSAoJSknLA0KICB5YXhpcyA9ICJ5MiIsDQogIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JlZCcsIGRhc2ggPSAnZGFzaCcpDQopDQoNCiMgQWRkIEN1dC1vZmYgTGluZSBhdCA4MCUNCmZpZyA8LSBmaWcgJT4lIGFkZF9saW5lcygNCiAgeCA9IH5yZW9yZGVyKHBhcmV0b19kYXRhJFByb2JsZW0sIC1wYXJldG9fZGF0YSRuKSwNCiAgeSA9IHJlcCg4MCwgbGVuZ3RoKHBhcmV0b19kYXRhJFByb2JsZW0pKSwNCiAgbmFtZSA9ICdDdXQtb2ZmIDgwJScsDQogIHlheGlzID0gInkyIiwNCiAgbGluZSA9IGxpc3QoY29sb3IgPSAnZ3JlZW4nLCBkYXNoID0gJ2RvdCcpDQopDQoNCiMgQWRqdXN0IGxheW91dA0KZmlnIDwtIGZpZyAlPiUgbGF5b3V0KA0KICB0aXRsZSA9ICJQYXJldG8gQ2hhcnQgLSBNb3N0IENvbW1vbiBQcm9ibGVtcyBEdXJpbmcgRXZlbnQgRXhlY3V0aW9uIiwNCiAgeGF4aXMgPSBsaXN0KA0KICAgIHRpdGxlID0gIkV2ZW50IFByb2JsZW1zIiwNCiAgICB0aWNrYW5nbGUgPSAtNDUgICAjIHRpbHQgNDUgZGVncmVlcw0KICApLA0KICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiTnVtYmVyIG9mIFByb2JsZW1zIiksDQogIHlheGlzMiA9IGxpc3QoDQogICAgdGl0bGUgPSAiQ3VtdWxhdGl2ZSAoJSkiLA0KICAgIG92ZXJsYXlpbmcgPSAieSIsDQogICAgc2lkZSA9ICJyaWdodCIsDQogICAgcmFuZ2UgPSBjKDAsIDEwMCkNCiAgKSwNCiAgbGVnZW5kID0gbGlzdCh4ID0gMC44LCB5ID0gMC43NSksDQogIHNoYXBlcyA9IGxpc3QoDQogICAgbGlzdCgNCiAgICAgIHR5cGUgPSAibGluZSIsDQogICAgICB4MCA9IC0wLjUsDQogICAgICB4MSA9IGxlbmd0aChwYXJldG9fZGF0YSRQcm9ibGVtKSAtIDAuNSwNCiAgICAgIHkwID0gODAsDQogICAgICB5MSA9IDgwLA0KICAgICAgeXJlZiA9ICJ5MiIsDQogICAgICBsaW5lID0gbGlzdChjb2xvciA9ICJncmVlbiIsIHdpZHRoID0gMiwgZGFzaCA9ICJkb3QiKQ0KICAgICkNCiAgKQ0KKQ0KDQojIFNob3cgY2hhcnQNCmZpZw0KYGBgDQoNCiMgU2NhdHRlciBEaWFncmFtDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQoNCmxpYnJhcnkocGxvdGx5KQ0KDQojIENyZWF0ZSBhIGRhdGFzZXQgd2l0aCBldmVudCBzaXplIChudW1iZXIgb2YgZ3Vlc3RzKSBhbmQgc3RhZmYgbnVtYmVyDQpzZXQuc2VlZCg0MikNCmV2ZW50X2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgRXZlbnRfU2l6ZSA9IGMoNTAsIDc1LCAxMDAsIDEyNSwgMTUwLCAxNzUsIDIwMCwgMjI1LCAyNTAsIDI3NSwgDQogICAgICAgICAgICAgICAgIDMwMCwgMzI1LCAzNTAsIDM3NSwgNDAwLCA0MjUsIDQ1MCwgNDc1LCA1MDAsIDUyNSksDQogIFN0YWZmX051bWJlciA9IGMoMTAsIDE0LCAxOCwgMjEsIDI1LCAyOCwgMzIsIDM1LCAzOCwgNDEsIA0KICAgICAgICAgICAgICAgICAgIDQ0LCA0OCwgNTEsIDU1LCA1OCwgNjIsIDY1LCA2OSwgNzIsIDc1KQ0KKQ0KDQojIEludHJvZHVjZSBzb21lIG5vaXNlIHRvIGdldCBhIGNvcnJlbGF0aW9uIG9mIGFyb3VuZCAwLjkNCmV2ZW50X2RhdGEkU3RhZmZfTnVtYmVyIDwtIGV2ZW50X2RhdGEkU3RhZmZfTnVtYmVyICsgcm5vcm0obiA9IDIwLCBtZWFuID0gMCwgc2QgPSAyKQ0KDQojIENhbGN1bGF0ZSB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgYmV0d2VlbiB0aGUgZXZlbnQgc2l6ZSBhbmQgc3RhZmYgbnVtYmVyDQpjb3JyZWxhdGlvbl92YWx1ZSA8LSBjb3IoZXZlbnRfZGF0YSRFdmVudF9TaXplLCBldmVudF9kYXRhJFN0YWZmX051bWJlcikNCg0KIyBDcmVhdGUgYSBzY2F0dGVyIHBsb3QgdXNpbmcgUGxvdGx5IHdpdGggYSBsaW5lYXIgcmVncmVzc2lvbiBsaW5lDQpmaWcgPC0gcGxvdF9seShldmVudF9kYXRhLCANCiAgICAgICAgICAgICAgIHggPSB+RXZlbnRfU2l6ZSwgDQogICAgICAgICAgICAgICB5ID0gflN0YWZmX051bWJlciwgDQogICAgICAgICAgICAgICB0eXBlID0gJ3NjYXR0ZXInLCANCiAgICAgICAgICAgICAgIG1vZGUgPSAnbWFya2VycycsDQogICAgICAgICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ2JsdWUnLCBzaXplID0gMTApKSAlPiUNCiAgYWRkX2xpbmVzKHggPSBldmVudF9kYXRhJEV2ZW50X1NpemUsIA0KICAgICAgICAgICAgeSA9IHByZWRpY3QobG0oU3RhZmZfTnVtYmVyIH4gRXZlbnRfU2l6ZSwgZGF0YSA9IGV2ZW50X2RhdGEpKSwgDQogICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICdyZWQnLCBkYXNoID0gJ3NvbGlkJywgd2lkdGggPSAyKSkgJT4lDQogIGxheW91dCh0aXRsZSA9IHBhc3RlKCJTY2F0dGVyIFBsb3Q6IFJlbGF0aW9uc2hpcCBCZXR3ZWVuIEV2ZW50IFNpemUgYW5kIFN0YWZmIE51bWJlclxuQ29ycmVsYXRpb246ICIsIHJvdW5kKGNvcnJlbGF0aW9uX3ZhbHVlLCAyKSksDQogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiRXZlbnQgU2l6ZSAoTnVtYmVyIG9mIEd1ZXN0cykiKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJTdGFmZiBOdW1iZXIiKSkNCg0KIyBTaG93IHRoZSBwbG90DQpmaWcNCmBgYA0K