yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
oracle_validation_view_model.cc
Go to the documentation of this file.
2
3#include <chrono>
4#include <ctime>
5
6#include "nlohmann/json.hpp"
7
9namespace {
10using json = nlohmann::json;
11} // namespace
12
13std::string CurrentTimestamp() {
14 const auto now = std::chrono::system_clock::now();
15 const auto t = std::chrono::system_clock::to_time_t(now);
16 char buf[32];
17 struct tm tm_utc {};
18#ifdef _WIN32
19 gmtime_s(&tm_utc, &t);
20#else
21 gmtime_r(&t, &tm_utc);
22#endif
23 std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &tm_utc);
24 return buf;
25}
26
27std::vector<std::string> BuildSmokeArgs(const SmokeOptions& opts) {
28 std::vector<std::string> args;
29 if (!opts.rom_path.empty()) {
30 args.push_back("--rom=" + opts.rom_path);
31 }
32 if (opts.strict_readiness) {
33 args.push_back("--strict-readiness");
34 }
35 if (opts.min_d6_track_rooms != 0) {
36 args.push_back("--min-d6-track-rooms=" +
37 std::to_string(opts.min_d6_track_rooms));
38 }
39 args.push_back("--format=json");
40 if (!opts.report_path.empty()) {
41 args.push_back("--report=" + opts.report_path);
42 }
43 return args;
44}
45
46std::vector<std::string> BuildPreflightArgs(const PreflightOptions& opts) {
47 std::vector<std::string> args;
48 if (!opts.rom_path.empty()) {
49 args.push_back("--rom=" + opts.rom_path);
50 }
51 if (!opts.required_collision_rooms.empty()) {
52 args.push_back("--required-collision-rooms=" +
54 }
55 if (opts.require_write_support) {
56 args.push_back("--require-write-support");
57 }
58 if (opts.skip_collision_maps) {
59 args.push_back("--skip-collision-maps");
60 }
61 args.push_back("--format=json");
62 if (!opts.report_path.empty()) {
63 args.push_back("--report=" + opts.report_path);
64 }
65 return args;
66}
67
68std::string BuildCliCommand(const std::string& command_name,
69 const std::vector<std::string>& args) {
70 std::string cmd = "z3ed " + command_name;
71 for (const auto& arg : args) {
72 cmd += " " + arg;
73 }
74 return cmd;
75}
76
77absl::StatusOr<SmokeResult> ParseSmokeCheckOutput(const std::string& json_str) {
78 const auto doc = json::parse(json_str, nullptr, false);
79 if (doc.is_discarded()) {
80 return absl::InvalidArgumentError(
81 "ParseSmokeCheckOutput: JSON parse failed");
82 }
83
84 if (!doc.contains("Oracle Smoke Check")) {
85 return absl::InvalidArgumentError(
86 "ParseSmokeCheckOutput: missing 'Oracle Smoke Check' key");
87 }
88 const auto& root = doc.at("Oracle Smoke Check");
89 const auto& checks = root.value("checks", json::object());
90
92 r.ok = root.value("ok", false);
93 r.status = root.value("status", "");
94 r.strict_readiness = root.value("strict_readiness", false);
95
96 const auto& d4 = checks.value("d4_zora_temple", json::object());
97 r.d4.structural_ok = d4.value("structural_ok", false);
98 r.d4.required_rooms_check = d4.value("required_rooms_check", "skipped");
99 if (d4.contains("required_rooms_ok")) {
100 r.d4.required_rooms_ok = d4.at("required_rooms_ok").get<bool>();
101 }
102
103 const auto& d6 = checks.value("d6_goron_mines", json::object());
104 r.d6.ok = d6.value("ok", false);
105 r.d6.track_rooms_found = d6.value("track_rooms_found", 0);
106 r.d6.min_track_rooms = d6.value("min_track_rooms", 0);
107 r.d6.meets_min_track_rooms = d6.value("meets_min_track_rooms", false);
108
109 const auto& d3 = checks.value("d3_kalyxo_castle", json::object());
110 r.d3.readiness_check = d3.value("readiness_check", "skipped");
111 if (d3.contains("ok")) {
112 r.d3.ok = d3.at("ok").get<bool>();
113 }
114
115 return r;
116}
117
118absl::StatusOr<PreflightResult> ParsePreflightOutput(
119 const std::string& json_str) {
120 const auto doc = json::parse(json_str, nullptr, false);
121 if (doc.is_discarded()) {
122 return absl::InvalidArgumentError(
123 "ParsePreflightOutput: JSON parse failed");
124 }
125 if (!doc.contains("Dungeon Oracle Preflight")) {
126 return absl::InvalidArgumentError(
127 "ParsePreflightOutput: missing 'Dungeon Oracle Preflight' key");
128 }
129 const auto& root = doc.at("Dungeon Oracle Preflight");
130
132 r.ok = root.value("ok", false);
133 r.error_count = root.value("error_count", 0);
134 r.water_fill_region_ok = root.value("water_fill_region_ok", false);
135 r.water_fill_table_ok = root.value("water_fill_table_ok", false);
136 r.custom_collision_maps_ok = root.value("custom_collision_maps_ok", false);
137 r.required_rooms_check = root.value("required_rooms_check", "skipped");
138 if (root.contains("required_rooms_ok")) {
139 r.required_rooms_ok = root.at("required_rooms_ok").get<bool>();
140 }
141 r.status = root.value("status", "");
142
143 for (const auto& e : root.value("errors", json::array())) {
144 PreflightError err;
145 err.code = e.value("code", "");
146 err.message = e.value("message", "");
147 err.status_code = e.value("status", "");
148 if (e.contains("room_id")) {
149 err.room_id = e.at("room_id").get<std::string>();
150 }
151 r.errors.push_back(std::move(err));
152 }
153
154 return r;
155}
156
157} // namespace yaze::editor::oracle_validation
std::vector< std::string > BuildSmokeArgs(const SmokeOptions &opts)
std::vector< std::string > BuildPreflightArgs(const PreflightOptions &opts)
std::string BuildCliCommand(const std::string &command_name, const std::vector< std::string > &args)
absl::StatusOr< SmokeResult > ParseSmokeCheckOutput(const std::string &json_str)
absl::StatusOr< PreflightResult > ParsePreflightOutput(const std::string &json_str)