diff --git a/map4.js b/map4.js index d637f74..3c0f0a6 100644 --- a/map4.js +++ b/map4.js @@ -66,15 +66,13 @@ // =================================== let elevatorInfo = new Map(); -// elevators.csv は map4.js と同じフォルダ fetch("./elevators.csv") .then((res) => res.text()) .then((text) => { - const lines = text.split("\n").slice(1); // 1行目ヘッダ除外 + const lines = text.split("\n").slice(1); lines.forEach((line) => { if (!line.trim()) return; - const [station, hasEV] = line.split(","); elevatorInfo.set(station.trim(), hasEV.trim() === "1"); }); @@ -82,7 +80,7 @@ console.log("EVデータ読み込み成功:", elevatorInfo); }); -// エレベーターアイコン +// エレベーターアイコン(※後で絶対パスに直す) const elevatorIcon = L.icon({ iconUrl: "./elevator.png", iconSize: [22, 22], @@ -178,7 +176,6 @@ status: myStatus, }); } - // =================================== // 待ち合わせピンアイコン // =================================== @@ -201,7 +198,7 @@ maxZoom: 19, }).addTo(map); - // ホストだけが待ち合わせピンを設置できる + // ホストだけが待ち合わせピンを置ける map.on("click", async (e) => { if (!isHost) return; @@ -268,7 +265,7 @@ const toRad = (deg) => (deg * Math.PI) / 180; const dLat = toRad(lat2 - lat1); - const dLng = toRad(lng2 - lng1); + const dLng = toRad(lat2 - lng1); const a = Math.sin(dLat / 2) ** 2 + @@ -291,9 +288,8 @@ document.getElementById("targetInfo").innerHTML = `待ち合わせ場所まで 約 ${km} km`; } - // =================================== -// メンバー一覧 +// メンバー状態カラー // =================================== function getStatusColor(s) { return { @@ -304,6 +300,9 @@ }[s] || "#ccc"; } +// =================================== +// メンバー一覧 +// =================================== function showMemberList(latestByDevice) { const list = document.getElementById("memberList"); list.innerHTML = ""; @@ -342,7 +341,7 @@ `; - // メンバータップでその場所へ移動 + // メンバーをタップでその位置へ移動 li.addEventListener("click", () => { const r = latestByDevice[member.device_id]; if (!r) return; @@ -352,6 +351,7 @@ list.appendChild(li); }); } + // =================================== // 他ユーザーのピン表示 // =================================== @@ -373,26 +373,25 @@ if (!latestByDevice[r.device_id]) latestByDevice[r.device_id] = r; }); - // ホスト自動交代(位置情報が揃ったあと) + // ホスト自動交代 await checkHostAuto(); // メンバー一覧更新 showMemberList(latestByDevice); - // 既存の他ユーザーピン削除 + // ピン消去 otherMarkers.forEach((m) => map.removeLayer(m)); otherMarkers = []; - // 他ユーザーのピンを再描画 + // ピン描画 Object.values(latestByDevice).forEach((r) => { - if (r.device_id === deviceId) return; // 自分は除外 + if (r.device_id === deviceId) return; const mk = createLabeledMarker(r.lat, r.lng, r.user_name, false); mk.addTo(map); otherMarkers.push(mk); }); - // 全員到着判定 checkAllArrived(); } @@ -407,7 +406,7 @@ const ok = users.every((u) => { const d = distanceMeters(u.lat, u.lng, targetLat, targetLng); - return d < 120; // 120m以内を到着とみなす + return d < 120; // 120m以内 }); if (!ok) return; @@ -429,7 +428,7 @@ } // =================================== -// 時刻フォーマット(チャット用) +// 時刻フォーマット // =================================== function formatTime(t) { const d = new Date(t); @@ -492,7 +491,6 @@ input.value = ""; loadMessages(); } - // =================================== // ホスト自動交代 // =================================== @@ -507,7 +505,7 @@ currentHostName = group.host_name; - // 6秒以内に更新があればオンライン + // 6秒以内 → オンライン const onlineUsers = Object.values(latestByDevice).filter( (u) => (Date.now() - new Date(u.updated_at)) / 1000 < 6 ); @@ -516,7 +514,7 @@ (u) => u.user_name === currentHostName ); - // ホストがオフライン → 最新更新者を新ホストに + // ホスト不在 → 最新更新者にホスト交代 if (!hostOnline && onlineUsers.length > 0) { const newHost = onlineUsers.sort( (a, b) => new Date(b.updated_at) - new Date(a.updated_at) @@ -533,6 +531,7 @@ isHost = currentUser === currentHostName; } + // UI更新 const hostLabel = document.getElementById("hostStatus"); if (hostLabel) { hostLabel.textContent = isHost ? "あなたはホストです" : "一般メンバーです"; @@ -581,6 +580,7 @@ location.href = `archive.html?group=${encodeURIComponent(currentGroup)}`; } } + // =================================== // 駅検索(Overpass API) // =================================== @@ -637,7 +637,7 @@ mk.bindPopup(name + "駅"); stationMarkers.push(mk); - // 🔵 EVピン(CSV と名前一致する駅のみ) + // 🔵 EVピン(CSV と名前一致) if (elevatorInfo.get(name)) { const ev = L.marker([st.lat, st.lon], { icon: elevatorIcon }) .addTo(map) @@ -646,11 +646,9 @@ } }); - // 最寄駅表示 box.textContent = `最寄り駅:${nearest.name}(約 ${(nearestDist / 1000).toFixed(2)} km)`; } - // =================================== // メイン処理 // =================================== @@ -658,16 +656,16 @@ loadParams(); setupStatusButtons(); - // デフォルト位置は皇居 + // デフォルト位置:皇居 let lat = 35.681236, lng = 139.767125; - // 現在位置 + // 現在位置を取得 try { const pos = await getPosition(); lat = pos.latitude; lng = pos.longitude; } catch { - // 位置取得失敗 → 皇居のまま + // 取得失敗 → 皇居のまま } lastLat = lat; @@ -676,7 +674,7 @@ // 地図初期化 initMap(lat, lng); - // 自分のピン・位置保存 + // 自分のピン描画 & 保存 renderSelfMarker(); await saveMyLocation(lat, lng); @@ -689,12 +687,14 @@ // チャット読み込み loadMessages(); - // 駅表示 + // 駅表示(EV 対応) loadStations(); - // =========================== - // 定期更新タイマー - // =========================== + // ------------------------------ + // ▼ 定期更新(高速リアルタイム)▼ + // ------------------------------ + + // GPS更新 setInterval(async () => { try { const pos = await getPosition(); @@ -707,14 +707,27 @@ } catch {} }, 2500); + // 他ユーザー位置 setInterval(showOtherUsers, 1500); + + // 待ち合わせ再取得 setInterval(loadSharedTarget, 9000); + + // チャット更新 setInterval(loadMessages, 2500); + + // ホスト自動交代 setInterval(checkHostAuto, 4000); + + // グループ解散チェック setInterval(checkGroupActive, 4000); + + // 駅の再検索 setInterval(loadStations, 15000); - // ボタン + // ------------------------------ + // ▼ ボタン ▼ + // ------------------------------ const exitBtn = document.getElementById("exitBtn"); if (exitBtn) exitBtn.onclick = () => (location.href = "index.html"); @@ -730,19 +743,19 @@ }); } - // マップサイズ調整 + // マップサイズ調整(スマホ対策) setTimeout(() => map.invalidateSize(), 500); } // =================================== -// DOMContentLoaded +// DOMContentLoaded(起動) // =================================== window.addEventListener("DOMContentLoaded", async () => { const p = new URLSearchParams(location.search); const g = p.get("group"); const u = p.get("user"); - // グループ確認 + // グループ存在チェック const { data, error } = await supa .from("groups") .select("*") @@ -767,12 +780,13 @@ return; } - // 反映 + // 設定反映 currentGroup = g; currentUser = u; currentHostName = data.host_name; isHost = currentUser === currentHostName; + // ホスト表示更新 const hostLabel = document.getElementById("hostStatus"); if (hostLabel) { hostLabel.textContent = isHost ? "あなたはホストです" : "一般メンバーです"; @@ -781,6 +795,6 @@ const disbandBtn = document.getElementById("disbandBtn"); if (disbandBtn) disbandBtn.style.display = isHost ? "inline-block" : "none"; - // アプリ起動 + // アプリ開始 main(); });