File size: 5,547 Bytes
57b8366
 
 
 
 
744cd23
 
 
 
 
 
 
57b8366
 
 
744cd23
 
 
57b8366
 
 
 
057d9c6
57b8366
 
 
057d9c6
57b8366
 
 
057d9c6
57b8366
 
 
 
057d9c6
57b8366
 
 
057d9c6
57b8366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# ui/layouts.py
import gradio as gr
from config import content, data, defaults
from core import callbacks

def create_ui(visit_count_html: str):
    """

    Creates and returns the Gradio UI Blocks.

    

    Args:

        visit_count_html: The Markdown string to display the visit count.

    """
    
    # --- Main UI Layout ---
    with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"), title="地球物理學與AI應用") as demo:
        # --- Display Visit Counter at the top ---
        gr.Markdown(visit_count_html)

        # --- Introduction Section ---
        gr.Markdown(content.course_introduction_md)

        # --- Main Tabs ---
        # ✨ --- UPDATED: Added emojis to tab labels for better UI --- ✨
        with gr.Tabs():
            
            # --- Tab 1: Course Goals ---
            with gr.TabItem("🎯 課程目標"):
                gr.Markdown(content.course_goals_md)

            # --- Tab 2: Course Schedule ---
            with gr.TabItem("🗓️ 課程進度"):
                gr.Markdown("### 每週課程安排")
                gr.DataFrame(data.schedule_df, wrap=True)

            # --- Tab 3: Grading Policy ---
            with gr.TabItem("💯 成績計算"):
                gr.Markdown(content.grading_policy_md)

            # --- Tab 4: Interactive Labs ---
            with gr.TabItem("🚀 互動體驗區 (程式碼實驗室)"):
                gr.Markdown("## 🚀 互動程式碼實驗室")
                gr.Markdown("歡迎來到這裡!直接修改下方的 Python 程式碼,點擊「執行」,即可在右側看到成果。這是學習程式與地球物理最直接的方式!")
                gr.Info("注意:執行環境已受限,僅支援資料視覺化相關操作。請勿嘗試檔案讀寫或網路請求。")

                # --- Lab 1: Mapping ---
                with gr.Accordion("🌍 地圖繪製實驗室 (PyGMT/Cartopy 概念)", open=True):
                    with gr.Row():
                        with gr.Column(scale=2):
                            gr.Markdown("### 說明\n這段程式碼使用 `cartopy` 和 `matplotlib` 函式庫來繪製地理地圖。\n\n**您可以試著:**\n1. 修改 `center_lon`, `center_lat` 來改變地圖中心。\n2. 調整 `extent_lon`, `extent_lat` 來縮放地圖。\n3. 將 `coastline_color` 改成 'red' 或其他顏色。\n4. **在 `symbols` 列表中新增或修改字典,來繪製自訂的符號(例如:標示您所在的城市)。**")
                            map_code = gr.Code(label="可編輯的 Python 程式碼", value=defaults.DEFAULT_MAP_CODE, language="python", lines=25)
                            map_run_button = gr.Button("執行程式碼", variant="primary")
                        with gr.Column(scale=3):
                            map_plot_output = gr.Plot(label="地圖輸出")
                            map_console_output = gr.Textbox(label="執行結果 / 錯誤訊息", lines=8, interactive=False)
                
                # --- Lab 2: Seismology ---
                with gr.Accordion("📈 震波圖繪製實驗室 (ObsPy 概念)", open=False):
                    with gr.Row():
                        with gr.Column(scale=2):
                            gr.Markdown("### 說明\n這段程式碼使用 `numpy` 產生模擬的地震波數據,並用 `matplotlib` 將其視覺化。\n\n**您可以試著:**\n1. 修改 `p_wave_arrival` 和 `s_wave_arrival` 來改變 P/S 波的抵達時間。\n2. 調整 `main_freq` 來改變地震波的頻率(數值越大,波形越密集)。\n3. 將 `decay_rate` 調小,觀察振幅衰減變慢的效果。")
                            seismo_code = gr.Code(label="可編輯的 Python 程式碼", value=defaults.DEFAULT_SEISMO_CODE, language="python", lines=25)
                            seismo_run_button = gr.Button("執行程式碼", variant="primary")
                        with gr.Column(scale=3):
                            seismo_plot_output = gr.Plot(label="震波圖輸出")
                            seismo_console_output = gr.Textbox(label="執行結果 / 錯誤訊息", lines=8, interactive=False)

            # --- Tab 5: AI Chatbot ---
            with gr.TabItem("🤖 AI 課程助教"):
                gr.Markdown("### 🤖 AI 課程助教 (知識庫強化版)")
                gr.Markdown("我內建了豐富的課程知識庫,試著問我 **「如何安裝Python環境?」**、**「什麼是版本控制?」** 或 **「給我一些期末專題的靈感」**")
                gr.ChatInterface(
                    callbacks.ai_chatbot_with_kb,
                    chatbot=gr.Chatbot(height=450, type="messages", avatar_images=(None, "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png")),
                    title="課程AI助教",
                    description="由結構化知識庫驅動的問答機器人"
                )

        # --- Connect Buttons to Backend Functions ---
        map_run_button.click(
            fn=lambda code: callbacks.execute_user_code(code, "地圖繪製"),
            inputs=[map_code],
            outputs=[map_plot_output, map_console_output]
        )
        seismo_run_button.click(
            fn=lambda code: callbacks.execute_user_code(code, "震波圖"),
            inputs=[seismo_code],
            outputs=[seismo_plot_output, seismo_console_output]
        )
            
    return demo