From 7e599410bf610f578bd6a92acb1579cc149f5665 Mon Sep 17 00:00:00 2001 From: Geoffrey Allott Date: Thu, 18 Mar 2021 20:14:11 +0000 Subject: [PATCH] various site improvements --- site/modules/card.js | 19 +++++- site/modules/chatroom.js | 129 ++++++++++++++++++++++++++++----------- site/modules/poker.js | 19 ++++-- site/modules/socket.js | 28 +++++++++ site/style/chatroom.css | 20 +++--- site/style/game-list.css | 8 +++ site/style/mainmenu.css | 3 +- site/style/poker.css | 7 +++ 8 files changed, 181 insertions(+), 52 deletions(-) diff --git a/site/modules/card.js b/site/modules/card.js index 4a3771d..be14c0f 100644 --- a/site/modules/card.js +++ b/site/modules/card.js @@ -25,9 +25,26 @@ export function short_suit(suit) { } } +export function pretty_suit(suit) { + switch (suit) { + case "Clubs": return "♣"; + case "Diamonds": return "♢"; + case "Hearts": return "♢"; + case "Spades": return "♠"; + } +} + +export function short_card(card) { + return short_rank(card.rank) + short_suit(card.suit); +} + +export function card_name(card) { + return short_rank(card.rank) + pretty_suit(card.suit); +} + export function card_href(card) { if (card === null) return "img/card-back-blue.svg"; - return "img/cards.svg#" + short_rank(card.rank) + short_suit(card.suit); + return "img/cards.svg#" + short_card(card); } export function suit_href(suit) { diff --git a/site/modules/chatroom.js b/site/modules/chatroom.js index 9a80c6c..0137fd6 100644 --- a/site/modules/chatroom.js +++ b/site/modules/chatroom.js @@ -1,3 +1,5 @@ +import { card_name, pretty_suit } from "./card.js"; + export class Chatroom { constructor(container, summary, actions, username, send) { this.container = container; @@ -18,11 +20,6 @@ export class Chatroom { this.chatroom_input.value = ""; }; this.chatroom.append(this.chatroom_input); - const close = document.createElement("button"); - close.classList.add("chatroom-close"); - close.innerText = "✗"; - close.onclick = () => this.send({type: "TakeAction", action: {action: "Leave"}}); - this.chatroom.append(close); this.container.append(this.chatroom); for (const user_action of this.actions) { @@ -34,19 +31,85 @@ export class Chatroom { } } + set_error_text(text) { + // TODO + } + take_action(user_action, initialising) { const is_at_end = this.chat.scrollTop + this.chat.clientHeight == this.chat.scrollHeight; switch (user_action.action.action) { case "Join": this.seats.set(user_action.username, user_action.action.seat); - this.chat.append(this.join_element(user_action.username)); + this.chat.append(this.join_element(user_action.username, "Joined")); break; case "Message": this.chat.append(this.message_element(user_action.username, user_action.action.message)); break; + case "PostBlind": + if (user_action.action.chips === 0) { + this.chat.append(this.info_element(user_action.username, "Posts ghost blind")); + } else { + this.chat.append(this.info_element(user_action.username, "Posts blind of " + user_action.action.chips)); + } + break; + case "Bet": + this.chat.append(this.info_element(user_action.username, "Bets " + user_action.action.chips)); + break; + case "Fold": + this.chat.append(this.info_element(user_action.username, "Folds")); + break; + case "TimeoutFold": + this.chat.append(this.info_element(user_action.username, "Folds due to timeout")); + break; + case "NextToDeal": + this.chat.append(this.info_element(user_action.username, "Next to deal")); + break; + case "ReceiveCard": + if (user_action.action.card === null) { + this.chat.append(this.info_element(user_action.username, "Receives card")); + } else { + this.chat.append(this.info_element(user_action.username, "Receives " + card_name(user_action.action.card))); + } + break; + case "CommunityCard": + this.chat.append(this.info_element(user_action.username, "Deals " + card_name(user_action.action.card))); + break; + case "EndDeal": + this.chat.append(this.info_element(user_action.username, "Ends deal")); + break; + case "RevealCard": + this.chat.append(this.info_element(user_action.username, "Reveals " + card_name(user_action.action.card))); + case "PlayCard": + this.chat.append(this.info_element(user_action.username, "Plays " + card_name(user_action.action.card))); + break; + case "CutCard": + this.chat.append(this.info_element(user_action.username, "Cuts " + card_name(user_action.action.card))); + break; + case "ChooseTrumps": + this.chat.append(this.info_element(user_action.username, "Chooses " + pretty_suit(user_action.action.suit) + " as trumps")); + break; + case "WinTrick": + this.chat.append(this.info_element(user_action.username, "Wins trick")); + break; + case "WinCall": + this.chat.append(this.info_element(user_action.username, "Wins the call")); + break; + case "WinHand": + this.chat.append(this.info_element( + user_action.username, + "Wins " + user_action.action.chips + " chips" + + (user_action.action.hand === null ? "" : " with " + user_action.action.hand) + )); + break; + case "WinGame": + this.chat.append(this.win_game_element(user_action.username, "Wins the game")); + break; + case "KnockedOut": + this.chat.append(this.leave_element(user_action.username, "Knocked out")); + break; case "Leave": this.seats.delete(user_action.username); - this.chat.append(this.leave_element(user_action.username)); + this.chat.append(this.leave_element(user_action.username, "Left")); if (!initialising && user_action.username === this.username) { this.send({type: "JoinLobby", filter: ""}); } @@ -63,45 +126,37 @@ export class Chatroom { } } - join_element(username) { - const join_element = document.createElement("div"); - join_element.classList.add("chatroom-join"); + chat_element(message_class, username, message) { + const chat_element = document.createElement("div"); + chat_element.classList.add(message_class); const username_element = document.createElement("div"); username_element.classList.add("chatroom-username"); username_element.innerText = username; - join_element.append(username_element); + chat_element.append(username_element); const text_element = document.createElement("div"); text_element.classList.add("chatroom-text"); - text_element.innerText = "Joined"; - join_element.append(text_element); - return join_element; + text_element.innerText = message; + chat_element.append(text_element); + return chat_element; + } + + join_element(username, message) { + return this.chat_element("chatroom-join", username, message); } message_element(username, message) { - const message_element = document.createElement("div"); - message_element.classList.add("chatroom-message"); - const username_element = document.createElement("div"); - username_element.classList.add("chatroom-username"); - username_element.innerText = username; - message_element.append(username_element); - const text_element = document.createElement("div"); - text_element.classList.add("chatroom-text"); - text_element.innerText = message; - message_element.append(text_element); - return message_element; + return this.chat_element("chatroom-message", username, message); } - leave_element(username) { - const leave_element = document.createElement("div"); - leave_element.classList.add("chatroom-leave"); - const username_element = document.createElement("div"); - username_element.classList.add("chatroom-username"); - username_element.innerText = username; - leave_element.append(username_element); - const text_element = document.createElement("div"); - text_element.classList.add("chatroom-text"); - text_element.innerText = "Left"; - leave_element.append(text_element); - return leave_element; + info_element(username, message) { + return this.chat_element("chatroom-info", username, message); + } + + win_game_element(username, message) { + return this.chat_element("chatroom-win-game", username, message); + } + + leave_element(username, message) { + return this.chat_element("chatroom-leave", username, message); } } diff --git a/site/modules/poker.js b/site/modules/poker.js index 6891836..b1ebce1 100644 --- a/site/modules/poker.js +++ b/site/modules/poker.js @@ -75,6 +75,16 @@ export class TexasHoldEm { 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"); @@ -217,9 +227,10 @@ export class TexasHoldEm { 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"; - 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); + 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); for (const [username, [user, stack, active, bet]] of this.user_icons) { @@ -347,7 +358,7 @@ export class TexasHoldEm { } min_bet() { - return this.chips_to_call(); /* + this.min_raise() TODO */ + return Math.min(this.all_in_bet(), this.chips_to_call() + this.min_raise()); } all_in_bet() { diff --git a/site/modules/socket.js b/site/modules/socket.js index 42e7553..180f85f 100644 --- a/site/modules/socket.js +++ b/site/modules/socket.js @@ -18,6 +18,7 @@ export class Socket { this.socket.onmessage = (msg) => this.onmessage(msg); this.socket.onclose = () => this.onclose(); this.state = "Connecting"; + this.last_filter = ""; this.scheduled_actions = []; this.schedule_timeout = null; @@ -67,8 +68,10 @@ export class Socket { this.state = "Connected"; break; case "LoginSuccess": + case "LeaveLobbySuccess": this.hide_login(); this.game = new MainMenu(this.container, message => this.send(message)); + this.container.append(this.close_button()); this.state = "LoggedIn"; break; case "JoinLobbyFailure": @@ -76,7 +79,9 @@ export class Socket { this.state = "LoggedIn"; break; case "JoinLobbySuccess": + this.last_filter = message.filter; this.game = new GameList(this.container, message.filter, message.games, message => this.send(message)) + this.container.append(this.close_button()); this.state = "InLobby"; break; case "NewGame": @@ -220,6 +225,28 @@ export class Socket { }; } + close_button() { + const close = document.createElement("button"); + close.classList.add("game-close"); + close.innerText = "✗"; + close.onclick = () => { + switch (this.state) { + case "LoggedIn": + this.send({type: "Logout"}); + break; + case "InLobby": + this.send({type: "LeaveLobby"}); + break; + case "InGame": + this.send({type: "TakeAction", action: {action: "Leave"}}); + this.send({type: "LeaveGame"}); + this.send({type: "JoinLobby", filter: this.last_filter}); + break; + } + }; + return close; + } + create_game_display(summary, actions) { this.container.textContent = ""; let Format; @@ -232,6 +259,7 @@ export class Socket { return; } this.game = new Format(this.container, summary, actions, this.auth.username, message => this.send(message)); + this.container.append(this.close_button()); } onclose() { diff --git a/site/style/chatroom.css b/site/style/chatroom.css index cc08952..4ff23a5 100644 --- a/site/style/chatroom.css +++ b/site/style/chatroom.css @@ -21,7 +21,7 @@ align-self: end; } -.chatroom-join, .chatroom-message, .chatroom-leave { +.chatroom-join, .chatroom-message, .chatroom-info, .chatroom-leave, .chatroom-win-game { display: flex; } @@ -36,6 +36,11 @@ border-radius: 3vw; } +.chatroom-info > .chatroom-username { + background-color: skyblue; + color: black; +} + .chatroom-join > .chatroom-username { background-color: limegreen; } @@ -49,6 +54,11 @@ background-color: red; } +.chatroom-win-game > .chatroom-username { + background: repeating-radial-gradient(circle at center, #a17f1a 0vw, gold, #a17f1a 2vw); + color: black; +} + .chatroom-text { justify-self: right; text-align: left; @@ -56,11 +66,3 @@ margin: 0.5vw; width: calc(100% - 36vw); } - -.chatroom-close { - display: block; - position: absolute; - right: 0; - top: 0; - font-size: inherit; -} diff --git a/site/style/game-list.css b/site/style/game-list.css index 8e52758..4096aeb 100644 --- a/site/style/game-list.css +++ b/site/style/game-list.css @@ -146,3 +146,11 @@ .game-title { font-weight: bold; } + +.game-close { + display: block; + position: absolute; + right: 0; + top: 0; + font-size: 5vw; +} diff --git a/site/style/mainmenu.css b/site/style/mainmenu.css index 0965336..68a5a71 100644 --- a/site/style/mainmenu.css +++ b/site/style/mainmenu.css @@ -1,7 +1,8 @@ .main-menu { display: flex; flex-wrap: wrap; - align-items: flex-start; + align-items: center; + justify-content: center; } .game-format-icon { diff --git a/site/style/poker.css b/site/style/poker.css index 4d0fae2..beb9a58 100644 --- a/site/style/poker.css +++ b/site/style/poker.css @@ -1,3 +1,8 @@ +.texas-hold-em * { + -webkit-user-select: none; + user-select: none; +} + .controls { fill: grey; stroke: black; @@ -38,10 +43,12 @@ stroke: black; stroke-width: 1px; transition: fill 0.5s; + pointer-events: none; } .bet-size-area.active { fill: #ffffff; + pointer-events: auto; } .bet-slider-area { -- 2.34.1