gtt / app.py
Starchik1's picture
Update app.py
1ced8fc verified
from flask import Flask, render_template_string, request, jsonify, session
import random
import time
from datetime import datetime
app = Flask(__name__)
app.secret_key = 'roulette_secret_key_2024'
class RouletteGame:
def __init__(self):
self.numbers = list(range(0, 37))
self.reds = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]
self.blacks = [2,4,6,8,10,11,13,15,17,20,22,24,26,28,29,31,33,35]
self.wheel_order = [0, 32, 15, 19, 4, 21, 2, 25, 17, 34, 6, 27, 13, 36, 11, 30, 8, 23,
10, 5, 24, 16, 33, 1, 20, 14, 31, 9, 22, 18, 29, 7, 28, 12, 35, 3, 26]
def spin(self):
return random.choice(self.numbers)
def check_win(self, number, bet_type, bet_value):
if bet_type == 'number':
return number == int(bet_value)
elif bet_type == 'color':
if bet_value == 'red':
return number in self.reds
elif bet_value == 'black':
return number in self.blacks
elif bet_type == 'even_odd':
if number == 0:
return False
if bet_value == 'even':
return number % 2 == 0
elif bet_value == 'odd':
return number % 2 == 1
elif bet_type == 'dozen':
if bet_value == 'first':
return 1 <= number <= 12
elif bet_value == 'second':
return 13 <= number <= 24
elif bet_value == 'third':
return 25 <= number <= 36
elif bet_type == 'column':
col = int(bet_value)
return number != 0 and (number % 3 == col)
elif bet_type == 'half':
if bet_value == '1-18':
return 1 <= number <= 18
elif bet_value == '19-36':
return 19 <= number <= 36
return False
def get_payout_multiplier(self, bet_type):
multipliers = {
'number': 35,
'color': 2,
'even_odd': 2,
'dozen': 3,
'column': 3,
'half': 2
}
return multipliers.get(bet_type, 1)
def init_session():
"""Инициализация сессии"""
if 'balance' not in session:
session['balance'] = 1000
session['history'] = []
session['total_games'] = 0
session['total_wins'] = 0
session.modified = True
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Казино Рулетка</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #0f4c75, #1b262c);
min-height: 100vh;
color: white;
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.header {
text-align: center;
margin-bottom: 30px;
background: rgba(0, 0, 0, 0.7);
padding: 20px;
border-radius: 15px;
border: 2px solid #ffd700;
}
.game-area {
display: grid;
grid-template-columns: 350px 1fr;
gap: 30px;
margin-bottom: 30px;
}
@media (max-width: 900px) {
.game-area {
grid-template-columns: 1fr;
}
}
.wheel-container {
background: rgba(0, 0, 0, 0.8);
padding: 20px;
border-radius: 15px;
border: 3px solid #ffd700;
text-align: center;
position: relative;
}
.wheel-wrapper {
position: relative;
width: 300px;
height: 300px;
margin: 0 auto;
}
.wheel {
position: relative;
width: 100%;
height: 100%;
background: #0a5c36;
border-radius: 50%;
border: 15px solid #8B4513;
overflow: hidden;
box-shadow:
0 0 30px rgba(255, 215, 0, 0.3),
inset 0 0 20px rgba(0, 0, 0, 0.5);
transition: transform 4s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.wheel-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: #ffd700;
border-radius: 50%;
border: 3px solid #8B4513;
z-index: 10;
box-shadow: 0 0 10px rgba(255, 215, 0, 0.8);
}
.wheel-number {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 14px;
color: white;
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
transform-origin: center;
left: 130px;
top: 20px;
border: 1px solid rgba(255,255,255,0.3);
box-shadow: inset 0 0 5px rgba(0,0,0,0.5);
}
.wheel-pointer {
position: absolute;
top: -10px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-top: 30px solid #ff4444;
z-index: 20;
filter: drop-shadow(0 0 5px rgba(255,0,0,0.7));
}
.ball {
position: absolute;
width: 20px;
height: 20px;
background: radial-gradient(circle at 5px 5px, #fff, #ccc, #666);
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 15;
box-shadow:
0 0 10px rgba(255, 255, 255, 0.8),
inset -2px -2px 5px rgba(0,0,0,0.5);
transition: all 0.1s ease;
}
.wheel-rim {
position: absolute;
top: -5px;
left: -5px;
right: -5px;
bottom: -5px;
border: 8px solid #daa520;
border-radius: 50%;
pointer-events: none;
}
.table-container {
background: rgba(0, 0, 0, 0.8);
padding: 20px;
border-radius: 15px;
border: 3px solid #ffd700;
}
.roulette-table {
display: grid;
grid-template-columns: 60px repeat(12, 1fr);
gap: 2px;
margin-bottom: 20px;
background: #0a5c36;
padding: 10px;
border-radius: 10px;
border: 2px solid #8B4513;
}
.table-cell {
padding: 12px 5px;
text-align: center;
background: #0a5c36;
border: 1px solid #daa520;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.table-cell::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.1) 50%, transparent 70%);
opacity: 0;
transition: opacity 0.3s;
}
.table-cell:hover::before {
opacity: 1;
}
.table-cell:hover {
transform: scale(1.05);
box-shadow: 0 0 15px gold;
z-index: 2;
}
.red {
background: linear-gradient(135deg, #d00, #f00, #d00);
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
}
.black {
background: linear-gradient(135deg, #111, #333, #111);
text-shadow: 1px 1px 2px rgba(255,255,255,0.3);
}
.green {
background: linear-gradient(135deg, #0a5c36, #0c7a4b, #0a5c36);
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
}
.bet-options {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
margin-bottom: 20px;
}
.bet-option {
padding: 15px;
text-align: center;
background: linear-gradient(135deg, #2d3748, #4a5568);
border: 2px solid #ffd700;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: bold;
position: relative;
overflow: hidden;
}
.bet-option::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s;
}
.bet-option:hover::before {
left: 100%;
}
.bet-option:hover {
background: linear-gradient(135deg, #4a5568, #2d3748);
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(255, 215, 0, 0.3);
}
.bet-option.active {
background: linear-gradient(135deg, #e53e3e, #c53030);
box-shadow: 0 0 20px #e53e3e;
animation: pulse-glow 1.5s infinite;
}
@keyframes pulse-glow {
0% { box-shadow: 0 0 15px #e53e3e; }
50% { box-shadow: 0 0 25px #e53e3e; }
100% { box-shadow: 0 0 15px #e53e3e; }
}
.controls {
display: flex;
gap: 15px;
align-items: center;
flex-wrap: wrap;
background: rgba(0, 0, 0, 0.7);
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
border: 2px solid #ffd700;
}
.balance-info {
font-size: 24px;
font-weight: bold;
color: #ffd700;
text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
}
input[type="number"] {
padding: 12px;
width: 120px;
border: 2px solid #ffd700;
border-radius: 5px;
background: #2d3748;
color: white;
font-size: 16px;
font-weight: bold;
}
button {
padding: 12px 25px;
background: linear-gradient(45deg, #ffd700, #ffed4e);
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
font-size: 16px;
color: #1b262c;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
transition: left 0.5s;
}
button:hover::before {
left: 100%;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(255, 215, 0, 0.6);
}
button:disabled {
background: #718096;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.result {
padding: 20px;
background: rgba(0, 0, 0, 0.8);
border-radius: 10px;
text-align: center;
font-size: 18px;
margin-bottom: 20px;
border: 2px solid;
transition: all 0.5s ease;
min-height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.win {
border-color: #48bb78;
background: rgba(72, 187, 120, 0.2);
animation: pulse-win 1s infinite;
}
.lose {
border-color: #e53e3e;
background: rgba(229, 62, 62, 0.2);
}
@keyframes pulse-win {
0% {
transform: scale(1);
box-shadow: 0 0 20px rgba(72, 187, 120, 0.5);
}
50% {
transform: scale(1.02);
box-shadow: 0 0 30px rgba(72, 187, 120, 0.8);
}
100% {
transform: scale(1);
box-shadow: 0 0 20px rgba(72, 187, 120, 0.5);
}
}
.history {
background: rgba(0, 0, 0, 0.8);
padding: 20px;
border-radius: 10px;
border: 2px solid #ffd700;
}
.history h3 {
margin-bottom: 15px;
color: #ffd700;
text-align: center;
}
.history-item {
padding: 10px;
border-bottom: 1px solid #4a5568;
display: flex;
justify-content: space-between;
transition: background 0.3s;
}
.history-item:hover {
background: rgba(255, 215, 0, 0.1);
}
.history-item:last-child {
border-bottom: none;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.stat-card {
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
text-align: center;
border: 1px solid #ffd700;
transition: transform 0.3s;
}
.stat-card:hover {
transform: translateY(-3px);
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #ffd700;
}
.winning-animation {
animation: win-spin 2s ease-out;
}
@keyframes win-spin {
0% { transform: rotate(0deg) scale(1); }
25% { transform: rotate(90deg) scale(1.1); }
50% { transform: rotate(180deg) scale(1.2); }
75% { transform: rotate(270deg) scale(1.1); }
100% { transform: rotate(360deg) scale(1); }
}
.ball-track {
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border: 3px dashed rgba(255, 255, 255, 0.2);
border-radius: 50%;
pointer-events: none;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎰 КАЗИНО РУЛЕТКА 🎰</h1>
<p>Испытайте удачу в классической европейской рулетке</p>
</div>
<div class="stats">
<div class="stat-card">
<div>Баланс</div>
<div class="stat-value" id="balance">1000</div>
</div>
<div class="stat-card">
<div>Последний выигрыш</div>
<div class="stat-value" id="lastWin">0</div>
</div>
<div class="stat-card">
<div>Всего игр</div>
<div class="stat-value" id="totalGames">0</div>
</div>
</div>
<div class="game-area">
<div class="wheel-container">
<h3>Колесо Рулетки</h3>
<div class="wheel-wrapper">
<div class="wheel-pointer"></div>
<div class="wheel" id="wheel">
<!-- Numbers will be generated by JavaScript -->
</div>
<div class="wheel-center"></div>
<div class="ball" id="ball"></div>
<div class="wheel-rim"></div>
<div class="ball-track"></div>
</div>
<div style="margin-top: 20px; font-size: 18px; font-weight: bold;">
Выпало: <span id="lastNumber" style="color: #ffd700;">-</span>
</div>
</div>
<div class="table-container">
<h3>Игровой стол</h3>
<div class="roulette-table" id="rouletteTable">
<!-- Table will be generated by JavaScript -->
</div>
<div class="bet-options">
<div class="bet-option" data-type="color" data-value="red">Красное (x2)</div>
<div class="bet-option" data-type="color" data-value="black">Черное (x2)</div>
<div class="bet-option" data-type="even_odd" data-value="even">Четное (x2)</div>
<div class="bet-option" data-type="even_odd" data-value="odd">Нечетное (x2)</div>
<div class="bet-option" data-type="dozen" data-value="first">1-12 (x3)</div>
<div class="bet-option" data-type="dozen" data-value="second">13-24 (x3)</div>
<div class="bet-option" data-type="dozen" data-value="third">25-36 (x3)</div>
<div class="bet-option" data-type="half" data-value="1-18">1-18 (x2)</div>
<div class="bet-option" data-type="half" data-value="19-36">19-36 (x2)</div>
<div class="bet-option" data-type="column" data-value="1">1-я колонка (x3)</div>
<div class="bet-option" data-type="column" data-value="2">2-я колонка (x3)</div>
<div class="bet-option" data-type="column" data-value="0">3-я колонка (x3)</div>
</div>
</div>
</div>
<div class="controls">
<div class="balance-info">Баланс: <span id="currentBalance">1000</span> ₽</div>
<input type="number" id="betAmount" value="10" min="1" max="1000">
<button id="spinButton">🎰 КРУТИТЬ</button>
<button id="clearButton">❌ ОЧИСТИТЬ</button>
<div>Ставка: <span id="currentBet" style="color: #ffd700;">Не выбрана</span></div>
</div>
<div class="result" id="result">
Сделайте ставку и нажмите "Крутить"
</div>
<div class="history">
<h3>История игр</h3>
<div id="historyList">
<!-- History will be populated by JavaScript -->
</div>
</div>
</div>
<script>
const gameState = {
balance: 1000,
currentBet: null,
currentBetType: null,
currentBetValue: null,
history: [],
totalGames: 0,
totalWins: 0
};
// Wheel configuration
const wheelOrder = [0, 32, 15, 19, 4, 21, 2, 25, 17, 34, 6, 27, 13, 36, 11, 30, 8, 23,
10, 5, 24, 16, 33, 1, 20, 14, 31, 9, 22, 18, 29, 7, 28, 12, 35, 3, 26];
const redNumbers = [32,19,21,25,34,27,36,30,23,5,16,1,14,9,18,7,12,35,3,26];
// Initialize game
function initGame() {
createWheelNumbers();
createRouletteTable();
updateDisplay();
}
// Create realistic wheel numbers
function createWheelNumbers() {
const wheel = document.getElementById('wheel');
const totalNumbers = wheelOrder.length;
wheelOrder.forEach((num, index) => {
const angle = (index / totalNumbers) * 360;
const numberEl = document.createElement('div');
// Determine color
let colorClass = 'black';
if (num === 0) {
colorClass = 'green';
} else if (redNumbers.includes(num)) {
colorClass = 'red';
}
numberEl.className = `wheel-number ${colorClass}`;
numberEl.textContent = num;
numberEl.style.transform = `rotate(${angle}deg) translate(0, -110px) rotate(-${angle}deg)`;
// Add subtle shadow for depth
numberEl.style.boxShadow = 'inset 2px 2px 5px rgba(0,0,0,0.5), inset -2px -2px 5px rgba(255,255,255,0.2)';
wheel.appendChild(numberEl);
});
}
// Create roulette table
function createRouletteTable() {
const table = document.getElementById('rouletteTable');
// Create zero cell
const zeroCell = document.createElement('div');
zeroCell.className = 'table-cell green';
zeroCell.textContent = '0';
zeroCell.dataset.type = 'number';
zeroCell.dataset.value = '0';
table.appendChild(zeroCell);
// Create number cells (3 columns x 12 rows)
for (let row = 0; row < 12; row++) {
for (let col = 0; col < 3; col++) {
const number = 3 * row + col + 1;
const numberEl = document.createElement('div');
const isRed = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36].includes(number);
numberEl.className = `table-cell ${isRed ? 'red' : 'black'}`;
numberEl.textContent = number;
numberEl.dataset.type = 'number';
numberEl.dataset.value = number;
table.appendChild(numberEl);
}
}
// Add event listeners
document.querySelectorAll('.table-cell, .bet-option').forEach(el => {
el.addEventListener('click', handleBetSelection);
});
}
// Handle bet selection
function handleBetSelection(e) {
const el = e.currentTarget;
const betType = el.dataset.type;
const betValue = el.dataset.value;
const betAmount = parseInt(document.getElementById('betAmount').value);
if (betAmount > gameState.balance) {
showResult('Недостаточно средств!', 'lose');
return;
}
// Remove active class from all bets
document.querySelectorAll('.bet-option, .table-cell').forEach(item => {
item.classList.remove('active');
});
// Add active class to current bet
el.classList.add('active');
gameState.currentBetType = betType;
gameState.currentBetValue = betValue;
gameState.currentBet = {
type: betType,
value: betValue,
amount: betAmount,
display: el.textContent
};
updateDisplay();
}
// Spin the wheel with realistic animation
async function spinWheel() {
if (!gameState.currentBet) {
showResult('Сначала сделайте ставку!', 'lose');
return;
}
const betAmount = parseInt(document.getElementById('betAmount').value);
if (betAmount > gameState.balance) {
showResult('Недостаточно средств!', 'lose');
return;
}
// Disable controls during spin
document.getElementById('spinButton').disabled = true;
document.getElementById('clearButton').disabled = true;
// Deduct bet amount
gameState.balance -= betAmount;
gameState.totalGames++;
// Enhanced wheel animation
const wheel = document.getElementById('wheel');
const ball = document.getElementById('ball');
// Reset wheel position
wheel.style.transition = 'none';
wheel.style.transform = 'rotate(0deg)';
// Ball animation
ball.style.transition = 'none';
ball.style.transform = 'translate(-50%, -50%)';
// Force reflow
setTimeout(() => {
const spins = 4 + Math.random() * 2; // 4-6 spins
const winningAngle = Math.random() * 360;
const totalRotation = spins * 360 + winningAngle;
// Apply animations
wheel.style.transition = `transform ${3 + spins}s cubic-bezier(0.1, 0.7, 0.2, 1.0)`;
wheel.style.transform = `rotate(${totalRotation}deg)`;
// Ball bouncing animation
ball.style.transition = `all 0.2s ease-out`;
let bounceCount = 0;
const bounceInterval = setInterval(() => {
if (bounceCount < 15) {
const offset = Math.sin(bounceCount * 0.5) * 5;
ball.style.transform = `translate(-50%, calc(-50% + ${offset}px))`;
bounceCount++;
} else {
clearInterval(bounceInterval);
}
}, 100);
}, 10);
// Send request to server
try {
const response = await fetch('/spin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
betType: gameState.currentBetType,
betValue: gameState.currentBetValue,
betAmount: betAmount
})
});
const data = await response.json();
// Show result after animation
setTimeout(() => {
handleSpinResult(data, betAmount);
}, 4000 + Math.random() * 1000);
} catch (error) {
console.error('Error:', error);
showResult('Ошибка соединения!', 'lose');
document.getElementById('spinButton').disabled = false;
document.getElementById('clearButton').disabled = false;
}
}
// Handle spin result
function handleSpinResult(data, betAmount) {
const won = data.win;
const payout = data.payout;
const winningNumber = data.winningNumber;
if (won) {
gameState.balance += payout;
gameState.totalWins++;
showResult(`🎉 ПОБЕДА! Выпало ${winningNumber}. Выигрыш: ${payout} ₽`, 'win');
// Winning animation
const wheel = document.getElementById('wheel');
wheel.classList.add('winning-animation');
setTimeout(() => {
wheel.classList.remove('winning-animation');
}, 2000);
} else {
showResult(`❌ Проигрыш. Выпало: ${winningNumber}`, 'lose');
}
// Update last number with color
const lastNumberEl = document.getElementById('lastNumber');
lastNumberEl.textContent = winningNumber;
lastNumberEl.style.color = data.color === 'red' ? '#ff4444' : data.color === 'black' ? '#000' : '#0a5c36';
// Add to history
addToHistory({
number: winningNumber,
bet: gameState.currentBet.display,
amount: betAmount,
payout: payout,
won: won,
timestamp: new Date().toLocaleTimeString()
});
// Update display and re-enable controls
updateDisplay();
document.getElementById('spinButton').disabled = false;
document.getElementById('clearButton').disabled = false;
// Clear bet after spin
gameState.currentBet = null;
gameState.currentBetType = null;
gameState.currentBetValue = null;
document.querySelectorAll('.bet-option, .table-cell').forEach(item => {
item.classList.remove('active');
});
}
// Add game to history
function addToHistory(game) {
gameState.history.unshift(game);
if (gameState.history.length > 10) {
gameState.history.pop();
}
updateHistoryDisplay();
}
// Update history display
function updateHistoryDisplay() {
const historyList = document.getElementById('historyList');
historyList.innerHTML = '';
gameState.history.forEach(game => {
const item = document.createElement('div');
item.className = `history-item ${game.won ? 'win' : 'lose'}`;
item.innerHTML = `
<span style="color: ${game.won ? '#48bb78' : '#e53e3e'}">${game.timestamp}</span>
<span>${game.bet}</span>
<span>${game.amount}₽</span>
<span style="color: ${getNumberColor(game.number)}">${game.number}</span>
<span style="color: ${game.won ? '#48bb78' : '#e53e3e'}">${game.won ? `+${game.payout}₽` : '−'}</span>
`;
historyList.appendChild(item);
});
}
// Helper function to get number color
function getNumberColor(number) {
if (number === 0) return '#0a5c36';
return redNumbers.includes(number) ? '#ff4444' : '#000';
}
// Show result message
function showResult(message, type) {
const result = document.getElementById('result');
result.textContent = message;
result.className = 'result';
if (type) {
result.classList.add(type);
}
}
// Update display
function updateDisplay() {
document.getElementById('currentBalance').textContent = gameState.balance;
document.getElementById('balance').textContent = gameState.balance;
document.getElementById('lastWin').textContent = gameState.history[0]?.payout || 0;
document.getElementById('totalGames').textContent = gameState.totalGames;
if (gameState.currentBet) {
document.getElementById('currentBet').textContent =
`${gameState.currentBet.display} (${gameState.currentBet.amount} ₽)`;
} else {
document.getElementById('currentBet').textContent = 'Не выбрана';
}
}
// Clear current bet
function clearBet() {
gameState.currentBet = null;
gameState.currentBetType = null;
gameState.currentBetValue = null;
document.querySelectorAll('.bet-option, .table-cell').forEach(item => {
item.classList.remove('active');
});
updateDisplay();
showResult('Ставка очищена', '');
}
// Event listeners
document.getElementById('spinButton').addEventListener('click', spinWheel);
document.getElementById('clearButton').addEventListener('click', clearBet);
// Initialize game when page loads
window.addEventListener('load', initGame);
</script>
</body>
</html>
'''
game = RouletteGame()
@app.route('/')
def index():
# Initialize session
init_session()
return render_template_string(HTML_TEMPLATE)
@app.route('/spin', methods=['POST'])
def spin():
# Ensure session is initialized
init_session()
data = request.json
bet_type = data['betType']
bet_value = data['betValue']
bet_amount = float(data['betAmount'])
# Check if player has enough balance
if bet_amount > session['balance']:
return jsonify({'error': 'Недостаточно средств'}), 400
# Deduct bet amount
session['balance'] -= bet_amount
session['total_games'] = session.get('total_games', 0) + 1
# Spin the wheel
winning_number = game.spin()
win = game.check_win(winning_number, bet_type, bet_value)
# Calculate payout
payout = 0
if win:
multiplier = game.get_payout_multiplier(bet_type)
payout = bet_amount * multiplier
session['balance'] += payout
session['total_wins'] = session.get('total_wins', 0) + 1
# Add to history
history_item = {
'number': winning_number,
'bet_type': bet_type,
'bet_value': bet_value,
'amount': bet_amount,
'payout': payout,
'won': win,
'timestamp': datetime.now().strftime('%H:%M:%S')
}
session['history'] = session.get('history', [])
session['history'].insert(0, history_item)
if len(session['history']) > 10:
session['history'] = session['history'][:10]
session.modified = True
return jsonify({
'winningNumber': winning_number,
'win': win,
'payout': payout,
'color': 'red' if winning_number in game.reds else 'black',
'newBalance': session['balance']
})
@app.route('/reset', methods=['POST'])
def reset():
session['balance'] = 1000
session['history'] = []
session['total_games'] = 0
session['total_wins'] = 0
session.modified = True
return jsonify({'message': 'Игра сброшена', 'balance': session['balance']})
@app.before_request
def before_request():
"""Ensure session is initialized before each request"""
init_session()
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=7860)