import parksData from "@/data/kodaira-parks.json"; import osmData from "@/data/parks-geojson"; import nearbyData from "@/data/kodaira-nearby-parks.json"; import facilitiesData from "@/data/kodaira-facilities.json"; import nearbyFacilitiesData from "@/data/kodaira-nearby-facilities.json"; export type Park = Record; function nearbyCentroid(feature: any): [number, number] { const g = feature.geometry; if (g.type === "Point") return [g.coordinates[1], g.coordinates[0]]; const ring = g.type === "Polygon" ? g.coordinates[0] : g.coordinates[0][0]; if (!ring?.length) return [0, 0]; let lat = 0; let lon = 0; for (const [x, y] of ring) { lon += x; lat += y; } return [lat / ring.length, lon / ring.length]; } function mapsQueryForNearby(name: string, city: string): string { return name ? (city && !name.startsWith(city) ? `${city}${name}` : name) : ""; } // 「小平市小川町2-1325」→「小川町」。公共施設の住所から町名を取り出す。 function townFromAddress(address: string): string { const match = /^小平市(.+?)(?:\d|$)/.exec(address || ""); return match ? match[1].trim() : ""; } // 市境500m以内の市外公園。小平市の公園と同じ表に「市外」バッジ付きで並べる。 const nearbyRows: Park[] = ((nearbyData as any).features ?? []).map((f: any) => { const p = f.properties || {}; const [lat, lon] = nearbyCentroid(f); const area = Math.round(Number(p.area_m2) || 0); const name = String(p.name || "").trim(); const mapsQuery = name ? mapsQueryForNearby(name, String(p.city || "")) : `${lat},${lon}`; return { "公園名": name, "住所": p.city ? `${p.city}(市外)` : "市外", "町名": "市外", "面積㎡": area ? String(area) : "", "500㎡以上": "", "種別": "市外", "南西部指定管理": "", "トイレ": "", "水飲み場": "", "ベンチ・椅子": "", "テーブル": "", "シェルター等": String(p["シェルター等"] || ""), "防災用具": "", "ボール遊び": "", "遊具": "", "駐車場": "", "その他設備": "", "緯度": String(lat), "経度": String(lon), "備考": `市外・小平市境から約${Math.round(Number(p.distance_m) || 0)}m${ f.geometry?.type === "Point" ? "・範囲未取得" : "" }`, "設置者": "市外", "状態": "", "地図キー": p.key || `${p.osm_type || ""}/${p.osm_id || ""}`, "時計": String(p["時計"] || ""), "地図URL": `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(mapsQuery)}`, }; }); // 市内・市外の公共施設を公園一覧と同じ行形式にする。 function facilityRow(f: any, nearby: boolean): Park { const name = String(f.name || "").trim(); const type = String(f.type || ""); const city = String(f.city || "").trim(); const address = String(f.address || city || (nearby ? "市外" : "")).trim(); const hours = f.hours ? `開館 ${f.hours}` : ""; const closed = f.closed ? `休館 ${f.closed}` : ""; const note = [type, hours, closed, f.note].filter(Boolean).join("。"); const mapsQuery = nearby ? mapsQueryForNearby(name, city) : name.startsWith("小平市") ? name : `小平市${name}`; const toilet = f.toilet === "○" ? "○" : ""; const water = f.water === "○" ? "○" : ""; return { "公園名": name, "住所": address, "町名": nearby ? "市外" : townFromAddress(address), "面積㎡": "", "500㎡以上": "", "種別": type, "南西部指定管理": "", "トイレ": toilet, "水飲み場": "", "給水": water, "ベンチ・椅子": "", "テーブル": "", "シェルター等": String(f["シェルター等"] || ""), "防災用具": "", "ボール遊び": "", "遊具": "", "駐車場": "", "その他設備": "", "緯度": f.lat != null ? String(f.lat) : "", "経度": f.lon != null ? String(f.lon) : "", "備考": note, "設置者": nearby ? "市外" : "小平市", "状態": "", "地図URL": `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(mapsQuery)}`, "公式URL": String(f.source || ""), "施設": "1", }; } const facilityRows: Park[] = [ ...(facilitiesData as any[]).map((f) => facilityRow(f, false)), ...(nearbyFacilitiesData as any[]).map((f) => facilityRow(f, true)), ]; export const parks: Park[] = [ ...(parksData as Park[]), ...nearbyRows, ...facilityRows, ]; export const total = parks.length; export const towns = [...new Set(parks.map((p) => p["町名"]).filter(Boolean))].sort( (a, b) => a.localeCompare(b, "ja"), ); // OpenStreetMapにポリゴンがあり、地図から位置を表示できる公園名。 export const mappedNames = new Set([ ...(osmData as any).features .map((f: any) => f.properties?.our_name) .filter(Boolean), ...((nearbyData as any).features ?? []) .map((f: any) => String(f.properties?.name || "").trim()) .filter(Boolean), ]);