org.opentripplanner.routing.bike_rental.TimeBasedBikeRentalFareServiceFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
package org.opentripplanner.routing.bike_rental;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Currency;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.opentripplanner.model.OtpTransitService;
import org.opentripplanner.common.model.P2;
import org.opentripplanner.routing.services.FareService;
import org.opentripplanner.routing.services.FareServiceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
public class TimeBasedBikeRentalFareServiceFactory implements FareServiceFactory {
private static Logger log = LoggerFactory
.getLogger(TimeBasedBikeRentalFareServiceFactory.class);
// Each entry is ; the list is sorted in
// ascending time order
private List> pricingBySecond;
private Currency currency;
@Override
public FareService makeFareService() {
return new TimeBasedBikeRentalFareService(currency, pricingBySecond);
}
@Override
public void processGtfs(OtpTransitService transitService) {
// Nothing to do
}
@Override
public void configure(JsonNode config) {
// Currency
String currencyStr = config.path("currency").asText(null);
// There is no "safe" default, so bail-out if missing
if (currencyStr == null)
throw new IllegalArgumentException("Missing mandatory 'currency' configuration.");
// The following line will throw an IllegalArgumentException if the currency is not found
currency = Currency.getInstance(currencyStr);
// List of {time, price_cents}
pricingBySecond = new ArrayList<>();
for (Iterator> i = config.path("prices").fields(); i.hasNext();) {
Map.Entry kv = i.next();
int maxTimeSec = hmToMinutes(kv.getKey()) * 60;
int priceCent = (int) Math.round(kv.getValue().asDouble() * 100);
pricingBySecond.add(new P2<>(maxTimeSec, priceCent));
}
if (pricingBySecond.isEmpty())
throw new IllegalArgumentException("Missing or empty mandatory 'prices' array.");
// Sort on increasing time
Collections.sort(pricingBySecond, new Comparator>() {
@Override
public int compare(P2 o1, P2 o2) {
return o1.first - o2.first;
}
});
// Check if price is increasing
int seconds = -1;
int lastCost = 0;
for (P2 bracket : pricingBySecond) {
int maxTime = bracket.first;
int cost = bracket.second;
if (maxTime == seconds) {
throw new IllegalArgumentException("Bike share pricing has two entries for "
+ maxTime);
}
if (cost < lastCost) {
log.warn("Bike share pricing has pathological pricing; keeping the bike for a "
+ maxTime + " is cheaper than keeping it for " + seconds);
}
seconds = maxTime;
lastCost = cost;
}
}
private int hmToMinutes(String hmStr) {
String[] hm = hmStr.split(":");
if (hm.length > 2)
throw new IllegalArgumentException("Invalid time: '" + hmStr + "'. Must be either 'hh:mm' or 'mm'.");
int minutes = 0;
for (String field : hm) {
minutes *= 60;
int fieldValue = Integer.parseInt(field);
minutes += fieldValue;
}
return minutes;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy