Jak powstał Avia Weather (cz. 3): jak rozszyfrować METAR na ludzki język
10.10.2026 · 3 min czytania
W części 2 aplikacja w końcu pokazała prawdziwe dane. Problem? Wyglądały tak:
EPWA 081200Z 24008KT 9999 BKN020 15/09 Q1018
Ja to jeszcze rozszyfruję, bo na co dzień mam z tym do czynienia w pracy. Jednak zwykły użytkownik / nowy pracownik w branży widzi ciąg przypadkowych znaków. Więc wypadało to przetłumaczyć.
Decyzja: kod ORAZ opis, nie opis ZAMIAST kodu#
Pierwsza pokusa to zamienić BKN020 na „zachmurzenie duże, 2000 ft” i tyle.
Tylko, że to by zabolało kogoś, kto te kody zna lub kogoś, kto chce je zrozumieć. Więc
ustaliłem zasadę:
Dekodery — mały słownik + bezpieczny fallback#
Każdy typ kodu dostał swoją małą funkcję-tłumacza. Wzorzec jest zawsze ten sam: słownik plus zabezpieczenie na nieznany kod.
Przykład — zachmurzenie (src/utils/clouds.ts):
const CLOUD_COVER: Record<string, string> = {
SKC: "bezchmurnie",
CLR: "bezchmurnie",
FEW: "zachmurzenie małe",
SCT: "zachmurzenie umiarkowane",
BKN: "zachmurzenie duże",
OVC: "zachmurzenie całkowite",
};
export function describeCloudCover(code: string): string {
return CLOUD_COVER[code.toUpperCase()] ?? code;
}
Trzy rzeczy, które tu robię świadomie:
Tym samym wzorcem zrobiłem resztę: reguły lotów (VFR, MVFR, IFR, LIFR),
typy prognozy w TAF-ie (BECMG, TEMPO, FROM), a wiatr VRB zamieniam na
„zmienny”. Jeden pomysł, cztery małe pliki, zero kopiuj-wklej logiki.
A skąd mam pewność, że to działa?#
Mógłbym po każdej zmianie ręcznie klikać po aplikacji i sprawdzać. Mógłbym — ale jestem leniwy w dobrym sensie. Napisałem testy w Vitest.
import { describe, it, expect } from "vitest";
import { describeCloudCover } from "./clouds";
describe("describeCloudCover", () => {
it("tłumaczy znany kod", () => {
expect(describeCloudCover("BKN")).toBe("zachmurzenie duże");
});
it("działa niezależnie od wielkości liter", () => {
expect(describeCloudCover("bkn")).toBe("zachmurzenie duże");
});
it("zwraca surowy kod, gdy go nie zna", () => {
expect(describeCloudCover("XYZ")).toBe("XYZ");
});
});
Pilnuję trzech rodzajów przypadków: typowy (znany kod), brzegowy (inna wielkość liter) i awaryjny (nieznany kod → fallback). To właśnie te „dziwne” przypadki najczęściej psują aplikację w praniu.
To tyle, jeśli chodzi o „jak powstał” — od pomysłu, przez dane, po tłumacza. Dalej już tylko kolejne usprawnienia: tryb ciemny, SEO, rebranding na Avia Weather… ale to historie na osobne wpisy.