Пример #1
0
 private void TodayQueuePlan_OnOperatorPlanMetricsUpdated(object sender, QueuePlanEventArgs e)
 {
     if (OnOperatorPlanMetricsUpdated != null)
     {
         logger.Debug("Запуск обработчика для события [OperatorPlanMetricsUpdated] с кол-вом слушателей [{0}]",
             OnOperatorPlanMetricsUpdated.GetInvocationList().Length);
         OnOperatorPlanMetricsUpdated(this, new QueueInstanceEventArgs()
         {
             OperatorPlanMetrics = Mapper.Map<OperatorPlanMetrics, DTO.OperatorPlanMetrics>(e.OperatorPlanMetrics)
         });
     }
 }
Пример #2
0
        private void TodayQueuePlan_CurrentClientRequestPlanUpdated(object sender, QueuePlanEventArgs e)
        {
            if (OnCurrentClientRequestPlanUpdated != null)
            {
                var eventArgs = new QueueInstanceEventArgs()
                {
                    Operator = Mapper.Map<Operator, DTO.Operator>(e.Operator)
                };

                if (e.ClientRequestPlan != null)
                {
                    logger.Debug("Текущий план запроса клиента у оператора [{0}] [{1}]", e.Operator, e.ClientRequestPlan);
                    eventArgs.ClientRequestPlan = Mapper.Map<ClientRequestPlan, DTO.ClientRequestPlan>(e.ClientRequestPlan);
                }
                else
                {
                    logger.Debug("У оператора [{0}] отсутствуют текущие запросы", e.Operator);
                }

                logger.Debug("Запуск обработчика для события [CurrentClientRequestPlanUpdated] с кол-вом слушателей [{0}]",
                    OnCurrentClientRequestPlanUpdated.GetInvocationList().Length);
                OnCurrentClientRequestPlanUpdated(this, eventArgs);
            }
        }
Пример #3
0
 private void TodayQueuePlan_OnBuilded(object sender, QueuePlanEventArgs e)
 {
     try
     {
         string directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "queue");
         if (!Directory.Exists(directory))
         {
             Directory.CreateDirectory(directory);
         }
         string file = Path.Combine(directory, string.Format("queue-plan-{0:00000}.txt", TodayQueuePlan.Version));
         File.WriteAllLines(file, TodayQueuePlan.Report);
     }
     catch (Exception exception)
     {
         logger.Error(exception);
     }
 }
Пример #4
0
        /// <summary>
        /// Построить план очереди
        /// </summary>
        /// <returns></returns>
        public void Build(TimeSpan planTime)
        {
            PlanTime = planTime;

            Report = new List<string>()
            {
                string.Format("Построение плана очереди на дату {0:dd.MM.yyyy} и время {1:hh\\:mm\\:ss}, номер недели {2}", PlanDate, PlanTime, WeekNumber)
            };

            foreach (var o in OperatorsPlans)
            {
                clientRequests.AddRange(o.ClientRequestPlans.Select(p => p.ClientRequest));
                o.ClientRequestPlans.Clear();

                o.PlanTime = PlanTime;
                o.Interruptions = GetOperatorInterruptions(o.Operator);
            }

            clientRequests.AddRange(NotDistributedClientRequests.Select(n => n.ClientRequest));
            NotDistributedClientRequests.Clear();

            var conditions = new[] {
                new {
                    Name = "Вызываемые",
                    Predicate = new Predicate<ClientRequest>(r => r.State == ClientRequestState.Calling)
                },
                new {
                    Name = "Обслуживаемые",
                    Predicate = new Predicate<ClientRequest>(r => r.State == ClientRequestState.Rendering)
                },
                new {
                    Name = "Переданные",
                    Predicate = new Predicate<ClientRequest>(r => r.State == ClientRequestState.Redirected)
                },
                new {
                    Name = "Предварительная запись с определенными операторами",
                    Predicate = new Predicate<ClientRequest>(r => r.Type == ClientRequestType.Early && r.Operator != null)
                },
                new {
                    Name = "Предварительная запись",
                    Predicate = new Predicate<ClientRequest>(r => r.Type == ClientRequestType.Early)
                },
                new {
                    Name = "Живая очередь с приоритетом",
                    Predicate = new Predicate<ClientRequest>(r => r.Type == ClientRequestType.Live && r.IsPriority)
                },
                new {
                    Name = "Живая очередь",
                    Predicate = new Predicate<ClientRequest>(r => r.Type == ClientRequestType.Live)
                }
            };

            clientRequests = clientRequests.Distinct().ToList();

            foreach (var condition in conditions)
            {
                var conditionClientRequests = clientRequests
                    .Where(new Func<ClientRequest, bool>(condition.Predicate))
                    .OrderByDescending(p => p.Service.Priority)
                    .ThenBy(p => p.RequestTime)
                    .ThenBy(p => p.CreateDate);

                Report.Add(string.Format("Планируется по условию [{0}] [{1}] запросов", condition.Name, conditionClientRequests.Count()));

                foreach (var conditionClientRequest in conditionClientRequests)
                {
                    Report.Add(string.Format("Планируется запрос [{0}]", conditionClientRequest));

                    if (conditionClientRequest.RequestDate != PlanDate)
                    {
                        Report.Add("Дата запроса не соответствует дате плана очереди");
                        continue;
                    }

                    var schedule = GetServiceSchedule(conditionClientRequest.Service);

                    Report.Add(string.Format("Определено расписание для услуги [{0}]", schedule));

                    try
                    {
                        OperatorPlan targetOperatorPlan;

                        if (conditionClientRequest.Operator != null)
                        {
                            Report.Add(string.Format("Оператор {0} определен ранее для запроса", conditionClientRequest.Operator));

                            targetOperatorPlan = GetOperatorPlan(conditionClientRequest.Operator);
                        }
                        else
                        {
                            var serviceRenderingMode = conditionClientRequest.Type == ClientRequestType.Early
                                ? ServiceRenderingMode.EarlyRequests
                                : ServiceRenderingMode.LiveRequests;

                            var renderings = GetServiceRenderings(schedule, conditionClientRequest.ServiceStep, serviceRenderingMode);

                            Report.Add("Поиск потенциальных операторов");

                            var potentialOperatorsPlans = renderings
                                .Where(r => r.Operator.IsActive)
                                .Select(r => new
                                {
                                    OperatorPlan = OperatorsPlans.FirstOrDefault(o => o.Operator.Equals(r.Operator)),
                                    Priority = r.Priority
                                }).Where(r => r.OperatorPlan != null)
                                .ToList();

                            foreach (var p in potentialOperatorsPlans)
                            {
                                Report.Add(string.Format("{0} {1}", p.OperatorPlan.Operator, p.OperatorPlan.Operator.Online ? "в сети" : "не в сети"));
                            }

                            if (PlanDate == DateTime.Today && schedule.OnlineOperatorsOnly)
                            {
                                Report.Add("Операторы не в сети игнорируются");

                                potentialOperatorsPlans.RemoveAll(p => !p.OperatorPlan.Operator.Online);
                            }

                            if (potentialOperatorsPlans.Count() == 0)
                            {
                                Report.Add("Операторы не найдены");

                                throw new Exception("В системе нет операторов способных обработать запрос");
                            }

                            var requestTime = conditionClientRequest.RequestTime;

                            if (requestTime < planTime)
                            {
                                requestTime = planTime;
                            }

                            var operatorPlanMetrics = potentialOperatorsPlans
                                .Select(p => new
                                {
                                    OperatorPlan = p.OperatorPlan,
                                    NearTimeInterval = p.OperatorPlan.GetNearTimeInterval(requestTime, schedule, conditionClientRequest.Type, conditionClientRequest.Subjects),
                                    IsOnline = p.OperatorPlan.Operator.Online,
                                    Availability = p.OperatorPlan.CurrentClientRequestPlan == null || !p.OperatorPlan.CurrentClientRequestPlan.ClientRequest.InWorking,
                                    DayWorkload = p.OperatorPlan.Metrics.DailyWorkload,
                                    PlaningWorkload = p.OperatorPlan.Metrics.PlaningWorkload
                                })
                                .OrderBy(m => m.NearTimeInterval)
                                .ThenByDescending(m => m.IsOnline)
                                .ThenByDescending(m => m.Availability)
                                .ThenBy(m => m.PlaningWorkload)
                                .ToList();

                            Report.Add("Расчет метрик операторов");

                            foreach (var m in operatorPlanMetrics)
                            {
                                m.OperatorPlan.Metrics.Standing++;

                                Report.Add(string.Format("{0} {1}, ближайший интервал времени: {2:hh\\:mm\\:ss}, доступность: {3}, дневная нагрузка: {4:hh\\:mm\\:ss}, планируемая нагрузка: {5:hh\\:mm\\:ss}",
                                    m.OperatorPlan, m.IsOnline ? "в сети" : "не в сети", m.NearTimeInterval, m.Availability ? "свободен" : "занят", m.DayWorkload, m.PlaningWorkload));
                            }

                            targetOperatorPlan = operatorPlanMetrics.Select(m => m.OperatorPlan).First();
                        }

                        if (targetOperatorPlan != null)
                        {
                            targetOperatorPlan.AddClientRequest(conditionClientRequest, schedule);

                            Report.Add(string.Format("Оператор [{0}] назначен для [{1}]", targetOperatorPlan, conditionClientRequest));
                        }
                        else
                        {
                            throw new Exception("Не удалось определить целевой план оператора");
                        }
                    }
                    catch (Exception exception)
                    {
                        NotDistributedClientRequests.Add(new NotDistributedClientRequest(conditionClientRequest, exception.Message));
                    }

                    Report.Add(string.Empty);
                }

                clientRequests.RemoveAll(condition.Predicate);
            }

            foreach (var r in clientRequests)
            {
                NotDistributedClientRequests.Add(new NotDistributedClientRequest(r, "Ни один оператор не может обслужить запрос клиента"));
            }

            clientRequests.Clear();

            Report.Add(string.Empty);

            foreach (var o in OperatorsPlans)
            {
                if (o.CurrentClientRequestPlan != null)
                {
                    Report.Add(string.Format("{0} текущий запрос [{1}]", o.Operator, o.CurrentClientRequestPlan));
                }

                foreach (var p in o.ClientRequestPlans)
                {
                    Report.Add(string.Format("{0} запланирован в {1:hh\\:mm\\:ss} {2}", p.Position, p.StartTime, p));
                }
            }

            if (OnCurrentClientRequestPlanUpdated != null)
            {
                logger.Info("Запуск обработчика для события [OnCurrentClientRequestPlanUpdated] с кол-вом слушателей [{0}]",
                    OnCurrentClientRequestPlanUpdated.GetInvocationList().Length);

                foreach (var o in OperatorsPlans)
                {
                    var e = new QueuePlanEventArgs()
                    {
                        Operator = o.Operator
                    };

                    if (o.CurrentClientRequestPlan != null)
                    {
                        e.ClientRequestPlan = o.CurrentClientRequestPlan;
                    }

                    OnCurrentClientRequestPlanUpdated(this, e);
                }
            }

            if (OnOperatorPlanMetricsUpdated != null)
            {
                logger.Info("Запуск обработчика для события [OnOperatorPlanMetricsUpdated] с кол-вом слушателей [{0}]",
                    OnOperatorPlanMetricsUpdated.GetInvocationList().Length);

                foreach (var o in OperatorsPlans)
                {
                    OnOperatorPlanMetricsUpdated(this, new QueuePlanEventArgs()
                    {
                        OperatorPlanMetrics = o.Metrics
                    });
                }
            }

            Version++;

            logger.Info("Построение плана очереди завершено с версией [{0}]", Version);

            if (OnBuilded != null)
            {
                OnBuilded(this, new QueuePlanEventArgs());
            }
        }