package com.moral.api.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.moral.api.entity.HistorySecondRadar;
import com.moral.api.mapper.HistorySecondRadarMapper;
import com.moral.api.pojo.query.radar.RadarListCond;
import com.moral.api.pojo.vo.radar.HistorySecondRadarListVo;
import com.moral.api.pojo.vo.radar.RadarListVo;
import com.moral.api.service.HistorySecondRadarService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
/**
*
* 服务实现类
*
*
* @author moral
* @since 2026-05-14
*/
@Service
public class HistorySecondRadarServiceImpl extends ServiceImpl implements HistorySecondRadarService {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final double HEIGHT_INTERVAL = 7.5;
@Override
public RadarListVo radarList(RadarListCond cond) {
RadarListVo radarListVo = new RadarListVo();
List time = new ArrayList<>();
List> pm25 = new ArrayList<>();
List> pm10 = new ArrayList<>();
List highList = buildHighList(cond.getHigh2());
List highList1 = buildHighList(cond.getHigh1());
List list = this.baseMapper.listRadar(cond);
for (HistorySecondRadarListVo row : list) {
time.add(row.getTimeStr());
double[] pm25Values = parseValues(row.getRadarData(), "a34004-Avg");
double[] pm10Values = parseValues(row.getRadarData(), "a34002-Avg");
pm25.add(buildPointList(pm25Values, highList.size(),highList1.size()));
pm10.add(buildPointList(pm10Values, highList.size(),highList1.size()));
}
radarListVo.setPm25(pm25);
radarListVo.setTime(time);
radarListVo.setPm10(pm10);
/* List> pm25 = new ArrayList<>();
List> pm10 = new ArrayList<>();
for(HistorySecondRadarListVo ot : list){
pm10.add(convertSingleRecordToJson(ot.getRadarDataPm10(),cond.getHigh1(),cond.getHigh2()));
pm25.add(convertSingleRecordToJson(ot.getRadarDataPm25(),cond.getHigh1(),cond.getHigh2()));
time.add(ot.getTimeStr());
}
radarListVo.setPm25(pm25);
radarListVo.setTime(time);
radarListVo.setPm10(pm10);*/
return radarListVo;
}
private static List buildPointList(double[] values, int pointCount, int minPointCount) {
List pointList = new ArrayList(pointCount);
int count = Math.min(pointCount, values.length);
int minCount = Math.min(minPointCount, values.length);
for (int i = minCount; i < count; i++) {
pointList.add(new double[]{values[i]});
}
return pointList;
}
private static List buildHighList(int MAX_HEIGHT) {
List highList = new ArrayList();
int count = (int) (MAX_HEIGHT / HEIGHT_INTERVAL) + 1;
for (int i = 0; i < count; i++) {
highList.add(formatHeight(i * HEIGHT_INTERVAL));
}
return highList;
}
private static double[] parseValues(String json, String key) {
if (json == null) {
return new double[0];
}
String keyToken = "\"" + key + "\":";
int keyIndex = json.indexOf(keyToken);
if (keyIndex < 0) {
return new double[0];
}
int bracketStart = json.indexOf('[', keyIndex + keyToken.length());
int bracketEnd = json.indexOf(']', bracketStart + 1);
if (bracketStart < 0 || bracketEnd < 0 || bracketEnd - bracketStart <= 1) {
return new double[0];
}
String body = json.substring(bracketStart + 1, bracketEnd).trim();
if (body.isEmpty()) {
return new double[0];
}
String[] parts = body.split(",");
double[] values = new double[parts.length];
for (int i = 0; i < parts.length; i++) {
values[i] = Double.parseDouble(parts[i].trim());
}
return values;
}
private static String formatHeight(double height) {
return BigDecimal.valueOf(height).stripTrailingZeros().toPlainString();
}
private List convertSingleRecordToJson(String rawData,int high1,int high2){
if (rawData == null || rawData.isEmpty()) {
return new ArrayList<>();
}
try {
// 3. 分割字符串
String[] valuesStr = rawData.split("\\*");
// 4. 预分配列表大小,假设约2000个数据,减少扩容
List seriesData = new ArrayList<>(valuesStr.length);
for (int i = 10; i < valuesStr.length; i++) {
// 简单的空值检查,避免 NumberFormatException
if (valuesStr[i].isEmpty()) continue;
double height = (i + 1) * HEIGHT_INTERVAL;
if(height> high1 && height < high2){
double pm25Value = Double.parseDouble(valuesStr[i]);
pm25Value = new BigDecimal(Double.toString(pm25Value))
.setScale(1, RoundingMode.HALF_UP)
.doubleValue();
// 使用 double 数组存储 [浓度, 高度],比对象更节省内存
seriesData.add(new double[]{pm25Value, height});
}
}
// 5. 序列化为 JSON
return seriesData;
} catch (Exception e) {
// 生产环境中建议记录日志,而不是打印堆栈
System.err.println("处理数据出错: " + e.getMessage());
return new ArrayList<>();
}
}
}