设备日历接口修改

parent 1dd2520c
This diff is collapsed.
......@@ -3,7 +3,9 @@ package com.aps.common.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.databind.DeserializationFeature;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
......@@ -27,10 +29,38 @@ public class JsonFileReader {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 添加更多配置确保字段正确映射
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
// 3. 反序列化JSON到对象列表
return objectMapper.readValue(jsonContent,
objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
}
}
public static <T> List<T> readListFromFile(String filePath, Class<T> clazz) throws IOException {
// 1. 检查文件是否存在
File file = new File(filePath);
if (!file.exists()) {
throw new IOException("File not found: " + filePath);
}
// 2. 读取文件内容
Scanner scanner = new Scanner(file, StandardCharsets.UTF_8.name()).useDelimiter("\\A");
String jsonContent = scanner.hasNext() ? scanner.next() : "";
// 3. 配置ObjectMapper支持Java 8时间API
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 添加更多配置确保字段正确映射
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
// 4. 反序列化JSON到对象列表
return objectMapper.readValue(jsonContent,
objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
}
}
\ No newline at end of file
package com.aps.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*") // 修改这里
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
// 允许所有域名访问,生产环境建议指定具体域名
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
config.setMaxAge(3600L);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
\ No newline at end of file
package com.aps.controller.gantt;
import com.aps.common.util.R;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
@Slf4j
@RestController
@RequestMapping("/api/files")
@Tag(name = "文件上传管理", description = "文件上传管理")
public class FileUploadController {
// 从配置文件中获取文件存储目录
@Value("${file.upload.dir:uploads}")
private String uploadDir;
private String absoluteUploadDir;
@PostConstruct
public void init() {
// 获取上传目录的绝对路径
absoluteUploadDir = Paths.get(uploadDir).toAbsolutePath().toString();
// 确保上传目录存在
File directory = new File(absoluteUploadDir);
if (!directory.exists()) {
boolean created = directory.mkdirs();
if (created) {
log.info("创建上传目录: {}", absoluteUploadDir);
} else {
log.error("创建上传目录失败: {}", absoluteUploadDir);
}
} else {
log.info("使用已存在的上传目录: {}", absoluteUploadDir);
}
}
@PostMapping(value = "/upload/machines", consumes = "multipart/form-data")
@Operation(summary = "上传machines.json文件", description = "上传machines.json文件")
@RequestBody(description = "选择要上传的 machines.json 文件", required = true,
content = @Content(mediaType = "multipart/form-data"))
public R<String> uploadMachines(
@Parameter(description = "选择要上传的 machines.json 文件")
@RequestParam("file") MultipartFile file) {
return uploadFile(file, "machines.json");
}
@PostMapping(value = "/upload/orders", consumes = "multipart/form-data")
@Operation(summary = "上传orders.json文件", description = "上传orders.json文件")
@RequestBody(description = "选择要上传的 orders.json 文件", required = true,
content = @Content(mediaType = "multipart/form-data"))
public R<String> uploadOrders(
@Parameter(description = "选择要上传的 orders.json 文件")
@RequestParam("file") MultipartFile file) {
return uploadFile(file, "orders.json");
}
@PostMapping(value = "/upload/products", consumes = "multipart/form-data")
@Operation(summary = "上传products.json文件", description = "上传products.json文件")
@RequestBody(description = "选择要上传的 products.json 文件", required = true,
content = @Content(mediaType = "multipart/form-data"))
public R<String> uploadProducts(
@Parameter(description = "选择要上传的 products.json 文件")
@RequestParam("file") MultipartFile file) {
return uploadFile(file, "products.json");
}
private R<String> uploadFile(MultipartFile file, String expectedFileName) {
if (file.isEmpty()) {
return R.failed("上传文件不能为空");
}
// 检查文件名
if (!file.getOriginalFilename().equals(expectedFileName)) {
return R.failed("请上传正确的文件: " + expectedFileName);
}
try {
// 保存文件到指定目录
String filePath = Paths.get(absoluteUploadDir, expectedFileName).toString();
file.transferTo(new File(filePath));
log.info("文件上传成功: {}", filePath);
return R.ok("文件上传成功: " + expectedFileName);
} catch (IOException e) {
log.error("文件上传失败", e);
return R.failed("文件上传失败: " + e.getMessage());
}
}
/**
* 获取上传文件的路径
* @param fileName 文件名
* @return 文件路径
*/
public String getUploadedFilePath(String fileName) {
return Paths.get(absoluteUploadDir, fileName).toString();
}
/**
* 检查文件是否存在
* @param fileName 文件名
* @return 是否存在
*/
public boolean isFileUploaded(String fileName) {
String filePath = Paths.get(absoluteUploadDir, fileName).toString();
return new File(filePath).exists();
}
}
\ No newline at end of file
package com.aps.entity.Gantt;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Schema(name = "产品甘特图数据模型", description = "产品甘特图数据模型")
public class ProductGanttVO {
@Schema(description = "产品ID")
private Integer id;
@Schema(description = "产品名称")
private String productName;
@Schema(description = "产品类型")
private Integer productType;
@Schema(description = "产品编号")
private Integer productId;
@Schema(description = "数量")
private Integer quantity;
@Schema(description = "编码")
private String code;
@Schema(description = "开始日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
private LocalDateTime startDate;
@Schema(description = "结束日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
private LocalDateTime endDate;
@Schema(description = "车间ID")
private Integer shopId;
@Schema(description = "车间名称")
private String shopName;
@Schema(description = "状态")
private String status;
@Schema(description = "头ID")
private Integer headerId;
@Schema(description = "头名称")
private String headerName;
@Schema(description = "任务列表")
private List<TaskVO> list;
}
\ No newline at end of file
package com.aps.entity.Gantt;
import com.aps.entity.basic.ShiftVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Schema(name = "资源甘特图数据模型", description = "资源甘特图数据模型")
public class ResourceGanttVO {
@Schema(description = "设备ID")
private Integer id;
@Schema(description = "设备名称")
private String name;
@Schema(description = "设备类型")
private String type;
@Schema(description = "是否可更换")
private Integer change;
@Schema(description = "是否可拆分")
private Integer split;
@Schema(description = "部门ID")
private Integer departmentId;
@Schema(description = "部门名称")
private String departmentName;
@Schema(description = "车间名称")
private String shopName;
@Schema(description = "车间ID")
private Integer shopId;
@Schema(description = "设备编码")
private String code;
@Schema(description = "任务列表")
private List<TaskVO> list;
private ShiftVO shift;
}
\ No newline at end of file
package com.aps.entity.Gantt;
import com.aps.entity.basic.Shift;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Schema(name = "任务数据模型", description = "任务数据模型")
public class TaskVO {
@Schema(description = "任务ID")
private Integer id;
@Schema(description = "计划ID")
private Integer planId;
@Schema(description = "产品类型")
private Integer productType;
@Schema(description = "产品名称")
private String productName;
@Schema(description = "产品ID")
private Integer productId;
@Schema(description = "数量")
private Integer quantity;
@Schema(description = "开始时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime start;
@Schema(description = "结束时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime end;
@Schema(description = "开始时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime absoluteStart;
@Schema(description = "结束时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime absoluteEnd;
@Schema(description = "准备时间")
private Integer setup;
@Schema(description = "收尾时间")
private Integer teardown;
@Schema(description = "设备更换时间")
private Integer equipChange;
@Schema(description = "设备冷却时间")
private Integer equipCooling;
@Schema(description = "设备类型")
private String equipType;
@Schema(description = "设备名称")
private String equipName;
@Schema(description = "持续时间")
private Integer duration;
@Schema(description = "设备ID")
private Integer equipId;
@Schema(description = "车间ID")
private Integer shopId;
@Schema(description = "车间名称")
private String shopName;
//‘0’:已发布 ‘1’:未发布
@Schema(description = "状态")
private Integer status;
@Schema(description = "明细ID")
private Long detailId;
@Schema(description = "头ID")
private Integer headerId;
@Schema(description = "头名称")
private String headerName;
@Schema(description = "工序序号")
private Integer seq;
@Schema(description = "工序名称")
private String seqName;
private int processingTime; // 绝对处理时间(分钟)
private int absolutePreparationTime; // 新增:绝对准备时间
}
\ No newline at end of file
......@@ -12,10 +12,25 @@ public class Gene {
private int orderId;
private int productId;
private int operationId;
private String operationName; // 添加工序名称
private int machineId;
private int startTime; // 相对开始时间(分钟)
private int endTime; // 相对结束时间(分钟)
private int batchSize; // 批次大小(订单可拆分)
private List<GeneDetail> geneDetails; // 时间详情
private int processingTime; // 绝对处理时间(分钟)
private int Id;
private int sequenceId;
private int setupTime; // 换型时
private int teardownTime; // 后处理时间(收尾时间)
private int contantTime; // 常数时间
private int preTime;
private int absoluteStartTime; // 相对开始时间(分钟)
private int absoluteEndTime; // 相对结束时间(分钟)
private int absolutePreparationTime; // 新增:绝对前处理时间
private int absoluteTeardownTime; // 新增:绝对后处理时间
private int absoluteSetupTime; // 新增:绝对换型时间
}
\ No newline at end of file
......@@ -28,4 +28,21 @@ public class Holiday {
public void setEnd(LocalDateTime end) {
this.end = end;
}
/**
* 将Holiday转换为MaintenanceWindow
* @return 对应的MaintenanceWindow对象
*/
public MaintenanceWindow toMaintenanceWindow() {
return new MaintenanceWindow(this.start, this.end, "Holiday Period");
}
/**
* 将Holiday转换为MaintenanceWindow(可指定原因)
* @param reason 维护原因
* @return 对应的MaintenanceWindow对象
*/
public MaintenanceWindow toMaintenanceWindow(String reason) {
return new MaintenanceWindow(this.start, this.end, reason);
}
}
\ No newline at end of file
......@@ -10,4 +10,7 @@ public class MachineOption {
private int machineId;
private int processingTime; // 加工时间
private int setupTime; // 换型时间(如果与前一个产品不同)
private int teardownTime; // 收尾时间(后处理时间)
private int contantTime; // 常数时间
private int preTime; // 前处理时间
}
\ No newline at end of file
......@@ -8,6 +8,7 @@ public class MaintenanceWindow {
private LocalDateTime endTime;
private String reason;
public MaintenanceWindow() {}
public MaintenanceWindow(LocalDateTime startTime, LocalDateTime endTime, String reason) {
......@@ -16,6 +17,23 @@ public class MaintenanceWindow {
this.reason = reason;
}
/**
* 从Holiday对象构造MaintenanceWindow
* @param holiday 假期对象
*/
public MaintenanceWindow(Holiday holiday) {
this(holiday.getStart(), holiday.getEnd(), "Holiday Period");
}
/**
* 从Holiday对象构造MaintenanceWindow(可指定原因)
* @param holiday 假期对象
* @param reason 维护原因
*/
public MaintenanceWindow(Holiday holiday, String reason) {
this(holiday.getStart(), holiday.getEnd(), reason);
}
// Getters and Setters
public LocalDateTime getStartTime() {
return startTime;
......@@ -41,6 +59,8 @@ public class MaintenanceWindow {
this.reason = reason;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
......
......@@ -15,7 +15,7 @@ public class ScheduleChromosome {
private double tardiness;
private Map<Integer, Double> objectiveValues;
private LocalDateTime baseTime;
private long sceneId; // 新增场景ID字段
public ScheduleChromosome() {
this.genes = new ArrayList<>();
this.objectiveValues = new HashMap<>();
......
package com.aps.entity.basic;
import lombok.Data;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Set;
@Data
public class Shift {
private LocalTime startTime;
private LocalTime endTime;
......@@ -13,6 +16,12 @@ public class Shift {
private boolean isTemporaryShift;
private int priority;
private Integer status;//0:正常班次 1:临时班次 2:维修
// 添加设备ID和名称字段
private Integer machineId;
private String machineName;
public Shift() {}
......@@ -40,13 +49,7 @@ public class Shift {
this.days = days;
}
// 辅助方法:将数字转换为DayOfWeek
public Set<DayOfWeek> getDaysAsEnum() {
if (days == null) return null;
return days.stream()
.map(day -> DayOfWeek.of(day == 0 ? 7 : day)) // 处理周日(0)转换为7
.collect(java.util.stream.Collectors.toSet());
}
public LocalDateTime getShiftDate() {
return shiftDate;
......@@ -71,4 +74,28 @@ public class Shift {
public void setPriority(int priority) {
this.priority = priority;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getMachineId() {
return machineId;
}
public void setMachineId(Integer machineId) {
this.machineId = machineId;
}
public String getMachineName() {
return machineName;
}
public void setMachineName(String machineName) {
this.machineName = machineName;
}
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
import java.util.List;
@Data
public class ShiftVO {
private int id;
private String name;
private List<Shift> shifts;
private List<MaintenanceWindow> maintenanceWindows;
}
......@@ -153,9 +153,36 @@ public class AlgorithmScheduler6 {
}
int processingTime = machineOption.getProcessingTime() * batchSize;
int preTime = machineOption.getPreTime(); // 前处理时间(常数时间,与批次大小无关)
int setupTime = 0; // 换型时间默认为0,仅在产品变化时计算
int teardownTime = machineOption.getTeardownTime(); // 后处理时间(常数时间,与批次大小无关)
// 计算换型时间
// 查找该机器上一个任务
Gene lastGeneOnMachine = chromosome.getGenes().stream()
.filter(g -> g.getMachineId() == machine.getId())
.max(Comparator.comparingInt(Gene::getEndTime))
.orElse(null);
// 如果上一个任务的产品与当前任务不同,则需要换型时间
if (lastGeneOnMachine != null && lastGeneOnMachine.getProductId() != order.getProductId()) {
setupTime = machineOption.getSetupTime();
}
// 前处理时间可以在上一个工序未完成时开始,所以调整开始时间
int adjustedPrevTime = prevtime;
if (preTime > 0 && lastGeneOnMachine != null) {
// 前处理可以在上一个任务结束前preTime时间开始
adjustedPrevTime = lastGeneOnMachine.getEndTime() - preTime;
}
// List<GeneDetail> geneDetails = GetNextAvailableTime(
// machine, prevtime, -1, processingTime,
// chromosome.getGenes(), false, true
// );
List<GeneDetail> geneDetails = GetNextAvailableTime(
machine, prevtime, -1, processingTime,
machine, adjustedPrevTime, -1, processingTime + teardownTime + setupTime,
chromosome.getGenes(), false, true
);
......@@ -163,7 +190,7 @@ public class AlgorithmScheduler6 {
int endTime = geneDetails.stream().mapToInt(GeneDetail::getEndTime).max().orElse(0);
machine.setEarliestTime(endTime);
machine.setTotalTaskTime(machine.getTotalTaskTime() + processingTime);
machine.setTotalTaskTime(machine.getTotalTaskTime() + +teardownTime + setupTime);
Gene gene = new Gene();
gene.setOrderId(order.getId());
......@@ -175,6 +202,8 @@ public class AlgorithmScheduler6 {
gene.setEndTime(endTime);
gene.setProcessingTime(processingTime);
gene.setGeneDetails(deepCopyGeneDetailList(geneDetails));
gene.setId(chromosome.getGenes().size() + 1);
gene.setSequenceId(operation.getSequence());
chromosome.getGenes().add(gene);
}
}
......
This diff is collapsed.
package com.aps.service.plan;
import com.aps.common.util.JsonFileReader;
import com.aps.controller.gantt.FileUploadController;
import com.aps.entity.Schedule.GenVO;
import com.aps.entity.Schedule.MachineVO;
import com.aps.entity.basic.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class PlanResultService {
// 注入FileUploadController
@Autowired
private FileUploadController fileUploadController;
private final LocalDateTime baseTime = LocalDateTime.of(2025, 10, 1, 0, 0, 0);
public List<ScheduleChromosome> execute() {
try {
// 1. 读取数据
List<Machine> machines = loadData("machines.json", Machine.class);
List<Product> products = loadData("products.json", Product.class);
List<Order> orders = loadData("orders.json", Order.class);
// 设置机器信息到班次中
for (Machine machine : machines) {
if (machine.getShifts() != null) {
for (Shift shift : machine.getShifts()) {
shift.setMachineId(machine.getId());
shift.setMachineName(machine.getName());
}
}
// 调试:打印机器和班次信息
System.out.println("Machine: " + machine.getId() + ", Name: " + machine.getName());
if (machine.getShifts() != null) {
for (Shift shift : machine.getShifts()) {
System.out.println(" Shift: " + shift.getStartTime() + " - " + shift.getEndTime() +
", Status: " + shift.getStatus() +
", MachineId: " + shift.getMachineId() +
", MachineName: " + shift.getMachineName());
}
}
}
// 创建节假日
List<Holiday> holidays = Arrays.asList(
new Holiday(LocalDateTime.of(2025, 10, 1, 0, 0),
LocalDateTime.of(2025, 10, 7, 23, 59))
);
// 将节假日添加到所有设备中
addHolidaysToAllMachines(machines, holidays);
// 3. 创建调度服务
MachineSchedulerService machineScheduler = new MachineSchedulerService(
holidays, LocalDateTime.of(2025, 10, 1, 0, 0, 0));
// 4. 初始化机器时间线
for (Machine machine : machines) {
MachineTimeline timeline = machineScheduler.getOrCreateTimeline(machine);
machine.setAvailability(timeline.getSegments());
}
// 5. 执行调度算法
AlgorithmScheduler7 scheduler = new AlgorithmScheduler7(products, machines, orders, machineScheduler);
List<ScheduleChromosome> scheduleChromosomes = scheduler.RunAll();
// 对调度结果按照 fitness 由高到低排序
scheduleChromosomes.sort((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()));
// 为每个 ScheduleChromosome 分配场景ID(基于排序后的位置)
for (int i = 0; i < scheduleChromosomes.size(); i++) {
scheduleChromosomes.get(i).setSceneId(i + 1); // 场景ID从1开始
}
return scheduleChromosomes;
} catch (Exception e) {
throw new RuntimeException("调度执行失败", e);
}
}
/**
* 加载数据,优先从上传文件夹加载,如果不存在则从resources加载
*
* @param fileName 文件名
* @param clazz 类型
* @param <T> 泛型
* @return 数据列表
* @throws IOException IO异常
*/
private <T> List<T> loadData(String fileName, Class<T> clazz) throws IOException {
// 检查是否有上传的文件
if (fileUploadController.isFileUploaded(fileName)) {
String filePath = fileUploadController.getUploadedFilePath(fileName);
return JsonFileReader.readListFromFile(filePath, clazz);
} else {
// 使用默认的resources文件
return JsonFileReader.readListFromResources(fileName, clazz);
}
}
/**
* 将假期添加到所有设备的维护窗口中
* @param machines 设备列表
* @param holidays 假期列表
*/
private void addHolidaysToAllMachines(List<Machine> machines, List<Holiday> holidays) {
if (machines == null || holidays == null) {
return;
}
for (Machine machine : machines) {
// 确保维护窗口列表不为null
if (machine.getMaintenanceWindows() == null) {
machine.setMaintenanceWindows(new ArrayList<>());
}
for (Holiday holiday : holidays) {
// 将假期转换为维护窗口并添加到设备中
MaintenanceWindow maintenanceWindow = new MaintenanceWindow(holiday, "Holiday Period");
machine.addMaintenanceWindow(maintenanceWindow);
}
}
}
public GenVO convertGeneToGenVO(Gene gene, LocalDateTime baseTime) {
GenVO genVO = new GenVO();
genVO.setOrderId(String.valueOf(gene.getOrderId()));
genVO.setOperationId(gene.getOperationId());
genVO.setEquipId(gene.getMachineId());
genVO.setQuantity(BigDecimal.valueOf(gene.getBatchSize()));
genVO.setStartTime(baseTime.plusMinutes(gene.getStartTime()));
genVO.setEndTime(baseTime.plusMinutes(gene.getEndTime()));
genVO.setOperationName(""); // 从其他数据源获取
genVO.setEquipName(""); // 从其他数据源获取
return genVO;
}
// 批量转换
public List<GenVO> convertGeneListToGenVO(List<Gene> geneList, LocalDateTime baseTime) {
return geneList.stream()
.map(gene -> convertGeneToGenVO(gene, baseTime))
.collect(Collectors.toList());
}
public List<MachineVO> convertMachineListToVO(List<Machine> machines) {
return machines.stream()
.map(this::convertToVO)
.collect(Collectors.toList());
}
private MachineVO convertToVO(Machine machine) {
MachineVO machineVO = new MachineVO();
machineVO.setId(machine.getId());
machineVO.setEquipId(String.valueOf(machine.getId()));
machineVO.setEquipName(machine.getName());
// 注意:tasks 字段需要在其他地方设置,因为 Machine 类中没有任务信息
return machineVO;
}
}
\ No newline at end of file
......@@ -2,6 +2,10 @@ server:
port: 8181 # 修改为你想要的端口号
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
mvc:
pathmatch:
matching-strategy: ant_path_matcher # Spring Boot 2.6+ 需要这个配置
......@@ -37,7 +41,11 @@ spring:
username: sa
password: root_mes123456
# MyBatis-Plus配置
# 文件上传配置
file:
upload:
dir: uploads
mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml # Mapper XML路径
type-aliases-package: com.aps.entity # 实体类包路径
......
......@@ -7,32 +7,37 @@
"days": [1, 2, 3, 4, 5],
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": false,
"priority": 0
"priority": 0,
"status":0
},{
"startTime": "18:00:00",
"endTime": "20:00:00",
"days": [1, 2, 3, 4, 5],
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": true,
"priority": 0
"priority": 0,
"status":1
},{
"startTime": "08:00:00",
"endTime": "18:00:00",
"days": [0],
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": true,
"priority": 0
"priority": 0,
"status":1
},{
"startTime": "08:00:00",
"endTime": "18:00:00",
"days": null,
"shiftDate": "2025-10-01T00:00:00",
"temporaryShift": true,
"priority": 0
"priority": 0,
"status":1
}],
"maintenanceWindows": [{
"startTime": "2025-10-08T10:00:00",
"endTime": "2025-10-10T12:00:00"
"endTime": "2025-10-10T12:00:00",
"status":2
}]
}, {
"id": 2,
......@@ -43,7 +48,8 @@
"days": [1, 2, 3,4,5],
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": false,
"priority": 0
"priority": 0,
"status":0
}],
"maintenanceWindows": null
}, {
......@@ -55,7 +61,8 @@
"days": [1, 2, 3, 4, 5],
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": false,
"priority": 0
"priority": 0,
"status":0
}],
"maintenanceWindows": null
}, {
......@@ -67,7 +74,8 @@
"days": [1, 2, 3, 4, 5],
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": false,
"priority": 0
"priority": 0,
"status":0
}],
"maintenanceWindows": null
}, {
......@@ -79,7 +87,8 @@
"days": [1, 2, 3, 4, 5],
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": false,
"priority": 0
"priority": 0,
"status":0
}],
"maintenanceWindows": null
}]
\ No newline at end of file
......@@ -11,7 +11,9 @@
{
"machineId": 2,
"processingTime": 11,
"setupTime": 59
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
}
],
"isInterrupt": false
......@@ -24,12 +26,16 @@
{
"machineId": 3,
"processingTime": 5,
"setupTime": 45
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
},
{
"machineId": 5,
"processingTime": 21,
"setupTime": 11
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
}
],
"isInterrupt": false
......@@ -42,7 +48,9 @@
{
"machineId": 5,
"processingTime": 6,
"setupTime": 40
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
}
],
"isInterrupt": false
......@@ -55,12 +63,16 @@
{
"machineId": 1,
"processingTime": 19,
"setupTime": 48
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
},
{
"machineId": 4,
"processingTime": 20,
"setupTime": 51
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
}
],
"isInterrupt": false
......@@ -79,7 +91,9 @@
{
"machineId": 1,
"processingTime": 5,
"setupTime": 30
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
}
],
"isInterrupt": false
......@@ -92,7 +106,9 @@
{
"machineId": 2,
"processingTime": 22,
"setupTime": 47
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
}
],
"isInterrupt": false
......@@ -105,12 +121,16 @@
{
"machineId": 1,
"processingTime": 8,
"setupTime": 35
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
},
{
"machineId": 5,
"processingTime": 28,
"setupTime": 31
"setupTime": 0,
"teardownTime": 0,
"preTime": 0
}
],
"isInterrupt": false
......
......@@ -4,6 +4,7 @@ package com.aps.demo;
import com.aps.common.util.JsonFileReader;
import com.aps.entity.basic.*;
import com.aps.service.plan.AlgorithmScheduler6;
import com.aps.service.plan.AlgorithmScheduler7;
import com.aps.service.plan.MachineSchedulerService;
import java.time.LocalDateTime;
......@@ -82,7 +83,7 @@ public class MachineSchedulerTest {
}
AlgorithmScheduler6 scheduler = new AlgorithmScheduler6(products,machines,orders, machineScheduler);
AlgorithmScheduler7 scheduler = new AlgorithmScheduler7(products,machines,orders, machineScheduler);
List<ScheduleChromosome> scheduleChromosomes = scheduler.RunAll();
for (ScheduleChromosome run:scheduleChromosomes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment