Syntax and Control Flow

Practicum ~ Week 4


M. Yustian Putra Muhadi

Institut Teknologi Sains Bandung

Lectur: Mr. Bakti Siregar, M.Sc., CDS

R Programming Data Science NIM: 52250015

Learning Objectives

1.

Understand and apply conditional statements (if, if-else, if-else if-else).

2.

Use loops (for loop, while loop, break, next) to analyze a dataset.


1 Dataset

# Membuat data frame dari tabel karyawan
data <- 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")
)
print(data)
##   ID  Name Age Salary   Position Performance
## 1  1 Bagas  25   5000      Staff        Good
## 2  2  Joan  30   7000 Supervisor   Very Good
## 3  3  Alya  27   6500      Staff     Average
## 4  4   Dwi  35  10000    Manager        Good
## 5  5 Nabil  40  12000   Director   Very Good

Employee Dataset

5 employees · 6 variables

ID Name Age Salary Position Performance
1 Bagas 25 $5,000 Staff Good
2 Joan 30 $7,000 Supervisor Very Good
3 Alya 27 $6,500 Staff Average
4 Dwi 35 $10,000 Manager Good
5 Nabil 40 $12,000 Director Very Good

Interpretation: This code builds the foundation for analysis by organizing employee data into a structured data frame. The table provides an immediate overview of six variables — ID, name, age, salary, position, and performance — which are crucial before performing further operations such as calculations or filtering. This step reflects standard practice in data programming, where data must be available in a structured format for efficient processing.


2 Conditional Statements

Task: Determine the bonus level based on employee performance:

  • Very Good → 20% of salary
  • Good → 10% of salary
  • Average → 5% of salary
# Menghitung bonus berdasarkan performance
for (i in 1:nrow(data)) {
  karyawan <- data[i, ]
  
  if (karyawan$Performance == "Very Good") {
    bonus <- karyawan$Salary * 0.20
  } else if (karyawan$Performance == "Good") {
    bonus <- karyawan$Salary * 0.10
  } else {  # Average
    bonus <- karyawan$Salary * 0.05
  }
  
  cat(paste0("Name: ", karyawan$Name, ", Bonus: ", as.integer(bonus), "\n"))
}
## Name: Bagas, Bonus: 500
## Name: Joan, Bonus: 1400
## Name: Alya, Bonus: 325
## Name: Dwi, Bonus: 1000
## Name: Nabil, Bonus: 2400

Bonus Calculator — if / else if / else

Very Good → 20% Good → 10% Average → 5%
10%
Bagas
Performance: Good
$500
Bonus 10% of $5,000
20%
Joan
Performance: Very Good
$1,400
Bonus 20% of $7,000
5%
Alya
Performance: Average
$325
Bonus 5% of $6,500
10%
Dwi
Performance: Good
$1,000
Bonus 10% of $10,000
20%
Nabil
Performance: Very Good
$2,400
Bonus 20% of $12,000

Interpretation: Branching logic (if-else) automatically determines different bonus percentages for each performance level: 20% for "Very Good," 10% for "Good," and 5% for "Average." This demonstrates how business decisions can be translated into code, ensuring consistent calculations and avoiding manual errors. Results are displayed in an informative format for easy management review.


3 Loops (For & While)

Loops Overview: Use loops to analyze the employee dataset using four techniques:

  • for loop — iterate over all employees to filter by salary
  • while loop — iterate until a condition is met
  • break — exit a loop early when a condition triggers
  • next — skip an iteration and continue to the next

3.1 For Loop

Task: Use a for loop to display employees with salary greater than 6,000.

# Menggunakan for loop untuk menampilkan karyawan dengan gaji > 6000
cat("Karyawan dengan gaji di atas 6000:\n")
## Karyawan dengan gaji di atas 6000:
for (i in 1:nrow(data)) {
  if (data$Salary[i] > 6000) {
    cat(paste0("Name: ", data$Name[i], ", Salary: ", data$Salary[i], "\n"))
  }
}
## Name: Joan, Salary: 7000
## Name: Alya, Salary: 6500
## Name: Dwi, Salary: 10000
## Name: Nabil, Salary: 12000
FOR LOOP Salary > 6,000
Joan — Supervisor
$7,000
Alya — Staff
$6,500
Dwi — Manager
$10,000
Nabil — Director
$12,000

Interpretation: Using a for loop, we filter employees with salaries above 6,000 by iterating each row and applying an if condition. This technique quickly identifies high-paid employees for further evaluation or policy decisions.


3.2 While Loop

Task: Use a while loop to display employees until a “Manager” is found, then stop.

# Menggunakan while loop sampai ditemukan posisi Manager
cat("Menampilkan karyawan sampai ditemukan Manager:\n")
## Menampilkan karyawan sampai ditemukan Manager:
i <- 1
while (i <= nrow(data)) {
  karyawan <- data[i, ]
  if (karyawan$Position == "Manager") {
    cat(paste0("Name: ", karyawan$Name, ", Position: ", karyawan$Position, " (Stop here)\n"))
    break
  } else {
    cat(paste0("Name: ", karyawan$Name, ", Position: ", karyawan$Position, "\n"))
  }
  i <- i + 1
}
## Name: Bagas, Position: Staff
## Name: Joan, Position: Supervisor
## Name: Alya, Position: Staff
## Name: Dwi, Position: Manager (Stop here)
WHILE LOOP Until Manager is found
Bagas
Staff
Joan
Supervisor
Alya
Staff
Dwi
Manager — STOP

Interpretation: The while loop processes employees sequentially, displaying each name and position until the "Manager" position is encountered. This reflects real-world scenarios like queue processing where data is handled up to a specific point based on dynamic conditions.


3.3 Break

Task: Use break to stop the loop immediately when a salary above 10,000 is found.

# Menggunakan break ketika menemukan gaji di atas 10000
cat("Menampilkan karyawan hingga menemukan gaji di atas 10,000:\n")
## Menampilkan karyawan hingga menemukan gaji di atas 10,000:
for (i in 1:nrow(data)) {
  if (data$Salary[i] > 10000) {
    cat(paste0("(Stopped because ", data$Name[i], " has a salary above 10,000)\n"))
    break
  } else {
    cat(paste0("Name: ", data$Name[i], ", Salary: ", data$Salary[i], "\n"))
  }
}
## Name: Bagas, Salary: 5000
## Name: Joan, Salary: 7000
## Name: Alya, Salary: 6500
## Name: Dwi, Salary: 10000
## (Stopped because Nabil has a salary above 10,000)
BREAK Stop when Salary > 10,000
Bagas
$5,000
Joan
$7,000
Alya
$6,500
Dwi
$10,000
BREAK — Nabil has salary above 10,000
$12,000

Interpretation: The break command halts the loop immediately upon finding a salary above 10,000, preventing unnecessary processing. This technique is useful in data retrieval when we only need to process records up to a specific threshold or condition.


3.4 Continue (Next)

Task: Use next to skip employees with “Average” performance and continue to the next iteration.

# Menggunakan continue untuk melewatkan karyawan dengan performance "Average"
cat("Karyawan dengan performa (selain Average):\n")
## Karyawan dengan performa (selain Average):
skipped <- c()

for (i in 1:nrow(data)) {
  if (data$Performance[i] == "Average") {
    skipped <- c(skipped, data$Name[i])
    next
  }
  cat(paste0("Name: ", data$Name[i], ", Performance: ", data$Performance[i], "\n"))
}
## Name: Bagas, Performance: Good
## Name: Joan, Performance: Very Good
## Name: Dwi, Performance: Good
## Name: Nabil, Performance: Very Good
if (length(skipped) > 0) {
  cat(paste0("(", paste(skipped, collapse = ", "),
             ifelse(length(skipped) == 1, " is ", " are "),
             "skipped because the performance is \"Average\")\n"))
}
## (Alya is skipped because the performance is "Average")
NEXT / CONTINUE Skip employees with Average performance
Bagas
Good
Joan
Very Good
Alya
skipped (Average)
Dwi
Good
Nabil
Very Good
Alya is skipped because performance is "Average"

Interpretation: The next command skips "Average" employees and records their names, displaying only those with "Good" and "Very Good" performance. This elegantly filters data without altering the original structure, and the omitted names are automatically reported at the end for transparency.

LS0tDQp0aXRsZTogIiBTeW50YXggYW5kIENvbnRyb2wgRmxvdyAiDQpzdWJ0aXRsZTogIiBQcmFjdGljdW0gfiBXZWVrIDQgIg0KYXV0aG9yOiANCiAgLSAiTS4gWXVzdGlhbiBQdXRyYSBNdWhhZGkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQoNCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246DQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgbGliX2RpcjogbGlicw0KICAgIGRmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpDQpsaWJyYXJ5KGh0bWx0b29scykNCmBgYA0KDQotLS0NCg0KYGBge3IgcHJvZmlsZSwgZWNobz1GQUxTRX0NCkhUTUwoJw0KPGRpdiBzdHlsZT0iDQogIGRpc3BsYXk6IGZsZXg7IGdhcDogMzBweDsgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzBmMjAyNywgIzIwM2E0MywgIzJjNTM2NCk7DQogIHBhZGRpbmc6IDM2cHg7IGJvcmRlci1yYWRpdXM6IDIwcHg7IG1hcmdpbjogMjRweCAwOw0KICBib3gtc2hhZG93OiAwIDIwcHggNjBweCByZ2JhKDAsMCwwLDAuNCk7DQogIGZvbnQtZmFtaWx5OiBHZW9yZ2lhLCBzZXJpZjsNCiI+DQogIDxkaXY+DQogICAgPGltZyBzcmM9Ik11aGhoLmpwZyINCiAgICAgICAgIG9uZXJyb3I9InRoaXMuc3R5bGUuZGlzcGxheT1cJ25vbmVcJzsgdGhpcy5uZXh0RWxlbWVudFNpYmxpbmcuc3R5bGUuZGlzcGxheT1cJ2ZsZXhcJzsiDQogICAgICAgICBzdHlsZT0id2lkdGg6MTgwcHg7IGhlaWdodDoxODBweDsgYm9yZGVyLXJhZGl1czo1MCU7IG9iamVjdC1maXQ6Y292ZXI7DQogICAgICAgICAgICAgICAgYm9yZGVyOiA0cHggc29saWQgIzAwZDRmZjsgYm94LXNoYWRvdzogMCAwIDMwcHggcmdiYSgwLDIxMiwyNTUsMC40KTsiPg0KICAgIDxkaXYgc3R5bGU9ImRpc3BsYXk6bm9uZTsgd2lkdGg6MTgwcHg7IGhlaWdodDoxODBweDsgYm9yZGVyLXJhZGl1czo1MCU7DQogICAgICAgICAgICAgICAgYmFja2dyb3VuZDpyZ2JhKDAsMjEyLDI1NSwwLjE1KTsgYm9yZGVyOjRweCBzb2xpZCAjMDBkNGZmOw0KICAgICAgICAgICAgICAgIGFsaWduLWl0ZW1zOmNlbnRlcjsganVzdGlmeS1jb250ZW50OmNlbnRlcjsNCiAgICAgICAgICAgICAgICBmb250LXNpemU6M2VtOyBjb2xvcjojMDBkNGZmOyI+PC9kaXY+DQogIDwvZGl2Pg0KICA8ZGl2Pg0KICAgIDxoMSBzdHlsZT0iY29sb3I6I2ZmZmZmZjsgbWFyZ2luOjAgMCA0cHggMDsgZm9udC1zaXplOjEuOWVtOyBsZXR0ZXItc3BhY2luZzoxcHg7Ij4NCiAgICAgIE0uIFl1c3RpYW4gUHV0cmEgTXVoYWRpDQogICAgPC9oMT4NCiAgICA8cCBzdHlsZT0iY29sb3I6IzAwZDRmZjsgbWFyZ2luOjAgMCA2cHggMDsgZm9udC1zaXplOjAuOWVtOyBsZXR0ZXItc3BhY2luZzoycHg7IHRleHQtdHJhbnNmb3JtOnVwcGVyY2FzZTsiPg0KICAgICAgSW5zdGl0dXQgVGVrbm9sb2dpIFNhaW5zIEJhbmR1bmcNCiAgICA8L3A+DQogICAgPHAgc3R5bGU9ImNvbG9yOiM4ODg7IG1hcmdpbjowIDAgMjBweCAwOyBmb250LXNpemU6MC44NWVtOyI+DQogICAgICBMZWN0dXI6IA0KICAgICAgTXIuIEJha3RpIFNpcmVnYXIsIE0uU2MuLCBDRFMNCiAgICA8L3A+DQogICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBnYXA6MTJweDsgZmxleC13cmFwOndyYXA7Ij4NCiAgICAgIDxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoNTIsMTUyLDIxOSwwLjI1KTsgY29sb3I6IzM0OThkYjsgcGFkZGluZzo4cHggMThweDsNCiAgICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICMzNDk4ZGI7IGJvcmRlci1yYWRpdXM6MjBweDsgZm9udC1zaXplOjAuODVlbTsgZm9udC13ZWlnaHQ6Ym9sZDsiPg0KICAgICAgICBSIFByb2dyYW1taW5nDQogICAgICA8L3NwYW4+DQogICAgICA8c3BhbiBzdHlsZT0iYmFja2dyb3VuZDpyZ2JhKDIzMSw3Niw2MCwwLjI1KTsgY29sb3I6I2U3NGMzYzsgcGFkZGluZzo4cHggMThweDsNCiAgICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICNlNzRjM2M7IGJvcmRlci1yYWRpdXM6MjBweDsgZm9udC1zaXplOjAuODVlbTsgZm9udC13ZWlnaHQ6Ym9sZDsiPg0KICAgICAgICBEYXRhIFNjaWVuY2UNCiAgICAgIDwvc3Bhbj4NCiAgICAgIDxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoNDYsMjA0LDExMywwLjI1KTsgY29sb3I6IzJlY2M3MTsgcGFkZGluZzo4cHggMThweDsNCiAgICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICMyZWNjNzE7IGJvcmRlci1yYWRpdXM6MjBweDsgZm9udC1zaXplOjAuODVlbTsgZm9udC13ZWlnaHQ6Ym9sZDsiPg0KICAgICAgICBOSU06IDUyMjUwMDE1DQogICAgICA8L3NwYW4+DQogICAgPC9kaXY+DQogIDwvZGl2Pg0KPC9kaXY+DQonKQ0KYGBgDQoNCi0tLQ0KDQpgYGB7ciBvYmplY3RpdmUsIGVjaG89RkFMU0V9DQpIVE1MKCcNCjxkaXYgc3R5bGU9Ig0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjMWExYTJlLCAjMTYyMTNlKTsNCiAgYm9yZGVyLWxlZnQ6IDVweCBzb2xpZCAjMDBkNGZmOw0KICBib3JkZXItcmFkaXVzOiAxMnB4OyBwYWRkaW5nOiAyOHB4IDMycHg7IG1hcmdpbjogMjRweCAwOw0KICBmb250LWZhbWlseTogR2VvcmdpYSwgc2VyaWY7DQogIGJveC1zaGFkb3c6IDAgOHB4IDMycHggcmdiYSgwLDAsMCwwLjMpOw0KIj4NCiAgPGgyIHN0eWxlPSJjb2xvcjojMDBkNGZmOyBtYXJnaW46MCAwIDE4cHggMDsgZm9udC1zaXplOjEuMWVtOyBsZXR0ZXItc3BhY2luZzoycHg7IHRleHQtdHJhbnNmb3JtOnVwcGVyY2FzZTsiPg0KICAgIExlYXJuaW5nIE9iamVjdGl2ZXMNCiAgPC9oMj4NCiAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGdhcDoxMnB4OyI+DQogICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpmbGV4LXN0YXJ0OyBnYXA6MTRweDsgcGFkZGluZzoxNHB4IDE4cHg7DQogICAgICAgICAgICAgICAgYmFja2dyb3VuZDpyZ2JhKDAsMjEyLDI1NSwwLjA4KTsgYm9yZGVyLXJhZGl1czoxMHB4OyI+DQogICAgICA8c3BhbiBzdHlsZT0iY29sb3I6IzAwZDRmZjsgZm9udC1zaXplOjEuM2VtOyBtaW4td2lkdGg6MzBweDsgZm9udC13ZWlnaHQ6Ym9sZDsiPjEuPC9zcGFuPg0KICAgICAgPHAgc3R5bGU9ImNvbG9yOiNlMGUwZTA7IG1hcmdpbjowOyBsaW5lLWhlaWdodDoxLjc7IGZvbnQtc2l6ZTowLjk1ZW07Ij4NCiAgICAgICAgVW5kZXJzdGFuZCBhbmQgYXBwbHkgPHN0cm9uZyBzdHlsZT0iY29sb3I6IzAwZDRmZjsiPmNvbmRpdGlvbmFsIHN0YXRlbWVudHM8L3N0cm9uZz4NCiAgICAgICAgKGlmLCBpZi1lbHNlLCBpZi1lbHNlIGlmLWVsc2UpLg0KICAgICAgPC9wPg0KICAgIDwvZGl2Pg0KICAgIDxkaXYgc3R5bGU9ImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6ZmxleC1zdGFydDsgZ2FwOjE0cHg7IHBhZGRpbmc6MTRweCAxOHB4Ow0KICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6cmdiYSgwLDIxMiwyNTUsMC4wOCk7IGJvcmRlci1yYWRpdXM6MTBweDsiPg0KICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiMwMGQ0ZmY7IGZvbnQtc2l6ZToxLjNlbTsgbWluLXdpZHRoOjMwcHg7IGZvbnQtd2VpZ2h0OmJvbGQ7Ij4yLjwvc3Bhbj4NCiAgICAgIDxwIHN0eWxlPSJjb2xvcjojZTBlMGUwOyBtYXJnaW46MDsgbGluZS1oZWlnaHQ6MS43OyBmb250LXNpemU6MC45NWVtOyI+DQogICAgICAgIFVzZSA8c3Ryb25nIHN0eWxlPSJjb2xvcjojMDBkNGZmOyI+bG9vcHM8L3N0cm9uZz4NCiAgICAgICAgKGZvciBsb29wLCB3aGlsZSBsb29wLCBicmVhaywgbmV4dCkgdG8gYW5hbHl6ZSBhIGRhdGFzZXQuDQogICAgICA8L3A+DQogICAgPC9kaXY+DQogIDwvZGl2Pg0KPC9kaXY+DQonKQ0KYGBgDQoNCi0tLQ0KDQojIERhdGFzZXQNCg0KYGBge3IgZGF0YXNldC1idWlsZH0NCiMgTWVtYnVhdCBkYXRhIGZyYW1lIGRhcmkgdGFiZWwga2FyeWF3YW4NCmRhdGEgPC0gZGF0YS5mcmFtZSgNCiAgSUQgICAgICAgICAgPSBjKDEsIDIsIDMsIDQsIDUpLA0KICBOYW1lICAgICAgICA9IGMoIkJhZ2FzIiwgIkpvYW4iLCAiQWx5YSIsICJEd2kiLCAiTmFiaWwiKSwNCiAgQWdlICAgICAgICAgPSBjKDI1LCAzMCwgMjcsIDM1LCA0MCksDQogIFNhbGFyeSAgICAgID0gYyg1MDAwLCA3MDAwLCA2NTAwLCAxMDAwMCwgMTIwMDApLA0KICBQb3NpdGlvbiAgICA9IGMoIlN0YWZmIiwgIlN1cGVydmlzb3IiLCAiU3RhZmYiLCAiTWFuYWdlciIsICJEaXJlY3RvciIpLA0KICBQZXJmb3JtYW5jZSA9IGMoIkdvb2QiLCAiVmVyeSBHb29kIiwgIkF2ZXJhZ2UiLCAiR29vZCIsICJWZXJ5IEdvb2QiKQ0KKQ0KcHJpbnQoZGF0YSkNCmBgYA0KDQpgYGB7ciBkYXRhc2V0LXZpc3VhbCwgZWNobz1GQUxTRX0NCnBvc2l0aW9uX2NvbG9ycyA8LSBjKA0KICAiU3RhZmYiICAgICAgPSAiIzM0OThkYiIsDQogICJTdXBlcnZpc29yIiA9ICIjOWI1OWI2IiwNCiAgIk1hbmFnZXIiICAgID0gIiNlNjdlMjIiLA0KICAiRGlyZWN0b3IiICAgPSAiI2U3NGMzYyINCikNCnBlcmZfY29sb3JzIDwtIGMoDQogICJWZXJ5IEdvb2QiID0gIiMyZWNjNzEiLA0KICAiR29vZCIgICAgICA9ICIjZjFjNDBmIiwNCiAgIkF2ZXJhZ2UiICAgPSAiI2U3NGMzYyINCikNCg0Kcm93c19odG1sIDwtICIiDQpmb3IgKGkgaW4gMTpucm93KGRhdGEpKSB7DQogIHBvc19jb2wgIDwtIHBvc2l0aW9uX2NvbG9yc1tkYXRhJFBvc2l0aW9uW2ldXQ0KICBwZXJmX2NvbCA8LSBwZXJmX2NvbG9yc1tkYXRhJFBlcmZvcm1hbmNlW2ldXQ0KICByb3dzX2h0bWwgPC0gcGFzdGUwKHJvd3NfaHRtbCwgc3ByaW50ZignDQogICAgPHRyIG9ubW91c2VvdmVyPSJ0aGlzLnN0eWxlLmJhY2tncm91bmQ9XCdyZ2JhKDAsMjEyLDI1NSwwLjA3KVwnIg0KICAgICAgICBvbm1vdXNlb3V0PSJ0aGlzLnN0eWxlLmJhY2tncm91bmQ9XCd0cmFuc3BhcmVudFwnIg0KICAgICAgICBzdHlsZT0iYm9yZGVyLWJvdHRvbToxcHggc29saWQgcmdiYSgyNTUsMjU1LDI1NSwwLjA3KTsgdHJhbnNpdGlvbjpiYWNrZ3JvdW5kIDAuMnM7Ij4NCiAgICAgIDx0ZCBzdHlsZT0icGFkZGluZzoxMnB4IDE2cHg7IGNvbG9yOiNhYWE7IHRleHQtYWxpZ246Y2VudGVyOyI+JWQ8L3RkPg0KICAgICAgPHRkIHN0eWxlPSJwYWRkaW5nOjEycHggMTZweDsgY29sb3I6I2ZmZjsgZm9udC13ZWlnaHQ6Ym9sZDsiPiVzPC90ZD4NCiAgICAgIDx0ZCBzdHlsZT0icGFkZGluZzoxMnB4IDE2cHg7IGNvbG9yOiNjY2M7IHRleHQtYWxpZ246Y2VudGVyOyI+JWQ8L3RkPg0KICAgICAgPHRkIHN0eWxlPSJwYWRkaW5nOjEycHggMTZweDsgY29sb3I6IzAwZDRmZjsgdGV4dC1hbGlnbjpjZW50ZXI7IGZvbnQtd2VpZ2h0OmJvbGQ7Ij4kJXM8L3RkPg0KICAgICAgPHRkIHN0eWxlPSJwYWRkaW5nOjEycHggMTZweDsgdGV4dC1hbGlnbjpjZW50ZXI7Ij4NCiAgICAgICAgPHNwYW4gc3R5bGU9ImJhY2tncm91bmQ6cmdiYSgwLDAsMCwwLjMpOyBjb2xvcjolczsgcGFkZGluZzo0cHggMTJweDsNCiAgICAgICAgICAgICAgICAgICAgIGJvcmRlcjoxcHggc29saWQgJXM7IGJvcmRlci1yYWRpdXM6MTJweDsgZm9udC1zaXplOjAuOGVtOyBmb250LXdlaWdodDpib2xkOyI+JXM8L3NwYW4+DQogICAgICA8L3RkPg0KICAgICAgPHRkIHN0eWxlPSJwYWRkaW5nOjEycHggMTZweDsgdGV4dC1hbGlnbjpjZW50ZXI7Ij4NCiAgICAgICAgPHNwYW4gc3R5bGU9ImJhY2tncm91bmQ6cmdiYSgwLDAsMCwwLjMpOyBjb2xvcjolczsgcGFkZGluZzo0cHggMTJweDsNCiAgICAgICAgICAgICAgICAgICAgIGJvcmRlcjoxcHggc29saWQgJXM7IGJvcmRlci1yYWRpdXM6MTJweDsgZm9udC1zaXplOjAuOGVtOyBmb250LXdlaWdodDpib2xkOyI+JXM8L3NwYW4+DQogICAgICA8L3RkPg0KICAgIDwvdHI+JywNCiAgICBkYXRhJElEW2ldLCBkYXRhJE5hbWVbaV0sIGRhdGEkQWdlW2ldLA0KICAgIGZvcm1hdChkYXRhJFNhbGFyeVtpXSwgYmlnLm1hcms9IiwiKSwNCiAgICBwb3NfY29sLCBwb3NfY29sLCBkYXRhJFBvc2l0aW9uW2ldLA0KICAgIHBlcmZfY29sLCBwZXJmX2NvbCwgZGF0YSRQZXJmb3JtYW5jZVtpXQ0KICApKQ0KfQ0KDQpIVE1MKHBhc3RlMCgnDQo8ZGl2IHN0eWxlPSINCiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzFhMWEyZSwgIzE2MjEzZSk7DQogIGJvcmRlci1yYWRpdXM6IDE2cHg7IHBhZGRpbmc6IDI4cHggMzJweDsgbWFyZ2luOiAyNHB4IDA7DQogIGZvbnQtZmFtaWx5OiBHZW9yZ2lhLCBzZXJpZjsNCiAgYm94LXNoYWRvdzogMCA4cHggMzJweCByZ2JhKDAsMCwwLDAuMyk7DQoiPg0KICA8aDIgc3R5bGU9ImNvbG9yOiMwMGQ0ZmY7IG1hcmdpbjowIDAgNHB4IDA7IGZvbnQtc2l6ZToxLjFlbTsgbGV0dGVyLXNwYWNpbmc6MnB4OyB0ZXh0LXRyYW5zZm9ybTp1cHBlcmNhc2U7Ij4NCiAgICBFbXBsb3llZSBEYXRhc2V0DQogIDwvaDI+DQogIDxwIHN0eWxlPSJjb2xvcjojODg4OyBtYXJnaW46MCAwIDIwcHggMDsgZm9udC1zaXplOjAuODJlbTsiPjUgZW1wbG95ZWVzIMK3IDYgdmFyaWFibGVzPC9wPg0KDQogIDxkaXYgc3R5bGU9Im92ZXJmbG93LXg6YXV0bzsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3JkZXI6MXB4IHNvbGlkIHJnYmEoMjU1LDI1NSwyNTUsMC4xKTsiPg0KICAgIDx0YWJsZSBzdHlsZT0id2lkdGg6MTAwJTsgYm9yZGVyLWNvbGxhcHNlOmNvbGxhcHNlOyBmb250LXNpemU6MC45ZW07Ij4NCiAgICAgIDx0aGVhZD4NCiAgICAgICAgPHRyIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoMCwyMTIsMjU1LDAuMTIpOyI+DQogICAgICAgICAgPHRoIHN0eWxlPSJwYWRkaW5nOjE0cHggMTZweDsgY29sb3I6IzAwZDRmZjsgdGV4dC1hbGlnbjpjZW50ZXI7IGxldHRlci1zcGFjaW5nOjFweDsiPklEPC90aD4NCiAgICAgICAgICA8dGggc3R5bGU9InBhZGRpbmc6MTRweCAxNnB4OyBjb2xvcjojMDBkNGZmOyB0ZXh0LWFsaWduOmxlZnQ7ICAgbGV0dGVyLXNwYWNpbmc6MXB4OyI+TmFtZTwvdGg+DQogICAgICAgICAgPHRoIHN0eWxlPSJwYWRkaW5nOjE0cHggMTZweDsgY29sb3I6IzAwZDRmZjsgdGV4dC1hbGlnbjpjZW50ZXI7IGxldHRlci1zcGFjaW5nOjFweDsiPkFnZTwvdGg+DQogICAgICAgICAgPHRoIHN0eWxlPSJwYWRkaW5nOjE0cHggMTZweDsgY29sb3I6IzAwZDRmZjsgdGV4dC1hbGlnbjpjZW50ZXI7IGxldHRlci1zcGFjaW5nOjFweDsiPlNhbGFyeTwvdGg+DQogICAgICAgICAgPHRoIHN0eWxlPSJwYWRkaW5nOjE0cHggMTZweDsgY29sb3I6IzAwZDRmZjsgdGV4dC1hbGlnbjpjZW50ZXI7IGxldHRlci1zcGFjaW5nOjFweDsiPlBvc2l0aW9uPC90aD4NCiAgICAgICAgICA8dGggc3R5bGU9InBhZGRpbmc6MTRweCAxNnB4OyBjb2xvcjojMDBkNGZmOyB0ZXh0LWFsaWduOmNlbnRlcjsgbGV0dGVyLXNwYWNpbmc6MXB4OyI+UGVyZm9ybWFuY2U8L3RoPg0KICAgICAgICA8L3RyPg0KICAgICAgPC90aGVhZD4NCiAgICAgIDx0Ym9keT4nLCByb3dzX2h0bWwsICcNCiAgICAgIDwvdGJvZHk+DQogICAgPC90YWJsZT4NCiAgPC9kaXY+DQoNCiAgPGRpdiBzdHlsZT0ibWFyZ2luLXRvcDoyMnB4OyBwYWRkaW5nOjE4cHggMjJweDsNCiAgICAgICAgICAgICAgYmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LDAuMDQpOyBib3JkZXItcmFkaXVzOjEwcHg7DQogICAgICAgICAgICAgIGJvcmRlci1sZWZ0OjNweCBzb2xpZCAjMDBkNGZmOyI+DQogICAgPHAgc3R5bGU9ImNvbG9yOiNiMGI4Yzg7IG1hcmdpbjowOyBsaW5lLWhlaWdodDoxLjg7IGZvbnQtc2l6ZTowLjllbTsiPg0KICAgICAgPHN0cm9uZyBzdHlsZT0iY29sb3I6IzAwZDRmZjsiPkludGVycHJldGF0aW9uOjwvc3Ryb25nPg0KICAgICAgVGhpcyBjb2RlIGJ1aWxkcyB0aGUgZm91bmRhdGlvbiBmb3IgYW5hbHlzaXMgYnkgb3JnYW5pemluZyBlbXBsb3llZSBkYXRhIGludG8gYSBzdHJ1Y3R1cmVkIGRhdGEgZnJhbWUuDQogICAgICBUaGUgdGFibGUgcHJvdmlkZXMgYW4gaW1tZWRpYXRlIG92ZXJ2aWV3IG9mIHNpeCB2YXJpYWJsZXMg4oCUIElELCBuYW1lLCBhZ2UsIHNhbGFyeSwgcG9zaXRpb24sIGFuZA0KICAgICAgcGVyZm9ybWFuY2Ug4oCUIHdoaWNoIGFyZSBjcnVjaWFsIGJlZm9yZSBwZXJmb3JtaW5nIGZ1cnRoZXIgb3BlcmF0aW9ucyBzdWNoIGFzIGNhbGN1bGF0aW9ucyBvciBmaWx0ZXJpbmcuDQogICAgICBUaGlzIHN0ZXAgcmVmbGVjdHMgc3RhbmRhcmQgcHJhY3RpY2UgaW4gZGF0YSBwcm9ncmFtbWluZywgd2hlcmUgZGF0YSBtdXN0IGJlIGF2YWlsYWJsZSBpbiBhIHN0cnVjdHVyZWQNCiAgICAgIGZvcm1hdCBmb3IgZWZmaWNpZW50IHByb2Nlc3NpbmcuDQogICAgPC9wPg0KICA8L2Rpdj4NCjwvZGl2Pg0KJykpDQpgYGANCg0KLS0tDQoNCiMgQ29uZGl0aW9uYWwgU3RhdGVtZW50cw0KDQoqKlRhc2s6KiogRGV0ZXJtaW5lIHRoZSBib251cyBsZXZlbCBiYXNlZCBvbiBlbXBsb3llZSBwZXJmb3JtYW5jZToNCg0KLSAqKlZlcnkgR29vZCoqIOKGkiAyMCUgb2Ygc2FsYXJ5ICANCi0gKipHb29kKiog4oaSIDEwJSBvZiBzYWxhcnkgIA0KLSAqKkF2ZXJhZ2UqKiDihpIgNSUgb2Ygc2FsYXJ5ICANCg0KYGBge3IgY29uZGl0aW9uYWwtY29kZX0NCiMgTWVuZ2hpdHVuZyBib251cyBiZXJkYXNhcmthbiBwZXJmb3JtYW5jZQ0KZm9yIChpIGluIDE6bnJvdyhkYXRhKSkgew0KICBrYXJ5YXdhbiA8LSBkYXRhW2ksIF0NCiAgDQogIGlmIChrYXJ5YXdhbiRQZXJmb3JtYW5jZSA9PSAiVmVyeSBHb29kIikgew0KICAgIGJvbnVzIDwtIGthcnlhd2FuJFNhbGFyeSAqIDAuMjANCiAgfSBlbHNlIGlmIChrYXJ5YXdhbiRQZXJmb3JtYW5jZSA9PSAiR29vZCIpIHsNCiAgICBib251cyA8LSBrYXJ5YXdhbiRTYWxhcnkgKiAwLjEwDQogIH0gZWxzZSB7ICAjIEF2ZXJhZ2UNCiAgICBib251cyA8LSBrYXJ5YXdhbiRTYWxhcnkgKiAwLjA1DQogIH0NCiAgDQogIGNhdChwYXN0ZTAoIk5hbWU6ICIsIGthcnlhd2FuJE5hbWUsICIsIEJvbnVzOiAiLCBhcy5pbnRlZ2VyKGJvbnVzKSwgIlxuIikpDQp9DQpgYGANCg0KYGBge3IgY29uZGl0aW9uYWwtdmlzdWFsLCBlY2hvPUZBTFNFfQ0KYm9udXNfcm93cyA8LSAiIg0KZm9yIChpIGluIDE6bnJvdyhkYXRhKSkgew0KICBpZiAoZGF0YSRQZXJmb3JtYW5jZVtpXSA9PSAiVmVyeSBHb29kIikgew0KICAgIGJvbnVzIDwtIGRhdGEkU2FsYXJ5W2ldICogMC4yMDsgcGN0IDwtICIyMCUiOyBjb2wgPC0gIiMyZWNjNzEiDQogICAgcmdiYV9iZyA8LSAicmdiYSg0NiwyMDQsMTEzLDAuMjUpIg0KICB9IGVsc2UgaWYgKGRhdGEkUGVyZm9ybWFuY2VbaV0gPT0gIkdvb2QiKSB7DQogICAgYm9udXMgPC0gZGF0YSRTYWxhcnlbaV0gKiAwLjEwOyBwY3QgPC0gIjEwJSI7IGNvbCA8LSAiI2YxYzQwZiINCiAgICByZ2JhX2JnIDwtICJyZ2JhKDI0MSwxOTYsMTUsMC4yNSkiDQogIH0gZWxzZSB7DQogICAgYm9udXMgPC0gZGF0YSRTYWxhcnlbaV0gKiAwLjA1OyBwY3QgPC0gIjUlIjsgIGNvbCA8LSAiI2U3NGMzYyINCiAgICByZ2JhX2JnIDwtICJyZ2JhKDIzMSw3Niw2MCwwLjI1KSINCiAgfQ0KICByb3dfaHRtbCA8LSBwYXN0ZTAoJw0KICAgIDxkaXYgc3R5bGU9ImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsNCiAgICAgICAgICAgICAgICBwYWRkaW5nOjE0cHggMjBweDsgYmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LDAuMDQpOw0KICAgICAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6MTBweDsgYm9yZGVyOjFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuMDgpOw0KICAgICAgICAgICAgICAgIG1hcmdpbi1ib3R0b206OHB4OyI+DQogICAgICA8ZGl2IHN0eWxlPSJkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjE0cHg7Ij4NCiAgICAgICAgPGRpdiBzdHlsZT0id2lkdGg6NDJweDsgaGVpZ2h0OjQycHg7IGJvcmRlci1yYWRpdXM6NTAlOw0KICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOicsIHJnYmFfYmcsICc7IGJvcmRlcjoycHggc29saWQgJywgY29sLCAnOw0KICAgICAgICAgICAgICAgICAgICBkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsganVzdGlmeS1jb250ZW50OmNlbnRlcjsNCiAgICAgICAgICAgICAgICAgICAgZm9udC13ZWlnaHQ6Ym9sZDsgY29sb3I6JywgY29sLCAnOyBmb250LXNpemU6MC43NWVtOyI+JywgcGN0LCAnPC9kaXY+DQogICAgICAgIDxkaXY+DQogICAgICAgICAgPGRpdiBzdHlsZT0iY29sb3I6I2ZmZjsgZm9udC13ZWlnaHQ6Ym9sZDsgZm9udC1zaXplOjAuOTVlbTsiPicsIGRhdGEkTmFtZVtpXSwgJzwvZGl2Pg0KICAgICAgICAgIDxkaXYgc3R5bGU9ImNvbG9yOiM4ODg7IGZvbnQtc2l6ZTowLjc4ZW07Ij5QZXJmb3JtYW5jZTogJywgZGF0YSRQZXJmb3JtYW5jZVtpXSwgJzwvZGl2Pg0KICAgICAgICA8L2Rpdj4NCiAgICAgIDwvZGl2Pg0KICAgICAgPGRpdiBzdHlsZT0idGV4dC1hbGlnbjpyaWdodDsiPg0KICAgICAgICA8ZGl2IHN0eWxlPSJjb2xvcjonLCBjb2wsICc7IGZvbnQtd2VpZ2h0OmJvbGQ7IGZvbnQtc2l6ZToxLjE1ZW07Ij4kJywNCiAgICAgICAgICBmb3JtYXQoYXMuaW50ZWdlcihib251cyksIGJpZy5tYXJrPSIsIiksICc8L2Rpdj4NCiAgICAgICAgPGRpdiBzdHlsZT0iY29sb3I6Izg4ODsgZm9udC1zaXplOjAuNzhlbTsiPkJvbnVzICcsIHBjdCwgJyBvZiAkJywNCiAgICAgICAgICBmb3JtYXQoZGF0YSRTYWxhcnlbaV0sIGJpZy5tYXJrPSIsIiksICc8L2Rpdj4NCiAgICAgIDwvZGl2Pg0KICAgIDwvZGl2PicpDQogIGJvbnVzX3Jvd3MgPC0gcGFzdGUwKGJvbnVzX3Jvd3MsIHJvd19odG1sKQ0KfQ0KDQpIVE1MKHBhc3RlMCgnDQo8ZGl2IHN0eWxlPSINCiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzFhMWEyZSwgIzE2MjEzZSk7DQogIGJvcmRlci1yYWRpdXM6IDE2cHg7IHBhZGRpbmc6IDI4cHggMzJweDsgbWFyZ2luOiAyNHB4IDA7DQogIGZvbnQtZmFtaWx5OiBHZW9yZ2lhLCBzZXJpZjsNCiAgYm94LXNoYWRvdzogMCA4cHggMzJweCByZ2JhKDAsMCwwLDAuMyk7DQoiPg0KICA8aDIgc3R5bGU9ImNvbG9yOiNmMzljMTI7IG1hcmdpbjowIDAgNnB4IDA7IGZvbnQtc2l6ZToxLjFlbTsgbGV0dGVyLXNwYWNpbmc6MnB4OyB0ZXh0LXRyYW5zZm9ybTp1cHBlcmNhc2U7Ij4NCiAgICBCb251cyBDYWxjdWxhdG9yIOKAlCBpZiAvIGVsc2UgaWYgLyBlbHNlDQogIDwvaDI+DQoNCiAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBnYXA6MTJweDsgbWFyZ2luLWJvdHRvbToyMnB4OyBmbGV4LXdyYXA6d3JhcDsiPg0KICAgIDxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoNDYsMjA0LDExMywwLjIpOyBjb2xvcjojMmVjYzcxOyBwYWRkaW5nOjVweCAxNHB4Ow0KICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICMyZWNjNzE7IGJvcmRlci1yYWRpdXM6MTJweDsgZm9udC1zaXplOjAuOGVtOyI+DQogICAgICBWZXJ5IEdvb2Qg4oaSIDIwJQ0KICAgIDwvc3Bhbj4NCiAgICA8c3BhbiBzdHlsZT0iYmFja2dyb3VuZDpyZ2JhKDI0MSwxOTYsMTUsMC4yKTsgY29sb3I6I2YxYzQwZjsgcGFkZGluZzo1cHggMTRweDsNCiAgICAgICAgICAgICAgICAgYm9yZGVyOjFweCBzb2xpZCAjZjFjNDBmOyBib3JkZXItcmFkaXVzOjEycHg7IGZvbnQtc2l6ZTowLjhlbTsiPg0KICAgICAgR29vZCDihpIgMTAlDQogICAgPC9zcGFuPg0KICAgIDxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoMjMxLDc2LDYwLDAuMik7IGNvbG9yOiNlNzRjM2M7IHBhZGRpbmc6NXB4IDE0cHg7DQogICAgICAgICAgICAgICAgIGJvcmRlcjoxcHggc29saWQgI2U3NGMzYzsgYm9yZGVyLXJhZGl1czoxMnB4OyBmb250LXNpemU6MC44ZW07Ij4NCiAgICAgIEF2ZXJhZ2Ug4oaSIDUlDQogICAgPC9zcGFuPg0KICA8L2Rpdj4NCg0KICA8ZGl2PicsIGJvbnVzX3Jvd3MsICc8L2Rpdj4NCg0KICA8ZGl2IHN0eWxlPSJtYXJnaW4tdG9wOjIycHg7IHBhZGRpbmc6MThweCAyMnB4Ow0KICAgICAgICAgICAgICBiYWNrZ3JvdW5kOnJnYmEoMjU1LDI1NSwyNTUsMC4wNCk7IGJvcmRlci1yYWRpdXM6MTBweDsNCiAgICAgICAgICAgICAgYm9yZGVyLWxlZnQ6M3B4IHNvbGlkICNmMzljMTI7Ij4NCiAgICA8cCBzdHlsZT0iY29sb3I6I2IwYjhjODsgbWFyZ2luOjA7IGxpbmUtaGVpZ2h0OjEuODsgZm9udC1zaXplOjAuOWVtOyI+DQogICAgICA8c3Ryb25nIHN0eWxlPSJjb2xvcjojZjM5YzEyOyI+SW50ZXJwcmV0YXRpb246PC9zdHJvbmc+DQogICAgICBCcmFuY2hpbmcgbG9naWMgKGlmLWVsc2UpIGF1dG9tYXRpY2FsbHkgZGV0ZXJtaW5lcyBkaWZmZXJlbnQgYm9udXMgcGVyY2VudGFnZXMgZm9yIGVhY2ggcGVyZm9ybWFuY2UNCiAgICAgIGxldmVsOiAyMCUgZm9yICJWZXJ5IEdvb2QsIiAxMCUgZm9yICJHb29kLCIgYW5kIDUlIGZvciAiQXZlcmFnZS4iIFRoaXMgZGVtb25zdHJhdGVzIGhvdyBidXNpbmVzcw0KICAgICAgZGVjaXNpb25zIGNhbiBiZSB0cmFuc2xhdGVkIGludG8gY29kZSwgZW5zdXJpbmcgY29uc2lzdGVudCBjYWxjdWxhdGlvbnMgYW5kIGF2b2lkaW5nIG1hbnVhbCBlcnJvcnMuDQogICAgICBSZXN1bHRzIGFyZSBkaXNwbGF5ZWQgaW4gYW4gaW5mb3JtYXRpdmUgZm9ybWF0IGZvciBlYXN5IG1hbmFnZW1lbnQgcmV2aWV3Lg0KICAgIDwvcD4NCiAgPC9kaXY+DQo8L2Rpdj4NCicpKQ0KYGBgDQoNCi0tLQ0KDQojIExvb3BzIChGb3IgJiBXaGlsZSkNCg0KKipMb29wcyBPdmVydmlldzoqKiBVc2UgbG9vcHMgdG8gYW5hbHl6ZSB0aGUgZW1wbG95ZWUgZGF0YXNldCB1c2luZyBmb3VyIHRlY2huaXF1ZXM6DQoNCi0gKipmb3IgbG9vcCoqIOKAlCBpdGVyYXRlIG92ZXIgYWxsIGVtcGxveWVlcyB0byBmaWx0ZXIgYnkgc2FsYXJ5DQotICoqd2hpbGUgbG9vcCoqIOKAlCBpdGVyYXRlIHVudGlsIGEgY29uZGl0aW9uIGlzIG1ldA0KLSAqKmJyZWFrKiog4oCUIGV4aXQgYSBsb29wIGVhcmx5IHdoZW4gYSBjb25kaXRpb24gdHJpZ2dlcnMNCi0gKipuZXh0Kiog4oCUIHNraXAgYW4gaXRlcmF0aW9uIGFuZCBjb250aW51ZSB0byB0aGUgbmV4dA0KDQojIyBGb3IgTG9vcA0KDQoqKlRhc2s6KiogVXNlIGEgKipmb3IgbG9vcCoqIHRvIGRpc3BsYXkgZW1wbG95ZWVzIHdpdGggc2FsYXJ5IGdyZWF0ZXIgdGhhbiAqKjYsMDAwKiouDQoNCmBgYHtyIGZvci1sb29wLWNvZGV9DQojIE1lbmdndW5ha2FuIGZvciBsb29wIHVudHVrIG1lbmFtcGlsa2FuIGthcnlhd2FuIGRlbmdhbiBnYWppID4gNjAwMA0KY2F0KCJLYXJ5YXdhbiBkZW5nYW4gZ2FqaSBkaSBhdGFzIDYwMDA6XG4iKQ0KZm9yIChpIGluIDE6bnJvdyhkYXRhKSkgew0KICBpZiAoZGF0YSRTYWxhcnlbaV0gPiA2MDAwKSB7DQogICAgY2F0KHBhc3RlMCgiTmFtZTogIiwgZGF0YSROYW1lW2ldLCAiLCBTYWxhcnk6ICIsIGRhdGEkU2FsYXJ5W2ldLCAiXG4iKSkNCiAgfQ0KfQ0KYGBgDQoNCmBgYHtyIGZvci1sb29wLXZpc3VhbCwgZWNobz1GQUxTRX0NCmZvcl9yb3dzIDwtICIiDQpmb3IgKGkgaW4gMTpucm93KGRhdGEpKSB7DQogIGlmIChkYXRhJFNhbGFyeVtpXSA+IDYwMDApIHsNCiAgICBmb3Jfcm93cyA8LSBwYXN0ZTAoZm9yX3Jvd3MsIHNwcmludGYoJw0KICAgICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsgYWxpZ24taXRlbXM6Y2VudGVyOw0KICAgICAgICAgICAgICAgICAgcGFkZGluZzoxMnB4IDE4cHg7IGJhY2tncm91bmQ6cmdiYSg1MiwxNTIsMjE5LDAuMSk7DQogICAgICAgICAgICAgICAgICBib3JkZXItcmFkaXVzOjhweDsgYm9yZGVyLWxlZnQ6M3B4IHNvbGlkICMzNDk4ZGI7IG1hcmdpbi1ib3R0b206OHB4OyI+DQogICAgICAgIDxkaXYgc3R5bGU9ImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MTBweDsiPg0KICAgICAgICAgIDxzcGFuIHN0eWxlPSJjb2xvcjojMzQ5OGRiOyBmb250LXNpemU6MC45ZW07Ij48L3NwYW4+DQogICAgICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiNmZmY7IGZvbnQtd2VpZ2h0OmJvbGQ7IGZvbnQtc2l6ZTowLjllbTsiPiVzPC9zcGFuPg0KICAgICAgICAgIDxzcGFuIHN0eWxlPSJjb2xvcjojODg4OyBmb250LXNpemU6MC44ZW07Ij7igJQgJXM8L3NwYW4+DQogICAgICAgIDwvZGl2Pg0KICAgICAgICA8c3BhbiBzdHlsZT0iY29sb3I6IzM0OThkYjsgZm9udC13ZWlnaHQ6Ym9sZDsgZm9udC1zaXplOjFlbTsiPiQlczwvc3Bhbj4NCiAgICAgIDwvZGl2PicsDQogICAgICBkYXRhJE5hbWVbaV0sIGRhdGEkUG9zaXRpb25baV0sDQogICAgICBmb3JtYXQoZGF0YSRTYWxhcnlbaV0sIGJpZy5tYXJrPSIsIikNCiAgICApKQ0KICB9DQp9DQoNCkhUTUwocGFzdGUwKCcNCjxkaXYgc3R5bGU9Ig0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjMWExYTJlLCAjMTYyMTNlKTsNCiAgYm9yZGVyLXJhZGl1czoxNHB4OyBwYWRkaW5nOjI0cHggMjhweDsgbWFyZ2luOjIwcHggMDsNCiAgZm9udC1mYW1pbHk6IEdlb3JnaWEsIHNlcmlmOw0KICBib3gtc2hhZG93OiAwIDZweCAyNHB4IHJnYmEoMCwwLDAsMC4zKTsNCiAgYm9yZGVyLXRvcDogM3B4IHNvbGlkICMzNDk4ZGI7DQoiPg0KICA8ZGl2IHN0eWxlPSJkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjEycHg7IG1hcmdpbi1ib3R0b206MTZweDsiPg0KICAgIDxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoNTIsMTUyLDIxOSwwLjIpOyBjb2xvcjojMzQ5OGRiOyBwYWRkaW5nOjVweCAxNHB4Ow0KICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICMzNDk4ZGI7IGJvcmRlci1yYWRpdXM6MTJweDsgZm9udC1zaXplOjAuOGVtOyBmb250LXdlaWdodDpib2xkOyI+DQogICAgICAgRk9SIExPT1ANCiAgICA8L3NwYW4+DQogICAgPHNwYW4gc3R5bGU9ImNvbG9yOiM4ODg7IGZvbnQtc2l6ZTowLjg1ZW07Ij5TYWxhcnkgJmd0OyA2LDAwMDwvc3Bhbj4NCiAgPC9kaXY+DQogICcsIGZvcl9yb3dzLCAnDQogIDxkaXYgc3R5bGU9Im1hcmdpbi10b3A6MThweDsgcGFkZGluZzoxNHB4IDE4cHg7DQogICAgICAgICAgICAgIGJhY2tncm91bmQ6cmdiYSgyNTUsMjU1LDI1NSwwLjA0KTsgYm9yZGVyLXJhZGl1czo4cHg7DQogICAgICAgICAgICAgIGJvcmRlci1sZWZ0OjNweCBzb2xpZCAjMzQ5OGRiOyI+DQogICAgPHAgc3R5bGU9ImNvbG9yOiNiMGI4Yzg7IG1hcmdpbjowOyBsaW5lLWhlaWdodDoxLjc7IGZvbnQtc2l6ZTowLjg4ZW07Ij4NCiAgICAgIDxzdHJvbmcgc3R5bGU9ImNvbG9yOiMzNDk4ZGI7Ij5JbnRlcnByZXRhdGlvbjo8L3N0cm9uZz4NCiAgICAgIFVzaW5nIGEgZm9yIGxvb3AsIHdlIGZpbHRlciBlbXBsb3llZXMgd2l0aCBzYWxhcmllcyBhYm92ZSA2LDAwMCBieSBpdGVyYXRpbmcgZWFjaCByb3cgYW5kDQogICAgICBhcHBseWluZyBhbiBpZiBjb25kaXRpb24uIFRoaXMgdGVjaG5pcXVlIHF1aWNrbHkgaWRlbnRpZmllcyBoaWdoLXBhaWQgZW1wbG95ZWVzIGZvciBmdXJ0aGVyDQogICAgICBldmFsdWF0aW9uIG9yIHBvbGljeSBkZWNpc2lvbnMuDQogICAgPC9wPg0KICA8L2Rpdj4NCjwvZGl2Pg0KJykpDQpgYGANCg0KLS0tDQoNCiMjIFdoaWxlIExvb3ANCg0KKipUYXNrOioqIFVzZSBhICoqd2hpbGUgbG9vcCoqIHRvIGRpc3BsYXkgZW1wbG95ZWVzIHVudGlsIGEgKioiTWFuYWdlciIqKiBpcyBmb3VuZCwgdGhlbiBzdG9wLg0KDQpgYGB7ciB3aGlsZS1sb29wLWNvZGV9DQojIE1lbmdndW5ha2FuIHdoaWxlIGxvb3Agc2FtcGFpIGRpdGVtdWthbiBwb3Npc2kgTWFuYWdlcg0KY2F0KCJNZW5hbXBpbGthbiBrYXJ5YXdhbiBzYW1wYWkgZGl0ZW11a2FuIE1hbmFnZXI6XG4iKQ0KaSA8LSAxDQp3aGlsZSAoaSA8PSBucm93KGRhdGEpKSB7DQogIGthcnlhd2FuIDwtIGRhdGFbaSwgXQ0KICBpZiAoa2FyeWF3YW4kUG9zaXRpb24gPT0gIk1hbmFnZXIiKSB7DQogICAgY2F0KHBhc3RlMCgiTmFtZTogIiwga2FyeWF3YW4kTmFtZSwgIiwgUG9zaXRpb246ICIsIGthcnlhd2FuJFBvc2l0aW9uLCAiIChTdG9wIGhlcmUpXG4iKSkNCiAgICBicmVhaw0KICB9IGVsc2Ugew0KICAgIGNhdChwYXN0ZTAoIk5hbWU6ICIsIGthcnlhd2FuJE5hbWUsICIsIFBvc2l0aW9uOiAiLCBrYXJ5YXdhbiRQb3NpdGlvbiwgIlxuIikpDQogIH0NCiAgaSA8LSBpICsgMQ0KfQ0KYGBgDQoNCmBgYHtyIHdoaWxlLWxvb3AtdmlzdWFsLCBlY2hvPUZBTFNFfQ0Kd2hpbGVfcm93cyA8LSAiIg0KaiA8LSAxDQp3aGlsZSAoaiA8PSBucm93KGRhdGEpKSB7DQogIGlmIChkYXRhJFBvc2l0aW9uW2pdID09ICJNYW5hZ2VyIikgew0KICAgIHdoaWxlX3Jvd3MgPC0gcGFzdGUwKHdoaWxlX3Jvd3MsIHNwcmludGYoJw0KICAgICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsgYWxpZ24taXRlbXM6Y2VudGVyOw0KICAgICAgICAgICAgICAgICAgcGFkZGluZzoxMnB4IDE4cHg7IGJhY2tncm91bmQ6cmdiYSgyMzEsNzYsNjAsMC4xNSk7DQogICAgICAgICAgICAgICAgICBib3JkZXItcmFkaXVzOjhweDsgYm9yZGVyLWxlZnQ6M3B4IHNvbGlkICNlNzRjM2M7IG1hcmdpbi1ib3R0b206OHB4OyI+DQogICAgICAgIDxkaXYgc3R5bGU9ImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MTBweDsiPg0KICAgICAgICAgIDxzcGFuIHN0eWxlPSJjb2xvcjojZTc0YzNjOyI+PC9zcGFuPg0KICAgICAgICAgIDxzcGFuIHN0eWxlPSJjb2xvcjojZTc0YzNjOyBmb250LXdlaWdodDpib2xkOyBmb250LXNpemU6MC45ZW07Ij4lczwvc3Bhbj4NCiAgICAgICAgPC9kaXY+DQogICAgICAgIDxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoMjMxLDc2LDYwLDAuMik7IGNvbG9yOiNlNzRjM2M7IHBhZGRpbmc6M3B4IDEycHg7DQogICAgICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICNlNzRjM2M7IGJvcmRlci1yYWRpdXM6MTBweDsgZm9udC1zaXplOjAuNzhlbTsgZm9udC13ZWlnaHQ6Ym9sZDsiPg0KICAgICAgICAgICVzIOKAlCBTVE9QDQogICAgICAgIDwvc3Bhbj4NCiAgICAgIDwvZGl2PicsDQogICAgICBkYXRhJE5hbWVbal0sIGRhdGEkUG9zaXRpb25bal0NCiAgICApKQ0KICAgIGJyZWFrDQogIH0gZWxzZSB7DQogICAgd2hpbGVfcm93cyA8LSBwYXN0ZTAod2hpbGVfcm93cywgc3ByaW50ZignDQogICAgICA8ZGl2IHN0eWxlPSJkaXNwbGF5OmZsZXg7IGp1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuOyBhbGlnbi1pdGVtczpjZW50ZXI7DQogICAgICAgICAgICAgICAgICBwYWRkaW5nOjEycHggMThweDsgYmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LDAuMDQpOw0KICAgICAgICAgICAgICAgICAgYm9yZGVyLXJhZGl1czo4cHg7IGJvcmRlci1sZWZ0OjNweCBzb2xpZCAjNTU1OyBtYXJnaW4tYm90dG9tOjhweDsiPg0KICAgICAgICA8ZGl2IHN0eWxlPSJkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjEwcHg7Ij4NCiAgICAgICAgICA8c3BhbiBzdHlsZT0iY29sb3I6Izg4ODsiPjwvc3Bhbj4NCiAgICAgICAgICA8c3BhbiBzdHlsZT0iY29sb3I6I2NjYzsgZm9udC1zaXplOjAuOWVtOyI+JXM8L3NwYW4+DQogICAgICAgIDwvZGl2Pg0KICAgICAgICA8c3BhbiBzdHlsZT0iY29sb3I6Izg4ODsgZm9udC1zaXplOjAuODVlbTsiPiVzPC9zcGFuPg0KICAgICAgPC9kaXY+JywNCiAgICAgIGRhdGEkTmFtZVtqXSwgZGF0YSRQb3NpdGlvbltqXQ0KICAgICkpDQogIH0NCiAgaiA8LSBqICsgMQ0KfQ0KDQpIVE1MKHBhc3RlMCgnDQo8ZGl2IHN0eWxlPSINCiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzFhMWEyZSwgIzE2MjEzZSk7DQogIGJvcmRlci1yYWRpdXM6MTRweDsgcGFkZGluZzoyNHB4IDI4cHg7IG1hcmdpbjoyMHB4IDA7DQogIGZvbnQtZmFtaWx5OiBHZW9yZ2lhLCBzZXJpZjsNCiAgYm94LXNoYWRvdzogMCA2cHggMjRweCByZ2JhKDAsMCwwLDAuMyk7DQogIGJvcmRlci10b3A6IDNweCBzb2xpZCAjOWI1OWI2Ow0KIj4NCiAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDoxMnB4OyBtYXJnaW4tYm90dG9tOjE2cHg7Ij4NCiAgICA8c3BhbiBzdHlsZT0iYmFja2dyb3VuZDpyZ2JhKDE1NSw4OSwxODIsMC4yKTsgY29sb3I6IzliNTliNjsgcGFkZGluZzo1cHggMTRweDsNCiAgICAgICAgICAgICAgICAgYm9yZGVyOjFweCBzb2xpZCAjOWI1OWI2OyBib3JkZXItcmFkaXVzOjEycHg7IGZvbnQtc2l6ZTowLjhlbTsgZm9udC13ZWlnaHQ6Ym9sZDsiPg0KICAgICAgV0hJTEUgTE9PUA0KICAgIDwvc3Bhbj4NCiAgICA8c3BhbiBzdHlsZT0iY29sb3I6Izg4ODsgZm9udC1zaXplOjAuODVlbTsiPlVudGlsIE1hbmFnZXIgaXMgZm91bmQ8L3NwYW4+DQogIDwvZGl2Pg0KICAnLCB3aGlsZV9yb3dzLCAnDQogIDxkaXYgc3R5bGU9Im1hcmdpbi10b3A6MThweDsgcGFkZGluZzoxNHB4IDE4cHg7DQogICAgICAgICAgICAgIGJhY2tncm91bmQ6cmdiYSgyNTUsMjU1LDI1NSwwLjA0KTsgYm9yZGVyLXJhZGl1czo4cHg7DQogICAgICAgICAgICAgIGJvcmRlci1sZWZ0OjNweCBzb2xpZCAjOWI1OWI2OyI+DQogICAgPHAgc3R5bGU9ImNvbG9yOiNiMGI4Yzg7IG1hcmdpbjowOyBsaW5lLWhlaWdodDoxLjc7IGZvbnQtc2l6ZTowLjg4ZW07Ij4NCiAgICAgIDxzdHJvbmcgc3R5bGU9ImNvbG9yOiM5YjU5YjY7Ij5JbnRlcnByZXRhdGlvbjo8L3N0cm9uZz4NCiAgICAgIFRoZSB3aGlsZSBsb29wIHByb2Nlc3NlcyBlbXBsb3llZXMgc2VxdWVudGlhbGx5LCBkaXNwbGF5aW5nIGVhY2ggbmFtZSBhbmQgcG9zaXRpb24gdW50aWwgdGhlDQogICAgICAiTWFuYWdlciIgcG9zaXRpb24gaXMgZW5jb3VudGVyZWQuIFRoaXMgcmVmbGVjdHMgcmVhbC13b3JsZCBzY2VuYXJpb3MgbGlrZSBxdWV1ZSBwcm9jZXNzaW5nDQogICAgICB3aGVyZSBkYXRhIGlzIGhhbmRsZWQgdXAgdG8gYSBzcGVjaWZpYyBwb2ludCBiYXNlZCBvbiBkeW5hbWljIGNvbmRpdGlvbnMuDQogICAgPC9wPg0KICA8L2Rpdj4NCjwvZGl2Pg0KJykpDQpgYGANCg0KLS0tDQoNCiMjIEJyZWFrDQoNCioqVGFzazoqKiBVc2UgKipicmVhayoqIHRvIHN0b3AgdGhlIGxvb3AgaW1tZWRpYXRlbHkgd2hlbiBhIHNhbGFyeSBhYm92ZSAqKjEwLDAwMCoqIGlzIGZvdW5kLg0KDQpgYGB7ciBicmVhay1jb2RlfQ0KIyBNZW5nZ3VuYWthbiBicmVhayBrZXRpa2EgbWVuZW11a2FuIGdhamkgZGkgYXRhcyAxMDAwMA0KY2F0KCJNZW5hbXBpbGthbiBrYXJ5YXdhbiBoaW5nZ2EgbWVuZW11a2FuIGdhamkgZGkgYXRhcyAxMCwwMDA6XG4iKQ0KZm9yIChpIGluIDE6bnJvdyhkYXRhKSkgew0KICBpZiAoZGF0YSRTYWxhcnlbaV0gPiAxMDAwMCkgew0KICAgIGNhdChwYXN0ZTAoIihTdG9wcGVkIGJlY2F1c2UgIiwgZGF0YSROYW1lW2ldLCAiIGhhcyBhIHNhbGFyeSBhYm92ZSAxMCwwMDApXG4iKSkNCiAgICBicmVhaw0KICB9IGVsc2Ugew0KICAgIGNhdChwYXN0ZTAoIk5hbWU6ICIsIGRhdGEkTmFtZVtpXSwgIiwgU2FsYXJ5OiAiLCBkYXRhJFNhbGFyeVtpXSwgIlxuIikpDQogIH0NCn0NCmBgYA0KDQpgYGB7ciBicmVhay12aXN1YWwsIGVjaG89RkFMU0V9DQpicmVha19yb3dzIDwtICIiDQpmb3IgKGkgaW4gMTpucm93KGRhdGEpKSB7DQogIGlmIChkYXRhJFNhbGFyeVtpXSA+IDEwMDAwKSB7DQogICAgYnJlYWtfcm93cyA8LSBwYXN0ZTAoYnJlYWtfcm93cywgc3ByaW50ZignDQogICAgICA8ZGl2IHN0eWxlPSJkaXNwbGF5OmZsZXg7IGp1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuOyBhbGlnbi1pdGVtczpjZW50ZXI7DQogICAgICAgICAgICAgICAgICBwYWRkaW5nOjEycHggMThweDsgYmFja2dyb3VuZDpyZ2JhKDIzMSw3Niw2MCwwLjE1KTsNCiAgICAgICAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6OHB4OyBib3JkZXI6MXB4IHNvbGlkICNlNzRjM2M7IG1hcmdpbi1ib3R0b206OHB4OyI+DQogICAgICAgIDxkaXYgc3R5bGU9ImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MTBweDsiPg0KICAgICAgICAgIDxzcGFuIHN0eWxlPSJjb2xvcjojZTc0YzNjOyBmb250LXNpemU6MS4xZW07Ij48L3NwYW4+DQogICAgICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiNlNzRjM2M7IGZvbnQtd2VpZ2h0OmJvbGQ7IGZvbnQtc2l6ZTowLjllbTsiPg0KICAgICAgICAgICAgQlJFQUsg4oCUICVzIGhhcyBzYWxhcnkgYWJvdmUgMTAsMDAwDQogICAgICAgICAgPC9zcGFuPg0KICAgICAgICA8L2Rpdj4NCiAgICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiNlNzRjM2M7IGZvbnQtd2VpZ2h0OmJvbGQ7Ij4kJXM8L3NwYW4+DQogICAgICA8L2Rpdj4nLA0KICAgICAgZGF0YSROYW1lW2ldLA0KICAgICAgZm9ybWF0KGRhdGEkU2FsYXJ5W2ldLCBiaWcubWFyaz0iLCIpDQogICAgKSkNCiAgICBicmVhaw0KICB9IGVsc2Ugew0KICAgIGJyZWFrX3Jvd3MgPC0gcGFzdGUwKGJyZWFrX3Jvd3MsIHNwcmludGYoJw0KICAgICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsgYWxpZ24taXRlbXM6Y2VudGVyOw0KICAgICAgICAgICAgICAgICAgcGFkZGluZzoxMnB4IDE4cHg7IGJhY2tncm91bmQ6cmdiYSgyNTUsMjU1LDI1NSwwLjA0KTsNCiAgICAgICAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6OHB4OyBib3JkZXItbGVmdDozcHggc29saWQgIzU1NTsgbWFyZ2luLWJvdHRvbTo4cHg7Ij4NCiAgICAgICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDoxMHB4OyI+DQogICAgICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiM4ODg7Ij48L3NwYW4+DQogICAgICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiNjY2M7IGZvbnQtc2l6ZTowLjllbTsiPiVzPC9zcGFuPg0KICAgICAgICA8L2Rpdj4NCiAgICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiNhYWE7IGZvbnQtc2l6ZTowLjg4ZW07Ij4kJXM8L3NwYW4+DQogICAgICA8L2Rpdj4nLA0KICAgICAgZGF0YSROYW1lW2ldLA0KICAgICAgZm9ybWF0KGRhdGEkU2FsYXJ5W2ldLCBiaWcubWFyaz0iLCIpDQogICAgKSkNCiAgfQ0KfQ0KDQpIVE1MKHBhc3RlMCgnDQo8ZGl2IHN0eWxlPSINCiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzFhMWEyZSwgIzE2MjEzZSk7DQogIGJvcmRlci1yYWRpdXM6MTRweDsgcGFkZGluZzoyNHB4IDI4cHg7IG1hcmdpbjoyMHB4IDA7DQogIGZvbnQtZmFtaWx5OiBHZW9yZ2lhLCBzZXJpZjsNCiAgYm94LXNoYWRvdzogMCA2cHggMjRweCByZ2JhKDAsMCwwLDAuMyk7DQogIGJvcmRlci10b3A6IDNweCBzb2xpZCAjZTc0YzNjOw0KIj4NCiAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDoxMnB4OyBtYXJnaW4tYm90dG9tOjE2cHg7Ij4NCiAgICA8c3BhbiBzdHlsZT0iYmFja2dyb3VuZDpyZ2JhKDIzMSw3Niw2MCwwLjIpOyBjb2xvcjojZTc0YzNjOyBwYWRkaW5nOjVweCAxNHB4Ow0KICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICNlNzRjM2M7IGJvcmRlci1yYWRpdXM6MTJweDsgZm9udC1zaXplOjAuOGVtOyBmb250LXdlaWdodDpib2xkOyI+DQogICAgICAgQlJFQUsNCiAgICA8L3NwYW4+DQogICAgPHNwYW4gc3R5bGU9ImNvbG9yOiM4ODg7IGZvbnQtc2l6ZTowLjg1ZW07Ij5TdG9wIHdoZW4gU2FsYXJ5ICZndDsgMTAsMDAwPC9zcGFuPg0KICA8L2Rpdj4NCiAgJywgYnJlYWtfcm93cywgJw0KICA8ZGl2IHN0eWxlPSJtYXJnaW4tdG9wOjE4cHg7IHBhZGRpbmc6MTRweCAxOHB4Ow0KICAgICAgICAgICAgICBiYWNrZ3JvdW5kOnJnYmEoMjU1LDI1NSwyNTUsMC4wNCk7IGJvcmRlci1yYWRpdXM6OHB4Ow0KICAgICAgICAgICAgICBib3JkZXItbGVmdDozcHggc29saWQgI2U3NGMzYzsiPg0KICAgIDxwIHN0eWxlPSJjb2xvcjojYjBiOGM4OyBtYXJnaW46MDsgbGluZS1oZWlnaHQ6MS43OyBmb250LXNpemU6MC44OGVtOyI+DQogICAgICA8c3Ryb25nIHN0eWxlPSJjb2xvcjojZTc0YzNjOyI+SW50ZXJwcmV0YXRpb246PC9zdHJvbmc+DQogICAgICBUaGUgYnJlYWsgY29tbWFuZCBoYWx0cyB0aGUgbG9vcCBpbW1lZGlhdGVseSB1cG9uIGZpbmRpbmcgYSBzYWxhcnkgYWJvdmUgMTAsMDAwLCBwcmV2ZW50aW5nDQogICAgICB1bm5lY2Vzc2FyeSBwcm9jZXNzaW5nLiBUaGlzIHRlY2huaXF1ZSBpcyB1c2VmdWwgaW4gZGF0YSByZXRyaWV2YWwgd2hlbiB3ZSBvbmx5IG5lZWQgdG8gcHJvY2Vzcw0KICAgICAgcmVjb3JkcyB1cCB0byBhIHNwZWNpZmljIHRocmVzaG9sZCBvciBjb25kaXRpb24uDQogICAgPC9wPg0KICA8L2Rpdj4NCjwvZGl2Pg0KJykpDQpgYGANCg0KLS0tDQoNCiMjIENvbnRpbnVlIChOZXh0KQ0KDQoqKlRhc2s6KiogVXNlICoqbmV4dCoqIHRvIHNraXAgZW1wbG95ZWVzIHdpdGggKioiQXZlcmFnZSIqKiBwZXJmb3JtYW5jZSBhbmQgY29udGludWUgdG8gdGhlIG5leHQgaXRlcmF0aW9uLg0KDQpgYGB7ciBuZXh0LWNvZGV9DQojIE1lbmdndW5ha2FuIGNvbnRpbnVlIHVudHVrIG1lbGV3YXRrYW4ga2FyeWF3YW4gZGVuZ2FuIHBlcmZvcm1hbmNlICJBdmVyYWdlIg0KY2F0KCJLYXJ5YXdhbiBkZW5nYW4gcGVyZm9ybWEgKHNlbGFpbiBBdmVyYWdlKTpcbiIpDQpza2lwcGVkIDwtIGMoKQ0KDQpmb3IgKGkgaW4gMTpucm93KGRhdGEpKSB7DQogIGlmIChkYXRhJFBlcmZvcm1hbmNlW2ldID09ICJBdmVyYWdlIikgew0KICAgIHNraXBwZWQgPC0gYyhza2lwcGVkLCBkYXRhJE5hbWVbaV0pDQogICAgbmV4dA0KICB9DQogIGNhdChwYXN0ZTAoIk5hbWU6ICIsIGRhdGEkTmFtZVtpXSwgIiwgUGVyZm9ybWFuY2U6ICIsIGRhdGEkUGVyZm9ybWFuY2VbaV0sICJcbiIpKQ0KfQ0KDQppZiAobGVuZ3RoKHNraXBwZWQpID4gMCkgew0KICBjYXQocGFzdGUwKCIoIiwgcGFzdGUoc2tpcHBlZCwgY29sbGFwc2UgPSAiLCAiKSwNCiAgICAgICAgICAgICBpZmVsc2UobGVuZ3RoKHNraXBwZWQpID09IDEsICIgaXMgIiwgIiBhcmUgIiksDQogICAgICAgICAgICAgInNraXBwZWQgYmVjYXVzZSB0aGUgcGVyZm9ybWFuY2UgaXMgXCJBdmVyYWdlXCIpXG4iKSkNCn0NCmBgYA0KDQpgYGB7ciBuZXh0LXZpc3VhbCwgZWNobz1GQUxTRX0NCm5leHRfcm93cyAgPC0gIiINCnNraXBwZWRfdiAgPC0gYygpDQoNCmZvciAoaSBpbiAxOm5yb3coZGF0YSkpIHsNCiAgaWYgKGRhdGEkUGVyZm9ybWFuY2VbaV0gPT0gIkF2ZXJhZ2UiKSB7DQogICAgc2tpcHBlZF92IDwtIGMoc2tpcHBlZF92LCBkYXRhJE5hbWVbaV0pDQogICAgbmV4dF9yb3dzIDwtIHBhc3RlMChuZXh0X3Jvd3MsIHNwcmludGYoJw0KICAgICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsgYWxpZ24taXRlbXM6Y2VudGVyOw0KICAgICAgICAgICAgICAgICAgcGFkZGluZzoxMnB4IDE4cHg7IGJhY2tncm91bmQ6cmdiYSgyMzEsNzYsNjAsMC4wOCk7DQogICAgICAgICAgICAgICAgICBib3JkZXItcmFkaXVzOjhweDsgYm9yZGVyLWxlZnQ6M3B4IHNvbGlkICNlNzRjM2M7DQogICAgICAgICAgICAgICAgICBvcGFjaXR5OjAuNTsgbWFyZ2luLWJvdHRvbTo4cHg7Ij4NCiAgICAgICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDoxMHB4OyI+DQogICAgICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiNlNzRjM2M7IGZvbnQtc2l6ZTowLjllbTsiPjwvc3Bhbj4NCiAgICAgICAgICA8c3BhbiBzdHlsZT0iY29sb3I6I2FhYTsgZm9udC1zdHlsZTppdGFsaWM7IGZvbnQtc2l6ZTowLjg4ZW07IHRleHQtZGVjb3JhdGlvbjpsaW5lLXRocm91Z2g7Ij4lczwvc3Bhbj4NCiAgICAgICAgPC9kaXY+DQogICAgICAgIDxzcGFuIHN0eWxlPSJjb2xvcjojZTc0YzNjOyBmb250LXNpemU6MC43OGVtOyBmb250LXN0eWxlOml0YWxpYzsiPnNraXBwZWQgKEF2ZXJhZ2UpPC9zcGFuPg0KICAgICAgPC9kaXY+JywNCiAgICAgIGRhdGEkTmFtZVtpXQ0KICAgICkpDQogICAgbmV4dA0KICB9DQogIGNvbDMgPC0gaWYgKGRhdGEkUGVyZm9ybWFuY2VbaV0gPT0gIlZlcnkgR29vZCIpICIjMmVjYzcxIiBlbHNlICIjZjFjNDBmIg0KICBuZXh0X3Jvd3MgPC0gcGFzdGUwKG5leHRfcm93cywgc3ByaW50ZignDQogICAgPGRpdiBzdHlsZT0iZGlzcGxheTpmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsgYWxpZ24taXRlbXM6Y2VudGVyOw0KICAgICAgICAgICAgICAgIHBhZGRpbmc6MTJweCAxOHB4OyBiYWNrZ3JvdW5kOnJnYmEoMjU1LDI1NSwyNTUsMC4wNCk7DQogICAgICAgICAgICAgICAgYm9yZGVyLXJhZGl1czo4cHg7IGJvcmRlci1sZWZ0OjNweCBzb2xpZCAlczsgbWFyZ2luLWJvdHRvbTo4cHg7Ij4NCiAgICAgIDxkaXYgc3R5bGU9ImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MTBweDsiPg0KICAgICAgICA8c3BhbiBzdHlsZT0iY29sb3I6JXM7Ij48L3NwYW4+DQogICAgICAgIDxzcGFuIHN0eWxlPSJjb2xvcjojZmZmOyBmb250LXdlaWdodDpib2xkOyBmb250LXNpemU6MC45ZW07Ij4lczwvc3Bhbj4NCiAgICAgIDwvZGl2Pg0KICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiVzOyBmb250LXNpemU6MC44NWVtOyBmb250LXdlaWdodDpib2xkOyI+JXM8L3NwYW4+DQogICAgPC9kaXY+JywNCiAgICBjb2wzLCBjb2wzLCBkYXRhJE5hbWVbaV0sIGNvbDMsIGRhdGEkUGVyZm9ybWFuY2VbaV0NCiAgKSkNCn0NCg0Kc2tpcF9ub3RlIDwtICIiDQppZiAobGVuZ3RoKHNraXBwZWRfdikgPiAwKSB7DQogIHNraXBfbm90ZSA8LSBzcHJpbnRmKCcNCiAgICA8ZGl2IHN0eWxlPSJtYXJnaW4tdG9wOjEwcHg7IHBhZGRpbmc6MTJweCAxOHB4Ow0KICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6cmdiYSgyMzEsNzYsNjAsMC4xKTsgYm9yZGVyLXJhZGl1czo4cHg7DQogICAgICAgICAgICAgICAgYm9yZGVyOjFweCBkYXNoZWQgI2U3NGMzYzsiPg0KICAgICAgPHNwYW4gc3R5bGU9ImNvbG9yOiNlNzRjM2M7IGZvbnQtc2l6ZTowLjg1ZW07IGZvbnQtc3R5bGU6aXRhbGljOyI+DQogICAgICAgICVzICVzIHNraXBwZWQgYmVjYXVzZSBwZXJmb3JtYW5jZSBpcyAiQXZlcmFnZSINCiAgICAgIDwvc3Bhbj4NCiAgICA8L2Rpdj4nLA0KICAgIHBhc3RlKHNraXBwZWRfdiwgY29sbGFwc2U9IiwgIiksDQogICAgaWZlbHNlKGxlbmd0aChza2lwcGVkX3YpID09IDEsICJpcyIsICJhcmUiKQ0KICApDQp9DQoNCkhUTUwocGFzdGUwKCcNCjxkaXYgc3R5bGU9Ig0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjMWExYTJlLCAjMTYyMTNlKTsNCiAgYm9yZGVyLXJhZGl1czoxNHB4OyBwYWRkaW5nOjI0cHggMjhweDsgbWFyZ2luOjIwcHggMDsNCiAgZm9udC1mYW1pbHk6IEdlb3JnaWEsIHNlcmlmOw0KICBib3gtc2hhZG93OiAwIDZweCAyNHB4IHJnYmEoMCwwLDAsMC4zKTsNCiAgYm9yZGVyLXRvcDogM3B4IHNvbGlkICNlNjdlMjI7DQoiPg0KICA8ZGl2IHN0eWxlPSJkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjEycHg7IG1hcmdpbi1ib3R0b206MTZweDsiPg0KICAgIDxzcGFuIHN0eWxlPSJiYWNrZ3JvdW5kOnJnYmEoMjMwLDEyNiwzNCwwLjIpOyBjb2xvcjojZTY3ZTIyOyBwYWRkaW5nOjVweCAxNHB4Ow0KICAgICAgICAgICAgICAgICBib3JkZXI6MXB4IHNvbGlkICNlNjdlMjI7IGJvcmRlci1yYWRpdXM6MTJweDsgZm9udC1zaXplOjAuOGVtOyBmb250LXdlaWdodDpib2xkOyI+DQogICAgICBORVhUIC8gQ09OVElOVUUNCiAgICA8L3NwYW4+DQogICAgPHNwYW4gc3R5bGU9ImNvbG9yOiM4ODg7IGZvbnQtc2l6ZTowLjg1ZW07Ij5Ta2lwIGVtcGxveWVlcyB3aXRoIEF2ZXJhZ2UgcGVyZm9ybWFuY2U8L3NwYW4+DQogIDwvZGl2Pg0KICAnLCBuZXh0X3Jvd3MsIHNraXBfbm90ZSwgJw0KICA8ZGl2IHN0eWxlPSJtYXJnaW4tdG9wOjE4cHg7IHBhZGRpbmc6MTRweCAxOHB4Ow0KICAgICAgICAgICAgICBiYWNrZ3JvdW5kOnJnYmEoMjU1LDI1NSwyNTUsMC4wNCk7IGJvcmRlci1yYWRpdXM6OHB4Ow0KICAgICAgICAgICAgICBib3JkZXItbGVmdDozcHggc29saWQgI2U2N2UyMjsiPg0KICAgIDxwIHN0eWxlPSJjb2xvcjojYjBiOGM4OyBtYXJnaW46MDsgbGluZS1oZWlnaHQ6MS43OyBmb250LXNpemU6MC44OGVtOyI+DQogICAgICA8c3Ryb25nIHN0eWxlPSJjb2xvcjojZTY3ZTIyOyI+SW50ZXJwcmV0YXRpb246PC9zdHJvbmc+DQogICAgICBUaGUgbmV4dCBjb21tYW5kIHNraXBzICJBdmVyYWdlIiBlbXBsb3llZXMgYW5kIHJlY29yZHMgdGhlaXIgbmFtZXMsIGRpc3BsYXlpbmcgb25seSB0aG9zZSB3aXRoDQogICAgICAiR29vZCIgYW5kICJWZXJ5IEdvb2QiIHBlcmZvcm1hbmNlLiBUaGlzIGVsZWdhbnRseSBmaWx0ZXJzIGRhdGEgd2l0aG91dCBhbHRlcmluZyB0aGUgb3JpZ2luYWwNCiAgICAgIHN0cnVjdHVyZSwgYW5kIHRoZSBvbWl0dGVkIG5hbWVzIGFyZSBhdXRvbWF0aWNhbGx5IHJlcG9ydGVkIGF0IHRoZSBlbmQgZm9yIHRyYW5zcGFyZW5jeS4NCiAgICA8L3A+DQogIDwvZGl2Pg0KPC9kaXY+DQonKSkNCmBgYA0KDQo=