AR04291 / app.py
Joey889's picture
Update app.py
37fb541 verified
import gradio as gr
import math
treasures = [
{"name": "寶藏第1個", "lat": 24.985703, "lon": 121.288680},
{"name": "寶藏第2個", "lat": 24.985900, "lon": 121.289000},
{"name": "寶藏第3個", "lat": 24.956398, "lon": 121.297729},
]
def haversine(lat1, lon1, lat2, lon2):
R = 6371000
phi1, phi2 = math.radians(lat1), math.radians(lat2)
d_phi = math.radians(lat2 - lat1)
d_lambda = math.radians(lon2 - lon1)
a = math.sin(d_phi/2)**2 + math.cos(phi1)*math.cos(phi2)*math.sin(d_lambda/2)**2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
return R * c
def check_nearest(lat, lon, found):
if not lat or not lon:
return "❌ 請先取得 GPS", "", "", found
try:
lat = float(lat)
lon = float(lon)
except:
return "❌ 座標格式錯誤", "", "", found
nearest = None
nearest_idx = None
min_distance = float("inf")
for idx, treasure in enumerate(treasures):
dist = haversine(lat, lon, treasure["lat"], treasure["lon"])
if dist < min_distance:
min_distance = dist
nearest = treasure
nearest_idx = idx
dist = haversine(lat, lon, nearest["lat"], nearest["lon"])
gmap = f"https://www.google.com/maps/dir/{lat},{lon}/{nearest['lat']},{nearest['lon']}"
if dist <= 30 and nearest_idx not in found:
found.append(nearest_idx)
status = f"🎯 找到 {nearest['name']}!距離:{dist:.2f} 公尺 ✅"
html = f"""
<h3>{nearest['name']} 🎉 已找到!</h3>
<img src="https://media.giphy.com/media/5GoVLqeAOo6PK/giphy.gif" style="width:100%; max-height:200px;">
"""
elif nearest_idx in found:
status = f"✅ {nearest['name']} 已找到!目前距離:{dist:.2f} 公尺"
html = f'<a href="{gmap}" target="_blank">➡️ 再次導航至 {nearest["name"]}</a>'
else:
status = f"📍 距離 {nearest['name']}{dist:.2f} 公尺,請再靠近一些"
html = f'<a href="{gmap}" target="_blank">➡️ 點我導航至 {nearest["name"]}</a>'
if len(found) == len(treasures):
html += """
<h2 style="text-align:center;">🎉 所有寶藏已找到!</h2>
<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExZGU4YzZhOTdjYjJmODlmZDEwZmExZDcyOTU4NGY5NGY4MzU3ZDM2YSZjdD1n/26n6WywJyh39n1pBu/giphy.gif" style="width:100%; max-height:300px;">
"""
progress = f"✅ 已找到:{', '.join([treasures[i]['name'] for i in sorted(found)])}" if found else ""
return status, html, progress, found
with gr.Blocks() as demo:
gr.Markdown("# 🗺️ GPS 尋寶遊戲")
gr.Markdown("📍 自動找最近寶藏,進入 30 公尺範圍內顯示動畫 🎉")
gr.HTML("""
<button id="gpsButton" style="padding:10px;font-size:16px;">📍 點我取得 GPS</button>
<script>
document.addEventListener("DOMContentLoaded", function () {
document.getElementById("gpsButton").addEventListener("click", function () {
navigator.geolocation.getCurrentPosition(
function(pos) {
const latbox = document.querySelectorAll("textarea")[0];
const lonbox = document.querySelectorAll("textarea")[1];
latbox.value = pos.coords.latitude;
lonbox.value = pos.coords.longitude;
latbox.dispatchEvent(new Event('input'));
lonbox.dispatchEvent(new Event('input'));
},
function(err) {
alert("⚠️ GPS 錯誤:" + err.message);
}
);
});
});
</script>
""")
with gr.Row():
lat = gr.Textbox(label="Latitude")
lon = gr.Textbox(label="Longitude")
status = gr.Markdown()
link = gr.HTML()
progress = gr.Markdown()
found_state = gr.State([])
btn = gr.Button("🔍 檢查距離 + 導航")
btn.click(fn=check_nearest, inputs=[lat, lon, found_state],
outputs=[status, link, progress, found_state])
demo.launch()