Created
May 31, 2022 04:18
-
-
Save jswny/623a4c7678ba6cd0966b7f2c9e8acedb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Poker Now HUD | |
// @namespace http://j1.io/ | |
// @version 0.1 | |
// @description HUD for Poker Now | |
// @author You | |
// @match https://www.pokernow.club/games/* | |
// @icon https://cdn.pokernow.club/favicon-cd2bc2773f4f49ce85f0.png | |
// @grant none | |
// ==/UserScript== | |
(function () { | |
"use strict"; | |
console.debug("Loading HUD..."); | |
const gameId = getGameId(); | |
console.debug(`Game ID: ${gameId}`); | |
const inititalInterval = 500; | |
const regularInterval = 5000; | |
setTimeout(setPlayerInfoOverflows, inititalInterval); | |
setTimeout(refreshHud, inititalInterval, gameId); | |
setInterval(refreshHud, regularInterval, gameId); | |
})(); | |
function getGameId() { | |
const path = window.location.pathname; | |
const gameIdRegex = /\/games\/(.*)/; | |
const matches = path.match(gameIdRegex); | |
return matches[1]; | |
} | |
function getPlayerElements() { | |
return document.getElementsByClassName("table-player"); | |
} | |
function setPlayerInfoOverflows() { | |
const playerInfoElements = document.querySelectorAll( | |
".table-player-infos-ctn" | |
); | |
playerInfoElements.forEach((element) => { | |
element.style.overflow = "visible"; | |
}); | |
} | |
function refreshHud(gameId) { | |
fetchLogEntries(gameId) | |
.then(parseBeginningOfHandIndex) | |
.then(([entries, index]) => parseStreets(entries, index)) | |
.then(parseMovesByPlayer) | |
.then(hydrateHud); | |
} | |
function fetchLogEntries(gameId) { | |
const logUrl = `https://www.pokernow.club/games/${gameId}/log?before_at=&after_at=&mm=false&v=2`; | |
return fetch(logUrl) | |
.then((response) => response.json()) | |
.then((data) => data.logs); | |
} | |
function parseBeginningOfHandIndex(entries) { | |
const beginningOfHandEntryIndex = entries.findIndex((entry) => | |
entry.msg.includes("-- starting hand") | |
); | |
const numMoves = beginningOfHandEntryIndex + 1; | |
console.debug(`Found ${numMoves} moves from the current hand`); | |
return [entries, beginningOfHandEntryIndex]; | |
} | |
function parseStreets(entries, beginningOfHandEntryIndex) { | |
console.debug("Parsing streets..."); | |
let movesByStreet = new Map(); | |
let currentStreet = "PF"; | |
let currentStreetMoves = []; | |
for (let i = beginningOfHandEntryIndex; i >= 0; i--) { | |
const entryMessage = entries[i].msg; | |
let streetChange = false; | |
let previousStreet = currentStreet; | |
if (entryMessage.includes("Flop: ")) { | |
currentStreet = "FL"; | |
streetChange = true; | |
} else if (entryMessage.includes("Turn: ")) { | |
currentStreet = "TU"; | |
streetChange = true; | |
} else if (entryMessage.includes("River: ")) { | |
currentStreet = "RV"; | |
streetChange = true; | |
} | |
if (streetChange) { | |
movesByStreet.set(previousStreet, currentStreetMoves); | |
currentStreetMoves = []; | |
} else { | |
currentStreetMoves.push(entryMessage); | |
} | |
} | |
movesByStreet.set(currentStreet, currentStreetMoves); | |
return movesByStreet; | |
} | |
function parseMovesByPlayer(movesByStreet) { | |
console.debug("Parsing player moves..."); | |
let movesByPlayer = new Map(); | |
const nameRegex = /"([^|]+)"/; | |
for (const [streetName, moves] of movesByStreet) { | |
for (const move of moves) { | |
const nameMatches = move.match(nameRegex); | |
if (nameMatches != null) { | |
const playerName = nameMatches[1]; | |
let playerMovesByStreet = movesByPlayer.get(playerName); | |
if (playerMovesByStreet) { | |
const playerStreetMoves = playerMovesByStreet.get(streetName); | |
if (playerStreetMoves) { | |
playerStreetMoves.push(move); | |
} else { | |
playerMovesByStreet.set(streetName, [move]); | |
} | |
} else { | |
playerMovesByStreet = new Map(); | |
playerMovesByStreet.set(streetName, [move]); | |
movesByPlayer.set(playerName, playerMovesByStreet); | |
} | |
} | |
} | |
} | |
console.debug(movesByPlayer); | |
return movesByPlayer; | |
} | |
function hydrateHud(movesByPlayer) { | |
const playerElements = getPlayerElements(); | |
console.debug(`Hydrating HUD for ${playerElements.length} players...`); | |
const nameRegex = /(.*) @/; | |
for (const playerElement of playerElements) { | |
const playerName = | |
playerElement.querySelector(".table-player-name").innerText; | |
let playerMoves = []; | |
for (const [playerNameWithId, playerMovesByStreet] of movesByPlayer) { | |
const nameMatches = playerNameWithId.match(nameRegex); | |
if (nameMatches != null && nameMatches[1] == playerName) { | |
const existingMovesElement = | |
playerElement.querySelector("#player-moves"); | |
if (existingMovesElement) { | |
existingMovesElement.remove(); | |
} | |
const movesElement = buildMovesElementForPlayer(playerMovesByStreet); | |
const playerInfoElement = playerElement.querySelector( | |
".table-player-infos-ctn" | |
); | |
playerInfoElement.appendChild(movesElement); | |
} | |
} | |
} | |
} | |
function parseMoveToShorthand(move) { | |
const checkRegex = /.* checks/; | |
const betRegex = /.* bets (\d+)/; | |
const callRegex = /.* calls (\d+)/; | |
const raiseRegex = /.* raises to (\d+)/; | |
const checkMatch = move.match(checkRegex); | |
const betMatch = move.match(betRegex); | |
const callMatch = move.match(callRegex); | |
const raiseMatch = move.match(raiseRegex); | |
let shorthand = null; | |
if (checkMatch) { | |
shorthand = "Check"; | |
} else if (betMatch) { | |
shorthand = `Bet ${betMatch[1]}`; | |
} else if (callMatch) { | |
shorthand = `Call ${callMatch[1]}`; | |
} else if (raiseMatch) { | |
shorthand = `Raise ${raiseMatch[1]}`; | |
} | |
return shorthand; | |
} | |
function buildMovesElementForPlayer(playerMovesByStreet) { | |
const movesElement = document.createElement("div"); | |
movesElement.id = "player-moves"; | |
movesElement.style.position = "absolute"; | |
movesElement.style.left = "5.2rem"; | |
movesElement.style.top = "2.6rem"; | |
movesElement.style.width = "4.7rem"; | |
movesElement.style.textAlign = "left"; | |
movesElement.style.margin = "0px"; | |
movesElement.style.right = "0px"; | |
movesElement.style.lineHeight = "0.6rem"; | |
movesElement.style.fontSize = "0.5rem"; | |
movesElement.style.color = "rgb(232, 230, 227)"; | |
movesElement.style.width = "auto"; | |
addMovesElementContentForPlayer(playerMovesByStreet, movesElement); | |
return movesElement; | |
} | |
function addMovesElementContentForPlayer(playerMovesByStreet, movesElement) { | |
for (const [street, playerStreetMoves] of playerMovesByStreet) { | |
const shorthandMoves = playerStreetMoves | |
.slice() | |
.map(parseMoveToShorthand) | |
.filter((m) => m != null) | |
.join(", "); | |
let color; | |
switch (street) { | |
case "PF": | |
color = "lightblue"; | |
break; | |
case "FL": | |
color = "green"; | |
break; | |
case "TU": | |
color = "orange"; | |
break; | |
case "RV": | |
color = "red"; | |
break; | |
} | |
const shorthandMovesWithStreet = `${street}: ${shorthandMoves}`; | |
const playerStreetMovesElement = document.createElement("p"); | |
playerStreetMovesElement.innerText = shorthandMovesWithStreet; | |
playerStreetMovesElement.style.color = color; | |
movesElement.appendChild(playerStreetMovesElement); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment