diff options
Diffstat (limited to 'src/openvic-simulation/dataloader')
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.cpp | 103 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.hpp | 25 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/NodeTools.cpp | 31 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/NodeTools.hpp | 42 |
4 files changed, 144 insertions, 57 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 82957fc..a30983b 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -49,18 +49,14 @@ fs::path Dataloader::lookup_file(fs::path const& path) const { return {}; } -const fs::path Dataloader::TXT = ".txt"; - static bool contains_file_with_name(Dataloader::path_vector_t const& paths, fs::path const& name) { - for (fs::path const& path : paths) { if (path.filename() == name) return true; } return false; } -Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, fs::path const* extension) const { - +Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, fs::path const& extension) const { path_vector_t ret; for (fs::path const& root : roots) { const fs::path composed = root / path; @@ -68,7 +64,7 @@ Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, for (fs::directory_entry const& entry : fs::directory_iterator { composed, ec }) { if (entry.is_regular_file()) { const fs::path file = entry; - if (extension == nullptr || file.extension() == *extension) { + if (extension.empty() || file.extension() == extension) { if (!contains_file_with_name(ret, file.filename())) { ret.push_back(file); } @@ -79,8 +75,7 @@ Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, return ret; } -bool Dataloader::apply_to_files_in_dir(fs::path const& path, std::function<bool(fs::path const&)> callback, fs::path const* extension) const { - +bool Dataloader::apply_to_files_in_dir(fs::path const& path, fs::path const& extension, callback_t<fs::path const&> callback) const { bool ret = true; for (fs::path const& file : lookup_files_in_dir(path, extension)) { ret &= callback(file); @@ -88,11 +83,11 @@ bool Dataloader::apply_to_files_in_dir(fs::path const& path, std::function<bool( return ret; } -template<std::derived_from<detail::BasicParser> Parser, bool (Parser::*parse_func)()> +template<std::derived_from<detail::BasicParser> Parser, bool (*parse_func)(Parser&)> static Parser _run_ovdl_parser(fs::path const& path) { Parser parser; std::string buffer; - auto error_log_stream = ovdl::detail::CallbackStream { + auto error_log_stream = detail::CallbackStream { [](void const* s, std::streamsize n, void* user_data) -> std::streamsize { if (s != nullptr && n > 0 && user_data != nullptr) { static_cast<std::string*>(user_data)->append(static_cast<char const*>(s), n); @@ -107,18 +102,18 @@ static Parser _run_ovdl_parser(fs::path const& path) { parser.set_error_log_to(error_log_stream); parser.load_from_file(path); if (!buffer.empty()) { - Logger::error("Parser load errors:\n\n", buffer, "\n"); + Logger::error("Parser load errors for ", path, ":\n\n", buffer, "\n"); buffer.clear(); } if (parser.has_fatal_error() || parser.has_error()) { Logger::error("Parser errors while loading ", path); return parser; } - if (!(parser.*parse_func)()) { - Logger::error("Parse function returned false!"); + if (!parse_func(parser)) { + Logger::error("Parse function returned false for ", path, "!"); } if (!buffer.empty()) { - Logger::error("Parser parse errors:\n\n", buffer, "\n"); + Logger::error("Parser parse errors for ", path, ":\n\n", buffer, "\n"); buffer.clear(); } if (parser.has_fatal_error() || parser.has_error()) { @@ -127,16 +122,30 @@ static Parser _run_ovdl_parser(fs::path const& path) { return parser; } +static bool _v2script_parse(v2script::Parser& parser) { + return parser.simple_parse(); +} + static v2script::Parser _parse_defines(fs::path const& path) { - return _run_ovdl_parser<v2script::Parser, &v2script::Parser::simple_parse>(path); + return _run_ovdl_parser<v2script::Parser, &_v2script_parse>(path); +} + +static bool _csv_parse(csv::Windows1252Parser& parser) { + return parser.parse_csv(); } static csv::Windows1252Parser _parse_csv(fs::path const& path) { - return _run_ovdl_parser<csv::Windows1252Parser, &csv::Windows1252Parser::parse_csv>(path); + return _run_ovdl_parser<csv::Windows1252Parser, &_csv_parse>(path); +} + +static callback_t<fs::path const&> _parse_defines_callback(node_callback_t callback) { + return [callback](fs::path const& path) -> bool { + return callback(_parse_defines(path).get_file_node()); + }; } bool Dataloader::_load_pop_types(PopManager& pop_manager, fs::path const& pop_type_directory) const { - const bool ret = apply_to_files_in_dir(pop_type_directory, + const bool ret = apply_to_files_in_dir(pop_type_directory, ".txt", [&pop_manager](fs::path const& file) -> bool { return pop_manager.load_pop_type_file(file.stem().string(), _parse_defines(file).get_file_node()); } @@ -148,7 +157,9 @@ bool Dataloader::_load_pop_types(PopManager& pop_manager, fs::path const& pop_ty return ret; } -bool Dataloader::_load_map_dir(Map& map, fs::path const& map_directory) const { +bool Dataloader::_load_map_dir(GameManager& game_manager, fs::path const& map_directory) const { + Map& map = game_manager.map; + static const fs::path defaults_filename = "default.map"; static const std::string default_definitions = "definition.csv"; static const std::string default_provinces = "provinces.bmp"; @@ -221,6 +232,16 @@ bool Dataloader::_load_map_dir(Map& map, fs::path const& map_directory) const { ret = false; } + if (!map.load_province_positions(game_manager.building_manager, _parse_defines(lookup_file(map_directory / positions)).get_file_node())) { + Logger::error("Failed to load province positions file!"); + ret = false; + } + + if (!map.load_region_file(_parse_defines(lookup_file(map_directory / region)).get_file_node())) { + Logger::error("Failed to load region file!"); + ret = false; + } + if (!map.set_water_province_list(water_province_identifiers)) { Logger::error("Failed to set water provinces!"); ret = false; @@ -231,7 +252,7 @@ bool Dataloader::_load_map_dir(Map& map, fs::path const& map_directory) const { } bool Dataloader::load_defines(GameManager& game_manager) const { - static const fs::path good_file = "common/goods.txt"; + static const fs::path goods_file = "common/goods.txt"; static const fs::path pop_type_directory = "poptypes"; static const fs::path graphical_culture_type_file = "common/graphicalculturetype.txt"; static const fs::path culture_file = "common/cultures.txt"; @@ -240,7 +261,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const { bool ret = true; - if (!game_manager.good_manager.load_good_file(_parse_defines(lookup_file(good_file)).get_file_node())) { + if (!game_manager.good_manager.load_goods_file(_parse_defines(lookup_file(goods_file)).get_file_node())) { Logger::error("Failed to load goods!"); ret = false; } @@ -260,7 +281,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load religions!"); ret = false; } - if (!_load_map_dir(game_manager.map, map_directory)) { + if (!_load_map_dir(game_manager, map_directory)) { Logger::error("Failed to load map!"); ret = false; } @@ -269,18 +290,38 @@ bool Dataloader::load_defines(GameManager& game_manager) const { } bool Dataloader::load_pop_history(GameManager& game_manager, fs::path const& path) const { - return apply_to_files_in_dir(path, + return apply_to_files_in_dir(path, ".txt", [&game_manager](fs::path const& file) -> bool { - return expect_dictionary( - [&game_manager](std::string_view province_key, ast::NodeCPtr province_node) -> bool { - Province* province = game_manager.map.get_province_by_identifier(province_key); - if (province == nullptr) { - Logger::error("Invalid province id: ", province_key); - return false; - } - return province->load_pop_list(game_manager.pop_manager, province_node); + return _parse_defines_callback(game_manager.map.expect_province_dictionary( + [&game_manager](Province& province, ast::NodeCPtr value) -> bool { + return province.load_pop_list(game_manager.pop_manager, value); } - )(_parse_defines(file).get_file_node()); + ))(file); + } + ); +} + +static bool _load_localisation_file(Dataloader::localisation_callback_t callback, std::vector<csv::LineObject> const& lines) { + bool ret = true; + for (csv::LineObject const& line : lines) { + const std::string_view key = line.get_value_for(0); + if (!key.empty()) { + const size_t max_entry = std::min<size_t>(line.value_count() - 1, Dataloader::_LocaleCount); + for (size_t i = 0; i < max_entry; ++i) { + const std::string_view entry = line.get_value_for(i + 1); + if (!entry.empty()) { + ret &= callback(key, static_cast<Dataloader::locale_t>(i), entry); + } + } + } + } + return ret; +} + +bool Dataloader::load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir) { + return apply_to_files_in_dir(localisation_dir, ".csv", + [callback](fs::path path) -> bool { + return _load_localisation_file(callback, _parse_csv(path).get_lines()); } ); } diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp index efada89..6741361 100644 --- a/src/openvic-simulation/dataloader/Dataloader.hpp +++ b/src/openvic-simulation/dataloader/Dataloader.hpp @@ -4,6 +4,8 @@ #include <functional> #include <vector> +#include "openvic-simulation/dataloader/NodeTools.hpp" + namespace OpenVic { namespace fs = std::filesystem; @@ -19,7 +21,7 @@ namespace OpenVic { path_vector_t roots; bool _load_pop_types(PopManager& pop_manager, fs::path const& pop_type_directory) const; - bool _load_map_dir(Map& map, fs::path const& map_directory) const; + bool _load_map_dir(GameManager& game_manager, fs::path const& map_directory) const; public: Dataloader() = default; @@ -27,13 +29,26 @@ namespace OpenVic { /* In reverse-load order, so base defines first and final loaded mod last */ bool set_roots(path_vector_t new_roots); + /* REQUIREMENTS: + * DAT-24 + */ fs::path lookup_file(fs::path const& path) const; - static const fs::path TXT; - path_vector_t lookup_files_in_dir(fs::path const& path, fs::path const* extension = &TXT) const; - bool apply_to_files_in_dir(fs::path const& path, std::function<bool(fs::path const&)> callback, - fs::path const* extension = &TXT) const; + path_vector_t lookup_files_in_dir(fs::path const& path, fs::path const& extension) const; + bool apply_to_files_in_dir(fs::path const& path, fs::path const& extension, + NodeTools::callback_t<fs::path const&> callback) const; bool load_defines(GameManager& game_manager) const; bool load_pop_history(GameManager& game_manager, fs::path const& path) const; + + enum locale_t : size_t { + English, French, German, Polish, Spanish, Italian, Swedish, Czech, Hungarian, Dutch, Portugese, Russian, Finnish, _LocaleCount + }; + static constexpr char const* locale_names[_LocaleCount] = { + "en_GB", "fr_FR", "de_DE", "pl_PL", "es_ES", "it_IT", "sv_SE", "cs_CZ", "hu_HU", "nl_NL", "pt_PT", "ru_RU", "fi_FI" + }; + + /* Args: key, locale, localisation */ + using localisation_callback_t = NodeTools::callback_t<std::string_view, locale_t, std::string_view>; + bool load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir = "localisation"); }; } diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp index 63a97ad..7dd6e16 100644 --- a/src/openvic-simulation/dataloader/NodeTools.cpp +++ b/src/openvic-simulation/dataloader/NodeTools.cpp @@ -19,20 +19,20 @@ static node_callback_t _expect_type(callback_t<T const&> callback) { }; } -template<typename T = ast::AbstractStringNode> +template<typename T> requires(std::derived_from<T, ast::AbstractStringNode>) -static callback_t<T const&> abstract_string_node_callback(callback_t<std::string_view> callback) { +static callback_t<T const&> _abstract_string_node_callback(callback_t<std::string_view> callback) { return [callback](T const& node) -> bool { return callback(node._name); }; } node_callback_t NodeTools::expect_identifier(callback_t<std::string_view> callback) { - return _expect_type<ast::IdentifierNode>(abstract_string_node_callback<ast::IdentifierNode>(callback)); + return _expect_type<ast::IdentifierNode>(_abstract_string_node_callback<ast::IdentifierNode>(callback)); } node_callback_t NodeTools::expect_string(callback_t<std::string_view> callback) { - return _expect_type<ast::StringNode>(abstract_string_node_callback<ast::StringNode>(callback)); + return _expect_type<ast::StringNode>(_abstract_string_node_callback<ast::StringNode>(callback)); } node_callback_t NodeTools::expect_identifier_or_string(callback_t<std::string_view> callback) { @@ -43,7 +43,7 @@ node_callback_t NodeTools::expect_identifier_or_string(callback_t<std::string_vi cast_node = node->cast_to<ast::StringNode>(); } if (cast_node != nullptr) { - return abstract_string_node_callback(callback)(*cast_node); + return _abstract_string_node_callback<ast::AbstractStringNode>(callback)(*cast_node); } Logger::error("Invalid node type ", node->get_type(), " when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static()); } else { @@ -148,6 +148,27 @@ node_callback_t NodeTools::expect_date(callback_t<Date> callback) { ); } +template<typename T, node_callback_t (*expect_func)(callback_t<T>)> +node_callback_t _expect_vec2(callback_t<vec2_t<T>> callback) { + return [callback](ast::NodeCPtr node) -> bool { + vec2_t<T> vec; + bool ret = expect_dictionary_keys( + "x", ONE_EXACTLY, expect_func(assign_variable_callback(vec.x)), + "y", ONE_EXACTLY, expect_func(assign_variable_callback(vec.y)) + )(node); + ret &= callback(vec); + return ret; + }; +} + +node_callback_t NodeTools::expect_ivec2(callback_t<ivec2_t> callback) { + return _expect_vec2<int64_t, expect_int>(callback); +} + +node_callback_t NodeTools::expect_fvec2(callback_t<fvec2_t> callback) { + return _expect_vec2<fixed_point_t, expect_fixed_point>(callback); +} + node_callback_t NodeTools::expect_assign(key_value_callback_t callback) { return _expect_type<ast::AssignNode>( [callback](ast::AssignNode const& assign_node) -> bool { diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index a68e922..51bbfa9 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -6,7 +6,7 @@ #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/Date.hpp" -#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/Vector.hpp" namespace OpenVic { namespace ast = ovdl::v2script::ast; @@ -20,6 +20,7 @@ namespace OpenVic { constexpr bool success_callback(ast::NodeCPtr) { return true; } using key_value_callback_t = callback_t<std::string_view, ast::NodeCPtr>; + constexpr bool key_value_success_callback(std::string_view, ast::NodeCPtr) { return true; } node_callback_t expect_identifier(callback_t<std::string_view> callback); node_callback_t expect_string(callback_t<std::string_view> callback); @@ -30,6 +31,8 @@ namespace OpenVic { node_callback_t expect_fixed_point(callback_t<fixed_point_t> callback); node_callback_t expect_colour(callback_t<colour_t> callback); node_callback_t expect_date(callback_t<Date> callback); + node_callback_t expect_ivec2(callback_t<ivec2_t> callback); + node_callback_t expect_fvec2(callback_t<fvec2_t> callback); node_callback_t expect_assign(key_value_callback_t callback); using length_callback_t = std::function<size_t(size_t)>; @@ -133,31 +136,38 @@ namespace OpenVic { }; } - template<typename T> - requires(std::integral<T>) - callback_t<uint64_t> assign_variable_callback_uint(const std::string_view name, T& var) { - return [&var, name](uint64_t val) -> bool { - if (val <= std::numeric_limits<T>::max()) { + template<typename I, typename T> + requires(std::integral<I>, std::integral<T>) + callback_t<I> _assign_variable_callback_int(const std::string_view name, T& var) { + return [&var, name](I val) -> bool { + if (std::numeric_limits<T>::lowest() <= val && val <= std::numeric_limits<T>::max()) { var = val; return true; } - Logger::error("Invalid ", name, ": ", val, " (valid range: [0, ", static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); + Logger::error("Invalid ", name, ": ", val, " (valid range: [", + static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ", + static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); return false; }; } template<typename T> requires(std::integral<T>) + callback_t<uint64_t> assign_variable_callback_uint(const std::string_view name, T& var) { + return _assign_variable_callback_int<uint64_t>(name, var); + } + + template<typename T> + requires(std::integral<T>) callback_t<int64_t> assign_variable_callback_int(const std::string_view name, T& var) { - return [&var, name](int64_t val) -> bool { - if (std::numeric_limits<T>::lowest() <= val && val <= std::numeric_limits<T>::max()) { - var = val; - return true; - } - Logger::error("Invalid ", name, ": ", val, " (valid range: [", - static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ", - static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); - return false; + return _assign_variable_callback_int<int64_t>(name, var); + } + + template<typename T> + callback_t<T const&> assign_variable_callback_pointer(T const*& var) { + return [&var](T const& val) -> bool { + var = &val; + return true; }; } } |