@startuml seq-wind title Визуализация поля ветра: статический режим и синхронизация с траекторией autonumber participant "predict/+page\n" as render participant "WindRenderer\n(.svelte)" as wr participant "WindCache\n(in-memory)" as cache participant "windApi" as wapi participant "Сервис\nпредсказателя\n(127.0.0.1:8080)" as pred participant "createWindInterpolator\n+ ParticleField" as pf note over wapi, pred Запросы идут НАПРЯМУЮ через fetch к сервису предсказателя, минуя client.ts: без CSRF и сессионных cookie. end note alt Статический режим (ветер по умолчанию) wr -> wr : параметры из активной области\n(высота старта, дата старта) wr -> cache : get(ключ = JSON параметров) alt промах кэша wr -> wapi : field({ altitude, step, time }) wapi -> pred : GET /api/v1/wind/field?altitude&step&time pred --> wapi : WindField [C_U, C_V] wapi --> wr : WindField wr -> cache : put(ключ, field) end wr -> pf : установить поле → анимация частиц end alt Режим синхронизации с траекторией note over wr : активен прогноз И timeline.max > 0 wr -> wr : bbox траектории + проверки\n(F ≤ Fmax, сторона ≤ Dmax) loop δ ∈ {0, ΔT, 2ΔT, …, F} wr -> wr : T = t0 + δ; высота a_{k*} (бин. поиск) wr -> cache : get(ключ кадра) alt промах кэша wr -> wapi : field({ altitude, step, time, min/max lat/lng }) wapi -> pred : GET /api/v1/wind/field?…(bbox) pred --> wapi : WindField кадра wapi --> wr : WindField wr -> cache : put(ключ кадра, field) end end loop при воспроизведении (timeline) wr -> wr : fieldAtFlightTime(δ):\nлинейная интерполяция [u,v]\nмежду соседними кадрами wr -> pf : currentField → плавная адвекция частиц end end note over wapi, pred windApi.meta() → GET /api/v1/wind/meta (опорное время / параметры сетки, при необходимости) end note @enduml