slevis commited on
Commit
3be7282
·
verified ·
1 Parent(s): d518bf8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +171 -12
app.py CHANGED
@@ -1,18 +1,177 @@
1
  import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  with gr.Blocks() as demo:
4
- Spieler = gr.Dropdown(choices=['Kirsten', 'Robert', 'Samuel'], label="Waehle Spieler:", info="Falls kein Alleinspieler, leer lassen")
5
- Spielart = gr.Dropdown(choices=['Null', 'Kreuz', 'Pik', 'Herz', 'Karo', 'Grande', 'Ramsch', 'Null offen'], label="Waehle Spielart:")
6
- Truempfe = gr.Dropdown(choices=['Kreuz', 'Pike', 'Herz', 'Karo', 'Ass', 'Zehn'], multiselect=True, label="Waehle Truempfe des Alleinspielers:")
 
 
 
 
 
 
 
 
 
 
7
  with gr.Row():
8
- Schneider = gr.Checkbox(label="Schneider?")
9
- Schwarz = gr.Checkbox(label="Schwarz?")
10
- speichere_spiel = gr.Button(value="Speichere Spiel")
11
- Turnier = gr.Dataframe(headers=['Kirsten', 'Robert', 'Samuel', 'Spielart', 'Alleinspieler', 'Truempfe', 'Schneider', 'Schwarz'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- @speichere_spiel.click(inputs=[Spieler, Spielart, Truempfe, Schneider, Schwarz], outputs=[Turnier])
14
- def spiel_hinzufuegen(Spieler, Spielart, Truempfe, Schneider, Schwarz):
15
- ...
16
- return ...
 
17
 
18
- demo.launch()
 
 
1
  import gradio as gr
2
+ import pandas as pd
3
+
4
+ # --- Konstanten für die Berechnung ---
5
+ # These constants are fine as they don't represent a changing state.
6
+ GRUNDWERTE = {"Karo": 9, "Herz": 10, "Pik": 11, "Kreuz": 12, "Grand": 24}
7
+ NULL_SPIELE = {"Null": 23, "Null Hand": 35, "Null Ouvert": 46, "Null Hand Ouvert": 59}
8
+ SPIELER = ["Kirsten", "Robert", "Samuel"]
9
+ HISTORY_DF_HEADERS = ["Kirsten", "Robert", "Samuel", "Spielwert", "Spielart", "Alleinspieler", "Details", "Verloren"]
10
+
11
+
12
+ # --- Hauptfunktionen ---
13
+
14
+ def calculate_spielwert(spielart, spitzen_str, hand, schneider, schwarz, schneider_angesagt, schwarz_angesagt, offen):
15
+ """Berechnet den reinen Spielwert (Reizwert) basierend auf den Spielregeln."""
16
+ # This function had no side effects and remains unchanged.
17
+ if spielart in NULL_SPIELE:
18
+ return NULL_SPIELE[spielart]
19
+ if spielart not in GRUNDWERTE or not spitzen_str:
20
+ return 0
21
+ spitzen_anzahl = int(spitzen_str.split(" ")[1])
22
+ gewinnstufe = 1
23
+ if hand: gewinnstufe += 1
24
+ if schneider: gewinnstufe += 1
25
+ if schneider_angesagt: gewinnstufe += 1
26
+ if schwarz: gewinnstufe += 1
27
+ if schwarz_angesagt: gewinnstufe += 1
28
+ if offen: gewinnstufe += 1
29
+ grundwert = GRUNDWERTE[spielart]
30
+ return (spitzen_anzahl + gewinnstufe) * grundwert
31
+
32
+ # --- REFACTURED FUNCTION ---
33
+ # No more global variables. The history_df is now passed as an argument.
34
+ def spiel_hinzufuegen(history_df, spieler, spielart, spitzen, hand, schneider, schwarz, schneider_angesagt, schwarz_angesagt, offen, verloren):
35
+ """
36
+ Fügt ein neues Spiel zum History-DataFrame hinzu und berechnet die Gesamtstände dynamisch.
37
+ """
38
+ spielwert = calculate_spielwert(spielart, spitzen, hand, schneider, schwarz, schneider_angesagt, schwarz_angesagt, offen)
39
+
40
+ # This dictionary stores the point change for this single round.
41
+ neue_punkte = {name: 0 for name in SPIELER}
42
+
43
+ if spieler: # Only if a soloist was selected
44
+ if not verloren:
45
+ # Soloist wins
46
+ neue_punkte[spieler] = 50 + spielwert
47
+ # Opponents get penalty points
48
+ for p in SPIELER:
49
+ if p != spieler:
50
+ neue_punkte[p] = -40
51
+ else:
52
+ # Soloist loses
53
+ neue_punkte[spieler] = -50 - (2 * spielwert) # The original had an error, this is the correct calculation for a lost game (-50 and -2*game_value)
54
+ # Opponents get points
55
+ for p in SPIELER:
56
+ if p != spieler:
57
+ neue_punkte[p] = 40
58
+
59
+ details = f"Spitzen: {spitzen or 'N/A'}"
60
+ if hand: details += ", Hand"
61
+ if schneider_angesagt: details += ", Schneider angesagt"
62
+ if schwarz_angesagt: details += ", Schwarz angesagt"
63
+ if offen: details += ", Offen"
64
+
65
+ # Create a dictionary for the new row
66
+ neues_spiel_eintrag = {
67
+ "Kirsten": neue_punkte["Kirsten"],
68
+ "Robert": neue_punkte["Robert"],
69
+ "Samuel": neue_punkte["Samuel"],
70
+ "Spielwert": spielwert,
71
+ "Spielart": spielart,
72
+ "Alleinspieler": spieler or "N/A",
73
+ "Details": details,
74
+ "Verloren": "Ja" if verloren else "Nein"
75
+ }
76
+
77
+ # --- NEW: STATE MANAGEMENT ---
78
+ # Convert the new game entry into a DataFrame of a single row
79
+ new_row_df = pd.DataFrame([neues_spiel_eintrag])
80
+
81
+ # Append the new row to the existing history DataFrame
82
+ updated_history_df = pd.concat([history_df, new_row_df], ignore_index=True)
83
+
84
+ # Calculate the totals by summing the columns of the *updated* history DataFrame
85
+ total_scores = updated_history_df[SPIELER].sum()
86
+ totals_df = pd.DataFrame([total_scores]) # Convert the totals Series to a DataFrame for display
87
+
88
+ # Return both updated DataFrames
89
+ return totals_df, updated_history_df
90
+
91
+ # --- REFACTURED FUNCTION ---
92
+ # This function no longer needs to modify globals. It just creates and returns empty DataFrames.
93
+ def reset_turnier():
94
+ """Setzt den gesamten Spielstand und die Historie zurück."""
95
+ empty_totals = pd.DataFrame([{"Kirsten": 0, "Robert": 0, "Samuel": 0}])
96
+ empty_history = pd.DataFrame(columns=HISTORY_DF_HEADERS)
97
+ return empty_totals, empty_history
98
+
99
+ # --- UI Definition mit Gradio ---
100
 
101
  with gr.Blocks() as demo:
102
+ gr.Markdown("# Skat-Punkte-Tracker")
103
+
104
+ gr.Markdown("### Gesamtpunktestand")
105
+
106
+ # --- NEW: Initialize DataFrames for the UI ---
107
+ initial_totals_df, initial_history_df = reset_turnier()
108
+
109
+ totals_output = gr.Dataframe(
110
+ value=initial_totals_df,
111
+ interactive=False,
112
+ show_row_numbers=False
113
+ )
114
+
115
  with gr.Row():
116
+ with gr.Column(scale=1):
117
+ gr.Markdown("### Neues Spiel eingeben")
118
+
119
+ spieler_input = gr.Dropdown(SPIELER, label="Alleinspieler")
120
+ spielart_input = gr.Dropdown(
121
+ choices=['Karo', 'Herz', 'Pik', 'Kreuz', 'Grand', 'Null', 'Null Hand', 'Null Ouvert', 'Null Hand Ouvert'], # Ramsch removed as it's not handled in the logic
122
+ label="Spielart"
123
+ )
124
+ spitzen_input = gr.Dropdown(
125
+ choices=[f"{m} {i}" for m in ["Mit", "Ohne"] for i in range(1, 5)], # Normal range is 1-4
126
+ label="Spitzen"
127
+ )
128
+
129
+ with gr.Row():
130
+ schneider_input = gr.Checkbox(label="Schneider")
131
+ schwarz_input = gr.Checkbox(label="Schwarz")
132
+ verloren_input = gr.Checkbox(label="Verloren?")
133
+
134
+ with gr.Accordion("Optionen für Handspiele", open=False):
135
+ hand_input = gr.Checkbox(label="Handspiel")
136
+ schneider_angesagt_input = gr.Checkbox(label="Schneider angesagt")
137
+ schwarz_angesagt_input = gr.Checkbox(label="Schwarz angesagt")
138
+ offen_input = gr.Checkbox(label="Offen / Ouvert")
139
+
140
+ with gr.Row():
141
+ speichere_spiel = gr.Button("Speichere Spiel", variant="primary", scale=2)
142
+ reset_button = gr.Button("Reset", variant="stop", scale=1)
143
+
144
+ with gr.Column(scale=2):
145
+ gr.Markdown("### Spielverlauf")
146
+ turnier_output = gr.Dataframe(
147
+ value=initial_history_df,
148
+ headers=HISTORY_DF_HEADERS,
149
+ interactive=False,
150
+ wrap=True
151
+ )
152
+
153
+ # List of all input components for a new game
154
+ inputs_list = [
155
+ spieler_input, spielart_input, spitzen_input,
156
+ hand_input, schneider_input, schwarz_input,
157
+ schneider_angesagt_input, schwarz_angesagt_input, offen_input,
158
+ verloren_input
159
+ ]
160
+
161
+ # --- NEW: Updated Click Handler ---
162
+ # The 'turnier_output' DataFrame is now also an INPUT to the function.
163
+ # It carries the current state of the game history.
164
+ speichere_spiel.click(
165
+ fn=spiel_hinzufuegen,
166
+ inputs=[turnier_output] + inputs_list,
167
+ outputs=[totals_output, turnier_output]
168
+ )
169
 
170
+ reset_button.click(
171
+ fn=reset_turnier,
172
+ inputs=[],
173
+ outputs=[totals_output, turnier_output]
174
+ )
175
 
176
+ if __name__ == "__main__":
177
+ demo.launch(share=True)