---
type: tech-risks
work_item_id: ET-005
title: "Технические риски — ET-005: Переключение единиц измерения (км/мили)"
version: 1
status: approved
created_at: 2026-05-21
authors:
  - "agent:architect"
---

# Технические риски — ET-005

Шкала: вероятность (Н/С/В) × влияние (Н/С/В).

## R1 — Пропуск одного из мест форматирования расстояний

- **Описание:** форматирование `(m/1000).toFixed(N)+' км'` захардкожено
  минимум в **13 местах** `src/web/app.js`. Если хотя бы одно не
  переведено на `Units.formatDistance()`, после переключения на мили это
  расстояние останется в км — нарушение AC-2 («все расстояния»).
- **Известные call-sites** (ориентир для разработки и review):
  `formatDist()` ≈ стр. 187–189; карточка сегмента ≈ 638; карточки
  маршрута ≈ 1157, 1191, 2202/2212, 2357/2370, 2605; scale-bar
  ≈ 1416–1440; всплывающая подсказка ≈ 1478; линейка/ruler ≈ 1837,
  1875, 1885, 1931. Список ориентировочный — нумерация строк может
  сдвинуться; обязателен повторный grep-аудит.
- **Вероятность / Влияние:** С / В.
- **Митигация:** централизация в `units.js` (ADR-0001); grep-аудит
  по `' км'` / `/ 1000` / `toFixed` на этапе разработки; e2e TP-02
  должен проверять **каждую** видимую поверхность с расстоянием, а не
  одну.

## R2 — Отсутствие политики для суб-километровых расстояний

- **Описание:** часть мест отображает расстояния < 1 км в метрах
  («м» — напр. линейка, стр. 1837/1885). Имперский эквивалент в AC не
  определён (футы? мили с долями?). Без явной политики возможен
  показ «м» в режиме «mi».
- **Вероятность / Влияние:** В / С.
- **Митигация:** зафиксировать политику в реализации `units.js`.
  Рекомендация архитектуры: в режиме `mi` суб-километровые значения
  показывать в милях с увеличенной точностью (напр. 2 знака), **футы
  не вводить** — это упрощает форматтер и достаточно для эндуро-сценария.
  Финальное решение — за разработкой/ревью, но политика должна быть
  единой и явной.

## R3 — Scale-bar имеет собственную логику единиц

- **Описание:** масштабная линейка карты (`szb`, стр. 1416–1440) уже
  содержит независимую логику `km`/`m` с «красивым» округлением. Это
  отдельный код-путь, который легко не заметить при рефакторинге.
- **Вероятность / Влияние:** С / С.
- **Митигация:** явно включить scale-bar в список перевода на `Units`
  и в оркестратор `onUnitChange()`; добавить scale-bar в проверки e2e
  TP-02.

## R4 — Несогласованный разделитель дробной части

- **Описание:** в `app.js` есть расхождение — `formatDist()` (стр. 189)
  использует точку (`12.3 км`), карточка сегмента (стр. 638) —
  `.replace('.', ',')` (`12,3 км`). При централизации форматтер должен
  выбрать один вариант, иначе UI станет визуально неоднородным.
- **Вероятность / Влияние:** В / Н.
- **Митигация:** `units.js` задаёт единый разделитель для всех
  поверхностей. Так как у задачи нет требования на локаль, рекомендуется
  оставить запятую (текущий пользовательский язык интерфейса — русский),
  но решение должно быть единым и явным.

## R5 — Конфликт точности: AC-2 vs существующие карточки

- **Описание:** AC-2 требует «округление до 1 знака», но карточки
  маршрутов сейчас используют `toFixed(0)` (целые км, стр. 2202, 2357).
  Слепое применение «1 знака» изменит вид карточек; слепое сохранение
  `toFixed(0)` нарушит букву AC-2.
- **Вероятность / Влияние:** С / Н.
- **Митигация:** `formatDistance(meters, {precision})` параметризует
  точность; по умолчанию — 1 знак (AC-2), карточки явно запрашивают
  свою точность. Трактовка: AC-2 задаёт точность пересчёта/дефолта, а
  не запрещает целочисленный показ в карточках.

## R6 — Экспорт GPX и параметрические значения не должны конвертироваться

- **Описание:** есть риск «заодно» сконвертировать величины, которые
  обязаны остаться метрическими: экспорт GPX (стандарт GPX — метры) и
  кнопки-параметры построения маршрута (`data-km` радиусы разведки/
  scenic: «20 км», «50», «100», `index.html:130–180`). Это **входные
  параметры**, а не отображаемые расстояния.
- **Вероятность / Влияние:** Н / С.
- **Митигация:** scope ET-005 — **только отображаемые** расстояния.
  GPX-данные и `data-km`-параметры из перевода единиц **исключены**;
  зафиксировать в review-чеклисте.

## R7 — Порядок подключения скриптов

- **Описание:** `units.js` подключается как классический скрипт; `app.js`
  обращается к `window.Units` на старте. Если `units.js` подключён после
  `app.js`, инициализация упадёт с `Units is not defined`.
- **Вероятность / Влияние:** Н / В.
- **Митигация:** `<script src="units.js">` строго перед
  `<script src="app.js">` в `index.html`; контрольная точка review;
  smoke-проверка загрузки страницы.

## R8 — Мобильное размещение переключателя

- **Описание:** НФТ ТЗ и AC-4 требуют доступности кнопки на всех
  размерах экрана и неперекрытия других элементов. Попап `#terrain-popup`
  пополняется ещё одним рядом — на узких экранах (375px, TP-05) возможен
  выход за пределы/перекрытие.
- **Вероятность / Влияние:** Н / С.
- **Митигация:** переиспользовать готовый `.seg-control` (адаптивен по
  ширине); проверить попап на 375px; e2e TP-05.

## Сводка

| ID | Риск | Вер. | Влияние | Класс |
|----|------|------|---------|-------|
| R1 | Пропуск call-site форматирования | С | В | Высокий |
| R2 | Нет политики для суб-км значений | В | С | Высокий |
| R3 | Scale-bar — отдельная логика единиц | С | С | Средний |
| R4 | Несогласованный десятичный разделитель | В | Н | Средний |
| R5 | Конфликт точности AC-2 vs карточки | С | Н | Низкий |
| R6 | GPX / параметры не конвертировать | Н | С | Низкий |
| R7 | Порядок подключения скриптов | Н | В | Средний |
| R8 | Мобильное размещение переключателя | Н | С | Низкий |

Блокирующих рисков нет. R1 и R2 требуют явного внимания на разработке и
ревью. Эскалация `arch:major-change` или возврат в Анализ не требуются.
