feat: explain income dispersion within comparable sample groups
This commit is contained in:
@@ -11,7 +11,34 @@ import { openSiteDatabase } from "../src/lib/site-database";
|
||||
import { categorySummary, evidenceUrl, reviewCompanyIds, validateResearch, type ResearchSnapshot } from "../src/lib/ai-research";
|
||||
import { consumeCode, initializeStore } from "../src/lib/auth-store";
|
||||
import { newAuthConfig } from "../src/lib/auth";
|
||||
import { arrDisclosureCoverage, arrDisclosures, describeIncome, groupIncome, platformIncomeSample } from "../src/lib/research-statistics";
|
||||
import { arrDisclosureCoverage, arrDisclosures, compareIncomeGroups, describeIncome, groupIncome, platformIncomeSample } from "../src/lib/research-statistics";
|
||||
|
||||
test("income interpretations compare sufficient samples within a provider and known billing model", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
const makePoints = (cat: string, values: number[], provider = "Stripe", model = "软件订阅") => values.map((value, index) => ({
|
||||
company: { ...snapshot.companies[0], id: `${cat}-${provider}-${model}-${index}`, cat, businessModel: model },
|
||||
observation: { ...snapshot.observations[0], provider }, value,
|
||||
}));
|
||||
const points = [
|
||||
...makePoints("C04", [100, 100, 100]),
|
||||
...makePoints("C06", [10, 10, 1000]),
|
||||
...makePoints("C08", [1, 10000]),
|
||||
...makePoints("C09", [1, 10, 10000], "RevenueCat"),
|
||||
...makePoints("C10", [1, 10, 10000], "Stripe", "硬件服务"),
|
||||
...makePoints("C07", [0, 0, 0]),
|
||||
...makePoints("C01", [1, 10, 100], "Stripe", "收费模式未核验"),
|
||||
];
|
||||
const comparisons = compareIncomeGroups(groupIncome(points));
|
||||
assert.equal(comparisons.length, 1);
|
||||
assert.equal(comparisons[0].leastDispersed.category, "C04");
|
||||
assert.equal(comparisons[0].mostDispersed.category, "C06");
|
||||
assert.equal(comparisons[0].leastSensitive.category, "C04");
|
||||
assert.equal(comparisons[0].mostSensitive.category, "C06");
|
||||
assert.deepEqual(compareIncomeGroups(groupIncome(points, false)), [], "merged billing models are not comparable here");
|
||||
const annualized = compareIncomeGroups(groupIncome(points.map((point) => ({ ...point, value: point.value * 12 }))));
|
||||
assert.equal(annualized[0].mostSensitive.category, comparisons[0].mostSensitive.category);
|
||||
assert.ok(Math.abs(annualized[0].mostDispersed.stats.cv! - comparisons[0].mostDispersed.stats.cv!) < 1e-12);
|
||||
});
|
||||
|
||||
test("ARR coverage counts companies once and separates missing disclosures from zero income", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
|
||||
Reference in New Issue
Block a user