From 9ae3165bf18652ddec07afe45424bf1331d27b59 Mon Sep 17 00:00:00 2001 From: Geoffrey Allott Date: Mon, 15 Mar 2021 22:58:43 +0000 Subject: [PATCH] add bet slider for texas holdem --- site/modules/poker.js | 85 +++++++++++++++++++++++++++++++++++++++++-- site/style/poker.css | 53 +++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 4 deletions(-) diff --git a/site/modules/poker.js b/site/modules/poker.js index e9f128c..60fbb28 100644 --- a/site/modules/poker.js +++ b/site/modules/poker.js @@ -24,6 +24,9 @@ export class TexasHoldEm { this.svg = document.createElementNS(svgns, "svg"); this.svg.classList.add("knock-out-whist"); this.svg.setAttribute("viewBox", "0 0 500 500"); + this.mouse_clicked = false; + this.svg.onmousedown = () => this.mouse_clicked = true; + this.svg.onmouseup = () => this.mouse_clicked = false; const background = document.createElementNS(svgns, "rect"); background.setAttribute("width", "500"); @@ -49,13 +52,75 @@ export class TexasHoldEm { const controls = document.createElementNS(svgns, "rect"); controls.setAttribute("x", "310"); - controls.setAttribute("y", "435"); + controls.setAttribute("y", "410"); controls.setAttribute("width", "185"); - controls.setAttribute("height", "60"); + controls.setAttribute("height", "85"); controls.setAttribute("rx", "15"); controls.classList.add("controls"); this.svg.append(controls); + this.bet_size_area = document.createElementNS(svgns, "rect"); + this.bet_size_area.setAttribute("x", "317"); + this.bet_size_area.setAttribute("y", "417"); + this.bet_size_area.setAttribute("width", "38"); + this.bet_size_area.setAttribute("height", "16"); + this.bet_size_area.classList.add("bet-size-area"); + this.svg.append(this.bet_size_area); + + this.bet_size = document.createElementNS(svgns, "text"); + this.bet_size.setAttribute("x", "336"); + this.bet_size.setAttribute("y", "429"); + this.bet_size.classList.add("bet-size"); + this.bet_size_text = document.createTextNode("150"); + this.bet_size.append(this.bet_size_text); + this.svg.append(this.bet_size); + + this.bet_slider = document.createElementNS(svgns, "g"); + this.bet_slider.classList.add("bet-slider"); + + this.bet_slider_track = document.createElementNS(svgns, "rect"); + this.bet_slider_track.setAttribute("x", "360"); + this.bet_slider_track.setAttribute("y", "422"); + this.bet_slider_track.setAttribute("width", "125"); + this.bet_slider_track.setAttribute("height", "6"); + this.bet_slider_track.classList.add("bet-slider-track"); + const point = this.svg.createSVGPoint(); + this.bet_slider_track.onmousemove = e => { + if (this.mouse_clicked) { + point.x = e.clientX; + point.y = e.clientY; + const coords = point.matrixTransform(this.svg.getScreenCTM().inverse()); + const x = Math.max(360, Math.min(475, coords.x - 5)); + const p = Math.pow((x - 360) / 115, 2); + const bet = Math.round(this.min_bet() * (1 - p) + this.all_in_bet() * p); + this.bet_size_text.textContent = bet; + this.bet_slider_thumb.setAttribute("x", x); + } + }; + this.bet_slider_track.onclick = e => { + point.x = e.clientX; + point.y = e.clientY; + const coords = point.matrixTransform(this.svg.getScreenCTM().inverse()); + const x = Math.max(360, Math.min(475, coords.x - 5)); + const p = Math.pow((x - 360) / 115, 2); + const bet = Math.round(this.min_bet() * (1 - p) + this.all_in_bet() * p); + this.bet_size_text.textContent = bet; + this.bet_slider_thumb.setAttribute("x", x); + }; + this.bet_slider.append(this.bet_slider_track); + + this.bet_slider_thumb = document.createElementNS(svgns, "rect"); + this.bet_slider_thumb.setAttribute("x", "360"); + this.bet_slider_thumb.setAttribute("y", "419"); + this.bet_slider_thumb.setAttribute("width", "10"); + this.bet_slider_thumb.setAttribute("height", "12"); + this.bet_slider_thumb.classList.add("bet-slider-thumb"); + this.bet_slider_thumb.onmousemove = this.bet_slider_track.onmousemove; + this.bet_slider_thumb.onclick = this.bet_slider_track.onclick; + this.bet_slider.append(this.bet_slider_thumb); + + this.svg.append(this.bet_slider); + this.fold_control = document.createElementNS(svgns, "rect"); this.fold_control.setAttribute("x", "315"); this.fold_control.setAttribute("y", "440"); @@ -99,7 +164,7 @@ export class TexasHoldEm { this.bet_control.setAttribute("height", "50"); this.bet_control.setAttribute("rx", "10"); this.bet_control.onclick = () => { - const chips = prompt("Chips to bet", this.chips_to_call() + this.min_raise()); + const chips = +this.bet_size_text.textContent; if (chips !== null && !isNaN(Number(chips))) { this.send({type: "TakeAction", action: {action: "Bet", chips: Number(chips)}}); } @@ -130,6 +195,10 @@ export class TexasHoldEm { this.call_control.classList.toggle("active", this.active === this.username); this.call_control_text.textContent = this.active === this.username && this.chips_to_call() == 0 ? "Check" : "Call"; this.bet_control.classList.toggle("active", this.active === this.username); + this.bet_size_area.classList.toggle("active", this.active === this.username); + this.bet_slider.classList.toggle("active", this.active === this.username); + this.bet_size_text.textContent = this.min_bet(); + this.bet_slider_thumb.setAttribute("x", 360); for (const [username, [user, stack, active, bet]] of this.user_icons) { if (!this.seats.has(username)) { this.svg.removeChild(user); @@ -254,6 +323,14 @@ export class TexasHoldEm { } } + min_bet() { + return this.chips_to_call(); /* + this.min_raise() TODO */ + } + + all_in_bet() { + return this.stacks.get(this.username) || 0; + } + min_raise() { if (this.community.length === 0) { return Math.max(this.big_blind, Math.max(...this.bets.values()) - this.big_blind); @@ -393,7 +470,7 @@ export class TexasHoldEm { new CongratulateWinner(this.svg, user_action.username); break; default: - console.error("Unhandled action for knock-out whist", user_action); + console.error("Unhandled action for texas hold'em", user_action); break; } } diff --git a/site/style/poker.css b/site/style/poker.css index 045f36d..fb69b7d 100644 --- a/site/style/poker.css +++ b/site/style/poker.css @@ -26,3 +26,56 @@ pointer-events: none; text-anchor: middle; } + +.bet-size { + pointer-events: none; + text-anchor: middle; + font-size: 8pt; +} + +.bet-size-area { + fill: #808080; + stroke: black; + stroke-width: 1px; + transition: fill 0.5s; +} + +.bet-size-area.active { + fill: #ffffff; +} + +.bet-slider-track { + fill: black; + stroke: #808080; + stroke-width: 1px; + transition: stroke 0.5s; + pointer-events: none; + cursor: pointer; +} + +.bet-slider.active > .bet-slider-track { + stroke: #8080ff; + pointer-events: auto; +} + +.bet-slider.active:hover > .bet-slider-track { + stroke: #a0a0ff; +} + +.bet-slider-thumb { + fill: #808080; + stroke: black; + stroke-width: 1px; + transition: fill 0.5s; + pointer-events: none; + cursor: pointer; +} + +.bet-slider.active > .bet-slider-thumb { + fill: #8080ff; + pointer-events: auto; +} + +.bet-slider.active > .bet-slider-thumb:hover { + fill: #a0a0ff; +} -- 2.34.1