Files
AIHostingTycoon/packages/game-engine/src/systems/market/developerEcosystem.ts
T
2026-04-26 08:16:02 -04:00

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;
}