File size: 4,265 Bytes
a1c0952
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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;