241 lines
10 KiB
Markdown
241 lines
10 KiB
Markdown
# Mobicoop V3 - Matcher
|
|
|
|
Mobility matching service for Mobicoop V3.
|
|
|
|
## Requirements
|
|
|
|
You need [Docker](https://docs.docker.com/engine/) and its [compose](https://docs.docker.com/compose/) plugin.
|
|
|
|
You also need NodeJS installed locally : we **strongly** advise to install [Node Version Manager](https://github.com/nvm-sh/nvm) and use the latest LTS version of Node (check that your local version matches with the one used in the Dockerfile).
|
|
|
|
The API will run inside a docker container, **but** the install itself is made outside the container, because during development we need tools that need to be available locally (eg. ESLint or Prettier with fix-on-save).
|
|
|
|
A RabbitMQ instance is also required to send / receive messages when data has been inserted/updated/deleted.
|
|
|
|
# Installation
|
|
|
|
- copy `.env.dist` to `.env` :
|
|
|
|
```bash
|
|
cp .env.dist .env
|
|
```
|
|
|
|
Modify it if needed.
|
|
|
|
- install the dependencies :
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
- start the containers :
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
The app runs automatically on port **5005**.
|
|
|
|
## Database migration
|
|
|
|
Before using the app, you need to launch the database migration (it will be launched inside the container) :
|
|
|
|
```bash
|
|
npm run migrate
|
|
```
|
|
|
|
## Usage
|
|
|
|
The app exposes the following [gRPC](https://grpc.io/) services :
|
|
|
|
- **Match** : find matching ads corresponding to the given criteria
|
|
|
|
For example, as a passenger, to search for drivers for a punctual carpool :
|
|
|
|
```json
|
|
{
|
|
"driver": false,
|
|
"passenger": true,
|
|
"frequency": "PUNCTUAL",
|
|
"algorithmType": "PASSENGER_ORIENTED",
|
|
"fromDate": "2024-06-05",
|
|
"toDate": "2024-06-05",
|
|
"schedule": [
|
|
{
|
|
"time": "07:30"
|
|
}
|
|
],
|
|
"waypoints": [
|
|
{
|
|
"houseNumber": "23",
|
|
"street": "rue de viller",
|
|
"postalCode": "54300",
|
|
"locality": "Lunéville",
|
|
"lon": 6.490527,
|
|
"lat": 48.590119,
|
|
"country": "France",
|
|
"position": 0
|
|
},
|
|
{
|
|
"houseNumber": "3",
|
|
"street": "rue du passage",
|
|
"postalCode": "67117",
|
|
"locality": "Ittenheim",
|
|
"lon": 7.594361,
|
|
"lat": 48.603004,
|
|
"country": "France",
|
|
"position": 1
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
As a passenger, to search for drivers for a recurrent carpool :
|
|
|
|
```json
|
|
{
|
|
"driver": false,
|
|
"passenger": true,
|
|
"frequency": "RECURRENT",
|
|
"algorithmType": "PASSENGER_ORIENTED",
|
|
"fromDate": "2024-01-02",
|
|
"toDate": "2024-06-30",
|
|
"strict": true,
|
|
"page": 1,
|
|
"perPage": 5,
|
|
"schedule": [
|
|
{
|
|
"day": 1,
|
|
"time": "07:30"
|
|
},
|
|
{
|
|
"day": 2,
|
|
"time": "07:45"
|
|
},
|
|
{
|
|
"day": 4,
|
|
"time": "07:30"
|
|
},
|
|
,
|
|
{
|
|
"day": 5,
|
|
"time": "07:30"
|
|
}
|
|
],
|
|
"waypoints": [
|
|
{
|
|
"houseNumber": "298",
|
|
"street": "Aveue de la liberté",
|
|
"postalCode": "86180",
|
|
"locality": "Buxerolles",
|
|
"lon": 0.364394,
|
|
"lat": 46.607501,
|
|
"country": "France",
|
|
"position": 0
|
|
},
|
|
{
|
|
"houseNumber": "1",
|
|
"street": "place du 8 mai 1945",
|
|
"postalCode": "47310",
|
|
"locality": "Roquefort",
|
|
"lon": 0.559606,
|
|
"lat": 44.175994,
|
|
"country": "France",
|
|
"position": 1
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
The list of possible criteria :
|
|
|
|
- **id** (optional): the id of a previous matching result (as a uuid)
|
|
- **driver** (boolean, optional): to search for passengers (_default : false_)
|
|
- **passenger** (boolean, optional): to search fo drivers (_default : true_)
|
|
- **frequency**: the frequency of the search (`PUNCTUAL` or `RECURRENT`)
|
|
- **strict** (boolean, optional): if set to true, allow matching only with similar frequency ads (_default : false_)
|
|
- **fromDate**: start date for recurrent ad, carpool date for punctual ad
|
|
- **toDate**: end date for recurrent ad, same as fromDate for punctual ad
|
|
- **schedule**: an array of schedule items, a schedule item containing :
|
|
- the week day as a number, from 0 (sunday) to 6 (saturday) if the ad is recurrent (default to fromDate day for punctual search)
|
|
- the departure time (as HH:MM)
|
|
- the margin around the departure time in seconds (optional) (_default : 900_)
|
|
- **seatsProposed** (integer, optional): number of seats proposed as driver (_default : 3_)
|
|
- **seatsRequested** (integer, optional): number of seats requested as passenger (_default : 1_)
|
|
- **waypoints**: an array of addresses that represent the waypoints of the journey (only first and last waypoints are used for passenger ads). Note that positions are **required** and **must** be consecutives
|
|
- **algorithmType** (optional): the type of algorithm to use (as of 2023-09-28, only the default `PASSENGER_ORIENTED` is accepted)
|
|
- **remoteness** (integer, optional): an integer to indicate the maximum flying distance (in metres) between the driver route and the passenger pick-up / drop-off points (_default : 15000_)
|
|
- **useProportion** (boolean, optional): a boolean to indicate if the matching algorithm will compare the distance of the passenger route against the distance of the driver route (_default : 1_). Works in combination with **proportion** parameter
|
|
- **proportion** (float, optional): a fraction (float between 0 and 1) to indicate minimum proportion of the distance of the passenger route against the distance of the driver route (_default : 0.3_). Works in combination with **use_proportion** parameter
|
|
- **useAzimuth** (boolean, optional): a boolean to indicate if the matching algorithm will use the azimuth of the driver and passenger routes (_default : 1_)
|
|
- **azimuthMargin** (integer, optional): an integer (representing the number of degrees) to indicate the range around the opposite azimuth to consider the candidate route excluded (_default : 10_)
|
|
- **maxDetourDistanceRatio** (float, optional): a fraction (float between 0 and 1) of the driver route distance to indicate the maximum detour distance acceptable for a passenger (_default : 0.3_)
|
|
- **maxDetourDurationRatio** (float, optional): a fraction (float between 0 and 1) of the driver route duration to indicate the maximum detour duration acceptable for a passenger (_default : 0.3_)
|
|
- **page** (integer, optional): the page of results to display (_default : 1_)
|
|
- **perPage** (integer, optional): the number of results to display per page (_default : 10_)
|
|
|
|
If the matching is successful, you will get a result, containing :
|
|
|
|
- **id**: the id of the matching; as matching is a time-consuming process, results are cached and thus accessible later using this id (pagination works as well !)
|
|
- **total**: the total number of results
|
|
- **page**: the number of the page that is returned (may be different than the number of the required page, if number of results does not match with perPage parameter)
|
|
- **perPage**: the number of results per page (as it may not be specified in the request)
|
|
- **data**: an array of the results themselves, each including:
|
|
- **id**: an id for the result
|
|
- **adId**: the id of the ad that matches
|
|
- **role**: the role of the ad owner in that match
|
|
- **distance**: the distance in metres of the resulting carpool
|
|
- **duration**: the duration in seconds of the resulting carpool
|
|
- **initialDistance**: the initial distance in metres for the driver
|
|
- **initialDuration**: the initial duration in seconds for the driver
|
|
- **distanceDetour**: the detour distance in metres
|
|
- **durationDetour**: the detour duration in seconds
|
|
- **distanceDetourPercentage**: the detour distance in percentage of the original distance
|
|
- **durationDetourPercentage**: the detour duration in percentage of the original duration
|
|
- **journeys**: the possible journeys for the carpool (one journey for punctual carpools, one or more journeys for recurrent carpools), each including:
|
|
- **day**: the week day for the journey, as a number, from 0 (sunday) to 6 (saturday)
|
|
- **firstDate**: the first possible date for the journey
|
|
- **lastDate**: the last possible date for the journey
|
|
- **steps**: the steps of the journey (coordinates with distance, duration and actors implied), each including:
|
|
- **distance**: the distance to reach the step in metres
|
|
- **duration**: the duration to reach the step in seconds
|
|
- **lon**: the longitude of the point for the step
|
|
- **lat**: the longitude of the point for the step
|
|
- **time**: the driver time at that step
|
|
- **actors**: the actors for that step:
|
|
- **role**: the role of the actor (`DRIVER` or `PASSENGER`)
|
|
- **target**: the meaning of the step for the actor:
|
|
- _START_ for the first point of the actor
|
|
- _FINISH_ for the last point of the actor
|
|
- _INTERMEDIATE_ for a driver intermediate point
|
|
- _NEUTRAL_ for a passenger point from the point of view of a driver
|
|
|
|
## Tests / ESLint / Prettier
|
|
|
|
Tests are run outside the container for ease of use (switching between different environments inside containers using prisma is complicated and error prone).
|
|
The integration tests use a dedicated database (see _db-test_ section of _docker-compose.yml_).
|
|
|
|
```bash
|
|
# run all tests (unit + integration)
|
|
npm run test
|
|
|
|
# unit tests only
|
|
npm run test:unit
|
|
|
|
# integration tests only
|
|
npm run test:integration
|
|
|
|
# coverage
|
|
npm run test:cov
|
|
|
|
# ESLint
|
|
npm run lint
|
|
|
|
# Prettier
|
|
npm run pretty
|
|
```
|
|
|
|
## License
|
|
|
|
Mobicoop V3 - Matcher Service is [AGPL licensed](LICENSE).
|