diff --git a/Mate.DataCore/Data/DynamicInitializer/Tables/MasterTableResource.cs b/Mate.DataCore/Data/DynamicInitializer/Tables/MasterTableResource.cs index c3bcaf8eb..60f827bad 100644 --- a/Mate.DataCore/Data/DynamicInitializer/Tables/MasterTableResource.cs +++ b/Mate.DataCore/Data/DynamicInitializer/Tables/MasterTableResource.cs @@ -2,6 +2,7 @@ using System.Linq; using Mate.DataCore.Data.Context; using Mate.DataCore.DataModel; +using Mate.DataCore.Nominal.Model; namespace Mate.DataCore.Data.DynamicInitializer.Tables { @@ -47,50 +48,73 @@ internal void CreateResourceTools(List resourceProperties) for (int i = 0; i < resourceProperties.Count; i++) { CreateTools(_capability.Capabilities[i], resourceProperties[i].SetupTime, - resourceProperties[i].OperatorCount); + resourceProperties[i].OperatorCount, limitedTools: false, numberOfWorker: 3); } } //was sind operators? -> Personen, die Maschinen umrüsten - private void CreateTools(M_ResourceCapability capability, long setupTime, int numberOfOperators) + private void CreateTools(M_ResourceCapability capability, long setupTime, int numberOfOperators, bool limitedTools = false, int numberOfWorker = 0) { List tools = new List(); List setups = new List(); List capabilityProviders = new List(); List operators = new List(); + List workers = new List(); for (int i = 1; i < 1 + numberOfOperators; i++) { - operators.Add(CreateNewResource(capability.Name + " Operator " + i, true, true, capability.Name)); + operators.Add(CreateNewResource(capability.Name + " Operator " + i, true, true, capability.Name + "O")); + } + + for (int i = 1; i < 1 + numberOfWorker; i++) + { + workers.Add(CreateNewResource(capability.Name + " Worker " + i, true, true, capability.Name + "W")); + } + + var numberOfTools = _capability.Capabilities + .Single(x => x.Name == capability.Name) + .ChildResourceCapabilities.Count(); + + for (int i = 0; i < numberOfTools; i++) + { + var tool = CreateNewResource($"Tool {capability.Name} {i}", false, false, null); + tools.Add(tool); } foreach (var resource in CapabilityToResourceDict.Single(x => x.Key == capability.Name).Value) { if (operators.Count > 0) { - foreach (var op in operators) + var nTool = 0; + foreach (var subCapability in _capability.Capabilities + .Single(x => x.Name == capability.Name) + .ChildResourceCapabilities) { - foreach (var subCapability in _capability.Capabilities - .Single(x => x.Name == capability.Name) - .ChildResourceCapabilities) + + foreach (var op in operators) { + foreach(var worker in workers) { var capabilityProvider = new M_ResourceCapabilityProvider() { Name = $"Provides {subCapability.Name} {resource.Name}", ResourceCapabilityId = subCapability.Id, }; - var tool = CreateNewResource($"Tool {resource.Name} {subCapability.Name}", false, false, null); - tools.Add(tool); - - setups.Add(CreateNewSetup(op, capabilityProvider, false, true, 0)); - setups.Add(CreateNewSetup(tool, capabilityProvider, true, true, setupTime)); - setups.Add(CreateNewSetup(resource, capabilityProvider, true, true, 0)); - capabilityProviders.Add(capabilityProvider); + // var tool = CreateNewResource($"Tool {resource.Name} {subCapability.Name}", false, false, null); + // tools.Add(tool); + + setups.Add(CreateNewSetup(op, capabilityProvider, false, true, 0)); + setups.Add(CreateNewSetup(tools[nTool], capabilityProvider, true, true, setupTime)); + setups.Add(CreateNewSetup(resource, capabilityProvider, true, true, 0)); + setups.Add(CreateNewSetup(worker, capabilityProvider, true, false, 0)); + capabilityProviders.Add(capabilityProvider); + } } + nTool++; } } else { + var nTool = 0; foreach (var subCapability in _capability.Capabilities .Single(x => x.Name == capability.Name) .ChildResourceCapabilities) @@ -100,18 +124,20 @@ private void CreateTools(M_ResourceCapability capability, long setupTime, int nu Name = $"Provides {subCapability.Name} {resource.Name}", ResourceCapabilityId = subCapability.Id, }; - var tool = CreateNewResource($"Tool {resource.Name} {subCapability.Name}", false, false, null); - tools.Add(tool); + //var tool = CreateNewResource($"Tool {resource.Name} {subCapability.Name}", false, false, null); + //tools.Add(tool); - setups.Add(CreateNewSetup(tool, capabilityProvider, true, true, setupTime)); + setups.Add(CreateNewSetup(tools[nTool], capabilityProvider, true, true, setupTime)); setups.Add(CreateNewSetup(resource, capabilityProvider, true, true, 0)); capabilityProviders.Add(capabilityProvider); + nTool++; } } CapabilityProviderDict.Add($"{resource.Name} Tooling", capabilityProviders); CapabilityToSetupDict.Add($"{resource.Name} Tooling", setups); CapabilityToResourceDict.Add($"{resource.Name} Tooling", tools); CapabilityToResourceDict.Add($"{resource.Name} Operators", operators); + CapabilityToResourceDict.Add($"{resource.Name} Worker", workers); } } diff --git a/Mate.DataCore/Data/Initializer/StoredProcedures/ArticleStatistics.cs b/Mate.DataCore/Data/Initializer/StoredProcedures/ArticleStatistics.cs index e5ca5e4dc..89ab99120 100644 --- a/Mate.DataCore/Data/Initializer/StoredProcedures/ArticleStatistics.cs +++ b/Mate.DataCore/Data/Initializer/StoredProcedures/ArticleStatistics.cs @@ -1,5 +1,7 @@ using Mate.DataCore.Data.Context; using Microsoft.EntityFrameworkCore; +using System.CodeDom; +using System.Collections.Generic; namespace Mate.DataCore.Data.Initializer.StoredProcedures { @@ -7,8 +9,9 @@ public static class ArticleStatistics { public static void CreateProcedures(MateDb ctx) { + List ctes = new List(); - string sql = string.Format( + string sqlArticleCTE = string.Format( @"CREATE OR ALTER PROCEDURE ArticleCTE @ArticleId int AS @@ -47,13 +50,70 @@ UNION ALL select Sum(u.dur) as SumDuration , sum(u.count) as SumOperations, sum(u.Po) as ProductionOrders from #Union u END"); + ctes.Add(sqlArticleCTE); + + string sqlArticleCapabilityComplexityCTE = string.Format( + @"CREATE OR ALTER PROCEDURE [dbo].[ArticleCapabilityComplexity] + @ArticleId int + AS + BEGIN + SET NOCOUNT ON; + DROP TABLE IF EXISTS dbo.#Temp; + DROP TABLE IF EXISTS dbo.#Union; + WITH Parts(AssemblyID, ComponentID, PerAssemblyQty, ComponentLevel, ResourceCapabilityId) AS + ( + SELECT b.ArticleParentId, b.ArticleChildId, CAST(b.Quantity AS decimal),0 AS ComponentLevel, 0 as ResourceCapabilityId + FROM dbo.M_ArticleBom AS b + join dbo.M_Article a on a.Id = b.ArticleParentId + where @ArticleId = a.Id + UNION ALL + SELECT bom.ArticleParentId, bom.ArticleChildId, CAST(PerAssemblyQty * bom.Quantity as DECIMAL), ComponentLevel + 1, 0 as ResourceCapabilityId + FROM dbo.M_ArticleBom AS bom + INNER join dbo.M_Article ac on ac.Id = bom.ArticleParentId + INNER JOIN Parts AS p ON bom.ArticleParentId = p.ComponentID + ) + select * into #Temp + from ( + select pr.Id,pr.Name, Sum(p.PerAssemblyQty) as qty, pr.ToBuild as ToBuild, p.ResourceCapabilityId as ResourceCapabilityId + FROM Parts AS p INNER JOIN M_Article AS pr ON p.ComponentID = pr.Id + Group By pr.Id, pr.Name, p.ComponentID, pr.ToBuild, p.ResourceCapabilityId) as x + + select * into #Union from ( + select Sum(o.Duration * t.qty) as dur, sum(t.qty) as count ,0 as 'Po', o.ResourceCapabilityId as ResourceCapabilityId + from dbo.M_Operation o join #Temp t on t.Id = o.ArticleId + FULL OUTER join M_ResourceCapability allCaps on allCaps.Id = o.ResourceCapabilityId + where o.ArticleId in (select t.Id from #Temp t) + group by o.ResourceCapabilityId + UNION ALL + SELECT SUM(ot.Duration) as dur, COUNT(*) as count , 0 as 'Po', ot.ResourceCapabilityId as ResourceCapabilityId + from dbo.M_Operation ot + FULL OUTER join M_ResourceCapability allCaps on allCaps.Id = ot.ResourceCapabilityId + where ot.ArticleId = @ArticleId + group by ot.ResourceCapabilityId + ) as x + UNION ALL + SELECT 0 as dur, 0 as count, sum(t.qty) + 1 as 'Po', t.ResourceCapabilityId as ResourceCapabilityId + from #Temp t + FULL OUTER join M_ResourceCapability allCaps on allCaps.Id = t.ResourceCapabilityId + where t.ToBuild = 1 + group by t.ResourceCapabilityId + select Sum(u.dur) as SumDuration , sum(u.count) as SumOperations, sum(u.Po) as ProductionOrders, allCaps.Id as ResourceCapabilityId from #Union u + FULL OUTER join M_ResourceCapability allCaps on allCaps.Id = u.ResourceCapabilityId + group by allCaps.Id + END"); + + ctes.Add(sqlArticleCapabilityComplexityCTE); + using (var command = ctx.Database.GetDbConnection().CreateCommand()) { - command.CommandText = sql; - ctx.Database.OpenConnection(); - command.ExecuteNonQuery(); - } + foreach(var cte in ctes) + { + command.CommandText = cte; + ctx.Database.OpenConnection(); + command.ExecuteNonQuery(); + } + } } public static long DeliveryDateEstimator(int articleId, double factor, MateDb dBContext) @@ -69,10 +129,10 @@ public static long DeliveryDateEstimator(int articleId, double factor, MateDb dB { while (reader.Read()) { - System.Diagnostics.Debug.WriteLine(string.Format("Summe der Dauer {0}; Summe der Operationen {1}; Summe der Prodktionsaufträge {2}", reader[0], reader[1], reader[2])); + System.Diagnostics.Debug.WriteLine(string.Format("Summe der Dauer {0}; Anzahl der Operationen {1}; Summe der Produktionsaufträge {2}", reader[0], reader[1], int.Parse(reader[2].ToString()) + 1)); // TODO Catch false informations estimatedProductDelivery = (long)(System.Convert.ToInt64(reader[0]) * factor); - System.Diagnostics.Debug.WriteLine("Estimated Product Delivery{0}", estimatedProductDelivery); + System.Diagnostics.Debug.WriteLine("Estimated Product Delivery {0}", estimatedProductDelivery); } } diff --git a/Mate.DataCore/Data/Seed/CapbilityTransformer.cs b/Mate.DataCore/Data/Seed/CapbilityTransformer.cs index 8bacb94fa..9094a5d49 100644 --- a/Mate.DataCore/Data/Seed/CapbilityTransformer.cs +++ b/Mate.DataCore/Data/Seed/CapbilityTransformer.cs @@ -25,7 +25,7 @@ public class CapbilityTransformer ToolCount = resourceConfig.GetToolsFor(i).Count, ResourceCount = (int)resourceConfig.ResourceGroupList[i].ResourceQuantity, SetupTime = (int)resourceConfig.GetMeanSetupDurationFor(i, 0).TotalMinutes, - OperatorCount = 2, + OperatorCount = 1, IsBatchAble = false }); diff --git a/Mate.DataCore/Data/Seed/MaterialTransformer.cs b/Mate.DataCore/Data/Seed/MaterialTransformer.cs index 5e89d7ff3..7497757ff 100644 --- a/Mate.DataCore/Data/Seed/MaterialTransformer.cs +++ b/Mate.DataCore/Data/Seed/MaterialTransformer.cs @@ -6,6 +6,7 @@ using Seed.Generator.Material; using System; using System.Collections.Generic; +using System.Data.HashFunction.xxHash; using System.Linq; namespace Mate.DataCore.Data.Seed @@ -13,6 +14,7 @@ namespace Mate.DataCore.Data.Seed public class MaterialTransformer { public static string BUSINESS_PARTNER_1 { get; private set; } = "BUSINESS_PARTNER_1"; + public static string BUSINESS_PARTNER_2 { get; private set; } = "BUSINESS_PARTNER_2"; public static void Transform(MateDb mateDb, Materials materials, DynamicInitializer.Tables.MasterTableResourceCapability masterTableCapabilities) { @@ -79,7 +81,7 @@ public static void Transform(MateDb mateDb, Materials materials, DynamicInitiali mateDb.ArticleBoms.AddRange(boms); mateDb.SaveChanges(); - CreateStocks(mateDb, businessPartners.First()); ; + CreateStocks(mateDb, businessPartners.ToList()); } @@ -87,7 +89,8 @@ private static M_BusinessPartner[] CreateBusinessPartners(MateDb mateDb) { var businessPartners = new M_BusinessPartner[] { - new M_BusinessPartner() {Debitor = true, Kreditor = false, Name = BUSINESS_PARTNER_1} + new M_BusinessPartner() {Debitor = true, Kreditor = false, Name = BUSINESS_PARTNER_1}, + new M_BusinessPartner() {Debitor = false, Kreditor = true, Name = BUSINESS_PARTNER_2} }; mateDb.BusinessPartners.AddRange(businessPartners); mateDb.SaveChanges(); @@ -146,7 +149,7 @@ private static M_ArticleBom CreateBOM(M_Article articleFrom, M_Article articlesT } - private static void CreateStocks(MateDb mateDb, M_BusinessPartner businessPartners) + private static void CreateStocks(MateDb mateDb, List businessPartners) { // get the name -> id mappings var dbArticles = mateDb.Articles.ToList(); @@ -161,18 +164,18 @@ private static void CreateStocks(MateDb mateDb, M_BusinessPartner businessPartne { ArticleForeignKey = article.Id, Name = "Stock: " + article.Name, - Min = article.ToPurchase ? 500 : 0, - Max = 10000, + Min = article.ToPurchase ? 100 : 0, + Max = 1000, Current = article.ToPurchase ? 1000 : 0, StartValue = article.ToPurchase ? 1000 : 0, }); articleToBusinessPartners.Add( new M_ArticleToBusinessPartner { - BusinessPartnerId = businessPartners.Id, + BusinessPartnerId = article.ToPurchase ? businessPartners.Single(x => x.Kreditor).Id : businessPartners.Single(x => x.Debitor).Id, ArticleId = article.Id, - PackSize = 1000, - Price = 1000 * article.Price, + PackSize = 5000, + Price = 5000 * article.Price, TimeToDelivery = 1440 }); } diff --git a/Mate.DataCore/Data/Seed/SEEDInitializer.cs b/Mate.DataCore/Data/Seed/SEEDInitializer.cs new file mode 100644 index 000000000..9d22dc9e9 --- /dev/null +++ b/Mate.DataCore/Data/Seed/SEEDInitializer.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using Seed; +using Seed.Parameter; +using Seed.Parameter.TransitionMatrix; +using Seed.Parameter.Operation; +using Seed.Generator.Material; +using Seed.Distributions; +using Seed.Generator.Operation; +using Mate.DataCore.Data.Context; +using System.Linq; + +namespace Mate.DataCore.Data.Seed +{ + public class SeedInitializer + { + public void GenerateTestData(string mateDbName, int machineCount, int toolCount + , int seed, double reuseRatio, double complexityRatio, double organizationalDegree + , int numberOfSalesMaterials, int verticalIntegration, int lambda = 2) + { + + //Generate Config + var seedConfig = new Configuration(); + var materialConfig = new MaterialConfig() + { + StructureParameter = new StructureParameter() { + ComplexityRatio = complexityRatio, // 1.9, + ReuseRatio = reuseRatio, // 1.3, + NumberOfSalesMaterials = numberOfSalesMaterials, + VerticalIntegration = verticalIntegration, + Seed = seed // 7 + }, + TransitionMatrixParameter = new TransitionMatrixParameter() { + Lambda = lambda, + OrganizationalDegree = organizationalDegree // 0.7 + } + }; + + seedConfig.WithOption(materialConfig); + + + + var rsSaw = new ResourceGroup("Saw") + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); + + var rsDrill = new ResourceGroup("Drill") + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); + + var rsAssembly = new ResourceGroup("Assembly") + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); + + var rsQuality = new ResourceGroup("Quality") + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); + + var resourceConfig = new ResourceConfig().WithResourceGroup(new List { rsSaw, rsDrill, rsAssembly, rsQuality }) + .WithDefaultOperationsDurationMean(TimeSpan.FromMinutes(10)) + .WithDefaultOperationsDurationVariance(0.20) + .WithDefaultSetupDurationMean(TimeSpan.FromMinutes(30)) + .WithDefaultOperationsAmountMean(8) + .WithDefaultOperationsAmountVariance(0.20); + + seedConfig.WithOption(resourceConfig); + + // Generator + var materials = MaterialGenerator.WithConfiguration(materialConfig) + .Generate(); + + var randomizer = new RandomizerBase(materialConfig.StructureParameter.Seed); + var randomizerCollection = RandomizerCollection.WithTransition(randomizer) + .WithOperationDuration(new RandomizerLogNormal(randomizer.Next(int.MaxValue))) + .WithOperationAmount(new RandomizerBinominial(randomizer.Next(int.MaxValue))) + .Build(); + + + var transitionMatrix = TransitionMatrixGenerator.WithConfiguration(seedConfig).Generate(); + + var operationDistributor = OperationDistributor.WithTransitionMatrix(transitionMatrix) + .WithRandomizerCollection(randomizerCollection) + .WithResourceConfig(resourceConfig) + .Build(); + + var operationGenerator = OperationGenerator.WithOperationDistributor(operationDistributor) + .WithMaterials(materials.NodesInUse.Where(x => x.IncomingEdgeIds.Any()).ToArray()) + .Generate(); + + + //Initilize DB + + MateDb mateDb = Dbms.GetMateDataBase(dbName: mateDbName).DbContext; + mateDb.Database.EnsureDeleted(); + mateDb.Database.EnsureCreated(); + + var masterTableCapabilities = CapbilityTransformer.Transform(mateDb, resourceConfig); + + MaterialTransformer.Transform(mateDb, materials, masterTableCapabilities); + + } + + + private List GenerateTools(int amount) + { + var listOfTools = new List(); + var counter = 2; + + + for (int i = 0; i < amount; i++) + { + + var nameOfTool = "Blade" + counter.ToString() + "mm"; + listOfTools.Add(new ResourceTool(nameOfTool)); + counter += 2; + } + + + return listOfTools; + + } + } + +} diff --git a/Mate.DataCore/DataModel/T_CustomerOrder.cs b/Mate.DataCore/DataModel/T_CustomerOrder.cs index 1597a53ad..54011a861 100644 --- a/Mate.DataCore/DataModel/T_CustomerOrder.cs +++ b/Mate.DataCore/DataModel/T_CustomerOrder.cs @@ -19,7 +19,7 @@ public class T_CustomerOrder : BaseEntity, IOrder [JsonIgnore] public virtual ICollection CustomerOrderParts { get; set; } public State State { get; set; } - + public override string ToString() { return $"{Id}: {Name}; {DueTime}"; diff --git a/Mate.DataCore/Mate.DataCore.csproj b/Mate.DataCore/Mate.DataCore.csproj index 37a0a1eff..f1f9f9b13 100644 --- a/Mate.DataCore/Mate.DataCore.csproj +++ b/Mate.DataCore/Mate.DataCore.csproj @@ -12,6 +12,7 @@ + diff --git a/Mate.DataCore/ReportingModel/SimulationOrder.cs b/Mate.DataCore/ReportingModel/SimulationOrder.cs index c9091d751..318a83417 100644 --- a/Mate.DataCore/ReportingModel/SimulationOrder.cs +++ b/Mate.DataCore/ReportingModel/SimulationOrder.cs @@ -7,6 +7,7 @@ namespace Mate.DataCore.ReportingModel public class SimulationOrder : ResultBaseEntity, IOrder { public string Name { get; set; } + public int Quantity { get; set; } public int OriginId { get; set; } public int DueTime { get; set; } public int CreationTime { get; set; } diff --git a/Mate.Production.CLI/Command.cs b/Mate.Production.CLI/Command.cs index 51bde8a39..7d593f648 100644 --- a/Mate.Production.CLI/Command.cs +++ b/Mate.Production.CLI/Command.cs @@ -28,6 +28,8 @@ public class Commands : List , new TimePeriodForThroughputCalculation() , new MaxBucketSize() , new TransitionFactor() + , new MinQuantity() + , new MaxQuantity() , new MaxDeliveryTime() , new MinDeliveryTime() , new TimeConstraintQueueLength() diff --git a/Mate.Production.CLI/ConsoleHub.cs b/Mate.Production.CLI/ConsoleHub.cs index aee698eca..6c48a597d 100644 --- a/Mate.Production.CLI/ConsoleHub.cs +++ b/Mate.Production.CLI/ConsoleHub.cs @@ -1,7 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using AkkaSim.Logging; +using JetBrains.Annotations; using Mate.Production.Core.SignalR; using Mate.Production.Core.SignalR.Messages; +using Mate.Production.Core.Types; using Newtonsoft.Json; using NLog; @@ -13,15 +16,22 @@ public class ConsoleHub: IMessageHub public List Logs= new List(); + public Action _streamWriter ; + + public ConsoleHub(Action streamWriter) + { + _streamWriter = streamWriter; + } + public void SendToAllClients(string msg, MessageType msgType) { - _logger.Log(LogLevel.Info, msgType.ToString() + ": " + msg); + _logger.Log(LogLevel.Info, msgType.ToString() + ": " + msg); //Console.WriteLine(msg); } public void SendToClient(string listener, string msg, MessageType msgType) { - _logger.Log(LogLevel.Info, $" {listener}: { msg } "); + _streamWriter(listener, msg); } public string ReturnMsgBox(string msg, MessageType type) @@ -35,9 +45,9 @@ public void StartSimulation(string simId, string simNumber) _logger.Log(LogLevel.Info, "Start Simulation (id:" + simId + " | simNumber:" + simNumber + ")"); } - public void ProcessingUpdate(int simId, int finished, string simType, int max) + public void ProcessingUpdate(int finished, int finishedPercent, string progress, int total) { - _logger.Log(LogLevel.Info, $"msg"); + _logger.Log(LogLevel.Info, $"Finished: " + finished +" ("+ finishedPercent + "%) from total " + total + " | "+ progress); } public void GuardianState(object msg) diff --git a/Mate.Production.CLI/LoggingHub.cs b/Mate.Production.CLI/LoggingHub.cs new file mode 100644 index 000000000..c24d417cc --- /dev/null +++ b/Mate.Production.CLI/LoggingHub.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using AkkaSim.Logging; +using Mate.Production.Core.SignalR; +using Mate.Production.Core.SignalR.Messages; +using Newtonsoft.Json; +using NLog; + +namespace Mate.Production.CLI +{ + public class LoggingHub: IMessageHub + { + Logger _logger = LogManager.GetLogger(TargetNames.LOG_AGENTS); + + public List Logs= new List(); + + public void SendToAllClients(string msg, MessageType msgType) + { + _logger.Log(LogLevel.Info, msgType.ToString() + ": " + msg); + //Console.WriteLine(msg); + } + + public void SendToClient(string listener, string msg, MessageType msgType) + { + _logger.Log(LogLevel.Info, $" {listener}: { msg } "); + } + + public string ReturnMsgBox(string msg, MessageType type) + { + //Console.WriteLine(value: msg); + return msg; + } + + public void StartSimulation(string simId, string simNumber) + { + _logger.Log(LogLevel.Info, "Start Simulation (id:" + simId + " | simNumber:" + simNumber + ")"); + } + + public void ProcessingUpdate(int simId, int finished, string simType, int max) + { + _logger.Log(LogLevel.Info, $"msg"); + } + + public void GuardianState(object msg) + { + Logs.Add(JsonConvert.SerializeObject(msg)); + } + + public void EndSimulation(string msg, string simId, string simNumber) + { + _logger.Log(LogLevel.Info, $"Simulation Id: { simId } | No. { simNumber } Finished."); + } + + } + +} \ No newline at end of file diff --git a/Mate.Production.CLI/Program.cs b/Mate.Production.CLI/Program.cs index 41f4bb355..c47d78b38 100644 --- a/Mate.Production.CLI/Program.cs +++ b/Mate.Production.CLI/Program.cs @@ -96,7 +96,7 @@ private static async Task StartHangfire(bool silent) try { Console.WriteLine(value: "Starting AkkaSim."); - var agentCore = new AgentCore(dbName, messageHub: new ConsoleHub()); + var agentCore = new AgentCore(dbName, messageHub: new LoggingHub()); await agentCore.RunAkkaSimulation(configuration: config); } diff --git a/Mate.Production.Core/AgentContinuation.cs b/Mate.Production.Core/AgentContinuation.cs index dff61b468..73c4a70ae 100644 --- a/Mate.Production.Core/AgentContinuation.cs +++ b/Mate.Production.Core/AgentContinuation.cs @@ -44,7 +44,7 @@ public override void AfterSimulationStopped(Simulation sim) tasks.Add(item.Ask(message: msg, timeout: TimeSpan.FromSeconds(value: 60 * 60))); } - Task.WaitAll(tasks.ToArray()); + Task.WaitAll(tasks.ToArray(), timeout: TimeSpan.FromSeconds(value: 60 * 10)); } @@ -53,7 +53,7 @@ public override void SimulationIsTerminating(Simulation sim) foreach (var item in _collectorRefs) { item.Ask(message: UpdateLiveFeed.Create(setup: true, target: _inbox.Receiver) - , timeout: TimeSpan.FromHours(value: 1)).Wait(); + , timeout: TimeSpan.FromMinutes(value: 15)).Wait(); } sim.ActorSystem.Terminate().Wait(); _logger.Log(LogLevel.Info, $"Simulation run for { sim.ActorSystem.Uptime } and ended!"); diff --git a/Mate.Production.Core/AgentSimulation.cs b/Mate.Production.Core/AgentSimulation.cs index 914bba6b8..050776da1 100644 --- a/Mate.Production.Core/AgentSimulation.cs +++ b/Mate.Production.Core/AgentSimulation.cs @@ -7,6 +7,8 @@ using Akka.Event; using AkkaSim; using AkkaSim.SpecialActors; +using Mate.DataCore.Data.Initializer.StoredProcedures; +using Mate.DataCore.Data.WrappersForPrimitives; using Mate.DataCore.DataModel; using Mate.DataCore.Nominal.Model; using Mate.Production.Core.Agents; @@ -16,6 +18,7 @@ using Mate.Production.Core.Agents.Guardian; using Mate.Production.Core.Agents.Guardian.Options; using Mate.Production.Core.Agents.HubAgent.Types.Central; +using Mate.Production.Core.Agents.ProductionAgent; using Mate.Production.Core.Agents.SupervisorAgent; using Mate.Production.Core.Environment; using Mate.Production.Core.Environment.Options; @@ -89,13 +92,24 @@ public override Task InitializeSimulation(Configuration configuratio }); } + private long GetCustomOrderTime(int productId) + { + return ArticleStatistics.DeliveryDateEstimator(productId, 10, DbProduction.DbContext); + } + + private void CreateSupervisor(Configuration configuration) { var products = DbProduction.DbContext.GetProducts(); - var initialTime = configuration.GetOption().Value; + // var initialTime = configuration.GetOption().Value; + + var estimatedThroughPuts = products.Select(a => new FSetEstimatedThroughputTime(a.Id + , GetCustomOrderTime(a.Id) + , a.Name)) + .ToList(); + + - var estimatedThroughPuts = products.Select(a => new FSetEstimatedThroughputTime(a.Id, initialTime, a.Name)) - .ToList(); var behave = Agents.SupervisorAgent.Behaviour.Factory.Default( dbNameProduction: DbProduction.DataBaseName.Value, diff --git a/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Contracts.cs b/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Contracts.cs index 36a348818..2558ae184 100644 --- a/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Contracts.cs +++ b/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Contracts.cs @@ -203,8 +203,9 @@ private void AddOrder(Contract.Instruction.StartOrder m) { var op = m.GetObjectFromMessage; var order = new SimulationOrder() { CreationTime = op.CustomerOrder.CreationTime - ,DueTime = op.CustomerOrder.DueTime + , DueTime = op.CustomerOrder.DueTime , State = State.Created + , Quantity = op.CustomerOrder.CustomerOrderParts.ToArray()[0].Quantity , BusinessPartnerId = op.CustomerOrder.BusinessPartnerId , Name = op.CustomerOrder.Name , OriginId = op.CustomerOrder.Id diff --git a/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Job.cs b/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Job.cs index d6047e0ed..71d80ece4 100644 --- a/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Job.cs +++ b/Mate.Production.Core/Agents/CollectorAgent/Collector.Analytics.Job.cs @@ -94,7 +94,7 @@ public bool EventHandle(SimulationMonitor simulationMonitor, object message) return true; } - + /// /// collect the resourceSetups of resource, cant be updated afterward /// @@ -195,7 +195,6 @@ private void CallAverageIdle(bool finalCall) Collector.Kpis.AddRange(kpis); } - private void CallTotal(bool finalCall) { if (finalCall) diff --git a/Mate.Production.Core/Agents/CollectorAgent/Types/OperationPosition.cs b/Mate.Production.Core/Agents/CollectorAgent/Types/OperationPosition.cs new file mode 100644 index 000000000..22dbb4653 --- /dev/null +++ b/Mate.Production.Core/Agents/CollectorAgent/Types/OperationPosition.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mate.Production.Core.Agents.CollectorAgent.Types +{ + public enum Process + { + Dequeue, + Enqueue + } + + public class OperationPosition + { + public long Time { get; private set; } + public int Position { get; private set; } + public string Resource { get; private set; } + public long Start { get; private set; } + public string Process { get; private set; } + public long RealTime { get; } + + public OperationPosition(long time, int position, string resource, long start, string process) + { + Time = time; + Position = position; + Resource = resource; + Start = start; + Process = process; + RealTime = DateTime.Now.Ticks; + } + + } +} diff --git a/Mate.Production.Core/Agents/DirectoryAgent/Behaviour/Central.cs b/Mate.Production.Core/Agents/DirectoryAgent/Behaviour/Central.cs index 656d58ee2..fd0b060fd 100644 --- a/Mate.Production.Core/Agents/DirectoryAgent/Behaviour/Central.cs +++ b/Mate.Production.Core/Agents/DirectoryAgent/Behaviour/Central.cs @@ -68,6 +68,7 @@ private void CreateHubAgent(FCentralResourceHubInformations.FResourceHubInformat , maxBucketSize: 0 // not used currently , dbConnectionStringGanttPlan: resourceHubInformation.DbConnectionString , dbConnectionStringMaster: resourceHubInformation.MasterDbConnectionString + , pathToGANTTPLANOptRunner: resourceHubInformation.PathToGANTTPLANOptRunner , workTimeGenerator: resourceHubInformation.WorkTimeGenerator as WorkTimeGenerator , debug: Agent.DebugThis , principal: Agent.Context.Self) diff --git a/Mate.Production.Core/Agents/HubAgent/Behaviour/Central.cs b/Mate.Production.Core/Agents/HubAgent/Behaviour/Central.cs index 699651a09..86d7e0f05 100644 --- a/Mate.Production.Core/Agents/HubAgent/Behaviour/Central.cs +++ b/Mate.Production.Core/Agents/HubAgent/Behaviour/Central.cs @@ -5,6 +5,7 @@ using Akka.Actor; using Akka.Util.Internal; using Mate.DataCore.Data.Context; +using Mate.DataCore.Data.WrappersForPrimitives; using Mate.DataCore.GanttPlan; using Mate.DataCore.GanttPlan.GanttPlanModel; using Mate.DataCore.Nominal; @@ -14,7 +15,9 @@ using Mate.Production.Core.Helper.DistributionProvider; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; +using static FArticles; using static FCentralActivities; +using static Mate.Production.Core.Agents.ResourceAgent.Resource.Instruction.Central; using Resource = Mate.Production.Core.Agents.ResourceAgent.Resource; namespace Mate.Production.Core.Agents.HubAgent.Behaviour @@ -24,6 +27,7 @@ class Central : Core.Types.Behaviour private Dictionary _scheduledActivities { get; } = new Dictionary(); private string _dbConnectionStringGanttPlan { get; } private string _dbConnectionStringMaster { get; } + private string _pathToGANTTPLANOptRunner { get; } private WorkTimeGenerator _workTimeGenerator { get; } private PlanManager _planManager { get; } = new PlanManager(); private ResourceManager _resourceManager { get; } = new ResourceManager(); @@ -35,11 +39,12 @@ class Central : Core.Types.Behaviour private List _SalesorderMaterialrelations { get; set; } = new List(); private Dictionary _prtResources { get; set; } = new Dictionary(); - public Central(string dbConnectionStringGanttPlan, string dbConnectionStringMaster, WorkTimeGenerator workTimeGenerator, SimulationType simulationType = SimulationType.Default) : base(childMaker: null, simulationType: simulationType) + public Central(string dbConnectionStringGanttPlan, string dbConnectionStringMaster, string pathToGANTTPLANOptRunner, WorkTimeGenerator workTimeGenerator, SimulationType simulationType = SimulationType.Default) : base(childMaker: null, simulationType: simulationType) { _workTimeGenerator = workTimeGenerator; _dbConnectionStringGanttPlan = dbConnectionStringGanttPlan; _dbConnectionStringMaster = dbConnectionStringMaster; + _pathToGANTTPLANOptRunner = pathToGANTTPLANOptRunner; _confirmationManager = new ConfirmationManager(dbConnectionStringGanttPlan); _stockPostingManager = new StockPostingManager(dbConnectionStringGanttPlan); @@ -115,7 +120,7 @@ private void LoadProductionOrders(IActorRef inboxActorRef) CreateComputationalTime("TimeWriteConfirmations", lastStep); System.Diagnostics.Debug.WriteLine("Start GanttPlan"); - GanttPlanOptRunner.RunOptAndExport("Continuous", "C:\\Users\\admin\\GANTTPLAN\\GanttPlanOptRunner.exe"); //changed to Init - merged configs + GanttPlanOptRunner.RunOptAndExport("Continuous", _pathToGANTTPLANOptRunner); //changed to Init - merged configs System.Diagnostics.Debug.WriteLine("Finish GanttPlan"); lastStep = stopwatch.ElapsedMilliseconds - lastStep; @@ -126,6 +131,7 @@ private void LoadProductionOrders(IActorRef inboxActorRef) { foreach (var resourceState in _resourceManager.resourceStateList) { + // put to an sorted Queue on each Resource resourceState.ActivityQueue = new Queue( localGanttPlanDbContext.GptblProductionorderOperationActivityResourceInterval @@ -144,6 +150,7 @@ private void LoadProductionOrders(IActorRef inboxActorRef) && x.ProductionorderOperationActivityResource.ProductionorderOperationActivity.Status != (int)GanttActivityState.Started)) .OrderBy(x => x.DateFrom) .ToList()); + } // filter Done and in Progress? var tempsalesorder = _SalesorderMaterialrelations; @@ -360,8 +367,9 @@ private bool NextActivityIsEqual(ResourceState resourceState, string activityKey //only randomize ActivityType "Operation" if (fActivity.ActivityId == 3) - { - randomizedDuration = _workTimeGenerator.GetRandomWorkTime(fActivity.Duration); + { + + randomizedDuration = _workTimeGenerator.GetRandomWorkTime(fActivity.Duration, fActivity.Key.GetHashCode()); } CreateSimulationJob(activity, Agent.CurrentTime, randomizedDuration, requiredCapability); @@ -533,8 +541,13 @@ public override bool AfterInit() #region Reporting public void CreateSimulationJob(GptblProductionorderOperationActivity activity, long start, long duration, string requiredCapabilityName) - { - var pub = activity.ToSimulationJob(start, duration, requiredCapabilityName); + { + var pub = MessageFactory.ToSimulationJob(activity, + start, + duration, + requiredCapabilityName + ); + //var pub = activity.ToSimulationJob(start, duration, requiredCapabilityName); Agent.Context.System.EventStream.Publish(@event: pub); } diff --git a/Mate.Production.Core/Agents/HubAgent/Behaviour/Default.cs b/Mate.Production.Core/Agents/HubAgent/Behaviour/Default.cs index b4f3b398a..d413ab1c0 100644 --- a/Mate.Production.Core/Agents/HubAgent/Behaviour/Default.cs +++ b/Mate.Production.Core/Agents/HubAgent/Behaviour/Default.cs @@ -386,7 +386,7 @@ private void SendFinalBucket(Guid bucketKey) bucket.Operations.ForEach(operation => { operation.Operation.RandomizedDuration = - _workTimeGenerator.GetRandomWorkTime(operation.Operation.Duration); + _workTimeGenerator.GetRandomWorkTime(operation.Operation.Duration, (operation.ProductionAgent.GetHashCode() + operation.Operation.HierarchyNumber).GetHashCode()); Agent.DebugMessage($"{operation.Operation.Name} {operation.Key} from {((FBuckets.FBucket)jobConfirmation.Job).Name} has new work time of {operation.Operation.RandomizedDuration}.", CustomLogger.JOB, LogLevel.Warn); diff --git a/Mate.Production.Core/Agents/HubAgent/Behaviour/Factory.cs b/Mate.Production.Core/Agents/HubAgent/Behaviour/Factory.cs index 81fb45f20..fd36d03fa 100644 --- a/Mate.Production.Core/Agents/HubAgent/Behaviour/Factory.cs +++ b/Mate.Production.Core/Agents/HubAgent/Behaviour/Factory.cs @@ -31,9 +31,9 @@ private static IBehaviour Default(long maxBucketSize, WorkTimeGenerator workTime } - public static IBehaviour Central(string dbConnectionStringGanttPlan, string dbConnectionStringMaster, WorkTimeGenerator workTimeGenerator) + public static IBehaviour Central(string dbConnectionStringGanttPlan, string dbConnectionStringMaster, string pathToGANTTPLANOptRunner, WorkTimeGenerator workTimeGenerator) { - return new Central(dbConnectionStringGanttPlan, dbConnectionStringMaster, workTimeGenerator); + return new Central(dbConnectionStringGanttPlan, dbConnectionStringMaster, pathToGANTTPLANOptRunner, workTimeGenerator); } private static IBehaviour Queuing(long maxBucketSize, WorkTimeGenerator workTimeGenerator) diff --git a/Mate.Production.Core/Agents/HubAgent/Behaviour/Queuing.cs b/Mate.Production.Core/Agents/HubAgent/Behaviour/Queuing.cs index 361af2682..c9eaca567 100644 --- a/Mate.Production.Core/Agents/HubAgent/Behaviour/Queuing.cs +++ b/Mate.Production.Core/Agents/HubAgent/Behaviour/Queuing.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using System.Linq; using Akka.Actor; using Mate.DataCore.Nominal; +using Mate.Production.Core.Agents.CollectorAgent.Types; using Mate.Production.Core.Agents.HubAgent.Types; using Mate.Production.Core.Agents.HubAgent.Types.Queuing; using Mate.Production.Core.Agents.ResourceAgent; @@ -89,11 +91,17 @@ private void EnqueueJob(IJob job) operation.UpdateHubAgent(hub: Agent.Context.Self); + //Dequeue behind the new jobs prio + _jobManager.SetJob(job, Agent.CurrentTime); + //Enqueue behing the new jobs prio + StartNext(); } + + private void StartNext() { var availableCapabilities = _resourceManager.GetAvailableCapabilities(); @@ -226,8 +234,11 @@ private void DoWork(Guid queueKey, IJob job) var jobQueue = _jobManager.GetActiveJob(queueKey); var nextJob = jobQueue.Dequeue(Agent.CurrentTime); + _jobManager.RemoveFromJobTracker(nextJob, this.Agent.CurrentTime); + + var operation = nextJob as FOperation; - var randomizedDuration = _workTimeGenerator.GetRandomWorkTime(nextJob.Duration); + var randomizedDuration = _workTimeGenerator.GetRandomWorkTime(nextJob.Duration, (operation.ProductionAgent.GetHashCode() + operation.Operation.HierarchyNumber).GetHashCode()); Agent.DebugMessage($"Start DoWork for {jobQueue.QueueId} with job {nextJob.Name} and randomized duration of {randomizedDuration}"); @@ -249,6 +260,7 @@ private void DoWork(Guid queueKey, IJob job) jobType: JobType.OPERATION ); + Agent.Send(Resource.Instruction.Queuing.DoJob.Create(fQueuingJob, (IActorRef)resource.IResourceRef)); } } @@ -335,5 +347,4 @@ private void CreateOperationResults(IQueueingJob fQueuingJob) Agent.Send(BasicInstruction.FinishJob.Create(fOperationResult, job.ProductionAgent)); } } - } diff --git a/Mate.Production.Core/Agents/HubAgent/Hub.Agent.cs b/Mate.Production.Core/Agents/HubAgent/Hub.Agent.cs index c526ec044..c343202e9 100644 --- a/Mate.Production.Core/Agents/HubAgent/Hub.Agent.cs +++ b/Mate.Production.Core/Agents/HubAgent/Hub.Agent.cs @@ -24,15 +24,15 @@ public Hub(ActorPaths actorPaths, Configuration configuration, long time, Simula this.Do(o: BasicInstruction.Initialize.Create(target: Self, message: HubAgent.Behaviour.Factory.Get(simType:simtype, maxBucketSize: maxBucketSize, workTimeGenerator: workTimeGenerator))); } - public static Props Props(ActorPaths actorPaths, Configuration configuration, long time, SimulationType simtype, long maxBucketSize, string dbConnectionStringGanttPlan, string dbConnectionStringMaster, WorkTimeGenerator workTimeGenerator, bool debug, IActorRef principal) + public static Props Props(ActorPaths actorPaths, Configuration configuration, long time, SimulationType simtype, long maxBucketSize, string dbConnectionStringGanttPlan, string dbConnectionStringMaster, string pathToGANTTPLANOptRunner, WorkTimeGenerator workTimeGenerator, bool debug, IActorRef principal) { - return Akka.Actor.Props.Create(factory: () => new Hub(actorPaths, configuration, time, simtype, maxBucketSize, dbConnectionStringGanttPlan, dbConnectionStringMaster, workTimeGenerator, debug, principal)); + return Akka.Actor.Props.Create(factory: () => new Hub(actorPaths, configuration, time, simtype, maxBucketSize, dbConnectionStringGanttPlan, dbConnectionStringMaster, pathToGANTTPLANOptRunner, workTimeGenerator, debug, principal)); } - public Hub(ActorPaths actorPaths, Configuration configuration, long time, SimulationType simtype, long maxBucketSize, string dbConnectionStringGanttPlan, string dbConnectionStringMaster, WorkTimeGenerator workTimeGenerator, bool debug, IActorRef principal) + public Hub(ActorPaths actorPaths, Configuration configuration, long time, SimulationType simtype, long maxBucketSize, string dbConnectionStringGanttPlan, string dbConnectionStringMaster, string pathToGANTTPLANOptRunner, WorkTimeGenerator workTimeGenerator, bool debug, IActorRef principal) : base(actorPaths: actorPaths, configuration: configuration, time, debug: debug, principal: principal) { - this.Do(o: BasicInstruction.Initialize.Create(target: Self, message: HubAgent.Behaviour.Factory.Central(dbConnectionStringGanttPlan, dbConnectionStringMaster, workTimeGenerator: workTimeGenerator))); + this.Do(o: BasicInstruction.Initialize.Create(target: Self, message: HubAgent.Behaviour.Factory.Central(dbConnectionStringGanttPlan, dbConnectionStringMaster, pathToGANTTPLANOptRunner, workTimeGenerator: workTimeGenerator))); } protected override void Finish() diff --git a/Mate.Production.Core/Agents/HubAgent/Types/Queuing/CapabilityJobStorage.cs b/Mate.Production.Core/Agents/HubAgent/Types/Queuing/CapabilityJobStorage.cs index 2ad3fb1e7..c3caa42cf 100644 --- a/Mate.Production.Core/Agents/HubAgent/Types/Queuing/CapabilityJobStorage.cs +++ b/Mate.Production.Core/Agents/HubAgent/Types/Queuing/CapabilityJobStorage.cs @@ -17,6 +17,15 @@ public CapabilityJobStorage() } + public JobQueue GetJobQueue(int requiredCapabilityId) + { + if (_jobStorage.TryGetValue(requiredCapabilityId, out var jobQueue)) + { + return jobQueue; + } + return null; + } + public void Add(IJob job, long currentTime) { if (_jobStorage.TryGetValue(job.RequiredCapability.Id, out var jobQueue)) diff --git a/Mate.Production.Core/Agents/HubAgent/Types/Queuing/JobManager.cs b/Mate.Production.Core/Agents/HubAgent/Types/Queuing/JobManager.cs index 0d92a150e..5673086ee 100644 --- a/Mate.Production.Core/Agents/HubAgent/Types/Queuing/JobManager.cs +++ b/Mate.Production.Core/Agents/HubAgent/Types/Queuing/JobManager.cs @@ -8,6 +8,7 @@ namespace Mate.Production.Core.Agents.HubAgent.Types.Queuing { public class JobManager { + JobTracker _jobTracker = new (); private List _pendingJobList { get; set; } = new List(); private CapabilityJobStorage _capabilityJobStorage { get; } private List _activeJobList { get; } = new List(); @@ -29,17 +30,7 @@ public void SetJob(IJob job, long currentTime) } _pendingJobList.Add(job); - - } - - public void Add(IJob job) - { - _pendingJobList.Add(job); - } - - public List GetNextJobQueues(long currentTime) - { - return _capabilityJobStorage.GetJobQueues(currentTime); + _jobTracker.Add(job, currentTime); } public List GetAllJobQueues(long currentTime, List availableCapabilities) @@ -74,5 +65,15 @@ internal void Remove(JobQueue jobQueue) { _capabilityJobStorage.Remove(jobQueue); } + + internal void RemoveFromJobTracker(IJob job, long time) { + _jobTracker.Remove(job, time); + } + + internal void TrackJobs(long time) + { + _jobTracker.TrackJobs(time); + } + } } diff --git a/Mate.Production.Core/Agents/HubAgent/Types/Queuing/JobTracker.cs b/Mate.Production.Core/Agents/HubAgent/Types/Queuing/JobTracker.cs new file mode 100644 index 000000000..355a1c863 --- /dev/null +++ b/Mate.Production.Core/Agents/HubAgent/Types/Queuing/JobTracker.cs @@ -0,0 +1,95 @@ +using Microsoft.EntityFrameworkCore.Query.Internal; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static IJobs; + +namespace Mate.Production.Core.Agents.HubAgent.Types.Queuing +{ + internal class JobTracker + { + //private List _jobs { get; set; } = new List(); + private Dictionary> JobDict { get; set; } = new Dictionary>(); + + StreamWriter fs = File.AppendText("C:\\temp\\queuelog_latest.csv"); + StreamWriter fsl = File.AppendText("C:\\temp\\queueLength_log_latest.csv"); + + + private List GetJobs(IJob job) + { + JobDict.TryGetValue(job.RequiredCapability.Name, out List jobs); + jobs ??= new List(); + return jobs; + } + + private void SetJobs(List jobs, string name) + { + JobDict.Remove(name); + JobDict.Add(name, jobs); + } + + private void WriteChangeSet(long time, string operation, List _jobs, string name) + { + var sorted = _jobs.Select((x, i) => new Tuple(x, i)) + .GroupBy(x => (x.Item1.StartConditions.Satisfied.ToString() + x.Item1.RequiredCapability.Id)) + .OrderByDescending(x => x.Key) + .ThenBy(x => x.Min(y => y.Item1.Priority(time))) + .SelectMany(x => x) + .Select((x, i) => new Tuple(i, x.Item1, Math.Abs(x.Item2 - i))); + + // var sorted = _jobs + // .Select((x, i) => new KeyValuePair(x, i)) + // .OrderByDescending(x => x.Key.StartConditions).ThenBy(x => x.Key.RequiredCapability).ThenBy(x => x.Key.Priority(time)) + // //.OrderBy(x => x.Key.Priority(time)) + // .Select((x, i) => new Tuple(x.Key, i - x.Value, i)) + // .ToList(); + + + _jobs = sorted.Select(x => x.Item2).ToList(); + SetJobs(_jobs, name); + + var output = name + ";" + _jobs.Count + ";" + operation + ";" ; + foreach (var d in sorted) + output = string.Concat(output, d.Item3, ";"); + fs.WriteLine(output); + + + var outputL = time + ";"; + var qlength = 0; + foreach (var keyValuePair in JobDict) { + qlength += keyValuePair.Value.Count; + } + qlength /= JobDict.Values.Count; + outputL = string.Concat(outputL, qlength, ";"); + fsl.WriteLine(outputL); + // System.Console.WriteLine("---- distance"); + //foreach (var d in sorted) + // System.Console.WriteLine("Original Pos " + d.Item3 + " Distance " + d.Item1 + " Value " + d.Item2.Prio); + + } + + public void Add(IJob job, long time) + { + var _jobs = GetJobs(job); + _jobs.RemoveAll(x => x.Key.Equals(job.Key)); + _jobs.Add(job); + + WriteChangeSet(time, "Add", _jobs, job.RequiredCapability.Name); + } + + public void Remove(IJob job, long time) + { + var _jobs = GetJobs(job); + _jobs.RemoveAll(x => x.Key.Equals(job.Key)); + WriteChangeSet(time, "Remove", _jobs, job.RequiredCapability.Name); + } + + public void TrackJobs(long time) => WriteChangeSet(time, "Sort", null, null); + + + } +} diff --git a/Mate.Production.Core/Agents/ProductionAgent/Behaviour/Default.cs b/Mate.Production.Core/Agents/ProductionAgent/Behaviour/Default.cs index 82de6634f..3099fac46 100644 --- a/Mate.Production.Core/Agents/ProductionAgent/Behaviour/Default.cs +++ b/Mate.Production.Core/Agents/ProductionAgent/Behaviour/Default.cs @@ -222,7 +222,9 @@ private void ArticleProvided(FArticleProvider fArticleProvider) Agent.DebugMessage(msg: $"Article {fArticleProvider.ArticleName} {fArticleProvider.ArticleKey} for {_articleToProduce.Article.Name} {_articleToProduce.Key} has been provided"); - _articleToProduce.ProviderList.AddRange(fArticleProvider.Provider); + var cpy = _articleToProduce.ProviderList.ToArray().ToList(); + cpy.AddRange(fArticleProvider.Provider); + _articleToProduce = _articleToProduce.UpdateProviderList(cpy); if(articleDictionary.AllProvided()) { diff --git a/Mate.Production.Core/Agents/ProductionAgent/Types/DispoArticleDictionary.cs b/Mate.Production.Core/Agents/ProductionAgent/Types/DispoArticleDictionary.cs index 7ff21e896..80900d015 100644 --- a/Mate.Production.Core/Agents/ProductionAgent/Types/DispoArticleDictionary.cs +++ b/Mate.Production.Core/Agents/ProductionAgent/Types/DispoArticleDictionary.cs @@ -9,7 +9,7 @@ namespace Mate.Production.Core.Agents.ProductionAgent.Types { public class DispoArticleDictionary { - public List DispoToArticleRelation = new List(); + private List DispoToArticleRelation = new List(); public FOperation Operation { get; set; } internal List GetAll => DispoToArticleRelation.ToList(); @@ -19,11 +19,21 @@ public DispoArticleDictionary(FOperation operation) } + public List GetProviderList => + DispoToArticleRelation.Select(x => x.Provider).ToList(); + + public void Add(IActorRef dispoRef, FArticle fArticle) { DispoToArticleRelation.Add(new ArticleProvider(dispoRef, fArticle)); } + public void Add(ArticleProvider provider) + { + DispoToArticleRelation.Add(provider); + } + + internal bool AllProvided() { return DispoToArticleRelation.All(x => x.Article.IsProvided); diff --git a/Mate.Production.Core/Agents/ProductionAgent/Types/OperationManager.cs b/Mate.Production.Core/Agents/ProductionAgent/Types/OperationManager.cs index 51208690e..4eca1acc0 100644 --- a/Mate.Production.Core/Agents/ProductionAgent/Types/OperationManager.cs +++ b/Mate.Production.Core/Agents/ProductionAgent/Types/OperationManager.cs @@ -16,7 +16,7 @@ public class OperationManager internal List GetProviderForOperation(Guid operationKey) { var articleTuple = _articleProvider.Single(x => x.Operation.Key == operationKey); - var provider = articleTuple.DispoToArticleRelation.Select(x => x.Provider).ToList(); + var provider = articleTuple.GetProviderList; return provider; } @@ -75,7 +75,7 @@ public void AddOperation(FOperation fOperation) public int CreateRequiredArticles(FArticle articleToProduce, IActorRef requestingAgent, long currentTime) { - List listAP = new List(); + List listAP = new (); var remainingDuration = articleToProduce.RemainingDuration; foreach (var fOperation in GetOperations.OrderByDescending(x => x.Operation.HierarchyNumber)) { remainingDuration += fOperation.Operation.Duration; @@ -96,7 +96,7 @@ public int CreateRequiredArticles(FArticle articleToProduce, IActorRef requestin , customerDue: articleToProduce.CustomerDue , currentTime: currentTime)); listAP.Add(createdArticleProvider); - provider.DispoToArticleRelation.Add(createdArticleProvider); + provider.Add(createdArticleProvider); } } return listAP.Count; diff --git a/Mate.Production.Core/Agents/ResourceAgent/Behaviour/Default.cs b/Mate.Production.Core/Agents/ResourceAgent/Behaviour/Default.cs index fb94671cd..f1daa1aa8 100644 --- a/Mate.Production.Core/Agents/ResourceAgent/Behaviour/Default.cs +++ b/Mate.Production.Core/Agents/ResourceAgent/Behaviour/Default.cs @@ -5,13 +5,16 @@ using Mate.DataCore.DataModel; using Mate.DataCore.Nominal; using Mate.DataCore.Nominal.Model; +using Mate.Production.Core.Agents.CollectorAgent.Types; using Mate.Production.Core.Agents.HubAgent; +using Mate.Production.Core.Agents.HubAgent.Types; using Mate.Production.Core.Agents.JobAgent; using Mate.Production.Core.Agents.ResourceAgent.Types; using Mate.Production.Core.Agents.ResourceAgent.Types.TimeConstraintQueue; using Mate.Production.Core.Helper; using Mate.Production.Core.Helper.DistributionProvider; using Mate.Production.Core.Types; +using static FBuckets; using static FResourceInformations; using Directory = Mate.Production.Core.Agents.DirectoryAgent.Directory; using LogLevel = NLog.LogLevel; @@ -114,9 +117,13 @@ internal void SetHubAgent(IActorRef hubAgent) private void RevokeJob(Guid jobKey) { - var revokedJob = _jobInProgress.RevokeJob(jobKey); + var (position, revokedJob) = _jobInProgress.RevokeJob(jobKey); if (revokedJob != null) { + foreach(var element in ((FBucket)revokedJob.Job).Operations) + { + (var duration, var opPosition) = _jobInProgress.GetTotalOperationsOfJobInProgress(element.Key,Agent.CurrentTime); + } Agent.DebugMessage(msg: $"Revoking Job from Processing {revokedJob.Job.Name} {revokedJob.Job.Key}", CustomLogger.JOB, LogLevel.Warn); Agent.Send(instruction: Job.Instruction.AcknowledgeRevoke.Create(message: Agent.Context.Self, target: revokedJob.JobAgentRef)); UpdateProcessingItem(); @@ -448,13 +455,15 @@ private void RequeueJobs(HashSet toRequeue) foreach (var job in toRequeue) { Agent.DebugMessage(msg: $"Remove for requeue {job.Job.Name} {job.Key} from {Agent.Context.Self.Path.Name}", CustomLogger.JOB, LogLevel.Warn); + _scopeQueue.RemoveJob(job); Agent.Send(instruction: Job.Instruction.StartRequeue.Create(target: job.JobAgentRef)); } } -#endregion -#region Reporting + #endregion + + #region Reporting void CreateProcessingTask(FOperations.FOperation item) { @@ -488,7 +497,7 @@ void CreateSetupTask(long gap, string type) Agent.Context.System.EventStream.Publish(@event: pub); } -#endregion + #endregion } } diff --git a/Mate.Production.Core/Agents/ResourceAgent/Types/JobInProgress.cs b/Mate.Production.Core/Agents/ResourceAgent/Types/JobInProgress.cs index 8ac59b120..7413e1ff5 100644 --- a/Mate.Production.Core/Agents/ResourceAgent/Types/JobInProgress.cs +++ b/Mate.Production.Core/Agents/ResourceAgent/Types/JobInProgress.cs @@ -3,9 +3,11 @@ using System.Linq; using Akka.Actor; using Mate.DataCore.DataModel; +using MathNet.Numerics.Statistics; using static FBuckets; using static FOperations; using static IConfirmations; +using static IJobs; namespace Mate.Production.Core.Agents.ResourceAgent.Types { @@ -24,8 +26,9 @@ public class JobInProgress public bool IsWorking {get; private set; } = false; private Queue _finalOperations { get; set; } = new Queue(); public bool ResetIsWorking() => IsWorking = false; + public int HasCurrent=> Current != null ? 1 : 0; - #region Passthrough Properties + #region Passthrough Properties public long JobDuration => Current.Job.Duration; public long JobMaxDuration => ((FBucket) Current.Job).MaxBucketSize; public int ResourceCapabilityId => Current.CapabilityProvider.ResourceCapabilityId; @@ -38,6 +41,77 @@ public class JobInProgress public List GanttItems => this.ReadyElements.Values.ToList(); public bool IsCurrentDelayed(long currentTime) => Current.ScopeConfirmation.GetScopeStart() < currentTime; public M_ResourceCapabilityProvider CapabilityProvider => Current.CapabilityProvider; + public int GetTotalOperationsOfJobInProgress() + { + int operations = 0; + int durationOperations = 0; + if (ReadyElements.Count > 0) + { + foreach (var element in ReadyElements) + { + operations += ((FBucket)element.Value.Job).Operations.Count(); + } + } + if(HasCurrent == 1) + { + operations += ((FBucket)Current.Job).Operations.Count(); + } + + return operations; + } + + public (int, int) GetTotalOperationsOfJobInProgress(Guid operationId, long currentTime) + { + int operations = 0; + int durationOperations = 0; + IJob operation = null; + + if (HasCurrent == 1) + operation = ((FBucket)Current.Job).Operations.SingleOrDefault(x => x.Key.Equals(operationId)) as IJob; + + //Wenn es in dem aktuellen Element ist + if (operation != null) + { + var jobPrio = operation.Priority(currentTime); + operations += ((FBucket)Current.Job).Operations.Count(x => ((IJob)x).Priority(currentTime) < jobPrio); + durationOperations += ((FBucket)Current.Job).Operations.Where(x => ((IJob)x).Priority(currentTime) < jobPrio).Sum(y => y.Operation.Duration); + } + //Ansonsten, wenn es in den ReadyElementen ist + else + { + if (HasCurrent == 1) + { + operations += ((FBucket)Current.Job).Operations.Count(); + } + IJob element = null; + foreach (var item in ReadyElements) + { + //Gehe solange über die Liste, bis du das Element in den Operationen gefunden hast + while (element == null) + { + var tmp = item.Value.Job as FBucket; + element = tmp.Operations.SingleOrDefault(x => x.Key.Equals(operationId)); + //((FBucket)ReadyElements.ToArray()[i].Job).Operations.SingleOrDefault(x => x.Key.Equals(operationId)); + + //Wenn das Element noch nicht in der Liste ist, nimm alle Operationen aus dieser Liste + if (element == null) + { + operations += tmp.Operations.Count; + break; + } + + var jobPrio = element.Priority(currentTime); + operations += tmp.Operations.Count(x => ((IJob)x).Priority(currentTime) < jobPrio); + durationOperations += tmp.Operations.Where(x => ((IJob)x).Priority(currentTime) < jobPrio).Sum(y => y.Operation.Duration); + + } + } + } + return (durationOperations, operations); + } + + + #endregion public void StartProcessing(long currentTime, long duration) @@ -101,19 +175,28 @@ public void Reset() _finalOperations = new (); } - public IConfirmation RevokeJob(Guid confirmationKey) + public (int, IConfirmation) RevokeJob(Guid confirmationKey) { if (IsSet && Current.Key.Equals(confirmationKey)) { var rev = Current; Reset(); - return rev; + return (0, rev); } var (key, revoked) = ReadyElements.FirstOrDefault(x => x.Value.Key.Equals(confirmationKey)); - if (revoked == null) return null; + if (revoked == null) return (0, null); ReadyElements.Remove(key); - return revoked; + return (JobPosition(revoked), revoked); + } + + public int JobPosition(IConfirmation job) + { + var position = 0; + if (IsSet) + position = position + ((FBucket)Current.Job).Operations.Count(); + position = position + ReadyElements.IndexOfKey(job.ScopeConfirmation.GetScopeStart()); + return position; } public void Add(IConfirmation confirmation) diff --git a/Mate.Production.Core/Agents/ResourceAgent/Types/TimeConstraintQueue/TimeConstraintQueue.cs b/Mate.Production.Core/Agents/ResourceAgent/Types/TimeConstraintQueue/TimeConstraintQueue.cs index 520562cfe..fdc313fb8 100644 --- a/Mate.Production.Core/Agents/ResourceAgent/Types/TimeConstraintQueue/TimeConstraintQueue.cs +++ b/Mate.Production.Core/Agents/ResourceAgent/Types/TimeConstraintQueue/TimeConstraintQueue.cs @@ -9,6 +9,7 @@ using static FScopes; using static IConfirmations; using static IJobs; +using static FScopeConfirmations; namespace Mate.Production.Core.Agents.ResourceAgent.Types.TimeConstraintQueue { @@ -16,6 +17,7 @@ public class TimeConstraintQueue : SortedList, IJobQueue { public long Limit { get; set; } public long Workload => this.Values.Sum(x => x.Job.Duration); + public TimeConstraintQueue(long limit) { Limit = limit; @@ -346,6 +348,35 @@ public bool QueueHealthCheck(long currentTime) } + public int GetAmountOfPreviousOperations(long scopeStart) + { + int operations = 0; + var index = this.IndexOfKey(scopeStart); + + foreach(var element in this.Where(x => x.Key < index)) + { + operations += ((FBucket)element.Value.Job).Operations.Count(); + + } + + return operations; + } + + public (long, int) GetPositionOfJobInJob(long scopeStart, Guid operationId, long currentTime) + { + int operations = 0; + long duration = 0; + var bucket = ((FBucket)this[scopeStart].Job); + var operation = bucket.Operations.Single(x => x.Key == operationId) as IJob; + foreach (var element in bucket.Operations.Cast().Where(x => x.Priority(currentTime) < operation.Priority(currentTime))) + { + operations++; + duration += element.Duration; + } + + return (duration, operations); + } + } } diff --git a/Mate.Production.Core/Agents/StorageAgent/Behaviour/Default.cs b/Mate.Production.Core/Agents/StorageAgent/Behaviour/Default.cs index b50a917b0..00597adf1 100644 --- a/Mate.Production.Core/Agents/StorageAgent/Behaviour/Default.cs +++ b/Mate.Production.Core/Agents/StorageAgent/Behaviour/Default.cs @@ -52,6 +52,7 @@ private void RequestArticle(FArticle requestItem) var stockReservation = MakeReservationFor(request: item); if (!stockReservation.IsInStock || item.Article.ToBuild) { + item = item.UpdateProviderList(p: new List()); // add to Request queue if not in Stock _requestedArticles.Add(item: item); } @@ -177,7 +178,7 @@ private void ProvideArticle(Guid articleKey) , stockExchangeId: article.StockExchangeId , articleFinishedAt: article.FinishedAt , customerDue: article.CustomerDue - , provider: article.ProviderList) + , provider: article.ProviderList.ToArray().ToList()) , target: article.DispoRequester , logThis: false)); diff --git a/Mate.Production.Core/Environment/Options/GANTTPLANOptRunnerPath.cs b/Mate.Production.Core/Environment/Options/GANTTPLANOptRunnerPath.cs new file mode 100644 index 000000000..59cf875dc --- /dev/null +++ b/Mate.Production.Core/Environment/Options/GANTTPLANOptRunnerPath.cs @@ -0,0 +1,20 @@ +using System; +using Mate.Production.Core.Environment.Abstractions; + +namespace Mate.Production.Core.Environment.Options +{ + public class GANTTPLANOptRunnerPath : Option + { + public GANTTPLANOptRunnerPath(string value) + { + _value = value; + } + + public GANTTPLANOptRunnerPath() + { + Action = (config, argument) => { + config.AddOption(o: new GANTTPLANOptRunnerPath(value: argument)); + }; + } + } +} diff --git a/Mate.Production.Core/Environment/Options/MaxQuantity.cs b/Mate.Production.Core/Environment/Options/MaxQuantity.cs new file mode 100644 index 000000000..ef759f8f4 --- /dev/null +++ b/Mate.Production.Core/Environment/Options/MaxQuantity.cs @@ -0,0 +1,20 @@ +using System; +using Mate.Production.Core.Environment.Abstractions; + +namespace Mate.Production.Core.Environment.Options +{ + public class MaxQuantity : Option + { + public MaxQuantity(int value) + { + _value = value; + } + + public MaxQuantity() + { + Action = (config, argument) => { + config.AddOption(o: new MaxQuantity(value: int.Parse(s: argument))); + }; + } + } +} diff --git a/Mate.Production.Core/Environment/Options/MinQuantity.cs b/Mate.Production.Core/Environment/Options/MinQuantity.cs new file mode 100644 index 000000000..3a4fde08e --- /dev/null +++ b/Mate.Production.Core/Environment/Options/MinQuantity.cs @@ -0,0 +1,20 @@ +using System; +using Mate.Production.Core.Environment.Abstractions; + +namespace Mate.Production.Core.Environment.Options +{ + public class MinQuantity : Option + { + public MinQuantity(int value) + { + _value = value; + } + + public MinQuantity() + { + Action = (config, argument) => { + config.AddOption(o: new MinQuantity(value: int.Parse(s: argument))); + }; + } + } +} diff --git a/Mate.Production.Core/GanttSimulation.cs b/Mate.Production.Core/GanttSimulation.cs index a26226620..1028247fc 100644 --- a/Mate.Production.Core/GanttSimulation.cs +++ b/Mate.Production.Core/GanttSimulation.cs @@ -174,6 +174,7 @@ private void CreateHubAgent(IActorRef directory, Configuration configuration) var hubInfo = new FResourceHubInformation(resourceList: _resourceDictionary , dbConnectionString: dbGantt.ConnectionString.Value , masterDbConnectionString: base.DbProduction.ConnectionString.Value + , pathToGANTTPLANOptRunner: configuration.GetOption().Value , workTimeGenerator: randomWorkTime); Simulation.SimulationContext.Tell( message: Directory.Instruction.Central.CreateHubAgent.Create(hubInfo, directory), diff --git a/Mate.Production.Core/Helper/DistributionProvider/DeflectionGenerator.cs b/Mate.Production.Core/Helper/DistributionProvider/DeflectionGenerator.cs index eff76f322..8c5bec29c 100644 --- a/Mate.Production.Core/Helper/DistributionProvider/DeflectionGenerator.cs +++ b/Mate.Production.Core/Helper/DistributionProvider/DeflectionGenerator.cs @@ -13,7 +13,7 @@ public class DeflectionGenerator Random _random = null; public DeflectionGenerator(int seed) { - var random = new Random(Seed: seed); + _random = new Random(Seed: seed); } diff --git a/Mate.Production.Core/Helper/DistributionProvider/OrderGenerator.cs b/Mate.Production.Core/Helper/DistributionProvider/OrderGenerator.cs index b30b67b71..ecd82f279 100644 --- a/Mate.Production.Core/Helper/DistributionProvider/OrderGenerator.cs +++ b/Mate.Production.Core/Helper/DistributionProvider/OrderGenerator.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Mate.DataCore.Data.Context; +using Mate.DataCore.Data.Context; using Mate.DataCore.Data.Initializer.StoredProcedures; using Mate.DataCore.DataModel; using Mate.Production.Core.Environment; using Mate.Production.Core.Environment.Options; using MathNet.Numerics.Distributions; +using System; +using System.Collections.Generic; +using System.Linq; namespace Mate.Production.Core.Helper.DistributionProvider { @@ -17,6 +17,7 @@ public class OrderGenerator private Random _seededRandom { get; set; } private Exponential _exponential { get; set; } private DiscreteUniform _prodVariation { get; set; } + private DiscreteUniform _amountVariation { get; set; } private ContinuousUniform _duetime { get; set; } private MateProductionDb _productionDomainContext { get; } @@ -35,6 +36,11 @@ public OrderGenerator(Configuration simConfig, MateProductionDb productionDomain //get equal distribution from 0 to 1 _prodVariation = new DiscreteUniform(lower: 0, upper: _productIds.Count() - 1, randomSource: _seededRandom); + //get equal distribution from 0 to 1 + _amountVariation = new DiscreteUniform(lower: simConfig.GetOption().Value + , upper: simConfig.GetOption().Value + , randomSource: _seededRandom); + //get equal distribution for duetime //TODO: Change Option from int to double _duetime = new ContinuousUniform(lower: Convert.ToDouble(simConfig.GetOption().Value) @@ -77,8 +83,10 @@ public T_CustomerOrder GetNewRandomOrder(long time) due = time + creationTime + due; System.Diagnostics.Debug.WriteLineIf(condition: _debug, message: "Product(" + productId + ")" + ";" + time + ";" + due); + var amount = _amountVariation.Sample(); + // only Returns new Order does not save context. - var order = _productionDomainContext.CreateNewOrder(articleId: productId, amount: 1, creationTime: time + creationTime, dueTime: due); + var order = _productionDomainContext.CreateNewOrder(articleId: productId, amount: amount, creationTime: time + creationTime, dueTime: due); return order; } } diff --git a/Mate.Production.Core/Helper/DistributionProvider/OrderGeneratorPerformance.cs b/Mate.Production.Core/Helper/DistributionProvider/OrderGeneratorPerformance.cs index 6dac8b149..1f9c6fa9d 100644 --- a/Mate.Production.Core/Helper/DistributionProvider/OrderGeneratorPerformance.cs +++ b/Mate.Production.Core/Helper/DistributionProvider/OrderGeneratorPerformance.cs @@ -29,8 +29,7 @@ public class OrderGeneratorPerformance : IOrderGenerator public OrderGeneratorPerformance(Configuration simConfig, List productIds, IEnumerable articles, IEnumerable businessPartners) { - _seededRandom = new Random(Seed: simConfig.GetOption().Value + - simConfig.GetOption().Value); + _seededRandom = new Random(Seed: simConfig.GetOption().Value); _exponential = new Exponential(rate: simConfig.GetOption().Value, randomSource: _seededRandom); _productIds = productIds; diff --git a/Mate.Production.Core/Helper/DistributionProvider/WorkTimeGenerator.cs b/Mate.Production.Core/Helper/DistributionProvider/WorkTimeGenerator.cs index 8a1eea3b3..d9ce4b8b8 100644 --- a/Mate.Production.Core/Helper/DistributionProvider/WorkTimeGenerator.cs +++ b/Mate.Production.Core/Helper/DistributionProvider/WorkTimeGenerator.cs @@ -42,7 +42,25 @@ public long GetRandomWorkTime(long duration) long newDuration; while (true) { - newDuration = (long)LogNormal.WithMeanVariance(duration, duration * _deviation, _sourceRandom).Sample(); + newDuration = (long)Math.Round(LogNormal.WithMeanVariance(duration, duration * _deviation, _sourceRandom).Sample()); + + //newDuration = (long)Math.Round(value: duration * _distribution.Sample(), mode: MidpointRounding.AwayFromZero); + if (newDuration <= 3 * duration) break; + } + return newDuration > 1 ? newDuration : 1; + } + + public long GetRandomWorkTime(long duration, int hash) + { + if (_deviation == 0.0) + return duration; + + _sourceRandom = new Random(Seed: hash ); + + long newDuration; + while (true) + { + newDuration = (long)Math.Round(LogNormal.WithMeanVariance(duration, duration * _deviation, _sourceRandom).Sample()); //newDuration = (long)Math.Round(value: duration * _distribution.Sample(), mode: MidpointRounding.AwayFromZero); if (newDuration <= 3 * duration) break; diff --git a/Mate.Production.Core/Mate.Production.Core.csproj b/Mate.Production.Core/Mate.Production.Core.csproj index 52ba3f08a..c5baef78a 100644 --- a/Mate.Production.Core/Mate.Production.Core.csproj +++ b/Mate.Production.Core/Mate.Production.Core.csproj @@ -11,7 +11,6 @@ - diff --git a/Mate.Production.Immutables/Mate.Production.Immutables.fsproj b/Mate.Production.Immutables/Mate.Production.Immutables.fsproj index 482c04ddd..9eb45e4ee 100644 --- a/Mate.Production.Immutables/Mate.Production.Immutables.fsproj +++ b/Mate.Production.Immutables/Mate.Production.Immutables.fsproj @@ -78,6 +78,7 @@ + diff --git a/Mate.Production.Immutables/Message/Central/FCentralResourceHubInformations.fs b/Mate.Production.Immutables/Message/Central/FCentralResourceHubInformations.fs index f417350a7..a1cb8f66c 100644 --- a/Mate.Production.Immutables/Message/Central/FCentralResourceHubInformations.fs +++ b/Mate.Production.Immutables/Message/Central/FCentralResourceHubInformations.fs @@ -3,5 +3,6 @@ ResourceList : obj DbConnectionString : string MasterDbConnectionString : string + PathToGANTTPLANOptRunner : string WorkTimeGenerator: obj } \ No newline at end of file diff --git a/Mate.Test/Online/Integration/ProductionTest.cs b/Mate.Test/Online/Integration/ProductionTest.cs index 4d18219bd..6714195c1 100644 --- a/Mate.Test/Online/Integration/ProductionTest.cs +++ b/Mate.Test/Online/Integration/ProductionTest.cs @@ -75,7 +75,7 @@ public ProductionTest(ITestOutputHelper testOutputHelper) _testOutputHelper.WriteLine("MateDB Initialization finished"); ResultDBInitializerBasic.DbInitialize(_resultContextDataBase.DbContext); _testOutputHelper.WriteLine("ResultD Basic Initialization finished"); - var messageHub = new ConsoleHub(); + var messageHub = new LoggingHub(); var simConfig = ArgumentConverter.ConfigurationConverter(_resultContextDataBase.DbContext, 1); simConfig.AddOption(new ResultsDbConnectionString(_resultContextDataBase.ConnectionString.Value)); simConfig.ReplaceOption(new TimeToAdvance(new TimeSpan(0L))); diff --git a/Mate.Test/SimulationEnvironment/AgentSystem.cs b/Mate.Test/SimulationEnvironment/AgentSystem.cs index 7d1529ce4..4b30f7912 100644 --- a/Mate.Test/SimulationEnvironment/AgentSystem.cs +++ b/Mate.Test/SimulationEnvironment/AgentSystem.cs @@ -1,4 +1,7 @@ +using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading.Tasks; using Akka.TestKit.Xunit; @@ -14,22 +17,30 @@ using Mate.DataCore.Nominal.Model; using Mate.Production.CLI; using Mate.Production.Core; +using Mate.Production.Core.Agents.CollectorAgent.Types; using Mate.Production.Core.Environment.Options; using Mate.Production.Core.Helper; +using MathNet.Numerics.Distributions; using Microsoft.EntityFrameworkCore; using NLog; using Xunit; +using Xunit.Abstractions; +using static Akka.IO.Tcp; using PriorityRule = Mate.DataCore.Nominal.PriorityRule; namespace Mate.Test.SimulationEnvironment { - public class AgentSystem : TestKit, IClassFixture + public class AgentSystem : TestKit//, IClassFixture { - private SeedInitializer seedInitializer = new SeedInitializer(); - private readonly string TestMateDb = "Test" + DataBaseConfiguration.MateDb; private readonly string TestMateResultDb = "Test" + DataBaseConfiguration.MateResultDb; + private readonly string logPath = @"C:\temp\TestTracker.txt"; + + StreamWriter _streamWriter; + public AgentSystem() { + _streamWriter = new StreamWriter(logPath); + } [Fact] public void TestRawSQL() @@ -153,7 +164,7 @@ public void SomethingToPlayWith() } } - + private void GetSetups(M_Resource resource, MateProductionDb masterCtx) { if (!resource.IsPhysical) @@ -186,7 +197,7 @@ private void GetSetups(M_Resource resource, MateProductionDb masterCtx) public static IEnumerable GetTestData() { var simNumber = 0; - var throughput = 1920; + var throughput = 10080; for (int i = 0; i < 1; i++) { @@ -212,31 +223,19 @@ public static IEnumerable GetTestData() //[MemberData(nameof(GetTestData))] //public async Task SystemTestAsync(SimulationType simulationType, PriorityRule priorityRule, int simNr, int maxBucketSize, long throughput, int seed , ModelSize resourceModelSize, ModelSize setupModelSize, double arrivalRate, bool distributeSetupsExponentially, bool createMeasurements = false) - + + [Theory] - //[InlineData(SimulationType.Default, 1700, 0.00)] - [InlineData(SimulationType.Default, 1705, 0.05)] - [InlineData(SimulationType.Default, 1710, 0.10)] - [InlineData(SimulationType.Default, 1715, 0.15)] - //[InlineData(SimulationType.Default, 1720, 0.20)] - [InlineData(SimulationType.Default, 1725, 0.25)] - [InlineData(SimulationType.Default, 1730, 0.30)] - [InlineData(SimulationType.Default, 1735, 0.35)] - [InlineData(SimulationType.Central, 2700, 0.00)] - [InlineData(SimulationType.Central, 2705, 0.05)] - [InlineData(SimulationType.Central, 2710, 0.10)] - [InlineData(SimulationType.Central, 2715, 0.15)] - [InlineData(SimulationType.Central, 2720, 0.20)] - [InlineData(SimulationType.Central, 2725, 0.25)] - [InlineData(SimulationType.Central, 2730, 0.30)] - [InlineData(SimulationType.Central, 2735, 0.35)] - public async Task AgentSystemTest(SimulationType simulationType, int simNr, double deviation) + // [x] [InlineData(SimulationType.Default, 110, 0.00, 0.035, 1337)] // throughput dynamic ruled + [InlineData(SimulationType.Queuing, 44, 0.0, 0.020, 169)] + public async Task AgentSystemTest(SimulationType simulationType, int simNr, double deviation, double arrivalRateRun, int seed + , int seedDataGen = 5, double reuse = 1.0, double complxity = 1.0, double organziationaldegree = 0.8, int numberOfSalesMaterials = 50, int verticalIntegration = 2) { - //var simNr = 2; + //var simNr = Random.Shared.Next(); //var simulationType = SimulationType.Default; - var seed = 169; - var throughput = 1920; - var arrivalRate = 0.035; + + var throughput = 1440 * 5; + var arrivalRate = arrivalRateRun; //LogConfiguration.LogTo(TargetTypes.Debugger, TargetNames.LOG_AGENTS, LogLevel.Trace, LogLevel.Trace); LogConfiguration.LogTo(TargetTypes.Debugger, TargetNames.LOG_AGENTS, LogLevel.Info, LogLevel.Info); @@ -258,62 +257,65 @@ public async Task AgentSystemTest(SimulationType simulationType, int simNr, doub //dbResult.DbContext.Database.EnsureCreated(); //ResultDBInitializerBasic.DbInitialize(dbResult.DbContext); - seedInitializer.GenerateTestData(TestMateDb); + DataCore.Data.Seed.SeedInitializer seedInitializer = new (); + seedInitializer.GenerateTestData(TestMateDb, machineCount: 4, toolCount: 6 + // , number of Worker + // , number of Products + , seed: seedDataGen + , reuseRatio: reuse + , complexityRatio: complxity + , organizationalDegree: organziationaldegree + , numberOfSalesMaterials: numberOfSalesMaterials + , verticalIntegration: verticalIntegration); - //dbMaster.DbContext.Database.EnsureDeleted(); - //dbMaster.DbContext.Database.EnsureCreated(); - //MasterDBInitializerTruck.DbInitialize(context: dbMaster.DbContext - // , resourceModelSize: resourceModelSize - // , setupModelSize: setupModelSize - // , operatorsModelSize: ModelSize.Small - // , numberOfWorkersForProcessing: 3 - // , secondResource: false - // , createMeasurements: createMeasurements - // , distributeSetupsExponentially: distributeSetupsExponentially); - //InMemoryContext.LoadData(source: _masterDBContext, target: _ctx); - var simConfig = Production.CLI.ArgumentConverter.ConfigurationConverter(dbResult.DbContext, 1); // update customized Items simConfig.AddOption(new ResultsDbConnectionString(dbResult.ConnectionString.Value)); - simConfig.ReplaceOption(new KpiTimeSpan(240)); - simConfig.ReplaceOption(new TimeConstraintQueueLength(480)); + simConfig.ReplaceOption(new GANTTPLANOptRunnerPath("D:\\Work\\GANTTPLAN\\GanttPlanOptRunner.exe")); + simConfig.ReplaceOption(new KpiTimeSpan(1440)); + simConfig.ReplaceOption(new TimeConstraintQueueLength(480 * 6 * 2)); // = schicht * setups * x simConfig.ReplaceOption(new SimulationKind(value: simulationType)); simConfig.ReplaceOption(new OrderArrivalRate(value: arrivalRate)); - simConfig.ReplaceOption(new OrderQuantity(value: 10000)); + simConfig.ReplaceOption(new OrderQuantity(value: 1000)); simConfig.ReplaceOption(new EstimatedThroughPut(value: throughput)); simConfig.ReplaceOption(new TimePeriodForThroughputCalculation(value: 4000)); simConfig.ReplaceOption(new Production.Core.Environment.Options.Seed(value: seed)); - simConfig.ReplaceOption(new SettlingStart(value: 2880)); - simConfig.ReplaceOption(new MinDeliveryTime(value: 10)); - simConfig.ReplaceOption(new MaxDeliveryTime(value: 15)); - simConfig.ReplaceOption(new SimulationEnd(value: 10080*3)); + simConfig.ReplaceOption(new SettlingStart(value: 1440)); + simConfig.ReplaceOption(new MinQuantity(value: 1)); + simConfig.ReplaceOption(new MaxQuantity(value: 1)); + simConfig.ReplaceOption(new MinDeliveryTime(value: 11)); + simConfig.ReplaceOption(new MaxDeliveryTime(value: 18)); + simConfig.ReplaceOption(new SimulationEnd(value: 1440 * 30)); simConfig.ReplaceOption(new SaveToDB(value: true)); - simConfig.ReplaceOption(new DebugSystem(value: false)); - simConfig.ReplaceOption(new DebugAgents(value: false)); + simConfig.ReplaceOption(new DebugSystem(value: true)); + simConfig.ReplaceOption(new DebugAgents(value: true)); simConfig.ReplaceOption(new WorkTimeDeviation(deviation)); - simConfig.ReplaceOption(new MaxBucketSize(value: 1920)); + simConfig.ReplaceOption(new MaxBucketSize(value: 480 * 6 * 2)); // = schicht * setups * x simConfig.ReplaceOption(new SimulationNumber(value: simNr)); simConfig.ReplaceOption(new CreateQualityData(false)); simConfig.ReplaceOption(new Mate.Production.Core.Environment.Options.PriorityRule(PriorityRule.LST)); ClearResultDBby(simNr: simConfig.GetOption(), dbName: TestMateResultDb); - BaseSimulation simContext = null; + BaseSimulation simContext; - if (simulationType == SimulationType.Default) - { - simContext = new AgentSimulation(TestMateDb, messageHub: new ConsoleHub()); - } - else + Action consoleWriter = (listnerToWrite, msgToWrite) => { if (listnerToWrite == "Contracts") { _streamWriter.WriteLine(msgToWrite); } }; + + if (simulationType == SimulationType.Central) { var ganttPlanContext = Dbms.GetGanttDataBase(DataBaseConfiguration.GP); ganttPlanContext.DbContext.Database.ExecuteSqlRaw("EXEC sp_MSforeachtable 'DELETE FROM ? '"); //Synchronisation GanttPlan - GanttPlanOptRunner.RunOptAndExport("Init", "C:\\Users\\admin\\GANTTPLAN\\GanttPlanOptRunner.exe"); - - simContext = new GanttSimulation(dbName: TestMateDb, messageHub: new ConsoleHub()); + GanttPlanOptRunner.RunOptAndExport("Init", simConfig.GetOption().Value); + //simContext = new GanttSimulation(dbName: TestMateDb, messageHub: new LoggingHub()); + simContext = new GanttSimulation(dbName: TestMateDb, messageHub: new ConsoleHub(consoleWriter)); + } + else + { + //simContext = new AgentSimulation(TestMateDb, messageHub: new LoggingHub()); + simContext = new AgentSimulation(TestMateDb, messageHub: new ConsoleHub(consoleWriter)); } var simulation = await simContext.InitializeSimulation(configuration: simConfig); @@ -361,11 +363,13 @@ private void ClearResultDBby(SimulationNumber simNr, string dbName) _ctxResult.RemoveRange(entities: itemsToRemove); _ctxResult.RemoveRange(entities: _ctxResult.Kpis.Where(predicate: a => a.SimulationNumber.Equals(_simNr.Value))); _ctxResult.RemoveRange(entities: _ctxResult.StockExchanges.Where(predicate: a => a.SimulationNumber.Equals(_simNr.Value))); + _ctxResult.RemoveRange(entities: _ctxResult.TaskItems.Where(predicate: a => a.SimulationNumber.Equals(_simNr.Value))); + _ctxResult.RemoveRange(entities: _ctxResult.SimulationOrders.Where(predicate: a => a.SimulationNumber.Equals(_simNr.Value))); + _ctxResult.RemoveRange(entities: _ctxResult.SimulationResourceSetups.Where(predicate: a => a.SimulationNumber.Equals(_simNr.Value))); _ctxResult.SaveChanges(); } } - [Fact] private void TestDbms() { diff --git a/Mate.Test/SimulationEnvironment/BenchmarkBucketSize.cs b/Mate.Test/SimulationEnvironment/BenchmarkBucketSize.cs index 457ee347b..6d3b73fe6 100644 --- a/Mate.Test/SimulationEnvironment/BenchmarkBucketSize.cs +++ b/Mate.Test/SimulationEnvironment/BenchmarkBucketSize.cs @@ -35,7 +35,7 @@ public class BenchmarkBucketSize public async Task BucketSizeTest() { //InMemoryContext.LoadData(source: _masterDBContext, target: _ctx); - var simContext = new AgentSimulation(dbName: TestMateDb, messageHub: new ConsoleHub()); + var simContext = new AgentSimulation(dbName: TestMateDb, messageHub: new LoggingHub()); var simConfig = Production.Core.Environment.Configuration.Create(args: new object[] { diff --git a/Mate.Test/SimulationEnvironment/BenchmarksOrderArrival.cs b/Mate.Test/SimulationEnvironment/BenchmarksOrderArrival.cs index baef876e2..2362b3883 100644 --- a/Mate.Test/SimulationEnvironment/BenchmarksOrderArrival.cs +++ b/Mate.Test/SimulationEnvironment/BenchmarksOrderArrival.cs @@ -35,7 +35,7 @@ public class BenchmarksOrderArrivalTest public async Task BenchmarksOrderArrival() { //InMemoryContext.LoadData(source: _masterDBContext, target: _ctx); - var simContext = new AgentSimulation(dbName: TestMateDb, messageHub: new ConsoleHub()); + var simContext = new AgentSimulation(dbName: TestMateDb, messageHub: new LoggingHub()); var simConfig = Mate.Production.Core.Environment.Configuration.Create(args: new object[] { diff --git a/Mate.Test/SimulationEnvironment/CentralSystem.cs b/Mate.Test/SimulationEnvironment/CentralSystem.cs index b07010d46..76a39815a 100644 --- a/Mate.Test/SimulationEnvironment/CentralSystem.cs +++ b/Mate.Test/SimulationEnvironment/CentralSystem.cs @@ -108,9 +108,9 @@ public async Task CentralSystemTest() ganttPlanContext.DbContext.Database.ExecuteSqlRaw("EXEC sp_MSforeachtable 'DELETE FROM ? '"); //Synchronisation GanttPlan - GanttPlanOptRunner.RunOptAndExport("Init", "D:\\Work\\GANTTPLAN\\GanttPlanOptRunner.exe"); + GanttPlanOptRunner.RunOptAndExport("Init", "C:\\tools\\Ganttplan\\GanttPlanOptRunner.exe"); - var simContext = new GanttSimulation(dbName: TestMateDb, messageHub: new ConsoleHub()); + var simContext = new GanttSimulation(dbName: TestMateDb, messageHub: new LoggingHub()); var simConfig = ArgumentConverter.ConfigurationConverter(masterPlanResultContext, 1); // update customized Items simConfig.AddOption(new ResultsDbConnectionString(masterPlanResultContext.Database.GetConnectionString())); @@ -122,6 +122,8 @@ public async Task CentralSystemTest() simConfig.ReplaceOption(new EstimatedThroughPut(value: throughput)); simConfig.ReplaceOption(new TimePeriodForThroughputCalculation(value: 4000)); simConfig.ReplaceOption(new Production.Core.Environment.Options.Seed(value: seed)); + simConfig.ReplaceOption(new MinQuantity(value: 1)); + simConfig.ReplaceOption(new MaxQuantity(value: 1)); simConfig.ReplaceOption(new MinDeliveryTime(value: 4)); simConfig.ReplaceOption(new MaxDeliveryTime(value: 6)); simConfig.ReplaceOption(new SettlingStart(value: 60)); @@ -237,10 +239,16 @@ public void TestGanttPlanApi() [Fact] public void GenerateRandomLogNormal() { - var _distribution = new LogNormal(mu: 2.5, sigma: 0.2); + var _sourceRandom = new Random(Seed: 169 + //TODO WARUM? + //+ simNumber + ); + + var sampler = LogNormal.WithMeanVariance(10, 10 * 0.2, _sourceRandom); for (int i = 0; i < 10000; i++) { - System.Diagnostics.Debug.WriteLine(_distribution.Sample()); + + System.Diagnostics.Debug.WriteLine(Math.Round(sampler.Sample())); } } diff --git a/Mate.Test/SimulationEnvironment/SEEDInitializer.cs b/Mate.Test/SimulationEnvironment/SEEDInitializer.cs index 53aa7ac1e..e00007287 100644 --- a/Mate.Test/SimulationEnvironment/SEEDInitializer.cs +++ b/Mate.Test/SimulationEnvironment/SEEDInitializer.cs @@ -19,28 +19,29 @@ namespace Mate.Test.SimulationEnvironment public class SeedInitializer : IDisposable { - private readonly string TestMateDb = "Test" + DataBaseConfiguration.MateDb; - public void Dispose() { } - public void GenerateTestData(string mateDbName) + public void GenerateTestData(string mateDbName, int machineCount, int toolCount + , int seed, double reuseRatio, double complexityRatio, double organizationalDegree + , int numberOfSalesMaterials, int verticalIntegration, int lambda = 2) { - + //Generate Config var seedConfig = new Configuration(); var materialConfig = new MaterialConfig() { StructureParameter = new StructureParameter() { - ComplexityRatio = 1.9, - ReuseRatio = 1.3, - NumberOfSalesMaterials = 100, - VerticalIntegration = 4 + ComplexityRatio = complexityRatio, // 1.9, + ReuseRatio = reuseRatio, // 1.3, + NumberOfSalesMaterials = numberOfSalesMaterials, + VerticalIntegration = verticalIntegration, + Seed = seed // 7 }, - TransitionMatrixParameter = new TransitionMatrixParameter() { - Lambda = 2, - OrganizationalDegree = 0.7 + TransitionMatrixParameter = new TransitionMatrixParameter() { + Lambda = lambda, + OrganizationalDegree = organizationalDegree // 0.7 } }; @@ -49,54 +50,26 @@ public void GenerateTestData(string mateDbName) var rsSaw = new ResourceGroup("Saw") - .WithResourceuQuantity(4) - .WithTools(new List { - new ResourceTool("Blade 4mm"), - new ResourceTool("Blade 6mm"), - new ResourceTool("Blade 8mm"), - new ResourceTool("Blade 10mm"), - new ResourceTool("Blade 12mm"), - new ResourceTool("Blade 14mm") - }); + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); var rsDrill = new ResourceGroup("Drill") - .WithResourceuQuantity(4) - .WithTools(new List { - new ResourceTool("Blade 4mm"), - new ResourceTool("Blade 6mm"), - new ResourceTool("Blade 8mm"), - new ResourceTool("Blade 10mm"), - new ResourceTool("Blade 12mm"), - new ResourceTool("Blade 14mm") - }); + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); var rsAssembly = new ResourceGroup("Assembly") - .WithResourceuQuantity(4) - .WithTools(new List { - new ResourceTool("Blade 4mm"), - new ResourceTool("Blade 6mm"), - new ResourceTool("Blade 8mm"), - new ResourceTool("Blade 10mm"), - new ResourceTool("Blade 12mm"), - new ResourceTool("Blade 14mm") - }); + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); var rsQuality = new ResourceGroup("Quality") - .WithResourceuQuantity(4) - .WithTools(new List { - new ResourceTool("Blade 4mm"), - new ResourceTool("Blade 6mm"), - new ResourceTool("Blade 8mm"), - new ResourceTool("Blade 10mm"), - new ResourceTool("Blade 12mm"), - new ResourceTool("Blade 14mm") - }); - - var resourceConfig = new ResourceConfig().WithResourceGroup(new List { rsSaw, rsDrill, rsAssembly, rsQuality}) + .WithResourceuQuantity(machineCount) + .WithTools(GenerateTools(toolCount)); + + var resourceConfig = new ResourceConfig().WithResourceGroup(new List { rsSaw, rsDrill, rsAssembly, rsQuality }) .WithDefaultOperationsDurationMean(TimeSpan.FromMinutes(10)) .WithDefaultOperationsDurationVariance(0.20) .WithDefaultSetupDurationMean(TimeSpan.FromMinutes(30)) - .WithDefaultOperationsAmountMean(5) + .WithDefaultOperationsAmountMean(8) .WithDefaultOperationsAmountVariance(0.20); seedConfig.WithOption(resourceConfig); @@ -136,5 +109,25 @@ public void GenerateTestData(string mateDbName) } + + private List GenerateTools(int amount) + { + var listOfTools = new List(); + var counter = 2; + + + for (int i = 0; i < amount; i++) + { + + var nameOfTool = "Blade" + counter.ToString() + "mm"; + listOfTools.Add(new ResourceTool(nameOfTool)); + counter += 2; + } + + + return listOfTools; + + } } + } diff --git a/Mate/Controllers/AgentLiveController.cs b/Mate/Controllers/AgentLiveController.cs index b4277afed..7656245e7 100644 --- a/Mate/Controllers/AgentLiveController.cs +++ b/Mate/Controllers/AgentLiveController.cs @@ -73,6 +73,8 @@ public void RunAsync(int simulationType, int orderAmount, double arivalRate,int simConfig.ReplaceOption(new DebugSystem(value: false)); simConfig.ReplaceOption(new WorkTimeDeviation(0.2)); simConfig.ReplaceOption(new MaxBucketSize(480)); + simConfig.ReplaceOption(new MinQuantity(1)); + simConfig.ReplaceOption(new MaxQuantity(1)); simConfig.ReplaceOption(new MinDeliveryTime(10)); simConfig.ReplaceOption(new MaxDeliveryTime(15)); simConfig.ReplaceOption(new Mate.Production.Core.Environment.Options.PriorityRule(value: DataCore.Nominal.PriorityRule.LST)); diff --git a/gource.ppm b/gource.ppm new file mode 100644 index 000000000..e69de29bb