Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
|
|
|
2 |
import streamlit as st
|
3 |
import pandas as pd
|
4 |
import plotly.express as px
|
@@ -8,16 +9,16 @@ import os
|
|
8 |
from datetime import datetime
|
9 |
from streamlit_flow import streamlit_flow
|
10 |
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
|
11 |
-
from streamlit_flow.layouts import TreeLayout
|
12 |
|
13 |
# Set page configuration to wide mode
|
14 |
Site_Name = '🦁CatRider🐈'
|
15 |
-
title="🦁CatRider🐈by👤Aaron Wacker"
|
16 |
-
helpURL='https://huggingface.co/awacke1'
|
17 |
-
bugURL='https://huggingface.co/spaces/awacke1'
|
18 |
-
icons='🦁'
|
19 |
|
20 |
-
useConfig=True
|
21 |
if useConfig:
|
22 |
st.set_page_config(
|
23 |
page_title=title,
|
@@ -81,32 +82,9 @@ ACTIONS = [
|
|
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
|
85 |
-
SUCCESS_CONCLUSIONS = [
|
86 |
-
"Your swift paws led you to victory! 🎉",
|
87 |
-
"You pounced at the perfect moment! 🏆",
|
88 |
-
"The stars aligned for your cat rider! 🌟",
|
89 |
-
"You navigated the challenge like a true feline champion! 🐱",
|
90 |
-
"Victory is sweet, just like a bowl of fresh milk! 🥛",
|
91 |
-
"Your opponents are left in awe of your skills! 😺",
|
92 |
-
"You’ve earned the title of Cat Commander! 🏅",
|
93 |
-
"All the other cats are jealous of your agility! 🏃♂️",
|
94 |
-
"Your strategy was flawless, and the victory is yours! 🎖️",
|
95 |
-
"Your cat rider is now a legend in the feline world! 👑"
|
96 |
-
]
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
"Maybe next time, kitty. Keep your tail up! 🐾",
|
101 |
-
"That didn’t go as planned. Time for a catnap to recover! 💤",
|
102 |
-
"Even the best cats have their off days. 😔",
|
103 |
-
"The challenge was too great this time. Better luck next time! 🍀",
|
104 |
-
"You might need more than nine lives to get through this. 🐈",
|
105 |
-
"The enemy was too clever for your plan. 🧠",
|
106 |
-
"You tripped over your own paws! 🐾",
|
107 |
-
"The cat gods were not in your favor today. 🙀",
|
108 |
-
"It’s okay, every cat has a learning curve. 📚"
|
109 |
-
]
|
110 |
|
111 |
# Function to save history to a markdown file
|
112 |
def save_history_to_file(history_df, user_id):
|
@@ -122,54 +100,50 @@ 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 |
-
#
|
126 |
def generate_situation():
|
127 |
return random.choice(SITUATIONS)
|
128 |
|
|
|
129 |
def generate_actions():
|
130 |
return random.sample(ACTIONS, min(3, len(ACTIONS)))
|
131 |
|
|
|
132 |
def evaluate_action(situation, action, gear_strength, rider_skill, history):
|
133 |
-
# Adjusted base success chance to around 50%
|
134 |
base_success_chance = 50
|
135 |
-
|
136 |
-
# Adjust success chance based on gear strength and rider skill
|
137 |
-
stat_modifier = (gear_strength + rider_skill - 10) * 2 # Assuming average stats sum to 10
|
138 |
success_chance = base_success_chance + stat_modifier
|
139 |
-
|
140 |
-
# Boost success chance for preferred action
|
141 |
if action['id'] == situation['preferred_action']:
|
142 |
success_chance += 10
|
143 |
-
|
144 |
-
# Adjust based on action history
|
145 |
-
if action['id'] in history:
|
146 |
-
success_chance += history[action['id']] * 2
|
147 |
-
|
148 |
-
# Clamp success chance between 5% and 95%
|
149 |
success_chance = max(5, min(95, success_chance))
|
150 |
-
|
151 |
outcome = random.randint(1, 100) <= success_chance
|
152 |
return outcome, success_chance
|
153 |
|
154 |
-
|
155 |
-
if outcome:
|
156 |
-
return random.choice(SUCCESS_CONCLUSIONS)
|
157 |
-
else:
|
158 |
-
return random.choice(FAILURE_CONCLUSIONS)
|
159 |
-
|
160 |
-
# 🔄 Update character stats based on outcome
|
161 |
def update_character_stats(game_state, outcome):
|
162 |
if outcome:
|
163 |
-
# Increase stats on success
|
164 |
game_state['rider_skill'] += 0.5
|
165 |
game_state['gear_strength'] += 0.2
|
166 |
else:
|
167 |
-
# Decrease stats on failure, but not below 1
|
168 |
game_state['rider_skill'] = max(1, game_state['rider_skill'] - 0.3)
|
169 |
game_state['gear_strength'] = max(1, game_state['gear_strength'] - 0.1)
|
170 |
return game_state
|
171 |
|
172 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
def create_knowledge_graph(history_df):
|
174 |
nodes = []
|
175 |
edges = []
|
@@ -178,27 +152,38 @@ def create_knowledge_graph(history_df):
|
|
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':
|
200 |
type='default',
|
201 |
-
shape='rectangle'
|
|
|
202 |
)
|
203 |
nodes.append(attempt_node)
|
204 |
|
@@ -212,103 +197,11 @@ def create_knowledge_graph(history_df):
|
|
212 |
|
213 |
return nodes, edges
|
214 |
|
215 |
-
#
|
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):
|
232 |
-
# Generate the encounter conclusion (success or failure)
|
233 |
-
conclusion = generate_encounter_conclusion(situation, action, outcome)
|
234 |
-
|
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']],
|
244 |
-
'timestamp': [timestamp],
|
245 |
-
'situation_id': [situation['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']],
|
253 |
-
'action_type': [action['type']],
|
254 |
-
'outcome': [outcome],
|
255 |
-
'conclusion': [conclusion],
|
256 |
-
'gear_strength': [game_state['gear_strength']],
|
257 |
-
'rider_skill': [game_state['rider_skill']],
|
258 |
-
'score': [game_state['score']]
|
259 |
-
})
|
260 |
-
|
261 |
-
# Add the new record to the game history DataFrame
|
262 |
-
game_state['history_df'] = pd.concat([game_state['history_df'], new_record], ignore_index=True)
|
263 |
-
|
264 |
-
# Update the history of actions (tracking how many times each action was used)
|
265 |
-
if action['id'] in game_state['history']:
|
266 |
-
game_state['history'][action['id']] += 1 if outcome else -1
|
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
|
273 |
-
def display_scoreboard(game_state):
|
274 |
-
# Calculate number of star emojis based on score
|
275 |
-
score = game_state['score']
|
276 |
-
stars = '⭐' * int(score)
|
277 |
-
|
278 |
-
# Create buckyball style outline (simplified)
|
279 |
-
outline = ''
|
280 |
-
if score > 0:
|
281 |
-
outline = '''
|
282 |
-
⬡ ⬡ ⬡ ⬡ ⬡
|
283 |
-
⬡ ⬡ ⬡ ⬡
|
284 |
-
⬡ ⬡ ⬡ ⬡ ⬡
|
285 |
-
⬡ ⬡ ⬡ ⬡
|
286 |
-
⬡ ⬡ ⬡ ⬡ ⬡
|
287 |
-
'''
|
288 |
-
else:
|
289 |
-
outline = 'No successes yet.'
|
290 |
-
|
291 |
-
st.markdown("## 🏅 Scoreboard")
|
292 |
-
st.markdown(f"**Score:** {stars} ({score})")
|
293 |
-
st.markdown(outline)
|
294 |
-
|
295 |
-
# 🎮 Main Game Application
|
296 |
def main():
|
297 |
st.title("🐱 Cat Rider 🏇")
|
298 |
|
299 |
-
#
|
300 |
-
st.markdown("""
|
301 |
-
### 📜 Game Rules
|
302 |
-
| Step | Description |
|
303 |
-
|------|-------------|
|
304 |
-
| 1️⃣ | Choose your Cat Rider |
|
305 |
-
| 2️⃣ | Select your Riding Gear |
|
306 |
-
| 3️⃣ | Set off on an Adventure |
|
307 |
-
| 4️⃣ | Encounter Challenges and Make Decisions |
|
308 |
-
| 5️⃣ | Complete the Quest and Grow Stronger |
|
309 |
-
""")
|
310 |
-
|
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()),
|
@@ -325,150 +218,20 @@ def main():
|
|
325 |
'succeeded': False
|
326 |
}
|
327 |
|
328 |
-
#
|
329 |
-
|
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 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
situation = game_state['current_situation']
|
371 |
-
st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
|
372 |
-
st.markdown(situation['description'])
|
373 |
-
st.markdown("### 🎭 Choose your action:")
|
374 |
-
|
375 |
-
# Generate actions if not already generated
|
376 |
-
if not game_state['actions']:
|
377 |
-
game_state['actions'] = generate_actions()
|
378 |
-
|
379 |
-
cols = st.columns(3)
|
380 |
-
action_chosen = False
|
381 |
-
for i, action in enumerate(game_state['actions']):
|
382 |
-
if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})", key=f"action_{i}_{game_state['current_attempt']}"):
|
383 |
-
outcome, success_chance = evaluate_action(situation, action, game_state['gear_strength'], game_state['rider_skill'], game_state['history'])
|
384 |
-
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
385 |
-
|
386 |
-
st.markdown(f"You decided to: **{action['name']}** ({action['type']})")
|
387 |
-
st.markdown(action['description'])
|
388 |
-
st.markdown(f"**Outcome:** {'✅ Success!' if outcome else '❌ Failure.'}")
|
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'] = []
|
396 |
-
else:
|
397 |
-
game_state['current_attempt'] += 1
|
398 |
-
# Generate new actions for retry
|
399 |
-
game_state['actions'] = generate_actions()
|
400 |
-
|
401 |
-
# 🔄 Update game state
|
402 |
-
game_state = update_game_state(
|
403 |
-
game_state,
|
404 |
-
situation,
|
405 |
-
action,
|
406 |
-
outcome,
|
407 |
-
timestamp
|
408 |
-
)
|
409 |
-
|
410 |
-
# Display conclusion
|
411 |
-
conclusion = game_state['history_df'].iloc[-1]['conclusion']
|
412 |
-
st.markdown(f"**Encounter Conclusion:** {conclusion}")
|
413 |
-
|
414 |
-
# Display updated stats
|
415 |
-
st.markdown(f"**Updated Stats:**")
|
416 |
-
st.markdown(f"💪 Gear Strength: {game_state['gear_strength']:.2f}")
|
417 |
-
st.markdown(f"🏋️ Rider Skill: {game_state['rider_skill']:.2f}")
|
418 |
-
|
419 |
-
# 🏅 Display Scoreboard
|
420 |
-
display_scoreboard(game_state)
|
421 |
-
|
422 |
-
action_chosen = True
|
423 |
-
break # Exit the loop after action is taken
|
424 |
-
|
425 |
-
# If no action was chosen, show a message
|
426 |
-
if not action_chosen:
|
427 |
-
st.markdown("Please choose an action to proceed.")
|
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.")
|
447 |
-
|
448 |
-
# 📊 Character Stats Visualization
|
449 |
-
data = {"Stat": ["Gear Strength 🛡️", "Rider Skill 🏇"],
|
450 |
-
"Value": [game_state['gear_strength'], game_state['rider_skill']]}
|
451 |
-
df = pd.DataFrame(data)
|
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()
|
|
|
1 |
|
2 |
+
|
3 |
import streamlit as st
|
4 |
import pandas as pd
|
5 |
import plotly.express as px
|
|
|
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 TreeLayout, RadialLayout
|
13 |
|
14 |
# Set page configuration to wide mode
|
15 |
Site_Name = '🦁CatRider🐈'
|
16 |
+
title = "🦁CatRider🐈by👤Aaron Wacker"
|
17 |
+
helpURL = 'https://huggingface.co/awacke1'
|
18 |
+
bugURL = 'https://huggingface.co/spaces/awacke1'
|
19 |
+
icons = '🦁'
|
20 |
|
21 |
+
useConfig = True
|
22 |
if useConfig:
|
23 |
st.set_page_config(
|
24 |
page_title=title,
|
|
|
82 |
{"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"}
|
83 |
]
|
84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
|
86 |
+
SUCCESS_CONCLUSIONS = ["Your swift paws led you to victory! 🎉"]
|
87 |
+
FAILURE_CONCLUSIONS = ["You tried your best, but it just wasn’t enough. 😿"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
# Function to save history to a markdown file
|
90 |
def save_history_to_file(history_df, user_id):
|
|
|
100 |
history_files = [f for f in os.listdir('.') if f.startswith('history_') and f.endswith('.md')]
|
101 |
return history_files
|
102 |
|
103 |
+
# Generate a random situation
|
104 |
def generate_situation():
|
105 |
return random.choice(SITUATIONS)
|
106 |
|
107 |
+
# Generate random actions
|
108 |
def generate_actions():
|
109 |
return random.sample(ACTIONS, min(3, len(ACTIONS)))
|
110 |
|
111 |
+
# Evaluate the chosen action
|
112 |
def evaluate_action(situation, action, gear_strength, rider_skill, history):
|
|
|
113 |
base_success_chance = 50
|
114 |
+
stat_modifier = (gear_strength + rider_skill - 10) * 2
|
|
|
|
|
115 |
success_chance = base_success_chance + stat_modifier
|
|
|
|
|
116 |
if action['id'] == situation['preferred_action']:
|
117 |
success_chance += 10
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
success_chance = max(5, min(95, success_chance))
|
|
|
119 |
outcome = random.randint(1, 100) <= success_chance
|
120 |
return outcome, success_chance
|
121 |
|
122 |
+
# Update character stats based on outcome
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
def update_character_stats(game_state, outcome):
|
124 |
if outcome:
|
|
|
125 |
game_state['rider_skill'] += 0.5
|
126 |
game_state['gear_strength'] += 0.2
|
127 |
else:
|
|
|
128 |
game_state['rider_skill'] = max(1, game_state['rider_skill'] - 0.3)
|
129 |
game_state['gear_strength'] = max(1, game_state['gear_strength'] - 0.1)
|
130 |
return game_state
|
131 |
|
132 |
+
# Create markdown preview of history
|
133 |
+
def create_markdown_preview(history_df):
|
134 |
+
markdown = "## 🌳 Journey Preview\n\n"
|
135 |
+
grouped = history_df.groupby(['situation_name'], sort=False)
|
136 |
+
for situation_name, group in grouped:
|
137 |
+
markdown += f"### {group.iloc[0]['situation_emoji']} **{situation_name}**\n"
|
138 |
+
for _, row in group.iterrows():
|
139 |
+
outcome_str = '✅ Success' if row['outcome'] else '❌ Failure'
|
140 |
+
stars = '⭐' * int(row['score'])
|
141 |
+
markdown += f"- Attempt {row['attempt']}: {row['action_emoji']} **{row['action_name']}**: {outcome_str} {stars}\n"
|
142 |
+
markdown += f" - {row['conclusion']}\n"
|
143 |
+
markdown += "\n"
|
144 |
+
return markdown
|
145 |
+
|
146 |
+
# Create knowledge graph with markdown support in nodes
|
147 |
def create_knowledge_graph(history_df):
|
148 |
nodes = []
|
149 |
edges = []
|
|
|
152 |
situation_node_id = f"situation_{row['situation_id']}"
|
153 |
action_node_id = f"action_{index}"
|
154 |
|
155 |
+
# Situation node with markdown content
|
156 |
if situation_node_id not in node_ids:
|
157 |
situation_node = StreamlitFlowNode(
|
158 |
+
id=situation_node_id,
|
159 |
pos=(0, 0),
|
160 |
+
data={'content': f"### {row['situation_emoji']} {row['situation_name']}\n\n{row['description']}"},
|
161 |
type='default',
|
162 |
+
shape='ellipse',
|
163 |
+
width=300
|
164 |
)
|
165 |
nodes.append(situation_node)
|
166 |
node_ids[situation_node_id] = situation_node_id
|
167 |
|
168 |
+
# Attempt node (action and outcome) with markdown content
|
169 |
+
outcome_content = '✅ **Success**' if row['outcome'] else '❌ **Failure**'
|
170 |
stars = '⭐' * int(row['score'])
|
171 |
+
attempt_node_content = f"""
|
172 |
+
#### {row['action_emoji']} {row['action_name']} ({outcome_content})
|
173 |
+
|
174 |
+
**Conclusion:** {row['conclusion']}
|
175 |
+
|
176 |
+
**Score:** {stars}
|
177 |
+
|
178 |
+
**Gear Strength:** {row['gear_strength']:.2f} | **Rider Skill:** {row['rider_skill']:.2f}
|
179 |
+
"""
|
180 |
attempt_node = StreamlitFlowNode(
|
181 |
+
id=action_node_id,
|
182 |
pos=(0, 0),
|
183 |
+
data={'content': attempt_node_content},
|
184 |
type='default',
|
185 |
+
shape='rectangle',
|
186 |
+
width=300
|
187 |
)
|
188 |
nodes.append(attempt_node)
|
189 |
|
|
|
197 |
|
198 |
return nodes, edges
|
199 |
|
200 |
+
# Main game application
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
def main():
|
202 |
st.title("🐱 Cat Rider 🏇")
|
203 |
|
204 |
+
# Initialize game state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
if 'game_state' not in st.session_state:
|
206 |
st.session_state.game_state = {
|
207 |
'user_id': str(uuid.uuid4()),
|
|
|
218 |
'succeeded': False
|
219 |
}
|
220 |
|
221 |
+
# Game logic...
|
222 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
game_state = st.session_state.game_state
|
224 |
|
225 |
+
# 🌳 Display Knowledge Journey Graph
|
226 |
+
if not game_state['history_df'].empty:
|
227 |
+
nodes, edges = create_knowledge_graph(game_state['history_df'])
|
228 |
+
try:
|
229 |
+
streamlit_flow('cat_rider_flow', nodes, edges, layout=TreeLayout(direction='down'), fit_view=True, height=600)
|
230 |
+
except Exception as e:
|
231 |
+
st.error(f"An error occurred while rendering the journey graph: {str(e)}")
|
232 |
+
st.markdown("Please try refreshing the page if the graph doesn't appear.")
|
233 |
+
|
234 |
+
# Rest of the game logic...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
235 |
|
236 |
if __name__ == "__main__":
|
237 |
main()
|