japanese-addresses-v2 / src /processes /01_make_prefecture_city.ts
matsuap's picture
Upload 65 files
a1c0952 verified
import fs from 'node:fs';
import path from 'node:path';
import { getAndParseCSVDataForId } from '../lib/ckan.js';
import { CityApi, PrefectureApi, SingleCity, SinglePrefecture } from '../data.js';
import { projectABRData } from '../lib/proj.js';
import { CityData, CityPosData, mergeCityData } from '../lib/ckan_data/city.js';
import { mergePrefectureData, PrefData, PrefPosData } from '../lib/ckan_data/prefecture.js';
function outputCityData(outDir: string, prefName: string, apiData: CityApi, prefectureApi: PrefectureApi) {
// 政令都市の「区名」が無い場合は出力から除外する
const filteredApiData = apiData.data.filter((city) => {
return (
// 区名がある場合はそのまま出力
city.ward !== undefined ||
// 区名が無い場合は、同じ市区町村名で区名があるデータが無いか確認(ある=政令都市のため、出力しない。ない=政令都市ではない)
apiData.data.filter((c2) => c2.city === city.city).every((c2) => c2.ward === undefined)
);
});
apiData.data = filteredApiData;
prefectureApi.data.find((pref) => pref.pref === prefName)!.cities = filteredApiData;
const outFile = path.join(outDir, 'ja', `${prefName}.json`);
fs.mkdirSync(path.dirname(outFile), { recursive: true });
fs.writeFileSync(outFile, JSON.stringify(apiData));
console.log(`${prefName.padEnd(4, ' ')}: ${filteredApiData.length.toString(10).padEnd(3, ' ')} 件の市区町村を出力した`);
}
async function main(argv: string[]) {
const updated = Math.floor(Date.now() / 1000);
const outDir = argv[2] || path.join(import.meta.dirname, '..', '..', 'out', 'api');
fs.mkdirSync(outDir, { recursive: true });
const [
prefMain,
prefPos,
main,
pos,
] = await Promise.all([
getAndParseCSVDataForId<PrefData>('ba-o1-000000_g2-000001'), // 都道府県
getAndParseCSVDataForId<PrefPosData>('ba-o1-000000_g2-000012'), // 位置参照拡張
getAndParseCSVDataForId<CityData>('ba-o1-000000_g2-000002'), // 市区町村
getAndParseCSVDataForId<CityPosData>('ba-o1-000000_g2-000013'), // 位置参照拡張
]);
const rawData = mergeCityData(main, pos);
const prefApiData: SinglePrefecture[] = [];
const rawPrefData = mergePrefectureData(prefMain, prefPos);
for (const raw of rawPrefData) {
prefApiData.push({
code: parseInt(raw.lg_code),
pref: raw.pref,
pref_k: raw.pref_kana,
pref_r: raw.pref_roma,
point: projectABRData(raw),
cities: [],
});
}
const prefApi: PrefectureApi = {
meta: {
updated,
},
data: prefApiData,
};
let lastPref: string | undefined = undefined;
let allCount = 0;
const processedLgCodes: Set<string> = new Set();
let apiData: SingleCity[] = [];
for (const raw of rawData) {
allCount++;
if (lastPref !== raw.pref && lastPref !== undefined) {
const api: CityApi = {
meta: {
updated,
},
data: apiData,
};
outputCityData(outDir, lastPref, api, prefApi);
apiData = [];
}
if (lastPref !== raw.pref) {
lastPref = raw.pref;
}
apiData.push({
code: parseInt(raw.lg_code),
county: raw.county === '' ? undefined : raw.county,
county_k: raw.county_kana === '' ? undefined : raw.county_kana,
county_r: raw.county_roma === '' ? undefined : raw.county_roma,
city: raw.city,
city_k: raw.city_kana,
city_r: raw.city_roma,
ward: raw.ward === '' ? undefined : raw.ward,
ward_k: raw.ward_kana === '' ? undefined : raw.ward_kana,
ward_r: raw.ward_roma === '' ? undefined : raw.ward_roma,
point: projectABRData(raw),
});
processedLgCodes.add(raw.lg_code);
}
if (lastPref) {
const api: CityApi = {
meta: {
updated,
},
data: apiData,
};
outputCityData(outDir, lastPref, api, prefApi);
}
const outFile = path.join(outDir, 'ja.json');
fs.writeFileSync(outFile, JSON.stringify(prefApi));
console.log(`全国: ${allCount} ${processedLgCodes.size} 件の市区町村を出力した`);
}
export default main;