| | |
| | | BigDecimal totalMileage = BigDecimal.valueOf(totalMileageKm); |
| | | |
| | | PricingRule baseRule = config.findMatchedRule(orderTime); |
| | | result.put("起步价(" + baseRule.ruleName + ")"+"-"+baseRule.start+"-"+baseRule.end, baseRule.baseFare); |
| | | result.put("起步价(" + baseRule.ruleName + ")"+"|"+baseRule.start+"-"+baseRule.end+"="+baseRule.baseMin+"&"+baseRule.baseKm, baseRule.baseFare); |
| | | |
| | | if (totalMileage.compareTo(baseRule.baseKm) <= 0) { |
| | | return formatMap(result); |
| | |
| | | // BigDecimal totalSeg = distFee.add(timeFee).add(longExtra); |
| | | // 超出里程 |
| | | if (isOverBaseM) { |
| | | bill.put(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ml", bill.getOrDefault(activeRule.ruleName + activeRule.start + "-" + activeRule.end + "_Ml", BigDecimal.ZERO).add(segM)); |
| | | bill.put(activeRule.ruleName + "|"+activeRule.start + "-" + activeRule.end + "_Ml", bill.getOrDefault(activeRule.ruleName + activeRule.start + "-" + activeRule.end + "_Ml", BigDecimal.ZERO).add(segM)); |
| | | } |
| | | // 超出时间 |
| | | if (isOverBaseMs) { |
| | | bill.put(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ms", bill.getOrDefault(activeRule.ruleName + activeRule.start + "-" + activeRule.end + "_Ms", BigDecimal.ZERO).add(segMs)); |
| | | bill.put(activeRule.ruleName + "|"+activeRule.start + "-" + activeRule.end + "_Ms", bill.getOrDefault(activeRule.ruleName + activeRule.start + "-" + activeRule.end + "_Ms", BigDecimal.ZERO).add(segMs)); |
| | | } |
| | | |
| | | // 若不存在规则名称,则添加 |
| | | activeRuleNameRate.computeIfAbsent(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ml", k -> activeRule.perKmRate); // 超出里程的加价 |
| | | activeRuleNameRate.computeIfAbsent(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ms",k ->activeRule.perMinRate); // 超出时间的加价 |
| | | activeRuleNameRate.computeIfAbsent(activeRule.ruleName + "|"+activeRule.start + "-" + activeRule.end + "_Ml", k -> activeRule.perKmRate); // 超出里程的加价 |
| | | activeRuleNameRate.computeIfAbsent(activeRule.ruleName + "|"+activeRule.start + "-" + activeRule.end + "_Ms",k ->activeRule.perMinRate); // 超出时间的加价 |
| | | |
| | | activeRuleNameList.add(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ml"); |
| | | activeRuleNameList.add(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ms"); |
| | | activeRuleNameList.add(activeRule.ruleName + "|"+activeRule.start + "-" + activeRule.end + "_Ml"); |
| | | activeRuleNameList.add(activeRule.ruleName + "|"+activeRule.start + "-" + activeRule.end + "_Ms"); |
| | | // result.put(activeRule.ruleName, result.getOrDefault(activeRule.ruleName, BigDecimal.ZERO).add(totalSeg)); |
| | | } |
| | | // 1. 基础费率计算 |
| | |
| | | if(ruleName.endsWith("_Ml")){ |
| | | BigDecimal exceedValue = bill.get(ruleName); |
| | | if(Objects.nonNull(exceedValue)){ |
| | | result.put("distance"+split[0], result.getOrDefault(split[0], BigDecimal.ZERO).add(exceedValue)); |
| | | exceedValue = exceedValue.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); |
| | | }else{ |
| | | exceedValue = BigDecimal.ZERO; |
| | |
| | | exceedValue = BigDecimal.ZERO; |
| | | } |
| | | BigDecimal exceedRate = activeRuleNameRate.get(ruleName); |
| | | result.put(split[0], result.getOrDefault(split[0], BigDecimal.ZERO).add(exceedValue.multiply(exceedRate))); |
| | | result.put("时长费"+split[0]+"&"+exceedValue, result.getOrDefault(split[0], BigDecimal.ZERO).add(exceedValue.multiply(exceedRate))); |
| | | } |
| | | } |
| | | // 2. 远途加价计算 (基于区间判定) |
| | | BigDecimal longExtra = calculateLongDistExtra(BigDecimal.valueOf(totalMileageKm), config.longSteps); |
| | | result.put("远途费", longExtra); |
| | | // 计算远途里程 |
| | | BigDecimal longExtraValue = calculateLongDistExtra(BigDecimal.valueOf(totalMileageKm), config.longSteps); |
| | | result.put("远途费&"+longExtraValue, longExtra); |
| | | return formatMap(result); |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | return billM.subtract(extraStart).multiply(extraRate); |
| | | } |
| | | /** |
| | | * 计算远途费的里程 |
| | | */ |
| | | private BigDecimal calculateLongDistExtraValue(BigDecimal billM, List<LongRangeStep> steps) { |
| | | if (billM.compareTo(BigDecimal.ZERO) <= 0) return BigDecimal.ZERO; |
| | | |
| | | // 当前点所在的公里数 |
| | | BigDecimal extraStart = BigDecimal.ZERO; |
| | | BigDecimal extraRate = BigDecimal.ZERO; |
| | | |
| | | // 匹配区间规则 |
| | | for (LongRangeStep step : steps) { |
| | | if (step.isMatch(billM)) { |
| | | extraRate = step.addPrice; |
| | | extraStart = step.numStart; |
| | | break; |
| | | } |
| | | } |
| | | return billM.subtract(extraStart); |
| | | } |
| | | |
| | | private Map<String, BigDecimal> formatMap(Map<String, BigDecimal> map) { |
| | |
| | | |
| | | public static class PricingConfig { |
| | | public PricingRule holiday; |
| | | public PricingRule peak; |
| | | public List<PricingRule> peaks = new ArrayList<>(); |
| | | public PricingRule night; |
| | | public List<PricingRule> normals = new ArrayList<>(); |
| | | public List<LongRangeStep> longSteps = new ArrayList<>(); // 修改为区间列表 |
| | |
| | | public PricingRule findMatchedRule(Date date) { |
| | | LocalTime t = date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime(); |
| | | if (holiday.isMatch(t)) return holiday; |
| | | if (peak.isMatch(t)) return peak; |
| | | for (PricingRule r : peaks) if (r.isMatch(t)) return r; |
| | | if (night.isMatch(t)) return night; |
| | | for (PricingRule r : normals) if (r.isMatch(t)) return r; |
| | | return normals.get(0); |
| | |
| | | |
| | | private static PricingConfig setupMockConfig() { |
| | | PricingConfig config = new PricingConfig(); |
| | | config.peak = new PricingRule("高峰期", "14:40", "14:46", 15.0, 3.0, 5.0, 3.0, 0.8); |
| | | config.peaks.add(new PricingRule("高峰期", "14:40", "14:46", 15.0, 3.0, 5.0, 3.0, 0.8)); |
| | | config.peaks.add(new PricingRule("高峰期", "19:40", "20:46", 15.0, 3.0, 5.0, 3.0, 0.8)); |
| | | config.night = new PricingRule("夜间行驶", "14:47", "14:48", 18.0, 3.0, 5.0, 3.5, 1.0); |
| | | config.holiday = new PricingRule("节假日", "18:47", "18:48", 18.0, 3.0, 5.0, 4, 2.0); |
| | | config.normals.add(new PricingRule("普通时段", "14:46", "14:47", 10.0, 3.0, 5.0, 2.4, 0.5)); |