Update app.py
Browse files
app.py
CHANGED
@@ -2463,68 +2463,67 @@ def show_main_interface():
|
|
2463 |
def save_completed_story():
|
2464 |
"""Save completed story with all available formats"""
|
2465 |
try:
|
2466 |
-
st.markdown("### 💾
|
2467 |
|
2468 |
-
|
2469 |
-
|
2470 |
-
|
2471 |
-
|
2472 |
try:
|
2473 |
-
|
2474 |
st.download_button(
|
2475 |
-
"📥 ดาวน์โหลด PDF",
|
2476 |
-
data=
|
2477 |
-
file_name=f"
|
2478 |
mime="application/pdf",
|
2479 |
-
key="
|
|
|
2480 |
)
|
2481 |
-
st.success("สร้าง PDF เรียบร้อยแล้ว!")
|
2482 |
except Exception as e:
|
2483 |
-
logging.error(f"
|
2484 |
-
st.error("
|
2485 |
-
|
2486 |
-
|
2487 |
-
|
2488 |
-
key="save_completed_progress",
|
2489 |
-
use_container_width=True):
|
2490 |
try:
|
2491 |
story_data = {
|
2492 |
'timestamp': datetime.now().isoformat(),
|
2493 |
'level': st.session_state.level,
|
|
|
2494 |
'story': st.session_state.story,
|
2495 |
-
'achievements': st.session_state.achievements,
|
2496 |
'stats': {
|
2497 |
key: list(value) if isinstance(value, set) else value
|
2498 |
for key, value in st.session_state.stats.items()
|
2499 |
},
|
2500 |
'points': st.session_state.points,
|
2501 |
-
'
|
2502 |
-
'
|
2503 |
}
|
2504 |
|
|
|
|
|
2505 |
st.download_button(
|
2506 |
-
"📥
|
2507 |
-
data=
|
2508 |
-
file_name=f"
|
2509 |
mime="application/json",
|
2510 |
-
key="
|
|
|
2511 |
)
|
2512 |
-
st.success("สร้างไฟล์บันทึกเรียบร้อยแล้ว!")
|
2513 |
except Exception as e:
|
2514 |
-
logging.error(f"
|
2515 |
-
st.error("
|
2516 |
|
2517 |
except Exception as e:
|
2518 |
-
logging.error(f"Error
|
2519 |
st.error("เกิดข้อผิดพลาดในการบันทึกเรื่องราว")
|
2520 |
-
|
2521 |
def show_completion_options():
|
2522 |
"""Display options and summary when story is completed"""
|
2523 |
try:
|
2524 |
-
# Show completion celebration
|
2525 |
st.balloons()
|
2526 |
|
2527 |
-
#
|
2528 |
st.markdown("""
|
2529 |
<div style="
|
2530 |
background-color: #e8f5e9;
|
@@ -2543,9 +2542,7 @@ def show_completion_options():
|
|
2543 |
</div>
|
2544 |
""", unsafe_allow_html=True)
|
2545 |
|
2546 |
-
# Show
|
2547 |
-
st.markdown("### 📊 สรุปเรื่องราว")
|
2548 |
-
|
2549 |
metrics_col1, metrics_col2 = st.columns(2)
|
2550 |
with metrics_col1:
|
2551 |
st.metric(
|
@@ -2571,22 +2568,21 @@ def show_completion_options():
|
|
2571 |
help="อัตราการเขียนถูกต้อง"
|
2572 |
)
|
2573 |
|
2574 |
-
#
|
2575 |
st.markdown("### 🎯 ต้องการทำอะไรต่อ?")
|
|
|
2576 |
|
2577 |
-
|
2578 |
-
key="save_final_story",
|
2579 |
-
use_container_width=True):
|
2580 |
-
save_completed_story()
|
2581 |
-
|
2582 |
if st.button("🔄 เริ่มเรื่องใหม่",
|
2583 |
-
key="
|
2584 |
use_container_width=True):
|
2585 |
-
if st.checkbox("✅ ยืนยันการเริ่มใหม่",
|
2586 |
-
|
2587 |
-
|
2588 |
-
|
2589 |
-
|
|
|
|
|
2590 |
|
2591 |
except Exception as e:
|
2592 |
logging.error(f"Error showing completion options: {str(e)}")
|
@@ -2667,45 +2663,100 @@ def reset_story_with_confirmation():
|
|
2667 |
st.error("เกิดข้อผิดพลาดในการรีเซ็ตเรื่อง")
|
2668 |
|
2669 |
def create_story_pdf():
|
2670 |
-
"""Create PDF
|
2671 |
try:
|
2672 |
buffer = io.BytesIO()
|
2673 |
-
doc = SimpleDocTemplate(
|
2674 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2675 |
|
2676 |
-
#
|
2677 |
styles = getSampleStyleSheet()
|
2678 |
title_style = ParagraphStyle(
|
2679 |
'CustomTitle',
|
2680 |
parent=styles['Title'],
|
2681 |
fontSize=24,
|
2682 |
-
spaceAfter=30
|
|
|
2683 |
)
|
2684 |
-
|
2685 |
-
|
2686 |
-
# Add content
|
2687 |
-
content_style = ParagraphStyle(
|
2688 |
'CustomBody',
|
2689 |
parent=styles['Normal'],
|
2690 |
fontSize=12,
|
2691 |
-
|
2692 |
-
spaceAfter=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2693 |
)
|
|
|
|
|
|
|
2694 |
|
|
|
2695 |
for entry in st.session_state.story:
|
|
|
|
|
|
|
|
|
|
|
2696 |
if entry['role'] == 'AI':
|
|
|
2697 |
color = colors.blue
|
2698 |
else:
|
|
|
2699 |
color = colors.black
|
2700 |
|
2701 |
-
|
2702 |
-
|
2703 |
-
|
|
|
|
|
2704 |
)
|
2705 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2706 |
|
2707 |
# Build PDF
|
2708 |
-
doc.build(
|
2709 |
pdf = buffer.getvalue()
|
2710 |
buffer.close()
|
2711 |
|
|
|
2463 |
def save_completed_story():
|
2464 |
"""Save completed story with all available formats"""
|
2465 |
try:
|
2466 |
+
st.markdown("### 💾 บันทึกเรื่องราว", unsafe_allow_html=True)
|
2467 |
|
2468 |
+
save_col1, save_col2 = st.columns(2)
|
2469 |
+
|
2470 |
+
with save_col1:
|
2471 |
+
# Create and offer PDF download
|
2472 |
try:
|
2473 |
+
pdf_data = create_story_pdf()
|
2474 |
st.download_button(
|
2475 |
+
label="📥 ดาวน์โหลด PDF",
|
2476 |
+
data=pdf_data,
|
2477 |
+
file_name=f"joystory_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
|
2478 |
mime="application/pdf",
|
2479 |
+
key="download_story_pdf",
|
2480 |
+
use_container_width=True
|
2481 |
)
|
|
|
2482 |
except Exception as e:
|
2483 |
+
logging.error(f"PDF creation failed: {str(e)}")
|
2484 |
+
st.error("ไม่สามารถสร้างไฟล์ PDF ได้")
|
2485 |
+
|
2486 |
+
with save_col2:
|
2487 |
+
# Create and offer JSON download
|
|
|
|
|
2488 |
try:
|
2489 |
story_data = {
|
2490 |
'timestamp': datetime.now().isoformat(),
|
2491 |
'level': st.session_state.level,
|
2492 |
+
'theme': st.session_state.current_theme,
|
2493 |
'story': st.session_state.story,
|
|
|
2494 |
'stats': {
|
2495 |
key: list(value) if isinstance(value, set) else value
|
2496 |
for key, value in st.session_state.stats.items()
|
2497 |
},
|
2498 |
'points': st.session_state.points,
|
2499 |
+
'achievements': st.session_state.achievements,
|
2500 |
+
'ending_type': st.session_state.ending_type
|
2501 |
}
|
2502 |
|
2503 |
+
json_str = json.dumps(story_data, ensure_ascii=False, indent=2)
|
2504 |
+
|
2505 |
st.download_button(
|
2506 |
+
label="📥 ดาวน์โหลดเรื่องราว",
|
2507 |
+
data=json_str,
|
2508 |
+
file_name=f"joystory_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
|
2509 |
mime="application/json",
|
2510 |
+
key="download_story_json",
|
2511 |
+
use_container_width=True
|
2512 |
)
|
|
|
2513 |
except Exception as e:
|
2514 |
+
logging.error(f"JSON creation failed: {str(e)}")
|
2515 |
+
st.error("ไม่สามารถสร้างไฟล์บันทึกได้")
|
2516 |
|
2517 |
except Exception as e:
|
2518 |
+
logging.error(f"Error in save_completed_story: {str(e)}")
|
2519 |
st.error("เกิดข้อผิดพลาดในการบันทึกเรื่องราว")
|
2520 |
+
|
2521 |
def show_completion_options():
|
2522 |
"""Display options and summary when story is completed"""
|
2523 |
try:
|
|
|
2524 |
st.balloons()
|
2525 |
|
2526 |
+
# Show completion message
|
2527 |
st.markdown("""
|
2528 |
<div style="
|
2529 |
background-color: #e8f5e9;
|
|
|
2542 |
</div>
|
2543 |
""", unsafe_allow_html=True)
|
2544 |
|
2545 |
+
# Show statistics
|
|
|
|
|
2546 |
metrics_col1, metrics_col2 = st.columns(2)
|
2547 |
with metrics_col1:
|
2548 |
st.metric(
|
|
|
2568 |
help="อัตราการเขียนถูกต้อง"
|
2569 |
)
|
2570 |
|
2571 |
+
# Save options
|
2572 |
st.markdown("### 🎯 ต้องการทำอะไรต่อ?")
|
2573 |
+
save_completed_story()
|
2574 |
|
2575 |
+
# New story option
|
|
|
|
|
|
|
|
|
2576 |
if st.button("🔄 เริ่มเรื่องใหม่",
|
2577 |
+
key="new_story_button",
|
2578 |
use_container_width=True):
|
2579 |
+
if st.checkbox("✅ ยืนยันการเริ่มใหม่", key="confirm_reset"):
|
2580 |
+
st.warning("การเริ่มใหม่จะลบเรื่องราวปัจจุบันทั้งหมด")
|
2581 |
+
if st.button("🔄 ยืนยันการเริ่มใหม่",
|
2582 |
+
key="final_confirm_reset",
|
2583 |
+
use_container_width=True):
|
2584 |
+
reset_story()
|
2585 |
+
st.rerun()
|
2586 |
|
2587 |
except Exception as e:
|
2588 |
logging.error(f"Error showing completion options: {str(e)}")
|
|
|
2663 |
st.error("เกิดข้อผิดพลาดในการรีเซ็ตเรื่อง")
|
2664 |
|
2665 |
def create_story_pdf():
|
2666 |
+
"""Create PDF from story content"""
|
2667 |
try:
|
2668 |
buffer = io.BytesIO()
|
2669 |
+
doc = SimpleDocTemplate(
|
2670 |
+
buffer,
|
2671 |
+
pagesize=A4,
|
2672 |
+
rightMargin=72,
|
2673 |
+
leftMargin=72,
|
2674 |
+
topMargin=72,
|
2675 |
+
bottomMargin=72
|
2676 |
+
)
|
2677 |
|
2678 |
+
# Prepare styles
|
2679 |
styles = getSampleStyleSheet()
|
2680 |
title_style = ParagraphStyle(
|
2681 |
'CustomTitle',
|
2682 |
parent=styles['Title'],
|
2683 |
fontSize=24,
|
2684 |
+
spaceAfter=30,
|
2685 |
+
alignment=1 # Center alignment
|
2686 |
)
|
2687 |
+
normal_style = ParagraphStyle(
|
|
|
|
|
|
|
2688 |
'CustomBody',
|
2689 |
parent=styles['Normal'],
|
2690 |
fontSize=12,
|
2691 |
+
spaceBefore=6,
|
2692 |
+
spaceAfter=6
|
2693 |
+
)
|
2694 |
+
|
2695 |
+
# Create story elements list
|
2696 |
+
elements = []
|
2697 |
+
|
2698 |
+
# Add title
|
2699 |
+
title_text = "My Story - JoyStory"
|
2700 |
+
elements.append(Paragraph(title_text, title_style))
|
2701 |
+
elements.append(Spacer(1, 12))
|
2702 |
+
|
2703 |
+
# Add metadata
|
2704 |
+
metadata_style = ParagraphStyle(
|
2705 |
+
'Metadata',
|
2706 |
+
parent=styles['Normal'],
|
2707 |
+
fontSize=10,
|
2708 |
+
textColor=colors.gray,
|
2709 |
+
alignment=1
|
2710 |
)
|
2711 |
+
metadata_text = f"Level: {st.session_state.level}<br/>Date: {datetime.now().strftime('%Y-%m-%d')}"
|
2712 |
+
elements.append(Paragraph(metadata_text, metadata_style))
|
2713 |
+
elements.append(Spacer(1, 20))
|
2714 |
|
2715 |
+
# Add story content
|
2716 |
for entry in st.session_state.story:
|
2717 |
+
# Skip system messages or empty entries
|
2718 |
+
if not entry.get('content'):
|
2719 |
+
continue
|
2720 |
+
|
2721 |
+
# Format based on role
|
2722 |
if entry['role'] == 'AI':
|
2723 |
+
text = f"🤖 AI: {entry['content']}"
|
2724 |
color = colors.blue
|
2725 |
else:
|
2726 |
+
text = f"👤 You: {entry['content']}"
|
2727 |
color = colors.black
|
2728 |
|
2729 |
+
# Create paragraph style with color
|
2730 |
+
style = ParagraphStyle(
|
2731 |
+
'ColoredText',
|
2732 |
+
parent=normal_style,
|
2733 |
+
textColor=color
|
2734 |
)
|
2735 |
+
|
2736 |
+
# Add paragraph
|
2737 |
+
elements.append(Paragraph(text, style))
|
2738 |
+
elements.append(Spacer(1, 6))
|
2739 |
+
|
2740 |
+
# Add statistics
|
2741 |
+
elements.append(Spacer(1, 20))
|
2742 |
+
stats_style = ParagraphStyle(
|
2743 |
+
'Stats',
|
2744 |
+
parent=styles['Normal'],
|
2745 |
+
fontSize=10,
|
2746 |
+
textColor=colors.gray
|
2747 |
+
)
|
2748 |
+
|
2749 |
+
stats_text = f"""
|
2750 |
+
Story Statistics:<br/>
|
2751 |
+
Total Sentences: {len(st.session_state.story)}<br/>
|
2752 |
+
Unique Words: {len(st.session_state.stats['vocabulary_used'])}<br/>
|
2753 |
+
Accuracy Rate: {st.session_state.stats['accuracy_rate']:.1f}%<br/>
|
2754 |
+
Total Points: {st.session_state.points['total']}
|
2755 |
+
"""
|
2756 |
+
elements.append(Paragraph(stats_text, stats_style))
|
2757 |
|
2758 |
# Build PDF
|
2759 |
+
doc.build(elements)
|
2760 |
pdf = buffer.getvalue()
|
2761 |
buffer.close()
|
2762 |
|