11import { drawOccupancyZonesTexts } from './drawOccupancyZonesTexts' ;
2- import type { SpaceTimeChartContextType } from '../../../../spaceTimeChart' ;
3- import {
4- TRACK_HEIGHT_CONTAINER ,
5- CANVAS_PADDING ,
6- OCCUPANCY_ZONE_Y_START ,
7- OCCUPANCY_ZONE_HEIGHT ,
8- FONTS ,
9- COLORS ,
10- } from '../../consts' ;
11- import type { OccupancyZone , Track } from '../../types' ;
2+ import { getCrispLineCoordinate , type SpaceTimeChartContextType } from '../../../../spaceTimeChart' ;
3+ import { OCCUPANCY_ZONE_Y_START , OCCUPANCY_ZONE_HEIGHT , FONTS , COLORS } from '../../consts' ;
4+ import type { OccupancyZone } from '../../types' ;
125
136const { SANS } = FONTS ;
147const { REMAINING_TRAINS_BACKGROUND , WHITE_100 , SELECTION_20 } = COLORS ;
158const REMAINING_TRAINS_WIDTH = 70 ;
169const REMAINING_TRAINS_HEIGHT = 24 ;
1710const REMAINING_TEXT_OFFSET = 12 ;
18- const Y_OFFSET_INCREMENT = 4 ;
19- const MAX_ZONES = 9 ;
2011const X_BACKGROUND_PADDING = 4 ;
2112const X_TROUGHTRAIN_BACKGROUND_PADDING = 8 ;
2213const BACKGROUND_HEIGHT = 40 ;
@@ -61,48 +52,50 @@ const drawThroughTrain = (ctx: CanvasRenderingContext2D, x: number, y: number) =
6152 ctx . stroke ( ) ;
6253} ;
6354
64- const drawRemainingTrainsBox = ( {
65- ctx,
66- remainingTrainsNb,
67- xPosition,
68- yPosition,
69- } : {
70- ctx : CanvasRenderingContext2D ;
71- remainingTrainsNb : number ;
72- xPosition : number ;
73- yPosition : number ;
74- } ) => {
75- const textY = yPosition + OCCUPANCY_ZONE_Y_START - REMAINING_TEXT_OFFSET ;
55+ export const drawRemainingTrainsBox = (
56+ ctx : CanvasRenderingContext2D ,
57+ { getTimePixel, getSpacePixel } : SpaceTimeChartContextType ,
58+ {
59+ time,
60+ position,
61+ yOffset,
62+ remainingTrainsNb,
63+ } : {
64+ time : number ;
65+ position : number ;
66+ yOffset : number ;
67+ remainingTrainsNb : number ;
68+ }
69+ ) => {
70+ const x = getTimePixel ( time ) ;
71+ const y = getSpacePixel ( position ) + yOffset ;
72+ const textY = y + OCCUPANCY_ZONE_Y_START - REMAINING_TEXT_OFFSET ;
7673
7774 ctx . fillStyle = REMAINING_TRAINS_BACKGROUND ;
7875 ctx . beginPath ( ) ;
79- ctx . rect ( xPosition , textY , REMAINING_TRAINS_WIDTH , REMAINING_TRAINS_HEIGHT ) ;
76+ ctx . rect ( x - REMAINING_TRAINS_WIDTH / 2 , textY , REMAINING_TRAINS_WIDTH , REMAINING_TRAINS_HEIGHT ) ;
8077 ctx . fill ( ) ;
8178 ctx . stroke ( ) ;
8279 ctx . fillStyle = WHITE_100 ;
8380 ctx . font = SANS ;
8481 ctx . textAlign = 'center' ;
8582 ctx . textBaseline = 'middle' ;
86- ctx . fillText (
87- `+${ remainingTrainsNb } trains` ,
88- xPosition + REMAINING_TRAINS_WIDTH / 2 ,
89- textY + REMAINING_TRAINS_HEIGHT / 2
90- ) ;
83+ ctx . fillText ( `+${ remainingTrainsNb } trains` , x , textY + REMAINING_TRAINS_HEIGHT / 2 ) ;
9184} ;
9285
93- const drawOccupationZone = (
86+ export const drawOccupationZone = (
9487 ctx : CanvasRenderingContext2D ,
9588 stcContext : SpaceTimeChartContextType ,
9689 {
9790 zone,
91+ yOffset,
9892 position,
99- yZone,
100- selectedTrainId,
93+ isSelected,
10194 } : {
10295 zone : OccupancyZone ;
96+ yOffset : number ;
10397 position : number ;
104- yZone : number ;
105- selectedTrainId ?: string ;
98+ isSelected ?: boolean ;
10699 }
107100) => {
108101 const isThroughTrain = zone . arrivalTime === zone . departureTime ;
@@ -114,12 +107,13 @@ const drawOccupationZone = (
114107 ctx . font = '400 10px IBM Plex Mono' ;
115108
116109 const { getTimePixel, getSpacePixel } = stcContext ;
117- const yStart = getSpacePixel ( position ) ;
110+ const yStart = getCrispLineCoordinate ( getSpacePixel ( position ) , BACKGROUND_HEIGHT ) ;
111+ const y = yStart + yOffset ;
118112 const yEnd = getSpacePixel ( position , true ) ;
119113 const arrivalTimePixel = getTimePixel ( zone . arrivalTime ) ;
120114 const departureTimePixel = getTimePixel ( zone . departureTime ) ;
121115
122- if ( selectedTrainId === zone . trainId ) {
116+ if ( isSelected ) {
123117 const extraWidth = isThroughTrain ? X_TROUGHTRAIN_BACKGROUND_PADDING : X_BACKGROUND_PADDING ;
124118 const originTextLength = ctx . measureText ( zone . originStation || '--' ) . width ;
125119 const destinationTextLength = ctx . measureText ( zone . destinationStation || '--' ) . width ;
@@ -128,7 +122,7 @@ const drawOccupationZone = (
128122 ctx . beginPath ( ) ;
129123 ctx . roundRect (
130124 arrivalTimePixel - originTextLength - extraWidth ,
131- yZone - BACKGROUND_HEIGHT / 2 ,
125+ y - BACKGROUND_HEIGHT / 2 ,
132126 departureTimePixel -
133127 arrivalTimePixel +
134128 originTextLength +
@@ -140,12 +134,13 @@ const drawOccupationZone = (
140134 ctx . fill ( ) ;
141135 }
142136
137+ ctx . fillStyle = zone . color ;
143138 if ( isThroughTrain ) {
144- drawThroughTrain ( ctx , arrivalTimePixel , yZone ) ;
139+ drawThroughTrain ( ctx , arrivalTimePixel , y ) ;
145140 } else {
146141 drawDefaultZone ( ctx , {
147142 x : arrivalTimePixel ,
148- y : yZone ,
143+ y,
149144 width : departureTimePixel - arrivalTimePixel ,
150145 } ) ;
151146 }
@@ -156,13 +151,13 @@ const drawOccupationZone = (
156151 ctx . setLineDash ( [ 1 , 4 ] ) ;
157152 if ( zone . arrivalDirection ) {
158153 ctx . beginPath ( ) ;
159- ctx . moveTo ( arrivalTimePixel , yZone ) ;
154+ ctx . moveTo ( arrivalTimePixel , y ) ;
160155 ctx . lineTo ( arrivalTimePixel , zone . arrivalDirection === 'up' ? yStart : yEnd ) ;
161156 ctx . stroke ( ) ;
162157 }
163158 if ( zone . departureDirection ) {
164159 ctx . beginPath ( ) ;
165- ctx . moveTo ( departureTimePixel , yZone ) ;
160+ ctx . moveTo ( departureTimePixel , y ) ;
166161 ctx . lineTo ( departureTimePixel , zone . departureDirection === 'up' ? yStart : yEnd ) ;
167162 ctx . stroke ( ) ;
168163 }
@@ -175,121 +170,7 @@ const drawOccupationZone = (
175170 arrivalTimePixel,
176171 departureTimePixel,
177172 isThroughTrain,
178- selectedTrainId,
179- yPosition : yZone ,
180- } ) ;
181- } ;
182-
183- export const drawOccupancyZones = (
184- ctx : CanvasRenderingContext2D ,
185- stcContext : SpaceTimeChartContextType ,
186- {
187- occupancyZones,
188- tracks,
189- position,
190- selectedTrainId,
191- topPadding = 0 ,
192- } : {
193- occupancyZones : OccupancyZone [ ] ;
194- tracks : Track [ ] ;
195- position : number ;
196- selectedTrainId ?: string ;
197- topPadding ?: number ;
198- }
199- ) => {
200- if ( ! tracks || ! occupancyZones || occupancyZones . length === 0 ) return ;
201-
202- const { getTimePixel, getSpacePixel } = stcContext ;
203- const baseY = getSpacePixel ( position ) + topPadding ;
204-
205- const sortedOccupancyZones = occupancyZones . sort ( ( a , b ) => a . arrivalTime - b . arrivalTime ) ;
206-
207- tracks . forEach ( ( track , index ) => {
208- const trackY = baseY + CANVAS_PADDING + index * TRACK_HEIGHT_CONTAINER ;
209-
210- const filteredOccupancyZones = sortedOccupancyZones . filter ( ( zone ) => zone . trackId === track . id ) ;
211-
212- let primaryArrivalTime = 0 ;
213- let primaryDepartureTime = 0 ;
214- let lastDepartureTime = primaryDepartureTime ;
215- let yPosition = OCCUPANCY_ZONE_Y_START ;
216- let yOffset = Y_OFFSET_INCREMENT ;
217- let zoneCounter = 0 ;
218- let zoneIndex = 0 ;
219-
220- while ( zoneIndex < filteredOccupancyZones . length ) {
221- const zone = filteredOccupancyZones [ zoneIndex ] ;
222- const { arrivalTime, departureTime } = zone ;
223-
224- // * if the zone is not overlapping with any previous one, draw it in the center of the track
225- // * and reset the primary values
226- // *
227- // * if the zone is overlapping with the previous one, draw it below or above the previous one
228- // * depending on the overlapping counter
229- // *
230- // * if the zone is overlapping with the previous one and the counter is higher than the max zones
231- // * draw the remaining trains box
232- // *
233- if ( arrivalTime > lastDepartureTime ) {
234- // reset to initial value if the zone is not overlapping
235- yPosition = OCCUPANCY_ZONE_Y_START ;
236- primaryArrivalTime = arrivalTime ;
237- primaryDepartureTime = departureTime ;
238- lastDepartureTime = departureTime ;
239- yOffset = Y_OFFSET_INCREMENT ;
240- zoneCounter = 1 ;
241-
242- drawOccupationZone ( ctx , stcContext , {
243- zone,
244- position,
245- selectedTrainId,
246- yZone : trackY + yPosition ,
247- } ) ;
248-
249- zoneIndex ++ ;
250-
251- continue ;
252- }
253-
254- if ( zoneCounter < MAX_ZONES ) {
255- // if so and it's an even index, move it to the bottom, if it's an odd index, move it to the top
256- if ( arrivalTime >= primaryArrivalTime ) {
257- if ( zoneCounter % 2 === 0 ) {
258- yPosition -= yOffset ;
259- } else {
260- yPosition += yOffset ;
261- }
262- }
263-
264- // update the last departure time if the current zone is longer
265- if ( departureTime >= lastDepartureTime ) lastDepartureTime = departureTime ;
266-
267- drawOccupationZone ( ctx , stcContext , {
268- zone,
269- position,
270- yZone : trackY + yPosition ,
271- selectedTrainId,
272- } ) ;
273-
274- zoneCounter ++ ;
275- yOffset += Y_OFFSET_INCREMENT ;
276- zoneIndex ++ ;
277-
278- continue ;
279- }
280-
281- const nextIndex = filteredOccupancyZones . findIndex (
282- ( filteredZone , i ) => i > zoneIndex && filteredZone . arrivalTime >= lastDepartureTime
283- ) ;
284-
285- const remainingTrainsNb = nextIndex - zoneIndex ;
286-
287- const xPosition =
288- getTimePixel ( ( primaryArrivalTime + lastDepartureTime ) / 2 ) - REMAINING_TRAINS_WIDTH / 2 ;
289-
290- drawRemainingTrainsBox ( { ctx, remainingTrainsNb, xPosition, yPosition : trackY } ) ;
291-
292- zoneIndex += remainingTrainsNb ;
293- }
173+ yPosition : y ,
174+ isSelected,
294175 } ) ;
295176} ;
0 commit comments