Project Alice
Loading...
Searching...
No Matches
webui.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <string>
5#include "container_types.hpp"
6#include "commands.hpp"
7#include <iostream>
8#include <chrono>
9#include <ctime>
10#include "system_state.hpp"
11#include "network.hpp"
12#include "parsers.hpp"
13#include "simple_fs.hpp"
14#include "network.hpp"
15#include "demographics.hpp"
16
17#include <text.hpp>
18#include <json.hpp>
19
20#define CPPHTTPLIB_NO_EXCEPTIONS
21#include <httplib.h>
22
23using json = nlohmann::json;
24
25namespace webui {
26
27// HTTP
28static httplib::Server svr;
29
31 json j = json::object();
32
33 j["r"] = sys::int_red_from_int(c);
34 j["g"] = sys::int_green_from_int(c);
35 j["b"] = sys::int_blue_from_int(c);
36
37
38 return j;
39}
40
41json format_nation(sys::state& state, dcon::nation_id n) {
42 json j = json::object();
43
44 j["id"] = n.index();
45 j["name"] = text::produce_simple_string(state, text::get_name(state, n));
46
47 auto identity = state.world.nation_get_identity_from_identity_holder(n);
48 auto color = state.world.national_identity_get_color(identity);
49
50 j["color"] = format_color(state, color);
51
52 return j;
53}
54
55json format_nation(sys::state& state, dcon::national_identity_id n) {
56 json j = json::object();
57
58 auto fid = dcon::fatten(state.world, n);
59
60 j["name"] = text::produce_simple_string(state, fid.get_name());
61 j["color"] = format_color(state, fid.get_color());
62
63 return j;
64}
65
66json format_wargoal(sys::state& state, dcon::wargoal_id wid) {
67 json j = json::object();
68
69 auto fid = dcon::fatten(state.world, wid);
70
71 j["added_by"] = format_nation(state, fid.get_added_by());
72 j["state"] = text::produce_simple_string(state, fid.get_associated_state().get_name());
73 j["target"] = format_nation(state, fid.get_target_nation());
74 j["cb"] = text::produce_simple_string(state, fid.get_type().get_name());
75
76 j["secondary_nation"] = format_nation(state, fid.get_secondary_nation());
77 j["associated_tag"] = format_nation(state, fid.get_associated_tag());
78
79 j["ticking_warscore"] = fid.get_ticking_war_score();
80
81 return j;
82}
83
85 json j = json::object();
86
87 j["added_by"] = format_nation(state, wid.added_by);
88 j["state"] = text::produce_simple_string(state, state.world.state_definition_get_name(wid.state));
89 j["target"] = format_nation(state, wid.target_nation);
90 j["cb"] = text::produce_simple_string(state, state.world.cb_type_get_name(wid.cb));
91
92 j["secondary_nation"] = format_nation(state, wid.secondary_nation);
93 j["associated_tag"] = format_nation(state, wid.wg_tag);
94
95 return j;
96}
97
98inline void init(sys::state& state) noexcept {
99
100 if(state.host_settings.alice_expose_webui != 1 || state.network_mode == sys::network_mode_type::client) {
101 return;
102 }
103
104 svr.Get("/", [](const httplib::Request&, httplib::Response& res) {
105 res.set_content("Homepage", "text/plain");
106 });
107
108 svr.Get("/date", [&](const httplib::Request& req, httplib::Response& res) {
109 auto dt = state.current_date.to_ymd(state.start_date);
110 json j = json::object();
111 j["year"] = dt.year;
112 j["month"] = dt.month;
113 j["day"] = dt.day;
114 j["date"] = std::to_string(dt.day) + "." + std::to_string(dt.month) + "." + std::to_string(dt.year);
115
116 res.set_content(j.dump(), "text/plain");
117 });
118
119
120 svr.Get("/nations", [&](const httplib::Request& req, httplib::Response& res) {
121 json jlist = json::array();
122
123 for(auto nation : state.world.in_nation) {
124 auto nation_ppp_gdp_text = text::format_float(economy::gdp_adjusted(state, nation.id));
125 float population = state.world.nation_get_demographics(nation.id, demographics::total);
126 auto nation_ppp_gdp_per_capita_text = text::format_float(economy::gdp_adjusted(state, nation.id) / population * 1000000.f);
127 auto nation_sol_text = text::format_float(demographics::calculate_nation_sol(state, nation.id));
128
129 auto national_bank = state.world.nation_get_national_bank(nation);
130 auto state_debt = nations::get_debt(state, nation);
131
132 json j = format_nation(state, nation);
133
134 j["population"] = population;
135 j["nation_ppp_gdp"] = nation_ppp_gdp_text;
136 j["nation_ppp_gdp_per_capita"] = nation_ppp_gdp_per_capita_text;
137 j["nation_sol"] = nation_sol_text;
138
139 j["national_bank"] = national_bank;
140 j["state_debt"] = state_debt;
141
142 jlist.push_back(j);
143 }
144
145 res.set_content(jlist.dump(), "text/plain");
146
147 });
148
149 svr.Get("/commodities", [&](const httplib::Request& req, httplib::Response& res) {
150 json jlist = json::array();
151
152 for(auto commodity : state.world.in_commodity) {
153 auto id = commodity.id.index();
154
155 auto commodity_name = text::produce_simple_string(state, state.world.commodity_get_name(commodity));
156
157 json j = json::object();
158
159 j["id"] = id;
160 j["name"] = commodity_name;
161
162 {
163 json jplist = json::array();
164 for(auto n : state.world.in_nation)
165 if(n.get_owned_province_count() != 0) {
166 json jel = format_nation(state, n);
167 jel["supply"] = economy::supply(state, n, commodity);
168
169 if(jel["supply"] > 0.0f) {
170 jplist.push_back(jel);
171 }
172 }
173 j["producers"] = jplist;
174 }
175 {
176 json jblist = json::array();
177 for(auto n : state.world.in_nation)
178 if(n.get_owned_province_count() != 0) {
179 json jel = format_nation(state, n);
180 jel["demand"] = economy::demand(state, n, commodity);
181
182 if(jel["demand"] > 0.0f) {
183 jblist.push_back(jel);
184 }
185 }
186
187 j["consumers"] = jblist;
188 }
189
190 jlist.push_back(j);
191 }
192
193 res.set_content(jlist.dump(), "text/plain");
194 });
195
196 svr.Get("/routes", [&](const httplib::Request& req, httplib::Response& res) {
197 json jlist = json::array();
198
199 for(auto cid : state.world.in_commodity) {
200 state.world.for_each_trade_route([&](dcon::trade_route_id trade_route) {
201 auto current_volume = state.world.trade_route_get_volume(trade_route, cid);
202 auto origin =
203 current_volume > 0.f
204 ? state.world.trade_route_get_connected_markets(trade_route, 0)
205 : state.world.trade_route_get_connected_markets(trade_route, 1);
206 auto target =
207 current_volume <= 0.f
208 ? state.world.trade_route_get_connected_markets(trade_route, 0)
209 : state.world.trade_route_get_connected_markets(trade_route, 1);
210
211 auto s_origin = state.world.market_get_zone_from_local_market(origin);
212 auto s_target = state.world.market_get_zone_from_local_market(target);
213
214 auto p_origin = state.world.state_instance_get_capital(s_origin);
215 auto p_target = state.world.state_instance_get_capital(s_target);
216
217 auto sat = state.world.market_get_direct_demand_satisfaction(origin, cid);
218
219 auto absolute_volume = std::abs(current_volume);
220 auto factual_volume = sat * absolute_volume;
221
222 if(absolute_volume <= 0) {
223 return;
224 }
225
226 bool is_sea = state.world.trade_route_get_distance(trade_route) == state.world.trade_route_get_sea_distance(trade_route);
227
228 auto commodity_name = text::produce_simple_string(state, state.world.commodity_get_name(cid));
229
230 json j = json::object();
231
232 j["commodity_id"] = cid.id.value;
233 j["commodity"] = commodity_name;
234
235 j["origin_market_id"] = origin.value;
236 j["target_market_id"] = target.value;
237
238 j["origin_state_id"] = s_origin.value;
239 j["target_state_id"] = s_target.value;
240
241 j["origin_province_id"] = p_origin.id.value;
242 j["target_province_id"] = p_target.id.value;
243
244 j["origin_province_name"] = text::produce_simple_string(state, state.world.province_get_name(p_origin));
245 j["target_province_name"] = text::produce_simple_string(state, state.world.province_get_name(p_target));
246
247 auto origin_country = state.world.province_get_nation_from_province_ownership(p_origin);
248 auto target_country = state.world.province_get_nation_from_province_ownership(p_target);
249
250 j["origin_country_id"] = origin_country.value;
251 j["target_country_id"] = target_country.value;
252
253 j["origin_country_name"] = text::produce_simple_string(state, text::get_name(state, origin_country));
254 j["target_country_name"] = text::produce_simple_string(state, text::get_name(state, target_country));
255
256 j["volume"] = text::format_float(factual_volume);
257 j["desired_volume"] = text::format_float(absolute_volume);
258
259 j["is_sea"] = is_sea;
260 jlist.push_back(j);
261 });
262 }
263
264 res.set_content(jlist.dump(), "text/plain");
265 });
266
267 svr.Get("/provinces", [&](const httplib::Request& req, httplib::Response& res) {
268 json jlist = json::array();
269
270 for(auto prov : state.world.in_province) {
271 auto id = prov.id.index();
272
273 auto province_name = text::produce_simple_string(state, state.world.province_get_name(prov));
274
275 auto owner = state.world.province_get_nation_from_province_ownership(prov.id);
276 auto prov_population = state.world.province_get_demographics(prov.id, demographics::total);
277
278 float num_capitalist = state.world.province_get_demographics(
279 prov,
280 demographics::to_key(state, state.culture_definitions.capitalists)
281 );
282
283 float num_aristocrat = state.world.province_get_demographics(
284 prov,
285 demographics::to_key(state, state.culture_definitions.aristocrat)
286 );
287
288 auto rgo = state.world.province_get_rgo(prov);
289
290 json j = json::object();
291
292 j["id"] = id;
293 j["name"] = province_name;
294 j["owner"] = format_nation(state, owner);
295 j["population"]["total"] = prov_population;
296 j["population"]["capitalist"] = num_capitalist;
297 j["population"]["aristocrat"] = num_aristocrat;
298
299 j["rgo"] = text::produce_simple_string(state, state.world.commodity_get_name(rgo));
300
301 jlist.push_back(j);
302 }
303
304 res.set_content(jlist.dump(), "text/plain");
305 });
306
307 svr.Get("/wars", [&](const httplib::Request& req, httplib::Response& res) {
308 json jlist = json::array();
309
310 for(auto war : state.world.in_war) {
311 auto id = war.id.index();
312
313 json j = json::object();
314
315 j["id"] = id;
316 j["name"] = text::produce_simple_string(state, war.get_name());
317 j["is_great"] = war.get_is_great();
318 j["is_crisis"] = war.get_is_crisis_war();
319 j["attacker_battle_score"] = war.get_attacker_battle_score();
320 j["defender_battle_score"] = war.get_defender_battle_score();
321 j["primary_attacker"] = format_nation(state, war.get_primary_attacker());
322 j["primary_defender"] = format_nation(state, war.get_primary_defender());
323
324 j["over_state"] = text::produce_simple_string(state, war.get_over_state().get_name());
325
326 json jalist = json::array();
327 json jdlist = json::array();
328 std::vector<dcon::nation_id> attackers;
329
330 for(auto wp : state.world.war_get_war_participant(war)) {
331 if(wp.get_is_attacker()) {
332 jalist.push_back(format_nation(state, wp.get_nation()));
333 attackers.push_back(wp.get_nation());
334 } else {
335 jdlist.push_back(format_nation(state, wp.get_nation()));
336 }
337 }
338
339 j["attackers"] = jalist;
340 j["defenders"] = jdlist;
341
342 json jawgslist = json::array();
343 json jdwgslist = json::array();
344
345 for(auto el : war.get_wargoals_attached()) {
346 auto wg = el.get_wargoal();
347 if(std::find(attackers.begin(), attackers.end(), wg.get_added_by()) != attackers.end()) {
348 jawgslist.push_back(format_wargoal(state, wg));
349 }
350 else {
351 jdwgslist.push_back(format_wargoal(state, wg));
352 }
353 }
354
355 j["attacker_wargoals"] = jawgslist;
356 j["defender_wargoals"] = jdwgslist;
357
358 jlist.push_back(j);
359 }
360
361 res.set_content(jlist.dump(), "text/plain");
362 });
363
364 svr.Get("/crisis", [&](const httplib::Request& req, httplib::Response& res) {
365 json j = json::object();
366
367 j["attacker"] = format_nation(state, state.crisis_attacker);
368 j["defender"] = format_nation(state, state.crisis_defender);
369
370 j["primary_attacker"] = format_nation(state, state.primary_crisis_attacker);
371 j["primary_defender"] = format_nation(state, state.primary_crisis_defender);
372
373 if(state.crisis_state_instance) {
374 auto fid = dcon::fatten(state.world, state.crisis_state_instance);
375 auto defid = fid.get_definition();
376 j["over_state"] = text::produce_simple_string(state, defid.get_name());
377 }
378
379 j["temperature"] = state.crisis_temperature;
380
381 json jalist = json::array();
382 json jdlist = json::array();
383
384 for(auto cp : state.crisis_participants) {
385 if(cp.supports_attacker) {
386 jalist.push_back(format_nation(state, cp.id));
387 } else if (!cp.merely_interested) {
388 jdlist.push_back(format_nation(state, cp.id));
389 }
390 }
391
392 j["attackers"] = jalist;
393 j["defenders"] = jdlist;
394
395 json jawgslist = json::array();
396 json jdwgslist = json::array();
397
398 for(auto awg : state.crisis_attacker_wargoals) {
399 jawgslist.push_back(format_wargoal(state, awg));
400 }
401 for(auto dwg : state.crisis_attacker_wargoals) {
402 jdwgslist.push_back(format_wargoal(state, dwg));
403 }
404
405 j["attacker_wargoals"] = jawgslist;
406 j["defender_wargoals"] = jdwgslist;
407
408 res.set_content(j.dump(), "text/plain");
409 });
410
411 svr.listen("0.0.0.0", 1234);
412}
413
414}
415
namespace for Niels Lohmann
Definition: json.hpp:19499
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:22488
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition: json.hpp:20413
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition: json.hpp:21626
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition: json.hpp:20672
bool listen(const std::string &host, int port, int socket_flags=0)
Definition: httplib.h:6326
Server & Get(const std::string &pattern, Handler handler)
Definition: httplib.h:6104
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
float calculate_nation_sol(sys::state &state, dcon::nation_id nation_id)
constexpr dcon::demographics_key total(0)
dcon::demographics_key to_key(sys::state const &state, dcon::pop_type_id v)
float supply(sys::state &state, dcon::market_id s, dcon::commodity_id c)
Definition: economy.cpp:206
float demand(sys::state &state, dcon::market_id s, dcon::commodity_id c)
Definition: economy.cpp:283
float gdp_adjusted(sys::state &state, dcon::market_id n)
Definition: economy.cpp:846
float get_debt(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:1615
int32_t int_red_from_int(uint32_t v)
int32_t int_blue_from_int(uint32_t v)
int32_t int_green_from_int(uint32_t v)
std::string format_float(float num, size_t digits)
Definition: text.cpp:981
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
Definition: text.cpp:617
dcon::text_key get_name(sys::state &state, dcon::nation_id id)
Definition: text.cpp:880
Definition: webui.hpp:25
json format_color(sys::state &state, uint32_t c)
Definition: webui.hpp:30
void init(sys::state &state) noexcept
Definition: webui.hpp:98
json format_wargoal(sys::state &state, dcon::wargoal_id wid)
Definition: webui.hpp:66
json format_nation(sys::state &state, dcon::nation_id n)
Definition: webui.hpp:41
uint uint32_t
void set_content(const char *s, size_t n, const std::string &content_type)
Definition: httplib.h:5775
dcon::nation_id target_nation
dcon::nation_id added_by
dcon::nation_id secondary_nation
dcon::cb_type_id cb
dcon::national_identity_id wg_tag
dcon::state_definition_id state
Holds important data about the game world, state, and other data regarding windowing,...