From df9a893026d5be21591cbb37d2d475e3f404a459 Mon Sep 17 00:00:00 2001 From: Alexander Harding Date: Sun, 5 Jan 2025 18:31:55 -0600 Subject: [PATCH] Fix pressure bug, add pressure altitudes, default to normalized, remove interpolated (#162) --- src/features/rap/Table.tsx | 4 +- src/features/rap/extra/settings/Settings.tsx | 2 +- .../rap/extra/settings/settingEnums.ts | 2 +- src/features/user/locationHash.ts | 2 +- src/features/user/storage.ts | 4 +- src/locales/de.json | 2 +- src/locales/en.json | 2 +- src/locales/es.json | 2 +- src/locales/fr.json | 2 +- src/locales/nl.json | 2 +- src/services/openMeteo.ts | 85 ++++--------------- 11 files changed, 28 insertions(+), 81 deletions(-) diff --git a/src/features/rap/Table.tsx b/src/features/rap/Table.tsx index a4336d8..cf86820 100644 --- a/src/features/rap/Table.tsx +++ b/src/features/rap/Table.tsx @@ -93,7 +93,7 @@ export default function Table({ ); switch (altitudeLevels) { - case AltitudeLevels.Default: + case AltitudeLevels.Raw: return filteredPressures; case AltitudeLevels.Normalized: return NORMALIZED_PRESSURE_MB.map((pressure) => @@ -103,7 +103,7 @@ export default function Table({ } switch (altitudeLevels) { - case AltitudeLevels.Default: + case AltitudeLevels.Raw: return windsAloftHour.altitudes .slice(0, rows) .filter((datum) => !hiddenAltitude(datum)); diff --git a/src/features/rap/extra/settings/Settings.tsx b/src/features/rap/extra/settings/Settings.tsx index d54ada3..71b1485 100644 --- a/src/features/rap/extra/settings/Settings.tsx +++ b/src/features/rap/extra/settings/Settings.tsx @@ -77,7 +77,7 @@ export default function Settings() { dispatch(setAltitudeLevels(value))} /> diff --git a/src/features/rap/extra/settings/settingEnums.ts b/src/features/rap/extra/settings/settingEnums.ts index afa2b52..c3025ba 100644 --- a/src/features/rap/extra/settings/settingEnums.ts +++ b/src/features/rap/extra/settings/settingEnums.ts @@ -5,8 +5,8 @@ export enum AltitudeType { } export enum AltitudeLevels { - Default = "Default", Normalized = "Normalized", + Raw = "Raw", } // CSS scroll-snap-stop diff --git a/src/features/user/locationHash.ts b/src/features/user/locationHash.ts index 9228602..95f1586 100644 --- a/src/features/user/locationHash.ts +++ b/src/features/user/locationHash.ts @@ -43,7 +43,7 @@ export function getAltitudeLevels() { const value = locationHashMap.get( ALTITUDE_LEVELS_STORAGE_KEY, ) as AltitudeLevels; - if (value !== AltitudeLevels.Default && value !== AltitudeLevels.Normalized) + if (value !== AltitudeLevels.Raw && value !== AltitudeLevels.Normalized) return undefined; return value; } diff --git a/src/features/user/storage.ts b/src/features/user/storage.ts index fd7e5ee..ce3716e 100644 --- a/src/features/user/storage.ts +++ b/src/features/user/storage.ts @@ -141,10 +141,10 @@ export function getAltitudeLevels(): AltitudeLevels { if ( typeof savedValue !== "string" || - (savedValue !== AltitudeLevels.Default && + (savedValue !== AltitudeLevels.Raw && savedValue !== AltitudeLevels.Normalized) ) - return AltitudeLevels.Default; + return AltitudeLevels.Normalized; return savedValue; } diff --git a/src/locales/de.json b/src/locales/de.json index 51f5dcf..ad77897 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -30,7 +30,7 @@ "Hush G-AIRMETs": "G-AIRMETs stummschalten", "Hush G-Airmets tip": "Wenn aktiviert, lösen neue G-AIRMETs keinen Hinweis für ungelesene Benachrichtigungen aus und werden am Ende der Liste der Benachrichtigungen angezeigt. Dies kann nützlich sein, wenn Sie G-AIRMETs als zu laut empfinden. [Nur USA]", "Localization in progress": "Die Lokalisierung läuft. Um zu helfen, senden Sie bitte eine E-Mail an hello@ppg.report", - "Default": "Standard", + "Raw": "Roh", "Normalized": "Normalisiert", "Advanced features": "Erweiterte Funktionen", "Advanced features tip": "EXPERIMENTELL. Aktuelle Funktionen umfassen: Feedback willkommen - hello@ppg.report", diff --git a/src/locales/en.json b/src/locales/en.json index 3d1a358..aef718e 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -30,7 +30,7 @@ "Hush G-AIRMETs": "Hush G-AIRMETs", "Hush G-Airmets tip": "If turned on, new G-AIRMETs will not trigger the unread alert notifications banner, and they will be pushed to the bottom of the alerts list. This can be useful if you find G-AIRMETs too noisy. [US-only]", "Localization in progress": "Localization is in progress. To help, please email hello@ppg.report", - "Default": "Default", + "Raw": "Raw", "Normalized": "Normalized", "Advanced features": "Advanced features", "Advanced features tip": "EXPERIMENTAL. Current features include: Feedback welcome — hello@ppg.report", diff --git a/src/locales/es.json b/src/locales/es.json index 42b31bb..666dc8b 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -30,7 +30,7 @@ "Hush G-AIRMETs": "Silenciar G-AIRMETs", "Hush G-Airmets tip": "Si está activado, los nuevos G-AIRMETs no activarán el banner de notificaciones de alertas no leídas y se mostrarán al final de la lista de alertas. Esto puede ser útil si encuentras los G-AIRMETs demasiado ruidosos. [Solo EE. UU.]", "Localization in progress": "La localización está en curso. Para ayudar, envía un correo electrónico a hello@ppg.report", - "Default": "Predeterminado", + "Raw": "Crudo", "Normalized": "Normalizado", "Advanced features": "Funciones avanzadas", "Advanced features tip": "EXPERIMENTAL. Las características actuales incluyen: Comentarios bienvenidos - hello@ppg.report", diff --git a/src/locales/fr.json b/src/locales/fr.json index 2dcc9cc..d0c09da 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -30,7 +30,7 @@ "Hush G-AIRMETs": "Réduire les G-AIRMETs", "Hush G-Airmets tip": "Si activée, les nouveaux G-AIRMETs ne déclencheront pas la bannière de notifications des alertes non lues, et ils seront poussés en bas de la liste des alertes. Ceci peut être utile si vous trouvez les G-AIRMETs trop bruyants. [Uniquement aux États-Unis]", "Localization in progress": "La localisation est en cours. Pour aider, veuillez envoyer un e-mail à hello@ppg.report", - "Default": "Par défaut", + "Raw": "Brut", "Normalized": "Normalisé", "Advanced features": "Fonctionnalités avancées", "Advanced features tip": "EXPÉRIMENTAL. Les fonctionnalités actuelles comprennent : Vos commentaires sont les bienvenus - hello@ppg.report", diff --git a/src/locales/nl.json b/src/locales/nl.json index d4ce2fc..3354a8b 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -30,7 +30,7 @@ "Hush G-AIRMETs": "Geluidsdemping G-AIRMET's", "Hush G-Airmets tip": "Als dit is ingeschakeld, zullen nieuwe G-AIRMET's de meldingsbanner voor ongelezen meldingen niet activeren en worden ze onderaan de lijst met meldingen weergegeven. Dit kan handig zijn als je de G-AIRMET's te storend vindt. [Alleen in de VS]", "Localization in progress": "Lokalisatie is in uitvoering. Stuur alstublieft een e-mail naar hello@ppg.report om te helpen.", - "Default": "Standaard", + "Raw": "Ruw", "Normalized": "Gestandaardiseerd", "Advanced features": "Geavanceerde functies", "Advanced features tip": "EXPERIMENTEEL. Huidige functies omvatten: Feedback is welkom - hello@ppg.report", diff --git a/src/services/openMeteo.ts b/src/services/openMeteo.ts index dcef612..513f9ae 100644 --- a/src/services/openMeteo.ts +++ b/src/services/openMeteo.ts @@ -1,9 +1,5 @@ import axios from "axios"; -import { WindsAloftAltitude, WindsAloftReport } from "../models/WindsAloft"; -import { - convertToInterpolatorWithHeight, - interpolateWindVectors, -} from "../helpers/interpolate"; +import { WindsAloftReport } from "../models/WindsAloft"; import { notEmpty } from "../helpers/array"; import zipObject from "lodash/zipObject"; import * as velitherm from "velitherm"; @@ -15,7 +11,8 @@ const FORECAST_DAYS_WINDS_ALOFT = 2; * in hPa */ const PRESSURE_ALTITUDES = [ - 1000, 975, 950, 925, 900, 850, 800, 700, 600, 500, 400, 300, 250, + 1000, 975, 950, 925, 900, 875, 850, 825, 800, 775, 750, 725, 700, 650, 600, + 550, 500, 450, 400, 300, 250, ] as const; const PRESSURE_ALTITUDE_METRICS = [ @@ -118,11 +115,12 @@ export async function getWindsAloft( windsAloft: WindsAloftReport; elevationInM: number; }> { - const aloft = await getOpenMeteoWindsAloft(latitude, longitude); + const response = await getOpenMeteoWindsAloft(latitude, longitude); + const windsAloft = convertOpenMeteoToWindsAloft(response); return { - windsAloft: interpolate(convertOpenMeteoToWindsAloft(aloft)), - elevationInM: aloft.elevation, + windsAloft, + elevationInM: response.elevation, }; } @@ -146,62 +144,6 @@ function convertOpenMeteoToWeather( }; } -function interpolate(report: WindsAloftReport): WindsAloftReport { - const lowestAltitudeMsl = - (report.elevationInM ?? 0) + Math.max(...AGL_ALTITUDES); - - return { - ...report, - hours: report.hours.map((hour) => ({ - ...hour, - altitudes: (() => { - const ditheredAltitudes: WindsAloftAltitude[] = []; - - for (let i = 0; i < hour.altitudes.length; i++) { - ditheredAltitudes.push(hour.altitudes[i]); - - if (!hour.altitudes[i + 1]) continue; - if (hour.altitudes[i].altitudeInM <= lowestAltitudeMsl) continue; - - const middleAltitude = - (hour.altitudes[i].altitudeInM + - hour.altitudes[i + 1].altitudeInM) / - 2; - - const { height, speed, direction } = interpolateWindVectors( - convertToInterpolatorWithHeight(hour.altitudes[i]), - convertToInterpolatorWithHeight(hour.altitudes[i + 1]), - middleAltitude, - ); - - const temperatureInC = Math.round( - (hour.altitudes[i].temperatureInC + - hour.altitudes[i + 1].temperatureInC) / - 2, - ); - - ditheredAltitudes.push({ - windSpeedInKph: Math.round(speed * 10) / 10, - windDirectionInDeg: Math.round(direction), - altitudeInM: Math.round(height), - temperatureInC, - dewpointInC: Math.round( - (hour.altitudes[i].dewpointInC + - hour.altitudes[i + 1].dewpointInC) / - 2, - ), - pressure: Math.round( - (hour.altitudes[i].pressure + hour.altitudes[i + 1].pressure) / 2, - ), - }); - } - - return ditheredAltitudes; - })(), - })), - }; -} - async function getOpenMeteoWindsAloft( latitude: number, longitude: number, @@ -300,6 +242,7 @@ function convertOpenMeteoToWindsAloft( openMeteoResponse.hourly[`temperature_${agl}m`][index], dewpointInC: velitherm.dewPoint( calculateRelativeHumidity( + openMeteoResponse.elevation, agl, openMeteoResponse.hourly[`surface_pressure`][index], openMeteoResponse.hourly[`temperature_${agl}m`][index], @@ -309,8 +252,11 @@ function convertOpenMeteoToWindsAloft( ), pressure: Math.round( velitherm.pressureFromAltitude( - agl, + openMeteoResponse.elevation + agl, openMeteoResponse.hourly["pressure_msl"][index], + (openMeteoResponse.hourly[`temperature_${agl}m`][index] + + openMeteoResponse.hourly[`temperature_2m`][index]) / + 2, ), ), })), @@ -354,20 +300,21 @@ function generateWeatherParams(): HourlyWeatherParams[] { } function calculateRelativeHumidity( - altitude: number, + elevation: number, + agl: number, basePressure: number, baseTemperature: number, baseRH: number, ): number { // Calculate the pressure at the given altitude const pressure = velitherm.pressureFromAltitude( - altitude, + elevation + agl, basePressure, baseTemperature, ); // Calculate the temperature at the given altitude - const temperature = baseTemperature - altitude * velitherm.gamma; + const temperature = baseTemperature - agl * velitherm.gamma; // Calculate the specific humidity at the given temperature and pressure const specificHumidity = velitherm.specificHumidity(