|
|
import random |
|
|
import os |
|
|
from flask import Flask, request, jsonify, render_template |
|
|
from flask_socketio import SocketIO, emit |
|
|
from flask_cors import CORS |
|
|
|
|
|
app = Flask(__name__, template_folder="templates") |
|
|
CORS(app, resources={r"/*": {"origins": "*"}}) |
|
|
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet') |
|
|
|
|
|
|
|
|
SUITS = ['Herz', 'Karo', 'Pik', 'Kreuz'] |
|
|
RANKS = {'7': 7, '8': 8, '9': 9, '10': 10, 'B': 10, 'D': 10, 'K': 10, 'A': 11} |
|
|
|
|
|
class GameState: |
|
|
def __init__(self): |
|
|
self.players = {} |
|
|
self.active_emails = [] |
|
|
self.middle = [] |
|
|
self.deck = [] |
|
|
self.turn_idx = 0 |
|
|
self.current_bet = 50 |
|
|
|
|
|
def calculate_score(self, hand): |
|
|
if not hand or len(hand) < 3: return 0 |
|
|
r = [c['rank'] for c in hand] |
|
|
if r[0] == r[1] == r[2]: return 30.5 |
|
|
sums = {'Herz': 0, 'Karo': 0, 'Pik': 0, 'Kreuz': 0} |
|
|
for c in hand: sums[c['suit']] += c['val'] |
|
|
return max(sums.values()) |
|
|
|
|
|
def broadcast_state(self): |
|
|
for email in self.active_emails: |
|
|
if email in self.players: |
|
|
self.players[email]['score'] = self.calculate_score(self.players[email].get('hand', [])) |
|
|
|
|
|
state = { |
|
|
'players': [self.players[e] for e in self.active_emails if e in self.players], |
|
|
'middle': self.middle, |
|
|
'turn_idx': self.turn_idx, |
|
|
'current_bet': self.current_bet, |
|
|
'pott': len(self.active_emails) * int(self.current_bet) |
|
|
} |
|
|
emit('update_table', state, broadcast=True) |
|
|
|
|
|
game = GameState() |
|
|
|
|
|
@app.route('/') |
|
|
def index(): return render_template('index.html') |
|
|
|
|
|
@app.route('/login', methods=['POST']) |
|
|
def login(): |
|
|
data = request.json |
|
|
email = data.get('email') |
|
|
if email not in game.players: |
|
|
game.players[email] = { |
|
|
'email': email, 'coins': 1000, 'hand': [], 'score': 0, |
|
|
'is_admin': len(game.players) == 0 |
|
|
} |
|
|
return jsonify({'stats': game.players[email]}) |
|
|
|
|
|
@socketio.on('join_game') |
|
|
def handle_join(data): |
|
|
email = data.get('email') |
|
|
if email and email not in game.active_emails: |
|
|
game.active_emails.append(email) |
|
|
game.broadcast_state() |
|
|
|
|
|
@socketio.on('start_round') |
|
|
def start_round(data): |
|
|
email = data.get('email') |
|
|
|
|
|
if email in game.players and game.players[email].get('is_admin'): |
|
|
game.deck = [{'suit': s, 'rank': r, 'val': v} for s in SUITS for r, v in RANKS.items()] |
|
|
random.shuffle(game.deck) |
|
|
game.middle = [game.deck.pop() for _ in range(3)] |
|
|
for e in game.active_emails: |
|
|
p = game.players[e] |
|
|
if p['coins'] >= game.current_bet: |
|
|
p['hand'] = [game.deck.pop() for _ in range(3)] |
|
|
p['coins'] -= int(game.current_bet) |
|
|
game.turn_idx = 0 |
|
|
game.broadcast_state() |
|
|
|
|
|
@socketio.on('player_action') |
|
|
def handle_action(data): |
|
|
email = data.get('email') |
|
|
if not game.active_emails or game.active_emails[game.turn_idx] != email: return |
|
|
p = game.players.get(email) |
|
|
|
|
|
if data['type'] == 'swap_one': |
|
|
p['hand'][data['h_idx']], game.middle[data['m_idx']] = game.middle[data['m_idx']], p['hand'][data['h_idx']] |
|
|
elif data['type'] == 'swap_all': |
|
|
p['hand'], game.middle = game.middle, p['hand'] |
|
|
elif data['type'] == 'knock': |
|
|
scores = {e: game.calculate_score(game.players[e]['hand']) for e in game.active_emails} |
|
|
max_s = max(scores.values()) |
|
|
winners = [e for e, s in scores.items() if s == max_s] |
|
|
pott = len(game.active_emails) * int(game.current_bet) |
|
|
for w in winners: game.players[w]['coins'] += pott // len(winners) |
|
|
emit('game_over', {'winner': ", ".join(winners), 'score': max_s, 'pott': pott}, broadcast=True) |
|
|
return |
|
|
|
|
|
game.turn_idx = (game.turn_idx + 1) % len(game.active_emails) |
|
|
game.broadcast_state() |
|
|
|
|
|
|
|
|
|
|
|
@socketio.on('admin/reshuffle') |
|
|
def admin_reshuffle(data): |
|
|
email = data.get('email') |
|
|
if email in game.players and game.players[email].get('is_admin'): |
|
|
game.deck = [{'suit': s, 'rank': r, 'val': v} for s in SUITS for r, v in RANKS.items()] |
|
|
random.shuffle(game.deck) |
|
|
|
|
|
game.middle = [game.deck.pop() for _ in range(3)] |
|
|
|
|
|
for e in game.active_emails: |
|
|
if e in game.players: |
|
|
game.players[e]['hand'] = [game.deck.pop() for _ in range(3)] |
|
|
|
|
|
emit('cards_reshuffled', broadcast=True) |
|
|
game.broadcast_state() |
|
|
|
|
|
@socketio.on('admin/end_game') |
|
|
def admin_end_game(data): |
|
|
email = data.get('email') |
|
|
if email in game.players and game.players[email].get('is_admin'): |
|
|
|
|
|
emit('game_ended_by_admin', broadcast=True) |
|
|
|
|
|
game.active_emails = [] |
|
|
game.middle = [] |
|
|
|
|
|
@socketio.on('admin/update_bet') |
|
|
def update_bet(data): |
|
|
email = data.get('email') |
|
|
if email in game.players and game.players[email].get('is_admin'): |
|
|
game.current_bet = int(data.get('bet', 50)) |
|
|
emit('bet_updated', {'new_bet': game.current_bet}, broadcast=True) |
|
|
game.broadcast_state() |
|
|
|
|
|
if __name__ == '__main__': |
|
|
socketio.run(app, host='0.0.0.0', port=7860) |