xxxxxxxxxx
269
/*
- Divide the screen into two frames
- top frame has the set of numbers
- Each number is in it's own box and randomly sorted
- bottom frame has the list of buckets
- vertical time line with the by ten clicks
- Walk through the numbers and illustrate they're placement
- random between 1..1000 100 buckets, increments of ten [0..9][10..19][20..29] etc.
- floor(51/10) = 5 bucket number
- insertion sort on the bucket
- illustrate the placement
- Smooth step to bucket
- Smooth step insertion sort
*/
let nums = [];
let scaleUnits = 600;
let animationPoints = [];
let numIdx = -1;
let animateID = 0;
let BOX_HEIGHT = 0.03;
let BOX_WIDTH = 0.05;
let bucketLocs = [];
let bucketCount = [];
let end = false;
let endframe = 0;
let bgColorTheta = 0;
let fps = 60;
let start = true;
var capturer = new CCapture({
format: 'png',
framerate: fps
});
class Vec2 {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Num {
constructor(pos, size, n) {
this.pos = pos;
this.size = size;
this.n = n;
}
}
class InsertEntity {
constructor(idx, x, n) {
this.idx = idx;
this.x = x;
this.n = n;
}
}
function cordToScreen(v) {
let w = new Vec2((width + (v.x * scaleUnits)) / 2.0, (height + (1 - v.y * scaleUnits)) / 2.0);
return w;
}
function v2line(v, w) {
let vp = cordToScreen(v);
let wp = cordToScreen(w);
line(vp.x, vp.y, wp.x, wp.y);
}
function smoothstep(edge0, edge1, x) {
// Scale, bias and saturate x to 0..1 range
x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
// Evaluate polynomial
return x * x * (3 - 2 * x);
}
function clamp(x, lowerlimit, upperlimit) {
if (x < lowerlimit)
x = lowerlimit;
if (x > upperlimit)
x = upperlimit;
return x;
}
function smoothmove(start, end) {
let result = [];
let rev = false;
if (end.x < start.x) {
let t = start;
start = end;
end = t;
rev = true;
}
let y = start.y;
for (let x = start.x; x <= end.x; x += 0.051) {
y = ((end.y - start.y) * smoothstep(start.x, end.x, x)) + start.y;
result.push(new Vec2(x, y));
}
result.push(new Vec2(end.x, end.y));
if (rev) {
return result.reverse();
}
return result;
}
function newNumbers() {
nums = [];
let x = -0.95;
let y = 0.95;
for (let i = 0; i < 100; i++) {
if (x + 0.16 > 1) {
x = -0.95;
y -= 0.06;
}
nums.push(new Num(new Vec2(x, y), new Vec2(BOX_WIDTH, BOX_HEIGHT), floor(random() * 1000)));
x += 0.1;
}
animationPoints = [];
numIdx = -1;
animateID = 0;
bucketCount = [];
for (let i = 0; i < 11; i++) {
bucketCount.push(0);
}
}
function buckets() {
let bucketStep = 1.25 / 10;
let y = -1;
let n = 1000;
let setLoc = bucketLocs.length == 0;
for (let i = 0; i < 11; i++) {
textSize(BOX_HEIGHT * (scaleUnits / 1.25));
let v = new Vec2(-1, y);
if (setLoc) {
bucketLocs.push(v);
}
let vp = cordToScreen(v);
colorMode(RGB);
color(255, 255, 255);
fill(255, 255, 255);
//stroke(0.5,1,1000);
text(n.toString(), vp.x, vp.y);
y += bucketStep;
n = n - 100;
}
}
function setup() {
createCanvas(scaleUnits * 1.05, scaleUnits * 1.05);
newNumbers();
frameRate(fps);
//capturer.start();
}
function numbox(num) {
let vp = cordToScreen(num.pos);
let wp = new Vec2(num.size.x * scaleUnits, num.size.y * scaleUnits);
let t = cordToScreen(new Vec2(num.pos.x + num.size.x / 4, num.pos.y - num.size.y * 1.5));
rect(vp.x, vp.y, wp.x, wp.y);
colorMode(RGB);
fill(0, 0, 0);
textSize(num.size.y * (scaleUnits / 1.5));
text(num.n.toString(), t.x, t.y);
}
function byN(a, b) {
if (a.n < b.n) {
return -1;
}
if (a.n > b.n) {
return 1;
}
return 0;
}
function reorgX(startx, v, n) {
let f = [];
f.push(new InsertEntity(-1, v.x, n));
for (let i = 0; i < nums.length; i++) {
if (nums[i].pos.y == v.y) {
f.push(new InsertEntity(i, nums[i].pos.x, nums[i].n));
}
}
f.sort(byN);
let x = startx;
for (let i = 0; i < f.length; i++) {
if (f[i].idx == -1) {
v.x = x;
} else {
nums[f[i].idx].pos.x = x;
}
x += 0.1;
}
return v;
}
function draw() {
if (start){
capturer.start();
start = false;
}
colorMode(HSB, 1, 1, 1);
background(abs(sin(bgColorTheta += (PI / 1000))), 0.5, 0.2);
buckets();
for (let i = 0; i < nums.length; i++) {
if (i == numIdx) {
continue;
}
colorMode(HSB, 1000, 1, 1);
fill(nums[i].n, 0.5, 0.8);
numbox(nums[i]);
}
if (numIdx >= 0){
colorMode(HSB, 1000, 1, 1);
fill(nums[numIdx].n, 0.5, 0.8);
numbox(nums[numIdx]);
}
if (end && endframe > 0) {
endframe--;
} else if (end) {
end = false;
capturer.stop();
capturer.save();
noLoop();
//return;
newNumbers();
} else if (animationPoints.length > 0 && animateID < animationPoints.length) {
nums[numIdx].pos.x = animationPoints[animateID].x;
nums[numIdx].pos.y = animationPoints[animateID].y;
animateID++;
} else if (numIdx < nums.length - 1) {
numIdx++;
animateID = 0;
let bucketIdx = 10 - floor(nums[numIdx].n / 100);
bucketCount[bucketIdx]++;
let v = new Vec2(bucketLocs[bucketIdx].x +
bucketCount[bucketIdx] * 0.1,
bucketLocs[bucketIdx].y);
v = reorgX(bucketLocs[bucketIdx].x + 0.1, v, nums[numIdx].n);
/*if (v.x < 0) {
animationPoints = smoothmove(nums[numIdx].pos, new Vec2(0.25, 0.25));
animationPoints = animationPoints.concat(new Vec2(0.25, 0.25), new Vec2(0.5, 0.5));
animationPoints = animationPoints.concat(smoothmove(new Vec2(0.5, 0.5), v));
} else {*/
animationPoints = smoothmove(nums[numIdx].pos, v);
//}
} else if (numIdx + 1 == nums.length) {
end = true;
endframe = frameRate() * 2;
numIdx = -1;
}
capturer.capture(document.getElementById('defaultCanvas0'));
}