const LINE_COUNT = 100;
const LINE_WIDTH = (1 / LINE_COUNT) * 0.94;
const LEN_FRAMES = 5;
const GET_FRAMES = 1;
const SET_FRAMES = 1;
const RQUEUE_SIZE = 15;
const seedrandom = (function() {
var seed = 0x2F6E2B0;
return function() {
seed = ((seed + 0x7ED55D16) + (seed << 12)) & 0xFFFFFFFF;
seed = ((seed ^ 0xC761C23C) ^ (seed >>> 19)) & 0xFFFFFFFF;
seed = ((seed + 0x165667B1) + (seed << 5)) & 0xFFFFFFFF;
seed = ((seed + 0xD3A2646C) ^ (seed << 9)) & 0xFFFFFFFF;
seed = ((seed + 0xFD7046C5) + (seed << 3)) & 0xFFFFFFFF;
seed = ((seed ^ 0xB55A4F09) ^ (seed >>> 16)) & 0xFFFFFFFF;
return (seed & 0xFFFFFFF) / 0x10000000;
};
}());
let fractionalWaitAmount = 0;
async function waitFrames(n) {
let amountToWait = n;
let amountToWaitFraction = amountToWait - Math.floor(amountToWait);
amountToWait = Math.floor(amountToWait);
fractionalWaitAmount += amountToWaitFraction;
let fractionalAdded = Math.floor(fractionalWaitAmount);
fractionalWaitAmount -= fractionalAdded;
amountToWait += fractionalAdded;
if (amountToWait < 1) return;
await on(frameNum + amountToWait);
}
let bg = sprite(rect(1, 1, "black")); let lineSprites = null;
function updateFromDrawState(state, arr) {
if (state.type === "len") {
bg.shape.colour = "#4d4d4d";
} else {
bg.shape.colour = "black";
}
const FUPPER = 700;
const FLOWER = 100;
if (state.type === "get") {
paud.playNote(((state.idx / LINE_COUNT) * (FUPPER - FLOWER)) + FLOWER, 0.001);
rqueue.push([state.idx, "#e63217"]);
} else if (state.type === "set") {
paud.playNote(((state.idx / LINE_COUNT) * (FUPPER - FLOWER)) + FLOWER, 0.001);
rqueue.push([state.idx, "#00d111"]);
}
rqueue = rqueue.slice(-RQUEUE_SIZE);
lineSprites.forEach((line, idx) => {
line.shape.colour = "white";
line.y = 1 - arr[idx];
});
rqueue.forEach(([idx, colour]) => {
lineSprites[idx].shape.colour = colour;
});
}
class WrappedArray {
constructor(arr) {
this._arr = arr;
if (lineSprites !== null) {
updateFromDrawState({
type: "none",
}, this._arr);
}
}
innerArr() {
return this._arr;
}
drawState() {
return this._drawState;
}
async len() {
updateFromDrawState({
type: "len",
}, this._arr);
await waitFrames(LEN_FRAMES);
return this._arr.length;
}
async get(idx) {
updateFromDrawState({
type: "get",
idx,
}, this._arr);
await waitFrames(GET_FRAMES);
return this._arr[idx];
}
async set(idx, val) {
updateFromDrawState({
type: "set",
idx,
}, this._arr);
await waitFrames(SET_FRAMES);
this._arr[idx] = val;
}
async swap(idx1, idx2) {
const val1 = await this.get(idx1);
const val2 = await this.get(idx2);
await this.set(idx1, val2);
await this.set(idx2, val1);
}
}
let lines;
let rqueue = [];
function resetLines() {
rqueue = [];
lines = new WrappedArray((new Array(LINE_COUNT)).fill().map((_val, idx) => (idx + 1) / (LINE_COUNT + 1)));
if (lineSprites !== null) {
lineSprites.forEach((line, idx) => {
line.shape.colour = "white";
});
}
}
resetLines();
lineSprites = lines.innerArr().map((val, idx) => {
return sprite(
rect(LINE_WIDTH, 1, "white"),
(1 / LINE_COUNT) * idx,
1 - val,
);
});
async function algFisherYates() {
var currentIndex = await lines.len(), temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(seedrandom() * currentIndex);
currentIndex -= 1;
temporaryValue = await lines.get(currentIndex);
await lines.set(currentIndex, await lines.get(randomIndex));
await lines.set(randomIndex, temporaryValue);
}
}
async function algRiffle() {
let len = await lines.len();
for (let i = 0; i < 3; i++) {
let i = Math.floor(len / 2);
let j = len - 1;
while (i > 0) {
let temp = await lines.get(i);
await lines.set(i--, await lines.get(j));
await lines.set(j--, temp);
}
}
}
async function algThilo() {
let len = await lines.len();
for (let i = 0; i < len; i++) {
let randomIndex = Math.floor(seedrandom() * len);
let randomIndex2 = Math.floor(seedrandom() * len);
let temp = await lines.get(randomIndex);
await lines.set(randomIndex, await lines.get(randomIndex2));
await lines.set(randomIndex2, temp);
}
}
const pivot = async (arr, randVals, start = 0, end = randVals.length + 1) => {
let pivot = randVals[start],
pointer = start;
for (let i = start; i < randVals.length; i++) {
if (randVals[i] < pivot) {
pointer++;
await arr.swap(pointer, i);
swap(randVals, pointer, i);
}
}
await arr.swap(start, pointer);
swap(randVals, start, pointer);
return pointer;
};
const swap = (list, a, b) => [list[a], list[b]] = [list[b], list[a]];
async function sortQuicksort(randVals, start = 0, end = randVals.length) {
let pivotIndex = await pivot(lines, randVals, start, end);
if (start >= end) return;
await sortQuicksort(randVals, start, pivotIndex);
await sortQuicksort(randVals, pivotIndex + 1, end);
return;
}
async function algLippert(sortAlg) {
const randVals = new Array(await lines.len()).fill().map(() => seedrandom());
await sortAlg(randVals);
}
async function algBogo() {
const len = await lines.len();
while (true) {
const idx1 = Math.floor(seedrandom() * len);
const idx2 = Math.floor(seedrandom() * len);
await lines.swap(idx1, idx2);
}
}
async function play() {
let curFrame = 0;
resetLines();
await algFisherYates();
await waitFrames(60);resetLines();
await algThilo();
await waitFrames(60);resetLines();
try { await algLippert(sortQuicksort); } catch (e) {console.warn(e);}
}
play();