From 33d1b36ca6ff5337b05f9b96cdad9e54684fb40f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Va=CC=81clav=20Volhejn?= <vaclav.volhejn@gmail.com>
Date: Tue, 5 Jan 2021 21:14:12 +0100
Subject: [PATCH] =?UTF-8?q?Opravit=20nalezen=C3=A9=20chyby/okrajov=C3=A9?=
 =?UTF-8?q?=20p=C5=99=C3=ADpady?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 bin/shorten-schools | 209 ++++++++++++++++++++++++++------------------
 1 file changed, 126 insertions(+), 83 deletions(-)

diff --git a/bin/shorten-schools b/bin/shorten-schools
index 6f19ce36..07db80dd 100755
--- a/bin/shorten-schools
+++ b/bin/shorten-schools
@@ -23,41 +23,12 @@ import copy
 import random
 import re
 import sys
+import argparse
 
 from sqlalchemy.orm import aliased
 
 import mo.db as db
 
-session = db.get_session()
-
-school_place_t = aliased(db.Place)
-parent_place_t = aliased(db.Place)
-
-schools_q = (
-    session.query(db.School, school_place_t, parent_place_t)
-    .filter(db.School.place_id == school_place_t.place_id)
-    .filter(parent_place_t.place_id == school_place_t.parent)
-    .all()
-)
-
-schools = []
-
-for school, place, parent_place in schools_q:
-
-    # Parent má být škola
-    assert parent_place.level == 3
-
-    # Toto platí před prvním spuštením skriptu, pak už ne (změníme place.name)
-    # assert place.name == school.official_name
-
-    schools.append(
-        {
-            "place_id": school.place_id,
-            "names": [school.official_name],
-            "city": parent_place.name,
-            "db_place": place,
-        }
-    )
 
 def eprint(*args, **kwargs):
     print(*args, file=sys.stderr, **kwargs)
@@ -91,38 +62,6 @@ def summarize(schools, k=5):
         eprint()
 
 
-city_rules = [
-    (r"(\w)-(\w)", r"\1 - \2"),  # Mezery kolem pomlček jsou někdy nekonzistentní
-    ("Praha", "v Praze"),
-    ("v Praze 4", "v Praze 12"),
-    (r"v Praze [0-9]+", "v Praze"),
-    ("v Praze", "Praha"),
-    None,  # Dummy
-]
-
-school_kinds = [
-    ("Gymnázium", "G"),
-    ("Vyšší odborná škola", "VOŠ"),
-    ("Střední odborná škola", "SOŠ"),
-    ("Střední zdravotnická škola", "SZŠ"),
-    ("Střední průmyslová škola", "SPŠ"),
-    ("Střední pedagogická škola", "SPŠ"),
-    ("Střední odborné učiliště", "SOU"),
-    ("Střední škola", "SŠ"),
-    ("Základní škola", "ZŠ"),
-    ("Základní umělecká škola", "ZUŠ"),
-    ("Mateřská škola", "MŠ"),
-]
-
-formalities = [
-    r",?-? ?příspěvková organizace",
-    r",? s.r.o.",
-    r",? o.p.s.",
-    r" s právem státní jazykové zkoušky",
-    r",? ?okres .+$",
-]
-
-
 def remove_formalities(name):
     for formality in formalities:
         name = re.sub(formality, "", name, flags=re.IGNORECASE)
@@ -190,6 +129,20 @@ def should_have_comma_after_name(p_name):
     return True
 
 
+def postprocess_name_part(p_name):
+    # Vyřeší okrajové případy části názvu před městem
+
+    p_name = p_name.strip(" ,-")
+    p_name = re.sub(
+        " v$", "", p_name
+    )  # Pro případy jako "G v Kroměříži" -> "G v, Kroměříž"
+
+    if should_have_comma_after_name(p_name):
+        p_name += ","
+
+    return p_name
+
+
 def shorten_all(schools):
     for sc in schools:
         sc["names"].append(remove_formalities(sc["names"][-1]))
@@ -204,7 +157,8 @@ def shorten_all(schools):
         if sc["parts"] is not None:
             if len(sc["parts"]) == 1:
                 # Název města nenalezen v názvu školy
-                sc["names"].append(f"{sc['names'][-1]}, {sc['city']}")
+                p_name = postprocess_name_part(sc["names"][-1])
+                sc["names"].append(f"{p_name} {sc['city']}")
             else:
                 # Když máme rozdělení, můžeme zkusit odstanit číslo popisné
                 # a případně i celý název ulice
@@ -213,9 +167,8 @@ def shorten_all(schools):
 
                 p_name, p_place = sc["parts"]
 
-                p_name = shorten_name(p_name).strip(" ,-")
-                if should_have_comma_after_name(p_name):
-                    p_name += ","
+                p_name = shorten_name(p_name)
+                p_name = postprocess_name_part(p_name)
 
                 p_place2, changed = remove_house_number(p_place)
 
@@ -224,12 +177,14 @@ def shorten_all(schools):
                         f"{p_name} {sc['city']}, {p_place2.strip(' ,-')}"
                     )
 
-                sc["names"].append(f"{p_name} {sc['city']}")
+                if "Praha" not in sc["city"]:  # např. "G Praha 2" nechceme
+                    sc["names"].append(f"{p_name} {sc['city']}")
 
     eprint(f"Successfully split up {n_split} schools")
 
     return schools
 
+
 def is_conflict(names1, names2):
     return any([(name in names1) for name in names2])
 
@@ -268,27 +223,115 @@ def remove_conflicts(shortened):
     eprint("Done (possible unremovable conflicts)")
 
 
-shortened = shorten_all(schools)
-remove_conflicts(shortened)
+city_rules = [
+    (r"(\w)-(\w)", r"\1 - \2"),  # Mezery kolem pomlček jsou někdy nekonzistentní
+    ("Praha", "v Praze"),
+    ("v Praze 4", "v Praze 12"),
+    (r"v Praze [0-9]+", "v Praze"),
+    ("v Praze", "Praha"),
+    None,  # Dummy
+]
+
+school_kinds = [
+    ("Gymnázium", "G"),
+    ("Vyšší odborná škola", "VOŠ"),
+    ("Střední odborná škola", "SOŠ"),
+    ("Střední zdravotnická škola", "SZŠ"),
+    ("Střední průmyslová škola", "SPŠ"),
+    ("Střední pedagogická škola", "SPŠ"),
+    ("Střední odborné učiliště", "SOU"),
+    ("Střední škola", "SŠ"),
+    ("Základní škola", "ZŠ"),
+    ("Základní umělecká škola", "ZUŠ"),
+    ("Mateřská škola", "MŠ"),
+]
+
+formalities = [
+    r",?-? ?příspěvková organizace",
+    r",? s\.r\.o\.",
+    r",? o\.p\.s\.",
+    r" s právem státní jazykové zkoušky",
+    r",? ?okres .+$",
+]
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description="Automaticky zkrátí jména škol v databázi"
+    )
+    parser.add_argument(
+        "-n",
+        "--dry-run",
+        action="store_true",
+        help="Jen zobrazit vygenerovaná zkrácení, neměnit databázi",
+    )
+    parser.add_argument(
+        "--restore", action="store_true", help="Vrátí se k oficiálním názvům"
+    )
+    args = parser.parse_args()
 
-summarize(shortened, k=10)
+    session = db.get_session()
+
+    school_place_t = aliased(db.Place)
+    parent_place_t = aliased(db.Place)
+
+    schools_q = (
+        session.query(db.School, school_place_t, parent_place_t)
+        .filter(db.School.place_id == school_place_t.place_id)
+        .filter(parent_place_t.place_id == school_place_t.parent)
+        .all()
+    )
 
-try:
-    from tqdm import tqdm
-except:
-    tqdm = lambda x: x
+    if args.restore:
+        eprint("Vracím se k původním názvům.")
+        for school, place, parent_place in schools_q:
+            place.name = school.official_name
 
+        session.commit()
+        return
 
-# Tohle trvá nesmyslně dlouho, určitě to jde rychleji
-places = session.query(db.Place)
+    schools = []
 
-for sc in tqdm(shortened):
-    sc["db_place"].name = sc["names"][-1]
+    for school, place, parent_place in schools_q:
 
-    (
-        places.filter(db.Place.place_id == sc["place_id"]).update(
-            {db.Place.name: sc["names"][-1]}
+        # Parent má být škola
+        assert parent_place.level == 3
+
+        # Toto platí před prvním spuštením skriptu, pak už ne (změníme place.name)
+        # assert place.name == school.official_name
+
+        schools.append(
+            {
+                "place_id": school.place_id,
+                "names": [school.official_name],
+                "city": parent_place.name,
+                "db_place": place,
+            }
         )
-    )
 
-session.commit()
+    shortened = shorten_all(schools)
+    remove_conflicts(shortened)
+
+    summarize(shortened, k=10)
+
+    if args.dry_run:
+        filename = "prejmenovani.txt"
+        with open(filename, "w") as f:
+            shortened.sort(key=lambda sc: sc["names"][0])
+
+            for sc in shortened:
+                # f.write(f"{sc['names'][0]} -> {sc['names'][-1]}\n")
+                f.write(f"{sc['names'][-1]}        ({sc['names'][0]})\n")
+                # f.write(f"{sc['names']}, {sc['city']}\n")
+
+        print(f"Seznam všech přejmenování uložen do {filename}.")
+        return
+
+    # Zapsat do DB
+    for sc in shortened:
+        sc["db_place"].name = sc["names"][-1]
+    session.commit()
+
+
+if __name__ == "__main__":
+    main()
-- 
GitLab