Skip to content

Planner: per-product rate goals (multiple pinned outputs per block) #36

Description

@ApocDev

A block can currently pin only one output to a target rate. The block doc (BlockData in app/src/db/schema.ts) stores a single target + rate, plus extraGoals: string[] for additional co-products. Those extra goals are unpinned: in buildBlock (app/src/server/factorio.ts) they are just relabeled from surplus exports into "primary outputs" and come out at whatever ratio the chosen recipes happen to produce. There is no way to give them their own target rate.

This breaks down for blocks that intentionally make several end products. Example: a single "logistics" block producing transport belts, undergrounds, splitters, and loaders. I want to set an independent goal rate for each (e.g. splitters @ 2/s, undergrounds @ 4/s, belts @ 10/s), not pin one and let the rest fall out.

The solver already supports this. BlockInput.targets in app/src/solver/block.ts is a { name: string; rate: number }[] and each entry becomes a pinned equation. The gap is the block doc model and the UI, not the math.

Proposed change

  • Extend BlockData so every goal can carry its own rate. Either replace target/rate/extraGoals with a goals: { name: string; rate: number }[] list, or add per-name rates alongside the existing fields. Keep a migration that maps the current { target, rate, extraGoals } shape onto the new one (add a case in app/src/server/migrations.ts, covered by migrations.test.ts).
  • Pass each goal as a pinned target to solveBlock instead of relabeling surplus exports. Drop the "extra goals = relabeled exports" path in factorio.ts (a goal with no recipe producing it stays an unmet/over-pinned target the solver reports, same as today).
  • UI in app/src/routes/block.$id.tsx: let each goal row have an editable rate, with add/remove. The first goal still drives auto-naming and the default icon.
  • Update everything that reads data.target / data.extraGoals to iterate the goal list: db/queries.ts, factory-solve.ts, agent-tools.ts, the assistant draft-a-block path, and the coherence/browse views.

Notes / open questions

  • Naming and the default icon currently key off the single primary goal; pick the first goal in the list for both.
  • Decide whether a goal can also be a negative rate (a consumption target) — the solver already allows it, but the UI may not need to expose that yet.

Part of #31.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: plannerProduction block / planning modelarea: webWeb UI (React/TanStack/vite-plus)enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions