From 118c4440c0e7ccf4f44850ab8876920c8b46a79e Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期六, 14 三月 2026 20:42:24 +0800
Subject: [PATCH] bugfix
---
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/OperationStrategyIndex.java | 121 +++++++++++++++++++++++-----------------
1 files changed, 70 insertions(+), 51 deletions(-)
diff --git a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/OperationStrategyIndex.java b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/OperationStrategyIndex.java
index 001b49b..99828f1 100644
--- a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/OperationStrategyIndex.java
+++ b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/OperationStrategyIndex.java
@@ -4,30 +4,31 @@
import com.alibaba.fastjson2.JSONObject;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.stream.Collectors;
/**
* 围栏运营策略时间范围索引工具类
*/
public final class OperationStrategyIndex {
- private final Map<Integer, List<TimeInterval>> allowedByType;
+ private final List<List<TimeInterval>> strategyIntervals;
/**
* 构造索引(内部使用)。
*
- * @param allowedByType 按 type 聚合后的允许时间区间
+ * @param strategyIntervals 策略组时间区间列表(每个策略组已 merge)
*/
- private OperationStrategyIndex(Map<Integer, List<TimeInterval>> allowedByType) {
- this.allowedByType = allowedByType;
+ private OperationStrategyIndex(List<List<TimeInterval>> strategyIntervals) {
+ this.strategyIntervals = strategyIntervals == null ? Collections.emptyList() : strategyIntervals;
}
/**
* 解析围栏 {@code operation_strategy} JSON 字符串为运营时间范围索引。
* <p>
- * 说明:会按 {@code type} 聚合并合并时间段,最终用于“时间覆盖范围”判断。
+ * 说明:会按“策略组”聚合并合并时间段;点位只要被任意一个策略组的时间段完整覆盖,则为正常。
* </p>
*
* @param operationStrategyJson 围栏运营策略 JSON(数组字符串)
@@ -35,39 +36,32 @@
*/
public static OperationStrategyIndex parse(String operationStrategyJson) {
if (operationStrategyJson == null || operationStrategyJson.isEmpty()) {
- return new OperationStrategyIndex(Collections.emptyMap());
+ return new OperationStrategyIndex(Collections.emptyList());
}
try {
JSONArray jsonArray = JSONArray.parseArray(operationStrategyJson);
if (jsonArray == null || jsonArray.isEmpty()) {
- return new OperationStrategyIndex(Collections.emptyMap());
+ return new OperationStrategyIndex(Collections.emptyList());
}
- Map<Integer, List<TimeInterval>> map = new java.util.HashMap<>();
+ List<List<TimeInterval>> groups = new java.util.ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
if (obj == null) {
continue;
}
- Integer type = obj.getInteger("type");
JSONArray timeArray = obj.getJSONArray("time");
- if (type == null || timeArray == null || timeArray.isEmpty()) {
+ if (timeArray == null || timeArray.isEmpty()) {
continue;
}
- List<TimeInterval> intervals = TimeInterval.parseRanges(timeArray);
- if (intervals.isEmpty()) {
- continue;
+ List<TimeInterval> intervals = TimeInterval.parseRangesDedup(timeArray);
+ List<TimeInterval> merged = TimeInterval.merge(intervals);
+ if (!merged.isEmpty()) {
+ groups.add(merged);
}
- map.merge(type, intervals, (a, b) -> {
- List<TimeInterval> merged = new java.util.ArrayList<>(a.size() + b.size());
- merged.addAll(a);
- merged.addAll(b);
- return TimeInterval.merge(merged);
- });
}
- map.replaceAll((k, v) -> TimeInterval.merge(v));
- return new OperationStrategyIndex(map);
+ return new OperationStrategyIndex(groups);
} catch (Exception e) {
- return new OperationStrategyIndex(Collections.emptyMap());
+ return new OperationStrategyIndex(Collections.emptyList());
}
}
@@ -78,7 +72,7 @@
* @return 时间区间列表;解析失败返回空列表
*/
public static List<TimeInterval> parsePointEffectiveTimePeriod(String jsonArrayStr) {
- return TimeInterval.parseJsonRanges(jsonArrayStr);
+ return TimeInterval.parseJsonRangesDedup(jsonArrayStr);
}
/**
@@ -124,10 +118,10 @@
* @return Union 区间列表(已 merge 并排序)
*/
public List<TimeInterval> unionAllowed() {
- if (allowedByType == null || allowedByType.isEmpty()) {
+ if (strategyIntervals == null || strategyIntervals.isEmpty()) {
return Collections.emptyList();
}
- List<TimeInterval> union = allowedByType.values().stream()
+ List<TimeInterval> union = strategyIntervals.stream()
.filter(Objects::nonNull)
.flatMap(List::stream)
.collect(Collectors.toList());
@@ -135,16 +129,27 @@
}
/**
- * 判断点位的时间段是否完全落在围栏 Union 运营时间覆盖范围内。
+ * 判断点位的时间段是否为正常。
+ * <p>
+ * 规则:只要点位的全部运营时间段被围栏“任意一个策略组”的时间段范围完整覆盖,则为正常。
+ * </p>
*
* @param pointIntervals 点位时间区间列表
- * @return true 表示点位每段时间都被围栏 Union 覆盖
+ * @return true 表示正常;false 表示不在任何一个策略组覆盖范围内
*/
public boolean isPointScheduleWithin(List<TimeInterval> pointIntervals) {
if (pointIntervals == null || pointIntervals.isEmpty()) {
return true;
}
- return TimeInterval.isWithin(pointIntervals, this.unionAllowed());
+ if (strategyIntervals == null || strategyIntervals.isEmpty()) {
+ return false;
+ }
+ for (List<TimeInterval> groupIntervals : strategyIntervals) {
+ if (TimeInterval.isWithin(pointIntervals, groupIntervals)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -202,7 +207,7 @@
* @param jsonArrayStr JSON 数组字符串(例如 ["08:00-12:00","13:00-18:00"])
* @return merge 后的区间列表;解析失败返回空列表
*/
- static List<TimeInterval> parseJsonRanges(String jsonArrayStr) {
+ static List<TimeInterval> parseJsonRangesDedup(String jsonArrayStr) {
if (jsonArrayStr == null || jsonArrayStr.isEmpty()) {
return Collections.emptyList();
}
@@ -211,7 +216,7 @@
if (arr == null || arr.isEmpty()) {
return Collections.emptyList();
}
- return merge(parseRanges(arr));
+ return merge(parseRangesDedup(arr));
} catch (Exception e) {
return Collections.emptyList();
}
@@ -221,7 +226,7 @@
* 解析 JSONArray 中的时间段为区间列表(不做 merge)。
*
* @param timeArray 时间段数组(元素形如 "HH:mm-HH:mm")
- * @return 区间列表(跨天会拆分为两段)
+ * @return 区间列表
*/
static List<TimeInterval> parseRanges(JSONArray timeArray) {
List<TimeInterval> result = new java.util.ArrayList<>();
@@ -233,7 +238,31 @@
}
/**
- * 解析单个时间段字符串为区间列表(支持跨天拆分:如 22:00-02:00)。
+ * 解析 JSONArray 中的时间段为区间列表(先按字符串去重,再解析;不做 merge)。
+ */
+ static List<TimeInterval> parseRangesDedup(JSONArray timeArray) {
+ if (timeArray == null || timeArray.isEmpty()) {
+ return Collections.emptyList();
+ }
+ Set<String> uniq = new LinkedHashSet<>();
+ for (int i = 0; i < timeArray.size(); i++) {
+ String range = timeArray.getString(i);
+ if (range != null && !range.isEmpty()) {
+ uniq.add(range);
+ }
+ }
+ List<TimeInterval> result = new java.util.ArrayList<>();
+ for (String range : uniq) {
+ result.addAll(parseRange(range));
+ }
+ return result;
+ }
+
+ /**
+ * 解析单个时间段字符串为区间列表。
+ * <p>
+ * 注意:业务约束不会出现跨天时间段;若出现 end < start,则视为非法配置并忽略该时间段。
+ * </p>
*/
private static List<TimeInterval> parseRange(String range) {
if (range == null || !range.contains("-")) {
@@ -249,10 +278,7 @@
return Collections.emptyList();
}
if (end < start) {
- List<TimeInterval> list = new java.util.ArrayList<>(2);
- list.add(new TimeInterval(start, 23 * 60 + 59));
- list.add(new TimeInterval(0, end));
- return list;
+ return Collections.emptyList();
}
return java.util.Collections.singletonList(new TimeInterval(start, end));
}
@@ -344,22 +370,15 @@
* main 自测:使用固定样例打印 old/new Union、是否修改/缩短,以及点位在旧/新范围内判断结果。
*/
public static void main(String[] args) {
- String oldJson = "[{\"name\": \"策略组1\", \"time\": [\"08:00-23:59\"], \"type\": 0, \"typeStr\": []}, {\"name\": \"策略组2\", \"time\": [\"07:00-23:59\"], \"type\": 2, \"typeStr\": \"\"}, {\"name\": \"策略组3\", \"time\": [\"02:00-23:59\"], \"type\": 1, \"typeStr\": \"\"}]";
- String newJson = "[{\"name\": \"策略组1\", \"time\": [\"08:00-23:59\"], \"type\": 0, \"typeStr\": []}, {\"name\": \"策略组2\", \"time\": [\"07:00-23:59\"], \"type\": 2, \"typeStr\": \"\"}, {\"name\": \"策略组3\", \"time\": [\"02:00-20:59\"], \"type\": 1, \"typeStr\": \"\"}]";
- String pointJson = "[\"07:00-13:00\", \"13:00-23:59\"]";
+ String pointJson = "[\"05:00-12:00\", \"13:00-23:59\"]";
+ String strategyJson = "[{\"name\": \"策略组1\", \"time\": [\"06:00-12:00\", \"13:00-23:59\"], \"type\": 0, \"typeStr\": []}, {\"name\": \"策略组2\", \"time\": [\"05:00-12:00\", \"12:00-23:00\"], \"type\": 2, \"typeStr\": \"\"}, {\"name\": \"策略组3\", \"time\": [\"09:00-23:59\"], \"type\": 1, \"typeStr\": \"\"}]";
- OperationStrategyIndex oldIndex = OperationStrategyIndex.parse(oldJson);
- OperationStrategyIndex newIndex = OperationStrategyIndex.parse(newJson);
+ OperationStrategyIndex index = OperationStrategyIndex.parse(strategyJson);
List<TimeInterval> pointIntervals = OperationStrategyIndex.parsePointEffectiveTimePeriod(pointJson);
- System.out.println("oldUnion=" + oldIndex.unionAllowed());
- System.out.println("newUnion=" + newIndex.unionAllowed());
- System.out.println("equalsNormalized=" + oldIndex.equalsNormalized(newIndex));
- System.out.println("hasAnyShrinkComparedTo=" + oldIndex.hasAnyShrinkComparedTo(newIndex));
- boolean inOld = oldIndex.isPointScheduleWithin(pointIntervals);
- boolean inNew = newIndex.isPointScheduleWithin(pointIntervals);
- System.out.println("point(inOld,inNew)=(" + inOld + "," + inNew + ")");
- boolean shouldDisable = !newIndex.isPointScheduleWithin(pointIntervals);
- System.out.println("shouldDisableByUnion=" + shouldDisable);
+ System.out.println("pointIntervals=" + pointIntervals);
+ System.out.println("fenceUnion=" + index.unionAllowed());
+ boolean ok = index.isPointScheduleWithin(pointIntervals);
+ System.out.println("isNormal=" + ok);
}
}
--
Gitblit v1.7.1