class LogicAND extends Element { constructor(_Container, RestoreData = null, logicengine,Inputs) { super(_Container, RestoreData,logicengine,Inputs); this.Name = "AND"; } getOutput(Output=0) { if (super.getOutput() === 0) return false; let ANDResult = true; for (let a = 0; a < this.totalInputs();a++) { if (!this.Inputs[a]) ANDResult = false; } return ANDResult; } drawElement(x,y,ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; //this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height); let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.moveTo(x+xOffset,y); ctx.lineTo((x+xOffset)+ this.Width/4,y); ctx.quadraticCurveTo(x+(this.Width - xOffset),y,x+(this.Width-xOffset),y+(this.Height/2)); ctx.quadraticCurveTo(x+(this.Width - xOffset),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height); ctx.lineTo(x+xOffset,y+this.Height); ctx.lineTo(x+xOffset,y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_AND = new ElementCatalog_Element("AND","The AND gate only outputs high when all of the inputs are high.","&",LogicAND,[2]); ElementReferenceTable.push(ElementCatalog_AND); ElementCategory_LOGIC.addElement(ElementCatalog_AND); class LogicNAND extends LogicAND { constructor(_Container, RestoreData = null, logicengine,Inputs) { super(_Container, RestoreData,logicengine,Inputs); this.Name = "NAND"; this.Width = 110; } getOutput(Output=0) { if (this.Disconnecting) return false; if (super.getOutput()) { return false; } else { return true; } } drawElement(x,y,ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.moveTo(x+xOffset,y); ctx.lineTo((x+xOffset)+ this.Width/4,y); ctx.quadraticCurveTo(x+(this.Width - (xOffset*1.5)),y,x+(this.Width-(xOffset*1.5)),y+(this.Height/2)); ctx.quadraticCurveTo(x+(this.Width - (xOffset*1.5)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height); ctx.lineTo(x+xOffset,y+this.Height); ctx.lineTo(x+xOffset,y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.strokeStyle = "#000000"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.beginPath(); ctx.fillStyle = "#000000"; ctx.strokeStyle = "#000000"; ctx.lineWidth = "1"; ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI); ctx.stroke(); ctx.fill(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width-xOffset,this.Height,this.Designator,"12px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_NAND = new ElementCatalog_Element("NAND","The NAND gate always outputs a high signal unless all the inputs are high then it goes low.","!&",LogicNAND,[2]); ElementReferenceTable.push(ElementCatalog_NAND); ElementCategory_LOGIC.addElement(ElementCatalog_NAND); class LogicOR extends Element { constructor(_Container, RestoreData = null, logicengine,Inputs) { super(_Container, RestoreData,logicengine,Inputs); this.Name = "OR"; } getOutput(Output=0) { if (super.getOutput() === 0) return false; let ORResult = false; for (let a = 0; a < this.totalInputs();a++) { if (this.Inputs[a]) ORResult = true; } return ORResult; } drawElement(x,y,ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; let drawWidth = this.Width; let drawHeight = this.Height; let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.moveTo(x+(xOffset/4),y); ctx.lineTo((x+xOffset)+ this.Width/4,y); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y,x+(this.Width-xOffset),y+(this.Height/2)); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height); ctx.lineTo(x+(xOffset/4),y+this.Height); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_OR = new ElementCatalog_Element("OR","The OR gate outputs a high when any input is HIGH.","|",LogicOR,[2]); ElementReferenceTable.push(ElementCatalog_OR); ElementCategory_LOGIC.addElement(ElementCatalog_OR); class LogicNOR extends LogicOR { constructor(_Container, RestoreData = null, logicengine,Inputs) { super(_Container, RestoreData,logicengine,Inputs); this.Name = "NOR"; this.Width = 110; } getOutput(Output=0) { if (super.getOutput() === 0) return false; if (super.getOutput()) { return false; } else { return true; } } drawElement(x,y,ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.moveTo(x+(xOffset/4),y); ctx.lineTo((x+xOffset)+ this.Width/4,y); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y,x+(this.Width-(xOffset*1.5)),y+(this.Height/2)); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height); ctx.lineTo(x+(xOffset/4),y+this.Height); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.beginPath(); ctx.fillStyle = "#000000"; ctx.strokeStyle = "#000000"; ctx.lineWidth = "1"; ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI); ctx.stroke(); ctx.fill(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width-xOffset,this.Height,this.Designator,"12px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_NOR = new ElementCatalog_Element("NOR","The NOR gate outputs a high only when all inputs are low.","!|",LogicNOR,[2]); ElementReferenceTable.push(ElementCatalog_NOR); ElementCategory_LOGIC.addElement(ElementCatalog_NOR); class LogicXOR extends Element { constructor(_Container, RestoreData = null, logicengine) { super(_Container, RestoreData,logicengine,2); // Only 2 inputs on XOR this.Name = "XOR"; this.removeProperty("Inputs"); } getOutput(Output=0) { if (super.getOutput() === 0) return false; let ORResult = false; if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true; return ORResult; } drawElement(x,y,ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; let drawWidth = this.Width; let drawHeight = this.Height; let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.moveTo(x+(xOffset/4),y); ctx.lineTo((x+xOffset)+ this.Width/4,y); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y,x+(this.Width-xOffset),y+(this.Height/2)); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height); ctx.lineTo(x+(xOffset/4),y+this.Height); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.lineWidth = "2"; ctx.beginPath(); ctx.shadowColor = "transparent"; ctx.moveTo(x+(xOffset/4)+10,y+this.Height); ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height - (this.Height/32)),x+xOffset+10,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height/32),x+(xOffset/4)+10,y); ctx.stroke(); ctx.beginPath(); ctx.moveTo(x+(xOffset/4),y+this.Height); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y); ctx.stroke(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_XOR = new ElementCatalog_Element("XOR","The XOR gate outputs a high when only 1 input is high.","^",LogicXOR,[]); ElementReferenceTable.push(ElementCatalog_XOR); ElementCategory_LOGIC.addElement(ElementCatalog_XOR); class LogicXNOR extends Element { constructor(_Container, RestoreData = null, logicengine) { super(_Container, RestoreData,logicengine,2); // Only 2 inputs on XOR this.Name = "XNOR"; this.removeProperty("Inputs"); this.Width = 110; } getOutput(Output=0) { if (super.getOutput() === 0) return false; let ORResult = false; if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true; return !ORResult; } drawElement(x,y,ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; let drawWidth = this.Width; let drawHeight = this.Height; let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.save(); ctx.beginPath(); ctx.moveTo(x+(xOffset/4),y); ctx.lineTo((x+xOffset)+ this.Width/4,y); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y,x+(this.Width-(xOffset*1.5)),y+(this.Height/2)); ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height); ctx.lineTo(x+(xOffset/4),y+this.Height); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.beginPath(); ctx.fillStyle = "#000000"; ctx.strokeStyle = "#000000"; ctx.lineWidth = "1"; ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI); ctx.stroke(); ctx.fill(); ctx.lineWidth = "2"; ctx.beginPath(); ctx.shadowColor = "transparent"; ctx.moveTo(x+(xOffset/4)+10,y+this.Height); ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height - (this.Height/32)),x+xOffset+10,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height/32),x+(xOffset/4)+10,y); ctx.stroke(); ctx.beginPath(); ctx.moveTo(x+(xOffset/4),y+this.Height); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2)); ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y); ctx.stroke(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width-(xOffset/2),this.Height,this.Designator,"10px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_XNOR = new ElementCatalog_Element("XNOR","The XNOR gate outputs a high only when both inputs are either low or high.","!^",LogicXNOR,[]); ElementReferenceTable.push(ElementCatalog_XNOR); ElementCategory_LOGIC.addElement(ElementCatalog_XNOR); class LogicNOT extends Element { constructor(_Container, RestoreData = null, logicengine) { super(_Container, RestoreData,logicengine,1); // Only 1 inputs on NOT this.Name = "NOT"; this.removeProperty("Inputs"); this.Width = 110; } getOutput(Output=0) { if (super.getOutput() === 0) return false; if (this.Inputs[0]) return false; return true; } drawElement(x,y,ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; let drawWidth = this.Width; let drawHeight = this.Height; let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.moveTo(x+xOffset,y); ctx.lineTo(x+(this.Width-(xOffset+10)),y+(this.Height/2)); ctx.lineTo(x+xOffset,y+this.Height); ctx.lineTo(x+xOffset,y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.beginPath(); ctx.fillStyle = "#000000"; ctx.strokeStyle = "#000000"; ctx.lineWidth = "1"; ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI); ctx.stroke(); ctx.fill(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width-(xOffset),this.Height,this.Designator,"12px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_NOT = new ElementCatalog_Element("NOT","The NOT gate outputs the opposite of the input.","!",LogicNOT,[]); ElementReferenceTable.push(ElementCatalog_NOT); ElementCategory_LOGIC.addElement(ElementCatalog_NOT); class LogicBuffer extends Element { ClockTick() { this.Output = this.Inputs[0]; this.Task.Enabled = false; this.Task.LastCall = 0; for (let a = 0; a < this.OutputConnections.length; a++) { this.LogicEngine.RecursionCount = 0; this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input, this.getOutput()); } this.drawElement(0,0,this.StaticCtx); } Delete() { super.Delete(); this.LogicEngine.Scheduler.deleteTask(this.Task); } getOutput(Output=0) { if (super.getOutput() === 0) return false; return this.Output; } setInput(Input, Value) { if (Input > 0) return; //super.setInput(Input, Value); Value = this._Container.isHigh(this,Input); if (Value !== false) Value = true; this.Inputs[Input] = Value; this.redraw = true; if (!this.Task.Enabled) { this.Task.LastCall = 0; this.Task.Enabled = true; } this.drawElement(0,0,this.StaticCtx); } constructor(_Container, RestoreData = null, logicengine) { super(_Container, RestoreData,logicengine,1); this.removeProperty("Inputs"); this.Output = false; this.Name = "Buffer"; this.Width = 100; this.Task = new Task("BufferTask","Buffer",0,9999999,this.ClockTick.bind(this)); this.Task.Time = 4; this.Task.Enabled = false; this.Task.LastCall = 0; this.removeProperty("Inputs"); if (RestoreData) this.Output = RestoreData.Output; this.LogicEngine.Scheduler.addTask(this.Task); } toJSON(key) { let superjson = super.toJSON(key); superjson.Task = { Enabled: this.Task.Enabled, Time: this.Task.Time, LastCall: Date.now() - this.Task.LastCall, CallCount: this.Task.CallCount }; return superjson; } drawElement(x, y, ctx) { if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible this.StaticCanvas.width = this.Width; this.StaticCanvas.height = this.Height; let drawWidth = this.Width; let drawHeight = this.Height; let xOffset = 20; let shadowColor = this.LogicEngine.Settings.ShadowColor; ctx.save(); ctx.beginPath(); ctx.moveTo(x+xOffset,y); ctx.lineTo(x+(this.Width-(xOffset)),y+(this.Height/2)); ctx.lineTo(x+xOffset,y+this.Height); ctx.lineTo(x+xOffset,y); ctx.lineWidth = "3"; ctx.fillStyle = "#f7e979"; ctx.shadowColor = shadowColor; ctx.shadowBlur = "6"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); ctx.fill(); ctx.restore(); this.drawTextCentered(ctx,x,y,this.Width-(xOffset),this.Height,this.Designator,"12px Console","#000"); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); } } let ElementCatalog_BUFFER = new ElementCatalog_Element("Buffer","The buffer is a special gate to allow the prevention of recursion loops.","|>",LogicBuffer,[]); ElementReferenceTable.push(ElementCatalog_BUFFER); ElementCategory_LOGIC.addElement(ElementCatalog_BUFFER);