2022-09-09 18:44:52 -07:00
|
|
|
import seedrandom from 'seedrandom';
|
|
|
|
|
|
|
|
import type { PickAlgorithm } from './types';
|
|
|
|
|
|
|
|
type Opts = {
|
|
|
|
/** Randomization seed. */
|
|
|
|
seed: string,
|
|
|
|
/**
|
|
|
|
* Start/end index of the slot by which one item will be randomly picked per page.
|
|
|
|
*
|
2022-09-09 20:26:36 -07:00
|
|
|
* Eg. `[2, 6]` will cause one item to be picked among the third through seventh indexes.
|
2022-09-09 18:44:52 -07:00
|
|
|
*
|
|
|
|
* `end` must be larger than `start`.
|
|
|
|
*/
|
|
|
|
range: [start: number, end: number],
|
|
|
|
/** Number of items in the page. */
|
|
|
|
pageSize: number,
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Algorithm to display items per-page.
|
|
|
|
* One item is randomly inserted into each page within the index range.
|
|
|
|
*/
|
2022-09-09 20:26:36 -07:00
|
|
|
const abovefoldAlgorithm: PickAlgorithm = (items, iteration, rawOpts) => {
|
|
|
|
const opts = normalizeOpts(rawOpts);
|
2022-09-09 18:44:52 -07:00
|
|
|
/** Current page of the index. */
|
2022-09-09 20:26:36 -07:00
|
|
|
const page = Math.floor(iteration / opts.pageSize);
|
2022-09-09 18:44:52 -07:00
|
|
|
/** Current index within the page. */
|
2022-09-09 20:26:36 -07:00
|
|
|
const pageIndex = (iteration % opts.pageSize);
|
2022-09-09 18:44:52 -07:00
|
|
|
/** RNG for the page. */
|
|
|
|
const rng = seedrandom(`${opts.seed}-page-${page}`);
|
|
|
|
/** Index to insert the item. */
|
2022-09-09 20:26:36 -07:00
|
|
|
const insertIndex = Math.floor(rng() * (opts.range[1] - opts.range[0])) + opts.range[0];
|
|
|
|
|
2022-09-09 18:44:52 -07:00
|
|
|
if (pageIndex === insertIndex) {
|
2022-09-09 18:49:17 -07:00
|
|
|
return items[page % items.length];
|
2022-09-09 18:44:52 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-09-09 20:26:36 -07:00
|
|
|
const normalizeOpts = (opts: unknown): Opts => {
|
|
|
|
const { seed, range, pageSize } = (opts && typeof opts === 'object' ? opts : {}) as Record<any, unknown>;
|
|
|
|
|
|
|
|
return {
|
|
|
|
seed: typeof seed === 'string' ? seed : '',
|
|
|
|
range: Array.isArray(range) ? [Number(range[0]), Number(range[1])] : [2, 6],
|
|
|
|
pageSize: typeof pageSize === 'number' ? pageSize : 20,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2022-09-09 18:44:52 -07:00
|
|
|
export {
|
|
|
|
abovefoldAlgorithm,
|
|
|
|
};
|