aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/Modifier.hpp
blob: bfd9ca7ed9153c62eca8cc90b3d1f5fbe60994c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#pragma once

#include "openvic-simulation/types/IdentifierRegistry.hpp"

namespace OpenVic {
   struct ModifierManager;

   struct ModifierEffect : HasIdentifier {
      friend struct ModifierManager;

   private:
      /* If true, positive values will be green and negative values will be red.
       * If false, the colours will be switced.
       */
      const bool positive_good;

      // TODO - format/precision, e.g. 80% vs 0.8 vs 0.800, 2 vs 2.0 vs 200%

      ModifierEffect(const std::string_view new_identifier, bool new_positive_good);

   public:
      ModifierEffect(ModifierEffect&&) = default;

      bool get_positive_good() const;
   };

   struct ModifierValue {
      friend struct ModifierManager;

      using effect_map_t = std::map<ModifierEffect const*, fixed_point_t>;
   private:
      effect_map_t values;

   public:
      ModifierValue();
      ModifierValue(effect_map_t&& new_values);
      ModifierValue(ModifierValue const&);
      ModifierValue(ModifierValue&&);

      ModifierValue& operator=(ModifierValue const&);
      ModifierValue& operator=(ModifierValue&&);

      /* Removes effect entries with a value of zero. */
      void trim();
      size_t get_effect_count() const;

      fixed_point_t get_effect(ModifierEffect const* effect, bool* successful = nullptr);
      bool has_effect(ModifierEffect const* effect) const;

      ModifierValue& operator+=(ModifierValue const& right);
      ModifierValue operator+(ModifierValue const& right) const;
      ModifierValue operator-() const;
      ModifierValue& operator-=(ModifierValue const& right);
      ModifierValue operator-(ModifierValue const& right) const;

      friend std::ostream& operator<<(std::ostream& stream, ModifierValue const& value);
   };

   struct Modifier : HasIdentifier, ModifierValue {
      friend struct ModifierManager;

      using icon_t = uint8_t;

   private:
      /* A modifier can have no icon (zero). */
      const icon_t icon;

      Modifier(const std::string_view new_identifier, ModifierValue&& new_values, icon_t new_icon);

   public:
      Modifier(Modifier&&) = default;

      icon_t get_icon() const;
   };

   struct ModifierInstance {

   private:
      Modifier const& modifier;
      Date expiry_date;

      ModifierInstance(Modifier const& modifier, Date expiry_date);

   public:
      Modifier const& get_modifier() const;
      Date const& get_expiry_date() const;
   };

   struct ModifierManager {

   private:
      IdentifierRegistry<ModifierEffect> modifier_effects;
      IdentifierRegistry<Modifier> modifiers;

      NodeTools::node_callback_t _expect_modifier_value_and_keys(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_map_t&& key_map) const;

      template<typename... Args>
      NodeTools::node_callback_t _expect_modifier_value_and_keys(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_map_t&& key_map,
         const std::string_view key, NodeTools::dictionary_entry_t::expected_count_t expected_count, NodeTools::node_callback_t callback,
         Args... args) const {
         NodeTools::add_key_map_entry(key_map, key, expected_count, callback);
         return _expect_modifier_value_and_keys(modifier_callback, std::move(key_map), args...);
      }

   public:
      ModifierManager();

      bool add_modifier_effect(const std::string_view identifier, bool province_good);
      IDENTIFIER_REGISTRY_ACCESSORS(ModifierEffect, modifier_effect)

      bool add_modifier(const std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon);
      IDENTIFIER_REGISTRY_ACCESSORS(Modifier, modifier)

      bool setup_modifier_effects();

      NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback) const;

      template<typename... Args>
      NodeTools::node_callback_t expect_modifier_value_and_keys(NodeTools::callback_t<ModifierValue&&> modifier_callback, Args... args) const {
         return _expect_modifier_value_and_keys(modifier_callback, {}, args...);
      }
   };
}