Team Ai
Apppublic

blackopsrepl/vehicle-routing-python

sourceHugging Faceapache-2.0updated 10mo agoView on Hugging Face
2likes
index.html474 linesDownload Raw Back to static
1<!doctype html>2<html lang="en">3<head>4  <meta charset="utf-8">5  <meta http-equiv="content-type" content="text/html; charset=UTF-8">6  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">7  <title>Vehicle Routing - SolverForge for Python</title>8  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css">9  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.css">10  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">11  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vis-timeline@7.7.2/styles/vis-timeline-graph2d.min.css"12        integrity="sha256-svzNasPg1yR5gvEaRei2jg+n4Pc3sVyMUWeS6xRAh6U=" crossorigin="anonymous">13  <link rel="stylesheet" href="/webjars/solverforge/css/solverforge-webui.css"/>14  <link rel="icon" href="/webjars/solverforge/img/solverforge-favicon.svg" type="image/svg+xml">15  <style>16    /* Customer marker icons */17    .customer-marker, .vehicle-home-marker, .temp-vehicle-marker {18      background: transparent !important;19      border: none !important;20    }21 22    /* Pulse animation for new vehicle placement */23    @keyframes pulse {24      0% { transform: scale(1); box-shadow: 0 2px 4px rgba(0,0,0,0.4); }25      50% { transform: scale(1.1); box-shadow: 0 4px 8px rgba(99, 102, 241, 0.6); }26      100% { transform: scale(1); box-shadow: 0 2px 4px rgba(0,0,0,0.4); }27    }28 29    /* Customer type buttons in modal */30    .customer-type-btn {31      transition: all 0.2s ease;32      padding: 0.75rem 0.5rem;33    }34    .customer-type-btn:hover {35      transform: translateY(-2px);36      box-shadow: 0 4px 8px rgba(0,0,0,0.15);37    }38 39    /* Vehicle table styling */40    #vehicles tr.vehicle-row {41      transition: background-color 0.2s ease;42    }43    #vehicles tr.vehicle-row:hover {44      background-color: rgba(99, 102, 241, 0.1);45    }46    #vehicles tr.vehicle-row.table-active {47      background-color: rgba(99, 102, 241, 0.15) !important;48    }49 50    /* Route number markers */51    .route-number-marker {52      background: transparent !important;53      border: none !important;54    }55 56    /* Notification panel */57    #notificationPanel {58      z-index: 1050;59    }60 61    /* Click hint for vehicle rows */62    #vehicles tr.vehicle-row td:not(:last-child) {63      cursor: pointer;64    }65 66    /* Solving spinner */67    #solvingSpinner {68      display: none;69      width: 1.25rem;70      height: 1.25rem;71      border: 2px solid #10b981;72      border-top-color: transparent;73      border-radius: 50%;74      animation: spin 0.75s linear infinite;75      vertical-align: middle;76    }77    #solvingSpinner.active {78      display: inline-block;79    }80    @keyframes spin {81      to { transform: rotate(360deg); }82    }83 84    /* Progress bar text should stay horizontal and inside */85    .progress-bar {86      overflow: visible;87      white-space: nowrap;88    }89 90    /* Map hint overlay */91    .map-hint {92      position: absolute;93      bottom: 20px;94      left: 50%;95      transform: translateX(-50%);96      background-color: rgba(255, 255, 255, 0.95);97      padding: 8px 16px;98      border-radius: 20px;99      box-shadow: 0 2px 8px rgba(0,0,0,0.2);100      font-size: 0.9rem;101      color: #374151;102      z-index: 1000;103      pointer-events: none;104      transition: opacity 0.3s ease;105    }106    .map-hint i {107      color: #10b981;108      margin-right: 6px;109    }110    .map-hint.hidden {111      opacity: 0;112    }113 114    /* Timeline stop badges */115    .timeline-stop-badge {116      background-color: #6366f1;117      color: white;118      padding: 1px 6px;119      border-radius: 10px;120      font-size: 0.7rem;121      font-weight: bold;122      margin-right: 4px;123    }124    .timeline-status-icon {125      margin-left: 4px;126      font-size: 0.85rem;127    }128    .timeline-status-ontime { color: #10b981; }129    .timeline-status-late { color: #ef4444; }130    .timeline-status-early { color: #3b82f6; }131    .vis-item .vis-item-content {132      font-size: 0.85rem;133      padding: 2px 4px;134    }135    .vis-labelset .vis-label {136      padding: 4px 8px;137    }138 139    /* Loading overlay */140    .loading-overlay {141      position: fixed;142      top: 0;143      left: 0;144      right: 0;145      bottom: 0;146      background: rgba(255, 255, 255, 0.95);147      display: flex;148      align-items: center;149      justify-content: center;150      z-index: 2000;151      transition: opacity 0.3s ease;152    }153    .loading-overlay.hidden {154      opacity: 0;155      pointer-events: none;156    }157    .loading-content {158      text-align: center;159      padding: 2rem;160    }161    .loading-spinner {162      width: 60px;163      height: 60px;164      border: 4px solid #e5e7eb;165      border-top-color: #10b981;166      border-radius: 50%;167      animation: spin 1s linear infinite;168      margin: 0 auto 1.5rem;169    }170    @keyframes spin {171      to { transform: rotate(360deg); }172    }173 174    /* Real Roads toggle styling */175    #realRoadRouting:checked {176      background-color: #10b981;177      border-color: #10b981;178    }179  </style>180</head>181<body>182 183<header id="solverforge-auto-header">184  <!-- Filled in by app.js -->185</header>186<div class="tab-content">187  <div id="demo" class="tab-pane fade show active container-fluid">188    <div class="sticky-top d-flex justify-content-center align-items-center">189      <div id="notificationPanel" style="position: absolute; top: .5rem;"></div>190    </div>191    <h1>Vehicle routing with capacity and time windows</h1>192    <p>Generate optimal route plan of a vehicle fleet with limited vehicle capacity and time windows.</p>193    <div class="container-fluid mb-2">194      <div class="row justify-content-start">195        <div class="col-9">196          <ul class="nav nav-pills col" role="tablist">197            <li class="nav-item" role="presentation">198              <button class="nav-link active" id="mapTab" data-bs-toggle="tab" data-bs-target="#mapPanel"199                      type="button"200                      role="tab" aria-controls="mapPanel" aria-selected="false">Map201              </button>202            </li>203            <li class="nav-item" role="presentation">204              <button class="nav-link" id="byVehicleTab" data-bs-toggle="tab" data-bs-target="#byVehiclePanel"205                      type="button" role="tab" aria-controls="byVehiclePanel" aria-selected="false">By vehicle206              </button>207            </li>208            <li class="nav-item" role="presentation">209              <button class="nav-link" id="byVisitTab" data-bs-toggle="tab" data-bs-target="#byVisitPanel"210                      type="button" role="tab" aria-controls="byVisitPanel" aria-selected="false">By visit211              </button>212            </li>213          </ul>214        </div>215        <div class="col-3">216          <button id="solveButton" type="button" class="btn btn-success">217            <i class="fas fa-play"></i> Solve218          </button>219          <button id="stopSolvingButton" type="button" class="btn btn-danger p-2">220            <i class="fas fa-stop"></i> Stop solving221          </button>222          <span id="solvingSpinner" class="ms-2"></span>223          <span id="score" class="score ms-2 align-middle fw-bold">Score: ?</span>224          <button id="analyzeButton" type="button" class="ms-2 btn btn-secondary">225            <span class="fas fa-question"></span>226          </button>227        </div>228      </div>229    </div>230 231    <div class="tab-content">232 233      <div class="tab-pane fade show active" id="mapPanel" role="tabpanel" aria-labelledby="mapTab">234        <div class="row">235          <div class="col-7 col-lg-8 col-xl-9 position-relative">236            <div id="map" style="width: 100%; height: 100vh;"></div>237            <div id="mapHint" class="map-hint">238              <i class="fas fa-mouse-pointer"></i> Click on the map to add a new visit239            </div>240          </div>241          <div class="col-5 col-lg-4 col-xl-3" style="height: 100vh; overflow-y: scroll;">242            <div class="row pt-2 row-cols-1">243              <div class="col">244                <h5>245                  Solution summary246                </h5>247                <table class="table">248                  <tr>249                    <td>Total driving time:</td>250                    <td><span id="drivingTime">unknown</span></td>251                  </tr>252                </table>253              </div>254              <div class="col mb-3">255                <h5>Time Windows</h5>256                <div class="d-flex flex-column gap-1">257                  <div><i class="fas fa-utensils" style="color: #f59e0b; width: 20px;"></i> <strong>Restaurant</strong> <small class="text-muted">06:00-10:00 · 20-40 min</small></div>258                  <div><i class="fas fa-building" style="color: #3b82f6; width: 20px;"></i> <strong>Business</strong> <small class="text-muted">09:00-17:00 · 15-30 min</small></div>259                  <div><i class="fas fa-home" style="color: #10b981; width: 20px;"></i> <strong>Residential</strong> <small class="text-muted">17:00-20:00 · 5-10 min</small></div>260                </div>261              </div>262              <div class="col">263                <div class="d-flex justify-content-between align-items-center mb-2">264                  <div>265                    <h5 class="mb-0">Vehicles</h5>266                    <small class="text-muted"><i class="fas fa-hand-pointer"></i> Click to highlight route</small>267                  </div>268                  <div class="btn-group btn-group-sm" role="group" aria-label="Vehicle management">269                    <button type="button" class="btn btn-outline-danger" id="removeVehicleBtn" title="Remove last vehicle">270                      <i class="fas fa-minus"></i>271                    </button>272                    <button type="button" class="btn btn-outline-success" id="addVehicleBtn" title="Add new vehicle">273                      <i class="fas fa-plus"></i>274                    </button>275                  </div>276                </div>277                <table class="table-sm w-100">278                  <thead>279                  <tr>280                    <th class="col-1"></th>281                    <th class="col-3">Name</th>282                    <th class="col-3">283                      Cargo284                      <i class="fas fa-info-circle" data-bs-toggle="tooltip" data-bs-placement="top"285                         data-html="true"286                         title="Units to deliver on this route. Each customer requires cargo units (e.g., packages, crates). Bar shows current load vs. vehicle capacity."></i>287                    </th>288                    <th class="col-2">Drive</th>289                    <th class="col-1"></th>290                  </tr>291                  </thead>292                  <tbody id="vehicles"></tbody>293                </table>294              </div>295            </div>296          </div>297        </div>298      </div>299 300 301      <div class="tab-pane fade" id="byVehiclePanel" role="tabpanel" aria-labelledby="byVehicleTab">302      </div>303      <div class="tab-pane fade" id="byVisitPanel" role="tabpanel" aria-labelledby="byVisitTab">304      </div>305    </div>306  </div>307 308  <div id="rest" class="tab-pane fade container-fluid">309    <h1>REST API Guide</h1>310 311    <h2>Vehicle routing with vehicle capacity and time windows - integration via cURL</h2>312 313    <h3>1. Download demo data</h3>314    <pre>315              <button class="btn btn-outline-dark btn-sm float-end"316                      onclick="copyTextToClipboard('curl1')">Copy</button>317              <code id="curl1">curl -X GET -H 'Accept:application/json' http://localhost:8080/demo-data/FIRENZE -o sample.json</code>318    </pre>319 320    <h3>2. Post the sample data for solving</h3>321    <p>The POST operation returns a <code>jobId</code> that should be used in subsequent commands.</p>322    <pre>323              <button class="btn btn-outline-dark btn-sm float-end"324                      onclick="copyTextToClipboard('curl2')">Copy</button>325              <code id="curl2">curl -X POST -H 'Content-Type:application/json' http://localhost:8080/route-plans -d@sample.json</code>326    </pre>327 328    <h3>3. Get the current status and score</h3>329    <pre>330              <button class="btn btn-outline-dark btn-sm float-end"331                      onclick="copyTextToClipboard('curl3')">Copy</button>332              <code id="curl3">curl -X GET -H 'Accept:application/json' http://localhost:8080/route-plans/{jobId}/status</code>333    </pre>334 335    <h3>4. Get the complete route plan</h3>336    <pre>337              <button class="btn btn-outline-dark btn-sm float-end"338                      onclick="copyTextToClipboard('curl4')">Copy</button>339              <code id="curl4">curl -X GET -H 'Accept:application/json' http://localhost:8080/route-plans/{jobId}</code>340    </pre>341 342    <h3>5. Terminate solving early</h3>343    <pre>344              <button class="btn btn-outline-dark btn-sm float-end"345                      onclick="copyTextToClipboard('curl5')">Copy</button>346              <code id="curl5">curl -X DELETE -H 'Accept:application/json' http://localhost:8080/route-plans/{jobId}</code>347    </pre>348  </div>349 350  <div id="openapi" class="tab-pane fade container-fluid">351    <h1>REST API Reference</h1>352    <div class="ratio ratio-1x1">353      <!-- "scrolling" attribute is obsolete, but e.g. Chrome does not support "overflow:hidden" -->354      <iframe src="/q/swagger-ui" style="overflow:hidden;" scrolling="no"></iframe>355    </div>356  </div>357</div>358<div class="modal fadebd-example-modal-lg" id="scoreAnalysisModal" tabindex="-1" aria-labelledby="scoreAnalysisModalLabel" aria-hidden="true">359  <div class="modal-dialog modal-lg modal-dialog-scrollable">360    <div class="modal-content">361      <div class="modal-header">362        <h1 class="modal-title fs-5" id="scoreAnalysisModalLabel">Score analysis <span id="scoreAnalysisScoreLabel"></span></h1>363        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>364      </div>365      <div class="modal-body" id="scoreAnalysisModalContent">366        <!-- Filled in by app.js -->367      </div>368      <div class="modal-footer">369        <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button>370      </div>371    </div>372  </div>373</div>374<form id='visitForm' class='needs-validation' novalidate>375    <div class="modal fadebd-example-modal-lg" id="newVisitModal" tabindex="-1"376         aria-labelledby="newVisitModalLabel"377         aria-hidden="true">378        <div class="modal-dialog modal-lg modal-dialog-scrollable">379            <div class="modal-content">380                <div class="modal-header">381                    <h1 class="modal-title fs-5" id="newVisitModalLabel">Add New Visit</h1>382                    <button type="button" class="btn-close" data-bs-dismiss="modal"383                            aria-label="Close"></button>384                </div>385                <div class="modal-body" id="newVisitModalContent">386                    <!-- Filled in by app.js -->387                </div>388                <div class="modal-footer" id="newVisitModalFooter">389                </div>390            </div>391        </div>392    </div>393</form>394<!-- Add Vehicle Modal -->395<div class="modal fade" id="addVehicleModal" tabindex="-1" aria-labelledby="addVehicleModalLabel" aria-hidden="true">396  <div class="modal-dialog">397    <div class="modal-content">398      <div class="modal-header">399        <h5 class="modal-title" id="addVehicleModalLabel"><i class="fas fa-truck"></i> Add New Vehicle</h5>400        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>401      </div>402      <div class="modal-body">403        <div class="mb-3">404          <label for="vehicleName" class="form-label">Name</label>405          <input type="text" class="form-control" id="vehicleName" placeholder="e.g., Kilo">406          <div class="form-text">Unique name for the vehicle</div>407        </div>408        <div class="mb-3">409          <label for="vehicleCapacity" class="form-label">Capacity</label>410          <input type="number" class="form-control" id="vehicleCapacity" value="25" min="1">411          <div class="form-text">Maximum cargo the vehicle can carry</div>412        </div>413        <div class="mb-3">414          <label for="vehicleDepartureTime" class="form-label">Departure Time</label>415          <input type="text" class="form-control" id="vehicleDepartureTime">416        </div>417        <div class="mb-3">418          <label class="form-label">Home Location</label>419          <div class="d-flex gap-2 mb-2">420            <button type="button" class="btn btn-outline-primary btn-sm" id="pickLocationBtn">421              <i class="fas fa-map-marker-alt"></i> Pick on Map422            </button>423            <span class="text-muted small align-self-center">or enter coordinates:</span>424          </div>425          <div class="row g-2">426            <div class="col-6">427              <input type="number" step="any" class="form-control" id="vehicleHomeLat" placeholder="Latitude">428            </div>429            <div class="col-6">430              <input type="number" step="any" class="form-control" id="vehicleHomeLng" placeholder="Longitude">431            </div>432          </div>433          <div id="vehicleLocationPreview" class="mt-2 text-muted small"></div>434        </div>435      </div>436      <div class="modal-footer">437        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>438        <button type="button" class="btn btn-success" id="confirmAddVehicle"><i class="fas fa-plus"></i> Add Vehicle</button>439      </div>440    </div>441  </div>442</div>443 444<!-- Loading/Progress Overlay -->445<div id="loadingOverlay" class="loading-overlay hidden">446  <div class="loading-content">447    <div class="loading-spinner"></div>448    <h5 id="loadingTitle">Loading Demo Data</h5>449    <p id="loadingMessage" class="text-muted mb-2">Initializing...</p>450    <div class="progress" style="width: 300px; height: 8px;">451      <div id="loadingProgress" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%"></div>452    </div>453    <small id="loadingDetail" class="text-muted mt-2 d-block"></small>454  </div>455</div>456 457<footer id="solverforge-auto-footer"></footer>458 459<script src="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.6.13/flatpickr.min.js"></script>460<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.6.13/flatpickr.min.css">461<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.js"></script>462<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>463<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js"></script>464<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.bundle.min.js"></script>465<script src="https://cdnjs.cloudflare.com/ajax/libs/js-joda/1.11.0/js-joda.min.js"></script>466<script src="https://cdn.jsdelivr.net/npm/vis-timeline@7.7.2/standalone/umd/vis-timeline-graph2d.min.js"467        integrity="sha256-Jy2+UO7rZ2Dgik50z3XrrNpnc5+2PAx9MhL2CicodME=" crossorigin="anonymous"></script>468<script src="/webjars/solverforge/js/solverforge-webui.js"></script>469<script src="/score-analysis.js"></script>470<script src="/recommended-fit.js"></script>471<script src="/app.js"></script>472</body>473</html>474