From 237359d107c5f8fb3e1f7a3532696eb19a6c56fc Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Mon, 2 May 2022 15:20:34 -0700 Subject: web: buffer player info and flush on state change Constant calls from Wasm to JS to replace unchanged elements in the DOM is not very efficient. --- web/static/dartboat.js | 6 +-- web/web_control.c | 19 ++++++---- web/web_ui.c | 100 +++++++++++++++++++++++++++++++++++++++++++++---- web/web_ui.h | 6 +++ 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/web/static/dartboat.js b/web/static/dartboat.js index 8716185..13a5da4 100644 --- a/web/static/dartboat.js +++ b/web/static/dartboat.js @@ -98,15 +98,15 @@ function hidePlayerInfo(n) { } function updatePlayerName(n, ptr) { - $(`#p${n}-name`).textContent = UTF8ToString(ptr); + $(`#p${n}-name`).textContent = ptr && UTF8ToString(ptr); } function updatePlayerRem(n, ptr) { - $(`#p${n}-rem`).textContent = UTF8ToString(ptr); + $(`#p${n}-rem`).textContent = ptr && UTF8ToString(ptr); } function updatePlayerSugg(n, ptr) { - $(`#p${n}-sugg`).textContent = UTF8ToString(ptr); + $(`#p${n}-sugg`).textContent = ptr && UTF8ToString(ptr); } function updatePlayerAvg(n, avg) { diff --git a/web/web_control.c b/web/web_control.c index 13e37ec..4f78d67 100644 --- a/web/web_control.c +++ b/web/web_control.c @@ -33,6 +33,7 @@ EMSCRIPTEN_KEEPALIVE void update_user_rem_from_pts(int pts) { update_player_rem(state->active_player, state->active_leg->rem - pts); + ui_flush_player_info(state->active_player); } EMSCRIPTEN_KEEPALIVE @@ -40,7 +41,7 @@ void end_boat_visit(int rem, double avg) { EM_ASM(svgClearPoints()); update_player_rem(2, rem); - EM_ASM({updatePlayerAvg($0, $1)}, 2, avg); + ui_set_player_avg(2, avg); EM_ASM({setPromptInput($0)}, ""); EM_ASM({promptMsgR($0)}, ""); @@ -114,6 +115,8 @@ void handle_next() boat_visit(); } } + + ui_flush(); } EMSCRIPTEN_KEEPALIVE @@ -156,7 +159,7 @@ void user_undo() if (state->num_darts) { state->num_darts = 0; - EM_ASM({updatePlayerAvg($0, $1)}, state->active_player, + ui_set_player_avg(state->active_player, ((double)(state->active_leg->start - state->active_leg->visits[ state->active_leg->n_visits-2].rem) / @@ -186,10 +189,10 @@ void user_undo() ++state->boat_undone; } - update_player_avg(state->active_player, 0); + ui_set_player_avg(state->active_player, 0); update_player_rem(state->active_player, l->rem); if (state->mode == M_PVC) { - update_player_avg(2, 0); + ui_set_player_avg(2, 0); update_player_rem(2, state->legs[1]->rem); } @@ -229,15 +232,15 @@ void start_match(int mode) state->legs[1] = leg_init(501, mode == M_PVC ? "Bot" : "Player 2"); EM_ASM({showPlayerInfo($0)}, 1); - EM_ASM({updatePlayerName($0, $1)}, 1, state->legs[0]->name); + update_player_name(1, state->legs[0]->name); update_player_rem(1, state->legs[0]->rem); - EM_ASM({updatePlayerAvg($0, $1)}, 1, 0); + update_player_avg(1, 0); if (mode != M_P) { EM_ASM({showPlayerInfo($0)}, 2); - EM_ASM({updatePlayerName($0, $1)}, 2, state->legs[1]->name); + update_player_name(2, state->legs[1]->name); update_player_rem(2, state->legs[1]->rem); - EM_ASM({updatePlayerAvg($0, $1)}, 2, 0); + update_player_avg(2, 0); } draw_visits(); diff --git a/web/web_ui.c b/web/web_ui.c index 7ac4182..070b898 100644 --- a/web/web_ui.c +++ b/web/web_ui.c @@ -12,6 +12,90 @@ #include +struct player_info { + char *name, *rem, *sugg; + double avg; +}; + +struct player_info buffered_info[2], flushed_info[2]; + +static inline void buffer_str(char *str, char **buffer, char *flushed) +{ + if (str == *buffer || (str && *buffer && !strcmp(str, *buffer))) + return; + + if (*buffer && *buffer != flushed) + free(*buffer); + + *buffer = str ? strdup(str) : NULL; +} + +void ui_set_player_name(int pn, char *str) +{ + buffer_str(str, &buffered_info[pn-1].name, flushed_info[pn-1].name); +} + +void ui_set_player_rem(int pn, char *str) +{ + buffer_str(str, &buffered_info[pn-1].rem, flushed_info[pn-1].rem); +} + +void ui_set_player_sugg(int pn, char *str) +{ + buffer_str(str, &buffered_info[pn-1].sugg, flushed_info[pn-1].sugg); +} + +void ui_set_player_avg(int pn, double avg) +{ + buffered_info[pn-1].avg = avg; +} + +static inline bool buffered_str_changed(char *buffered, char *flushed) +{ + return (!buffered != !flushed) || + (buffered && flushed && strcmp(buffered, flushed)); +} + +static inline void free_flushed_str(char *flushed, char *buffered) +{ + if (flushed && flushed != buffered) + free(flushed); +} + +void ui_flush_player_info(int pn) +{ + if (buffered_str_changed(buffered_info[pn-1].name, + flushed_info[pn-1].name)) + EM_ASM({updatePlayerName($0, $1)}, pn, buffered_info[pn-1].name); + + if (buffered_str_changed(buffered_info[pn-1].rem, + flushed_info[pn-1].rem)) + EM_ASM({updatePlayerRem($0, $1)}, pn, buffered_info[pn-1].rem); + + if (buffered_str_changed(buffered_info[pn-1].sugg, + flushed_info[pn-1].sugg)) + EM_ASM({updatePlayerSugg($0, $1)}, pn, buffered_info[pn-1].sugg); + + if (buffered_info[pn-1].avg != flushed_info[pn-1].avg) + EM_ASM({updatePlayerAvg($0, $1)}, pn, buffered_info[pn-1].avg); + + free_flushed_str(flushed_info[pn-1].name, buffered_info[pn-1].name); + free_flushed_str(flushed_info[pn-1].rem, buffered_info[pn-1].rem); + free_flushed_str(flushed_info[pn-1].sugg, buffered_info[pn-1].sugg); + flushed_info[pn-1] = buffered_info[pn-1]; +} + +void ui_flush() +{ + ui_flush_player_info(1); + ui_flush_player_info(2); +} + +void update_player_name(int pn, char *str) +{ + ui_set_player_name(pn, str); +} + void update_player_sugg(int pn, int rem) { char str[15] = {0}, *p = str; @@ -25,13 +109,13 @@ void update_player_sugg(int pn, int rem) } } - EM_ASM({updatePlayerSugg($0, $1)}, pn, str); + ui_set_player_sugg(pn, str); } void update_player_avg(int pn, int n_darts) { struct leg *l = state->legs[pn-1]; - EM_ASM({updatePlayerAvg($0, $1)}, pn, + ui_set_player_avg(pn, l->n_visits ? (l->rem > 0 ? ((double)(l->start - l->rem) / l->n_visits) : ((double)l->start / (((l->n_visits - 1) * 3) + n_darts) * 3)) : @@ -88,17 +172,17 @@ void update_player_rem(int pn, int rem) else sprintf(str, "%d", rem); - EM_ASM({updatePlayerRem($0, $1)}, pn, str); + ui_set_player_rem(pn, str); if (pn == 1 || state->mode != M_PVC) update_player_sugg(pn, rem); } void clear_player_info(int pn) { - EM_ASM({updatePlayerName($0, $1)}, pn, ""); - EM_ASM({updatePlayerRem($0, $1)}, pn, ""); - EM_ASM({updatePlayerSugg($0, $1)}, pn, ""); - EM_ASM({updatePlayerAvg($0, $1)}, pn, 0); + ui_set_player_name(pn, ""); + ui_set_player_rem(pn, ""); + ui_set_player_sugg(pn, ""); + ui_set_player_avg(pn, 0); } EMSCRIPTEN_KEEPALIVE @@ -116,6 +200,8 @@ void draw_boat_throwing(int pts, char *str, double x, double y) EM_ASM({setPromptInput($0)}, pts_str); EM_ASM({promptMsgR($0)}, str); free(str); + + ui_flush_player_info(2); // FIXME bot hard-coded as player 2 } bool is_key_active(char *k) diff --git a/web/web_ui.h b/web/web_ui.h index fa961fb..a302e0a 100644 --- a/web/web_ui.h +++ b/web/web_ui.h @@ -3,6 +3,12 @@ #include +void ui_flush(); + +void ui_flush_player_info(int pn); +void ui_set_player_avg(int pn, double avg); + +void update_player_name(int pn, char *str); void update_player_sugg(int pn, int rem); void update_player_avg(int pn, int n_darts); void update_player_rem(int pn, int rem); -- cgit v1.2.3-70-g09d2