Skip to content

Commit

Permalink
Market price graphs (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasdoehne authored May 7, 2022
1 parent dc8b5d8 commit 5d9f435
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 19 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ For balance and immersion, only some information about other empires is shown by
- `Store data of all countries`: This will read detailed budgets and pop statistics for non-player countries. It will increase the processing time and database file size, but will allow you to inspect other countries by selecting them from the dropdown menu at the top. (Basic economy information is always read, this setting only controls the very detailed budgets)
- `Filter history ledger by event type`: By default, the event ledger does not show everything on the main page. For example, more detailed events like leader level-ups are only shown on that specific leader's ledger entry. This setting allows you to change this behavior and see all events on the main page.

## Market Price Graphs

The dashboard includes graphs of market prices for each resource in the game. To get the correct values, you will need to manually configure some things in the file `config.yml`, as these settings are not available in the built-in settings page.

If `config.yml` does not exist, go to the settings page linked at the top (or `localhost:28053/settings/`) and hit "Apply Settings". This will create the file with all of your current settings.

These configurations are applied only when preparing the graph, so you can adjust them at any time in the configuration without reprocessing any data.

### Market fees

Currently, there is no easy way to get the market fee information from the save files. To still get the correct numbers in the graph, you can add the fee manually in the configuration by creating additional entries in the `market_fee` section. By default, a constant fee of 30% is assumed.

For example, to configure a game where the market_fee changed to 20% in 2240 and 5% in 2300, you could change the market_fee section like this:
```
market_fee:
- {date: 2200.01.01, fee: 0.3}
- {date: 2240.01.01, fee: 0.2}
- {date: 2300.01.01, fee: 0.05}
```

### Resources

The default resource configuration should be correct for the current vanilla Stellaris game.

When using mods that change resources in the game (or if Stellaris is updated in the future), you might need to manually adjust the resource configuration in `config.yml` to have the data collected for the additional resources.

These values must be configured in the correct order, for vanilla Stellaris, this is the same order in which they are defined in the game file `common/strategic_resources/00_strategic_resources.txt`.

## How to improve performance

If you find that the dashboard is too slow to browse, you can try some of these things:
Expand Down
2 changes: 1 addition & 1 deletion configure_layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Disabling some graphs means that the dashboard has to do less work, making it faster to browse. Also, you can remove any graphs that you don't care about and arrange them into tabs in whatever way you prefer.

The configuration is written in YAML format which is quite easy to understand. You can chose almost any name for the tabs, except for "Galaxy Map", which is reserved.
The configuration is written in YAML format which is quite easy to understand. You can chose almost any name for the tabs, except for "Galaxy Map" and "Markets", which are reserved for special tabs and will be ignored.

For example this would be a valid configuration you can add to the config.yml:
```yaml
Expand Down
2 changes: 1 addition & 1 deletion mod/stellaris_dashboard/descriptor.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name="Stellaris Dashboard"
version="v2.0-alpha"
version="v3.0"
tags={
"Utilities"
"Gameplay"
Expand Down
67 changes: 58 additions & 9 deletions stellarisdashboard/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
import traceback
from collections import defaultdict
from typing import List, Dict
from typing import List, Dict, Optional, Any

import yaml

Expand All @@ -16,7 +16,7 @@
LOG_FORMAT = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

CONFIG = None
logger = None
logger: logging.Logger = None


def initialize_logger():
Expand Down Expand Up @@ -57,6 +57,8 @@ def _get_default_base_output_path():
return pathlib.Path.cwd() / "output"


GALAXY_MAP_TAB = "Galaxy Map"
MARKET_TAB = "Markets"
DEFAULT_TAB_LAYOUT = {
"Budget": [
"energy_budget",
Expand Down Expand Up @@ -130,8 +132,35 @@ def _get_default_base_output_path():
"victory_score_graph",
"victory_economy_score_graph",
],
MARKET_TAB: [], # filled dynamically based on resource config
}
GALAXY_MAP_TAB = "Galaxy Map"
DEFAULT_MARKET_RESOURCES = [
# all available resources, in the order in which they are defined in the game files
# common/strategic_resources/00_strategic_resources.txt
# Put None as price of non-tradeable resources (These must still be added because ordering matters)
{"name": "time", "base_price": None},
{"name": "energy", "base_price": None},
{"name": "minerals", "base_price": 1},
{"name": "food", "base_price": 1},
{"name": "physics_research", "base_price": None},
{"name": "society_research", "base_price": None},
{"name": "engineering_research", "base_price": None},
{"name": "influence", "base_price": None},
{"name": "unity", "base_price": None},
{"name": "consumer_goods", "base_price": 2},
{"name": "alloys", "base_price": 4},
{"name": "volatile_motes", "base_price": 10},
{"name": "exotic_gases", "base_price": 10},
{"name": "rare_crystals", "base_price": 10},
{"name": "sr_living_metal", "base_price": 20},
{"name": "sr_zro", "base_price": 20},
{"name": "sr_dark_matter", "base_price": 20},
{"name": "nanites", "base_price": None},
{"name": "minor_artifacts", "base_price": None},
{"name": "menace", "base_price": None},
]
DEFAULT_MARKET_FEE = [{"date": "2200.01.01", "fee": 0.3}]


DEFAULT_SETTINGS = dict(
save_file_path=_get_default_save_path(),
Expand All @@ -153,6 +182,8 @@ def _get_default_base_output_path():
plot_width=1150,
plot_height=640,
tab_layout=DEFAULT_TAB_LAYOUT,
market_resources=DEFAULT_MARKET_RESOURCES,
market_fee=DEFAULT_MARKET_FEE,
)


Expand Down Expand Up @@ -186,6 +217,8 @@ class Config:
debug_mode: bool = False

tab_layout: Dict[str, List[str]] = None
market_resources: List[Dict[str, Any]] = None
market_fee: List[Dict[str, float]] = None

PATH_KEYS = {
"base_output_path",
Expand Down Expand Up @@ -215,11 +248,21 @@ class Config:
"save_name_filter",
"log_level",
}
DICT_KEYS = {"tab_layout"}
ALL_KEYS = PATH_KEYS | BOOL_KEYS | INT_KEYS | FLOAT_KEYS | STR_KEYS | DICT_KEYS
DICT_KEYS = {
"tab_layout",
}
LIST_KEYS = {
"market_resources",
"market_fee",
}
ALL_KEYS = (
PATH_KEYS | BOOL_KEYS | INT_KEYS | FLOAT_KEYS | STR_KEYS | DICT_KEYS | LIST_KEYS
)

def apply_dict(self, settings_dict):
logger.info("Updating settings")
tab_layout = self._preprocess_tab_layout(settings_dict)
settings_dict["tab_layout"] = tab_layout
for key, val in settings_dict.items():
if key not in Config.ALL_KEYS:
logger.info(f"Ignoring unknown setting {key} with value {val}.")
Expand All @@ -231,8 +274,7 @@ def apply_dict(self, settings_dict):
val = self._process_path_keys(key, val)
if val is None:
continue
if key == "tab_layout":
val = self._process_tab_layout(val)

self.__setattr__(key, val)
if val != old_val:
logger.info(
Expand Down Expand Up @@ -263,7 +305,8 @@ def _process_path_keys(self, key, val):
return
return val

def _process_tab_layout(self, layout_dict):
def _preprocess_tab_layout(self, settings_dict):
layout_dict = settings_dict.get("tab_layout", DEFAULT_TAB_LAYOUT)
if not isinstance(layout_dict, dict):
logger.error(f"Invalid tab layout configuration: {layout_dict}")
logger.info(f"Falling back to default tab layout.")
Expand All @@ -272,7 +315,13 @@ def _process_tab_layout(self, layout_dict):
for tab, plot_list in layout_dict.items():
if tab == GALAXY_MAP_TAB:
logger.warning(f"Ignoring tab {tab}, it is reserved for the galaxy map")
pass
continue
if tab == MARKET_TAB:
logger.warning(
f"Ignoring values for tab {tab}, it is filled dynamically"
)
processed[tab] = []
continue
if not isinstance(plot_list, list):
logger.warning(f"Ignoring invalid graph list for tab {tab}")
pass
Expand Down
9 changes: 6 additions & 3 deletions stellarisdashboard/dashboard_app/graph_ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,12 @@ def update_content(

children = []
if tab_value in config.CONFIG.tab_layout:
plots = visualization_data.get_plot_specifications_for_tab_layout().get(
tab_value
)
if tab_value == config.MARKET_TAB:
plots = visualization_data.get_market_graphs(config.CONFIG.market_resources)
else:
plots = visualization_data.get_plot_specifications_for_tab_layout().get(
tab_value
)
plot_data = visualization_data.get_current_execution_plot_data(
game_id, country_perspective
)
Expand Down
2 changes: 1 addition & 1 deletion stellarisdashboard/dashboard_app/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

logger = logging.getLogger(__name__)

VERSION = "v2.1"
VERSION = "v3.0"


def parse_version(version: str):
Expand Down
Loading

0 comments on commit 5d9f435

Please sign in to comment.