/**
 * Computes the routes saving them
 */
void
computeRoutes(RONet& net, ROLoader& loader, OptionsCont& oc) {
    // initialise the loader
    loader.openRoutes(net);
    // prepare the output
    const std::string& filename = oc.getString("output-file");
    std::string altFilename = filename + ".alt";
    const size_t len = filename.length();
    if (len > 4 && filename.substr(len - 4) == ".xml") {
        altFilename = filename.substr(0, len - 4) + ".alt.xml";
    } else if (len > 4 && filename.substr(len - 4) == ".sbx") {
        altFilename = filename.substr(0, len - 4) + ".alt.sbx";
    }
    net.openOutput(filename, altFilename, oc.getString("vtype-output"));
    // build the router
    SUMOAbstractRouter<ROEdge, ROVehicle>* router;
    const std::string measure = oc.getString("weight-attribute");
    const std::string routingAlgorithm = oc.getString("routing-algorithm");
    if (measure == "traveltime") {
        if (routingAlgorithm == "dijkstra") {
            if (net.hasRestrictions()) {
                router = new DijkstraRouterTT_Direct<ROEdge, ROVehicle, prohibited_withRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime);
            } else {
                router = new DijkstraRouterTT_Direct<ROEdge, ROVehicle, prohibited_noRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime);
            }
        } else if (routingAlgorithm == "astar") {
            if (net.hasRestrictions()) {
                router = new AStarRouterTT_Direct<ROEdge, ROVehicle, prohibited_withRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime);
            } else {
                router = new AStarRouterTT_Direct<ROEdge, ROVehicle, prohibited_noRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime);
            }
#ifdef HAVE_INTERNAL // catchall for internal stuff
        } else if (routingAlgorithm == "bulkstar") {
            if (net.hasRestrictions()) {
                router = new BulkStarRouterTT<ROEdge, ROVehicle, prohibited_withRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime, &ROEdge::getMinimumTravelTime);
            } else {
                router = new BulkStarRouterTT<ROEdge, ROVehicle, prohibited_noRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime, &ROEdge::getMinimumTravelTime);
            }

        } else if (routingAlgorithm == "CH") {
            // defaultVehicle is only in constructor and may be safely deleted
            // it is mainly needed for its maximum speed. @todo XXX make this configurable
            ROVehicle defaultVehicle(SUMOVehicleParameter(), 0, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID));
            const SUMOTime begin = string2time(oc.getString("begin"));
            const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
                                           string2time(oc.getString("weight-period")) :
                                           std::numeric_limits<int>::max());
            if (net.hasRestrictions()) {
                router = new CHRouter<ROEdge, ROVehicle, prohibited_withRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime, &defaultVehicle, begin, weightPeriod, true);
            } else {
                router = new CHRouter<ROEdge, ROVehicle, prohibited_noRestrictions<ROEdge, ROVehicle> >(
                    net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime, &defaultVehicle, begin, weightPeriod, false);
            }

        } else if (routingAlgorithm == "CHWrapper") {
            const SUMOTime begin = string2time(oc.getString("begin"));
            const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
                                           string2time(oc.getString("weight-period")) :
                                           std::numeric_limits<int>::max());

            router = new CHRouterWrapper<ROEdge, ROVehicle, prohibited_withRestrictions<ROEdge, ROVehicle> >(
                net.getEdgeNo(), oc.getBool("ignore-errors"), &ROEdge::getTravelTime, begin, weightPeriod);

#endif // have HAVE_INTERNAL
        } else {
            throw ProcessError("Unknown routing Algorithm '" + routingAlgorithm + "'!");
        }

    } else {
        DijkstraRouterEffort_Direct<ROEdge, ROVehicle, prohibited_withRestrictions<ROEdge, ROVehicle> >::Operation op;
        if (measure == "CO") {
            op = &ROEdge::getCOEffort;
        } else if (measure == "CO2") {
            op = &ROEdge::getCO2Effort;
        } else if (measure == "PMx") {
            op = &ROEdge::getPMxEffort;
        } else if (measure == "HC") {
            op = &ROEdge::getHCEffort;
        } else if (measure == "NOx") {
            op = &ROEdge::getNOxEffort;
        } else if (measure == "fuel") {
            op = &ROEdge::getFuelEffort;
        } else if (measure == "noise") {
            op = &ROEdge::getNoiseEffort;
        } else {
            net.closeOutput();
            throw ProcessError("Unknown measure (weight attribute '" + measure + "')!");
        }
        if (net.hasRestrictions()) {
            router = new DijkstraRouterEffort_Direct<ROEdge, ROVehicle, prohibited_withRestrictions<ROEdge, ROVehicle> >(
                net.getEdgeNo(), oc.getBool("ignore-errors"), op, &ROEdge::getTravelTime);
        } else {
            router = new DijkstraRouterEffort_Direct<ROEdge, ROVehicle, prohibited_noRestrictions<ROEdge, ROVehicle> >(
                net.getEdgeNo(), oc.getBool("ignore-errors"), op, &ROEdge::getTravelTime);
        }
    }
    // process route definitions
    try {
        if (routingAlgorithm == "bulkstar") {
#ifdef HAVE_INTERNAL // catchall for internal stuff
            // need to load all routes for spatial aggregation
            loader.processAllRoutesWithBulkRouter(string2time(oc.getString("begin")), string2time(oc.getString("end")), net, *router);
#endif
        } else {
            loader.processRoutes(string2time(oc.getString("begin")), string2time(oc.getString("end")), net, *router);
        }
        // end the processing
        net.closeOutput();
        delete router;
        ROCostCalculator::cleanup();
    } catch (ProcessError&) {
        net.closeOutput();
        delete router;
        ROCostCalculator::cleanup();
        throw;
    }
}