awacke1 commited on
Commit
dd5d5b4
Β·
verified Β·
1 Parent(s): 119c81d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -50
app.py CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
3
  import plotly.express as px
4
  import random
5
  import uuid
 
6
  from datetime import datetime
7
  from streamlit_flow import streamlit_flow
8
  from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
@@ -13,7 +14,13 @@ CAT_RIDERS = [
13
  {"name": "Whiskers", "type": "Speed", "emoji": "🐾", "strength": 3, "skill": 7},
14
  {"name": "Fluffy", "type": "Bravery", "emoji": "🦁", "strength": 5, "skill": 5},
15
  {"name": "Midnight", "type": "Stealth", "emoji": "πŸŒ‘", "strength": 4, "skill": 6},
16
- {"name": "Bella", "type": "Charm", "emoji": "😺", "strength": 2, "skill": 8}
 
 
 
 
 
 
17
  ]
18
 
19
  RIDING_GEAR = [
@@ -78,6 +85,20 @@ FAILURE_CONCLUSIONS = [
78
  "It’s okay, every cat has a learning curve. πŸ“š"
79
  ]
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  # 🧠 Game Mechanics
82
  def generate_situation():
83
  return random.choice(SITUATIONS)
@@ -86,16 +107,24 @@ def generate_actions():
86
  return random.sample(ACTIONS, min(3, len(ACTIONS)))
87
 
88
  def evaluate_action(situation, action, gear_strength, rider_skill, history):
89
- # Determine if the action is the preferred action
90
- base_success_chance = (gear_strength + rider_skill) / 2
 
 
 
 
 
 
91
  if action['id'] == situation['preferred_action']:
92
- success_chance = base_success_chance + 30 # Boost success chance for preferred action
93
- else:
94
- success_chance = base_success_chance
95
 
 
96
  if action['id'] in history:
97
  success_chance += history[action['id']] * 2
98
 
 
 
 
99
  outcome = random.randint(1, 100) <= success_chance
100
  return outcome, success_chance
101
 
@@ -123,7 +152,7 @@ def create_heterogeneous_graph(history_df):
123
  edges = []
124
  node_ids = {}
125
  for index, row in history_df.iterrows():
126
- situation_node_id = f"situation_{row['situation_id']}_{index}"
127
  action_node_id = f"action_{row['action_id']}_{index}"
128
  outcome_node_id = f"outcome_{index}"
129
 
@@ -186,10 +215,10 @@ def create_heterogeneous_graph(history_df):
186
  # πŸ“ Markdown Preview with Subpoints for Each Action
187
  def create_markdown_preview(history_df):
188
  markdown = "## 🌳 Journey Preview\n\n"
189
- grouped = history_df.groupby('situation_name', sort=False)
190
 
191
- for situation_name, group in grouped:
192
- markdown += f"### {group.iloc[0]['situation_emoji']} **{situation_name}**\n"
193
  for _, row in group.iterrows():
194
  outcome_str = 'βœ… Success' if row['outcome'] else '❌ Failure'
195
  stars = '⭐' * int(row['score'])
@@ -206,6 +235,9 @@ def update_game_state(game_state, situation, action, outcome, timestamp):
206
  # Update stats based on the outcome
207
  game_state = update_character_stats(game_state, outcome)
208
 
 
 
 
209
  # Create a new record for the history
210
  new_record = pd.DataFrame({
211
  'user_id': [game_state['user_id']],
@@ -214,6 +246,7 @@ def update_game_state(game_state, situation, action, outcome, timestamp):
214
  'situation_name': [situation['name']],
215
  'situation_emoji': [situation['emoji']],
216
  'situation_type': [situation['type']],
 
217
  'action_id': [action['id']],
218
  'action_name': [action['name']],
219
  'action_emoji': [action['emoji']],
@@ -285,9 +318,22 @@ def main():
285
  'rider_skill': 0,
286
  'cat_rider': None,
287
  'riding_gear': None,
288
- 'history_df': pd.DataFrame(columns=['user_id', 'timestamp', 'situation_id', 'situation_name', 'situation_emoji', 'situation_type', 'action_id', 'action_name', 'action_emoji', 'action_type', 'outcome', 'conclusion', 'gear_strength', 'rider_skill', 'score'])
 
 
 
289
  }
290
 
 
 
 
 
 
 
 
 
 
 
291
  # 🐱 Cat Rider Selection
292
  if st.session_state.game_state['cat_rider'] is None:
293
  st.markdown("## Choose Your Cat Rider:")
@@ -296,6 +342,7 @@ def main():
296
  if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})", key=f"rider_{i}"):
297
  st.session_state.game_state['cat_rider'] = rider
298
  st.session_state.game_state['rider_skill'] = rider['skill']
 
299
 
300
  # πŸ‡ Riding Gear Selection
301
  if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None:
@@ -307,18 +354,30 @@ def main():
307
  st.session_state.game_state['gear_strength'] = gear['strength']
308
 
309
  # 🎭 Game Loop
310
- if st.session_state.game_state['cat_rider'] is not None and st.session_state.game_state['riding_gear'] is not None:
311
- situation = generate_situation()
312
- actions = generate_actions()
313
 
 
 
 
 
 
 
 
 
 
314
  st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
315
  st.markdown(situation['description'])
316
  st.markdown("### 🎭 Choose your action:")
317
 
 
 
 
 
318
  cols = st.columns(3)
319
- for i, action in enumerate(actions):
320
- if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})", key=f"action_{i}"):
321
- outcome, success_chance = evaluate_action(situation, action, st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill'], st.session_state.game_state['history'])
 
322
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
323
 
324
  st.markdown(f"You decided to: **{action['name']}** ({action['type']})")
@@ -327,11 +386,18 @@ def main():
327
  st.markdown(f"**Success Chance:** {success_chance:.2f}%")
328
 
329
  if outcome:
330
- st.session_state.game_state['score'] += 1
 
 
 
 
 
 
 
331
 
332
  # πŸ”„ Update game state
333
- st.session_state.game_state = update_game_state(
334
- st.session_state.game_state,
335
  situation,
336
  action,
337
  outcome,
@@ -339,42 +405,65 @@ def main():
339
  )
340
 
341
  # Display conclusion
342
- conclusion = st.session_state.game_state['history_df'].iloc[-1]['conclusion']
343
  st.markdown(f"**Encounter Conclusion:** {conclusion}")
344
 
345
  # Display updated stats
346
  st.markdown(f"**Updated Stats:**")
347
- st.markdown(f"πŸ’ͺ Gear Strength: {st.session_state.game_state['gear_strength']:.2f}")
348
- st.markdown(f"πŸ‹οΈ Rider Skill: {st.session_state.game_state['rider_skill']:.2f}")
349
 
350
  # πŸ… Display Scoreboard
351
- display_scoreboard(st.session_state.game_state)
352
-
353
- # Integration point for both functions
354
- if not st.session_state.game_state['history_df'].empty:
355
- # πŸ“ Display Markdown Preview
356
- st.markdown(create_markdown_preview(st.session_state.game_state['history_df']))
357
-
358
- # 🌳 Display Heterogeneous Journey Graph
359
- st.markdown("## 🌳 Your Journey (Heterogeneous Graph)")
360
- nodes, edges = create_heterogeneous_graph(st.session_state.game_state['history_df'])
361
- try:
362
- streamlit_flow('cat_rider_flow',
363
- nodes,
364
- edges,
365
- layout=TreeLayout(direction='down'),
366
- fit_view=True,
367
- height=600)
368
- except Exception as e:
369
- st.error(f"An error occurred while rendering the journey graph: {str(e)}")
370
- st.markdown("Please try refreshing the page if the graph doesn't appear.")
371
-
372
- # πŸ“Š Character Stats Visualization
373
- data = {"Stat": ["Gear Strength πŸ›‘οΈ", "Rider Skill πŸ‡"],
374
- "Value": [st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill']]}
375
- df = pd.DataFrame(data)
376
- fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats πŸ“Š")
377
- st.plotly_chart(fig)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
 
379
  if __name__ == "__main__":
380
  main()
 
3
  import plotly.express as px
4
  import random
5
  import uuid
6
+ import os
7
  from datetime import datetime
8
  from streamlit_flow import streamlit_flow
9
  from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
 
14
  {"name": "Whiskers", "type": "Speed", "emoji": "🐾", "strength": 3, "skill": 7},
15
  {"name": "Fluffy", "type": "Bravery", "emoji": "🦁", "strength": 5, "skill": 5},
16
  {"name": "Midnight", "type": "Stealth", "emoji": "πŸŒ‘", "strength": 4, "skill": 6},
17
+ {"name": "Bella", "type": "Charm", "emoji": "😺", "strength": 2, "skill": 8},
18
+ {"name": "Shadow", "type": "Mystery", "emoji": "πŸ‘€", "strength": 4, "skill": 6},
19
+ {"name": "Simba", "type": "Royalty", "emoji": "🦁", "strength": 5, "skill": 7},
20
+ {"name": "Luna", "type": "Magic", "emoji": "πŸŒ™", "strength": 3, "skill": 8},
21
+ {"name": "Leo", "type": "Courage", "emoji": "🐯", "strength": 6, "skill": 5},
22
+ {"name": "Milo", "type": "Playful", "emoji": "😼", "strength": 4, "skill": 7},
23
+ {"name": "Nala", "type": "Grace", "emoji": "🐈", "strength": 5, "skill": 6}
24
  ]
25
 
26
  RIDING_GEAR = [
 
85
  "It’s okay, every cat has a learning curve. πŸ“š"
86
  ]
87
 
88
+ # Function to save history to a markdown file
89
+ def save_history_to_file(history_df, user_id, scenario_name):
90
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
91
+ filename = f"history_{user_id}_{scenario_name}_{timestamp}.md"
92
+ markdown = create_markdown_preview(history_df)
93
+ with open(filename, 'w', encoding='utf-8') as f:
94
+ f.write(markdown)
95
+ return filename
96
+
97
+ # Function to load saved histories
98
+ def load_saved_histories():
99
+ history_files = [f for f in os.listdir('.') if f.startswith('history_') and f.endswith('.md')]
100
+ return history_files
101
+
102
  # 🧠 Game Mechanics
103
  def generate_situation():
104
  return random.choice(SITUATIONS)
 
107
  return random.sample(ACTIONS, min(3, len(ACTIONS)))
108
 
109
  def evaluate_action(situation, action, gear_strength, rider_skill, history):
110
+ # Adjusted base success chance to around 50%
111
+ base_success_chance = 50
112
+
113
+ # Adjust success chance based on gear strength and rider skill
114
+ stat_modifier = (gear_strength + rider_skill - 10) * 2 # Assuming average stats sum to 10
115
+ success_chance = base_success_chance + stat_modifier
116
+
117
+ # Boost success chance for preferred action
118
  if action['id'] == situation['preferred_action']:
119
+ success_chance += 10
 
 
120
 
121
+ # Adjust based on action history
122
  if action['id'] in history:
123
  success_chance += history[action['id']] * 2
124
 
125
+ # Clamp success chance between 5% and 95%
126
+ success_chance = max(5, min(95, success_chance))
127
+
128
  outcome = random.randint(1, 100) <= success_chance
129
  return outcome, success_chance
130
 
 
152
  edges = []
153
  node_ids = {}
154
  for index, row in history_df.iterrows():
155
+ situation_node_id = f"situation_{row['situation_id']}_{row['attempt']}"
156
  action_node_id = f"action_{row['action_id']}_{index}"
157
  outcome_node_id = f"outcome_{index}"
158
 
 
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', 'attempt'], sort=False)
219
 
220
+ for (situation_name, attempt), group in grouped:
221
+ markdown += f"### {group.iloc[0]['situation_emoji']} **{situation_name}** (Attempt {attempt})\n"
222
  for _, row in group.iterrows():
223
  outcome_str = 'βœ… Success' if row['outcome'] else '❌ Failure'
224
  stars = '⭐' * int(row['score'])
 
235
  # Update stats based on the outcome
236
  game_state = update_character_stats(game_state, outcome)
237
 
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']],
 
246
  'situation_name': [situation['name']],
247
  'situation_emoji': [situation['emoji']],
248
  'situation_type': [situation['type']],
249
+ 'attempt': [attempt],
250
  'action_id': [action['id']],
251
  'action_name': [action['name']],
252
  'action_emoji': [action['emoji']],
 
318
  'rider_skill': 0,
319
  'cat_rider': None,
320
  'riding_gear': None,
321
+ 'history_df': pd.DataFrame(columns=['user_id', 'timestamp', 'situation_id', 'situation_name', 'situation_emoji', 'situation_type', 'attempt', 'action_id', 'action_name', 'action_emoji', 'action_type', 'outcome', 'conclusion', 'gear_strength', 'rider_skill', 'score']),
322
+ 'current_situation': None,
323
+ 'current_attempt': 1,
324
+ 'actions': []
325
  }
326
 
327
+ # Sidebar functionality
328
+ st.sidebar.header("πŸ“‚ Saved Histories")
329
+ history_files = load_saved_histories()
330
+ if history_files:
331
+ selected_history = st.sidebar.selectbox("Select a history to load:", history_files)
332
+ if st.sidebar.button("Load Selected History"):
333
+ with open(selected_history, 'r', encoding='utf-8') as f:
334
+ st.session_state.game_state['loaded_history'] = f.read()
335
+ st.sidebar.success(f"Loaded {selected_history}")
336
+
337
  # 🐱 Cat Rider Selection
338
  if st.session_state.game_state['cat_rider'] is None:
339
  st.markdown("## Choose Your Cat Rider:")
 
342
  if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})", key=f"rider_{i}"):
343
  st.session_state.game_state['cat_rider'] = rider
344
  st.session_state.game_state['rider_skill'] = rider['skill']
345
+ st.session_state.game_state['user_id'] = rider['name'] # Use rider name as user ID
346
 
347
  # πŸ‡ Riding Gear Selection
348
  if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None:
 
354
  st.session_state.game_state['gear_strength'] = gear['strength']
355
 
356
  # 🎭 Game Loop
357
+ game_state = st.session_state.game_state
 
 
358
 
359
+ if game_state['cat_rider'] is not None and game_state['riding_gear'] is not None:
360
+ # Check if current_situation is None or if the player succeeded in the previous situation
361
+ if game_state['current_situation'] is None or game_state['succeeded']:
362
+ # Generate a new situation
363
+ game_state['current_situation'] = generate_situation()
364
+ game_state['current_attempt'] = 1
365
+ game_state['succeeded'] = False
366
+
367
+ situation = game_state['current_situation']
368
  st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
369
  st.markdown(situation['description'])
370
  st.markdown("### 🎭 Choose your action:")
371
 
372
+ # Generate actions if not already generated
373
+ if not game_state['actions']:
374
+ game_state['actions'] = generate_actions()
375
+
376
  cols = st.columns(3)
377
+ action_chosen = False
378
+ for i, action in enumerate(game_state['actions']):
379
+ if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})", key=f"action_{i}_{game_state['current_attempt']}"):
380
+ outcome, success_chance = evaluate_action(situation, action, game_state['gear_strength'], game_state['rider_skill'], game_state['history'])
381
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
382
 
383
  st.markdown(f"You decided to: **{action['name']}** ({action['type']})")
 
386
  st.markdown(f"**Success Chance:** {success_chance:.2f}%")
387
 
388
  if outcome:
389
+ game_state['score'] += 1
390
+ game_state['succeeded'] = True
391
+ # Clear actions for next situation
392
+ game_state['actions'] = []
393
+ else:
394
+ game_state['current_attempt'] += 1
395
+ # Generate new actions for retry
396
+ game_state['actions'] = generate_actions()
397
 
398
  # πŸ”„ Update game state
399
+ game_state = update_game_state(
400
+ game_state,
401
  situation,
402
  action,
403
  outcome,
 
405
  )
406
 
407
  # Display conclusion
408
+ conclusion = game_state['history_df'].iloc[-1]['conclusion']
409
  st.markdown(f"**Encounter Conclusion:** {conclusion}")
410
 
411
  # Display updated stats
412
  st.markdown(f"**Updated Stats:**")
413
+ st.markdown(f"πŸ’ͺ Gear Strength: {game_state['gear_strength']:.2f}")
414
+ st.markdown(f"πŸ‹οΈ Rider Skill: {game_state['rider_skill']:.2f}")
415
 
416
  # πŸ… Display Scoreboard
417
+ display_scoreboard(game_state)
418
+
419
+ action_chosen = True
420
+ break # Exit the loop after action is taken
421
+
422
+ # If no action was chosen, show a message
423
+ if not action_chosen:
424
+ st.markdown("Please choose an action to proceed.")
425
+
426
+ # Integration point for both functions
427
+ if not game_state['history_df'].empty:
428
+ # πŸ“ Display Markdown Preview
429
+ st.markdown(create_markdown_preview(game_state['history_df']))
430
+
431
+ # 🌳 Display Heterogeneous Journey Graph
432
+ st.markdown("## 🌳 Your Journey (Heterogeneous Graph)")
433
+ nodes, edges = create_heterogeneous_graph(game_state['history_df'])
434
+ try:
435
+ streamlit_flow('cat_rider_flow',
436
+ nodes,
437
+ edges,
438
+ layout=TreeLayout(direction='down'),
439
+ fit_view=True,
440
+ height=600)
441
+ except Exception as e:
442
+ st.error(f"An error occurred while rendering the journey graph: {str(e)}")
443
+ st.markdown("Please try refreshing the page if the graph doesn't appear.")
444
+
445
+ # πŸ“Š Character Stats Visualization
446
+ data = {"Stat": ["Gear Strength πŸ›‘οΈ", "Rider Skill πŸ‡"],
447
+ "Value": [game_state['gear_strength'], game_state['rider_skill']]}
448
+ df = pd.DataFrame(data)
449
+ fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats πŸ“Š")
450
+ st.plotly_chart(fig)
451
+
452
+ # Save history to file
453
+ if st.button("πŸ’Ύ Save Game History"):
454
+ filename = save_history_to_file(game_state['history_df'], game_state['user_id'], situation['name'])
455
+ st.success(f"History saved to {filename}")
456
+
457
+ # Provide download button for saved history
458
+ st.sidebar.markdown("### πŸ“₯ Download Histories")
459
+ for history_file in history_files:
460
+ with open(history_file, 'r', encoding='utf-8') as f:
461
+ st.sidebar.download_button(
462
+ label=f"Download {history_file}",
463
+ data=f.read(),
464
+ file_name=history_file,
465
+ mime='text/markdown'
466
+ )
467
 
468
  if __name__ == "__main__":
469
  main()