use tabs, not spaces

remotes/1693176582716663532/tmp_refs/heads/watchparty
Aevann1 2022-10-29 01:39:31 +02:00
parent 065a024639
commit 5719688178
25 changed files with 2124 additions and 2124 deletions

View File

@ -144,8 +144,8 @@ blockquote a {
.sidebar
{
border-radius: 6px;
margin-top: 6px;
border-radius: 6px;
margin-top: 6px;
}
h5.post-title a:visited {

View File

@ -32,7 +32,7 @@
.ricardo img {
max-height: 15rem !important;
max-height: min(30vw,15rem) !important;
max-height: min(30vw,15rem) !important;
}
.ricardoleft {

View File

@ -1,70 +1,70 @@
#posts {
display: grid;
grid-template: auto / auto auto auto;
display: grid;
grid-template: auto / auto auto auto;
}
@media (min-width: 1668px) {
#frontpage .post-img {
height:105px;
width:150px;
}
#frontpage .post-img {
height:105px;
width:150px;
}
#frontpage .post-title {
font-size: 18px;
}
#frontpage .post-title {
font-size: 18px;
}
#frontpage .post-meta, .post-actions button, .post-actions a {
font-size:14px;
}
#frontpage .post-meta, .post-actions button, .post-actions a {
font-size:14px;
}
}
@media (max-width: 960px) {
#posts {
display: grid;
grid-template: auto / auto auto;
}
#posts {
display: grid;
grid-template: auto / auto auto;
}
}
@media (max-width: 768px) {
#posts {
display: grid;
grid-template: auto / auto;
}
#posts {
display: grid;
grid-template: auto / auto;
}
}
#frontpage .sidebar {
display:none !important;
display:none !important;
}
#frontpage .container {
max-width: 1750px;
max-width: 1750px;
}
#frontpage .voting.d-md-flex {
display: none !important;
display: none !important;
}
#frontpage .voting.d-md-none {
display: block !important;
display: block !important;
}
#frontpage .card-footer {
display: block !important;
display: block !important;
}
#frontpage .post-actions.d-md-block {
display: none !important;
display: none !important;
}
#fronpage.card {
padding: 0.5rem !important;
padding: 0.5rem !important;
}
#frontpage .modal.d-md-none.show {
display: inline-block !important;
max-width: 30rem;
display: inline-block !important;
max-width: 30rem;
}
#frontpage .fa-expand-alt {
display:none;
display:none;
}

View File

@ -1,7 +1,7 @@
@import 'classic.css?v=4031';
:root {
--muted: #999;
--black: #999;
--bgc: #222;
--muted: #999;
--black: #999;
--bgc: #222;
}

View File

@ -96,8 +96,8 @@ blockquote {
.sidebar
{
border-radius: 6px;
margin-top: 6px;
border-radius: 6px;
margin-top: 6px;
}
h5.post-title a:visited {

View File

@ -71,12 +71,12 @@ pre {
.sidebar
{
border-radius: 6px;
margin-top: 6px;
border-radius: 6px;
margin-top: 6px;
}
.modal-content {
background-color: var(--gray-900);
background-color: var(--gray-900);
}
.modal .comment-actions .list-group-item {
@ -97,5 +97,5 @@ h5.post-title a:visited {
}
.empty-state-img {
filter: brightness(99);
filter: brightness(99);
}

View File

@ -135,7 +135,7 @@ color: var(--gray-700);
.post-title
{
color: var(--gray-300) !important;
color: var(--gray-300) !important;
}
.tooltip-inner {

View File

@ -1,12 +1,12 @@
@charset "UTF-8";
button {
background: none;
border: none;
padding: 0;
margin: 0;
border: none;
padding: 0;
margin: 0;
color: var(--primary);
text-decoration: none;
background-color: transparent;
text-decoration: none;
background-color: transparent;
}
*, *::before, *::after {
box-sizing: border-box;
@ -334,7 +334,7 @@ pre code {
.shadow {
/* box-shadow: 0 0.1px 3px rgba(190, 113, 113, 0.05), 0 0 0 0.1px rgba(0, 0, 0, 0.05); */
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.4);
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.4);
}
.shadow-none {
box-shadow: none !important;
@ -796,14 +796,14 @@ input[type=submit].btn-follow, input[type=reset].btn-follow, input[type=button].
}
@keyframes expand
{
0% { opacity: 0.0; transform: scaleY(0.7); }
100% { opacity: 1.0; transform: scaleY(1.0); }
0% { opacity: 0.0; transform: scaleY(0.7); }
100% { opacity: 1.0; transform: scaleY(1.0); }
}
.dropdown-menu-right.show
{
transform-origin: top;
animation: expand .20s 1;
transform-origin: top;
animation: expand .20s 1;
}
@ -825,12 +825,12 @@ input[type=submit].btn-follow, input[type=reset].btn-follow, input[type=button].
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.4);
border-radius: 0.35rem;
box-shadow: 0px 2px 20px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 20px rgba(0, 0, 0, 0.3);
}
.dropdown-menu-right {
right: 0;
left: auto;
left: -2px !important;
left: -2px !important;
}
@media (min-width: 992px) {
.dropdown-menu-lg-left {
@ -1123,11 +1123,11 @@ nav
align-items: center;
justify-content: space-between;
padding: 0.5rem 1rem;
transition: border-bottom .2s;
transition: border-bottom .2s;
}
.navbar-active
{
border-bottom: 1px solid rgba(18, 18, 18, .4);
border-bottom: 1px solid rgba(18, 18, 18, .4);
}
.navbar .container, .navbar .container-fluid {
display: flex;
@ -3071,7 +3071,7 @@ label.terms {
padding: 0.5rem 1rem;
border-radius: 0.35rem;
color: var(--black);
transition: background .1s, transform .2s;
transition: background .1s, transform .2s;
}
.dropdown-item:hover, .dropdown-item:focus, .dropdown-item.active {
color: var(--black);
@ -3079,7 +3079,7 @@ label.terms {
background-color: var(--gray-300);
}
.dropdown-item:active {
transform: scale(0.95);
transform: scale(0.95);
}
@ -3134,7 +3134,7 @@ small, .small {
.active-anim.arrow-up::before
{
color: var(--primary);
color: var(--primary);
}
@ -3153,78 +3153,78 @@ small, .small {
}
.arrow-up, .arrow-down
{
position: relative;
display: inline-block;
position: relative;
display: inline-block;
}
.arrow-up.active-anim
{
animation: bounce-top .7s 1 0s;
-webkit-animation: bounce-top .7s 1 0s;
animation: bounce-top .7s 1 0s;
-webkit-animation: bounce-top .7s 1 0s;
}
.arrow-down.active-anim
{
animation: bounce-bot .7s 1 0s;
-webkit-animation: bounce-bot .7s 1 0s;
animation: bounce-bot .7s 1 0s;
-webkit-animation: bounce-bot .7s 1 0s;
}
@keyframes bounce-top {
20% {
transform: translateY(-9px);
animation-timing-function: ease-in;
opacity: 1;
}
52% {
transform: translateY(-6px);
animation-timing-function: ease-in;
opacity: 1;
}
69% {
transform: translateY(-3px);
animation-timing-function: ease-in;
opacity: 1;
}
35%,
63%,
79%,
100% {
transform: translateY(0px);
animation-timing-function: ease-out;
}
20% {
transform: translateY(-9px);
animation-timing-function: ease-in;
opacity: 1;
}
52% {
transform: translateY(-6px);
animation-timing-function: ease-in;
opacity: 1;
}
69% {
transform: translateY(-3px);
animation-timing-function: ease-in;
opacity: 1;
}
35%,
63%,
79%,
100% {
transform: translateY(0px);
animation-timing-function: ease-out;
}
}
@keyframes bounce-bot {
30% {
transform: translateY(6px);
animation-timing-function: ease-in;
opacity: 1;
}
52% {
transform: translateY(3px);
animation-timing-function: ease-in;
opacity: 1;
}
69% {
transform: translateY(2px);
animation-timing-function: ease-in;
opacity: 1;
}
100% {
transform: translateY(0px);
animation-timing-function: ease-out;
}
30% {
transform: translateY(6px);
animation-timing-function: ease-in;
opacity: 1;
}
52% {
transform: translateY(3px);
animation-timing-function: ease-in;
opacity: 1;
}
69% {
transform: translateY(2px);
animation-timing-function: ease-in;
opacity: 1;
}
100% {
transform: translateY(0px);
animation-timing-function: ease-out;
}
}
.comment-write.collapsed
{
animation: expand-reply .3s 1;
animation: expand-reply .3s 1;
}
@keyframes expand-reply
{
0% { opacity: .6; padding-top: 0px; height: 0px; overflow: hidden; }
100% { opacity: 1;padding-top: 0px; height: 182px; overflow: hidden; }
0% { opacity: .6; padding-top: 0px; height: 0px; overflow: hidden; }
100% { opacity: 1;padding-top: 0px; height: 182px; overflow: hidden; }
}
.active.arrow-down::before {
@ -3261,7 +3261,7 @@ small, .small {
}
.score-up-anim
{
color: var(--primary);
color: var(--primary);
}
.score-down {
color: #38B2AC !important;
@ -3272,13 +3272,13 @@ small, .small {
.voting .arrow-up,
.voting .arrow-down
{
display: block;
display: block;
}
.catalog .voting .arrow-up,
.catalog .voting .arrow-down
{
display: inline-block;
display: inline-block;
}
@ -4207,9 +4207,9 @@ pre .com, code .com {
-ms-transition: all 0.15s ease;
transition: all 0.15s ease;
width: 25vw;
height: 35vh;
height: 35vh;
-o-object-fit: contain;
object-fit: contain;
object-fit: contain;
}
@media (max-width: 767.98px) {
.gif-categories img {
@ -4244,7 +4244,7 @@ pre .com, code .com {
}
.modal-backdrop.show
{
background-color: rgba(33, 38, 45, .8);
background-color: rgba(33, 38, 45, .8);
}
@media (max-width: 767.98px) {
@ -4376,13 +4376,13 @@ pre .com, code .com {
font-size: 1.5rem;
color: var(--gray-200);
opacity: 1;
}
#voting .arrow-up,
.voting .arrow-up,
.voting .arrow-down
{
display: inline-block;
}
}
#voting .arrow-up,
.voting .arrow-up,
.voting .arrow-down
{
display: inline-block;
}
.active.arrow-up::before, .active.arrow-up:hover::before {
color: var(--primary);
@ -4819,30 +4819,30 @@ input[type=radio] ~ .custom-control-label::before {
}
span[data-bs-toggle], .pat-preview {
position: relative;
display: inline-block;
position: relative;
display: inline-block;
}
img[src="/i/hand.webp"] {
position: absolute;
width: 90%;
height: 90%;
margin-top: -10%;
z-index: 1;
position: absolute;
width: 90%;
height: 90%;
margin-top: -10%;
z-index: 1;
}
img[src="/i/hand.webp"]+img {
animation: pat-pfp-anim 0.3s infinite;
transform-origin: bottom center;
margin-top: 10%;
text-align: center;
object-fit: contain;
animation: pat-pfp-anim 0.3s infinite;
transform-origin: bottom center;
margin-top: 10%;
text-align: center;
object-fit: contain;
}
img[src="/i/hand.webp"]+img[src^="/pp/"], img[src="/i/hand.webp"]+img[src$="/pic"] {
border-radius: 50%;
}
@keyframes pat-pfp-anim {
0% { transform: scale(1, 0.8) }
50% { transform: scale(0.8, 1) }
100% { transform: scale(1, 0.8) }
0% { transform: scale(1, 0.8) }
50% { transform: scale(0.8, 1) }
100% { transform: scale(1, 0.8) }
}
/* Fix for <ol> being populated with <li><p></p></li> in many contexts. */
@ -5211,8 +5211,8 @@ li > .sidebar {
.sidebar
{
border-radius: 6px;
margin-top: 6px;
border-radius: 6px;
margin-top: 6px;
}
@ -5305,20 +5305,20 @@ th, td {
}
.glow .post-title, .glow a, .glow .post-meta *, .glow .user-info *, .glow .comment-text, .glow .comment-actions *, .glow {
color:lightgreen !important;
text-shadow:1px 1px 1px darkgreen, 0 0 5px green;
color:lightgreen !important;
text-shadow:1px 1px 1px darkgreen, 0 0 5px green;
}
.glow .score-up, .glow .active.arrow-up::before, .glow .arrow-up::after, .glow .arrow-up:hover::before {
color: lime !important;
color: lime !important;
}
.glow .score-down, .glow .active.arrow-down::before, .glow .arrow-down::after, .glow .arrow-down:hover::before {
color: lime !important;
color: lime !important;
}
.glow .arrow-up::before, .glow .arrow-down::before, .glow .score {
color: lightgreen;
color: lightgreen;
}
.glow .post-body a, .glow .comment-text a {
@ -5468,14 +5468,14 @@ audio, video {
.lottery-page--wrapper {
flex-direction: column;
justify-content: center;
padding: 2rem;
padding: 2rem;
}
.lottery-page--wrapper > div
{
width: 300px;
height: 300px;
}
.lottery-page--wrapper > div
{
width: 300px;
height: 300px;
}
.lottery-page--action {
margin-bottom: 1rem;
@ -5647,14 +5647,14 @@ g {
}
.ext-link {
position:absolute;
bottom: 0;
right: 0;
font-size:14px;
color:white;
background-color:var(--primary);
padding:3px;
border-radius:.35rem;
position:absolute;
bottom: 0;
right: 0;
font-size:14px;
color:white;
background-color:var(--primary);
padding:3px;
border-radius:.35rem;
}
/* ------- Font Awesome ------- */
@ -6042,8 +6042,8 @@ g {
.post-preview {
padding: 11px 14px 0 14px !important;
margin-bottom: 0.5rem !important;
margin-top: 0.5rem !important;
margin-bottom: 0.5rem !important;
margin-top: 0.5rem !important;
}
@ -6054,7 +6054,7 @@ g {
}
.showmore {
width: 99%;
width: 99%;
padding: 5px;
margin: 5px 1px;
border-radius: 5px;
@ -6063,7 +6063,7 @@ g {
background: -webkit-linear-gradient(left, red, orange, yellow, green, blue, indigo, violet );
text-shadow:-1px -1px 0 black,1px -1px 0 black,-1px 1px 0 black,1px 1px 0 black;
font-weight: 600;
border: 2px solid var(--primary);
border: 2px solid var(--primary);
font-size: 20px;
}
@ -6089,66 +6089,66 @@ g {
.ghostdiv
{
display: block;
white-space: pre-wrap;
word-break: break-word;
/* Attempt to copy the textarea/input padding */
padding: 15px;
display: block;
white-space: pre-wrap;
word-break: break-word;
/* Attempt to copy the textarea/input padding */
padding: 15px;
}
#speed-carot-modal
{
background-color: var(--gray-700);
max-height: 500px;
overflow-y: auto;
overflow-x: hidden;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
background-color: var(--gray-700);
max-height: 500px;
overflow-y: auto;
overflow-x: hidden;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
z-index:999;
}
#speed-carot-modal .speed-modal-option
{
border-bottom: 1px solid #606060;
padding: 4px;
cursor: pointer;
border-bottom: 1px solid #606060;
padding: 4px;
cursor: pointer;
}
#speed-carot-modal .speed-modal-option:hover,
#speed-carot-modal .speed-modal-option:focus,
#speed-carot-modal .speed-modal-option.selected
{
background-color: rgba(255, 255, 255, 0.2);
background-color: rgba(255, 255, 255, 0.2);
}
#speed-carot-modal .speed-modal-image
{
object-fit: contain;
width: 30px;
height: 30px;
object-fit: contain;
width: 30px;
height: 30px;
}
#speed-carot-modal .speed-modal-option span
{
overflow: hidden;
display: inline-block;
vertical-align: middle;
margin-left: 10px;
margin-right: 10px;
overflow: hidden;
display: inline-block;
vertical-align: middle;
margin-left: 10px;
margin-right: 10px;
}
.rainbow-text:not(a) {
background-image: repeating-linear-gradient(135deg, violet, rgb(178, 94, 238), lightblue, green, yellow, orange, #ff7f7f 50%) !important;
color: transparent !important;
background-clip: text !important;
-webkit-background-clip: text !important;
font-weight: 700 !important;
background-image: repeating-linear-gradient(135deg, violet, rgb(178, 94, 238), lightblue, green, yellow, orange, #ff7f7f 50%) !important;
color: transparent !important;
background-clip: text !important;
-webkit-background-clip: text !important;
font-weight: 700 !important;
}
.rainbow-text:not(a) > p {
color: transparent !important;
color: transparent !important;
}
.btn-rainbow {
@ -6219,7 +6219,7 @@ blockquote + blockquote, div > blockquote:first-child, blockquote:last-child {
}
div.markdown {
height: auto;
white-space: pre-wrap;
white-space: pre-wrap;
}
@media (max-width: 768px) or (min-width: 992px) {
#sidebar-btn {
@ -6236,11 +6236,11 @@ div.markdown {
}
.directory--link:hover * {
color: var(--primary) !important;
color: var(--primary) !important;
}
::-webkit-input-placeholder {
opacity: 0.7 !important;
opacity: 0.7 !important;
}
.text-brown {

View File

@ -44,8 +44,8 @@ body, .navbar-light, .navbar-dark, .card, .modal-content, .comment-write textare
.sidebar
{
border-radius: 6px;
margin-top: 6px;
border-radius: 6px;
margin-top: 6px;
}
.table th, .table td {

View File

@ -1,7 +1,7 @@
.mod:before {
content: '(((';
content: '(((';
}
.mod:after {
content: ')))';
}
content: ')))';
}

View File

@ -221,8 +221,8 @@
.sidebar
{
border-radius: 6px;
margin-top: 6px;
border-radius: 6px;
margin-top: 6px;
}
.tooltip-inner {

View File

@ -158,8 +158,8 @@ blockquote {
.sidebar
{
border-radius: 0px;
margin-top: 6px;
border-radius: 0px;
margin-top: 6px;
}
h5.post-title a:visited {

View File

@ -20,7 +20,7 @@ class Leaderboard:
value_func = None
def __init__(self, header_name:str, table_header_name:str, html_id:str, table_column_name:str,
user_relative_url:Optional[str], query_function:Callable[..., Tuple[Any, Any, Any]],
user_relative_url:Optional[str], query_function:Callable[..., Tuple[Any, Any, Any]],
criteria, v:User, value_func:Optional[Callable[[User], Union[int, Column]]], db:scoped_session, users, limit=LEADERBOARD_LIMIT):
self.header_name = header_name
self.table_header_name = table_header_name

View File

@ -9,99 +9,99 @@ from files.helpers.wrappers import *
def get_game_feed(game):
games = g.db.query(Casino_Game) \
.filter(Casino_Game.active == False, Casino_Game.kind == game) \
.order_by(Casino_Game.created_utc.desc()).limit(30).all()
games = g.db.query(Casino_Game) \
.filter(Casino_Game.active == False, Casino_Game.kind == game) \
.order_by(Casino_Game.created_utc.desc()).limit(30).all()
def format_game(game):
user = g.db.query(User).filter(User.id == game.user_id).one()
wonlost = 'lost' if game.winnings < 0 else 'won'
relevant_currency = "coin" if game.currency == "coins" else "marseybux"
def format_game(game):
user = g.db.query(User).filter(User.id == game.user_id).one()
wonlost = 'lost' if game.winnings < 0 else 'won'
relevant_currency = "coin" if game.currency == "coins" else "marseybux"
return {
"user": user.username,
"won_or_lost": wonlost,
"amount": abs(game.winnings),
"currency": relevant_currency
}
return {
"user": user.username,
"won_or_lost": wonlost,
"amount": abs(game.winnings),
"currency": relevant_currency
}
return list(map(format_game, games))
return list(map(format_game, games))
def get_game_leaderboard(game):
timestamp_24h_ago = time.time() - 86400
timestamp_all_time = 1662825600 # "All Time" starts on release day
timestamp_24h_ago = time.time() - 86400
timestamp_all_time = 1662825600 # "All Time" starts on release day
biggest_win_all_time = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.desc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_all_time).limit(1).one_or_none()
biggest_win_all_time = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.desc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_all_time).limit(1).one_or_none()
biggest_win_last_24h = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.desc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_24h_ago).limit(1).one_or_none()
biggest_win_last_24h = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.desc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_24h_ago).limit(1).one_or_none()
biggest_loss_all_time = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.asc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_all_time).limit(1).one_or_none()
biggest_loss_all_time = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.asc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_all_time).limit(1).one_or_none()
biggest_loss_last_24h = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.asc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_24h_ago).limit(1).one_or_none()
biggest_loss_last_24h = g.db.query(Casino_Game.user_id, User.username, Casino_Game.currency, Casino_Game.winnings).select_from(
Casino_Game).join(User).order_by(Casino_Game.winnings.asc()).filter(Casino_Game.kind == game, Casino_Game.created_utc > timestamp_24h_ago).limit(1).one_or_none()
if not biggest_win_all_time:
biggest_win_all_time = [None, None, None, 0]
if not biggest_win_all_time:
biggest_win_all_time = [None, None, None, 0]
if not biggest_win_last_24h:
biggest_win_last_24h = [None, None, None, 0]
if not biggest_win_last_24h:
biggest_win_last_24h = [None, None, None, 0]
if not biggest_loss_all_time:
biggest_loss_all_time = [None, None, None, 0]
if not biggest_loss_all_time:
biggest_loss_all_time = [None, None, None, 0]
if not biggest_loss_last_24h:
biggest_loss_last_24h = [None, None, None, 0]
if not biggest_loss_last_24h:
biggest_loss_last_24h = [None, None, None, 0]
return {
"all_time": {
"biggest_win": {
return {
"all_time": {
"biggest_win": {
"user": biggest_win_all_time[1],
"currency": biggest_win_all_time[2],
"amount": biggest_win_all_time[3]
},
"biggest_loss": {
"biggest_loss": {
"user": biggest_loss_all_time[1],
"currency": biggest_loss_all_time[2],
"amount": abs(biggest_loss_all_time[3])
}
},
"last_24h": {
"biggest_win": {
},
"last_24h": {
"biggest_win": {
"user": biggest_win_last_24h[1],
"currency": biggest_win_last_24h[2],
"amount": biggest_win_last_24h[3]
},
"biggest_loss": {
"biggest_loss": {
"user": biggest_loss_last_24h[1],
"currency": biggest_loss_last_24h[2],
"amount": abs(biggest_loss_last_24h[3])
}
}
}
}
}
def distribute_wager_badges(user, wager, won):
badges_earned = []
badges_earned = []
if won:
if wager >= 1000:
badges_earned.append(160)
if wager >= 10000:
badges_earned.append(161)
if wager >= 100000:
badges_earned.append(162)
else:
if wager >= 1000:
badges_earned.append(157)
if wager >= 10000:
badges_earned.append(158)
if wager >= 100000:
badges_earned.append(159)
if won:
if wager >= 1000:
badges_earned.append(160)
if wager >= 10000:
badges_earned.append(161)
if wager >= 100000:
badges_earned.append(162)
else:
if wager >= 1000:
badges_earned.append(157)
if wager >= 10000:
badges_earned.append(158)
if wager >= 100000:
badges_earned.append(159)
for badge in badges_earned:
badge_grant(user, badge)
for badge in badges_earned:
badge_grant(user, badge)

View File

@ -8,35 +8,35 @@ CLOUDFLARE_REQUEST_TIMEOUT_SECS = 5
DEFAULT_CLOUDFLARE_ZONE = 'blahblahblah'
def _request_from_cloudflare(url:str, method:str, post_data_str) -> bool:
if CF_ZONE == DEFAULT_CLOUDFLARE_ZONE: return False
try:
res = str(requests.request(method, f"{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/{url}", headers=CF_HEADERS, data=post_data_str, timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS))
except:
return False
return res == "<Response [200]>"
if CF_ZONE == DEFAULT_CLOUDFLARE_ZONE: return False
try:
res = str(requests.request(method, f"{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/{url}", headers=CF_HEADERS, data=post_data_str, timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS))
except:
return False
return res == "<Response [200]>"
def get_security_level() -> Optional[str]:
res = None
try:
res = requests.get(f'{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS).json()['result']['value']
except:
pass
return res
res = None
try:
res = requests.get(f'{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS).json()['result']['value']
except:
pass
return res
def set_security_level(under_attack="high") -> bool:
return _request_from_cloudflare("settings/security_level", "PATCH", f'{{"value":"{under_attack}"}}')
return _request_from_cloudflare("settings/security_level", "PATCH", f'{{"value":"{under_attack}"}}')
def purge_entire_cache() -> bool:
return _request_from_cloudflare("purge_cache", "POST", '{"purge_everything":true}')
return _request_from_cloudflare("purge_cache", "POST", '{"purge_everything":true}')
def purge_files_in_cache(files:Union[List[str],str]) -> bool:
if CF_ZONE == DEFAULT_CLOUDFLARE_ZONE: return False
if isinstance(files, str):
files = [files]
post_data = {"files": files}
res = None
try:
res = requests.post(f'{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, data=json.dumps(post_data), timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS)
except:
return False
return res == "<Response [200]>"
if CF_ZONE == DEFAULT_CLOUDFLARE_ZONE: return False
if isinstance(files, str):
files = [files]
post_data = {"files": files}
res = None
try:
res = requests.post(f'{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, data=json.dumps(post_data), timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS)
except:
return False
return res == "<Response [200]>"

View File

@ -866,13 +866,13 @@ AWARDS = {
"price": 1500
},
"spider": {
"kind": "spider",
"title": "Spider!",
"description": f"Summons a spider to terrorize the recipient for 24 hours.",
"icon": "fas fa-spider",
"color": "text-brown",
"price": 2000
},
"kind": "spider",
"title": "Spider!",
"description": f"Summons a spider to terrorize the recipient for 24 hours.",
"icon": "fas fa-spider",
"color": "text-brown",
"price": 2000
},
"agendaposter": {
"kind": "agendaposter",
"title": "Chud",

View File

@ -199,58 +199,58 @@ def get_comment(i:Union[str, int], v:Optional[User]=None, graceful=False) -> Opt
return add_vote_and_block_props(comment, v, CommentVote)
def add_block_props(target:Union[Submission, Comment, User], v:Optional[User]):
if not v: return target
id = None
if not v: return target
id = None
if any(isinstance(target, cls) for cls in [Submission, Comment]):
id = target.author_id
elif isinstance(target, User):
id = target.id
else:
raise TypeError("add_block_props only supports non-None submissions, comments, and users")
if hasattr(target, 'is_blocking') and hasattr(target, 'is_blocked'):
return target
if any(isinstance(target, cls) for cls in [Submission, Comment]):
id = target.author_id
elif isinstance(target, User):
id = target.id
else:
raise TypeError("add_block_props only supports non-None submissions, comments, and users")
if hasattr(target, 'is_blocking') and hasattr(target, 'is_blocked'):
return target
if v.id == id or id == AUTOJANNY_ID: # users can't block or be blocked by themselves or AutoJanny
target.is_blocking = False
target.is_blocked = False
return target
if v.id == id or id == AUTOJANNY_ID: # users can't block or be blocked by themselves or AutoJanny
target.is_blocking = False
target.is_blocked = False
return target
block = g.db.query(UserBlock).filter(
or_(
and_(
UserBlock.user_id == v.id,
UserBlock.target_id == id
),
and_(
UserBlock.user_id == id,
UserBlock.target_id == v.id
)
)
).first()
target.is_blocking = block and block.user_id == v.id
target.is_blocked = block and block.target_id == v.id
return target
block = g.db.query(UserBlock).filter(
or_(
and_(
UserBlock.user_id == v.id,
UserBlock.target_id == id
),
and_(
UserBlock.user_id == id,
UserBlock.target_id == v.id
)
)
).first()
target.is_blocking = block and block.user_id == v.id
target.is_blocked = block and block.target_id == v.id
return target
def add_vote_props(target:Union[Submission, Comment], v:Optional[User], vote_cls):
if hasattr(target, 'voted'): return target
if hasattr(target, 'voted'): return target
vt = g.db.query(vote_cls.vote_type).filter_by(user_id=v.id)
if vote_cls == Vote:
vt = vt.filter_by(submission_id=target.id)
elif vote_cls == CommentVote:
vt = vt.filter_by(comment_id=target.id)
else:
vt = None
if vt: vt = vt.one_or_none()
target.voted = vt.vote_type if vt else 0
return target
vt = g.db.query(vote_cls.vote_type).filter_by(user_id=v.id)
if vote_cls == Vote:
vt = vt.filter_by(submission_id=target.id)
elif vote_cls == CommentVote:
vt = vt.filter_by(comment_id=target.id)
else:
vt = None
if vt: vt = vt.one_or_none()
target.voted = vt.vote_type if vt else 0
return target
def add_vote_and_block_props(target:Union[Submission, Comment], v:Optional[User], vote_cls):
if not v: return target
target = add_block_props(target, v)
return add_vote_props(target, v, vote_cls)
if not v: return target
target = add_block_props(target, v)
return add_vote_props(target, v, vote_cls)
def get_comments(cids:Iterable[int], v:Optional[User]=None) -> List[Comment]:
if not cids: return []

View File

@ -8,290 +8,290 @@ 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"
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"
EVEN = "EVEN"
ODD = "ODD"
class RouletteRedBlack(str, Enum):
RED = "RED"
BLACK = "BLACK"
RED = "RED"
BLACK = "BLACK"
class RouletteHighLow(str, Enum):
HIGH = "HIGH"
LOW = "LOW"
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)
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)
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)
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,
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()
return g.db.query(Casino_Game).filter(
Casino_Game.active == True,
Casino_Game.kind == 'roulette'
).all()
def charge_gambler(gambler, amount, currency):
charged = gambler.charge_account(currency, amount)
charged = gambler.charge_account(currency, amount)
if not charged:
raise Exception("Gambler cannot afford charge.")
if not charged:
raise Exception("Gambler cannot afford charge.")
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')
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()
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']
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)
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()
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()
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)
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
}
})
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
return participants, bets, active_games
def spin_roulette_wheel():
participants, bets, active_games = get_roulette_bets_and_betters()
participants, bets, active_games = get_roulette_bets_and_betters()
if len(participants) > 0:
number = randint(0, 37) # 37 is 00
if len(participants) > 0:
number = randint(0, 37) # 37 is 00
if number > 0 and number < 37: # 0 and 00 do not pay anything
winners, payouts, rewards_by_game_id = determine_roulette_winners(number, bets)
else:
winners = []
payouts = {}
rewards_by_game_id = {}
if number > 0 and number < 37: # 0 and 00 do not pay anything
winners, payouts, rewards_by_game_id = determine_roulette_winners(number, bets)
else:
winners = []
payouts = {}
rewards_by_game_id = {}
# 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']
# 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']
gambler.pay_account('coins', coin_winnings)
gambler.pay_account('procoins', procoin_winnings)
gambler.pay_account('coins', coin_winnings)
gambler.pay_account('procoins', procoin_winnings)
# Notify the winners.
notification_text = f"Winning number: {number}\nCongratulations! One or more of your roulette bets paid off!\n"
# 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} coins.\n"
if coin_winnings > 0:
notification_text = notification_text + \
f"* You received {coin_winnings} coins.\n"
if procoin_winnings > 0:
notification_text = notification_text + \
f"* You received {procoin_winnings} marseybux.\n"
if procoin_winnings > 0:
notification_text = notification_text + \
f"* You received {procoin_winnings} marseybux.\n"
send_repeatable_notification(user_id, notification_text)
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.")
# 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()
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
# 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)
game.active = False
g.db.add(game)
# Commit early when dirty because of long-running tasks after roulette
g.db.commit()
# Commit early when dirty because of long-running tasks after roulette
g.db.commit()
def determine_roulette_winners(number, bets):
winners = []
payouts = {}
rewards_by_game_id = {}
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']
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 gambler_id in winners:
winners.append(gambler_id)
if not payouts.get(gambler_id):
payouts[gambler_id] = {
'coins': 0,
'procoins': 0
}
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
if not rewards_by_game_id.get(game_id):
rewards_by_game_id[game_id] = reward
payouts[gambler_id][currency] += payout
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)
# 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
# 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)
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
# 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)
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
# 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)
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
# 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)
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
# 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)
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
# 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)
for bet in bets[RouletteAction.HIGH_LOW_BET]:
if bet['which'] == high_low:
add_to_winnings(bet)
return winners, payouts, rewards_by_game_id
return winners, payouts, rewards_by_game_id
def get_roulette_bets():
return get_roulette_bets_and_betters()[1]
return get_roulette_bets_and_betters()[1]

View File

@ -8,20 +8,20 @@ from flask import g
class BlackjackStatus(str, Enum):
PLAYING = "PLAYING"
STAYED = "STAYED"
PUSHED = "PUSHED"
WON = "WON"
LOST = "LOST"
BLACKJACK = "BLACKJACK"
PLAYING = "PLAYING"
STAYED = "STAYED"
PUSHED = "PUSHED"
WON = "WON"
LOST = "LOST"
BLACKJACK = "BLACKJACK"
class BlackjackAction(str, Enum):
DEAL = "DEAL"
HIT = "HIT"
STAY = "STAY"
DOUBLE_DOWN = "DOUBLE_DOWN"
BUY_INSURANCE = "BUY_INSURANCE"
DEAL = "DEAL"
HIT = "HIT"
STAY = "STAY"
DOUBLE_DOWN = "DOUBLE_DOWN"
BUY_INSURANCE = "BUY_INSURANCE"
ranks = ("2", "3", "4", "5", "6", "7", "8", "9", "X", "J", "Q", "K", "A")
@ -32,350 +32,350 @@ minimum_bet = 5
def get_initial_state():
return {
"player": [],
"player_value": 0,
"dealer": [],
"dealer_value": 0,
"player_bought_insurance": False,
"player_doubled_down": False,
"status": BlackjackStatus.PLAYING,
"actions": [BlackjackAction.DEAL],
"wager": {
"amount": 0,
"currency": "coins"
},
"payout": 0
}
return {
"player": [],
"player_value": 0,
"dealer": [],
"dealer_value": 0,
"player_bought_insurance": False,
"player_doubled_down": False,
"status": BlackjackStatus.PLAYING,
"actions": [BlackjackAction.DEAL],
"wager": {
"amount": 0,
"currency": "coins"
},
"payout": 0
}
def build_casino_game(gambler, wager, currency):
initial_state = get_initial_state()
initial_state['wager']['amount'] = wager
initial_state['wager']['currency'] = currency
initial_state = get_initial_state()
initial_state['wager']['amount'] = wager
initial_state['wager']['currency'] = currency
casino_game = Casino_Game()
casino_game.user_id = gambler.id
casino_game.currency = currency
casino_game.wager = wager
casino_game.winnings = 0
casino_game.kind = 'blackjack'
casino_game.game_state = json.dumps(initial_state)
casino_game.active = True
g.db.add(casino_game)
casino_game = Casino_Game()
casino_game.user_id = gambler.id
casino_game.currency = currency
casino_game.wager = wager
casino_game.winnings = 0
casino_game.kind = 'blackjack'
casino_game.game_state = json.dumps(initial_state)
casino_game.active = True
g.db.add(casino_game)
return casino_game
return casino_game
def get_active_twentyone_game(gambler):
return g.db.query(Casino_Game).filter(
Casino_Game.active == True,
Casino_Game.kind == 'blackjack',
Casino_Game.user_id == gambler.id).first()
return g.db.query(Casino_Game).filter(
Casino_Game.active == True,
Casino_Game.kind == 'blackjack',
Casino_Game.user_id == gambler.id).first()
def get_active_twentyone_game_state(gambler):
active_game = get_active_twentyone_game(gambler)
full_state = json.loads(active_game.game_state)
return remove_exploitable_information(full_state)
active_game = get_active_twentyone_game(gambler)
full_state = json.loads(active_game.game_state)
return remove_exploitable_information(full_state)
def charge_gambler(gambler, amount, currency):
charged = gambler.charge_account(currency, amount)
if not charged:
raise Exception("Gambler cannot afford charge.")
charged = gambler.charge_account(currency, amount)
if not charged:
raise Exception("Gambler cannot afford charge.")
def create_new_game(gambler, wager, currency):
existing_game = get_active_twentyone_game(gambler)
over_minimum_bet = wager >= minimum_bet
existing_game = get_active_twentyone_game(gambler)
over_minimum_bet = wager >= minimum_bet
if existing_game:
raise Exception("Gambler already has a game in progress.")
if existing_game:
raise Exception("Gambler already has a game in progress.")
if not over_minimum_bet:
raise Exception(f"Gambler must bet over {minimum_bet} {currency}.")
if not over_minimum_bet:
raise Exception(f"Gambler must bet over {minimum_bet} {currency}.")
try:
charge_gambler(gambler, wager, currency)
new_game = build_casino_game(gambler, wager, currency)
g.db.add(new_game)
g.db.commit()
except:
raise Exception(f"Gambler cannot afford to bet {wager} {currency}.")
try:
charge_gambler(gambler, wager, currency)
new_game = build_casino_game(gambler, wager, currency)
g.db.add(new_game)
g.db.commit()
except:
raise Exception(f"Gambler cannot afford to bet {wager} {currency}.")
def handle_blackjack_deal(state):
deck = build_deck(state)
first = deck.pop()
second = deck.pop()
third = deck.pop()
fourth = deck.pop()
state['player'] = [first, third]
state['dealer'] = [second, fourth]
deck = build_deck(state)
first = deck.pop()
second = deck.pop()
third = deck.pop()
fourth = deck.pop()
state['player'] = [first, third]
state['dealer'] = [second, fourth]
return state
return state
def handle_blackjack_hit(state):
deck = build_deck(state)
next_card = deck.pop()
state['player'].append(next_card)
deck = build_deck(state)
next_card = deck.pop()
state['player'].append(next_card)
return state
return state
def handle_blackjack_stay(state):
state['status'] = BlackjackStatus.STAYED
state['status'] = BlackjackStatus.STAYED
return state
return state
def handle_blackjack_double_down(state):
state['player_doubled_down'] = True
state = handle_blackjack_hit(state)
state = handle_blackjack_stay(state)
state['player_doubled_down'] = True
state = handle_blackjack_hit(state)
state = handle_blackjack_stay(state)
return state
return state
def handle_blackjack_buy_insurance(state):
state['player_bought_insurance'] = True
state['player_bought_insurance'] = True
return state
return state
def check_for_completion(state):
after_initial_deal = len(
state['player']) == 2 and len(state['dealer']) == 2
player_hand_value = get_value_of_hand(state['player'])
dealer_hand_value = get_value_of_hand(state['dealer'])
after_initial_deal = len(
state['player']) == 2 and len(state['dealer']) == 2
player_hand_value = get_value_of_hand(state['player'])
dealer_hand_value = get_value_of_hand(state['dealer'])
# Both player and dealer were initially dealt 21: Push.
if after_initial_deal and player_hand_value == 21 and dealer_hand_value == 21:
state['status'] = BlackjackStatus.PUSHED
return True, state
# Both player and dealer were initially dealt 21: Push.
if after_initial_deal and player_hand_value == 21 and dealer_hand_value == 21:
state['status'] = BlackjackStatus.PUSHED
return True, state
# Player was originally dealt 21, dealer was not: Blackjack.
if after_initial_deal and player_hand_value == 21:
state['status'] = BlackjackStatus.BLACKJACK
return True, state
# Player was originally dealt 21, dealer was not: Blackjack.
if after_initial_deal and player_hand_value == 21:
state['status'] = BlackjackStatus.BLACKJACK
return True, state
# Player went bust: Lost.
if player_hand_value == -1:
state['status'] = BlackjackStatus.LOST
return True, state
# Player went bust: Lost.
if player_hand_value == -1:
state['status'] = BlackjackStatus.LOST
return True, state
# Player chose to stay: Deal rest for dealer then determine winner.
if state['status'] == BlackjackStatus.STAYED:
deck = build_deck(state)
# Player chose to stay: Deal rest for dealer then determine winner.
if state['status'] == BlackjackStatus.STAYED:
deck = build_deck(state)
while dealer_hand_value < 17 and dealer_hand_value != -1:
next_card = deck.pop()
state['dealer'].append(next_card)
dealer_hand_value = get_value_of_hand(state['dealer'])
while dealer_hand_value < 17 and dealer_hand_value != -1:
next_card = deck.pop()
state['dealer'].append(next_card)
dealer_hand_value = get_value_of_hand(state['dealer'])
if player_hand_value > dealer_hand_value or dealer_hand_value == -1:
state['status'] = BlackjackStatus.WON
elif dealer_hand_value > player_hand_value:
state['status'] = BlackjackStatus.LOST
else:
state['status'] = BlackjackStatus.PUSHED
if player_hand_value > dealer_hand_value or dealer_hand_value == -1:
state['status'] = BlackjackStatus.WON
elif dealer_hand_value > player_hand_value:
state['status'] = BlackjackStatus.LOST
else:
state['status'] = BlackjackStatus.PUSHED
state['player_value'] = get_value_of_hand(state['player'])
state['dealer_value'] = get_value_of_hand(state['dealer'])
state['player_value'] = get_value_of_hand(state['player'])
state['dealer_value'] = get_value_of_hand(state['dealer'])
return True, state
return True, state
return False, state
return False, state
def does_insurance_apply(state):
dealer = state['dealer']
dealer_hand_value = get_value_of_hand(dealer)
dealer_first_card_ace = dealer[0][0] == 'A'
dealer_never_hit = len(dealer) == 2
return dealer_hand_value == 21 and dealer_first_card_ace and dealer_never_hit
dealer = state['dealer']
dealer_hand_value = get_value_of_hand(dealer)
dealer_first_card_ace = dealer[0][0] == 'A'
dealer_never_hit = len(dealer) == 2
return dealer_hand_value == 21 and dealer_first_card_ace and dealer_never_hit
def can_purchase_insurance(state):
dealer = state['dealer']
dealer_first_card_ace = dealer[0][0] == 'A'
dealer_never_hit = len(dealer) == 2
return dealer_first_card_ace and dealer_never_hit and not state['player_bought_insurance']
dealer = state['dealer']
dealer_first_card_ace = dealer[0][0] == 'A'
dealer_never_hit = len(dealer) == 2
return dealer_first_card_ace and dealer_never_hit and not state['player_bought_insurance']
def can_double_down(state):
player = state['player']
player_hand_value = get_value_of_hand(player)
player_never_hit = len(player) == 2
return player_hand_value in (10, 11) and player_never_hit
player = state['player']
player_hand_value = get_value_of_hand(player)
player_never_hit = len(player) == 2
return player_hand_value in (10, 11) and player_never_hit
def handle_payout(gambler, state, game):
status = state['status']
payout = 0
status = state['status']
payout = 0
if status == BlackjackStatus.BLACKJACK:
game.winnings = floor(game.wager * 3/2)
payout = game.wager + game.winnings
elif status == BlackjackStatus.WON:
game.winnings = game.wager
payout = game.wager * 2
elif status == BlackjackStatus.LOST:
dealer = state['dealer']
dealer_first_card_ace = dealer[0][0] == 'A'
dealer_never_hit = len(dealer) == 2
dealer_hand_value = get_value_of_hand(dealer) == 21
insurance_applies = dealer_hand_value == 21 and dealer_first_card_ace and dealer_never_hit
if status == BlackjackStatus.BLACKJACK:
game.winnings = floor(game.wager * 3/2)
payout = game.wager + game.winnings
elif status == BlackjackStatus.WON:
game.winnings = game.wager
payout = game.wager * 2
elif status == BlackjackStatus.LOST:
dealer = state['dealer']
dealer_first_card_ace = dealer[0][0] == 'A'
dealer_never_hit = len(dealer) == 2
dealer_hand_value = get_value_of_hand(dealer) == 21
insurance_applies = dealer_hand_value == 21 and dealer_first_card_ace and dealer_never_hit
if insurance_applies and state['player_bought_insurance']:
game.winnings = 0
payout = game.wager
else:
game.winnings = -game.wager
payout = 0
elif status == BlackjackStatus.PUSHED:
game.winnings = 0
payout = game.wager
else:
raise Exception("Attempted to payout a game that has not finished.")
if insurance_applies and state['player_bought_insurance']:
game.winnings = 0
payout = game.wager
else:
game.winnings = -game.wager
payout = 0
elif status == BlackjackStatus.PUSHED:
game.winnings = 0
payout = game.wager
else:
raise Exception("Attempted to payout a game that has not finished.")
gambler.pay_account(game.currency, payout)
if game.currency == 'coins':
if status in (BlackjackStatus.BLACKJACK, BlackjackStatus.WON):
distribute_wager_badges(gambler, game.wager, won=True)
elif status == BlackjackStatus.LOST:
distribute_wager_badges(gambler, game.wager, won=False)
gambler.pay_account(game.currency, payout)
if game.currency == 'coins':
if status in (BlackjackStatus.BLACKJACK, BlackjackStatus.WON):
distribute_wager_badges(gambler, game.wager, won=True)
elif status == BlackjackStatus.LOST:
distribute_wager_badges(gambler, game.wager, won=False)
game.active = False
g.db.add(game)
game.active = False
g.db.add(game)
return payout
return payout
def remove_exploitable_information(state):
safe_state = state
if len(safe_state['dealer']) >= 2:
safe_state['dealer'][1] = '?'
safe_state = state
if len(safe_state['dealer']) >= 2:
safe_state['dealer'][1] = '?'
safe_state['dealer_value'] = '?'
return safe_state
safe_state['dealer_value'] = '?'
return safe_state
action_handlers = {
BlackjackAction.DEAL: handle_blackjack_deal,
BlackjackAction.HIT: handle_blackjack_hit,
BlackjackAction.STAY: handle_blackjack_stay,
BlackjackAction.DOUBLE_DOWN: handle_blackjack_double_down,
BlackjackAction.BUY_INSURANCE: handle_blackjack_buy_insurance,
BlackjackAction.DEAL: handle_blackjack_deal,
BlackjackAction.HIT: handle_blackjack_hit,
BlackjackAction.STAY: handle_blackjack_stay,
BlackjackAction.DOUBLE_DOWN: handle_blackjack_double_down,
BlackjackAction.BUY_INSURANCE: handle_blackjack_buy_insurance,
}
def dispatch_action(gambler, action):
game = get_active_twentyone_game(gambler)
handler = action_handlers[action]
game = get_active_twentyone_game(gambler)
handler = action_handlers[action]
if not game:
raise Exception(
'Gambler has no active blackjack game.')
if not handler:
raise Exception(
f'Illegal action {action} passed to Blackjack#dispatch_action.')
if not game:
raise Exception(
'Gambler has no active blackjack game.')
if not handler:
raise Exception(
f'Illegal action {action} passed to Blackjack#dispatch_action.')
state = json.loads(game.game_state)
state = json.loads(game.game_state)
if action == BlackjackAction.BUY_INSURANCE:
if not can_purchase_insurance(state):
raise Exception("Insurance cannot be purchased.")
if action == BlackjackAction.BUY_INSURANCE:
if not can_purchase_insurance(state):
raise Exception("Insurance cannot be purchased.")
charge_gambler(gambler, floor(game.wager / 2), game.currency)
if action == BlackjackAction.DOUBLE_DOWN:
if not can_double_down(state):
raise Exception("Cannot double down.")
charge_gambler(gambler, floor(game.wager / 2), game.currency)
if action == BlackjackAction.DOUBLE_DOWN:
if not can_double_down(state):
raise Exception("Cannot double down.")
charge_gambler(gambler, game.wager, game.currency)
game.wager *= 2
charge_gambler(gambler, game.wager, game.currency)
game.wager *= 2
new_state = handler(state)
new_state['player_value'] = get_value_of_hand(new_state['player'])
new_state['dealer_value'] = get_value_of_hand(new_state['dealer'])
new_state['actions'] = get_available_actions(new_state)
new_state = handler(state)
new_state['player_value'] = get_value_of_hand(new_state['player'])
new_state['dealer_value'] = get_value_of_hand(new_state['dealer'])
new_state['actions'] = get_available_actions(new_state)
game.game_state = json.dumps(new_state)
g.db.add(game)
game.game_state = json.dumps(new_state)
g.db.add(game)
game_over, final_state = check_for_completion(new_state)
game_over, final_state = check_for_completion(new_state)
if game_over:
payout = handle_payout(gambler, final_state, game)
final_state['actions'] = [BlackjackAction.DEAL]
final_state['payout'] = payout
return final_state
else:
safe_state = remove_exploitable_information(new_state)
return safe_state
if game_over:
payout = handle_payout(gambler, final_state, game)
final_state['actions'] = [BlackjackAction.DEAL]
final_state['payout'] = payout
return final_state
else:
safe_state = remove_exploitable_information(new_state)
return safe_state
def shuffle(collection):
random.shuffle(collection)
return collection
random.shuffle(collection)
return collection
def build_deck(state):
card_counts = {}
card_counts = {}
for card in deck:
card_counts[card] = deck_count
for card in deck:
card_counts[card] = deck_count
cards_already_dealt = state['player'].copy()
cards_already_dealt.extend(state['dealer'].copy())
cards_already_dealt = state['player'].copy()
cards_already_dealt.extend(state['dealer'].copy())
for card in cards_already_dealt:
card_counts[card] = card_counts[card] - 1
for card in cards_already_dealt:
card_counts[card] = card_counts[card] - 1
deck_without_already_dealt_cards = []
deck_without_already_dealt_cards = []
for card in deck:
amount = card_counts[card]
for card in deck:
amount = card_counts[card]
for _ in range(amount):
deck_without_already_dealt_cards.append(card)
for _ in range(amount):
deck_without_already_dealt_cards.append(card)
return shuffle(deck_without_already_dealt_cards)
return shuffle(deck_without_already_dealt_cards)
def get_value_of_card(card):
rank = card[0]
return 0 if rank == "A" else min(ranks.index(rank) + 2, 10)
rank = card[0]
return 0 if rank == "A" else min(ranks.index(rank) + 2, 10)
def get_value_of_hand(hand):
without_aces = sum(map(get_value_of_card, hand))
ace_count = sum("A" in c for c in hand)
possibilities = []
without_aces = sum(map(get_value_of_card, hand))
ace_count = sum("A" in c for c in hand)
possibilities = []
for i in range(ace_count + 1):
value = without_aces + (ace_count - i) + i * 11
possibilities.append(-1 if value > 21 else value)
for i in range(ace_count + 1):
value = without_aces + (ace_count - i) + i * 11
possibilities.append(-1 if value > 21 else value)
return max(possibilities)
return max(possibilities)
def get_available_actions(state):
actions = []
actions = []
if state['status'] == BlackjackStatus.PLAYING:
actions.append(BlackjackAction.HIT)
actions.append(BlackjackAction.STAY)
if state['status'] == BlackjackStatus.PLAYING:
actions.append(BlackjackAction.HIT)
actions.append(BlackjackAction.STAY)
if can_double_down(state):
actions.append(BlackjackAction.DOUBLE_DOWN)
if can_double_down(state):
actions.append(BlackjackAction.DOUBLE_DOWN)
if can_purchase_insurance(state):
actions.append(BlackjackAction.BUY_INSURANCE)
if can_purchase_insurance(state):
actions.append(BlackjackAction.BUY_INSURANCE)
return actions
return actions

View File

@ -16,10 +16,10 @@ from files.helpers.lottery import *
@auth_required
@feature_required('GAMBLING')
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("/casino/<game>")
@ -27,27 +27,27 @@ def casino(v):
@auth_required
@feature_required('GAMBLING')
def casino_game_page(v, game):
if v.rehab:
return render_template("casino/rehab.html", v=v)
elif game not in CASINO_GAME_KINDS:
abort(404)
if v.rehab:
return render_template("casino/rehab.html", v=v)
elif game not in CASINO_GAME_KINDS:
abort(404)
feed = json.dumps(get_game_feed(game))
leaderboard = json.dumps(get_game_leaderboard(game))
feed = json.dumps(get_game_feed(game))
leaderboard = json.dumps(get_game_leaderboard(game))
game_state = ''
if game == 'blackjack':
if get_active_twentyone_game(v):
game_state = json.dumps(get_active_twentyone_game_state(v))
game_state = ''
if game == 'blackjack':
if get_active_twentyone_game(v):
game_state = json.dumps(get_active_twentyone_game_state(v))
return render_template(
f"casino/{game}_screen.html",
v=v,
game=game,
feed=feed,
leaderboard=leaderboard,
game_state=game_state
)
return render_template(
f"casino/{game}_screen.html",
v=v,
game=game,
feed=feed,
leaderboard=leaderboard,
game_state=game_state
)
@app.get("/casino/<game>/feed")
@ -55,13 +55,13 @@ def casino_game_page(v, game):
@auth_required
@feature_required('GAMBLING')
def casino_game_feed(v, game):
if v.rehab:
abort(403, "You are under Rehab award effect!")
elif game not in CASINO_GAME_KINDS:
abort(404)
if v.rehab:
abort(403, "You are under Rehab award effect!")
elif game not in CASINO_GAME_KINDS:
abort(404)
feed = get_game_feed(game)
return {"feed": feed}
feed = get_game_feed(game)
return {"feed": feed}
# Lottershe
@ -70,11 +70,11 @@ def casino_game_feed(v, game):
@auth_required
@feature_required('GAMBLING')
def lottershe(v):
if v.rehab:
return render_template("casino/rehab.html", v=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)
participants = get_users_participating_in_lottery()
return render_template("lottery.html", v=v, participants=participants)
# Slots
@app.post("/casino/slots")
@ -82,28 +82,28 @@ def lottershe(v):
@auth_required
@feature_required('GAMBLING')
def pull_slots(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
try:
wager = int(request.values.get("wager"))
except:
abort(400, "Invalid wager.")
try:
wager = int(request.values.get("wager"))
except:
abort(400, "Invalid wager.")
try:
currency = request.values.get("currency")
except:
abort(400, "Invalid currency (expected 'coin' or 'marseybux').")
try:
currency = request.values.get("currency")
except:
abort(400, "Invalid currency (expected 'coin' or 'marseybux').")
if (currency == "coin" and wager > v.coins) or (currency == "marseybux" and wager > v.procoins):
abort(400, f"Not enough {currency} to make that bet")
if (currency == "coin" and wager > v.coins) or (currency == "marseybux" and wager > v.procoins):
abort(400, f"Not enough {currency} to make that bet")
success, game_state = casino_slot_pull(v, wager, currency)
success, game_state = casino_slot_pull(v, wager, currency)
if success:
return {"game_state": game_state, "gambler": {"coins": v.coins, "procoins": v.procoins}}
else:
abort(400, f"Wager must be more than 5 {currency}")
if success:
return {"game_state": game_state, "gambler": {"coins": v.coins, "procoins": v.procoins}}
else:
abort(400, f"Wager must be more than 5 {currency}")
# 21
@ -112,19 +112,19 @@ def pull_slots(v):
@auth_required
@feature_required('GAMBLING')
def blackjack_deal_to_player(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
try:
wager = int(request.values.get("wager"))
currency = request.values.get("currency")
create_new_game(v, wager, currency)
state = dispatch_action(v, BlackjackAction.DEAL)
feed = get_game_feed('blackjack')
try:
wager = int(request.values.get("wager"))
currency = request.values.get("currency")
create_new_game(v, wager, currency)
state = dispatch_action(v, BlackjackAction.DEAL)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except Exception as e:
abort(400, str(e))
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except Exception as e:
abort(400, str(e))
@app.post("/casino/twentyone/hit")
@ -132,15 +132,15 @@ def blackjack_deal_to_player(v):
@auth_required
@feature_required('GAMBLING')
def blackjack_player_hit(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
try:
state = dispatch_action(v, BlackjackAction.HIT)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to hit.")
try:
state = dispatch_action(v, BlackjackAction.HIT)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to hit.")
@app.post("/casino/twentyone/stay")
@ -148,15 +148,15 @@ def blackjack_player_hit(v):
@auth_required
@feature_required('GAMBLING')
def blackjack_player_stay(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
try:
state = dispatch_action(v, BlackjackAction.STAY)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to stay.")
try:
state = dispatch_action(v, BlackjackAction.STAY)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to stay.")
@app.post("/casino/twentyone/double-down")
@ -164,15 +164,15 @@ def blackjack_player_stay(v):
@auth_required
@feature_required('GAMBLING')
def blackjack_player_doubled_down(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
try:
state = dispatch_action(v, BlackjackAction.DOUBLE_DOWN)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to double down.")
try:
state = dispatch_action(v, BlackjackAction.DOUBLE_DOWN)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to double down.")
@app.post("/casino/twentyone/buy-insurance")
@ -180,15 +180,15 @@ def blackjack_player_doubled_down(v):
@auth_required
@feature_required('GAMBLING')
def blackjack_player_bought_insurance(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
try:
state = dispatch_action(v, BlackjackAction.BUY_INSURANCE)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(403, "Unable to buy insurance.")
try:
state = dispatch_action(v, BlackjackAction.BUY_INSURANCE)
feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(403, "Unable to buy insurance.")
# Roulette
@app.get("/casino/roulette/bets")
@ -196,12 +196,12 @@ def blackjack_player_bought_insurance(v):
@auth_required
@feature_required('GAMBLING')
def roulette_get_bets(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
bets = get_roulette_bets()
bets = get_roulette_bets()
return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}}
return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}}
@app.post("/casino/roulette/place-bet")
@ -209,22 +209,22 @@ def roulette_get_bets(v):
@auth_required
@feature_required('GAMBLING')
def roulette_player_placed_bet(v):
if v.rehab:
abort(403, "You are under Rehab award effect!")
if v.rehab:
abort(403, "You are under Rehab award effect!")
try:
bet = request.values.get("bet")
which = request.values.get("which")
amount = int(request.values.get("wager"))
currency = request.values.get("currency")
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:
abort(400, f"Minimum bet is 5 {currency}.")
if amount < 5:
abort(400, f"Minimum bet is 5 {currency}.")
gambler_placed_roulette_bet(v, bet, which, amount, currency)
gambler_placed_roulette_bet(v, bet, which, amount, currency)
bets = get_roulette_bets()
bets = get_roulette_bets()
return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to place a bet.")
return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except:
abort(400, "Unable to place a bet.")

View File

@ -2,218 +2,218 @@
{% block script %}
<script>
function makeBlackjackRequest(action) {
const xhr = new XMLHttpRequest();
xhr.open("post", `/casino/twentyone/${action}`);
xhr.onload = handleBlackjackResponse.bind(null, xhr);
xhr.blackjackAction = action;
return xhr;
}
function makeBlackjackRequest(action) {
const xhr = new XMLHttpRequest();
xhr.open("post", `/casino/twentyone/${action}`);
xhr.onload = handleBlackjackResponse.bind(null, xhr);
xhr.blackjackAction = action;
return xhr;
}
function handleBlackjackResponse(xhr) {
try {
const response = JSON.parse(xhr.response);
const succeeded = xhr.status >= 200 &&
xhr.status < 300 &&
response &&
!response.error;
function handleBlackjackResponse(xhr) {
try {
const response = JSON.parse(xhr.response);
const succeeded = xhr.status >= 200 &&
xhr.status < 300 &&
response &&
!response.error;
clearResult();
clearResult();
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."
};
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."
};
updateResult(results[xhr.blackjackAction], "danger");
}
}
updateResult(results[xhr.blackjackAction], "danger");
}
}
function updateBlackjackActions(state) {
const actions = Array.from(document.querySelectorAll('.twentyone-btn'));
function updateBlackjackActions(state) {
const actions = Array.from(document.querySelectorAll('.twentyone-btn'));
// Hide all actions.
actions.forEach(action => action.style.display = 'none');
// 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`);
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`);
})
setTimeout(() => {
const dealButton = document.getElementById(`twentyone-DEAL`);
})
if (dealButton) {
dealButton.style.display = 'inline-block'
}
}
}
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);
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);
updateBlackjackActions(state);
table.innerHTML = `
<div style="position: relative;">
${dealerCards}
</div>
${playerCards}
`;
table.innerHTML = `
<div style="position: relative;">
${dealerCards}
</div>
${playerCards}
`;
const currency = state.wager.currency === 'coins' ? 'coins' : 'marseybux';
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;
}
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);
updateCardsetBackgrounds(state);
if (state.status === 'PLAYING') {
updateResult(`${state.wager.amount} ${currency} are at stake`, "success");
} else {
enableWager();
}
}
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'));
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}`)
}
}
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();
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);
form.append("formkey", formkey());
form.append("wager", amount);
form.append("currency", currency);
request.send(form);
request.send(form);
clearResult();
disableWager();
drawFromDeck();
}
clearResult();
disableWager();
drawFromDeck();
}
function hit() {
const request = makeBlackjackRequest('hit');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
function hit() {
const request = makeBlackjackRequest('hit');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
drawFromDeck();
}
drawFromDeck();
}
function stay() {
const request = makeBlackjackRequest('stay');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
}
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);
function doubleDown() {
const request = makeBlackjackRequest('double-down');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
drawFromDeck();
}
drawFromDeck();
}
function buyInsurance() {
const request = makeBlackjackRequest('buy-insurance');
const form = new FormData();
form.append("formkey", formkey());
request.send(form);
}
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 buildBlackjackDeck() {
document.getElementById('blackjack-table-deck').innerHTML = `
<div style="position: absolute; top: 150px; left: -100px;">
${buildPlayingCardDeck()}
</div>
`;
}
function initializeBlackjack() {
buildBlackjackDeck();
function initializeBlackjack() {
buildBlackjackDeck();
try {
const passed = document.getElementById('blackjack-table').dataset.state;
const state = JSON.parse(passed);
updateBlackjackTable(state);
} catch (error) {
updateBlackjackActions();
}
}
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("DOMContentLoaded", initializeBlackjack);
}
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeBlackjack();
} else {
document.addEventListener("DOMContentLoaded", initializeBlackjack);
}
</script>
{% endblock %}
@ -225,74 +225,74 @@
{% block actions %}
<style>
.blackjack-cardset {
position: relative;
display: flex;
align-items: center;
margin-bottom: 1rem;
max-width: 470px;
overflow: auto;
box-shadow: 1px 1px 5px 1px rgba(60, 60, 60, 0.81) inset;
-webkit-box-shadow: 1px 1px 5px 1px rgba(60, 60, 60, 0.81) inset;
-moz-box-shadow: 1px 1px 5px 1px rgba(60, 60, 60, 0.81) inset;
}
.blackjack-cardset {
position: relative;
display: flex;
align-items: center;
margin-bottom: 1rem;
max-width: 470px;
overflow: auto;
box-shadow: 1px 1px 5px 1px rgba(60, 60, 60, 0.81) inset;
-webkit-box-shadow: 1px 1px 5px 1px rgba(60, 60, 60, 0.81) inset;
-moz-box-shadow: 1px 1px 5px 1px rgba(60, 60, 60, 0.81) inset;
}
.blackjack-cardset__PLAYING {
background-image: radial-gradient(circle farthest-corner at 10% 20%, rgba(14, 174, 87, 1) 0%, rgba(12, 116, 117, 1) 90%);
}
.blackjack-cardset__PLAYING {
background-image: radial-gradient(circle farthest-corner at 10% 20%, rgba(14, 174, 87, 1) 0%, rgba(12, 116, 117, 1) 90%);
}
.blackjack-cardset__LOST {
background-image: linear-gradient(109.6deg, rgba(14, 11, 56, 1) 11.2%, rgba(239, 37, 37, 1) 91.1%);
}
.blackjack-cardset__LOST {
background-image: linear-gradient(109.6deg, rgba(14, 11, 56, 1) 11.2%, rgba(239, 37, 37, 1) 91.1%);
}
.blackjack-cardset__PUSHED {
background-image: linear-gradient(110.3deg, rgba(73, 93, 109, 1) 4.3%, rgba(49, 55, 82, 1) 96.7%);
}
.blackjack-cardset__PUSHED {
background-image: linear-gradient(110.3deg, rgba(73, 93, 109, 1) 4.3%, rgba(49, 55, 82, 1) 96.7%);
}
.blackjack-cardset__WON {
background-image: radial-gradient( circle farthest-corner at -0.6% 44.4%, rgba(142,252,152,1) 0%, rgba(107,214,250,1) 90% );
}
.blackjack-cardset__WON {
background-image: radial-gradient( circle farthest-corner at -0.6% 44.4%, rgba(142,252,152,1) 0%, rgba(107,214,250,1) 90% );
}
.blackjack-cardset__BLACKJACK {
background-image: linear-gradient(64.3deg, rgba(254, 122, 152, 0.81) 17.7%, rgba(255, 206, 134, 1) 64.7%, rgba(172, 253, 163, 0.64) 112.1%);
}
.blackjack-cardset__BLACKJACK {
background-image: linear-gradient(64.3deg, rgba(254, 122, 152, 0.81) 17.7%, rgba(255, 206, 134, 1) 64.7%, rgba(172, 253, 163, 0.64) 112.1%);
}
.blackjack-cardset .playing-card {
margin-right: -3rem;
min-width: 100px;
}
.blackjack-cardset .playing-card {
margin-right: -3rem;
min-width: 100px;
}
.blackjack-cardset-value {
z-index: 3;
top: 0;
right: 0;
text-transform: uppercase;
letter-spacing: 2px;
text-align: right;
position: absolute;
background-color: rgba(70, 70, 70, 0.6);
padding: 0.5rem;
color: #DDD;
}
.blackjack-cardset-value {
z-index: 3;
top: 0;
right: 0;
text-transform: uppercase;
letter-spacing: 2px;
text-align: right;
position: absolute;
background-color: rgba(70, 70, 70, 0.6);
padding: 0.5rem;
color: #DDD;
}
.twentyone-btn {
margin-right: 1rem;
margin-bottom: 1rem;
text-transform: uppercase;
letter-spacing: 2px;
}
.twentyone-btn {
margin-right: 1rem;
margin-bottom: 1rem;
text-transform: uppercase;
letter-spacing: 2px;
}
</style>
<div role="group" class="btn-group">
<button type="button" id="twentyone-DEAL" class="btn btn-primary twentyone-btn" onclick="deal()">Deal</button>
<button type="button" id="twentyone-HIT" class="btn btn-primary twentyone-btn" onclick="hit()" style="display: none;">Hit</button>
<button type="button" id="twentyone-STAY" class="btn btn-primary twentyone-btn" onclick="stay()"
style="display: none;">Stay</button>
<button type="button" id="twentyone-DOUBLE_DOWN" class="btn btn-primary twentyone-btn" onclick="doubleDown()"
style="display: none;">Double Down</button>
<button type="button" id="twentyone-BUY_INSURANCE" class="btn btn-primary twentyone-btn" onclick="buyInsurance()"
style="display: none;">Buy
Insurance</button>
<button type="button" id="twentyone-DEAL" class="btn btn-primary twentyone-btn" onclick="deal()">Deal</button>
<button type="button" id="twentyone-HIT" class="btn btn-primary twentyone-btn" onclick="hit()" style="display: none;">Hit</button>
<button type="button" id="twentyone-STAY" class="btn btn-primary twentyone-btn" onclick="stay()"
style="display: none;">Stay</button>
<button type="button" id="twentyone-DOUBLE_DOWN" class="btn btn-primary twentyone-btn" onclick="doubleDown()"
style="display: none;">Double Down</button>
<button type="button" id="twentyone-BUY_INSURANCE" class="btn btn-primary twentyone-btn" onclick="buyInsurance()"
style="display: none;">Buy
Insurance</button>
</div>
{% endblock %}

View File

@ -2,468 +2,468 @@
<title>{{game.capitalize()}}</title>
{% endblock %} {% block content %}
<style>
.game_screen-title {
display: flex;
align-items: center;
justify-content: center;
text-transform: uppercase;
opacity: 0.6;
}
.game_screen-title {
display: flex;
align-items: center;
justify-content: center;
text-transform: uppercase;
opacity: 0.6;
}
.game_screen-title hr {
flex: 1;
margin-left: 0.5rem;
}
.game_screen-title hr {
flex: 1;
margin-left: 0.5rem;
}
#casinoGameResult {
visibility: hidden;
margin-top: 1rem;
}
#casinoGameResult {
visibility: hidden;
margin-top: 1rem;
}
#casinoGameFeedList {
max-height: 110px;
overflow: auto;
list-style-type: none;
}
#casinoGameFeedList {
max-height: 110px;
overflow: auto;
list-style-type: none;
}
</style>
<script type="text/javascript">
/**
* This script block contains generic helper function usable across casino games:
* - Wagers
* - Feed
* - Leaderboard
*/
/**
* 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("DOMContentLoaded", initializeGame);
}
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initializeGame();
} else {
document.addEventListener("DOMContentLoaded", initializeGame);
}
function initializeGame() {
updateFeed();
updateLeaderboard();
}
function initializeGame() {
updateFeed();
updateLeaderboard();
}
function updatePlayerCurrencies(updated) {
if (updated.coins) {
document.getElementById("user-coins-amount").innerText = updated.coins;
}
function updatePlayerCurrencies(updated) {
if (updated.coins) {
document.getElementById("user-coins-amount").innerText = updated.coins;
}
if (updated.procoins) {
document.getElementById("user-bux-amount").innerText = updated.procoins;
}
}
if (updated.procoins) {
document.getElementById("user-bux-amount").innerText = updated.procoins;
}
}
function getWager() {
const amount = document.getElementById("wagerAmount").value;
const currency = document.querySelector(
'input[name="wagerCurrency"]:checked'
).value;
const genericCurrency = currency == 'marseybux' ? 'procoins' : 'coins';
function getWager() {
const amount = document.getElementById("wagerAmount").value;
const currency = document.querySelector(
'input[name="wagerCurrency"]:checked'
).value;
const genericCurrency = currency == 'marseybux' ? 'procoins' : 'coins';
return { amount, currency: genericCurrency, localCurrency: currency };
}
return { amount, currency: genericCurrency, localCurrency: currency };
}
function disableWager() {
document.getElementById("wagerAmount").disabled = true;
document.getElementById("wagerCoins").disabled = true;
document.getElementById("wagerProcoins").disabled = true;
}
function disableWager() {
document.getElementById("wagerAmount").disabled = true;
document.getElementById("wagerCoins").disabled = true;
document.getElementById("wagerProcoins").disabled = true;
}
function enableWager() {
document.getElementById("wagerAmount").disabled = false;
document.getElementById("wagerCoins").disabled = false;
document.getElementById("wagerProcoins").disabled = false;
}
function enableWager() {
document.getElementById("wagerAmount").disabled = false;
document.getElementById("wagerCoins").disabled = false;
document.getElementById("wagerProcoins").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 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 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;
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 = "";
}
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("");
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;
}
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.onload = handleFeedResponse.bind(null, xhr);
xhr.send();
}
function reloadFeed() {
const game = document.getElementById('casino-game-wrapper').dataset.game;
const xhr = new XMLHttpRequest();
xhr.open("get", `/casino/${game}/feed`);
xhr.onload = handleFeedResponse.bind(null, xhr);
xhr.send();
}
function handleFeedResponse(xhr) {
let response;
function handleFeedResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.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");
}
}
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', procoins: 'marseybux' })[currency];
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', procoins: '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>
`;
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>
`;
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>
`;
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>
`;
}
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 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 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 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');
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>
`;
}
return `
<div id="playingCardDeck" class="playing-card-deck">
${cards}
</div>
`;
}
function drawFromDeck() {
try {
const [topCard] = Array.from(document.querySelectorAll("#playingCardDeck > *")).reverse();
function drawFromDeck() {
try {
const [topCard] = Array.from(document.querySelectorAll("#playingCardDeck > *")).reverse();
topCard.classList.add('drawing-a-card');
topCard.classList.add('drawing-a-card');
setTimeout(() => {
topCard.classList.remove('drawing-a-card');
}, 600);
} catch { }
}
setTimeout(() => {
topCard.classList.remove('drawing-a-card');
}, 600);
} catch { }
}
</script>
{% block script %} {% endblock %}
<style>
@keyframes drawing {
from {
left: 0;
opacity: 1;
}
@keyframes drawing {
from {
left: 0;
opacity: 1;
}
to {
left: 100px;
opacity: 0;
}
}
to {
left: 100px;
opacity: 0;
}
}
.drawing-a-card {
animation: drawing 1s ease-in-out;
}
.drawing-a-card {
animation: drawing 1s ease-in-out;
}
.playing-card-deck {
position: relative;
z-index: 3;
box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-webkit-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-moz-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
}
.playing-card-deck {
position: relative;
z-index: 3;
box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-webkit-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-moz-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
}
.flipped-playing-card {
position: absolute;
width: 100px;
height: 150px;
border-radius: 4px;
border: 1px solid #21262C;
background-color: #FF66AC;
transform: scale(0.7);
}
.flipped-playing-card {
position: absolute;
width: 100px;
height: 150px;
border-radius: 4px;
border: 1px solid #21262C;
background-color: #FF66AC;
transform: scale(0.7);
}
.playing-card {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 150px;
border-radius: 4px;
border: 1px solid #21262C;
background-color: #FFF;
box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-webkit-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-moz-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
}
.playing-card {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 150px;
border-radius: 4px;
border: 1px solid #21262C;
background-color: #FFF;
box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-webkit-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
-moz-box-shadow: -5px 5px 5px 0px rgba(60, 60, 60, 0.56);
}
.playing-card_red {
color: #ff0000;
}
.playing-card_red {
color: #ff0000;
}
.playing-card_black {
color: #333;
}
.playing-card_black {
color: #333;
}
.playing-card_small {
font-size: 18px;
position: absolute;
}
.playing-card_small {
font-size: 18px;
position: absolute;
}
.playing-card_large {
font-size: 48px;
text-align: center;
}
.playing-card_large {
font-size: 48px;
text-align: center;
}
.playing-card_topright {
top: 6px;
right: 6px;
}
.playing-card_topright {
top: 6px;
right: 6px;
}
.playing-card_bottomleft {
bottom: 6px;
left: 6px;
transform: scaleX(-1) scaleY(-1);
}
.playing-card_bottomleft {
bottom: 6px;
left: 6px;
transform: scaleX(-1) scaleY(-1);
}
#casinoGameResult {
text-transform: uppercase;
text-align: center;
letter-spacing: 3px;
font-weight: 700;
}
#casinoGameResult {
text-transform: uppercase;
text-align: center;
letter-spacing: 3px;
font-weight: 700;
}
.casino-game-leaderboard {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
}
.casino-game-leaderboard {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
}
.casino-game-leaderboard-info {
text-align: right;
text-transform: uppercase;
letter-spacing: 2px;
}
.casino-game-leaderboard-info {
text-align: right;
text-transform: uppercase;
letter-spacing: 2px;
}
.leaderboard-marsey-trophy {
position: relative;
width: 100px;
height: 100px;
}
.leaderboard-marsey-trophy {
position: relative;
width: 100px;
height: 100px;
}
.leaderboard-marsey-trophy__marsey {
position: relative;
z-index: 1;
height: 100px;
}
.leaderboard-marsey-trophy__marsey {
position: relative;
z-index: 1;
height: 100px;
}
.leaderboard-marsey-trophy__trophy {
position: absolute;
right: 0;
bottom: 0;
z-index: 2;
font-size: 48px;
}
.leaderboard-marsey-trophy__trophy {
position: absolute;
right: 0;
bottom: 0;
z-index: 2;
font-size: 48px;
}
</style>
<div id="casino-game-wrapper" data-game="{{game}}" class="container-fluid" style="max-width: 500px">
<div class="row row-cols-1">
<div class="col game_screen-title">
<h3>{{game}}</h3>
<hr>
</div>
<div class="col">{% block screen %} {% endblock %}</div>
<div class="col">
<div id="casinoGameResult" class="alert" role="alert">
{% block result %} {% endblock %}
</div>
</div>
<div class="col">
<div class="row row-cols-2">
<div class="col">
<div class="game_screen-title">
<h5>Wager</h5>
<hr>
</div>
<input id="wagerAmount" type="number" min="5" step="1" value="5" class="form-control">
</div>
<div class="col">
<div class="game_screen-title">
<h5>Currency</h5>
<hr>
</div>
<div class="btn-group" role="group" aria-label="Select a currency.">
<input type="radio" class="btn-check" name="wagerCurrency" autocomplete="off" id="wagerCoins"
value="coin" checked>
<label for="wagerCoins" class="btn btn-primary">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin" width="32" data-bs-toggle="tooltip"
data-bs-placement="bottom" title="Coin" aria-label="Coin">
</label>
<input type="radio" class="btn-check ml-2" name="wagerCurrency" autocomplete="off" id="wagerProcoins"
value="marseybux">
<label for="wagerProcoins" class="btn btn-primary">
<img src="/i/marseybux.webp?v=2000" alt="marseybux" width="32" data-bs-toggle="tooltip"
data-bs-placement="bottom" title="Marseybux" aria-label="Marseybux">
</label>
</div>
</div>
</div>
</div>
<div class="col">
<div class="game_screen-title">
<h5>{% block actiontext %}Actions{% endblock %}</h5>
<hr>
</div>
{% block actions %} {% endblock %}
</div>
<div id="casinoGameFeed" data-feed="{{feed}}" class="col">
<div class="game_screen-title">
<h5>Feed</h5>
<hr>
</div>
<ul id="casinoGameFeedList"></ul>
<button type="button" class="btn btn-secondary" style="width: 100%" onclick="reloadFeed()">
Reload Feed
</button>
</div>
<div class="col">
<div class="game_screen-title">
<h5>Leaders</h5>
<hr>
</div>
<div id="gameLeaderboard" data-leaderboard="{{leaderboard}}">
<!-- Biggest Winner All Time -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseyhappytears.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: gold;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Winner (All Time)</small>
<h3 id="biggestWinnerAllTime">-</h3>
</div>
</div>
<!-- Biggest Winner 24h -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseyexcited.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: gold;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Winner (Last 24h)</small>
<h3 id="biggestWinner24h">-</h3>
</div>
</div>
<!-- Biggest Loser 24h -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseycry.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: darkred;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Loser (Last 24h)</small>
<h3 id="biggestLoser24h">-</h3>
</div>
</div>
<!-- Biggest Loser All Time -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseyrain.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: darkred;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Loser (All Time)</small>
<h3 id="biggestLoserAllTime">-</h3>
</div>
</div>
</div>
</div>
</div>
<div class="row row-cols-1">
<div class="col game_screen-title">
<h3>{{game}}</h3>
<hr>
</div>
<div class="col">{% block screen %} {% endblock %}</div>
<div class="col">
<div id="casinoGameResult" class="alert" role="alert">
{% block result %} {% endblock %}
</div>
</div>
<div class="col">
<div class="row row-cols-2">
<div class="col">
<div class="game_screen-title">
<h5>Wager</h5>
<hr>
</div>
<input id="wagerAmount" type="number" min="5" step="1" value="5" class="form-control">
</div>
<div class="col">
<div class="game_screen-title">
<h5>Currency</h5>
<hr>
</div>
<div class="btn-group" role="group" aria-label="Select a currency.">
<input type="radio" class="btn-check" name="wagerCurrency" autocomplete="off" id="wagerCoins"
value="coin" checked>
<label for="wagerCoins" class="btn btn-primary">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin" width="32" data-bs-toggle="tooltip"
data-bs-placement="bottom" title="Coin" aria-label="Coin">
</label>
<input type="radio" class="btn-check ml-2" name="wagerCurrency" autocomplete="off" id="wagerProcoins"
value="marseybux">
<label for="wagerProcoins" class="btn btn-primary">
<img src="/i/marseybux.webp?v=2000" alt="marseybux" width="32" data-bs-toggle="tooltip"
data-bs-placement="bottom" title="Marseybux" aria-label="Marseybux">
</label>
</div>
</div>
</div>
</div>
<div class="col">
<div class="game_screen-title">
<h5>{% block actiontext %}Actions{% endblock %}</h5>
<hr>
</div>
{% block actions %} {% endblock %}
</div>
<div id="casinoGameFeed" data-feed="{{feed}}" class="col">
<div class="game_screen-title">
<h5>Feed</h5>
<hr>
</div>
<ul id="casinoGameFeedList"></ul>
<button type="button" class="btn btn-secondary" style="width: 100%" onclick="reloadFeed()">
Reload Feed
</button>
</div>
<div class="col">
<div class="game_screen-title">
<h5>Leaders</h5>
<hr>
</div>
<div id="gameLeaderboard" data-leaderboard="{{leaderboard}}">
<!-- Biggest Winner All Time -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseyhappytears.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: gold;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Winner (All Time)</small>
<h3 id="biggestWinnerAllTime">-</h3>
</div>
</div>
<!-- Biggest Winner 24h -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseyexcited.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: gold;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Winner (Last 24h)</small>
<h3 id="biggestWinner24h">-</h3>
</div>
</div>
<!-- Biggest Loser 24h -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseycry.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: darkred;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Loser (Last 24h)</small>
<h3 id="biggestLoser24h">-</h3>
</div>
</div>
<!-- Biggest Loser All Time -->
<div class="casino-game-leaderboard">
<div class="leaderboard-marsey-trophy">
<img class="leaderboard-marsey-trophy__marsey" src="/e/marseyrain.webp">
<i class="fas fa-trophy leaderboard-marsey-trophy__trophy" style="color: darkred;"></i>
</div>
<div class="casino-game-leaderboard-info">
<small>Biggest Loser (All Time)</small>
<h3 id="biggestLoserAllTime">-</h3>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,11 +1,11 @@
{% extends "default.html" %} {% block content %}
<div style="text-transform: uppercase; letter-spacing: 2px; display: flex; flex-direction: column; align-items: center;">
<div style="margin-top: 3rem;">
<h2>No one was there for Britney…</h2>
</div>
<div style="text-align: right; margin-bottom: 3rem;">
<h2>…but were here for you. Youve been checked into Rehab.</h2>
</div>
<img src="/i/rDrama/brit.webp" style="text-align: center">
<div style="margin-top: 3rem;">
<h2>No one was there for Britney…</h2>
</div>
<div style="text-align: right; margin-bottom: 3rem;">
<h2>…but were here for you. Youve been checked into Rehab.</h2>
</div>
<img src="/i/rDrama/brit.webp" style="text-align: center">
</div>
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@ -2,124 +2,124 @@
{% block script %}
<script type="text/javascript">
function pullSlots() {
const { amount, currency } = getWager();
function pullSlots() {
const { amount, currency } = getWager();
console.log({amount, currency})
console.log({amount, currency})
disableWager();
clearResult();
document.getElementById("casinoSlotsPull").disabled = true;
disableWager();
clearResult();
document.getElementById("casinoSlotsPull").disabled = true;
const xhr = new XMLHttpRequest();
xhr.open("post", "/casino/slots");
xhr.onload = handleSlotsResponse.bind(null, xhr);
const xhr = new XMLHttpRequest();
xhr.open("post", "/casino/slots");
xhr.onload = handleSlotsResponse.bind(null, xhr);
const form = new FormData();
form.append("formkey", formkey());
form.append("wager", amount);
form.append("currency", currency);
const form = new FormData();
form.append("formkey", formkey());
form.append("wager", amount);
form.append("currency", currency);
xhr.send(form);
}
xhr.send(form);
}
function handleSlotsResponse(xhr) {
let response;
function handleSlotsResponse(xhr) {
let response;
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
try {
response = JSON.parse(xhr.response);
} catch (error) {
console.error(error);
}
const succeeded =
xhr.status >= 200 && xhr.status < 300 && response && !response.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(",");
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];
}
for (let i = 0; i < 3; i++) {
reels[i].innerHTML = symbols[i];
}
let className;
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";
}
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);
}
updateResult(state.text, className);
updatePlayerCurrencies(gambler);
reloadFeed()
} else {
updateResult(response.error, "danger");
console.error(response.error);
}
enableWager();
document.getElementById("casinoSlotsPull").disabled = false;
}
enableWager();
document.getElementById("casinoSlotsPull").disabled = false;
}
</script>
{% endblock %}
{% block screen %}
<style>
.slots_reels {
display: flex;
align-items: center;
justify-content: center;
}
.slots_reels {
display: flex;
align-items: center;
justify-content: center;
}
.slots_reel {
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
border: 2px solid black;
background-color: var(--gray);
border: 1px solid var(--black);
border-radius: 8px;
font-size: 64px;
}
.slots_reel {
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
border: 2px solid black;
background-color: var(--gray);
border: 1px solid var(--black);
border-radius: 8px;
font-size: 64px;
}
.slots_reel:nth-child(2) {
margin: 0 1rem;
}
.slots_reel:nth-child(2) {
margin: 0 1rem;
}
</style>
<div class="slots_reels">
<div class="slots_reel">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin">
</div>
<div class="slots_reel">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin">
</div>
<div class="slots_reel">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin">
</div>
<div class="slots_reel">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin">
</div>
<div class="slots_reel">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin">
</div>
<div class="slots_reel">
<img src="/i/rDrama/coins.webp?v=3009" alt="coin">
</div>
</div>
{% endblock %}
{% block actions %}
<div class="btn-group" role="group">
<button
type="button"
id="casinoSlotsPull"
class="btn btn-primary"
style="width: 100%"
onclick="pullSlots()"
>
Pull
</button>
<button
type="button"
id="casinoSlotsPull"
class="btn btn-primary"
style="width: 100%"
onclick="pullSlots()"
>
Pull
</button>
</div>
{% endblock %}