aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/logger.c24
-rw-r--r--data/client.c522
-rw-r--r--data/client.cpp528
-rw-r--r--data/plots.c35
-rw-r--r--data/server.c1
-rwxr-xr-xsalis.py29
-rw-r--r--ui/curses/ui.c10
7 files changed, 562 insertions, 587 deletions
diff --git a/core/logger.c b/core/logger.c
index 880c231..efff3dc 100644
--- a/core/logger.c
+++ b/core/logger.c
@@ -9,8 +9,8 @@
#define LOG_LINE_SIZE 1024
enum LogLevel {
- LOG_INFO,
- LOG_WARN,
+ INFO,
+ WARN,
};
char g_log_buff[LOG_LINE_SIZE];
@@ -18,7 +18,7 @@ char g_log_buff[LOG_LINE_SIZE];
void log_msg_to_buff(char *out, int size, enum LogLevel level, bool colored, const char *format, va_list args) {
assert(out);
assert(size);
- assert(level == LOG_INFO || level == LOG_WARN);
+ assert(level == INFO || level == WARN);
assert(format);
struct timespec ts;
@@ -26,26 +26,26 @@ void log_msg_to_buff(char *out, int size, enum LogLevel level, bool colored, con
long msec = ts.tv_nsec / 1000000;
struct tm tm = *localtime(&ts.tv_sec);
pid_t pid = getpid();
- char *level_str = NULL;
+ const char *level_str = NULL;
switch (level) {
- case LOG_INFO:
+ case INFO:
level_str = "INFO";
break;
- case LOG_WARN:
+ case WARN:
level_str = "WARN";
break;
default:
assert(false);
}
- char *color_code = NULL;
+ const char *color_code = NULL;
if (colored) {
switch (level) {
- case LOG_INFO:
+ case INFO:
color_code = "\033[1;32m";
break;
- case LOG_WARN:
+ case WARN:
color_code = "\033[1;33m";
break;
default:
@@ -75,7 +75,7 @@ void log_msg_to_buff(char *out, int size, enum LogLevel level, bool colored, con
}
void log_msg(enum LogLevel level, bool colored, const char *format, va_list args) {
- assert(level == LOG_INFO || level == LOG_WARN);
+ assert(level == INFO || level == WARN);
assert(format);
log_msg_to_buff(g_log_buff, LOG_LINE_SIZE, level, colored, format, args);
@@ -87,7 +87,7 @@ void log_info(const char *format, ...) {
va_list args;
va_start(args, format);
- log_msg(LOG_INFO, true, format, args);
+ log_msg(INFO, true, format, args);
va_end(args);
}
@@ -96,6 +96,6 @@ void log_warn(const char *format, ...) {
va_list args;
va_start(args, format);
- log_msg(LOG_WARN, true, format, args);
+ log_msg(WARN, true, format, args);
va_end(args);
}
diff --git a/data/client.c b/data/client.c
deleted file mode 100644
index d5e8e56..0000000
--- a/data/client.c
+++ /dev/null
@@ -1,522 +0,0 @@
-#include <curses.h>
-#include <locale.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "logger.c"
-#include "plots.c"
-#include "tui.c"
-
-#define UI_AVAIL_PLOTS_COL PANE_AND_MARGIN_WIDTH
-#define UI_WINDOWS_COL (PANE_AND_MARGIN_WIDTH * 2)
-#define UI_PLOTS_COL (PANE_AND_MARGIN_WIDTH * 3)
-
-#define MAX_WINDOW_ROWS 4
-#define MAX_WINDOW_COLS 4
-#define MAX_WINDOW_PLOTS (MAX_WINDOW_ROWS * MAX_WINDOW_COLS)
-
-#define CTRL(x) (x & 0x1f)
-
-enum {
- PAIR_HEADER = 1,
- PAIR_SELECTED = 2,
- PAIR_TO_BE_CREATED = 3,
- PAIR_TO_BE_UPDATED = 4,
- PAIR_TO_BE_REMOVED = 5,
-};
-
-enum UIColumn {
- UICOL_AVAIL_PLOTS,
- UICOL_WINDOWS,
- UICOL_PLOTS,
- UICOL_COUNT,
-};
-
-enum WindowState {
- WINDOW_TO_BE_CREATED,
- WINDOW_TO_BE_UPDATED,
- WINDOW_IS_LIVE,
- WINDOW_TO_BE_REMOVED,
-};
-
-enum WindowPlotState {
- PLOT_TO_BE_CREATED,
- PLOT_IS_LIVE,
- PLOT_TO_BE_REMOVED,
-};
-
-struct WindowHandle {
- size_t wid;
- size_t rows;
- size_t cols;
- size_t rows_update;
- size_t cols_update;
- enum WindowState state;
- size_t plot_count;
- size_t plot_sel;
- enum WindowPlotState plot_states[MAX_WINDOW_PLOTS];
- struct PlotDef *plot_defs[MAX_WINDOW_PLOTS];
-};
-
-// Globals
-bool g_exit;
-enum UIColumn g_col_sel;
-size_t g_apsel;
-size_t g_wsel;
-size_t g_apscroll;
-size_t g_wscroll;
-size_t g_pscroll;
-size_t g_wid_count;
-struct WindowHandle *g_window_handles;
-size_t g_window_count;
-size_t g_window_cap;
-
-// ----------------------------------------------------------------------------
-// UI functions
-// ----------------------------------------------------------------------------
-void ui_print_sim_description(void) {
- // Simulation desciption
- int l = 1;
-
- tui_line(false, l++, PAIR_HEADER, A_BOLD, "SALIS DATA CLIENT");
- tui_str_field(l++, "name", NAME);
- tui_ulx_field(l++, "seed", SEED);
- tui_str_field(l++, "conn", IP ":" PORT_STR);
- tui_str_field(l++, "anc", ANC);
- tui_str_field(l++, "arch", ARCH);
- tui_ulx_field(l++, "asav", AUTOSAVE_INTERVAL);
- tui_ulx_field(l++, "cres", CORES);
-#if defined(MUTA_FLIP)
- tui_str_field(l++, "mflp", "true");
-#else
- tui_str_field(l++, "mflp", "false");
-#endif
- tui_ulx_field(l++, "mrng", MUTA_RANGE);
- tui_ulx_field(l++, "size", MVEC_SIZE);
-#if defined(MVEC_LOOP)
- tui_str_field(l++, "loop", "true");
-#else
- tui_str_field(l++, "loop", "false");
-#endif
-#if defined(COMPRESS)
- tui_str_field(l++, "xsav", "enabled");
-#else
- tui_str_field(l++, "xsav", "disabled");
-#endif
- tui_ulx_field(l++, "dpsi", DATA_PUSH_INTERVAL);
-
- // Window summary
- l++;
-
- tui_line(false, l++, PAIR_HEADER, A_BOLD, "SUMMARY");
- tui_uld_field(l++, "wcnt", g_window_count);
- tui_uld_field(l++, "wcap", g_window_cap);
- tui_uld_field(l++, "widc", g_wid_count);
-}
-
-void ui_print_avail_plots(void) {
- int l = 1;
- int pair = g_col_sel == UICOL_AVAIL_PLOTS ? PAIR_SELECTED : PAIR_HEADER;
-
- tui_field(l++, UI_AVAIL_PLOTS_COL, pair, A_BOLD, "AVAIL PLOTS [%ld:%ld]", g_apsel, g_apscroll);
-
- for (size_t i = g_apscroll; i < g_general_plots_count; i++) {
- pair = i == g_apsel ? PAIR_SELECTED : PAIR_NORMAL;
- tui_field(l++, UI_AVAIL_PLOTS_COL, pair, A_NORMAL, g_general_plots_def[i].name);
- }
-}
-
-void ui_print_windows(void) {
- int l = 1;
- int pair = g_col_sel == UICOL_WINDOWS ? PAIR_SELECTED : PAIR_HEADER;
-
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
- tui_field(l++, UI_WINDOWS_COL, pair, A_BOLD, "WINDOWS [%ld:%ld]", whdl->wid, g_wscroll);
-
- for (size_t i = g_wscroll; i < g_window_count; i++) {
- whdl = &g_window_handles[i];
- char mark = ' ';
-
- switch (whdl->state) {
- case WINDOW_TO_BE_CREATED:
- pair = PAIR_TO_BE_CREATED;
- mark = '+';
- break;
- case WINDOW_TO_BE_UPDATED:
- pair = PAIR_TO_BE_UPDATED;
- mark = 'u';
- break;
- case WINDOW_IS_LIVE:
- pair = PAIR_NORMAL;
- break;
- case WINDOW_TO_BE_REMOVED:
- pair = PAIR_TO_BE_REMOVED;
- mark = 'd';
- break;
- }
-
- pair = i == g_wsel ? PAIR_SELECTED : pair;
- tui_field(l++, UI_WINDOWS_COL, pair, A_NORMAL, "wid:%ld [%dx%d] %c", whdl->wid, whdl->rows_update, whdl->cols_update, mark);
- }
-}
-
-void ui_print_plots(void) {
- int l = 1;
- int pair = g_col_sel == UICOL_PLOTS ? PAIR_SELECTED : PAIR_HEADER;
-
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
- tui_field(l++, UI_PLOTS_COL, pair, A_BOLD, "PLOTS [%ld:%ld]", whdl->plot_sel, g_pscroll);
-
- if (!g_window_count) return;
-
- for (size_t i = g_pscroll; i < whdl->plot_count; i++) {
- struct PlotDef *plot_def = whdl->plot_defs[i];
- enum WindowPlotState plot_state = whdl->plot_states[i];
- char mark = ' ';
-
- switch (plot_state) {
- case PLOT_TO_BE_CREATED:
- pair = PAIR_TO_BE_CREATED;
- mark = '+';
- break;
- case PLOT_IS_LIVE:
- pair = PAIR_NORMAL;
- break;
- case PLOT_TO_BE_REMOVED:
- pair = PAIR_TO_BE_REMOVED;
- mark = 'd';
- break;
- }
-
- pair = i == whdl->plot_sel ? PAIR_SELECTED : pair;
- tui_field(l++, UI_PLOTS_COL, pair, A_NORMAL, "%s %c", plot_def->name, mark);
- plot_def++;
- }
-}
-
-void ui_print_footer(void) {
- tui_field(LINES - 1, 1, PAIR_NORMAL, A_NORMAL, "[+] new window | [enter] add plot | [x] delete elem | [ctrl+c] quit");
-}
-
-void ui_print(void) {
- ui_print_sim_description();
- ui_print_avail_plots();
- ui_print_windows();
- ui_print_plots();
- ui_print_footer();
-}
-
-// ----------------------------------------------------------------------------
-// Control function
-// ----------------------------------------------------------------------------
-void ev_scroll(int ev) {
- size_t *scroll_var = NULL;
-
- switch (g_col_sel) {
- case UICOL_AVAIL_PLOTS:
- scroll_var = &g_apscroll;
- break;
- case UICOL_WINDOWS:
- scroll_var = &g_wscroll;
- break;
- case UICOL_PLOTS:
- scroll_var = &g_pscroll;
- break;
- default:;
- }
-
- assert(scroll_var);
-
- switch (ev) {
- case 'w':
- *scroll_var += 1;
- break;
- case 's':
- *scroll_var -= (*scroll_var ? 1 : 0);
- break;
- case 'q':
- *scroll_var = 0;
- break;
- }
-}
-
-void ev_new_window(void) {
- if (g_window_count == g_window_cap) {
- // Reallocate dynamic array
- size_t new_window_cap = g_window_cap * 2;
- struct WindowHandle *new_window_handles = calloc(new_window_cap, sizeof(struct WindowHandle));
- memcpy(new_window_handles, g_window_handles, sizeof(struct WindowHandle) * g_window_count);
- free(g_window_handles);
- g_window_cap = new_window_cap;
- g_window_handles = new_window_handles;
- }
-
- g_window_count++;
- g_window_handles[g_window_count - 1] = (struct WindowHandle){
- .wid = g_wid_count++,
- .rows = 2,
- .cols = 2,
- .rows_update = 2,
- .cols_update = 2,
- .state = WINDOW_TO_BE_CREATED,
- };
-}
-
-void ev_delete_window_handle(size_t widx) {
- assert(g_window_count);
- assert(widx < g_window_count);
- assert(g_window_handles[widx].state == WINDOW_TO_BE_CREATED);
-
- for (size_t i = widx; i < g_window_count - 1; i++) {
- memcpy(&g_window_handles[i], &g_window_handles[i + 1], sizeof(struct WindowHandle));
- }
-
- g_window_handles[g_window_count - 1] = (struct WindowHandle){ 0 };
- g_window_count--;
- g_wsel -= (g_window_count && g_wsel == g_window_count) ? 1 : 0;
-}
-
-void ev_add_plot(void) {
- assert(g_col_sel == UICOL_AVAIL_PLOTS);
- assert(g_window_count);
-
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
- size_t max_plots = whdl->rows_update * whdl->cols_update;
- size_t pidx = 0;
-
- do {
- if (!whdl->plot_defs[pidx]) break;
- pidx++;
- } while (pidx < max_plots);
-
- if (pidx == max_plots) return;
-
- whdl->plot_count++;
- whdl->plot_states[pidx] = PLOT_TO_BE_CREATED;
- whdl->plot_defs[pidx] = &g_general_plots_def[g_apsel];
-}
-
-void ev_delete_plot(size_t widx) {
- assert(g_window_count);
- assert(widx < g_window_count);
-
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
- assert(whdl->plot_count);
- assert(whdl->plot_sel < whdl->plot_count);
- assert(whdl->plot_states[whdl->plot_sel] == PLOT_TO_BE_CREATED);
-
- for (size_t i = whdl->plot_sel; i < whdl->plot_count - 1; i++) {
- whdl->plot_states[i] = whdl->plot_states[i + 1];
- whdl->plot_defs[i] = whdl->plot_defs[i + 1];
- }
-
- whdl->plot_states[whdl->plot_count - 1] = 0;
- whdl->plot_defs[whdl->plot_count - 1] = NULL;
- whdl->plot_count--;
-
- if (!whdl->plot_count) {
- whdl->plot_sel = 0;
- } else if (whdl->plot_sel >= whdl->plot_count) {
- whdl->plot_sel = whdl->plot_count - 1;
- }
-}
-
-void ev_delete_elem(void) {
- if (g_col_sel == UICOL_WINDOWS && g_window_count) {
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
-
- switch (whdl->state) {
- case WINDOW_TO_BE_CREATED:
- ev_delete_window_handle(g_wsel);
- break;
- case WINDOW_TO_BE_UPDATED:
- break;
- case WINDOW_IS_LIVE:
- break;
- case WINDOW_TO_BE_REMOVED:
- break;
- }
- }
-
- if (g_col_sel == UICOL_PLOTS && g_window_count && g_window_handles[g_wsel].plot_count) {
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
-
- switch (whdl->plot_states[whdl->plot_sel]) {
- case PLOT_TO_BE_CREATED:
- ev_delete_plot(g_wsel);
- break;
- case PLOT_IS_LIVE:
- break;
- case PLOT_TO_BE_REMOVED:
- break;
- }
- }
-}
-
-void ev_resize_window(int ev) {
- assert(g_col_sel == UICOL_WINDOWS);
- assert(g_window_count);
-
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
-
- switch (ev) {
- case 'A':
- if (whdl->cols_update > 1 && (whdl->rows_update * (whdl->cols_update - 1)) >= whdl->plot_count) whdl->cols_update--;
- break;
- case 'D':
- whdl->cols_update += whdl->cols_update < MAX_WINDOW_COLS ? 1 : 0;
- break;
- case 'W':
- if (whdl->rows_update > 1 && (whdl->cols_update * (whdl->rows_update - 1)) >= whdl->plot_count) whdl->rows_update--;
- break;
- case 'S':
- whdl->rows_update += whdl->rows_update < MAX_WINDOW_ROWS ? 1 : 0;
- break;
- }
-}
-
-void ev_swap_plots(int ev) {
- assert(g_col_sel == UICOL_PLOTS);
- assert(g_window_count);
-
- struct WindowHandle *whdl = &g_window_handles[g_wsel];
- size_t pidx1;
- size_t pidx2;
-
- switch (ev) {
- case 'W':
- if (!whdl->plot_count || !whdl->plot_sel) return;
- pidx1 = whdl->plot_sel;
- pidx2 = whdl->plot_sel - 1;
- whdl->plot_sel--;
- break;
- case 'S':
- if (!whdl->plot_count || whdl->plot_sel >= whdl->plot_count - 1) return;
- pidx1 = whdl->plot_sel;
- pidx2 = whdl->plot_sel + 1;
- whdl->plot_sel++;
- break;
- }
-
- enum WindowPlotState tmp_state = whdl->plot_states[pidx1];
- whdl->plot_states[pidx1] = whdl->plot_states[pidx2];
- whdl->plot_states[pidx2] = tmp_state;
-
- struct PlotDef *tmp_def = whdl->plot_defs[pidx1];
- whdl->plot_defs[pidx1] = whdl->plot_defs[pidx2];
- whdl->plot_defs[pidx2] = tmp_def;
-}
-
-void ev_handle(void) {
- int ev = getch();
-
- switch (ev) {
- case CTRL('c'):
- g_exit = true;
- break;
- case KEY_RESIZE:
- tui_line_buff_resize();
- break;
- case 'w':
- case 's':
- case 'q':
- ev_scroll(ev);
- break;
- case 'Q':
- g_apscroll = 0;
- g_wscroll = 0;
- g_pscroll = 0;
- break;
- case KEY_LEFT:
- g_col_sel -= g_col_sel ? 1 : 0;
- break;
- case KEY_RIGHT:
- g_col_sel += g_col_sel < UICOL_COUNT - 1 ? 1 : 0;
- break;
- case KEY_UP:
- if (g_col_sel == UICOL_AVAIL_PLOTS && g_apsel) g_apsel--;
- if (g_col_sel == UICOL_WINDOWS && g_wsel) g_wsel--;
- if (g_col_sel == UICOL_PLOTS && g_window_count && g_window_handles[g_wsel].plot_sel) g_window_handles[g_wsel].plot_sel--;
- break;
- case KEY_DOWN:
- if (g_col_sel == UICOL_AVAIL_PLOTS && g_apsel < g_general_plots_count - 1) g_apsel++;
- if (g_col_sel == UICOL_WINDOWS && g_window_count && g_wsel < g_window_count - 1) g_wsel++;
- if (g_col_sel == UICOL_PLOTS && g_window_count && g_window_handles[g_wsel].plot_count && g_window_handles[g_wsel].plot_sel < g_window_handles[g_wsel].plot_count - 1) g_window_handles[g_wsel].plot_sel++;
- break;
- case '+':
- ev_new_window();
- break;
- case '\n':
- if (g_col_sel == UICOL_AVAIL_PLOTS && g_window_count) ev_add_plot();
- break;
- case 'x':
- ev_delete_elem();
- break;
- case 'A':
- case 'D':
- case 'W':
- case 'S':
- if (g_col_sel == UICOL_WINDOWS && g_window_count) ev_resize_window(ev);
- if (g_col_sel == UICOL_PLOTS && g_window_count) ev_swap_plots(ev);
- break;
- default:
- break;
- }
-}
-
-// ----------------------------------------------------------------------------
-// Main functions
-// ----------------------------------------------------------------------------
-void init(void) {
- log_info("Initializing salis data client");
-
- setlocale(LC_ALL, "");
-
- initscr();
- raw();
- noecho();
- curs_set(0);
- keypad(stdscr, TRUE);
-
- start_color();
- init_color(COLOR_BLACK, 0, 0, 0);
-
- init_pair(PAIR_NORMAL, COLOR_WHITE, COLOR_BLACK);
- init_pair(PAIR_HEADER, COLOR_BLUE, COLOR_BLACK);
- init_pair(PAIR_SELECTED, COLOR_YELLOW, COLOR_BLACK);
- init_pair(PAIR_TO_BE_CREATED, COLOR_GREEN, COLOR_BLACK);
- init_pair(PAIR_TO_BE_UPDATED, COLOR_GREEN, COLOR_BLACK);
- init_pair(PAIR_TO_BE_REMOVED, COLOR_RED, COLOR_BLACK);
-
- tui_line_buff_resize();
-
- g_window_count = 0;
- g_window_cap = 1;
- g_window_handles = calloc(g_window_cap, sizeof(struct WindowHandle));
-}
-
-void exec(void) {
- while (!g_exit) {
- ui_print();
- ev_handle();
- clear();
- }
-}
-
-void quit(void) {
- tui_line_buff_free();
- endwin();
- log_info("Shutting down salis data client");
-}
-
-int main(void) {
- init();
- exec();
- quit();
-
- free(g_window_handles);
- g_window_count = 0;
- g_window_cap = 0;
-
- return 0;
-}
diff --git a/data/client.cpp b/data/client.cpp
new file mode 100644
index 0000000..74f2bc5
--- /dev/null
+++ b/data/client.cpp
@@ -0,0 +1,528 @@
+#include <GLFW/glfw3.h>
+#include <imgui.h>
+#include <imgui_impl_glfw.h>
+#include <imgui_impl_opengl3.h>
+#include <implot.h>
+#include <limits.h>
+#include <math.h>
+
+#include <initializer_list>
+
+#include "logger.c"
+
+#define COLOR_BG ImVec4(0.f, 0.f, 0.f, 1.f)
+#define FONT_SIZE 12.f
+#define FONT_SOURCE "/usr/share/fonts/droid/DroidSansMono.ttf"
+#define GLSL_VERSION "#version 130"
+#define WINDOW_STYLE (ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings)
+
+#define DEFAULT_ENTRIES 2000
+#define DEFAULT_NTH 1
+#define DEFAULT_X_AXIS 0
+#define DEFAULT_X_LOW 0
+#define DEFAULT_X_HIGH INT_MAX
+#define DEFAULT_HM_LEFT 0
+#define DEFAULT_HM_PIXEL_COUNT 0x400
+
+#define PLOT_MIN_COLS 1
+#define PLOT_MAX_COLS 8
+
+enum Status {
+ STATUS_STOPPED,
+ STATUS_RUNNING,
+ STATUS_STOPPING,
+};
+
+struct Plot {
+ Plot(const char *name, const char *section, std::initializer_list<const char *> cols)
+ : name(name), section(section), cols(cols.begin()) {}
+
+ const char *name;
+ const char *section;
+ const char *const *cols;
+};
+
+// Globals
+GLFWwindow *g_window;
+ImGuiIO *g_io;
+ImGuiStyle *g_imgui_style;
+ImPlotStyle *g_implot_style;
+int g_status;
+
+// Data col
+bool g_data_col_visible = true;
+float g_data_col_width;
+
+const char *g_x_axes[] = {
+ "rowid",
+ "steps",
+#define FOR_CORE(i) "cycl_" #i,
+ FOR_CORES
+#undef FOR_CORE
+};
+
+int g_entries = DEFAULT_ENTRIES;
+int g_nth = DEFAULT_NTH;
+int g_x_axis = DEFAULT_X_AXIS;
+int g_x_low = DEFAULT_X_LOW;
+int g_x_high = DEFAULT_X_HIGH;
+int g_hm_left = DEFAULT_HM_LEFT;
+int g_hm_pixel_count = DEFAULT_HM_PIXEL_COUNT;
+int g_hm_pixel_pow; // calculate on startup
+bool g_data_touched;
+
+// Plots
+Plot g_plots[] = {
+ Plot("cycl", "general", {
+#define FOR_CORE(i) "cycl_" #i,
+ FOR_CORES
+#undef FOR_CORE
+ nullptr,
+ }),
+ Plot("mall", "general", {
+#define FOR_CORE(i) "mall_" #i,
+ FOR_CORES
+#undef FOR_CORE
+ nullptr,
+ }),
+ Plot("pnum", "general", {
+#define FOR_CORE(i) "pnum_" #i,
+ FOR_CORES
+#undef FOR_CORE
+ nullptr,
+ }),
+ Plot("ppop", "general", {
+#define FOR_CORE(i) "pfst_" #i, "plst_" #i,
+ FOR_CORES
+#undef FOR_CORE
+ nullptr,
+ }),
+ Plot("ambs", "general", {
+#define FOR_CORE(i) "amb0_" #i, "amb1_" #i,
+ FOR_CORES
+#undef FOR_CORE
+ nullptr,
+ }),
+ Plot("eevs", "general", {
+#define FOR_CORE(i) "emb0_" #i, "emb1_" #i, "eliv_" #i, "edea_" #i,
+ FOR_CORES
+#undef FOR_CORE
+ nullptr,
+ }),
+};
+
+#define PLOT_COUNT (int)(sizeof(g_plots) / sizeof(g_plots[0]))
+
+// Layout
+int g_plot_cols = 2;
+int g_plot_col_selected;
+int g_plot_row_selected;
+Plot *g_plot_cells[PLOT_MAX_COLS][PLOT_COUNT];
+Plot *g_plot_selected = &g_plots[0];
+bool g_plot_maximized;
+
+// ----------------------------------------------------------------------------
+// Data functions
+// ----------------------------------------------------------------------------
+int data_calc_max_hm_pixel_pow(void) {
+ return (int)floor(log2((float)(MVEC_SIZE - g_hm_left) / (float)g_hm_pixel_count));
+}
+
+void data_clamp(int *field, int low, int high) {
+ assert(field);
+ if (*field < low) *field = low;
+ if (*field > high) *field = high;
+}
+
+void data_validate(void) {
+ data_clamp(&g_entries, 1, DEFAULT_ENTRIES);
+ data_clamp(&g_nth, DEFAULT_NTH, INT_MAX);
+ data_clamp(&g_x_low, DEFAULT_X_LOW, INT_MAX);
+ data_clamp(&g_x_high, g_x_low + 1, DEFAULT_X_HIGH);
+ #if !defined(MVEC_LOOP)
+ data_clamp(&g_hm_left, DEFAULT_HM_LEFT, MVEC_SIZE);
+ #endif
+ data_clamp(&g_hm_pixel_count, 1, DEFAULT_HM_PIXEL_COUNT);
+ data_clamp(&g_hm_pixel_pow, 0, data_calc_max_hm_pixel_pow());
+ g_data_touched = false;
+}
+
+void data_reset_values(void) {
+ g_entries = DEFAULT_ENTRIES;
+ g_nth = DEFAULT_NTH;
+ g_x_axis = DEFAULT_X_AXIS;
+ g_x_low = DEFAULT_X_LOW;
+ g_x_high = DEFAULT_X_HIGH;
+ g_hm_left = DEFAULT_HM_LEFT;
+ g_hm_pixel_count = DEFAULT_HM_PIXEL_COUNT;
+ g_hm_pixel_pow = data_calc_max_hm_pixel_pow();
+}
+
+void data_reset_plot_cells(void) {
+ for (size_t i = 0; i < PLOT_MAX_COLS; i++) {
+ for (size_t j = 0; j < PLOT_COUNT; j++) {
+ g_plot_cells[i][j] = nullptr;
+ }
+ }
+}
+
+void data_start_fetching(void) {
+ assert(g_status == STATUS_RUNNING);
+ log_info("Starting data fetching thread");
+ // start data fetching thread
+}
+
+void data_stop_fetching(void) {
+ assert(g_status == STATUS_STOPPING);
+ log_info("Stopping data fetching thread");
+ // join data fetching thread (set STATUS_STOPPED from within thread)
+ g_status = STATUS_STOPPED;
+}
+
+// ----------------------------------------------------------------------------
+// GUI functions
+// ----------------------------------------------------------------------------
+void gui_print_data_col(void) {
+ const ImGuiViewport *viewport = ImGui::GetMainViewport();
+ const ImVec2 next_win_pos = viewport->Pos;
+ const ImVec2 next_win_size = ImVec2(-1.f, viewport->Size.y);
+
+ ImGui::SetNextWindowPos(next_win_pos);
+ ImGui::SetNextWindowSize(next_win_size);
+ ImGui::Begin("data-col", nullptr, WINDOW_STYLE);
+ g_data_col_width = ImGui::GetWindowWidth();
+
+ ImGui::SeparatorText("SALIS data client");
+ ImGui::LabelText("name", NAME);
+ ImGui::LabelText("seed", "%#lx", SEED);
+ ImGui::LabelText("server", IP ":" PORT_STR);
+ ImGui::LabelText("arch", ARCH);
+ ImGui::LabelText("cores", "%d", CORES);
+ ImGui::LabelText("mvec-size", "%#lx", MVEC_SIZE);
+ #if defined(MVEC_LOOP)
+ ImGui::LabelText("mvec-loop", "true");
+ #else
+ ImGui::LabelText("mvec-loop", "false");
+ #endif
+ ImGui::LabelText("data-push", "%#lx", DATA_PUSH_INTERVAL);
+
+ switch (g_status) {
+ case STATUS_STOPPED:
+ ImGui::LabelText("status", "%s", "stopped");
+ break;
+ case STATUS_RUNNING:
+ ImGui::LabelText("status", "%s", "running");
+ break;
+ case STATUS_STOPPING:
+ ImGui::LabelText("status", "%s", "stopping");
+ break;
+ }
+
+ ImGui::SeparatorText("Data fields");
+
+ switch (g_status) {
+ case STATUS_STOPPED:
+ if (ImGui::InputInt("entries", &g_entries, 0, 0, ImGuiInputTextFlags_CharsDecimal)) g_data_touched = true;
+ if (ImGui::InputInt("nth", &g_nth, 0, 0, ImGuiInputTextFlags_CharsDecimal)) g_data_touched = true;
+
+ if (ImGui::BeginCombo("x-axis", g_x_axes[g_x_axis])) {
+ for (int i = 0; i < CORES + 2; i++) {
+ if (ImGui::Selectable(g_x_axes[i], g_x_axis == i)) {
+ g_x_axis = i;
+ g_data_touched = true;
+ }
+ }
+
+ ImGui::EndCombo();
+ }
+
+ if (ImGui::InputInt("x-low", &g_x_low, 0, 0, ImGuiInputTextFlags_CharsDecimal)) g_data_touched = true;
+ if (ImGui::InputInt("x-high", &g_x_high, 0, 0, ImGuiInputTextFlags_CharsDecimal)) g_data_touched = true;
+ if (ImGui::InputInt("hm-left", &g_hm_left, 0, 0, ImGuiInputTextFlags_CharsDecimal)) g_data_touched = true;
+ if (ImGui::InputInt("hm-pxl-count", &g_hm_pixel_count, 0, 0, ImGuiInputTextFlags_CharsDecimal)) g_data_touched = true;
+ if (ImGui::InputInt("hm-pxl-pow", &g_hm_pixel_pow, 0, 0, ImGuiInputTextFlags_CharsDecimal)) g_data_touched = true;
+
+ if (ImGui::Button("Run", ImVec2(-1.f, 0.f))) {
+ g_status = STATUS_RUNNING;
+ data_start_fetching();
+ }
+
+ if (ImGui::Button("Reset", ImVec2(-1.f, 0.f))) data_reset_values();
+
+ break;
+ case STATUS_RUNNING:
+ case STATUS_STOPPING:
+ ImGui::LabelText("entries", "%d", g_entries);
+ ImGui::LabelText("nth", "%d", g_nth);
+ ImGui::LabelText("x-axis", "%s", g_x_axes[g_x_axis]);
+ ImGui::LabelText("x-low", "%d", g_x_low);
+ ImGui::LabelText("x-high", "%d", g_x_high);
+ ImGui::LabelText("hm-left", "%d", g_hm_left);
+ ImGui::LabelText("hm-pxl-count", "%d", g_hm_pixel_count);
+ ImGui::LabelText("hm-pxl-pow", "%d", g_hm_pixel_pow);
+
+ if (g_status == STATUS_RUNNING) {
+ if (ImGui::Button("Stop", ImVec2(-1.f, 0.f))) {
+ g_status = STATUS_STOPPING;
+ data_stop_fetching();
+ }
+ }
+ }
+
+ ImGui::SeparatorText("Layout");
+ ImGui::SliderInt("cols", &g_plot_cols, PLOT_MIN_COLS, PLOT_MAX_COLS);
+
+ ImGui::End();
+}
+
+void gui_print_plots(void) {
+ const char *section_current = g_plots[0].section;
+ const char *section_next = nullptr;
+ bool plots_covered[PLOT_COUNT] = { 0 };
+
+ const ImGuiViewport *viewport = ImGui::GetMainViewport();
+ const ImVec2 next_win_pos = g_data_col_visible ? ImVec2(g_data_col_width, viewport->Pos.y) : viewport->Pos;
+ const ImVec2 next_win_size = g_data_col_visible ? ImVec2(viewport->Size.x - g_data_col_width, -1.f) : ImVec2(viewport->Size.x, -1.f);
+
+ ImGui::SetNextWindowPos(next_win_pos);
+ ImGui::SetNextWindowSize(next_win_size);
+ ImGui::Begin("plots", nullptr, WINDOW_STYLE);
+
+ int col = 0;
+ int row = 0;
+
+ while (section_current) {
+ ImGui::SeparatorText(section_current);
+ ImGui::BeginTable("plots-table", g_plot_cols);
+
+ for (int i = 0; i < PLOT_COUNT; i++) {
+ if (g_plots[i].section != section_current) {
+ section_next = (!section_next && !plots_covered[i]) ? g_plots[i].section : section_next;
+ continue;
+ }
+
+ ImGui::TableNextColumn();
+
+ if (&g_plots[i] == g_plot_selected) {
+ g_plot_col_selected = col;
+ g_plot_row_selected = row;
+ g_implot_style->Colors[ImPlotCol_FrameBg] = g_imgui_style->Colors[ImGuiCol_FrameBg];
+ }
+
+ if (ImPlot::BeginPlot(g_plots[i].name)) {
+ int test_x[] = {0,1,2,3};
+ int test_y1[] = {1,2,3,4};
+ int test_y2[] = {2,4,8,16};
+ ImPlot::PlotLine("test1", test_x, test_y1, 4);
+ ImPlot::PlotLine("test2", test_x, test_y2, 4);
+ ImPlot::EndPlot();
+ }
+
+ g_implot_style->Colors[ImPlotCol_FrameBg] = COLOR_BG;
+
+ g_plot_cells[col][row] = &g_plots[i];
+ col = (col + 1) % g_plot_cols;
+ row += col ? 0 : 1;
+
+ plots_covered[i] = true;
+ }
+
+ section_current = section_next;
+ section_next = nullptr;
+ ImGui::EndTable();
+
+ row += col ? 1 : 0;
+ col = 0;
+ }
+
+ ImGui::End();
+}
+
+void gui_print_plot_maximized(void) {
+ const ImGuiViewport *viewport = ImGui::GetMainViewport();
+ ImGui::SetNextWindowPos(viewport->Pos);
+ ImGui::SetNextWindowSize(viewport->Size);
+ ImGui::Begin("plot-fullscreen", nullptr, WINDOW_STYLE);
+
+ if (ImPlot::BeginPlot(g_plot_selected->name, viewport->Size)) {
+ int test_x[] = {0,1,2,3};
+ int test_y1[] = {1,2,3,4};
+ int test_y2[] = {2,4,8,16};
+ ImPlot::PlotLine("test1", test_x, test_y1, 4);
+ ImPlot::PlotLine("test2", test_x, test_y2, 4);
+ ImPlot::EndPlot();
+ }
+
+ ImGui::End();
+}
+
+void gui_print(void) {
+ if (g_plot_maximized) {
+ gui_print_plot_maximized();
+ } else {
+ if (g_data_col_visible) gui_print_data_col();
+ gui_print_plots();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Main functions
+// ----------------------------------------------------------------------------
+void glfw_error_callback(int error, const char* description) {
+ log_warn("GLFW error %d: %s", error, description);
+}
+
+void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
+ (void)window;
+ (void)scancode;
+
+ if (action != GLFW_PRESS) return;
+
+ if (g_plot_maximized) {
+ switch (mods) {
+ case GLFW_MOD_CONTROL:
+ switch (key) {
+ case GLFW_KEY_C:
+ glfwSetWindowShouldClose(g_window, GLFW_TRUE);
+ break;
+ }
+
+ break;
+
+ case 0:
+ switch (key) {
+ case GLFW_KEY_F:
+ g_plot_maximized = !g_plot_maximized;
+ break;
+ }
+
+ break;
+ }
+
+ return;
+ }
+
+ switch (mods) {
+ case GLFW_MOD_CONTROL:
+ switch (key) {
+ case GLFW_KEY_C:
+ glfwSetWindowShouldClose(g_window, GLFW_TRUE);
+ break;
+ case GLFW_KEY_N:
+ g_data_col_visible = !g_data_col_visible;
+ break;
+ case GLFW_KEY_LEFT:
+ g_plot_cols -= g_plot_cols > 1 ? 1 : 0;
+ data_reset_plot_cells();
+ break;
+ case GLFW_KEY_RIGHT:
+ g_plot_cols += g_plot_cols < PLOT_MAX_COLS ? 1 : 0;
+ data_reset_plot_cells();
+ break;
+ }
+
+ break;
+
+ case 0:
+ switch (key) {
+ case GLFW_KEY_LEFT:
+ g_plot_col_selected -= g_plot_col_selected ? 1 : 0;
+ g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ break;
+ case GLFW_KEY_RIGHT:
+ g_plot_col_selected += (g_plot_col_selected < PLOT_MAX_COLS - 1 && g_plot_cells[g_plot_col_selected + 1][g_plot_row_selected]) ? 1 : 0;
+ g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ break;
+ case GLFW_KEY_UP:
+ g_plot_row_selected -= g_plot_row_selected ? 1 : 0;
+ g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ break;
+ case GLFW_KEY_DOWN:
+ g_plot_row_selected += (g_plot_row_selected < PLOT_COUNT - 1 && g_plot_cells[g_plot_col_selected][g_plot_row_selected + 1]) ? 1 : 0;
+ g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ break;
+ case GLFW_KEY_F:
+ g_plot_maximized = !g_plot_maximized;
+ break;
+ }
+
+ break;
+ }
+}
+
+int main(int argc, char **argv) {
+ (void)argc;
+ (void)argv;
+
+ log_info("Starting SALIS data client");
+
+ log_info("Initializing GLFW");
+ glfwSetErrorCallback(glfw_error_callback);
+ glfwInitHint(GLFW_WAYLAND_LIBDECOR, GLFW_WAYLAND_DISABLE_LIBDECOR);
+ if (!glfwInit()) assert(false);
+
+ float scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor());
+ g_window = glfwCreateWindow((int)(800 * scale), (int)(600 * scale), "SALIS data client", nullptr, nullptr);
+ assert(g_window);
+ glfwSetKeyCallback(g_window, glfw_key_callback);
+ glfwMakeContextCurrent(g_window);
+ glfwSwapInterval(1); // enable vsync
+
+ log_info("Initializing ImGui");
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImPlot::CreateContext();
+
+ g_io = &ImGui::GetIO();
+ g_io->Fonts->AddFontFromFileTTF(FONT_SOURCE);
+ g_io->IniFilename = nullptr;
+
+ g_imgui_style = &ImGui::GetStyle();
+ g_imgui_style->Colors[ImGuiCol_WindowBg] = COLOR_BG;
+ g_imgui_style->FontScaleDpi = scale;
+ g_imgui_style->FontSizeBase = FONT_SIZE;
+ g_imgui_style->ItemSpacing = ImVec2(g_imgui_style->ItemSpacing.x, 2.f);
+ g_imgui_style->ScaleAllSizes(scale);
+
+ g_implot_style = &ImPlot::GetStyle();
+ g_implot_style->Colors[ImPlotCol_FrameBg] = COLOR_BG;
+
+ ImGui_ImplGlfw_InitForOpenGL(g_window, true);
+ ImGui_ImplOpenGL3_Init(GLSL_VERSION);
+
+ g_hm_pixel_pow = data_calc_max_hm_pixel_pow();
+
+ // Main loop
+ while (!glfwWindowShouldClose(g_window)) {
+ glfwPollEvents();
+
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ gui_print();
+
+ if (g_data_touched) {
+ data_validate();
+ }
+
+ ImGui::Render();
+ int display_w, display_h;
+ glfwGetFramebufferSize(g_window, &display_w, &display_h);
+ glViewport(0, 0, display_w, display_h);
+ glClearColor(0.f, 0.f, 0.f, 1.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+ glfwSwapBuffers(g_window);
+ }
+
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImPlot::DestroyContext();
+ ImGui::DestroyContext();
+
+ log_info("Stopping SALIS data client");
+ glfwDestroyWindow(g_window);
+ glfwTerminate();
+ return 0;
+}
diff --git a/data/plots.c b/data/plots.c
deleted file mode 100644
index 211346f..0000000
--- a/data/plots.c
+++ /dev/null
@@ -1,35 +0,0 @@
-enum PlotType {
- PLOT_LINES,
-};
-
-struct PlotDef {
- const char *name;
- const char *table;
- enum PlotType plot_type;
- const char **cols;
-};
-
-struct PlotDef g_general_plots_def[] = {
- { .name = "cycl", .table = "general", .plot_type = PLOT_LINES, .cols = (const char *[]){
-#define FOR_CORE(i) "cycl_" #i,
- FOR_CORES
-#undef FOR_CORE
- }},
- { .name = "mall", .table = "general", .plot_type = PLOT_LINES, .cols = (const char *[]){
-#define FOR_CORE(i) "mall_" #i,
- FOR_CORES
-#undef FOR_CORE
- }},
- { .name = "pnum", .table = "general", .plot_type = PLOT_LINES, .cols = (const char *[]){
-#define FOR_CORE(i) "pnum_" #i,
- FOR_CORES
-#undef FOR_CORE
- }},
- { .name = "ppop", .table = "general", .plot_type = PLOT_LINES, .cols = (const char *[]){
-#define FOR_CORE(i) "pfst_" #i, "plst_" #i,
- FOR_CORES
-#undef FOR_CORE
- }},
-};
-
-size_t g_general_plots_count = sizeof(g_general_plots_def) / sizeof(struct PlotDef);
diff --git a/data/server.c b/data/server.c
index f7f1121..c2fd276 100644
--- a/data/server.c
+++ b/data/server.c
@@ -25,7 +25,6 @@ void respond_name(int client_fd) {
json_object_to_fd(client_fd, sim_name, JSON_C_TO_STRING_PRETTY);
json_object_put(sim_name);
}
-break;
void respond_opts(int client_fd) {
log_info("Client requested simulation options");
diff --git a/salis.py b/salis.py
index f8f6ce0..7569430 100755
--- a/salis.py
+++ b/salis.py
@@ -23,7 +23,7 @@ epilog = f"Use '-h' to show command arguments; e.g. '{prog} new -h'"
parser = ArgumentParser(description="Salis: Simple A-Life Simulator", epilog=epilog, formatter_class=RawTextHelpFormatter, prog=prog)
sub_parsers = parser.add_subparsers(dest="command", required=True)
-formatter_class = lambda prog: ArgumentDefaultsHelpFormatter(max_help_position=32, prog=prog)
+formatter_class = lambda prog: ArgumentDefaultsHelpFormatter(max_help_position=48, prog=prog)
new = sub_parsers.add_parser("new", formatter_class=formatter_class, help="create new simulation")
load = sub_parsers.add_parser("load", formatter_class=formatter_class, help="load saved simulation")
@@ -62,13 +62,15 @@ options = {
(("C", "clones"), (new,), fmt_id): {"metavar": "N", "help": "number of ancestor clones on each core", "default": 1, "required": False, "type": nat},
(("c", "cores"), (new,), fmt_id): {"metavar": "N", "help": "number of simulator cores", "default": 2, "required": False, "type": nat},
(("d", "data-push-pow"), (new,), fmt_id): {"metavar": "POW", "help": "data aggregation interval exponent; interval = 2^{POW} >= {sync-pow}; a value of 0 disables data aggregation; requires 'sqlite' and 'zlib'", "default": 28, "required": False, "type": pos},
- (("F", "muta-flip"), (new,), fmt_id): {"action": "store_true", "help": "cosmic rays flip bits instead of randomizing whole bytes", "required": False},
(("f", "force"), (new,), fmt_id): {"action": "store_true", "help": "overwrite existing simulation of given name", "required": False},
- (("G", "compiler-flags"), (new, load, server, client), fmt_id): {"metavar": "FLAGS", "help": "base set of flags to pass to C compiler", "default": "-Wall -Wextra -Werror -pedantic", "required": False, "type": str},
- (("g", "compiler"), (new, load, server, client), fmt_id): {"metavar": "CC", "help": "C compiler to use", "default": "gcc", "required": False, "type": str},
+ (("F", "muta-flip"), (new,), fmt_id): {"action": "store_true", "help": "cosmic rays flip bits instead of randomizing whole bytes", "required": False},
+ (("g", "c-compiler"), (new, load, server, client), fmt_id): {"metavar": "CC", "help": "C compiler to use", "default": "gcc", "required": False, "type": str},
+ (("G", "c-compiler-flags"), (new, load, server, client), fmt_id): {"metavar": "FLAGS", "help": "base set of flags to pass to C compiler", "default": "-Wall -Wextra -Werror -pedantic", "required": False, "type": str},
+ (("g++", "cpp-compiler"), (client,), fmt_id): {"metavar": "CXX", "help": "C++ compiler to use", "default": "g++", "required": False, "type": str},
+ (("G++", "cpp-compiler-flags"), (client,), fmt_id): {"metavar": "FLAGS", "help": "base set of flags to pass to C++ compiler", "default": "-Wall -Wextra -Werror -pedantic", "required": False, "type": str},
(("H", "home"), (new, load, server), fmt_id): {"metavar": "PATH", "help": "salis home directory", "default": os.path.join(os.environ["HOME"], ".salis"), "required": False, "type": str},
- (("M", "muta-pow"), (new,), fmt_id): {"metavar": "POW", "help": "mutator range exponent; each step a cosmic ray hits addr, where addr = rand_uint64() %% 2^{POW}; lower values of POW mean higher mutation rates", "default": 32, "required": False, "type": pos},
(("i", "ip"), (client,), fmt_id): {"metavar": "IP", "help": "ip address of server", "default": "127.0.0.1", "required": False, "type": str},
+ (("M", "muta-pow"), (new,), fmt_id): {"metavar": "POW", "help": "mutator range exponent; each step a cosmic ray hits addr, where addr = rand_uint64() %% 2^{POW}; lower values of POW mean higher mutation rates", "default": 32, "required": False, "type": pos},
(("m", "mvec-pow"), (new,), fmt_id): {"metavar": "POW", "help": "memory core size exponent; size = 2^{POW}", "default": 20, "required": False, "type": pos},
(("n", "name"), (new, load, server), fmt_id): {"metavar": "NAME", "help": "name of new or loaded simulation", "default": "def.sim", "required": False, "type": str},
(("o", "optimized"), (new, load, server, client), fmt_id): {"action": "store_true", "help": "build with optimizations", "required": False},
@@ -93,22 +95,22 @@ args = parser.parse_args()
# Build class
# ------------------------------------------------------------------------------
class Build:
- def __init__(self, path, log, library=False):
+ def __init__(self, path, log, library=False, cpp=False):
self.log = log
self.library = library
self.tempdir = TemporaryDirectory(prefix="salis_", delete=not args.keep_temp_dir)
- self.log.info(f"Generated temporary directory for C builds at: {self.tempdir.name}")
+ self.log.info(f"Generated temporary directory for builds at: {self.tempdir.name}")
self.name = os.path.splitext(os.path.basename(path))[0]
self.binfile = os.path.join(self.tempdir.name, f"{self.name}{".so" if library else ""}")
self.argsfile = os.path.join(self.tempdir.name, f"{self.name}.arg")
- self.flags = {*args.compiler_flags.split(), *({"-shared", "-fPIC"} if library else set()), *({"-O3"} if args.optimized else {"-ggdb"})}
+ self.flags = {*(args.cpp_compiler_flags if cpp else args.c_compiler_flags).split(), *({"-shared", "-fPIC"} if library else set()), *({"-O3"} if args.optimized else {"-ggdb"})}
self.defines = {"-DNDEBUG"} if args.optimized else set()
self.links = set()
- self.build_cmd = [args.compiler, f"@{self.argsfile}", path, "-o", self.binfile]
+ self.build_cmd = [args.cpp_compiler if cpp else args.c_compiler, f"@{self.argsfile}", path, "-o", self.binfile]
self.log.info(f"Build class initialized for {"library" if library else "executable"}: {path}")
self.log.info(f"Compiler flags stored at: {self.argsfile}")
@@ -431,12 +433,15 @@ if args.command == "server":
# Populate for client
if args.command == "client":
- ns.b = Build("data/client.c", log)
+ ns.b = Build("data/client.cpp", log, cpp=True)
pop_net_vars()
pop_general()
ns.b.defines.add(f"-DIP=\"{args.ip}\"")
- ns.b.defines.add("-DNCURSES_WIDECHAR=1")
- ns.b.links.add("-lcurses")
+ ns.b.links.add("-lGL")
+ ns.b.links.add("-lglfw")
+ ns.b.links.add("-limgui")
+ ns.b.links.add("-limplot")
+ ns.b.links.add("-lm")
# ------------------------------------------------------------------------------
# Build and launch executable
diff --git a/ui/curses/ui.c b/ui/curses/ui.c
index 9542287..287745b 100644
--- a/ui/curses/ui.c
+++ b/ui/curses/ui.c
@@ -718,10 +718,10 @@ void tui_info_impl(const char *format, ...) {
va_list args;
va_start(args, format);
- log_msg_to_buff(g_logs[g_log_ptr], LOG_LINE_SIZE, LOG_INFO, false, format, args);
+ log_msg_to_buff(g_logs[g_log_ptr], LOG_LINE_SIZE, INFO, false, format, args);
va_end(args);
- g_log_levels[g_log_ptr] = LOG_INFO;
+ g_log_levels[g_log_ptr] = INFO;
g_log_cnt++;
g_log_ptr = (g_log_ptr + 1) % LOG_LINE_COUNT;
}
@@ -731,10 +731,10 @@ void tui_warn_impl(const char *format, ...) {
va_list args;
va_start(args, format);
- log_msg_to_buff(g_logs[g_log_ptr], LOG_LINE_SIZE, LOG_WARN, false, format, args);
+ log_msg_to_buff(g_logs[g_log_ptr], LOG_LINE_SIZE, WARN, false, format, args);
va_end(args);
- g_log_levels[g_log_ptr] = LOG_WARN;
+ g_log_levels[g_log_ptr] = WARN;
g_log_cnt++;
g_log_ptr = (g_log_ptr + 1) % LOG_LINE_COUNT;
}
@@ -751,7 +751,7 @@ void tui_print_log_line(unsigned lptr, int line) {
tui_clear_log_line(line);
if (strlen(g_logs[lptr])) {
- tui_field(line, PANE_AND_MARGIN_WIDTH, g_log_levels[lptr] == LOG_INFO ? PAIR_INFO : PAIR_WARN, A_NORMAL, "%.38s", g_logs[lptr]);
+ tui_field(line, PANE_AND_MARGIN_WIDTH, g_log_levels[lptr] == INFO ? PAIR_INFO : PAIR_WARN, A_NORMAL, "%.38s", g_logs[lptr]);
tui_field(line, PANE_AND_MARGIN_WIDTH + 38, PAIR_NORMAL, A_NORMAL, g_logs[lptr] + 38);
}
}