626ca51041
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
72 lines
2.6 KiB
TypeScript
72 lines
2.6 KiB
TypeScript
import type { DeveloperEcosystem } from '@ai-tycoon/shared';
|
|
import {
|
|
BASE_DEV_GROWTH,
|
|
FREE_TIER_DEV_MULTIPLIER,
|
|
OPEN_SOURCE_DEV_BOOST,
|
|
DEV_REL_EFFECTIVENESS,
|
|
SDK_GROWTH_BONUS,
|
|
DEV_ECOSYSTEM_WEIGHTS,
|
|
STARTUP_ADOPTION_PER_DEV,
|
|
ENTERPRISE_REFERRAL_PER_STARTUP,
|
|
TAM_BASE_SIZES,
|
|
} from '@ai-tycoon/shared';
|
|
import type { Era } from '@ai-tycoon/shared';
|
|
|
|
export function processDeveloperEcosystem(
|
|
eco: DeveloperEcosystem,
|
|
openSourceCount: number,
|
|
apiFreeTierDevs: number,
|
|
apiTotalDevs: number,
|
|
engineeringHeadcount: number,
|
|
era: Era,
|
|
): DeveloperEcosystem {
|
|
const updated = { ...eco };
|
|
|
|
const eraCap = TAM_BASE_SIZES[era].developer;
|
|
|
|
const growthRate =
|
|
BASE_DEV_GROWTH +
|
|
apiFreeTierDevs * FREE_TIER_DEV_MULTIPLIER +
|
|
openSourceCount * OPEN_SOURCE_DEV_BOOST +
|
|
updated.devRelSpending * DEV_REL_EFFECTIVENESS +
|
|
updated.sdkCoverage * SDK_GROWTH_BONUS;
|
|
|
|
const logisticDamping = Math.max(0, 1 - updated.communitySize / Math.max(1, eraCap));
|
|
updated.communityGrowthRate = growthRate * logisticDamping;
|
|
updated.communitySize = Math.max(0, updated.communitySize + updated.communitySize * updated.communityGrowthRate);
|
|
|
|
if (updated.communitySize < 10 && apiTotalDevs > 0) {
|
|
updated.communitySize += 1 + apiTotalDevs * 0.1;
|
|
}
|
|
|
|
updated.activeDevelopers = apiTotalDevs;
|
|
updated.openSourceContributions = openSourceCount;
|
|
|
|
const sdkTarget = Math.min(1, engineeringHeadcount / 50);
|
|
updated.sdkCoverage += (sdkTarget - updated.sdkCoverage) * 0.005;
|
|
updated.sdkCoverage = Math.min(1, Math.max(0, updated.sdkCoverage));
|
|
|
|
const docTarget = Math.min(1, updated.devRelSpending / 500);
|
|
updated.documentationQuality += (docTarget - updated.documentationQuality) * 0.003;
|
|
updated.documentationQuality = Math.min(1, Math.max(0, updated.documentationQuality));
|
|
|
|
const communityNorm = Math.min(1, updated.communitySize / Math.max(1, eraCap * 0.1));
|
|
const activeRatio = updated.communitySize > 0
|
|
? Math.min(1, updated.activeDevelopers / updated.communitySize)
|
|
: 0;
|
|
const osNorm = Math.min(1, openSourceCount / 5);
|
|
|
|
updated.ecosystemScore = (
|
|
DEV_ECOSYSTEM_WEIGHTS.communitySize * communityNorm +
|
|
DEV_ECOSYSTEM_WEIGHTS.activeRatio * activeRatio +
|
|
DEV_ECOSYSTEM_WEIGHTS.sdkCoverage * updated.sdkCoverage +
|
|
DEV_ECOSYSTEM_WEIGHTS.docQuality * updated.documentationQuality +
|
|
DEV_ECOSYSTEM_WEIGHTS.openSource * osNorm
|
|
) * 100;
|
|
|
|
updated.startupsAdopted = Math.floor(updated.activeDevelopers * STARTUP_ADOPTION_PER_DEV);
|
|
updated.enterpriseReferrals = Math.floor(updated.startupsAdopted * ENTERPRISE_REFERRAL_PER_STARTUP);
|
|
|
|
return updated;
|
|
}
|