Estimation de la distance plutôt que de compter sur l'instabilité de signal.eu.org/osm

This commit is contained in:
Emmy D'Anello 2024-12-08 01:47:02 +01:00
parent 99bd7a88a5
commit 11ab6f66f7
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
7 changed files with 42 additions and 94 deletions

View File

@ -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";

View File

@ -65,7 +65,6 @@ model TrainTrip {
departureTime DateTime @db.Timestamptz(3) departureTime DateTime @db.Timestamptz(3)
arrivalTime DateTime @db.Timestamptz(3) arrivalTime DateTime @db.Timestamptz(3)
infoJson Json infoJson Json
geometry String
moneyUpdate MoneyUpdate? moneyUpdate MoneyUpdate?
} }

View File

@ -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
}

View File

@ -15,7 +15,7 @@ export class CreateTrainDto {
@IsNumber() @IsNumber()
@Type(() => Number) @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 distance: number
@IsString() @IsString()
@ -39,8 +39,4 @@ export class CreateTrainDto {
@IsJSON() @IsJSON()
@ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" }) @ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" })
infoJson: JsonValue infoJson: JsonValue
@IsString()
@ApiProperty({ description: "Géométrie de la course, obtenue par https://signal.eu.org/osm/" })
geometry: string
} }

View File

@ -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

View File

@ -13,7 +13,7 @@ export class TrainEntity implements TrainTrip {
@ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le trajet" }) @ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le trajet" })
userId: number 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 distance: number
@ApiProperty({ description: "Nom de la gare de départ" }) @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" }) @ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" })
infoJson: JsonValue infoJson: JsonValue
@ApiProperty({ description: "Géométrie de la course, obtenue par https://signal.eu.org/osm/" })
geometry: string
} }

View File

@ -7,8 +7,7 @@ import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { paginate } from 'src/common/utils/pagination.utils' import { paginate } from 'src/common/utils/pagination.utils'
import { ImportTrainDto } from './dto/import-train.dto' import { ImportTrainDto } from './dto/import-train.dto'
import { InterrailJourney, InterrailLegInfo, InterrailTravelInfo } from './dto/interrail-api.dto' import { InterrailJourney, InterrailLegInfo, InterrailTravelInfo } from './dto/interrail-api.dto'
import { JsonObject } from '@prisma/client/runtime/library' import { distanceCoordinates } from 'src/common/utils/calculus.utils'
import { OSMRResponse } from './dto/osmr-api.dto'
@Injectable() @Injectable()
export class TrainsService { export class TrainsService {
@ -65,15 +64,14 @@ export class TrainsService {
arrival.setDate(arrival.getDate() + travelInfoJson.arrivalTime.offset) arrival.setDate(arrival.getDate() + travelInfoJson.arrivalTime.offset)
const legInfoJson: InterrailLegInfo = JSON.parse(leg.infoJson) const legInfoJson: InterrailLegInfo = JSON.parse(leg.infoJson)
const coordinatesString = legInfoJson.trainStopStations.map(trainStopStation => { const distance = legInfoJson.trainStopStations
return `${trainStopStation.coordinates.longitude},${trainStopStation.coordinates.latitude}` .map(trainStopStation => trainStopStation.coordinates)
}).join(';') .reduce((distance, coordinates, index) => {
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 (index === 0)
if (osmrResult?.code === "NoRoute") return distance
throw new NotAcceptableException("Aucune route n'a été trouvée avec https://signal.eu.org/osm/") const oldCoordinates = legInfoJson.trainStopStations.at(index - 1).coordinates
const route = osmrResult.routes[0] return distance + distanceCoordinates({ from: oldCoordinates, to: coordinates })
const distance = route.distance }, 0)
const geometry = route.geometry
return this.prisma.trainTrip.upsert({ return this.prisma.trainTrip.upsert({
where: { where: {
@ -88,7 +86,6 @@ export class TrainsService {
departureTime: departure, departureTime: departure,
arrivalTime: arrival, arrivalTime: arrival,
infoJson: leg.infoJson, infoJson: leg.infoJson,
geometry: geometry,
}, },
update: { update: {
userId: user.id, userId: user.id,
@ -98,7 +95,6 @@ export class TrainsService {
departureTime: departure, departureTime: departure,
arrivalTime: arrival, arrivalTime: arrival,
infoJson: leg.infoJson, infoJson: leg.infoJson,
geometry: geometry,
} }
}) })
} }