Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resource sim : non-volatile recipes #17

Open
12 of 15 tasks
gotmachine opened this issue Jul 29, 2021 · 0 comments
Open
12 of 15 tasks

Resource sim : non-volatile recipes #17

gotmachine opened this issue Jul 29, 2021 · 0 comments
Labels
code enhancement New feature or request

Comments

@gotmachine
Copy link
Contributor

gotmachine commented Jul 29, 2021

Objectives :

  • Allow user-configurable priorities for every recipe
  • Implement a post resource update callback for resource utilization scaling, instead of the (not entirely reliable) UtilizationFactor
  • Unify the whole resource sim around using recipes (ie, get ride of the direct Consume/Produce methods)
  • Performance improvements

Work items :

  • Recipe/Input/Output base class refactor
  • Depreciate ResourceBroker, recipes are the brokers
  • Allow Recipe editing (changing inputs/outputs dynamically)
  • Implement priority system and recipe list sorting
  • Implement user overrides for priorities
  • Move VesselResource dictionaries to integer keys instead of strings
  • Implement local resource input/output
  • Implement "alt input" inputs
  • Processes re-refactor
  • Local processes
  • Codebase migration : recipes
  • Codebase migration : processes
  • Codebase migration : local processes
  • Codebase migration : science data processing
  • Codebase migration : comms and control

Priority system

The executed recipes will be sorted by an integer value representing their priority. This allow deterministic results in the constraint solver, at least partially. Main use case is to have critical EC consumers (ex : ECLSS) prioritized over less critical ones. However, we need to be extra careful as to how the player can customize the priorities, as this only works if, for a specific resource, all recipes consuming that resource have a higher priority than recipes producing that resource. And since a single recipe can produce / consume multiple resources, that conditions can't be be satisfied for all resources.

Simple example :

  • Recipe A : EC input / Oxygen input
  • Recipe B : EC input / Oxygen output
  • Recipe C : EC output / Oxygen input

Here we want recipe A to have priority over recipe B in terms of EC consumption. But the consequence for Oxygen is that recipe A may, or may not be prioritized over recipe C. This will likely be quite confusing ti the player if we expose it "as is". In practice, since the only real use case for priorities is EC management, we should likely lock the EC input vs output priorities, separate them as two lists in the UI, and only allow re-organization within each list.

Additionally, some systems are relying on multiple recipes with mandatory relative priorities. Having recipes referencing other recipes will be needed for that to work.

Implementation

Managing priorities on a per-recipe basis will likely be mess, there are too many recipes coming from everywhere. Since we already implement recipe categories, managing the priorities at this level feels more manageable. For customization, the user would be presented a list of categories, and we would save a list of <category, priority> pairs at the vessel level. For handling recipe level internal priority constraints, on the premise that those pairs would always belong to the same category, this would work as priority offset. For example, categories would be 100, 200, 300, etc, while offsets would have to be in the 0-99 range.

To ensure that EC management is correct, EC producers should always have a negative priority, and everything else shoudl have a positive priority.

Local resource input/output

Implement a RecipeIO derivative that apply a production/consumption to a single part, instead of to the whole vessel resource.
Use cases : self-consuming processes (RTG, scrubbers...), possibly other "captive fuel" processes, boiloff...

In any case, we must check worstIO against the part resource wrapper amount/capacity/local deferred, and acquire a reference to the local resource wrapper in addition to the vessel wide wrapper.

But how to integrate correctly with the rest of the sim ?

  • Apply the change to VesselResource.Deferred so other recipes can compute their IOFactor correctly
  • Add the change to the vessel resource wrapper localDeffered variable
  • Add a part resource wrapper local deferred variable, and also register the change here.
  • In the SyncToPartResources() call :
    • Substract localDeffered from Deferred
    • On the part wrapper synchronization, first add the part wrapper deferred, then compute k and do the usual Deffered * k addition.
  • Performance impact should be reasonable : one extra addition per part wrapper, one extra variable to clear on synchronization. The local resource wrapper acquisition likely only need to be performed once, so no losses on that front.
  • This should support any scenario, including multiple recipes working on the same local wrapper.
  • If that works well, the idea could be extended to IOs working on a "resource part set" which would allow a basic form of flow priorities where the player can define an arbitrary set of part to be consumed from / produced to either exclusively or in priority.

Processes re-refactor

The current process implementation is messy. It adds a bunch of virtual resources that bloat the resource sim, uses a weird pooling pattern on the ProcessController side of things, and result in tons of dictionary calls to the VesselData list of processes. Proposed refactor :

  • Separate controlled processes and vessel-wide processes at the config level
  • Build a static list of vessel-wide processes (always executed)
  • Move processes execution from Kerbalism.FixedUpdate to VesselData
  • Instead of setting the capacity from the ProcessController.OnVesselDataUpdate(), register the controller to be processed by VesselData (same "list-swaping" pattern as for Recipes)
  • Get ride of the virtual resource, instead use the Recipe scaling functionality
  • For self-consuming processes (RTG, non-regen scrubber), implement a "local process" module.
    • Use a classic KSP resource and the local input recipe functionality.
    • Possibly implement a capacity modifier expression

Possible solution to the experiment / transmit scaling issue :

Experiments update :

  • Set a data virtual resource amount, unique for each module, according to the nominal data rate.
  • If "streaming" is enabled, activate a "transmit" recipe :
    • resources inputs at nominal rates
    • data input at nominal rate
    • transmitCapacity input, at the nominal data rate
    • EC input, according to the comms EC cost per data rate
  • Have a lower priority "store" recipe
    • resources inputs at nominal rates
    • data input at nominal rate
    • driveCapacity input, at the nominal data rate.

Vessel update :

  • Iterate on all drives, set the driveCapacity resource amount
  • Set the transmitCapacity amount according to the available comms data rate
  • For each file flagged for transmission, add a recipe with
    • transmitCapacity input
    • EC input, according to the comms EC cost per data rate

Experiments post-resource update :

  • Transmit or store the data according to the ExecutedFactor of the transmit/store recipes

Vessel post-resource update :

  • Transmit the data for every file, according to the ExecutedFactor of the corresponding recipe

Problems / Implications :

  • Samples could work the same, but until a decision is made about if I reimplement them as cargo parts, just ignore it.
  • This will be messy to handle on the UI side. The stored file transmission recipes can go in the "comms" category, but streaming experiments will have 2 separate EC inputs, one corresponding to the running cost, the other to the transmit cost, and both will appear under the "experiment" category.
@gotmachine gotmachine added code enhancement New feature or request labels Jul 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant