Portland KPI Report

Load required libraries

# Load required libraries
library(readxl)        
library(dplyr)         
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)       
library(tidyr)         
library(stringr)       
library(scales)        
library(gridExtra)     
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
library(knitr)        
library(rmarkdown)    
library(lubridate)     
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
library(RColorBrewer)  

Load requiered excel data base

# Load the dataset
bd <-read_excel("/Users/sebastianespi/Downloads/DATA BASE sebastian - KPI portalnd report.xlsx")
bd
## # A tibble: 105 × 8
##     Week Name    Category   Acknowledgements `Late Ack >3days` `TTS < 10 days`
##    <dbl> <chr>   <chr>                 <dbl>             <dbl>           <dbl>
##  1    25 Team    Percentage               18                10              61
##  2    25 Ivey    Percentage               19                10              16
##  3    25 Corrina Percentage               16                89               4
##  4    26 Team    QTY                     319                30              56
##  5    26 Team    Percentage               17                 9               2
##  6    26 Ivey    QTY                     195                20              17
##  7    26 Ivey    Percentage               19                10               1
##  8    26 Corrina QTY                     124                10              39
##  9    26 Corrina Percentage               16                 8               3
## 10    27 Team    QTY                     348                30              56
## # ℹ 95 more rows
## # ℹ 2 more variables: `Invoice past due` <dbl>, `W-OTD (OOR)` <chr>

Exploratory Analisis of the data base

# Clean the dataset - your data is already in the right format
bd_clean <- bd %>%
  mutate(
    # Convert percentage columns to numeric (already clean numeric values)
    `Acknowledgements_%` = case_when(
      Category == "Percentage" ~ as.numeric(`Acknowledgements`),
      TRUE ~ NA_real_
    ),
    
    `Late Ack >3days_%` = case_when(
      Category == "Percentage" ~ as.numeric(`Late Ack >3days`),
      TRUE ~ NA_real_
    ),
    
    `TTS < 10 days_%` = case_when(
      Category == "Percentage" ~ as.numeric(`TTS < 10 days`),
      TRUE ~ NA_real_
    ),
    
    `Invoice past due_%` = case_when(
      Category == "Percentage" ~ as.numeric(`Invoice past due`),
      TRUE ~ NA_real_
    ),
    
    `W-OTD (OOR)_%` = case_when(
      Category == "Percentage" ~ as.numeric(`W-OTD (OOR)`),
      TRUE ~ NA_real_
    ),
    
    # Convert quantity columns to numeric
    `Acknowledgements_QTY` = case_when(
      Category == "QTY" ~ as.numeric(`Acknowledgements`),
      TRUE ~ NA_real_
    ),
    
    `Late Ack >3days_QTY` = case_when(
      Category == "QTY" ~ as.numeric(`Late Ack >3days`),
      TRUE ~ NA_real_
    ),
    
    `TTS < 10 days_QTY` = case_when(
      Category == "QTY" ~ as.numeric(`TTS < 10 days`),
      TRUE ~ NA_real_
    ),
    
    `Invoice past due_QTY` = case_when(
      Category == "QTY" ~ as.numeric(`Invoice past due`),
      TRUE ~ NA_real_
    ),
    
    # Parse W-OTD (OOR) quantity (numerator/denominator format)
    `W-OTD (OOR)_Numerator` = case_when(
      Category == "QTY" & str_detect(`W-OTD (OOR)`, "/") ~ as.numeric(str_extract(`W-OTD (OOR)`, "^[0-9]+")),
      TRUE ~ NA_real_
    ),
    `W-OTD (OOR)_Denominator` = case_when(
      Category == "QTY" & str_detect(`W-OTD (OOR)`, "/") ~ as.numeric(str_extract(`W-OTD (OOR)`, "[0-9]+$")),
      TRUE ~ NA_real_
    )
  )
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `W-OTD (OOR)_% = case_when(...)`.
## Caused by warning:
## ! NAs introduced by coercion
# Separate data by category (QTY vs Percentage)
bd_percentages <- bd_clean %>% 
  filter(Category == "Percentage") %>%
  select(Week, Name, `Acknowledgements_%`, `Late Ack >3days_%`, `TTS < 10 days_%`, 
         `Invoice past due_%`, `W-OTD (OOR)_%`)

bd_quantities <- bd_clean %>% 
  filter(Category == "QTY") %>%
  select(Week, Name, `Acknowledgements_QTY`, `Late Ack >3days_QTY`, `TTS < 10 days_QTY`, 
         `Invoice past due_QTY`, `W-OTD (OOR)_Numerator`, `W-OTD (OOR)_Denominator`)

cat("Data cleaning completed successfully!\n")
## Data cleaning completed successfully!
cat("Percentage data points:", nrow(bd_percentages), "\n")
## Percentage data points: 54
cat("Quantity data points:", nrow(bd_quantities), "\n\n")
## Quantity data points: 51
# Display sample of cleaned data to verify
cat("Sample of Percentage Data:\n")
## Sample of Percentage Data:
print(head(bd_percentages))
## # A tibble: 6 × 7
##    Week Name    `Acknowledgements_%` `Late Ack >3days_%` `TTS < 10 days_%`
##   <dbl> <chr>                  <dbl>               <dbl>             <dbl>
## 1    25 Team                      18                  10                61
## 2    25 Ivey                      19                  10                16
## 3    25 Corrina                   16                  89                 4
## 4    26 Team                      17                   9                 2
## 5    26 Ivey                      19                  10                 1
## 6    26 Corrina                   16                   8                 3
## # ℹ 2 more variables: `Invoice past due_%` <dbl>, `W-OTD (OOR)_%` <dbl>
# Create color palette for consistent theming
team_colors <- c("Team" = "#2E86AB", "Ivey" = "#A23B72", "Corrina" = "#F18F01")

GRAPH 1: Acknowledgements Percentage Analysis

graph_ack_pct <- ggplot(bd_percentages, aes(x = Week, y = `Acknowledgements_%`, color = Name)) +
  geom_line(linewidth = 2, alpha = 0.8) +
  geom_point(size = 5) +
  scale_color_manual(values = team_colors) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 10)) +
  labs(
    title = "Acknowledgements Rate Analysis by Team Member",
    subtitle = "Weekly acknowledgement percentage performance (Week 25-42)",
    x = "Week Number",
    y = "Acknowledgements Rate (%)",
    color = "Team Member",
    caption = "Higher percentages indicate better acknowledgement performance"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_ack_pct)

Acknowledgements Rate: This graph shows the efficiency in processing acknowledgements for each team member. Higher percentages indicate better performance in acknowledgement processing.

GRAPH 2: Late Acknowledgements (>3 days) Percentage Analysis

graph_late_pct <- ggplot(bd_percentages, aes(x = Week, y = `Late Ack >3days_%`, color = Name)) +
  geom_line(linewidth = 2, alpha = 0.8) +
  geom_point(size = 5) +
  scale_color_manual(values = team_colors) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 10)) +
  labs(
    title = "Late Acknowledgements Rate Analysis (>3 days)",
    subtitle = "Percentage of acknowledgements delayed by more than 3 days",
    x = "Week Number",
    y = "Late Acknowledgements Rate (%)",
    color = "Team Member",
    caption = "Lower percentages indicate better performance"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_late_pct)

Late Acknowledgements (>3 days): This graph tracks delays in acknowledgement processing, where lower percentages are better. Spikes in this graph may indicate system issues, increased volume, or process bottlenecks.

GRAPH 3: Time to Ship (<10 days) Percentage Analysis

graph_tts_pct <- ggplot(bd_percentages, aes(x = Week, y = `TTS < 10 days_%`, color = Name)) +
  geom_line(linewidth = 2, alpha = 0.8) +
  geom_point(size = 5) +
  scale_color_manual(values = team_colors) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 10)) +
  labs(
    title = "Time to Ship Performance Analysis (<10 days)",
    subtitle = "Percentage of orders shipped within 10 days",
    x = "Week Number",
    y = "TTS < 10 days Rate (%)",
    color = "Team Member",
    caption = "Higher percentages indicate better shipping performance"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_tts_pct)

Time to Ship (<10 days): This graph measures shipping efficiency, where higher percentages mean more orders are shipped within 10 days, which is excellent for customer satisfaction.

GRAPH 4: Invoice Past Due Percentage Analysis

graph_invoice_pct <- ggplot(bd_percentages, aes(x = Week, y = `Invoice past due_%`, color = Name)) +
  geom_line(linewidth = 2, alpha = 0.8) +
  geom_point(size = 5) +
  scale_color_manual(values = team_colors) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 10)) +
  labs(
    title = "Invoice Past Due Rate Analysis",
    subtitle = "Percentage of invoices that are past due",
    x = "Week Number",
    y = "Invoice Past Due Rate (%)",
    color = "Team Member",
    caption = "Lower percentages indicate better invoice management"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_invoice_pct)

Invoice Past Due: This graph monitors billing and payment management, where lower percentages are better. High percentages may suggest billing process issues, customer payment problems, or credit management challenges that require immediate attention.

GRAPH 5: W-OTD (OOR) Percentage Analysis

graph_wotd_pct <- ggplot(bd_percentages, aes(x = Week, y = `W-OTD (OOR)_%`, color = Name)) +
  geom_line(linewidth = 2, alpha = 0.8) +
  geom_point(size = 5) +
  scale_color_manual(values = team_colors) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 10)) +
  labs(
    title = "W-OTD (OOR) Performance Analysis",
    subtitle = "Open Order Report / On-Time Delivery percentage",
    x = "Week Number",
    y = "W-OTD (OOR) Rate (%)",
    color = "Team Member",
    caption = "Higher percentages indicate better order management"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_wotd_pct)

W-OTD (OOR) Performance: This graph tracks open order reports and on-time delivery performance, where higher percentages indicate better order management and delivery success.

GRAPH 6: Acknowledgements Quantity Analysis

graph_ack_qty <- ggplot(bd_quantities, aes(x = Week, y = `Acknowledgements_QTY`, fill = Name)) +
  geom_col(position = "dodge", alpha = 0.8, width = 0.7) +
  scale_fill_manual(values = team_colors) +
  scale_y_continuous(labels = comma_format()) +
  labs(
    title = "Acknowledgements Volume Analysis by Team Member",
    subtitle = "Weekly quantity of acknowledgements processed",
    x = "Week Number",
    y = "Number of Acknowledgements",
    fill = "Team Member",
    caption = "Shows actual workload and processing volume"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_ack_qty)

Graphs 6-10 - Volume Analysis: These bar charts show actual workload volumes for each team member, helping understand the scale of operations and workload distribution

GRAPH 7: Late Acknowledgements Quantity Analysis

graph_late_qty <- ggplot(bd_quantities, aes(x = Week, y = `Late Ack >3days_QTY`, fill = Name)) +
  geom_col(position = "dodge", alpha = 0.8, width = 0.7) +
  scale_fill_manual(values = team_colors) +
  scale_y_continuous(labels = comma_format()) +
  labs(
    title = "Late Acknowledgements Volume Analysis (>3 days)",
    subtitle = "Number of acknowledgements delayed by more than 3 days",
    x = "Week Number",
    y = "Number of Late Acknowledgements",
    fill = "Team Member",
    caption = "Shows actual volume of delayed acknowledgements"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_late_qty)

GRAPH 8: Time to Ship Quantity Analysis

graph_tts_qty <- ggplot(bd_quantities, aes(x = Week, y = `TTS < 10 days_QTY`, fill = Name)) +
  geom_col(position = "dodge", alpha = 0.8, width = 0.7) +
  scale_fill_manual(values = team_colors) +
  scale_y_continuous(labels = comma_format()) +
  labs(
    title = "Time to Ship Volume Analysis (<10 days)",
    subtitle = "Number of orders shipped within 10 days",
    x = "Week Number",
    y = "Number of Orders Shipped <10 days",
    fill = "Team Member",
    caption = "Shows actual volume of fast shipments"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )

print(graph_tts_qty)

GRAPH 9: Invoice Past Due Quantity Analysis

graph_invoice_qty <- ggplot(bd_quantities, aes(x = Week, y = `Invoice past due_QTY`, fill = Name)) +
  geom_col(position = "dodge", alpha = 0.8, width = 0.7) +
  scale_fill_manual(values = team_colors) +
  scale_y_continuous(labels = comma_format()) +
  labs(
    title = "Invoice Past Due Volume Analysis",
    subtitle = "Number of invoices that are past due",
    x = "Week Number",
    y = "Number of Past Due Invoices",
    fill = "Team Member",
    caption = "Shows actual volume of overdue invoices"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )
print(graph_invoice_qty)

GRAPH 10: W-OTD (OOR) Volume Analysis

graph_wotd_qty <- ggplot(bd_quantities, aes(x = Week, y = `W-OTD (OOR)_Numerator`, fill = Name)) +
  geom_col(position = "dodge", alpha = 0.8, width = 0.7) +
  scale_fill_manual(values = team_colors) +
  scale_y_continuous(labels = comma_format()) +
  labs(
    title = "W-OTD (OOR) Open Orders Volume Analysis",
    subtitle = "Number of open orders reported by team member",
    x = "Week Number",
    y = "Number of Open Orders",
    fill = "Team Member",
    caption = "Shows actual volume of open orders"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12, color = "gray60"),
    legend.position = "bottom",
    panel.grid.minor = element_blank(),
    axis.text = element_text(size = 10)
  )
print(graph_wotd_qty)

LS0tCnRpdGxlOiAiUG9ydGxhbmQgUGxhbnQgS1BJIFRyYWNrZXIiCmF1dGhvcjogIlNlYmFzdGlhbiBFc3Bpbm96YSAtIFN1cGx5IENoYWluIEZsb3cgQ29udHJvbGxlciBhbmQgUHJvamVjdCBNYW5hZ21lbnQgSW50ZXJuIgpkYXRlOiAiMjAyNS0xMC0xNSIKb3V0cHV0OiAKIGh0bWxfZG9jdW1lbnQ6IAogIHRvYzogVFJVRQogIHRvY19mbG9hdDogVFJVRQogIGNvZGVfZG93bmxvYWQ6IFRSVUUKICB0aGVtZTogeWV0aQotLS0KCiMgPHNwYW4gc3R5bGU9J2NvbG9yOkdyZWVuOyc+ICBQb3J0bGFuZCBLUEkgUmVwb3J0IDwvc3Bhbj4gCgohW10oaHR0cHM6Ly90NC5mdGNkbi5uZXQvanBnLzA2LzM0LzYxLzM3LzM2MF9GXzYzNDYxMzc1Nl81cU1lMkZER2g3MzR4dG1leEw4dVRqOUJRMmN1MlJOeC5qcGcpCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6R3JlZW47Jz4gTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMgPC9zcGFuPiAKCmBgYHtyfQojIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkocmVhZHhsKSAgICAgICAgCmxpYnJhcnkoZHBseXIpICAgICAgICAgCmxpYnJhcnkoZ2dwbG90MikgICAgICAgCmxpYnJhcnkodGlkeXIpICAgICAgICAgCmxpYnJhcnkoc3RyaW5ncikgICAgICAgCmxpYnJhcnkoc2NhbGVzKSAgICAgICAgCmxpYnJhcnkoZ3JpZEV4dHJhKSAgICAgCmxpYnJhcnkoa25pdHIpICAgICAgICAKbGlicmFyeShybWFya2Rvd24pICAgIApsaWJyYXJ5KGx1YnJpZGF0ZSkgICAgIApsaWJyYXJ5KFJDb2xvckJyZXdlcikgIApgYGAKCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpHcmVlbjsnPiBMb2FkIHJlcXVpZXJlZCBleGNlbCBkYXRhIGJhc2U8L3NwYW4+IApgYGB7cn0KIyBMb2FkIHRoZSBkYXRhc2V0CmJkIDwtcmVhZF9leGNlbCgiL1VzZXJzL3NlYmFzdGlhbmVzcGkvRG93bmxvYWRzL0RBVEEgQkFTRSBzZWJhc3RpYW4gLSBLUEkgcG9ydGFsbmQgcmVwb3J0Lnhsc3giKQpiZApgYGAKCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpHcmVlbjsnPiBFeHBsb3JhdG9yeSBBbmFsaXNpcyBvZiB0aGUgZGF0YSBiYXNlIDwvc3Bhbj4gCmBgYHtyfQojIENsZWFuIHRoZSBkYXRhc2V0IC0geW91ciBkYXRhIGlzIGFscmVhZHkgaW4gdGhlIHJpZ2h0IGZvcm1hdApiZF9jbGVhbiA8LSBiZCAlPiUKICBtdXRhdGUoCiAgICAjIENvbnZlcnQgcGVyY2VudGFnZSBjb2x1bW5zIHRvIG51bWVyaWMgKGFscmVhZHkgY2xlYW4gbnVtZXJpYyB2YWx1ZXMpCiAgICBgQWNrbm93bGVkZ2VtZW50c18lYCA9IGNhc2Vfd2hlbigKICAgICAgQ2F0ZWdvcnkgPT0gIlBlcmNlbnRhZ2UiIH4gYXMubnVtZXJpYyhgQWNrbm93bGVkZ2VtZW50c2ApLAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICksCiAgICAKICAgIGBMYXRlIEFjayA+M2RheXNfJWAgPSBjYXNlX3doZW4oCiAgICAgIENhdGVnb3J5ID09ICJQZXJjZW50YWdlIiB+IGFzLm51bWVyaWMoYExhdGUgQWNrID4zZGF5c2ApLAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICksCiAgICAKICAgIGBUVFMgPCAxMCBkYXlzXyVgID0gY2FzZV93aGVuKAogICAgICBDYXRlZ29yeSA9PSAiUGVyY2VudGFnZSIgfiBhcy5udW1lcmljKGBUVFMgPCAxMCBkYXlzYCksCiAgICAgIFRSVUUgfiBOQV9yZWFsXwogICAgKSwKICAgIAogICAgYEludm9pY2UgcGFzdCBkdWVfJWAgPSBjYXNlX3doZW4oCiAgICAgIENhdGVnb3J5ID09ICJQZXJjZW50YWdlIiB+IGFzLm51bWVyaWMoYEludm9pY2UgcGFzdCBkdWVgKSwKICAgICAgVFJVRSB+IE5BX3JlYWxfCiAgICApLAogICAgCiAgICBgVy1PVEQgKE9PUilfJWAgPSBjYXNlX3doZW4oCiAgICAgIENhdGVnb3J5ID09ICJQZXJjZW50YWdlIiB+IGFzLm51bWVyaWMoYFctT1REIChPT1IpYCksCiAgICAgIFRSVUUgfiBOQV9yZWFsXwogICAgKSwKICAgIAogICAgIyBDb252ZXJ0IHF1YW50aXR5IGNvbHVtbnMgdG8gbnVtZXJpYwogICAgYEFja25vd2xlZGdlbWVudHNfUVRZYCA9IGNhc2Vfd2hlbigKICAgICAgQ2F0ZWdvcnkgPT0gIlFUWSIgfiBhcy5udW1lcmljKGBBY2tub3dsZWRnZW1lbnRzYCksCiAgICAgIFRSVUUgfiBOQV9yZWFsXwogICAgKSwKICAgIAogICAgYExhdGUgQWNrID4zZGF5c19RVFlgID0gY2FzZV93aGVuKAogICAgICBDYXRlZ29yeSA9PSAiUVRZIiB+IGFzLm51bWVyaWMoYExhdGUgQWNrID4zZGF5c2ApLAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICksCiAgICAKICAgIGBUVFMgPCAxMCBkYXlzX1FUWWAgPSBjYXNlX3doZW4oCiAgICAgIENhdGVnb3J5ID09ICJRVFkiIH4gYXMubnVtZXJpYyhgVFRTIDwgMTAgZGF5c2ApLAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICksCiAgICAKICAgIGBJbnZvaWNlIHBhc3QgZHVlX1FUWWAgPSBjYXNlX3doZW4oCiAgICAgIENhdGVnb3J5ID09ICJRVFkiIH4gYXMubnVtZXJpYyhgSW52b2ljZSBwYXN0IGR1ZWApLAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICksCiAgICAKICAgICMgUGFyc2UgVy1PVEQgKE9PUikgcXVhbnRpdHkgKG51bWVyYXRvci9kZW5vbWluYXRvciBmb3JtYXQpCiAgICBgVy1PVEQgKE9PUilfTnVtZXJhdG9yYCA9IGNhc2Vfd2hlbigKICAgICAgQ2F0ZWdvcnkgPT0gIlFUWSIgJiBzdHJfZGV0ZWN0KGBXLU9URCAoT09SKWAsICIvIikgfiBhcy5udW1lcmljKHN0cl9leHRyYWN0KGBXLU9URCAoT09SKWAsICJeWzAtOV0rIikpLAogICAgICBUUlVFIH4gTkFfcmVhbF8KICAgICksCiAgICBgVy1PVEQgKE9PUilfRGVub21pbmF0b3JgID0gY2FzZV93aGVuKAogICAgICBDYXRlZ29yeSA9PSAiUVRZIiAmIHN0cl9kZXRlY3QoYFctT1REIChPT1IpYCwgIi8iKSB+IGFzLm51bWVyaWMoc3RyX2V4dHJhY3QoYFctT1REIChPT1IpYCwgIlswLTldKyQiKSksCiAgICAgIFRSVUUgfiBOQV9yZWFsXwogICAgKQogICkKCiMgU2VwYXJhdGUgZGF0YSBieSBjYXRlZ29yeSAoUVRZIHZzIFBlcmNlbnRhZ2UpCmJkX3BlcmNlbnRhZ2VzIDwtIGJkX2NsZWFuICU+JSAKICBmaWx0ZXIoQ2F0ZWdvcnkgPT0gIlBlcmNlbnRhZ2UiKSAlPiUKICBzZWxlY3QoV2VlaywgTmFtZSwgYEFja25vd2xlZGdlbWVudHNfJWAsIGBMYXRlIEFjayA+M2RheXNfJWAsIGBUVFMgPCAxMCBkYXlzXyVgLCAKICAgICAgICAgYEludm9pY2UgcGFzdCBkdWVfJWAsIGBXLU9URCAoT09SKV8lYCkKCmJkX3F1YW50aXRpZXMgPC0gYmRfY2xlYW4gJT4lIAogIGZpbHRlcihDYXRlZ29yeSA9PSAiUVRZIikgJT4lCiAgc2VsZWN0KFdlZWssIE5hbWUsIGBBY2tub3dsZWRnZW1lbnRzX1FUWWAsIGBMYXRlIEFjayA+M2RheXNfUVRZYCwgYFRUUyA8IDEwIGRheXNfUVRZYCwgCiAgICAgICAgIGBJbnZvaWNlIHBhc3QgZHVlX1FUWWAsIGBXLU9URCAoT09SKV9OdW1lcmF0b3JgLCBgVy1PVEQgKE9PUilfRGVub21pbmF0b3JgKQoKY2F0KCJEYXRhIGNsZWFuaW5nIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHkhXG4iKQpjYXQoIlBlcmNlbnRhZ2UgZGF0YSBwb2ludHM6IiwgbnJvdyhiZF9wZXJjZW50YWdlcyksICJcbiIpCmNhdCgiUXVhbnRpdHkgZGF0YSBwb2ludHM6IiwgbnJvdyhiZF9xdWFudGl0aWVzKSwgIlxuXG4iKQoKIyBEaXNwbGF5IHNhbXBsZSBvZiBjbGVhbmVkIGRhdGEgdG8gdmVyaWZ5CmNhdCgiU2FtcGxlIG9mIFBlcmNlbnRhZ2UgRGF0YTpcbiIpCnByaW50KGhlYWQoYmRfcGVyY2VudGFnZXMpKQoKIyBDcmVhdGUgY29sb3IgcGFsZXR0ZSBmb3IgY29uc2lzdGVudCB0aGVtaW5nCnRlYW1fY29sb3JzIDwtIGMoIlRlYW0iID0gIiMyRTg2QUIiLCAiSXZleSIgPSAiI0EyM0I3MiIsICJDb3JyaW5hIiA9ICIjRjE4RjAxIikKYGBgCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpHcmVlbjsnPiBHUkFQSCAxOiBBY2tub3dsZWRnZW1lbnRzIFBlcmNlbnRhZ2UgQW5hbHlzaXMgPC9zcGFuPiAKCmBgYHtyfQpncmFwaF9hY2tfcGN0IDwtIGdncGxvdChiZF9wZXJjZW50YWdlcywgYWVzKHggPSBXZWVrLCB5ID0gYEFja25vd2xlZGdlbWVudHNfJWAsIGNvbG9yID0gTmFtZSkpICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMiwgYWxwaGEgPSAwLjgpICsKICBnZW9tX3BvaW50KHNpemUgPSA1KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHRlYW1fY29sb3JzKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTAwKSwgYnJlYWtzID0gc2VxKDAsIDEwMCwgMTApKSArCiAgbGFicygKICAgIHRpdGxlID0gIkFja25vd2xlZGdlbWVudHMgUmF0ZSBBbmFseXNpcyBieSBUZWFtIE1lbWJlciIsCiAgICBzdWJ0aXRsZSA9ICJXZWVrbHkgYWNrbm93bGVkZ2VtZW50IHBlcmNlbnRhZ2UgcGVyZm9ybWFuY2UgKFdlZWsgMjUtNDIpIiwKICAgIHggPSAiV2VlayBOdW1iZXIiLAogICAgeSA9ICJBY2tub3dsZWRnZW1lbnRzIFJhdGUgKCUpIiwKICAgIGNvbG9yID0gIlRlYW0gTWVtYmVyIiwKICAgIGNhcHRpb24gPSAiSGlnaGVyIHBlcmNlbnRhZ2VzIGluZGljYXRlIGJldHRlciBhY2tub3dsZWRnZW1lbnQgcGVyZm9ybWFuY2UiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJncmF5NjAiKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQoKcHJpbnQoZ3JhcGhfYWNrX3BjdCkKCmBgYAoqKkFja25vd2xlZGdlbWVudHMgUmF0ZToqKiBUaGlzIGdyYXBoIHNob3dzIHRoZSBlZmZpY2llbmN5IGluIHByb2Nlc3NpbmcgYWNrbm93bGVkZ2VtZW50cyBmb3IgZWFjaCB0ZWFtIG1lbWJlci4gSGlnaGVyIHBlcmNlbnRhZ2VzIGluZGljYXRlIGJldHRlciBwZXJmb3JtYW5jZSBpbiBhY2tub3dsZWRnZW1lbnQgcHJvY2Vzc2luZy4KCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpHcmVlbjsnPiBHUkFQSCAyOiBMYXRlIEFja25vd2xlZGdlbWVudHMgKD4zIGRheXMpIFBlcmNlbnRhZ2UgQW5hbHlzaXMgPC9zcGFuPiAKYGBge3J9CmdyYXBoX2xhdGVfcGN0IDwtIGdncGxvdChiZF9wZXJjZW50YWdlcywgYWVzKHggPSBXZWVrLCB5ID0gYExhdGUgQWNrID4zZGF5c18lYCwgY29sb3IgPSBOYW1lKSkgKwogIGdlb21fbGluZShsaW5ld2lkdGggPSAyLCBhbHBoYSA9IDAuOCkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gdGVhbV9jb2xvcnMpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApLCBicmVha3MgPSBzZXEoMCwgMTAwLCAxMCkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTGF0ZSBBY2tub3dsZWRnZW1lbnRzIFJhdGUgQW5hbHlzaXMgKD4zIGRheXMpIiwKICAgIHN1YnRpdGxlID0gIlBlcmNlbnRhZ2Ugb2YgYWNrbm93bGVkZ2VtZW50cyBkZWxheWVkIGJ5IG1vcmUgdGhhbiAzIGRheXMiLAogICAgeCA9ICJXZWVrIE51bWJlciIsCiAgICB5ID0gIkxhdGUgQWNrbm93bGVkZ2VtZW50cyBSYXRlICglKSIsCiAgICBjb2xvciA9ICJUZWFtIE1lbWJlciIsCiAgICBjYXB0aW9uID0gIkxvd2VyIHBlcmNlbnRhZ2VzIGluZGljYXRlIGJldHRlciBwZXJmb3JtYW5jZSIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImdyYXk2MCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApCgpwcmludChncmFwaF9sYXRlX3BjdCkKCmBgYAoqKkxhdGUgQWNrbm93bGVkZ2VtZW50cyAoPjMgZGF5cyk6KiogVGhpcyBncmFwaCB0cmFja3MgZGVsYXlzIGluIGFja25vd2xlZGdlbWVudCBwcm9jZXNzaW5nLCB3aGVyZSBsb3dlciBwZXJjZW50YWdlcyBhcmUgYmV0dGVyLiBTcGlrZXMgaW4gdGhpcyBncmFwaCBtYXkgaW5kaWNhdGUgc3lzdGVtIGlzc3VlcywgaW5jcmVhc2VkIHZvbHVtZSwgb3IgcHJvY2VzcyBib3R0bGVuZWNrcy4gCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6R3JlZW47Jz4gR1JBUEggMzogVGltZSB0byBTaGlwICg8MTAgZGF5cykgUGVyY2VudGFnZSBBbmFseXNpcyA8L3NwYW4+CgpgYGB7cn0KZ3JhcGhfdHRzX3BjdCA8LSBnZ3Bsb3QoYmRfcGVyY2VudGFnZXMsIGFlcyh4ID0gV2VlaywgeSA9IGBUVFMgPCAxMCBkYXlzXyVgLCBjb2xvciA9IE5hbWUpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDIsIGFscGhhID0gMC44KSArCiAgZ2VvbV9wb2ludChzaXplID0gNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB0ZWFtX2NvbG9ycykgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCksIGJyZWFrcyA9IHNlcSgwLCAxMDAsIDEwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJUaW1lIHRvIFNoaXAgUGVyZm9ybWFuY2UgQW5hbHlzaXMgKDwxMCBkYXlzKSIsCiAgICBzdWJ0aXRsZSA9ICJQZXJjZW50YWdlIG9mIG9yZGVycyBzaGlwcGVkIHdpdGhpbiAxMCBkYXlzIiwKICAgIHggPSAiV2VlayBOdW1iZXIiLAogICAgeSA9ICJUVFMgPCAxMCBkYXlzIFJhdGUgKCUpIiwKICAgIGNvbG9yID0gIlRlYW0gTWVtYmVyIiwKICAgIGNhcHRpb24gPSAiSGlnaGVyIHBlcmNlbnRhZ2VzIGluZGljYXRlIGJldHRlciBzaGlwcGluZyBwZXJmb3JtYW5jZSIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImdyYXk2MCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApCgpwcmludChncmFwaF90dHNfcGN0KQoKYGBgCioqVGltZSB0byBTaGlwICg8MTAgZGF5cyk6KiogVGhpcyBncmFwaCBtZWFzdXJlcyBzaGlwcGluZyBlZmZpY2llbmN5LCB3aGVyZSBoaWdoZXIgcGVyY2VudGFnZXMgbWVhbiBtb3JlIG9yZGVycyBhcmUgc2hpcHBlZCB3aXRoaW4gMTAgZGF5cywgd2hpY2ggaXMgZXhjZWxsZW50IGZvciBjdXN0b21lciBzYXRpc2ZhY3Rpb24uCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6R3JlZW47Jz4gR1JBUEggNDogSW52b2ljZSBQYXN0IER1ZSBQZXJjZW50YWdlIEFuYWx5c2lzIDwvc3Bhbj4KCmBgYHtyfQpncmFwaF9pbnZvaWNlX3BjdCA8LSBnZ3Bsb3QoYmRfcGVyY2VudGFnZXMsIGFlcyh4ID0gV2VlaywgeSA9IGBJbnZvaWNlIHBhc3QgZHVlXyVgLCBjb2xvciA9IE5hbWUpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDIsIGFscGhhID0gMC44KSArCiAgZ2VvbV9wb2ludChzaXplID0gNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB0ZWFtX2NvbG9ycykgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCksIGJyZWFrcyA9IHNlcSgwLCAxMDAsIDEwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJJbnZvaWNlIFBhc3QgRHVlIFJhdGUgQW5hbHlzaXMiLAogICAgc3VidGl0bGUgPSAiUGVyY2VudGFnZSBvZiBpbnZvaWNlcyB0aGF0IGFyZSBwYXN0IGR1ZSIsCiAgICB4ID0gIldlZWsgTnVtYmVyIiwKICAgIHkgPSAiSW52b2ljZSBQYXN0IER1ZSBSYXRlICglKSIsCiAgICBjb2xvciA9ICJUZWFtIE1lbWJlciIsCiAgICBjYXB0aW9uID0gIkxvd2VyIHBlcmNlbnRhZ2VzIGluZGljYXRlIGJldHRlciBpbnZvaWNlIG1hbmFnZW1lbnQiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJncmF5NjAiKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQoKcHJpbnQoZ3JhcGhfaW52b2ljZV9wY3QpCmBgYAoqKkludm9pY2UgUGFzdCBEdWU6KiogVGhpcyBncmFwaCBtb25pdG9ycyBiaWxsaW5nIGFuZCBwYXltZW50IG1hbmFnZW1lbnQsIHdoZXJlIGxvd2VyIHBlcmNlbnRhZ2VzIGFyZSBiZXR0ZXIuIEhpZ2ggcGVyY2VudGFnZXMgbWF5IHN1Z2dlc3QgYmlsbGluZyBwcm9jZXNzIGlzc3VlcywgY3VzdG9tZXIgcGF5bWVudCBwcm9ibGVtcywgb3IgY3JlZGl0IG1hbmFnZW1lbnQgY2hhbGxlbmdlcyB0aGF0IHJlcXVpcmUgaW1tZWRpYXRlIGF0dGVudGlvbi4KCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpHcmVlbjsnPiBHUkFQSCA1OiBXLU9URCAoT09SKSBQZXJjZW50YWdlIEFuYWx5c2lzIDwvc3Bhbj4KYGBge3J9CmdyYXBoX3dvdGRfcGN0IDwtIGdncGxvdChiZF9wZXJjZW50YWdlcywgYWVzKHggPSBXZWVrLCB5ID0gYFctT1REIChPT1IpXyVgLCBjb2xvciA9IE5hbWUpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDIsIGFscGhhID0gMC44KSArCiAgZ2VvbV9wb2ludChzaXplID0gNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB0ZWFtX2NvbG9ycykgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCksIGJyZWFrcyA9IHNlcSgwLCAxMDAsIDEwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJXLU9URCAoT09SKSBQZXJmb3JtYW5jZSBBbmFseXNpcyIsCiAgICBzdWJ0aXRsZSA9ICJPcGVuIE9yZGVyIFJlcG9ydCAvIE9uLVRpbWUgRGVsaXZlcnkgcGVyY2VudGFnZSIsCiAgICB4ID0gIldlZWsgTnVtYmVyIiwKICAgIHkgPSAiVy1PVEQgKE9PUikgUmF0ZSAoJSkiLAogICAgY29sb3IgPSAiVGVhbSBNZW1iZXIiLAogICAgY2FwdGlvbiA9ICJIaWdoZXIgcGVyY2VudGFnZXMgaW5kaWNhdGUgYmV0dGVyIG9yZGVyIG1hbmFnZW1lbnQiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJncmF5NjAiKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQoKcHJpbnQoZ3JhcGhfd290ZF9wY3QpCmBgYAoKKipXLU9URCAoT09SKSBQZXJmb3JtYW5jZToqKiBUaGlzIGdyYXBoIHRyYWNrcyBvcGVuIG9yZGVyIHJlcG9ydHMgYW5kIG9uLXRpbWUgZGVsaXZlcnkgcGVyZm9ybWFuY2UsIHdoZXJlIGhpZ2hlciBwZXJjZW50YWdlcyBpbmRpY2F0ZSBiZXR0ZXIgb3JkZXIgbWFuYWdlbWVudCBhbmQgZGVsaXZlcnkgc3VjY2Vzcy4gCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6R3JlZW47Jz4gR1JBUEggNjogQWNrbm93bGVkZ2VtZW50cyBRdWFudGl0eSBBbmFseXNpcyA8L3NwYW4+CmBgYHtyfQpncmFwaF9hY2tfcXR5IDwtIGdncGxvdChiZF9xdWFudGl0aWVzLCBhZXMoeCA9IFdlZWssIHkgPSBgQWNrbm93bGVkZ2VtZW50c19RVFlgLCBmaWxsID0gTmFtZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIsIGFscGhhID0gMC44LCB3aWR0aCA9IDAuNykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRlYW1fY29sb3JzKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hX2Zvcm1hdCgpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkFja25vd2xlZGdlbWVudHMgVm9sdW1lIEFuYWx5c2lzIGJ5IFRlYW0gTWVtYmVyIiwKICAgIHN1YnRpdGxlID0gIldlZWtseSBxdWFudGl0eSBvZiBhY2tub3dsZWRnZW1lbnRzIHByb2Nlc3NlZCIsCiAgICB4ID0gIldlZWsgTnVtYmVyIiwKICAgIHkgPSAiTnVtYmVyIG9mIEFja25vd2xlZGdlbWVudHMiLAogICAgZmlsbCA9ICJUZWFtIE1lbWJlciIsCiAgICBjYXB0aW9uID0gIlNob3dzIGFjdHVhbCB3b3JrbG9hZCBhbmQgcHJvY2Vzc2luZyB2b2x1bWUiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJncmF5NjAiKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQoKcHJpbnQoZ3JhcGhfYWNrX3F0eSkKYGBgCgoqKkdyYXBocyA2LTEwIC0gVm9sdW1lIEFuYWx5c2lzOioqIFRoZXNlIGJhciBjaGFydHMgc2hvdyBhY3R1YWwgd29ya2xvYWQgdm9sdW1lcyBmb3IgZWFjaCB0ZWFtIG1lbWJlciwgaGVscGluZyB1bmRlcnN0YW5kIHRoZSBzY2FsZSBvZiBvcGVyYXRpb25zIGFuZCB3b3JrbG9hZCBkaXN0cmlidXRpb24KCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6R3JlZW47Jz4gR1JBUEggNzogTGF0ZSBBY2tub3dsZWRnZW1lbnRzIFF1YW50aXR5IEFuYWx5c2lzIDwvc3Bhbj4KYGBge3J9CmdyYXBoX2xhdGVfcXR5IDwtIGdncGxvdChiZF9xdWFudGl0aWVzLCBhZXMoeCA9IFdlZWssIHkgPSBgTGF0ZSBBY2sgPjNkYXlzX1FUWWAsIGZpbGwgPSBOYW1lKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIiwgYWxwaGEgPSAwLjgsIHdpZHRoID0gMC43KSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdGVhbV9jb2xvcnMpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWFfZm9ybWF0KCkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTGF0ZSBBY2tub3dsZWRnZW1lbnRzIFZvbHVtZSBBbmFseXNpcyAoPjMgZGF5cykiLAogICAgc3VidGl0bGUgPSAiTnVtYmVyIG9mIGFja25vd2xlZGdlbWVudHMgZGVsYXllZCBieSBtb3JlIHRoYW4gMyBkYXlzIiwKICAgIHggPSAiV2VlayBOdW1iZXIiLAogICAgeSA9ICJOdW1iZXIgb2YgTGF0ZSBBY2tub3dsZWRnZW1lbnRzIiwKICAgIGZpbGwgPSAiVGVhbSBNZW1iZXIiLAogICAgY2FwdGlvbiA9ICJTaG93cyBhY3R1YWwgdm9sdW1lIG9mIGRlbGF5ZWQgYWNrbm93bGVkZ2VtZW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImdyYXk2MCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApCgpwcmludChncmFwaF9sYXRlX3F0eSkKYGBgCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6R3JlZW47Jz4gR1JBUEggODogVGltZSB0byBTaGlwIFF1YW50aXR5IEFuYWx5c2lzIDwvc3Bhbj4KCmBgYHtyfQpncmFwaF90dHNfcXR5IDwtIGdncGxvdChiZF9xdWFudGl0aWVzLCBhZXMoeCA9IFdlZWssIHkgPSBgVFRTIDwgMTAgZGF5c19RVFlgLCBmaWxsID0gTmFtZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIsIGFscGhhID0gMC44LCB3aWR0aCA9IDAuNykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRlYW1fY29sb3JzKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hX2Zvcm1hdCgpKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRpbWUgdG8gU2hpcCBWb2x1bWUgQW5hbHlzaXMgKDwxMCBkYXlzKSIsCiAgICBzdWJ0aXRsZSA9ICJOdW1iZXIgb2Ygb3JkZXJzIHNoaXBwZWQgd2l0aGluIDEwIGRheXMiLAogICAgeCA9ICJXZWVrIE51bWJlciIsCiAgICB5ID0gIk51bWJlciBvZiBPcmRlcnMgU2hpcHBlZCA8MTAgZGF5cyIsCiAgICBmaWxsID0gIlRlYW0gTWVtYmVyIiwKICAgIGNhcHRpb24gPSAiU2hvd3MgYWN0dWFsIHZvbHVtZSBvZiBmYXN0IHNoaXBtZW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImdyYXk2MCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApCgpwcmludChncmFwaF90dHNfcXR5KQoKYGBgCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6R3JlZW47Jz4gR1JBUEggOTogSW52b2ljZSBQYXN0IER1ZSBRdWFudGl0eSBBbmFseXNpcyA8L3NwYW4+CmBgYHtyfQpncmFwaF9pbnZvaWNlX3F0eSA8LSBnZ3Bsb3QoYmRfcXVhbnRpdGllcywgYWVzKHggPSBXZWVrLCB5ID0gYEludm9pY2UgcGFzdCBkdWVfUVRZYCwgZmlsbCA9IE5hbWUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBhbHBoYSA9IDAuOCwgd2lkdGggPSAwLjcpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB0ZWFtX2NvbG9ycykgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYV9mb3JtYXQoKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJJbnZvaWNlIFBhc3QgRHVlIFZvbHVtZSBBbmFseXNpcyIsCiAgICBzdWJ0aXRsZSA9ICJOdW1iZXIgb2YgaW52b2ljZXMgdGhhdCBhcmUgcGFzdCBkdWUiLAogICAgeCA9ICJXZWVrIE51bWJlciIsCiAgICB5ID0gIk51bWJlciBvZiBQYXN0IER1ZSBJbnZvaWNlcyIsCiAgICBmaWxsID0gIlRlYW0gTWVtYmVyIiwKICAgIGNhcHRpb24gPSAiU2hvd3MgYWN0dWFsIHZvbHVtZSBvZiBvdmVyZHVlIGludm9pY2VzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiZ3JheTYwIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKcHJpbnQoZ3JhcGhfaW52b2ljZV9xdHkpCgpgYGAKCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpHcmVlbjsnPiBHUkFQSCAxMDogVy1PVEQgKE9PUikgVm9sdW1lIEFuYWx5c2lzIDwvc3Bhbj4KCmBgYHtyfQpncmFwaF93b3RkX3F0eSA8LSBnZ3Bsb3QoYmRfcXVhbnRpdGllcywgYWVzKHggPSBXZWVrLCB5ID0gYFctT1REIChPT1IpX051bWVyYXRvcmAsIGZpbGwgPSBOYW1lKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIiwgYWxwaGEgPSAwLjgsIHdpZHRoID0gMC43KSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdGVhbV9jb2xvcnMpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWFfZm9ybWF0KCkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVy1PVEQgKE9PUikgT3BlbiBPcmRlcnMgVm9sdW1lIEFuYWx5c2lzIiwKICAgIHN1YnRpdGxlID0gIk51bWJlciBvZiBvcGVuIG9yZGVycyByZXBvcnRlZCBieSB0ZWFtIG1lbWJlciIsCiAgICB4ID0gIldlZWsgTnVtYmVyIiwKICAgIHkgPSAiTnVtYmVyIG9mIE9wZW4gT3JkZXJzIiwKICAgIGZpbGwgPSAiVGVhbSBNZW1iZXIiLAogICAgY2FwdGlvbiA9ICJTaG93cyBhY3R1YWwgdm9sdW1lIG9mIG9wZW4gb3JkZXJzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiZ3JheTYwIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKcHJpbnQoZ3JhcGhfd290ZF9xdHkpCmBgYAo=