VppUnEventParser.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package com.usky.vpp.util;
  2. import com.usky.vpp.enums.VppUnEventPhase;
  3. import org.springframework.util.StringUtils;
  4. import java.math.BigDecimal;
  5. import java.math.RoundingMode;
  6. import java.time.LocalDateTime;
  7. import java.util.ArrayList;
  8. import java.util.Collections;
  9. import java.util.List;
  10. import java.util.Map;
  11. /**
  12. * 解析运管平台 DistributeEventRequest / Event 结构(DLT 1867 联调 JSON 实例)
  13. */
  14. public final class VppUnEventParser {
  15. private VppUnEventParser() {
  16. }
  17. @SuppressWarnings("unchecked")
  18. public static List<Map<String, Object>> extractEvents(Map<String, Object> body) {
  19. if (body == null) {
  20. return Collections.emptyList();
  21. }
  22. Object events = body.get("events");
  23. if (events instanceof List) {
  24. return (List<Map<String, Object>>) events;
  25. }
  26. if (body.containsKey("descriptor") || body.containsKey("activePeriod")) {
  27. return Collections.singletonList(body);
  28. }
  29. return Collections.emptyList();
  30. }
  31. @SuppressWarnings("unchecked")
  32. public static Map<String, Object> getDescriptor(Map<String, Object> event) {
  33. if (event == null) {
  34. return Collections.emptyMap();
  35. }
  36. Object descriptor = event.get("descriptor");
  37. if (descriptor instanceof Map) {
  38. return (Map<String, Object>) descriptor;
  39. }
  40. return event;
  41. }
  42. @SuppressWarnings("unchecked")
  43. public static Map<String, Object> getTarget(Map<String, Object> event) {
  44. if (event == null) {
  45. return Collections.emptyMap();
  46. }
  47. Object target = event.get("target");
  48. return target instanceof Map ? (Map<String, Object>) target : Collections.emptyMap();
  49. }
  50. @SuppressWarnings("unchecked")
  51. public static List<Map<String, Object>> getTargetResources(Map<String, Object> event) {
  52. Map<String, Object> target = getTarget(event);
  53. Object resources = target.get("resources");
  54. if (!(resources instanceof List)) {
  55. return Collections.emptyList();
  56. }
  57. List<Map<String, Object>> list = new ArrayList<>();
  58. for (Object item : (List<?>) resources) {
  59. if (item instanceof Map) {
  60. list.add((Map<String, Object>) item);
  61. }
  62. }
  63. return list;
  64. }
  65. public static VppUnEventPhase detectPhase(Map<String, Object> event) {
  66. Map<String, Object> descriptor = getDescriptor(event);
  67. Boolean filing = VppUnPayloadHelper.getBoolean(descriptor, "filing");
  68. Boolean lastFiling = VppUnPayloadHelper.getBoolean(descriptor, "lastFiling");
  69. List<Map<String, Object>> resources = getTargetResources(event);
  70. boolean hasValues = hasResourceValues(resources);
  71. if (Boolean.TRUE.equals(filing) && !hasValues) {
  72. return VppUnEventPhase.INVITATION;
  73. }
  74. if (Boolean.TRUE.equals(filing) && hasValues) {
  75. return VppUnEventPhase.DECLARE_FEEDBACK;
  76. }
  77. if (Boolean.FALSE.equals(filing) && Boolean.TRUE.equals(lastFiling) && hasValues) {
  78. return VppUnEventPhase.SPLIT_RESULT;
  79. }
  80. if (Boolean.FALSE.equals(filing) && Boolean.TRUE.equals(lastFiling)) {
  81. return VppUnEventPhase.SPLIT_NOTICE;
  82. }
  83. if (hasValues) {
  84. return VppUnEventPhase.CLEARING_PUBLICITY;
  85. }
  86. return VppUnEventPhase.UNKNOWN;
  87. }
  88. public static String getEventId(Map<String, Object> event) {
  89. Map<String, Object> descriptor = getDescriptor(event);
  90. return VppUnPayloadHelper.getString(descriptor, "eventID", "eventId", "event_id");
  91. }
  92. public static Integer mapResponseType(Map<String, Object> descriptor) {
  93. Object notification = VppUnPayloadHelper.getRaw(descriptor, "notification");
  94. Integer mapped = VppUnPayloadHelper.parseResponseType(notification);
  95. if (mapped != null) {
  96. return mapped;
  97. }
  98. return 1;
  99. }
  100. public static Integer mapEventType(Map<String, Object> descriptor) {
  101. Object control = VppUnPayloadHelper.getRaw(descriptor, "control");
  102. Integer mapped = VppUnPayloadHelper.parseEventType(control);
  103. if (mapped != null) {
  104. return mapped;
  105. }
  106. String text = control == null ? "" : String.valueOf(control);
  107. if (text.contains("fillValley")) {
  108. return 2;
  109. }
  110. return 1;
  111. }
  112. public static Integer mapPlatformStatus(Map<String, Object> descriptor) {
  113. String status = VppUnPayloadHelper.getString(descriptor, "status");
  114. if (!StringUtils.hasText(status)) {
  115. return null;
  116. }
  117. switch (status.trim().toLowerCase()) {
  118. case "cancelled":
  119. return 4;
  120. case "completed":
  121. return 3;
  122. case "active":
  123. return 2;
  124. case "far":
  125. case "near":
  126. case "none":
  127. default:
  128. return 0;
  129. }
  130. }
  131. @SuppressWarnings("unchecked")
  132. public static LocalDateTime[] resolveActivePeriod(Map<String, Object> event) {
  133. Object periods = event.get("activePeriod");
  134. if (!(periods instanceof List) || ((List<?>) periods).isEmpty()) {
  135. return new LocalDateTime[]{null, null};
  136. }
  137. Object first = ((List<?>) periods).get(0);
  138. if (!(first instanceof Map)) {
  139. return new LocalDateTime[]{null, null};
  140. }
  141. Map<String, Object> period = (Map<String, Object>) first;
  142. LocalDateTime start = VppUnPayloadHelper.getDateTime(period, "dtstart", "startTime");
  143. LocalDateTime end = VppUnPayloadHelper.getDateTime(period, "dtend", "endTime");
  144. return new LocalDateTime[]{start, end};
  145. }
  146. @SuppressWarnings("unchecked")
  147. public static BigDecimal extractDemandChargeKw(Map<String, Object> event) {
  148. BigDecimal maxAbs = null;
  149. Object signals = event.get("signals");
  150. if (!(signals instanceof Map)) {
  151. return null;
  152. }
  153. Object signal = ((Map<String, Object>) signals).get("signal");
  154. List<?> signalList;
  155. if (signal instanceof List) {
  156. signalList = (List<?>) signal;
  157. } else if (signal instanceof Map) {
  158. signalList = Collections.singletonList(signal);
  159. } else {
  160. return null;
  161. }
  162. for (Object sigObj : signalList) {
  163. if (!(sigObj instanceof Map)) {
  164. continue;
  165. }
  166. Map<String, Object> sig = (Map<String, Object>) sigObj;
  167. String signalName = VppUnPayloadHelper.getString(sig, "signalName");
  168. if (!"DEMAND_CHARGE".equalsIgnoreCase(signalName)) {
  169. continue;
  170. }
  171. maxAbs = maxAbs(maxAbs, maxAbsFromIntervals(sig));
  172. }
  173. return maxAbs;
  174. }
  175. @SuppressWarnings("unchecked")
  176. public static BigDecimal extractEnergyPrice(Map<String, Object> event) {
  177. Object signals = event.get("signals");
  178. if (!(signals instanceof Map)) {
  179. return null;
  180. }
  181. Object signal = ((Map<String, Object>) signals).get("signal");
  182. List<?> signalList;
  183. if (signal instanceof List) {
  184. signalList = (List<?>) signal;
  185. } else if (signal instanceof Map) {
  186. signalList = Collections.singletonList(signal);
  187. } else {
  188. return null;
  189. }
  190. BigDecimal sum = BigDecimal.ZERO;
  191. int count = 0;
  192. for (Object sigObj : signalList) {
  193. if (!(sigObj instanceof Map)) {
  194. continue;
  195. }
  196. Map<String, Object> sig = (Map<String, Object>) sigObj;
  197. String signalName = VppUnPayloadHelper.getString(sig, "signalName");
  198. if (!"ENERGY_PRICE".equalsIgnoreCase(signalName)) {
  199. continue;
  200. }
  201. List<BigDecimal> values = valuesFromIntervals(sig);
  202. for (BigDecimal value : values) {
  203. sum = sum.add(value);
  204. count++;
  205. }
  206. }
  207. if (count == 0) {
  208. return null;
  209. }
  210. return sum.divide(BigDecimal.valueOf(count), 4, RoundingMode.HALF_UP);
  211. }
  212. public static BigDecimal sumResourceLoadKw(List<Map<String, Object>> resources, boolean absolute) {
  213. BigDecimal total = BigDecimal.ZERO;
  214. for (Map<String, Object> resource : resources) {
  215. BigDecimal load = maxAbsFromResourceValues(resource);
  216. if (load == null) {
  217. load = VppUnPayloadHelper.getDecimal(resource, "load");
  218. }
  219. if (load == null) {
  220. continue;
  221. }
  222. total = total.add(absolute ? load.abs() : load);
  223. }
  224. return total;
  225. }
  226. @SuppressWarnings("unchecked")
  227. private static List<BigDecimal> valuesFromIntervals(Map<String, Object> signal) {
  228. Object intervals = signal.get("intervals");
  229. if (!(intervals instanceof Map)) {
  230. return Collections.emptyList();
  231. }
  232. Object irregular = ((Map<String, Object>) intervals).get("irregular");
  233. if (!(irregular instanceof Map)) {
  234. return Collections.emptyList();
  235. }
  236. Object values = ((Map<String, Object>) irregular).get("values");
  237. if (!(values instanceof List)) {
  238. return Collections.emptyList();
  239. }
  240. List<BigDecimal> result = new ArrayList<>();
  241. for (Object item : (List<?>) values) {
  242. if (item instanceof Map) {
  243. BigDecimal value = VppUnPayloadHelper.getDecimal((Map<String, Object>) item, "value");
  244. if (value != null) {
  245. result.add(value);
  246. }
  247. }
  248. }
  249. return result;
  250. }
  251. private static BigDecimal maxAbsFromIntervals(Map<String, Object> signal) {
  252. BigDecimal max = null;
  253. for (BigDecimal value : valuesFromIntervals(signal)) {
  254. max = maxAbs(max, value.abs());
  255. }
  256. return max;
  257. }
  258. @SuppressWarnings("unchecked")
  259. private static BigDecimal maxAbsFromResourceValues(Map<String, Object> resource) {
  260. Object values = resource.get("values");
  261. if (!(values instanceof List)) {
  262. return null;
  263. }
  264. BigDecimal max = null;
  265. for (Object item : (List<?>) values) {
  266. if (item instanceof Map) {
  267. BigDecimal value = VppUnPayloadHelper.getDecimal((Map<String, Object>) item, "value");
  268. if (value != null) {
  269. max = maxAbs(max, value.abs());
  270. }
  271. }
  272. }
  273. return max;
  274. }
  275. private static boolean hasResourceValues(List<Map<String, Object>> resources) {
  276. for (Map<String, Object> resource : resources) {
  277. if (maxAbsFromResourceValues(resource) != null) {
  278. return true;
  279. }
  280. if (VppUnPayloadHelper.getDecimal(resource, "load") != null) {
  281. return true;
  282. }
  283. }
  284. return false;
  285. }
  286. private static BigDecimal maxAbs(BigDecimal current, BigDecimal candidate) {
  287. if (candidate == null) {
  288. return current;
  289. }
  290. if (current == null || candidate.compareTo(current) > 0) {
  291. return candidate;
  292. }
  293. return current;
  294. }
  295. }