Версия: 2.0.0
Дата: 2025-12-25
Статус: Стандарт
Правила генерации стандартизированных названий для всех типов пиротехнических изделий.
Все наименования следуют единому формату:
[ТИП] "[НАЗВАНИЕ]" [ХАРАКТЕРИСТИКИ]
Компоненты:
- ТИП - тип изделия с заглавной буквы (Батарея салютов, Фонтан, и т.д.)
- НАЗВАНИЕ - коммерческое название в двойных кавычках
- ХАРАКТЕРИСТИКИ - калибр, залпы, высота, время (зависит от типа)
батарея)Шаблон:
Батарея салютов "[НАЗВАНИЕ]" [КАЛИБР]мм [ЗАЛПЫ] залпов
Regex:
^Батарея салютов "([^"]+)" (\d+)мм (\d+) залпов?$
Примеры:
- Батарея салютов "Праздничный" 30мм 49 залпов
- Батарея салютов "Юбилей" 30мм 100 залпов
- Батарея салютов "Золотая Москва" 25мм 25 залпов
Варианты:
- Короткая форма: Батарея "[НАЗВАНИЕ]" [ЗАЛПЫ] залпов
- Альтернатива: Салют "[НАЗВАНИЕ]" [ЗАЛПЫ] залпов
фонтан)Шаблон:
Фонтан "[НАЗВАНИЕ]" [ВЫСОТА]м
Regex:
^Фонтан "([^"]+)" (\d+)м$
Примеры:
- Фонтан "Золотой водопад" 3м
- Фонтан "Серебряный каскад" 5м
- Фонтан "Огненный дождь" 3м 60сек (с временем)
римская свеча)Шаблон:
Римская свеча "[НАЗВАНИЕ]" [ВЫСТРЕЛЫ] выстрелов
Regex:
^Римская свеча "([^"]+)" (\d+) выстрелов?$
Примеры:
- Римская свеча "Северное сияние" 10 выстрелов
- Римская свеча "Комета" 8 выстрелов
- Римская свеча "Звезда" 20мм 10 выстрелов (с калибром)
петарда)Шаблон:
Петарды "[НАЗВАНИЕ]" упаковка [N] шт
Regex:
^Петарды "([^"]+)" упаковка (\d+) шт$
Примеры:
- Петарды "Корсар-1" упаковка 20 шт
- Петарды "Корсар-4" упаковка 6 шт
- Петарды "Черная дробь" упаковка 10 шт
ракета)Шаблон:
Ракета "[НАЗВАНИЕ]" [N] залпов
Regex:
^Ракета "([^"]+)" (\d+) залпов?$
Примеры:
- Ракета "Комета" 5 залпов
- Ракета "Метеор" 3 залпа
бенгальские)Шаблон:
Бенгальские огни [N]см, [N] штук
ВАЖНО: Коммерческого названия в кавычках НЕТ!
Regex:
^Бенгальские огни (\d+)см, (\d+) штук?$
Примеры:
- Бенгальские огни 25см, 10 штук
- Бенгальские огни 40см, 5 штук
- Бенгальские огни 50см, 3 штуки
дым)Шаблон:
Дымовое изделие "[НАЗВАНИЕ]" [ЦВЕТ]
ВАЖНО: Не "Дым", а "Дымовое изделие"!
Regex:
^Дымовое изделие "([^"]+)" ([а-я]+)$
Примеры:
- Дымовое изделие "Облако" синий
- Дымовое изделие "Туман" красный
- Дымовое изделие "MA0509" зеленый
Цвета: белый, красный, синий, зеленый, желтый, оранжевый, фиолетовый
хлопушка)Шаблон:
Хлопушка "[НАЗВАНИЕ]" [ДЛИНА]см
Regex:
^Хлопушка "([^"]+)" (\d+)см$
Примеры:
- Хлопушка "Праздничная" 30см
- Хлопушка "Новогодняя" 60см
летающий)Шаблон:
[ТИП] "[НАЗВАНИЕ]"
Типы: НЛО, Вертолёт, Пчёлка
Примеры:
- НЛО "Летающая тарелка"
- Вертолёт "Апачи"
- Пчёлка "Майя"
набор)Шаблон:
Набор "[НАЗВАНИЕ]"
Regex:
^Набор "([^"]+)"$
Примеры:
- Набор "Новогодний"
- Набор "Семейный праздник"
def generate_product_name(product: Dict[str, Any]) -> str:
"""
Генерирует стандартизированное название товара
Args:
product: Нормализованные данные товара с полями:
- salute_type: тип изделия (lowercase!)
- commercial_name: коммерческое название
- caliber_mm: калибр в мм
- shots_count: количество залпов
- height_mm: высота в мм
- duration_sec: время работы
- pack_qty: количество в упаковке
- length_mm: длина (для бенгальских, хлопушек)
Returns:
Стандартизированное название
"""
salute_type = product.get('salute_type', '').lower()
name = product.get('commercial_name', 'Без названия')
# БАТАРЕИ
if salute_type == 'батарея':
caliber = product.get('caliber_mm')
shots = product.get('shots_count')
parts = ['Батарея салютов', f'"{name}"']
if caliber:
parts.append(f'{int(caliber)}мм')
if shots:
shots_word = get_shots_word(shots) # залп/залпа/залпов
parts.append(f'{shots} {shots_word}')
return ' '.join(parts)
# ФОНТАНЫ
elif salute_type == 'фонтан':
height_mm = product.get('height_mm')
duration = product.get('duration_sec')
parts = ['Фонтан', f'"{name}"']
if height_mm:
height_m = height_mm // 1000
parts.append(f'{height_m}м')
if duration:
parts.append(f'{duration}сек')
return ' '.join(parts)
# РИМСКИЕ СВЕЧИ
elif salute_type == 'римская свеча':
shots = product.get('shots_count')
caliber = product.get('caliber_mm')
parts = ['Римская свеча', f'"{name}"']
if caliber:
parts.append(f'{int(caliber)}мм')
if shots:
shots_word = get_shots_word(shots, word='выстрел')
parts.append(f'{shots} {shots_word}')
return ' '.join(parts)
# ПЕТАРДЫ
elif salute_type == 'петарда':
pack_qty = product.get('pack_qty')
parts = ['Петарды', f'"{name}"']
if pack_qty:
parts.append(f'упаковка {pack_qty} шт')
return ' '.join(parts)
# РАКЕТЫ
elif salute_type == 'ракета':
shots = product.get('shots_count')
parts = ['Ракета', f'"{name}"']
if shots:
shots_word = get_shots_word(shots)
parts.append(f'{shots} {shots_word}')
return ' '.join(parts)
# БЕНГАЛЬСКИЕ ОГНИ (БЕЗ НАЗВАНИЯ!)
elif salute_type == 'бенгальские':
length_mm = product.get('length_mm')
pack_qty = product.get('pack_qty')
if length_mm and length_mm > 100:
length_cm = length_mm // 10
else:
length_cm = length_mm if length_mm else None
parts = ['Бенгальские огни']
if length_cm:
parts.append(f'{length_cm}см')
if pack_qty:
qty_word = get_qty_word(pack_qty) # штука/штуки/штук
if length_cm:
return f'{parts[0]} {length_cm}см, {pack_qty} {qty_word}'
else:
return f'{parts[0]} {pack_qty} {qty_word}'
return ' '.join(parts)
# ДЫМОВЫЕ ИЗДЕЛИЯ
elif salute_type == 'дым':
# TODO: извлечь цвет из названия или отдельного поля
return f'Дымовое изделие "{name}"'
# ХЛОПУШКИ
elif salute_type == 'хлопушка':
length_mm = product.get('length_mm')
parts = ['Хлопушка', f'"{name}"']
if length_mm:
if length_mm > 100:
length_cm = length_mm // 10
else:
length_cm = length_mm
parts.append(f'{length_cm}см')
return ' '.join(parts)
# ЛЕТАЮЩИЕ
elif salute_type == 'летающий':
# TODO: определить конкретный тип (НЛО, Вертолёт, Пчёлка)
return f'Летающее изделие "{name}"'
# НАБОРЫ
elif salute_type == 'набор':
return f'Набор "{name}"'
# FALLBACK
else:
return f'{salute_type.capitalize()} "{name}"'
def get_shots_word(count: int, word: str = 'залп') -> str:
"""Правильное склонение для залпов/выстрелов"""
# залп, залпа, залпов
# выстрел, выстрела, выстрелов
if count % 10 == 1 and count % 100 != 11:
return word
elif count % 10 in (2, 3, 4) and count % 100 not in (12, 13, 14):
if word == 'залп':
return 'залпа'
elif word == 'выстрел':
return 'выстрела'
else:
if word == 'залп':
return 'залпов'
elif word == 'выстрел':
return 'выстрелов'
Примеры:
- 1 залп, 21 залп, 31 залп
- 2 залпа, 3 залпа, 4 залпа, 22 залпа
- 5 залпов, 10 залпов, 25 залпов, 100 залпов
def get_qty_word(count: int) -> str:
"""Правильное склонение для штук"""
# штука, штуки, штук
if count % 10 == 1 and count % 100 != 11:
return 'штука'
elif count % 10 in (2, 3, 4) and count % 100 not in (12, 13, 14):
return 'штуки'
else:
return 'штук'
Примеры:
- 1 штука, 21 штука
- 2 штуки, 3 штуки, 4 штуки, 22 штуки
- 5 штук, 10 штук, 20 штук
Версия: 2.0.0
Дата: 2025-12-25