Update app.py
Browse files
app.py
CHANGED
@@ -13,6 +13,276 @@ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
|
|
13 |
from reportlab.pdfbase import pdfmetrics
|
14 |
from reportlab.pdfbase.ttfonts import TTFont
|
15 |
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
# ระบบ Achievements
|
18 |
achievements_list = {
|
@@ -226,6 +496,543 @@ def submit_story():
|
|
226 |
# Clear input
|
227 |
st.session_state.text_input = ""
|
228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
def show_welcome_section():
|
230 |
st.markdown("""
|
231 |
<div class="welcome-header">
|
@@ -773,10 +1580,31 @@ if st.session_state.should_reset:
|
|
773 |
reset_story()
|
774 |
|
775 |
# Main UI Layout
|
|
|
|
|
|
|
776 |
st.markdown("# 📖 JoyStory")
|
777 |
show_welcome_section()
|
778 |
show_parent_guide() # Add parent guide right after welcome section
|
779 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
780 |
# Sidebar for settings
|
781 |
with st.sidebar:
|
782 |
st.markdown("### 📂 โหลดความก้าวหน้า")
|
@@ -866,6 +1694,7 @@ with col1:
|
|
866 |
)
|
867 |
|
868 |
with col2:
|
|
|
869 |
if st.session_state.feedback:
|
870 |
st.markdown("""
|
871 |
<div class="thai-eng">
|
|
|
13 |
from reportlab.pdfbase import pdfmetrics
|
14 |
from reportlab.pdfbase.ttfonts import TTFont
|
15 |
from datetime import datetime
|
16 |
+
from typing import Dict, List, Optional, Tuple
|
17 |
+
import random
|
18 |
+
|
19 |
+
# Theme Configuration
|
20 |
+
story_themes = {
|
21 |
+
'fantasy': {
|
22 |
+
'id': 'fantasy',
|
23 |
+
'icon': '🏰',
|
24 |
+
'name_en': 'Fantasy & Magic',
|
25 |
+
'name_th': 'แฟนตาซีและเวทมนตร์',
|
26 |
+
'description_th': 'ผจญภัยในโลกแห่งเวทมนตร์และจินตนาการ',
|
27 |
+
'description_en': 'Adventure in a world of magic and imagination',
|
28 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
29 |
+
'vocabulary': {
|
30 |
+
'Beginner': ['dragon', 'magic', 'wand', 'spell', 'wizard', 'fairy', 'castle', 'king', 'queen'],
|
31 |
+
'Intermediate': ['potion', 'enchanted', 'castle', 'creature', 'power', 'scroll', 'portal', 'magical'],
|
32 |
+
'Advanced': ['sorcery', 'mystical', 'enchantment', 'prophecy', 'ancient', 'legendary', 'mythical']
|
33 |
+
},
|
34 |
+
'story_starters': {
|
35 |
+
'Beginner': [
|
36 |
+
{'th': 'วันหนึ่งฉันเจอไม้วิเศษในสวน...', 'en': 'One day, I found a magic wand in the garden...'},
|
37 |
+
{'th': 'มังกรน้อยกำลังมองหาเพื่อน...', 'en': 'The little dragon was looking for a friend...'},
|
38 |
+
{'th': 'เจ้าหญิงน้อยมีความลับวิเศษ...', 'en': 'The little princess had a magical secret...'}
|
39 |
+
],
|
40 |
+
'Intermediate': [
|
41 |
+
{'th': 'ในปราสาทเก่าแก่มีประตูลึกลับ...', 'en': 'In the ancient castle, there was a mysterious door...'},
|
42 |
+
{'th': 'เมื่อน้ำยาวิเศษเริ่มส่องแสง...', 'en': 'When the magic potion started to glow...'},
|
43 |
+
{'th': 'หนังสือเวทมนตร์เล่มนั้นเปิดออกเอง...', 'en': 'The spellbook opened by itself...'}
|
44 |
+
],
|
45 |
+
'Advanced': [
|
46 |
+
{'th': 'คำทำนายโบราณกล่าวถึงผู้วิเศษที่จะมา...', 'en': 'The ancient prophecy spoke of a wizard who would come...'},
|
47 |
+
{'th': 'ในโลกที่เวทมนตร์กำลังจะสูญหาย...', 'en': 'In a world where magic was fading away...'},
|
48 |
+
{'th': 'ณ จุดบรรจบของดวงดาวทั้งห้า...', 'en': 'At the convergence of the five stars...'}
|
49 |
+
]
|
50 |
+
},
|
51 |
+
'background_color': '#E8F3FF',
|
52 |
+
'accent_color': '#1E88E5'
|
53 |
+
},
|
54 |
+
'nature': {
|
55 |
+
'id': 'nature',
|
56 |
+
'icon': '🌳',
|
57 |
+
'name_en': 'Nature & Animals',
|
58 |
+
'name_th': 'ธรรมชาติและสัตว์โลก',
|
59 |
+
'description_th': 'เรื่องราวของสัตว์น้อยใหญ่และธรรมชาติอันงดงาม',
|
60 |
+
'description_en': 'Stories of animals and beautiful nature',
|
61 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
62 |
+
'vocabulary': {
|
63 |
+
'Beginner': ['tree', 'bird', 'flower', 'cat', 'dog', 'garden', 'rabbit', 'butterfly', 'sun'],
|
64 |
+
'Intermediate': ['forest', 'river', 'mountain', 'wildlife', 'season', 'weather', 'rainbow', 'stream'],
|
65 |
+
'Advanced': ['ecosystem', 'habitat', 'wilderness', 'environment', 'conservation', 'migration', 'climate']
|
66 |
+
},
|
67 |
+
'story_starters': {
|
68 |
+
'Beginner': [
|
69 |
+
{'th': 'แมวน้อยเจอนกในสวน...', 'en': 'The little cat found a bird in the garden...'},
|
70 |
+
{'th': 'ดอกไม้สวยกำลังเบ่งบาน...', 'en': 'The beautiful flower was blooming...'},
|
71 |
+
{'th': 'กระต่ายน้อยหลงทางในสวน...', 'en': 'The little rabbit got lost in the garden...'}
|
72 |
+
],
|
73 |
+
'Intermediate': [
|
74 |
+
{'th': 'ในป่าใหญ่มีเสียงลึกลับ...', 'en': 'In the big forest, there was a mysterious sound...'},
|
75 |
+
{'th': 'แม่น้ำสายนี้มีความลับ...', 'en': 'This river had a secret...'},
|
76 |
+
{'th': 'สายรุ้งพาดผ่านภูเขา...', 'en': 'A rainbow stretched across the mountain...'}
|
77 |
+
],
|
78 |
+
'Advanced': [
|
79 |
+
{'th': 'ฝูงนกกำลังอพยพย้ายถิ่น...', 'en': 'The birds were migrating...'},
|
80 |
+
{'th': 'ป่าฝนกำลังเปลี่ยนแปลง...', 'en': 'The rainforest was changing...'},
|
81 |
+
{'th': 'ค��ามลับของระบบนิเวศ...', 'en': 'The secret of the ecosystem...'}
|
82 |
+
]
|
83 |
+
},
|
84 |
+
'background_color': '#F1F8E9',
|
85 |
+
'accent_color': '#4CAF50'
|
86 |
+
},
|
87 |
+
'space': {
|
88 |
+
'id': 'space',
|
89 |
+
'icon': '🚀',
|
90 |
+
'name_en': 'Space Adventure',
|
91 |
+
'name_th': 'ผจญภัยในอวกาศ',
|
92 |
+
'description_th': 'เรื่องราวการสำรวจอวกาศและดวงดาวอันน่าตื่นเต้น',
|
93 |
+
'description_en': 'Exciting stories of space exploration and celestial discoveries',
|
94 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
95 |
+
'vocabulary': {
|
96 |
+
'Beginner': ['star', 'moon', 'planet', 'sun', 'rocket', 'alien', 'space', 'light'],
|
97 |
+
'Intermediate': ['astronaut', 'spacecraft', 'galaxy', 'meteor', 'satellite', 'orbit', 'comet'],
|
98 |
+
'Advanced': ['constellation', 'nebula', 'astronomy', 'telescope', 'exploration', 'discovery']
|
99 |
+
},
|
100 |
+
'story_starters': {
|
101 |
+
'Beginner': [
|
102 |
+
{'th': 'จรวดลำน้อยพร้อมบินแล้ว...', 'en': 'The little rocket was ready to fly...'},
|
103 |
+
{'th': 'ดาวดวงน้อยเปล่งแสงวิบวับ...', 'en': 'The little star twinkled brightly...'},
|
104 |
+
{'th': 'มนุษย์ต่างดาวที่เป็นมิตร...', 'en': 'The friendly alien...'}
|
105 |
+
],
|
106 |
+
'Intermediate': [
|
107 |
+
{'th': 'นักบินอวกาศพบสิ่งประหลาด...', 'en': 'The astronaut found something strange...'},
|
108 |
+
{'th': 'ดาวเคราะห์ดวงใหม่ถูกค้นพบ...', 'en': 'A new planet was discovered...'},
|
109 |
+
{'th': 'สถานีอวกาศส่งสัญญาณลึกลับ...', 'en': 'The space station sent a mysterious signal...'}
|
110 |
+
],
|
111 |
+
'Advanced': [
|
112 |
+
{'th': 'การสำรวจดาวหางนำไปสู่การค้นพบ...', 'en': 'The comet exploration led to a discovery...'},
|
113 |
+
{'th': 'กาแล็กซี่ที่ไม่มีใครเคยเห็น...', 'en': 'An unknown galaxy appeared...'},
|
114 |
+
{'th': 'ความลับของหลุมดำ...', 'en': 'The secret of the black hole...'}
|
115 |
+
]
|
116 |
+
},
|
117 |
+
'background_color': '#E1F5FE',
|
118 |
+
'accent_color': '#0288D1'
|
119 |
+
},
|
120 |
+
'adventure': {
|
121 |
+
'id': 'adventure',
|
122 |
+
'icon': '🗺️',
|
123 |
+
'name_en': 'Adventure & Quest',
|
124 |
+
'name_th': 'การผจญภัยและการค้นหา',
|
125 |
+
'description_th': 'ออกผจญภัยค้นหาสมบัติและความลับต่างๆ',
|
126 |
+
'description_en': 'Embark on quests to find treasures and secrets',
|
127 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
128 |
+
'vocabulary': {
|
129 |
+
'Beginner': ['map', 'treasure', 'cave', 'island', 'path', 'boat', 'key', 'chest'],
|
130 |
+
'Intermediate': ['compass', 'adventure', 'journey', 'mystery', 'explore', 'discover', 'quest'],
|
131 |
+
'Advanced': ['expedition', 'archaeology', 'artifact', 'ancient', 'mysterious', 'discovery']
|
132 |
+
},
|
133 |
+
'story_starters': {
|
134 |
+
'Beginner': [
|
135 |
+
{'th': 'แผนที่เก่าแก่ชิ้นหนึ่ง...', 'en': 'An old map showed...'},
|
136 |
+
{'th': 'บนเกาะเล็กๆ มีสมบัติ...', 'en': 'On a small island, there was a treasure...'},
|
137 |
+
{'th': 'ถ้ำลึกลับถูกค้นพบ...', 'en': 'A mysterious cave was found...'}
|
138 |
+
],
|
139 |
+
'Intermediate': [
|
140 |
+
{'th': 'เข็มทิศวิเศษชี้ไปที่...', 'en': 'The magical compass pointed to...'},
|
141 |
+
{'th': 'การเดินทางเริ่มต้นที่...', 'en': 'The journey began at...'},
|
142 |
+
{'th': 'ความลับของวัตถุโบราณ...', 'en': 'The secret of the ancient artifact...'}
|
143 |
+
],
|
144 |
+
'Advanced': [
|
145 |
+
{'th': 'การสำรวจซากปรักหักพังนำไปสู่...', 'en': 'The ruins exploration led to...'},
|
146 |
+
{'th': 'นักโบราณคดีค้นพบ...', 'en': 'The archaeologist discovered...'},
|
147 |
+
{'th': 'ความลับของอารยธรรมโบราณ...', 'en': 'The secret of the ancient civilization...'}
|
148 |
+
]
|
149 |
+
},
|
150 |
+
'background_color': '#FFF3E0',
|
151 |
+
'accent_color': '#FF9800'
|
152 |
+
},
|
153 |
+
'school': {
|
154 |
+
'id': 'school',
|
155 |
+
'icon': '🏫',
|
156 |
+
'name_en': 'School & Friends',
|
157 |
+
'name_th': 'โรงเรียนและเพื่อน',
|
158 |
+
'description_th': 'เรื่องราวสนุกๆ ในโรงเรียนกับเพื่อนๆ',
|
159 |
+
'description_en': 'Fun stories about school life and friendship',
|
160 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
161 |
+
'vocabulary': {
|
162 |
+
'Beginner': ['friend', 'teacher', 'book', 'classroom', 'pencil', 'desk', 'lunch', 'play'],
|
163 |
+
'Intermediate': ['homework', 'project', 'library', 'playground', 'student', 'lesson', 'study'],
|
164 |
+
'Advanced': ['presentation', 'experiment', 'knowledge', 'research', 'collaboration', 'achievement']
|
165 |
+
},
|
166 |
+
'story_starters': {
|
167 |
+
'Beginner': [
|
168 |
+
{'th': 'วันแรกในห้องเรียนใหม่...', 'en': 'First day in the new classroom...'},
|
169 |
+
{'th': 'เพื่อนใหม่ในโรงเรียน...', 'en': 'A new friend at school...'},
|
170 |
+
{'th': 'ที่โต๊ะอาหารกลางวัน...', 'en': 'At the lunch table...'}
|
171 |
+
],
|
172 |
+
'Intermediate': [
|
173 |
+
{'th': 'โครงงานพิเศษของห้องเรา...', 'en': 'Our class special project...'},
|
174 |
+
{'th': 'ในห้องสมุดมีความลับ...', 'en': 'The library had a secret...'},
|
175 |
+
{'th': 'การทดลองวิทยาศาสตร์ครั้งนี้...', 'en': 'This science experiment...'}
|
176 |
+
],
|
177 |
+
'Advanced': [
|
178 |
+
{'th': 'การนำเสนอครั้งสำคัญ...', 'en': 'The important presentation...'},
|
179 |
+
{'th': 'การค้นคว้าพิเศษนำไปสู่...', 'en': 'The special research led to...'},
|
180 |
+
{'th': 'โครงการความร่วมมือระหว่างห้อง...', 'en': 'The inter-class collaboration project...'}
|
181 |
+
]
|
182 |
+
},
|
183 |
+
'background_color': '#F3E5F5',
|
184 |
+
'accent_color': '#9C27B0'
|
185 |
+
},
|
186 |
+
'superhero': {
|
187 |
+
'id': 'superhero',
|
188 |
+
'icon': '🦸',
|
189 |
+
'name_en': 'Superheroes',
|
190 |
+
'name_th': 'ซูเปอร์ฮีโร่',
|
191 |
+
'description_th': 'เรื่องราวของฮีโร่ตัวน้อยผู้ช่วยเหลือผู้อื่น',
|
192 |
+
'description_en': 'Stories of young heroes helping others',
|
193 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
194 |
+
'vocabulary': {
|
195 |
+
'Beginner': ['hero', 'help', 'save', 'power', 'mask', 'cape', 'fly', 'strong'],
|
196 |
+
'Intermediate': ['rescue', 'protect', 'brave', 'courage', 'mission', 'team', 'secret', 'mighty'],
|
197 |
+
'Advanced': ['superhero', 'extraordinary', 'responsibility', 'leadership', 'determination', 'justice']
|
198 |
+
},
|
199 |
+
'story_starters': {
|
200 |
+
'Beginner': [
|
201 |
+
{'th': 'ฮีโร่น้อยคนใหม่ของเมือง...', 'en': 'The city\'s new young hero...'},
|
202 |
+
{'th': 'พลังพิเศษของฉันทำให้...', 'en': 'My special power made me...'},
|
203 |
+
{'th': 'เมื่อต้องช่วยเหลือแมวตัวน้อย...', 'en': 'When I had to save a little cat...'}
|
204 |
+
],
|
205 |
+
'Intermediate': [
|
206 |
+
{'th': 'ภารกิจลับของทีมฮีโร่...', 'en': 'The hero team\'s secret mission...'},
|
207 |
+
{'th': 'พลังใหม่ที่น่าประหลาดใจ...', 'en': 'A surprising new power...'},
|
208 |
+
{'th': 'การช่วยเหลือครั้งสำคัญ...', 'en': 'An important rescue mission...'}
|
209 |
+
],
|
210 |
+
'Advanced': [
|
211 |
+
{'th': 'ความรับผิดชอบของการเป็นฮีโร่...', 'en': 'The responsibility of being a hero...'},
|
212 |
+
{'th': 'เมื่อเมืองต้องการฮีโร่...', 'en': 'When the city needed a hero...'},
|
213 |
+
{'th': 'การต่อสู้เพื่อความยุติธรรม...', 'en': 'Fighting for justice...'}
|
214 |
+
]
|
215 |
+
},
|
216 |
+
'background_color': '#FFE0B2',
|
217 |
+
'accent_color': '#F57C00'
|
218 |
+
},
|
219 |
+
'mystery': {
|
220 |
+
'id': 'mystery',
|
221 |
+
'icon': '🔍',
|
222 |
+
'name_en': 'Mystery & Detective',
|
223 |
+
'name_th': 'ไขปริศนาและนักสืบ',
|
224 |
+
'description_th': 'สืบสวนปริศนาและไขความลับต่างๆ',
|
225 |
+
'description_en': 'Solve mysteries and uncover secrets',
|
226 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
227 |
+
'vocabulary': {
|
228 |
+
'Beginner': ['clue', 'find', 'look', 'search', 'mystery', 'hidden', 'secret', 'detective'],
|
229 |
+
'Intermediate': ['investigate', 'evidence', 'puzzle', 'solve', 'discover', 'suspicious', 'case'],
|
230 |
+
'Advanced': ['investigation', 'deduction', 'enigma', 'cryptic', 'mysterious', 'revelation']
|
231 |
+
},
|
232 |
+
'story_starters': {
|
233 |
+
'Beginner': [
|
234 |
+
{'th': 'มีรอยปริศนาในสวน...', 'en': 'There were mysterious footprints in the garden...'},
|
235 |
+
{'th': 'จดหมายลึกลับถูกส่งมา...', 'en': 'A mysterious letter arrived...'},
|
236 |
+
{'th': 'ของเล่นหายไปอย่างลึกลับ...', 'en': 'The toy mysteriously disappeared...'}
|
237 |
+
],
|
238 |
+
'Intermediate': [
|
239 |
+
{'th': 'เบาะแสชิ้นแรกนำไปสู่...', 'en': 'The first clue led to...'},
|
240 |
+
{'th': 'ความลับในห้องเก่า...', 'en': 'The secret in the old room...'},
|
241 |
+
{'th': 'รหัสลับถูกค้นพบ...', 'en': 'A secret code was found...'}
|
242 |
+
],
|
243 |
+
'Advanced': [
|
244 |
+
{'th': 'คดีปริศนาที่ยากที่สุด...', 'en': 'The most challenging mystery case...'},
|
245 |
+
{'th': 'ความลับที่ซ่อนอยู่มานาน...', 'en': 'A long-hidden secret...'},
|
246 |
+
{'th': 'การสืบสวนนำไปสู่การค้นพบ...', 'en': 'The investigation led to a discovery...'}
|
247 |
+
]
|
248 |
+
},
|
249 |
+
'background_color': '#E0E0E0',
|
250 |
+
'accent_color': '#616161'
|
251 |
+
},
|
252 |
+
'science': {
|
253 |
+
'id': 'science',
|
254 |
+
'icon': '🔬',
|
255 |
+
'name_en': 'Science & Discovery',
|
256 |
+
'name_th': 'วิทยาศาสตร์และการค้นพบ',
|
257 |
+
'description_th': 'การทดลองและค้นพบทางวิทยาศาสตร์ที่น่าตื่นเต้น',
|
258 |
+
'description_en': 'Exciting scientific experiments and discoveries',
|
259 |
+
'level_range': ['Beginner', 'Intermediate', 'Advanced'],
|
260 |
+
'vocabulary': {
|
261 |
+
'Beginner': ['experiment', 'science', 'lab', 'test', 'mix', 'observe', 'change', 'result'],
|
262 |
+
'Intermediate': ['hypothesis', 'research', 'discovery', 'invention', 'laboratory', 'scientist'],
|
263 |
+
'Advanced': ['innovation', 'technological', 'breakthrough', 'analysis', 'investigation']
|
264 |
+
},
|
265 |
+
'story_starters': {
|
266 |
+
'Beginner': [
|
267 |
+
{'th': 'การทดลองง่ายๆ เริ่มต้นด้วย...', 'en': 'The simple experiment started with...'},
|
268 |
+
{'th': 'ในห้องทดลองมีสิ่งมหัศจรรย์...', 'en': 'In the lab, there was something amazing...'},
|
269 |
+
{'th': 'เมื่อผสมสองสิ่งเข้าด้วยกัน...', 'en': 'When mixing the two things together...'}
|
270 |
+
],
|
271 |
+
'Intermediate': [
|
272 |
+
{'th': 'การค้นพบที่น่าประหลาดใจ...', 'en': 'A surprising discovery...'},
|
273 |
+
{'th': 'สิ่งประดิษฐ์ใหม่ทำให้...', 'en': 'The new invention made...'},
|
274 |
+
{'th': 'การทดลองที่ไม่คาดคิด...', 'en': 'An unexpected experiment...'}
|
275 |
+
],
|
276 |
+
'Advanced': [
|
277 |
+
{'th': 'นวัตกรรมที่จะเปลี่ยนโลก...', 'en': 'Innovation that would change the world...'},
|
278 |
+
{'th': 'การค้นพบทางวิทยาศาสตร์ครั้งสำคัญ...', 'en': 'An important scientific discovery...'},
|
279 |
+
{'th': 'เทคโนโลยีใหม่ที่น่าทึ่ง...', 'en': 'Amazing new technology...'}
|
280 |
+
]
|
281 |
+
},
|
282 |
+
'background_color': '#E8EAF6',
|
283 |
+
'accent_color': '#3F51B5'
|
284 |
+
}
|
285 |
+
}
|
286 |
|
287 |
# ระบบ Achievements
|
288 |
achievements_list = {
|
|
|
496 |
# Clear input
|
497 |
st.session_state.text_input = ""
|
498 |
|
499 |
+
# Theme Helper Functions
|
500 |
+
def get_available_themes(level: str) -> List[Dict]:
|
501 |
+
"""Get list of themes available for the current level."""
|
502 |
+
return [
|
503 |
+
theme for theme in story_themes.values()
|
504 |
+
if level in theme['level_range']
|
505 |
+
]
|
506 |
+
|
507 |
+
def generate_dynamic_story_starter(theme_id: str, level: str) -> Dict[str, str]:
|
508 |
+
"""
|
509 |
+
Dynamically generate a story starter based on theme and level.
|
510 |
+
Returns both Thai and English versions.
|
511 |
+
"""
|
512 |
+
theme = story_themes.get(theme_id, {})
|
513 |
+
|
514 |
+
# Theme-specific elements for dynamic generation
|
515 |
+
theme_elements = {
|
516 |
+
'fantasy': {
|
517 |
+
'characters': {
|
518 |
+
'Beginner': [
|
519 |
+
('young wizard', 'พ่อมดน้อย'),
|
520 |
+
('fairy', 'นางฟ้า'),
|
521 |
+
('friendly dragon', 'มังกรใจดี'),
|
522 |
+
('magical cat', 'แมวเวทมนตร์'),
|
523 |
+
],
|
524 |
+
'Intermediate': [
|
525 |
+
('mysterious wizard', 'พ่อมดลึกลับ'),
|
526 |
+
('ancient dragon', 'มังกรโบราณ'),
|
527 |
+
('enchanted princess', 'เจ้าหญิงต้องมนตร์'),
|
528 |
+
],
|
529 |
+
'Advanced': [
|
530 |
+
('legendary sorcerer', 'จอมเวทในตำนาน'),
|
531 |
+
('mythical creature', 'สัตว์ในตำนาน'),
|
532 |
+
('wise elder wizard', 'พ่อมดผู้เฒ่าผู้เป็นปราชญ์'),
|
533 |
+
]
|
534 |
+
},
|
535 |
+
'locations': {
|
536 |
+
'Beginner': [
|
537 |
+
('magical garden', 'สวนเวทมนตร์'),
|
538 |
+
('enchanted forest', 'ป่าวิเศษ'),
|
539 |
+
],
|
540 |
+
'Intermediate': [
|
541 |
+
('ancient castle', 'ปราสาทโบราณ'),
|
542 |
+
('wizard school', 'โรงเรียนเวทมนตร์'),
|
543 |
+
],
|
544 |
+
'Advanced': [
|
545 |
+
('mystical realm', 'อาณาจักรเวทมนตร์'),
|
546 |
+
('floating islands', 'เกาะลอยฟ้า'),
|
547 |
+
]
|
548 |
+
},
|
549 |
+
'objects': {
|
550 |
+
'Beginner': [
|
551 |
+
('magic wand', 'ไม้กายสิทธิ์'),
|
552 |
+
('glowing crystal', 'คริสตัลเรืองแสง'),
|
553 |
+
],
|
554 |
+
'Intermediate': [
|
555 |
+
('ancient spellbook', 'ตำราเวทโบราณ'),
|
556 |
+
('magical artifact', 'วัตถุวิเศษ'),
|
557 |
+
],
|
558 |
+
'Advanced': [
|
559 |
+
('legendary sword', 'ดาบในตำนาน'),
|
560 |
+
('mystical orb', 'ลูกแก้ววิเศษ'),
|
561 |
+
]
|
562 |
+
}
|
563 |
+
},
|
564 |
+
'nature': {
|
565 |
+
'characters': {
|
566 |
+
'Beginner': [
|
567 |
+
('little bird', 'นกน้อย'),
|
568 |
+
('friendly squirrel', 'กระรอกน้อยใจดี'),
|
569 |
+
('playful rabbit', 'กระต่ายซน'),
|
570 |
+
],
|
571 |
+
'Intermediate': [
|
572 |
+
('wise owl', 'นกฮูกผู้รอบรู้'),
|
573 |
+
('busy beaver', 'บีเวอร์ขยัน'),
|
574 |
+
('clever fox', 'จิ้งจอกเจ้าปัญญา'),
|
575 |
+
],
|
576 |
+
'Advanced': [
|
577 |
+
('majestic eagle', 'อินทรีผู้สง่างาม'),
|
578 |
+
('mysterious panther', 'เสือดำลึกลับ'),
|
579 |
+
]
|
580 |
+
},
|
581 |
+
'locations': {
|
582 |
+
'Beginner': [
|
583 |
+
('flower garden', 'สวนดอกไม้'),
|
584 |
+
('small pond', 'สระน้ำเล็กๆ'),
|
585 |
+
],
|
586 |
+
'Intermediate': [
|
587 |
+
('deep forest', 'ป่าลึก'),
|
588 |
+
('mountain peak', 'ยอดเขาสูง'),
|
589 |
+
],
|
590 |
+
'Advanced': [
|
591 |
+
('ancient rainforest', 'ป่าดึกดำบรรพ์'),
|
592 |
+
('hidden valley', 'หุบเขาซ่อนเร้น'),
|
593 |
+
]
|
594 |
+
},
|
595 |
+
'objects': {
|
596 |
+
'Beginner': [
|
597 |
+
('colorful flower', 'ดอกไม้สีสวย'),
|
598 |
+
('fallen leaf', 'ใบไม้ร่วง'),
|
599 |
+
],
|
600 |
+
'Intermediate': [
|
601 |
+
('old tree', 'ต้นไม้เก่าแก่'),
|
602 |
+
('clear stream', 'ลำธารใส'),
|
603 |
+
],
|
604 |
+
'Advanced': [
|
605 |
+
('rare plant', 'พืชหายาก'),
|
606 |
+
('ancient tree', 'ต้นไม้โบราณ'),
|
607 |
+
]
|
608 |
+
}
|
609 |
+
},
|
610 |
+
'space': {
|
611 |
+
'characters': {
|
612 |
+
'Beginner': [
|
613 |
+
('friendly alien', 'มนุษย์ต่างดาวใจดี'),
|
614 |
+
('little astronaut', 'นักบินอวกาศตัวน้อย'),
|
615 |
+
('space robot', 'หุ่นยนต์อวกาศ'),
|
616 |
+
],
|
617 |
+
'Intermediate': [
|
618 |
+
('space explorer', 'นักสำรวจอวกาศ'),
|
619 |
+
('alien scientist', 'นักวิทยาศาสตร์ต่างดาว'),
|
620 |
+
('space pilot', 'นักบินยานอวกาศ'),
|
621 |
+
],
|
622 |
+
'Advanced': [
|
623 |
+
('galactic commander', 'ผู้บัญชาการก���แล็กซี่'),
|
624 |
+
('space archaeologist', 'นักโบราณคดีอวกาศ'),
|
625 |
+
]
|
626 |
+
},
|
627 |
+
'locations': {
|
628 |
+
'Beginner': [
|
629 |
+
('small planet', 'ดาวเคราะห์เล็กๆ'),
|
630 |
+
('space station', 'สถานีอวกาศ'),
|
631 |
+
],
|
632 |
+
'Intermediate': [
|
633 |
+
('mysterious galaxy', 'กาแล็กซี่ลึกลับ'),
|
634 |
+
('alien world', 'โลกต่างดาว'),
|
635 |
+
],
|
636 |
+
'Advanced': [
|
637 |
+
('black hole', 'หลุมดำ'),
|
638 |
+
('distant nebula', 'เนบิวลาไกลโพ้น'),
|
639 |
+
]
|
640 |
+
},
|
641 |
+
'objects': {
|
642 |
+
'Beginner': [
|
643 |
+
('shiny meteor', 'ดาวตกเปล่งประกาย'),
|
644 |
+
('space telescope', 'กล้องดูดาว'),
|
645 |
+
],
|
646 |
+
'Intermediate': [
|
647 |
+
('advanced spaceship', 'ยานอวกาศลำใหม่'),
|
648 |
+
('mysterious signal', 'สัญญาณลึกลับ'),
|
649 |
+
],
|
650 |
+
'Advanced': [
|
651 |
+
('alien artifact', 'วัตถุโบราณจากต่างดาว'),
|
652 |
+
('space anomaly', 'ความผิดปกติในอวกาศ'),
|
653 |
+
]
|
654 |
+
}
|
655 |
+
},
|
656 |
+
'adventure': {
|
657 |
+
'characters': {
|
658 |
+
'Beginner': [
|
659 |
+
('young explorer', 'นักผจญภัยตัวน้อย'),
|
660 |
+
('treasure hunter', 'นักล่าสมบัติ'),
|
661 |
+
('brave sailor', 'กะลาสีผู้กล้า'),
|
662 |
+
],
|
663 |
+
'Intermediate': [
|
664 |
+
('experienced guide', 'ไกด์ผู้ชำนาญ'),
|
665 |
+
('mysterious traveler', 'นักเดินทางลึกลับ'),
|
666 |
+
],
|
667 |
+
'Advanced': [
|
668 |
+
('legendary explorer', 'นักสำรวจในตำนาน'),
|
669 |
+
('ancient guardian', 'ผู้พิทักษ์โบราณ'),
|
670 |
+
]
|
671 |
+
},
|
672 |
+
'locations': {
|
673 |
+
'Beginner': [
|
674 |
+
('hidden cave', 'ถ้ำซ่อนเร้น'),
|
675 |
+
('treasure island', 'เกาะสมบัติ'),
|
676 |
+
],
|
677 |
+
'Intermediate': [
|
678 |
+
('ancient ruins', 'ซากปรักหักพัง'),
|
679 |
+
('mysterious temple', 'วัดลึกลับ'),
|
680 |
+
],
|
681 |
+
'Advanced': [
|
682 |
+
('lost city', 'เมืองที่สาบสูญ'),
|
683 |
+
('forbidden valley', 'หุบเขาต้องห้าม'),
|
684 |
+
]
|
685 |
+
},
|
686 |
+
'objects': {
|
687 |
+
'Beginner': [
|
688 |
+
('old map', 'แผนที่เก่า'),
|
689 |
+
('golden compass', 'เข็มทิศทองคำ'),
|
690 |
+
],
|
691 |
+
'Intermediate': [
|
692 |
+
('ancient scroll', 'ม้วนกระดาษโบราณ'),
|
693 |
+
('magical key', 'กุญแจวิเศษ'),
|
694 |
+
],
|
695 |
+
'Advanced': [
|
696 |
+
('legendary artifact', 'วัตถุโบราณในตำนาน'),
|
697 |
+
('sacred relic', 'วัตถุศักดิ์สิทธิ์'),
|
698 |
+
]
|
699 |
+
}
|
700 |
+
},
|
701 |
+
'school': {
|
702 |
+
'characters': {
|
703 |
+
'Beginner': [
|
704 |
+
('new student', 'นักเรียนใหม่'),
|
705 |
+
('kind teacher', 'คุณครูใจดี'),
|
706 |
+
('best friend', 'เพื่อนรัก'),
|
707 |
+
],
|
708 |
+
'Intermediate': [
|
709 |
+
('class president', 'หัวหน้าห้อง'),
|
710 |
+
('school librarian', 'บรรณารักษ์'),
|
711 |
+
],
|
712 |
+
'Advanced': [
|
713 |
+
('exchange student', 'นักเรียนแลกเปลี่ยน'),
|
714 |
+
('science genius', 'อัจฉริยะวิทยาศาสตร์'),
|
715 |
+
]
|
716 |
+
},
|
717 |
+
'locations': {
|
718 |
+
'Beginner': [
|
719 |
+
('classroom', 'ห้องเรียน'),
|
720 |
+
('school playground', 'สนามเด็กเล่น'),
|
721 |
+
],
|
722 |
+
'Intermediate': [
|
723 |
+
('science lab', 'ห้องทดลองวิทยาศาสตร์'),
|
724 |
+
('school library', 'ห้องสมุด'),
|
725 |
+
],
|
726 |
+
'Advanced': [
|
727 |
+
('school theater', 'โรงละครโรงเรียน'),
|
728 |
+
('computer room', 'ห้องคอมพิวเตอร์'),
|
729 |
+
]
|
730 |
+
},
|
731 |
+
'objects': {
|
732 |
+
'Beginner': [
|
733 |
+
('new book', 'หนังสือเล่มใหม่'),
|
734 |
+
('special pencil', 'ดินสอวิเศษ'),
|
735 |
+
],
|
736 |
+
'Intermediate': [
|
737 |
+
('science project', 'โครงงานวิทยาศาสตร์'),
|
738 |
+
('old diary', 'ไดอารี่เก่า'),
|
739 |
+
],
|
740 |
+
'Advanced': [
|
741 |
+
('robotics kit', 'ชุดประดิษฐ์หุ่นยนต์'),
|
742 |
+
('ancient textbook', 'ตำราเรียนโบราณ'),
|
743 |
+
]
|
744 |
+
}
|
745 |
+
},
|
746 |
+
'superhero': {
|
747 |
+
'characters': {
|
748 |
+
'Beginner': [
|
749 |
+
('young hero', 'ฮีโร่ตัวน้อย'),
|
750 |
+
('super pet', 'สัตว์เลี้ยงพลังพิเศษ'),
|
751 |
+
('friendly sidekick', 'ผู้ช่วยฮีโร่'),
|
752 |
+
],
|
753 |
+
'Intermediate': [
|
754 |
+
('masked vigilante', 'ฮีโร่ปริศนา'),
|
755 |
+
('super teacher', 'คุณครูพลังพิเศษ'),
|
756 |
+
],
|
757 |
+
'Advanced': [
|
758 |
+
('legendary hero', 'ฮีโร่ในตำนาน'),
|
759 |
+
('protector of justice', 'ผู้พิทักษ์ความยุติธรรม'),
|
760 |
+
]
|
761 |
+
},
|
762 |
+
'locations': {
|
763 |
+
'Beginner': [
|
764 |
+
('hero school', 'โรงเรียนฮีโร่'),
|
765 |
+
('secret hideout', 'ที่ซ่อนลับ'),
|
766 |
+
],
|
767 |
+
'Intermediate': [
|
768 |
+
('hero headquarters', 'ศูนย์บัญชาการฮีโร่'),
|
769 |
+
('training ground', 'สนามฝึกซ้อม'),
|
770 |
+
],
|
771 |
+
'Advanced': [
|
772 |
+
('hero academy', 'สถาบันฝึกฮีโร่'),
|
773 |
+
('crisis center', 'ศูนย์รับมือวิกฤต'),
|
774 |
+
]
|
775 |
+
},
|
776 |
+
'objects': {
|
777 |
+
'Beginner': [
|
778 |
+
('hero mask', 'หน้ากากฮีโร่'),
|
779 |
+
('power crystal', 'คริสตัลพลัง'),
|
780 |
+
],
|
781 |
+
'Intermediate': [
|
782 |
+
('super gadget', 'อุปกรณ์พิเศษ'),
|
783 |
+
('power suit', 'ชุดพลังพิเศษ'),
|
784 |
+
],
|
785 |
+
'Advanced': [
|
786 |
+
('ultimate weapon', 'อาวุธสุดยอด'),
|
787 |
+
('ancient power source', 'แหล่งพลังโบราณ'),
|
788 |
+
]
|
789 |
+
}
|
790 |
+
},
|
791 |
+
'mystery': {
|
792 |
+
'characters': {
|
793 |
+
'Beginner': [
|
794 |
+
('young detective', 'นักสืบตัวน้อย'),
|
795 |
+
('mysterious neighbor', 'เพื่อนบ้านปริศนา'),
|
796 |
+
('helpful friend', 'เพื่อนผู้ช่วย'),
|
797 |
+
],
|
798 |
+
'Intermediate': [
|
799 |
+
('famous detective', 'นักสืบชื่อดัง'),
|
800 |
+
('mystery writer', 'นักเขียนนิยายปริศนา'),
|
801 |
+
],
|
802 |
+
'Advanced': [
|
803 |
+
('master detective', 'ยอดนักสืบ'),
|
804 |
+
('crime expert', 'ผู้เชี่ยวชาญคดี'),
|
805 |
+
]
|
806 |
+
},
|
807 |
+
'locations': {
|
808 |
+
'Beginner': [
|
809 |
+
('old house', 'บ้านเก่า'),
|
810 |
+
('mystery shop', 'ร้านค้าปริศนา'),
|
811 |
+
],
|
812 |
+
'Intermediate': [
|
813 |
+
('abandoned building', 'ตึกร้าง'),
|
814 |
+
('detective office', 'สำนักงานนักสืบ'),
|
815 |
+
],
|
816 |
+
'Advanced': [
|
817 |
+
('secret laboratory', 'ห้องทดลองลับ'),
|
818 |
+
('mystery mansion', 'คฤหาสน์ปริศนา'),
|
819 |
+
]
|
820 |
+
},
|
821 |
+
'objects': {
|
822 |
+
'Beginner': [
|
823 |
+
('mysterious letter', 'จดหมายปริศนา'),
|
824 |
+
('strange footprint', 'รอยเท้าประหลาด'),
|
825 |
+
],
|
826 |
+
'Intermediate': [
|
827 |
+
('ancient cipher', 'รหัสลับโบราณ'),
|
828 |
+
('hidden clue', '���บาะแสซ่อนเร้น'),
|
829 |
+
],
|
830 |
+
'Advanced': [
|
831 |
+
('secret document', 'เอกสารลับ'),
|
832 |
+
('mysterious artifact', 'วัตถุปริศนา'),
|
833 |
+
]
|
834 |
+
}
|
835 |
+
},
|
836 |
+
'science': {
|
837 |
+
'characters': {
|
838 |
+
'Beginner': [
|
839 |
+
('young scientist', 'นักวิทยาศาสตร์ตัวน้อย'),
|
840 |
+
('robot friend', 'หุ่นยนต์เพื่อนรัก'),
|
841 |
+
('curious student', 'นักเรียนช่างสงสัย'),
|
842 |
+
],
|
843 |
+
'Intermediate': [
|
844 |
+
('brilliant inventor', 'นักประดิษฐ์อัจฉริยะ'),
|
845 |
+
('science teacher', 'คุณครูวิทยาศาสตร์'),
|
846 |
+
],
|
847 |
+
'Advanced': [
|
848 |
+
('famous researcher', 'นักวิจัยชื่อดัง'),
|
849 |
+
('genius professor', 'ศาสตราจารย์อัจฉริยะ'),
|
850 |
+
]
|
851 |
+
},
|
852 |
+
'locations': {
|
853 |
+
'Beginner': [
|
854 |
+
('science lab', 'ห้องทดลองวิทยาศาสตร์'),
|
855 |
+
('invention workshop', 'ห้องประดิษฐ์'),
|
856 |
+
],
|
857 |
+
'Intermediate': [
|
858 |
+
('research center', 'ศูนย์วิจัย'),
|
859 |
+
('robotics lab', 'ห้องปฏิบัติการหุ่นยนต์'),
|
860 |
+
],
|
861 |
+
'Advanced': [
|
862 |
+
('quantum laboratory', 'ห้องปฏิบัติการควอนตัม'),
|
863 |
+
('innovation center', 'ศูนย์นวัตกรรม'),
|
864 |
+
]
|
865 |
+
},
|
866 |
+
'objects': {
|
867 |
+
'Beginner': [
|
868 |
+
('colorful chemical', 'สารเคมีสีสันสดใส'),
|
869 |
+
('strange invention', 'สิ่งประดิษฐ์แปลกใหม่'),
|
870 |
+
],
|
871 |
+
'Intermediate': [
|
872 |
+
('advanced machine', 'เครื่องจักรทันสมัย'),
|
873 |
+
('experimental device', 'อุปกรณ์ทดลอง'),
|
874 |
+
],
|
875 |
+
'Advanced': [
|
876 |
+
('groundbreaking discovery', 'การค้นพบที่ยิ่งใหญ่'),
|
877 |
+
('revolutionary invention', 'สิ่งประดิษฐ์ปฏิวัติโลก'),
|
878 |
+
]
|
879 |
+
}
|
880 |
+
}
|
881 |
+
}
|
882 |
+
|
883 |
+
def get_random_element(category: str) -> Tuple[str, str]:
|
884 |
+
"""Get random element from the specified category for current theme and level."""
|
885 |
+
elements = theme_elements.get(theme_id, {}).get(category, {}).get(level, [])
|
886 |
+
if not elements:
|
887 |
+
elements = theme_elements.get(theme_id, {}).get(category, {}).get('Beginner', [])
|
888 |
+
return random.choice(elements) if elements else ('', '')
|
889 |
+
|
890 |
+
# Get random elements
|
891 |
+
character_en, character_th = get_random_element('characters')
|
892 |
+
location_en, location_th = get_random_element('locations')
|
893 |
+
object_en, object_th = get_random_element('objects')
|
894 |
+
|
895 |
+
# Templates for different levels
|
896 |
+
templates = {
|
897 |
+
'Beginner': {
|
898 |
+
'en': [
|
899 |
+
f"One day, {character_en} found {object_en} in {location_en}...",
|
900 |
+
f"In {location_en}, {character_en} saw something special...",
|
901 |
+
f"{character_en} was walking in {location_en} when suddenly...",
|
902 |
+
f"The story begins when {character_en} discovered {object_en}...",
|
903 |
+
],
|
904 |
+
'th': [
|
905 |
+
f"วันหนึ่ง {character_th}เจอ{object_th}ใน{location_th}...",
|
906 |
+
f"ที่{location_th} {character_th}เห็นบางสิ่งที่พิเศษ...",
|
907 |
+
f"{character_th}กำลังเดินอยู่ใน{location_th} เมื่อจู่ๆ...",
|
908 |
+
f"เรื่องราวเริ่มต้นเมื่อ{character_th}ค้นพบ{object_th}...",
|
909 |
+
]
|
910 |
+
},
|
911 |
+
'Intermediate': {
|
912 |
+
'en': [
|
913 |
+
f"While exploring {location_en}, {character_en} discovered {object_en} that seemed magical...",
|
914 |
+
f"The story begins when {character_en} encountered a mysterious {object_en} in {location_en}...",
|
915 |
+
f"Something strange was happening in {location_en}, and {character_en} knew it had to do with {object_en}...",
|
916 |
+
f"Nobody knew why {character_en} found {object_en} in {location_en}, but...",
|
917 |
+
],
|
918 |
+
'th': [
|
919 |
+
f"ขณะที่สำรวจ{location_th} {character_th}ได้ค้นพบ{object_th}ที่ดูม���เวทมนตร์...",
|
920 |
+
f"เรื่องราวเริ่มต้นเมื่อ{character_th}พบกับ{object_th}ที่ลึกลับใน{location_th}...",
|
921 |
+
f"มีบางสิ่งประหลาดเกิดขึ้นใน{location_th} และ{character_th}รู้ว่ามันเกี่ยวข้องกับ{object_th}...",
|
922 |
+
f"ไม่มีใครรู้ว่าทำไม{character_th}ถึงพบ{object_th}ใน{location_th} แต่...",
|
923 |
+
]
|
924 |
+
},
|
925 |
+
'Advanced': {
|
926 |
+
'en': [
|
927 |
+
f"Legend speaks of {object_en} hidden within {location_en}, and {character_en} was destined to find it...",
|
928 |
+
f"In the depths of {location_en}, {character_en} uncovered an ancient mystery surrounding {object_en}...",
|
929 |
+
f"As {character_en} ventured through {location_en}, the secrets of {object_en} began to unfold...",
|
930 |
+
f"The discovery of {object_en} by {character_en} in {location_en} would change everything...",
|
931 |
+
],
|
932 |
+
'th': [
|
933 |
+
f"ตำนานเล่าขานถึง{object_th}ที่ซ่อนอยู่ใน{location_th} และ{character_th}ถูกลิขิตให้เป็นผู้ค้นพบ...",
|
934 |
+
f"ในส่วนลึกของ{location_th} {character_th}ได้พบกับปริศนาโบราณเกี่ยวกับ{object_th}...",
|
935 |
+
f"ขณะที่{character_th}ผจญภัยใน{location_th} ความลับของ{object_th}ก็เริ่มเผยออกมา...",
|
936 |
+
f"การค้นพบ{object_th}โดย{character_th}ใน{location_th}จะเปลี่ยนแปลงทุกสิ่ง...",
|
937 |
+
]
|
938 |
+
}
|
939 |
+
}
|
940 |
+
|
941 |
+
# Select random template for the current level
|
942 |
+
level_templates = templates.get(level, templates['Beginner'])
|
943 |
+
starter_en = random.choice(level_templates['en'])
|
944 |
+
starter_th = random.choice(level_templates['th'])
|
945 |
+
|
946 |
+
return {
|
947 |
+
'en': starter_en,
|
948 |
+
'th': starter_th
|
949 |
+
}
|
950 |
+
|
951 |
+
|
952 |
+
|
953 |
+
def get_theme_story_starter(theme_id: str, level: str) -> Dict[str, str]:
|
954 |
+
"""Get a dynamically generated story starter for the selected theme and level."""
|
955 |
+
return generate_dynamic_story_starter(theme_id, level)
|
956 |
+
|
957 |
+
def get_theme_vocabulary(theme_id: str, level: str) -> List[str]:
|
958 |
+
"""Get vocabulary list for the selected theme and level."""
|
959 |
+
theme = story_themes.get(theme_id)
|
960 |
+
if not theme:
|
961 |
+
return []
|
962 |
+
return theme['vocabulary'].get(level, [])
|
963 |
+
|
964 |
+
# Add to session state initialization
|
965 |
+
def init_theme_state():
|
966 |
+
if 'current_theme' not in st.session_state:
|
967 |
+
st.session_state.current_theme = None
|
968 |
+
if 'theme_story_starter' not in st.session_state:
|
969 |
+
st.session_state.theme_story_starter = None
|
970 |
+
|
971 |
+
# Theme Selection UI
|
972 |
+
def show_theme_selection():
|
973 |
+
st.markdown("""
|
974 |
+
<div class="thai-eng">
|
975 |
+
<div class="thai">🎨 เลือกธีมเรื่องราว</div>
|
976 |
+
<div class="eng">Choose Story Theme</div>
|
977 |
+
</div>
|
978 |
+
""", unsafe_allow_html=True)
|
979 |
+
|
980 |
+
available_themes = get_available_themes(st.session_state.level)
|
981 |
+
|
982 |
+
# Create theme selection cards
|
983 |
+
cols = st.columns(2)
|
984 |
+
for idx, theme in enumerate(available_themes):
|
985 |
+
with cols[idx % 2]:
|
986 |
+
theme_card = f"""
|
987 |
+
<div style="
|
988 |
+
background-color: {theme['background_color']};
|
989 |
+
padding: 15px;
|
990 |
+
border-radius: 10px;
|
991 |
+
margin: 5px 0;
|
992 |
+
border: 2px solid {theme['accent_color']};
|
993 |
+
cursor: pointer;
|
994 |
+
">
|
995 |
+
<h3>{theme['icon']} {theme['name_th']}</h3>
|
996 |
+
<p style="font-size: 0.9em; color: #666;">
|
997 |
+
{theme['description_th']}
|
998 |
+
</p>
|
999 |
+
</div>
|
1000 |
+
"""
|
1001 |
+
if st.markdown(theme_card, unsafe_allow_html=True):
|
1002 |
+
st.session_state.current_theme = theme['id']
|
1003 |
+
st.session_state.theme_story_starter = get_theme_story_starter(theme['id'], st.session_state.level)
|
1004 |
+
|
1005 |
+
# Add theme-specific CSS
|
1006 |
+
def add_theme_css():
|
1007 |
+
st.markdown("""
|
1008 |
+
<style>
|
1009 |
+
.theme-card {
|
1010 |
+
transition: transform 0.2s;
|
1011 |
+
}
|
1012 |
+
.theme-card:hover {
|
1013 |
+
transform: translateY(-2px);
|
1014 |
+
}
|
1015 |
+
.theme-vocabulary {
|
1016 |
+
background-color: #f8f9fa;
|
1017 |
+
padding: 10px;
|
1018 |
+
border-radius: 8px;
|
1019 |
+
margin: 5px 0;
|
1020 |
+
}
|
1021 |
+
</style>
|
1022 |
+
""", unsafe_allow_html=True)
|
1023 |
+
|
1024 |
+
# Theme-specific vocabulary suggestions
|
1025 |
+
def show_theme_vocabulary():
|
1026 |
+
if st.session_state.current_theme:
|
1027 |
+
vocab_list = get_theme_vocabulary(
|
1028 |
+
st.session_state.current_theme,
|
1029 |
+
st.session_state.level
|
1030 |
+
)
|
1031 |
+
if vocab_list:
|
1032 |
+
st.markdown("### 📚 Theme Vocabulary")
|
1033 |
+
for word in vocab_list:
|
1034 |
+
st.markdown(f"- {word}")
|
1035 |
+
|
1036 |
def show_welcome_section():
|
1037 |
st.markdown("""
|
1038 |
<div class="welcome-header">
|
|
|
1580 |
reset_story()
|
1581 |
|
1582 |
# Main UI Layout
|
1583 |
+
# In your main UI section, after init_session_state()
|
1584 |
+
init_theme_state()
|
1585 |
+
add_theme_css()
|
1586 |
st.markdown("# 📖 JoyStory")
|
1587 |
show_welcome_section()
|
1588 |
show_parent_guide() # Add parent guide right after welcome section
|
1589 |
|
1590 |
+
# After showing the welcome section and before the main story area
|
1591 |
+
if not st.session_state.current_theme:
|
1592 |
+
show_theme_selection()
|
1593 |
+
else:
|
1594 |
+
# Show current theme and option to change
|
1595 |
+
if st.button("🔄 Change Theme"):
|
1596 |
+
st.session_state.current_theme = None
|
1597 |
+
st.rerun()
|
1598 |
+
|
1599 |
+
# Show theme-specific story starter if no story has been started
|
1600 |
+
if not st.session_state.story and st.session_state.theme_story_starter:
|
1601 |
+
st.markdown(f"""
|
1602 |
+
<div class="story-starter">
|
1603 |
+
<p class="thai">{st.session_state.theme_story_starter['th']}</p>
|
1604 |
+
<p class="eng">{st.session_state.theme_story_starter['en']}</p>
|
1605 |
+
</div>
|
1606 |
+
""", unsafe_allow_html=True)
|
1607 |
+
|
1608 |
# Sidebar for settings
|
1609 |
with st.sidebar:
|
1610 |
st.markdown("### 📂 โหลดความก้าวหน้า")
|
|
|
1694 |
)
|
1695 |
|
1696 |
with col2:
|
1697 |
+
show_theme_vocabulary()
|
1698 |
if st.session_state.feedback:
|
1699 |
st.markdown("""
|
1700 |
<div class="thai-eng">
|