Public
Edited
Mar 24, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
agency = ({
uuid: "agency123",
name: "Targomo GmbH",
address: { lng: 13.41533, lat: 52.523299 }
})
Insert cell
Insert cell
transports = dateRange.map((d) => createDayAgent(d))
Insert cell
Insert cell
function createDayAgent(date) {
return {
vehicle: {
uuid: `agent_${date}`,
storeUuid: agency.uuid,
priority: 1,
fixedTravelCosts: (dayjs(date).get("d") - 1) * 60 // each day of the week gets an additional 60s penalty to prioritize earlier dates
},
metadata: {
earliestDepartureTime: `${date}T08:00:00+01:00`, // day start
latestArrivalTime: `${date}T18:00:00+01:00`, // day end
interruptionTimes: [
{
start: `${date}T12:00:00+01:00`, // lunch break start
end: `${date}T13:00:00+01:00` // lunch break end
}
],
start: agency.address, // could also be a home address
endDestination: agency.address // could also be a home address
}
};
}
Insert cell
function createOrder(config) {
const { uuid, storeUuid, lnglat, visitingTimes, color } = config;

const orderConfig = {
uuid,
storeUuid,
priority: 1,
address: {
avgHandlingTime: 3600, // the is the meeting time
lat: lnglat.lat,
lng: lnglat.lng
},
visitingTimes, // if already scheduled, we enforce with strict visiting times
color
};

return orderConfig;
}
Insert cell
timeOffset = (d, key) => dayjs(d[key]).diff(dayjs(dayjs(d[key]).startOf("day"))) // get ms since day start to plot on calendar
Insert cell
Insert cell
config = ({
optimizationTime: 2,
optimizationAlgorithm: "CONSTRAINT_SATISFACTION",
stores: [agency],
orders: allVisits,
transports,
optimizationMetadata: {
geojsonCreation: "ROUTING_SERVICE",
unimprovedWaitingTime: 1,
disableShiftingOfVehicleDeparture: false,
filterOrdersWithWaitingCostHigherThan: 3600,
travelOptions: {
travelType: "car",
elevationEnabled: true,
maxEdgeWeight: 3600,
edgeWeight: "time",
serviceUrl: "https://api.targomo.com/westcentraleurope/",
serviceKey: targomoKey(),
// waitingCostFactors: {
// "0": 0.0,
// "300": 0.5
// }
}
}
})
Insert cell
Insert cell
fullOptimization = {
const rawFetch = await fetch(
`https://api.targomo.com/fleetplanner/v1/api/key-auth/optimizations?key=${targomoKey()}`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(config)
}
);

return await rawFetch.json();
}
Insert cell
{
const routeGeoJSON = turf.featureCollection(
fullOptimization.tours
.map((d, i) =>
d.featureCollection.features
.filter((f) => f.geometry.type === "LineString")
.map((f) => {
f.properties.tour = i + 1;
f.properties.color = d3.schemeCategory10[9 - i];
return f;
})
)
.flat()
);
map.getSource("route").setData(routeGeoJSON);
return routeGeoJSON;
}
Insert cell
optimization = {
const toursFormat = fullOptimization.tours
.map((d, i) =>
d.tourItems.map((t) => {
const { expectedStartVisit, expectedDeparture, order } = t;
const orderMatch = config.orders.find((o) => o.uuid === order.uuid);
const tourFormat = {
sort: +dayjs(expectedStartVisit),
start: dayjs(expectedStartVisit),
end: dayjs(expectedDeparture),
order: order.uuid,
tour: i + 1,
color: allVisits.find((d) => d.uuid === order.uuid).color
};
return tourFormat;
})
)
.flat()
.sort((a, b) => a.sort < b.sort);

updateCompTable(toursFormat);

return toursFormat;
}
Insert cell
Insert cell
viewof candidateLocation = {
const uuid = "planned1";
const [lat, lng] = [52.54069923102475, 13.206526560634476];
const inp = Inputs.input({ lng, lat, uuid });
const marker = new maplibre.Marker({
draggable: true,
color: d3.schemeCategory10[0]
})
.setLngLat({ lng, lat })
.addTo(map);

marker.on("dragend", () => {
inp.value = { ...marker.getLngLat(), uuid };
inp.dispatchEvent(new Event("input", { bubbles: true }));
});
return inp;
}
Insert cell
currentmarkers = []
Insert cell
{
currentmarkers.forEach((marker) => marker.remove());
for (const item of calendarItems) {
const marker = new maplibre.Marker({
color: item.color
})
.setLngLat(item.geolocation)
.addTo(map);
currentmarkers.push(marker);
}
}
Insert cell
calendarItemsAll = [
{
id: "scheduled1",
location: "Im Marienpark 23, 12107 Berlin, Germany",
geolocation: { lat: 52.438082, lng: 13.36822 },
color: d3.schemeCategory10[1],
start: "2023-03-21T09:00:00+01:00",
end: "2023-03-21T10:00:00+01:00"
},
{
id: "scheduled2",
location: "Potsdamer Str. 182, 10783 Berlin, Germany",
geolocation: { lat: 52.493704, lng: 13.360434 },
color: d3.schemeCategory10[2],
start: "2023-03-21T10:30:00+01:00",
end: "2023-03-21T11:30:00+01:00"
},
{
id: "scheduled3",
location: "Jesse-Owens-Allee, 14053 Berlin, Germany",
geolocation: { lat: 52.511138, lng: 13.238996 },
color: d3.schemeCategory10[3],
start: "2023-03-21T13:00:00+01:00",
end: "2023-03-21T14:00:00+01:00"
},
{
id: "scheduled4",
location: "Lehrter Str. 57, 10557 Berlin, Germany",
geolocation: { lat: 52.533042, lng: 13.359729 },
color: d3.schemeCategory10[4],
start: "2023-03-21T16:00:00+01:00",
end: "2023-03-21T17:00:00+01:00"
},
{
id: "scheduled5",
location: "An d. Wuhlheide 263, 12555 Berlin, Germany",
geolocation: { lat: 52.457349, lng: 13.568059 },
color: d3.schemeCategory10[5],
start: "2023-03-22T10:00:00+01:00",
end: "2023-03-22T11:00:00+01:00"
},
{
id: "scheduled6",
location: "Rennbahnstraße 45, 13086 Berlin, Germany",
geolocation: { lat: 52.563628, lng: 13.455974 },
color: d3.schemeCategory10[6],
start: "2023-03-22T15:30:00+01:00",
end: "2023-03-22T16:30:00+01:00"
}
]
Insert cell
Insert cell
{
const bbox = turf.bbox(
turf.featureCollection([
...calendarItems.map((d) =>
turf.point([d.geolocation.lng, d.geolocation.lat])
),
turf.point([agency.address.lng, agency.address.lat]),
turf.point([candidateLocation.lng, candidateLocation.lat])
])
);
map.fitBounds(bbox, { padding: 50 });
}
Insert cell
function updateCompTable(optimized) {
mutable compTable = optimized
.map((d) => {
const { start, end, order, tour, sort } = d;
return {
tour,
meeting: order,
sort,
start: start.format("YYYY-MM-DD HH:mm"),
end: end.format("YYYY-MM-DD HH:mm")
};
})
.sort((a, b) => a.sort - b.sort)
.map((d) => {
const { sort, ...fields } = d;
return fields;
});
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dateRange = {
const start = dayjs("2023-03-20T00:00:00");
const days = Array.from({ length: 5 }).map((d, i) =>
start.add(i, "day").format("YYYY-MM-DD")
);
return days;
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more