package cn.cecep.talroad.service.impl;

import cn.cecep.talroad.common.core.domain.R;
import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.common.core.utils.StringUtils;
import cn.cecep.talroad.common.redis.service.RedisService;
import cn.cecep.talroad.common.security.utils.SecurityUtils;
import cn.cecep.talroad.domain.*;
import cn.cecep.talroad.domain.analysis.BasDeviceParamAnalyse;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisConverter;
import cn.cecep.talroad.enums.PollutantTypeEnum;
import cn.cecep.talroad.enums.TimeTypeEnum;
import cn.cecep.talroad.feign.BaseRegionService;
import cn.cecep.talroad.mapper.*;
import cn.cecep.talroad.mapper.analysis.BasDeviceParamAnalyseMapper;
import cn.cecep.talroad.mapper.analysis.SRaOnlineEmissionsGasMapper;
import cn.cecep.talroad.mapper.analysis.SRaOnlineEmissionsWaterMapper;
import cn.cecep.talroad.service.HomePageMapService;
import cn.cecep.talroad.service.IPcAdslFactoryService;
import cn.cecep.talroad.service.IPcFactoryService;
import cn.cecep.talroad.service.IPcOutletService;
import cn.cecep.talroad.util.EmissionsConstants;
import cn.cecep.talroad.util.RedisUtils;
import cn.cecep.talroad.vo.*;
import cn.cecep.talroad.vo.homepage.*;
import cn.cecep.talroad.vo.query.EffectiveMonitoringRateQuery;
import cn.cecep.talroad.vo.query.PcFactoryQuery;
import cn.cecep.talroad.vo.query.SEnvWaterMonRealQuery;
import cn.cecep.talroad.vo.query.analysis.MonitoringPointWarningDetailsQuery;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


/**
 * 企业基本信息Service业务层处理
 *
 * @author szhpt
 * @date 2023-01-11
 */
@Slf4j
@Service
public class HomePageMapServiceImpl implements HomePageMapService {
    @Autowired
    public RedisTemplate redisTemplate;

    @Autowired
    private IPcFactoryService pcFactoryService;

    @Autowired
    private PcFactoryMapper pcFactoryMapper;

    @Autowired
    private BMainPollDisSelfMonMapper bMainPollDisSelfMonMapper;

    @Autowired
    private PcYieldTrendMapper pcYieldTrendMapper;

    @Autowired
    private STaskYieldTrendMapper sTaskYieldTrendMapper;

    @Autowired
    private SRaOnlineEmissionsGasMapper sRaOnlineEmissionsGasMapper;

    @Autowired
    private SRaOnlineEmissionsWaterMapper sRaOnlineEmissionsWaterMapper;

    @Autowired
    private BMainEmissionPollutionAirMapper bMainEmissionPollutionAirMapper;

    @Autowired
    private BMainEmissionPollutionWaterMapper bMainEmissionPollutionWaterMapper;

    @Autowired
    private EmissionsConstants emissionsConstants;
    @Autowired
    @Qualifier("baseRegionService")
    private BaseRegionService baseRegionService;

    @Autowired
    private RedisService redisService;

    @Override
    @Cacheable(cacheNames = "CompanyOverview", key = "(#industry ?: 'ALL')+(#region ?:'ALL')", sync = true)
    public HpmCompanyOverviewVo selectCompanyOverview(String industry,String region) {
        List<String> regionArr=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(region);
        if(r.getCode()==200){
            regionArr=r.getData();
        }
        HpmCompanyOverviewVo selectCompanyOverview = pcFactoryMapper.selectCompanyOverview(industry,regionArr);
        HpmCompanyOverviewVo selectOutletOverview = pcFactoryMapper.selectOutletOverview(industry,regionArr);

        selectCompanyOverview.setWaterEnterprise(selectOutletOverview.getWaterEnterprise());
        selectCompanyOverview.setWaterMainOutlet(selectOutletOverview.getWaterMainOutlet());
        selectCompanyOverview.setWaterOrdinaryOutlet(selectOutletOverview.getWaterOrdinaryOutlet());

        selectCompanyOverview.setAirEnterprise(selectOutletOverview.getAirEnterprise());
        selectCompanyOverview.setAirMainOutlet(selectOutletOverview.getAirMainOutlet());
        selectCompanyOverview.setAirOrdinaryOutlet(selectOutletOverview.getAirOrdinaryOutlet());

        selectCompanyOverview.setAirInorganization(selectOutletOverview.getAirInorganization());

        // 查询雨水排口数量
        HpmCompanyOverviewVo vo3 = pcFactoryMapper.selectWaterRainwaterOutlet(industry,regionArr);
        selectCompanyOverview.setWaterRainwaterOutlet(vo3.getWaterRainwaterOutlet());

        return selectCompanyOverview;
    }

   @Override
    @Cacheable(cacheNames = "MeritRatingOverview", key = "(#industry ?: 'ALL')+(#regionCode ?:'ALL')", sync = true)
    public HpmMeriRatingOverviewVo selectMeritRatingOverview(String industry,String regionCode) {
        List<String> regionCodes=new ArrayList<>();
       R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
       if(r.getCode()==200){
           regionCodes=r.getData();
       }
        HpmMeriRatingOverviewVo hpmMeriRatingOverviewVo = Optional.ofNullable(
                pcFactoryMapper.selectMeritRatingOverview(industry,regionCodes)).orElse(new HpmMeriRatingOverviewVo());
        int num = hpmMeriRatingOverviewVo.getCompleteRatingNum() + hpmMeriRatingOverviewVo.getIncompleteRatingNum();

        hpmMeriRatingOverviewVo.setCompleteRatingProp(new BigDecimal(hpmMeriRatingOverviewVo.getCompleteRatingNum() == 0 ? 0 : hpmMeriRatingOverviewVo.getCompleteRatingNum() / num).setScale(4, RoundingMode.HALF_UP));
        hpmMeriRatingOverviewVo.setIncompleteRatingProp(new BigDecimal(hpmMeriRatingOverviewVo.getIncompleteRatingNum() == 0 ? 0 : hpmMeriRatingOverviewVo.getCompleteRatingNum() / num).setScale(4, RoundingMode.HALF_UP));

        return hpmMeriRatingOverviewVo;
    }

    @Override
    public HpmEnvironmentOverviewVo selectOnvironmentOverview(String industry,String regionCode) {
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
        if(r.getCode()==200){
            regionCodes=r.getData();
        }
        return pcFactoryMapper.selectOnvironmentOverview(industry,regionCodes);
    }

    @Override
    @Cacheable(cacheNames = "EmissionTrackingOverview", key = "(#emissionType ?: 'ALL')+(#regionCode ?:'ALL')", sync = true)
    public HpmEmissionTrackingOverviewVo selectEmissionTrackingOverview(String emissionType,String regionCode) {
        emissionType = StringUtils.equals(emissionType, "1") ? "执行报告" : "系统核算";
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
        if(r.getCode()==200){
            regionCodes=r.getData();
        }
        HpmEmissionTrackingOverviewVo hpmEmissionTrackingOverviewVo = pcFactoryMapper.selectGasEmissionTrackingOverview(emissionType,regionCodes);
        HpmEmissionTrackingOverviewVo waterEmissionTrackingOverview = pcFactoryMapper.selectWaterEmissionTrackingOverview(emissionType,regionCodes);
        if (Objects.isNull(hpmEmissionTrackingOverviewVo)) {
            return new HpmEmissionTrackingOverviewVo();
        }

        hpmEmissionTrackingOverviewVo.setActualDischargeCod(waterEmissionTrackingOverview.getActualDischargeCod());
        hpmEmissionTrackingOverviewVo.setPermissibleDischargeCod(waterEmissionTrackingOverview.getPermissibleDischargeCod());
        hpmEmissionTrackingOverviewVo.setActualDischargeTn(waterEmissionTrackingOverview.getActualDischargeTn());
        hpmEmissionTrackingOverviewVo.setPermissibleDischargeTn(waterEmissionTrackingOverview.getPermissibleDischargeTn());
        hpmEmissionTrackingOverviewVo.setActualDischargeTp(waterEmissionTrackingOverview.getActualDischargeTp());
        hpmEmissionTrackingOverviewVo.setPermissibleDischargeTp(waterEmissionTrackingOverview.getPermissibleDischargeTp());
        hpmEmissionTrackingOverviewVo.setActualDischargeNhn(waterEmissionTrackingOverview.getActualDischargeNhn());
        hpmEmissionTrackingOverviewVo.setPermissibleDischargeNhn(waterEmissionTrackingOverview.getPermissibleDischargeNhn());

        hpmEmissionTrackingOverviewVo.setRatioSo2(hpmEmissionTrackingOverviewVo.getPermissibleDischargeSo2().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargeSo2().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargeSo2(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        hpmEmissionTrackingOverviewVo.setRatioNox(hpmEmissionTrackingOverviewVo.getPermissibleDischargeNox().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargeNox().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargeNox(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        hpmEmissionTrackingOverviewVo.setRatioPm(hpmEmissionTrackingOverviewVo.getPermissibleDischargePm().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargePm().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargePm(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        hpmEmissionTrackingOverviewVo.setRatioVocs(hpmEmissionTrackingOverviewVo.getPermissibleDischargeVocs().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargeVocs().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargeVocs(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));

        hpmEmissionTrackingOverviewVo.setRatioCod(hpmEmissionTrackingOverviewVo.getPermissibleDischargeCod().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargeCod().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargeCod(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        hpmEmissionTrackingOverviewVo.setRatioNhn(hpmEmissionTrackingOverviewVo.getPermissibleDischargeNhn().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargeNhn().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargeNhn(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        hpmEmissionTrackingOverviewVo.setRatioTn(hpmEmissionTrackingOverviewVo.getPermissibleDischargeTn().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargeTn().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargeTn(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        hpmEmissionTrackingOverviewVo.setRatioTp(hpmEmissionTrackingOverviewVo.getPermissibleDischargeTp().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
                hpmEmissionTrackingOverviewVo.getActualDischargeTp().divide(hpmEmissionTrackingOverviewVo.getPermissibleDischargeTp(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        return hpmEmissionTrackingOverviewVo;
    }

    @Override
    public HpmEmissionRatioOverviewVo selectEmissionRatioOverview(String regionCode) {
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
        if(r.getCode()==200){
            regionCodes=r.getData();
        }
        // 污染物名称（污染物名称：SO2、NOx、颗粒物、VOCs、COD、氨氮、总磷、总氮， 如果名称填写So2则不会统计至首页大屏中）
        return Optional.ofNullable(bMainPollDisSelfMonMapper.selectCountByPollutantsName(regionCodes)).orElse(new HpmEmissionRatioOverviewVo());
    }

    @Override
    @Cacheable(cacheNames = "EnterpriseMapPop", key = "#factoryId ?: 'ALL'", sync = true)
    public HpmEnterprisePopVo selectEnterpriseMapPop(String factoryId) {
        HpmEnterprisePopVo hpmEnterprisePopVo = new HpmEnterprisePopVo();

//        PcOutlet pcOutlet = pcOutletMapper.selectOne(new LambdaQueryWrapper<PcOutlet>().eq(PcOutlet::getId, outletId));
//        if (Objects.isNull(pcOutlet)){
//            throw new ServiceException("排口未找到或者不正确，请稍后重试");
//        }

        PcFactoryQuery query = new PcFactoryQuery();
        query.setId(factoryId);
        List<PcFactoryVo> pcFactoryVos = pcFactoryMapper.selectPcFactoryVoList(query, null,null);
        PcFactoryVo vo = pcFactoryVos.get(0);

        hpmEnterprisePopVo.setFactoryLabelList(pcFactoryService.getLabel(factoryId, true));
        hpmEnterprisePopVo.setFactoryName(vo.getFactoryName());
        hpmEnterprisePopVo.setCityName(vo.getCityName());
        hpmEnterprisePopVo.setCountryName(vo.getCountryName());
        hpmEnterprisePopVo.setWipollunit(vo.getWipollunit());
        hpmEnterprisePopVo.setIndustryCategory(vo.getIndustryCategoryName());
        hpmEnterprisePopVo.setProdBusiOperation(vo.getProdBusiOperation());

        return hpmEnterprisePopVo;
    }

    @Override
    public List<ImportPollutionDischargeVo> selectImportPollutionDischarge(String regionCode) {
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
        if(r.getCode()==200){
            regionCodes=r.getData();
        }
        return pcFactoryMapper.selectImportPollutionDischarge(regionCodes);
    }

    @Override
    public EnvironmentCreditPropVo selectProportionOfEcologicalEnvironmentCredit() {
        return pcFactoryMapper.selectProportionOfEcologicalEnvironmentCredit();
    }

    @Override
    @Cacheable(cacheNames = "RankingStat", key = "(#pollutantType ?: 'ALL')+(#regionCode ?: 'ALL')", sync = true)
    public DistributionOfMajorEmittersVo selectRankingStat(String pollutantType,String regionCode) {
        DistributionOfMajorEmittersVo distributionOfMajorEmittersVo = new DistributionOfMajorEmittersVo();
        Map<String, String> gasFieldMap = MapUtil.<String, String>builder()
                .put("NOₓ", "actuallyEmittingNox")
                .put("SO₂", "actuallyEmittingSo2")
                .put("VOCs", "actuallyEmittingVocs")
                .put("颗粒物", "actuallyEmittingPm")
                .build();
        Map<String, String> waterFieldMap = MapUtil.<String, String>builder()
                .put("COD", "actuallyEmittingCod")
                .put("总氮", "actuallyEmittingTn")
                .put("总磷", "actuallyEmittingTp")
                .put("氨氮", "actuallyEmittingNhn")
                .build();

        int thisYear = DateUtil.thisYear();

        List<?> emissionListByCompany;
        List<?> emissionListByCompanyAndIndustry;
        final String field;
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
        if(r.getCode()==200){
            regionCodes=r.getData();
        }
        if (gasFieldMap.containsKey(pollutantType)) {
            field = gasFieldMap.get(pollutantType);
            emissionListByCompany = bMainEmissionPollutionAirMapper.selectEmissionDataList("系统核算", null,
                    thisYear + "", null, null, false,regionCodes);
            emissionListByCompanyAndIndustry = bMainEmissionPollutionAirMapper.selectEmissionDataList("系统核算", null,
                    thisYear + "", null, null, true,regionCodes);
        } else if (waterFieldMap.containsKey(pollutantType)) {
            field = waterFieldMap.get(pollutantType);
            emissionListByCompany = bMainEmissionPollutionWaterMapper.selectEmissionDataList("系统核算", null,
                    thisYear + "", null, null, false,regionCodes);
            emissionListByCompanyAndIndustry = bMainEmissionPollutionWaterMapper.selectEmissionDataList("系统核算", null,
                    thisYear + "", null, null, true,regionCodes);
        } else {
            return distributionOfMajorEmittersVo;
        }

        if (Objects.isNull(emissionListByCompany)) {
            return distributionOfMajorEmittersVo;
        }

        Stream<AbstractMap.SimpleEntry<BigDecimal, BigDecimal>> groupedStream = getGroupedStream(10, field, emissionListByCompany);
        if (Objects.nonNull(groupedStream)) {
            List<String> xData = groupedStream.map(entry -> entry.getKey() + "-" + entry.getValue()).collect(Collectors.toList());
            List<Long> factoryEmissionsCount = getCountGroupByPartitionCount(emissionListByCompany, field, getGroupedStream(10, field, emissionListByCompany));

            distributionOfMajorEmittersVo.setXData(xData);
            distributionOfMajorEmittersVo.setFactoryEmissionsCount(factoryEmissionsCount);
        }
        // 查询group by行业的排放量
//        List<Map<String, Object>> emissionsByCompanyAndIndustry = pcFactoryMapper.selectEmissionsByCompany(pollutantType, true);

        Map<AbstractMap.SimpleEntry<String, String>, List<Object>> industryCategory = emissionListByCompanyAndIndustry.stream()
                .filter(x -> ObjectUtil.isNotEmpty(BeanUtil.getFieldValue(x, "indusName")))
                .collect(Collectors.groupingBy(x -> new AbstractMap.SimpleEntry<>(BeanUtil.getFieldValue(x, "indusName").toString(),
                        String.valueOf(BeanUtil.getFieldValue(x, "industryCategory")))));

        List<Map<String, Object>> industryEmissionsCount = industryCategory.keySet()
                .stream()
                .map(key -> {
                    List<?> maps = industryCategory.get(key);
                    Stream<AbstractMap.SimpleEntry<BigDecimal, BigDecimal>> groupedStreamByIndustry = getGroupedStream(20, field, maps);
                    List<Long> factoryEmissionsCountByIndustry = getCountGroupByPartitionCount(maps, field, groupedStreamByIndustry);
                    return MapUtil.<String, Object>builder()
                            .put("name", key.getKey())
                            .put("code", key.getValue())
                            .put("num", CollUtil.isEmpty(factoryEmissionsCountByIndustry) ? 0 : CollUtil.getLast(factoryEmissionsCountByIndustry))
                            .build();
                }).collect(Collectors.toList());

        industryEmissionsCount.add(MapUtil.<String, Object>builder()
                .put("name", "企业总数")
                .put("code", "factory")
                .put("num", industryEmissionsCount.stream()
                        .mapToLong(x -> Long.parseLong(x.get("num").toString()))
                        .sum())
                .build());

        distributionOfMajorEmittersVo.setIndustryEmissionsCount(industryEmissionsCount);

        return distributionOfMajorEmittersVo;
    }

    @Override
    public EChartsVO enterpriseMapPopEmissionTrends(String factoryId, final String dataType, String startTime, String endTime) {
        EChartsVO eChartsVO = new EChartsVO();
        // 定义查询数据，格式化数据的日期类型，每个类型均为不同环境的类型，format是前端传递的类型，dateFormat是返回前端的格式化类型，pgSqlDateFormat是pg数据库类型
        final String format, dateFormat, pgSqlDateFormat;
        DateTime monitoringStartTime, monitoringEndTime;
        switch (dataType) {
            default:
                format = "yyyy-MM-dd HH:mm:ss";
                dateFormat = "yyyy-MM-dd HH:mm:ss";
                pgSqlDateFormat = "YYYY-MM-DD HH24:MI:SS";
                monitoringEndTime = DateUtil.parse(endTime, format);
                break;
            case "Y":
                // 年
                format = "yyyy";
                dateFormat = "yyyy-MM-dd";
                pgSqlDateFormat = "YYYY-MM-DD";
                DateTime parseYear = DateUtil.parse(endTime, format);
                monitoringEndTime = parseYear.year() == DateUtil.thisYear() ? new DateTime() : DateUtil.endOfYear(parseYear);
                break;
            case "M":
                // 月
                format = "yyyy-MM";
                dateFormat = "yyyy-MM-dd";
                pgSqlDateFormat = "YYYY-MM-DD";
                DateTime parseMonth = DateUtil.parse(endTime, format);
                monitoringEndTime = DateUtil.compare(parseMonth, new Date(), format) == 0 ? new DateTime() : DateUtil.endOfMonth(parseMonth);
                break;
            case "D":
                // 天
                format = "yyyy-MM-dd";
                dateFormat = "yyyy-MM-dd HH";
                pgSqlDateFormat = "YYYY-MM-DD HH24";
                DateTime parseDay = DateUtil.parse(endTime, format);
                monitoringEndTime = DateUtil.compare(parseDay, new Date(), format) == 0 ? new DateTime() : DateUtil.endOfDay(parseDay);
                break;
        }
        monitoringStartTime = DateUtil.parse(startTime, format);
        List<DateTime> timeRange = DateUtil.rangeToList(monitoringStartTime, monitoringEndTime, "D".equals(dataType) ? DateField.HOUR_OF_DAY : DateField.DAY_OF_MONTH);
        final String pgSqlFormat = StringUtils.format("to_char(monitor_time, '{}')", pgSqlDateFormat);

        eChartsVO.setXData(CollUtil.map(timeRange, x -> DateUtil.format(x, dateFormat), false));

        List<Map<String, String>> items = new ArrayList<>();
        items.add(new HashMap<String, String>() {{
            put("name", "SO₂");
            put("prop", "so2Emissions");
            put("unit", "kg");
        }});
        items.add(new HashMap<String, String>() {{
            put("name", "NOₓ");
            put("prop", "noxEmissions");
            put("unit", "kg");
        }});
        items.add(new HashMap<String, String>() {{
            put("name", "颗粒物");
            put("prop", "pmEmissions");
            put("unit", "kg");
        }});
        items.add(new HashMap<String, String>() {{
            put("name", "VOCs");
            put("prop", "vocsEmissions");
            put("unit", "kg");
        }});

        // 通过动态sql 获取不同groupby字段的排放量  gas -> "NOX", "SO2", "Vocs", "pm"  这里只获取主要字段
        final String[] gasImportantFields = emissionsConstants.getGasImportantFieldMap().keySet().toArray(new String[0]);
        List<GasPollEmissionsVO> gasPollEmissionsVos = sRaOnlineEmissionsGasMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
                monitoringStartTime.toString(), monitoringEndTime.toString(), gasImportantFields, null, pgSqlFormat);

        List<EChartsVO.SeriesObj> gasEmissionsSeries = getEmissionsSeries(items, gasPollEmissionsVos, timeRange, dateFormat, "groupByField");

        if (StringUtils.equals("D", dataType)) {
            // 废水没有小时数据，这里判断后不显示

            items = new ArrayList<>();
            items.add(new HashMap<String, String>() {{
                put("name", "COD浓度");
                put("prop", "codConcentration");
                put("unit", "kg");
            }});
            items.add(new HashMap<String, String>() {{
                put("name", "氨氮");
                put("prop", "ammoniaNitrogen");
                put("unit", "kg");
            }});
            items.add(new HashMap<String, String>() {{
                put("name", "总氮");
                put("prop", "nitrogenConcentration");
                put("unit", "kg");
            }});
            items.add(new HashMap<String, String>() {{
                put("name", "总磷");
                put("prop", "phosphorusConcentration");
                put("unit", "kg");
            }});

            final String[] waterImportantFields = emissionsConstants.getWaterImportantFieldMap().keySet().toArray(new String[0]);
            List<WaterPollEmissionsVO> waterPollEmissionsVos = sRaOnlineEmissionsWaterMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
                    monitoringStartTime.toString(), monitoringEndTime.toString(), waterImportantFields, null, pgSqlFormat);

            List<EChartsVO.SeriesObj> waterEmissionsSeries = getEmissionsSeries(items, waterPollEmissionsVos, timeRange, dateFormat, "groupByField");

            CollUtil.addAll(gasEmissionsSeries, waterEmissionsSeries);
        }

        eChartsVO.setSeries(gasEmissionsSeries);
        return eChartsVO;
    }

    @Override
    public EChartsVO selectEnterpriseMapPopYield(String factoryId, final String dataType, String startTime, String endTime) {
        EChartsVO eChartsVO = new EChartsVO();
        final String format, dateFormat;
        DateTime monitoringStartTime, monitoringEndTime;
        switch (dataType) {
            default:
                format = "yyyy-MM-dd HH:mm:ss";
                dateFormat = "yyyy-MM-dd HH:mm:ss";
                monitoringEndTime = DateUtil.parse(endTime, format);
                break;
            case "Y":
                // 年
                format = "yyyy";
                dateFormat = "yyyy-MM-dd";
                DateTime parse = DateUtil.parse(endTime, format);
                monitoringEndTime = parse.year() == DateUtil.thisYear() ? new DateTime() : DateUtil.endOfYear(parse);
                break;
            case "M":
                // 月
                format = "yyyy-MM";
                dateFormat = "yyyy-MM-dd";
                DateTime parseMonth = DateUtil.parse(endTime, format);
                monitoringEndTime = DateUtil.compare(parseMonth, new Date(), format) == 0 ? new DateTime() : DateUtil.endOfMonth(parseMonth);
                break;
            case "D":
                // 天
                format = "yyyy-MM-dd";
                dateFormat = "yyyy-MM-dd HH";
                DateTime parseDay = DateUtil.parse(endTime, format);
                monitoringEndTime = DateUtil.compare(parseDay, new Date(), format) == 0 ? new DateTime() : DateUtil.endOfDay(parseDay);
                break;
        }

        monitoringStartTime = DateUtil.parse(startTime, format);

        List<DateTime> timeRange = DateUtil.rangeToList(monitoringStartTime, monitoringEndTime, "D".equals(dataType) ? DateField.HOUR_OF_DAY : DateField.DAY_OF_MONTH);

        eChartsVO.setXData(CollUtil.map(timeRange, x -> DateUtil.format(x, dateFormat), false));

        List<PcYieldTrend> pcYieldTrends = pcYieldTrendMapper.selectByFactoryId(factoryId);

        List<STaskYieldTrend> sTaskYieldTrends = sTaskYieldTrendMapper.selectList(new QueryWrapper<STaskYieldTrend>()
                .select("factory_id","time_type","data_time","dict_code","sum(\"number\") as number")
                .eq("factory_id", factoryId)
                .eq("time_type", TimeTypeEnum.DAY.getCode().equals(dataType) ? TimeTypeEnum.HOUR.getCode() : TimeTypeEnum.DAY.getCode())
                .between("data_time", monitoringStartTime, monitoringEndTime)
                .groupBy("factory_id","time_type","data_time","dict_code")
                .orderByAsc("data_time"));

        List<EChartsVO.SeriesObj> collect = pcYieldTrends.stream()
                .map(pcYieldTrend -> {
                    EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
                    ser.setName(pcYieldTrend.getSmall());
                    ser.setUnit(pcYieldTrend.getUnit());
                    List<Object> values = new ArrayList<>();
                    timeRange.forEach(dataTime ->{

                        Double d = sTaskYieldTrends.stream().filter(sTaskYieldTrend -> StringUtils.equals(sTaskYieldTrend.getDictCode(), pcYieldTrend.getCode())&&DateUtil.compare(dataTime, sTaskYieldTrend.getDataTime(), dateFormat) == 0)
                                    .mapToDouble(sTaskYieldTrend->sTaskYieldTrend.getNumber().doubleValue()).findFirst().orElse(0);
                        values.add(d);
                    });
                    ser.setValues(values);
                    return ser;
                }).collect(Collectors.toList());

        eChartsVO.setSeries(collect);
        return eChartsVO;
    }

    @Override
    public EChartsVO emissionTrends(String factoryId, String selectType, String dataType, String startTime, String endTime) {
        EChartsVO eChartsVO = new EChartsVO();
        final String format, dateFormat, pgSqlDateFormat;
        DateTime monitoringStartTime, monitoringEndTime;
        switch (dataType) {
            default:
                format = "yyyy-MM-dd HH:mm:ss";
                dateFormat = "yyyy-MM-dd HH:mm:ss";
                pgSqlDateFormat = "YYYY-MM-DD HH24:MI:SS";
                monitoringStartTime = StringUtils.isNotEmpty(startTime) ? DateUtil.parse(startTime, format) : DateUtil.beginOfDay(new DateTime());
                monitoringEndTime = StringUtils.isNotEmpty(endTime) ? DateUtil.parse(endTime, format) : new DateTime();
                break;
            case "Y":
                // 年
                format = "yyyy";
                dateFormat = "yyyy-MM-dd";
                pgSqlDateFormat = "YYYY-MM-DD";
                DateTime parseStart = StringUtils.isNotEmpty(startTime) ? DateUtil.parse(startTime, format) : new DateTime();
                DateTime parseEnd = StringUtils.isNotEmpty(endTime) ? DateUtil.parse(endTime, format) : new DateTime();
                monitoringStartTime = DateUtil.beginOfYear(parseStart);
                monitoringEndTime = parseEnd.year() == DateUtil.thisYear() ? new DateTime() : DateUtil.endOfYear(parseEnd);
                break;
            case "M":
                // 月
                format = "yyyy-MM";
                dateFormat = "yyyy-MM-dd";
                pgSqlDateFormat = "YYYY-MM-DD";
                monitoringStartTime = DateUtil.beginOfMonth(StringUtils.isNotEmpty(startTime) ? DateUtil.parse(startTime, format) : new DateTime());
                monitoringEndTime = DateUtil.endOfMonth(StringUtils.isNotEmpty(endTime) ? DateUtil.parse(endTime, format) : new DateTime());
                break;
            case "D":
                // 天
                format = "yyyy-MM-dd";
                dateFormat = "yyyy-MM-dd HH";
                pgSqlDateFormat = "YYYY-MM-DD HH24";
                monitoringStartTime = DateUtil.beginOfDay(StringUtils.isNotEmpty(startTime) ? DateUtil.parse(startTime, format) : new DateTime());
                monitoringEndTime = DateUtil.endOfDay(StringUtils.isNotEmpty(endTime) ? DateUtil.parse(endTime, format) : new DateTime());
                break;
        }

        final String pgSqlFormat = StringUtils.format("to_char(monitor_time, '{}')", pgSqlDateFormat);

        List<DateTime> timeRange = DateUtil.rangeToList(monitoringStartTime, monitoringEndTime, "D".equals(dataType) ? DateField.HOUR_OF_DAY : DateField.DAY_OF_MONTH);
        eChartsVO.setXData(CollUtil.map(timeRange, x -> DateUtil.format(x, dateFormat), false));

        List<Map<String, String>> items;
        switch (selectType) {
            case "1":
                items = new ArrayList<>();
                items.add(new HashMap<String, String>() {{
                    put("name", "SO₂");
                    put("prop", "so2Emissions");
                    put("unit", "kg");
                }});
                items.add(new HashMap<String, String>() {{
                    put("name", "NOₓ");
                    put("prop", "noxEmissions");
                    put("unit", "kg");
                }});
                items.add(new HashMap<String, String>() {{
                    put("name", "颗粒物");
                    put("prop", "pmEmissions");
                    put("unit", "kg");
                }});
                items.add(new HashMap<String, String>() {{
                    put("name", "VOCs");
                    put("prop", "vocsEmissions");
                    put("unit", "kg");
                }});
                final String[] gasImportantFields = emissionsConstants.getGasImportantFieldMap().keySet().toArray(new String[0]);
                List<GasPollEmissionsVO> gasPollEmissionsVos = sRaOnlineEmissionsGasMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
                        monitoringStartTime.toString(), monitoringEndTime.toString(), gasImportantFields, null, pgSqlFormat);

                List<EChartsVO.SeriesObj> gasEmissionsSeries = getEmissionsSeries(items, gasPollEmissionsVos, timeRange, dateFormat, "groupByField");
                eChartsVO.setSeries(gasEmissionsSeries);
                return eChartsVO;
            case "2":
                // 废水没有消失数据，这里展示当天的日数据
                if (StringUtils.equals("D", dataType)) {
                    return emissionTrends(factoryId, selectType, "M", null, null);

                }
                items = new ArrayList<>();
                items.add(new HashMap<String, String>() {{
                    put("name", "COD浓度");
                    put("prop", "codConcentration");
                    put("unit", "kg");
                }});
                items.add(new HashMap<String, String>() {{
                    put("name", "氨氮");
                    put("prop", "ammoniaNitrogen");
                    put("unit", "kg");
                }});
                items.add(new HashMap<String, String>() {{
                    put("name", "总氮");
                    put("prop", "nitrogenConcentration");
                    put("unit", "kg");
                }});
                items.add(new HashMap<String, String>() {{
                    put("name", "总磷");
                    put("prop", "phosphorusConcentration");
                    put("unit", "kg");
                }});
                final String[] waterImportantFields = emissionsConstants.getWaterImportantFieldMap().keySet().toArray(new String[0]);
                List<WaterPollEmissionsVO> waterPollEmissionsVos = sRaOnlineEmissionsWaterMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
                        monitoringStartTime.toString(), monitoringEndTime.toString(), waterImportantFields, null, pgSqlFormat);
                List<EChartsVO.SeriesObj> waterEmissionsSeries = getEmissionsSeries(items, waterPollEmissionsVos, timeRange, dateFormat, "groupByField");
                eChartsVO.setSeries(waterEmissionsSeries);
                return eChartsVO;
            // 适配 企业档案-在线监控-产品产量
            case "3":
                return selectEnterpriseMapPopYield(factoryId, dataType, monitoringStartTime.toString(), monitoringEndTime.toString());
            default:
                return emissionTrends(factoryId, "1", dataType, startTime, endTime);
        }
    }

    /**
     * 对列表中的某个字段的数据，分成固定份数
     *
     * @param partitionCount 固定份数
     * @param field          字段名称
     * @param emissions      列表数据
     * @return key为起始值，value为结束值，ex：["10-66", "66-122", "122-178", "178-234", "234-290", "290-346", "346-402", "402-458", "458-514",…]
     */
    public Stream<AbstractMap.SimpleEntry<BigDecimal, BigDecimal>> getGroupedStream(int partitionCount, String field, List<?> emissions) {
        BigDecimal maxEmissions = emissions.stream().map(x -> new BigDecimal(BeanUtil.getFieldValue(x, field).toString())).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO).setScale(0, RoundingMode.UP);
        BigDecimal minEmissions = emissions.stream().map(x -> new BigDecimal(BeanUtil.getFieldValue(x, field).toString())).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO).setScale(0, RoundingMode.DOWN);

        BigDecimal range = maxEmissions.subtract(minEmissions);
        BigDecimal partitionSize = range.divide(new BigDecimal(partitionCount), 0, RoundingMode.HALF_UP);

        if (range.compareTo(BigDecimal.ZERO) == 0 || partitionSize.compareTo(BigDecimal.ZERO) == 0) {
            return null;
        }

        return IntStream.range(0, partitionCount)
                .mapToObj(i -> {
                    BigDecimal start = minEmissions.add(partitionSize.multiply(new BigDecimal(i)));
                    BigDecimal end = start.add(partitionSize);
                    if (i == partitionCount - 1) {
                        end = maxEmissions;
                    }
                    return new AbstractMap.SimpleEntry<>(start, end);
                });
    }

    /**
     * 对列表的数据通过区间 获取企业数量
     *
     * @param emissions     列表的数据
     * @param field         字段名称
     * @param groupedStream getGroupedStream方法获取的区间Stream
     * @return 每个区间的企业数量 ex: [1, 1, 1, 0, 1, 0, 0, 0, 0, 1]
     */
    public List<Long> getCountGroupByPartitionCount(List<?> emissions, String field, Stream<AbstractMap.SimpleEntry<BigDecimal, BigDecimal>> groupedStream) {

        return groupedStream == null ? Collections.emptyList() : groupedStream
                .map(entry -> {
                    BigDecimal start = entry.getKey();
                    BigDecimal end = entry.getValue();
                    return emissions.stream()
                            .map(x -> new BigDecimal(BeanUtil.getFieldValue(x, field).toString()))
                            .filter(value -> value.compareTo(start) >= 0 && value.compareTo(end) <= 0)
                            .count();
                })
                .collect(Collectors.toList());
    }

    public List<EChartsVO.SeriesObj> getEmissionsSeries(List<Map<String, String>> items, List<?> data, List<DateTime> timeRange, String dateFormat, String timeField) {
        return items.parallelStream().map(item -> {
            EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
            ser.setName(item.getOrDefault("name", ""));
            ser.setUnit(item.getOrDefault("unit", ""));
//            List<Object> values = Lists.newArrayListWithCapacity(timeRange.size());
            Object[] values = new Object[timeRange.size()];
            data.forEach(x -> {
                BigDecimal prop = BeanUtil.getProperty(x, item.get("prop"));
                Object value = Objects.isNull(prop) ? null : prop.setScale(4, RoundingMode.HALF_UP);
                DateTime dateTime = DateUtil.parse(BeanUtil.getProperty(x, timeField), dateFormat);

                values[CollUtil.indexOf(timeRange, y -> DateUtil.compare(y, dateTime, dateFormat) == 0)] = value;
            });
            ser.setValues(Arrays.asList(values));
            return ser;
        }).collect(Collectors.toList());

    }


    /**
     * 根据传入的缓存名称删除对应的缓存
     *
     * @param redisKey
     * @return
     */
    @Override
    public Boolean cleanRedisByCacheNames(String redisKey) {
        //组装模糊删除key所需格式
        String fuzzyRedisKey = redisKey+"::*";
        return RedisUtils.delKeysByPattern(redisTemplate, fuzzyRedisKey);
    }

    @Override
    public OverviewOnlineMonitorsVo overviewOnlineMonitors() {
        String regionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> rs = baseRegionService.getRegionCodeListChild(regionCode);
        if(rs.getCode()==200){
            regionCodes=rs.getData();
        }
        return pcFactoryMapper.overviewOnlineMonitors(regionCodes);
    }

    @Override
    public EChartsVO monitoringPointWarning(String type) {
        String regionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> rs = baseRegionService.getRegionCodeListChild(regionCode);
        if(rs.getCode()==200){
            regionCodes=rs.getData();
        }
        MonitoringPointWarningVo ma=new MonitoringPointWarningVo();
        if(type.equals("1")){
            ma= pcFactoryMapper.gasMonitoringPointWarning(regionCodes);
        }else {
            ma= pcFactoryMapper.waterMonitoringPointWarning(regionCodes);
        }
        EChartsVO eChartsVO=new EChartsVO();
        List<EChartsVO.SeriesObj> items= new ArrayList<>();
        EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
        ser.setName("预警");
        ser.setValues(new ArrayList<>());
        items.add(ser);
        EChartsVO.SeriesObj ser1 = new EChartsVO.SeriesObj();
        ser1.setName("报警");
        ser1.setValues(new ArrayList<>());
        items.add(ser1);
        EChartsVO.SeriesObj ser2 = new EChartsVO.SeriesObj();
        ser2.setName("异常");
        ser2.setValues(new ArrayList<>());
        items.add(ser2);
        items.get(0).getValues().add(ma.getGasMonitoringWarning());
        items.get(1).getValues().add(ma.getGasMonitoringExceeding());
        items.get(2).getValues().add(ma.getGasMonitoringAbnormal());
        eChartsVO.setSeries(items);
        return eChartsVO;
    }

    @Override
    public IPage<MonitoringPointWarningDetailsVo> monitoringPointWarningDetails(MonitoringPointWarningDetailsQuery query) {
        String regionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> rs = baseRegionService.getRegionCodeListChild(regionCode);
        if(rs.getCode()==200){
            regionCodes=rs.getData();
        }
        Page<MonitoringPointWarningDetailsVo> page=new Page<>(query.getPageNum(),query.getPageSize());
        List<MonitoringPointWarningDetailsVo> list=pcFactoryMapper.monitoringPointWarningDetails(page,regionCodes);
        page.setRecords(list);
        return page;
    }

    @Override
    public List<MonitoringPointWarningDetailsVo> exportMonitoringPointWarningDetails(MonitoringPointWarningDetailsQuery query) {
        String regionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> rs = baseRegionService.getRegionCodeListChild(regionCode);
        if(rs.getCode()==200){
            regionCodes=rs.getData();
        }
        Page<MonitoringPointWarningDetailsVo> page=new Page<>(query.getPageNum(),query.getPageSize());
        List<MonitoringPointWarningDetailsVo> list=pcFactoryMapper.monitoringPointWarningDetails(page, regionCodes);
        return list;
    }

    @Override
    public List<EnterpriseIssuesTopVo> enterpriseIssuesTop() {
        String regionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> rs = baseRegionService.getRegionCodeListChild(regionCode);
        if(rs.getCode()==200){
            regionCodes=rs.getData();
        }
        return pcFactoryMapper.enterpriseIssuesTop(regionCodes);
    }

    @Override
    public EChartsVO effectiveMonitoringRate(EffectiveMonitoringRateQuery query) {
        String regionCode = "";
        if(StringUtils.isEmpty(query.getRegionCode())){
            regionCode=SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        }else {
            regionCode=query.getRegionCode();
        }
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> rs = baseRegionService.getRegionCodeListChild(regionCode);
        if(rs.getCode()==200){
            regionCodes=rs.getData();
        }
        query.setRegionCodes(regionCodes);
        if(query.getType().equals("1")){
            List<String> allHour = DateUtils.getRangeTimes("H", query.getMonitoringStartTime(), query.getMonitoringEndTime());
            //缓存
            List<SEnvGasMonReal> sEnvGasMonReals=new ArrayList<>();
            AtomicLong atomicLong=new AtomicLong(0);
            String finalRegionCode = regionCode;
            allHour.forEach(item->{
                atomicLong.set(atomicLong.incrementAndGet());
                query.setMonitoringTime(item+":00:00");
                SEnvGasMonReal cacheObject = redisService.getCacheObject("effectiveMonitoringRateGas::"+ finalRegionCode + item);
                if(ObjectUtil.isNull(cacheObject)){
                    SEnvGasMonReal sEnvGasMonReal=pcFactoryMapper.gasEffectiveMonitoringRates(query);
                    redisService.setCacheObject("effectiveMonitoringRateGas::"+ finalRegionCode +item,sEnvGasMonReal,atomicLong.get(), TimeUnit.HOURS);
                    if(ObjectUtil.isNotNull(sEnvGasMonReal)){
                        sEnvGasMonReals.add(sEnvGasMonReal);
                    }
                }else {
                    if(ObjectUtil.isNotNull(cacheObject)){
                        sEnvGasMonReals.add(cacheObject);
                    }
                }
            });
//            List<SEnvGasMonReal> sEnvGasMonReals=pcFactoryMapper.gasEffectiveMonitoringRate(query);
            // x轴数据
            List<String> xdata = DateUtils.getRangeTimes(query.getDataType(), query.getMonitoringStartTime(), query.getMonitoringEndTime());

            // 以日期为key,转为map 日期格式要保证与x轴格式一样
            Map<String, SEnvGasMonReal> gasMonRealMap = sEnvGasMonReals.stream().collect(Collectors.toMap(o -> {
                        Date date = DateUtils.parseDate(o.getMonitoringTime());
                        o.setDataType(query.getDataType());
                        if (TimeTypeEnum.MONTH.getCode().equals(o.getDataType())) {
                            return DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", date);
                        } else if (TimeTypeEnum.HOUR.getCode().equals(o.getDataType())) {
                            return DateUtils.parseDateToStr("yyyy-MM-dd HH", date);
                        } else {
                            return DateUtils.parseDateToStr("yyyy-MM-dd", date);
                        }
                    }, o -> o,
                    // TODO 数据问题导致存在key相同的，暂取第一条
                    (o1, o2) -> o1));

        /*
            将查询到的监测数据转为曲线图要求的格式
         */
            List<EChartsVO.SeriesObj> series = new ArrayList<>();
                String str = "so2Emission,noxEmission,pmEmission,vocsEmission";
                List<String> list = Arrays.stream(str.split(",")).collect(Collectors.toList());
                for (SEnvGasMonRealServiceImpl.PollutantEnum pollutantEnum : SEnvGasMonRealServiceImpl.PollutantEnum.values()) {
                    if(list.contains(pollutantEnum.prop)){
                        EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
                        ser.setName(pollutantEnum.label);
                        ser.setUnit(pollutantEnum.unit);
                        ser.setProp(pollutantEnum.prop);

                        // 遍历x轴数据，保证x轴与系列数据一一对应
                        List<Object> values = xdata.stream().map(o -> {
                            SEnvGasMonReal monReal = gasMonRealMap.get(o);
                            if (monReal == null) {
                                return null;
                            }
                            return BeanUtil.getProperty(monReal, ser.getProp());
                        }).collect(Collectors.toList());
                        ser.setValues(values);
                        series.add(ser);
                    }
                }
            EChartsVO chartsVO = new EChartsVO();
            chartsVO.setXData(xdata);
            chartsVO.setSeries(series);
            return chartsVO;
        }else {
            List<String> allHour = DateUtils.getRangeTimes("H", query.getMonitoringStartTime(), query.getMonitoringEndTime());
            //缓存
            List<SEnvWaterMonReal> waterMonReals=new ArrayList<>();
            AtomicLong atomicLong=new AtomicLong(0);
            String finalRegionCode1 = regionCode;
            allHour.forEach(item->{
                atomicLong.set(atomicLong.incrementAndGet());
                query.setMonitoringTime(item+":00:00");
                SEnvWaterMonReal cacheObject = redisService.getCacheObject("effectiveMonitoringRateWater::"+ finalRegionCode1 +item);
                if(ObjectUtil.isNull(cacheObject)){
                    SEnvWaterMonReal SEnvWaterMonReal=pcFactoryMapper.effectiveMonitoringRates(query);
                    redisService.setCacheObject("effectiveMonitoringRateWater::"+ finalRegionCode1 +item,SEnvWaterMonReal,atomicLong.get(), TimeUnit.HOURS);
                    if(ObjectUtil.isNotNull(SEnvWaterMonReal)){
                        waterMonReals.add(SEnvWaterMonReal);
                    }
                }else {
                    if(ObjectUtil.isNotNull(cacheObject)){
                        waterMonReals.add(cacheObject);
                    }
                }
            });

//            List<SEnvWaterMonReal> waterMonReals=pcFactoryMapper.effectiveMonitoringRate(query);
            // x轴数据
            List<String> xdata = DateUtils.getRangeTimes(query.getDataType(), query.getMonitoringStartTime(), query.getMonitoringEndTime());

            // 以日期为key,转为map 日期格式要保证与x轴格式一样
            Map<String, SEnvWaterMonReal> waterMonRealMap = waterMonReals.stream().collect(Collectors.toMap(o -> {
                        Date date = DateUtils.parseDate(o.getMonitoringTime());
                        o.setDataType(query.getDataType());
                        if (TimeTypeEnum.MONTH.getCode().equals(o.getDataType())) {
                            return DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", date);
                        } else if (TimeTypeEnum.HOUR.getCode().equals(o.getDataType())) {
                            return DateUtils.parseDateToStr("yyyy-MM-dd HH", date);
                        } else {
                            return DateUtils.parseDateToStr("yyyy-MM-dd", date);
                        }
                    }, o -> o,
                    // TODO 数据问题导致存在key相同的，暂取第一条
                    (o1, o2) -> o1));

            /*
                将查询到的监测数据转为曲线图要求的格式
             */
            // 系列
            List<EChartsVO.SeriesObj> series = new ArrayList<>();
                String str = "codEmission,ammoniaNitrogenEmission,nitrogenConcentrationEmission,phosphorusConcentrationEmission";
                List<String> list = Arrays.stream(str.split(",")).collect(Collectors.toList());
                for (SEnvWaterMonRealServiceImpl.PollutantEnumEmission pollutantEnum : SEnvWaterMonRealServiceImpl.PollutantEnumEmission.values()) {
                    if(list.contains(pollutantEnum.prop)) {
                        EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
                        ser.setName(pollutantEnum.label);
                        ser.setUnit(pollutantEnum.unit);
                        ser.setProp(pollutantEnum.prop);

                        // 遍历x轴数据，保证x轴与系列数据一一对应
                        List<Object> values = xdata.stream().map(o -> {
                            SEnvWaterMonReal monReal = waterMonRealMap.get(o);
                            if (monReal == null) {
                                return null;
                            }
                            return BeanUtil.getProperty(monReal, ser.getProp());
                        }).collect(Collectors.toList());
                        ser.setValues(values);
                        series.add(ser);
                    }
                }
                EChartsVO chartsVO = new EChartsVO();
                chartsVO.setXData(xdata);
                chartsVO.setSeries(series);
                return chartsVO;
            }
    }

    @Override
    public List<RegionalOnlineMonitoringVo> regionalOnlineMonitoring(EffectiveMonitoringRateQuery query) {
        String regionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> rs = baseRegionService.getRegionCodeListChild(regionCode);
        if(rs.getCode()==200){
            regionCodes=rs.getData();
        }
        query.setRegionCodes(regionCodes);
        List<SysBasRegion> regionArr=new ArrayList<>();
        R<List<SysBasRegion>> r = baseRegionService.getRegionList(regionCode);
        if(r.getCode()==200){
            regionArr=r.getData();
        }
        //封装数据
        List<RegionalOnlineMonitoringVo> regionalOnlineMonitoringVos=new ArrayList<>();
        regionArr.forEach(item->{
            RegionalOnlineMonitoringVo chil=new RegionalOnlineMonitoringVo();
            chil.setRegionName(item.getRegionName());
            chil.setDistrictCode(item.getRegionCode());
            regionalOnlineMonitoringVos.add(chil);
        });
        //监测点位数量
       List<RegionalOnlineMonitoringVo> numberMonitors= pcFactoryMapper.numberMonitoringPoints(query);
        //有效监测率
        List<RegionalOnlineMonitoringVo> monitoringRates= pcFactoryMapper.monitoringRate(query);
        monitoringRates.forEach(item->{
                if ((BigDecimal.ZERO).compareTo(item.getTotal()) != 0 ) {
                    item.setMonitoringRate(item.getDivisor().divide(item.getTotal(), 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString() + "%");
                }
        });
        //超标率
        List<RegionalOnlineMonitoringVo> excessRates= pcFactoryMapper.excessRate(query);
        excessRates.forEach(item->{
                if ((BigDecimal.ZERO).compareTo(item.getTotal()) != 0 ) {
                    item.setExcessRate(item.getDivisor().divide(item.getTotal(),2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString()+"%");
                }
        });
        Map<String, RegionalOnlineMonitoringVo> numberMonitorsMap = numberMonitors.stream().collect(Collectors.toMap(RegionalOnlineMonitoringVo::getDistrictCode, a -> a,(k1, k2)->k1));
        Map<String, RegionalOnlineMonitoringVo> monitoringRatesMap = monitoringRates.stream().collect(Collectors.toMap(RegionalOnlineMonitoringVo::getDistrictCode, a -> a,(k1, k2)->k1));
        Map<String, RegionalOnlineMonitoringVo> excessRatesMap = excessRates.stream().collect(Collectors.toMap(RegionalOnlineMonitoringVo::getDistrictCode, a -> a,(k1, k2)->k1));
        regionalOnlineMonitoringVos.forEach(item->{
            if(numberMonitorsMap.containsKey(item.getDistrictCode())){
                item.setNumberMonitoringPoints(numberMonitorsMap.get(item.getDistrictCode()).getNumberMonitoringPoints());
            }else {
                item.setNumberMonitoringPoints("0");
            }
            if(monitoringRatesMap.containsKey(item.getDistrictCode())){
                item.setMonitoringRate(monitoringRatesMap.get(item.getDistrictCode()).getMonitoringRate());
            }else {
                item.setMonitoringRate("0%");
            }
            if(excessRatesMap.containsKey(item.getDistrictCode())){
                item.setExcessRate(excessRatesMap.get(item.getDistrictCode()).getExcessRate());
            }else {
                item.setExcessRate("0%");
            }
        });
        return regionalOnlineMonitoringVos;
    }

    /**
     * 数据类型 1：DCS监控数据:，2：分表计电监测数据，3：在线监测数据，4：无组织监控数据:5：网格化监控数据，6：废水国省控站点监控数据，7：废气国省控站点监控数据
     * @param paramKeys
     * @return
     */
    @Transactional
    public Boolean initializeBasDeviceParamAll(String[] paramKeys) {
        Date startDate  = new Date();
        log.info("初始化bas_device_param任务开始++++++++++++++++++++++++++++++++++++++++++="+startDate);
        //第一步 获取所有企业
        List<PcFactory> factoryList =  pcFactoryMapper.selectPcFactory();
        /*ExecutorService taskExecutor = Executors.newCachedThreadPool();
        ExecutorService pool = Executors.newFixedThreadPool(50);
        final CountDownLatch latch = new CountDownLatch(factoryList.size());//用于判断所有的线程是否结束*/
        //第二步 循环企业
        //第三步 循环类型 获取 企业是否包含此类型数据
        //第四不 获取各类型数据的参数值
        //第五步 根据获取的参数组装list 存到数据库中，对已有的数据做更新操作，不改变后边设置的值。对位存在的数据做插入操作，对多余的数据做标记操作（修改状态）。
        for (PcFactory pcFactory:factoryList) {
           /* Runnable run = new Runnable() {
                public void run() {
                    try {*/
                         for(String paramKey:paramKeys){
                             switch (paramKey) {
                                 case "2":
                                     findOrInsertEL(pcFactory.getId(),"A002",paramKey);
                                     //分表计电监测设备
                                     break;
                                 case "3":
                                     findOrInsertOnLine(pcFactory.getId(),"A003",paramKey);
                                     break;
                                    //在线监测设备
                                 case "4":
                                     //无组织监控数据
                                     findOrInsertInorganization(pcFactory.getId(),"A004",paramKey);
                                 default:
                                     break;
                             }
                        }
                    /* } finally {
                        latch.countDown(); //每次调用CountDown()，计数减1
                    }
                }
            };
            taskExecutor.execute(run);*///开启线程执行池中的任务。还有一个方法submit也可以做到，它的功能是提交指定的任务去执行并且返回Future对象，即执行的结果
        }

/*        try {
            //等待所有线程执行完毕
            latch.await();//主程序执行到await()函数会阻塞等待线程的执行，直到计数为0
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        taskExecutor.shutdown();//关闭线程池*/
        log.info("初始化bas_device_param任务结束++++++++++++++++++++++++++++++++++++++++++="+((new Date()).getTime()-startDate.getTime()));
        return false;
    }
    @Autowired
    private PcAdslFactoryMapper pcAdslFactoryMapper;
    @Autowired
    private BasDeviceSiteMapper basDeviceSiteMapper;
    @Autowired
    private BasDeviceParamAnalyseMapper basDeviceParamAnalyseMapper;
    @Autowired
    private BasDeviceParamMapper basDeviceParamMapper;
    @Autowired
    private PcOutletMapper pcOutletMapper;
    public void findOrInsertEL(String factoryId,String paramKey,String datetype){
        //查询企业是否接入分表计电，如果是 则获取分表计电设备
        PcAdslFactory pc = new PcAdslFactory();
        pc.setFactoryId(factoryId);
        pc.setAdslCode(paramKey);
        List<PcAdslFactory> pcAdslFactory = pcAdslFactoryMapper.selectPcAdslFactoryList(pc);
        if(pcAdslFactory.size()>0){
            //获取点位信息
            List<BasDeviceSite>  bdsList = basDeviceSiteMapper.selectDevicePoints(factoryId);
            log.info("分表计电----企业id++++++"+factoryId+":=====返回list"+bdsList);
            //获取参数信息
            QueryWrapper<BasDeviceParamAnalyse> queryWrapper = new QueryWrapper<BasDeviceParamAnalyse>();
            queryWrapper.eq("data_type", datetype);
            List<BasDeviceParamAnalyse> bdpaList = basDeviceParamAnalyseMapper.selectList(queryWrapper);
            //组装List
            if(bdsList.size()>0){
                List<BasDeviceParam> oldbsold = new ArrayList<>();
                List<BasDeviceParam> newbdpone = new ArrayList<>();
                for(BasDeviceSite bs:bdsList ){
                    //第一步 先将企业所有的参数置为未启用状态
                    basDeviceParamMapper.updateValueParam(bs.getDeviceId(),datetype,"EL","0");
                    //第二步 处理企业信息
                    if(bdpaList.size()>0){
                        for(BasDeviceParamAnalyse bdp:bdpaList){
                            BasDeviceParam bsold = basDeviceParamMapper.selectBasDeviceParam(datetype,"EL",bdp.getDeviceParamCode());
                            if(bsold!=null){
                                bsold.setIsStatus(bdp.getIsStatus());
                                oldbsold.add(bsold);
                                basDeviceParamMapper.updateById(bsold);
                            }else{
                                BasDeviceParam  bdpone = new BasDeviceParam();
                                bdpone.setDataType(datetype); //设置数据类型
                                bdpone.setIndustry("EL");//设置行业
                                bdpone.setParamId(bdp.getDeviceParamCode());//设置参数编码字段
                                bdpone.setParamName(bdp.getDeviceParamName());//设置参数名称
                                bdpone.setParamUnit(bdp.getDeviceParamUnit());//设置参数单位
                                bdpone.setIsStatus(bdp.getIsStatus());//设置参数是否启用
                                bdpone.setDeviceId(bs.getDeviceId());//设置设备id
                                bdpone.setDeviceSiteId(bs.getId());//设置分表计电监测点id
                                bdpone.setIsOnline(1L);
                                bdpone.setCreateTime(new Date());
                                bdpone.setDeviceType("1");
                                bdpone.setFacilityType("1");
                                bdpone.setMultiNum(1L);
                                bdpone.setStandbyNum(1L);
                                newbdpone.add(bdpone);
                                basDeviceParamMapper.insert(bdpone);
                            }
                        }
                    }
                }
                log.info("分表计电----企业id++++++"+factoryId+":=====修改条数"+oldbsold+":=====新增条数"+newbdpone);
                /*if(oldbsold.size()>0){
                    basDeviceParamMapper.updateByIdList(oldbsold);
                }
                if(newbdpone.size()>0){
                    basDeviceParamMapper.batchInsert(newbdpone);
                }*/
            }
        }
    }
    public void findOrInsertOnLine(String factoryId,String paramKey,String datetype){
        //查询企业是否接入分表计电，如果是 则获取分表计电设备
        PcAdslFactory pc = new PcAdslFactory();
        pc.setFactoryId(factoryId);
        pc.setAdslCode(paramKey);
        List<PcAdslFactory> pcAdslFactory = pcAdslFactoryMapper.selectPcAdslFactoryList(pc);
        if(pcAdslFactory.size()>0){
            //获取点位信息
            List<PcOutlet>  bdsList = pcOutletMapper.selectOnLinePoints(factoryId,"4");
            log.info("在线监测----企业id++++++"+factoryId+":=====返回list"+bdsList);
            //获取参数信息
            QueryWrapper<BasDeviceParamAnalyse> queryWrapper = new QueryWrapper<BasDeviceParamAnalyse>();
            queryWrapper.eq("data_type", datetype);
            List<BasDeviceParamAnalyse> bdpaList = basDeviceParamAnalyseMapper.selectList(queryWrapper);
            String deviceType = "AIR";
            //组装List
            if(bdsList.size()>0){
                List<BasDeviceParam> oldbsold = new ArrayList<>();
                List<BasDeviceParam> newbdpone = new ArrayList<>();
                for(PcOutlet bs:bdsList ){
                    if("2".equals(bs.getPollutantOutletType())){
                        deviceType = "WATER";
                    }
                    //第一步 先将企业所有的参数置为未启用状态
                    basDeviceParamMapper.updateValueParam(bs.getOutletCode(),datetype,deviceType,"0");
                    //第二步 处理企业信息
                    if(bdpaList.size()>0){
                        for(BasDeviceParamAnalyse bdp:bdpaList){
                            BasDeviceParam bsold = basDeviceParamMapper.selectBasDeviceParam(datetype,deviceType,bdp.getDeviceParamCode());
                            if(bsold!=null){
                                bsold.setIsStatus(bdp.getIsStatus());
                                basDeviceParamMapper.updateById(bsold);
                                oldbsold.add(bsold);
                            }else{
                                BasDeviceParam  bdpone = new BasDeviceParam();
                                bdpone.setDataType(datetype); //设置数据类型
                                bdpone.setIndustry(deviceType);//设置行业
                                bdpone.setParamId(bdp.getDeviceParamCode());//设置参数编码字段
                                bdpone.setParamName(bdp.getDeviceParamName());//设置参数名称
                                bdpone.setParamUnit(bdp.getDeviceParamUnit());//设置参数单位
                                bdpone.setIsStatus(bdp.getIsStatus());//设置参数是否启用
                                bdpone.setDeviceId(bs.getOutletCode());//设置设备id
                                bdpone.setDeviceSiteId(bs.getId());//设置分表计电监测点id
                                bdpone.setIsOnline(1L);
                                bdpone.setCreateTime(new Date());
                                bdpone.setDeviceType("1");
                                bdpone.setFacilityType("1");
                                bdpone.setMultiNum(1L);
                                bdpone.setStandbyNum(1L);
                                basDeviceParamMapper.insert(bdpone);
                                newbdpone.add(bdpone);
                            }
                        }
                    }
                }
                log.info("在线监测----企业id++++++"+factoryId+":=====修改条数"+oldbsold+":=====新增条数"+newbdpone);
               /* if(oldbsold.size()>0){
                    basDeviceParamMapper.updateByIdList(oldbsold);
                }
                if(newbdpone.size()>0){
                    basDeviceParamMapper.batchInsert(newbdpone);
                }*/
            }
        }
    }
    public void findOrInsertInorganization(String factoryId,String paramKey,String datetype){
        //查询企业是否接入分表计电，如果是 则获取分表计电设备
        PcAdslFactory pc = new PcAdslFactory();
        pc.setFactoryId(factoryId);
        pc.setAdslCode(paramKey);
        List<PcAdslFactory> pcAdslFactory = pcAdslFactoryMapper.selectPcAdslFactoryList(pc);
        if(pcAdslFactory.size()>0){
            //获取点位信息
            List<PcOutlet>  bdsList = pcOutletMapper.selectOnLinePoints(factoryId,"3");
            log.info("无组织----企业id++++++"+factoryId+":=====返回list"+bdsList);
            //获取参数信息
            QueryWrapper<BasDeviceParamAnalyse> queryWrapper = new QueryWrapper<BasDeviceParamAnalyse>();
            queryWrapper.eq("data_type", datetype);
            List<BasDeviceParamAnalyse> bdpaList = basDeviceParamAnalyseMapper.selectList(queryWrapper);
            //组装List
            if(bdsList.size()>0){
                List<BasDeviceParam> oldbsold = new ArrayList<>();
                List<BasDeviceParam> newbdpone = new ArrayList<>();
                for(PcOutlet bs:bdsList ){
                    //第一步 先将企业所有的参数置为未启用状态
                    basDeviceParamMapper.updateValueParam(bs.getOutletCode(),datetype,"INORG","0");
                    //第二步 处理企业信息
                    if(bdpaList.size()>0){
                        for(BasDeviceParamAnalyse bdp:bdpaList){
                            BasDeviceParam bsold = basDeviceParamMapper.selectBasDeviceParam(datetype,"INORG",bdp.getDeviceParamCode());
                            if(bsold!=null){
                                bsold.setIsStatus(bdp.getIsStatus());
                                basDeviceParamMapper.updateById(bsold);
                                oldbsold.add(bsold);
                            }else{
                                BasDeviceParam  bdpone = new BasDeviceParam();
                                bdpone.setDataType(datetype); //设置数据类型
                                bdpone.setIndustry("INORG");//设置行业
                                bdpone.setParamId(bdp.getDeviceParamCode());//设置参数编码字段
                                bdpone.setParamName(bdp.getDeviceParamName());//设置参数名称
                                bdpone.setParamUnit(bdp.getDeviceParamUnit());//设置参数单位
                                bdpone.setIsStatus(bdp.getIsStatus());//设置参数是否启用
                                bdpone.setDeviceId(bs.getOutletCode());//设置设备id
                                bdpone.setDeviceSiteId(bs.getId());//设置分表计电监测点id
                                bdpone.setIsOnline(1L);
                                bdpone.setCreateTime(new Date());
                                bdpone.setDeviceType("1");
                                bdpone.setFacilityType("1");
                                bdpone.setMultiNum(1L);
                                bdpone.setStandbyNum(1L);
                                basDeviceParamMapper.insert(bdpone);
                                newbdpone.add(bdpone);
                            }
                        }
                    }
                }
                log.info("无组织---企业id++++++"+factoryId+":=====修改条数"+oldbsold+":=====新增条数"+newbdpone);
                /*if(oldbsold.size()>0){
                    basDeviceParamMapper.updateByIdList(oldbsold);
                }
                if(newbdpone.size()>0){
                    basDeviceParamMapper.batchInsert(newbdpone);
                }*/
            }
        }
    }

	@Override
	public List<HpmEmissionTrackingMonVo> getEmissionTrackingMon(String factoryId, String monitoringPointId, String startTime,
			String endTime) {
		List<HpmEmissionTrackingMonVo> datas = new ArrayList<>();
		HpmEmissionTrackingMonVo hetmv = new HpmEmissionTrackingMonVo();
		final String format, dateFormat, pgSqlDateFormat;
        DateTime monitoringStartTime, monitoringEndTime;
        // 月
        format = "yyyy-MM";
        dateFormat = "yyyy-MM-dd";
        pgSqlDateFormat = "YYYY-MM";
        DateTime parseMonth = DateUtil.parse(endTime, format);
        monitoringEndTime = DateUtil.compare(parseMonth, new Date(), format) == 0 ? new DateTime() : DateUtil.endOfMonth(parseMonth);
                
        monitoringStartTime = DateUtil.parse(startTime, format);
        List<DateTime> timeRange = DateUtil.rangeToList(monitoringStartTime, monitoringEndTime, DateField.DAY_OF_MONTH);
        final String pgSqlFormat = StringUtils.format("to_char(monitor_time, '{}')", pgSqlDateFormat);
        final String[] waterImportantFields = emissionsConstants.getWaterImportantFieldMap().keySet().toArray(new String[0]);
        final String[] gasImportantFields = emissionsConstants.getGasImportantFieldMap().keySet().toArray(new String[0]);
        
        List<GasPollEmissionsVO> gasPollEmissionsVos = new ArrayList<>(); 
        List<WaterPollEmissionsVO> waterPollEmissionsVos = new ArrayList<>(); 
		//判断是否查询全部
		if(StringUtils.isEmpty(monitoringPointId)){
			//查询全部
			gasPollEmissionsVos = sRaOnlineEmissionsGasMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
                    monitoringStartTime.toString(), monitoringEndTime.toString(), gasImportantFields, null, pgSqlFormat);
			
			waterPollEmissionsVos = sRaOnlineEmissionsWaterMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
					startTime.toString(), endTime.toString(), waterImportantFields, null, pgSqlFormat);

		} else {
			//判断monitoringPointId是gas or water
			PcOutlet pcOutlet = pcOutletMapper.selectById(monitoringPointId);
			if (PollutantTypeEnum.GAS.getCode().contentEquals(pcOutlet.getPollutantType())) {
				//gas
				gasPollEmissionsVos = sRaOnlineEmissionsGasMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
	                    monitoringStartTime.toString(), monitoringEndTime.toString(), gasImportantFields, null, pgSqlFormat);
			} else {
				//water
				waterPollEmissionsVos = sRaOnlineEmissionsWaterMapper.selectEmissionDataList(factoryId, pgSqlDateFormat,
						startTime.toString(), endTime.toString(), waterImportantFields, null, pgSqlFormat);
			}
		}
		datas = handleDatas(gasPollEmissionsVos ,waterPollEmissionsVos);
		
		return datas;
	}

    @Override
    public BMainEmissionAndstatusScaleVo selectEmissionAndstatusScale(String regionCode) {
        BMainEmissionAndstatusScaleVo bMainEmissionAndstatusScaleVo = new BMainEmissionAndstatusScaleVo();
        List<String> xData = Arrays.asList("0","0.2","0.4","0.6","0.8","1");
        bMainEmissionAndstatusScaleVo.setXData(xData);
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
        if(r.getCode()==200){
            regionCodes=r.getData();
        }
        //计算大气和废水数量
        BMainEmissionAndstatusCountVo bMainEmissionAndstatusCountVo = bMainPollDisSelfMonMapper.selectEmissionAndstatus(regionCodes);
        //大气
        BigDecimal atmosphere = bMainEmissionAndstatusCountVo.getAtmosphere();
        if(atmosphere.compareTo(new BigDecimal(0)) == 0){
            bMainEmissionAndstatusScaleVo.setActualDischargeAtmosphereScale(new BigDecimal(0));
            bMainEmissionAndstatusScaleVo.setPermissibleDischargeAtmosphereScale(new BigDecimal(0));
        }else{
            //自动监测大气占比
            BigDecimal actualDischargeAtmosphere = bMainEmissionAndstatusCountVo.getActualDischargeAtmosphere();
            BigDecimal actualDischargeAtmosphereScale = actualDischargeAtmosphere.divide(atmosphere,2,BigDecimal.ROUND_HALF_DOWN);
            bMainEmissionAndstatusScaleVo.setActualDischargeAtmosphereScale(actualDischargeAtmosphereScale);
            //手动监测大气占比
            BigDecimal permissibleDischargeAtmosphere = bMainEmissionAndstatusCountVo.getPermissibleDischargeAtmosphere();
            BigDecimal permissibleDischargeAtmosphereScale = permissibleDischargeAtmosphere.divide(atmosphere,2,BigDecimal.ROUND_HALF_DOWN);
            bMainEmissionAndstatusScaleVo.setPermissibleDischargeAtmosphereScale(permissibleDischargeAtmosphereScale);
        }
        //废水
        BigDecimal water = bMainEmissionAndstatusCountVo.getWater();
        if(water.compareTo(new BigDecimal(0)) == 0){
            bMainEmissionAndstatusScaleVo.setPermissibleDischargeWaterScale(new BigDecimal(0));
            bMainEmissionAndstatusScaleVo.setActualDischargeWaterScale(new BigDecimal(0));
        }else{
            //自动监测废水占比
            BigDecimal actualDischargeWater = bMainEmissionAndstatusCountVo.getActualDischargeWater();
            BigDecimal actualDischargeWaterScale = actualDischargeWater.divide(water,2,BigDecimal.ROUND_HALF_UP);
            bMainEmissionAndstatusScaleVo.setActualDischargeWaterScale(actualDischargeWaterScale);
            //手动监测废水占比
            BigDecimal permissibleDischargeWater = bMainEmissionAndstatusCountVo.getPermissibleDischargeWater();
            BigDecimal permissibleDischargeWaterScale = permissibleDischargeWater.divide(water,2,BigDecimal.ROUND_HALF_UP);
            bMainEmissionAndstatusScaleVo.setPermissibleDischargeWaterScale(permissibleDischargeWaterScale);
        }
        return bMainEmissionAndstatusScaleVo;
    }

    private List<HpmEmissionTrackingMonVo> handleDatas(List<GasPollEmissionsVO> gasList, List<WaterPollEmissionsVO> waterList){
		List<HpmEmissionTrackingMonVo> datas = new ArrayList<>();
		HpmEmissionTrackingMonVo hetmv = new HpmEmissionTrackingMonVo();
		if (!gasList.isEmpty()) {
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("SO₂");
			hetmv.setUnit("kg");
			hetmv.setXData(gasList.stream().map(GasPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(gasList.stream().map(GasPollEmissionsVO::getSo2Emissions).collect(Collectors.toList()));
			datas.add(hetmv);
			
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("NOx");
			hetmv.setUnit("kg");
			hetmv.setXData(gasList.stream().map(GasPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(gasList.stream().map(GasPollEmissionsVO::getNoxEmissions).collect(Collectors.toList()));
			datas.add(hetmv);
			
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("PM");
			hetmv.setUnit("kg");
			hetmv.setXData(gasList.stream().map(GasPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(gasList.stream().map(GasPollEmissionsVO::getPmEmissions).collect(Collectors.toList()));
			datas.add(hetmv);
			
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("VOCs");
			hetmv.setUnit("kg");
			hetmv.setXData(gasList.stream().map(GasPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(gasList.stream().map(GasPollEmissionsVO::getVocsEmissions).collect(Collectors.toList()));
			datas.add(hetmv);
		}
		if (!waterList.isEmpty()) {
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("COD");
			hetmv.setUnit("kg");
			hetmv.setXData(waterList.stream().map(WaterPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(waterList.stream().map(WaterPollEmissionsVO::getCodEmissions).collect(Collectors.toList()));
			datas.add(hetmv);
			
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("氨氮");
			hetmv.setUnit("kg");
			hetmv.setXData(waterList.stream().map(WaterPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(waterList.stream().map(WaterPollEmissionsVO::getAmmoniaNitrogenEmissions).collect(Collectors.toList()));
			datas.add(hetmv);
			
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("总氮");
			hetmv.setUnit("kg");
			hetmv.setXData(waterList.stream().map(WaterPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(waterList.stream().map(WaterPollEmissionsVO::getTotalNitrogenEmissions).collect(Collectors.toList()));
			datas.add(hetmv);
			
			hetmv = new HpmEmissionTrackingMonVo();
			hetmv.setName("总磷");
			hetmv.setUnit("kg");
			hetmv.setXData(waterList.stream().map(WaterPollEmissionsVO::getGroupByField).collect(Collectors.toList()));
			hetmv.setYData(waterList.stream().map(WaterPollEmissionsVO::getTotalPhosphorusEmissions).collect(Collectors.toList()));
			datas.add(hetmv);
		}
		return datas;
	}
}
