summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-04-28 18:27:47 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-04-28 18:27:47 -0700
commit0fdc050919f0a7a2dce53baf348ab1f9b328d6da (patch)
tree5fa41806e0eb8140b815a4dd901de31a12fabe24 /web
parentfcc02efbff337c05bf448231cd8bfbe016939f8a (diff)
downloaddartboat-0fdc050919f0a7a2dce53baf348ab1f9b328d6da.tar.gz
dartboat-0fdc050919f0a7a2dce53baf348ab1f9b328d6da.tar.xz
web: less javascript, more c
Diffstat (limited to 'web')
-rw-r--r--web/dartboat_wasm.c7
-rw-r--r--web/static/dartboard.js151
-rw-r--r--web/static/dartboat.js24
-rw-r--r--web/static/index.html5
-rw-r--r--web/svg_dartboard.c280
5 files changed, 311 insertions, 156 deletions
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 @@
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="dartboat.js"></script>
- <script src="dartboard.js"></script>
<script src="dartboat_wasm.js"></script>
</head>
<body>
@@ -60,8 +59,8 @@
<div id="keypad-dartboard" class="keypad" style="display: none">
<div id="dartboard-container">
<svg viewBox="0 0 451 451">
- <g id="dartboard"></g>
- <g id="dartboard-points"></g>
+ <g id="dartboard" transform="translate(225.5 225.5) scale(1 -1)"></g>
+ <g id="dartboard-points" transform="translate(225.5 225.5) scale(1 -1)"></g>
</svg>
</div>
</div>
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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <emscripten/emscripten.h>
+
+#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);
+}