Practicum Advance
Functions & Loops

Profil Mahasiswa - Anindya Kristianingputri
Foto Profil Anindya Kristianingputri

Anindya Kristianingputri

NIM: 52250025
Lecture
Bakti Siregar, M.Sc., CDS
Bandung Institute of Technology and Sciences
Student Major Data Science
R Programming
Data Science Programming 1
Function and Loops

1 Dynamic Multi Formula Function

Dynamic Multi-Formula Function

A dynamic multi-formula function like compute_formula(x, formula) enables a single routine to evaluate different mathematical expressions by selecting the appropriate formula type. It supports linear (y = 5x + 10), quadratic (y = 0.3x²), cubic (y = 0.02x³), and exponential (y = 1.2ˣ) formulas. When invoked, the function checks the given formula identifier — for linear it returns 5x + 10, for quadratic it computes 0.3x², for cubic 0.02x³, and for exponential 1.2 raised to the power x. This approach keeps the code flexible, reusable, and clean; you only change the formula parameter without rewriting logic, making it ideal for simulations, data modeling, and educational tools.

1.1 Nested loops to compute multiple formulas at once

library(DT)

compute_formula <- function(x, formulas) {
  results <- list()
  
  valid_formulas <- c("linear","quadratic","cubic","exponential")
  
  # Outer loop → formula type
  for (f in formulas) {
    
    # VALIDASI INPUT
    if (!(f %in% valid_formulas)) {
      warning(paste("Formula", f, "is not valid and will be skipped"))
      next
    }
    
    y_values <- numeric(length(x))
    
    # Inner loop → x values
    for (i in seq_along(x)) {
      
      if (f == "linear") {
        y_values[i] <- 5*x[i] + 10
        
      } else if (f == "quadratic") {
        y_values[i] <- 0.3*(x[i]^2)
        
      } else if (f == "cubic") {
        y_values[i] <- 0.02*(x[i]^3)
        
      } else if (f == "exponential") {
        y_values[i] <- 1.2^x[i]
      }
    }
    
    results[[f]] <- y_values
  }
  
  return(results)
}

# Data x
x <- 1:20

# Jalankan function
hasil <- compute_formula(x, c("linear","quadratic","cubic","exponential"))

# Combine into one large table 
all_data <- data.frame()

for (name in names(hasil)) {
  temp <- data.frame(
    x = x,
    y = hasil[[name]],
    formula = name
  )
  
  all_data <- rbind(all_data, temp)
}

# Display interactive table
datatable(
  all_data,
  options = list(
    pageLength = 10,
    autoWidth = TRUE
  ),
  caption = "Table of Calculation Results for All Formulas"
)

Interpretation

The nested loop successfully generates 80 data points by computing four formulas (linear, quadratic, cubic, and exponential) for values of (x) from 1 to 20. The results show clear differences in growth patterns: the linear function increases steadily, the quadratic and cubic functions grow at an accelerating rate, and the exponential function increases the fastest as (x) becomes larger. By organizing all results into a single dataset, the program allows easy comparison between formulas and demonstrates how nested loops can efficiently handle repetitive calculations and produce structured outputs.

1.2 Validate Formula Input

Input Validation - Highlight Kode

Input validation has already been implemented in the program, where the function checks whether each formula type is valid by comparing it with a predefined list of allowed formulas (linear, quadratic, cubic, and exponential); if an invalid input is detected, the program generates a warning message using warning() and skips the incorrect formula with next, allowing the function to continue processing only valid inputs, as indicated by the conditional check if (!(f %in% valid_formulas)).

1.3 Plot all formulas on same graph for x = 1:20

library(ggplot2)
library(plotly)

# Plot ggplot (dark mode)
p <- ggplot(all_data, aes(x = x, y = y, color = formula)) +
  geom_line(size = 1.3) +
  geom_point(size = 2) +
  scale_color_manual(values = c(
    "linear" = "#00F5FF",      # cyan neon
    "quadratic" = "#39FF14",   # neon green
    "cubic" = "#FF6EC7",       # neon pink
    "exponential" = "#FFD700"  # neon yellow
  )) +
  labs(
    title = "Comparison of Mathematical Formulas",
    x = "Value of x",
    y = "Result (y)",
    color = "Formula Type"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.background = element_rect(fill = "#0D0D0D", color = NA),
    panel.background = element_rect(fill = "#0D0D0D", color = NA),
    panel.grid.major = element_line(color = "#2A2A2A"),
    panel.grid.minor = element_line(color = "#1A1A1A"),
    text = element_text(color = "white"),
    axis.text = element_text(color = "#CCCCCC"),
    legend.background = element_rect(fill = "#0D0D0D"),
    legend.key = element_rect(fill = "#0D0D0D"),
    plot.title = element_text(face = "bold", size = 16)
  )

# Interaktif
ggplotly(p)

Interpretation

The visualization compares linear, quadratic, cubic, and exponential functions over the range ( x = 1 ) to ( 20 ), highlighting distinct growth patterns. The linear function demonstrates a constant and stable rate of increase, while the quadratic and cubic functions exhibit progressively accelerating growth, with the cubic function increasing more rapidly at higher values of ( x ). In contrast, the exponential function shows the most significant and rapid growth, especially as ( x ) becomes large. Overall, the results indicate that as the complexity of the function increases, the rate of change becomes more pronounced, with exponential growth dominating and producing substantially larger outputs compared to the other functions.

2 Nested Simulation: Multi-Sales & Discounts

Simulate Sales Function - Formal Explanation

In this segment, we discuss the simulate_sales(n_salesperson, days) function, which generates four columns: sales_id, day, sales_amount, and discount_rate. This function contains a nested function responsible for calculating cumulative sales per salesperson. Subsequently, the function applies conditional discounts, where the discount rate is determined based on the value of sales_amount. The process is executed by iterating through each salesperson using a loop. Finally, the function also provides summary statistics and a cumulative sales plot to facilitate the analysis of sales trends over time.

2.1 Nested function to calculate cumulative sales per salesperson

Nested Function - Cumulative Sales

A nested function is used to calculate cumulative sales per salesperson because it allows the cumulative sum logic to be encapsulated inside the main function, keeping the code organized and reusable. By applying this nested function to each salesperson individually through a loop, the program can track the running total of sales day by day for every salesperson separately, without mixing values between different salespersons. This approach is useful for identifying performance trends, monitoring progress toward sales targets, and comparing which salespersons are consistently growing their sales over time. Additionally, the nested structure makes the code easier to debug and maintain, as the cumulative calculation logic is isolated from the main data processing workflow.

2.2 Apply conditional discounts based on sales amount

Discount Mechanism
Discount Mechanism Description:

This design reflects a stepwise incentive system in which higher sales values correspond to higher discount rates, maintaining a consistent and scalable progression. Such an approach demonstrates the application of conditional logic to implement a structured pricing strategy that rewards increased sales performance.

Discount Tier Structure

Sales Amount (Units/Value) Discount Rate Incentive Type
≤ 250 12% Basic Incentive
250 & ≤ 500 24% Mid-Level Reward
500 36% High Performer Bonus

2.3 Loop per salesperson

# Load library
library(DT)

# Function to simulate sales data (decimal values)
simulate_sales <- function(n_salesperson, days) {
  
  set.seed(123)
  
  data_list <- list()
  counter <- 1
  
  # Loop per salesperson
  for (sp in 1:n_salesperson) {
    
    # Loop per day
    for (d in 1:days) {
      
      # Generate decimal sales amount (100 - 800)
      sales_amount <- round(runif(1, min = 100, max = 800), 2)
      
      data_list[[counter]] <- data.frame(
        sales_id = paste0("SP_", sp),
        day = d,
        sales_amount = sales_amount
      )
      
      counter <- counter + 1
    }
  }
  
  # Combine all data
  sales_data <- do.call(rbind, data_list)
  
  return(sales_data)
}

# Generate data (15 salesperson, 7 days)
sales_data <- simulate_sales(8, 7)

# Show interactive table
datatable(sales_data)

2.3.1 Apply conditional discounts

# Load library
library(DT)

# Function to simulate sales data (with discount)
simulate_sales <- function(n_salesperson, days) {
  
  set.seed(123)
  
  data_list <- list()
  counter <- 1
  
  # Loop per salesperson
  for (sp in 1:n_salesperson) {
    
    # Loop per day
    for (d in 1:days) {
      
      # Generate decimal sales amount (100 - 800)
      sales_amount <- round(runif(1, min = 100, max = 800), 2)
      
      # Apply discount rules
      if (sales_amount <= 250) {
        discount_rate <- 0.12
      } else if (sales_amount <= 500) {
        discount_rate <- 0.24
      } else {
        discount_rate <- 0.36
      }
      
      # Convert to percentage format
      discount_label <- paste0(discount_rate * 100, "%")
      
      data_list[[counter]] <- data.frame(
        sales_id = paste0("SP_", sp),
        day = d,
        sales_amount = sales_amount,
        discount_rate = discount_label
      )
      
      counter <- counter + 1
    }
  }
  
  # Combine all data
  sales_data <- do.call(rbind, data_list)
  
  return(sales_data)
}

# Generate data
sales_data <- simulate_sales(8, 7)

# Show interactive table
datatable(sales_data)

2.4 Summary stats and cumulative sales plot

2.4.1 Summary stats

Summary Statistics
Summary statistics are numerical measures used to summarize and describe the main characteristics of a dataset, allowing us to understand the data without examining each observation individually. Common summary statistics include the mean (average value), median (middle value), minimum and maximum (smallest and largest values), standard deviation (which indicates how spread out the data is), and quartiles (which divide the data into four equal parts). In R, these statistics can be calculated easily using functions such as summary(data$variable) for a quick overview, or more specific functions like mean(), median(), sd(), min(), and max() for detailed analysis. Overall, summary statistics are useful for identifying patterns, understanding data distribution, detecting outliers, and comparing different groups, such as evaluating the performance of multiple salespersons.

2.4.1.1 Example

library(DT)

sales_data %>%
  group_by(sales_id) %>%
  summarise(
    mean = mean(sales_amount),
    median = median(sales_amount),
    min = min(sales_amount),
    max = max(sales_amount),
    sd = sd(sales_amount)
  )

2.4.2 Cumulative Sales Plot

Cumulative Sales Plot
A cumulative sales plot is a graphical representation that shows the running total of sales over time, allowing us to observe how sales accumulate day by day. It is calculated by summing sales amounts sequentially using a cumulative sum function, such as cumsum() in R, which adds each new value to the total of all previous values. To create this plot, the data is typically grouped (e.g., by salesperson), sorted by time (e.g., day), and then transformed into cumulative values before being visualized using a line chart. The main purpose of a cumulative sales plot is to identify trends in overall performance, compare growth between different salespersons, and detect periods of rapid or slow sales accumulation. This type of visualization is especially useful for tracking progress toward targets and understanding long-term sales behavior rather than focusing on daily fluctuations.

2.4.2.1 Example

library(dplyr)
library(plotly)

# count cumulative sales
sales_cum <- sales_data %>%
  arrange(sales_id, day) %>%
  group_by(sales_id) %>%
  mutate(cum_sales = cumsum(sales_amount)) %>%
  ungroup()

# color
neon_colors <- c(
  "#00FFFF", "#FF00FF", "#39FF14", "#FF073A",
  "#FFD300", "#FF6EC7", "#00FFEF", "#B026FF"
)

# Plot interaktif
fig <- plot_ly(
  data = sales_cum,
  x = ~day,
  y = ~cum_sales,
  color = ~sales_id,
  colors = neon_colors,
  type = "scatter",
  mode = "lines+markers",
  text = ~paste(
    "Sales:", sales_id,
    "<br>Day:", day,
    "<br>Cumulative:", round(cum_sales, 2)
  ),
  hoverinfo = "text"
) %>%
  layout(
    title = list(
      text = "Cumulative Sales per Salesperson",
      font = list(color = "#FFFFFF")
    ),
    paper_bgcolor = "#000000",
    plot_bgcolor = "#000000",
    font = list(color = "#FFFFFF"),
    xaxis = list(
      title = "Day",
      color = "#FFFFFF",
      gridcolor = "#333333"
    ),
    yaxis = list(
      title = "Cumulative Sales",
      color = "#FFFFFF",
      gridcolor = "#333333"
    ),
    legend = list(font = list(color = "#FFFFFF"))
  )

fig

Interpretation

From the visualization, salespersons whose lines consistently remain above others can be identified as top performers, as they achieve higher total sales throughout the period, while those with lower cumulative curves indicate relatively weaker performance. Additionally, fluctuations in the steepness of the lines reveal variations in daily sales contributions—sharp increases suggest high sales on particular days, whereas smoother, gradual increases indicate stable but moderate performance. Overall, this plot is useful for comparing sales performance across individuals, identifying consistent high performers, and detecting patterns such as rapid growth phases or stagnation periods. It provides a clearer picture of long-term performance trends compared to daily sales data, making it valuable for performance evaluation and decision-making.

3 Multi-Level Performance Categorization

Multi-Level Performance Categorization
Chapter: Multi-Level Performance Categorization discusses the function categorize_performance(sales_amount) with 5 categories: Excellent, Very Good, Good, Average, and Poor. The discussion covers looping through a vector to classify each sales value, calculating percentages per category, and visualizing the distribution using a bar plot and a pie chart.

3.1 Loop Through Vector

Loop Through Vector - Explanation
“Loop through vector” means iterating over each element in a vector one by one using a loop (such as a for loop) and applying a specific operation to each value. In this task, it requires taking each sales_amount value, evaluating it using conditional logic (e.g., if-else) to assign it into a performance category like Excellent, Very Good, Good, Average, or Poor, and storing the results in a new vector.

3.1.1 Category

Performance Categories
Category Range Description
Excellent ≥ 700 Outstanding performance, far above target
Very Good 500 – 699 Very good, above expectations
Good 300 – 499 Good, meeting standard target
Average 200 – 299 Sufficient, within reasonable limits
Poor < 200 Below target, needs serious evaluation

3.2 Calculate Precentage per Category

library(dplyr)
library(DT)

# Function kategorisasi
categorize_performance <- function(sales_amount) {
  
  categories <- c()
  
  for (i in sales_amount) {
    
    if (i >= 700) {
      categories <- c(categories, "Excellent")
      
    } else if (i >= 500) {
      categories <- c(categories, "Very Good")
      
    } else if (i >= 300) {
      categories <- c(categories, "Good")
      
    } else if (i >= 200) {
      categories <- c(categories, "Average")
      
    } else {
      categories <- c(categories, "Poor")
    }
  }
  
  return(categories)
}

# Terapkan ke data (WAJIB dulu)
sales_data$performance_category <- categorize_performance(sales_data$sales_amount)

# Baru ubah jadi factor biar urut
sales_data$performance_category <- factor(
  sales_data$performance_category,
  levels = c("Excellent", "Very Good", "Good", "Average", "Poor")
)

# Summary tabel (pakai .drop = FALSE biar semua kategori muncul)
summary_table <- sales_data %>%
  count(performance_category, .drop = FALSE) %>%
  mutate(percentage = round(n / sum(n) * 100, 2))

# Tampilkan tabel interaktif
datatable(
  summary_table,
  options = list(
    pageLength = 5,
    dom = 'Bfrtip',
    buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
  ),
  rownames = FALSE,
  caption = "Sales Performance Distribution"
)

3.3 Bar plot and pie chart of distribution

3.3.1 Bar plot

library(ggplot2)
library(plotly)

# Base ggplot
p <- ggplot(summary_table, aes(x = performance_category, y = n, fill = performance_category)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c(
    "Excellent" = "#39FF14",
    "Very Good" = "#00FFFF",
    "Good" = "#FFD300",
    "Average" = "#FF6EC7",
    "Poor" = "#FF073A"
  )) +
  labs(
    title = "Sales Performance Distribution",
    x = "Performance Category",
    y = "Count"
  ) +
  theme_minimal() +
  theme(
    plot.background = element_rect(fill = "black", color = NA),
    panel.background = element_rect(fill = "black"),
    text = element_text(color = "white"),
    axis.text = element_text(color = "white"),
    legend.text = element_text(color = "white"),
    legend.title = element_blank()
  )

# Convert to interactive plot
ggplotly(p)

Interpretation

From the chart, it can be seen that the Good category has the tallest bar, meaning most of the salespeople are performing well, followed by Excellent in the second highest position, indicating quite a few salespeople have achieved outstanding performance. Meanwhile, the Very Good and Average categories have bars of medium height, suggesting that the remaining salespeople are spread across very good and average levels. The Poor category appears to be the shortest, so only a few salespeople have low performance and it is not too concerning. Overall, the sales team’s performance distribution tends to skew to the right (from Good to Excellent), which means the team has healthy and positive performance, although salespeople in the Average category need to be encouraged to move up to Good or Very Good.

3.3.2 Pie Chart

library(plotly)

# Pie chart interaktif
plot_ly(
  data = summary_table,
  labels = ~performance_category,
  values = ~n,
  type = "pie",
  marker = list(colors = c(
    "#39FF14",  # Excellent
    "#00FFFF",  # Very Good
    "#FFD300",  # Good
    "#FF6EC7",  # Average
    "#FF073A"   # Poor
  ))
) %>%
  layout(
    title = list(
      text = "Sales Performance Proportion",
      font = list(color = "#FFFFFF")
    ),
    paper_bgcolor = "#000000",
    plot_bgcolor = "#000000",
    font = list(color = "#FFFFFF")
  )

Interpretation

The pie chart illustrates the proportion of each sales performance category relative to the total dataset. Each slice represents a category, and its size reflects its percentage contribution. Larger slices indicate more dominant performance categories, while smaller slices show less frequent occurrences. This visualization helps to quickly understand the overall composition of sales performance and identify which categories contribute the most to total sales.

4 Multi Company Data Set Simulation

Multi-Company Simulation - Formal Explanation

In this segment, we discuss the generate_company_data(n_company, n_employees) function, which generates a dataset containing the following columns: company_id, employee_id, salary, department, performance_score, and KPI_score. This function uses nested loops — an outer loop iterates over each company, and an inner loop iterates over each employee within that company. Subsequently, the function applies conditional logic to identify top performers based on the rule KPI_score > 90. After generating the data, the function calculates a summary per company including average salary, average performance score, and maximum KPI score. Finally, the function also provides a summary table and plots (such as bar charts or boxplots) to visualize the distribution and comparison across companies.

4.1 Company Data

library(DT)

set.seed(123)

generate_hotel_data <- function(n_company = 3, n_employees = 20) {
  
  data_list <- list()
  counter <- 1
  
  departments <- c(
    "Front Office", "Housekeeping", "Food & Beverage",
    "Kitchen", "Maintenance", "HR", "Finance"
  )
  
  for (c in 1:n_company) {
    
    for (e in 1:n_employees) {
      
      salary <- round(runif(1, 3000, 10000), 0)
      performance_score <- round(runif(1, 60, 100), 1)
      KPI_score <- round(runif(1, 65, 100), 1)
      
      # Conditional logic 
      if (KPI_score > 90) {
        top_status <- "Top Performer"
      } else {
        top_status <- "Regular"
      }
      
      data_list[[counter]] <- data.frame(
        company_id = paste0("Hotel_", c),
        employee_id = paste0("H", c, "_E", sprintf("%02d", e)),
        salary = salary,
        department = sample(departments, 1),
        performance_score = performance_score,
        KPI_score = KPI_score,
        top_performer = top_status   # kolom baru
      )
      
      counter <- counter + 1
    }
  }
  
  hotel_data <- do.call(rbind, data_list)
  return(hotel_data)
}

hotel_data <- generate_hotel_data(3, 20)

# tampilkan
datatable(hotel_data)

4.2 Summary per company

library(dplyr)
library(DT)

# Summary per company
company_summary <- hotel_data %>%
  group_by(company_id) %>%
  summarise(
    avg_salary = round(mean(salary), 2),
    avg_performance = round(mean(performance_score), 2),
    max_KPI = max(KPI_score),
    total_employee = n(),
    top_performers = sum(top_performer == "Top Performer")
  )

# Tampilkan dalam DT
datatable(
  company_summary,
  options = list(
    pageLength = 5,
    dom = 'Bfrtip',
    buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
  ),
  rownames = FALSE,
  caption = "Company Performance Summary"
)

4.3 Visualization

library(plotly)

plot_ly(
  data = company_summary,
  x = ~company_id,
  y = ~avg_performance,
  type = "bar",
  marker = list(color = c("#00FFFF", "#FF00FF", "#39FF14")),
  name = ~company_id
) %>%
  layout(
    title = "Average Performance Score by Company",
    xaxis = list(title = "Company", color = "white"),
    yaxis = list(title = "Average Performance Score", color = "white"),
    plot_bgcolor = "black",
    paper_bgcolor = "black",
    font = list(color = "white")
  )

Interpretation

The bar chart compares the average performance scores across the three companies. Each bar represents a company, and its height indicates the overall performance level of its employees. The company with the highest bar demonstrates the strongest average performance, suggesting better employee productivity and effectiveness. Differences in bar heights highlight variations in workforce quality among the companies, making it easier to identify which company performs best overall. This visualization provides a clear and straightforward comparison, supporting performance evaluation and strategic decision-making.

5 Monte Carlo Simulation: Pi & Probability

Monte Carlo Simulation - Pi & Probability

In this segment, we discuss the monte_carlo_pi(n_points) function, which performs a Monte Carlo simulation to estimate the value of π (pi) along with additional probability analysis. The function uses a loop that runs for a specified number of iterations (n_points). Within each iteration, random points are generated within a square bounding a unit circle. The function then counts how many points fall inside the circle and uses the ratio of points inside the circle to total points to compute an approximation of π. Additionally, the function performs probability analysis by calculating the probability of random points falling inside a specific sub-square region. Finally, the function produces a plot that visualizes the generated points, distinguishing between points that fall inside the circle and those outside, providing an intuitive understanding of the Monte Carlo method.

5.1 Loop for iteration

Loop Iteration - Monte Carlo Explanation
In this segment, the loop iteration plays a key role as the main mechanism to repeat the random point generation process as many as n_points times. Without a loop, we can only generate one point, which is certainly not enough for accurate statistical estimation. The more iterations (the larger n_points), the more accurate the estimated value of π becomes, following the Law of Large Numbers.

5.2 Implementation

# Load DT library
library(DT)

# Monte Carlo simulation to estimate pi
set.seed(123) # for reproducibility

n_points <- 2750
inside_count <- 0

for (i in 1:n_points) {
  x <- runif(1, -1, 1)
  y <- runif(1, -1, 1)
  if (x^2 + y^2 <= 1) {
    inside_count <- inside_count + 1
  }
}

pi_estimate <- 4 * inside_count / n_points

# Create a summary data frame
results_df <- data.frame(
  Metric = c("Total points (n_points)", 
             "Points inside circle", 
             "Estimated π", 
             "Actual π", 
             "Error"),
  Value = c(n_points, 
            inside_count, 
            round(pi_estimate, 6), 
            pi, 
            abs(round(pi_estimate - pi, 6)))
)

# Display as interactive table
datatable(results_df, 
          options = list(dom = 't', 
                         pageLength = 5),
          rownames = FALSE,
          caption = "Monte Carlo Simulation Results for π Estimation")

5.3 Compute probability of random points falling in sub-square

library(DT)

# PROBABILITY OF RANDOM POINTS IN SUB-SQUARE


# Parameter
n_points <- 2750

# Sub-square boundaries (0.5 to 1)
x_min <- 0.5
x_max <- 1
y_min <- 0.5
y_max <- 1

# Initialize counter
sub_square_count <- 0

# Loop through iterations
for (i in 1:n_points) {
  
  # Generate random point (x, y) between -1 and 1
  x <- runif(1, -1, 1)
  y <- runif(1, -1, 1)
  
  # Check if point is inside the sub-square
  if (x >= x_min && x <= x_max && y >= y_min && y <= y_max) {
    sub_square_count <- sub_square_count + 1
  }
}

# Calculate probability
probability <- sub_square_count / n_points
percentage <- probability * 100

# Create result table
result <- data.frame(
  Statistic = c("Total Points", "Points Inside Sub-square", "Probability", "Percentage"),
  Value = c(
    format(n_points, big.mark = ","), 
    format(sub_square_count, big.mark = ","), 
    paste0(round(probability, 6)),
    paste0(round(percentage, 4), "%")
  )
)

# Display interactive table
datatable(
  result,
  options = list(
    dom = 't',
    paging = FALSE,
    ordering = FALSE
  ),
  rownames = FALSE,
  caption = htmltools::tags$caption(
    style = "caption-side: top; text-align: center; font-size: 16px; font-weight: bold;",
    "Probability of Random Points in Sub-Square (0.5 to 1)"
  )
)

5.4 Plot points inside vs outside circle

# PLOT POINTS INSIDE VS OUTSIDE CIRCLE

library(plotly)

# Parameter
n_points <- 2750

# Initialize vectors to store coordinates
x_coords <- numeric(n_points)
y_coords <- numeric(n_points)
inside_flag <- logical(n_points)

# Loop to generate random points
for (i in 1:n_points) {
  x_coords[i] <- runif(1, -1, 1)
  y_coords[i] <- runif(1, -1, 1)
  
  # Check if point is inside the circle
  if (x_coords[i]^2 + y_coords[i]^2 <= 1) {
    inside_flag[i] <- TRUE
  } else {
    inside_flag[i] <- FALSE
  }
}

# Calculate pi estimation
inside_count <- sum(inside_flag)
pi_estimate <- 4 * inside_count / n_points

# Create data frame
df <- data.frame(
  x = x_coords,
  y = y_coords,
  status = ifelse(inside_flag, "Inside Circle", "Outside Circle")
)

# Create circle boundary points
theta <- seq(0, 2 * pi, length.out = 500)
circle <- data.frame(x = cos(theta), y = sin(theta))

# Create square boundary
square <- data.frame(
  x = c(-1, 1, 1, -1, -1),
  y = c(-1, -1, 1, 1, -1)
)

# GLOW IN THE DARK PLOT with Plotly
plot_ly() %>%
  
  # Points inside circle (neon red)
  add_trace(
    data = df[df$status == "Inside Circle", ],
    x = ~x, y = ~y,
    type = "scatter",
    mode = "markers",
    marker = list(
      size = 5,
      color = "#ff2a2a",
      opacity = 0.8,
      line = list(color = "#ff0000", width = 1)
    ),
    name = "Inside Circle",
    hoverinfo = "text",
    text = ~paste("Inside Circle\nx:", round(x, 4), "\ny:", round(y, 4))
  ) %>%
  
  # Points outside circle (neon blue)
  add_trace(
    data = df[df$status == "Outside Circle", ],
    x = ~x, y = ~y,
    type = "scatter",
    mode = "markers",
    marker = list(
      size = 3,
      color = "#00bfff",
      opacity = 0.5,
      line = list(color = "#0088ff", width = 0.5)
    ),
    name = "Outside Circle",
    hoverinfo = "text",
    text = ~paste("Outside Circle\nx:", round(x, 4), "\ny:", round(y, 4))
  ) %>%
  
  # Circle boundary (neon green glow)
  add_trace(
    data = circle,
    x = ~x, y = ~y,
    type = "scatter",
    mode = "lines",
    line = list(
      color = "#39ff14",
      width = 3,
      dash = "solid"
    ),
    name = "Circle Boundary (x² + y² = 1)",
    hoverinfo = "none"
  ) %>%
  
  # Square boundary (neon purple)
  add_trace(
    data = square,
    x = ~x, y = ~y,
    type = "scatter",
    mode = "lines",
    line = list(
      color = "#bf00ff",
      width = 2,
      dash = "dash"
    ),
    name = "Square Boundary (-1 to 1)",
    hoverinfo = "none"
  ) %>%
  
  # Layout with dark theme (glow in the dark)
  layout(
    title = list(
      text = paste("MONTE CARLO PI ESTIMATION\nn =", n_points, "| Estimated Pi =", round(pi_estimate, 6), "| Actual Pi =", round(pi, 6)),
      font = list(color = "#ffffff", size = 16, family = "Arial"),
      x = 0.5,
      xanchor = "center"
    ),
    paper_bgcolor = "#0a0a0a",
    plot_bgcolor = "#050505",
    xaxis = list(
      title = list(text = "X AXIS", font = list(color = "#ffffff")),
      range = c(-1.15, 1.15),
      gridcolor = "#1a1a1a",
      zerolinecolor = "#333333",
      tickfont = list(color = "#cccccc"),
      showgrid = TRUE,
      gridwidth = 0.5
    ),
    yaxis = list(
      title = list(text = "Y AXIS", font = list(color = "#ffffff")),
      range = c(-1.15, 1.15),
      gridcolor = "#1a1a1a",
      zerolinecolor = "#333333",
      tickfont = list(color = "#cccccc"),
      showgrid = TRUE,
      gridwidth = 0.5,
      scaleanchor = "x",
      scaleratio = 1
    ),
    legend = list(
      title = list(text = "LEGEND", font = list(color = "#ffffff")),
      font = list(color = "#ffffff"),
      bgcolor = "rgba(0,0,0,0.7)",
      bordercolor = "#39ff14",
      borderwidth = 1,
      x = 0.02,
      y = 0.98
    ),
    hovermode = "closest",
    annotations = list(
      list(
        text = paste("INSIDE:", inside_count, "| OUTSIDE:", n_points - inside_count),
        x = 0.5,
        y = -0.08,
        xref = "paper",
        yref = "paper",
        showarrow = FALSE,
        font = list(color = "#39ff14", size = 11, family = "monospace"),
        bgcolor = "rgba(0,0,0,0.6)",
        borderpad = 4
      ),
      list(
        text = "GLOW IN THE DARK MODE",
        x = 0.5,
        y = 1.05,
        xref = "paper",
        yref = "paper",
        showarrow = FALSE,
        font = list(color = "#bf00ff", size = 9, family = "monospace")
      )
    )
  ) %>%
  config(
    displayModeBar = TRUE,
    modeBarButtonsToRemove = c("lasso2d", "select2d"),
    displaylogo = FALSE,
    toImageButtonOptions = list(format = "png", filename = "monte_carlo_glow")
  )

Interpretation

Throwing 2,750 darts at a square target that has a circle drawn inside it, and only about 172 darts (6.25%) hit inside the circle. Using this ratio, we can calculate that π is approximately 3.14 because the proportion of darts inside the circle equals the circle’s area (π) divided by the square’s area (4). The more darts we throw, the more accurate our pi value becomes, as the law of large numbers reduces random variation and pushes the estimate closer to the true mathematical constant. This Monte Carlo method demonstrates how random sampling can solve

6 Advanced Data Transformation & Feature Engineering

Advanced Data Transformation & Feature Engineering

In this segment, we discuss Advanced Data Transformation & Feature Engineering, covering two key functions: normalize_columns(df) which applies loop-based normalization to scale numeric columns to a 0-1 range using (x - min)/(max - min), and z_score(df) which standardizes data to have a mean of 0 and standard deviation of 1. From these transformed values, new features like performance_category (e.g., Low, Medium, High) and salary_bracket (e.g., Entry, Mid, Senior) are created through binning and conditional logic, enabling more intuitive grouping and analysis. To assess the impact of these transformations, the section compares distributions before and after using histograms and boxplots, which reveal changes in shape, spread, outliers, and central tendency. This comparison ensures that transformations work as intended and prepares the dataset for reliable machine learning or statistical modeling.

6.1 Loop-based normalization

Loop-Based Normalization

In this segment, loop-based normalization is implemented within the normalize_columns(df) function to scale numeric columns to a uniform range, typically 0 to 1, using the formula (x - min)/(max - min). The function uses a loop to iterate through each column of the dataframe, checks if the column is numeric, and then applies the normalization formula to every value in that column. This approach provides full control over the transformation process, allowing for conditional handling of different data types and making the logic transparent and educational. By scaling all numeric features to the same range, loop-based normalization ensures that no single variable dominates analyses or machine learning models due to larger magnitude, while also preserving the relative relationships and distribution shape of the original data.

6.2 New Features

library(DT)

set.seed(123)

generate_hotel_data <- function(n_employees = 120) {
  
  departments <- c(
    "Front Office", "Housekeeping", "Food & Beverage",
    "Kitchen", "Maintenance", "HR", "Finance"
  )
  
  data_list <- vector("list", n_employees)
  
  for (e in seq_len(n_employees)) {
    
    
    # Salary
    
    salary <- round(rlnorm(1, meanlog = 8.7, sdlog = 0.35))
    
    # Mild outlier 
    if (runif(1) < 0.03) {
      salary <- salary * runif(1, 1.3, 1.8)
    }
    
    # Clipping biar aman untuk Z-score
    salary <- min(max(salary, 2500), 18000)
    
    
    # Scores
    performance_score <- round(runif(1, 55, 100), 1)
    KPI_score         <- round(runif(1, 60, 100), 1)
    
    
    # Performance Category
    perf_cat <- if (performance_score >= 90) {
      "Excellent"
    } else if (performance_score >= 80) {
      "Very Good"
    } else if (performance_score >= 70) {
      "Good"
    } else if (performance_score >= 60) {
      "Average"
    } else {
      "Poor"
    }
    
    # Salary Bracket 
    sal_bracket <- if (salary >= 12000) {
      "High"
    } else if (salary >= 7000) {
      "Medium"
    } else {
      "Low"
    }
    
    data_list[[e]] <- data.frame(
      employee_id = sprintf("E%03d", e),
      department  = sample(departments, 1),
      salary      = salary,
      performance_score = performance_score,
      KPI_score   = KPI_score,
      performance_category = perf_cat,
      salary_bracket = sal_bracket,
      stringsAsFactors = FALSE
    )
  }
  
  hotel_data <- do.call(rbind, data_list)
  return(hotel_data)
}

hotel_data <- generate_hotel_data(120)

datatable(
  hotel_data,
  options = list(pageLength = 10, autoWidth = TRUE),
  rownames = FALSE,
  caption = "Hotel Employee Dataset (Realistic & Stat-Safe)"
)
library(DT)
library(dplyr)

set.seed(123)

# Fungsi generate data hotel
generate_hotel_data <- function(n_employees = 120) {
  
  departments <- c(
    "Front Office", "Housekeeping", "Food & Beverage",
    "Kitchen", "Maintenance", "HR", "Finance"
  )
  
  data_list <- vector("list", n_employees)
  
  for (e in seq_len(n_employees)) {
    
    # Realistic Salary (controlled skew)
    salary <- round(rlnorm(1, meanlog = 8.7, sdlog = 0.35))
    
    if (runif(1) < 0.03) salary <- salary * runif(1, 1.3, 1.8)
    
    salary <- min(max(salary, 2500), 18000)
    
    # Scores
    performance_score <- round(runif(1, 55, 100), 1)
    KPI_score         <- round(runif(1, 60, 100), 1)
    
    # Performance Category
    perf_cat <- case_when(
      performance_score >= 90 ~ "Excellent",
      performance_score >= 80 ~ "Very Good",
      performance_score >= 70 ~ "Good",
      performance_score >= 60 ~ "Average",
      TRUE ~ "Poor"
    )
    
    # Salary Bracket
    sal_bracket <- case_when(
      salary >= 12000 ~ "High",
      salary >= 7000  ~ "Medium",
      TRUE            ~ "Low"
    )
    
    data_list[[e]] <- data.frame(
      employee_id = sprintf("E%03d", e),
      department  = sample(departments, 1),
      salary      = salary,
      performance_score = performance_score,
      KPI_score   = KPI_score,
      performance_category = perf_cat,
      salary_bracket = sal_bracket,
      stringsAsFactors = FALSE
    )
  }
  
  hotel_data <- do.call(rbind, data_list)
  return(hotel_data)
}


# Fungsi Normalisasi (Min-Max)
normalize_columns <- function(df, cols) {
  df %>%
    mutate(across(all_of(cols), ~ (. - min(.)) / (max(.) - min(.)), .names = "{.col}_norm"))
}

# Fungsi Z-score
z_score <- function(df, cols) {
  df %>%
    mutate(across(all_of(cols), ~ as.numeric(scale(.)), .names = "{.col}_z"))
}

#
# Generate Data & Apply Transformasi
hotel_data <- generate_hotel_data(120)

# Normalisasi kolom salary & performance_score
hotel_data_norm <- normalize_columns(hotel_data, c("salary", "performance_score"))

# Z-score kolom salary & performance_score
hotel_data_final <- z_score(hotel_data_norm, c("salary", "performance_score"))


# Tampilkan Data & Summary
datatable(
  hotel_data_final,
  options = list(pageLength = 10, autoWidth = TRUE),
  rownames = FALSE,
  caption = "Hotel Employee Dataset dengan Normalisasi & Z-Score"
)
summary(hotel_data_final[, c("salary_norm", "performance_score_norm", "salary_z", "performance_score_z")])
##   salary_norm     performance_score_norm    salary_z       performance_score_z
##  Min.   :0.0000   Min.   :0.0000         Min.   :-1.8084   Min.   :-1.7187    
##  1st Qu.:0.2350   1st Qu.:0.2709         1st Qu.:-0.6789   1st Qu.:-0.7895    
##  Median :0.3496   Median :0.4707         Median :-0.1282   Median :-0.1043    
##  Mean   :0.3763   Mean   :0.5011         Mean   : 0.0000   Mean   : 0.0000    
##  3rd Qu.:0.4977   3rd Qu.:0.7619         3rd Qu.: 0.5834   3rd Qu.: 0.8946    
##  Max.   :1.0000   Max.   :1.0000         Max.   : 2.9978   Max.   : 1.7114

6.3 Compare Distribution Before and After

6.3.1 Performance Score

library(plotly)

fig_box_perf <- plot_ly(data = hotel_data_final) %>%
  add_trace(
    y = ~performance_score,
    type = "box",
    name = "Before",
    boxpoints = "outliers",
    marker = list(color = "#00FFFF"),
    line = list(color = "#00FFFF")
  ) %>%
  add_trace(
    y = ~performance_score_norm,
    type = "box",
    name = "After Normalization",
    boxpoints = "outliers",
    marker = list(color = "#FF00FF"),
    line = list(color = "#FF00FF")
  ) %>%
  layout(
    title = list(
      text = "Performance Score: Before vs After Normalization",
      font = list(color = "#FFFFFF")
    ),
    
    # background gelap
    paper_bgcolor = "#0A0A0A",
    plot_bgcolor  = "#0A0A0A",
    
    # axis
    yaxis = list(
      title = "Value",
      color = "#FFFFFF",
      gridcolor = "#333333"
    ),
    
    xaxis = list(
      color = "#FFFFFF"
    ),
    
    # legend
    legend = list(
      font = list(color = "#FFFFFF")
    ),
    
    boxmode = "group"
  )

fig_box_perf

Interpretation

The boxplot comparison shows original performance scores ranging from 55 to 100, with median, IQR, and outliers reflecting natural variation. After min-max normalization, all values are rescaled to 0–1 while preserving the exact distribution shape, including median position and data spread. This confirms that normalization only changes the scale, not the underlying distribution or relationships within the dataset. Outliers remain visible after normalization, now expressed within the 0–1 scale, making the data ready for cross-variable comparison or machine learning applications.

6.3.2 Salary

library(plotly)

fig_salary_z <- plot_ly(hotel_data_final) %>%
  add_trace(
    x = ~salary,
    type = "histogram",
    name = "Before (Original)",
    opacity = 0.7,
    marker = list(color = "cyan", line = list(color = "white", width = 1)),
    hovertemplate = "Salary: %{x}<br>Frequency: %{y}<extra></extra>"
  ) %>%
  add_trace(
    x = ~salary_z,
    type = "histogram",
    name = "After Z-Score",
    opacity = 0.7,
    marker = list(color = "magenta", line = list(color = "white", width = 1)),
    hovertemplate = "Z-Score: %{x}<br>Frequency: %{y}<extra></extra>"
  ) %>%
  layout(
    title = list(
      text = "Salary Distribution: Before vs After Z-Score Normalization",
      font = list(color = "white", size = 18, family = "Arial Black")
    ),
    barmode = "overlay",
    plot_bgcolor = "black",
    paper_bgcolor = "black",
    xaxis = list(
      title = list(text = "Value", font = list(color = "white")),
      tickfont = list(color = "white"),
      gridcolor = "gray30",
      zerolinecolor = "gray50"
    ),
    yaxis = list(
      title = list(text = "Frequency", font = list(color = "white")),
      tickfont = list(color = "white"),
      gridcolor = "gray30",
      zerolinecolor = "gray50"
    ),
    legend = list(
      font = list(color = "white", size = 12),
      bgcolor = "rgba(0,0,0,0.6)",
      bordercolor = "white",
      borderwidth = 1
    ),
    hoverlabel = list(bgcolor = "white", font = list(color = "black"))
  ) %>%
  config(displayModeBar = TRUE)

fig_salary_z

Interpretation

The original salary histogram shows a right-skewed distribution concentrated between IDR 3–7 million, with a peak at IDR 4.5 million and a few extreme values above IDR 20 million acting as clear outliers. After Z-score normalization, the same distribution shifts to center at zero with a standard deviation of one, preserving the exact right-skewed shape and the relative position of each salary value. The outliers originally above IDR 20 million now appear as Z-scores above +2.8, making them instantly recognizable as statistical outliers without any loss of information. Thus, Z-score normalization does not alter the data’s structure or hide extreme values but merely rescales the salary into standardized units, enabling direct comparison with other normalized variables like performance or tenure.

7 Mini Project:Company KPI Dashboard & Simulation

Mini Project - Company KPI Dashboard

This mini project generates a synthetic dataset for 5–10 companies with 50–200 employees each. Columns include employee_id, company_id, salary, performance_score, KPI_score, and department. A loop is used to categorize employees into KPI tiers (Excellent, Good, Satisfactory, Needs Improvement).

The project summarizes each company by calculating average salary, average KPI score, and identifying top performers. Output includes tables for top performers and department analysis, plus salary distribution plots. Advanced visualizations feature grouped bar charts and scatter plots with regression lines to explore relationships between salary and KPI.

7.1 Generate Data

library(data.table)

set.seed(123)

# Parameter
n_companies <- 7
n_employees <- 100

departments <- c(
  "Front Office", "Housekeeping", "Food & Beverage",
  "Kitchen", "Maintenance", "HR", "Finance"
)

# List penampung
all_data <- vector("list", n_companies)

# Loop perusahaan
for (c in 1:n_companies) {
  
  company_id <- paste0("HOTEL_", sprintf("%02d", c))
  
  # Loop karyawan dalam bentuk data.table langsung
  dt <- data.table(
    employee_id = paste0(company_id, "_E", sprintf("%03d", 1:n_employees)),
    company_id  = company_id,
    
    # Salary (skewed)
    salary = pmin(
      pmax(round(rlnorm(n_employees, meanlog = 8.7, sdlog = 0.35)), 2500),
      20000
    ),
    
    performance_score = round(runif(n_employees, 55, 100), 1),
    KPI_score         = round(runif(n_employees, 60, 100), 1),
    department        = sample(departments, n_employees, replace = TRUE)
  )
  
  all_data[[c]] <- dt
}

# Gabungkan semua
hotel_multi_dt <- rbindlist(all_data)

# Lihat hasil
hotel_multi_dt

7.2 Summarize per company

library(data.table)
summary_company <- hotel_multi_dt[, .(
  avg_salary = round(mean(salary), 2),
  avg_KPI = round(mean(KPI_score), 2),
  top_performers = sum(performance_score >= 90)
), by = company_id][order(company_id)]

summary_company

7.3 Loop to categorize employees into KPI tiers

library(data.table)

set.seed(123)

# Parameter
n_companies <- 7
n_employees <- 100

departments <- c(
  "Front Office", "Housekeeping", "Food & Beverage",
  "Kitchen", "Maintenance", "HR", "Finance"
)

# List penampung
all_data <- vector("list", n_companies)

# Loop perusahaan
for (c in 1:n_companies) {
  
  company_id <- paste0("HOTEL_", sprintf("%02d", c))
  
  # Loop karyawan dalam bentuk data.table langsung
  dt <- data.table(
    employee_id = paste0(company_id, "_E", sprintf("%03d", 1:n_employees)),
    company_id  = company_id,
    
    # Salary (skewed)
    salary = pmin(
      pmax(round(rlnorm(n_employees, meanlog = 8.7, sdlog = 0.35)), 2500),
      20000
    ),
    
    performance_score = round(runif(n_employees, 55, 100), 1),
    KPI_score         = round(runif(n_employees, 60, 100), 1),
    department        = sample(departments, n_employees, replace = TRUE)
  )
  
  all_data[[c]] <- dt
}

# Gabungkan semua
hotel_multi_dt <- rbindlist(all_data)

# Tambahkan kolom KPI_tier
hotel_multi_dt[, KPI_tier := fifelse(
  KPI_score >= 90, "Excellent",
  fifelse(
    KPI_score >= 80, "Good",
    fifelse(
      KPI_score >= 70, "Average",
      "Low"
    )
  )
)]


# Lihat hasil
hotel_multi_dt

7.4 Visualization

7.4.1 Barchart Top Performance per Company

library(plotly)
library(dplyr)

top_perf <- hotel_multi_dt %>%
  group_by(company_id) %>%
  summarise(top_performers = sum(performance_score >= 90))

plot_ly(
  top_perf,
  x = ~company_id,
  y = ~top_performers,
  type = 'bar',
  marker = list(
    color = "#00FFFF",
    line = list(color = "#FF00FF", width = 2) # glow outline
  )
) %>%
  layout(
    title = list(
      text = "Top Performers per Company",
      font = list(color = "#FF00FF", size = 20)
    ),
    
    #  BACKGROUND HITAM
    plot_bgcolor = "#000000",
    paper_bgcolor = "#000000",
    
    # FONT NEON
    font = list(color = "#00FFFF"),
    
    # GRID + AXIS GLOW
    xaxis = list(
      title = "Company",
      gridcolor = "#222222",
      zerolinecolor = "#444444",
      tickfont = list(color = "#00FFFF")
    ),
    
    yaxis = list(
      title = "Top Performers",
      gridcolor = "#222222",
      zerolinecolor = "#444444",
      tickfont = list(color = "#00FFFF")
    )
  )

Interpretation

Through the bar chart, differences in the distribution of top performers across companies can be observed. Companies with taller bars indicate that they have more high-performing employees, which may reflect effective human resource management, a good performance evaluation system, or a work environment that supports productivity. Conversely, companies with fewer top performers may indicate potential areas for improvement in employee performance management, such as training, work motivation, or a suboptimal assessment system.

7.4.2 Histogram Salary Distribution

library(plotly)

p <- plot_ly(
  data = hotel_multi_dt,
  x = ~salary,
  type = "histogram",
  marker = list(color = "#39FF14")
)

p <- p %>%
  layout(
    title = list(text = "Salary Distribution"),
    plot_bgcolor = "#000000",
    paper_bgcolor = "#000000",
    font = list(color = "#39FF14"),
    
    xaxis = list(title = "Salary"),
    yaxis = list(title = "Count")
  )
p

Interpretation

The histogram indicates that most employees are concentrated within a certain salary range, suggesting that the company has a dominant pay level for the majority of its workforce. There are fewer employees in the higher salary ranges, which implies that high-paying positions are limited. If the distribution is skewed to the right, it shows that most employees earn lower to mid-level salaries, with only a small number receiving significantly higher pay. This pattern reflects a typical organizational structure where top-level positions are fewer compared to entry- and mid-level roles.

library(plotly)

# Warna neon untuk setiap department
neon_colors <- c(
  "#39FF14",  # Neon green
  "#FF0730",  # Neon red
  "#00FFFF",  # Neon cyan
  "#FF00FF",  # Neon magenta
  "#FFCC00",  # Neon yellow
  "#FF6600"   # Neon orange
)

# Buat model regression untuk keseluruhan data
model <- lm(KPI_score ~ salary, data = hotel_multi_dt)
hotel_multi_dt$fitted_kpi <- fitted(model)

p <- plot_ly(
  data = hotel_multi_dt,
  x = ~salary,
  y = ~KPI_score,
  color = ~department,
  colors = neon_colors,
  type = "scatter",
  mode = "markers",
  marker = list(
    size = 8,
    opacity = 0.8
  )
) %>%
  add_lines(
    x = ~salary,
    y = ~fitted_kpi,
    line = list(color = "#FF0730", width = 3),
    name = "Regression Line",
    inherit = FALSE
  ) %>%
  layout(
    title = list(
      text = "Salary vs KPI Score by Department with Regression Line",
      font = list(color = "#00FFFF", size = 18)
    ),
    plot_bgcolor = "#000000",
    paper_bgcolor = "#000000",
    font = list(color = "#39FF14"),
    xaxis = list(
      title = "Salary",
      gridcolor = "#333333",
      tickfont = list(color = "#FFCC00")
    ),
    yaxis = list(
      title = "KPI Score",
      gridcolor = "#333333",
      tickfont = list(color = "#FFCC00")
    ),
    legend = list(
      font = list(color = "#00FFFF"),
      bgcolor = "rgba(0,0,0,0.7)",
      bordercolor = "#39FF14",
      borderwidth = 1
    )
  )

p

Interpretation

The histogram indicates that most employees are concentrated within a certain salary range, suggesting that the company has a dominant pay level for the majority of its workforce. There are fewer employees in the higher salary ranges, which implies that high-paying positions are limited. If the distribution is skewed to the right, it shows that most employees earn lower to mid-level salaries, with only a small number receiving significantly higher pay. This pattern reflects a typical organizational structure where top-level positions are fewer compared to entry- and mid-level roles.

LS0tDQp0aXRsZTogIlByYWN0aWN1bSBBZHZhbmNlIA0KDQoNCkZ1bmN0aW9ucyAmIExvb3BzIiAgICAgICAgICAgICMgTWFpbiB0aXRsZSBvZiB0aGUgZG9jdW1lbnQNCmF1dGhvcjogIkFuaW5keWEgS3Jpc3RpYW5pbmdwdXRyaSIgICAgICAjIFJlcGxhY2Ugd2l0aCB5b3VyIGZ1bGwgbmFtZQ0KZGF0ZTogICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCIgIyBBdXRvIGRpc3BsYXlzIHRoZSBjdXJyZW50IGRhdGUNCm91dHB1dDogICAgICAgICAgICAgICAgICAgICAgICAgIyBPdXRwdXQgc2VjdGlvbiBkZWZpbmVzIHRoZSBmb3JtYXQgYW5kIGxheW91dCANCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246ICAgICAgIyBodHRwczovL2dpdGh1Yi5jb20vanViYS9ybWRmb3JtYXRzDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUgICAgICAgICMgRW1iZWRzIGFsbCByZXNvdXJjZXMgKENTUywgSlMsIGltYWdlcykgDQogICAgdGh1bWJuYWlsczogdHJ1ZSAgICAgICAgICAgICMgRGlzcGxheXMgaW1hZ2UgdGh1bWJuYWlscyBpbiB0aGUgZG9jDQogICAgbGlnaHRib3g6IHRydWUgICAgICAgICAgICAgICMgRW5hYmxlcyBjbGljayB0byBlbmxhcmdlIGltYWdlcw0KICAgIGdhbGxlcnk6IHRydWUgICAgICAgICAgICAgICAjIEdyb3VwcyBpbWFnZXMgaW50byBhbiBpbnRlcmFjdGl2ZSBnYWxsZXJ5DQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlICAgICAgICMgQXV0b21hdGljYWxseSBudW1iZXJzIGFsbCBzZWN0aW9ucw0KICAgIGxpYl9kaXI6IGxpYnMgICAgICAgICAgICAgICAjIERpcmVjdG9yeSB3aGVyZSBKYXZhU2NyaXB0L0NTUyBsaWJyYXJpZXMNCiAgICBkZl9wcmludDogInBhZ2VkIiAgICAgICAgICAgIyBEaXNwbGF5cyBkYXRhIGZyYW1lcyBhcyBpbnRlcmFjdGl2ZSBwYWdlZCANCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93IiAgICAgICAgIyBBbGxvd3MgZm9sZGluZy91bmZvbGRpbmcgUiBjb2RlIGJsb2NrcyANCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMgICAgICAgICAgIyBBZGRzIGEgYnV0dG9uIHRvIGRvd25sb2FkIGFsbCBSIGNvZGUNCi0tLQ0KDQpgYGB7PWh0bWx9DQo8c3R5bGU+DQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogNDdweCAhaW1wb3J0YW50Ow0KICBmb250LXdlaWdodDogODAwOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiUGxheWZhaXIgRGlzcGxheSIsICJHZW9yZ2lhIiwgIlRpbWVzIE5ldyBSb21hbiIsIHNlcmlmICFpbXBvcnRhbnQ7DQogIGZvbnQtc3R5bGU6IGl0YWxpYyAhaW1wb3J0YW50Ow0KICBtYXJnaW4tYm90dG9tOiAyMHB4ICFpbXBvcnRhbnQ7DQogIGxpbmUtaGVpZ2h0OiAxLjI7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgcGFkZGluZy1ib3R0b206IDE1cHggIWltcG9ydGFudDsNCiAgY29sb3I6ICM4MDAwMjAgIWltcG9ydGFudDsNCn0NCg0KaDEudGl0bGU6OmFmdGVyIHsNCiAgY29udGVudDogIiI7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgYm90dG9tOiAwOw0KICBsZWZ0OiA1MCU7DQogIHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKTsNCiAgd2lkdGg6IDE1MHB4Ow0KICBoZWlnaHQ6IDJweDsNCiAgYmFja2dyb3VuZDogIzgwMDAyMDsNCiAgb3BhY2l0eTogMC4zOw0KfQ0KDQoucGVyZmVjdC1jZW50ZXItYm94IHsNCiAgcG9zaXRpb246IHJlbGF0aXZlOw0KICBwYWRkaW5nOiAyNXB4IDQwcHggIWltcG9ydGFudDsNCiAgbWFyZ2luOiAyMHB4IGF1dG8gIWltcG9ydGFudDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBkaXNwbGF5OiB0YWJsZTsNCiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgI2YwZjhmZiAwJSwgI2U2ZjNmZiAxMDAlKTsNCiAgYm9yZGVyOiAxcHggc29saWQgIzgwMDAyMDsNCiAgYm9yZGVyLXJhZGl1czogMjVweDsNCiAgYm94LXNoYWRvdzogMCA0cHggMTVweCByZ2JhKDEyOCwgMCwgMzIsIDAuMTUpOw0KICBtYXgtd2lkdGg6IDUwMHB4Ow0KICBmb250LWZhbWlseTogIkNvcm1vcmFudCBHYXJhbW9uZCIsICJHZW9yZ2lhIiwgIlRpbWVzIE5ldyBSb21hbiIsIHNlcmlmICFpbXBvcnRhbnQ7DQp9DQoNCi5wZXJmZWN0LWNlbnRlci1ib3g6OmJlZm9yZSwNCi5wZXJmZWN0LWNlbnRlci1ib3g6OmFmdGVyIHsNCiAgY29udGVudDogIuKcvyI7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgd2lkdGg6IGF1dG87DQogIGhlaWdodDogYXV0bzsNCiAgZm9udC1zaXplOiAyNHB4Ow0KICBjb2xvcjogIzgwMDAyMDsNCiAgYm9yZGVyOiBub25lOw0KICBvcGFjaXR5OiAwLjU7DQogIHRyYW5zaXRpb246IGFsbCAwLjNzIGVhc2U7DQp9DQoNCi5wZXJmZWN0LWNlbnRlci1ib3g6OmJlZm9yZSB7DQogIHRvcDogNXB4Ow0KICBsZWZ0OiAxMHB4Ow0KICBib3JkZXI6IG5vbmU7DQp9DQoNCi5wZXJmZWN0LWNlbnRlci1ib3g6OmFmdGVyIHsNCiAgYm90dG9tOiA1cHg7DQogIHJpZ2h0OiAxMHB4Ow0KICBib3JkZXI6IG5vbmU7DQp9DQoNCi5wZXJmZWN0LWNlbnRlci1ib3g6aG92ZXI6OmJlZm9yZSwNCi5wZXJmZWN0LWNlbnRlci1ib3g6aG92ZXI6OmFmdGVyIHsNCiAgdHJhbnNmb3JtOiBzY2FsZSgxLjIpOw0KICBvcGFjaXR5OiAwLjk7DQogIGNvbG9yOiAjODAwMDIwOw0KfQ0KDQoud2Vlay1udW1iZXIgew0KICBmb250LXNpemU6IDE4cHggIWltcG9ydGFudDsNCiAgZm9udC13ZWlnaHQ6IDcwMDsNCiAgbGV0dGVyLXNwYWNpbmc6IDAuNXB4Ow0KICBtYXJnaW4tYm90dG9tOiA1cHggIWltcG9ydGFudDsNCiAgbGluZS1oZWlnaHQ6IDEuMzsNCiAgZm9udC1mYW1pbHk6ICJNb250c2VycmF0IiwgIlJhbGV3YXkiLCAiSGVsdmV0aWNhIE5ldWUiLCBzYW5zLXNlcmlmICFpbXBvcnRhbnQ7DQogIGNvbG9yOiAjODAwMDIwOw0KfQ0KDQouYXNzaWdubWVudC10aXRsZSB7DQogIGZvbnQtc2l6ZTogMTRweCAhaW1wb3J0YW50Ow0KICBmb250LXdlaWdodDogNTAwOw0KICBwb3NpdGlvbjogcmVsYXRpdmU7DQogIHBhZGRpbmctdG9wOiA4cHggIWltcG9ydGFudDsNCiAgbWFyZ2luLXRvcDogNXB4ICFpbXBvcnRhbnQ7DQogIGxpbmUtaGVpZ2h0OiAxLjM7DQogIGZvbnQtZmFtaWx5OiAiQ29ybW9yYW50IEluZmFudCIsICJHZW9yZ2lhIiwgIlRpbWVzIE5ldyBSb21hbiIsIHNlcmlmICFpbXBvcnRhbnQ7DQogIGNvbG9yOiAjNWY5ZWEwOw0KfQ0KDQouYXNzaWdubWVudC10aXRsZTo6YmVmb3JlIHsNCiAgY29udGVudDogIuKcpiI7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgdG9wOiAtNXB4Ow0KICBsZWZ0OiA1MCU7DQogIHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKTsNCiAgd2lkdGg6IGF1dG87DQogIGhlaWdodDogYXV0bzsNCiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7DQogIG9wYWNpdHk6IDAuNjsNCiAgZm9udC1zaXplOiAxNnB4Ow0KICBjb2xvcjogIzgwMDAyMDsNCn0NCg0KLmNvbnRhaW5lciB7DQogIG1hcmdpbjogMCAhaW1wb3J0YW50Ow0KICBwYWRkaW5nOiAyMHB4ICFpbXBvcnRhbnQ7DQogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICNmNWYwZmEgMCUsICNlOGYwZjUgMTAwJSk7DQp9DQoNCi5jb250ZW50LXdyYXBwZXIgew0KICBkaXNwbGF5OiBmbGV4Ow0KICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOw0KICBnYXA6IDE1cHggIWltcG9ydGFudDsNCiAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCn0NCjwvc3R5bGU+DQpgYGANCg0KYGBgez1odG1sfQ0KPCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJpZCI+DQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+DQogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPg0KICAgIDx0aXRsZT5Qcm9maWwgTWFoYXNpc3dhIC0gQW5pbmR5YSBLcmlzdGlhbmluZ3B1dHJpPC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnUGxheWZhaXIgRGlzcGxheScsICdHZW9yZ2lhJywgJ1RpbWVzIE5ldyBSb21hbicsIHNlcmlmOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgI0FERDhFNiAwJSwgIzg3Q0VFQiAxMDAlKTsNCiAgICAgICAgICAgIG1pbi1oZWlnaHQ6IDEwMHZoOw0KICAgICAgICAgICAgcGFkZGluZzogNDBweCAzMHB4Ow0KICAgICAgICAgICAgZGlzcGxheTogZmxleDsNCiAgICAgICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICAgICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250YWluZXIgew0KICAgICAgICAgICAgbWF4LXdpZHRoOiAxMTAwcHg7DQogICAgICAgICAgICB3aWR0aDogMTAwJTsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNmZmZmZmY7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAzMHB4Ow0KICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMjVweCA1MHB4IHJnYmEoMTI4LCAwLCAzMiwgMC4yNSk7DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDEyOCwgMCwgMzIsIDAuMTUpOw0KICAgICAgICB9DQoNCiAgICAgICAgLyogSGVhZGVyIGRlbmdhbiAyIGtvbG9tICovDQogICAgICAgIC5oZWFkZXItbGFuZHNjYXBlIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICM4MDAwMjAsICM2MDAwMTgpOw0KICAgICAgICAgICAgcGFkZGluZzogNDBweCA0NXB4Ow0KICAgICAgICAgICAgZGlzcGxheTogZ3JpZDsNCiAgICAgICAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogYXV0byAxZnI7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgZ2FwOiA0MHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLyogS29sb20gS2lyaSAtIEZvdG8gKi8NCiAgICAgICAgLnBob3RvLWNvbCB7DQogICAgICAgICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgICAgIH0NCg0KICAgICAgICAucGhvdG8tY29udGFpbmVyIHsNCiAgICAgICAgICAgIHdpZHRoOiAxMzBweDsNCiAgICAgICAgICAgIGhlaWdodDogMTMwcHg7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA1MCU7DQogICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuOw0KICAgICAgICAgICAgYm9yZGVyOiA0cHggc29saWQgI0FERDhFNjsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgOHB4IDIwcHggcmdiYSgwLCAwLCAwLCAwLjI1KTsNCiAgICAgICAgICAgIHRyYW5zaXRpb246IHRyYW5zZm9ybSAwLjNzIGVhc2U7DQogICAgICAgIH0NCg0KICAgICAgICAucGhvdG8tY29udGFpbmVyOmhvdmVyIHsNCiAgICAgICAgICAgIHRyYW5zZm9ybTogc2NhbGUoMS4wMik7DQogICAgICAgIH0NCg0KICAgICAgICAucHJvZmlsZS1waG90byB7DQogICAgICAgICAgICB3aWR0aDogMTAwJTsNCiAgICAgICAgICAgIGhlaWdodDogMTAwJTsNCiAgICAgICAgICAgIG9iamVjdC1maXQ6IGNvdmVyOw0KICAgICAgICB9DQoNCiAgICAgICAgLyogS29sb20gS2FuYW4gLSBOYW1hICYgTklNICovDQogICAgICAgIC5pbmZvLWNvbCB7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KICAgICAgICB9DQoNCiAgICAgICAgLm5hbWUgew0KICAgICAgICAgICAgZm9udC1zaXplOiAyOHB4Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDgwMDsNCiAgICAgICAgICAgIGNvbG9yOiAjZmZmZmZmOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdQbGF5ZmFpciBEaXNwbGF5JywgJ0dlb3JnaWEnLCBzZXJpZjsNCiAgICAgICAgICAgIGZvbnQtc3R5bGU6IGl0YWxpYzsNCiAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IDEycHg7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMXB4Ow0KICAgICAgICAgICAgdGV4dC1zaGFkb3c6IDJweCAycHggNHB4IHJnYmEoMCwgMCwgMCwgMC4yKTsNCiAgICAgICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7DQogICAgICAgIH0NCg0KICAgICAgICAubmltIHsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNBREQ4RTY7DQogICAgICAgICAgICBjb2xvcjogIzgwMDAyMDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDhweCAyNHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNDBweDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA3MDA7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ01vbnRzZXJyYXQnLCAnUmFsZXdheScsIHNhbnMtc2VyaWY7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMXB4Ow0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAycHggOHB4IHJnYmEoMCwgMCwgMCwgMC4xKTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8qIEVGRUsgRUxFR0FOIHVudHVrIG5hbWEgZG9zZW4gLSBTb2Z0IFNoaW1tZXIgKyBHb2xkIEdyYWRpZW50ICovDQogICAgICAgIC5kb3Nlbi1uYW1lIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgNCiAgICAgICAgICAgICAgICAxMjBkZWcsDQogICAgICAgICAgICAgICAgI0Q0QUYzNyAwJSwNCiAgICAgICAgICAgICAgICAjRkZGNUUwIDI1JSwNCiAgICAgICAgICAgICAgICAjRDRBRjM3IDUwJSwNCiAgICAgICAgICAgICAgICAjRkZGNUUwIDc1JSwNCiAgICAgICAgICAgICAgICAjRDRBRjM3IDEwMCUNCiAgICAgICAgICAgICk7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLXNpemU6IDI1MCUgYXV0bzsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY2xpcDogdGV4dDsNCiAgICAgICAgICAgIC13ZWJraXQtYmFja2dyb3VuZC1jbGlwOiB0ZXh0Ow0KICAgICAgICAgICAgLXdlYmtpdC10ZXh0LWZpbGwtY29sb3I6IHRyYW5zcGFyZW50Ow0KICAgICAgICAgICAgYW5pbWF0aW9uOiBlbGVnYW50U2hpbW1lciAzcyBlYXNlLWluLW91dCBpbmZpbml0ZTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA3MDA7DQogICAgICAgICAgICBmb250LXNpemU6IDIwcHg7DQogICAgICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1BsYXlmYWlyIERpc3BsYXknLCAnR2VvcmdpYScsIHNlcmlmOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDFweDsNCiAgICAgICAgICAgIHRleHQtc2hhZG93OiBub25lOw0KICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOw0KICAgICAgICB9DQoNCiAgICAgICAgQGtleWZyYW1lcyBlbGVnYW50U2hpbW1lciB7DQogICAgICAgICAgICAwJSB7DQogICAgICAgICAgICAgICAgYmFja2dyb3VuZC1wb3NpdGlvbjogMCUgY2VudGVyOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgMTAwJSB7DQogICAgICAgICAgICAgICAgYmFja2dyb3VuZC1wb3NpdGlvbjogMjAwJSBjZW50ZXI7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICAvKiBIb3ZlciBlZmZlY3QgZWxlZ2FuICovDQogICAgICAgIC5kb3Nlbi1uYW1lOmhvdmVyIHsNCiAgICAgICAgICAgIGFuaW1hdGlvbjogZWxlZ2FudFNoaW1tZXIgMS4ycyBlYXNlLWluLW91dCBpbmZpbml0ZTsNCiAgICAgICAgICAgIHRyYW5zZm9ybTogc2NhbGUoMS4wMSk7DQogICAgICAgICAgICB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gMC40cyBlYXNlOw0KICAgICAgICB9DQoNCiAgICAgICAgLyogQ29udGVudCBCYXdhaCAqLw0KICAgICAgICAuY29udGVudC1ib3R0b20gew0KICAgICAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgI2YwZjhmZiAwJSwgI2U2ZjNmZiAxMDAlKTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDQwcHggNDVweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC8qIE5hbWEgRG9zZW4gZGkgYXRhcyBpbnN0aXR1dCAqLw0KICAgICAgICAuZG9zZW4tc2VjdGlvbiB7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogICAgICAgICAgICBtYXJnaW4tYm90dG9tOiAyNXB4Ow0KICAgICAgICAgICAgcGFkZGluZy1ib3R0b206IDIwcHg7DQogICAgICAgICAgICBib3JkZXItYm90dG9tOiAycHggc29saWQgI0FERDhFNjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5kb3Nlbi1sYWJlbCB7DQogICAgICAgICAgICBmb250LXNpemU6IDEzcHg7DQogICAgICAgICAgICBjb2xvcjogIzgwMDAyMDsNCiAgICAgICAgICAgIGxldHRlci1zcGFjaW5nOiAzcHg7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ01vbnRzZXJyYXQnLCBzYW5zLXNlcmlmOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDsNCiAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IDEwcHg7DQogICAgICAgICAgICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlOw0KICAgICAgICB9DQoNCiAgICAgICAgLyogS2FtcHVzIEluZm8gKi8NCiAgICAgICAgLmNhbXB1cy1pbmZvIHsNCiAgICAgICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IDQwcHg7DQogICAgICAgIH0NCg0KICAgICAgICAuY2FtcHVzLW5hbWUgew0KICAgICAgICAgICAgZm9udC1zaXplOiAyNHB4Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDcwMDsNCiAgICAgICAgICAgIGNvbG9yOiAjODAwMDIwOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdQbGF5ZmFpciBEaXNwbGF5JywgJ0dlb3JnaWEnLCBzZXJpZjsNCiAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IDEwcHg7DQogICAgICAgIH0NCg0KICAgICAgICAubWFqb3Igew0KICAgICAgICAgICAgZm9udC1zaXplOiAxOHB4Ow0KICAgICAgICAgICAgY29sb3I6ICMyYzE4MTA7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0Nvcm1vcmFudCBHYXJhbW9uZCcsICdHZW9yZ2lhJywgc2VyaWY7DQogICAgICAgICAgICBmb250LXdlaWdodDogNTAwOw0KICAgICAgICB9DQoNCiAgICAgICAgLyogU2tpbGxzIFNlY3Rpb24gKi8NCiAgICAgICAgLnNraWxscy1saXN0IHsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGdhcDogMTVweDsNCiAgICAgICAgICAgIGZsZXgtd3JhcDogbm93cmFwOw0KICAgICAgICB9DQoNCiAgICAgICAgLnNraWxsLWl0ZW0gew0KICAgICAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzgwMDAyMCwgI2EwMTAzMCk7DQogICAgICAgICAgICBjb2xvcjogd2hpdGU7DQogICAgICAgICAgICBwYWRkaW5nOiAxMHB4IDE4cHg7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA1MHB4Ow0KICAgICAgICAgICAgZm9udC1zaXplOiAxM3B4Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnTW9udHNlcnJhdCcsICdSYWxld2F5Jywgc2Fucy1zZXJpZjsNCiAgICAgICAgICAgIGJvcmRlcjogMnB4IHNvbGlkICNBREQ4RTY7DQogICAgICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMC4zcyBlYXNlOw0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCA1cHggMTJweCByZ2JhKDEyOCwgMCwgMzIsIDAuMik7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogICAgICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwOw0KICAgICAgICB9DQoNCiAgICAgICAgLnNraWxsLWl0ZW06aG92ZXIgew0KICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC02cHgpOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzYwMDAxOCwgIzgwMDAyMCk7DQogICAgICAgICAgICBib3JkZXItY29sb3I6ICNENEFGMzc7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDEwcHggMjJweCByZ2JhKDEyOCwgMCwgMzIsIDAuMyk7DQogICAgICAgIH0NCg0KICAgICAgICAvKiBSZXNwb25zaXZlICovDQogICAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA5NTBweCkgew0KICAgICAgICAgICAgLnNraWxscy1saXN0IHsNCiAgICAgICAgICAgICAgICBmbGV4LXdyYXA6IHdyYXA7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIC5za2lsbC1pdGVtIHsNCiAgICAgICAgICAgICAgICB3aGl0ZS1zcGFjZTogbm9ybWFsOw0KICAgICAgICAgICAgICAgIGZvbnQtc2l6ZTogMTJweDsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiA4cHggMTVweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA3NTBweCkgew0KICAgICAgICAgICAgLmhlYWRlci1sYW5kc2NhcGUgew0KICAgICAgICAgICAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogMWZyOw0KICAgICAgICAgICAgICAgIGdhcDogMjBweDsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAzMHB4IDI1cHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIC5pbmZvLWNvbCB7DQogICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAucGhvdG8tY29udGFpbmVyIHsNCiAgICAgICAgICAgICAgICB3aWR0aDogMTEwcHg7DQogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMTBweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIA0KICAgICAgICAgICAgLm5hbWUgew0KICAgICAgICAgICAgICAgIGZvbnQtc2l6ZTogMjRweDsNCiAgICAgICAgICAgICAgICB3aGl0ZS1zcGFjZTogbm9ybWFsOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDU1MHB4KSB7DQogICAgICAgICAgICBib2R5IHsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAyMHB4IDE1cHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIC5oZWFkZXItbGFuZHNjYXBlIHsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAyNXB4IDIwcHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIC5jb250ZW50LWJvdHRvbSB7DQogICAgICAgICAgICAgICAgcGFkZGluZzogMjVweCAyMHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAubmFtZSB7DQogICAgICAgICAgICAgICAgZm9udC1zaXplOiAyMHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAubmltIHsNCiAgICAgICAgICAgICAgICBmb250LXNpemU6IDE1cHg7DQogICAgICAgICAgICAgICAgcGFkZGluZzogNnB4IDE4cHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIC5za2lsbC1pdGVtIHsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiA4cHggMTRweDsNCiAgICAgICAgICAgICAgICBmb250LXNpemU6IDExcHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIC5jYW1wdXMtbmFtZSB7DQogICAgICAgICAgICAgICAgZm9udC1zaXplOiAyMHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAubWFqb3Igew0KICAgICAgICAgICAgICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIA0KICAgICAgICAgICAgLmRvc2VuLW5hbWUgew0KICAgICAgICAgICAgICAgIGZvbnQtc2l6ZTogMTdweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIA0KICAgICAgICAgICAgLnNraWxscy1saXN0IHsNCiAgICAgICAgICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOw0KICAgICAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICAgICAgZ2FwOiAxMHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAuc2tpbGwtaXRlbSB7DQogICAgICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICAgICAgbWF4LXdpZHRoOiAyMjBweDsNCiAgICAgICAgICAgICAgICB3aGl0ZS1zcGFjZTogbm9ybWFsOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5Pg0KICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+DQogICAgICAgIDwhLS0gSEVBREVSOiBGb3RvICsgTmFtYSAmIE5JTSAtLT4NCiAgICAgICAgPGRpdiBjbGFzcz0iaGVhZGVyLWxhbmRzY2FwZSI+DQogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwaG90by1jb2wiPg0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9InBob3RvLWNvbnRhaW5lciI+DQogICAgICAgICAgICAgICAgICAgIDxpbWcgc3JjPSJDOi9Vc2Vycy9XSU5ET1dTIDExL09uZURyaXZlL0Rlc2t0b3AvUGVtcm9ncmFtYW4gU2FpbnMgRGF0YSBTZW1lc3RlciAyL3Byb2ZpbGUucG5nIiANCiAgICAgICAgICAgICAgICAgICAgICAgICBhbHQ9IkZvdG8gUHJvZmlsIEFuaW5keWEgS3Jpc3RpYW5pbmdwdXRyaSIgDQogICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9InByb2ZpbGUtcGhvdG8iPg0KICAgICAgICAgICAgICAgIDwvZGl2Pg0KICAgICAgICAgICAgPC9kaXY+DQogICAgICAgICAgICANCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImluZm8tY29sIj4NCiAgICAgICAgICAgICAgICA8aDEgY2xhc3M9Im5hbWUiPkFuaW5keWEgS3Jpc3RpYW5pbmdwdXRyaTwvaDE+DQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibmltIj5OSU06IDUyMjUwMDI1PC9kaXY+DQogICAgICAgICAgICA8L2Rpdj4NCiAgICAgICAgPC9kaXY+DQoNCiAgICAgICAgPCEtLSBDT05URU5UIEJBV0FIIC0tPg0KICAgICAgICA8ZGl2IGNsYXNzPSJjb250ZW50LWJvdHRvbSI+DQogICAgICAgICAgICA8IS0tIE5hbWEgRG9zZW4gZGVuZ2FuIGVmZWsgRUxFR0FOIC0tPg0KICAgICAgICAgICAgPGRpdiBjbGFzcz0iZG9zZW4tc2VjdGlvbiI+DQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZG9zZW4tbGFiZWwiPkxlY3R1cmU8L2Rpdj4NCiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJkb3Nlbi1uYW1lIj5CYWt0aSBTaXJlZ2FyLCBNLlNjLiwgQ0RTPC9kaXY+DQogICAgICAgICAgICA8L2Rpdj4NCg0KICAgICAgICAgICAgPCEtLSBJbmZvIEthbXB1cyAtLT4NCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhbXB1cy1pbmZvIj4NCiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYW1wdXMtbmFtZSI+QmFuZHVuZyBJbnN0aXR1dGUgb2YgVGVjaG5vbG9neSBhbmQgU2NpZW5jZXM8L2Rpdj4NCiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYWpvciI+U3R1ZGVudCBNYWpvciBEYXRhIFNjaWVuY2U8L2Rpdj4NCiAgICAgICAgICAgIDwvZGl2Pg0KDQogICAgICAgICAgICA8IS0tIDMgU2tpbGwgLS0+DQogICAgICAgICAgICA8ZGl2IGNsYXNzPSJza2lsbHMtbGlzdCI+DQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ic2tpbGwtaXRlbSI+UiBQcm9ncmFtbWluZzwvZGl2Pg0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9InNraWxsLWl0ZW0iPkRhdGEgU2NpZW5jZSBQcm9ncmFtbWluZyAxPC9kaXY+DQogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ic2tpbGwtaXRlbSI+RnVuY3Rpb24gYW5kIExvb3BzPC9kaXY+DQogICAgICAgICAgICA8L2Rpdj4NCiAgICAgICAgPC9kaXY+DQogICAgPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KDQoNCiMgRHluYW1pYyBNdWx0aSBGb3JtdWxhIEZ1bmN0aW9uDQoNCmBgYHs9aHRtbH0NCjwhRE9DVFlQRSBodG1sPg0KPGh0bWwgbGFuZz0iZW4iPg0KPGhlYWQ+DQogICAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPg0KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wIj4NCiAgICA8dGl0bGU+RHluYW1pYyBNdWx0aS1Gb3JtdWxhIEZ1bmN0aW9uPC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNkOWQ2Y2Y7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1NlZ29lIFVJJywgJ1JvYm90bycsICdOb3RvIFNhbnMnLCBzeXN0ZW0tdWksIHNhbnMtc2VyaWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyNHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzZkMmUyZTsNCiAgICAgICAgICAgIG1heC13aWR0aDogODYwcHg7DQogICAgICAgICAgICB3aWR0aDogMTAwJTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDI0cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDEycHggMjRweCByZ2JhKDAsIDAsIDAsIDAuMik7DQogICAgICAgICAgICBwYWRkaW5nOiAycmVtIDJyZW07DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjOWI2YTVjOw0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggcCB7DQogICAgICAgICAgICBjb2xvcjogI2YwZTJkNDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMS4wNXJlbTsNCiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjY1Ow0KICAgICAgICAgICAgdGV4dC1hbGlnbjoganVzdGlmeTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA0MDA7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMC4ycHg7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgIH0NCg0KICAgICAgICAuaGlnaGxpZ2h0IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmNWM1NDI7DQogICAgICAgICAgICBjb2xvcjogIzNhMWExYTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICAgICAgICAgcGFkZGluZzogMC4xcmVtIDAuM3JlbTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnQ291cmllciBOZXcnLCBtb25vc3BhY2U7DQogICAgICAgIH0NCg0KICAgICAgICBjb2RlIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0YTFlMWU7DQogICAgICAgICAgICBjb2xvcjogI2Y1ZTJjZTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDAuMnJlbSAwLjRyZW07DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgbW9ub3NwYWNlOw0KICAgICAgICB9DQogICAgPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5Pg0KPGRpdiBjbGFzcz0ibWFyb29uLWJveCI+DQogICAgPHA+DQogICAgICAgIEEgZHluYW1pYyBtdWx0aS1mb3JtdWxhIGZ1bmN0aW9uIGxpa2UgPGNvZGU+Y29tcHV0ZV9mb3JtdWxhKHgsIGZvcm11bGEpPC9jb2RlPiBlbmFibGVzIGEgc2luZ2xlIHJvdXRpbmUgdG8gZXZhbHVhdGUgZGlmZmVyZW50IG1hdGhlbWF0aWNhbCBleHByZXNzaW9ucyBieSBzZWxlY3RpbmcgdGhlIGFwcHJvcHJpYXRlIGZvcm11bGEgdHlwZS4gSXQgc3VwcG9ydHMgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+bGluZWFyPC9zcGFuPiA8Y29kZT4oeSA9IDV4ICsgMTApPC9jb2RlPiwgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+cXVhZHJhdGljPC9zcGFuPiA8Y29kZT4oeSA9IDAuM3jCsik8L2NvZGU+LCA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5jdWJpYzwvc3Bhbj4gPGNvZGU+KHkgPSAwLjAyeMKzKTwvY29kZT4sIGFuZCA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5leHBvbmVudGlhbDwvc3Bhbj4gPGNvZGU+KHkgPSAxLjLLoyk8L2NvZGU+IGZvcm11bGFzLiBXaGVuIGludm9rZWQsIHRoZSBmdW5jdGlvbiBjaGVja3MgdGhlIGdpdmVuIGZvcm11bGEgaWRlbnRpZmllciDigJQgZm9yIGxpbmVhciBpdCByZXR1cm5zIDxjb2RlPjV4ICsgMTA8L2NvZGU+LCBmb3IgcXVhZHJhdGljIGl0IGNvbXB1dGVzIDxjb2RlPjAuM3jCsjwvY29kZT4sIGZvciBjdWJpYyA8Y29kZT4wLjAyeMKzPC9jb2RlPiwgYW5kIGZvciBleHBvbmVudGlhbCA8Y29kZT4xLjIgcmFpc2VkIHRvIHRoZSBwb3dlciB4PC9jb2RlPi4gVGhpcyBhcHByb2FjaCBrZWVwcyB0aGUgY29kZSBmbGV4aWJsZSwgcmV1c2FibGUsIGFuZCBjbGVhbjsgeW91IG9ubHkgY2hhbmdlIHRoZSBmb3JtdWxhIHBhcmFtZXRlciB3aXRob3V0IHJld3JpdGluZyBsb2dpYywgbWFraW5nIGl0IGlkZWFsIGZvciBzaW11bGF0aW9ucywgZGF0YSBtb2RlbGluZywgYW5kIGVkdWNhdGlvbmFsIHRvb2xzLg0KICAgIDwvcD4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCiMjIE5lc3RlZCBsb29wcyB0byBjb21wdXRlIG11bHRpcGxlIGZvcm11bGFzIGF0IG9uY2UNCg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoRFQpDQoNCmNvbXB1dGVfZm9ybXVsYSA8LSBmdW5jdGlvbih4LCBmb3JtdWxhcykgew0KICByZXN1bHRzIDwtIGxpc3QoKQ0KICANCiAgdmFsaWRfZm9ybXVsYXMgPC0gYygibGluZWFyIiwicXVhZHJhdGljIiwiY3ViaWMiLCJleHBvbmVudGlhbCIpDQogIA0KICAjIE91dGVyIGxvb3Ag4oaSIGZvcm11bGEgdHlwZQ0KICBmb3IgKGYgaW4gZm9ybXVsYXMpIHsNCiAgICANCiAgICAjIFZBTElEQVNJIElOUFVUDQogICAgaWYgKCEoZiAlaW4lIHZhbGlkX2Zvcm11bGFzKSkgew0KICAgICAgd2FybmluZyhwYXN0ZSgiRm9ybXVsYSIsIGYsICJpcyBub3QgdmFsaWQgYW5kIHdpbGwgYmUgc2tpcHBlZCIpKQ0KICAgICAgbmV4dA0KICAgIH0NCiAgICANCiAgICB5X3ZhbHVlcyA8LSBudW1lcmljKGxlbmd0aCh4KSkNCiAgICANCiAgICAjIElubmVyIGxvb3Ag4oaSIHggdmFsdWVzDQogICAgZm9yIChpIGluIHNlcV9hbG9uZyh4KSkgew0KICAgICAgDQogICAgICBpZiAoZiA9PSAibGluZWFyIikgew0KICAgICAgICB5X3ZhbHVlc1tpXSA8LSA1KnhbaV0gKyAxMA0KICAgICAgICANCiAgICAgIH0gZWxzZSBpZiAoZiA9PSAicXVhZHJhdGljIikgew0KICAgICAgICB5X3ZhbHVlc1tpXSA8LSAwLjMqKHhbaV1eMikNCiAgICAgICAgDQogICAgICB9IGVsc2UgaWYgKGYgPT0gImN1YmljIikgew0KICAgICAgICB5X3ZhbHVlc1tpXSA8LSAwLjAyKih4W2ldXjMpDQogICAgICAgIA0KICAgICAgfSBlbHNlIGlmIChmID09ICJleHBvbmVudGlhbCIpIHsNCiAgICAgICAgeV92YWx1ZXNbaV0gPC0gMS4yXnhbaV0NCiAgICAgIH0NCiAgICB9DQogICAgDQogICAgcmVzdWx0c1tbZl1dIDwtIHlfdmFsdWVzDQogIH0NCiAgDQogIHJldHVybihyZXN1bHRzKQ0KfQ0KDQojIERhdGEgeA0KeCA8LSAxOjIwDQoNCiMgSmFsYW5rYW4gZnVuY3Rpb24NCmhhc2lsIDwtIGNvbXB1dGVfZm9ybXVsYSh4LCBjKCJsaW5lYXIiLCJxdWFkcmF0aWMiLCJjdWJpYyIsImV4cG9uZW50aWFsIikpDQoNCiMgQ29tYmluZSBpbnRvIG9uZSBsYXJnZSB0YWJsZSANCmFsbF9kYXRhIDwtIGRhdGEuZnJhbWUoKQ0KDQpmb3IgKG5hbWUgaW4gbmFtZXMoaGFzaWwpKSB7DQogIHRlbXAgPC0gZGF0YS5mcmFtZSgNCiAgICB4ID0geCwNCiAgICB5ID0gaGFzaWxbW25hbWVdXSwNCiAgICBmb3JtdWxhID0gbmFtZQ0KICApDQogIA0KICBhbGxfZGF0YSA8LSByYmluZChhbGxfZGF0YSwgdGVtcCkNCn0NCg0KIyBEaXNwbGF5IGludGVyYWN0aXZlIHRhYmxlDQpkYXRhdGFibGUoDQogIGFsbF9kYXRhLA0KICBvcHRpb25zID0gbGlzdCgNCiAgICBwYWdlTGVuZ3RoID0gMTAsDQogICAgYXV0b1dpZHRoID0gVFJVRQ0KICApLA0KICBjYXB0aW9uID0gIlRhYmxlIG9mIENhbGN1bGF0aW9uIFJlc3VsdHMgZm9yIEFsbCBGb3JtdWxhcyINCikNCmBgYA0KDQo8ZGl2IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNGRkY5QzQ7IHBhZGRpbmc6MTVweDsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3JkZXI6MXB4IHNvbGlkICNGREQ4MzU7IG1hcmdpbi10b3A6MTBweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPg0KDQoqKkludGVycHJldGF0aW9uKiogDQoNClRoZSBuZXN0ZWQgbG9vcCBzdWNjZXNzZnVsbHkgZ2VuZXJhdGVzIDgwIGRhdGEgcG9pbnRzIGJ5IGNvbXB1dGluZyBmb3VyIGZvcm11bGFzIChsaW5lYXIsIHF1YWRyYXRpYywgY3ViaWMsIGFuZCBleHBvbmVudGlhbCkgZm9yIHZhbHVlcyBvZiAoeCkgZnJvbSAxIHRvIDIwLiBUaGUgcmVzdWx0cyBzaG93IGNsZWFyIGRpZmZlcmVuY2VzIGluIGdyb3d0aCBwYXR0ZXJuczogdGhlIGxpbmVhciBmdW5jdGlvbiBpbmNyZWFzZXMgc3RlYWRpbHksIHRoZSBxdWFkcmF0aWMgYW5kIGN1YmljIGZ1bmN0aW9ucyBncm93IGF0IGFuIGFjY2VsZXJhdGluZyByYXRlLCBhbmQgdGhlIGV4cG9uZW50aWFsIGZ1bmN0aW9uIGluY3JlYXNlcyB0aGUgZmFzdGVzdCBhcyAoeCkgYmVjb21lcyBsYXJnZXIuIEJ5IG9yZ2FuaXppbmcgYWxsIHJlc3VsdHMgaW50byBhIHNpbmdsZSBkYXRhc2V0LCB0aGUgcHJvZ3JhbSBhbGxvd3MgZWFzeSBjb21wYXJpc29uIGJldHdlZW4gZm9ybXVsYXMgYW5kIGRlbW9uc3RyYXRlcyBob3cgbmVzdGVkIGxvb3BzIGNhbiBlZmZpY2llbnRseSBoYW5kbGUgcmVwZXRpdGl2ZSBjYWxjdWxhdGlvbnMgYW5kIHByb2R1Y2Ugc3RydWN0dXJlZCBvdXRwdXRzLg0KDQo8L2Rpdj4NCg0KIyMgVmFsaWRhdGUgRm9ybXVsYSBJbnB1dA0KDQpgYGB7PWh0bWx9DQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sIGxhbmc9ImlkIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4NCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogICAgPHRpdGxlPklucHV0IFZhbGlkYXRpb24gLSBIaWdobGlnaHQgS29kZTwvdGl0bGU+DQogICAgPHN0eWxlPg0KICAgICAgICAqIHsNCiAgICAgICAgICAgIG1hcmdpbjogMDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDA7DQogICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94Ow0KICAgICAgICB9DQoNCiAgICAgICAgYm9keSB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZDlkNmNmOw0KICAgICAgICAgICAgbWluLWhlaWdodDogMTAwdmg7DQogICAgICAgICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdTZWdvZSBVSScsICdSb2JvdG8nLCAnTm90byBTYW5zJywgc3lzdGVtLXVpLCBzYW5zLXNlcmlmOw0KICAgICAgICAgICAgcGFkZGluZzogMjRweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5tYXJvb24tYm94IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM2ZDJlMmU7DQogICAgICAgICAgICBtYXgtd2lkdGg6IDg2MHB4Ow0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAyNHB4Ow0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAxMnB4IDI0cHggcmdiYSgwLCAwLCAwLCAwLjIpOw0KICAgICAgICAgICAgcGFkZGluZzogMnJlbSAycmVtOw0KICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgIzliNmE1YzsNCiAgICAgICAgfQ0KDQogICAgICAgIC5tYXJvb24tYm94IHAgew0KICAgICAgICAgICAgY29sb3I6ICNmMGUyZDQ7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDVyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS42NTsNCiAgICAgICAgICAgIHRleHQtYWxpZ246IGp1c3RpZnk7DQogICAgICAgICAgICBmb250LXdlaWdodDogNDAwOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDAuMnB4Ow0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICB9DQoNCiAgICAgICAgLmhpZ2hsaWdodCB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjVjNTQyOw0KICAgICAgICAgICAgY29sb3I6ICMzYTFhMWE7DQogICAgICAgICAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDAuMXJlbSAwLjNyZW07DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgbW9ub3NwYWNlOw0KICAgICAgICB9DQoNCiAgICAgICAgY29kZSB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGExZTFlOw0KICAgICAgICAgICAgY29sb3I6ICNmNWUyY2U7DQogICAgICAgICAgICBwYWRkaW5nOiAwLjJyZW0gMC40cmVtOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNnB4Ow0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdDb3VyaWVyIE5ldycsIG1vbm9zcGFjZTsNCiAgICAgICAgfQ0KICAgIDwvc3R5bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCjxkaXYgY2xhc3M9Im1hcm9vbi1ib3giPg0KICAgIDxwPg0KICAgICAgICBJbnB1dCB2YWxpZGF0aW9uIGhhcyBhbHJlYWR5IGJlZW4gaW1wbGVtZW50ZWQgaW4gdGhlIHByb2dyYW0sIHdoZXJlIHRoZSBmdW5jdGlvbiBjaGVja3Mgd2hldGhlciBlYWNoIGZvcm11bGEgdHlwZSBpcyB2YWxpZCBieSBjb21wYXJpbmcgaXQgd2l0aCBhIHByZWRlZmluZWQgbGlzdCBvZiBhbGxvd2VkIGZvcm11bGFzIChsaW5lYXIsIHF1YWRyYXRpYywgY3ViaWMsIGFuZCBleHBvbmVudGlhbCk7IGlmIGFuIGludmFsaWQgaW5wdXQgaXMgZGV0ZWN0ZWQsIHRoZSBwcm9ncmFtIGdlbmVyYXRlcyBhIHdhcm5pbmcgbWVzc2FnZSB1c2luZyA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij53YXJuaW5nKCk8L3NwYW4+IGFuZCBza2lwcyB0aGUgaW5jb3JyZWN0IGZvcm11bGEgd2l0aCA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5uZXh0PC9zcGFuPiwgYWxsb3dpbmcgdGhlIGZ1bmN0aW9uIHRvIGNvbnRpbnVlIHByb2Nlc3Npbmcgb25seSB2YWxpZCBpbnB1dHMsIGFzIGluZGljYXRlZCBieSB0aGUgY29uZGl0aW9uYWwgY2hlY2sgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+aWYgKCEoZiAlaW4lIHZhbGlkX2Zvcm11bGFzKSk8L3NwYW4+Lg0KICAgIDwvcD4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCiMjIFBsb3QgYWxsIGZvcm11bGFzIG9uIHNhbWUgZ3JhcGggZm9yIHggPSAxOjIwDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00fQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBQbG90IGdncGxvdCAoZGFyayBtb2RlKQ0KcCA8LSBnZ3Bsb3QoYWxsX2RhdGEsIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gZm9ybXVsYSkpICsNCiAgZ2VvbV9saW5lKHNpemUgPSAxLjMpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygNCiAgICAibGluZWFyIiA9ICIjMDBGNUZGIiwgICAgICAjIGN5YW4gbmVvbg0KICAgICJxdWFkcmF0aWMiID0gIiMzOUZGMTQiLCAgICMgbmVvbiBncmVlbg0KICAgICJjdWJpYyIgPSAiI0ZGNkVDNyIsICAgICAgICMgbmVvbiBwaW5rDQogICAgImV4cG9uZW50aWFsIiA9ICIjRkZENzAwIiAgIyBuZW9uIHllbGxvdw0KICApKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBNYXRoZW1hdGljYWwgRm9ybXVsYXMiLA0KICAgIHggPSAiVmFsdWUgb2YgeCIsDQogICAgeSA9ICJSZXN1bHQgKHkpIiwNCiAgICBjb2xvciA9ICJGb3JtdWxhIFR5cGUiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiMwRDBEMEQiLCBjb2xvciA9IE5BKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiIzBEMEQwRCIsIGNvbG9yID0gTkEpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiIzJBMkEyQSIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiIzFBMUExQSIpLA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiI0NDQ0NDQyIpLA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiIzBEMEQwRCIpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjMEQwRDBEIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYpDQogICkNCg0KIyBJbnRlcmFrdGlmDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCjxkaXYgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0ZGRjlDNDsgcGFkZGluZzoxNXB4OyBib3JkZXItcmFkaXVzOjEwcHg7IGJvcmRlcjoxcHggc29saWQgI0ZERDgzNTsgbWFyZ2luLXRvcDoxMHB4OyB0ZXh0LWFsaWduOiBqdXN0aWZ5OyI+DQoNCioqSW50ZXJwcmV0YXRpb24qKiANCg0KVGhlIHZpc3VhbGl6YXRpb24gY29tcGFyZXMgbGluZWFyLCBxdWFkcmF0aWMsIGN1YmljLCBhbmQgZXhwb25lbnRpYWwgZnVuY3Rpb25zIG92ZXIgdGhlIHJhbmdlICggeCA9IDEgKSB0byAoIDIwICksIGhpZ2hsaWdodGluZyBkaXN0aW5jdCBncm93dGggcGF0dGVybnMuIFRoZSBsaW5lYXIgZnVuY3Rpb24gZGVtb25zdHJhdGVzIGEgY29uc3RhbnQgYW5kIHN0YWJsZSByYXRlIG9mIGluY3JlYXNlLCB3aGlsZSB0aGUgcXVhZHJhdGljIGFuZCBjdWJpYyBmdW5jdGlvbnMgZXhoaWJpdCBwcm9ncmVzc2l2ZWx5IGFjY2VsZXJhdGluZyBncm93dGgsIHdpdGggdGhlIGN1YmljIGZ1bmN0aW9uIGluY3JlYXNpbmcgbW9yZSByYXBpZGx5IGF0IGhpZ2hlciB2YWx1ZXMgb2YgKCB4ICkuIEluIGNvbnRyYXN0LCB0aGUgZXhwb25lbnRpYWwgZnVuY3Rpb24gc2hvd3MgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgYW5kIHJhcGlkIGdyb3d0aCwgZXNwZWNpYWxseSBhcyAoIHggKSBiZWNvbWVzIGxhcmdlLiBPdmVyYWxsLCB0aGUgcmVzdWx0cyBpbmRpY2F0ZSB0aGF0IGFzIHRoZSBjb21wbGV4aXR5IG9mIHRoZSBmdW5jdGlvbiBpbmNyZWFzZXMsIHRoZSByYXRlIG9mIGNoYW5nZSBiZWNvbWVzIG1vcmUgcHJvbm91bmNlZCwgd2l0aCBleHBvbmVudGlhbCBncm93dGggZG9taW5hdGluZyBhbmQgcHJvZHVjaW5nIHN1YnN0YW50aWFsbHkgbGFyZ2VyIG91dHB1dHMgY29tcGFyZWQgdG8gdGhlIG90aGVyIGZ1bmN0aW9ucy4NCg0KPC9kaXY+DQoNCg0KIyBOZXN0ZWQgU2ltdWxhdGlvbjogTXVsdGktU2FsZXMgJiBEaXNjb3VudHMNCg0KYGBgez1odG1sfQ0KPCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJlbiI+DQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+DQogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPg0KICAgIDx0aXRsZT5TaW11bGF0ZSBTYWxlcyBGdW5jdGlvbiAtIEZvcm1hbCBFeHBsYW5hdGlvbjwvdGl0bGU+DQogICAgPHN0eWxlPg0KICAgICAgICAqIHsNCiAgICAgICAgICAgIG1hcmdpbjogMDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDA7DQogICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94Ow0KICAgICAgICB9DQoNCiAgICAgICAgYm9keSB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZDlkNmNmOw0KICAgICAgICAgICAgbWluLWhlaWdodDogMTAwdmg7DQogICAgICAgICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdTZWdvZSBVSScsICdSb2JvdG8nLCAnTm90byBTYW5zJywgc3lzdGVtLXVpLCBzYW5zLXNlcmlmOw0KICAgICAgICAgICAgcGFkZGluZzogMjRweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5tYXJvb24tYm94IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM2ZDJlMmU7DQogICAgICAgICAgICBtYXgtd2lkdGg6IDg2MHB4Ow0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAyNHB4Ow0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAxMnB4IDI0cHggcmdiYSgwLCAwLCAwLCAwLjIpOw0KICAgICAgICAgICAgcGFkZGluZzogMnJlbSAycmVtOw0KICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgIzliNmE1YzsNCiAgICAgICAgfQ0KDQogICAgICAgIC5tYXJvb24tYm94IHAgew0KICAgICAgICAgICAgY29sb3I6ICNmMGUyZDQ7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDVyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS42NTsNCiAgICAgICAgICAgIHRleHQtYWxpZ246IGp1c3RpZnk7DQogICAgICAgICAgICBmb250LXdlaWdodDogNDAwOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDAuMnB4Ow0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICB9DQoNCiAgICAgICAgLmhpZ2hsaWdodCB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjVjNTQyOw0KICAgICAgICAgICAgY29sb3I6ICMzYTFhMWE7DQogICAgICAgICAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDAuMXJlbSAwLjNyZW07DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgbW9ub3NwYWNlOw0KICAgICAgICB9DQoNCiAgICAgICAgY29kZSB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGExZTFlOw0KICAgICAgICAgICAgY29sb3I6ICNmNWUyY2U7DQogICAgICAgICAgICBwYWRkaW5nOiAwLjJyZW0gMC40cmVtOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNnB4Ow0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdDb3VyaWVyIE5ldycsIG1vbm9zcGFjZTsNCiAgICAgICAgfQ0KICAgIDwvc3R5bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCjxkaXYgY2xhc3M9Im1hcm9vbi1ib3giPg0KICAgIDxwPg0KICAgICAgICBJbiB0aGlzIHNlZ21lbnQsIHdlIGRpc2N1c3MgdGhlIDxjb2RlPnNpbXVsYXRlX3NhbGVzKG5fc2FsZXNwZXJzb24sIGRheXMpPC9jb2RlPiBmdW5jdGlvbiwgd2hpY2ggZ2VuZXJhdGVzIGZvdXIgY29sdW1uczogPGNvZGU+c2FsZXNfaWQ8L2NvZGU+LCA8Y29kZT5kYXk8L2NvZGU+LCA8Y29kZT5zYWxlc19hbW91bnQ8L2NvZGU+LCBhbmQgPGNvZGU+ZGlzY291bnRfcmF0ZTwvY29kZT4uIFRoaXMgZnVuY3Rpb24gY29udGFpbnMgYSA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5uZXN0ZWQgZnVuY3Rpb248L3NwYW4+IHJlc3BvbnNpYmxlIGZvciBjYWxjdWxhdGluZyBjdW11bGF0aXZlIHNhbGVzIHBlciBzYWxlc3BlcnNvbi4gU3Vic2VxdWVudGx5LCB0aGUgZnVuY3Rpb24gYXBwbGllcyA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5jb25kaXRpb25hbCBkaXNjb3VudHM8L3NwYW4+LCB3aGVyZSB0aGUgZGlzY291bnQgcmF0ZSBpcyBkZXRlcm1pbmVkIGJhc2VkIG9uIHRoZSB2YWx1ZSBvZiA8Y29kZT5zYWxlc19hbW91bnQ8L2NvZGU+LiBUaGUgcHJvY2VzcyBpcyBleGVjdXRlZCBieSBpdGVyYXRpbmcgdGhyb3VnaCBlYWNoIHNhbGVzcGVyc29uIHVzaW5nIGEgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+bG9vcDwvc3Bhbj4uIEZpbmFsbHksIHRoZSBmdW5jdGlvbiBhbHNvIHByb3ZpZGVzIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPnN1bW1hcnkgc3RhdGlzdGljczwvc3Bhbj4gYW5kIGEgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+Y3VtdWxhdGl2ZSBzYWxlcyBwbG90PC9zcGFuPiB0byBmYWNpbGl0YXRlIHRoZSBhbmFseXNpcyBvZiBzYWxlcyB0cmVuZHMgb3ZlciB0aW1lLg0KICAgIDwvcD4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCiMjIE5lc3RlZCBmdW5jdGlvbiB0byBjYWxjdWxhdGUgY3VtdWxhdGl2ZSBzYWxlcyBwZXIgc2FsZXNwZXJzb24gDQoNCmBgYHs9aHRtbH0NCjwhRE9DVFlQRSBodG1sPg0KPGh0bWwgbGFuZz0iZW4iPg0KPGhlYWQ+DQogICAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPg0KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wIj4NCiAgICA8dGl0bGU+TmVzdGVkIEZ1bmN0aW9uIC0gQ3VtdWxhdGl2ZSBTYWxlczwvdGl0bGU+DQogICAgPHN0eWxlPg0KICAgICAgICAqIHsNCiAgICAgICAgICAgIG1hcmdpbjogMDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDA7DQogICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94Ow0KICAgICAgICB9DQoNCiAgICAgICAgYm9keSB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZDlkNmNmOw0KICAgICAgICAgICAgbWluLWhlaWdodDogMTAwdmg7DQogICAgICAgICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdTZWdvZSBVSScsICdSb2JvdG8nLCAnTm90byBTYW5zJywgc3lzdGVtLXVpLCBzYW5zLXNlcmlmOw0KICAgICAgICAgICAgcGFkZGluZzogMjRweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jcmVhbS1ib3ggew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZkZmFmNjsNCiAgICAgICAgICAgIG1heC13aWR0aDogODYwcHg7DQogICAgICAgICAgICB3aWR0aDogMTAwJTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDI0cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDEycHggMjRweCByZ2JhKDAsIDAsIDAsIDAuMik7DQogICAgICAgICAgICBwYWRkaW5nOiAycmVtIDJyZW07DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjYjg4NjBiOw0KICAgICAgICB9DQoNCiAgICAgICAgLmNyZWFtLWJveCBwIHsNCiAgICAgICAgICAgIGNvbG9yOiAjMmMxODEwOw0KICAgICAgICAgICAgZm9udC1zaXplOiAxLjA1cmVtOw0KICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDEuNjU7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDQwMDsNCiAgICAgICAgICAgIGxldHRlci1zcGFjaW5nOiAwLjJweDsNCiAgICAgICAgICAgIG1hcmdpbjogMDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5oaWdobGlnaHQgew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2Y1YzU0MjsNCiAgICAgICAgICAgIGNvbG9yOiAjM2ExYTFhOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgICAgICAgICBwYWRkaW5nOiAwLjFyZW0gMC4zcmVtOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNnB4Ow0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdDb3VyaWVyIE5ldycsIG1vbm9zcGFjZTsNCiAgICAgICAgfQ0KDQogICAgICAgIGNvZGUgew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzJkMmExZTsNCiAgICAgICAgICAgIGNvbG9yOiAjZjJlNmM5Ow0KICAgICAgICAgICAgcGFkZGluZzogMC4ycmVtIDAuNHJlbTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnQ291cmllciBOZXcnLCBtb25vc3BhY2U7DQogICAgICAgIH0NCiAgICA8L3N0eWxlPg0KPC9oZWFkPg0KPGJvZHk+DQo8ZGl2IGNsYXNzPSJjcmVhbS1ib3giPg0KICAgIDxwPg0KICAgICAgICBBIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPm5lc3RlZCBmdW5jdGlvbjwvc3Bhbj4gaXMgdXNlZCB0byBjYWxjdWxhdGUgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+Y3VtdWxhdGl2ZSBzYWxlcyBwZXIgc2FsZXNwZXJzb248L3NwYW4+IGJlY2F1c2UgaXQgYWxsb3dzIHRoZSBjdW11bGF0aXZlIHN1bSBsb2dpYyB0byBiZSBlbmNhcHN1bGF0ZWQgaW5zaWRlIHRoZSBtYWluIGZ1bmN0aW9uLCBrZWVwaW5nIHRoZSBjb2RlIG9yZ2FuaXplZCBhbmQgcmV1c2FibGUuIEJ5IGFwcGx5aW5nIHRoaXMgbmVzdGVkIGZ1bmN0aW9uIHRvIGVhY2ggc2FsZXNwZXJzb24gaW5kaXZpZHVhbGx5IHRocm91Z2ggYSA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5sb29wPC9zcGFuPiwgdGhlIHByb2dyYW0gY2FuIHRyYWNrIHRoZSBydW5uaW5nIHRvdGFsIG9mIHNhbGVzIGRheSBieSBkYXkgZm9yIGV2ZXJ5IHNhbGVzcGVyc29uIHNlcGFyYXRlbHksIHdpdGhvdXQgbWl4aW5nIHZhbHVlcyBiZXR3ZWVuIGRpZmZlcmVudCBzYWxlc3BlcnNvbnMuIFRoaXMgYXBwcm9hY2ggaXMgdXNlZnVsIGZvciA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5pZGVudGlmeWluZyBwZXJmb3JtYW5jZSB0cmVuZHM8L3NwYW4+LCBtb25pdG9yaW5nIHByb2dyZXNzIHRvd2FyZCBzYWxlcyB0YXJnZXRzLCBhbmQgY29tcGFyaW5nIHdoaWNoIHNhbGVzcGVyc29ucyBhcmUgY29uc2lzdGVudGx5IGdyb3dpbmcgdGhlaXIgc2FsZXMgb3ZlciB0aW1lLiBBZGRpdGlvbmFsbHksIHRoZSBuZXN0ZWQgc3RydWN0dXJlIG1ha2VzIHRoZSBjb2RlIGVhc2llciB0byBkZWJ1ZyBhbmQgbWFpbnRhaW4sIGFzIHRoZSBjdW11bGF0aXZlIGNhbGN1bGF0aW9uIGxvZ2ljIGlzIGlzb2xhdGVkIGZyb20gdGhlIG1haW4gZGF0YSBwcm9jZXNzaW5nIHdvcmtmbG93Lg0KICAgIDwvcD4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCiMjIEFwcGx5IGNvbmRpdGlvbmFsIGRpc2NvdW50cyBiYXNlZCBvbiBzYWxlcyBhbW91bnQNCg0KYGBgez1odG1sfQ0KPCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJpZCI+DQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+DQogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPg0KICAgIDx0aXRsZT5EaXNjb3VudCBNZWNoYW5pc208L3RpdGxlPg0KICAgIDxzdHlsZT4NCiAgICAgICAgKiB7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgICAgICBwYWRkaW5nOiAwOw0KICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDsNCiAgICAgICAgfQ0KDQogICAgICAgIGJvZHkgew0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgJ1RpbWVzIE5ldyBSb21hbicsIFRpbWVzLCBzZXJpZjsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzZTBiMGIgMCUsICMxYTAxMDEgMTAwJSk7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBwYWRkaW5nOiAyMHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRhaW5lciB7DQogICAgICAgICAgICBtYXgtd2lkdGg6IDkwMHB4Ow0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZmRmYWY2Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTZweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMjBweCA0MHB4IHJnYmEoMCwwLDAsMC40KTsNCiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjYjg4NjBiOw0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRlbnQgew0KICAgICAgICAgICAgcGFkZGluZzogNDBweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5kZXNjcmlwdGlvbiB7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDJyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS43Ow0KICAgICAgICAgICAgY29sb3I6ICMyYzE4MTA7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KICAgICAgICAgICAgbWFyZ2luLWJvdHRvbTogMzVweDsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNmZmY5ZWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyNXB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTJweDsNCiAgICAgICAgICAgIGJvcmRlci1sZWZ0OiA1cHggc29saWQgI2I4ODYwYjsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMnB4IDhweCByZ2JhKDAsMCwwLDAuMDUpOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdQYWxhdGlubycsICdHZW9yZ2lhJywgc2VyaWY7DQogICAgICAgIH0NCg0KICAgICAgICAuZGVzY3JpcHRpb24gc3Ryb25nIHsNCiAgICAgICAgICAgIGNvbG9yOiAjOGIxYTFhOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDcwMDsNCiAgICAgICAgfQ0KDQogICAgICAgIC50aWVyLXRhYmxlIHsNCiAgICAgICAgICAgIHdpZHRoOiAxMDAlOw0KICAgICAgICAgICAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTsNCiAgICAgICAgICAgIG1hcmdpbjogMjVweCAwOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTJweDsNCiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDVweCAxNXB4IHJnYmEoMCwwLDAsMC4xKTsNCiAgICAgICAgfQ0KDQogICAgICAgIC50aWVyLXRhYmxlIHRoIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICM2YjFhMWEgMCUsICMzZTBhMGEgMTAwJSk7DQogICAgICAgICAgICBjb2xvcjogI2Q0YWYzNzsNCiAgICAgICAgICAgIHBhZGRpbmc6IDE1cHg7DQogICAgICAgICAgICBmb250LXdlaWdodDogNjAwOw0KICAgICAgICAgICAgZm9udC1zaXplOiAxcmVtOw0KICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgICAgICAgYm9yZGVyLWJvdHRvbTogMnB4IHNvbGlkICNkNGFmMzc7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMXB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLnRpZXItdGFibGUgdGQgew0KICAgICAgICAgICAgcGFkZGluZzogMTJweCAxNXB4Ow0KICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZmZmNmNTsNCiAgICAgICAgICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZThkYmJjOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDsNCiAgICAgICAgICAgIGNvbG9yOiAjMmMxODEwOw0KICAgICAgICB9DQoNCiAgICAgICAgLnRpZXItdGFibGUgdHI6aG92ZXIgdGQgew0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZjZjZlODsNCiAgICAgICAgICAgIHRyYW5zaXRpb246IDAuMnM7DQogICAgICAgIH0NCg0KICAgICAgICAudGllci10YWJsZSB0ZDpmaXJzdC1jaGlsZCB7DQogICAgICAgICAgICBmb250LXdlaWdodDogNjAwOw0KICAgICAgICAgICAgY29sb3I6ICM1YTBlMGU7DQogICAgICAgIH0NCg0KICAgICAgICAuZGlzY291bnQtYmFkZ2Ugew0KICAgICAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgI2I4ODYwYiAwJSwgI2Q0YWYzNyAxMDAlKTsNCiAgICAgICAgICAgIGNvbG9yOiAjMmMwNTA1Ow0KICAgICAgICAgICAgcGFkZGluZzogNXB4IDE0cHg7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAzMHB4Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7DQogICAgICAgICAgICBmb250LXNpemU6IDAuOXJlbTsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMXB4IDNweCByZ2JhKDAsMCwwLDAuMik7DQogICAgICAgIH0NCg0KICAgICAgICBoMyB7DQogICAgICAgICAgICBjb2xvcjogIzZiMWExYTsNCiAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IDE1cHg7DQogICAgICAgICAgICBmb250LXdlaWdodDogNjAwOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDFweDsNCiAgICAgICAgICAgIGJvcmRlci1sZWZ0OiA0cHggc29saWQgI2I4ODYwYjsNCiAgICAgICAgICAgIHBhZGRpbmctbGVmdDogMTVweDsNCiAgICAgICAgfQ0KDQogICAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA2MDBweCkgew0KICAgICAgICAgICAgLmNvbnRlbnQgew0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDIwcHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAudGllci10YWJsZSB0aCwgLnRpZXItdGFibGUgdGQgew0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDEwcHg7DQogICAgICAgICAgICAgICAgZm9udC1zaXplOiAwLjlyZW07DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICA8L3N0eWxlPg0KPC9oZWFkPg0KPGJvZHk+DQogICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4NCiAgICAgICAgPGRpdiBjbGFzcz0iY29udGVudCI+DQogICAgICAgICAgICA8ZGl2IGNsYXNzPSJkZXNjcmlwdGlvbiI+DQogICAgICAgICAgICAgICAgPHN0cm9uZz5EaXNjb3VudCBNZWNoYW5pc20gRGVzY3JpcHRpb246PC9zdHJvbmc+PGJyPjxicj4NCiAgICAgICAgICAgICAgICBUaGlzIGRlc2lnbiByZWZsZWN0cyBhIHN0ZXB3aXNlIGluY2VudGl2ZSBzeXN0ZW0gaW4gd2hpY2ggaGlnaGVyIHNhbGVzIHZhbHVlcyBjb3JyZXNwb25kIHRvIGhpZ2hlciBkaXNjb3VudCByYXRlcywgbWFpbnRhaW5pbmcgYSBjb25zaXN0ZW50IGFuZCBzY2FsYWJsZSBwcm9ncmVzc2lvbi4gU3VjaCBhbiBhcHByb2FjaCBkZW1vbnN0cmF0ZXMgdGhlIGFwcGxpY2F0aW9uIG9mIGNvbmRpdGlvbmFsIGxvZ2ljIHRvIGltcGxlbWVudCBhIHN0cnVjdHVyZWQgcHJpY2luZyBzdHJhdGVneSB0aGF0IHJld2FyZHMgaW5jcmVhc2VkIHNhbGVzIHBlcmZvcm1hbmNlLg0KICAgICAgICAgICAgPC9kaXY+DQoNCiAgICAgICAgICAgIDxoMz5EaXNjb3VudCBUaWVyIFN0cnVjdHVyZTwvaDM+DQogICAgICAgICAgICA8dGFibGUgY2xhc3M9InRpZXItdGFibGUiPg0KICAgICAgICAgICAgICAgIDx0aGVhZD4NCiAgICAgICAgICAgICAgICAgICAgPHRyPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRoPlNhbGVzIEFtb3VudCAoVW5pdHMvVmFsdWUpPC90aD4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5EaXNjb3VudCBSYXRlPC90aD4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5JbmNlbnRpdmUgVHlwZTwvdGg+DQogICAgICAgICAgICAgICAgICAgIDwvdHI+DQogICAgICAgICAgICAgICAgPC90aGVhZD4NCiAgICAgICAgICAgICAgICA8dGJvZHk+DQogICAgICAgICAgICAgICAgICAgIDx0cj4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD4g4omkIDI1MCA8L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzcGFuIGNsYXNzPSJkaXNjb3VudC1iYWRnZSI+MTIlPC9zcGFuPjwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+QmFzaWMgSW5jZW50aXZlPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICAgICAgPHRyPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPiAyNTAgJiDiiaQgNTAwIDwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PHNwYW4gY2xhc3M9ImRpc2NvdW50LWJhZGdlIj4yNCU8L3NwYW4+PC90ZD4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5NaWQtTGV2ZWwgUmV3YXJkPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICAgICAgPHRyPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkID41MDAgPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48c3BhbiBjbGFzcz0iZGlzY291bnQtYmFkZ2UiPjM2JTwvc3Bhbj48L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPkhpZ2ggUGVyZm9ybWVyIEJvbnVzPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICA8L3Rib2R5Pg0KICAgICAgICAgICAgPC90YWJsZT4NCiAgICAgICAgPC9kaXY+DQogICAgPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KIyMgTG9vcCBwZXIgc2FsZXNwZXJzb24NCg0KYGBge3J9DQojIExvYWQgbGlicmFyeQ0KbGlicmFyeShEVCkNCg0KIyBGdW5jdGlvbiB0byBzaW11bGF0ZSBzYWxlcyBkYXRhIChkZWNpbWFsIHZhbHVlcykNCnNpbXVsYXRlX3NhbGVzIDwtIGZ1bmN0aW9uKG5fc2FsZXNwZXJzb24sIGRheXMpIHsNCiAgDQogIHNldC5zZWVkKDEyMykNCiAgDQogIGRhdGFfbGlzdCA8LSBsaXN0KCkNCiAgY291bnRlciA8LSAxDQogIA0KICAjIExvb3AgcGVyIHNhbGVzcGVyc29uDQogIGZvciAoc3AgaW4gMTpuX3NhbGVzcGVyc29uKSB7DQogICAgDQogICAgIyBMb29wIHBlciBkYXkNCiAgICBmb3IgKGQgaW4gMTpkYXlzKSB7DQogICAgICANCiAgICAgICMgR2VuZXJhdGUgZGVjaW1hbCBzYWxlcyBhbW91bnQgKDEwMCAtIDgwMCkNCiAgICAgIHNhbGVzX2Ftb3VudCA8LSByb3VuZChydW5pZigxLCBtaW4gPSAxMDAsIG1heCA9IDgwMCksIDIpDQogICAgICANCiAgICAgIGRhdGFfbGlzdFtbY291bnRlcl1dIDwtIGRhdGEuZnJhbWUoDQogICAgICAgIHNhbGVzX2lkID0gcGFzdGUwKCJTUF8iLCBzcCksDQogICAgICAgIGRheSA9IGQsDQogICAgICAgIHNhbGVzX2Ftb3VudCA9IHNhbGVzX2Ftb3VudA0KICAgICAgKQ0KICAgICAgDQogICAgICBjb3VudGVyIDwtIGNvdW50ZXIgKyAxDQogICAgfQ0KICB9DQogIA0KICAjIENvbWJpbmUgYWxsIGRhdGENCiAgc2FsZXNfZGF0YSA8LSBkby5jYWxsKHJiaW5kLCBkYXRhX2xpc3QpDQogIA0KICByZXR1cm4oc2FsZXNfZGF0YSkNCn0NCg0KIyBHZW5lcmF0ZSBkYXRhICgxNSBzYWxlc3BlcnNvbiwgNyBkYXlzKQ0Kc2FsZXNfZGF0YSA8LSBzaW11bGF0ZV9zYWxlcyg4LCA3KQ0KDQojIFNob3cgaW50ZXJhY3RpdmUgdGFibGUNCmRhdGF0YWJsZShzYWxlc19kYXRhKQ0KYGBgDQoNCiMjIyBBcHBseSBjb25kaXRpb25hbCBkaXNjb3VudHMNCg0KYGBge3J9DQojIExvYWQgbGlicmFyeQ0KbGlicmFyeShEVCkNCg0KIyBGdW5jdGlvbiB0byBzaW11bGF0ZSBzYWxlcyBkYXRhICh3aXRoIGRpc2NvdW50KQ0Kc2ltdWxhdGVfc2FsZXMgPC0gZnVuY3Rpb24obl9zYWxlc3BlcnNvbiwgZGF5cykgew0KICANCiAgc2V0LnNlZWQoMTIzKQ0KICANCiAgZGF0YV9saXN0IDwtIGxpc3QoKQ0KICBjb3VudGVyIDwtIDENCiAgDQogICMgTG9vcCBwZXIgc2FsZXNwZXJzb24NCiAgZm9yIChzcCBpbiAxOm5fc2FsZXNwZXJzb24pIHsNCiAgICANCiAgICAjIExvb3AgcGVyIGRheQ0KICAgIGZvciAoZCBpbiAxOmRheXMpIHsNCiAgICAgIA0KICAgICAgIyBHZW5lcmF0ZSBkZWNpbWFsIHNhbGVzIGFtb3VudCAoMTAwIC0gODAwKQ0KICAgICAgc2FsZXNfYW1vdW50IDwtIHJvdW5kKHJ1bmlmKDEsIG1pbiA9IDEwMCwgbWF4ID0gODAwKSwgMikNCiAgICAgIA0KICAgICAgIyBBcHBseSBkaXNjb3VudCBydWxlcw0KICAgICAgaWYgKHNhbGVzX2Ftb3VudCA8PSAyNTApIHsNCiAgICAgICAgZGlzY291bnRfcmF0ZSA8LSAwLjEyDQogICAgICB9IGVsc2UgaWYgKHNhbGVzX2Ftb3VudCA8PSA1MDApIHsNCiAgICAgICAgZGlzY291bnRfcmF0ZSA8LSAwLjI0DQogICAgICB9IGVsc2Ugew0KICAgICAgICBkaXNjb3VudF9yYXRlIDwtIDAuMzYNCiAgICAgIH0NCiAgICAgIA0KICAgICAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UgZm9ybWF0DQogICAgICBkaXNjb3VudF9sYWJlbCA8LSBwYXN0ZTAoZGlzY291bnRfcmF0ZSAqIDEwMCwgIiUiKQ0KICAgICAgDQogICAgICBkYXRhX2xpc3RbW2NvdW50ZXJdXSA8LSBkYXRhLmZyYW1lKA0KICAgICAgICBzYWxlc19pZCA9IHBhc3RlMCgiU1BfIiwgc3ApLA0KICAgICAgICBkYXkgPSBkLA0KICAgICAgICBzYWxlc19hbW91bnQgPSBzYWxlc19hbW91bnQsDQogICAgICAgIGRpc2NvdW50X3JhdGUgPSBkaXNjb3VudF9sYWJlbA0KICAgICAgKQ0KICAgICAgDQogICAgICBjb3VudGVyIDwtIGNvdW50ZXIgKyAxDQogICAgfQ0KICB9DQogIA0KICAjIENvbWJpbmUgYWxsIGRhdGENCiAgc2FsZXNfZGF0YSA8LSBkby5jYWxsKHJiaW5kLCBkYXRhX2xpc3QpDQogIA0KICByZXR1cm4oc2FsZXNfZGF0YSkNCn0NCg0KIyBHZW5lcmF0ZSBkYXRhDQpzYWxlc19kYXRhIDwtIHNpbXVsYXRlX3NhbGVzKDgsIDcpDQoNCiMgU2hvdyBpbnRlcmFjdGl2ZSB0YWJsZQ0KZGF0YXRhYmxlKHNhbGVzX2RhdGEpDQpgYGANCiMjIFN1bW1hcnkgc3RhdHMgYW5kIGN1bXVsYXRpdmUgc2FsZXMgcGxvdA0KDQojIyMgU3VtbWFyeSBzdGF0cw0KDQpgYGB7PWh0bWx9DQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sIGxhbmc9ImlkIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4NCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogICAgPHRpdGxlPlN1bW1hcnkgU3RhdGlzdGljczwvdGl0bGU+DQogICAgPHN0eWxlPg0KICAgICAgICAqIHsNCiAgICAgICAgICAgIG1hcmdpbjogMDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDA7DQogICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94Ow0KICAgICAgICB9DQoNCiAgICAgICAgYm9keSB7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0dlb3JnaWEnLCAnVGltZXMgTmV3IFJvbWFuJywgVGltZXMsIHNlcmlmOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzNlMGIwYiAwJSwgIzFhMDEwMSAxMDAlKTsNCiAgICAgICAgICAgIG1pbi1oZWlnaHQ6IDEwMHZoOw0KICAgICAgICAgICAgZGlzcGxheTogZmxleDsNCiAgICAgICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICAgICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgICAgICAgICAgIHBhZGRpbmc6IDIwcHg7DQogICAgICAgIH0NCg0KICAgICAgICAuY29udGFpbmVyIHsNCiAgICAgICAgICAgIG1heC13aWR0aDogMTAwMHB4Ow0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZmRmYWY2Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTZweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMjBweCA0MHB4IHJnYmEoMCwwLDAsMC40KTsNCiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjYjg4NjBiOw0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRlbnQgew0KICAgICAgICAgICAgcGFkZGluZzogNDBweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5kZXNjcmlwdGlvbiB7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDJyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS43Ow0KICAgICAgICAgICAgY29sb3I6ICMyYzE4MTA7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZmZjllZjsNCiAgICAgICAgICAgIHBhZGRpbmc6IDI1cHg7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAxMnB4Ow0KICAgICAgICAgICAgYm9yZGVyLWxlZnQ6IDVweCBzb2xpZCAjYjg4NjBiOw0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAycHggOHB4IHJnYmEoMCwwLDAsMC4wNSk7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1BhbGF0aW5vJywgJ0dlb3JnaWEnLCBzZXJpZjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5kZXNjcmlwdGlvbiBzdHJvbmcgew0KICAgICAgICAgICAgY29sb3I6ICM4YjFhMWE7DQogICAgICAgICAgICBmb250LXdlaWdodDogNzAwOw0KICAgICAgICB9DQoNCiAgICAgICAgLyogZ2F5YSBzcGVjaWFsIHVudHVrIGZ1bmdzaSBSICovDQogICAgICAgIC5yLWZ1bmN0aW9uIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICMyZDJhMWU7DQogICAgICAgICAgICBjb2xvcjogI2YyZTZjOTsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnQ291cmllciBOZXcnLCAnRmlyYSBDb2RlJywgbW9ub3NwYWNlOw0KICAgICAgICAgICAgcGFkZGluZzogM3B4IDEwcHg7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAyMHB4Ow0KICAgICAgICAgICAgZm9udC1zaXplOiAwLjlyZW07DQogICAgICAgICAgICBmb250LXdlaWdodDogNTAwOw0KICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDAuM3B4Ow0KICAgICAgICAgICAgYm94LXNoYWRvdzogaW5zZXQgMCAwIDAgMXB4ICNiODg2MGIsIDAgMXB4IDJweCByZ2JhKDAsMCwwLDAuMSk7DQogICAgICAgIH0NCg0KICAgICAgICBAbWVkaWEgKG1heC13aWR0aDogNjAwcHgpIHsNCiAgICAgICAgICAgIC5jb250ZW50IHsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAyMHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgLnItZnVuY3Rpb24gew0KICAgICAgICAgICAgICAgIGZvbnQtc2l6ZTogMC44cmVtOw0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDJweCA4cHg7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICA8L3N0eWxlPg0KPC9oZWFkPg0KPGJvZHk+DQogICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4NCiAgICAgICAgPGRpdiBjbGFzcz0iY29udGVudCI+DQogICAgICAgICAgICA8ZGl2IGNsYXNzPSJkZXNjcmlwdGlvbiI+DQogICAgICAgICAgICAgICAgPHN0cm9uZz5TdW1tYXJ5IHN0YXRpc3RpY3M8L3N0cm9uZz4gYXJlIG51bWVyaWNhbCBtZWFzdXJlcyB1c2VkIHRvIHN1bW1hcml6ZSBhbmQgZGVzY3JpYmUgdGhlIG1haW4gY2hhcmFjdGVyaXN0aWNzIG9mIGEgZGF0YXNldCwgYWxsb3dpbmcgdXMgdG8gdW5kZXJzdGFuZCB0aGUgZGF0YSB3aXRob3V0IGV4YW1pbmluZyBlYWNoIG9ic2VydmF0aW9uIGluZGl2aWR1YWxseS4gQ29tbW9uIHN1bW1hcnkgc3RhdGlzdGljcyBpbmNsdWRlIHRoZSBtZWFuIChhdmVyYWdlIHZhbHVlKSwgbWVkaWFuIChtaWRkbGUgdmFsdWUpLCBtaW5pbXVtIGFuZCBtYXhpbXVtIChzbWFsbGVzdCBhbmQgbGFyZ2VzdCB2YWx1ZXMpLCBzdGFuZGFyZCBkZXZpYXRpb24gKHdoaWNoIGluZGljYXRlcyBob3cgc3ByZWFkIG91dCB0aGUgZGF0YSBpcyksIGFuZCBxdWFydGlsZXMgKHdoaWNoIGRpdmlkZSB0aGUgZGF0YSBpbnRvIGZvdXIgZXF1YWwgcGFydHMpLiBJbiBSLCB0aGVzZSBzdGF0aXN0aWNzIGNhbiBiZSBjYWxjdWxhdGVkIGVhc2lseSB1c2luZyBmdW5jdGlvbnMgc3VjaCBhcyA8c3BhbiBjbGFzcz0ici1mdW5jdGlvbiI+c3VtbWFyeShkYXRhJHZhcmlhYmxlKTwvc3Bhbj4gZm9yIGEgcXVpY2sgb3ZlcnZpZXcsIG9yIG1vcmUgc3BlY2lmaWMgZnVuY3Rpb25zIGxpa2UgPHNwYW4gY2xhc3M9InItZnVuY3Rpb24iPm1lYW4oKTwvc3Bhbj4sIDxzcGFuIGNsYXNzPSJyLWZ1bmN0aW9uIj5tZWRpYW4oKTwvc3Bhbj4sIDxzcGFuIGNsYXNzPSJyLWZ1bmN0aW9uIj5zZCgpPC9zcGFuPiwgPHNwYW4gY2xhc3M9InItZnVuY3Rpb24iPm1pbigpPC9zcGFuPiwgYW5kIDxzcGFuIGNsYXNzPSJyLWZ1bmN0aW9uIj5tYXgoKTwvc3Bhbj4gZm9yIGRldGFpbGVkIGFuYWx5c2lzLiBPdmVyYWxsLCBzdW1tYXJ5IHN0YXRpc3RpY3MgYXJlIHVzZWZ1bCBmb3IgaWRlbnRpZnlpbmcgcGF0dGVybnMsIHVuZGVyc3RhbmRpbmcgZGF0YSBkaXN0cmlidXRpb24sIGRldGVjdGluZyBvdXRsaWVycywgYW5kIGNvbXBhcmluZyBkaWZmZXJlbnQgZ3JvdXBzLCBzdWNoIGFzIGV2YWx1YXRpbmcgdGhlIHBlcmZvcm1hbmNlIG9mIG11bHRpcGxlIHNhbGVzcGVyc29ucy4NCiAgICAgICAgICAgIDwvZGl2Pg0KICAgICAgICA8L2Rpdj4NCiAgICA8L2Rpdj4NCjwvYm9keT4NCjwvaHRtbD4NCmBgYA0KDQojIyMjIEV4YW1wbGUNCg0KYGBge3J9DQpsaWJyYXJ5KERUKQ0KDQpzYWxlc19kYXRhICU+JQ0KICBncm91cF9ieShzYWxlc19pZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuID0gbWVhbihzYWxlc19hbW91bnQpLA0KICAgIG1lZGlhbiA9IG1lZGlhbihzYWxlc19hbW91bnQpLA0KICAgIG1pbiA9IG1pbihzYWxlc19hbW91bnQpLA0KICAgIG1heCA9IG1heChzYWxlc19hbW91bnQpLA0KICAgIHNkID0gc2Qoc2FsZXNfYW1vdW50KQ0KICApDQpgYGANCg0KIyMjIEN1bXVsYXRpdmUgU2FsZXMgUGxvdCANCg0KYGBgez1odG1sfQ0KPCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJpZCI+DQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+DQogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPg0KICAgIDx0aXRsZT5DdW11bGF0aXZlIFNhbGVzIFBsb3Q8L3RpdGxlPg0KICAgIDxzdHlsZT4NCiAgICAgICAgKiB7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgICAgICBwYWRkaW5nOiAwOw0KICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDsNCiAgICAgICAgfQ0KDQogICAgICAgIGJvZHkgew0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgJ1RpbWVzIE5ldyBSb21hbicsIFRpbWVzLCBzZXJpZjsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzZTBiMGIgMCUsICMxYTAxMDEgMTAwJSk7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBwYWRkaW5nOiAyMHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRhaW5lciB7DQogICAgICAgICAgICBtYXgtd2lkdGg6IDEwMDBweDsNCiAgICAgICAgICAgIHdpZHRoOiAxMDAlOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZkZmFmNjsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDE2cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDIwcHggNDBweCByZ2JhKDAsMCwwLDAuNCk7DQogICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuOw0KICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgI2I4ODYwYjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250ZW50IHsNCiAgICAgICAgICAgIHBhZGRpbmc6IDQwcHg7DQogICAgICAgIH0NCg0KICAgICAgICAuZGVzY3JpcHRpb24gew0KICAgICAgICAgICAgZm9udC1zaXplOiAxLjAycmVtOw0KICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDEuNzsNCiAgICAgICAgICAgIGNvbG9yOiAjMmMxODEwOw0KICAgICAgICAgICAgdGV4dC1hbGlnbjoganVzdGlmeTsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNmZmY5ZWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyNXB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTJweDsNCiAgICAgICAgICAgIGJvcmRlci1sZWZ0OiA1cHggc29saWQgI2I4ODYwYjsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMnB4IDhweCByZ2JhKDAsMCwwLDAuMDUpOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdQYWxhdGlubycsICdHZW9yZ2lhJywgc2VyaWY7DQogICAgICAgIH0NCg0KICAgICAgICAuZGVzY3JpcHRpb24gc3Ryb25nIHsNCiAgICAgICAgICAgIGNvbG9yOiAjOGIxYTFhOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDcwMDsNCiAgICAgICAgfQ0KDQogICAgICAgIC8qIGdheWEgc3BlY2lhbCB1bnR1ayBmdW5nc2kgUiAqLw0KICAgICAgICAuci1mdW5jdGlvbiB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjMmQyYTFlOw0KICAgICAgICAgICAgY29sb3I6ICNmMmU2Yzk7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgJ0ZpcmEgQ29kZScsIG1vbm9zcGFjZTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDNweCAxMHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMjBweDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMC45cmVtOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgICAgICAgICAgIGxldHRlci1zcGFjaW5nOiAwLjNweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IGluc2V0IDAgMCAwIDFweCAjYjg4NjBiLCAwIDFweCAycHggcmdiYSgwLDAsMCwwLjEpOw0KICAgICAgICB9DQoNCiAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDYwMHB4KSB7DQogICAgICAgICAgICAuY29udGVudCB7DQogICAgICAgICAgICAgICAgcGFkZGluZzogMjBweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIC5yLWZ1bmN0aW9uIHsNCiAgICAgICAgICAgICAgICBmb250LXNpemU6IDAuOHJlbTsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAycHggOHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5Pg0KICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+DQogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRlbnQiPg0KICAgICAgICAgICAgPGRpdiBjbGFzcz0iZGVzY3JpcHRpb24iPg0KICAgICAgICAgICAgICAgIDxzdHJvbmc+QSBjdW11bGF0aXZlIHNhbGVzIHBsb3Q8L3N0cm9uZz4gaXMgYSBncmFwaGljYWwgcmVwcmVzZW50YXRpb24gdGhhdCBzaG93cyB0aGUgcnVubmluZyB0b3RhbCBvZiBzYWxlcyBvdmVyIHRpbWUsIGFsbG93aW5nIHVzIHRvIG9ic2VydmUgaG93IHNhbGVzIGFjY3VtdWxhdGUgZGF5IGJ5IGRheS4gSXQgaXMgY2FsY3VsYXRlZCBieSBzdW1taW5nIHNhbGVzIGFtb3VudHMgc2VxdWVudGlhbGx5IHVzaW5nIGEgY3VtdWxhdGl2ZSBzdW0gZnVuY3Rpb24sIHN1Y2ggYXMgPHNwYW4gY2xhc3M9InItZnVuY3Rpb24iPmN1bXN1bSgpPC9zcGFuPiBpbiBSLCB3aGljaCBhZGRzIGVhY2ggbmV3IHZhbHVlIHRvIHRoZSB0b3RhbCBvZiBhbGwgcHJldmlvdXMgdmFsdWVzLiBUbyBjcmVhdGUgdGhpcyBwbG90LCB0aGUgZGF0YSBpcyB0eXBpY2FsbHkgZ3JvdXBlZCAoZS5nLiwgYnkgc2FsZXNwZXJzb24pLCBzb3J0ZWQgYnkgdGltZSAoZS5nLiwgZGF5KSwgYW5kIHRoZW4gdHJhbnNmb3JtZWQgaW50byBjdW11bGF0aXZlIHZhbHVlcyBiZWZvcmUgYmVpbmcgdmlzdWFsaXplZCB1c2luZyBhIGxpbmUgY2hhcnQuIFRoZSBtYWluIHB1cnBvc2Ugb2YgYSBjdW11bGF0aXZlIHNhbGVzIHBsb3QgaXMgdG8gaWRlbnRpZnkgdHJlbmRzIGluIG92ZXJhbGwgcGVyZm9ybWFuY2UsIGNvbXBhcmUgZ3Jvd3RoIGJldHdlZW4gZGlmZmVyZW50IHNhbGVzcGVyc29ucywgYW5kIGRldGVjdCBwZXJpb2RzIG9mIHJhcGlkIG9yIHNsb3cgc2FsZXMgYWNjdW11bGF0aW9uLiBUaGlzIHR5cGUgb2YgdmlzdWFsaXphdGlvbiBpcyBlc3BlY2lhbGx5IHVzZWZ1bCBmb3IgdHJhY2tpbmcgcHJvZ3Jlc3MgdG93YXJkIHRhcmdldHMgYW5kIHVuZGVyc3RhbmRpbmcgbG9uZy10ZXJtIHNhbGVzIGJlaGF2aW9yIHJhdGhlciB0aGFuIGZvY3VzaW5nIG9uIGRhaWx5IGZsdWN0dWF0aW9ucy4NCiAgICAgICAgICAgIDwvZGl2Pg0KICAgICAgICA8L2Rpdj4NCiAgICA8L2Rpdj4NCjwvYm9keT4NCjwvaHRtbD4NCmBgYA0KDQojIyMjIEV4YW1wbGUgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbG90bHkpDQoNCiMgY291bnQgY3VtdWxhdGl2ZSBzYWxlcw0Kc2FsZXNfY3VtIDwtIHNhbGVzX2RhdGEgJT4lDQogIGFycmFuZ2Uoc2FsZXNfaWQsIGRheSkgJT4lDQogIGdyb3VwX2J5KHNhbGVzX2lkKSAlPiUNCiAgbXV0YXRlKGN1bV9zYWxlcyA9IGN1bXN1bShzYWxlc19hbW91bnQpKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgY29sb3INCm5lb25fY29sb3JzIDwtIGMoDQogICIjMDBGRkZGIiwgIiNGRjAwRkYiLCAiIzM5RkYxNCIsICIjRkYwNzNBIiwNCiAgIiNGRkQzMDAiLCAiI0ZGNkVDNyIsICIjMDBGRkVGIiwgIiNCMDI2RkYiDQopDQoNCiMgUGxvdCBpbnRlcmFrdGlmDQpmaWcgPC0gcGxvdF9seSgNCiAgZGF0YSA9IHNhbGVzX2N1bSwNCiAgeCA9IH5kYXksDQogIHkgPSB+Y3VtX3NhbGVzLA0KICBjb2xvciA9IH5zYWxlc19pZCwNCiAgY29sb3JzID0gbmVvbl9jb2xvcnMsDQogIHR5cGUgPSAic2NhdHRlciIsDQogIG1vZGUgPSAibGluZXMrbWFya2VycyIsDQogIHRleHQgPSB+cGFzdGUoDQogICAgIlNhbGVzOiIsIHNhbGVzX2lkLA0KICAgICI8YnI+RGF5OiIsIGRheSwNCiAgICAiPGJyPkN1bXVsYXRpdmU6Iiwgcm91bmQoY3VtX3NhbGVzLCAyKQ0KICApLA0KICBob3ZlcmluZm8gPSAidGV4dCINCikgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QoDQogICAgICB0ZXh0ID0gIkN1bXVsYXRpdmUgU2FsZXMgcGVyIFNhbGVzcGVyc29uIiwNCiAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gIiNGRkZGRkYiKQ0KICAgICksDQogICAgcGFwZXJfYmdjb2xvciA9ICIjMDAwMDAwIiwNCiAgICBwbG90X2JnY29sb3IgPSAiIzAwMDAwMCIsDQogICAgZm9udCA9IGxpc3QoY29sb3IgPSAiI0ZGRkZGRiIpLA0KICAgIHhheGlzID0gbGlzdCgNCiAgICAgIHRpdGxlID0gIkRheSIsDQogICAgICBjb2xvciA9ICIjRkZGRkZGIiwNCiAgICAgIGdyaWRjb2xvciA9ICIjMzMzMzMzIg0KICAgICksDQogICAgeWF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAiQ3VtdWxhdGl2ZSBTYWxlcyIsDQogICAgICBjb2xvciA9ICIjRkZGRkZGIiwNCiAgICAgIGdyaWRjb2xvciA9ICIjMzMzMzMzIg0KICAgICksDQogICAgbGVnZW5kID0gbGlzdChmb250ID0gbGlzdChjb2xvciA9ICIjRkZGRkZGIikpDQogICkNCg0KZmlnDQpgYGANCg0KPGRpdiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojRkZGOUM0OyBwYWRkaW5nOjE1cHg7IGJvcmRlci1yYWRpdXM6MTBweDsgYm9yZGVyOjFweCBzb2xpZCAjRkREODM1OyBtYXJnaW4tdG9wOjEwcHg7IHRleHQtYWxpZ246IGp1c3RpZnk7Ij4NCg0KKipJbnRlcnByZXRhdGlvbioqDQoNCkZyb20gdGhlIHZpc3VhbGl6YXRpb24sIHNhbGVzcGVyc29ucyB3aG9zZSBsaW5lcyBjb25zaXN0ZW50bHkgcmVtYWluIGFib3ZlIG90aGVycyBjYW4gYmUgaWRlbnRpZmllZCBhcyB0b3AgcGVyZm9ybWVycywgYXMgdGhleSBhY2hpZXZlIGhpZ2hlciB0b3RhbCBzYWxlcyB0aHJvdWdob3V0IHRoZSBwZXJpb2QsIHdoaWxlIHRob3NlIHdpdGggbG93ZXIgY3VtdWxhdGl2ZSBjdXJ2ZXMgaW5kaWNhdGUgcmVsYXRpdmVseSB3ZWFrZXIgcGVyZm9ybWFuY2UuIEFkZGl0aW9uYWxseSwgZmx1Y3R1YXRpb25zIGluIHRoZSBzdGVlcG5lc3Mgb2YgdGhlIGxpbmVzIHJldmVhbCB2YXJpYXRpb25zIGluIGRhaWx5IHNhbGVzIGNvbnRyaWJ1dGlvbnPigJRzaGFycCBpbmNyZWFzZXMgc3VnZ2VzdCBoaWdoIHNhbGVzIG9uIHBhcnRpY3VsYXIgZGF5cywgd2hlcmVhcyBzbW9vdGhlciwgZ3JhZHVhbCBpbmNyZWFzZXMgaW5kaWNhdGUgc3RhYmxlIGJ1dCBtb2RlcmF0ZSBwZXJmb3JtYW5jZS4gT3ZlcmFsbCwgdGhpcyBwbG90IGlzIHVzZWZ1bCBmb3IgY29tcGFyaW5nIHNhbGVzIHBlcmZvcm1hbmNlIGFjcm9zcyBpbmRpdmlkdWFscywgaWRlbnRpZnlpbmcgY29uc2lzdGVudCBoaWdoIHBlcmZvcm1lcnMsIGFuZCBkZXRlY3RpbmcgcGF0dGVybnMgc3VjaCBhcyByYXBpZCBncm93dGggcGhhc2VzIG9yIHN0YWduYXRpb24gcGVyaW9kcy4gSXQgcHJvdmlkZXMgYSBjbGVhcmVyIHBpY3R1cmUgb2YgbG9uZy10ZXJtIHBlcmZvcm1hbmNlIHRyZW5kcyBjb21wYXJlZCB0byBkYWlseSBzYWxlcyBkYXRhLCBtYWtpbmcgaXQgdmFsdWFibGUgZm9yIHBlcmZvcm1hbmNlIGV2YWx1YXRpb24gYW5kIGRlY2lzaW9uLW1ha2luZy4NCg0KPC9kaXY+DQoNCiMgTXVsdGktTGV2ZWwgUGVyZm9ybWFuY2UgQ2F0ZWdvcml6YXRpb24gDQoNCmBgYHs9aHRtbH0NCjwhRE9DVFlQRSBodG1sPg0KPGh0bWwgbGFuZz0iZW4iPg0KPGhlYWQ+DQogICAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPg0KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wIj4NCiAgICA8dGl0bGU+TXVsdGktTGV2ZWwgUGVyZm9ybWFuY2UgQ2F0ZWdvcml6YXRpb248L3RpdGxlPg0KICAgIDxzdHlsZT4NCiAgICAgICAgKiB7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgICAgICBwYWRkaW5nOiAwOw0KICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDsNCiAgICAgICAgfQ0KDQogICAgICAgIGJvZHkgew0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgJ1RpbWVzIE5ldyBSb21hbicsIFRpbWVzLCBzZXJpZjsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzZTBiMGIgMCUsICMxYTAxMDEgMTAwJSk7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBwYWRkaW5nOiAyMHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRhaW5lciB7DQogICAgICAgICAgICBtYXgtd2lkdGg6IDk1MHB4Ow0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZmRmYWY2Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTZweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMjBweCA0MHB4IHJnYmEoMCwwLDAsMC40KTsNCiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjYjg4NjBiOw0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRlbnQgew0KICAgICAgICAgICAgcGFkZGluZzogNDBweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5kZXNjcmlwdGlvbiB7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDJyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS43Ow0KICAgICAgICAgICAgY29sb3I6ICMyYzE4MTA7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZmZjllZjsNCiAgICAgICAgICAgIHBhZGRpbmc6IDI4cHggMzJweDsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDEycHg7DQogICAgICAgICAgICBib3JkZXItbGVmdDogNXB4IHNvbGlkICNiODg2MGI7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDJweCA4cHggcmdiYSgwLDAsMCwwLjA1KTsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnUGFsYXRpbm8nLCAnR2VvcmdpYScsIHNlcmlmOw0KICAgICAgICB9DQoNCiAgICAgICAgLmRlc2NyaXB0aW9uIHN0cm9uZyB7DQogICAgICAgICAgICBjb2xvcjogIzhiMWExYTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA3MDA7DQogICAgICAgIH0NCg0KICAgICAgICAuci1mdW5jdGlvbiB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjMmQyYTFlOw0KICAgICAgICAgICAgY29sb3I6ICNmMmU2Yzk7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgJ0ZpcmEgQ29kZScsIG1vbm9zcGFjZTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDNweCAxMHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMjBweDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMC45cmVtOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgICAgICAgICAgIGxldHRlci1zcGFjaW5nOiAwLjNweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IGluc2V0IDAgMCAwIDFweCAjYjg4NjBiLCAwIDFweCAycHggcmdiYSgwLDAsMCwwLjEpOw0KICAgICAgICB9DQoNCiAgICAgICAgLmNhdGVnb3J5LWJhZGdlIHsNCiAgICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICM2YjFhMWEgMCUsICMzZTBhMGEgMTAwJSk7DQogICAgICAgICAgICBjb2xvcjogI2Q0YWYzNzsNCiAgICAgICAgICAgIHBhZGRpbmc6IDJweCAxMHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMjBweDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMC44NXJlbTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7DQogICAgICAgICAgICBtYXJnaW46IDAgMnB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDYwMHB4KSB7DQogICAgICAgICAgICAuY29udGVudCB7DQogICAgICAgICAgICAgICAgcGFkZGluZzogMjBweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIC5kZXNjcmlwdGlvbiB7DQogICAgICAgICAgICAgICAgcGFkZGluZzogMjBweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIC5yLWZ1bmN0aW9uIHsNCiAgICAgICAgICAgICAgICBmb250LXNpemU6IDAuOHJlbTsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAycHggOHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5Pg0KICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+DQogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRlbnQiPg0KICAgICAgICAgICAgPGRpdiBjbGFzcz0iZGVzY3JpcHRpb24iPg0KICAgICAgICAgICAgICAgIDxzdHJvbmc+Q2hhcHRlcjogTXVsdGktTGV2ZWwgUGVyZm9ybWFuY2UgQ2F0ZWdvcml6YXRpb248L3N0cm9uZz4gZGlzY3Vzc2VzIHRoZSBmdW5jdGlvbiA8c3BhbiBjbGFzcz0ici1mdW5jdGlvbiI+Y2F0ZWdvcml6ZV9wZXJmb3JtYW5jZShzYWxlc19hbW91bnQpPC9zcGFuPiB3aXRoIDxzdHJvbmc+NSBjYXRlZ29yaWVzPC9zdHJvbmc+OiANCiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0iY2F0ZWdvcnktYmFkZ2UiPkV4Y2VsbGVudDwvc3Bhbj4sIA0KICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJjYXRlZ29yeS1iYWRnZSI+VmVyeSBHb29kPC9zcGFuPiwgDQogICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImNhdGVnb3J5LWJhZGdlIj5Hb29kPC9zcGFuPiwgDQogICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImNhdGVnb3J5LWJhZGdlIj5BdmVyYWdlPC9zcGFuPiwgYW5kIA0KICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJjYXRlZ29yeS1iYWRnZSI+UG9vcjwvc3Bhbj4uIA0KICAgICAgICAgICAgICAgIFRoZSBkaXNjdXNzaW9uIGNvdmVycyA8c3Ryb25nPmxvb3BpbmcgdGhyb3VnaCBhIHZlY3Rvcjwvc3Ryb25nPiB0byBjbGFzc2lmeSBlYWNoIHNhbGVzIHZhbHVlLCBjYWxjdWxhdGluZyA8c3Ryb25nPnBlcmNlbnRhZ2VzIHBlciBjYXRlZ29yeTwvc3Ryb25nPiwgYW5kIHZpc3VhbGl6aW5nIHRoZSBkaXN0cmlidXRpb24gdXNpbmcgYSA8c3Ryb25nPmJhciBwbG90PC9zdHJvbmc+IGFuZCBhIDxzdHJvbmc+cGllIGNoYXJ0PC9zdHJvbmc+Lg0KICAgICAgICAgICAgPC9kaXY+DQogICAgICAgIDwvZGl2Pg0KICAgIDwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCiMjIExvb3AgVGhyb3VnaCBWZWN0b3IgDQoNCmBgYHs9aHRtbH0NCjwhRE9DVFlQRSBodG1sPg0KPGh0bWwgbGFuZz0iZW4iPg0KPGhlYWQ+DQogICAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPg0KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wIj4NCiAgICA8dGl0bGU+TG9vcCBUaHJvdWdoIFZlY3RvciAtIEV4cGxhbmF0aW9uPC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsICdUaW1lcyBOZXcgUm9tYW4nLCBUaW1lcywgc2VyaWY7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjM2UwYjBiIDAlLCAjMWEwMTAxIDEwMCUpOw0KICAgICAgICAgICAgbWluLWhlaWdodDogMTAwdmg7DQogICAgICAgICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgcGFkZGluZzogMjBweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250YWluZXIgew0KICAgICAgICAgICAgbWF4LXdpZHRoOiA5NTBweDsNCiAgICAgICAgICAgIHdpZHRoOiAxMDAlOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZkZmFmNjsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDE2cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDIwcHggNDBweCByZ2JhKDAsMCwwLDAuNCk7DQogICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuOw0KICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgI2I4ODYwYjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250ZW50IHsNCiAgICAgICAgICAgIHBhZGRpbmc6IDQwcHg7DQogICAgICAgIH0NCg0KICAgICAgICAuZGVzY3JpcHRpb24gew0KICAgICAgICAgICAgZm9udC1zaXplOiAxLjAycmVtOw0KICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDEuNzsNCiAgICAgICAgICAgIGNvbG9yOiAjMmMxODEwOw0KICAgICAgICAgICAgdGV4dC1hbGlnbjoganVzdGlmeTsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNmZmY5ZWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyOHB4IDMycHg7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAxMnB4Ow0KICAgICAgICAgICAgYm9yZGVyLWxlZnQ6IDVweCBzb2xpZCAjYjg4NjBiOw0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAycHggOHB4IHJnYmEoMCwwLDAsMC4wNSk7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1BhbGF0aW5vJywgJ0dlb3JnaWEnLCBzZXJpZjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5kZXNjcmlwdGlvbiBzdHJvbmcgew0KICAgICAgICAgICAgY29sb3I6ICM4YjFhMWE7DQogICAgICAgICAgICBmb250LXdlaWdodDogNzAwOw0KICAgICAgICB9DQoNCiAgICAgICAgLnItZnVuY3Rpb24gew0KICAgICAgICAgICAgYmFja2dyb3VuZDogIzJkMmExZTsNCiAgICAgICAgICAgIGNvbG9yOiAjZjJlNmM5Ow0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdDb3VyaWVyIE5ldycsICdGaXJhIENvZGUnLCBtb25vc3BhY2U7DQogICAgICAgICAgICBwYWRkaW5nOiAzcHggMTBweDsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDIwcHg7DQogICAgICAgICAgICBmb250LXNpemU6IDAuOXJlbTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA1MDA7DQogICAgICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMC4zcHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiBpbnNldCAwIDAgMCAxcHggI2I4ODYwYiwgMCAxcHggMnB4IHJnYmEoMCwwLDAsMC4xKTsNCiAgICAgICAgfQ0KDQogICAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA2MDBweCkgew0KICAgICAgICAgICAgLmNvbnRlbnQgew0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDIwcHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAuZGVzY3JpcHRpb24gew0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDIwcHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAuci1mdW5jdGlvbiB7DQogICAgICAgICAgICAgICAgZm9udC1zaXplOiAwLjhyZW07DQogICAgICAgICAgICAgICAgcGFkZGluZzogMnB4IDhweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIDwvc3R5bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCiAgICA8ZGl2IGNsYXNzPSJjb250YWluZXIiPg0KICAgICAgICA8ZGl2IGNsYXNzPSJjb250ZW50Ij4NCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImRlc2NyaXB0aW9uIj4NCiAgICAgICAgICAgICAgICA8c3Ryb25nPuKAnExvb3AgdGhyb3VnaCB2ZWN0b3LigJ08L3N0cm9uZz4gbWVhbnMgaXRlcmF0aW5nIG92ZXIgZWFjaCBlbGVtZW50IGluIGEgdmVjdG9yIG9uZSBieSBvbmUgdXNpbmcgYSBsb29wIChzdWNoIGFzIGEgPHNwYW4gY2xhc3M9InItZnVuY3Rpb24iPmZvcjwvc3Bhbj4gbG9vcCkgYW5kIGFwcGx5aW5nIGEgc3BlY2lmaWMgb3BlcmF0aW9uIHRvIGVhY2ggdmFsdWUuIEluIHRoaXMgdGFzaywgaXQgcmVxdWlyZXMgdGFraW5nIGVhY2ggPHNwYW4gY2xhc3M9InItZnVuY3Rpb24iPnNhbGVzX2Ftb3VudDwvc3Bhbj4gdmFsdWUsIGV2YWx1YXRpbmcgaXQgdXNpbmcgY29uZGl0aW9uYWwgbG9naWMgKGUuZy4sIDxzcGFuIGNsYXNzPSJyLWZ1bmN0aW9uIj5pZi1lbHNlPC9zcGFuPikgdG8gYXNzaWduIGl0IGludG8gYSBwZXJmb3JtYW5jZSBjYXRlZ29yeSBsaWtlIEV4Y2VsbGVudCwgVmVyeSBHb29kLCBHb29kLCBBdmVyYWdlLCBvciBQb29yLCBhbmQgc3RvcmluZyB0aGUgcmVzdWx0cyBpbiBhIG5ldyB2ZWN0b3IuIA0KICAgICAgICAgICAgPC9kaXY+DQogICAgICAgIDwvZGl2Pg0KICAgIDwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCiMjIyBDYXRlZ29yeSANCg0KYGBgez1odG1sfQ0KPCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJlbiI+DQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+DQogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPg0KICAgIDx0aXRsZT5QZXJmb3JtYW5jZSBDYXRlZ29yaWVzPC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsICdUaW1lcyBOZXcgUm9tYW4nLCBUaW1lcywgc2VyaWY7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjM2UwYjBiIDAlLCAjMWEwMTAxIDEwMCUpOw0KICAgICAgICAgICAgbWluLWhlaWdodDogMTAwdmg7DQogICAgICAgICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgcGFkZGluZzogMjBweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250YWluZXIgew0KICAgICAgICAgICAgbWF4LXdpZHRoOiA4MDBweDsNCiAgICAgICAgICAgIHdpZHRoOiAxMDAlOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZkZmFmNjsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDE2cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDIwcHggNDBweCByZ2JhKDAsMCwwLDAuNCk7DQogICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuOw0KICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgI2I4ODYwYjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250ZW50IHsNCiAgICAgICAgICAgIHBhZGRpbmc6IDQwcHg7DQogICAgICAgIH0NCg0KICAgICAgICAuY2F0ZWdvcnktdGFibGUgew0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBib3JkZXItY29sbGFwc2U6IGNvbGxhcHNlOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTJweDsNCiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDVweCAxNXB4IHJnYmEoMCwwLDAsMC4xKTsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jYXRlZ29yeS10YWJsZSB0aCB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjNmIxYTFhIDAlLCAjM2UwYTBhIDEwMCUpOw0KICAgICAgICAgICAgY29sb3I6ICNkNGFmMzc7DQogICAgICAgICAgICBwYWRkaW5nOiAxNXB4Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMXJlbTsNCiAgICAgICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgICAgICAgICAgIGJvcmRlci1ib3R0b206IDJweCBzb2xpZCAjZDRhZjM3Ow0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDFweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jYXRlZ29yeS10YWJsZSB0ZCB7DQogICAgICAgICAgICBwYWRkaW5nOiAxMnB4IDE1cHg7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZmZmY2Y1Ow0KICAgICAgICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNlOGRiYmM7DQogICAgICAgICAgICBmb250LXdlaWdodDogNTAwOw0KICAgICAgICAgICAgY29sb3I6ICMyYzE4MTA7DQogICAgICAgIH0NCg0KICAgICAgICAuY2F0ZWdvcnktdGFibGUgdHI6aG92ZXIgdGQgew0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZjZjZlODsNCiAgICAgICAgICAgIHRyYW5zaXRpb246IDAuMnM7DQogICAgICAgIH0NCg0KICAgICAgICAuY2F0ZWdvcnktdGFibGUgdGQ6Zmlyc3QtY2hpbGQgew0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgICAgICAgICAgIGNvbG9yOiAjNWEwZTBlOw0KICAgICAgICB9DQoNCiAgICAgICAgLnJhbmdlLWJhZGdlIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICNiODg2MGIgMCUsICNkNGFmMzcgMTAwJSk7DQogICAgICAgICAgICBjb2xvcjogIzJjMDUwNTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDVweCAxNHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMzBweDsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOw0KICAgICAgICAgICAgZm9udC1zaXplOiAwLjg1cmVtOw0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAxcHggM3B4IHJnYmEoMCwwLDAsMC4yKTsNCiAgICAgICAgfQ0KDQogICAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA2MDBweCkgew0KICAgICAgICAgICAgLmNvbnRlbnQgew0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDIwcHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAuY2F0ZWdvcnktdGFibGUgdGgsIC5jYXRlZ29yeS10YWJsZSB0ZCB7DQogICAgICAgICAgICAgICAgcGFkZGluZzogMTBweDsNCiAgICAgICAgICAgICAgICBmb250LXNpemU6IDAuODVyZW07DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICA8L3N0eWxlPg0KPC9oZWFkPg0KPGJvZHk+DQogICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4NCiAgICAgICAgPGRpdiBjbGFzcz0iY29udGVudCI+DQogICAgICAgICAgICA8dGFibGUgY2xhc3M9ImNhdGVnb3J5LXRhYmxlIj4NCiAgICAgICAgICAgICAgICA8dGhlYWQ+DQogICAgICAgICAgICAgICAgICAgIDx0cj4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5DYXRlZ29yeTwvdGg+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGg+UmFuZ2U8L3RoPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRoPkRlc2NyaXB0aW9uPC90aD4NCiAgICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICA8L3RoZWFkPg0KICAgICAgICAgICAgICAgIDx0Ym9keT4NCiAgICAgICAgICAgICAgICAgICAgPHRyPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPkV4Y2VsbGVudDwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PHNwYW4gY2xhc3M9InJhbmdlLWJhZGdlIj7iiaUgNzAwPC9zcGFuPjwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+T3V0c3RhbmRpbmcgcGVyZm9ybWFuY2UsIGZhciBhYm92ZSB0YXJnZXQ8L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0KICAgICAgICAgICAgICAgICAgICA8dHI+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+VmVyeSBHb29kPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48c3BhbiBjbGFzcz0icmFuZ2UtYmFkZ2UiPjUwMCDigJMgNjk5PC9zcGFuPjwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+VmVyeSBnb29kLCBhYm92ZSBleHBlY3RhdGlvbnM8L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0KICAgICAgICAgICAgICAgICAgICA8dHI+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+R29vZDwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PHNwYW4gY2xhc3M9InJhbmdlLWJhZGdlIj4zMDAg4oCTIDQ5OTwvc3Bhbj48L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPkdvb2QsIG1lZXRpbmcgc3RhbmRhcmQgdGFyZ2V0PC90ZD4NCiAgICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICAgICAgPHRyPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPkF2ZXJhZ2U8L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzcGFuIGNsYXNzPSJyYW5nZS1iYWRnZSI+MjAwIOKAkyAyOTk8L3NwYW4+PC90ZD4NCiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5TdWZmaWNpZW50LCB3aXRoaW4gcmVhc29uYWJsZSBsaW1pdHM8L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0KICAgICAgICAgICAgICAgICAgICA8dHI+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+UG9vcjwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PHNwYW4gY2xhc3M9InJhbmdlLWJhZGdlIj48IDIwMDwvc3Bhbj48L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPkJlbG93IHRhcmdldCwgbmVlZHMgc2VyaW91cyBldmFsdWF0aW9uPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICA8L3Rib2R5Pg0KICAgICAgICAgICAgPC90YWJsZT4NCiAgICAgICAgPC9kaXY+DQogICAgPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KIyMgQ2FsY3VsYXRlIFByZWNlbnRhZ2UgcGVyIENhdGVnb3J5IA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoRFQpDQoNCiMgRnVuY3Rpb24ga2F0ZWdvcmlzYXNpDQpjYXRlZ29yaXplX3BlcmZvcm1hbmNlIDwtIGZ1bmN0aW9uKHNhbGVzX2Ftb3VudCkgew0KICANCiAgY2F0ZWdvcmllcyA8LSBjKCkNCiAgDQogIGZvciAoaSBpbiBzYWxlc19hbW91bnQpIHsNCiAgICANCiAgICBpZiAoaSA+PSA3MDApIHsNCiAgICAgIGNhdGVnb3JpZXMgPC0gYyhjYXRlZ29yaWVzLCAiRXhjZWxsZW50IikNCiAgICAgIA0KICAgIH0gZWxzZSBpZiAoaSA+PSA1MDApIHsNCiAgICAgIGNhdGVnb3JpZXMgPC0gYyhjYXRlZ29yaWVzLCAiVmVyeSBHb29kIikNCiAgICAgIA0KICAgIH0gZWxzZSBpZiAoaSA+PSAzMDApIHsNCiAgICAgIGNhdGVnb3JpZXMgPC0gYyhjYXRlZ29yaWVzLCAiR29vZCIpDQogICAgICANCiAgICB9IGVsc2UgaWYgKGkgPj0gMjAwKSB7DQogICAgICBjYXRlZ29yaWVzIDwtIGMoY2F0ZWdvcmllcywgIkF2ZXJhZ2UiKQ0KICAgICAgDQogICAgfSBlbHNlIHsNCiAgICAgIGNhdGVnb3JpZXMgPC0gYyhjYXRlZ29yaWVzLCAiUG9vciIpDQogICAgfQ0KICB9DQogIA0KICByZXR1cm4oY2F0ZWdvcmllcykNCn0NCg0KIyBUZXJhcGthbiBrZSBkYXRhIChXQUpJQiBkdWx1KQ0Kc2FsZXNfZGF0YSRwZXJmb3JtYW5jZV9jYXRlZ29yeSA8LSBjYXRlZ29yaXplX3BlcmZvcm1hbmNlKHNhbGVzX2RhdGEkc2FsZXNfYW1vdW50KQ0KDQojIEJhcnUgdWJhaCBqYWRpIGZhY3RvciBiaWFyIHVydXQNCnNhbGVzX2RhdGEkcGVyZm9ybWFuY2VfY2F0ZWdvcnkgPC0gZmFjdG9yKA0KICBzYWxlc19kYXRhJHBlcmZvcm1hbmNlX2NhdGVnb3J5LA0KICBsZXZlbHMgPSBjKCJFeGNlbGxlbnQiLCAiVmVyeSBHb29kIiwgIkdvb2QiLCAiQXZlcmFnZSIsICJQb29yIikNCikNCg0KIyBTdW1tYXJ5IHRhYmVsIChwYWthaSAuZHJvcCA9IEZBTFNFIGJpYXIgc2VtdWEga2F0ZWdvcmkgbXVuY3VsKQ0Kc3VtbWFyeV90YWJsZSA8LSBzYWxlc19kYXRhICU+JQ0KICBjb3VudChwZXJmb3JtYW5jZV9jYXRlZ29yeSwgLmRyb3AgPSBGQUxTRSkgJT4lDQogIG11dGF0ZShwZXJjZW50YWdlID0gcm91bmQobiAvIHN1bShuKSAqIDEwMCwgMikpDQoNCiMgVGFtcGlsa2FuIHRhYmVsIGludGVyYWt0aWYNCmRhdGF0YWJsZSgNCiAgc3VtbWFyeV90YWJsZSwNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDUsDQogICAgZG9tID0gJ0JmcnRpcCcsDQogICAgYnV0dG9ucyA9IGMoJ2NvcHknLCAnY3N2JywgJ2V4Y2VsJywgJ3BkZicsICdwcmludCcpDQogICksDQogIHJvd25hbWVzID0gRkFMU0UsDQogIGNhcHRpb24gPSAiU2FsZXMgUGVyZm9ybWFuY2UgRGlzdHJpYnV0aW9uIg0KKQ0KYGBgDQoNCg0KDQojIyBCYXIgcGxvdCBhbmQgcGllIGNoYXJ0IG9mIGRpc3RyaWJ1dGlvbiANCg0KIyMjIEJhciBwbG90IA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEJhc2UgZ2dwbG90DQpwIDwtIGdncGxvdChzdW1tYXJ5X3RhYmxlLCBhZXMoeCA9IHBlcmZvcm1hbmNlX2NhdGVnb3J5LCB5ID0gbiwgZmlsbCA9IHBlcmZvcm1hbmNlX2NhdGVnb3J5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKA0KICAgICJFeGNlbGxlbnQiID0gIiMzOUZGMTQiLA0KICAgICJWZXJ5IEdvb2QiID0gIiMwMEZGRkYiLA0KICAgICJHb29kIiA9ICIjRkZEMzAwIiwNCiAgICAiQXZlcmFnZSIgPSAiI0ZGNkVDNyIsDQogICAgIlBvb3IiID0gIiNGRjA3M0EiDQogICkpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJTYWxlcyBQZXJmb3JtYW5jZSBEaXN0cmlidXRpb24iLA0KICAgIHggPSAiUGVyZm9ybWFuY2UgQ2F0ZWdvcnkiLA0KICAgIHkgPSAiQ291bnQiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJibGFjayIsIGNvbG9yID0gTkEpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJibGFjayIpLA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiKSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ3aGl0ZSIpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQ0KICApDQoNCiMgQ29udmVydCB0byBpbnRlcmFjdGl2ZSBwbG90DQpnZ3Bsb3RseShwKQ0KYGBgDQoNCjxkaXYgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0ZGRjlDNDsgcGFkZGluZzoxNXB4OyBib3JkZXItcmFkaXVzOjEwcHg7IGJvcmRlcjoxcHggc29saWQgI0ZERDgzNTsgbWFyZ2luLXRvcDoxMHB4OyB0ZXh0LWFsaWduOiBqdXN0aWZ5OyI+DQoNCioqSW50ZXJwcmV0YXRpb24qKg0KDQpGcm9tIHRoZSBjaGFydCwgaXQgY2FuIGJlIHNlZW4gdGhhdCB0aGUgR29vZCBjYXRlZ29yeSBoYXMgdGhlIHRhbGxlc3QgYmFyLCBtZWFuaW5nIG1vc3Qgb2YgdGhlIHNhbGVzcGVvcGxlIGFyZSBwZXJmb3JtaW5nIHdlbGwsIGZvbGxvd2VkIGJ5IEV4Y2VsbGVudCBpbiB0aGUgc2Vjb25kIGhpZ2hlc3QgcG9zaXRpb24sIGluZGljYXRpbmcgcXVpdGUgYSBmZXcgc2FsZXNwZW9wbGUgaGF2ZSBhY2hpZXZlZCBvdXRzdGFuZGluZyBwZXJmb3JtYW5jZS4gTWVhbndoaWxlLCB0aGUgVmVyeSBHb29kIGFuZCBBdmVyYWdlIGNhdGVnb3JpZXMgaGF2ZSBiYXJzIG9mIG1lZGl1bSBoZWlnaHQsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgcmVtYWluaW5nIHNhbGVzcGVvcGxlIGFyZSBzcHJlYWQgYWNyb3NzIHZlcnkgZ29vZCBhbmQgYXZlcmFnZSBsZXZlbHMuIFRoZSBQb29yIGNhdGVnb3J5IGFwcGVhcnMgdG8gYmUgdGhlIHNob3J0ZXN0LCBzbyBvbmx5IGEgZmV3IHNhbGVzcGVvcGxlIGhhdmUgbG93IHBlcmZvcm1hbmNlIGFuZCBpdCBpcyBub3QgdG9vIGNvbmNlcm5pbmcuIE92ZXJhbGwsIHRoZSBzYWxlcyB0ZWFtJ3MgcGVyZm9ybWFuY2UgZGlzdHJpYnV0aW9uIHRlbmRzIHRvIHNrZXcgdG8gdGhlIHJpZ2h0IChmcm9tIEdvb2QgdG8gRXhjZWxsZW50KSwgd2hpY2ggbWVhbnMgdGhlIHRlYW0gaGFzIGhlYWx0aHkgYW5kIHBvc2l0aXZlIHBlcmZvcm1hbmNlLCBhbHRob3VnaCBzYWxlc3Blb3BsZSBpbiB0aGUgQXZlcmFnZSBjYXRlZ29yeSBuZWVkIHRvIGJlIGVuY291cmFnZWQgdG8gbW92ZSB1cCB0byBHb29kIG9yIFZlcnkgR29vZC4NCg0KPC9kaXY+DQoNCg0KIyMjIFBpZSBDaGFydCANCg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShwbG90bHkpDQoNCiMgUGllIGNoYXJ0IGludGVyYWt0aWYNCnBsb3RfbHkoDQogIGRhdGEgPSBzdW1tYXJ5X3RhYmxlLA0KICBsYWJlbHMgPSB+cGVyZm9ybWFuY2VfY2F0ZWdvcnksDQogIHZhbHVlcyA9IH5uLA0KICB0eXBlID0gInBpZSIsDQogIG1hcmtlciA9IGxpc3QoY29sb3JzID0gYygNCiAgICAiIzM5RkYxNCIsICAjIEV4Y2VsbGVudA0KICAgICIjMDBGRkZGIiwgICMgVmVyeSBHb29kDQogICAgIiNGRkQzMDAiLCAgIyBHb29kDQogICAgIiNGRjZFQzciLCAgIyBBdmVyYWdlDQogICAgIiNGRjA3M0EiICAgIyBQb29yDQogICkpDQopICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICJTYWxlcyBQZXJmb3JtYW5jZSBQcm9wb3J0aW9uIiwNCiAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gIiNGRkZGRkYiKQ0KICAgICksDQogICAgcGFwZXJfYmdjb2xvciA9ICIjMDAwMDAwIiwNCiAgICBwbG90X2JnY29sb3IgPSAiIzAwMDAwMCIsDQogICAgZm9udCA9IGxpc3QoY29sb3IgPSAiI0ZGRkZGRiIpDQogICkNCmBgYA0KDQo8ZGl2IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNGRkY5QzQ7IHBhZGRpbmc6MTVweDsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3JkZXI6MXB4IHNvbGlkICNGREQ4MzU7IG1hcmdpbi10b3A6MTBweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPg0KDQoqKkludGVycHJldGF0aW9uKioNCg0KVGhlIHBpZSBjaGFydCBpbGx1c3RyYXRlcyB0aGUgcHJvcG9ydGlvbiBvZiBlYWNoIHNhbGVzIHBlcmZvcm1hbmNlIGNhdGVnb3J5IHJlbGF0aXZlIHRvIHRoZSB0b3RhbCBkYXRhc2V0LiBFYWNoIHNsaWNlIHJlcHJlc2VudHMgYSBjYXRlZ29yeSwgYW5kIGl0cyBzaXplIHJlZmxlY3RzIGl0cyBwZXJjZW50YWdlIGNvbnRyaWJ1dGlvbi4gTGFyZ2VyIHNsaWNlcyBpbmRpY2F0ZSBtb3JlIGRvbWluYW50IHBlcmZvcm1hbmNlIGNhdGVnb3JpZXMsIHdoaWxlIHNtYWxsZXIgc2xpY2VzIHNob3cgbGVzcyBmcmVxdWVudCBvY2N1cnJlbmNlcy4gVGhpcyB2aXN1YWxpemF0aW9uIGhlbHBzIHRvIHF1aWNrbHkgdW5kZXJzdGFuZCB0aGUgb3ZlcmFsbCBjb21wb3NpdGlvbiBvZiBzYWxlcyBwZXJmb3JtYW5jZSBhbmQgaWRlbnRpZnkgd2hpY2ggY2F0ZWdvcmllcyBjb250cmlidXRlIHRoZSBtb3N0IHRvIHRvdGFsIHNhbGVzLg0KDQo8L2Rpdj4NCg0KDQojIE11bHRpIENvbXBhbnkgRGF0YSBTZXQgU2ltdWxhdGlvbiANCg0KYGBgez1odG1sfQ0KPCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJlbiI+DQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+DQogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPg0KICAgIDx0aXRsZT5NdWx0aS1Db21wYW55IFNpbXVsYXRpb24gLSBGb3JtYWwgRXhwbGFuYXRpb248L3RpdGxlPg0KICAgIDxzdHlsZT4NCiAgICAgICAgKiB7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgICAgICBwYWRkaW5nOiAwOw0KICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDsNCiAgICAgICAgfQ0KDQogICAgICAgIGJvZHkgew0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2Q5ZDZjZjsNCiAgICAgICAgICAgIG1pbi1oZWlnaHQ6IDEwMHZoOw0KICAgICAgICAgICAgZGlzcGxheTogZmxleDsNCiAgICAgICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICAgICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnU2Vnb2UgVUknLCAnUm9ib3RvJywgJ05vdG8gU2FucycsIHN5c3RlbS11aSwgc2Fucy1zZXJpZjsNCiAgICAgICAgICAgIHBhZGRpbmc6IDI0cHg7DQogICAgICAgIH0NCg0KICAgICAgICAubWFyb29uLWJveCB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNmQyZTJlOw0KICAgICAgICAgICAgbWF4LXdpZHRoOiA4NjBweDsNCiAgICAgICAgICAgIHdpZHRoOiAxMDAlOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMjRweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMTJweCAyNHB4IHJnYmEoMCwgMCwgMCwgMC4yKTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDJyZW0gMnJlbTsNCiAgICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICM5YjZhNWM7DQogICAgICAgIH0NCg0KICAgICAgICAubWFyb29uLWJveCBwIHsNCiAgICAgICAgICAgIGNvbG9yOiAjZjBlMmQ0Ow0KICAgICAgICAgICAgZm9udC1zaXplOiAxLjA1cmVtOw0KICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDEuNjU7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDQwMDsNCiAgICAgICAgICAgIGxldHRlci1zcGFjaW5nOiAwLjJweDsNCiAgICAgICAgICAgIG1hcmdpbjogMDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5oaWdobGlnaHQgew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2Y1YzU0MjsNCiAgICAgICAgICAgIGNvbG9yOiAjM2ExYTFhOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgICAgICAgICBwYWRkaW5nOiAwLjFyZW0gMC4zcmVtOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNnB4Ow0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdDb3VyaWVyIE5ldycsIG1vbm9zcGFjZTsNCiAgICAgICAgfQ0KDQogICAgICAgIGNvZGUgew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzRhMWUxZTsNCiAgICAgICAgICAgIGNvbG9yOiAjZjVlMmNlOw0KICAgICAgICAgICAgcGFkZGluZzogMC4ycmVtIDAuNHJlbTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnQ291cmllciBOZXcnLCBtb25vc3BhY2U7DQogICAgICAgIH0NCiAgICA8L3N0eWxlPg0KPC9oZWFkPg0KPGJvZHk+DQo8ZGl2IGNsYXNzPSJtYXJvb24tYm94Ij4NCiAgICA8cD4NCiAgICAgICAgSW4gdGhpcyBzZWdtZW50LCB3ZSBkaXNjdXNzIHRoZSA8Y29kZT5nZW5lcmF0ZV9jb21wYW55X2RhdGEobl9jb21wYW55LCBuX2VtcGxveWVlcyk8L2NvZGU+IGZ1bmN0aW9uLCB3aGljaCBnZW5lcmF0ZXMgYSBkYXRhc2V0IGNvbnRhaW5pbmcgdGhlIGZvbGxvd2luZyBjb2x1bW5zOiA8Y29kZT5jb21wYW55X2lkPC9jb2RlPiwgPGNvZGU+ZW1wbG95ZWVfaWQ8L2NvZGU+LCA8Y29kZT5zYWxhcnk8L2NvZGU+LCA8Y29kZT5kZXBhcnRtZW50PC9jb2RlPiwgPGNvZGU+cGVyZm9ybWFuY2Vfc2NvcmU8L2NvZGU+LCBhbmQgPGNvZGU+S1BJX3Njb3JlPC9jb2RlPi4gVGhpcyBmdW5jdGlvbiB1c2VzIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPm5lc3RlZCBsb29wczwvc3Bhbj4g4oCUIGFuIG91dGVyIGxvb3AgaXRlcmF0ZXMgb3ZlciBlYWNoIGNvbXBhbnksIGFuZCBhbiBpbm5lciBsb29wIGl0ZXJhdGVzIG92ZXIgZWFjaCBlbXBsb3llZSB3aXRoaW4gdGhhdCBjb21wYW55LiBTdWJzZXF1ZW50bHksIHRoZSBmdW5jdGlvbiBhcHBsaWVzIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPmNvbmRpdGlvbmFsIGxvZ2ljPC9zcGFuPiB0byBpZGVudGlmeSB0b3AgcGVyZm9ybWVycyBiYXNlZCBvbiB0aGUgcnVsZSA8Y29kZT5LUElfc2NvcmUgPiA5MDwvY29kZT4uIEFmdGVyIGdlbmVyYXRpbmcgdGhlIGRhdGEsIHRoZSBmdW5jdGlvbiBjYWxjdWxhdGVzIGEgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+c3VtbWFyeSBwZXIgY29tcGFueTwvc3Bhbj4gaW5jbHVkaW5nIGF2ZXJhZ2Ugc2FsYXJ5LCBhdmVyYWdlIHBlcmZvcm1hbmNlIHNjb3JlLCBhbmQgbWF4aW11bSBLUEkgc2NvcmUuIEZpbmFsbHksIHRoZSBmdW5jdGlvbiBhbHNvIHByb3ZpZGVzIGEgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+c3VtbWFyeSB0YWJsZTwvc3Bhbj4gYW5kIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPnBsb3RzPC9zcGFuPiAoc3VjaCBhcyBiYXIgY2hhcnRzIG9yIGJveHBsb3RzKSB0byB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbiBhbmQgY29tcGFyaXNvbiBhY3Jvc3MgY29tcGFuaWVzLg0KICAgIDwvcD4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCiMjIENvbXBhbnkgRGF0YSANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoRFQpDQoNCnNldC5zZWVkKDEyMykNCg0KZ2VuZXJhdGVfaG90ZWxfZGF0YSA8LSBmdW5jdGlvbihuX2NvbXBhbnkgPSAzLCBuX2VtcGxveWVlcyA9IDIwKSB7DQogIA0KICBkYXRhX2xpc3QgPC0gbGlzdCgpDQogIGNvdW50ZXIgPC0gMQ0KICANCiAgZGVwYXJ0bWVudHMgPC0gYygNCiAgICAiRnJvbnQgT2ZmaWNlIiwgIkhvdXNla2VlcGluZyIsICJGb29kICYgQmV2ZXJhZ2UiLA0KICAgICJLaXRjaGVuIiwgIk1haW50ZW5hbmNlIiwgIkhSIiwgIkZpbmFuY2UiDQogICkNCiAgDQogIGZvciAoYyBpbiAxOm5fY29tcGFueSkgew0KICAgIA0KICAgIGZvciAoZSBpbiAxOm5fZW1wbG95ZWVzKSB7DQogICAgICANCiAgICAgIHNhbGFyeSA8LSByb3VuZChydW5pZigxLCAzMDAwLCAxMDAwMCksIDApDQogICAgICBwZXJmb3JtYW5jZV9zY29yZSA8LSByb3VuZChydW5pZigxLCA2MCwgMTAwKSwgMSkNCiAgICAgIEtQSV9zY29yZSA8LSByb3VuZChydW5pZigxLCA2NSwgMTAwKSwgMSkNCiAgICAgIA0KICAgICAgIyBDb25kaXRpb25hbCBsb2dpYyANCiAgICAgIGlmIChLUElfc2NvcmUgPiA5MCkgew0KICAgICAgICB0b3Bfc3RhdHVzIDwtICJUb3AgUGVyZm9ybWVyIg0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgdG9wX3N0YXR1cyA8LSAiUmVndWxhciINCiAgICAgIH0NCiAgICAgIA0KICAgICAgZGF0YV9saXN0W1tjb3VudGVyXV0gPC0gZGF0YS5mcmFtZSgNCiAgICAgICAgY29tcGFueV9pZCA9IHBhc3RlMCgiSG90ZWxfIiwgYyksDQogICAgICAgIGVtcGxveWVlX2lkID0gcGFzdGUwKCJIIiwgYywgIl9FIiwgc3ByaW50ZigiJTAyZCIsIGUpKSwNCiAgICAgICAgc2FsYXJ5ID0gc2FsYXJ5LA0KICAgICAgICBkZXBhcnRtZW50ID0gc2FtcGxlKGRlcGFydG1lbnRzLCAxKSwNCiAgICAgICAgcGVyZm9ybWFuY2Vfc2NvcmUgPSBwZXJmb3JtYW5jZV9zY29yZSwNCiAgICAgICAgS1BJX3Njb3JlID0gS1BJX3Njb3JlLA0KICAgICAgICB0b3BfcGVyZm9ybWVyID0gdG9wX3N0YXR1cyAgICMga29sb20gYmFydQ0KICAgICAgKQ0KICAgICAgDQogICAgICBjb3VudGVyIDwtIGNvdW50ZXIgKyAxDQogICAgfQ0KICB9DQogIA0KICBob3RlbF9kYXRhIDwtIGRvLmNhbGwocmJpbmQsIGRhdGFfbGlzdCkNCiAgcmV0dXJuKGhvdGVsX2RhdGEpDQp9DQoNCmhvdGVsX2RhdGEgPC0gZ2VuZXJhdGVfaG90ZWxfZGF0YSgzLCAyMCkNCg0KIyB0YW1waWxrYW4NCmRhdGF0YWJsZShob3RlbF9kYXRhKQ0KYGBgDQoNCiMjIFN1bW1hcnkgcGVyIGNvbXBhbnkNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KERUKQ0KDQojIFN1bW1hcnkgcGVyIGNvbXBhbnkNCmNvbXBhbnlfc3VtbWFyeSA8LSBob3RlbF9kYXRhICU+JQ0KICBncm91cF9ieShjb21wYW55X2lkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGF2Z19zYWxhcnkgPSByb3VuZChtZWFuKHNhbGFyeSksIDIpLA0KICAgIGF2Z19wZXJmb3JtYW5jZSA9IHJvdW5kKG1lYW4ocGVyZm9ybWFuY2Vfc2NvcmUpLCAyKSwNCiAgICBtYXhfS1BJID0gbWF4KEtQSV9zY29yZSksDQogICAgdG90YWxfZW1wbG95ZWUgPSBuKCksDQogICAgdG9wX3BlcmZvcm1lcnMgPSBzdW0odG9wX3BlcmZvcm1lciA9PSAiVG9wIFBlcmZvcm1lciIpDQogICkNCg0KIyBUYW1waWxrYW4gZGFsYW0gRFQNCmRhdGF0YWJsZSgNCiAgY29tcGFueV9zdW1tYXJ5LA0KICBvcHRpb25zID0gbGlzdCgNCiAgICBwYWdlTGVuZ3RoID0gNSwNCiAgICBkb20gPSAnQmZydGlwJywNCiAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnLCAncGRmJywgJ3ByaW50JykNCiAgKSwNCiAgcm93bmFtZXMgPSBGQUxTRSwNCiAgY2FwdGlvbiA9ICJDb21wYW55IFBlcmZvcm1hbmNlIFN1bW1hcnkiDQopDQpgYGANCg0KIyMgVmlzdWFsaXphdGlvbg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShwbG90bHkpDQoNCnBsb3RfbHkoDQogIGRhdGEgPSBjb21wYW55X3N1bW1hcnksDQogIHggPSB+Y29tcGFueV9pZCwNCiAgeSA9IH5hdmdfcGVyZm9ybWFuY2UsDQogIHR5cGUgPSAiYmFyIiwNCiAgbWFya2VyID0gbGlzdChjb2xvciA9IGMoIiMwMEZGRkYiLCAiI0ZGMDBGRiIsICIjMzlGRjE0IikpLA0KICBuYW1lID0gfmNvbXBhbnlfaWQNCikgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9ICJBdmVyYWdlIFBlcmZvcm1hbmNlIFNjb3JlIGJ5IENvbXBhbnkiLA0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJDb21wYW55IiwgY29sb3IgPSAid2hpdGUiKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQXZlcmFnZSBQZXJmb3JtYW5jZSBTY29yZSIsIGNvbG9yID0gIndoaXRlIiksDQogICAgcGxvdF9iZ2NvbG9yID0gImJsYWNrIiwNCiAgICBwYXBlcl9iZ2NvbG9yID0gImJsYWNrIiwNCiAgICBmb250ID0gbGlzdChjb2xvciA9ICJ3aGl0ZSIpDQogICkNCmBgYA0KDQo8ZGl2IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNGRkY5QzQ7IHBhZGRpbmc6MTVweDsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3JkZXI6MXB4IHNvbGlkICNGREQ4MzU7IG1hcmdpbi10b3A6MTBweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPg0KDQoqKkludGVycHJldGF0aW9uKioNCg0KVGhlIGJhciBjaGFydCBjb21wYXJlcyB0aGUgYXZlcmFnZSBwZXJmb3JtYW5jZSBzY29yZXMgYWNyb3NzIHRoZSB0aHJlZSBjb21wYW5pZXMuIEVhY2ggYmFyIHJlcHJlc2VudHMgYSBjb21wYW55LCBhbmQgaXRzIGhlaWdodCBpbmRpY2F0ZXMgdGhlIG92ZXJhbGwgcGVyZm9ybWFuY2UgbGV2ZWwgb2YgaXRzIGVtcGxveWVlcy4gVGhlIGNvbXBhbnkgd2l0aCB0aGUgaGlnaGVzdCBiYXIgZGVtb25zdHJhdGVzIHRoZSBzdHJvbmdlc3QgYXZlcmFnZSBwZXJmb3JtYW5jZSwgc3VnZ2VzdGluZyBiZXR0ZXIgZW1wbG95ZWUgcHJvZHVjdGl2aXR5IGFuZCBlZmZlY3RpdmVuZXNzLiBEaWZmZXJlbmNlcyBpbiBiYXIgaGVpZ2h0cyBoaWdobGlnaHQgdmFyaWF0aW9ucyBpbiB3b3JrZm9yY2UgcXVhbGl0eSBhbW9uZyB0aGUgY29tcGFuaWVzLCBtYWtpbmcgaXQgZWFzaWVyIHRvIGlkZW50aWZ5IHdoaWNoIGNvbXBhbnkgcGVyZm9ybXMgYmVzdCBvdmVyYWxsLiBUaGlzIHZpc3VhbGl6YXRpb24gcHJvdmlkZXMgYSBjbGVhciBhbmQgc3RyYWlnaHRmb3J3YXJkIGNvbXBhcmlzb24sIHN1cHBvcnRpbmcgcGVyZm9ybWFuY2UgZXZhbHVhdGlvbiBhbmQgc3RyYXRlZ2ljIGRlY2lzaW9uLW1ha2luZy4NCg0KPC9kaXY+DQoNCiMgTW9udGUgQ2FybG8gU2ltdWxhdGlvbjogUGkgJiBQcm9iYWJpbGl0eQ0KDQpgYGB7PWh0bWx9DQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sIGxhbmc9ImVuIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4NCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogICAgPHRpdGxlPk1vbnRlIENhcmxvIFNpbXVsYXRpb24gLSBQaSAmIFByb2JhYmlsaXR5PC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNkOWQ2Y2Y7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1NlZ29lIFVJJywgJ1JvYm90bycsICdOb3RvIFNhbnMnLCBzeXN0ZW0tdWksIHNhbnMtc2VyaWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyNHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzZkMmUyZTsNCiAgICAgICAgICAgIG1heC13aWR0aDogODYwcHg7DQogICAgICAgICAgICB3aWR0aDogMTAwJTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDI0cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDEycHggMjRweCByZ2JhKDAsIDAsIDAsIDAuMik7DQogICAgICAgICAgICBwYWRkaW5nOiAycmVtIDJyZW07DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjOWI2YTVjOw0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggcCB7DQogICAgICAgICAgICBjb2xvcjogI2YwZTJkNDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMS4wNXJlbTsNCiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjY1Ow0KICAgICAgICAgICAgdGV4dC1hbGlnbjoganVzdGlmeTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA0MDA7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMC4ycHg7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgIH0NCg0KICAgICAgICAuaGlnaGxpZ2h0IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmNWM1NDI7DQogICAgICAgICAgICBjb2xvcjogIzNhMWExYTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICAgICAgICAgcGFkZGluZzogMC4xcmVtIDAuM3JlbTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnQ291cmllciBOZXcnLCBtb25vc3BhY2U7DQogICAgICAgIH0NCg0KICAgICAgICBjb2RlIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0YTFlMWU7DQogICAgICAgICAgICBjb2xvcjogI2Y1ZTJjZTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDAuMnJlbSAwLjRyZW07DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgbW9ub3NwYWNlOw0KICAgICAgICB9DQogICAgPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5Pg0KPGRpdiBjbGFzcz0ibWFyb29uLWJveCI+DQogICAgPHA+DQogICAgICAgIEluIHRoaXMgc2VnbWVudCwgd2UgZGlzY3VzcyB0aGUgPGNvZGU+bW9udGVfY2FybG9fcGkobl9wb2ludHMpPC9jb2RlPiBmdW5jdGlvbiwgd2hpY2ggcGVyZm9ybXMgYSBNb250ZSBDYXJsbyBzaW11bGF0aW9uIHRvIGVzdGltYXRlIHRoZSB2YWx1ZSBvZiDPgCAocGkpIGFsb25nIHdpdGggYWRkaXRpb25hbCBwcm9iYWJpbGl0eSBhbmFseXNpcy4gVGhlIGZ1bmN0aW9uIHVzZXMgYSA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5sb29wPC9zcGFuPiB0aGF0IHJ1bnMgZm9yIGEgc3BlY2lmaWVkIG51bWJlciBvZiBpdGVyYXRpb25zIChuX3BvaW50cykuIFdpdGhpbiBlYWNoIGl0ZXJhdGlvbiwgcmFuZG9tIHBvaW50cyBhcmUgZ2VuZXJhdGVkIHdpdGhpbiBhIHNxdWFyZSBib3VuZGluZyBhIHVuaXQgY2lyY2xlLiBUaGUgZnVuY3Rpb24gdGhlbiA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5jb3VudHMgaG93IG1hbnkgcG9pbnRzIGZhbGwgaW5zaWRlIHRoZSBjaXJjbGU8L3NwYW4+IGFuZCB1c2VzIHRoZSByYXRpbyBvZiBwb2ludHMgaW5zaWRlIHRoZSBjaXJjbGUgdG8gdG90YWwgcG9pbnRzIHRvIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPmNvbXB1dGUgYW4gYXBwcm94aW1hdGlvbiBvZiDPgDwvc3Bhbj4uIEFkZGl0aW9uYWxseSwgdGhlIGZ1bmN0aW9uIHBlcmZvcm1zIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPnByb2JhYmlsaXR5IGFuYWx5c2lzPC9zcGFuPiBieSBjYWxjdWxhdGluZyB0aGUgcHJvYmFiaWxpdHkgb2YgcmFuZG9tIHBvaW50cyBmYWxsaW5nIGluc2lkZSBhIHNwZWNpZmljIHN1Yi1zcXVhcmUgcmVnaW9uLiBGaW5hbGx5LCB0aGUgZnVuY3Rpb24gcHJvZHVjZXMgYSA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5wbG90PC9zcGFuPiB0aGF0IHZpc3VhbGl6ZXMgdGhlIGdlbmVyYXRlZCBwb2ludHMsIGRpc3Rpbmd1aXNoaW5nIGJldHdlZW4gcG9pbnRzIHRoYXQgZmFsbCBpbnNpZGUgdGhlIGNpcmNsZSBhbmQgdGhvc2Ugb3V0c2lkZSwgcHJvdmlkaW5nIGFuIGludHVpdGl2ZSB1bmRlcnN0YW5kaW5nIG9mIHRoZSBNb250ZSBDYXJsbyBtZXRob2QuDQogICAgPC9wPg0KPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KIyMgTG9vcCBmb3IgaXRlcmF0aW9uIA0KDQpgYGB7PWh0bWx9DQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sIGxhbmc9ImVuIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4NCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogICAgPHRpdGxlPkxvb3AgSXRlcmF0aW9uIC0gTW9udGUgQ2FybG8gRXhwbGFuYXRpb248L3RpdGxlPg0KICAgIDxzdHlsZT4NCiAgICAgICAgKiB7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgICAgICBwYWRkaW5nOiAwOw0KICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDsNCiAgICAgICAgfQ0KDQogICAgICAgIGJvZHkgew0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgJ1RpbWVzIE5ldyBSb21hbicsIFRpbWVzLCBzZXJpZjsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzZTBiMGIgMCUsICMxYTAxMDEgMTAwJSk7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBwYWRkaW5nOiAyMHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRhaW5lciB7DQogICAgICAgICAgICBtYXgtd2lkdGg6IDk1MHB4Ow0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZmRmYWY2Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMTZweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMjBweCA0MHB4IHJnYmEoMCwwLDAsMC40KTsNCiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjYjg4NjBiOw0KICAgICAgICB9DQoNCiAgICAgICAgLmNvbnRlbnQgew0KICAgICAgICAgICAgcGFkZGluZzogNDBweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC5kZXNjcmlwdGlvbiB7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDJyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS43Ow0KICAgICAgICAgICAgY29sb3I6ICMyYzE4MTA7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KICAgICAgICAgICAgYmFja2dyb3VuZDogI2ZmZjllZjsNCiAgICAgICAgICAgIHBhZGRpbmc6IDI4cHggMzJweDsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDEycHg7DQogICAgICAgICAgICBib3JkZXItbGVmdDogNXB4IHNvbGlkICNiODg2MGI7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDJweCA4cHggcmdiYSgwLDAsMCwwLjA1KTsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnUGFsYXRpbm8nLCAnR2VvcmdpYScsIHNlcmlmOw0KICAgICAgICB9DQoNCiAgICAgICAgLmRlc2NyaXB0aW9uIHN0cm9uZyB7DQogICAgICAgICAgICBjb2xvcjogIzhiMWExYTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA3MDA7DQogICAgICAgIH0NCg0KICAgICAgICAuci1mdW5jdGlvbiB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjMmQyYTFlOw0KICAgICAgICAgICAgY29sb3I6ICNmMmU2Yzk7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgJ0ZpcmEgQ29kZScsIG1vbm9zcGFjZTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDNweCAxMHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMjBweDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMC45cmVtOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgICAgICAgICAgIGxldHRlci1zcGFjaW5nOiAwLjNweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IGluc2V0IDAgMCAwIDFweCAjYjg4NjBiLCAwIDFweCAycHggcmdiYSgwLDAsMCwwLjEpOw0KICAgICAgICB9DQoNCiAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDYwMHB4KSB7DQogICAgICAgICAgICAuY29udGVudCB7DQogICAgICAgICAgICAgICAgcGFkZGluZzogMjBweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIC5kZXNjcmlwdGlvbiB7DQogICAgICAgICAgICAgICAgcGFkZGluZzogMjBweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIC5yLWZ1bmN0aW9uIHsNCiAgICAgICAgICAgICAgICBmb250LXNpemU6IDAuOHJlbTsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAycHggOHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5Pg0KICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+DQogICAgICAgIDxkaXYgY2xhc3M9ImNvbnRlbnQiPg0KICAgICAgICAgICAgPGRpdiBjbGFzcz0iZGVzY3JpcHRpb24iPg0KICAgICAgICAgICAgICAgIEluIHRoaXMgc2VnbWVudCwgdGhlIGxvb3AgaXRlcmF0aW9uIHBsYXlzIGEga2V5IHJvbGUgYXMgdGhlIG1haW4gbWVjaGFuaXNtIHRvIHJlcGVhdCB0aGUgcmFuZG9tIHBvaW50IGdlbmVyYXRpb24gcHJvY2VzcyBhcyBtYW55IGFzIDxzcGFuIGNsYXNzPSJyLWZ1bmN0aW9uIj5uX3BvaW50czwvc3Bhbj4gdGltZXMuIFdpdGhvdXQgYSBsb29wLCB3ZSBjYW4gb25seSBnZW5lcmF0ZSBvbmUgcG9pbnQsIHdoaWNoIGlzIGNlcnRhaW5seSBub3QgZW5vdWdoIGZvciBhY2N1cmF0ZSBzdGF0aXN0aWNhbCBlc3RpbWF0aW9uLiBUaGUgbW9yZSBpdGVyYXRpb25zICh0aGUgbGFyZ2VyIDxzcGFuIGNsYXNzPSJyLWZ1bmN0aW9uIj5uX3BvaW50czwvc3Bhbj4pLCB0aGUgbW9yZSBhY2N1cmF0ZSB0aGUgZXN0aW1hdGVkIHZhbHVlIG9mIM+AIGJlY29tZXMsIGZvbGxvd2luZyB0aGUgTGF3IG9mIExhcmdlIE51bWJlcnMuDQogICAgICAgICAgICA8L2Rpdj4NCiAgICAgICAgPC9kaXY+DQogICAgPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KIyMgSW1wbGVtZW50YXRpb24NCg0KYGBge3J9DQojIExvYWQgRFQgbGlicmFyeQ0KbGlicmFyeShEVCkNCg0KIyBNb250ZSBDYXJsbyBzaW11bGF0aW9uIHRvIGVzdGltYXRlIHBpDQpzZXQuc2VlZCgxMjMpICMgZm9yIHJlcHJvZHVjaWJpbGl0eQ0KDQpuX3BvaW50cyA8LSAyNzUwDQppbnNpZGVfY291bnQgPC0gMA0KDQpmb3IgKGkgaW4gMTpuX3BvaW50cykgew0KICB4IDwtIHJ1bmlmKDEsIC0xLCAxKQ0KICB5IDwtIHJ1bmlmKDEsIC0xLCAxKQ0KICBpZiAoeF4yICsgeV4yIDw9IDEpIHsNCiAgICBpbnNpZGVfY291bnQgPC0gaW5zaWRlX2NvdW50ICsgMQ0KICB9DQp9DQoNCnBpX2VzdGltYXRlIDwtIDQgKiBpbnNpZGVfY291bnQgLyBuX3BvaW50cw0KDQojIENyZWF0ZSBhIHN1bW1hcnkgZGF0YSBmcmFtZQ0KcmVzdWx0c19kZiA8LSBkYXRhLmZyYW1lKA0KICBNZXRyaWMgPSBjKCJUb3RhbCBwb2ludHMgKG5fcG9pbnRzKSIsIA0KICAgICAgICAgICAgICJQb2ludHMgaW5zaWRlIGNpcmNsZSIsIA0KICAgICAgICAgICAgICJFc3RpbWF0ZWQgz4AiLCANCiAgICAgICAgICAgICAiQWN0dWFsIM+AIiwgDQogICAgICAgICAgICAgIkVycm9yIiksDQogIFZhbHVlID0gYyhuX3BvaW50cywgDQogICAgICAgICAgICBpbnNpZGVfY291bnQsIA0KICAgICAgICAgICAgcm91bmQocGlfZXN0aW1hdGUsIDYpLCANCiAgICAgICAgICAgIHBpLCANCiAgICAgICAgICAgIGFicyhyb3VuZChwaV9lc3RpbWF0ZSAtIHBpLCA2KSkpDQopDQoNCiMgRGlzcGxheSBhcyBpbnRlcmFjdGl2ZSB0YWJsZQ0KZGF0YXRhYmxlKHJlc3VsdHNfZGYsIA0KICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICd0JywgDQogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDUpLA0KICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsDQogICAgICAgICAgY2FwdGlvbiA9ICJNb250ZSBDYXJsbyBTaW11bGF0aW9uIFJlc3VsdHMgZm9yIM+AIEVzdGltYXRpb24iKQ0KYGBgDQoNCiMjIENvbXB1dGUgcHJvYmFiaWxpdHkgb2YgcmFuZG9tIHBvaW50cyBmYWxsaW5nICBpbiBzdWItc3F1YXJlDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KERUKQ0KDQojIFBST0JBQklMSVRZIE9GIFJBTkRPTSBQT0lOVFMgSU4gU1VCLVNRVUFSRQ0KDQoNCiMgUGFyYW1ldGVyDQpuX3BvaW50cyA8LSAyNzUwDQoNCiMgU3ViLXNxdWFyZSBib3VuZGFyaWVzICgwLjUgdG8gMSkNCnhfbWluIDwtIDAuNQ0KeF9tYXggPC0gMQ0KeV9taW4gPC0gMC41DQp5X21heCA8LSAxDQoNCiMgSW5pdGlhbGl6ZSBjb3VudGVyDQpzdWJfc3F1YXJlX2NvdW50IDwtIDANCg0KIyBMb29wIHRocm91Z2ggaXRlcmF0aW9ucw0KZm9yIChpIGluIDE6bl9wb2ludHMpIHsNCiAgDQogICMgR2VuZXJhdGUgcmFuZG9tIHBvaW50ICh4LCB5KSBiZXR3ZWVuIC0xIGFuZCAxDQogIHggPC0gcnVuaWYoMSwgLTEsIDEpDQogIHkgPC0gcnVuaWYoMSwgLTEsIDEpDQogIA0KICAjIENoZWNrIGlmIHBvaW50IGlzIGluc2lkZSB0aGUgc3ViLXNxdWFyZQ0KICBpZiAoeCA+PSB4X21pbiAmJiB4IDw9IHhfbWF4ICYmIHkgPj0geV9taW4gJiYgeSA8PSB5X21heCkgew0KICAgIHN1Yl9zcXVhcmVfY291bnQgPC0gc3ViX3NxdWFyZV9jb3VudCArIDENCiAgfQ0KfQ0KDQojIENhbGN1bGF0ZSBwcm9iYWJpbGl0eQ0KcHJvYmFiaWxpdHkgPC0gc3ViX3NxdWFyZV9jb3VudCAvIG5fcG9pbnRzDQpwZXJjZW50YWdlIDwtIHByb2JhYmlsaXR5ICogMTAwDQoNCiMgQ3JlYXRlIHJlc3VsdCB0YWJsZQ0KcmVzdWx0IDwtIGRhdGEuZnJhbWUoDQogIFN0YXRpc3RpYyA9IGMoIlRvdGFsIFBvaW50cyIsICJQb2ludHMgSW5zaWRlIFN1Yi1zcXVhcmUiLCAiUHJvYmFiaWxpdHkiLCAiUGVyY2VudGFnZSIpLA0KICBWYWx1ZSA9IGMoDQogICAgZm9ybWF0KG5fcG9pbnRzLCBiaWcubWFyayA9ICIsIiksIA0KICAgIGZvcm1hdChzdWJfc3F1YXJlX2NvdW50LCBiaWcubWFyayA9ICIsIiksIA0KICAgIHBhc3RlMChyb3VuZChwcm9iYWJpbGl0eSwgNikpLA0KICAgIHBhc3RlMChyb3VuZChwZXJjZW50YWdlLCA0KSwgIiUiKQ0KICApDQopDQoNCiMgRGlzcGxheSBpbnRlcmFjdGl2ZSB0YWJsZQ0KZGF0YXRhYmxlKA0KICByZXN1bHQsDQogIG9wdGlvbnMgPSBsaXN0KA0KICAgIGRvbSA9ICd0JywNCiAgICBwYWdpbmcgPSBGQUxTRSwNCiAgICBvcmRlcmluZyA9IEZBTFNFDQogICksDQogIHJvd25hbWVzID0gRkFMU0UsDQogIGNhcHRpb24gPSBodG1sdG9vbHM6OnRhZ3MkY2FwdGlvbigNCiAgICBzdHlsZSA9ICJjYXB0aW9uLXNpZGU6IHRvcDsgdGV4dC1hbGlnbjogY2VudGVyOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBib2xkOyIsDQogICAgIlByb2JhYmlsaXR5IG9mIFJhbmRvbSBQb2ludHMgaW4gU3ViLVNxdWFyZSAoMC41IHRvIDEpIg0KICApDQopDQpgYGANCg0KIyMgUGxvdCBwb2ludHMgaW5zaWRlIHZzIG91dHNpZGUgY2lyY2xlIA0KDQpgYGB7cn0NCg0KIyBQTE9UIFBPSU5UUyBJTlNJREUgVlMgT1VUU0lERSBDSVJDTEUNCg0KbGlicmFyeShwbG90bHkpDQoNCiMgUGFyYW1ldGVyDQpuX3BvaW50cyA8LSAyNzUwDQoNCiMgSW5pdGlhbGl6ZSB2ZWN0b3JzIHRvIHN0b3JlIGNvb3JkaW5hdGVzDQp4X2Nvb3JkcyA8LSBudW1lcmljKG5fcG9pbnRzKQ0KeV9jb29yZHMgPC0gbnVtZXJpYyhuX3BvaW50cykNCmluc2lkZV9mbGFnIDwtIGxvZ2ljYWwobl9wb2ludHMpDQoNCiMgTG9vcCB0byBnZW5lcmF0ZSByYW5kb20gcG9pbnRzDQpmb3IgKGkgaW4gMTpuX3BvaW50cykgew0KICB4X2Nvb3Jkc1tpXSA8LSBydW5pZigxLCAtMSwgMSkNCiAgeV9jb29yZHNbaV0gPC0gcnVuaWYoMSwgLTEsIDEpDQogIA0KICAjIENoZWNrIGlmIHBvaW50IGlzIGluc2lkZSB0aGUgY2lyY2xlDQogIGlmICh4X2Nvb3Jkc1tpXV4yICsgeV9jb29yZHNbaV1eMiA8PSAxKSB7DQogICAgaW5zaWRlX2ZsYWdbaV0gPC0gVFJVRQ0KICB9IGVsc2Ugew0KICAgIGluc2lkZV9mbGFnW2ldIDwtIEZBTFNFDQogIH0NCn0NCg0KIyBDYWxjdWxhdGUgcGkgZXN0aW1hdGlvbg0KaW5zaWRlX2NvdW50IDwtIHN1bShpbnNpZGVfZmxhZykNCnBpX2VzdGltYXRlIDwtIDQgKiBpbnNpZGVfY291bnQgLyBuX3BvaW50cw0KDQojIENyZWF0ZSBkYXRhIGZyYW1lDQpkZiA8LSBkYXRhLmZyYW1lKA0KICB4ID0geF9jb29yZHMsDQogIHkgPSB5X2Nvb3JkcywNCiAgc3RhdHVzID0gaWZlbHNlKGluc2lkZV9mbGFnLCAiSW5zaWRlIENpcmNsZSIsICJPdXRzaWRlIENpcmNsZSIpDQopDQoNCiMgQ3JlYXRlIGNpcmNsZSBib3VuZGFyeSBwb2ludHMNCnRoZXRhIDwtIHNlcSgwLCAyICogcGksIGxlbmd0aC5vdXQgPSA1MDApDQpjaXJjbGUgPC0gZGF0YS5mcmFtZSh4ID0gY29zKHRoZXRhKSwgeSA9IHNpbih0aGV0YSkpDQoNCiMgQ3JlYXRlIHNxdWFyZSBib3VuZGFyeQ0Kc3F1YXJlIDwtIGRhdGEuZnJhbWUoDQogIHggPSBjKC0xLCAxLCAxLCAtMSwgLTEpLA0KICB5ID0gYygtMSwgLTEsIDEsIDEsIC0xKQ0KKQ0KDQojIEdMT1cgSU4gVEhFIERBUksgUExPVCB3aXRoIFBsb3RseQ0KcGxvdF9seSgpICU+JQ0KICANCiAgIyBQb2ludHMgaW5zaWRlIGNpcmNsZSAobmVvbiByZWQpDQogIGFkZF90cmFjZSgNCiAgICBkYXRhID0gZGZbZGYkc3RhdHVzID09ICJJbnNpZGUgQ2lyY2xlIiwgXSwNCiAgICB4ID0gfngsIHkgPSB+eSwNCiAgICB0eXBlID0gInNjYXR0ZXIiLA0KICAgIG1vZGUgPSAibWFya2VycyIsDQogICAgbWFya2VyID0gbGlzdCgNCiAgICAgIHNpemUgPSA1LA0KICAgICAgY29sb3IgPSAiI2ZmMmEyYSIsDQogICAgICBvcGFjaXR5ID0gMC44LA0KICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAiI2ZmMDAwMCIsIHdpZHRoID0gMSkNCiAgICApLA0KICAgIG5hbWUgPSAiSW5zaWRlIENpcmNsZSIsDQogICAgaG92ZXJpbmZvID0gInRleHQiLA0KICAgIHRleHQgPSB+cGFzdGUoIkluc2lkZSBDaXJjbGVcbng6Iiwgcm91bmQoeCwgNCksICJcbnk6Iiwgcm91bmQoeSwgNCkpDQogICkgJT4lDQogIA0KICAjIFBvaW50cyBvdXRzaWRlIGNpcmNsZSAobmVvbiBibHVlKQ0KICBhZGRfdHJhY2UoDQogICAgZGF0YSA9IGRmW2RmJHN0YXR1cyA9PSAiT3V0c2lkZSBDaXJjbGUiLCBdLA0KICAgIHggPSB+eCwgeSA9IH55LA0KICAgIHR5cGUgPSAic2NhdHRlciIsDQogICAgbW9kZSA9ICJtYXJrZXJzIiwNCiAgICBtYXJrZXIgPSBsaXN0KA0KICAgICAgc2l6ZSA9IDMsDQogICAgICBjb2xvciA9ICIjMDBiZmZmIiwNCiAgICAgIG9wYWNpdHkgPSAwLjUsDQogICAgICBsaW5lID0gbGlzdChjb2xvciA9ICIjMDA4OGZmIiwgd2lkdGggPSAwLjUpDQogICAgKSwNCiAgICBuYW1lID0gIk91dHNpZGUgQ2lyY2xlIiwNCiAgICBob3ZlcmluZm8gPSAidGV4dCIsDQogICAgdGV4dCA9IH5wYXN0ZSgiT3V0c2lkZSBDaXJjbGVcbng6Iiwgcm91bmQoeCwgNCksICJcbnk6Iiwgcm91bmQoeSwgNCkpDQogICkgJT4lDQogIA0KICAjIENpcmNsZSBib3VuZGFyeSAobmVvbiBncmVlbiBnbG93KQ0KICBhZGRfdHJhY2UoDQogICAgZGF0YSA9IGNpcmNsZSwNCiAgICB4ID0gfngsIHkgPSB+eSwNCiAgICB0eXBlID0gInNjYXR0ZXIiLA0KICAgIG1vZGUgPSAibGluZXMiLA0KICAgIGxpbmUgPSBsaXN0KA0KICAgICAgY29sb3IgPSAiIzM5ZmYxNCIsDQogICAgICB3aWR0aCA9IDMsDQogICAgICBkYXNoID0gInNvbGlkIg0KICAgICksDQogICAgbmFtZSA9ICJDaXJjbGUgQm91bmRhcnkgKHjCsiArIHnCsiA9IDEpIiwNCiAgICBob3ZlcmluZm8gPSAibm9uZSINCiAgKSAlPiUNCiAgDQogICMgU3F1YXJlIGJvdW5kYXJ5IChuZW9uIHB1cnBsZSkNCiAgYWRkX3RyYWNlKA0KICAgIGRhdGEgPSBzcXVhcmUsDQogICAgeCA9IH54LCB5ID0gfnksDQogICAgdHlwZSA9ICJzY2F0dGVyIiwNCiAgICBtb2RlID0gImxpbmVzIiwNCiAgICBsaW5lID0gbGlzdCgNCiAgICAgIGNvbG9yID0gIiNiZjAwZmYiLA0KICAgICAgd2lkdGggPSAyLA0KICAgICAgZGFzaCA9ICJkYXNoIg0KICAgICksDQogICAgbmFtZSA9ICJTcXVhcmUgQm91bmRhcnkgKC0xIHRvIDEpIiwNCiAgICBob3ZlcmluZm8gPSAibm9uZSINCiAgKSAlPiUNCiAgDQogICMgTGF5b3V0IHdpdGggZGFyayB0aGVtZSAoZ2xvdyBpbiB0aGUgZGFyaykNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gbGlzdCgNCiAgICAgIHRleHQgPSBwYXN0ZSgiTU9OVEUgQ0FSTE8gUEkgRVNUSU1BVElPTlxubiA9Iiwgbl9wb2ludHMsICJ8IEVzdGltYXRlZCBQaSA9Iiwgcm91bmQocGlfZXN0aW1hdGUsIDYpLCAifCBBY3R1YWwgUGkgPSIsIHJvdW5kKHBpLCA2KSksDQogICAgICBmb250ID0gbGlzdChjb2xvciA9ICIjZmZmZmZmIiwgc2l6ZSA9IDE2LCBmYW1pbHkgPSAiQXJpYWwiKSwNCiAgICAgIHggPSAwLjUsDQogICAgICB4YW5jaG9yID0gImNlbnRlciINCiAgICApLA0KICAgIHBhcGVyX2JnY29sb3IgPSAiIzBhMGEwYSIsDQogICAgcGxvdF9iZ2NvbG9yID0gIiMwNTA1MDUiLA0KICAgIHhheGlzID0gbGlzdCgNCiAgICAgIHRpdGxlID0gbGlzdCh0ZXh0ID0gIlggQVhJUyIsIGZvbnQgPSBsaXN0KGNvbG9yID0gIiNmZmZmZmYiKSksDQogICAgICByYW5nZSA9IGMoLTEuMTUsIDEuMTUpLA0KICAgICAgZ3JpZGNvbG9yID0gIiMxYTFhMWEiLA0KICAgICAgemVyb2xpbmVjb2xvciA9ICIjMzMzMzMzIiwNCiAgICAgIHRpY2tmb250ID0gbGlzdChjb2xvciA9ICIjY2NjY2NjIiksDQogICAgICBzaG93Z3JpZCA9IFRSVUUsDQogICAgICBncmlkd2lkdGggPSAwLjUNCiAgICApLA0KICAgIHlheGlzID0gbGlzdCgNCiAgICAgIHRpdGxlID0gbGlzdCh0ZXh0ID0gIlkgQVhJUyIsIGZvbnQgPSBsaXN0KGNvbG9yID0gIiNmZmZmZmYiKSksDQogICAgICByYW5nZSA9IGMoLTEuMTUsIDEuMTUpLA0KICAgICAgZ3JpZGNvbG9yID0gIiMxYTFhMWEiLA0KICAgICAgemVyb2xpbmVjb2xvciA9ICIjMzMzMzMzIiwNCiAgICAgIHRpY2tmb250ID0gbGlzdChjb2xvciA9ICIjY2NjY2NjIiksDQogICAgICBzaG93Z3JpZCA9IFRSVUUsDQogICAgICBncmlkd2lkdGggPSAwLjUsDQogICAgICBzY2FsZWFuY2hvciA9ICJ4IiwNCiAgICAgIHNjYWxlcmF0aW8gPSAxDQogICAgKSwNCiAgICBsZWdlbmQgPSBsaXN0KA0KICAgICAgdGl0bGUgPSBsaXN0KHRleHQgPSAiTEVHRU5EIiwgZm9udCA9IGxpc3QoY29sb3IgPSAiI2ZmZmZmZiIpKSwNCiAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gIiNmZmZmZmYiKSwNCiAgICAgIGJnY29sb3IgPSAicmdiYSgwLDAsMCwwLjcpIiwNCiAgICAgIGJvcmRlcmNvbG9yID0gIiMzOWZmMTQiLA0KICAgICAgYm9yZGVyd2lkdGggPSAxLA0KICAgICAgeCA9IDAuMDIsDQogICAgICB5ID0gMC45OA0KICAgICksDQogICAgaG92ZXJtb2RlID0gImNsb3Nlc3QiLA0KICAgIGFubm90YXRpb25zID0gbGlzdCgNCiAgICAgIGxpc3QoDQogICAgICAgIHRleHQgPSBwYXN0ZSgiSU5TSURFOiIsIGluc2lkZV9jb3VudCwgInwgT1VUU0lERToiLCBuX3BvaW50cyAtIGluc2lkZV9jb3VudCksDQogICAgICAgIHggPSAwLjUsDQogICAgICAgIHkgPSAtMC4wOCwNCiAgICAgICAgeHJlZiA9ICJwYXBlciIsDQogICAgICAgIHlyZWYgPSAicGFwZXIiLA0KICAgICAgICBzaG93YXJyb3cgPSBGQUxTRSwNCiAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiIzM5ZmYxNCIsIHNpemUgPSAxMSwgZmFtaWx5ID0gIm1vbm9zcGFjZSIpLA0KICAgICAgICBiZ2NvbG9yID0gInJnYmEoMCwwLDAsMC42KSIsDQogICAgICAgIGJvcmRlcnBhZCA9IDQNCiAgICAgICksDQogICAgICBsaXN0KA0KICAgICAgICB0ZXh0ID0gIkdMT1cgSU4gVEhFIERBUksgTU9ERSIsDQogICAgICAgIHggPSAwLjUsDQogICAgICAgIHkgPSAxLjA1LA0KICAgICAgICB4cmVmID0gInBhcGVyIiwNCiAgICAgICAgeXJlZiA9ICJwYXBlciIsDQogICAgICAgIHNob3dhcnJvdyA9IEZBTFNFLA0KICAgICAgICBmb250ID0gbGlzdChjb2xvciA9ICIjYmYwMGZmIiwgc2l6ZSA9IDksIGZhbWlseSA9ICJtb25vc3BhY2UiKQ0KICAgICAgKQ0KICAgICkNCiAgKSAlPiUNCiAgY29uZmlnKA0KICAgIGRpc3BsYXlNb2RlQmFyID0gVFJVRSwNCiAgICBtb2RlQmFyQnV0dG9uc1RvUmVtb3ZlID0gYygibGFzc28yZCIsICJzZWxlY3QyZCIpLA0KICAgIGRpc3BsYXlsb2dvID0gRkFMU0UsDQogICAgdG9JbWFnZUJ1dHRvbk9wdGlvbnMgPSBsaXN0KGZvcm1hdCA9ICJwbmciLCBmaWxlbmFtZSA9ICJtb250ZV9jYXJsb19nbG93IikNCiAgKQ0KYGBgDQoNCjxkaXYgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0ZGRjlDNDsgcGFkZGluZzoxNXB4OyBib3JkZXItcmFkaXVzOjEwcHg7IGJvcmRlcjoxcHggc29saWQgI0ZERDgzNTsgbWFyZ2luLXRvcDoxMHB4OyB0ZXh0LWFsaWduOiBqdXN0aWZ5OyI+DQoNCioqSW50ZXJwcmV0YXRpb24qKg0KDQpUaHJvd2luZyAyLDc1MCBkYXJ0cyBhdCBhIHNxdWFyZSB0YXJnZXQgdGhhdCBoYXMgYSBjaXJjbGUgZHJhd24gaW5zaWRlIGl0LCBhbmQgb25seSBhYm91dCAxNzIgZGFydHMgKDYuMjUlKSBoaXQgaW5zaWRlIHRoZSBjaXJjbGUuIFVzaW5nIHRoaXMgcmF0aW8sIHdlIGNhbiBjYWxjdWxhdGUgdGhhdCDPgCBpcyBhcHByb3hpbWF0ZWx5IDMuMTQgYmVjYXVzZSB0aGUgcHJvcG9ydGlvbiBvZiBkYXJ0cyBpbnNpZGUgdGhlIGNpcmNsZSBlcXVhbHMgdGhlIGNpcmNsZSdzIGFyZWEgKM+AKSBkaXZpZGVkIGJ5IHRoZSBzcXVhcmUncyBhcmVhICg0KS4gVGhlIG1vcmUgZGFydHMgd2UgdGhyb3csIHRoZSBtb3JlIGFjY3VyYXRlIG91ciBwaSB2YWx1ZSBiZWNvbWVzLCBhcyB0aGUgbGF3IG9mIGxhcmdlIG51bWJlcnMgcmVkdWNlcyByYW5kb20gdmFyaWF0aW9uIGFuZCBwdXNoZXMgdGhlIGVzdGltYXRlIGNsb3NlciB0byB0aGUgdHJ1ZSBtYXRoZW1hdGljYWwgY29uc3RhbnQuIFRoaXMgTW9udGUgQ2FybG8gbWV0aG9kIGRlbW9uc3RyYXRlcyBob3cgcmFuZG9tIHNhbXBsaW5nIGNhbiBzb2x2ZQ0KDQo8L2Rpdj4NCg0KIyBBZHZhbmNlZCBEYXRhIFRyYW5zZm9ybWF0aW9uICYgRmVhdHVyZSBFbmdpbmVlcmluZw0KDQpgYGB7PWh0bWx9DQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sIGxhbmc9ImVuIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4NCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogICAgPHRpdGxlPkFkdmFuY2VkIERhdGEgVHJhbnNmb3JtYXRpb24gJiBGZWF0dXJlIEVuZ2luZWVyaW5nPC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNkOWQ2Y2Y7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1NlZ29lIFVJJywgJ1JvYm90bycsICdOb3RvIFNhbnMnLCBzeXN0ZW0tdWksIHNhbnMtc2VyaWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyNHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzZkMmUyZTsNCiAgICAgICAgICAgIG1heC13aWR0aDogODYwcHg7DQogICAgICAgICAgICB3aWR0aDogMTAwJTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDI0cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDEycHggMjRweCByZ2JhKDAsIDAsIDAsIDAuMik7DQogICAgICAgICAgICBwYWRkaW5nOiAycmVtIDJyZW07DQogICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjOWI2YTVjOw0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggcCB7DQogICAgICAgICAgICBjb2xvcjogI2YwZTJkNDsNCiAgICAgICAgICAgIGZvbnQtc2l6ZTogMS4wNXJlbTsNCiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjY1Ow0KICAgICAgICAgICAgdGV4dC1hbGlnbjoganVzdGlmeTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA0MDA7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMC4ycHg7DQogICAgICAgICAgICBtYXJnaW46IDA7DQogICAgICAgIH0NCg0KICAgICAgICAuaGlnaGxpZ2h0IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmNWM1NDI7DQogICAgICAgICAgICBjb2xvcjogIzNhMWExYTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICAgICAgICAgcGFkZGluZzogMC4xcmVtIDAuM3JlbTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnQ291cmllciBOZXcnLCBtb25vc3BhY2U7DQogICAgICAgIH0NCg0KICAgICAgICBjb2RlIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0YTFlMWU7DQogICAgICAgICAgICBjb2xvcjogI2Y1ZTJjZTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDAuMnJlbSAwLjRyZW07DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgbW9ub3NwYWNlOw0KICAgICAgICB9DQogICAgPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5Pg0KPGRpdiBjbGFzcz0ibWFyb29uLWJveCI+DQogICAgPHA+DQogICAgICAgIEluIHRoaXMgc2VnbWVudCwgd2UgZGlzY3VzcyA8c3Ryb25nPkFkdmFuY2VkIERhdGEgVHJhbnNmb3JtYXRpb24gJiBGZWF0dXJlIEVuZ2luZWVyaW5nPC9zdHJvbmc+LCBjb3ZlcmluZyB0d28ga2V5IGZ1bmN0aW9uczogPGNvZGU+bm9ybWFsaXplX2NvbHVtbnMoZGYpPC9jb2RlPiB3aGljaCBhcHBsaWVzIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPmxvb3AtYmFzZWQgbm9ybWFsaXphdGlvbjwvc3Bhbj4gdG8gc2NhbGUgbnVtZXJpYyBjb2x1bW5zIHRvIGEgMC0xIHJhbmdlIHVzaW5nICh4IC0gbWluKS8obWF4IC0gbWluKSwgYW5kIDxjb2RlPnpfc2NvcmUoZGYpPC9jb2RlPiB3aGljaCBzdGFuZGFyZGl6ZXMgZGF0YSB0byBoYXZlIGEgbWVhbiBvZiAwIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMS4gRnJvbSB0aGVzZSB0cmFuc2Zvcm1lZCB2YWx1ZXMsIG5ldyBmZWF0dXJlcyBsaWtlIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPnBlcmZvcm1hbmNlX2NhdGVnb3J5PC9zcGFuPiAoZS5nLiwgTG93LCBNZWRpdW0sIEhpZ2gpIGFuZCA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5zYWxhcnlfYnJhY2tldDwvc3Bhbj4gKGUuZy4sIEVudHJ5LCBNaWQsIFNlbmlvcikgYXJlIGNyZWF0ZWQgdGhyb3VnaCBiaW5uaW5nIGFuZCBjb25kaXRpb25hbCBsb2dpYywgZW5hYmxpbmcgbW9yZSBpbnR1aXRpdmUgZ3JvdXBpbmcgYW5kIGFuYWx5c2lzLiBUbyBhc3Nlc3MgdGhlIGltcGFjdCBvZiB0aGVzZSB0cmFuc2Zvcm1hdGlvbnMsIHRoZSBzZWN0aW9uIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPmNvbXBhcmVzIGRpc3RyaWJ1dGlvbnMgYmVmb3JlIGFuZCBhZnRlcjwvc3Bhbj4gdXNpbmcgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+aGlzdG9ncmFtcyBhbmQgYm94cGxvdHM8L3NwYW4+LCB3aGljaCByZXZlYWwgY2hhbmdlcyBpbiBzaGFwZSwgc3ByZWFkLCBvdXRsaWVycywgYW5kIGNlbnRyYWwgdGVuZGVuY3kuIFRoaXMgY29tcGFyaXNvbiBlbnN1cmVzIHRoYXQgdHJhbnNmb3JtYXRpb25zIHdvcmsgYXMgaW50ZW5kZWQgYW5kIHByZXBhcmVzIHRoZSBkYXRhc2V0IGZvciByZWxpYWJsZSBtYWNoaW5lIGxlYXJuaW5nIG9yIHN0YXRpc3RpY2FsIG1vZGVsaW5nLg0KICAgIDwvcD4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0KYGBgDQoNCg0KIyMgTG9vcC1iYXNlZCBub3JtYWxpemF0aW9uDQoNCmBgYHs9aHRtbH0NCjwhRE9DVFlQRSBodG1sPg0KPGh0bWwgbGFuZz0iZW4iPg0KPGhlYWQ+DQogICAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPg0KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wIj4NCiAgICA8dGl0bGU+TG9vcC1CYXNlZCBOb3JtYWxpemF0aW9uPC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNkOWQ2Y2Y7DQogICAgICAgICAgICBtaW4taGVpZ2h0OiAxMDB2aDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1NlZ29lIFVJJywgJ1JvYm90bycsICdOb3RvIFNhbnMnLCBzeXN0ZW0tdWksIHNhbnMtc2VyaWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyNHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLmNyZWFtLWJveCB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmRmYWY2Ow0KICAgICAgICAgICAgbWF4LXdpZHRoOiA4NjBweDsNCiAgICAgICAgICAgIHdpZHRoOiAxMDAlOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMjRweDsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMTJweCAyNHB4IHJnYmEoMCwgMCwgMCwgMC4yKTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDJyZW0gMnJlbTsNCiAgICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNiODg2MGI7DQogICAgICAgIH0NCg0KICAgICAgICAuY3JlYW0tYm94IHAgew0KICAgICAgICAgICAgY29sb3I6ICMyYzE4MTA7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDVyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS42NTsNCiAgICAgICAgICAgIHRleHQtYWxpZ246IGp1c3RpZnk7DQogICAgICAgICAgICBmb250LXdlaWdodDogNDAwOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDAuMnB4Ow0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICB9DQoNCiAgICAgICAgLmhpZ2hsaWdodCB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjVjNTQyOw0KICAgICAgICAgICAgY29sb3I6ICMzYTFhMWE7DQogICAgICAgICAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDAuMXJlbSAwLjNyZW07DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgbW9ub3NwYWNlOw0KICAgICAgICB9DQoNCiAgICAgICAgY29kZSB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmQyYTFlOw0KICAgICAgICAgICAgY29sb3I6ICNmMmU2Yzk7DQogICAgICAgICAgICBwYWRkaW5nOiAwLjJyZW0gMC40cmVtOw0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNnB4Ow0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdDb3VyaWVyIE5ldycsIG1vbm9zcGFjZTsNCiAgICAgICAgfQ0KICAgIDwvc3R5bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCjxkaXYgY2xhc3M9ImNyZWFtLWJveCI+DQogICAgPHA+DQogICAgICAgIEluIHRoaXMgc2VnbWVudCwgPHNwYW4gY2xhc3M9ImhpZ2hsaWdodCI+bG9vcC1iYXNlZCBub3JtYWxpemF0aW9uPC9zcGFuPiBpcyBpbXBsZW1lbnRlZCB3aXRoaW4gdGhlIDxjb2RlPm5vcm1hbGl6ZV9jb2x1bW5zKGRmKTwvY29kZT4gZnVuY3Rpb24gdG8gc2NhbGUgbnVtZXJpYyBjb2x1bW5zIHRvIGEgdW5pZm9ybSByYW5nZSwgdHlwaWNhbGx5IDAgdG8gMSwgdXNpbmcgdGhlIGZvcm11bGEgKHggLSBtaW4pLyhtYXggLSBtaW4pLiBUaGUgZnVuY3Rpb24gdXNlcyBhIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPmxvb3A8L3NwYW4+IHRvIGl0ZXJhdGUgdGhyb3VnaCBlYWNoIGNvbHVtbiBvZiB0aGUgZGF0YWZyYW1lLCBjaGVja3MgaWYgdGhlIGNvbHVtbiBpcyBudW1lcmljLCBhbmQgdGhlbiBhcHBsaWVzIHRoZSBub3JtYWxpemF0aW9uIGZvcm11bGEgdG8gZXZlcnkgdmFsdWUgaW4gdGhhdCBjb2x1bW4uIFRoaXMgYXBwcm9hY2ggcHJvdmlkZXMgZnVsbCBjb250cm9sIG92ZXIgdGhlIHRyYW5zZm9ybWF0aW9uIHByb2Nlc3MsIGFsbG93aW5nIGZvciBjb25kaXRpb25hbCBoYW5kbGluZyBvZiBkaWZmZXJlbnQgZGF0YSB0eXBlcyBhbmQgbWFraW5nIHRoZSBsb2dpYyB0cmFuc3BhcmVudCBhbmQgZWR1Y2F0aW9uYWwuIEJ5IHNjYWxpbmcgYWxsIG51bWVyaWMgZmVhdHVyZXMgdG8gdGhlIHNhbWUgcmFuZ2UsIGxvb3AtYmFzZWQgbm9ybWFsaXphdGlvbiBlbnN1cmVzIHRoYXQgbm8gc2luZ2xlIHZhcmlhYmxlIGRvbWluYXRlcyBhbmFseXNlcyBvciBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBkdWUgdG8gbGFyZ2VyIG1hZ25pdHVkZSwgd2hpbGUgYWxzbyBwcmVzZXJ2aW5nIHRoZSByZWxhdGl2ZSByZWxhdGlvbnNoaXBzIGFuZCBkaXN0cmlidXRpb24gc2hhcGUgb2YgdGhlIG9yaWdpbmFsIGRhdGEuDQogICAgPC9wPg0KPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KDQojIyBOZXcgRmVhdHVyZXMgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KERUKQ0KDQpzZXQuc2VlZCgxMjMpDQoNCmdlbmVyYXRlX2hvdGVsX2RhdGEgPC0gZnVuY3Rpb24obl9lbXBsb3llZXMgPSAxMjApIHsNCiAgDQogIGRlcGFydG1lbnRzIDwtIGMoDQogICAgIkZyb250IE9mZmljZSIsICJIb3VzZWtlZXBpbmciLCAiRm9vZCAmIEJldmVyYWdlIiwNCiAgICAiS2l0Y2hlbiIsICJNYWludGVuYW5jZSIsICJIUiIsICJGaW5hbmNlIg0KICApDQogIA0KICBkYXRhX2xpc3QgPC0gdmVjdG9yKCJsaXN0Iiwgbl9lbXBsb3llZXMpDQogIA0KICBmb3IgKGUgaW4gc2VxX2xlbihuX2VtcGxveWVlcykpIHsNCiAgICANCiAgICANCiAgICAjIFNhbGFyeQ0KICAgIA0KICAgIHNhbGFyeSA8LSByb3VuZChybG5vcm0oMSwgbWVhbmxvZyA9IDguNywgc2Rsb2cgPSAwLjM1KSkNCiAgICANCiAgICAjIE1pbGQgb3V0bGllciANCiAgICBpZiAocnVuaWYoMSkgPCAwLjAzKSB7DQogICAgICBzYWxhcnkgPC0gc2FsYXJ5ICogcnVuaWYoMSwgMS4zLCAxLjgpDQogICAgfQ0KICAgIA0KICAgICMgQ2xpcHBpbmcgYmlhciBhbWFuIHVudHVrIFotc2NvcmUNCiAgICBzYWxhcnkgPC0gbWluKG1heChzYWxhcnksIDI1MDApLCAxODAwMCkNCiAgICANCiAgICANCiAgICAjIFNjb3Jlcw0KICAgIHBlcmZvcm1hbmNlX3Njb3JlIDwtIHJvdW5kKHJ1bmlmKDEsIDU1LCAxMDApLCAxKQ0KICAgIEtQSV9zY29yZSAgICAgICAgIDwtIHJvdW5kKHJ1bmlmKDEsIDYwLCAxMDApLCAxKQ0KICAgIA0KICAgIA0KICAgICMgUGVyZm9ybWFuY2UgQ2F0ZWdvcnkNCiAgICBwZXJmX2NhdCA8LSBpZiAocGVyZm9ybWFuY2Vfc2NvcmUgPj0gOTApIHsNCiAgICAgICJFeGNlbGxlbnQiDQogICAgfSBlbHNlIGlmIChwZXJmb3JtYW5jZV9zY29yZSA+PSA4MCkgew0KICAgICAgIlZlcnkgR29vZCINCiAgICB9IGVsc2UgaWYgKHBlcmZvcm1hbmNlX3Njb3JlID49IDcwKSB7DQogICAgICAiR29vZCINCiAgICB9IGVsc2UgaWYgKHBlcmZvcm1hbmNlX3Njb3JlID49IDYwKSB7DQogICAgICAiQXZlcmFnZSINCiAgICB9IGVsc2Ugew0KICAgICAgIlBvb3IiDQogICAgfQ0KICAgIA0KICAgICMgU2FsYXJ5IEJyYWNrZXQgDQogICAgc2FsX2JyYWNrZXQgPC0gaWYgKHNhbGFyeSA+PSAxMjAwMCkgew0KICAgICAgIkhpZ2giDQogICAgfSBlbHNlIGlmIChzYWxhcnkgPj0gNzAwMCkgew0KICAgICAgIk1lZGl1bSINCiAgICB9IGVsc2Ugew0KICAgICAgIkxvdyINCiAgICB9DQogICAgDQogICAgZGF0YV9saXN0W1tlXV0gPC0gZGF0YS5mcmFtZSgNCiAgICAgIGVtcGxveWVlX2lkID0gc3ByaW50ZigiRSUwM2QiLCBlKSwNCiAgICAgIGRlcGFydG1lbnQgID0gc2FtcGxlKGRlcGFydG1lbnRzLCAxKSwNCiAgICAgIHNhbGFyeSAgICAgID0gc2FsYXJ5LA0KICAgICAgcGVyZm9ybWFuY2Vfc2NvcmUgPSBwZXJmb3JtYW5jZV9zY29yZSwNCiAgICAgIEtQSV9zY29yZSAgID0gS1BJX3Njb3JlLA0KICAgICAgcGVyZm9ybWFuY2VfY2F0ZWdvcnkgPSBwZXJmX2NhdCwNCiAgICAgIHNhbGFyeV9icmFja2V0ID0gc2FsX2JyYWNrZXQsDQogICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCiAgICApDQogIH0NCiAgDQogIGhvdGVsX2RhdGEgPC0gZG8uY2FsbChyYmluZCwgZGF0YV9saXN0KQ0KICByZXR1cm4oaG90ZWxfZGF0YSkNCn0NCg0KaG90ZWxfZGF0YSA8LSBnZW5lcmF0ZV9ob3RlbF9kYXRhKDEyMCkNCg0KZGF0YXRhYmxlKA0KICBob3RlbF9kYXRhLA0KICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsIGF1dG9XaWR0aCA9IFRSVUUpLA0KICByb3duYW1lcyA9IEZBTFNFLA0KICBjYXB0aW9uID0gIkhvdGVsIEVtcGxveWVlIERhdGFzZXQgKFJlYWxpc3RpYyAmIFN0YXQtU2FmZSkiDQopDQoNCmBgYA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KGRwbHlyKQ0KDQpzZXQuc2VlZCgxMjMpDQoNCiMgRnVuZ3NpIGdlbmVyYXRlIGRhdGEgaG90ZWwNCmdlbmVyYXRlX2hvdGVsX2RhdGEgPC0gZnVuY3Rpb24obl9lbXBsb3llZXMgPSAxMjApIHsNCiAgDQogIGRlcGFydG1lbnRzIDwtIGMoDQogICAgIkZyb250IE9mZmljZSIsICJIb3VzZWtlZXBpbmciLCAiRm9vZCAmIEJldmVyYWdlIiwNCiAgICAiS2l0Y2hlbiIsICJNYWludGVuYW5jZSIsICJIUiIsICJGaW5hbmNlIg0KICApDQogIA0KICBkYXRhX2xpc3QgPC0gdmVjdG9yKCJsaXN0Iiwgbl9lbXBsb3llZXMpDQogIA0KICBmb3IgKGUgaW4gc2VxX2xlbihuX2VtcGxveWVlcykpIHsNCiAgICANCiAgICAjIFJlYWxpc3RpYyBTYWxhcnkgKGNvbnRyb2xsZWQgc2tldykNCiAgICBzYWxhcnkgPC0gcm91bmQocmxub3JtKDEsIG1lYW5sb2cgPSA4LjcsIHNkbG9nID0gMC4zNSkpDQogICAgDQogICAgaWYgKHJ1bmlmKDEpIDwgMC4wMykgc2FsYXJ5IDwtIHNhbGFyeSAqIHJ1bmlmKDEsIDEuMywgMS44KQ0KICAgIA0KICAgIHNhbGFyeSA8LSBtaW4obWF4KHNhbGFyeSwgMjUwMCksIDE4MDAwKQ0KICAgIA0KICAgICMgU2NvcmVzDQogICAgcGVyZm9ybWFuY2Vfc2NvcmUgPC0gcm91bmQocnVuaWYoMSwgNTUsIDEwMCksIDEpDQogICAgS1BJX3Njb3JlICAgICAgICAgPC0gcm91bmQocnVuaWYoMSwgNjAsIDEwMCksIDEpDQogICAgDQogICAgIyBQZXJmb3JtYW5jZSBDYXRlZ29yeQ0KICAgIHBlcmZfY2F0IDwtIGNhc2Vfd2hlbigNCiAgICAgIHBlcmZvcm1hbmNlX3Njb3JlID49IDkwIH4gIkV4Y2VsbGVudCIsDQogICAgICBwZXJmb3JtYW5jZV9zY29yZSA+PSA4MCB+ICJWZXJ5IEdvb2QiLA0KICAgICAgcGVyZm9ybWFuY2Vfc2NvcmUgPj0gNzAgfiAiR29vZCIsDQogICAgICBwZXJmb3JtYW5jZV9zY29yZSA+PSA2MCB+ICJBdmVyYWdlIiwNCiAgICAgIFRSVUUgfiAiUG9vciINCiAgICApDQogICAgDQogICAgIyBTYWxhcnkgQnJhY2tldA0KICAgIHNhbF9icmFja2V0IDwtIGNhc2Vfd2hlbigNCiAgICAgIHNhbGFyeSA+PSAxMjAwMCB+ICJIaWdoIiwNCiAgICAgIHNhbGFyeSA+PSA3MDAwICB+ICJNZWRpdW0iLA0KICAgICAgVFJVRSAgICAgICAgICAgIH4gIkxvdyINCiAgICApDQogICAgDQogICAgZGF0YV9saXN0W1tlXV0gPC0gZGF0YS5mcmFtZSgNCiAgICAgIGVtcGxveWVlX2lkID0gc3ByaW50ZigiRSUwM2QiLCBlKSwNCiAgICAgIGRlcGFydG1lbnQgID0gc2FtcGxlKGRlcGFydG1lbnRzLCAxKSwNCiAgICAgIHNhbGFyeSAgICAgID0gc2FsYXJ5LA0KICAgICAgcGVyZm9ybWFuY2Vfc2NvcmUgPSBwZXJmb3JtYW5jZV9zY29yZSwNCiAgICAgIEtQSV9zY29yZSAgID0gS1BJX3Njb3JlLA0KICAgICAgcGVyZm9ybWFuY2VfY2F0ZWdvcnkgPSBwZXJmX2NhdCwNCiAgICAgIHNhbGFyeV9icmFja2V0ID0gc2FsX2JyYWNrZXQsDQogICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCiAgICApDQogIH0NCiAgDQogIGhvdGVsX2RhdGEgPC0gZG8uY2FsbChyYmluZCwgZGF0YV9saXN0KQ0KICByZXR1cm4oaG90ZWxfZGF0YSkNCn0NCg0KDQojIEZ1bmdzaSBOb3JtYWxpc2FzaSAoTWluLU1heCkNCm5vcm1hbGl6ZV9jb2x1bW5zIDwtIGZ1bmN0aW9uKGRmLCBjb2xzKSB7DQogIGRmICU+JQ0KICAgIG11dGF0ZShhY3Jvc3MoYWxsX29mKGNvbHMpLCB+ICguIC0gbWluKC4pKSAvIChtYXgoLikgLSBtaW4oLikpLCAubmFtZXMgPSAiey5jb2x9X25vcm0iKSkNCn0NCg0KIyBGdW5nc2kgWi1zY29yZQ0Kel9zY29yZSA8LSBmdW5jdGlvbihkZiwgY29scykgew0KICBkZiAlPiUNCiAgICBtdXRhdGUoYWNyb3NzKGFsbF9vZihjb2xzKSwgfiBhcy5udW1lcmljKHNjYWxlKC4pKSwgLm5hbWVzID0gInsuY29sfV96IikpDQp9DQoNCiMNCiMgR2VuZXJhdGUgRGF0YSAmIEFwcGx5IFRyYW5zZm9ybWFzaQ0KaG90ZWxfZGF0YSA8LSBnZW5lcmF0ZV9ob3RlbF9kYXRhKDEyMCkNCg0KIyBOb3JtYWxpc2FzaSBrb2xvbSBzYWxhcnkgJiBwZXJmb3JtYW5jZV9zY29yZQ0KaG90ZWxfZGF0YV9ub3JtIDwtIG5vcm1hbGl6ZV9jb2x1bW5zKGhvdGVsX2RhdGEsIGMoInNhbGFyeSIsICJwZXJmb3JtYW5jZV9zY29yZSIpKQ0KDQojIFotc2NvcmUga29sb20gc2FsYXJ5ICYgcGVyZm9ybWFuY2Vfc2NvcmUNCmhvdGVsX2RhdGFfZmluYWwgPC0gel9zY29yZShob3RlbF9kYXRhX25vcm0sIGMoInNhbGFyeSIsICJwZXJmb3JtYW5jZV9zY29yZSIpKQ0KDQoNCiMgVGFtcGlsa2FuIERhdGEgJiBTdW1tYXJ5DQpkYXRhdGFibGUoDQogIGhvdGVsX2RhdGFfZmluYWwsDQogIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwgYXV0b1dpZHRoID0gVFJVRSksDQogIHJvd25hbWVzID0gRkFMU0UsDQogIGNhcHRpb24gPSAiSG90ZWwgRW1wbG95ZWUgRGF0YXNldCBkZW5nYW4gTm9ybWFsaXNhc2kgJiBaLVNjb3JlIg0KKQ0KDQpzdW1tYXJ5KGhvdGVsX2RhdGFfZmluYWxbLCBjKCJzYWxhcnlfbm9ybSIsICJwZXJmb3JtYW5jZV9zY29yZV9ub3JtIiwgInNhbGFyeV96IiwgInBlcmZvcm1hbmNlX3Njb3JlX3oiKV0pDQpgYGANCg0KIyMgQ29tcGFyZSBEaXN0cmlidXRpb24gQmVmb3JlIGFuZCBBZnRlciANCg0KIyMjIFBlcmZvcm1hbmNlIFNjb3JlIA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkocGxvdGx5KQ0KDQpmaWdfYm94X3BlcmYgPC0gcGxvdF9seShkYXRhID0gaG90ZWxfZGF0YV9maW5hbCkgJT4lDQogIGFkZF90cmFjZSgNCiAgICB5ID0gfnBlcmZvcm1hbmNlX3Njb3JlLA0KICAgIHR5cGUgPSAiYm94IiwNCiAgICBuYW1lID0gIkJlZm9yZSIsDQogICAgYm94cG9pbnRzID0gIm91dGxpZXJzIiwNCiAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gIiMwMEZGRkYiKSwNCiAgICBsaW5lID0gbGlzdChjb2xvciA9ICIjMDBGRkZGIikNCiAgKSAlPiUNCiAgYWRkX3RyYWNlKA0KICAgIHkgPSB+cGVyZm9ybWFuY2Vfc2NvcmVfbm9ybSwNCiAgICB0eXBlID0gImJveCIsDQogICAgbmFtZSA9ICJBZnRlciBOb3JtYWxpemF0aW9uIiwNCiAgICBib3hwb2ludHMgPSAib3V0bGllcnMiLA0KICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAiI0ZGMDBGRiIpLA0KICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gIiNGRjAwRkYiKQ0KICApICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICJQZXJmb3JtYW5jZSBTY29yZTogQmVmb3JlIHZzIEFmdGVyIE5vcm1hbGl6YXRpb24iLA0KICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiI0ZGRkZGRiIpDQogICAgKSwNCiAgICANCiAgICAjIGJhY2tncm91bmQgZ2VsYXANCiAgICBwYXBlcl9iZ2NvbG9yID0gIiMwQTBBMEEiLA0KICAgIHBsb3RfYmdjb2xvciAgPSAiIzBBMEEwQSIsDQogICAgDQogICAgIyBheGlzDQogICAgeWF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAiVmFsdWUiLA0KICAgICAgY29sb3IgPSAiI0ZGRkZGRiIsDQogICAgICBncmlkY29sb3IgPSAiIzMzMzMzMyINCiAgICApLA0KICAgIA0KICAgIHhheGlzID0gbGlzdCgNCiAgICAgIGNvbG9yID0gIiNGRkZGRkYiDQogICAgKSwNCiAgICANCiAgICAjIGxlZ2VuZA0KICAgIGxlZ2VuZCA9IGxpc3QoDQogICAgICBmb250ID0gbGlzdChjb2xvciA9ICIjRkZGRkZGIikNCiAgICApLA0KICAgIA0KICAgIGJveG1vZGUgPSAiZ3JvdXAiDQogICkNCg0KZmlnX2JveF9wZXJmDQpgYGANCg0KPGRpdiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojRkZGOUM0OyBwYWRkaW5nOjE1cHg7IGJvcmRlci1yYWRpdXM6MTBweDsgYm9yZGVyOjFweCBzb2xpZCAjRkREODM1OyBtYXJnaW4tdG9wOjEwcHg7IHRleHQtYWxpZ246IGp1c3RpZnk7Ij4NCg0KKipJbnRlcnByZXRhdGlvbioqDQoNClRoZSBib3hwbG90IGNvbXBhcmlzb24gc2hvd3Mgb3JpZ2luYWwgcGVyZm9ybWFuY2Ugc2NvcmVzIHJhbmdpbmcgZnJvbSA1NSB0byAxMDAsIHdpdGggbWVkaWFuLCBJUVIsIGFuZCBvdXRsaWVycyByZWZsZWN0aW5nIG5hdHVyYWwgdmFyaWF0aW9uLiBBZnRlciBtaW4tbWF4IG5vcm1hbGl6YXRpb24sIGFsbCB2YWx1ZXMgYXJlIHJlc2NhbGVkIHRvIDDigJMxIHdoaWxlIHByZXNlcnZpbmcgdGhlIGV4YWN0IGRpc3RyaWJ1dGlvbiBzaGFwZSwgaW5jbHVkaW5nIG1lZGlhbiBwb3NpdGlvbiBhbmQgZGF0YSBzcHJlYWQuIFRoaXMgY29uZmlybXMgdGhhdCBub3JtYWxpemF0aW9uIG9ubHkgY2hhbmdlcyB0aGUgc2NhbGUsIG5vdCB0aGUgdW5kZXJseWluZyBkaXN0cmlidXRpb24gb3IgcmVsYXRpb25zaGlwcyB3aXRoaW4gdGhlIGRhdGFzZXQuIE91dGxpZXJzIHJlbWFpbiB2aXNpYmxlIGFmdGVyIG5vcm1hbGl6YXRpb24sIG5vdyBleHByZXNzZWQgd2l0aGluIHRoZSAw4oCTMSBzY2FsZSwgbWFraW5nIHRoZSBkYXRhIHJlYWR5IGZvciBjcm9zcy12YXJpYWJsZSBjb21wYXJpc29uIG9yIG1hY2hpbmUgbGVhcm5pbmcgYXBwbGljYXRpb25zLg0KDQo8L2Rpdj4NCg0KDQojIyMgU2FsYXJ5IA0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHBsb3RseSkNCg0KZmlnX3NhbGFyeV96IDwtIHBsb3RfbHkoaG90ZWxfZGF0YV9maW5hbCkgJT4lDQogIGFkZF90cmFjZSgNCiAgICB4ID0gfnNhbGFyeSwNCiAgICB0eXBlID0gImhpc3RvZ3JhbSIsDQogICAgbmFtZSA9ICJCZWZvcmUgKE9yaWdpbmFsKSIsDQogICAgb3BhY2l0eSA9IDAuNywNCiAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gImN5YW4iLCBsaW5lID0gbGlzdChjb2xvciA9ICJ3aGl0ZSIsIHdpZHRoID0gMSkpLA0KICAgIGhvdmVydGVtcGxhdGUgPSAiU2FsYXJ5OiAle3h9PGJyPkZyZXF1ZW5jeTogJXt5fTxleHRyYT48L2V4dHJhPiINCiAgKSAlPiUNCiAgYWRkX3RyYWNlKA0KICAgIHggPSB+c2FsYXJ5X3osDQogICAgdHlwZSA9ICJoaXN0b2dyYW0iLA0KICAgIG5hbWUgPSAiQWZ0ZXIgWi1TY29yZSIsDQogICAgb3BhY2l0eSA9IDAuNywNCiAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gIm1hZ2VudGEiLCBsaW5lID0gbGlzdChjb2xvciA9ICJ3aGl0ZSIsIHdpZHRoID0gMSkpLA0KICAgIGhvdmVydGVtcGxhdGUgPSAiWi1TY29yZTogJXt4fTxicj5GcmVxdWVuY3k6ICV7eX08ZXh0cmE+PC9leHRyYT4iDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QoDQogICAgICB0ZXh0ID0gIlNhbGFyeSBEaXN0cmlidXRpb246IEJlZm9yZSB2cyBBZnRlciBaLVNjb3JlIE5vcm1hbGl6YXRpb24iLA0KICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAid2hpdGUiLCBzaXplID0gMTgsIGZhbWlseSA9ICJBcmlhbCBCbGFjayIpDQogICAgKSwNCiAgICBiYXJtb2RlID0gIm92ZXJsYXkiLA0KICAgIHBsb3RfYmdjb2xvciA9ICJibGFjayIsDQogICAgcGFwZXJfYmdjb2xvciA9ICJibGFjayIsDQogICAgeGF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSBsaXN0KHRleHQgPSAiVmFsdWUiLCBmb250ID0gbGlzdChjb2xvciA9ICJ3aGl0ZSIpKSwNCiAgICAgIHRpY2tmb250ID0gbGlzdChjb2xvciA9ICJ3aGl0ZSIpLA0KICAgICAgZ3JpZGNvbG9yID0gImdyYXkzMCIsDQogICAgICB6ZXJvbGluZWNvbG9yID0gImdyYXk1MCINCiAgICApLA0KICAgIHlheGlzID0gbGlzdCgNCiAgICAgIHRpdGxlID0gbGlzdCh0ZXh0ID0gIkZyZXF1ZW5jeSIsIGZvbnQgPSBsaXN0KGNvbG9yID0gIndoaXRlIikpLA0KICAgICAgdGlja2ZvbnQgPSBsaXN0KGNvbG9yID0gIndoaXRlIiksDQogICAgICBncmlkY29sb3IgPSAiZ3JheTMwIiwNCiAgICAgIHplcm9saW5lY29sb3IgPSAiZ3JheTUwIg0KICAgICksDQogICAgbGVnZW5kID0gbGlzdCgNCiAgICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDEyKSwNCiAgICAgIGJnY29sb3IgPSAicmdiYSgwLDAsMCwwLjYpIiwNCiAgICAgIGJvcmRlcmNvbG9yID0gIndoaXRlIiwNCiAgICAgIGJvcmRlcndpZHRoID0gMQ0KICAgICksDQogICAgaG92ZXJsYWJlbCA9IGxpc3QoYmdjb2xvciA9ICJ3aGl0ZSIsIGZvbnQgPSBsaXN0KGNvbG9yID0gImJsYWNrIikpDQogICkgJT4lDQogIGNvbmZpZyhkaXNwbGF5TW9kZUJhciA9IFRSVUUpDQoNCmZpZ19zYWxhcnlfeg0KYGBgDQoNCjxkaXYgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0ZGRjlDNDsgcGFkZGluZzoxNXB4OyBib3JkZXItcmFkaXVzOjEwcHg7IGJvcmRlcjoxcHggc29saWQgI0ZERDgzNTsgbWFyZ2luLXRvcDoxMHB4OyB0ZXh0LWFsaWduOiBqdXN0aWZ5OyI+DQoNCioqSW50ZXJwcmV0YXRpb24qKg0KDQpUaGUgb3JpZ2luYWwgc2FsYXJ5IGhpc3RvZ3JhbSBzaG93cyBhIHJpZ2h0LXNrZXdlZCBkaXN0cmlidXRpb24gY29uY2VudHJhdGVkIGJldHdlZW4gSURSIDPigJM3IG1pbGxpb24sIHdpdGggYSBwZWFrIGF0IElEUiA0LjUgbWlsbGlvbiBhbmQgYSBmZXcgZXh0cmVtZSB2YWx1ZXMgYWJvdmUgSURSIDIwIG1pbGxpb24gYWN0aW5nIGFzIGNsZWFyIG91dGxpZXJzLiBBZnRlciBaLXNjb3JlIG5vcm1hbGl6YXRpb24sIHRoZSBzYW1lIGRpc3RyaWJ1dGlvbiBzaGlmdHMgdG8gY2VudGVyIGF0IHplcm8gd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBvbmUsIHByZXNlcnZpbmcgdGhlIGV4YWN0IHJpZ2h0LXNrZXdlZCBzaGFwZSBhbmQgdGhlIHJlbGF0aXZlIHBvc2l0aW9uIG9mIGVhY2ggc2FsYXJ5IHZhbHVlLiBUaGUgb3V0bGllcnMgb3JpZ2luYWxseSBhYm92ZSBJRFIgMjAgbWlsbGlvbiBub3cgYXBwZWFyIGFzIFotc2NvcmVzIGFib3ZlICsyLjgsIG1ha2luZyB0aGVtIGluc3RhbnRseSByZWNvZ25pemFibGUgYXMgc3RhdGlzdGljYWwgb3V0bGllcnMgd2l0aG91dCBhbnkgbG9zcyBvZiBpbmZvcm1hdGlvbi4gVGh1cywgWi1zY29yZSBub3JtYWxpemF0aW9uIGRvZXMgbm90IGFsdGVyIHRoZSBkYXRhJ3Mgc3RydWN0dXJlIG9yIGhpZGUgZXh0cmVtZSB2YWx1ZXMgYnV0IG1lcmVseSByZXNjYWxlcyB0aGUgc2FsYXJ5IGludG8gc3RhbmRhcmRpemVkIHVuaXRzLCBlbmFibGluZyBkaXJlY3QgY29tcGFyaXNvbiB3aXRoIG90aGVyIG5vcm1hbGl6ZWQgdmFyaWFibGVzIGxpa2UgcGVyZm9ybWFuY2Ugb3IgdGVudXJlLg0KDQo8L2Rpdj4NCg0KDQojIE1pbmkgUHJvamVjdDpDb21wYW55IEtQSSBEYXNoYm9hcmQgJiBTaW11bGF0aW9uIA0KDQpgYGB7PWh0bWx9DQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sIGxhbmc9ImVuIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4NCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogICAgPHRpdGxlPk1pbmkgUHJvamVjdCAtIENvbXBhbnkgS1BJIERhc2hib2FyZDwvdGl0bGU+DQogICAgPHN0eWxlPg0KICAgICAgICAqIHsNCiAgICAgICAgICAgIG1hcmdpbjogMDsNCiAgICAgICAgICAgIHBhZGRpbmc6IDA7DQogICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94Ow0KICAgICAgICB9DQoNCiAgICAgICAgYm9keSB7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjZDlkNmNmOw0KICAgICAgICAgICAgbWluLWhlaWdodDogMTAwdmg7DQogICAgICAgICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdTZWdvZSBVSScsICdSb2JvdG8nLCBzeXN0ZW0tdWksIHNhbnMtc2VyaWY7DQogICAgICAgICAgICBwYWRkaW5nOiAyNHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzZkMmUyZTsNCiAgICAgICAgICAgIG1heC13aWR0aDogODYwcHg7DQogICAgICAgICAgICB3aWR0aDogMTAwJTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDI0cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDEycHggMjRweCByZ2JhKDAsIDAsIDAsIDAuMik7DQogICAgICAgICAgICBwYWRkaW5nOiAycmVtOw0KICAgICAgICAgICAgYm9yZGVyOiAxcHggc29saWQgIzliNmE1YzsNCiAgICAgICAgfQ0KDQogICAgICAgIC5tYXJvb24tYm94IHAgew0KICAgICAgICAgICAgY29sb3I6ICNmMGUyZDQ7DQogICAgICAgICAgICBmb250LXNpemU6IDEuMDVyZW07DQogICAgICAgICAgICBsaW5lLWhlaWdodDogMS42NTsNCiAgICAgICAgICAgIHRleHQtYWxpZ246IGp1c3RpZnk7DQogICAgICAgICAgICBtYXJnaW4tYm90dG9tOiAxcmVtOw0KICAgICAgICB9DQoNCiAgICAgICAgLm1hcm9vbi1ib3ggcDpsYXN0LWNoaWxkIHsNCiAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IDA7DQogICAgICAgIH0NCg0KICAgICAgICAuaGlnaGxpZ2h0IHsNCiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmNWM1NDI7DQogICAgICAgICAgICBjb2xvcjogIzNhMWExYTsNCiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICAgICAgICAgcGFkZGluZzogMC4xcmVtIDAuM3JlbTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgICAgICAgfQ0KDQogICAgICAgIGNvZGUgew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzRhMWUxZTsNCiAgICAgICAgICAgIGNvbG9yOiAjZjVlMmNlOw0KICAgICAgICAgICAgcGFkZGluZzogMC4ycmVtIDAuNHJlbTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgICAgICAgfQ0KICAgIDwvc3R5bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCjxkaXYgY2xhc3M9Im1hcm9vbi1ib3giPg0KICAgIDxwPg0KICAgICAgICBUaGlzIG1pbmkgcHJvamVjdCBnZW5lcmF0ZXMgYSBzeW50aGV0aWMgZGF0YXNldCBmb3IgPGNvZGU+NeKAkzEwIGNvbXBhbmllczwvY29kZT4gd2l0aCA8Y29kZT41MOKAkzIwMCBlbXBsb3llZXM8L2NvZGU+IGVhY2guIENvbHVtbnMgaW5jbHVkZSA8Y29kZT5lbXBsb3llZV9pZDwvY29kZT4sIDxjb2RlPmNvbXBhbnlfaWQ8L2NvZGU+LCA8Y29kZT5zYWxhcnk8L2NvZGU+LCA8Y29kZT5wZXJmb3JtYW5jZV9zY29yZTwvY29kZT4sIDxjb2RlPktQSV9zY29yZTwvY29kZT4sIGFuZCA8Y29kZT5kZXBhcnRtZW50PC9jb2RlPi4gQSA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5sb29wPC9zcGFuPiBpcyB1c2VkIHRvIGNhdGVnb3JpemUgZW1wbG95ZWVzIGludG8gS1BJIHRpZXJzIChFeGNlbGxlbnQsIEdvb2QsIFNhdGlzZmFjdG9yeSwgTmVlZHMgSW1wcm92ZW1lbnQpLg0KICAgIDwvcD4NCg0KICAgIDxwPg0KICAgICAgICBUaGUgcHJvamVjdCBzdW1tYXJpemVzIGVhY2ggY29tcGFueSBieSBjYWxjdWxhdGluZyA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5hdmVyYWdlIHNhbGFyeTwvc3Bhbj4sIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPmF2ZXJhZ2UgS1BJIHNjb3JlPC9zcGFuPiwgYW5kIGlkZW50aWZ5aW5nIDxzcGFuIGNsYXNzPSJoaWdobGlnaHQiPnRvcCBwZXJmb3JtZXJzPC9zcGFuPi4gT3V0cHV0IGluY2x1ZGVzIHRhYmxlcyBmb3IgdG9wIHBlcmZvcm1lcnMgYW5kIGRlcGFydG1lbnQgYW5hbHlzaXMsIHBsdXMgc2FsYXJ5IGRpc3RyaWJ1dGlvbiBwbG90cy4gQWR2YW5jZWQgdmlzdWFsaXphdGlvbnMgZmVhdHVyZSA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5ncm91cGVkIGJhciBjaGFydHM8L3NwYW4+IGFuZCA8c3BhbiBjbGFzcz0iaGlnaGxpZ2h0Ij5zY2F0dGVyIHBsb3RzIHdpdGggcmVncmVzc2lvbiBsaW5lczwvc3Bhbj4gdG8gZXhwbG9yZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gc2FsYXJ5IGFuZCBLUEkuDQogICAgPC9wPg0KPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KIyMgR2VuZXJhdGUgRGF0YSANCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KGRhdGEudGFibGUpDQoNCnNldC5zZWVkKDEyMykNCg0KIyBQYXJhbWV0ZXINCm5fY29tcGFuaWVzIDwtIDcNCm5fZW1wbG95ZWVzIDwtIDEwMA0KDQpkZXBhcnRtZW50cyA8LSBjKA0KICAiRnJvbnQgT2ZmaWNlIiwgIkhvdXNla2VlcGluZyIsICJGb29kICYgQmV2ZXJhZ2UiLA0KICAiS2l0Y2hlbiIsICJNYWludGVuYW5jZSIsICJIUiIsICJGaW5hbmNlIg0KKQ0KDQojIExpc3QgcGVuYW1wdW5nDQphbGxfZGF0YSA8LSB2ZWN0b3IoImxpc3QiLCBuX2NvbXBhbmllcykNCg0KIyBMb29wIHBlcnVzYWhhYW4NCmZvciAoYyBpbiAxOm5fY29tcGFuaWVzKSB7DQogIA0KICBjb21wYW55X2lkIDwtIHBhc3RlMCgiSE9URUxfIiwgc3ByaW50ZigiJTAyZCIsIGMpKQ0KICANCiAgIyBMb29wIGthcnlhd2FuIGRhbGFtIGJlbnR1ayBkYXRhLnRhYmxlIGxhbmdzdW5nDQogIGR0IDwtIGRhdGEudGFibGUoDQogICAgZW1wbG95ZWVfaWQgPSBwYXN0ZTAoY29tcGFueV9pZCwgIl9FIiwgc3ByaW50ZigiJTAzZCIsIDE6bl9lbXBsb3llZXMpKSwNCiAgICBjb21wYW55X2lkICA9IGNvbXBhbnlfaWQsDQogICAgDQogICAgIyBTYWxhcnkgKHNrZXdlZCkNCiAgICBzYWxhcnkgPSBwbWluKA0KICAgICAgcG1heChyb3VuZChybG5vcm0obl9lbXBsb3llZXMsIG1lYW5sb2cgPSA4LjcsIHNkbG9nID0gMC4zNSkpLCAyNTAwKSwNCiAgICAgIDIwMDAwDQogICAgKSwNCiAgICANCiAgICBwZXJmb3JtYW5jZV9zY29yZSA9IHJvdW5kKHJ1bmlmKG5fZW1wbG95ZWVzLCA1NSwgMTAwKSwgMSksDQogICAgS1BJX3Njb3JlICAgICAgICAgPSByb3VuZChydW5pZihuX2VtcGxveWVlcywgNjAsIDEwMCksIDEpLA0KICAgIGRlcGFydG1lbnQgICAgICAgID0gc2FtcGxlKGRlcGFydG1lbnRzLCBuX2VtcGxveWVlcywgcmVwbGFjZSA9IFRSVUUpDQogICkNCiAgDQogIGFsbF9kYXRhW1tjXV0gPC0gZHQNCn0NCg0KIyBHYWJ1bmdrYW4gc2VtdWENCmhvdGVsX211bHRpX2R0IDwtIHJiaW5kbGlzdChhbGxfZGF0YSkNCg0KIyBMaWhhdCBoYXNpbA0KaG90ZWxfbXVsdGlfZHQNCmBgYA0KDQojIyBTdW1tYXJpemUgcGVyIGNvbXBhbnkNCg0KYGBge3J9DQpsaWJyYXJ5KGRhdGEudGFibGUpDQpzdW1tYXJ5X2NvbXBhbnkgPC0gaG90ZWxfbXVsdGlfZHRbLCAuKA0KICBhdmdfc2FsYXJ5ID0gcm91bmQobWVhbihzYWxhcnkpLCAyKSwNCiAgYXZnX0tQSSA9IHJvdW5kKG1lYW4oS1BJX3Njb3JlKSwgMiksDQogIHRvcF9wZXJmb3JtZXJzID0gc3VtKHBlcmZvcm1hbmNlX3Njb3JlID49IDkwKQ0KKSwgYnkgPSBjb21wYW55X2lkXVtvcmRlcihjb21wYW55X2lkKV0NCg0Kc3VtbWFyeV9jb21wYW55DQpgYGANCg0KIyMgTG9vcCB0byBjYXRlZ29yaXplIGVtcGxveWVlcyBpbnRvIEtQSSB0aWVycw0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoZGF0YS50YWJsZSkNCg0Kc2V0LnNlZWQoMTIzKQ0KDQojIFBhcmFtZXRlcg0Kbl9jb21wYW5pZXMgPC0gNw0Kbl9lbXBsb3llZXMgPC0gMTAwDQoNCmRlcGFydG1lbnRzIDwtIGMoDQogICJGcm9udCBPZmZpY2UiLCAiSG91c2VrZWVwaW5nIiwgIkZvb2QgJiBCZXZlcmFnZSIsDQogICJLaXRjaGVuIiwgIk1haW50ZW5hbmNlIiwgIkhSIiwgIkZpbmFuY2UiDQopDQoNCiMgTGlzdCBwZW5hbXB1bmcNCmFsbF9kYXRhIDwtIHZlY3RvcigibGlzdCIsIG5fY29tcGFuaWVzKQ0KDQojIExvb3AgcGVydXNhaGFhbg0KZm9yIChjIGluIDE6bl9jb21wYW5pZXMpIHsNCiAgDQogIGNvbXBhbnlfaWQgPC0gcGFzdGUwKCJIT1RFTF8iLCBzcHJpbnRmKCIlMDJkIiwgYykpDQogIA0KICAjIExvb3Aga2FyeWF3YW4gZGFsYW0gYmVudHVrIGRhdGEudGFibGUgbGFuZ3N1bmcNCiAgZHQgPC0gZGF0YS50YWJsZSgNCiAgICBlbXBsb3llZV9pZCA9IHBhc3RlMChjb21wYW55X2lkLCAiX0UiLCBzcHJpbnRmKCIlMDNkIiwgMTpuX2VtcGxveWVlcykpLA0KICAgIGNvbXBhbnlfaWQgID0gY29tcGFueV9pZCwNCiAgICANCiAgICAjIFNhbGFyeSAoc2tld2VkKQ0KICAgIHNhbGFyeSA9IHBtaW4oDQogICAgICBwbWF4KHJvdW5kKHJsbm9ybShuX2VtcGxveWVlcywgbWVhbmxvZyA9IDguNywgc2Rsb2cgPSAwLjM1KSksIDI1MDApLA0KICAgICAgMjAwMDANCiAgICApLA0KICAgIA0KICAgIHBlcmZvcm1hbmNlX3Njb3JlID0gcm91bmQocnVuaWYobl9lbXBsb3llZXMsIDU1LCAxMDApLCAxKSwNCiAgICBLUElfc2NvcmUgICAgICAgICA9IHJvdW5kKHJ1bmlmKG5fZW1wbG95ZWVzLCA2MCwgMTAwKSwgMSksDQogICAgZGVwYXJ0bWVudCAgICAgICAgPSBzYW1wbGUoZGVwYXJ0bWVudHMsIG5fZW1wbG95ZWVzLCByZXBsYWNlID0gVFJVRSkNCiAgKQ0KICANCiAgYWxsX2RhdGFbW2NdXSA8LSBkdA0KfQ0KDQojIEdhYnVuZ2thbiBzZW11YQ0KaG90ZWxfbXVsdGlfZHQgPC0gcmJpbmRsaXN0KGFsbF9kYXRhKQ0KDQojIFRhbWJhaGthbiBrb2xvbSBLUElfdGllcg0KaG90ZWxfbXVsdGlfZHRbLCBLUElfdGllciA6PSBmaWZlbHNlKA0KICBLUElfc2NvcmUgPj0gOTAsICJFeGNlbGxlbnQiLA0KICBmaWZlbHNlKA0KICAgIEtQSV9zY29yZSA+PSA4MCwgIkdvb2QiLA0KICAgIGZpZmVsc2UoDQogICAgICBLUElfc2NvcmUgPj0gNzAsICJBdmVyYWdlIiwNCiAgICAgICJMb3ciDQogICAgKQ0KICApDQopXQ0KDQoNCiMgTGloYXQgaGFzaWwNCmhvdGVsX211bHRpX2R0DQpgYGANCg0KDQojIyBWaXN1YWxpemF0aW9uIA0KDQojIyMgQmFyY2hhcnQgVG9wIFBlcmZvcm1hbmNlIHBlciBDb21wYW55IA0KDQpgYGB7cn0NCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShkcGx5cikNCg0KdG9wX3BlcmYgPC0gaG90ZWxfbXVsdGlfZHQgJT4lDQogIGdyb3VwX2J5KGNvbXBhbnlfaWQpICU+JQ0KICBzdW1tYXJpc2UodG9wX3BlcmZvcm1lcnMgPSBzdW0ocGVyZm9ybWFuY2Vfc2NvcmUgPj0gOTApKQ0KDQpwbG90X2x5KA0KICB0b3BfcGVyZiwNCiAgeCA9IH5jb21wYW55X2lkLA0KICB5ID0gfnRvcF9wZXJmb3JtZXJzLA0KICB0eXBlID0gJ2JhcicsDQogIG1hcmtlciA9IGxpc3QoDQogICAgY29sb3IgPSAiIzAwRkZGRiIsDQogICAgbGluZSA9IGxpc3QoY29sb3IgPSAiI0ZGMDBGRiIsIHdpZHRoID0gMikgIyBnbG93IG91dGxpbmUNCiAgKQ0KKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gbGlzdCgNCiAgICAgIHRleHQgPSAiVG9wIFBlcmZvcm1lcnMgcGVyIENvbXBhbnkiLA0KICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiI0ZGMDBGRiIsIHNpemUgPSAyMCkNCiAgICApLA0KICAgIA0KICAgICMgIEJBQ0tHUk9VTkQgSElUQU0NCiAgICBwbG90X2JnY29sb3IgPSAiIzAwMDAwMCIsDQogICAgcGFwZXJfYmdjb2xvciA9ICIjMDAwMDAwIiwNCiAgICANCiAgICAjIEZPTlQgTkVPTg0KICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gIiMwMEZGRkYiKSwNCiAgICANCiAgICAjIEdSSUQgKyBBWElTIEdMT1cNCiAgICB4YXhpcyA9IGxpc3QoDQogICAgICB0aXRsZSA9ICJDb21wYW55IiwNCiAgICAgIGdyaWRjb2xvciA9ICIjMjIyMjIyIiwNCiAgICAgIHplcm9saW5lY29sb3IgPSAiIzQ0NDQ0NCIsDQogICAgICB0aWNrZm9udCA9IGxpc3QoY29sb3IgPSAiIzAwRkZGRiIpDQogICAgKSwNCiAgICANCiAgICB5YXhpcyA9IGxpc3QoDQogICAgICB0aXRsZSA9ICJUb3AgUGVyZm9ybWVycyIsDQogICAgICBncmlkY29sb3IgPSAiIzIyMjIyMiIsDQogICAgICB6ZXJvbGluZWNvbG9yID0gIiM0NDQ0NDQiLA0KICAgICAgdGlja2ZvbnQgPSBsaXN0KGNvbG9yID0gIiMwMEZGRkYiKQ0KICAgICkNCiAgKQ0KYGBgDQoNCjxkaXYgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0ZGRjlDNDsgcGFkZGluZzoxNXB4OyBib3JkZXItcmFkaXVzOjEwcHg7IGJvcmRlcjoxcHggc29saWQgI0ZERDgzNTsgbWFyZ2luLXRvcDoxMHB4OyB0ZXh0LWFsaWduOiBqdXN0aWZ5OyI+DQoNCioqSW50ZXJwcmV0YXRpb24qKg0KDQpUaHJvdWdoIHRoZSBiYXIgY2hhcnQsIGRpZmZlcmVuY2VzIGluIHRoZSBkaXN0cmlidXRpb24gb2YgdG9wIHBlcmZvcm1lcnMgYWNyb3NzIGNvbXBhbmllcyBjYW4gYmUgb2JzZXJ2ZWQuIENvbXBhbmllcyB3aXRoIHRhbGxlciBiYXJzIGluZGljYXRlIHRoYXQgdGhleSBoYXZlIG1vcmUgaGlnaC1wZXJmb3JtaW5nIGVtcGxveWVlcywgd2hpY2ggbWF5IHJlZmxlY3QgZWZmZWN0aXZlIGh1bWFuIHJlc291cmNlIG1hbmFnZW1lbnQsIGEgZ29vZCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uIHN5c3RlbSwgb3IgYSB3b3JrIGVudmlyb25tZW50IHRoYXQgc3VwcG9ydHMgcHJvZHVjdGl2aXR5LiBDb252ZXJzZWx5LCBjb21wYW5pZXMgd2l0aCBmZXdlciB0b3AgcGVyZm9ybWVycyBtYXkgaW5kaWNhdGUgcG90ZW50aWFsIGFyZWFzIGZvciBpbXByb3ZlbWVudCBpbiBlbXBsb3llZSBwZXJmb3JtYW5jZSBtYW5hZ2VtZW50LCBzdWNoIGFzIHRyYWluaW5nLCB3b3JrIG1vdGl2YXRpb24sIG9yIGEgc3Vib3B0aW1hbCBhc3Nlc3NtZW50IHN5c3RlbS4NCg0KPC9kaXY+DQoNCiMjIyBIaXN0b2dyYW0gU2FsYXJ5IERpc3RyaWJ1dGlvbiANCg0KYGBge3J9DQpsaWJyYXJ5KHBsb3RseSkNCg0KcCA8LSBwbG90X2x5KA0KICBkYXRhID0gaG90ZWxfbXVsdGlfZHQsDQogIHggPSB+c2FsYXJ5LA0KICB0eXBlID0gImhpc3RvZ3JhbSIsDQogIG1hcmtlciA9IGxpc3QoY29sb3IgPSAiIzM5RkYxNCIpDQopDQoNCnAgPC0gcCAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gbGlzdCh0ZXh0ID0gIlNhbGFyeSBEaXN0cmlidXRpb24iKSwNCiAgICBwbG90X2JnY29sb3IgPSAiIzAwMDAwMCIsDQogICAgcGFwZXJfYmdjb2xvciA9ICIjMDAwMDAwIiwNCiAgICBmb250ID0gbGlzdChjb2xvciA9ICIjMzlGRjE0IiksDQogICAgDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlNhbGFyeSIpLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJDb3VudCIpDQogICkNCnANCmBgYA0KDQo8ZGl2IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNGRkY5QzQ7IHBhZGRpbmc6MTVweDsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3JkZXI6MXB4IHNvbGlkICNGREQ4MzU7IG1hcmdpbi10b3A6MTBweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPg0KDQoqKkludGVycHJldGF0aW9uKioNCg0KVGhlIGhpc3RvZ3JhbSBpbmRpY2F0ZXMgdGhhdCBtb3N0IGVtcGxveWVlcyBhcmUgY29uY2VudHJhdGVkIHdpdGhpbiBhIGNlcnRhaW4gc2FsYXJ5IHJhbmdlLCBzdWdnZXN0aW5nIHRoYXQgdGhlIGNvbXBhbnkgaGFzIGEgZG9taW5hbnQgcGF5IGxldmVsIGZvciB0aGUgbWFqb3JpdHkgb2YgaXRzIHdvcmtmb3JjZS4gVGhlcmUgYXJlIGZld2VyIGVtcGxveWVlcyBpbiB0aGUgaGlnaGVyIHNhbGFyeSByYW5nZXMsIHdoaWNoIGltcGxpZXMgdGhhdCBoaWdoLXBheWluZyBwb3NpdGlvbnMgYXJlIGxpbWl0ZWQuIElmIHRoZSBkaXN0cmlidXRpb24gaXMgc2tld2VkIHRvIHRoZSByaWdodCwgaXQgc2hvd3MgdGhhdCBtb3N0IGVtcGxveWVlcyBlYXJuIGxvd2VyIHRvIG1pZC1sZXZlbCBzYWxhcmllcywgd2l0aCBvbmx5IGEgc21hbGwgbnVtYmVyIHJlY2VpdmluZyBzaWduaWZpY2FudGx5IGhpZ2hlciBwYXkuIFRoaXMgcGF0dGVybiByZWZsZWN0cyBhIHR5cGljYWwgb3JnYW5pemF0aW9uYWwgc3RydWN0dXJlIHdoZXJlIHRvcC1sZXZlbCBwb3NpdGlvbnMgYXJlIGZld2VyIGNvbXBhcmVkIHRvIGVudHJ5LSBhbmQgbWlkLWxldmVsIHJvbGVzLg0KDQo8L2Rpdj4NCg0KDQpgYGB7cn0NCmxpYnJhcnkocGxvdGx5KQ0KDQojIFdhcm5hIG5lb24gdW50dWsgc2V0aWFwIGRlcGFydG1lbnQNCm5lb25fY29sb3JzIDwtIGMoDQogICIjMzlGRjE0IiwgICMgTmVvbiBncmVlbg0KICAiI0ZGMDczMCIsICAjIE5lb24gcmVkDQogICIjMDBGRkZGIiwgICMgTmVvbiBjeWFuDQogICIjRkYwMEZGIiwgICMgTmVvbiBtYWdlbnRhDQogICIjRkZDQzAwIiwgICMgTmVvbiB5ZWxsb3cNCiAgIiNGRjY2MDAiICAgIyBOZW9uIG9yYW5nZQ0KKQ0KDQojIEJ1YXQgbW9kZWwgcmVncmVzc2lvbiB1bnR1ayBrZXNlbHVydWhhbiBkYXRhDQptb2RlbCA8LSBsbShLUElfc2NvcmUgfiBzYWxhcnksIGRhdGEgPSBob3RlbF9tdWx0aV9kdCkNCmhvdGVsX211bHRpX2R0JGZpdHRlZF9rcGkgPC0gZml0dGVkKG1vZGVsKQ0KDQpwIDwtIHBsb3RfbHkoDQogIGRhdGEgPSBob3RlbF9tdWx0aV9kdCwNCiAgeCA9IH5zYWxhcnksDQogIHkgPSB+S1BJX3Njb3JlLA0KICBjb2xvciA9IH5kZXBhcnRtZW50LA0KICBjb2xvcnMgPSBuZW9uX2NvbG9ycywNCiAgdHlwZSA9ICJzY2F0dGVyIiwNCiAgbW9kZSA9ICJtYXJrZXJzIiwNCiAgbWFya2VyID0gbGlzdCgNCiAgICBzaXplID0gOCwNCiAgICBvcGFjaXR5ID0gMC44DQogICkNCikgJT4lDQogIGFkZF9saW5lcygNCiAgICB4ID0gfnNhbGFyeSwNCiAgICB5ID0gfmZpdHRlZF9rcGksDQogICAgbGluZSA9IGxpc3QoY29sb3IgPSAiI0ZGMDczMCIsIHdpZHRoID0gMyksDQogICAgbmFtZSA9ICJSZWdyZXNzaW9uIExpbmUiLA0KICAgIGluaGVyaXQgPSBGQUxTRQ0KICApICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICJTYWxhcnkgdnMgS1BJIFNjb3JlIGJ5IERlcGFydG1lbnQgd2l0aCBSZWdyZXNzaW9uIExpbmUiLA0KICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSAiIzAwRkZGRiIsIHNpemUgPSAxOCkNCiAgICApLA0KICAgIHBsb3RfYmdjb2xvciA9ICIjMDAwMDAwIiwNCiAgICBwYXBlcl9iZ2NvbG9yID0gIiMwMDAwMDAiLA0KICAgIGZvbnQgPSBsaXN0KGNvbG9yID0gIiMzOUZGMTQiKSwNCiAgICB4YXhpcyA9IGxpc3QoDQogICAgICB0aXRsZSA9ICJTYWxhcnkiLA0KICAgICAgZ3JpZGNvbG9yID0gIiMzMzMzMzMiLA0KICAgICAgdGlja2ZvbnQgPSBsaXN0KGNvbG9yID0gIiNGRkNDMDAiKQ0KICAgICksDQogICAgeWF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAiS1BJIFNjb3JlIiwNCiAgICAgIGdyaWRjb2xvciA9ICIjMzMzMzMzIiwNCiAgICAgIHRpY2tmb250ID0gbGlzdChjb2xvciA9ICIjRkZDQzAwIikNCiAgICApLA0KICAgIGxlZ2VuZCA9IGxpc3QoDQogICAgICBmb250ID0gbGlzdChjb2xvciA9ICIjMDBGRkZGIiksDQogICAgICBiZ2NvbG9yID0gInJnYmEoMCwwLDAsMC43KSIsDQogICAgICBib3JkZXJjb2xvciA9ICIjMzlGRjE0IiwNCiAgICAgIGJvcmRlcndpZHRoID0gMQ0KICAgICkNCiAgKQ0KDQpwDQpgYGANCg0KDQo8ZGl2IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNGRkY5QzQ7IHBhZGRpbmc6MTVweDsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3JkZXI6MXB4IHNvbGlkICNGREQ4MzU7IG1hcmdpbi10b3A6MTBweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPg0KDQoqKkludGVycHJldGF0aW9uKioNCg0KVGhlIGhpc3RvZ3JhbSBpbmRpY2F0ZXMgdGhhdCBtb3N0IGVtcGxveWVlcyBhcmUgY29uY2VudHJhdGVkIHdpdGhpbiBhIGNlcnRhaW4gc2FsYXJ5IHJhbmdlLCBzdWdnZXN0aW5nIHRoYXQgdGhlIGNvbXBhbnkgaGFzIGEgZG9taW5hbnQgcGF5IGxldmVsIGZvciB0aGUgbWFqb3JpdHkgb2YgaXRzIHdvcmtmb3JjZS4gVGhlcmUgYXJlIGZld2VyIGVtcGxveWVlcyBpbiB0aGUgaGlnaGVyIHNhbGFyeSByYW5nZXMsIHdoaWNoIGltcGxpZXMgdGhhdCBoaWdoLXBheWluZyBwb3NpdGlvbnMgYXJlIGxpbWl0ZWQuIElmIHRoZSBkaXN0cmlidXRpb24gaXMgc2tld2VkIHRvIHRoZSByaWdodCwgaXQgc2hvd3MgdGhhdCBtb3N0IGVtcGxveWVlcyBlYXJuIGxvd2VyIHRvIG1pZC1sZXZlbCBzYWxhcmllcywgd2l0aCBvbmx5IGEgc21hbGwgbnVtYmVyIHJlY2VpdmluZyBzaWduaWZpY2FudGx5IGhpZ2hlciBwYXkuIFRoaXMgcGF0dGVybiByZWZsZWN0cyBhIHR5cGljYWwgb3JnYW5pemF0aW9uYWwgc3RydWN0dXJlIHdoZXJlIHRvcC1sZXZlbCBwb3NpdGlvbnMgYXJlIGZld2VyIGNvbXBhcmVkIHRvIGVudHJ5LSBhbmQgbWlkLWxldmVsIHJvbGVzLg0KDQo8L2Rpdj4=