110 lines
5.8 KiB
Python
110 lines
5.8 KiB
Python
"""Сборка `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()
|