From a4f1e60ece6dac22c4d913fc70124873803f30ab Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Fri, 20 May 2022 01:38:05 -0700 Subject: web: add (incomplete) support for 3+ player matches --- web/static/dartboat.js | 5 ++ web/static/fonts/bootstrap-icons-sub.woff2 | Bin 1088 -> 1116 bytes web/static/index.html | 2 + web/static/style.css | 50 +++++++++++ web/web_control.c | 22 ++--- web/web_match.c | 2 +- web/web_match.h | 3 +- web/web_prompt.c | 5 +- web/web_scoreboard.c | 128 ++++++++++++++++++++++++++--- web/web_scoreboard.h | 4 +- 10 files changed, 193 insertions(+), 28 deletions(-) diff --git a/web/static/dartboat.js b/web/static/dartboat.js index 54cb29b..5c7f011 100644 --- a/web/static/dartboat.js +++ b/web/static/dartboat.js @@ -185,6 +185,11 @@ document.addEventListener('DOMContentLoaded', () => { e.currentTarget.style.display = 'none'; }; $$('.modal').forEach(x => x.addEventListener('click', f)); + + $('#info-slot-prev').addEventListener('click', () => + _scoreboard_prev_slot()); + $('#info-slot-next').addEventListener('click', () => + _scoreboard_next_slot()); }); document.addEventListener('keydown', e => { diff --git a/web/static/fonts/bootstrap-icons-sub.woff2 b/web/static/fonts/bootstrap-icons-sub.woff2 index 391919f..116a249 100644 Binary files a/web/static/fonts/bootstrap-icons-sub.woff2 and b/web/static/fonts/bootstrap-icons-sub.woff2 differ diff --git a/web/static/index.html b/web/static/index.html index 8da5baa..196db91 100644 --- a/web/static/index.html +++ b/web/static/index.html @@ -24,6 +24,8 @@
oi!
+
+
diff --git a/web/static/style.css b/web/static/style.css index 5131eab..f8b6ea0 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -473,6 +473,56 @@ body { visibility: visible; } +#info #info-slot-prev, #info #info-slot-next { + visibility: hidden; + + color: #eee; + background-color: #583a90; + font-size: 2em; + height: 1.6em; + width: 1em; + + outline: #111 solid 2px; + + position: absolute; + + display: flex; + align-items: center; + justify-content: center; +} + +#info #info-slot-prev { + left: 0%; + right: 100%; + top: 50%; + bottom: 50%; + transform: translate(0%, -50%); +} + +#info #info-slot-next { + left: 100%; + right: 0%; + top: 50%; + bottom: 50%; + transform: translate(-100%, -50%); +} + +#info #info-slot-prev.visible, #info #info-slot-next.visible { + visibility: visible; +} + +@media (hover: hover) and (pointer: fine) { + #info #info-slot-prev:hover, #info #info-slot-next:hover { + color: #fff; + background-color: #6e49b4; + } +} + +#info #info-slot-prev:active, #info #info-slot-next:active { + color: #fff; + background-color: #7b51ca; +} + #info #p1-info, #info #p2-info { background-color: #222; font-size: 1.5em; diff --git a/web/web_control.c b/web/web_control.c index 74d42e2..5389a23 100644 --- a/web/web_control.c +++ b/web/web_control.c @@ -260,6 +260,9 @@ void match_mode_selected(int mode) match_opts->p1_type = PT_COMP; match_opts->p2_name = "Computer 2"; match_opts->p2_type = PT_COMP; + } else if (mode == M_PVPVP) { + match_opts->p1_name = "Player 1"; + match_opts->p2_name = "Player 2"; } prompt_match_opts(); @@ -273,17 +276,14 @@ void start_match() match_opts->p1_name); match_add_player(match_opts->start_pts, match_opts->p2_type, match_opts->p2_name ? match_opts->p2_name : "oi"); - - show_player_info(1); - update_player_name(1, state->legs[0]->name); - update_player_rem(1, state->legs[0]->rem); - update_player_avg(1, 0); - - if (match_num_players() != 1) { - show_player_info(2); - update_player_name(2, state->legs[1]->name); - update_player_rem(2, state->legs[1]->rem); - update_player_avg(2, 0); + if (match_opts->mode == M_PVPVP) + match_add_player(match_opts->start_pts, PT_USER, "Player 3"); + + scoreboard_show_info(match_num_players()); + for (int i = 1; i <= match_num_players(); ++i) { + update_player_name(i, state->legs[i - 1]->name); + update_player_rem(i, state->legs[i - 1]->rem); + update_player_avg(i, 0); } dom_enable_exit_dialogue(true); diff --git a/web/web_match.c b/web/web_match.c index bdd049d..793aedd 100644 --- a/web/web_match.c +++ b/web/web_match.c @@ -72,7 +72,7 @@ int match_num_players() if (state->mode == M_P) return 1; - return 2; + return state->num_players; } int match_winning_player() diff --git a/web/web_match.h b/web/web_match.h index 715be76..0654eb7 100644 --- a/web/web_match.h +++ b/web/web_match.h @@ -9,7 +9,8 @@ enum match_mode { M_P, M_PVP, M_CVC, - M_LAST = M_CVC + M_PVPVP, + M_LAST = M_PVPVP }; enum player_type { diff --git a/web/web_prompt.c b/web/web_prompt.c index c9e4f55..ad907bc 100644 --- a/web/web_prompt.c +++ b/web/web_prompt.c @@ -185,9 +185,7 @@ void prompt_end_match() void prompt_select_mode() { - dom_set_uniq_class(NULL, "visible", "[id$=-info-inner]"); - for (int pn = 1; pn < 3; ++pn) - clear_player_info(pn); + scoreboard_hide_info(); dom_set_content("#visits", NULL); set_prompt_mode(PM_SELECT_MODE); @@ -199,6 +197,7 @@ void prompt_select_mode() add_list_opt("One-player scoreboard"); add_list_opt("Two-player scoreboard"); add_list_opt("Computer vs computer"); + add_list_opt("Three-player scoreboard"); flush_list_opts(); } diff --git a/web/web_scoreboard.c b/web/web_scoreboard.c index fa1a672..79bddb2 100644 --- a/web/web_scoreboard.c +++ b/web/web_scoreboard.c @@ -15,20 +15,106 @@ static struct { bufstr name, rem, sugg, avg; -} bufs[2]; +} bufs[4]; -void scoreboard_set_player_active(int pn) +#define NUM_SLOTS 2 +static int slots[NUM_SLOTS]; +static int active_pn = -1; + +static void flush_slot(int slot) +{ + int pn = slots[slot - 1]; + if (pn == -1) return; + + // FIXME: should be combined with flushing player info + char sel[32]; + int len = sprintf(sel, "#p%d-", slot); + strcpy(sel + len, "name"); + dom_set_content(sel, bufstr_flush(&bufs[pn-1].name)); + strcpy(sel + len, "rem"); + dom_set_content(sel, bufstr_flush(&bufs[pn-1].rem)); + strcpy(sel + len, "sugg"); + dom_set_content(sel, bufstr_flush(&bufs[pn-1].sugg)); + strcpy(sel + len, "avg"); + dom_set_content(sel, bufstr_flush(&bufs[pn-1].avg)); +} + +static int player_slot(int pn) +{ + for (int i = 0; i < NUM_SLOTS; ++i) { + if (slots[i] == pn) + return i + 1; + } + + return -1; +} + +static void set_slot_player(int slot, int pn) +{ + if (slots[slot - 1] != pn) { + slots[slot - 1] = pn; + flush_slot(slot); + } +} + +static void set_slot_active(int slot) { char buf[64], *sel = buf; - if (pn == -1) + if (slot == -1) sel = NULL; else - sprintf(sel, "#p%d-info", pn); + sprintf(sel, "#p%d-info", slot); dom_set_uniq_class(sel, "active", "[id$=-info]"); } +EMSCRIPTEN_KEEPALIVE +void scoreboard_prev_slot() +{ + set_slot_player(2, slots[0]); + set_slot_player(1, slots[1] == 1 ? match_num_players() : slots[1] - 1); + set_slot_active(player_slot(active_pn)); +} + +EMSCRIPTEN_KEEPALIVE +void scoreboard_next_slot() +{ + set_slot_player(1, slots[1]); + set_slot_player(2, slots[0] == match_num_players() ? 1 : slots[0] + 1); + set_slot_active(player_slot(active_pn)); +} + +void scoreboard_set_player_active(int pn) +{ + active_pn = pn; + + if (pn == -1) { + set_slot_active(-1); + return; + } + + int np = match_num_players(); + int slot1, slot2, pslot; + if (np == 1) { + slot1 = 1; + slot2 = -1; + pslot = 1; + } else if (np == 2) { + slot1 = 1; + slot2 = 2; + pslot = pn == 1 ? 1 : 2; + } else { + slot1 = pn; + slot2 = pn == np ? 1 : pn + 1; + pslot = 1; + } + + set_slot_player(1, slot1); + set_slot_player(2, slot2); + set_slot_active(pslot); +} + void scoreboard_set_player_name(int pn, char *str) { bufstr_buf(&bufs[pn-1].name, str); @@ -53,8 +139,11 @@ void scoreboard_set_player_avg(int pn, double avg) void scoreboard_flush_player_info(int pn) { + int slot = player_slot(pn); + if (slot == -1) return; + char sel[32]; - int len = sprintf(sel, "#p%d-", pn); + int len = sprintf(sel, "#p%d-", slot); if (bufstr_changed(&bufs[pn-1].name)) { strcpy(sel + len, "name"); @@ -133,14 +222,23 @@ void update_player_rem(int pn, int rem) update_player_sugg(pn, rem); } -void show_player_info(int pn) +void scoreboard_show_info(int num_players) { - char sel[64]; - sprintf(sel, "#p%d-info-inner", pn); - dom_add_class(sel, "visible"); + set_slot_player(1, 1); + dom_add_class("#p1-info-inner", "visible"); + + if (num_players > 1) { + set_slot_player(2, 2); + dom_add_class("#p2-info-inner", "visible"); + } + + if (num_players > 2) { + dom_add_class("#info-slot-prev", "visible"); + dom_add_class("#info-slot-next", "visible"); + } } -void clear_player_info(int pn) +static void clear_player_info(int pn) { scoreboard_set_player_name(pn, NULL); scoreboard_set_player_rem(pn, NULL); @@ -148,6 +246,16 @@ void clear_player_info(int pn) scoreboard_set_player_avg(pn, 0); } +void scoreboard_hide_info() +{ + dom_set_uniq_class(NULL, "visible", "[id$=-info-inner]"); + for (int pn = 1; pn < 4; ++pn) // FIXME + clear_player_info(pn); + + dom_remove_class("#info-slot-prev", "visible"); + dom_remove_class("#info-slot-next", "visible"); +} + static struct dom_elem *create_div(char *str, char *class) { struct dom_elem *e = dom_elem_init(NULL, "div", 1); diff --git a/web/web_scoreboard.h b/web/web_scoreboard.h index 6525654..c712b8e 100644 --- a/web/web_scoreboard.h +++ b/web/web_scoreboard.h @@ -15,8 +15,8 @@ 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); -void show_player_info(int pn); -void clear_player_info(int pn); +void scoreboard_show_info(int num_players); +void scoreboard_hide_info(); void draw_visits(); -- cgit v1.2.3-70-g09d2