From 5e0dbb7535c03f9999da54083e9187a223690d61 Mon Sep 17 00:00:00 2001 From: Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> Date: Sun, 8 Nov 2026 23:56:57 +0900 Subject: parks: 周辺公園を一覧表に表示し、保存時の同名統合を修正 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parks-rows.ts: 周辺の公園も市内公園と同じ設備項目を一覧表に出す park-editor.mjs: 重複判定をOSM ID(なければ名前+住所)に変え、 同名の別公園が保存で消えないようにする kodaira-nearby-parks.json: 水飲み場「?」と復元した萩山公園を反映 --- scripts/park-editor.mjs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/park-editor.mjs b/scripts/park-editor.mjs index b3a3e80..f6c20a4 100644 --- a/scripts/park-editor.mjs +++ b/scripts/park-editor.mjs @@ -95,10 +95,25 @@ function recordKey(obj) { return null; } +// 重複判定用のキー。名前だけで判定すると、同名の別公園(例: 萩山公園が2か所) +// まで1件にまとめてしまうため、OSMのIDや住所も含める。 +function dedupeKey(obj) { + const src = obj && obj.properties ? obj.properties : obj; + if (!src) return null; + if (src.osm_type && src.osm_id != null && String(src.osm_id) !== "") { + return `${src.osm_type}/${src.osm_id}`; + } + const name = recordKey(obj); + if (!name) return null; + const address = src["住所"] || src.address || ""; + return `${name}|${address}`; +} + function canonicalKeysFrom(lists) { const keys = new Set(); for (const list of lists) { - for (const rec of list || []) { + if (!Array.isArray(list)) continue; + for (const rec of list) { const src = rec && rec.properties ? rec.properties : rec; if (!src) continue; for (const key of Object.keys(src)) { @@ -178,7 +193,7 @@ function mergeMissing(postedList, currentList, canonicalKeys) { const deduped = []; const byKey = new Map(); for (const rec of postedList) { - const key = recordKey(rec); + const key = dedupeKey(rec); if (!key) { deduped.push(rec); continue; @@ -196,12 +211,12 @@ function mergeMissing(postedList, currentList, canonicalKeys) { const map = new Map(); for (const rec of currentList) { - const key = recordKey(rec); + const key = dedupeKey(rec); if (key) map.set(key, rec); } const postedKeys = new Set(); for (const rec of postedList) { - const key = recordKey(rec); + const key = dedupeKey(rec); if (!key) continue; postedKeys.add(key); const current = map.get(key); @@ -306,12 +321,11 @@ const server = createServer(async (req, res) => { // 古い画面からの保存で、新しい項目・レコードが消えないようにマージする const current = JSON.parse(await readFile(target.dataset.path, "utf-8")); - const canonicalKeys = canonicalKeysFrom([current, data.features || data]); - if (target.id === "nearbyParks") { - mergeMissing(data.features, current.features || [], canonicalKeys); - } else { - mergeMissing(data, current, canonicalKeys); - } + // 周辺の公園は FeatureCollection({ type, features })なので、配列に直す + const currentList = Array.isArray(current) ? current : current.features || []; + const incomingList = target.id === "nearbyParks" ? data.features : data; + const canonicalKeys = canonicalKeysFrom([currentList, incomingList]); + mergeMissing(incomingList, currentList, canonicalKeys); const text = target.dataset.pretty ? `${JSON.stringify(data, null, 2)}\n` -- cgit v1.3.1