알림문제 수정

This commit is contained in:
Macbook
2026-05-28 01:45:53 +09:00
parent aace2282d5
commit 01218b99c9
6 changed files with 180 additions and 31 deletions
@@ -3,11 +3,14 @@ package com.goldenchart.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
@@ -39,9 +42,9 @@ public class StrategyDslTimeframeNormalizer {
if (root == null || root.isNull()) return root;
if ("TIMEFRAME".equals(root.path("type").asText(""))) {
// START 다중 분봉(candleTypes) — 편집기 저장값 유지, candleType 은 배열 첫 값과 동기화
// START 다중 분봉(candleTypes) — stale 1m 제거 후 candleType 동기화
if (hasCandleTypesArray(root)) {
return syncTimeframePrimary(root);
return syncTimeframePrimary(reconcileStartCandleTypes(root));
}
String current = LiveStrategyTimeframeService.normalize(root.path("candleType").asText("1m"));
// 편집기에서 명시한 단일 분봉(3m, 5m 등)은 조건 노드 기본 1m 추론으로 덮어쓰지 않음
@@ -270,6 +273,71 @@ public class StrategyDslTimeframeNormalizer {
return arr.isArray() && !arr.isEmpty();
}
/**
* START candleTypes 에 남은 레거시 1m 제거.
* <ul>
* <li>[1m, 5m] + 조건 leftCandleType 5m → [5m] (편집기 5m만 선택·1m 기본값 잔존)</li>
* <li>[1m, 3m, 5m] 다중 OR 선택은 유지</li>
* <li>조건에 1m 명시 시 유지</li>
* </ul>
*/
public static Set<String> resolveStartCandleTypes(JsonNode timeframeNode) {
ObjectNode reconciled = reconcileStartCandleTypesStatic(timeframeNode);
Set<String> out = new LinkedHashSet<>();
JsonNode arr = reconciled.path("candleTypes");
if (arr.isArray() && !arr.isEmpty()) {
for (JsonNode t : arr) {
String ct = LiveStrategyTimeframeService.normalize(t.asText(""));
if (!ct.isBlank()) out.add(ct);
}
return out;
}
out.add(LiveStrategyTimeframeService.normalize(
reconciled.path("candleType").asText("1m")));
return out;
}
private ObjectNode reconcileStartCandleTypes(JsonNode tf) {
return reconcileStartCandleTypesStatic(tf);
}
private static ObjectNode reconcileStartCandleTypesStatic(JsonNode tf) {
ObjectNode copy = tf.deepCopy();
JsonNode arr = tf.path("candleTypes");
if (!arr.isArray() || arr.size() < 2) return copy;
JsonNode subtree = firstTimeframeChild(tf);
Set<String> explicit = collectExplicitCandleTypes(subtree);
if (explicit.contains("1m")) return copy;
List<String> normalized = new ArrayList<>();
for (JsonNode t : arr) {
String ct = LiveStrategyTimeframeService.normalize(t.asText(""));
if (!ct.isBlank() && !normalized.contains(ct)) normalized.add(ct);
}
if (!normalized.contains("1m")) return copy;
long non1mCount = normalized.stream().filter(ct -> !"1m".equals(ct)).count();
if (non1mCount == 0) return copy;
// [1m, 3m, 5m] 등 1m+복수 상위봉 OR — 1m 의도적 선택으로 간주
if (non1mCount >= 2) return copy;
ArrayNode newArr = JsonNodeFactory.instance.arrayNode();
for (String ct : normalized) {
if (!"1m".equals(ct)) newArr.add(ct);
}
if (newArr.isEmpty()) return copy;
copy.set("candleTypes", newArr);
copy.put("candleType", LiveStrategyTimeframeService.normalize(newArr.get(0).asText("1m")));
return copy;
}
private static JsonNode firstTimeframeChild(JsonNode timeframeNode) {
JsonNode children = timeframeNode.path("children");
if (children.isArray() && !children.isEmpty()) return children.get(0);
return timeframeNode.path("child");
}
/** candleTypes[] 가 있으면 candleType 을 첫 항목과 맞춤 (stale 1m 방지) */
private ObjectNode syncTimeframePrimary(JsonNode tf) {
ObjectNode copy = tf.deepCopy();