99 lines
4.5 KiB
TypeScript
99 lines
4.5 KiB
TypeScript
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<ArrayBuffer> | 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
|
|
} |