25ee793208
* Factor out section header * Remove daily balance change * Remove dead code * Layout, add streak * Fix visibility observer to work on server * Tweak * Search perserved by url * Add pill query param * Add search page * Extract component for ProbChangeRow * Explore groups page * Add search row * Add trending groups section * Add unfollow option for group * Experimental home: accommodate old saved sections. * Tweaks to search layout * Rearrange layout * Daily movers page * Add streak grayed out indicator * Use firebase query instead of algolia search for groups * Replace trending group card with pills * Hide streak if you turned off that notification * Listen for group updates * Better UI for adding / removing groups * Toast feedback for join/leave group. Customize button moved to bottom. * Remove Home title * Refactor arrange home * Add new for you section * Add prefetch * Move home out of experimental! * Remove unused import * Show non-public markets from group
56 lines
1.4 KiB
TypeScript
56 lines
1.4 KiB
TypeScript
export const randomString = (length = 12) =>
|
|
Math.random()
|
|
.toString(16)
|
|
.substring(2, length + 2)
|
|
|
|
export function genHash(str: string) {
|
|
// xmur3
|
|
let h: number
|
|
for (let i = 0, h = 1779033703 ^ str.length; i < str.length; i++) {
|
|
h = Math.imul(h ^ str.charCodeAt(i), 3432918353)
|
|
h = (h << 13) | (h >>> 19)
|
|
}
|
|
return function () {
|
|
h = Math.imul(h ^ (h >>> 16), 2246822507)
|
|
h = Math.imul(h ^ (h >>> 13), 3266489909)
|
|
return (h ^= h >>> 16) >>> 0
|
|
}
|
|
}
|
|
|
|
export function createRNG(seed: string) {
|
|
// https://stackoverflow.com/a/47593316/1592933
|
|
|
|
const gen = genHash(seed)
|
|
let [a, b, c, d] = [gen(), gen(), gen(), gen()]
|
|
|
|
// sfc32
|
|
return function () {
|
|
a >>>= 0
|
|
b >>>= 0
|
|
c >>>= 0
|
|
d >>>= 0
|
|
let t = (a + b) | 0
|
|
a = b ^ (b >>> 9)
|
|
b = (c + (c << 3)) | 0
|
|
c = (c << 21) | (c >>> 11)
|
|
d = (d + 1) | 0
|
|
t = (t + d) | 0
|
|
c = (c + t) | 0
|
|
return (t >>> 0) / 4294967296
|
|
}
|
|
}
|
|
|
|
export const shuffle = (array: unknown[], rand: () => number) => {
|
|
for (let i = 0; i < array.length; i++) {
|
|
const swapIndex = Math.floor(rand() * (array.length - i))
|
|
;[array[i], array[swapIndex]] = [array[swapIndex], array[i]]
|
|
}
|
|
}
|
|
|
|
export function chooseRandomSubset<T>(items: T[], count: number) {
|
|
const fiveMinutes = 5 * 60 * 1000
|
|
const seed = Math.round(Date.now() / fiveMinutes).toString()
|
|
shuffle(items, createRNG(seed))
|
|
return items.slice(0, count)
|
|
}
|