105 lines
3.5 KiB
TypeScript
105 lines
3.5 KiB
TypeScript
// @ts-ignore
|
|
import * as random from "fast-random";
|
|
|
|
|
|
/**
|
|
* Shuffles the given array in-place.
|
|
*
|
|
* @param array the array to shuffle
|
|
* @param seed the seed for the random number generator
|
|
* @returns the array that was given to this function to shuffle
|
|
*/
|
|
export function shuffleArrayInPlace(array: any[], seed: number | undefined = undefined): any[] {
|
|
const rng = random(seed);
|
|
|
|
for (let i = array.length - 1; i > 0; i--) {
|
|
const j = rng.nextInt() % (i + 1);
|
|
[array[i], array[j]] = [array[j], array[i]];
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* Slices `array` into chunks of `chunkSize` elements each.
|
|
*
|
|
* If `array` does not contain a multiple of `chunkSize` elements, the last chunk will contain fewer elements.
|
|
*
|
|
* @param array the array to chunkify
|
|
* @param chunkSize the size of each chunk
|
|
* @returns an array of the extracted chunks
|
|
*/
|
|
export function chunkifyArray(array: any[], chunkSize: number): any[] {
|
|
const chunks = [];
|
|
for (let i = 0; i < array.length; i += chunkSize)
|
|
chunks.push(array.slice(i, i + chunkSize));
|
|
return chunks;
|
|
}
|
|
|
|
/**
|
|
* Creates an array of `size` consecutive integers starting at `startAt`.
|
|
*
|
|
* Taken from https://stackoverflow.com/a/10050831 (CC BY-SA 4.0).
|
|
*
|
|
* @param length the number of consecutive integers to put in the array
|
|
* @param beginAt the first integer to return
|
|
* @returns the array of consecutive integers
|
|
*/
|
|
export function range(length: number, beginAt: number = 0): number[] {
|
|
return [...Array(length).keys()].map(i => i + beginAt);
|
|
}
|
|
|
|
/**
|
|
* Waits for FontAwesome to have loaded and then invokes the callback.
|
|
*
|
|
* Taken from https://stackoverflow.com/a/35572620/ (CC BY-SA 3.0).
|
|
*
|
|
* @param callback the function to invoke once the font has loaded
|
|
* @param timeout the maximum time in milliseconds to wait for the font to load
|
|
*/
|
|
export function waitForForkAwesome(callback: () => void, timeout: number | undefined = undefined): void {
|
|
const canvas = document.createElement("canvas");
|
|
const ctx = canvas.getContext("2d")!;
|
|
const fontSize = 36;
|
|
const testCharacter = "\uF047";
|
|
const targetPixelCount = 500;
|
|
|
|
const ccw = canvas.width = fontSize * 1.5;
|
|
const cch = canvas.height = fontSize * 1.5;
|
|
ctx.font = `${fontSize}px ForkAwesome`;
|
|
ctx.textAlign = "center";
|
|
ctx.textBaseline = "middle";
|
|
|
|
const startTime = performance.now();
|
|
const failTime = timeout === undefined ? undefined : startTime + timeout;
|
|
requestAnimationFrame(fontOnload);
|
|
|
|
/**
|
|
* Repeatedly invokes itself until the font has loaded or the timeout has been reached.
|
|
*
|
|
* @param time the time in milliseconds at which this function is invoked
|
|
*/
|
|
function fontOnload(time: number): void {
|
|
const currentCount = getPixelCount();
|
|
if (failTime !== undefined && time > failTime) alert(`ForkAwesome failed to load after ${timeout}ms.`);
|
|
else if (currentCount < targetPixelCount) requestAnimationFrame(fontOnload);
|
|
else callback();
|
|
}
|
|
|
|
/**
|
|
* Draws a character in the canvas and returns the number of pixels that have been drawn.
|
|
*
|
|
* @returns the number of pixels that have been drawn
|
|
*/
|
|
function getPixelCount(): number {
|
|
ctx.clearRect(0, 0, ccw, cch);
|
|
ctx.fillText(testCharacter, ccw / 2, cch / 2);
|
|
|
|
const data = ctx.getImageData(0, 0, ccw, cch).data;
|
|
let count = 0;
|
|
for (let i = 3; i < data.length; i += 4)
|
|
if (data[i] > 10) count++;
|
|
return count;
|
|
}
|
|
}
|