aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/scripts/ConditionalWeight.cpp
blob: 29dc93b3cb484c2f84774930022e828d00f086d2 (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
#include "ConditionalWeight.hpp"

using namespace OpenVic;
using namespace OpenVic::NodeTools;

template<typename T>
static NodeCallback auto expect_modifier(std::vector<T>& items) {
   return [&items](ast::NodeCPtr node) -> bool {
      fixed_point_t weight = 0;
      bool successful = false;
      bool ret = expect_key("factor", expect_fixed_point(assign_variable_callback(weight)), &successful)(node);
      if (!successful) {
         Logger::info("ConditionalWeight modifier missing factor key!");
         return false;
      }
      ConditionScript condition;
      ret &= condition.expect_script()(node);
      items.emplace_back(std::make_pair(weight, std::move(condition)));
      return ret;
   };
}

node_callback_t ConditionalWeight::expect_conditional_weight(base_key_t base_key) {
   return expect_dictionary_keys(
      // TODO - add days and years as options with a shared expected count of ONE_EXACTLY
      base_key_to_string(base_key), ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base)),
      "modifier", ZERO_OR_MORE, expect_modifier(condition_weight_items),
      "group", ZERO_OR_MORE, [this](ast::NodeCPtr node) -> bool {
         condition_weight_group_t items;
         const bool ret = expect_dictionary_keys(
            "modifier", ONE_OR_MORE, expect_modifier(items)
         )(node);
         if (!items.empty()) {
            condition_weight_items.emplace_back(std::move(items));
            return ret;
         }
         Logger::error("ConditionalWeight group must have at least one modifier!");
         return false;
      }
   );
}

struct ConditionalWeight::parse_scripts_visitor_t {
   GameManager const& game_manager;

   bool operator()(condition_weight_t& condition_weight) const {
      return condition_weight.second.parse_script(false, game_manager);
   }
   bool operator()(condition_weight_item_t& item) const {
      return std::visit(*this, item);
   }
   template<typename T>
   bool operator()(std::vector<T>& items) const {
      bool ret = true;
      for (T& item : items) {
         ret &= (*this)(item);
      }
      return ret;
   }
};

bool ConditionalWeight::parse_scripts(GameManager const& game_manager) {
   return parse_scripts_visitor_t { game_manager }(condition_weight_items);
}