BeamNG.Earth
BeamNG.drive용 1:1 비율 실시간 지구, 실제 고도·위성 이미지·부동 원점·보조 서버에서 LOD 스트리밍
A web application for beatmania IIDX players to track and analyze BPI scores, featuring score import, progress monitoring, rival comparisons, and community metrics.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A web application for tracking and analyzing BPI (Beat Power Indicator) scores in beatmania IIDX. Players can import their scores, monitor progress over time, compare stats with rivals, and view aggregated metrics across the community.README 전문 보기 ↗A web application for tracking and analyzing BPI (Beat Power Indicator) scores in beatmania IIDX. Players can import their scores, monitor progress over time, compare stats with rivals, and view aggregated metrics across the community.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (Pages Router) |
| Language | TypeScript |
| UI | shadcn/ui (Radix UI), Tailwind CSS v4, Recharts, Lucide React, Sonner |
| Database | MySQL (via Kysely query builder) |
| Auth | Firebase Authentication |
| Backend Services | Firebase Admin SDK |
| Data Fetching | SWR |
| Cron Jobs | node-cron (sitemap, Arena metrics/distribution, Radar & song ranking caches) |
| Testing | Vitest |
git clone <repository-url>
cd BPIManager2
This project uses pnpm (enforced via preinstall, so npm install/yarn will refuse to run):
pnpm install
Copy .env.example to .env.local and fill in all values:
cp .env.example .env.local
| Variable | Description |
|---|---|
BASEURL | Public base URL of the deployment (used for sitemaps, OAuth metadata, etc.) |
DB_HOST | MySQL host (e.g. localhost) |
DB_PORT | MySQL port (defaults to 3306 if unset) |
DB_DATABASE | Database name (e.g. beatmaniaBpi) |
DB_USER | MySQL username |
DB_PW | MySQL password |
FIREBASE_PROJECT_ID | Firebase project ID |
FIREBASE_PRIVATE_KEY_ID | Service account private key ID |
FIREBASE_PRIVATE_KEY | Service account private key (include \n line breaks) |
FIREBASE_CLIENT_EMAIL | Service account client email |
FIREBASE_CLIENT_ID | Service account client ID |
FIREBASE_AUTH_URI | Firebase auth URI |
FIREBASE_TOKEN_URI | Firebase token URI |
FIREBASE_AUTH_PROVIDER_X509_CERT_URL | Auth provider cert URL |
FIREBASE_CLIENT_X509_CERT_URL | Client cert URL |
FIREBASE_UNIVERSE_DOMAIN | Usually googleapis.com |
DISCORD_BOT_TOKEN | (optional) Discord bot token; enables the Discord bot integration |
DISCORD_GUILD_ID | (optional) Discord guild ID the bot operates in |
DISCORD_COFFEE_ROLE_ID | (optional) Discord role ID granted to a supporter tier |
DISCORD_SABA_ROLE_ID | (optional) Discord role ID granted to a supporter tier |
DISCORD_SPARKLE_ROLE_ID | (optional) Discord role ID granted to a supporter tier |
USER_DELETION_BACKUP_DIR | (optional) Directory for pre-deletion user data backups (defaults under the OS home directory) |
Apply the schema to your MySQL instance:
mysql -u <user> -p < migrations/schema.sql
This creates the beatmaniaBpi database and all required tables (users, scores, bkScores, songs, songDef, follows, logs, notifications, userRadarCache, userStatusLogs, apiKeys, etc.). The schema is managed as a single SQL file (using CREATE TABLE IF NOT EXISTS, safe to re-run) rather than through a migration framework; schema changes are applied manually to existing environments. Kysely's type definitions (src/types/db.ts) are maintained by hand alongside schema changes, not generated.
The dev server uses HTTPS (required for certain browser APIs):
pnpm dev
Open https://localhost:3000 in your browser. Accept the self-signed certificate warning on first launch.
| Command | Description |
|---|---|
pnpm dev | Start development server (HTTPS) |
pnpm build | Build for production |
pnpm start | Start production server |
pnpm lint | Run ESLint |
pnpm test | Run all tests with Vitest (unit + integration) |
pnpm test:unit | Run only unit tests (no external dependencies required) |
pnpm test:integration | Run integration tests (requires a running dev server etc.) |
pnpm test:ui | Run tests with the Vitest UI |
pnpm fetch-arena-metadata | Fetch Arena metadata via scripts/fetchArenaMetadata.ts |
src/
├── assets/ # Static assets (images, lottie animations, etc.)
├── components/
│ ├── partials/ # Page-specific & shared composite components
│ │ ├── features/ # Used by exactly one page (Import, Logs, Metrics, Profile,
│ │ │ # Ranking, Rivals, Settings, Songs, Timeline, ...)
│ │ ├── common/ # Reused across 2+ features/shells (Auth, Charts, DashBoard,
│ │ │ # ListControls, Notifications, Rivals, Songs, ...)
│ │ ├── modal/ # Dialogs/modals (AccountSettings, ImageCrop, RivalComparison, SongDetail, ...)
│ │ └── shell/ # Page-level shells (RequireAuth, DashboardLayout, ProfileLayoutShell, ...)
│ └── ui/ # shadcn/ui-based generic UI primitives
├── constants/ # Constants (IIDX versions/ranks, BPM, radar topElements, theme, ...)
├── contexts/ # React context providers (locale, profile, stats, users)
├── hooks/ # SWR fetch + local state hooks, grouped by domain
│ # (dashboard, logs, rivals/social, stats, songs, users, ...)
├── lib/
│ ├── arena/ # Arena rank metrics generation
│ ├── bpi/ # BPI calculation (BpiCalculator) & score optimizer
│ ├── cache/ # Caching helpers
│ ├── cron/ # Scheduled jobs (sitemap, Arena metrics, Radar cache)
│ ├── dayjs/ # dayjs instance with plugins/timezone configured
│ ├── db/ # Kysely queries, split by role (see CLAUDE.md for details)
│ │ ├── domains/ # Single-table repositories (scores, songs, users, follow, ...)
│ │ ├── orchestrators/ # Cross-domain write transactions (batchDeletion, userDeletion, ...)
│ │ ├── aggregates/ # Cross-domain read-only aggregation views (stats, rivalScores, ...)
│ │ ├── shared/ # Side-effect-free query builders/helpers
│ │ └── index.ts # Kysely connection singleton
│ ├── discord/ # Discord.js bot
│ ├── firebase/ # Firebase Admin & Auth helpers
│ ├── i18n/ # Internationalization helpers
│ ├── lamp/ # LAMP score import utilities
│ ├── mcp/ # MCP server tools
│ ├── monthly-review/ # Monthly review generation
│ ├── radar/ # Radar chart cache calculation
│ ├── scores/ # Score evaluation helpers (improvement diff, manual batch IDs)
│ ├── subhandlers/ # API sub-handlers
│ ├── transfer/ # Data transfer / account export-import utilities
│ └── utils.ts # Shared utilities
├── middlewares/api/ # Next.js API middlewares (auth guards, profile access, etc.)
├── pages/ # Next.js Pages Router (screens & API routes)
│ └── api/v1/users/[userId]/ # REST API: scores, batches, stats, rivals,
│ # all-scores, ranking, notifications, iidx-tower, tickets, ...
├── schemas/ # Zod request/response schemas, grouped by domain
├── services/ # SWR fetchers / Next.js API request helpers
├── styles/ # Global styles (Tailwind CSS v4)
├── types/ # Type definitions (db.ts is maintained by hand alongside schema changes)
└── utils/ # Pure function utilities
public/
└── data/metrics/arena/ # Auto-generated Arena metric JSON files
migrations/
└── schema.sql # Full database schema
test/
├── unit/ # No external dependencies (day-to-day: `pnpm test:unit`)
└── integration/ # Requires a running dev server etc.
On server startup, src/instrumentation.ts starts the Arena/cron service (src/lib/cron/job.ts) and the Discord bot. Each cron task also runs once immediately on startup:
public/.public/data/metrics/arena/ and invalidates the Arena averages cache.DISCORD_BOT_TOKEN) for supporter role sync and related integrations..env.local.staging (not master — a push to master triggers a production deploy)pnpm test and pnpm lint to verifystaging; staging → master release PRs are cut separately