Update app.py
Browse files
app.py
CHANGED
|
@@ -1,84 +1,71 @@
|
|
| 1 |
import eventlet
|
| 2 |
eventlet.monkey_patch()
|
| 3 |
|
| 4 |
-
import
|
| 5 |
-
import
|
| 6 |
-
from flask import Flask, render_template, request, jsonify
|
| 7 |
from flask_socketio import SocketIO, emit
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
logging.basicConfig(level=logging.INFO)
|
| 11 |
|
| 12 |
app = Flask(__name__)
|
| 13 |
-
app
|
| 14 |
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet')
|
| 15 |
|
| 16 |
-
# -
|
| 17 |
game_state = {
|
| 18 |
"players": [],
|
| 19 |
"middle": [],
|
| 20 |
"deck": [],
|
| 21 |
"turn_idx": 0,
|
| 22 |
-
"
|
| 23 |
-
"
|
| 24 |
}
|
| 25 |
|
| 26 |
def create_deck():
|
| 27 |
suits = ['Herz', 'Karo', 'Pik', 'Kreuz']
|
| 28 |
-
ranks =
|
| 29 |
-
return [{
|
| 30 |
|
| 31 |
-
def
|
| 32 |
-
if not hand or len(hand) < 3: return 0
|
| 33 |
-
values = {'7':7, '8':8, '9':9, '10':10, 'B':10, 'D':10, 'K':10, 'A':11}
|
| 34 |
-
# Drei Gleiche (z.B. drei 7er) = 30.5
|
| 35 |
-
if hand[0]['rank'] == hand[1]['rank'] == hand[2]['rank']:
|
| 36 |
-
return 30.5
|
| 37 |
-
# Summe pro Farbe
|
| 38 |
scores = {'Herz': 0, 'Karo': 0, 'Pik': 0, 'Kreuz': 0}
|
| 39 |
-
for
|
| 40 |
-
scores[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
return max(scores.values())
|
| 42 |
|
| 43 |
-
@app.route('/')
|
| 44 |
-
def index():
|
| 45 |
-
return render_template('index.html')
|
| 46 |
-
|
| 47 |
@app.route('/login', methods=['POST'])
|
| 48 |
def login():
|
| 49 |
data = request.json
|
| 50 |
-
email = data.get('email'
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
if not player:
|
| 58 |
-
player = {"email": email, "coins": 1000, "hand": [], "score": 0, "is_admin": is_admin}
|
| 59 |
-
game_state["players"].append(player)
|
| 60 |
-
|
| 61 |
-
return jsonify({"status": "ok", "stats": {"is_admin": is_admin}})
|
| 62 |
|
| 63 |
@socketio.on('join_game')
|
| 64 |
def on_join(data):
|
| 65 |
emit('update_table', game_state, broadcast=True)
|
| 66 |
|
| 67 |
-
@socketio.on('admin/set_bet')
|
| 68 |
-
def on_set_bet(data):
|
| 69 |
-
game_state["current_bet"] = int(data.get('bet', 50))
|
| 70 |
-
|
| 71 |
@socketio.on('start_round')
|
| 72 |
-
def
|
| 73 |
deck = create_deck()
|
| 74 |
random.shuffle(deck)
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
p[
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
game_state[
|
| 81 |
-
game_state[
|
|
|
|
|
|
|
|
|
|
| 82 |
emit('update_table', game_state, broadcast=True)
|
| 83 |
|
| 84 |
@socketio.on('player_action')
|
|
@@ -86,23 +73,41 @@ def on_action(data):
|
|
| 86 |
email = data.get('email')
|
| 87 |
action_type = data.get('type')
|
| 88 |
|
| 89 |
-
|
| 90 |
-
current_player =
|
| 91 |
-
|
| 92 |
-
if current_player["email"] != email: return
|
| 93 |
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
elif action_type == 'swap_all':
|
| 99 |
-
current_player[
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
-
|
| 103 |
-
game_state[
|
|
|
|
|
|
|
| 104 |
emit('update_table', game_state, broadcast=True)
|
| 105 |
|
| 106 |
if __name__ == '__main__':
|
| 107 |
-
|
| 108 |
-
socketio.run(app, host='0.0.0.0', port=7860, debug=False)
|
|
|
|
| 1 |
import eventlet
|
| 2 |
eventlet.monkey_patch()
|
| 3 |
|
| 4 |
+
import flask
|
| 5 |
+
from flask import Flask, request, jsonify
|
|
|
|
| 6 |
from flask_socketio import SocketIO, emit
|
| 7 |
+
from flask_cors import CORS
|
| 8 |
+
import random
|
|
|
|
| 9 |
|
| 10 |
app = Flask(__name__)
|
| 11 |
+
CORS(app)
|
| 12 |
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet')
|
| 13 |
|
| 14 |
+
# Spiel-Datenstruktur
|
| 15 |
game_state = {
|
| 16 |
"players": [],
|
| 17 |
"middle": [],
|
| 18 |
"deck": [],
|
| 19 |
"turn_idx": 0,
|
| 20 |
+
"knocked_by": None, # Speichert, wer geklopft hat
|
| 21 |
+
"active": False
|
| 22 |
}
|
| 23 |
|
| 24 |
def create_deck():
|
| 25 |
suits = ['Herz', 'Karo', 'Pik', 'Kreuz']
|
| 26 |
+
ranks = {'7':7, '8':8, '9':9, '10':10, 'B':10, 'D':10, 'K':10, 'A':11}
|
| 27 |
+
return [{'suit': s, 'rank': r, 'val': v} for s in suits for r, v in ranks.items()]
|
| 28 |
|
| 29 |
+
def calc_score(hand):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
scores = {'Herz': 0, 'Karo': 0, 'Pik': 0, 'Kreuz': 0}
|
| 31 |
+
for c in hand:
|
| 32 |
+
scores[c['suit']] += c['val']
|
| 33 |
+
|
| 34 |
+
# Spezialregel: Drei Gleiche (z.B. drei 7er) = 30.5 Punkte
|
| 35 |
+
ranks = [c['rank'] for c in hand]
|
| 36 |
+
if len(set(ranks)) == 1: return 30.5
|
| 37 |
+
|
| 38 |
return max(scores.values())
|
| 39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
@app.route('/login', methods=['POST'])
|
| 41 |
def login():
|
| 42 |
data = request.json
|
| 43 |
+
email = data.get('email')
|
| 44 |
+
# Einfache User-Verwaltung
|
| 45 |
+
user = next((p for p in game_state['players'] if p['email'] == email), None)
|
| 46 |
+
if not user:
|
| 47 |
+
user = {"email": email, "coins": 1000, "hand": [], "score": 0, "is_admin": len(game_state['players']) == 0}
|
| 48 |
+
game_state['players'].append(user)
|
| 49 |
+
return jsonify({"stats": user})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
@socketio.on('join_game')
|
| 52 |
def on_join(data):
|
| 53 |
emit('update_table', game_state, broadcast=True)
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
@socketio.on('start_round')
|
| 56 |
+
def start_round(data):
|
| 57 |
deck = create_deck()
|
| 58 |
random.shuffle(deck)
|
| 59 |
+
|
| 60 |
+
for p in game_state['players']:
|
| 61 |
+
p['hand'] = [deck.pop(), deck.pop(), deck.pop()]
|
| 62 |
+
p['score'] = calc_score(p['hand'])
|
| 63 |
+
|
| 64 |
+
game_state['middle'] = [deck.pop(), deck.pop(), deck.pop()]
|
| 65 |
+
game_state['deck'] = deck
|
| 66 |
+
game_state['turn_idx'] = 0
|
| 67 |
+
game_state['knocked_by'] = None
|
| 68 |
+
game_state['active'] = True
|
| 69 |
emit('update_table', game_state, broadcast=True)
|
| 70 |
|
| 71 |
@socketio.on('player_action')
|
|
|
|
| 73 |
email = data.get('email')
|
| 74 |
action_type = data.get('type')
|
| 75 |
|
| 76 |
+
current_player = game_state['players'][game_state['turn_idx']]
|
| 77 |
+
if current_player['email'] != email: return
|
|
|
|
|
|
|
| 78 |
|
| 79 |
+
# AKTION: KLOPFEN
|
| 80 |
+
if action_type == 'knock' and game_state['knocked_by'] is None:
|
| 81 |
+
game_state['knocked_by'] = email
|
| 82 |
+
|
| 83 |
+
# AKTION: TAUSCHEN (EINE)
|
| 84 |
+
elif action_type == 'swap_one':
|
| 85 |
+
h_idx, m_idx = data['h_idx'], data['m_idx']
|
| 86 |
+
current_player['hand'][h_idx], game_state['middle'][m_idx] = \
|
| 87 |
+
game_state['middle'][m_idx], current_player['hand'][h_idx]
|
| 88 |
+
|
| 89 |
+
# AKTION: ALLE TAUSCHEN
|
| 90 |
elif action_type == 'swap_all':
|
| 91 |
+
current_player['hand'], game_state['middle'] = game_state['middle'], current_player['hand']
|
| 92 |
+
|
| 93 |
+
# Score aktualisieren
|
| 94 |
+
current_player['score'] = calc_score(current_player['hand'])
|
| 95 |
+
|
| 96 |
+
# Nächster Spieler
|
| 97 |
+
game_state['turn_idx'] = (game_state['turn_idx'] + 1) % len(game_state['players'])
|
| 98 |
+
|
| 99 |
+
# PRÜFEN OB SPIEL ENDE (Wenn der nächste Spieler derjenige ist, der geklopft hat)
|
| 100 |
+
next_player = game_state['players'][game_state['turn_idx']]
|
| 101 |
+
if next_player['email'] == game_state['knocked_by']:
|
| 102 |
+
finish_game()
|
| 103 |
+
else:
|
| 104 |
+
emit('update_table', game_state, broadcast=True)
|
| 105 |
|
| 106 |
+
def finish_game():
|
| 107 |
+
game_state['active'] = False
|
| 108 |
+
winner = max(game_state['players'], key=lambda p: p['score'])
|
| 109 |
+
emit('game_over', {'winner': winner['email'], 'score': winner['score']}, broadcast=True)
|
| 110 |
emit('update_table', game_state, broadcast=True)
|
| 111 |
|
| 112 |
if __name__ == '__main__':
|
| 113 |
+
socketio.run(app, host="0.0.0.0", port=7860)
|
|
|