use tabs, not spaces
parent
065a024639
commit
5719688178
|
@ -144,8 +144,8 @@ blockquote a {
|
|||
|
||||
.sidebar
|
||||
{
|
||||
border-radius: 6px;
|
||||
margin-top: 6px;
|
||||
border-radius: 6px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
h5.post-title a:visited {
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
.ricardo img {
|
||||
max-height: 15rem !important;
|
||||
max-height: min(30vw,15rem) !important;
|
||||
max-height: min(30vw,15rem) !important;
|
||||
}
|
||||
|
||||
.ricardoleft {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import 'classic.css?v=4031';
|
||||
|
||||
:root {
|
||||
--muted: #999;
|
||||
--black: #999;
|
||||
--bgc: #222;
|
||||
--muted: #999;
|
||||
--black: #999;
|
||||
--bgc: #222;
|
||||
}
|
||||
|
|
|
@ -96,8 +96,8 @@ blockquote {
|
|||
|
||||
.sidebar
|
||||
{
|
||||
border-radius: 6px;
|
||||
margin-top: 6px;
|
||||
border-radius: 6px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
h5.post-title a:visited {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ color: var(--gray-700);
|
|||
|
||||
.post-title
|
||||
{
|
||||
color: var(--gray-300) !important;
|
||||
color: var(--gray-300) !important;
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.mod:before {
|
||||
content: '(((';
|
||||
content: '(((';
|
||||
}
|
||||
|
||||
.mod:after {
|
||||
content: ')))';
|
||||
}
|
||||
content: ')))';
|
||||
}
|
||||
|
|
|
@ -221,8 +221,8 @@
|
|||
|
||||
.sidebar
|
||||
{
|
||||
border-radius: 6px;
|
||||
margin-top: 6px;
|
||||
border-radius: 6px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
|
|
|
@ -158,8 +158,8 @@ blockquote {
|
|||
|
||||
.sidebar
|
||||
{
|
||||
border-radius: 0px;
|
||||
margin-top: 6px;
|
||||
border-radius: 0px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
h5.post-title a:visited {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]>"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 []
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 we’re here for you. You’ve 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 we’re here for you. You’ve 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
|
@ -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 %}
|
||||
|
|
Loading…
Reference in New Issue