Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ public class VehicleRouteDemoResource {
private static final LocalTime AFTERNOON_WINDOW_END = LocalTime.of(18, 0);

public enum DemoData {
PHILADELPHIA(0, 55, 6, LocalTime.of(7, 30),
PHILADELPHIA(2, 55, 6, LocalTime.of(7, 30),
1, 2, 15, 30,
new Location(39.7656099067391, -76.83782328143754),
new Location(40.77636644354855, -74.9300739430771)),
GHENT(1, 65, 6, LocalTime.of(7, 30),
1, 2, 15, 30,
new Location(50.990000, 3.620000), new Location(51.130000, 3.840000)),
HARTFORT(1, 50, 6, LocalTime.of(7, 30),
1, 3, 20, 30,
new Location(41.48366520850297, -73.15901689943055),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const routeGroup = L.layerGroup().addTo(map);

/************************************ Time line constants and variable definitions ************************************/

const byVehiclePanel = document.getElementById("byVehiclePanel");
const byVehicleTimelineElement = document.getElementById("byVehicleTimeline");
const byVehicleTimelineOptions = {
timeAxis: {scale: "hour"},
orientation: {axis: "top"},
Expand All @@ -35,9 +35,9 @@ const byVehicleTimelineOptions = {
};
const byVehicleGroupData = new vis.DataSet();
const byVehicleItemData = new vis.DataSet();
const byVehicleTimeline = new vis.Timeline(byVehiclePanel, byVehicleItemData, byVehicleGroupData, byVehicleTimelineOptions);
const byVehicleTimeline = new vis.Timeline(byVehicleTimelineElement, byVehicleItemData, byVehicleGroupData, byVehicleTimelineOptions);

const byVisitPanel = document.getElementById("byVisitPanel");
const byVisitTimelineElement = document.getElementById("byVisitTimeline");
const byVisitTimelineOptions = {
timeAxis: {scale: "hour"},
orientation: {axis: "top"},
Expand All @@ -50,7 +50,7 @@ const byVisitTimelineOptions = {
};
const byVisitGroupData = new vis.DataSet();
const byVisitItemData = new vis.DataSet();
const byVisitTimeline = new vis.Timeline(byVisitPanel, byVisitItemData, byVisitGroupData, byVisitTimelineOptions);
const byVisitTimeline = new vis.Timeline(byVisitTimelineElement, byVisitItemData, byVisitGroupData, byVisitTimelineOptions);

const BG_COLORS = ["#009E73","#0072B2","#D55E00","#000000","#CC79A7","#E69F00","#F0E442","#F6768E","#C10020","#A6BDD7","#803E75","#007D34","#56B4E9","#999999","#8DD3C7","#FFD92F","#B3DE69","#FB8072","#80B1D3","#B15928","#CAB2D6","#1B9E77","#E7298A","#6A3D9A"];
const FG_COLORS = ["#FFFFFF","#FFFFFF","#FFFFFF","#FFFFFF","#FFFFFF","#000000","#000000","#FFFFFF","#FFFFFF","#000000","#FFFFFF","#FFFFFF","#FFFFFF","#000000","#000000","#000000","#000000","#FFFFFF","#000000","#FFFFFF","#000000","#FFFFFF","#FFFFFF","#FFFFFF"];
Expand Down Expand Up @@ -107,6 +107,11 @@ function colorByVehicle(vehicle) {
return vehicle === null ? null : pickColor('vehicle' + vehicle.id);
}

function formatScore(score) {
if (!score) return '?';
return score.replace('hard', 'H').replace('medium', 'M').replace('soft', 'S');
}

function formatDrivingTime(drivingTimeInSeconds) {
return `${Math.floor(drivingTimeInSeconds / 3600)}h ${Math.round((drivingTimeInSeconds % 3600) / 60)}m`;
}
Expand Down Expand Up @@ -209,7 +214,7 @@ function renderRoutes(solution) {
}

// Summary
$('#score').text(solution.score);
$('#score').text(formatScore(solution.score));
$("#info").text(`This dataset has ${solution.visits.length} visits who need to be assigned to ${solution.vehicles.length} vehicles.`);
$('#drivingTime').text(formatDrivingTime(solution.totalDrivingTimeSeconds));
}
Expand Down Expand Up @@ -303,7 +308,7 @@ function renderTimelines(routePlan) {
id: visit.id + '_wait',
group: visit.vehicle, // visit.vehicle is the vehicle.id due to Jackson serialization
subgroup: visit.vehicle,
content: byVehicleWaitElement.ahtml(),
content: byVehicleWaitElement.html(),
start: visit.arrivalTime,
end: visit.minStartTime
});
Expand Down Expand Up @@ -353,6 +358,10 @@ function renderTimelines(routePlan) {
byVehicleTimeline.setWindow(routePlan.startDateTime, routePlan.endDateTime);
byVisitTimeline.setWindow(routePlan.startDateTime, routePlan.endDateTime);
}
requestAnimationFrame(() => {
if ($('#byVehiclePanel').hasClass('active')) byVehicleTimeline.redraw();
if ($('#byVisitPanel').hasClass('active')) byVisitTimeline.redraw();
});
}

function analyze() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
.nav-pills {
--bs-nav-pills-link-active-bg: var(--ts-violet-1-rgb);
}

.legend-swatch {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 3px;
flex-shrink: 0;
}
</style>
</head>
<body>
Expand Down Expand Up @@ -99,7 +107,6 @@
<button id="stopSolvingButton" type="button" class="btn btn-danger p-2">
<i class="fas fa-stop"></i> Stop solving
</button>
<span id="score" class="score ms-2 align-middle fw-bold">Score: ?</span>
<button id="analyzeButton" type="button" class="ms-2 btn btn-secondary">
<span class="fas fa-question"></span>
</button>
Expand All @@ -120,6 +127,10 @@ <h5>
Solution summary
</h5>
<table class="table">
<tr>
<td>Score:</td>
<td><span id="score" class="fw-bold">?</span></td>
</tr>
<tr>
<td>Total driving time:</td>
<td><span id="drivingTime">unknown</span></td>
Expand Down Expand Up @@ -152,8 +163,27 @@ <h5>Vehicles</h5>


<div class="tab-pane fade" id="byVehiclePanel" role="tabpanel" aria-labelledby="byVehicleTab">
<div class="d-flex align-items-center flex-wrap gap-2 px-3 py-2 border-bottom bg-light">
<span class="text-muted small">Each row shows a vehicle's day: travel blocks, optional wait, and service stops.</span>
<div class="ms-auto d-flex gap-3 flex-wrap">
<span class="d-flex align-items-center gap-1 small"><span class="legend-swatch" style="background:#f7dd8f;"></span>Travel</span>
<span class="d-flex align-items-center gap-1 small"><span class="legend-swatch" style="background:#97C2FC;"></span>Wait</span>
<span class="d-flex align-items-center gap-1 small"><span class="legend-swatch" style="background:#83C159;"></span>Service</span>
<span class="d-flex align-items-center gap-1 small"><span class="legend-swatch" style="background:#EF2929;"></span>Late</span>
</div>
</div>
<div id="byVehicleTimeline"></div>
</div>
<div class="tab-pane fade" id="byVisitPanel" role="tabpanel" aria-labelledby="byVisitTab">
<div class="d-flex align-items-center flex-wrap gap-2 px-3 py-2 border-bottom bg-light">
<span class="text-muted small">Each row shows a visit's assigned vehicle and where it falls relative to its time window.</span>
<div class="ms-auto d-flex gap-3 flex-wrap">
<span class="d-flex align-items-center gap-1 small"><span class="legend-swatch" style="background:#8AE234;opacity:0.4;"></span>Time window</span>
<span class="d-flex align-items-center gap-1 small"><span class="legend-swatch" style="background:#83C159;"></span>Assigned</span>
<span class="d-flex align-items-center gap-1 small"><span class="legend-swatch" style="background:#EF2929;"></span>Late / Unassigned</span>
</div>
</div>
<div id="byVisitTimeline"></div>
</div>
</div>
</div>
Expand Down
Loading