Skip to content

Commit

Permalink
fix: round also the delay value on punctuality layers (#1202)
Browse files Browse the repository at this point in the history
* fix: round also the delay value on punctuality layers

* fix: display nothing if no realtime for this vehivle

* fix: make sure arrival time is not bigger than departure time (included delays)

* fix: fix typo
  • Loading branch information
oterral authored Nov 22, 2024
1 parent ac50a82 commit 2a74f82
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 19 deletions.
16 changes: 16 additions & 0 deletions src/layers/TralisLayer/TralisLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
realtimeDelayStyle,
sortByDelay,
} from "mobility-toolbox-js/ol";
import getDelayString from "../../utils/getDelayString";

/**
* Trajserv value: 'Tram', 'Subway / Metro / S-Bahn', 'Train', 'Bus', 'Ferry', 'Cable Car', 'Gondola', 'Funicular', 'Long distance bus', 'Rail',
Expand Down Expand Up @@ -52,6 +53,20 @@ const getRadius = (type, zoom) => {
}
};

const getDelayText = (delayInMs, cancelled) => {
if (cancelled) {
return String.fromCodePoint(0x00d7);
}

// no realtime or realtime is broken
if (delayInMs === null) {
return null;
}

// Same function used by the RouteSchedule component
return getDelayString(delayInMs, true);
};

class TralisLayer extends RealtimeLayer {
constructor(options) {
// You can filter the trains displayed using the following properties:
Expand Down Expand Up @@ -83,6 +98,7 @@ class TralisLayer extends RealtimeLayer {
style: realtimeDelayStyle,
styleOptions: {
getRadius,
getDelayText,
},
sort: sortByDelay,
fullTrajectoryStyle: fullTrajectoryDelayStyle,
Expand Down
42 changes: 23 additions & 19 deletions src/popups/PunctualityPopup/PunctualityPopup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useDispatch, useSelector } from "react-redux";
import Feature from "ol/Feature";
import RouteSchedule from "react-spatial/components/RouteSchedule";
import TralisLayer from "../../layers/TralisLayer";
import getDelayText, { getDelaySecure } from "../../utils/getDelayString";

function PunctualityPopup({ feature, layer }) {
const dispatch = useDispatch();
Expand Down Expand Up @@ -53,28 +54,31 @@ function PunctualityPopup({ feature, layer }) {
<RouteSchedule
trackerLayer={layer}
lineInfos={lineInfos}
getDelayString={(milliseconds, isArrival) => {
let timeInMs = milliseconds;
if (timeInMs < 0) {
timeInMs = 0;
}
const h = Math.floor(timeInMs / 3600000);
const m = (isArrival ? Math.ceil : Math.floor)(
(timeInMs % 3600000) / 60000,
);
getDelayString={getDelayText}
renderArrivalDelay={(delay, stop, getDelayString, getDelayColor) => {
let delayToDisplay = delay;

if (h === 0 && m === 0) {
return "+0m";
}
if (h === 0) {
return `+${m}m`;
// In some edge cases when arrival and departure time are in the
// same minute and delay too, we need to display the departure
// delay instead of the arrival delay to make sure the arrival
// time + ceiled delay is not greater than the departure time +
// floored delay.
// see TRAFWART-1702
if (
getDelaySecure(stop.departureDelay) +
stop.departureTime -
(getDelaySecure(delay) + stop.arrivalTime) <
60000
) {
delayToDisplay = getDelaySecure(stop.departureDelay);
}
return `+${h}h${m}m`;
}}
renderArrivalDelay={(delay, stop, getDelayString, getDelayColor) => {
return (
<span style={{ color: getDelayColor?.(delay, stop) || "inherit" }}>
{`${getDelayString?.(delay, true) || ""}`}
<span
style={{
color: getDelayColor?.(delayToDisplay, stop) || "inherit",
}}
>
{`${getDelayString?.(delayToDisplay, true) || ""}`}
</span>
);
}}
Expand Down
41 changes: 41 additions & 0 deletions src/utils/getDelayString.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// We round the minutes down for departure times and up for arrival times.
export const getDelaySecure = (milliseconds, isArrival) => {
let timeInMs = milliseconds;
if (timeInMs < 0) {
timeInMs = 0;
}
const h = Math.floor(timeInMs / 3600000);
const m = (isArrival ? Math.ceil : Math.floor)((timeInMs % 3600000) / 60000);

return h * 3600000 + m * 60000;
};

// We round the minutes down for departure times and up for arrival times.
const getDelayString = (milliseconds, isArrival) => {
let timeInMs = milliseconds;
if (timeInMs < 0) {
timeInMs = 0;
}
timeInMs = getDelaySecure(timeInMs, isArrival);
const h = Math.floor(timeInMs / 3600000);
const m = (timeInMs % 3600000) / 60000;

if (h === 0 && m === 0) {
return "+0m";
}
if (h === 0) {
return `+${m}m`;
}

let str = `+`;
if (h > 0) {
str += `${h}h`;
}

if (m > 0) {
str += `${m}m`;
}
return str;
};

export default getDelayString;
24 changes: 24 additions & 0 deletions src/utils/getDelayString.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import getDelayString from "./getDelayString";

describe("getDelayString", () => {
it('should return "+0m" when delay <= 0', () => {
expect(getDelayString(0)).toBe("+0m");
expect(getDelayString(-1)).toBe("+0m");
});

it('should return "+Xm" when delay is between hours and 0', () => {
expect(getDelayString(69000)).toBe("+1m");
expect(getDelayString(129000)).toBe("+2m");
});

it('should return "+XhXm" when delay is more than 1 hour', () => {
expect(getDelayString(3659000)).toBe("+1h");
expect(getDelayString(3661000)).toBe("+1h1m");
expect(getDelayString(36610000)).toBe("+10h10m");
});

it("should ceil the result if it is an arrival time", () => {
expect(getDelayString(3659000, true)).toBe("+1h1m");
expect(getDelayString(3659000)).toBe("+1h");
});
});

0 comments on commit 2a74f82

Please sign in to comment.