ee4c177233
Field sweep additions, all absent from OpenStreetMap and found by the author on Google Maps: 40.16 滝下八幡神社 栗山町字滝下 43.07 滝下発電所 栗山町字滝下 (北海道企業局) 57.44 登川神社 夕張市楓 66.78 豊進神社 むかわ町穂別稲里 71.86 穂別ダム神社 むかわ町穂別稲里 79.67 福山神社 むかわ町穂別福山 93.58 名石駐車場 占冠村字中央 102.36 日高神社 日高町宮下町 104.52 日高発電所 日高町字千栄 (北海道電力) 106.22 右左府発電所 日高町字日高 Plus 滝ノ上信号場 and 楓信号場, which OSM tags railway=signal / railway=junction with no place tag, so both fell through every filter. Corrections: モトツ橋 moved 86.16 → 87.12. It does not cross パンケモトツ沢川; it is the sheltered span between モトツトンネル and 福山トンネル, roofed by モトツシェルター — the identical 62 m lengths are the same deck. Author also fixed 下福山橋 → 77.05 and オロロップ橋 → 77.55, matching route01's order. Readings: kana is the source of truth. Romaji regenerated from it in wāpuro style, no macrons. Adds 274-romaji.py, which does that deterministically and is idempotent against the current table. Artifact now shows Romaji in the table and kana under each strip mark. CSV and GeoJSON re-propagated. 168 entries, 118 with readings. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S6MpcBisZYhX45oDGRRJoz
131 lines
5.7 KiB
Python
Executable File
131 lines
5.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Fill the Romaji column of 274-dev.md from its Kana column.
|
|
|
|
Kana is the source of truth. Romaji is generated wāpuro-style — no macrons,
|
|
since they are awkward to type: おう→ou, ゅう→yuu, っ doubles the following
|
|
consonant, ー repeats the preceding vowel, ん→n' before a vowel or y.
|
|
|
|
The trailing generic is split off and lowercased (Kawabata hashi, Houshin jinja,
|
|
Takinoue kosenkyou); 丁目 take a hyphen (Shinmachi 3-choume). Compound proper
|
|
stems stay as one token, because kana carries no word boundary — add them to
|
|
MANUAL below if you want a break.
|
|
|
|
python3 274-romaji.py # rewrite the Romaji column
|
|
python3 274-romaji.py --check # report differences, change nothing
|
|
|
|
Rows with no kana are left with an empty Romaji cell rather than a guess.
|
|
"""
|
|
import io, os, re, sys
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
DOC = os.path.join(HERE, '274-dev.md')
|
|
|
|
# stems that must not have a trailing 川 split off — it is part of the name
|
|
NOSPLIT = {'のぼりかわ', 'にいかわ', 'しんかわ', 'みかわ', 'たきさわがわ'}
|
|
# hand-set forms that the mechanical rules cannot derive
|
|
MANUAL = {}
|
|
|
|
|
|
import re
|
|
Y={'きゃ':'kya','きゅ':'kyu','きょ':'kyo','しゃ':'sha','しゅ':'shu','しょ':'sho',
|
|
'ちゃ':'cha','ちゅ':'chu','ちょ':'cho','にゃ':'nya','にゅ':'nyu','にょ':'nyo',
|
|
'ひゃ':'hya','ひゅ':'hyu','ひょ':'hyo','みゃ':'mya','みゅ':'myu','みょ':'myo',
|
|
'りゃ':'rya','りゅ':'ryu','りょ':'ryo','ぎゃ':'gya','ぎゅ':'gyu','ぎょ':'gyo',
|
|
'じゃ':'ja','じゅ':'ju','じょ':'jo','びゃ':'bya','びゅ':'byu','びょ':'byo',
|
|
'ぴゃ':'pya','ぴゅ':'pyu','ぴょ':'pyo','ぢゃ':'ja','ぢゅ':'ju','ぢょ':'jo',
|
|
'しぇ':'she','ちぇ':'che','じぇ':'je','てぃ':'ti','でぃ':'di','ふぁ':'fa',
|
|
'ふぃ':'fi','ふぇ':'fe','ふぉ':'fo','うぃ':'wi','うぇ':'we','うぉ':'wo','とぅ':'tu'}
|
|
S={'あ':'a','い':'i','う':'u','え':'e','お':'o','か':'ka','き':'ki','く':'ku','け':'ke','こ':'ko',
|
|
'さ':'sa','し':'shi','す':'su','せ':'se','そ':'so','た':'ta','ち':'chi','つ':'tsu','て':'te','と':'to',
|
|
'な':'na','に':'ni','ぬ':'nu','ね':'ne','の':'no','は':'ha','ひ':'hi','ふ':'fu','へ':'he','ほ':'ho',
|
|
'ま':'ma','み':'mi','む':'mu','め':'me','も':'mo','や':'ya','ゆ':'yu','よ':'yo',
|
|
'ら':'ra','り':'ri','る':'ru','れ':'re','ろ':'ro','わ':'wa','を':'o','ん':'n',
|
|
'が':'ga','ぎ':'gi','ぐ':'gu','げ':'ge','ご':'go','ざ':'za','じ':'ji','ず':'zu','ぜ':'ze','ぞ':'zo',
|
|
'だ':'da','ぢ':'ji','づ':'zu','で':'de','ど':'do','ば':'ba','び':'bi','ぶ':'bu','べ':'be','ぼ':'bo',
|
|
'ぱ':'pa','ぴ':'pi','ぷ':'pu','ぺ':'pe','ぽ':'po',
|
|
'ぁ':'a','ぃ':'i','ぅ':'u','ぇ':'e','ぉ':'o','ゃ':'ya','ゅ':'yu','ょ':'yo'}
|
|
VOW='aiueo'
|
|
|
|
def kana2romaji(s):
|
|
out=[];i=0
|
|
while i<len(s):
|
|
c=s[i]
|
|
if c.isdigit(): out.append(c); i+=1; continue
|
|
if c=='ー':
|
|
if out and out[-1] and out[-1][-1] in VOW: out.append(out[-1][-1])
|
|
i+=1; continue
|
|
if c=='っ':
|
|
j=i+1
|
|
if j<len(s):
|
|
nxt=Y.get(s[j:j+2]) or S.get(s[j],'')
|
|
if nxt and nxt[0] not in VOW: out.append(nxt[0])
|
|
i+=1; continue
|
|
two=s[i:i+2]
|
|
if two in Y: out.append(Y[two]); i+=2; continue
|
|
if c in S:
|
|
r=S[c]
|
|
if c=='ん':
|
|
nx=s[i+1:i+2]
|
|
nr=Y.get(s[i+1:i+3]) or S.get(nx,'')
|
|
if nr and (nr[0] in VOW or nr[0]=='y'): r="n'"
|
|
out.append(r); i+=1; continue
|
|
out.append(c); i+=1
|
|
return ''.join(out)
|
|
|
|
GENERIC=['しんごうじょう','こせんきょう','りくきょう','ほどうきょう','ちゅうがっこう','しょうがっこう','ゆうびんきょく','はつでんしょ',
|
|
'へんでんしょ','ちゅうしゃじょう','しょうぼうしょ','としょかん','きねんかん','こうみんかん',
|
|
'きゃんぷじょう','しぇるたー','とんねる','じんじゃ','だいばし','おおはし','ばし','はし',
|
|
'がわ','かわ','だむ','やくば','こうこう','こうえん','かいかん','ほーる','えき','てん','ちょうめ']
|
|
|
|
|
|
def split_generic(kana):
|
|
if kana in NOSPLIT: return kana,''
|
|
for g in GENERIC:
|
|
if kana.endswith(g) and len(kana)>len(g):
|
|
return kana[:-len(g)], g
|
|
return kana, ''
|
|
|
|
import re as _re
|
|
def romanise(kana):
|
|
m=_re.match(r'^(.*?)(\d+)ちょうめ$',kana)
|
|
if m:
|
|
a=kana2romaji(m.group(1)); a=a[:1].upper()+a[1:]
|
|
return '%s %s-choume'%(a,m.group(2))
|
|
stem,gen=split_generic(kana)
|
|
a=kana2romaji(stem); b=kana2romaji(gen) if gen else ''
|
|
a=a[:1].upper()+a[1:]
|
|
return (a+' '+b).strip() if b else a
|
|
|
|
|
|
def process(text):
|
|
out, filled, changed = [], 0, 0
|
|
for line in text.split('\n'):
|
|
if line.startswith('| ') and line.count('|') >= 13:
|
|
c = [x.strip() for x in line.strip('|').split('|')]
|
|
if re.match(r'^\d+\.\d+$', c[0]):
|
|
kana = c[3]
|
|
new = MANUAL.get(kana, romanise(kana)) if kana else ''
|
|
if new != c[4]:
|
|
if not c[4]:
|
|
filled += 1
|
|
else:
|
|
changed += 1
|
|
c[4] = new
|
|
line = '| ' + ' | '.join(c) + ' |'
|
|
out.append(line)
|
|
return '\n'.join(out), filled, changed
|
|
|
|
|
|
def main():
|
|
text = io.open(DOC, encoding='utf-8').read()
|
|
new, filled, changed = process(text)
|
|
if '--check' in sys.argv:
|
|
print('%d blank cells would be filled, %d existing would change' % (filled, changed))
|
|
return
|
|
io.open(DOC, 'w', encoding='utf-8').write(new)
|
|
print('%d filled, %d normalised' % (filled, changed))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|