# robertley/sap-calculator architecture

> Architecture diagram of the GitHub repository robertley/sap-calculator, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/robertley/sap-calculator
- Repository: https://github.com/robertley/sap-calculator

## Overview

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: [`src/app/runtime/state`](https://github.com/robertley/sap-calculator/tree/master/src/app/runtime/state) (Runtime state), [`src/app/integrations`](https://github.com/robertley/sap-calculator/tree/master/src/app/integrations) (Integrations), [`src/app/gameplay`](https://github.com/robertley/sap-calculator/tree/master/src/app/gameplay) (Gameplay core), [`simulation`](https://github.com/robertley/sap-calculator/tree/master/simulation) (Headless sim)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_src_app["src/app"]
  node_integrations_root["Integrations<br/>Wiring layer"]
  node_ability_integration["Ability wiring<br/>Event orchestration"]
  node_pet_equipment_toy["Content wiring<br/>Factory registries"]
  node_replay_integration["Replay import<br/>Replay pipeline"]
  node_sim_service["Simulation svc<br/>App service"]
  node_domain_model["Domain model<br/>Game rules"]
  node_catalog_content["Catalog<br/>Content data"]
end

subgraph group_ui["UI shell"]
  node_src_main["App entry<br/>Angular bootstrap<br/>[main.ts]"]
  node_app_shell["Shell<br/>[app.component.ts]"]
  node_ui_features["Feature UI<br/>Angular components"]
  node_shell_state["Shell state<br/>UI facades"]
end

subgraph group_core["Simulation core"]
  node_gameplay_core["Gameplay core<br/>Combat engine"]
  node_simulation_runner["Runner<br/>Battle orchestrator"]
  node_event_processor["Events<br/>Combat loop<br/>[event-processor.ts]"]
  node_ability_engine["Abilities<br/>Trigger resolver<br/>[ability-engine.ts]"]
end

subgraph group_runtime["Runtime state"]
  node_runtime_state["Runtime state<br/>State services"]
  node_runtime_utils["Runtime utils<br/>App helpers"]
end

subgraph group_assets["Assets"]
  node_asset_data["Game data<br/>Static data"]
end

subgraph group_headless["Headless"]
  node_headless_sim["Headless sim<br/>Node bundle"]
  node_evolution_search["Evolution<br/>Research workflow"]
end

subgraph group_aux["Aux services"]
  node_proxy_server["Replay proxy<br/>Node server<br/>[index.js]"]
  node_automation_scripts["Scripts<br/>Tooling"]
end

node_src_main -->|"boots"| node_app_shell
node_app_shell -->|"uses"| node_shell_state
node_app_shell -->|"renders"| node_ui_features
node_ui_features -->|"binds"| node_runtime_state
node_shell_state -->|"syncs"| node_runtime_state
node_runtime_state -->|"maps config"| node_sim_service
node_runtime_utils -.->|"supports"| node_runtime_state
node_integrations_root -->|"wires"| node_pet_equipment_toy
node_integrations_root -->|"wires"| node_ability_integration
node_integrations_root -->|"wires"| node_replay_integration
node_integrations_root -->|"exposes"| node_sim_service
node_pet_equipment_toy -->|"reads"| node_catalog_content
node_ability_integration -->|"operates on"| node_domain_model
node_replay_integration -->|"imports"| node_runtime_state
node_sim_service -->|"executes"| node_gameplay_core
node_gameplay_core -->|"drives"| node_simulation_runner
node_simulation_runner -->|"steps"| node_event_processor
node_event_processor -->|"resolves"| node_ability_engine
node_ability_engine -->|"mutates"| node_domain_model
node_gameplay_core -->|"depends on"| node_domain_model
node_headless_sim -->|"reuses"| node_gameplay_core
node_headless_sim -.->|"feeds"| node_automation_scripts
node_proxy_server -.->|"supports"| node_replay_integration
node_asset_data -.->|"backing data"| node_catalog_content
node_automation_scripts -.->|"invokes"| node_headless_sim
node_evolution_search -.->|"scores"| node_headless_sim

click node_src_main "https://github.com/robertley/sap-calculator/blob/master/src/main.ts"
click node_app_shell "https://github.com/robertley/sap-calculator/blob/master/src/app/ui/shell/app.component.ts"
click node_ui_features "https://github.com/robertley/sap-calculator/tree/master/src/app/ui/components"
click node_shell_state "https://github.com/robertley/sap-calculator/tree/master/src/app/ui/shell/state"
click node_runtime_state "https://github.com/robertley/sap-calculator/tree/master/src/app/runtime/state"
click node_runtime_utils "https://github.com/robertley/sap-calculator/tree/master/src/app/runtime"
click node_integrations_root "https://github.com/robertley/sap-calculator/tree/master/src/app/integrations"
click node_ability_integration "https://github.com/robertley/sap-calculator/tree/master/src/app/integrations/ability"
click node_pet_equipment_toy "https://github.com/robertley/sap-calculator/tree/master/src/app/integrations/pet"
click node_replay_integration "https://github.com/robertley/sap-calculator/tree/master/src/app/integrations/replay"
click node_sim_service "https://github.com/robertley/sap-calculator/blob/master/src/app/integrations/simulation/simulation.service.ts"
click node_gameplay_core "https://github.com/robertley/sap-calculator/tree/master/src/app/gameplay"
click node_simulation_runner "https://github.com/robertley/sap-calculator/blob/master/src/app/gameplay/simulation-runner.ts"
click node_event_processor "https://github.com/robertley/sap-calculator/blob/master/src/app/gameplay/event-processor.ts"
click node_ability_engine "https://github.com/robertley/sap-calculator/blob/master/src/app/gameplay/ability-engine.ts"
click node_domain_model "https://github.com/robertley/sap-calculator/tree/master/src/app/domain"
click node_catalog_content "https://github.com/robertley/sap-calculator/tree/master/src/app/domain/entities/catalog"
click node_asset_data "https://github.com/robertley/sap-calculator/tree/master/src/assets/data"
click node_headless_sim "https://github.com/robertley/sap-calculator/tree/master/simulation"
click node_proxy_server "https://github.com/robertley/sap-calculator/blob/master/server/index.js"
click node_automation_scripts "https://github.com/robertley/sap-calculator/tree/master/scripts"
click node_evolution_search "https://github.com/robertley/sap-calculator/blob/master/scripts/evolution/ray_pytorch_evolution.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_integrations_root,node_ability_integration,node_pet_equipment_toy,node_replay_integration,node_sim_service,node_domain_model,node_catalog_content,node_proxy_server,node_automation_scripts toneBlue
class node_src_main,node_app_shell,node_ui_features,node_shell_state toneAmber
class node_gameplay_core,node_simulation_runner,node_event_processor,node_ability_engine toneMint
class node_runtime_state,node_runtime_utils toneRose
class node_asset_data toneIndigo
class node_headless_sim,node_evolution_search toneTeal
```

## Components

### src/app

Angular app, runtime state, domain model, and simulation wiring

- [Integrations](https://github.com/robertley/sap-calculator/tree/master/src/app/integrations): Wiring layer · Connects catalog content, app state, logs, replay, and simulation services · `src/app/integrations`
- [Ability wiring](https://github.com/robertley/sap-calculator/tree/master/src/app/integrations/ability): Event orchestration · Queues, priorities, and attack/faint/toy/status event handlers · `src/app/integrations/ability`
- [Content wiring](https://github.com/robertley/sap-calculator/tree/master/src/app/integrations/pet): Factory registries · Factories and registries for pets, equipment, and toys · `src/app/integrations/pet`
- [Replay import](https://github.com/robertley/sap-calculator/tree/master/src/app/integrations/replay): Replay pipeline · Replay API plumbing, calc parsing, odds, and positioning images · `src/app/integrations/replay`
- [Simulation svc](https://github.com/robertley/sap-calculator/blob/master/src/app/integrations/simulation/simulation.service.ts): App service · Creates simulation jobs, chooses worker or in-process execution, and returns results · `src/app/integrations/simulation/simulation.service.ts`
- [Domain model](https://github.com/robertley/sap-calculator/tree/master/src/app/domain): Game rules · Core entities, combat state, targeting, players, and simulation interfaces · `src/app/domain`
- [Catalog](https://github.com/robertley/sap-calculator/tree/master/src/app/domain/entities/catalog): Content data · 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](https://github.com/robertley/sap-calculator/blob/master/src/main.ts): Angular bootstrap · Bootstraps the browser application · `src/main.ts`
- [Shell](https://github.com/robertley/sap-calculator/blob/master/src/app/ui/shell/app.component.ts): Angular shell · Top-level UI component and app workflow host · `src/app/ui/shell/app.component.ts`
- [Feature UI](https://github.com/robertley/sap-calculator/tree/master/src/app/ui/components): Angular components · Team editing, replay calculator, import/export, dialogs, and reports · `src/app/ui/components`
- [Shell state](https://github.com/robertley/sap-calculator/tree/master/src/app/ui/shell/state): UI facades · 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](https://github.com/robertley/sap-calculator/tree/master/src/app/gameplay): Combat engine · Battle execution pipeline and deterministic randomness · `src/app/gameplay`
- [Runner](https://github.com/robertley/sap-calculator/blob/master/src/app/gameplay/simulation-runner.ts): Battle orchestrator · Sets up battles and coordinates execution · `src/app/gameplay/simulation-runner.ts`
- [Events](https://github.com/robertley/sap-calculator/blob/master/src/app/gameplay/event-processor.ts): Combat loop · Drives combat events through the battle lifecycle · `src/app/gameplay/event-processor.ts`
- [Abilities](https://github.com/robertley/sap-calculator/blob/master/src/app/gameplay/ability-engine.ts): Trigger resolver · Resolves triggers, timing, and priority ordering · `src/app/gameplay/ability-engine.ts`

### Runtime state

Mutable app state and persistence bridge

- [Runtime state](https://github.com/robertley/sap-calculator/tree/master/src/app/runtime/state): State services · Local storage, URL sync, calculator/game state, and simulation form mapping · `src/app/runtime/state`
- [Runtime utils](https://github.com/robertley/sap-calculator/tree/master/src/app/runtime): App helpers · Rounding, randomness, sound prefs, assets, and pack metadata · `src/app/runtime`

### Assets

Static game data and media

- [Game data](https://github.com/robertley/sap-calculator/tree/master/src/assets/data): Static 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](https://github.com/robertley/sap-calculator/tree/master/simulation): Node bundle · Library and CLI bundle for standalone simulations and batch evaluation · `simulation`
- [Evolution](https://github.com/robertley/sap-calculator/blob/master/scripts/evolution/ray_pytorch_evolution.py): Research workflow · 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](https://github.com/robertley/sap-calculator/blob/master/server/index.js): Node server · Small auxiliary backend for replay API and health endpoints · `server/index.js`
- [Scripts](https://github.com/robertley/sap-calculator/tree/master/scripts): Tooling · Extraction, debugging, entity generation, and replay/team tooling · `scripts`

## Connections

- 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
