matcher/README.md

241 lines
10 KiB
Markdown
Raw Normal View History

2023-04-06 09:12:49 +00:00
# Mobicoop V3 - Matcher
2023-04-06 06:57:21 +00:00
2023-04-06 09:12:49 +00:00
Mobility matching service for Mobicoop V3.
2023-04-06 06:57:21 +00:00
2023-04-06 09:12:49 +00:00
## Requirements
2023-04-06 06:57:21 +00:00
2023-04-06 09:12:49 +00:00
You need [Docker](https://docs.docker.com/engine/) and its [compose](https://docs.docker.com/compose/) plugin.
2023-04-06 06:57:21 +00:00
2023-04-06 09:12:49 +00:00
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).
2023-04-06 06:57:21 +00:00
2023-04-06 09:12:49 +00:00
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).
2023-09-28 14:31:26 +00:00
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).