/** Ray-casting algorithm to test if a point is inside a polygon */ export function pointInPolygon(lat: number, lng: number, polygon: [number, number][]): boolean { let inside = false; for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { const [yi, xi] = polygon[i]; const [yj, xj] = polygon[j]; if ((yi > lat) !== (yj > lat) && lng < ((xj - xi) * (lat - yi)) / (yj - yi) + xi) { inside = !inside; } } return inside; } /** Format a number in French locale */ export const fr = (n: number, decimals = 2) => n.toLocaleString('fr-FR', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); export type CurrencyUnit = 'DU' | 'G1'; /** Format a G1 value in the given unit, with k/M suffix */ export function formatValue(g1Value: number, unit: CurrencyUnit, duDaily: number): string { const val = unit === 'DU' ? g1Value / duDaily : g1Value; const suffix = unit === 'DU' ? 'DU' : '\u011e1'; if (val >= 1_000_000) return fr(val / 1_000_000) + ' M' + suffix; if (val >= 1_000) return fr(val / 1_000) + ' k' + suffix; return fr(val) + ' ' + suffix; } /** Binary-search count of udBlocks entries >= joinBlock (udBlocks is sorted ascending). */ export function countUdSince(udBlocks: number[], joinBlock: number): number { let lo = 0, hi = udBlocks.length; while (lo < hi) { const mid = (lo + hi) >> 1; if (udBlocks[mid] < joinBlock) lo = mid + 1; else hi = mid; } return udBlocks.length - lo; } /** Date to ISO-like string (yyyy-mm-dd) */ export const dateToString = (date: Date) => date.getFullYear() + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2); /** Number of days between a date and today */ export const getDays = (date: string | undefined) => { if (!date) return 0; const d = new Date(date); const today = new Date(); return Math.floor(Math.abs(d.getTime() - today.getTime()) / (1000 * 3600 * 24)); }; /** Seniority ratio between two dates (days from today) */ export const getRatio = (date1: string | undefined, date2: string | undefined) => { return getDays(date1) / Math.max(getDays(date2), 1); }; export const Block0Date = '2017-03-08'; export type Friend = { name: string; date: string; }; export type TableFriend = Friend & { [key: string]: string | number; displayName: string; displayDate: string; du: number; };