summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/dartboat_wasm.c20
-rw-r--r--web/static/dartboat.js85
-rw-r--r--web/static/index.html16
-rw-r--r--web/static/style.css168
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;
}
}
-*/