generated from streamlit/basic-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
streamlit_app.py
173 lines (130 loc) Β· 5.79 KB
/
streamlit_app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import streamlit as st
import pandas as pd
import json
import os
st.set_page_config(page_title="Tunisian Rami Scorekeeper", page_icon="π", layout="wide")
class Player:
"""Represents a player in the Tunisian Rami game."""
def __init__(self, name: str):
self.name = name
self.score = 0
self.round_scores = []
def update_score(self, score_change: int):
"""Updates the player's score and tracks round history."""
self.score += score_change
self.round_scores.append(self.score)
def save_round_scores(self):
"""Saves the round scores in session state."""
st.session_state.round_scores = self.round_scores
def load_round_scores(self):
"""Loads the round scores from session state."""
self.round_scores = st.session_state.round_scores
def reset_round_scores(self):
"""Resets the round scores."""
self.round_scores = []
def reset_score(self):
"""Resets the player's score."""
self.score = 0
class TunisianRamiGame:
"""Manages the game logic and state for Tunisian Rami."""
def __init__(self, player_names: list[str]):
self.players = {name: Player(name) for name in player_names}
self.round_history = [] # Correct data structure for round history
def record_round(self, round_scores: dict[str, int]): # Corrected type annotation
"""Records the scores for a round and updates player histories."""
self.round_history.append(round_scores)
for name, score_change in round_scores.items():
self.players[name].update_score(score_change)
def get_current_scores(self) -> dict[str, int]:
"""Returns a dictionary of current player scores."""
return {player.name: player.score for player in self.players.values()}
def get_round_history_dataframe(self) -> pd.DataFrame:
"""Returns a DataFrame showing the score history for each round."""
df_data = {player.name: player.round_scores
for player in self.players.values()}
df = pd.DataFrame(df_data)
df.index.name = "Round"
df.index += 1
return df
def save_game(self, filename="rami_game.json"):
"""Saves the game state to a JSON file."""
game_data = {
"players": {name: player.round_scores for name, player in self.players.items()},
"round_history": self.round_history
}
with open(filename, 'w') as f:
json.dump(game_data, f)
def load_game(self, filename="rami_game.json"):
"""Loads the game state from a JSON file."""
if os.path.exists(filename):
with open(filename, 'r') as f:
game_data = json.load(f)
self.players = {name: Player(name) for name in game_data["players"]}
for name, round_scores in game_data["players"].items():
self.players[name].round_scores = round_scores
self.players[name].score = round_scores[-1] if round_scores else 0
self.round_history = game_data["round_history"]
else:
st.warning("No saved game found. Starting a new game.")
def reset_game(self):
"""Resets the game state."""
self.players = {name: Player(name) for name in self.players}
self.round_history = []
# --- Streamlit App UI ---
st.title("Tunisian Rami Scorekeeper ππΉπ³")
# --- Game Setup (Sidebar) ---
st.sidebar.header("Game Setup")
num_players = st.sidebar.number_input("Number of Players:", min_value=2, max_value=5, value=5)
default_player_names = ["Saleh", "Achref", "Morta", "Khalil"]
player_names = [st.sidebar.text_input(f"Player {i+1} Name:", value=name) for i, name in enumerate(default_player_names[:num_players])]
# --- Initialize or Load Game ---
if 'game' not in st.session_state:
st.session_state.game = TunisianRamiGame(player_names)
game = st.session_state.game
if st.sidebar.button("New Game"):
game.reset_game()
game.players = {name: Player(name) for name in player_names}
st.session_state.game = game
st.session_state.round_scores = {} # Reset round scores in session state
game.save_game()
else:
game.load_game()
st.session_state.game = game # Save the game in session state
# --- Gameplay Section ---
st.header("Score Adjustments π²")
cols = st.columns(len(game.players))
round_scores = {}
for i, (player_name, player) in enumerate(game.players.items()):
with cols[i]:
round_scores[player_name] = st.number_input(
f"Adjust {player_name}'s score:",
value=100,
key=f"input_{player_name}", # Unique key
step=50
)
if st.button("Record Round β‘οΈ"):
game.record_round(round_scores)
game.save_game()
# reset score inputs to 0
# st.experimental_rerun()
# --- Display Scores ---
st.header("Current Scores π")
st.bar_chart(pd.DataFrame([game.get_current_scores()]).transpose())
# --- Round History Table ---
st.header("Round History π")
if game.round_history:
st.table(game.get_round_history_dataframe())
else:
st.write("No rounds recorded yet.")
# display round based bars chart each round will display the added scores
st.header("Round Based Scores")
if game.round_history:
for i, round_scores in enumerate(game.round_history):
if sum(round_scores.values()) == 0:
st.subheader(f"Round {i+1} (Frish Round)")
else:
st.subheader(f"Round {i+1}")
st.bar_chart(pd.DataFrame([round_scores]).transpose())
# if no scores added then its a frish rouncd
else:
st.write("No rounds recorded yet.")