aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/data/parks-rows.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/data/parks-rows.ts')
-rw-r--r--src/data/parks-rows.ts141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/data/parks-rows.ts b/src/data/parks-rows.ts
new file mode 100644
index 0000000..39d7ae0
--- /dev/null
+++ b/src/data/parks-rows.ts
@@ -0,0 +1,141 @@
+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<string, string>;
+
+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.includes(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(lat),
+ "経度": String(lon),
+ "備考": `市外・小平市境から約${Math.round(Number(p.distance_m) || 0)}m${
+ f.geometry?.type === "Point" ? "・範囲未取得" : ""
+ }`,
+ "設置者": "市外",
+ "状態": "",
+ "地図キー": p.key || `${p.osm_type || ""}/${p.osm_id || ""}`,
+ "地図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}`;
+ const toilet = f.toilet === "○" ? "○" : "";
+ const water = f.water === "○" ? "○" : "";
+ return {
+ "公園名": name,
+ "住所": address,
+ "町名": nearby ? "市外" : townFromAddress(address),
+ "面積㎡": "",
+ "500㎡以上": "",
+ "種別": type,
+ "南西部指定管理": "",
+ "トイレ": toilet,
+ "水飲み場": "",
+ "給水": water,
+ "ベンチ・椅子": "",
+ "テーブル": "",
+ "パーゴラ": "",
+ "東屋": "",
+ "防災用具": "",
+ "ボール遊び": "",
+ "遊具": "",
+ "駐車場": "",
+ "その他設備": "",
+ "緯度": 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<string>([
+ ...(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),
+]);