From 22646d963e2b0c9b5ef629aa7704158026cfa6d1 Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Sun, 1 May 2022 15:07:11 -0700 Subject: web: split code into more files This is currently very messy with all the files interdependent on one another and a lot of the logic still in the main file. It will take some time to refactor and clean up. --- web/dartboat_wasm.c | 158 +------------------------------- web/svg.c | 256 ---------------------------------------------------- web/svg.h | 7 -- web/web_match.c | 20 ++++ web/web_match.h | 29 ++++++ web/web_svg.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++ web/web_svg.h | 7 ++ web/web_ui.c | 134 +++++++++++++++++++++++++++ web/web_ui.h | 18 ++++ 9 files changed, 468 insertions(+), 417 deletions(-) delete mode 100644 web/svg.c delete mode 100644 web/svg.h create mode 100644 web/web_match.c create mode 100644 web/web_match.h create mode 100644 web/web_svg.c create mode 100644 web/web_svg.h create mode 100644 web/web_ui.c create mode 100644 web/web_ui.h (limited to 'web') diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c index 658277d..c43e73d 100644 --- a/web/dartboat_wasm.c +++ b/web/dartboat_wasm.c @@ -1,4 +1,5 @@ -#include "svg.h" +#include "web_svg.h" +#include "web_ui.h" #include "checkouts.h" #include "comp.h" @@ -11,6 +12,8 @@ #include +#include "web_match.h" + int delay_ms = 1000; enum prompt_mode { @@ -36,25 +39,6 @@ void set_prompt_mode(enum prompt_mode mode) pm == PM_SELECT_MODE ? "select_mode" : "default"); } -enum match_mode { - M_FIRST = 1, - M_PVC = M_FIRST, - M_P, - M_PVP, - M_LAST = M_PVP -}; - -struct match_state { - enum match_mode mode; - struct leg *legs[2]; - struct leg *active_leg; - int active_player; - int boat_undone; - int num_darts; -}; - -struct match_state *state; - void set_active_player(int pn) { state->active_player = pn; @@ -78,103 +62,11 @@ void toggle_active_player() set_active_player(3 - state->active_player); } -void update_player_sugg(int pn, int rem) -{ - char str[15] = {0}, *p = str; - - if (rem > 1 && rem <= 170) { - char *target; - int i = 3, trem = rem; - while (i && trem && (target = CHECKOUTS[--i][trem-1])) { - p += sprintf(p, i == 2 ? "%s" : "-%s", target); - trem -= segment_points(segment_from_name(target)); - } - } - - EM_ASM({updatePlayerSugg($0, $1)}, pn, str); -} - -bool is_match_over() -{ - return state->legs[0]->rem <= 0 || state->legs[1]->rem <= 0; -} - -void draw_visits() -{ - EM_ASM({clearVisits()}); - - char visit_no[10], p1_pts[10], p1_rem[10], - p2_pts[10], p2_rem[10], p2_darts[100]; - - sprintf(p1_rem, "%d", state->legs[0]->start); - sprintf(p2_rem, "%d", state->legs[1]->start); - EM_ASM({drawVisit($0, $1, $2, $3, $4, $5)}, - "0", "", p1_rem, "", state->mode == M_P ? "" : p2_rem, ""); - - int n_visits = state->legs[0]->n_visits > state->legs[1]->n_visits ? - state->legs[0]->n_visits : state->legs[1]->n_visits; - for (int i = 0; i < n_visits; ++i) { - visit_no[0] = p1_pts[0] = p1_rem[0] = - p2_pts[0] = p2_rem[0] = p2_darts[0] = 0; - - sprintf(visit_no, "%d", i + 1); - - struct visit *v = state->legs[0]->visits + i; - sprintf(p1_pts, "%d", v->points); - sprintf(p1_rem, "%d", v->rem); - - if (i < state->legs[1]->n_visits) { - v = state->legs[1]->visits + i; - sprintf(p2_pts, "%d", v->points); - sprintf(p2_rem, "%d", v->rem); - - for (int j = 0; j < v->n_darts; ++j) { - char *n = segment_name(v->darts[j]); - sprintf(p2_darts + (j ? (j*5 - 1) : 0), - j == 0 ? "%4s" : " %4s", n); - free(n); - } - } - - EM_ASM({drawVisit($0, $1, $2, $3, $4, $5)}, - visit_no, p1_pts, p1_rem, p2_pts, p2_rem, p2_darts); - } -} - -void update_player_rem(int pn, int rem) -{ - char str[5]; - if (rem < 0 || rem == 1) - strcpy(str, "BUST"); - else - sprintf(str, "%d", rem); - - EM_ASM({updatePlayerRem($0, $1)}, pn, str); - if (pn == 1 || state->mode != M_PVC) - update_player_sugg(pn, rem); -} - EMSCRIPTEN_KEEPALIVE void update_user_rem_from_pts(int pts) { update_player_rem(state->active_player, state->active_leg->rem - pts); } -EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str, double x, double y) -{ - char pts_str[10]; - sprintf(pts_str, "%d", pts); - - int rem = state->legs[1]->n_visits > 1 ? - state->legs[1]->visits[state->legs[1]->n_visits-2].rem : - state->legs[1]->start; - - svg_draw_point(x, y); - update_player_rem(2, rem - pts); - EM_ASM({setPromptInput($0)}, pts_str); - EM_ASM({promptMsgR($0)}, str); - free(str); -} - void handle_next(); EMSCRIPTEN_KEEPALIVE void end_boat_visit(int rem, double avg) { @@ -230,14 +122,6 @@ EMSCRIPTEN_KEEPALIVE void boat_visit() delay_ms * (v->n_darts + 1), l->rem, avg); } -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); -} - void prompt_num_darts() { set_prompt_mode(PM_NUM_DARTS); @@ -297,16 +181,6 @@ void handle_next() } } -void update_player_avg(int pn, int n_darts) -{ - struct leg *l = state->legs[pn-1]; - EM_ASM({updatePlayerAvg($0, $1)}, 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)) : - 0); -} - EMSCRIPTEN_KEEPALIVE void user_visit(int points) { if (!is_points_valid(points, state->active_leg->rem)) { @@ -400,15 +274,6 @@ EMSCRIPTEN_KEEPALIVE void user_num_darts(int n) handle_next(); } -void free_state() -{ - state->legs[1]->n_visits += state->boat_undone; // avoid memory leak - leg_free(state->legs[0]); - leg_free(state->legs[1]); - free(state); - state = NULL; -} - EMSCRIPTEN_KEEPALIVE void start_match(int mode) { if (mode < M_FIRST || mode > M_LAST) { @@ -466,21 +331,6 @@ void init_boat() EM_ASM({updateStdev($0)}, horizontal_stdev); } -bool is_key_active(char *k) -{ - return (EM_ASM_INT({return isKeyActive($0)}, k)); -} - -void toggle_key(char *k) -{ - EM_ASM({toggleKey($0)}, k); -} - -void deactivate_key(char *k) -{ - EM_ASM({deactivateKey($0)}, k); -} - char *prompt_get() { return (char *)EM_ASM_INT({return promptGet()}); diff --git a/web/svg.c b/web/svg.c deleted file mode 100644 index 6744ac6..0000000 --- a/web/svg.c +++ /dev/null @@ -1,256 +0,0 @@ -#include "svg.h" - -#include "board.h" -#include "comp.h" - -#include -#include -#include - -#include - -#define NUM_SECTORS 20 -#define SECTOR_WIDTH 18.0 - -#define C_BLACK "#272b2c" -#define C_WHITE "#fbe3ba" -#define C_RED "#f6302f" -#define C_GREEN "#22912d" -#define C_WIRE "#909ca0" -#define C_WIRE_INNER "#d8e6ec" - -struct elem { - char *name; - int n_attrs, size_attrs; - char **attr_names, **attr_vals; - char *content; -}; - -struct elem *elem_init(char *name, int size_attrs) -{ - struct elem *e = malloc(sizeof(*e)); - - size_t size = strlen(name) + 1; - e->name = malloc(size * sizeof(*(e->name))); - memcpy(e->name, name, size); - - e->n_attrs = 0; - e->size_attrs = size_attrs; - e->attr_names = malloc(size_attrs * sizeof(*(e->attr_names))); - e->attr_vals = malloc(size_attrs * sizeof(*(e->attr_vals))); - e->content = NULL; - - return e; -} - -void elem_free(struct elem *e) -{ - for(int i = 0; i < e->n_attrs; ++i) { - free(e->attr_names[i]); - free(e->attr_vals[i]); - } - - free(e->content); - free(e->attr_names); - free(e->attr_vals); - free(e->name); - free(e); -} - -void elem_add_attr(struct elem *e, char *name, char *val) -{ - if (e->n_attrs == e->size_attrs) { - e->size_attrs *= 2; - e->attr_names = realloc(e->attr_names, - e->size_attrs * sizeof(*(e->attr_names))); - e->attr_vals = realloc(e->attr_vals, - e->size_attrs * sizeof(*(e->attr_vals))); - } - - size_t size = strlen(name) + 1; - e->attr_names[e->n_attrs] = malloc(size); - memcpy(e->attr_names[e->n_attrs], name, size); - - size = strlen(val) + 1; - e->attr_vals[e->n_attrs] = malloc(size); - memcpy(e->attr_vals[e->n_attrs++], val, size); -} - -void elem_add_attr_double(struct elem *e, char *name, double val) -{ - char str[512]; - sprintf(str, "%f", val); - elem_add_attr(e, name, str); -} - -// draws a ring if angles are equal -struct elem *gen_arc(double a1, double a2, double r1, double r2, char *col) -{ - struct ccoords cc1 = pol_to_cart((struct pcoords){ - .a = (a1 == a2 ? 1 : a2), .r = r1 }); - struct ccoords cc2 = pol_to_cart((struct pcoords){ - .a = (a1 == a2 ? 0 : a1), .r = r1 }); - struct ccoords cc3 = pol_to_cart((struct pcoords){ - .a = (a1 == a2 ? 0 : a1), .r = r2 }); - struct ccoords cc4 = pol_to_cart((struct pcoords){ - .a = (a1 == a2 ? 1 : a2), .r = r2 }); - - struct elem *e = elem_init("path", 2); - elem_add_attr(e, "fill", col); - - char buf[512]; - int buflen = 0; - buflen += sprintf(buf + buflen, "M%f %f", cc1.x, cc1.y); - buflen += sprintf(buf + buflen, "A%f %f 0 0 0 %f %f", - r1, r1, cc2.x, cc2.y); - if (a1 == a2) - buflen += sprintf(buf + buflen, "A%f %f 0 1 0 %f %f", - r1, r1, cc1.x, cc1.y); - buflen += sprintf(buf + buflen, "L%f %f", cc3.x, cc3.y); - buflen += sprintf(buf + buflen, "A%f %f 0 0 1 %f %f", - r2, r2, cc4.x, cc4.y); - if (a1 == a2) - buflen += sprintf(buf + buflen, "A%f %f 0 1 1 %f %f", - r2, r2, cc3.x, cc3.y); - buf[buflen++] = 'Z'; - buf[buflen++] = 0; - elem_add_attr(e, "d", buf); - - return e; -} - -struct elem *gen_segment(double a, double r1, double r2, char *col) -{ - return gen_arc(a - SECTOR_WIDTH/2, a + SECTOR_WIDTH/2, r1, r2, col); -} - -struct elem *gen_ring(double r, double w, char *col) -{ - return gen_arc(0, 0, r - w/2, r + w/2, col); -} - -struct elem *gen_circle(double r, char *col) -{ - struct elem *e = elem_init("circle", 2); - elem_add_attr(e, "fill", col); - elem_add_attr_double(e, "r", r); - - return e; -} - -struct elem *gen_line(double a, double r1, double r2, double w, char *col) -{ - struct ccoords cc1 = pol_to_cart((struct pcoords){ .a = a, .r = r1 }); - struct ccoords cc2 = pol_to_cart((struct pcoords){ .a = a, .r = r2 }); - - struct elem *e = elem_init("line", 6); - elem_add_attr(e, "stroke", col); - elem_add_attr_double(e, "x1", cc1.x); - elem_add_attr_double(e, "y1", cc1.y); - elem_add_attr_double(e, "x2", cc2.x); - elem_add_attr_double(e, "y2", cc2.y); - elem_add_attr_double(e, "stroke-width", w); - - return e; -} - -int draw_spider(int elemc, struct elem **elemv) -{ - for (int i = 5; i > 1; --i) { - elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH, C_WIRE); - elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH/2, C_WIRE_INNER); - } - - for (int i = 0; i < NUM_SECTORS; ++i) { - double a = 90 - i*SECTOR_WIDTH - SECTOR_WIDTH/2; - if (a < 0) a += 360; - - elemv[elemc++] = gen_line(a, OUTER_DISTS[1], OUTER_DISTS[5] + 10, - WIRE_WIDTH, C_WIRE); - elemv[elemc++] = gen_line(a, OUTER_DISTS[1], OUTER_DISTS[5] + 10, - WIRE_WIDTH/2, C_WIRE_INNER); - } - - for (int i = 1; i >= 0; --i) { - elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH, C_WIRE); - elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH/2, C_WIRE_INNER); - } - - return elemc; -} - -int draw_numbers(int elemc, struct elem **elemv) -{ - elemv[elemc++] = gen_ring(DIAMETER/2 - WIRE_WIDTH*4, WIRE_WIDTH, "#ddd"); - - int r = DIAMETER/2 - 33/2; - for (int i = 0; i < 20; ++i) { - struct elem *e = elemv[elemc++] = elem_init("text", 5); - elem_add_attr(e, "font-size", "33"); - elem_add_attr(e, "fill", "#fff"); - elem_add_attr(e, "text-anchor", "middle"); - elem_add_attr(e, "dominant-baseline", "central"); - - char buf[512]; - double a = 90 - i*SECTOR_WIDTH; - if (a < 0) a += 360; - struct ccoords cc = pol_to_cart((struct pcoords){ .a = a, .r = r }); - sprintf(buf, "scale(1 -1) translate(%f %f) rotate(%f)", - cc.x, -cc.y, a <= 180 ? 90 -a : 270 -a); - elem_add_attr(e, "transform", buf); - - e->content = malloc(3); - sprintf(e->content, "%d", SECTORS[i]); - } - - return elemc; -} - -void draw_elemv(int layer, int elemc, struct elem **elemv) -{ - EM_ASM({svgDrawElemv($0, $1, $2, $3, $4, $5, $6, $7)}, - layer, elemc, elemv, - offsetof(struct elem, name), offsetof(struct elem, n_attrs), - offsetof(struct elem, attr_names), offsetof(struct elem, attr_vals), - offsetof(struct elem, content)); -} - -void svg_draw_board() -{ - struct elem **elemv = malloc(200 * sizeof(*elemv)); - int elemc = 0; - - elemv[elemc++] = gen_circle(DIAMETER/2, C_BLACK); - - for (int i = 5; i > 1; --i) { - for (int j = 0; j < NUM_SECTORS; ++j) { - double a = 90 - j*SECTOR_WIDTH; - if (a < 0) a += 360; - elemv[elemc++] = gen_segment(a, OUTER_DISTS[i-1], OUTER_DISTS[i], - i%2 ? (j%2 ? C_GREEN : C_RED) : (j%2 ? C_WHITE : C_BLACK)); - } - } - - elemv[elemc++] = gen_circle(OUTER_DISTS[1], C_GREEN); - elemv[elemc++] = gen_circle(OUTER_DISTS[0], C_RED); - - elemc = draw_spider(elemc, elemv); - elemc = draw_numbers(elemc, elemv); - - draw_elemv(0, elemc, elemv); - - for (int i = 0; i < elemc; ++i) - free(elemv[i]); - free(elemv); -} - -void svg_draw_point(double x, double y) { - struct elem *e = gen_circle(8, "#33f"); - elem_add_attr(e, "stroke", "#ff0"); - elem_add_attr(e, "stroke-width", "2"); - elem_add_attr_double(e, "cx", x); - elem_add_attr_double(e, "cy", y); - - draw_elemv(1, 1, &e); - elem_free(e); -} diff --git a/web/svg.h b/web/svg.h deleted file mode 100644 index 3321846..0000000 --- a/web/svg.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef SVG_H -#define SVG_H - -void svg_draw_board(); -void svg_draw_point(double x, double y); - -#endif diff --git a/web/web_match.c b/web/web_match.c new file mode 100644 index 0000000..47bc6e6 --- /dev/null +++ b/web/web_match.c @@ -0,0 +1,20 @@ +#include "web_match.h" + +#include +#include + +struct match_state *state; + +void free_state() +{ + state->legs[1]->n_visits += state->boat_undone; // avoid memory leak + leg_free(state->legs[0]); + leg_free(state->legs[1]); + free(state); + state = NULL; +} + +bool is_match_over() +{ + return state->legs[0]->rem <= 0 || state->legs[1]->rem <= 0; +} diff --git a/web/web_match.h b/web/web_match.h new file mode 100644 index 0000000..4b4c7bb --- /dev/null +++ b/web/web_match.h @@ -0,0 +1,29 @@ +#ifndef WEB_MATCH_H +#define WEB_MATCH_H + +#include "match.h" + +enum match_mode { + M_FIRST = 1, + M_PVC = M_FIRST, + M_P, + M_PVP, + M_LAST = M_PVP +}; + +struct match_state { + enum match_mode mode; + struct leg *legs[2]; + struct leg *active_leg; + int active_player; + int boat_undone; + int num_darts; +}; + +extern struct match_state *state; + +void free_state(); + +bool is_match_over(); + +#endif diff --git a/web/web_svg.c b/web/web_svg.c new file mode 100644 index 0000000..9b8f25d --- /dev/null +++ b/web/web_svg.c @@ -0,0 +1,256 @@ +#include "web_svg.h" + +#include "board.h" +#include "comp.h" + +#include +#include +#include + +#include + +#define NUM_SECTORS 20 +#define SECTOR_WIDTH 18.0 + +#define C_BLACK "#272b2c" +#define C_WHITE "#fbe3ba" +#define C_RED "#f6302f" +#define C_GREEN "#22912d" +#define C_WIRE "#909ca0" +#define C_WIRE_INNER "#d8e6ec" + +struct elem { + char *name; + int n_attrs, size_attrs; + char **attr_names, **attr_vals; + char *content; +}; + +struct elem *elem_init(char *name, int size_attrs) +{ + struct elem *e = malloc(sizeof(*e)); + + size_t size = strlen(name) + 1; + e->name = malloc(size * sizeof(*(e->name))); + memcpy(e->name, name, size); + + e->n_attrs = 0; + e->size_attrs = size_attrs; + e->attr_names = malloc(size_attrs * sizeof(*(e->attr_names))); + e->attr_vals = malloc(size_attrs * sizeof(*(e->attr_vals))); + e->content = NULL; + + return e; +} + +void elem_free(struct elem *e) +{ + for(int i = 0; i < e->n_attrs; ++i) { + free(e->attr_names[i]); + free(e->attr_vals[i]); + } + + free(e->content); + free(e->attr_names); + free(e->attr_vals); + free(e->name); + free(e); +} + +void elem_add_attr(struct elem *e, char *name, char *val) +{ + if (e->n_attrs == e->size_attrs) { + e->size_attrs *= 2; + e->attr_names = realloc(e->attr_names, + e->size_attrs * sizeof(*(e->attr_names))); + e->attr_vals = realloc(e->attr_vals, + e->size_attrs * sizeof(*(e->attr_vals))); + } + + size_t size = strlen(name) + 1; + e->attr_names[e->n_attrs] = malloc(size); + memcpy(e->attr_names[e->n_attrs], name, size); + + size = strlen(val) + 1; + e->attr_vals[e->n_attrs] = malloc(size); + memcpy(e->attr_vals[e->n_attrs++], val, size); +} + +void elem_add_attr_double(struct elem *e, char *name, double val) +{ + char str[512]; + sprintf(str, "%f", val); + elem_add_attr(e, name, str); +} + +// draws a ring if angles are equal +struct elem *gen_arc(double a1, double a2, double r1, double r2, char *col) +{ + struct ccoords cc1 = pol_to_cart((struct pcoords){ + .a = (a1 == a2 ? 1 : a2), .r = r1 }); + struct ccoords cc2 = pol_to_cart((struct pcoords){ + .a = (a1 == a2 ? 0 : a1), .r = r1 }); + struct ccoords cc3 = pol_to_cart((struct pcoords){ + .a = (a1 == a2 ? 0 : a1), .r = r2 }); + struct ccoords cc4 = pol_to_cart((struct pcoords){ + .a = (a1 == a2 ? 1 : a2), .r = r2 }); + + struct elem *e = elem_init("path", 2); + elem_add_attr(e, "fill", col); + + char buf[512]; + int buflen = 0; + buflen += sprintf(buf + buflen, "M%f %f", cc1.x, cc1.y); + buflen += sprintf(buf + buflen, "A%f %f 0 0 0 %f %f", + r1, r1, cc2.x, cc2.y); + if (a1 == a2) + buflen += sprintf(buf + buflen, "A%f %f 0 1 0 %f %f", + r1, r1, cc1.x, cc1.y); + buflen += sprintf(buf + buflen, "L%f %f", cc3.x, cc3.y); + buflen += sprintf(buf + buflen, "A%f %f 0 0 1 %f %f", + r2, r2, cc4.x, cc4.y); + if (a1 == a2) + buflen += sprintf(buf + buflen, "A%f %f 0 1 1 %f %f", + r2, r2, cc3.x, cc3.y); + buf[buflen++] = 'Z'; + buf[buflen++] = 0; + elem_add_attr(e, "d", buf); + + return e; +} + +struct elem *gen_segment(double a, double r1, double r2, char *col) +{ + return gen_arc(a - SECTOR_WIDTH/2, a + SECTOR_WIDTH/2, r1, r2, col); +} + +struct elem *gen_ring(double r, double w, char *col) +{ + return gen_arc(0, 0, r - w/2, r + w/2, col); +} + +struct elem *gen_circle(double r, char *col) +{ + struct elem *e = elem_init("circle", 2); + elem_add_attr(e, "fill", col); + elem_add_attr_double(e, "r", r); + + return e; +} + +struct elem *gen_line(double a, double r1, double r2, double w, char *col) +{ + struct ccoords cc1 = pol_to_cart((struct pcoords){ .a = a, .r = r1 }); + struct ccoords cc2 = pol_to_cart((struct pcoords){ .a = a, .r = r2 }); + + struct elem *e = elem_init("line", 6); + elem_add_attr(e, "stroke", col); + elem_add_attr_double(e, "x1", cc1.x); + elem_add_attr_double(e, "y1", cc1.y); + elem_add_attr_double(e, "x2", cc2.x); + elem_add_attr_double(e, "y2", cc2.y); + elem_add_attr_double(e, "stroke-width", w); + + return e; +} + +int draw_spider(int elemc, struct elem **elemv) +{ + for (int i = 5; i > 1; --i) { + elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH, C_WIRE); + elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH/2, C_WIRE_INNER); + } + + for (int i = 0; i < NUM_SECTORS; ++i) { + double a = 90 - i*SECTOR_WIDTH - SECTOR_WIDTH/2; + if (a < 0) a += 360; + + elemv[elemc++] = gen_line(a, OUTER_DISTS[1], OUTER_DISTS[5] + 10, + WIRE_WIDTH, C_WIRE); + elemv[elemc++] = gen_line(a, OUTER_DISTS[1], OUTER_DISTS[5] + 10, + WIRE_WIDTH/2, C_WIRE_INNER); + } + + for (int i = 1; i >= 0; --i) { + elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH, C_WIRE); + elemv[elemc++] = gen_ring(OUTER_DISTS[i], WIRE_WIDTH/2, C_WIRE_INNER); + } + + return elemc; +} + +int draw_numbers(int elemc, struct elem **elemv) +{ + elemv[elemc++] = gen_ring(DIAMETER/2 - WIRE_WIDTH*4, WIRE_WIDTH, "#ddd"); + + int r = DIAMETER/2 - 33/2; + for (int i = 0; i < 20; ++i) { + struct elem *e = elemv[elemc++] = elem_init("text", 5); + elem_add_attr(e, "font-size", "33"); + elem_add_attr(e, "fill", "#fff"); + elem_add_attr(e, "text-anchor", "middle"); + elem_add_attr(e, "dominant-baseline", "central"); + + char buf[512]; + double a = 90 - i*SECTOR_WIDTH; + if (a < 0) a += 360; + struct ccoords cc = pol_to_cart((struct pcoords){ .a = a, .r = r }); + sprintf(buf, "scale(1 -1) translate(%f %f) rotate(%f)", + cc.x, -cc.y, a <= 180 ? 90 -a : 270 -a); + elem_add_attr(e, "transform", buf); + + e->content = malloc(3); + sprintf(e->content, "%d", SECTORS[i]); + } + + return elemc; +} + +void draw_elemv(int layer, int elemc, struct elem **elemv) +{ + EM_ASM({svgDrawElemv($0, $1, $2, $3, $4, $5, $6, $7)}, + layer, elemc, elemv, + offsetof(struct elem, name), offsetof(struct elem, n_attrs), + offsetof(struct elem, attr_names), offsetof(struct elem, attr_vals), + offsetof(struct elem, content)); +} + +void svg_draw_board() +{ + struct elem **elemv = malloc(200 * sizeof(*elemv)); + int elemc = 0; + + elemv[elemc++] = gen_circle(DIAMETER/2, C_BLACK); + + for (int i = 5; i > 1; --i) { + for (int j = 0; j < NUM_SECTORS; ++j) { + double a = 90 - j*SECTOR_WIDTH; + if (a < 0) a += 360; + elemv[elemc++] = gen_segment(a, OUTER_DISTS[i-1], OUTER_DISTS[i], + i%2 ? (j%2 ? C_GREEN : C_RED) : (j%2 ? C_WHITE : C_BLACK)); + } + } + + elemv[elemc++] = gen_circle(OUTER_DISTS[1], C_GREEN); + elemv[elemc++] = gen_circle(OUTER_DISTS[0], C_RED); + + elemc = draw_spider(elemc, elemv); + elemc = draw_numbers(elemc, elemv); + + draw_elemv(0, elemc, elemv); + + for (int i = 0; i < elemc; ++i) + free(elemv[i]); + free(elemv); +} + +void svg_draw_point(double x, double y) { + struct elem *e = gen_circle(8, "#33f"); + elem_add_attr(e, "stroke", "#ff0"); + elem_add_attr(e, "stroke-width", "2"); + elem_add_attr_double(e, "cx", x); + elem_add_attr_double(e, "cy", y); + + draw_elemv(1, 1, &e); + elem_free(e); +} diff --git a/web/web_svg.h b/web/web_svg.h new file mode 100644 index 0000000..aae0b0e --- /dev/null +++ b/web/web_svg.h @@ -0,0 +1,7 @@ +#ifndef WEB_SVG_H +#define WEB_SVG_H + +void svg_draw_board(); +void svg_draw_point(double x, double y); + +#endif diff --git a/web/web_ui.c b/web/web_ui.c new file mode 100644 index 0000000..7ac4182 --- /dev/null +++ b/web/web_ui.c @@ -0,0 +1,134 @@ +#include "web_match.h" +#include "web_svg.h" +#include "web_ui.h" + +#include "checkouts.h" +#include "match.h" + +#include +#include +#include +#include + +#include + +void update_player_sugg(int pn, int rem) +{ + char str[15] = {0}, *p = str; + + if (rem > 1 && rem <= 170) { + char *target; + int i = 3, trem = rem; + while (i && trem && (target = CHECKOUTS[--i][trem-1])) { + p += sprintf(p, i == 2 ? "%s" : "-%s", target); + trem -= segment_points(segment_from_name(target)); + } + } + + EM_ASM({updatePlayerSugg($0, $1)}, pn, str); +} + +void update_player_avg(int pn, int n_darts) +{ + struct leg *l = state->legs[pn-1]; + EM_ASM({updatePlayerAvg($0, $1)}, 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)) : + 0); +} + +void draw_visits() +{ + EM_ASM({clearVisits()}); + + char visit_no[10], p1_pts[10], p1_rem[10], + p2_pts[10], p2_rem[10], p2_darts[100]; + + sprintf(p1_rem, "%d", state->legs[0]->start); + sprintf(p2_rem, "%d", state->legs[1]->start); + EM_ASM({drawVisit($0, $1, $2, $3, $4, $5)}, + "0", "", p1_rem, "", state->mode == M_P ? "" : p2_rem, ""); + + int n_visits = state->legs[0]->n_visits > state->legs[1]->n_visits ? + state->legs[0]->n_visits : state->legs[1]->n_visits; + for (int i = 0; i < n_visits; ++i) { + visit_no[0] = p1_pts[0] = p1_rem[0] = + p2_pts[0] = p2_rem[0] = p2_darts[0] = 0; + + sprintf(visit_no, "%d", i + 1); + + struct visit *v = state->legs[0]->visits + i; + sprintf(p1_pts, "%d", v->points); + sprintf(p1_rem, "%d", v->rem); + + if (i < state->legs[1]->n_visits) { + v = state->legs[1]->visits + i; + sprintf(p2_pts, "%d", v->points); + sprintf(p2_rem, "%d", v->rem); + + for (int j = 0; j < v->n_darts; ++j) { + char *n = segment_name(v->darts[j]); + sprintf(p2_darts + (j ? (j*5 - 1) : 0), + j == 0 ? "%4s" : " %4s", n); + free(n); + } + } + + EM_ASM({drawVisit($0, $1, $2, $3, $4, $5)}, + visit_no, p1_pts, p1_rem, p2_pts, p2_rem, p2_darts); + } +} + +void update_player_rem(int pn, int rem) +{ + char str[5]; + if (rem < 0 || rem == 1) + strcpy(str, "BUST"); + else + sprintf(str, "%d", rem); + + EM_ASM({updatePlayerRem($0, $1)}, 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); +} + +EMSCRIPTEN_KEEPALIVE +void draw_boat_throwing(int pts, char *str, double x, double y) +{ + char pts_str[10]; + sprintf(pts_str, "%d", pts); + + int rem = state->legs[1]->n_visits > 1 ? + state->legs[1]->visits[state->legs[1]->n_visits-2].rem : + state->legs[1]->start; + + svg_draw_point(x, y); + update_player_rem(2, rem - pts); + EM_ASM({setPromptInput($0)}, pts_str); + EM_ASM({promptMsgR($0)}, str); + free(str); +} + +bool is_key_active(char *k) +{ + return (EM_ASM_INT({return isKeyActive($0)}, k)); +} + +void toggle_key(char *k) +{ + EM_ASM({toggleKey($0)}, k); +} + +void deactivate_key(char *k) +{ + EM_ASM({deactivateKey($0)}, k); +} diff --git a/web/web_ui.h b/web/web_ui.h new file mode 100644 index 0000000..fa961fb --- /dev/null +++ b/web/web_ui.h @@ -0,0 +1,18 @@ +#ifndef WEB_UI_H +#define WEB_UI_H + +#include + +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 clear_player_info(int pn); + +void draw_visits(); +void draw_boat_throwing(int pts, char *str, double x, double y); + +bool is_key_active(char *k); +void toggle_key(char *k); +void deactivate_key(char *k); + +#endif -- cgit v1.2.3-70-g09d2