/** * How full a list of groups' spans are: for a sample of groups (from * group_sizes.ts's TSV), XOVER windows of `window` articles at evenly spaced * points; articles found / asked, weighted by span. * * node --env-file=.env --import=@poppinss/ts-exec tools/group_fill.ts groups.tsv [groups] [points] [window] */ import { readFileSync } from 'node:fs' import { XoverClient } from '#lib/nntp/index' const [file, fromRank, toRank] = process.argv.slice(2, 5) const sampleSize = Number(process.argv[5] ?? 25) const points = Number(process.argv[6] ?? 5) const window = Number(process.argv[7] ?? 1000) const rows = readFileSync(file, 'utf8').trim().split('\n').map((l) => l.split('\t')).filter((r) => Number(r[0]) >= Number(fromRank) && Number(r[0]) <= Number(toRank)) const step = rows.length / sampleSize const sample = Array.from({ length: sampleSize }, (_, i) => rows[Math.floor(i * step)]) const env = process.env const tasks = sample.flatMap(([, name, low, high]) => Array.from({ length: points }, (_, p) => ({ name, at: Math.floor(Number(low) + ((Number(high) - Number(low)) * (p + 0.5)) / points) }))) const found = new Map() await Promise.all( Array.from({ length: 4 }, async () => { const client = await XoverClient.connect({ host: env.NNTP_HOST!, port: Number(env.NNTP_PORT ?? 563), user: env.NNTP_USER, password: env.NNTP_PASSWORD, secure: (env.NNTP_SECURE ?? 'true') !== 'false', compress: true, timeoutMs: 60_000 }) let current = '' while (tasks.length) { const t = tasks.shift()! if (t.name !== current) await client.group((current = t.name)) const n = (await client.xover(t.at, t.at + window - 1)).length found.set(t.name, (found.get(t.name) ?? 0) + n) } client.close() }) ) let spanAll = 0 let existing = 0 for (const [, name, , , span] of sample) { const fill = (found.get(name) ?? 0) / (points * window) spanAll += Number(span) existing += Number(span) * fill console.log(`${name}\t${(100 * fill).toFixed(0)}%`) } console.log(`weighted fill ${(100 * existing / spanAll).toFixed(1)}% of the span`)