{"id":25833259,"url":"https://github.com/rezi-gelenidze/route-smart","last_synced_at":"2026-07-02T10:31:55.376Z","repository":{"id":245489477,"uuid":"806106025","full_name":"rezi-gelenidze/route-smart","owner":"rezi-gelenidze","description":"Logistics optimization system designed to match parcels with trips and vice versa in Georgia. Using graph theory and the A* algorithm, it ensures efficient routing and delivery.","archived":false,"fork":false,"pushed_at":"2025-04-22T11:55:32.000Z","size":6044,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-24T19:31:04.014Z","etag":null,"topics":["graph-algorithms","leaflet","matching","postgis","react","spring"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rezi-gelenidze.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-05-26T11:50:22.000Z","updated_at":"2025-06-16T18:58:09.000Z","dependencies_parsed_at":"2024-06-22T11:29:13.492Z","dependency_job_id":"005e0073-0563-4aae-b0a0-3504dcea59e4","html_url":"https://github.com/rezi-gelenidze/route-smart","commit_stats":null,"previous_names":["rezi-gelenidze/route-smart","rgelenidze-godaddy/route-smart"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rezi-gelenidze/route-smart","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezi-gelenidze%2Froute-smart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezi-gelenidze%2Froute-smart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezi-gelenidze%2Froute-smart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezi-gelenidze%2Froute-smart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rezi-gelenidze","download_url":"https://codeload.github.com/rezi-gelenidze/route-smart/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezi-gelenidze%2Froute-smart/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35043933,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graph-algorithms","leaflet","matching","postgis","react","spring"],"created_at":"2025-02-28T22:47:35.404Z","updated_at":"2026-07-02T10:31:55.352Z","avatar_url":"https://github.com/rezi-gelenidze.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Route Smart (v1.0-alpha) 🚚\n\nRoute Smart is a powerful algorithm designed to efficiently match senders (with parcels or autostop persons) and\nshippers (with trips) in Georgia. This solution leverages graph-based pathfinding to provide optimal matches, ensuring\nthat parcels can find appropriate trips and vice versa.\n\n## Table of Contents\n\n1. [Problem Statement](#problem-statement)\n2. [Solution Overview](#solution-overview)\n3. [Data Model](#data-model)\n4. [Pathfinding](#pathfinding)\n5. [Matching](#matching)\n6. [Precomputing Paths](#precomputing-paths)\n7. [Querying The Results](#querying-the-results)\n8. [API Endpoints](#api-endpoints)\n9. [Running the Application](#running-the-application)\n10. [Running the Application without docker (Not recommended)](#running-the-application-without-docker-not-recommended)\n11. [Conclusion](#conclusion)\n\n## Problem Statement 🔴\n\nIn a logistics network, we often encounter the challenge of matching parcels with trips and trips with parcels. The goal\nis to ensure that parcels can be transported from their origin to their destination by finding compatible trips that\npass through their route. Similarly, trips should be able to find parcels along their path to maximize efficiency and\nutilization.\n\n## Solution Overview 💡\n\nThe solution involves several key steps:\n\n1. **Data Model**: Representing destinations and routes as a graph.\n2. **Pathfinding**: Implementing the A* search algorithm to find optimal paths.\n3. **Matching**: Matching parcels with trips and trips with parcels based on the computed paths.\n4. **Querying**: Efficiently querying the results to provide matches.\n\n## Data Model 🗺️\n\n### Destinations\n\nThe system covers major destinations in Georgia (96 in total), each represented as a node in the graph. These\ndestinations include cities and towns mapped with unique identifiers (1-96 Primary Key).\n\nI assembled the map on Google Maps and then continued working on it in QGIS. I calculated complexity of the routes (by\ngeographical environment and road quality) and road (non-linear) distance between nodes using google maps. I exported\nthe map as a GeoJSON file and imported it into the database using the PostGIS extension (PostgreSQL with geospatial\ncapabilities).\n\n![](./docs/map.png)\n*Map of Georgia with Destinations, Apkhazia and Samachablo is not drawn as logistics is temporarily disabled due to Russian\noccupation.*\n\n[View Map on Google Maps](https://www.google.com/maps/d/u/0/edit?mid=1bXmfwIW-t9tvpHyvGA0sK_kCt-5noVE)\n\n### Graph Representation\n\nEach destination (node) is connected to other destinations via edges. These edges are weighted with the distance and\ncomplexity of the route. The graph is represented as an adjacency list where each node has a list of tuples representing\nits neighbors, the distance to them, and the complexity of the route.\n\n```java\npublic class Node {\n    private Long id;\n    private String name;\n    private Point geom; // Geometry point for location\n}\n\npublic class Edge {\n    private Long id;\n    private Node fromNode;\n    private Node toNode;\n    private double distance;\n    private int complexity;\n    private LineString geom; // Geometry line for route\n}\n\npublic class PrecomputedPath {\n    private Long id;\n    private Node startNode;\n    private Node endNode;\n    private String path; // Comma-separated sequence list of node IDs\n    private double totalDistance;\n    private double averageComplexity;\n}\n```\n\n## Pathfinding 🧭\n\n### A* Search Algorithm\n\nThe A* search algorithm is used to find the best possible routes from a start to an end destination. This algorithm\ncombines the strengths of Dijkstra's algorithm and Greedy Best-First-Search. It uses a heuristic function (Euclidean\ndistance) and road complexity and road (non-linear) distance from A to B constraints to estimate the cost from the\ncurrent node to the destination.\n\n## Matching 🚚📦\n\n### Matching Trips with Parcels\n\nWhen a trip is created, the system needs to find all parcels that can be picked up along the trip's route. The algorithm\nchecks if the parcel's route is a subpath of any of the precomputed paths for the trip.\n\n### Matching Parcels with Trips\n\nSimilarly, when a parcel is created, the system finds all trips that can transport the parcel along their route. The\nalgorithm checks if the trip's route contains the parcel's route as a subpath.\n\n## Precomputing Paths\n\nTo optimize the matching process, the system precomputes all possible paths between destinations. This ensures that the\nmatching algorithm can quickly find the best possible routes without having to compute them on the fly. (Memoization)\n\n## Querying The Results\n\nThe system uses optimized SQL queries to efficiently find matching trips and parcels. This ensures that the results are\nreturned quickly and accurately.\n\n## API Endpoints\n\n### Matching Controller\n\n#### Match Trips with Parcels\n\n**GET /match/trip/**\n\nQuery Parameters:\n\n- `fromId` (Long, optional): ID of the starting node.\n- `fromDisplay` (String, optional): Display name of the starting node.\n- `toId` (Long, optional): ID of the ending node.\n- `toDisplay` (String, optional): Display name of the ending node.\n- `verbose` (Boolean, optional, default: false): Verbose flag.\n\nResponse:\n\n- List of matching parcels.\n\n#### Create Trip\n\n**POST /match/trip/**\n\nRequest Body:\n\n- `CreateTripDTO`: DTO containing `identifier`, `fromId`, and `toId`.\n\nResponse:\n\n- `Trip`: The created trip object.\n\n#### Match Trip with Parcels by ID\n\n**GET /match/trip/{tripId}**\n\nPath Parameters:\n\n- `tripId` (Long): ID of the trip.\n\nQuery Parameters:\n\n- `verbose` (Boolean, optional, default: false): Verbose flag.\n\nResponse:\n\n- List of matching parcels.\n\n#### Delete Trip\n\n**DELETE /match/trip/{tripId}**\n\nPath Parameters:\n\n- `tripId` (Long): ID of the trip.\n\nResponse:\n\n- HTTP 204 No Content.\n\n#### Match Parcels with Trips\n\n**GET /match/parcel/**\n\nQuery Parameters:\n\n- `fromId` (Long, optional): ID of the starting node.\n- `fromDisplay` (String, optional): Display name of the starting node.\n- `toId` (Long, optional): ID of the ending node.\n- `toDisplay` (String, optional): Display name of the ending node.\n- `verbose` (Boolean, optional, default: false): Verbose flag.\n\nResponse:\n\n- List of matching trips.\n\n#### Create Parcel\n\n**POST /match/parcel/**\n\nRequest Body:\n\n- `CreateParcelDTO`: DTO containing `identifier`, `fromId`, and `toId`.\n\nResponse:\n\n- `Parcel`: The created parcel object.\n\n#### Match Parcel with Trips by ID\n\n**GET /match/parcel/{parcelId}**\n\nPath Parameters:\n\n- `parcelId` (Long): ID of the parcel.\n\nQuery Parameters:\n\n- `verbose` (Boolean, optional, default: false): Verbose flag.\n\nResponse:\n\n- List of matching trips.\n\n#### Delete Parcel\n\n**DELETE /match/parcel/{parcelId}**\n\nPath Parameters:\n\n- `parcelId` (Long): ID of the parcel.\n\nResponse:\n\n- HTTP 204 No Content.\n\n## Running the Application\n\nHere is the guide to install Docker, Docker Compose, and run your application using `docker-compose up --build`.\n\n#### Step 1: Install Docker\n\n#### Step 2: Install Docker Compose\n\n#### Step 3: Preparation\n\n1. Ensure that you have the project files (`Dockerfile`, `docker-compose.yml`, `entrypoint.sh`, `.env`, etc.) in your\n   project directory.\n2. Create the `.env` file in your project directory with the following content:\n\n```plaintext\nPOSTGRES_DB=route_smart_db\nPOSTGRES_USER=routesmart_app\nPOSTGRES_PASSWORD=app_password\nPOSTGRES_HOST=db\nPOSTGRES_PORT=5432\n```\n\n#### Step 4: Build and Run the Application\n\n1. Open a terminal (Command Prompt, PowerShell, or terminal in Linux/Mac).\n2. Navigate to the project directory where your `docker-compose.yml` is located.\n3. Run the following command to build and start the containers:\n\n```sh\ndocker-compose up --build\n```\n\nThis command will:\n\n- Build the Docker images for your application and the database.\n- Start the containers defined in the `docker-compose.yml` file.\n- Run the necessary database seeding and precomputing steps defined in the `entrypoint.sh` script.\n\n#### Step 3: Verify the Application\n\n1. Once the containers are up and running, open a web browser.\n2. Navigate to `http://localhost:8080` to access your application.\n3. You can use the provided API endpoints to interact with the application.\n\n#### Stopping the Application\n\nTo stop the application, press `Ctrl + C` in the terminal where the application is running. This will stop the\ncontainers.\n\nAlternatively, you can stop the containers using the following command in your project directory:\n\n```sh\ndocker-compose down\n```\n\nThis command will stop and remove the containers defined in the `docker-compose.yml` file.\n\n## Running the Application without docker (Not recommended)\n\n### Prerequisites\n\n- Java 17\n- Maven\n- Spring Boot\n- PostGIS-enabled PostgreSQL running on localhost:5432\n\n### Running the Application with Command Line Arguments\n\nRun the following command to start the application:\n\n```sh\nmvn spring-boot:run\n```\n\nTo seed the edges and nodes (edges.geojson and nodes.geojson must be present in the resources folder):\n\n```sh\nmvn spring-boot:run -Dspring-boot.run.arguments=seed\n```\n\nTo seed random parcels and trips:\n\n```sh\nmvn spring-boot:run -Dspring-boot.run.arguments=seed-dummy\n```\n\nTo precompute paths (Memoization step for optimized pathfinding):\n\n```sh\nmvn spring-boot:run -Dspring-boot.run.arguments=precompute\n```\n\n## Conclusion\n\nRoute Smart is a comprehensive solution for efficiently matching parcels with trips and vice versa. By leveraging\ngraph-based pathfinding and optimized querying, it ensures that logistics operations are streamlined and efficient. This\nsystem was first prototyped in Python and then implemented in Spring Boot for enhanced performance and scalability.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frezi-gelenidze%2Froute-smart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frezi-gelenidze%2Froute-smart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frezi-gelenidze%2Froute-smart/lists"}