Skip to content

Commit 59d669a

Browse files
committed
Fix train catapulting & other improvements in the area
1 parent 76dd8a7 commit 59d669a

File tree

4 files changed

+85
-44
lines changed

4 files changed

+85
-44
lines changed

src/core/station.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ export class Station {
2121
#tracks: Track[] = [];
2222
/** trains starting at this Station */
2323
#startingTrains: Map<TrainTemplate, SpawnTrainScheduleStep> = new Map();
24+
/** already spawned trains to avoid multiple spawns */
2425
#alreadySpawnedTrains: Set<TrainTemplate> = new Set();
2526

2627
constructor(name: string, position: Position) {
2728
this.#name = name;
2829
this.#position = position;
2930
}
3031

32+
/** Used in the importer module */
3133
addScheduleInfo(
3234
train: TrainTemplate,
3335
track: Track,
@@ -47,13 +49,15 @@ export class Station {
4749
this.#trainsSchedule.set(train, scheduleStep);
4850
}
4951

52+
/** Used in the importer module */
5053
addStartingTrain(train: TrainTemplate, departureTime: Time, track: Track) {
5154
this.#startingTrains.set(train, new SpawnTrainScheduleStep(train, departureTime, track));
5255
}
5356

5457
step() {
5558
// check if any trains should depart or be destroyed
5659
this.departureTrains();
60+
5761
// check if trains are to be spawned
5862
this.#startingTrains.forEach((schedule: SpawnTrainScheduleStep, train: TrainTemplate) => {
5963
if (
@@ -114,14 +118,27 @@ export class Station {
114118
} else if (anyTrainToWaitFor) {
115119
track.train!.delay.addWaitingDelay(simulation.timeStep);
116120
}
121+
} else if (trainSchedule && trainSchedule.arrivalTime && !trainSchedule.departureTime) {
122+
// no departure time - train ends here
123+
const train = this.departTrain(track, trainSchedule);
124+
console.log(`Train ${train.displayName()} ends at the station: ${this.#name}`);
117125
} else if (trainSchedule) {
118126
// no departure time - train skips the station (departs immediately)
119-
this.departTrain(track, trainSchedule);
127+
const train = this.departTrain(track, trainSchedule);
128+
console.log(`Train ${train.displayName()} skips station ${this.#name}`);
129+
} else {
130+
throw new Error(
131+
`No schedule found for train ${track.train.displayName()} at station ${this.#name}`
132+
);
120133
}
121134
}
122135
});
123136
}
124137

138+
/**
139+
* Returns a list of trains that are late to arrive at the station
140+
* @returns array of late trains
141+
*/
125142
lateTrainsToArrive(): Train[] {
126143
const delayedTrainsTemplates = Array.from(this.#trainsSchedule.entries())
127144
.filter(
@@ -148,12 +165,16 @@ export class Station {
148165
if (trainSchedule.nextStation && trainSchedule.nextRail) {
149166
// Assuming that the train has nextRail if it has nextStation
150167
train.nextStation = trainSchedule.nextStation;
151-
const direction = trainSchedule.nextRail.fromStation === this ? TrainDirection.FromStartToEnd : TrainDirection.FromEndToStart;
152-
train.position = new TrainPositionOnRail(trainSchedule.nextRail!, direction, 0); // Is nextRail already in the schedule?
168+
const direction =
169+
trainSchedule.nextRail.fromStation === this
170+
? TrainDirection.FromStartToEnd
171+
: TrainDirection.FromEndToStart;
172+
train.position = new TrainPositionOnRail(trainSchedule.nextRail!, direction, 0);
153173
} else {
154174
this.destroyTrain(train);
155175
}
156176
trainSchedule.satisfied = true;
177+
return train;
157178
}
158179

159180
spawnTrain(trainTemplate: TrainTemplate, preferredTrack: Track): Train | null {

src/core/train.ts

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export class Train {
3636
}
3737

3838
// TODO - make delay reduction visible by adjusting train speeds to be more accurate
39+
// TODO - fix user delays if not at the station (before it)
3940
// TODO - make train speeds reduce before meeting stations
4041
step() {
4142
if (!this.#isWaiting) {
@@ -47,6 +48,9 @@ export class Train {
4748
}
4849
}
4950

51+
/**
52+
* Train movement logic
53+
*/
5054
move() {
5155
if (this.#position instanceof TrainPositionOnRail) {
5256
// updating position based on velocity and acceleration
@@ -63,30 +67,39 @@ export class Train {
6367
}
6468
}
6569

70+
/** Approaching the next station logic */
6671
handleNextStationArrival() {
6772
if (this.#nextStation) {
6873
if (!(this.#position instanceof TrainPositionOnRail)) return; // safety check
6974
const arrived = (this.#position as TrainPositionOnRail).distance >= this.#position.rail.length();
75+
7076
// checking if the train reached its next station
7177
const nextSchedule = this.#nextStation.trainsSchedule.get(this.trainTemplate);
72-
if (arrived && nextSchedule?.arrivalTime) {
73-
// TODO ^ - idk if it should be like this - depends on TrainPositionOnRail management
74-
const trackAtTheStation = this.#nextStation.assignTrack(this.trainTemplate, nextSchedule.track);
75-
if (trackAtTheStation == null) {
76-
// cannot arrive at the station - track full; waiting
77-
// Z jaką prędkością może czekać pociąg?
78-
this.#isWaiting = true;
79-
this.#delay.addConflictDelay(this.calculateConflictDelay());
80-
81-
return;
82-
} else {
83-
this.#isWaiting = false;
78+
if (arrived) {
79+
if (nextSchedule) {
80+
const trackAtTheStation = this.#nextStation.assignTrack(this.trainTemplate, nextSchedule.track);
81+
82+
if (trackAtTheStation == null) {
83+
// cannot arrive at the station - track full; waiting
84+
// Z jaką prędkością może czekać pociąg?
85+
this.#isWaiting = true;
86+
this.#delay.addConflictDelay(this.calculateConflictDelay());
87+
return;
88+
} else {
89+
this.#isWaiting = false;
90+
this.#position = trackAtTheStation; // TrainPositionOnRail no longer useful
91+
this.#nextStation = null;
92+
93+
// only if this is a real stop
94+
if (nextSchedule.arrivalTime) {
95+
this.stop();
96+
this.#acceleration = AccelerationStatus.Constant;
97+
}
8498

85-
this.#position = trackAtTheStation; // TrainPositionOnRail no longer useful
86-
this.#position.trainArrival(this, nextSchedule.arrivalTime);
87-
this.stop();
88-
this.#nextStation = null;
89-
this.#acceleration = AccelerationStatus.Constant;
99+
this.#position.trainArrival(this, nextSchedule.arrivalTime);
100+
}
101+
} else {
102+
throw new Error("Train schedule missing for the next station");
90103
}
91104
}
92105
} else {
@@ -118,37 +131,25 @@ export class Train {
118131
this.#acceleration = newAccelerationStatus;
119132
}
120133

134+
/**
135+
* Calculates delay due to (track occupancy) conflicts at the next station
136+
* @returns delay time in seconds
137+
*/
121138
calculateConflictDelay(): number {
122139
let conflictDelay: number = 0;
123140
if (this.#nextStation) {
124-
const firstTrackTrain = this.#nextStation.tracks[0].train;
125-
if (firstTrackTrain) {
126-
let firstTrackTrainSchedule = this.#nextStation.trainsSchedule.get(firstTrackTrain.trainTemplate);
127-
if (firstTrackTrainSchedule) {
128-
if (firstTrackTrainSchedule.departureTime) {
141+
const trackNumber = this.#nextStation.trainsSchedule.get(this.trainTemplate)?.track.trackNumber;
142+
const trackTrain = this.#nextStation.tracks.find((t) => t.trackNumber === trackNumber)?.train;
143+
144+
if (trackTrain) {
145+
let trackTrainSchedule = this.#nextStation!.trainsSchedule.get(trackTrain.trainTemplate);
146+
if (trackTrainSchedule) {
147+
if (trackTrainSchedule.departureTime) {
129148
conflictDelay =
130-
firstTrackTrainSchedule.departureTime.toSeconds() - simulation.currentTime.toSeconds();
149+
trackTrainSchedule.departureTime.toSeconds() - simulation.currentTime.toSeconds();
131150
}
132151
}
133152
}
134-
135-
this.#nextStation.tracks.forEach((track) => {
136-
const trackTrain = track.train;
137-
if (trackTrain) {
138-
let trackTrainSchedule = this.#nextStation!.trainsSchedule.get(trackTrain.trainTemplate);
139-
if (trackTrainSchedule) {
140-
if (trackTrainSchedule.departureTime) {
141-
if (
142-
trackTrainSchedule.departureTime.toSeconds() - simulation.currentTime.toSeconds() <
143-
conflictDelay
144-
) {
145-
conflictDelay =
146-
trackTrainSchedule.departureTime.toSeconds() - simulation.currentTime.toSeconds();
147-
}
148-
}
149-
}
150-
}
151-
});
152153
}
153154
return conflictDelay;
154155
}
@@ -169,6 +170,11 @@ export class Train {
169170
return this.trainTemplate.displayName();
170171
}
171172

173+
/**
174+
* Determines if the train should wait longer at the station for other trains with specific priorities
175+
* @param otherTrain train to wait for (or not to wait for)
176+
* @returns boolean indicating whether to wait longer
177+
*/
172178
shouldWaitLonger(otherTrain: Train): boolean {
173179
const timeLeft = this.trainTemplate.type.maxWaitingTime - this.#delay.currentWaitingTimeAtTheStationInSeconds;
174180
if (

src/ui/panel.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ class UiPanel {
9595
}
9696
return a.platformNumber - b.platformNumber;
9797
})
98+
.filter(
99+
// skip printing imaginary tracks except those with scheduled arrival/ departure times (e.g. abroad)
100+
(track) =>
101+
station.nextArrivalForTrack(track, simulation.currentTime) !== null ||
102+
station.nextDepartureForTrack(track, simulation.currentTime) !== null
103+
)
98104
.map(
99105
(track) =>
100106
`<tr><th>${track.platformNumber} (${track.trackNumber})</th><td>${

src/utils/delay.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,12 @@ export class Delay {
7272
get currentWaitingTimeAtTheStationInSeconds(): number {
7373
return simulation.currentTime.toSeconds() - this.#actualTrainArrival.toSeconds();
7474
}
75+
76+
get userDelayInSeconds(): number {
77+
return this.#dExternal;
78+
}
79+
80+
set userDelayInSeconds(delay: number) {
81+
this.#dExternal = delay;
82+
}
7583
}

0 commit comments

Comments
 (0)