Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active January 2, 2016 10:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nitaku/8289840 to your computer and use it in GitHub Desktop.
Save nitaku/8289840 to your computer and use it in GitHub Desktop.
Fractal treemap of Kyupapa (321 leaves)
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)
})
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)
#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;
}
<!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>
(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);
@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
{"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"}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment