Practicum Syntax and Control Flow

Profil Mahasiswa - Anindya Kristianingputri
Foto Profil Anindya Kristianingputri

Anindya Kristianingputri

NIM: 52250025

Student Major Data Science

Bandung Institute of Science and Technology

Lecture: Bakti Siregar, M.Sc., CDS
R Programming Programming Data Science Syntax and Contraflow
Konsep Probabilitas

Application of Looping Structures in Employee Dataset Analysis Using R

This dataset contains data of five employees with several variables: ID as employee identification, Name, Age, Salary as the amount of salary, Position as the job title within the company, and Performance as a performance rating such as Good, Very Good, and Average.

This data serves as a simple example to practice the use of loops in R programming, specifically for loops and while loops, in conducting dataset analysis. Through this exercise, we can understand how to traverse each row of data, perform specific condition checks, and control the flow of loops using the break command to stop the process and continue to skip data that does not meet certain conditions.

suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(kableExtra))

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000),
  Position = c("Staff","Supervisor","Staff","Manager","Director"),
  Performance = c("Good","Very Good","Average","Good","Very Good")
)

# table
kable(data_karyawan, caption = "Employee Dataset") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped","bordered")) %>%
  row_spec(0, background = "#6F4E37", color = "white")
Employee Dataset
ID Name Age Salary Position Performance
1 Bagas 25 5000 Staff Good
2 Joan 30 7000 Supervisor Very Good
3 Alya 27 6500 Staff Average
4 Dwi 35 10000 Manager Good
5 Nabil 40 12000 Director Very Good

1 Conditional Statement

In R programming, a conditional statement is a control structure used to execute specific commands based on a logical condition that evaluates to TRUE or FALSE. In R, conditional statements typically use the commands if, else if, and else to evaluate a condition and determine the action to be executed by the program. This structure is often used in data analysis to check variable values, group data based on certain criteria, or determine the next steps in the data processing workflow.

Question: A company wants to calculate employee bonuses based on their performance. Employees with Very Good performance receive 20% of their salary as a bonus, employees with Good performance receive 10% of their salary, and employees with Average performance receive 5% of their salary. Using these rules, write a program to determine the bonus level for each employee and calculate the bonus amount based on their salary.

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000),
  Position = c("Staff","Supervisor","Staff","Manager","Director"),
  Performance = c("Good","Very Good","Average","Good","Very Good")
)

# Calculate the bonus and display the output
for(i in 1:nrow(data_karyawan)){
  
  if(data_karyawan$Performance[i] == "Very Good"){
    bonus <- 0.20 * data_karyawan$Salary[i]
    
  } else if(data_karyawan$Performance[i] == "Good"){
    bonus <- 0.10 * data_karyawan$Salary[i]
    
  } else if(data_karyawan$Performance[i] == "Average"){
    bonus <- 0.05 * data_karyawan$Salary[i]
    
  } else{
    bonus <- 0
  }
  
  cat(paste0("Name: ", data_karyawan$Name[i], ", Bonus: ", bonus, "\n"))
}
## Name: Bagas, Bonus: 500
## Name: Joan, Bonus: 1400
## Name: Alya, Bonus: 325
## Name: Dwi, Bonus: 1000
## Name: Nabil, Bonus: 2400
suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(kableExtra))

library(knitr)
library(kableExtra)

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000),
  Position = c("Staff","Supervisor","Staff","Manager","Director"),
  Performance = c("Good","Very Good","Average","Good","Very Good")
)

# Create bonus column
bonus <- c()

for(i in 1:nrow(data_karyawan)){
  
  if(data_karyawan$Performance[i] == "Very Good"){
    bonus[i] <- 0.20 * data_karyawan$Salary[i]
    
  } else if(data_karyawan$Performance[i] == "Good"){
    bonus[i] <- 0.10 * data_karyawan$Salary[i]
    
  } else if(data_karyawan$Performance[i] == "Average"){
    bonus[i] <- 0.05 * data_karyawan$Salary[i]
    
  } else{
    bonus[i] <- 0
  }
}

# Result data 
hasil_bonus <- data.frame(
  Name = data_karyawan$Name,
  Bonus = bonus
)

kable(hasil_bonus, caption = "Employee Bonus Result") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped","bordered")) %>%
  row_spec(0, background = "#6F4E37", color = "white") %>%
  column_spec(1:2, border_left = TRUE, border_right = TRUE)
Employee Bonus Result
Name Bonus
Bagas 500
Joan 1400
Alya 325
Dwi 1000
Nabil 2400

2 Loops (For & While)

2.1 for loop

A for loop is used when the number of iterations is already known in advance. The loop begins by initializing a counter, then checking a condition before executing the code inside the loop. After each execution, the counter increases, and the process repeats until the condition is no longer satisfied.

Instruction:

Use a for loop to display the names of employees whose salary is greater than 6000.

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000)
)

# For loop to display employees with salary greater than 6000
for(i in 1:nrow(data_karyawan)) {
  if(data_karyawan$Salary[i] > 6000) {
    cat("Name:", data_karyawan$Name[i], 
        ", Salary:", data_karyawan$Salary[i], "\n")
  }
}
## Name: Joan , Salary: 7000 
## Name: Alya , Salary: 6500 
## Name: Dwi , Salary: 10000 
## Name: Nabil , Salary: 12000
suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(kableExtra))

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000)
)

# Store the results
nama <- c()
gaji <- c()

# For loop to find salaries greater than 6000
for(i in 1:nrow(data_karyawan)) {
  if(data_karyawan$Salary[i] > 6000) {
    nama <- c(nama, data_karyawan$Name[i])
    gaji <- c(gaji, data_karyawan$Salary[i])
  }
}

# Result data
hasil <- data.frame(
  Name = nama,
  Salary = gaji
)

# table
kable(hasil, caption = "Employees with Salary Greater Than 6000") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped","bordered")) %>%
  row_spec(0, background = "#6F4E37", color = "white")
Employees with Salary Greater Than 6000
Name Salary
Joan 7000
Alya 6500
Dwi 10000
Nabil 12000

2.2 While Loop

A while loop is used when a process needs to continue running as long as a certain condition remains true. The loop repeatedly executes the code and checks the condition after each iteration. This process continues until the condition eventually becomes false, at which point the loop stops.

Instruction:

Use a while loop to display employees until a “Manager” is found.

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000),
  Position = c("Staff","Supervisor","Staff","Manager","Director"),
  Performance = c("Good","Very Good","Average","Good","Very Good")
)

# While loop to display employees until a Manager is found
i <- 1

while(i <= nrow(data_karyawan)) {
  
  if(data_karyawan$Position[i] == "Manager") {
    cat("Name:", data_karyawan$Name[i],
        ", Position:", data_karyawan$Position[i],
        "(Stop here)\n")
    break
  }
  
  cat("Name:", data_karyawan$Name[i],
      ", Position:", data_karyawan$Position[i], "\n")
  
  i <- i + 1
}
## Name: Bagas , Position: Staff 
## Name: Joan , Position: Supervisor 
## Name: Alya , Position: Staff 
## Name: Dwi , Position: Manager (Stop here)
suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(kableExtra))

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000),
  Position = c("Staff","Supervisor","Staff","Manager","Director"),
  Performance = c("Good","Very Good","Average","Good","Very Good")
)

# Store the results
nama <- c()
posisi <- c()

i <- 1

# While loop
while(i <= nrow(data_karyawan)){
  
  nama <- c(nama, data_karyawan$Name[i])
  posisi <- c(posisi, data_karyawan$Position[i])
  
  if(data_karyawan$Position[i] == "Manager"){
    posisi[length(posisi)] <- paste(posisi[length(posisi)], "(Stop here)")
    break
  }
  
  i <- i + 1
}

# Result 
hasil <- data.frame(
  Name = nama,
  Position = posisi
)

# table
kable(hasil, caption = " Until Manager Found") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped","bordered")) %>%
  row_spec(0, background = "#6F4E37", color = "white")
Until Manager Found
Name Position
Bagas Staff
Joan Supervisor
Alya Staff
Dwi Manager (Stop here)

2.3 Break

A break statement is used to stop a loop immediately before it finishes all of its iterations. When the break condition is met, the program exits the loop right away. This allows the loop to terminate early without continuing the remaining repetitions.

Instruction:

Use break to stop the loop when an employee with a salary above 10,000 is found.

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000)
)

# For loop with break when salary above 10000
for(i in 1:nrow(data_karyawan)) {
  
  if(data_karyawan$Salary[i] > 10000) {
    break
  }
  
  cat("Name:", data_karyawan$Name[i], 
      ", Salary:", data_karyawan$Salary[i], "\n")
}
## Name: Bagas , Salary: 5000 
## Name: Joan , Salary: 7000 
## Name: Alya , Salary: 6500 
## Name: Dwi , Salary: 10000
suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(kableExtra))

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Age = c(25,30,27,35,40),
  Salary = c(5000,7000,6500,10000,12000)
)

# Store results
nama <- c()
gaji <- c()

# For loop with break
for(i in 1:nrow(data_karyawan)) {
  
  if(data_karyawan$Salary[i] > 10000) {
    break
  }
  
  nama <- c(nama, data_karyawan$Name[i])
  gaji <- c(gaji, data_karyawan$Salary[i])
}

# Result data
hasil <- data.frame(
  Name = nama,
  Salary = gaji
)

# table
kable(hasil, caption = "Until Salary Above 10,000 Found") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped","bordered")) %>%
  row_spec(0, background = "#6F4E37", color = "white")
Until Salary Above 10,000 Found
Name Salary
Bagas 5000
Joan 7000
Alya 6500
Dwi 10000

2.4 Continue

The continue statement skips the current iteration without stopping the loop and immediately moves to the next iteration. The loop then checks the condition again before executing the next cycle. The loop will stop when the condition is no longer satisfied or when a break statement is encountered. If the condition remains true, the loop continues to run unless it is interrupted by a break.

Instruction:

Use continue to skip employees with “Average” performance.

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Performance = c("Good","Very Good","Average","Good","Very Good")
)

# For loop using next (continue) to skip "Average"
for(i in 1:nrow(data_karyawan)) {
  
  if(data_karyawan$Performance[i] == "Average") {
    next
  }
  
  cat("Name:", data_karyawan$Name[i], 
      ", Performance:", data_karyawan$Performance[i], "\n")
}
## Name: Bagas , Performance: Good 
## Name: Joan , Performance: Very Good 
## Name: Dwi , Performance: Good 
## Name: Nabil , Performance: Very Good
suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(kableExtra))

# Employee dataset
data_karyawan <- data.frame(
  ID = c(1,2,3,4,5),
  Name = c("Bagas","Joan","Alya","Dwi","Nabil"),
  Performance = c("Good","Very Good","Average","Good","Very Good")
)

# Store results
nama <- c()
perf <- c()

# For loop using next (continue)
for(i in 1:nrow(data_karyawan)) {
  
  if(data_karyawan$Performance[i] == "Average") {
    next
  }
  
  nama <- c(nama, data_karyawan$Name[i])
  perf <- c(perf, data_karyawan$Performance[i])
}

# Result data
hasil <- data.frame(
  Name = nama,
  Performance = perf
)

# table
kable(hasil, caption = "Employees with Non-Average") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped","bordered")) %>%
  row_spec(0, background = "#6F4E37", color = "white")
Employees with Non-Average
Name Performance
Bagas Good
Joan Very Good
Dwi Good
Nabil Very Good

Conclusion

This activity demonstrates how conditional statements enable programs to make decisions based on specific criteria. Here, conditions are used to assign employee bonus percentages according to performance levels such as Very Good, Good, and Average. Through these logical structures, the program can automatically compute the appropriate bonus from each employee's salary, enhancing both efficiency and consistency in the process.

Moreover, looping mechanisms like the for and while loops, combined with control statements such as break and continue, streamline repetitive operations involved in handling employee records. The for loop proves effective for scanning datasets to identify employees meeting particular conditions, while the while loop continues execution until a specified condition is fulfilled. The break statement terminates a loop prematurely when a desired condition is met, and continue allows the loop to bypass certain data without halting entirely. Collectively, these programming constructs contribute to the development of efficient systems for managing and analyzing employee data.

LS0tDQp0aXRsZTogIlByYWN0aWN1bSBTeW50YXggYW5kIENvbnRyb2wgRmxvdyIgICAgICAgICAgICAjIE1haW4gdGl0bGUgb2YgdGhlIGRvY3VtZW50DQphdXRob3I6ICJBbmluZHlhIEtyaXN0aWFuaW5ncHV0cmkiICAgICAgIyBSZXBsYWNlIHdpdGggeW91ciBmdWxsIG5hbWUNCmRhdGU6ICAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiICMgQXV0byBkaXNwbGF5cyB0aGUgY3VycmVudCBkYXRlDQpvdXRwdXQ6ICAgICAgICAgICAgICAgICAgICAgICAgICMgT3V0cHV0IHNlY3Rpb24gZGVmaW5lcyB0aGUgZm9ybWF0IGFuZCBsYXlvdXQgDQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOiAgICAgICMgaHR0cHM6Ly9naXRodWIuY29tL2p1YmEvcm1kZm9ybWF0cw0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlICAgICAgICAjIEVtYmVkcyBhbGwgcmVzb3VyY2VzIChDU1MsIEpTLCBpbWFnZXMpIA0KICAgIHRodW1ibmFpbHM6IHRydWUgICAgICAgICAgICAjIERpc3BsYXlzIGltYWdlIHRodW1ibmFpbHMgaW4gdGhlIGRvYw0KICAgIGxpZ2h0Ym94OiB0cnVlICAgICAgICAgICAgICAjIEVuYWJsZXMgY2xpY2sgdG8gZW5sYXJnZSBpbWFnZXMNCiAgICBnYWxsZXJ5OiB0cnVlICAgICAgICAgICAgICAgIyBHcm91cHMgaW1hZ2VzIGludG8gYW4gaW50ZXJhY3RpdmUgZ2FsbGVyeQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZSAgICAgICAjIEF1dG9tYXRpY2FsbHkgbnVtYmVycyBhbGwgc2VjdGlvbnMNCiAgICBsaWJfZGlyOiBsaWJzICAgICAgICAgICAgICAgIyBEaXJlY3Rvcnkgd2hlcmUgSmF2YVNjcmlwdC9DU1MgbGlicmFyaWVzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCIgICAgICAgICAgICMgRGlzcGxheXMgZGF0YSBmcmFtZXMgYXMgaW50ZXJhY3RpdmUgcGFnZWQgDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyIgICAgICAgICMgQWxsb3dzIGZvbGRpbmcvdW5mb2xkaW5nIFIgY29kZSBibG9ja3MgDQogICAgY29kZV9kb3dubG9hZDogeWVzICAgICAgICAgICMgQWRkcyBhIGJ1dHRvbiB0byBkb3dubG9hZCBhbGwgUiBjb2RlDQotLS0NCg0KYGBgez1odG1sfQ0KPHN0eWxlPg0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDQ3cHggIWltcG9ydGFudDsNCiAgZm9udC13ZWlnaHQ6IDgwMDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkhpcmFnaW5vIE1hcnUgR290aGljIiwgIll1IEdvdGhpYyIsICJNUyBQR290aGljIiwgc2Fucy1zZXJpZiAhaW1wb3J0YW50Ow0KICBmb250LXN0eWxlOiBpdGFsaWMgIWltcG9ydGFudDsNCiAgbWFyZ2luLWJvdHRvbTogMjBweCAhaW1wb3J0YW50Ow0KICBsaW5lLWhlaWdodDogMS4yOw0KICBwb3NpdGlvbjogcmVsYXRpdmU7DQogIHBhZGRpbmctYm90dG9tOiAxNXB4ICFpbXBvcnRhbnQ7DQp9DQoNCmgxLnRpdGxlOjphZnRlciB7DQogIGNvbnRlbnQ6ICIiOw0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGJvdHRvbTogMDsNCiAgbGVmdDogNTAlOw0KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7DQogIHdpZHRoOiAxNTBweDsNCiAgaGVpZ2h0OiAycHg7DQogIGJhY2tncm91bmQ6IGN1cnJlbnRDb2xvcjsNCiAgb3BhY2l0eTogMC4zOw0KfQ0KDQoucGVyZmVjdC1jZW50ZXItYm94IHsNCiAgcG9zaXRpb246IHJlbGF0aXZlOw0KICBwYWRkaW5nOiAyNXB4IDQwcHggIWltcG9ydGFudDsNCiAgbWFyZ2luOiAyMHB4IGF1dG8gIWltcG9ydGFudDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBkaXNwbGF5OiB0YWJsZTsNCiAgYmFja2dyb3VuZDogI2ZmZjlmOTsNCiAgYm9yZGVyOiAxcHggc29saWQgI2ZmYjZjMTsNCiAgYm9yZGVyLXJhZGl1czogMjVweDsNCiAgYm94LXNoYWRvdzogMCA0cHggMTVweCByZ2JhKDI1NSwgMTgyLCAxOTMsIDAuMyk7DQogIG1heC13aWR0aDogNTAwcHg7DQogIGZvbnQtZmFtaWx5OiAiS2F3YWlpIiwgIkNvbWljIFNhbnMgTVMiLCAiQ2hhbGtib2FyZCIsIGN1cnNpdmUgIWltcG9ydGFudDsNCn0NCg0KLnBlcmZlY3QtY2VudGVyLWJveDo6YmVmb3JlLA0KLnBlcmZlY3QtY2VudGVyLWJveDo6YWZ0ZXIgew0KICBjb250ZW50OiAi4py/IjsNCiAgcG9zaXRpb246IGFic29sdXRlOw0KICB3aWR0aDogYXV0bzsNCiAgaGVpZ2h0OiBhdXRvOw0KICBmb250LXNpemU6IDI0cHg7DQogIGNvbG9yOiAjZmY5OWNjOw0KICBib3JkZXI6IG5vbmU7DQogIG9wYWNpdHk6IDAuNjsNCiAgdHJhbnNpdGlvbjogYWxsIDAuM3MgZWFzZTsNCn0NCg0KLnBlcmZlY3QtY2VudGVyLWJveDo6YmVmb3JlIHsNCiAgdG9wOiA1cHg7DQogIGxlZnQ6IDEwcHg7DQogIGJvcmRlcjogbm9uZTsNCn0NCg0KLnBlcmZlY3QtY2VudGVyLWJveDo6YWZ0ZXIgew0KICBib3R0b206IDVweDsNCiAgcmlnaHQ6IDEwcHg7DQogIGJvcmRlcjogbm9uZTsNCn0NCg0KLnBlcmZlY3QtY2VudGVyLWJveDpob3Zlcjo6YmVmb3JlLA0KLnBlcmZlY3QtY2VudGVyLWJveDpob3Zlcjo6YWZ0ZXIgew0KICB0cmFuc2Zvcm06IHNjYWxlKDEuMik7DQogIG9wYWNpdHk6IDE7DQp9DQoNCi53ZWVrLW51bWJlciB7DQogIGZvbnQtc2l6ZTogMThweCAhaW1wb3J0YW50Ow0KICBmb250LXdlaWdodDogNzAwOw0KICBsZXR0ZXItc3BhY2luZzogMC41cHg7DQogIG1hcmdpbi1ib3R0b206IDVweCAhaW1wb3J0YW50Ow0KICBsaW5lLWhlaWdodDogMS4zOw0KICBmb250LWZhbWlseTogIlJvdW5kZWQgTXBsdXMgMWMiLCAiTW9jaGl5IFBvcCBPbmUiLCAiQ2hhbGtib2FyZCIsIHNhbnMtc2VyaWYgIWltcG9ydGFudDsNCiAgY29sb3I6ICNmZjY5YjQ7DQp9DQoNCi5hc3NpZ25tZW50LXRpdGxlIHsNCiAgZm9udC1zaXplOiAxNHB4ICFpbXBvcnRhbnQ7DQogIGZvbnQtd2VpZ2h0OiA1MDA7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgcGFkZGluZy10b3A6IDhweCAhaW1wb3J0YW50Ow0KICBtYXJnaW4tdG9wOiA1cHggIWltcG9ydGFudDsNCiAgbGluZS1oZWlnaHQ6IDEuMzsNCiAgZm9udC1mYW1pbHk6ICJLYXdhaWkiLCAiTW9jaGl5IFBvcCBQIE9uZSIsICJDaGFsa2JvYXJkIFNFIiwgY3Vyc2l2ZSAhaW1wb3J0YW50Ow0KICBjb2xvcjogIzkzNzBkYjsNCn0NCg0KLmFzc2lnbm1lbnQtdGl0bGU6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICLinKYiOw0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIHRvcDogLTVweDsNCiAgbGVmdDogNTAlOw0KICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7DQogIHdpZHRoOiBhdXRvOw0KICBoZWlnaHQ6IGF1dG87DQogIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50Ow0KICBvcGFjaXR5OiAwLjU7DQogIGZvbnQtc2l6ZTogMTZweDsNCn0NCg0KLmNvbnRhaW5lciB7DQogIG1hcmdpbjogMCAhaW1wb3J0YW50Ow0KICBwYWRkaW5nOiAyMHB4ICFpbXBvcnRhbnQ7DQogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICNmZmYwZjUgMCUsICNmZmU0ZTEgMTAwJSk7DQp9DQoNCi5jb250ZW50LXdyYXBwZXIgew0KICBkaXNwbGF5OiBmbGV4Ow0KICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOw0KICBnYXA6IDE1cHggIWltcG9ydGFudDsNCiAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCn0NCjwvc3R5bGU+DQpgYGANCg0KYGBgez1odG1sfQ0KPCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJpZCI+DQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+DQogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPg0KICAgIDx0aXRsZT5Qcm9maWwgTWFoYXNpc3dhIC0gQW5pbmR5YSBLcmlzdGlhbmluZ3B1dHJpPC90aXRsZT4NCiAgICA8c3R5bGU+DQogICAgICAgICogew0KICAgICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7DQogICAgICAgIH0NCg0KICAgICAgICBib2R5IHsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnUGxheWZhaXIgRGlzcGxheScsICdHZW9yZ2lhJywgc2VyaWY7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWltYWdlOiByZXBlYXRpbmctbGluZWFyLWdyYWRpZW50KDQ1ZGVnLCANCiAgICAgICAgICAgICAgICAjNUQzQTFBIDBweCwgIzVEM0ExQSAycHgsDQogICAgICAgICAgICAgICAgIzdCNEYyQiAycHgsICM3QjRGMkIgOHB4LA0KICAgICAgICAgICAgICAgICM1RDNBMUEgOHB4LCAjNUQzQTFBIDEwcHgsDQogICAgICAgICAgICAgICAgIzhCNUEyQiAxMHB4LCAjOEI1QTJCIDE2cHgNCiAgICAgICAgICAgICk7DQogICAgICAgICAgICBjb2xvcjogIzJDMTgxMDsNCiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjU7DQogICAgICAgICAgICBwYWRkaW5nOiAyMHB4Ow0KICAgICAgICAgICAgZGlzcGxheTogZmxleDsNCiAgICAgICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICAgICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgICAgICAgICAgIG1pbi1oZWlnaHQ6IDEwMHZoOw0KICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOw0KICAgICAgICB9DQoNCiAgICAgICAgYm9keTo6YmVmb3JlIHsNCiAgICAgICAgICAgIGNvbnRlbnQ6ICIiOw0KICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlOw0KICAgICAgICAgICAgdG9wOiAwOw0KICAgICAgICAgICAgbGVmdDogMDsNCiAgICAgICAgICAgIHJpZ2h0OiAwOw0KICAgICAgICAgICAgYm90dG9tOiAwOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogcmdiYSgxMzksIDY5LCAxOSwgMC4xNSk7DQogICAgICAgICAgICBwb2ludGVyLWV2ZW50czogbm9uZTsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250YWluZXIgew0KICAgICAgICAgICAgbWF4LXdpZHRoOiA3NTBweDsNCiAgICAgICAgICAgIHdpZHRoOiAxMDAlOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogI0Y0RTZEOTsNCiAgICAgICAgICAgIGJhY2tncm91bmQtaW1hZ2U6IHVybCgnZGF0YTppbWFnZS9zdmcreG1sO3V0ZjgsPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MCIgaGVpZ2h0PSI4MCIgdmlld0JveD0iMCAwIDgwIDgwIj48cGF0aCBkPSJNMCAwIEw4MCAwIEw4MCA4MCBMMCA4MCBaIiBmaWxsPSIlMjNGNEU2RDkiLz48cGF0aCBkPSJNMTUgMCBMMjUgMCBMMjAgODAgTDEwIDgwIiBmaWxsPSIlMjNEMkI0OEMiIG9wYWNpdHk9IjAuMDgiLz48cGF0aCBkPSJNMzUgMCBMNDUgMCBMNDAgODAgTDMwIDgwIiBmaWxsPSIlMjNEMkI0OEMiIG9wYWNpdHk9IjAuMDgiLz48cGF0aCBkPSJNNTUgMCBMNjUgMCBMNjAgODAgTDUwIDgwIiBmaWxsPSIlMjNEMkI0OEMiIG9wYWNpdHk9IjAuMDgiLz48L3N2Zz4nKTsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDI0cHg7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDE1cHggMzBweCByZ2JhKDcwLCAzNSwgMTAsIDAuNCk7DQogICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuOw0KICAgICAgICAgICAgYm9yZGVyOiA2cHggc29saWQgIzhCNUEyQjsNCiAgICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgICAgICAgfQ0KDQogICAgICAgIC5jb250YWluZXI6OmJlZm9yZSB7DQogICAgICAgICAgICBjb250ZW50OiAiIjsNCiAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgICAgICAgICAgIHRvcDogOHB4Ow0KICAgICAgICAgICAgbGVmdDogOHB4Ow0KICAgICAgICAgICAgcmlnaHQ6IDhweDsNCiAgICAgICAgICAgIGJvdHRvbTogOHB4Ow0KICAgICAgICAgICAgYm9yZGVyOiAxcHggZGFzaGVkICNDMTlBNkI7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAxNnB4Ow0KICAgICAgICAgICAgcG9pbnRlci1ldmVudHM6IG5vbmU7DQogICAgICAgICAgICBvcGFjaXR5OiAwLjM7DQogICAgICAgIH0NCg0KICAgICAgICAuaGVhZGVyIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICM2QjRGMzIsICM4QjVBMkIpOw0KICAgICAgICAgICAgY29sb3I6ICNGRkVCQ0Q7DQogICAgICAgICAgICBwYWRkaW5nOiAzNXB4IDMwcHggMzBweCAzMHB4Ow0KICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOw0KICAgICAgICAgICAgYm9yZGVyLWJvdHRvbTogM3B4IHNvbGlkICNDMTlBNkI7DQogICAgICAgIH0NCg0KICAgICAgICAucHJvZmlsZS1jb250ZW50IHsNCiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgICAgICAgZ2FwOiAzMHB4Ow0KICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOw0KICAgICAgICAgICAgei1pbmRleDogMjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5waG90by1jb250YWluZXIgew0KICAgICAgICAgICAgZmxleC1zaHJpbms6IDA7DQogICAgICAgICAgICB3aWR0aDogMTMwcHg7DQogICAgICAgICAgICBoZWlnaHQ6IDEzMHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNTAlOw0KICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjsNCiAgICAgICAgICAgIGJvcmRlcjogNHB4IHNvbGlkICNERUI4ODc7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDhweCAxOHB4IHJnYmEoMCwgMCwgMCwgMC4yNSk7DQogICAgICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7DQogICAgICAgICAgICB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gMC4zcyBlYXNlOw0KICAgICAgICB9DQoNCiAgICAgICAgLnBob3RvLWNvbnRhaW5lcjpob3ZlciB7DQogICAgICAgICAgICB0cmFuc2Zvcm06IHNjYWxlKDEuMDMpOw0KICAgICAgICB9DQoNCiAgICAgICAgLnByb2ZpbGUtcGhvdG8gew0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBoZWlnaHQ6IDEwMCU7DQogICAgICAgICAgICBvYmplY3QtZml0OiBjb3ZlcjsNCiAgICAgICAgfQ0KDQogICAgICAgIC5wcm9maWxlLWluZm8gew0KICAgICAgICAgICAgZmxleDogMTsNCiAgICAgICAgICAgIHRleHQtYWxpZ246IGxlZnQ7DQogICAgICAgIH0NCg0KICAgICAgICAubmFtZSB7DQogICAgICAgICAgICBmb250LXNpemU6IDI4cHg7DQogICAgICAgICAgICBmb250LXdlaWdodDogNzAwOw0KICAgICAgICAgICAgbWFyZ2luLWJvdHRvbTogNXB4Ow0KICAgICAgICAgICAgY29sb3I6ICNGRkU0QzQ7DQogICAgICAgICAgICB0ZXh0LXNoYWRvdzogMnB4IDJweCAwICM1RDNBMUE7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0JydXNoIFNjcmlwdCBNVCcsICdMdWNpZGEgSGFuZHdyaXRpbmcnLCBjdXJzaXZlOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDFweDsNCiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjI7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KICAgICAgICB9DQoNCiAgICAgICAgLm5pbSB7DQogICAgICAgICAgICBmb250LXNpemU6IDE1cHg7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjQzE5QTZCOw0KICAgICAgICAgICAgY29sb3I6ICMyQzE4MTA7DQogICAgICAgICAgICBwYWRkaW5nOiA1cHggMTVweDsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDI1cHg7DQogICAgICAgICAgICBtYXJnaW4tYm90dG9tOiAxMnB4Ow0KICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICM4QjVBMkI7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ0NvdXJpZXIgTmV3JywgbW9ub3NwYWNlOw0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAycHggNXB4IHJnYmEoMCwgMCwgMCwgMC4xNSk7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KICAgICAgICB9DQoNCiAgICAgICAgLnN0dWR5LWluZm8gew0KICAgICAgICAgICAgZm9udC1zaXplOiAxNXB4Ow0KICAgICAgICAgICAgbWFyZ2luLWJvdHRvbTogNnB4Ow0KICAgICAgICAgICAgY29sb3I6ICNGNURFQjM7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1BhbGF0aW5vJywgJ0dlb3JnaWEnLCBzZXJpZjsNCiAgICAgICAgICAgIGZvbnQtc3R5bGU6IGl0YWxpYzsNCiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjU7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KICAgICAgICB9DQoNCiAgICAgICAgLnN0dWR5LWluZm8gcCB7DQogICAgICAgICAgICBtYXJnaW4tYm90dG9tOiAzcHg7DQogICAgICAgIH0NCg0KICAgICAgICAuZG9zZW4taW5mbyB7DQogICAgICAgICAgICBmb250LXNpemU6IDE0cHg7DQogICAgICAgICAgICBtYXJnaW4tdG9wOiAxMnB4Ow0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgICAgICAgICAgIGNvbG9yOiAjRkZEQUI5Ow0KICAgICAgICAgICAgYmFja2dyb3VuZDogIzVEM0ExQTsNCiAgICAgICAgICAgIHBhZGRpbmc6IDZweCAxNnB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMzBweDsNCiAgICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNDMTlBNkI7DQogICAgICAgICAgICBmb250LWZhbWlseTogJ1RyZWJ1Y2hldCBNUycsIHNhbnMtc2VyaWY7DQogICAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMC41cHg7DQogICAgICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KICAgICAgICB9DQoNCiAgICAgICAgLnNraWxscy1zZWN0aW9uIHsNCiAgICAgICAgICAgIHBhZGRpbmc6IDIwcHggMjVweDsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICNFNkQ1Qjg7DQogICAgICAgICAgICBiYWNrZ3JvdW5kLWltYWdlOiByZXBlYXRpbmctbGluZWFyLWdyYWRpZW50KDBkZWcsIA0KICAgICAgICAgICAgICAgIHRyYW5zcGFyZW50LCANCiAgICAgICAgICAgICAgICB0cmFuc3BhcmVudCAyNXB4LCANCiAgICAgICAgICAgICAgICByZ2JhKDEzOSwgNjksIDE5LCAwLjAzKSAyNXB4LCANCiAgICAgICAgICAgICAgICByZ2JhKDEzOSwgNjksIDE5LCAwLjAzKSA1MHB4DQogICAgICAgICAgICApOw0KICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOw0KICAgICAgICB9DQoNCiAgICAgICAgLnNraWxscy1zZWN0aW9uOjpiZWZvcmUgew0KICAgICAgICAgICAgY29udGVudDogIiI7DQogICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7DQogICAgICAgICAgICB0b3A6IDVweDsNCiAgICAgICAgICAgIGxlZnQ6IDE1cHg7DQogICAgICAgICAgICB3aWR0aDogMjBweDsNCiAgICAgICAgICAgIGhlaWdodDogMjBweDsNCiAgICAgICAgICAgIGJvcmRlci1sZWZ0OiAxLjVweCBzb2xpZCAjOEI1QTJCOw0KICAgICAgICAgICAgYm9yZGVyLXRvcDogMS41cHggc29saWQgIzhCNUEyQjsNCiAgICAgICAgICAgIG9wYWNpdHk6IDAuMjU7DQogICAgICAgIH0NCg0KICAgICAgICAuc2tpbGxzLXNlY3Rpb246OmFmdGVyIHsNCiAgICAgICAgICAgIGNvbnRlbnQ6ICIiOw0KICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlOw0KICAgICAgICAgICAgYm90dG9tOiA1cHg7DQogICAgICAgICAgICByaWdodDogMTVweDsNCiAgICAgICAgICAgIHdpZHRoOiAyMHB4Ow0KICAgICAgICAgICAgaGVpZ2h0OiAyMHB4Ow0KICAgICAgICAgICAgYm9yZGVyLXJpZ2h0OiAxLjVweCBzb2xpZCAjOEI1QTJCOw0KICAgICAgICAgICAgYm9yZGVyLWJvdHRvbTogMS41cHggc29saWQgIzhCNUEyQjsNCiAgICAgICAgICAgIG9wYWNpdHk6IDAuMjU7DQogICAgICAgIH0NCg0KICAgICAgICAuc2tpbGxzLWxpc3Qgew0KICAgICAgICAgICAgZGlzcGxheTogZmxleDsNCiAgICAgICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICAgICAgICAgICAgZmxleC13cmFwOiB3cmFwOw0KICAgICAgICAgICAgZ2FwOiAxMnB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLnNraWxsLWl0ZW0gew0KICAgICAgICAgICAgYmFja2dyb3VuZDogIzhCNUEyQjsNCiAgICAgICAgICAgIGNvbG9yOiAjRkZGNUU2Ow0KICAgICAgICAgICAgcGFkZGluZzogOHB4IDE4cHg7DQogICAgICAgICAgICBib3JkZXItcmFkaXVzOiAzMHB4Ow0KICAgICAgICAgICAgZm9udC1zaXplOiAxM3B4Ow0KICAgICAgICAgICAgYm9yZGVyOiAxLjVweCBzb2xpZCAjREVCODg3Ow0KICAgICAgICAgICAgYm94LXNoYWRvdzogMCAzcHggMCAjNUQzQTFBLCAwIDZweCAxMHB4IHJnYmEoNzAsIDM1LCAxMCwgMC4xNSk7DQogICAgICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycyBlYXNlOw0KICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnR2FyYW1vbmQnLCAnVGltZXMgTmV3IFJvbWFuJywgc2VyaWY7DQogICAgICAgICAgICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlOw0KICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IDAuOHB4Ow0KICAgICAgICB9DQoNCiAgICAgICAgLnNraWxsLWl0ZW06bnRoLWNoaWxkKDIpIHsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6ICM5QjZFM0E7DQogICAgICAgIH0NCg0KICAgICAgICAuc2tpbGwtaXRlbTpob3ZlciB7DQogICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTJweCk7DQogICAgICAgICAgICBib3gtc2hhZG93OiAwIDJweCAwICM1RDNBMUEsIDAgOHB4IDEycHggcmdiYSg3MCwgMzUsIDEwLCAwLjIpOw0KICAgICAgICAgICAgYmFja2dyb3VuZDogI0E4N0I0NTsNCiAgICAgICAgICAgIGJvcmRlci1jb2xvcjogI0Y0QTQ2MDsNCiAgICAgICAgfQ0KDQogICAgICAgIC53b29kLWRlY29yYXRpb24gew0KICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlOw0KICAgICAgICAgICAgd2lkdGg6IDEwMCU7DQogICAgICAgICAgICBoZWlnaHQ6IDEwMCU7DQogICAgICAgICAgICBwb2ludGVyLWV2ZW50czogbm9uZTsNCiAgICAgICAgfQ0KDQogICAgICAgIC53b29kLWRlY29yYXRpb24gc3BhbiB7DQogICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7DQogICAgICAgICAgICBiYWNrZ3JvdW5kOiAjQzE5QTZCOw0KICAgICAgICAgICAgb3BhY2l0eTogMC4wODsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDhweDsNCiAgICAgICAgfQ0KDQogICAgICAgIC53b29kLWRlY29yYXRpb24gc3BhbjpudGgtY2hpbGQoMSkgew0KICAgICAgICAgICAgdG9wOiAxNXB4Ow0KICAgICAgICAgICAgbGVmdDogMTVweDsNCiAgICAgICAgICAgIHdpZHRoOiA0MHB4Ow0KICAgICAgICAgICAgaGVpZ2h0OiA4cHg7DQogICAgICAgICAgICB0cmFuc2Zvcm06IHJvdGF0ZSgyNWRlZyk7DQogICAgICAgIH0NCg0KICAgICAgICAud29vZC1kZWNvcmF0aW9uIHNwYW46bnRoLWNoaWxkKDIpIHsNCiAgICAgICAgICAgIGJvdHRvbTogMjBweDsNCiAgICAgICAgICAgIHJpZ2h0OiAyMHB4Ow0KICAgICAgICAgICAgd2lkdGg6IDYwcHg7DQogICAgICAgICAgICBoZWlnaHQ6IDEwcHg7DQogICAgICAgICAgICB0cmFuc2Zvcm06IHJvdGF0ZSgtMTVkZWcpOw0KICAgICAgICB9DQoNCiAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDYwMHB4KSB7DQogICAgICAgICAgICAucHJvZmlsZS1jb250ZW50IHsNCiAgICAgICAgICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOw0KICAgICAgICAgICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgICAgICAgICAgICAgICBnYXA6IDE1cHg7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIC5wcm9maWxlLWluZm8gew0KICAgICAgICAgICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgLm5hbWUgew0KICAgICAgICAgICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgLm5pbSB7DQogICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAuc3R1ZHktaW5mbyB7DQogICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAuZG9zZW4taW5mbyB7DQogICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAuaGVhZGVyIHsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOiAyNXB4IDIwcHg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICANCiAgICAgICAgICAgIC5waG90by1jb250YWluZXIgew0KICAgICAgICAgICAgICAgIHdpZHRoOiAxMTBweDsNCiAgICAgICAgICAgICAgICBoZWlnaHQ6IDExMHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAubmFtZSB7DQogICAgICAgICAgICAgICAgZm9udC1zaXplOiAyNHB4Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAuc2tpbGxzLXNlY3Rpb24gew0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDE4cHggMTVweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIA0KICAgICAgICAgICAgLnNraWxsLWl0ZW0gew0KICAgICAgICAgICAgICAgIHBhZGRpbmc6IDZweCAxNHB4Ow0KICAgICAgICAgICAgICAgIGZvbnQtc2l6ZTogMTJweDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIDwvc3R5bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCiAgICA8ZGl2IGNsYXNzPSJjb250YWluZXIiPg0KICAgICAgICA8ZGl2IGNsYXNzPSJ3b29kLWRlY29yYXRpb24iPg0KICAgICAgICAgICAgPHNwYW4+PC9zcGFuPg0KICAgICAgICAgICAgPHNwYW4+PC9zcGFuPg0KICAgICAgICA8L2Rpdj4NCiAgICAgICAgDQogICAgICAgIDxoZWFkZXIgY2xhc3M9ImhlYWRlciI+DQogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwcm9maWxlLWNvbnRlbnQiPg0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9InBob3RvLWNvbnRhaW5lciI+DQogICAgICAgICAgICAgICAgICAgIDxpbWcgc3JjPSJDOi9Vc2Vycy9XSU5ET1dTIDExL09uZURyaXZlL0Rlc2t0b3AvUGVtcm9ncmFtYW4gU2FpbnMgRGF0YSBTZW1lc3RlciAyL3Byb2ZpbGUucG5nIiANCiAgICAgICAgICAgICAgICAgICAgICAgICBhbHQ9IkZvdG8gUHJvZmlsIEFuaW5keWEgS3Jpc3RpYW5pbmdwdXRyaSIgDQogICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9InByb2ZpbGUtcGhvdG8iPg0KICAgICAgICAgICAgICAgIDwvZGl2Pg0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9InByb2ZpbGUtaW5mbyI+DQogICAgICAgICAgICAgICAgICAgIDxoMSBjbGFzcz0ibmFtZSI+QW5pbmR5YSBLcmlzdGlhbmluZ3B1dHJpPC9oMT4NCiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibmltIj5OSU06IDUyMjUwMDI1PC9kaXY+DQogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9InN0dWR5LWluZm8iPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHA+U3R1ZGVudCBNYWpvciBEYXRhIFNjaWVuY2U8L3A+DQogICAgICAgICAgICAgICAgICAgICAgICA8cD5CYW5kdW5nIEluc3RpdHV0ZSBvZiBTY2llbmNlIGFuZCBUZWNobm9sb2d5PC9wPg0KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4NCiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZG9zZW4taW5mbyI+DQogICAgICAgICAgICAgICAgICAgICAgICBMZWN0dXJlOiBCYWt0aSBTaXJlZ2FyLCBNLlNjLiwgQ0RTDQogICAgICAgICAgICAgICAgICAgIDwvZGl2Pg0KICAgICAgICAgICAgICAgIDwvZGl2Pg0KICAgICAgICAgICAgPC9kaXY+DQogICAgICAgIDwvaGVhZGVyPg0KDQogICAgICAgIDxkaXYgY2xhc3M9InNraWxscy1zZWN0aW9uIj4NCiAgICAgICAgICAgIDxkaXYgY2xhc3M9InNraWxscy1saXN0Ij4NCiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0ic2tpbGwtaXRlbSI+UiBQcm9ncmFtbWluZzwvc3Bhbj4NCiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0ic2tpbGwtaXRlbSI+UHJvZ3JhbW1pbmcgRGF0YSBTY2llbmNlPC9zcGFuPg0KICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJza2lsbC1pdGVtIj5TeW50YXggYW5kIENvbnRyYWZsb3c8L3NwYW4+DQogICAgICAgICAgICA8L2Rpdj4NCiAgICAgICAgPC9kaXY+DQogICAgPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KDQpgYGB7PWh0bWx9DQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sIGxhbmc9ImlkIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4NCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogICAgPHRpdGxlPktvbnNlcCBQcm9iYWJpbGl0YXM8L3RpdGxlPg0KICAgIDxzdHlsZT4NCiAgICAgICAgLnByb2JhYmlsaXRhcy1ib3ggew0KICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzhCNDUxMzsgIA0KICAgICAgICAgICAgY29sb3I6IHdoaXRlOyAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgcGFkZGluZzogMzBweDsNCiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDhweDsNCiAgICAgICAgICAgIG1heC13aWR0aDogODAwcHg7DQogICAgICAgICAgICBtYXJnaW46IDIwcHggYXV0bzsNCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnU2Vnb2UgVUknLCBUYWhvbWEsIEdlbmV2YSwgVmVyZGFuYSwgc2Fucy1zZXJpZjsNCiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjg7ICAgICAgICAgICAgIC8qIEphcmFrIGFudGFyIGJhcmlzIGxlYmloIGxlZ2EgKi8NCiAgICAgICAgICAgIHRleHQtYWxpZ246IGp1c3RpZnk7ICAgICAgICAgICANCiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgNHB4IDhweCByZ2JhKDAsIDAsIDAsIDAuMik7DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIC5wcm9iYWJpbGl0YXMtYm94IHAgew0KICAgICAgICAgICAgbWFyZ2luOiAwIDAgMTVweCAwOyAgICAgICAgICAgIC8qIEphcmFrIGFudGFyIHBhcmFncmFmICovDQogICAgICAgICAgICBmb250LXNpemU6IDE2cHg7DQogICAgICAgIH0NCg0KICAgICAgICAucHJvYmFiaWxpdGFzLWJveCBzdHJvbmcgew0KICAgICAgICAgICAgY29sb3I6ICNGRkQ3MDA7ICAgICAgICAgICAgICAgIC8qIFdhcm5hIGVtYXMgdW50dWsganVkdWwgKi8NCiAgICAgICAgfQ0KICAgIDwvc3R5bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCiAgICA8ZGl2IGNsYXNzPSJwcm9iYWJpbGl0YXMtYm94Ij4NCiAgICAgICAgPHA+PHN0cm9uZz5BcHBsaWNhdGlvbiBvZiBMb29waW5nIFN0cnVjdHVyZXMgaW4gRW1wbG95ZWUgRGF0YXNldCBBbmFseXNpcyBVc2luZyBSPC9zdHJvbmc+PC9wPg0KICAgICAgICA8cD5UaGlzIGRhdGFzZXQgY29udGFpbnMgZGF0YSBvZiBmaXZlIGVtcGxveWVlcyB3aXRoIHNldmVyYWwgdmFyaWFibGVzOiBJRCBhcyBlbXBsb3llZSBpZGVudGlmaWNhdGlvbiwgTmFtZSwgQWdlLCBTYWxhcnkgYXMgdGhlIGFtb3VudCBvZiBzYWxhcnksIFBvc2l0aW9uIGFzIHRoZSBqb2IgdGl0bGUgd2l0aGluIHRoZSBjb21wYW55LCBhbmQgUGVyZm9ybWFuY2UgYXMgYSBwZXJmb3JtYW5jZSByYXRpbmcgc3VjaCBhcyBHb29kLCBWZXJ5IEdvb2QsIGFuZCBBdmVyYWdlLjwvcD4NCiAgICAgICAgPHA+VGhpcyBkYXRhIHNlcnZlcyBhcyBhIHNpbXBsZSBleGFtcGxlIHRvIHByYWN0aWNlIHRoZSB1c2Ugb2YgbG9vcHMgaW4gUiBwcm9ncmFtbWluZywgc3BlY2lmaWNhbGx5IGZvciBsb29wcyBhbmQgd2hpbGUgbG9vcHMsIGluIGNvbmR1Y3RpbmcgZGF0YXNldCBhbmFseXNpcy4gVGhyb3VnaCB0aGlzIGV4ZXJjaXNlLCB3ZSBjYW4gdW5kZXJzdGFuZCBob3cgdG8gdHJhdmVyc2UgZWFjaCByb3cgb2YgZGF0YSwgcGVyZm9ybSBzcGVjaWZpYyBjb25kaXRpb24gY2hlY2tzLCBhbmQgY29udHJvbCB0aGUgZmxvdyBvZiBsb29wcyB1c2luZyB0aGUgYnJlYWsgY29tbWFuZCB0byBzdG9wIHRoZSBwcm9jZXNzIGFuZCBjb250aW51ZSB0byBza2lwIGRhdGEgdGhhdCBkb2VzIG5vdCBtZWV0IGNlcnRhaW4gY29uZGl0aW9ucy48L3A+DQogICAgPC9kaXY+DQo8L2JvZHk+DQo8L2h0bWw+DQpgYGANCg0KDQpgYGB7cn0NCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KGtuaXRyKSkNCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KGthYmxlRXh0cmEpKQ0KDQojIEVtcGxveWVlIGRhdGFzZXQNCmRhdGFfa2FyeWF3YW4gPC0gZGF0YS5mcmFtZSgNCiAgSUQgPSBjKDEsMiwzLDQsNSksDQogIE5hbWUgPSBjKCJCYWdhcyIsIkpvYW4iLCJBbHlhIiwiRHdpIiwiTmFiaWwiKSwNCiAgQWdlID0gYygyNSwzMCwyNywzNSw0MCksDQogIFNhbGFyeSA9IGMoNTAwMCw3MDAwLDY1MDAsMTAwMDAsMTIwMDApLA0KICBQb3NpdGlvbiA9IGMoIlN0YWZmIiwiU3VwZXJ2aXNvciIsIlN0YWZmIiwiTWFuYWdlciIsIkRpcmVjdG9yIiksDQogIFBlcmZvcm1hbmNlID0gYygiR29vZCIsIlZlcnkgR29vZCIsIkF2ZXJhZ2UiLCJHb29kIiwiVmVyeSBHb29kIikNCikNCg0KIyB0YWJsZQ0Ka2FibGUoZGF0YV9rYXJ5YXdhbiwgY2FwdGlvbiA9ICJFbXBsb3llZSBEYXRhc2V0IikgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJib3JkZXJlZCIpKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICIjNkY0RTM3IiwgY29sb3IgPSAid2hpdGUiKQ0KYGBgDQoNCiMgQ29uZGl0aW9uYWwgU3RhdGVtZW50IA0KDQo6Ojoge3N0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmMGY1ZmY7IGJvcmRlci1sZWZ0OjZweCBzb2xpZCAjMDAwMDgwOyBwYWRkaW5nOjEycHg7IGJvcmRlci1yYWRpdXM6OHB4OyBtYXJnaW46MjBweCAwOyJ9DQo8cCBzdHlsZT0idGV4dC1hbGlnbjoganVzdGlmeTsgdGV4dC1qdXN0aWZ5OiBpbnRlci13b3JkOyI+DQpJbiBSIHByb2dyYW1taW5nLCBhIGNvbmRpdGlvbmFsIHN0YXRlbWVudCBpcyBhIGNvbnRyb2wgc3RydWN0dXJlIHVzZWQgdG8gZXhlY3V0ZSBzcGVjaWZpYyBjb21tYW5kcyBiYXNlZCBvbiBhIGxvZ2ljYWwgY29uZGl0aW9uIHRoYXQgZXZhbHVhdGVzIHRvIFRSVUUgb3IgRkFMU0UuIEluIFIsIGNvbmRpdGlvbmFsIHN0YXRlbWVudHMgdHlwaWNhbGx5IHVzZSB0aGUgY29tbWFuZHMgaWYsIGVsc2UgaWYsIGFuZCBlbHNlIHRvIGV2YWx1YXRlIGEgY29uZGl0aW9uIGFuZCBkZXRlcm1pbmUgdGhlIGFjdGlvbiB0byBiZSBleGVjdXRlZCBieSB0aGUgcHJvZ3JhbS4gVGhpcyBzdHJ1Y3R1cmUgaXMgb2Z0ZW4gdXNlZCBpbiBkYXRhIGFuYWx5c2lzIHRvIGNoZWNrIHZhcmlhYmxlIHZhbHVlcywgZ3JvdXAgZGF0YSBiYXNlZCBvbiBjZXJ0YWluIGNyaXRlcmlhLCBvciBkZXRlcm1pbmUgdGhlIG5leHQgc3RlcHMgaW4gdGhlIGRhdGEgcHJvY2Vzc2luZyB3b3JrZmxvdy4NCjwvcD4NCjo6Og0KDQo6Ojp7c3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0QxRkZGQTsgYm9yZGVyLWxlZnQ6NnB4IHNvbGlkICMwMDAwODA7IHBhZGRpbmc6MTJweDsgYm9yZGVyLXJhZGl1czo4cHg7IG1hcmdpbjoyMHB4IDA7In0NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5OyB0ZXh0LWp1c3RpZnk6IGludGVyLXdvcmQ7Ij4NCioqUXVlc3Rpb246KioNCkEgY29tcGFueSB3YW50cyB0byBjYWxjdWxhdGUgZW1wbG95ZWUgYm9udXNlcyBiYXNlZCBvbiB0aGVpciBwZXJmb3JtYW5jZS4gRW1wbG95ZWVzIHdpdGggKipWZXJ5IEdvb2QqKiBwZXJmb3JtYW5jZSByZWNlaXZlICoqMjAlIG9mIHRoZWlyIHNhbGFyeSBhcyBhIGJvbnVzKiosIGVtcGxveWVlcyB3aXRoICoqR29vZCoqIHBlcmZvcm1hbmNlIHJlY2VpdmUgKioxMCUgb2YgdGhlaXIgc2FsYXJ5KiosIGFuZCBlbXBsb3llZXMgd2l0aCAqKkF2ZXJhZ2UqKiBwZXJmb3JtYW5jZSByZWNlaXZlICoqNSUgb2YgdGhlaXIgc2FsYXJ5KiouIFVzaW5nIHRoZXNlIHJ1bGVzLCB3cml0ZSBhIHByb2dyYW0gdG8gZGV0ZXJtaW5lIHRoZSBib251cyBsZXZlbCBmb3IgZWFjaCBlbXBsb3llZSBhbmQgY2FsY3VsYXRlIHRoZSBib251cyBhbW91bnQgYmFzZWQgb24gdGhlaXIgc2FsYXJ5Lg0KPC9wPg0KOjo6DQoNCmBgYHtyfQ0KIyBFbXBsb3llZSBkYXRhc2V0DQpkYXRhX2thcnlhd2FuIDwtIGRhdGEuZnJhbWUoDQogIElEID0gYygxLDIsMyw0LDUpLA0KICBOYW1lID0gYygiQmFnYXMiLCJKb2FuIiwiQWx5YSIsIkR3aSIsIk5hYmlsIiksDQogIEFnZSA9IGMoMjUsMzAsMjcsMzUsNDApLA0KICBTYWxhcnkgPSBjKDUwMDAsNzAwMCw2NTAwLDEwMDAwLDEyMDAwKSwNCiAgUG9zaXRpb24gPSBjKCJTdGFmZiIsIlN1cGVydmlzb3IiLCJTdGFmZiIsIk1hbmFnZXIiLCJEaXJlY3RvciIpLA0KICBQZXJmb3JtYW5jZSA9IGMoIkdvb2QiLCJWZXJ5IEdvb2QiLCJBdmVyYWdlIiwiR29vZCIsIlZlcnkgR29vZCIpDQopDQoNCiMgQ2FsY3VsYXRlIHRoZSBib251cyBhbmQgZGlzcGxheSB0aGUgb3V0cHV0DQpmb3IoaSBpbiAxOm5yb3coZGF0YV9rYXJ5YXdhbikpew0KICANCiAgaWYoZGF0YV9rYXJ5YXdhbiRQZXJmb3JtYW5jZVtpXSA9PSAiVmVyeSBHb29kIil7DQogICAgYm9udXMgPC0gMC4yMCAqIGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldDQogICAgDQogIH0gZWxzZSBpZihkYXRhX2thcnlhd2FuJFBlcmZvcm1hbmNlW2ldID09ICJHb29kIil7DQogICAgYm9udXMgPC0gMC4xMCAqIGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldDQogICAgDQogIH0gZWxzZSBpZihkYXRhX2thcnlhd2FuJFBlcmZvcm1hbmNlW2ldID09ICJBdmVyYWdlIil7DQogICAgYm9udXMgPC0gMC4wNSAqIGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldDQogICAgDQogIH0gZWxzZXsNCiAgICBib251cyA8LSAwDQogIH0NCiAgDQogIGNhdChwYXN0ZTAoIk5hbWU6ICIsIGRhdGFfa2FyeWF3YW4kTmFtZVtpXSwgIiwgQm9udXM6ICIsIGJvbnVzLCAiXG4iKSkNCn0NCmBgYA0KDQoNCmBgYHtyfQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa25pdHIpKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa2FibGVFeHRyYSkpDQoNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQoNCiMgRW1wbG95ZWUgZGF0YXNldA0KZGF0YV9rYXJ5YXdhbiA8LSBkYXRhLmZyYW1lKA0KICBJRCA9IGMoMSwyLDMsNCw1KSwNCiAgTmFtZSA9IGMoIkJhZ2FzIiwiSm9hbiIsIkFseWEiLCJEd2kiLCJOYWJpbCIpLA0KICBBZ2UgPSBjKDI1LDMwLDI3LDM1LDQwKSwNCiAgU2FsYXJ5ID0gYyg1MDAwLDcwMDAsNjUwMCwxMDAwMCwxMjAwMCksDQogIFBvc2l0aW9uID0gYygiU3RhZmYiLCJTdXBlcnZpc29yIiwiU3RhZmYiLCJNYW5hZ2VyIiwiRGlyZWN0b3IiKSwNCiAgUGVyZm9ybWFuY2UgPSBjKCJHb29kIiwiVmVyeSBHb29kIiwiQXZlcmFnZSIsIkdvb2QiLCJWZXJ5IEdvb2QiKQ0KKQ0KDQojIENyZWF0ZSBib251cyBjb2x1bW4NCmJvbnVzIDwtIGMoKQ0KDQpmb3IoaSBpbiAxOm5yb3coZGF0YV9rYXJ5YXdhbikpew0KICANCiAgaWYoZGF0YV9rYXJ5YXdhbiRQZXJmb3JtYW5jZVtpXSA9PSAiVmVyeSBHb29kIil7DQogICAgYm9udXNbaV0gPC0gMC4yMCAqIGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldDQogICAgDQogIH0gZWxzZSBpZihkYXRhX2thcnlhd2FuJFBlcmZvcm1hbmNlW2ldID09ICJHb29kIil7DQogICAgYm9udXNbaV0gPC0gMC4xMCAqIGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldDQogICAgDQogIH0gZWxzZSBpZihkYXRhX2thcnlhd2FuJFBlcmZvcm1hbmNlW2ldID09ICJBdmVyYWdlIil7DQogICAgYm9udXNbaV0gPC0gMC4wNSAqIGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldDQogICAgDQogIH0gZWxzZXsNCiAgICBib251c1tpXSA8LSAwDQogIH0NCn0NCg0KIyBSZXN1bHQgZGF0YSANCmhhc2lsX2JvbnVzIDwtIGRhdGEuZnJhbWUoDQogIE5hbWUgPSBkYXRhX2thcnlhd2FuJE5hbWUsDQogIEJvbnVzID0gYm9udXMNCikNCg0Ka2FibGUoaGFzaWxfYm9udXMsIGNhcHRpb24gPSAiRW1wbG95ZWUgQm9udXMgUmVzdWx0IikgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJib3JkZXJlZCIpKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICIjNkY0RTM3IiwgY29sb3IgPSAid2hpdGUiKSAlPiUNCiAgY29sdW1uX3NwZWMoMToyLCBib3JkZXJfbGVmdCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpDQpgYGANCg0KDQoNCiMgTG9vcHMgKEZvciAmIFdoaWxlKQ0KDQojIyBmb3IgbG9vcCANCg0KOjo6IHtzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZjBmNWZmOyBib3JkZXItbGVmdDo2cHggc29saWQgIzAwMDA4MDsgcGFkZGluZzoxMnB4OyBib3JkZXItcmFkaXVzOjhweDsgbWFyZ2luOjIwcHggMDsifQ0KPHAgc3R5bGU9InRleHQtYWxpZ246IGp1c3RpZnk7IHRleHQtanVzdGlmeTogaW50ZXItd29yZDsiPg0KQSAqKmZvciBsb29wKiogaXMgdXNlZCB3aGVuIHRoZSBudW1iZXIgb2YgaXRlcmF0aW9ucyBpcyBhbHJlYWR5IGtub3duIGluIGFkdmFuY2UuIFRoZSBsb29wIGJlZ2lucyBieSBpbml0aWFsaXppbmcgYSBjb3VudGVyLCB0aGVuIGNoZWNraW5nIGEgY29uZGl0aW9uIGJlZm9yZSBleGVjdXRpbmcgdGhlIGNvZGUgaW5zaWRlIHRoZSBsb29wLiBBZnRlciBlYWNoIGV4ZWN1dGlvbiwgdGhlIGNvdW50ZXIgaW5jcmVhc2VzLCBhbmQgdGhlIHByb2Nlc3MgcmVwZWF0cyB1bnRpbCB0aGUgY29uZGl0aW9uIGlzIG5vIGxvbmdlciBzYXRpc2ZpZWQuDQo8L3A+DQo6OjoNCg0KDQo6Ojp7c3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0QxRkZGQTsgYm9yZGVyLWxlZnQ6NnB4IHNvbGlkICMwMDAwODA7IHBhZGRpbmc6MTJweDsgYm9yZGVyLXJhZGl1czo4cHg7IG1hcmdpbjoyMHB4IDA7In0NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5OyB0ZXh0LWp1c3RpZnk6IGludGVyLXdvcmQ7Ij4NCioqSW5zdHJ1Y3Rpb246KioNCg0KVXNlIGEgZm9yIGxvb3AgdG8gZGlzcGxheSB0aGUgbmFtZXMgb2YgZW1wbG95ZWVzIHdob3NlIHNhbGFyeSBpcyBncmVhdGVyIHRoYW4gNjAwMC4NCjwvcD4NCjo6Og0KDQoNCmBgYHtyfQ0KIyBFbXBsb3llZSBkYXRhc2V0DQpkYXRhX2thcnlhd2FuIDwtIGRhdGEuZnJhbWUoDQogIElEID0gYygxLDIsMyw0LDUpLA0KICBOYW1lID0gYygiQmFnYXMiLCJKb2FuIiwiQWx5YSIsIkR3aSIsIk5hYmlsIiksDQogIEFnZSA9IGMoMjUsMzAsMjcsMzUsNDApLA0KICBTYWxhcnkgPSBjKDUwMDAsNzAwMCw2NTAwLDEwMDAwLDEyMDAwKQ0KKQ0KDQojIEZvciBsb29wIHRvIGRpc3BsYXkgZW1wbG95ZWVzIHdpdGggc2FsYXJ5IGdyZWF0ZXIgdGhhbiA2MDAwDQpmb3IoaSBpbiAxOm5yb3coZGF0YV9rYXJ5YXdhbikpIHsNCiAgaWYoZGF0YV9rYXJ5YXdhbiRTYWxhcnlbaV0gPiA2MDAwKSB7DQogICAgY2F0KCJOYW1lOiIsIGRhdGFfa2FyeWF3YW4kTmFtZVtpXSwgDQogICAgICAgICIsIFNhbGFyeToiLCBkYXRhX2thcnlhd2FuJFNhbGFyeVtpXSwgIlxuIikNCiAgfQ0KfQ0KYGBgDQoNCmBgYHtyfQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa25pdHIpKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa2FibGVFeHRyYSkpDQoNCiMgRW1wbG95ZWUgZGF0YXNldA0KZGF0YV9rYXJ5YXdhbiA8LSBkYXRhLmZyYW1lKA0KICBJRCA9IGMoMSwyLDMsNCw1KSwNCiAgTmFtZSA9IGMoIkJhZ2FzIiwiSm9hbiIsIkFseWEiLCJEd2kiLCJOYWJpbCIpLA0KICBBZ2UgPSBjKDI1LDMwLDI3LDM1LDQwKSwNCiAgU2FsYXJ5ID0gYyg1MDAwLDcwMDAsNjUwMCwxMDAwMCwxMjAwMCkNCikNCg0KIyBTdG9yZSB0aGUgcmVzdWx0cw0KbmFtYSA8LSBjKCkNCmdhamkgPC0gYygpDQoNCiMgRm9yIGxvb3AgdG8gZmluZCBzYWxhcmllcyBncmVhdGVyIHRoYW4gNjAwMA0KZm9yKGkgaW4gMTpucm93KGRhdGFfa2FyeWF3YW4pKSB7DQogIGlmKGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldID4gNjAwMCkgew0KICAgIG5hbWEgPC0gYyhuYW1hLCBkYXRhX2thcnlhd2FuJE5hbWVbaV0pDQogICAgZ2FqaSA8LSBjKGdhamksIGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldKQ0KICB9DQp9DQoNCiMgUmVzdWx0IGRhdGENCmhhc2lsIDwtIGRhdGEuZnJhbWUoDQogIE5hbWUgPSBuYW1hLA0KICBTYWxhcnkgPSBnYWppDQopDQoNCiMgdGFibGUNCmthYmxlKGhhc2lsLCBjYXB0aW9uID0gIkVtcGxveWVlcyB3aXRoIFNhbGFyeSBHcmVhdGVyIFRoYW4gNjAwMCIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwiYm9yZGVyZWQiKSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAiIzZGNEUzNyIsIGNvbG9yID0gIndoaXRlIikNCmBgYA0KDQoNCg0KIyMgV2hpbGUgTG9vcCANCg0KDQo6Ojoge3N0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmMGY1ZmY7IGJvcmRlci1sZWZ0OjZweCBzb2xpZCAjMDAwMDgwOyBwYWRkaW5nOjEycHg7IGJvcmRlci1yYWRpdXM6OHB4OyBtYXJnaW46MjBweCAwOyJ9DQo8cCBzdHlsZT0idGV4dC1hbGlnbjoganVzdGlmeTsgdGV4dC1qdXN0aWZ5OiBpbnRlci13b3JkOyI+DQpBICoqd2hpbGUgbG9vcCoqIGlzIHVzZWQgd2hlbiBhIHByb2Nlc3MgbmVlZHMgdG8gY29udGludWUgcnVubmluZyBhcyBsb25nIGFzIGEgY2VydGFpbiBjb25kaXRpb24gcmVtYWlucyB0cnVlLiBUaGUgbG9vcCByZXBlYXRlZGx5IGV4ZWN1dGVzIHRoZSBjb2RlIGFuZCBjaGVja3MgdGhlIGNvbmRpdGlvbiBhZnRlciBlYWNoIGl0ZXJhdGlvbi4gVGhpcyBwcm9jZXNzIGNvbnRpbnVlcyB1bnRpbCB0aGUgY29uZGl0aW9uIGV2ZW50dWFsbHkgYmVjb21lcyBmYWxzZSwgYXQgd2hpY2ggcG9pbnQgdGhlIGxvb3Agc3RvcHMuDQo8L3A+DQo6OjoNCg0KOjo6e3N0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNEMUZGRkE7IGJvcmRlci1sZWZ0OjZweCBzb2xpZCAjMDAwMDgwOyBwYWRkaW5nOjEycHg7IGJvcmRlci1yYWRpdXM6OHB4OyBtYXJnaW46MjBweCAwOyJ9DQo8cCBzdHlsZT0idGV4dC1hbGlnbjoganVzdGlmeTsgdGV4dC1qdXN0aWZ5OiBpbnRlci13b3JkOyI+DQoqKkluc3RydWN0aW9uOioqDQoNClVzZSBhIHdoaWxlIGxvb3AgdG8gZGlzcGxheSBlbXBsb3llZXMgdW50aWwgYSDigJxNYW5hZ2Vy4oCdIGlzIGZvdW5kLg0KPC9wPg0KOjo6DQoNCg0KYGBge3J9DQojIEVtcGxveWVlIGRhdGFzZXQNCmRhdGFfa2FyeWF3YW4gPC0gZGF0YS5mcmFtZSgNCiAgSUQgPSBjKDEsMiwzLDQsNSksDQogIE5hbWUgPSBjKCJCYWdhcyIsIkpvYW4iLCJBbHlhIiwiRHdpIiwiTmFiaWwiKSwNCiAgQWdlID0gYygyNSwzMCwyNywzNSw0MCksDQogIFNhbGFyeSA9IGMoNTAwMCw3MDAwLDY1MDAsMTAwMDAsMTIwMDApLA0KICBQb3NpdGlvbiA9IGMoIlN0YWZmIiwiU3VwZXJ2aXNvciIsIlN0YWZmIiwiTWFuYWdlciIsIkRpcmVjdG9yIiksDQogIFBlcmZvcm1hbmNlID0gYygiR29vZCIsIlZlcnkgR29vZCIsIkF2ZXJhZ2UiLCJHb29kIiwiVmVyeSBHb29kIikNCikNCg0KIyBXaGlsZSBsb29wIHRvIGRpc3BsYXkgZW1wbG95ZWVzIHVudGlsIGEgTWFuYWdlciBpcyBmb3VuZA0KaSA8LSAxDQoNCndoaWxlKGkgPD0gbnJvdyhkYXRhX2thcnlhd2FuKSkgew0KICANCiAgaWYoZGF0YV9rYXJ5YXdhbiRQb3NpdGlvbltpXSA9PSAiTWFuYWdlciIpIHsNCiAgICBjYXQoIk5hbWU6IiwgZGF0YV9rYXJ5YXdhbiROYW1lW2ldLA0KICAgICAgICAiLCBQb3NpdGlvbjoiLCBkYXRhX2thcnlhd2FuJFBvc2l0aW9uW2ldLA0KICAgICAgICAiKFN0b3AgaGVyZSlcbiIpDQogICAgYnJlYWsNCiAgfQ0KICANCiAgY2F0KCJOYW1lOiIsIGRhdGFfa2FyeWF3YW4kTmFtZVtpXSwNCiAgICAgICIsIFBvc2l0aW9uOiIsIGRhdGFfa2FyeWF3YW4kUG9zaXRpb25baV0sICJcbiIpDQogIA0KICBpIDwtIGkgKyAxDQp9DQpgYGANCg0KDQpgYGB7cn0NCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KGtuaXRyKSkNCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KGthYmxlRXh0cmEpKQ0KDQojIEVtcGxveWVlIGRhdGFzZXQNCmRhdGFfa2FyeWF3YW4gPC0gZGF0YS5mcmFtZSgNCiAgSUQgPSBjKDEsMiwzLDQsNSksDQogIE5hbWUgPSBjKCJCYWdhcyIsIkpvYW4iLCJBbHlhIiwiRHdpIiwiTmFiaWwiKSwNCiAgQWdlID0gYygyNSwzMCwyNywzNSw0MCksDQogIFNhbGFyeSA9IGMoNTAwMCw3MDAwLDY1MDAsMTAwMDAsMTIwMDApLA0KICBQb3NpdGlvbiA9IGMoIlN0YWZmIiwiU3VwZXJ2aXNvciIsIlN0YWZmIiwiTWFuYWdlciIsIkRpcmVjdG9yIiksDQogIFBlcmZvcm1hbmNlID0gYygiR29vZCIsIlZlcnkgR29vZCIsIkF2ZXJhZ2UiLCJHb29kIiwiVmVyeSBHb29kIikNCikNCg0KIyBTdG9yZSB0aGUgcmVzdWx0cw0KbmFtYSA8LSBjKCkNCnBvc2lzaSA8LSBjKCkNCg0KaSA8LSAxDQoNCiMgV2hpbGUgbG9vcA0Kd2hpbGUoaSA8PSBucm93KGRhdGFfa2FyeWF3YW4pKXsNCiAgDQogIG5hbWEgPC0gYyhuYW1hLCBkYXRhX2thcnlhd2FuJE5hbWVbaV0pDQogIHBvc2lzaSA8LSBjKHBvc2lzaSwgZGF0YV9rYXJ5YXdhbiRQb3NpdGlvbltpXSkNCiAgDQogIGlmKGRhdGFfa2FyeWF3YW4kUG9zaXRpb25baV0gPT0gIk1hbmFnZXIiKXsNCiAgICBwb3Npc2lbbGVuZ3RoKHBvc2lzaSldIDwtIHBhc3RlKHBvc2lzaVtsZW5ndGgocG9zaXNpKV0sICIoU3RvcCBoZXJlKSIpDQogICAgYnJlYWsNCiAgfQ0KICANCiAgaSA8LSBpICsgMQ0KfQ0KDQojIFJlc3VsdCANCmhhc2lsIDwtIGRhdGEuZnJhbWUoDQogIE5hbWUgPSBuYW1hLA0KICBQb3NpdGlvbiA9IHBvc2lzaQ0KKQ0KDQojIHRhYmxlDQprYWJsZShoYXNpbCwgY2FwdGlvbiA9ICIgVW50aWwgTWFuYWdlciBGb3VuZCIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwiYm9yZGVyZWQiKSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAiIzZGNEUzNyIsIGNvbG9yID0gIndoaXRlIikNCmBgYA0KDQoNCiMjIEJyZWFrIA0KDQoNCjo6OiB7c3R5bGU9ImJhY2tncm91bmQtY29sb3I6I2YwZjVmZjsgYm9yZGVyLWxlZnQ6NnB4IHNvbGlkICMwMDAwODA7IHBhZGRpbmc6MTJweDsgYm9yZGVyLXJhZGl1czo4cHg7IG1hcmdpbjoyMHB4IDA7In0NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5OyB0ZXh0LWp1c3RpZnk6IGludGVyLXdvcmQ7Ij4NCkEgKipicmVhayBzdGF0ZW1lbnQqKiBpcyB1c2VkIHRvIHN0b3AgYSBsb29wIGltbWVkaWF0ZWx5IGJlZm9yZSBpdCBmaW5pc2hlcyBhbGwgb2YgaXRzIGl0ZXJhdGlvbnMuIFdoZW4gdGhlIGJyZWFrIGNvbmRpdGlvbiBpcyBtZXQsIHRoZSBwcm9ncmFtIGV4aXRzIHRoZSBsb29wIHJpZ2h0IGF3YXkuIFRoaXMgYWxsb3dzIHRoZSBsb29wIHRvIHRlcm1pbmF0ZSBlYXJseSB3aXRob3V0IGNvbnRpbnVpbmcgdGhlIHJlbWFpbmluZyByZXBldGl0aW9ucy4NCjwvcD4NCjo6Og0KDQo6Ojp7c3R5bGU9ImJhY2tncm91bmQtY29sb3I6I0QxRkZGQTsgYm9yZGVyLWxlZnQ6NnB4IHNvbGlkICMwMDAwODA7IHBhZGRpbmc6MTJweDsgYm9yZGVyLXJhZGl1czo4cHg7IG1hcmdpbjoyMHB4IDA7In0NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5OyB0ZXh0LWp1c3RpZnk6IGludGVyLXdvcmQ7Ij4NCioqSW5zdHJ1Y3Rpb246KioNCg0KVXNlIGJyZWFrIHRvIHN0b3AgdGhlIGxvb3Agd2hlbiBhbiBlbXBsb3llZSB3aXRoIGEgc2FsYXJ5IGFib3ZlIDEwLDAwMCBpcyBmb3VuZC4NCjwvcD4NCjo6Og0KDQpgYGB7cn0NCiMgRW1wbG95ZWUgZGF0YXNldA0KZGF0YV9rYXJ5YXdhbiA8LSBkYXRhLmZyYW1lKA0KICBJRCA9IGMoMSwyLDMsNCw1KSwNCiAgTmFtZSA9IGMoIkJhZ2FzIiwiSm9hbiIsIkFseWEiLCJEd2kiLCJOYWJpbCIpLA0KICBBZ2UgPSBjKDI1LDMwLDI3LDM1LDQwKSwNCiAgU2FsYXJ5ID0gYyg1MDAwLDcwMDAsNjUwMCwxMDAwMCwxMjAwMCkNCikNCg0KIyBGb3IgbG9vcCB3aXRoIGJyZWFrIHdoZW4gc2FsYXJ5IGFib3ZlIDEwMDAwDQpmb3IoaSBpbiAxOm5yb3coZGF0YV9rYXJ5YXdhbikpIHsNCiAgDQogIGlmKGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldID4gMTAwMDApIHsNCiAgICBicmVhaw0KICB9DQogIA0KICBjYXQoIk5hbWU6IiwgZGF0YV9rYXJ5YXdhbiROYW1lW2ldLCANCiAgICAgICIsIFNhbGFyeToiLCBkYXRhX2thcnlhd2FuJFNhbGFyeVtpXSwgIlxuIikNCn0NCmBgYA0KDQoNCmBgYHtyfQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa25pdHIpKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa2FibGVFeHRyYSkpDQoNCiMgRW1wbG95ZWUgZGF0YXNldA0KZGF0YV9rYXJ5YXdhbiA8LSBkYXRhLmZyYW1lKA0KICBJRCA9IGMoMSwyLDMsNCw1KSwNCiAgTmFtZSA9IGMoIkJhZ2FzIiwiSm9hbiIsIkFseWEiLCJEd2kiLCJOYWJpbCIpLA0KICBBZ2UgPSBjKDI1LDMwLDI3LDM1LDQwKSwNCiAgU2FsYXJ5ID0gYyg1MDAwLDcwMDAsNjUwMCwxMDAwMCwxMjAwMCkNCikNCg0KIyBTdG9yZSByZXN1bHRzDQpuYW1hIDwtIGMoKQ0KZ2FqaSA8LSBjKCkNCg0KIyBGb3IgbG9vcCB3aXRoIGJyZWFrDQpmb3IoaSBpbiAxOm5yb3coZGF0YV9rYXJ5YXdhbikpIHsNCiAgDQogIGlmKGRhdGFfa2FyeWF3YW4kU2FsYXJ5W2ldID4gMTAwMDApIHsNCiAgICBicmVhaw0KICB9DQogIA0KICBuYW1hIDwtIGMobmFtYSwgZGF0YV9rYXJ5YXdhbiROYW1lW2ldKQ0KICBnYWppIDwtIGMoZ2FqaSwgZGF0YV9rYXJ5YXdhbiRTYWxhcnlbaV0pDQp9DQoNCiMgUmVzdWx0IGRhdGENCmhhc2lsIDwtIGRhdGEuZnJhbWUoDQogIE5hbWUgPSBuYW1hLA0KICBTYWxhcnkgPSBnYWppDQopDQoNCiMgdGFibGUNCmthYmxlKGhhc2lsLCBjYXB0aW9uID0gIlVudGlsIFNhbGFyeSBBYm92ZSAxMCwwMDAgRm91bmQiKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsImJvcmRlcmVkIikpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIiM2RjRFMzciLCBjb2xvciA9ICJ3aGl0ZSIpDQpgYGANCg0KDQojIyBDb250aW51ZSANCg0KDQoNCjo6OiB7c3R5bGU9ImJhY2tncm91bmQtY29sb3I6I2YwZjVmZjsgYm9yZGVyLWxlZnQ6NnB4IHNvbGlkICMwMDAwODA7IHBhZGRpbmc6MTJweDsgYm9yZGVyLXJhZGl1czo4cHg7IG1hcmdpbjoyMHB4IDA7In0NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5OyB0ZXh0LWp1c3RpZnk6IGludGVyLXdvcmQ7Ij4NClRoZSAqKmNvbnRpbnVlIHN0YXRlbWVudCoqIHNraXBzIHRoZSBjdXJyZW50IGl0ZXJhdGlvbiB3aXRob3V0IHN0b3BwaW5nIHRoZSBsb29wIGFuZCBpbW1lZGlhdGVseSBtb3ZlcyB0byB0aGUgbmV4dCBpdGVyYXRpb24uIFRoZSBsb29wIHRoZW4gY2hlY2tzIHRoZSBjb25kaXRpb24gYWdhaW4gYmVmb3JlIGV4ZWN1dGluZyB0aGUgbmV4dCBjeWNsZS4gVGhlIGxvb3Agd2lsbCBzdG9wIHdoZW4gdGhlIGNvbmRpdGlvbiBpcyBubyBsb25nZXIgc2F0aXNmaWVkIG9yIHdoZW4gYSBicmVhayBzdGF0ZW1lbnQgaXMgZW5jb3VudGVyZWQuIElmIHRoZSBjb25kaXRpb24gcmVtYWlucyB0cnVlLCB0aGUgbG9vcCBjb250aW51ZXMgdG8gcnVuIHVubGVzcyBpdCBpcyBpbnRlcnJ1cHRlZCBieSBhIGJyZWFrLg0KPC9wPg0KOjo6DQoNCjo6OntzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojRDFGRkZBOyBib3JkZXItbGVmdDo2cHggc29saWQgIzAwMDA4MDsgcGFkZGluZzoxMnB4OyBib3JkZXItcmFkaXVzOjhweDsgbWFyZ2luOjIwcHggMDsifQ0KPHAgc3R5bGU9InRleHQtYWxpZ246IGp1c3RpZnk7IHRleHQtanVzdGlmeTogaW50ZXItd29yZDsiPg0KKipJbnN0cnVjdGlvbjoqKg0KDQpVc2UgY29udGludWUgdG8gc2tpcCBlbXBsb3llZXMgd2l0aCDigJxBdmVyYWdl4oCdIHBlcmZvcm1hbmNlLg0KPC9wPg0KOjo6DQoNCg0KYGBge3J9DQojIEVtcGxveWVlIGRhdGFzZXQNCmRhdGFfa2FyeWF3YW4gPC0gZGF0YS5mcmFtZSgNCiAgSUQgPSBjKDEsMiwzLDQsNSksDQogIE5hbWUgPSBjKCJCYWdhcyIsIkpvYW4iLCJBbHlhIiwiRHdpIiwiTmFiaWwiKSwNCiAgUGVyZm9ybWFuY2UgPSBjKCJHb29kIiwiVmVyeSBHb29kIiwiQXZlcmFnZSIsIkdvb2QiLCJWZXJ5IEdvb2QiKQ0KKQ0KDQojIEZvciBsb29wIHVzaW5nIG5leHQgKGNvbnRpbnVlKSB0byBza2lwICJBdmVyYWdlIg0KZm9yKGkgaW4gMTpucm93KGRhdGFfa2FyeWF3YW4pKSB7DQogIA0KICBpZihkYXRhX2thcnlhd2FuJFBlcmZvcm1hbmNlW2ldID09ICJBdmVyYWdlIikgew0KICAgIG5leHQNCiAgfQ0KICANCiAgY2F0KCJOYW1lOiIsIGRhdGFfa2FyeWF3YW4kTmFtZVtpXSwgDQogICAgICAiLCBQZXJmb3JtYW5jZToiLCBkYXRhX2thcnlhd2FuJFBlcmZvcm1hbmNlW2ldLCAiXG4iKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa25pdHIpKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoa2FibGVFeHRyYSkpDQoNCiMgRW1wbG95ZWUgZGF0YXNldA0KZGF0YV9rYXJ5YXdhbiA8LSBkYXRhLmZyYW1lKA0KICBJRCA9IGMoMSwyLDMsNCw1KSwNCiAgTmFtZSA9IGMoIkJhZ2FzIiwiSm9hbiIsIkFseWEiLCJEd2kiLCJOYWJpbCIpLA0KICBQZXJmb3JtYW5jZSA9IGMoIkdvb2QiLCJWZXJ5IEdvb2QiLCJBdmVyYWdlIiwiR29vZCIsIlZlcnkgR29vZCIpDQopDQoNCiMgU3RvcmUgcmVzdWx0cw0KbmFtYSA8LSBjKCkNCnBlcmYgPC0gYygpDQoNCiMgRm9yIGxvb3AgdXNpbmcgbmV4dCAoY29udGludWUpDQpmb3IoaSBpbiAxOm5yb3coZGF0YV9rYXJ5YXdhbikpIHsNCiAgDQogIGlmKGRhdGFfa2FyeWF3YW4kUGVyZm9ybWFuY2VbaV0gPT0gIkF2ZXJhZ2UiKSB7DQogICAgbmV4dA0KICB9DQogIA0KICBuYW1hIDwtIGMobmFtYSwgZGF0YV9rYXJ5YXdhbiROYW1lW2ldKQ0KICBwZXJmIDwtIGMocGVyZiwgZGF0YV9rYXJ5YXdhbiRQZXJmb3JtYW5jZVtpXSkNCn0NCg0KIyBSZXN1bHQgZGF0YQ0KaGFzaWwgPC0gZGF0YS5mcmFtZSgNCiAgTmFtZSA9IG5hbWEsDQogIFBlcmZvcm1hbmNlID0gcGVyZg0KKQ0KDQojIHRhYmxlDQprYWJsZShoYXNpbCwgY2FwdGlvbiA9ICJFbXBsb3llZXMgd2l0aCBOb24tQXZlcmFnZSIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwiYm9yZGVyZWQiKSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAiIzZGNEUzNyIsIGNvbG9yID0gIndoaXRlIikNCmBgYA0KDQoNCmBgYHs9aHRtbH0NCjxkaXYgc3R5bGU9Ig0KYmFja2dyb3VuZC1jb2xvcjojOEI0NTEzOw0KY29sb3I6I2ZmZmZmZjsNCnBhZGRpbmc6MzVweDsNCmJvcmRlci1yYWRpdXM6MTJweDsNCm1heC13aWR0aDo5MDBweDsNCm1hcmdpbjozMHB4IGF1dG87DQpmb250LWZhbWlseTonU2Vnb2UgVUknLCBUYWhvbWEsIEdlbmV2YSwgVmVyZGFuYSwgc2Fucy1zZXJpZjsNCmxpbmUtaGVpZ2h0OjEuOTsNCnRleHQtYWxpZ246anVzdGlmeTsNCmJveC1zaGFkb3c6MCA2cHggMTRweCByZ2JhKDAsMCwwLDAuMjUpOw0KIj4NCg0KPHAgc3R5bGU9ImZvbnQtc2l6ZToyMnB4OyBmb250LXdlaWdodDo3MDA7IGNvbG9yOiNGRkMxMDc7IG1hcmdpbi1ib3R0b206MThweDsiPg0KQ29uY2x1c2lvbg0KPC9wPg0KDQo8cCBzdHlsZT0iZm9udC1zaXplOjE3cHg7Ij4NClRoaXMgYWN0aXZpdHkgZGVtb25zdHJhdGVzIGhvdyA8c3Ryb25nPmNvbmRpdGlvbmFsIHN0YXRlbWVudHM8L3N0cm9uZz4gZW5hYmxlIHByb2dyYW1zIHRvIG1ha2UgZGVjaXNpb25zIGJhc2VkIG9uIHNwZWNpZmljIGNyaXRlcmlhLiBIZXJlLCBjb25kaXRpb25zIGFyZSB1c2VkIHRvIGFzc2lnbiBlbXBsb3llZSBib251cyBwZXJjZW50YWdlcyBhY2NvcmRpbmcgdG8gcGVyZm9ybWFuY2UgbGV2ZWxzIHN1Y2ggYXMgPGVtPlZlcnkgR29vZDwvZW0+LCA8ZW0+R29vZDwvZW0+LCBhbmQgPGVtPkF2ZXJhZ2U8L2VtPi4gVGhyb3VnaCB0aGVzZSBsb2dpY2FsIHN0cnVjdHVyZXMsIHRoZSBwcm9ncmFtIGNhbiBhdXRvbWF0aWNhbGx5IGNvbXB1dGUgdGhlIGFwcHJvcHJpYXRlIGJvbnVzIGZyb20gZWFjaCBlbXBsb3llZSdzIHNhbGFyeSwgZW5oYW5jaW5nIGJvdGggZWZmaWNpZW5jeSBhbmQgY29uc2lzdGVuY3kgaW4gdGhlIHByb2Nlc3MuDQo8L3A+DQoNCjxwIHN0eWxlPSJmb250LXNpemU6MTdweDsiPg0KTW9yZW92ZXIsIDxzdHJvbmc+bG9vcGluZyBtZWNoYW5pc21zPC9zdHJvbmc+IGxpa2UgdGhlIDxzdHJvbmc+Zm9yPC9zdHJvbmc+IGFuZCA8c3Ryb25nPndoaWxlPC9zdHJvbmc+IGxvb3BzLCBjb21iaW5lZCB3aXRoIGNvbnRyb2wgc3RhdGVtZW50cyBzdWNoIGFzIDxzdHJvbmc+YnJlYWs8L3N0cm9uZz4gYW5kIDxzdHJvbmc+Y29udGludWU8L3N0cm9uZz4sIHN0cmVhbWxpbmUgcmVwZXRpdGl2ZSBvcGVyYXRpb25zIGludm9sdmVkIGluIGhhbmRsaW5nIGVtcGxveWVlIHJlY29yZHMuIFRoZSA8c3Ryb25nPmZvciBsb29wPC9zdHJvbmc+IHByb3ZlcyBlZmZlY3RpdmUgZm9yIHNjYW5uaW5nIGRhdGFzZXRzIHRvIGlkZW50aWZ5IGVtcGxveWVlcyBtZWV0aW5nIHBhcnRpY3VsYXIgY29uZGl0aW9ucywgd2hpbGUgdGhlIDxzdHJvbmc+d2hpbGUgbG9vcDwvc3Ryb25nPiBjb250aW51ZXMgZXhlY3V0aW9uIHVudGlsIGEgc3BlY2lmaWVkIGNvbmRpdGlvbiBpcyBmdWxmaWxsZWQuIFRoZSA8c3Ryb25nPmJyZWFrPC9zdHJvbmc+IHN0YXRlbWVudCB0ZXJtaW5hdGVzIGEgbG9vcCBwcmVtYXR1cmVseSB3aGVuIGEgZGVzaXJlZCBjb25kaXRpb24gaXMgbWV0LCBhbmQgPHN0cm9uZz5jb250aW51ZTwvc3Ryb25nPiBhbGxvd3MgdGhlIGxvb3AgdG8gYnlwYXNzIGNlcnRhaW4gZGF0YSB3aXRob3V0IGhhbHRpbmcgZW50aXJlbHkuIENvbGxlY3RpdmVseSwgdGhlc2UgcHJvZ3JhbW1pbmcgY29uc3RydWN0cyBjb250cmlidXRlIHRvIHRoZSBkZXZlbG9wbWVudCBvZiBlZmZpY2llbnQgc3lzdGVtcyBmb3IgbWFuYWdpbmcgYW5kIGFuYWx5emluZyBlbXBsb3llZSBkYXRhLg0KPC9wPg0KDQo8L2Rpdj4NCmBgYA0K