using Enigmos.Boards; using Enigmos.Exceptions; using Enigmos.Modules.ControllingModules; using Enigmos.Modules.InterlayerModules; using Enigmos.Ports; using Enigmos.Ports.DataPorts; using Godot; using Nocturnis.DataStructures; using Nocturnis.DataStructures.ConfigurableParameters; using Nocturnis.DataStructures.DataPortGroups; using Nocturnis.Enigmos.Modules; using Nocturnis.Enigmos.Ports; using Nocturnis.Enigmos.Ports.DataPorts; using Nocturnis.Enigmos.Ports.DataPorts.Directions; using Nocturnis.GlobalManagement.Constants; using Nocturnis.GlobalManagement.Providers; namespace Enigmos.Modules.ProgrammableModules; public partial class OptimizationModule : ProgrammableModule, IPolymorphismModule, IParameterizedModule, IOptimizationModule { private bool OptimizationEnded { get; set; } private double? CachedOptimizeValue { get; set; } public IDataInPort? InternalIterOut { get; set; } public IDataOutPort? InternalArrayIn { get; set; } public IData CachedResult { get; set; } = GlobalProvider.DataStructureProvider!.NewData(0, EnigmosConstant.DataPortTypes.Null); private IData[] CachedInput { get; set; } = Array.Empty(); private int ProcessingIndex { get; set; } private IBoolParameter? UsingMax { get; set; } private IDataPortGroup[] InterlayerGroups { get; set; } = Array.Empty(); private IDataPortGroup? OptimizationGroup { get; set; } private DataInPort? ArrayInput { get; set; } private InterlayerDataInModule[] ExplicitInputs { get; set; } = Array.Empty(); private OptimizationItemOutputModule? ItemOut { get; set; } private OptimizationValueOutputModule? ValueOut { get; set; } public override IEnumerable Ports => new[] { ArrayInput! }; public new OptimizationModuleBoard UnderlyingBoard { get => (base.UnderlyingBoard as OptimizationModuleBoard)!; set => base.UnderlyingBoard = value; } public HashSet ConfigurableParameters { get; set; } = new(); public HashSet ConfigurablePortGroups { get; set; } = new(); public override IEnumerable ExplicitPorts => new IBasePort[] { ItemOut!.DataOut, ValueOut!.DataOut! } .Union(ExplicitInputs.Select(c => c.DataIn)!); public override BaseModule[] SubModules() => ExplicitInputs .Union(new BaseModule[] { ItemOut, ValueOut }) .ToArray(); public override IEnumerable ImplicitPorts => new IBasePort[] { UnderlyingBoard.IterOut.Output, UnderlyingBoard.ValueIn.DataIn } .Union(UnderlyingBoard.ImplicitDataOuts.Select(c => c.DataOut)); public override void Init() { base.Init(); UnderlyingBoard = GlobalProvider.SceneProvider! .AssetMapper() .Instantiate(); UnderlyingBoard.Init(); InterlayerGroups = new IDataPortGroup[3]; ExplicitInputs = new InterlayerDataInModule[3]; InternalIterOut = this.GetPort("InternalIterOut"); for (int i = 0; i < 3; i++) { ExplicitInputs[i] = GetModule($"EI{i + 1}"); ExplicitInputs[i].DualModule = UnderlyingBoard.ImplicitDataOuts[i]; UnderlyingBoard.ImplicitDataOuts[i].DualModule = ExplicitInputs[i]; } OptimizationEnded = true; CachedInput = Array.Empty(); //CachedArray = Array.Empty(); ProcessingIndex = 0; CachedResult = GlobalProvider.DataStructureProvider!.NullData; CachedOptimizeValue = null; ArrayInput = this.GetPort("ArrayInput"); ItemOut = GetModule("ItemOut"); ValueOut = GetModule("ValueOut"); for (int i = 0; i < 3; i++) { InterlayerGroups[i] = GlobalProvider.DataStructureProvider.NewDataPortGroup( this, new IDataPort[] { ExplicitInputs[i].DataIn!, UnderlyingBoard.ImplicitDataOuts[i].DataOut! }, $"Exterior In -> Interior Out{i}", EnigmosConstant.DataPortTypes.Real, EnigmosConstant.DataPortTypes.AnyType ); ExplicitInputs[i].Board = Board; } OptimizationGroup = GlobalProvider.DataStructureProvider.NewDataPortGroup( this, new IDataPort[] { ArrayInput }, "Array Input Type", EnigmosConstant.DataPortTypes.AnyArrayType, EnigmosConstant.DataPortTypes.AnyArray ); UsingMax = GlobalProvider.DataStructureProvider.NewBoolParameter( "Method", "Max", "Min", true ); ItemOut.DataOut.SetDataType(EnigmosConstant.DataPortTypes.Real); ValueOut.DataOut!.SetDataType(EnigmosConstant.DataPortTypes.Real); ConfigurableParameters = new HashSet { UsingMax }; ConfigurablePortGroups = InterlayerGroups.Union(new[] { OptimizationGroup }).ToHashSet(); PostInit(); } public void Inference() { StringName elementType = GlobalProvider.DataPackageTypeProvider!.ToElement(OptimizationGroup!.SelectedType); ItemOut!.DataOut.SetDataType(elementType); UnderlyingBoard.IterOut!.Output!.SetDataType(elementType); } private void SoftReset() => UnderlyingBoard.Reset(); public void Optimize() { if (OptimizationEnded) { CachedOptimizeValue = null; CachedInput = InternalArrayIn!.OutData.Get!.Array; CachedResult = GlobalProvider.DataStructureProvider.NewData(0, EnigmosConstant.DataPortTypes.Null); ProcessingIndex = 0; } while (ProcessingIndex < CachedInput.Length) { SoftReset(); UnderlyingBoard.IterOut!.Output!.OutData.UpdateCalculation( cache => (CachedInput[ProcessingIndex].Data, CachedInput[ProcessingIndex].Type)! ); UnderlyingBoard.IterOut.Output.OutData.Expire(); double currentValue = UnderlyingBoard.ValueIn!.DataIn!.GetData.Get!.Double; IData currentOut = InternalIterOut!.GetData.Get!; if (UsingMax!.ParameterValue) { if (CachedOptimizeValue == null || (CachedOptimizeValue < currentValue)) { CachedOptimizeValue = currentValue; CachedResult.Assign(currentOut.Data!, currentOut.Type!); } } else { if (CachedOptimizeValue == null || CachedOptimizeValue > currentValue) { CachedOptimizeValue = currentValue; CachedResult.Assign(currentOut.Data!, currentOut.Type!); } } ProcessingIndex++; } ValueOut!.Define(); OptimizationEnded = true; } public bool Calculated { get; set; } }