Skip to content

Instantly share code, notes, and snippets.

@BibMartin
Created May 15, 2020 17:56
Show Gist options
  • Save BibMartin/e7da03789f175efe43cd484fc789591a to your computer and use it in GitHub Desktop.
Save BibMartin/e7da03789f175efe43cd484fc789591a to your computer and use it in GitHub Desktop.
Three tiles systems : Squares, Triangles, Hexagons ; with a hash system to encode them
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import folium\n",
"import tiles\n",
"\n",
"lat, lng = (45.8381, 3.1205)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Squares"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<tiles.SquareTile at 0x1fe1a867f98>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sq = tiles.SquareTile.from_lat_lng(lat, lng, 15)\n",
"sq"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(45.84028105450087, 3.1256103515625)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sq.central_point()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1683178484"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sq.to_hash()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'15/16668/11678'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sq.to_string()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(15, 16668, 11678)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sq.to_tuple()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[45.84410779560204, 3.1201171875],\n",
" [45.84410779560204, 3.131103515625],\n",
" [45.83645405018771, 3.131103515625],\n",
" [45.83645405018771, 3.1201171875]]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sq.vertex()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'type': 'Polygon',\n",
" 'coordinates': [[[3.1201171875, 45.84410779560204],\n",
" [3.131103515625, 45.84410779560204],\n",
" [3.131103515625, 45.83645405018771],\n",
" [3.1201171875, 45.83645405018771]]]}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sq.to_geojson()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF9hMzVkOGZjNDM3ZDA0NTU5OTIzZWE0NzI5NTIxODRiMSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfYTM1ZDhmYzQzN2QwNDU1OTkyM2VhNDcyOTUyMTg0YjEiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwX2EzNWQ4ZmM0MzdkMDQ1NTk5MjNlYTQ3Mjk1MjE4NGIxID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwX2EzNWQ4ZmM0MzdkMDQ1NTk5MjNlYTQ3Mjk1MjE4NGIxIiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFswLCAwXSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDEsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl81MTk4OWRhYmRkNDA0NGIwYThlYmQ3NDhjY2ZiZTM0MCA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiRGF0YSBieSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSwgdW5kZXIgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9EYkxcdTAwM2MvYVx1MDAzZS4iLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTM1ZDhmYzQzN2QwNDU1OTkyM2VhNDcyOTUyMTg0YjEpOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fNWZiZmJjNDBlMmZjNDA5ZjlkYjRjMzFhYzg5ZjhjNWFfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzVkOGZjNDM3ZDA0NTU5OTIzZWE0NzI5NTIxODRiMS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl81ZmJmYmM0MGUyZmM0MDlmOWRiNGMzMWFjODlmOGM1YSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl81ZmJmYmM0MGUyZmM0MDlmOWRiNGMzMWFjODlmOGM1YV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1ZDhmYzQzN2QwNDU1OTkyM2VhNDcyOTUyMTg0YjEpOwogICAgICAgICAgICBnZW9fanNvbl81ZmJmYmM0MGUyZmM0MDlmOWRiNGMzMWFjODlmOGM1YS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEyMDExNzE4NzUsIDQ1Ljg0NDEwNzc5NTYwMjA0XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44NDQxMDc3OTU2MDIwNF0sIFszLjEzMTEwMzUxNTYyNSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xMjAxMTcxODc1LCA0NS44MzY0NTQwNTAxODc3MV1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFya2VyXzkwOWVlN2MxYWQ5YjRjNWU4OTY4ODU3NGM3OGZhNmE5ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbNDUuODM4MSwgMy4xMjA1XSwKICAgICAgICAgICAgICAgIHt9CiAgICAgICAgICAgICkuYWRkVG8obWFwX2EzNWQ4ZmM0MzdkMDQ1NTk5MjNlYTQ3Mjk1MjE4NGIxKTsKICAgICAgICAKICAgIAogICAgICAgICAgICBtYXBfYTM1ZDhmYzQzN2QwNDU1OTkyM2VhNDcyOTUyMTg0YjEuZml0Qm91bmRzKAogICAgICAgICAgICAgICAgW1s0NS44MzY0NTQwNTAxODc3MSwgMy4xMjAxMTcxODc1XSwgWzQ1Ljg0NDEwNzc5NTYwMjA0LCAzLjEzMTEwMzUxNTYyNV1dLAogICAgICAgICAgICAgICAge30KICAgICAgICAgICAgKTsKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x1fe1a878898>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m = folium.Map()\n",
"m.add_child(folium.GeoJson(sq.to_geojson()))\n",
"m.add_child(folium.Marker([lat, lng]))\n",
"m.fit_bounds(m.get_bounds())\n",
"m"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjIiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFswLCAwXSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDEsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl83YTE4MzFmMGM4OGM0M2YzOWQ4MjRiMGFmMjk4MTM3OSA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiRGF0YSBieSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSwgdW5kZXIgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9EYkxcdTAwM2MvYVx1MDAzZS4iLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fODg2YjBiODUyNzFmNDE4NzlmMTAxZjIxYjUxYThjNDZfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl84ODZiMGI4NTI3MWY0MTg3OWYxMDFmMjFiNTFhOGM0NiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl84ODZiMGI4NTI3MWY0MTg3OWYxMDFmMjFiNTFhOGM0Nl9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl84ODZiMGI4NTI3MWY0MTg3OWYxMDFmMjFiNTFhOGM0Ni5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEyMDExNzE4NzUsIDQ1Ljg0NDEwNzc5NTYwMjA0XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44NDQxMDc3OTU2MDIwNF0sIFszLjEzMTEwMzUxNTYyNSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xMjAxMTcxODc1LCA0NS44MzY0NTQwNTAxODc3MV1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzJiNTZjMzY4ZmU0ZjQ5YTlhNGVjMTc3ZWI1ODNjM2ZmX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fMmI1NmMzNjhmZTRmNDlhOWE0ZWMxNzdlYjU4M2MzZmYgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fMmI1NmMzNjhmZTRmNDlhOWE0ZWMxNzdlYjU4M2MzZmZfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fMmI1NmMzNjhmZTRmNDlhOWE0ZWMxNzdlYjU4M2MzZmYuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMjAxMTcxODc1LCA0NS44MzY0NTQwNTAxODc3MV0sIFszLjEzMTEwMzUxNTYyNSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgyODc5OTI1MTkyMTM0XSwgWzMuMTIwMTE3MTg3NSwgNDUuODI4Nzk5MjUxOTIxMzRdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl9hMjNkZGQyZGU1YzQ0ZjVhYjUzMDU0ZTA5NGMzOGJjNl9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uX2EyM2RkZDJkZTVjNDRmNWFiNTMwNTRlMDk0YzM4YmM2ID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uX2EyM2RkZDJkZTVjNDRmNWFiNTMwNTRlMDk0YzM4YmM2X29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgICAgIGdlb19qc29uX2EyM2RkZDJkZTVjNDRmNWFiNTMwNTRlMDk0YzM4YmM2LmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTIwMTE3MTg3NSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgyODc5OTI1MTkyMTM0XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MjExNDM0MDA3OTQ3XSwgWzMuMTIwMTE3MTg3NSwgNDUuODIxMTQzNDAwNzk0N11dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzQ0OGFmNmVhNWU5OTQ1NWFhZTBjYzdhMGVjMDEzYzk4X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fNDQ4YWY2ZWE1ZTk5NDU1YWFlMGNjN2EwZWMwMTNjOTggPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fNDQ4YWY2ZWE1ZTk5NDU1YWFlMGNjN2EwZWMwMTNjOThfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fNDQ4YWY2ZWE1ZTk5NDU1YWFlMGNjN2EwZWMwMTNjOTguYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMjAxMTcxODc1LCA0NS44MjExNDM0MDA3OTQ3XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MjExNDM0MDA3OTQ3XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjEyMDExNzE4NzUsIDQ1LjgxMzQ4NjQ5Njc5OTcyXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fZDMwMGNkMjI2ZGMwNDczNjhkZGU0NzM5YTMwNGZmOTdfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl9kMzAwY2QyMjZkYzA0NzM2OGRkZTQ3MzlhMzA0ZmY5NyA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl9kMzAwY2QyMjZkYzA0NzM2OGRkZTQ3MzlhMzA0ZmY5N19vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl9kMzAwY2QyMjZkYzA0NzM2OGRkZTQ3MzlhMzA0ZmY5Ny5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEyMDExNzE4NzUsIDQ1LjgxMzQ4NjQ5Njc5OTcyXSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjEzMTEwMzUxNTYyNSwgNDUuODA1ODI4NTM5OTI4MzU2XSwgWzMuMTIwMTE3MTg3NSwgNDUuODA1ODI4NTM5OTI4MzU2XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fODVlNDY4Y2IzZWQzNDdhYzk4M2Q5MGYzZGNjN2RjZDlfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl84NWU0NjhjYjNlZDM0N2FjOTgzZDkwZjNkY2M3ZGNkOSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl84NWU0NjhjYjNlZDM0N2FjOTgzZDkwZjNkY2M3ZGNkOV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl84NWU0NjhjYjNlZDM0N2FjOTgzZDkwZjNkY2M3ZGNkOS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuODQ0MTA3Nzk1NjAyMDRdLCBbMy4xNDIwODk4NDM3NSwgNDUuODQ0MTA3Nzk1NjAyMDRdLCBbMy4xNDIwODk4NDM3NSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgzNjQ1NDA1MDE4NzcxXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fYjcxNzEwZTZlZDg5NGI2OWFiNjg5ZGVlOTc4OTA3ODlfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl9iNzE3MTBlNmVkODk0YjY5YWI2ODlkZWU5Nzg5MDc4OSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl9iNzE3MTBlNmVkODk0YjY5YWI2ODlkZWU5Nzg5MDc4OV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl9iNzE3MTBlNmVkODk0YjY5YWI2ODlkZWU5Nzg5MDc4OS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xNDIwODk4NDM3NSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xNDIwODk4NDM3NSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgyODc5OTI1MTkyMTM0XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fMjBkYmU3MTY0OWM2NGJkMzgxYjMzMTQyNWY1OGNmMjVfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl8yMGRiZTcxNjQ5YzY0YmQzODFiMzMxNDI1ZjU4Y2YyNSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl8yMGRiZTcxNjQ5YzY0YmQzODFiMzMxNDI1ZjU4Y2YyNV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl8yMGRiZTcxNjQ5YzY0YmQzODFiMzMxNDI1ZjU4Y2YyNS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xNDIwODk4NDM3NSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xNDIwODk4NDM3NSwgNDUuODIxMTQzNDAwNzk0N10sIFszLjEzMTEwMzUxNTYyNSwgNDUuODIxMTQzNDAwNzk0N11dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2E5MTVkNzViNDM4YjRlY2M5YjE5NzYxZjIwZGQ0ZmNjX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fYTkxNWQ3NWI0MzhiNGVjYzliMTk3NjFmMjBkZDRmY2MgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fYTkxNWQ3NWI0MzhiNGVjYzliMTk3NjFmMjBkZDRmY2Nfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fYTkxNWQ3NWI0MzhiNGVjYzliMTk3NjFmMjBkZDRmY2MuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMzExMDM1MTU2MjUsIDQ1LjgyMTE0MzQwMDc5NDddLCBbMy4xNDIwODk4NDM3NSwgNDUuODIxMTQzNDAwNzk0N10sIFszLjE0MjA4OTg0Mzc1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjEzMTEwMzUxNTYyNSwgNDUuODEzNDg2NDk2Nzk5NzJdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl9kMGU4ZDlkNzVkMzM0MTRlOTVhMzQzZGUxY2I4YjRhMV9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uX2QwZThkOWQ3NWQzMzQxNGU5NWEzNDNkZTFjYjhiNGExID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uX2QwZThkOWQ3NWQzMzQxNGU5NWEzNDNkZTFjYjhiNGExX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgICAgIGdlb19qc29uX2QwZThkOWQ3NWQzMzQxNGU5NWEzNDNkZTFjYjhiNGExLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTMxMTAzNTE1NjI1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjE0MjA4OTg0Mzc1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjE0MjA4OTg0Mzc1LCA0NS44MDU4Mjg1Mzk5MjgzNTZdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgwNTgyODUzOTkyODM1Nl1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2NkZGVjYjM5ZGQxNDQ5YzBhODkxNWViNDY0ZTFjNDE2X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fY2RkZWNiMzlkZDE0NDljMGE4OTE1ZWI0NjRlMWM0MTYgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fY2RkZWNiMzlkZDE0NDljMGE4OTE1ZWI0NjRlMWM0MTZfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fY2RkZWNiMzlkZDE0NDljMGE4OTE1ZWI0NjRlMWM0MTYuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNDIwODk4NDM3NSwgNDUuODQ0MTA3Nzk1NjAyMDRdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1Ljg0NDEwNzc5NTYwMjA0XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44MzY0NTQwNTAxODc3MV0sIFszLjE0MjA4OTg0Mzc1LCA0NS44MzY0NTQwNTAxODc3MV1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzNkZTM2OWI5Mjg2NDQwMzg4MDA1NmJiMmNjY2RhMjU2X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fM2RlMzY5YjkyODY0NDAzODgwMDU2YmIyY2NjZGEyNTYgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fM2RlMzY5YjkyODY0NDAzODgwMDU2YmIyY2NjZGEyNTZfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fM2RlMzY5YjkyODY0NDAzODgwMDU2YmIyY2NjZGEyNTYuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNDIwODk4NDM3NSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgzNjQ1NDA1MDE4NzcxXSwgWzMuMTUzMDc2MTcxODc1LCA0NS44Mjg3OTkyNTE5MjEzNF0sIFszLjE0MjA4OTg0Mzc1LCA0NS44Mjg3OTkyNTE5MjEzNF1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2QyYjcyZmM4Y2QzODRmNjhiODg1MTE3NWQzZDU2OGIyX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fZDJiNzJmYzhjZDM4NGY2OGI4ODUxMTc1ZDNkNTY4YjIgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fZDJiNzJmYzhjZDM4NGY2OGI4ODUxMTc1ZDNkNTY4YjJfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fZDJiNzJmYzhjZDM4NGY2OGI4ODUxMTc1ZDNkNTY4YjIuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNDIwODk4NDM3NSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgyODc5OTI1MTkyMTM0XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44MjExNDM0MDA3OTQ3XSwgWzMuMTQyMDg5ODQzNzUsIDQ1LjgyMTE0MzQwMDc5NDddXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl8wOGRkYWIxMTc4OTQ0MmNlOWFkZGM4YWM4ZWI4ZGNhZV9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzA4ZGRhYjExNzg5NDQyY2U5YWRkYzhhYzhlYjhkY2FlID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzA4ZGRhYjExNzg5NDQyY2U5YWRkYzhhYzhlYjhkY2FlX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgICAgIGdlb19qc29uXzA4ZGRhYjExNzg5NDQyY2U5YWRkYzhhYzhlYjhkY2FlLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTQyMDg5ODQzNzUsIDQ1LjgyMTE0MzQwMDc5NDddLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgyMTE0MzQwMDc5NDddLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgxMzQ4NjQ5Njc5OTcyXSwgWzMuMTQyMDg5ODQzNzUsIDQ1LjgxMzQ4NjQ5Njc5OTcyXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fYzQxZWY2MDE0NjhiNGZiM2JkZWQ2MDlmMGM4MDY1OTJfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl9jNDFlZjYwMTQ2OGI0ZmIzYmRlZDYwOWYwYzgwNjU5MiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl9jNDFlZjYwMTQ2OGI0ZmIzYmRlZDYwOWYwYzgwNjU5Ml9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl9jNDFlZjYwMTQ2OGI0ZmIzYmRlZDYwOWYwYzgwNjU5Mi5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE0MjA4OTg0Mzc1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjE1MzA3NjE3MTg3NSwgNDUuODEzNDg2NDk2Nzk5NzJdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgwNTgyODUzOTkyODM1Nl0sIFszLjE0MjA4OTg0Mzc1LCA0NS44MDU4Mjg1Mzk5MjgzNTZdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl8wODY0M2FmMTJiMjE0YjQwOTIyYzA3ODE4ZDQ3NTEzOV9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzA4NjQzYWYxMmIyMTRiNDA5MjJjMDc4MThkNDc1MTM5ID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzA4NjQzYWYxMmIyMTRiNDA5MjJjMDc4MThkNDc1MTM5X29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgICAgIGdlb19qc29uXzA4NjQzYWYxMmIyMTRiNDA5MjJjMDc4MThkNDc1MTM5LmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTUzMDc2MTcxODc1LCA0NS44NDQxMDc3OTU2MDIwNF0sIFszLjE2NDA2MjUsIDQ1Ljg0NDEwNzc5NTYwMjA0XSwgWzMuMTY0MDYyNSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgzNjQ1NDA1MDE4NzcxXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fNTc3MTg1NjllNzRiNDAyNDhjZDEyMzA0NGIxOWMwOWVfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl81NzcxODU2OWU3NGI0MDI0OGNkMTIzMDQ0YjE5YzA5ZSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl81NzcxODU2OWU3NGI0MDI0OGNkMTIzMDQ0YjE5YzA5ZV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl81NzcxODU2OWU3NGI0MDI0OGNkMTIzMDQ0YjE5YzA5ZS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE1MzA3NjE3MTg3NSwgNDUuODM2NDU0MDUwMTg3NzFdLCBbMy4xNjQwNjI1LCA0NS44MzY0NTQwNTAxODc3MV0sIFszLjE2NDA2MjUsIDQ1LjgyODc5OTI1MTkyMTM0XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44Mjg3OTkyNTE5MjEzNF1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2ViZTI0YmM3MjU3ZjQ2MDY5OTg2YmE0MmZlNWU3NDk2X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fZWJlMjRiYzcyNTdmNDYwNjk5ODZiYTQyZmU1ZTc0OTYgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fZWJlMjRiYzcyNTdmNDYwNjk5ODZiYTQyZmU1ZTc0OTZfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fZWJlMjRiYzcyNTdmNDYwNjk5ODZiYTQyZmU1ZTc0OTYuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNTMwNzYxNzE4NzUsIDQ1LjgyODc5OTI1MTkyMTM0XSwgWzMuMTY0MDYyNSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xNjQwNjI1LCA0NS44MjExNDM0MDA3OTQ3XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44MjExNDM0MDA3OTQ3XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fMWRiNTFhM2IzNzI1NDc1NGIxN2VhNjgyYTIyMTQ3MWZfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl8xZGI1MWEzYjM3MjU0NzU0YjE3ZWE2ODJhMjIxNDcxZiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl8xZGI1MWEzYjM3MjU0NzU0YjE3ZWE2ODJhMjIxNDcxZl9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl8xZGI1MWEzYjM3MjU0NzU0YjE3ZWE2ODJhMjIxNDcxZi5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE1MzA3NjE3MTg3NSwgNDUuODIxMTQzNDAwNzk0N10sIFszLjE2NDA2MjUsIDQ1LjgyMTE0MzQwMDc5NDddLCBbMy4xNjQwNjI1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjE1MzA3NjE3MTg3NSwgNDUuODEzNDg2NDk2Nzk5NzJdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl8zYTc0OGZiYTc3NDQ0ZTcwYWNhNTExMjA1YjQ0ZTA2Nl9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzNhNzQ4ZmJhNzc0NDRlNzBhY2E1MTEyMDViNDRlMDY2ID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzNhNzQ4ZmJhNzc0NDRlNzBhY2E1MTEyMDViNDRlMDY2X29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgICAgIGdlb19qc29uXzNhNzQ4ZmJhNzc0NDRlNzBhY2E1MTEyMDViNDRlMDY2LmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTUzMDc2MTcxODc1LCA0NS44MTM0ODY0OTY3OTk3Ml0sIFszLjE2NDA2MjUsIDQ1LjgxMzQ4NjQ5Njc5OTcyXSwgWzMuMTY0MDYyNSwgNDUuODA1ODI4NTM5OTI4MzU2XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44MDU4Mjg1Mzk5MjgzNTZdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl85MzVkODZhOTQ4ZGY0NTUxYjc1ODUwN2YwYWM0ODc2M19vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzkzNWQ4NmE5NDhkZjQ1NTFiNzU4NTA3ZjBhYzQ4NzYzID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzkzNWQ4NmE5NDhkZjQ1NTFiNzU4NTA3ZjBhYzQ4NzYzX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgICAgIGdlb19qc29uXzkzNWQ4NmE5NDhkZjQ1NTFiNzU4NTA3ZjBhYzQ4NzYzLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTY0MDYyNSwgNDUuODQ0MTA3Nzk1NjAyMDRdLCBbMy4xNzUwNDg4MjgxMjUsIDQ1Ljg0NDEwNzc5NTYwMjA0XSwgWzMuMTc1MDQ4ODI4MTI1LCA0NS44MzY0NTQwNTAxODc3MV0sIFszLjE2NDA2MjUsIDQ1LjgzNjQ1NDA1MDE4NzcxXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fM2RmN2QwMWI5ZmZjNGQyZGIxODliNjc4N2EyNjExNTFfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl8zZGY3ZDAxYjlmZmM0ZDJkYjE4OWI2Nzg3YTI2MTE1MSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl8zZGY3ZDAxYjlmZmM0ZDJkYjE4OWI2Nzg3YTI2MTE1MV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl8zZGY3ZDAxYjlmZmM0ZDJkYjE4OWI2Nzg3YTI2MTE1MS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE2NDA2MjUsIDQ1LjgzNjQ1NDA1MDE4NzcxXSwgWzMuMTc1MDQ4ODI4MTI1LCA0NS44MzY0NTQwNTAxODc3MV0sIFszLjE3NTA0ODgyODEyNSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xNjQwNjI1LCA0NS44Mjg3OTkyNTE5MjEzNF1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2RhMzRhNTM2NTViODRlMjY4NDhiNzhkOGNjYTRlN2YxX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fZGEzNGE1MzY1NWI4NGUyNjg0OGI3OGQ4Y2NhNGU3ZjEgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fZGEzNGE1MzY1NWI4NGUyNjg0OGI3OGQ4Y2NhNGU3ZjFfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjKTsKICAgICAgICAgICAgZ2VvX2pzb25fZGEzNGE1MzY1NWI4NGUyNjg0OGI3OGQ4Y2NhNGU3ZjEuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNjQwNjI1LCA0NS44Mjg3OTkyNTE5MjEzNF0sIFszLjE3NTA0ODgyODEyNSwgNDUuODI4Nzk5MjUxOTIxMzRdLCBbMy4xNzUwNDg4MjgxMjUsIDQ1LjgyMTE0MzQwMDc5NDddLCBbMy4xNjQwNjI1LCA0NS44MjExNDM0MDA3OTQ3XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fYmU1YjhhMmI5NzRhNGQ3ODk0YzA2NTg2MGMyNDUwZWJfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYy5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl9iZTViOGEyYjk3NGE0ZDc4OTRjMDY1ODYwYzI0NTBlYiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl9iZTViOGEyYjk3NGE0ZDc4OTRjMDY1ODYwYzI0NTBlYl9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfMDEzMGY0MDA0OWFjNDU1ZjgxMGRhYjE4NTU0ZmZmZmMpOwogICAgICAgICAgICBnZW9fanNvbl9iZTViOGEyYjk3NGE0ZDc4OTRjMDY1ODYwYzI0NTBlYi5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE2NDA2MjUsIDQ1LjgyMTE0MzQwMDc5NDddLCBbMy4xNzUwNDg4MjgxMjUsIDQ1LjgyMTE0MzQwMDc5NDddLCBbMy4xNzUwNDg4MjgxMjUsIDQ1LjgxMzQ4NjQ5Njc5OTcyXSwgWzMuMTY0MDYyNSwgNDUuODEzNDg2NDk2Nzk5NzJdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl8wODUxYjg4YmQ2ODc0ZjVhOGM5ZmQxMzgxMDExMzQzZF9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzA4NTFiODhiZDY4NzRmNWE4YzlmZDEzODEwMTEzNDNkID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzA4NTFiODhiZDY4NzRmNWE4YzlmZDEzODEwMTEzNDNkX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgICAgIGdlb19qc29uXzA4NTFiODhiZDY4NzRmNWE4YzlmZDEzODEwMTEzNDNkLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTY0MDYyNSwgNDUuODEzNDg2NDk2Nzk5NzJdLCBbMy4xNzUwNDg4MjgxMjUsIDQ1LjgxMzQ4NjQ5Njc5OTcyXSwgWzMuMTc1MDQ4ODI4MTI1LCA0NS44MDU4Mjg1Mzk5MjgzNTZdLCBbMy4xNjQwNjI1LCA0NS44MDU4Mjg1Mzk5MjgzNTZdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIG1hcmtlcl9kODYwYjYwM2NhMDU0NGNiYWY1MWQxYWJlMGFmZDAyMSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzQ1LjgzODEsIDMuMTIwNV0sCiAgICAgICAgICAgICAgICB7fQogICAgICAgICAgICApLmFkZFRvKG1hcF8wMTMwZjQwMDQ5YWM0NTVmODEwZGFiMTg1NTRmZmZmYyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgbWFwXzAxMzBmNDAwNDlhYzQ1NWY4MTBkYWIxODU1NGZmZmZjLmZpdEJvdW5kcygKICAgICAgICAgICAgICAgIFtbNDUuODA1ODI4NTM5OTI4MzU2LCAzLjEyMDExNzE4NzVdLCBbNDUuODQ0MTA3Nzk1NjAyMDQsIDMuMTc1MDQ4ODI4MTI1XV0sCiAgICAgICAgICAgICAgICB7fQogICAgICAgICAgICApOwogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x1fe1a878128>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m = folium.Map()\n",
"for i in range(5):\n",
" for j in range(5):\n",
" m.add_child(folium.GeoJson(tiles.SquareTile(sq.x + i, sq.y + j, sq.z).to_geojson()))\n",
"m.add_child(folium.Marker([lat, lng]))\n",
"m.fit_bounds(m.get_bounds())\n",
"m"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('15/16668/11678', '15/16668/11678')"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tiles.tile_from_hash(sq.to_hash()).to_string(), sq.to_string()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Triangles"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<tiles.TriangleTile at 0x1fe1a89e5c0>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"trig = tiles.TriangleTile.from_lat_lng(lat, lng, 15)\n",
"trig"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF82MjQ5NzJjMzk4ZTM0YTdkYjZlYTE3MTUxNzBmMzk5NSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfNjI0OTcyYzM5OGUzNGE3ZGI2ZWExNzE1MTcwZjM5OTUiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzYyNDk3MmMzOThlMzRhN2RiNmVhMTcxNTE3MGYzOTk1ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzYyNDk3MmMzOThlMzRhN2RiNmVhMTcxNTE3MGYzOTk1IiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFswLCAwXSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDEsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl81Y2Q1ODMyZjhkYzE0Y2RhOWNlMGNjY2E4YzI4NDhmZCA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiRGF0YSBieSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSwgdW5kZXIgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9EYkxcdTAwM2MvYVx1MDAzZS4iLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNjI0OTcyYzM5OGUzNGE3ZGI2ZWExNzE1MTcwZjM5OTUpOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fMzRlMzA3NGMyMDM5NDViOTk1NTQzOTE1ZmJiNzdkM2Rfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF82MjQ5NzJjMzk4ZTM0YTdkYjZlYTE3MTUxNzBmMzk5NS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl8zNGUzMDc0YzIwMzk0NWI5OTU1NDM5MTVmYmI3N2QzZCA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl8zNGUzMDc0YzIwMzk0NWI5OTU1NDM5MTVmYmI3N2QzZF9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfNjI0OTcyYzM5OGUzNGE3ZGI2ZWExNzE1MTcwZjM5OTUpOwogICAgICAgICAgICBnZW9fanNvbl8zNGUzMDc0YzIwMzk0NWI5OTU1NDM5MTVmYmI3N2QzZC5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEwOTEzMDg1OTM3NSwgNDUuODQzOTcwMzc1NDkyMTNdLCBbMy4xMjAxMTcxODc1LCA0NS44MzA3MTI5OTkzNDEyM10sIFszLjEzMTEwMzUxNTYyNSwgNDUuODQzOTcwMzc1NDkyMTNdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIG1hcmtlcl9mZDdjMWY3OThkYjI0ODFkYWU3ZDVmYzgyZGIyYTU1NiA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzQ1LjgzODEsIDMuMTIwNV0sCiAgICAgICAgICAgICAgICB7fQogICAgICAgICAgICApLmFkZFRvKG1hcF82MjQ5NzJjMzk4ZTM0YTdkYjZlYTE3MTUxNzBmMzk5NSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgbWFwXzYyNDk3MmMzOThlMzRhN2RiNmVhMTcxNTE3MGYzOTk1LmZpdEJvdW5kcygKICAgICAgICAgICAgICAgIFtbNDUuODMwNzEyOTk5MzQxMjMsIDMuMTA5MTMwODU5Mzc1XSwgWzQ1Ljg0Mzk3MDM3NTQ5MjEzLCAzLjEzMTEwMzUxNTYyNV1dLAogICAgICAgICAgICAgICAge30KICAgICAgICAgICAgKTsKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x1fe1a867390>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m = folium.Map()\n",
"m.add_child(folium.GeoJson(trig.to_geojson()))\n",
"m.add_child(folium.Marker([lat, lng]))\n",
"m.fit_bounds(m.get_bounds())\n",
"m"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1IiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFswLCAwXSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDEsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl80OWE2M2UwM2NmZDg0M2FiODUwNjRkZGI1YWFkZjI4YyA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiRGF0YSBieSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSwgdW5kZXIgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9EYkxcdTAwM2MvYVx1MDAzZS4iLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fODgwYzUxN2JiYzU5NDVlN2FlY2NmNGU0ZDBjMDIzZTNfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl84ODBjNTE3YmJjNTk0NWU3YWVjY2Y0ZTRkMGMwMjNlMyA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl84ODBjNTE3YmJjNTk0NWU3YWVjY2Y0ZTRkMGMwMjNlM19vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl84ODBjNTE3YmJjNTk0NWU3YWVjY2Y0ZTRkMGMwMjNlMy5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEwOTEzMDg1OTM3NSwgNDUuODQzOTcwMzc1NDkyMTNdLCBbMy4xMjAxMTcxODc1LCA0NS44MzA3MTI5OTkzNDEyM10sIFszLjEzMTEwMzUxNTYyNSwgNDUuODQzOTcwMzc1NDkyMTNdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl9jYzllNTg0ZjM1ZmI0MzUwYWU5YThmYTY3NGU3MjZiM19vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1LmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uX2NjOWU1ODRmMzVmYjQzNTBhZTlhOGZhNjc0ZTcyNmIzID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uX2NjOWU1ODRmMzVmYjQzNTBhZTlhOGZhNjc0ZTcyNmIzX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSk7CiAgICAgICAgICAgIGdlb19qc29uX2NjOWU1ODRmMzVmYjQzNTBhZTlhOGZhNjc0ZTcyNmIzLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTA5MTMwODU5Mzc1LCA0NS44MTc0NTI0NjQ2MTU3M10sIFszLjEyMDExNzE4NzUsIDQ1LjgzMDcxMjk5OTM0MTIzXSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MTc0NTI0NjQ2MTU3M11dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2ZhZjdmMGEwNmQ3MTQ2NGU4OGE1YTM3NGJkZDFmOWM2X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fZmFmN2YwYTA2ZDcxNDY0ZTg4YTVhMzc0YmRkMWY5YzYgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fZmFmN2YwYTA2ZDcxNDY0ZTg4YTVhMzc0YmRkMWY5YzZfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1KTsKICAgICAgICAgICAgZ2VvX2pzb25fZmFmN2YwYTA2ZDcxNDY0ZTg4YTVhMzc0YmRkMWY5YzYuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMDkxMzA4NTkzNzUsIDQ1LjgxNzQ1MjQ2NDYxNTczXSwgWzMuMTIwMTE3MTg3NSwgNDUuODA0MTg4NzcxMjczNTddLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgxNzQ1MjQ2NDYxNTczXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fYmMyMjI4ZDA3Njc3NDcyNmFlNTcxNTgxMmIzOTg3YWVfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl9iYzIyMjhkMDc2Nzc0NzI2YWU1NzE1ODEyYjM5ODdhZSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl9iYzIyMjhkMDc2Nzc0NzI2YWU1NzE1ODEyYjM5ODdhZV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl9iYzIyMjhkMDc2Nzc0NzI2YWU1NzE1ODEyYjM5ODdhZS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEwOTEzMDg1OTM3NSwgNDUuNzkwOTIxOTE5MjczMzVdLCBbMy4xMjAxMTcxODc1LCA0NS44MDQxODg3NzEyNzM1N10sIFszLjEzMTEwMzUxNTYyNSwgNDUuNzkwOTIxOTE5MjczMzVdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl83ZTI3MmQ5NjM0NGQ0MDQzOWZhMWUyNWJmYjQ3N2Q2ZF9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1LmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzdlMjcyZDk2MzQ0ZDQwNDM5ZmExZTI1YmZiNDc3ZDZkID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzdlMjcyZDk2MzQ0ZDQwNDM5ZmExZTI1YmZiNDc3ZDZkX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSk7CiAgICAgICAgICAgIGdlb19qc29uXzdlMjcyZDk2MzQ0ZDQwNDM5ZmExZTI1YmZiNDc3ZDZkLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTA5MTMwODU5Mzc1LCA0NS43OTA5MjE5MTkyNzMzNV0sIFszLjEyMDExNzE4NzUsIDQ1Ljc3NzY1MTkwODU3NDM0XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS43OTA5MjE5MTkyNzMzNV1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzFiYzRiNDE5YTRhODRiZDg5ZTIwOTMyZjBlZTljOThkX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fMWJjNGI0MTlhNGE4NGJkODllMjA5MzJmMGVlOWM5OGQgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fMWJjNGI0MTlhNGE4NGJkODllMjA5MzJmMGVlOWM5OGRfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1KTsKICAgICAgICAgICAgZ2VvX2pzb25fMWJjNGI0MTlhNGE4NGJkODllMjA5MzJmMGVlOWM5OGQuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMjAxMTcxODc1LCA0NS44MzA3MTI5OTkzNDEyM10sIFszLjEzMTEwMzUxNTYyNSwgNDUuODQzOTcwMzc1NDkyMTNdLCBbMy4xNDIwODk4NDM3NSwgNDUuODMwNzEyOTk5MzQxMjNdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl8zMmI3OWVkNzY0NTE0NzI3YjdlYzI2ZGUzYzg0YzZlY19vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1LmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzMyYjc5ZWQ3NjQ1MTQ3MjdiN2VjMjZkZTNjODRjNmVjID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzMyYjc5ZWQ3NjQ1MTQ3MjdiN2VjMjZkZTNjODRjNmVjX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSk7CiAgICAgICAgICAgIGdlb19qc29uXzMyYjc5ZWQ3NjQ1MTQ3MjdiN2VjMjZkZTNjODRjNmVjLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTIwMTE3MTg3NSwgNDUuODMwNzEyOTk5MzQxMjNdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgxNzQ1MjQ2NDYxNTczXSwgWzMuMTQyMDg5ODQzNzUsIDQ1LjgzMDcxMjk5OTM0MTIzXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fZDJmNTE2MzY3Y2EwNDFkMDkyMzU0YmMyOTY4ZjljNjFfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl9kMmY1MTYzNjdjYTA0MWQwOTIzNTRiYzI5NjhmOWM2MSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl9kMmY1MTYzNjdjYTA0MWQwOTIzNTRiYzI5NjhmOWM2MV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl9kMmY1MTYzNjdjYTA0MWQwOTIzNTRiYzI5NjhmOWM2MS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEyMDExNzE4NzUsIDQ1LjgwNDE4ODc3MTI3MzU3XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MTc0NTI0NjQ2MTU3M10sIFszLjE0MjA4OTg0Mzc1LCA0NS44MDQxODg3NzEyNzM1N11dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2E2NTcwZmM2M2U4NjQ2OTRhM2FhODc1YmM1YWE1NGQxX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fYTY1NzBmYzYzZTg2NDY5NGEzYWE4NzViYzVhYTU0ZDEgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fYTY1NzBmYzYzZTg2NDY5NGEzYWE4NzViYzVhYTU0ZDFfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1KTsKICAgICAgICAgICAgZ2VvX2pzb25fYTY1NzBmYzYzZTg2NDY5NGEzYWE4NzViYzVhYTU0ZDEuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMjAxMTcxODc1LCA0NS44MDQxODg3NzEyNzM1N10sIFszLjEzMTEwMzUxNTYyNSwgNDUuNzkwOTIxOTE5MjczMzVdLCBbMy4xNDIwODk4NDM3NSwgNDUuODA0MTg4NzcxMjczNTddXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl80MGIzYzJmYmZiNDU0Y2E4OWM5MzU4YzBmMDRlNTVhZF9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1LmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzQwYjNjMmZiZmI0NTRjYTg5YzkzNThjMGYwNGU1NWFkID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzQwYjNjMmZiZmI0NTRjYTg5YzkzNThjMGYwNGU1NWFkX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSk7CiAgICAgICAgICAgIGdlb19qc29uXzQwYjNjMmZiZmI0NTRjYTg5YzkzNThjMGYwNGU1NWFkLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTIwMTE3MTg3NSwgNDUuNzc3NjUxOTA4NTc0MzRdLCBbMy4xMzExMDM1MTU2MjUsIDQ1Ljc5MDkyMTkxOTI3MzM1XSwgWzMuMTQyMDg5ODQzNzUsIDQ1Ljc3NzY1MTkwODU3NDM0XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fZjkxY2NjOTRhODQxNDc0N2E5YmUwZDg2YzY0MjgxNTJfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl9mOTFjY2M5NGE4NDE0NzQ3YTliZTBkODZjNjQyODE1MiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl9mOTFjY2M5NGE4NDE0NzQ3YTliZTBkODZjNjQyODE1Ml9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl9mOTFjY2M5NGE4NDE0NzQ3YTliZTBkODZjNjQyODE1Mi5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuODQzOTcwMzc1NDkyMTNdLCBbMy4xNDIwODk4NDM3NSwgNDUuODMwNzEyOTk5MzQxMjNdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1Ljg0Mzk3MDM3NTQ5MjEzXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fOTMwOGE5ZDI4ZThlNDAxYmIzYTU3ZjMwNTY3NTgxNzRfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl85MzA4YTlkMjhlOGU0MDFiYjNhNTdmMzA1Njc1ODE3NCA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl85MzA4YTlkMjhlOGU0MDFiYjNhNTdmMzA1Njc1ODE3NF9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl85MzA4YTlkMjhlOGU0MDFiYjNhNTdmMzA1Njc1ODE3NC5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuODE3NDUyNDY0NjE1NzNdLCBbMy4xNDIwODk4NDM3NSwgNDUuODMwNzEyOTk5MzQxMjNdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgxNzQ1MjQ2NDYxNTczXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fN2M4M2NhMDdhMzBhNGRlZjhkYTBiODg3YmVlZmY2NzVfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl83YzgzY2EwN2EzMGE0ZGVmOGRhMGI4ODdiZWVmZjY3NSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl83YzgzY2EwN2EzMGE0ZGVmOGRhMGI4ODdiZWVmZjY3NV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl83YzgzY2EwN2EzMGE0ZGVmOGRhMGI4ODdiZWVmZjY3NS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuODE3NDUyNDY0NjE1NzNdLCBbMy4xNDIwODk4NDM3NSwgNDUuODA0MTg4NzcxMjczNTddLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgxNzQ1MjQ2NDYxNTczXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fNDEyYzA0M2I3ZTZhNGQwMWI4MTQ1N2U0NTgwNDViNTlfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl80MTJjMDQzYjdlNmE0ZDAxYjgxNDU3ZTQ1ODA0NWI1OSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl80MTJjMDQzYjdlNmE0ZDAxYjgxNDU3ZTQ1ODA0NWI1OV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl80MTJjMDQzYjdlNmE0ZDAxYjgxNDU3ZTQ1ODA0NWI1OS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuNzkwOTIxOTE5MjczMzVdLCBbMy4xNDIwODk4NDM3NSwgNDUuODA0MTg4NzcxMjczNTddLCBbMy4xNTMwNzYxNzE4NzUsIDQ1Ljc5MDkyMTkxOTI3MzM1XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fMGQxYmIxZjkzZjI1NDgzYzhjOGZjNDkyODBhNzI3MGNfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl8wZDFiYjFmOTNmMjU0ODNjOGM4ZmM0OTI4MGE3MjcwYyA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl8wZDFiYjFmOTNmMjU0ODNjOGM4ZmM0OTI4MGE3MjcwY19vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl8wZDFiYjFmOTNmMjU0ODNjOGM4ZmM0OTI4MGE3MjcwYy5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEzMTEwMzUxNTYyNSwgNDUuNzkwOTIxOTE5MjczMzVdLCBbMy4xNDIwODk4NDM3NSwgNDUuNzc3NjUxOTA4NTc0MzRdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1Ljc5MDkyMTkxOTI3MzM1XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fMzA2OGExOWU4NmY5NGJiZmI5ZjhjM2U1YzhlN2UwYjVfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl8zMDY4YTE5ZTg2Zjk0YmJmYjlmOGMzZTVjOGU3ZTBiNSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl8zMDY4YTE5ZTg2Zjk0YmJmYjlmOGMzZTVjOGU3ZTBiNV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl8zMDY4YTE5ZTg2Zjk0YmJmYjlmOGMzZTVjOGU3ZTBiNS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE0MjA4OTg0Mzc1LCA0NS44MzA3MTI5OTkzNDEyM10sIFszLjE1MzA3NjE3MTg3NSwgNDUuODQzOTcwMzc1NDkyMTNdLCBbMy4xNjQwNjI1LCA0NS44MzA3MTI5OTkzNDEyM11dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2YyODAzNTg0MTE3MjQ4MjZhZGNjNGUwZjRiZTQ1N2M1X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fZjI4MDM1ODQxMTcyNDgyNmFkY2M0ZTBmNGJlNDU3YzUgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fZjI4MDM1ODQxMTcyNDgyNmFkY2M0ZTBmNGJlNDU3YzVfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1KTsKICAgICAgICAgICAgZ2VvX2pzb25fZjI4MDM1ODQxMTcyNDgyNmFkY2M0ZTBmNGJlNDU3YzUuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNDIwODk4NDM3NSwgNDUuODMwNzEyOTk5MzQxMjNdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgxNzQ1MjQ2NDYxNTczXSwgWzMuMTY0MDYyNSwgNDUuODMwNzEyOTk5MzQxMjNdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl9iNTgyZTA4MDdmN2I0ZTQ5YmMyNmNmMDc1NzE1Y2U5Nl9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1LmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uX2I1ODJlMDgwN2Y3YjRlNDliYzI2Y2YwNzU3MTVjZTk2ID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uX2I1ODJlMDgwN2Y3YjRlNDliYzI2Y2YwNzU3MTVjZTk2X29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSk7CiAgICAgICAgICAgIGdlb19qc29uX2I1ODJlMDgwN2Y3YjRlNDliYzI2Y2YwNzU3MTVjZTk2LmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTQyMDg5ODQzNzUsIDQ1LjgwNDE4ODc3MTI3MzU3XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44MTc0NTI0NjQ2MTU3M10sIFszLjE2NDA2MjUsIDQ1LjgwNDE4ODc3MTI3MzU3XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fOTJkZjM4MDQzNTA1NGU0ZWI4NjEyZDEwZTkyNDI2Y2Zfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl85MmRmMzgwNDM1MDU0ZTRlYjg2MTJkMTBlOTI0MjZjZiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl85MmRmMzgwNDM1MDU0ZTRlYjg2MTJkMTBlOTI0MjZjZl9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl85MmRmMzgwNDM1MDU0ZTRlYjg2MTJkMTBlOTI0MjZjZi5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE0MjA4OTg0Mzc1LCA0NS44MDQxODg3NzEyNzM1N10sIFszLjE1MzA3NjE3MTg3NSwgNDUuNzkwOTIxOTE5MjczMzVdLCBbMy4xNjQwNjI1LCA0NS44MDQxODg3NzEyNzM1N11dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2VjNjQ2ZTJjZDVkYTQxYzhhYjExNmVjMDEzODBiMDhkX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fZWM2NDZlMmNkNWRhNDFjOGFiMTE2ZWMwMTM4MGIwOGQgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fZWM2NDZlMmNkNWRhNDFjOGFiMTE2ZWMwMTM4MGIwOGRfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1KTsKICAgICAgICAgICAgZ2VvX2pzb25fZWM2NDZlMmNkNWRhNDFjOGFiMTE2ZWMwMTM4MGIwOGQuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNDIwODk4NDM3NSwgNDUuNzc3NjUxOTA4NTc0MzRdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1Ljc5MDkyMTkxOTI3MzM1XSwgWzMuMTY0MDYyNSwgNDUuNzc3NjUxOTA4NTc0MzRdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl9lYmNhOWEzYjYyMDA0YTNlYjA5ZWE5ZWQzZDcxMjZlOF9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1LmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uX2ViY2E5YTNiNjIwMDRhM2ViMDllYTllZDNkNzEyNmU4ID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uX2ViY2E5YTNiNjIwMDRhM2ViMDllYTllZDNkNzEyNmU4X29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSk7CiAgICAgICAgICAgIGdlb19qc29uX2ViY2E5YTNiNjIwMDRhM2ViMDllYTllZDNkNzEyNmU4LmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTUzMDc2MTcxODc1LCA0NS44NDM5NzAzNzU0OTIxM10sIFszLjE2NDA2MjUsIDQ1LjgzMDcxMjk5OTM0MTIzXSwgWzMuMTc1MDQ4ODI4MTI1LCA0NS44NDM5NzAzNzU0OTIxM11dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzEzYWZlMDYxYzk3NDQyMGNhOWFkZjQ3NmZiM2I2NmY3X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fMTNhZmUwNjFjOTc0NDIwY2E5YWRmNDc2ZmIzYjY2ZjcgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fMTNhZmUwNjFjOTc0NDIwY2E5YWRmNDc2ZmIzYjY2Zjdfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1KTsKICAgICAgICAgICAgZ2VvX2pzb25fMTNhZmUwNjFjOTc0NDIwY2E5YWRmNDc2ZmIzYjY2ZjcuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNTMwNzYxNzE4NzUsIDQ1LjgxNzQ1MjQ2NDYxNTczXSwgWzMuMTY0MDYyNSwgNDUuODMwNzEyOTk5MzQxMjNdLCBbMy4xNzUwNDg4MjgxMjUsIDQ1LjgxNzQ1MjQ2NDYxNTczXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fOGViYmVjZWYwYmE3NDNjNjgyNWE5MmNiMzk4NjJjYjdfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl84ZWJiZWNlZjBiYTc0M2M2ODI1YTkyY2IzOTg2MmNiNyA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl84ZWJiZWNlZjBiYTc0M2M2ODI1YTkyY2IzOTg2MmNiN19vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgICAgICBnZW9fanNvbl84ZWJiZWNlZjBiYTc0M2M2ODI1YTkyY2IzOTg2MmNiNy5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE1MzA3NjE3MTg3NSwgNDUuODE3NDUyNDY0NjE1NzNdLCBbMy4xNjQwNjI1LCA0NS44MDQxODg3NzEyNzM1N10sIFszLjE3NTA0ODgyODEyNSwgNDUuODE3NDUyNDY0NjE1NzNdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl85ZjU4Mzc0ZDAxNDY0ZmU5YjRiZDIyZjQ5YzZkOTcwOV9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1LmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzlmNTgzNzRkMDE0NjRmZTliNGJkMjJmNDljNmQ5NzA5ID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzlmNTgzNzRkMDE0NjRmZTliNGJkMjJmNDljNmQ5NzA5X29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNSk7CiAgICAgICAgICAgIGdlb19qc29uXzlmNTgzNzRkMDE0NjRmZTliNGJkMjJmNDljNmQ5NzA5LmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTUzMDc2MTcxODc1LCA0NS43OTA5MjE5MTkyNzMzNV0sIFszLjE2NDA2MjUsIDQ1LjgwNDE4ODc3MTI3MzU3XSwgWzMuMTc1MDQ4ODI4MTI1LCA0NS43OTA5MjE5MTkyNzMzNV1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzcwNjY2ZTA5Yzk4ZDRmNmFiMGRmZmVmMzljNGRkOTUzX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fNzA2NjZlMDljOThkNGY2YWIwZGZmZWYzOWM0ZGQ5NTMgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fNzA2NjZlMDljOThkNGY2YWIwZGZmZWYzOWM0ZGQ5NTNfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwX2EzNTA5MDgwNWQyNzQ1NDA5ZWVlNjI1OTZiNDI1ZTA1KTsKICAgICAgICAgICAgZ2VvX2pzb25fNzA2NjZlMDljOThkNGY2YWIwZGZmZWYzOWM0ZGQ5NTMuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNTMwNzYxNzE4NzUsIDQ1Ljc5MDkyMTkxOTI3MzM1XSwgWzMuMTY0MDYyNSwgNDUuNzc3NjUxOTA4NTc0MzRdLCBbMy4xNzUwNDg4MjgxMjUsIDQ1Ljc5MDkyMTkxOTI3MzM1XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBtYXJrZXJfMTNjNmMzNDg3MGM4NGE1ZjkwYTRmMGNkOTcxZjRjZDkgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFs0NS44MzgxLCAzLjEyMDVdLAogICAgICAgICAgICAgICAge30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTM1MDkwODA1ZDI3NDU0MDllZWU2MjU5NmI0MjVlMDUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIG1hcF9hMzUwOTA4MDVkMjc0NTQwOWVlZTYyNTk2YjQyNWUwNS5maXRCb3VuZHMoCiAgICAgICAgICAgICAgICBbWzQ1Ljc3NzY1MTkwODU3NDM0LCAzLjEwOTEzMDg1OTM3NV0sIFs0NS44NDM5NzAzNzU0OTIxMywgMy4xNzUwNDg4MjgxMjVdXSwKICAgICAgICAgICAgICAgIHt9CiAgICAgICAgICAgICk7CiAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x1fe1a8e2f28>"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m = folium.Map()\n",
"for i in range(5):\n",
" for j in range(5):\n",
" m.add_child(folium.GeoJson(tiles.TriangleTile(trig.x + i, trig.y + j, trig.z).to_geojson()))\n",
"m.add_child(folium.Marker([lat, lng]))\n",
"m.fit_bounds(m.get_bounds())\n",
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Hexagons"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<tiles.HexagonalTile at 0x1fe1a8e2860>"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"hexg = tiles.HexagonalTile.from_lat_lng(lat, lng, 15)\n",
"hexg"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF9hYjUxNmVkNTFkNmE0YjdhOTI4NjdhNWQ0M2VjNmNiYSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfYWI1MTZlZDUxZDZhNGI3YTkyODY3YTVkNDNlYzZjYmEiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwX2FiNTE2ZWQ1MWQ2YTRiN2E5Mjg2N2E1ZDQzZWM2Y2JhID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwX2FiNTE2ZWQ1MWQ2YTRiN2E5Mjg2N2E1ZDQzZWM2Y2JhIiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFswLCAwXSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDEsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl8zOGY5MzczN2Y1ZWU0OWJjYjViMjRlNTYwMzljNDcyYyA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiRGF0YSBieSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSwgdW5kZXIgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9EYkxcdTAwM2MvYVx1MDAzZS4iLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWI1MTZlZDUxZDZhNGI3YTkyODY3YTVkNDNlYzZjYmEpOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fMDQ0MDM5M2U5NjExNDUxOWI3ZjY2ODExZDJjN2NhZWJfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF9hYjUxNmVkNTFkNmE0YjdhOTI4NjdhNWQ0M2VjNmNiYS5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl8wNDQwMzkzZTk2MTE0NTE5YjdmNjY4MTFkMmM3Y2FlYiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl8wNDQwMzkzZTk2MTE0NTE5YjdmNjY4MTFkMmM3Y2FlYl9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfYWI1MTZlZDUxZDZhNGI3YTkyODY3YTVkNDNlYzZjYmEpOwogICAgICAgICAgICBnZW9fanNvbl8wNDQwMzkzZTk2MTE0NTE5YjdmNjY4MTFkMmM3Y2FlYi5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEyMDExNzE4NzUsIDQ1LjgzOTU1MTYwMTA1ODU5NV0sIFszLjEwOTEzMDg1OTM3NSwgNDUuODM1MTMyNDc1Njc1NV0sIFszLjEwOTEzMDg1OTM3NSwgNDUuODI2MjkzMTcyMDU0MjFdLCBbMy4xMjAxMTcxODc1LCA0NS44MjE4NzI5OTM4MTI5Ml0sIFszLjEzMTEwMzUxNTYyNSwgNDUuODI2MjkzMTcyMDU0MjFdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgzNTEzMjQ3NTY3NTVdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIG1hcmtlcl82YzU5NmYxMjAyMjg0YjgwYmNiYmQ5YjY0OGQ2Y2ZlOSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzQ1LjgzODEsIDMuMTIwNV0sCiAgICAgICAgICAgICAgICB7fQogICAgICAgICAgICApLmFkZFRvKG1hcF9hYjUxNmVkNTFkNmE0YjdhOTI4NjdhNWQ0M2VjNmNiYSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgbWFwX2FiNTE2ZWQ1MWQ2YTRiN2E5Mjg2N2E1ZDQzZWM2Y2JhLmZpdEJvdW5kcygKICAgICAgICAgICAgICAgIFtbNDUuODIxODcyOTkzODEyOTIsIDMuMTA5MTMwODU5Mzc1XSwgWzQ1LjgzOTU1MTYwMTA1ODU5NSwgMy4xMzExMDM1MTU2MjVdXSwKICAgICAgICAgICAgICAgIHt9CiAgICAgICAgICAgICk7CiAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x1fe1a901b70>"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m = folium.Map()\n",
"m.add_child(folium.GeoJson(hexg.to_geojson()))\n",
"m.add_child(folium.Marker([lat, lng]))\n",
"m.fit_bounds(m.get_bounds())\n",
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**WARNING** : To get a single coverage of the map, you must only select tiles for which `(x+y)%2==0` !"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2MyB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzIiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFswLCAwXSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDEsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl8xMjA0OTg5NTI3ZDk0NDkxOTIxNDU5YTFmNzE1ODE2NiA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiRGF0YSBieSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSwgdW5kZXIgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9EYkxcdTAwM2MvYVx1MDAzZS4iLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMpOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fNDlhOGIxZDllOTY4NGJjN2JhZDI0MGFiZmEyMTBjNTdfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2My5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl80OWE4YjFkOWU5Njg0YmM3YmFkMjQwYWJmYTIxMGM1NyA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl80OWE4YjFkOWU5Njg0YmM3YmFkMjQwYWJmYTIxMGM1N19vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMpOwogICAgICAgICAgICBnZW9fanNvbl80OWE4YjFkOWU5Njg0YmM3YmFkMjQwYWJmYTIxMGM1Ny5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjEyMDExNzE4NzUsIDQ1LjgzOTU1MTYwMTA1ODU5NV0sIFszLjEwOTEzMDg1OTM3NSwgNDUuODM1MTMyNDc1Njc1NV0sIFszLjEwOTEzMDg1OTM3NSwgNDUuODI2MjkzMTcyMDU0MjFdLCBbMy4xMjAxMTcxODc1LCA0NS44MjE4NzI5OTM4MTI5Ml0sIFszLjEzMTEwMzUxNTYyNSwgNDUuODI2MjkzMTcyMDU0MjFdLCBbMy4xMzExMDM1MTU2MjUsIDQ1LjgzNTEzMjQ3NTY3NTVdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl83YWJjNTJjMDc0Yjc0MmMxYmVkNWZjOTFjNzk4NGQ5ZV9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzdhYmM1MmMwNzRiNzQyYzFiZWQ1ZmM5MWM3OTg0ZDllID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzdhYmM1MmMwNzRiNzQyYzFiZWQ1ZmM5MWM3OTg0ZDllX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2Myk7CiAgICAgICAgICAgIGdlb19qc29uXzdhYmM1MmMwNzRiNzQyYzFiZWQ1ZmM5MWM3OTg0ZDllLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTIwMTE3MTg3NSwgNDUuODEzMDMxNTg0NDYxMTNdLCBbMy4xMDkxMzA4NTkzNzUsIDQ1LjgwODYxMDM1MzM0NzYxXSwgWzMuMTA5MTMwODU5Mzc1LCA0NS43OTk3NjY4MzgyMzc1MjRdLCBbMy4xMjAxMTcxODc1LCA0NS43OTUzNDQ1NTQyMzc5OF0sIFszLjEzMTEwMzUxNTYyNSwgNDUuNzk5NzY2ODM4MjM3NTI0XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MDg2MTAzNTMzNDc2MV1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2Q4MDI1MDhkMWIyMjQ2OWM4MzA3ZjNmYjA5ZTBkYjZiX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fZDgwMjUwOGQxYjIyNDY5YzgzMDdmM2ZiMDllMGRiNmIgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fZDgwMjUwOGQxYjIyNDY5YzgzMDdmM2ZiMDllMGRiNmJfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzKTsKICAgICAgICAgICAgZ2VvX2pzb25fZDgwMjUwOGQxYjIyNDY5YzgzMDdmM2ZiMDllMGRiNmIuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMjAxMTcxODc1LCA0NS43ODY0OTg5MzMzNDIyMV0sIFszLjEwOTEzMDg1OTM3NSwgNDUuNzgyMDc1NTk2NDQzMDRdLCBbMy4xMDkxMzA4NTkzNzUsIDQ1Ljc3MzIyNzg2OTczNDY2XSwgWzMuMTIwMTE3MTg3NSwgNDUuNzY4ODAzNDc5OTIyNTNdLCBbMy4xMzExMDM1MTU2MjUsIDQ1Ljc3MzIyNzg2OTczNDY2XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS43ODIwNzU1OTY0NDMwNF1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzJkY2Y2NzU3Njg4NDQ4OWRhMGY2YzRlOWZkMjRkZWU2X29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fMmRjZjY3NTc2ODg0NDg5ZGEwZjZjNGU5ZmQyNGRlZTYgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fMmRjZjY3NTc2ODg0NDg5ZGEwZjZjNGU5ZmQyNGRlZTZfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzKTsKICAgICAgICAgICAgZ2VvX2pzb25fMmRjZjY3NTc2ODg0NDg5ZGEwZjZjNGU5ZmQyNGRlZTYuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xMzExMDM1MTU2MjUsIDQ1LjgyNjI5MzE3MjA1NDIxXSwgWzMuMTIwMTE3MTg3NSwgNDUuODIxODcyOTkzODEyOTJdLCBbMy4xMjAxMTcxODc1LCA0NS44MTMwMzE1ODQ0NjExM10sIFszLjEzMTEwMzUxNTYyNSwgNDUuODA4NjEwMzUzMzQ3NjFdLCBbMy4xNDIwODk4NDM3NSwgNDUuODEzMDMxNTg0NDYxMTNdLCBbMy4xNDIwODk4NDM3NSwgNDUuODIxODcyOTkzODEyOTJdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl84ZjYzMTgzNDA5YzI0N2U0Yjc3NjQ3NGMxMzdjZTg3ZF9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzhmNjMxODM0MDljMjQ3ZTRiNzc2NDc0YzEzN2NlODdkID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzhmNjMxODM0MDljMjQ3ZTRiNzc2NDc0YzEzN2NlODdkX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2Myk7CiAgICAgICAgICAgIGdlb19qc29uXzhmNjMxODM0MDljMjQ3ZTRiNzc2NDc0YzEzN2NlODdkLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTMxMTAzNTE1NjI1LCA0NS43OTk3NjY4MzgyMzc1MjRdLCBbMy4xMjAxMTcxODc1LCA0NS43OTUzNDQ1NTQyMzc5OF0sIFszLjEyMDExNzE4NzUsIDQ1Ljc4NjQ5ODkzMzM0MjIxXSwgWzMuMTMxMTAzNTE1NjI1LCA0NS43ODIwNzU1OTY0NDMwNF0sIFszLjE0MjA4OTg0Mzc1LCA0NS43ODY0OTg5MzMzNDIyMV0sIFszLjE0MjA4OTg0Mzc1LCA0NS43OTUzNDQ1NTQyMzc5OF1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uX2FhNzZiMTMwOTg5NzQzZTdiMTczNjAxNzNjZGI2YTJlX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fYWE3NmIxMzA5ODk3NDNlN2IxNzM2MDE3M2NkYjZhMmUgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fYWE3NmIxMzA5ODk3NDNlN2IxNzM2MDE3M2NkYjZhMmVfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzKTsKICAgICAgICAgICAgZ2VvX2pzb25fYWE3NmIxMzA5ODk3NDNlN2IxNzM2MDE3M2NkYjZhMmUuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNDIwODk4NDM3NSwgNDUuODM5NTUxNjAxMDU4NTk1XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MzUxMzI0NzU2NzU1XSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MjYyOTMxNzIwNTQyMV0sIFszLjE0MjA4OTg0Mzc1LCA0NS44MjE4NzI5OTM4MTI5Ml0sIFszLjE1MzA3NjE3MTg3NSwgNDUuODI2MjkzMTcyMDU0MjFdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgzNTEzMjQ3NTY3NTVdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl85NzgyMWMyNGEzMzc0OWRhOTIxZTlkYzgwOWQ3OTMxMl9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzk3ODIxYzI0YTMzNzQ5ZGE5MjFlOWRjODA5ZDc5MzEyID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzk3ODIxYzI0YTMzNzQ5ZGE5MjFlOWRjODA5ZDc5MzEyX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2Myk7CiAgICAgICAgICAgIGdlb19qc29uXzk3ODIxYzI0YTMzNzQ5ZGE5MjFlOWRjODA5ZDc5MzEyLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTQyMDg5ODQzNzUsIDQ1LjgxMzAzMTU4NDQ2MTEzXSwgWzMuMTMxMTAzNTE1NjI1LCA0NS44MDg2MTAzNTMzNDc2MV0sIFszLjEzMTEwMzUxNTYyNSwgNDUuNzk5NzY2ODM4MjM3NTI0XSwgWzMuMTQyMDg5ODQzNzUsIDQ1Ljc5NTM0NDU1NDIzNzk4XSwgWzMuMTUzMDc2MTcxODc1LCA0NS43OTk3NjY4MzgyMzc1MjRdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1LjgwODYxMDM1MzM0NzYxXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fODljYTllYzNmN2U4NDBiZDg4NTgxY2ZmOGM2NmQ1NmJfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2My5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl84OWNhOWVjM2Y3ZTg0MGJkODg1ODFjZmY4YzY2ZDU2YiA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl84OWNhOWVjM2Y3ZTg0MGJkODg1ODFjZmY4YzY2ZDU2Yl9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMpOwogICAgICAgICAgICBnZW9fanNvbl84OWNhOWVjM2Y3ZTg0MGJkODg1ODFjZmY4YzY2ZDU2Yi5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE0MjA4OTg0Mzc1LCA0NS43ODY0OTg5MzMzNDIyMV0sIFszLjEzMTEwMzUxNTYyNSwgNDUuNzgyMDc1NTk2NDQzMDRdLCBbMy4xMzExMDM1MTU2MjUsIDQ1Ljc3MzIyNzg2OTczNDY2XSwgWzMuMTQyMDg5ODQzNzUsIDQ1Ljc2ODgwMzQ3OTkyMjUzXSwgWzMuMTUzMDc2MTcxODc1LCA0NS43NzMyMjc4Njk3MzQ2Nl0sIFszLjE1MzA3NjE3MTg3NSwgNDUuNzgyMDc1NTk2NDQzMDRdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl83ZTFkNGJlMzJjZTg0ZWJhYjcxNzFjNjc4MjRmYzVhM19vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uXzdlMWQ0YmUzMmNlODRlYmFiNzE3MWM2NzgyNGZjNWEzID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uXzdlMWQ0YmUzMmNlODRlYmFiNzE3MWM2NzgyNGZjNWEzX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2Myk7CiAgICAgICAgICAgIGdlb19qc29uXzdlMWQ0YmUzMmNlODRlYmFiNzE3MWM2NzgyNGZjNWEzLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTUzMDc2MTcxODc1LCA0NS44MjYyOTMxNzIwNTQyMV0sIFszLjE0MjA4OTg0Mzc1LCA0NS44MjE4NzI5OTM4MTI5Ml0sIFszLjE0MjA4OTg0Mzc1LCA0NS44MTMwMzE1ODQ0NjExM10sIFszLjE1MzA3NjE3MTg3NSwgNDUuODA4NjEwMzUzMzQ3NjFdLCBbMy4xNjQwNjI1LCA0NS44MTMwMzE1ODQ0NjExM10sIFszLjE2NDA2MjUsIDQ1LjgyMTg3Mjk5MzgxMjkyXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fNzQ1NDczZTRiZGNmNDQ5NzhhYmRiYTFhYjk1ODFlMjFfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2My5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl83NDU0NzNlNGJkY2Y0NDk3OGFiZGJhMWFiOTU4MWUyMSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl83NDU0NzNlNGJkY2Y0NDk3OGFiZGJhMWFiOTU4MWUyMV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMpOwogICAgICAgICAgICBnZW9fanNvbl83NDU0NzNlNGJkY2Y0NDk3OGFiZGJhMWFiOTU4MWUyMS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE1MzA3NjE3MTg3NSwgNDUuNzk5NzY2ODM4MjM3NTI0XSwgWzMuMTQyMDg5ODQzNzUsIDQ1Ljc5NTM0NDU1NDIzNzk4XSwgWzMuMTQyMDg5ODQzNzUsIDQ1Ljc4NjQ5ODkzMzM0MjIxXSwgWzMuMTUzMDc2MTcxODc1LCA0NS43ODIwNzU1OTY0NDMwNF0sIFszLjE2NDA2MjUsIDQ1Ljc4NjQ5ODkzMzM0MjIxXSwgWzMuMTY0MDYyNSwgNDUuNzk1MzQ0NTU0MjM3OThdXV0sICJ0eXBlIjogIlBvbHlnb24ifSk7CiAgICAgICAgCiAgICAKICAgICAgICBmdW5jdGlvbiBnZW9fanNvbl9hNTVmYjUyMzE2Nzg0NDZiOWNmMmUwMjgxNDY3ODlkZF9vbkVhY2hGZWF0dXJlKGZlYXR1cmUsIGxheWVyKSB7CiAgICAgICAgICAgIGxheWVyLm9uKHsKICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICAgICAgbWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzLmZpdEJvdW5kcyhlLnRhcmdldC5nZXRCb3VuZHMoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgICAgdmFyIGdlb19qc29uX2E1NWZiNTIzMTY3ODQ0NmI5Y2YyZTAyODE0Njc4OWRkID0gTC5nZW9Kc29uKG51bGwsIHsKICAgICAgICAgICAgICAgIG9uRWFjaEZlYXR1cmU6IGdlb19qc29uX2E1NWZiNTIzMTY3ODQ0NmI5Y2YyZTAyODE0Njc4OWRkX29uRWFjaEZlYXR1cmUsCiAgICAgICAgICAgIAogICAgICAgIH0pLmFkZFRvKG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2Myk7CiAgICAgICAgICAgIGdlb19qc29uX2E1NWZiNTIzMTY3ODQ0NmI5Y2YyZTAyODE0Njc4OWRkLmFkZERhdGEoeyJjb29yZGluYXRlcyI6IFtbWzMuMTY0MDYyNSwgNDUuODM5NTUxNjAxMDU4NTk1XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44MzUxMzI0NzU2NzU1XSwgWzMuMTUzMDc2MTcxODc1LCA0NS44MjYyOTMxNzIwNTQyMV0sIFszLjE2NDA2MjUsIDQ1LjgyMTg3Mjk5MzgxMjkyXSwgWzMuMTc1MDQ4ODI4MTI1LCA0NS44MjYyOTMxNzIwNTQyMV0sIFszLjE3NTA0ODgyODEyNSwgNDUuODM1MTMyNDc1Njc1NV1dXSwgInR5cGUiOiAiUG9seWdvbiJ9KTsKICAgICAgICAKICAgIAogICAgICAgIGZ1bmN0aW9uIGdlb19qc29uXzk1ZGZkMjRiOGJkZTQ0ZDBhZDQwNjc5ZmE2MmZjZGJkX29uRWFjaEZlYXR1cmUoZmVhdHVyZSwgbGF5ZXIpIHsKICAgICAgICAgICAgbGF5ZXIub24oewogICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgICAgICAgICBtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMuZml0Qm91bmRzKGUudGFyZ2V0LmdldEJvdW5kcygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgZ2VvX2pzb25fOTVkZmQyNGI4YmRlNDRkMGFkNDA2NzlmYTYyZmNkYmQgPSBMLmdlb0pzb24obnVsbCwgewogICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogZ2VvX2pzb25fOTVkZmQyNGI4YmRlNDRkMGFkNDA2NzlmYTYyZmNkYmRfb25FYWNoRmVhdHVyZSwKICAgICAgICAgICAgCiAgICAgICAgfSkuYWRkVG8obWFwXzlhN2QzNjhhYWVmZjRiZGI5NDU3ZjY5YTQ0NzIwZjYzKTsKICAgICAgICAgICAgZ2VvX2pzb25fOTVkZmQyNGI4YmRlNDRkMGFkNDA2NzlmYTYyZmNkYmQuYWRkRGF0YSh7ImNvb3JkaW5hdGVzIjogW1tbMy4xNjQwNjI1LCA0NS44MTMwMzE1ODQ0NjExM10sIFszLjE1MzA3NjE3MTg3NSwgNDUuODA4NjEwMzUzMzQ3NjFdLCBbMy4xNTMwNzYxNzE4NzUsIDQ1Ljc5OTc2NjgzODIzNzUyNF0sIFszLjE2NDA2MjUsIDQ1Ljc5NTM0NDU1NDIzNzk4XSwgWzMuMTc1MDQ4ODI4MTI1LCA0NS43OTk3NjY4MzgyMzc1MjRdLCBbMy4xNzUwNDg4MjgxMjUsIDQ1LjgwODYxMDM1MzM0NzYxXV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgZnVuY3Rpb24gZ2VvX2pzb25fNjAwMjdiZGJiMTRkNGQzZjkyYjVmNmE4NThmYjVjMzVfb25FYWNoRmVhdHVyZShmZWF0dXJlLCBsYXllcikgewogICAgICAgICAgICBsYXllci5vbih7CiAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgICAgICAgIG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2My5maXRCb3VuZHMoZS50YXJnZXQuZ2V0Qm91bmRzKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIHZhciBnZW9fanNvbl82MDAyN2JkYmIxNGQ0ZDNmOTJiNWY2YTg1OGZiNWMzNSA9IEwuZ2VvSnNvbihudWxsLCB7CiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBnZW9fanNvbl82MDAyN2JkYmIxNGQ0ZDNmOTJiNWY2YTg1OGZiNWMzNV9vbkVhY2hGZWF0dXJlLAogICAgICAgICAgICAKICAgICAgICB9KS5hZGRUbyhtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMpOwogICAgICAgICAgICBnZW9fanNvbl82MDAyN2JkYmIxNGQ0ZDNmOTJiNWY2YTg1OGZiNWMzNS5hZGREYXRhKHsiY29vcmRpbmF0ZXMiOiBbW1szLjE2NDA2MjUsIDQ1Ljc4NjQ5ODkzMzM0MjIxXSwgWzMuMTUzMDc2MTcxODc1LCA0NS43ODIwNzU1OTY0NDMwNF0sIFszLjE1MzA3NjE3MTg3NSwgNDUuNzczMjI3ODY5NzM0NjZdLCBbMy4xNjQwNjI1LCA0NS43Njg4MDM0Nzk5MjI1M10sIFszLjE3NTA0ODgyODEyNSwgNDUuNzczMjI3ODY5NzM0NjZdLCBbMy4xNzUwNDg4MjgxMjUsIDQ1Ljc4MjA3NTU5NjQ0MzA0XV1dLCAidHlwZSI6ICJQb2x5Z29uIn0pOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBtYXJrZXJfZjliODQ1MmU3Nzg0NDNmODkzMjAyYjYyNDk5ZDg3NDQgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFs0NS44MzgxLCAzLjEyMDVdLAogICAgICAgICAgICAgICAge30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfOWE3ZDM2OGFhZWZmNGJkYjk0NTdmNjlhNDQ3MjBmNjMpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIG1hcF85YTdkMzY4YWFlZmY0YmRiOTQ1N2Y2OWE0NDcyMGY2My5maXRCb3VuZHMoCiAgICAgICAgICAgICAgICBbWzQ1Ljc2ODgwMzQ3OTkyMjUzLCAzLjEwOTEzMDg1OTM3NV0sIFs0NS44Mzk1NTE2MDEwNTg1OTUsIDMuMTc1MDQ4ODI4MTI1XV0sCiAgICAgICAgICAgICAgICB7fQogICAgICAgICAgICApOwogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x1fe1a9135c0>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m = folium.Map()\n",
"for i in range(5):\n",
" for j in range(5):\n",
" if (i + j) % 2 == 0:\n",
" m.add_child(folium.GeoJson(tiles.HexagonalTile(hexg.x + i, hexg.y + j, hexg.z).to_geojson()))\n",
"m.add_child(folium.Marker([lat, lng]))\n",
"m.fit_bounds(m.get_bounds())\n",
"m"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
import numpy as np
import pandas as pd
def mercator(lat):
"""Map latitudes (in deg) to Mercator projection.
(Between -1 and 1 for latitudes between -85.05 and +85.05).
"""
return np.arcsinh(np.tan(lat * np.pi / 180.)) / np.pi
def mercator_inv(x):
"""Map Mercator "longitudes" to DEG-longitudes."""
return np.arctan(np.sinh(x * np.pi)) * 180 / np.pi
porte_de_dijon = (45.8381, 3.1205) # A GPS position to make tests
def to_hash(x, y, z, prefix=1):
"""Hash the values of x and y in an single int.
If x = 0bXXXXXX and y = 0bYYYYYY,
then the output's binary string will be : bin(prefix) + "XYXYXYXYXY".
"""
assert prefix in [1, 2, 3]
return (
int('0'.join(bin(x)[2:])+'0', 2) + int('0'.join(bin(y)[2:]), 2) + prefix * 2**(2*z)
)
def from_hash(n):
if n in (1,2,3):
return 0,0,0,n
s = bin(n)[2:]
if len(s)%2:
prefix, suffix = int(s[:1], 2), s[1:]
else:
prefix, suffix = int(s[:2], 2), s[2:]
return int(suffix[::2], 2), int(suffix[1::2], 2), len(suffix)//2, prefix
def tile_from_hash(n):
x, y, z, prefix = from_hash(n)
if prefix == 1:
return SquareTile(x, y, z)
if prefix == 2:
return TriangleTile(x, y, z)
if prefix == 3:
return HexagonalTile(x, y, z)
def test_hash_function():
assert bin(to_hash(0,0,5)) == '0b10000000000'
assert bin(to_hash(31,0,5)) == '0b11010101010'
assert bin(to_hash(0,31,5)) == '0b10101010101'
assert bin(to_hash(31,31,5)) == '0b11111111111'
assert bin(to_hash(0,0,5,2)) == '0b100000000000'
assert bin(to_hash(31,0,5,2)) == '0b101010101010'
assert bin(to_hash(0,31,5,2)) == '0b100101010101'
assert bin(to_hash(31,31,5,2)) == '0b101111111111'
for n in range(4, 10000):
assert to_hash(*from_hash(n)) == n, n
i = 0
for z in range(8):
for prefix in range(1,4):
for x in range(2**z):
for y in range(2**z):
i += 1
assert from_hash(to_hash(x, y, z, prefix)) == (x, y, z, prefix), (x, y, z, prefix)
class Tile(object):
def __init__(self, x, y, z):
self.x = int(x)
self.y = int(y)
self.z = int(z)
def to_string(self, include_zoom=True):
if include_zoom:
return '{}/{}/{}'.format(self.z, self.x, self.y)
else:
return '{}/{}'.format(self.x, self.y)
def to_tuple(self, include_zoom=True):
if include_zoom:
return (self.z, self.x, self.y)
else:
return (self.x, self.y)
def vertex(self):
raise NotImplementedError()
def to_geojson(self):
return { "type": "Polygon", "coordinates": [[x[::-1] for x in self.vertex()]]}
class SquareTile(Tile):
def from_lat_lng(lat, lng, zoom):
x, y = (lng + 180) / 360, (1 - mercator(lat)) / 2 # x=0-1, y=1-0
return SquareTile(int(x * 2**zoom), int(y * 2**zoom), zoom)
def central_point(self):
x = (self.x + 0.5) / 2**self.z
y = (self.y + 0.5) / 2**self.z
return mercator_inv(1 - y * 2), x * 360 - 180
def vertex(self):
return [
[mercator_inv(1 - (self.y + j) / 2**self.z * 2), (self.x + i) / 2**self.z * 360 - 180]
for i, j in zip([0, 1, 1, 0], [0, 0, 1, 1])]
def to_hash(self):
prefix = 1
return to_hash(self.x, self.y, self.z, prefix=prefix)
def test_square_tile():
z = 18
s = SquareTile.from_lat_lng(*porte_de_dijon, z)
sc = s.central_point()
assert SquareTile.from_lat_lng(*sc, z).central_point() == sc
class TriangleTile(Tile):
def from_lat_lng(lat, lng, zoom):
x, y = (lng + 180) / 360, (0.5 - mercator(lat)*0.5/np.sqrt(3))
dx, mx = divmod(x * 2**zoom, 1)
dy, my = divmod(y * 2**zoom, 1)
if (dx + dy) % 2 == 0:
return TriangleTile(int(dx + (mx>my)), int(dy), zoom)
else:
return TriangleTile(int(dx + (mx>1-my)), int(dy), zoom)
def _transform(self, lat, lng):
"""transforms latitude and longitude into variables x and y,
so that a tile will have width and heaight equal to 1."""
return (
(lng + 180) / 360 * 2**self.z,
(1 - mercator(lat)/np.sqrt(3)) / 2 * 2**self.z
)
def _transform_inv(self, x, y):
"""transforms latitude and longitude into variables x and y,
so that a tile will have width and heaight equal to 1."""
return (
mercator_inv((1 - 2 * y / 2**self.z) * np.sqrt(3)),
x / 2**self.z * 360 - 180
)
def central_point(self):
x = self.x
if int(self.x + self.y) % 2 == 0: # triangle pointing up
y = (self.y + 2/3)
else:
y = (self.y + 1/3)
return self._transform_inv(x, y)
def vertex(self):
if int(self.x + self.y) % 2 == 0: # triangle pointing up
dys = [1, 0, 1]
else:
dys = [0, 1, 0]
return [
self._transform_inv(self.x + dx, self.y + dy)
for dx, dy in zip([-1, 0, 1], dys)]
def to_hash(self):
prefix = 2
return to_hash(self.x, self.y, self.z, prefix=prefix)
def test_triangle_tile():
z = 18
t = TriangleTile.from_lat_lng(*porte_de_dijon, z)
tc = t.central_point()
assert TriangleTile.from_lat_lng(*tc, z).central_point() == tc
assert t._transform(*t._transform_inv(t.x, t.y)) == (t.x, t.y)
assert (
np.round(t._transform_inv(*t._transform(*porte_de_dijon)), 10) == np.round(porte_de_dijon, 10)
).all()
class HexagonalTile(Tile):
def from_lat_lng(lat, lng, zoom):
x, y = (lng + 180) / 360, (0.5 - mercator(lat)*0.5/np.sqrt(3))
dx, mx = divmod(x * 2**zoom, 1)
dy, my = divmod(y * 2**zoom, 1)
if (dx + dy) % 2 == 0:
if mx < 2 - 3 * my:
return HexagonalTile(int(dx), int(dy), zoom)
else:
return HexagonalTile(int(dx+1), int(dy+1), zoom)
else:
if 1 - mx < 2 - 3 * my:
return HexagonalTile(int(dx+1), int(dy), zoom)
else:
return HexagonalTile(int(dx), int(dy+1), zoom)
def _transform(self, lat, lng):
"""transforms latitude and longitude into variables x and y,
so that a tile will have width and heaight equal to 1."""
return (
(lng + 180) / 360 * 2**self.z,
(1 - mercator(lat)/np.sqrt(3)) / 2 * 2**self.z
)
def _transform_inv(self, x, y):
"""transforms latitude and longitude into variables x and y,
so that a tile will have width and heaight equal to 1."""
return (
mercator_inv((1 - 2 * y / 2**self.z) * np.sqrt(3)),
x / 2**self.z * 360 - 180
)
def central_point(self):
x = self.x
y = self.y
#if int(self.x + self.y) % 2 == 0: # triangle pointing up
# y = (self.y + 2/3)
#else:
# y = (self.y + 1/3)
return self._transform_inv(x, y)
def vertex(self):
dxs = np.array([0, -1, -1, 0, 1, 1])
dys = np.array([-2, -1, 1, 2, 1, -1]) / 3
#if int(self.x + self.y) % 2 == 0: # triangle pointing up
# dys = [1, 0, 1]
#else:
# dys = [0, 1, 0]
return [
self._transform_inv(self.x + dx, self.y + dy)
for dx, dy in zip(dxs, dys)]
def to_hash(self):
prefix = 3
return to_hash(self.x, self.y, self.z, prefix=prefix)
def test_hexagon_tile():
z = 18
t = HexagonalTile.from_lat_lng(*porte_de_dijon, z)
tc = t.central_point()
assert HexagonalTile.from_lat_lng(*tc, z).central_point() == tc
assert t._transform(*t._transform_inv(t.x, t.y)) == (t.x, t.y)
assert (
np.round(t._transform_inv(*t._transform(*porte_de_dijon)), 10) == np.round(porte_de_dijon, 10)
).all()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment