/** * Tutarı (kuruş, tam sayı) oranlara göre paylaştırır. Artan kuruşlar en büyük kalan * yöntemiyle dağıtılır (eşitlikte önce gelen pay); toplam her zaman korunur. */ export function allocate(amount: number, ratios: number[]): number[] { if (!Number.isInteger(amount) || amount < 0) throw new TypeError('amount negatif olmayan tam sayı (kuruş) olmalı'); if (ratios.length === 0) throw new RangeError('en az bir oran gerekli'); if (ratios.some((r) => r < 0)) throw new RangeError('oranlar negatif olamaz'); const total = ratios.reduce((a, b) => a + b, 0); if (total === 0) throw new RangeError('oranların toplamı sıfır olamaz'); const exact = ratios.map((r) => (amount * r) / total); const shares = exact.map((x) => Math.floor(x)); const remainder = amount - shares.reduce((a, b) => a + b, 0); const order = exact .map((x, i) => ({ i, frac: x - Math.floor(x) })) .sort((a, b) => b.frac - a.frac || a.i - b.i); for (let k = 0; k < remainder; k++) shares[order[k].i] += 1; return shares; } /** Tutarı `parts` eşit paya böler; artan kuruşlar baştaki paylara gider. */ export function splitEvenly(amount: number, parts: number): number[] { if (!Number.isInteger(parts) || parts < 1) throw new RangeError('parts en az 1 olmalı'); return allocate(amount, new Array(parts).fill(1)); }