From 24b71a541f73bffc4ba65ad479b441df2913ef0a Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Thu, 21 Apr 2022 19:54:05 -0700 Subject: rewrite some JS web logic in C --- web/dartboat_wasm.c | 88 ++++++++++++++++++++++++-------------- web/static/dartboat.js | 113 ++++++++++++++++++++----------------------------- 2 files changed, 101 insertions(+), 100 deletions(-) diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c index b2c306c..65888b2 100644 --- a/web/dartboat_wasm.c +++ b/web/dartboat_wasm.c @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -75,36 +76,6 @@ EMSCRIPTEN_KEEPALIVE int is_match_over(struct match_state *state) { return 0; } -EMSCRIPTEN_KEEPALIVE void boat_visit(struct match_state *state) { - if (state->l1->rem <= 0 || state->l2->rem <= 0) - return; - - struct leg *l = state->l2; - comp_visit(l); - - struct visit *v = l->visits + l->n_visits - 1; - - char *s1 = segment_name(v->darts[0]), - *s2 = v->n_darts > 1 ? segment_name(v->darts[1]) : NULL, - *s3 = v->n_darts > 2 ? segment_name(v->darts[2]) : NULL; - - double avg; - if (v->rem > 0) - avg = (double)(l->start - l->rem) / l->n_visits; - else - avg = ((double)l->start / (((l->n_visits - 1) * 3) + v->n_darts)) * 3; - - EM_ASM({boatVisitRes($0, $1, $2, $3, $4, $5, $6, $7, $8)}, - l->rem, v->n_darts, segment_points(v->darts[0]), - v->n_darts > 1 ? segment_points(v->darts[1]) : 0, - v->n_darts > 2 ? segment_points(v->darts[2]) : 0, - s1, s2, s3, avg); - - free(s1); - free(s2); - free(s3); -} - EMSCRIPTEN_KEEPALIVE void draw_match(struct match_state *state) { struct leg *l1 = state->l1; struct leg *l2 = state->l2; @@ -148,8 +119,6 @@ EMSCRIPTEN_KEEPALIVE void draw_match(struct match_state *state) { if (l1->rem <= 0) { EM_ASM(promptNumDarts()); - //EM_ASM({promptMsg($0)}, "You win! :)"); - //EM_ASM(matchOver()); } else if (l2->rem <= 0) { EM_ASM({promptMsg($0)}, "Bot wins. :("); EM_ASM(matchOver()); @@ -158,6 +127,61 @@ EMSCRIPTEN_KEEPALIVE void draw_match(struct match_state *state) { } } +EMSCRIPTEN_KEEPALIVE void boat_visit(struct match_state *state, int delay_ms) { + if (state->l1->rem <= 0 || state->l2->rem <= 0) + return; + + EM_ASM({promptMsg($0)}, "Bot is throwing…"); + + struct leg *l = state->l2; + comp_visit(l); + + struct visit *v = l->visits + l->n_visits - 1; + + double avg; + if (v->rem > 0) + avg = (double)(l->start - l->rem) / l->n_visits; + else + avg = ((double)l->start / (((l->n_visits - 1) * 3) + v->n_darts)) * 3; + + if (!delay_ms) { + EM_ASM({updateBoatRem($0)}, l->rem); + EM_ASM({updateBoatAvg($0)}, avg); + EM_ASM({clearMatchLog()}); + draw_match(state); + if (!is_match_over(state)) + EM_ASM(setUserActive()); + return; + } + + int pts = segment_points(v->darts[0]); + char str[20]; + char *seg_name = segment_name(v->darts[0]); + strcpy(str, seg_name); + free(seg_name); + + EM_ASM({scheduleBoatThrowing($0, $1, $2)}, pts, str, delay_ms); + + if (v->n_darts > 1) { + pts += segment_points(v->darts[1]); + seg_name = segment_name(v->darts[1]); + strcat(strcat(str, "-"), seg_name); + free(seg_name); + EM_ASM({scheduleBoatThrowing($0, $1, $2)}, pts, str, delay_ms * 2); + } + + if (v->n_darts > 2) { + pts += segment_points(v->darts[2]); + seg_name = segment_name(v->darts[2]); + strcat(strcat(str, "-"), seg_name); + free(seg_name); + EM_ASM({scheduleBoatThrowing($0, $1, $2)}, pts, str, delay_ms * 3); + } + + EM_ASM({scheduleEndBoatThrowing($0, $1, $2)}, + l->rem, avg, delay_ms * (v->n_darts + 1)); +} + EMSCRIPTEN_KEEPALIVE int resp_numdarts(struct match_state *state, int n_darts) { if (n_darts < 1 || n_darts > 4) return 0; diff --git a/web/static/dartboat.js b/web/static/dartboat.js index c1a197a..7ffe78d 100644 --- a/web/static/dartboat.js +++ b/web/static/dartboat.js @@ -1,9 +1,8 @@ -let match_active = false; -let prompt_disable = false; let prompt_num_darts = false; let match_state, user_rem, boat_rem; let oi_timeout; let delay_ms = 1000; +let prompt_mode; const POINT_CLASSES = [180, 140, 100, 60, 40, 20, 1, 0]; @@ -13,13 +12,17 @@ function stcall(f, ret_type, arg_types, args) { args ? [match_state].concat(args) : [match_state]); } +function clearMatchLog() { + document.getElementById('match').textContent = ''; +} + function initMatch() { - stcall('free_match'); + if (match_state) + stcall('free_match'); updateDelay(delay_ms); match_state = stcall('start_match', 'number'); - match_active = true; - document.getElementById('user-state').className = 'active'; - document.getElementById('match').textContent = ''; + setUserActive(); + clearMatchLog(); promptSuggStr(''); stcall('draw_match'); } @@ -96,14 +99,8 @@ function promptUpdateRem() { updateUserStateRem(pts ? user_rem - pts : user_rem); } -function boatTempRem(pts, str) { - updateBoatStateRem(boat_rem - pts); - document.getElementById('prompt').textContent = pts; - promptSuggStr(str); -} - function promptAppend(val) { - if (!match_active || prompt_disable) return; + if (!prompt_mode || prompt_mode == 'init_match') return; clearOi(); let elem = document.getElementById('prompt'); @@ -115,7 +112,7 @@ function promptAppend(val) { } function promptClear() { - if (!match_active || prompt_disable) return; + if (!prompt_mode || prompt_mode == 'init_match') return; clearOi(); document.getElementById('prompt').textContent = ''; @@ -123,7 +120,7 @@ function promptClear() { } function promptBackspace() { - if (!match_active || prompt_disable) return; + if (!prompt_mode || prompt_mode == 'init_match') return; clearOi(); let elem = document.getElementById('prompt'); @@ -137,22 +134,21 @@ function promptNumDarts() { } function setBoatActive() { - document.getElementById('user-state').className = ''; - document.getElementById('boat-state').className = 'active'; - promptMsgStr('Bot is throwing…'); - prompt_disable = true; + document.getElementById('user-state').classList.remove('active'); + document.getElementById('boat-state').classList.add('active'); + prompt_mode = null; } function setUserActive() { - document.getElementById('user-state').className = 'active'; - document.getElementById('boat-state').className = ''; - prompt_disable = false; + document.getElementById('boat-state').classList.remove('active'); + document.getElementById('user-state').classList.add('active'); + prompt_mode = 'user_active'; } function promptSubmit(remaining) { clearOi(); - if (prompt_disable) return; - if (!match_active) { + if (!prompt_mode) return; + if (prompt_mode == 'init_match') { initMatch(); return; } @@ -179,67 +175,48 @@ function promptSubmit(remaining) { return; } - elem = document.getElementById('match'); - elem.textContent = ''; + clearMatchLog(); stcall('draw_match'); if (!stcall('is_match_over', 'number')) { setBoatActive(); - stcall('boat_visit', 'number'); + stcall('boat_visit', 'number', ['number'], [delay_ms]); } } -function boatVisitRes(rem, n, p1, p2, p3, ptr1, ptr2, ptr3, avg) { - // cannot convert in timeout func because strings are freed in c func - let s1 = UTF8ToString(ptr1); - let s2 = UTF8ToString(ptr2); - let s3 = UTF8ToString(ptr3); - - if (delay_ms == 0) { - updateBoatRem(rem); - updateBoatAvg(avg); - document.getElementById('match').textContent = ''; - stcall('draw_match'); - setUserActive(); - } else { - setTimeout(function() { boatTempRem(p1, s1); }, delay_ms); +function drawBoatThrowing(pts, str) { + updateBoatStateRem(boat_rem - pts); + document.getElementById('prompt').textContent = pts; + promptSuggStr(str); +} - if (n > 1) { - setTimeout(function() { boatTempRem(p1 + p2, `${s1}-${s2}`); }, delay_ms * 2); - } +function scheduleBoatThrowing(pts, ptr, delay_ms) { + // ptr to c string must be copied before returning + let str = UTF8ToString(ptr); + setTimeout(function() { drawBoatThrowing(pts, str); }, delay_ms); +} - if (n > 2) { - setTimeout(function() { boatTempRem(p1 + p2 + p3, `${s1}-${s2}-${s3}`); }, delay_ms * 3); - } +function endBoatThrowing(rem, avg) { + updateBoatRem(rem); + updateBoatAvg(avg); + document.getElementById('prompt').textContent = ''; + clearMatchLog(); + promptSuggStr(''); + stcall('draw_match'); + if (!stcall('is_match_over', 'number')) + setUserActive(); +} - setTimeout(function() { - updateBoatRem(rem); - updateBoatAvg(avg); - document.getElementById('prompt').textContent = ''; - document.getElementById('match').textContent = ''; - stcall('draw_match'); - promptSuggStr(''); - setUserActive(); - }, delay_ms * (n + 1)); - } +function scheduleEndBoatThrowing(rem, avg, delay_ms) { + setTimeout(function() { endBoatThrowing(rem, avg); }, delay_ms); } function matchOver() { - match_active = false; + prompt_mode = 'init_match'; promptSuggStr('Press OK to play again.'); document.getElementById('user-state').className = ''; } -function drawVisitNames(n1, n2) { - let elem = document.getElementById('match'); - for (let [k, v] of Object.entries({ 'user-name': n1, 'boat-name': n2 })) { - let div = document.createElement('div'); - div.className = k; - div.textContent = UTF8ToString(v); - elem.append(div); - } -} - function drawVisit(visit_no, u_pts, u_rem, b_pts, b_rem, b_darts) { let elem = document.getElementById('match'); -- cgit v1.2.3-70-g09d2