Switch to a hash-based shuffle so adding new items won't change the shuffled order of existing items
This commit is contained in:
parent
cf17ec85a7
commit
bede558347
1 changed files with 28 additions and 23 deletions
|
@ -1,31 +1,36 @@
|
|||
const LCG_M = Math.pow(2, 32);
|
||||
const LCG_A = 0xd9f5;
|
||||
const LCG_C = 69;
|
||||
|
||||
function lcg(seed) {
|
||||
let value = seed % LCG_M;
|
||||
|
||||
return (n) => {
|
||||
value = (LCG_A * value + LCG_C) % LCG_M;
|
||||
return Math.floor(n * value / LCG_M);
|
||||
};
|
||||
// cyrb53a beta (c) 2023 bryc (github.com/bryc)
|
||||
function cyrb53a_beta(str, seed = 0) {
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
for (const codePoint of str) {
|
||||
ch = codePoint.codePointAt(0);
|
||||
h1 = Math.imul(h1 ^ ch, 0x85ebca77);
|
||||
h2 = Math.imul(h2 ^ ch, 0xc2b2ae3d);
|
||||
}
|
||||
h1 ^= Math.imul(h1 ^ (h2 >>> 15), 0x735a2d97);
|
||||
h2 ^= Math.imul(h2 ^ (h1 >>> 15), 0xcaf649a9);
|
||||
h1 ^= h2 >>> 16;
|
||||
h2 ^= h1 >>> 16;
|
||||
return 2097152 * (h2 >>> 0) + (h1 >>> 11);
|
||||
}
|
||||
|
||||
function seedableShuffledCopy(list, seed) {
|
||||
const gen = lcg(seed);
|
||||
const l = [...list];
|
||||
const SEED_BOUND = Math.pow(2, 32);
|
||||
|
||||
for (let i = 0; i < l.length - 1; ++i) {
|
||||
j = i + gen(l.length - i);
|
||||
const tmp = l[i];
|
||||
l[i] = l[j];
|
||||
l[j] = tmp;
|
||||
}
|
||||
return l;
|
||||
function seedableShuffledCopy(list, key, seed) {
|
||||
const hashedIndices = list.map((elem, idx) => ({ idx, hash: cyrb53a_beta(key(elem), seed) }));
|
||||
hashedIndices.sort((a, b) => {
|
||||
if (a.hash > b.hash) {
|
||||
return 1;
|
||||
}
|
||||
if (a.hash < b.hash) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return hashedIndices.map((entry) => list[entry.idx]);
|
||||
}
|
||||
|
||||
function newSeed() {
|
||||
return Math.floor(Math.random() * LCG_M);
|
||||
return Math.floor(Math.random() * SEED_BOUND);
|
||||
}
|
||||
|
||||
let receivedStore = JSON.parse(localStorage.getItem('receivedStore')) || {};
|
||||
|
@ -96,7 +101,7 @@ function setupIndex() {
|
|||
|
||||
switch (ordering) {
|
||||
case 'shuffle':
|
||||
orderedWorks = seedableShuffledCopy(WORKS, shuffleSeed);
|
||||
orderedWorks = seedableShuffledCopy(WORKS, (work) => work.id, shuffleSeed);
|
||||
break;
|
||||
case 'dateAsc':
|
||||
orderedWorks = WORKS.toReversed();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue