Skip to content

Commit 6297dcf

Browse files
authored
Merge pull request #2213 from SneakBug8/feature/api
JSON API adjustments
2 parents ce9911d + 245de8b commit 6297dcf

File tree

3 files changed

+222
-17
lines changed

3 files changed

+222
-17
lines changed

src/network/webapi/controllers.hpp

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,22 @@ inline void init(sys::state& state) noexcept {
3535
if(state.host_settings.alice_expose_webui != 1 || state.network_mode == sys::network_mode_type::client) {
3636
return;
3737
}
38+
/* Conventions:
39+
/{collection}/(\d+) for one entry retrieval,
40+
/{collection}/all to retrieve all entries of type
41+
*/
3842

3943
svr.Get("/", [](const httplib::Request&, httplib::Response& res) {
4044
res.set_content("Homepage", "text/plain");
4145
});
4246

4347
svr.Get("/date", [&](const httplib::Request& req, httplib::Response& res) {
44-
auto dt = state.current_date.to_ymd(state.start_date);
45-
json j = json::object();
46-
j["year"] = dt.year;
47-
j["month"] = dt.month;
48-
j["day"] = dt.day;
49-
j["date"] = std::to_string(dt.day) + "." + std::to_string(dt.month) + "." + std::to_string(dt.year);
50-
48+
json j = format_date(state, state.current_date);
5149
res.set_content(j.dump(), "text/plain");
5250
});
5351

5452

55-
svr.Get("/nations", [&](const httplib::Request& req, httplib::Response& res) {
53+
svr.Get("/nation/all", [&](const httplib::Request& req, httplib::Response& res) {
5654
json jlist = json::array();
5755

5856
for(auto nation : state.world.in_nation) {
@@ -86,7 +84,7 @@ inline void init(sys::state& state) noexcept {
8684
res.set_content(j.dump(), "text/plain");
8785
});
8886

89-
svr.Get("/commodities", [&](const httplib::Request& req, httplib::Response& res) {
87+
svr.Get("/commodity/all", [&](const httplib::Request& req, httplib::Response& res) {
9088
json jlist = json::array();
9189

9290
for(auto commodity : state.world.in_commodity) {
@@ -178,7 +176,7 @@ inline void init(sys::state& state) noexcept {
178176
res.set_content(j.dump(), "text/plain");
179177
});
180178

181-
svr.Get("/provinces", [&](const httplib::Request& req, httplib::Response& res) {
179+
svr.Get("/province/all", [&](const httplib::Request& req, httplib::Response& res) {
182180
json jlist = json::array();
183181

184182
for(auto prov : state.world.in_province) {
@@ -304,6 +302,63 @@ inline void init(sys::state& state) noexcept {
304302
res.set_content(j.dump(), "text/plain");
305303
});
306304

305+
svr.Get("/unittype/all", [&](const httplib::Request& req, httplib::Response& res) {
306+
json jlist = json::array();
307+
308+
for(uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
309+
dcon::unit_type_id uid = dcon::unit_type_id{ dcon::unit_type_id::value_base_t(i) };
310+
auto j = json::object();
311+
312+
jlist.push_back(format_unit_type(state, uid));
313+
}
314+
315+
res.set_content(jlist.dump(), "text/plain");
316+
});
317+
318+
svr.Get(R"(/army/all)", [&](const httplib::Request& req, httplib::Response& res) {
319+
320+
auto j = json::array();
321+
322+
for(auto a : state.world.in_army) {
323+
j.push_back(format_army(state, a));
324+
}
325+
326+
res.set_content(j.dump(), "text/plain");
327+
});
328+
329+
svr.Get(R"(/navy/all)", [&](const httplib::Request& req, httplib::Response& res) {
330+
331+
auto j = json::array();
332+
333+
for(auto n : state.world.in_navy) {
334+
j.push_back(format_navy(state, n));
335+
}
336+
337+
res.set_content(j.dump(), "text/plain");
338+
});
339+
340+
svr.Get(R"(/regiment/(\d+))", [&](const httplib::Request& req, httplib::Response& res) {
341+
auto match = req.matches[1];
342+
auto num = std::atoi(match.str().c_str());
343+
344+
dcon::regiment_id p{ dcon::regiment_id::value_base_t(num) };
345+
346+
auto j = format_regiment(state, p);
347+
348+
res.set_content(j.dump(), "text/plain");
349+
});
350+
351+
svr.Get(R"(/ship/(\d+))", [&](const httplib::Request& req, httplib::Response& res) {
352+
auto match = req.matches[1];
353+
auto num = std::atoi(match.str().c_str());
354+
355+
dcon::ship_id p{ dcon::ship_id::value_base_t(num) };
356+
357+
auto j = format_ship(state, p);
358+
359+
res.set_content(j.dump(), "text/plain");
360+
});
361+
307362
svr.listen("0.0.0.0", 1234);
308363
}
309364

src/network/webapi/jsonlayer.cpp

Lines changed: 156 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,27 @@ using json = nlohmann::json;
1212

1313
namespace webui {
1414

15+
/*
16+
Convention: pass id.index() for references (-1 for invalid value) and convert indexes back into values on client-side (0 for invalid value)
17+
*/
18+
1519
json format_color(sys::state& state, uint32_t c) {
1620
json j = json::object();
1721

1822
j["r"] = sys::int_red_from_int(c);
1923
j["g"] = sys::int_green_from_int(c);
2024
j["b"] = sys::int_blue_from_int(c);
2125

26+
return j;
27+
}
28+
29+
json format_date(sys::state& state, sys::date date) {
30+
json j = json::object();
31+
auto dt = date.to_ymd(state.start_date);
32+
j["year"] = dt.year;
33+
j["month"] = dt.month;
34+
j["day"] = dt.day;
35+
j["date"] = std::to_string(dt.day) + "." + std::to_string(dt.month) + "." + std::to_string(dt.year);
2236

2337
return j;
2438
}
@@ -60,7 +74,7 @@ json format_commodity(sys::state& state, dcon::commodity_id c) {
6074
json format_commodity_link(sys::state& state, dcon::commodity_id c) {
6175
json j = json::object();
6276

63-
j["id"] = c.index();;
77+
j["id"] = c.index();
6478
j["name"] = text::produce_simple_string(state, state.world.commodity_get_name(c));
6579
j["key"] = state.to_string_view(state.world.commodity_get_name(c));
6680
j["color"] = format_color(state, state.world.commodity_get_color(c));
@@ -80,7 +94,7 @@ json format_nation(sys::state& state, dcon::nation_id n) {
8094
j["color"] = format_color(state, color);
8195

8296
auto capital = state.world.nation_get_capital(n);
83-
j["capital"] = format_province_link(state, capital);
97+
j["capital"] = capital.id.index();
8498

8599
json jlist = json::array();
86100
for(auto st : state.world.in_state_instance) {
@@ -223,8 +237,10 @@ json format_province(sys::state& state, dcon::province_id pid) {
223237
j["name"] = province_name;
224238
j["provid"] = state.world.province_get_provid(prov);
225239

226-
j["owner"] = format_nation_link(state, owner);
227-
j["state"] = format_state_link(state, sid);
240+
if(owner) {
241+
j["owner"] = owner.index(); // format_nation_link(state, owner);
242+
}
243+
// j["state"] = format_state_instance_link(state, sid);
228244

229245
j["x"] = state.world.province_get_mid_point(prov).x;
230246
j["y"] = state.world.province_get_mid_point(prov).y;
@@ -270,7 +286,7 @@ json format_province(sys::state& state, dcon::province_id pid) {
270286
if(economy::rgo_max_employment(state, c, prov) > 100.f) {
271287
json t = json::object();
272288

273-
t["commodity"] = format_commodity_link(state, c);
289+
t["commodity"] = c.id.index();
274290

275291
t["max_employment"] = economy::rgo_max_employment(state, c, prov);
276292

@@ -286,7 +302,7 @@ json format_province(sys::state& state, dcon::province_id pid) {
286302
t["employment"]["no_education"]["target"] = int(target_employment);
287303
t["employment"]["no_education"]["satisfaction"] = satisfaction;
288304
t["employment"]["no_education"]["actual"] = int(target_employment * satisfaction);
289-
t["employment"]["no_education"]["wage"] = state.world.province_get_labor_price(prov, economy::labor::no_education);
305+
t["employment"]["no_education"]["wage"] = double(state.world.province_get_labor_price(prov, economy::labor::no_education));
290306
t["employment"]["no_education"]["max"] = int(economy::rgo_max_employment(state, c, prov));
291307

292308
bool const is_mine = state.world.commodity_get_is_mine(c);
@@ -311,7 +327,9 @@ json format_province(sys::state& state, dcon::province_id pid) {
311327
json jlist = json::array();
312328
for(auto floc : state.world.in_factory_location) {
313329
if(floc.get_province() == prov) {
314-
jlist.push_back(format_factory(state, floc.get_factory()));
330+
// jlist.push_back(format_factory(state, floc.get_factory()));
331+
auto fid = floc.get_factory().id.index();
332+
jlist.push_back(fid);
315333
}
316334
}
317335
j["factories"] = jlist;
@@ -447,4 +465,135 @@ json format_wargoal(sys::state& state, sys::full_wg wid) {
447465
return j;
448466
}
449467

468+
json format_ship(sys::state& state, dcon::ship_id id) {
469+
json j = json::object();
470+
471+
j["id"] = id.index();
472+
473+
// j["name"] = text::produce_simple_string(state, state.world.ship_get_name(id));
474+
j["type"] = state.world.ship_get_type(id).value;
475+
j["strength"] = state.world.ship_get_strength(id);
476+
j["org"] = state.world.ship_get_org(id);
477+
j["pending_split"] = state.world.ship_get_pending_split(id);
478+
j["experience"] = state.world.ship_get_experience(id);
479+
return j;
480+
481+
}
482+
json format_army(sys::state& state, dcon::army_id id) {
483+
json j = json::object();
484+
485+
j["id"] = id.index();
486+
j["name"] = state.to_string_view(state.world.army_get_name(id));
487+
488+
j["location"] = (int32_t) state.world.army_get_location_from_army_location(id).index();
489+
490+
j["black_flag"] = state.world.army_get_black_flag(id);
491+
j["is_retreating"] = state.world.army_get_is_retreating(id);
492+
j["is_rebel_hunter"] = state.world.army_get_is_rebel_hunter(id);
493+
j["moving_to_merge"] = state.world.army_get_moving_to_merge(id);
494+
j["special_order"] = state.world.army_get_special_order(id);
495+
j["dig_in"] = state.world.army_get_dig_in(id);
496+
j["path"] = json::array();
497+
for(auto p : state.world.army_get_path(id)) {
498+
j["path"].push_back((int32_t)p.index());
499+
}
500+
j["arrival_time"] = format_date(state, state.world.army_get_arrival_time(id));
501+
j["unused_travel_days"] = state.world.army_get_unused_travel_days(id);
502+
// j["ai_activity"] = state.world.army_get_ai_activity(id);
503+
// j["ai_province"] = state.world.army_get_ai_province(id);
504+
j["is_ai_controlled"] = state.world.army_get_is_ai_controlled(id);
505+
506+
j["regiments"] = json::array();
507+
for(const auto am : state.world.army_get_army_membership(id)) {
508+
auto rid = am.get_regiment();
509+
j["regiments"].push_back(rid.id.index());
510+
}
511+
512+
return j;
513+
514+
}
515+
json format_navy(sys::state& state, dcon::navy_id id) {
516+
json j = json::object();
517+
518+
j["id"] = id.index();
519+
j["name"] = state.to_string_view(state.world.navy_get_name(id));
520+
j["path"] = json::array();
521+
522+
j["location"] = (int32_t)state.world.navy_get_location_from_navy_location(id).index();
523+
524+
for(auto p : state.world.navy_get_path(id)) {
525+
j["path"].push_back((int32_t)p.index());
526+
}
527+
j["arrival_time"] = format_date(state, state.world.navy_get_arrival_time(id));
528+
j["unused_travel_days"] = state.world.navy_get_unused_travel_days(id);
529+
j["months_outside_naval_range"] = state.world.navy_get_months_outside_naval_range(id);
530+
j["is_retreating"] = state.world.navy_get_is_retreating(id);
531+
j["moving_to_merge"] = state.world.navy_get_moving_to_merge(id);
532+
j["ai_activity"] = state.world.navy_get_ai_activity(id);
533+
534+
j["ships"] = json::array();
535+
for(const auto am : state.world.navy_get_navy_membership(id)) {
536+
auto rid = am.get_ship();
537+
j["ships"].push_back(rid.id.index());
538+
}
539+
return j;
540+
541+
}
542+
543+
json format_regiment(sys::state& state, dcon::regiment_id id) {
544+
json j = json::object();
545+
546+
j["id"] = id.index();
547+
j["name"] = text::produce_simple_string(state, state.to_string_view(state.world.regiment_get_name(id)));
548+
549+
// Non-localised type name and id
550+
auto type = state.world.regiment_get_type(id);
551+
j["type_name"] = state.to_string_view(state.military_definitions.unit_base_definitions[type].name);
552+
j["type_id"] = type.index();
553+
554+
j["strength"] = state.world.regiment_get_strength(id);
555+
j["pending_combat_damage"] = state.world.regiment_get_pending_combat_damage(id);
556+
j["pending_attrition_damage"] = state.world.regiment_get_pending_attrition_damage(id);
557+
j["org"] = state.world.regiment_get_org(id);
558+
j["pending_split"] = state.world.regiment_get_pending_split(id);
559+
j["experience"] = state.world.regiment_get_experience(id);
560+
return j;
561+
}
562+
563+
json format_unit_type(sys::state& state, dcon::unit_type_id id) {
564+
json j = json::object();
565+
566+
auto type = state.military_definitions.unit_base_definitions[id];
567+
568+
j["id"] = id.index();
569+
j["name"] = state.to_string_view(type.name);
570+
571+
j["attack_or_gun_power"] = type.attack_or_gun_power;
572+
j["build_cost"] = format_commodity_set(state, type.build_cost);
573+
j["build_time"] = type.build_time;
574+
j["can_build_overseas"] = type.can_build_overseas;
575+
j["capital"] = type.capital;
576+
j["colonial_points"] = type.colonial_points;
577+
j["default_organisation"] = type.default_organisation;
578+
j["defence_or_hull"] = type.defence_or_hull;
579+
j["discipline_or_evasion"] = type.discipline_or_evasion;
580+
j["is_land"] = type.is_land;
581+
j["maneuver"] = type.maneuver;
582+
j["maximum_speed"] = type.maximum_speed;
583+
j["min_port_level"] = type.min_port_level;
584+
j["naval_icon"] = type.naval_icon;
585+
j["primary_culture"] = type.primary_culture;
586+
j["reconnaissance_or_fire_range"] = type.reconnaissance_or_fire_range;
587+
j["siege_or_torpedo_attack"] = type.siege_or_torpedo_attack;
588+
j["supply_consumption"] = type.supply_consumption;
589+
j["supply_consumption_score"] = type.supply_consumption_score;
590+
j["supply_cost"] = format_commodity_set(state, type.supply_cost);
591+
j["support"] = type.support;
592+
593+
return j;
594+
595+
}
596+
597+
598+
450599
}

src/network/webapi/jsonlayer.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ using json = nlohmann::json;
55
namespace webui {
66

77
json format_color(sys::state& state, uint32_t c);
8+
json format_date(sys::state& state, sys::date date);
89

910
json format_commodity(sys::state& state, dcon::commodity_id c);
1011
json format_commodity_link(sys::state& state, dcon::commodity_id c);

0 commit comments

Comments
 (0)