Pemograman Ilmu Data

Sintaksis dan Aliran Kontrol

Logo


1 KODE R

2 2.5 Praktikum

2.1 2.5.1 Tujuan

Menentukan tipe data variabel berikut dalam Python dan R:

\[\text{Pengenal}\] \[\text{Nama} \] \[\text{Usia} \] \[\text{Gaji} \] \[\text{Posisi} \] \[\text{Pertunjukan} \]
1 Bagas 25 5000 Staf Bagus
2 Joan 30 7000 Pengawas Sangat bagus
3 Alya 27 6500 Staf Rata-rata
4 Dwi 35 10000 Manajer Bagus
5 Nabil 40 12000 Direktur Sangat bagus

2.1.1 Kode R

# Membuat dataset karyawan sebagai list of # Dataset karyawan dalam bentuk list of lists
employees <- list(
    list(ID = 1, Name = "Bagas", Age = 25, Salary = 5000, Position = "Staff", Performance = "Good"),
    list(ID = 2, Name = "Joan", Age = 30, Salary = 7000, Position = "Supervisor", Performance = "Very Good"),
    list(ID = 3, Name = "Alya", Age = 27, Salary = 6500, Position = "Staff", Performance = "Average"),
    list(ID = 4, Name = "Dwi", Age = 35, Salary = 10000, Position = "Manager", Performance = "Good"),
    list(ID = 5, Name = "Nabil", Age = 40, Salary = 12000, Position = "Director", Performance = "Very Good")
)

2.1.1.1 Penjelasan Kode

  1. Data karyawan disimpan dalam bentuk list of lists.

  2. Setiap karyawan direpresentasikan sebagai list yang berisi atribut seperti ID, Name, Age, Salary, Position, dan Performance.

2.1.2 Menaikkan Gaji Berdasarkan Performa

# 1. Menaikkan gaji berdasarkan performa
cat("Contoh 1: Penyesuaian gaji berdasarkan performa\n")
## Contoh 1: Penyesuaian gaji berdasarkan performa
for (i in seq_along(employees)) {
    if (employees[[i]]$Performance == "Very Good") {
        kenaikan <- employees[[i]]$Salary * 0.10
    } else if (employees[[i]]$Performance == "Good") {
        kenaikan <- employees[[i]]$Salary * 0.05
    } else if (employees[[i]]$Performance == "Average") {
        kenaikan <- employees[[i]]$Salary * 0.02
    } else {
        kenaikan <- employees[[i]]$Salary * 0.01
    }
    employees[[i]]$Salary <- employees[[i]]$Salary + kenaikan
    cat(employees[[i]]$Name, ": Gaji baru =", employees[[i]]$Salary, "\n")
}
## Bagas : Gaji baru = 5250 
## Joan : Gaji baru = 7700 
## Alya : Gaji baru = 6630 
## Dwi : Gaji baru = 10500 
## Nabil : Gaji baru = 13200

2.1.2.1 Penjelasan Kode

  1. Loop for digunakan untuk menelusuri setiap karyawan.

  2. Struktur if-else menentukan kenaikan gaji berdasarkan performa:

  • “Very Good” → Naik 10%

  • “Good” → Naik 5%

  • “Average” → Naik 2%

  • Lainnya → Naik 1%

  1. Gaji karyawan diperbarui dan ditampilkan

2.1.3 Mencari Karyawan dengan Posisi “Director”

# 2. Mencari karyawan dengan posisi "Director"
cat("\nContoh 2: Mencari posisi Director\n")
## 
## Contoh 2: Mencari posisi Director
index <- 1
while (index <= length(employees)) {
    if (employees[[index]]$Position == "Director") {
        cat("Found:", employees[[index]]$Name, "adalah Director\n")
        break
    }
    index <- index + 1
}
## Found: Nabil adalah Director

2.1.3.1 Penjelasan Kode

  1. Loop while digunakan untuk mencari karyawan dengan posisi “Director”.

  2. Jika ditemukan, nama karyawan akan dicetak, lalu loop berhenti menggunakan break.

  3. Jika tidak ditemukan, index bertambah dan loop terus berjalan.

2.1.4 Melewati Pegawai dengan Posisi “Staff”

# 3. Melewati pegawai dengan posisi "Staff"
cat("\nContoh 3: Filter non-staff\n")
## 
## Contoh 3: Filter non-staff
for (emp in employees) {
    if (emp$Position == "Staff") {
        next
    }
    cat(emp$Name, "(", emp$Position, ")\n")
}
## Joan ( Supervisor )
## Dwi ( Manager )
## Nabil ( Director )

2.1.4.1 Penjelasan Kode

  1. Loop for mengecek semua karyawan.

  2. Jika posisi karyawan adalah “Staff”, perintah next akan melewatkan iterasi tersebut.

Karyawan dengan posisi selain “Staff” akan ditampilkan.

2.1.5 Mengelompokkan Karyawan Berdasarkan Usia

# 4. Mengelompokkan karyawan berdasarkan usia
cat("\nContoh 4: Kategori usia\n")
## 
## Contoh 4: Kategori usia
for (emp in employees) {
    if (emp$Age < 30) {
        kategori <- "Muda"
    } else if (emp$Age >= 30 & emp$Age < 40) {
        kategori <- "Dewasa"
    } else {
        kategori <- "Senior"
    }
    cat(emp$Name, ":", kategori, "\n")
}
## Bagas : Muda 
## Joan : Dewasa 
## Alya : Muda 
## Dwi : Dewasa 
## Nabil : Senior

2.1.5.1 Penjelasan Kode

  1. Loop for digunakan untuk mengecek umur setiap karyawan.

  2. if-else menentukan kategori usia:

  • < 30 tahun“Muda”

  • 30 – 39 tahun“Dewasa”

  • >= 40 tahun“Senior”

  1. Hasil kategori usia dicetak.

2.1.6 Mencari Karyawan dengan Gaji > 10K tapi Bukan “Director”

# 5. Mencari karyawan dengan gaji > 10K tapi bukan "Director"
cat("\nContoh 5: Cari karyawan dengan gaji > 10k tapi bukan Director\n")
## 
## Contoh 5: Cari karyawan dengan gaji > 10k tapi bukan Director
counter <- 1
while (counter <= length(employees)) {
    emp <- employees[[counter]]
    if (emp$Position == "Director") {
        counter <- counter + 1
        next
    }
    if (emp$Salary > 10000) {
        cat(emp$Name, "memenuhi kriteria\n")
        break
    }
    counter <- counter + 1
}
## Dwi memenuhi kriteria

2.1.6.1 Penjelasan Kode

  1. Loop while digunakan untuk mencari karyawan dengan gaji lebih dari 10.000.

  2. Jika posisi karyawan adalah “Director”, maka akan dilewati menggunakan next.

  3. Jika ditemukan karyawan dengan gaji > 10K, namanya akan dicetak dan loop berhenti dengan break.

  4. Loop terus berjalan hingga menemukan karyawan yang sesuai atau semua data telah dicek.

2.2 kesimpulan

Kode ini menunjukkan berbagai teknik pemrograman dalam R, seperti:

  1. Looping (for, while) untuk membaca data karyawan.

  2. Conditional Statements (if-else) untuk menentukan kenaikan gaji dan kategori usia.

  3. Break & Continue (next, break) untuk mengontrol alur perulangan.

  4. Pengolahan Data dalam list of lists untuk menyimpan dan memanipulasi informasi karyawan.

2.3 2.5.2 Pernyataan Kondisional

2.3.1 Dataset Karyawan

# Dataset Karyawan
employees <- list(
    list(ID = 1, Name = "Bagas", Age = 25, Salary = 5000, Position = "Staff", Performance = "Good"),
    list(ID = 2, Name = "Joan", Age = 30, Salary = 7000, Position = "Supervisor", Performance = "Very Good"),
    list(ID = 3, Name = "Alya", Age = 27, Salary = 6500, Position = "Staff", Performance = "Average"),
    list(ID = 4, Name = "Dwi", Age = 35, Salary = 10000, Position = "Manager", Performance = "Good"),
    list(ID = 5, Name = "Nabil", Age = 40, Salary = 12000, Position = "Director", Performance = "Very Good")
)

2.3.1.1 Penjelasan Kode

  1. employees adalah list yang berisi daftar karyawan.

  2. Setiap karyawan direpresentasikan sebagai list yang berisi atribut seperti ID, Name, Age, Salary, Position, dan Performance.

  3. Data ini akan digunakan untuk perhitungan bonus.

2.3.2

# Menghitung dan menampilkan bonus berdasarkan performa
cat("Bonus Karyawan:\n")
## Bonus Karyawan:
for (emp in employees) {
    if (emp$Performance == "Very Good") {
        bonus <- emp$Salary * 0.20  # 20% untuk performa Very Good
    } else if (emp$Performance == "Good") {
        bonus <- emp$Salary * 0.10  # 10% untuk performa Good
    } else if (emp$Performance == "Average") {
        bonus <- emp$Salary * 0.05  # 5% untuk performa Average
    } else {
        bonus <- 0  # Tidak ada bonus untuk performa lainnya
    }
    
    cat("Name:", emp$Name, ", Bonus:", format(bonus, nsmall = 2), "\n")
}
## Name: Bagas , Bonus: 500.00 
## Name: Joan , Bonus: 1400.00 
## Name: Alya , Bonus: 325.00 
## Name: Dwi , Bonus: 1000.00 
## Name: Nabil , Bonus: 2400.00

2.3.2.1 Penjelasan Kode

  1. cat(“Bonus Karyawan:”) → Menampilkan judul sebelum daftar bonus karyawan.

  2. Loop for → Menelusuri setiap karyawan dalam list employees.

  3. if-else → Menentukan besar bonus berdasarkan kategori performa:

  • “Very Good” → Bonus 20% dari gaji.

  • “Good” → Bonus 10% dari gaji.

  • “Average” → Bonus 5% dari gaji.

  • Kategori lainnya → Bonus 0.

  1. format(bonus, nsmall = 2) → Menampilkan bonus dengan dua angka desimal untuk format yang lebih rapi.

  2. cat() → Digunakan untuk mencetak hasil dengan format “Name: Nama, Bonus: Bonus”.

2.4 Kesimpulan

Kode ini menghitung bonus karyawan berdasarkan performa mereka dengan menggunakan:

  1. Loop for untuk membaca semua karyawan.

  2. Struktur if-else untuk menentukan besar bonus berdasarkan performa.

  3. cat() untuk mencetak hasil dengan format yang rapi dan mudah dibaca.

2.5 2.5.3 Perulangan (For & While)

2.5.1 Gunakan for loop untuk membuat daftar karyawan dengan gaji lebih dari 6000

# Dataset Karyawan
employees <- list(
    list(ID = 1, Name = "Bagas", Age = 25, Salary = 5000, Position = "Staff", Performance = "Good"),
    list(ID = 2, Name = "Joan", Age = 30, Salary = 7000, Position = "Supervisor", Performance = "Very Good"),
    list(ID = 3, Name = "Alya", Age = 27, Salary = 6500, Position = "Staff", Performance = "Average"),
    list(ID = 4, Name = "Dwi", Age = 35, Salary = 10000, Position = "Manager", Performance = "Good"),
    list(ID = 5, Name = "Nabil", Age = 40, Salary = 12000, Position = "Director", Performance = "Very Good")
)

# 1. Menampilkan karyawan dengan gaji lebih dari 6000
cat("Karyawan dengan gaji lebih dari 6000:\n")
## Karyawan dengan gaji lebih dari 6000:
for (emp in employees) {
    if (emp$Salary > 6000) {
        cat("Name:", emp$Name, ", Salary:", emp$Salary, "\n")
    }
}
## Name: Joan , Salary: 7000 
## Name: Alya , Salary: 6500 
## Name: Dwi , Salary: 10000 
## Name: Nabil , Salary: 12000

2.5.1.1 Penjelasan Kode

  1. Loop for membaca semua data karyawan.

  2. if (emp$Salary > 6000) mengecek apakah gaji karyawan lebih dari 6000.

  3. Jika kondisi terpenuhi, nama dan gaji dicetak menggunakan cat().

2.5.2 Gunakan while loop untuk menampilkan karyawan hingga “Manager” ditemukan

# 2. Menampilkan karyawan hingga menemukan Manager
cat("\nMenampilkan karyawan hingga menemukan Manager:\n")
## 
## Menampilkan karyawan hingga menemukan Manager:
index <- 1
while (index <= length(employees)) {
    emp <- employees[[index]]
    cat("Name:", emp$Name, ", Position:", emp$Position, "\n")
    
    if (emp$Position == "Manager") {
        cat("(Stop here)\n")  # Memberi tahu bahwa loop berhenti
        break  # Keluar dari loop setelah menemukan Manager
    }
    index <- index + 1
}
## Name: Bagas , Position: Staff 
## Name: Joan , Position: Supervisor 
## Name: Alya , Position: Staff 
## Name: Dwi , Position: Manager 
## (Stop here)

2.5.2.1 Penjelasan Kode

  1. while (index <= length(employees)) menjalankan loop selama indeks dalam batas panjang daftar.

  2. cat() mencetak nama dan posisi karyawan.

  3. Jika jabatan “Manager” ditemukan, teks “(Stop here)” ditampilkan, dan loop berhenti dengan break.

2.5.3 Gunakan break untuk menghentikan loop saat menemukan gaji > 10.000

# 3. Menampilkan karyawan hingga menemukan gaji di atas 10.000
cat("\nMenampilkan karyawan hingga menemukan gaji di atas 10.000:\n")
## 
## Menampilkan karyawan hingga menemukan gaji di atas 10.000:
for (emp in employees) {
    if (emp$Salary > 10000) {
        cat("(Stopped because", emp$Name, "has a salary above 10,000)\n")
        break  # Menghentikan loop setelah menemukan gaji > 10.000
    }
    cat("Name:", emp$Name, ", Salary:", emp$Salary, "\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)

2.5.3.1 Penjelasan Kode

  1. Loop for membaca semua karyawan.

  2. Jika gaji lebih dari 10.000, teks pemberhentian ditampilkan, dan loop berhenti dengan break.

  3. Sebelum itu, semua karyawan dengan gaji di bawah 10.000 tetap ditampilkan.

2.5.4 Gunakan next untuk melewati karyawan dengan performa “Average”

# 4. Menampilkan karyawan dengan mengabaikan performa 'Average'
cat("\nMenampilkan karyawan dengan mengabaikan performa 'Average':\n")
## 
## Menampilkan karyawan dengan mengabaikan performa 'Average':
skipped <- ""  # Variabel untuk menyimpan info karyawan yang dilewati

for (emp in employees) {
    if (emp$Performance == "Average") {
        skipped <- paste("(", emp$Name, "is skipped because the performance is 'Average')")  
        next  # Lewati iterasi jika performa "Average"
    }
    cat("Name:", emp$Name, ", Performance:", emp$Performance, "\n")
}
## Name: Bagas , Performance: Good 
## Name: Joan , Performance: Very Good 
## Name: Dwi , Performance: Good 
## Name: Nabil , Performance: Very Good
cat(skipped, "\n")  # Menampilkan informasi karyawan yang dilewati
## ( Alya is skipped because the performance is 'Average')

2.5.4.1 Penjelasan Kode

  1. Loop for membaca semua karyawan.

  2. Jika performa “Average”, variabel skipped menyimpan teks bahwa karyawan dilewati.

  3. next digunakan untuk melewati iterasi, sehingga data karyawan tersebut tidak dicetak.

  4. Setelah loop selesai, teks skipped ditampilkan untuk memberi tahu siapa yang dilewati.

2.6 Kesimpulan

  1. Loop for untuk iterasi data:
  • Digunakan untuk menelusuri seluruh daftar karyawan.

  • Menerapkan kondisi untuk menyaring data, seperti menampilkan karyawan dengan gaji lebih dari 6000.

  1. Loop while untuk membaca data secara bertahap:
  • Digunakan untuk menampilkan karyawan satu per satu hingga menemukan karyawan dengan jabatan “Manager”, lalu berhenti.
  1. Penggunaan break dalam loop:
  • Digunakan untuk menghentikan iterasi lebih awal ketika syarat tertentu terpenuhi.

  • Contoh: Jika ada karyawan dengan gaji lebih dari 10.000, loop langsung dihentikan.

  1. Penggunaan next untuk melewati iterasi:
  • Digunakan untuk melewati karyawan dengan performa “Average”, sehingga mereka tidak ditampilkan dalam hasil akhir.
LS0tDQp0aXRsZTogIlBlbW9ncmFtYW4gSWxtdSBEYXRhIg0Kc3VidGl0bGU6ICJTaW50YWtzaXMgZGFuIEFsaXJhbiBLb250cm9sIg0KYXV0aG9yOiANCiAgLSAiRHdpIFNyaSBZYW50aSBNYW51bGxhbmciDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNzczogIkM6L1VzZXJzL0R3aSBNYW51bGxhbmcvRG93bmxvYWRzL3N0eWxlLmNzcyINCi0tLQ0KPGltZyBpZD0ibG9nby11dGFtYSIgc3JjPSJDOi9Vc2Vycy9Ed2kgTWFudWxsYW5nL1BpY3R1cmVzL0NhbWVyYSBSb2xsL2R3aS5qcGciIGFsdD0iTG9nbyIgc3R5bGU9IndpZHRoOjIwMHB4OyBkaXNwbGF5OiBibG9jazsgbWFyZ2luOiBhdXRvOyI+DQoNCi0tLQ0KIyBLT0RFIFINCg0KIyAqKjIuNSBQcmFrdGlrdW0gKioNCg0KIyMgMi41LjEgVHVqdWFuDQoNCk1lbmVudHVrYW4gdGlwZSBkYXRhIHZhcmlhYmVsIGJlcmlrdXQgZGFsYW0gUHl0aG9uIGRhbiBSOg0KDQoNCnwgJCRcdGV4dHtQZW5nZW5hbH0kJHwgJCRcdGV4dHtOYW1hfSAkJHwkJFx0ZXh0e1VzaWF9ICQkfCQkXHRleHR7R2FqaX0gJCR8JCRcdGV4dHtQb3Npc2l9ICQkfCQkXHRleHR7UGVydHVuanVrYW59ICQkfA0KfDotLS0tLS0tLS0tLTp8Oi0tLS0tLS06fDotLS0tLS0tOnw6LS0tLS0tLTp8Oi0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tOnwNCnwxICAgICAgICAgICAgfEJhZ2FzICAgIHwyNSAgICAgICB8NTAwMCAgICAgfFN0YWYgICAgICAgfEJhZ3VzICAgICAgICAgICB8DQp8MiAgICAgICAgICAgIHxKb2FuICAgICB8MzAgICAgICAgfDcwMDAgICAgIHxQZW5nYXdhcyAgIHxTYW5nYXQgYmFndXMgICAgfCANCnwzICAgICAgICAgICAgfEFseWEgICAgIHwyNyAgICAgICB8NjUwMCAgICAgfFN0YWYgICAgICAgfFJhdGEtcmF0YSAgICAgICB8DQp8NCAgICAgICAgICAgIHxEd2kgICAgICB8MzUgICAgICAgfDEwMDAwICAgIHxNYW5hamVyICAgIHxCYWd1cyAgICAgICAgICAgfA0KfDUgICAgICAgICAgICB8TmFiaWwgICAgfDQwICAgICAgIHwxMjAwMCAgICB8RGlyZWt0dXIgICB8U2FuZ2F0IGJhZ3VzICAgIHwgIA0KDQoNCiMjIyBLb2RlIFINCg0KYGBge3IsICBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9VFJVRSwgZWNobz1UUlVFfQ0KDQojIE1lbWJ1YXQgZGF0YXNldCBrYXJ5YXdhbiBzZWJhZ2FpIGxpc3Qgb2YgIyBEYXRhc2V0IGthcnlhd2FuIGRhbGFtIGJlbnR1ayBsaXN0IG9mIGxpc3RzDQplbXBsb3llZXMgPC0gbGlzdCgNCiAgICBsaXN0KElEID0gMSwgTmFtZSA9ICJCYWdhcyIsIEFnZSA9IDI1LCBTYWxhcnkgPSA1MDAwLCBQb3NpdGlvbiA9ICJTdGFmZiIsIFBlcmZvcm1hbmNlID0gIkdvb2QiKSwNCiAgICBsaXN0KElEID0gMiwgTmFtZSA9ICJKb2FuIiwgQWdlID0gMzAsIFNhbGFyeSA9IDcwMDAsIFBvc2l0aW9uID0gIlN1cGVydmlzb3IiLCBQZXJmb3JtYW5jZSA9ICJWZXJ5IEdvb2QiKSwNCiAgICBsaXN0KElEID0gMywgTmFtZSA9ICJBbHlhIiwgQWdlID0gMjcsIFNhbGFyeSA9IDY1MDAsIFBvc2l0aW9uID0gIlN0YWZmIiwgUGVyZm9ybWFuY2UgPSAiQXZlcmFnZSIpLA0KICAgIGxpc3QoSUQgPSA0LCBOYW1lID0gIkR3aSIsIEFnZSA9IDM1LCBTYWxhcnkgPSAxMDAwMCwgUG9zaXRpb24gPSAiTWFuYWdlciIsIFBlcmZvcm1hbmNlID0gIkdvb2QiKSwNCiAgICBsaXN0KElEID0gNSwgTmFtZSA9ICJOYWJpbCIsIEFnZSA9IDQwLCBTYWxhcnkgPSAxMjAwMCwgUG9zaXRpb24gPSAiRGlyZWN0b3IiLCBQZXJmb3JtYW5jZSA9ICJWZXJ5IEdvb2QiKQ0KKQ0KDQpgYGANCiMjIyMgUGVuamVsYXNhbiBLb2RlDQoNCjEuIERhdGEga2FyeWF3YW4gZGlzaW1wYW4gZGFsYW0gYmVudHVrICoqbGlzdCBvZiBsaXN0cyoqLg0KDQoyLiBTZXRpYXAga2FyeWF3YW4gZGlyZXByZXNlbnRhc2lrYW4gc2ViYWdhaSBsaXN0IHlhbmcgYmVyaXNpIGF0cmlidXQgc2VwZXJ0aSAqSUQqLCAqTmFtZSosICpBZ2UqLCAqU2FsYXJ5KiwgKlBvc2l0aW9uKiwgZGFuICpQZXJmb3JtYW5jZSouDQoNCiMjIyBNZW5haWtrYW4gR2FqaSBCZXJkYXNhcmthbiBQZXJmb3JtYQ0KDQpgYGB7ciwgIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFLCBlY2hvPVRSVUV9DQoNCiMgMS4gTWVuYWlra2FuIGdhamkgYmVyZGFzYXJrYW4gcGVyZm9ybWENCmNhdCgiQ29udG9oIDE6IFBlbnllc3VhaWFuIGdhamkgYmVyZGFzYXJrYW4gcGVyZm9ybWFcbiIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGVtcGxveWVlcykpIHsNCiAgICBpZiAoZW1wbG95ZWVzW1tpXV0kUGVyZm9ybWFuY2UgPT0gIlZlcnkgR29vZCIpIHsNCiAgICAgICAga2VuYWlrYW4gPC0gZW1wbG95ZWVzW1tpXV0kU2FsYXJ5ICogMC4xMA0KICAgIH0gZWxzZSBpZiAoZW1wbG95ZWVzW1tpXV0kUGVyZm9ybWFuY2UgPT0gIkdvb2QiKSB7DQogICAgICAgIGtlbmFpa2FuIDwtIGVtcGxveWVlc1tbaV1dJFNhbGFyeSAqIDAuMDUNCiAgICB9IGVsc2UgaWYgKGVtcGxveWVlc1tbaV1dJFBlcmZvcm1hbmNlID09ICJBdmVyYWdlIikgew0KICAgICAgICBrZW5haWthbiA8LSBlbXBsb3llZXNbW2ldXSRTYWxhcnkgKiAwLjAyDQogICAgfSBlbHNlIHsNCiAgICAgICAga2VuYWlrYW4gPC0gZW1wbG95ZWVzW1tpXV0kU2FsYXJ5ICogMC4wMQ0KICAgIH0NCiAgICBlbXBsb3llZXNbW2ldXSRTYWxhcnkgPC0gZW1wbG95ZWVzW1tpXV0kU2FsYXJ5ICsga2VuYWlrYW4NCiAgICBjYXQoZW1wbG95ZWVzW1tpXV0kTmFtZSwgIjogR2FqaSBiYXJ1ID0iLCBlbXBsb3llZXNbW2ldXSRTYWxhcnksICJcbiIpDQp9DQoNCg0KYGBgDQojIyMjIFBlbmplbGFzYW4gS29kZQ0KDQoxLiAqKkxvb3AqKiAqZm9yKiBkaWd1bmFrYW4gdW50dWsgbWVuZWx1c3VyaSBzZXRpYXAga2FyeWF3YW4uDQoNCjIuIFN0cnVrdHVyICppZi1lbHNlKiBtZW5lbnR1a2FuIGtlbmFpa2FuIGdhamkgYmVyZGFzYXJrYW4gcGVyZm9ybWE6DQoNCi0gIlZlcnkgR29vZCIg4oaSIE5haWsgKjEwJSoNCg0KLSAiR29vZCIg4oaSIE5haWsgKjUlKg0KDQotICJBdmVyYWdlIiDihpIgTmFpayAqMiUqDQoNCi0gTGFpbm55YSDihpIgTmFpayAqMSUqDQoNCjMuIEdhamkga2FyeWF3YW4gZGlwZXJiYXJ1aSBkYW4gZGl0YW1waWxrYW4NCg0KIyMjIE1lbmNhcmkgS2FyeWF3YW4gZGVuZ2FuIFBvc2lzaSAiRGlyZWN0b3IiDQoNCmBgYHtyLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9VFJVRSwgZWNobz1UUlVFfQ0KDQojIDIuIE1lbmNhcmkga2FyeWF3YW4gZGVuZ2FuIHBvc2lzaSAiRGlyZWN0b3IiDQpjYXQoIlxuQ29udG9oIDI6IE1lbmNhcmkgcG9zaXNpIERpcmVjdG9yXG4iKQ0KaW5kZXggPC0gMQ0Kd2hpbGUgKGluZGV4IDw9IGxlbmd0aChlbXBsb3llZXMpKSB7DQogICAgaWYgKGVtcGxveWVlc1tbaW5kZXhdXSRQb3NpdGlvbiA9PSAiRGlyZWN0b3IiKSB7DQogICAgICAgIGNhdCgiRm91bmQ6IiwgZW1wbG95ZWVzW1tpbmRleF1dJE5hbWUsICJhZGFsYWggRGlyZWN0b3JcbiIpDQogICAgICAgIGJyZWFrDQogICAgfQ0KICAgIGluZGV4IDwtIGluZGV4ICsgMQ0KfQ0KDQpgYGANCiMjIyMgUGVuamVsYXNhbiBLb2RlDQoNCjEuICoqTG9vcCoqICp3aGlsZSogZGlndW5ha2FuIHVudHVrIG1lbmNhcmkga2FyeWF3YW4gZGVuZ2FuIHBvc2lzaSAqIkRpcmVjdG9yIiouDQoNCjIuIEppa2EgZGl0ZW11a2FuLCBuYW1hIGthcnlhd2FuIGFrYW4gZGljZXRhaywgbGFsdSBsb29wIGJlcmhlbnRpIG1lbmdndW5ha2FuICpicmVhayouDQoNCjMuIEppa2EgdGlkYWsgZGl0ZW11a2FuLCBpbmRleCBiZXJ0YW1iYWggZGFuIGxvb3AgdGVydXMgYmVyamFsYW4uDQoNCiMjIyBNZWxld2F0aSBQZWdhd2FpIGRlbmdhbiBQb3Npc2kgIlN0YWZmIg0KDQpgYGB7ciwgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPVRSVUUsIGVjaG89VFJVRX0NCg0KIyAzLiBNZWxld2F0aSBwZWdhd2FpIGRlbmdhbiBwb3Npc2kgIlN0YWZmIg0KY2F0KCJcbkNvbnRvaCAzOiBGaWx0ZXIgbm9uLXN0YWZmXG4iKQ0KZm9yIChlbXAgaW4gZW1wbG95ZWVzKSB7DQogICAgaWYgKGVtcCRQb3NpdGlvbiA9PSAiU3RhZmYiKSB7DQogICAgICAgIG5leHQNCiAgICB9DQogICAgY2F0KGVtcCROYW1lLCAiKCIsIGVtcCRQb3NpdGlvbiwgIilcbiIpDQp9DQoNCmBgYA0KDQojIyMjIFBlbmplbGFzYW4gS29kZQ0KDQoxLiAqKkxvb3AqKiAqZm9yKiBtZW5nZWNlayBzZW11YSBrYXJ5YXdhbi4NCg0KMi4gSmlrYSBwb3Npc2kga2FyeWF3YW4gYWRhbGFoICoiU3RhZmYiKiwgcGVyaW50YWggKm5leHQqIGFrYW4gbWVsZXdhdGthbiBpdGVyYXNpIHRlcnNlYnV0Lg0KDQpLYXJ5YXdhbiBkZW5nYW4gcG9zaXNpIHNlbGFpbiAqIlN0YWZmIiogYWthbiBkaXRhbXBpbGthbi4NCg0KIyMjIE1lbmdlbG9tcG9ra2FuIEthcnlhd2FuIEJlcmRhc2Fya2FuIFVzaWENCg0KYGBge3IsIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFLCBlY2hvPVRSVUV9DQoNCiMgNC4gTWVuZ2Vsb21wb2trYW4ga2FyeWF3YW4gYmVyZGFzYXJrYW4gdXNpYQ0KY2F0KCJcbkNvbnRvaCA0OiBLYXRlZ29yaSB1c2lhXG4iKQ0KZm9yIChlbXAgaW4gZW1wbG95ZWVzKSB7DQogICAgaWYgKGVtcCRBZ2UgPCAzMCkgew0KICAgICAgICBrYXRlZ29yaSA8LSAiTXVkYSINCiAgICB9IGVsc2UgaWYgKGVtcCRBZ2UgPj0gMzAgJiBlbXAkQWdlIDwgNDApIHsNCiAgICAgICAga2F0ZWdvcmkgPC0gIkRld2FzYSINCiAgICB9IGVsc2Ugew0KICAgICAgICBrYXRlZ29yaSA8LSAiU2VuaW9yIg0KICAgIH0NCiAgICBjYXQoZW1wJE5hbWUsICI6Iiwga2F0ZWdvcmksICJcbiIpDQp9DQoNCg0KYGBgDQojIyMjIFBlbmplbGFzYW4gS29kZQ0KDQoxLiAqKkxvb3AqKiAqZm9yKiBkaWd1bmFrYW4gdW50dWsgbWVuZ2VjZWsgdW11ciBzZXRpYXAga2FyeWF3YW4uDQoNCjIuICppZi1lbHNlKiBtZW5lbnR1a2FuIGthdGVnb3JpIHVzaWE6DQoNCi0gKjwgMzAgdGFodW4qIOKGkiAqIk11ZGEiKg0KDQotICozMCDigJMgMzkgdGFodW4qIOKGkiAqIkRld2FzYSIqDQoNCi0gKj49IDQwIHRhaHVuKiDihpIgKiJTZW5pb3IiKg0KDQozLiBIYXNpbCBrYXRlZ29yaSB1c2lhIGRpY2V0YWsuDQoNCiMjIyBNZW5jYXJpIEthcnlhd2FuIGRlbmdhbiBHYWppID4gMTBLIHRhcGkgQnVrYW4gIkRpcmVjdG9yIg0KDQpgYGB7ciwgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPVRSVUUsIGVjaG89VFJVRX0NCiMgNS4gTWVuY2FyaSBrYXJ5YXdhbiBkZW5nYW4gZ2FqaSA+IDEwSyB0YXBpIGJ1a2FuICJEaXJlY3RvciINCmNhdCgiXG5Db250b2ggNTogQ2FyaSBrYXJ5YXdhbiBkZW5nYW4gZ2FqaSA+IDEwayB0YXBpIGJ1a2FuIERpcmVjdG9yXG4iKQ0KY291bnRlciA8LSAxDQp3aGlsZSAoY291bnRlciA8PSBsZW5ndGgoZW1wbG95ZWVzKSkgew0KICAgIGVtcCA8LSBlbXBsb3llZXNbW2NvdW50ZXJdXQ0KICAgIGlmIChlbXAkUG9zaXRpb24gPT0gIkRpcmVjdG9yIikgew0KICAgICAgICBjb3VudGVyIDwtIGNvdW50ZXIgKyAxDQogICAgICAgIG5leHQNCiAgICB9DQogICAgaWYgKGVtcCRTYWxhcnkgPiAxMDAwMCkgew0KICAgICAgICBjYXQoZW1wJE5hbWUsICJtZW1lbnVoaSBrcml0ZXJpYVxuIikNCiAgICAgICAgYnJlYWsNCiAgICB9DQogICAgY291bnRlciA8LSBjb3VudGVyICsgMQ0KfQ0KDQpgYGANCiMjIyMgUGVuamVsYXNhbiBLb2RlDQoNCjEuICoqTG9vcCoqICp3aGlsZSogZGlndW5ha2FuIHVudHVrIG1lbmNhcmkga2FyeWF3YW4gZGVuZ2FuIGdhamkgbGViaWggZGFyaSAxMC4wMDAuDQoNCjIuIEppa2EgcG9zaXNpIGthcnlhd2FuIGFkYWxhaCAqIkRpcmVjdG9yIiosIG1ha2EgYWthbiBkaWxld2F0aSBtZW5nZ3VuYWthbiAqbmV4dCouDQoNCjMuIEppa2EgZGl0ZW11a2FuIGthcnlhd2FuIGRlbmdhbiBnYWppID4gMTBLLCBuYW1hbnlhIGFrYW4gZGljZXRhayBkYW4gbG9vcCBiZXJoZW50aSBkZW5nYW4gKmJyZWFrKi4NCg0KNC4gTG9vcCB0ZXJ1cyBiZXJqYWxhbiBoaW5nZ2EgbWVuZW11a2FuIGthcnlhd2FuIHlhbmcgc2VzdWFpIGF0YXUgc2VtdWEgZGF0YSB0ZWxhaCBkaWNlay4NCg0KDQojIyBrZXNpbXB1bGFuIA0KDQpLb2RlIGluaSBtZW51bmp1a2thbiBiZXJiYWdhaSB0ZWtuaWsgcGVtcm9ncmFtYW4gZGFsYW0gKipSKiosIHNlcGVydGk6DQoNCjEuICoqTG9vcGluZyoqICgqZm9yKiwgKndoaWxlKikgdW50dWsgbWVtYmFjYSBkYXRhIGthcnlhd2FuLg0KDQoyLiAqKkNvbmRpdGlvbmFsIFN0YXRlbWVudHMqKiAoKmlmLWVsc2UqKSB1bnR1ayBtZW5lbnR1a2FuIGtlbmFpa2FuIGdhamkgZGFuIGthdGVnb3JpIHVzaWEuDQoNCjMuICoqQnJlYWsgJiBDb250aW51ZSoqICgqbmV4dCosICpicmVhayopIHVudHVrIG1lbmdvbnRyb2wgYWx1ciBwZXJ1bGFuZ2FuLg0KDQo0LiAqKlBlbmdvbGFoYW4gRGF0YSBkYWxhbSoqICpsaXN0IG9mIGxpc3RzKiB1bnR1ayBtZW55aW1wYW4gZGFuIG1lbWFuaXB1bGFzaSBpbmZvcm1hc2kga2FyeWF3YW4uDQoNCg0KIyMgMi41LjIgUGVybnlhdGFhbiBLb25kaXNpb25hbA0KDQojIyMgRGF0YXNldCBLYXJ5YXdhbg0KDQpgYGB7ciwgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPVRSVUUsIGVjaG89VFJVRX0NCiMgRGF0YXNldCBLYXJ5YXdhbg0KZW1wbG95ZWVzIDwtIGxpc3QoDQogICAgbGlzdChJRCA9IDEsIE5hbWUgPSAiQmFnYXMiLCBBZ2UgPSAyNSwgU2FsYXJ5ID0gNTAwMCwgUG9zaXRpb24gPSAiU3RhZmYiLCBQZXJmb3JtYW5jZSA9ICJHb29kIiksDQogICAgbGlzdChJRCA9IDIsIE5hbWUgPSAiSm9hbiIsIEFnZSA9IDMwLCBTYWxhcnkgPSA3MDAwLCBQb3NpdGlvbiA9ICJTdXBlcnZpc29yIiwgUGVyZm9ybWFuY2UgPSAiVmVyeSBHb29kIiksDQogICAgbGlzdChJRCA9IDMsIE5hbWUgPSAiQWx5YSIsIEFnZSA9IDI3LCBTYWxhcnkgPSA2NTAwLCBQb3NpdGlvbiA9ICJTdGFmZiIsIFBlcmZvcm1hbmNlID0gIkF2ZXJhZ2UiKSwNCiAgICBsaXN0KElEID0gNCwgTmFtZSA9ICJEd2kiLCBBZ2UgPSAzNSwgU2FsYXJ5ID0gMTAwMDAsIFBvc2l0aW9uID0gIk1hbmFnZXIiLCBQZXJmb3JtYW5jZSA9ICJHb29kIiksDQogICAgbGlzdChJRCA9IDUsIE5hbWUgPSAiTmFiaWwiLCBBZ2UgPSA0MCwgU2FsYXJ5ID0gMTIwMDAsIFBvc2l0aW9uID0gIkRpcmVjdG9yIiwgUGVyZm9ybWFuY2UgPSAiVmVyeSBHb29kIikNCikNCmBgYA0KDQojIyMjIFBlbmplbGFzYW4gS29kZQ0KDQoxLiAqZW1wbG95ZWVzKiBhZGFsYWggKipsaXN0KiogeWFuZyBiZXJpc2kgZGFmdGFyIGthcnlhd2FuLg0KDQoyLiBTZXRpYXAga2FyeWF3YW4gZGlyZXByZXNlbnRhc2lrYW4gc2ViYWdhaSBsaXN0IHlhbmcgYmVyaXNpIGF0cmlidXQgc2VwZXJ0aSAqSUQqLCAqTmFtZSosICpBZ2UqLCAqU2FsYXJ5KiwgKlBvc2l0aW9uKiwgZGFuICpQZXJmb3JtYW5jZSouDQoNCjMuIERhdGEgaW5pIGFrYW4gZGlndW5ha2FuIHVudHVrIHBlcmhpdHVuZ2FuIGJvbnVzLg0KDQojIyMNCg0KYGBge3IsIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFLCBlY2hvPVRSVUV9DQojIE1lbmdoaXR1bmcgZGFuIG1lbmFtcGlsa2FuIGJvbnVzIGJlcmRhc2Fya2FuIHBlcmZvcm1hDQpjYXQoIkJvbnVzIEthcnlhd2FuOlxuIikNCmZvciAoZW1wIGluIGVtcGxveWVlcykgew0KICAgIGlmIChlbXAkUGVyZm9ybWFuY2UgPT0gIlZlcnkgR29vZCIpIHsNCiAgICAgICAgYm9udXMgPC0gZW1wJFNhbGFyeSAqIDAuMjAgICMgMjAlIHVudHVrIHBlcmZvcm1hIFZlcnkgR29vZA0KICAgIH0gZWxzZSBpZiAoZW1wJFBlcmZvcm1hbmNlID09ICJHb29kIikgew0KICAgICAgICBib251cyA8LSBlbXAkU2FsYXJ5ICogMC4xMCAgIyAxMCUgdW50dWsgcGVyZm9ybWEgR29vZA0KICAgIH0gZWxzZSBpZiAoZW1wJFBlcmZvcm1hbmNlID09ICJBdmVyYWdlIikgew0KICAgICAgICBib251cyA8LSBlbXAkU2FsYXJ5ICogMC4wNSAgIyA1JSB1bnR1ayBwZXJmb3JtYSBBdmVyYWdlDQogICAgfSBlbHNlIHsNCiAgICAgICAgYm9udXMgPC0gMCAgIyBUaWRhayBhZGEgYm9udXMgdW50dWsgcGVyZm9ybWEgbGFpbm55YQ0KICAgIH0NCiAgICANCiAgICBjYXQoIk5hbWU6IiwgZW1wJE5hbWUsICIsIEJvbnVzOiIsIGZvcm1hdChib251cywgbnNtYWxsID0gMiksICJcbiIpDQp9DQpgYGANCiMjIyMgUGVuamVsYXNhbiBLb2RlDQoNCjEuICpjYXQoIkJvbnVzIEthcnlhd2FuOlxuIikqIOKGkiBNZW5hbXBpbGthbiBqdWR1bCBzZWJlbHVtIGRhZnRhciBib251cyBrYXJ5YXdhbi4NCg0KMi4gKipMb29wKiogKmZvciog4oaSIE1lbmVsdXN1cmkgc2V0aWFwIGthcnlhd2FuIGRhbGFtIGxpc3QgKmVtcGxveWVlcyouDQoNCjMuICppZi1lbHNlKiDihpIgTWVuZW50dWthbiBiZXNhciBib251cyBiZXJkYXNhcmthbiBrYXRlZ29yaSBwZXJmb3JtYToNCg0KLSAqIlZlcnkgR29vZCIqIOKGkiBCb251cyAqKjIwJSoqIGRhcmkgZ2FqaS4NCg0KLSAqIkdvb2QiKiDihpIgQm9udXMgKioxMCUqKiBkYXJpIGdhamkuDQoNCi0gKiJBdmVyYWdlIiog4oaSIEJvbnVzICoqNSUqKiBkYXJpIGdhamkuDQoNCi0gS2F0ZWdvcmkgbGFpbm55YSDihpIgQm9udXMgKiowKiouDQoNCjQuICpmb3JtYXQoYm9udXMsIG5zbWFsbCA9IDIpKiDihpIgTWVuYW1waWxrYW4gYm9udXMgZGVuZ2FuIGR1YSBhbmdrYSBkZXNpbWFsIHVudHVrIGZvcm1hdCB5YW5nIGxlYmloIHJhcGkuDQoNCjUuICpjYXQoKSog4oaSIERpZ3VuYWthbiB1bnR1ayBtZW5jZXRhayBoYXNpbCBkZW5nYW4gZm9ybWF0ICoiTmFtZTogTmFtYSwgQm9udXM6IEJvbnVzIiouDQoNCg0KIyMgS2VzaW1wdWxhbg0KDQpLb2RlIGluaSBtZW5naGl0dW5nIGJvbnVzIGthcnlhd2FuIGJlcmRhc2Fya2FuIHBlcmZvcm1hIG1lcmVrYSBkZW5nYW4gbWVuZ2d1bmFrYW46DQoNCjEuICoqTG9vcCoqICpmb3IqIHVudHVrIG1lbWJhY2Egc2VtdWEga2FyeWF3YW4uDQoNCjIuICoqU3RydWt0dXIqKiAqaWYtZWxzZSogdW50dWsgbWVuZW50dWthbiBiZXNhciBib251cyBiZXJkYXNhcmthbiBwZXJmb3JtYS4NCg0KMy4gKmNhdCgpKiB1bnR1ayBtZW5jZXRhayBoYXNpbCBkZW5nYW4gZm9ybWF0IHlhbmcgcmFwaSBkYW4gbXVkYWggZGliYWNhLg0KDQojIyAyLjUuMyBQZXJ1bGFuZ2FuIChGb3IgJiBXaGlsZSkNCg0KIyMjIEd1bmFrYW4gKmZvciogbG9vcCB1bnR1ayBtZW1idWF0IGRhZnRhciBrYXJ5YXdhbiBkZW5nYW4gZ2FqaSBsZWJpaCBkYXJpIDYwMDANCg0KYGBge3IsIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFLCBlY2hvPVRSVUV9DQojIERhdGFzZXQgS2FyeWF3YW4NCmVtcGxveWVlcyA8LSBsaXN0KA0KICAgIGxpc3QoSUQgPSAxLCBOYW1lID0gIkJhZ2FzIiwgQWdlID0gMjUsIFNhbGFyeSA9IDUwMDAsIFBvc2l0aW9uID0gIlN0YWZmIiwgUGVyZm9ybWFuY2UgPSAiR29vZCIpLA0KICAgIGxpc3QoSUQgPSAyLCBOYW1lID0gIkpvYW4iLCBBZ2UgPSAzMCwgU2FsYXJ5ID0gNzAwMCwgUG9zaXRpb24gPSAiU3VwZXJ2aXNvciIsIFBlcmZvcm1hbmNlID0gIlZlcnkgR29vZCIpLA0KICAgIGxpc3QoSUQgPSAzLCBOYW1lID0gIkFseWEiLCBBZ2UgPSAyNywgU2FsYXJ5ID0gNjUwMCwgUG9zaXRpb24gPSAiU3RhZmYiLCBQZXJmb3JtYW5jZSA9ICJBdmVyYWdlIiksDQogICAgbGlzdChJRCA9IDQsIE5hbWUgPSAiRHdpIiwgQWdlID0gMzUsIFNhbGFyeSA9IDEwMDAwLCBQb3NpdGlvbiA9ICJNYW5hZ2VyIiwgUGVyZm9ybWFuY2UgPSAiR29vZCIpLA0KICAgIGxpc3QoSUQgPSA1LCBOYW1lID0gIk5hYmlsIiwgQWdlID0gNDAsIFNhbGFyeSA9IDEyMDAwLCBQb3NpdGlvbiA9ICJEaXJlY3RvciIsIFBlcmZvcm1hbmNlID0gIlZlcnkgR29vZCIpDQopDQoNCiMgMS4gTWVuYW1waWxrYW4ga2FyeWF3YW4gZGVuZ2FuIGdhamkgbGViaWggZGFyaSA2MDAwDQpjYXQoIkthcnlhd2FuIGRlbmdhbiBnYWppIGxlYmloIGRhcmkgNjAwMDpcbiIpDQpmb3IgKGVtcCBpbiBlbXBsb3llZXMpIHsNCiAgICBpZiAoZW1wJFNhbGFyeSA+IDYwMDApIHsNCiAgICAgICAgY2F0KCJOYW1lOiIsIGVtcCROYW1lLCAiLCBTYWxhcnk6IiwgZW1wJFNhbGFyeSwgIlxuIikNCiAgICB9DQp9DQoNCmBgYA0KIyMjIyBQZW5qZWxhc2FuIEtvZGUNCg0KMS4gKipMb29wKiogKmZvciogbWVtYmFjYSBzZW11YSBkYXRhIGthcnlhd2FuLg0KDQoyLiAqaWYgKGVtcCRTYWxhcnkgPiA2MDAwKSogbWVuZ2VjZWsgYXBha2FoIGdhamkga2FyeWF3YW4gbGViaWggZGFyaSA2MDAwLg0KDQozLiBKaWthIGtvbmRpc2kgdGVycGVudWhpLCBuYW1hIGRhbiBnYWppIGRpY2V0YWsgbWVuZ2d1bmFrYW4gKmNhdCgpKi4NCg0KIyMjIEd1bmFrYW4gKndoaWxlKiBsb29wIHVudHVrIG1lbmFtcGlsa2FuIGthcnlhd2FuIGhpbmdnYSAiTWFuYWdlciIgZGl0ZW11a2FuDQoNCmBgYHtyLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9VFJVRSwgZWNobz1UUlVFfQ0KIyAyLiBNZW5hbXBpbGthbiBrYXJ5YXdhbiBoaW5nZ2EgbWVuZW11a2FuIE1hbmFnZXINCmNhdCgiXG5NZW5hbXBpbGthbiBrYXJ5YXdhbiBoaW5nZ2EgbWVuZW11a2FuIE1hbmFnZXI6XG4iKQ0KaW5kZXggPC0gMQ0Kd2hpbGUgKGluZGV4IDw9IGxlbmd0aChlbXBsb3llZXMpKSB7DQogICAgZW1wIDwtIGVtcGxveWVlc1tbaW5kZXhdXQ0KICAgIGNhdCgiTmFtZToiLCBlbXAkTmFtZSwgIiwgUG9zaXRpb246IiwgZW1wJFBvc2l0aW9uLCAiXG4iKQ0KICAgIA0KICAgIGlmIChlbXAkUG9zaXRpb24gPT0gIk1hbmFnZXIiKSB7DQogICAgICAgIGNhdCgiKFN0b3AgaGVyZSlcbiIpICAjIE1lbWJlcmkgdGFodSBiYWh3YSBsb29wIGJlcmhlbnRpDQogICAgICAgIGJyZWFrICAjIEtlbHVhciBkYXJpIGxvb3Agc2V0ZWxhaCBtZW5lbXVrYW4gTWFuYWdlcg0KICAgIH0NCiAgICBpbmRleCA8LSBpbmRleCArIDENCn0NCmBgYA0KIyMjIyBQZW5qZWxhc2FuIEtvZGUNCg0KMS4gKndoaWxlIChpbmRleCA8PSBsZW5ndGgoZW1wbG95ZWVzKSkqIG1lbmphbGFua2FuIGxvb3Agc2VsYW1hIGluZGVrcyBkYWxhbSBiYXRhcyBwYW5qYW5nIGRhZnRhci4NCg0KMi4gKmNhdCgpKiBtZW5jZXRhayBuYW1hIGRhbiBwb3Npc2kga2FyeWF3YW4uDQoNCjMuIEppa2EgKipqYWJhdGFuICJNYW5hZ2VyIiBkaXRlbXVrYW4qKiwgdGVrcyAqKiIoU3RvcCBoZXJlKSIqKiBkaXRhbXBpbGthbiwgZGFuIGxvb3AgYmVyaGVudGkgZGVuZ2FuICpicmVhayouDQoNCiMjIyBHdW5ha2FuICpicmVhayogdW50dWsgbWVuZ2hlbnRpa2FuIGxvb3Agc2FhdCBtZW5lbXVrYW4gZ2FqaSA+IDEwLjAwMA0KDQpgYGB7ciwgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPVRSVUUsIGVjaG89VFJVRX0NCiMgMy4gTWVuYW1waWxrYW4ga2FyeWF3YW4gaGluZ2dhIG1lbmVtdWthbiBnYWppIGRpIGF0YXMgMTAuMDAwDQpjYXQoIlxuTWVuYW1waWxrYW4ga2FyeWF3YW4gaGluZ2dhIG1lbmVtdWthbiBnYWppIGRpIGF0YXMgMTAuMDAwOlxuIikNCmZvciAoZW1wIGluIGVtcGxveWVlcykgew0KICAgIGlmIChlbXAkU2FsYXJ5ID4gMTAwMDApIHsNCiAgICAgICAgY2F0KCIoU3RvcHBlZCBiZWNhdXNlIiwgZW1wJE5hbWUsICJoYXMgYSBzYWxhcnkgYWJvdmUgMTAsMDAwKVxuIikNCiAgICAgICAgYnJlYWsgICMgTWVuZ2hlbnRpa2FuIGxvb3Agc2V0ZWxhaCBtZW5lbXVrYW4gZ2FqaSA+IDEwLjAwMA0KICAgIH0NCiAgICBjYXQoIk5hbWU6IiwgZW1wJE5hbWUsICIsIFNhbGFyeToiLCBlbXAkU2FsYXJ5LCAiXG4iKQ0KfQ0KYGBgDQojIyMjIFBlbmplbGFzYW4gS29kZQ0KDQoxLiAqKkxvb3AqKiAqZm9yKiBtZW1iYWNhIHNlbXVhIGthcnlhd2FuLg0KDQoyLiBKaWthICoqZ2FqaSBsZWJpaCBkYXJpIDEwLjAwMCoqLCB0ZWtzIHBlbWJlcmhlbnRpYW4gZGl0YW1waWxrYW4sIGRhbiBsb29wIGJlcmhlbnRpIGRlbmdhbiAqYnJlYWsqLg0KDQozLiBTZWJlbHVtIGl0dSwgc2VtdWEga2FyeWF3YW4gZGVuZ2FuIGdhamkgZGkgYmF3YWggMTAuMDAwIHRldGFwIGRpdGFtcGlsa2FuLg0KDQojIyMgR3VuYWthbiAqbmV4dCogdW50dWsgbWVsZXdhdGkga2FyeWF3YW4gZGVuZ2FuIHBlcmZvcm1hICJBdmVyYWdlIg0KDQpgYGB7ciwgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPVRSVUUsIGVjaG89VFJVRX0NCiMgNC4gTWVuYW1waWxrYW4ga2FyeWF3YW4gZGVuZ2FuIG1lbmdhYmFpa2FuIHBlcmZvcm1hICdBdmVyYWdlJw0KY2F0KCJcbk1lbmFtcGlsa2FuIGthcnlhd2FuIGRlbmdhbiBtZW5nYWJhaWthbiBwZXJmb3JtYSAnQXZlcmFnZSc6XG4iKQ0Kc2tpcHBlZCA8LSAiIiAgIyBWYXJpYWJlbCB1bnR1ayBtZW55aW1wYW4gaW5mbyBrYXJ5YXdhbiB5YW5nIGRpbGV3YXRpDQoNCmZvciAoZW1wIGluIGVtcGxveWVlcykgew0KICAgIGlmIChlbXAkUGVyZm9ybWFuY2UgPT0gIkF2ZXJhZ2UiKSB7DQogICAgICAgIHNraXBwZWQgPC0gcGFzdGUoIigiLCBlbXAkTmFtZSwgImlzIHNraXBwZWQgYmVjYXVzZSB0aGUgcGVyZm9ybWFuY2UgaXMgJ0F2ZXJhZ2UnKSIpICANCiAgICAgICAgbmV4dCAgIyBMZXdhdGkgaXRlcmFzaSBqaWthIHBlcmZvcm1hICJBdmVyYWdlIg0KICAgIH0NCiAgICBjYXQoIk5hbWU6IiwgZW1wJE5hbWUsICIsIFBlcmZvcm1hbmNlOiIsIGVtcCRQZXJmb3JtYW5jZSwgIlxuIikNCn0NCg0KY2F0KHNraXBwZWQsICJcbiIpICAjIE1lbmFtcGlsa2FuIGluZm9ybWFzaSBrYXJ5YXdhbiB5YW5nIGRpbGV3YXRpDQpgYGANCiMjIyMgUGVuamVsYXNhbiBLb2RlDQoNCjEuICoqTG9vcCoqICpmb3IqIG1lbWJhY2Egc2VtdWEga2FyeWF3YW4uDQoNCjIuIEppa2EgKipwZXJmb3JtYSAiQXZlcmFnZSIqKiwgdmFyaWFiZWwgKnNraXBwZWQqIG1lbnlpbXBhbiB0ZWtzIGJhaHdhIGthcnlhd2FuIGRpbGV3YXRpLg0KDQozLiAqbmV4dCogZGlndW5ha2FuIHVudHVrIG1lbGV3YXRpIGl0ZXJhc2ksIHNlaGluZ2dhIGRhdGEga2FyeWF3YW4gdGVyc2VidXQgdGlkYWsgZGljZXRhay4NCg0KNC4gKipTZXRlbGFoIGxvb3Agc2VsZXNhaSoqLCB0ZWtzICpza2lwcGVkKiBkaXRhbXBpbGthbiB1bnR1ayBtZW1iZXJpIHRhaHUgc2lhcGEgeWFuZyBkaWxld2F0aS4NCg0KIyMgS2VzaW1wdWxhbg0KDQoxLiAqKkxvb3AqKiAqZm9yKiB1bnR1ayBpdGVyYXNpIGRhdGE6DQoNCi0gRGlndW5ha2FuIHVudHVrIG1lbmVsdXN1cmkgc2VsdXJ1aCBkYWZ0YXIga2FyeWF3YW4uDQoNCi0gTWVuZXJhcGthbiBrb25kaXNpIHVudHVrIG1lbnlhcmluZyBkYXRhLCBzZXBlcnRpIG1lbmFtcGlsa2FuIGthcnlhd2FuIGRlbmdhbiAqKmdhamkgbGViaWggZGFyaSA2MDAwKiouDQoNCjIuICoqTG9vcCoqICp3aGlsZSogdW50dWsgbWVtYmFjYSBkYXRhIHNlY2FyYSBiZXJ0YWhhcDoNCg0KLSBEaWd1bmFrYW4gdW50dWsgbWVuYW1waWxrYW4ga2FyeWF3YW4gKipzYXR1IHBlciBzYXR1KiogaGluZ2dhIG1lbmVtdWthbiBrYXJ5YXdhbiBkZW5nYW4gamFiYXRhbiAqKiJNYW5hZ2VyIioqLCBsYWx1IGJlcmhlbnRpLg0KDQozLiBQZW5nZ3VuYWFuICpicmVhayogZGFsYW0gKipsb29wKio6DQoNCi0gRGlndW5ha2FuIHVudHVrIG1lbmdoZW50aWthbiBpdGVyYXNpIGxlYmloIGF3YWwga2V0aWthICoqc3lhcmF0IHRlcnRlbnR1IHRlcnBlbnVoaSoqLg0KDQotIENvbnRvaDogSmlrYSBhZGEga2FyeWF3YW4gZGVuZ2FuICoqZ2FqaSBsZWJpaCBkYXJpIDEwLjAwMCoqLCBsb29wIGxhbmdzdW5nIGRpaGVudGlrYW4uDQoNCjQuIFBlbmdndW5hYW4gKm5leHQqIHVudHVrIG1lbGV3YXRpIGl0ZXJhc2k6DQoNCi0gRGlndW5ha2FuIHVudHVrICoqbWVsZXdhdGkga2FyeWF3YW4qKiBkZW5nYW4gcGVyZm9ybWEgKioiQXZlcmFnZSIqKiwgc2VoaW5nZ2EgbWVyZWthIHRpZGFrIGRpdGFtcGlsa2FuIGRhbGFtIGhhc2lsIGFraGlyLg0KDQojIFJlZmVyZW5zaQ0KDQpodHRwczovL2Jvb2tkb3duLm9yZy9kc2NpZW5jZWxhYnMvZGF0YV9zY2llbmNlX3Byb2dyYW1taW5nLzAyLVN5bnRheC1hbmQtQ29udHJvbC1GbG93Lmh0bWwjcHJhY3RpY3VtDQoNCmh0dHBzOi8vY29sYWIucmVzZWFyY2guZ29vZ2xlLmNvbS9kcml2ZS8xTUdaSFpOcExjMW1zZjRXNWNjM2NxV0Z0T3Y4Z1lYVG8/dXNwPXNoYXJpbmcNCg==