How robertley/sap-calculator works
1. What this repository is
- This is a Super Auto Pets battle calculator and simulator.
- It combines an Angular front end, a pure combat simulation core, replay import/parsing, optional proxy/server support, and a headless CLI/library for batch simulation.
2. Primary architectural boundary: src/app/domain
- The domain layer holds the game’s core model: pets, equipment, toys, players, combat state, abilities, targeting, and simulation configuration interfaces.
- The large entities/catalog/** tree is the content catalog: concrete implementations of official and custom pets/equipment/toys, organized by pack/tier/type.
- This layer is intended to be logic-first and mostly UI-agnostic.
3. Combat engine: src/app/gameplay
- This is the pure execution pipeline for battles.
- SimulationRunner sets up the battle, EventProcessor drives combat events, AbilityEngine resolves triggers/priority, and simulation-randomness.ts controls deterministic randomness.
- This layer is the main “simulation core” and sits underneath both the Angular UI and headless simulation bundle.
4. Wiring/orchestration: src/app/integrations
- Integrations connect catalog content and runtime behavior into the simulation.
- Subsystems include:
- pet, equipment, toy: registries, factories, and service wrappers for constructing runtime entities from catalog definitions.
- ability: queues, priorities, event triggers, and specific handlers for attack/faint/status/toy events.
- simulation: simulation service, worker bridge, constants, and positioning optimizer.
- replay: replay API plumbing, calc parsing, odds/image helpers.
- log: log service and render/merge helpers.
- This layer is where domain objects become usable in the app.
5. Application/runtime state: src/app/runtime
- Runtime services manage mutable app state, persistence, and mapping between UI forms and simulation config.
- Notable pieces are local storage, URL-state sync, calculator state, game state, sound preferences, and utility helpers like rounding/random.
- This layer is the bridge between the UI and the simulation services.
6. Angular UI shell: src/app/ui
- The UI is organized around a shell (src/app/ui/shell/app.component.ts) plus feature components for team editing, replay calculator, import/export, reporting bugs, and dialogs.
- The shell is decomposed into workflow/state/view modules, which keeps the top-level app component thin and pushes behavior into focused facades and state services.
- The UI consumes runtime/integration services rather than implementing battle rules itself.
7. Simulation data flow from UI to results
- The user edits team state in the Angular UI.
- Runtime state is converted into a SimulationConfig.
- SimulationService sends the job to simulation.worker.ts when available, or runs in-process.
- The engine computes battle outcomes, logs, and positioning results, which then flow back to the UI for display.
8. Headless simulation path: simulation/
- The simulation/ directory contains a Node/TypeScript bundle used outside the browser.
- It exposes a library entrypoint and a CLI for running single simulations, preset pool evaluation, and batch evaluation.
- This is the execution path used for automation, batch analysis, and evolutionary search workflows.
9. Replay and import pipeline
- Replay-related code ingests battle/replay data, parses calculator output, and can generate images or structured replay artifacts.
- The repository supports proxying replay APIs through the local Angular dev server, with an optional local backend target configured via environment variables.
- The replay subsystem is distinct from the battle simulator: it transforms external replay data into calculator input/output, rather than resolving combat rules.
10. Optional replay proxy server: server/
- server/index.js provides a small backend with /api/health, /api/replays/:id/turns, and /api/replay-battle.
- The Angular dev server proxies /api traffic to this service or to the external replay API target.
- This is an auxiliary boundary for network access, not the main application runtime.
11. Content and asset dependencies
- Static game data is stored under src/assets/data as JSON/text files for pets, food, toys, perks, pet sounds, and “Dangers and Useful.”
- The app also ships a large asset set for art, sounds, and fonts, which materially affects UI rendering and audio behavior.
- The content registry code in src/app/integrations/* and src/app/domain/entities/catalog/* must stay aligned with these data assets.
12. Testing and regression strategy
- The repo uses Vitest as the primary test system, with broad coverage of simulation edge cases, replay parsing, UI interactions, and registry synchronization.
- The many simulation regression tests indicate the combat engine is the most behavior-sensitive subsystem.
- There are also pilot/meta tests to ensure catalogs and registries stay in sync with the generated/tested manifest.
13. Automation and research tooling
- scripts/ contains a mix of data extraction, replay fetching, parser debugging, entity-test generation, and team-generation tooling.
- scripts/evolution/ adds a Python/Ray/PyTorch evolutionary search workflow that consumes the headless simulation CLI.
- These scripts are externalized support tools around the simulator, not part of the core runtime path.
14. Diagram-friendly summary
- The core architecture is: Angular UI and persisted runtime state at the top, orchestration/integration services in the middle, and a pure combat domain + gameplay engine underneath.
- Surrounding that core are replay ingestion/proxy services, headless CLI/batch execution, and large static content/asset catalogs.
- The main design principle is separation between game rules, app state, and presentation.
Main entry points: state Runtime state · integrations Integrations · gameplay Gameplay core · simulation Headless sim
Components 22
src/app
Angular app, runtime state, domain model, and simulation wiring
- Integrations · Connects catalog content, app state, logs, replay, and simulation services
src/app/integrations - Ability wiring · Queues, priorities, and attack/faint/toy/status event handlers
src/app/integrations/ability - Content wiring · Factories and registries for pets, equipment, and toys
src/app/integrations/pet - Replay import · Replay API plumbing, calc parsing, odds, and positioning images
src/app/integrations/replay - Simulation svc · Creates simulation jobs, chooses worker or in-process execution, and returns results
src/app/integrations/simulation/simulation.service.ts - Domain model · Core entities, combat state, targeting, players, and simulation interfaces
src/app/domain - Catalog · Concrete official and custom pets, equipment, and toys organized by pack and tier
src/app/domain/entities/catalog
UI shell
Presentation layer and feature components
- App entry · Bootstraps the browser application
src/main.ts - Shell · Top-level UI component and app workflow host
src/app/ui/shell/app.component.ts - Feature UI · Team editing, replay calculator, import/export, dialogs, and reports
src/app/ui/components - Shell state · Feature state, forms, themes, teams, and overlays for the shell
src/app/ui/shell/state
Simulation core
Pure combat execution and game rules
- Gameplay core · Battle execution pipeline and deterministic randomness
src/app/gameplay - Runner · Sets up battles and coordinates execution
src/app/gameplay/simulation-runner.ts - Events · Drives combat events through the battle lifecycle
src/app/gameplay/event-processor.ts - Abilities · Resolves triggers, timing, and priority ordering
src/app/gameplay/ability-engine.ts
Runtime state
Mutable app state and persistence bridge
- Runtime state · Local storage, URL sync, calculator/game state, and simulation form mapping
src/app/runtime/state - Runtime utils · Rounding, randomness, sound prefs, assets, and pack metadata
src/app/runtime
Assets
Static game data and media
- Game data · JSON and text data for pets, food, toys, perks, sounds, and helpers
src/assets/data
Headless
Node CLI and batch simulation entrypoints
- Headless sim · Library and CLI bundle for standalone simulations and batch evaluation
simulation - Evolution · Python/Ray/PyTorch evolutionary search built on the headless simulator
scripts/evolution/ray_pytorch_evolution.py
Aux services
Replay proxy and automation tooling
- Replay proxy · Small auxiliary backend for replay API and health endpoints
server/index.js - Scripts · Extraction, debugging, entity generation, and replay/team tooling
scripts
Connections 26
- App entry → Shell: boots · Bootstraps the Angular shell
- Shell → Shell state: uses · Shell delegates workflow state to facades and services
- Shell → Feature UI: renders · Shell hosts feature components
- Feature UI → Runtime state: binds · Forms and UI actions flow into persisted app state
- Shell state → Runtime state: syncs · Shell state reads and updates runtime state
- Runtime state → Simulation svc: maps config · Converts UI state into simulation configuration
- Runtime utils → Runtime state: supports · Utility helpers support state mapping and preferences
- Integrations → Content wiring: wires · Constructs runtime entities from catalog definitions
- Integrations → Ability wiring: wires · Sets up ability queues and event handlers
- Integrations → Replay import: wires · Connects replay parsing and image helpers
- Integrations → Simulation svc: exposes · Provides simulation-facing application services
- Content wiring → Catalog: reads · Registry and factory layers consume catalog definitions
- Ability wiring → Domain model: operates on · Ability events run against domain entities and combat state
- Replay import → Runtime state: imports · Replay parsing produces calculator-friendly state
- Simulation svc → Gameplay core: executes · Hands simulation jobs to the combat engine
- Gameplay core → Runner: drives · Runner coordinates battle setup and execution
- Runner → Events: steps · Event processor advances combat flow
- Events → Abilities: resolves · Events invoke ability timing and priority resolution
- Abilities → Domain model: mutates · Ability resolution updates combat and player state
- Gameplay core → Domain model: depends on · Engine relies on core game entities and interfaces
- Headless sim → Gameplay core: reuses · CLI/library path shares the same combat engine
- Headless sim → Scripts: feeds · Batch workflows consume the headless bundle
- Replay proxy → Replay import: supports · Auxiliary backend serves replay API traffic
- Game data → Catalog: backing data · Static data must stay aligned with catalog registries
- Scripts → Headless sim: invokes · Tooling and research scripts call into the simulator
- Evolution → Headless sim: scores · Evolutionary search evaluates candidates via the simulator