mirror of
https://gitlab.com/mobicoop/v3/service/matcher.git
synced 2026-01-01 14:02:39 +00:00
basic ad entity without direction
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
import { DefaultParams } from '../types/default-params.type';
|
||||
|
||||
export interface DefaultParamsProviderPort {
|
||||
getParams(): DefaultParams;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Coordinates } from '../types/coordinates.type';
|
||||
|
||||
export interface DirectionEncoderPort {
|
||||
encode(coordinates: Coordinates[]): string;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export interface GeodesicPort {
|
||||
inverse(
|
||||
lon1: number,
|
||||
lat1: number,
|
||||
lon2: number,
|
||||
lat2: number,
|
||||
): {
|
||||
azimuth: number;
|
||||
distance: number;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { GeorouterPort } from './georouter.port';
|
||||
|
||||
export interface GeorouterCreatorPort {
|
||||
create(type: string, url: string): GeorouterPort;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { GeorouterSettings } from '../types/georouter-settings.type';
|
||||
import { Path } from '../types/path.type';
|
||||
import { Route } from '../types/route.type';
|
||||
|
||||
export interface GeorouterPort {
|
||||
routes(paths: Path[], settings: GeorouterSettings): Promise<Route[]>;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export type Coordinates = {
|
||||
lon: number;
|
||||
lat: number;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export type DefaultParams = {
|
||||
GEOROUTER_TYPE: string;
|
||||
GEOROUTER_URL: string;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export type GeorouterSettings = {
|
||||
withPoints: boolean;
|
||||
withTime: boolean;
|
||||
withDistance: boolean;
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { PathType } from '../../domain/route.types';
|
||||
import { Point } from './point.type';
|
||||
|
||||
export type Path = {
|
||||
type: PathType;
|
||||
points: Point[];
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import { PointContext } from '../../domain/route.types';
|
||||
import { Coordinates } from './coordinates.type';
|
||||
|
||||
export type Point = Coordinates & {
|
||||
context?: PointContext;
|
||||
};
|
||||
11
src/modules/geography/core/application/types/route.type.ts
Normal file
11
src/modules/geography/core/application/types/route.type.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Point } from './point.type';
|
||||
|
||||
export type Route = {
|
||||
name: string;
|
||||
distance: number;
|
||||
duration: number;
|
||||
fwdAzimuth: number;
|
||||
backAzimuth: number;
|
||||
distanceAzimuth: number;
|
||||
points: Point[];
|
||||
};
|
||||
117
src/modules/geography/core/domain/route.entity.ts
Normal file
117
src/modules/geography/core/domain/route.entity.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { AggregateRoot, AggregateID } from '@mobicoop/ddd-library';
|
||||
import {
|
||||
CreateRouteProps,
|
||||
Path,
|
||||
Role,
|
||||
RouteProps,
|
||||
PathType,
|
||||
} from './route.types';
|
||||
import { WaypointProps } from './value-objects/waypoint.value-object';
|
||||
|
||||
export class RouteEntity extends AggregateRoot<RouteProps> {
|
||||
protected readonly _id: AggregateID;
|
||||
|
||||
static create = async (create: CreateRouteProps): Promise<RouteEntity> => {
|
||||
const props: RouteProps = await create.georouter.routes(
|
||||
this.getPaths(create.roles, create.waypoints),
|
||||
create.georouterSettings,
|
||||
);
|
||||
const route = new RouteEntity({ props });
|
||||
return route;
|
||||
};
|
||||
|
||||
validate(): void {
|
||||
// entity business rules validation to protect it's invariant before saving entity to a database
|
||||
}
|
||||
|
||||
private static getPaths = (
|
||||
roles: Role[],
|
||||
waypoints: WaypointProps[],
|
||||
): Path[] => {
|
||||
const paths: Path[] = [];
|
||||
if (roles.includes(Role.DRIVER) && roles.includes(Role.PASSENGER)) {
|
||||
if (waypoints.length == 2) {
|
||||
// 2 points => same route for driver and passenger
|
||||
const commonPath: Path = {
|
||||
type: PathType.COMMON,
|
||||
points: waypoints,
|
||||
};
|
||||
paths.push(commonPath);
|
||||
} else {
|
||||
const driverPath: Path = RouteEntity.createDriverPath(waypoints);
|
||||
const passengerPath: Path = RouteEntity.createPassengerPath(waypoints);
|
||||
paths.push(driverPath, passengerPath);
|
||||
}
|
||||
} else if (roles.includes(Role.DRIVER)) {
|
||||
const driverPath: Path = RouteEntity.createDriverPath(waypoints);
|
||||
paths.push(driverPath);
|
||||
} else if (roles.includes(Role.PASSENGER)) {
|
||||
const passengerPath: Path = RouteEntity.createPassengerPath(waypoints);
|
||||
paths.push(passengerPath);
|
||||
}
|
||||
return paths;
|
||||
};
|
||||
|
||||
private static createDriverPath = (waypoints: WaypointProps[]): Path => {
|
||||
return {
|
||||
type: PathType.DRIVER,
|
||||
points: waypoints,
|
||||
};
|
||||
};
|
||||
|
||||
private static createPassengerPath = (waypoints: WaypointProps[]): Path => {
|
||||
return {
|
||||
type: PathType.PASSENGER,
|
||||
points: [waypoints[0], waypoints[waypoints.length - 1]],
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// import { IGeodesic } from '../interfaces/geodesic.interface';
|
||||
// import { Point } from '../types/point.type';
|
||||
// import { SpacetimePoint } from './spacetime-point';
|
||||
|
||||
// export class Route {
|
||||
// distance: number;
|
||||
// duration: number;
|
||||
// fwdAzimuth: number;
|
||||
// backAzimuth: number;
|
||||
// distanceAzimuth: number;
|
||||
// points: Point[];
|
||||
// spacetimePoints: SpacetimePoint[];
|
||||
// private geodesic: IGeodesic;
|
||||
|
||||
// constructor(geodesic: IGeodesic) {
|
||||
// this.distance = undefined;
|
||||
// this.duration = undefined;
|
||||
// this.fwdAzimuth = undefined;
|
||||
// this.backAzimuth = undefined;
|
||||
// this.distanceAzimuth = undefined;
|
||||
// this.points = [];
|
||||
// this.spacetimePoints = [];
|
||||
// this.geodesic = geodesic;
|
||||
// }
|
||||
|
||||
// setPoints = (points: Point[]): void => {
|
||||
// this.points = points;
|
||||
// this.setAzimuth(points);
|
||||
// };
|
||||
|
||||
// setSpacetimePoints = (spacetimePoints: SpacetimePoint[]): void => {
|
||||
// this.spacetimePoints = spacetimePoints;
|
||||
// };
|
||||
|
||||
// protected setAzimuth = (points: Point[]): void => {
|
||||
// const inverse = this.geodesic.inverse(
|
||||
// points[0].lon,
|
||||
// points[0].lat,
|
||||
// points[points.length - 1].lon,
|
||||
// points[points.length - 1].lat,
|
||||
// );
|
||||
// this.fwdAzimuth =
|
||||
// inverse.azimuth >= 0 ? inverse.azimuth : 360 - Math.abs(inverse.azimuth);
|
||||
// this.backAzimuth =
|
||||
// this.fwdAzimuth > 180 ? this.fwdAzimuth - 180 : this.fwdAzimuth + 180;
|
||||
// this.distanceAzimuth = inverse.distance;
|
||||
// };
|
||||
// }
|
||||
54
src/modules/geography/core/domain/route.types.ts
Normal file
54
src/modules/geography/core/domain/route.types.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { GeorouterPort } from '../application/ports/georouter.port';
|
||||
import { GeorouterSettings } from '../application/types/georouter-settings.type';
|
||||
import { SpacetimePointProps } from './value-objects/timepoint.value-object';
|
||||
import { WaypointProps } from './value-objects/waypoint.value-object';
|
||||
|
||||
// All properties that a Route has
|
||||
export interface RouteProps {
|
||||
name: string;
|
||||
distance: number;
|
||||
duration: number;
|
||||
fwdAzimuth: number;
|
||||
backAzimuth: number;
|
||||
distanceAzimuth: number;
|
||||
waypoints: WaypointProps[];
|
||||
spacetimePoints: SpacetimePointProps[];
|
||||
}
|
||||
|
||||
// Properties that are needed for a Route creation
|
||||
export interface CreateRouteProps {
|
||||
roles: Role[];
|
||||
waypoints: WaypointProps[];
|
||||
georouter: GeorouterPort;
|
||||
georouterSettings: GeorouterSettings;
|
||||
}
|
||||
|
||||
export type Path = {
|
||||
type: PathType;
|
||||
points: Point[];
|
||||
};
|
||||
|
||||
export type Point = {
|
||||
lon: number;
|
||||
lat: number;
|
||||
context?: PointContext;
|
||||
};
|
||||
|
||||
export enum Role {
|
||||
DRIVER = 'DRIVER',
|
||||
PASSENGER = 'PASSENGER',
|
||||
}
|
||||
|
||||
export enum PointContext {
|
||||
HOUSE_NUMBER = 'HOUSE_NUMBER',
|
||||
STREET_ADDRESS = 'STREET_ADDRESS',
|
||||
LOCALITY = 'LOCALITY',
|
||||
VENUE = 'VENUE',
|
||||
OTHER = 'OTHER',
|
||||
}
|
||||
|
||||
export enum PathType {
|
||||
COMMON = 'common',
|
||||
DRIVER = 'driver',
|
||||
PASSENGER = 'passenger',
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { ArgumentInvalidException, ValueObject } from '@mobicoop/ddd-library';
|
||||
|
||||
/** Note:
|
||||
* Value Objects with multiple properties can contain
|
||||
* other Value Objects inside if needed.
|
||||
* */
|
||||
|
||||
export interface SpacetimePointProps {
|
||||
lon: number;
|
||||
lat: number;
|
||||
duration: number;
|
||||
distance: number;
|
||||
}
|
||||
|
||||
export class SpacetimePoint extends ValueObject<SpacetimePointProps> {
|
||||
get lon(): number {
|
||||
return this.props.lon;
|
||||
}
|
||||
|
||||
get lat(): number {
|
||||
return this.props.lat;
|
||||
}
|
||||
|
||||
get duration(): number {
|
||||
return this.props.duration;
|
||||
}
|
||||
|
||||
get distance(): number {
|
||||
return this.props.distance;
|
||||
}
|
||||
|
||||
protected validate(props: SpacetimePointProps): void {
|
||||
if (props.duration < 0)
|
||||
throw new ArgumentInvalidException(
|
||||
'duration must be greater than or equal to 0',
|
||||
);
|
||||
if (props.distance < 0)
|
||||
throw new ArgumentInvalidException(
|
||||
'distance must be greater than or equal to 0',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
ArgumentInvalidException,
|
||||
ArgumentOutOfRangeException,
|
||||
ValueObject,
|
||||
} from '@mobicoop/ddd-library';
|
||||
import { PointContext } from '../route.types';
|
||||
|
||||
/** Note:
|
||||
* Value Objects with multiple properties can contain
|
||||
* other Value Objects inside if needed.
|
||||
* */
|
||||
|
||||
export interface WaypointProps {
|
||||
position: number;
|
||||
lon: number;
|
||||
lat: number;
|
||||
context?: PointContext;
|
||||
}
|
||||
|
||||
export class Waypoint extends ValueObject<WaypointProps> {
|
||||
get position(): number {
|
||||
return this.props.position;
|
||||
}
|
||||
|
||||
get lon(): number {
|
||||
return this.props.lon;
|
||||
}
|
||||
|
||||
get lat(): number {
|
||||
return this.props.lat;
|
||||
}
|
||||
|
||||
get context(): PointContext {
|
||||
return this.props.context;
|
||||
}
|
||||
|
||||
protected validate(props: WaypointProps): void {
|
||||
if (props.position < 0)
|
||||
throw new ArgumentInvalidException(
|
||||
'position must be greater than or equal to 0',
|
||||
);
|
||||
if (props.lon > 180 || props.lon < -180)
|
||||
throw new ArgumentOutOfRangeException('lon must be between -180 and 180');
|
||||
if (props.lat > 90 || props.lat < -90)
|
||||
throw new ArgumentOutOfRangeException('lat must be between -90 and 90');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user