File size: 2,367 Bytes
5f24abe | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | export type LiteUsageBreakdownSource = {
model: string
name: string
cost: number
quotaCost: number
multiplier?: number
estimated: boolean
}
export type LiteUsageBreakdownItem = {
model: string
name: string
cost?: number
multiplier?: number
quotaCost: number
contributionPercent: number
estimated: boolean
}
export function buildLiteUsageBreakdown(input: { usage: number; limit: number; sources: LiteUsageBreakdownSource[] }) {
// Legacy usage can resolve to the same rate as a separately grouped recorded multiplier.
const groups = new Map<string, LiteUsageBreakdownSource>()
input.sources.forEach((item) => {
const key = JSON.stringify([item.model, item.multiplier])
const row = groups.get(key)
if (!row) {
groups.set(key, { ...item })
return
}
row.cost += item.cost
row.quotaCost += item.quotaCost
row.estimated ||= item.estimated
})
const rows: LiteUsageBreakdownItem[] = Array.from(groups.values())
.filter((item) => item.cost !== 0 || item.quotaCost !== 0)
.sort((a, b) => b.quotaCost - a.quotaCost)
.map((item) => ({
...item,
contributionPercent: 0,
}))
const usagePercent = getUsagePercent(input.usage, input.limit)
const target = Math.max(0, Math.round(usagePercent * 10))
const totalQuota = rows.reduce((total, item) => total + Math.max(0, item.quotaCost), 0)
const units = rows.map((item) => {
const exact = totalQuota === 0 ? 0 : (Math.max(0, item.quotaCost) / totalQuota) * target
const value = Math.floor(exact)
return { item, exact, value }
})
const remaining = target - units.reduce((total, item) => total + item.value, 0)
const ranked = units.toSorted((a, b) => b.exact - b.value - (a.exact - a.value))
Array.from({ length: ranked.length === 0 ? 0 : remaining }).forEach((_, index) => {
ranked[index % ranked.length].value += 1
})
units.forEach((unit) => (unit.item.contributionPercent = unit.value / 10))
return {
usage: input.usage,
limit: input.limit,
usagePercent,
rows,
}
}
export function getModelQuotaLimit(limit: number, multiplier?: number) {
if (multiplier === undefined || multiplier <= 0) return
return limit / multiplier
}
export function getUsagePercent(amount: number, limit: number) {
if (limit === 0) return 0
return Math.round((amount / limit) * 1000) / 10
}
|