diff options
-rw-r--r-- | web/dartboat_wasm.c | 20 | ||||
-rw-r--r-- | web/static/dartboat.js | 85 | ||||
-rw-r--r-- | web/static/index.html | 16 | ||||
-rw-r--r-- | web/static/style.css | 168 |
4 files changed, 166 insertions, 123 deletions
diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c index 3be713b..4eaa6ce 100644 --- a/web/dartboat_wasm.c +++ b/web/dartboat_wasm.c @@ -17,7 +17,7 @@ struct match_state { void suggested(int rem, char *buf) { buf[0] = 0; - if (rem <= 170) { + if (rem > 1 && rem <= 170) { char *target = CHECKOUTS[2][rem-1]; if (target) { int trem = rem - segment_points(segment_from_name(target)); @@ -36,6 +36,16 @@ void suggested(int rem, char *buf) { } } +EMSCRIPTEN_KEEPALIVE void get_suggested(int rem, int player) { + static char buf[20]; + suggested(rem, buf); + + if (player == 1) + EM_ASM({userSugg($0)}, buf); + else + EM_ASM({boatSugg($0)}, buf); +} + EMSCRIPTEN_KEEPALIVE bool user_visit(struct match_state *state, int points) { if (state->l1->rem <= 0 || state->l2->rem <= 0) return false; @@ -53,10 +63,6 @@ EMSCRIPTEN_KEEPALIVE bool user_visit(struct match_state *state, int points) { v->rem = l->rem; EM_ASM({updateUserRem($0)}, l->rem); - char sug[100]; - suggested(v->rem, sug); - EM_ASM({promptSugg($0)}, sug); - return true; } @@ -97,8 +103,6 @@ EMSCRIPTEN_KEEPALIVE void draw_match(struct match_state *state) { char visit_no[10], u_pts[10], u_rem[10], b_pts[10], b_rem[10], b_darts[100]; visit_no[0] = u_pts[0] = u_rem[0] = b_pts[0] = b_rem[0] = b_darts[0] = 0; - EM_ASM({drawVisitNames($0, $1)}, - l1->name, l2->name); EM_ASM({drawVisit($0, $1, $2, $3, $4, $5)}, "0", "", "501", "", "501", ""); @@ -137,7 +141,6 @@ EMSCRIPTEN_KEEPALIVE void draw_match(struct match_state *state) { EM_ASM({promptMsg($0)}, "You win! :)"); EM_ASM(matchOver()); } else if (l2->rem <= 0) { - EM_ASM({promptSugg($0)}, ""); EM_ASM({promptMsg($0)}, "Bot wins. :("); EM_ASM(matchOver()); } else { @@ -177,7 +180,6 @@ EMSCRIPTEN_KEEPALIVE void free_match(struct match_state *state) { } EMSCRIPTEN_KEEPALIVE void change_stdev(float hstdev, float vstdev) { - printf("%f %f\n", hstdev, vstdev); horizontal_stdev = hstdev; vertical_stdev = vstdev; } diff --git a/web/static/dartboat.js b/web/static/dartboat.js index 5eb3283..015c541 100644 --- a/web/static/dartboat.js +++ b/web/static/dartboat.js @@ -17,20 +17,20 @@ function initMatch() { updateDelay(delay_ms); match_state = stcall('start_match', 'number'); match_active = true; - document.getElementById('user-rem').className = 'active'; + document.getElementById('user-state').className = 'active'; document.getElementById('match').textContent = ''; - promptSuggStr(""); + promptSuggStr(''); stcall('draw_match'); } function oi() { - document.getElementById('oi').textContent = 'oi!'; + document.getElementById('oi').style.visibility = 'visible'; oi_timeout = setTimeout(function() { oi_timeout = null; clearOi() }, 3000); } function clearOi() { - document.getElementById('oi').textContent = ''; + document.getElementById('oi').style.visibility = 'hidden'; if (oi_timeout) { clearTimeout(oi_timeout); @@ -39,11 +39,13 @@ function clearOi() { } function updateUserRem(rem) { - user_rem = document.getElementById('user-rem').textContent = rem; + user_rem = rem; + updateUserStateRem(rem); } function updateBoatRem(rem) { - boat_rem = document.getElementById('boat-rem').textContent = rem; + boat_rem = rem; + updateBoatStateRem(rem); } function promptMsg(p) { @@ -54,32 +56,39 @@ function promptMsgStr(str) { document.getElementById('prompt-msg').textContent = str; } -function promptSugg(p) { - document.getElementById('prompt-sugg').textContent = UTF8ToString(p); +function userSugg(p) { + document.getElementById('user-sugg').textContent = UTF8ToString(p); +} + +function boatSugg(p) { + document.getElementById('boat-sugg').textContent = UTF8ToString(p); } function promptSuggStr(str) { document.getElementById('prompt-sugg').textContent = str; } +function updateUserStateRem(rem) { + let elem = document.getElementById('user-rem'); + elem.textContent = rem < 0 || rem == 1 ? 'BUST' : rem; + Module.ccall('get_suggested', null, ['number', 'number'], [rem, 1]); +} + +function updateBoatStateRem(rem) { + let elem = document.getElementById('boat-rem'); + elem.textContent = rem < 0 || rem == 1 ? 'BUST' : rem; + Module.ccall('get_suggested', null, ['number', 'number'], [rem, 2]); +} + function promptUpdateRem() { let elem = document.getElementById('user-rem'); let pts = document.getElementById('prompt').textContent; - if (pts) { - let nrem = user_rem - pts; - let nrem_str = nrem < 0 || nrem == 1 ? "BUST" : nrem; - elem.textContent = `${user_rem} » ${nrem_str}`; - } else { - elem.textContent = user_rem; - } + + updateUserStateRem(pts ? user_rem - pts : user_rem); } function boatTempRem(pts, str) { - let elem = document.getElementById('boat-rem'); - let nrem = boat_rem - pts; - let nrem_str = nrem < 0 || nrem == 1 ? "BUST" : nrem; - elem.textContent = `${nrem_str} « ${boat_rem}`; - + updateBoatStateRem(boat_rem - pts); document.getElementById('prompt').textContent = pts; promptSuggStr(str); } @@ -113,19 +122,19 @@ function promptBackspace() { } function setBoatActive() { - document.getElementById('user-rem').className = ''; - document.getElementById('boat-rem').className = 'active'; - promptMsgStr("Bot is throwing…"); + document.getElementById('user-state').className = ''; + document.getElementById('boat-state').className = 'active'; + promptMsgStr('Bot is throwing…'); prompt_disable = true; } function setUserActive() { - document.getElementById('user-rem').className = 'active'; - document.getElementById('boat-rem').className = ''; + document.getElementById('user-state').className = 'active'; + document.getElementById('boat-state').className = ''; prompt_disable = false; } -function promptSubmit() { +function promptSubmit(remaining) { clearOi(); if (prompt_disable) return; if (!match_active) { @@ -138,6 +147,9 @@ function promptSubmit() { if (!p_user) return; promptClear(); + if (remaining) + p_user = user_rem - p_user; + if (!stcall('user_visit', 'number', ['number'], [p_user])) { oi(); return; @@ -165,10 +177,6 @@ function boatVisitRes(rem, n, p1, p2, p3, ptr1, ptr2, ptr3) { stcall('draw_match'); setUserActive(); } else { - // backup to restore after bot is done - let user_sugg = document.getElementById('prompt-sugg').textContent; - promptSuggStr(''); - setTimeout(function() { boatTempRem(p1, s1); }, delay_ms); if (n > 1) { @@ -183,8 +191,8 @@ function boatVisitRes(rem, n, p1, p2, p3, ptr1, ptr2, ptr3) { updateBoatRem(rem); document.getElementById('prompt').textContent = ''; document.getElementById('match').textContent = ''; - promptSuggStr(user_sugg); stcall('draw_match'); + promptSuggStr(''); setUserActive(); }, delay_ms * (n + 1)); } @@ -192,8 +200,8 @@ function boatVisitRes(rem, n, p1, p2, p3, ptr1, ptr2, ptr3) { function matchOver() { match_active = false; - promptSuggStr("Press OK to play again."); - document.getElementById('user-rem').className = ''; + promptSuggStr('Press OK to play again.'); + document.getElementById('user-state').className = ''; } function drawVisitNames(n1, n2) { @@ -209,16 +217,15 @@ function drawVisitNames(n1, n2) { function drawVisit(visit_no, u_pts, u_rem, b_pts, b_rem, b_darts) { let elem = document.getElementById('match'); - for (let [i, v] of [visit_no, u_pts, u_rem, b_rem, b_pts, b_darts].entries()) { + for (let [i, v] of [u_pts, u_rem, visit_no, b_rem, b_pts, b_darts].entries()) { let div = document.createElement('div'); let vv = div.textContent = UTF8ToString(v); - if (i == 0) { - div.className = 'visit-no'; - } else if (i == 1 || i == 4) { + if (i == 0 || i == 4) { div.className = `p${POINT_CLASSES.find(x => x <= vv)}`; } else if (i == 5) { - div.className = 'darts'; + if (vv) div.textContent = `… ${vv}`; } + div.className += ` visit-col${i+1}`; elem.append(div); } @@ -252,6 +259,8 @@ function processKey(data) { promptSubmit(); else if (key == 'Backspace') promptBackspace(); + else if (key == 'r') + promptSubmit(true); } function modal(id) { diff --git a/web/static/index.html b/web/static/index.html index 861adc5..a5863ca 100644 --- a/web/static/index.html +++ b/web/static/index.html @@ -10,10 +10,20 @@ </head> <body> <div id="main"> + <div id="rem-bar"> + <div id="oi">oi!</div> + <div id="user-state"> + <div id="user-name">User</div> + <div id="user-rem"></div> + <div id="user-sugg"></div> + </div> + <div id="boat-state"> + <div id="boat-name">Bot</div> + <div id="boat-rem"></div> + <div id="boat-sugg"></div> + </div> + </div> <div id="keypad"> - <div id="user-rem"></div> - <div id="oi"></div> - <div id="boat-rem"></div> <div id="prompt-container"> <div id="prompt-msg"></div> <div id="prompt"></div> diff --git a/web/static/style.css b/web/static/style.css index 6bd312f..5287cfc 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -3,7 +3,7 @@ body { color: #ddd; - background-color: #1a1a1a; + background-color: #000; font-family: 'Lato', sans-serif; user-select: none; @@ -12,69 +12,108 @@ body { } div#main { + background-color: #1a1a1a; + height: calc(100vh - 2*2px); - width: calc(100vw - 2*2px); - margin: 2px; + width: min(80vh, calc(100vw - 2*2px)); + margin: 0 auto; + padding: 2px; display: grid; - grid-template-columns: min-content 2fr; - grid-template-rows: min-content 1fr; - grid-template-areas: "keypad settings-bar" "keypad match"; + grid-template-columns: 1fr; + grid-template-rows: min-content min-content 2fr 2fr; + grid-template-areas: "settings-bar" "rem-bar" "match" "keypad"; } div#keypad { grid-area: keypad; - font-size: 2vh; - - width: clamp(54vh, 30vw, 60vh); + font-size: clamp(1.5vh, 2vw, 2vh); display: grid; grid-template-columns: repeat(3, 1fr); - grid-template-rows: min-content 2fr; + grid-template-rows: 1.2fr; grid-auto-rows: 1fr; } div#oi { + visibility: hidden; + + background-color: #1a1a1a; font-size: 2em; + height: 1.2em; + width: 3ch; + + position: absolute; + left: 50%; + right: 50%; + top: 50%; + bottom: 50%; + transform: translate(-50%, -50%); display: flex; align-items: center; justify-content: center; } -div#user-rem, div#boat-rem { - background-color: #333; +div#rem-bar { + position: relative; + grid-column: 1 / span 3; + + font-size: clamp(1.5vh, 2vw, 2vh); + + display: grid; + grid-template-columns: repeat(2, 1fr); +} + +div#user-state, div#boat-state { + background-color: #222; font-size: 1.5em; margin: 2px; padding: 0.4rem; + flex-direction: column; display: flex; align-items: center; - justify-content: left; } -div#boat-rem { - grid-column: 3; +div#user-state.active, div#boat-state.active { + background-color: #240; +} +div#user-rem, div#boat-rem { + font-size: 3em; + font-weight: bold; +} + +div#boat-rem { justify-content: right; } -div#user-rem.active, div#boat-rem.active { - background-color: #240; +div#user-name, div#boat-name { + color: #aaa; +} + +div#user-sugg, div#boat-sugg { + color: #aaa; + font-size: 0.8em; +} + +div#user-sugg:after, div#boat-sugg:after { + content: '\200b'; } div#prompt-container { grid-column: 1 / span 3; - background-color: #333; + background-color: #222; margin: 2px; - display: grid; - grid-template-rows: 1fr 3fr 1fr; - grid-template-columns: 1fr; + display: flex; + align-items: center; + justify-content: center; } div#prompt-msg, div#prompt, div#prompt-sugg { @@ -82,15 +121,22 @@ div#prompt-msg, div#prompt, div#prompt-sugg { display: grid; align-items: center; - justify-content: center; } -div#prompt { - font-size: 5em; +div#prompt-msg, div#prompt-sugg { + flex: 1; + color: #aaa; + padding: 0 0.4rem; } div#prompt-sugg { - color: #aaa; + text-align: right; +} + +div#prompt { + text-align: center; + font-size: 3em; + width: 4ch; } div.key { @@ -124,8 +170,8 @@ div.key.num { div#settings-bar { grid-area: settings-bar; - background-color: #333; - font-size: 2vh; + background-color: #222; + font-size: clamp(1.5vh, 2vw, 2vh); margin: 2px; padding: 0.4rem; @@ -145,7 +191,7 @@ div#settings-bar div.input.first { } div#settings-bar div.input { - background-color: #282828; + background-color: #333; display: flex; flex-wrap: wrap; @@ -159,7 +205,7 @@ div#settings-bar span { div#settings-bar input { color: #ddd; - background-color: #304; + background-color: #3d2466; font-family: inherit; font-size: 1em; text-align: right; @@ -170,68 +216,62 @@ div#settings-bar input { } div#settings-bar div.help-button { - background-color: #304; - font-weight: bold; + background-color: #3d2466; + font-weight: 700; padding: 0 0.4em; } @media (hover: hover) and (pointer: fine) { div#settings-bar input:hover { - background-color: #608; + background-color: #5c3699; } div#settings-bar div.help-button:hover { - background-color: #608; + background-color: #5c3699; } } -div#settings-bar input#stdev:focus { +div#settings-bar input:focus { color: #fff; - background-color: #80a; + background-color: #6e41b8; + outline: #5a0 solid 3px; } div#settings-bar div.help-button:active { color: #fff; - background-color: #80a; -} - -div#settings-bar input#stdev:focus { - outline: #5a0 solid 3px; + background-color: #6e41b8; } div#match { grid-area: match; - background-color: #333; - font-size: 2vh; + background-color: #222; + font-size: clamp(1.5vh, 2vw, 2vh); - overflow-y: scroll; + overflow: auto; + scrollbar-gutter: stable both-edges; margin: 2px; padding: 0.4rem; display: grid; - grid-template-columns: repeat(6, max-content); + grid-template-columns: 1.5ch repeat(5, 2fr) 1.5ch; grid-auto-rows: min-content; grid-row-gap: 0.3em; - grid-column-gap: 1.5em; } div#match div { - font-size: 1.5em; - font-family: monospace; - white-space: pre; + font-size: 2em; - min-width: 3ch; + min-width: 0; display: flex; align-items: center; justify-content: center; } -div#match .user-name { color: #aaa; background-color: #444; grid-column: 2 / span 2; justify-content: center; } -div#match .boat-name { color: #aaa; background-color: #444; grid-column: 4 / span 2; justify-content: center; } -div#match .visit-no { color: #888; grid-column: 1; } +div#match .visit-col1 { grid-column: 2; } +div#match .visit-col3 { color: #888; grid-column: 4; } div#match .p0 { color: #f00; font-weight: bold; } div#match .p1 { color: #f00; } div#match .p20 { color: #f60; } @@ -240,7 +280,7 @@ div#match .p60 { color: #dd0; } div#match .p100 { color: #2c2; } div#match .p140 { color: #0f0; } div#match .p180 { color: #0f0; font-weight: bold; } -div#match .darts { color: #888; justify-content: left; } +div#match .visit-col6 { color: #888; justify-content: left; font-family: monospace; white-space: pre; } .modal { background-color: rgba(0, 0, 0, 0.6); @@ -256,7 +296,7 @@ div#match .darts { color: #888; justify-content: left; } } .modal-content { - background-color: #333; + background-color: #222; font-size: 1.4em; font-family: 'Source Serif Pro', serif; @@ -290,24 +330,7 @@ a:hover { color: #7d0; } -@media (max-aspect-ratio: 1/1) { - div#main { - grid-template-columns: 1fr; - grid-template-rows: min-content 1fr 3fr; - grid-template-areas: "settings-bar" "match" "keypad"; - } - - div#keypad, div#match, div#settings-bar { - font-size: clamp(1.5vh, 2vw, 2vh); - } - - div#keypad { - width: auto; - } -} - -/* -@media (max-aspect-ratio: 3/5) { +@media (max-aspect-ratio: 9/20) { div#settings-bar div.input { display: flex; flex-direction: column; @@ -321,4 +344,3 @@ a:hover { font-size: 3em; } } -*/ |