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;
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");
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");
}
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)) {