# Оценка наблюдений Статус наблюдения отражает, удался ли приём. Он выставляется тремя путями: автоматически при загрузке результатов, автоматически при их отсутствии и вручную при вычитке. ## Шкала | Числовое значение | Статус | Как появляется | |---|---|---| | `100` | good | Автоматически при получении кадров или вручную | | `0` | unknown | Значение по умолчанию, наблюдение не оценивалось | | `-1000` | failed | Автоматически, если артефактов нет вовсе | | отрицательные | bad | Вручную при вычитке | Отдельно хранится `waterfall_status` — результат ручной вычитки водопада. Именно он отличает оценку человека от автоматической: `NULL` означает, что водопад никто не смотрел. ## Автоматический «failed» `find_and_rate_failed_observations` (каждые 15 минут) находит наблюдения, у которых одновременно: * нет водопада (`waterfall == ""`); * нет аудио (`payload == ""`); * нет демодулированных данных; * прошло больше `OBS_NO_RESULTS_IGNORE_TIME` с момента окончания; * наблюдение не архивировано. Всем таким проставляется `-1000`. Массовое появление «failed» обычно означает, что станции не загружают результаты, а не что приём не удался — см. [](troubleshooting.md). ## Оценка при загрузке `rate_observation(observation_id, action, action_value)` вызывается при событиях — загрузке кадра, установке статуса водопада и т. п. — и возвращает результат во всех формах сразу: числом, именем бейджа и отображаемым названием. Ключевое правило: приём одного кадра для аналоговых режимов (**CW**, **FM**) не считается успехом — эти режимы исключаются из автоматического «good». ## Баг завышенных оценок и его исправление ```{warning} До исправления в `rate_observation` ветка `data_upload` сравнивала ForeignKey `downlink_mode` со списком строк. Такое сравнение всегда истинно, поэтому **любое** наблюдение, получившее хотя бы один кадр, оценивалось как «good» (100) — включая CW и FM, которые проверка как раз должна была исключать. Вся статистика успешности сети, построенная на этих данных, завышена. ``` Точно откатить последствия нельзя: значение `100`, записанное багом, в самом поле неотличимо от `100`, поставленного человеком при вычитке. Поэтому команда `recalculate_observation_ratings` намеренно консервативна и трогает только то, на что никто не претендовал вручную. Наблюдение сбрасывается, если выполнены **все** условия: * `status == 100`; * есть демодулированные данные (то есть ошибочная ветка действительно отработала); * режим передачи вниз — CW или FM; * `waterfall_status` пуст — водопад никто не вычитывал. Такие наблюдения возвращаются в `0` («unknown»), а не в «bad»: наблюдение никогда не оценивали, и объявить его неудачным — та же ошибка, только зеркальная. По умолчанию команда работает в режиме предпросмотра, запись — по флагу `--apply`: ```bash docker compose run --rm web django-admin recalculate_observation_ratings docker compose run --rm web django-admin recalculate_observation_ratings --apply ``` ## Влияние на аналитику Оценка проставляется позже самого наблюдения, поэтому суточные метрики пересобираются не за один прошедший день, а за окно в 30 дней — см. [](analytics.md).