using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Filters;
using Siger.ApiDashboard.Result;
using Siger.ApiDashboard.Utilities;
using Siger.Middlelayer.CncRepository.Entities;
using Siger.Middlelayer.CncRepository.Repositories.Interface;
using Siger.Middlelayer.CncRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Dapper;
using Siger.Middlelayer.Dapper.SearchCondition;
using Siger.Middlelayer.Dapper.Utilities;
using Siger.Middlelayer.Dapper.Utilities.Machine;
using Siger.Middlelayer.Dapper.Utilities.Oee;
using Siger.Middlelayer.Dapper.Utilities.Slice;
using Siger.Middlelayer.DashboardRepository.Entities;
using Siger.Middlelayer.DashboardRepository.Repositories.Interface;
using Siger.Middlelayer.DashboardRepository.Response;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Redis.RedisEntities;
using Siger.Middlelayer.Redis.Repositories;
using Siger.Middlelayer.Redis.Utility;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Share.Models;
using Siger.Middlelayer.Share.Utilities;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.Dapper.ResultData;
using ResponseEfficiencyAnalysisInfo = Siger.Middlelayer.DashboardRepository.Response.ResponseEfficiencyAnalysisInfo;
using Siger.Middlelayer.QmsRepository.Repositories.Interface;
using System.Globalization;
using Siger.Middlelayer.Repository.Data.Tpm;
using MachineRepairStatus = Siger.Middlelayer.Common.ModuleEnum.MachineRepairStatus;
using Siger.Middlelayer.Repository.Entities;
using siger_project_dashboard_machine_group = Siger.Middlelayer.DashboardRepository.Entities.siger_project_dashboard_machine_group;
using IProductionBeatSetRepository = Siger.Middlelayer.CncRepository.Repositories.Interface.IProductionBeatSetRepository;

namespace Siger.ApiDashboard.Controllers
{
    [Route("dashboard/[controller]/[action]")]
    [ApiController]
    [NoTokenValidateFilter]
    public class DashboardShowController : ControllerBase
    {
        private readonly ISigerProjectRepository _projectRepository;
        private readonly IDashboardCombRepository _dashboardCombRepository;
        private readonly IDashboardCombPageRepository _dashboardCombPageRepository;
        private readonly IDashboardCombPageConditionRepository _combPageConditionRepository;
        private readonly IDashboardPagePatialRepository _pagePatialRepository;
        private readonly Middlelayer.CncRepository.Repositories.Interface.IProductPlanRepository _planRepository;
        private readonly IProductionTimeRepository _timeRepository;
     //   private readonly IProductionBeatSetRepository _productionReportRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISigerProjectMachineExtendRepository _machineExtendRepository;
        private readonly IMachineParamAlarmRepository _machineParamAlarmRepository;
        private readonly IProductionConfigRepository _productionConfigRepository;
        private readonly IProductionBeatSetRepository _beatSetRepository;
        private readonly IRepairRepository _repairRepository;
        private readonly ISigerProjectUserRepository _userRepository;
        private readonly Isiger_wms_stockRepository _stockRepository;
        private readonly ISigerTrSnTraceDetailsRepository _sigerTrSnTraceDetails;
        private readonly ISigerCheckItem _sigerCheckItem;
        private readonly ISigerProjectLevelSectionMachineRepository _levelSectionMachine;
        private readonly IQmsSensorParameterRepository _sensorParameter;
        private readonly ISigerProjectLevelSectionRepository _levelSection;
        private readonly IPlanTimeRepository _planTime;
        private readonly IPlanRepository _tpmplanRepository;
        private readonly IFaultTypeRepository _faultTypeRepository;
        private readonly ISparepartRepository _sparepartRepository;
        private readonly IPlanSignRepository _planSignRepository;
        private readonly ISigerProjectMachineTypeRepository _machineTypeRepository;
        private readonly IQmsSensorTypeRepository _sensorTypeRepository;
        private readonly IProductionTimeAllocationRepository _timeAllocationRepository;
        private readonly IDashboardMachineGroupRepository _machineGroupRepository;
        private readonly ISigerSystemConfigRepository _systemConfigRepository;
        private readonly ISigerProjectRestTypeRepository _restTypeRepository;
        private int _companyId;
        private int _projectId;

        /// <inheritdoc />
        public DashboardShowController(IDashboardCombRepository dashboardCombRepository, IDashboardCombPageRepository dashboardCombPageRepository,
            IDashboardCombPageConditionRepository combPageConditionRepository, IDashboardPagePatialRepository pagePatialRepository,
            Middlelayer.CncRepository.Repositories.Interface.IProductPlanRepository planRepository, IProductionTimeRepository timeRepository,
            IMachineParamAlarmRepository machineParamAlarmRepository, ISigerProjectMachineRepository machineRepository,
            IProductionConfigRepository productionConfigRepository, IProductionBeatSetRepository beatSetRepository, ISigerProjectRestTypeRepository restTypeRepository,
            ISigerProjectRepository projectRepository, IProductionTimeAllocationRepository timeAllocationRepository,
            IRepairRepository repairRepository, ISigerProjectUserRepository userRepository, Isiger_wms_stockRepository stockRepository, ISigerTrSnTraceDetailsRepository sigerTrSnTraceDetails,
            ISigerCheckItem sigerCheckItem, ISigerProjectLevelSectionMachineRepository levelSectionMachine, IQmsSensorParameterRepository sensorParameter, ISigerProjectLevelSectionRepository levelSection
            , IPlanTimeRepository planTime, IPlanRepository tpmplanRepository, IFaultTypeRepository faultTypeRepository, ISparepartRepository sparepartRepository, ISigerProjectMachineExtendRepository machineExtendRepository,
            IPlanSignRepository planSignRepository, ISigerProjectMachineTypeRepository machineTypeRepository, IQmsSensorTypeRepository sensorTypeRepository,
            IDashboardMachineGroupRepository machineGroupRepository, ISigerSystemConfigRepository systemConfigRepository)
        {
            _dashboardCombRepository = dashboardCombRepository;
            _dashboardCombPageRepository = dashboardCombPageRepository;
            _combPageConditionRepository = combPageConditionRepository;
            _pagePatialRepository = pagePatialRepository;

            _planRepository = planRepository;
          //  _productionReportRepository = productionReportRepository;
            _timeRepository = timeRepository;
            _machineParamAlarmRepository = machineParamAlarmRepository;
            _machineRepository = machineRepository;
            _productionConfigRepository = productionConfigRepository;
            _beatSetRepository = beatSetRepository;
            _timeAllocationRepository = timeAllocationRepository;
            _projectRepository = projectRepository;
            _restTypeRepository = restTypeRepository;
            _repairRepository = repairRepository;
            _userRepository = userRepository;
            _stockRepository = stockRepository;
            _sigerTrSnTraceDetails = sigerTrSnTraceDetails;
            _sigerCheckItem = sigerCheckItem;
            _levelSectionMachine = levelSectionMachine;
            _sensorParameter = sensorParameter;
            _levelSection = levelSection;
            _planTime = planTime;
            _tpmplanRepository = tpmplanRepository;
            _faultTypeRepository = faultTypeRepository;
            _sparepartRepository = sparepartRepository;
            _machineExtendRepository = machineExtendRepository;

            _planSignRepository = planSignRepository;

            _machineTypeRepository = machineTypeRepository;
            _sensorTypeRepository = sensorTypeRepository;

            _machineGroupRepository = machineGroupRepository;
            _systemConfigRepository = systemConfigRepository;
        }

        [HttpGet]
        public IActionResult GetAllComb()
        {
            var dataComs = _dashboardCombRepository
                .GetList(q => q.project_id == _projectId && q.status == (int)RowState.Valid)
                .OrderBy(q => q.id);

            return new ObjectResult(dataComs);
        }

        [HttpGet]
        public IActionResult GetAllCombPages(int id, int projectId)
        {
            var project = _projectRepository.Get(q => q.id == projectId && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(RequestEnum.ProjectNotFound);
            }

            var pages = _dashboardCombRepository.GetCombPages(id, projectId);
            if (!pages.Any())
            {
                throw new ServerException(500193);
            }
            var response = new List<ResponseGetAllCombPage>();

            foreach (var page in pages)
            {
                var combPage = _combPageConditionRepository.GetAllCombPage(page.page_code, page.id.ToStr());
                if (combPage != null)
                {
                    response.Add(new ResponseGetAllCombPage
                    {
                        condition = combPage.condition,
                        page_code = page.page_code,
                        id = page.id,
                        w = combPage.w,
                        x = combPage.x,
                        h = combPage.h,
                        y = combPage.y,
                        page_patial_code = combPage.page_patial_code,
                        page_patial_condition_code = combPage.page_patial_condition_code,
                        //组合页面得时长
                        cycle=page.cycle,
                        title=page.title
                    });
                }
            }

            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetPageDetails(string page_code, string page_id)
        {
            var pageId = page_id.ToInt();
            if (pageId == 0)
            {
                throw new ServerException(500195);
            }
            var conditions = _pagePatialRepository.GetList(q => q.page_code == page_code).ToList();
            var combPage = _dashboardCombPageRepository.Get(q => q.id == pageId);
            if (combPage == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var result = new PageDetailsResult
            {
                title = combPage.title,
                data = conditions
            };

            return result;
        }

        [HttpGet]
        public async Task<IActionResult> GetAllData(string patial_code, string page_id, int projectid, int page, int pagesize)
        {
            var data = _combPageConditionRepository.GetAllData(patial_code, page_id);
            if (data == null)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            var project = _projectRepository.Get(q => q.id == projectid && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(RequestEnum.ProjectNotFound);
            }

            _projectId = projectid;
            _companyId = project.companyid.ToInt();

            var machineIds = new List<int>(); // machineIds or sectionIds
            var machineId = 0;
            var sectionId = 0;
            var keyValues = new List<ResponseKeyValue>();
            var groups = new List<siger_project_dashboard_machine_group>();
            switch (data.type)
            {
                case 1:
                    break;
                case 2: //type=2时，条件是设备字符串
                case 7: //type=7时，条件是产线Id
                case 9:
                    if (!string.IsNullOrWhiteSpace(data.condition))
                    {
                        var conditions = data.condition.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var con in conditions)
                        {
                            int.TryParse(con, out var mahcineId);
                            machineIds.Add(mahcineId);
                        }
                    }
                    break;
                case 5:

                    break;
                case 6:
                    if (!string.IsNullOrWhiteSpace(data.condition))
                    {
                        var conditions = data.condition.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                        sectionId = conditions[conditions.Length - 1].ToInt();
                    }
                    break;
                case 8:
                    var sectionMachineId = data.condition.Split('-');
                    if (sectionMachineId.Length != 2)
                    {
                        throw new BadRequestException(RequestEnum.ParameterError);
                    }
                    sectionId = sectionMachineId[0].ToInt();
                    machineId = sectionMachineId[1].ToInt();
                    break;
                case 12: //type=12时，条件是产线上一级Id
                    if (!string.IsNullOrWhiteSpace(data.condition))
                    {
                        var conditions = data.condition.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var con in conditions)
                        {
                            int.TryParse(con, out var mahcineId);
                            machineIds.Add(mahcineId);
                        }
                    }
                    break;
                case 13: //265-266-267-268-269-270-271-272-273-274_早班|00:00:00 - 08:00:00;中班|08:00:00 - 16:00:00;晚班|16:00:00 - 23:59:59
                    if (!string.IsNullOrWhiteSpace(data.condition))
                    {
                        var conditions = data.condition.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
                        if (conditions.Length == 2)
                        {
                            var ids = conditions[0].Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                            foreach (var con in ids)
                            {
                                int.TryParse(con, out var mahcineId);
                                machineIds.Add(mahcineId);
                            }

                            var values = conditions[1].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                            foreach (var value in values)
                            {
                                var shift = value.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                                if (shift.Length == 2)
                                {
                                    keyValues.Add(new ResponseKeyValue(shift[0], shift[1]));
                                }
                            }
                        }
                    }
                    break;
                case 14:
                    if (!string.IsNullOrWhiteSpace(data.condition))
                    {
                        var conditions = data.condition.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                        var ids = conditions.Select(t => t.ToInt()).ToList();
                        groups = _machineGroupRepository.GetList(t => ids.Contains(t.id) && t.projectid == projectid &&
                            t.status == (int)RowState.Valid).OrderBy(q => q.group).ToList();
                    }
                    break;
            }
            var dtStartTime = DateTime.Parse(DateTime.Now.ToString(ParameterConstant.DateFromZero));
            var dtEndTime = DateTime.Parse(DateTime.Now.ToString(ParameterConstant.DateTimeFormat));
            var dtWeekStart = DateTime.Parse(DateTime.Now.AddDays(-7).ToString(ParameterConstant.DateFromZero));
            var dtNow = DateTime.Now;
            var monthTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM") + "-01 0:00:00");
            var dtLastDayEnd = DateTime.Parse(DateTime.Now.AddDays(-1).ToString(ParameterConstant.DateFromZero));
            var dtLastMonthEnd = DateTime.Parse(DateTime.Now.AddDays(-15).ToString(ParameterConstant.DateFromZero));

            var result = new DashBoardResult { code = patial_code };
            switch (patial_code)
            {
                case "dashboard1_1": //dashboard1_1 订单完成情况
                    result.data = await GetDashboard11ResultAsync();
                    break;
                case "dashboard1_2"://dashboard1_2 生产中的工单
                    result.data = GetDashboard12Result();
                    break;
                case "dashboard1_3"://dashboard1_3 本周OEE
                    result.data = await GetDashboard13ResultAsync(machineIds, dtWeekStart, dtEndTime);
                    break;
                case "dashboard1_4"://dashboard1_4 设备运行情况
                    result.data = await GetDashboard14ResultAsync(machineIds, dtWeekStart, dtEndTime);
                    break;
                case "dashboard1_5"://dashboard1_5 当天设备产量统计
                    result.data = await GetDashboard15ResultAsync(machineIds);
                    break;
                case "dashboard1_6"://dashboard1_6 本周产量统计
                    result.data = await GetDashboard16ResultAsync(machineIds);
                    break;
                case "dashboard2_1"://dashboard2_1 设备切片状态数据
                    result.data = await GetSliceSatesAsync(machineIds, dtWeekStart, dtLastDayEnd);
                    break;
                case "dashboard2_2"://dashboard2_2 同dashboard1_5
                    result.data = await GetDashboard15ResultAsync(machineIds);
                    break;
                case "dashboard2_3"://dashboard2_3
                    result.data = data.condition;
                    break;
                case "dashboard2_4"://dashboard2_4 同dashboard1_6
                    result.data = await GetDashboard16ResultAsync(machineIds);
                    break;
                case "machine_status_1": //设备状态列表
                    result.data = await GetMachineRunningStatusAsync(machineIds);
                    break;
                case "machine_status_list_1": //设备状态一览
                    result.data = await GetDashboardMachineRunningStateListResult(machineIds);
                    break;
                case "slice_status_1": //切片状态一览
                    result.data = await GetDashboardSliceStatusResultAsync(dtStartTime, dtEndTime, machineIds);
                    break;
                case "slice_1": //切片数据分析
                    result.data = await GetSliceSatesAsync(machineIds, dtLastMonthEnd, dtLastDayEnd);
                    break;
                case "production_plan_1": //生产计划安排
                    result.data = await GetDashboardPlanResultAsync();
                    break;
                case "productivity_1": // 生产效率查看
                    result.data = await GetProductivityResultAsync(machineIds);
                    break;
                case "oee_1": //oee
                    result.data = await GetDashboard13ResultAsync(machineIds, dtLastMonthEnd, dtEndTime);
                    break;
                case "production_line_1": //总大屏看板1
                    result.data = await GetProductionLine1Result(machineIds); //dashboard1_4
                    break;
                case "production_line_2"://总大屏看板2
                    result.data = await GetProductionLine2Result(dtStartTime, dtEndTime, monthTime, machineIds);
                    break;
                case "production_line_3"://总大屏看板3
                    result.data = await GetProductionLine3Result(dtStartTime, dtEndTime, machineIds);
                    break;
                case "production_line_4"://总大屏看板4
                    result.data = await GetProductionLine4Result(dtStartTime, dtEndTime, machineIds);
                    break;
                case "production_line_5"://总大屏看板5
                    result.data = await GetProductionLine5Result(dtStartTime, dtEndTime, data.condition.ToInt());
                    break;
                case "workshop_kanban_1": //车间看板
                    result.data = await GetDashboardWorkShopResult(dtStartTime, dtEndTime, monthTime, sectionId);
                    break;
                case "gaobo_status_1": //高博设备状态
                    result.data = await GetGaoboStatus1(machineIds);
                    break;
                case "dbd2_production_1": //产线综合1
                    result.data = await GetSliceSatesAsync(machineIds, dtWeekStart, dtNow.AddDays(-1));
                    break;
                case "dbd2_production_2"://产线综合2
                    result.data = await GetDashboard15ResultAsync(machineIds);
                    break;
                case "dbd2_production_3"://产线综合3
                    result.data = await GetDashboardDbProduction3Result(machineIds);
                    break;
                case "dbd2_production_4"://产线综合4
                    result.data = await GetDashboard16ResultAsync(machineIds);
                    break;
                case "all_production_1": //选择产线
                    result.data = await GetAllProductLineResult(dtStartTime, dtEndTime, machineIds);
                    break;
                case "production_beat_1": //产线标准节拍图
                    result.data = GetDashboardProductionBeat(sectionId, machineId, dtStartTime, dtEndTime);
                    break;
                case "time_goes_1": //时间出来高推移
                    result.data = await GetDashboardTimeGoResult(machineId, dtStartTime, dtEndTime);
                    break;
                case "slice_machine_1":
                    result.data = await GetMachineSliceSatesAsync(machineIds, dtStartTime, dtEndTime);
                    break;
                case "slice_week_1":
                    result.data = await GetWeekSliceSatesAsync(machineIds);
                    break;
                case "output_analysis_1":
                    result.data = await GetOutPutAnalysisAsync(machineIds, keyValues);
                    break;
                case "furnace_diecasting_1":
                case "furnace_diecasting_2":
                case "furnace_diecasting_3":
                case "furnace_diecasting_4":
                    result.data = page_id;
                    break;
                case "e_maintenance_status_1":
                    result.data = await GetMachineRepairStatus(machineIds, projectid);
                    break;
                case "output_efficiency_1": //产出效率--马来西亚
                    result.data = await GetOutPutEfficiencyAsync(machineIds, keyValues);
                    break;
                case "acc_quality_display_1": //移动极值--质量看板
                    result.data = await GetAccQuantityDisplay(machineIds[machineIds.Count() - 1], data.acc_text_value, data.right_article_num);
                    break;
                case "tpm_status_1":
                    result.data = await GetMachineRepair(machineIds, projectid, page, pagesize);
                    break;
                case "tpm_plan_am_1":
                    result.data = await GetMaintainPlan(machineIds, (int)PlanModeType.AM, projectid, page, pagesize);
                    break;
                case "tpm_plan_pm_1":
                    result.data = await GetMaintainPlan(machineIds, (int)PlanModeType.PM, projectid, page, pagesize);
                    break;
                case "skf_gtc_3d_1":
                    result.data = await GetRigStatusMonitor(projectid, patial_code);
                    break;
                case "skf_gtc_3d_2":
                    result.data = await GetCalibrationStatusList(projectid, page, pagesize);
                    break;
                case "skf_gtc_3d_3":
                    result.data = await GetAlMachineRepairList(projectid, page, pagesize);
                    break;
                case "skf_gtc_3d_4":
                    result.data = await GetDashboardSliceStatusPageList(page, pagesize, _companyId, projectid);
                    break;
                case "skf_gtc_3d_5":
                    result.data = await GetMachineCalenderWeekly(projectid, page, pagesize);
                    break;
                case "skf_gtc_3d_6":
                    result.data = await MachineTypeCountByRepairRunState(projectid, _companyId);
                    break;
                case "skf_gtc_3d_7":
                    result.data = await KpiTrendUtlization(projectid);
                    break;
                case "skf_gtc_3d_8":
                    result.data = KpiTrendMTTR(projectid);
                    break;
            }

            return result;
        }

        private async Task<MachineRepairs> GetMachineRepair(List<int> machineIds, int projectid, int page, int pagesize)
        {
            return await Task.Run(() =>
            {
                var response = new MachineRepairs();

                var machines = _machineRepository.GetList(t =>
                    machineIds.Contains(t.id) && t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                var machineRepairStatus = new List<MachineRepairState>();
                var repairs = _repairRepository.GetList(t =>
                    t.status < (int)MachineRepairStatus.Completed && t.status > 0 && t.projectid == projectid &&
                    machineIds.Contains(t.machineid)).OrderBy(t => t.status).ToList();
                var machineStates = new List<MachineRepairStateList>();
                foreach (var machineId in machineIds)
                {
                    var minStatus = repairs.Where(t => t.machineid == machineId).OrderBy(t => t.status).ToList();
                    if (minStatus.Any())
                    {
                        machineStates.Add(new MachineRepairStateList
                        {
                            machineid = machineId,
                            status = minStatus.First().status
                        });
                    }
                    else
                    {
                        machineStates.Add(new MachineRepairStateList
                        {
                            machineid = machineId,
                            status = (int)MachineRepairStatus.Completed
                        });
                    }
                }
                machineRepairStatus.Add(new MachineRepairState
                {
                    name = "200032",
                    status = (int)MachineRepairStatus.WaitingForOrders,
                    count = machineStates.Count(m => m.status == 1),
                    icon = "glyphicon glyphicon-exclamation-sign"
                });
                machineRepairStatus.Add(new MachineRepairState
                {
                    name = "200033",
                    status = (int)MachineRepairStatus.WaitingForCheckIn,
                    count = machineStates.Count(m => m.status == 2),
                    icon = "glyphicon glyphicon-copy"
                });
                machineRepairStatus.Add(new MachineRepairState
                {
                    name = "200034",
                    status = (int)MachineRepairStatus.WaitingForRepair,
                    count = machineStates.Count(m => m.status == 3),
                    icon = "glyphicon glyphicon-wrench"
                });
                machineRepairStatus.Add(new MachineRepairState
                {
                    name = "200035",
                    status = (int)MachineRepairStatus.WaitingForRenew,
                    count = machineStates.Count(m => m.status == 4),
                    icon = "glyphicon glyphicon-wrench"
                });
                machineRepairStatus.Add(new MachineRepairState
                {
                    name = "900704",
                    status = (int)MachineRepairStatus.WaitingForFeedback,
                    count = machineStates.Count(m => m.status == 5),
                    icon = "glyphicon glyphicon-paste"
                });
                machineRepairStatus.Add(new MachineRepairState
                {
                    name = "100200",
                    status = 8,
                    count = machineStates.Count(m => m.status == 6),
                    icon = "glyphicon glyphicon-thumbs-up"
                });

                var orders = new List<MachineRepairingOrder>();
                var faults =
                    _faultTypeRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                var spareparts = _sparepartRepository
                    .GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                var users = _userRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid)
                    .ToList();
                foreach (var repair in repairs)
                {
                    var machine = machines.FirstOrDefault(t => t.id == repair.machineid);
                    if (machine == null)
                    {
                        continue;
                    }

                    var faulttype = faults.FirstOrDefault(t => t.id == repair.faultid);
                    var faultmode = faults.FirstOrDefault(t => t.id == repair.real_faultid);
                    var sparepartout = string.Empty;
                    if (!string.IsNullOrWhiteSpace(repair.sparepartid))
                    {
                        var spares = repair.sparepartid.Split(',');
                        foreach (var spare in spares)
                        {
                            var parts = spare.Split('*');
                            if (parts.Length > 1)
                            {
                                var sparepart = spareparts.FirstOrDefault(t => t.id == parts[0].ToInt());
                                if (sparepart != null)
                                {
                                    sparepartout += $"{sparepart.title}*{parts[1]}";
                                }
                            }
                        }
                    }

                    var user = users.FirstOrDefault(t => t.mid == repair.mid);
                    orders.Add(new MachineRepairingOrder
                    {
                        id = repair.id.ToString(),
                        status = repair.status,
                        location = string.Join("-", GetPositionByMachineId(repair.machineid, projectid)),
                        machinename = machine.title,
                        faulttype = faulttype?.title ?? "",
                        fault_description = repair.fault_description,
                        faultcontent = faultmode?.title ?? "",
                        remark = repair.remark,
                        repair_process = repair.repair_process,
                        reason = repair.real_faultid_desc,
                        sparepartout = sparepartout,
                        createtimeformat = UnixTimeHelper.ConvertIntDateTime(repair.createtime),
                        reportname = user?.name ?? "",
                        haslong = (UnixTimeHelper.GetNow() - repair.createtime) / 60
                    });
                }

                response.pagesize = pagesize;
                response.page = page;
                response.total = orders.Count;
                response.data = orders.Skip((page - 1) * pagesize).Take(pagesize).ToList();
                response.status = machineRepairStatus;
                return response;
            });
        }

        private async Task<MaintainPlans> GetMaintainPlan(List<int> machineIds, int modetype, int projectid, int page, int pagesize)
        {
            return await Task.Run(() =>
            {
                var response = new MaintainPlans();

                var machineStatusList = new List<PlanStateList>();
                var machineStatus = 1;
                var etime = UnixTimeHelper.GetTodayUnix() + 86399;
                var planinformation = _planTime
                    .GetPlanInformationByMachineIds(modetype, machineIds, 0, etime, projectid).Where(t => t.information == (int)PlanStatus.Overdue).ToList();
                foreach (var machineId in machineIds)
                {
                    if (!planinformation.Any())
                    {
                        machineStatus = 1;
                    }
                    else
                    {
                        var plans = planinformation.Where(t => t.machineid == machineId).ToList();
                        if (plans.Count(t => t.information == (int)PlanStatus.Overdue) > 0)
                        {
                            machineStatus = 3;
                        }
                        else if (plans.Count(t => t.information > (int)PlanStatus.UnExecuted) > 0)
                        {
                            machineStatus = 2;
                        }
                        else
                        {
                            machineStatus = 1;
                        }
                    }
                    machineStatusList.Add(new PlanStateList
                    {
                        machineid = machineId,
                        status = machineStatus
                    });
                }

                response.status.Add(new PlanState
                {
                    name = "100200",
                    status = 8,
                    count = machineStatusList.Count(m => m.status == 1),
                    icon = "glyphicon glyphicon-thumbs-up"
                });
                response.status.Add(new PlanState
                {
                    name = "1134",
                    status = 3,
                    count = machineStatusList.Count(m => m.status == 3),
                    icon = "glyphicon glyphicon-exclamation-sign"
                });
                response.status.Add(new PlanState
                {
                    name = "1133",
                    status = 2,
                    count = machineStatusList.Count(m => m.status == 2),
                    icon = "glyphicon glyphicon-copy"
                });
                var users = _userRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid)
                    .ToList();
                planinformation = planinformation.OrderBy(t => t.instruction_time).Take(100).ToList();
                var planIds = planinformation.Select(t => t.planid).Distinct().ToList();
                foreach (var planId in planIds)
                {
                    var times = planinformation.Where(t => t.planid == planId).OrderBy(t => t.instruction_time).ToList();
                    if (!times.Any())
                    {
                        continue;
                    }

                    var plan = times.First();
                    var user = users.FirstOrDefault(t => t.mid == plan.mid);
                    response.data.Add(new MaintainPlanOrder
                    {
                        station = string.Join('-', GetPositionByMachineId(plan.machineid, projectid)),
                        machinetitle = plan.machinetitle,
                        num = planinformation.Count(t => t.planid == plan.planid),
                        instruction_time = UnixTimeHelper.ConvertIntDate(plan.instruction_time),
                        name = user?.name ?? "",
                        status = plan.information
                    });
                }

                response.pagesize = pagesize;
                response.page = page;
                response.total = response.data.Count;
                response.data = response.data.Skip((page - 1) * pagesize).Take(pagesize).ToList();
                return response;
            });
        }

        private async Task<TpmMachineRepairResult> GetMachineRepairStatus(List<int> sectionIds, int projectid)
        {
            return await Task.Run(() =>
            {
                var response = new TpmMachineRepairResult();

                var machines = _machineRepository.GetLevelSectionMachines(0, projectid).ToList();
                sectionIds = machines.Where(t => sectionIds.Contains(t.section_id)).Select(t => t.section_id).ToList();
                var machineIds = machines.Where(t => sectionIds.Contains(t.section_id)).Select(t => t.machine_id).ToList();
                var machineRepairs = _repairRepository.GetList(t =>
                    machineIds.Contains(t.machineid) && t.projectid == projectid &&
                    t.status < (int)MachineRepairStatus.Deleted && t.status > (int)RowState.Invalid);
                foreach (var sectionId in sectionIds)
                {
                    var model = new MachineRepairStatusModel();
                    var sectionTitles = GetPositionBySectionId(sectionId, projectid);
                    var machineids = machines.Where(t => t.section_id == sectionId).Select(t => t.machine_id);
                    var repairs = machineRepairs.Where(t => machineids.Contains(t.machineid)).OrderBy(t => t.status).ToList();
                    var minStatusRepair = repairs.FirstOrDefault();
                    if (minStatusRepair != null)
                    {
                        model.location = string.Join('-', sectionTitles);
                        model.status = minStatusRepair.status;
                        model.repair_count = repairs.Count(t => t.status < (int)MachineRepairStatus.Completed);
                        var offlineRepairs = repairs.OrderBy(t => t.createtime).Where(t => t.offlinestatus == 1).ToList();
                        model.downtime = (offlineRepairs.Any() ? UnixTimeHelper.GetNow() - offlineRepairs.First().createtime : 0) / 60;
                        switch (minStatusRepair.status)
                        {
                            case (int)MachineRepairStatus.WaitingForOrders:
                                break;
                            case (int)MachineRepairStatus.WaitingForCheckIn:
                                var user = _userRepository.Get(t => t.projectid == projectid && t.mid == minStatusRepair.takemid && t.status == (int)RowState.Valid);
                                model.executor = user?.name ?? "";
                                break;
                            case (int)MachineRepairStatus.WaitingForRepair:
                                user = _userRepository.Get(t => t.projectid == projectid && t.mid == minStatusRepair.signmid && t.status == (int)RowState.Valid);
                                model.executor = user?.name ?? "";
                                break;
                            case (int)MachineRepairStatus.WaitingForRenew:
                                user = _userRepository.Get(t => t.projectid == projectid && t.mid == minStatusRepair.mid && t.status == (int)RowState.Valid);
                                model.executor = user?.name ?? "";
                                break;
                            case (int)MachineRepairStatus.WaitingForFeedback:
                                user = _userRepository.Get(t => t.projectid == projectid && t.mid == minStatusRepair.repairmid && t.status == (int)RowState.Valid);
                                model.executor = user?.name ?? "";
                                break;
                            case (int)MachineRepairStatus.Completed:
                                model.repair_count = 0;
                                break;
                        }
                    }
                    else
                    {
                        model = new MachineRepairStatusModel
                        {
                            location = string.Join('-', sectionTitles),
                            status = (int)MachineRepairStatus.Completed,
                            repair_count = 0,
                            executor = "",
                            downtime = 0
                        };
                    }

                    response.MachineRepairStatus.Add(model);
                }

                return response;
            });
        }

        private List<string> GetPositionBySectionId(int sectionId, int projectid)
        {
            var titleList = new List<string>();
            var sections = _machineRepository.GetParentSelfLevelSections(sectionId, projectid).ToList();
            if (sections.Any())
            {
                titleList = sections.Select(t => t.title).ToList();
                titleList = titleList.Take(3).ToList();
                titleList.Reverse();
            }
            return titleList;
        }

        private List<string> GetPositionByMachineId(int machineId, int projectid)
        {
            var titleList = new List<string>();
            var levelmachine = _repairRepository.GetLevelSectionByMachineId(machineId, projectid);
            if (levelmachine != null)
            {
                var sections = _repairRepository.GetParentSelfLevelSections(levelmachine.id, projectid).ToList();
                if (sections.Any())
                {
                    titleList = sections.Select(t => t.title).ToList();
                    titleList.Reverse();
                }
            }
            return titleList;
        }

        /// <summary>
        /// 获取产线层级
        /// </summary>
        /// <param name="sectionId"></param>
        /// <returns></returns>
        private string GetSectionId(int sectionId)
        {
            var ids = _machineRepository.GetParentLevelSectionIds(sectionId, _projectId).Distinct().ToList().OrderByDescending(o => o).ToList();

            return string.Join(',', ids).TrimEnd(',');
        }

        private async Task<Dashboard11Result> GetDashboard11ResultAsync()
        {
            var startTime = UnixTimeHelper.GetTodayUnix() - 86400 * 30;
            var endTime = UnixTimeHelper.GetTodayUnix() + 86400 - 1;

            var query1 = await _planRepository.GetListAsync(q => q.projectid == _projectId && q.delivery_time >= startTime &&
                                                    q.delivery_time <= endTime);
            var query2 = query1.Where(q => q.status == (int)PlanProcess.Finished && q.delivery_time >= q.finish_time);
            var query3 = query1.Where(q => q.status == (int)PlanProcess.Finished);

            var count1 = query1.Count();
            var count2 = query2.Count();
            var count3 = query3.Count();

            var result = new Dashboard11Result
            {
                first = new FirstParameter
                {
                    num1 = count1,
                    num2 = count2,
                    num3 = count3
                }
            };
            result.second.Add(new SecondParameter
            {
                name = "准时完成数",
                num1 = count2,
                num2 = count1 - count2
            });
            result.second.Add(new SecondParameter
            {
                name = "最终完成数",
                num1 = count3,
                num2 = count1 - count3
            });
            return result;
        }

        private List<siger_project_product_plan> GetDashboard12Result()
        {
            var plans = _planRepository.GetList(q => q.projectid == _projectId && q.status == (int)PlanProcess.Producing);

            return plans.OrderBy(q => q.delivery_time).Take(10).ToList();
        }

        private async Task<Dashboard13Result> GetDashboard13ResultAsync(IEnumerable<int> machineIds, DateTime dtStart, DateTime dtEnd)
        {
            var result = new Dashboard13Result();

            var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, 0);
            //var times = _timeRepository.GetRestTimesByMachine(machineIds, _projectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, _projectId);
            var repositoey = new SliceSateRepository(_companyId, _projectId);
            for (var i = 0; i < dates.Count; i++)
            {
                DateTime start = DateTime.Parse(dates[i].ToString(ParameterConstant.DateFromZero));
                DateTime end = start.AddDays(1).AddSeconds(-1);
                result.x.Add(start.ToString(ParameterConstant.MonthDayFormay));

                var sliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, start.ToString(ParameterConstant.DateTimeFormat), end.ToString(ParameterConstant.DateTimeFormat));
                double oeeTotal = 0;
                var oeeEntity = new OeeDetailEntity();
                foreach (var machineId in machineIds)
                {
                    var machineSlice = sliceSates.Where(q => q.MachineID == machineId);
                    if (machineSlice.Any())
                    {
                        var unixStart = UnixTimeHelper.ConvertDataTimeLong(start);
                        var unixEnd = UnixTimeHelper.ConvertDataTimeLong(end);
                        var reports = _beatSetRepository.GetProductReport(unixStart, unixEnd, new List<int> { machineId }, _projectId);
                        oeeEntity = OeeManager.GetOeeByTime(start, end, machineSlice, new List<int> { machineId }, reports, times);
                        oeeTotal += oeeEntity.OEE;
                    }
                }
                if (machineIds.Count() == 1)
                {
                    result.type = "1";
                    result.y.Add(i, new OeeDetailEntity(oeeEntity.OEE1, oeeEntity.OEE2, oeeEntity.OEE3));
                }
                else
                {
                    result.type = "2";
                    result.y.Add(i, new OeeDetailEntity(Math.Round(oeeTotal / machineIds.Count(), 2)));
                }
            }

            return result;
        }

        private async Task<Dashboard14Result> GetDashboard14ResultAsync(IEnumerable<int> machineIds, DateTime dtStart, DateTime dtEnd)
        {
            var result = new Dashboard14Result
            {
                analysis = await GetSliceSatesAsync(machineIds, dtStart, dtEnd),
                status = await GetMachineRunningStatusAsync(machineIds)
            };

            return result;
        }

        private async Task<List<MachineCanvasDataInfo>> GetSliceSatesAsync(IEnumerable<int> machineIds, DateTime dtStart, DateTime dtEnd)
        {
            var responses = new List<MachineCanvasDataInfo>();

            var repository = new DailySliceSateRepository(_companyId, _projectId);
            var sliceSates = await repository.GetCncDailySliceSatesAsync(machineIds, dtStart, dtEnd);

            var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, 0);
            foreach (var date in dates)
            {
                var start = date;
                var end = date.AddDays(1).AddSeconds(-1);

                if (DateTime.Now.Date.Subtract(date.Date).Days <= 0)
                {
                    responses.Add(await SliceManager.GetMachineSlice(start, end, machineIds,
                        _companyId, _projectId, end.ToString(ParameterConstant.MonthDayFormay)));
                }
                else
                {
                    var daySlice = sliceSates.Where(q => q.date <= end && q.date >= start);
                    responses.Add(DaySliceManager.GetMachineSlice(start, end, daySlice, end.ToString(ParameterConstant.MonthDayFormay)));
                }
            }

            return responses;
        }

        private async Task<List<MachineCanvasDataInfo>> GetMachineSliceSatesAsync(IEnumerable<int> machineIds, DateTime dtStart, DateTime dtEnd)
        {
            var responses = new List<MachineCanvasDataInfo>();

            var machines = _machineRepository.GetNCLevelSectionNames(machineIds, _projectId);

            foreach (var machine in machines)
            {
                responses.Add(await SliceManager.GetMachineSlice(dtStart, dtEnd, new List<int> { machine.machine_id },
                    _companyId, _projectId, machine.lastSecondSectionTitle + "-" + machine.lastSectionTitle));
            }
            //添加平均值
            var total = machineIds.Count();
            double shutdown = 0; //关机
            double running = 0; //运行
            double debugging = 0; //调试
            double free = 0; //空闲
            double fault = 0; //故障
            foreach (var response in responses)
            {
                shutdown += response.data.num1;
                running += response.data.num2;
                debugging += response.data.num3;
                free += response.data.num4;
                fault += response.data.num5;
            }
            var average = new MachineCanvasDataInfo
            {
                datetime = "平均值(Average)",
                data = new MachineSateCount
                {
                    datetime = "平均值(Average)",
                    num1 = Math.Round(shutdown / total, 2),
                    num2 = Math.Round(running / total, 2),
                    num3 = Math.Round(debugging / total, 2),
                    num4 = Math.Round(free / total, 2),
                    num5 = Math.Round(fault / total, 2),
                }
            };
            responses.Add(average);

            return responses;
        }

        private async Task<List<MachineCanvasDataInfo>> GetWeekSliceSatesAsync(IEnumerable<int> machineIds)
        {
            var responses = new List<MachineCanvasDataInfo>();

            var now = DateTime.Now;
            var i = now.DayOfWeek - DayOfWeek.Monday;
            if (i == -1)
            {
                i = 6;
            }
            var date = now.Subtract(new TimeSpan(i, 0, 0, 0));
            var end = date.AddDays(i);
            DateTime dtDay;

            for (dtDay = date.Date; dtDay.CompareTo(end) < 0; dtDay = dtDay.AddDays(1).Date)
            {
                var dtEnd = dtDay.AddDays(1).AddSeconds(-1);
                if (dtEnd > DateTime.Now)
                {
                    dtEnd = DateTime.Now;
                }
                responses.Add(await SliceManager.GetMachineSlice(dtDay, dtEnd, machineIds,
                    _companyId, _projectId, RestTimeManager.GetDayofWeek(dtDay)));
            }

            //没有数据的集合
            var weekEnd = date.Date.AddDays(6);
            var nodataList = new List<MachineCanvasDataInfo>();
            for (dtDay = end.Date.AddDays(1); dtDay.CompareTo(weekEnd) <= 0; dtDay = dtDay.AddDays(1).Date)
            {
                nodataList.Add(new MachineCanvasDataInfo
                {
                    datetime = RestTimeManager.GetDayofWeek(dtDay),
                    data = new MachineSateCount
                    {
                        datetime = RestTimeManager.GetDayofWeek(dtDay),
                        num1 = 100,
                        num2 = 0,
                        num3 = 0,
                        num4 = 0,
                        num5 = 0,
                    }
                });
            }

            //添加平均值
            var total = i + 1;
            double shutdown = 0; //关机
            double running = 0; //运行
            double debugging = 0; //调试
            double free = 0; //空闲
            double fault = 0; //故障
            foreach (var response in responses)
            {
                shutdown += response.data.num1;
                running += response.data.num2;
                debugging += response.data.num3;
                free += response.data.num4;
                fault += response.data.num5;
            }
            var average = new MachineCanvasDataInfo
            {
                datetime = "平均值(Average)",
                data = new MachineSateCount
                {
                    datetime = "平均值(Average)",
                    num1 = Math.Round(shutdown / total, 2),
                    num2 = Math.Round(running / total, 2),
                    num3 = Math.Round(debugging / total, 2),
                    num4 = Math.Round(free / total, 2),
                    num5 = Math.Round(fault / total, 2),
                }
            };

            responses.AddRange(nodataList);
            responses.Add(average);

            return responses;
        }

        private async Task<List<GetOutPutAnalysisResult>> GetOutPutAnalysisAsync(IEnumerable<int> machineIds, IEnumerable<ResponseKeyValue> shifts)
        {
            var response = new List<GetOutPutAnalysisResult>();
            if (!machineIds.Any() || !shifts.Any())
            {
                return response;
            }

            var shiftInfoes = ConvertShifts(shifts);
            if (!shiftInfoes.Any())
            {
                return response;
            }

            var validMachines = _machineRepository.GetNCLevelSectionNames(machineIds, _projectId).ToList();
            if (!validMachines.Any())
            {
                return response;
            }

            var beates = _beatSetRepository.GetList(q => machineIds.Contains(q.machineID) && q.projectID == _projectId && q.status == (int)RowState.Valid).ToList();
            machineIds = validMachines.Select(m => m.machine_id).ToList();
            var repository = new ProductRepository(_companyId, _projectId);
            int no = 1;
            foreach (var shiftInfo in shiftInfoes)
            {
                var query = repository.GetYileds(shiftInfo.StartTime.ToString(ParameterConstant.DateTimeFormat),
                    shiftInfo.EndTime.ToString(ParameterConstant.DateTimeFormat), machineIds);

                foreach (var machine in validMachines)
                {
                    var machineYileds = query.Where(q => q.machineID == machine.machine_id);
                    if (machineYileds.Any())
                    {
                        var yields = await YieldMangaer.GetProgramNosTwo(machineYileds, shiftInfo.StartTime.ToString(ParameterConstant.DateTimeFormat),
                            machine.machine_id, (int)UnixTimeHelper.ConvertDataTimeLong(shiftInfo.EndTime));

                        var routes = GetProductRoutesOee(yields);
                        foreach (var yiled in yields)
                        {
                            var end = yiled.endTime.ToDateTime();
                            var beat = beates.FirstOrDefault(q => q.machineID == machine.machine_id && q.process_number == yiled.programNo
                                                                  && q.start_time <= end && q.end_time >= end);
                            var actYield = beat == null ? yiled.yield : yiled.yield * beat.yieldrate;
                            var route = routes.FirstOrDefault(q => q.machine_id == machine.machine_id && q.program_code == yiled.programNo);
                            var res = new GetOutPutAnalysisResult
                            {
                                index = no,
                                machineName = machine.lastSecondSectionTitle + "-" + machine.lastSectionTitle,
                                shift = shiftInfo.Name,
                            };
                            if (route != null)
                            {
                                res.productName = route.product_name;
                                res.theoreticalOutput = route.efficiency <= 0
                                    ? "NA"
                                    : Math.Round(route.efficiency, 0).ToString();
                                res.actualOutput = actYield;
                                res.efficiency = route.efficiency <= 0
                                    ? 100
                                    : Math.Round(actYield / res.theoreticalOutput.ToDouble() * 100, 2);
                            }
                            response.Add(res);
                        }
                    }
                }
            }

            return response;
        }

        private IList<ResponseGetListMachineYield> GetProductRoutesOee(IList<ProgramYield> programs)
        {
            var result = new List<ResponseGetListMachineYield>();
            var machineIds = programs.Select(m => m.machineId).ToList();
            var beats = _beatSetRepository.GetList(q =>
                machineIds.Contains(q.machineID) && q.projectID == _projectId && q.status == (int)RowState.Valid).ToList();

            //var times = _timeRepository.GetRestTimesByMachine(machineIds, _projectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, _projectId);
            foreach (var program in programs)
            {
                var end = program.endTime.ToDateTime();
                var beat = beats.FirstOrDefault(q => q.machineID == program.machineId && q.process_number == program.programNo
                                                     && q.start_time <= end && q.end_time >= end);

                var entity = new ResponseGetListMachineYield
                {
                    machine_id = program.machineId,
                    program_code = program.programNo,
                    product_name = "",
                    route_name = ""
                };

                if (beat != null)
                {
                    entity.product_name = beat.product_name_text;
                    entity.route_name = beat.route_name;
                }

                //var newRun = RestTimeManager.GetNewRun(program.machineId, program.startTime.ToDateTime(), program.endTime.ToDateTime(), times);
                //                                                                                         如果当前时间小于结束时间，用当前时间计算
                var newRun = RestTimeManager.GetNewRun(program.machineId, program.startTime.ToDateTime(), DateTime.Now < program.endTime.ToDateTime() ? DateTime.Now : program.endTime.ToDateTime(), times);
                entity.efficiency = newRun / beat?.standard_besat ?? 0; ;

                result.Add(entity);
            }

            return result;
        }

        private List<ShiftInfo> ConvertShifts(IEnumerable<ResponseKeyValue> shifts)
        {
            var shiftInfoes = new List<ShiftInfo>();
            foreach (var shift in shifts)
            {
                var times = shift.value.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                if (times.Length == 2)
                {
                    var successStart = DateTime.TryParse(times[0].Replace(" ", ""), out var startTime);
                    var successEnd = DateTime.TryParse(times[1].Replace(" ", ""), out var endTime);
                    if (successStart && successEnd)
                    {
                        shiftInfoes.Add(new ShiftInfo
                        {
                            Name = shift.key,
                            StartTime = startTime,
                            EndTime = endTime
                        });
                    }
                }
            }

            return shiftInfoes;
        }

        private async Task<DashboardListMachineYieldBySignResult> GetDashboard15ResultAsync(IEnumerable<int> machineIds)
        {
            var startTime = DateTime.Now.ToString(ParameterConstant.DateFromZero);
            var endTime = DateTime.Now.ToString(ParameterConstant.DateTimeFormat);

            var repository = new ProductRepository(_companyId, _projectId);
            var query = await repository.GetYieldsAsync(startTime, endTime, machineIds);
            var responses = new DashboardListMachineYieldBySignResult();

            var machines = await _machineRepository.GetListAsync(q => machineIds.Contains(q.id) && q.projectid == _projectId && q.status == (int)RowState.Valid && q.category == (int)MachineCategory.NC);

            foreach (var machine in machines)
            {
                responses.x.Add(machine.title);
                responses.y.Add(query.Where(q => q.machineID == machine.id).Sum(m => m.yield));
            }

            return responses;
        }

        private async Task<DashboardListMachineYieldBySignResult> GetDashboard16ResultAsync(IEnumerable<int> machineIds)
        {
            var startTime = DateTime.Now.ToString(ParameterConstant.DateFromZero);
            var endTime = DateTime.Now.ToString(ParameterConstant.DateTimeFormat);

            var repository = new ProductRepository(_companyId, _projectId);
            var responses = new DashboardListMachineYieldBySignResult();

            var dates = new List<string>();
            var products = new List<int>();

            for (var i = 7; i > 0; i--)
            {
                var query = await repository.GetYieldsAsync(startTime, endTime, machineIds);

                dates.Add(DateTime.Parse(startTime).ToString("MM-dd"));
                products.Add(query.Sum(m => m.yield));

                endTime = startTime;
                startTime = DateTime.Parse(startTime).AddDays(-1).ToString(ParameterConstant.DateFromZero);
            }

            dates.Reverse();
            products.Reverse();

            responses.x = dates;
            responses.y = products;
            return responses;
        }

        private async Task<DashboardMachineRunningStateResult> GetMachineRunningStatusAsync(IEnumerable<int> machineIds)
        {
            var result = new DashboardMachineRunningStateResult();
            var validMachines = _machineRepository.GetNCLevelSectionNames(machineIds, _projectId);
            var machineDatas = validMachines.ToList();
            if (!machineDatas.Any())
            {
                return result;
            }
            try
            {
                var validateMachineIds = machineDatas.Select(m => m.machine_id);
                var machineAlarms = await _machineParamAlarmRepository.GetListAsync(q => validateMachineIds.Contains(q.machine_id) && q.status == (int)RowState.Valid);

                var redisRepository = new CNCEquipmentStateRepository(_companyId, _projectId);
                var machineStates = redisRepository.GetCNCEquipmentStates(validateMachineIds);
                foreach (var machine in machineDatas)
                {
                    var alarm = machineAlarms.FirstOrDefault(q => q.machine_id == machine.machine_id);
                    if (alarm != null)
                    {
                        var alarmReturn = Mapper<siger_project_machine_param_alarm, MachineAlarm>.Map(alarm);
                        if (!result.listAll.Keys.Contains(machine.machine_id))
                        {
                            result.listAll.Add(machine.machine_id, alarmReturn);
                        }                        
                    }
                    else
                    {
                        if (!result.listAll.Keys.Contains(machine.machine_id))
                        {
                            result.listAll.Add(machine.machine_id, new ArrayList());
                        }                            
                    }

                    var machineState = machineStates.FirstOrDefault(q => q.MachineId == machine.machine_id);
                    if (machineState != null)
                    {
                        var machineReturn = Mapper<CNCEquipmentState, MachineState>.Map(machineState);
                        machineReturn.Staus = ResetMachineStatus(machineState.Status, machineState.LastUpdateTime);
                        if (machineReturn.Staus == 0) //关机
                        {
                            machineReturn.FeedRatio = 0;
                            machineReturn.FeedSpeed = 0;
                            machineReturn.SpindleSpeed1 = 0;
                            machineReturn.SpindleRatio = 0;
                            machineReturn.PN = "";
                            machineReturn.SPN = "";
                        }
                        machineReturn.machineTitle = machine.lastSectionTitle;// 最后一级产线名称
                        machineReturn.title = machine.lastSecondSectionTitle;
                        result.last_data.data.Add(machineReturn);
                        result.data = (machineReturn);
                    }
                    else
                    {
                        var machineReturn = new MachineState
                        {
                            MachineId = machine.machine_id,
                            machineTitle = machine.lastSectionTitle,// 最后一级产线名称
                            title = machine.lastSecondSectionTitle
                        };
                        result.last_data.data.Add(machineReturn);
                    }
                }
            }
            catch (Exception e)
            {
                Logger.WriteLineError("GetMachineRunningStatusAsync failed, error :" + e);
            }

            return result;
        }

        private async Task<DashboardMachineRunningStateListResult> GetDashboardMachineRunningStateListResult(IEnumerable<int> machineIds)
        {
            var validMachines = _machineRepository.GetNCLevelSectionNames(machineIds, _projectId);
            var machineDatas = validMachines.ToList();
            var result = new DashboardMachineRunningStateListResult
            {
                ret = 1,
                ids = machineIds.ToList(),
                startTime = DateTime.Now.ToString(ParameterConstant.DateFromZero),
                endTime = DateTime.Now.ToString(ParameterConstant.DateToEnd),
                machines = machineIds.ToList(),
                iszy = "dev",
            };
            if (!machineDatas.Any())
            {
                return result;
            }

            var states = await MachineManager.GetMachineRunningStatesResultAsync(_companyId, _projectId, machineDatas);
            result.data = states.data;
            result.last_data = states.last_data;
            result.zy_data = states.zy_data;

            return result;
        }

        private async Task<DashboardMachineCanvasParetoInfoResult> GetDashboardSliceStatusResultAsync(DateTime dtStart, DateTime dtEnd, IEnumerable<int> machineIds)
        {
            var result = new DashboardMachineCanvasParetoInfoResult
            {
                startTime = dtStart.ToString(ParameterConstant.DateTimeFormat),
                endTime = dtEnd.ToString(ParameterConstant.DateTimeFormat),
                total_time_span = (dtEnd - dtStart).TotalSeconds
            };

            var validMachines = _machineRepository.GetNCLevelSectionNames(0, _projectId);

            var canvas = await SliceManager.GetMachineSliceNew(dtStart, dtEnd, machineIds, validMachines, _companyId, _projectId);

            result.canvas = canvas.canvas;
            result.pareto = canvas.pareto;

            return result;
        }

        private int ResetMachineStatus(int oldStatus, string lastUpdateTime)
        {
            if (DateTime.Now.Subtract(DateTime.Parse(lastUpdateTime)).TotalMinutes > CommonConst.MachineShutDownThreshold)
            {
                return 0; //关机
            }
            return oldStatus;
        }

        private async Task<List<siger_project_product_plan>> GetDashboardPlanResultAsync()
        {
            var plans = await _planRepository.GetListAsync(q => q.projectid == _projectId && q.status != (int)PlanProcess.Stop);

            return plans.OrderBy(q => q.status).ThenBy(q => q.delivery_time).Take(10).ToList();
        }

        private async Task<List<ResponseEfficiencyAnalysisInfo>> GetProductivityResultAsync(IEnumerable<int> machineIds)
        {
            var startTime = DateTime.Now.ToString(ParameterConstant.DateFromZero);
            var endTime = DateTime.Now.ToString(ParameterConstant.DateTimeFormat);

            var dtStart = DateTime.Parse(startTime);
            var dtEnd = DateTime.Parse(endTime);

            var responses = new List<ResponseEfficiencyAnalysisInfo>();
            var repositoey = new SliceSateRepository(_companyId, _projectId);

            var sliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, startTime, endTime);


            //var machines = _machineRepository.GetList(q => machineIds.Contains(q.id) && q.projectid == _projectId && q.status == (int)RowState.Valid && q.category == (int)MachineCategory.NC);
            var machines = _machineRepository.GetMathineTitle(machineIds, (int)RowState.Valid, _projectId, (int)MachineCategory.NC);
            //var times = _timeRepository.GetRestTimesByMachine(machineIds, _projectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, _projectId);
            var repository = new ProductRepository(_companyId, _projectId);
            foreach (var machineId in machineIds)
            {
                var machine = machines.FirstOrDefault(q => q.id == machineId);
                var machineTitle = machine != null ? machine.title : "";
                //不看设备看工位
                //var machineTitle = machine != null ? machine.code : "";
                var response = new ResponseEfficiencyAnalysisInfo
                {
                    machineID = machineId,
                    title = machineTitle,
                    productivity = 0,
                    yield = 0
                };
                if (sliceSates.Any())
                {
                    double productivity = 0;
                    double yield = 0;
                    var oee = OeeManager.GetOeeByTime(dtStart, dtEnd, sliceSates, new List<int> { machineId },
                        null, times);
                    productivity = oee.OEE1;
                    response.productivity = Math.Round(productivity, 2);

                    //yield
                    var query = await repository.GetYieldsAsync(startTime, endTime, new List<int> { machineId });
                    var yiledSum = query.Sum(q => q.yield);
                    if (yiledSum == 0)
                    {
                        yield = 0;
                    }
                    else
                    {
                        yield = oee.Run / yiledSum;
                    }

                    response.yield = Math.Round(yield, 2);
                }

                responses.Add(response);
            }

            return responses;
        }

        private async Task<List<DashboardDbProduction3List>> GetDashboardDbProduction3Result(IEnumerable<int> sectionIds)
        {
            var result = new List<DashboardDbProduction3List>();

            var configs = await _productionConfigRepository.GetListAsync(q =>
                q.projectid == _projectId && sectionIds.Contains(q.production_section_id) && q.status == (int)RowState.Valid);
            var machineIds = configs.Select(m => m.machine_id);

            var repository = new CNCEquipmentStateRepository(_companyId, _projectId);
            var machineStates = repository.GetCNCEquipmentStates(machineIds);

            foreach (var config in configs.ToList())
            {
                var status = 0;
                var machineState = machineStates.FirstOrDefault(m => m.MachineId == config.machine_id);
                if (machineState != null)
                {
                    status = ResetMachineStatus(machineState.Status, machineState.LastUpdateTime);
                }

                result.Add(new DashboardDbProduction3List
                {
                    Status = status,
                    h = config.h,
                    x = config.x,
                    y = config.y,
                    w = config.w,
                    machine_id = config.machine_id,
                    machine_section_id = config.machine_section_id,
                    machine_section_title = config.machine_section_title,
                    production_section_title = config.production_section_title
                });
            }
            return result;
        }

        private async Task<DashboardProductionLine1Result> GetProductionLine1Result(IEnumerable<int> machineIds)
        {
            var result = new DashboardProductionLine1Result { status = await GetMachineRunningStatusAsync(machineIds) };

            return result;
        }

        private async Task<DashboardProductionLine2Result> GetProductionLine2Result(DateTime startTime, DateTime endTime, DateTime startMonthTime,
            IEnumerable<int> machineIds)
        {
            var result = new DashboardProductionLine2Result
            {
                eff =
                {
                    big = "没有数据",
                    small = "没有数据"
                }
            };
            var repositoey = new SliceSateRepository(_companyId, _projectId);

            var daySliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, startTime.ToString(ParameterConstant.DateTimeFormat),
                endTime.ToString(ParameterConstant.DateTimeFormat));

            var dayStatus = SliceManager.GetMachineStatusHold(machineIds, startTime, endTime, daySliceSates);
            if (dayStatus == null || !dayStatus.Any())
            {
                return result;
            }
            result.day = new StatusTimeHours
            {
                debugging = Math.Round(dayStatus.First(m => m.Status == MachineRunningStatus.Debugging).TimeSpan / 3600, 2),
                fault = Math.Round(dayStatus.First(m => m.Status == MachineRunningStatus.Fault).TimeSpan / 3600, 2),
                free = Math.Round(dayStatus.First(m => m.Status == MachineRunningStatus.Free).TimeSpan / 3600, 2),
                running = Math.Round(dayStatus.First(m => m.Status == MachineRunningStatus.Running).TimeSpan / 3600, 2),
                shutdown = Math.Round(dayStatus.First(m => m.Status == MachineRunningStatus.Shutdown).TimeSpan / 3600, 2),
            };
            var productivity = await GetProductivityResultAsync(machineIds);
            if (productivity != null && productivity.Any()) // 按productivity排序，取最大和最小的设备
            {
                var orderedPro = productivity.OrderBy(q => q.productivity);
                result.eff.big = orderedPro.Last().title;
                result.eff.small = orderedPro.First().title;
            }

            var monthSliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, startMonthTime.ToString(ParameterConstant.DateTimeFormat),
                endTime.ToString(ParameterConstant.DateTimeFormat));
            var monthStatus = SliceManager.GetMachineStatusHold(machineIds, startMonthTime, endTime, monthSliceSates);
            if (monthStatus != null && monthStatus.Any())
            {
                result.month = new StatusTimeHours
                {
                    debugging = Math.Round(monthStatus.First(m => m.Status == MachineRunningStatus.Debugging).TimeSpan / 3600, 2),
                    fault = Math.Round(monthStatus.First(m => m.Status == MachineRunningStatus.Fault).TimeSpan / 3600, 2),
                    free = Math.Round(monthStatus.First(m => m.Status == MachineRunningStatus.Free).TimeSpan / 3600, 2),
                    running = Math.Round(monthStatus.First(m => m.Status == MachineRunningStatus.Running).TimeSpan / 3600, 2),
                    shutdown = Math.Round(monthStatus.First(m => m.Status == MachineRunningStatus.Shutdown).TimeSpan / 3600, 2),
                };
            }

            return result;
        }

        private async Task<StatusTimeHours> GetProductionLine3Result(DateTime startTime, DateTime endTime, IEnumerable<int> machineIds)
        {
            var repositoey = new SliceSateRepository(_companyId, _projectId);

            var daySliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, startTime.ToString(ParameterConstant.DateTimeFormat),
                endTime.ToString(ParameterConstant.DateTimeFormat));

            double debugging = 0;
            double fault = 0;
            double free = 0;
            double running = 0;
            double shutdown = 0;
            foreach (var machineId in machineIds)
            {
                var dayStatus = SliceManager.GetMachineStatusHold(new List<int> { machineId }, startTime, endTime, daySliceSates);
                if (dayStatus != null && dayStatus.Any())
                {
                    debugging += dayStatus.First(m => m.Status == MachineRunningStatus.Debugging).TimeSpan;
                    fault += dayStatus.First(m => m.Status == MachineRunningStatus.Fault).TimeSpan;
                    free += dayStatus.First(m => m.Status == MachineRunningStatus.Free).TimeSpan;
                    running += dayStatus.First(m => m.Status == MachineRunningStatus.Running).TimeSpan;
                    //shutdown += dayStatus.First(m => m.Status == MachineRunningStatus.Shutdown).TimeSpan;
                }
            }
            var totalCount = (endTime - startTime).TotalSeconds * machineIds.Count();
            shutdown = totalCount - (running + debugging + free + fault);
            return new StatusTimeHours
            {
                debugging = Math.Round(debugging / 3600, 2),
                fault = Math.Round(fault / 3600, 2),
                free = Math.Round(free / 3600, 2),
                running = Math.Round(running / 3600, 2),
                shutdown = Math.Round(shutdown / 3600, 2),
            };
        }

        private async Task<DashboardProductionLine4Result> GetProductionLine4Result(DateTime startTime, DateTime endTime, IEnumerable<int> machineIds)
        {
            var result = new DashboardProductionLine4Result();
            //var query = await _machineRepository.GetListAsync(q => machineIds.Contains(q.id) && q.status == (int)RowState.Valid && q.projectid == _projectId && q.category == (int)MachineCategory.NC);
            var query=_machineRepository.GetMathineTitle(machineIds,(int)RowState.Valid, _projectId ,(int)MachineCategory.NC);

            var machines = query.OrderBy(m => m.sorting).ThenBy(m=>m.id).ToList();
            var yesterdayStart = DateTime.Now.AddDays(-1).ToString(ParameterConstant.DateFromZero);
            var yesterdayEnd = DateTime.Now.AddDays(-1).ToString(ParameterConstant.DateToEnd);
            var oneYesStart = DateTime.Now.AddDays(-2).ToString(ParameterConstant.DateFromZero);
            var oneYesEnd = DateTime.Now.AddDays(-2).ToString(ParameterConstant.DateToEnd);

            var validMachineIds = machines.Select(m => m.id);
            var todayRunning = await GetRunning(startTime, endTime, validMachineIds);
            var yesterdayRunning = await GetRunning(DateTime.Parse(yesterdayStart), DateTime.Parse(yesterdayEnd), validMachineIds);
            var oneYesRunning = await GetRunning(DateTime.Parse(oneYesStart), DateTime.Parse(oneYesEnd), validMachineIds);

            foreach (var machine in machines)
            {

                var title = machine.title;
                //不看设备看工位
                //var title = machine.code;
                result.Day.title.Add(title);
                result.Day.running.Add(todayRunning[machine.id]);

                result.Yesterday.title.Add(title);
                result.Yesterday.running.Add(yesterdayRunning[machine.id]);

                result.OneYesterday.title.Add(title);
                result.OneYesterday.running.Add(oneYesRunning[machine.id]);

            }

            return result;
        }

        private async Task<Dictionary<int, double>> GetRunning(DateTime startTime, DateTime endTime, IEnumerable<int> machineIds)
        {
            var repositoey = new SliceSateRepository(_companyId, _projectId);
            var daySliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, startTime.ToString(ParameterConstant.DateTimeFormat),
                endTime.ToString(ParameterConstant.DateTimeFormat));

            var dic = new Dictionary<int, double>();

            foreach (var machineId in machineIds)
            {
                var machineSlice = daySliceSates.Where(q => q.MachineID == machineId);

                var dayStatus = SliceManager.GetMachineStatusHold(new List<int> { machineId }, startTime, endTime, machineSlice);
                if (dayStatus != null && dayStatus.Any())
                {
                    var running = dayStatus.First(m => m.Status == MachineRunningStatus.Running).TimeSpan;
                    var total = (endTime - startTime).TotalSeconds;
                    if (!dic.Keys.Contains(machineId))
                    {
                        dic.Add(machineId, total <= 0 ? 0 : Math.Round(running / total * 100, 2));
                    }                    
                }
                else
                {
                    if (!dic.Keys.Contains(machineId)) 
                    {
                        dic.Add(machineId, 0);
                    }                       
                }
            }

            return dic;
        }

        private async Task<DashboardProductionLine5> GetProductionLine5Result(DateTime startTime, DateTime endTime, int levelId)
        {
            var result = new DashboardProductionLine5();
            var responses = new List<MachineCanvasDataInfo>();
            //var sections = _machineRepository.GetLevelSectionsByLevelId(levelId, _projectId);
            var sections = _machineRepository.GetNCLevelSections(0, _projectId);
            sections = sections.Where(t => t.levelid == levelId).ToList();

            var levels = sections.Where(q => q.levelid == levelId).ToList();
            //求单位运行时间之和
            double Unittime = 0;
            //求单位平均时间之和
            double UnitAvgtime = 0;
            foreach (var levelSection in levels)
            {
                var machineIds = _machineRepository.GetNCLevelSectionMachineIds(levelSection.id, _projectId);
                if (!machineIds.Any())
                {
                    continue;
                }
                var repositoey = new SliceSateRepository(_companyId, _projectId);
                var daySliceSates = await repositoey.GetCncSliceSatesAsync(machineIds,
                    startTime.ToString(ParameterConstant.DateTimeFormat),
                    endTime.ToString(ParameterConstant.DateTimeFormat));

                var dayStatus = SliceManager.GetMachineStatusHold(machineIds, startTime,
                    endTime, daySliceSates);

                if (dayStatus == null)
                {
                }
                else
                {
                    var running = dayStatus.FirstOrDefault(q => q.Status == MachineRunningStatus.Running);

                    //单位运行时间之和
                    Unittime += running.TimeSpan;
                    //单位平均时间之和
                    UnitAvgtime += running.TimeSpan / machineIds.Count();
                }

            }
            foreach (var levelSection in levels)
            {
                var machineIds = _machineRepository.GetNCLevelSectionMachineIds(levelSection.id, _projectId);
                if (!machineIds.Any())
                {
                    continue;
                }

                responses.Add(await SliceManager.GetMachineSlice(startTime, endTime, machineIds,
                    _companyId, _projectId, levelSection.title));

                var repositoey = new SliceSateRepository(_companyId, _projectId);
                var daySliceSates = await repositoey.GetCncSliceSatesAsync(machineIds,
                    startTime.ToString(ParameterConstant.DateTimeFormat),
                    endTime.ToString(ParameterConstant.DateTimeFormat));

                var dayStatus = SliceManager.GetMachineStatusHold(machineIds, startTime,
                    endTime, daySliceSates);
                var nameValue = new NameValue
                {
                    name = levelSection.title
                };
                var nameValueDan = new NameValue
                {
                    name = levelSection.title
                };

                if (dayStatus == null)
                {
                    //level
                    result.level.running.Add(nameValue);
                    //dan
                    result.dan.running.Add(nameValue);
                }
                else
                {
                    var running = dayStatus.FirstOrDefault(q => q.Status == MachineRunningStatus.Running);
                    //level 总效率 
                    nameValue.value = running?.TimeSpan <= 0
                        ? 0
                        : Math.Round(running?.TimeSpan / 3600 ?? 0, 2);
                    if (Unittime > 0)
                    {
                        nameValue.percent = Math.Round((running?.TimeSpan / Unittime) *100??0,2).ToString();

                    }
                    else
                    {
                        nameValue.percent = "0";
                    }

                    //dan 单位效率
                    nameValueDan.value = running?.TimeSpan <= 0
                        ? 0
                        : Math.Round(running?.TimeSpan / machineIds.Count() / 3600 ?? 0, 2);
                    if (UnitAvgtime > 0)
                    {
                        //用于总效率边上的百分比
                        nameValueDan.percent = running?.TimeSpan <= 0
                        ? "0"
                        : Math.Round((running?.TimeSpan / machineIds.Count() / UnitAvgtime) * 100 ?? 0, 2).ToString();
                    }
                    else
                    {
                        nameValueDan.percent = "0";
                    }
                    result.level.running.Add(nameValue);

                    result.dan.running.Add(nameValueDan);
                }

                result.level.title.Add(levelSection.title);
                result.dan.title.Add(levelSection.title);

                var count = levels.Count;
                result.dan.color = ColorHelper.GetColors(count);
                result.level.color = ColorHelper.GetColors(count);
            }

            result.qie = responses;

            return result;
        }

        private async Task<DashboardGaoboStatus1> GetGaoboStatus1(IEnumerable<int> machineIds)
        {
            var result = new DashboardGaoboStatus1
            {
                status = await GetMachineRunningStatusAsync(machineIds)
            };

            var redisRepository = new CNCEquipmentStateRepository(_companyId, _projectId);
            var machineStates = redisRepository.GetCNCEquipmentStates(machineIds);
            var validMachines = _machineRepository.GetNCLevelSectionNames(machineIds, _projectId);
            var machineDatas = validMachines.OrderBy(m => m.machine_name).ToList();
            if (!machineDatas.Any())
            {
                return result;
            }
            foreach (var machine in machineDatas)
            {
                var machineReturn = new MachineState();
                var machineState = machineStates.FirstOrDefault(q => q.MachineId == machine.machine_id);
                if (machineState != null)
                {
                    machineReturn = Mapper<CNCEquipmentState, MachineState>.Map(machineState);
                    machineReturn.Staus = ResetMachineStatus(machineState.Status, machineState.LastUpdateTime);
                    machineReturn.machineTitle = machine.lastSectionTitle;
                }
                else
                {
                    machineReturn.MachineId = machine.machine_id;
                    machineReturn.machineTitle = machine.lastSectionTitle;
                }
                result.status2.Add(machineReturn);
            }

            return result;
        }

        private async Task<DashboardAllProductLineResult> GetAllProductLineResult(DateTime dtStart, DateTime dtEnd, IEnumerable<int> sectionIds)
        {
            var result = new DashboardAllProductLineResult();

            var machines = new List<int>();
            foreach (var sectionId in sectionIds)
            {
                var mids = _machineRepository.GetNCMachinIdsBySectionId(sectionId, 0, _projectId);
                machines.AddRange(mids);
            }
            var machineIds = machines.Distinct();

            var machineStatus = await GetMachineRunningStatusAsync(machineIds);
            result.iszy = machineStatus.iszy;
            result.last_data = machineStatus.last_data;
            result.listAll = machineStatus.listAll;
            result.zy_data = machineStatus.zy_data;

            var redisRepository = new CNCEquipmentStateRepository(_companyId, _projectId);
            var machineStates = redisRepository.GetCNCEquipmentStates(machineIds);

            var repositoey = new SliceSateRepository(_companyId, _projectId);
            var sliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, dtStart.ToString(ParameterConstant.DateTimeFormat),
                dtEnd.ToString(ParameterConstant.DateTimeFormat));

            //var times = _timeRepository.GetRestTimesByMachine(machineIds, _projectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, _projectId);
            foreach (var sectionId in sectionIds)
            {
                var configs = _productionConfigRepository.GetList(q =>
                    q.projectid == _projectId && q.status == (int)RowState.Valid
                                             && q.production_section_id == sectionId);
                var listConfigs = new List<DashboardDbProduction3List>();
                foreach (var config in configs)
                {
                    var machineState = machineStates.FirstOrDefault(m => m.MachineId == config.machine_id);
                    double oee1 = 0;
                    if (sliceSates != null && sliceSates.Any())
                    {
                        var oee = OeeManager.GetOeeByTime(dtStart, dtEnd, sliceSates, new List<int> { config.machine_id }, null, times);
                        oee1 = oee.OEE1;
                    }

                    listConfigs.Add(new DashboardDbProduction3List
                    {
                        h = config.h,
                        machine_id = config.machine_id,
                        machine_section_id = config.machine_section_id,
                        machine_section_title = config.machine_section_title,
                        production_section_id = config.production_section_id,
                        production_section_title = config.production_section_title,
                        w = config.w,
                        y = config.y,
                        x = config.x,
                        Status = machineState != null ? ResetMachineStatus(machineState.Status, machineState.LastUpdateTime) : 0,
                        time_lag = oee1
                    });
                }



                result.product[sectionId] = listConfigs;
            }

            return result;
        }

        private DashboardProductionBeatResult GetDashboardProductionBeat(int sectionId, int machineId, DateTime dtStart, DateTime dtEnd)
        {
            var result = new DashboardProductionBeatResult();
            var configs = _productionConfigRepository.GetList(q =>
                q.projectid == _projectId && q.status == (int)RowState.Valid
                                         && q.production_section_id == sectionId);
            if (!configs.Any())
            {
                result.ret = 3;
                result.code = "800319";
                return result;
            }

            foreach (var config in configs.ToList())
            {
                var conf = Mapper<siger_project_production_configuration, ProductionBeat>.Map(config);
                var beat = _beatSetRepository.Get(q => q.machineID == config.machine_id && q.status == (int)RowState.Valid
                                                                                        && q.start_time <= dtEnd && q.end_time >= dtEnd);
                conf.besat = beat == null ? "NA" : beat.standard_besat.ToString();

                result.product_list.Add(conf);
            }

            var left = GetBeatLeft(machineId, dtStart, dtEnd);
            if (left == null)
            {
                result.ret = 4;
                result.code = "800320";
                return result;
            }

            result.product_name_text = left.product_name_text;
            result.daily_standard_output = left.daily_standard_output;
            result.process_number = left.process_number;
            result.planNum = left.planNum;
            result.productionNum = left.productionNum;
            result.YieldRate = left.YieldRate;

            return result;
        }

        private BeatTimeLeft GetBeatLeft(int machineId, DateTime dtStart, DateTime dtEnd)
        {
            var left = new BeatTimeLeft();

            var productRep = new ProductRepository(_companyId, _projectId);
            var yields = productRep.GetYieldByMachine(machineId, dtStart.ToString(ParameterConstant.DateTimeFormat), dtEnd.ToString(ParameterConstant.DateTimeFormat));

            var programs = yields.Select(m => m.programCode).Distinct().ToList();

            var beatProgram = _beatSetRepository.GetList(q =>
                q.machineID == machineId && programs.Contains(q.process_number) && q.status == (int)RowState.Valid
                && q.start_time <= dtEnd && q.end_time >= dtEnd).FirstOrDefault();
            if (beatProgram == null)
            {
                return null;
            }

            left.product_name_text = beatProgram.product_name_text;
            left.daily_standard_output = beatProgram.daily_standard_output;
            left.process_number = beatProgram.process_number;
            var hours = (dtEnd - dtStart).TotalHours;
            var planNumber = beatProgram.daily_standard_output / 24;
            var plan = planNumber * hours;
            left.planNum = Math.Round(plan, 0);
            var outputs = yields.Sum(m => m.yield * beatProgram.yieldrate);
            left.productionNum = outputs;
            left.YieldRate = Math.Round(left.planNum <= 0 ? 0 : outputs / left.planNum * 100, 2);
            left.yieldradio = beatProgram.yieldrate;
            return left;
        }

        private async Task<DashboardTimeGoResult> GetDashboardTimeGoResult(int machineId, DateTime dtStart, DateTime dtEnd)
        {
            var result = new DashboardTimeGoResult();
            //left
            var left = GetBeatLeft(machineId, dtStart, dtEnd);
            if (left == null)
            {
                result._left.ret = 0;
            }
            else
            {
                result._left.ret = 1;
                result._left.product_name_text = left.product_name_text;
                result._left.daily_standard_output = left.daily_standard_output;
                result._left.process_number = left.process_number;
                result._left.planNum = left.planNum;
                result._left.productionNum = left.productionNum;
                result._left.YieldRate = left.YieldRate;
            }

            //right
            var timeIng = (dtEnd - dtStart).TotalSeconds;
            var step = Math.Ceiling(timeIng / 3600);

            var productRep = new ProductRepository(_companyId, _projectId);
            var totalYield = 0;

            for (int i = 0; i < step; i++)
            {
                var startTime = dtStart.AddHours(i);
                var endTime = startTime.AddHours(1);
                if (endTime >= dtEnd)
                {
                    endTime = dtEnd;
                }
                var yield = await productRep.GetYieldsByMachineAsync(machineId, startTime.ToString(ParameterConstant.DateTimeFormat), endTime.ToString(ParameterConstant.DateTimeFormat));

                var yieldNum = new YieldNum
                {
                    yield_num = yield * (left == null ? 1 : left.yieldradio),
                    yield_time = i + 1,
                    yield_title = 0
                };
                result._right.yieldNum.Add(yieldNum);
                totalYield += yield;
            }

            result._right.OnAverage = Math.Round(totalYield / step, 2);

            return result;

        }

        private async Task<DashboardWorkShopResult> GetDashboardWorkShopResult(DateTime startTime, DateTime endTime, DateTime startMonthTime,
            int sectionId)
        {
            var result = new DashboardWorkShopResult();
            var machineIds = _machineRepository.GetNCMachinIdsBySectionId(sectionId, 0, _projectId,true);
            if (!machineIds.Any())
            {
                return result;
            }

            //res_1
            result.res_1 = await GetMachineRunningStatusAsync(machineIds);

            //res_2
            result.res_2 = await GetProductionLine2Result(startTime, endTime, startMonthTime, machineIds);

            //res_3
            result.res_3 = await GetProductionLine4Result(startTime, endTime, machineIds);

            //res_4
            var slice = await SliceManager.GetMachineSlice(startTime, endTime, machineIds, _companyId, _projectId, string.Empty);
            result.res_4.num1 = slice.data.num1;
            result.res_4.num2 = slice.data.num2;
            result.res_4.num3 = slice.data.num3;
            result.res_4.num4 = slice.data.num4;
            result.res_4.num5 = slice.data.num5;

            //res_5
            var monthResult = await OneDayProductionLine5(startMonthTime, endTime, machineIds);
            result.res_5.month = monthResult; //本月

            var oneMonthResult = await OneDayProductionLine5(startMonthTime.AddMonths(-1), startMonthTime.AddSeconds(-1), machineIds);
            result.res_5.onemonth = oneMonthResult; //上月

            return result;
        }

        private async Task<OneDayProductionLine5> OneDayProductionLine5(DateTime startTime, DateTime endTime, IEnumerable<int> machineIds)
        {
            var result = new OneDayProductionLine5();
            var machines = _machineRepository.GetNCLevelSectionNames(machineIds, _projectId);
            var validMachineIds = machines.Select(m => m.machine_id);

            var repositoey = new SliceSateRepository(_companyId, _projectId);
            var daySliceSates = await repositoey.GetCncSliceSatesAsync(validMachineIds, startTime.ToString(ParameterConstant.DateTimeFormat), endTime.ToString(ParameterConstant.DateTimeFormat));

            foreach (var levelMachineId in machineIds)
            {
                var machine = machines.FirstOrDefault(m => m.machine_id == levelMachineId);
                if (machine != null)
                {
                    var machineSlice = daySliceSates.Where(m => m.MachineID == machine.machine_id);
                    var dayStatus = SliceManager.GetMachineStatusHold(new List<int> { levelMachineId }, startTime, endTime, machineSlice);
                    var nameValue = new NameValue
                    {
                        name = machine.lastSecondSectionTitle + "-" + machine.lastSectionTitle
                    };

                    if (dayStatus == null)
                    {
                        //level
                        result.running.Add(nameValue);
                    }
                    else
                    {
                        var running = dayStatus.FirstOrDefault(q => q.Status == MachineRunningStatus.Running);
                        //level
                        nameValue.value = Math.Round(running?.TimeSpan / 3600 ?? 0, 2);
                        result.running.Add(nameValue);
                    }
                    //result.title.Add(machine.machine_name);
                    //不看设备看工位
                    result.title.Add(machine.lastSectionTitle);
                }
            }

            return result;
        }

        [HttpGet]
        public IActionResult PmTitle(int machineId)
        {
            var result = new PmTitle();

            var config = _productionConfigRepository.Get(m => m.machine_id == machineId && m.status == (int)RowState.Valid);
            if (config != null)
            {
                result.machine_section_title = config.machine_section_title;
                result.production_section_title = config.production_section_title;
            }
            //取最后一个程序号
            var repository = new ProductRepository(_companyId, _projectId);
            result.program = repository.GetProgramNo(machineId);

            return new ObjectResult(result);
        }

        [HttpGet]
        public async Task<IActionResult> PostSliceFigure(int machineId)
        {
            var dtStartTime = DateTime.Parse(DateTime.Now.ToString(ParameterConstant.DateFromZero));
            var dtEndTime = DateTime.Parse(DateTime.Now.ToString(ParameterConstant.DateTimeFormat));

            var result = await GetDashboardSliceStatusResultAsync(dtStartTime, dtEndTime, new List<int> { machineId });

            return new ObjectResult(result);
        }

        [HttpGet]
        public async Task<IActionResult> PostSlicePillarsTable(int machineId)
        {
            var dtStartSlice = DateTime.Now.AddDays(-7);
            var dtEndSlice = DateTime.Now;
            var slice = await GetSliceSatesAsync(new List<int> { machineId }, dtStartSlice, dtEndSlice);

            return new ObjectResult(slice);
        }

        [HttpGet]
        public IActionResult PoliceTable(int machineId)
        {
            var result = new List<ResponseGetMachineAlarmList>();
            var condition = new CncAlarmAnalysResultCondition
            {
                STime = DateTime.Now.ToString(ParameterConstant.DateFromZero),
                ETime = DateTime.Now.ToString(ParameterConstant.DateTimeFormat),
                MachinIds = new List<int> { machineId },
            };

            var cncExceptionRepository = new AlarmAnalysResultRepository(_companyId, _projectId);
            var exceptions = cncExceptionRepository.GetNoPagedCncExceptionParamsSates(condition).Take(15);
            foreach (var exception in exceptions)
            {
                var machine = _machineRepository.Get(q =>
                    q.id == exception.machineId && q.projectid == _projectId && q.status == (int)RowState.Valid && q.category == (int)MachineCategory.NC);
                var entity = new ResponseGetMachineAlarmList
                {
                    id = exception.id,
                    MachineCode = machine == null ? "" : machine.code,
                    Code = exception.code,
                    Message = exception.message,
                    Duration = UnixTimeHelper.GetTimeBySecond((int)(exception.Etime - exception.Stime).TotalSeconds),
                    Active = exception.status,
                    StartTime = exception.Stime.ToString(ParameterConstant.DateTimeFormat),
                    EndTime = exception.Etime.ToString(ParameterConstant.DateTimeFormat),
                    FaultContent = exception.FaultContent,
                    FaultSolution = exception.FaultSolution,
                    FaultReason = exception.FaultReason,
                };

                result.Add(entity);
            }
            return new ObjectResult(result);
        }

        private IEnumerable<int> GetMachineIds(string comb_page_id, string page_patial_code)
        {
            var condition = _combPageConditionRepository.Get(q => q.page_patial_code == page_patial_code && q.comb_page_id == comb_page_id
                                                                                                               && q.status == (int)RowState.Valid);
            if (string.IsNullOrWhiteSpace(condition?.condition))
            {
                return new List<int>();
            }

            var ids = condition.condition.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);

            return ids.Select(id => id.ToInt()).ToList();
        }

        /// <summary>
        /// 利达大屏,左侧熔炉
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetDieCastingBoard1(string comb_page_id, int projectid)
        {
            var project = _projectRepository.Get(q => q.id == projectid && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(RequestEnum.ProjectNotFound);
            }

            _companyId = project.companyid.ToInt();
            _projectId = project.id;

            var result = new List<ResponseGetDieCastingMachine>();
            var machineIds = GetMachineIds(comb_page_id, "furnace_diecasting_1");
            if (!machineIds.Any())
            {
                return new ObjectResult(result);
            }

            var rep = new CNCPressureTemperatureRepository(_companyId, _projectId);
            var machinePressures = rep.GetCncPressureTemperatures(machineIds).ToList();

            var machines = _machineRepository.GetList(q => machineIds.Contains(q.id) && q.projectid == _projectId && q.status == (int)RowState.Valid).ToList();
            if (!machines.Any())
            {
                return new ObjectResult(result);
            }
            var dicValues = _combPageConditionRepository.GetDictValue(AccDictCost.FurnaceTempLimit, _projectId).ToList();
            foreach (var mn in machines.OrderBy(m => m.title))
            {
                var machine = machines.FirstOrDefault(q => q.id == mn.id);
                if (machine == null)
                {
                    continue;
                }

                var pressure = machinePressures.FirstOrDefault(q => q.mn == machine.id);
                if (pressure == null || DateTime.Now.Subtract(DateTime.Parse(pressure.t)).TotalSeconds > 120)
                {
                    var entity = new ResponseGetDieCastingMachine
                    {
                        machine_name = machine.title,
                        counter = 0,
                        mould = "",
                        status = 3,
                        temperature = "NA",
                        over_limit = 0,
                        total_counter = 0,
                    };
                    result.Add(entity);
                }
                else
                {
                    var isOver = 0;
                    if (dicValues.Any() && dicValues.Count == 2)
                    {
                        var max = dicValues.FirstOrDefault(m => m.dkey.ToLower() == "max");
                        var min = dicValues.FirstOrDefault(m => m.dkey.ToLower() == "min");
                        if (max != null && pressure.temperature.ToDouble() > max.dval.ToDouble())
                        {
                            isOver = 1;
                        }
                        if (min != null && pressure.temperature.ToDouble() < min.dval.ToDouble())
                        {
                            isOver = 1;
                        }
                    }

                    var response = new ResponseGetDieCastingMachine
                    {
                        machine_name = machine.title,
                        status = pressure.opm,
                        temperature = pressure.temperature.ToStr(),
                        over_limit = isOver,
                    };
                    result.Add(response);
                }
            }

            return new ObjectResult(result);
        }

        /// <summary>
        /// 利达压铸大屏，左侧压铸机
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetDieCastingBoard2(string comb_page_id, int projectid)
        {
            var project = _projectRepository.Get(q => q.id == projectid && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(RequestEnum.ProjectNotFound);
            }

            _companyId = project.companyid.ToInt();
            _projectId = project.id;
            var result = new List<ResponseGetDieCastingMachine>();
            var machineIds = GetMachineIds(comb_page_id, "furnace_diecasting_2");
            if (!machineIds.Any())
            {
                return new ObjectResult(result);
            }

            var rep = new CNCPressureTemperatureRepository(_companyId, _projectId);
            var machinePressures = rep.GetCncPressureTemperatures(machineIds).ToList();

            var machines = _machineRepository.GetList(q => machineIds.Contains(q.id) && q.projectid == _projectId && q.status == (int)RowState.Valid).ToList();
            if (!machines.Any())
            {
                return new ObjectResult(result);
            }
            var dicValues = _combPageConditionRepository.GetDictValue(AccDictCost.FurnacePressureLimit, _projectId).ToList();
            foreach (var mn in machines.OrderBy(m => m.title))
            {
                var machine = machines.FirstOrDefault(q => q.id == mn.id);
                if (machine == null)
                {
                    continue;
                }
                var pressure = machinePressures.FirstOrDefault(q => q.mn == machine.id);
                if (pressure == null || DateTime.Now.Subtract(DateTime.Parse(pressure.t)).TotalSeconds > 120) //未采集到数据或者大于120秒钟
                {
                    var entity = new ResponseGetDieCastingMachine
                    {
                        machine_name = machine.title,
                        counter = 0,
                        mould = "",
                        pressure = "NA",
                        status = 3,
                        over_limit = 0,
                        total_counter = 0,
                    };
                    result.Add(entity);
                }
                else
                {
                    var isOver = 0;
                    if (dicValues.Any() && dicValues.Count == 2)
                    {
                        var max = dicValues.FirstOrDefault(m => m.dkey.ToLower() == "max");
                        var min = dicValues.FirstOrDefault(m => m.dkey.ToLower() == "min");
                        if (max != null && pressure.pressure.ToDouble() > max.dval.ToDouble())
                        {
                            isOver = 1;
                        }
                        if (min != null && pressure.pressure.ToDouble() < min.dval.ToDouble())
                        {
                            isOver = 1;
                        }
                    }

                    var usageRep = new MouldUsageDataRepository(_companyId, _projectId);
                    var machineRep = new MachineMouldUsageRepository(_companyId, _projectId);
                    var mouldConfig = new MouldConfigRepository(_companyId, _projectId);
                    var mould = mouldConfig.GetMachineMould(machine.id);
                    var mouldName = mould;
                    if (!string.IsNullOrWhiteSpace(mould))
                    {
                        var stock = _stockRepository.Get(q => q.serial_number == mould && q.projectid == _projectId);
                        if (stock != null)
                        {
                            mouldName = stock.material_name;
                        }
                    }
                    var response = new ResponseGetDieCastingMachine
                    {
                        machine_name = machine.title,
                        counter = machineRep.GetMachineMouldUsage(machine.id, mould), //当前设备上模具的总合模次数
                        mould = mouldName,
                        pressure = pressure.pressure.ToStr(),
                        status = pressure.opm,
                        over_limit = isOver,
                        total_counter = usageRep.GetMouldUsage(mould), //模具的总合模次数
                    };
                    result.Add(response);
                }
            }

            return new ObjectResult(result);
        }

        private async Task<GetOutPutEfficiencyResult> GetOutPutEfficiencyAsync(IEnumerable<int> machineIds, IEnumerable<ResponseKeyValue> shifts)
        {
            var response = new GetOutPutEfficiencyResult();
            if (!machineIds.Any() || !shifts.Any())
            {
                return response;
            }

            var shiftInfoes = ConvertShifts(shifts);
            if (!shiftInfoes.Any())
            {
                return response;
            }

            var validMachines = _machineRepository.GetNCLevelSectionNames(machineIds, _projectId).ToList();
            if (!validMachines.Any())
            {
                return response;
            }
            var validMachineIds = validMachines.Select(m => m.machine_id).ToList();
            var now = DateTime.Now;
            var i = (int)now.DayOfWeek;
            var date = DateTime.Parse(now.AddDays(-i).ToShortDateString());
            var end = DateTime.Parse(now.AddDays(6 - i).AddSeconds(-1).ToShortDateString());
            //var lastWeekStart = DateTime.Parse(date.AddDays(-7).ToShortDateString());
            //var lastWeekEnd = date.AddSeconds(-1);

            var repository = new DailySliceSateRepository(_companyId, _projectId);

            //效率
            var currentShift = shiftInfoes.FirstOrDefault(q => q.StartTime <= now && q.EndTime >= now);
            if (currentShift != null)
            {
                var eff = await GetListProductionEfficiencyAnalysis(validMachineIds,
                    currentShift.StartTime.ToString(ParameterConstant.DateTimeFormat),
                    now.ToString(ParameterConstant.DateTimeFormat));

                response.debug_loss = eff.debug_loss;
                response.idle_loss = eff.idle_loss;
                response.fault_loss = eff.fault_loss;
                response.shutdown_loss = eff.shutdown_loss;
                response.total_efficiency = eff.total_eff;
                response.shift = currentShift.Name;
            }

            //上周运行效率
            //var lastWeekRunning = await GetMachineProductionEfficiencyAnalysis(validMachineIds, lastWeekStart.ToString(ParameterConstant.DateTimeFormat), lastWeekEnd.ToString(ParameterConstant.DateTimeFormat));
            //response.machine_run.title.Add("Last week");
            //response.machine_run.running.Add(lastWeekRunning);

            //上周
            //var sliceSates = await repository.GetCncDailySliceSatesAsync(validMachineIds, lastWeekStart, end);
            //var lastWeekSlice = sliceSates.Where(q => q.date >= lastWeekStart && q.date <= lastWeekEnd);
            //response.slice.Add(OeeCalByDayHelper.GetMachineSlice(lastWeekStart, lastWeekEnd, lastWeekSlice, "Last week"));

            var sliceSates = await repository.GetCncDailySliceSatesAsync(validMachineIds, date, end);
            DateTime dtDay;
            for (dtDay = date.Date; dtDay.CompareTo(end) <= 0; dtDay = dtDay.AddDays(1).Date)
            {
                var title = dtDay.DayOfWeek.ToString();
                response.machine_run.title.Add(title);

                var dtEnd = dtDay.AddDays(1).AddSeconds(-1);
                if (dtEnd.Date == now.Date)
                {
                    var slice = await SliceManager.GetMachineSlice(dtDay, now, validMachineIds, _companyId, _projectId, title, 2);
                    response.slice.Add(slice);

                    var running = await GetMachineProductionEfficiencyAnalysis(validMachineIds, dtDay.ToString(ParameterConstant.DateTimeFormat), now.ToString(ParameterConstant.DateTimeFormat));
                    response.machine_run.running.Add(running);
                }
                else if (dtEnd.Date > now.Date)
                {
                    response.slice.Add(new MachineCanvasDataInfo
                    {
                        datetime = title,
                        data = new MachineSateCount
                        {
                            datetime = title,
                            num1 = 100,
                            num2 = 0,
                            num3 = 0,
                            num4 = 0,
                            num5 = 0,
                        }
                    });

                    response.machine_run.running.Add(0);
                }
                else
                {
                    var daySlice = sliceSates.Where(q => q.date <= dtEnd && q.date >= dtDay);
                    response.slice.Add(DaySliceManager.GetMachineSlice(dtDay, dtEnd, daySlice, title));

                    var running = await GetMachineProductionEfficiencyAnalysis(validMachineIds, dtDay.ToString(ParameterConstant.DateTimeFormat), dtEnd.ToString(ParameterConstant.DateTimeFormat));
                    response.machine_run.running.Add(running);
                }
            }

            return response;
        }

        private async Task<EfficiencySummary> GetListProductionEfficiencyAnalysis(IEnumerable<int> machineIds, string starttime, string end)
        {
            return await Task.Run(() =>
            {
                var success = DateTime.TryParse(starttime, out var dtStart);
                if (!success)
                {
                    throw new ServerException(500146);
                }
                success = DateTime.TryParse(end, out var dtEnd);
                if (!success)
                {
                    throw new ServerException(500146);
                }
                var result = new EfficiencySummary();

                var repository = new ProductRepository(_companyId, _projectId);
                var yields = repository.GetYileds(starttime, end, machineIds).ToList();

                var sliceRep = new SliceSateRepository(_companyId, _projectId);
                var slices = sliceRep.GetCncSliceSates(machineIds, starttime, end);

                var beats = _beatSetRepository.GetList(q => machineIds.Contains(q.machineID) && q.projectID == _projectId && q.status == (int)RowState.Valid
                                                            && q.start_time <= dtEnd && q.end_time >= dtEnd).ToList();
                var times = GetRestTimesBySections1(machineIds);
                double totalEfficiency = 0;
                double totalDebug = 0;
                double totalFault = 0;
                double totalShutdown = 0;
                var count = 0;

                var machineProgramNos = YieldMangaer.GetMachineProgramNos(yields, starttime, machineIds, UnixTimeHelper.GetUnixByShortDate(end));

                foreach (var machineProgramNo in machineProgramNos)
                {
                    var machineSlice = slices.Where(q => q.MachineID == machineProgramNo.machineId);

                    double runTimes = 0;
                    var rests = RestTimeManager.GetRunTimeByPrograms(times, machineProgramNo, dtStart, dtEnd, ref runTimes);

                    count++;
                    var machineYield = yields.Count(q => q.machineID == machineProgramNo.machineId && q.programCode == machineProgramNo.programNo);
                    var beat = beats.FirstOrDefault(q => q.machineID == machineProgramNo.machineId && q.process_number == machineProgramNo.programNo);
                    if (beat != null && runTimes != 0)
                    {
                        //0 关机 1 运行 2 调试 3 空闲 4 故障
                        var shutdown = SliceManager.GetResetTimesBySlice(0, machineProgramNo.TimeRanges, machineSlice, rests);
                        var debug = SliceManager.GetResetTimesBySlice(2, machineProgramNo.TimeRanges, machineSlice, rests);
                        var fault = SliceManager.GetResetTimesBySlice(4, machineProgramNo.TimeRanges, machineSlice, rests);
                        var run = SliceManager.GetResetTimesBySlice(1, machineProgramNo.TimeRanges, machineSlice, null);

                        runTimes = runTimes < 0 ? run : runTimes;

                        totalDebug += debug / runTimes;
                        totalFault += fault / runTimes;
                        totalShutdown += shutdown / runTimes;
                        totalEfficiency += (beat.standard_besat + beat.updown_besat) * machineYield / runTimes;
                    }
                }

                result.total_eff = count == 0 ? 0 : (totalEfficiency / count * 100).FormatDouble();
                result.debug_loss = count == 0 ? 0 : (totalDebug / count * 100).FormatDouble();
                result.fault_loss = count == 0 ? 0 : (totalFault / count * 100).FormatDouble();
                result.shutdown_loss = count == 0 ? 0 : (totalShutdown / count * 100).FormatDouble();
                result.idle_loss = count == 0 ? 0 : (100 - (result.total_eff + result.debug_loss + result.fault_loss + result.shutdown_loss)).FormatDouble();

                return result;
            });
        }

        private async Task<double> GetMachineProductionEfficiencyAnalysis(IEnumerable<int> machineIds, string starttime, string end)
        {
            return await Task.Run(() =>
            {
                var success = DateTime.TryParse(starttime, out var dtStart);
                if (!success)
                {
                    throw new ServerException(500146);
                }
                success = DateTime.TryParse(end, out var dtEnd);
                if (!success)
                {
                    throw new ServerException(500146);
                }
                double result = 0;

                var repository = new ProductRepository(_companyId, _projectId);
                var yields = repository.GetYileds(starttime, end, machineIds).ToList();

                var beats = _beatSetRepository.GetList(q => machineIds.Contains(q.machineID) && q.projectID == _projectId && q.status == (int)RowState.Valid
                                                            && q.start_time <= dtEnd && q.end_time >= dtEnd).ToList();
                var times = GetRestTimesBySections1(machineIds);
                double totalEfficiency = 0;
                var count = 0;

                var machineProgramNos = YieldMangaer.GetMachineProgramNos(yields, starttime, machineIds, UnixTimeHelper.GetUnixByShortDate(end));
                foreach (var machineProgramNo in machineProgramNos)
                {
                    double runTimes = 0;
                    RestTimeManager.GetRunTimeByPrograms(times, machineProgramNo, dtStart, dtEnd, ref runTimes);

                    count++;
                    var machineYield = yields.Count(q => q.machineID == machineProgramNo.machineId && q.programCode == machineProgramNo.programNo);
                    var beat = beats.FirstOrDefault(q => q.machineID == machineProgramNo.machineId && q.process_number == machineProgramNo.programNo);
                    if (beat != null && runTimes != 0)
                    {
                        var beatInfo = beat.standard_besat + beat.updown_besat;
                        totalEfficiency += beatInfo * machineYield / runTimes;
                    }
                }

                result = count == 0 ? 0 : Math.Round(totalEfficiency / count * 100, 1);

                return result;
            });
           
        }

        private IEnumerable<MachineRestInfo> GetRestTimesBySections(IEnumerable<int> machineIds)
        {
            var result = new List<MachineRestInfo>();

            var times = _timeRepository.GetList(m => machineIds.Contains(m.machineid) && m.status == (int)RowState.Valid).ToList();
            foreach (var machineId in machineIds)
            {
                var machineTimes = times.Where(q => q.machineid == machineId);
                foreach (var time in machineTimes)
                {
                    result.Add(new MachineRestInfo
                    {
                        BingTime = time.bing_time,
                        EndTime = time.end_time,
                        MachineId = machineId,
                        TimeType = (TimeType)time.typeid
                    });
                }
            }

            return result;
        }


        private IEnumerable<MachineRestInfo> GetRestTimesBySections1(IEnumerable<int> machineIds)
        {
            var result = new List<MachineRestInfo>();
            foreach (var machineId in machineIds)
            {
                var times = _timeAllocationRepository.GetList(m =>
                    m.machineid == machineId && m.status == (int)RowState.Valid && m.projectid == _projectId).ToList();
                foreach (var time in times)
                {
                    var types = time.typeids.Split(',');
                    foreach (var item in types)
                    {
                        var rest = _restTypeRepository.GetList(q => q.id == item.ToInt() && q.status == (int)RowState.Valid && q.projectid == _projectId).FirstOrDefault();
                        if (rest != null)
                        {
                            result.Add(new MachineRestInfo
                            {
                                BingTime = rest.startTime,
                                EndTime = rest.endTime,
                                MachineId = machineId,
                                SectionId = time.sectionid,
                                TimeType = (TimeType)rest.range
                            });
                        }

                    }

                }
            }
            return result;
        }
        /// <summary>
        /// MTS 质量看板 item 移动极值图
        /// </summary>
        /// <returns></returns>
        private async Task<AccQuantityDisplay> GetAccQuantityDisplay(int station, string Item, int count)
        {
            return await Task.Run(() =>
            {

                /*
               *    $Sample            array / json    样本数据
               *    $SampleCount       int             所有样本数据的 总数（ 多少条 ）
               *    $SampleCombined    int             所有样本数据的 总合
               *    $SampleMean        int             所有样本数据的 均值
               *    $sigma             int             样本标准差(公差)
               *
               *    $Range             array           从后往前，依次做差，求Range
               *    $RangeCount        int             Range 总数（ 多少条 ）
               *    $RangeCombined     int             Range  总合
               *    $RangeMean         int             Range 均值
               *
               *    $d2                int             恒定值
               *    $UCL               int             单值的上限
               *    $LCL               int             单值的下限
               *
               *    $parameterValue    int             参数中值
               *    $sigma             int             所有样本数据的公差
               *    $tolerance         int             公差宽度
               *    $process           int             过程宽度
               */
                var rounding = 4;
                var oqcItem = _sigerCheckItem.Get(f => f.Item.Equals(Item) && f.Station == station && f.CheckType.ToUpper() == "V");
                if (oqcItem == null)
                    throw new BadRequestException(CommonEnum.RecordNotFound);

                if (!double.TryParse(oqcItem.Min, out double MinValue) || !double.TryParse(oqcItem.Max, out double MaxValue))
                    throw new BadRequestException(CommonEnum.CheckFaild);

                var dtsData = _sigerTrSnTraceDetails.GetDtsItem(_projectId, station, Item, count);
                if (!dtsData.Any())
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                var realData = dtsData.Select(s => s.Value).ToList();
                if (!realData.Any())
                    throw new BadRequestException(CommonEnum.RecordNotFound);

                var ItemName = oqcItem.Item; //检测项
                var SampleData = ConvertValue(realData).ToList(); //样本数据
                var SampleCount = SampleData.Count();
                var SampleCombined = Math.Round(SampleData.Sum(), rounding); //样本总和
                var SampleMean = Math.Round(SampleCombined / SampleCount, rounding); //样本均值

                var Range = AccQuantityCalculationHelper.GetRang(SampleData, rounding);
                var RangeCount = Range.Count;
                var RangeCombined = Math.Round(Range.Sum(), rounding);
                var RangeMean = Math.Round(RangeCombined / RangeCount, rounding);

                var UCL = AccQuantityCalculationHelper.UCLx(SampleMean, RangeMean, rounding);
                var LCL = AccQuantityCalculationHelper.LCLx(SampleMean, RangeMean,  rounding);

                var RangUCL = AccQuantityCalculationHelper.UCLr(RangeMean, rounding);
                var RangLCL = 0d;

                var Sigma = AccQuantityCalculationHelper.GetVariance(SampleData, SampleMean, rounding);
                var ParameterValue = Math.Round(Math.Abs((MinValue + MaxValue) / 2), rounding);
                var Tolerance = MaxValue - MinValue;
                var Process = 6 * Sigma;

                var cp = Math.Round(Tolerance / Process, rounding);
                var cpu = Math.Round((MaxValue - SampleMean) / (3 * Sigma), rounding);
                var cpl = Math.Round((SampleMean - MinValue) / (3 * Sigma), rounding); //?
                var cpk = Math.Min(cpu, cpl);

                var result = new AccQuantityDisplay();
                result.AccQualityData_left_middle = AccQuantityCalculationHelper.accQualityMiddle(SampleData, UCL, LCL, SampleMean);
                result.AccQualityData_left_bottom = AccQuantityCalculationHelper.accQualityLefeBottom(Range, RangUCL, RangLCL, RangeMean);
                result.AccQualityData_right_top = AccQuantityCalculationHelper.AccQualityDatalefttop(SampleData, rounding);
                result.AccQualityData_right_bottom_left = AccQuantityCalculationHelper.accQualityBottomleft(SampleCount, SampleMean, Sigma, cp, cpk);
                result.AccQualityData_right_bottom_right = AccQuantityCalculationHelper.accQualitybottomright(MaxValue, MinValue, ParameterValue, cpu, cpl);

                return result;

                #region  DemoData
                //return new AccQuantityDisplay
                //{
                //    AccQualityData_left_middle = new AccQualityDataleftmiddle
                //    {
                //        LCLArray = new List<double> { -0.0045, -0.0045, -0.0045, -0.0045, -0.0045, -0.0045, -0.0045, -0.0045, -0.0045, -0.0045, -0.0045 },
                //        Sample = new List<double> { 0.01, 0.014, 0.008, 0.01, 0.012, 0.002, 0.011, 0.006, 0.009, 0.009, 0.01 },
                //        SampleMeanArray = new List<double> { 0.0088, 0.0088, 0.0088, 0.0088, 0.0088, 0.0088, 0.0088, 0.0088, 0.0088, 0.0088, 0.0088, 0.0088 },
                //        UCLArray = new List<double> { 0.0221, 0.0221, 0.0221, 0.0221, 0.0221, 0.0221, 0.0221, 0.0221, 0.0221, 0.0221, 0.0221, 0.0221 },
                //        xAxis = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }
                //    },
                //    AccQualityData_left_bottom = new AccQualityDataleftbottom
                //    {
                //        Range = new List<double> { 0.004, 0.006, 0.002, 0.002, 0.01, 0.009, 0.005, 0.003, 0, 0.001, 0.002, 0, 0.002, 0.001, 0.004, 0.01 },
                //        RangeLCLArray = new List<int> { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                //        RangeMeanArray = new List<double> { 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 },
                //        RangeUCLArray = new List<double> { 0.0163, 0.0163, 0.0163, 0.0163, 0.0163, 0.0163, 0.0163, 0.0163, 0.0163, 0.0163, 0.0163, 0.0163 },
                //        xAxis = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }
                //    },
                //    AccQualityData_right_bottom_left = new AccQualityDatarightbottomleft
                //    {
                //        SampleMean = 0.0088,
                //        SampleCount = 99,
                //        cp = 0.979,
                //        cpk = 0.5762,
                //        sigma = 0.0051
                //    },
                //    AccQualityData_right_bottom_right = new AccQualityDatarightbottomright
                //    {
                //        cpl = 0.5762,
                //        cpu = 1.3818,
                //        parameterValue = 0.015,
                //        right_foot_offline = 0,
                //        right_foot_online = 0.03
                //    }
                //};
                #endregion

            });
        }
        /// <summary>
        ///  转换类型
        /// </summary>
        /// <param name="Source"></param>
        /// <returns></returns>
        private List<double> ConvertValue(List<string> Source)
        {
            var result = new List<double>();
            for (var i = 0; i < Source.Count; i++)
            {
                if (!double.TryParse(Source[i], out double value))
                    continue;
                result.Add(value);
            }
            return result;
        }
        /// <summary>
        /// SKF设备看板(传pid)
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> GetRigStatusMonitor(int projectid, string patial_code)
        {
            var ret = new ResponseRigStatusMonitor();
            //var lineModel = _levelSection.Get(f => f.id.Equals(line) && f.status == (int)RowState.Valid);
            //if (lineModel == null)//排除无效产线
            //{
            //    throw new BadRequestException(RequestEnum.LineNotNull);
            //}
            var systemConfig = _systemConfigRepository.Get(q =>
                q.key == SystemConfigKey.SkfDashboardTarget && q.status == (int)RowState.Valid);
            ret.Target = systemConfig == null ? "000" : systemConfig.value;
            _projectId = projectid;
            var project = _projectRepository.Get(q => q.id == _projectId && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(RequestEnum.ProjectNotFound);
            }
            _companyId = project.companyid.ToInt();
            var sections = _levelSection.GetList(f => f.projectid.Equals(_projectId) && f.status == (int)RowState.Valid).Select(s => s.id).Distinct();
            var mids = _levelSectionMachine.GetList(f => f.status == (int)RowState.Valid && sections.Contains(f.section_id)).Select(s => s.machine_id).Distinct().ToList();
            var now = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
            var dtStart = now.AddDays(-now.DayOfYear + 1);
            var dtEnd = now.AddYears(1).AddDays(-now.AddYears(1).DayOfYear);
            var dailyRep = new DailySliceSateRepository(_companyId, _projectId);
            var sliceSates = await dailyRep.GetCncDailySliceSatesAsync(mids, dtStart, dtEnd);
            var machinecount = sliceSates.GroupBy(g => g.machineID).Count();
            var actulal = sliceSates.Sum(s => s.run);
            if (sliceSates.Count() != 0)
            {
                actulal = actulal / machinecount;
                actulal = actulal / (UnixTimeHelper.GetUnixByShortDate(now.ToStr()) - UnixTimeHelper.GetUnixByShortDate(dtStart.ToStr()));
                ret.Actual = Math.Round(actulal * 100, 0).ToString("000");
                ret.Actual_YTD = ret.Actual;
            }
            else
            {
                ret.Actual = "000";
                ret.Actual_YTD = "000";
            }
            var start = DateTime.Now.AddDays(1 - DateTime.Now.Day).Date;
            var slice = sliceSates.Where(f => f.date >= start && f.date <= now);
            var month = slice.Sum(s => s.run);
            if (slice.Count() != 0)
            {
                month = month / slice.Count();
                month = month / (UnixTimeHelper.GetUnixByShortDate(now.ToStr()) - UnixTimeHelper.GetUnixByShortDate(start.ToStr()));
                ret.Monthly = Math.Round(month * 100, 0).ToString("000");
            }
            else
            {
                ret.Monthly = "000";
            }

            var pageId = _dashboardCombRepository.GetPageIdByCode(patial_code);
            var configs = _productionConfigRepository.GetList(q => q.projectid == _projectId && q.status == (int)RowState.Valid && q.page_id == pageId).ToList();
            var redisRepository = new CNCEquipmentStateRepository(_companyId, _projectId);
            int machine_count = 0;
            if (mids.Any())
            {
                var machines = _machineRepository.GetList(f => mids.Contains(f.id)).ToList();
                machine_count += machines.Count;
                var machineStates = redisRepository.GetCNCEquipmentStates(machines.Select(s => s.id));
                var repairs = _repairRepository.GetList(t => mids.Contains(t.machineid) && t.projectid == _projectId && t.status > 0 &&
                    t.status < (int)MachineRepairStatus.WaitingForFeedback).ToList();

                var planSigns = _planSignRepository.GetList(t => t.projectid == _projectId && t.status == (int)RowState.Valid &&
                    mids.Contains(t.machine_id) && t.create_time >= UnixTimeHelper.GetTodayUnix()).ToList();
                var signMachineIds = planSigns.Select(t => t.machine_id).ToList();
                foreach (var machine in machines)
                {
                    var machineStatus = new ResponseMachineStatus
                    {
                        mid = machine.id,
                        name = machine.title,
                        code = _machineExtendRepository.Get(f => f.machine_id.Equals(machine.id) && f.status == (int)RowState.Valid)?.machine_shortname ?? "N/A",
                        MaintenanceState = (int)PlanStatus.Normal,
                    };
                    //传感器状态
                    machineStatus.SensorState = (int)SensorStatus.Normal;
                    var sensorStatess = _sensorParameter.GetList(f => f.status > 0 && f.mid.Equals(machine.id)).ToList();
                    if (sensorStatess.Any())
                    {
                        if (sensorStatess.Count(t => t.status == (int)SensorStatus.OverDue) > 0)
                        {
                            machineStatus.SensorState = (int)SensorStatus.OverDue;
                        }
                        else if (sensorStatess.Count(t => t.status == (int)SensorStatus.WaitMark) > 0)
                        {
                            machineStatus.SensorState = (int)SensorStatus.WaitMark;
                        }
                    }
                    //设备状态
                    var machineState = machineStates.FirstOrDefault(q => q.MachineId == machine.id);
                    var runState = machineState?.Status ?? (int)SkfMachineRunningStatus.Shutdown;
                    if (signMachineIds.Contains(machine.id) || sensorStatess.Count(t => t.status == (int)SensorStatus.Marking) > 0)
                    {
                        runState = (int)SkfMachineRunningStatus.MaintainSensor;
                    }
                    var repair = repairs.Where(t => t.machineid == machine.id).ToList();
                    if (repair.Any())
                    {
                        runState = (int)SkfMachineRunningStatus.Repairing;
                    }
                    machineStatus.RunState = runState;
                    //填写设备位置
                    var config = configs.FirstOrDefault(f => f.machine_id.Equals(machine.id));
                    if (config != null)
                    {
                        machineStatus.x = config.x.ToStr();
                        machineStatus.y = config.y.ToStr();
                        machineStatus.w = config.w.ToStr();
                        machineStatus.v = config.v.ToStr();
                        machineStatus.h = config.h.ToStr();
                    }
                    //设备保养状态填写
                    var planModel = _planTime.GetPlanInformation(0, machine.id, 0, Convert.ToInt32(UnixTimeHelper.ConvertDataTimeLong(DateTime.Now.AddDays(1))) - 1, _projectId).ToList();
                    if (planModel.Any())
                    {
                        if (planModel.Count(t => t.information == (int)PlanStatus.Overdue) > 0)
                        {
                            machineStatus.MaintenanceState = (int)PlanStatus.Overdue;
                        }
                        else if (planModel.Count(t => t.information == (int)PlanStatus.UnExecuted) > 0)
                        {
                            machineStatus.MaintenanceState = (int)PlanStatus.UnExecuted;
                        }
                        else
                        {
                            machineStatus.MaintenanceState = (int)PlanStatus.Normal;
                        }
                    }
                    ret.Add(machineStatus);
                }
            }
            ret.today_time = DateTime.Now.ToString(ParameterConstant.DateFormat);
            ret.machine_count = machine_count.ToString("000");
            return new ObjectResult(ret);
        }
        /// <summary>
        /// MTTR
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult KpiTrendMTTR(int projectid)
        {
            _projectId = projectid;
            var mids = _machineRepository.GetList(f => f.projectid.Equals(_projectId) && f.status == (int)RowState.Valid).Select(s => s.id);
            var ret = new ResponsKpiTrend();
            var now = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
            var dtStart = now.AddDays(-now.DayOfYear + 1);
            var dtEnd = now.AddYears(1).AddDays(-now.AddYears(1).DayOfYear);
            var startTime = UnixTimeHelper.GetUnixByShortDate(dtStart.ToStr());
            var endTime = UnixTimeHelper.GetUnixByShortDate(dtEnd.ToStr());
            var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, 2);
            var repairs = _repairRepository.GetRepairsForMTTR(mids, startTime, endTime,
                0, 0, 0, _projectId);
            for (var i = 0; i < dates.Count; i++)
            {
                DateTime start;
                DateTime end;
                start = dates[i].AddDays(1 - dates[i].Day);
                end = dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1); //到月底
                ret.X.Add(start.ToString("MMM", CultureInfo.CreateSpecificCulture("en-GB")));
                ret.Y1.Add(GetMachineMTTRBF(start, end, repairs, 30));
                ret.Y2.Add(GetMachineMTTRBF(start, end, repairs, 30, 2));
            }
            return new ObjectResult(ret);
        }
        /// <summary>
        /// RepairTimes
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult KpiTrendRepairTimes(int projectid)
        {
            _projectId = projectid;
            var mids = _machineRepository.GetList(f => f.projectid.Equals(_projectId) && f.status == (int)RowState.Valid).Select(s => s.id);
            var ret = new ResponsKpiTrend();
            var now = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
            var dtStart = now.AddDays(-now.DayOfYear + 1);
            var dtEnd = now.AddYears(1).AddDays(-now.AddYears(1).DayOfYear);
            var startTime = UnixTimeHelper.GetUnixByShortDate(dtStart.ToStr());
            var endTime = UnixTimeHelper.GetUnixByShortDate(dtEnd.ToStr());
            var model = _repairRepository.GetList(f => f.projectid.Equals(_projectId) && f.status != (int)RowState.Invalid && f.createtime >= startTime && f.createtime <= endTime);
            var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, 2);
            for (var i = 0; i < dates.Count; i++)
            {
                DateTime start;
                DateTime end;
                start = dates[i].AddDays(1 - dates[i].Day);
                end = dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1); //到月底
                startTime = UnixTimeHelper.GetUnixByShortDate(start.ToStr());
                endTime = UnixTimeHelper.GetUnixByShortDate(end.ToStr());
                ret.X.Add(start.ToString("MMM", CultureInfo.CreateSpecificCulture("en-GB")));
                ret.Y1.Add(model.Count(f => f.createtime >= startTime && f.createtime <= endTime));
                ret.Y2.Add(model.Count(f => f.createtime >= startTime && f.createtime <= endTime && f.status == (int)MachineRepairStatus.Completed));
            }
            return new ObjectResult(ret);
        }
        /// <summary>
        /// Utlization
        /// </summary>
        /// <param name="projectid"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> KpiTrendUtlization(int projectid)
        {
            _projectId = projectid;
            var project = _projectRepository.Get(q => q.id == _projectId && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(RequestEnum.ProjectNotFound);
            }
            _companyId = project.companyid.ToInt();
            var mids = _machineRepository.GetList(f => f.projectid.Equals(_projectId) && f.status == (int)RowState.Valid).Select(s => s.id);
            var ret = new ResponsKpiTrend();
            var now = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
            var dtStart = now.AddDays(-now.DayOfYear + 1);
            var dtEnd = now.AddYears(1).AddDays(-now.AddYears(1).DayOfYear);
            var dailyRep = new DailySliceSateRepository(_companyId, _projectId);
            var sliceSates = await dailyRep.GetCncDailySliceSatesAsync(mids, dtStart, dtEnd);
            var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, 2);
            for (var i = 0; i < dates.Count; i++)
            {
                DateTime start;
                DateTime end;
                start = dates[i].AddDays(1 - dates[i].Day);
                end = start.AddMonths(1).AddSeconds(-1); //到月底
                ret.X.Add(start.ToString("MMM", CultureInfo.CreateSpecificCulture("en-GB")));
                var diff = UnixTimeHelper.GetUnixByShortDate(end.ToStr()) - UnixTimeHelper.GetUnixByShortDate(start.ToStr());
                var slice = sliceSates.Where(f => f.date >= start && f.date <= end);
                var data = slice.Sum(s => s.run) / slice.Count() / diff;
                if (slice.Count() == 0)
                {
                    data = 0;
                }
                ret.Y1.Add(Math.Round(data, 2));
            }
            return new ObjectResult(ret);
        }
        /// <summary>
        /// CalibrationTime
        /// </summary>
        /// <param name="projectid"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> KpiTrendCalibrationTime(int projectid)
        {
            _projectId = projectid;
            var project = _projectRepository.Get(q => q.id == _projectId && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(RequestEnum.ProjectNotFound);
            }
            _companyId = project.companyid.ToInt();
            var mids = _machineRepository.GetList(f => f.projectid.Equals(_projectId) && f.status == (int)RowState.Valid).Select(s => s.id);
            var ret = new ResponsKpiTrend();
            var now = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
            var dtStart = now.AddDays(-now.DayOfYear + 1);
            var dtEnd = now.AddYears(1).AddDays(-now.AddYears(1).DayOfYear);
            var dailyRep = new DailySliceSateRepository(_companyId, _projectId);
            var sliceSates = await dailyRep.GetCncDailySliceSatesAsync(mids, dtStart, dtEnd);
            var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, 2);
            for (var i = 0; i < dates.Count; i++)
            {
                DateTime start;
                DateTime end;
                start = dates[i].AddDays(1 - dates[i].Day);
                end = dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1); //到月底
                ret.X.Add(start.ToString("MMM", CultureInfo.CreateSpecificCulture("en-GB")));
                var diff = UnixTimeHelper.GetUnixByShortDate(end.ToStr()) - UnixTimeHelper.GetUnixByShortDate(start.ToStr());
                var slice = sliceSates.Where(f => f.date >= start && f.date <= end);
                var rundata = slice.Sum(s => s.run) / slice.Count() / diff;
                var stopdata = slice.Sum(s => s.shutdown) / slice.Count() / diff;
                var data = 1 - rundata - stopdata;
                if (data == 1 || slice.Count() == 0)//排除无效数据
                {
                    data = 0;
                }
                ret.Y1.Add(Math.Round(data, 2));
            }
            return new ObjectResult(ret);
        }

        /// <summary>
        /// 故障率和使用率
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="list"></param>
        /// <param name="interal"></param>
        /// <param name="type">1: MTTR 2: MTBF</param>
        /// <returns></returns>
        private double GetMachineMTTRBF(DateTime start, DateTime end, IEnumerable<RepairListForMTTR> list, int interal, int type = 1)
        {
            if (!list.Any())
            {
                return 0;
            }

            var dtStart = UnixTimeHelper.ConvertDataTimeLong(start);
            var dtEnd = UnixTimeHelper.ConvertDataTimeLong(end);

            var repairs = list.Where(q => q.createtime >= dtStart && q.createtime <= dtEnd);
            var machineIds = repairs.Select(m => m.machineid).Distinct();
            if (!machineIds.Any())
            {
                return 0;
            }

            double totalNormalSeconds = 0;
            int totalNumber = repairs.Count();
            foreach (var machineId in machineIds)
            {
                var machineRepairs = repairs.Where(q => q.machineid == machineId).OrderBy(m => m.createtime)
                    .ToList();
                if (machineRepairs.Any())
                {
                    if (machineRepairs.Count == 1)
                    {
                        totalNormalSeconds = machineRepairs[0].checktime > dtEnd
                            ? dtEnd - machineRepairs[0].createtime
                            : machineRepairs[0].checktime - machineRepairs[0].createtime;
                    }
                    else
                    {
                        totalNormalSeconds += machineRepairs[0].createtime - dtStart;
                        for (int i = 0; i < machineRepairs.Count - 1; i++)
                        {
                            //排除被包含的记录
                            if (machineRepairs[i + 1].checktime > machineRepairs[i].checktime
                                && machineRepairs[i + 1].createtime > machineRepairs[i].checktime)
                            {
                                totalNormalSeconds +=
                                    machineRepairs[i].checktime - machineRepairs[i + 1].createtime;
                            }
                            else
                            {
                                totalNumber--;
                            }
                        }

                        totalNormalSeconds += machineRepairs[machineRepairs.Count - 1].checktime >= dtEnd
                            ? 0
                            : dtEnd - machineRepairs[machineRepairs.Count - 1].checktime;
                    }
                }
            }

            if (totalNumber > 0)
            {
                totalNormalSeconds = totalNormalSeconds / 60;

                if (type == 1)
                {
                    return Math.Round(totalNormalSeconds / totalNumber, 0);
                }

                var total = 24 * 60 * interal * totalNumber;
                if (total > totalNormalSeconds)
                {
                    return Math.Round((total - totalNormalSeconds) / totalNumber, 0);
                }

                return 0;
            }

            return 0;
        }

        private async Task<AllMachineRepairList> GetAlMachineRepairList(int projectid, int page, int pagesize)
        {
            return await Task.Run(() =>
            {
                var response = new AllMachineRepairList();

                var machines = _machineRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                var machineIds = machines.Select(t => t.id).ToList();
                var repairs = _repairRepository.GetList(t =>
                    t.status < (int)MachineRepairStatus.Completed && t.status > 0 && t.projectid == projectid &&
                    machineIds.Contains(t.machineid)).OrderBy(t => t.status).ToList();
                var machineStates = new List<MachineRepairData>();
                var faults = _faultTypeRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                foreach (var machine in machines)
                {
                    var minStatus = repairs.Where(t => t.machineid == machine.id).OrderBy(t => t.status).ToList();
                    if (minStatus.Any())
                    {
                        var repair = minStatus.First();
                        var faulttype = faults.FirstOrDefault(t => t.id == repair.faultid);
                        var faultmode = faults.FirstOrDefault(t => t.id == repair.real_faultid);
                        machineStates.Add(new MachineRepairData
                        {
                            machinename = machine.title,
                            failure_mode = faulttype == null ? faultmode?.title ?? "" : faulttype.title + (faultmode == null ? "" : " " + faultmode.title),
                            failure_time = UnixTimeHelper.ConvertIntDateTime(minStatus.First().createtime)
                        });
                    }
                }

                response.pagesize = pagesize;
                response.page = page;
                response.total = machineStates.Count;
                response.data = machineStates.Skip((page - 1) * pagesize).Take(pagesize).ToList();
                return response;
            });
        }

        [HttpGet]
        public async Task<MachineTypeRepairFaultAndRunState> MachineTypeCountByRepairRunState(int projectid, int companyid)
        {
            return await Task.Run(() =>
            {
                var res = new MachineTypeRepairFaultAndRunState();
                var machines = _machineRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                var machineIds = machines.Select(t => t.id).ToList();
                var repairs = _repairRepository.GetList(t =>
                    t.status < (int)MachineRepairStatus.Completed && t.status > 0 && t.projectid == projectid &&
                    machineIds.Contains(t.machineid)).OrderBy(t => t.status).ToList();

                var machineTypes = _machineTypeRepository.GetList(t => t.projectid == projectid &&
                    t.parentid > 0 && t.status == (int)RowState.Valid).ToList();

                var rep = new CNCEquipmentStateRepository(companyid, projectid);
                var cncStates = rep.GetCNCEquipmentStates();
                var runStates = cncStates.Where(t => t.Status == (int)MachineRunningStatus.Running).ToList();

                var failures = new List<MachineTypeRateInRepair>();
                var utilizes = new List<MachineTypeRunState>();

                foreach (var machineType in machineTypes)
                {
                    var machineids = machines.Where(t => t.typeid == machineType.id).Select(t => t.id).ToList();
                    var repair = repairs.Where(t => machineids.Contains(t.machineid)).ToList();
                    failures.Add(new MachineTypeRateInRepair
                    {
                        name = machineType.title,
                        count = repair.Count,
                        rate = 0
                    });
                    var runState = runStates.Where(t => machineids.Contains(t.MachineId)).ToList();
                    utilizes.Add(new MachineTypeRunState
                    {
                        name = machineType.title,
                        count = runState.Count,
                        rate = 0
                    });
                    res.NAMES.Add(machineType.title);
                }
                var failureTotal = failures.Sum(t => t.count);
                var utilizeTotal = utilizes.Sum(t => t.count);
                foreach (var failure in failures)
                {
                    res.failure.Add(new MachineTypeRateInRepair
                    {
                        name = failure.name,
                        count = failure.count,
                        rate = failureTotal > 0 ? Math.Round((failure.count / (double)failureTotal) * 100, 2) : 0
                    });
                }
                foreach (var utilize in utilizes)
                {
                    res.utilize.Add(new MachineTypeRunState
                    {
                        name = utilize.name,
                        count = utilize.count,
                        rate = utilizeTotal > 0 ? Math.Round((utilize.count / (double)utilizeTotal) * 100, 2) : 0
                    });
                }

                return res;
            });
        }

        private async Task<MachineSensorList> GetCalibrationStatusList(int projectid, int page, int pagesize)
        {
            return await Task.Run(() =>
            {
                var response = new MachineSensorList();

                var sensorStates = new List<MachineSensorData>();
                var sensors = _sensorParameter.GetList(t => t.projectid == projectid &&
                    (t.status == (int)SensorStatus.OverDue || t.status == (int)SensorStatus.WaitMark || t.status == (int)SensorStatus.Verification ||
                    t.status == (int)SensorStatus.Marking)).ToList();
                var sensorTypes = _sensorTypeRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                foreach (var sensor in sensors)
                {
                    var sensorType = sensorTypes.FirstOrDefault(t => t.id == sensor.typeid);
                    sensorStates.Add(new MachineSensorData
                    {
                        sensor = sensor.sensor_code,
                        sensor_type = sensorType?.title ?? "",
                        status = sensor.status,
                        last_calibration = sensor.mark_time > 0 ? UnixTimeHelper.ConvertIntDateTime(sensor.mark_time) : ""
                    });
                }

                response.pagesize = pagesize;
                response.page = page;
                response.total = sensorStates.Count;
                response.data = sensorStates.Skip((page - 1) * pagesize).Take(pagesize).ToList();
                return response;
            });
        }

        private async Task<DashboardMachineCanvasParetoInfoPagedResult> GetDashboardSliceStatusPageList(int page, int pagesize, int companyid, int projectid)
        {
            var dtStart = DateTime.Today;//"2020-02-10 00:00:00".ToDateTime();
            var dtEnd = DateTime.Now;//"2020-02-10 23:59:59".ToDateTime();
            var result = new DashboardMachineCanvasParetoInfoPagedResult
            {
                startTime = dtStart.ToString(ParameterConstant.DateTimeFormat),
                endTime = dtEnd.ToString(ParameterConstant.DateTimeFormat),
                total_time_span = (dtEnd - dtStart).TotalSeconds,
                page = page,
                pagesize = pagesize
            };

            var validMachines = _machineRepository.GetNCLevelSectionNames(0, _projectId);

            var machineIds = _machineRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid && t.category == (int)MachineCategory.NC)
                .Select(t => t.id).ToList();
            var canvas = await SliceManager.GetMachineSliceNew(dtStart, dtEnd, machineIds, validMachines, companyid, projectid);

            result.total = canvas.canvas.Count;
            result.canvas = canvas.canvas.Skip((page - 1) * pagesize).Take(pagesize).ToList();
            result.pareto = canvas.pareto.Skip((page - 1) * pagesize).Take(pagesize).ToList();

            return result;
        }

        private async Task<MachineMachineCalenderWeeklyList> GetMachineCalenderWeekly(int projectid, int page, int pagesize)
        {
            return await Task.Run(() =>
            {
                var res = new MachineMachineCalenderWeeklyList();
                var machines = _machineRepository.GetList(t => t.projectid == projectid && t.status == (int)RowState.Valid).ToList();
                var result = new List<MachineMachineCalenderWeekly>();
                foreach (var machine in machines)
                {
                    result.Add(new MachineMachineCalenderWeekly
                    {
                        machinename = machine.title,
                        calender_type = new List<int> { 1, 2, 3, 1, 2, 3, 1 }
                    });
                }
                res.page = page;
                res.pagesize = pagesize;
                res.total = result.Count;
                res.data = result.Skip((page - 1) * pagesize).Take(pagesize).ToList(); ;
                return res;
            });
        }
    }
}
