awacke1 commited on
Commit
dc60f58
ยท
verified ยท
1 Parent(s): 0f4bb5a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -192
app.py CHANGED
@@ -1,15 +1,3 @@
1
- # 1. Configuration
2
- import streamlit as st
3
- import pandas as pd
4
- import plotly.express as px
5
- import random
6
- import uuid
7
- import os
8
- import re
9
- from datetime import datetime
10
- from streamlit_flow import streamlit_flow
11
- from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
12
- from streamlit_flow.layouts import RadialLayout
13
 
14
  # Set page configuration to wide mode
15
  Site_Name = '๐ŸฆCatRider๐Ÿˆ'
@@ -32,6 +20,18 @@ if useConfig:
32
  }
33
  )
34
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  # ๐Ÿฑ Cat Rider and Gear Data
36
  CAT_RIDERS = [
37
  {"name": "Whiskers", "type": "Speed", "emoji": "๐Ÿพ", "strength": 3, "skill": 7},
@@ -55,30 +55,30 @@ RIDING_GEAR = [
55
 
56
  # ๐ŸŒ Game World Data (Expanded to 10 Situations)
57
  SITUATIONS = [
58
- {"id": "feline_escape", "name": "The Great Feline Escape", "description": "Your cat rider is trapped in an old mansion...", "emoji": "๐Ÿšช", "type": "escape", "preferred_action": "agility"},
59
- {"id": "lost_temple", "name": "The Treasure of the Lost Temple", "description": "On a quest to retrieve an ancient artifact...", "emoji": "๐Ÿ›๏ธ", "type": "exploration", "preferred_action": "resourcefulness"},
60
- {"id": "royal_tournament", "name": "The Royal Tournament", "description": "Compete in a grand tournament...", "emoji": "๐Ÿ‘‘", "type": "competition", "preferred_action": "bravery"},
61
- {"id": "sky_race", "name": "The Sky Race", "description": "Compete in the annual Sky Race...", "emoji": "โ˜๏ธ", "type": "competition", "preferred_action": "agility"},
62
- {"id": "cheese_heist", "name": "The Great Cheese Heist", "description": "Your cat rider must sneak into the royal pantry...", "emoji": "๐Ÿง€", "type": "heist", "preferred_action": "stealth"},
63
- {"id": "pirate_cove", "name": "The Pirate Cove", "description": "Sail the high seas with your trusty crew...", "emoji": "๐Ÿดโ€โ˜ ๏ธ", "type": "exploration", "preferred_action": "bravery"},
64
- {"id": "feline_moon_mission", "name": "The Feline Moon Mission", "description": "Blast off into space...", "emoji": "๐ŸŒ•", "type": "exploration", "preferred_action": "resourcefulness"},
65
- {"id": "purr_summit", "name": "The Purr Summit", "description": "Join a secret gathering of the most intellectual cats...", "emoji": "๐Ÿ“œ", "type": "debate", "preferred_action": "insight"},
66
- {"id": "feline_invasion", "name": "The Feline Invasion", "description": "Aliens have invaded Earth...", "emoji": "๐Ÿ‘ฝ", "type": "battle", "preferred_action": "strategy"},
67
- {"id": "eternal_catnap", "name": "The Eternal Catnap", "description": "You've entered a sacred temple...", "emoji": "๐Ÿ’ค", "type": "exploration", "preferred_action": "stealth"}
68
  ]
69
 
70
  # ๐Ÿง  Expanded Actions (10 Actions)
71
  ACTIONS = [
72
- {"id": "stealth", "name": "Use Stealth", "description": "Sneak past obstacles...", "emoji": "๐Ÿคซ", "type": "skill"},
73
- {"id": "agility", "name": "Showcase Agility", "description": "Perform impressive acrobatic maneuvers...", "emoji": "๐Ÿƒ", "type": "physical"},
74
- {"id": "charm", "name": "Charm Others", "description": "Use your cat's natural charisma...", "emoji": "๐Ÿ˜ป", "type": "social"},
75
- {"id": "resourcefulness", "name": "Be Resourceful", "description": "Utilize the environment or items...", "emoji": "๐Ÿง ", "type": "mental"},
76
- {"id": "bravery", "name": "Show Bravery", "description": "Face dangers head-on...", "emoji": "๐Ÿฆ", "type": "physical"},
77
- {"id": "strategy", "name": "Develop a Strategy", "description": "Use tactical thinking...", "emoji": "๐Ÿง ", "type": "mental"},
78
- {"id": "speed", "name": "Sprint Away", "description": "Run faster than you've ever run...", "emoji": "๐Ÿƒโ€โ™€๏ธ", "type": "physical"},
79
- {"id": "insight", "name": "Use Insight", "description": "Tap into ancient feline wisdom...", "emoji": "๐Ÿ”ฎ", "type": "mental"},
80
- {"id": "distraction", "name": "Create a Distraction", "description": "Use cunning tricks...", "emoji": "๐Ÿช„", "type": "mental"},
81
- {"id": "negotiation", "name": "Negotiate", "description": "Use diplomacy and clever negotiation...", "emoji": "๐Ÿ’ผ", "type": "social"}
82
  ]
83
 
84
  # Expanded conclusions for outcomes - 10 items each for success and failure
@@ -112,55 +112,15 @@ FAILURE_CONCLUSIONS = [
112
  def save_history_to_file(history_df, user_id):
113
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
114
  filename = f"history_{user_id}_{timestamp}.md"
115
- markdown, _, _ = process_journey_history(history_df)
116
  with open(filename, 'w', encoding='utf-8') as f:
117
  f.write(markdown)
118
  return filename
119
 
120
- # Function to load saved histories and reconstruct game state
121
- def load_saved_histories(user_id):
122
- history_files = [f for f in os.listdir('.') if f.startswith(f'history_{user_id}_') and f.endswith('.md')]
123
- history_files.sort() # Ensure files are sorted by timestamp
124
- combined_history = ''
125
- for history_file in history_files:
126
- with open(history_file, 'r', encoding='utf-8') as f:
127
- combined_history += f.read() + '\n'
128
- return combined_history
129
-
130
- # Function to parse markdown history and reconstruct history DataFrame
131
- def parse_history_markdown(markdown_text):
132
- lines = markdown_text.split('\n')
133
- data = []
134
- current_situation = None
135
- for line in lines:
136
- situation_match = re.match(r"### (\S+) \*\*(.+)\*\*", line)
137
- if situation_match:
138
- situation_emoji = situation_match.group(1)
139
- situation_name = situation_match.group(2)
140
- continue
141
- attempt_match = re.match(r"Attempt (\d+): (\S+) \*\*(.+)\*\*: (โœ… Success|โŒ Failure) (\S*)", line)
142
- if attempt_match:
143
- attempt = int(attempt_match.group(1))
144
- action_emoji = attempt_match.group(2)
145
- action_name = attempt_match.group(3)
146
- outcome_str = attempt_match.group(4)
147
- stars = attempt_match.group(5)
148
- outcome = True if outcome_str == 'โœ… Success' else False
149
- score = len(stars)
150
- conclusion_line_index = lines.index(line) + 1
151
- conclusion = lines[conclusion_line_index] if conclusion_line_index < len(lines) else ''
152
- data.append({
153
- 'situation_name': situation_name,
154
- 'situation_emoji': situation_emoji,
155
- 'attempt': attempt,
156
- 'action_name': action_name,
157
- 'action_emoji': action_emoji,
158
- 'outcome': outcome,
159
- 'score': score,
160
- 'conclusion': conclusion
161
- })
162
- history_df = pd.DataFrame(data)
163
- return history_df
164
 
165
  # ๐Ÿง  Game Mechanics
166
  def generate_situation():
@@ -209,95 +169,63 @@ def update_character_stats(game_state, outcome):
209
  game_state['gear_strength'] = max(1, game_state['gear_strength'] - 0.1)
210
  return game_state
211
 
212
- # ๐ŸŒณ Process Journey History to Create Markdown and Graph Data
213
- def process_journey_history(history_df):
214
- markdown = "## ๐ŸŒณ Journey Preview\n\n"
215
  nodes = []
216
  edges = []
217
  node_ids = {}
218
- score = 0 # To keep track of the score for success nodes
219
-
220
- grouped = history_df.groupby(['situation_name'], sort=False)
221
 
222
- # Main node to connect all situations
223
- main_node_id = "main"
224
- main_node = StreamlitFlowNode(
225
- main_node_id,
226
- pos=(0, 0),
227
- data={'content': "# Your Journey"},
228
- type='input',
229
- target_position='bottom',
230
- width=200
231
- )
232
- nodes.append(main_node)
233
-
234
- for situation_name, group in grouped:
235
- situation_emoji = group.iloc[0]['situation_emoji']
236
- situation_id = group.iloc[0].get('situation_id', str(uuid.uuid4()))
237
- situation_node_id = f"situation_{situation_id}"
238
-
239
- markdown += f"### {situation_emoji} **{situation_name}**\n"
240
-
241
- # Create situation node if not already created
242
  if situation_node_id not in node_ids:
243
  situation_node = StreamlitFlowNode(
244
  situation_node_id,
245
  pos=(0, 0),
246
- data={'content': f"### {situation_emoji} {situation_name}"},
247
  type='default',
248
- target_position='top',
249
- source_position='bottom',
250
- width=200
251
  )
252
  nodes.append(situation_node)
253
  node_ids[situation_node_id] = situation_node_id
254
 
255
- # Edge from main node to situation node
256
- edges.append(StreamlitFlowEdge(
257
- id=f"edge_{main_node_id}_{situation_node_id}",
258
- source=main_node_id,
259
- target=situation_node_id,
260
- animated=True
261
- ))
262
-
263
- for idx, row in group.iterrows():
264
- attempt = row['attempt']
265
- action_emoji = row['action_emoji']
266
- action_name = row['action_name']
267
- outcome = row['outcome']
268
- outcome_str = 'โœ… Success' if outcome else 'โŒ Failure'
269
- stars = 'โญ' * int(row.get('score', 0)) if outcome else ''
270
- conclusion = row.get('conclusion', '')
271
-
272
- markdown += f"Attempt {attempt}: {action_emoji} **{action_name}**: {outcome_str} {stars}\n"
273
- markdown += f"{conclusion}\n"
274
-
275
- # Create attempt node
276
- attempt_node_id = f"attempt_{situation_id}_{attempt}_{idx}"
277
- attempt_content = f"Attempt {attempt}: {action_emoji} {action_name}\n{outcome_str} {stars}\n{conclusion}"
278
-
279
- attempt_node = StreamlitFlowNode(
280
- attempt_node_id,
281
- pos=(0, 0),
282
- data={'content': attempt_content},
283
- type='output',
284
- target_position='top',
285
- source_position='bottom',
286
- width=250
287
- )
288
- nodes.append(attempt_node)
289
-
290
- # Edge from situation to attempt
291
- edges.append(StreamlitFlowEdge(
292
- id=f"edge_{situation_node_id}_{attempt_node_id}",
293
- source=situation_node_id,
294
- target=attempt_node_id,
295
- animated=True
296
- ))
297
 
 
 
 
 
 
 
 
298
  markdown += "\n"
299
-
300
- return markdown, nodes, edges
301
 
302
  # ๐Ÿ”„ Update game state with the result of the action
303
  def update_game_state(game_state, situation, action, outcome, timestamp):
@@ -310,10 +238,6 @@ def update_game_state(game_state, situation, action, outcome, timestamp):
310
  # Update attempt count
311
  attempt = game_state['current_attempt']
312
 
313
- # Update score
314
- if outcome:
315
- game_state['score'] += 1
316
-
317
  # Create a new record for the history
318
  new_record = pd.DataFrame({
319
  'user_id': [game_state['user_id']],
@@ -343,9 +267,6 @@ def update_game_state(game_state, situation, action, outcome, timestamp):
343
  else:
344
  game_state['history'][action['id']] = 1 if outcome else -1
345
 
346
- # Automatically save history after each action
347
- save_history_to_file(game_state['history_df'], game_state['user_id'])
348
-
349
  return game_state
350
 
351
  # ๐Ÿ… Display Scoreboard with Star Emojis and Buckyball Outline
@@ -390,7 +311,7 @@ def main():
390
  # ๐Ÿ Initialize game state
391
  if 'game_state' not in st.session_state:
392
  st.session_state.game_state = {
393
- 'user_id': None,
394
  'score': 0,
395
  'history': {},
396
  'gear_strength': 0,
@@ -404,38 +325,38 @@ def main():
404
  'succeeded': False
405
  }
406
 
407
- game_state = st.session_state.game_state
408
-
409
- # ๐Ÿฑ Cat Rider Selection or Loading Previous State
410
- if game_state['cat_rider'] is None:
411
- st.markdown("## Choose Your Cat Rider or Load Previous Journey:")
412
- # Check for existing histories
413
- existing_riders = [f.split('_')[1] for f in os.listdir('.') if f.startswith('history_')]
414
- existing_riders = list(set(existing_riders))
 
 
 
 
 
415
  cols = st.columns(len(CAT_RIDERS))
416
  for i, rider in enumerate(CAT_RIDERS):
417
  if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})", key=f"rider_{i}"):
418
- game_state['cat_rider'] = rider
419
- game_state['rider_skill'] = rider['skill']
420
- game_state['user_id'] = rider['name'] # Use rider name as user ID
421
-
422
- # Load existing history if available
423
- existing_history = load_saved_histories(game_state['user_id'])
424
- if existing_history:
425
- history_df = parse_history_markdown(existing_history)
426
- game_state['history_df'] = history_df
427
- game_state['score'] = history_df['score'].max() if not history_df.empty else 0
428
 
429
  # ๐Ÿ‡ Riding Gear Selection
430
- if game_state['riding_gear'] is None and game_state['cat_rider'] is not None:
431
  st.markdown("## Select Your Riding Gear:")
432
  cols = st.columns(len(RIDING_GEAR))
433
  for i, gear in enumerate(RIDING_GEAR):
434
  if cols[i].button(f"{gear['name']} ({gear['type']})", key=f"gear_{i}"):
435
- game_state['riding_gear'] = gear
436
- game_state['gear_strength'] = gear['strength']
437
 
438
  # ๐ŸŽญ Game Loop
 
 
439
  if game_state['cat_rider'] is not None and game_state['riding_gear'] is not None:
440
  # Check if current_situation is None or if the player succeeded in the previous situation
441
  if game_state['current_situation'] is None or game_state['succeeded']:
@@ -468,6 +389,7 @@ def main():
468
  st.markdown(f"**Success Chance:** {success_chance:.2f}%")
469
 
470
  if outcome:
 
471
  game_state['succeeded'] = True
472
  # Clear actions for next situation
473
  game_state['actions'] = []
@@ -506,21 +428,19 @@ def main():
506
 
507
  # Integration point for both functions
508
  if not game_state['history_df'].empty:
509
- # ๐Ÿ“ Process Journey History to get markdown and graph data
510
- markdown_preview, nodes, edges = process_journey_history(game_state['history_df'])
511
-
512
  # ๐Ÿ“ Display Markdown Preview
513
- st.markdown(markdown_preview)
514
 
515
  # ๐ŸŒณ Display Knowledge Journey Graph
516
  st.markdown("## ๐ŸŒณ Your Journey (Knowledge Graph)")
 
517
  try:
518
  streamlit_flow('cat_rider_flow',
519
  nodes,
520
  edges,
521
- layout=RadialLayout(),
522
  fit_view=True,
523
- height=1000)
524
  except Exception as e:
525
  st.error(f"An error occurred while rendering the journey graph: {str(e)}")
526
  st.markdown("Please try refreshing the page if the graph doesn't appear.")
@@ -532,12 +452,24 @@ def main():
532
  fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats ๐Ÿ“Š")
533
  st.plotly_chart(fig)
534
 
535
- # Automatically load saved history if available
536
- if game_state['user_id'] and not game_state['history_df'].empty:
537
- existing_history = load_saved_histories(game_state['user_id'])
538
- if existing_history:
539
- st.markdown("## ๐Ÿ“‚ Loaded Journey History")
540
- st.markdown(existing_history)
 
 
 
 
 
 
 
 
 
 
 
541
 
542
  if __name__ == "__main__":
543
  main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
  # Set page configuration to wide mode
3
  Site_Name = '๐ŸฆCatRider๐Ÿˆ'
 
20
  }
21
  )
22
 
23
+
24
+ import streamlit as st
25
+ import pandas as pd
26
+ import plotly.express as px
27
+ import random
28
+ import uuid
29
+ import os
30
+ from datetime import datetime
31
+ from streamlit_flow import streamlit_flow
32
+ from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
33
+ from streamlit_flow.layouts import TreeLayout
34
+
35
  # ๐Ÿฑ Cat Rider and Gear Data
36
  CAT_RIDERS = [
37
  {"name": "Whiskers", "type": "Speed", "emoji": "๐Ÿพ", "strength": 3, "skill": 7},
 
55
 
56
  # ๐ŸŒ Game World Data (Expanded to 10 Situations)
57
  SITUATIONS = [
58
+ {"id": "feline_escape", "name": "The Great Feline Escape", "description": "Your cat rider is trapped in an old mansion, which is about to be demolished. Using agility, wit, and bravery, orchestrate the perfect escape before the walls crumble! ๐Ÿš๏ธ", "emoji": "๐Ÿšช", "type": "escape", "preferred_action": "agility"},
59
+ {"id": "lost_temple", "name": "The Treasure of the Lost Temple", "description": "On a quest to retrieve an ancient artifact, your cat rider must navigate through a labyrinth filled with traps and guardian spirits. Don't let the spooky ghosts get you! ๐Ÿ‘ป", "emoji": "๐Ÿ›๏ธ", "type": "exploration", "preferred_action": "resourcefulness"},
60
+ {"id": "royal_tournament", "name": "The Royal Tournament", "description": "Compete in a grand tournament where the finest cat riders showcase their skills and bravery to earn the title of the Royal Rider. Prepare for a showdown with noble feline adversaries! ๐Ÿฑ", "emoji": "๐Ÿ‘‘", "type": "competition", "preferred_action": "bravery"},
61
+ {"id": "sky_race", "name": "The Sky Race", "description": "Compete in the annual Sky Race, where your cat rider flies across the skies on a magical broomstick! Watch out for lightning storms and mischievous crows! ๐ŸŒฉ๏ธ", "emoji": "โ˜๏ธ", "type": "competition", "preferred_action": "agility"},
62
+ {"id": "cheese_heist", "name": "The Great Cheese Heist", "description": "Your cat rider must sneak into the royal pantry to steal the legendary Cheese of Destiny. Beware โ€“ the palace mice are guarding it! ๐Ÿง€", "emoji": "๐Ÿง€", "type": "heist", "preferred_action": "stealth"},
63
+ {"id": "pirate_cove", "name": "The Pirate Cove", "description": "Sail the high seas with your trusty crew of cats and uncover the secrets of Pirate Cove. Beware of the treacherous Sea Dogs! ๐Ÿดโ€โ˜ ๏ธ", "emoji": "๐Ÿดโ€โ˜ ๏ธ", "type": "exploration", "preferred_action": "bravery"},
64
+ {"id": "feline_moon_mission", "name": "The Feline Moon Mission", "description": "Blast off into space! Your mission is to plant the flag of Catopia on the moon. Pilot your rocket through an asteroid field! ๐Ÿš€", "emoji": "๐ŸŒ•", "type": "exploration", "preferred_action": "resourcefulness"},
65
+ {"id": "purr_summit", "name": "The Purr Summit", "description": "Join a secret gathering of the most intellectual cats in the world. Engage in a battle of wits and wisdom to become the Grand Purr! ๐Ÿง ", "emoji": "๐Ÿ“œ", "type": "debate", "preferred_action": "insight"},
66
+ {"id": "feline_invasion", "name": "The Feline Invasion", "description": "Aliens have invaded Earth and only your cat rider can save the planet! Use cunning strategies to repel the invaders! ๐Ÿ‘ฝ", "emoji": "๐Ÿ‘ฝ", "type": "battle", "preferred_action": "strategy"},
67
+ {"id": "eternal_catnap", "name": "The Eternal Catnap", "description": "You've entered a sacred temple where cats nap for centuries. Can you navigate the dream world and escape before you too are lulled into eternal slumber? ๐Ÿ›๏ธ", "emoji": "๐Ÿ’ค", "type": "exploration", "preferred_action": "stealth"}
68
  ]
69
 
70
  # ๐Ÿง  Expanded Actions (10 Actions)
71
  ACTIONS = [
72
+ {"id": "stealth", "name": "Use Stealth", "description": "Sneak past obstacles or enemies without being detected. You're like a ninja in the shadows! ๐Ÿพ", "emoji": "๐Ÿคซ", "type": "skill"},
73
+ {"id": "agility", "name": "Showcase Agility", "description": "Perform impressive acrobatic maneuvers to overcome challenges. Cats always land on their feet, right? ๐Ÿƒ", "emoji": "๐Ÿƒ", "type": "physical"},
74
+ {"id": "charm", "name": "Charm Others", "description": "Use your cat's natural charisma to win over allies or distract foes. Who could resist those cute eyes? ๐Ÿ˜ป", "emoji": "๐Ÿ˜ป", "type": "social"},
75
+ {"id": "resourcefulness", "name": "Be Resourceful", "description": "Utilize the environment or items in creative ways to solve problems. Think on your paws! ๐Ÿง ", "emoji": "๐Ÿง ", "type": "mental"},
76
+ {"id": "bravery", "name": "Show Bravery", "description": "Face dangers head-on with your feline courage. Not all heroes wear capes โ€“ some wear fur! ๐Ÿฆ", "emoji": "๐Ÿฆ", "type": "physical"},
77
+ {"id": "strategy", "name": "Develop a Strategy", "description": "Use tactical thinking to outsmart opponents and gain the upper hand in battle. Brains over brawn! ๐Ÿง ", "emoji": "๐Ÿง ", "type": "mental"},
78
+ {"id": "speed", "name": "Sprint Away", "description": "Run faster than you've ever run before to escape danger. Like a cat fleeing a vacuum cleaner! ๐Ÿƒโ€โ™€๏ธ", "emoji": "๐Ÿƒโ€โ™€๏ธ", "type": "physical"},
79
+ {"id": "insight", "name": "Use Insight", "description": "Tap into ancient feline wisdom to solve puzzles and mysteries. A cat always knows! ๐Ÿ”ฎ", "emoji": "๐Ÿ”ฎ", "type": "mental"},
80
+ {"id": "distraction", "name": "Create a Distraction", "description": "Use cunning tricks and diversions to draw attention away from your real goal. Look over there! ๐Ÿช„", "emoji": "๐Ÿช„", "type": "mental"},
81
+ {"id": "negotiation", "name": "Negotiate", "description": "Use diplomacy and clever negotiation to get out of a tight spot. Every cat has their price! ๐Ÿ’ผ", "emoji": "๐Ÿ’ผ", "type": "social"}
82
  ]
83
 
84
  # Expanded conclusions for outcomes - 10 items each for success and failure
 
112
  def save_history_to_file(history_df, user_id):
113
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
114
  filename = f"history_{user_id}_{timestamp}.md"
115
+ markdown = create_markdown_preview(history_df)
116
  with open(filename, 'w', encoding='utf-8') as f:
117
  f.write(markdown)
118
  return filename
119
 
120
+ # Function to load saved histories
121
+ def load_saved_histories():
122
+ history_files = [f for f in os.listdir('.') if f.startswith('history_') and f.endswith('.md')]
123
+ return history_files
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
  # ๐Ÿง  Game Mechanics
126
  def generate_situation():
 
169
  game_state['gear_strength'] = max(1, game_state['gear_strength'] - 0.1)
170
  return game_state
171
 
172
+ # ๐ŸŒณ Journey Visualization
173
+ def create_knowledge_graph(history_df):
 
174
  nodes = []
175
  edges = []
176
  node_ids = {}
177
+ for index, row in history_df.iterrows():
178
+ situation_node_id = f"situation_{row['situation_id']}"
179
+ action_node_id = f"action_{index}"
180
 
181
+ # Situation node
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  if situation_node_id not in node_ids:
183
  situation_node = StreamlitFlowNode(
184
  situation_node_id,
185
  pos=(0, 0),
186
+ data={'content': f"{row['situation_emoji']} {row['situation_name']}"},
187
  type='default',
188
+ shape='ellipse'
 
 
189
  )
190
  nodes.append(situation_node)
191
  node_ids[situation_node_id] = situation_node_id
192
 
193
+ # Attempt node (action and outcome)
194
+ outcome_content = 'โœ… Success' if row['outcome'] else 'โŒ Failure'
195
+ stars = 'โญ' * int(row['score'])
196
+ attempt_node = StreamlitFlowNode(
197
+ action_node_id,
198
+ pos=(0, 0),
199
+ data={'content': f"{row['action_emoji']} {row['action_name']} ({outcome_content})\n{row['conclusion']}\n{stars}"},
200
+ type='default',
201
+ shape='rectangle'
202
+ )
203
+ nodes.append(attempt_node)
204
+
205
+ # Edge from situation to attempt
206
+ edges.append(StreamlitFlowEdge(
207
+ id=f"edge_{situation_node_id}_{action_node_id}",
208
+ source=situation_node_id,
209
+ target=action_node_id,
210
+ animated=True
211
+ ))
212
+
213
+ return nodes, edges
214
+
215
+ # ๐Ÿ“ Markdown Preview with Subpoints for Each Action
216
+ def create_markdown_preview(history_df):
217
+ markdown = "## ๐ŸŒณ Journey Preview\n\n"
218
+ grouped = history_df.groupby(['situation_name'], sort=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
+ for situation_name, group in grouped:
221
+ markdown += f"### {group.iloc[0]['situation_emoji']} **{situation_name}**\n"
222
+ for _, row in group.iterrows():
223
+ outcome_str = 'โœ… Success' if row['outcome'] else 'โŒ Failure'
224
+ stars = 'โญ' * int(row['score'])
225
+ markdown += f"- Attempt {row['attempt']}: {row['action_emoji']} **{row['action_name']}**: {outcome_str} {stars}\n"
226
+ markdown += f" - {row['conclusion']}\n"
227
  markdown += "\n"
228
+ return markdown
 
229
 
230
  # ๐Ÿ”„ Update game state with the result of the action
231
  def update_game_state(game_state, situation, action, outcome, timestamp):
 
238
  # Update attempt count
239
  attempt = game_state['current_attempt']
240
 
 
 
 
 
241
  # Create a new record for the history
242
  new_record = pd.DataFrame({
243
  'user_id': [game_state['user_id']],
 
267
  else:
268
  game_state['history'][action['id']] = 1 if outcome else -1
269
 
 
 
 
270
  return game_state
271
 
272
  # ๐Ÿ… Display Scoreboard with Star Emojis and Buckyball Outline
 
311
  # ๐Ÿ Initialize game state
312
  if 'game_state' not in st.session_state:
313
  st.session_state.game_state = {
314
+ 'user_id': str(uuid.uuid4()),
315
  'score': 0,
316
  'history': {},
317
  'gear_strength': 0,
 
325
  'succeeded': False
326
  }
327
 
328
+ # Sidebar functionality
329
+ st.sidebar.header("๐Ÿ“‚ Saved Histories")
330
+ history_files = load_saved_histories()
331
+ if history_files:
332
+ selected_history = st.sidebar.selectbox("Select a history to load:", history_files)
333
+ if st.sidebar.button("Load Selected History"):
334
+ with open(selected_history, 'r', encoding='utf-8') as f:
335
+ st.session_state.game_state['loaded_history'] = f.read()
336
+ st.sidebar.success(f"Loaded {selected_history}")
337
+
338
+ # ๐Ÿฑ Cat Rider Selection
339
+ if st.session_state.game_state['cat_rider'] is None:
340
+ st.markdown("## Choose Your Cat Rider:")
341
  cols = st.columns(len(CAT_RIDERS))
342
  for i, rider in enumerate(CAT_RIDERS):
343
  if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})", key=f"rider_{i}"):
344
+ st.session_state.game_state['cat_rider'] = rider
345
+ st.session_state.game_state['rider_skill'] = rider['skill']
346
+ st.session_state.game_state['user_id'] = rider['name'] # Use rider name as user ID
 
 
 
 
 
 
 
347
 
348
  # ๐Ÿ‡ Riding Gear Selection
349
+ if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None:
350
  st.markdown("## Select Your Riding Gear:")
351
  cols = st.columns(len(RIDING_GEAR))
352
  for i, gear in enumerate(RIDING_GEAR):
353
  if cols[i].button(f"{gear['name']} ({gear['type']})", key=f"gear_{i}"):
354
+ st.session_state.game_state['riding_gear'] = gear
355
+ st.session_state.game_state['gear_strength'] = gear['strength']
356
 
357
  # ๐ŸŽญ Game Loop
358
+ game_state = st.session_state.game_state
359
+
360
  if game_state['cat_rider'] is not None and game_state['riding_gear'] is not None:
361
  # Check if current_situation is None or if the player succeeded in the previous situation
362
  if game_state['current_situation'] is None or game_state['succeeded']:
 
389
  st.markdown(f"**Success Chance:** {success_chance:.2f}%")
390
 
391
  if outcome:
392
+ game_state['score'] += 1
393
  game_state['succeeded'] = True
394
  # Clear actions for next situation
395
  game_state['actions'] = []
 
428
 
429
  # Integration point for both functions
430
  if not game_state['history_df'].empty:
 
 
 
431
  # ๐Ÿ“ Display Markdown Preview
432
+ st.markdown(create_markdown_preview(game_state['history_df']))
433
 
434
  # ๐ŸŒณ Display Knowledge Journey Graph
435
  st.markdown("## ๐ŸŒณ Your Journey (Knowledge Graph)")
436
+ nodes, edges = create_knowledge_graph(game_state['history_df'])
437
  try:
438
  streamlit_flow('cat_rider_flow',
439
  nodes,
440
  edges,
441
+ layout=TreeLayout(direction='down'),
442
  fit_view=True,
443
+ height=600)
444
  except Exception as e:
445
  st.error(f"An error occurred while rendering the journey graph: {str(e)}")
446
  st.markdown("Please try refreshing the page if the graph doesn't appear.")
 
452
  fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats ๐Ÿ“Š")
453
  st.plotly_chart(fig)
454
 
455
+ # Save history to file
456
+ if st.button("๐Ÿ’พ Save Game History"):
457
+ filename = save_history_to_file(game_state['history_df'], game_state['user_id'])
458
+ st.success(f"History saved to {filename}")
459
+ # Update history files list
460
+ history_files = load_saved_histories()
461
+
462
+ # Provide download buttons for saved histories
463
+ st.sidebar.markdown("### ๐Ÿ“ฅ Download Histories")
464
+ for history_file in history_files:
465
+ with open(history_file, 'r', encoding='utf-8') as f:
466
+ st.sidebar.download_button(
467
+ label=f"Download {history_file}",
468
+ data=f.read(),
469
+ file_name=history_file,
470
+ mime='text/markdown'
471
+ )
472
 
473
  if __name__ == "__main__":
474
  main()
475
+