Table of Contents

Part. A

Part. B

Part. A



Step 0 of 6 Data aquisition and preparation

Data access - MODIS

For this guide, the appEEARS platform will be used to acquire free, ready-to-use data-samples. appEEARS is an easy to use web GUI for downloading MODIS data specifically for your study area without the need for any pre-processing. appEEARS is provided by USGS


Step 1 of 6 Login or Register

Go to https://lpdaacsvc.cr.usgs.gov/appeears/ and click “Sign In” in the upper right-hand corner, “LOG IN” with your Earthdata credentials or if you do not have an Earthdata account, click on “REGISTER” and follow the instructions on the page to create one


On the top menu, select “Extract”, then “Area Sample”.


Step 2 of 6 Entering download temporal and spatial coverage in appEEARS


Enter a request name, the start and end date for your data. Keep in mind that the Vegetation Condition Index (VCI) is more reliable for more years of data (higher temporal extent). Because the final output is based on seasonal variability, please make sure that your start date is first of January and your end date marks 31st of December. If your study-area is located south of the equator, make sure the start date is first of July and the end date is 30th of June. Also, please note that the first full month of MODIS data is March 2000. If you want to select your study area manually, you can do so using the map and its tools to the right (right map box). If you want to use specific country-borders, please see step 3) as follows.


Step 3 of 6 Downloading and preparing country or region boundary shapefile

Important: If your country border consists of multiple polygons, please use the appEEARS map tools to draw a single polygon around your study area instead.
Another option is Via http://www.gadm.org/country, you can download shapefiles for every country of the world for use within appEEARS. Visit the website by opening a new tab or window and select a country from the upper drop-down menu. From the lower drop-down menu, select “Shapefile” and click on “OK”.

On the next page, you will see a preview of the shapefile. Click on “download” (below the preview) and save the zip-file. Now, open the zip-file and delete all files except the ones ending in “adm0”. All others refer to different administrative levels. In case you are interested in a certain province or district boundary, you can extract this with some GIS-operation.


Step 4 of 6 Appliying the country or region boundary

Finally, drag-and-drop the prepared zip-file into the designated area on the appEEARS website

Your area will now appear in the map. If you are notified that “The shape you selected was too complex to display and was automatically reduced [.]” - just proceed with the following steps. It will have no negative effect on data aquisition.


Step 5 of 6 Selecting MODIS bands of interest

The data required is the 16-day Enhanced Vegetation Index (EVI) composites. In the “Search for a product” box, first, enter “MOD13Q1” and select the “MOD13Q1.006” 250m vegetation indices, then select 250m 16-days EVI and 250 16-days pixel-reliability (optional, select if quality masking is wanted)

Lastly, select “GeoTiff” Output option, click the box below (“Search for a projection”) and select “Geographic” projection. If you have done everything correctly, it should look like this below:

You can now click “submit” your request using the button on the bottom of the page. Depending on the size of your study area and the selected time-period, the data preparation may take some hours. You can check the progress using the “Explore” tab on the top of the page. You will also get an email notification as soon as your request is finished


Step 6 of 6 Conclusion of request and download of data & data.txt file

Once your request is finished, click on the “Explore” tab, then on the download-button of your request.

Scroll down, select “All” and save the “Save Download list”. Remember the location of your download-list. Alternatively if you wish to download and save all data for analysis at a later time select “ALL” and then download to a suitable folder of your choice.


Part. B



Start of season (SOS) variables
BlockA <- stack()
  #Iterating through all 23 images of the season
  for (i in 1:23){
    #Read start-of-season dates
    s <- SoS
    #Read dates up to 16 days before peak of season
    e <- (Peak - 1)
    
    #Check if current iteration lies within the seasonal dates of each pixel
    s[s > i] <- NA
    e[e < i] <- NA
    
    #Creating a binary mask and apply to the VCI image
    m <- s*e
    v <- yVCI[[i]]*(m/m)

    #Add layer to stack
    BlockA <- stack(BlockA, v)
    
  }

Create mean of this time-block Block-A Start Of Season

BlockA <- calc(BlockA, fun=mean, na.rm=T)
Peak of season variables

See comments above

BlockB <- stack()
  for (i in 1:23){
    s <- Peak
    e <- Peak
    
    s[s > i] <- NA
    e[e < i] <- NA
    
    m <- s*e
    v <- yVCI[[i]]*(m/m)
            
    BlockB <- stack(BlockB, v)
  }

Create mean of this time-block Block-B Peak of season

BlockB <- calc(BlockB, fun=mean, na.rm=T)
End of season (EOS) variables

See comments above

BlockC <- stack()
  for (i in 1:23){
    s <- (Peak + 1)
    e <- EoS
    
    s[s > i] <- NA
    e[e < i] <- NA

    m <- s*e
    v <- yVCI[[i]]*(m/m)
       
    BlockC <- stack(BlockC, v)
  }

Create mean of this time-block Block-c EOS

 BlockC <- calc(BlockC, fun=mean, na.rm=T)



Weighting: 5-7-1 start-peak-end of season mean

Result: weighted VCI by season

WeightedStack<-stack(BlockA,BlockA,BlockA,BlockA,BlockA,
                     BlockB,BlockB,BlockB,BlockB,BlockB,BlockB,BlockB,
                     BlockC)

Create the mean of the season weighthed block stacks

WeightedVCI <- calc(WeightedStack, fun=mean,na.rm=T)

Raster mean classification

Output: five classes

cWeightedVCI <- reclassify(WeightedVCI, c(-1, 10, 4,  10, 20, 3,  20, 30, 2, 30,40, 1,40,101,0))  
writeRaster(cWeightedVCI,filename=paste0(dataPath,"/weighted/",dscr,"_droughtFiveCl.tif"),format="GTiff",overwrite=T)

Output: three classes required for the next steps of the analysis as recomended by the Technical guidance for monitoring and reporting on progress in achieving the global targets of the Sendai Framework for Disaster Risk Reduction

#(Progress report)
  dWeightedVCI <- reclassify(WeightedVCI, c(-1, 10, 2,  10, 40, 1,  40, 101, 0))  
  writeRaster(dWeightedVCI,filename=paste0(dataPath,"/weighted/",dscr,"_droughtThreeCl.tif"),format="GTiff",overwrite=T)
  
#(Progress report)
print(paste0('Weighting indices (Step 6 of 6): ',round((sy-as.numeric(min(YEARs))) (as.numeric(max(YEARs))-as.numeric(min(YEARs)))  * 100, digits=2),'%'))
}
}


Deleting all temp files

tmp <- list.files(path=paste0(dataPath,'/temp/'), recursive=F, ignore.case=T, full.names=T)
file.remove(tmp)
Finished
#Finished
print(paste0(Sys.time(),' - Finished. You will find the data in the subfolders \'VCI\' and \'weighted\' (classified drought indicators) at ', dataPath,"."))

Once you entered all necessary information, select the whole code (CTRL + a) and click on “run” (or: CTRL + Enter). Depending on your study-area, calculations will take several hours. The script will keep you updated with the current steps being performed in the console. You will also see a message in the console once it is completely finished. Sometimes execution might seem unresponsive. As long as you can see the little stop sign above the console, you can be sure the script is still running (see image below)


LS0tDQp0aXRsZTogJyAnDQoNCg0Kc3VidGl0bGU6IENvbnRyaWJ1dGlvbiB0byB0aGUgU2VuZGFpIEZyYW1ld29yayBmb3IgRGlzYXN0ZXIgUmlzayBSZWR1Y3Rpb24gKFNGRFJSKQ0KICBNb25pdG9yaW5nIGJhc2VkIG9uIHRoZSBUZWNobmljYWwgZ3VpZGFuY2UgZm9yIG1vbml0b3JpbmcgYW5kIHJlcG9ydGluZyBvbiBwcm9ncmVzcw0KICBpbiBhY2hpZXZpbmcgdGhlIGdsb2JhbCB0YXJnZXRzIG9mIHRoZSBTZW5kYWkgRnJhbWV3b3JrIGZvciBEaXNhc3RlciBSaXNrIFJlZHVjdGlvbi4NCg0KYXV0aG9yOg0KIA0KDQpvdXRwdXQ6DQogID8gfC0NCiAgOiBkZWZhdWx0DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgICBodG1sX25vdGVib29rDQogICAgLS0tLS0NCg0KLS0tDQoNCiMjIyMgKipUYWJsZSBvZiBDb250ZW50cyoqDQojIyMjIFtQYXJ0LiBBXSgjUGFydEEpDQojIyMjIyMgW1N0ZXAgMCBvZiA2LiBEYXRhIGFxdWlzaXRpb24gYW5kIHByZXBhcmF0aW9uXSgjMCkNCiMjIyMjIyBbU3RlcCAxIG9mIDYuIExvZ2luIG9yIFJlZ2lzdGVyXSgjMSkNCiMjIyMjIyBbU3RlcCAyIG9mIDYuIEVudGVyaW5nIGRvd25sb2FkIHRlbXBvcmFsIGFuZCBzcGF0aWFsIGNvdmVyYWdlIGluIGFwcEVFQVJTXSgjMikNCiMjIyMjIyBbU3RlcCAzIG9mIDYuIERvd25sb2FkaW5nIGFuZCBwcmVwYXJpbmcgY291bnRyeSBvciByZWdpb24gYm91bmRhcnkgc2hhcGVmaWxlXSgjMykNCiMjIyMjIyBbU3RlcCA0IG9mIDYuIEFwcGxpeWluZyB0aGUgY291bnRyeSBvciByZWdpb24gYm91bmRhcnldKCM0KQ0KIyMjIyMjIFtTdGVwIDUgb2YgNi4gU2VsZWN0aW5nIE1PRElTIGJhbmRzIG9mIGludGVyZXN0XSgjNSkNCiMjIyMjIyBbU3RlcCA2IG9mIDYuIENvbmNsdXNpb24gb2YgcmVxdWVzdCBhbmQgZG93bmxvYWQgb2YgZGF0YSAmIGRhdGEudHh0IGZpbGVdKCM2KQ0KDQojIyMjIFtQYXJ0LiBCXSgjUGFydEIpDQoNCiMjIyMjIyBbU3RlcCAwIG9mIDYuICBSLCBSLVN0dWRpbyBhbmQgUi1jb2RlIHByZXBhcmF0aW9uc10oIzAwKQ0KIyMjIyMjIFtpLiBSIGFuZCBSLXN0dWRpbyBkb3dubG9hZCBhbmQgaW5zdGFsbGF0aW9uXSgjaSkNCiMjIyMjIyBbaWkuIEZpbmFsIHByZXBhcmF0aW9ucyAtIFIgQ29kZV0oI2lpKQ0KIyMjIyMjIFtTdGVwIDEgb2YgNi4gRG93bmxvYWRpbmcgRmlsZXMgaWYgcmVxdWlyZWRdKCMxMSkNCiMjIyMjIyBbU3RlcCAyIG9mIDYuIFN0YXJ0aW5nIEVWSS9WQ0kgYmxvY2sgRGF0YSBwcmVwYXJhdGlvbiAgJiAgRVZJIG1hc2tpbmddKCMyMikNCiMjIyMjIyBbU3RlcCAzIG9mIDYuIEFwcGx5aW5nIFZDSSBjYWxjdWxhdGlvbiB0byBlYWNoIGNodW5rIHRoYXQgd2FzIHByZXZpb3VzbHkgY3JlYXRlZCBpbiBzdGVwIDJdKCMzMykNCiMjIyMjIyBbU3RlcCA0IG9mIDYuIFZDSSBjaHVuayBtZXJnaW5nIGFuZCBvdXRwdXRdKCM0NCkNCiMjIyMjIyBbU3RlcCA1IG9mIDYuIFRoZSBzZWFzb25hbGl0eS9waGVub2xvZ3kgIGJsb2NrXSgjNTUpDQojIyMjIyMgW1N0ZXAgNiBvZiA2LiAgV2VpZ2h0ZWQgbGluZWFyIGNvbWJpbmF0aW9uIG9mIFZDSSBvdXRwdXQgIGFuZCBFVkkgUGhlbm9sb2d5IG91dHB1dF0oIzY2KQ0KKioqKioqDQojIyMjIFtQYXJ0LiBBXSgjKXtuYW1lPVBhcnRBfQ0KKioqKioqDQoNCioqKioqDQo+ICMjIyMjIFtTdGVwIDAgb2YgNiBEYXRhIGFxdWlzaXRpb24gYW5kIHByZXBhcmF0aW9uXSgjKXtuYW1lPTB9IA0KDQoqKioqKg0KDQoNCiMjIyMgRGF0YSBhY2Nlc3MgLSBNT0RJUw0KDQpGb3IgdGhpcyBndWlkZSwgdGhlIGFwcEVFQVJTIHBsYXRmb3JtIHdpbGwgYmUgdXNlZCB0byBhY3F1aXJlIGZyZWUsIHJlYWR5LXRvLXVzZSBkYXRhLXNhbXBsZXMuIGFwcEVFQVJTIGlzIGFuIGVhc3kgdG8gdXNlIHdlYiBHVUkgZm9yIGRvd25sb2FkaW5nIE1PRElTIGRhdGEgc3BlY2lmaWNhbGx5IGZvciB5b3VyIHN0dWR5IGFyZWEgd2l0aG91dCB0aGUgbmVlZCBmb3IgYW55IHByZS1wcm9jZXNzaW5nLiBhcHBFRUFSUyBpcyBwcm92aWRlZCBieSBVU0dTDQoNCioqKioqDQo+ICMjIyMjIFtTdGVwIDEgb2YgNiBMb2dpbiBvciBSZWdpc3Rlcl0oIyl7bmFtZT0xfQ0KDQoqKioqKg0KDQpHbyB0byBodHRwczovL2xwZGFhY3N2Yy5jci51c2dzLmdvdi9hcHBlZWFycy8gYW5kIGNsaWNrICoqKiJTaWduIEluIioqKiBpbiB0aGUgdXBwZXIgcmlnaHQtaGFuZCBjb3JuZXIsICoqKiJMT0cgSU4iKioqIHdpdGggeW91ciBFYXJ0aGRhdGEgY3JlZGVudGlhbHMgb3IgaWYgeW91IGRvIG5vdCBoYXZlIGFuIEVhcnRoZGF0YSBhY2NvdW50LCBjbGljayBvbiAqKioiUkVHSVNURVIiKioqIGFuZCBmb2xsb3cgdGhlIGluc3RydWN0aW9ucyBvbiB0aGUgcGFnZSB0byBjcmVhdGUgb25lDQoNCiFbXShpbWFnZTAxLnBuZykNCg0KDQoNCjxicj4NCk9uIHRoZSB0b3AgbWVudSwgc2VsZWN0ICoqKiJFeHRyYWN0IioqKiwgdGhlbiAqKioiQXJlYSBTYW1wbGUiKioqLg0KPGJyPg0KIVtdKGltYWdlMDIucG5nKSANCjxicj4NCg0KDQoqKioqKg0KPiAjIyMjIyBbU3RlcCAyIG9mIDYgRW50ZXJpbmcgZG93bmxvYWQgdGVtcG9yYWwgYW5kIHNwYXRpYWwgY292ZXJhZ2UgaW4gYXBwRUVBUlNdKCMpe25hbWU9Mn0NCg0KKioqKioNCg0KIVtdKGltYWdlMDMucG5nKQ0KDQoNCiFbXShpbWFnZTA0LnBuZykNCg0KPGJyPg0KRW50ZXIgYSByZXF1ZXN0IG5hbWUsIHRoZSBzdGFydCBhbmQgZW5kIGRhdGUgZm9yIHlvdXIgZGF0YS4gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIFZlZ2V0YXRpb24gQ29uZGl0aW9uIEluZGV4IChWQ0kpIGlzIG1vcmUgcmVsaWFibGUgZm9yIG1vcmUgeWVhcnMgb2YgZGF0YSAoaGlnaGVyIHRlbXBvcmFsIGV4dGVudCkuIEJlY2F1c2UgdGhlIGZpbmFsIG91dHB1dCBpcyBiYXNlZCBvbiBzZWFzb25hbCB2YXJpYWJpbGl0eSwgcGxlYXNlIG1ha2Ugc3VyZSB0aGF0IHlvdXIgc3RhcnQgZGF0ZSBpcyBmaXJzdCBvZiBKYW51YXJ5IGFuZCB5b3VyIGVuZCBkYXRlIG1hcmtzIDMxc3Qgb2YgRGVjZW1iZXIuIElmIHlvdXIgc3R1ZHktYXJlYSBpcyBsb2NhdGVkIHNvdXRoIG9mIHRoZSBlcXVhdG9yLCBtYWtlIHN1cmUgdGhlIHN0YXJ0IGRhdGUgaXMgZmlyc3Qgb2YgSnVseSBhbmQgdGhlIGVuZCBkYXRlIGlzIDMwdGggb2YgSnVuZS4gQWxzbywgcGxlYXNlIG5vdGUgdGhhdCB0aGUgZmlyc3QgZnVsbCBtb250aCBvZiBNT0RJUyBkYXRhIGlzIE1hcmNoIDIwMDAuIElmIHlvdSB3YW50IHRvIHNlbGVjdCB5b3VyIHN0dWR5IGFyZWEgbWFudWFsbHksIHlvdSBjYW4gZG8gc28gdXNpbmcgdGhlIG1hcCBhbmQgaXRzIHRvb2xzIHRvIHRoZSByaWdodCAocmlnaHQgbWFwIGJveCkuIElmIHlvdSB3YW50IHRvIHVzZSBzcGVjaWZpYyBjb3VudHJ5LWJvcmRlcnMsIHBsZWFzZSBzZWUgc3RlcCAzKSBhcyBmb2xsb3dzLg0KDQoqKioqKioNCj4gIyMjIyMgW1N0ZXAgMyBvZiA2IERvd25sb2FkaW5nIGFuZCBwcmVwYXJpbmcgY291bnRyeSBvciByZWdpb24gYm91bmRhcnkgc2hhcGVmaWxlXSgjKXtuYW1lPTN9DQoNCioqKioqKg0KDQpJbXBvcnRhbnQ6IElmIHlvdXIgY291bnRyeSBib3JkZXIgY29uc2lzdHMgb2YgbXVsdGlwbGUgcG9seWdvbnMsIHBsZWFzZSB1c2UgdGhlIGFwcEVFQVJTIG1hcCB0b29scyB0byBkcmF3IGEgc2luZ2xlIHBvbHlnb24gYXJvdW5kIHlvdXIgc3R1ZHkgYXJlYSBpbnN0ZWFkLiAgDQpBbm90aGVyIG9wdGlvbiBpcyBWaWEgaHR0cDovL3d3dy5nYWRtLm9yZy9jb3VudHJ5LCB5b3UgY2FuIGRvd25sb2FkIHNoYXBlZmlsZXMgZm9yIGV2ZXJ5IGNvdW50cnkgb2YgdGhlIHdvcmxkIGZvciB1c2Ugd2l0aGluIGFwcEVFQVJTLiBWaXNpdCB0aGUgd2Vic2l0ZSBieSBvcGVuaW5nIGEgbmV3IHRhYiBvciB3aW5kb3cgYW5kIHNlbGVjdCBhIGNvdW50cnkgZnJvbSB0aGUgdXBwZXIgZHJvcC1kb3duIG1lbnUuIEZyb20gdGhlIGxvd2VyIGRyb3AtZG93biBtZW51LCBzZWxlY3QgIlNoYXBlZmlsZSIgYW5kIGNsaWNrIG9uICJPSyIuDQoNCiFbIF0oaW1hZ2UwNS5wbmcpDQoNCg0KT24gdGhlIG5leHQgcGFnZSwgeW91IHdpbGwgc2VlIGEgcHJldmlldyBvZiB0aGUgc2hhcGVmaWxlLiBDbGljayBvbiAiZG93bmxvYWQiIChiZWxvdyB0aGUgcHJldmlldykgYW5kIHNhdmUgdGhlIHppcC1maWxlLiBOb3csIG9wZW4gdGhlIHppcC1maWxlIGFuZCBkZWxldGUgYWxsIGZpbGVzIGV4Y2VwdCB0aGUgb25lcyBlbmRpbmcgaW4gImFkbTAiLiBBbGwgb3RoZXJzIHJlZmVyIHRvIGRpZmZlcmVudCBhZG1pbmlzdHJhdGl2ZSBsZXZlbHMuIEluIGNhc2UgeW91IGFyZSBpbnRlcmVzdGVkIGluIGEgY2VydGFpbiBwcm92aW5jZSBvciBkaXN0cmljdCBib3VuZGFyeSwgeW91IGNhbiBleHRyYWN0IHRoaXMgd2l0aCBzb21lIEdJUy1vcGVyYXRpb24uDQoNCiFbXShpbWFnZTA2LnBuZykNCg0KKioqKg0KPiAjIyMjIyBbU3RlcCA0IG9mIDYgQXBwbGl5aW5nIHRoZSBjb3VudHJ5IG9yIHJlZ2lvbiBib3VuZGFyeV0oIyl7bmFtZT00fQ0KDQoqKioqDQoNCkZpbmFsbHksIGRyYWctYW5kLWRyb3AgdGhlIHByZXBhcmVkIHppcC1maWxlIGludG8gdGhlIGRlc2lnbmF0ZWQgYXJlYSBvbiB0aGUgYXBwRUVBUlMgd2Vic2l0ZQ0KDQohW10oaW1hZ2UwN2EucG5nKQ0KDQoNCllvdXIgYXJlYSB3aWxsIG5vdyBhcHBlYXIgaW4gdGhlIG1hcC4gSWYgeW91IGFyZSBub3RpZmllZCB0aGF0ICoqKiJUaGUgc2hhcGUgeW91IHNlbGVjdGVkIHdhcyB0b28gY29tcGxleCB0byBkaXNwbGF5IGFuZCB3YXMgYXV0b21hdGljYWxseSByZWR1Y2VkIFsuXSIqKiogLSBqdXN0IHByb2NlZWQgd2l0aCB0aGUgZm9sbG93aW5nIHN0ZXBzLiBJdCB3aWxsIGhhdmUgbm8gbmVnYXRpdmUgZWZmZWN0IG9uIGRhdGEgYXF1aXNpdGlvbi4NCg0KKioqKioqDQo+ICMjIyMjIFtTdGVwIDUgb2YgNiBTZWxlY3RpbmcgTU9ESVMgYmFuZHMgb2YgaW50ZXJlc3RdKCMpe25hbWU9NX0NCg0KKioqKioqDQoNClRoZSBkYXRhIHJlcXVpcmVkIGlzIHRoZSAxNi1kYXkgRW5oYW5jZWQgVmVnZXRhdGlvbiBJbmRleCAoRVZJKSBjb21wb3NpdGVzLiBJbiB0aGUgKioqIlNlYXJjaCBmb3IgYSBwcm9kdWN0IioqKiBib3gsIGZpcnN0LCBlbnRlciAqKioiTU9EMTNRMSIqKiogYW5kIHNlbGVjdCB0aGUgKioqIk1PRDEzUTEuMDA2IioqKiAyNTBtIHZlZ2V0YXRpb24gaW5kaWNlcywgdGhlbiBzZWxlY3QgKioqMjUwbSAxNi1kYXlzIEVWSSoqKiBhbmQgKioqMjUwIDE2LWRheXMgcGl4ZWwtcmVsaWFiaWxpdHkqKiogKG9wdGlvbmFsLCBzZWxlY3QgaWYgcXVhbGl0eSBtYXNraW5nIGlzIHdhbnRlZCkNCiFbXShpbWFnZTA4LnBuZykNCg0KTGFzdGx5LCBzZWxlY3QgKioqIkdlb1RpZmYiKioqICBPdXRwdXQgb3B0aW9uLCBjbGljayB0aGUgYm94IGJlbG93ICgiU2VhcmNoIGZvciBhIHByb2plY3Rpb24iKSBhbmQgc2VsZWN0ICoqKiJHZW9ncmFwaGljIioqKiBwcm9qZWN0aW9uLiBJZiB5b3UgaGF2ZSBkb25lIGV2ZXJ5dGhpbmcgY29ycmVjdGx5LCBpdCBzaG91bGQgbG9vayBsaWtlIHRoaXMgYmVsb3c6DQohW10oaW1hZ2UxMC5wbmcpDQoNCllvdSBjYW4gbm93IGNsaWNrICoqKiJzdWJtaXQiKioqIHlvdXIgcmVxdWVzdCB1c2luZyB0aGUgYnV0dG9uIG9uIHRoZSBib3R0b20gb2YgdGhlIHBhZ2UuIERlcGVuZGluZyBvbiB0aGUgc2l6ZSBvZiB5b3VyIHN0dWR5IGFyZWEgYW5kIHRoZSBzZWxlY3RlZCB0aW1lLXBlcmlvZCwgdGhlIGRhdGEgcHJlcGFyYXRpb24gbWF5IHRha2Ugc29tZSBob3Vycy4gWW91IGNhbiBjaGVjayB0aGUgcHJvZ3Jlc3MgdXNpbmcgdGhlICoqKiJFeHBsb3JlIioqKiB0YWIgb24gdGhlIHRvcCBvZiB0aGUgcGFnZS4gWW91IHdpbGwgYWxzbyBnZXQgYW4gZW1haWwgbm90aWZpY2F0aW9uIGFzIHNvb24gYXMgeW91ciByZXF1ZXN0IGlzIGZpbmlzaGVkDQoNCioqKioNCj4gIyMjIyMgW1N0ZXAgNiBvZiA2IENvbmNsdXNpb24gb2YgcmVxdWVzdCBhbmQgZG93bmxvYWQgb2YgZGF0YSAmIGRhdGEudHh0IGZpbGVdKCMpe25hbWU9Nn0NCg0KKioqKg0KDQpPbmNlIHlvdXIgcmVxdWVzdCBpcyBmaW5pc2hlZCwgY2xpY2sgb24gdGhlICoqKiJFeHBsb3JlIioqKiB0YWIsIHRoZW4gb24gdGhlIGRvd25sb2FkLWJ1dHRvbiBvZiB5b3VyIHJlcXVlc3QuDQoNCiFbXShpbWFnZTExYS5wbmcpDQoNClNjcm9sbCBkb3duLCBzZWxlY3QgKioqIkFsbCIqKiogYW5kIHNhdmUgdGhlICoqKiJTYXZlIERvd25sb2FkIGxpc3QiKioqLiBSZW1lbWJlciB0aGUgbG9jYXRpb24gb2YgeW91ciBkb3dubG9hZC1saXN0LiBBbHRlcm5hdGl2ZWx5IGlmIHlvdSB3aXNoIHRvIGRvd25sb2FkIGFuZCBzYXZlIGFsbCBkYXRhIGZvciBhbmFseXNpcyBhdCBhIGxhdGVyIHRpbWUgc2VsZWN0ICoqKiJBTEwiKioqIGFuZCB0aGVuIGRvd25sb2FkIHRvIGEgc3VpdGFibGUgZm9sZGVyIG9mIHlvdXIgY2hvaWNlLiANCg0KIVtdKGltYWdlMTFiLnBuZykNCg0KDQoqKioqKioqDQojIyMjIFtQYXJ0LiBCXSgjKXtuYW1lPVBhcnRCfQ0KKioqKioqDQoqKioqKioNCiMjIyMjIEFncmljdWx0dXJhbCBkcm91Z2h0IGltcGFjdCBjbGFzc2lmaWNhdGlvbiB1c2luZyB3ZWlnaHRlZCBsaW5lYXIgY29tYmluYXRpb24gb2YgRVZJIHBoZW5vbG9neSBhbmQgVkNJIChTZWUgImluIGRldGFpbCIgcGFnZSBvZiB0aGUgUmVjb21tZW5kZWQgUHJhY3RpY2UgZm9yIG1vcmUgaW5mb3JtYXRpb24pDQoqKioqKioqDQoNCioqKioqKg0KPiAjIyMjIyBbU3RlcCAwIG9mIDYgIFIsIFItU3R1ZGlvIGFuZCBSLWNvZGUgcHJlcGFyYXRpb25zXSgjKXtuYW1lPTAwfQ0KDQoqKioqDQoNCiMjIyMjIyBbaS4gUiBhbmQgUi1zdHVkaW8gZG93bmxvYWQgYW5kIGluc3RhbGxhdGlvbl0oIyl7bmFtZT1pfQ0KDQpUaGlzIHByYWN0aWNlIHVzZXMgUiBTY3JpcHQuIE1ha2Ugc3VyZSB0byBpbnN0YWxsIFIgaWYgaXQgaXMgbm90IGluc3RhbGxlZCBvbiB5b3VyIG1hY2hpbmUgeWV0ICh2aXNpdCBodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy8pLiBUaGUgUi1TdHVkaW8gaW50ZXJmYWNlIGlzIGFsc28gdXNlZC4gV2UgcmVjb21tZW5kIGluc3RhbGxpbmcgaXQgYXMgd2VsbCAodmlzaXQgaHR0cHM6Ly93d3cucnN0dWRpby5jb20vKS4NCkJlZm9yZSBydW5uaW5nIHRoZSBSLUNvZGUsIHlvdSB3aWxsIG5lZWQgdG8gZG93bmxvYWQgdGhlIGdyZWVuYnJvd24gUi1wYWNrYWdlIHdoaWNoIGlzIHVzZWQgdG8gY2FsY3VsYXRlIHBoZW5vbG9neSAobW9yZSBpbmZvOiBodHRwOi8vZ3JlZW5icm93bi5yLWZvcmdlLnItcHJvamVjdC5vcmcvKS4gVmlzaXQgaHR0cDovL2dyZWVuYnJvd24uci1mb3JnZS5yLXByb2plY3Qub3JnL3Rhci8sIGRvd25sb2FkICJncmVlbmJyb3duXzIuNC4zLnRhci5neiIgKGRvIG5vdCBleHRyYWN0IHRoZSBwYWNrYWdlKSBhbmQgcmVtZW1iZXIgdGhlIGxvY2F0aW9uIHlvdSBzYXZlZCBpdCB0by4NCg0KDQojIyMjIyMgW2lpLiBGaW5hbCBwcmVwYXJhdGlvbnMgLSBSIENvZGVdKCMpe25hbWU9aWl9DQoNCkRvd25sb2FkIHRoZSBSLUNvZGUgZm9yIHRoaXMgcHJhY3RpY2UgW2hlcmVdKGh0dHA6Ly93d3cudW4tc3BpZGVyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL0FncmljdWx0dXJhbERyb3VnaHRJbXBhY3QudHh0KSBhbmQgb3BlbiBpdCBpbiBSLVN0dWRpby4gQmVmb3JlIHJ1bm5pbmcsIHlvdSB3aWxsIG5lZWQgdG8gYWRkIGluZm9ybWF0aW9uIHRvIHRoZSBmb2xsb3dpbmcgbGluZSBiZWxvdyBhcyBzZWVuIGluIHRoZSBpbWFnZSBhbmQgc2NyaXB0Lg0KDQohW10oaW1hZ2UxMy5wbmcpDQoNCjxicj4NCg0KRm9sZGVycyBmb3IgaW5wdXQgYW5kIG91dHB1dCBvZiB0aGUgYW5hbHlzaXMgb2YgdGhlIGFncmljdWx0dXJhbCBkcm91Z2h0IGltcGFjdCAgDQoNCjxicj4NCiFbXShmaWxlcy5wbmcpDQoNCiAgICAgICAgICAgICAgICANCg0KPGJyPg0KSW4gbGluZSA2IGZyb20gaW1hZ2UgYWJvdmUsIGVudGVyIGEgcGF0aCB3aGVyZSB5b3UgaGF2ZSBlbm91Z2ggZnJlZSBzcGFjZSBmb3IgYWxsIHByb2R1Y3RzIGFuZCB0ZW1wb3JhcnkgZmlsZXMuIERlcGVuZGluZyBvbiB0aGUgc3R1ZHktYXJlYSwgYSBsb3Qgb2YgZ2lnYWJ5dGVzIG1heSBiZSBuZWVkZWQuDQoNCj4gIyMjIyMgKipOb3RlKio6IFRvIHdyaXRlIGxpbmVzIGluIHIgYXMgY29tbWVudHMgdXNlICoqKiIjIioqKiBiZWZvcmUgc3RhcnRpbmcgdGhlIHNlbnRlbmNlLCB0aGVyZWZvcmUgaWYgeW91IGZpbmQgYW55IGNvbW1lbnQgYWZ0ZXIgKioqIiMiKioqIGl0IGlzIG5vdCBtZW50IGlzIG5vdCBtZW50dG8gYmUgZXZhbHVhdGVkIGFuZCBpdCB3aWxsIG5vdCBiZSBldmFsdWF0ZWQgYnkgUiANCg0KSW4gY2FzZSB5b3UgYWxyZWFkeSBkb3dubG9hZGVkIHRoZSBkYXRhIGZyb20gYXBwZWFycyBtYW51YWxseSBiZWZvcmVoYW5kLCBlbnRlciB0aGUgcGF0aCB0byB5b3VyIGRhdGEsIHRoZW4gZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgaW4gKioqIlN0ZXAgMSBvZiA2LiBEb3dubG9hZGluZyBGaWxlcyIqKiogYnkgY29tbWVudGluZyBvdXQgdGhlIGxpbmVzIGxpa2Ugc2VlbiBiZWxvdyB1c2luZyAqKiojKioqIGFzIHNlZW4gYmVsb3cNCg0KPGJyPg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KI2ZpbGVzbCA8LSBzY2FuKGRvd25sb2FkTGlzdCwgd2hhdD0nbGlzdCcsICNzZXA9J1xuJykNCiNmb3IgKGQgaW4gMTpsZW5ndGgoZmlsZXNsKSl7DQojICBpZiAoZ3JlcGwoIl9WSV9RdWFsaXR5XyIsZmlsZXNsW2RdKSA9PSBGKXsNCiMgICAgY3VybF9kb3dubG9hZCh1cmw9ZmlsZXNsW2RdLCAjZGVzdGZpbGU9cGFzdGUwKGRhdGFQYXRoLCIvIixiYXNlbmFtZShmaWxlc2xbZF0pIykscXVpZXQgPSBULCBoYW5kbGUgPSBuZXdfaGFuZGxlKCkpDQojICB9DQojICBwcmludChwYXN0ZTAoJ0Rvd25sb2FkaW5nIHNvdXJjZSBkYXRhIChTdGVwIDEgI29mIDYpOiAnLHJvdW5kKGQgLyBsZW5ndGgoZmlsZXNsKSAqIDEwMCwgI2RpZ2l0cz0yKSwnJScpKQ0KI30NCmBgYA0KDQpJbiBsaW5lIDEwLCBlbnRlciB0aGUgZXhhY3QgcGF0aCAoaW5jbHVkaW5nIGZpbGUtZW5kaW5nKSB0byB5b3VyIGRvd25sb2FkLWxpc3QgdGhhdCB5b3UgcmVjZWl2ZWQgZnJvbSBhcHBFRUFSUy4NCkluIGxpbmUgMTMsIGVudGVyIHRoZSBleGFjdCBwYXRoIChpbmNsdWRpbmcgZmlsZS1lbmRpbmcpIHRvIHRoZSBncmVlbmJyb3duLXBhY2thZ2UgeW91IGRvd25sb2FkZWQuDQoNCkVudGVyIHRoZSBwYXRoIHRvIHRoZSBhIGZvbGRlciB3aGVyZSB5b3UgaGF2ZSBlbm91Z2ggZnJlZSBzcGFjZSB0byBzdG9yZSB5b3VyIE1PRElTIGRhdGEgYW5kIHRoZSByZXN1bHRpbmcgcHJvZHVjdHMNCioqUGxlYXNlIGRvIG5vdCB1c2UgYmFja3NsYXNoZXMoJiM5MjspIGV4Y2VwdCB5b3UgYXJlIHdvcmtpbmcgd2l0aCBhIE1BQyBvciBMaW51eCoqDQoNCg0KW2NvbW1lbnRdOiAjICh0aGlzIGlzIGEgY29tbWVudCkNCg0KYGBge3IgZXZhbD1GQUxTRSB9DQpkYXRhUGF0aCA8LSAiRDovVWtyYWluZV93b3Jrc2hvcC9LaWV2X291dCINCmBgYA0KDQpFbnRlciB0aGUgcGF0aCB0byB5b3VyIGFwcEVFQVJTIGRvd25sb2FkLWxpc3QgKGluY2x1ZGluZyAiLnR4dCIhKS4gSWYgeW91IGRvd25sb2FkZWQgdGhlIGRhdGEgZnJvbSBhcHBFRUFSUyBiZWZvcmVoYW5kLCBlbnRlciB0aGUgcGF0aCB0byB0aGUgZGF0YSBoZXJlIChhbGwgZGF0YSBuZWVkcyB0byBiZSBpbiBvbmUgZm9sZGVyKQ0KDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpkb3dubG9hZExpc3QgPC0gIkM6L1VzZXJzL21kdWd1cnUvRGVza3RvcC9Va3JhaW5lX3dvcmtzaG9wL2RhdGFfdGV4dC9raWV2LWRvd25sb2FkLWxpc3QudHh0Ig0KYGBgDQpFbnRlciB0aGUgbG9jYXRpb24gb2YgdGhlIGdyZWVuYnJvd24tcGFja2FnZSB5b3UgZG93bmxvYWRlZCBhY2NvcmRpbmcgdG8gdGhlIHN0ZXAtYnktc3RlcCBndWlkZSAoaW5jbHVkaW5nICIudGFyLmd6IiEpDQoNCmBgYHtyIGV2YWw9RkFMU0UgfQ0KZGlyX0dCIDwtICJEOi9Va3JhaW5lX3dvcmtzaG9wL2dyZWVuYnJvd24vZ3JlZW5icm93bl8yLjQuMy50YXIuZ3oiDQpgYGANCioqKkhlbWlzcGhlcmUgb2YgeW91ciBzdHVkeS1hcmVhOiAxID0gbm9ydGggaGVtaXNwaGVyZSA7IDAgPSBzb3V0aCBoZW1pc3BoZXJlLiBXZSBhcmUgY29uc2lkZXJpbmcgdGhlIFNvdXRoZXJuIEhlbWlzcGhlcmUgZm9yIHRoaXMgd29ya2Zsb3cgKioqDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpoZW1pc3BoZXJlIDwtIDANCmBgYA0KDQpRdWFsaXR5IG1hc2tpbmc6IHJlcGxhY2UgdGhlICcwJyB3aXRoIGEgJzEnIHRvIGFwcGx5IE1PRElTIFBpeGVsIFJlbGlhYmlsaXR5IGRhdGEuIElmIHlvdSBhcmUgbm90IHN1cmUgd2hldGhlciB5b3Ugc2hvdWxkIGVuYWJsZSB0aGlzIG9wdGlvbiwgaXQgaXMgcmVjb21tZW5kZWQgdGhhdCB5b3UgZmluZCBvdXQgbW9yZSBhYm91dCBQaXhlbCBSZWxpYWJpbGl0eS4gQ2hlY2sgdGhlICoqKiJpbiBEZXRhaWwiKioqIHBhZ2UgZm9yIG1vcmUgaW5mb3JtYXRpb24uDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpjbG91ZG1hc2sgPC0gMQ0KYGBgDQoNCioqKioqDQoNCioqKkluc3RhbGxpbmcgYWxsIG5lZWRlZCBwYWNrYWdlcyBmb3IgdGhlIGRldGVybWluaXRpb24gb2YgdGhlIEhhemFyZCBjbGFzc2VzKioqDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQojIyMjSW5zdGFsbGluZyBhbGwgbmVlZGVkIHBhY2thZ2VzDQppZiAoImN1cmwiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoImN1cmwiKQ0KfQ0KaWYgKCJyYXN0ZXIiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoInJhc3RlciIpDQp9DQppZiAoInN0cnVjY2hhbmdlIiAlaW4lIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKSA9PSBGQUxTRSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJzdHJ1Y2NoYW5nZSIpDQp9DQppZiAoIktlbmRhbGwiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoIktlbmRhbGwiKQ0KfQ0KaWYgKCJuY2RmNCIgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkgPT0gRkFMU0UpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygibmNkZjQiKQ0KfQ0KaWYgKCJiZmFzdCIgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkgPT0gRkFMU0UpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiYmZhc3QiKQ0KfQ0KaWYgKCJwaGVub3BpeCIgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkgPT0gRkFMU0UpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygicGhlbm9waXgiKQ0KfQ0KaWYgKCJmaWVsZHMiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoImZpZWxkcyIpDQp9DQppZiAoImRvUGFyYWxsZWwiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoImRvUGFyYWxsZWwiKQ0KfQ0KaWYgKCJzbm93IiAlaW4lIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKSA9PSBGQUxTRSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJzbm93IikNCn0NCmlmICgicXVhbnRyZWciICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoInF1YW50cmVnIikNCn0NCmlmICgicGFyYWxsZWwiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBhcmFsbGVsIikNCn0NCmlmICgiem9vIiAlaW4lIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKSA9PSBGQUxTRSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ6b28iKQ0KfQ0KaWYgKCJzYW5kd2ljaCIgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkgPT0gRkFMU0UpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygic2FuZHdpY2giKQ0KfQ0KI0luc3RhbGxpbmcgZ3JlZW5icm93biBmb3Igc2Vhc29uYWxpdHkNCmlmICgiZ3JlZW5icm93biIgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkgPT0gRkFMU0UpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcyhkaXJfR0IsIHJlcG9zID0gTlVMTCwgdHlwZT0ic291cmNlIikNCn0NCmlmICgicmdkYWwiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKSB7DQogIGluc3RhbGwucGFja2FnZXMoInJnZGFsIikNCg0KYGBgDQoNCkxvYWQgcGFja2FnZXMgdXNpbmcgdGhlIHRoZSBmdW5jdGlvbiAqKipsaWJyYXJ5KioqIHdoZW4gcmVxdWlyZWQNCg0KYGBge3IgZXZhbD1GQUxTRX0NCmxpYnJhcnkocGhlbm9waXgpDQpsaWJyYXJ5KEtlbmRhbGwpDQpsaWJyYXJ5KG5jZGY0KQ0KbGlicmFyeShmaWVsZHMpDQpsaWJyYXJ5KGRvUGFyYWxsZWwpDQpsaWJyYXJ5KHN0cnVjY2hhbmdlKQ0KbGlicmFyeShiZmFzdCkNCmxpYnJhcnkoc25vdykNCmxpYnJhcnkocXVhbnRyZWcpDQpsaWJyYXJ5KHBhcmFsbGVsKQ0KbGlicmFyeSh6b28pDQpsaWJyYXJ5KHNhbmR3aWNoKQ0KbGlicmFyeShyYXN0ZXIpDQpsaWJyYXJ5KGN1cmwpDQpsaWJyYXJ5KGdyZWVuYnJvd24pDQpsaWJyYXJ5KHJnZGFsKQ0KYGBgDQoNCioqKioqDQo+ICMjIyMjIFtTdGVwIDEgb2YgNiBEb3dubG9hZGluZyBGaWxlcyBpZiByZXF1aXJlZF0oIyl7bmFtZT0xMX0NCg0KKioqKioNCg0KRG93bmxvYWQgZGF0YSBFVkkgYW5kIGRhdGEgUGl4ZWwgUmVsaWFiaWxpdHkgd2hpY2ggd2FzIHByZXZpb3VzbHkgb3JkZXJlZCBmcm9tIHRoZSBBcHBsaWNhdGlvbiBmb3IgRXh0cmFjdGluZyBhbmQgRXhwbG9yaW5nIEFuYWx5c2lzIFJlYWR5IFNhbXBsZXMgKGFwcEVFQVJTKS4gVGhlIHRleHQgZmlsZSBwcmV2aW91c2x5IHNhdmVkIGNvbnRhaW5zIGFsbCBncmFudWxlcyBvcmRlcmVkIChleGNlcHQgJ1ZJIHF1YWxpdHkgY29udHJvbCcgZGF0YSBhcyB0aGV5IGFyZSBub3QgbmVlZGVkKQ0KDQoqKipJZiB5b3UgZG93bmxvYWRlZCB5b3VyIGRhdGEgZnJvbSBhcHBFRUFSUyBiZWZvcmVoYW5kLCBjb21tZW50IG91dCB0aGUgZm9sbG93aW5nIGVpZ2h0IGxpbmVzIGJlbG93IHVzaW5nICMqKiogDQpgYGB7ciBldmFsPUZBTFNFfQ0KZmlsZXNsIDwtIHNjYW4oZG93bmxvYWRMaXN0LCB3aGF0PSdsaXN0Jywgc2VwPSdcbicpDQpmb3IgKGQgaW4gMTpsZW5ndGgoZmlsZXNsKSl7DQogIGlmIChncmVwbCgiX1ZJX1F1YWxpdHlfIixmaWxlc2xbZF0pID09IEYpew0KICAgIGN1cmxfZG93bmxvYWQodXJsPWZpbGVzbFtkXSwgZGVzdGZpbGU9cGFzdGUwKGRhdGFQYXRoLCIvIixiYXNlbmFtZShmaWxlc2xbZF0pKSxxdWlldCA9IFQsIGhhbmRsZSA9IG5ld19oYW5kbGUoKSkNCiAgfQ0KICBwcmludChwYXN0ZTAoJ0Rvd25sb2FkaW5nIHNvdXJjZSBkYXRhIChTdGVwIDEgb2YgNik6ICcscm91bmQoZCAvIGxlbmd0aChmaWxlc2wpICogMTAwLCBkaWdpdHM9MiksJyUnKSkNCn0NCmBgYA0KIVtdKHJhd0VWSS5wbmcpDQoNCkNyZWF0aW5nIGEgdGVtcC1kaXJlY3RvcnkgZm9yIGludGVybWVkaWF0ZSBjYWxjdWxhdGlvbnMgYW5kIHNldHRpbmcgbWVtb3J5IGxpbWl0IHRvIGltcHJvdmUgdGhlIGNvbXB1dGluZyBjYXBhY2l0eSBvZiByDQpgYGB7ciBldmFsID0gRkFMU0V9DQpkaXIuY3JlYXRlKHBhc3RlMChkYXRhUGF0aCwnL3RlbXAvJykpDQpyYXN0ZXJPcHRpb25zKHRtcGRpcj1wYXN0ZTAoZGF0YVBhdGgsJy90ZW1wLycpKQ0KcmFzdGVyT3B0aW9ucyh0b2xlcmFuY2U9MSkNCm1lbW9yeS5saW1pdCg4MDAwMCkNCmBgYA0KDQoNCkxpc3RpbmcgdXAgYWxsIGRvd25sb2FkZWQgVElGLWZpbGVzIGluIHRoZSBkYXRhIGZvbGRlcg0KYGBge3J9DQpyYXN0ZXJEYXRhIDwtIGxpc3QuZmlsZXMocGF0aD1kYXRhUGF0aCwgcGF0dGVybj0nLnRpZiQnLCByZWN1cnNpdmU9RiwgaWdub3JlLmNhc2U9VCwgZnVsbC5uYW1lcz1UKQ0KcmFzdGVyRmlsZXMgPC0gYmFzZW5hbWUocmFzdGVyRGF0YSkNCmBgYA0KDQpDaHVuay1zaXplIGZvciBwcm9jZXNzaW5nIChpbiBQaXhlbCkgPGJyPg0KWW91IGNhbiByZWR1Y2UgdGhlc2UgbnVtYmVycyBpZiB5b3UgcnVuIGludG8gUkFNLVByb2JsZW1zIGVhcmx5IG9uOiBUcnkgcmVkdWNpbmcgdGhlIG51bWJlcnMgdG8gMTAwMC4gSWYgeW91IHN0aWxsIHJ1biBpbnRvIFJBTS1wcm9ibGVtcywgcmVkdWNlIHRvIDUwMCBvciAyNTAuPGJyPg0KT25seSByZWR1Y2UgdGhlIG51bWJlcnMgaWYgeW91IGhhdmUgbWVtb3J5IGlzc3VlcyAoIkVycm9yOiBjYW5ub3QgYWxsb2NhdGUgdmVjdG9yIG9mIHNpemUgWy4uLl0iKQ0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KDQpjaHdpZHRoIDwtIDEwMDANCmNoaGVpZ2h0IDwtIDEwMDANCmBgYA0KKioqKg0KDQo+IyMjIyMgW1N0ZXAgMiBvZiA2IFN0YXJ0aW5nIEVWSS9WQ0kgYmxvY2sgRGF0YSBwcmVwYXJhdGlvbiAgJiAgRVZJIG1hc2tpbmddKCMpe25hbWU9MjJ9DQoNCioqKioNCkxpc3RpbmcgYWxsIEVWSSByYXN0ZXJzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIHBpeGVsIHJlbGlhYmlsaXR5IGRhdGENCg0KYGBge3IgZXZhbD0gRkFMU0V9DQpFVklyYXN0ZXJEYXRhIDwtIHJhc3RlckRhdGFbZ3JlcGwoJ0VWSScscmFzdGVyRGF0YSldIA0KRVZJcWMgPC0gcmFzdGVyRGF0YVtncmVwbCgncGl4ZWxfcmVsaWFiaWxpdHknLHJhc3RlckRhdGEpXSANCmBgYA0KDQoNCg0KQXV0b21hdGljYWxseSBhZGp1c3RpbmcgY2h1bmsgc2l6ZSBmb3Igc21hbGwgc2NlbmVzIGlmIG5lZWRlZA0KDQpgYGB7ciBldmFsID0gRkFMU0V9DQppbml0aWFsIDwtIHJhc3RlcihFVklyYXN0ZXJEYXRhWzFdKQ0KaWYgKGFzLm51bWVyaWMobmNvbChpbml0aWFsKSkgPD0gY2h3aWR0aCB8fCBhcy5udW1lcmljKG5yb3coaW5pdGlhbCkpIDw9IGNoaGVpZ2h0KXsNCiAgY2h3aWR0aCA8LSBjZWlsaW5nKG5jb2woaW5pdGlhbCkvMikNCn0NCmBgYA0KDQpQYXJzaW5nIGFsbCBET1kgYW5kIFllYXJzIGZyb20gdGhlIGZpbGVuYW1lcw0KDQpgYGB7ciBldmFsPSBGQUxTRX0NCkRPWXMgPC0gdW5pcXVlKHN1YnN0cihiYXNlbmFtZShFVklyYXN0ZXJEYXRhKSwzOCw0MCkpDQpZRUFScyA8LSB1bmlxdWUoc3Vic3RyKGJhc2VuYW1lKEVWSXJhc3RlckRhdGEpLDM0LDM3KSkNCmBgYA0KKioqVkNJOiBjaHVua3dpc2UgY2FsY3VsYXRpb24qKioNCg0KQ3JlYXRpbmcgb3V0cHV0IGZvbGRlcg0KDQpgYGB7ciBldmFsPSBGQUxTRX0NCmRpci5jcmVhdGUocGFzdGUwKGRhdGFQYXRoLCcvVkNJJykpDQpkaXIuY3JlYXRlKHBhc3RlMChkYXRhUGF0aCwnL0VWSScpKQ0KYGBgDQoNCkRldGVybWluaW5nIGNodW5rLXNoYXBlZmlsZQ0KDQpMb2FkaW5nIGV4YW1wbGUgaW1hZ2UgZnJvbSB0aGUgZG93bmxvYWRlZCBkYXRhDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpleFJTVCA8LSByYXN0ZXIoRVZJcmFzdGVyRGF0YVsxXSkNCmBgYA0KDQoNCg0KDQpgYGB7ciBldmFsPUZ9DQpleFBSPC1yYXN0ZXIoRVZJcWNbMV0pDQpgYGANCg0KDQoNCg0KDQpEZXRlcm1pbmluZyBjaHVua3MNCmBgYHtyIGV2YWw9RkFMU0V9DQpoICAgPC0gY2VpbGluZyhuY29sKGV4UlNUKS9jZWlsaW5nKG5jb2woZXhSU1QpIC8gY2h3aWR0aCkpDQp2ICAgPC0gY2VpbGluZyhucm93KGV4UlNUKS9jZWlsaW5nKG5yb3coZXhSU1QpIC8gY2hoZWlnaHQpKSANCg0KYGBgDQoNCkNyZWF0aW5nIHNoYXBlZmlsZSBmb3IgZWFjaCBjaHVuaw0KDQpgYGB7ciBldmFsPUZBTFNFfQ0Kc3BsaXQgICAgIDwtIGFnZ3JlZ2F0ZShleFJTVCxmYWN0PWMoaCx2KSkNCnNwbGl0W10gICA8LSAxOm5jZWxsKHNwbGl0KQ0Kc3BsaXRzaHAgIDwtIHJhc3RlclRvUG9seWdvbnMoc3BsaXQpDQpuYW1lcyhzcGxpdHNocCkgPC0gJ3NoYXBlcycNCm5vdGlsZXMgPC0gbmNlbGwoc3BsaXQpDQpgYGANCg0KRmlsdGVyIHZhbHVlcyBmb3IgcXVhbGl0eSBtYXNraW5nIGNsb3VkZWQgcGl4ZWxzOiAiMCIgYW5kICIxIiBpbiB0aGUgcGl4ZWwgcmVsaWFiaWxpdHkgYmFuZHMgYXJlIGFjY2VwdGVkIGFzIHN1ZmZpY2llbnQgcXVhbGl0eQ0KDQohW10oUFIucG5nKQ0KDQpSYW5rIEtleXxTdW1tYXJ5IFFBDQotLS0tLS0tLXwtLS0tLS0tLQ0KLTEgICAgICB8RmlsbC9ObyBEYXRhDQoqKiowKioqIHwqKipHb29kIGRhdGEqKioNCioqKjEqKiogfCoqKk1hcmdpbmFsIERhdGEqKioNCiAyICAgICAgfFNub3cvSWNlDQogMyAgICAgIHxDbG91ZHkNCiANCkZvciB0aGlzIGFuYWx5c2lzIHdlIHdpbGwgYmUgY29uc2lkZXJpbmcgZ29vZCBkYXRhIGFuZCBtYXJnaW5hbCBkYXRhDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpnb29kVmFsdWVzIDwtIGMoMCwxKQ0KYGBgDQoNCg0KIVtdKEVWSXdpdGhvdXQgY2xvdWRzLnBuZykNCg0KDQpNYXNraW5nIGNsb3Vkcy9zbm93OyBTcGxpdHRpbmcgZGF0YSBpbnRvIGNodW5rcw0KYGBge3IgZXZhbD1GQUxTRX0NCg0KZm9yIChkIGluIDE6bGVuZ3RoKERPWXMpKXsNCiAgI0ZpbHRlcmluZyBhbGwgcmVsZXZhbnQgZGF0YSBmb3IgdGhpcyBET1kNCiAgdnJhc3RlckRhdGEgPC0gRVZJcmFzdGVyRGF0YVtncmVwbChwYXN0ZTAoRE9Zc1tkXSwnX2FpZCcpLEVWSXJhc3RlckRhdGEpXQ0KICAjLi5hbmQgdGhlaXIgY29ycmVzcG9uZGluZyBwaXhlbCByZWxpYWJpbGl0eSBkYXRhDQogIHZRQyA8LSBFVklxY1tncmVwbChwYXN0ZTAoRE9Zc1tkXSwnX2FpZCcpLEVWSXFjKV0NCiAgI1JlYWRpbmcgeWVhcnMgb2YgYXZhaWxhYmxlIGRhdGENCiAgdlllYXIgPC0gc3Vic3RyKGJhc2VuYW1lKHZyYXN0ZXJEYXRhKSwzNCwzNykNCiAgZm9yICh5IGluIDE6bGVuZ3RoKHZZZWFyKSl7DQogICAgdmlQUkUgPC0gcmFzdGVyKHZyYXN0ZXJEYXRhW3ldKQ0KCSNBcHBseWluZyBxdWFsaXR5IG1hc2sgdG8gZWFjaCBpbWFnZSAoaWYgbWFza2luZyB3YXMgYWN0aXZhdGVkKQ0KICAgIGlmIChjbG91ZG1hc2sgPT0gMSl7DQogICAgICBxYyA8LSByYXN0ZXIodlFDW3ldKQ0KICAgICAgdmlQUkUgPC0gb3ZlcmxheSh2aVBSRSwgcWMsIGZ1biA9IGZ1bmN0aW9uKHgsIHkpIHsNCiAgICAgICAgeFshKHkgJWluJSBnb29kVmFsdWVzKV0gPC0gTkENCiAgICAgICAgcmV0dXJuKHgpDQogICAgICB9KQ0KICAgIH0NCmBgYA0KDQoNClNwbGl0dGluZyAobWFza2VkKSBkYXRhIGludG8gQ2h1bmtzDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpmb3IoaSBpbiAxOm5jZWxsKHNwbGl0KSl7DQogICAgICBleCAgICAgICAgICA8LSBleHRlbnQoc3BsaXRzaHBbc3BsaXRzaHAkc2hhcGVzPT1pLF0pDQogICAgICBleHggICAgICAgICA8LSBjcm9wKHZpUFJFLGV4KQ0KICAgICAgd3JpdGVSYXN0ZXIoZXh4LGZpbGVuYW1lPXBhc3RlMChkYXRhUGF0aCwnL3RlbXAvJyxET1lzW2RdLCdfJyx2WWVhclt5XSwnX0VWSUNIVU5LJyxmb3JtYXRDKGksIHdpZHRoPTMsIGZsYWc9JzAnKSksZm9ybWF0PSdHVGlmZicsIG92ZXJ3cml0ZT1UUlVFKQ0KfQ0KfQ0KICAjKFByb2dyZXNzIHJlcG9ydCkNCiAgcHJpbnQocGFzdGUwKCdEYXRhIHByZXBhcmF0aW9uIChWQ0kpICYgbWFza2luZyAoU3RlcCAyIG9mIDYpOiAnLHJvdW5kKGQgLyBsZW5ndGgoRE9ZcykgICogMTAwLCBkaWdpdHM9MiksJyUnKSkNCn0NCmBgYA0KKioqKg0KPiAjIyMjIyBbU3RlcCAzIG9mIDYgQXBwbHlpbmcgVkNJIGNhbGN1bGF0aW9uIHRvIGVhY2ggY2h1bmsgdGhhdCB3YXMgcHJldmlvdXNseSBjcmVhdGVkIGluIHN0ZXAgMl0oIyl7bmFtZT0zfQ0KDQoqKioqDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQojTGlzdCBhbGwgY2h1bmtzDQpFVkljaHVua3MgPC0gbGlzdC5maWxlcyhwYXRoPXBhc3RlMChkYXRhUGF0aCwnL3RlbXAvJyksIHBhdHRlcm49J19FVklDSFVOSycsIHJlY3Vyc2l2ZT1GLCBpZ25vcmUuY2FzZT1ULCBmdWxsLm5hbWVzPVQpDQpmb3IgKGQgaW4gMTpsZW5ndGgoRE9Zcykpew0KICBmb3IgKHQgaW4gMTpub3RpbGVzKXsNCiAgICAjRmlsdGVyaW5nIHJlbGV2YW50IGNodW5rcyBmb3IgdGhpcyBzcGVjaWZpYyBkYXRlDQogICAgc0VWSWNodW5rcyA8LSBFVkljaHVua3NbZ3JlcGwocGFzdGUwKERPWXNbZF0sJ18nKSxFVkljaHVua3MpXSANCiAgICBzRVZJY2h1bmtzIDwtIHNFVkljaHVua3NbZ3JlcGwocGFzdGUwKCdfRVZJQ0hVTksnLGZvcm1hdEModCwgd2lkdGg9MywgZmxhZz0nMCcpKSxzRVZJY2h1bmtzKV0gDQoJI0xpc3RpbmcgeWVhcnMgb2YgZGF0YSBhdmFpbGFibGUgZm9yIGVhY2ggRE9ZDQoJdnZZZWFyIDwtIHN1YnN0cihiYXNlbmFtZShzRVZJY2h1bmtzKSw1LDgpDQogICAgDQogICAgaWYgKGxlbmd0aChzRVZJY2h1bmtzKSA+IDApew0KICAgICAgc1QgPC0gc3RhY2soc0VWSWNodW5rcykNCiAgICAgIA0KCSAgI1JlbW92aW5nIGZpbGxlci12YWx1ZXMgZnJvbSBFVkkgZGF0YQ0KCSAgc1Rbc1Q8KC0yOTk5KV0gPC0gTkENCiAgICAgIA0KICAgICAgI1ZDSSBmb3JtdWxhIGFwcGxpY2F0aW9uDQogICAgICB2aW1heCA8LSBzdGFja0FwcGx5KHNUICwgcmVwKDEsIG5sYXllcnMgKHNUKSksIG1heCwgbmEucm09VCkNCiAgICAgIHZpbWluIDwtIHN0YWNrQXBwbHkoc1QgLCByZXAoMSwgbmxheWVycyAoc1QpKSwgbWluLCBuYS5ybT1UKQ0KICAgICAgeiA8LSB2aW1heCAtIHZpbWluDQogICAgICBWQ0kgPC0gKChzVCAtdmltaW4pL3opKjEwMA0KICAgICAgDQogICAgICAjV3JpdGluZyBWQ0ktY2h1bmtzIGZvciBlYWNoIGF2YWlsYWJsZSB5ZWFyDQogICAgICBmb3IgKHkgaW4gMTpsZW5ndGgodnZZZWFyKSl7DQogICAgICAgIHdyaXRlUmFzdGVyKFZDSVtbeV1dLGZpbGVuYW1lPXBhc3RlMChkYXRhUGF0aCwnL3RlbXAvJyxET1lzW2RdLCdfJyx2dlllYXJbeV0sJ19WQ0lDSFVOSycsZm9ybWF0Qyh0LCB3aWR0aD0zLCBmbGFnPScwJykpLGZvcm1hdD0nR1RpZmYnLCBvdmVyd3JpdGU9VFJVRSkNCiAgICAgIH0NCiAgICB9DQogIH0NCiAgIyhQcm9ncmVzcyByZXBvcnQpDQogIHByaW50KHBhc3RlMCgnVkNJIHByb2Nlc3NpbmcgKFN0ZXAgMyBvZiA2KTogJyxyb3VuZChkIC8gbGVuZ3RoKERPWXMpICAqIDEwMCwgZGlnaXRzPTIpLCclJykpDQp9DQoNCmBgYA0KDQohW10oVkNJLnBuZykNCg0KDQo8YnI+DQoNCioqKioqDQo+ICMjIyMjIFtTdGVwIDQgb2YgNiBWQ0kgY2h1bmsgbWVyZ2luZyBhbmQgb3V0cHV0XSgjKXtuYW1lPTQ0fQ0KDQoqKioqKg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KI0xpc3RpbmcgYWxsIGNyZWF0ZWQgY2h1bmtzDQpWQ0ljaHVua3MgPC0gbGlzdC5maWxlcyhwYXRoPXBhc3RlMChkYXRhUGF0aCwnL3RlbXAvJyksIHBhdHRlcm49J19WQ0lDSFVOSycsIHJlY3Vyc2l2ZT1GLCBpZ25vcmUuY2FzZT1ULCBmdWxsLm5hbWVzPVQpDQojTG9vcGluZyB0aHJvdWdoIGVhY2ggYXZhaWxhYmxlIERPWV9ZRUFSIGNvbWJpbmF0aW9uDQpmb3IgKHkgaW4gMTpsZW5ndGgoWUVBUnMpKXsNCiAgZm9yIChkIGluIDE6bGVuZ3RoKERPWXMpKXsNCiAgICAjTGlzdGluZyByZWxldmFudCBjaHVua3MgKEVWSSwgVkNJKSBmb3IgdGhpcyBzcGVjaWZpYyBkYXRlDQogICAgc1ZDSWNodW5rcyA8LSBWQ0ljaHVua3NbZ3JlcGwocGFzdGUwKERPWXNbZF0sJ18nLFlFQVJzW3ldLCdfJyksVkNJY2h1bmtzKV0NCiAgICBzRVZJY2h1bmtzIDwtIEVWSWNodW5rc1tncmVwbChwYXN0ZTAoRE9Zc1tkXSwnXycsWUVBUnNbeV0sJ18nKSxFVkljaHVua3MpXSANCiAgICAjQ3JlYXRpbmcgcmFzdGVyLWxpc3Qgb2YgdGhlIEVWSSBjaHVua3MNCiAgICBpZiAobGVuZ3RoKHNFVkljaHVua3MpID4gMCl7DQogICAgICBpZiAobGVuZ3RoKHNFVkljaHVua3MpID4gMSl7DQogICAgICAgIHNNb3MgPC0gbGlzdCgpDQogICAgICAgIGZvciAobyBpbiAxOmxlbmd0aChzRVZJY2h1bmtzKSl7DQogICAgICAgICAgc01vcyA8LSBhcHBlbmQoc01vcywgcmFzdGVyKHNFVkljaHVua3Nbb10pKQ0KICAgICAgICB9DQogICAgICAgICNNb3NhaWNraW5nIHRoZSBFVkkgY2h1bmtzDQogICAgICAgIHNNb3MkZnVuID0gbWVhbg0KICAgICAgICBNb3MgPC0gZG8uY2FsbChtb3NhaWMsIHNNb3MpDQogICAgICAgIE1vcyA8LSBNb3MqMC4wMDAxDQoJCSNPdXRwdXQgb2YgbW9zYWlja2VkLCBzY2FsZWQgRVZJIGltYWdlDQogICAgICAgIHdyaXRlUmFzdGVyKE1vcyxmaWxlbmFtZT1wYXN0ZTAoZGF0YVBhdGgsJy9FVkkvJyxET1lzW2RdLCdfJyxZRUFSc1t5XSwnX0VWSScpLGZvcm1hdD0nR1RpZmYnLCBvdmVyd3JpdGU9VFJVRSkNCiAgICAgIH1lbHNlew0KCQkjRmFpbC1zYWZlIGluIGNhc2Ugb25seSBvbmUgY2h1bmsgaXMgYXZhaWxhYmxlDQogICAgICAgIGV4cCA8LSByYXN0ZXIoc0VWSWNodW5rc1sxXSkNCiAgICAgICAgZXhwIDwtIGV4cCowLjAwMDENCiAgICAgICAgd3JpdGVSYXN0ZXIoZXhwLGZpbGVuYW1lPXBhc3RlMChkYXRhUGF0aCwnL0VWSS8nLERPWXNbZF0sJ18nLFlFQVJzW3ldLCdfRVZJJyksZm9ybWF0PSdHVGlmZicsIG92ZXJ3cml0ZT1UUlVFKQ0KICAgICAgfQ0KICAgIH0NCgkjQ3JlYXRpbmcgcmFzdGVyLWxpc3Qgb2YgdGhlIFZDSSBjaHVua3MNCiAgICBpZiAobGVuZ3RoKHNWQ0ljaHVua3MpID4gMCl7DQogICAgICBpZiAobGVuZ3RoKHNWQ0ljaHVua3MpID4gMSl7DQogICAgICAgIHNNb3MgPC0gbGlzdCgpDQogICAgICAgIGZvciAobyBpbiAxOmxlbmd0aChzVkNJY2h1bmtzKSl7DQogICAgICAgICAgc01vcyA8LSBhcHBlbmQoc01vcywgcmFzdGVyKHNWQ0ljaHVua3Nbb10pKQ0KICAgICAgICB9DQogICAgICAgICNNb3NhaWNraW5nIHRoZSBWQ0kgY2h1bmtzDQogICAgICAgIHNNb3MkZnVuID0gbWVhbg0KICAgICAgICBNb3MgPC0gZG8uY2FsbChtb3NhaWMsIHNNb3MpDQogICAgICAgIA0KCSAgICAjT3V0cHV0OiBmaW5hbCBWQ0kgbW9zYWljDQogICAgICAgIHdyaXRlUmFzdGVyKE1vcyxmaWxlbmFtZT1wYXN0ZTAoZGF0YVBhdGgsJy9WQ0kvJyxET1lzW2RdLCdfJyxZRUFSc1t5XSwnX1ZDSScpLGZvcm1hdD0nR1RpZmYnLCBvdmVyd3JpdGU9VFJVRSkNCiAgICAgIH1lbHNlew0KCSAgICAjRmFpbC1zYWZlIGluIGNhc2Ugb25seSBvbmUgY2h1bmsgaXMgYXZhaWxhYmxlDQogICAgICAgIHdyaXRlUmFzdGVyKHJhc3RlcihzVkNJY2h1bmtzWzFdKSxmaWxlbmFtZT1wYXN0ZTAoZGF0YVBhdGgsJy9WQ0kvJyxET1lzW2RdLCdfJyxZRUFSc1t5XSwnX1ZDSScpLGZvcm1hdD0nR1RpZmYnLCBvdmVyd3JpdGU9VFJVRSkNCiAgICAgIH0NCiAgICB9DQogICAgcHJpbnQocGFzdGUwKCdFVkkgb3V0cHV0ICYgVkNJIG91dHB1dCAoU3RlcCA0IG9mIDYpOiAnLHJvdW5kKChkKyhsZW5ndGgoRE9ZcykqKHktMSkpKS8obGVuZ3RoKERPWXMpKmxlbmd0aChZRUFScykpKjEwMCwgZGlnaXRzPTIpLCclJykpIA0KICB9DQp9DQpgYGANCg0KDQo+ICMjIyMgUmVtb3ZpbmcgdGVtcCBmaWxlcyB0byBmcmVlIHNwYWNlDQpgYGB7ciBldmFsPUZBTFNFfQ0KdG1wIDwtIGxpc3QuZmlsZXMocGF0aD1wYXN0ZTAoZGF0YVBhdGgsJy90ZW1wLycpLCByZWN1cnNpdmU9RiwgaWdub3JlLmNhc2U9VCwgZnVsbC5uYW1lcz1UKQ0KZmlsZS5yZW1vdmUodG1wKQ0KYGBgDQoNCioqKioqDQo+ICMjIyMjIFtTdGVwIDUgb2YgNiBUaGUgc2Vhc29uYWxpdHkvcGhlbm9sb2d5ICBibG9ja10oIyl7bmFtZT01NX0NCg0KKioqKioNCg0KQ3JlYXRpbmcgb3V0cHV0IGZvbGRlciBmb3IgdGhlIHNlYXNvbnMNCg0KYGBge3IgZXZhbD1GQUxTRX0NCmRpci5jcmVhdGUocGFzdGUwKGRhdGFQYXRoLCcvc2Vhc29uLycpKQ0KYGBgDQoNCj4gU2Vhc29uYWxpdHkgZm9yIGVhY2ggeWVhcg0KDQpMaXN0aW5nIEVWSSBkYXRhIHdoaWNoIGlzIHRoZSBiYXNlIGZvciBzZWFzb25hbGl0eSBjYWxjdWxhdGlvbg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KYWxsRVZJIDwtIGxpc3QuZmlsZXMocGFzdGUwKGRhdGFQYXRoLCcvRVZJLycpLCBwYXR0ZXJuPSIudGlmJCIsIHJlY3Vyc2l2ZT1GLCBmdWxsLm5hbWVzID0gVCkNCmBgYA0KDQpDcmVhdGluZyBhIHN0YWNrIG9mIGFsbCBFVkkgZGF0YQ0KDQpgYGB7ciBldmFsPUZBTFNFfQ0Kc0VWSSA8LSBzdGFjayhhbGxFVkkpDQpgYGANCg0KUGFzc2luZyBhIHN0YXJ0aW5nIHllYXIgdG8gZ3JlZW5icm93biBmb3IgcHJvcGVyIG91dHB1dCBmaWxlbmFtZXMNCg0KYGBge3IgZXZhbD1GQUxTRX0NCnN0RGF0ZSA8LSBjKGFzLm51bWVyaWMobWluKFlFQVJzKSksMDEsMDEpDQpgYGANCj4gU3RhcnQgbXVsdGljb3JlIHByb2Nlc3NpbmcNCg0KKiBUaGUgc2Vhc29uYWxpdHktY2FsY3VsYXRpb24gd2lsbCB0YWtlIGFkdmFudGFnZSBvZiBhbGwgQ1BVIGNvcmVzLiBUaGUgUEMgbWlnaHQgbGFnIGR1cmluZyB0aGUgcHJvY2VzcyBhbmQgbWF5IG5vdCBiZSB1c2FibGUgZm9yIG90aGVyIHRhc2tzIGluIGEgcHJvZHVjdGl2ZSB3YXkNCiogSWYgeW91IHdhbnQgdG8ga2VlcCB1c2luZyB5b3VyIFBDIGR1cmluZyB0aGUgcHJvY2VzcywgcmVkdWNlIHRoZSBudW1iZXIgb2YgdXNlZCBjb3JlcyBieSBvbmUuIFRvIGRvIHRoaXMsIHJlcGxhY2UgbWF4KGFzLm51bWVyaWMoU3lzLmdldGVudignTlVNQkVSX09GX1BST0NFU1NPUlMnKSksMSkgd2l0aCBtYXgoYXMubnVtZXJpYyhTeXMuZ2V0ZW52KCdOVU1CRVJfT0ZfUFJPQ0VTU09SUycpKS0xLDEpIGluIHRoZSBmb2xsb3dpbmcgbGluZS4NCg0KYGBge3IgZXZhbD1GQUxTRX0NCm5vX2NvcmVzIDwtIG1heChhcy5udW1lcmljKFN5cy5nZXRlbnYoJ05VTUJFUl9PRl9QUk9DRVNTT1JTJykpLDEpDQpwcmludChwYXN0ZTAoU3lzLnRpbWUoKSwiIFNlYXNvbmFsaXR5IGNhbGN1bGF0aW9uICh0aGlzIHdpbGwgdGFrZSBhIHdoaWxlOyBTdGVwIDUgb2YgNikiKSkNCmJlZ2luQ2x1c3Rlcihub19jb3JlcykNCmBgYA0KDQpTZWFzb25hbGl0eSBjYWxjdWxhdGlvbg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KI0NoZWNrIHRoZSBncmVlbmJyb3duLXBhY2thZ2UgZG9jdW1lbnRhdGlvbiBhdCBodHRwOi8vZ3JlZW5icm93bi5yLWZvcmdlLnItcHJvamVjdC5vcmcvIGFuZCB0aGUgImluIGRldGFpbCIgcGFnZSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiB0aGUgY2FsY3VsYXRpb24NCnBoZW5tYXAgPC0gY2x1c3RlclIoc0VWSSxmdW49UGhlbm9sb2d5UmFzdGVyLGFyZ3M9bGlzdChzdGFydCA9IHN0RGF0ZSwgZnJlcSA9IDIzLCB0c2dmPU5VTEwsIGFwcHJvYWNoPSJEZXJpdiIsIGNoZWNrLnNlYXNvbmFsaXR5PU5VTEwpKQ0KDQpgYGANCg0KRW5kaW5nIG11bHRpLWNvcmUgcHJvY2Vzc2luZw0KYGBge3IgZXZhbD1GQUxTRX0NCmVuZENsdXN0ZXIoKQ0KYGBgDQoNCg0KDQpPdXRwdXQgUGhlbm9sb2d5DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpuIDwtIE5hbWVzUGhlbm9sb2d5UmFzdGVyKHBoZW5tYXAsIHN0YXJ0PWFzLm51bWVyaWMoWUVBUnNbMV0pKQ0KZm9yIChpIGluIDE6bmxheWVycyhwaGVubWFwKSl7DQogIHdyaXRlUmFzdGVyKHBoZW5tYXBbW2ldXSxmaWxlbmFtZT1wYXN0ZTAoZGF0YVBhdGgsIi9zZWFzb24vIixuW2ldLCIudGlmIiksZm9ybWF0PSJHVGlmZiIsb3ZlcndyaXRlPVQpDQp9DQpgYGANCioqKioqDQo+ICMjIyMjIFtTdGVwIDYgb2YgNiAgV2VpZ2h0ZWQgbGluZWFyIGNvbWJpbmF0aW9uIG9mIFZDSSBvdXRwdXQgIGFuZCBFVkkgUGhlbm9sb2d5IG91dHB1dF0oIyl7bmFtZT02Nn0NCg0KKioqKioNCg0KTGlzdCBhbGwgZmluaXNoZWQgVkNJIGltYWdlcw0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KYWxsVkNJIDwtIGxpc3QuZmlsZXMocGFzdGUwKGRhdGFQYXRoLCcvVkNJLycpLCBwYXR0ZXJuPSIudGlmJCIsIHJlY3Vyc2l2ZT1GLCBmdWxsLm5hbWVzID0gVCkNCg0KYGBgDQoNCkNyZWF0ZSBhbiBvdXRwdXQtZm9sZGVyIGZvciB0aGUgZmluYWwgb3V0cHV0DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpkaXIuY3JlYXRlKHBhc3RlMChkYXRhUGF0aCwnL3dlaWdodGVkJykpDQpgYGANCg0KTG9vcGluZyB0aHJvdWdoIGVhY2ggeWVhcigvc2Vhc29uKQ0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KZm9yIChzeSBpbiBhcy5udW1lcmljKG1pbihZRUFScykpOmFzLm51bWVyaWMobWF4KFlFQVJzKSkpew0KICANCiAgI0ZhaWwtc2FmZTogY2hlY2sgaWYgc2Vhc29uYWxpdHkgZGF0YSB3YXMgY2FsY3VsYXRlZCBmb3IgdGhlIHllYXINCiAgaWYgKGZpbGUuZXhpc3RzKHBhc3RlMChkYXRhUGF0aCwiL3NlYXNvbi8iLCJTT1MuIixzeSwiLnRpZiIpKSAmJiAhKHN5ID09IG1heChZRUFScykgJiYgaGVtaXNwaGVyZSAhPSAxKSl7DQogIA0KICAjQ2hlY2sgZm9yIGhlbWlzcGhlcmUsIGxvYWQgVkNJIGRhdGEgZm9yIHRoZSB5ZWFyDQogIGlmIChoZW1pc3BoZXJlID09IDEpew0KICBseVZDSSA8LSBhbGxWQ0lbZ3JlcGwoc3ksYWxsVkNJKV0NCiAgZHNjciA8LSBzeQ0KICB9ZWxzZXsNCiAgI0xvYWQgY29ycmVjdCBkYXRhIGlmIHNvdXRoZXJuIGhlbWlzcGhlcmUgd2FzIHNlbGVjdGVkIChzZWFzb25hbGl0eSBzaGlmdCkNCiAgbHlWQ0kgPC0gYyhhbGxWQ0lbZ3JlcGwoc3ksYWxsVkNJKV0sYWxsVkNJW2dyZXBsKHN5KzEsYWxsVkNJKV0pDQogIGlmIChzeSA9PSBtaW4oWUVBUnMpKXsNCiAgbHlWQ0kgPC0gbHlWQ0lbMToyM10NCiAgIH1lbHNlew0KICBseVZDSSA8LSBseVZDSVsxMzozNV0NCiAgfQ0KICAjQWRqdXN0aW5nIG91dHB1dCBmaWxlbmFtZXMgaWYgc291dGhlcm4gaGVtaXNwaGVyZSB3YXMgc2VsZWN0ZWQNCiAgZHNjciA8LSBwYXN0ZTAoc3ksIl8iLHN5KzEpDQogIH0NCiAgDQpgYGANCg0KU3RhY2tpbmcgYWxsIFZDSSBmb3IgdGhlIHllYXINCg0KYGBge3IgZXZhbD1GQUxTRX0NCiAgeVZDSSA8LSBzdGFjayhseVZDSSkNCmBgYA0KDQpMb2FkaW5nIHNlYXNvbmFsaXR5IHJhc3RlcnMgZm9yIHRoZSB5ZWFyDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQogIFNvUyA8LSByYXN0ZXIocGFzdGUwKGRhdGFQYXRoLCIvc2Vhc29uLyIsIlNPUy4iLHN5LCIudGlmIikpDQogIFBlYWsgPC0gcmFzdGVyKHBhc3RlMChkYXRhUGF0aCwiL3NlYXNvbi8iLCJQT1AuIixzeSwiLnRpZiIpKQ0KICBFb1MgPC0gcmFzdGVyKHBhc3RlMChkYXRhUGF0aCwiL3NlYXNvbi8iLCJFT1MuIixzeSwiLnRpZiIpKQ0KICANCmBgYA0KDQo+IENyZWF0aW5nIFZDSSBtZWFucyBmb3IgdGhlIHRocmVlICJibG9ja3MiIG9mIHNlYXNvbmFsIHRpbWluZw0KDQojIyMjIyBTdGFydCBvZiBzZWFzb24gKFNPUykgdmFyaWFibGVzDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpCbG9ja0EgPC0gc3RhY2soKQ0KICAjSXRlcmF0aW5nIHRocm91Z2ggYWxsIDIzIGltYWdlcyBvZiB0aGUgc2Vhc29uDQogIGZvciAoaSBpbiAxOjIzKXsNCiAgICAjUmVhZCBzdGFydC1vZi1zZWFzb24gZGF0ZXMNCiAgICBzIDwtIFNvUw0KCSNSZWFkIGRhdGVzIHVwIHRvIDE2IGRheXMgYmVmb3JlIHBlYWsgb2Ygc2Vhc29uDQogICAgZSA8LSAoUGVhayAtIDEpDQogICAgDQoJI0NoZWNrIGlmIGN1cnJlbnQgaXRlcmF0aW9uIGxpZXMgd2l0aGluIHRoZSBzZWFzb25hbCBkYXRlcyBvZiBlYWNoIHBpeGVsDQogICAgc1tzID4gaV0gPC0gTkENCiAgICBlW2UgPCBpXSA8LSBOQQ0KICAgIA0KCSNDcmVhdGluZyBhIGJpbmFyeSBtYXNrIGFuZCBhcHBseSB0byB0aGUgVkNJIGltYWdlDQogICAgbSA8LSBzKmUNCiAgICB2IDwtIHlWQ0lbW2ldXSoobS9tKQ0KDQoJI0FkZCBsYXllciB0byBzdGFjaw0KICAgIEJsb2NrQSA8LSBzdGFjayhCbG9ja0EsIHYpDQogICAgDQogIH0NCmBgYA0KDQpDcmVhdGUgbWVhbiBvZiB0aGlzIHRpbWUtYmxvY2sgQmxvY2stQSBTdGFydCBPZiBTZWFzb24NCg0KYGBge3IgZXZhbD1GQUxTRX0NCkJsb2NrQSA8LSBjYWxjKEJsb2NrQSwgZnVuPW1lYW4sIG5hLnJtPVQpDQpgYGANCg0KICANCiMjIyMjIFBlYWsgb2Ygc2Vhc29uIHZhcmlhYmxlcw0KDQoqKipTZWUgY29tbWVudHMgYWJvdmUqKioNCg0KYGBge3IgZXZhbD1GQUxTRX0NCkJsb2NrQiA8LSBzdGFjaygpDQogIGZvciAoaSBpbiAxOjIzKXsNCiAgICBzIDwtIFBlYWsNCiAgICBlIDwtIFBlYWsNCiAgICANCiAgICBzW3MgPiBpXSA8LSBOQQ0KICAgIGVbZSA8IGldIDwtIE5BDQogICAgDQogICAgbSA8LSBzKmUNCiAgICB2IDwtIHlWQ0lbW2ldXSoobS9tKQ0KICAgIAkJDQogICAgQmxvY2tCIDwtIHN0YWNrKEJsb2NrQiwgdikNCiAgfQ0KYGBgDQoNCkNyZWF0ZSBtZWFuIG9mIHRoaXMgdGltZS1ibG9jayBCbG9jay1CIFBlYWsgb2Ygc2Vhc29uDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpCbG9ja0IgPC0gY2FsYyhCbG9ja0IsIGZ1bj1tZWFuLCBuYS5ybT1UKQ0KYGBgDQoNCiMjIyMjIEVuZCBvZiBzZWFzb24gKEVPUykgdmFyaWFibGVzDQoNCioqKlNlZSBjb21tZW50cyBhYm92ZSoqKg0KYGBge3IgZXZhbD1GQUxTRX0NCkJsb2NrQyA8LSBzdGFjaygpDQogIGZvciAoaSBpbiAxOjIzKXsNCiAgICBzIDwtIChQZWFrICsgMSkNCiAgICBlIDwtIEVvUw0KICAgIA0KICAgIHNbcyA+IGldIDwtIE5BDQogICAgZVtlIDwgaV0gPC0gTkENCg0KICAgIG0gPC0gcyplDQogICAgdiA8LSB5VkNJW1tpXV0qKG0vbSkNCiAgICAgICANCiAgICBCbG9ja0MgPC0gc3RhY2soQmxvY2tDLCB2KQ0KICB9DQpgYGANCg0KQ3JlYXRlIG1lYW4gb2YgdGhpcyB0aW1lLWJsb2NrIEJsb2NrLWMgRU9TDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQogQmxvY2tDIDwtIGNhbGMoQmxvY2tDLCBmdW49bWVhbiwgbmEucm09VCkNCmBgYA0KDQo8YnI+DQoNCiFbXShzZWFzb24ucG5nKQ0KDQo8YnI+DQoNCj4gV2VpZ2h0aW5nOiAqNS03LTEqIHN0YXJ0LXBlYWstZW5kIG9mIHNlYXNvbiBtZWFuDQoNClJlc3VsdDogd2VpZ2h0ZWQgVkNJIGJ5IHNlYXNvbg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KV2VpZ2h0ZWRTdGFjazwtc3RhY2soQmxvY2tBLEJsb2NrQSxCbG9ja0EsQmxvY2tBLEJsb2NrQSwNCiAgICAgICAgICAgICAgICAgICAgIEJsb2NrQixCbG9ja0IsQmxvY2tCLEJsb2NrQixCbG9ja0IsQmxvY2tCLEJsb2NrQiwNCiAgICAgICAgICAgICAgICAgICAgIEJsb2NrQykNCmBgYA0KDQpDcmVhdGUgdGhlIG1lYW4gb2YgdGhlIHNlYXNvbiB3ZWlnaHRoZWQgYmxvY2sgc3RhY2tzDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpXZWlnaHRlZFZDSSA8LSBjYWxjKFdlaWdodGVkU3RhY2ssIGZ1bj1tZWFuLG5hLnJtPVQpDQpgYGANCg0KPiBSYXN0ZXIgbWVhbiBjbGFzc2lmaWNhdGlvbg0KDQoqKipPdXRwdXQ6IGZpdmUgY2xhc3NlcyoqKg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KY1dlaWdodGVkVkNJIDwtIHJlY2xhc3NpZnkoV2VpZ2h0ZWRWQ0ksIGMoLTEsIDEwLCA0LCAgMTAsIDIwLCAzLCAgMjAsIDMwLCAyLCAzMCw0MCwgMSw0MCwxMDEsMCkpICANCndyaXRlUmFzdGVyKGNXZWlnaHRlZFZDSSxmaWxlbmFtZT1wYXN0ZTAoZGF0YVBhdGgsIi93ZWlnaHRlZC8iLGRzY3IsIl9kcm91Z2h0Rml2ZUNsLnRpZiIpLGZvcm1hdD0iR1RpZmYiLG92ZXJ3cml0ZT1UKQ0KICANCmBgYA0KDQoqKipPdXRwdXQ6IHRocmVlIGNsYXNzZXMgcmVxdWlyZWQgZm9yIHRoZSBuZXh0IHN0ZXBzIG9mIHRoZSBhbmFseXNpcyBhcyByZWNvbWVuZGVkIGJ5IHRoZSBUZWNobmljYWwgZ3VpZGFuY2UgZm9yIG1vbml0b3JpbmcgYW5kIHJlcG9ydGluZyBvbiBwcm9ncmVzcyBpbiBhY2hpZXZpbmcgdGhlIGdsb2JhbCB0YXJnZXRzIG9mIHRoZSBTZW5kYWkgRnJhbWV3b3JrIGZvciBEaXNhc3RlciBSaXNrIFJlZHVjdGlvbioqKg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KDQojKFByb2dyZXNzIHJlcG9ydCkNCiAgZFdlaWdodGVkVkNJIDwtIHJlY2xhc3NpZnkoV2VpZ2h0ZWRWQ0ksIGMoLTEsIDEwLCAyLCAgMTAsIDQwLCAxLCAgNDAsIDEwMSwgMCkpICANCiAgd3JpdGVSYXN0ZXIoZFdlaWdodGVkVkNJLGZpbGVuYW1lPXBhc3RlMChkYXRhUGF0aCwiL3dlaWdodGVkLyIsZHNjciwiX2Ryb3VnaHRUaHJlZUNsLnRpZiIpLGZvcm1hdD0iR1RpZmYiLG92ZXJ3cml0ZT1UKQ0KICANCiMoUHJvZ3Jlc3MgcmVwb3J0KQ0KcHJpbnQocGFzdGUwKCdXZWlnaHRpbmcgaW5kaWNlcyAoU3RlcCA2IG9mIDYpOiAnLHJvdW5kKChzeS1hcy5udW1lcmljKG1pbihZRUFScykpKSAoYXMubnVtZXJpYyhtYXgoWUVBUnMpKS1hcy5udW1lcmljKG1pbihZRUFScykpKSAgKiAxMDAsIGRpZ2l0cz0yKSwnJScpKQ0KfQ0KfQ0KYGBgDQoNCiFbXShBZ3JpY3VsdHVyYWxEcm91Z2h0SW1wYWN0LnBuZykNCjxicj4NCg0KRGVsZXRpbmcgYWxsIHRlbXAgZmlsZXMNCg0KYGBge3IgZXZhbD1GQUxTRX0NCnRtcCA8LSBsaXN0LmZpbGVzKHBhdGg9cGFzdGUwKGRhdGFQYXRoLCcvdGVtcC8nKSwgcmVjdXJzaXZlPUYsIGlnbm9yZS5jYXNlPVQsIGZ1bGwubmFtZXM9VCkNCmZpbGUucmVtb3ZlKHRtcCkNCg0KYGBgDQoNCj4gIyMjIyMgRmluaXNoZWQNCg0KYGBge3J9DQojRmluaXNoZWQNCnByaW50KHBhc3RlMChTeXMudGltZSgpLCcgLSBGaW5pc2hlZC4gWW91IHdpbGwgZmluZCB0aGUgZGF0YSBpbiB0aGUgc3ViZm9sZGVycyBcJ1ZDSVwnIGFuZCBcJ3dlaWdodGVkXCcgKGNsYXNzaWZpZWQgZHJvdWdodCBpbmRpY2F0b3JzKSBhdCAnLCBkYXRhUGF0aCwiLiIpKQ0KDQoNCmBgYA0KDQpPbmNlIHlvdSBlbnRlcmVkIGFsbCBuZWNlc3NhcnkgaW5mb3JtYXRpb24sIHNlbGVjdCB0aGUgd2hvbGUgY29kZSAoQ1RSTCArIGEpIGFuZCBjbGljayBvbiAicnVuIiAob3I6IENUUkwgKyBFbnRlcikuIERlcGVuZGluZyBvbiB5b3VyIHN0dWR5LWFyZWEsIGNhbGN1bGF0aW9ucyB3aWxsIHRha2Ugc2V2ZXJhbCBob3Vycy4gVGhlIHNjcmlwdCB3aWxsIGtlZXAgeW91IHVwZGF0ZWQgd2l0aCB0aGUgY3VycmVudCBzdGVwcyBiZWluZyBwZXJmb3JtZWQgaW4gdGhlIGNvbnNvbGUuIFlvdSB3aWxsIGFsc28gc2VlIGEgbWVzc2FnZSBpbiB0aGUgY29uc29sZSBvbmNlIGl0IGlzIGNvbXBsZXRlbHkgZmluaXNoZWQuIFNvbWV0aW1lcyBleGVjdXRpb24gbWlnaHQgc2VlbSB1bnJlc3BvbnNpdmUuIEFzIGxvbmcgYXMgeW91IGNhbiBzZWUgdGhlIGxpdHRsZSBzdG9wIHNpZ24gYWJvdmUgdGhlIGNvbnNvbGUsIHlvdSBjYW4gYmUgc3VyZSB0aGUgc2NyaXB0IGlzIHN0aWxsIHJ1bm5pbmcgKHNlZSBpbWFnZSBiZWxvdykNCg0KPGJyPg0KDQohW10oSW1hZ2UxNC5wbmcpDQoNCg0K