Skip to content

Commit

Permalink
front: implement macro editor OP import
Browse files Browse the repository at this point in the history
  • Loading branch information
emersion committed Jul 9, 2024
1 parent c390cb4 commit 431f85d
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { osrdEditoastApi } from 'common/api/osrdEditoastApi';
import type { SearchResultItemOperationalPoint, SearchPayload } from 'common/api/osrdEditoastApi';
import type { AppDispatch } from 'store';

import type { Node } from './types';

const convertGeoCoords = (nodes: Node[]) => {
const xCoords = nodes.map((node) => node.positionX);
const yCoords = nodes.map((node) => node.positionY);
const minX = Math.min(...xCoords);
const minY = Math.min(...yCoords);
const maxX = Math.max(...xCoords);
const maxY = Math.max(...yCoords);
const width = maxX - minX;
const height = maxY - minY;
// TODO: grab NGE component size
const scaleX = 800;
const scaleY = 500;
const padding = 0.1;

return nodes.map((node) => {
const normalizedX = (node.positionX - minX) / width;
const normalizedY = (node.positionY - minY) / height;
const paddedX = normalizedX * (1 - 2 * padding) + padding;
const paddedY = normalizedY * (1 - 2 * padding) + padding;
return {
...node,
positionX: scaleX * paddedX,
positionY: scaleY * paddedY,
};
});
};

const importTimetable = async (infraId: number, timetableId: number, dispatch: AppDispatch) => {
const timetablePromise = dispatch(
osrdEditoastApi.endpoints.getV2TimetableById.initiate({ id: timetableId })
);
const { train_ids } = await timetablePromise.unwrap();

const trainSchedulesPromise = dispatch(
osrdEditoastApi.endpoints.postV2TrainSchedule.initiate({
body: { ids: train_ids },
})
);
const trainSchedules = await trainSchedulesPromise.unwrap();

// Collect UICs, trigrams and operational point IDs
const pathItems = trainSchedules.map((schedule) => schedule.path).flat();
const uics = new Set<number>();
const trigrams = new Set<string>();
const opIds = new Set<string>();
// eslint-disable-next-line no-restricted-syntax
for (const item of pathItems) {
if ('uic' in item) {
uics.add(item.uic);
} else if ('trigram' in item) {
trigrams.add(item.trigram);
} else if ('operational_point' in item) {
opIds.add(item.operational_point);
}
}

if (uics.size === 0 && trigrams.size === 0 && opIds.size === 0) {
return [];
}

const filterChs = ['BV', '00']; // we're only interested in stations
const searchPayload: SearchPayload = {
object: 'operationalpoint',
query: [
'and',
['=', ['infra_id'], infraId],
['or', ...filterChs.map((ch) => ['=', ['ch'], ch])],
[
'or',
...[...uics].map((uic) => ['=', ['uic'], uic]),
...[...trigrams].map((trigram) => ['=', ['trigram'], trigram]),
...[...opIds].map((id) => ['=', ['obj_id'], id]),
],
],
};

const searchResults = [];
const pageSize = 100;
let done = false;
for (let page = 1; !done; page += 1) {
const searchPromise = dispatch(
osrdEditoastApi.endpoints.postSearch.initiate({
page,
pageSize,
searchPayload,
})
);
// eslint-disable-next-line no-await-in-loop
const results = await searchPromise.unwrap();
searchResults.push(...results);
done = results.length < pageSize;
}

let nodes: Node[] = searchResults.map((searchResult) => {
const op = searchResult as SearchResultItemOperationalPoint;
return {
id: op.obj_id,
betriebspunktName: op.trigram,
fullName: op.name,
positionX: op.geographic.coordinates[0],
positionY: op.geographic.coordinates[1],
ports: [],
transitions: [],
connections: [],
resourceId: 1,
perronkanten: 10,
connectionTime: 0,
trainrunCategoryHaltezeiten: {},
symmetryAxis: 0,
warnings: [],
labelIds: [],
};
});

nodes = convertGeoCoords(nodes);

// TODO: remove
// eslint-disable-next-line
console.log(nodes);

return nodes;
};

export default importTimetable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// NGE DTO types, see:
// https://github.com/SchweizerischeBundesbahnen/netzgrafik-editor-frontend/blob/main/src/app/data-structures/business.data.structures.ts

export type Haltezeit = {
haltezeit: number;
no_halt: boolean;
};

export type Node = {
id: string; // TODO: in NGE this is a number
/** Trigram */
betriebspunktName: string;
fullName: string;
positionX: number;
positionY: number;
ports: unknown[];
transitions: unknown[];
connections: unknown[];
resourceId: number;
/** Number of tracks where train can stop */
perronkanten: number;
/** Time needed to change train in minutes */
connectionTime: number;
trainrunCategoryHaltezeiten: { [category: string]: Haltezeit };
symmetryAxis: number;
warnings: unknown[];
labelIds: number[];
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { getSpaceTimeChartData, selectProjectionV2 } from './getSimulationResult
import ImportTrainScheduleV2 from './ImportTrainScheduleV2';
import ManageTrainScheduleV2 from './ManageTrainScheduleV2';
import SimulationResultsV2 from './SimulationResultsV2';
import importTimetableToNGE from '../../components/MacroEditor/import';

type SimulationParams = {
projectId: string;
Expand Down Expand Up @@ -146,6 +147,13 @@ const ScenarioV2 = () => {
[]
);

// TODO: drop this
useEffect(() => {
if (infraId && timetableId) {
importTimetableToNGE(infraId, timetableId, dispatch);
}
}, [infraId, timetableId]);

if (!scenario || !infraId || !timetableId || !timetable) return null;

return (
Expand Down

0 comments on commit 431f85d

Please sign in to comment.