From 446a32d0e301285e54fa1030fb2138b0169d3fae Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Mon, 2 May 2022 05:53:27 -0700 Subject: web: move control logic to separate file --- web/dartboat_wasm.c | 301 +--------------------------------------------------- web/web_control.c | 257 ++++++++++++++++++++++++++++++++++++++++++++ web/web_control.h | 18 ++++ web/web_prompt.c | 57 ++++++++-- web/web_prompt.h | 5 + 5 files changed, 329 insertions(+), 309 deletions(-) create mode 100644 web/web_control.c create mode 100644 web/web_control.h diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c index c245771..42535aa 100644 --- a/web/dartboat_wasm.c +++ b/web/dartboat_wasm.c @@ -1,314 +1,15 @@ -#include "web_match.h" +#include "web_control.h" #include "web_opts.h" #include "web_prompt.h" #include "web_svg.h" -#include "web_ui.h" -#include "checkouts.h" #include "comp.h" -#include #include -#include -#include #include #include -#include "web_match.h" - -void set_prompt_mode(enum prompt_mode mode) -{ - pm = mode; - - if (pm != PM_DARTBOARD) - EM_ASM(setPromptActive()); - else - EM_ASM(setPromptInactive()); - - EM_ASM({setKeypad($0)}, pm == PM_DARTBOARD ? "dartboard" : - pm == PM_SELECT_MODE ? "select_mode" : "default"); -} - -void set_active_player(int pn) -{ - state->active_player = pn; - state->active_leg = state->legs[pn-1]; - EM_ASM({setPlayerActive($0)}, pn); - - if (state->mode == M_PVC && pn == 2) { - EM_ASM({promptMsgL($0)}, "Bot is throwing…"); - set_prompt_mode(PM_DARTBOARD); - } else { - EM_ASM({promptMsgL($0)}, "Enter points:"); - EM_ASM({setKeyLabel($0, $1)}, "submit", "OK"); - EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING"); - set_prompt_mode(PM_VISIT); - } - EM_ASM({promptMsgR($0)}, ""); -} - -void toggle_active_player() -{ - set_active_player(3 - state->active_player); -} - -EMSCRIPTEN_KEEPALIVE -void update_user_rem_from_pts(int pts) -{ - update_player_rem(state->active_player, state->active_leg->rem - pts); -} - -void handle_next(); -EMSCRIPTEN_KEEPALIVE -void end_boat_visit(int rem, double avg) -{ - EM_ASM(svgClearPoints()); - update_player_rem(2, rem); - EM_ASM({updatePlayerAvg($0, $1)}, 2, avg); - EM_ASM({setPromptInput($0)}, ""); - EM_ASM({promptMsgR($0)}, ""); - - draw_visits(); - handle_next(); -} - -EMSCRIPTEN_KEEPALIVE -void boat_visit() -{ - struct leg *l = state->legs[1]; - if (state->boat_undone) { - --state->boat_undone; - l->rem = l->visits[l->n_visits++].rem; - } else { - comp_visit(l); - } - - struct visit *v = l->visits + l->n_visits - 1; - double avg = v->rem > 0 ? - (double)(l->start - l->rem) / l->n_visits : - (double)l->start / (((l->n_visits - 1) * 3) + v->n_darts) * 3; - - if (!delay_ms) { - end_boat_visit(l->rem, avg); - return; - } - - int pts = 0; - char str[15] = {0}; - size_t len_str = 0; - - for (int i = 0; i < v->n_darts; ++i) { - pts += segment_points(v->darts[i]); - char *seg_name = segment_name(v->darts[i]); - len_str += sprintf(str + len_str, i ? "-%s" : "%s", seg_name); - free(seg_name); - - struct ccoords c = v->ccoords[i]; - - char *tmp = malloc(len_str + 1); // free in draw_boat_throwing - memcpy(tmp, str, len_str + 1); - EM_ASM({scheduleCCall($0, $1, $2, $3, $4, $5)}, "draw_boat_throwing", - delay_ms * (i+1), pts, tmp, c.x, c.y); - } - - EM_ASM({scheduleCCall($0, $1, $2, $3)}, "end_boat_visit", - delay_ms * (v->n_darts + 1), l->rem, avg); -} - -void prompt_num_darts() -{ - set_prompt_mode(PM_NUM_DARTS); - EM_ASM({promptMsgL($0)}, "Darts needed?"); - EM_ASM({promptMsgR($0)}, ""); - EM_ASM({setKeyLabel($0, $1)}, "submit", "OK"); - EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING"); -} - -void prompt_end_match() -{ - EM_ASM(setPlayerActive()); // sets all inactive - set_prompt_mode(PM_END_MATCH); - EM_ASM({promptMsgL($0)}, - state->mode == M_PVC && state->legs[1]->rem <= 0 ? "Bot wins. :(" : - "You win! :)"); - EM_ASM({promptMsgR($0)}, ""); - EM_ASM({setKeyLabel($0, $1)}, "submit", "END MATCH"); - EM_ASM({setKeyLabel($0, $1)}, "rem", "REMATCH"); -} - -void prompt_select_mode() -{ - for (int pn = 1; pn < 3; ++pn) { - EM_ASM({hidePlayerInfo($0)}, pn); - clear_player_info(pn); - } - EM_ASM(clearVisits()); - - set_prompt_mode(PM_SELECT_MODE); - EM_ASM({promptMsgL($0)}, "Select match mode:"); - EM_ASM({promptMsgR($0)}, ""); -} - -void handle_next() -{ - if (!state) { - prompt_select_mode(); - } else if (is_match_over()) { - if (state->num_darts || - (state->mode == M_PVC && state->legs[1]->rem <= 0)) - prompt_end_match(); - else - prompt_num_darts(); - } else { - if (state->mode == M_P) { - set_active_player(1); - } else { - if (state->active_player) - toggle_active_player(); - else - set_active_player(1); - - if (state->mode == M_PVC && state->active_player == 2) - boat_visit(); - } - } -} - -EMSCRIPTEN_KEEPALIVE -void user_visit(int points) -{ - if (!is_points_valid(points, state->active_leg->rem)) { - EM_ASM(oi()); - return; - } - - struct leg *l = state->active_leg; - if (l->n_visits == l->size_visits) - leg_grow_visits(l); - struct visit *v = l->visits + l->n_visits++; - v->points = points; - l->rem -= points; - v->rem = l->rem; - update_player_rem(state->active_player, l->rem); - - if (v->rem > 0) - update_player_avg(state->active_player, 0); - - draw_visits(); - handle_next(); -} - -EMSCRIPTEN_KEEPALIVE -void user_visit_to_rem(int rem) -{ - user_visit(state->legs[0]->rem - rem); -} - -EMSCRIPTEN_KEEPALIVE -void user_undo() -{ - if (!state->legs[0]->n_visits) { - EM_ASM(oi()); - return; - } - - if (state->num_darts) { - state->num_darts = 0; - EM_ASM({updatePlayerAvg($0, $1)}, state->active_player, - ((double)(state->active_leg->start - - state->active_leg->visits[ - state->active_leg->n_visits-2].rem) / - (state->active_leg->n_visits-1))); - handle_next(); - return; - } - - if (state->mode == M_PVC) { - set_active_player(1); - } else if (state->mode == M_PVP) { - if (is_match_over()) - set_active_player(state->active_player); - else - toggle_active_player(); - } - - struct leg *l = state->active_leg; - struct visit *v = l->visits + --l->n_visits; - l->rem += v->points; - memcpy(v, 0, sizeof(*v)); - - if (state->mode == M_PVC && state->legs[1]->n_visits > l->n_visits) { - state->legs[1]->rem += - state->legs[1]->visits[--state->legs[1]->n_visits].points; - ++state->boat_undone; - } - - update_player_avg(state->active_player, 0); - update_player_rem(state->active_player, l->rem); - if (state->mode == M_PVC) { - update_player_avg(2, 0); - update_player_rem(2, state->legs[1]->rem); - } - - draw_visits(); - - if (state->mode != M_P) // FIXME avoid double toggle? - toggle_active_player(); - handle_next(); -} - -EMSCRIPTEN_KEEPALIVE -void user_num_darts(int n) -{ - if (n < 1 || n > 3) { - EM_ASM(oi()); - return; - } - - state->num_darts = n; - update_player_avg(state->active_player, n); - - handle_next(); -} - -EMSCRIPTEN_KEEPALIVE -void start_match(int mode) -{ - if (mode < M_FIRST || mode > M_LAST) { - EM_ASM(oi()); - return; - } - - if (state) free_state(); // rematch gets us here - state = calloc(1, sizeof(*state)); - state->mode = mode; - state->legs[0] = leg_init(501, mode == M_PVP ? "Player 1" : "User"); - 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_rem(1, state->legs[0]->rem); - EM_ASM({updatePlayerAvg($0, $1)}, 1, 0); - - if (mode != M_P) { - EM_ASM({showPlayerInfo($0)}, 2); - EM_ASM({updatePlayerName($0, $1)}, 2, state->legs[1]->name); - update_player_rem(2, state->legs[1]->rem); - EM_ASM({updatePlayerAvg($0, $1)}, 2, 0); - } - - draw_visits(); - handle_next(); -} - -EMSCRIPTEN_KEEPALIVE -void end_match() -{ - if (state) free_state(); - handle_next(); -} - EMSCRIPTEN_KEEPALIVE void init() { diff --git a/web/web_control.c b/web/web_control.c new file mode 100644 index 0000000..b1e20bc --- /dev/null +++ b/web/web_control.c @@ -0,0 +1,257 @@ +#include "web_control.h" +#include "web_match.h" +#include "web_opts.h" +#include "web_prompt.h" +#include "web_ui.h" + +#include "comp.h" + +#include +#include +#include + +#include + +void set_active_player(int pn) +{ + state->active_player = pn; + state->active_leg = state->legs[pn-1]; + EM_ASM({setPlayerActive($0)}, pn); + + if (state->mode == M_PVC && pn == 2) { + EM_ASM({promptMsgL($0)}, "Bot is throwing…"); + set_prompt_mode(PM_DARTBOARD); + } else { + EM_ASM({promptMsgL($0)}, "Enter points:"); + EM_ASM({setKeyLabel($0, $1)}, "submit", "OK"); + EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING"); + set_prompt_mode(PM_VISIT); + } + EM_ASM({promptMsgR($0)}, ""); +} + +void toggle_active_player() +{ + set_active_player(3 - state->active_player); +} + +EMSCRIPTEN_KEEPALIVE +void update_user_rem_from_pts(int pts) +{ + update_player_rem(state->active_player, state->active_leg->rem - pts); +} + +EMSCRIPTEN_KEEPALIVE +void end_boat_visit(int rem, double avg) +{ + EM_ASM(svgClearPoints()); + update_player_rem(2, rem); + EM_ASM({updatePlayerAvg($0, $1)}, 2, avg); + EM_ASM({setPromptInput($0)}, ""); + EM_ASM({promptMsgR($0)}, ""); + + draw_visits(); + handle_next(); +} + +EMSCRIPTEN_KEEPALIVE +void boat_visit() +{ + struct leg *l = state->legs[1]; + if (state->boat_undone) { + --state->boat_undone; + l->rem = l->visits[l->n_visits++].rem; + } else { + comp_visit(l); + } + + struct visit *v = l->visits + l->n_visits - 1; + double avg = v->rem > 0 ? + (double)(l->start - l->rem) / l->n_visits : + (double)l->start / (((l->n_visits - 1) * 3) + v->n_darts) * 3; + + if (!delay_ms) { + end_boat_visit(l->rem, avg); + return; + } + + int pts = 0; + char str[15] = {0}; + size_t len_str = 0; + + for (int i = 0; i < v->n_darts; ++i) { + pts += segment_points(v->darts[i]); + char *seg_name = segment_name(v->darts[i]); + len_str += sprintf(str + len_str, i ? "-%s" : "%s", seg_name); + free(seg_name); + + struct ccoords c = v->ccoords[i]; + + char *tmp = malloc(len_str + 1); // free in draw_boat_throwing + memcpy(tmp, str, len_str + 1); + EM_ASM({scheduleCCall($0, $1, $2, $3, $4, $5)}, "draw_boat_throwing", + delay_ms * (i+1), pts, tmp, c.x, c.y); + } + + EM_ASM({scheduleCCall($0, $1, $2, $3)}, "end_boat_visit", + delay_ms * (v->n_darts + 1), l->rem, avg); +} + +void handle_next() +{ + if (!state) { + prompt_select_mode(); + } else if (is_match_over()) { + if (state->num_darts || + (state->mode == M_PVC && state->legs[1]->rem <= 0)) + prompt_end_match(); + else + prompt_num_darts(); + } else { + if (state->mode == M_P) { + set_active_player(1); + } else { + if (state->active_player) + toggle_active_player(); + else + set_active_player(1); + + if (state->mode == M_PVC && state->active_player == 2) + boat_visit(); + } + } +} + +EMSCRIPTEN_KEEPALIVE +void user_visit(int points) +{ + if (!is_points_valid(points, state->active_leg->rem)) { + EM_ASM(oi()); + return; + } + + struct leg *l = state->active_leg; + if (l->n_visits == l->size_visits) + leg_grow_visits(l); + struct visit *v = l->visits + l->n_visits++; + v->points = points; + l->rem -= points; + v->rem = l->rem; + update_player_rem(state->active_player, l->rem); + + if (v->rem > 0) + update_player_avg(state->active_player, 0); + + draw_visits(); + handle_next(); +} + +EMSCRIPTEN_KEEPALIVE +void user_visit_to_rem(int rem) +{ + user_visit(state->legs[0]->rem - rem); +} + +EMSCRIPTEN_KEEPALIVE +void user_undo() +{ + if (!state->legs[0]->n_visits) { + EM_ASM(oi()); + return; + } + + if (state->num_darts) { + state->num_darts = 0; + EM_ASM({updatePlayerAvg($0, $1)}, state->active_player, + ((double)(state->active_leg->start - + state->active_leg->visits[ + state->active_leg->n_visits-2].rem) / + (state->active_leg->n_visits-1))); + handle_next(); + return; + } + + if (state->mode == M_PVC) { + set_active_player(1); + } else if (state->mode == M_PVP) { + if (is_match_over()) + set_active_player(state->active_player); + else + toggle_active_player(); + } + + struct leg *l = state->active_leg; + struct visit *v = l->visits + --l->n_visits; + l->rem += v->points; + memcpy(v, 0, sizeof(*v)); + + if (state->mode == M_PVC && state->legs[1]->n_visits > l->n_visits) { + state->legs[1]->rem += + state->legs[1]->visits[--state->legs[1]->n_visits].points; + ++state->boat_undone; + } + + update_player_avg(state->active_player, 0); + update_player_rem(state->active_player, l->rem); + if (state->mode == M_PVC) { + update_player_avg(2, 0); + update_player_rem(2, state->legs[1]->rem); + } + + draw_visits(); + + if (state->mode != M_P) // FIXME avoid double toggle? + toggle_active_player(); + handle_next(); +} + +EMSCRIPTEN_KEEPALIVE +void user_num_darts(int n) +{ + if (n < 1 || n > 3) { + EM_ASM(oi()); + return; + } + + state->num_darts = n; + update_player_avg(state->active_player, n); + + handle_next(); +} + +EMSCRIPTEN_KEEPALIVE +void start_match(int mode) +{ + if (mode < M_FIRST || mode > M_LAST) { + EM_ASM(oi()); + return; + } + + if (state) free_state(); // rematch gets us here + state = calloc(1, sizeof(*state)); + state->mode = mode; + state->legs[0] = leg_init(501, mode == M_PVP ? "Player 1" : "User"); + 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_rem(1, state->legs[0]->rem); + EM_ASM({updatePlayerAvg($0, $1)}, 1, 0); + + if (mode != M_P) { + EM_ASM({showPlayerInfo($0)}, 2); + EM_ASM({updatePlayerName($0, $1)}, 2, state->legs[1]->name); + update_player_rem(2, state->legs[1]->rem); + EM_ASM({updatePlayerAvg($0, $1)}, 2, 0); + } + + draw_visits(); + handle_next(); +} + +EMSCRIPTEN_KEEPALIVE +void end_match() +{ + if (state) free_state(); + handle_next(); +} diff --git a/web/web_control.h b/web/web_control.h new file mode 100644 index 0000000..33cbd2c --- /dev/null +++ b/web/web_control.h @@ -0,0 +1,18 @@ +#ifndef WEB_CONTROL_H +#define WEB_CONTROL_H + +void set_active_player(int pn); +void toggle_active_player(); + +void start_match(int mode); +void end_match(); +void user_visit(int points); +void user_num_darts(int n); +void user_undo(); +void user_visit_to_rem(int rem); +void update_user_rem_from_pts(int pts); +void end_boat_visit(int rem, double avg); + +void handle_next(); + +#endif diff --git a/web/web_prompt.c b/web/web_prompt.c index 64a23fd..abc5a05 100644 --- a/web/web_prompt.c +++ b/web/web_prompt.c @@ -1,3 +1,4 @@ +#include "web_control.h" #include "web_prompt.h" #include "web_match.h" #include "web_ui.h" @@ -7,17 +8,55 @@ #include -// FIXME forward declaring these until the code is better modularised -void start_match(int mode); -void user_num_darts(int n); -void user_visit(int points); -void user_visit_to_rem(int rem); -void end_match(); -void update_user_rem_from_pts(int pts); -void user_undo(); - enum prompt_mode pm; +void set_prompt_mode(enum prompt_mode mode) +{ + pm = mode; + + if (pm != PM_DARTBOARD) + EM_ASM(setPromptActive()); + else + EM_ASM(setPromptInactive()); + + EM_ASM({setKeypad($0)}, pm == PM_DARTBOARD ? "dartboard" : + pm == PM_SELECT_MODE ? "select_mode" : "default"); +} + +void prompt_num_darts() +{ + set_prompt_mode(PM_NUM_DARTS); + EM_ASM({promptMsgL($0)}, "Darts needed?"); + EM_ASM({promptMsgR($0)}, ""); + EM_ASM({setKeyLabel($0, $1)}, "submit", "OK"); + EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING"); +} + +void prompt_end_match() +{ + EM_ASM(setPlayerActive()); // sets all inactive + set_prompt_mode(PM_END_MATCH); + EM_ASM({promptMsgL($0)}, + state->mode == M_PVC && state->legs[1]->rem <= 0 ? "Bot wins. :(" : + "You win! :)"); + EM_ASM({promptMsgR($0)}, ""); + EM_ASM({setKeyLabel($0, $1)}, "submit", "END MATCH"); + EM_ASM({setKeyLabel($0, $1)}, "rem", "REMATCH"); +} + +void prompt_select_mode() +{ + for (int pn = 1; pn < 3; ++pn) { + EM_ASM({hidePlayerInfo($0)}, pn); + clear_player_info(pn); + } + EM_ASM(clearVisits()); + + set_prompt_mode(PM_SELECT_MODE); + EM_ASM({promptMsgL($0)}, "Select match mode:"); + EM_ASM({promptMsgR($0)}, ""); +} + char *prompt_get() { return (char *)EM_ASM_INT({return promptGet()}); diff --git a/web/web_prompt.h b/web/web_prompt.h index b416f2a..e70f779 100644 --- a/web/web_prompt.h +++ b/web/web_prompt.h @@ -11,6 +11,11 @@ enum prompt_mode { extern enum prompt_mode pm; +void set_prompt_mode(enum prompt_mode mode); void prompt_handle(char *command, char *data); +void prompt_num_darts(); +void prompt_end_match(); +void prompt_select_mode(); + #endif -- cgit v1.2.3-70-g09d2