using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Shapes; namespace DigiSim.Logic.Gates { public class CustomGate : Gate { public int Inputs { get; } public int Outputs { get; } public string Symbol { get; } public LookupTable Lookup { get; } public CustomGate(double x, double y) : base(x, y, 50, 50) { } private CustomGate(string symbol, LookupTable lookup) { Symbol = symbol; Lookup = lookup; Inputs = lookup.InputCount; Outputs = lookup.OutputCount; Constructor(0, 0, 0, 0); } protected override void InternalSetup(Canvas canvas) { Shape = new Rectangle(); int connectorCount = Math.Max(Inputs, Outputs); Size = new Size(50, connectorCount * 25); SetInputs(Inputs); SetOutputs(Outputs); CreateConnections(); Text = Symbol; Instantiate(); } public override void Update(Gate source) { bool[] snapshot = new bool[ConnectedInputs.Length]; for (var i = 0; i < snapshot.Length; i++) { snapshot[i] = ConnectedInputs[i].IsPowered; } bool[] outputs = Lookup.GetOutputs(snapshot); for (var i = 0; i < ConnectedOutputs.Length; i++) { ConnectedOutputs[i].IsPowered = outputs[i]; } UpdateShapes(); UpdateConnectedGates(source); } public struct LookupTable { public bool[,] Inputs { get; } public bool[,] Outputs { get; } public int InputCount { get; } public int OutputCount { get; } public int Length { get; } public LookupTable(int inputCount, int outputCount, int length) { Inputs = new bool[length, inputCount]; Outputs = new bool[length, outputCount]; InputCount = inputCount; OutputCount = outputCount; Length = length; } public bool[] GetOutputs(bool[] inputs) { if (inputs.Length != InputCount) throw new ArgumentOutOfRangeException(nameof(inputs)); for (int i = 0; i < Length; i++) { bool found = true; for (int j = 0; j < InputCount; j++) { if (Inputs[i, j] != inputs[j]) { found = false; break; } } if (found) { bool[] output = new bool[OutputCount]; for (int o = 0; o < OutputCount; o++) { output[o] = Outputs[i, o]; } return output; } } return new bool[OutputCount]; } public void SetLookup(bool[] inputs, bool[] outputs, int index) { if (index >= Length) throw new IndexOutOfRangeException(nameof(index)); for (var i = 0; i < inputs.Length; i++) { Inputs[index, i] = inputs[i]; } for (var i = 0; i < outputs.Length; i++) { Outputs[index, i] = outputs[i]; } } } private static LookupTable CreateLookup(Gate[] gates) { List inputs = new List(); List outputs = new List(); foreach (var gate in gates) { if (gate is Input) inputs.Add(gate as Input); if (gate is Output) outputs.Add(gate as Output); } int possibilities = (int) Math.Pow(2, inputs.Count); LookupTable lookupTable = new LookupTable(inputs.Count, outputs.Count, possibilities); for (var i = 0; i < possibilities; i++) { bool[] inputSequenze = new bool[inputs.Count]; bool[] outputSequenze = new bool[outputs.Count]; char[] sequenze = Convert.ToString(i, 2).PadLeft(inputs.Count, '0').ToCharArray(); for (var j = 0; j < sequenze.Length; j++) { inputSequenze[j] = sequenze[j] == '1'; inputs[j].Powered = sequenze[j] == '1'; inputs[j].Update(inputs[j]); } for (var j = 0; j < outputs.Count; j++) { outputSequenze[j] = outputs[j].ConnectedInputs[0].IsPowered; } lookupTable.SetLookup(inputSequenze, outputSequenze, i); } return lookupTable; } public static CustomGate CreateCustomGateFromBoard(Gate[] gates, string symbol) { return new CustomGate(symbol, CreateLookup(gates)); } } }