Update app.py
Browse files
app.py
CHANGED
@@ -1,15 +1,261 @@
|
|
1 |
-
import
|
2 |
-
|
3 |
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
-
#
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import random
|
3 |
|
4 |
+
#########################
|
5 |
+
# ฟังก์ชันคำนวณง่าย ๆ
|
6 |
+
#########################
|
7 |
|
8 |
+
def approximate_temperature(planet_type, distance_au):
|
9 |
+
"""
|
10 |
+
คำนวณอุณหภูมิ (สมมุติเบื้องต้น) ตามชนิดดาว + ระยะ AU
|
11 |
+
"""
|
12 |
+
# กำหนด base_temp
|
13 |
+
if planet_type == "ดาวหิน (Rocky Planet)":
|
14 |
+
base_temp = 15
|
15 |
+
elif planet_type == "ดาวก๊าซ (Gas Giant)":
|
16 |
+
base_temp = 30
|
17 |
+
elif planet_type == "ดาวน้ำแข็ง (Icy Planet)":
|
18 |
+
base_temp = -50
|
19 |
+
else:
|
20 |
+
base_temp = 0
|
21 |
|
22 |
+
# ปรับตามระยะทาง
|
23 |
+
if distance_au > 1.0:
|
24 |
+
diff = (distance_au - 1.0) * 20
|
25 |
+
approx_temp = base_temp - diff
|
26 |
+
else:
|
27 |
+
diff = (1.0 - distance_au) * 30
|
28 |
+
approx_temp = base_temp + diff
|
29 |
|
30 |
+
return round(approx_temp)
|
31 |
+
|
32 |
+
def approximate_gravity(diameter_earth):
|
33 |
+
"""
|
34 |
+
แรงโน้มถ่วงสมมุติ (g) = diameter_earth เท่า
|
35 |
+
"""
|
36 |
+
return round(1.0 * diameter_earth, 2)
|
37 |
+
|
38 |
+
#########################
|
39 |
+
# ฟังก์ชันสรุปข้อมูล (สำหรับเด็ก)
|
40 |
+
#########################
|
41 |
+
def child_friendly_summary(
|
42 |
+
name_th, planet_type_th, temp_c, gravity_g, atmosphere_th, life_th
|
43 |
+
):
|
44 |
+
"""
|
45 |
+
สร้างข้อความสรุป (ภาษาไทย) ให้เด็กอ่านเข้าใจง่าย
|
46 |
+
เช่น "ดาว ซานาดา เป็นดาวหิน อุณหภูมิใกล้ๆ 20°C มีบรรยากาศ..."
|
47 |
+
"""
|
48 |
+
if temp_c > 40:
|
49 |
+
temp_comment = "ค่อนข้างร้อนเลยนะ!"
|
50 |
+
elif temp_c < -10:
|
51 |
+
temp_comment = "หนาวมาก ๆ เลยนะ!"
|
52 |
+
else:
|
53 |
+
temp_comment = "ค่อนข้างสบาย ๆ น่าอยู่!"
|
54 |
+
|
55 |
+
if gravity_g > 1.5:
|
56 |
+
gravity_comment = f"แรงโน้มถ่วงประมาณ {gravity_g}g เลยนะ อาจจะเดินยากหน่อย!"
|
57 |
+
elif gravity_g < 0.5:
|
58 |
+
gravity_comment = f"แรงโน้มถ่วงเบาแค่ {gravity_g}g ระวังลอยได้นะ!"
|
59 |
+
else:
|
60 |
+
gravity_comment = f"แรงโน้มถ่วงกำลังดี ~{gravity_g}g"
|
61 |
+
|
62 |
+
summary_th = (
|
63 |
+
f"ดาว {name_th} เป็น{planet_type_th} "
|
64 |
+
f"อุณหภูมิราว ๆ {temp_c}°C {temp_comment}\n"
|
65 |
+
f"{gravity_comment}\n"
|
66 |
+
f"บรรยากาศ: {atmosphere_th}\n"
|
67 |
+
f"มีสิ่งมีชีวิต: {life_th}\n"
|
68 |
+
f"น่าสนุกจังเลย!"
|
69 |
+
)
|
70 |
+
return summary_th
|
71 |
+
|
72 |
+
|
73 |
+
#########################
|
74 |
+
# ฟังก์ชันสร้าง Prompt
|
75 |
+
#########################
|
76 |
+
def generate_planet_info(
|
77 |
+
planet_name_th,
|
78 |
+
planet_type_th,
|
79 |
+
distance_str,
|
80 |
+
diameter_str,
|
81 |
+
atmosphere_th,
|
82 |
+
life_th
|
83 |
+
):
|
84 |
+
# 1) แปลง string เป็น float
|
85 |
+
try:
|
86 |
+
distance_au = float(distance_str)
|
87 |
+
except:
|
88 |
+
distance_au = 1.0
|
89 |
+
|
90 |
+
try:
|
91 |
+
diameter_factor = float(diameter_str)
|
92 |
+
except:
|
93 |
+
diameter_factor = 1.0
|
94 |
+
|
95 |
+
# 2) คำนวณ
|
96 |
+
temp_c = approximate_temperature(planet_type_th, distance_au)
|
97 |
+
gravity_g = approximate_gravity(diameter_factor)
|
98 |
+
|
99 |
+
# 3) สรุปเด็กอ่านง่าย (child_friendly_summary)
|
100 |
+
child_summary = child_friendly_summary(
|
101 |
+
planet_name_th, planet_type_th, temp_c, gravity_g, atmosphere_th, life_th
|
102 |
+
)
|
103 |
+
|
104 |
+
# 4) รายละเอียดเชิงเทคนิค (ภาษาไทย)
|
105 |
+
detail_th = (
|
106 |
+
f"ชื่อดาวเคราะห์: {planet_name_th}\n"
|
107 |
+
f"ชนิดดาว: {planet_type_th}\n"
|
108 |
+
f"ระยะห่างจากดาวฤกษ์: ~{distance_au} AU\n"
|
109 |
+
f"ขนาด: ~{diameter_factor} เท่าโลก\n"
|
110 |
+
f"อุณหภูมิพื้นผิวโดยประมาณ: ~{temp_c} °C\n"
|
111 |
+
f"แรงโน้มถ่วง: ~{gravity_g} g\n"
|
112 |
+
f"บรรยากาศ: {atmosphere_th}\n"
|
113 |
+
f"สิ่งมีชีวิต: {life_th}\n"
|
114 |
+
)
|
115 |
+
|
116 |
+
# 5) Prompt ภาษาอังกฤษ (สำหรับ Midjourney)
|
117 |
+
# แปลง planet_type_th เป็นคำอังกฤษสั้น ๆ
|
118 |
+
type_map = {
|
119 |
+
"ดาวหิน (Rocky Planet)": "a rocky planet",
|
120 |
+
"ดาวก๊าซ (Gas Giant)": "a gas giant",
|
121 |
+
"ดาวน้ำแข็ง (Icy Planet)": "an icy planet",
|
122 |
+
}
|
123 |
+
type_en = type_map.get(planet_type_th, "a mysterious planet")
|
124 |
+
prompt_en = (
|
125 |
+
f"Planet Name: '{planet_name_th}' | "
|
126 |
+
f"{type_en}, orbiting at {distance_au} AU, "
|
127 |
+
f"size about {diameter_factor}x Earth diameter, "
|
128 |
+
f"with atmosphere '{atmosphere_th}', "
|
129 |
+
f"hosting '{life_th}'. "
|
130 |
+
f"Surface temperature ~{temp_c} C, "
|
131 |
+
f"gravity ~{gravity_g} g. "
|
132 |
+
f"Highly detailed, awe-inspiring, cinematic."
|
133 |
+
)
|
134 |
+
|
135 |
+
return child_summary, detail_th, prompt_en
|
136 |
+
|
137 |
+
|
138 |
+
#########################
|
139 |
+
# สร้าง UI (Gradio)
|
140 |
+
#########################
|
141 |
+
|
142 |
+
css_code = """
|
143 |
+
body {
|
144 |
+
background-color: #F9FBFF;
|
145 |
+
font-family: "Kanit", sans-serif;
|
146 |
+
}
|
147 |
+
#title {
|
148 |
+
color: #4A90E2;
|
149 |
+
text-align: center;
|
150 |
+
font-size: 2rem;
|
151 |
+
margin-top: 20px;
|
152 |
+
margin-bottom: 10px;
|
153 |
+
font-weight: bold;
|
154 |
+
}
|
155 |
+
.game-desc {
|
156 |
+
margin: 0 auto;
|
157 |
+
width: 90%;
|
158 |
+
background-color: #ECF6FF;
|
159 |
+
border: 2px dashed #B3DAFF;
|
160 |
+
border-radius: 10px;
|
161 |
+
padding: 15px;
|
162 |
+
color: #333;
|
163 |
+
margin-bottom: 20px;
|
164 |
+
}
|
165 |
+
.btn-main {
|
166 |
+
background-color: #FFE066;
|
167 |
+
border: 2px solid #FFCA28;
|
168 |
+
font-weight: bold;
|
169 |
+
font-size: 1.1rem;
|
170 |
+
padding: 10px 30px;
|
171 |
+
border-radius: 10px;
|
172 |
+
margin-right: 10px;
|
173 |
+
}
|
174 |
+
#child-summary, #detail-th, #prompt-en {
|
175 |
+
background-color: #FFFDF5;
|
176 |
+
border: 2px solid #FFE082;
|
177 |
+
border-radius: 10px;
|
178 |
+
padding: 10px;
|
179 |
+
margin-bottom: 20px;
|
180 |
+
}
|
181 |
+
"""
|
182 |
+
|
183 |
+
def welcome_text():
|
184 |
+
return "ยินดีต้อนรับสู่ Planetary Adventure! ลองกรอกข้อมูลแล้วกด 'สร้างโลกแฟนตาซี' ดูสิ!"
|
185 |
+
|
186 |
+
# ปุ่ม Copy Prompt (HTML + JS)
|
187 |
+
copy_button_html = """
|
188 |
+
<button style="background-color: #F06292; border: 2px solid #E91E63; font-weight: bold;
|
189 |
+
font-size: 1.0rem; padding: 8px 20px; border-radius: 10px;"
|
190 |
+
onclick="copyPromptText()">
|
191 |
+
คัดลอก Prompt
|
192 |
+
</button>
|
193 |
+
<script>
|
194 |
+
function copyPromptText() {
|
195 |
+
const promptBox = document.querySelector('#prompt-en textarea');
|
196 |
+
if (!promptBox) {
|
197 |
+
alert('ไม่พบข้อความ Prompt!');
|
198 |
+
return;
|
199 |
+
}
|
200 |
+
const promptText = promptBox.value;
|
201 |
+
navigator.clipboard.writeText(promptText);
|
202 |
+
alert('คัดลอก Prompt แล้ว! นำไปใช้ใน Midjourney ได้เลย~');
|
203 |
+
}
|
204 |
+
</script>
|
205 |
+
"""
|
206 |
+
|
207 |
+
with gr.Blocks(css=css_code) as demo:
|
208 |
+
gr.Markdown("<h1 id='title'>Planetary Adventure (Thai) + สรุปข้อมูลดวงดาว</h1>")
|
209 |
+
gr.Markdown("""
|
210 |
+
<div class="game-desc">
|
211 |
+
<p>สร้างดาวเคราะห์ในจินตนาการ พร้อมข้อความสรุปสนุก ๆ สำหรับเด็ก และ Prompt ภาษาอังกฤษเพื่อนำไปเจนภาพ!</p>
|
212 |
+
<ol>
|
213 |
+
<li>กรอกข้อมูลด้านล่างเป็นภาษาไทย เช่น ชื่อดาว, ชนิดดาว, ฯลฯ</li>
|
214 |
+
<li>กดปุ่ม <strong>"สร้างโลกแฟนตาซี"</strong></li>
|
215 |
+
<li>ดู <em>ข้อความสรุป (สำหรับเด็ก)</em>, <em>รายละเอียด (เทคนิค)</em> และ <em>Prompt อังกฤษ</em></li>
|
216 |
+
<li>กด "<strong>คัดลอก Prompt</strong>" เพื่อเอาไปใช้ใน AI สร้างภาพ เช่น Midjourney</li>
|
217 |
+
</ol>
|
218 |
+
</div>
|
219 |
+
""")
|
220 |
+
|
221 |
+
planet_name = gr.Textbox(label="ชื่อดาวเคราะห์ (ภาษาไทย)", placeholder="ตัวอย่าง: ดาวซานาดา")
|
222 |
+
planet_type = gr.Dropdown(
|
223 |
+
label="ชนิดดาว",
|
224 |
+
choices=["ดาวหิน (Rocky Planet)", "ดาวก๊าซ (Gas Giant)", "ดาวน้ำแข็ง (Icy Planet)"],
|
225 |
+
value="ดาวหิน (Rocky Planet)"
|
226 |
+
)
|
227 |
+
distance_au = gr.Textbox(label="ระยะห่างจากดาวฤกษ์ (หน่วย AU)", placeholder="เช่น 0.8 หรือ 1 หรือ 2")
|
228 |
+
diameter_factor = gr.Textbox(label="ขนาดเส้นผ่านศูนย์กลาง (เท่าโลก)", placeholder="เช่น 1, 2, 0.5")
|
229 |
+
atmosphere_th = gr.Textbox(label="ลักษณะบรรยากาศ", placeholder="ตัวอย่าง: ออกซิเจนบาง ๆ, มีคาร์บอนไดออกไซด์สูง")
|
230 |
+
life_th = gr.Textbox(label="สิ่งมีชีวิตบนดาว", placeholder="ตัวอย่าง: สัตว์เลื้อยคลานขนาดยักษ์")
|
231 |
+
|
232 |
+
create_btn = gr.Button("สร้างโลกแฟนตาซี", elem_classes="btn-main")
|
233 |
+
|
234 |
+
child_summary_output = gr.Textbox(
|
235 |
+
label="ข้อความสรุป (อ่านง่ายสำหรับเด็ก)",
|
236 |
+
interactive=False,
|
237 |
+
elem_id="child-summary"
|
238 |
+
)
|
239 |
+
detail_th_output = gr.Textbox(
|
240 |
+
label="รายละเอียด (เทคนิค)",
|
241 |
+
interactive=False,
|
242 |
+
elem_id="detail-th"
|
243 |
+
)
|
244 |
+
prompt_en_output = gr.Textbox(
|
245 |
+
label="Prompt ภาษาอังกฤษ",
|
246 |
+
interactive=False,
|
247 |
+
elem_id="prompt-en"
|
248 |
+
)
|
249 |
+
|
250 |
+
gr.HTML(copy_button_html)
|
251 |
+
|
252 |
+
# เมื่อกดปุ่ม
|
253 |
+
create_btn.click(
|
254 |
+
fn=generate_planet_info,
|
255 |
+
inputs=[planet_name, planet_type, distance_au, diameter_factor, atmosphere_th, life_th],
|
256 |
+
outputs=[child_summary_output, detail_th_output, prompt_en_output]
|
257 |
+
)
|
258 |
+
|
259 |
+
demo.load(fn=welcome_text, inputs=None, outputs=child_summary_output)
|
260 |
+
|
261 |
+
demo.launch()
|