2026-11-12 23:41:42 +04:00

110 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Сборка `companies.csv` (спека §4.1): 400 вымышленных организаций без случайности.
Запуск из корня репозитория: `python -m synthgen.dictionary.build` — перезаписывает `companies.csv`.
Имена — перебор «прилагательное × существительное» по отраслям с фиксированным шагом, ИНН — подряд от 0100001.
"""
import csv
from pathlib import Path
from synthgen import inn
from synthgen.dictionary import CSV_PATH, HEADER, Org
FIRST_SEQ = 100001 # ИНН-номер 0100001
PER_SECTOR = 55
IP_COUNT = 40
BANK_COUNT = 30
# (основа, окончания для m/f/n)
_ADJ = ["Лазурн", "Янтарн", "Изумрудн", "Рубинов", "Серебрян", "Заревн", "Лунн", "Северн"]
_ENDINGS = {"m": "ый", "f": "ая", "n": "ое"}
# отрасль → существительные (слово, род)
_SECTORS: dict[str, list[tuple[str, str]]] = {
"агро": [("Нива", "f"), ("Колос", "m"), ("Урожай", "m"), ("Пашня", "f"), ("Зерно", "n"),
("Луг", "m"), ("Сад", "m"), ("Борозда", "f"), ("Поле", "n"), ("Амбар", "m")],
"торговля": [("Рынок", "m"), ("Склад", "m"), ("Лавка", "f"), ("Ярмарка", "f"), ("Базар", "m"),
("Торг", "m"), ("Магазин", "m"), ("Прилавок", "m"), ("Пассаж", "m"), ("Товар", "m")],
"логистика": [("Путь", "m"), ("Маршрут", "m"), ("Фургон", "m"), ("Трасса", "f"), ("Обоз", "m"),
("Тягач", "m"), ("Рейс", "m"), ("Перевал", "m"), ("Караван", "m"), ("Эстакада", "f")],
"производство": [("Завод", "m"), ("Цех", "m"), ("Станок", "m"), ("Мельница", "f"), ("Пекарня", "f"),
("Кузница", "f"), ("Фабрика", "f"), ("Горн", "m"), ("Верфь", "f"), ("Мануфактура", "f")],
"услуги": [("Сервис", "m"), ("Бюро", "n"), ("Центр", "m"), ("Консалт", "m"), ("Профи", "m"),
("Партнёр", "m"), ("Совет", "m"), ("Контора", "f"), ("Мастерская", "f"), ("Приём", "m")],
"строительство": [("Фундамент", "m"), ("Кирпич", "m"), ("Монолит", "m"), ("Каркас", "m"), ("Проект", "m"),
("Стройка", "f"), ("Бастион", "m"), ("Зодчий", "m"), ("Арка", "f"), ("Мост", "m")],
}
_BANK_WORDS = ["Банк", "Кредитный Банк", "Деловой Банк", "Земельный Банк"]
_SURNAMES = [
"Авдонина", "Бражников", "Ветрова", "Голубев", "Дроздова", "Ермаков", "Жарова", "Зуев", "Игнатова", "Копылов",
"Лаврова", "Мартынов", "Норина", "Овчаров", "Пименова", "Рябов", "Сорокина", "Тарасов", "Устинова", "Фролов",
"Хромова", "Цветаев", "Чернова", "Шаров", "Щукина", "Юдин", "Яковлева", "Баранов", "Волкова", "Гусев",
"Денисова", "Елисеев", "Зайцева", "Исаев", "Калинина", "Леонов", "Маслова", "Назаров", "Орлова", "Панов",
]
_INITIALS = ["Е.И.", "А.П.", "Н.С.", "В.Д.", "О.А.", "М.В.", "И.Н.", "С.К.", "Т.Р.", "Д.Л."]
_IP_KINDS = ["услуги", "торговля", "логистика", "агро", "строительство", "производство"]
def _kpp(seq: int) -> str:
"""КПП: `00` + двузначный номер + `01001` (как в #35)."""
return f"00{seq % 100:02d}01001"
def _legal_form(idx: int) -> str:
if idx % 17 == 0:
return "ПАО"
return "АО" if idx % 5 == 0 else "ООО"
def build_records() -> list[Org]:
"""400 записей: 330 юрлиц по отраслям (с шагом 3 по сетке 80 пар), 40 ИП, 30 банков."""
orgs: list[Org] = []
seq = FIRST_SEQ
def add(name: str, form: str, kind: str) -> None:
nonlocal seq
if form == "ИП":
orgs.append(Org(name, form, inn.make_inn12(seq), "", kind))
else:
orgs.append(Org(name, form, inn.make_inn10(seq), _kpp(seq), kind))
seq += 1
legal_idx = 0
for j in range(PER_SECTOR):
pair = (j * 3) % (len(_ADJ) * 10) # gcd(3, 80) = 1 — пары не повторяются
adj_stem = _ADJ[pair % len(_ADJ)]
for kind, nouns in _SECTORS.items():
noun, gender = nouns[pair // len(_ADJ)]
legal_idx += 1
form = _legal_form(legal_idx)
add(f"{adj_stem}{_ENDINGS[gender]} {noun} {form}", form, kind)
for j in range(IP_COUNT):
add(f"{_SURNAMES[j]} {_INITIALS[j % len(_INITIALS)]} ИП", "ИП", _IP_KINDS[j % len(_IP_KINDS)])
for j in range(BANK_COUNT):
stem = _ADJ[j % len(_ADJ)]
words = _BANK_WORDS[(j // len(_ADJ)) % len(_BANK_WORDS)]
form = "ПАО" if j % 2 else "АО"
add(f"{stem}ый {words} {form}", form, "банк")
return orgs
def write_csv(path: Path, orgs: list[Org] | None = None) -> None:
rows = orgs if orgs is not None else build_records()
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w", encoding="utf-8", newline="") as fh:
writer = csv.writer(fh, delimiter=";", lineterminator="\n")
writer.writerow(HEADER)
for o in rows:
writer.writerow([o.name, o.form, o.inn, o.kpp, o.kind])
def main() -> None:
write_csv(CSV_PATH)
print(f"записано {CSV_PATH}")
if __name__ == "__main__":
main()