1+ import { SiriVelocityAggregationPydanticModel } from '@hasadna/open-bus-api-client'
12import { useQuery } from '@tanstack/react-query'
23import { SIRI_API } from 'src/api/apiConfig'
34import dayjs from 'src/dayjs'
@@ -9,31 +10,15 @@ export interface VelocityAggregationBounds {
910 maxLon : number
1011}
1112
13+ const cacheDomain = 'https://docbuvbfdq5r6.cloudfront.net/'
14+
1215export function useVelocityAggregationData (
1316 bounds : VelocityAggregationBounds ,
1417 timestamp : dayjs . Dayjs ,
1518 zoom : number ,
1619) {
1720 const { data, isLoading, error } = useQuery ( {
18- queryFn : async ( ) => {
19- const data =
20- await SIRI_API . velocityAggregationSiriVelocityAggregationSiriVelocityAggregationGet ( {
21- recordedFrom : timestamp . toDate ( ) ,
22- lonMin : bounds . minLon ,
23- lonMax : bounds . maxLon ,
24- latMin : bounds . minLat ,
25- latMax : bounds . maxLat ,
26- roundingPrecision : zoom ,
27- } ) . then ( ( data ) => data . filter ( ( p ) => p . totalSampleCount > 4 ) )
28-
29- if ( data . length === 0 ) {
30- throw new Error (
31- 'No data points with more than 4 samples found in the specified area. Try expanding the area.' ,
32- )
33- }
34-
35- return data
36- } ,
21+ queryFn : queryFn . bind ( null , bounds , timestamp , zoom ) ,
3722 queryKey : [
3823 'velocity_aggregation' ,
3924 bounds . minLon ,
@@ -42,8 +27,66 @@ export function useVelocityAggregationData(
4227 bounds . maxLat ,
4328 zoom ,
4429 timestamp . toString ( ) ,
30+ 'v2' ,
4531 ] ,
4632 } )
4733
4834 return { data, loading : isLoading , error, currZoom : zoom }
4935}
36+
37+ function snakeToCamel ( o : SiriVelocityAggregationPydanticModel ) {
38+ return Object . fromEntries (
39+ Object . entries ( o ) . map ( ( [ k , v ] ) => {
40+ const newKey = k . replace ( / ( _ \w ) / g, ( m ) => m [ 1 ] . toUpperCase ( ) )
41+ return [ newKey , v ]
42+ } ) ,
43+ )
44+ }
45+
46+ async function loadFromCache (
47+ bounds : VelocityAggregationBounds ,
48+ timestamp : dayjs . Dayjs ,
49+ zoom : number ,
50+ ) {
51+ const dataFromCache = await fetch (
52+ `${ cacheDomain } siri_velocity_aggregation/siri_velocity_aggregation?recorded_from=${ encodeURIComponent (
53+ timestamp . toISOString ( ) ,
54+ ) } &lon_min=${ bounds . minLon } &lon_max=${ bounds . maxLon } &lat_min=${ bounds . minLat } &lat_max=${ bounds . maxLat } &rounding_precision=${ zoom } `,
55+ )
56+ . then ( async ( res ) => {
57+ if ( ! res . ok ) {
58+ throw new Error ( 'No cached data found' )
59+ }
60+ const rawResult = ( await res . json ( ) ) as SiriVelocityAggregationPydanticModel [ ]
61+ return rawResult . map ( snakeToCamel )
62+ } )
63+ . catch ( ( ) => null )
64+
65+ return dataFromCache
66+ }
67+
68+ async function queryFn ( bounds : VelocityAggregationBounds , timestamp : dayjs . Dayjs , zoom : number ) {
69+ // only try cached data if date is in the past
70+ if ( timestamp . isBefore ( dayjs ( 'yesterday' ) ) ) {
71+ const cachedData = await loadFromCache ( bounds , timestamp , zoom )
72+ if ( cachedData ) {
73+ return cachedData
74+ }
75+ }
76+ const data = await SIRI_API . velocityAggregationSiriVelocityAggregationSiriVelocityAggregationGet ( {
77+ recordedFrom : timestamp . toDate ( ) ,
78+ lonMin : bounds . minLon ,
79+ lonMax : bounds . maxLon ,
80+ latMin : bounds . minLat ,
81+ latMax : bounds . maxLat ,
82+ roundingPrecision : zoom ,
83+ } ) . then ( ( data ) => data . filter ( ( p ) => p . totalSampleCount > 4 ) )
84+
85+ if ( data . length === 0 ) {
86+ throw new Error (
87+ 'No data points with more than 4 samples found in the specified area. Try expanding the area.' ,
88+ )
89+ }
90+
91+ return data
92+ }
0 commit comments