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
125
126
127
128
|
#include <cstring>
#include <openvic-simulation/dataloader/Dataloader.hpp>
#include <openvic-simulation/GameManager.hpp>
#include <openvic-simulation/testing/Testing.hpp>
#include <openvic-simulation/utility/Logger.hpp>
using namespace OpenVic;
static void print_help(std::ostream& stream, char const* program_name) {
stream
<< "Usage: " << program_name << " [-h] [-t] [-b <path>] [path]+\n"
<< " -h : Print this help message and exit the program.\n"
<< " -t : Run tests after loading defines.\n"
<< " -b : Use the following path as the base directory (instead of searching for one).\n"
<< " -s : Use the following path as a hint to search for a base directory.\n"
<< "Any following paths are read as mod directories, with priority starting at one above the base directory.\n"
<< "(Paths with spaces need to be enclosed in \"quotes\").\n";
}
static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests) {
bool ret = true;
GameManager game_manager { []() {
Logger::info("State updated");
}, nullptr };
ret &= game_manager.load_definitions(
roots,
[](std::string_view key, Dataloader::locale_t locale, std::string_view localisation) -> bool {
return true;
}
);
if (run_tests) {
Testing testing { game_manager.get_definition_manager() };
std::cout << std::endl << "Testing Loaded" << std::endl << std::endl;
testing.execute_all_scripts();
testing.report_results();
std::cout << "Testing Executed" << std::endl << std::endl;
}
return ret;
}
/*
$ program [-h] [-t] [-b] [path]+
*/
int main(int argc, char const* argv[]) {
Logger::set_logger_funcs();
char const* program_name = StringUtils::get_filename(argc > 0 ? argv[0] : nullptr, "<program>");
fs::path root;
bool run_tests = false;
int argn = 0;
/* Reads the next argument and converts it to a path via path_transform. If reading or converting fails, an error
* message and the help text are displayed, along with returning false to signify the program should exit.
*/
const auto _read = [&root, &argn, argc, argv, program_name](
std::string_view command, std::string_view path_use, auto path_transform) -> bool {
if (root.empty()) {
if (++argn < argc) {
char const* path = argv[argn];
root = path_transform(path);
if (!root.empty()) {
return true;
} else {
std::cerr << "Empty path after giving \"" << path << "\" to " << path_use
<< " command line argument \"" << command << "\"." << std::endl;
}
} else {
std::cerr << "Missing path after " << path_use << " command line argument \"" << command << "\"." << std::endl;
}
} else {
std::cerr << "Duplicate " << path_use << " command line argument \"-b\"." << std::endl;
}
print_help(std::cerr, program_name);
return false;
};
while (++argn < argc) {
char const* arg = argv[argn];
if (strcmp(arg, "-h") == 0) {
print_help(std::cout, program_name);
return 0;
} else if (strcmp(arg, "-t") == 0) {
run_tests = true;
} else if (strcmp(arg, "-b") == 0) {
if (!_read("-b", "base directory", std::identity {})) {
return -1;
}
} else if (strcmp(arg, "-s") == 0) {
if (!_read("-s", "search hint", Dataloader::search_for_game_path)) {
return -1;
}
} else {
break;
}
}
if (root.empty()) {
root = Dataloader::search_for_game_path();
if (root.empty()) {
std::cerr << "Search for base directory path failed!" << std::endl;
print_help(std::cerr, program_name);
return -1;
}
}
Dataloader::path_vector_t roots { root };
while (argn < argc) {
static const fs::path mod_directory = "mod";
roots.emplace_back(root / mod_directory / argv[argn++]);
}
std::cout << "!!! HEADLESS SIMULATION START !!!" << std::endl;
const bool ret = run_headless(roots, run_tests);
std::cout << "!!! HEADLESS SIMULATION END !!!" << std::endl;
std::cout << "\nLoad returned: " << (ret ? "SUCCESS" : "FAILURE") << std::endl;
std::cout << "\nLogger Summary: Info = " << Logger::get_info_count() << ", Warning = " << Logger::get_warning_count()
<< ", Error = " << Logger::get_error_count() << std::endl;
return ret ? 0 : -1;
}
|