Add Roulette (#351)
* Add roulette file * Rename variable to avoid name collission * Add basic route and create new template for game * More work on the roulette template * Initial connection of front-end roulette to back-end roulette * Add to cron job * Pass bets to the front end * Update front-end looks * Add stackable poker chips for bets * Minor last changes * Handle minimum bets * Add bet tableremotes/1693045480750635534/spooky-22
parent
e0d32c7105
commit
7d8cfe5576
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
|
@ -14,12 +14,13 @@ def get_game_feed(game):
|
||||||
def format_game(game):
|
def format_game(game):
|
||||||
user = g.db.query(User).filter(User.id == game.user_id).one()
|
user = g.db.query(User).filter(User.id == game.user_id).one()
|
||||||
wonlost = 'lost' if game.winnings < 0 else 'won'
|
wonlost = 'lost' if game.winnings < 0 else 'won'
|
||||||
|
relevant_currency = "dramacoin" if game.currency == "coins" else "marseybux"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"user": user.username,
|
"user": user.username,
|
||||||
"won_or_lost": wonlost,
|
"won_or_lost": wonlost,
|
||||||
"amount": abs(game.winnings),
|
"amount": abs(game.winnings),
|
||||||
"currency": game.currency
|
"currency": relevant_currency
|
||||||
}
|
}
|
||||||
|
|
||||||
return list(map(format_game, games))
|
return list(map(format_game, games))
|
||||||
|
@ -80,7 +81,3 @@ def get_game_leaderboard(game):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_game_stats_for_player(player):
|
|
||||||
pass
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ from files.cli import g, app, db_session
|
||||||
import click
|
import click
|
||||||
from files.helpers.const import *
|
from files.helpers.const import *
|
||||||
from files.helpers.alerts import send_repeatable_notification
|
from files.helpers.alerts import send_repeatable_notification
|
||||||
|
from files.helpers.roulette import spin_roulette_wheel
|
||||||
from files.helpers.get import *
|
from files.helpers.get import *
|
||||||
from files.helpers.actions import *
|
from files.helpers.actions import *
|
||||||
from files.classes import *
|
from files.classes import *
|
||||||
|
@ -28,6 +29,7 @@ def cron(every_5m, every_1h, every_1d, every_1mo):
|
||||||
if every_5m:
|
if every_5m:
|
||||||
lottery.check_if_end_lottery_task()
|
lottery.check_if_end_lottery_task()
|
||||||
offsitementions.offsite_mentions_task()
|
offsitementions.offsite_mentions_task()
|
||||||
|
spin_roulette_wheel()
|
||||||
|
|
||||||
if every_1h:
|
if every_1h:
|
||||||
awards.award_timers_bots_task()
|
awards.award_timers_bots_task()
|
||||||
|
|
|
@ -0,0 +1,295 @@
|
||||||
|
import json
|
||||||
|
from random import randint
|
||||||
|
from enum import Enum
|
||||||
|
from files.helpers.alerts import *
|
||||||
|
from files.classes.casino_game import Casino_Game
|
||||||
|
from files.helpers.get import get_account
|
||||||
|
from flask import g
|
||||||
|
|
||||||
|
|
||||||
|
class RouletteAction(str, Enum):
|
||||||
|
STRAIGHT_UP_BET = "STRAIGHT_UP_BET"
|
||||||
|
LINE_BET = "LINE_BET"
|
||||||
|
COLUMN_BET = "COLUMN_BET"
|
||||||
|
DOZEN_BET = "DOZEN_BET"
|
||||||
|
EVEN_ODD_BET = "EVEN_ODD_BET"
|
||||||
|
RED_BLACK_BET = "RED_BLACK_BET"
|
||||||
|
HIGH_LOW_BET = "HIGH_LOW_BET"
|
||||||
|
|
||||||
|
|
||||||
|
class RouletteEvenOdd(str, Enum):
|
||||||
|
EVEN = "EVEN"
|
||||||
|
ODD = "ODD"
|
||||||
|
|
||||||
|
|
||||||
|
class RouletteRedBlack(str, Enum):
|
||||||
|
RED = "RED"
|
||||||
|
BLACK = "BLACK"
|
||||||
|
|
||||||
|
|
||||||
|
class RouletteHighLow(str, Enum):
|
||||||
|
HIGH = "HIGH"
|
||||||
|
LOW = "LOW"
|
||||||
|
|
||||||
|
|
||||||
|
REDS = (1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36)
|
||||||
|
BLACKS = (2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35)
|
||||||
|
LINES = {
|
||||||
|
1: (1, 2, 3, 4, 5, 6),
|
||||||
|
2: (7, 8, 9, 10, 11, 12),
|
||||||
|
3: (13, 14, 15, 16, 17, 18),
|
||||||
|
4: (19, 20, 21, 22, 23, 24),
|
||||||
|
5: (25, 26, 27, 28, 29, 30),
|
||||||
|
6: (31, 32, 33, 34, 35, 36)
|
||||||
|
}
|
||||||
|
COLUMNS = {
|
||||||
|
1: (1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34),
|
||||||
|
2: (2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35),
|
||||||
|
3: (3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36)
|
||||||
|
}
|
||||||
|
DOZENS = {
|
||||||
|
1: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
|
||||||
|
2: (13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24),
|
||||||
|
3: (25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36)
|
||||||
|
}
|
||||||
|
PAYOUT_MULITPLIERS = {
|
||||||
|
RouletteAction.STRAIGHT_UP_BET: 35,
|
||||||
|
RouletteAction.LINE_BET: 5,
|
||||||
|
RouletteAction.COLUMN_BET: 2,
|
||||||
|
RouletteAction.DOZEN_BET: 2,
|
||||||
|
RouletteAction.EVEN_ODD_BET: 1,
|
||||||
|
RouletteAction.RED_BLACK_BET: 1,
|
||||||
|
RouletteAction.HIGH_LOW_BET: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_roulette_games():
|
||||||
|
return g.db.query(Casino_Game).filter(
|
||||||
|
Casino_Game.active == True,
|
||||||
|
Casino_Game.kind == 'roulette'
|
||||||
|
).all()
|
||||||
|
|
||||||
|
|
||||||
|
def charge_gambler(gambler, amount, currency):
|
||||||
|
currency_gambler_holds = getattr(gambler, currency)
|
||||||
|
can_afford = currency_gambler_holds >= amount
|
||||||
|
|
||||||
|
if not can_afford:
|
||||||
|
raise Exception("Gambler cannot afford charge.")
|
||||||
|
|
||||||
|
setattr(gambler, currency, currency_gambler_holds - amount)
|
||||||
|
g.db.add(gambler)
|
||||||
|
|
||||||
|
|
||||||
|
def gambler_placed_roulette_bet(gambler, bet, which, amount, currency):
|
||||||
|
if not bet in (
|
||||||
|
RouletteAction.STRAIGHT_UP_BET,
|
||||||
|
RouletteAction.LINE_BET,
|
||||||
|
RouletteAction.COLUMN_BET,
|
||||||
|
RouletteAction.DOZEN_BET,
|
||||||
|
RouletteAction.EVEN_ODD_BET,
|
||||||
|
RouletteAction.RED_BLACK_BET,
|
||||||
|
RouletteAction.HIGH_LOW_BET
|
||||||
|
):
|
||||||
|
raise Exception(
|
||||||
|
f'Illegal bet {bet} passed to Roulette#gambler_placed_roulette_bet')
|
||||||
|
|
||||||
|
active_games = get_active_roulette_games()
|
||||||
|
|
||||||
|
if len(active_games) == 0:
|
||||||
|
parent_id = int(time.time())
|
||||||
|
else:
|
||||||
|
parent_id = json.loads(active_games[0].game_state)['parent_id']
|
||||||
|
|
||||||
|
charge_gambler(gambler, amount, currency)
|
||||||
|
|
||||||
|
game = Casino_Game()
|
||||||
|
game.user_id = gambler.id
|
||||||
|
game.currency = currency
|
||||||
|
game.wager = amount
|
||||||
|
game.winnings = 0
|
||||||
|
game.kind = 'roulette'
|
||||||
|
game.game_state = json.dumps(
|
||||||
|
{"parent_id": parent_id, "bet": bet, "which": which})
|
||||||
|
game.active = True
|
||||||
|
g.db.add(game)
|
||||||
|
g.db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def get_roulette_bets_and_betters():
|
||||||
|
participants = []
|
||||||
|
bets = {
|
||||||
|
RouletteAction.STRAIGHT_UP_BET: [],
|
||||||
|
RouletteAction.LINE_BET: [],
|
||||||
|
RouletteAction.COLUMN_BET: [],
|
||||||
|
RouletteAction.DOZEN_BET: [],
|
||||||
|
RouletteAction.EVEN_ODD_BET: [],
|
||||||
|
RouletteAction.RED_BLACK_BET: [],
|
||||||
|
RouletteAction.HIGH_LOW_BET: [],
|
||||||
|
}
|
||||||
|
active_games = get_active_roulette_games()
|
||||||
|
|
||||||
|
for game in active_games:
|
||||||
|
if not game.user_id in participants:
|
||||||
|
participants.append(game.user_id)
|
||||||
|
|
||||||
|
user = get_account(game.user_id)
|
||||||
|
game_state = json.loads(game.game_state)
|
||||||
|
bet = game_state['bet']
|
||||||
|
bets[bet].append({
|
||||||
|
'game_id': game.id,
|
||||||
|
'gambler': game.user_id,
|
||||||
|
'gambler_username': user.username,
|
||||||
|
'gambler_profile_url': user.profile_url,
|
||||||
|
'bet': bet,
|
||||||
|
'which': game_state['which'],
|
||||||
|
'wager': {
|
||||||
|
'amount': game.wager,
|
||||||
|
'currency': game.currency
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return participants, bets, active_games
|
||||||
|
|
||||||
|
|
||||||
|
def spin_roulette_wheel():
|
||||||
|
participants, bets, active_games = get_roulette_bets_and_betters()
|
||||||
|
|
||||||
|
if len(participants) > 0:
|
||||||
|
number = randint(0, 37) # 37 is 00
|
||||||
|
winners, payouts, rewards_by_game_id = determine_roulette_winners(
|
||||||
|
number, bets)
|
||||||
|
|
||||||
|
# Pay out to the winners and send a notification.
|
||||||
|
for user_id in winners:
|
||||||
|
gambler = get_account(user_id)
|
||||||
|
gambler_payout = payouts[user_id]
|
||||||
|
coin_winnings = gambler_payout['coins']
|
||||||
|
procoin_winnings = gambler_payout['procoins']
|
||||||
|
|
||||||
|
setattr(gambler, 'coins', gambler.coins + coin_winnings)
|
||||||
|
setattr(gambler, 'procoins', gambler.procoins + procoin_winnings)
|
||||||
|
|
||||||
|
g.db.add(gambler)
|
||||||
|
|
||||||
|
# Notify the winners.
|
||||||
|
notification_text = f"Winning number: {number}\nCongratulations! One or more of your roulette bets paid off!\n"
|
||||||
|
|
||||||
|
if coin_winnings > 0:
|
||||||
|
notification_text = notification_text + \
|
||||||
|
f"* You received {coin_winnings} dramacoins.\n"
|
||||||
|
|
||||||
|
if procoin_winnings > 0:
|
||||||
|
notification_text = notification_text + \
|
||||||
|
f"* You received {procoin_winnings} marseybux.\n"
|
||||||
|
|
||||||
|
send_repeatable_notification(user_id, notification_text)
|
||||||
|
|
||||||
|
# Give condolences.
|
||||||
|
for participant in participants:
|
||||||
|
if not participant in winners:
|
||||||
|
send_repeatable_notification(
|
||||||
|
participant, f"Winning number: {number}\nSorry, none of your recent roulette bets paid off.")
|
||||||
|
|
||||||
|
g.db.flush()
|
||||||
|
|
||||||
|
# Adjust game winnings.
|
||||||
|
for game in active_games:
|
||||||
|
if rewards_by_game_id.get(game.id):
|
||||||
|
game.winnings = rewards_by_game_id[game.id]
|
||||||
|
else:
|
||||||
|
game.winnings = -game.wager
|
||||||
|
|
||||||
|
game.active = False
|
||||||
|
g.db.add(game)
|
||||||
|
|
||||||
|
|
||||||
|
def determine_roulette_winners(number, bets):
|
||||||
|
winners = []
|
||||||
|
payouts = {}
|
||||||
|
rewards_by_game_id = {}
|
||||||
|
|
||||||
|
def add_to_winnings(bet):
|
||||||
|
game_id = int(bet['game_id'])
|
||||||
|
gambler_id = bet['gambler']
|
||||||
|
wager_amount = bet['wager']['amount']
|
||||||
|
bet_kind = bet['bet']
|
||||||
|
reward = wager_amount * PAYOUT_MULITPLIERS[bet_kind]
|
||||||
|
payout = wager_amount + reward
|
||||||
|
currency = bet['wager']['currency']
|
||||||
|
|
||||||
|
if not gambler_id in winners:
|
||||||
|
winners.append(gambler_id)
|
||||||
|
|
||||||
|
if not payouts.get(gambler_id):
|
||||||
|
payouts[gambler_id] = {
|
||||||
|
'coins': 0,
|
||||||
|
'procoins': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if not rewards_by_game_id.get(game_id):
|
||||||
|
rewards_by_game_id[game_id] = reward
|
||||||
|
|
||||||
|
payouts[gambler_id][currency] += payout
|
||||||
|
|
||||||
|
# Straight-Up Bet
|
||||||
|
for bet in bets[RouletteAction.STRAIGHT_UP_BET]:
|
||||||
|
if int(bet['which']) == number:
|
||||||
|
add_to_winnings(bet)
|
||||||
|
|
||||||
|
# Line Bet
|
||||||
|
line = -1
|
||||||
|
for i in range(1, 7):
|
||||||
|
if number in LINES[i]:
|
||||||
|
line = i
|
||||||
|
|
||||||
|
for bet in bets[RouletteAction.LINE_BET]:
|
||||||
|
if int(bet['which']) == line:
|
||||||
|
add_to_winnings(bet)
|
||||||
|
|
||||||
|
# Column Bet
|
||||||
|
column = -1
|
||||||
|
for i in range(1, 4):
|
||||||
|
if number in COLUMNS[i]:
|
||||||
|
column = i
|
||||||
|
|
||||||
|
for bet in bets[RouletteAction.COLUMN_BET]:
|
||||||
|
if int(bet['which']) == column:
|
||||||
|
add_to_winnings(bet)
|
||||||
|
|
||||||
|
# Dozen Bet
|
||||||
|
dozen = -1
|
||||||
|
for i in range(1, 4):
|
||||||
|
if number in DOZENS[i]:
|
||||||
|
dozen = i
|
||||||
|
|
||||||
|
for bet in bets[RouletteAction.DOZEN_BET]:
|
||||||
|
if int(bet['which']) == dozen:
|
||||||
|
add_to_winnings(bet)
|
||||||
|
|
||||||
|
# Even/Odd Bet
|
||||||
|
even_odd = RouletteEvenOdd.EVEN if number % 2 == 0 else RouletteEvenOdd.ODD
|
||||||
|
|
||||||
|
for bet in bets[RouletteAction.EVEN_ODD_BET]:
|
||||||
|
if bet['which'] == even_odd:
|
||||||
|
add_to_winnings(bet)
|
||||||
|
|
||||||
|
# Red/Black Bet
|
||||||
|
red_black = RouletteRedBlack.RED if number in REDS else RouletteRedBlack.BLACK
|
||||||
|
|
||||||
|
for bet in bets[RouletteAction.RED_BLACK_BET]:
|
||||||
|
if bet['which'] == red_black:
|
||||||
|
add_to_winnings(bet)
|
||||||
|
|
||||||
|
# High/Low Bet
|
||||||
|
high_low = RouletteHighLow.HIGH if number > 18 else RouletteHighLow.LOW
|
||||||
|
|
||||||
|
for bet in bets[RouletteAction.HIGH_LOW_BET]:
|
||||||
|
if bet['which'] == high_low:
|
||||||
|
add_to_winnings(bet)
|
||||||
|
|
||||||
|
return winners, payouts, rewards_by_game_id
|
||||||
|
|
||||||
|
|
||||||
|
def get_roulette_bets():
|
||||||
|
return get_roulette_bets_and_betters()[1]
|
|
@ -1,8 +1,6 @@
|
||||||
import json
|
import json
|
||||||
from locale import currency
|
|
||||||
from math import floor
|
from math import floor
|
||||||
import random
|
import random
|
||||||
from functools import reduce
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from files.classes.casino_game import Casino_Game
|
from files.classes.casino_game import Casino_Game
|
||||||
from flask import g
|
from flask import g
|
||||||
|
@ -362,6 +360,7 @@ def get_value_of_hand(hand):
|
||||||
|
|
||||||
return max(possibilities)
|
return max(possibilities)
|
||||||
|
|
||||||
|
|
||||||
def get_available_actions(state):
|
def get_available_actions(state):
|
||||||
actions = []
|
actions = []
|
||||||
|
|
||||||
|
@ -371,8 +370,8 @@ def get_available_actions(state):
|
||||||
|
|
||||||
if can_double_down(state):
|
if can_double_down(state):
|
||||||
actions.append(BlackjackAction.DOUBLE_DOWN)
|
actions.append(BlackjackAction.DOUBLE_DOWN)
|
||||||
|
|
||||||
if can_purchase_insurance(state):
|
if can_purchase_insurance(state):
|
||||||
actions.append(BlackjackAction.BUY_INSURANCE)
|
actions.append(BlackjackAction.BUY_INSURANCE)
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
|
|
|
@ -8,32 +8,26 @@ from files.helpers.slots import *
|
||||||
from files.helpers.lottery import *
|
from files.helpers.lottery import *
|
||||||
from files.helpers.casino import *
|
from files.helpers.casino import *
|
||||||
from files.helpers.twentyone import *
|
from files.helpers.twentyone import *
|
||||||
|
from files.helpers.roulette import *
|
||||||
|
|
||||||
|
|
||||||
@app.get("/casino")
|
@app.get("/casino")
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def casino(v):
|
def casino(v):
|
||||||
if v.rehab: return render_template("casino/rehab.html", v=v)
|
if v.rehab:
|
||||||
|
return render_template("casino/rehab.html", v=v)
|
||||||
|
|
||||||
return render_template("casino.html", v=v)
|
return render_template("casino.html", v=v)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/lottershe")
|
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
|
||||||
@auth_required
|
|
||||||
def lottershe(v):
|
|
||||||
if v.rehab: return render_template("casino/rehab.html", v=v)
|
|
||||||
participants = get_users_participating_in_lottery()
|
|
||||||
return render_template("lottery.html", v=v, participants=participants)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/casino/<game>")
|
@app.get("/casino/<game>")
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def casino_game_page(v, game):
|
def casino_game_page(v, game):
|
||||||
if v.rehab: return render_template("casino/rehab.html", v=v)
|
if v.rehab:
|
||||||
|
return render_template("casino/rehab.html", v=v)
|
||||||
|
|
||||||
feed = json.dumps(get_game_feed(game))
|
feed = json.dumps(get_game_feed(game))
|
||||||
leaderboard = json.dumps(get_game_leaderboard(game))
|
leaderboard = json.dumps(get_game_leaderboard(game))
|
||||||
|
|
||||||
|
@ -50,15 +44,31 @@ def casino_game_page(v, game):
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def casino_game_feed(v, game):
|
def casino_game_feed(v, game):
|
||||||
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
feed = get_game_feed(game)
|
feed = get_game_feed(game)
|
||||||
return {"feed": feed}
|
return {"feed": feed}
|
||||||
|
|
||||||
|
|
||||||
|
# Lottershe
|
||||||
|
@app.get("/lottershe")
|
||||||
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
|
@auth_required
|
||||||
|
def lottershe(v):
|
||||||
|
if v.rehab:
|
||||||
|
return render_template("casino/rehab.html", v=v)
|
||||||
|
|
||||||
|
participants = get_users_participating_in_lottery()
|
||||||
|
return render_template("lottery.html", v=v, participants=participants)
|
||||||
|
|
||||||
|
# Slots
|
||||||
@app.post("/casino/slots")
|
@app.post("/casino/slots")
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def pull_slots(v):
|
def pull_slots(v):
|
||||||
if v.rehab: return {"error": "You are under Rehab award effect!"}, 400
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
wager = int(request.values.get("wager"))
|
wager = int(request.values.get("wager"))
|
||||||
|
@ -81,11 +91,13 @@ def pull_slots(v):
|
||||||
return {"error": f"Wager must be more than 5 {currency}."}, 400
|
return {"error": f"Wager must be more than 5 {currency}."}, 400
|
||||||
|
|
||||||
|
|
||||||
|
# 21
|
||||||
@app.post("/casino/twentyone/deal")
|
@app.post("/casino/twentyone/deal")
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def blackjack_deal_to_player(v):
|
def blackjack_deal_to_player(v):
|
||||||
if v.rehab: return {"error": "You are under Rehab award effect!"}, 400
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
wager = int(request.values.get("wager"))
|
wager = int(request.values.get("wager"))
|
||||||
|
@ -94,17 +106,18 @@ def blackjack_deal_to_player(v):
|
||||||
state = dispatch_action(v, BlackjackAction.DEAL)
|
state = dispatch_action(v, BlackjackAction.DEAL)
|
||||||
feed = get_game_feed('blackjack')
|
feed = get_game_feed('blackjack')
|
||||||
|
|
||||||
return {"success": True, "state": state, "feed": feed}
|
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"error": str(e)}
|
return {"error": str(e)}, 400
|
||||||
|
|
||||||
|
|
||||||
@app.post("/casino/twentyone/hit")
|
@app.post("/casino/twentyone/hit")
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def blackjack_player_hit(v):
|
def blackjack_player_hit(v):
|
||||||
if v.rehab: return {"error": "You are under Rehab award effect!"}, 400
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
state = dispatch_action(v, BlackjackAction.HIT)
|
state = dispatch_action(v, BlackjackAction.HIT)
|
||||||
feed = get_game_feed('blackjack')
|
feed = get_game_feed('blackjack')
|
||||||
|
@ -117,7 +130,8 @@ def blackjack_player_hit(v):
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def blackjack_player_stay(v):
|
def blackjack_player_stay(v):
|
||||||
if v.rehab: return {"error": "You are under Rehab award effect!"}, 400
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
state = dispatch_action(v, BlackjackAction.STAY)
|
state = dispatch_action(v, BlackjackAction.STAY)
|
||||||
|
@ -131,7 +145,8 @@ def blackjack_player_stay(v):
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def blackjack_player_doubled_down(v):
|
def blackjack_player_doubled_down(v):
|
||||||
if v.rehab: return {"error": "You are under Rehab award effect!"}, 400
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
state = dispatch_action(v, BlackjackAction.DOUBLE_DOWN)
|
state = dispatch_action(v, BlackjackAction.DOUBLE_DOWN)
|
||||||
|
@ -145,7 +160,8 @@ def blackjack_player_doubled_down(v):
|
||||||
@limiter.limit("100/minute;2000/hour;12000/day")
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
@auth_required
|
@auth_required
|
||||||
def blackjack_player_bought_insurance(v):
|
def blackjack_player_bought_insurance(v):
|
||||||
if v.rehab: return {"error": "You are under Rehab award effect!"}, 400
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
state = dispatch_action(v, BlackjackAction.BUY_INSURANCE)
|
state = dispatch_action(v, BlackjackAction.BUY_INSURANCE)
|
||||||
|
@ -153,3 +169,40 @@ def blackjack_player_bought_insurance(v):
|
||||||
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
|
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
|
||||||
except:
|
except:
|
||||||
return {"error": "Unable to buy insurance."}, 400
|
return {"error": "Unable to buy insurance."}, 400
|
||||||
|
|
||||||
|
# Roulette
|
||||||
|
@app.get("/casino/roulette/bets")
|
||||||
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
|
@auth_required
|
||||||
|
def roulette_get_bets(v):
|
||||||
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
|
bets = get_roulette_bets()
|
||||||
|
|
||||||
|
return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/casino/roulette/place-bet")
|
||||||
|
@limiter.limit("100/minute;2000/hour;12000/day")
|
||||||
|
@auth_required
|
||||||
|
def roulette_player_placed_bet(v):
|
||||||
|
if v.rehab:
|
||||||
|
return {"error": "You are under Rehab award effect!"}, 400
|
||||||
|
|
||||||
|
try:
|
||||||
|
bet = request.values.get("bet")
|
||||||
|
which = request.values.get("which")
|
||||||
|
amount = int(request.values.get("wager"))
|
||||||
|
currency = request.values.get("currency")
|
||||||
|
|
||||||
|
if amount < 5:
|
||||||
|
return {"error": f"Minimum bet is 5 {currency}."}
|
||||||
|
|
||||||
|
gambler_placed_roulette_bet(v, bet, which, amount, currency)
|
||||||
|
|
||||||
|
bets = get_roulette_bets()
|
||||||
|
|
||||||
|
return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}}
|
||||||
|
except:
|
||||||
|
return {"error": "Unable to place a bet."}, 400
|
|
@ -3,6 +3,12 @@
|
||||||
{# Title (~25char max), Description (~80char max),
|
{# Title (~25char max), Description (~80char max),
|
||||||
Icon (fa-foo-bar), Color (#ff0000), URL (/post/12345/) #}
|
Icon (fa-foo-bar), Color (#ff0000), URL (/post/12345/) #}
|
||||||
{%- set GAME_INDEX = [
|
{%- set GAME_INDEX = [
|
||||||
|
(
|
||||||
|
'Roulette',
|
||||||
|
'Round and round the wheel of fate turns',
|
||||||
|
'fa-circle', '#999',
|
||||||
|
'/casino/roulette',
|
||||||
|
),
|
||||||
(
|
(
|
||||||
'Slots',
|
'Slots',
|
||||||
'Today\'s your lucky day',
|
'Today\'s your lucky day',
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
if (succeeded) {
|
if (succeeded) {
|
||||||
updateBlackjackTable(response.state);
|
updateBlackjackTable(response.state);
|
||||||
updateFeed(response.feed);
|
updateFeed(response.feed);
|
||||||
|
updatePlayerCurrencies(response.gambler);
|
||||||
} else {
|
} else {
|
||||||
console.error("Error: ", response.error);
|
console.error("Error: ", response.error);
|
||||||
throw new Error("Error")
|
throw new Error("Error")
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
).value;
|
).value;
|
||||||
const genericCurrency = currency == 'marseybux' ? 'procoins' : 'coins';
|
const genericCurrency = currency == 'marseybux' ? 'procoins' : 'coins';
|
||||||
|
|
||||||
return { amount, currency: genericCurrency };
|
return { amount, currency: genericCurrency, localCurrency: currency };
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableWager() {
|
function disableWager() {
|
||||||
|
@ -82,6 +82,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateResult(text, className) {
|
function updateResult(text, className) {
|
||||||
|
clearResult();
|
||||||
const result = document.getElementById("casinoGameResult");
|
const result = document.getElementById("casinoGameResult");
|
||||||
result.style.visibility = "visible";
|
result.style.visibility = "visible";
|
||||||
result.innerText = text;
|
result.innerText = text;
|
||||||
|
@ -396,7 +397,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="game_screen-title">
|
<div class="game_screen-title">
|
||||||
<h5>Actions</h5>
|
<h5>{% block actiontext %}Actions{% endblock %}</h5>
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
{% block actions %} {% endblock %}
|
{% block actions %} {% endblock %}
|
||||||
|
|
|
@ -0,0 +1,578 @@
|
||||||
|
{% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
if (
|
||||||
|
document.readyState === "complete" ||
|
||||||
|
(document.readyState !== "loading" && !document.documentElement.doScroll)
|
||||||
|
) {
|
||||||
|
initializeGame();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", 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 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\">";
|
||||||
|
for (let i = 1; i < 13; i++) {
|
||||||
|
const isRed = reds.includes(i);
|
||||||
|
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
|
||||||
|
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\">";
|
||||||
|
for (let i = 13; i < 25; i++) {
|
||||||
|
const isRed = reds.includes(i);
|
||||||
|
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
|
||||||
|
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\">";
|
||||||
|
for (let i = 25; i < 37; i++) {
|
||||||
|
const isRed = reds.includes(i);
|
||||||
|
const correctNumber = CELL_TO_NUMBER_LOOKUP[i];
|
||||||
|
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 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 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,
|
||||||
|
procoins: 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,
|
||||||
|
procoins: 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 dramacoinImgHtml = `
|
||||||
|
<img
|
||||||
|
src="/i/rDrama/coins.webp?v=3009"
|
||||||
|
alt="coin"
|
||||||
|
width="32"
|
||||||
|
data-bs-toggle="tooltip"
|
||||||
|
data-bs-placement="bottom"
|
||||||
|
title=""
|
||||||
|
aria-label="Dramacoin"
|
||||||
|
data-bs-original-title="Dramacoin" />
|
||||||
|
`;
|
||||||
|
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, dramacoin, marseybux } = flatBets.reduce((prev, next) => {
|
||||||
|
if (!prev.participants.includes(next.gambler_username)) {
|
||||||
|
prev.participants.push(next.gambler_username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next.wager.currency == 'coins') {
|
||||||
|
prev.dramacoin += next.wager.amount;
|
||||||
|
} else {
|
||||||
|
prev.marseybux += next.wager.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prev;
|
||||||
|
}, { participants: [], dramacoin: 0, marseybux: 0 });
|
||||||
|
const dramacoinText = `${dramacoin} ${dramacoinImgHtml}`;
|
||||||
|
const marseybuxText = `${marseybux} ${marseybuxImgHtml}`;
|
||||||
|
const playerText = participants.length > 1 ? `${participants.length} players are` : `1 player is`;
|
||||||
|
const totalText = dramacoin && marseybux ? `${dramacoinText} and ${marseybuxText}` : dramacoin ? dramacoinText : 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} ${dramacoinImgHtml}` : "";
|
||||||
|
const procoinText = wagerTotal.procoins > 0 ? `${wagerTotal.procoins} ${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} ${dramacoinImgHtml}` : "";
|
||||||
|
const procoinText = individualBet.amounts.procoins > 0 ? `${individualBet.amounts.procoins} ${marseybuxImgHtml}` : "";
|
||||||
|
const details = {
|
||||||
|
STRAIGHT_UP_BET: `that the number will be ${individualBet.which}`,
|
||||||
|
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 texts = {
|
||||||
|
STRAIGHT_UP_BET: `Bet ${amount} ${currency} on ${which}?\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.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.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>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block screen %}
|
||||||
|
<style>
|
||||||
|
.roulette-table-number {
|
||||||
|
flex: 1;
|
||||||
|
height: 60px;
|
||||||
|
border: 1px solid white;
|
||||||
|
background: green;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: white;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-table-number__black {
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-table-number__red {
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-table-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-table-column {
|
||||||
|
flex: 1;
|
||||||
|
height: 60px;
|
||||||
|
border: 1px solid white;
|
||||||
|
background: green;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: white;
|
||||||
|
font-weight: bolder;
|
||||||
|
writing-mode: vertical-rl;
|
||||||
|
text-orientation: sideways;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-table-line,
|
||||||
|
.roulette-table-1to1 {
|
||||||
|
border: 1px solid white;
|
||||||
|
background: green;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: white;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-table-line {
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-table-1to1 {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-poker-chip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-bet-summary--heading {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-bet-summary--heading p {
|
||||||
|
margin: 0;
|
||||||
|
margin-left: 1rem;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-bet-summary--list {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-poker-chip img:last-child {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roulette-total-bets {
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="roulette-table">
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block actiontext %}
|
||||||
|
Bets
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block actions %}
|
||||||
|
<div id="roulette-bets">
|
||||||
|
<div class="roulette-bet-summary">
|
||||||
|
<div class="roulette-bet-summary--heading">
|
||||||
|
<div class="roulette-poker-chip">
|
||||||
|
<img src="/i/pokerchip.webp" width="40" height="40" />
|
||||||
|
<img src="/e/marseycodecellove.webp" width="40" height="40" />
|
||||||
|
</div>
|
||||||
|
<p>111 is betting 4 and 4:
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ul class="roulette-bet-summary--list">
|
||||||
|
<li>2 <img src="/i/rDrama/coins.webp?v=3009" alt="coin" width="32" data-bs-toggle="tooltip"
|
||||||
|
data-bs-placement="bottom" title="" aria-label="Dramacoin" data-bs-original-title="Dramacoin"> that
|
||||||
|
the number will be black.</li>
|
||||||
|
<li>2 <img src="/i/rDrama/coins.webp?v=3009" alt="coin" width="32" data-bs-toggle="tooltip"
|
||||||
|
data-bs-placement="bottom" title="" aria-label="Dramacoin" data-bs-original-title="Dramacoin"> that
|
||||||
|
the number will be even.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="game_screen-title">
|
||||||
|
<h5>How to Bet</h5>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Bet</th>
|
||||||
|
<th>Payout</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Straight Up</td>
|
||||||
|
<td>35:1</td>
|
||||||
|
<td>
|
||||||
|
Click any single number. <br />
|
||||||
|
You win if the roulette lands on that number.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Line</td>
|
||||||
|
<td>5:1</td>
|
||||||
|
<td>
|
||||||
|
Click Line 1, Line 2 ... Line 6. <br />
|
||||||
|
You win if the roulette lands on any of the six numbers beneath the line.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Column</td>
|
||||||
|
<td>2:1</td>
|
||||||
|
<td>
|
||||||
|
Click Col 1, Col 2 or Col 3. <br />
|
||||||
|
You win if the roulette lands on any of the 12 numbers to the left of the column.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Dozen</td>
|
||||||
|
<td>2:1</td>
|
||||||
|
<td>
|
||||||
|
Click 1st12, 2nd12 or 3rd12. <br />
|
||||||
|
You win if the roulette lands on a number within 1-12, 13-24 or 25-36, respectively.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Even/Odd</td>
|
||||||
|
<td>1:1</td>
|
||||||
|
<td>
|
||||||
|
Click EVEN or ODD. <br />
|
||||||
|
You win if the roulette lands on a number that matches your choice.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Red/Black</td>
|
||||||
|
<td>1:1</td>
|
||||||
|
<td>
|
||||||
|
Click RED or BLACK. <br />
|
||||||
|
You win if the roulette lands on a number that is the same color as your choice.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>High/Low</td>
|
||||||
|
<td>1:1</td>
|
||||||
|
<td>
|
||||||
|
Click 1:18 or 19:36. <br />
|
||||||
|
You win if the roulette lands on a number within your selected range.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TYPE casino_game_kind ADD VALUE 'roulette';
|
Loading…
Reference in New Issue