package com.trafficaudit.reportexport.calc;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.trafficaudit.dataimport.entity.CityBusMonthly;
|
import com.trafficaudit.dataimport.entity.CityTaxiMonthly;
|
import com.trafficaudit.dataimport.mapper.CityBusMonthlyMapper;
|
import com.trafficaudit.dataimport.mapper.CityTaxiMonthlyMapper;
|
import org.springframework.stereotype.Service;
|
|
import javax.annotation.Resource;
|
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 城市客运口径计算服务(汇总大表数据驱动改造 M1-城市客运-公交/出租/轨道轮渡,2026-09-08)。
|
*
|
* 口径与既有多表导出 loadCityBusByMonth / loadCityTaxiByMonth / loadCityRailFerryByMonth 完全一致
|
* (决策基线 A2/B4/B5/C7;2026-07 与 _备份…_清理前_20260904.xlsx 公交/出租/轨道轮渡台账页 O 列回归 0 差异):
|
* - 公交/出租:按月 → 市州 → [客运量, 旅客周转量, 城市内客运量, 城市内旅客周转量],按 DB city 字段分组,"全省"=全部市州合计;
|
* - 轨道/轮渡:同一 city_bus_monthly 表的 rail / ferry 字段(轨道=武汉/黄石,轮渡=武汉;全省=合计)。
|
*
|
* 输出为“月 → 市州 → double[4]”;累计由写回层对 1..m 月求和。同比按 Q1 以母版缓存 2025 参照组为基准,不在本服务计算。
|
*/
|
@Service
|
public class PaxCalc {
|
|
public static final String PROVINCE = "全省";
|
|
@Resource
|
private CityBusMonthlyMapper cityBusMapper;
|
@Resource
|
private CityTaxiMonthlyMapper cityTaxiMapper;
|
|
/** 公交:月 → 市州 → [客运量,周转量,城市内客运量,城市内周转量] */
|
public Map<Integer, Map<String, double[]>> busMonthly(String yearPrefix, int limit) {
|
Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>();
|
List<CityBusMonthly> rows = cityBusMapper.selectList(
|
new LambdaQueryWrapper<CityBusMonthly>().likeRight(CityBusMonthly::getReportPeriod, yearPrefix));
|
for (CityBusMonthly r : rows) {
|
int m = monthOf(r.getReportPeriod());
|
if (m < 1 || m > limit) continue;
|
String city = r.getCity() == null ? "未知" : r.getCity();
|
accumulate(result, city, m,
|
nz(r.getPassengerVolume()), nz(r.getTurnover()),
|
nz(r.getPassengerCity()), nz(r.getTurnoverCity()));
|
}
|
return result;
|
}
|
|
/** 巡游出租:月 → 市州 → [客运量,周转量,城市内客运量,城市内周转量] */
|
public Map<Integer, Map<String, double[]>> taxiMonthly(String yearPrefix, int limit) {
|
Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>();
|
List<CityTaxiMonthly> rows = cityTaxiMapper.selectList(
|
new LambdaQueryWrapper<CityTaxiMonthly>().likeRight(CityTaxiMonthly::getReportPeriod, yearPrefix));
|
for (CityTaxiMonthly r : rows) {
|
int m = monthOf(r.getReportPeriod());
|
if (m < 1 || m > limit) continue;
|
String city = r.getCity() == null ? "未知" : r.getCity();
|
accumulate(result, city, m,
|
nz(r.getPassengerVolume()), nz(r.getTurnover()),
|
nz(r.getPassengerCity()), nz(r.getTurnoverCity()));
|
}
|
return result;
|
}
|
|
/** 轨道/轮渡:月 → 市州 → [轨道客运量,轨道周转量,轮渡客运量,轮渡周转量] */
|
public Map<Integer, Map<String, double[]>> railFerryMonthly(String yearPrefix, int limit) {
|
Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>();
|
List<CityBusMonthly> rows = cityBusMapper.selectList(
|
new LambdaQueryWrapper<CityBusMonthly>().likeRight(CityBusMonthly::getReportPeriod, yearPrefix));
|
for (CityBusMonthly r : rows) {
|
int m = monthOf(r.getReportPeriod());
|
if (m < 1 || m > limit) continue;
|
String city = r.getCity() == null ? "未知" : r.getCity();
|
accumulate(result, city, m,
|
nz(r.getRailPassengerVolume()), nz(r.getRailTurnover()),
|
nz(r.getFerryPassengerVolume()), nz(r.getFerryTurnover()));
|
}
|
return result;
|
}
|
|
private void accumulate(Map<Integer, Map<String, double[]>> result, String city, int m,
|
double v0, double v1, double v2, double v3) {
|
Map<String, double[]> cityMap = result.computeIfAbsent(m, k -> new HashMap<>());
|
double[] arr = cityMap.computeIfAbsent(city, k -> new double[4]);
|
arr[0] += v0;
|
arr[1] += v1;
|
arr[2] += v2;
|
arr[3] += v3;
|
double[] prov = cityMap.computeIfAbsent(PROVINCE, k -> new double[4]);
|
prov[0] += v0;
|
prov[1] += v1;
|
prov[2] += v2;
|
prov[3] += v3;
|
}
|
|
private int monthOf(String reportPeriod) {
|
if (reportPeriod == null) return 0;
|
String[] parts = reportPeriod.split("-");
|
if (parts.length < 2) return 0;
|
try {
|
return Integer.parseInt(parts[1]);
|
} catch (NumberFormatException e) {
|
return 0;
|
}
|
}
|
|
private double nz(Double v) { return v == null ? 0.0 : v; }
|
}
|