Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore: better documentation #83

Merged
merged 10 commits into from
Oct 27, 2023
47 changes: 47 additions & 0 deletions src/api/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ type NetworkPayload = {
vType: VType[];
};

/**
* Uploads a network payload to initiate a simulation.
* @param {NetworkPayload} network - The network payload containing various network elements.
* @returns {Promise<SimulationInfo>} The response with simulation details.
* @throws {Error} Throws an error if the upload fails.
*/
export async function uploadNetwork(
network: NetworkPayload,
): Promise<SimulationInfo> {
Expand All @@ -35,6 +41,12 @@ export async function uploadNetwork(
return await response.json();
}

/**
* Fetches the output of a specific simulation.
* @param {string} simulationId - The ID of the simulation.
* @returns {Promise<SimulationOutput>} The simulation output details.
* @throws {Error} Throws an error if fetching the output fails.
*/
export async function getSimulationOutput(
simulationId: string,
): Promise<SimulationOutput> {
Expand All @@ -55,6 +67,12 @@ export async function getSimulationOutput(
return await response.json();
}

/**
* Fetches the output statistics of a specific simulation.
* @param {string} simulationId - The ID of the simulation.
* @returns {Promise<SimulationStatistics>} The simulation output statistics.
* @throws {Error} Throws an error if fetching the statistics fails.
*/
export async function getSimulationOutputStatistics(
simulationId: string,
): Promise<SimulationStatistics> {
Expand All @@ -75,6 +93,12 @@ export async function getSimulationOutputStatistics(
return await response.json();
}

/**
* Fetches the analytics of a specific simulation.
* @param {string} simulationId - The ID of the simulation.
* @returns {Promise<SimulationAnalytics>} The simulation analytics details.
* @throws {Error} Throws an error if fetching the analytics fails.
*/
export async function getSimulationAnalytics(
simulationId: string,
): Promise<SimulationAnalytics> {
Expand All @@ -97,6 +121,12 @@ export async function getSimulationAnalytics(
return await response.json();
}

/**
* Fetches information of a specific simulation.
* @param {string} simulationId - The ID of the simulation.
* @returns {Promise<SimulationInfo>} The simulation information.
* @throws {Error} Throws an error if fetching the information fails.
*/
export async function getSimulationInfo(
simulationId: string,
): Promise<SimulationInfo> {
Expand All @@ -114,6 +144,13 @@ export async function getSimulationInfo(
return await response.json();
}

/**
* Modifies a specific simulation with a new network payload.
* @param {string} simulationId - The ID of the simulation.
* @param {NetworkPayload} network - The new network payload.
* @returns {Promise<SimulationInfo>} The updated simulation details.
* @throws {Error} Throws an error if the modification fails.
*/
export async function modifyNetwork(
simulationId: string,
network: NetworkPayload,
Expand All @@ -133,6 +170,11 @@ export async function modifyNetwork(
return await response.json();
}

/**
* Deletes a specific simulation.
* @param {string} simulationId - The ID of the simulation.
* @throws {Error} Throws an error if the deletion fails.
*/
export async function deleteSimulation(simulationId: string) {
const response = await fetch(`${BASE_URL}/simulation/${simulationId}`, {
method: 'DELETE',
Expand All @@ -148,6 +190,11 @@ export async function deleteSimulation(simulationId: string) {
return await response.json();
}

/**
* Fetches information of all simulations.
* @returns {Promise<SimulationInfo[]>} A list of all simulation details.
* @throws {Error} Throws an error if fetching the information fails.
*/
export async function getAllSimulationInfo(): Promise<SimulationInfo[]> {
const response = await fetch(`${BASE_URL}/simulations`, {
method: 'GET',
Expand Down
4 changes: 0 additions & 4 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ import { ProjectUploadButton } from './ProjectUploadButton';
import { SimulationHistoryButton } from './SimulationHistory/SimulationHistoryButton';
import { SimulationSummary } from './SimulationHistory/SimulationSummary';

export function classNames(...classes: string[]) {
return classes.filter(Boolean).join(' ');
}

export function Header() {
const network = useNetworkStore();

Expand Down
2 changes: 1 addition & 1 deletion src/components/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { XMarkIcon } from '@heroicons/react/24/outline';

import { RoadPropertiesEditor } from '~/components/Editors/RoadProperties';
import { IntersectionPropertiesEditor } from '~/components/Editors/IntersectionProperties';
import { RoadPropertiesEditor } from '~/components/Editors/RoadProperties';
import { ModalViewNames, useLeftSideBar } from '~/zustand/useLeftSideBar';
import { useSelector } from '~/zustand/useSelected';

Expand Down
22 changes: 21 additions & 1 deletion src/helpers/format/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@ import { format as formatTz, utcToZonedTime } from 'date-fns-tz';

import { IntersectionType } from '~/types/Network';

export function formatISOString(dateString: string, timeZone: string = Intl.DateTimeFormat().resolvedOptions().timeZone) {
/**
* Formats an ISO date string to a local date and time.
* @param {string} dateString - The ISO date string to format.
* @param {string} [timeZone=Intl.DateTimeFormat().resolvedOptions().timeZone] - The timezone to format the date to.
* @returns {Object} An object containing the formatted date and time.
* @throws {Error} Throws an error if the date string is invalid.
*/
export function formatISOString(
dateString: string,
timeZone: string = Intl.DateTimeFormat().resolvedOptions().timeZone,
) {
const date = parseISO(dateString);

if (!isValid(date)) {
Expand All @@ -21,6 +31,11 @@ export function formatISOString(dateString: string, timeZone: string = Intl.Date
};
}

/**
* Formats simulation time given in milliseconds to a MM:SS:MS format.
* @param {number} milliseconds - The number of milliseconds to format.
* @returns {string} The formatted time in MM:SS:MS format.
*/
export function formatSimulationTime(milliseconds: number) {
const remainingMilliseconds = Math.floor(milliseconds / 10) % 100;
const totalSeconds = Math.floor(milliseconds / 1000);
Expand All @@ -33,6 +48,11 @@ export function formatSimulationTime(milliseconds: number) {
)}:${String(remainingMilliseconds).padStart(2, '0')}`;
}

/**
* Converts an intersection type enum to a human-readable string.
* @param {IntersectionType} type - The intersection type to convert.
* @returns {string} A human-readable string representation of the intersection type.
*/
export function prettyPrintIntersectionType(type: IntersectionType) {
// Replace underscores with spaces and capitalize the first letter
return type.replace(/_/g, ' ').replace(/^\w/, c => c.toUpperCase());
Expand Down
6 changes: 6 additions & 0 deletions src/helpers/sumo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ export type SumoMessage = {
};
};

/**
* Extracts and transforms cars from a SUMO message to match the required Car format.
* @param {string} sumoMessage - The SUMO message as a JSON string.
* @returns {Car[]} An array of cars transformed from the SUMO message.
* @throws {Error} Throws an error if the SUMO message is in an invalid format or cannot be parsed.
*/
export function extractCarsFromSumoMessage(sumoMessage: string): Car[] {
let parsedJson: SumoMessage;
const cars: Car[] = [];
Expand Down
91 changes: 90 additions & 1 deletion src/helpers/zustand/NetworkStoreHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { Network, useNetworkStore } from '~/zustand/useNetworkStore';
/**
* Given pointA and pointB and a line drawn between edges from C to D
* find if the line intersects with the hypothetical line drawn between A and B

* @param {Network} network - The network containing all edges.
* @param {Point} pointA - The start point of the edge.
* @param {Point} pointB - The end point of the edge.
* @returns {boolean} - Returns true if there is an intersection, otherwise false.
*/
export function edgeDoesIntersect(
network: Network,
Expand Down Expand Up @@ -37,6 +42,13 @@ export function edgeDoesIntersect(
return false;
}

/**
* Checks if point q lies on the line segment formed by points p and r.
* @param {Point} p - The starting point of the segment.
* @param {Point} q - The point to check.
* @param {Point} r - The ending point of the segment.
* @returns {boolean} - Returns true if q lies on the segment, otherwise false.
*/
export function onSegment(p: Point, q: Point, r: Point): boolean {
return (
q.x <= Math.max(p.x, r.x) &&
Expand All @@ -46,6 +58,13 @@ export function onSegment(p: Point, q: Point, r: Point): boolean {
);
}

/**
* Determines the orientation of an ordered triplet of points.
* @param {Point} p - First point.
* @param {Point} q - Second point.
* @param {Point} r - Third point.
* @returns {number} - Returns 0 for colinear, 1 for clockwise, and 2 for counterclockwise.
*/
export function orientation(p: Point, q: Point, r: Point): number {
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
if (val === 0) {
Expand All @@ -54,6 +73,14 @@ export function orientation(p: Point, q: Point, r: Point): number {
return val > 0 ? 1 : 2; // clockwise or counterclockwise
}

/**
* @param {Point} A - Start point of the first segment.
* @param {Point} B - End point of the first segment.
* @param {Point} C - Start point of the second segment.
* @param {Point} D - End point of the second segment.
* @returns {boolean} - Returns true if segments intersect, otherwise false.
*/

export function doIntersect(A: Point, B: Point, C: Point, D: Point): boolean {
const o1 = orientation(A, B, C);
const o2 = orientation(A, B, D);
Expand Down Expand Up @@ -88,18 +115,36 @@ export function doIntersect(A: Point, B: Point, C: Point, D: Point): boolean {
return false;
}

/**
* Checks if two points are equal.
* @param {Point} p1 - The first point.
* @param {Point} p2 - The second point.
* @returns {boolean} - Returns true if points are equal, otherwise false.
*/
export function arePointsEqual(p1: Point, p2: Point) {
return p1.x === p2.x && p1.y === p2.y;
}

/**
* Generates a route ID based on the provided from and to strings.
* @param {string} from - The source string.
* @param {string} to - The sink string.
* @returns {string} - Returns the generated route ID.
*/
export function createRouteId(from: string, to: string) {
const source = from.split('_');
const sink = to.split('_');

return `${source[0]}_to_${sink[1]}`;
}

// TODO: Add more data to the store so we can get O(1) retrieval of edges for a node
// TODO: Add more data to the store so we can get O(1) retrieval of edges for a node/**
/**
* Retrieves all edge IDs associated with a given node.
* @param {string} nodeId - The node's ID.
* @param {Record<string, Edge>} edges - All edges in the network.
* @returns {string[]} - Returns an array of edge IDs associated with the node.
*/
export function getAllEdgeIdsForNode(
nodeId: string,
edges: Record<string, Edge>,
Expand All @@ -115,6 +160,13 @@ export function getAllEdgeIdsForNode(
return edgeIds;
}

/**
* @param {Record<string, Route>} routes - All routes in the network.
* @param {Record<string, Connection>} connections - All connections in the network.
* @param {Record<string, Flow>} flow - The network flow.
* @param {Edge} newEdge - The newly added edge.
* @returns {Object} - Returns updated connections, routes, and flows.
*/
export function updateAssociatesOnNewEdge(
edges: Record<string, Edge>,
routes: Record<string, Route>,
Expand Down Expand Up @@ -182,6 +234,13 @@ export function updateAssociatesOnNewEdge(
return { newConnections, newRoutes, newFlows };
}

/**
* @param {string} to - Destination edge ID.
* @param {number} fromNumLanes - Number of lanes in the source edge.
* @param {number} toNumLanes - Number of lanes in the destination edge.
* @param {Record<string, Connection>} connections - All connections in the network.
* @returns {Record<string, Connection>} - Returns updated connections.
*/
export function updateConnectionsOnLaneChange(
from: string,
to: string,
Expand Down Expand Up @@ -236,6 +295,13 @@ export function updateConnectionsOnLaneChange(
return newConnections;
}

/**
* Removes items from a record based on a condition.
* @template T
* @param {Record<string, T>} items - The items to process.
* @param {function(T): boolean} condition - The condition to test each item against.
* @returns {Record<string, T>} - Returns the record without the removed items.
*/
export function removeItems<T>(
items: Record<string, T>,
condition: (item: T) => boolean,
Expand All @@ -250,6 +316,13 @@ export function removeItems<T>(
return newItems;
}

/**
* Determines the leading and trailing terminals for a given edge.
* @param {Edge} edge - The edge to process.
* @param {number} [lambdat=50] - Parameter affecting the calculation.
* @param {number} [lambdal=50] - Parameter affecting the calculation.
* @returns {Object} - Returns an object containing arrays of leading and trailing terminals.
*/
export function getEdgeTerminals(
edge: Edge,
lambdat: number = 50,
Expand Down Expand Up @@ -309,6 +382,11 @@ export function getEdgeTerminals(
};
}

/**
* Handles the download event for the network data.
* @param {function(string, string)} downloadJson - Function to trigger the download.
* @param {Network} network - The network data.
*/
export function handleDownloadEvent(
downloadJson: (jsonString: string, fileName: string) => void,
network: Network,
Expand All @@ -317,6 +395,11 @@ export function handleDownloadEvent(
downloadJson(jsonString, network.documentName);
}

/**
* Determines if the network has any data.
* @param {Network} network - The network to check.
* @returns {boolean} - Returns true if the network has data, otherwise false.
*/
export function networkHasData(network: Network) {
return [
network.nodes,
Expand All @@ -327,6 +410,12 @@ export function networkHasData(network: Network) {
].some(record => Object.values(record).length > 0);
}

/**
* Retrieves all edges associated with a given node.
* @param {string} nodeId - The node's ID.
* @param {Record<string, Edge>} edges - All edges in the network.
* @returns {Edge[]} - Returns an array of edges associated with the node.
*/
export function getEdgesAssociatedWithNode(
nodeId: string,
edges: Record<string, Edge>,
Expand Down
11 changes: 11 additions & 0 deletions src/hooks/useJsonDownloader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
/**
* Custom hook to facilitate downloading JSON data as a file.
*
* @returns {function(string, string): void} - A function that triggers a download of a JSON string as a file.
*/
const useJsonDownloader = () => {
/**
* Initiates the download of a JSON string as a file.
*
* @param {string} jsonString - The JSON data as a string.
* @param {string} fileName - Desired name for the downloaded file.
*/
const downloadJson = (jsonString: string, fileName: string) => {
const blob = new Blob([jsonString], { type: 'application/json' });
const url = URL.createObjectURL(blob);
Expand Down
Loading