Skip to content

Commit

Permalink
Merge pull request #27 from Marija-Kov/refactor-usegetdepartures
Browse files Browse the repository at this point in the history
  • Loading branch information
Marija-Kov authored Jul 10, 2024
2 parents 5085c9b + 8848d71 commit 2a2dd3b
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 98 deletions.
6 changes: 3 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { SetStateAction, useState } from "react";
import Form from "./components/Form";
import Departure from "./components/Departure";
import Info from "./components/Info";
import { DepartureReturned } from "./typeDefinitions/types";
import { ResultDeparture } from "./typeDefinitions/types";

function App() {
const [departures, setDepartures] = useState<DepartureReturned[] | string>(
const [departures, setDepartures] = useState<ResultDeparture[] | string>(
[]
);
const [appInfo, setAppInfo] = useState(false);

const runSetDepartures = (
d: SetStateAction<DepartureReturned[] | string>
d: SetStateAction<ResultDeparture[] | string>
) => {
setDepartures(d);
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useRef, useState } from "react";
import useGetDepartures from "../hooks/useGetDepartures";
import useGetDepartures from "../hooks/useGetDepartures/useGetDepartures";
import { StationName } from "../typeDefinitions/boringTypes";
import { FormProps, Input, YyyyMmDd, Time } from "../typeDefinitions/types";

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { StationDetails, YyyyMmDd } from "../typeDefinitions/types";
import { StationDetails, YyyyMmDd } from "../../typeDefinitions/types";

const useFetchData = () => {
const url =
Expand Down
89 changes: 0 additions & 89 deletions src/hooks/useGetDepartures.tsx

This file was deleted.

File renamed without changes.
59 changes: 59 additions & 0 deletions src/hooks/useGetDepartures/useGetDepartures.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { ResultDeparture, Input } from "../../typeDefinitions/types";
import useFetchData from "../useFetchData/useFetchData";
import {
frequencyOnDate,
stationIndex,
filterDepartures,
timeToNumber,
direction,
transformToReturnFormat,
getResult,
} from "./utils";

const useGetDepartures = () => {
const { fetchData } = useFetchData();

const getDepartures = async (
input: Input
): Promise<ResultDeparture[] | string> => {
if (!input.from || !input.to || !input.date || !input.time)
return "All fields must be filled";

if (input.from === input.to) return "That is not a route";

const data = await fetchData();
const stations = data.stations;
const frequency = frequencyOnDate(input.date, data.holidays);
const indexFrom = stationIndex(stations, input.from);
const indexTo = stationIndex(stations, input.to);

const possibleDepartures = filterDepartures(
stations[indexFrom].departures,
timeToNumber(input.time),
direction(indexFrom, indexTo),
frequency
);

if (!possibleDepartures.length) return "no departures";

const possibleDeparturesEnriched = transformToReturnFormat(
possibleDepartures,
stations,
indexFrom,
indexTo
);

const possibleArrivals = filterDepartures(
stations[indexTo].departures,
timeToNumber(input.time),
direction(indexFrom, indexTo),
frequency
);

return getResult(possibleDeparturesEnriched, possibleArrivals);
};

return { getDepartures };
};

export default useGetDepartures;
150 changes: 150 additions & 0 deletions src/hooks/useGetDepartures/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { StationName } from "../../typeDefinitions/boringTypes";
import {
ResultDeparture,
StationDetailsDeparture,
StationDetails,
Time,
YyyyMmDd,
} from "../../typeDefinitions/types";

/**
* Creates an array out of departure objects with found arrival matches; filters out the undefined.
* @returns An array of departures with all the necessary response information.
*/
export function getResult(
possibleDepartures: ResultDeparture[],
possibleArrivals: StationDetailsDeparture[]
) {
const result: ResultDeparture[] = [];
for (let departure of possibleDepartures) {
result.push(matchADepartureWithAnArrival(departure, possibleArrivals));
}
return result.filter((r) => r !== undefined);
}

/**
* Finds departure-arrival pairs among pre-filtered departures (which are also enriched)
* and arrivals based on matching trainIds.
* When a match is found, real arrival time is written to the enriched departure object.
* @returns A departure object with all the necessary response information or undefined.
*/
function matchADepartureWithAnArrival(
departure: ResultDeparture,
possibleArrivals: StationDetailsDeparture[]
) {
const matchingArrival = possibleArrivals.filter(
(arrival: StationDetailsDeparture) =>
arrival.trainDetails.id === departure.trainId
)[0];
return matchingArrival && writeArrivalTime(departure, matchingArrival);
}

/**
* Writes actual arrival time over arrival time placeholder in an enriched departure object.
* @returns A departure with a matching arrival time.
*/
function writeArrivalTime(
departure: ResultDeparture,
arrival: StationDetailsDeparture
) {
departure.arrivalTime = timeToString(arrival.time);
return departure;
}

/**
* Transforms departure objects (adds properties) into format that would be found in the final result.
* Sets a placeholder for arrival time.
* @returns Array of enriched departure objects.
*/
export function transformToReturnFormat(
departures: StationDetailsDeparture[],
stations: StationDetails[],
departureStationIndex: number,
arrivalStationIndex: number
) {
return departures.map((departure: StationDetailsDeparture) => {
return {
departureTime: timeToString(departure.time),
arrivalTime: "0:10", // placeholder
trainId: departure.trainDetails.id,
from: formatName(stations, departureStationIndex),
to: formatName(stations, arrivalStationIndex),
} as ResultDeparture;
});
}

/**
* Filters departures/arrivals at a station based on input time, inferred direction and frequency.
* @returns Narrowed down selection of departures that are to be processed further.
*/
export function filterDepartures(
departures: StationDetailsDeparture[],
time: number,
direction: 1 | 2,
frequency: (boolean | string)[]
) {
return departures.filter((departure: StationDetailsDeparture) => {
return (
departure.time >= time &&
departure.trainDetails.directionId === direction &&
frequency.includes(departure.trainDetails.activeOnWeekendsAndHolidays)
);
});
}

/**
* Converts a number into a time string.
*/
function timeToString(time: number) {
return time.toFixed(2).split(".").join(":") as Time;
}

/**
* Converts time string into a number.
*/
export function timeToNumber(time: Time) {
return Number(time.split(":").join("."));
}

/**
* @returns An array with 2 values of booleans or 1 boolean and 1 string denoting
* whether a train is active every day (true), Monday to Friday only (false)
* or weekends and holidays only ("w&h_only");
* They serve as departure filtering criteria.
*/
export function frequencyOnDate(date: YyyyMmDd, holidays: YyyyMmDd[]) {
const day = new Date(date).getDay();
return day === 0 || day === 6 || holidays.includes(date)
? [true, "w&h_only"]
: [true, false];
}

/**
* @returns Index of station in the list of stations (starting with Batajnica, ending with Ovca).
*/
export function stationIndex(
stations: StationDetails[],
endpoint: StationName
) {
return stations
.filter((station: StationDetails) => station.name === endpoint)
.map((station: StationDetails) => stations.indexOf(station))[0];
}

/**
* @returns A station name with correct spacing and capitalization.
*/
function formatName(stations: StationDetails[], stationIndex: number) {
return stations[stationIndex].nameFormatted;
}

/**
* Calculates direction based on departure and arrival station index.
* @returns Number 1 or 2.
*/
export function direction(
departureStationIndex: number,
arrivalStationIndex: number
) {
return departureStationIndex > arrivalStationIndex ? 2 : 1;
}
8 changes: 4 additions & 4 deletions src/typeDefinitions/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export type DepartureProps = {
trainId: TrainIdDirection1 | TrainIdDirection2;
};

export type DepartureReturned = DepartureProps & {
export type ResultDeparture = DepartureProps & {
from: StationNameFormatted;
to: StationNameFormatted;
};

export type FormProps = {
runSetDepartures: (d: string | DepartureReturned[]) => void;
runSetDepartures: (d: string | ResultDeparture[]) => void;
};

export type InfoProps = {
Expand All @@ -43,10 +43,10 @@ export type InfoProps = {
export type StationDetails = {
name: StationName;
nameFormatted: StationNameFormatted;
departures: StationDeparture[];
departures: StationDetailsDeparture[];
};

export type StationDeparture = {
export type StationDetailsDeparture = {
time: number;
trainDetails: TrainDetails;
};
Expand Down

0 comments on commit 2a2dd3b

Please sign in to comment.