This notebook is licensed under the MIT License. If you use the code or data visualization designs contained within this notebook, it would be greatly appreciated if proper attribution is given back to this notebook and/or myself. Thanks! :)

Via https://twitter.com/felipehoffa/status/1111050585120206848

0.1 Setup

Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     
── Attaching packages ──────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.2.1     ✔ purrr   0.3.2
✔ tibble  2.1.3     ✔ dplyr   0.8.3
✔ tidyr   1.0.0     ✔ stringr 1.4.0
✔ readr   1.3.1     ✔ forcats 0.4.0
── Conflicts ─────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()

Attaching package: ‘scales’

The following object is masked from ‘package:purrr’:

    discard

The following object is masked from ‘package:readr’:

    col_factor

Attaching package: ‘lubridate’

The following object is masked from ‘package:base’:

    date
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Catalina 10.15

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] bigrquery_1.2.0 lubridate_1.7.4 scales_1.0.0    forcats_0.4.0  
 [5] stringr_1.4.0   dplyr_0.8.3     purrr_0.3.2     readr_1.3.1    
 [9] tidyr_1.0.0     tibble_2.1.3    ggplot2_3.2.1   tidyverse_1.2.1

loaded via a namespace (and not attached):
 [1] tidyselect_0.2.5 xfun_0.10        haven_2.1.1      lattice_0.20-38 
 [5] colorspace_1.4-1 vctrs_0.2.0      generics_0.0.2   htmltools_0.4.0 
 [9] yaml_2.2.0       base64enc_0.1-3  rlang_0.4.0      pillar_1.4.2    
[13] glue_1.3.1       withr_2.1.2      DBI_1.0.0        bit64_0.9-7     
[17] modelr_0.1.5     readxl_1.3.1     lifecycle_0.1.0  munsell_0.5.0   
[21] gtable_0.3.0     cellranger_1.1.0 rvest_0.3.4      evaluate_0.14   
[25] knitr_1.25       broom_0.5.2      Rcpp_1.0.2       backports_1.1.5 
[29] jsonlite_1.6     bit_1.1-14       hms_0.5.1        digest_0.6.21   
[33] stringi_1.4.3    grid_3.6.1       cli_1.1.0        tools_3.6.1     
[37] magrittr_1.5     lazyeval_0.2.2   crayon_1.3.4     pkgconfig_2.0.3 
[41] zeallot_0.1.0    xml2_1.2.2       assertthat_0.2.1 rmarkdown_1.16  
[45] httr_1.4.1       rstudioapi_0.10  R6_2.4.0         nlme_3.1-141    
[49] compiler_3.6.1  

1 EDA

1.1 SFO → SEA Flight Duration

Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
Authentication complete.
Complete
Billed: 0 B
Downloading 102 rows in 1 pages.

Parsing [========================================================] ETA:  0s
                                                                           

NB: As of ggplot 3.2.0, you must have the group aesthetic for boxplots manually specifying the bounds. (https://stackoverflow.com/q/57192727)

Alternate approach using ribbons (not used in final blog post since harder to visually parse, but present here for posterity):

1.2 SFO → JFK Distribution

Complete
Billed: 0 B
Downloading 102 rows in 1 pages.

Parsing [========================================================] ETA:  0s
                                                                           

1.3 JFK → SFO Flight Time Distribution

Complete
Billed: 0 B
Downloading 102 rows in 1 pages.

Parsing [========================================================] ETA:  0s
                                                                           

1.4 SFO → JFK Flight Speed

Complete
Billed: 0 B
Downloading 102 rows in 1 pages.

Parsing [========================================================] ETA:  0s
                                                                           

1.5 JFK → SFO Flight Speed

Complete
Billed: 0 B
Downloading 102 rows in 1 pages.

Parsing [========================================================] ETA:  0s
                                                                           

1.6 SFO → JFK Departure Delay

Complete
Billed: 0 B
Downloading 102 rows in 1 pages.

Parsing [========================================================] ETA:  0s
                                                                           

Remove whiskers since it distorts the graph unhelpfully.

1.7 JFK → SFO Departure Delay

Complete
Billed: 0 B
Downloading 102 rows in 1 pages.

Parsing [========================================================] ETA:  0s
                                                                           

2 LICENSE

MIT License

Copyright (c) 2019 Max Woolf

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

LS0tCnRpdGxlOiAiVmlzdWFsaXppbmcgQWlybGluZSBGbGlnaHQgQ2hhcmFjdGVyaXN0aWNzIEJldHdlZW4gU0ZPIGFuZCBKRksiCmF1dGhvcjogIk1heCBXb29sZiAoQG1pbmltYXhpcikiCmRhdGU6ICIyMDE5LTEwLTIzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIG1hdGhqYXg6IG51bGwKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIHRvYzogVHJ1ZQotLS0KClRoaXMgbm90ZWJvb2sgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBJZiB5b3UgdXNlIHRoZSBjb2RlIG9yIGRhdGEgdmlzdWFsaXphdGlvbiBkZXNpZ25zIGNvbnRhaW5lZCB3aXRoaW4gdGhpcyBub3RlYm9vaywgaXQgd291bGQgYmUgZ3JlYXRseSBhcHByZWNpYXRlZCBpZiBwcm9wZXIgYXR0cmlidXRpb24gaXMgZ2l2ZW4gYmFjayB0byB0aGlzIG5vdGVib29rIGFuZC9vciBteXNlbGYuIFRoYW5rcyEgOikKClZpYSBodHRwczovL3R3aXR0ZXIuY29tL2ZlbGlwZWhvZmZhL3N0YXR1cy8xMTExMDUwNTg1MTIwMjA2ODQ4CgojIyBTZXR1cAoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoYmlncnF1ZXJ5KQoKc2Vzc2lvbkluZm8oKQpgYGAKCmBgYHtyfQojIFN3aXRjaCB0byB5b3VyIG93biBHQ1AgcHJvamVjdCBJRApwcm9qZWN0X2lkIDwtICI8UFJPSkVDVF9JRD4iICAKYGBgCgoKYGBge3J9CnRoZW1lX3NldCh0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZT05LCBiYXNlX2ZhbWlseT0iU291cmNlIFNhbnMgUHJvIikgKwogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseT0iU291cmNlIFNhbnMgUHJvIEJvbGQiLCBtYXJnaW49bWFyZ2luKHQgPSAtMC4xLCBiID0gMC4xLCB1bml0PSdjbScpLCBzaXplPTEyKSwKICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KCksCiAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dCgpLAogICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYW1pbHk9IlJvYm90byBDb25kZW5zZWQiKSwKICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFtaWx5PSJSb2JvdG8gQ29uZGVuc2VkIiksCiAgICAgICAgICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5PSJTb3VyY2UgU2FucyBQcm8gU2VtaWJvbGQiLCBjb2xvcj0iIzk2OTY5NiIsIHNpemU9OCksCiAgICAgICAgICAgICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChjb2xvcj0iIzk2OTY5NiIpLAogICAgICAgICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoKSwKICAgICAgICAgICAgICAgICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMC4yNSwgdW5pdD0nY20nKSkpCmBgYAoKIyBFREEKCiMjIFNGTyDihpIgU0VBIEZsaWdodCBEdXJhdGlvbgoKYGBge3J9CnF1ZXJ5IDwtICIKI3N0YW5kYXJkU1FMClNFTEVDVCBZZWFyLCBNb250aCwgbnVtX2ZsaWdodHMsCnRpbWVfcVtPRkZTRVQoNSldIEFTIHFfNSwKdGltZV9xW09GRlNFVCgyNSldIEFTIHFfMjUsCnRpbWVfcVtPRkZTRVQoNTApXSBBUyBxXzUwLAp0aW1lX3FbT0ZGU0VUKDc1KV0gQVMgcV83NSwKdGltZV9xW09GRlNFVCg5NSldIEFTIHFfOTUKRlJPTSAoClNFTEVDVCBZZWFyLCBNb250aCwKICBDT1VOVCgqKSBhcyBudW1fZmxpZ2h0cywKICBBUFBST1hfUVVBTlRJTEVTKEFjdHVhbEVsYXBzZWRUaW1lLCAxMDApIEFTIHRpbWVfcQpGUk9NIGBmaC1iaWdxdWVyeS5mbGlnaHRzLm9udGltZV8yMDE5MDhgCldIRVJFIE9yaWdpbiA9ICdTRk8nCkFORCBEZXN0ID0gJ1NFQScKQU5EIEZsaWdodERhdGVfeWVhciA+ICcyMDEwLTAxLTAxJwpHUk9VUCBCWSBZZWFyLCBNb250aAopCk9SREVSIEJZIFllYXIsIE1vbnRoCiIKCmRmIDwtIGJxX3Byb2plY3RfcXVlcnkocHJvamVjdF9pZCwgcXVlcnkpICU+JSBicV90YWJsZV9kb3dubG9hZCgpCgojIGdncGxvdDIgbGlrZXMgYSBkYXRlIGZvciB0aW1lc2VyaWVzCmRmX3RmIDwtIGRmICU+JQogICAgICAgICAgbXV0YXRlKGRhdGUgPSB5bWQocGFzdGUoWWVhciwgTW9udGgsICIxIikpLAogICAgICAgICAgICAgICAgIHllYXJfZmFjdG9yID0gZmFjdG9yKGFzLm51bWVyaWMoWWVhcikpKQoKZGZfdGYgJT4lIGhlYWQoMTApCmBgYAoKTkI6IEFzIG9mIGdncGxvdCAzLjIuMCwgeW91IG11c3QgaGF2ZSB0aGUgYGdyb3VwYCBhZXN0aGV0aWMgZm9yIGJveHBsb3RzIG1hbnVhbGx5IHNwZWNpZnlpbmcgdGhlIGJvdW5kcy4gKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS81NzE5MjcyNykKCmBgYHtyfQpwbG90IDwtCiAgZ2dwbG90KGRmX3RmLAogICAgICAgICBhZXMoCiAgICAgICAgICAgeCA9IGRhdGUsCiAgICAgICAgICAgeW1pbiA9IHFfNSwKICAgICAgICAgICBsb3dlciA9IHFfMjUsCiAgICAgICAgICAgbWlkZGxlID0gcV81MCwKICAgICAgICAgICB1cHBlciA9IHFfNzUsCiAgICAgICAgICAgeW1heCA9IHFfOTUsCiAgICAgICAgICAgZ3JvdXAgPSBkYXRlLAogICAgICAgICAgIGZpbGwgPSB5ZWFyX2ZhY3RvcgogICAgICAgICApKSArCiAgZ2VvbV9ib3hwbG90KHN0YXQgPSAiaWRlbnRpdHkiLCBzaXplPTAuMykgKwogIHNjYWxlX2ZpbGxfaHVlKGw9NTAsIGd1aWRlPUYpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAnMSB5ZWFyJywgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHByZXR0eV9icmVha3MoNikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEZsaWdodCBUaW1lcyBvZiBGbGlnaHRzIEZyb20gU0ZPIOKGkiBTRUEsIGJ5IE1vbnRoIiwKICAgIHN1YnRpdGxlID0gInZpYSBVUyBEb1QuIEJveCBib3VuZHMgYXJlIDI1dGgvNzV0aCBxdWFudGlsZXMsIHdoaXNrZXJzIGFyZSA1dGgvOTV0aCBxdWFudGlsZXMuIiwKICAgIHkgPSAnVG90YWwgRWxhcHNlZCBGbGlnaHQgVGltZSAoTWludXRlcyknLAogICAgZmlsbCA9ICcnLAogICAgY2FwdGlvbiA9ICdNYXggV29vbGYg4oCUIG1pbmltYXhpci5jb20nCiAgKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKQoKZ2dzYXZlKCdzZm9fc2VhX2ZsaWdodF9kdXJhdGlvbi5wbmcnLAogICAgICAgcGxvdCwKICAgICAgIHdpZHRoID0gNiwKICAgICAgIGhlaWdodCA9IDQpCmBgYAoKIVtdKHNmb19zZWFfZmxpZ2h0X2R1cmF0aW9uLnBuZykKCkFsdGVybmF0ZSBhcHByb2FjaCB1c2luZyByaWJib25zIChub3QgdXNlZCBpbiBmaW5hbCBibG9nIHBvc3Qgc2luY2UgaGFyZGVyIHRvIHZpc3VhbGx5IHBhcnNlLCBidXQgcHJlc2VudCBoZXJlIGZvciBwb3N0ZXJpdHkpOgoKYGBge3J9CnBsb3QgPC0KICBnZ3Bsb3QoZGZfdGYsCiAgICAgICAgIGFlcygKICAgICAgICAgICB4ID0gZGF0ZSwKICAgICAgICAgICAjZ3JvdXAgPSAiYWxsIiwKICAgICAgICAgICBjb2xvciA9IHllYXJfZmFjdG9yLAogICAgICAgICAgIGZpbGwgPSB5ZWFyX2ZhY3RvcgogICAgICAgICApKSArCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBxXzUsIHltYXggPSBxXzk1KSwgYWxwaGE9MC4zLCBzaXplPTAsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBxXzI1LCB5bWF4ID0gcV83NSksIGFscGhhPTAuMywgc2l6ZT0wLCBzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fbGluZShhZXMoeSA9IHFfNTApLCBzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX2NvbG9yX2h1ZShsPTUwLCBndWlkZT1GKSArCiAgc2NhbGVfZmlsbF9odWUobD01MCwgZ3VpZGU9RikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICcxIHllYXInLCBkYXRlX2xhYmVscyA9ICIlWSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gcHJldHR5X2JyZWFrcyg2KSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgRmxpZ2h0IFRpbWVzIG9mIEFpcmxpbmUgRmxpZ2h0cyBGcm9tIFNGTyDihpIgU0VBLCBieSBNb250aCIsCiAgICBzdWJ0aXRsZSA9ICJ2aWEgVVMgRG9ULiBCb3ggYm91bmRzIGFyZSAyNXRoLzc1dGggcXVhbnRpbGVzLCB3aGlza2VycyBhcmUgNXRoLzk1dGggcXVhbnRpbGVzIiwKICAgIHkgPSAnVG90YWwgRWxhcHNlZCBGbGlnaHQgVGltZSAoTWludXRlcyknLAogICAgZmlsbCA9ICcnLAogICAgY29sb3IgPSAnJywKICAgIGNhcHRpb24gPSAnTWF4IFdvb2xmIOKAlCBtaW5pbWF4aXIuY29tJwogICkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCmdnc2F2ZSgnc2ZvX3NlYV9mbGlnaHRfZHVyYXRpb25fcmliYm9uLnBuZycsCiAgICAgICBwbG90LAogICAgICAgd2lkdGggPSA2LAogICAgICAgaGVpZ2h0ID0gNCkKYGBgCgohW10oc2ZvX3NlYV9mbGlnaHRfZHVyYXRpb25fcmliYm9uLnBuZykKCiMjIFNGTyDihpIgSkZLIERpc3RyaWJ1dGlvbgoKYGBge3J9CnF1ZXJ5IDwtICIKI3N0YW5kYXJkU1FMClNFTEVDVCBZZWFyLCBNb250aCwgbnVtX2ZsaWdodHMsCnRpbWVfcVtPRkZTRVQoNSldIEFTIHFfNSwKdGltZV9xW09GRlNFVCgyNSldIEFTIHFfMjUsCnRpbWVfcVtPRkZTRVQoNTApXSBBUyBxXzUwLAp0aW1lX3FbT0ZGU0VUKDc1KV0gQVMgcV83NSwKdGltZV9xW09GRlNFVCg5NSldIEFTIHFfOTUKRlJPTSAoClNFTEVDVCBZZWFyLCBNb250aCwKICBDT1VOVCgqKSBhcyBudW1fZmxpZ2h0cywKICBBUFBST1hfUVVBTlRJTEVTKEFjdHVhbEVsYXBzZWRUaW1lLCAxMDApIEFTIHRpbWVfcQpGUk9NIGBmaC1iaWdxdWVyeS5mbGlnaHRzLm9udGltZV8yMDE5MDhgCldIRVJFIE9yaWdpbiA9ICdTRk8nCkFORCBEZXN0ID0gJ0pGSycKQU5EIEZsaWdodERhdGVfeWVhciA+ICcyMDEwLTAxLTAxJwpHUk9VUCBCWSBZZWFyLCBNb250aAopCk9SREVSIEJZIFllYXIsIE1vbnRoCiIKCmRmIDwtIGJxX3Byb2plY3RfcXVlcnkocHJvamVjdF9pZCwgcXVlcnkpICU+JSBicV90YWJsZV9kb3dubG9hZCgpCgpkZl90ZiA8LSBkZiAlPiUKICAgICAgICAgIG11dGF0ZShkYXRlID0geW1kKHBhc3RlKFllYXIsIE1vbnRoLCAiMSIpKSwKICAgICAgICAgICAgICAgICB5ZWFyX2ZhY3RvciA9IGZhY3Rvcihhcy5udW1lcmljKFllYXIpKSkKCmRmX3RmICU+JSBoZWFkKDEwKQpgYGAKCmBgYHtyfQpwbG90IDwtCiAgZ2dwbG90KGRmX3RmLAogICAgICAgICBhZXMoCiAgICAgICAgICAgeCA9IGRhdGUsCiAgICAgICAgICAgeW1pbiA9IHFfNSwKICAgICAgICAgICBsb3dlciA9IHFfMjUsCiAgICAgICAgICAgbWlkZGxlID0gcV81MCwKICAgICAgICAgICB1cHBlciA9IHFfNzUsCiAgICAgICAgICAgeW1heCA9IHFfOTUsCiAgICAgICAgICAgZ3JvdXAgPSBkYXRlLAogICAgICAgICAgIGZpbGwgPSB5ZWFyX2ZhY3RvcgogICAgICAgICApKSArCiAgZ2VvbV9ib3hwbG90KHN0YXQgPSAiaWRlbnRpdHkiLCBzaXplPTAuMykgKwogIHNjYWxlX2ZpbGxfaHVlKGw9NTAsIGd1aWRlPUYsIGguc3RhcnQ9MTgwLCBkaXJlY3Rpb249MSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICcxIHllYXInLCBkYXRlX2xhYmVscyA9ICIlWSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gcHJldHR5X2JyZWFrcyg2KSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgRmxpZ2h0IFRpbWVzIG9mIEZsaWdodHMgRnJvbSBTRk8g4oaSIEpGSywgYnkgTW9udGgiLAogICAgc3VidGl0bGUgPSAidmlhIFVTIERvVC4gQm94IGJvdW5kcyBhcmUgMjV0aC83NXRoIHF1YW50aWxlcywgd2hpc2tlcnMgYXJlIDV0aC85NXRoIHF1YW50aWxlcy4iLAogICAgeSA9ICdUb3RhbCBFbGFwc2VkIEZsaWdodCBUaW1lIChNaW51dGVzKScsCiAgICBmaWxsID0gJycsCiAgICBjYXB0aW9uID0gJ01heCBXb29sZiDigJQgbWluaW1heGlyLmNvbScKICApICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoJ3Nmb19qZmtfZmxpZ2h0X2R1cmF0aW9uLnBuZycsCiAgICAgICBwbG90LAogICAgICAgd2lkdGggPSA2LAogICAgICAgaGVpZ2h0ID0gNCkKYGBgCgohW10oc2ZvX2pma19mbGlnaHRfZHVyYXRpb24ucG5nKQoKIyMgSkZLIOKGkiBTRk8gRmxpZ2h0IFRpbWUgRGlzdHJpYnV0aW9uCgpgYGB7cn0KcXVlcnkgPC0gIgojc3RhbmRhcmRTUUwKU0VMRUNUIFllYXIsIE1vbnRoLCBudW1fZmxpZ2h0cywKdGltZV9xW09GRlNFVCg1KV0gQVMgcV81LAp0aW1lX3FbT0ZGU0VUKDI1KV0gQVMgcV8yNSwKdGltZV9xW09GRlNFVCg1MCldIEFTIHFfNTAsCnRpbWVfcVtPRkZTRVQoNzUpXSBBUyBxXzc1LAp0aW1lX3FbT0ZGU0VUKDk1KV0gQVMgcV85NQpGUk9NICgKU0VMRUNUIFllYXIsIE1vbnRoLAogIENPVU5UKCopIGFzIG51bV9mbGlnaHRzLAogIEFQUFJPWF9RVUFOVElMRVMoQWN0dWFsRWxhcHNlZFRpbWUsIDEwMCkgQVMgdGltZV9xCkZST00gYGZoLWJpZ3F1ZXJ5LmZsaWdodHMub250aW1lXzIwMTkwOGAKV0hFUkUgT3JpZ2luID0gJ0pGSycKQU5EIERlc3QgPSAnU0ZPJwpBTkQgRmxpZ2h0RGF0ZV95ZWFyID4gJzIwMTAtMDEtMDEnCkdST1VQIEJZIFllYXIsIE1vbnRoCikKT1JERVIgQlkgWWVhciwgTW9udGgKIgoKZGYgPC0gYnFfcHJvamVjdF9xdWVyeShwcm9qZWN0X2lkLCBxdWVyeSkgJT4lIGJxX3RhYmxlX2Rvd25sb2FkKCkKCmRmX3RmIDwtIGRmICU+JQogICAgICAgICAgbXV0YXRlKGRhdGUgPSB5bWQocGFzdGUoWWVhciwgTW9udGgsICIxIikpLAogICAgICAgICAgICAgICAgIHllYXJfZmFjdG9yID0gZmFjdG9yKGFzLm51bWVyaWMoWWVhcikpKQoKZGZfdGYgJT4lIGhlYWQoMTApCmBgYAoKCgpgYGB7cn0KcGxvdCA8LQogIGdncGxvdChkZl90ZiwKICAgICAgICAgYWVzKAogICAgICAgICAgIHggPSBkYXRlLAogICAgICAgICAgIHltaW4gPSBxXzUsCiAgICAgICAgICAgbG93ZXIgPSBxXzI1LAogICAgICAgICAgIG1pZGRsZSA9IHFfNTAsCiAgICAgICAgICAgdXBwZXIgPSBxXzc1LAogICAgICAgICAgIHltYXggPSBxXzk1LAogICAgICAgICAgIGdyb3VwID0gZGF0ZSwKICAgICAgICAgICBmaWxsID0geWVhcl9mYWN0b3IKICAgICAgICAgKSkgKwogIGdlb21fYm94cGxvdChzdGF0ID0gImlkZW50aXR5Iiwgc2l6ZT0wLjMpICsKICBzY2FsZV9maWxsX2h1ZShsPTUwLCBndWlkZT1GLCBoLnN0YXJ0PTE4MCwgZGlyZWN0aW9uPS0xKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gJzEgeWVhcicsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBwcmV0dHlfYnJlYWtzKDYpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBGbGlnaHQgVGltZXMgb2YgRmxpZ2h0cyBGcm9tIEpGSyDihpIgU0ZPLCBieSBNb250aCIsCiAgICBzdWJ0aXRsZSA9ICJ2aWEgVVMgRG9ULiBCb3ggYm91bmRzIGFyZSAyNXRoLzc1dGggcXVhbnRpbGVzLCB3aGlza2VycyBhcmUgNXRoLzk1dGggcXVhbnRpbGVzLiIsCiAgICB5ID0gJ1RvdGFsIEVsYXBzZWQgRmxpZ2h0IFRpbWUgKE1pbnV0ZXMpJywKICAgIGZpbGwgPSAnJywKICAgIGNhcHRpb24gPSAnTWF4IFdvb2xmIOKAlCBtaW5pbWF4aXIuY29tJwogICkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCmdnc2F2ZSgnamZrX3Nmb19mbGlnaHRfZHVyYXRpb24ucG5nJywKICAgICAgIHBsb3QsCiAgICAgICB3aWR0aCA9IDYsCiAgICAgICBoZWlnaHQgPSA0KQpgYGAKCiFbXShqZmtfc2ZvX2ZsaWdodF9kdXJhdGlvbi5wbmcpCgojIyBTRk8g4oaSIEpGSyBGbGlnaHQgU3BlZWQKCmBgYHtyfQpxdWVyeSA8LSAiI3N0YW5kYXJkU1FMClNFTEVDVCBZZWFyLCBNb250aCwgbnVtX2ZsaWdodHMsCnRpbWVfcVtPRkZTRVQoNSldIEFTIHFfNSwKdGltZV9xW09GRlNFVCgyNSldIEFTIHFfMjUsCnRpbWVfcVtPRkZTRVQoNTApXSBBUyBxXzUwLAp0aW1lX3FbT0ZGU0VUKDc1KV0gQVMgcV83NSwKdGltZV9xW09GRlNFVCg5NSldIEFTIHFfOTUKRlJPTSAoClNFTEVDVCBZZWFyLCBNb250aCwKICBDT1VOVCgqKSBhcyBudW1fZmxpZ2h0cywKICBBUFBST1hfUVVBTlRJTEVTKERpc3RhbmNlLyhBaXJUaW1lLzYwKSwgMTAwKSBBUyB0aW1lX3EKRlJPTSBgZmgtYmlncXVlcnkuZmxpZ2h0cy5vbnRpbWVfMjAxOTA4YApXSEVSRSBPcmlnaW4gPSAnU0ZPJwpBTkQgRGVzdCA9ICdKRksnCkFORCBGbGlnaHREYXRlX3llYXIgPiAnMjAxMC0wMS0wMScKR1JPVVAgQlkgMSwgMgopCk9SREVSIEJZIFllYXIsIE1vbnRoIgoKZGYgPC0gYnFfcHJvamVjdF9xdWVyeShwcm9qZWN0X2lkLCBxdWVyeSkgJT4lIGJxX3RhYmxlX2Rvd25sb2FkKCkKCmRmX3RmIDwtIGRmICU+JQogICAgICAgICAgbXV0YXRlKGRhdGUgPSB5bWQocGFzdGUoWWVhciwgTW9udGgsICIxIikpLAogICAgICAgICAgICAgICAgIHllYXJfZmFjdG9yID0gZmFjdG9yKGFzLm51bWVyaWMoWWVhcikpKQoKZGZfdGYgJT4lIGhlYWQoMTApCmBgYAoKYGBge3J9CnBsb3QgPC0KICBnZ3Bsb3QoZGZfdGYsCiAgICAgICAgIGFlcygKICAgICAgICAgICB4ID0gZGF0ZSwKICAgICAgICAgICB5bWluID0gcV81LAogICAgICAgICAgIGxvd2VyID0gcV8yNSwKICAgICAgICAgICBtaWRkbGUgPSBxXzUwLAogICAgICAgICAgIHVwcGVyID0gcV83NSwKICAgICAgICAgICB5bWF4ID0gcV85NSwKICAgICAgICAgICBncm91cCA9IGRhdGUsCiAgICAgICAgICAgZmlsbCA9IHllYXJfZmFjdG9yCiAgICAgICAgICkpICsKICBnZW9tX2JveHBsb3Qoc3RhdCA9ICJpZGVudGl0eSIsIHNpemU9MC4zKSArCiAgc2NhbGVfZmlsbF9odWUobD01MCwgZ3VpZGU9RiwgaC5zdGFydD0xODAsIGRpcmVjdGlvbj0xKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gJzEgeWVhcicsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBwcmV0dHlfYnJlYWtzKDYpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBGbGlnaHQgU3BlZWRzIG9mIEZsaWdodHMgRnJvbSBTRk8g4oaSIEpGSywgYnkgTW9udGgiLAogICAgc3VidGl0bGUgPSAidmlhIFVTIERvVC4gQm94IGJvdW5kcyBhcmUgMjV0aC83NXRoIHF1YW50aWxlcywgd2hpc2tlcnMgYXJlIDV0aC85NXRoIHF1YW50aWxlcy4iLAogICAgeSA9ICdBdmVyYWdlIFBsYW5lIEZsaWdodCBTcGVlZCAoTWlsZXMgUGVyIEhvdXIpJywKICAgIGZpbGwgPSAnJywKICAgIGNhcHRpb24gPSAnTWF4IFdvb2xmIOKAlCBtaW5pbWF4aXIuY29tJwogICkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCmdnc2F2ZSgnc2ZvX2pma19mbGlnaHRfc3BlZWQucG5nJywKICAgICAgIHBsb3QsCiAgICAgICB3aWR0aCA9IDYsCiAgICAgICBoZWlnaHQgPSA0KQpgYGAKCiFbXShzZm9famZrX2ZsaWdodF9zcGVlZC5wbmcpCgojIyBKRksg4oaSIFNGTyBGbGlnaHQgU3BlZWQKCmBgYHtyfQpxdWVyeSA8LSAiI3N0YW5kYXJkU1FMClNFTEVDVCBZZWFyLCBNb250aCwgbnVtX2ZsaWdodHMsCnRpbWVfcVtPRkZTRVQoNSldIEFTIHFfNSwKdGltZV9xW09GRlNFVCgyNSldIEFTIHFfMjUsCnRpbWVfcVtPRkZTRVQoNTApXSBBUyBxXzUwLAp0aW1lX3FbT0ZGU0VUKDc1KV0gQVMgcV83NSwKdGltZV9xW09GRlNFVCg5NSldIEFTIHFfOTUKRlJPTSAoClNFTEVDVCBZZWFyLCBNb250aCwKICBDT1VOVCgqKSBhcyBudW1fZmxpZ2h0cywKICBBUFBST1hfUVVBTlRJTEVTKERpc3RhbmNlLyhBaXJUaW1lLzYwKSwgMTAwKSBBUyB0aW1lX3EKRlJPTSBgZmgtYmlncXVlcnkuZmxpZ2h0cy5vbnRpbWVfMjAxOTA4YApXSEVSRSBPcmlnaW4gPSAnSkZLJwpBTkQgRGVzdCA9ICdTRk8nCkFORCBGbGlnaHREYXRlX3llYXIgPiAnMjAxMC0wMS0wMScKR1JPVVAgQlkgMSwgMgopCk9SREVSIEJZIFllYXIsIE1vbnRoIgoKZGYgPC0gYnFfcHJvamVjdF9xdWVyeShwcm9qZWN0X2lkLCBxdWVyeSkgJT4lIGJxX3RhYmxlX2Rvd25sb2FkKCkKCmRmX3RmIDwtIGRmICU+JQogICAgICAgICAgbXV0YXRlKGRhdGUgPSB5bWQocGFzdGUoWWVhciwgTW9udGgsICIxIikpLAogICAgICAgICAgICAgICAgIHllYXJfZmFjdG9yID0gZmFjdG9yKGFzLm51bWVyaWMoWWVhcikpKQoKZGZfdGYgJT4lIGhlYWQoMTApCmBgYAoKYGBge3J9CnBsb3QgPC0KICBnZ3Bsb3QoZGZfdGYsCiAgICAgICAgIGFlcygKICAgICAgICAgICB4ID0gZGF0ZSwKICAgICAgICAgICB5bWluID0gcV81LAogICAgICAgICAgIGxvd2VyID0gcV8yNSwKICAgICAgICAgICBtaWRkbGUgPSBxXzUwLAogICAgICAgICAgIHVwcGVyID0gcV83NSwKICAgICAgICAgICB5bWF4ID0gcV85NSwKICAgICAgICAgICBncm91cCA9IGRhdGUsCiAgICAgICAgICAgZmlsbCA9IHllYXJfZmFjdG9yCiAgICAgICAgICkpICsKICBnZW9tX2JveHBsb3Qoc3RhdCA9ICJpZGVudGl0eSIsIHNpemU9MC4zKSArCiAgc2NhbGVfZmlsbF9odWUobD01MCwgZ3VpZGU9RiwgaC5zdGFydD0xODAsIGRpcmVjdGlvbj0tMSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICcxIHllYXInLCBkYXRlX2xhYmVscyA9ICIlWSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gcHJldHR5X2JyZWFrcyg2KSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgRmxpZ2h0IFNwZWVkcyBvZiBGbGlnaHRzIEZyb20gSkZLIOKGkiBTRk8sIGJ5IE1vbnRoIiwKICAgIHN1YnRpdGxlID0gInZpYSBVUyBEb1QuIEJveCBib3VuZHMgYXJlIDI1dGgvNzV0aCBxdWFudGlsZXMsIHdoaXNrZXJzIGFyZSA1dGgvOTV0aCBxdWFudGlsZXMuIiwKICAgIHkgPSAnQXZlcmFnZSBQbGFuZSBGbGlnaHQgU3BlZWQgKE1pbGVzIFBlciBIb3VyKScsCiAgICBmaWxsID0gJycsCiAgICBjYXB0aW9uID0gJ01heCBXb29sZiDigJQgbWluaW1heGlyLmNvbScKICApICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoJ2pma19zZm9fZmxpZ2h0X3NwZWVkLnBuZycsCiAgICAgICBwbG90LAogICAgICAgd2lkdGggPSA2LAogICAgICAgaGVpZ2h0ID0gNCkKYGBgCgohW10oamZrX3Nmb19mbGlnaHRfc3BlZWQucG5nKQoKIyMgU0ZPIOKGkiBKRksgRGVwYXJ0dXJlIERlbGF5CgpgYGB7cn0KcXVlcnkgPC0gIiNzdGFuZGFyZFNRTApTRUxFQ1QgWWVhciwgTW9udGgsIG51bV9mbGlnaHRzLAp0aW1lX3FbT0ZGU0VUKDUpXSBBUyBxXzUsCnRpbWVfcVtPRkZTRVQoMjUpXSBBUyBxXzI1LAp0aW1lX3FbT0ZGU0VUKDUwKV0gQVMgcV81MCwKdGltZV9xW09GRlNFVCg3NSldIEFTIHFfNzUsCnRpbWVfcVtPRkZTRVQoOTUpXSBBUyBxXzk1CkZST00gKApTRUxFQ1QgWWVhciwgTW9udGgsCiAgQ09VTlQoKikgYXMgbnVtX2ZsaWdodHMsCiAgQVBQUk9YX1FVQU5USUxFUyhEZXBEZWxheSwgMTAwKSBBUyB0aW1lX3EKRlJPTSBgZmgtYmlncXVlcnkuZmxpZ2h0cy5vbnRpbWVfMjAxOTA4YApXSEVSRSBPcmlnaW4gPSAnU0ZPJwpBTkQgRGVzdCA9ICdKRksnCkFORCBGbGlnaHREYXRlX3llYXIgPiAnMjAxMC0wMS0wMScKR1JPVVAgQlkgMSwgMgopCk9SREVSIEJZIFllYXIsIE1vbnRoIgoKZGYgPC0gYnFfcHJvamVjdF9xdWVyeShwcm9qZWN0X2lkLCBxdWVyeSkgJT4lIGJxX3RhYmxlX2Rvd25sb2FkKCkKCmRmX3RmIDwtIGRmICU+JQogICAgICAgICAgbXV0YXRlKGRhdGUgPSB5bWQocGFzdGUoWWVhciwgTW9udGgsICIxIikpLAogICAgICAgICAgICAgICAgIHllYXJfZmFjdG9yID0gZmFjdG9yKGFzLm51bWVyaWMoWWVhcikpKQoKZGZfdGYgJT4lIGhlYWQoMTApCmBgYAoKYGBge3J9CnBsb3QgPC0KICBnZ3Bsb3QoZGZfdGYsCiAgICAgICAgIGFlcygKICAgICAgICAgICB4ID0gZGF0ZSwKICAgICAgICAgICB5bWluID0gcV81LAogICAgICAgICAgIGxvd2VyID0gcV8yNSwKICAgICAgICAgICBtaWRkbGUgPSBxXzUwLAogICAgICAgICAgIHVwcGVyID0gcV83NSwKICAgICAgICAgICB5bWF4ID0gcV85NSwKICAgICAgICAgICBncm91cCA9IGRhdGUsCiAgICAgICAgICAgZmlsbCA9IHllYXJfZmFjdG9yCiAgICAgICAgICkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MCwgbGluZXR5cGU9J2Rhc2hlZCcsIGNvbG9yPSJncmF5IikgKwogIGdlb21fYm94cGxvdChzdGF0ID0gImlkZW50aXR5Iiwgc2l6ZT0wLjMpICsKICBzY2FsZV9maWxsX2h1ZShsPTUwLCBndWlkZT1GLCBoLnN0YXJ0PTE4MCwgZGlyZWN0aW9uPTEpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAnMSB5ZWFyJywgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHByZXR0eV9icmVha3MoNikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIERlcGFydHVyZSBEZWxheXMgb2YgRmxpZ2h0cyBGcm9tIFNGTyDihpIgSkZLLCBieSBNb250aCIsCiAgICBzdWJ0aXRsZSA9ICJ2aWEgVVMgRG9ULiBCb3ggYm91bmRzIGFyZSAyNXRoLzc1dGggcXVhbnRpbGVzLCB3aGlza2VycyBhcmUgNXRoLzk1dGggcXVhbnRpbGVzLiIsCiAgICB5ID0gJ0RlcGFydHVyZSBEZWxheSAoTWludXRlcyknLAogICAgZmlsbCA9ICcnLAogICAgY2FwdGlvbiA9ICdNYXggV29vbGYg4oCUIG1pbmltYXhpci5jb20nCiAgKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKQoKZ2dzYXZlKCdzZm9famZrX2RlcGFydHVyZV9kZWxheS5wbmcnLAogICAgICAgcGxvdCwKICAgICAgIHdpZHRoID0gNiwKICAgICAgIGhlaWdodCA9IDQpCmBgYAoKIVtdKHNmb19qZmtfZGVwYXJ0dXJlX2RlbGF5LnBuZykKClJlbW92ZSB3aGlza2VycyBzaW5jZSBpdCBkaXN0b3J0cyB0aGUgZ3JhcGggdW5oZWxwZnVsbHkuCgpgYGB7cn0KcGxvdCA8LQogIGdncGxvdChkZl90ZiwKICAgICAgICAgYWVzKAogICAgICAgICAgIHggPSBkYXRlLAogICAgICAgICAgIHltaW4gPSBxXzI1LAogICAgICAgICAgIGxvd2VyID0gcV8yNSwKICAgICAgICAgICBtaWRkbGUgPSBxXzUwLAogICAgICAgICAgIHVwcGVyID0gcV83NSwKICAgICAgICAgICB5bWF4ID0gcV83NSwKICAgICAgICAgICBncm91cCA9IGRhdGUsCiAgICAgICAgICAgZmlsbCA9IHllYXJfZmFjdG9yCiAgICAgICAgICkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MCwgbGluZXR5cGU9J2Rhc2hlZCcsIGNvbG9yPSJncmF5IikgKwogIGdlb21fYm94cGxvdChzdGF0ID0gImlkZW50aXR5Iiwgc2l6ZT0wLjMpICsKICBzY2FsZV9maWxsX2h1ZShsPTUwLCBndWlkZT1GLCBoLnN0YXJ0PTE4MCwgZGlyZWN0aW9uPTEpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAnMSB5ZWFyJywgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHByZXR0eV9icmVha3MoNikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIERlcGFydHVyZSBEZWxheXMgb2YgRmxpZ2h0cyBGcm9tIFNGTyDihpIgSkZLLCBieSBNb250aCIsCiAgICBzdWJ0aXRsZSA9ICJ2aWEgVVMgRG9ULiBCb3ggYm91bmRzIGFyZSAyNXRoLzc1dGggcXVhbnRpbGVzLiIsCiAgICB5ID0gJ0RlcGFydHVyZSBEZWxheSAoTWludXRlcyknLAogICAgZmlsbCA9ICcnLAogICAgY2FwdGlvbiA9ICdNYXggV29vbGYg4oCUIG1pbmltYXhpci5jb20nCiAgKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKQoKZ2dzYXZlKCdzZm9famZrX2RlcGFydHVyZV9kZWxheV9ub3doaXNrZXJzLnBuZycsCiAgICAgICBwbG90LAogICAgICAgd2lkdGggPSA2LAogICAgICAgaGVpZ2h0ID0gNCkKYGBgCgohW10oc2ZvX2pma19kZXBhcnR1cmVfZGVsYXlfbm93aGlza2Vycy5wbmcpCgojIyBKRksg4oaSIFNGTyBEZXBhcnR1cmUgRGVsYXkKCmBgYHtyfQpxdWVyeSA8LSAiI3N0YW5kYXJkU1FMClNFTEVDVCBZZWFyLCBNb250aCwgbnVtX2ZsaWdodHMsCnRpbWVfcVtPRkZTRVQoNSldIEFTIHFfNSwKdGltZV9xW09GRlNFVCgyNSldIEFTIHFfMjUsCnRpbWVfcVtPRkZTRVQoNTApXSBBUyBxXzUwLAp0aW1lX3FbT0ZGU0VUKDc1KV0gQVMgcV83NSwKdGltZV9xW09GRlNFVCg5NSldIEFTIHFfOTUKRlJPTSAoClNFTEVDVCBZZWFyLCBNb250aCwKICBDT1VOVCgqKSBhcyBudW1fZmxpZ2h0cywKICBBUFBST1hfUVVBTlRJTEVTKERlcERlbGF5LCAxMDApIEFTIHRpbWVfcQpGUk9NIGBmaC1iaWdxdWVyeS5mbGlnaHRzLm9udGltZV8yMDE5MDhgCldIRVJFIE9yaWdpbiA9ICdKRksnCkFORCBEZXN0ID0gJ1NGTycKQU5EIEZsaWdodERhdGVfeWVhciA+ICcyMDEwLTAxLTAxJwpHUk9VUCBCWSAxLCAyCikKT1JERVIgQlkgWWVhciwgTW9udGgiCgpkZiA8LSBicV9wcm9qZWN0X3F1ZXJ5KHByb2plY3RfaWQsIHF1ZXJ5KSAlPiUgYnFfdGFibGVfZG93bmxvYWQoKQoKZGZfdGYgPC0gZGYgJT4lCiAgICAgICAgICBtdXRhdGUoZGF0ZSA9IHltZChwYXN0ZShZZWFyLCBNb250aCwgIjEiKSksCiAgICAgICAgICAgICAgICAgeWVhcl9mYWN0b3IgPSBmYWN0b3IoYXMubnVtZXJpYyhZZWFyKSkpCgpkZl90ZiAlPiUgaGVhZCgxMCkKYGBgCgpgYGB7cn0KcGxvdCA8LQogIGdncGxvdChkZl90ZiwKICAgICAgICAgYWVzKAogICAgICAgICAgIHggPSBkYXRlLAogICAgICAgICAgIHltaW4gPSBxXzI1LAogICAgICAgICAgIGxvd2VyID0gcV8yNSwKICAgICAgICAgICBtaWRkbGUgPSBxXzUwLAogICAgICAgICAgIHVwcGVyID0gcV83NSwKICAgICAgICAgICB5bWF4ID0gcV83NSwKICAgICAgICAgICBncm91cCA9IGRhdGUsCiAgICAgICAgICAgZmlsbCA9IHllYXJfZmFjdG9yCiAgICAgICAgICkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MCwgbGluZXR5cGU9J2Rhc2hlZCcsIGNvbG9yPSJncmF5IikgKwogIGdlb21fYm94cGxvdChzdGF0ID0gImlkZW50aXR5Iiwgc2l6ZT0wLjMpICsKICBzY2FsZV9maWxsX2h1ZShsPTUwLCBndWlkZT1GLCBoLnN0YXJ0PTE4MCwgZGlyZWN0aW9uPS0xKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gJzEgeWVhcicsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBwcmV0dHlfYnJlYWtzKDYpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBEZXBhcnR1cmUgRGVsYXlzIG9mIEZsaWdodHMgRnJvbSBKRksg4oaSIFNGTywgYnkgTW9udGgiLAogICAgc3VidGl0bGUgPSAidmlhIFVTIERvVC4gQm94IGJvdW5kcyBhcmUgMjV0aC83NXRoIHF1YW50aWxlcy4iLAogICAgeSA9ICdEZXBhcnR1cmUgRGVsYXkgKE1pbnV0ZXMpJywKICAgIGZpbGwgPSAnJywKICAgIGNhcHRpb24gPSAnTWF4IFdvb2xmIOKAlCBtaW5pbWF4aXIuY29tJwogICkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCmdnc2F2ZSgnamZrX3Nmb19kZXBhcnR1cmVfZGVsYXlfbm93aGlza2Vycy5wbmcnLAogICAgICAgcGxvdCwKICAgICAgIHdpZHRoID0gNiwKICAgICAgIGhlaWdodCA9IDQpCmBgYAoKIVtdKGpma19zZm9fZGVwYXJ0dXJlX2RlbGF5X25vd2hpc2tlcnMucG5nKQoKIyBMSUNFTlNFCgpNSVQgTGljZW5zZQoKQ29weXJpZ2h0IChjKSAyMDE5IE1heCBXb29sZgoKUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weQpvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwgdG8gZGVhbAppbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzCnRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwKY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCmZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CgpUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbiBhbGwKY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4KClRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCklNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLApGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUKQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgpMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLApPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRQpTT0ZUV0FSRS4=