完成责任量化功能

This commit is contained in:
2023-07-28 13:36:15 +08:00
parent a14381bcc5
commit d8cbf9c971
6 changed files with 155 additions and 63 deletions

View File

@@ -0,0 +1,25 @@
package com.njcn.advance.pojo.bo.responsibility;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author hongawen
* @version 1.0.0
* @date 2023年07月28日 11:32
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RespCommon implements Serializable {
private int pNum;
private int userIntervalTime;
private int lineInterval;
}

View File

@@ -0,0 +1,25 @@
package com.njcn.advance.pojo.bo.responsibility;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author hongawen
* @version 1.0.0
* @date 2023年07月28日 11:38
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RespHarmData implements Serializable {
private float[] harmData;
private List<Long> harmTime;
private float overLimit;
}

View File

@@ -57,7 +57,7 @@ public class UserDataController extends BaseController {
@OperateInfo(info = LogEnum.BUSINESS_COMMON) @OperateInfo(info = LogEnum.BUSINESS_COMMON)
@GetMapping("/userDataIntegrityList") @PostMapping("/userDataIntegrityList")
@ApiOperation("用采完整性不足列表") @ApiOperation("用采完整性不足列表")
@ApiImplicitParam(name = "userDataIntegrityParam", value = "查询参数", required = true) @ApiImplicitParam(name = "userDataIntegrityParam", value = "查询参数", required = true)
public HttpResult<Page<RespUserDataIntegrity>> userDataIntegrityList(@RequestBody @Validated UserDataIntegrityParam userDataIntegrityParam) { public HttpResult<Page<RespUserDataIntegrity>> userDataIntegrityList(@RequestBody @Validated UserDataIntegrityParam userDataIntegrityParam) {

View File

@@ -2,6 +2,7 @@ package com.njcn.advance.service.responsibility;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.advance.pojo.bo.responsibility.UserDataExcel;
import com.njcn.advance.pojo.po.responsibility.RespUserData; import com.njcn.advance.pojo.po.responsibility.RespUserData;
import com.njcn.common.pojo.dto.SelectOption; import com.njcn.common.pojo.dto.SelectOption;
import com.njcn.web.pojo.param.BaseParam; import com.njcn.web.pojo.param.BaseParam;
@@ -33,4 +34,6 @@ public interface IRespUserDataService extends IService<RespUserData> {
List<SelectOption> userDataSelect(); List<SelectOption> userDataSelect();
void deleteUserDataByIds(List<String> ids); void deleteUserDataByIds(List<String> ids);
List<UserDataExcel> getUserDataExcelList(String userDataId);
} }

View File

@@ -86,6 +86,8 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
private final IRespDataResultService respDataResultService; private final IRespDataResultService respDataResultService;
private final IRespUserDataService respUserDataService;
@Override @Override
public Page<RespDataDTO> responsibilityList(BaseParam queryParam) { public Page<RespDataDTO> responsibilityList(BaseParam queryParam) {
QueryWrapper<RespDataDTO> queryWrapper = new QueryWrapper<>(); QueryWrapper<RespDataDTO> queryWrapper = new QueryWrapper<>();
@@ -135,59 +137,23 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
//调用c++依赖需要待初始化的参数 //调用c++依赖需要待初始化的参数
int pNode, pNum, win, harmNum; int pNode, pNum, win, harmNum;
float harmMk; float harmMk;
LambdaQueryWrapper<RespUserData> userDataLambdaQueryWrapper = new LambdaQueryWrapper<>(); List<UserDataExcel> userDataExcels = respUserDataService.getUserDataExcelList(responsibilityCalculateParam.getUserDataId());
userDataLambdaQueryWrapper.eq(RespUserData::getId, responsibilityCalculateParam.getUserDataId()).eq(RespUserData::getState, DataStateEnum.ENABLE.getCode());
RespUserData respUserData = iRespUserDataService.getOne(userDataLambdaQueryWrapper);
if (Objects.isNull(respUserData)) {
throw new BusinessException(AdvanceResponseEnum.USER_DATA_NOT_FOUND);
}
InputStream fileStream = fileStorageUtil.getFileStream(respUserData.getDataPath());
String excelDataStr = IoUtil.read(fileStream, CharsetUtil.UTF_8);
//将文件流转为list集合
List<UserDataExcel> userDataExcels = JSONArray.parseArray(excelDataStr, UserDataExcel.class);
if (CollectionUtils.isEmpty(userDataExcels)) {
throw new BusinessException(AdvanceResponseEnum.USER_DATA_NOT_FOUND);
}
//开始处理,根据接口参数需求,需要节点数(用户数,用户名+监测点号为一个用户),时间范围内功率数据 //开始处理,根据接口参数需求,需要节点数(用户数,用户名+监测点号为一个用户),时间范围内功率数据
DealDataResult dealDataResult = RespUserDataServiceImpl.getStanderData(userDataExcels, 1); DealDataResult dealDataResult = RespUserDataServiceImpl.getStanderData(userDataExcels, 1);
Map<String/*户号@监测点号@户名*/, Map<String/*yyyy-MM-dd天日期*/, List<UserDataExcel>>> totalData = dealDataResult.getTotalListData();
Map<String/*户号@监测点号@户名*/, Map<String/*yyyy-MM-dd天日期*/, List<UserDataExcel>>> finalData = new HashMap<>();
/*第一个参数pNode 如果时间范围内完整性不足90%的节点,不参与责任量化统计,因为之前处理过用采数据此时只需要判断是否满足100%就可以判断*/
//根据时间天数,获取理论上多少次用采数据
List<String> dateStr = PubUtils.getTimes(DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime(), DatePattern.NORM_DATE_PATTERN), DateUtil.parse(responsibilityCalculateParam.getSearchEndTime(), DatePattern.NORM_DATE_PATTERN)); List<String> dateStr = PubUtils.getTimes(DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime(), DatePattern.NORM_DATE_PATTERN), DateUtil.parse(responsibilityCalculateParam.getSearchEndTime(), DatePattern.NORM_DATE_PATTERN));
int dueCounts = dateStr.size() * 96; Map<String/*户号@监测点号@户名*/, Map<String/*yyyy-MM-dd天日期*/, List<UserDataExcel>>> finalData = getFinalUserData(dealDataResult, dateStr);
Set<String> userNames = totalData.keySet();
for (String userName : userNames) {
int realCounts = 0;
Map<String, List<UserDataExcel>> temp = totalData.get(userName);
for (String date : dateStr) {
if (CollectionUtil.isNotEmpty(temp.get(date))) {
realCounts = realCounts + temp.get(date).size();
}
}
if (realCounts == dueCounts) {
//只有期望和实际数量一致的时候才作为计算用户
finalData.put(userName, temp);
}
}
//至此finalData便是我们最终获得的用于计算责任数据,第一个参数节点数值pNode获取到 //至此finalData便是我们最终获得的用于计算责任数据,第一个参数节点数值pNode获取到
//第一个参数pNode
pNode = finalData.size(); pNode = finalData.size();
if (pNode < 1) { if (pNode < 1) {
//没有合理的用采数据直接返回 //没有合理的用采数据直接返回
throw new BusinessException(AdvanceResponseEnum.USER_DATA_P_NODE_PARAMETER_ERROR); throw new BusinessException(AdvanceResponseEnum.USER_DATA_P_NODE_PARAMETER_ERROR);
} }
//第二个参数pNum根据起始时间和截止时间以及监测点测量间隔计算数量 //第二个参数pNum根据起始时间和截止时间以及监测点测量间隔计算数量
LineDetailDataVO lineDetailData = lineFeignClient.getLineDetailData(responsibilityCalculateParam.getLineId()).getData(); RespCommon pNumAndInterval = getPNumAndInterval(finalData, responsibilityCalculateParam.getLineId(), dateStr);
int lineInterval = lineDetailData.getTimeInterval(); pNum = pNumAndInterval.getPNum();
int userIntervalTime; int userIntervalTime = pNumAndInterval.getUserIntervalTime();
if (lineInterval == 1 || lineInterval == 3 || lineInterval == 5) { int lineInterval = pNumAndInterval.getLineInterval();
userIntervalTime = 15;
pNum = dateStr.size() * 96;
} else {
userIntervalTime = 30;
pNum = dateStr.size() * 48;
finalData = dealFinalDataByLineInterval(finalData);
}
//第三个参数win,根据起始时间和截止时间的间隔 //第三个参数win,根据起始时间和截止时间的间隔
if (dateStr.size() > 1) { if (dateStr.size() > 1) {
win = 96; win = 96;
@@ -200,21 +166,7 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
harmNum = pNum; harmNum = pNum;
//至此基础数据组装完毕,开始组装功率数据和谐波数据 //至此基础数据组装完毕,开始组装功率数据和谐波数据
//先做谐波数据理论上到这步的时候谐波数据是满足完整性并已经补充完整性到100%,此处需要将谐波数据与功率数据长度匹配上 //先做谐波数据理论上到这步的时候谐波数据是满足完整性并已经补充完整性到100%,此处需要将谐波数据与功率数据长度匹配上
HarmHistoryDataDTO data = harmDataFeignClient.getHistoryHarmData(new HistoryHarmParam(responsibilityCalculateParam.getSearchBeginTime(), responsibilityCalculateParam.getSearchEndTime(), responsibilityCalculateParam.getLineId(), responsibilityCalculateParam.getType(), responsibilityCalculateParam.getTime())).getData(); RespHarmData respHarmData = getRespHarmData(responsibilityCalculateParam,lineInterval);
List<HarmData> historyData = data.getHistoryData();
historyData = getDataWithLineInterval(historyData, lineInterval);
//理论上此处的historyData的长度等于pNum,开始填充harm_data
float[] harmData = new float[144000];
//谐波波形的横轴时间集合
List<Long> harmTime = new ArrayList<>();
for (int i = 0; i < historyData.size(); i++) {
Float value = historyData.get(i).getValue();
if (value != null) {
value = value * 1000;
}
harmData[i] = value;
harmTime.add(PubUtils.instantToDate(historyData.get(i).getTime()).getTime());
}
//harmData填充完毕后开始组装功率数据 //harmData填充完毕后开始组装功率数据
//首先获取当前时间内的各个用户的数据 //首先获取当前时间内的各个用户的数据
Map<String/*用户名*/, List<UserDataExcel>> originalPData = new HashMap<>(); Map<String/*用户名*/, List<UserDataExcel>> originalPData = new HashMap<>();
@@ -256,7 +208,7 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
qvvrStruct.harm_num = harmNum; qvvrStruct.harm_num = harmNum;
qvvrStruct.harm_mk = harmMk; qvvrStruct.harm_mk = harmMk;
qvvrStruct.p_data = pData; qvvrStruct.p_data = pData;
qvvrStruct.harm_data = harmData; qvvrStruct.harm_data = respHarmData.getHarmData();
ResponsibilityCallDllOrSo responsibilityCallDllOrSo = new ResponsibilityCallDllOrSo("harm_response"); ResponsibilityCallDllOrSo responsibilityCallDllOrSo = new ResponsibilityCallDllOrSo("harm_response");
responsibilityCallDllOrSo.setPath(); responsibilityCallDllOrSo.setPath();
ResponsibilityCallDllOrSo.ResponsibilityLibrary responsibilityLibrary = ResponsibilityCallDllOrSo.ResponsibilityLibrary.INSTANTCE; ResponsibilityCallDllOrSo.ResponsibilityLibrary responsibilityLibrary = ResponsibilityCallDllOrSo.ResponsibilityLibrary.INSTANTCE;
@@ -397,7 +349,7 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
.eq(RespDataResult::getTime, responsibilityCalculateParam.getTime()) .eq(RespDataResult::getTime, responsibilityCalculateParam.getTime())
.eq(RespDataResult::getStartTime, DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime() + " 00:00:00", DatePattern.NORM_DATETIME_PATTERN)) .eq(RespDataResult::getStartTime, DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime() + " 00:00:00", DatePattern.NORM_DATETIME_PATTERN))
.eq(RespDataResult::getEndTime, DateUtil.parse(responsibilityCalculateParam.getSearchEndTime() + " 23:59:59", DatePattern.NORM_DATETIME_PATTERN)) .eq(RespDataResult::getEndTime, DateUtil.parse(responsibilityCalculateParam.getSearchEndTime() + " 23:59:59", DatePattern.NORM_DATETIME_PATTERN))
.eq(RespDataResult::getLimitValue, data.getOverLimit()); .eq(RespDataResult::getLimitValue, respHarmData.getOverLimit());
RespDataResult respDataResult = respDataResultService.getOne(respDataResultLambdaQueryWrapper); RespDataResult respDataResult = respDataResultService.getOne(respDataResultLambdaQueryWrapper);
if (Objects.isNull(respDataResult)) { if (Objects.isNull(respDataResult)) {
respDataResult = new RespDataResult(); respDataResult = new RespDataResult();
@@ -405,7 +357,7 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
respDataResult.setTime(responsibilityCalculateParam.getTime()); respDataResult.setTime(responsibilityCalculateParam.getTime());
respDataResult.setStartTime(DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime() + " 00:00:00", DatePattern.NORM_DATETIME_PATTERN)); respDataResult.setStartTime(DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime() + " 00:00:00", DatePattern.NORM_DATETIME_PATTERN));
respDataResult.setEndTime(DateUtil.parse(responsibilityCalculateParam.getSearchEndTime() + " 23:59:59", DatePattern.NORM_DATETIME_PATTERN)); respDataResult.setEndTime(DateUtil.parse(responsibilityCalculateParam.getSearchEndTime() + " 23:59:59", DatePattern.NORM_DATETIME_PATTERN));
respDataResult.setLimitValue(data.getOverLimit()); respDataResult.setLimitValue(respHarmData.getOverLimit());
//时间横轴数据 timeDatas //时间横轴数据 timeDatas
JSONArray timeDataJson = JSONArray.parseArray(JSON.toJSONString(timeDatas)); JSONArray timeDataJson = JSONArray.parseArray(JSON.toJSONString(timeDatas));
InputStream timeDataStream = IoUtil.toStream(timeDataJson.toString(), CharsetUtil.UTF_8); InputStream timeDataStream = IoUtil.toStream(timeDataJson.toString(), CharsetUtil.UTF_8);
@@ -417,7 +369,7 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
String customerPath = fileStorageUtil.uploadStream(customerStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); String customerPath = fileStorageUtil.uploadStream(customerStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json"));
respDataResult.setUserDetailData(customerPath); respDataResult.setUserDetailData(customerPath);
//调用qvvr生成的中间数据 //调用qvvr生成的中间数据
CacheQvvrData cacheQvvrData = new CacheQvvrData(qvvrStruct.getP_node(), qvvrStruct.getHarm_num(), qvvrStruct.getHarm_data(), qvvrStruct.FKdata, qvvrStruct.HKdata, names, userIntervalTime, qvvrStruct.win, userIntervalTime, harmTime); CacheQvvrData cacheQvvrData = new CacheQvvrData(qvvrStruct.getP_node(), qvvrStruct.getHarm_num(), qvvrStruct.getHarm_data(), qvvrStruct.FKdata, qvvrStruct.HKdata, names, userIntervalTime, qvvrStruct.win, userIntervalTime, respHarmData.getHarmTime());
JSONObject cacheQvvrDataDataJson = (JSONObject) JSONObject.toJSON(cacheQvvrData); JSONObject cacheQvvrDataDataJson = (JSONObject) JSONObject.toJSON(cacheQvvrData);
InputStream cacheQvvrDataStream = IoUtil.toStream(cacheQvvrDataDataJson.toString(), CharsetUtil.UTF_8); InputStream cacheQvvrDataStream = IoUtil.toStream(cacheQvvrDataDataJson.toString(), CharsetUtil.UTF_8);
String cacheQvvrDataPath = fileStorageUtil.uploadStream(cacheQvvrDataStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); String cacheQvvrDataPath = fileStorageUtil.uploadStream(cacheQvvrDataStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json"));
@@ -868,4 +820,73 @@ public class RespDataServiceImpl extends ServiceImpl<RespDataMapper, RespData> i
result.add(tempe); result.add(tempe);
return result; return result;
} }
/***
* 用采数据,根据用户选择的时间窗口过滤出稍后用于计算的用采数据
*/
private Map<String, Map<String, List<UserDataExcel>>> getFinalUserData(DealDataResult dealDataResult, List<String> dateStr) {
Map<String/*户号@监测点号@户名*/, Map<String/*yyyy-MM-dd天日期*/, List<UserDataExcel>>> totalData = dealDataResult.getTotalListData();
Map<String/*户号@监测点号@户名*/, Map<String/*yyyy-MM-dd天日期*/, List<UserDataExcel>>> finalData = new HashMap<>();
/*第一个参数pNode 如果时间范围内完整性不足90%的节点,不参与责任量化统计,因为之前处理过用采数据此时只需要判断是否满足100%就可以判断*/
int dueCounts = dateStr.size() * 96;
Set<String> userNames = totalData.keySet();
for (String userName : userNames) {
int realCounts = 0;
Map<String, List<UserDataExcel>> temp = totalData.get(userName);
for (String date : dateStr) {
if (CollectionUtil.isNotEmpty(temp.get(date))) {
realCounts = realCounts + temp.get(date).size();
}
}
if (realCounts == dueCounts) {
//只有期望和实际数量一致的时候才作为计算用户
finalData.put(userName, temp);
}
}
return finalData;
}
/***
* 处理获取pNum参数
*/
private RespCommon getPNumAndInterval(Map<String, Map<String, List<UserDataExcel>>> finalData, String lineId, List<String> dateStr) {
int pNum;
LineDetailDataVO lineDetailData = lineFeignClient.getLineDetailData(lineId).getData();
int lineInterval = lineDetailData.getTimeInterval();
int userIntervalTime;
if (lineInterval == 1 || lineInterval == 3 || lineInterval == 5) {
userIntervalTime = 15;
pNum = dateStr.size() * 96;
} else {
userIntervalTime = 30;
pNum = dateStr.size() * 48;
finalData = dealFinalDataByLineInterval(finalData);
}
return new RespCommon(pNum, userIntervalTime,lineInterval);
}
/***
* 获取责任需要的谐波数据
*/
private RespHarmData getRespHarmData(ResponsibilityCalculateParam responsibilityCalculateParam, int lineInterval){
HarmHistoryDataDTO data = harmDataFeignClient.getHistoryHarmData(new HistoryHarmParam(responsibilityCalculateParam.getSearchBeginTime(), responsibilityCalculateParam.getSearchEndTime(), responsibilityCalculateParam.getLineId(), responsibilityCalculateParam.getType(), responsibilityCalculateParam.getTime())).getData();
List<HarmData> historyData = data.getHistoryData();
historyData = getDataWithLineInterval(historyData, lineInterval);
//理论上此处的historyData的长度等于pNum,开始填充harm_data
float[] harmData = new float[144000];
//谐波波形的横轴时间集合
List<Long> harmTime = new ArrayList<>();
for (int i = 0; i < historyData.size(); i++) {
Float value = historyData.get(i).getValue();
if (value != null) {
value = value * 1000;
}
harmData[i] = value;
harmTime.add(PubUtils.instantToDate(historyData.get(i).getTime()).getTime());
}
return new RespHarmData(harmData,harmTime,data.getOverLimit());
}
} }

View File

@@ -132,6 +132,24 @@ public class RespUserDataServiceImpl extends ServiceImpl<RespUserDataMapper, Res
this.baseMapper.deleteUserDataByIds(ids); this.baseMapper.deleteUserDataByIds(ids);
} }
@Override
public List<UserDataExcel> getUserDataExcelList(String userDataId) {
LambdaQueryWrapper<RespUserData> userDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
userDataLambdaQueryWrapper.eq(RespUserData::getId, userDataId).eq(RespUserData::getState, DataStateEnum.ENABLE.getCode());
RespUserData respUserData = this.getOne(userDataLambdaQueryWrapper);
if (Objects.isNull(respUserData)) {
throw new BusinessException(AdvanceResponseEnum.USER_DATA_NOT_FOUND);
}
InputStream fileStream = fileStorageUtil.getFileStream(respUserData.getDataPath());
String excelDataStr = IoUtil.read(fileStream, CharsetUtil.UTF_8);
//将文件流转为list集合
List<UserDataExcel> userDataExcels = JSONArray.parseArray(excelDataStr, UserDataExcel.class);
if (CollectionUtils.isEmpty(userDataExcels)) {
throw new BusinessException(AdvanceResponseEnum.USER_DATA_NOT_FOUND);
}
return userDataExcels;
}
/** /**
* 根据流获取出用采有功功率数据 * 根据流获取出用采有功功率数据