Overhaul market system with shared TAM competition, multi-tier pricing, enterprise pipeline, and developer ecosystem
CI / build-and-push (push) Successful in 42s
CI / build-and-push (push) Successful in 42s
Replaces the simplified single-subscriber market with a full competitive simulation: shared TAM with softmax market shares across 4 segments, multi-tier consumer subscriptions (Free/Plus/Pro/Team) and API tiers (Free/PAYG/Scale/Enterprise), enterprise sales pipeline (Lead→Qualification→POC→Negotiation→Active→Renewal) with SLA tracking, developer ecosystem flywheel, technology obsolescence pressure, seasonal demand cycles, and two new product lines (Code Assistant, AI Agents Platform). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import type { ApiTierState, ApiTierId, DeveloperEcosystem } from '@ai-tycoon/shared';
|
||||
import {
|
||||
API_TIER_ORDER,
|
||||
API_CONVERSION_RATES,
|
||||
API_TIER_CHURN_RATES,
|
||||
API_TOKENS_PER_DEVELOPER_PER_TICK,
|
||||
} from '@ai-tycoon/shared';
|
||||
|
||||
export interface ApiTickResult {
|
||||
apiTiers: ApiTierState;
|
||||
apiRevenue: number;
|
||||
totalApiTokenDemand: number;
|
||||
}
|
||||
|
||||
export function processApiTiers(
|
||||
tiers: ApiTierState,
|
||||
playerDevCustomers: number,
|
||||
modelQuality: number,
|
||||
seasonalApiMultiplier: number,
|
||||
ecosystem: DeveloperEcosystem,
|
||||
): ApiTickResult {
|
||||
const updated: ApiTierState = {
|
||||
tiers: { ...tiers.tiers },
|
||||
totalDevelopers: 0,
|
||||
totalTokensPerTick: 0,
|
||||
};
|
||||
|
||||
for (const id of API_TIER_ORDER) {
|
||||
updated.tiers[id] = { ...tiers.tiers[id], config: { ...tiers.tiers[id].config } };
|
||||
}
|
||||
|
||||
if (modelQuality <= 0) {
|
||||
return { apiTiers: updated, apiRevenue: 0, totalApiTokenDemand: 0 };
|
||||
}
|
||||
|
||||
const targetFreeDevelopers = playerDevCustomers * 0.1 * seasonalApiMultiplier;
|
||||
const freeGrowth = (targetFreeDevelopers - updated.tiers.free.developerCount) * 0.03;
|
||||
updated.tiers.free.developerCount = Math.max(0, updated.tiers.free.developerCount + freeGrowth);
|
||||
const freeChurn = updated.tiers.free.developerCount * API_TIER_CHURN_RATES.free;
|
||||
updated.tiers.free.developerCount = Math.max(0, updated.tiers.free.developerCount - freeChurn);
|
||||
updated.tiers.free.churnRate = API_TIER_CHURN_RATES.free;
|
||||
|
||||
const prevTierMap: Record<ApiTierId, ApiTierId | null> = {
|
||||
free: null,
|
||||
payg: 'free',
|
||||
scale: 'payg',
|
||||
'enterprise-api': 'scale',
|
||||
};
|
||||
|
||||
for (const id of API_TIER_ORDER) {
|
||||
if (id === 'free') continue;
|
||||
const tier = updated.tiers[id];
|
||||
if (!tier.config.isActive) continue;
|
||||
|
||||
const prevId = prevTierMap[id];
|
||||
if (!prevId) continue;
|
||||
const prevTier = updated.tiers[prevId];
|
||||
|
||||
const convKey = `${prevId}->${id}`;
|
||||
const baseRate = API_CONVERSION_RATES[convKey] ?? 0;
|
||||
const ecosystemBoost = 1 + ecosystem.ecosystemScore / 200;
|
||||
const convRate = baseRate * Math.max(0.1, modelQuality) * ecosystemBoost * seasonalApiMultiplier;
|
||||
|
||||
const converting = prevTier.developerCount * convRate;
|
||||
prevTier.developerCount = Math.max(0, prevTier.developerCount - converting);
|
||||
tier.developerCount += converting;
|
||||
|
||||
tier.churnRate = API_TIER_CHURN_RATES[id];
|
||||
const churned = tier.developerCount * tier.churnRate;
|
||||
tier.developerCount = Math.max(0, tier.developerCount - churned);
|
||||
}
|
||||
|
||||
let totalDevelopers = 0;
|
||||
let totalTokens = 0;
|
||||
let apiRevenue = 0;
|
||||
|
||||
for (const id of API_TIER_ORDER) {
|
||||
const tier = updated.tiers[id];
|
||||
totalDevelopers += tier.developerCount;
|
||||
|
||||
const tokensPerDev = API_TOKENS_PER_DEVELOPER_PER_TICK[id];
|
||||
tier.tokensPerTick = tier.developerCount * tokensPerDev;
|
||||
totalTokens += tier.tokensPerTick;
|
||||
|
||||
apiRevenue += tier.developerCount * (tier.config.monthlyFee / 86400);
|
||||
apiRevenue += (tier.tokensPerTick / 1_000_000) * tier.config.outputTokenPrice;
|
||||
}
|
||||
|
||||
updated.totalDevelopers = totalDevelopers;
|
||||
updated.totalTokensPerTick = totalTokens;
|
||||
|
||||
return {
|
||||
apiTiers: updated,
|
||||
apiRevenue: Math.max(0, apiRevenue),
|
||||
totalApiTokenDemand: totalTokens,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user