Commit 334fab9e by chamberone

feat: 算法支持不同的交通工具

1 parent 5b510ce2
......@@ -11,6 +11,8 @@ import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
......@@ -59,13 +61,13 @@ public class GeoDistanceCalculator {
}
}
private Map<Location, Map<Location, Pair>> calculateBulkDistanceDuration(Collection<Location> fromLocations, Collection<Location> toLocations) {
private Map<Location, Map<Location, Pair>> calculateBulkDistanceDuration(Collection<Location> fromLocations, Collection<Location> toLocations, Integer vehicleType) {
return fromLocations.stream().collect(Collectors.toMap(
Function.identity(),
from -> toLocations.stream().collect(Collectors.toMap(
Function.identity(),
to -> {
Distance distance = RoadDistanceUtils.getDistance(from, to);
Distance distance = RoadDistanceUtils.getDistance(from, to, vehicleType);
long path = (long) distance.getDis();
long time = distance.getTime();
return new Pair(path, time);
......@@ -74,18 +76,17 @@ public class GeoDistanceCalculator {
));
}
public void initDistanceMaps(Collection<Location> locationList) {
Map<Location, Map<Location, Pair>> distanceMatrix = calculateBulkDistanceDuration(locationList, locationList);
locationList.forEach(location -> {
Map<Location, Pair> mapPair = distanceMatrix.get(location);
mapPair.forEach((loc2, pair) -> {
location.getDistanceMap().put(loc2, pair.Distance);
location.getDistanceTimeMap().put(loc2, pair.Duration);
public void initDistanceMaps(Collection<Location> locationList, List<Integer> vehicleTypes) {
for (Integer vehicleType: vehicleTypes) {
Map<Location, Map<Location, Pair>> distanceMatrix = calculateBulkDistanceDuration(locationList, locationList, vehicleType);
locationList.forEach(location -> {
Map<Location, Pair> mapPair = distanceMatrix.get(location);
mapPair.forEach((loc2, pair) -> {
location.getDistanceMap(vehicleType).put(loc2, pair.Distance);
location.getDistanceTimeMap(vehicleType).put(loc2, pair.Duration);
});
});
});
}
}
}
......
......@@ -51,6 +51,9 @@ public class DispatchEngineer implements Serializable {
@Column(name = "max_distance")
private Integer maxDistance;
@Column(name = "vehicle_type")
private Integer vehicleType;
private String ext = "";
......
......@@ -131,9 +131,9 @@ public class Customer {
// throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet.");
}
if (previousCustomer == null) {
return technician.getDepot().getLocation().getDistanceTo(location);
return technician.getDepot().getLocation().getDistanceTo(technician.getVehicleType(),location);
}
return previousCustomer.getLocation().getDistanceTo(location);
return previousCustomer.getLocation().getDistanceTo(technician.getVehicleType(),location);
}
/**
......@@ -147,9 +147,9 @@ public class Customer {
// throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet.");
}
if (previousCustomer == null) {
return technician.getDepot().getLocation().getPathTimeTo(location);
return technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(),location);
}
return previousCustomer.getLocation().getPathTimeTo(location);
return previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(),location);
}
@Override
......
......@@ -24,10 +24,26 @@ public class Location {
private double latitude;
private double longitude;
// 汽车路网矩阵
@JsonIgnore
private Map<Location, Long> distanceMap = new HashMap<Location, Long>();// 路网距离矩阵
private Map<Location, Long> carDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> distanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
private Map<Location, Long> carDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
// 电动车路网矩阵
@JsonIgnore
private Map<Location, Long> electricBicycleDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> electricBicycleDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
// 自行车路网矩阵
@JsonIgnore
private Map<Location, Long> bicycleDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> bicycleDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
// 步行路网矩阵
@JsonIgnore
private Map<Location, Long> walkDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> walkDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
public Location(long id) {
this.id = id;
......@@ -47,36 +63,101 @@ public class Location {
this.latitude = latitude;
}
/**
* Set the distance map. Distances are in meters.
*
* @param distanceMap a map containing distances from here to other locations
*/
public void setDistanceMap(Map<Location, Long> distanceMap) {
this.distanceMap = distanceMap;
}
/**
* Distance to the given location in meters.
*
* @param location other location
* @return distance in meters
* 根据不同交通方式返回不同距离
*
* @param vehicleType
* @param location
* @return
*/
public long getDistanceTo(Location location) {
return distanceMap.get(location);
}
public long getDistanceTo(Integer vehicleType, Location location) {
if (null == vehicleType) {
return carDistanceMap.get(location);
}
switch (vehicleType) {
case 1:
return carDistanceMap.get(location);
case 2:
return electricBicycleDistanceMap.get(location);
case 3:
return bicycleDistanceMap.get(location);
case 4:
return walkDistanceMap.get(location);
}
return carDistanceMap.get(location);
}
public Map<Location, Long> getDistanceMap(Integer vehicleType) {
if (null == vehicleType) {
return carDistanceMap;
}
switch (vehicleType) {
case 1:
return carDistanceMap;
case 2:
return electricBicycleDistanceMap;
case 3:
return bicycleDistanceMap;
case 4:
return walkDistanceMap;
}
return carDistanceMap;
}
public Map<Location, Long> getDistanceTimeMap(Integer vehicleType) {
if (null == vehicleType) {
return carDistanceTimeMap;
}
switch (vehicleType) {
case 1:
return carDistanceTimeMap;
case 2:
return electricBicycleDistanceTimeMap;
case 3:
return bicycleDistanceTimeMap;
case 4:
return walkDistanceTimeMap;
}
return carDistanceTimeMap;
}
public int getPathTimeTo(Integer vehicleType, Location location) {
if (null == vehicleType) {
return carDistanceTimeMap.get(location).intValue() / 60;
}
switch (vehicleType) {
case 1:
return carDistanceTimeMap.get(location).intValue() / 60;
case 2:
return electricBicycleDistanceTimeMap.get(location).intValue() / 60;
case 3:
return bicycleDistanceTimeMap.get(location).intValue() / 60;
case 4:
return walkDistanceTimeMap.get(location).intValue() / 60;
}
return carDistanceTimeMap.get(location).intValue() / 60;
}
/**
* time to the given location in minutes.
*
* @param location other location
* @return time in minutes
*/
public int getPathTimeTo(Location location) {
return distanceTimeMap.get(location).intValue()/60;
public int getCarPathTimeTo(Location location) {
return carDistanceTimeMap.get(location).intValue() / 60;
}
public int getElectricBicyclePathTimeTo(Location location) {
return electricBicycleDistanceTimeMap.get(location).intValue() / 60;
}
public int getBicyclePathTimeTo(Location location) {
return bicycleDistanceTimeMap.get(location).intValue() / 60;
}
public int getWalkDathTimeTo(Location location) {
return walkDistanceTimeMap.get(location).intValue() / 60;
}
// ************************************************************************
......@@ -110,5 +191,4 @@ public class Location {
'}';
}
}
......@@ -44,6 +44,9 @@ public class Technician {
// 单位是米,这里要注意
private int maxDistanceMeter;
// 交通方式 1汽车;2电动车;3自行车;4步行 默认是汽车
private Integer vehicleType;
@PlanningListVariable
private List<Customer> customerList = new ArrayList<>();
......@@ -76,6 +79,20 @@ public class Technician {
this.maxDistanceMeter = maxDistanceMeter;
this.preferredlocationDistanceMap = preferredlocationDistanceMap;
}
public Technician(long id, String code, int maxCount, int maxMinute, int maxDistanceMeter, Integer vehicleType, Depot depot,
int startTime, int endTime, Set<String> skills, Map<String, Long> preferredlocationDistanceMap) {
this.id = id;
this.code = code;
this.depot = depot;
this.startTime = startTime;
this.endTime = endTime;
this.skills = skills;
this.maxCount = maxCount;
this.maxMinute = maxMinute;
this.maxDistanceMeter = maxDistanceMeter;
this.preferredlocationDistanceMap = preferredlocationDistanceMap;
}
// ************************************************************************
// Complex methods
......@@ -114,10 +131,10 @@ public class Technician {
Location previousLocation = depot.getLocation();
for (Customer customer : customerList) {
totalDistance += previousLocation.getDistanceTo(customer.getLocation());
totalDistance += previousLocation.getDistanceTo(this.getVehicleType(),customer.getLocation());
previousLocation = customer.getLocation();
}
totalDistance += previousLocation.getDistanceTo(depot.getLocation());
totalDistance += previousLocation.getDistanceTo(this.getVehicleType(), depot.getLocation());
return totalDistance;
}
......
......@@ -210,8 +210,8 @@ public class BatchServiceImpl implements BatchService {
jdbcTemplate.update("delete from dispatch_order where team_id=? and batch_no=?", teamId, batchNo);
log.info("写入新批次技术员、工单数据, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo);
String sqlEngineer = "INSERT INTO dispatch_engineer (team_id, batch_no, engineer_code, engineer_name, x, y, max_num, max_minute, max_distance)\n"
+ "SELECT o.team_id,?,o.engineer_code, a.name , b.x, b.y , max_num, max_minute, max_distance FROM `org_team_engineer` o,engineer_info a,engineer_business b \r\n"
String sqlEngineer = "INSERT INTO dispatch_engineer (team_id, batch_no, engineer_code, engineer_name, x, y, max_num, max_minute, max_distance, vehicle_type)\n"
+ "SELECT o.team_id,?,o.engineer_code, a.name , b.x, b.y , max_num, max_minute, max_distance, b.vehicle FROM `org_team_engineer` o,engineer_info a,engineer_business b \r\n"
+ " WHERE o.team_id=? AND `status`=1\r\n"
+ " AND o.engineer_code=a.engineer_code AND a.engineer_code = b.engineer_code \r\n"
+ " AND b.x IS NOT NULL AND b.x !=''" + " order by a.engineer_code asc";
......
......@@ -240,7 +240,7 @@ public class DataUtils {
Location locationi = locationIndex.get(i + 1);
for (int j = 0; j < pathMatrix[i].length; j++) {
Location locationj = locationIndex.get(j + 1);
locationi.getDistanceMap().put(locationj, pathMatrix[i][j]);
locationi.getDistanceMap(1).put(locationj, pathMatrix[i][j]);
}
}
......@@ -259,7 +259,7 @@ public class DataUtils {
Location locationi = locationIndex.get(i + 1);
for (int j = 0; j < pathTimeMatrix[i].length; j++) {
Location locationj = locationIndex.get(j + 1);
locationi.getDistanceTimeMap().put(locationj, pathTimeMatrix[i][j]);
locationi.getDistanceTimeMap(1).put(locationj, pathTimeMatrix[i][j]);
}
}
......
......@@ -72,12 +72,12 @@ public class DispatchSolutionUtils {
startPath = technician.getDepot().getStartTime();
// endPath = startPath +
// customer.getLocation().getPathTimeTo(technician.getDepot().getLocation());
endPath = startPath + technician.getDepot().getLocation().getPathTimeTo(customer.getLocation());
endPath = startPath + technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(),customer.getLocation());
} else {
startPath = previousCustomer.getDepartureTime();
// endPath = startPath +
// customer.getLocation().getPathTimeTo(previousCustomer.getLocation());
endPath = startPath + previousCustomer.getLocation().getPathTimeTo(customer.getLocation());
endPath = startPath + previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(),customer.getLocation());
}
if (customer.getArrivalTime() > customer.getEndTime()) {
......
......@@ -26,7 +26,7 @@ import lombok.Data;
*/
public class RoadDistanceUtils {
public static String URL = "https://api.map.baidu.com/routematrix/v2/riding?";
public static String URL = "https://api.map.baidu.com/routematrix/v2/";
public static String AK = "doR30pE7R0I7ivGLwMpkpsTT4bos9Akg";
/**
......@@ -42,20 +42,21 @@ public class RoadDistanceUtils {
*
* @param from
* @param to
* @param vehicleType 不能为空
* @return
*/
public static Distance getDistance(Location from, Location to) {
public static Distance getDistance(Location from, Location to, int vehicleType) {
try {
String key = from.getLongitude() + "," + from.getLatitude() + ";" + to.getLongitude() + ","
+ to.getLatitude();
+ to.getLatitude() + "|" + vehicleType;
Distance distance = distanceCache.get(key);
if (null == distance) {
distance = getDistance(from.getLatitude() + "," + from.getLongitude(),
to.getLatitude() + "," + to.getLongitude());
if(null == distance) {
to.getLatitude() + "," + to.getLongitude(), vehicleType);
if (null == distance) {
Distance dis = new Distance();
return dis;
}else {
} else {
distanceCache.put(key, distance);
}
return distance;
......@@ -68,14 +69,34 @@ public class RoadDistanceUtils {
}
}
private static Distance getDistance(String yx1, String yx2) throws Exception {
private static Distance getDistance(String yx1, String yx2, int vehicleType) throws Exception {
Map<String, String> params = new HashMap<String, String>();
params.put("origins", yx1);
params.put("destinations", yx2);
params.put("ak", AK);
params.put("riding_type", "1");// 电动自行车
params.put("coord_type", "gcj02");
String text = requestGetAK(URL, params);
String url = "";
switch (vehicleType) {
case 1:
url = URL + "driving?";
break;
case 2:
params.put("riding_type", "1");// 电动自行车
url = URL + "riding?";
break;
case 3:
params.put("riding_type", "0");// 普通自行车
url = URL + "riding?";
break;
case 4:
url = URL + "walking?";
break;
}
String text = requestGetAK(url, params);
BDResult webResult = gson.fromJson(text, BDResult.class);
float dis = webResult.getResult().get(0).getDistance().getValue() / 1000F;
int time = webResult.getResult().get(0).getDuration().getValue();
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!