Gán điểm kết thúc của chặng trước làm điểm khởi hành của chặng sau
This commit is contained in:
@@ -383,20 +383,57 @@ class RoutingController {
|
||||
|
||||
@Post('optimize/:legId')
|
||||
async optimize(@Param('legId', ParseUUIDPipe) legId: string) {
|
||||
const currentLeg = await this.prisma.leg.findUnique({
|
||||
where: { id: legId },
|
||||
});
|
||||
if (!currentLeg) throw new NotFoundException('Không tìm thấy chặng');
|
||||
|
||||
const locations = await this.prisma.location.findMany({
|
||||
where: { legId },
|
||||
});
|
||||
|
||||
if (locations.length <= 2) return locations;
|
||||
if (locations.length === 0) return { locations: [], totalDistance: 0 };
|
||||
|
||||
// KHAI BÁO startAnchor ở đầu hàm để tránh lỗi scope TS2304
|
||||
let startAnchor: any = null;
|
||||
|
||||
// Tìm địa điểm cuối cùng của chặng trước đó
|
||||
const prevLeg = await this.prisma.leg.findFirst({
|
||||
where: {
|
||||
tourId: currentLeg.tourId,
|
||||
sequence: currentLeg.sequence - 1
|
||||
},
|
||||
include: { locations: { orderBy: { plannedStart: 'asc' } } }
|
||||
});
|
||||
|
||||
if (prevLeg?.locations?.length) {
|
||||
startAnchor = prevLeg.locations[prevLeg.locations.length - 1];
|
||||
}
|
||||
|
||||
if (locations.length <= 2 && !startAnchor) return { locations, totalDistance: 0 };
|
||||
|
||||
// Thuật toán Greedy TSP đơn giản để tối ưu hóa lộ trình
|
||||
const optimized = [];
|
||||
const unvisited = [...locations];
|
||||
|
||||
// Bắt đầu với địa điểm có thời gian dự kiến sớm nhất hiện tại
|
||||
let current = unvisited.sort((a, b) =>
|
||||
(a.plannedStart?.getTime() || 0) - (b.plannedStart?.getTime() || 0)
|
||||
).shift()!;
|
||||
let current: any;
|
||||
if (startAnchor) {
|
||||
let nearestIdx = 0;
|
||||
let minDist = Infinity;
|
||||
for (let i = 0; i < unvisited.length; i++) {
|
||||
const d = calculateDistance(startAnchor.latitude, startAnchor.longitude, unvisited[i].latitude, unvisited[i].longitude);
|
||||
if (d < minDist) {
|
||||
minDist = d;
|
||||
nearestIdx = i;
|
||||
}
|
||||
}
|
||||
current = unvisited.splice(nearestIdx, 1)[0];
|
||||
} else {
|
||||
current = unvisited.sort((a, b) =>
|
||||
(a.plannedStart?.getTime() || 0) - (b.plannedStart?.getTime() || 0)
|
||||
).shift()!;
|
||||
}
|
||||
optimized.push(current);
|
||||
|
||||
while (unvisited.length > 0) {
|
||||
@@ -416,6 +453,15 @@ class RoutingController {
|
||||
|
||||
// Tính toán tổng quãng đường di chuyển của chặng (km)
|
||||
let totalDistance = 0;
|
||||
|
||||
// Cộng thêm quãng đường từ chặng trước nối sang chặng này
|
||||
if (startAnchor) {
|
||||
totalDistance += calculateDistance(
|
||||
startAnchor.latitude, startAnchor.longitude,
|
||||
optimized[0].latitude, optimized[0].longitude
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < optimized.length - 1; i++) {
|
||||
totalDistance += calculateDistance(
|
||||
optimized[i].latitude, optimized[i].longitude,
|
||||
|
||||
Reference in New Issue
Block a user