fix: tạm dừng thuật toán tìm đường đi
This commit is contained in:
@@ -640,7 +640,7 @@ export const TourDetailPage = ({
|
||||
const coordsString = `${p1.longitude},${p1.latitude};${p2.longitude},${p2.latitude}`;
|
||||
|
||||
segmentPromises.push(
|
||||
fetch(`https://router.project-osrm.org/route/v1/${travelMode}/${coordsString}?overview=full&geometries=geojson&alternatives=true`)
|
||||
fetch(`https://router.project-osrm.org/route/v1/${travelMode}/${coordsString}?overview=full&geometries=geojson&alternatives=3`) // Yêu cầu tối đa 5 phương án thay thế cho mỗi phân đoạn
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error(`OSRM API error: ${res.status}`);
|
||||
return res.json();
|
||||
@@ -674,14 +674,24 @@ export const TourDetailPage = ({
|
||||
|
||||
const overallAlternativeRoutes: OSRMRoute[] = [];
|
||||
// Limit overall alternatives based on the number of alternatives for the first segment, up to 3
|
||||
const maxOverallAlternatives = Math.min(3, allSegmentAlternatives[0]?.length || 1);
|
||||
const maxOverallAlternativesToGenerate = 3; // Số lượng lộ trình tổng thể muốn tạo
|
||||
|
||||
for (let altIdx = 0; altIdx < maxOverallAlternatives; altIdx++) {
|
||||
const selectedSegmentIndices: number[] = allSegmentAlternatives.map((_, segIdx) =>
|
||||
segIdx === 0 ? altIdx : 0 // Use altIdx for first segment, 0 for others
|
||||
// Heuristic để tạo các lộ trình tổng thể đa dạng hơn:
|
||||
// 1. Lộ trình chính (fastest/default cho tất cả các phân đoạn)
|
||||
const primarySegmentIndices = allSegmentAlternatives.map(() => 0);
|
||||
const primaryCombinedRoute = combineSegmentRoutes(allSegmentAlternatives, primarySegmentIndices);
|
||||
if (primaryCombinedRoute) {
|
||||
overallAlternativeRoutes.push(primaryCombinedRoute);
|
||||
}
|
||||
|
||||
// 2. Các lộ trình thay thế: Thử kết hợp các phương án thay thế từ các phân đoạn
|
||||
// Ví dụ: Lấy phương án thứ N của mỗi phân đoạn (nếu có), hoặc phương án 0 nếu không có
|
||||
for (let altChoice = 1; altChoice < maxOverallAlternativesToGenerate; altChoice++) {
|
||||
const selectedSegmentIndices: number[] = allSegmentAlternatives.map(segmentAlts =>
|
||||
Math.min(altChoice, segmentAlts.length - 1) // Chọn phương án thứ 'altChoice', hoặc phương án cuối cùng nếu không đủ
|
||||
);
|
||||
const combinedRoute = combineSegmentRoutes(allSegmentAlternatives, selectedSegmentIndices);
|
||||
if (combinedRoute) {
|
||||
if (combinedRoute && !overallAlternativeRoutes.some(r => JSON.stringify(r.geometry.coordinates) === JSON.stringify(combinedRoute.geometry.coordinates))) {
|
||||
overallAlternativeRoutes.push(combinedRoute);
|
||||
}
|
||||
}
|
||||
@@ -711,6 +721,33 @@ export const TourDetailPage = ({
|
||||
}
|
||||
}, [selectedRouteIndex, routes]);
|
||||
|
||||
// Tính toán thông tin hiển thị cho lộ trình đang chọn để đề xuất cho người dùng
|
||||
const selectedRouteInfo = useMemo(() => {
|
||||
if (!routes || routes.length === 0 || !routes[selectedRouteIndex]) return null;
|
||||
const r = routes[selectedRouteIndex];
|
||||
|
||||
// Định dạng thời gian di chuyển
|
||||
const duration = r.duration;
|
||||
const hours = Math.floor(duration / 3600);
|
||||
const minutes = Math.round((duration % 3600) / 60);
|
||||
const durationStr = hours > 0 ? `${hours}h${minutes}p` : `${minutes}p`;
|
||||
|
||||
// Xác định nhãn đề xuất: Index 0 thường là lộ trình tối ưu nhất của OSRM (thông dụng nhất)
|
||||
// Kiểm tra thêm nếu đây là lộ trình ngắn nhất trong các phương án
|
||||
const isShortest = routes.length > 1 && r.distance === Math.min(...routes.map(rt => rt.distance));
|
||||
|
||||
let label = "Lộ trình";
|
||||
if (selectedRouteIndex === 0) label = "Đề xuất";
|
||||
else if (isShortest) label = "Ngắn nhất";
|
||||
else label = `Lựa chọn ${selectedRouteIndex + 1}`;
|
||||
|
||||
return {
|
||||
distance: (r.distance / 1000).toFixed(1),
|
||||
duration: durationStr,
|
||||
label
|
||||
};
|
||||
}, [routes, selectedRouteIndex]);
|
||||
|
||||
useEffect(() => {
|
||||
if (initialViewState) {
|
||||
setMapCenter(initialViewState.center);
|
||||
@@ -1391,6 +1428,22 @@ export const TourDetailPage = ({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Overlay thông tin lộ trình đề xuất (Lộ trình thông dụng nhất) */}
|
||||
{selectedRouteInfo && drivingRoute.length > 0 && (
|
||||
<div className="absolute top-3 left-1/2 -translate-x-1/2 z-[1001] bg-white/80 backdrop-blur-md px-4 py-2 rounded-2xl shadow-xl border border-white flex items-center gap-3 animate-in fade-in slide-in-from-top-2 duration-500">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Navigation className="w-3.5 h-3.5 text-blue-600 rotate-45" />
|
||||
<span className="text-[10px] font-black text-gray-400 uppercase tracking-tighter">{selectedRouteInfo.label}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs font-bold text-blue-700 whitespace-nowrap">
|
||||
<span>{selectedRouteInfo.distance} km</span>
|
||||
<span className="text-gray-300">•</span>
|
||||
<span>{selectedRouteInfo.duration}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<MapContainer
|
||||
center={initialViewState?.center || mapCenter}
|
||||
zoom={mapZoom}
|
||||
@@ -1647,6 +1700,7 @@ export const TourDetailPage = ({
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => { setSelectedRouteIndex(idx); setIsMapControlsOpen(false); }}
|
||||
title={`${(route.distance / 1000).toFixed(1)} km - ${Math.round(route.duration / 60)}p`}
|
||||
className={`w-8 h-8 flex items-center justify-center rounded-lg transition-all border ${
|
||||
selectedRouteIndex === idx
|
||||
? 'bg-blue-600 text-white border-blue-600 shadow-sm'
|
||||
|
||||
Reference in New Issue
Block a user