Profil Mahasiswa - Anindya Kristianingputri
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
|
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
|
Loops (For &
While)
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
|
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)
|
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
|
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