
By Mongina Dolphine
October 29 2019
R was initially developed for statistical computations. With the advancement of R-Spatial libraries such as rgdal,which is R’s interface to Geospatial Abstraction Library enabling R to handle a broader range of spatial data formats,it has now become possible for spatial data analysis and visualization, by use of functionalities within rgdal such as readOGR().
Some pros and cons of R include:
| 1.Free |
No official support |
| 2.Reproducible |
Steep learning curve (No user interface) |
| 3.Online help |
Slow with large datasets |
This tutorial will attempt to scratch the surface of the mapping capabilities of R-Spatial by use of three main mapping libraries.The choice of a particular library is dependent on intended use of the map, accuracy required and variable to be mapped.
1. Mapview
Has functionalities that quickly and conveniently create interactive visualisations of spatial data with or without background maps. Attributes of displayed features are fully queryable via pop-up windows.[Source:https://cran.r-project.org/web/packages/mapview/index.html].
The full documentation is available from
mapview.pdf.
1.1.RColorBrewer
It creates nice looking color palettes especially for thematic maps.The South Africa consumer price index data,available from South Africa Data Portal, represents sequential, diverging and qualitative variables, a perfect use case for this example.
1.2.Sequential Palettes
Are suited to order data that progress from low to high. Lightness steps dominate the look of these schemes with light colors for low data values to dark colors for high values. This can easily be reversed.
Map 1:Sequential color palette showing the Alcohol Consumer Price Index in South Africa
1.3.Diverging Palettes
They put equal empasis on mid-range critical values and extremes at both ends of the data range. The critical class or break in the middle of the legend is emphasised with light colors and low and high extrems are emphasised with dark colors that have contrasting hues.
Map 2:Diverging color palette showing the opinion polls on whether the government should control social media
1.4.Qualitative Palettes
These do not imply magnitude differences between legend classes and hues are used to create the primary visual differences between classes. Qualitative schemes are best suited to representing nominal or categorical data.
Map 3:Qualitative color palette showing the provinces in South Africa
1.5.A bit of GIS Analysis
Now that we have seen the maping basics, we will perform some basic analysis.Suppose we want to visualise the province with the highest Consumer Price Index on alcohol, we will querry the CPI_Alcoho column. From the legend, we already know that the highest value is 115.8,below is the code that will give us the output.
Map 4:A simple filtration
2.Tmap
With tmap package, thematic maps can be generated with great flexibility. [Source:https://cran.r-project.org/web/packages/tmap/vignettes/tmap-getstarted.html.]
The major advantage of tmap over other mapping libraries lies in the tmap_animation functionality, which has the ability to create a gif or mpeg animation from a tmap plot.This is particularly useful when visualizing spatio-temporal variables or when there is need to visualize a series of maps side by side without having to switch in between layers.

Map 5:A series of Consumer Price Indices Maps
2.1.Animated maps with tmap_animation()
The tmap_animation functionality from library magick produces beautiful animated maps.Below is a chunk of code that demonstrates this.

monginadolphine
MonginaDolphine8
Dolphine Mongina
monginadolphine3@gmail.com
LS0tDQp0aXRsZTogPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+IDxiPiAqKjAwMTpNYXAgQ29kaW5nIHdpdGggUioqIDwvYj4gPC9wPg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCjxpbWcgc3JjPSJEYWxiZXJnIGxvZ292MS5wbmciIHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MHB4O3JpZ2h0OjBweDt3aWR0aDoyMDBweDsiLz4NCg0KPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+KioqQnkgTW9uZ2luYSBEb2xwaGluZSoqKjwvcD4NCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPioqKk9jdG9iZXIgMjkgMjAxOSoqKjwvcD4NClwNClIgd2FzIGluaXRpYWxseSBkZXZlbG9wZWQgZm9yIHN0YXRpc3RpY2FsIGNvbXB1dGF0aW9ucy4gV2l0aCB0aGUgYWR2YW5jZW1lbnQgb2YgUi1TcGF0aWFsIGxpYnJhcmllcyBzdWNoIGFzIFtyZ2RhbF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JnZGFsL2luZGV4Lmh0bWwpLHdoaWNoIGlzIFIncyBpbnRlcmZhY2UgdG8gR2Vvc3BhdGlhbCBBYnN0cmFjdGlvbiBMaWJyYXJ5IGVuYWJsaW5nIFIgdG8gaGFuZGxlIGEgYnJvYWRlciByYW5nZSBvZiBzcGF0aWFsIGRhdGEgZm9ybWF0cyxpdCBoYXMgbm93IGJlY29tZSBwb3NzaWJsZSBmb3Igc3BhdGlhbCBkYXRhIGFuYWx5c2lzIGFuZCB2aXN1YWxpemF0aW9uLCBieSB1c2Ugb2YgZnVuY3Rpb25hbGl0aWVzIHdpdGhpbiByZ2RhbCBzdWNoIGFzIFtyZWFkT0dSKCldKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9yZ2RhbC92ZXJzaW9ucy8xLjQtNi90b3BpY3MvcmVhZE9HUikuDQoNCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPjxmb250IHNpemU9IjQiPiAqKlNvbWUgcHJvcyBhbmQgY29ucyBvZiBSIGluY2x1ZGU6KiogDQo8L2ZvbnQ+PC9wPg0KDQoNClByb3MgICAgICAgICAgICB8IENvbnMNCi0tLS0gICAgICAgICAgICB8IC0tLS0tDQoxLkZyZWUgICAgICAgICAgfCBObyBvZmZpY2lhbCBzdXBwb3J0DQoyLlJlcHJvZHVjaWJsZSAgfCBTdGVlcCBsZWFybmluZyBjdXJ2ZSAoTm8gdXNlciBpbnRlcmZhY2UpDQozLk9ubGluZSBoZWxwICAgfCBTbG93IHdpdGggbGFyZ2UgZGF0YXNldHMNCg0KVGhpcyB0dXRvcmlhbCB3aWxsIGF0dGVtcHQgdG8gc2NyYXRjaCB0aGUgc3VyZmFjZSBvZiB0aGUgbWFwcGluZyBjYXBhYmlsaXRpZXMgb2YgUi1TcGF0aWFsIGJ5IHVzZSBvZiB0aHJlZSBtYWluIG1hcHBpbmcgbGlicmFyaWVzLlRoZSBjaG9pY2Ugb2YgYSBwYXJ0aWN1bGFyIGxpYnJhcnkgaXMgZGVwZW5kZW50IG9uICoqaW50ZW5kZWQgdXNlIG9mIHRoZSBtYXAqKiwgKiphY2N1cmFjeSByZXF1aXJlZCoqIGFuZCAqKnZhcmlhYmxlIHRvIGJlIG1hcHBlZCoqLlwNCg0KPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+PGZvbnQgc2l6ZT0iNSI+ICoqMS4gTWFwdmlldyoqIA0KPC9mb250PjwvcD4NCkhhcyBmdW5jdGlvbmFsaXRpZXMgdGhhdCBxdWlja2x5IGFuZCBjb252ZW5pZW50bHkgY3JlYXRlIGludGVyYWN0aXZlIHZpc3VhbGlzYXRpb25zIG9mIHNwYXRpYWwgZGF0YSB3aXRoIG9yIHdpdGhvdXQgYmFja2dyb3VuZCBtYXBzLiBBdHRyaWJ1dGVzIG9mIGRpc3BsYXllZCBmZWF0dXJlcyBhcmUgZnVsbHkgcXVlcnlhYmxlIHZpYSBwb3AtdXAgd2luZG93cy5bU291cmNlOmh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYXB2aWV3L2luZGV4Lmh0bWxdLg0KDQpUaGUgZnVsbCBkb2N1bWVudGF0aW9uIGlzIGF2YWlsYWJsZSBmcm9tIFttYXB2aWV3LnBkZl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hcHZpZXcvbWFwdmlldy5wZGYpLlwNClwNCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPjxmb250IHNpemU9IjQiPiAqKjEuMS5SQ29sb3JCcmV3ZXIqKiANCjwvZm9udD48L3A+DQpJdCBjcmVhdGVzIG5pY2UgbG9va2luZyBjb2xvciBwYWxldHRlcyBlc3BlY2lhbGx5IGZvciB0aGVtYXRpYyBtYXBzLlRoZSBTb3V0aCBBZnJpY2EgY29uc3VtZXIgcHJpY2UgaW5kZXggZGF0YSxhdmFpbGFibGUgZnJvbSBbU291dGggQWZyaWNhIERhdGEgUG9ydGFsXShodHRwOi8vc291dGhhZnJpY2Eub3BlbmRhdGFmb3JhZnJpY2Eub3JnL3VzZXIvZG93bmxvYWRhdHRhY2htZW50P2lkPTIxOTQ0MCksIHJlcHJlc2VudHMgc2VxdWVudGlhbCwgZGl2ZXJnaW5nIGFuZCBxdWFsaXRhdGl2ZSB2YXJpYWJsZXMsIGEgcGVyZmVjdCB1c2UgY2FzZSBmb3IgdGhpcyBleGFtcGxlLg0KDQoNCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPjxmb250IHNpemU9IjQiPiAqKjEuMi5TZXF1ZW50aWFsIFBhbGV0dGVzKiogDQo8L2ZvbnQ+PC9wPg0KQXJlIHN1aXRlZCB0byBvcmRlciBkYXRhIHRoYXQgcHJvZ3Jlc3MgZnJvbSBsb3cgdG8gaGlnaC4gTGlnaHRuZXNzIHN0ZXBzIGRvbWluYXRlIHRoZSBsb29rIG9mIHRoZXNlIHNjaGVtZXMgd2l0aCBsaWdodCBjb2xvcnMgZm9yIGxvdyBkYXRhIHZhbHVlcyB0byBkYXJrIGNvbG9ycyBmb3IgaGlnaCB2YWx1ZXMuIFRoaXMgY2FuIGVhc2lseSBiZSByZXZlcnNlZC4NCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoIm1hcHZpZXciKSAjbWFwdmlldyBpbnN0YWxsYXRpb24NCiM/bWFwdmlldygpICNkaXNwbGF5cyB0aGUgc3ludGF4DQpsaWJyYXJ5KHJnZGFsKQ0KbGlicmFyeShtYXB2aWV3KQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpTb3V0aF9BZnJpY2FfQ1BJIDwtIHJlYWRPR1IoInphX2NwaTIuc2hwIikgI2xvYWQgdGhlIHNoYXBlZmlsZQ0KI1NvdXRoX0FmcmljYV9DUEkkQ1BJX0FsY29obyA+Pj4gU2VxdWVudGlhbCBDb2xvciBQYWxldHRlDQpwYWxzZXEgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJQdXJwbGVzIikpICNTZXF1ZW50aWFsIGNvbG9yIHBhbGV0dGUNCm1hcHZpZXcoU291dGhfQWZyaWNhX0NQSSxhbHBoYS5yZWdpb25zID0gMSxsYXllci5uYW1lPSJBbGNvaG9sIENvbnN1bWVyIFByaWNlIEluZGV4IiwgDQogICAgICAgIHpjb2wgPSAiQ1BJX0FsY29obyIsY29sLnJlZ2lvbnMgPSBwYWxzZXEsbGVnZW5kID0gVFJVRSxsYXllcnMuY29udHJvbC5wb3MgPSAidG9wcmlnaHQiKSANCiANCmBgYA0KDQpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMH0NCm1hcHZpZXcoU291dGhfQWZyaWNhX0NQSSxhbHBoYS5yZWdpb25zID0gMSxsYXllci5uYW1lPSJBbGNvaG9sIENvbnN1bWVyIFByaWNlIEluZGV4IiwgDQogICAgICAgIHpjb2wgPSAiQ1BJX0FsY29obyIsY29sLnJlZ2lvbnMgPSBwYWxzZXEsbGVnZW5kID0gVFJVRSxsYXllcnMuY29udHJvbC5wb3MgPSAidG9wcmlnaHQiKSAjVmlzdWFsaXplcyB0aGUgcHJvdmluY2VzDQpgYGANCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPjxmb250IHNpemU9IjIiPiAqTWFwIDE6U2VxdWVudGlhbCBjb2xvciBwYWxldHRlIHNob3dpbmcgdGhlIEFsY29ob2wgQ29uc3VtZXIgUHJpY2UgSW5kZXggaW4gU291dGggQWZyaWNhKiANCjwvZm9udD48L3A+DQoNCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPjxmb250IHNpemU9IjQiPiAqKjEuMy5EaXZlcmdpbmcgUGFsZXR0ZXMqKiANCjwvZm9udD48L3A+DQpUaGV5IHB1dCBlcXVhbCBlbXBhc2lzIG9uIG1pZC1yYW5nZSBjcml0aWNhbCB2YWx1ZXMgYW5kIGV4dHJlbWVzIGF0IGJvdGggZW5kcyBvZiB0aGUgZGF0YSByYW5nZS4gVGhlIGNyaXRpY2FsIGNsYXNzIG9yIGJyZWFrIGluIHRoZSBtaWRkbGUgb2YgdGhlIGxlZ2VuZCBpcyBlbXBoYXNpc2VkIHdpdGggbGlnaHQgY29sb3JzIGFuZCBsb3cgYW5kIGhpZ2ggZXh0cmVtcyBhcmUgZW1waGFzaXNlZCB3aXRoIGRhcmsgY29sb3JzIHRoYXQgaGF2ZSBjb250cmFzdGluZyBodWVzLg0KDQpgYGB7cn0NCiMjU291dGhfQWZyaWNhX0NQSSRkaXZzYV9PcGluID4+PiBEaXZlcmdpbmcgUGFsZXR0ZQ0KcGFsZHZnIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiV2hpdGUiLCJSZWQiLCAiQmx1ZSIpKSNkaXZlcmdpbmcgcGFsZXR0ZXMNCm1hcHZpZXcoU291dGhfQWZyaWNhX0NQSSxhbHBoYS5yZWdpb25zID0gMSxsYXllci5uYW1lPSJHb3Zlcm5tZW50IHNob3VsZCBjb250cm9sIHNvY2lhbCBtZWRpYSIsIHpjb2wgPSAiZGl2c2FfT3BpbiIsY29sLnJlZ2lvbnM9cGFsZHZnKSAjVmlzdWFsaXplcyB0aGUgT3BpbmlvbiBwb2xscw0KYGBgDQoNCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQ0KbWFwdmlldyhTb3V0aF9BZnJpY2FfQ1BJLGFscGhhLnJlZ2lvbnMgPSAxLGxheWVyLm5hbWU9IkdvdmVybm1lbnQgc2hvdWxkIGNvbnRyb2wgc29jaWFsIG1lZGlhIiwgemNvbCA9ICJkaXZzYV9PcGluIixjb2wucmVnaW9ucz1wYWxkdmcpDQpgYGANCg0KPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+PGZvbnQgc2l6ZT0iMiI+ICpNYXAgMjpEaXZlcmdpbmcgY29sb3IgcGFsZXR0ZSBzaG93aW5nIHRoZSBvcGluaW9uIHBvbGxzIG9uIHdoZXRoZXIgdGhlIGdvdmVybm1lbnQgc2hvdWxkIGNvbnRyb2wgc29jaWFsIG1lZGlhKiANCjwvZm9udD48L3A+DQo8cCBzdHlsZSA9ICJjb2xvcjojODcxOTQ2Ij48Zm9udCBzaXplPSI0Ij4gKioxLjQuUXVhbGl0YXRpdmUgUGFsZXR0ZXMqKiANCjwvZm9udD48L3A+DQpUaGVzZSBkbyBub3QgaW1wbHkgbWFnbml0dWRlIGRpZmZlcmVuY2VzIGJldHdlZW4gbGVnZW5kIGNsYXNzZXMgYW5kIGh1ZXMgYXJlIHVzZWQgdG8gY3JlYXRlIHRoZSBwcmltYXJ5IHZpc3VhbCBkaWZmZXJlbmNlcyBiZXR3ZWVuIGNsYXNzZXMuIFF1YWxpdGF0aXZlIHNjaGVtZXMgYXJlIGJlc3Qgc3VpdGVkIHRvIHJlcHJlc2VudGluZyBub21pbmFsIG9yIGNhdGVnb3JpY2FsIGRhdGEuDQpgYGB7cn0NCiMjU291dGhfQWZyaWNhX0NQSSRWQVJOQU1FXzEgPj4+IFF1YWxpdGF0aXZlIENvbG9yIFBhbGV0dGUNCnBhbHF1YWwgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDMsICJEYXJrMiIpKSAjcXVhbGl0YXRpdmUgcGFsZXR0ZXMNCm1hcHZpZXcoU291dGhfQWZyaWNhX0NQSSxhbHBoYS5yZWdpb25zID0gMSxsYXllci5uYW1lPSJTb3V0aCBBZnJpY2FuIFByb3ZpbmNlcyIsIA0KICAgICAgICB6Y29sID0gIk5BTUVfMSIsY29sLnJlZ2lvbnMgPSBwYWxxdWFsICkgI1Zpc3VhbGl6ZXMgdGhlIHByb3ZpbmNlcw0KYGBgDQoNCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQ0KbWFwdmlldyhTb3V0aF9BZnJpY2FfQ1BJLGFscGhhLnJlZ2lvbnMgPSAxLGxheWVyLm5hbWU9IlNvdXRoIEFmcmljYW4gUHJvdmluY2VzIiwgDQogICAgICAgIHpjb2wgPSAiTkFNRV8xIixjb2wucmVnaW9ucyA9IHBhbHF1YWwgKSAjVmlzdWFsaXplcyB0aGUgcHJvdmluY2VzDQpgYGANCg0KPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+PGZvbnQgc2l6ZT0iMiI+ICpNYXAgMzpRdWFsaXRhdGl2ZSBjb2xvciBwYWxldHRlIHNob3dpbmcgdGhlIHByb3ZpbmNlcyBpbiBTb3V0aCBBZnJpY2EqIA0KPC9mb250PjwvcD4NCg0KPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+PGZvbnQgc2l6ZT0iNCI+ICoqMS41LkEgYml0IG9mIEdJUyBBbmFseXNpcyoqIA0KPC9mb250PjwvcD4NCk5vdyB0aGF0IHdlIGhhdmUgc2VlbiB0aGUgbWFwaW5nIGJhc2ljcywgd2Ugd2lsbCBwZXJmb3JtIHNvbWUgYmFzaWMgYW5hbHlzaXMuU3VwcG9zZSB3ZSB3YW50IHRvIHZpc3VhbGlzZSB0aGUgcHJvdmluY2Ugd2l0aCB0aGUgaGlnaGVzdCBDb25zdW1lciBQcmljZSBJbmRleCBvbiBhbGNvaG9sLCB3ZSB3aWxsIHF1ZXJyeSB0aGUgKipDUElfQWxjb2hvKiogY29sdW1uLiBGcm9tIHRoZSBsZWdlbmQsIHdlIGFscmVhZHkga25vdyB0aGF0IHRoZSBoaWdoZXN0IHZhbHVlIGlzICoqMTE1LjgqKixiZWxvdyBpcyB0aGUgY29kZSB0aGF0IHdpbGwgZ2l2ZSB1cyB0aGUgb3V0cHV0Lg0KDQpgYGB7cn0NCm1hcHZpZXcoU291dGhfQWZyaWNhX0NQSVtTb3V0aF9BZnJpY2FfQ1BJJENQSV9BbGNvaG8gPT0gMTE1LjgsXSwNCiAgICAgICAgY29sLnJlZ2lvbnM9IlJlZCIsIGxheWVyLm5hbWUgPSAiSGlnaGVzdCBDb25zdW1lciBQcmljZSBJbmRleCBvbiBBbGNvaG9sIikgKyANCiAgICNmaWx0cmF0aW9uDQpgYGANCg0KYGBge3IgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTB9DQogIA0KbWFwdmlldyhTb3V0aF9BZnJpY2FfQ1BJLGFscGhhLnJlZ2lvbnMgPSAwLGxheWVyLm5hbWU9IlNvdXRoIEFmcmljYSIsbGVnZW5kID0gRkFMU0UpICttYXB2aWV3KFNvdXRoX0FmcmljYV9DUElbU291dGhfQWZyaWNhX0NQSSRDUElfQWxjb2hvID09IDExNS44LF0sDQogICAgICAgIGNvbC5yZWdpb25zPSJSZWQiLCBsYXllci5uYW1lID0gIkhpZ2hlc3QgQ29uc3VtZXIgUHJpY2UgSW5kZXggb24gQWxjb2hvbCIpICNmaWx0cmF0aW9uDQpgYGANCg0KPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+PGZvbnQgc2l6ZT0iMiI+ICpNYXAgNDpBIHNpbXBsZSBmaWx0cmF0aW9uKiANCjwvZm9udD48L3A+DQoNCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPjxmb250IHNpemU9IjUiPiAqKjIuVG1hcCoqIA0KPC9mb250PjwvcD4NCg0KV2l0aCB0bWFwIHBhY2thZ2UsIHRoZW1hdGljIG1hcHMgY2FuIGJlIGdlbmVyYXRlZCB3aXRoIGdyZWF0IGZsZXhpYmlsaXR5LiBbU291cmNlOmh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy90bWFwL3ZpZ25ldHRlcy90bWFwLWdldHN0YXJ0ZWQuaHRtbC5dXA0KVGhlIG1ham9yIGFkdmFudGFnZSBvZiB0bWFwIG92ZXIgb3RoZXIgbWFwcGluZyBsaWJyYXJpZXMgbGllcyBpbiB0aGUgW3RtYXBfYW5pbWF0aW9uIGZ1bmN0aW9uYWxpdHldKA0KaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3RtYXAvdmVyc2lvbnMvMi4zL3RvcGljcy90bWFwX2FuaW1hdGlvbg0KKSwgd2hpY2ggaGFzIHRoZSBhYmlsaXR5IHRvIGNyZWF0ZSBhIGdpZiBvciBtcGVnIGFuaW1hdGlvbiBmcm9tIGEgdG1hcCBwbG90LlRoaXMgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHZpc3VhbGl6aW5nICoqc3BhdGlvLXRlbXBvcmFsIHZhcmlhYmxlcyoqIG9yIHdoZW4gdGhlcmUgaXMgbmVlZCB0byB2aXN1YWxpemUgYSBzZXJpZXMgb2YgbWFwcyBzaWRlIGJ5IHNpZGUgd2l0aG91dCBoYXZpbmcgdG8gc3dpdGNoIGluIGJldHdlZW4gbGF5ZXJzLg0KDQpgYGB7cn0NCm1hMSA9IHRtX3NoYXBlKFNvdXRoX0FmcmljYV9DUEkpICsgdG1fZmlsbChjb2wgPSAiQ1BJX0FsY29obyIsIHBhbGV0dGUgPSAiUmVkcyINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdGl0bGUgPSAiQWxjb2hvbCBDLlAuSSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmlzLnBvcnRyYWl0ID0gRkFMU0UpDQoNCm1hMiA9IHRtX3NoYXBlKFNvdXRoX0FmcmljYV9DUEkpICsgdG1fZmlsbChjb2wgPSAiQ1BJX0hlYWx0aCIsIHBhbGV0dGUgPSAiR3JlZW5zIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0aXRsZSA9ICJIZWFsdGggQy5QLkkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5pcy5wb3J0cmFpdCA9IEZBTFNFKQ0KDQptYTMgPSB0bV9zaGFwZShTb3V0aF9BZnJpY2FfQ1BJKSArIHRtX2ZpbGwoY29sID0gIkNQSV9Db25zdW0iLCBwYWxldHRlID0gIkJsdWVzIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0aXRsZSA9ICJDb25zdW1wdGlvbiBDLlAuSSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmlzLnBvcnRyYWl0ID0gRkFMU0UpDQoNCg0KYGBgDQoNCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwLCBtZXNzYWdlPUZBTFNFfQ0KdG1hcF9hcnJhbmdlKCBtYTEsbWEyLCBtYTMpDQpgYGANCg0KPHAgc3R5bGUgPSAiY29sb3I6Izg3MTk0NiI+PGZvbnQgc2l6ZT0iMiI+ICpNYXAgNTpBIHNlcmllcyBvZiBDb25zdW1lciBQcmljZSBJbmRpY2VzIE1hcHMqIDwvZm9udD48L3A+DQoNCjxwIHN0eWxlID0gImNvbG9yOiM4NzE5NDYiPjxmb250IHNpemU9IjQiPiAqKjIuMS5BbmltYXRlZCBtYXBzIHdpdGggdG1hcF9hbmltYXRpb24oKSoqIDwvZm9udD48L3A+DQpUaGUgdG1hcF9hbmltYXRpb24gZnVuY3Rpb25hbGl0eSBmcm9tIFtsaWJyYXJ5IG1hZ2lja10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ2ljay92aWduZXR0ZXMvaW50cm8uaHRtbCkgcHJvZHVjZXMgYmVhdXRpZnVsIGFuaW1hdGVkIG1hcHMuQmVsb3cgaXMgYSBjaHVuayBvZiBjb2RlIHRoYXQgZGVtb25zdHJhdGVzIHRoaXMuDQoNCmBgYHtyfQ0Kc2FfYW5pbSA8LSANCiAgdG1fc2hhcGUoU291dGhfQWZyaWNhX0NQSSkgKw0KICAgdG1fcG9seWdvbnMoYWxwaGEgPSAwKSArDQogIHRtX3NoYXBlKFNvdXRoX0FmcmljYV9DUEkpICsNCiAgIHRtX3BvbHlnb25zKCJDUElfQ29uc3VtIiwgcGFsZXR0ZSA9ICItUmVkcyIsdGl0bGUgPSAiQ29uc3VtZXIgUHJpY2UgSW5kZXgiKSArDQogICB0bV9mYWNldHMoYWxvbmcgPSAiTkFNRV8xIiwgZnJlZS5jb29yZHMgPSBGQUxTRSkgDQp0bWFwX2FuaW1hdGlvbih1cmJfYW5pbSwgZmlsZW5hbWUgPSAiU0EuZ2lmIix3aWR0aCA9IDEyMDAsZGVsYXkgPSAyNTApDQpgYGANCg0KIVtdKEM6L1VzZXJzL2xvY2FuaW50ZXJuMi9EZXNrdG9wL1dvcmsvTE9DQU4gVFJBSU5JTkcvU0EuZ2lmKXt3aWR0aD01NTBweH0NCg0KDQoNCg0KDQo8Y2VudGVyPiFbXShDOi9Vc2Vycy9sb2NhbmludGVybjIvRGVza3RvcC9Xb3JrL0xPQ0FOIFRSQUlOSU5HL3R3aXR0ZXIucG5nKXt3aWR0aD05MHB4fVttb25naW5hZG9scGhpbmVdKGh0dHBzOi8vdHdpdHRlci5jb20vTW9uZ2luYURvbHBoaW5lKSANCg0KPGNlbnRlcj4hW10oQzovVXNlcnMvbG9jYW5pbnRlcm4yL0Rlc2t0b3AvV29yay9MT0NBTiBUUkFJTklORy9naXQucG5nKXt3aWR0aD00NXB4fVtNb25naW5hRG9scGhpbmU4XShodHRwczovL2dpdGh1Yi5jb20vTW9uZ2luYURvbHBoaW5lOCkNCg0KPGNlbnRlcj4hW10oQzovVXNlcnMvbG9jYW5pbnRlcm4yL0Rlc2t0b3AvV29yay9MT0NBTiBUUkFJTklORy9saW5rZWRpbi1sb2dvLnBuZyl7d2lkdGg9OTBweH1bRG9scGhpbmUgTW9uZ2luYV0oaHR0cHM6Ly93d3cubGlua2VkaW4uY29tL2luL2RvbHBoaW5lLW1vbmdpbmEtOTAzMzE0MTM1LykNCg0KPGNlbnRlcj4hW10oQzovVXNlcnMvbG9jYW5pbnRlcm4yL0Rlc2t0b3AvV29yay9MT0NBTiBUUkFJTklORy9HbWFpbF9JY29uLnBuZyl7d2lkdGg9NDNweH0gbW9uZ2luYWRvbHBoaW5lM0BnbWFpbC5jb20NCg0KDQoNCg==