Skip to content

Commit

Permalink
Merge pull request #476 from HSLdevcom/DT-6387
Browse files Browse the repository at this point in the history
DT-6387 Vehicles appearing on the screen with delay
  • Loading branch information
sharhio authored Nov 14, 2024
2 parents 8fc9f1e + 71e4b6e commit d1fb81a
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 255 deletions.
60 changes: 19 additions & 41 deletions src/MonitorMapContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,35 @@
import React, { FC, useEffect, useRef, useState } from 'react';
import React, { FC } from 'react';
import cx from 'classnames';
import MonitorMap from './ui/monitorMap';
import { IMapSettings } from './util/Interfaces';
import { changeTopics, startMqtt, stopMqtt } from './util/mqttUtils';
import { useMergeState } from './util/utilityHooks';
import { IDeparture } from './ui/MonitorRow';
interface IProps {
preview?: boolean;
mapSettings: IMapSettings;
modal?: boolean;
updateMap?: (settings: IMapSettings) => void;
topics?: string[];
departures?: any;
departuresForMap?: Array<IDeparture>;
lang: string;
mqttProps?: any;
}
const MonitorMapContainer: FC<IProps> = ({
preview,
mapSettings,
modal,
updateMap,
topics,
departures,
departuresForMap,
lang,
mqttProps,
}) => {
const [state, setState] = useMergeState({
client: undefined,
messages: [],
});
const [started, setStarted] = useState(false);
const clientRef = useRef(null);
const topicRef = useRef(null);

if (state.client) {
clientRef.current = state.client;
if (!started) {
setStarted(true);
} else if (topicRef.current.length === 0) {
// We have new topics and current topics are empty, so client needs to be updated
const settings = {
client: clientRef.current,
oldTopics: [],
options: topics,
};
changeTopics(settings, topicRef);
}
}
useEffect(() => {
if ((topics && topics.length) || (!state.client && !started && topics)) {
startMqtt(topics, setState, clientRef, topicRef);
}
return () => {
stopMqtt(clientRef.current, topicRef.current);
};
}, []);
const isLandscape = true;

const {
messages,
clientRef,
newTopics,
topicRef,
vehicleMarkerState,
setVehicleMarkerState,
} = mqttProps || { messages: [] };
return (
<div
className={cx('monitor-container', {
Expand All @@ -68,12 +44,14 @@ const MonitorMapContainer: FC<IProps> = ({
mapSettings={mapSettings}
modal={modal}
updateMap={updateMap}
messages={state.messages}
messages={messages}
clientRef={clientRef}
newTopics={topics}
newTopics={newTopics}
topicRef={topicRef}
departures={departures}
departuresForMap={departuresForMap}
lang={lang}
vehicleMarkerState={vehicleMarkerState}
setVehicleMarkerState={setVehicleMarkerState}
/>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions src/defaultConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,5 @@ export default {
inUse: false,
},
lineCodeMaxLength: 7, // Maximum length of line code to show in the monitor, values larger than 7 are not supported by horizontal layouts
rtVehicleOffsetSeconds: 120, // How many seconds in the future the real-time vehicle should be shown
};
1 change: 1 addition & 0 deletions src/monitorConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default {
map: {
inUse: false,
},
rtVehicleOffsetSeconds: 120,
},
jyvaskyla: {
fonts: {
Expand Down
112 changes: 11 additions & 101 deletions src/ui/CarouselContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ import { IDeparture } from './MonitorRow';
import MonitorAlertRow from './MonitorAlertRow';
import { getLayout } from '../util/getResources';
import cx from 'classnames';
import uniqBy from 'lodash/uniqBy';
import {
stopTimeAbsoluteDepartureTime,
stoptimeSpecificDepartureId,
} from '../util/monitorUtils';
import { sortAndFilter } from '../util/monitorUtils';
import MonitorAlertRowStatic from './MonitorAlertRowStatic';
import { getCurrentSeconds } from '../time';

interface IProps {
stationDepartures: Array<Array<Array<IDeparture>>>; // First array is for individual cards, next array for the two columns inside each card
Expand All @@ -21,52 +16,17 @@ interface IProps {
preview?: boolean;
closedStopViews: Array<IClosedStop>;
trainsWithTrack?: Array<ITrainData>;
mqttProps: any;
}

const sortAndFilter = (departures, trainsWithTrack) => {
const sortedAndFiltered = uniqBy(
departures.sort(
(stopTimeA, stopTimeB) =>
stopTimeAbsoluteDepartureTime(stopTimeA) -
stopTimeAbsoluteDepartureTime(stopTimeB),
),
departure => stoptimeSpecificDepartureId(departure),
).filter(
departure =>
departure.serviceDay + departure.realtimeDeparture >= getCurrentSeconds(),
);
const sortedAndFilteredWithTrack = trainsWithTrack ? [] : sortedAndFiltered;
if (sortedAndFiltered.length > 0 && trainsWithTrack) {
sortedAndFiltered.forEach(sf => {
const trackDataFound = trainsWithTrack.filter(
tt =>
(tt.lineId === sf.trip.route.shortName ||
tt.trainNumber.toString() === sf.trip.route.shortName) &&
tt.timeInSecs === sf.serviceDay + sf.scheduledDeparture,
);
if (trackDataFound.length === 0) {
sortedAndFilteredWithTrack.push({ ...sf });
} else {
sortedAndFilteredWithTrack.push({
...sf,
stop: {
...sf.stop,
platformCode: trackDataFound[0].track,
},
});
}
});
}
return sortedAndFilteredWithTrack;
};

const CarouselContainer: FC<IProps> = ({
stopDepartures,
stationDepartures,
alerts,
preview = false,
closedStopViews,
trainsWithTrack,
mqttProps,
}) => {
const { cards: views, languages, mapSettings } = useContext(MonitorContext);
const mapLanguage = languages.length === 1 ? languages[0] : 'fi';
Expand Down Expand Up @@ -111,6 +71,12 @@ const CarouselContainer: FC<IProps> = ({

const index = Math.floor(current / 2) % finalViews.length;

// show vehicles that have passed the stop
const departuresForMap = [
...stationDepartures[index][0],
...stopDepartures[index][0],
];

const departures = [
sortAndFilter(
[...stationDepartures[index][0], ...stopDepartures[index][0]],
Expand All @@ -121,63 +87,6 @@ const CarouselContainer: FC<IProps> = ({
trainsWithTrack,
),
];
let initialTopics = [];
if (mapSettings?.showMap) {
// Todo. This is a hacky solution to easiest way of figuring out all the departures.
// Map keeps record of all it's stops, so it has all their departures. This should be done
// more coherent way when there is time.
const allDep = [];

for (let i = 0; i < views.length; i++) {
const element = [
sortAndFilter(
[...stationDepartures[i][0], ...stopDepartures[i][0]],
trainsWithTrack,
),
sortAndFilter(
[...stationDepartures[i][1], ...stopDepartures[i][1]],
trainsWithTrack,
),
];
allDep.push(element);
}

const mapDepartures = allDep
.map(o => o.flatMap(a => a))
.reduce((a, b) => (a.length > b.length ? a : b));
initialTopics = mapDepartures
.filter(t => t.realtime)
.map(dep => {
const feedId = dep.trip.gtfsId.split(':')[0];
const topic = {
feedId: feedId,
route: dep.trip.route?.gtfsId?.split(':')[1],
tripId: dep.trip.gtfsId.split(':')[1],
shortName: dep.trip.route.shortName,
type: 3,
...dep,
};
if (feedId.toLowerCase() === 'hsl') {
const i = dep.stops.findIndex(d => dep.stop.gtfsId === d.gtfsId);
if (i !== dep.stops.length - 1) {
const additionalStop = dep.stops[i + 1];
topic.additionalStop = additionalStop;
}
}
return topic;
});
}
const topics = initialTopics;
initialTopics.forEach(t => {
if (t.additionalStop) {
const additionalTopic = {
...t,
stop: t.additionalStop,
additionalStop: null,
};
topics.push(additionalTopic);
}
});
const lan = languages[language] === 'en' ? 'fi' : languages[language];
// for easy testing of different layouts
const newView = {
Expand Down Expand Up @@ -256,8 +165,9 @@ const CarouselContainer: FC<IProps> = ({
alertRowSpan={alertSpan}
closedStopViews={closedStopViews}
mapSettings={mapSettings}
topics={topics}
mqttProps={mqttProps}
mapLanguage={mapLanguage}
departuresForMap={departuresForMap}
/>
);
};
Expand Down
Loading

0 comments on commit d1fb81a

Please sign in to comment.