import moment from 'moment' import { valueToColorInterpolated, valueToColorThreshold } from '../../../helpers/interpolateColors' import { GribMessage, MeteoConversion } from '../interfaces' import { PRECIPITATION } from './constants' import { fetchBuffer } from '../../../helpers/fetch' import { apiHost } from '../../../consts' export function precipitationColors( encodedValue: number, { reference, binaryScale, decimalScale}: MeteoConversion, isInterpolated = true, ): [number, number, number, number] { const rainMM = (reference + encodedValue * Math.pow(2, binaryScale)) * Math.pow(10, -decimalScale) return isInterpolated ? valueToColorInterpolated(rainMM, PRECIPITATION) : valueToColorThreshold(rainMM, PRECIPITATION) } export function hourPrecipitationColors( encodedValNow: number, convNow: MeteoConversion, encodedValPrev: number, convPrev: MeteoConversion, isInterpolated = true, ): [number, number, number, number] { const nowVal = (convNow.reference + encodedValNow * Math.pow(2, convNow.binaryScale)) * Math.pow(10, -convNow.decimalScale) const prevVal = (convPrev.reference + encodedValPrev * Math.pow(2, convPrev.binaryScale)) * Math.pow(10, -convPrev.decimalScale) const rainMM = nowVal - prevVal return isInterpolated ? valueToColorInterpolated(rainMM, PRECIPITATION) : valueToColorThreshold(rainMM, PRECIPITATION) } export function fetchHourPrecipitationData( customMessage: GribMessage, gribArr: GribMessage[], ): Promise<[GribMessage[], ArrayBuffer[], ArrayBuffer[]]> { const totalPrecipitation = gribArr.find(g => isPrecipitation(g) && g.time.referenceTime === customMessage.time.referenceTime && g.time.forecastTime === customMessage.time.forecastTime ) if (!totalPrecipitation) throw new Error('Not found total precipitation') const { forecastTime } = totalPrecipitation.time const prevForecastTime = moment(forecastTime.replace(/(\d{2})(\d{2})Z/, '$1:$2:00Z')) .subtract(1, 'hours') .utc() .format("YYYY-MM-DDTHHmm")+'Z' const prevTotalPrecipitation = gribArr.find(g => isPrecipitation(g) && g.time.referenceTime === customMessage.time.referenceTime && g.time.forecastTime === prevForecastTime ) const section7now = totalPrecipitation.sections.find(section => section.id === 7) const section7prev = prevTotalPrecipitation?.sections.find(section => section.id === 7) if (!section7now) throw new Error('Didnt found binary section for total precipitation') const nowBinaryOffset = section7now.offset + 5 const nowBinaryLength = section7now.size - 5 const nowFileName = `harmonie_${totalPrecipitation.time.referenceTime}_${totalPrecipitation.time.forecastTime}.grib` // for oldest message there is no more -1h message let prevPromise: Promise | undefined if (prevTotalPrecipitation && section7prev) { const prevBinaryOffset = section7prev.offset + 5 const prevBinaryLength = section7prev.size - 5 const prevFileName = `harmonie_${prevTotalPrecipitation.time.referenceTime}_${prevTotalPrecipitation.time.forecastTime}.grib` prevPromise = fetchBuffer(`${apiHost}/api/grib/binary-chunk/${prevBinaryOffset}/${prevBinaryLength}/${prevFileName}`) } if (!prevPromise) prevPromise = new Promise(resolve => resolve(new Uint8Array(nowBinaryLength).buffer)) return Promise.all([ fetchBuffer(`${apiHost}/api/grib/binary-chunk/${nowBinaryOffset}/${nowBinaryLength}/${nowFileName}`), prevPromise, ]).then(([bufferNow, bufferPrev]) => { const messages = [customMessage, totalPrecipitation, prevTotalPrecipitation ?? totalPrecipitation] const buffers = [bufferNow, bufferNow, bufferPrev] return [messages, buffers, []] }) } export function isPrecipitation(grib: GribMessage): boolean { return grib.meteo.discipline === 0 && grib.meteo.category === 1 && grib.meteo.product === 52 } export function isCalculatedHourPrecipitation(grib: GribMessage): boolean { return grib.meteo.discipline === 0 && grib.meteo.category === 1 && grib.meteo.product === 236 } export function getFakeHourPrecipitation(totalPrecipitation: GribMessage): GribMessage { const modifiedPrecipitation = structuredClone(totalPrecipitation) modifiedPrecipitation.meteo = {...modifiedPrecipitation.meteo, product: 236} modifiedPrecipitation.title = 'meteorology, moisture, hour precipitation rate' return modifiedPrecipitation }