2023-04-09 18:55:27 +04:00
using FurnitureAssemblyContracts.BindingModels ;
using FurnitureAssemblyContracts.BusinessLogicsContarcts ;
using FurnitureAssemblyContracts.SearchModels ;
using FurnitureAssemblyContracts.ViewModels ;
using FurnitureAssemblyDataModels.Enums ;
using Microsoft.Extensions.Logging ;
namespace FurnitureAssemblyBusinessLogic
{
public class WorkModeling : IWorkProcess
{
private readonly ILogger _logger ;
private readonly Random _rnd ;
private IOrderLogic ? _orderLogic ;
public WorkModeling ( ILogger < WorkModeling > logger )
{
_logger = logger ;
_rnd = new Random ( 1000 ) ;
}
public void DoWork ( IImplementerLogic implementerLogic , IOrderLogic
orderLogic )
{
_orderLogic = orderLogic ;
var implementers = implementerLogic . ReadList ( null ) ;
if ( implementers = = null )
{
_logger . LogWarning ( "DoWork. Implementers is null" ) ;
return ;
}
var orders = _orderLogic . ReadList ( new OrderSearchModel
{
Status = OrderStatus . П р и н я т
} ) ;
2023-04-20 21:15:57 +04:00
var ordersInWorking = _orderLogic . ReadList ( new OrderSearchModel
{
Status = OrderStatus . В ы п о л н я е т с я
} ) ;
var ordersInWaiting = _orderLogic . ReadList ( new OrderSearchModel
{
Status = OrderStatus . О ж и д а н и е
} ) ;
// могут остаться заказы в этих статусах, поэтому следует их тоже пустить в работу
if ( ordersInWorking ! = null )
orders ? . AddRange ( ordersInWorking ) ;
if ( ordersInWaiting ! = null )
orders ? . AddRange ( ordersInWaiting ) ;
2023-04-09 18:55:27 +04:00
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 implementer in implementers )
{
2023-04-10 09:57:08 +04:00
Task . Run ( ( ) = > WorkerWorkAsync ( implementer , orders ) ) ;
2023-04-09 18:55:27 +04:00
}
}
/// <summary>
/// Иммитация работы исполнителя
/// </summary>
/// <param name="implementer"></param>
/// <param name="orders"></param>
private async Task WorkerWorkAsync ( ImplementerViewModel implementer , List < OrderViewModel > orders )
{
if ( _orderLogic = = null | | implementer = = null )
{
return ;
}
2023-04-20 21:15:57 +04:00
// Тут пока комментарий. Итак. По заданию требуется: один заказ "Ожидание" -> все заказы "Выполняется" -> все заказы "Принят",
// но в этом случае мы никогда можем не выполнить ожидающиеся...
// Сейчас логика такая: все заказы "Ожидание" -> один заказ "Выполняется" -> все заказы "Принят". Таким образом, мы потенциально можем выполнить все находящиеся в ожидании,
// потом только взять один заказ из выполняющихся и перейти к новым
//await RunOrderInWaiting(implementer);
await Task . Run ( ( ) = >
{
foreach ( var order in orders . Where ( x = > x . Status = = OrderStatus . О ж и д а н и е & & x . ImplementerId = = implementer . Id ) )
{
try
{
_orderLogic . FinishOrder ( new OrderBindingModel
{
Id = order . Id
} ) ;
// отдыхаем
Thread . Sleep ( implementer . Qualification * _rnd . Next ( 10 , 100 ) ) ;
}
// кто-то мог уже перехватить заказ, игнорируем ошибку
catch ( InvalidOperationException ex )
{
_logger . LogWarning ( ex , "Error try get work" ) ;
}
// заканчиваем выполнение имитации в случае иной ошибки
catch ( Exception ex )
{
_logger . LogError ( ex , "Error while do work" ) ;
throw ;
}
}
} ) ;
2023-04-09 18:55:27 +04:00
await RunOrderInWork ( implementer ) ;
await Task . Run ( ( ) = >
{
2023-04-20 21:15:57 +04:00
foreach ( var order in orders . Where ( x = > x . Status = = OrderStatus . П р и н я т ) )
2023-04-09 18:55:27 +04:00
{
try
{
_logger . LogDebug ( "DoWork. Worker {Id} try get order { Order}" , implementer . Id , order . Id ) ;
// пытаемся назначить заказ на исполнителя
_orderLogic . TakeOrderInWork ( new OrderBindingModel
{
Id = order . Id ,
ImplementerId = implementer . Id
} ) ;
// делаем работу
Thread . Sleep ( implementer . WorkExperience * _rnd . Next ( 100 ,
1000 ) * order . Count ) ;
_logger . LogDebug ( "DoWork. Worker {Id} finish order{ Order} " , implementer . Id , order . Id ) ;
_orderLogic . FinishOrder ( new OrderBindingModel
2023-04-20 21:15:57 +04:00
{
Id = order . Id
} ) ;
2023-04-10 09:57:08 +04:00
// отдыхаем
Thread . Sleep ( implementer . Qualification * _rnd . Next ( 10 , 100 ) ) ;
2023-04-09 18:55:27 +04:00
}
// кто-то мог уже перехватить заказ, игнорируем ошибку
catch ( InvalidOperationException ex )
{
_logger . LogWarning ( ex , "Error try get work" ) ;
}
// заканчиваем выполнение имитации в случае иной ошибки
catch ( Exception ex )
{
_logger . LogError ( ex , "Error while do work" ) ;
throw ;
2023-04-10 09:57:08 +04:00
}
2023-04-09 18:55:27 +04:00
}
} ) ;
}
/// <summary>
/// Ищем заказ, которые уже в работе (вдруг исполнителя прервали)
/// </summary>
/// <param name="implementer"></param>
/// <returns></returns>
private async Task RunOrderInWork ( ImplementerViewModel implementer )
{
if ( _orderLogic = = null | | implementer = = null )
{
return ;
}
try
{
var runOrder = await Task . Run ( ( ) = > _orderLogic . ReadElement ( new OrderSearchModel
{
ImplementerId = implementer . Id ,
Status = OrderStatus . В ы п о л н я е т с я
} ) ) ;
if ( runOrder = = null )
{
return ;
}
_logger . LogDebug ( "DoWork. Worker {Id} back to order {Order}" ,
implementer . Id , runOrder . Id ) ;
// доделываем работу
Thread . Sleep ( implementer . WorkExperience * _rnd . Next ( 100 , 300 ) *
runOrder . Count ) ;
_logger . LogDebug ( "DoWork. Worker {Id} finish order {Order}" ,
implementer . Id , runOrder . Id ) ;
_orderLogic . FinishOrder ( new OrderBindingModel
{
2023-04-10 09:57:08 +04:00
Id = runOrder . Id
2023-04-09 18:55:27 +04:00
} ) ;
// отдыхаем
Thread . Sleep ( implementer . Qualification * _rnd . Next ( 10 , 100 ) ) ;
}
// заказа может не быть, просто игнорируем ошибку
catch ( InvalidOperationException ex )
{
_logger . LogWarning ( ex , "Error try get work" ) ;
}
// а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации
catch ( Exception ex )
{
_logger . LogError ( ex , "Error while do work" ) ;
throw ;
}
}
2023-04-20 21:15:57 +04:00
/// <summary>
/// Ищем заказ, которые находятся в ожидании
/// </summary>
/// <param name="implementer"></param>
/// <returns></returns>
private async Task RunOrderInWaiting ( ImplementerViewModel implementer )
{
if ( _orderLogic = = null | | implementer = = null )
{
return ;
}
try
{
var runOrder = await Task . Run ( ( ) = > _orderLogic . ReadElement ( new OrderSearchModel
{
ImplementerId = implementer . Id ,
Status = OrderStatus . О ж и д а н и е
} ) ) ;
if ( runOrder = = null )
{
return ;
}
_orderLogic . FinishOrder ( new OrderBindingModel
{
Id = runOrder . Id
} ) ;
// отдыхаем
Thread . Sleep ( implementer . Qualification * _rnd . Next ( 10 , 100 ) ) ;
}
// заказа может не быть, просто игнорируем ошибку
catch ( InvalidOperationException ex )
{
_logger . LogWarning ( ex , "Error try get work" ) ;
}
// а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации
catch ( Exception ex )
{
_logger . LogError ( ex , "Error while do work" ) ;
throw ;
}
}
2023-04-09 18:55:27 +04:00
}
}