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') # --- KONFIGURATION --- 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') # Nur der Admin kann die Runde starten und den Einsatz einziehen 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() # --- ADMIN SPEZIAL FUNKTIONEN --- @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) # Neue Karten für die Mitte game.middle = [game.deck.pop() for _ in range(3)] # Neue Karten für alle aktiven Spieler (ohne Bezahlung) 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'): # Signal an alle: Spiel vorbei, bitte neu laden emit('game_ended_by_admin', broadcast=True) # Server-Seitig Daten aufräumen 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)