Skip to content

Commit

Permalink
Use special handling for LEN (airport) station (#21)
Browse files Browse the repository at this point in the history
- Use special handling for ring route (kehärata) trains to show LEN as destination station if the given station code is earlier on the train time table rows than LEN
- Display airplane icon next to LEN station name on StationTimeTableRow
- Fix issue where Lentoasema name was shown as Lento
- Add tests for LEN station handling in getTrainDestinationStation
  • Loading branch information
viliket authored Sep 15, 2023
1 parent 3310d41 commit 6dc2cac
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 7 deletions.
7 changes: 5 additions & 2 deletions src/components/StationTimeTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
TableCell,
TableRow,
} from '@mui/material';
import { ChevronRight } from 'mdi-material-ui';
import { Airplane, ChevronRight } from 'mdi-material-ui';
import RouterLink from 'next/link';

import {
Expand Down Expand Up @@ -47,7 +47,7 @@ function StationTimeTableRow({
: train.trainType.name + train.trainNumber;
const deptOrDestStation =
timeTableType === TimeTableRowType.Departure
? getTrainDestinationStation(train)
? getTrainDestinationStation(train, stationCode)
: getTrainDepartureStation(train);
const deptOrDestStationName = deptOrDestStation
? getTrainStationName(deptOrDestStation)
Expand Down Expand Up @@ -111,6 +111,9 @@ function StationTimeTableRow({
onClick={handleStationClick}
>
{deptOrDestStationName}
{deptOrDestStation?.shortCode === 'LEN' && (
<Airplane sx={{ position: 'absolute', fontSize: '1.3rem' }} />
)}
</Link>
</TableCell>
<TableCell align="center">
Expand Down
118 changes: 118 additions & 0 deletions src/utils/__tests__/train.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,80 @@ const train: TrainDetailsFragment = {
],
};

/**
* Ring rail (Kehärata) train HKI to HKI via LEN (airport)
*/
const ringRailTrainBase: TrainDetailsFragment = {
...trainBase,
commuterLineid: 'I',
timeTableRows: [
{
...departureTimeTableRowBase,
scheduledTime: '2023-01-25T08:55:00Z',
station: {
name: 'Helsinki',
shortCode: 'HKI',
},
},
{
...arrivalTimeTableRowBase,
scheduledTime: '2023-01-25T09:00:00Z',
station: {
name: 'Pasila',
shortCode: 'PSL',
},
},
{
...departureTimeTableRowBase,
scheduledTime: '2023-01-25T09:05:00Z',
station: {
name: 'Pasila',
shortCode: 'PSL',
},
},
{
...arrivalTimeTableRowBase,
scheduledTime: '2023-01-25T11:00:00Z',
station: {
name: 'Lentoasema',
shortCode: 'LEN',
},
},
{
...departureTimeTableRowBase,
scheduledTime: '2023-01-25T11:05:00Z',
station: {
name: 'Lentoasema',
shortCode: 'LEN',
},
},
{
...arrivalTimeTableRowBase,
scheduledTime: '2023-01-25T11:30:00Z',
station: {
name: 'Pasila',
shortCode: 'PSL',
},
},
{
...departureTimeTableRowBase,
scheduledTime: '2023-01-25T11:35:00Z',
station: {
name: 'Pasila',
shortCode: 'PSL',
},
},
{
...arrivalTimeTableRowBase,
scheduledTime: '2023-01-25T11:40:00Z',
station: {
name: 'Helsinki',
shortCode: 'HKI',
},
},
],
};

describe('getTimeTableRowRealTime', () => {
it('should be the scheduled time of the row when neither actual time or live estimate time is defined', () => {
expect(
Expand Down Expand Up @@ -177,6 +251,50 @@ describe('getTrainDestinationStation', () => {
expect(station).toBeDefined();
expect(station!.name).toBe('Tampere');
});
describe.each(['I', 'P'])('ring rail %s train', (commuterLineid: string) => {
const ringRailTrain = {
...ringRailTrainBase,
commuterLineid: commuterLineid,
};

beforeEach(() => {
jest.useFakeTimers();
});

afterEach(() => {
jest.useRealTimers();
});

it('should be the LEN (airport) station when the given station is earlier than LEN', () => {
jest.setSystemTime(parseISO('2023-01-25T08:55:00Z'));

const destStationAtHki = getTrainDestinationStation(ringRailTrain, 'HKI');
expect(destStationAtHki).toBeDefined();
expect(destStationAtHki!.name).toBe('Lentoasema');

const destStationAtPsl = getTrainDestinationStation(ringRailTrain, 'PSL');
expect(destStationAtPsl).toBeDefined();
expect(destStationAtPsl!.name).toBe('Lentoasema');
});

it('should be the station of the destination time table row when the given station is later than LEN', () => {
// Train is between section PSL - LEN based on current time and train schedule
// So train has already passed PSL (first time)
jest.setSystemTime(parseISO('2023-01-25T10:30:00Z'));

const destStationAtLen = getTrainDestinationStation(ringRailTrain, 'LEN');
expect(destStationAtLen).toBeDefined();
expect(destStationAtLen!.name).toBe('Helsinki');

const destStationAtPsl = getTrainDestinationStation(ringRailTrain, 'PSL');
expect(destStationAtPsl).toBeDefined();
expect(destStationAtPsl!.name).toBe('Helsinki');

const destStationAtHki = getTrainDestinationStation(ringRailTrain, 'HKI');
expect(destStationAtHki).toBeDefined();
expect(destStationAtHki!.name).toBe('Helsinki');
});
});
});

describe('getTrainDepartureStationName', () => {
Expand Down
48 changes: 43 additions & 5 deletions src/utils/train.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { parseISO } from 'date-fns';
import { orderBy } from 'lodash';

import { TrainByStationFragment } from '../graphql/generated/digitraffic';
import {
TimeTableRowType,
TrainByStationFragment,
} from '../graphql/generated/digitraffic';

import getTimeTableRowForStation from './getTimeTableRowForStation';

export function getTimeTableRowRealTime(row: {
scheduledTime: string;
Expand Down Expand Up @@ -30,7 +35,37 @@ export function getTrainDepartureStation(train: TrainByStationFragment) {
return getDepartureTimeTableRow(train)?.station;
}

export function getTrainDestinationStation(train: TrainByStationFragment) {
export function getTrainDestinationStation(
train: TrainByStationFragment,
stationCode?: string
) {
// Special handling for ring route (kehärata) trains:
// Return LEN (airport) as the destination station if
// the given station code is earlier on the train
// time table rows than the airport.
if (
stationCode &&
train.commuterLineid &&
['I', 'P'].includes(train.commuterLineid)
) {
const stationRow = getTimeTableRowForStation(
stationCode,
train,
TimeTableRowType.Departure
);
const airportArrivalRow = getTimeTableRowForStation(
'LEN',
train,
TimeTableRowType.Arrival
);
if (
airportArrivalRow &&
stationRow &&
stationRow.scheduledTime < airportArrivalRow.scheduledTime
) {
return airportArrivalRow.station;
}
}
return getDestinationTimeTableRow(train)?.station;
}

Expand All @@ -39,15 +74,18 @@ export function getTrainDepartureStationName(train: TrainByStationFragment) {
return departureStation ? getTrainStationName(departureStation) : undefined;
}

export function getTrainDestinationStationName(train: TrainByStationFragment) {
const destinationStation = getTrainDestinationStation(train);
export function getTrainDestinationStationName(
train: TrainByStationFragment,
stationCode?: string
) {
const destinationStation = getTrainDestinationStation(train, stationCode);
return destinationStation
? getTrainStationName(destinationStation)
: undefined;
}

export function getTrainStationName(station: { name: string }) {
return station.name.replace('asema', '').trimEnd();
return station.name.replace(' asema', '').trimEnd();
}

export function getWagonNumberFromVehicleId(
Expand Down

0 comments on commit 6dc2cac

Please sign in to comment.