diff --git a/server/prisma/migrations/20241207230134_remove_train_geometry/migration.sql b/server/prisma/migrations/20241207230134_remove_train_geometry/migration.sql new file mode 100644 index 0000000..16fcfb2 --- /dev/null +++ b/server/prisma/migrations/20241207230134_remove_train_geometry/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `geometry` on the `TrainTrip` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "TrainTrip" DROP COLUMN "geometry"; diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index e6e372f..e3ca76b 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -65,7 +65,6 @@ model TrainTrip { departureTime DateTime @db.Timestamptz(3) arrivalTime DateTime @db.Timestamptz(3) infoJson Json - geometry String moneyUpdate MoneyUpdate? } diff --git a/server/src/common/utils/calculus.utils.ts b/server/src/common/utils/calculus.utils.ts new file mode 100644 index 0000000..dfc7c8f --- /dev/null +++ b/server/src/common/utils/calculus.utils.ts @@ -0,0 +1,23 @@ +const EARTH_RADIUS = 6378137 + +type Coordinates = { + latitude: number + longitude: number +} + +type UseDistanceTypes = { + from: Coordinates + to: Coordinates +} + +export function toRadians(degrees: number) { + return (degrees * Math.PI) / 180 +} + +export function distanceCoordinates({ from, to }: UseDistanceTypes) { + const distance = EARTH_RADIUS * Math.acos( + Math.sin(toRadians(to.latitude)) * Math.sin(toRadians(from.latitude)) + + Math.cos(toRadians(to.latitude)) * Math.cos(toRadians(from.latitude)) * Math.cos(toRadians(from.longitude) - toRadians(to.longitude)), + ) + return distance +} diff --git a/server/src/trains/dto/create-train.dto.ts b/server/src/trains/dto/create-train.dto.ts index 4a1ced3..6761a91 100644 --- a/server/src/trains/dto/create-train.dto.ts +++ b/server/src/trains/dto/create-train.dto.ts @@ -15,7 +15,7 @@ export class CreateTrainDto { @IsNumber() @Type(() => Number) - @ApiProperty({ description: "Distance en mètres du trajet, calculé sur https://signal.eu.org/osm/" }) + @ApiProperty({ description: "Distance estimée en mètres du trajet" }) distance: number @IsString() @@ -39,8 +39,4 @@ export class CreateTrainDto { @IsJSON() @ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" }) infoJson: JsonValue - - @IsString() - @ApiProperty({ description: "Géométrie de la course, obtenue par https://signal.eu.org/osm/" }) - geometry: string } diff --git a/server/src/trains/dto/osmr-api.dto.ts b/server/src/trains/dto/osmr-api.dto.ts deleted file mode 100644 index 799cdc8..0000000 --- a/server/src/trains/dto/osmr-api.dto.ts +++ /dev/null @@ -1,71 +0,0 @@ -export enum DrivingSide { - LEFT = "left", - RIGHT = "right", -} - -export type OSMRLocation = number[] - -export interface OSMRWaypoint { - location: OSMRLocation - distance: number - hint: string - name: string -} - -export interface OSMRIntersection { - location: OSMRLocation - bearings: number[] - entry: boolean[] - in?: number - out?: number - classes: string[] -} - -export interface OSMRManeuver { - type: string - location: OSMRLocation - bearing_before: number - bearing_after: number -} - -export interface OSMRLegStep { - distance: number - duration: number - weight: number - driving_side: DrivingSide - intersections: OSMRIntersection[] - ref: string - name: string - mode: string - maneuver: OSMRManeuver - geometry: string -} - -export interface OSMRLeg { - distance: number - steps: OSMRLegStep[] - duration: number - weight: number - summary: string -} - -export interface OSMRRoute { - distance: number - weight_name: SVGStringList - legs: OSMRLeg[] - duration: number - weight: number - geometry: string -} - -export interface OSMRTrain { - waypoints: OSMRWaypoint[] - routes: OSMRRoute[] -} - -export interface OSMRError { - code: string - message: string -} - -export type OSMRResponse = OSMRTrain & OSMRError diff --git a/server/src/trains/entities/train.entity.ts b/server/src/trains/entities/train.entity.ts index 7f87553..cf8dba6 100644 --- a/server/src/trains/entities/train.entity.ts +++ b/server/src/trains/entities/train.entity.ts @@ -13,7 +13,7 @@ export class TrainEntity implements TrainTrip { @ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le trajet" }) userId: number - @ApiProperty({ description: "Distance en mètres du trajet, calculé sur https://signal.eu.org/osm/" }) + @ApiProperty({ description: "Distance estimée en mètres du trajet" }) distance: number @ApiProperty({ description: "Nom de la gare de départ" }) @@ -30,7 +30,4 @@ export class TrainEntity implements TrainTrip { @ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" }) infoJson: JsonValue - - @ApiProperty({ description: "Géométrie de la course, obtenue par https://signal.eu.org/osm/" }) - geometry: string } diff --git a/server/src/trains/trains.service.ts b/server/src/trains/trains.service.ts index 71f6ca1..382be91 100644 --- a/server/src/trains/trains.service.ts +++ b/server/src/trains/trains.service.ts @@ -7,8 +7,7 @@ import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' import { paginate } from 'src/common/utils/pagination.utils' import { ImportTrainDto } from './dto/import-train.dto' import { InterrailJourney, InterrailLegInfo, InterrailTravelInfo } from './dto/interrail-api.dto' -import { JsonObject } from '@prisma/client/runtime/library' -import { OSMRResponse } from './dto/osmr-api.dto' +import { distanceCoordinates } from 'src/common/utils/calculus.utils' @Injectable() export class TrainsService { @@ -65,15 +64,14 @@ export class TrainsService { arrival.setDate(arrival.getDate() + travelInfoJson.arrivalTime.offset) const legInfoJson: InterrailLegInfo = JSON.parse(leg.infoJson) - const coordinatesString = legInfoJson.trainStopStations.map(trainStopStation => { - return `${trainStopStation.coordinates.longitude},${trainStopStation.coordinates.latitude}` - }).join(';') - const osmrResult: OSMRResponse = await fetch(`https://signal.eu.org/osm/eu/route/v1/train/${coordinatesString}?overview=full&steps=true&exclude=highspeed`).then(result => result.json()) - if (osmrResult?.code === "NoRoute") - throw new NotAcceptableException("Aucune route n'a été trouvée avec https://signal.eu.org/osm/") - const route = osmrResult.routes[0] - const distance = route.distance - const geometry = route.geometry + const distance = legInfoJson.trainStopStations + .map(trainStopStation => trainStopStation.coordinates) + .reduce((distance, coordinates, index) => { + if (index === 0) + return distance + const oldCoordinates = legInfoJson.trainStopStations.at(index - 1).coordinates + return distance + distanceCoordinates({ from: oldCoordinates, to: coordinates }) + }, 0) return this.prisma.trainTrip.upsert({ where: { @@ -88,7 +86,6 @@ export class TrainsService { departureTime: departure, arrivalTime: arrival, infoJson: leg.infoJson, - geometry: geometry, }, update: { userId: user.id, @@ -98,7 +95,6 @@ export class TrainsService { departureTime: departure, arrivalTime: arrival, infoJson: leg.infoJson, - geometry: geometry, } }) }