fix casino js

pull/83/head
Aevann 2022-12-29 12:58:51 +02:00
parent 56b80d447d
commit ed323817f5
8 changed files with 883 additions and 887 deletions

View File

@ -0,0 +1,224 @@
function makeBlackjackRequest(action) {
const xhr = new XMLHttpRequest();
xhr.open("post", `/casino/twentyone/${action}`);
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleBlackjackResponse.bind(null, xhr);
xhr.blackjackAction = action;
return xhr;
}
function handleBlackjackResponse(xhr) {
let status;
try {
const response = JSON.parse(xhr.response);
const succeeded = xhr.status >= 200 &&
xhr.status < 300 &&
response &&
!response.error;
clearResult();
status = xhr.status;
if (status == 429) {
throw new Error(response["details"]);
}
if (succeeded) {
updateBlackjackTable(response.state);
updateFeed(response.feed);
updatePlayerCurrencies(response.gambler);
} else {
console.error("Error: ", response.error);
throw new Error("Error")
}
} catch (error) {
const results = {
deal: "Unable to deal a new hand. Is one in progress?",
hit: "Unable to hit.",
stay: "Unable to stay.",
"double-down": "Unable to double down.",
"buy-insurance": "Unable to buy insurance."
};
result = results[xhr.blackjackAction];
if (status == 429) {
result = error.message;
}
updateResult(result, "danger");
}
}
function updateBlackjackActions(state) {
const actions = Array.from(document.querySelectorAll('.twentyone-btn'));
// Hide all actions.
actions.forEach(action => action.style.display = 'none');
if (state) {
// Show the correct ones.
state.actions.forEach(action => document.getElementById(`twentyone-${action}`).style.display = 'inline-block');
} else {
const dealButton = document.getElementById(`twentyone-DEAL`);
setTimeout(() => {
const dealButton = document.getElementById(`twentyone-DEAL`);
})
if (dealButton) {
dealButton.style.display = 'inline-block'
}
}
}
function updateBlackjackTable(state) {
const table = document.getElementById('blackjack-table');
const charactersToRanks = {
X: "10"
};
const charactersToSuits = {
S: "♠️",
H: "♥️",
C: "♣️",
D: "♦️",
};
const makeCardset = (from, who, value) => `
<div class="blackjack-cardset">
<div class="blackjack-cardset-value">
${value === -1 ? `${who} went bust` : `${who} has ${value}`}
</div>
${from
.filter(card => card !== "?")
.map(([rankCharacter, suitCharacter]) => {
const rank = charactersToRanks[rankCharacter] || rankCharacter;
const suit = charactersToSuits[suitCharacter] || suitCharacter;
return buildPlayingCard(rank, suit);
})
.join('')}
</div>
`;
const dealerCards = makeCardset(state.dealer, 'Dealer', state.dealer_value);
const playerCards = makeCardset(state.player, 'Player', state.player_value);
updateBlackjackActions(state);
table.innerHTML = `
<div style="position: relative;">
${dealerCards}
</div>
${playerCards}
`;
const currency = state.wager.currency === 'coins' ? 'coins' : 'marseybux';
switch (state.status) {
case 'BLACKJACK':
updateResult(`Blackjack: Received ${state.payout} ${currency}`, "warning");
break;
case 'WON':
updateResult(`Won: Received ${state.payout} ${currency}`, "success");
break;
case 'PUSHED':
updateResult(`Pushed: Received ${state.wager.amount} ${currency}`, "success");
break;
case 'LOST':
updateResult(`Lost ${state.wager.amount} ${currency}`, "danger");
break;
default:
break;
}
updateCardsetBackgrounds(state);
if (state.status === 'PLAYING') {
updateResult(`${state.wager.amount} ${currency} are at stake`, "success");
} else {
enableWager();
}
}
function updateCardsetBackgrounds(state) {
const cardsets = Array.from(document.querySelectorAll('.blackjack-cardset'));
for (const cardset of cardsets) {
['PLAYING', 'LOST', 'PUSHED', 'WON', 'BLACKJACK'].forEach(status => cardset.classList.remove(`blackjack-cardset__${status}`));
cardset.classList.add(`blackjack-cardset__${state.status}`)
}
}
function deal() {
const request = makeBlackjackRequest('deal');
const { amount, currency } = getWager();
const form = new FormData();
form.append("formkey", formkey());
form.append("wager", amount);
form.append("currency", currency);
request.send(form);
clearResult();
disableWager();
drawFromDeck();
}
function hit() {
const request = makeBlackjackRequest('hit');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
drawFromDeck();
}
function stay() {
const request = makeBlackjackRequest('stay');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
}
function doubleDown() {
const request = makeBlackjackRequest('double-down');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
drawFromDeck();
}
function buyInsurance() {
const request = makeBlackjackRequest('buy-insurance');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
}
function buildBlackjackDeck() {
document.getElementById('blackjack-table-deck').innerHTML = `
<div style="position: absolute; top: 150px; left: -100px;">
${buildPlayingCardDeck()}
</div>
`;
}
function initializeBlackjack() {
buildBlackjackDeck();
try {
const passed = document.getElementById('blackjack-table').dataset.state;
const state = JSON.parse(passed);
updateBlackjackTable(state);
} catch (error) {
updateBlackjackActions();
}
}
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeBlackjack();
} else {
document.addEventListener("load", initializeBlackjack);
}

View File

@ -0,0 +1,201 @@
/**
* This script block contains generic helper function usable across casino games:
* - Wagers
* - Feed
* - Leaderboard
*/
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeGame();
} else {
document.addEventListener("load", initializeGame);
}
function initializeGame() {
updateFeed();
updateLeaderboard();
}
function updatePlayerCurrencies(updated) {
if (updated.coins) {
document.getElementById("user-coins-amount").innerText = updated.coins;
}
if (updated.marseybux) {
document.getElementById("user-bux-amount").innerText = updated.marseybux;
}
}
function getWager() {
const amount = document.getElementById("wagerAmount").value;
const currency = document.querySelector(
'input[name="wagerCurrency"]:checked'
).value;
const genericCurrency = currency == 'marseybux' ? 'marseybux' : 'coins';
return { amount, currency: genericCurrency, localCurrency: currency };
}
function disableWager() {
document.getElementById("wagerAmount").disabled = true;
document.getElementById("wagerCoins").disabled = true;
document.getElementById("wagerMarseybux").disabled = true;
}
function enableWager() {
document.getElementById("wagerAmount").disabled = false;
document.getElementById("wagerCoins").disabled = false;
document.getElementById("wagerMarseybux").disabled = false;
}
function updateResult(text, className) {
clearResult();
const result = document.getElementById("casinoGameResult");
result.style.visibility = "visible";
result.innerText = text;
result.classList.add(`alert-${className}`);
}
function clearResult() {
const result = document.getElementById("casinoGameResult");
result.style.visibility = "hidden";
result.innerText = "N/A";
result.classList.remove("alert-success", "alert-danger", "alert-warning");
}
function updateFeed(newFeed) {
let feed;
if (newFeed) {
feed = newFeed;
} else {
const gameFeed = document.getElementById("casinoGameFeed");
feed = gameFeed.dataset.feed;
feed = JSON.parse(feed);
gameFeed.dataset.feed = "";
}
const feedHtml = feed
.map(
(entry) =>
`
<li
style="display: flex; align-items: center; justify-content: space-between;"
class="${entry.won_or_lost === "won" ? "text-success" : "text-danger"}">
<div>
<a href="/@${entry.user}">@${entry.user}</a> ${entry.won_or_lost} ${entry.amount
} ${entry.currency}
</div>
</li>
`
)
.join("");
document.getElementById("casinoGameFeedList").innerHTML = feedHtml;
}
function reloadFeed() {
const game = document.getElementById('casino-game-wrapper').dataset.game;
const xhr = new XMLHttpRequest();
xhr.open("get", `/casino/${game}/feed`);
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleFeedResponse.bind(null, xhr);
xhr.send();
}
function handleFeedResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.error;
if (succeeded) {
document.getElementById("casinoGameFeed").dataset.feed = JSON.stringify(response.feed);
updateFeed();
} else {
console.error("error");
}
}
function updateLeaderboard() {
const leaderboardContainer = document.getElementById("gameLeaderboard");
const leaderboardData = JSON.parse(leaderboardContainer.dataset.leaderboard);
const [biggestWinnerAllTime, biggestWinner24h, biggestLoser24h, biggestLoserAllTime] = [
'biggestWinnerAllTime', 'biggestWinner24h', 'biggestLoser24h', 'biggestLoserAllTime'
].map(id => document.getElementById(id));
const formatLocalCurrencyName = currency => ({ coins: 'coins', marseybux: 'marseybux' })[currency];
biggestWinnerAllTime.innerHTML = `
<a href="/@${leaderboardData.all_time.biggest_win.user}">${leaderboardData.all_time.biggest_win.user}</a> <br><small>${leaderboardData.all_time.biggest_win.amount} ${formatLocalCurrencyName(leaderboardData.all_time.biggest_win.currency)}</small>
`;
biggestWinner24h.innerHTML = `
<a href="/@${leaderboardData.last_24h.biggest_win.user}">${leaderboardData.last_24h.biggest_win.user}</a> <br> <small>${leaderboardData.last_24h.biggest_win.amount} ${formatLocalCurrencyName(leaderboardData.last_24h.biggest_win.currency)}</small>
`;
biggestLoser24h.innerHTML = `
<a href="/@${leaderboardData.last_24h.biggest_loss.user}">${leaderboardData.last_24h.biggest_loss.user}</a> <br> <small>${leaderboardData.last_24h.biggest_loss.amount} ${formatLocalCurrencyName(leaderboardData.last_24h.biggest_loss.currency)}</small>
`;
biggestLoserAllTime.innerHTML = `
<a href="/@${leaderboardData.all_time.biggest_loss.user}">${leaderboardData.all_time.biggest_loss.user}</a> <br> <small>${leaderboardData.all_time.biggest_loss.amount} ${formatLocalCurrencyName(leaderboardData.all_time.biggest_loss.currency)}</small>
`;
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getRandomCardAngle() {
const skew = 10
return getRandomInt(-skew, skew);
}
function buildPlayingCard(rank, suit) {
return `
<div
style="transform: scale(0.7) rotateZ(${getRandomCardAngle()}deg)"
class="playing-card playing-card_${["", ""].includes(suit) ? 'red' : 'black'}">
<div class="playing-card_small playing-card_topright">${rank}${suit}</div>
<div class="playing-card_large">${rank}${suit}</div>
<div class="playing-card_small playing-card_bottomleft">${rank}${suit}</div>
</div>
`;
}
function buildPlayingCardDeck(size = 14) {
const cards = Array.from({ length: size }, (_, index) => `
<div
style="bottom: ${index}px; left: ${-index}px"
class="flipped-playing-card"></div>
`).join('\n');
return `
<div id="playingCardDeck" class="playing-card-deck">
${cards}
</div>
`;
}
function drawFromDeck() {
try {
const [topCard] = Array.from(document.querySelectorAll("#playingCardDeck > *")).reverse();
topCard.classList.add('drawing-a-card');
setTimeout(() => {
topCard.classList.remove('drawing-a-card');
}, 600);
} catch { }
}

View File

@ -0,0 +1,387 @@
// Kiss my ass if you're judgin'
const CELL_TO_NUMBER_LOOKUP = {
1: 3,
2: 6,
3: 9,
4: 12,
5: 15,
6: 18,
7: 21,
8: 24,
9: 27,
10: 30,
11: 33,
12: 36,
13: 2,
14: 5,
15: 8,
16: 11,
17: 14,
18: 17,
19: 20,
20: 23,
21: 26,
22: 29,
23: 32,
24: 35,
25: 1,
26: 4,
27: 7,
28: 10,
29: 13,
30: 16,
31: 19,
32: 22,
33: 25,
34: 28,
35: 31,
36: 34
};
function initializeGame() {
buildRouletteTable();
updateResult("Rolls occur every five minutes", "success");
requestRouletteBets();
}
function buildRouletteTable() {
const table = document.getElementById('roulette-table');
const reds = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];
let html = "";
// Lines
html += `
<div class="roulette-table-row">
<div style="flex: 1"></div>
<div id="LINE_BET#1" onclick="placeChip('LINE_BET', '1')" class="roulette-table-1to1">Line 1</div>
<div id="LINE_BET#2" onclick="placeChip('LINE_BET', '2')" class="roulette-table-1to1">Line 2</div>
<div id="LINE_BET#3" onclick="placeChip('LINE_BET', '3')" class="roulette-table-1to1">Line 3</div>
<div id="LINE_BET#4" onclick="placeChip('LINE_BET', '4')" class="roulette-table-1to1">Line 4</div>
<div id="LINE_BET#5" onclick="placeChip('LINE_BET', '5')" class="roulette-table-1to1">Line 5</div>
<div id="LINE_BET#6" onclick="placeChip('LINE_BET', '6')" class="roulette-table-1to1">Line 6</div>
<div style="flex: 1"></div>
</div>
`;
// First Column
html += "<div class=\"roulette-table-row\">";
html += `<div id="STRAIGHT_UP_BET#37" onclick="placeChip('STRAIGHT_UP_BET', '37')" class="roulette-table-number roulette-table-number__green">00</div>`
for (let i = 1; i < 13; i++) {
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
const isRed = reds.includes(correctNumber);
html += `<div
id="STRAIGHT_UP_BET#${correctNumber}"
onclick="placeChip('STRAIGHT_UP_BET', '${correctNumber}')"
class="roulette-table-number roulette-table-number__${isRed ? 'red' : 'black'}">
${correctNumber}
</div>
`;
}
html += `<div id="COLUMN_BET#3" class="roulette-table-column" onclick="placeChip('COLUMN_BET', '3')">Col 3</div>`;
html += "</div>";
// Second Column
html += "<div class=\"roulette-table-row\">";
html += `<div id="roulette-spacer-left-middle" class="roulette-table-number roulette-table-number__green"></div>`
for (let i = 13; i < 25; i++) {
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
const isRed = reds.includes(correctNumber);
html += `<div
id="STRAIGHT_UP_BET#${correctNumber}"
onclick="placeChip('STRAIGHT_UP_BET', '${correctNumber}')"
class="roulette-table-number roulette-table-number__${isRed ? 'red' : 'black'}">
${correctNumber}
</div>
`;
}
html += `<div id="COLUMN_BET#2" class="roulette-table-column" onclick="placeChip('COLUMN_BET', '2')">Col 2</div>`;
html += "</div>";
// Third Column
html += "<div class=\"roulette-table-row\">";
html += `<div id="STRAIGHT_UP_BET#0" onclick="placeChip('STRAIGHT_UP_BET', '0')" class="roulette-table-number roulette-table-number__green">0</div>`
for (let i = 25; i < 37; i++) {
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
const isRed = reds.includes(correctNumber);
html += `<div
id="STRAIGHT_UP_BET#${correctNumber}"
onclick="placeChip('STRAIGHT_UP_BET', '${correctNumber}')"
class="roulette-table-number roulette-table-number__${isRed ? 'red' : 'black'}">
${correctNumber}
</div>
`;
}
html += `<div id="COLUMN_BET#1" class="roulette-table-column" onclick="placeChip('COLUMN_BET', '1')">Col 1</div>`;
html += "</div>";
// Line Bets and 1:1 Bets
html += `
<div class="roulette-table-row">
<div style="flex: 1"></div>
<div id="DOZEN_BET#1" class="roulette-table-line" onclick="placeChip('DOZEN_BET', '1')">1st12</div>
<div id="DOZEN_BET#2" class="roulette-table-line" onclick="placeChip('DOZEN_BET', '2')">2nd12</div>
<div id="DOZEN_BET#3" class="roulette-table-line" onclick="placeChip('DOZEN_BET', '3')">3rd12</div>
<div style="flex: 1"></div>
</div>
<div class="roulette-table-row">
<div style="flex: 1"></div>
<div id="HIGH_LOW_BET#LOW" class="roulette-table-1to1" onclick="placeChip('HIGH_LOW_BET', 'LOW')">1:18</div>
<div id="EVEN_ODD_BET#EVEN" class="roulette-table-1to1" onclick="placeChip('EVEN_ODD_BET', 'EVEN')">EVEN</div>
<div id="RED_BLACK_BET#RED" class="roulette-table-1to1" onclick="placeChip('RED_BLACK_BET', 'RED')" style="background-color: red">RED</div>
<div id="RED_BLACK_BET#BLACK" class="roulette-table-1to1" onclick="placeChip('RED_BLACK_BET', 'BLACK')" style="background-color: black">BLACK</div>
<div id="EVEN_ODD_BET#ODD" class="roulette-table-1to1" onclick="placeChip('EVEN_ODD_BET', 'ODD')">ODD</div>
<div id="HIGH_LOW_BET#HIGH" class="roulette-table-1to1" onclick="placeChip('HIGH_LOW_BET', 'HIGH')">19:36</div>
<div style="flex: 1"></div>
</div>
`;
table.innerHTML = html;
}
function formatFlatBets(bets) {
let flatBets = [];
for (const betCollection of Object.values(bets)) {
flatBets = flatBets.concat(betCollection)
}
return flatBets;
}
function formatNormalizedBets(bets) {
const normalizedBets = {
gamblers: [],
gamblersByName: {}
};
const flatBets = formatFlatBets(bets);
for (const bet of flatBets) {
if (!normalizedBets.gamblers.includes(bet.gambler_username)) {
normalizedBets.gamblers.push(bet.gambler_username);
}
if (!normalizedBets.gamblersByName[bet.gambler_username]) {
normalizedBets.gamblersByName[bet.gambler_username] = {
name: bet.gambler_username,
avatar: bet.gambler_profile_url,
profile: `/@${bet.gambler_username}`,
wagerTotal: {
coins: 0,
marseybux: 0
},
wagers: []
}
}
const entry = normalizedBets.gamblersByName[bet.gambler_username];
entry.wagerTotal[bet.wager.currency] += bet.wager.amount;
const existingWager = entry.wagers.find(wager => wager.bet === bet.bet && wager.which === bet.which);
if (existingWager) {
existingWager.amounts[bet.wager.currency] += bet.wager.amount;
} else {
const newEntry = {
bet: bet.bet,
which: bet.which,
amounts: {
coins: 0,
marseybux: 0
},
};
newEntry.amounts[bet.wager.currency] += bet.wager.amount;
entry.wagers.push(newEntry);
}
}
return normalizedBets;
}
function buildPokerChip(avatar) {
return `
<div class="roulette-poker-chip">
<img src="/i/pokerchip.webp" width="40" height="40">
<img src="${avatar}" width="40" height="40">
</div>
`;
}
function buildRouletteBets(bets) {
const betArea = document.getElementById("roulette-bets");
const flatBets = formatFlatBets(bets);
const normalizedBets = formatNormalizedBets(bets);
const coinImgHtml = `
<img
src="/i/rDrama/coins.webp?v=3009"
alt="coin"
width="32"
data-bs-toggle="tooltip"
data-bs-placement="bottom"
title=""
aria-label="Coin"
data-bs-original-title="Coin">
`;
const marseybuxImgHtml = `
<img
src="/i/marseybux.webp?v=2000"
alt="marseybux"
data-bs-toggle="tooltip"
data-bs-placement="bottom"
title=""
aria-label="Marseybux"
width="32" class="mr-1 ml-1"
data-bs-original-title="Marseybux">
`;
const { participants, coin, marseybux } = flatBets.reduce((prev, next) => {
if (!prev.participants.includes(next.gambler_username)) {
prev.participants.push(next.gambler_username);
}
if (next.wager.currency == 'coins') {
prev.coin += next.wager.amount;
} else {
prev.marseybux += next.wager.amount;
}
return prev;
}, { participants: [], coin: 0, marseybux: 0 });
const coinText = `${coin} ${coinImgHtml}`;
const marseybuxText = `${marseybux} ${marseybuxImgHtml}`;
const playerText = participants.length > 1 ? `${participants.length} players are` : `1 player is`;
const totalText = coin && marseybux ? `${coinText} and ${marseybuxText}` : coin ? coinText : marseybuxText;
const fullTotalText = participants.length === 0 ? "No one has placed a bet" : `${playerText} betting a total of ${totalText}`;
let betHtml = `
<small class="roulette-total-bets">${fullTotalText}</small>
<hr>
`;
for (player of normalizedBets.gamblers) {
const { name, avatar, wagerTotal, wagers } = normalizedBets.gamblersByName[player];
betHtml += `<div class="roulette-bet-summary">`;
// Heading
betHtml += ` <div class="roulette-bet-summary--heading">`;
betHtml += buildPokerChip(avatar);
const coinText = wagerTotal.coins > 0 ? `${wagerTotal.coins} ${coinImgHtml}` : "";
const procoinText = wagerTotal.marseybux > 0 ? `${wagerTotal.marseybux} ${marseybuxImgHtml}` : "";
const bettingText = coinText && procoinText ? `${coinText} and ${procoinText}` : coinText || procoinText;
betHtml += `<p>${name} is betting ${bettingText}:</p>`;
betHtml += ` </div>`;
// Individual bets
betHtml += `<ul class="roulette-bet-summary--list">`;
for (const individualBet of wagers) {
const coinText = individualBet.amounts.coins > 0 ? `${individualBet.amounts.coins} ${coinImgHtml}` : "";
const procoinText = individualBet.amounts.marseybux > 0 ? `${individualBet.amounts.marseybux} ${marseybuxImgHtml}` : "";
const straightUpWhich = (individualBet.which == 37) ? "00" : individualBet.which;
const details = {
STRAIGHT_UP_BET: `that the number will be ${straightUpWhich}`,
LINE_BET: `that the number will be within line ${individualBet.which}`,
COLUMN_BET: `that the number will be within column ${individualBet.which}`,
DOZEN_BET: `that the number will be within dozen ${individualBet.which}`,
EVEN_ODD_BET: `that the number will be ${individualBet.which.toLowerCase()}`,
RED_BLACK_BET: `that the color of the number will be ${individualBet.which.toLowerCase()}`,
HIGH_LOW_BET: `that the number will be ${individualBet.which === "HIGH" ? "higher than 18" : "lower than 19"}`
}
const betText = coinText && procoinText ? `${coinText} and ${procoinText}` : coinText || procoinText;
betHtml += `<li>${betText} ${details[individualBet.bet]}</li>`;
}
betHtml += `</ul>`;
betHtml += `</div>`;
}
betArea.innerHTML = betHtml;
}
function placeChip(bet, which) {
const { amount, currency: safeCurrency, localCurrency: currency } = getWager();
const whichNice = which == 37 ? "00" : which;
const texts = {
STRAIGHT_UP_BET: `Bet ${amount} ${currency} on ${whichNice}?\nYou could win ${amount * 35} ${currency}.`,
LINE_BET: `Bet ${amount} ${currency} on line ${which}?\nYou could win ${amount * 5} ${currency}.`,
COLUMN_BET: `Bet ${amount} ${currency} column ${which}?\nYou could win ${amount * 2} ${currency}.`,
DOZEN_BET: `Bet ${amount} ${currency} dozen ${which}?\nYou could win ${amount * 2} ${currency}.`,
EVEN_ODD_BET: `Bet ${amount} ${currency} that the number will be ${which.toLowerCase()}?\nYou could win ${amount} ${currency}.`,
RED_BLACK_BET: `Bet ${amount} ${currency} that the number will be ${which.toLowerCase()}?\nYou could win ${amount} ${currency}.`,
HIGH_LOW_BET: `Bet ${amount} ${currency} that the number will be ${which === "HIGH" ? "higher than 18" : "lower than 19"}?\nYou could win ${amount} ${currency}.`,
}
const text = texts[bet] || "";
const confirmed = window.confirm(text);
if (confirmed) {
const xhr = new XMLHttpRequest();
xhr.open("post", "/casino/roulette/place-bet");
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleRouletteResponse.bind(null, xhr);
const form = new FormData();
form.append("formkey", formkey());
form.append("bet", bet);
form.append("which", which);
form.append("wager", amount);
form.append("currency", safeCurrency);
xhr.send(form);
}
}
function addChipsToTable(bets) {
const flatBets = formatFlatBets(bets);
for (const bet of flatBets) {
const tableElement = document.getElementById(`${bet.bet}#${bet.which}`);
tableElement.style.position = 'relative';
const count = tableElement.dataset.count ? parseInt(tableElement.dataset.count) + 1 : 1;
tableElement.dataset.count = count;
const chip = buildPokerChip(bet.gambler_profile_url)
tableElement.innerHTML = `${tableElement.innerHTML}<div style="position: absolute; bottom: ${count + 2}px; left: -${count + 2}px; transform: scale(0.5);">${chip}</div>`;
}
}
function requestRouletteBets() {
const xhr = new XMLHttpRequest();
xhr.open("get", "/casino/roulette/bets");
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleRouletteResponse.bind(null, xhr);
xhr.send();
}
function handleRouletteResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.error;
if (succeeded) {
buildRouletteBets(response.bets);
addChipsToTable(response.bets);
updatePlayerCurrencies(response.gambler);
updateResult("Rolls occur every five minutes", "success");
} else {
updateResult("Unable to place that bet.", "danger");
}
}
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeGame();
} else {
document.addEventListener("load", initializeGame);
}

View File

@ -0,0 +1,67 @@
function pullSlots() {
const { amount, currency } = getWager();
console.log({amount, currency})
disableWager();
clearResult();
document.getElementById("casinoSlotsPull").disabled = true;
const xhr = new XMLHttpRequest();
xhr.open("post", "/casino/slots");
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleSlotsResponse.bind(null, xhr);
const form = new FormData();
form.append("formkey", formkey());
form.append("wager", amount);
form.append("currency", currency);
xhr.send(form);
}
function handleSlotsResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.error;
if (succeeded) {
const { game_state, gambler } = response;
const state = JSON.parse(game_state);
const reels = Array.from(document.querySelectorAll(".slots_reel"));
const symbols = state.symbols.split(",");
for (let i = 0; i < 3; i++) {
reels[i].innerHTML = symbols[i];
}
let className;
if (state.text.includes("Jackpot")) {
className = "warning";
} else if (state.text.includes("Won")) {
className = "success";
} else if (state.text.includes("Lost")) {
className = "danger";
} else {
className = "success";
}
updateResult(state.text, className);
updatePlayerCurrencies(gambler);
reloadFeed()
} else {
updateResult(response.error, "danger");
console.error(response.error);
}
enableWager();
document.getElementById("casinoSlotsPull").disabled = false;
}

View File

@ -1,232 +1,7 @@
{% extends "casino/game_screen.html" %}
{% block script %}
<script nonce="{{g.nonce}}">
function makeBlackjackRequest(action) {
const xhr = new XMLHttpRequest();
xhr.open("post", `/casino/twentyone/${action}`);
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleBlackjackResponse.bind(null, xhr);
xhr.blackjackAction = action;
return xhr;
}
function handleBlackjackResponse(xhr) {
let status;
try {
const response = JSON.parse(xhr.response);
const succeeded = xhr.status >= 200 &&
xhr.status < 300 &&
response &&
!response.error;
clearResult();
status = xhr.status;
if (status == 429) {
throw new Error(response["details"]);
}
if (succeeded) {
updateBlackjackTable(response.state);
updateFeed(response.feed);
updatePlayerCurrencies(response.gambler);
} else {
console.error("Error: ", response.error);
throw new Error("Error")
}
} catch (error) {
const results = {
deal: "Unable to deal a new hand. Is one in progress?",
hit: "Unable to hit.",
stay: "Unable to stay.",
"double-down": "Unable to double down.",
"buy-insurance": "Unable to buy insurance."
};
result = results[xhr.blackjackAction];
if (status == 429) {
result = error.message;
}
updateResult(result, "danger");
}
}
function updateBlackjackActions(state) {
const actions = Array.from(document.querySelectorAll('.twentyone-btn'));
// Hide all actions.
actions.forEach(action => action.style.display = 'none');
if (state) {
// Show the correct ones.
state.actions.forEach(action => document.getElementById(`twentyone-${action}`).style.display = 'inline-block');
} else {
const dealButton = document.getElementById(`twentyone-DEAL`);
setTimeout(() => {
const dealButton = document.getElementById(`twentyone-DEAL`);
})
if (dealButton) {
dealButton.style.display = 'inline-block'
}
}
}
function updateBlackjackTable(state) {
const table = document.getElementById('blackjack-table');
const charactersToRanks = {
X: "10"
};
const charactersToSuits = {
S: "♠️",
H: "♥️",
C: "♣️",
D: "♦️",
};
const makeCardset = (from, who, value) => `
<div class="blackjack-cardset">
<div class="blackjack-cardset-value">
${value === -1 ? `${who} went bust` : `${who} has ${value}`}
</div>
${from
.filter(card => card !== "?")
.map(([rankCharacter, suitCharacter]) => {
const rank = charactersToRanks[rankCharacter] || rankCharacter;
const suit = charactersToSuits[suitCharacter] || suitCharacter;
return buildPlayingCard(rank, suit);
})
.join('')}
</div>
`;
const dealerCards = makeCardset(state.dealer, 'Dealer', state.dealer_value);
const playerCards = makeCardset(state.player, 'Player', state.player_value);
updateBlackjackActions(state);
table.innerHTML = `
<div style="position: relative;">
${dealerCards}
</div>
${playerCards}
`;
const currency = state.wager.currency === 'coins' ? 'coins' : 'marseybux';
switch (state.status) {
case 'BLACKJACK':
updateResult(`Blackjack: Received ${state.payout} ${currency}`, "warning");
break;
case 'WON':
updateResult(`Won: Received ${state.payout} ${currency}`, "success");
break;
case 'PUSHED':
updateResult(`Pushed: Received ${state.wager.amount} ${currency}`, "success");
break;
case 'LOST':
updateResult(`Lost ${state.wager.amount} ${currency}`, "danger");
break;
default:
break;
}
updateCardsetBackgrounds(state);
if (state.status === 'PLAYING') {
updateResult(`${state.wager.amount} ${currency} are at stake`, "success");
} else {
enableWager();
}
}
function updateCardsetBackgrounds(state) {
const cardsets = Array.from(document.querySelectorAll('.blackjack-cardset'));
for (const cardset of cardsets) {
['PLAYING', 'LOST', 'PUSHED', 'WON', 'BLACKJACK'].forEach(status => cardset.classList.remove(`blackjack-cardset__${status}`));
cardset.classList.add(`blackjack-cardset__${state.status}`)
}
}
function deal() {
const request = makeBlackjackRequest('deal');
const { amount, currency } = getWager();
const form = new FormData();
form.append("formkey", formkey());
form.append("wager", amount);
form.append("currency", currency);
request.send(form);
clearResult();
disableWager();
drawFromDeck();
}
function hit() {
const request = makeBlackjackRequest('hit');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
drawFromDeck();
}
function stay() {
const request = makeBlackjackRequest('stay');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
}
function doubleDown() {
const request = makeBlackjackRequest('double-down');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
drawFromDeck();
}
function buyInsurance() {
const request = makeBlackjackRequest('buy-insurance');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
}
function buildBlackjackDeck() {
document.getElementById('blackjack-table-deck').innerHTML = `
<div style="position: absolute; top: 150px; left: -100px;">
${buildPlayingCardDeck()}
</div>
`;
}
function initializeBlackjack() {
buildBlackjackDeck();
try {
const passed = document.getElementById('blackjack-table').dataset.state;
const state = JSON.parse(passed);
updateBlackjackTable(state);
} catch (error) {
updateBlackjackActions();
}
}
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeBlackjack();
} else {
document.addEventListener("load", initializeBlackjack);
}
</script>
<script defer src="{{'js/blackjack_screen.js' | asset}}"></script>
{% endblock %}
{% block screen %}

View File

@ -27,209 +27,7 @@
}
</style>
<script nonce="{{g.nonce}}">
/**
* This script block contains generic helper function usable across casino games:
* - Wagers
* - Feed
* - Leaderboard
*/
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeGame();
} else {
document.addEventListener("load", initializeGame);
}
function initializeGame() {
updateFeed();
updateLeaderboard();
}
function updatePlayerCurrencies(updated) {
if (updated.coins) {
document.getElementById("user-coins-amount").innerText = updated.coins;
}
if (updated.marseybux) {
document.getElementById("user-bux-amount").innerText = updated.marseybux;
}
}
function getWager() {
const amount = document.getElementById("wagerAmount").value;
const currency = document.querySelector(
'input[name="wagerCurrency"]:checked'
).value;
const genericCurrency = currency == 'marseybux' ? 'marseybux' : 'coins';
return { amount, currency: genericCurrency, localCurrency: currency };
}
function disableWager() {
document.getElementById("wagerAmount").disabled = true;
document.getElementById("wagerCoins").disabled = true;
document.getElementById("wagerMarseybux").disabled = true;
}
function enableWager() {
document.getElementById("wagerAmount").disabled = false;
document.getElementById("wagerCoins").disabled = false;
document.getElementById("wagerMarseybux").disabled = false;
}
function updateResult(text, className) {
clearResult();
const result = document.getElementById("casinoGameResult");
result.style.visibility = "visible";
result.innerText = text;
result.classList.add(`alert-${className}`);
}
function clearResult() {
const result = document.getElementById("casinoGameResult");
result.style.visibility = "hidden";
result.innerText = "N/A";
result.classList.remove("alert-success", "alert-danger", "alert-warning");
}
function updateFeed(newFeed) {
let feed;
if (newFeed) {
feed = newFeed;
} else {
const gameFeed = document.getElementById("casinoGameFeed");
feed = gameFeed.dataset.feed;
feed = JSON.parse(feed);
gameFeed.dataset.feed = "";
}
const feedHtml = feed
.map(
(entry) =>
`
<li
style="display: flex; align-items: center; justify-content: space-between;"
class="${entry.won_or_lost === "won" ? "text-success" : "text-danger"}">
<div>
<a href="/@${entry.user}">@${entry.user}</a> ${entry.won_or_lost} ${entry.amount
} ${entry.currency}
</div>
</li>
`
)
.join("");
document.getElementById("casinoGameFeedList").innerHTML = feedHtml;
}
function reloadFeed() {
const game = document.getElementById('casino-game-wrapper').dataset.game;
const xhr = new XMLHttpRequest();
xhr.open("get", `/casino/${game}/feed`);
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleFeedResponse.bind(null, xhr);
xhr.send();
}
function handleFeedResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.error;
if (succeeded) {
document.getElementById("casinoGameFeed").dataset.feed = JSON.stringify(response.feed);
updateFeed();
} else {
console.error("error");
}
}
function updateLeaderboard() {
const leaderboardContainer = document.getElementById("gameLeaderboard");
const leaderboardData = JSON.parse(leaderboardContainer.dataset.leaderboard);
const [biggestWinnerAllTime, biggestWinner24h, biggestLoser24h, biggestLoserAllTime] = [
'biggestWinnerAllTime', 'biggestWinner24h', 'biggestLoser24h', 'biggestLoserAllTime'
].map(id => document.getElementById(id));
const formatLocalCurrencyName = currency => ({ coins: 'coins', marseybux: 'marseybux' })[currency];
biggestWinnerAllTime.innerHTML = `
<a href="/@${leaderboardData.all_time.biggest_win.user}">${leaderboardData.all_time.biggest_win.user}</a> <br><small>${leaderboardData.all_time.biggest_win.amount} ${formatLocalCurrencyName(leaderboardData.all_time.biggest_win.currency)}</small>
`;
biggestWinner24h.innerHTML = `
<a href="/@${leaderboardData.last_24h.biggest_win.user}">${leaderboardData.last_24h.biggest_win.user}</a> <br> <small>${leaderboardData.last_24h.biggest_win.amount} ${formatLocalCurrencyName(leaderboardData.last_24h.biggest_win.currency)}</small>
`;
biggestLoser24h.innerHTML = `
<a href="/@${leaderboardData.last_24h.biggest_loss.user}">${leaderboardData.last_24h.biggest_loss.user}</a> <br> <small>${leaderboardData.last_24h.biggest_loss.amount} ${formatLocalCurrencyName(leaderboardData.last_24h.biggest_loss.currency)}</small>
`;
biggestLoserAllTime.innerHTML = `
<a href="/@${leaderboardData.all_time.biggest_loss.user}">${leaderboardData.all_time.biggest_loss.user}</a> <br> <small>${leaderboardData.all_time.biggest_loss.amount} ${formatLocalCurrencyName(leaderboardData.all_time.biggest_loss.currency)}</small>
`;
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getRandomCardAngle() {
const skew = 10
return getRandomInt(-skew, skew);
}
function buildPlayingCard(rank, suit) {
return `
<div
style="transform: scale(0.7) rotateZ(${getRandomCardAngle()}deg)"
class="playing-card playing-card_${["♥️", "♦️"].includes(suit) ? 'red' : 'black'}">
<div class="playing-card_small playing-card_topright">${rank}${suit}</div>
<div class="playing-card_large">${rank}${suit}</div>
<div class="playing-card_small playing-card_bottomleft">${rank}${suit}</div>
</div>
`;
}
function buildPlayingCardDeck(size = 14) {
const cards = Array.from({ length: size }, (_, index) => `
<div
style="bottom: ${index}px; left: ${-index}px"
class="flipped-playing-card"></div>
`).join('\n');
return `
<div id="playingCardDeck" class="playing-card-deck">
${cards}
</div>
`;
}
function drawFromDeck() {
try {
const [topCard] = Array.from(document.querySelectorAll("#playingCardDeck > *")).reverse();
topCard.classList.add('drawing-a-card');
setTimeout(() => {
topCard.classList.remove('drawing-a-card');
}, 600);
} catch { }
}
</script>
<script defer src="{{'js/game_screen.js' | asset}}"></script>
{% block script %} {% endblock %}

View File

@ -1,395 +1,7 @@
{% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %}
{% block script %}
<script nonce="{{g.nonce}}">
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeGame();
} else {
document.addEventListener("load", initializeGame);
}
// Kiss my ass if you're judgin'
const CELL_TO_NUMBER_LOOKUP = {
1: 3,
2: 6,
3: 9,
4: 12,
5: 15,
6: 18,
7: 21,
8: 24,
9: 27,
10: 30,
11: 33,
12: 36,
13: 2,
14: 5,
15: 8,
16: 11,
17: 14,
18: 17,
19: 20,
20: 23,
21: 26,
22: 29,
23: 32,
24: 35,
25: 1,
26: 4,
27: 7,
28: 10,
29: 13,
30: 16,
31: 19,
32: 22,
33: 25,
34: 28,
35: 31,
36: 34
};
function initializeGame() {
buildRouletteTable();
updateResult("Rolls occur every five minutes", "success");
requestRouletteBets();
}
function buildRouletteTable() {
const table = document.getElementById('roulette-table');
const reds = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];
let html = "";
// Lines
html += `
<div class="roulette-table-row">
<div style="flex: 1"></div>
<div id="LINE_BET#1" onclick="placeChip('LINE_BET', '1')" class="roulette-table-1to1">Line 1</div>
<div id="LINE_BET#2" onclick="placeChip('LINE_BET', '2')" class="roulette-table-1to1">Line 2</div>
<div id="LINE_BET#3" onclick="placeChip('LINE_BET', '3')" class="roulette-table-1to1">Line 3</div>
<div id="LINE_BET#4" onclick="placeChip('LINE_BET', '4')" class="roulette-table-1to1">Line 4</div>
<div id="LINE_BET#5" onclick="placeChip('LINE_BET', '5')" class="roulette-table-1to1">Line 5</div>
<div id="LINE_BET#6" onclick="placeChip('LINE_BET', '6')" class="roulette-table-1to1">Line 6</div>
<div style="flex: 1"></div>
</div>
`;
// First Column
html += "<div class=\"roulette-table-row\">";
html += `<div id="STRAIGHT_UP_BET#37" onclick="placeChip('STRAIGHT_UP_BET', '37')" class="roulette-table-number roulette-table-number__green">00</div>`
for (let i = 1; i < 13; i++) {
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
const isRed = reds.includes(correctNumber);
html += `<div
id="STRAIGHT_UP_BET#${correctNumber}"
onclick="placeChip('STRAIGHT_UP_BET', '${correctNumber}')"
class="roulette-table-number roulette-table-number__${isRed ? 'red' : 'black'}">
${correctNumber}
</div>
`;
}
html += `<div id="COLUMN_BET#3" class="roulette-table-column" onclick="placeChip('COLUMN_BET', '3')">Col 3</div>`;
html += "</div>";
// Second Column
html += "<div class=\"roulette-table-row\">";
html += `<div id="roulette-spacer-left-middle" class="roulette-table-number roulette-table-number__green"></div>`
for (let i = 13; i < 25; i++) {
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
const isRed = reds.includes(correctNumber);
html += `<div
id="STRAIGHT_UP_BET#${correctNumber}"
onclick="placeChip('STRAIGHT_UP_BET', '${correctNumber}')"
class="roulette-table-number roulette-table-number__${isRed ? 'red' : 'black'}">
${correctNumber}
</div>
`;
}
html += `<div id="COLUMN_BET#2" class="roulette-table-column" onclick="placeChip('COLUMN_BET', '2')">Col 2</div>`;
html += "</div>";
// Third Column
html += "<div class=\"roulette-table-row\">";
html += `<div id="STRAIGHT_UP_BET#0" onclick="placeChip('STRAIGHT_UP_BET', '0')" class="roulette-table-number roulette-table-number__green">0</div>`
for (let i = 25; i < 37; i++) {
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
const isRed = reds.includes(correctNumber);
html += `<div
id="STRAIGHT_UP_BET#${correctNumber}"
onclick="placeChip('STRAIGHT_UP_BET', '${correctNumber}')"
class="roulette-table-number roulette-table-number__${isRed ? 'red' : 'black'}">
${correctNumber}
</div>
`;
}
html += `<div id="COLUMN_BET#1" class="roulette-table-column" onclick="placeChip('COLUMN_BET', '1')">Col 1</div>`;
html += "</div>";
// Line Bets and 1:1 Bets
html += `
<div class="roulette-table-row">
<div style="flex: 1"></div>
<div id="DOZEN_BET#1" class="roulette-table-line" onclick="placeChip('DOZEN_BET', '1')">1st12</div>
<div id="DOZEN_BET#2" class="roulette-table-line" onclick="placeChip('DOZEN_BET', '2')">2nd12</div>
<div id="DOZEN_BET#3" class="roulette-table-line" onclick="placeChip('DOZEN_BET', '3')">3rd12</div>
<div style="flex: 1"></div>
</div>
<div class="roulette-table-row">
<div style="flex: 1"></div>
<div id="HIGH_LOW_BET#LOW" class="roulette-table-1to1" onclick="placeChip('HIGH_LOW_BET', 'LOW')">1:18</div>
<div id="EVEN_ODD_BET#EVEN" class="roulette-table-1to1" onclick="placeChip('EVEN_ODD_BET', 'EVEN')">EVEN</div>
<div id="RED_BLACK_BET#RED" class="roulette-table-1to1" onclick="placeChip('RED_BLACK_BET', 'RED')" style="background-color: red">RED</div>
<div id="RED_BLACK_BET#BLACK" class="roulette-table-1to1" onclick="placeChip('RED_BLACK_BET', 'BLACK')" style="background-color: black">BLACK</div>
<div id="EVEN_ODD_BET#ODD" class="roulette-table-1to1" onclick="placeChip('EVEN_ODD_BET', 'ODD')">ODD</div>
<div id="HIGH_LOW_BET#HIGH" class="roulette-table-1to1" onclick="placeChip('HIGH_LOW_BET', 'HIGH')">19:36</div>
<div style="flex: 1"></div>
</div>
`;
table.innerHTML = html;
}
function formatFlatBets(bets) {
let flatBets = [];
for (const betCollection of Object.values(bets)) {
flatBets = flatBets.concat(betCollection)
}
return flatBets;
}
function formatNormalizedBets(bets) {
const normalizedBets = {
gamblers: [],
gamblersByName: {}
};
const flatBets = formatFlatBets(bets);
for (const bet of flatBets) {
if (!normalizedBets.gamblers.includes(bet.gambler_username)) {
normalizedBets.gamblers.push(bet.gambler_username);
}
if (!normalizedBets.gamblersByName[bet.gambler_username]) {
normalizedBets.gamblersByName[bet.gambler_username] = {
name: bet.gambler_username,
avatar: bet.gambler_profile_url,
profile: `/@${bet.gambler_username}`,
wagerTotal: {
coins: 0,
marseybux: 0
},
wagers: []
}
}
const entry = normalizedBets.gamblersByName[bet.gambler_username];
entry.wagerTotal[bet.wager.currency] += bet.wager.amount;
const existingWager = entry.wagers.find(wager => wager.bet === bet.bet && wager.which === bet.which);
if (existingWager) {
existingWager.amounts[bet.wager.currency] += bet.wager.amount;
} else {
const newEntry = {
bet: bet.bet,
which: bet.which,
amounts: {
coins: 0,
marseybux: 0
},
};
newEntry.amounts[bet.wager.currency] += bet.wager.amount;
entry.wagers.push(newEntry);
}
}
return normalizedBets;
}
function buildPokerChip(avatar) {
return `
<div class="roulette-poker-chip">
<img src="/i/pokerchip.webp" width="40" height="40">
<img src="${avatar}" width="40" height="40">
</div>
`;
}
function buildRouletteBets(bets) {
const betArea = document.getElementById("roulette-bets");
const flatBets = formatFlatBets(bets);
const normalizedBets = formatNormalizedBets(bets);
const coinImgHtml = `
<img
src="/i/rDrama/coins.webp?v=3009"
alt="coin"
width="32"
data-bs-toggle="tooltip"
data-bs-placement="bottom"
title=""
aria-label="Coin"
data-bs-original-title="Coin">
`;
const marseybuxImgHtml = `
<img
src="/i/marseybux.webp?v=2000"
alt="marseybux"
data-bs-toggle="tooltip"
data-bs-placement="bottom"
title=""
aria-label="Marseybux"
width="32" class="mr-1 ml-1"
data-bs-original-title="Marseybux">
`;
const { participants, coin, marseybux } = flatBets.reduce((prev, next) => {
if (!prev.participants.includes(next.gambler_username)) {
prev.participants.push(next.gambler_username);
}
if (next.wager.currency == 'coins') {
prev.coin += next.wager.amount;
} else {
prev.marseybux += next.wager.amount;
}
return prev;
}, { participants: [], coin: 0, marseybux: 0 });
const coinText = `${coin} ${coinImgHtml}`;
const marseybuxText = `${marseybux} ${marseybuxImgHtml}`;
const playerText = participants.length > 1 ? `${participants.length} players are` : `1 player is`;
const totalText = coin && marseybux ? `${coinText} and ${marseybuxText}` : coin ? coinText : marseybuxText;
const fullTotalText = participants.length === 0 ? "No one has placed a bet" : `${playerText} betting a total of ${totalText}`;
let betHtml = `
<small class="roulette-total-bets">${fullTotalText}</small>
<hr>
`;
for (player of normalizedBets.gamblers) {
const { name, avatar, wagerTotal, wagers } = normalizedBets.gamblersByName[player];
betHtml += `<div class="roulette-bet-summary">`;
// Heading
betHtml += ` <div class="roulette-bet-summary--heading">`;
betHtml += buildPokerChip(avatar);
const coinText = wagerTotal.coins > 0 ? `${wagerTotal.coins} ${coinImgHtml}` : "";
const procoinText = wagerTotal.marseybux > 0 ? `${wagerTotal.marseybux} ${marseybuxImgHtml}` : "";
const bettingText = coinText && procoinText ? `${coinText} and ${procoinText}` : coinText || procoinText;
betHtml += `<p>${name} is betting ${bettingText}:</p>`;
betHtml += ` </div>`;
// Individual bets
betHtml += `<ul class="roulette-bet-summary--list">`;
for (const individualBet of wagers) {
const coinText = individualBet.amounts.coins > 0 ? `${individualBet.amounts.coins} ${coinImgHtml}` : "";
const procoinText = individualBet.amounts.marseybux > 0 ? `${individualBet.amounts.marseybux} ${marseybuxImgHtml}` : "";
const straightUpWhich = (individualBet.which == 37) ? "00" : individualBet.which;
const details = {
STRAIGHT_UP_BET: `that the number will be ${straightUpWhich}`,
LINE_BET: `that the number will be within line ${individualBet.which}`,
COLUMN_BET: `that the number will be within column ${individualBet.which}`,
DOZEN_BET: `that the number will be within dozen ${individualBet.which}`,
EVEN_ODD_BET: `that the number will be ${individualBet.which.toLowerCase()}`,
RED_BLACK_BET: `that the color of the number will be ${individualBet.which.toLowerCase()}`,
HIGH_LOW_BET: `that the number will be ${individualBet.which === "HIGH" ? "higher than 18" : "lower than 19"}`
}
const betText = coinText && procoinText ? `${coinText} and ${procoinText}` : coinText || procoinText;
betHtml += `<li>${betText} ${details[individualBet.bet]}</li>`;
}
betHtml += `</ul>`;
betHtml += `</div>`;
}
betArea.innerHTML = betHtml;
}
function placeChip(bet, which) {
const { amount, currency: safeCurrency, localCurrency: currency } = getWager();
const whichNice = which == 37 ? "00" : which;
const texts = {
STRAIGHT_UP_BET: `Bet ${amount} ${currency} on ${whichNice}?\nYou could win ${amount * 35} ${currency}.`,
LINE_BET: `Bet ${amount} ${currency} on line ${which}?\nYou could win ${amount * 5} ${currency}.`,
COLUMN_BET: `Bet ${amount} ${currency} column ${which}?\nYou could win ${amount * 2} ${currency}.`,
DOZEN_BET: `Bet ${amount} ${currency} dozen ${which}?\nYou could win ${amount * 2} ${currency}.`,
EVEN_ODD_BET: `Bet ${amount} ${currency} that the number will be ${which.toLowerCase()}?\nYou could win ${amount} ${currency}.`,
RED_BLACK_BET: `Bet ${amount} ${currency} that the number will be ${which.toLowerCase()}?\nYou could win ${amount} ${currency}.`,
HIGH_LOW_BET: `Bet ${amount} ${currency} that the number will be ${which === "HIGH" ? "higher than 18" : "lower than 19"}?\nYou could win ${amount} ${currency}.`,
}
const text = texts[bet] || "";
const confirmed = window.confirm(text);
if (confirmed) {
const xhr = new XMLHttpRequest();
xhr.open("post", "/casino/roulette/place-bet");
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleRouletteResponse.bind(null, xhr);
const form = new FormData();
form.append("formkey", formkey());
form.append("bet", bet);
form.append("which", which);
form.append("wager", amount);
form.append("currency", safeCurrency);
xhr.send(form);
}
}
function addChipsToTable(bets) {
const flatBets = formatFlatBets(bets);
for (const bet of flatBets) {
const tableElement = document.getElementById(`${bet.bet}#${bet.which}`);
tableElement.style.position = 'relative';
const count = tableElement.dataset.count ? parseInt(tableElement.dataset.count) + 1 : 1;
tableElement.dataset.count = count;
const chip = buildPokerChip(bet.gambler_profile_url)
tableElement.innerHTML = `${tableElement.innerHTML}<div style="position: absolute; bottom: ${count + 2}px; left: -${count + 2}px; transform: scale(0.5);">${chip}</div>`;
}
}
function requestRouletteBets() {
const xhr = new XMLHttpRequest();
xhr.open("get", "/casino/roulette/bets");
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleRouletteResponse.bind(null, xhr);
xhr.send();
}
function handleRouletteResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.error;
if (succeeded) {
buildRouletteBets(response.bets);
addChipsToTable(response.bets);
updatePlayerCurrencies(response.gambler);
updateResult("Rolls occur every five minutes", "success");
} else {
updateResult("Unable to place that bet.", "danger");
}
}
</script>
<script defer src="{{'js/roulette_screen.js' | asset}}"></script>
{% endblock %}
{% block screen %}

View File

@ -1,75 +1,7 @@
{% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %}
{% block script %}
<script nonce="{{g.nonce}}">
function pullSlots() {
const { amount, currency } = getWager();
console.log({amount, currency})
disableWager();
clearResult();
document.getElementById("casinoSlotsPull").disabled = true;
const xhr = new XMLHttpRequest();
xhr.open("post", "/casino/slots");
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = handleSlotsResponse.bind(null, xhr);
const form = new FormData();
form.append("formkey", formkey());
form.append("wager", amount);
form.append("currency", currency);
xhr.send(form);
}
function handleSlotsResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.error;
if (succeeded) {
const { game_state, gambler } = response;
const state = JSON.parse(game_state);
const reels = Array.from(document.querySelectorAll(".slots_reel"));
const symbols = state.symbols.split(",");
for (let i = 0; i < 3; i++) {
reels[i].innerHTML = symbols[i];
}
let className;
if (state.text.includes("Jackpot")) {
className = "warning";
} else if (state.text.includes("Won")) {
className = "success";
} else if (state.text.includes("Lost")) {
className = "danger";
} else {
className = "success";
}
updateResult(state.text, className);
updatePlayerCurrencies(gambler);
reloadFeed()
} else {
updateResult(response.error, "danger");
console.error(response.error);
}
enableWager();
document.getElementById("casinoSlotsPull").disabled = false;
}
</script>
<script defer src="{{'js/slots_screen.js' | asset}}"></script>
{% endblock %}
{% block screen %}