Another unambiguous fractal treemap, this time a very small one.
Last active
January 2, 2016 10:28
-
-
Save nitaku/8289840 to your computer and use it in GitHub Desktop.
Fractal treemap of Kyupapa (321 leaves)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
from itertools import izip | |
import csv | |
import json | |
from shapely.geometry.polygon import Polygon | |
import shapely.wkt | |
from fiona import collection | |
from shapely.geometry import mapping | |
import re | |
import os | |
# yield the leaves of the tree, also computing each leaf path | |
def leafify(node, path=()): | |
if 'c' not in node: | |
node['path'] = path + (node,) | |
yield node | |
else: | |
for c in node['c']: | |
for l in leafify(c, path + (node,)): | |
yield l | |
def gosperify(tree_path, hexes_path, output_regions_dir_path, depth_filename): | |
leaves_done = 0 | |
layers = {} | |
depth_levels = {} | |
print('Reading the tree...') | |
with open(tree_path, 'rb') as tree_file: | |
tree = json.loads(tree_file.read()) | |
print('Reading hexes...') | |
# iterate over the hexes taken from the file | |
with open(hexes_path, 'rb') as hexes_file: | |
hexes_reader = csv.reader(hexes_file, delimiter=';', quotechar='#') | |
for leaf, hexes_row in izip(leafify(tree), hexes_reader): | |
path = leaf['path'] | |
hex = shapely.wkt.loads(hexes_row[0]) | |
for depth in xrange(len(path)): | |
# add the hex to its political regions | |
ancestor_or_self = path[depth] | |
if depth not in layers: | |
layers[depth] = {} | |
if id(ancestor_or_self) not in layers[depth]: | |
layers[depth][id(ancestor_or_self)] = { | |
'geometry': hex, | |
'node': ancestor_or_self | |
} | |
else: | |
layers[depth][id(ancestor_or_self)]['geometry'] = layers[depth][id(ancestor_or_self)]['geometry'].union(hex) | |
# add the hex to all the depth levels with d <= depth | |
if depth not in depth_levels: | |
depth_levels[depth] = hex | |
else: | |
depth_levels[depth] = depth_levels[depth].union(hex) | |
# logging | |
leaves_done += 1 | |
print('%d leaves done' % leaves_done, end='\r') | |
print('Writing political regions...') | |
schema = {'geometry': 'Polygon', 'properties': {'label': 'str'}} | |
if not os.path.exists(output_regions_dir_path): | |
os.makedirs(output_regions_dir_path) | |
for depth, regions in layers.items(): | |
with collection(output_regions_dir_path+'/'+str(depth)+'.json', 'w', 'GeoJSON', schema) as output: | |
for _, region_obj in regions.items(): | |
output.write({ | |
'properties': { | |
'label': region_obj['node']['l'] | |
}, | |
'geometry': mapping(region_obj['geometry']) | |
}) | |
print('Writing depth_levels...') | |
schema = {'geometry': 'Polygon', 'properties': {'depth': 'int'}} | |
with collection(depth_filename, 'w', 'GeoJSON', schema) as output: | |
for depth, region in depth_levels.items(): | |
output.write({ | |
'properties': { | |
'depth': depth | |
}, | |
'geometry': mapping(region) | |
}) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
concat = (a) -> a.reduce ((a,o) -> a.concat(o)), [] | |
window.main = () -> | |
### "globals" ### | |
vis = null | |
width = 960 | |
height = 500 | |
svg = d3.select('body').append('svg') | |
.attr('width', width) | |
.attr('height', height) | |
### ZOOM and PAN ### | |
### create container elements ### | |
container = svg.append('g') | |
.attr('transform','translate(470, 136)') | |
container.call(d3.behavior.zoom().scaleExtent([1, 49]).on('zoom', (() -> vis.attr('transform', "translate(#{d3.event.translate})scale(#{d3.event.scale})")))) | |
vis = container.append('g') | |
### create a rectangular overlay to catch events ### | |
### WARNING rect size is huge but not infinite. this is a dirty hack ### | |
vis.append('rect') | |
.attr('class', 'overlay') | |
.attr('x', -500000) | |
.attr('y', -500000) | |
.attr('width', 1000000) | |
.attr('height', 1000000) | |
### END ZOOM and PAN ### | |
### custom projection to make hexagons appear regular (y axis is also flipped) ### | |
radius = 6 | |
dx = radius * 2 * Math.sin(Math.PI / 3) | |
dy = radius * 1.5 | |
path_generator = d3.geo.path() | |
.projection d3.geo.transform({ | |
point: (x,y) -> | |
this.stream.point(x * dx / 2, -(y - (2 - (y & 1)) / 3) * dy / 2) | |
}) | |
### depth scale ### | |
whiteness = 0.6 | |
whiten = (color) -> d3.interpolateHcl(color, d3.hcl(undefined,0,100))(whiteness) | |
colorify = d3.scale.quantize() | |
.domain([0..9]) | |
.range(['#396353','#0DB14B','#6DC067','#ABD69B','#DAEAC1','#DFCCE4','#C7B2D6','#9474B4','#754098','#504971'].map(whiten)) | |
# .range(['#59A80F','#9ED54C','#C4ED68','#E2FF9E','#F0F2DD','#F8CA8C','#E9A189','#D47384','#AC437B','#8C286E']) | |
# .range(['#FFFCF6','#FFF7DB','#FFF4C2','#FEECAE','#F8CA8C','#F0A848','#C07860','#A86060','#784860','#604860']) | |
### legend ### | |
legend = svg.append('g') | |
.attr('id','legend') | |
.attr('transform', 'translate(30,20)') | |
scale = [colorify.domain()[0]..colorify.domain()[1]] | |
categories = legend.selectAll('.category') | |
.data(scale) | |
.enter().append('g') | |
.attr('class', 'category') | |
.attr('transform', (d,i) -> "translate(0,#{i*22})") | |
categories.append('rect') | |
.attr('x', 0).attr('y', 0) | |
.attr('width', 22).attr('height', 22) | |
.attr('fill', (d) -> colorify(d)) | |
categories.append('text') | |
.attr('y', 11) | |
.attr('dx', -4) | |
.attr('dy', '0.35em') | |
.text((d) -> d) | |
### load topoJSON data ### | |
d3.json 'regions_depth.topo.json', (error, data) -> | |
### write the name of the land ### | |
title = svg.append('text') | |
.attr('class', 'title') | |
.text(topojson.feature(data, data.objects['0']).features[0].properties.label) | |
.attr('transform', 'translate(80,40)') | |
### define the level zero region (the land) ### | |
defs = svg.append('defs') | |
defs.append('path') | |
.datum(topojson.feature(data, data.objects['0']).features[0]) | |
.attr('id', 'land') | |
.attr('d', path_generator) | |
### faux land glow (using filters takes too much resources) ### | |
vis.append('use') | |
.attr('class', 'land-glow-outer') | |
.attr('xlink:href', '#land') | |
vis.append('use') | |
.attr('class', 'land-glow-inner') | |
.attr('xlink:href', '#land') | |
### draw the depth levels ### | |
vis.selectAll('.contour') | |
.data(topojson.feature(data, data.objects.depth).features) | |
.enter().append('path') | |
.attr('class', 'contour') | |
.attr('d', path_generator) | |
.attr('fill', (d) -> colorify(d.properties.depth)) | |
### draw the land border ### | |
vis.append('use') | |
.attr('class', 'land-fill') | |
.attr('xlink:href', '#land') | |
### draw the political boundaries ### | |
for depth in [1..2] | |
vis.append('path') | |
.datum(topojson.mesh(data, data.objects[depth], ((a,b) -> a isnt b))) | |
.attr('d', path_generator) | |
.attr('class', 'boundary') | |
.style('stroke-width', "#{1.8/depth}px") | |
### draw the other labels ### | |
vis.selectAll('.label') | |
.data(concat((topojson.feature(data, data.objects[depth]).features.map((d) -> {feature: d, depth: depth}) for depth in [2..1]))) | |
.enter().append('text') | |
.attr('class', 'label') | |
.attr('dy','0.35em') | |
.attr('transform', ((d) -> | |
centroid = path_generator.centroid(d.feature) | |
area = path_generator.area(d.feature) | |
return "translate(#{centroid[0]},#{centroid[1]}) scale(#{10/d.depth})" | |
)) | |
.text((d) -> d.feature.properties.label) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#land { | |
fill: none; | |
} | |
.land-glow-outer { | |
stroke: #eeeeee; | |
stroke-width: 16px; | |
} | |
.land-glow-inner { | |
stroke: #dddddd; | |
stroke-width: 8px; | |
} | |
.land-fill { | |
stroke: #444444; | |
stroke-width: 2px; | |
} | |
.contour { | |
stroke: none; | |
} | |
.category text { | |
text-anchor: end; | |
fill: #444444; | |
font-family: sans-serif; | |
font-weight: bold; | |
font-size: 14px; | |
pointer-events: none; | |
text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white; | |
} | |
.boundary { | |
stroke: #444444; | |
fill: none; | |
pointer-events: none; | |
} | |
@font-face { | |
font-family: "Lacuna"; | |
src: url("lacuna.ttf"); | |
} | |
.label { | |
text-transform: capitalize; | |
text-anchor: middle; | |
font-size: 2.5px; | |
fill: #444444; | |
pointer-events: none; | |
font-family: "Lacuna"; | |
text-shadow: -2px 0 white, 0 2px white, 2px 0 white, 0 -2px white, -1px -1px white, 1px -1px white, 1px 1px white, -1px 1px white; | |
} | |
.title { | |
text-transform: capitalize; | |
text-anchor: start; | |
font-size: 24pt; | |
fill: #444444; | |
pointer-events: none; | |
font-family: "Lacuna"; | |
text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white; | |
} | |
.overlay { | |
fill: transparent; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Fractal treemap - Kyupapa (321)</title> | |
<link type="text/css" href="index.css" rel="stylesheet"/> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://d3js.org/topojson.v1.min.js"></script> | |
<script src="index.js"></script> | |
</head> | |
<body onload="main()"> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
var concat; | |
concat = function(a) { | |
return a.reduce((function(a, o) { | |
return a.concat(o); | |
}), []); | |
}; | |
window.main = function() { | |
/* "globals" | |
*/ | |
var categories, colorify, container, dx, dy, height, legend, path_generator, radius, scale, svg, vis, whiten, whiteness, width, _i, _ref, _ref2, _results; | |
vis = null; | |
width = 960; | |
height = 500; | |
svg = d3.select('body').append('svg').attr('width', width).attr('height', height); | |
/* ZOOM and PAN | |
*/ | |
/* create container elements | |
*/ | |
container = svg.append('g').attr('transform', 'translate(470, 136)'); | |
container.call(d3.behavior.zoom().scaleExtent([1, 49]).on('zoom', (function() { | |
return vis.attr('transform', "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); | |
}))); | |
vis = container.append('g'); | |
/* create a rectangular overlay to catch events | |
*/ | |
/* WARNING rect size is huge but not infinite. this is a dirty hack | |
*/ | |
vis.append('rect').attr('class', 'overlay').attr('x', -500000).attr('y', -500000).attr('width', 1000000).attr('height', 1000000); | |
/* END ZOOM and PAN | |
*/ | |
/* custom projection to make hexagons appear regular (y axis is also flipped) | |
*/ | |
radius = 6; | |
dx = radius * 2 * Math.sin(Math.PI / 3); | |
dy = radius * 1.5; | |
path_generator = d3.geo.path().projection(d3.geo.transform({ | |
point: function(x, y) { | |
return this.stream.point(x * dx / 2, -(y - (2 - (y & 1)) / 3) * dy / 2); | |
} | |
})); | |
/* depth scale | |
*/ | |
whiteness = 0.6; | |
whiten = function(color) { | |
return d3.interpolateHcl(color, d3.hcl(void 0, 0, 100))(whiteness); | |
}; | |
colorify = d3.scale.quantize().domain([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).range(['#396353', '#0DB14B', '#6DC067', '#ABD69B', '#DAEAC1', '#DFCCE4', '#C7B2D6', '#9474B4', '#754098', '#504971'].map(whiten)); | |
/* legend | |
*/ | |
legend = svg.append('g').attr('id', 'legend').attr('transform', 'translate(30,20)'); | |
scale = (function() { | |
_results = []; | |
for (var _i = _ref = colorify.domain()[0], _ref2 = colorify.domain()[1]; _ref <= _ref2 ? _i <= _ref2 : _i >= _ref2; _ref <= _ref2 ? _i++ : _i--){ _results.push(_i); } | |
return _results; | |
}).apply(this); | |
categories = legend.selectAll('.category').data(scale).enter().append('g').attr('class', 'category').attr('transform', function(d, i) { | |
return "translate(0," + (i * 22) + ")"; | |
}); | |
categories.append('rect').attr('x', 0).attr('y', 0).attr('width', 22).attr('height', 22).attr('fill', function(d) { | |
return colorify(d); | |
}); | |
categories.append('text').attr('y', 11).attr('dx', -4).attr('dy', '0.35em').text(function(d) { | |
return d; | |
}); | |
/* load topoJSON data | |
*/ | |
return d3.json('regions_depth.topo.json', function(error, data) { | |
/* write the name of the land | |
*/ | |
var defs, depth, title; | |
title = svg.append('text').attr('class', 'title').text(topojson.feature(data, data.objects['0']).features[0].properties.label).attr('transform', 'translate(80,40)'); | |
/* define the level zero region (the land) | |
*/ | |
defs = svg.append('defs'); | |
defs.append('path').datum(topojson.feature(data, data.objects['0']).features[0]).attr('id', 'land').attr('d', path_generator); | |
/* faux land glow (using filters takes too much resources) | |
*/ | |
vis.append('use').attr('class', 'land-glow-outer').attr('xlink:href', '#land'); | |
vis.append('use').attr('class', 'land-glow-inner').attr('xlink:href', '#land'); | |
/* draw the depth levels | |
*/ | |
vis.selectAll('.contour').data(topojson.feature(data, data.objects.depth).features).enter().append('path').attr('class', 'contour').attr('d', path_generator).attr('fill', function(d) { | |
return colorify(d.properties.depth); | |
}); | |
/* draw the land border | |
*/ | |
vis.append('use').attr('class', 'land-fill').attr('xlink:href', '#land'); | |
/* draw the political boundaries | |
*/ | |
for (depth = 1; depth <= 2; depth++) { | |
vis.append('path').datum(topojson.mesh(data, data.objects[depth], (function(a, b) { | |
return a !== b; | |
}))).attr('d', path_generator).attr('class', 'boundary').style('stroke-width', "" + (1.8 / depth) + "px"); | |
} | |
/* draw the other labels | |
*/ | |
return vis.selectAll('.label').data(concat((function() { | |
var _results2; | |
_results2 = []; | |
for (depth = 2; depth >= 1; depth--) { | |
_results2.push(topojson.feature(data, data.objects[depth]).features.map(function(d) { | |
return { | |
feature: d, | |
depth: depth | |
}; | |
})); | |
} | |
return _results2; | |
})())).enter().append('text').attr('class', 'label').attr('dy', '0.35em').attr('transform', (function(d) { | |
var area, centroid; | |
centroid = path_generator.centroid(d.feature); | |
area = path_generator.area(d.feature); | |
return "translate(" + centroid[0] + "," + centroid[1] + ") scale(" + (10 / d.depth) + ")"; | |
})).text(function(d) { | |
return d.feature.properties.label; | |
}); | |
}); | |
}; | |
}).call(this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@mixin halo($color) | |
text-shadow: -1px 0 $color, 0 1px $color, 1px 0 $color, 0 -1px $color | |
@mixin halo_double($color) | |
text-shadow: -2px 0 $color, 0 2px $color, 2px 0 $color, 0 -2px $color, -1px -1px $color, 1px -1px $color, 1px 1px $color, -1px 1px $color | |
#land | |
fill: none | |
.land-glow-outer | |
stroke: #EEE | |
stroke-width: 16px | |
.land-glow-inner | |
stroke: #DDD | |
stroke-width: 8px | |
.land-fill | |
stroke: #444 | |
stroke-width: 2px | |
.contour | |
stroke: none | |
.category text | |
text-anchor: end | |
fill: #444 | |
font-family: sans-serif | |
font-weight: bold | |
font-size: 14px | |
pointer-events: none | |
@include halo(white) | |
.boundary | |
stroke: #444 | |
fill: none | |
// avoid blinking when hovering regions | |
pointer-events: none | |
@font-face | |
font-family: 'Lacuna' | |
src: url('lacuna.ttf') | |
.label | |
text-transform: capitalize | |
text-anchor: middle | |
font-size: 2.5px | |
fill: #444 | |
pointer-events: none | |
font-family: 'Lacuna' | |
@include halo_double(white) | |
.title | |
text-transform: capitalize | |
text-anchor: start | |
font-size: 24pt | |
fill: #444 | |
pointer-events: none | |
font-family: 'Lacuna' | |
@include halo(white) | |
// zoom and pan | |
.overlay | |
fill: transparent |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"c": [{"c": [{"c": [{"c": [{"c": [{"l": "fokata"}, {"c": [{"l": "pasizoma"}, {"l": "arfusiopa"}], "l": "pafle"}, {"c": [{"l": "piibotri"}, {"l": "anflebugolu"}, {"l": "kyana"}, {"l": "koflenopi"}, {"c": [{"l": "aressibi"}], "l": "kyasu"}, {"l": "busifoko"}], "l": "sipa"}, {"l": "esse"}, {"l": "kanapakyu"}], "l": "kasuleno"}, {"c": [{"l": "sefle"}, {"l": "oo"}], "l": "boes"}, {"l": "mabu"}, {"l": "subuisu"}], "l": "sebu"}, {"l": "noketrike"}], "l": "gokafu"}, {"l": "zoosulu"}], "l": "gofunelu"}, {"c": [{"l": "luflenonopa"}, {"c": [{"c": [{"l": "fugonoango"}], "l": "esflesulupe"}, {"l": "lufo"}], "l": "pakasubono"}, {"c": [{"l": "kabutazo"}, {"l": "iboilui"}, {"l": "kyasufo"}, {"l": "futafufo"}, {"c": [{"l": "fletrikonape"}, {"c": [{"c": [{"l": "nokyanapa"}, {"c": [{"l": "komasuanne"}, {"l": "learbimano"}, {"l": "keflo"}, {"l": "flekekezo"}], "l": "tabu"}, {"l": "annoluarfo"}, {"l": "arseluflo"}, {"l": "taisi"}, {"l": "pifuanpa"}, {"c": [{"l": "tapi"}, {"l": "luopa"}], "l": "flepearnai"}], "l": "trisebibobi"}, {"c": [{"l": "estri"}, {"l": "fubifle"}, {"l": "nafubu"}, {"l": "nopale"}, {"c": [{"l": "napi"}, {"l": "zoflenafo"}], "l": "okyukyu"}, {"l": "kyukebole"}, {"l": "tase"}], "l": "pamasesi"}, {"l": "koespi"}, {"l": "tanepaflean"}, {"l": "notritai"}, {"l": "osi"}], "l": "artrikepa"}, {"l": "nakefotale"}, {"l": "kyapa"}], "l": "bumalu"}, {"l": "buanmago"}], "l": "koboarma"}, {"c": [{"l": "sigofumatri"}, {"c": [{"l": "lusike"}, {"l": "fogo"}, {"c": [{"c": [{"l": "flepiespibu"}, {"l": "okaarzosi"}, {"l": "floanta"}, {"c": [{"l": "kataan"}, {"l": "zonoluta"}, {"l": "anbu"}, {"l": "nosina"}], "l": "sekyubupe"}, {"l": "omabu"}, {"l": "esma"}, {"l": "nofumaflo"}], "l": "nobu"}], "l": "kyaflofupina"}], "l": "nesibo"}, {"c": [{"c": [{"c": [{"l": "flomaflepi"}, {"l": "butaflean"}, {"l": "trisibimafo"}, {"l": "lekakafu"}], "l": "arsegotako"}, {"l": "mabubotrise"}, {"c": [{"l": "seno"}, {"l": "fuan"}, {"c": [{"l": "anlebies"}, {"l": "fobule"}, {"l": "arbifoneno"}, {"l": "pekyatribule"}], "l": "manakaluflo"}, {"l": "peflolebiko"}, {"l": "kyuan"}], "l": "sikale"}, {"c": [{"c": [{"l": "pesuzofu"}, {"l": "goigo"}, {"l": "segoikeno"}, {"l": "peibigo"}, {"l": "keesgoeses"}, {"l": "nole"}], "l": "suifose"}, {"c": [{"l": "fokoesar"}, {"l": "nakyu"}, {"l": "buo"}, {"l": "sigotrise"}, {"l": "kana"}, {"l": "boanflefo"}], "l": "trinose"}], "l": "senesupe"}], "l": "tritaesfle"}, {"c": [{"c": [{"c": [{"l": "flolu"}, {"l": "flelunearne"}, {"l": "kokaise"}, {"l": "lupaflo"}, {"l": "bufufono"}], "l": "trikyusefle"}, {"l": "koflo"}, {"l": "masesepepi"}, {"l": "kose"}], "l": "sumapifo"}], "l": "paluar"}], "l": "esfukezobi"}, {"c": [{"l": "ibi"}, {"l": "zobi"}, {"c": [{"l": "anpebufloi"}, {"c": [{"c": [{"l": "nenope"}, {"l": "subuneno"}, {"l": "nabuzo"}, {"l": "arisitripe"}, {"l": "flear"}, {"l": "neke"}, {"l": "lese"}], "l": "piesanle"}, {"c": [{"l": "konake"}], "l": "buko"}, {"c": [{"l": "kyupebina"}, {"l": "selene"}], "l": "kyutatrio"}, {"l": "fosi"}, {"l": "keo"}], "l": "ifleanse"}, {"l": "anma"}, {"l": "estri"}], "l": "itrika"}, {"c": [{"l": "kyupikoesse"}, {"c": [{"l": "talukyaka"}], "l": "sepabule"}], "l": "peimakaes"}, {"c": [{"c": [{"l": "takakyuflo"}, {"c": [{"l": "pakyu"}, {"l": "kago"}, {"l": "floflokyanezo"}, {"l": "arpaigo"}, {"l": "nefle"}], "l": "arsu"}, {"c": [{"l": "near"}], "l": "osesu"}, {"l": "bieskyaka"}, {"l": "flokapitano"}, {"l": "fupaflofletri"}], "l": "nasi"}, {"l": "zosubuke"}, {"l": "kesipian"}, {"l": "fuzo"}, {"c": [{"l": "sufoopibi"}], "l": "biipa"}], "l": "zoes"}], "l": "suseo"}], "l": "fuzotrisilu"}, {"c": [{"l": "keseotries"}, {"l": "petafopasi"}, {"c": [{"c": [{"c": [{"l": "piose"}, {"l": "luko"}, {"l": "imaes"}, {"l": "anpego"}], "l": "esna"}, {"c": [{"l": "futri"}, {"l": "keoarkya"}, {"l": "bobimape"}, {"l": "paanfoitri"}], "l": "pekotrisu"}, {"l": "nalugonesi"}, {"l": "pao"}, {"l": "bisugogo"}, {"c": [{"l": "ipaar"}, {"c": [{"l": "fleke"}, {"l": "siflo"}], "l": "makya"}, {"l": "mamakaoma"}, {"l": "obu"}, {"l": "noopalena"}], "l": "suoneflole"}], "l": "okya"}, {"c": [{"l": "bunakolui"}, {"l": "lukeole"}, {"l": "fosinaflo"}], "l": "pikobi"}, {"l": "sule"}, {"l": "zopitrii"}, {"l": "okeke"}, {"l": "bubi"}, {"c": [{"l": "noarkyuna"}, {"l": "kako"}, {"c": [{"c": [{"l": "bisukyubopi"}, {"l": "sukya"}, {"l": "naesar"}, {"l": "kyuo"}, {"l": "otrika"}, {"l": "flepa"}], "l": "kyafoflekya"}, {"l": "kyunozo"}, {"c": [{"l": "tanekata"}, {"l": "trinoarar"}, {"l": "koluo"}, {"l": "ianle"}, {"l": "kyusu"}, {"l": "nenama"}], "l": "ifuar"}, {"c": [{"l": "legonomasi"}, {"l": "kyubosu"}, {"l": "leanifle"}], "l": "anpakyaneflo"}, {"c": [{"l": "zofosetri"}, {"l": "nokesusi"}, {"l": "kyuzo"}, {"l": "lenoanne"}, {"l": "senafle"}, {"l": "noeszopi"}], "l": "tamabi"}], "l": "gokyasugona"}, {"c": [{"l": "bigosi"}, {"c": [{"l": "sunotabuo"}, {"l": "peika"}], "l": "osemakyu"}], "l": "kyakear"}, {"c": [{"l": "bunao"}, {"c": [{"l": "koseko"}, {"l": "sunefusu"}, {"l": "nearoan"}], "l": "kyasi"}], "l": "fleflofle"}, {"l": "gokyuse"}], "l": "lubuflezo"}], "l": "lekyubose"}, {"c": [{"l": "triflo"}, {"c": [{"c": [{"c": [{"l": "eskafle"}, {"l": "sufopa"}, {"l": "sekeansisi"}, {"l": "zolunono"}, {"l": "tafu"}, {"l": "nokyakyu"}], "l": "lelepees"}, {"l": "seko"}], "l": "zotrikyaanle"}, {"l": "mago"}, {"c": [{"l": "luesbinosi"}, {"c": [{"l": "mabinosuar"}], "l": "kosu"}], "l": "nafloluzo"}], "l": "takya"}, {"l": "kyafleibibo"}, {"c": [{"c": [{"c": [{"l": "lekoflolulu"}, {"l": "pafo"}, {"l": "lupama"}], "l": "papi"}, {"l": "makyu"}, {"l": "butripesi"}, {"l": "lulugoma"}, {"c": [{"l": "boeskyanaflo"}, {"l": "sitabofuar"}, {"l": "bofleartase"}, {"l": "zobupafle"}], "l": "zokokesebi"}, {"l": "nozo"}], "l": "nabuseikya"}, {"l": "sisebu"}, {"c": [{"l": "penezo"}, {"l": "eskya"}], "l": "flozofletri"}, {"l": "funafleo"}], "l": "ketri"}, {"l": "arsubugo"}], "l": "fokasuflo"}, {"c": [{"c": [{"l": "sinabikesi"}, {"l": "nasufle"}, {"c": [{"l": "kyaflobo"}], "l": "kyunakasian"}], "l": "kyakaluflene"}, {"c": [{"l": "arse"}, {"c": [{"l": "tailees"}, {"l": "kotrifle"}], "l": "ikonezo"}, {"c": [{"l": "lesupifo"}], "l": "kamakakao"}], "l": "tako"}], "l": "supiflenoke"}, {"l": "koeslubuar"}, {"c": [{"c": [{"c": [{"l": "arfle"}], "l": "suta"}, {"l": "konesumalu"}, {"c": [{"l": "nean"}, {"c": [{"l": "nebi"}, {"l": "luogo"}, {"l": "foka"}, {"l": "nesubikyu"}, {"l": "kebo"}], "l": "neke"}, {"l": "flopabiflole"}, {"c": [{"l": "kona"}], "l": "kane"}], "l": "kope"}, {"l": "bipakyubu"}], "l": "tafotrinana"}, {"l": "lefofo"}], "l": "estribubian"}], "l": "mana"}], "l": "esfle"}, {"c": [{"c": [{"l": "zokearse"}, {"l": "bupipifle"}, {"c": [{"l": "kobiarflo"}, {"c": [{"l": "leta"}, {"l": "floikekyubo"}, {"l": "fofulu"}, {"l": "bolusunao"}, {"l": "fleluno"}, {"l": "kyafosusefo"}], "l": "pekasi"}, {"c": [{"l": "nafugo"}, {"c": [{"l": "sesi"}, {"l": "tribo"}, {"l": "sukyuse"}, {"l": "zotrina"}, {"l": "pefoka"}, {"l": "naar"}, {"c": [{"l": "gokya"}, {"l": "flesetri"}, {"l": "kyutri"}, {"l": "luflosikyu"}, {"l": "taar"}], "l": "esboko"}], "l": "piotalu"}, {"l": "supabitrisu"}, {"c": [{"l": "kosu"}], "l": "sekobi"}, {"l": "kyunebi"}, {"c": [{"l": "kyuflosipeke"}, {"c": [{"l": "kyasunano"}, {"l": "artano"}, {"l": "arnele"}, {"l": "oankya"}, {"l": "lenekyaizo"}], "l": "omale"}, {"l": "tako"}], "l": "zoka"}, {"l": "nofloanpi"}], "l": "sususunoar"}, {"l": "kyutatriko"}], "l": "flokyaflefokyu"}], "l": "fubigobo"}, {"c": [{"c": [{"c": [{"c": [{"l": "flenatafleke"}, {"l": "butritrikese"}, {"l": "bibugofo"}, {"l": "trike"}], "l": "siluanfu"}, {"c": [{"l": "floke"}, {"l": "neflesu"}, {"l": "taibu"}, {"l": "kyaesarfofu"}, {"l": "kefo"}, {"l": "tai"}], "l": "flees"}, {"l": "ipapalena"}, {"c": [{"l": "buonafle"}, {"c": [{"l": "kyukobokyu"}, {"l": "bokyu"}, {"l": "fleflofo"}, {"l": "bulene"}, {"l": "naan"}], "l": "peflotritri"}, {"l": "fletana"}, {"l": "nosenopa"}, {"l": "tritane"}, {"c": [{"l": "taflo"}, {"l": "nalubuna"}, {"l": "kona"}, {"l": "trizoobi"}, {"l": "pabo"}, {"l": "arkokefu"}, {"l": "anna"}], "l": "kosi"}, {"l": "zosina"}], "l": "zogo"}, {"l": "tribi"}, {"l": "sibobiesar"}], "l": "palukekyuka"}, {"c": [{"l": "fogotataes"}, {"l": "seseflelu"}, {"l": "nozooo"}, {"l": "ilema"}], "l": "leesflo"}, {"l": "koflofuflofu"}, {"l": "zopezoko"}], "l": "luosu"}, {"c": [{"l": "goflolukyu"}], "l": "lufoansipe"}, {"l": "makyanabu"}, {"l": "setri"}, {"l": "mapepeko"}], "l": "fomanoseo"}, {"c": [{"c": [{"l": "tasikyu"}, {"l": "flekaflozosu"}, {"c": [{"l": "sukyukyu"}], "l": "naleno"}, {"c": [{"l": "fupaleka"}, {"c": [{"l": "nefobi"}], "l": "arbi"}, {"c": [{"l": "zoflelefuna"}, {"l": "flezopebio"}, {"c": [{"l": "lekoikyu"}, {"l": "gobuta"}, {"l": "sugole"}, {"l": "neopago"}, {"l": "zobukekyu"}], "l": "koanflekabu"}], "l": "kyuzoflokyako"}], "l": "flokekalupe"}], "l": "kasekaselu"}], "l": "masinanoma"}], "l": "pemapeo"}], "l": "kyupapa"} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment