/// <summary> /// Connects a circuit component as the input/source of the /// invoking wire. /// </summary> /// <param name="component">The component to connect</param> /// <returns>A Parse Error if an error arises, otherwise null</returns> public void ConnectSource(CircuitComponent component, int index) { // If we already made this connection, we're done! if (_sourceComponent == component) { return; } // Make the connection. _sourceComponent = component; _sourceIndex = index; // Make sure the circuit component also has this connection if (component is LogicGate) { ((LogicGate)component).ConnectOutput(this); } else if (component is CircuitInput) { ((CircuitInput)component).Connect(this); } else if (component is CircuitOutput) { ((CircuitOutput)component).Connect(this); } }
/// <summary> /// Default constructor for making a new, /// unconnected wire-mesh associated with a /// given shape. /// </summary> /// <param name="shape">The shape associated /// with the new wire</param> public WireMesh(Sketch.Shape shape) : base(shape) { _sourceComponent = null; _dependentComponents = new List <CircuitComponent>(); loadEndpoints(); }
/// <summary> /// Connects a circuit component as an output/dependent of the /// invoking wire. /// </summary> /// <param name="component">The component to connect</param> public void ConnectDependent(CircuitComponent component) { // If we already made this connection, we're done! if (!_dependentComponents.Contains(component)) { _dependentComponents.Add(component); } else { return; } if (Source != null) { component.ConnectInput(Source, SourceIndex); } // Make sure the circuit component also has this connection if (component is LogicGate) { ((LogicGate)component).ConnectInput(this); } else if (component is CircuitOutput) { ((CircuitOutput)component).Connect(this); } else if (component is CircuitInput) { ((CircuitInput)component).Connect(this); } }
/// <summary> /// Default constructor for making a new, /// unconnected wire-mesh associated with a /// given shape. /// </summary> /// <param name="shape">The shape associated /// with the new wire</param> public WireMesh(Sketch.Shape shape) { _associatedShape = shape; _sourceComponent = null; _dependentComponents = new List <CircuitComponent>(); loadEndpoints(); }
public bool HasOutput(CircuitComponent component, int index) { if (OutputComponents.Count >= index + 1) { if (OutputComponents[index].Contains(component)) { return(true); } } return(false); }
/// <summary> /// Returns true if this circuit component has the given component and index connected as an input /// </summary> /// <param name="component"></param> /// <param name="index"></param> /// <returns></returns> public bool HasInput(CircuitComponent component, int index) { if (_inputComponents.ContainsKey(component)) { if (_inputComponents[component].Contains(index)) { return(true); } } return(false); }
/// <summary> /// Add connections between the given component and its inputs to the dictionary of circuit connections. /// (computes the input/output indices, then passes that info to connect(...) which actually adds the /// connection to the dictionary). /// </summary> /// <param name="connections">Existing dictionary of connctions.</param> /// <param name="component">Element whose inputs we add</param> /// <returns>The dictionary with the new connections added</returns> private Dictionary <Shape, Dictionary <int, Tuple <Shape, int> > > recordConnections( Dictionary <Shape, Dictionary <int, Tuple <Shape, int> > > connections, CircuitComponent component) { // Find the inputs to this component using the component's input wires. foreach (int destindex in component.InputComponents.Keys) { connections = recordConnection(connections, component.InputComponents[destindex].Item1.Shape, component.InputComponents[destindex].Item2, component.Shape, destindex); } return(connections); }
/// <summary> /// Connects a given circuit component as an input to the /// invoking logic gate. /// </summary> /// <param name="wire">The component to connect</param> public void ConnectInput(CircuitComponent component, int sourceindex) { // If we already made this connection, we're done! if (!_inputComponents.ContainsKey(component)) { _inputComponents[component] = new List <int>(); } // Make the connection. _inputComponents[component].Add(sourceindex); // Ensure that the given component also has this connection. component.ConnectOutput(this, sourceindex); }
/// <summary> /// Gets the endpoints in this wiremeesh which are connected to the specified circuit component. /// </summary> /// <param name="otherShape">The circuit component we're looking for connections to</param> /// <returns>A list of the endpoints in this shape connected to the specified component</returns> public List <Sketch.EndPoint> ConnectedEndpoints(CircuitComponent otherShape) { List <Sketch.EndPoint> connectedEndpoints = new List <Sketch.EndPoint>(); foreach (Sketch.EndPoint endpoint in Endpoints) { if (endpoint.ConnectedShape == otherShape.Shape) { connectedEndpoints.Add(endpoint); } } return(connectedEndpoints); }
/// <summary> /// Connects a given circuit component as an input to the /// invoking logic gate. /// </summary> /// <param name="wire">The component to connect</param> public void ConnectInput(CircuitComponent component, int index) { // If we already made this connection, we're done! if (_inputComponents.ContainsKey(component)) { return; } // Make the connection. _inputComponents.Add(component, index); // Ensure that the given component also has this connection. component.ConnectOutput(this, index); }
/// <summary> /// Connects all the circuit components (logic gates, /// circuit inputs, and circuit outputs) that share /// a wire-mesh to each other /// </summary> private void connectComponentsToComponents() { foreach (WireMesh wireMesh in _wireMeshes.Values) { if (!wireMesh.HasSource) { continue; } CircuitComponent wireInput = wireMesh.Source; foreach (CircuitComponent wireOutput in wireMesh.Dependents) { wireInput.ConnectOutput(wireOutput, wireMesh.SourceIndex); } } }
/// <summary> /// Connects a circuit component to the output of the /// invoking logic gate. In other words, the output of /// the invoking logic gate becomes directly tied with /// an input or value of a given circuit component. /// </summary> /// <param name="wire">The component to connect</param> public void ConnectOutput(CircuitComponent component, int index) { while (_outputComponents.Count < index + 1) { _outputComponents.Add(new List <CircuitComponent>()); } // If we already made this connection, we're done! if (_outputComponents[index].Contains(component)) { return; } // Make the connection. _outputComponents[index].Add(component); // Ensure that the given component also has this connection. component.ConnectInput(this, index); }
/// <summary> /// Connects a circuit component as an output/dependent of the /// invoking wire. /// </summary> /// <param name="component">The component to connect</param> public void ConnectDependent(CircuitComponent component) { // If we already made this connection, we're done! if (_dependentComponents.Contains(component)) { return; } // Make the connection. _dependentComponents.Add(component); // Make sure the circuit component also has this connection if (component is LogicGate) { ((LogicGate)component).ConnectInput(this); } else if (component is CircuitOutput) { ((CircuitOutput)component).Connect(this); } }
/// <summary> /// Sorts inputs by where they are on screen, constructs the input dictionary /// </summary> public void OrderInputs() { // Get all the endpoints List <Sketch.EndPoint> connectedEndpoints = InputEndpoints; Dictionary <Sketch.EndPoint, CircuitComponent> endpointsToNotBubbles = new Dictionary <Sketch.EndPoint, CircuitComponent>(); // Take care of any not bubbles foreach (CircuitComponent connected in _inputComponents.Keys) { if (Domain.LogicDomain.IsGate(connected.Type) && connected.Shape.ConnectedShapes.Contains(Shape) && connected.InputEndpoints.Count > 0) { connectedEndpoints.Add(connected.InputEndpoints[0]); endpointsToNotBubbles[connected.InputEndpoints[0]] = connected; } } // Sort all these endpoints connectedEndpoints.Sort(EndpointSort); // Make the input dictionary _inputDictionary.Clear(); for (int index = 0; index < connectedEndpoints.Count; index++) { if (EndpointsToWires.ContainsKey(connectedEndpoints[index])) { WireMesh wire = EndpointsToWires[connectedEndpoints[index]]; if (wire.HasSource) { _inputDictionary[index] = new Tuple <CircuitComponent, int>(wire.Source, wire.SourceIndex); } } else { CircuitComponent notBubble = endpointsToNotBubbles[connectedEndpoints[index]]; _inputDictionary[index] = new Tuple <CircuitComponent, int>(notBubble, 0); } } }
/// <summary> /// Checks whether the circuit is valid, returns a bool indicating this. /// Adds any errors it comes across to the _parseErrors list. /// /// Looks for: /// * Each wire has one source and at least one output /// * No wire outputs to an input and no output is a wire's input /// * Each gate has an allowable number of inputs and outputs /// * Each circuit element and wire have reciprocal connections /// * Each input and output are connected to something /// </summary> /// <returns>A bool, which is true if the circuit is valid</returns> private bool CheckCircuit() { // Assume the circuit is fine, decide otherwise later. bool valid = true; #region Check Wire Connections // Each wire should have one input and at least one output foreach (WireMesh mesh in _wireMeshes.Values) { // Do the connections exist? if (!mesh.HasSource) { valid = false; _parseErrors.Add(new ParseError("The wire " + mesh.Name + " is missing a source.", "This wire does not have a source. Try dragging its red endpoints to connect it to something.", mesh.Shape)); } /* * // This is actually ok right now, outputs can be drawn in the middle of wires to give intermediary values. * else if (mesh.Source is CircuitOutput) * { * valid = false; * _parseErrors.Add(new ParseError("The wire " + mesh.Name + "'s source is an output, " + mesh.Source.Name + ".", * "This wire's source is an output, " + mesh.Source.Name + ".", mesh.Shape)); * } */ if (mesh.Dependents.Count < 1) { valid = false; _parseErrors.Add(new ParseError("The wire " + mesh.Name + " has no dependents.", "Nothing uses this wire's value! Please connect it to something by dragging its endpoints.", mesh.Shape)); } foreach (CircuitComponent connected in mesh.Dependents) { if (connected is CircuitInput) { valid = false; _parseErrors.Add(new ParseError("The wire " + mesh.Name + " is giving a value to the input" + connected.Name + ".", "This wire is giving a value to the input" + connected.Name + ".", mesh.Shape)); } } } #endregion #region Check Gate Connections // Each gate should have the correct number of inputs and outputs foreach (LogicGate gate in LogicGates) { // Get the minimum and maximum input and output numbers Utilities.IntRange inputs = _domain.NumberInputs(gate.Type); Utilities.IntRange outputs = _domain.NumberOutputs(gate.Type); // Check input numbers if (gate.InputComponents.Count < inputs.Min) { valid = false; _parseErrors.Add(new ParseError("The gate " + gate.Name + " is missing some inputs. It needs at least " + inputs.Min + " but has " + gate.InputComponents.Count + ".", "This gate is missing some inputs. It needs at least " + inputs.Min + " but has " + gate.InputComponents.Count + ".", gate.Shape)); } else if (gate.InputComponents.Count > inputs.Max) { valid = false; _parseErrors.Add(new ParseError("The gate " + gate.Name + " has too many inputs. It needs at most " + inputs.Max + " but has " + gate.InputComponents.Count + ".", "This gate has too many inputs. It needs at most " + inputs.Max + " but has " + gate.InputComponents.Count + ".", gate.Shape)); } // Check input connections foreach (int index in gate.InputComponents.Keys) { CircuitComponent component = gate.InputComponents[index].Item1; if (!component.HasOutput(gate, gate.InputComponents[index].Item2)) { valid = false; _parseErrors.Add(new ParseError("The gate " + gate.Name + " is connected to the component " + component.Name + ", but that component is not connected to the gate!", "The gate " + gate.Name + " is connected to the component " + component.Name + ", but that component is not connected to the gate!", component.Shape)); } } // Check output numbers if (gate.OutputComponents.Count < outputs.Min) { valid = false; _parseErrors.Add(new ParseError("The gate " + gate.Name + " is missing some outputs. It needs at least " + outputs.Min + " but has " + gate.OutputComponents.Count + ".", "This gate is missing some outputs. It needs at least " + outputs.Min + " but has " + gate.OutputComponents.Count + ".", gate.Shape)); } else if (gate.OutputComponents.Count > outputs.Max) { valid = false; _parseErrors.Add(new ParseError("The gate " + gate.Name + " has too many outputs. It needs at most " + outputs.Max + " but has " + gate.OutputComponents.Count + ".", "This gate has too many outputs. It needs at most " + outputs.Max + " but has " + gate.OutputComponents.Count + ".", gate.Shape)); } // Check output connections foreach (WireMesh wire in gate.OutputWires) { if (wire.Source != gate) { valid = false; _parseErrors.Add(new ParseError("The gate " + gate.Name + " is connected to the wire " + wire.Name + ", but that wire is not connected to the gate!", "The gate " + gate.Name + " is connected to the wire " + wire.Name + ", but that wire is not connected to the gate!", wire.Shape)); } } // Check output connections for (int i = 0; i < gate.OutputComponents.Count; i++) { foreach (CircuitComponent component in gate.OutputComponents[i]) { if (!component.HasInput(gate, i)) { valid = false; _parseErrors.Add(new ParseError("The gate " + gate.Name + " is connected to the component " + component.Name + ", but that component is not connected to the gate!", "The gate " + gate.Name + " is connected to the component " + component.Name + ", but that component is not connected to the gate!", component.Shape)); } } } } #endregion #region Check Input/Output connections // Each input should be connected correctly foreach (CircuitInput input in _circuitInputs.Values) { if (input.OutputWires.Count == 0) { valid = false; _parseErrors.Add(new ParseError("The input " + input.Name + " is not connected to anything.", "This input (" + input.Name + ") is not connected to anything.", input.Shape)); } else { foreach (WireMesh wire in input.OutputWires) { if (wire.Source != input) { valid = false; _parseErrors.Add(new ParseError("The input " + input.Name + " is connected to the wire " + wire.Name + ", but that wire does not get it's value from the input!", "This input (" + input.Name + ") is connected to the wire " + wire.Name + ", but that wire does not get it's value from thr input!", input.Shape)); } } } if (input.InputWires.Count > 0) { valid = false; _parseErrors.Add(new ParseError("The input " + input.Name + " connected as an output.", "This input (" + input.Name + ") is connected as an output.", input.Shape)); } } // Each output should be connected correctly foreach (CircuitOutput output in _circuitOutputs.Values) { if (output.InputWires.Count == 0) { valid = false; _parseErrors.Add(new ParseError("The output " + output.Name + " is not getting a value from anything.", "This output (" + output.Name + ") is not getting a value from anything.", output.Shape)); } else if (output.InputWires.Count > 1) { valid = false; _parseErrors.Add(new ParseError("The output " + output.Name + " gets a value from more than one wire.", "This output (" + output.Name + ") gets a value from more than one wire.", output.Shape)); } else if (!output.SourceWire.Dependents.Contains(output)) { valid = false; _parseErrors.Add(new ParseError("The output " + output.Name + " is connected to the wire " + output.SourceWire.Name + ", but that wire does not give it's value to the output!", "This output (" + output.Name + ") is connected to the wire " + output.SourceWire.Name + ", but that wire does not give it's value to the output!", output.Shape)); } foreach (WireMesh wire in output.OutputWires) { if (wire.Source != output) { valid = false; _parseErrors.Add(new ParseError("The output " + output.Name + " is connected to the wire " + wire.Name + ", but that wire does not get it's value from the output!", "This output (" + output.Name + ") is connected to the wire " + wire.Name + ", but that wire does not get it's value from the output!", output.Shape)); } } } #endregion return(valid); }