Compare commits
2 Commits
5e4007160c
...
035d4f0385
| Author | SHA1 | Date | |
|---|---|---|---|
| 035d4f0385 | |||
| c1cc70eeb9 |
@@ -35,7 +35,7 @@ jobs:
|
|||||||
run: pnpm test
|
run: pnpm test
|
||||||
|
|
||||||
- name: Run greedy simulation
|
- name: Run greedy simulation
|
||||||
run: pnpm --filter @ai-tycoon/game-simulation simulate:ci
|
run: pnpm --filter @token-empire/game-simulation simulate:ci
|
||||||
|
|
||||||
multi-run-balance:
|
multi-run-balance:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -54,8 +54,8 @@ jobs:
|
|||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run multi-simulation (100 runs)
|
- name: Run multi-simulation (100 runs)
|
||||||
run: pnpm --filter @ai-tycoon/game-simulation multirun -- --runs 100 --parallel 10 --strategy persona --ticks 28800 --no-timeseries
|
run: pnpm --filter @token-empire/game-simulation multirun -- --runs 100 --parallel 10 --strategy persona --ticks 28800 --no-timeseries
|
||||||
|
|
||||||
- name: Interpret results
|
- name: Interpret results
|
||||||
if: always()
|
if: always()
|
||||||
run: pnpm --filter @ai-tycoon/game-simulation interpret -- --summary multirun-summary.csv
|
run: pnpm --filter @token-empire/game-simulation interpret -- --summary multirun-summary.csv
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: gitea.thewrightserver.net
|
REGISTRY: gitea.thewrightserver.net
|
||||||
IMAGE_PREFIX: gitea.thewrightserver.net/josh/aihostingtycoon
|
IMAGE_PREFIX: gitea.thewrightserver.net/josh/tokenempire
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-push:
|
build-and-push:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# AI Tycoon
|
# Token Empire
|
||||||
|
|
||||||
A browser-based incremental/idle game where you manage an AI company from a garage startup to building AGI. Navigate the real tensions of the AI industry: scaling compute, training frontier models, balancing safety vs capability, hiring talent, and competing with rival labs.
|
A browser-based incremental/idle game where you manage an AI company from a garage startup to building AGI. Navigate the real tensions of the AI industry: scaling compute, training frontier models, balancing safety vs capability, hiring talent, and competing with rival labs.
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ The web app starts at `http://localhost:5173` (or the next available port). The
|
|||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
ai-tycoon/
|
token-empire/
|
||||||
├── apps/
|
├── apps/
|
||||||
│ ├── web/ # React frontend (Vite)
|
│ ├── web/ # React frontend (Vite)
|
||||||
│ └── server/ # Hono API backend
|
│ └── server/ # Hono API backend
|
||||||
@@ -81,7 +81,7 @@ pnpm clean # Clean build artifacts
|
|||||||
The backend requires PostgreSQL for cloud saves and leaderboards. Set the connection string in `apps/server/.env`:
|
The backend requires PostgreSQL for cloud saves and leaderboards. Set the connection string in `apps/server/.env`:
|
||||||
|
|
||||||
```
|
```
|
||||||
DATABASE_URL=postgresql://user:password@localhost:5432/ai_tycoon
|
DATABASE_URL=postgresql://user:password@localhost:5432/token_empire
|
||||||
```
|
```
|
||||||
|
|
||||||
Run migrations:
|
Run migrations:
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ COPY --from=deps /app/node_modules ./node_modules
|
|||||||
COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules
|
COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules
|
||||||
COPY --from=deps /app/apps/server/node_modules ./apps/server/node_modules
|
COPY --from=deps /app/apps/server/node_modules ./apps/server/node_modules
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN pnpm --filter @ai-tycoon/shared build && \
|
RUN pnpm --filter @token-empire/shared build && \
|
||||||
pnpm --filter @ai-tycoon/server typecheck
|
pnpm --filter @token-empire/server typecheck
|
||||||
|
|
||||||
FROM base AS production
|
FROM base AS production
|
||||||
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
|
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ export default defineConfig({
|
|||||||
schema: './src/db/schema.ts',
|
schema: './src/db/schema.ts',
|
||||||
out: './drizzle',
|
out: './drizzle',
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
url: process.env.DATABASE_URL ?? 'postgresql://localhost:5432/ai_tycoon',
|
url: process.env.DATABASE_URL ?? 'postgresql://localhost:5432/token_empire',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@ai-tycoon/server",
|
"name": "@token-empire/server",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"db:push": "drizzle-kit push"
|
"db:push": "drizzle-kit push"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-tycoon/shared": "workspace:*",
|
"@token-empire/shared": "workspace:*",
|
||||||
"@hono/node-server": "^1.13.8",
|
"@hono/node-server": "^1.13.8",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"drizzle-orm": "^0.44.2",
|
"drizzle-orm": "^0.44.2",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ai-tycoon/tsconfig": "workspace:*",
|
"@token-empire/tsconfig": "workspace:*",
|
||||||
"@types/node": "^25.6.0",
|
"@types/node": "^25.6.0",
|
||||||
"drizzle-kit": "^0.31.1",
|
"drizzle-kit": "^0.31.1",
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { migrate } from 'drizzle-orm/postgres-js/migrator';
|
|||||||
import postgres from 'postgres';
|
import postgres from 'postgres';
|
||||||
import * as schema from './schema';
|
import * as schema from './schema';
|
||||||
|
|
||||||
const connectionString = process.env.DATABASE_URL ?? 'postgresql://localhost:5432/ai_tycoon';
|
const connectionString = process.env.DATABASE_URL ?? 'postgresql://localhost:5432/token_empire';
|
||||||
|
|
||||||
const client = postgres(connectionString);
|
const client = postgres(connectionString);
|
||||||
export const db = drizzle(client, { schema });
|
export const db = drizzle(client, { schema });
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ app.route('/api/invites', invitesRouter);
|
|||||||
|
|
||||||
const port = Number(process.env.PORT) || 3001;
|
const port = Number(process.env.PORT) || 3001;
|
||||||
|
|
||||||
console.log(`AI Tycoon API server starting on port ${port}...`);
|
console.log(`Token Empire API server starting on port ${port}...`);
|
||||||
|
|
||||||
await runMigrations();
|
await runMigrations();
|
||||||
await seedAdmin();
|
await seedAdmin();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "@ai-tycoon/tsconfig/node.json",
|
"extends": "@token-empire/tsconfig/node.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src"
|
"rootDir": "src"
|
||||||
|
|||||||
+3
-3
@@ -18,9 +18,9 @@ COPY --from=deps /app/apps/web/node_modules ./apps/web/node_modules
|
|||||||
COPY . .
|
COPY . .
|
||||||
ARG VITE_API_URL=
|
ARG VITE_API_URL=
|
||||||
ENV VITE_API_URL=$VITE_API_URL
|
ENV VITE_API_URL=$VITE_API_URL
|
||||||
RUN pnpm --filter @ai-tycoon/shared build && \
|
RUN pnpm --filter @token-empire/shared build && \
|
||||||
pnpm --filter @ai-tycoon/game-engine build && \
|
pnpm --filter @token-empire/game-engine build && \
|
||||||
pnpm --filter @ai-tycoon/web build
|
pnpm --filter @token-empire/web build
|
||||||
|
|
||||||
FROM nginx:alpine
|
FROM nginx:alpine
|
||||||
COPY --from=build /app/apps/web/dist /usr/share/nginx/html
|
COPY --from=build /app/apps/web/dist /usr/share/nginx/html
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>AI Tycoon</title>
|
<title>Token Empire</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@ai-tycoon/web",
|
"name": "@token-empire/web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-tycoon/shared": "workspace:*",
|
"@token-empire/shared": "workspace:*",
|
||||||
"@ai-tycoon/game-engine": "workspace:*",
|
"@token-empire/game-engine": "workspace:*",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"recharts": "^2.15.0",
|
"recharts": "^2.15.0",
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"lucide-react": "^0.475.0"
|
"lucide-react": "^0.475.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ai-tycoon/tsconfig": "workspace:*",
|
"@token-empire/tsconfig": "workspace:*",
|
||||||
"@types/react": "^19.1.0",
|
"@types/react": "^19.1.0",
|
||||||
"@types/react-dom": "^19.1.0",
|
"@types/react-dom": "^19.1.0",
|
||||||
"@vitejs/plugin-react": "^4.4.0",
|
"@vitejs/plugin-react": "^4.4.0",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { OfflineCatchUp } from '@/components/game/OfflineCatchUp';
|
|||||||
import { InviteGateScreen } from '@/components/game/InviteGateScreen';
|
import { InviteGateScreen } from '@/components/game/InviteGateScreen';
|
||||||
import { useGameLoop } from '@/hooks/useGameLoop';
|
import { useGameLoop } from '@/hooks/useGameLoop';
|
||||||
import { useAuthGate } from '@/hooks/useAuthGate';
|
import { useAuthGate } from '@/hooks/useAuthGate';
|
||||||
import { TICK_INTERVAL_MS } from '@ai-tycoon/shared';
|
import { TICK_INTERVAL_MS } from '@token-empire/shared';
|
||||||
import { Sparkles, RefreshCw, WifiOff } from 'lucide-react';
|
import { Sparkles, RefreshCw, WifiOff } from 'lucide-react';
|
||||||
|
|
||||||
function LoadingScreen() {
|
function LoadingScreen() {
|
||||||
@@ -16,7 +16,7 @@ function LoadingScreen() {
|
|||||||
<div className="inline-flex items-center gap-2 mb-4">
|
<div className="inline-flex items-center gap-2 mb-4">
|
||||||
<Sparkles className="text-accent-light animate-pulse" size={32} />
|
<Sparkles className="text-accent-light animate-pulse" size={32} />
|
||||||
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
||||||
AI Tycoon
|
Token Empire
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-surface-500 text-sm">Loading...</p>
|
<p className="text-surface-500 text-sm">Loading...</p>
|
||||||
@@ -32,7 +32,7 @@ function BackendErrorScreen({ error, onRetry }: { error: string; onRetry: () =>
|
|||||||
<div className="inline-flex items-center gap-2 mb-6">
|
<div className="inline-flex items-center gap-2 mb-6">
|
||||||
<Sparkles className="text-accent-light" size={32} />
|
<Sparkles className="text-accent-light" size={32} />
|
||||||
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
||||||
AI Tycoon
|
Token Empire
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { X, CheckCircle, AlertTriangle, AlertCircle, Info, Bell, Trash2 } from 'lucide-react';
|
import { X, CheckCircle, AlertTriangle, AlertCircle, Info, Bell, Trash2 } from 'lucide-react';
|
||||||
import { useGameStore, type GameNotification } from '@/store';
|
import { useGameStore, type GameNotification } from '@/store';
|
||||||
import { formatDuration } from '@ai-tycoon/shared';
|
import { formatDuration } from '@token-empire/shared';
|
||||||
|
|
||||||
const ICON_MAP = {
|
const ICON_MAP = {
|
||||||
success: { icon: CheckCircle, color: 'text-success' },
|
success: { icon: CheckCircle, color: 'text-success' },
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export function DevMenu() {
|
|||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [activeTab, setActiveTab] = useState<Tab>('resources');
|
const [activeTab, setActiveTab] = useState<Tab>('resources');
|
||||||
|
|
||||||
const isEnabled = import.meta.env.DEV || localStorage.getItem('ai-tycoon-dev-menu') === 'true';
|
const isEnabled = import.meta.env.DEV || localStorage.getItem('token-empire-dev-menu') === 'true';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isEnabled) return;
|
if (!isEnabled) return;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import type { FundingRoundType } from '@ai-tycoon/shared';
|
import type { FundingRoundType } from '@token-empire/shared';
|
||||||
|
|
||||||
function DevButton({ onClick, children, variant = 'default' }: {
|
function DevButton({ onClick, children, variant = 'default' }: {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatMoney } from '@ai-tycoon/shared';
|
import { formatMoney } from '@token-empire/shared';
|
||||||
|
|
||||||
function DevButton({ onClick, children, variant = 'default' }: {
|
function DevButton({ onClick, children, variant = 'default' }: {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatMoney, formatNumber, formatFlops, formatPercent } from '@ai-tycoon/shared';
|
import { formatMoney, formatNumber, formatFlops, formatPercent } from '@token-empire/shared';
|
||||||
|
|
||||||
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { processTick, setAchievementDefinitions, ACHIEVEMENT_DEFINITIONS, TECH_TREE } from '@ai-tycoon/game-engine';
|
import { processTick, setAchievementDefinitions, ACHIEVEMENT_DEFINITIONS, TECH_TREE } from '@token-empire/game-engine';
|
||||||
import type { GameState, Era } from '@ai-tycoon/shared';
|
import type { GameState, Era } from '@token-empire/shared';
|
||||||
|
|
||||||
function DevButton({ onClick, children, variant = 'default' }: {
|
function DevButton({ onClick, children, variant = 'default' }: {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatMoney, formatNumber, formatPercent } from '@ai-tycoon/shared';
|
import { formatMoney, formatNumber, formatPercent } from '@token-empire/shared';
|
||||||
import { Share2, Copy, Check } from 'lucide-react';
|
import { Share2, Copy, Check } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { ACHIEVEMENT_DEFINITIONS } from '@ai-tycoon/game-engine';
|
import { ACHIEVEMENT_DEFINITIONS } from '@token-empire/game-engine';
|
||||||
|
|
||||||
export function CompanyStatsCard({ onClose }: { onClose: () => void }) {
|
export function CompanyStatsCard({ onClose }: { onClose: () => void }) {
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
@@ -25,7 +25,7 @@ export function CompanyStatsCard({ onClose }: { onClose: () => void }) {
|
|||||||
const minutes = Math.floor((totalPlayTime % 3600) / 60);
|
const minutes = Math.floor((totalPlayTime % 3600) / 60);
|
||||||
|
|
||||||
const statsText = [
|
const statsText = [
|
||||||
`${companyName} — AI Tycoon`,
|
`${companyName} — Token Empire`,
|
||||||
`Era: ${eraLabel} | Playtime: ${hours}h ${minutes}m`,
|
`Era: ${eraLabel} | Playtime: ${hours}h ${minutes}m`,
|
||||||
`Cash: ${formatMoney(money)} | Revenue: ${formatMoney(totalRevenue)}`,
|
`Cash: ${formatMoney(money)} | Revenue: ${formatMoney(totalRevenue)}`,
|
||||||
`Valuation: ${formatMoney(valuation)}`,
|
`Valuation: ${formatMoney(valuation)}`,
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ export function InviteGateScreen({ onRegistered }: { onRegistered: () => void })
|
|||||||
<div className="inline-flex items-center gap-2 mb-4">
|
<div className="inline-flex items-center gap-2 mb-4">
|
||||||
<Sparkles className="text-accent-light" size={32} />
|
<Sparkles className="text-accent-light" size={32} />
|
||||||
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
||||||
AI Tycoon
|
Token Empire
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-surface-400 text-sm">
|
<p className="text-surface-400 text-sm">
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function NewGameScreen() {
|
|||||||
<div className="inline-flex items-center gap-2 mb-4">
|
<div className="inline-flex items-center gap-2 mb-4">
|
||||||
<Sparkles className="text-accent-light" size={32} />
|
<Sparkles className="text-accent-light" size={32} />
|
||||||
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
<h1 className="text-4xl font-bold bg-gradient-to-r from-accent-light to-accent bg-clip-text text-transparent">
|
||||||
AI Tycoon
|
Token Empire
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-surface-400 text-sm">
|
<p className="text-surface-400 text-sm">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect, useRef } from 'react';
|
import { useState, useEffect, useRef } from 'react';
|
||||||
import { formatMoney, formatDuration, formatNumber, MAX_OFFLINE_TICKS, TICK_INTERVAL_MS } from '@ai-tycoon/shared';
|
import { formatMoney, formatDuration, formatNumber, MAX_OFFLINE_TICKS, TICK_INTERVAL_MS } from '@token-empire/shared';
|
||||||
import { GameEngine } from '@ai-tycoon/game-engine';
|
import { GameEngine } from '@token-empire/game-engine';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
|
|
||||||
interface OfflineResult {
|
interface OfflineResult {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { X, Lightbulb } from 'lucide-react';
|
import { X, Lightbulb } from 'lucide-react';
|
||||||
|
|
||||||
const DISMISSED_KEY = 'ai-tycoon-dismissed-hints';
|
const DISMISSED_KEY = 'token-empire-dismissed-hints';
|
||||||
|
|
||||||
function getDismissed(): Set<string> {
|
function getDismissed(): Set<string> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const NAV_ITEMS: { page: ActivePage; label: string; icon: typeof LayoutDashboard
|
|||||||
|
|
||||||
function getInitialCollapsed(): boolean {
|
function getInitialCollapsed(): boolean {
|
||||||
try {
|
try {
|
||||||
const stored = localStorage.getItem('ai-tycoon-sidebar-collapsed');
|
const stored = localStorage.getItem('token-empire-sidebar-collapsed');
|
||||||
if (stored !== null) return stored === 'true';
|
if (stored !== null) return stored === 'true';
|
||||||
return window.innerWidth < 1280;
|
return window.innerWidth < 1280;
|
||||||
} catch { return false; }
|
} catch { return false; }
|
||||||
@@ -82,7 +82,7 @@ export function Sidebar() {
|
|||||||
const toggleCollapse = () => {
|
const toggleCollapse = () => {
|
||||||
setCollapsed(prev => {
|
setCollapsed(prev => {
|
||||||
const next = !prev;
|
const next = !prev;
|
||||||
localStorage.setItem('ai-tycoon-sidebar-collapsed', String(next));
|
localStorage.setItem('token-empire-sidebar-collapsed', String(next));
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -166,7 +166,7 @@ export function Sidebar() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={`${collapsed ? 'px-2 py-3 text-center' : 'p-4'} border-t border-surface-700 text-xs text-surface-500`}>
|
<div className={`${collapsed ? 'px-2 py-3 text-center' : 'p-4'} border-t border-surface-700 text-xs text-surface-500`}>
|
||||||
{collapsed ? 'v0.1' : 'AI Tycoon v0.1'}
|
{collapsed ? 'v0.1' : 'Token Empire v0.1'}
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { Pause, Play, Bell, Share2 } from 'lucide-react';
|
|||||||
import { CompanyStatsCard } from '@/components/game/CompanyStatsCard';
|
import { CompanyStatsCard } from '@/components/game/CompanyStatsCard';
|
||||||
import { NotificationPanel } from '@/components/common/NotificationPanel';
|
import { NotificationPanel } from '@/components/common/NotificationPanel';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatMoney, formatNumber, formatDuration, formatPercent } from '@ai-tycoon/shared';
|
import { formatMoney, formatNumber, formatDuration, formatPercent } from '@token-empire/shared';
|
||||||
import type { GameSpeed } from '@ai-tycoon/shared';
|
import type { GameSpeed } from '@token-empire/shared';
|
||||||
import { Tooltip } from '@/components/common/Tooltip';
|
import { Tooltip } from '@/components/common/Tooltip';
|
||||||
|
|
||||||
const SPEEDS: GameSpeed[] = [1, 2, 5];
|
const SPEEDS: GameSpeed[] = [1, 2, 5];
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { api, getAuthToken, setAuthToken, clearAuthToken, decodeTokenPayload } from '@/lib/api';
|
import { api, getAuthToken, setAuthToken, clearAuthToken, decodeTokenPayload } from '@/lib/api';
|
||||||
import { AUTO_SAVE_INTERVAL_TICKS } from '@ai-tycoon/shared';
|
import { AUTO_SAVE_INTERVAL_TICKS } from '@token-empire/shared';
|
||||||
|
|
||||||
export function useCloudSave() {
|
export function useCloudSave() {
|
||||||
const tickCount = useGameStore((s) => s.meta.tickCount);
|
const tickCount = useGameStore((s) => s.meta.tickCount);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { GameEngine, setAchievementDefinitions, ACHIEVEMENT_DEFINITIONS } from '@ai-tycoon/game-engine';
|
import { GameEngine, setAchievementDefinitions, ACHIEVEMENT_DEFINITIONS } from '@token-empire/game-engine';
|
||||||
import type { TickNotification } from '@ai-tycoon/game-engine';
|
import type { TickNotification } from '@token-empire/game-engine';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
|
|
||||||
export function useGameLoop(skip = false) {
|
export function useGameLoop(skip = false) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useGameStore, type ActivePage } from '@/store';
|
import { useGameStore, type ActivePage } from '@/store';
|
||||||
import type { GameSpeed } from '@ai-tycoon/shared';
|
import type { GameSpeed } from '@token-empire/shared';
|
||||||
|
|
||||||
const PAGE_SHORTCUTS: Record<string, ActivePage> = {
|
const PAGE_SHORTCUTS: Record<string, ActivePage> = {
|
||||||
d: 'dashboard',
|
d: 'dashboard',
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
const API_BASE = import.meta.env.VITE_API_URL ?? 'http://localhost:3001';
|
const API_BASE = import.meta.env.VITE_API_URL ?? 'http://localhost:3001';
|
||||||
|
|
||||||
let authToken: string | null = localStorage.getItem('ai-tycoon-auth-token');
|
let authToken: string | null = localStorage.getItem('token-empire-auth-token');
|
||||||
|
|
||||||
export function setAuthToken(token: string) {
|
export function setAuthToken(token: string) {
|
||||||
authToken = token;
|
authToken = token;
|
||||||
localStorage.setItem('ai-tycoon-auth-token', token);
|
localStorage.setItem('token-empire-auth-token', token);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAuthToken() {
|
export function getAuthToken() {
|
||||||
@@ -13,7 +13,7 @@ export function getAuthToken() {
|
|||||||
|
|
||||||
export function clearAuthToken() {
|
export function clearAuthToken() {
|
||||||
authToken = null;
|
authToken = null;
|
||||||
localStorage.removeItem('ai-tycoon-auth-token');
|
localStorage.removeItem('token-empire-auth-token');
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TokenPayload {
|
export interface TokenPayload {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { ACHIEVEMENT_DEFINITIONS } from '@ai-tycoon/game-engine';
|
import { ACHIEVEMENT_DEFINITIONS } from '@token-empire/game-engine';
|
||||||
import { formatNumber } from '@ai-tycoon/shared';
|
import { formatNumber } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
Trophy, Lock, Server, Brain, Rocket, DollarSign, Sprout, Users,
|
Trophy, Lock, Server, Brain, Rocket, DollarSign, Sprout, Users,
|
||||||
Globe, Sparkles, TrendingUp, Building2, Atom, Cpu, FlaskConical,
|
Globe, Sparkles, TrendingUp, Building2, Atom, Cpu, FlaskConical,
|
||||||
GitBranch, Zap,
|
GitBranch, Zap,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import type { AchievementCondition } from '@ai-tycoon/shared';
|
import type { AchievementCondition } from '@token-empire/shared';
|
||||||
|
|
||||||
const ICON_MAP: Record<string, React.ComponentType<{ size?: number; className?: string }>> = {
|
const ICON_MAP: Record<string, React.ComponentType<{ size?: number; className?: string }>> = {
|
||||||
Trophy, Server, Brain, Rocket, DollarSign, Sprout, Users,
|
Trophy, Server, Brain, Rocket, DollarSign, Sprout, Users,
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { Swords, TrendingUp, Shield, Users, Brain, ShoppingCart } from 'lucide-r
|
|||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { ConfirmModal } from '@/components/common/ConfirmModal';
|
import { ConfirmModal } from '@/components/common/ConfirmModal';
|
||||||
import { Tooltip } from '@/components/common/Tooltip';
|
import { Tooltip } from '@/components/common/Tooltip';
|
||||||
import { formatMoney, formatNumber } from '@ai-tycoon/shared';
|
import { formatMoney, formatNumber } from '@token-empire/shared';
|
||||||
import type { Era } from '@ai-tycoon/shared';
|
import type { Era } from '@token-empire/shared';
|
||||||
|
|
||||||
const ARCHETYPE_LABELS: Record<string, string> = {
|
const ARCHETYPE_LABELS: Record<string, string> = {
|
||||||
'safety-first': 'Safety-First Lab',
|
'safety-first': 'Safety-First Lab',
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { useGameStore, type ActivePage } from '@/store';
|
import { useGameStore, type ActivePage } from '@/store';
|
||||||
import { formatMoney, formatNumber, formatPercent, formatDuration } from '@ai-tycoon/shared';
|
import { formatMoney, formatNumber, formatPercent, formatDuration } from '@token-empire/shared';
|
||||||
import type { Era } from '@ai-tycoon/shared';
|
import type { Era } from '@token-empire/shared';
|
||||||
import { TECH_TREE } from '@ai-tycoon/game-engine';
|
import { TECH_TREE } from '@token-empire/game-engine';
|
||||||
import {
|
import {
|
||||||
DollarSign, TrendingUp, TrendingDown, Minus, Cpu, Brain, Users,
|
DollarSign, TrendingUp, TrendingDown, Minus, Cpu, Brain, Users,
|
||||||
Shield, ChevronRight, Zap, Wifi, Sparkles, FlaskConical, Building2,
|
Shield, ChevronRight, Zap, Wifi, Sparkles, FlaskConical, Building2,
|
||||||
@@ -96,7 +96,7 @@ export function DashboardPage() {
|
|||||||
|
|
||||||
{totalDCs === 0 && (
|
{totalDCs === 0 && (
|
||||||
<TutorialHint id="welcome">
|
<TutorialHint id="welcome">
|
||||||
Welcome to AI Tycoon! Start by building a cluster in the Infrastructure tab, then add a campus and data center to deploy racks and train your first AI model.
|
Welcome to Token Empire! Start by building a cluster in the Infrastructure tab, then add a campus and data center to deploy racks and train your first AI model.
|
||||||
</TutorialHint>
|
</TutorialHint>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Database, ShoppingCart, Zap } from 'lucide-react';
|
import { Database, ShoppingCart, Zap } from 'lucide-react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatNumber, formatMoney, uuid } from '@ai-tycoon/shared';
|
import { formatNumber, formatMoney, uuid } from '@token-empire/shared';
|
||||||
import type { OwnedDataset, DataDomain } from '@ai-tycoon/shared';
|
import type { OwnedDataset, DataDomain } from '@token-empire/shared';
|
||||||
|
|
||||||
interface MarketplaceDataset {
|
interface MarketplaceDataset {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatMoney, formatPercent, formatNumber, FUNDING_ROUNDS } from '@ai-tycoon/shared';
|
import { formatMoney, formatPercent, formatNumber, FUNDING_ROUNDS } from '@token-empire/shared';
|
||||||
import type { FundingRoundType } from '@ai-tycoon/shared';
|
import type { FundingRoundType } from '@token-empire/shared';
|
||||||
import { TrendingUp, DollarSign, PiggyBank, BarChart3, Rocket, Check, X as XIcon } from 'lucide-react';
|
import { TrendingUp, DollarSign, PiggyBank, BarChart3, Rocket, Check, X as XIcon } from 'lucide-react';
|
||||||
import { AreaChart, Area, XAxis, YAxis, ResponsiveContainer, LineChart, Line, Tooltip } from 'recharts';
|
import { AreaChart, Area, XAxis, YAxis, ResponsiveContainer, LineChart, Line, Tooltip } from 'recharts';
|
||||||
import { canRaiseFunding } from '@ai-tycoon/game-engine';
|
import { canRaiseFunding } from '@token-empire/game-engine';
|
||||||
import type { GameState } from '@ai-tycoon/shared';
|
import type { GameState } from '@token-empire/shared';
|
||||||
|
|
||||||
export function FinancePage() {
|
export function FinancePage() {
|
||||||
const money = useGameStore((s) => s.economy.money);
|
const money = useGameStore((s) => s.economy.money);
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ import {
|
|||||||
SWITCH_TIER_CONFIGS,
|
SWITCH_TIER_CONFIGS,
|
||||||
DC_UPGRADE_COST_FRACTION, DC_UPGRADE_INCREMENT,
|
DC_UPGRADE_COST_FRACTION, DC_UPGRADE_INCREMENT,
|
||||||
skuTotalFlops,
|
skuTotalFlops,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type {
|
import type {
|
||||||
DCTier, RackSkuId, LocationId, PipelineStage, Era,
|
DCTier, RackSkuId, LocationId, PipelineStage, Era,
|
||||||
Cluster, Campus, DataCenter, DeploymentCohort,
|
Cluster, Campus, DataCenter, DeploymentCohort,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
const ERA_ORDER: Era[] = ['startup', 'scaleup', 'bigtech', 'agi'];
|
const ERA_ORDER: Era[] = ['startup', 'scaleup', 'bigtech', 'agi'];
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Trophy, Medal, Clock, TrendingUp } from 'lucide-react';
|
import { Trophy, Medal, Clock, TrendingUp } from 'lucide-react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatMoney, formatNumber } from '@ai-tycoon/shared';
|
import { formatMoney, formatNumber } from '@token-empire/shared';
|
||||||
import { api, getAuthToken } from '@/lib/api';
|
import { api, getAuthToken } from '@/lib/api';
|
||||||
|
|
||||||
interface LeaderboardEntry {
|
interface LeaderboardEntry {
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import {
|
|||||||
SIZE_TIER_LABELS,
|
SIZE_TIER_LABELS,
|
||||||
SFT_SPECIALIZATION_BONUSES,
|
SFT_SPECIALIZATION_BONUSES,
|
||||||
PRETRAINING_BASE_TICKS,
|
PRETRAINING_BASE_TICKS,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type {
|
import type {
|
||||||
ModelArchitecture, DataMixAllocation, SFTSpecialization, AlignmentMethod,
|
ModelArchitecture, DataMixAllocation, SFTSpecialization, AlignmentMethod,
|
||||||
DataDomain, QuantizationLevel, BaseModel, ModelVariant,
|
DataDomain, QuantizationLevel, BaseModel, ModelVariant,
|
||||||
SizeTier, ModelFamily,
|
SizeTier, ModelFamily,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
const DATA_MIX_PRESETS: Record<string, { label: string; mix: DataMixAllocation }> = {
|
const DATA_MIX_PRESETS: Record<string, { label: string; mix: DataMixAllocation }> = {
|
||||||
balanced: { label: 'Balanced', mix: DEFAULT_DATA_MIX },
|
balanced: { label: 'Balanced', mix: DEFAULT_DATA_MIX },
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { FlaskConical, Lock, Check, Play, ListOrdered, X } from 'lucide-react';
|
import { FlaskConical, Lock, Check, Play, ListOrdered, X } from 'lucide-react';
|
||||||
import { TutorialHint } from '@/components/game/TutorialHint';
|
import { TutorialHint } from '@/components/game/TutorialHint';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatDuration, formatPercent, formatNumber, formatMoney } from '@ai-tycoon/shared';
|
import { formatDuration, formatPercent, formatNumber, formatMoney } from '@token-empire/shared';
|
||||||
import { TECH_TREE, getAvailableResearch } from '@ai-tycoon/game-engine';
|
import { TECH_TREE, getAvailableResearch } from '@token-empire/game-engine';
|
||||||
import type { ResearchNode } from '@ai-tycoon/shared';
|
import type { ResearchNode } from '@token-empire/shared';
|
||||||
|
|
||||||
const CATEGORY_COLORS: Record<string, string> = {
|
const CATEGORY_COLORS: Record<string, string> = {
|
||||||
generation: 'border-purple-500/50 bg-purple-500/10',
|
generation: 'border-purple-500/50 bg-purple-500/10',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
formatNumber, formatPercent,
|
formatNumber, formatPercent,
|
||||||
type TrafficPriority, type OverflowBehavior, type RoutingStrategy,
|
type TrafficPriority, type OverflowBehavior, type RoutingStrategy,
|
||||||
TRAFFIC_PRIORITIES,
|
TRAFFIC_PRIORITIES,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
Activity, Shield, Clock, CheckCircle, XCircle, Layers,
|
Activity, Shield, Clock, CheckCircle, XCircle, Layers,
|
||||||
AlertTriangle, Zap, Server, ArrowRight,
|
AlertTriangle, Zap, Server, ArrowRight,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function SettingsPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
localStorage.removeItem('ai-tycoon-save');
|
localStorage.removeItem('token-empire-save');
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ export function SettingsPage() {
|
|||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = `ai-tycoon-${companyName.replace(/\s+/g, '-').toLowerCase()}.json`;
|
a.download = `token-empire-${companyName.replace(/\s+/g, '-').toLowerCase()}.json`;
|
||||||
a.click();
|
a.click();
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
};
|
};
|
||||||
@@ -51,7 +51,7 @@ export function SettingsPage() {
|
|||||||
}
|
}
|
||||||
setImportData({ data, name: data.meta.companyName });
|
setImportData({ data, name: data.meta.companyName });
|
||||||
} catch {
|
} catch {
|
||||||
addNotification({ title: 'Import Failed', message: 'Could not read save file. Make sure it is a valid AI Tycoon export.', type: 'danger', tick: useGameStore.getState().meta.tickCount });
|
addNotification({ title: 'Import Failed', message: 'Could not read save file. Make sure it is a valid Token Empire export.', type: 'danger', tick: useGameStore.getState().meta.tickCount });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
@@ -60,7 +60,7 @@ export function SettingsPage() {
|
|||||||
|
|
||||||
const confirmImport = () => {
|
const confirmImport = () => {
|
||||||
if (!importData) return;
|
if (!importData) return;
|
||||||
localStorage.setItem('ai-tycoon-save', JSON.stringify({ state: importData.data }));
|
localStorage.setItem('token-empire-save', JSON.stringify({ state: importData.data }));
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Users, Plus, Star, Briefcase } from 'lucide-react';
|
import { Users, Plus, Star, Briefcase } from 'lucide-react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatMoney } from '@ai-tycoon/shared';
|
import { formatMoney } from '@token-empire/shared';
|
||||||
import { KEY_HIRE_POOL } from '@ai-tycoon/game-engine';
|
import { KEY_HIRE_POOL } from '@token-empire/game-engine';
|
||||||
import type { DepartmentId } from '@ai-tycoon/shared';
|
import type { DepartmentId } from '@token-empire/shared';
|
||||||
|
|
||||||
const DEPT_LABELS: Record<string, string> = {
|
const DEPT_LABELS: Record<string, string> = {
|
||||||
research: 'Research',
|
research: 'Research',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatNumber, formatMoney, formatPercent } from '@ai-tycoon/shared';
|
import { formatNumber, formatMoney, formatPercent } from '@token-empire/shared';
|
||||||
import type { ApiTierId } from '@ai-tycoon/shared';
|
import type { ApiTierId } from '@token-empire/shared';
|
||||||
import { Code, Check } from 'lucide-react';
|
import { Code, Check } from 'lucide-react';
|
||||||
|
|
||||||
const TIER_ORDER: ApiTierId[] = ['free', 'payg', 'scale', 'enterprise-api'];
|
const TIER_ORDER: ApiTierId[] = ['free', 'payg', 'scale', 'enterprise-api'];
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatNumber, formatMoney, formatPercent } from '@ai-tycoon/shared';
|
import { formatNumber, formatMoney, formatPercent } from '@token-empire/shared';
|
||||||
import type { ConsumerTierId } from '@ai-tycoon/shared';
|
import type { ConsumerTierId } from '@token-empire/shared';
|
||||||
import { Users, Check } from 'lucide-react';
|
import { Users, Check } from 'lucide-react';
|
||||||
|
|
||||||
const TIER_ORDER: ConsumerTierId[] = ['free', 'plus', 'pro', 'team'];
|
const TIER_ORDER: ConsumerTierId[] = ['free', 'plus', 'pro', 'team'];
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatNumber, formatMoney, formatPercent } from '@ai-tycoon/shared';
|
import { formatNumber, formatMoney, formatPercent } from '@token-empire/shared';
|
||||||
import { Boxes, Check } from 'lucide-react';
|
import { Boxes, Check } from 'lucide-react';
|
||||||
|
|
||||||
function useAppliedFeedback() {
|
function useAppliedFeedback() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatNumber, formatMoney, formatPercent } from '@ai-tycoon/shared';
|
import { formatNumber, formatMoney, formatPercent } from '@token-empire/shared';
|
||||||
import type { EnterprisePipelineStage, EnterpriseSegment } from '@ai-tycoon/shared';
|
import type { EnterprisePipelineStage, EnterpriseSegment } from '@token-empire/shared';
|
||||||
import { Building2, AlertTriangle } from 'lucide-react';
|
import { Building2, AlertTriangle } from 'lucide-react';
|
||||||
|
|
||||||
const STAGE_ORDER: EnterprisePipelineStage[] = ['lead', 'qualification', 'poc', 'negotiation'];
|
const STAGE_ORDER: EnterprisePipelineStage[] = ['lead', 'qualification', 'poc', 'negotiation'];
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatNumber, formatPercent } from '@ai-tycoon/shared';
|
import { formatNumber, formatPercent } from '@token-empire/shared';
|
||||||
import type { TAMSegmentId } from '@ai-tycoon/shared';
|
import type { TAMSegmentId } from '@token-empire/shared';
|
||||||
import { Globe, TrendingUp, Clock, Thermometer } from 'lucide-react';
|
import { Globe, TrendingUp, Clock, Thermometer } from 'lucide-react';
|
||||||
|
|
||||||
const SEGMENT_LABELS: Record<TAMSegmentId, string> = {
|
const SEGMENT_LABELS: Record<TAMSegmentId, string> = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { useGameStore } from '@/store';
|
import { useGameStore } from '@/store';
|
||||||
import { formatNumber, formatMoney, formatPercent } from '@ai-tycoon/shared';
|
import { formatNumber, formatMoney, formatPercent } from '@token-empire/shared';
|
||||||
import { Wrench, Bot, Check, Lock } from 'lucide-react';
|
import { Wrench, Bot, Check, Lock } from 'lucide-react';
|
||||||
|
|
||||||
function useAppliedFeedback() {
|
function useAppliedFeedback() {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import type {
|
|||||||
ModelArchitecture, AlignmentMethod, SizeTier,
|
ModelArchitecture, AlignmentMethod, SizeTier,
|
||||||
SFTSpecialization, QuantizationLevel, VariantCreationJob,
|
SFTSpecialization, QuantizationLevel, VariantCreationJob,
|
||||||
ConsumerTierId, ApiTierId,
|
ConsumerTierId, ApiTierId,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
INITIAL_SETTINGS, SAVE_VERSION,
|
INITIAL_SETTINGS, SAVE_VERSION,
|
||||||
INITIAL_ECONOMY, INITIAL_INFRASTRUCTURE, INITIAL_COMPUTE,
|
INITIAL_ECONOMY, INITIAL_INFRASTRUCTURE, INITIAL_COMPUTE,
|
||||||
@@ -39,12 +39,12 @@ import {
|
|||||||
SFT_TIME_FRACTION, ALIGNMENT_TIME_FRACTION,
|
SFT_TIME_FRACTION, ALIGNMENT_TIME_FRACTION,
|
||||||
SIZE_TIER_MAP, SIZE_TIER_LABELS,
|
SIZE_TIER_MAP, SIZE_TIER_LABELS,
|
||||||
POINT_RELEASE_TIME_FRACTION, POINT_RELEASE_MAX_VERSION,
|
POINT_RELEASE_TIME_FRACTION, POINT_RELEASE_MAX_VERSION,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
emptyDCNetworkSummary, emptyCampusNetworkSummary, emptyClusterNetworkSummary,
|
emptyDCNetworkSummary, emptyCampusNetworkSummary, emptyClusterNetworkSummary,
|
||||||
TECH_TREE, onModelDeployed,
|
TECH_TREE, onModelDeployed,
|
||||||
} from '@ai-tycoon/game-engine';
|
} from '@token-empire/game-engine';
|
||||||
import { INITIAL_RIVALS } from '@ai-tycoon/game-engine';
|
import { INITIAL_RIVALS } from '@token-empire/game-engine';
|
||||||
|
|
||||||
export type ActivePage = 'dashboard' | 'infrastructure' | 'research' | 'models'
|
export type ActivePage = 'dashboard' | 'infrastructure' | 'research' | 'models'
|
||||||
| 'market' | 'serving' | 'talent' | 'data' | 'competitors' | 'finance' | 'achievements' | 'leaderboard' | 'invitations' | 'settings';
|
| 'market' | 'serving' | 'talent' | 'data' | 'competitors' | 'finance' | 'achievements' | 'leaderboard' | 'invitations' | 'settings';
|
||||||
@@ -1428,7 +1428,7 @@ export const useGameStore = create<Store>()(
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: 'ai-tycoon-save',
|
name: 'token-empire-save',
|
||||||
version: SAVE_VERSION,
|
version: SAVE_VERSION,
|
||||||
partialize: (state) => {
|
partialize: (state) => {
|
||||||
const { activePage, notifications, infraNav, modelsTab, ...rest } = state;
|
const { activePage, notifications, infraNav, modelsTab, ...rest } = state;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "@ai-tycoon/tsconfig/react.json",
|
"extends": "@token-empire/tsconfig/react.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|||||||
+7
-7
@@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
web:
|
web:
|
||||||
image: gitea.thewrightserver.net/josh/aihostingtycoon/web:latest
|
image: gitea.thewrightserver.net/josh/tokenempire/web:latest
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -8,11 +8,11 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
server:
|
server:
|
||||||
image: gitea.thewrightserver.net/josh/aihostingtycoon/server:latest
|
image: gitea.thewrightserver.net/josh/tokenempire/server:latest
|
||||||
ports:
|
ports:
|
||||||
- "3001:3001"
|
- "3001:3001"
|
||||||
environment:
|
environment:
|
||||||
- DATABASE_URL=postgresql://aitycoon:aitycoon@db:5432/aitycoon
|
- DATABASE_URL=postgresql://tokenempire:tokenempire@db:5432/tokenempire
|
||||||
- PORT=3001
|
- PORT=3001
|
||||||
- CORS_ORIGIN=*
|
- CORS_ORIGIN=*
|
||||||
- JWT_SECRET=change-me-to-a-random-secret
|
- JWT_SECRET=change-me-to-a-random-secret
|
||||||
@@ -26,13 +26,13 @@ services:
|
|||||||
db:
|
db:
|
||||||
image: postgres:17-alpine
|
image: postgres:17-alpine
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=aitycoon
|
- POSTGRES_USER=tokenempire
|
||||||
- POSTGRES_PASSWORD=aitycoon
|
- POSTGRES_PASSWORD=tokenempire
|
||||||
- POSTGRES_DB=aitycoon
|
- POSTGRES_DB=tokenempire
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U aitycoon"]
|
test: ["CMD-SHELL", "pg_isready -U tokenempire"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ The game engine and simulation core have no React dependency. They can run ident
|
|||||||
## Monorepo Layout
|
## Monorepo Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
ai-tycoon/
|
token-empire/
|
||||||
├── turbo.json # Turborepo task config
|
├── turbo.json # Turborepo task config
|
||||||
├── pnpm-workspace.yaml # Workspace definition
|
├── pnpm-workspace.yaml # Workspace definition
|
||||||
│
|
│
|
||||||
@@ -122,7 +122,7 @@ The store uses a slice pattern with 14 slices, each owning a portion of the game
|
|||||||
|
|
||||||
### Persistence
|
### Persistence
|
||||||
|
|
||||||
- **localStorage**: Auto-save every 60 ticks under key `ai-tycoon-save`. The Zustand `persist` middleware handles serialization.
|
- **localStorage**: Auto-save every 60 ticks under key `token-empire-save`. The Zustand `persist` middleware handles serialization.
|
||||||
- **Cloud saves**: Optional. POST to `/api/saves` every 5 minutes when authenticated. Requires the Hono backend + PostgreSQL.
|
- **Cloud saves**: Optional. POST to `/api/saves` every 5 minutes when authenticated. Requires the Hono backend + PostgreSQL.
|
||||||
- **Save format versioning**: A `version` field in meta enables migration functions for breaking state changes.
|
- **Save format versioning**: A `version` field in meta enables migration functions for breaking state changes.
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "ai-tycoon",
|
"name": "token-empire",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "turbo dev",
|
"dev": "turbo dev",
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
"clean": "turbo clean",
|
"clean": "turbo clean",
|
||||||
"simulate": "turbo simulate --filter=@ai-tycoon/game-simulation",
|
"simulate": "turbo simulate --filter=@token-empire/game-simulation",
|
||||||
"simulate:ci": "pnpm --filter @ai-tycoon/game-simulation simulate:ci"
|
"simulate:ci": "pnpm --filter @token-empire/game-simulation simulate:ci"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"turbo": "^2.5.0",
|
"turbo": "^2.5.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@ai-tycoon/game-engine",
|
"name": "@token-empire/game-engine",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -11,10 +11,10 @@
|
|||||||
"test": "vitest run"
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-tycoon/shared": "workspace:*"
|
"@token-empire/shared": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ai-tycoon/tsconfig": "workspace:*",
|
"@token-empire/tsconfig": "workspace:*",
|
||||||
"typescript": "^5.8.0"
|
"typescript": "^5.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import type {
|
|||||||
Cluster, Campus, DataCenter, DeploymentCohort,
|
Cluster, Campus, DataCenter, DeploymentCohort,
|
||||||
DCNetworkSummary, CampusNetworkSummary, ClusterNetworkSummary,
|
DCNetworkSummary, CampusNetworkSummary, ClusterNetworkSummary,
|
||||||
TrainingPipeline, BaseModel, ModelFamily,
|
TrainingPipeline, BaseModel, ModelFamily,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import { uuid } from '@ai-tycoon/shared';
|
import { uuid } from '@token-empire/shared';
|
||||||
import type { DeepPartial } from './createTestState';
|
import type { DeepPartial } from './createTestState';
|
||||||
|
|
||||||
function emptyDCNetwork(): DCNetworkSummary {
|
function emptyDCNetwork(): DCNetworkSummary {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { GameState } from '@ai-tycoon/shared';
|
import type { GameState } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
INITIAL_SETTINGS, SAVE_VERSION,
|
INITIAL_SETTINGS, SAVE_VERSION,
|
||||||
INITIAL_ECONOMY, INITIAL_INFRASTRUCTURE, INITIAL_COMPUTE,
|
INITIAL_ECONOMY, INITIAL_INFRASTRUCTURE, INITIAL_COMPUTE,
|
||||||
INITIAL_RESEARCH, INITIAL_MODELS, INITIAL_MARKET,
|
INITIAL_RESEARCH, INITIAL_MODELS, INITIAL_MARKET,
|
||||||
INITIAL_COMPETITORS, INITIAL_TALENT, INITIAL_DATA,
|
INITIAL_COMPETITORS, INITIAL_TALENT, INITIAL_DATA,
|
||||||
INITIAL_REPUTATION, INITIAL_ACHIEVEMENTS,
|
INITIAL_REPUTATION, INITIAL_ACHIEVEMENTS,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
export type DeepPartial<T> = T extends object
|
export type DeepPartial<T> = T extends object
|
||||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { AchievementDefinition } from '@ai-tycoon/shared';
|
import type { AchievementDefinition } from '@token-empire/shared';
|
||||||
|
|
||||||
export const ACHIEVEMENT_DEFINITIONS: AchievementDefinition[] = [
|
export const ACHIEVEMENT_DEFINITIONS: AchievementDefinition[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Competitor } from '@ai-tycoon/shared';
|
import type { Competitor } from '@token-empire/shared';
|
||||||
|
|
||||||
export const INITIAL_RIVALS: Competitor[] = [
|
export const INITIAL_RIVALS: Competitor[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { EnterpriseSegment } from '@ai-tycoon/shared';
|
import type { EnterpriseSegment } from '@token-empire/shared';
|
||||||
|
|
||||||
export const ENTERPRISE_NAMES: Record<EnterpriseSegment, string[]> = {
|
export const ENTERPRISE_NAMES: Record<EnterpriseSegment, string[]> = {
|
||||||
startup: [
|
startup: [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { DepartmentId } from '@ai-tycoon/shared';
|
import type { DepartmentId } from '@token-empire/shared';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A recruitable key hire as it appears in the available pool.
|
* A recruitable key hire as it appears in the available pool.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ResearchNode } from '@ai-tycoon/shared';
|
import type { ResearchNode } from '@token-empire/shared';
|
||||||
|
|
||||||
export const TECH_TREE: ResearchNode[] = [
|
export const TECH_TREE: ResearchNode[] = [
|
||||||
// === COMPUTE / INFRASTRUCTURE ===
|
// === COMPUTE / INFRASTRUCTURE ===
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState } from '@ai-tycoon/shared';
|
import type { GameState } from '@token-empire/shared';
|
||||||
import { processTick } from './tick';
|
import { processTick } from './tick';
|
||||||
|
|
||||||
export interface GameEngineCallbacks {
|
export interface GameEngineCallbacks {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { processAchievements } from './achievementSystem';
|
import { processAchievements } from './achievementSystem';
|
||||||
import { createTestState } from '../__test-utils__';
|
import { createTestState } from '../__test-utils__';
|
||||||
import type { AchievementDefinition } from '@ai-tycoon/shared';
|
import type { AchievementDefinition } from '@token-empire/shared';
|
||||||
|
|
||||||
function makeDef(overrides: Partial<AchievementDefinition> = {}): AchievementDefinition {
|
function makeDef(overrides: Partial<AchievementDefinition> = {}): AchievementDefinition {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState, AchievementState, AchievementDefinition } from '@ai-tycoon/shared';
|
import type { GameState, AchievementState, AchievementDefinition } from '@token-empire/shared';
|
||||||
|
|
||||||
export interface AchievementTickResult {
|
export interface AchievementTickResult {
|
||||||
achievements: AchievementState;
|
achievements: AchievementState;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||||
import { processCompetitors } from './competitorSystem';
|
import { processCompetitors } from './competitorSystem';
|
||||||
import { createTestState, createSeededRNG } from '../__test-utils__';
|
import { createTestState, createSeededRNG } from '../__test-utils__';
|
||||||
import { FRESHNESS_DECAY_RATE } from '@ai-tycoon/shared';
|
import { FRESHNESS_DECAY_RATE } from '@token-empire/shared';
|
||||||
import type { Competitor } from '@ai-tycoon/shared';
|
import type { Competitor } from '@token-empire/shared';
|
||||||
|
|
||||||
const rng = createSeededRNG(42);
|
const rng = createSeededRNG(42);
|
||||||
beforeEach(() => rng.install());
|
beforeEach(() => rng.install());
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { GameState, CompetitorState, Competitor } from '@ai-tycoon/shared';
|
import type { GameState, CompetitorState, Competitor } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
COMPETITOR_PRODUCT_THRESHOLDS,
|
COMPETITOR_PRODUCT_THRESHOLDS,
|
||||||
COMPETITOR_CATCHUP_SHARE_THRESHOLD,
|
COMPETITOR_CATCHUP_SHARE_THRESHOLD,
|
||||||
COMPETITOR_CATCHUP_PRICE_CUT,
|
COMPETITOR_CATCHUP_PRICE_CUT,
|
||||||
FRESHNESS_DECAY_RATE,
|
FRESHNESS_DECAY_RATE,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
function updateCompetitorProducts(rival: Competitor): Competitor['products'] {
|
function updateCompetitorProducts(rival: Competitor): Competitor['products'] {
|
||||||
const cap = rival.estimatedCapability;
|
const cap = rival.estimatedCapability;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { createTestState } from '../__test-utils__';
|
import { createTestState } from '../__test-utils__';
|
||||||
import { computeCapacity, finalizeCompute } from './computeSystem';
|
import { computeCapacity, finalizeCompute } from './computeSystem';
|
||||||
import type { InfrastructureState } from '@ai-tycoon/shared';
|
import type { InfrastructureState } from '@token-empire/shared';
|
||||||
import { INITIAL_INFRASTRUCTURE, FLOPS_TO_TOKENS_MULTIPLIER, COMPUTE_SNAPSHOT_INTERVAL, MAX_COMPUTE_HISTORY } from '@ai-tycoon/shared';
|
import { INITIAL_INFRASTRUCTURE, FLOPS_TO_TOKENS_MULTIPLIER, COMPUTE_SNAPSHOT_INTERVAL, MAX_COMPUTE_HISTORY } from '@token-empire/shared';
|
||||||
|
|
||||||
function createInfrastructure(overrides: Partial<InfrastructureState> = {}): InfrastructureState {
|
function createInfrastructure(overrides: Partial<InfrastructureState> = {}): InfrastructureState {
|
||||||
return { ...INITIAL_INFRASTRUCTURE, ...overrides };
|
return { ...INITIAL_INFRASTRUCTURE, ...overrides };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { GameState, ComputeState, InfrastructureState } from '@ai-tycoon/shared';
|
import type { GameState, ComputeState, InfrastructureState } from '@token-empire/shared';
|
||||||
import { FLOPS_TO_TOKENS_MULTIPLIER, COMPUTE_SNAPSHOT_INTERVAL, MAX_COMPUTE_HISTORY } from '@ai-tycoon/shared';
|
import { FLOPS_TO_TOKENS_MULTIPLIER, COMPUTE_SNAPSHOT_INTERVAL, MAX_COMPUTE_HISTORY } from '@token-empire/shared';
|
||||||
import type { ResearchBonuses } from './researchBonuses';
|
import type { ResearchBonuses } from './researchBonuses';
|
||||||
|
|
||||||
export interface CapacityResult {
|
export interface CapacityResult {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { processData } from './dataSystem';
|
import { processData } from './dataSystem';
|
||||||
import { createTestState } from '../__test-utils__';
|
import { createTestState } from '../__test-utils__';
|
||||||
import type { DataPartnership } from '@ai-tycoon/shared';
|
import type { DataPartnership } from '@token-empire/shared';
|
||||||
|
|
||||||
function makePartnership(tokensPerTick: number): DataPartnership {
|
function makePartnership(tokensPerTick: number): DataPartnership {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState, DataState } from '@ai-tycoon/shared';
|
import type { GameState, DataState } from '@token-empire/shared';
|
||||||
|
|
||||||
export function processData(state: GameState): DataState {
|
export function processData(state: GameState): DataState {
|
||||||
const subscribers = state.market.consumerTiers.totalUsers;
|
const subscribers = state.market.consumerTiers.totalUsers;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest';
|
|||||||
import { processEconomy } from './economySystem';
|
import { processEconomy } from './economySystem';
|
||||||
import { createTestState, createTestCluster } from '../__test-utils__';
|
import { createTestState, createTestCluster } from '../__test-utils__';
|
||||||
import type { MarketTickResult } from './marketSystem';
|
import type { MarketTickResult } from './marketSystem';
|
||||||
import type { InfrastructureState } from '@ai-tycoon/shared';
|
import type { InfrastructureState } from '@token-empire/shared';
|
||||||
|
|
||||||
function createMarketResult(
|
function createMarketResult(
|
||||||
overrides: Partial<MarketTickResult> = {},
|
overrides: Partial<MarketTickResult> = {},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { GameState, EconomyState, InfrastructureState } from '@ai-tycoon/shared';
|
import type { GameState, EconomyState, InfrastructureState } from '@token-empire/shared';
|
||||||
import { FINANCIAL_SNAPSHOT_INTERVAL, MAX_FINANCIAL_HISTORY, REGULATION_COMPLIANCE_PER_CAPABILITY } from '@ai-tycoon/shared';
|
import { FINANCIAL_SNAPSHOT_INTERVAL, MAX_FINANCIAL_HISTORY, REGULATION_COMPLIANCE_PER_CAPABILITY } from '@token-empire/shared';
|
||||||
import { TECH_TREE } from '../data/techTree';
|
import { TECH_TREE } from '../data/techTree';
|
||||||
import type { MarketTickResult } from './marketSystem';
|
import type { MarketTickResult } from './marketSystem';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { GameState, Era } from '@ai-tycoon/shared';
|
import type { GameState, Era } from '@token-empire/shared';
|
||||||
import { ERA_THRESHOLDS } from '@ai-tycoon/shared';
|
import { ERA_THRESHOLDS } from '@token-empire/shared';
|
||||||
|
|
||||||
export function checkEraTransition(state: GameState): Era | null {
|
export function checkEraTransition(state: GameState): Era | null {
|
||||||
const current = state.meta.currentEra;
|
const current = state.meta.currentEra;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { GameState, FundingState, FundingRoundType } from '@ai-tycoon/shared';
|
import type { GameState, FundingState, FundingRoundType } from '@token-empire/shared';
|
||||||
import { FUNDING_ROUNDS } from '@ai-tycoon/shared';
|
import { FUNDING_ROUNDS } from '@token-empire/shared';
|
||||||
|
|
||||||
const ROUND_ORDER: FundingRoundType[] = ['seed', 'seriesA', 'seriesB', 'seriesC', 'seriesD', 'ipo'];
|
const ROUND_ORDER: FundingRoundType[] = ['seed', 'seriesA', 'seriesB', 'seriesC', 'seriesD', 'ipo'];
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type {
|
|||||||
DeploymentCohort, PipelineStage, RackSkuId,
|
DeploymentCohort, PipelineStage, RackSkuId,
|
||||||
SwitchTier, DCNetworkSummary, CampusNetworkSummary, ClusterNetworkSummary,
|
SwitchTier, DCNetworkSummary, CampusNetworkSummary, ClusterNetworkSummary,
|
||||||
RepairBatch, CampusRetrofitQueue, DCTier, IntraNodeInterconnect, NetworkFabric, RackSkuConfig,
|
RepairBatch, CampusRetrofitQueue, DCTier, IntraNodeInterconnect, NetworkFabric, RackSkuConfig,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
LOCATION_CONFIGS,
|
LOCATION_CONFIGS,
|
||||||
RACK_SKU_CONFIGS,
|
RACK_SKU_CONFIGS,
|
||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
COOLING_TYPE_CONFIGS,
|
COOLING_TYPE_CONFIGS,
|
||||||
NETWORK_FABRIC_CONFIGS,
|
NETWORK_FABRIC_CONFIGS,
|
||||||
estimateNetworkSlots,
|
estimateNetworkSlots,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type { TickNotification } from '../tick';
|
import type { TickNotification } from '../tick';
|
||||||
import type { ResearchBonuses } from './researchBonuses';
|
import type { ResearchBonuses } from './researchBonuses';
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { ApiTierState, ApiTierId, DeveloperEcosystem, TierServingMetrics } from '@ai-tycoon/shared';
|
import type { ApiTierState, ApiTierId, DeveloperEcosystem, TierServingMetrics } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
API_TIER_ORDER,
|
API_TIER_ORDER,
|
||||||
API_CONVERSION_RATES,
|
API_CONVERSION_RATES,
|
||||||
API_TIER_CHURN_RATES,
|
API_TIER_CHURN_RATES,
|
||||||
API_TOKENS_PER_DEVELOPER_PER_TICK,
|
API_TOKENS_PER_DEVELOPER_PER_TICK,
|
||||||
REJECTION_CHURN_MULTIPLIER,
|
REJECTION_CHURN_MULTIPLIER,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
export interface ApiTickResult {
|
export interface ApiTickResult {
|
||||||
apiTiers: ApiTierState;
|
apiTiers: ApiTierState;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ConsumerTierState, ConsumerTierId, TierServingMetrics } from '@ai-tycoon/shared';
|
import type { ConsumerTierState, ConsumerTierId, TierServingMetrics } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
CONSUMER_TIER_ORDER,
|
CONSUMER_TIER_ORDER,
|
||||||
CONVERSION_RATES,
|
CONVERSION_RATES,
|
||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
PRICE_SATISFACTION_WEIGHT,
|
PRICE_SATISFACTION_WEIGHT,
|
||||||
PRICE_CHURN_EXPONENT,
|
PRICE_CHURN_EXPONENT,
|
||||||
PRICE_CHURN_MAX_MULTIPLIER,
|
PRICE_CHURN_MAX_MULTIPLIER,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
export interface ConsumerTickResult {
|
export interface ConsumerTickResult {
|
||||||
consumerTiers: ConsumerTierState;
|
consumerTiers: ConsumerTierState;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { DeveloperEcosystem } from '@ai-tycoon/shared';
|
import type { DeveloperEcosystem } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
BASE_DEV_GROWTH,
|
BASE_DEV_GROWTH,
|
||||||
FREE_TIER_DEV_MULTIPLIER,
|
FREE_TIER_DEV_MULTIPLIER,
|
||||||
@@ -9,8 +9,8 @@ import {
|
|||||||
STARTUP_ADOPTION_PER_DEV,
|
STARTUP_ADOPTION_PER_DEV,
|
||||||
ENTERPRISE_REFERRAL_PER_STARTUP,
|
ENTERPRISE_REFERRAL_PER_STARTUP,
|
||||||
TAM_BASE_SIZES,
|
TAM_BASE_SIZES,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type { Era } from '@ai-tycoon/shared';
|
import type { Era } from '@token-empire/shared';
|
||||||
|
|
||||||
export function processDeveloperEcosystem(
|
export function processDeveloperEcosystem(
|
||||||
eco: DeveloperEcosystem,
|
eco: DeveloperEcosystem,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type {
|
|||||||
EnterprisePipelineStage,
|
EnterprisePipelineStage,
|
||||||
DeveloperEcosystem,
|
DeveloperEcosystem,
|
||||||
TierServingMetrics,
|
TierServingMetrics,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
BASE_LEAD_RATE,
|
BASE_LEAD_RATE,
|
||||||
LEAD_EXPIRY_TICKS,
|
LEAD_EXPIRY_TICKS,
|
||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
ENTERPRISE_CAPABILITY_REQUIREMENTS,
|
ENTERPRISE_CAPABILITY_REQUIREMENTS,
|
||||||
ENTERPRISE_TOKENS_PER_TICK,
|
ENTERPRISE_TOKENS_PER_TICK,
|
||||||
ENTERPRISE_REJECTION_SLA_MULTIPLIER,
|
ENTERPRISE_REJECTION_SLA_MULTIPLIER,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import { ENTERPRISE_NAMES } from '../../data/enterpriseNames';
|
import { ENTERPRISE_NAMES } from '../../data/enterpriseNames';
|
||||||
|
|
||||||
let leadIdCounter = 0;
|
let leadIdCounter = 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { GameState, MarketState, ModelCapabilities } from '@ai-tycoon/shared';
|
import type { GameState, MarketState, ModelCapabilities } from '@token-empire/shared';
|
||||||
import { CONSUMER_TOKENS_PER_SUBSCRIBER, API_TOKENS_PER_DEVELOPER_PER_TICK, BATCH_API_DEMAND_PER_DEV, makeInitialServingMetrics } from '@ai-tycoon/shared';
|
import { CONSUMER_TOKENS_PER_SUBSCRIBER, API_TOKENS_PER_DEVELOPER_PER_TICK, BATCH_API_DEMAND_PER_DEV, makeInitialServingMetrics } from '@token-empire/shared';
|
||||||
import type { TrafficPriority, TierServingMetrics } from '@ai-tycoon/shared';
|
import type { TrafficPriority, TierServingMetrics } from '@token-empire/shared';
|
||||||
import { computeSeasonal } from './seasonalSystem';
|
import { computeSeasonal } from './seasonalSystem';
|
||||||
import { updateObsolescence } from './obsolescenceSystem';
|
import { updateObsolescence } from './obsolescenceSystem';
|
||||||
import { buildPlayerProfile, buildCompetitorProfile, computeMarketShares, updateTAMGrowth } from './tamSystem';
|
import { buildPlayerProfile, buildCompetitorProfile, computeMarketShares, updateTAMGrowth } from './tamSystem';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { ObsolescenceState, Era } from '@ai-tycoon/shared';
|
import type { ObsolescenceState, Era } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
OBSOLESCENCE_BASELINE_GROWTH,
|
OBSOLESCENCE_BASELINE_GROWTH,
|
||||||
OBSOLESCENCE_ERA_ACCELERATOR,
|
OBSOLESCENCE_ERA_ACCELERATOR,
|
||||||
FRESHNESS_DECAY_RATE,
|
FRESHNESS_DECAY_RATE,
|
||||||
NEW_MODEL_BOOST_TICKS,
|
NEW_MODEL_BOOST_TICKS,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
export function updateObsolescence(
|
export function updateObsolescence(
|
||||||
obs: ObsolescenceState,
|
obs: ObsolescenceState,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CodeAssistantState, AgentsPlatformState, ModelCapabilities } from '@ai-tycoon/shared';
|
import type { CodeAssistantState, AgentsPlatformState, ModelCapabilities } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
CODE_ASSISTANT_MIN_CODING_SCORE,
|
CODE_ASSISTANT_MIN_CODING_SCORE,
|
||||||
CODE_ASSISTANT_BASE_ADOPTION_RATE,
|
CODE_ASSISTANT_BASE_ADOPTION_RATE,
|
||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
AGENTS_PLATFORM_MIN_AGENTS_SCORE,
|
AGENTS_PLATFORM_MIN_AGENTS_SCORE,
|
||||||
AGENTS_PLATFORM_BASE_ADOPTION_RATE,
|
AGENTS_PLATFORM_BASE_ADOPTION_RATE,
|
||||||
AGENTS_PLATFORM_CHURN_RATE,
|
AGENTS_PLATFORM_CHURN_RATE,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
export interface ProductLineResult {
|
export interface ProductLineResult {
|
||||||
codeAssistant: CodeAssistantState;
|
codeAssistant: CodeAssistantState;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { SeasonalPhase } from '@ai-tycoon/shared';
|
import type { SeasonalPhase } from '@token-empire/shared';
|
||||||
import { SEASONAL_CYCLE_TICKS, SEASONAL_MULTIPLIERS } from '@ai-tycoon/shared';
|
import { SEASONAL_CYCLE_TICKS, SEASONAL_MULTIPLIERS } from '@token-empire/shared';
|
||||||
|
|
||||||
export interface SeasonalResult {
|
export interface SeasonalResult {
|
||||||
phase: SeasonalPhase;
|
phase: SeasonalPhase;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import type {
|
|||||||
ServingMetrics,
|
ServingMetrics,
|
||||||
ModelUtilizationEntry,
|
ModelUtilizationEntry,
|
||||||
BatchApiState,
|
BatchApiState,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type { BaseModel, ModelsState, SizeTier } from '@ai-tycoon/shared';
|
import type { BaseModel, ModelsState, SizeTier } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
MODEL_SIZE_THROUGHPUT_SCALER,
|
MODEL_SIZE_THROUGHPUT_SCALER,
|
||||||
MOE_SPEED_MULTIPLIER,
|
MOE_SPEED_MULTIPLIER,
|
||||||
@@ -18,8 +18,8 @@ import {
|
|||||||
BASE_LATENCY_MS,
|
BASE_LATENCY_MS,
|
||||||
QUEUE_LATENCY_MS_PER_PERCENT,
|
QUEUE_LATENCY_MS_PER_PERCENT,
|
||||||
BATCH_API_MAX_PENDING,
|
BATCH_API_MAX_PENDING,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import { makeInitialServingMetrics } from '@ai-tycoon/shared';
|
import { makeInitialServingMetrics } from '@token-empire/shared';
|
||||||
|
|
||||||
export interface ModelServingSlot {
|
export interface ModelServingSlot {
|
||||||
modelId: string;
|
modelId: string;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type {
|
|||||||
Era,
|
Era,
|
||||||
ObsolescenceState,
|
ObsolescenceState,
|
||||||
DeveloperEcosystem,
|
DeveloperEcosystem,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
TAM_BASE_SIZES,
|
TAM_BASE_SIZES,
|
||||||
TAM_GROWTH_PER_TICK,
|
TAM_GROWTH_PER_TICK,
|
||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
NEW_MODEL_BOOST_VALUE,
|
NEW_MODEL_BOOST_VALUE,
|
||||||
CONSUMER_TIER_BASE_PERCEIVED_VALUE,
|
CONSUMER_TIER_BASE_PERCEIVED_VALUE,
|
||||||
PERCEIVED_VALUE_REPUTATION_RANGE,
|
PERCEIVED_VALUE_REPUTATION_RANGE,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
export interface ParticipantProfile {
|
export interface ParticipantProfile {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState } from '@ai-tycoon/shared';
|
import type { GameState } from '@token-empire/shared';
|
||||||
import { processMarketV2 } from './market/index';
|
import { processMarketV2 } from './market/index';
|
||||||
import type { ResearchBonuses } from './researchBonuses';
|
import type { ResearchBonuses } from './researchBonuses';
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { processModels } from './modelSystem';
|
|||||||
import {
|
import {
|
||||||
POINT_RELEASE_CAPABILITY_GAIN,
|
POINT_RELEASE_CAPABILITY_GAIN,
|
||||||
VRAM_REQUIREMENTS_BY_GENERATION,
|
VRAM_REQUIREMENTS_BY_GENERATION,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type { ResearchBonuses } from './researchBonuses';
|
import type { ResearchBonuses } from './researchBonuses';
|
||||||
|
|
||||||
const rng = createSeededRNG(42);
|
const rng = createSeededRNG(42);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type {
|
|||||||
GameState, ModelsState, BaseModel, ModelCapabilities, SafetyProfile,
|
GameState, ModelsState, BaseModel, ModelCapabilities, SafetyProfile,
|
||||||
TrainingPipeline, TrainingEvent, TrainingEventType,
|
TrainingPipeline, TrainingEvent, TrainingEventType,
|
||||||
ModelVariant, VariantCreationJob,
|
ModelVariant, VariantCreationJob,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
uuid, VRAM_REQUIREMENTS_BY_GENERATION,
|
uuid, VRAM_REQUIREMENTS_BY_GENERATION,
|
||||||
MOE_CAPABILITY_MULTIPLIER, MOE_SPEED_MULTIPLIER,
|
MOE_CAPABILITY_MULTIPLIER, MOE_SPEED_MULTIPLIER,
|
||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
POINT_RELEASE_CAPABILITY_GAIN,
|
POINT_RELEASE_CAPABILITY_GAIN,
|
||||||
SIZE_TIER_LABELS,
|
SIZE_TIER_LABELS,
|
||||||
MODEL_BASE_SAFETY,
|
MODEL_BASE_SAFETY,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type { ResearchBonuses } from './researchBonuses';
|
import type { ResearchBonuses } from './researchBonuses';
|
||||||
|
|
||||||
export interface ModelTickResult {
|
export interface ModelTickResult {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
LOW_SAFETY_THRESHOLD,
|
LOW_SAFETY_THRESHOLD,
|
||||||
SAFETY_RECORD_RECOVERY_RATE,
|
SAFETY_RECORD_RECOVERY_RATE,
|
||||||
SAFETY_INCIDENT_REPUTATION_HIT,
|
SAFETY_INCIDENT_REPUTATION_HIT,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
|
|
||||||
const rng = createSeededRNG(42);
|
const rng = createSeededRNG(42);
|
||||||
beforeEach(() => rng.install());
|
beforeEach(() => rng.install());
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState, ReputationState } from '@ai-tycoon/shared';
|
import type { GameState, ReputationState } from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
MAX_REPUTATION_HISTORY,
|
MAX_REPUTATION_HISTORY,
|
||||||
SAFETY_INCIDENT_PROBABILITY_BASE,
|
SAFETY_INCIDENT_PROBABILITY_BASE,
|
||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
LOW_SAFETY_THRESHOLD,
|
LOW_SAFETY_THRESHOLD,
|
||||||
SAFETY_RECORD_RECOVERY_RATE,
|
SAFETY_RECORD_RECOVERY_RATE,
|
||||||
PUBLIC_PERCEPTION_GROWTH_RATE,
|
PUBLIC_PERCEPTION_GROWTH_RATE,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import type { ResearchBonuses } from './researchBonuses';
|
import type { ResearchBonuses } from './researchBonuses';
|
||||||
|
|
||||||
export interface ReputationTickResult {
|
export interface ReputationTickResult {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState, ResearchState, ActiveResearch, ComputeState } from '@ai-tycoon/shared';
|
import type { GameState, ResearchState, ActiveResearch, ComputeState } from '@token-empire/shared';
|
||||||
import { TECH_TREE } from '../data/techTree';
|
import { TECH_TREE } from '../data/techTree';
|
||||||
|
|
||||||
export interface ResearchTickResult {
|
export interface ResearchTickResult {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { GameState, TalentState } from '@ai-tycoon/shared';
|
import type { GameState, TalentState } from '@token-empire/shared';
|
||||||
import { ERA_BUDGET_COST_MULTIPLIER } from '@ai-tycoon/shared';
|
import { ERA_BUDGET_COST_MULTIPLIER } from '@token-empire/shared';
|
||||||
|
|
||||||
const SALARY_PER_HEADCOUNT_PER_TICK = 5;
|
const SALARY_PER_HEADCOUNT_PER_TICK = 5;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState, AchievementDefinition } from '@ai-tycoon/shared';
|
import type { GameState, AchievementDefinition } from '@token-empire/shared';
|
||||||
import { processEconomy } from './systems/economySystem';
|
import { processEconomy } from './systems/economySystem';
|
||||||
import { processInfrastructure } from './systems/infrastructureSystem';
|
import { processInfrastructure } from './systems/infrastructureSystem';
|
||||||
import { computeCapacity, finalizeCompute } from './systems/computeSystem';
|
import { computeCapacity, finalizeCompute } from './systems/computeSystem';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "@ai-tycoon/tsconfig/base.json",
|
"extends": "@token-empire/tsconfig/base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src"
|
"rootDir": "src"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@ai-tycoon/game-simulation",
|
"name": "@token-empire/game-simulation",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
"test": "vitest run"
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-tycoon/shared": "workspace:*",
|
"@token-empire/shared": "workspace:*",
|
||||||
"@ai-tycoon/game-engine": "workspace:*"
|
"@token-empire/game-engine": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ai-tycoon/tsconfig": "workspace:*",
|
"@token-empire/tsconfig": "workspace:*",
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"tsx": "^4.19.4",
|
"tsx": "^4.19.4",
|
||||||
"typescript": "^5.8.0"
|
"typescript": "^5.8.0"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState } from '@ai-tycoon/shared';
|
import type { GameState } from '@token-empire/shared';
|
||||||
|
|
||||||
export function acquireCompetitor(state: GameState, competitorId: string): boolean {
|
export function acquireCompetitor(state: GameState, competitorId: string): boolean {
|
||||||
const rival = state.competitors.rivals.find(r => r.id === competitorId);
|
const rival = state.competitors.rivals.find(r => r.id === competitorId);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState, OwnedDataset } from '@ai-tycoon/shared';
|
import type { GameState, OwnedDataset } from '@token-empire/shared';
|
||||||
|
|
||||||
export function purchaseDataset(state: GameState, dataset: OwnedDataset, cost: number): boolean {
|
export function purchaseDataset(state: GameState, dataset: OwnedDataset, cost: number): boolean {
|
||||||
if (state.economy.money < cost) return false;
|
if (state.economy.money < cost) return false;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { GameState, FundingRoundType } from '@ai-tycoon/shared';
|
import type { GameState, FundingRoundType } from '@token-empire/shared';
|
||||||
import { FUNDING_ROUNDS } from '@ai-tycoon/shared';
|
import { FUNDING_ROUNDS } from '@token-empire/shared';
|
||||||
import { canRaiseFunding, getNextFundingRound } from '@ai-tycoon/game-engine';
|
import { canRaiseFunding, getNextFundingRound } from '@token-empire/game-engine';
|
||||||
|
|
||||||
export function raiseFunding(state: GameState, roundType: FundingRoundType): boolean {
|
export function raiseFunding(state: GameState, roundType: FundingRoundType): boolean {
|
||||||
const config = FUNDING_ROUNDS[roundType];
|
const config = FUNDING_ROUNDS[roundType];
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type {
|
|||||||
GameState, Era, LocationId, DCTier, RackSkuId,
|
GameState, Era, LocationId, DCTier, RackSkuId,
|
||||||
Cluster, Campus, DataCenter, DeploymentCohort,
|
Cluster, Campus, DataCenter, DeploymentCohort,
|
||||||
CoolingType, NetworkFabric, PipelineStage,
|
CoolingType, NetworkFabric, PipelineStage,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
LOCATION_CONFIGS, DC_TIER_CONFIGS, RACK_SKU_CONFIGS,
|
LOCATION_CONFIGS, DC_TIER_CONFIGS, RACK_SKU_CONFIGS,
|
||||||
CLUSTER_COST_CONFIG, CAMPUS_TIER_COSTS, FIRST_CAMPUS_BUILD_TICKS,
|
CLUSTER_COST_CONFIG, CAMPUS_TIER_COSTS, FIRST_CAMPUS_BUILD_TICKS,
|
||||||
@@ -11,10 +11,10 @@ import {
|
|||||||
FABRIC_ORDER, NETWORK_FABRIC_CONFIGS,
|
FABRIC_ORDER, NETWORK_FABRIC_CONFIGS,
|
||||||
DC_UPGRADE_COST_FRACTION, DC_UPGRADE_INCREMENT,
|
DC_UPGRADE_COST_FRACTION, DC_UPGRADE_INCREMENT,
|
||||||
estimateNetworkSlots, maxComputeRacks,
|
estimateNetworkSlots, maxComputeRacks,
|
||||||
} from '@ai-tycoon/shared';
|
} from '@token-empire/shared';
|
||||||
import {
|
import {
|
||||||
emptyDCNetworkSummary, emptyCampusNetworkSummary, emptyClusterNetworkSummary,
|
emptyDCNetworkSummary, emptyCampusNetworkSummary, emptyClusterNetworkSummary,
|
||||||
} from '@ai-tycoon/game-engine';
|
} from '@token-empire/game-engine';
|
||||||
import { simId } from './ids';
|
import { simId } from './ids';
|
||||||
|
|
||||||
const ERA_ORDER: Era[] = ['startup', 'scaleup', 'bigtech', 'agi'];
|
const ERA_ORDER: Era[] = ['startup', 'scaleup', 'bigtech', 'agi'];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { GameState, ConsumerTierId, ApiTierId } from '@ai-tycoon/shared';
|
import type { GameState, ConsumerTierId, ApiTierId } from '@token-empire/shared';
|
||||||
|
|
||||||
export function setTrainingAllocation(state: GameState, ratio: number): void {
|
export function setTrainingAllocation(state: GameState, ratio: number): void {
|
||||||
state.compute.trainingAllocation = ratio;
|
state.compute.trainingAllocation = ratio;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user