Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
H
HYH.APSJ
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
佟礼
HYH.APSJ
Commits
1e00c75d
Commit
1e00c75d
authored
Jul 27, 2026
by
DESKTOP-VKRD9QF\Administration
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 修复自动插单排程异常
parent
74589725
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
397 additions
and
43 deletions
+397
-43
IdGroupingWithDualSerial.java
...a/com/aps/service/Algorithm/IdGroupingWithDualSerial.java
+8
-0
ScheduleOperationService.java
...a/com/aps/service/Algorithm/ScheduleOperationService.java
+60
-5
LanuchServiceImpl.java
src/main/java/com/aps/service/impl/LanuchServiceImpl.java
+16
-6
LockedOrderProcessorService.java
...ava/com/aps/service/plan/LockedOrderProcessorService.java
+2
-2
PlanResultService.java
src/main/java/com/aps/service/plan/PlanResultService.java
+16
-8
SceneService.java
src/main/java/com/aps/service/plan/SceneService.java
+43
-22
AutoInsertPayloadTest.java
src/test/java/com/aps/demo/AutoInsertPayloadTest.java
+38
-0
AutoInsertProtectionTest.java
src/test/java/com/aps/demo/AutoInsertProtectionTest.java
+100
-0
SceneServiceVersionTest.java
src/test/java/com/aps/demo/SceneServiceVersionTest.java
+70
-0
LanuchServiceImplTest.java
...test/java/com/aps/service/impl/LanuchServiceImplTest.java
+44
-0
No files found.
src/main/java/com/aps/service/Algorithm/IdGroupingWithDualSerial.java
View file @
1e00c75d
...
@@ -388,6 +388,13 @@ public class IdGroupingWithDualSerial {
...
@@ -388,6 +388,13 @@ public class IdGroupingWithDualSerial {
* @return 包含新分组的结果列表
* @return 包含新分组的结果列表
*/
*/
public
static
List
<
GroupResult
>
addNewDataWithIsolatedGroup
(
List
<
GroupResult
>
existingResults
,
List
<
String
>
newIdList
,
List
<
String
>
newChildIdList
)
{
public
static
List
<
GroupResult
>
addNewDataWithIsolatedGroup
(
List
<
GroupResult
>
existingResults
,
List
<
String
>
newIdList
,
List
<
String
>
newChildIdList
)
{
return
addNewDataWithIsolatedGroup
(
existingResults
,
newIdList
,
newChildIdList
,
1
);
}
public
static
List
<
GroupResult
>
addNewDataWithIsolatedGroup
(
List
<
GroupResult
>
existingResults
,
List
<
String
>
newIdList
,
List
<
String
>
newChildIdList
,
int
minimumGlobalSerial
)
{
// 空值安全检查
// 空值安全检查
if
(
newIdList
==
null
||
newIdList
.
isEmpty
())
{
if
(
newIdList
==
null
||
newIdList
.
isEmpty
())
{
return
existingResults
;
return
existingResults
;
...
@@ -428,6 +435,7 @@ public class IdGroupingWithDualSerial {
...
@@ -428,6 +435,7 @@ public class IdGroupingWithDualSerial {
.
mapToInt
(
NodeInfo:
:
getGlobalSerial
)
.
mapToInt
(
NodeInfo:
:
getGlobalSerial
)
.
max
()
.
max
()
.
orElse
(
0
);
.
orElse
(
0
);
maxGlobalSerial
=
Math
.
max
(
maxGlobalSerial
,
Math
.
max
(
1
,
minimumGlobalSerial
)
-
1
);
int
[]
globalCounter
=
{
maxGlobalSerial
+
1
};
int
[]
globalCounter
=
{
maxGlobalSerial
+
1
};
// 4. 为每个连通分量创建独立分组
// 4. 为每个连通分量创建独立分组
...
...
src/main/java/com/aps/service/Algorithm/ScheduleOperationService.java
View file @
1e00c75d
...
@@ -1240,6 +1240,7 @@ if(targetOp.getSequence()>1) {
...
@@ -1240,6 +1240,7 @@ if(targetOp.getSequence()>1) {
ProdLaunchOrder
newLaunchOrder
,
List
<
ProdProcessExec
>
newProcessExecs
,
ProdLaunchOrder
newLaunchOrder
,
List
<
ProdProcessExec
>
newProcessExecs
,
List
<
ProdEquipment
>
newProdEquipments
,
List
<
ProdEquipment
>
newProdEquipments
,
LocalDateTime
anchorTime
,
GlobalParam
globalParam
)
{
LocalDateTime
anchorTime
,
GlobalParam
globalParam
)
{
pinFrozenResults
(
chromosome
,
anchorTime
);
List
<
Order
>
orders
=
chromosome
.
getOrders
();
List
<
Order
>
orders
=
chromosome
.
getOrders
();
List
<
GroupResult
>
OperatRels
=
chromosome
.
getOperatRel
();
List
<
GroupResult
>
OperatRels
=
chromosome
.
getOperatRel
();
...
@@ -1257,12 +1258,11 @@ if(targetOp.getSequence()>1) {
...
@@ -1257,12 +1258,11 @@ if(targetOp.getSequence()>1) {
newOrder
.
setRoutingCode
(
newLaunchOrder
.
getRoutingCode
());
newOrder
.
setRoutingCode
(
newLaunchOrder
.
getRoutingCode
());
newOrder
.
setSerie
(
newLaunchOrder
.
getSerie
());
newOrder
.
setSerie
(
newLaunchOrder
.
getSerie
());
int
maxOrderId
=
orders
.
stream
().
mapToInt
(
Order:
:
getId
).
max
().
orElse
(
0
)
+
1
;
int
newGroupId
=
resolveNextAutoInsertGroupId
(
chromosome
)
;
newOrder
.
setId
(
maxOrder
Id
);
newOrder
.
setId
(
newGroup
Id
);
orders
.
add
(
newOrder
);
orders
.
add
(
newOrder
);
int
maxGroupId
=
OperatRels
.
size
();
padOperationRelations
(
OperatRels
,
newGroupId
);
int
newGroupId
=
maxGroupId
+
1
;
List
<
Entry
>
newEntrys
=
new
ArrayList
<>();
List
<
Entry
>
newEntrys
=
new
ArrayList
<>();
List
<
String
>
newIdList
=
new
ArrayList
<>();
List
<
String
>
newIdList
=
new
ArrayList
<>();
...
@@ -1357,7 +1357,12 @@ if(targetOp.getSequence()>1) {
...
@@ -1357,7 +1357,12 @@ if(targetOp.getSequence()>1) {
}
}
}
}
OperatRels
=
IdGroupingWithDualSerial
.
addNewDataWithIsolatedGroup
(
OperatRels
,
newIdList
,
newChildIdList
);
int
nextOperationId
=
chromosome
.
getAllOperations
().
stream
()
.
mapToInt
(
Entry:
:
getId
)
.
max
()
.
orElse
(
0
)
+
1
;
OperatRels
=
IdGroupingWithDualSerial
.
addNewDataWithIsolatedGroup
(
OperatRels
,
newIdList
,
newChildIdList
,
nextOperationId
);
chromosome
.
setOperatRel
(
new
CopyOnWriteArrayList
<>(
OperatRels
));
chromosome
.
setOperatRel
(
new
CopyOnWriteArrayList
<>(
OperatRels
));
int
globalOpId
=
chromosome
.
getGlobalOpList
().
stream
()
int
globalOpId
=
chromosome
.
getGlobalOpList
().
stream
()
...
@@ -1531,6 +1536,56 @@ if(targetOp.getSequence()>1) {
...
@@ -1531,6 +1536,56 @@ if(targetOp.getSequence()>1) {
globalParam
.
setIsCheckSf
(
originalIsCheckSf
);
globalParam
.
setIsCheckSf
(
originalIsCheckSf
);
}
}
private
void
pinFrozenResults
(
Chromosome
chromosome
,
LocalDateTime
anchorTime
)
{
if
(
chromosome
==
null
||
chromosome
.
getBaseTime
()
==
null
||
anchorTime
==
null
||
chromosome
.
getResult
()
==
null
||
chromosome
.
getResult
().
isEmpty
())
{
return
;
}
int
anchorSeconds
=
(
int
)
java
.
time
.
temporal
.
ChronoUnit
.
SECONDS
.
between
(
chromosome
.
getBaseTime
(),
anchorTime
);
Map
<
Integer
,
Entry
>
entriesById
=
chromosome
.
getAllOperations
()
==
null
?
Collections
.
emptyMap
()
:
chromosome
.
getAllOperations
().
stream
()
.
collect
(
Collectors
.
toMap
(
Entry:
:
getId
,
entry
->
entry
,
(
left
,
right
)
->
left
));
int
pinnedCount
=
0
;
for
(
GAScheduleResult
result
:
chromosome
.
getResult
())
{
if
(
result
==
null
||
result
.
getStartTime
()
>=
anchorSeconds
)
{
continue
;
}
result
.
setLockStartTime
(
1
);
result
.
setDesignatedStartTime
(
result
.
getStartTime
());
result
.
setForcedMachineId
(
result
.
getMachineId
());
Entry
entry
=
entriesById
.
get
(
result
.
getOperationId
());
if
(
entry
!=
null
)
{
entry
.
setDesignatedStartTime
(
chromosome
.
getBaseTime
().
plusSeconds
(
result
.
getStartTime
()));
}
pinnedCount
++;
}
}
private
int
resolveNextAutoInsertGroupId
(
Chromosome
chromosome
)
{
int
maxOrderId
=
chromosome
.
getOrders
()
==
null
?
0
:
chromosome
.
getOrders
().
stream
().
mapToInt
(
Order:
:
getId
).
max
().
orElse
(
0
);
int
maxEntryGroupId
=
chromosome
.
getAllOperations
()
==
null
?
0
:
chromosome
.
getAllOperations
().
stream
().
mapToInt
(
Entry:
:
getGroupId
).
max
().
orElse
(
0
);
int
maxResultGroupId
=
chromosome
.
getResult
()
==
null
?
0
:
chromosome
.
getResult
().
stream
().
mapToInt
(
GAScheduleResult:
:
getGroupId
).
max
().
orElse
(
0
);
int
relationCount
=
chromosome
.
getOperatRel
()
==
null
?
0
:
chromosome
.
getOperatRel
().
size
();
return
Math
.
max
(
Math
.
max
(
maxOrderId
,
maxEntryGroupId
),
Math
.
max
(
maxResultGroupId
,
relationCount
))
+
1
;
}
private
void
padOperationRelations
(
List
<
GroupResult
>
operationRelations
,
int
newGroupId
)
{
while
(
operationRelations
.
size
()
<
newGroupId
-
1
)
{
operationRelations
.
add
(
new
GroupResult
(
new
ArrayList
<>(),
new
HashMap
<>()));
}
}
private
int
calcBestMachineSeq
(
Entry
entry
,
Chromosome
chromosome
,
LocalDateTime
anchorTime
)
{
private
int
calcBestMachineSeq
(
Entry
entry
,
Chromosome
chromosome
,
LocalDateTime
anchorTime
)
{
List
<
MachineOption
>
rawOptions
=
entry
.
getMachineOptions
();
List
<
MachineOption
>
rawOptions
=
entry
.
getMachineOptions
();
if
(
rawOptions
==
null
||
rawOptions
.
isEmpty
())
{
if
(
rawOptions
==
null
||
rawOptions
.
isEmpty
())
{
...
...
src/main/java/com/aps/service/impl/LanuchServiceImpl.java
View file @
1e00c75d
...
@@ -2066,12 +2066,11 @@ public class LanuchServiceImpl implements LanuchService {
...
@@ -2066,12 +2066,11 @@ public class LanuchServiceImpl implements LanuchService {
.
filter
(
Objects:
:
nonNull
)
.
filter
(
Objects:
:
nonNull
)
.
collect
(
Collectors
.
toSet
());
.
collect
(
Collectors
.
toSet
());
Optional
<
RoutingHeader
>
sceneRouting
=
candidates
.
stream
()
RoutingHeader
sceneRouting
=
selectExistingSceneRouting
(
candidates
,
sceneRoutingIds
);
.
filter
(
header
->
sceneRoutingIds
.
contains
(
header
.
getId
()))
if
(
sceneRouting
!=
null
)
{
.
filter
(
this
::
hasResolvableProcessResources
)
log
.
info
(
"Auto insert reuses existing routing: sceneId={}, materialId={}, routingId={}, routingCode={}"
,
.
findFirst
();
sceneId
,
materialId
,
sceneRouting
.
getId
(),
sceneRouting
.
getCode
());
if
(
sceneRouting
.
isPresent
())
{
return
sceneRouting
;
return
sceneRouting
.
get
();
}
}
Optional
<
RoutingHeader
>
namedValidRouting
=
candidates
.
stream
()
Optional
<
RoutingHeader
>
namedValidRouting
=
candidates
.
stream
()
...
@@ -2088,6 +2087,17 @@ public class LanuchServiceImpl implements LanuchService {
...
@@ -2088,6 +2087,17 @@ public class LanuchServiceImpl implements LanuchService {
return
anyValidRouting
.
orElse
(
candidates
.
get
(
0
));
return
anyValidRouting
.
orElse
(
candidates
.
get
(
0
));
}
}
static
RoutingHeader
selectExistingSceneRouting
(
List
<
RoutingHeader
>
candidates
,
Set
<
Integer
>
sceneRoutingIds
)
{
if
(
CollectionUtils
.
isEmpty
(
candidates
)
||
CollectionUtils
.
isEmpty
(
sceneRoutingIds
))
{
return
null
;
}
return
candidates
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
header
->
sceneRoutingIds
.
contains
(
header
.
getId
()))
.
findFirst
()
.
orElse
(
null
);
}
private
boolean
hasResolvableProcessResources
(
RoutingHeader
routingHeader
)
{
private
boolean
hasResolvableProcessResources
(
RoutingHeader
routingHeader
)
{
if
(
routingHeader
==
null
||
routingHeader
.
getId
()
==
null
)
{
if
(
routingHeader
==
null
||
routingHeader
.
getId
()
==
null
)
{
return
false
;
return
false
;
...
...
src/main/java/com/aps/service/plan/LockedOrderProcessorService.java
View file @
1e00c75d
...
@@ -344,7 +344,7 @@ public class LockedOrderProcessorService {
...
@@ -344,7 +344,7 @@ public class LockedOrderProcessorService {
// 深拷贝工单并转换时间
// 深拷贝工单并转换时间
GAScheduleResult
lockedResult
=
copyGAScheduleResult
(
result
);
GAScheduleResult
lockedResult
=
copyGAScheduleResult
(
result
);
lockedResult
.
setIsLocked
(
false
);
// 重要:标记为锁定工单,确保重新解码时不被清除
lockedResult
.
setIsLocked
(
false
);
// 仍参与解码,通过固定开始时间保持原排程
// 转换时间:从旧baseTime转换到新baseTime
// 转换时间:从旧baseTime转换到新baseTime
LocalDateTime
prevStartTime
=
oldBaseTime
.
plusSeconds
(
result
.
getStartTime
());
LocalDateTime
prevStartTime
=
oldBaseTime
.
plusSeconds
(
result
.
getStartTime
());
...
...
src/main/java/com/aps/service/plan/PlanResultService.java
View file @
1e00c75d
...
@@ -1362,7 +1362,7 @@ public class PlanResultService {
...
@@ -1362,7 +1362,7 @@ public class PlanResultService {
ScheduleOperation
.
dragOperation
(
chromosome
,
opId
,
targetopId
,
isfront
,
newMachineId
,
globalParam
);
ScheduleOperation
.
dragOperation
(
chromosome
,
opId
,
targetopId
,
isfront
,
newMachineId
,
globalParam
);
// WriteScheduleSummary(chromosome);
// WriteScheduleSummary(chromosome);
_sceneService
.
saveChromosomeToFile
(
chromosome
,
SceneId
);
saveChromosomeOrThrow
(
chromosome
,
SceneId
,
"drag operation"
);
return
chromosome
;
return
chromosome
;
}
}
/**
/**
...
@@ -1492,9 +1492,12 @@ public class PlanResultService {
...
@@ -1492,9 +1492,12 @@ public class PlanResultService {
throw
new
RuntimeException
(
"quantity 不能为空"
);
throw
new
RuntimeException
(
"quantity 不能为空"
);
}
}
Double
quantity
=
Double
.
valueOf
(
String
.
valueOf
(
qtyObj
));
Double
quantity
=
Double
.
valueOf
(
String
.
valueOf
(
qtyObj
));
LocalDateTime
startDate
=
parseOrderDateTime
(
newOrderData
.
get
(
"startDate"
));
LocalDateTime
startDate
=
parseOrderDateTime
(
LocalDateTime
endDate
=
parseOrderDateTime
(
newOrderData
.
get
(
"endDate"
));
getFirstStringValue
(
newOrderData
,
"startDate"
,
"begintime"
,
"beginTime"
));
Integer
priority
=
parseOrderPriority
(
newOrderData
.
get
(
"priority"
));
LocalDateTime
endDate
=
parseOrderDateTime
(
getFirstStringValue
(
newOrderData
,
"endDate"
,
"deliverytime"
,
"deliveryTime"
));
Integer
priority
=
parseOrderPriority
(
getFirstStringValue
(
newOrderData
,
"priority"
,
"prioritry"
));
// 1. 创建新订单(沿用现有创建逻辑)
// 1. 创建新订单(沿用现有创建逻辑)
R
<
String
>
insertResp
=
lanuchService
.
insertOrder
(
sceneId
,
orderCode
,
materialId
,
R
<
String
>
insertResp
=
lanuchService
.
insertOrder
(
sceneId
,
orderCode
,
materialId
,
...
@@ -1552,7 +1555,6 @@ public class PlanResultService {
...
@@ -1552,7 +1555,6 @@ public class PlanResultService {
if
(
newProdEquipments
==
null
||
newProdEquipments
.
isEmpty
())
{
if
(
newProdEquipments
==
null
||
newProdEquipments
.
isEmpty
())
{
throw
new
RuntimeException
(
"自动插单失败:新工单未生成可选设备,请检查PROD_EQUIPMENT"
);
throw
new
RuntimeException
(
"自动插单失败:新工单未生成可选设备,请检查PROD_EQUIPMENT"
);
}
}
// 4. 计算锚点时间:基准时间 + 冻结期
// 4. 计算锚点时间:基准时间 + 冻结期
LocalDateTime
baseTime
=
chromosome
.
getBaseTime
();
LocalDateTime
baseTime
=
chromosome
.
getBaseTime
();
LambdaQueryWrapper
<
ApsTimeConfig
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
LambdaQueryWrapper
<
ApsTimeConfig
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
...
@@ -1587,7 +1589,7 @@ public class PlanResultService {
...
@@ -1587,7 +1589,7 @@ public class PlanResultService {
// 6. 保存
// 6. 保存
WriteScheduleSummary
(
chromosome
);
WriteScheduleSummary
(
chromosome
);
_sceneService
.
saveChromosomeToFile
(
chromosome
,
sceneId
);
saveChromosomeOrThrow
(
chromosome
,
sceneId
,
"auto insert order"
);
return
chromosome
;
return
chromosome
;
}
}
...
@@ -1659,7 +1661,7 @@ public class PlanResultService {
...
@@ -1659,7 +1661,7 @@ public class PlanResultService {
ScheduleOperation
.
moveOperation
(
chromosome
,
opId
,
(
int
)
ChronoUnit
.
SECONDS
.
between
(
chromosome
.
getBaseTime
(),
newStartTime
),
newMachineId
,
globalParam
,
lockStartTime
);
ScheduleOperation
.
moveOperation
(
chromosome
,
opId
,
(
int
)
ChronoUnit
.
SECONDS
.
between
(
chromosome
.
getBaseTime
(),
newStartTime
),
newMachineId
,
globalParam
,
lockStartTime
);
// WriteScheduleSummary(chromosome);
// WriteScheduleSummary(chromosome);
_sceneService
.
saveChromosomeToFile
(
chromosome
,
SceneId
);
saveChromosomeOrThrow
(
chromosome
,
SceneId
,
"move operation"
);
return
chromosome
;
return
chromosome
;
}
}
...
@@ -1870,10 +1872,16 @@ public class PlanResultService {
...
@@ -1870,10 +1872,16 @@ public class PlanResultService {
scheduleOperation
.
InsertOrder
(
chromosome
,
afterOrderId
,
newOrderId
,
newLaunchOrder
,
newProcessExecs
,
globalParam
);
scheduleOperation
.
InsertOrder
(
chromosome
,
afterOrderId
,
newOrderId
,
newLaunchOrder
,
newProcessExecs
,
globalParam
);
WriteScheduleSummary
(
chromosome
);
WriteScheduleSummary
(
chromosome
);
_sceneService
.
saveChromosomeToFile
(
chromosome
,
SceneId
);
saveChromosomeOrThrow
(
chromosome
,
SceneId
,
"insert order"
);
return
chromosome
;
return
chromosome
;
}
}
private
void
saveChromosomeOrThrow
(
Chromosome
chromosome
,
String
sceneId
,
String
operationName
)
{
if
(!
_sceneService
.
saveChromosomeToFile
(
chromosome
,
sceneId
))
{
throw
new
RuntimeException
(
operationName
+
" failed: unable to save schedule version"
);
}
}
public
Chromosome
MergeOrder
(
String
SceneId
,
String
sourceorderId
,
String
targetorderId
)
{
public
Chromosome
MergeOrder
(
String
SceneId
,
String
sourceorderId
,
String
targetorderId
)
{
Chromosome
chromosome
=
_sceneService
.
loadChromosomeFromFile
(
SceneId
);
Chromosome
chromosome
=
_sceneService
.
loadChromosomeFromFile
(
SceneId
);
...
...
src/main/java/com/aps/service/plan/SceneService.java
View file @
1e00c75d
...
@@ -16,7 +16,10 @@ import java.io.FileInputStream;
...
@@ -16,7 +16,10 @@ import java.io.FileInputStream;
import
java.io.FileOutputStream
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Files
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
java.util.zip.GZIPInputStream
;
import
java.util.zip.GZIPInputStream
;
import
java.util.zip.GZIPOutputStream
;
import
java.util.zip.GZIPOutputStream
;
...
@@ -42,6 +45,7 @@ public class SceneService {
...
@@ -42,6 +45,7 @@ public class SceneService {
private
RedisUtils
redisUtils
;
private
RedisUtils
redisUtils
;
private
final
ObjectMapper
objectMapper
=
createObjectMapper
();
private
final
ObjectMapper
objectMapper
=
createObjectMapper
();
private
final
Map
<
String
,
Object
>
sceneLocks
=
new
ConcurrentHashMap
<>();
private
ObjectMapper
createObjectMapper
()
{
private
ObjectMapper
createObjectMapper
()
{
ObjectMapper
objectMapper
=
new
ObjectMapper
();
ObjectMapper
objectMapper
=
new
ObjectMapper
();
...
@@ -154,38 +158,38 @@ public class SceneService {
...
@@ -154,38 +158,38 @@ public class SceneService {
return
false
;
return
false
;
}
}
Object
sceneLock
=
sceneLocks
.
computeIfAbsent
(
sceneId
,
key
->
new
Object
());
synchronized
(
sceneLock
)
{
try
{
try
{
ObjectMapper
objectMapper
=
createObjectMapper
();
ObjectMapper
objectMapper
=
createObjectMapper
();
SceneChromsome
sceneChromsome
=
(
SceneChromsome
)
redisUtils
.
get
(
"SceneId."
+
sceneId
);
SceneChromsome
sceneChromsome
=
(
SceneChromsome
)
redisUtils
.
get
(
"SceneId."
+
sceneId
);
Integer
nextVersion
;
List
<
SceneDetail
>
retainedDetails
=
new
ArrayList
<>();
if
(
sceneChromsome
==
null
)
{
if
(
sceneChromsome
==
null
)
{
sceneChromsome
=
new
SceneChromsome
();
sceneChromsome
=
new
SceneChromsome
();
sceneChromsome
.
setSceneID
(
sceneId
);
sceneChromsome
.
setSceneID
(
sceneId
);
sceneChromsome
.
setVersion
(
1
)
;
nextVersion
=
1
;
}
else
{
}
else
{
Integer
currentVersion
=
sceneChromsome
.
getVersion
();
Integer
currentVersion
=
sceneChromsome
.
getVersion
();
List
<
SceneDetail
>
nextVersions
=
sceneChromsome
.
getSceneDetails
().
stream
()
if
(
currentVersion
==
null
)
{
.
filter
(
detail
->
detail
.
getVersion
()
>
currentVersion
)
currentVersion
=
0
;
.
collect
(
Collectors
.
toList
());
if
(!
nextVersions
.
isEmpty
())
{
for
(
SceneDetail
detail
:
nextVersions
)
{
File
nextFile
=
getChromosomeFile
(
sceneId
,
detail
.
getVersion
().
toString
());
Files
.
deleteIfExists
(
nextFile
.
toPath
());
}
}
nextVersion
=
currentVersion
+
1
;
if
(
sceneChromsome
.
getSceneDetails
()
!=
null
)
{
Integer
finalCurrentVersion
=
currentVersion
;
retainedDetails
.
addAll
(
sceneChromsome
.
getSceneDetails
().
stream
()
.
filter
(
detail
->
detail
!=
null
&&
detail
.
getVersion
()
!=
null
&&
detail
.
getVersion
()
<=
finalCurrentVersion
)
.
collect
(
Collectors
.
toList
()));
}
}
sceneChromsome
.
getSceneDetails
().
removeIf
(
detail
->
detail
.
getVersion
()
>
currentVersion
);
sceneChromsome
.
setVersion
(
sceneChromsome
.
getVersion
()
+
1
);
}
}
SceneDetail
sceneDetail
=
new
SceneDetail
();
File
file
=
getChromosomeFile
(
sceneId
,
nextVersion
.
toString
());
sceneDetail
.
setVersion
(
sceneChromsome
.
getVersion
());
sceneChromsome
.
getSceneDetails
().
add
(
sceneDetail
);
redisUtils
.
set
(
"SceneId."
+
sceneId
,
sceneChromsome
);
File
file
=
getChromosomeFile
(
sceneId
,
sceneChromsome
.
getVersion
().
toString
());
File
tempFile
=
new
File
(
file
.
getParentFile
(),
file
.
getName
()
+
".tmp"
);
File
tempFile
=
new
File
(
file
.
getParentFile
(),
file
.
getName
()
+
".tmp"
);
chromosome
.
setVersion
(
sceneChromsome
.
getVersion
()
);
chromosome
.
setVersion
(
nextVersion
);
if
(
useCompression
)
{
if
(
useCompression
)
{
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
tempFile
);
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
tempFile
);
GZIPOutputStream
gzos
=
new
GZIPOutputStream
(
fos
))
{
GZIPOutputStream
gzos
=
new
GZIPOutputStream
(
fos
))
{
...
@@ -227,6 +231,22 @@ public class SceneService {
...
@@ -227,6 +231,22 @@ public class SceneService {
}
}
Files
.
move
(
tempFile
.
toPath
(),
file
.
toPath
());
Files
.
move
(
tempFile
.
toPath
(),
file
.
toPath
());
if
(
sceneChromsome
.
getSceneDetails
()
!=
null
)
{
for
(
SceneDetail
detail
:
sceneChromsome
.
getSceneDetails
())
{
if
(
detail
!=
null
&&
detail
.
getVersion
()
!=
null
&&
detail
.
getVersion
()
>
nextVersion
)
{
File
futureFile
=
getChromosomeFile
(
sceneId
,
detail
.
getVersion
().
toString
());
Files
.
deleteIfExists
(
futureFile
.
toPath
());
}
}
}
SceneDetail
sceneDetail
=
new
SceneDetail
();
sceneDetail
.
setVersion
(
nextVersion
);
retainedDetails
.
add
(
sceneDetail
);
sceneChromsome
.
setVersion
(
nextVersion
);
sceneChromsome
.
setSceneDetails
(
retainedDetails
);
redisUtils
.
set
(
"SceneId."
+
sceneId
,
sceneChromsome
);
logger
.
info
(
"染色体保存成功,场景ID: {}, 文件: {}"
,
sceneId
,
file
.
getAbsolutePath
());
logger
.
info
(
"染色体保存成功,场景ID: {}, 文件: {}"
,
sceneId
,
file
.
getAbsolutePath
());
return
true
;
return
true
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
...
@@ -234,6 +254,7 @@ public class SceneService {
...
@@ -234,6 +254,7 @@ public class SceneService {
return
false
;
return
false
;
}
}
}
}
}
public
SceneChromsome
getSceneChromsome
(
String
sceneId
)
{
public
SceneChromsome
getSceneChromsome
(
String
sceneId
)
{
return
(
SceneChromsome
)
redisUtils
.
get
(
"SceneId."
+
sceneId
);
return
(
SceneChromsome
)
redisUtils
.
get
(
"SceneId."
+
sceneId
);
...
...
src/test/java/com/aps/demo/AutoInsertPayloadTest.java
0 → 100644
View file @
1e00c75d
package
com
.
aps
.
demo
;
import
com.aps.service.plan.PlanResultService
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.time.LocalDateTime
;
import
java.util.HashMap
;
import
java.util.Map
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
class
AutoInsertPayloadTest
{
@Test
void
autoInsertPayloadSupportsFrontendDateAndPriorityAliases
()
{
PlanResultService
service
=
new
PlanResultService
();
Map
<
String
,
Object
>
payload
=
new
HashMap
<>();
payload
.
put
(
"begintime"
,
"2026-07-01T00:00:00.000Z"
);
payload
.
put
(
"deliverytime"
,
"2026-07-31T00:00:00.000Z"
);
payload
.
put
(
"prioritry"
,
"3"
);
String
startText
=
ReflectionTestUtils
.
invokeMethod
(
service
,
"getFirstStringValue"
,
payload
,
new
String
[]{
"startDate"
,
"begintime"
,
"beginTime"
});
String
endText
=
ReflectionTestUtils
.
invokeMethod
(
service
,
"getFirstStringValue"
,
payload
,
new
String
[]{
"endDate"
,
"deliverytime"
,
"deliveryTime"
});
String
priorityText
=
ReflectionTestUtils
.
invokeMethod
(
service
,
"getFirstStringValue"
,
payload
,
new
String
[]{
"priority"
,
"prioritry"
});
LocalDateTime
start
=
ReflectionTestUtils
.
invokeMethod
(
service
,
"parseOrderDateTime"
,
startText
);
LocalDateTime
end
=
ReflectionTestUtils
.
invokeMethod
(
service
,
"parseOrderDateTime"
,
endText
);
Integer
priority
=
ReflectionTestUtils
.
invokeMethod
(
service
,
"parseOrderPriority"
,
priorityText
);
assertEquals
(
LocalDateTime
.
of
(
2026
,
7
,
1
,
0
,
0
),
start
);
assertEquals
(
LocalDateTime
.
of
(
2026
,
7
,
31
,
0
,
0
),
end
);
assertEquals
(
Integer
.
valueOf
(
3
),
priority
);
}
}
src/test/java/com/aps/demo/AutoInsertProtectionTest.java
0 → 100644
View file @
1e00c75d
package
com
.
aps
.
demo
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Algorithm.GAScheduleResult
;
import
com.aps.entity.Algorithm.IDAndChildID.GroupResult
;
import
com.aps.entity.Algorithm.IDAndChildID.NodeInfo
;
import
com.aps.entity.basic.Entry
;
import
com.aps.entity.basic.Order
;
import
com.aps.service.Algorithm.IdGroupingWithDualSerial
;
import
com.aps.service.Algorithm.ScheduleOperationService
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.concurrent.CopyOnWriteArrayList
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
class
AutoInsertProtectionTest
{
@Test
void
frozenResultIsPinnedBeforeAutoInsertRedecode
()
{
LocalDateTime
baseTime
=
LocalDateTime
.
of
(
2026
,
5
,
1
,
0
,
0
);
Chromosome
chromosome
=
new
Chromosome
();
chromosome
.
setBaseTime
(
baseTime
);
Entry
frozenEntry
=
new
Entry
();
frozenEntry
.
setId
(
10
);
chromosome
.
setAllOperations
(
new
CopyOnWriteArrayList
<>(
Arrays
.
asList
(
frozenEntry
)));
GAScheduleResult
frozenResult
=
new
GAScheduleResult
();
frozenResult
.
setOperationId
(
10
);
frozenResult
.
setMachineId
(
31L
);
frozenResult
.
setStartTime
(
3600
);
GAScheduleResult
futureResult
=
new
GAScheduleResult
();
futureResult
.
setOperationId
(
11
);
futureResult
.
setMachineId
(
32L
);
futureResult
.
setStartTime
(
20000
);
chromosome
.
setResult
(
new
CopyOnWriteArrayList
<>(
Arrays
.
asList
(
frozenResult
,
futureResult
)));
ScheduleOperationService
service
=
new
ScheduleOperationService
(
null
,
null
);
ReflectionTestUtils
.
invokeMethod
(
service
,
"pinFrozenResults"
,
chromosome
,
baseTime
.
plusSeconds
(
10000
));
assertEquals
(
1
,
frozenResult
.
getLockStartTime
());
assertEquals
(
3600
,
frozenResult
.
getDesignatedStartTime
());
assertEquals
(
Long
.
valueOf
(
31L
),
frozenResult
.
getForcedMachineId
());
assertEquals
(
baseTime
.
plusSeconds
(
3600
),
frozenEntry
.
getDesignatedStartTime
());
assertEquals
(
0
,
futureResult
.
getLockStartTime
());
}
@Test
void
autoInsertOperationIdsStartAfterExistingChromosomeOperations
()
{
NodeInfo
existingNode
=
new
NodeInfo
(
"old"
,
3
,
1
,
new
ArrayList
<>(),
new
ArrayList
<>());
List
<
GroupResult
>
relations
=
new
ArrayList
<>(
Collections
.
singletonList
(
new
GroupResult
(
new
ArrayList
<>(
Collections
.
singletonList
(
existingNode
)),
new
HashMap
<>())));
List
<
GroupResult
>
updated
=
IdGroupingWithDualSerial
.
addNewDataWithIsolatedGroup
(
relations
,
Collections
.
singletonList
(
"new"
),
Collections
.
singletonList
(
""
),
12
);
GroupResult
insertedGroup
=
updated
.
get
(
updated
.
size
()
-
1
);
assertEquals
(
Integer
.
valueOf
(
12
),
insertedGroup
.
getNodeInfoList
().
get
(
0
).
getGlobalSerial
());
}
@Test
void
autoInsertGroupIdStartsAfterExistingOrderEntryAndResultGroups
()
{
Chromosome
chromosome
=
new
Chromosome
();
Order
order
=
new
Order
();
order
.
setId
(
3
);
chromosome
.
setOrders
(
new
CopyOnWriteArrayList
<>(
Collections
.
singletonList
(
order
)));
Entry
entry
=
new
Entry
();
entry
.
setGroupId
(
4
);
chromosome
.
setAllOperations
(
new
CopyOnWriteArrayList
<>(
Collections
.
singletonList
(
entry
)));
GAScheduleResult
result
=
new
GAScheduleResult
();
result
.
setGroupId
(
4
);
chromosome
.
setResult
(
new
CopyOnWriteArrayList
<>(
Collections
.
singletonList
(
result
)));
chromosome
.
setOperatRel
(
new
CopyOnWriteArrayList
<>(
Collections
.
singletonList
(
new
GroupResult
(
new
ArrayList
<>(),
new
HashMap
<>()))));
ScheduleOperationService
service
=
new
ScheduleOperationService
(
null
,
null
);
Integer
nextGroupId
=
ReflectionTestUtils
.
invokeMethod
(
service
,
"resolveNextAutoInsertGroupId"
,
chromosome
);
ReflectionTestUtils
.
invokeMethod
(
service
,
"padOperationRelations"
,
chromosome
.
getOperatRel
(),
nextGroupId
);
assertEquals
(
Integer
.
valueOf
(
5
),
nextGroupId
);
assertEquals
(
4
,
chromosome
.
getOperatRel
().
size
());
}
}
src/test/java/com/aps/demo/SceneServiceVersionTest.java
0 → 100644
View file @
1e00c75d
package
com
.
aps
.
demo
;
import
com.aps.common.util.redis.RedisUtils
;
import
com.aps.entity.Algorithm.Chromosome
;
import
com.aps.entity.Schedule.SceneChromsome
;
import
com.aps.service.plan.SceneService
;
import
org.junit.jupiter.api.AfterEach
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.io.File
;
import
java.util.concurrent.atomic.AtomicReference
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNotNull
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertTrue
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyString
;
import
static
org
.
mockito
.
Mockito
.
doAnswer
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
class
SceneServiceVersionTest
{
private
final
String
sceneId
=
"VERSION_TEST_"
+
System
.
nanoTime
();
@AfterEach
void
cleanVersionFiles
()
{
File
resultDir
=
new
File
(
"result"
);
File
[]
files
=
resultDir
.
listFiles
((
dir
,
name
)
->
name
.
startsWith
(
"chromosome_result_"
+
sceneId
+
"_"
));
if
(
files
==
null
)
{
return
;
}
for
(
File
file
:
files
)
{
file
.
delete
();
}
}
@Test
void
undoAndRedoKeepInsertAndMoveAsSeparateVersions
()
{
AtomicReference
<
SceneChromsome
>
sceneState
=
new
AtomicReference
<>();
RedisUtils
redisUtils
=
mock
(
RedisUtils
.
class
);
when
(
redisUtils
.
get
(
anyString
())).
thenAnswer
(
invocation
->
sceneState
.
get
());
doAnswer
(
invocation
->
{
sceneState
.
set
(
invocation
.
getArgument
(
1
));
return
null
;
}).
when
(
redisUtils
).
set
(
anyString
(),
any
());
SceneService
sceneService
=
new
SceneService
();
ReflectionTestUtils
.
setField
(
sceneService
,
"redisUtils"
,
redisUtils
);
Chromosome
inserted
=
new
Chromosome
();
inserted
.
setGenerateType
(
"inserted"
);
assertTrue
(
sceneService
.
saveChromosomeToFile
(
inserted
,
sceneId
));
Chromosome
moved
=
sceneService
.
loadChromosomeFromFile
(
sceneId
);
moved
.
setGenerateType
(
"moved"
);
assertTrue
(
sceneService
.
saveChromosomeToFile
(
moved
,
sceneId
));
Chromosome
undone
=
sceneService
.
moveChromosome
(
sceneId
,
0
);
assertNotNull
(
undone
);
assertEquals
(
1
,
undone
.
getVersion
());
assertEquals
(
"inserted"
,
undone
.
getGenerateType
());
Chromosome
redone
=
sceneService
.
revertVersion
(
sceneId
,
2
);
assertNotNull
(
redone
);
assertEquals
(
2
,
redone
.
getVersion
());
assertEquals
(
"moved"
,
redone
.
getGenerateType
());
}
}
src/test/java/com/aps/service/impl/LanuchServiceImplTest.java
0 → 100644
View file @
1e00c75d
package
com
.
aps
.
service
.
impl
;
import
com.aps.entity.RoutingHeader
;
import
org.junit.jupiter.api.Test
;
import
java.time.LocalDate
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNull
;
class
LanuchServiceImplTest
{
@Test
void
autoInsertPrefersNewestRoutingAlreadyUsedBySameMaterialInScene
()
{
RoutingHeader
newestOtherRouting
=
routing
(
300
,
LocalDate
.
of
(
2026
,
7
,
20
));
RoutingHeader
newestExistingRouting
=
routing
(
200
,
LocalDate
.
of
(
2026
,
7
,
19
));
RoutingHeader
olderExistingRouting
=
routing
(
100
,
LocalDate
.
of
(
2026
,
7
,
18
));
RoutingHeader
selected
=
LanuchServiceImpl
.
selectExistingSceneRouting
(
Arrays
.
asList
(
newestOtherRouting
,
newestExistingRouting
,
olderExistingRouting
),
new
HashSet
<>(
Arrays
.
asList
(
100
,
200
)));
assertEquals
(
Integer
.
valueOf
(
200
),
selected
.
getId
());
}
@Test
void
autoInsertFallsBackWhenSceneHasNoRoutingForMaterial
()
{
RoutingHeader
selected
=
LanuchServiceImpl
.
selectExistingSceneRouting
(
Collections
.
singletonList
(
routing
(
300
,
LocalDate
.
of
(
2026
,
7
,
20
))),
Collections
.
singleton
(
100
));
assertNull
(
selected
);
}
private
RoutingHeader
routing
(
int
id
,
LocalDate
creationTime
)
{
RoutingHeader
routingHeader
=
new
RoutingHeader
();
routingHeader
.
setId
(
id
);
routingHeader
.
setCreationTime
(
creationTime
);
return
routingHeader
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment