Easy-to-manage touch screens
Free, open-source touch screens. Guided USB setup, a drag-and-drop editor and local control. Made for Home Assistant.
Прогноз северного сияния для семи точек Мурманской области: Kp-индекс, облачность по ярусам, лучшее время наблюдения и подсказка, куда ехать этой ночью.
Translation pending
LifestyleJavaScript · CSSGitHub @PoInT8137OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Дашборд прогноза северного сияния для Мурманска: Kp-индекс NOAA SWPC, облачность по ярусам Open-Meteo, оценка шанса и лучшее время наблюдения этой ночью. Чистый HTML/CSS/JS без зависимостей и сборки.
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Дашборд прогноза северного сияния для семи точек Мурманской области: текущий Kp-индекс, облачность по ярусам, оценка шанса увидеть сияние и лучшее время для наблюдения ближайшей ночью. Интерфейс на трёх языках — русском, английском и китайском: в Мурманск за сиянием едут туристы со всего мира (см. Языки). HTML, CSS и чистый JavaScript. Без фреймворков, без сборки, без зависимостей: страница — это несколько статических файлов и браузер. Необязательная серверная часть — только для уведомлений при закрытом приложении (см. ниже).Read the full README ↗
Дашборд прогноза северного сияния для семи точек Мурманской области: текущий Kp-индекс, облачность по ярусам, оценка шанса увидеть сияние и лучшее время для наблюдения ближайшей ночью.
Интерфейс на трёх языках — русском, английском и китайском: в Мурманск за сиянием едут туристы со всего мира (см. Языки).
HTML, CSS и чистый JavaScript. Без фреймворков, без сборки, без зависимостей: страница — это несколько статических файлов и браузер. Необязательная серверная часть — только для уведомлений при закрытом приложении (см. ниже).
Двойной клик по index.html обычно работает: оба API отдают Access-Control-Allow-Origin: *. Если браузер всё же заблокирует запросы со страницы, открытой по file://, поднимите локальный сервер:
python -m http.server 8765
и откройте http://localhost:8765.
node --test tools/*.test.mjs и cd worker && npm test: тесты сайта и сервера (их же гоняет GitHub Actions).tools/budget.test.mjs: бюджет скорости. Первый заход (страница, стили, скрипты в gzip) не тяжелее заданного числа КБ и файлов.tools/golden.test.mjs: эталонные ночи из tools/golden-nights.json. Реальные случаи, где ответ известен (например, 8.10.2026: яркое сияние при Kp 0,67).node tools/lighthouse.mjs: замер скорости как с телефона на медленном мобильном интернете (медиана трёх прогонов).node tools/live-check.mjs: после публикации проверяет версию на сайте, файлы и время ответа сервера данных..githooks/pre-commit (включается командой git config --worktree core.hooksPath .githooks): перед коммитом тесты, совпадение версий страницы и кэша, нет длинных тире в новых строках.Пять вкладок: «Сейчас» — условия в выбранной точке, «Куда ехать ночью» — сравнение всех семи точек на ближайшую ночь, «Карта» — семь точек на схеме области, «Гид» — советы для туриста, «Настройки» — вид и единицы, а ниже уведомления: проверка и настройка. Вкладка запоминается и отражается в адресе (#now, #tonight, #map, #guide, #settings), так что ссылкой можно поделиться; старые ссылки #notify открывают «Настройки». На широком экране навигация сверху, на узком — внизу экрана и листается вбок; выбранная вкладка сама доезжает до середины панели.
Вкладка «Сейчас»:
| Блок | Содержимое |
|---|---|
| Шанс увидеть сияние | Низкий / средний / высокий на текущий момент, пояснение и список учтённых факторов |
| Лучшее время этой ночью | Окно наблюдения и почасовая раскладка ближайшей ночи |
| Kp-индекс | Текущее значение, шкала 0–9, время измерения |
| Облачность | Эффективная облачность, разбивка по трём ярусам |
| Погода на месте | Температура и «ощущается как», ветер с порывами и направлением, видимость, влажность; главное, что мешает: туман, снег, осадки или сильный ветер |
| Солнечный ветер | Bz, сила поля и скорость со спутников в точке L1, график Bz за 2 часа и оценка на ближайший час |
| Модель NOAA OVATION | Вероятность сияния в поле зрения и прямо над точкой на ближайшие 30–90 минут |
| Прогноз Kp | Трое суток с шагом 3 часа, текущая трёхчасовка подсвечена |
Вкладка «Куда ехать ночью»:
| Блок | Содержимое |
|---|---|
| Ответ | Лучшая точка и её окно наблюдения — либо прямое «ехать некуда» |
| Список точек | Все семь по убыванию оценки: окно, облачность, порог Kp, расстояние и время в пути |
| Когда ехать | Прогноз NOAA на 27 дней: наибольший Kp по дням, светлые ночи и яркая Луна, лучшие даты для выбранной точки |
Облачность для всех семи точек запрашивается одним запросом к Open-Meteo: API принимает список координат через запятую и возвращает массив в том же порядке. Kp и его прогноз переиспользуются с первой вкладки — это планетарные величины, одинаковые для всей области.
Данные второй вкладки грузятся при первом её открытии, а не при старте приложения, и кэшируются на тех же правилах, что остальные: три часа, пометка возраста при показе из кэша.
Если ни в одной точке условия не дотягивают до среднего, в ответе так и написано — «ехать некуда», с указанием причины. Лучшее из плохого в крупной строке не показывается, но список ниже остаётся полным: по нему видно основание для вывода.
Точка выбирается в шапке, выбор сохраняется в браузере. Координаты проверены по открытому геокодеру Open-Meteo (данные GeoNames), геомагнитная широта посчитана дипольным приближением IGRF для эпохи ~2025 (полюс 80.7° с. ш., 72.7° з. д.):
sin(φm) = sin(φ)·sin(φp) + cos(φ)·cos(φp)·cos(λ − λp)
| Точка | Широта | Долгота | Геомагн. широта | Засветка | Сияние заметно от Kp |
|---|---|---|---|---|---|
| Мурманск | 68.9678 | 33.0992 | 64,87 | сильная | 1,0 |
| Териберка | 69.1609 | 35.1453 | 64,78 | минимальная | 1,1 |
| Мончегорск | 67.9397 | 32.8739 | 63,94 | заметная | 1,5 |
| Ловозеро | 68.0056 | 35.0187 | 63,72 | слабая | 1,6 |
| Кировск | 67.6148 | 33.6727 | 63,53 | заметная | 1,7 |
| Апатиты | 67.5827 | 33.4134 | 63,53 | заметная | 1,7 |
| Кандалакша | 67.1512 | 32.4128 | 63,26 | заметная | 1,8 |
Деталь, которую видно только из этой таблицы: Териберка географически севернее Мурманска, а геомагнитно — южнее. Геомагнитная сетка наклонена, и Териберка лежит восточнее. Её преимущество перед городом не в широте, а в отсутствии засветки.
Оговорка: дипольное приближение — не строгая скорректированная геомагнитная широта (CGM), которой пользуются в авроральной науке. В этом регионе расхождение до полуградуса, то есть до четверти единицы Kp — меньше шага самих данных NOAA.
Прогноз говорит, что сияние возможно, а отметка очевидца — что оно есть. На вкладке «Сейчас» карточка «Очевидцы» показывает, сколько человек за последний час отметили сияние у выбранной точки (и сколько из них — яркое), а ниже — отметки у других точек области. Кнопка «Вижу сияние!» предлагает выбрать «слабое» или «яркое» и отправляет отметку.
Отметка анонимна: на сервер уходят только точка и сила сияния — без текста, фото и координат; адрес не хранится (см. worker/README.md), отметки живут сутки. Отметить можно, только когда у точки темно, и не чаще раза в 30 минут — страница показывает это заранее, сервер проверяет сам. Для своего места отметка ставится у ближайшей точки области. Сводка обновляется вместе с остальными данными, не чаще раза в 2 минуты; если сервер уведомлений не настроен, карточки нет.
Под «Очевидцами» — ссылки на камеры, по которым видно, есть ли сияние прямо сейчас, от ближней к дальней: Териберка (прямая трансляция, 84 км от Мурманска), Соданкюля (камера всего неба SGO), Скибутн (UiT), Кируна (IRF), Абиску (Lights over Lapland). Только ссылки, без встраивания снимков: чужие серверы не нагружаются, их условия не нарушаются, а их сбой не ломает страницу. Расстояния — в выбранных единицах, подписи — на языке страницы. Адреса проверены 26.09.2026 (js/webcams.js).
Кроме семи точек области можно добавить до пяти своих мест — например, озеро или сопку, куда вы ездите смотреть сияние. Добавляются пунктом «+ Добавить своё место…» в выборе точки, кнопкой «Добавить своё место на карте» (нажать на схему в нужном месте) или в разделе «Мои места» на вкладке «Настройки». Координаты вводятся вручную (запятая или точка; обе сразу можно вставить в поле широты), берутся с карты или кнопкой «Где я сейчас».
Для своего места считается всё то же, что для городов: облачность (оно входит в общий запрос по всем точкам), окно наблюдения, OVATION, Луна, вердикт. Пороги Kp — по геомагнитной широте, посчитанной по той же формуле, что у семи точек (geomagneticLatitude в core.js воспроизводит их значения до сотой). Засветка и дорога неизвестны — они не показываются; расстояние — от Мурманска по прямой. Принимаются места на севере: широта 60–72°, долгота 20–50° в. д. — для других широт пороги Kp не подходят.
Места хранятся только в браузере (aurora.places) и на сервер не уходят. Сервер уведомлений знает только семь точек, поэтому для своего места подписка оформляется на ближайшую из них — это сказано в подсказке. Испорченная запись в хранилище не ломает страницу: негодные места просто пропускаются.
Kp. Пороги занижены относительно привычных: вся область лежит практически под авроральным овалом, и сияние здесь возможно уже при Kp 2, тогда как в средней полосе нужен Kp 5–6.
Экваториальная граница овала опускается примерно на 2° геомагнитной широты на каждую единицу Kp, то есть овал оказывается над головой при Kp ≈ (67° − φm) / 2. Для Мурманска это ≈ 1,1, и пороги 1 / 2 / 3, подобранные под него, уже это отражают. Поэтому шкала не считается заново для каждой точки, а якорится на Мурманск и сдвигается:
сдвиг = (φm Мурманска − φm точки) / 2
порог = порог Мурманска + сдвиг
| Kp относительно порогов точки | Балл |
|---|---|
| ≥ верхнего | 3 |
| ≥ среднего | 2 |
| ≥ нижнего | 1 |
| ниже | 0 |
Практический смысл: при типичном Kp 2,67 Мурманск получает балл 2, а Кандалакша — 1. Разница почти в целую единицу Kp между крайними точками соответствует 200 км по меридиану.
Засветка в расчёт не входит намеренно: это не прогнозируемая величина, а свойство места, и смешивать её с погодой в одной формуле значило бы выдавать за прогноз то, что прогнозом не является. Она появляется в списке факторов и в пояснении к вердикту — например, для Мурманска советом отъехать на 15–20 км от огней.
Облачность. Сияние светится на высоте 100–300 км, выше любых облаков, поэтому важна только прозрачность слоя:
| Ярус | Высота | Типичные облака | Вес |
|---|---|---|---|
| Нижний | 0–2 км | Stratus, stratocumulus | 1,0 |
| Средний | 2–7 км | Altostratus, altocumulus | 0,8 |
| Верхний | 7–12 км | Cirrus, cirrostratus | 0,35 |
Ярусы сводятся в одно число по модели случайного перекрытия:
итог = 1 − (1 − low) · (1 − 0,8·mid) · (1 − 0,35·high)
Простое сложение процентов дважды учитывает перекрытие слоёв. Сравнение на 9261 сочетании с шагом 5 % показало, что сумма упирается в потолок 100 % на 57 % пространства значений и в 19 % сочетаний объявляет небо закрытым там, где модель перекрытия видит просветы. На сплошных ярусах обе формулы совпадают тождественно.
Пороги балла: ≤ 25 % — ясно (3), ≤ 50 % — переменная облачность (2), ≤ 75 % — просветы редки (1), выше — небо закрыто (0).
Луна в расчёт уровня не входит — как и засветка. Полная Луна над горизонтом заметно глушит слабое сияние, но это влияет на то, что именно человек увидит, а не на то, есть ли сияние. Луна показывается фактором в вердикте («Луна: 92%, над горизонтом»), строкой в окне наблюдения («Луна 100%, над горизонтом 19:50–23:57», «зайдёт в 03:14») и среди факторов на вкладке «Куда ехать». Пояснение «яркая Луна, слабое сияние выцветет, смотрите на север, спиной к Луне» добавляется только когда Луна действительно мешает и смотреть на небо имеет смысл.
Помеха зависит от освещённости диска и высоты: низкая Луна светит в основном вдоль горизонта и небо над головой почти не засвечивает, поэтому вклад растёт до 25° над горизонтом. Считается локально, без запросов, как высота Солнца; общий код лежит в core.js, так что сервер уведомлений может использовать те же функции.
Положение Луны — усечённая теория Меёса («Астрономические алгоритмы», гл. 47). Точность проверена по независимому источнику, астрономическому API Морской обсерватории США (данные лежат в tools/fixtures/usno-moon-2026.json, тест — tools/moon.test.mjs):
| Что сверялось | Расхождение |
|---|---|
| 50 фаз Луны за 2026 год | в среднем 1,6 мин, наибольшее 3,1 мин |
| 38 восходов и заходов в Мурманске и Кандалакше | наибольшее 1,2 мин |
| Освещённость диска | до 1–2 процентных пунктов |
| Полярные случаи: Луна не заходит (21 декабря), не восходит (11 февраля), видна 17 минут (5 июня) | совпадают |
Один нюанс из живой проверки: осенью и зимой Луна на этой широте часто вообще не поднимается над горизонтом (максимальная высота = 90° − широта + склонение, а у Мурманска это около 21°), и это верно, а не ошибка: 21 сентября 2026 года по данным обсерватории Луна «всё время под горизонтом», как и в расчёте.
Итог — произведение баллов: ≥ 6 высокий, ≥ 2 средний, иначе низкий.
Высота Солнца считается локально для координат выбранной точки, без запросов к API. С мая по июль здесь полярный день, и при любом Kp и чистом небе сияние не видно, поэтому светлое небо принудительно опускает вердикт до низкого.
Kp, прогноз Kp, солнечный ветер, OVATION и прогноз на 27 дней страница берёт сначала у сервера уведомлений (/noaa/…, см. worker/README.md): он отдаёт те же файлы в компактном виде — за обновление приходит около 60 КБ вместо 2 МБ, что заметно на мобильном интернете, — и выручает, если сеть не пускает к NOAA. Если не отвечает сервер, запрос уходит к NOAA напрямую, как раньше.
Облачность и погоду сайт берёт у Open-Meteo напрямую. Если прямой запрос не проходит — сеть или VPN не пускает к api.open-meteo.com, адрес выбрал суточный лимит Open-Meteo, — тот же запрос повторяется через сервер уведомлений (/meteo, см. worker/README.md), и до конца сеанса запросы к Open-Meteo сразу идут через него. Если Open-Meteo не отвечает и серверу, сервер берёт прогноз у резервной модели MET Norway — в карточке облачности тогда так и написано: «Модель прогноза: MET Norway». Не помог и сервер — в карточке остаётся исходная причина.
Второе мнение об облаках. После того как карточка облачности показана, страница спрашивает у сервера общую облачность модели MET Norway (/metno/cloud) и сравнивает её с ICON-EU. Модели согласны, значит под карточкой короткая строка об этом. Расходятся на 40 п.п. и больше, значит жёлтая строка «прогноз облаков сейчас ненадёжен» и отдельная строка в «Подробнее» у вердикта. Сам уровень от второго мнения не меняется: уведомления сервер считает по ICON-EU, и сайт с ними должен совпадать.
Kp описывает прошедшие три часа, поэтому о начинающейся суббуре он сообщает с опозданием. Спутники NOAA в точке L1 (1,5 млн км к Солнцу) видят солнечный ветер за 30–90 минут до того, как он дойдёт до Земли. Главное для сияния — Bz, север-юг магнитного поля ветра: когда он устойчиво южный (отрицательный), энергия ветра проходит в магнитосферу.
| Оценка | Условие |
|---|---|
| сильный южный | Bz в среднем ≤ −10 нТл за 15 минут |
| устойчиво южный | Bz в среднем ≤ −5 нТл за 20 минут |
| слабо южный | сейчас южный, но слабо или недолго |
| северный | Bz ≥ 0 |
Текущий Bz — среднее за 5 минут: поминутные отсчёты заметно дрожат. Время в пути до Земли считается по скорости ветра (1,5 млн км / скорость). Данные старше получаса за «сейчас» не выдаются — спутники иногда замолкают.
Уровень вердикта от солнечного ветра не меняется: это прогноз на час вперёд, а не текущее состояние. Но если шанс сейчас не высокий, небо открыто и темно, а Bz южный, к пояснению добавляется «солнечный ветер обещает рост активности в ближайший час». Расчёт — solarWindSummary() в core.js, общий с сервером на случай будущих ранних уведомлений.
Источники: json/rtsw/rtsw_mag_1m.json (сутки поминутных данных, около 90 КБ в сжатом виде; берётся основной поток active, а если основной спутник молчит больше получаса — самый свежий из остальных, с пометкой в карточке; ряды разных спутников не смешиваются) и products/summary/solar-wind-speed.json. Прежние адреса products/solar-wind/*.json NOAA убрала — отвечают 404.
Приходит тем же запросом к Open-Meteo, что и облачность (модель ICON-EU), и хранится вместе с ней — отдельного запроса нет. Главное условие выбирается по приоритету: туман (коды ВМО 45/48 или видимость меньше 1 км) → снег → осадки (дождь, морось, гроза) → сильный ветер (порывы от 15 м/с) → «осадков нет».
Туман облачность не показывает: модель видит ясное небо, а над головой молоко. Поэтому при тумане в вердикт добавляются фактор «Туман» и пояснение; уровень шанса не меняется. Единицы следуют настройкам: при милях ветер — в милях в час, видимость — в милях; температура — °C или °F.
Для тех, кто выбирает даты поездки. NOAA раз в неделю (по понедельникам) публикует таблицу text/27-day-outlook.txt: на каждые сутки UTC — наибольший ожидаемый Kp. Прогноз строится по вращению Солнца: области, давшие бурю, через 27 суток часто дают её снова. Точность невысокая, погода неизвестна — это ориентир, а не обещание, и карточка так и говорит.
Каждый день окрашивается по порогам Kp выбранной точки (как вердикт). В местную полночь (21:00 UTC) проверяется, будет ли ночь тёмной, и насколько светит Луна. Лучшие даты — подряд идущие дни с высоким уровнем, тёмной ночью и без яркой Луны (освещённость меньше 70%); яркая Луна не исключает день, если буря на 2 единицы Kp сильнее порога «высокого» — такая видна и так. Показываются до трёх сильнейших отрезков, по порядку дат.
Таблица загружается при открытии вкладки «Куда ехать» и не чаще раза в 6 часов; сохранённая годится 8 дней. Разбор и оценка — parseOutlook27(), outlookDays(), outlookBestRanges() в core.js.
На вкладке «Куда ехать» под прогнозом на 27 дней — как было в последние ночи у выбранной точки: для каждой ночи уровень шанса, наибольший Kp, наименьшая облачность и лучшие часы, а сверху итог («из последних 6 ночей шанс был хотя бы средним в 2 ночи»). Видно, что вы пропустили и как часто здесь бывает шанс.
Оценка задним числом — по тем же правилам, что окно наблюдения (hourLevel): Kp — измеренный NOAA по трёхчасовкам за 7 суток (products/noaa-planetary-k-index.json), облачность — та же модель ICON-EU за прошлые дни (Open-Meteo, past_days=7), высота Солнца — локально. В счёт идут только завершившиеся ночи, целиком попавшие в данные; идущая ночь — это окно наблюдения на «Сейчас». Летом, когда темноты нет, так и написано. Два небольших запроса — только при открытии вкладки, не чаще раза в час, с кэшем на три часа.
Под «Прошлыми ночами» — итог сверки прогноза с фактом. Сервер уведомлений каждый вечер записывает, какой шанс на ночь обещает прогноз для семи точек, а утром сверяет с измеренным Kp NOAA и облачностью ICON-EU за прошедшие часы — по тем же правилам, что окно наблюдения. Карточка показывает, в какой доле случаев уровень совпал, насколько часто прогноз ошибался на одну и на две ступени и что было, когда обещали высокий шанс. Пока сверено меньше пяти ночей, цифр нет — только «статистика копится». Подробности — в worker/README.md.
OVATION Prime считает по солнечному ветру вероятность увидеть сияние прямо над головой — на сетке 1°×1° по всей Земле, с упреждением 30–90 минут. Сияние светится на высоте 100–300 км и видно у северного горизонта за несколько сотен километров, поэтому кроме клетки самой точки берётся максимум в поле зрения: до 5° к северу и ±3° по долготе (на 65–70° с. ш. это около 550 × 250 км). Подпись: от 50% — «яркое сияние в поле зрения», от 30% — «вероятно», от 10% — «возможна слабая дуга у горизонта».
Облаков и светлого неба модель не учитывает — это делает вердикт, и в его уровень OVATION не входит. Файл весит около 140 КБ в сжатом виде, поэтому запрашивается не чаще раза в 15 минут (кнопка «Повторить» — всегда), а в кэш кладутся только числа по семи точкам, не сетка. Наблюдение старше полутора часов прогнозом не считается. Расчёт — ovationSummary() в core.js.
Вердикт относится к текущему моменту, а планировать поездку нужно на ночь, поэтому дашборд отдельно считает лучшее время ближайшей ночи. Новых запросов для этого не нужно — всё уже загружено:
Ночью считается ближайший непрерывный отрезок часов, когда Солнце ниже −6°. Каждому часу присваивается тот же уровень, что и вердикту: произведение баллов за Kp и облачность, с понижением до среднего, если темнота неполная (Солнце выше −12°). Окно — самый длинный непрерывный ряд часов с максимальным уровнем.
Под окном — график всей ночи, по столбцу на час: цветная полоса шанса, столбики облачности (нейтрального цвета — это не оценка, а сколько неба закрыто) и прогнозного Kp, отметка Луны, если она над горизонтом (ярче — полнее), и время. Светлые столбцы — сумерки, рамка — лучшее окно. Нажатие на час (или стрелки на клавиатуре) показывает под графиком его подробности; по умолчанию выбрано начало окна. Видно не только «когда лучше», но и почему именно тогда. Луна берётся в середине часа: если она заходит в 03:14, час 03:00–04:00 считается безлунным.
В полярный день тёмных часов не находится, и карточка честно сообщает, что темноты не будет.
Дашборд запрашивает у Open-Meteo не суммарную облачность, а три яруса по отдельности — и при проверке выяснилось, что этим полям можно верить не у всякой модели.
Исходное наблюдение: при ярусах 6 / 3 / 0 (практически чистое небо) API отдавал суммарную облачность 62 %. Это противоречие, а не округление: при любом допущении о перекрытии слоёв суммарная облачность обязана лежать между максимумом яруса и суммой ярусов.
max(ярусы) ≤ всего ≤ min(100, сумма ярусов)
Проверка двенадцати моделей на 48 часах почасового ряда (17 сентября 2026, точка 68.97 / 33.07):
| Модель | Часов с нарушением неравенства | Расхождение > 30 п.п. | Среднее расхождение |
|---|---|---|---|
best_match | 16 из 48 (33 %) | 23 % часов | 17 п.п. |
metno_seamless | 16 из 48 (33 %) | 23 % часов | 17 п.п. |
icon_eu | 0 | 0 | 2 п.п. |
ecmwf_ifs025 | 12 (25 %) | 0 | 8 п.п. |
gfs_seamless | 1 (2 %) | 0 | 1 п.п. |
Что из этого следует:
best_match для Мурманска — это MET Norway. Ответы best_match и metno_seamless совпали до единицы во всех четырёх полях и на всех 48 часах.icon_eu и gfs_seamless, а ярусы 8 / 13 / 0 разделили только knmi_seamless и dmi_seamless — сборки, которые, судя по совпадению значений до единицы, берут их из общего источника.Поэтому модель указывается явно (models=icon_eu), а не отдаётся на автовыбор. ICON-EU грубее локальной скандинавской модели — сетка 7 км против ~1 км, — но её поля самосогласованы, а для расчёта по ярусам это важнее разрешения.
Название действующей модели выведено в карточке облачности, чтобы подмена источника не прошла незаметно. Модель меняется одним значением CONFIG.weatherModel в app.js.
Страховка. Если оценка по ярусам и суммарная облачность всё же разойдутся больше чем на 30 процентных пунктов, в карточке появится предупреждение «данные об облачности противоречивы», а балл за облачность будет ограничен: высокий при недостоверных данных не ставится.
localStorage. При отказе показываются сохранённые данные приглушённо, с пометкой «данные 12 минут назад» и кнопкой «Повторить». Старше трёх часов не показываются вовсе.try/catch: в приватном режиме обращение к localStorage бросает исключение, при переполнении квоты падает запись. Кэш необязателен — без него дашборд работает как раньше.index.html разметка: вердикт, окно наблюдения, Kp, облачность, прогноз
i18n.js движок переводов: выбор языка, подстановки, множественные числа
lang/ словари интерфейса: ru.js (эталон), en.js, zh.js
styles.css тёмная «полярная» тема, адаптив до 375 px
vendor/ сторонний код без изменений: qrcode.js (MIT) для окна «Поделиться»
splash.js заставка первого визита: сияние на холсте, пропуск, переход к дашборду
map.js схема области для вкладки «Карта» (собрана tools/build-map.mjs из Natural Earth)
core.js расчётное ядро: точки, пороги Kp, облачность по ярусам, высота Солнца, уровень вердикта
app.js точка входа: запуск и регистрация service worker
js/ код приложения по темам: основа, «Сейчас», ночь, «Куда ехать», карта, уведомления,
вкладки и вердикт, «Поделиться», настройки и язык (см. js/README.md)
push.js подписка браузера на уведомления с сервера
config.js настройки развёртывания: адрес сервера уведомлений и открытый ключ
manifest.json манифест PWA
robots.txt для поисковиков: всё открыто, ссылка на карту сайта
sitemap.xml карта сайта: адрес по умолчанию и три языковые версии
sw.js service worker: кэш оболочки приложения, показ push-уведомлений
icons/ иконки 192, 512 и maskable
worker/ сервер уведомлений (Cloudflare Worker), необязательный
tools/ тесты и скрипты проверки: согласие сайта и сервера, клиент push, service worker
Почему расчёт вынесен в core.js. Его используют и страница, и сервер уведомлений. Копия формул на сервере разошлась бы с сайтом при первой же правке, и уведомление «высокий шанс» оказалось бы при открытии приложения «средним». Поэтому файл общий, а тест tools/parity.test.mjs сравнивает вердикт сайта и сервера на ~970 тыс. комбинаций Kp и облачности, для всех точек и на реальной высоте Солнца в течение всего года.
Папка tools/ не нужна странице для работы: это тесты (node --test tools/*.test.mjs) и одноразовые скрипты, которыми проверялся выбор метеомодели. Подробности — в tools/README.md.
Семь точек на схеме области, цвет — шанс на ближайшую ночь (те же данные, что на вкладке «Куда ехать»; открытие любой из двух вкладок загружает их для обеих). Нажатие на точку показывает под картой её строку из списка — окно, облачность, порог Kp, дорогу — и кнопку «Смотреть условия», которая делает её точкой наблюдения и открывает «Сейчас».
Схема — собственная, без библиотек и чужих тайлов: работает офлайн и весит около 12 КБ. Контуры области и озёр взяты из Natural Earth (общественное достояние) и собраны скриптом tools/build-map.mjs в map.js. Рамка — район семи точек, а не вся область: иначе на телефоне точки слиплись бы в пятую часть карты. Сама схема тянется по ширине, а точки — это кнопки поверх неё в CSS-пикселях: их размер не зависит от масштаба, они доступны с клавиатуры и подписаны для скринридера. Подписи Кировска и Апатитов (15 км друг от друга) разведены в разные стороны.
Облака над областью. Семь точек не отвечают на вопрос «а если отъехать на 30 км?», поэтому поверх схемы лежит слой облачности. Над рамкой карты берётся сетка 9 × 10 узлов (шаг около 30 км), и для всех узлов одним запросом к Open-Meteo приходит почасовая облачность по ярусам на сутки вперёд — та же модель ICON-EU и та же модель перекрытия ярусов, что для точек. Между узлами значения плавно смешиваются (билинейно), так что видна картина, а не квадраты; ясные места остаются прозрачными, сплошные облака закрывают схему не полностью, а береговые линии повторены поверх слоя. Ползунок листает часы от текущего на сутки вперёд, под ним — облачность числом у выбранной на карте точки. Слой можно выключить, выбор запоминается.
Сетка грузится только при открытии карты, не чаще раза в час (модель пересчитывается раз в несколько часов), и сохраняется: без сети показываются сохранённые облака с пометкой возраста, прошедшие часы отбрасываются.
При первом открытии за сеанс (новая вкладка или запуск установленного приложения) за шапкой поднимаются и гаснут пять «занавесов» сияния — зелёные, бирюзовые, фиолетовые, — заголовок переливается градиентом, а шапка, вкладки и карточки проявляются волной. Около 2 секунд, только CSS: класс intro на <html> ставит встроенный скрипт в <head> и снимает через 2,6 с.
Анимация ничего не задерживает — данные грузятся и считаются параллельно. Повторно в том же сеансе её нет, а при системной настройке «уменьшить движение» — нет вовсе (проверяется и в скрипте, и в CSS). Хранилище недоступно — страница просто открывается без анимации.
Самый первый раз на устройстве сайт открывается полноэкранной заставкой: звёздное небо, три переливающиеся ленты сияния (зелёная, бирюзовая, фиолетовая, цвета — из темы), название и регион. Около 2,8 с, затем за 0,6 с плавно растворяется в дашборд. Пропустить можно сразу: кнопкой «Пропустить» (она в фокусе, над полосой системных жестов с учётом safe-area), клавишей Esc или нажатием в любом месте; тогда переход — 0,25 с. Свернули вкладку — заставка тоже заканчивается.
aurora.splash в localStorage. При повторных визитах заставки нет вовсе — только лёгкая анимация запуска раз за сеанс (выше). Укороченная версия на 1–1,5 с повторному посетителю ничего не сообщает, а открыть прогноз он хочет сразу — поэтому её нет. В первый визит лёгкая анимация не запускается, чтобы не было двух подряд.<head> до первой отрисовки, заставка — отдельный слой поверх страницы, а запросы к NOAA и Open-Meteo уходят сразу при загрузке, параллельно с анимацией.visibility: hidden), пока заполняется данными, и проявляется одновременно с исчезновением заставки.splash.js в оболочке service worker, так что офлайн заставка тоже работает.Проверено в Chrome (телефон 375×812, DPR 3, и компьютер 1280×800): 60 кадров/с, медиана кадра 16,7 мс; при замедлении CPU в 4 раза медиана та же, дольше 50 мс — 7 кадров из ~165 (в основном при разборе скриптов на старте); CLS 0; первый запрос к данным — через 0,1 с после начала загрузки (0,4 с при замедлении).
Кнопка «Поделиться» в шапке открывает окно со ссылкой на сайт на выбранном языке (?lang=ru|en|zh, по умолчанию — язык страницы) и её QR-кодом. Действия: «Отправить…» (системное меню, где оно есть — на телефонах), «Скопировать ссылку» и «Скачать QR для печати» — PNG по 12 пикселей на модуль, чтобы распечатать для гостей отеля или туристической группы.
QR строит библиотека qrcode-generator (Kazuhiko Arase, MIT), скопированная без изменений в vendor/qrcode.js. Она подгружается при первом открытии окна, а не со страницей, и лежит в оболочке service worker — работает офлайн. Коррекция ошибок уровня M, тихая зона в 4 модуля, белый фон — код читается и в тёмной теме. Сгенерированные коды для всех трёх языков проверены декодером OpenCV: распознаются в точности как нужные ссылки.
Вкладка для туриста, статичный текст на трёх языках, пять разделов:
Советов по одежде в гиде нет намеренно — это проверяет тест.
На вкладке «Настройки» блок «Вид и единицы» (хранится в браузере одной записью aurora.settings; по умолчанию всё как было до появления настроек):
| Настройка | Варианты | Что меняет |
|---|---|---|
| Часовой пояс | Мурманск (МСК, по умолчанию) · моё устройство | все времена на сайте: окно наблюдения, прогноз Kp, восходы и заходы Луны, подпись «Обновлено в …» |
| Формат времени | 24 часа · 12 часов (AM/PM) | те же места |
| Расстояния | километры · мили | «От Мурманска 120 км» на вкладке «Куда ехать»; ветер (м/с или мили в час) и видимость |
| Температура | °C · °F | карточка «Погода на месте» |
| Автообновление | 5 · 10 · 30 минут · выкл. | период опроса NOAA и Open-Meteo и подпись в подвале; при «выкл.» данные обновляются кнопкой «Обновить» |
| Тема | тёмная (по умолчанию) · светлая · как в системе · ночное зрение | цвета всей страницы и цвет строки состояния браузера; выбор применяется до первой отрисовки, без вспышки другой темы |
| Размер текста | обычный · крупный (×1,15) · очень крупный (×1,3) | страница масштабируется целиком |
| Открывать на вкладке | где закрыл (по умолчанию) · «Сейчас» · «Куда ехать» · «Карта» | стартовая вкладка; ссылка с адресом (#tonight) важнее настройки |
| Тихие часы | выкл. · 22–08 · 23–07 · 00–06 | уведомления о сиянии в эти часы не приходят — ни от страницы, ни с сервера; время по выбранному часовому поясу; пробные уведомления приходят всегда |
| О каком шансе сообщать | только высокий (по умолчанию) · средний и высокий | порог уведомлений страницы и сервера |
| Небо скоро откроется | выкл. (по умолчанию) · вкл. | сигнал с сервера о просвете в облаках в ближайшие 3 часа, когда сияние возможно |
О чём сообщать. Блок на вкладке «Настройки»: порог — «только высокий» (по умолчанию) или «средний и высокий» — действует и на уведомления страницы, и на уведомления с сервера; уведомление приходит, когда шанс поднялся до порога или выше прежнего, не чаще раза в 3 часа. «Небо скоро откроется» (выкл. по умолчанию) — сигнал с сервера: сейчас сплошные облака, но сияние возможно, а модель обещает просвет в ближайшие 3 часа; раз за ночь. Подробности — в worker/README.md.
Тихие часы и сервер. Если включены уведомления с сервера, страница сообщает ему окно и часовой пояс (название IANA, например Europe/Moscow), и сервер сам не шлёт в это время. Сигнал не пропадает: пока «высокий» держится, подписчик остаётся подходящим и получит уведомление первым проходом после окончания тихих часов. Пропущенные не расходуют лимит отправок. Уведомления страницы в тихие часы просто пропускаются — переход уже состоялся.
Светлая тема — это переопределение переменных CSS: цвета в коде (TONE) — ссылки на переменные, поэтому перерисовка при смене темы не нужна. Контраст текста и тонов — не ниже 4,5:1 на фоне и на карточке в обеих темах, это проверяет тест.
Ночное зрение — красная тема для наблюдения. Глаза привыкают к темноте 20–30 минут, и белый экран сбивает это за секунду; палочки сетчатки, которыми мы видим в темноте, почти не чувствуют длинноволновый красный. Поэтому всё красное на почти чёрном фоне, без цветного свечения и ореолов, картинки и QR-код перекрашены фильтром, а облака на карте в этой теме тёмные — гасят экран, а не подсвечивают. Уровни шанса различаются яркостью и всегда подписаны словами. Включается одним нажатием кнопкой с глазом в шапке и так же выключается — к той теме, что была до неё. Тест проверяет, что все цвета темы красные и контраст текста не ниже 4,5:1.
Кнопка «Сбросить настройки» возвращает значения по умолчанию. Язык переключается в шапке и отдельной настройкой не дублируется. Расчёт шанса от настроек не зависит: меняются только слова, числа и время на экране. Недопустимое или испорченное значение в хранилище заменяется значением по умолчанию — страница не ломается.
Ниже блока настроек на той же вкладке — уведомления (см. следующий раздел).
Переключатель «Русский · English · 中文» стоит в шапке. Какой язык показать, решается по порядку:
?lang=en, ?lang=zh, ?lang=ru (им удобно делиться: ссылка или QR-код для гостей отеля сразу откроется на нужном языке; выбор запоминается);zh-CN, zh-TW, zh-Hans дают китайский, ru-* — русский;Что переводится: весь интерфейс, названия городов, подсказки и вердикт, тексты ошибок, диагностика уведомлений, уведомления страницы, а с сервером уведомлений — и push-уведомления при закрытом приложении. Расчёт от языка не зависит: уровень шанса при тех же Kp и облачности один и тот же на любом языке (проверяется тестом).
Как принято в языке: десятичная запятая только в русском (4,3, а не 4.3), формы множественного числа берутся из Intl.PluralRules (1 минуту, 2 минуты, 5 минут; 1 minute, 2 minutes; 5分钟), день недели и порядок слов — свои. Время везде московское (Мурманская область живёт по нему, UTC+3), 24-часовое, чтобы совпадало с расписаниями на месте.
Как добавить язык. Скопируйте lang/en.js в lang/<код>.js, переведите значения, подключите файл в index.html, sw.js (оболочка приложения) и добавьте язык в I18N_LANGS в i18n.js. Тест tools/i18n.test.mjs проверит, что ключи и подстановки {имя} совпадают с русскими, что нет пропущенного или лишнего, и что все ключи, которые называет код, существуют.
Оговорка о переводах. Английский и китайский тексты написаны без носителей языка и не вычитаны ими. Смысл и числа проверены тестами, но интонация и устоявшиеся выражения (особенно в китайской версии) стоит показать носителю: правки — только в lang/en.js и lang/zh.js, код трогать не нужно.
Под вердиктом есть кнопка «Сообщить о высоком шансе». Разрешение браузер спрашивает только по её нажатию, после согласия приходит пробное уведомление — сразу видно, что система их пропускает. Повторное нажатие выключает.
Уведомление приходит, когда вердикт выбранной точки переходит в «Высокий», а не на каждом обновлении, пока он держится. Дополнительные правила:
На вкладке «Уведомления» можно проверить, что всё работает. Пошаговая проверка показывает, где именно проблема: поддерживает ли браузер уведомления, выдано ли разрешение сайту, активен ли service worker, включены ли уведомления о высоком шансе и открыто ли приложение как установленное (на iPhone без этого не работает). Кнопка «Отправить пробное» шлёт уведомление сразу, «Через 10 секунд» — с задержкой, чтобы успеть свернуть приложение и проверить главный сценарий: придёт ли уведомление в фоне. Ниже — памятка, что делать, если не пришло, для Chrome и Edge, Windows, macOS, Android и iPhone.
Уведомления показываются через service worker — на Android обычный конструктор new Notification() не работает. Нажатие на уведомление открывает приложение или возвращает фокус уже открытому.
Ограничение. Сам сайт — статические файлы, и закрытая страница проснуться не может: эти уведомления работают, пока приложение открыто — во вкладке, в том числе фоновой, или в установленном окне. На телефоне система обычно приостанавливает свёрнутое приложение, так что там это скорее сигнал, пока экран не погас. Для уведомлений при закрытом приложении нужен сервер — см. следующий раздел. На iPhone уведомления доступны только в приложении, добавленном на экран «Домой».
Если развёрнут сервер уведомлений, на вкладке «Настройки» появляется блок с кнопкой «Включить уведомления». Сервер — Cloudflare Worker на бесплатном тарифе: раз в 5 минут он смотрит Kp (NOAA) и облачность (Open-Meteo) для точек, на которые есть подписчики, считает вердикт тем же кодом, что и сайт, и при переходе в «Высокий» шлёт push через сервис вашего браузера. Уведомление приходит, даже когда приложение закрыто.
Правила те же: при переходе в «Высокий», не чаще раза в 3 часа, ничего по неполным данным, «высокий», который уже идёт, никого не будит. Подписка привязана к выбранной точке и переезжает вместе с выбором в шапке. Пока серверные уведомления включены, страница свои не показывает, чтобы не было двух одинаковых.
Кнопка «Через 20 секунд» проверяет главный сценарий целиком: нажмите её и сразу закройте приложение совсем — уведомление придёт с сервера.
Пульс. Сервер записывает время и итог каждой проверки по расписанию, а вкладка «Настройки» показывает «сервер проверял условия 4 минуты назад». Если проверок не было больше 30 минут, там появится предупреждение, что уведомления могут не прийти, — сломавшийся cron не останется незамеченным.
Приватность. Сервер хранит только адрес подписки браузера, выбранную точку, язык уведомлений и тихие часы с часовым поясом: ни имён, ни почты, ни координат человека. Выключение уведомлений удаляет запись, недействительные подписки удаляются автоматически. Пока в config.js не указан адрес сервера, блок скрыт, а сайт работает как раньше.
Дашборд — PWA: в Chrome и Edge его можно установить с панели адреса, на Android — «Добавить на главный экран», на iOS — «Поделиться» → «На экран «Домой»». Запускается в отдельном окне без адресной строки, с тёмной темой системных панелей.
Ярлыки. Долгое нажатие на значок установленного приложения (или правый клик по нему на компьютере) предлагает три ярлыка: «Куда ехать» (/#tonight), «Карта» (/#map) и «Ночное зрение» (/?theme=night#now). Последний включает красную тему ещё до первой отрисовки и запоминает прежнюю — кнопка с глазом в шапке вернёт её; параметр после этого убирается из адреса, чтобы перезагрузка не включала тему снова.
Service worker кэширует только оболочку приложения — index.html, styles.css, app.js, манифест и иконки — по стратегии cache-first. Запросы к NOAA и Open-Meteo не кэшируются вообще и всегда идут в сеть: их свежесть обеспечивает localStorage со своей отсечкой в три часа и пометкой возраста, а два кэша с разными правилами устаревания давали бы противоречивые показания.
Без сети дашборд открывается из кэша и показывает последние сохранённые данные приглушённо, с подписью вроде «Данные 8 минут назад» на каждой карточке.
Имя кэша версионировано (aurora-v34 и дальше). При изменении файлов оболочки версия поднимается: install перезагружает файлы, минуя HTTP-кэш, activate удаляет предыдущую версию. Плата за cache-first — обновление применяется со следующего открытия приложения, а не в текущем сеансе.
hreflang="x-default"), ?lang=ru|en|zh — отдельные версии. Их связывают теги hreflang и sitemap.xml; canonical указывает на ту версию, по которой открыли страницу (его ставит applyLanguage()).icons/og-image.png 1200×630 — кадр заставки.WebApplication): название, описание, бесплатность, языки, регион.robots.txt открывает сайт целиком, кроме служебных tools/ и worker/.Согласованность всего этого (адреса, размеры картинки, переводы) проверяет tools/seo.test.mjs. Чтобы сайт быстрее попал в выдачу, его стоит добавить в Яндекс Вебмастер и Google Search Console и отправить там sitemap.xml; при изменениях страницы в sitemap.xml обновляется lastmod.
Оба API публичные, без ключей и регистрации.
Оценка ориентировочная.
© 2026 Ilya Minichev. Все права защищены. Репозиторий открыт для просмотра, но использовать, копировать, изменять и распространять код и материалы без письменного разрешения автора нельзя — подробности в LICENSE. Сторонний код (vendor/qrcode.js, MIT) и данные NOAA, Open-Meteo и Natural Earth остаются на условиях своих правообладателей.