Commit cb2bca4d by 张晓

组装中心点偏好、location_list

1 parent 97be5dc6
......@@ -120,6 +120,13 @@
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
......@@ -127,6 +134,14 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.dituhui.pea.dispatch.common;
import com.dituhui.pea.dispatch.pojo.Location;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
......@@ -14,7 +15,10 @@ import java.util.stream.Collectors;
@Component
public class GeoDistanceCalculator {
private long calculateDistance(Location from, Location to) {
// 驾车每秒种平均距离(高德导航历史数据计算得出)
final float avgRate = 7.65F;
public long calculateDistance(Location from, Location to) {
if (from.equals(to)) {
return 0L;
}
......@@ -29,9 +33,7 @@ public class GeoDistanceCalculator {
}
private Map<Location, Map<Location, Long>> calculateBulkDistance(
Collection<Location> fromLocations,
Collection<Location> toLocations) {
private Map<Location, Map<Location, Long>> calculateBulkDistance(Collection<Location> fromLocations, Collection<Location> toLocations) {
return fromLocations.stream().collect(Collectors.toMap(
Function.identity(),
from -> toLocations.stream().collect(Collectors.toMap(
......@@ -41,9 +43,46 @@ public class GeoDistanceCalculator {
));
}
class Pair {
// 距离(米)
Long Distance;
// 距离对应耗时(秒)
Long Duration;
public Pair(Long distance, Long duration) {
Distance = distance;
this.Duration = duration;
}
}
private Map<Location, Map<Location, Pair>> calculateBulkDistanceDuration(Collection<Location> fromLocations, Collection<Location> toLocations) {
return fromLocations.stream().collect(Collectors.toMap(
Function.identity(),
from -> toLocations.stream().collect(Collectors.toMap(
Function.identity(),
to -> {
long distance = calculateDistance(from, to);
long duration = Math.round(distance / avgRate);
return new Pair(distance, duration);
}
))
));
}
public void initDistanceMaps(Collection<Location> locationList) {
Map<Location, Map<Location, Long>> distanceMatrix = calculateBulkDistance(locationList, locationList);
locationList.forEach(location -> location.setDistanceMap(distanceMatrix.get(location)));
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);
});
});
}
}
package com.dituhui.pea.dispatch.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.dispatch.entity.DispatchBatch;
import com.dituhui.pea.dispatch.service.BatchService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author zhangx
*/
@Slf4j
@RequestMapping("/dispatch-pre")
@RestController
public class BatchController {
@Autowired
BatchService batchService;
@Data
class DispatchBatchDTO {
String groupId;
String batchNo;
int engineerNum;
int orderNum;
LocalDateTime startTime;
LocalDateTime endTime;
String status;
}
@GetMapping("/test")
public Result<?> test() {
log.info("test");
try {
List<String> customerWindowslines = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/customerWindows.csv")), "utf-8");
return Result.success(customerWindowslines);
} catch (FileNotFoundException e) {
log.error("test error", e);
return Result.failed(e.getMessage());
}
}
@GetMapping("/test2")
public Result<?> test2() {
log.info("test");
try {
List<String> customerWindowslines = IOUtils.readLines(new ClassPathResource("data/customerWindows.csv").getInputStream(), "utf-8");
return Result.success(customerWindowslines);
} catch (FileNotFoundException e) {
log.error("test error", e);
return Result.failed(e.getMessage());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/*
* 检查指定日期的小组是否有在运行的批次任务,有则返回,没有则创建后返回批次码
*/
@GetMapping("/batch/build/{groupId}/{day}")
public Result<?> buildBatch(@PathVariable String groupId, @PathVariable String day) {
log.info("buildBatch, groupId:{}, day:{}", groupId, day);
try {
String batchNo = batchService.buildBatchNo(groupId, day);
DispatchBatch batch = batchService.queryBatch(groupId, batchNo);
DispatchBatchDTO batchDTO = new DispatchBatchDTO();
BeanUtil.copyProperties(batch, batchDTO, CopyOptions.create().setIgnoreNullValue(true));
return Result.success(batchDTO);
} catch (SQLException e) {
log.error("buildBatch error", e);
return Result.failed(e.getMessage());
}
}
@GetMapping("/batch/query/{groupId}/{batchNo}")
public Result<?> queryBatch(@PathVariable String groupId, @PathVariable String batchNo) {
log.info("buildBatch, groupId:{}, batchNo:{}", groupId, batchNo);
DispatchBatch batch = batchService.queryBatch(groupId, batchNo);
DispatchBatchDTO batchDTO = new DispatchBatchDTO();
BeanUtil.copyProperties(batch, batchDTO, CopyOptions.create().setIgnoreNullValue(true));
return Result.success(batchDTO);
}
}
......@@ -16,6 +16,7 @@
package com.dituhui.pea.dispatch.controller;
import com.dituhui.pea.dispatch.service.SolveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -35,6 +36,7 @@ public class DispatchController {
@Autowired
private DispatchService dispatchService;
@GetMapping("/manual")
public Result<?> manualDispatch(
@RequestParam(value = "unimprovedSecondsSpentLimit", required = false) Long unimprovedSecondsSpentLimit,
......
package com.dituhui.pea.dispatch.controller;
import cn.hutool.core.map.MapUtil;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.dispatch.constraint.DispatchConstraintProvider;
import com.dituhui.pea.dispatch.pojo.Customer;
import com.dituhui.pea.dispatch.pojo.DispatchSolution;
import com.dituhui.pea.dispatch.pojo.Technician;
import com.dituhui.pea.dispatch.service.ExtractService;
import com.dituhui.pea.dispatch.service.SolveService;
import lombok.extern.slf4j.Slf4j;
import org.optaplanner.core.api.score.buildin.hardsoftlong.HardSoftLongScore;
import org.optaplanner.core.api.solver.SolverManager;
import org.optaplanner.core.api.solver.SolverStatus;
import org.optaplanner.core.config.solver.SolverConfig;
import org.optaplanner.core.config.solver.SolverManagerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
import java.util.*;
/**
* @author zhangx
*/
@Slf4j
@RequestMapping("/dispatch-pre")
@RestController
public class PrepareController {
@Autowired
ExtractService extractService;
@Autowired
SolveService solveService;
private SolverManager<DispatchSolution, UUID> solverManager;
public PrepareController() {
SolverConfig solverConfig = new SolverConfig().withSolutionClass(DispatchSolution.class);
solverConfig.withEntityClassList(Arrays.asList(Technician.class, Customer.class));// 这里不能漏掉,否则约束不生效
solverConfig.withConstraintProviderClass(DispatchConstraintProvider.class);
solverConfig.withTerminationSpentLimit(Duration.ofSeconds(10));
solverManager = SolverManager.create(solverConfig, new SolverManagerConfig());
}
/*
* 检查指定日期的小组是否有在运行的批次任务,有则返回,没有则创建后返回批次码
*/
@GetMapping("/prepare/solveTest/{groupId}/{batchNo}")
public Result<?> prepareAndSolve(@PathVariable String groupId, @PathVariable String batchNo) {
log.info("prepareSolve, groupId:{}, day:{}", groupId, batchNo);
DispatchSolution solution = solveService.prepareAndSolveSolution(groupId, batchNo);
List<Technician> technicianList = solution.getTechnicianList();
List<Customer> customerList = solution.getCustomerList();
HardSoftLongScore score = solution.getScore();
log.info("prepareSolve done, groupId:{}, day:{}, score:{}", groupId, batchNo, score.toString());
Map<String, Object> resultMap = MapUtil.builder(new HashMap<String, Object>()).put("score", score).put("technicians", technicianList).put("customer-size", customerList.size()).build();
return Result.success(resultMap);
}
// 异步任务运行 todo
@GetMapping("/prepare/solveAsync/{groupId}/{batchNo}")
public Result<?> solveAsync(@PathVariable String groupId, @PathVariable String batchNo) {
log.info("调用引擎处理-异步处理, groupId:{}, batchNo:{}", groupId, batchNo);
UUID problemId = solveService.generateProblemId(groupId, batchNo);
// 提交问题开始求解
DispatchSolution problem = solveService.prepareSolution(groupId, batchNo);
solverManager.solveAndListen(problemId, id -> problem,
this.extractService::saveAndExtractSolution);
log.error("调用引擎处理-异步处理, 已触发异步, groupId:{}, batchNo:{}", groupId, batchNo);
return Result.success("已触发异步执行");
}
@GetMapping("/prepare/solveStatus/{groupId}/{batchNo}")
public Result<?> solveStatus(@PathVariable String groupId, @PathVariable String batchNo) {
log.info("查询引擎处理状态, groupId:{}, batchNo:{}", groupId, batchNo);
UUID problemId = solveService.generateProblemId(groupId, batchNo);
SolverStatus status = solverManager.getSolverStatus(problemId);
log.info("查询引擎处理状态, groupId:{}, batchNo:{}, status:{}", groupId, batchNo, status.toString());
return Result.success(status);
}
@GetMapping("/prepare/solveStop/{groupId}/{batchNo}")
public Result<?> solveStop(@PathVariable String groupId, @PathVariable String batchNo) {
log.info("停止引擎处理批次, groupId:{}, batchNo:{}", groupId, batchNo);
UUID problemId = solveService.generateProblemId(groupId, batchNo);
solverManager.terminateEarly(problemId);
SolverStatus status = solverManager.getSolverStatus(problemId);
log.info("停止引擎处理批次, groupId:{}, batchNo:{}, status:{}", groupId, batchNo, status.toString());
return Result.success(status);
}
}
......@@ -16,10 +16,7 @@
package com.dituhui.pea.dispatch.service.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.UncheckedIOException;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
......@@ -45,6 +42,7 @@ import org.optaplanner.core.config.solver.termination.TerminationConfig;
import org.optaplanner.persistence.jackson.impl.domain.solution.JacksonSolutionFileIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
......@@ -66,7 +64,7 @@ public class DispatchServiceImpl implements DispatchService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public Result<?> manualDispatch(long unimprovedSecondsSpentLimit, long secondsSpentLimit) throws UncheckedIOException, FileNotFoundException {
public Result<?> manualDispatch(long unimprovedSecondsSpentLimit, long secondsSpentLimit) throws UncheckedIOException, IOException {
logger.info("{}", "invoke manualDispatch");
// 创建解决方案对象
......@@ -135,8 +133,8 @@ public class DispatchServiceImpl implements DispatchService {
}
private static Map<String, Integer> loadCustomerCodeServiceTimeMap()
throws UncheckedIOException, FileNotFoundException {
List<String> customerServiceTime = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/customerServiceTime.csv")),
throws UncheckedIOException, IOException {
List<String> customerServiceTime = IOUtils.readLines(new ClassPathResource("data/customerServiceTime.csv").getInputStream(),
"utf-8");
Map<String, Integer> customerCodeServiceTimeMap = new HashMap<String, Integer>();// code-time
for (int i = 0; i < customerServiceTime.size(); i++) {
......@@ -148,9 +146,9 @@ public class DispatchServiceImpl implements DispatchService {
}
private static Map<String, Map<String, Long>> loadPreferredlocationDistanceMap()
throws UncheckedIOException, FileNotFoundException {
throws UncheckedIOException, IOException {
List<String> technicianCodeLocation = IOUtils
.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/technicianLocation.csv")), "utf-8");
.readLines(new ClassPathResource("data/technicianLocation.csv").getInputStream(), "utf-8");
Map<String, String> technicianCodeLocationMap = new HashMap<String, String>();// 序号-code
for (int i = 0; i < technicianCodeLocation.size(); i++) {
String line = technicianCodeLocation.get(i);
......@@ -159,7 +157,7 @@ public class DispatchServiceImpl implements DispatchService {
}
List<String> customerCodeLocation = IOUtils
.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/customerLocation.csv")), "utf-8");
.readLines(new ClassPathResource("data/customerLocation.csv").getInputStream(), "utf-8");
Map<String, String> customerCodeLocationMap = new HashMap<String, String>();// 序号-code
for (int i = 0; i < customerCodeLocation.size(); i++) {
String line = customerCodeLocation.get(i);
......@@ -207,8 +205,8 @@ public class DispatchServiceImpl implements DispatchService {
return 6378137 * c;
}
private static Map<String, String> loadCustomerCodeSkillMap() throws UncheckedIOException, FileNotFoundException {
List<String> customerSkill = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/customerSkill.csv")), "utf-8");
private static Map<String, String> loadCustomerCodeSkillMap() throws UncheckedIOException, IOException {
List<String> customerSkill = IOUtils.readLines(new ClassPathResource("data/customerSkill.csv").getInputStream(), "utf-8");
Map<String, String> customerCodeSkillMap = new HashMap<String, String>();// code-技能
for (int i = 0; i < customerSkill.size(); i++) {
String line = customerSkill.get(i);
......@@ -219,8 +217,8 @@ public class DispatchServiceImpl implements DispatchService {
}
private static Map<String, Set<String>> loadTechnicianCodeSkillsMap()
throws UncheckedIOException, FileNotFoundException {
List<String> technicianSkills = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/technicianSkills.csv")), "utf-8");
throws UncheckedIOException, IOException {
List<String> technicianSkills = IOUtils.readLines(new ClassPathResource("data/technicianSkills.csv").getInputStream(), "utf-8");
Map<String, Set<String>> technicianCodeSkillsMap = new HashMap<String, Set<String>>();// code-技能
for (int i = 0; i < technicianSkills.size(); i++) {
String line = technicianSkills.get(i);
......@@ -237,8 +235,8 @@ public class DispatchServiceImpl implements DispatchService {
return technicianCodeSkillsMap;
}
private static Map<Integer, String> loadTechnicianIndex() throws UncheckedIOException, FileNotFoundException {
List<String> technicianIndexlines = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/technicianIndex.csv")), "utf-8");
private static Map<Integer, String> loadTechnicianIndex() throws UncheckedIOException, IOException {
List<String> technicianIndexlines = IOUtils.readLines(new ClassPathResource("data/technicianIndex.csv").getInputStream(), "utf-8");
Map<Integer, String> technicianIndexMap = new HashMap<Integer, String>();// 序号-code
for (int i = 0; i < technicianIndexlines.size(); i++) {
technicianIndexMap.put(i + 1, technicianIndexlines.get(i));
......@@ -246,8 +244,8 @@ public class DispatchServiceImpl implements DispatchService {
return technicianIndexMap;
}
private static Map<Integer, String> loadCustomerIndex() throws UncheckedIOException, FileNotFoundException {
List<String> customerIndexlines = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/customerIndex.csv")), "utf-8");
private static Map<Integer, String> loadCustomerIndex() throws UncheckedIOException, IOException {
List<String> customerIndexlines = IOUtils.readLines(new ClassPathResource("data/customerIndex.csv").getInputStream(), "utf-8");
Map<Integer, String> customerIndexMap = new HashMap<Integer, String>();// 序号-code
for (int i = 0; i < customerIndexlines.size(); i++) {
customerIndexMap.put(i + 1, customerIndexlines.get(i));
......@@ -257,14 +255,14 @@ public class DispatchServiceImpl implements DispatchService {
private static DispatchSolution createVehicleRoutingSolution(Map<Integer, String> customerIndexMap,
Map<Integer, String> technicianIndexMap, Map<String, Set<String>> technicianCodeSkillsMap,
Map<String, String> customerCodeSkillMap, Map<String, Map<String, Long>> preferredlocationDistanceMap, Map<String, Integer> customerCodeServiceTimeMap) throws UncheckedIOException, FileNotFoundException {
Map<String, String> customerCodeSkillMap, Map<String, Map<String, Long>> preferredlocationDistanceMap, Map<String, Integer> customerCodeServiceTimeMap) throws UncheckedIOException, IOException {
DispatchSolution vehicleRoutingSolution = new DispatchSolution();
// 翻转map
Map<String, Integer> customerIndexMap2 = customerIndexMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
// 初始化距离矩阵
List<String> pathMatrixlines = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/pathMatrix.csv")), "utf-8");
List<String> pathMatrixlines = IOUtils.readLines(new ClassPathResource("data/pathMatrix.csv").getInputStream(), "utf-8");
long[][] pathMatrix = new long[customerIndexMap.keySet().size() + 1][customerIndexMap.keySet().size() + 1];
for (int i = 0; i < pathMatrixlines.size(); i++) {
String line = pathMatrixlines.get(i);
......@@ -287,7 +285,7 @@ public class DispatchServiceImpl implements DispatchService {
}
// 初始化时间矩阵
List<String> pathTimeMatrixlines = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/pathTimeMatrix.csv")), "utf-8");
List<String> pathTimeMatrixlines = IOUtils.readLines(new ClassPathResource("data/pathTimeMatrix.csv").getInputStream(), "utf-8");
long[][] pathTimeMatrix = new long[customerIndexMap.keySet().size() + 1][customerIndexMap.keySet().size() + 1];
for (int i = 0; i < pathTimeMatrixlines.size(); i++) {
String line = pathTimeMatrixlines.get(i);
......@@ -306,7 +304,8 @@ public class DispatchServiceImpl implements DispatchService {
}
// 初始化订单服务窗
List<String> customerWindowslines = IOUtils.readLines(new FileInputStream(ResourceUtils.getFile("classpath:data/customerWindows.csv")), "utf-8");
List<String> customerWindowslines = IOUtils.readLines(new ClassPathResource("data/customerWindows.csv").getInputStream(), "utf-8");
Map<Integer, Integer> customerStartMap = new HashMap<Integer, Integer>();
Map<Integer, Integer> customerEndMap = new HashMap<Integer, Integer>();
for (int i = 0; i < customerWindowslines.size(); i++) {
......
......@@ -11,18 +11,16 @@ import com.dituhui.pea.dispatch.pojo.*;
import com.dituhui.pea.dispatch.service.ExtractService;
import com.dituhui.pea.dispatch.service.SolveService;
import lombok.extern.slf4j.Slf4j;
import org.optaplanner.core.api.solver.*;
import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
import org.optaplanner.core.config.solver.SolverConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
......@@ -55,7 +53,8 @@ public class SolveServiceImpl implements SolveService {
// 查询技术员所有技能集
private List<String> queryEngineerSkills(String engineerCode) {
List<String> result = new ArrayList<>();
String sql = "select concat( b.brand, b.type, b.skill) as skill from engineer_skill a left join product_category b \n" + "\ton a.category_id= b.product_category_id where a.engineer_code=? and a.status=1 ";
String sql = "select concat( b.brand, b.type, b.skill) as skill from engineer_skill a left join product_category b \n"
+ "\ton a.category_id= b.product_category_id where a.engineer_code=? and a.status=1 ";
Object[] param = {engineerCode};
result = jdbcTemplate.queryForList(sql, param, String.class);
return result;
......@@ -81,23 +80,6 @@ public class SolveServiceImpl implements SolveService {
oneDepot = new Depot(oneGroup.getId(), oneGroup.getGroupId(), deptLocation, 60 * 8, 60 * 18);
// depotlist 技术员中收点列表
ArrayList<Depot> depotList = new ArrayList<Depot>();
// technicianList
ArrayList<Technician> technicianList = new ArrayList<>();
dispatchEngineerRepo.findByGroupIdAndBatchNo(groupId, batchNo).forEach(engineer -> {
Location location = new Location(engineer.getId(), engineer.getEngineerCode(), "中心点", Double.parseDouble(engineer.getX()), Double.parseDouble(engineer.getY()));
Depot depot = new Depot(engineer.getId(), engineer.getEngineerCode(), location, 60 * 8, 60 * 18);
depotList.add(depot);
List<String> skillList = queryEngineerSkills(engineer.getEngineerCode());
// todo
// Technician vehicle = new Technician(engineer.getId(), engineer.getEngineerCode(),
// engineer.getMaxNum(), engineer.getMaxMinute(), engineer.getMaxDistance() * 1000, depot,
// 60 * 8, 60 * 18, Set.copyOf(skillList), ? );
// technicianList.add(vehicle);
});
// customerlist
ArrayList<Customer> customerList = new ArrayList<>();
......@@ -121,6 +103,30 @@ public class SolveServiceImpl implements SolveService {
customerList.add(customer);
});
// depotlist 技术员中收点列表
ArrayList<Depot> depotList = new ArrayList<Depot>();
// technicianList
ArrayList<Technician> technicianList = new ArrayList<>();
dispatchEngineerRepo.findByGroupIdAndBatchNo(groupId, batchNo).forEach(engineer -> {
Location location = new Location(engineer.getId(), engineer.getEngineerCode(), "中心点", Double.parseDouble(engineer.getX()), Double.parseDouble(engineer.getY()));
Depot depot = new Depot(engineer.getId(), engineer.getEngineerCode(), location, 60 * 8, 60 * 18);
depotList.add(depot);
List<String> skillList = queryEngineerSkills(engineer.getEngineerCode());
// 距离偏好map
Map<String, Long> preferedLoctionDistanceMap = new HashMap<String, Long>();
customerList.forEach(customer -> {
long distance= distanceCalculator.calculateDistance(location, customer.getLocation());
preferedLoctionDistanceMap.put(engineer.getEngineerCode(), distance);
});
Technician vehicle = new Technician(engineer.getId(), engineer.getEngineerCode(),
engineer.getMaxNum(), engineer.getMaxMinute(), engineer.getMaxDistance() * 1000, depot,
60 * 8, 60 * 18, Set.copyOf(skillList), preferedLoctionDistanceMap );
technicianList.add(vehicle);
});
//locationlist
List<Location> locationList = Stream.concat(depotList.stream().map(Depot::getLocation), customerList.stream().map(Customer::getLocation)).collect(Collectors.toList());
......
package com.dituhui.pea.dispatch;
import com.dituhui.pea.dispatch.pojo.DispatchSolution;
import com.dituhui.pea.dispatch.service.SolveService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
class SolveServiceTest {
@Autowired
SolveService solveService;
String groupId = "gsuzhou";
String batchNo = "20230705-1500";
@Test
public void test1() {
log.info("init");
DispatchSolution solution = solveService.prepareAndSolveSolution(groupId, batchNo);
log.info("result:{}", solution);
log.info("done");
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!