export function cycleNext(current: number, max: number) { if (current + 1 === max) return 0; else return current + 1; } export function cyclePrev(current: number, max: number) { if (current === 0) return max; else return current - 1; } export function randomFromArray(a: Array): T { const l = a.length; if (l === 0) throw new Error("Empty array!"); const randomIdx = Math.floor(Math.random() * l); const idx = randomIdx === l ? randomIdx - 1 : randomIdx; const el = a[idx]!; return el; } export function randomFromArrayMany( a: Array, count: number, canRepeat = false, ): Array { if (canRepeat) return [...new Array(count)].map((s) => randomFromArray(a)); else return randomFromArrayNoRepeat(a, count); } export function randomFromArrayNoRepeat( a: Array, count: number, acc?: Set, ): T[] { const all = new Set(a); const st = acc ? acc : new Set(); if (all.size === st.size || st.size === count) return [...st]; const el = randomFromArray(a); if (!st.has(el)) st.add(el); return randomFromArrayNoRepeat(a, count, st); } export function notRandomFromArray(data: string, a: Array): T { const l = a.length; const ind = hashTextToNumber(data, l - 1); return a[ind]!; } function hashTextToNumber(text: string, max: number): number { let hash = 0; for (let i = 0; i < text.length; i++) { const char = text.charCodeAt(i); hash = (hash << 5) - hash + char; hash = hash & hash; // Convert to 32-bit integer } // Make sure the hash is positive and within the given range return Math.abs(hash) % max; } // Format time for display (HH:MM:SS) export const formatTime = (seconds: number): string => { const hrs = Math.floor(seconds / 3600); const mins = Math.floor((seconds % 3600) / 60); const secs = Math.floor(seconds % 60); return `${hrs.toString().padStart(2, "0")}:${mins .toString() .padStart(2, "0")}:${secs.toString().padStart(2, "0")}`; }; export function date_diff(date: number, type: "short" | "long") { const now = new Date().getTime(); const diff = now - new Date(date).getTime(); if (type == "short") { return to_string(diff / 1000); } else { return to_string_long(diff / 1000); } } function to_string(s: number) { if (s < 60) { return "now"; } else if (s < 3600) { return `${Math.ceil(s / 60)}m`; } else if (s < 86400) { return `${Math.ceil(s / 60 / 60)}h`; } else if (s < 2678400) { return `${Math.ceil(s / 60 / 60 / 24)}d`; } else if (s < 32140800) { return `${Math.ceil(s / 60 / 60 / 24 / 30)}mo`; } else { return `${Math.ceil(s / 60 / 60 / 24 / 30 / 12)}y`; } } function to_string_long(s: number) { if (s < 60) { return "right now"; } else if (s < 3600) { return `${Math.ceil(s / 60)} minutes ago`; } else if (s < 86400) { return `${Math.ceil(s / 60 / 60)} hours ago`; } else if (s < 2678400) { return `${Math.ceil(s / 60 / 60 / 24)} days ago`; } else if (s < 32140800) { return `${Math.ceil(s / 60 / 60 / 24 / 30)} months ago`; } else { return `${Math.ceil(s / 60 / 60 / 24 / 30 / 12)} years ago`; } }