Tugas 3 Data Science Programming

Web Scraping

Isnaini Nur Hasanah (52240005)

March 13, 2025

Logo

Apabila kita ingin menganalisis sesuatu, kita pasti membutuhkan data. Data biasanya tersedia dalam format seperti teks, CSV, atau file Excel, sehingga mudah dimuat ke dalam R dan menjalankan skrip untuk mendapatkan hasil dan jawaban yang dibutuhkan. Namun, jika data tersebut tidak disusun dengan rapi, melainkan tersebar di berbagai lokasi di satu atau lebih situs web, maka kita akan menggunakan Web Scraping. Web scraping adalah teknik untuk mengambil data dari situs web dan mengolahnya dalam bentuk yang lebih terstruktur. Dalam laporan ini, kita akan membahas cara melakukan web scraping di R menggunakan paket rvest. Beberapa contoh yang dibahas mencakup:

  • Copy-paste tabel sebagai alternatif scraping

  • Scraping data dari tabel dalam situs web

  • Scraping dari beberapa situs web sekaligus

  • Scraping data non-tabel dengan bantuan ChatGPT

Penjelasan dari web scraping, yaitu:

1 Copy-Paste Tabel Menggunakan datapasta

Contoh pertama sebenarnya bukan web scraping, melainkan jalan pintas. Jika Anda menemukan tabel di sebuah situs web dan ingin mengambil informasi dari tabel tersebut ke dalam R, salah satu cara tercepat adalah:

  1. Sorot seluruh sel tabel.

  2. Tahan tombol mouse hingga mencapai header tabel.

  3. Tekan Ctrl + C atau klik kanan dan pilih Copy.

Di R, setelah menginstal paket datapasta, Anda akan memiliki fitur tambahan yang memungkinkan Anda langsung menempelkan data dari clipboard sebagai data frame ke dalam R. Misalnya, saya ingin menyimpan informasi dalam sebuah objek bernama Olympic_medals dan menempelkannya sebagai data frame. Formatnya akan terlihat seperti ini:

  • Kolom pertama berisi peringkat (rank).

  • Kolom Nations berisi nama negara.

  • Kolom lainnya menunjukkan jumlah medali emas, perak, dan perunggu yang dimenangkan, serta totalnya.

  • Tipe data akan dikenali secara otomatis, dengan nama negara sebagai karakter dan jumlah medali sebagai integer.

## 1) datapasta 
library(datapasta)
## Warning: package 'datapasta' was built under R version 4.4.3
#https://www.topendsports.com/events/summer/medal-tally/all-time-all.htm

olympic_medals <- data.frame(
  stringsAsFactors = FALSE,
       check.names = FALSE,
                                Rank = c(1L,2L,3L,4L,5L,6L,7L,8L,9L,
                                         10L,11L,12L,13L,14L,15L,16L,
                                         17L,18L,19L,20L,21L,22L,23L,24L,
                                         25L,26L,27L,28L,29L,30L,31L,32L,
                                         33L,34L,35L,36L,37L,38L,39L,40L,
                                         41L,42L,43L,44L,45L,46L,47L,48L,
                                         49L,50L,51L,52L,53L,54L,55L,
                                         56L,57L,58L,59L,60L,61L,62L,63L,
                                         64L,65L,66L,67L,68L,69L,70L,71L,
                                         72L,73L,74L,75L,76L,77L,78L,79L,
                                         80L,81L,82L,83L,84L,85L,86L,87L,
                                         88L,89L,90L,91L,92L,93L,94L,
                                         95L,96L,97L,98L,99L,100L,101L,102L,
                                         103L,104L,105L,106L,107L,108L,
                                         109L,110L,111L,112L,113L,114L,115L,
                                         116L,117L,118L,119L,120L,121L,
                                         122L,123L,124L,125L,126L,127L,128L,
                                         129L,130L,131L,132L,133L,134L,
                                         135L,136L,137L,138L,139L,140L,141L,
                                         142L,143L,144L,145L,146L,147L),
                      `Nation.(NOC)` = c("United States","Soviet Union",
                                         "Germany","Great Britain","China",
                                         "France","Italy","Hungary","Russia",
                                         "Japan","Australia","East Germany",
                                         "Sweden","Finland","South Korea",
                                         "Netherlands","Romania","Cuba","Poland",
                                         "Canada","Norway","Bulgaria",
                                         "Switzerland","New Zealand","Czechoslovakia",
                                         "Denmark","Spain","Belgium",
                                         "Türkiye","Brazil","Ukraine","Greece",
                                         "Kenya","Yugoslavia","South Africa",
                                         "Jamaica","Iran","Ethiopia","Argentina",
                                         "Austria","Czechia","North Korea",
                                         "Kazakhstan","Croatia","Belarus",
                                         "Mexico","Ireland","Georgia",
                                         "Uzbekistan","Estonia","Thailand","India",
                                         "Slovakia","Egypt","Indonesia",
                                         "Slovenia","Mixed team","Bahamas",
                                         "Azerbaijan","Chinese Taipei","Morocco",
                                         "Lithuania","Serbia","Colombia","Portugal",
                                         "Algeria","Tunisia","Latvia",
                                         "Uganda","Nigeria","Venezuela",
                                         "Trinidad and Tobago","Israel",
                                         "Dominican Republic","Pakistan","Zimbabwe","Cameroon",
                                         "Ecuador","Kosovo","Mongolia",
                                         "Armenia","Chile","Puerto Rico",
                                         "Uruguay","Hong Kong","Qatar","Fiji",
                                         "Bahrain","Philippines",
                                         "Independent Olympic Athletes/Participants","Singapore",
                                         "Vietnam","Costa Rica","Peru",
                                         "Ivory Coast","Tajikistan","Syria",
                                         "Grenada","Panama","Jordan","Suriname",
                                         "Bermuda","Mozambique","Burundi",
                                         "Luxembourg","United Arab Emirates",
                                         "Malaysia","Kyrgyzstan","Moldova","Ghana",
                                         "Namibia","Bohemia","Iceland",
                                         "Saudi Arabia","Lebanon","San Marino",
                                         "Kuwait","Sri Lanka",
                                         "Serbia and Montenegro","Haiti","North Macedonia",
                                         "Niger","Zambia","British West Indies",
                                         "Botswana","Tanzania","Afghanistan",
                                         "Iraq","Sudan","Cyprus","Senegal",
                                         "Samoa","Guyana","Guatemala","Paraguay",
                                         "Netherlands Antilles","Gabon",
                                         "Barbados","Montenegro","Mauritius",
                                         "Eritrea","Burkina Faso","Virgin Islands",
                                         "Djibouti","Turkmenistan","Tonga",
                                         "Togo"),
                        No..of.Games = c(28L,10L,25L,29L,11L,29L,28L,
                                         27L,10L,23L,29L,5L,28L,26L,18L,
                                         27L,22L,21L,22L,27L,26L,21L,29L,
                                         24L,16L,28L,24L,27L,23L,23L,7L,
                                         29L,15L,18L,20L,18L,17L,14L,
                                         25L,28L,7L,10L,7L,8L,7L,24L,22L,
                                         7L,7L,13L,17L,25L,7L,23L,16L,8L,
                                         3L,17L,7L,15L,15L,10L,5L,20L,
                                         25L,14L,15L,12L,16L,17L,19L,18L,
                                         17L,15L,18L,14L,15L,15L,2L,14L,
                                         7L,24L,19L,22L,17L,10L,15L,10L,
                                         22L,4L,17L,16L,16L,19L,14L,7L,
                                         14L,10L,18L,11L,13L,19L,11L,7L,
                                         24L,10L,14L,7L,7L,15L,8L,3L,21L,
                                         12L,18L,15L,13L,18L,1L,16L,7L,
                                         13L,14L,1L,11L,14L,15L,15L,13L,
                                         11L,15L,10L,18L,15L,13L,13L,11L,
                                         13L,4L,10L,6L,10L,13L,9L,7L,
                                         10L,11L),
                                Gold = c(1061L,440L,285L,285L,262L,
                                         226L,217L,181L,170L,169L,167L,153L,
                                         148L,101L,96L,95L,90L,85L,72L,
                                         71L,60L,54L,53L,53L,49L,48L,48L,
                                         43L,41L,37L,35L,35L,35L,28L,27L,
                                         26L,24L,23L,21L,19L,19L,16L,15L,
                                         14L,13L,13L,11L,10L,10L,10L,10L,
                                         10L,10L,8L,8L,8L,8L,8L,7L,7L,
                                         7L,6L,6L,5L,5L,5L,5L,4L,4L,3L,
                                         3L,3L,3L,3L,3L,3L,3L,3L,3L,
                                         2L,2L,2L,2L,2L,2L,2L,2L,2L,1L,
                                         1L,1L,1L,1L,1L,1L,1L,1L,1L,1L,
                                         1L,1L,1L,1L,1L,1L,1L,0L,0L,0L,
                                         0L,0L,0L,0L,0L,0L,0L,0L,0L,
                                         0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,
                                         0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,
                                         0L,0L,0L,0L,0L,0L,0L,0L,0L),
                              Silver = c(836L,357L,326L,315L,199L,258L,
                                         188L,154L,157L,150L,177L,129L,
                                         176L,85L,91L,104L,97L,71L,89L,
                                         108L,51L,88L,79L,33L,49L,78L,72L,
                                         54L,26L,42L,36L,45L,42L,31L,33L,
                                         36L,23L,12L,26L,34L,21L,16L,21L,
                                         13L,30L,24L,10L,12L,6L,9L,8L,
                                         9L,14L,11L,14L,9L,4L,2L,14L,11L,
                                         5L,7L,7L,13L,9L,4L,3L,11L,4L,
                                         11L,7L,5L,1L,5L,3L,4L,1L,2L,0L,
                                         11L,8L,7L,2L,2L,3L,1L,0L,1L,
                                         5L,1L,2L,3L,1L,3L,1L,1L,1L,1L,
                                         0L,1L,0L,0L,0L,1L,1L,0L,8L,3L,
                                         2L,1L,5L,1L,2L,2L,2L,1L,0L,
                                         2L,2L,1L,1L,1L,1L,0L,1L,2L,0L,
                                         0L,1L,1L,1L,1L,0L,1L,1L,1L,1L,
                                         0L,1L,0L,0L,0L,1L,0L,1L,1L,0L),
                              Bronze = c(739L,325L,363L,315L,173L,280L,
                                         213L,176L,178L,178L,213L,127L,
                                         179L,119L,100L,122L,121L,85L,137L,
                                         147L,49L,82L,73L,53L,45L,79L,
                                         47L,58L,37L,71L,68L,41L,36L,31L,
                                         29L,25L,29L,23L,30L,41L,27L,22L,
                                         36L,14L,42L,36L,14L,18L,20L,17L,
                                         17L,14L,8L,19L,15L,11L,4L,6L,
                                         28L,18L,12L,13L,11L,15L,14L,8L,
                                         7L,6L,3L,13L,9L,11L,9L,4L,4L,1L,
                                         2L,0L,0L,17L,8L,4L,6L,6L,4L,
                                         5L,1L,0L,8L,3L,2L,1L,2L,0L,2L,
                                         2L,2L,1L,2L,1L,1L,1L,1L,0L,0L,
                                         1L,5L,4L,4L,4L,0L,3L,2L,2L,
                                         2L,2L,3L,0L,0L,1L,1L,1L,1L,2L,
                                         1L,0L,2L,1L,0L,0L,0L,0L,1L,0L,
                                         0L,0L,0L,1L,0L,1L,1L,1L,0L,1L,
                                         0L,0L,1L),
                               Total = c(2636L,1122L,974L,915L,634L,
                                         764L,618L,511L,505L,497L,557L,409L,
                                         503L,305L,287L,321L,308L,241L,
                                         298L,326L,160L,224L,205L,139L,143L,
                                         205L,167L,155L,104L,150L,139L,
                                         121L,113L,90L,89L,87L,76L,58L,77L,
                                         94L,67L,54L,72L,41L,85L,73L,35L,
                                         40L,36L,36L,35L,35L,32L,38L,
                                         37L,28L,16L,14L,49L,36L,24L,26L,
                                         24L,33L,28L,17L,15L,21L,11L,27L,
                                         19L,19L,13L,12L,10L,8L,6L,5L,3L,
                                         30L,18L,13L,10L,10L,9L,8L,3L,
                                         3L,14L,5L,5L,5L,4L,4L,4L,4L,4L,
                                         3L,3L,3L,2L,2L,2L,2L,2L,2L,
                                         13L,7L,6L,5L,5L,4L,4L,4L,4L,3L,
                                         3L,2L,2L,2L,2L,2L,2L,2L,2L,2L,
                                         2L,1L,1L,1L,1L,1L,1L,1L,1L,
                                         1L,1L,1L,1L,1L,1L,1L,1L,1L,1L,
                                         1L,1L)
                  )

print(olympic_medals)
##     Rank                              Nation.(NOC) No..of.Games Gold Silver
## 1      1                             United States           28 1061    836
## 2      2                              Soviet Union           10  440    357
## 3      3                                   Germany           25  285    326
## 4      4                             Great Britain           29  285    315
## 5      5                                     China           11  262    199
## 6      6                                    France           29  226    258
## 7      7                                     Italy           28  217    188
## 8      8                                   Hungary           27  181    154
## 9      9                                    Russia           10  170    157
## 10    10                                     Japan           23  169    150
## 11    11                                 Australia           29  167    177
## 12    12                              East Germany            5  153    129
## 13    13                                    Sweden           28  148    176
## 14    14                                   Finland           26  101     85
## 15    15                               South Korea           18   96     91
## 16    16                               Netherlands           27   95    104
## 17    17                                   Romania           22   90     97
## 18    18                                      Cuba           21   85     71
## 19    19                                    Poland           22   72     89
## 20    20                                    Canada           27   71    108
## 21    21                                    Norway           26   60     51
## 22    22                                  Bulgaria           21   54     88
## 23    23                               Switzerland           29   53     79
## 24    24                               New Zealand           24   53     33
## 25    25                            Czechoslovakia           16   49     49
## 26    26                                   Denmark           28   48     78
## 27    27                                     Spain           24   48     72
## 28    28                                   Belgium           27   43     54
## 29    29                                   Türkiye           23   41     26
## 30    30                                    Brazil           23   37     42
## 31    31                                   Ukraine            7   35     36
## 32    32                                    Greece           29   35     45
## 33    33                                     Kenya           15   35     42
## 34    34                                Yugoslavia           18   28     31
## 35    35                              South Africa           20   27     33
## 36    36                                   Jamaica           18   26     36
## 37    37                                      Iran           17   24     23
## 38    38                                  Ethiopia           14   23     12
## 39    39                                 Argentina           25   21     26
## 40    40                                   Austria           28   19     34
## 41    41                                   Czechia            7   19     21
## 42    42                               North Korea           10   16     16
## 43    43                                Kazakhstan            7   15     21
## 44    44                                   Croatia            8   14     13
## 45    45                                   Belarus            7   13     30
## 46    46                                    Mexico           24   13     24
## 47    47                                   Ireland           22   11     10
## 48    48                                   Georgia            7   10     12
## 49    49                                Uzbekistan            7   10      6
## 50    50                                   Estonia           13   10      9
## 51    51                                  Thailand           17   10      8
## 52    52                                     India           25   10      9
## 53    53                                  Slovakia            7   10     14
## 54    54                                     Egypt           23    8     11
## 55    55                                 Indonesia           16    8     14
## 56    56                                  Slovenia            8    8      9
## 57    57                                Mixed team            3    8      4
## 58    58                                   Bahamas           17    8      2
## 59    59                                Azerbaijan            7    7     14
## 60    60                            Chinese Taipei           15    7     11
## 61    61                                   Morocco           15    7      5
## 62    62                                 Lithuania           10    6      7
## 63    63                                    Serbia            5    6      7
## 64    64                                  Colombia           20    5     13
## 65    65                                  Portugal           25    5      9
## 66    66                                   Algeria           14    5      4
## 67    67                                   Tunisia           15    5      3
## 68    68                                    Latvia           12    4     11
## 69    69                                    Uganda           16    4      4
## 70    70                                   Nigeria           17    3     11
## 71    71                                 Venezuela           19    3      7
## 72    72                       Trinidad and Tobago           18    3      5
## 73    73                                    Israel           17    3      1
## 74    74                        Dominican Republic           15    3      5
## 75    75                                  Pakistan           18    3      3
## 76    76                                  Zimbabwe           14    3      4
## 77    77                                  Cameroon           15    3      1
## 78    78                                   Ecuador           15    3      2
## 79    79                                    Kosovo            2    3      0
## 80    80                                  Mongolia           14    2     11
## 81    81                                   Armenia            7    2      8
## 82    82                                     Chile           24    2      7
## 83    83                               Puerto Rico           19    2      2
## 84    84                                   Uruguay           22    2      2
## 85    85                                 Hong Kong           17    2      3
## 86    86                                     Qatar           10    2      1
## 87    87                                      Fiji           15    2      0
## 88    88                                   Bahrain           10    2      1
## 89    89                               Philippines           22    1      5
## 90    90 Independent Olympic Athletes/Participants            4    1      1
## 91    91                                 Singapore           17    1      2
## 92    92                                   Vietnam           16    1      3
## 93    93                                Costa Rica           16    1      1
## 94    94                                      Peru           19    1      3
## 95    95                               Ivory Coast           14    1      1
## 96    96                                Tajikistan            7    1      1
## 97    97                                     Syria           14    1      1
## 98    98                                   Grenada           10    1      1
## 99    99                                    Panama           18    1      0
## 100  100                                    Jordan           11    1      1
## 101  101                                  Suriname           13    1      0
## 102  102                                   Bermuda           19    1      0
## 103  103                                Mozambique           11    1      0
## 104  104                                   Burundi            7    1      1
## 105  105                                Luxembourg           24    1      1
## 106  106                      United Arab Emirates           10    1      0
## 107  107                                  Malaysia           14    0      8
## 108  108                                Kyrgyzstan            7    0      3
## 109  109                                   Moldova            7    0      2
## 110  110                                     Ghana           15    0      1
## 111  111                                   Namibia            8    0      5
## 112  112                                   Bohemia            3    0      1
## 113  113                                   Iceland           21    0      2
## 114  114                              Saudi Arabia           12    0      2
## 115  115                                   Lebanon           18    0      2
## 116  116                                San Marino           15    0      1
## 117  117                                    Kuwait           13    0      0
## 118  118                                 Sri Lanka           18    0      2
## 119  119                     Serbia and Montenegro            1    0      2
## 120  120                                     Haiti           16    0      1
## 121  121                           North Macedonia            7    0      1
## 122  122                                     Niger           13    0      1
## 123  123                                    Zambia           14    0      1
## 124  124                       British West Indies            1    0      0
## 125  125                                  Botswana           11    0      1
## 126  126                                  Tanzania           14    0      2
## 127  127                               Afghanistan           15    0      0
## 128  128                                      Iraq           15    0      0
## 129  129                                     Sudan           13    0      1
## 130  130                                    Cyprus           11    0      1
## 131  131                                   Senegal           15    0      1
## 132  132                                     Samoa           10    0      1
## 133  133                                    Guyana           18    0      0
## 134  134                                 Guatemala           15    0      1
## 135  135                                  Paraguay           13    0      1
## 136  136                      Netherlands Antilles           13    0      1
## 137  137                                     Gabon           11    0      1
## 138  138                                  Barbados           13    0      0
## 139  139                                Montenegro            4    0      1
## 140  140                                 Mauritius           10    0      0
## 141  141                                   Eritrea            6    0      0
## 142  142                              Burkina Faso           10    0      0
## 143  143                            Virgin Islands           13    0      1
## 144  144                                  Djibouti            9    0      0
## 145  145                              Turkmenistan            7    0      1
## 146  146                                     Tonga           10    0      1
## 147  147                                      Togo           11    0      0
##     Bronze Total
## 1      739  2636
## 2      325  1122
## 3      363   974
## 4      315   915
## 5      173   634
## 6      280   764
## 7      213   618
## 8      176   511
## 9      178   505
## 10     178   497
## 11     213   557
## 12     127   409
## 13     179   503
## 14     119   305
## 15     100   287
## 16     122   321
## 17     121   308
## 18      85   241
## 19     137   298
## 20     147   326
## 21      49   160
## 22      82   224
## 23      73   205
## 24      53   139
## 25      45   143
## 26      79   205
## 27      47   167
## 28      58   155
## 29      37   104
## 30      71   150
## 31      68   139
## 32      41   121
## 33      36   113
## 34      31    90
## 35      29    89
## 36      25    87
## 37      29    76
## 38      23    58
## 39      30    77
## 40      41    94
## 41      27    67
## 42      22    54
## 43      36    72
## 44      14    41
## 45      42    85
## 46      36    73
## 47      14    35
## 48      18    40
## 49      20    36
## 50      17    36
## 51      17    35
## 52      14    35
## 53       8    32
## 54      19    38
## 55      15    37
## 56      11    28
## 57       4    16
## 58       6    14
## 59      28    49
## 60      18    36
## 61      12    24
## 62      13    26
## 63      11    24
## 64      15    33
## 65      14    28
## 66       8    17
## 67       7    15
## 68       6    21
## 69       3    11
## 70      13    27
## 71       9    19
## 72      11    19
## 73       9    13
## 74       4    12
## 75       4    10
## 76       1     8
## 77       2     6
## 78       0     5
## 79       0     3
## 80      17    30
## 81       8    18
## 82       4    13
## 83       6    10
## 84       6    10
## 85       4     9
## 86       5     8
## 87       1     3
## 88       0     3
## 89       8    14
## 90       3     5
## 91       2     5
## 92       1     5
## 93       2     4
## 94       0     4
## 95       2     4
## 96       2     4
## 97       2     4
## 98       1     3
## 99       2     3
## 100      1     3
## 101      1     2
## 102      1     2
## 103      1     2
## 104      0     2
## 105      0     2
## 106      1     2
## 107      5    13
## 108      4     7
## 109      4     6
## 110      4     5
## 111      0     5
## 112      3     4
## 113      2     4
## 114      2     4
## 115      2     4
## 116      2     3
## 117      3     3
## 118      0     2
## 119      0     2
## 120      1     2
## 121      1     2
## 122      1     2
## 123      1     2
## 124      2     2
## 125      1     2
## 126      0     2
## 127      2     2
## 128      1     1
## 129      0     1
## 130      0     1
## 131      0     1
## 132      0     1
## 133      1     1
## 134      0     1
## 135      0     1
## 136      0     1
## 137      0     1
## 138      1     1
## 139      0     1
## 140      1     1
## 141      1     1
## 142      1     1
## 143      0     1
## 144      1     1
## 145      0     1
## 146      0     1
## 147      1     1

2 Scraping Data dari Tabel dalam Situs Web

Jika tabel tidak bisa disalin secara manual, kita memerlukan paket rvest. Paket ini diucapkan seperti “Harvest”, karena kita ingin memanen data dari situs web. Fungsi pertama yang kita perlukan adalah read_html(), yang memerlukan URL sebagai input. Misalnya, kita ingin mengambil daftar paket R dalam urutan alfabet dari sebuah situs web. Jika kita menjalankan kode untuk membaca HTML dari situs tersebut, kita akan melihat bahwa objek yang dihasilkan adalah dokumen HTML dengan struktur head dan body.

Saat kita melihat isi halaman web tersebut, kita melihat bahwa informasi yang kita butuhkan tersembunyi di dalam node HTML. Dengan menekan F12, kita bisa membuka alat pengembang dan menggunakan element inspector untuk menemukan elemen yang memuat data yang kita butuhkan. Misalnya, kita ingin mengambil tabel berisi daftar paket R. Dengan menggunakan HTML node inspector, kita bisa menemukan elemen yang menyimpan data tersebut. Kemudian, kita bisa menggunakan html_node() untuk mengambil elemen tersebut dan html_table() untuk mengubahnya menjadi data frame. Setelah dibersihkan (menghapus NA dan placeholder di antara huruf alfabet), kita mendapatkan tabel yang rapi berisi nama dan deskripsi paket R.

## 2) basic webscraping
library(rvest)
## Warning: package 'rvest' was built under R version 4.4.3
url <- "https://cran.r-project.org/web/packages/available_packages_by_name.html"

# Membaca HTML dari situs
webpage <- read_html(url)

# Mengambil tabel dari halaman
paket_table <- webpage %>% html_node("table") %>% html_table(fill = TRUE)

# Menampilkan data yang telah diambil
print(paket_table)
## # A tibble: 22,222 × 2
##    X1              X2                                                           
##    <chr>           <chr>                                                        
##  1 ""               <NA>                                                        
##  2 "A3"            "Accurate, Adaptable, and Accessible Error Metrics for Predi…
##  3 "AalenJohansen" "Conditional Aalen-Johansen Estimation"                      
##  4 "AATtools"      "Reliability and Scoring Routines for the Approach-Avoidance…
##  5 "ABACUS"        "Apps Based Activities for Communicating and Understanding\n…
##  6 "abasequence"   "Coding 'ABA' Patterns for Sequence Data"                    
##  7 "abbreviate"    "Readable String Abbreviation"                               
##  8 "abc"           "Tools for Approximate Bayesian Computation (ABC)"           
##  9 "abc.data"      "Data Only: Tools for Approximate Bayesian Computation (ABC)"
## 10 "ABC.RAP"       "Array Based CpG Region Analysis Pipeline"                   
## # ℹ 22,212 more rows

3 Scraping Data dari Beberapa Situs Web Sekaligus

Untuk mengambil data dari beberapa sumber sekaligus, kita bisa membuat daftar URL dan melakukan scraping secara otomatis. Dalam contoh berikutnya, saya ingin mengambil data dari empat situs web berbeda yang memuat daftar pemain untuk Kejuaraan Eropa (EURO). Ketika kita menggunakan F12, kita melihat bahwa tabel yang kita butuhkan tersembunyi dalam elemen dengan ID tertentu. Dalam hal ini, ID yang diperlukan adalah “yw1”.

Langkah-langkahnya:

  • Buat data frame referensi yang menyimpan daftar URL dan ID tabel.

  • Gunakan loop untuk membaca setiap halaman web dan mengambil tabel yang kita butuhkan.

  • Bersihkan data (hapus kolom yang tidak diperlukan, hilangkan duplikasi, dll.).

  • Gabungkan hasil scraping dari empat situs web menjadi satu tabel.

Setelah loop selesai, kita mendapatkan data dari empat negara sekaligus (Jerman, Spanyol, Italia, dan Prancis) dengan hanya beberapa baris kode.

# Memuat pustaka yang diperlukan
library(rvest)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# Daftar URL dan ID tabel yang akan di-scrape
data_sources <- data.frame(
  country = c("Jerman", "Spanyol", "Italia", "Prancis"),
  url = c(
    "https://www.transfermarkt.com/germany/kader/verein/3262/saison_id/2023/plus/1",
    "https://www.transfermarkt.com/spain/kader/verein/3375/saison_id/2023/plus/1",
    "https://www.transfermarkt.com/italy/kader/verein/3376/saison_id/2023/plus/1",
    "https://www.transfermarkt.com/france/kader/verein/3377/saison_id/2023/plus/1"
  ),
  table_id = '//*[@id="yw1"]' # XPath untuk elemen tabel
)

# List untuk menyimpan data dari tiap halaman
all_data <- list()

# Loop untuk mengambil data dari setiap situs
for (i in 1:nrow(data_sources)) {
  tryCatch({
    # Baca halaman web
    page <- read_html(data_sources$url[i])
    
    # Ambil tabel menggunakan XPath
    table <- page %>% html_node(xpath = data_sources$table_id) %>% html_table(fill = TRUE)
    
    # Pastikan tabel ada sebelum diproses
    if (!is.null(table)) {
      table$Country <- data_sources$country[i] # Tambahkan kolom negara
      all_data[[i]] <- table
    } else {
      message("Tabel tidak ditemukan untuk ", data_sources$country[i])
    }
  }, error = function(e) {
    message("Gagal mengambil data untuk ", data_sources$country[i], ": ", e$message)
  })
}
## Gagal mengambil data untuk Jerman: `xpath` must be a single string, not a character vector.
## Gagal mengambil data untuk Spanyol: `xpath` must be a single string, not a character vector.
## Gagal mengambil data untuk Italia: `xpath` must be a single string, not a character vector.
## Gagal mengambil data untuk Prancis: `xpath` must be a single string, not a character vector.
# Gabungkan semua hasil jika ada data yang berhasil diambil
if (length(all_data) > 0) {
  final_data <- bind_rows(all_data)
  print(final_data)
} else {
  message("Tidak ada data yang berhasil diambil.")
}
## Tidak ada data yang berhasil diambil.

4 Scraping Data Non-Tabel dengan ChatGPT

Misalnya, kita ingin mengekstrak informasi dari 1000 komunitas teratas yang terdaftar di halaman Discovery School. Informasi yang dibutuhkan:

  • Nama komunitas

  • Deskripsi

  • Status (private/public)

  • Jumlah anggota

  • Biaya berlangganan

Ketika kita menekan F12, kita bisa melihat bahwa informasi ini tidak ada dalam tabel, melainkan tersebar di berbagai nodes HTML.

Trik praktis:

  • Klik kanan pada elemen yang berisi data yang kita butuhkan.

  • Pilih Copy Element.

  • Tempelkan kode HTML ke dalam ChatGPT dan tanyakan di mana lokasi informasi yang kita butuhkan.

  • ChatGPT akan menganalisis kode HTML dan memberikan skrip R yang bisa digunakan untuk mengambil data tersebut.

Jika kita ingin mengambil data dari beberapa halaman, kita bisa membuat URL dinamis dengan mengganti nomor halaman di dalam loop. Jika data tersebar di elemen non-tabel, kita bisa menggunakan html_nodes() untuk mengekstrak informasi yang relevan.

# Memuat pustaka yang diperlukan
library(rvest)
library(dplyr)

# Daftar URL komunitas virtual
urls <- c(
  "https://www.reddit.com/r/programming/",
  "https://www.deviantart.com/",
  "https://www.flickr.com/groups/central/",
  "https://www.goodreads.com/group/show/1-goodreads-authors"
)

# Inisialisasi data frame untuk menyimpan data komunitas
community_data <- data.frame(
  Name = character(),
  Description = character(),
  Members = character(),
  Status = character(),
  stringsAsFactors = FALSE
)

# Fungsi untuk membersihkan teks
clean_text <- function(text) {
  gsub("[\r\n\t]", "", text) %>% trimws()
}

# Loop melalui setiap URL
for (url in urls) {
  # Coba untuk membaca halaman web
  try({
    webpage <- read_html(url)
    
    # Mengambil elemen spesifik berdasarkan struktur halaman
    if (grepl("reddit", url)) {
      name <- webpage %>% html_node("h1") %>% html_text() %>% clean_text()
      description <- webpage %>% html_node("p") %>% html_text() %>% clean_text()
      members <- webpage %>% html_node(".subscribers") %>% html_text() %>% clean_text()
      status <- webpage %>% html_node(".usercount") %>% html_text() %>% clean_text()
    } else if (grepl("deviantart", url)) {
      name <- webpage %>% html_node(".group-name") %>% html_text() %>% clean_text()
      description <- webpage %>% html_node(".group-description") %>% html_text() %>% clean_text()
      members <- webpage %>% html_node(".group-stats") %>% html_text() %>% clean_text()
      status <- "Aktif"
    } else if (grepl("flickr", url)) {
      name <- webpage %>% html_node(".group-title") %>% html_text() %>% clean_text()
      description <- webpage %>% html_node(".group-description") %>% html_text() %>% clean_text()
      members <- webpage %>% html_node(".member-count") %>% html_text() %>% clean_text()
      status <- "Aktif"
    } else if (grepl("goodreads", url)) {
      name <- webpage %>% html_node("#groupName") %>% html_text() %>% clean_text()
      description <- webpage %>% html_node("#description") %>% html_text() %>% clean_text()
      members <- webpage %>% html_node(".members") %>% html_text() %>% clean_text()
      status <- "Aktif"
    } else {
      name <- NA
      description <- NA
      members <- NA
      status <- NA
    }
    
    # Menambahkan data ke data frame
    community_data <- rbind(community_data, data.frame(
      Name = name,
      Description = description,
      Members = members,
      Status = status,
      stringsAsFactors = FALSE
    ))
  }, silent = TRUE)
}

# Menampilkan data komunitas
print(community_data)
##   Name
## 1 <NA>
## 2 <NA>
## 3 <NA>
##                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Description
## 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         <NA>
## 2 Deskripsi GrupWelcome to FlickrCentral! Just like Grand Central but without the oyster bar, the trains, New York City...FlickrCentral is a place for the newbies to get a taste of what Flickr is about, and a place for the more experienced users to keep a finger on the pulse of our favorite addiction. This group is for viewing Flickr from high above - a place for posts on things that are about Flickr or would interest MOST Flickrites.We adhere to Flickr's Group Guidelines and Community Guidelines.This is a moderated group. The moderators retain the right to delete (or lock as appropriate) threads and comments that do not follow these rules, guidelines or are perceived to be abusive, redundant, self-promotional/commercial or not leading to novel discussion.
## 3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         <NA>
##   Members Status
## 1    <NA>  Aktif
## 2    <NA>  Aktif
## 3    <NA>  Aktif
LS0tDQp0aXRsZTogIlR1Z2FzIDMgRGF0YSBTY2llbmNlIFByb2dyYW1taW5nIg0Kc3VidGl0bGU6ICJXZWIgU2NyYXBpbmciDQphdXRob3I6IA0KICAiSXNuYWluaSBOdXIgSGFzYW5haCAoNTIyNDAwMDUpIg0KZGF0ZTogICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6ZG93bmN1dGU6ICAgIyBodHRwczovL2dpdGh1Yi5jb20vanViYS9ybWRmb3JtYXRzDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgbGliX2RpcjogbGlicw0KICAgIGRmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjc3M6ICJzdHlsZSAoMSkuY3NzIg0KICAgIHBhcmFtczoNCiAgZWNobzogZmFsc2UNCmVkaXRvcl9vcHRpb25zOiANCiAgbWFya2Rvd246IA0KICAgIHdyYXA6IDcyDQotLS0NCg0KPGltZyBpZD0iSXNuYSIgc3JjPSJDOlxVc2Vyc1xBU1VTXERlc2t0b3BcU3RhdGlzdGlrYSBEYXNhclxJc25hLnBuZyIgYWx0PSJMb2dvIiBzdHlsZT0id2lkdGg6MjAwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87Ij4NCg0KQXBhYmlsYSBraXRhIGluZ2luIG1lbmdhbmFsaXNpcyBzZXN1YXR1LCBraXRhIHBhc3RpIG1lbWJ1dHVoa2FuIGRhdGEuIERhdGEgYmlhc2FueWEgdGVyc2VkaWEgZGFsYW0gZm9ybWF0IHNlcGVydGkgdGVrcywgQ1NWLCBhdGF1IGZpbGUgRXhjZWwsIHNlaGluZ2dhIG11ZGFoIGRpbXVhdCBrZSBkYWxhbSBSIGRhbiBtZW5qYWxhbmthbiBza3JpcCB1bnR1ayBtZW5kYXBhdGthbiBoYXNpbCBkYW4gamF3YWJhbiB5YW5nIGRpYnV0dWhrYW4uIE5hbXVuLCBqaWthIGRhdGEgdGVyc2VidXQgdGlkYWsgZGlzdXN1biBkZW5nYW4gcmFwaSwgbWVsYWlua2FuIHRlcnNlYmFyIGRpIGJlcmJhZ2FpIGxva2FzaSBkaSBzYXR1IGF0YXUgbGViaWggc2l0dXMgd2ViLCBtYWthIGtpdGEgYWthbiBtZW5nZ3VuYWthbiAqKldlYiBTY3JhcGluZyoqLiBXZWIgc2NyYXBpbmcgYWRhbGFoIHRla25payB1bnR1ayBtZW5nYW1iaWwgZGF0YSBkYXJpIHNpdHVzIHdlYiBkYW4gbWVuZ29sYWhueWEgZGFsYW0gYmVudHVrIHlhbmcgbGViaWggdGVyc3RydWt0dXIuIERhbGFtIGxhcG9yYW4gaW5pLCBraXRhIGFrYW4gbWVtYmFoYXMgY2FyYSBtZWxha3VrYW4gd2ViIHNjcmFwaW5nIGRpIFIgbWVuZ2d1bmFrYW4gcGFrZXQgcnZlc3QuIEJlYmVyYXBhIGNvbnRvaCB5YW5nIGRpYmFoYXMgbWVuY2FrdXA6DQoNCi0gQ29weS1wYXN0ZSB0YWJlbCBzZWJhZ2FpIGFsdGVybmF0aWYgc2NyYXBpbmcNCg0KLSBTY3JhcGluZyBkYXRhIGRhcmkgdGFiZWwgZGFsYW0gc2l0dXMgd2ViDQoNCi0gU2NyYXBpbmcgZGFyaSBiZWJlcmFwYSBzaXR1cyB3ZWIgc2VrYWxpZ3VzDQoNCi0gU2NyYXBpbmcgZGF0YSBub24tdGFiZWwgZGVuZ2FuIGJhbnR1YW4gQ2hhdEdQVCANCg0KUGVuamVsYXNhbiBkYXJpIHdlYiBzY3JhcGluZywgeWFpdHU6DQoNCiMgQ29weS1QYXN0ZSBUYWJlbCBNZW5nZ3VuYWthbiBkYXRhcGFzdGENCg0KQ29udG9oIHBlcnRhbWEgc2ViZW5hcm55YSBidWthbiB3ZWIgc2NyYXBpbmcsIG1lbGFpbmthbiBqYWxhbiBwaW50YXMuIEppa2EgQW5kYSBtZW5lbXVrYW4gdGFiZWwgZGkgc2VidWFoIHNpdHVzIHdlYiBkYW4gaW5naW4gbWVuZ2FtYmlsIGluZm9ybWFzaSBkYXJpIHRhYmVsIHRlcnNlYnV0IGtlIGRhbGFtIFIsIHNhbGFoIHNhdHUgY2FyYSB0ZXJjZXBhdCBhZGFsYWg6ICANCg0KICAxLiBTb3JvdCBzZWx1cnVoIHNlbCB0YWJlbC4NCg0KICAyLiBUYWhhbiB0b21ib2wgbW91c2UgaGluZ2dhIG1lbmNhcGFpIGhlYWRlciB0YWJlbC4NCg0KICAzLiBUZWthbiBDdHJsICsgQyBhdGF1IGtsaWsga2FuYW4gZGFuIHBpbGloIENvcHkuDQogIA0KRGkgUiwgc2V0ZWxhaCBtZW5naW5zdGFsIHBha2V0IGRhdGFwYXN0YSwgQW5kYSBha2FuIG1lbWlsaWtpIGZpdHVyIHRhbWJhaGFuIHlhbmcgbWVtdW5na2lua2FuIEFuZGEgbGFuZ3N1bmcgbWVuZW1wZWxrYW4gZGF0YSBkYXJpIGNsaXBib2FyZCBzZWJhZ2FpIGRhdGEgZnJhbWUga2UgZGFsYW0gUi4gTWlzYWxueWEsIHNheWEgaW5naW4gbWVueWltcGFuIGluZm9ybWFzaSBkYWxhbSBzZWJ1YWggb2JqZWsgYmVybmFtYSBPbHltcGljX21lZGFscyBkYW4gbWVuZW1wZWxrYW5ueWEgc2ViYWdhaSBkYXRhIGZyYW1lLiBGb3JtYXRueWEgYWthbiB0ZXJsaWhhdCBzZXBlcnRpIGluaToNCg0KLSBLb2xvbSBwZXJ0YW1hIGJlcmlzaSBwZXJpbmdrYXQgKHJhbmspLg0KDQotIEtvbG9tIE5hdGlvbnMgYmVyaXNpIG5hbWEgbmVnYXJhLg0KDQotIEtvbG9tIGxhaW5ueWEgbWVudW5qdWtrYW4ganVtbGFoIG1lZGFsaSBlbWFzLCBwZXJhaywgZGFuIHBlcnVuZ2d1IHlhbmcgZGltZW5hbmdrYW4sIHNlcnRhIHRvdGFsbnlhLg0KDQotIFRpcGUgZGF0YSBha2FuIGRpa2VuYWxpIHNlY2FyYSBvdG9tYXRpcywgZGVuZ2FuIG5hbWEgbmVnYXJhIHNlYmFnYWkga2FyYWt0ZXIgZGFuIGp1bWxhaCBtZWRhbGkgc2ViYWdhaSBpbnRlZ2VyLg0KICANCmBgYHtyfQ0KIyMgMSkgZGF0YXBhc3RhIA0KbGlicmFyeShkYXRhcGFzdGEpDQoNCiNodHRwczovL3d3dy50b3BlbmRzcG9ydHMuY29tL2V2ZW50cy9zdW1tZXIvbWVkYWwtdGFsbHkvYWxsLXRpbWUtYWxsLmh0bQ0KDQpvbHltcGljX21lZGFscyA8LSBkYXRhLmZyYW1lKA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsDQogICAgICAgY2hlY2submFtZXMgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmFuayA9IGMoMUwsMkwsM0wsNEwsNUwsNkwsN0wsOEwsOUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEwTCwxMUwsMTJMLDEzTCwxNEwsMTVMLDE2TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTdMLDE4TCwxOUwsMjBMLDIxTCwyMkwsMjNMLDI0TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMjVMLDI2TCwyN0wsMjhMLDI5TCwzMEwsMzFMLDMyTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMzNMLDM0TCwzNUwsMzZMLDM3TCwzOEwsMzlMLDQwTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNDFMLDQyTCw0M0wsNDRMLDQ1TCw0NkwsNDdMLDQ4TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNDlMLDUwTCw1MUwsNTJMLDUzTCw1NEwsNTVMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1NkwsNTdMLDU4TCw1OUwsNjBMLDYxTCw2MkwsNjNMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA2NEwsNjVMLDY2TCw2N0wsNjhMLDY5TCw3MEwsNzFMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA3MkwsNzNMLDc0TCw3NUwsNzZMLDc3TCw3OEwsNzlMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA4MEwsODFMLDgyTCw4M0wsODRMLDg1TCw4NkwsODdMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA4OEwsODlMLDkwTCw5MUwsOTJMLDkzTCw5NEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDk1TCw5NkwsOTdMLDk4TCw5OUwsMTAwTCwxMDFMLDEwMkwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEwM0wsMTA0TCwxMDVMLDEwNkwsMTA3TCwxMDhMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMDlMLDExMEwsMTExTCwxMTJMLDExM0wsMTE0TCwxMTVMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMTZMLDExN0wsMTE4TCwxMTlMLDEyMEwsMTIxTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTIyTCwxMjNMLDEyNEwsMTI1TCwxMjZMLDEyN0wsMTI4TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTI5TCwxMzBMLDEzMUwsMTMyTCwxMzNMLDEzNEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEzNUwsMTM2TCwxMzdMLDEzOEwsMTM5TCwxNDBMLDE0MUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDE0MkwsMTQzTCwxNDRMLDE0NUwsMTQ2TCwxNDdMKSwNCiAgICAgICAgICAgICAgICAgICAgICBgTmF0aW9uLihOT0MpYCA9IGMoIlVuaXRlZCBTdGF0ZXMiLCJTb3ZpZXQgVW5pb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR2VybWFueSIsIkdyZWF0IEJyaXRhaW4iLCJDaGluYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGcmFuY2UiLCJJdGFseSIsIkh1bmdhcnkiLCJSdXNzaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSmFwYW4iLCJBdXN0cmFsaWEiLCJFYXN0IEdlcm1hbnkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3dlZGVuIiwiRmlubGFuZCIsIlNvdXRoIEtvcmVhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldGhlcmxhbmRzIiwiUm9tYW5pYSIsIkN1YmEiLCJQb2xhbmQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2FuYWRhIiwiTm9yd2F5IiwiQnVsZ2FyaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3dpdHplcmxhbmQiLCJOZXcgWmVhbGFuZCIsIkN6ZWNob3Nsb3Zha2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRlbm1hcmsiLCJTcGFpbiIsIkJlbGdpdW0iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVMO8cmtpeWUiLCJCcmF6aWwiLCJVa3JhaW5lIiwiR3JlZWNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIktlbnlhIiwiWXVnb3NsYXZpYSIsIlNvdXRoIEFmcmljYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKYW1haWNhIiwiSXJhbiIsIkV0aGlvcGlhIiwiQXJnZW50aW5hIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkF1c3RyaWEiLCJDemVjaGlhIiwiTm9ydGggS29yZWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiS2F6YWtoc3RhbiIsIkNyb2F0aWEiLCJCZWxhcnVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1leGljbyIsIklyZWxhbmQiLCJHZW9yZ2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlV6YmVraXN0YW4iLCJFc3RvbmlhIiwiVGhhaWxhbmQiLCJJbmRpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTbG92YWtpYSIsIkVneXB0IiwiSW5kb25lc2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNsb3ZlbmlhIiwiTWl4ZWQgdGVhbSIsIkJhaGFtYXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXplcmJhaWphbiIsIkNoaW5lc2UgVGFpcGVpIiwiTW9yb2NjbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMaXRodWFuaWEiLCJTZXJiaWEiLCJDb2xvbWJpYSIsIlBvcnR1Z2FsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFsZ2VyaWEiLCJUdW5pc2lhIiwiTGF0dmlhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVnYW5kYSIsIk5pZ2VyaWEiLCJWZW5lenVlbGEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVHJpbmlkYWQgYW5kIFRvYmFnbyIsIklzcmFlbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEb21pbmljYW4gUmVwdWJsaWMiLCJQYWtpc3RhbiIsIlppbWJhYndlIiwiQ2FtZXJvb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRWN1YWRvciIsIktvc292byIsIk1vbmdvbGlhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFybWVuaWEiLCJDaGlsZSIsIlB1ZXJ0byBSaWNvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVydWd1YXkiLCJIb25nIEtvbmciLCJRYXRhciIsIkZpamkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFocmFpbiIsIlBoaWxpcHBpbmVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkluZGVwZW5kZW50IE9seW1waWMgQXRobGV0ZXMvUGFydGljaXBhbnRzIiwiU2luZ2Fwb3JlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZpZXRuYW0iLCJDb3N0YSBSaWNhIiwiUGVydSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJdm9yeSBDb2FzdCIsIlRhamlraXN0YW4iLCJTeXJpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcmVuYWRhIiwiUGFuYW1hIiwiSm9yZGFuIiwiU3VyaW5hbWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmVybXVkYSIsIk1vemFtYmlxdWUiLCJCdXJ1bmRpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkx1eGVtYm91cmciLCJVbml0ZWQgQXJhYiBFbWlyYXRlcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNYWxheXNpYSIsIkt5cmd5enN0YW4iLCJNb2xkb3ZhIiwiR2hhbmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFtaWJpYSIsIkJvaGVtaWEiLCJJY2VsYW5kIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNhdWRpIEFyYWJpYSIsIkxlYmFub24iLCJTYW4gTWFyaW5vIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkt1d2FpdCIsIlNyaSBMYW5rYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZXJiaWEgYW5kIE1vbnRlbmVncm8iLCJIYWl0aSIsIk5vcnRoIE1hY2Vkb25pYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOaWdlciIsIlphbWJpYSIsIkJyaXRpc2ggV2VzdCBJbmRpZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQm90c3dhbmEiLCJUYW56YW5pYSIsIkFmZ2hhbmlzdGFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklyYXEiLCJTdWRhbiIsIkN5cHJ1cyIsIlNlbmVnYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2Ftb2EiLCJHdXlhbmEiLCJHdWF0ZW1hbGEiLCJQYXJhZ3VheSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZXRoZXJsYW5kcyBBbnRpbGxlcyIsIkdhYm9uIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhcmJhZG9zIiwiTW9udGVuZWdybyIsIk1hdXJpdGl1cyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFcml0cmVhIiwiQnVya2luYSBGYXNvIiwiVmlyZ2luIElzbGFuZHMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRGppYm91dGkiLCJUdXJrbWVuaXN0YW4iLCJUb25nYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUb2dvIiksDQogICAgICAgICAgICAgICAgICAgICAgICBOby4ub2YuR2FtZXMgPSBjKDI4TCwxMEwsMjVMLDI5TCwxMUwsMjlMLDI4TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMjdMLDEwTCwyM0wsMjlMLDVMLDI4TCwyNkwsMThMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyN0wsMjJMLDIxTCwyMkwsMjdMLDI2TCwyMUwsMjlMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyNEwsMTZMLDI4TCwyNEwsMjdMLDIzTCwyM0wsN0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDI5TCwxNUwsMThMLDIwTCwxOEwsMTdMLDE0TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMjVMLDI4TCw3TCwxMEwsN0wsOEwsN0wsMjRMLDIyTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgN0wsN0wsMTNMLDE3TCwyNUwsN0wsMjNMLDE2TCw4TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgM0wsMTdMLDdMLDE1TCwxNUwsMTBMLDVMLDIwTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMjVMLDE0TCwxNUwsMTJMLDE2TCwxN0wsMTlMLDE4TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTdMLDE1TCwxOEwsMTRMLDE1TCwxNUwsMkwsMTRMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA3TCwyNEwsMTlMLDIyTCwxN0wsMTBMLDE1TCwxMEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIyTCw0TCwxN0wsMTZMLDE2TCwxOUwsMTRMLDdMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxNEwsMTBMLDE4TCwxMUwsMTNMLDE5TCwxMUwsN0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDI0TCwxMEwsMTRMLDdMLDdMLDE1TCw4TCwzTCwyMUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEyTCwxOEwsMTVMLDEzTCwxOEwsMUwsMTZMLDdMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxM0wsMTRMLDFMLDExTCwxNEwsMTVMLDE1TCwxM0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDExTCwxNUwsMTBMLDE4TCwxNUwsMTNMLDEzTCwxMUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEzTCw0TCwxMEwsNkwsMTBMLDEzTCw5TCw3TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTBMLDExTCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdvbGQgPSBjKDEwNjFMLDQ0MEwsMjg1TCwyODVMLDI2MkwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIyNkwsMjE3TCwxODFMLDE3MEwsMTY5TCwxNjdMLDE1M0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDE0OEwsMTAxTCw5NkwsOTVMLDkwTCw4NUwsNzJMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA3MUwsNjBMLDU0TCw1M0wsNTNMLDQ5TCw0OEwsNDhMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA0M0wsNDFMLDM3TCwzNUwsMzVMLDM1TCwyOEwsMjdMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyNkwsMjRMLDIzTCwyMUwsMTlMLDE5TCwxNkwsMTVMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxNEwsMTNMLDEzTCwxMUwsMTBMLDEwTCwxMEwsMTBMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMEwsMTBMLDhMLDhMLDhMLDhMLDhMLDdMLDdMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA3TCw2TCw2TCw1TCw1TCw1TCw1TCw0TCw0TCwzTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgM0wsM0wsM0wsM0wsM0wsM0wsM0wsM0wsM0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDJMLDJMLDJMLDJMLDJMLDJMLDJMLDJMLDJMLDFMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxTCwxTCwxTCwxTCwxTCwxTCwxTCwxTCwxTCwxTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMUwsMUwsMUwsMUwsMUwsMUwsMUwsMEwsMEwsMEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBMLDBMLDBMLDBMLDBMLDBMLDBMLDBMLDBMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwTCwwTCwwTCwwTCwwTCwwTCwwTCwwTCwwTCwwTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMEwsMEwsMEwsMEwsMEwsMEwsMEwsMEwsMEwsMEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBMLDBMLDBMLDBMLDBMLDBMLDBMLDBMLDBMKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNpbHZlciA9IGMoODM2TCwzNTdMLDMyNkwsMzE1TCwxOTlMLDI1OEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDE4OEwsMTU0TCwxNTdMLDE1MEwsMTc3TCwxMjlMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxNzZMLDg1TCw5MUwsMTA0TCw5N0wsNzFMLDg5TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTA4TCw1MUwsODhMLDc5TCwzM0wsNDlMLDc4TCw3MkwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDU0TCwyNkwsNDJMLDM2TCw0NUwsNDJMLDMxTCwzM0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDM2TCwyM0wsMTJMLDI2TCwzNEwsMjFMLDE2TCwyMUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEzTCwzMEwsMjRMLDEwTCwxMkwsNkwsOUwsOEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDlMLDE0TCwxMUwsMTRMLDlMLDRMLDJMLDE0TCwxMUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDVMLDdMLDdMLDEzTCw5TCw0TCwzTCwxMUwsNEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDExTCw3TCw1TCwxTCw1TCwzTCw0TCwxTCwyTCwwTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTFMLDhMLDdMLDJMLDJMLDNMLDFMLDBMLDFMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1TCwxTCwyTCwzTCwxTCwzTCwxTCwxTCwxTCwxTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMEwsMUwsMEwsMEwsMEwsMUwsMUwsMEwsOEwsM0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDJMLDFMLDVMLDFMLDJMLDJMLDJMLDFMLDBMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyTCwyTCwxTCwxTCwxTCwxTCwwTCwxTCwyTCwwTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMEwsMUwsMUwsMUwsMUwsMEwsMUwsMUwsMUwsMUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBMLDFMLDBMLDBMLDBMLDFMLDBMLDFMLDFMLDBMKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJyb256ZSA9IGMoNzM5TCwzMjVMLDM2M0wsMzE1TCwxNzNMLDI4MEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIxM0wsMTc2TCwxNzhMLDE3OEwsMjEzTCwxMjdMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxNzlMLDExOUwsMTAwTCwxMjJMLDEyMUwsODVMLDEzN0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDE0N0wsNDlMLDgyTCw3M0wsNTNMLDQ1TCw3OUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQ3TCw1OEwsMzdMLDcxTCw2OEwsNDFMLDM2TCwzMUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDI5TCwyNUwsMjlMLDIzTCwzMEwsNDFMLDI3TCwyMkwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDM2TCwxNEwsNDJMLDM2TCwxNEwsMThMLDIwTCwxN0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDE3TCwxNEwsOEwsMTlMLDE1TCwxMUwsNEwsNkwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDI4TCwxOEwsMTJMLDEzTCwxMUwsMTVMLDE0TCw4TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgN0wsNkwsM0wsMTNMLDlMLDExTCw5TCw0TCw0TCwxTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMkwsMEwsMEwsMTdMLDhMLDRMLDZMLDZMLDRMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1TCwxTCwwTCw4TCwzTCwyTCwxTCwyTCwwTCwyTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMkwsMkwsMUwsMkwsMUwsMUwsMUwsMUwsMEwsMEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDFMLDVMLDRMLDRMLDRMLDBMLDNMLDJMLDJMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyTCwyTCwzTCwwTCwwTCwxTCwxTCwxTCwxTCwyTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMUwsMEwsMkwsMUwsMEwsMEwsMEwsMEwsMUwsMEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBMLDBMLDBMLDFMLDBMLDFMLDFMLDFMLDBMLDFMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwTCwwTCwxTCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG90YWwgPSBjKDI2MzZMLDExMjJMLDk3NEwsOTE1TCw2MzRMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA3NjRMLDYxOEwsNTExTCw1MDVMLDQ5N0wsNTU3TCw0MDlMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1MDNMLDMwNUwsMjg3TCwzMjFMLDMwOEwsMjQxTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMjk4TCwzMjZMLDE2MEwsMjI0TCwyMDVMLDEzOUwsMTQzTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMjA1TCwxNjdMLDE1NUwsMTA0TCwxNTBMLDEzOUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEyMUwsMTEzTCw5MEwsODlMLDg3TCw3NkwsNThMLDc3TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOTRMLDY3TCw1NEwsNzJMLDQxTCw4NUwsNzNMLDM1TCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNDBMLDM2TCwzNkwsMzVMLDM1TCwzMkwsMzhMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzN0wsMjhMLDE2TCwxNEwsNDlMLDM2TCwyNEwsMjZMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyNEwsMzNMLDI4TCwxN0wsMTVMLDIxTCwxMUwsMjdMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxOUwsMTlMLDEzTCwxMkwsMTBMLDhMLDZMLDVMLDNMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzMEwsMThMLDEzTCwxMEwsMTBMLDlMLDhMLDNMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzTCwxNEwsNUwsNUwsNUwsNEwsNEwsNEwsNEwsNEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDNMLDNMLDNMLDJMLDJMLDJMLDJMLDJMLDJMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxM0wsN0wsNkwsNUwsNUwsNEwsNEwsNEwsNEwsM0wsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDNMLDJMLDJMLDJMLDJMLDJMLDJMLDJMLDJMLDJMLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyTCwxTCwxTCwxTCwxTCwxTCwxTCwxTCwxTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMUwsMUwsMUwsMUwsMUwsMUwsMUwsMUwsMUwsMUwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDFMLDFMKQ0KICAgICAgICAgICAgICAgICAgKQ0KDQpwcmludChvbHltcGljX21lZGFscykNCmBgYA0KDQojIFNjcmFwaW5nIERhdGEgZGFyaSBUYWJlbCBkYWxhbSBTaXR1cyBXZWINCg0KDQpKaWthIHRhYmVsIHRpZGFrIGJpc2EgZGlzYWxpbiBzZWNhcmEgbWFudWFsLCBraXRhIG1lbWVybHVrYW4gcGFrZXQgcnZlc3QuIFBha2V0IGluaSBkaXVjYXBrYW4gc2VwZXJ0aSAiSGFydmVzdCIsIGthcmVuYSBraXRhIGluZ2luIG1lbWFuZW4gZGF0YSBkYXJpIHNpdHVzIHdlYi4gRnVuZ3NpIHBlcnRhbWEgeWFuZyBraXRhIHBlcmx1a2FuIGFkYWxhaCByZWFkX2h0bWwoKSwgeWFuZyBtZW1lcmx1a2FuIFVSTCBzZWJhZ2FpIGlucHV0LiBNaXNhbG55YSwga2l0YSBpbmdpbiBtZW5nYW1iaWwgZGFmdGFyIHBha2V0IFIgZGFsYW0gdXJ1dGFuIGFsZmFiZXQgZGFyaSBzZWJ1YWggc2l0dXMgd2ViLiBKaWthIGtpdGEgbWVuamFsYW5rYW4ga29kZSB1bnR1ayBtZW1iYWNhIEhUTUwgZGFyaSBzaXR1cyB0ZXJzZWJ1dCwga2l0YSBha2FuIG1lbGloYXQgYmFod2Egb2JqZWsgeWFuZyBkaWhhc2lsa2FuIGFkYWxhaCBkb2t1bWVuIEhUTUwgZGVuZ2FuIHN0cnVrdHVyIGhlYWQgZGFuIGJvZHkuDQoNClNhYXQga2l0YSBtZWxpaGF0IGlzaSBoYWxhbWFuIHdlYiB0ZXJzZWJ1dCwga2l0YSBtZWxpaGF0IGJhaHdhIGluZm9ybWFzaSB5YW5nIGtpdGEgYnV0dWhrYW4gdGVyc2VtYnVueWkgZGkgZGFsYW0gbm9kZSBIVE1MLiBEZW5nYW4gbWVuZWthbiBGMTIsIGtpdGEgYmlzYSBtZW1idWthIGFsYXQgcGVuZ2VtYmFuZyBkYW4gbWVuZ2d1bmFrYW4gZWxlbWVudCBpbnNwZWN0b3IgdW50dWsgbWVuZW11a2FuIGVsZW1lbiB5YW5nIG1lbXVhdCBkYXRhIHlhbmcga2l0YSBidXR1aGthbi4gTWlzYWxueWEsIGtpdGEgaW5naW4gbWVuZ2FtYmlsIHRhYmVsIGJlcmlzaSBkYWZ0YXIgcGFrZXQgUi4gRGVuZ2FuIG1lbmdndW5ha2FuIEhUTUwgbm9kZSBpbnNwZWN0b3IsIGtpdGEgYmlzYSBtZW5lbXVrYW4gZWxlbWVuIHlhbmcgbWVueWltcGFuIGRhdGEgdGVyc2VidXQuIEtlbXVkaWFuLCBraXRhIGJpc2EgbWVuZ2d1bmFrYW4gaHRtbF9ub2RlKCkgdW50dWsgbWVuZ2FtYmlsIGVsZW1lbiB0ZXJzZWJ1dCBkYW4gaHRtbF90YWJsZSgpIHVudHVrIG1lbmd1YmFobnlhIG1lbmphZGkgZGF0YSBmcmFtZS4gU2V0ZWxhaCBkaWJlcnNpaGthbiAobWVuZ2hhcHVzIE5BIGRhbiBwbGFjZWhvbGRlciBkaSBhbnRhcmEgaHVydWYgYWxmYWJldCksIGtpdGEgbWVuZGFwYXRrYW4gdGFiZWwgeWFuZyByYXBpIGJlcmlzaSBuYW1hIGRhbiBkZXNrcmlwc2kgcGFrZXQgUi4NCmBgYHtyfQ0KIyMgMikgYmFzaWMgd2Vic2NyYXBpbmcNCmxpYnJhcnkocnZlc3QpDQoNCnVybCA8LSAiaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2F2YWlsYWJsZV9wYWNrYWdlc19ieV9uYW1lLmh0bWwiDQoNCiMgTWVtYmFjYSBIVE1MIGRhcmkgc2l0dXMNCndlYnBhZ2UgPC0gcmVhZF9odG1sKHVybCkNCg0KIyBNZW5nYW1iaWwgdGFiZWwgZGFyaSBoYWxhbWFuDQpwYWtldF90YWJsZSA8LSB3ZWJwYWdlICU+JSBodG1sX25vZGUoInRhYmxlIikgJT4lIGh0bWxfdGFibGUoZmlsbCA9IFRSVUUpDQoNCiMgTWVuYW1waWxrYW4gZGF0YSB5YW5nIHRlbGFoIGRpYW1iaWwNCnByaW50KHBha2V0X3RhYmxlKQ0KYGBgDQojIFNjcmFwaW5nIERhdGEgZGFyaSBCZWJlcmFwYSBTaXR1cyBXZWIgU2VrYWxpZ3VzDQoNClVudHVrIG1lbmdhbWJpbCBkYXRhIGRhcmkgYmViZXJhcGEgc3VtYmVyIHNla2FsaWd1cywga2l0YSBiaXNhIG1lbWJ1YXQgZGFmdGFyIFVSTCBkYW4gbWVsYWt1a2FuIHNjcmFwaW5nIHNlY2FyYSBvdG9tYXRpcy4NCkRhbGFtIGNvbnRvaCBiZXJpa3V0bnlhLCBzYXlhIGluZ2luIG1lbmdhbWJpbCBkYXRhIGRhcmkgZW1wYXQgc2l0dXMgd2ViIGJlcmJlZGEgeWFuZyBtZW11YXQgZGFmdGFyIHBlbWFpbiB1bnR1ayBLZWp1YXJhYW4gRXJvcGEgKEVVUk8pLiBLZXRpa2Ega2l0YSBtZW5nZ3VuYWthbiBGMTIsIGtpdGEgbWVsaWhhdCBiYWh3YSB0YWJlbCB5YW5nIGtpdGEgYnV0dWhrYW4gdGVyc2VtYnVueWkgZGFsYW0gZWxlbWVuIGRlbmdhbiBJRCB0ZXJ0ZW50dS4gRGFsYW0gaGFsIGluaSwgSUQgeWFuZyBkaXBlcmx1a2FuIGFkYWxhaCAieXcxIi4NCg0KKipMYW5na2FoLWxhbmdrYWhueWE6KioNCg0KLSBCdWF0IGRhdGEgZnJhbWUgcmVmZXJlbnNpIHlhbmcgbWVueWltcGFuIGRhZnRhciBVUkwgZGFuIElEIHRhYmVsLg0KDQotIEd1bmFrYW4gbG9vcCB1bnR1ayBtZW1iYWNhIHNldGlhcCBoYWxhbWFuIHdlYiBkYW4gbWVuZ2FtYmlsIHRhYmVsIHlhbmcga2l0YSBidXR1aGthbi4NCg0KLSBCZXJzaWhrYW4gZGF0YSAoaGFwdXMga29sb20geWFuZyB0aWRhayBkaXBlcmx1a2FuLCBoaWxhbmdrYW4gZHVwbGlrYXNpLCBkbGwuKS4NCg0KLSBHYWJ1bmdrYW4gaGFzaWwgc2NyYXBpbmcgZGFyaSBlbXBhdCBzaXR1cyB3ZWIgbWVuamFkaSBzYXR1IHRhYmVsLg0KDQpTZXRlbGFoIGxvb3Agc2VsZXNhaSwga2l0YSBtZW5kYXBhdGthbiBkYXRhIGRhcmkgZW1wYXQgbmVnYXJhIHNla2FsaWd1cyAoSmVybWFuLCBTcGFueW9sLCBJdGFsaWEsIGRhbiBQcmFuY2lzKSBkZW5nYW4gaGFueWEgYmViZXJhcGEgYmFyaXMga29kZS4NCg0KDQpgYGB7cn0NCiMgTWVtdWF0IHB1c3Rha2EgeWFuZyBkaXBlcmx1a2FuDQpsaWJyYXJ5KHJ2ZXN0KQ0KbGlicmFyeShkcGx5cikNCg0KIyBEYWZ0YXIgVVJMIGRhbiBJRCB0YWJlbCB5YW5nIGFrYW4gZGktc2NyYXBlDQpkYXRhX3NvdXJjZXMgPC0gZGF0YS5mcmFtZSgNCiAgY291bnRyeSA9IGMoIkplcm1hbiIsICJTcGFueW9sIiwgIkl0YWxpYSIsICJQcmFuY2lzIiksDQogIHVybCA9IGMoDQogICAgImh0dHBzOi8vd3d3LnRyYW5zZmVybWFya3QuY29tL2dlcm1hbnkva2FkZXIvdmVyZWluLzMyNjIvc2Fpc29uX2lkLzIwMjMvcGx1cy8xIiwNCiAgICAiaHR0cHM6Ly93d3cudHJhbnNmZXJtYXJrdC5jb20vc3BhaW4va2FkZXIvdmVyZWluLzMzNzUvc2Fpc29uX2lkLzIwMjMvcGx1cy8xIiwNCiAgICAiaHR0cHM6Ly93d3cudHJhbnNmZXJtYXJrdC5jb20vaXRhbHkva2FkZXIvdmVyZWluLzMzNzYvc2Fpc29uX2lkLzIwMjMvcGx1cy8xIiwNCiAgICAiaHR0cHM6Ly93d3cudHJhbnNmZXJtYXJrdC5jb20vZnJhbmNlL2thZGVyL3ZlcmVpbi8zMzc3L3NhaXNvbl9pZC8yMDIzL3BsdXMvMSINCiAgKSwNCiAgdGFibGVfaWQgPSAnLy8qW0BpZD0ieXcxIl0nICMgWFBhdGggdW50dWsgZWxlbWVuIHRhYmVsDQopDQoNCiMgTGlzdCB1bnR1ayBtZW55aW1wYW4gZGF0YSBkYXJpIHRpYXAgaGFsYW1hbg0KYWxsX2RhdGEgPC0gbGlzdCgpDQoNCiMgTG9vcCB1bnR1ayBtZW5nYW1iaWwgZGF0YSBkYXJpIHNldGlhcCBzaXR1cw0KZm9yIChpIGluIDE6bnJvdyhkYXRhX3NvdXJjZXMpKSB7DQogIHRyeUNhdGNoKHsNCiAgICAjIEJhY2EgaGFsYW1hbiB3ZWINCiAgICBwYWdlIDwtIHJlYWRfaHRtbChkYXRhX3NvdXJjZXMkdXJsW2ldKQ0KICAgIA0KICAgICMgQW1iaWwgdGFiZWwgbWVuZ2d1bmFrYW4gWFBhdGgNCiAgICB0YWJsZSA8LSBwYWdlICU+JSBodG1sX25vZGUoeHBhdGggPSBkYXRhX3NvdXJjZXMkdGFibGVfaWQpICU+JSBodG1sX3RhYmxlKGZpbGwgPSBUUlVFKQ0KICAgIA0KICAgICMgUGFzdGlrYW4gdGFiZWwgYWRhIHNlYmVsdW0gZGlwcm9zZXMNCiAgICBpZiAoIWlzLm51bGwodGFibGUpKSB7DQogICAgICB0YWJsZSRDb3VudHJ5IDwtIGRhdGFfc291cmNlcyRjb3VudHJ5W2ldICMgVGFtYmFoa2FuIGtvbG9tIG5lZ2FyYQ0KICAgICAgYWxsX2RhdGFbW2ldXSA8LSB0YWJsZQ0KICAgIH0gZWxzZSB7DQogICAgICBtZXNzYWdlKCJUYWJlbCB0aWRhayBkaXRlbXVrYW4gdW50dWsgIiwgZGF0YV9zb3VyY2VzJGNvdW50cnlbaV0pDQogICAgfQ0KICB9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIHsNCiAgICBtZXNzYWdlKCJHYWdhbCBtZW5nYW1iaWwgZGF0YSB1bnR1ayAiLCBkYXRhX3NvdXJjZXMkY291bnRyeVtpXSwgIjogIiwgZSRtZXNzYWdlKQ0KICB9KQ0KfQ0KDQojIEdhYnVuZ2thbiBzZW11YSBoYXNpbCBqaWthIGFkYSBkYXRhIHlhbmcgYmVyaGFzaWwgZGlhbWJpbA0KaWYgKGxlbmd0aChhbGxfZGF0YSkgPiAwKSB7DQogIGZpbmFsX2RhdGEgPC0gYmluZF9yb3dzKGFsbF9kYXRhKQ0KICBwcmludChmaW5hbF9kYXRhKQ0KfSBlbHNlIHsNCiAgbWVzc2FnZSgiVGlkYWsgYWRhIGRhdGEgeWFuZyBiZXJoYXNpbCBkaWFtYmlsLiIpDQp9DQpgYGANCg0KDQojIFNjcmFwaW5nIERhdGEgTm9uLVRhYmVsIGRlbmdhbiBDaGF0R1BUDQoNCk1pc2FsbnlhLCBraXRhIGluZ2luIG1lbmdla3N0cmFrIGluZm9ybWFzaSBkYXJpIDEwMDAga29tdW5pdGFzIHRlcmF0YXMgeWFuZyB0ZXJkYWZ0YXIgZGkgaGFsYW1hbiBEaXNjb3ZlcnkgU2Nob29sLiBJbmZvcm1hc2kgeWFuZyBkaWJ1dHVoa2FuOg0KDQotIE5hbWEga29tdW5pdGFzDQoNCi0gRGVza3JpcHNpDQoNCi0gU3RhdHVzIChwcml2YXRlL3B1YmxpYykNCg0KLSBKdW1sYWggYW5nZ290YQ0KDQotIEJpYXlhIGJlcmxhbmdnYW5hbg0KDQpLZXRpa2Ega2l0YSBtZW5la2FuIEYxMiwga2l0YSBiaXNhIG1lbGloYXQgYmFod2EgaW5mb3JtYXNpIGluaSB0aWRhayBhZGEgZGFsYW0gdGFiZWwsIG1lbGFpbmthbiB0ZXJzZWJhciBkaSBiZXJiYWdhaSBub2RlcyBIVE1MLg0KDQoqKlRyaWsgcHJha3RpczoqKg0KDQotIEtsaWsga2FuYW4gcGFkYSBlbGVtZW4geWFuZyBiZXJpc2kgZGF0YSB5YW5nIGtpdGEgYnV0dWhrYW4uDQoNCi0gUGlsaWggQ29weSBFbGVtZW50Lg0KDQotIFRlbXBlbGthbiBrb2RlIEhUTUwga2UgZGFsYW0gQ2hhdEdQVCBkYW4gdGFueWFrYW4gZGkgbWFuYSBsb2thc2kgaW5mb3JtYXNpIHlhbmcga2l0YSBidXR1aGthbi4NCg0KLSBDaGF0R1BUIGFrYW4gbWVuZ2FuYWxpc2lzIGtvZGUgSFRNTCBkYW4gbWVtYmVyaWthbiBza3JpcCBSIHlhbmcgYmlzYSBkaWd1bmFrYW4gdW50dWsgbWVuZ2FtYmlsIGRhdGEgdGVyc2VidXQuDQoNCkppa2Ega2l0YSBpbmdpbiBtZW5nYW1iaWwgZGF0YSBkYXJpIGJlYmVyYXBhIGhhbGFtYW4sIGtpdGEgYmlzYSBtZW1idWF0IFVSTCBkaW5hbWlzIGRlbmdhbiBtZW5nZ2FudGkgbm9tb3IgaGFsYW1hbiBkaSBkYWxhbSBsb29wLg0KSmlrYSBkYXRhIHRlcnNlYmFyIGRpIGVsZW1lbiBub24tdGFiZWwsIGtpdGEgYmlzYSBtZW5nZ3VuYWthbiBodG1sX25vZGVzKCkgdW50dWsgbWVuZ2Vrc3RyYWsgaW5mb3JtYXNpIHlhbmcgcmVsZXZhbi4NCg0KYGBge3J9DQojIE1lbXVhdCBwdXN0YWthIHlhbmcgZGlwZXJsdWthbg0KbGlicmFyeShydmVzdCkNCmxpYnJhcnkoZHBseXIpDQoNCiMgRGFmdGFyIFVSTCBrb211bml0YXMgdmlydHVhbA0KdXJscyA8LSBjKA0KICAiaHR0cHM6Ly93d3cucmVkZGl0LmNvbS9yL3Byb2dyYW1taW5nLyIsDQogICJodHRwczovL3d3dy5kZXZpYW50YXJ0LmNvbS8iLA0KICAiaHR0cHM6Ly93d3cuZmxpY2tyLmNvbS9ncm91cHMvY2VudHJhbC8iLA0KICAiaHR0cHM6Ly93d3cuZ29vZHJlYWRzLmNvbS9ncm91cC9zaG93LzEtZ29vZHJlYWRzLWF1dGhvcnMiDQopDQoNCiMgSW5pc2lhbGlzYXNpIGRhdGEgZnJhbWUgdW50dWsgbWVueWltcGFuIGRhdGEga29tdW5pdGFzDQpjb21tdW5pdHlfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBOYW1lID0gY2hhcmFjdGVyKCksDQogIERlc2NyaXB0aW9uID0gY2hhcmFjdGVyKCksDQogIE1lbWJlcnMgPSBjaGFyYWN0ZXIoKSwNCiAgU3RhdHVzID0gY2hhcmFjdGVyKCksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQojIEZ1bmdzaSB1bnR1ayBtZW1iZXJzaWhrYW4gdGVrcw0KY2xlYW5fdGV4dCA8LSBmdW5jdGlvbih0ZXh0KSB7DQogIGdzdWIoIltcclxuXHRdIiwgIiIsIHRleHQpICU+JSB0cmltd3MoKQ0KfQ0KDQojIExvb3AgbWVsYWx1aSBzZXRpYXAgVVJMDQpmb3IgKHVybCBpbiB1cmxzKSB7DQogICMgQ29iYSB1bnR1ayBtZW1iYWNhIGhhbGFtYW4gd2ViDQogIHRyeSh7DQogICAgd2VicGFnZSA8LSByZWFkX2h0bWwodXJsKQ0KICAgIA0KICAgICMgTWVuZ2FtYmlsIGVsZW1lbiBzcGVzaWZpayBiZXJkYXNhcmthbiBzdHJ1a3R1ciBoYWxhbWFuDQogICAgaWYgKGdyZXBsKCJyZWRkaXQiLCB1cmwpKSB7DQogICAgICBuYW1lIDwtIHdlYnBhZ2UgJT4lIGh0bWxfbm9kZSgiaDEiKSAlPiUgaHRtbF90ZXh0KCkgJT4lIGNsZWFuX3RleHQoKQ0KICAgICAgZGVzY3JpcHRpb24gPC0gd2VicGFnZSAlPiUgaHRtbF9ub2RlKCJwIikgJT4lIGh0bWxfdGV4dCgpICU+JSBjbGVhbl90ZXh0KCkNCiAgICAgIG1lbWJlcnMgPC0gd2VicGFnZSAlPiUgaHRtbF9ub2RlKCIuc3Vic2NyaWJlcnMiKSAlPiUgaHRtbF90ZXh0KCkgJT4lIGNsZWFuX3RleHQoKQ0KICAgICAgc3RhdHVzIDwtIHdlYnBhZ2UgJT4lIGh0bWxfbm9kZSgiLnVzZXJjb3VudCIpICU+JSBodG1sX3RleHQoKSAlPiUgY2xlYW5fdGV4dCgpDQogICAgfSBlbHNlIGlmIChncmVwbCgiZGV2aWFudGFydCIsIHVybCkpIHsNCiAgICAgIG5hbWUgPC0gd2VicGFnZSAlPiUgaHRtbF9ub2RlKCIuZ3JvdXAtbmFtZSIpICU+JSBodG1sX3RleHQoKSAlPiUgY2xlYW5fdGV4dCgpDQogICAgICBkZXNjcmlwdGlvbiA8LSB3ZWJwYWdlICU+JSBodG1sX25vZGUoIi5ncm91cC1kZXNjcmlwdGlvbiIpICU+JSBodG1sX3RleHQoKSAlPiUgY2xlYW5fdGV4dCgpDQogICAgICBtZW1iZXJzIDwtIHdlYnBhZ2UgJT4lIGh0bWxfbm9kZSgiLmdyb3VwLXN0YXRzIikgJT4lIGh0bWxfdGV4dCgpICU+JSBjbGVhbl90ZXh0KCkNCiAgICAgIHN0YXR1cyA8LSAiQWt0aWYiDQogICAgfSBlbHNlIGlmIChncmVwbCgiZmxpY2tyIiwgdXJsKSkgew0KICAgICAgbmFtZSA8LSB3ZWJwYWdlICU+JSBodG1sX25vZGUoIi5ncm91cC10aXRsZSIpICU+JSBodG1sX3RleHQoKSAlPiUgY2xlYW5fdGV4dCgpDQogICAgICBkZXNjcmlwdGlvbiA8LSB3ZWJwYWdlICU+JSBodG1sX25vZGUoIi5ncm91cC1kZXNjcmlwdGlvbiIpICU+JSBodG1sX3RleHQoKSAlPiUgY2xlYW5fdGV4dCgpDQogICAgICBtZW1iZXJzIDwtIHdlYnBhZ2UgJT4lIGh0bWxfbm9kZSgiLm1lbWJlci1jb3VudCIpICU+JSBodG1sX3RleHQoKSAlPiUgY2xlYW5fdGV4dCgpDQogICAgICBzdGF0dXMgPC0gIkFrdGlmIg0KICAgIH0gZWxzZSBpZiAoZ3JlcGwoImdvb2RyZWFkcyIsIHVybCkpIHsNCiAgICAgIG5hbWUgPC0gd2VicGFnZSAlPiUgaHRtbF9ub2RlKCIjZ3JvdXBOYW1lIikgJT4lIGh0bWxfdGV4dCgpICU+JSBjbGVhbl90ZXh0KCkNCiAgICAgIGRlc2NyaXB0aW9uIDwtIHdlYnBhZ2UgJT4lIGh0bWxfbm9kZSgiI2Rlc2NyaXB0aW9uIikgJT4lIGh0bWxfdGV4dCgpICU+JSBjbGVhbl90ZXh0KCkNCiAgICAgIG1lbWJlcnMgPC0gd2VicGFnZSAlPiUgaHRtbF9ub2RlKCIubWVtYmVycyIpICU+JSBodG1sX3RleHQoKSAlPiUgY2xlYW5fdGV4dCgpDQogICAgICBzdGF0dXMgPC0gIkFrdGlmIg0KICAgIH0gZWxzZSB7DQogICAgICBuYW1lIDwtIE5BDQogICAgICBkZXNjcmlwdGlvbiA8LSBOQQ0KICAgICAgbWVtYmVycyA8LSBOQQ0KICAgICAgc3RhdHVzIDwtIE5BDQogICAgfQ0KICAgIA0KICAgICMgTWVuYW1iYWhrYW4gZGF0YSBrZSBkYXRhIGZyYW1lDQogICAgY29tbXVuaXR5X2RhdGEgPC0gcmJpbmQoY29tbXVuaXR5X2RhdGEsIGRhdGEuZnJhbWUoDQogICAgICBOYW1lID0gbmFtZSwNCiAgICAgIERlc2NyaXB0aW9uID0gZGVzY3JpcHRpb24sDQogICAgICBNZW1iZXJzID0gbWVtYmVycywNCiAgICAgIFN0YXR1cyA9IHN0YXR1cywNCiAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KICAgICkpDQogIH0sIHNpbGVudCA9IFRSVUUpDQp9DQoNCiMgTWVuYW1waWxrYW4gZGF0YSBrb211bml0YXMNCnByaW50KGNvbW11bml0eV9kYXRhKQ0KYGBg