| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package com.usky.vpp.util;
- import com.usky.common.core.exception.BusinessException;
- import org.springframework.util.StringUtils;
- import java.math.BigDecimal;
- /**
- * 响应量系数区间:结构化边界校验、匹配、重叠判断与展示串拼装。
- */
- public final class VppResponseCoefficientHelper {
- private VppResponseCoefficientHelper() {
- }
- /**
- * 由结构化边界构建区间并校验。
- */
- public static Range of(BigDecimal lower, BigDecimal upper,
- Boolean lowerInclusive, Boolean upperInclusive) {
- if (lower == null && upper == null) {
- throw new BusinessException("响应量系数下限与上限不能同时为空");
- }
- boolean lowerInc = lower != null && Boolean.TRUE.equals(lowerInclusive);
- boolean upperInc = upper != null && Boolean.TRUE.equals(upperInclusive);
- if (lower != null && upper != null && lower.compareTo(upper) >= 0) {
- throw new BusinessException("响应量系数区间下限必须小于上限");
- }
- return new Range(lower, upper, lowerInc, upperInc);
- }
- public static boolean matches(BigDecimal lower, BigDecimal upper,
- Boolean lowerInclusive, Boolean upperInclusive,
- BigDecimal coefficient) {
- return coefficient != null && of(lower, upper, lowerInclusive, upperInclusive).contains(coefficient);
- }
- public static boolean matches(Range range, BigDecimal coefficient) {
- return coefficient != null && range != null && range.contains(coefficient);
- }
- public static boolean overlaps(Range left, Range right) {
- return left != null && right != null && left.overlaps(right);
- }
- /** 拼装展示串,如 [0.6,0.8)、<0.6、>1.4。 */
- public static String format(BigDecimal lower, BigDecimal upper,
- Boolean lowerInclusive, Boolean upperInclusive) {
- return of(lower, upper, lowerInclusive, upperInclusive).format();
- }
- public static String format(Range range) {
- return range == null ? null : range.format();
- }
- /**
- * 解析历史字符串区间,仅供数据迁移使用。
- */
- public static Range parse(String expression) {
- if (!StringUtils.hasText(expression)) {
- throw new BusinessException("响应量系数不能为空");
- }
- String value = expression.trim().replace(',', ',').replace(" ", "");
- try {
- if (value.startsWith("<=")) {
- return new Range(null, new BigDecimal(value.substring(2)), false, true);
- }
- if (value.startsWith("<")) {
- return new Range(null, new BigDecimal(value.substring(1)), false, false);
- }
- if (value.startsWith(">=")) {
- return new Range(new BigDecimal(value.substring(2)), null, true, false);
- }
- if (value.startsWith(">")) {
- return new Range(new BigDecimal(value.substring(1)), null, false, false);
- }
- if ((value.startsWith("[") || value.startsWith("("))
- && (value.endsWith("]") || value.endsWith(")"))) {
- String[] bounds = value.substring(1, value.length() - 1).split(",", -1);
- if (bounds.length != 2) {
- throw new IllegalArgumentException();
- }
- BigDecimal lower = new BigDecimal(bounds[0]);
- BigDecimal upper = new BigDecimal(bounds[1]);
- if (lower.compareTo(upper) >= 0) {
- throw new BusinessException("响应量系数区间下限必须小于上限");
- }
- return new Range(lower, upper, value.startsWith("["), value.endsWith("]"));
- }
- } catch (NumberFormatException ex) {
- throw new BusinessException("响应量系数格式无效");
- }
- throw new BusinessException("响应量系数格式无效,示例:[0.6,0.8)、<0.6、>1.4");
- }
- public static final class Range {
- private final BigDecimal lower;
- private final BigDecimal upper;
- private final boolean lowerInclusive;
- private final boolean upperInclusive;
- private Range(BigDecimal lower, BigDecimal upper, boolean lowerInclusive, boolean upperInclusive) {
- this.lower = lower;
- this.upper = upper;
- this.lowerInclusive = lowerInclusive;
- this.upperInclusive = upperInclusive;
- }
- public BigDecimal getLower() {
- return lower;
- }
- public BigDecimal getUpper() {
- return upper;
- }
- public boolean isLowerInclusive() {
- return lowerInclusive;
- }
- public boolean isUpperInclusive() {
- return upperInclusive;
- }
- public boolean contains(BigDecimal value) {
- if (lower != null) {
- int comparison = value.compareTo(lower);
- if (comparison < 0 || (comparison == 0 && !lowerInclusive)) {
- return false;
- }
- }
- if (upper != null) {
- int comparison = value.compareTo(upper);
- if (comparison > 0 || (comparison == 0 && !upperInclusive)) {
- return false;
- }
- }
- return true;
- }
- public boolean overlaps(Range other) {
- return upperAllows(other.lower, other.lowerInclusive)
- && other.upperAllows(lower, lowerInclusive);
- }
- public String format() {
- if (lower == null && upper != null) {
- return (upperInclusive ? "<=" : "<") + upper.stripTrailingZeros().toPlainString();
- }
- if (upper == null && lower != null) {
- return (lowerInclusive ? ">=" : ">") + lower.stripTrailingZeros().toPlainString();
- }
- String left = lowerInclusive ? "[" : "(";
- String right = upperInclusive ? "]" : ")";
- return left + lower.stripTrailingZeros().toPlainString()
- + "," + upper.stripTrailingZeros().toPlainString() + right;
- }
- private boolean upperAllows(BigDecimal otherLower, boolean otherLowerInclusive) {
- if (upper == null || otherLower == null) {
- return true;
- }
- int comparison = upper.compareTo(otherLower);
- return comparison > 0 || (comparison == 0 && upperInclusive && otherLowerInclusive);
- }
- }
- }
|