Skip to content
Snippets Groups Projects
Commit dea40226 authored by Martin Mareš's avatar Martin Mareš
Browse files

Import škol pokračuje

parent 39d223a1
No related branches found
No related tags found
No related merge requests found
TODO 0 → 100644
### Dořešit v importu škol ###
WARNING: Obec Černovice je podle rejstříku v okrese CZ0632, podle RUIAN je na výběr ['CZ0641', 'CZ0321', 'CZ0422', 'CZ0633'] => dořešit ručně!
WARNING: Obec Zlín je podle rejstříku v okrese CZ0721, ale pod RUIAN v CZ0724 => preferuji RUIAN
WARNING: Obec Ostrava je podle rejstříku v okrese CZ0108, ale pod RUIAN v CZ0806 => preferuji RUIAN
WARNING: Obec Brno je podle rejstříku v okrese CZ0643, ale pod RUIAN v CZ0642 => preferuji RUIAN
WARNING: Obec Brno je podle rejstříku v okrese CZ0643, ale pod RUIAN v CZ0642 => preferuji RUIAN
WARNING: Obec Řepice je podle rejstříku v okrese CZ0313, ale pod RUIAN v CZ0316 => preferuji RUIAN
WARNING: Obec Chrudim je podle rejstříku v okrese CZ0532, ale pod RUIAN v CZ0531 => preferuji RUIAN
WARNING: Obec Chlumec je podle rejstříku v okrese CZ0426, podle RUIAN je na výběr ['CZ0427', 'CZ0312'] => dořešit ručně!
WARNING: Obec Hranice je podle rejstříku v okrese CZ0712, podle RUIAN je na výběr ['CZ0311', 'CZ0411', 'CZ0714'] => dořešit ručně!
WARNING: Obec Úvaly je podle rejstříku v okrese CZ0203, ale pod RUIAN v CZ0209 => preferuji RUIAN
WARNING: Obec Dobřichovice je podle rejstříku v okrese CZ0202, ale pod RUIAN v CZ020A => preferuji RUIAN
WARNING: Obec Pchery je podle rejstříku v okrese CZ0204, ale pod RUIAN v CZ0203 => preferuji RUIAN
WARNING: Obec Poděbrady je podle rejstříku v okrese CZ0204, ale pod RUIAN v CZ0208 => preferuji RUIAN
#!/usr/bin/env python3
# Show all regions in the DB
import mo.db as db
from collections import defaultdict
session = db.get_session()
root = None
children = defaultdict(list)
def walk(place, expected_level=0):
indent = '\t' * place.level
print(f"{indent}{place.name} [{place.type.name}] #{place.place_id} NUTS={place.nuts}")
assert place.level == expected_level
for c in sorted(children[place.place_id], key=lambda p: p.name):
walk(c, expected_level + 1)
for place in session.query(db.Place).all():
if place.parent:
children[place.parent].append(place)
else:
assert not root
root = place
walk(root)
#!/usr/bin/env python3
# Initialize schools from parsed school register
# Uses db/skoly/parsed/*.tsv
from typing import List, Dict
# Naplní databázi školami a obcemi, v nichž školy sídlí
# Používá db/skoly/parsed/*.tsv
#
# Pozor, zrada: rejstřík škol je sice rozdělený do okresů dle NUTS/LAU,
# ale školy tam řadí podle úřadu, u nějž je škole registrovaná, což vůbec
# nemusí odpovídat skutečnému sídlu školy. Proto si poněkud magicky pomáháme
# číselníkem obcí z RUIANu.
from typing import List, Dict, DefaultDict
import sys
from pathlib import Path
import mo.db as db
import re
import csv
from collections import defaultdict
session = db.get_session()
new_town_cnt = 0
......@@ -14,9 +21,11 @@ new_school_cnt = 0
def import_schools(path: Path, nuts: str):
# XXX: The school register uses several invalid NUTS codes :( Fix them!
# XXX: Rejstřík škol používá několik chybných/obsoletních NUTS kódů :(
nuts = re.sub('^CZ011', 'CZ010', nuts)
nuts = re.sub('^CZ021', 'CZ020', nuts)
nuts = re.sub('^CZ061', 'CZ063', nuts)
nuts = re.sub('^CZ062', 'CZ064', nuts)
nuts = re.sub('^CZ081', 'CZ080', nuts)
with path.open('r') as file:
......@@ -43,8 +52,8 @@ def import_schools(path: Path, nuts: str):
addr = make_address(misto, ulice, cp, co)
addr2 = make_address(misto2, ulice2, cp2, co2)
if addr != addr2:
print(f"WARNING: Address mismatch, check regions: <{addr}> != <{addr2}>", file=sys.stderr)
# if addr != addr2:
# print(f"WARNING: Škola má dvě různé adresy: <{addr}> != <{addr2}>", file=sys.stderr)
town = lookup_town(misto2, nuts)
print(town)
......@@ -82,10 +91,32 @@ def make_address(misto: str, ulice: str, cp: str, co: str) -> str:
def lookup_town(misto: str, region_nuts: str) -> db.Place:
town = session.query(db.Place).filter_by(level=3, name=misto).first()
ruian_nuts = ruian_obec_to_okres_nuts[misto]
region = None
if region_nuts in ruian_nuts:
nuts = region_nuts
elif not ruian_nuts:
if misto.startswith('Praha '):
# XXX: Pražské obvody nejsou v RUIANu
region = session.query(db.Place).filter_by(level=2, name=misto).first()
assert region
else:
nuts = region_nuts
print(f"WARNING: Obec {misto} není v RUIAN", file=sys.stderr)
elif len(ruian_nuts) == 1:
nuts = ruian_nuts[0]
print(f"WARNING: Obec {misto} je podle rejstříku v okrese {region_nuts}, ale pod RUIAN v {nuts} => preferuji RUIAN", file=sys.stderr)
else:
nuts = region_nuts
print(f"WARNING: Obec {misto} je podle rejstříku v okrese {region_nuts}, podle RUIAN je na výběr {ruian_nuts} => dořešit ručně!", file=sys.stderr)
if not region:
region = session.query(db.Place).filter_by(level=2, nuts=nuts).first()
assert region
town = session.query(db.Place).filter_by(level=3, parent=region.place_id, name=misto).first()
if town is None:
region = session.query(db.Place).filter_by(level=2, nuts=region_nuts).first()
assert region is not None, f"Failed to find region with NUTS code {region_nuts}"
town = db.Place(level=3, parent=region.place_id, name=misto, type=db.PlaceType.region)
session.add(town)
session.flush()
......@@ -94,6 +125,40 @@ def lookup_town(misto: str, region_nuts: str) -> db.Place:
return town
def load_ruian_csv(name):
with open(name) as file:
reader = csv.reader(file, delimiter=';')
rows = list(reader)
columns = {}
i = 0
for h in rows[0]:
columns[h] = i
i += 1
return columns, rows[1:]
ruian_obec_to_okres_nuts: DefaultDict[str, List[str]] = defaultdict(list)
def load_ruian():
ocols, okresy = load_ruian_csv('db/ruian/UI_OKRES.csv')
okres_by_id: Dict[int, List[str]] = {}
for o in okresy:
id = int(o[ocols['KOD']])
assert id not in okres_by_id
okres_by_id[id] = o
mcols, mesta = load_ruian_csv('db/ruian/UI_OBEC.csv')
for m in mesta:
jmeno = m[mcols['NAZEV']]
oid = int(m[mcols['OKRES_KOD']])
okres = okres_by_id[oid]
# print(f"{jmeno} -> {okres}")
ruian_obec_to_okres_nuts[jmeno].append(okres[ocols['NUTS_LAU']])
load_ruian()
for path in Path('db/skoly/parsed').glob('*.tsv'):
m = re.fullmatch(r'^[A-Z]-(CZ\w+)\.tsv', path.name)
assert m is not None
......@@ -101,4 +166,4 @@ for path in Path('db/skoly/parsed').glob('*.tsv'):
import_schools(path, nuts)
session.commit()
print(f"Imported {new_school_cnt} schools, created {new_town_cnt} new towns.")
print(f"Importováno {new_school_cnt} škol, založeno {new_town_cnt} nových obcí.")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment