import streamlit as st import json import datetime from openai import OpenAI from typing import Dict, List, Set import io from reportlab.lib import colors from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch from reportlab.pdfgen import canvas from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from datetime import datetime from typing import Dict, List, Optional, Tuple import random # Theme Configuration story_themes = { 'fantasy': { 'id': 'fantasy', 'icon': '🏰', 'name_en': 'Fantasy & Magic', 'name_th': 'แฟนตาซีและเวทมนตร์', 'description_th': 'ผจญภัยในโลกแห่งเวทมนตร์และจินตนาการ', 'description_en': 'Adventure in a world of magic and imagination', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['dragon', 'magic', 'wand', 'spell', 'wizard', 'fairy', 'castle', 'king', 'queen'], 'Intermediate': ['potion', 'enchanted', 'castle', 'creature', 'power', 'scroll', 'portal', 'magical'], 'Advanced': ['sorcery', 'mystical', 'enchantment', 'prophecy', 'ancient', 'legendary', 'mythical'] }, 'story_starters': { 'Beginner': [ {'th': 'วันหนึ่งฉันเจอไม้วิเศษในสวน...', 'en': 'One day, I found a magic wand in the garden...'}, {'th': 'มังกรน้อยกำลังมองหาเพื่อน...', 'en': 'The little dragon was looking for a friend...'}, {'th': 'เจ้าหญิงน้อยมีความลับวิเศษ...', 'en': 'The little princess had a magical secret...'} ], 'Intermediate': [ {'th': 'ในปราสาทเก่าแก่มีประตูลึกลับ...', 'en': 'In the ancient castle, there was a mysterious door...'}, {'th': 'เมื่อน้ำยาวิเศษเริ่มส่องแสง...', 'en': 'When the magic potion started to glow...'}, {'th': 'หนังสือเวทมนตร์เล่มนั้นเปิดออกเอง...', 'en': 'The spellbook opened by itself...'} ], 'Advanced': [ {'th': 'คำทำนายโบราณกล่าวถึงผู้วิเศษที่จะมา...', 'en': 'The ancient prophecy spoke of a wizard who would come...'}, {'th': 'ในโลกที่เวทมนตร์กำลังจะสูญหาย...', 'en': 'In a world where magic was fading away...'}, {'th': 'ณ จุดบรรจบของดวงดาวทั้งห้า...', 'en': 'At the convergence of the five stars...'} ] }, 'background_color': '#E8F3FF', 'accent_color': '#1E88E5' }, 'nature': { 'id': 'nature', 'icon': '🌳', 'name_en': 'Nature & Animals', 'name_th': 'ธรรมชาติและสัตว์โลก', 'description_th': 'เรื่องราวของสัตว์น้อยใหญ่และธรรมชาติอันงดงาม', 'description_en': 'Stories of animals and beautiful nature', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['tree', 'bird', 'flower', 'cat', 'dog', 'garden', 'rabbit', 'butterfly', 'sun'], 'Intermediate': ['forest', 'river', 'mountain', 'wildlife', 'season', 'weather', 'rainbow', 'stream'], 'Advanced': ['ecosystem', 'habitat', 'wilderness', 'environment', 'conservation', 'migration', 'climate'] }, 'story_starters': { 'Beginner': [ {'th': 'แมวน้อยเจอนกในสวน...', 'en': 'The little cat found a bird in the garden...'}, {'th': 'ดอกไม้สวยกำลังเบ่งบาน...', 'en': 'The beautiful flower was blooming...'}, {'th': 'กระต่ายน้อยหลงทางในสวน...', 'en': 'The little rabbit got lost in the garden...'} ], 'Intermediate': [ {'th': 'ในป่าใหญ่มีเสียงลึกลับ...', 'en': 'In the big forest, there was a mysterious sound...'}, {'th': 'แม่น้ำสายนี้มีความลับ...', 'en': 'This river had a secret...'}, {'th': 'สายรุ้งพาดผ่านภูเขา...', 'en': 'A rainbow stretched across the mountain...'} ], 'Advanced': [ {'th': 'ฝูงนกกำลังอพยพย้ายถิ่น...', 'en': 'The birds were migrating...'}, {'th': 'ป่าฝนกำลังเปลี่ยนแปลง...', 'en': 'The rainforest was changing...'}, {'th': 'ความลับของระบบนิเวศ...', 'en': 'The secret of the ecosystem...'} ] }, 'background_color': '#F1F8E9', 'accent_color': '#4CAF50' }, 'space': { 'id': 'space', 'icon': '🚀', 'name_en': 'Space Adventure', 'name_th': 'ผจญภัยในอวกาศ', 'description_th': 'เรื่องราวการสำรวจอวกาศและดวงดาวอันน่าตื่นเต้น', 'description_en': 'Exciting stories of space exploration and celestial discoveries', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['star', 'moon', 'planet', 'sun', 'rocket', 'alien', 'space', 'light'], 'Intermediate': ['astronaut', 'spacecraft', 'galaxy', 'meteor', 'satellite', 'orbit', 'comet'], 'Advanced': ['constellation', 'nebula', 'astronomy', 'telescope', 'exploration', 'discovery'] }, 'story_starters': { 'Beginner': [ {'th': 'จรวดลำน้อยพร้อมบินแล้ว...', 'en': 'The little rocket was ready to fly...'}, {'th': 'ดาวดวงน้อยเปล่งแสงวิบวับ...', 'en': 'The little star twinkled brightly...'}, {'th': 'มนุษย์ต่างดาวที่เป็นมิตร...', 'en': 'The friendly alien...'} ], 'Intermediate': [ {'th': 'นักบินอวกาศพบสิ่งประหลาด...', 'en': 'The astronaut found something strange...'}, {'th': 'ดาวเคราะห์ดวงใหม่ถูกค้นพบ...', 'en': 'A new planet was discovered...'}, {'th': 'สถานีอวกาศส่งสัญญาณลึกลับ...', 'en': 'The space station sent a mysterious signal...'} ], 'Advanced': [ {'th': 'การสำรวจดาวหางนำไปสู่การค้นพบ...', 'en': 'The comet exploration led to a discovery...'}, {'th': 'กาแล็กซี่ที่ไม่มีใครเคยเห็น...', 'en': 'An unknown galaxy appeared...'}, {'th': 'ความลับของหลุมดำ...', 'en': 'The secret of the black hole...'} ] }, 'background_color': '#E1F5FE', 'accent_color': '#0288D1' }, 'adventure': { 'id': 'adventure', 'icon': '🗺️', 'name_en': 'Adventure & Quest', 'name_th': 'การผจญภัยและการค้นหา', 'description_th': 'ออกผจญภัยค้นหาสมบัติและความลับต่างๆ', 'description_en': 'Embark on quests to find treasures and secrets', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['map', 'treasure', 'cave', 'island', 'path', 'boat', 'key', 'chest'], 'Intermediate': ['compass', 'adventure', 'journey', 'mystery', 'explore', 'discover', 'quest'], 'Advanced': ['expedition', 'archaeology', 'artifact', 'ancient', 'mysterious', 'discovery'] }, 'story_starters': { 'Beginner': [ {'th': 'แผนที่เก่าแก่ชิ้นหนึ่ง...', 'en': 'An old map showed...'}, {'th': 'บนเกาะเล็กๆ มีสมบัติ...', 'en': 'On a small island, there was a treasure...'}, {'th': 'ถ้ำลึกลับถูกค้นพบ...', 'en': 'A mysterious cave was found...'} ], 'Intermediate': [ {'th': 'เข็มทิศวิเศษชี้ไปที่...', 'en': 'The magical compass pointed to...'}, {'th': 'การเดินทางเริ่มต้นที่...', 'en': 'The journey began at...'}, {'th': 'ความลับของวัตถุโบราณ...', 'en': 'The secret of the ancient artifact...'} ], 'Advanced': [ {'th': 'การสำรวจซากปรักหักพังนำไปสู่...', 'en': 'The ruins exploration led to...'}, {'th': 'นักโบราณคดีค้นพบ...', 'en': 'The archaeologist discovered...'}, {'th': 'ความลับของอารยธรรมโบราณ...', 'en': 'The secret of the ancient civilization...'} ] }, 'background_color': '#FFF3E0', 'accent_color': '#FF9800' }, 'school': { 'id': 'school', 'icon': '🏫', 'name_en': 'School & Friends', 'name_th': 'โรงเรียนและเพื่อน', 'description_th': 'เรื่องราวสนุกๆ ในโรงเรียนกับเพื่อนๆ', 'description_en': 'Fun stories about school life and friendship', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['friend', 'teacher', 'book', 'classroom', 'pencil', 'desk', 'lunch', 'play'], 'Intermediate': ['homework', 'project', 'library', 'playground', 'student', 'lesson', 'study'], 'Advanced': ['presentation', 'experiment', 'knowledge', 'research', 'collaboration', 'achievement'] }, 'story_starters': { 'Beginner': [ {'th': 'วันแรกในห้องเรียนใหม่...', 'en': 'First day in the new classroom...'}, {'th': 'เพื่อนใหม่ในโรงเรียน...', 'en': 'A new friend at school...'}, {'th': 'ที่โต๊ะอาหารกลางวัน...', 'en': 'At the lunch table...'} ], 'Intermediate': [ {'th': 'โครงงานพิเศษของห้องเรา...', 'en': 'Our class special project...'}, {'th': 'ในห้องสมุดมีความลับ...', 'en': 'The library had a secret...'}, {'th': 'การทดลองวิทยาศาสตร์ครั้งนี้...', 'en': 'This science experiment...'} ], 'Advanced': [ {'th': 'การนำเสนอครั้งสำคัญ...', 'en': 'The important presentation...'}, {'th': 'การค้นคว้าพิเศษนำไปสู่...', 'en': 'The special research led to...'}, {'th': 'โครงการความร่วมมือระหว่างห้อง...', 'en': 'The inter-class collaboration project...'} ] }, 'background_color': '#F3E5F5', 'accent_color': '#9C27B0' }, 'superhero': { 'id': 'superhero', 'icon': '🦸', 'name_en': 'Superheroes', 'name_th': 'ซูเปอร์ฮีโร่', 'description_th': 'เรื่องราวของฮีโร่ตัวน้อยผู้ช่วยเหลือผู้อื่น', 'description_en': 'Stories of young heroes helping others', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['hero', 'help', 'save', 'power', 'mask', 'cape', 'fly', 'strong'], 'Intermediate': ['rescue', 'protect', 'brave', 'courage', 'mission', 'team', 'secret', 'mighty'], 'Advanced': ['superhero', 'extraordinary', 'responsibility', 'leadership', 'determination', 'justice'] }, 'story_starters': { 'Beginner': [ {'th': 'ฮีโร่น้อยคนใหม่ของเมือง...', 'en': 'The city\'s new young hero...'}, {'th': 'พลังพิเศษของฉันทำให้...', 'en': 'My special power made me...'}, {'th': 'เมื่อต้องช่วยเหลือแมวตัวน้อย...', 'en': 'When I had to save a little cat...'} ], 'Intermediate': [ {'th': 'ภารกิจลับของทีมฮีโร่...', 'en': 'The hero team\'s secret mission...'}, {'th': 'พลังใหม่ที่น่าประหลาดใจ...', 'en': 'A surprising new power...'}, {'th': 'การช่วยเหลือครั้งสำคัญ...', 'en': 'An important rescue mission...'} ], 'Advanced': [ {'th': 'ความรับผิดชอบของการเป็นฮีโร่...', 'en': 'The responsibility of being a hero...'}, {'th': 'เมื่อเมืองต้องการฮีโร่...', 'en': 'When the city needed a hero...'}, {'th': 'การต่อสู้เพื่อความยุติธรรม...', 'en': 'Fighting for justice...'} ] }, 'background_color': '#FFE0B2', 'accent_color': '#F57C00' }, 'mystery': { 'id': 'mystery', 'icon': '🔍', 'name_en': 'Mystery & Detective', 'name_th': 'ไขปริศนาและนักสืบ', 'description_th': 'สืบสวนปริศนาและไขความลับต่างๆ', 'description_en': 'Solve mysteries and uncover secrets', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['clue', 'find', 'look', 'search', 'mystery', 'hidden', 'secret', 'detective'], 'Intermediate': ['investigate', 'evidence', 'puzzle', 'solve', 'discover', 'suspicious', 'case'], 'Advanced': ['investigation', 'deduction', 'enigma', 'cryptic', 'mysterious', 'revelation'] }, 'story_starters': { 'Beginner': [ {'th': 'มีรอยปริศนาในสวน...', 'en': 'There were mysterious footprints in the garden...'}, {'th': 'จดหมายลึกลับถูกส่งมา...', 'en': 'A mysterious letter arrived...'}, {'th': 'ของเล่นหายไปอย่างลึกลับ...', 'en': 'The toy mysteriously disappeared...'} ], 'Intermediate': [ {'th': 'เบาะแสชิ้นแรกนำไปสู่...', 'en': 'The first clue led to...'}, {'th': 'ความลับในห้องเก่า...', 'en': 'The secret in the old room...'}, {'th': 'รหัสลับถูกค้นพบ...', 'en': 'A secret code was found...'} ], 'Advanced': [ {'th': 'คดีปริศนาที่ยากที่สุด...', 'en': 'The most challenging mystery case...'}, {'th': 'ความลับที่ซ่อนอยู่มานาน...', 'en': 'A long-hidden secret...'}, {'th': 'การสืบสวนนำไปสู่การค้นพบ...', 'en': 'The investigation led to a discovery...'} ] }, 'background_color': '#E0E0E0', 'accent_color': '#616161' }, 'science': { 'id': 'science', 'icon': '🔬', 'name_en': 'Science & Discovery', 'name_th': 'วิทยาศาสตร์และการค้นพบ', 'description_th': 'การทดลองและค้นพบทางวิทยาศาสตร์ที่น่าตื่นเต้น', 'description_en': 'Exciting scientific experiments and discoveries', 'level_range': ['Beginner', 'Intermediate', 'Advanced'], 'vocabulary': { 'Beginner': ['experiment', 'science', 'lab', 'test', 'mix', 'observe', 'change', 'result'], 'Intermediate': ['hypothesis', 'research', 'discovery', 'invention', 'laboratory', 'scientist'], 'Advanced': ['innovation', 'technological', 'breakthrough', 'analysis', 'investigation'] }, 'story_starters': { 'Beginner': [ {'th': 'การทดลองง่ายๆ เริ่มต้นด้วย...', 'en': 'The simple experiment started with...'}, {'th': 'ในห้องทดลองมีสิ่งมหัศจรรย์...', 'en': 'In the lab, there was something amazing...'}, {'th': 'เมื่อผสมสองสิ่งเข้าด้วยกัน...', 'en': 'When mixing the two things together...'} ], 'Intermediate': [ {'th': 'การค้นพบที่น่าประหลาดใจ...', 'en': 'A surprising discovery...'}, {'th': 'สิ่งประดิษฐ์ใหม่ทำให้...', 'en': 'The new invention made...'}, {'th': 'การทดลองที่ไม่คาดคิด...', 'en': 'An unexpected experiment...'} ], 'Advanced': [ {'th': 'นวัตกรรมที่จะเปลี่ยนโลก...', 'en': 'Innovation that would change the world...'}, {'th': 'การค้นพบทางวิทยาศาสตร์ครั้งสำคัญ...', 'en': 'An important scientific discovery...'}, {'th': 'เทคโนโลยีใหม่ที่น่าทึ่ง...', 'en': 'Amazing new technology...'} ] }, 'background_color': '#E8EAF6', 'accent_color': '#3F51B5' } } # ระบบ Achievements achievements_list = { 'perfect_writer': { 'name': '🌟 นักเขียนไร้ที่ติ', 'description': 'เขียนถูกต้อง 5 ประโยคติดต่อกัน', 'condition': lambda: st.session_state.points['streak'] >= 5 }, 'vocabulary_master': { 'name': '📚 ราชาคำศัพท์', 'description': 'ใช้คำศัพท์ไม่ซ้ำกัน 50 คำ', 'condition': lambda: len(st.session_state.stats['vocabulary_used']) >= 50 }, 'quick_learner': { 'name': '🚀 นักเรียนจอมขยัน', 'description': 'แก้ไขประโยคให้ถูกต้องภายใน 3 วินาที', 'condition': lambda: True # ต้องเพิ่มการจับเวลา }, 'story_master': { 'name': '📖 นักแต่งนิทาน', 'description': 'เขียนเรื่องยาว 10 ประโยค', 'condition': lambda: len(st.session_state.story) >= 10 }, 'accuracy_king': { 'name': '👑 ราชาความแม่นยำ', 'description': 'มีอัตราความถูกต้อง 80% ขึ้นไป (อย่างน้อย 10 ประโยค)', 'condition': lambda: ( st.session_state.stats['total_sentences'] >= 10 and st.session_state.stats['accuracy_rate'] >= 80 ) } } # Set up Streamlit page configuration st.set_page_config( page_title="JoyStory - Interactive Story Adventure", page_icon="📖", layout="wide", initial_sidebar_state="collapsed", ) # Initialize OpenAI client client = OpenAI() # Define level configurations level_options = { 'Beginner': { 'thai_name': 'ระดับเริ่มต้น (ป.1-3)', 'age_range': '7-9 ปี', 'description': 'เหมาะสำหรับน้องๆ ที่เริ่มเรียนรู้การเขียนประโยคภาษาอังกฤษ', 'features': [ 'ประโยคสั้นๆ ง่ายๆ', 'คำศัพท์พื้นฐานที่ใช้ในชีวิตประจำวัน', 'มีคำแนะนำภาษาไทยละเอียด', 'เน้นการใช้ Present Simple Tense' ] }, 'Intermediate': { 'thai_name': 'ระดับกลาง (ป.4-6)', 'age_range': '10-12 ปี', 'description': 'เหมาะสำหรับน้องๆ ที่สามารถเขียนประโยคพื้นฐานได้แล้ว', 'features': [ 'ประโยคซับซ้อนขึ้น', 'เริ่มใช้ Past Tense ได้', 'คำศัพท์หลากหลายขึ้น', 'สามารถเขียนเรื่องราวต่อเนื่องได้' ] }, 'Advanced': { 'thai_name': 'ระดับก้าวหน้า (ม.1-3)', 'age_range': '13-15 ปี', 'description': 'เหมาะสำหรับน้องๆ ที่มีพื้นฐานภาษาอังกฤษดี', 'features': [ 'เขียนเรื่องราวได้หลากหลายรูปแบบ', 'ใช้ Tense ต่างๆ ได้', 'คำศัพท์ระดับสูงขึ้น', 'สามารถแต่งเรื่องที่ซับซ้อนได้' ] } } # Add custom CSS including new styles for level selection st.markdown(""" """, unsafe_allow_html=True) # Initialize session state variables def init_session_state(): if 'current_theme' not in st.session_state: st.session_state.current_theme = None if 'theme_story_starter' not in st.session_state: st.session_state.theme_story_starter = None if 'story' not in st.session_state: st.session_state.story = [] if 'feedback' not in st.session_state: st.session_state.feedback = None if 'level' not in st.session_state: st.session_state.level = 'Beginner' if 'unique_words' not in st.session_state: st.session_state.unique_words = set() if 'total_words' not in st.session_state: st.session_state.total_words = 0 if 'should_reset' not in st.session_state: st.session_state.should_reset = False if 'user_input' not in st.session_state: st.session_state.user_input = "" if 'points' not in st.session_state: st.session_state.points = { 'total': 0, 'perfect_sentences': 0, 'corrections_made': 0, 'streak': 0, 'max_streak': 0 } if 'corrections' not in st.session_state: st.session_state.corrections = {} if 'stats' not in st.session_state: st.session_state.stats = { 'total_sentences': 0, 'correct_first_try': 0, 'accuracy_rate': 0.0, 'vocabulary_used': set(), 'corrections_made': 0 } if 'achievements' not in st.session_state: st.session_state.achievements = [] init_session_state() # เพิ่มฟังก์ชันสำหรับจัดการ input def clear_input(): st.session_state.user_input = "" # Callback function for submit button def submit_story(): """Handle story submission and processing.""" if st.session_state.text_input.strip(): user_text = st.session_state.text_input.strip() # ตรวจสอบว่ามีเรื่องเริ่มต้นหรือยัง if not st.session_state.story: st.error("กรุณาเลือกธีมเรื่องราวก่อนเริ่มเขียน") return try: # รับ feedback และตรวจสอบความถูกต้อง feedback_data = provide_feedback(user_text, st.session_state.level) st.session_state.feedback = feedback_data is_correct = not feedback_data.get('has_errors', False) # เพิ่มประโยคของผู้ใช้ (เพิ่มครั้งเดียว) st.session_state.story.append({ "role": "You", "content": user_text, "is_corrected": False, "is_correct": is_correct }) # เพิ่มคำศัพท์ที่ใช้ words = set(user_text.lower().split()) st.session_state.stats['vocabulary_used'].update(words) # อัพเดตคะแนนและ achievements update_points(is_correct) update_achievements() # Generate AI continuation text_for_continuation = feedback_data['corrected'] if feedback_data['has_errors'] else user_text ai_response = generate_story_continuation(text_for_continuation, st.session_state.level) # เพิ่มการตอบกลับของ AI st.session_state.story.append({ "role": "AI", "content": ai_response }) # Clear input st.session_state.text_input = "" except Exception as e: st.error("เกิดข้อผิดพลาดในการวิเคราะห์ประโยค กรุณาลองใหม่อีกครั้ง") st.error(f"Debug - Error in submit_story: {str(e)}") # Theme Helper Functions def get_available_themes(level: str) -> List[Dict]: """Get list of themes available for the current level.""" return [ theme for theme in story_themes.values() if level in theme['level_range'] ] def generate_dynamic_story_starter(theme_id: str, level: str) -> Dict[str, str]: """ Dynamically generate a story starter based on theme and level. Returns both Thai and English versions. """ theme = story_themes.get(theme_id, {}) # Theme-specific elements for dynamic generation theme_elements = { 'fantasy': { 'characters': { 'Beginner': [ ('young wizard', 'พ่อมดน้อย'), ('fairy', 'นางฟ้า'), ('friendly dragon', 'มังกรใจดี'), ('magical cat', 'แมวเวทมนตร์'), ], 'Intermediate': [ ('mysterious wizard', 'พ่อมดลึกลับ'), ('ancient dragon', 'มังกรโบราณ'), ('enchanted princess', 'เจ้าหญิงต้องมนตร์'), ], 'Advanced': [ ('legendary sorcerer', 'จอมเวทในตำนาน'), ('mythical creature', 'สัตว์ในตำนาน'), ('wise elder wizard', 'พ่อมดผู้เฒ่าผู้เป็นปราชญ์'), ] }, 'locations': { 'Beginner': [ ('magical garden', 'สวนเวทมนตร์'), ('enchanted forest', 'ป่าวิเศษ'), ], 'Intermediate': [ ('ancient castle', 'ปราสาทโบราณ'), ('wizard school', 'โรงเรียนเวทมนตร์'), ], 'Advanced': [ ('mystical realm', 'อาณาจักรเวทมนตร์'), ('floating islands', 'เกาะลอยฟ้า'), ] }, 'objects': { 'Beginner': [ ('magic wand', 'ไม้กายสิทธิ์'), ('glowing crystal', 'คริสตัลเรืองแสง'), ], 'Intermediate': [ ('ancient spellbook', 'ตำราเวทโบราณ'), ('magical artifact', 'วัตถุวิเศษ'), ], 'Advanced': [ ('legendary sword', 'ดาบในตำนาน'), ('mystical orb', 'ลูกแก้ววิเศษ'), ] } }, 'nature': { 'characters': { 'Beginner': [ ('little bird', 'นกน้อย'), ('friendly squirrel', 'กระรอกน้อยใจดี'), ('playful rabbit', 'กระต่ายซน'), ], 'Intermediate': [ ('wise owl', 'นกฮูกผู้รอบรู้'), ('busy beaver', 'บีเวอร์ขยัน'), ('clever fox', 'จิ้งจอกเจ้าปัญญา'), ], 'Advanced': [ ('majestic eagle', 'อินทรีผู้สง่างาม'), ('mysterious panther', 'เสือดำลึกลับ'), ] }, 'locations': { 'Beginner': [ ('flower garden', 'สวนดอกไม้'), ('small pond', 'สระน้ำเล็กๆ'), ], 'Intermediate': [ ('deep forest', 'ป่าลึก'), ('mountain peak', 'ยอดเขาสูง'), ], 'Advanced': [ ('ancient rainforest', 'ป่าดึกดำบรรพ์'), ('hidden valley', 'หุบเขาซ่อนเร้น'), ] }, 'objects': { 'Beginner': [ ('colorful flower', 'ดอกไม้สีสวย'), ('fallen leaf', 'ใบไม้ร่วง'), ], 'Intermediate': [ ('old tree', 'ต้นไม้เก่าแก่'), ('clear stream', 'ลำธารใส'), ], 'Advanced': [ ('rare plant', 'พืชหายาก'), ('ancient tree', 'ต้นไม้โบราณ'), ] } }, 'space': { 'characters': { 'Beginner': [ ('friendly alien', 'มนุษย์ต่างดาวใจดี'), ('little astronaut', 'นักบินอวกาศตัวน้อย'), ('space robot', 'หุ่นยนต์อวกาศ'), ], 'Intermediate': [ ('space explorer', 'นักสำรวจอวกาศ'), ('alien scientist', 'นักวิทยาศาสตร์ต่างดาว'), ('space pilot', 'นักบินยานอวกาศ'), ], 'Advanced': [ ('galactic commander', 'ผู้บัญชาการกาแล็กซี่'), ('space archaeologist', 'นักโบราณคดีอวกาศ'), ] }, 'locations': { 'Beginner': [ ('small planet', 'ดาวเคราะห์เล็กๆ'), ('space station', 'สถานีอวกาศ'), ], 'Intermediate': [ ('mysterious galaxy', 'กาแล็กซี่ลึกลับ'), ('alien world', 'โลกต่างดาว'), ], 'Advanced': [ ('black hole', 'หลุมดำ'), ('distant nebula', 'เนบิวลาไกลโพ้น'), ] }, 'objects': { 'Beginner': [ ('shiny meteor', 'ดาวตกเปล่งประกาย'), ('space telescope', 'กล้องดูดาว'), ], 'Intermediate': [ ('advanced spaceship', 'ยานอวกาศลำใหม่'), ('mysterious signal', 'สัญญาณลึกลับ'), ], 'Advanced': [ ('alien artifact', 'วัตถุโบราณจากต่างดาว'), ('space anomaly', 'ความผิดปกติในอวกาศ'), ] } }, 'adventure': { 'characters': { 'Beginner': [ ('young explorer', 'นักผจญภัยตัวน้อย'), ('treasure hunter', 'นักล่าสมบัติ'), ('brave sailor', 'กะลาสีผู้กล้า'), ], 'Intermediate': [ ('experienced guide', 'ไกด์ผู้ชำนาญ'), ('mysterious traveler', 'นักเดินทางลึกลับ'), ], 'Advanced': [ ('legendary explorer', 'นักสำรวจในตำนาน'), ('ancient guardian', 'ผู้พิทักษ์โบราณ'), ] }, 'locations': { 'Beginner': [ ('hidden cave', 'ถ้ำซ่อนเร้น'), ('treasure island', 'เกาะสมบัติ'), ], 'Intermediate': [ ('ancient ruins', 'ซากปรักหักพัง'), ('mysterious temple', 'วัดลึกลับ'), ], 'Advanced': [ ('lost city', 'เมืองที่สาบสูญ'), ('forbidden valley', 'หุบเขาต้องห้าม'), ] }, 'objects': { 'Beginner': [ ('old map', 'แผนที่เก่า'), ('golden compass', 'เข็มทิศทองคำ'), ], 'Intermediate': [ ('ancient scroll', 'ม้วนกระดาษโบราณ'), ('magical key', 'กุญแจวิเศษ'), ], 'Advanced': [ ('legendary artifact', 'วัตถุโบราณในตำนาน'), ('sacred relic', 'วัตถุศักดิ์สิทธิ์'), ] } }, 'school': { 'characters': { 'Beginner': [ ('new student', 'นักเรียนใหม่'), ('kind teacher', 'คุณครูใจดี'), ('best friend', 'เพื่อนรัก'), ], 'Intermediate': [ ('class president', 'หัวหน้าห้อง'), ('school librarian', 'บรรณารักษ์'), ], 'Advanced': [ ('exchange student', 'นักเรียนแลกเปลี่ยน'), ('science genius', 'อัจฉริยะวิทยาศาสตร์'), ] }, 'locations': { 'Beginner': [ ('classroom', 'ห้องเรียน'), ('school playground', 'สนามเด็กเล่น'), ], 'Intermediate': [ ('science lab', 'ห้องทดลองวิทยาศาสตร์'), ('school library', 'ห้องสมุด'), ], 'Advanced': [ ('school theater', 'โรงละครโรงเรียน'), ('computer room', 'ห้องคอมพิวเตอร์'), ] }, 'objects': { 'Beginner': [ ('new book', 'หนังสือเล่มใหม่'), ('special pencil', 'ดินสอวิเศษ'), ], 'Intermediate': [ ('science project', 'โครงงานวิทยาศาสตร์'), ('old diary', 'ไดอารี่เก่า'), ], 'Advanced': [ ('robotics kit', 'ชุดประดิษฐ์หุ่นยนต์'), ('ancient textbook', 'ตำราเรียนโบราณ'), ] } }, 'superhero': { 'characters': { 'Beginner': [ ('young hero', 'ฮีโร่ตัวน้อย'), ('super pet', 'สัตว์เลี้ยงพลังพิเศษ'), ('friendly sidekick', 'ผู้ช่วยฮีโร่'), ], 'Intermediate': [ ('masked vigilante', 'ฮีโร่ปริศนา'), ('super teacher', 'คุณครูพลังพิเศษ'), ], 'Advanced': [ ('legendary hero', 'ฮีโร่ในตำนาน'), ('protector of justice', 'ผู้พิทักษ์ความยุติธรรม'), ] }, 'locations': { 'Beginner': [ ('hero school', 'โรงเรียนฮีโร่'), ('secret hideout', 'ที่ซ่อนลับ'), ], 'Intermediate': [ ('hero headquarters', 'ศูนย์บัญชาการฮีโร่'), ('training ground', 'สนามฝึกซ้อม'), ], 'Advanced': [ ('hero academy', 'สถาบันฝึกฮีโร่'), ('crisis center', 'ศูนย์รับมือวิกฤต'), ] }, 'objects': { 'Beginner': [ ('hero mask', 'หน้ากากฮีโร่'), ('power crystal', 'คริสตัลพลัง'), ], 'Intermediate': [ ('super gadget', 'อุปกรณ์พิเศษ'), ('power suit', 'ชุดพลังพิเศษ'), ], 'Advanced': [ ('ultimate weapon', 'อาวุธสุดยอด'), ('ancient power source', 'แหล่งพลังโบราณ'), ] } }, 'mystery': { 'characters': { 'Beginner': [ ('young detective', 'นักสืบตัวน้อย'), ('mysterious neighbor', 'เพื่อนบ้านปริศนา'), ('helpful friend', 'เพื่อนผู้ช่วย'), ], 'Intermediate': [ ('famous detective', 'นักสืบชื่อดัง'), ('mystery writer', 'นักเขียนนิยายปริศนา'), ], 'Advanced': [ ('master detective', 'ยอดนักสืบ'), ('crime expert', 'ผู้เชี่ยวชาญคดี'), ] }, 'locations': { 'Beginner': [ ('old house', 'บ้านเก่า'), ('mystery shop', 'ร้านค้าปริศนา'), ], 'Intermediate': [ ('abandoned building', 'ตึกร้าง'), ('detective office', 'สำนักงานนักสืบ'), ], 'Advanced': [ ('secret laboratory', 'ห้องทดลองลับ'), ('mystery mansion', 'คฤหาสน์ปริศนา'), ] }, 'objects': { 'Beginner': [ ('mysterious letter', 'จดหมายปริศนา'), ('strange footprint', 'รอยเท้าประหลาด'), ], 'Intermediate': [ ('ancient cipher', 'รหัสลับโบราณ'), ('hidden clue', 'เบาะแสซ่อนเร้น'), ], 'Advanced': [ ('secret document', 'เอกสารลับ'), ('mysterious artifact', 'วัตถุปริศนา'), ] } }, 'science': { 'characters': { 'Beginner': [ ('young scientist', 'นักวิทยาศาสตร์ตัวน้อย'), ('robot friend', 'หุ่นยนต์เพื่อนรัก'), ('curious student', 'นักเรียนช่างสงสัย'), ], 'Intermediate': [ ('brilliant inventor', 'นักประดิษฐ์อัจฉริยะ'), ('science teacher', 'คุณครูวิทยาศาสตร์'), ], 'Advanced': [ ('famous researcher', 'นักวิจัยชื่อดัง'), ('genius professor', 'ศาสตราจารย์อัจฉริยะ'), ] }, 'locations': { 'Beginner': [ ('science lab', 'ห้องทดลองวิทยาศาสตร์'), ('invention workshop', 'ห้องประดิษฐ์'), ], 'Intermediate': [ ('research center', 'ศูนย์วิจัย'), ('robotics lab', 'ห้องปฏิบัติการหุ่นยนต์'), ], 'Advanced': [ ('quantum laboratory', 'ห้องปฏิบัติการควอนตัม'), ('innovation center', 'ศูนย์นวัตกรรม'), ] }, 'objects': { 'Beginner': [ ('colorful chemical', 'สารเคมีสีสันสดใส'), ('strange invention', 'สิ่งประดิษฐ์แปลกใหม่'), ], 'Intermediate': [ ('advanced machine', 'เครื่องจักรทันสมัย'), ('experimental device', 'อุปกรณ์ทดลอง'), ], 'Advanced': [ ('groundbreaking discovery', 'การค้นพบที่ยิ่งใหญ่'), ('revolutionary invention', 'สิ่งประดิษฐ์ปฏิวัติโลก'), ] } } } def get_random_element(category: str) -> Tuple[str, str]: """Get random element from the specified category for current theme and level.""" elements = theme_elements.get(theme_id, {}).get(category, {}).get(level, []) if not elements: elements = theme_elements.get(theme_id, {}).get(category, {}).get('Beginner', []) return random.choice(elements) if elements else ('', '') # Get random elements character_en, character_th = get_random_element('characters') location_en, location_th = get_random_element('locations') object_en, object_th = get_random_element('objects') # Templates for different levels templates = { 'Beginner': { 'en': [ f"One day, {character_en} found {object_en} in {location_en}...", f"In {location_en}, {character_en} saw something special...", f"{character_en} was walking in {location_en} when suddenly...", f"The story begins when {character_en} discovered {object_en}...", ], 'th': [ f"วันหนึ่ง {character_th}เจอ{object_th}ใน{location_th}...", f"ที่{location_th} {character_th}เห็นบางสิ่งที่พิเศษ...", f"{character_th}กำลังเดินอยู่ใน{location_th} เมื่อจู่ๆ...", f"เรื่องราวเริ่มต้นเมื่อ{character_th}ค้นพบ{object_th}...", ] }, 'Intermediate': { 'en': [ f"While exploring {location_en}, {character_en} discovered {object_en} that seemed magical...", f"The story begins when {character_en} encountered a mysterious {object_en} in {location_en}...", f"Something strange was happening in {location_en}, and {character_en} knew it had to do with {object_en}...", f"Nobody knew why {character_en} found {object_en} in {location_en}, but...", ], 'th': [ f"ขณะที่สำรวจ{location_th} {character_th}ได้ค้นพบ{object_th}ที่ดูมีเวทมนตร์...", f"เรื่องราวเริ่มต้นเมื่อ{character_th}พบกับ{object_th}ที่ลึกลับใน{location_th}...", f"มีบางสิ่งประหลาดเกิดขึ้นใน{location_th} และ{character_th}รู้ว่ามันเกี่ยวข้องกับ{object_th}...", f"ไม่มีใครรู้ว่าทำไม{character_th}ถึงพบ{object_th}ใน{location_th} แต่...", ] }, 'Advanced': { 'en': [ f"Legend speaks of {object_en} hidden within {location_en}, and {character_en} was destined to find it...", f"In the depths of {location_en}, {character_en} uncovered an ancient mystery surrounding {object_en}...", f"As {character_en} ventured through {location_en}, the secrets of {object_en} began to unfold...", f"The discovery of {object_en} by {character_en} in {location_en} would change everything...", ], 'th': [ f"ตำนานเล่าขานถึง{object_th}ที่ซ่อนอยู่ใน{location_th} และ{character_th}ถูกลิขิตให้เป็นผู้ค้นพบ...", f"ในส่วนลึกของ{location_th} {character_th}ได้พบกับปริศนาโบราณเกี่ยวกับ{object_th}...", f"ขณะที่{character_th}ผจญภัยใน{location_th} ความลับของ{object_th}ก็เริ่มเผยออกมา...", f"การค้นพบ{object_th}โดย{character_th}ใน{location_th}จะเปลี่ยนแปลงทุกสิ่ง...", ] } } # Select random template for the current level level_templates = templates.get(level, templates['Beginner']) starter_en = random.choice(level_templates['en']) starter_th = random.choice(level_templates['th']) return { 'en': starter_en, 'th': starter_th } def convert_sets_to_lists(obj): """แปลง set เป็น list สำหรับการ serialize เป็น JSON""" if isinstance(obj, set): return list(obj) elif isinstance(obj, dict): return {key: convert_sets_to_lists(value) for key, value in obj.items()} elif isinstance(obj, list): return [convert_sets_to_lists(item) for item in obj] return obj def get_theme_story_starter(theme_id: str, level: str) -> Dict[str, str]: """Get a dynamically generated story starter for the selected theme and level.""" return generate_dynamic_story_starter(theme_id, level) def get_theme_vocabulary(theme_id: str, level: str) -> List[Dict[str, str]]: """ Get theme-specific vocabulary with Thai translations and example sentences. Returns list of dictionaries containing word, type, thai meaning, and example. """ vocab_data = { 'fantasy': { 'Beginner': [ { 'word': 'magic', 'type': 'noun', 'thai': 'เวทมนตร์', 'example_en': 'The magic made flowers appear.', 'example_th': 'เวทมนตร์ทำให้ดอกไม้ปรากฏขึ้น' }, { 'word': 'wizard', 'type': 'noun', 'thai': 'พ่อมด', 'example_en': 'The wizard waved his wand.', 'example_th': 'พ่อมดโบกไม้กายสิทธิ์' } ], 'Intermediate': [ { 'word': 'enchanted', 'type': 'adjective', 'thai': 'ที่ถูกสะกดด้วยเวทมนตร์', 'example_en': 'They found an enchanted forest.', 'example_th': 'พวกเขาพบป่าที่ถูกสะกดด้วยเวทมนตร์' } ] }, 'mystery': { 'Beginner': [ { 'word': 'clue', 'type': 'noun', 'thai': 'เบาะแส', 'example_en': 'The detective found an important clue.', 'example_th': 'นักสืบพบเบาะแสสำคัญ' } ] } } # แสดงคำศัพท์พร้อมตัวอย่างประโยคในหน้า UI def show_vocabulary(word_list: List[Dict[str, str]]): st.markdown("### 📚 คำศัพท์น่ารู้ประจำธีม") for word_data in word_list: st.markdown(f"""
💡 เคล็ดลับ: ให้น้องๆ พูดเรื่องราวที่อยากเขียนเป็นภาษาไทยก่อน แล้วค่อยๆ ช่วยกันแปลงเป็นภาษาอังกฤษ
🎬 เริ่มเรื่อง:
{entry.get('thai_content', '')}
{entry['content']}
🤖 AI: {entry['content']}
👤 You: {status_icon}{entry['content']}
Streak ปัจจุบัน: {st.session_state.points['streak']} ประโยค
Streak สูงสุด: {st.session_state.points['max_streak']} ประโยค
{st.session_state.theme_story_starter['th']}
{st.session_state.theme_story_starter['en']}
{feedback_data['feedback']}
ประโยคที่ถูกต้อง:
{feedback_data['corrected']}
{feedback_data.get('feedback', '✨ เขียนได้ถูกต้องแล้วค่ะ!')}