6#include "nlohmann/json.hpp"
10using json = nlohmann::json;
14 const auto now = std::chrono::system_clock::now();
15 const auto t = std::chrono::system_clock::to_time_t(now);
19 gmtime_s(&tm_utc, &t);
21 gmtime_r(&t, &tm_utc);
23 std::strftime(buf,
sizeof(buf),
"%Y-%m-%dT%H:%M:%SZ", &tm_utc);
28 std::vector<std::string> args;
30 args.push_back(
"--rom=" + opts.
rom_path);
33 args.push_back(
"--strict-readiness");
36 args.push_back(
"--min-d6-track-rooms=" +
39 args.push_back(
"--format=json");
47 std::vector<std::string> args;
49 args.push_back(
"--rom=" + opts.
rom_path);
52 args.push_back(
"--required-collision-rooms=" +
56 args.push_back(
"--require-write-support");
59 args.push_back(
"--skip-collision-maps");
61 args.push_back(
"--format=json");
69 const std::vector<std::string>& args) {
70 std::string cmd =
"z3ed " + command_name;
71 for (
const auto& arg : args) {
78 const auto doc = json::parse(json_str,
nullptr,
false);
79 if (doc.is_discarded()) {
80 return absl::InvalidArgumentError(
81 "ParseSmokeCheckOutput: JSON parse failed");
84 if (!doc.contains(
"Oracle Smoke Check")) {
85 return absl::InvalidArgumentError(
86 "ParseSmokeCheckOutput: missing 'Oracle Smoke Check' key");
88 const auto& root = doc.at(
"Oracle Smoke Check");
89 const auto& checks = root.value(
"checks", json::object());
92 r.
ok = root.value(
"ok",
false);
93 r.
status = root.value(
"status",
"");
96 const auto& d4 = checks.value(
"d4_zora_temple", json::object());
99 if (d4.contains(
"required_rooms_ok")) {
103 const auto& d6 = checks.value(
"d6_goron_mines", json::object());
104 r.
d6.
ok = d6.value(
"ok",
false);
109 const auto& d3 = checks.value(
"d3_kalyxo_castle", json::object());
111 if (d3.contains(
"ok")) {
112 r.
d3.
ok = d3.at(
"ok").get<
bool>();
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");
125 if (!doc.contains(
"Dungeon Oracle Preflight")) {
126 return absl::InvalidArgumentError(
127 "ParsePreflightOutput: missing 'Dungeon Oracle Preflight' key");
129 const auto& root = doc.at(
"Dungeon Oracle Preflight");
132 r.
ok = root.value(
"ok",
false);
138 if (root.contains(
"required_rooms_ok")) {
141 r.
status = root.value(
"status",
"");
143 for (
const auto& e : root.value(
"errors", json::array())) {
145 err.
code = e.value(
"code",
"");
146 err.
message = e.value(
"message",
"");
148 if (e.contains(
"room_id")) {
149 err.
room_id = e.at(
"room_id").get<std::string>();
151 r.
errors.push_back(std::move(err));
std::vector< std::string > BuildSmokeArgs(const SmokeOptions &opts)
std::vector< std::string > BuildPreflightArgs(const PreflightOptions &opts)
std::string CurrentTimestamp()
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)
std::optional< std::string > room_id
std::string required_collision_rooms
bool require_write_support
std::string required_rooms_check
bool water_fill_region_ok
bool custom_collision_maps_ok
std::optional< bool > required_rooms_ok
std::vector< PreflightError > errors
std::string readiness_check
std::optional< bool > required_rooms_ok
std::string required_rooms_check
bool meets_min_track_rooms