package com.usky.vpp.util; import com.usky.vpp.enums.VppUnEventPhase; import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; /** * 解析运管平台 DistributeEventRequest / Event 结构(DLT 1867 联调 JSON 实例) */ public final class VppUnEventParser { private VppUnEventParser() { } @SuppressWarnings("unchecked") public static List> extractEvents(Map body) { if (body == null) { return Collections.emptyList(); } Object events = body.get("events"); if (events instanceof List) { return (List>) events; } if (body.containsKey("descriptor") || body.containsKey("activePeriod")) { return Collections.singletonList(body); } return Collections.emptyList(); } @SuppressWarnings("unchecked") public static Map getDescriptor(Map event) { if (event == null) { return Collections.emptyMap(); } Object descriptor = event.get("descriptor"); if (descriptor instanceof Map) { return (Map) descriptor; } return event; } @SuppressWarnings("unchecked") public static Map getTarget(Map event) { if (event == null) { return Collections.emptyMap(); } Object target = event.get("target"); return target instanceof Map ? (Map) target : Collections.emptyMap(); } @SuppressWarnings("unchecked") public static List> getTargetResources(Map event) { Map target = getTarget(event); Object resources = target.get("resources"); if (!(resources instanceof List)) { return Collections.emptyList(); } List> list = new ArrayList<>(); for (Object item : (List) resources) { if (item instanceof Map) { list.add((Map) item); } } return list; } public static VppUnEventPhase detectPhase(Map event) { Map descriptor = getDescriptor(event); Boolean filing = VppUnPayloadHelper.getBoolean(descriptor, "filing"); Boolean lastFiling = VppUnPayloadHelper.getBoolean(descriptor, "lastFiling"); List> resources = getTargetResources(event); boolean hasValues = hasResourceValues(resources); if (Boolean.TRUE.equals(filing) && !hasValues) { return VppUnEventPhase.INVITATION; } if (Boolean.TRUE.equals(filing) && hasValues) { return VppUnEventPhase.DECLARE_FEEDBACK; } if (Boolean.FALSE.equals(filing) && Boolean.TRUE.equals(lastFiling) && hasValues) { return VppUnEventPhase.SPLIT_RESULT; } if (Boolean.FALSE.equals(filing) && Boolean.TRUE.equals(lastFiling)) { return VppUnEventPhase.SPLIT_NOTICE; } if (hasValues) { return VppUnEventPhase.CLEARING_PUBLICITY; } return VppUnEventPhase.UNKNOWN; } public static String getEventId(Map event) { Map descriptor = getDescriptor(event); return VppUnPayloadHelper.getString(descriptor, "eventID", "eventId", "event_id"); } public static Integer mapResponseType(Map descriptor) { Object notification = VppUnPayloadHelper.getRaw(descriptor, "notification"); Integer mapped = VppUnPayloadHelper.parseResponseType(notification); if (mapped != null) { return mapped; } return 1; } public static Integer mapEventType(Map descriptor) { Object control = VppUnPayloadHelper.getRaw(descriptor, "control"); Integer mapped = VppUnPayloadHelper.parseEventType(control); if (mapped != null) { return mapped; } String text = control == null ? "" : String.valueOf(control); if (text.contains("fillValley")) { return 2; } return 1; } public static Integer mapPlatformStatus(Map descriptor) { String status = VppUnPayloadHelper.getString(descriptor, "status"); if (!StringUtils.hasText(status)) { return null; } switch (status.trim().toLowerCase()) { case "cancelled": return 4; case "completed": return 3; case "active": return 2; case "far": case "near": case "none": default: return 0; } } @SuppressWarnings("unchecked") public static LocalDateTime[] resolveActivePeriod(Map event) { Object periods = event.get("activePeriod"); if (!(periods instanceof List) || ((List) periods).isEmpty()) { return new LocalDateTime[]{null, null}; } Object first = ((List) periods).get(0); if (!(first instanceof Map)) { return new LocalDateTime[]{null, null}; } Map period = (Map) first; LocalDateTime start = VppUnPayloadHelper.getDateTime(period, "dtstart", "startTime"); LocalDateTime end = VppUnPayloadHelper.getDateTime(period, "dtend", "endTime"); return new LocalDateTime[]{start, end}; } @SuppressWarnings("unchecked") public static BigDecimal extractDemandChargeKw(Map event) { BigDecimal maxAbs = null; Object signals = event.get("signals"); if (!(signals instanceof Map)) { return null; } Object signal = ((Map) signals).get("signal"); List signalList; if (signal instanceof List) { signalList = (List) signal; } else if (signal instanceof Map) { signalList = Collections.singletonList(signal); } else { return null; } for (Object sigObj : signalList) { if (!(sigObj instanceof Map)) { continue; } Map sig = (Map) sigObj; String signalName = VppUnPayloadHelper.getString(sig, "signalName"); if (!"DEMAND_CHARGE".equalsIgnoreCase(signalName)) { continue; } maxAbs = maxAbs(maxAbs, maxAbsFromIntervals(sig)); } return maxAbs; } @SuppressWarnings("unchecked") public static BigDecimal extractEnergyPrice(Map event) { Object signals = event.get("signals"); if (!(signals instanceof Map)) { return null; } Object signal = ((Map) signals).get("signal"); List signalList; if (signal instanceof List) { signalList = (List) signal; } else if (signal instanceof Map) { signalList = Collections.singletonList(signal); } else { return null; } BigDecimal sum = BigDecimal.ZERO; int count = 0; for (Object sigObj : signalList) { if (!(sigObj instanceof Map)) { continue; } Map sig = (Map) sigObj; String signalName = VppUnPayloadHelper.getString(sig, "signalName"); if (!"ENERGY_PRICE".equalsIgnoreCase(signalName)) { continue; } List values = valuesFromIntervals(sig); for (BigDecimal value : values) { sum = sum.add(value); count++; } } if (count == 0) { return null; } return sum.divide(BigDecimal.valueOf(count), 4, RoundingMode.HALF_UP); } public static BigDecimal sumResourceLoadKw(List> resources, boolean absolute) { BigDecimal total = BigDecimal.ZERO; for (Map resource : resources) { BigDecimal load = maxAbsFromResourceValues(resource); if (load == null) { load = VppUnPayloadHelper.getDecimal(resource, "load"); } if (load == null) { continue; } total = total.add(absolute ? load.abs() : load); } return total; } @SuppressWarnings("unchecked") private static List valuesFromIntervals(Map signal) { Object intervals = signal.get("intervals"); if (!(intervals instanceof Map)) { return Collections.emptyList(); } Object irregular = ((Map) intervals).get("irregular"); if (!(irregular instanceof Map)) { return Collections.emptyList(); } Object values = ((Map) irregular).get("values"); if (!(values instanceof List)) { return Collections.emptyList(); } List result = new ArrayList<>(); for (Object item : (List) values) { if (item instanceof Map) { BigDecimal value = VppUnPayloadHelper.getDecimal((Map) item, "value"); if (value != null) { result.add(value); } } } return result; } private static BigDecimal maxAbsFromIntervals(Map signal) { BigDecimal max = null; for (BigDecimal value : valuesFromIntervals(signal)) { max = maxAbs(max, value.abs()); } return max; } @SuppressWarnings("unchecked") private static BigDecimal maxAbsFromResourceValues(Map resource) { Object values = resource.get("values"); if (!(values instanceof List)) { return null; } BigDecimal max = null; for (Object item : (List) values) { if (item instanceof Map) { BigDecimal value = VppUnPayloadHelper.getDecimal((Map) item, "value"); if (value != null) { max = maxAbs(max, value.abs()); } } } return max; } private static boolean hasResourceValues(List> resources) { for (Map resource : resources) { if (maxAbsFromResourceValues(resource) != null) { return true; } if (VppUnPayloadHelper.getDecimal(resource, "load") != null) { return true; } } return false; } private static BigDecimal maxAbs(BigDecimal current, BigDecimal candidate) { if (candidate == null) { return current; } if (current == null || candidate.compareTo(current) > 0) { return candidate; } return current; } }