break out bet controls into a separate class
authorGeoffrey Allott <geoffrey@allott.email>
Sat, 20 May 2023 19:50:05 +0000 (20:50 +0100)
committerGeoffrey Allott <geoffrey@allott.email>
Sat, 20 May 2023 19:50:05 +0000 (20:50 +0100)
site/modules/poker.js

index b83354e56a144d8fc8cd71751723060c5c9d3d9f..f3058f107b843d2eec701aa1d1ddf7bef23001ee 100644 (file)
@@ -4,6 +4,106 @@ import { card_href, suit_href } from "./card.js";
 import { Chatroom } from "./chatroom.js";
 import { CongratulateWinner } from "./winner.js";
 
+function set_element_attributes(element, attributes) {
+    for (const [attr, value] of attributes) {
+        element.setAttribute(attr, value);
+    }
+}
+
+function create_svg_element(svg, name, class_list, attributes) {
+    const element = document.createElementNS(svgns, name);
+    set_element_attributes(element, attributes);
+    for (const cls of class_list) {
+        element.classList.add(cls);
+    }
+    svg.append(element);
+    return element;
+}
+
+export class BetControls {
+    constructor(game) {
+        this.game = game
+        this.mouse_clicked = false;
+        document.addEventListener("mousedown", () => this.mouse_clicked = true);
+        document.addEventListener("mouseup", () => this.mouse_clicked = false);
+
+        this.background = create_svg_element(this.game.svg, "rect", ["controls"], [["x", "310"], ["y", "410"], ["width", "185"], ["height", "85"], ["rx", "15"]])
+        this.bet_size_area = create_svg_element(this.game.svg, "rect", ["bet-size-area"], [["x", "317"], ["y", "417"], ["width", "38"], ["height", "16"]])
+        this.bet_size_area.onclick = () => {
+            const chips = prompt("Chips to bet", this.bet_size_text.textContent);
+            if (chips !== null && !isNaN(Number(chips))) {
+                const bet = Math.max(this.game.min_bet(), Math.min(this.game.all_in_bet(), Number(chips)));
+                this.bet_size_text.textContent = Number(chips);
+                const p = (bet - this.game.min_bet()) / (this.game.all_in_bet() - this.game.min_bet());
+                const x = Math.max(360, Math.min(475, Math.sqrt(p) * 115 + 360));
+                this.bet_slider_thumb.setAttribute("x", x);
+            }
+        };
+
+        this.bet_size = create_svg_element(this.game.svg, "text", ["bet-size"], [["x", "336"], ["y", "429"]])
+        this.bet_size_text = document.createTextNode("150");
+        this.bet_size.append(this.bet_size_text);
+
+        const point = this.game.svg.createSVGPoint();
+        const move_slider = e => {
+            point.x = e.clientX;
+            point.y = e.clientY;
+            const coords = point.matrixTransform(this.game.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.game.min_bet() * (1 - p) + this.game.all_in_bet() * p);
+            this.bet_size_text.textContent = bet;
+            this.bet_slider_thumb.setAttribute("x", x);
+        };
+
+        this.bet_slider = create_svg_element(this.game.svg, "g", ["bet-slider"], []);
+        this.bet_slider_area = create_svg_element(this.bet_slider, "rect", ["bet-slider-area"], [["x", "360"], ["y", "417"], ["width", "125"], ["height", "16"]])
+        this.bet_slider_track = create_svg_element(this.bet_slider, "rect", ["bet-slider-track"], [["x", "360"], ["y", "422"], ["width", "125"], ["height", "6"]])
+        this.bet_slider_thumb = create_svg_element(this.bet_slider, "rect", ["bet-slider-thumb"], [["x", "360"], ["y", "419"], ["width", "10"], ["height", "12"]])
+        this.bet_slider_area.onmousedown = this.bet_slider_track.onmousedown = this.bet_slider_thumb.onmousedown = move_slider;
+        this.bet_slider_area.onmousemove = this.bet_slider_track.onmousemove = this.bet_slider_thumb.onmousemove = e => { if (this.mouse_clicked) move_slider(e); };
+        this.bet_slider_area.ontouchmove = this.bet_slider_track.ontouchmove = this.bet_slider_thumb.ontouchmove = e => move_slider(e.touches.item(0));
+
+        this.fold_control = create_svg_element(this.game.svg, "rect", ["fold-control"], [["x", "315"], ["y", "440"], ["width", "55"], ["height", "50"], ["rx", "10"]])
+        this.fold_control.onclick = () => this.game.send({type: "TakeAction", action: {action: "Fold"}});
+
+        this.fold_control_label = create_svg_element(this.game.svg, "text", ["fold-control-label"], [["x", "342.5"], ["y", "470"]])
+        this.fold_control_text = document.createTextNode("Fold");
+        this.fold_control_label.append(this.fold_control_text);
+
+        this.call_control = create_svg_element(this.game.svg, "rect", ["call-control"], [["x", "375"], ["y", "440"], ["width", "55"], ["height", "50"], ["rx", "10"]])
+        this.call_control.onclick = () => this.game.send({type: "TakeAction", action: {action: "Bet", chips: this.game.chips_to_call()}});
+
+        this.call_control_label = create_svg_element(this.game.svg, "text", ["call-control-label"], [["x", "402.5"], ["y", "470"]]);
+        this.call_control_text = document.createTextNode("Call");
+        this.call_control_label.append(this.call_control_text);
+
+        this.bet_control = create_svg_element(this.game.svg, "rect", ["bet-control"], [["x", "435"], ["y", "440"], ["width", "55"], ["height", "50"], ["rx", "10"]])
+        this.bet_control.onclick = () => {
+            const chips = +this.bet_size_text.textContent;
+            if (chips !== null && !isNaN(Number(chips))) {
+                game.send({type: "TakeAction", action: {action: "Bet", chips: Number(chips)}});
+            }
+        }
+
+        this.bet_control_label = create_svg_element(this.game.svg, "text", ["bet-control-label"], [["x", "462.5"], ["y", "470"]])
+        this.bet_control_text = document.createTextNode("Bet");
+        this.bet_control_label.append(this.bet_control_text);
+    }
+
+    redraw() {
+        this.fold_control.classList.toggle("active", this.game.active === this.game.username && this.game.chips_to_call() > 0);
+        this.call_control.classList.toggle("active", this.game.active === this.game.username);
+        this.call_control_text.textContent = this.game.active === this.game.username && this.game.chips_to_call() == 0 ? "Check" : "Call";
+        const can_bet = this.game.active === this.game.username && this.game.chips_to_call() < this.game.all_in_bet();
+        this.bet_control.classList.toggle("active", can_bet);
+        this.bet_size_area.classList.toggle("active", can_bet);
+        this.bet_slider.classList.toggle("active", can_bet);
+        this.bet_size_text.textContent = this.game.min_bet();
+        this.bet_slider_thumb.setAttribute("x", 360);
+    }
+};
+
 export class TexasHoldEm {
     constructor(container, summary, actions, username, send, close) {
         this.container = container;
@@ -23,10 +123,6 @@ export class TexasHoldEm {
         this.big_blind = this.small_blind * 2;
         this.error_text_timeout = null;
 
-        this.mouse_clicked = false;
-        document.addEventListener("mousedown", () => this.mouse_clicked = true);
-        document.addEventListener("mouseup", () => this.mouse_clicked = false);
-
         this.svg = document.createElementNS(svgns, "svg");
         this.svg.classList.add("texas-hold-em");
         this.svg.setAttribute("viewBox", "0 0 500 500");
@@ -80,149 +176,7 @@ export class TexasHoldEm {
         pot_size.append(this.pot_size_text);
         this.svg.append(pot_size);
 
-        const controls = document.createElementNS(svgns, "rect");
-        controls.setAttribute("x", "310");
-        controls.setAttribute("y", "410");
-        controls.setAttribute("width", "185");
-        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.bet_size_area.onclick = () => {
-            const chips = prompt("Chips to bet", this.bet_size_text.textContent);
-            if (chips !== null && !isNaN(Number(chips))) {
-                const bet = Math.max(this.min_bet(), Math.min(this.all_in_bet(), Number(chips)));
-                this.bet_size_text.textContent = Number(chips);
-                const p = (bet - this.min_bet()) / (this.all_in_bet() - this.min_bet());
-                const x = Math.max(360, Math.min(475, Math.sqrt(p) * 115 + 360));
-                this.bet_slider_thumb.setAttribute("x", x);
-            }
-        };
-        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);
-
-        const move_slider = 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 = document.createElementNS(svgns, "g");
-        this.bet_slider.classList.add("bet-slider");
-
-        this.bet_slider_area = document.createElementNS(svgns, "rect");
-        this.bet_slider_area.setAttribute("x", "360");
-        this.bet_slider_area.setAttribute("y", "417");
-        this.bet_slider_area.setAttribute("width", "125");
-        this.bet_slider_area.setAttribute("height", "16");
-        this.bet_slider_area.onmousedown = move_slider;
-        this.bet_slider_area.onmousemove = e => { if (this.mouse_clicked) move_slider(e); };
-        this.bet_slider_area.ontouchmove = e => move_slider(e.touches.item(0));
-        this.bet_slider_area.classList.add("bet-slider-area");
-        this.bet_slider.append(this.bet_slider_area);
-
-        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.onmousedown = move_slider;
-        this.bet_slider_track.onmousemove = e => { if (this.mouse_clicked) move_slider(e); };
-        this.bet_slider_track.ontouchmove = e => move_slider(e.touches.item(0));
-        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.onmousedown = move_slider;
-        this.bet_slider_thumb.onmousemove = e => { if (this.mouse_clicked) move_slider(e); };
-        this.bet_slider_thumb.ontouchmove = e => move_slider(e.touches.item(0));
-        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");
-        this.fold_control.setAttribute("width", "55");
-        this.fold_control.setAttribute("height", "50");
-        this.fold_control.setAttribute("rx", "10");
-        this.fold_control.onclick = () => this.send({type: "TakeAction", action: {action: "Fold"}});
-        this.fold_control.classList.add("fold-control");
-        this.svg.append(this.fold_control);
-
-        const fold_control_label = document.createElementNS(svgns, "text");
-        const fold_control_text = document.createTextNode("Fold");
-        fold_control_label.append(fold_control_text);
-        fold_control_label.setAttribute("x", "342.5");
-        fold_control_label.setAttribute("y", "470");
-        fold_control_label.classList.add("fold-control-label");
-        this.svg.append(fold_control_label);
-
-        this.call_control = document.createElementNS(svgns, "rect");
-        this.call_control.setAttribute("x", "375");
-        this.call_control.setAttribute("y", "440");
-        this.call_control.setAttribute("width", "55");
-        this.call_control.setAttribute("height", "50");
-        this.call_control.setAttribute("rx", "10");
-        this.call_control.onclick = () => this.send({type: "TakeAction", action: {action: "Bet", chips: this.chips_to_call()}});
-        this.call_control.classList.add("call-control");
-        this.svg.append(this.call_control);
-
-        const call_control_label = document.createElementNS(svgns, "text");
-        this.call_control_text = document.createTextNode("Call");
-        call_control_label.append(this.call_control_text);
-        call_control_label.setAttribute("x", "402.5");
-        call_control_label.setAttribute("y", "470");
-        call_control_label.classList.add("call-control-label");
-        this.svg.append(call_control_label);
-
-        this.bet_control = document.createElementNS(svgns, "rect");
-        this.bet_control.setAttribute("x", "435");
-        this.bet_control.setAttribute("y", "440");
-        this.bet_control.setAttribute("width", "55");
-        this.bet_control.setAttribute("height", "50");
-        this.bet_control.setAttribute("rx", "10");
-        this.bet_control.onclick = () => {
-            const chips = +this.bet_size_text.textContent;
-            if (chips !== null && !isNaN(Number(chips))) {
-                this.send({type: "TakeAction", action: {action: "Bet", chips: Number(chips)}});
-            }
-        }
-        this.bet_control.classList.add("bet-control");
-        this.svg.append(this.bet_control);
-
-        const bet_control_label = document.createElementNS(svgns, "text");
-        const bet_control_text = document.createTextNode("Bet");
-        bet_control_label.append(bet_control_text);
-        bet_control_label.setAttribute("x", "462.5");
-        bet_control_label.setAttribute("y", "470");
-        bet_control_label.classList.add("bet-control-label");
-        this.svg.append(bet_control_label);
+        this.bet_controls = new BetControls(this)
 
         this.close_control = document.createElementNS(svgns, "rect");
         this.close_control.setAttribute("x", "460");
@@ -323,15 +277,7 @@ export class TexasHoldEm {
     }
 
     redraw_players() {
-        this.fold_control.classList.toggle("active", this.active === this.username && this.chips_to_call() > 0);
-        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";
-        const can_bet = this.active === this.username && this.chips_to_call() < this.all_in_bet();
-        this.bet_control.classList.toggle("active", can_bet);
-        this.bet_size_area.classList.toggle("active", can_bet);
-        this.bet_slider.classList.toggle("active", can_bet);
-        this.bet_size_text.textContent = this.min_bet();
-        this.bet_slider_thumb.setAttribute("x", 360);
+        this.bet_controls.redraw()
         this.pot_size_text.textContent = this.pot || "";
         for (const [username, [user, stack, active, bet]] of this.user_icons) {
             if (!this.seats.has(username)) {