11import type { PilotDelta } from "@sr24/types/vatsim" ;
22import { Feature } from "ol" ;
3- import { LineString } from "ol/geom" ;
3+ import type { Coordinate } from "ol/coordinate" ;
4+ import { LineString , type Point } from "ol/geom" ;
45import { fromLonLat } from "ol/proj" ;
56import Stroke from "ol/style/Stroke" ;
67import Style from "ol/style/Style" ;
78import { fetchTrackPoints } from "@/storage/cache" ;
8- import { trackSource } from "./dataLayers" ;
9-
10- interface Cached {
11- id : string | null ;
12- coords : [ number , number ] ;
13- index : number ;
14- stroke ?: Stroke ;
15- timestamp ?: number ;
16- }
9+ import { pilotMainSource , trackSource } from "./dataLayers" ;
1710
1811const STALE_MS = 60 * 1000 ;
19- const cached : Cached = {
20- id : null ,
21- coords : [ 0 , 0 ] ,
22- index : - 1 ,
23- } ;
12+
13+ let pilotId : string | null = null ;
14+ let lastIndex = 0 ;
15+ let lastCoords : Coordinate = [ 0 , 0 ] ;
16+ let lastStroke : Stroke | undefined ;
17+ let lastTimestamp = 0 ;
18+ let animatedTrackFeature : Feature < LineString > | null = null ;
19+ let pilotFeature : Feature < Point > | null = null ;
2420
2521export async function initTrackFeatures ( id : string | null ) : Promise < void > {
2622 if ( ! id ) return ;
2723 const trackPoints = await fetchTrackPoints ( id . replace ( "pilot_" , "" ) ) ;
2824 const trackFeatures : Feature < LineString > [ ] = [ ] ;
2925
30- for ( cached . index = 0 ; cached . index < trackPoints . length - 1 ; cached . index ++ ) {
31- const start = trackPoints [ cached . index ] ;
32- const end = trackPoints [ cached . index + 1 ] ;
26+ for ( lastIndex = 0 ; lastIndex < trackPoints . length - 1 ; lastIndex ++ ) {
27+ const start = trackPoints [ lastIndex ] ;
28+ const end = trackPoints [ lastIndex + 1 ] ;
3329
3430 const trackFeature = new Feature ( {
3531 geometry : new LineString (
@@ -44,48 +40,63 @@ export async function initTrackFeatures(id: string | null): Promise<void> {
4440 const style = new Style ( { stroke : stroke } ) ;
4541
4642 trackFeature . setStyle ( style ) ;
47- trackFeature . setId ( `track_${ id } _${ cached . index } ` ) ;
43+ trackFeature . setId ( `track_${ id } _${ lastIndex } ` ) ;
4844 trackFeatures . push ( trackFeature ) ;
4945
50- if ( cached . index === trackPoints . length - 2 ) {
51- cached . coords = [ end . longitude , end . latitude ] ;
52- cached . stroke = stroke ;
46+ if ( lastIndex === trackPoints . length - 2 ) {
47+ lastCoords = fromLonLat ( [ end . longitude , end . latitude ] ) ;
48+ lastStroke = stroke ;
49+ animatedTrackFeature = trackFeature ;
5350 }
5451 }
5552
5653 trackSource . clear ( ) ;
5754 trackSource . addFeatures ( trackFeatures ) ;
58- cached . id = id ;
59- cached . timestamp = Date . now ( ) ;
55+
56+ pilotId = id ;
57+ pilotFeature = pilotMainSource . getFeatureById ( id ) as Feature < Point > ;
58+ lastTimestamp = Date . now ( ) ;
6059}
6160
6261export async function updateTrackFeatures ( delta : PilotDelta ) : Promise < void > {
6362 if ( trackSource . getFeatures ( ) . length === 0 ) return ;
6463
65- const pilot = delta . updated . find ( ( p ) => `pilot_${ p . id } ` === cached . id ) ;
66- if ( ! cached . id || ! pilot ) return ;
64+ const pilot = delta . updated . find ( ( p ) => `pilot_${ p . id } ` === pilotId ) ;
65+ if ( ! pilotId || ! pilot ) return ;
6766 if ( pilot . latitude === undefined || pilot . longitude === undefined ) return ;
6867
69- if ( Date . now ( ) - ( cached . timestamp || 0 ) > STALE_MS ) {
70- await initTrackFeatures ( cached . id ) ;
68+ if ( Date . now ( ) - ( lastTimestamp || 0 ) > STALE_MS ) {
69+ await initTrackFeatures ( pilotId ) ;
7170 return ;
7271 }
7372
73+ if ( animatedTrackFeature ) {
74+ const geom = animatedTrackFeature . getGeometry ( ) as LineString ;
75+ const coords = geom . getCoordinates ( ) ;
76+ coords [ 1 ] = lastCoords ;
77+ geom . setCoordinates ( coords ) ;
78+ animatedTrackFeature . setGeometry ( geom ) ;
79+ }
80+
7481 const trackFeature = new Feature ( {
75- geometry : new LineString ( [ cached . coords , [ pilot . longitude , pilot . latitude ] ] . map ( ( coord ) => fromLonLat ( coord ) ) ) ,
82+ geometry : new LineString ( [ lastCoords , fromLonLat ( [ pilot . longitude , pilot . latitude ] ) ] ) ,
7683 type : "track" ,
7784 } ) ;
7885
7986 const stroke =
80- pilot . altitude_agl !== undefined && pilot . altitude_ms !== undefined ? getTrackSegmentColor ( pilot . altitude_agl , pilot . altitude_ms ) : cached . stroke ;
87+ pilot . altitude_agl !== undefined && pilot . altitude_ms !== undefined ? getTrackSegmentColor ( pilot . altitude_agl , pilot . altitude_ms ) : lastStroke ;
8188 const style = new Style ( { stroke : stroke } ) ;
8289
8390 trackFeature . setStyle ( style ) ;
84- trackFeature . setId ( `track_${ pilot . id } _${ ++ cached . index } ` ) ;
91+ trackFeature . setId ( `track_${ pilot . id } _${ ++ lastIndex } ` ) ;
8592
8693 trackSource . addFeature ( trackFeature ) ;
8794
88- cached . coords = [ pilot . longitude , pilot . latitude ] ;
95+ lastCoords = fromLonLat ( [ pilot . longitude , pilot . latitude ] ) ;
96+ lastStroke = stroke ;
97+ pilotFeature = pilotMainSource . getFeatureById ( `pilot_${ pilot . id } ` ) as Feature < Point > ;
98+ lastTimestamp = Date . now ( ) ;
99+ animatedTrackFeature = trackFeature ;
89100}
90101
91102function getTrackSegmentColor ( altitude_agl : number , altitude_ms : number ) : Stroke {
@@ -129,3 +140,16 @@ function getTrackSegmentColor(altitude_agl: number, altitude_ms: number): Stroke
129140 width : 3 ,
130141 } ) ;
131142}
143+
144+ export function animateTrackFeatures ( ) : void {
145+ if ( ! animatedTrackFeature || ! pilotFeature || trackSource . getFeatures ( ) . length === 0 ) return ;
146+
147+ const pilotCoords = pilotFeature . getGeometry ( ) ?. getCoordinates ( ) ;
148+ if ( ! pilotCoords ) return ;
149+
150+ const geom = animatedTrackFeature . getGeometry ( ) as LineString ;
151+ const coords = geom . getCoordinates ( ) ;
152+ coords [ 1 ] = pilotCoords ;
153+ geom . setCoordinates ( coords ) ;
154+ animatedTrackFeature . setGeometry ( geom ) ;
155+ }
0 commit comments