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

FEATURE: Better SmartSupply #1623

Open
wants to merge 10 commits into
base: dev
Choose a base branch
from

Conversation

cmfrydos
Copy link
Contributor

@cmfrydos cmfrydos commented Aug 23, 2024

FEATURE: Better SmartSupply

This pull request introduces a new algorithm to improve the current functionality of SmartSupply. The algorithm addresses several shortcomings of the existing system, extending its capabilities and making it more reliable and user-friendly for players.
The new algorithm is a bit better at handling tricky situations, but it’s still possible for players to create their own version using the in-game scripting tools if they prefer to save on SmartSupply costs.

Basics

Corporations cycle through several distinct phases: "START" -> "PURCHASE" -> "PRODUCTION" -> "EXPORT" -> "SALE". To ensure sufficient base materials for production, players must calculate the necessary quantities during the "PURCHASE" phase. SmartSupply automates this task, making it more convenient. The products and materials used can vary by industry, with different sizes and conversion ratios.

Current Problems

There are two major and two minor issues with the current implementation.

a) Overbuying Resources When Products Are Larger Than Their Base Materials

The current algorithm fails to account for situations where the volume of materials increases during production. For example, in mining, small amounts of hardware are used to produce large quantities of ore and minerals. The old algorithm tends to overbuy materials, leaving insufficient room for production. The new algorithm reserves the exact amount of space needed for production.

b) Underbuying When Base Materials Are Already in the Warehouse

When base materials are already present in the warehouse, the current algorithm reduces the maximum amount of resources that can be bought by the space occupied by these materials. It then splits the remaining space according to material ratios and buys the necessary amounts. However, this approach only adjusts for base resources already in the warehouse after the split, leading to inefficiencies. For example:

  • Suppose product C is made from A and B, both of size 1:
    • 1 A + 1 B -> 1 C
  • If the warehouse is 20% filled with A and 80% empty, the algorithm splits this empty space 1:1 between A and B.
  • Resulting in:
    • 0.2 A in store
    • Up to 0.4 A and 0.4 B to be bought
  • After purchasing, the warehouse contains:
    • 40% A, 40% B, and 20% empty space.

c) (Minor) Activation with a One-Cycle Delay

The current algorithm relies on "measured" production volume information from the previous production cycle to calculate the necessary materials, causing a one-cycle delay in activation and updating. The new algorithm, instead, calculates the required amounts directly, eliminating this delay.

d) (Minor) Ignoring Import Volume

The current algorithm does not consider the amount of imported materials when determining available space, which can result in insufficient base materials for the next cycle. The new algorithm addresses this by reserving space for the import cycle.

Changes

  • Immediate activation using the most current production data.
  • Reserving enough headroom in the warehouse for the import and production stages.
  • Correctly filling warehouses according to the correct ratio of input material volumes, while avoiding overloading production capacities.

New SmartSupply Algorithm Overview

The main task of SmartSupply is to optimize the usage of available space in the warehouse. The goal is to ensure that:

  1. Production is maximized.
  2. All purchased resources are fully utilized.
  3. Future imports are not congested.

Before the SmartSupply algorithm is triggered, the warehouse might look like this:

Initial Warehouse State

Improved Algorithm: Reserving Space for Imports

The new algorithm enhances the previous approach by reserving space for the IMPORT/EXPORT phase, which occurs after the PRODUCTION phase and before the SALE phase. This reservation ensures that there is no congestion when importing new materials.

Warehouse with Reserved Space

Analyzing Filled Space

Next, the algorithm analyzes the filled space. It identifies the space used by existing input materials and combines this with the empty space to determine the "available space" for production.

Analyzing Filled Space

Calculating Ratios and reserving Space for Output

SmartSupply's task is now to adjust the ratios of resources within this space to optimize production. The algorithm examines each required input material, calculates the ratio of existing to needed quantities, and adjusts the available space accordingly. If there is already more of a resource than required, the algorithm removes the space allocated for that resource and recalculates the ratios.

Example 1: Mining

For example, in mining:

  • Input: 0.1 units of Hardware → Output: 1 unit of Ore + 1 unit of Mineral.
  • Space Conversion: 0.006 liters of Hardware → 0.01 liters of Ore + 0.04 liters of Minerals.

The corresponding ratios are:

  • 0.006 liters of Hardware : 0.01 liters of Ore : 0.04 liters of Minerals.

Normalized:

  • 0.107 liters Hardware : 0.179 liters Ore : 0.714 liters Minerals.

Ratio for Mining

Here, the output is 8.34 times larger than the input. To accommodate this, we divide the available space by 8.34:

Adjusted Available Space

Dropping the output and focusing on the input materials, we get:

Input Ratio for Mining

In this case, only Hardware is needed, and the newly calculated "available space" will be filled with it until production requirements are fully satisfied.

Example 2: Chemicals

Let's consider another example with Chemicals. To produce 1 unit of chemicals:

  • Input: 1 unit of Plants + 0.5 units of Water → Output: 1 unit of Chemicals.
  • Space Conversion: 0.05 liters of Plant + 0.025 liters of Water → 0.05 liters of Chemical.

Normalized ratios:

  • 0.4 liters Plant : 0.2 liters Water : 0.4 liters Chemical.

Ratio for Chemicals

Since the sum of the input material volumes is larger than the output volume, we don't need to reserve extra space for the production. We drop the output and normalize the input ratio again:

  • 0.66 liters Plant : 0.33 liters Water.

Input Ratio for Chemicals

Adjusting for existing Materials

Finally, we compare the existing ratios to the required ones, and sorting the material by this fraction. For example, if the available space currently looks like this:

Available Space for Chemicals
We get the following ratios:

  • Existing are 0.2 Plants : 0.4 Water
  • Required were 0.66 Plants : 0.33 Water
  • Plants: 0.2 / 0.66 = 0.30
  • Water: 0.4 / 0.33 = 1.21

Thus treat Water, with the greater existing:required-ratio, first, then Plants.

We find that Water is not needed in large quantities and is even too high (fraction > 1). Therefore, we remove its share from the available space, adjust the ratios, and normalize again. The remaining space should then be filled with Plants, but not excessively—production capacity must be taken into account to avoid overbuying resources.

Conclusion

This algorithm is more advanced than the previous one and handles edge cases more effectively. When dealing with multiple products or output materials and when production limits are involved, it is supported by the function getProductionCapacity(), which calculates both the average product size and total production capacity. This separate function ensures that the algorithm can manage these scenarios efficiently.

One significant advantage of this new approach is that it activates immediately, without requiring a "warm-up" cycle as the old algorithm did. Notably, the new SmartSupply Algorithm and the production capacity calculation are two separate improvements and could be split into different parts or pull requests.

Testing

Test-Driven Development (TDD)

To ensure the reliability of the new algorithm, I have added a suite of Jest tests. Some of these tests are designed to fail with the current version of SmartSupply, highlighting areas where the new algorithm improves functionality.

As I am relatively new to Jest and unit testing in general, I welcome any feedback or suggestions for improving these tests.

Shortcomings / Room for Further Improvement

  • If production factors change between the PURCHASE and PRODUCTION phases, the materials bought may not precisely match those consumed.
  • Depending on the sequence of import and export operations for a given office, there could be additional space in the warehouse that could be used more efficiently.

Related Issues Not Addressed by This PR

  • Production limits (set by the player) not functioning correctly.
  • Inaccurate maximum production calculation when the warehouse is nearly full, leading to underproduction in cases where space is cleared up during production. (This PR introduces improved calculation methods that could be refactored later to enhance both SmartSupply and Production logic.)
  • Import, Export, and Sale stages are treated separately, even though they logically belong together, which exacerbates warehouse congestion.

While these issues are not directly related to SmartSupply, I’m open to discussing them in the comment section. This could potentially lead to more PRs and further improvements.

Discussion and Open Questions

Discussion

1. Correct Implementation of Production Limits

The current implementation of production limits, those set by players, has some quirks that need addressing. Although this is more of a bug, it seems that the developers have not reached a consensus on how to resolve it. SmartSupply needs to be synchronized with any future changes to this quirky implementation of limits to ensure consistency and prevent issues such as overproduction or underutilization of warehouse space. Input on how to approach this issue is appreciated.

2. Placement of Functions and Logic / Codestyle

I’m currently unsure where to place the new functions introduced in this PR. They logically belong to the Division.js module, but I’ve separated them into their own file because they seem to add new functionality that isn’t part of the core game. Should these functions remain in their own file, or should they be integrated into the existing module? I’m open to suggestions on the most logical and maintainable structure.

3. Concept of Multiple Market Cycles per Processing Step

While reviewing the code, I came across the concept of multiple market cycles per processing step. However, I’m unsure of its intended purpose or how it is currently used, if at all. Clarification on this concept’s role and any potential applications would be helpful. Understanding its function could lead to better integration or improvements within the SmartSupply system.

4. Optimizing Production Throughput with Geometric Series

There is potential to optimize production throughput by using a geometric series to manage space freed up during the "PRODUCTION" stage. This approach could maximize throughput, but careful consideration is needed to ensure that a full warehouse after production does not hinder imports. One idea is to allow players to set a production space limit (e.g., Production Space = CAPACITY - IMPORTS) to balance production and imports, or automatically limit production to avoid rejecting any planned imports. The calculation logic from smartSupply.ts/getProductionCapacity could be reused here, but community feedback is essential to refine and develop this concept further.

Additionally, it’s important to note that the current version of SmartSupply provided here depends on the production algorithm being updated alongside it. Depending on the outcome of this discussion, the SmartSupply algorithm may need slight adjustments to stay synchronized with the production logic.

5. Feedback, Suggestions, and Criticisms

I encourage everyone to provide feedback, suggestions, and criticisms on this PR. Are there any potential oversights? Is the approach taken here in line with what the community needs? Are there additional features or adjustments that could enhance the implementation? All comments are welcome to ensure that this PR meets expectations and improves overall gameplay.

Especially since I’m new to this game, repository, and JavaScript, I’m really thankful for any guiding comments and tips on how to write better code and PR's. This is also my first "real" PR tackling a more advanced feature. I also want to apologize for any awkward language choices, as English is my second language. I hope everything is clear, but if not, please don’t hesitate to ask.

6. Further Testing and Implementation

While I believe the general concept is sound and all current "theoretical" jest tests have passed, I’m not yet fully convinced that the code is entirely bug-free or will work flawlessly in its current state. I would like to conduct more extensive testing, particularly with a more complex scenario involving multiple divisions exporting to each other and operating at or near full warehouse capacity. Writing these additional tests and potentially running some "real-world" tests within a live corporation environment would be beneficial, but it will take a few more days to complete.

At this stage, it should also be clear whether this change is actually welcome or should be rejected, and I appreciate your feedback. As with any first version, bugs are likely to be present. While I encourage you to review these changes, it might be worth discussing how long this should remain in testing, and possibly consider skipping a version number or two before full implementation to be on the safe side.

@d0sboots
Copy link
Collaborator

I'm all for more unit-tests! Woo!

At the time of writing this comment, there was no prod code yet, so hard to evaluate the goals of a new algorithm. But I guess that's why it's a draft. XD

@catloversg because they're the big brain on corps, and have very good ideas about when/how to make changes there.

@cmfrydos cmfrydos marked this pull request as ready for review August 26, 2024 22:52
@cmfrydos
Copy link
Contributor Author

I'm all for more unit-tests! Woo!

At the time of writing this comment, there was no prod code yet, so hard to evaluate the goals of a new algorithm. But I guess that's why it's a draft. XD

Yup, I was using this document as my working version, so it might not be very professional. To be honest, I'm not entirely sure how to properly use the draft feature.

While testing, I was utterly amazed at how easy it was to write scenarios as unit tests. They just magically work without requiring 'real' interaction with the game. 👍 This really speaks to the strength of the game's architecture. However, the tests do rely on 'internal' game objects, which might cause them to fail if the internal structure changes. I'm not sure how to make them more reliable, but I hope it's clear that they are meant to be discarded when they can no longer accurately measure what they're supposed to. That said, they were a huge help during development. It's astonishing how quickly things can break unexpectedly, and it's really nice to get immediate feedback. I definitely need to do this more in my own projects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants