106 lines
4.5 KiB
TypeScript
106 lines
4.5 KiB
TypeScript
import { Accessor, Component, createSignal, Setter, Signal } from 'solid-js'
|
|
|
|
import { CROP_BOUNDS, DrawOptions, GribMessage, MeteoParam } from './interfaces'
|
|
import { fetchGribBinaries } from './fetchGrib'
|
|
import { drawGrib } from './draw/drawGrib'
|
|
|
|
import styles from './harmonie.module.css'
|
|
import { processPromisesInBatches } from '../helpers/progressivePromises'
|
|
|
|
const METEO_PARAMS: [string, MeteoParam][] = [
|
|
['temperature', { discipline: 0, category: 0, product: 0, levelType: -1, levelValue: -1, subType: 'now' }],
|
|
['precipitation', { discipline: 0, category: 1, product: 236, levelType: -1, levelValue: -1, subType: 'now' }],
|
|
['categorical precipitation', { discipline: 0, category: 1, product: 192, levelType: -1, levelValue: -1, subType: 'now' }],
|
|
['wind speed', { discipline: 0, category: 2, product: 1, levelType: -1, levelValue: -1, subType: 'now' }],
|
|
['wind speed gust', { discipline: 0, category: 2, product: 22, levelType: -1, levelValue: -1, subType: 'now' }],
|
|
['wind direction', { discipline: 0, category: 2, product: 192, levelType: -1, levelValue: -1, subType: 'now' }],
|
|
]
|
|
|
|
export const ReferenceTimes: Component<{
|
|
setIsLoading: Setter<boolean>,
|
|
getFileList: Accessor<string[]>,
|
|
getGribList: Accessor<GribMessage[]>,
|
|
options: DrawOptions,
|
|
imgListSignal: Signal<[string, ImageBitmap | undefined][]>,
|
|
setRefDate: Setter<string>,
|
|
onClick: () => void,
|
|
}> = ({
|
|
setIsLoading,
|
|
getFileList,
|
|
getGribList,
|
|
options,
|
|
imgListSignal: [getImgList, setImgList],
|
|
setRefDate,
|
|
onClick,
|
|
}) => {
|
|
const [getActiveDate, setActiveDate] = createSignal('')
|
|
const dateList = (): [string, number][] => {
|
|
const datesStr = getFileList().map(f => f.replace('harmonie_', '').split('_')[0])
|
|
const uniqueDates = [...new Set(datesStr)]
|
|
return uniqueDates.map(dateStr => [
|
|
dateStr,
|
|
datesStr.filter(d => d === dateStr).length
|
|
])
|
|
}
|
|
|
|
function onActiveDate(date: string) {
|
|
onClick()
|
|
const newValue = getActiveDate() === date ? '' : date
|
|
setActiveDate(newValue)
|
|
}
|
|
|
|
async function fetchDrawImgList(refDateStr: string, param: MeteoParam) {
|
|
setIsLoading(true)
|
|
const cropBounds = options.getIsCrop() ? CROP_BOUNDS : undefined
|
|
const contour = options.getIsContour()
|
|
const isInterpolated = options.getIsInterpolated()
|
|
const forecastList = getGribList()
|
|
.filter(g => g.time.referenceTime === refDateStr)
|
|
.filter(g => g.meteo.discipline === param.discipline && g.meteo.category === param.category && g.meteo.product === param.product)
|
|
const emptyImgList: [string, undefined][] = forecastList
|
|
.map((grib): [string, undefined] => [grib.time.forecastTime, undefined])
|
|
.sort((a, b) => a[0] > b[0] ? 1 : -1)
|
|
setImgList(emptyImgList)
|
|
const promiseFnsList = forecastList.map((grib): () => Promise<[string, ImageBitmap]> => async () => {
|
|
const canvas = document.createElement('canvas')
|
|
const [messages, buffers, bitmasks] = await fetchGribBinaries(grib, getGribList())
|
|
drawGrib(canvas, messages, buffers, bitmasks, cropBounds, contour, isInterpolated)
|
|
// just to be sure that draws
|
|
await new Promise(resolve => setTimeout(resolve))
|
|
const img = await createImageBitmap(canvas)
|
|
return [grib.time.forecastTime, img]
|
|
})
|
|
|
|
processPromisesInBatches(
|
|
promiseFnsList,
|
|
([forecastDate, img]) => {
|
|
const udpdatedImgList = [...getImgList()]
|
|
const idx = udpdatedImgList.findIndex(([d]) => forecastDate === d)
|
|
if (idx >= 0) udpdatedImgList[idx][1] = img
|
|
setImgList(udpdatedImgList)
|
|
},
|
|
).finally(() => {
|
|
setRefDate(refDateStr)
|
|
setIsLoading(false)
|
|
})
|
|
}
|
|
|
|
return <ul class={styles.dateList}>
|
|
{ dateList().map(([dateStr, count]) =>
|
|
<li>
|
|
<div onClick={() => onActiveDate(dateStr)}>
|
|
<b>{ dateStr }</b> ({ count })
|
|
</div>
|
|
<ul
|
|
class={styles.controls}
|
|
style={{ display: getActiveDate() === dateStr ? 'block' : 'none'}}
|
|
>
|
|
{ METEO_PARAMS.map(([paramName, param]) =>
|
|
<li onClick={() => fetchDrawImgList(dateStr, param)}>
|
|
{ paramName }
|
|
</li>
|
|
)}
|
|
</ul>
|
|
</li>)}
|
|
</ul>
|
|
} |