A multi-module Gradle build.
CodeForge/
├── app/
│ ├── shared/ Compose Multiplatform UI, ViewModel, API client (commonMain)
│ │ + platform code: Monaco bridge (web), plain editor (Android, Desktop)
│ ├── webApp/ WebAssembly entry point, index.html, monaco-bridge.js
│ ├── androidApp/ Android entry point
│ └── desktopApp/ Desktop entry point
└── backend/
├── src/main/kotlin/
│ ├── config/ AppConfig: settings from the environment or the private secrets file
│ ├── routes/ problems, submissions, Codeforces import
│ ├── service/ JudgeService (builds the job, maps results to verdicts), Codeforces scraper, IST times
│ ├── worker/ JudgeWorkers: claim, lease heartbeat, reaper, Redis wake-ups
│ ├── sandbox/ Sandbox, DockerSandbox, ProcessSandbox
│ ├── queue/ Redis connection and wake-up push
│ ├── models/ Exposed tables
│ └── database/ connection, schema, seed data
├── judge-sandbox/
│ ├── harness/judge.py compile once, run tests with limits, measure, decide status
│ ├── test/run_tests.py attack suite for both sandbox modes
│ └── Dockerfile sandbox image: g++, OpenJDK 21, Python 3
├── deploy/start.sh Render entry point: moves secrets out of the environment
├── Dockerfile Render image (process mode) and a docker-mode target
└── docker-compose.yml PostgreSQL, Redis and the backend with the Docker sandbox
JudgeViewModelholds the state: imported problem and its real limits, code per language, judging flag, the latest verdict, metrics and per-test results, history.- Importing a problem resets results, metrics and test nodes. Executing keeps the previous result on screen until the new verdict arrives.
- The UI is built from small panels (
ForgePanel) on one theme (ForgeTheme,ForgeType): verdict stamp, heat line, test-case nodes, metrics with limit bars, event log, results. - On the web,
CodeTextAreaplaces the Monaco editor (an HTML element) over an empty Compose box and keeps it aligned; it hides the editor while a dropdown is open over it.