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