From 0fdc050919f0a7a2dce53baf348ab1f9b328d6da Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Thu, 28 Apr 2022 18:27:47 -0700 Subject: web: less javascript, more c --- board.h | 4 + comp.h | 1 + web/dartboat_wasm.c | 7 +- web/static/dartboard.js | 151 -------------------------- web/static/dartboat.js | 24 +++++ web/static/index.html | 5 +- web/svg_dartboard.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 316 insertions(+), 156 deletions(-) delete mode 100644 web/static/dartboard.js create mode 100644 web/svg_dartboard.c diff --git a/board.h b/board.h index c7fb477..e5ffb24 100644 --- a/board.h +++ b/board.h @@ -4,6 +4,7 @@ #include // board spec from WDF rules +#define DIAMETER 451.0 #define WIRE_WIDTH 1.56 #define INNER_DIAMETER_BULL 12.7 #define INNER_DIAMETER_25 31.8 @@ -37,6 +38,9 @@ struct segment { int sector; }; +extern int SECTORS[]; +extern double OUTER_DISTS[]; + void init_board(); struct ccoords { diff --git a/comp.h b/comp.h index 4cab400..c7882d3 100644 --- a/comp.h +++ b/comp.h @@ -5,6 +5,7 @@ extern double horizontal_stdev, vertical_stdev; +struct ccoords pol_to_cart(struct pcoords c); void comp_visit(struct leg *l); #endif diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c index 84cad62..48c16b1 100644 --- a/web/dartboat_wasm.c +++ b/web/dartboat_wasm.c @@ -157,6 +157,7 @@ EMSCRIPTEN_KEEPALIVE void update_user_rem_from_pts(int pts) update_player_rem(state->active_player, state->active_leg->rem - pts); } +void draw_point(double, double); EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str, double x, double y) { char pts_str[10]; @@ -166,7 +167,7 @@ EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str, double x, doubl state->legs[1]->visits[state->legs[1]->n_visits-2].rem : state->legs[1]->start; - EM_ASM({draw_point($0, $1)}, x, y); + draw_point(x, y); update_player_rem(2, rem - pts); EM_ASM({setPromptInput($0)}, pts_str); EM_ASM({promptMsgR($0)}, str); @@ -176,7 +177,7 @@ EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str, double x, doubl void handle_next(); EMSCRIPTEN_KEEPALIVE void end_boat_visit(int rem, double avg) { - EM_ASM(clear_points()); + EM_ASM(clearPoints()); update_player_rem(2, rem); EM_ASM({updatePlayerAvg($0, $1)}, 2, avg); EM_ASM({setPromptInput($0)}, ""); @@ -458,10 +459,12 @@ EMSCRIPTEN_KEEPALIVE void set_stdev(float stdev) horizontal_stdev = vertical_stdev = stdev; } +void draw_board(); void init_boat() { srand(time(NULL)); init_board(); + draw_board(); EM_ASM(readOpts()); EM_ASM({updateDelay($0)}, delay_ms); diff --git a/web/static/dartboard.js b/web/static/dartboard.js deleted file mode 100644 index 46e5c4c..0000000 --- a/web/static/dartboard.js +++ /dev/null @@ -1,151 +0,0 @@ -const diameter = 451.0; -const dists = [7.13, 16.68, 97.06, 106.62, 159.66, 169.22]; -const wire_width = 1.56; -const sectors = ['20', '1', '18', '4', '13', '6', '10', '15', '2', '17', - '3', '19', '7', '16', '8', '11', '14', '9', '12', '5']; - -const c_black = '#272b2c'; -const c_white = '#fbe3ba'; -const c_red = '#f6302f'; -const c_green = '#22912d'; -const c_wire = '#909ca0'; -const c_wire_inner = '#d8e6ec'; - -const svgns = 'http://www.w3.org/2000/svg'; - -function p2c(a, r) { - const t = a * Math.PI / 180; - return [r * Math.cos(t), r * Math.sin(t)]; -} - -function gen_arc(a1, a2, r1, r2, c) { - const [x1, y1] = p2c(a1 === a2 ? 1 : a2, r1); - const [x2, y2] = p2c(a1 === a2 ? 0 : a1, r1); - const [x3, y3] = p2c(a1 === a2 ? 0 : a1, r2); - const [x4, y4] = p2c(a1 === a2 ? 1 : a2, r2); - - const elem = document.createElementNS(svgns, 'path'); - elem.setAttribute('d', - `M${x1} ${y1}` + - `A${r1} ${r1} 0 0 0 ${x2} ${y2}` + - (a1 === a2 ? `A${r1} ${r1} 0 1 0 ${x1} ${y1}` : '') + - `L${x3} ${y3}` + - `A${r2} ${r2} 0 0 1 ${x4} ${y4}` + - (a1 === a2 ? `A${r2} ${r2} 0 1 1 ${x3} ${y3}` : '') + - 'Z'); - elem.setAttribute('fill', c) - return elem; -} - -function gen_segment(a, r1, r2, c) { - return gen_arc(a - 9, a + 9, r1, r2, c); -} - -function gen_ring(r, w, c) { - return gen_arc(0, 0, r - w/2, r + w/2, c); -} - -function gen_circle(r, c) { - const elem = document.createElementNS(svgns, 'circle'); - elem.setAttribute('r', r); - elem.setAttribute('fill', c) - return elem; -} - -function gen_line(a, r1, r2, w, c) { - const [x1, y1] = p2c(a, r1); - const [x2, y2] = p2c(a, r2); - - const elem = document.createElementNS(svgns, 'line'); - elem.setAttribute('x1', x1); - elem.setAttribute('y1', y1); - elem.setAttribute('x2', x2); - elem.setAttribute('y2', y2); - elem.setAttribute('stroke', c); - elem.setAttribute('stroke-width', w); - return elem; -} - -function draw_spider(board) { - for (let i = 5; i > 1; --i) { - board.appendChild(gen_ring(dists[i], wire_width, c_wire)); - board.appendChild(gen_ring(dists[i], wire_width/2, c_wire_inner)); - } - - for (let i = 20; i > 0; --i) { - let a = 90 - (i * 18) - 9; - if (a < 0) a += 360; - board.appendChild(gen_line(a, dists[1], dists[5] + 10, - wire_width, c_wire)); - board.appendChild(gen_line(a, dists[1], dists[5] + 10 - wire_width/4, - wire_width/2, c_wire_inner)); - } - - for (let i = 1; i >= 0; --i) { - board.appendChild(gen_ring(dists[i], wire_width, c_wire)); - board.appendChild(gen_ring(dists[i], wire_width/2, c_wire_inner)); - } -} - -function draw_numbers(board) { - board.appendChild(gen_ring(diameter/2 - wire_width*4, wire_width, '#ddd')); - - const r = diameter/2 - 33/2; - for (let i = 0; i < 20; ++i) { - let a = 90 - (i * 18); - if (a < 0) a += 360; - const [x, y] = p2c(a, r); - - const elem = document.createElementNS(svgns, 'text'); - elem.textContent = sectors[i]; - elem.setAttribute('font-size', '33'); - elem.setAttribute('fill', '#fff'); - elem.setAttribute('transform', `scale(1 -1) translate(${x} ${-y}) ` + - `rotate(${a <= 180 ? 90 - a : 270 - a})`); - elem.setAttribute('text-anchor', 'middle'); - elem.setAttribute('dominant-baseline', 'central'); - board.appendChild(elem); - } -} - -function draw_board() { - const board = document.getElementById('dartboard'); - const points = document.getElementById('dartboard-points'); - - const r = diameter/2; - board.setAttribute('transform', `translate(${r} ${r}) scale(1 -1)`); - points.setAttribute('transform', `translate(${r} ${r}) scale(1 -1)`); - board.appendChild(gen_circle(r, c_black)); - - for (let i = 5; i > 1; --i) { - for (let j = 0; j < 20; ++j) { - let a = 90 - (j * 18); - if (a < 0) a += 360; - - const elem = gen_segment(a, dists[i-1], dists[i], - i%2 ? (j%2 ? c_green : c_red) : (j%2 ? c_white : c_black)); - board.appendChild(elem); - } - } - - board.appendChild(gen_circle(dists[1], c_green)); - board.appendChild(gen_circle(dists[0], c_red)); - draw_spider(board); - draw_numbers(board); -} - -function draw_point(x, y) { - const points = document.getElementById('dartboard-points'); - elem = gen_circle(8, '#33f'); - elem.setAttribute('cx', x); - elem.setAttribute('cy', y); - elem.setAttribute('stroke', '#ff0'); - elem.setAttribute('stroke-width', '2'); - points.appendChild(elem); -} - -function clear_points() { - document.getElementById('dartboard-points').textContent = ''; -} - -document.addEventListener('DOMContentLoaded', () => draw_board()); diff --git a/web/static/dartboat.js b/web/static/dartboat.js index 98bbb37..53a113a 100644 --- a/web/static/dartboat.js +++ b/web/static/dartboat.js @@ -136,6 +136,30 @@ function drawVisit(visit_no, p1_pts, p1_rem, p2_pts, p2_rem, p2_darts) { e.scrollTop = e.scrollHeight; } +function drawElem(target, name, n_attrs, attr_names, attr_vals, content) { + const e = document.createElementNS('http://www.w3.org/2000/svg', + UTF8ToString(name)); + if (content) e.textContent = UTF8ToString(content); + + for (let i = 0; i < n_attrs; ++i) + e.setAttribute(UTF8ToString(HEAP32[(attr_names + i*4)>>2]), + UTF8ToString(HEAP32[(attr_vals + i*4)>>2])); + + target.appendChild(e); +} + +function drawElemBoard(...args) { + drawElem($('#dartboard'), ...args); +} + +function drawElemPoint(...args) { + drawElem($('#dartboard-points'), ...args); +} + +function clearPoints() { + $('#dartboard-points').textContent = ''; +} + function updateDelay(val) { $('#delay').value = val; } diff --git a/web/static/index.html b/web/static/index.html index a9c5aea..c1a2fdd 100644 --- a/web/static/index.html +++ b/web/static/index.html @@ -6,7 +6,6 @@ - @@ -60,8 +59,8 @@ diff --git a/web/svg_dartboard.c b/web/svg_dartboard.c new file mode 100644 index 0000000..74c4f1c --- /dev/null +++ b/web/svg_dartboard.c @@ -0,0 +1,280 @@ +#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; + int size_attrs; + char **attr_names; + char **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 * sizeof(**(e->attr_names))); + memcpy(e->attr_names[e->n_attrs], name, size); + + size = strlen(val) + 1; + e->attr_vals[e->n_attrs] = malloc(size * sizeof(**(e->attr_vals))); + memcpy(e->attr_vals[e->n_attrs++], val, size); +} + +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'; + 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); + + char buf[512]; + sprintf(buf, "%f", r); + elem_add_attr(e, "r", buf); + + 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); + + char buf[512]; + sprintf(buf, "%f", cc1.x); + elem_add_attr(e, "x1", buf); + sprintf(buf, "%f", cc1.y); + elem_add_attr(e, "y1", buf); + sprintf(buf, "%f", cc2.x); + elem_add_attr(e, "x2", buf); + sprintf(buf, "%f", cc2.y); + elem_add_attr(e, "y2", buf); + sprintf(buf, "%f", w); + elem_add_attr(e, "stroke-width", buf); + + return e; +} + +void draw_elem(struct elem *e) +{ + EM_ASM({drawElemBoard($0, $1, $2, $3, $4)}, + e->name, e->n_attrs, e->attr_names, e->attr_vals, e->content); +} + +void draw_spider() +{ + struct elem *e; + + for (int i = 5; i > 1; --i) { + e = gen_ring(OUTER_DISTS[i], WIRE_WIDTH, C_WIRE); + draw_elem(e); + elem_free(e); + e = gen_ring(OUTER_DISTS[i], WIRE_WIDTH/2, C_WIRE_INNER); + draw_elem(e); + elem_free(e); + } + + for (int i = 0; i < NUM_SECTORS; ++i) { + double a = 90 - i*SECTOR_WIDTH - SECTOR_WIDTH/2; + if (a < 0) a += 360; + + e = gen_line(a, OUTER_DISTS[1], OUTER_DISTS[5] + 10, + WIRE_WIDTH, C_WIRE); + draw_elem(e); + elem_free(e); + e = gen_line(a, OUTER_DISTS[1], OUTER_DISTS[5] + 10, + WIRE_WIDTH/2, C_WIRE_INNER); + draw_elem(e); + elem_free(e); + } + + for (int i = 1; i >= 0; --i) { + e = gen_ring(OUTER_DISTS[i], WIRE_WIDTH, C_WIRE); + draw_elem(e); + elem_free(e); + e = gen_ring(OUTER_DISTS[i], WIRE_WIDTH/2, C_WIRE_INNER); + draw_elem(e); + elem_free(e); + } +} + +EMSCRIPTEN_KEEPALIVE void draw_numbers() +{ + struct elem *e; + + e = gen_ring(DIAMETER/2 - WIRE_WIDTH*4, WIRE_WIDTH, "#ddd"); + draw_elem(e); + elem_free(e); + + int r = DIAMETER/2 - 33/2; + for (int i = 0; i < 20; ++i) { + double a = 90 - i*SECTOR_WIDTH; + if (a < 0) a += 360; + struct ccoords cc = pol_to_cart((struct pcoords){ .a = a, .r = r }); + + e = 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]; + 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]); + + draw_elem(e); + elem_free(e); + } +} + +void draw_board() +{ + struct elem *e; + + e = gen_circle(DIAMETER/2, C_BLACK); + draw_elem(e); + elem_free(e); + + 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; + + e = gen_segment(a, OUTER_DISTS[i-1], OUTER_DISTS[i], + i%2 ? (j%2 ? C_GREEN : C_RED) : (j%2 ? C_WHITE : C_BLACK)); + draw_elem(e); + elem_free(e); + } + } + + e = gen_circle(OUTER_DISTS[1], C_GREEN); + draw_elem(e); + elem_free(e); + e = gen_circle(OUTER_DISTS[0], C_RED); + draw_elem(e); + elem_free(e); + + draw_spider(); + draw_numbers(); +} + +void 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"); + + char buf[512]; + sprintf(buf, "%f", x); + elem_add_attr(e, "cx", buf); + sprintf(buf, "%f", y); + elem_add_attr(e, "cy", buf); + + EM_ASM({drawElemPoint($0, $1, $2, $3, $4)}, + e->name, e->n_attrs, e->attr_names, e->attr_vals); + elem_free(e); +} -- cgit v1.2.3-70-g09d2