using DressAtelierContracts.BindingModels; using DressAtelierContracts.BusinessLogicContracts; using DressAtelierContracts.SearchModels; using DressAtelierContracts.ViewModels; using DressAtelierDataModels.Enums; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace DressAtelierBusinessLogic.BusinessLogic { public class WorkImitation : IWorkImitation { private readonly ILogger _logger; private readonly Random _rnd; private IOrderLogic? _orderLogic; public WorkImitation(ILogger logger) { _logger = logger; _rnd = new Random(1000); } public void DoWork(IEmployeeLogic employeeLogic,IOrderLogic orderLogic) { _orderLogic = orderLogic; var employees = employeeLogic.ReadList(null); if(employees == null) { _logger.LogWarning("DoWork. List of employees is null"); return; } var orders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Accepted }); if(orders == null || orders.Count == 0) { _logger.LogWarning("DoWork. Orders is null or empty"); return; } _logger.LogDebug("DoWork for {Count} orders", orders.Count); foreach (var employee in employees) { Task.Run(() => EmployeeWorkAsync(employee, orders)); } } private async Task EmployeeWorkAsync(EmployeeViewModel employee, List orders) { if(_orderLogic == null || employee == null) { return; } await MoveOrderInWork(employee); await Task.Run(() => { foreach (var order in orders) { try { _logger.LogDebug("DoWork. Employee {ID} is trying to get an order {Order}", employee.ID, order.ID); _orderLogic.TakeOrderInWork(new OrderBindingModel { ID = order.ID, EmployeeID = employee.ID, }); Thread.Sleep(employee.WorkExperience * _rnd.Next(100, 1000) * order.Count); _logger.LogDebug("DoWork. Employee {ID} finished order {Order}", employee.ID, order.ID); _orderLogic.ReadyOrder(new OrderBindingModel { ID = order.ID }); Thread.Sleep(employee.Qualification * _rnd.Next(10, 100)); } catch (InvalidOperationException ex) { _logger.LogWarning(ex, "Attempt to get work error."); } catch (Exception ex) { _logger.LogError(ex, "In process of doing work error"); throw; } } }); } private async Task MoveOrderInWork(EmployeeViewModel employee) { if (_orderLogic == null || employee == null) { return; } try { var runOrder = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel { EmployeeID = employee.ID, Status = OrderStatus.InProcess })); if (runOrder == null) { return; } _logger.LogDebug("DoWork. Employee {ID} back to order {Order}", employee.ID, runOrder.ID); // доделываем работу Thread.Sleep(employee.WorkExperience * _rnd.Next(100, 300) * runOrder.Count); _logger.LogDebug("DoWork. Employee {ID} finish order {Order}", employee.ID, runOrder.ID); _orderLogic.ReadyOrder(new OrderBindingModel { ID = runOrder.ID }); // отдыхаем Thread.Sleep(employee.Qualification * _rnd.Next(10, 100)); } // заказа может не быть, просто игнорируем ошибку catch (InvalidOperationException ex) { _logger.LogWarning(ex, "Attempt to get work error."); } // а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации catch (Exception ex) { _logger.LogError(ex, "In process of doing work error"); throw; } } } }