"github.com/nextmv-io/code/engines/route"
fleetEngine "github.com/nextmv-io/code/engines/route/fleet"
"github.com/nextmv-io/code/hop/run/cli"
"github.com/nextmv-io/code/hop/solve"
// Struct to read from JSON in.
Stops []route.Stop `json:"stops,omitempty"`
Vehicles []string `json:"vehicles,omitempty"`
// Struct to customize part of the output.
type outputRoute struct {
VehicleID string `json:"vehicle_id,omitempty"`
NumStops int `json:"num_stops,omitempty"`
// Custom type to implement the FleetMarshaller interface.
type fleetMarshaller struct {
Routes []outputRoute `json:"routes"`
Unassigned int `json:"unassigned"`
// Marshall the number of unassigned stops and the number of stops per route.
func (m *fleetMarshaller) Marshal(s fleetEngine.State) ([]byte, error) {
routes := make([]outputRoute, len(vehicles))
for v, state := range vehicles {
// Ignore vehicle's start and end locations by using the length of
// the route and subtracting two stops.
VehicleID: state.Input().VehicleID.(string),
NumStops: len(state.Route()) - 2,
m.Unassigned = s.Unassigned().Len()
// Use the CLI runner to solve a Vehicle Routing Problem.
f := func(i input, opt solve.Options) (solve.Solver, error) {
// Declare the router and its solver.
router, err := route.NewRouter(i.Stops, i.Vehicles, route.Output(nil, &m))
return router.Solver(opt)