
Một đơn hàng nằm gần kho A hơn trên bản đồ, nhưng kho A phải vòng qua cầu còn kho B có đường đi thẳng tới khách. Nếu chỉ so khoảng cách đường chim bay, hệ thống có thể phân đơn không phù hợp. API tính khoảng cách đường bộ giữa nhiều điểm giúp đặt các phương án cạnh nhau: từ từng kho đến từng khách mất bao nhiêu mét và bao nhiêu giây theo tuyến tính được.
TrackAsia Distance Matrix v1 nhận loại phương tiện, danh sách tọa độ và chỉ số điểm nguồn, điểm đích.[2] Phần dễ sai trong triển khai thường nằm ở việc ghép kết quả về đúng mã kho, mã đơn. Một bảng số hoàn toàn hợp lệ vẫn dẫn tới quyết định sai nếu hàng và cột bị gắn nhầm đối tượng.
Trước hết cần bảng ba nhân tám hay mười một nhân mười một?
Giả sử có ba kho và tám khách, mỗi khách đều cần so với ba kho. Bạn cần 3 × 8 = 24 cặp kho–khách. Không cần tính cả kho với kho, khách với khách thành bảng 11 × 11. Đây là phép tính lượng dữ liệu cần dùng, chưa phải kết luận về số đơn vị bị tính phí.
Mỗi hàng ứng với một nguồn theo thứ tự yêu cầu; mỗi cột ứng với một đích. Hãy giữ mảng mã kho và mã khách ngay cạnh mảng tọa độ. Nếu sắp xếp lại một mảng sau khi tạo URL, cần dựng lại toàn bộ chỉ số tương ứng. Khi lưu kết quả, lưu kèm mã nghiệp vụ và loại phương tiện; đừng chỉ giữ một bảng số mà ý nghĩa phụ thuộc thứ tự mảng của lần chạy trước.
Ma trận vuông có ích khi bài toán sau đó cần chi phí đi lại giữa mọi điểm, chẳng hạn bộ tối ưu đang thử các thứ tự ghé khác nhau. Đó là nhu cầu khác với chọn kho phục vụ. Xác định quyết định cần hỗ trợ trước khi mặc định gửi tất cả nguồn và đích.
Khoảng cách và thời gian trả về có nghĩa gì?
Tài liệu Matrix v1 nói khoảng cách thuộc tuyến nhanh nhất, không nhất thiết tuyến ngắn nhất theo số kilômét. Khoảng cách tính bằng mét, thời gian tính bằng giây.[2] Vì vậy, tuyến 8 km đi 12 phút có thể là phương án được chọn dù có tuyến 6 km chậm hơn. Không nên ghi trong giao diện rằng đó là “số km nhỏ nhất có thể” nếu dịch vụ không cam kết như vậy.
Chiều A đến B cũng không nhất thiết bằng chiều B đến A. Đường một chiều, lối vào và hướng tiếp cận có thể tạo khác biệt. Giữ chiều di chuyển trong khóa lưu tạm và thử cả hai chiều nếu nghiệp vụ dùng cả hai. Sao chép nửa tam giác của ma trận sang nửa còn lại là giả định của ứng dụng, không phải bảo đảm của API.
Thời gian di chuyển chưa bao gồm đầy đủ bốc dỡ, chờ bảo vệ, nghỉ giữa ca hay khung giờ nhận hàng. Matrix cung cấp đầu vào lập kế hoạch; riêng một con số duration không phải giờ đến cam kết, cũng không chứng minh có dự báo giao thông trực tiếp. Nếu cần thời gian phụ thuộc giờ xuất phát, hãy xác nhận yêu cầu đó bằng tài liệu và thử nghiệm riêng.
Chọn loại xe và thứ tự tọa độ trước khi viết vòng lặp
Các profile được tài liệu liệt kê gồm car, moto, truck, walk.[2] Chọn loại phù hợp với chuyến đang đánh giá và lưu nó cùng kết quả. So một lần chạy xe máy với một lần chạy ô tô rồi quy mọi khác biệt cho chất lượng nhà cung cấp sẽ không cho kết luận hữu ích.
Có profile xe tải không đồng nghĩa đã có mọi tham số chiều cao, tổng tải trọng, hàng nguy hiểm hoặc giờ cấm đô thị. Các yêu cầu đó cần tham số được mô tả và kiểm tra theo xe thực tế. Người điều phối vẫn phải xác minh những hạn chế áp dụng cho phương tiện và chuyến đi.
Matrix dùng cặp kinh độ,vĩ độ trong đường dẫn. Trong khi đó, Directions v2 của TrackAsia mô tả tham số điểm đầu, điểm cuối theo vĩ độ,kinh độ.[2][10] Nên dùng đối tượng có tên {lng, lat} trong chương trình rồi chuyển đổi ở chỗ gọi dịch vụ. Mảng hai số không có nhãn rất dễ đi nhầm từ API này sang API khác.
Chạy một ví dụ kho–khách hoàn chỉnh
Lưu đoạn sau thành matrix.mjs, dùng Node.js 20 trở lên và chạy node matrix.mjs. Mẫu dùng khóa công khai có giới hạn để thử nhỏ; nếu dùng khóa tài khoản, đặt biến môi trường TRACKASIA_KEY. Tên kho, khách và các điểm là dữ liệu minh họa, không phải địa chỉ cơ sở kinh doanh đã xác minh.
const depots = [
{ id: 'depot-A', lng: 106.698, lat: 10.773 },
{ id: 'depot-B', lng: 106.720, lat: 10.795 }
];
const customers = [
{ id: 'customer-1', lng: 106.705, lat: 10.780 },
{ id: 'customer-2', lng: 106.710, lat: 10.785 }
];
const points = [...depots, ...customers];
for (const point of points) {
if (!Number.isFinite(point.lng) || !Number.isFinite(point.lat)
|| Math.abs(point.lng) > 180 || Math.abs(point.lat) > 90) {
throw new Error(`Invalid coordinate: ${point.id}`);
}
}
const coordinates = points.map(p => `${p.lng},${p.lat}`).join(';');
const url = new URL(`https://maps.track-asia.com/distance-matrix/v1/car/${coordinates}`);
url.search = new URLSearchParams({
sources: depots.map((_, i) => i).join(';'),
destinations: customers.map((_, i) => depots.length + i).join(';'),
annotations: 'distance,duration',
key: process.env.TRACKASIA_KEY || 'public_key'
});
const response = await fetch(url, { signal: AbortSignal.timeout(15000) });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
if (data.code !== 'Ok') throw new Error(`Matrix: ${data.code}`);
for (const table of [data.distances, data.durations]) {
if (!Array.isArray(table) || table.length !== depots.length
|| table.some(row => !Array.isArray(row) || row.length !== customers.length)) {
throw new Error('Unexpected matrix dimensions');
}
}
const pairs = depots.flatMap((depot, i) => customers.map((customer, j) => {
const metres = data.distances[i][j];
const seconds = data.durations[i][j];
const available = Number.isFinite(metres) && metres >= 0
&& Number.isFinite(seconds) && seconds >= 0;
return { depotId: depot.id, customerId: customer.id,
metres: available ? metres : null,
seconds: available ? seconds : null,
state: available ? 'routed' : 'unavailable' };
}));
console.table(pairs);
Đầu ra có hai hàng khoảng cách và hai hàng thời gian vì yêu cầu chọn hai kho và hai khách. Chương trình tạo bốn đối tượng nối số liệu về đúng mã nghiệp vụ. Giữ nguyên mét và giây khi tính toán; chỉ đổi sang km hoặc phút lúc hiển thị. Không cần chép một giá trị khoảng cách cố định làm kết quả mong đợi, vì dữ liệu đường đi của dịch vụ có thể được cập nhật.
Mẫu chủ động không bật fallback_speed. Nhờ vậy, quy tắc đơn giản là không dùng hành trình đường bộ không khả dụng để xếp hạng. Nếu khóa bị từ chối hoặc dịch vụ trả lỗi, chương trình dừng thay vì tạo một bảng trống rồi coi là thành công.
Thử với mã nguồn: So sánh kho bằng ma trận đường bộ
Gọi ma trận 2 kho × 2 khách hàng, đọc đủ bốn cặp theo mét và giây trước khi phân công kho.
Ví dụ gọi API dùng public_key giới hạn; ảnh chụp phiên chạy của mã nguồn bên dưới.
Giải nén ZIP, chạy python3 -m http.server 8080 trong thư mục vừa giải nén, rồi mở http://localhost:8080/index-vi.html. README tiếng Việt và tiếng Anh nằm trong ZIP; không cần npm hay bước build.

Ô không có tuyến tuyệt đối không được biến thành số không
Kiểm tra HTTP, code, kích thước từng bảng và từng ô trước khi chọn phương án. Trong JavaScript, Number(null) bằng 0; chuyển mọi giá trị qua Number() có thể vô tình làm một cặp không đi được trở thành hành trình hấp dẫn nhất. Ví dụ kiểm tra số hữu hạn trước khi tính toán để tránh nhầm này.
Số 0 thật vẫn có thể hợp lệ khi hai điểm trùng nhau hoặc gần như trùng. Nó khác với dữ liệu thiếu. Giữ nguyên sự khác biệt và xem lại kết quả nhỏ bất thường khi kho và khách lẽ ra ở xa. Nếu bước tìm tọa độ trước đó gắn cả hai vào cùng một điểm, Matrix có tính đúng cũng không cứu được quyết định nghiệp vụ.
Tài liệu có fallback_speed: nếu không tìm được tuyến, hệ thống có thể lấy khoảng cách đường chim bay và tốc độ này để ước lượng thời gian.[2] Nếu dùng, cần phân biệt cặp ước lượng với cặp có tuyến, đồng thời quy định cặp nào được tham gia phân công. Không cam kết khả năng tiếp cận đường bộ từ một đoạn thẳng. Nếu phản hồi chưa giúp ứng dụng nhận biết phần ước lượng đủ rõ cho bài toán, không bật cơ chế đó trong quyết định phân đơn.
Khi số điểm tăng, chia lô mà không mất ánh xạ
Xác nhận giới hạn kích thước yêu cầu và hạn mức tài khoản trước khi chọn số điểm mỗi lô. Cách chia dễ kiểm tra là lấy một tập con kho và một tập con khách, dựng danh sách tọa độ chung rồi ghi từng ô về mã nghiệp vụ toàn cục. Chỉ số trong URL bắt đầu lại ở mỗi lô, còn mã kho trong doanh nghiệp không đổi.
Ghi ngay lô đã hoàn tất, kèm loại xe, phiên bản tọa độ và thời điểm xử lý. Nếu khách đã sửa điểm nhận hàng, kết quả cũ không nên còn đủ điều kiện sử dụng chỉ vì mã khách vẫn giữ nguyên. Quản lý phiên bản tọa độ đáng tin cậy hơn lưu tạm chỉ theo tên khách.
Lỗi mạng tạm thời có thể thử lại có giới hạn và có chờ. Tọa độ sai cần sửa dữ liệu, lỗi xác thực cần sửa cấu hình, không có tuyến cần ngoại lệ nghiệp vụ. Không thử lại cả ba như thể đều do mạng chập chờn. Nhật ký nên có dịch vụ, thời gian và kết quả nhưng tránh ghi URL chứa khóa API.
Nếu so lặp lại cùng các cặp, hỏi rõ quyền lưu và tái sử dụng theo thỏa thuận. Lưu được về mặt kỹ thuật không có nghĩa được giữ vô thời hạn. Tọa độ chi nhánh do doanh nghiệp quản lý và kết quả tuyến do nhà cung cấp trả có thể chịu quy tắc lưu khác nhau.
Từ bảng số đến quyết định phân công
Với một khách, chọn kho có thời gian nhỏ nhất là quy tắc xếp hạng đơn giản. Nhưng trước đó cần loại kho thiếu hàng hoặc ngoài vùng phục vụ. Nếu không, hành trình ngắn nhất có thể dẫn tới kho không thực hiện được đơn. Giao diện nên giải thích kho bị loại vì tồn kho, năng lực hay đường đi, thay vì chỉ hiện “không phù hợp”.
Với nhiều đơn cùng lúc, mỗi đơn tự chọn tài xế gần nhất có thể gán một người cho nhiều nhiệm vụ đồng thời. Thuật toán ghép cặp hoặc bộ tối ưu nhiều xe xử lý bài toán dùng chung nguồn lực khác với Matrix. Dịch vụ cung cấp chi phí di chuyển; thuật toán và quy tắc nghiệp vụ cung cấp cách phân công. Phân biệt rõ hai phần khi giới thiệu tính năng cho đội vận hành.
Thời gian phục vụ cũng nên nằm ngoài bảng di chuyển. Nếu minh họa mỗi điểm mất 15 phút dỡ hàng, ghi đó là giả định riêng của kế hoạch. Đừng sửa số giây gốc để giấu phần cộng thêm; tách hai loại thời gian giúp điều tra chênh lệch sau này dễ hơn.
Thử những cặp khó trong vùng hoạt động thật
Một tập kiểm tra nhỏ nên có điểm qua sông, đường một chiều ở cả hai hướng, cơ sở khó tiếp cận và hai điểm trùng tọa độ. Xác nhận thứ tự tọa độ và ánh xạ ID trước khi đánh giá tuyến. Khi so nhà cung cấp, dùng cùng loại xe, cùng điểm và cùng các cặp yêu cầu; nếu không, bạn đang so hai bài toán khác nhau.
Với ô đáng ngờ, dùng Directions để xem tuyến chi tiết thay vì lấy hình học của mọi ô trong ma trận. Matrix phục vụ so sánh nhiều cặp; vẽ tuyến là một luồng tích hợp và một lượng sử dụng khác. Giữ endpoint, profile và tọa độ trong hồ sơ lỗi để đội hỗ trợ tái hiện được.
Trước khi đưa vào vận hành, thống nhất cách xử lý cặp không có tuyến và tần suất tính lại. Gửi TrackAsia số nguồn, số đích, số lần tính và mức đồng thời cao điểm để xác nhận giới hạn cùng đơn vị phí. Một tích hợp tốt giúp người dùng hiểu quyết định và xử lý ngoại lệ an toàn, chứ không chỉ lấy được bảng số thật nhanh.
Sources
[2] https://docs.track-asia.com/api-integration/distance-matrix/v1
[10] https://docs.track-asia.com/api-integration/directions/v2