From: Geoffrey Allott Date: Sun, 21 Mar 2021 14:11:30 +0000 (+0000) Subject: add embedded chat for texas holdem X-Git-Url: https://git.pointlesshacks.com/?a=commitdiff_plain;h=f6bd92e42da014bb8b67b9147ce0b3ebd0cd2389;p=pokerwave.git add embedded chat for texas holdem --- diff --git a/site/modules/datetime.js b/site/modules/datetime.js new file mode 100644 index 0000000..9499403 --- /dev/null +++ b/site/modules/datetime.js @@ -0,0 +1,46 @@ +export function parse_datetime(input) { + const re = /^(?:(?[0-9]{4})-(?[0-9]{1,2})-(?[0-9]{1,2})\s)?\s*(?[0-9]{1,2}):(?[0-9]{2})(?::(?[0-9]{2}))?$/; + const match = input.match(re); + if (match === null) return null; + const datetime = new Date(); + if (match.groups.year !== undefined) datetime.setFullYear(+match.groups.year); + if (match.groups.month !== undefined) datetime.setMonth(+match.groups.month - 1); + if (match.groups.day !== undefined) datetime.setDate(+match.groups.day); + datetime.setHours(+match.groups.hour); + datetime.setMinutes(+match.groups.minute); + datetime.setSeconds(match.groups.second !== undefined ? +match.groups.second : 0); + return datetime.getTime(); +} + +export function stringify_datetime(millis) { + if (millis === null || millis === undefined) return null; + const datetime = new Date(millis); + const pad = num => String(num).padStart(2, '0'); + const now = new Date(); + let date = ""; + if (datetime.getFullYear() !== now.getFullYear() || datetime.getMonth() !== now.getMonth() || datetime.getDate() !== now.getDate()) { + date = datetime.getFullYear() + "-" + pad(datetime.getMonth() + 1) + "-" + pad(datetime.getDate()) + " "; + } + const time = pad(datetime.getHours()) + ":" + pad(datetime.getMinutes()); + let seconds = ""; + if (datetime.getSeconds() !== 0) { + seconds = ":" + pad(datetime.getSeconds()); + } + return date + time + seconds; +} + +export function parse_duration(input) { + const re = /^(?:(?[0-9]{1,2}):)?(?[0-9]{2}):(?[0-9]{2})$/; + const match = input.match(re); + if (match === null) return null; + return ((((match.groups.hours !== undefined ? +match.groups.hours : 0) * 60 + +match.groups.minutes) * 60) + +match.groups.seconds) * 1000; +} + +export function stringify_duration(millis) { + if (millis === null || millis === undefined) return null; + const hours = ((millis / 1000 / 60 / 60) >> 0); + const minutes = ((millis / 1000 / 60) >> 0) % 60; + const seconds = ((millis / 1000) >> 0) % 60; + const pad = num => String(num).padStart(2, '0'); + return (hours !== 0 ? pad(hours) + ":" : "") + pad(minutes) + ":" + pad(seconds); +} diff --git a/site/modules/gamelist.js b/site/modules/gamelist.js index 9237549..a75a1cb 100644 --- a/site/modules/gamelist.js +++ b/site/modules/gamelist.js @@ -1,3 +1,4 @@ +import { parse_datetime, parse_duration, stringify_datetime, stringify_duration } from "./datetime.js"; import { random_title } from "./words.js"; export class GameList { @@ -103,20 +104,37 @@ export class GameList { const id_row = document.createElement("tr"); const id_header = document.createElement("th"); - id_header.innerText = "id"; + id_header.innerText = "ID"; const id_value = document.createElement("td"); id_value.innerText = game.id; id_row.append(id_header); id_row.append(id_value); table.append(id_row); + const field_types = { + start_time: "datetime", + round_length: "duration", + tournament_length: "duration", + action_timeout: "duration", + }; + for (const setting of Object.keys(game.settings)) { if (setting === "title") continue; const row = document.createElement("tr"); const header = document.createElement("th"); - header.innerText = setting; + header.innerText = setting.split("_").map(w => w[0].toUpperCase() + w.substr(1)).join(" "); const value = document.createElement("td"); - value.innerText = game.settings[setting]; + switch (field_types[setting]) { + case "datetime": + value.innerText = stringify_datetime(game.settings[setting]) || "When Full"; + break; + case "duration": + value.innerText = stringify_duration(game.settings[setting]) || ""; + break; + default: + value.innerText = game.settings[setting]; + break; + } row.append(header); row.append(value); table.append(row); @@ -185,15 +203,16 @@ export class GameList { table.append(format_row); const fields = [ - { name: "max_players", display: "Max Players", value: 2, formats: ["TexasHoldEm", "KnockOutWhist"] }, - { name: "small_blind", display: "Small Blind", value: 25, formats: ["TexasHoldEm"] }, - { name: "starting_stack", display: "Starting Stack", value: 1000, formats: ["TexasHoldEm"] }, - { name: "round_length", display: "Round Length", value: 60000, formats: ["TexasHoldEm"] }, - { name: "tournament_length", display: "Tournament Length", value: 600000, formats: ["TexasHoldEm"] }, - { name: "action_timeout", display: "Action Timeout", value: 30000, formats: ["TexasHoldEm"] }, + { name: "start_time", display: "Start Time", value: "", type: "datetime", formats: ["TexasHoldEm", "KnockOutWhist"] }, + { name: "max_players", display: "Max Players", value: 2, type: "number", formats: ["TexasHoldEm", "KnockOutWhist"] }, + { name: "small_blind", display: "Small Blind", value: 25, type: "number", formats: ["TexasHoldEm"] }, + { name: "starting_stack", display: "Starting Stack", value: 5000, step: 1000, type: "number", formats: ["TexasHoldEm"] }, + { name: "round_length", display: "Round Length", value: "", type: "duration", formats: ["TexasHoldEm"] }, + { name: "tournament_length", display: "Tournament Length", value: "", type: "duration", formats: ["TexasHoldEm"] }, + { name: "action_timeout", display: "Action Timeout", value: "", type: "duration", formats: ["TexasHoldEm"] }, ]; - for (const {name, display, value, formats} of fields) { + for (const {name, display, value, type, step, formats} of fields) { const row = document.createElement("tr"); row.classList.add("game-field"); for (const format of formats) { @@ -204,9 +223,42 @@ export class GameList { row.append(title); const cell = document.createElement("td"); const input = document.createElement("input"); - input.setAttribute("type", "number"); + switch (type) { + case "datetime": + input.setAttribute("placeholder", "[yyyy-mm-dd] hh:mm[:ss]"); + input.onchange = () => { + settings[name] = parse_datetime(input.value); + input.classList.toggle("invalid-input", settings[name] === null && input.value !== ""); + if (settings[name] === null) { + delete settings[name]; + } + }; + break; + case "duration": + input.setAttribute("placeholder", "[hh:]mm:ss"); + input.onchange = () => { + settings[name] = parse_duration(input.value); + input.classList.toggle("invalid-input", settings[name] === null && input.value !== ""); + if (settings[name] === null) { + delete settings[name]; + } + }; + break; + case "number": + input.setAttribute("type", "number"); + input.setAttribute("min", 0); + if (step !== undefined) { + input.setAttribute("step", step); + } + input.onchange = () => { + settings[name] = Number(input.value); + if (settings[name] === 0) { + delete settings[name]; + } + }; + break; + } input.value = value; - input.onchange = () => settings[name] = Number(input.value); input.onchange(); cell.append(input); row.append(cell); diff --git a/site/modules/poker.js b/site/modules/poker.js index 72c6b54..6ea0fd5 100644 --- a/site/modules/poker.js +++ b/site/modules/poker.js @@ -1,6 +1,7 @@ const svgns = "http://www.w3.org/2000/svg"; import { card_href, suit_href } from "./card.js"; +import { Chatroom } from "./chatroom.js"; import { CongratulateWinner } from "./winner.js"; export class TexasHoldEm { @@ -215,11 +216,27 @@ export class TexasHoldEm { bet_control_label.classList.add("bet-control-label"); this.svg.append(bet_control_label); + this.chat_control = document.createElementNS(svgns, "rect"); + this.chat_control.setAttribute("x", "5"); + this.chat_control.setAttribute("y", "470"); + this.chat_control.setAttribute("width", "25"); + this.chat_control.setAttribute("height", "25"); + this.chat_control.setAttribute("rx", "2"); + this.chat_control.onclick = () => this.chatroom_container.classList.toggle("hidden"); + this.chat_control.classList.add("chat-control"); + this.svg.append(this.chat_control); + this.container.append(this.svg); for (const user_action of this.actions) { this.take_action(user_action); } + this.chatroom_container = document.createElement("div"); + this.chatroom_container.classList.add("embedded-chatroom"); + this.chatroom = new Chatroom(this.chatroom_container, summary, actions, username, send); + + this.container.append(this.chatroom_container); + if (!this.seats.has(this.username)) { this.send({type: "TakeAction", action: {action: "Join", seat: 0, chips: this.summary.settings.starting_stack}}); } diff --git a/site/style/chatroom.css b/site/style/chatroom.css index fddab8d..2d2c418 100644 --- a/site/style/chatroom.css +++ b/site/style/chatroom.css @@ -2,7 +2,7 @@ width: 100%; height: 100%; display: grid; - font-size: 4vw; + font-size: 4vmin; overflow: hidden; position: relative; background-color: #dfefff; @@ -16,7 +16,7 @@ .chatroom > input { width: 100%; - height: 10vw; + height: 10vmin; font-size: inherit; align-self: end; } @@ -27,13 +27,13 @@ .chatroom-username { justify-self: left; - width: 36vw; + width: 36vmin; height: 100%; - margin: 0.5vw; + margin: 0.5vmin; background-color: grey; color: white; text-align: center; - border-radius: 3vw; + border-radius: 3vmin; } .chatroom-error > .chatroom-username { @@ -59,7 +59,7 @@ } .chatroom-win-game > .chatroom-username { - background: repeating-radial-gradient(circle at center, #a17f1a 0vw, gold, #a17f1a 2vw); + background: repeating-radial-gradient(circle at center, #a17f1a 0vmin, gold, #a17f1a 2vmin); color: black; } @@ -67,6 +67,6 @@ justify-self: right; text-align: left; height: 100%; - margin: 0.5vw; - width: calc(100% - 36vw); + margin: 0.5vmin; + width: calc(100% - 36vmin); } diff --git a/site/style/game.css b/site/style/game.css index 6c0cc4c..deb73af 100644 --- a/site/style/game.css +++ b/site/style/game.css @@ -13,3 +13,24 @@ top: 0; font-size: 5vw; } + +@media (max-aspect-ratio: 1/1) { + .embedded-chatroom { + grid-row: 2; + grid-column: 1; + width: 100vw; + height: calc(100vh - 100vw); + } +} + +@media (min-aspect-ratio: 1/1) { + .embedded-chatroom { + grid-row: 1; + grid-column: 2; + width: calc(100vw - 100vh); + height: 100vh; + } +} + +.embedded-chatroom + grid-column: 2; diff --git a/site/style/poker.css b/site/style/poker.css index beb9a58..f0446b9 100644 --- a/site/style/poker.css +++ b/site/style/poker.css @@ -9,6 +9,17 @@ stroke-width: 2px; } +.chat-control { + fill: #e0e0e0; + stroke: black; + stroke-width: 1px; + transition: fill 0.5s; +} + +.chat-control:hover { + fill: #ffffff; +} + .fold-control, .call-control, .bet-control { fill: #808080; stroke: black;