Map & Additional Data
Data yang digunakan terdiri dari dua bagian. Pertama data untuk map, yang diantaranya terdapat kolom geometry sebagai polygon. Data kedua adalah data berisi nilai yang akan ditampilkan. Kedua data tersebut di-join berdasarkan kolom yang sesuai. Dalam hal ini di-join berdasarkan kolom NAME_1 (data shp) dan Provinsi (data tambahan).
Map Data
Download data dengan format .shp dari web berikut. Pilih Indonesia untuk Country dan pilih Administrative areas untuk Subject. Klik OK dan Download, kemudian simpan file IDN_adm.zip dan extract pada suatu folder.
Buka https://mapshaper.org untuk membuat ukuran file .shp yang akan digunakan menjadi lebih kecil, sehingga lebih cepat ketika diimport ke R.
Upload file .shp dan file pendukung lainnya untuk level provinsi, yaitu IDN_adm1 (kecuali file .csv).
Pilih menu Simplify kemudian klik Apply.
Atur parameter yang ada. Semakin kecil nilainya maka semakin sederhana peta yang dibuat dan ukuran filenya pun semakin kecil.
Jika sudah selesai pengaturannya, kemudian export dalam format shapefile dan extract dalam sebuah folder. Sebaiknya jangan me-replace file .shp asli.
Additional Data
Untuk data tambahan yang akan ditampilkan dapat kita gunakan data dari BPS. Unduh data tersebut dalam format Excel file.
Agar lebih mudah, simpan dalam format .csv.
Mapping
library(sf)
library(plotly)
library(dplyr)
library(tidyr)
library(readr)
shp <- sf::read_sf("IDN_adm1.shp")
str(shp)
Classes ‘sf’, ‘tbl_df’, ‘tbl’ and 'data.frame': 34 obs. of 10 variables:
$ ID_0 : num 106 106 106 106 106 106 106 106 106 106 ...
$ ISO : chr "IDN" "IDN" "IDN" "IDN" ...
$ NAME_0 : chr "Indonesia" "Indonesia" "Indonesia" "Indonesia" ...
$ ID_1 : num 1 2 3 4 5 6 7 8 9 10 ...
$ NAME_1 : chr "Aceh" "Bali" "Bangka-Belitung" "Banten" ...
$ TYPE_1 : chr "Propinsi" "Propinsi" "Propinsi" "Propinsi" ...
$ ENGTYPE_1: chr "Autonomous Province" "Province" "Province" "Province" ...
$ NL_NAME_1: chr NA NA NA NA ...
$ VARNAME_1: chr "Achin|Atjeh|Nanggroe Aceh Darussalam" "Penida|Lembongan|Ceningan|Menjangan" "Babel|Kepulauan Bangka Belitung" NA ...
$ geometry :sfc_MULTIPOLYGON of length 34; first list element: List of 6
..$ :List of 1
.. ..$ : num [1:5, 1:2] 97.1 97.2 97.1 97.1 97.1 ...
..$ :List of 1
.. ..$ : num [1:7, 1:2] 97.2 97.3 97.4 97.3 97.3 ...
..$ :List of 1
.. ..$ : num [1:25, 1:2] 95.8 95.9 95.9 96 96 ...
..$ :List of 1
.. ..$ : num [1:100, 1:2] 96.2 96.2 96.1 96 95.9 ...
..$ :List of 1
.. ..$ : num [1:4, 1:2] 95.06 95.13 95.07 95.06 5.75 ...
..$ :List of 1
.. ..$ : num [1:6, 1:2] 95.2 95.3 95.4 95.3 95.3 ...
..- attr(*, "class")= chr "XY" "MULTIPOLYGON" "sfg"
- attr(*, "sf_column")= chr "geometry"
- attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA
..- attr(*, "names")= chr "ID_0" "ISO" "NAME_0" "ID_1" ...
Variabel NAME_1 adalah nama provinsi.
plot_ly(shp)
bps_file1 <- read_csv("bps-file1.csv", col_names = FALSE, skip = 3)
bps_file1 <- bps_file1 %>%
rename(Provinsi = X1,
LuasPanen = X2,
Produktivitas = X3,
Produksi = X4)
bps_file1 <- bps_file1 %>%
mutate(Provinsi = if_else(Provinsi == "DKI JAKARTA", "JAKARTA RAYA",
if_else(Provinsi == "DI YOGYAKARTA", "YOGYAKARTA",
if_else(Provinsi == "KEP. BANGKA BELITUNG", "BANGKA-BELITUNG",
if_else(Provinsi == "PAPUA BARAT", "IRIAN JAYA BARAT",
if_else(Provinsi == "KEP. RIAU", "KEPULAUAN RIAU",
Provinsi))))),
Provinsi = stringr::str_to_title(Provinsi))
head(bps_file1)
Join data shp dengan bps_file1 berdasarkan variabel NAME_1 = Provinsi
shp <- shp %>%
left_join(bps_file1, by = c("NAME_1" = "Provinsi"))
head(shp)
Simple feature collection with 6 features and 12 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 95.05889 ymin: -8.849167 xmax: 123.5241 ymax: 5.907781
epsg (SRID): 4326
proj4string: +proj=longlat +datum=WGS84 +no_defs
Basic Map
plot_ly(shp, color = ~LuasPanen, split = ~NAME_1,
text = ~paste("<b>", NAME_1, "</b><br>",
"<b>Luas Panen</b>:", LuasPanen, "(ha)"),
hoveron = "fills", hoverinfo = "text")
Hide Legend
plot_ly(shp, color = ~LuasPanen, split = ~NAME_1,
span = I(1), showlegend = FALSE,
text = ~paste("<b>", NAME_1, "</b><br>",
"<b>Luas Panen</b>:", LuasPanen, "(ha)"),
hoveron = "fills", hoverinfo = "text")
Modify Colorbar Title
plot_ly(shp, color = ~LuasPanen, split = ~NAME_1, span = I(1),
text = ~paste("<b>", NAME_1, "</b><br>",
"<b>Luas Panen</b>:", LuasPanen, "(ha)"),
hoveron = "fills", hoverinfo = "text", showlegend = FALSE) %>%
colorbar(title = "Luas Panen 2018")
Hide Colorbar
plot_ly(shp, color = ~LuasPanen, split = ~NAME_1, span = I(1),
text = ~paste("<b>", NAME_1, "</b><br>",
"<b>Luas Panen</b>:", LuasPanen, "(ha)"),
hoveron = "fills", hoverinfo = "text", showlegend = FALSE) %>%
colorbar(title = "Luas Panen 2018") %>%
hide_colorbar()
Hide Plotly Logo on Mode Bar
plot_ly(shp, color = ~LuasPanen, split = ~NAME_1, span = I(1),
text = ~paste("<b>", NAME_1, "</b><br>",
"<b>Luas Panen</b>:", LuasPanen, "(ha)"),
hoveron = "fills", hoverinfo = "text", showlegend = FALSE) %>%
colorbar(title = "Luas Panen 2018") %>%
hide_colorbar() %>%
config(displaylogo = FALSE)
Hide Entire Mode Bar
plot_ly(shp, color = ~LuasPanen, split = ~NAME_1, span = I(1),
text = ~paste("<b>", NAME_1, "</b><br>",
"<b>Luas Panen</b>:", LuasPanen, "(ha)"),
hoveron = "fills", hoverinfo = "text", showlegend = FALSE) %>%
colorbar(title = "Luas Panen 2018") %>%
hide_colorbar() %>%
config(displayModeBar = FALSE)
LS0tDQp0aXRsZTogIlBsb3RseSBTcGF0aWFsIFZpc3VhbGl6YXRpb24iDQphdXRob3I6ICJCeSBBZXAgSGlkYXlhdHVsb2giDQpkYXRlOiAiTGFzdCBVcGRhdGU6IGByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJWQgJWIgJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IHNwYWNlbGFiDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHRydWUNCi0tLQ0KDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpib2R5eyAvKiBOb3JtYWwgICovDQogICAgICBmb250LXNpemU6IDEycHg7DQogIH0NCnRkIHsgIC8qIFRhYmxlICAqLw0KICBmb250LXNpemU6IDEycHg7DQp9DQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMzhweDsNCiAgY29sb3I6IGxpZ2h0Ymx1ZTsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQpoMSB7IC8qIEhlYWRlciAxICovDQogIGZvbnQtc2l6ZTogMjRweDsNCiAgY29sb3I6IERhcmtCbHVlOw0KfQ0KaDIgeyAvKiBIZWFkZXIgMiAqLw0KICBmb250LXNpemU6IDIwcHg7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCn0NCmgzIHsgLyogSGVhZGVyIDMgKi8NCiAgZm9udC1zaXplOiAxNnB4Ow0KIyAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCn0NCmg0IHsgLyogSGVhZGVyIDQgKi8NCiAgZm9udC1zaXplOiAxNHB4Ow0KICBjb2xvcjogRGFya0JsdWU7DQp9DQpjb2RlLnJ7IC8qIENvZGUgYmxvY2sgKi8NCiAgICBmb250LXNpemU6IDEycHg7DQp9DQpwcmUgeyAvKiBDb2RlIGJsb2NrIC0gZGV0ZXJtaW5lcyBjb2RlIHNwYWNpbmcgYmV0d2VlbiBsaW5lcyAqLw0KICAgIGZvbnQtc2l6ZTogMTJweDsNCn0NCjwvc3R5bGU+DQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQoja25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA5LjUsIHJlc3VsdHMgPSAnaG9sZCcsIHdhcm5pbmcgPSBGQUxTRSwgZmlnLnNob3cgPSAnaG9sZCcsIG1lc3NhZ2UgPSBGQUxTRSkgDQpvcHRpb25zKHNjaXBlbiA9IDk5KQ0KYGBgDQoNCiMgT2JqZWN0aXZlDQoNClZpc3VhbGlzYXNpIGRhdGEgZGVuZ2FuIHBldGEgZGFyaSBkYXRhIHNoYXBlZmlsZSBkYW4gZGF0YSB0YW1iYWhhbi4NCg0KIyBNYXAgJiBBZGRpdGlvbmFsIERhdGENCg0KRGF0YSB5YW5nIGRpZ3VuYWthbiB0ZXJkaXJpIGRhcmkgZHVhIGJhZ2lhbi4gUGVydGFtYSBkYXRhIHVudHVrIG1hcCwgeWFuZyBkaWFudGFyYW55YSB0ZXJkYXBhdCBrb2xvbSBgZ2VvbWV0cnlgIHNlYmFnYWkgcG9seWdvbi4gRGF0YSBrZWR1YSBhZGFsYWggZGF0YSBiZXJpc2kgbmlsYWkgeWFuZyBha2FuIGRpdGFtcGlsa2FuLiBLZWR1YSBkYXRhIHRlcnNlYnV0IGRpLWpvaW4gYmVyZGFzYXJrYW4ga29sb20geWFuZyBzZXN1YWkuIERhbGFtIGhhbCBpbmkgZGktam9pbiBiZXJkYXNhcmthbiBrb2xvbSBgTkFNRV8xYCAoZGF0YSBzaHApIGRhbiBgUHJvdmluc2lgIChkYXRhIHRhbWJhaGFuKS4NCg0KIyMgTWFwIERhdGENCkRvd25sb2FkIGRhdGEgZGVuZ2FuIGZvcm1hdCAuc2hwIGRhcmkgW3dlYiBiZXJpa3V0XShodHRwczovL3d3dy5kaXZhLWdpcy5vcmcvZ2RhdGEpLiBQaWxpaCAqKkluZG9uZXNpYSoqIHVudHVrICpDb3VudHJ5KiBkYW4gcGlsaWggKipBZG1pbmlzdHJhdGl2ZSBhcmVhcyoqIHVudHVrICpTdWJqZWN0Ki4gS2xpayAqKk9LKiogZGFuICoqRG93bmxvYWQqKiwga2VtdWRpYW4gc2ltcGFuIGZpbGUgKklETl9hZG0uemlwKiBkYW4gZXh0cmFjdCBwYWRhIHN1YXR1IGZvbGRlci4NCg0KIVtEb3dubG9hZCBTaGFwZWZpbGVdKGRvd25sb2FkX3NocC5wbmcpDQoNCkJ1a2EgPGh0dHBzOi8vbWFwc2hhcGVyLm9yZz4gdW50dWsgbWVtYnVhdCB1a3VyYW4gZmlsZSAuc2hwIHlhbmcgYWthbiBkaWd1bmFrYW4gbWVuamFkaSBsZWJpaCBrZWNpbCwgc2VoaW5nZ2EgbGViaWggY2VwYXQga2V0aWthIGRpaW1wb3J0IGtlIFIuIA0KDQohW21hcHNoYXBlci5vcmddKG1hcHNoYXBlci5wbmcpDQoNClVwbG9hZCBmaWxlIC5zaHAgZGFuIGZpbGUgcGVuZHVrdW5nIGxhaW5ueWEgdW50dWsgbGV2ZWwgcHJvdmluc2ksIHlhaXR1IElETl9hZG0xIChrZWN1YWxpIGZpbGUgLmNzdikuDQoNCiFbVXBsb2FkIEZpbGVdKHVwbG9hZF9zaHAucG5nKQ0KDQohW1VwbG9hZCBGaWxlXSh1cGxvYWRfc2hwMi5wbmcpDQoNClBpbGloIG1lbnUgKipTaW1wbGlmeSoqIGtlbXVkaWFuIGtsaWsgKipBcHBseSoqLg0KDQohW1NpbXBsaWZ5XSh1cGxvYWRfc2hwMy5wbmcpDQoNCkF0dXIgcGFyYW1ldGVyIHlhbmcgYWRhLiBTZW1ha2luIGtlY2lsIG5pbGFpbnlhIG1ha2Egc2VtYWtpbiBzZWRlcmhhbmEgcGV0YSB5YW5nIGRpYnVhdCBkYW4gdWt1cmFuIGZpbGVueWEgcHVuIHNlbWFraW4ga2VjaWwuDQoNCiFbU2ltcGxpZnldKHNldF9zaHAucG5nKQ0KDQpKaWthIHN1ZGFoIHNlbGVzYWkgcGVuZ2F0dXJhbm55YSwga2VtdWRpYW4gZXhwb3J0IGRhbGFtIGZvcm1hdCBzaGFwZWZpbGUgZGFuIGV4dHJhY3QgZGFsYW0gc2VidWFoIGZvbGRlci4gU2ViYWlrbnlhIGphbmdhbiBtZS1yZXBsYWNlIGZpbGUgLnNocCBhc2xpLg0KDQohW1VwbG9hZCBGaWxlXShleHBvcnRfc2hwLnBuZykNCg0KDQojIyBBZGRpdGlvbmFsIERhdGENClVudHVrIGRhdGEgdGFtYmFoYW4geWFuZyBha2FuIGRpdGFtcGlsa2FuIGRhcGF0IGtpdGEgZ3VuYWthbiBbZGF0YSBkYXJpIEJQU10oaHR0cHM6Ly93d3cuYnBzLmdvLmlkL2R5bmFtaWN0YWJsZS8yMDE5LzA0LzE1LzE2MDgvbHVhcy1wYW5lbi1wcm9kdWtzaS1kYW4tcHJvZHVrdGl2aXRhcy1wYWRpLW1lbnVydXQtcHJvdmluc2ktMjAxOC5odG1sKS4gVW5kdWggZGF0YSB0ZXJzZWJ1dCBkYWxhbSBmb3JtYXQgRXhjZWwgZmlsZS4gDQoNCkFnYXIgbGViaWggbXVkYWgsIHNpbXBhbiBkYWxhbSBmb3JtYXQgLmNzdi4NCg0KIyBNYXBwaW5nDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHJlYWRyKQ0KYGBgDQoNCmBgYHtyfQ0Kc2hwIDwtIHNmOjpyZWFkX3NmKCJJRE5fYWRtMS5zaHAiKQ0Kc3RyKHNocCkNCmBgYA0KDQpWYXJpYWJlbCBgTkFNRV8xYCBhZGFsYWggbmFtYSBwcm92aW5zaS4NCg0KYGBge3IgZmlnLndpZHRoPTh9DQpwbG90X2x5KHNocCkNCmBgYA0KDQoNCmBgYHtyfQ0KYnBzX2ZpbGUxIDwtIHJlYWRfY3N2KCJicHMtZmlsZTEuY3N2IiwgY29sX25hbWVzID0gRkFMU0UsIHNraXAgPSAzKQ0KYnBzX2ZpbGUxIDwtIGJwc19maWxlMSAlPiUgDQogIHJlbmFtZShQcm92aW5zaSA9IFgxLA0KICAgICAgICAgTHVhc1BhbmVuID0gWDIsDQogICAgICAgICBQcm9kdWt0aXZpdGFzID0gWDMsDQogICAgICAgICBQcm9kdWtzaSA9IFg0KQ0KDQpicHNfZmlsZTEgPC0gYnBzX2ZpbGUxICU+JSANCiAgbXV0YXRlKFByb3ZpbnNpID0gaWZfZWxzZShQcm92aW5zaSA9PSAiREtJIEpBS0FSVEEiLCAiSkFLQVJUQSBSQVlBIiwgDQogICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoUHJvdmluc2kgPT0gIkRJIFlPR1lBS0FSVEEiLCAiWU9HWUFLQVJUQSIsDQogICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoUHJvdmluc2kgPT0gIktFUC4gQkFOR0tBIEJFTElUVU5HIiwgIkJBTkdLQS1CRUxJVFVORyIsDQogICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoUHJvdmluc2kgPT0gIlBBUFVBIEJBUkFUIiwgIklSSUFOIEpBWUEgQkFSQVQiLCANCiAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShQcm92aW5zaSA9PSAiS0VQLiBSSUFVIiwgIktFUFVMQVVBTiBSSUFVIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgUHJvdmluc2kpKSkpKSwNCiAgICAgICAgIFByb3ZpbnNpID0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKFByb3ZpbnNpKSkNCmhlYWQoYnBzX2ZpbGUxKQ0KYGBgDQoNCkpvaW4gZGF0YSBgc2hwYCBkZW5nYW4gYGJwc19maWxlMWAgYmVyZGFzYXJrYW4gdmFyaWFiZWwgYE5BTUVfMSA9IFByb3ZpbnNpYA0KDQpgYGB7cn0NCnNocCA8LSBzaHAgJT4lIA0KICBsZWZ0X2pvaW4oYnBzX2ZpbGUxLCBieSA9IGMoIk5BTUVfMSIgPSAiUHJvdmluc2kiKSkNCmhlYWQoc2hwKQ0KYGBgDQoNCiMjIEJhc2ljIE1hcA0KDQpgYGB7ciBmaWcud2lkdGg9OH0NCnBsb3RfbHkoc2hwLCBjb2xvciA9IH5MdWFzUGFuZW4sIHNwbGl0ID0gfk5BTUVfMSwNCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgiPGI+IiwgTkFNRV8xLCAiPC9iPjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICI8Yj5MdWFzIFBhbmVuPC9iPjoiLCBMdWFzUGFuZW4sICIoaGEpIiksDQogICAgICAgIGhvdmVyb24gPSAiZmlsbHMiLCBob3ZlcmluZm8gPSAidGV4dCIpDQpgYGANCg0KIyMgSGlkZSBMZWdlbmQNCg0KYGBge3IgZmlnLndpZHRoPTh9DQpwbG90X2x5KHNocCwgY29sb3IgPSB+THVhc1BhbmVuLCBzcGxpdCA9IH5OQU1FXzEsDQogICAgICAgIHNwYW4gPSBJKDEpLCBzaG93bGVnZW5kID0gRkFMU0UsDQogICAgICAgIHRleHQgPSB+cGFzdGUoIjxiPiIsIE5BTUVfMSwgIjwvYj48YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAiPGI+THVhcyBQYW5lbjwvYj46IiwgTHVhc1BhbmVuLCAiKGhhKSIpLA0KICAgICAgICBob3Zlcm9uID0gImZpbGxzIiwgaG92ZXJpbmZvID0gInRleHQiKQ0KYGBgDQoNCiMjIE1vZGlmeSBDb2xvcmJhciBUaXRsZQ0KYGBge3IgZmlnLndpZHRoPTh9DQpwbG90X2x5KHNocCwgY29sb3IgPSB+THVhc1BhbmVuLCBzcGxpdCA9IH5OQU1FXzEsIHNwYW4gPSBJKDEpLCANCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgiPGI+IiwgTkFNRV8xLCAiPC9iPjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICI8Yj5MdWFzIFBhbmVuPC9iPjoiLCBMdWFzUGFuZW4sICIoaGEpIiksDQogICAgICAgIGhvdmVyb24gPSAiZmlsbHMiLCBob3ZlcmluZm8gPSAidGV4dCIsIHNob3dsZWdlbmQgPSBGQUxTRSkgJT4lIA0KICBjb2xvcmJhcih0aXRsZSA9ICJMdWFzIFBhbmVuIDIwMTgiKQ0KYGBgDQoNCiMjIEhpZGUgQ29sb3JiYXINCg0KYGBge3IgZmlnLndpZHRoPTh9DQpwbG90X2x5KHNocCwgY29sb3IgPSB+THVhc1BhbmVuLCBzcGxpdCA9IH5OQU1FXzEsIHNwYW4gPSBJKDEpLCANCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgiPGI+IiwgTkFNRV8xLCAiPC9iPjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICI8Yj5MdWFzIFBhbmVuPC9iPjoiLCBMdWFzUGFuZW4sICIoaGEpIiksDQogICAgICAgIGhvdmVyb24gPSAiZmlsbHMiLCBob3ZlcmluZm8gPSAidGV4dCIsIHNob3dsZWdlbmQgPSBGQUxTRSkgJT4lIA0KICBjb2xvcmJhcih0aXRsZSA9ICJMdWFzIFBhbmVuIDIwMTgiKSAlPiUgDQogIGhpZGVfY29sb3JiYXIoKQ0KYGBgDQoNCiMjIEhpZGUgUGxvdGx5IExvZ28gb24gTW9kZSBCYXINCg0KYGBge3IgZmlnLndpZHRoPTh9DQpwbG90X2x5KHNocCwgY29sb3IgPSB+THVhc1BhbmVuLCBzcGxpdCA9IH5OQU1FXzEsIHNwYW4gPSBJKDEpLCANCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgiPGI+IiwgTkFNRV8xLCAiPC9iPjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICI8Yj5MdWFzIFBhbmVuPC9iPjoiLCBMdWFzUGFuZW4sICIoaGEpIiksDQogICAgICAgIGhvdmVyb24gPSAiZmlsbHMiLCBob3ZlcmluZm8gPSAidGV4dCIsIHNob3dsZWdlbmQgPSBGQUxTRSkgJT4lIA0KICBjb2xvcmJhcih0aXRsZSA9ICJMdWFzIFBhbmVuIDIwMTgiKSAlPiUgDQogIGhpZGVfY29sb3JiYXIoKSAlPiUgDQogIGNvbmZpZyhkaXNwbGF5bG9nbyA9IEZBTFNFKQ0KYGBgDQoNCiMjIEhpZGUgRW50aXJlIE1vZGUgQmFyDQoNCmBgYHtyIGZpZy53aWR0aD04fQ0KcGxvdF9seShzaHAsIGNvbG9yID0gfkx1YXNQYW5lbiwgc3BsaXQgPSB+TkFNRV8xLCBzcGFuID0gSSgxKSwgDQogICAgICAgIHRleHQgPSB+cGFzdGUoIjxiPiIsIE5BTUVfMSwgIjwvYj48YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAiPGI+THVhcyBQYW5lbjwvYj46IiwgTHVhc1BhbmVuLCAiKGhhKSIpLA0KICAgICAgICBob3Zlcm9uID0gImZpbGxzIiwgaG92ZXJpbmZvID0gInRleHQiLCBzaG93bGVnZW5kID0gRkFMU0UpICU+JSANCiAgY29sb3JiYXIodGl0bGUgPSAiTHVhcyBQYW5lbiAyMDE4IikgJT4lIA0KICBoaWRlX2NvbG9yYmFyKCkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCmBgYA0KDQojIENvbmNsdXNpb24NCg0KR3VuYWthbiBmaWxlIC5zaHAgeWFuZyBtdWRhaCBkaWRhcGF0a2FuIGRpIGludGVybmV0IHVudHVrIHZpc3VhbGlzYXNpIHNwYXNpYWwgYmVydXBhIG1hcC4gSW1wb3J0IGZpbGUgLnNocCBkYW4gYmViZXJhcGEgZmlsZSBwZW5kdWt1bmdueWEgZGVuZ2FuIGZ1bmdzaSBgcmVhZF9zZigpYCBkYXJpIHBhY2thZ2UgYHNmYC4gS2VtdWRpYW4gZ3VuYWthbiBmdW5nc2kgYHBsb3RfbHkoKWAgZGFyaSBwYWNrYWdlIGBwbG90bHlgIGRhbiB1bnR1ayBtZW5hbXBpbGthbiB2aXN1YWxpc2FzaSBtYXAgZGFuIGRhdGEgdGFtYmFoYW5ueWEuDQoNCmBgYHtyIHJ1bmFsbH0NCg0KYGBgDQoNCg==