Сервіси
Модуль SEARCH: алгоритм маршрутів і POST_DRONE
Додаток A до рамкового ТЗ: блок-схема № 3.1.1 — основний і єдиний алгоритм пошуку для будь-якого перевезення, що потребує понад одного виду транспорту, розширена на шість видів транспорту без зміни структури графа.
Це специфікація алгоритму, а не працюючий сервіс: жодної бази points/lots, жодного API /search/routes і жодного Go-сервіса SEARCH у цьому демо немає. JSON Schema контракту POST_DRONE (schemas/post-drone.schema.json) і її перевірка (schemas/check_schema.py) — реальні, робочі файли цього репозиторію: 12 прикладів валідні, 37 із 37 мутацій відхилено. ci/check_contract_text.py — теж реальний файл, і тепер він виконується: каталог proto/ і grpc_tools на місці, прогін дає 24 перевірки узгодженості тексту ТЗ зі схемою й proto-контрактом, а self-test виявляє 10 із 10 мутацій. Цей прогін — крок job-а proto конвеєра contract.yml, тобто частина обов'язкової перевірки «Контракт proto модуля SEARCH».
Підсистеми модуля (S1–S8)
| ID | Назва | Зміст |
|---|---|---|
S1 | Простий пошук заявок | Пошук по одному розділу за фільтрами: країна, регіон, пункт, дата, тип транспорту, тип завантаження, маса, обʼєм |
S2 | Фільтр «інші напрямки» | Два незалежні списки пунктів відправлення / призначення |
S3 | Пошук зворотних рейсів | Заявки, виставлені до пункту відправлення (ймовірний зворотний рейс) |
S4 | Пошук мультимодального маршруту | Основний алгоритм — блок-схема № 3.1.1; ланцюг заявок з 2–4 плечима по 6 видах транспорту |
S5 | Fallback «компанії напрямку» | Перелік компаній, які коли-небудь перевозили в цьому напрямку |
S6 | Fallback «можливі сполучення» | Перелік станцій/портів/аеропортів/точок дрона, між якими існує сполучення |
S7 | Ранжування | Сортування за критерієм «вартість» або «швидкість» + успадкований коефіцієнт переваги |
S8 | Збереження запиту | Історія запитів, підписка, сповіщення про нові відповідні заявки |
Шість видів транспорту в графі маршруту
Дрон — не плече графа, а пост-обробка вже знайденого маршруту: єдина реалізація замість чотирьох копій умови в кожній гілці.
| Код | Назва | Роль у графі | База пунктів |
|---|---|---|---|
M | Море | Магістральне плече (гілка 1) | порти (seaport) |
F | Авіа | Магістральне плече — альтернатива морю | аеропорти (airport) |
T | ЖД | Фідерне плече 1-го рівня | станції (rail_station) |
A | Авто | Фідерне плече 2-го рівня, «остання миля» | міста (city) |
D | Дрон | Не плече графа — пост-обробка останнього авто-плеча | майданчики (drone_pad) |
X | Мультимодальний | Не окреме плече — розділ із доступом до заявок усіх розділів | усі типи пунктів |
Ворота модуля POST_DRONE (рисунок 3.1.1-7)
Кожне «ні» — вихід із модуля: авто-плече лишається без змін, дрон-варіант не створюється і не замінює авто-варіант.
| Ворота | Перевірка | Код причини | Сценарій |
|---|---|---|---|
| 1 | Плече останнє й вид — авто | not_last_auto_leg | T16 |
| 2 | Зона дозволена (немає no_permit) | no_permit | T17 |
| 3 | d ≤ range_km × drone_range_margin | out_of_range | T18 |
| 4 | weight_t × 1000 ≤ max_payload_kg, габарити, ADR, не живі тварини | cargo_not_allowed | T19 |
| 5 | Лот D знайдено або підставлено площадку в межах max_legs=4 | no_drone_lot / no_landing_pad / max_legs_exceeded / extra_leg_disabled | T20, T22, T23 |
| 6 | Погода у вікні вильоту (не відмова — прапорець weather_risk) | — (weather_risk) | T21, T26 |
| — | Модуль вимкнено запитом | drone_disabled | T24 |
| — | Перевищено бюджет модуля | timeout | T25 |
Ранжування: ваги критерію та штрафи за прапорці
| Критерій | wc | wt | wk | wr | wn |
|---|---|---|---|---|---|
cost | 0.55 | 0.10 | 0.15 | 0.10 | 0.10 |
time | 0.10 | 0.55 | 0.10 | 0.10 | 0.15 |
balanced | 0.30 | 0.30 | 0.15 | 0.15 | 0.10 |
| Прапорець | Штраф | Обґрунтування |
|---|---|---|
weather_risk | 0.08 | Ризик погоди або невідома погода у дрон-плечі |
no_permit | 0.10 | Плече без дозволу вимагає дій учасника |
customs_missing | 0.06 | У плечі немає потрібного документа CMR/T1/TIR |
estimated_price | 0.03 | Вартість не з лота, а з медіан link_stats |
Кроки CI (обовʼязкові для злиття)
Контракт, правило гілки та валютно-мовні сценарії не потребують ні бази, ні застосунку — лише текст ТЗ, схему і фікстури.
| Крок | Команда | Що падає |
|---|---|---|
| Контракт | schemas/validate_schema.py, schemas/check_schema.py | невалідний приклад A.8.4.1, порушення програмної перевірки, непокрита мутація, непокритий код reason |
| Правило гілки | ci/check_ruleset.py | перевірка з правила не відповідає job-у, gate не залежить від нового job-а, фільтр paths у тригері, сценарій не описаний у ТЗ |
| Числа в документації | ci/check_doc_counts.py | твердження ТЗ про кількість обовʼязкових перевірок, діапазон правил R1–RN, кількість сценаріїв pull request чи назва групи сценаріїв відстали від фактичного складу правила гілки й конвеєрів |
| Валюти й мови | schemas/check_i18n.py | різна базова валюта в A.5 і рамковому ТЗ, застарілий курс без позначки, непокрита мутація |
| Текст/схема/proto | ci/check_contract_text.py (U1–U5, N1–N5) | розбіжність носія одиниці ваги або коду валюти між ТЗ, схемою і proto |
| Юніт і приймання | тести модуля + сценарії T1–T27 | розбіжність реалізації або поведінки з контрактом (модуль ще не реалізований) |
Стан у цьому репозиторії: schemas/check_schema.py, schemas/check_i18n.py, ci/check_ruleset.py (R1–R11, 18 мутацій) і новий ci/check_doc_counts.py (D1–D8, 9 мутацій) проходять на 100% — перевірено в цій сесії, разом із самоперевіркою ci/check_doc_counts.py --self-test. ci/check_ruleset.py поки узгоджує лише конвеєр контракту й UI-сценаріїв — job proto, який мав би викликати ci/check_contract_text.py, ще не доданий.