|
|
|
|
@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.scheduler.T
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.utils.DataTypeParseUtil;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.devicecontactmodel.vo.DeviceContactModelPageReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.utils.TimeConverterUtil;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordRespVO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.mqttdatarecord.vo.MqttDataRecordPageReqVO;
|
|
|
|
|
@ -64,10 +65,7 @@ import org.springframework.validation.annotation.Validated;
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.sql.Timestamp;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.time.Duration;
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.time.LocalTime;
|
|
|
|
|
import java.time.*;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
@ -1746,40 +1744,97 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
return new PageResult<>(availableDeviceList, page.getTotal());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<DeviceDO> deviceList(DevicePageReqVO pageReqVO) {
|
|
|
|
|
return deviceMapper.selectList(pageReqVO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 按时间区间查询设备整体开机率、稼动率日趋势。
|
|
|
|
|
* 按天复用 deviceOperationPage 统计单设备数据后求平均。
|
|
|
|
|
* 按时间区间查询设备整体开机率、稼动率日趋势
|
|
|
|
|
* 一次性查询时间范围内按天、按设备的统计数据,避免按天循环重复查库
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public List<DeviceRateTrendPointRespVO> getDeviceRateTrend(DeviceRateTrendReqVO reqVO) {
|
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
|
|
|
|
|
// 根据 period 解析查询日期范围,不包含当天
|
|
|
|
|
DeviceRateTrendPeriodEnum.DateRange dateRange = DeviceRateTrendPeriodEnum.valueOfCode(reqVO.getPeriod()).resolve(LocalDate.now());
|
|
|
|
|
LocalDateTime startDateTime = dateRange.getStart().atStartOfDay();
|
|
|
|
|
LocalDateTime endDateTime = dateRange.getEnd().atTime(LocalTime.MAX).withNano(0);
|
|
|
|
|
// 默认只统计排产设备,这里先得到最终参与统计的设备集合
|
|
|
|
|
|
|
|
|
|
DeviceRateTrendPeriodEnum.DateRange dateRange =
|
|
|
|
|
DeviceRateTrendPeriodEnum.valueOfCode(reqVO.getPeriod()).resolve(LocalDate.now());
|
|
|
|
|
|
|
|
|
|
LocalDate startDate = dateRange.getStart();
|
|
|
|
|
LocalDate endDate = dateRange.getEnd();
|
|
|
|
|
LocalDateTime startDateTime = startDate.atStartOfDay();
|
|
|
|
|
LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX).withNano(0);
|
|
|
|
|
|
|
|
|
|
String filteredIds = buildFilteredDeviceIds(reqVO);
|
|
|
|
|
if (StringUtils.isBlank(filteredIds)) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Long> deviceIds = Arrays.stream(filteredIds.split(","))
|
|
|
|
|
.filter(StringUtils::isNotBlank)
|
|
|
|
|
.map(Long::valueOf)
|
|
|
|
|
.distinct()
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Map<String, Object>> statsList = tdengineService.selectDeviceStatsTrendFromTD(
|
|
|
|
|
deviceIds,
|
|
|
|
|
startDateTime.format(formatter),
|
|
|
|
|
endDateTime.format(formatter)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// day -> (deviceId -> record)
|
|
|
|
|
Map<LocalDate, Map<Long, DeviceTotalTimeRecordRespVO>> dayDeviceRecordMap = convertTrendStatsToMap(statsList);
|
|
|
|
|
|
|
|
|
|
// skipHoliday 时,区间一次查出所有节假日,避免按天查库
|
|
|
|
|
Set<LocalDate> holidaySet = Collections.emptySet();
|
|
|
|
|
if (Boolean.TRUE.equals(reqVO.getSkipHoliday())) {
|
|
|
|
|
List<Date> holidays = deviceMapper.selectHolidayDaysInRange(
|
|
|
|
|
java.sql.Timestamp.valueOf(startDate.atStartOfDay()),
|
|
|
|
|
java.sql.Timestamp.valueOf(endDate.plusDays(1).atStartOfDay())
|
|
|
|
|
);
|
|
|
|
|
holidaySet = holidays == null ? Collections.emptySet() : holidays.stream()
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.map(this::toLocalDateSafe)
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int deviceCount = deviceIds.size();
|
|
|
|
|
List<DeviceRateTrendPointRespVO> result = new ArrayList<>();
|
|
|
|
|
for (LocalDate day = startDateTime.toLocalDate(); !day.isAfter(endDateTime.toLocalDate()); day = day.plusDays(1)) {
|
|
|
|
|
// 跳过节假日时,这一天不查询,也不返回
|
|
|
|
|
if (Boolean.TRUE.equals(reqVO.getSkipHoliday()) && isHoliday(day)) {
|
|
|
|
|
|
|
|
|
|
for (LocalDate day = startDate; !day.isAfter(endDate); day = day.plusDays(1)) {
|
|
|
|
|
if (Boolean.TRUE.equals(reqVO.getSkipHoliday()) && holidaySet.contains(day)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
LocalDateTime dayStart = day.atStartOfDay();
|
|
|
|
|
LocalDateTime dayEnd = day.atTime(LocalTime.MAX).withNano(0);
|
|
|
|
|
// 复用现有 deviceOperationPage,查出当天每台设备的开机率、稼动率基础数据
|
|
|
|
|
List<DeviceTotalTimeRecordRespVO> deviceDayList = queryDeviceDayList(reqVO, filteredIds, dayStart.format(formatter), dayEnd.format(formatter));
|
|
|
|
|
|
|
|
|
|
Map<Long, DeviceTotalTimeRecordRespVO> dayMap =
|
|
|
|
|
dayDeviceRecordMap.getOrDefault(day, Collections.emptyMap());
|
|
|
|
|
|
|
|
|
|
double powerOnRateSum = 0D;
|
|
|
|
|
double utilizationRateSum = 0D;
|
|
|
|
|
int deviceCount = deviceDayList.size();
|
|
|
|
|
|
|
|
|
|
for (DeviceTotalTimeRecordRespVO record : deviceDayList) {
|
|
|
|
|
powerOnRateSum += parsePercentValue(record.getPowerOnRate());
|
|
|
|
|
utilizationRateSum += parsePercentValue(record.getUtilizationRate());
|
|
|
|
|
}
|
|
|
|
|
for (Long deviceId : deviceIds) {
|
|
|
|
|
DeviceTotalTimeRecordRespVO record = dayMap.get(deviceId);
|
|
|
|
|
if (record == null) {
|
|
|
|
|
// 无数据按 0
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 直接按秒计算,不走字符串百分比解析
|
|
|
|
|
double offlineSec = record.getTotalOfflineTime();
|
|
|
|
|
double runningSec = record.getTotalRunningTime();
|
|
|
|
|
double standbySec = record.getTotalStandbyTime();
|
|
|
|
|
double faultSec = record.getTotalFaultTime();
|
|
|
|
|
|
|
|
|
|
double onlineSec = runningSec + standbySec + faultSec;
|
|
|
|
|
double totalSec = offlineSec + onlineSec;
|
|
|
|
|
|
|
|
|
|
double powerOnRate = totalSec > 0 ? (onlineSec / totalSec) : 0D;
|
|
|
|
|
double utilizationRate = onlineSec > 0 ? (runningSec / onlineSec) : 0D;
|
|
|
|
|
|
|
|
|
|
powerOnRateSum += powerOnRate * 100D;
|
|
|
|
|
utilizationRateSum += utilizationRate * 100D;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceRateTrendPointRespVO point = new DeviceRateTrendPointRespVO();
|
|
|
|
|
point.setDay(day.toString());
|
|
|
|
|
@ -1787,11 +1842,101 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
point.setPowerOnRate(formatPercentValue(deviceCount > 0 ? powerOnRateSum / deviceCount : 0D));
|
|
|
|
|
point.setUtilizationRate(formatPercentValue(deviceCount > 0 ? utilizationRateSum / deviceCount : 0D));
|
|
|
|
|
result.add(point);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Map<LocalDate, Map<Long, DeviceTotalTimeRecordRespVO>> convertTrendStatsToMap(List<Map<String, Object>> statsList) {
|
|
|
|
|
Map<LocalDate, Map<Long, DeviceTotalTimeRecordRespVO>> result = new LinkedHashMap<>();
|
|
|
|
|
if (statsList == null || statsList.isEmpty()) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (Map<String, Object> row : statsList) {
|
|
|
|
|
Object statDayObj = row.get("statDay");
|
|
|
|
|
if (statDayObj == null) {
|
|
|
|
|
statDayObj = row.get("statday");
|
|
|
|
|
}
|
|
|
|
|
if (statDayObj == null || row.get("deviceId") == null) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalDate statDay;
|
|
|
|
|
if (statDayObj instanceof Timestamp) {
|
|
|
|
|
statDay = ((Timestamp) statDayObj).toLocalDateTime().toLocalDate();
|
|
|
|
|
} else if (statDayObj instanceof LocalDateTime) {
|
|
|
|
|
statDay = ((LocalDateTime) statDayObj).toLocalDate();
|
|
|
|
|
} else {
|
|
|
|
|
statDay = LocalDateTime.parse(statDayObj.toString().replace(" ", "T")).toLocalDate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Long deviceId = ((Number) row.get("deviceId")).longValue();
|
|
|
|
|
|
|
|
|
|
DeviceTotalTimeRecordRespVO vo = new DeviceTotalTimeRecordRespVO();
|
|
|
|
|
vo.setId(deviceId);
|
|
|
|
|
vo.setTotalOfflineTime(getDoubleValue(row, "totalOfflineTime"));
|
|
|
|
|
vo.setTotalRunningTime(getDoubleValue(row, "totalRunningTime"));
|
|
|
|
|
vo.setTotalStandbyTime(getDoubleValue(row, "totalStandbyTime"));
|
|
|
|
|
vo.setTotalFaultTime(getDoubleValue(row, "totalFaultTime"));
|
|
|
|
|
|
|
|
|
|
result.computeIfAbsent(statDay, key -> new HashMap<>()).put(deviceId, vo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 将按天按设备统计结果转换为 day -> device stats
|
|
|
|
|
*/
|
|
|
|
|
private Map<LocalDate, List<DeviceTotalTimeRecordRespVO>> convertTrendStats(List<Map<String, Object>> statsList) {
|
|
|
|
|
Map<LocalDate, List<DeviceTotalTimeRecordRespVO>> result = new LinkedHashMap<>();
|
|
|
|
|
if (statsList == null || statsList.isEmpty()) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (Map<String, Object> row : statsList) {
|
|
|
|
|
Object statDayObj = row.get("statDay");
|
|
|
|
|
if (statDayObj == null) {
|
|
|
|
|
statDayObj = row.get("statday");
|
|
|
|
|
}
|
|
|
|
|
if (statDayObj == null) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalDate statDay;
|
|
|
|
|
if (statDayObj instanceof Timestamp) {
|
|
|
|
|
statDay = ((Timestamp) statDayObj).toLocalDateTime().toLocalDate();
|
|
|
|
|
} else if (statDayObj instanceof LocalDateTime) {
|
|
|
|
|
statDay = ((LocalDateTime) statDayObj).toLocalDate();
|
|
|
|
|
} else {
|
|
|
|
|
statDay = LocalDateTime.parse(statDayObj.toString().replace(" ", "T")).toLocalDate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceTotalTimeRecordRespVO vo = new DeviceTotalTimeRecordRespVO();
|
|
|
|
|
vo.setId(((Number) row.get("deviceId")).longValue());
|
|
|
|
|
vo.setTotalOfflineTime(getDoubleValue(row, "totalOfflineTime"));
|
|
|
|
|
vo.setTotalRunningTime(getDoubleValue(row, "totalRunningTime"));
|
|
|
|
|
vo.setTotalStandbyTime(getDoubleValue(row, "totalStandbyTime"));
|
|
|
|
|
vo.setTotalFaultTime(getDoubleValue(row, "totalFaultTime"));
|
|
|
|
|
|
|
|
|
|
result.computeIfAbsent(statDay, key -> new ArrayList<>()).add(vo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private DeviceTotalTimeRecordReqVO buildTrendReqVO(LocalDate day) {
|
|
|
|
|
DeviceTotalTimeRecordReqVO reqVO = new DeviceTotalTimeRecordReqVO();
|
|
|
|
|
reqVO.setStartTime(day.atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
|
|
|
|
reqVO.setEndTime(day.atTime(LocalTime.MAX).withNano(0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
|
|
|
|
return reqVO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private double parsePercentValue(String percent) {
|
|
|
|
|
if (StringUtils.isBlank(percent)) {
|
|
|
|
|
return 0D;
|
|
|
|
|
@ -1810,37 +1955,57 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
return String.format("%.2f%%", value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private LocalDate toLocalDateSafe(Date date) {
|
|
|
|
|
if (date instanceof java.sql.Date) {
|
|
|
|
|
return ((java.sql.Date) date).toLocalDate();
|
|
|
|
|
}
|
|
|
|
|
if (date instanceof java.sql.Timestamp) {
|
|
|
|
|
return ((java.sql.Timestamp) date).toLocalDateTime().toLocalDate();
|
|
|
|
|
}
|
|
|
|
|
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<DeviceTotalTimeRecordRespVO> queryDeviceDayList(DeviceRateTrendReqVO reqVO, String ids, String startTime, String endTime) {
|
|
|
|
|
DeviceTotalTimeRecordReqVO pageReqVO =
|
|
|
|
|
new DeviceTotalTimeRecordReqVO();
|
|
|
|
|
pageReqVO.setDeviceCode(reqVO.getDeviceCode());
|
|
|
|
|
pageReqVO.setDeviceName(reqVO.getDeviceName());
|
|
|
|
|
pageReqVO.setIds(ids);
|
|
|
|
|
pageReqVO.setStartTime(startTime);
|
|
|
|
|
pageReqVO.setEndTime(endTime);
|
|
|
|
|
return deviceOperationRecordService.deviceOperationPageList(pageReqVO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String buildFilteredDeviceIds(DeviceRateTrendReqVO reqVO) {
|
|
|
|
|
boolean onlyScheduled = reqVO.getOnlyScheduled() == null || reqVO.getOnlyScheduled();
|
|
|
|
|
|
|
|
|
|
// 不只看排产设备时:
|
|
|
|
|
// 1. 如果前端传了 ids,就按传入 ids 查询
|
|
|
|
|
// 2. 如果前端没传 ids,就查询全部设备 id
|
|
|
|
|
if (!onlyScheduled) {
|
|
|
|
|
return reqVO.getIds();
|
|
|
|
|
if (StringUtils.isNotBlank(reqVO.getIds())) {
|
|
|
|
|
return reqVO.getIds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Long> allDeviceIds = deviceMapper.getAllDeviceIds();
|
|
|
|
|
if (CollectionUtils.isEmpty(allDeviceIds)) {
|
|
|
|
|
return "-1";
|
|
|
|
|
}
|
|
|
|
|
return allDeviceIds.stream()
|
|
|
|
|
.map(String::valueOf)
|
|
|
|
|
.collect(Collectors.joining(","));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 只统计排产设备
|
|
|
|
|
Collection<Long> requestIds = parseIds(reqVO.getIds());
|
|
|
|
|
List<Long> filteredDvIds = deviceMapper.selectScheduledDvIds(requestIds);
|
|
|
|
|
|
|
|
|
|
// 如果前端传了 ids,则在排产设备中再次过滤
|
|
|
|
|
if (StringUtils.isNotBlank(reqVO.getIds())) {
|
|
|
|
|
Set<Long> requestIdSet = new HashSet<>(requestIds);
|
|
|
|
|
filteredDvIds = filteredDvIds.stream().filter(requestIdSet::contains).collect(Collectors.toList());
|
|
|
|
|
filteredDvIds = filteredDvIds.stream()
|
|
|
|
|
.filter(requestIdSet::contains)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (filteredDvIds.isEmpty()) {
|
|
|
|
|
return "-1";
|
|
|
|
|
}
|
|
|
|
|
return filteredDvIds.stream().map(String::valueOf).collect(Collectors.joining(","));
|
|
|
|
|
|
|
|
|
|
return filteredDvIds.stream()
|
|
|
|
|
.map(String::valueOf)
|
|
|
|
|
.collect(Collectors.joining(","));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean isHoliday(LocalDate day) {
|
|
|
|
|
@ -1848,10 +2013,6 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
return !CollectionUtils.isEmpty(holidays);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String toPercent(double value) {
|
|
|
|
|
return String.format("%.2f%%", value * 100);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Collection<Long> parseIds(String ids) {
|
|
|
|
|
if (StringUtils.isBlank(ids)) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
@ -1865,5 +2026,71 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 根据设备单条运行时长统计,计算开机率和稼动率
|
|
|
|
|
* 计算逻辑与 calculateAndSetConvertedValues 保持一致:
|
|
|
|
|
* 开机率 = 在线时间 / 总时间
|
|
|
|
|
* 稼动率 = 运行时间 / 在线时间
|
|
|
|
|
*/
|
|
|
|
|
private void calculateRate(DeviceTotalTimeRecordRespVO record) {
|
|
|
|
|
if (record == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double offlineSec = record.getTotalOfflineTime();
|
|
|
|
|
double runningSec = record.getTotalRunningTime();
|
|
|
|
|
double standbySec = record.getTotalStandbyTime();
|
|
|
|
|
double faultSec = record.getTotalFaultTime();
|
|
|
|
|
|
|
|
|
|
// 在线时间 = 运行 + 待机 + 故障
|
|
|
|
|
double onlineSec = runningSec + standbySec + faultSec;
|
|
|
|
|
double totalSec = offlineSec + onlineSec;
|
|
|
|
|
|
|
|
|
|
// 防止异常值
|
|
|
|
|
if (totalSec < 0) {
|
|
|
|
|
totalSec = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 开机率 = 在线时间 / 总时间
|
|
|
|
|
double powerOnRate = 0D;
|
|
|
|
|
if (totalSec > 0) {
|
|
|
|
|
powerOnRate = onlineSec / totalSec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 稼动率 = 运行时间 / 在线时间
|
|
|
|
|
double utilizationRate = 0D;
|
|
|
|
|
if (onlineSec > 0) {
|
|
|
|
|
utilizationRate = runningSec / onlineSec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
record.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate));
|
|
|
|
|
record.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Double getDoubleValue(Map<String, Object> row, String key) {
|
|
|
|
|
if (row == null || key == null) {
|
|
|
|
|
return 0D;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Object value = row.get(key);
|
|
|
|
|
if (value == null) {
|
|
|
|
|
value = row.get(key.toLowerCase());
|
|
|
|
|
}
|
|
|
|
|
if (value == null) {
|
|
|
|
|
return 0D;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value instanceof Number) {
|
|
|
|
|
return ((Number) value).doubleValue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
return Double.parseDouble(value.toString());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
return 0D;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|