|
<!doctype html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>parsing</title> |
|
<style> |
|
* { box-sizing: border-box; } |
|
body { |
|
font-family: "Open Sans", sans-serif; |
|
margin: 0; |
|
} |
|
circle { |
|
fill: #008000; |
|
stroke: none; |
|
} |
|
#svg-wrap { |
|
margin: 10px auto; |
|
position: relative; |
|
overflow: scroll; |
|
} |
|
.bucket-top { |
|
stroke: none; |
|
fill: #999; |
|
} |
|
.bucket-barrel { |
|
stroke: none; |
|
fill: #e1e1e1; |
|
} |
|
.bucket-wire { |
|
stroke: #979797; |
|
stroke-linecap: round; |
|
fill: none; |
|
} |
|
.bucket-handle { |
|
stroke: none; |
|
fill: #4a4a4a; |
|
} |
|
.drop-path { |
|
stroke: none; |
|
fill: none; |
|
} |
|
.drop-guide { |
|
fill: none; |
|
stroke: #e1e1e1; |
|
stroke-width: 1.5px; |
|
stroke-linecap: round; |
|
} |
|
.count-text, count-label { fill: #444; } |
|
</style> |
|
</head> |
|
<body> |
|
<div id="svg-wrap"> |
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> |
|
<g id="drop-paths"></g> |
|
<g id="drop-guides"></g> |
|
<g id="buckets"></g> |
|
<g id="counts"></g> |
|
</svg> |
|
</div> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.min.js"></script> |
|
<script> |
|
var svg = d3.select('svg'); |
|
var dropPathsGrp = svg.select('#drop-paths'); |
|
var dropGuidesGrp = svg.select('#drop-guides'); |
|
var bucketsGrp = svg.select('#buckets'); |
|
var countsGrp = svg.select('#counts'); |
|
var rwd = { x: 0, y: 0}; |
|
var ballR = 0; |
|
var interval = 10000; |
|
var cats = [ |
|
'processed', |
|
'parsed', |
|
'unique', |
|
'cat_1', |
|
'cat_2', |
|
'cat_3', |
|
'cat_4', |
|
'cat_5', |
|
'cat_6', |
|
'cat_7', |
|
'cat_8', |
|
'cat_9', |
|
'cat_10', |
|
'duplicates', |
|
'cat_11', |
|
'cat_12', |
|
'cat_13', |
|
'failed', |
|
]; |
|
|
|
var stats = { |
|
'processed': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'parsed': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'unique': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_1': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_2': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_3': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_4': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_5': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_6': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_7': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_8': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_9': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_10': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'duplicates': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_11': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_12': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'cat_13': { count: 0, queued : 0, countText: {}, path: {} }, |
|
'failed': { count: 0, queued : 0, countText: {}, path: {} } |
|
}; |
|
|
|
var updates = []; |
|
var upIdx = 0; |
|
var upLen = 60; |
|
|
|
function genData () { |
|
var upX = 0; |
|
var tots = initTots(); |
|
|
|
for (upX; upX < upLen; upX += 1 ) { |
|
updates.push(genRow()); |
|
} |
|
|
|
function genRow () { |
|
var processed = 0; |
|
var parsed = 0; |
|
var failed = 0; |
|
var unique = 0; |
|
var cat_1 = 0; |
|
var uidd = 0; |
|
var cat_9; |
|
var row = {}; |
|
cats.forEach(function (cat) { |
|
var catCt = 0; |
|
if (cat == 'processed') { |
|
processed = randRange(0, 75); |
|
failed = randRange(0, 10); |
|
parsed = processed - failed; |
|
catCt = processed; |
|
} |
|
if (cat == 'parsed') { |
|
catCt = parsed; |
|
} |
|
if (cat == 'unique') { |
|
unique = parsed - randRange(0, parsed); |
|
catCt = unique; |
|
} |
|
if (cat == 'cat_1') { |
|
cat_1 = unique - randRange(0, 10); |
|
catCt = cat_1; |
|
uidd = unique - cat_1; |
|
} |
|
if (cat == 'cat_2' || cat == 'cat_3' || cat == 'cat_4' || cat == 'cat_11') { |
|
if (uidd) { |
|
catCt = uidd - randRange(0, uidd); |
|
uidd = uidd - catCt; |
|
} |
|
} |
|
if (cat == 'cat_5' || cat == 'cat_6' || cat == 'cat_7' || cat == 'cat_8' ) { |
|
catCt = randRange(0, 25); |
|
} |
|
if (cat == 'cat_9') { |
|
catCt = unique - randRange(0, unique); |
|
cat_9 = catCt; |
|
} |
|
if (cat == 'cat_10') { |
|
catCt = unique - cat_9; |
|
} |
|
if (cat == 'duplicates') { |
|
catCt = parsed - unique; |
|
} |
|
if (cat == 'cat_12') { |
|
catCt = randRange(0, 5); |
|
} |
|
if (cat == 'cat_13') { |
|
catCt = randRange(0, 15); |
|
} |
|
if (cat == 'failed') { |
|
catCt = failed; |
|
} |
|
|
|
row[cat] = tots[cat] + catCt; |
|
tots[cat] = row[cat]; |
|
}); |
|
|
|
return row; |
|
} |
|
|
|
function initTots () { |
|
var tots = {}; |
|
cats.forEach(function (cat) { tots[cat] = 0; }); |
|
return tots; |
|
} |
|
} |
|
|
|
function drawBuckets () { |
|
var barrel = [ |
|
['M',[40,4]], |
|
['L',[36,38]], |
|
['C',[36,40],' ',[28.84,42],' ',[20,42]], |
|
['C',[11.163,42],' ',[4,40],' ',[4,38]], |
|
['L',[0,4]], |
|
['C',[0.5,6.3],' ',[9.275,8],' ',[20,8]], |
|
['C',[30.724,8],' ',[39.477,6.3],' ',[40,4]], |
|
['Z'] |
|
]; |
|
var barrelD = calcD(barrel); |
|
|
|
var wire = [ |
|
['M',[0,4]], |
|
['C',[0,4],' ',[0,22],' ',[20,22]], |
|
['C', [40,22],' ',[40,4],' ',[40,4]] |
|
]; |
|
var wireD = calcD(wire); |
|
|
|
var handle = { x: 16, y: 20, width: 8, height: 4, rx: 2 }; |
|
|
|
var bucketY = to3(rwd.y * 403); |
|
|
|
var buckets = { |
|
'processed': 28, |
|
'parsed': 92, |
|
'unique': 156, |
|
'cat_1': 220, |
|
'cat_2': 284, |
|
'cat_3': 348, |
|
'cat_4': 412, |
|
'cat_5': 476, |
|
'cat_6': 540, |
|
'cat_7': 604, |
|
'cat_8': 668, |
|
'cat_9': 732, |
|
'cat_10': 796, |
|
'duplicates': 860, |
|
'cat_11': 924, |
|
'cat_12': 988, |
|
'cat_13': 1052, |
|
'failed': 1116 |
|
}; |
|
|
|
cats.forEach(function (cat) { |
|
var bucket = buckets[cat]; |
|
drawTop(cat, bucket); |
|
drawBucket(cat, bucket); |
|
}); |
|
|
|
function drawTop (cat, bucket) { |
|
var bucketX = to3(buckets[cat] * rwd.x); |
|
var rx = to3(rwd.x * 20); |
|
var ry = to3(rwd.y * 4); |
|
var cx = bucketX + rx; |
|
var cy = bucketY + ry; |
|
|
|
dropPathsGrp.append('ellipse') |
|
.attr('id', 'bucket-top-' + cat) |
|
.attr('class', 'bucket-top') |
|
.attr('cx', cx) |
|
.attr('cy', cy) |
|
.attr('rx', rx) |
|
.attr('ry', ry); |
|
} |
|
|
|
function drawBucket (cat, bucket) { |
|
var bucketGrp = bucketsGrp.append('g') |
|
.attr('id', 'bucket-' + cat) |
|
.attr('transform', 'translate(' + to3(bucket * rwd.x) + ',' + bucketY + ')'); |
|
|
|
bucketGrp.append('path') |
|
.attr('class', 'bucket-barrel') |
|
.attr('d', barrelD); |
|
|
|
bucketGrp.append('path') |
|
.attr('class', 'bucket-wire') |
|
.attr('d', wireD) |
|
.attr('stroke-linecap', 'round'); |
|
|
|
bucketGrp.append('rect') |
|
.attr('class', 'bucket-handle') |
|
.attr('x', to3(16 * rwd.x)) |
|
.attr('y', to3(20 * rwd.y)) |
|
.attr('width', to3(8 * rwd.x)) |
|
.attr('height', to3(4 * rwd.y)) |
|
.attr('rx', to3(2 * rwd.x)); |
|
} |
|
} |
|
|
|
function drawPaths () { |
|
var dropPaths = { |
|
'processed': [ ['M',[16,16]], ['L',[296,32]], ['L',[48,112]], ['L',[48,406]] ], |
|
'parsed': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[112,208]], ['L',[112,406]] ], |
|
'unique': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[176,304]], ['L',[176,406]] ], |
|
'cat_1': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[240,336]], ['L',[240,406]] ], |
|
'cat_2': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,250]], ['L',[304,336]], ['L',[304,406]] ], |
|
'cat_3': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,260]], ['L',[368,336]], ['L',[368,406]] ], |
|
'cat_4': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,260]], ['L',[432,336]], ['L',[432,406]] ], |
|
'cat_5': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,260]], ['L',[496,336]], ['L',[496,406]] ], |
|
'cat_6': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,260]], ['L',[560,336]], ['L',[560,406]] ], |
|
'cat_7': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,260]], ['L',[624,336]], ['L',[624,406]] ], |
|
'cat_8': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,260]], ['L',[688,336]], ['L',[688,406]] ], |
|
'cat_9': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[525,250]], ['L',[752,311]], ['L',[752,406]] ], |
|
'cat_10': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[508,176]], ['L',[525,225]], ['L',[592,244.4]], ['L',[816,304]], ['L',[816,406]] ], |
|
'duplicates': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[513,174.3]], ['L',[880,272]], ['L',[880,406]] ], |
|
'cat_11': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[1008,240]], ['L',[944,304]], ['L',[944,406]] ], |
|
'cat_12': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[1008,240]], ['L',[1008,406]] ], |
|
'cat_13': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[592,144]], ['L',[1008,240]], ['L',[1072,304]], ['L',[1072,406]] ], |
|
'failed': [ ['M',[16,16]], ['L',[296,32]], ['L',[560,48]], ['L',[1136,187.5]], ['L',[1136,406]] ] |
|
}; |
|
var dropGuides = [ |
|
{ id: 'init', points: [ ['M',[9.75,22.5]], ['L',[258.5,37]] ] }, |
|
{ id: 'processed', points: [ ['M',[526.5,52.75]], ['L',[296,39]], ['L',[54.75,117]], ['L',[54.75,144]] ] }, |
|
{ id: 'parsed', points: [ ['M',[584.239,140.024]], ['L',[555.928,56.354]], ['L',[118.5,212.39]], ['L',[118.5,239.824]] ] }, |
|
{ id: 'query-table', points: [ ['M',[535.032,173.16]], ['L',[592.484,151.051]], ['L',[994.548,243.828]] ] }, |
|
{ id: 'unique', points: [ ['M',[516.5,221]], ['L',[503.818,185.111]], ['L',[182.75,308.75]], ['L',[182.75,336]] ] }, |
|
{ id: 'cat_4', points: [ ['M',[438.75,368]], ['L',[438.75,339.089]], ['L',[508,282.75]] ] }, |
|
{ id: 'cat_1', points: [ ['M',[246.5,368]], ['L',[246.5,340.308]], ['L',[518.418,234.626]] ] }, |
|
{ id: 'cat_2', points: [ ['M',[310.75,368]], ['L',[310.75,340]], ['L',[470.811,278]] ] }, |
|
{ id: 'cat_3', points: [ ['M',[374.75,368]], ['L',[374.75,338.688]], ['L',[473.877,292]] ] }, |
|
{ id: 'sub-cat_6', points: [ ['M',[502.75,368]], ['L',[502.75,337.5]], ['L',[525.5,277.75]], ['L',[553.25,337.5]], ['L',[553.25,368]] ] }, |
|
{ id: 'cat_7', points: [ ['M',[543.5,282.75]], ['L',[617.25,339.5]], ['L',[617.25,368]] ] }, |
|
{ id: 'cat_8', points: [ ['M',[578.5,292]], ['L',[681.25,340]], ['L',[681.25,368]] ] }, |
|
{ id: 'cat_9', points: [ ['M',[603.175,278]], ['L',[745.25,316.25]], ['L',[745.25,342]] ] }, |
|
{ id: 'cat_10', points: [ ['M',[532,234]], ['L',[809.25,309.25]], ['L',[809.25,336]] ] }, |
|
{ id: 'duplicates', points: [ ['M',[517.4,182.5]], ['L',[873.25,277.171]], ['L',[873.25,304]] ] }, |
|
{ id: 'cat_11', points: [ ['M',[950.5,336]], ['L',[950.5,306.683]], ['L',[1001.03625,256.5]] ] }, |
|
{ id: 'cat_13', points: [ ['M',[1014.9,256.5]], ['L',[1065.25,307]], ['L',[1065.25,336.188]] ] }, |
|
{ id: 'failed', points: [ ['M',[570.22,57.4]], ['L',[1129.25,192.808]], ['L',[1129.25,222.135]] ] } |
|
]; |
|
|
|
cats.forEach(function (cat) { |
|
var dropD = calcD(dropPaths[cat]); |
|
drawDrop(cat, dropD); |
|
}); |
|
|
|
dropGuides.forEach(function (dropGuide) { |
|
dropGuidesGrp.append('path') |
|
.attr('id', 'guide-' + dropGuide.id) |
|
.attr('class', 'drop-guide') |
|
.attr('d', calcD(dropGuide.points)) |
|
}); |
|
|
|
function drawDrop(cat, dropD) { |
|
var dropPath = dropPathsGrp.append('path') |
|
.attr('id', 'drop-' + cat) |
|
.attr('class', 'drop-path') |
|
.attr('d', dropD); |
|
// TODO: append another path here for hover? |
|
|
|
setStatProps(cat, dropPath); |
|
} |
|
} |
|
|
|
function drawCounts () { |
|
var countY = to3(566 * rwd.y); |
|
var labelY = to3(488.5 * rwd.y); |
|
var counts = { |
|
'processed': { x: 48, label: 'Processed' }, |
|
'parsed': { x: 112, label: 'Parsed' }, |
|
'unique': { x: 176, label: 'Unique' }, |
|
'cat_1': { x: 240, label: 'Cat 1' }, |
|
'cat_2': { x: 304, label: 'Cat 2' }, |
|
'cat_3': { x: 368, label: 'Cat 3' }, |
|
'cat_4': { x: 432, label: 'Cat 4' }, |
|
'cat_5': { x: 496, label: 'Cat 5' }, |
|
'cat_6': { x: 560, label: 'Cat 6' }, |
|
'cat_7': { x: 624, label: 'Cat 7' }, |
|
'cat_8': { x: 688, label: 'Cat 8' }, |
|
'cat_9': { x: 752, label: 'Cat 9' }, |
|
'cat_10': { x: 816, label: 'Cat 10' }, |
|
'duplicates': { x: 880, label: 'Duplicates' }, |
|
'cat_11': { x: 944, label: 'Cat 11' }, |
|
'cat_12': { x: 1008, label: 'Cat 12' }, |
|
'cat_13': { x: 1072, label: 'Cat 13' }, |
|
'failed': { x: 1136, label: 'Failed' } |
|
} |
|
|
|
cats.forEach(function(cat) { |
|
var count = counts[cat]; |
|
drawCount(cat, count); |
|
procLabel(count); |
|
}); |
|
|
|
function drawCount(cat, count) { |
|
var countX = to3(count.x * rwd.x); |
|
var fontSize = to3(16 * rwd.y); |
|
var countText = countsGrp.append('text') |
|
.attr('id', 'count-' + cat) |
|
.attr('class', 'count-text') |
|
.attr('x', countX) |
|
.attr('y', countY) |
|
.attr('font-size', fontSize) |
|
.attr('text-anchor', 'middle') |
|
.text('0'); |
|
|
|
stats[cat].countText = countText; |
|
} |
|
|
|
function procLabel(count) { |
|
var labelX = to3(count.x * rwd.x); |
|
|
|
drawLabel(count.label, labelX, labelY); |
|
} |
|
|
|
function drawLabel(label, labelX, labelY) { |
|
var fontSize = to3(12 * rwd.y); |
|
countsGrp.append('text') |
|
.attr('class', 'count-label') |
|
.attr('x', labelX) |
|
.attr('y', labelY) |
|
.attr('font-size', function () { return fontSize < 8 ? 8 : fontSize; }) |
|
.attr('text-anchor', 'middle') |
|
.text(label) |
|
.attr('transform', 'translate(' + labelX + ',' + labelY + ') rotate(-45) translate(' + -labelX + ',' + -labelY + ')'); |
|
} |
|
} |
|
|
|
function load (idx) { |
|
var next = idx + 1; |
|
var data = updates[idx]; |
|
|
|
console.log('\nprocessing ' + next + ' of ' + upLen + '\n') |
|
|
|
updateAll(data); |
|
|
|
if (next < upLen) { |
|
upIdx = next; |
|
setTimeout(function() { |
|
load(upIdx); |
|
}, interval); |
|
} |
|
} |
|
|
|
function dequeue () { |
|
cats.forEach(function(cat) { |
|
if (stats[cat].queued > 0) { |
|
stats[cat].queued -= 1; |
|
ballDrop(stats[cat], dropEnd, stats[cat]) |
|
} |
|
}); |
|
setTimeout(dequeue, 150); |
|
} |
|
|
|
function updateAll (data) { |
|
// console.log('queued: ') |
|
cats.forEach(function(cat) { |
|
var stat = stats[cat]; |
|
updateStat(cat, stat, data); |
|
}); |
|
} |
|
|
|
function updateStat (cat, stat, data) { |
|
var dx = 0, diff = 0, delay = 0; |
|
if ( data[cat] ) { |
|
diff = +data[cat] - stat.count; |
|
if (diff > 0) { |
|
stat.count += diff; |
|
stat.queued += diff; |
|
} |
|
} |
|
// console.log(cat + ': ' + stat.queued) |
|
} |
|
|
|
function updateCountText (stat) { |
|
var count = +stat.countText.text() + 1; |
|
stat.countText.text(count); |
|
} |
|
|
|
function dropEnd (circle, stat) { |
|
updateCountText(stat); |
|
d3.select(circle).remove(); |
|
} |
|
|
|
function ballDrop (stat, callback, args) { |
|
var path = stat.path.node(); |
|
var ball = svg.append('circle') |
|
.attr('r', ballR) |
|
.attr('transform', function () { |
|
return 'translate(' + stat.pathStart.x + ',' + stat.pathStart.y + ')'; |
|
}) |
|
.transition() |
|
.ease('cubic-in') |
|
.duration(Math.round(stat.pathLength) * 3) |
|
.attrTween('transform', transAlongPath(path, stat.pathLength)) |
|
.each('end', function() { |
|
callback && callback(ball.node(), args); |
|
}); |
|
} |
|
|
|
function transAlongPath (path, length) { |
|
return function(d, i, a) { |
|
return function(t) { |
|
var point = path.getPointAtLength(t * length); |
|
return 'translate(' + point.x + ',' + point.y + ')'; |
|
}; |
|
}; |
|
} |
|
|
|
function init () { |
|
genData(); |
|
setDims(); |
|
drawBuckets(); |
|
drawPaths(); |
|
drawCounts(); |
|
load(upIdx); |
|
dequeue(); |
|
} |
|
|
|
function setDims () { |
|
var defaultWidth = 1184; |
|
var defaultHeight = 580; |
|
var minWidth = 560; |
|
var minHeight = 290; |
|
var svgWidth = 0; |
|
var svgHeight = 0; |
|
var width = window.innerWidth - 20; |
|
var height = window.innerHeight - 20; |
|
var svgWrap = document.getElementById('svg-wrap'); |
|
var wrapBounds = {}; |
|
|
|
svgWrap.style.width = width + 'px'; |
|
svgWrap.style.height = height + 'px'; |
|
wrapBounds = svgWrap.getBoundingClientRect(); |
|
|
|
svgWidth = width > minWidth ? width : minWidth; |
|
rwd.x = svgWidth / defaultWidth; |
|
svgHeight = height > minHeight ? height : minHeight; |
|
rwd.y = svgHeight / defaultHeight; |
|
|
|
ballR = Math.round(5 * Math.min(rwd.x, rwd.y)); |
|
|
|
svg.attr('width', svgWidth).attr('height', svgHeight); |
|
} |
|
|
|
function calcD (pathArr) { |
|
var d = ''; |
|
pathArr.forEach(function(pathTo) { |
|
pathTo.forEach(function(cmd) { |
|
if (Array.isArray(cmd)) { |
|
d += to3(cmd[0] * rwd.x); |
|
if (cmd[1]) { |
|
d += ',' + to3(cmd[1] * rwd.y) |
|
} |
|
} else { |
|
d += cmd; |
|
} |
|
}); |
|
d += ' '; |
|
}); |
|
return d; |
|
} |
|
|
|
function setStatProps (cat, path) { |
|
var stat = stats[cat]; |
|
var node = path.node(); |
|
stat.path = path; |
|
stat.pathStart = node.getPointAtLength(0); |
|
stat.pathEnd = node.getPointAtLength(node.getTotalLength()); |
|
stat.pathLength = node.getTotalLength(); |
|
} |
|
|
|
function randRange (min, max) { |
|
return parseInt(Math.round(min + Math.random() * (max - min))); |
|
} |
|
|
|
function to3 (n) { return parseFloat(n.toFixed(3)) } |
|
|
|
function leftPad (num, padding, padChar) { |
|
// returns left-padded string from an int or float |
|
var padded = num + '', |
|
padLen = padding || 2, |
|
padder = padChar || '0'; |
|
|
|
if (padded.length < padLen) { |
|
while (padded.length < padLen) { |
|
padded = padder + padded; |
|
} |
|
} |
|
return padded; |
|
} |
|
|
|
init(); |
|
</script> |
|
</body> |
|
</html> |