2022-02-18 19:28:52 +01:00
|
|
|
import { utcToZonedTime } from 'date-fns-tz'
|
|
|
|
|
|
|
|
import { BXL_TZ, GAME_STARTING_DATE } from '@/globals'
|
|
|
|
|
|
|
|
export function getCurrentDate(): Date {
|
|
|
|
return utcToZonedTime(new Date(), BXL_TZ)
|
|
|
|
}
|
|
|
|
|
2022-02-22 22:52:50 +01:00
|
|
|
export function getCurrentSessionKey(): string {
|
2022-02-22 22:54:01 +01:00
|
|
|
const now = getCurrentDate()
|
|
|
|
// https://stackoverflow.com/a/28149561
|
|
|
|
const tzoffset = now.getTimezoneOffset() * 60000
|
|
|
|
const localISOTime = new Date(now.getTime() - tzoffset).toISOString()
|
|
|
|
return localISOTime.slice(0, 10)
|
2022-02-22 22:52:50 +01:00
|
|
|
}
|
|
|
|
|
2022-02-23 22:39:53 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param a
|
|
|
|
* @param b
|
|
|
|
* @returns Percentage rounded to 2 decimals
|
|
|
|
*/
|
|
|
|
export function percentageDiff(a: number, b: number): number {
|
|
|
|
return Math.round(((a - b) / ((a + b) / 2)) * 100) / 100
|
|
|
|
}
|
|
|
|
|
2022-02-18 19:28:52 +01:00
|
|
|
// #region RNG
|
|
|
|
|
|
|
|
export let random = Math.random
|
|
|
|
|
2022-02-07 22:14:31 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param min inclusive
|
|
|
|
* @param max exclusive
|
|
|
|
* @returns
|
|
|
|
*/
|
2022-02-18 19:28:52 +01:00
|
|
|
export function randRange(min: number, max: number, rnd = random): number {
|
2022-02-09 22:10:58 +01:00
|
|
|
return Math.floor(rnd() * (max - min) + min)
|
|
|
|
}
|
|
|
|
|
2022-02-18 19:28:52 +01:00
|
|
|
export function randItem<T>(items: T[], rnd = random): T {
|
2022-02-09 22:10:58 +01:00
|
|
|
return items[Math.floor(rnd() * items.length)]
|
2022-02-07 22:14:31 +01:00
|
|
|
}
|
2022-02-18 12:24:25 +01:00
|
|
|
|
2022-02-18 19:28:52 +01:00
|
|
|
export function setMathPRNG(): void {
|
|
|
|
random = Math.random
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setDailyPRNG(): void {
|
|
|
|
random = initDailyPRNG()
|
|
|
|
}
|
|
|
|
|
2022-02-18 12:24:25 +01:00
|
|
|
/**
|
|
|
|
* Shuffles an array in place and returns it
|
|
|
|
* @param array
|
|
|
|
* @returns
|
|
|
|
*/
|
|
|
|
export function shuffle<T>(array: T[]): T[] {
|
|
|
|
let currentIndex = array.length
|
2022-02-18 19:28:52 +01:00
|
|
|
let randomIndex: number
|
2022-02-18 12:24:25 +01:00
|
|
|
|
|
|
|
// While there remain elements to shuffle...
|
|
|
|
while (currentIndex !== 0) {
|
|
|
|
// Pick a remaining element...
|
2022-02-18 19:28:52 +01:00
|
|
|
randomIndex = Math.floor(random() * currentIndex)
|
2022-02-18 12:24:25 +01:00
|
|
|
currentIndex--
|
|
|
|
|
|
|
|
// And swap it with the current element.
|
|
|
|
;[array[currentIndex], array[randomIndex]] = [
|
|
|
|
array[randomIndex],
|
|
|
|
array[currentIndex],
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
return array
|
|
|
|
}
|
2022-02-18 19:28:52 +01:00
|
|
|
|
|
|
|
function initDailyPRNG(): () => number {
|
|
|
|
// Prefix the seed when in dev to avoid spoiling myself while working on it
|
|
|
|
const prefix = import.meta.env.DEV ? 'dev-' : ''
|
2022-02-22 22:52:50 +01:00
|
|
|
const hashed = hashStr(prefix + getCurrentSessionKey())
|
2022-02-18 19:28:52 +01:00
|
|
|
return mulberry32(hashed)
|
|
|
|
}
|
|
|
|
|
|
|
|
function mulberry32(a: number) {
|
|
|
|
return function () {
|
|
|
|
let t = (a += 0x6d2b79f5)
|
|
|
|
t = Math.imul(t ^ (t >>> 15), t | 1)
|
|
|
|
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
|
|
|
|
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* https://stackoverflow.com/a/7616484
|
|
|
|
* @param val
|
|
|
|
* @returns
|
|
|
|
*/
|
|
|
|
function hashStr(val: string): number {
|
|
|
|
let hash = 0
|
|
|
|
if (val.length === 0) {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
for (let i = 0; i < val.length; ++i) {
|
|
|
|
hash = (hash << 5) - hash + val[i].charCodeAt(0)
|
|
|
|
hash |= 0
|
|
|
|
}
|
|
|
|
return hash
|
|
|
|
}
|
|
|
|
|
|
|
|
// #endregion RNG
|