├── .gitignore ├── .jshintignore ├── .jshintrc ├── .stickler.yml ├── LICENSE ├── README.md ├── config.json ├── javascripts ├── DOMdefinitions.js ├── classes │ ├── action.js │ ├── bus.js │ ├── busGroup.js │ ├── busInput.js │ ├── busUnwrapper.js │ ├── busWrapper.js │ ├── clickBox.js │ ├── conpoint.js │ ├── customSketch.js │ ├── decoder.js │ ├── diode.js │ ├── group.js │ ├── input.js │ ├── label.js │ ├── logicGate.js │ ├── output.js │ ├── segmentDisplay.js │ ├── transformation.js │ └── wire.js ├── constants.js ├── cpdiodes.js ├── customDialog.js ├── dialogs.js ├── loadsave.js ├── modifierMenu.js ├── mouse.js ├── parsing.js ├── previews.js ├── selectionHandling.js ├── sketch.js └── undoredo.js ├── libraries ├── bootstrap.min.js ├── jquery.min.js ├── lodash.js ├── p5.dom.js ├── p5.js ├── p5.min.js └── stickUp.min.js ├── package-lock.json ├── package.json ├── public.key ├── site_scripts ├── create_account.js ├── dashboard.js ├── eduSignup.js ├── edu_tutorial.js ├── education.js ├── edulogin.js ├── getstarted.js ├── index.js ├── index_page.js ├── jwt_module.js ├── lib_front.js ├── login.js ├── migrations │ ├── 20190916195158_create_user_table.js │ └── 20190916204924_encrypt_user_password.js ├── store.js ├── survicate.js ├── tos_legal.js └── user_data.js ├── views ├── css │ ├── ArcaMajora3-Bold.otf │ ├── bootstrap.css │ └── index_style.css ├── dashboard.pug ├── eduLogin.pug ├── eduSignup.pug ├── education.pug ├── getstarted.pug ├── hosting-tutorial.pug ├── images │ ├── alt_logo.png │ ├── alt_logo_dark.png │ ├── alt_logo_small.png │ ├── and-gate.png │ ├── buffer.png │ ├── businput.png │ ├── button.png │ ├── carousel_1_new.png │ ├── carousel_1_new_dark.png │ ├── carousel_2_new.png │ ├── carousel_2_new_dark.png │ ├── carousel_3_new.png │ ├── carousel_3_new_dark.png │ ├── clock.png │ ├── counter.png │ ├── custom_frontpage.png │ ├── d-flipflop.png │ ├── decoder.png │ ├── demux.png │ ├── favi.png │ ├── front_teaser.png │ ├── front_teaser_white.png │ ├── fulladd.png │ ├── fulladd_old.png │ ├── github_dark.png │ ├── halfadd.png │ ├── jk-flipflop.png │ ├── label.png │ ├── label_white.png │ ├── logo_index_new.png │ ├── logo_index_new_white.png │ ├── mux.png │ ├── not-gate.png │ ├── or-gate.png │ ├── output.png │ ├── register.png │ ├── rs-clocked.png │ ├── rs-flipflop.png │ ├── segments.png │ ├── switch.png │ ├── t-flipflop.png │ ├── twitter.png │ ├── uni-hl-demo.jpg │ ├── unwrapper.png │ ├── wrapper.png │ └── xor-gate.png ├── index.pug ├── legal.pug ├── librarySketches │ ├── library__0gates.json │ ├── library__0gates.png │ ├── library__0gates.txt │ ├── library__0gates_frame.png │ ├── library__1halfadder.json │ ├── library__1halfadder.png │ ├── library__1halfadder.txt │ ├── library__1halfadder_frame.png │ ├── library__2fulladder.json │ ├── library__2fulladder.png │ ├── library__2fulladder.txt │ ├── library__2fulladder_frame.png │ ├── library__3traffic.json │ ├── library__3traffic.png │ ├── library__3traffic.txt │ ├── library__3traffic_frame.png │ ├── library__44BitCounter.json │ ├── library__44BitCounter.png │ ├── library__44BitCounter.txt │ ├── library__44BitCounter_frame.png │ ├── library__5tour.json │ └── library__hover.png ├── logijs.pug ├── login.pug ├── profile.pug ├── robots.txt ├── signup.pug ├── sketches │ ├── 1-buffer.json │ ├── 1-demux.json │ ├── 1-mux.json │ ├── 2-counter.json │ ├── 2-decoder.json │ ├── 2-demux.json │ ├── 2-mux.json │ ├── 3-buffer.json │ ├── 3-counter.json │ ├── 3-decoder.json │ ├── 3-demux.json │ ├── 3-mux.json │ ├── 4-counter.json │ ├── 4-decoder.json │ ├── 4-register.json │ ├── 5-counter.json │ ├── 5-decoder.json │ ├── d-flipflop.json │ ├── full_add.json │ ├── half_add.json │ ├── inverter.json │ ├── jk-flipflop.json │ ├── not-gate.json │ ├── rs-clocked.json │ ├── rs-flipflop.json │ └── t-flipflop.json └── tos.pug └── webapp_style.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | userSketches/ 3 | views/previews 4 | views/sharedSketches 5 | .DS_Store 6 | private.key 7 | public.key 8 | nodemon.json 9 | google76e7434874552abc.html 10 | site_scripts/knexfile.js 11 | views/images/legacy/ -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | libraries/* -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "maxerr" : 50, 3 | "bitwise" : true, 4 | "camelcase" : false, 5 | "curly" : true, 6 | "eqeqeq" : true, 7 | "forin" : true, 8 | "freeze" : true, 9 | "immed" : false, 10 | "latedef" : false, 11 | "newcap" : false, 12 | "noarg" : true, 13 | "noempty" : true, 14 | "nonbsp" : true, 15 | "nonew" : false, 16 | "plusplus" : false, 17 | "quotmark" : false, 18 | "undef" : false, 19 | "unused" : false, 20 | "strict" : false, 21 | "maxparams" : false, 22 | "maxdepth" : false, 23 | "maxstatements" : false, 24 | "maxcomplexity" : false, 25 | "maxlen" : false, 26 | "varstmt" : false, 27 | "asi" : false, 28 | "boss" : false, 29 | "debug" : false, 30 | "eqnull" : false, 31 | "esversion" : 6, 32 | "moz" : false, 33 | "evil" : false, 34 | "expr" : false, 35 | "funcscope" : false, 36 | "globalstrict" : false, 37 | "iterator" : false, 38 | "lastsemic" : false, 39 | "laxbreak" : false, 40 | "laxcomma" : false, 41 | "loopfunc" : false, 42 | "multistr" : false, 43 | "noyield" : false, 44 | "notypeof" : false, 45 | "proto" : false, 46 | "scripturl" : false, 47 | "shadow" : false, 48 | "sub" : false, 49 | "supernew" : false, 50 | "validthis" : false, 51 | "browser" : true, 52 | "browserify" : false, 53 | "couch" : false, 54 | "devel" : true, 55 | "dojo" : false, 56 | "jasmine" : false, 57 | "jquery" : false, 58 | "mocha" : true, 59 | "mootools" : false, 60 | "node" : false, 61 | "nonstandard" : false, 62 | "phantom" : false, 63 | "prototypejs" : false, 64 | "qunit" : false, 65 | "rhino" : false, 66 | "shelljs" : false, 67 | "typed" : false, 68 | "worker" : false, 69 | "wsh" : false, 70 | "yui" : false, 71 | "globals" : {} 72 | } -------------------------------------------------------------------------------- /.stickler.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | jshint: 3 | config: './.jshintrc' 4 | files: 5 | ignore: 6 | - 'bower_components/*' 7 | - 'node_modules/*' 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Please note: 2 | 3 | LogiJS development is currently in an indefinite hold in favor of its spiritual successor [Linkuit Studio](https://github.com/SimonBuxx/Linkuit-Studio). Linkuit Studio is a logic circuit simulator comparable to LogiJS but running as a native Windows application. 4 | 5 | While it still misses some features present in LogiJS, Linkuit Studio is much more stable and maintainable than LogiJS. If you like LogiJS, give [Linkuit Studio](https://github.com/SimonBuxx/Linkuit-Studio) a try. 6 | 7 | Issues in this project won't be fixed by me at the moment. But thank you to everyone who is sharing their ideas and creating bug reports. 8 | 9 | [![logijs_github_banner](https://user-images.githubusercontent.com/6598913/216174650-d2f11bc9-d385-4372-bea0-36d27bad99ca.png)](https://linkuit.com/) 10 |


11 | # LogiJS - Logic Circuit Simulation 12 | ![xor_animation](https://user-images.githubusercontent.com/6598913/111069437-5be79d80-84cd-11eb-90d4-ade8780d9feb.gif) 13 | 14 | LogiJS is an open source logic ciruit simulation webapp. 15 | Focused on educational purposes, its applications range from experiments with basic logic circuits to complex CPU design. 16 | 17 | My goal is to make LogiJS as user-friendly and performant as possible while providing all features expected by educational facilities. 18 | For the near future, please excuse minor bugs, performance issues or rapid changes in design and functionality. 19 | The software is still under development and I'm trying to improve it every day. 20 | 21 | To try it out, visit https://logijs.com/. 22 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "organization": { 3 | "name": "Universität zu Lübeck", 4 | "first_line": "Universität", 5 | "second_line": "zu Lübeck" 6 | }, 7 | "accounts": { 8 | "allow_signups": "true", 9 | "enable_login": "true", 10 | "user_identificator": "email", 11 | "require_verification": "false", 12 | "limit_email_hosts": "false", 13 | "allowed_hosts": ["student.uni-luebeck.de", "uni-luebeck.de"] 14 | }, 15 | "custom_index_page": { 16 | "use_custom_page": "false", 17 | "background_image": "https://cdn.prod.www.spiegel.de/images/880f3df9-0001-0004-0000-000000092544_w1528_r1.2514619883040936_fpx35.93_fpy54.98.jpg", 18 | "show_organization_name": "true", 19 | "refer_to_logijs_com": "true", 20 | "background_text": "Universität zu Lübeck", 21 | "allow_entering_without_login": "true", 22 | "show_made_in_luebeck": "true" 23 | }, 24 | "localization": { 25 | "login": "Login", 26 | "register": "Konto erstellen", 27 | "email": "E-Mail", 28 | "username": "Nutzername", 29 | "password": "Passwort", 30 | "switch_to_logijs_com": "Zu LogiJS.com wechseln", 31 | "continue_without_login": "Ohne Anmeldung fortfahren", 32 | "toggle_dark_mode": "Dunklen Modus an-/ausschalten", 33 | "login_failed": "Anmeldung fehlgeschlagen", 34 | "signup_successful": "Registrierung erfolgreich", 35 | "already_signed_up": "Du hast schon ein Konto?", 36 | "username_invalid": "Nutzername ungültig", 37 | "email_invalid": "E-Mail-Adresse ungültig", 38 | "password_invalid": "Passwort ungültig", 39 | "password_rules": "Bitte gebe zwischen 6 und 50 klein- UND großgeschriebene Zeichen ein, inklusive mindestens einer Zahl", 40 | "username_taken": "Nutzername schon vergeben" 41 | } 42 | } -------------------------------------------------------------------------------- /javascripts/classes/action.js: -------------------------------------------------------------------------------- 1 | // File: action.js 2 | 3 | function Action(actionType, actionIndizes, actionObject) { 4 | this.actionType = actionType; 5 | this.actionIndizes = actionIndizes; 6 | this.actionObject = actionObject; 7 | } -------------------------------------------------------------------------------- /javascripts/classes/bus.js: -------------------------------------------------------------------------------- 1 | // File: bus.js 2 | 3 | function Bus(dir, startX, startY) { 4 | this.highColor = color(HRED, HGREEN, HBLUE); // Color for high 5 | this.lowColor = color(LRED, LGREEN, LBLUE); // Color for low 6 | this.markedColor = color(MRED, MGREEN, MBLUE); // Color for marked 7 | 8 | this.direction = dir; // 0 or 1, meaning horizontal or vertical 9 | 10 | this.startX = 0; // Start point of the segment 11 | this.startY = 0; 12 | 13 | this.endX = 0; 14 | this.endY = 0; 15 | 16 | this.busWidth = 0; // number of wires contained 17 | this.busWidthSet = false; 18 | this.showBusMarker = false; // Show the diagonal line and bus width 19 | 20 | this.textDistance = 12; // Distance of the bus width label to the bus 21 | this.textSize = 15; 22 | 23 | this.marked = false; 24 | 25 | this.group = -1; 26 | 27 | this.id = 'bb' + Date.now() + Math.random(); 28 | 29 | this.changePosition(startX, startY); // Initialize the start point 30 | 31 | this.states = Array(this.busWidth).fill(false); // create an array for the wire states 32 | } 33 | 34 | Bus.prototype.getData = function () { 35 | var data = {}; 36 | data.x1 = JSON.stringify(this.startX); 37 | data.y1 = JSON.stringify(this.startY); 38 | if (this.startX !== this.endX) { 39 | data.x2 = JSON.stringify(this.endX); 40 | } else { 41 | data.y2 = JSON.stringify(this.endY); 42 | } 43 | return data; 44 | }; 45 | 46 | Bus.prototype.alterPosition = function (x1, y1) { 47 | this.endX += x1; 48 | this.endY += y1; 49 | this.startX += x1; 50 | this.startY += y1; 51 | }; 52 | 53 | Bus.prototype.changePosition = function (newX, newY) { 54 | this.startX = Math.round(newX / GRIDSIZE) * GRIDSIZE; 55 | this.startY = Math.round(newY / GRIDSIZE) * GRIDSIZE; 56 | switch (this.direction) { 57 | case 0: 58 | this.endX = this.startX + GRIDSIZE; 59 | this.endY = this.startY; 60 | break; 61 | case 1: 62 | this.endY = this.startY + GRIDSIZE; 63 | this.endX = this.startX; 64 | break; 65 | default: 66 | console.log('No valid direction given!'); 67 | } 68 | }; 69 | 70 | Bus.prototype.setStates = function (s) { 71 | this.states = s; 72 | }; 73 | 74 | Bus.prototype.setBusWidth = function (newWidth) { 75 | this.busWidth = newWidth; 76 | this.busWidthSet = true; 77 | } 78 | 79 | Bus.prototype.setGroup = function (g) { 80 | this.group = g; 81 | }; 82 | 83 | Bus.prototype.getOutput = function () { 84 | return this.states; 85 | }; 86 | 87 | Bus.prototype.show = function (del = false, num='') { 88 | strokeWeight(6); 89 | if (this.marked || del) { 90 | stroke(this.markedColor); 91 | } else { 92 | stroke(this.lowColor); 93 | } 94 | 95 | line(this.startX, this.startY, this.endX, this.endY); // Draw the bus line 96 | 97 | if (this.showBusMarker) { 98 | strokeWeight(3); 99 | if (this.direction === 0) { 100 | line(this.startX + Math.abs((this.endX - this.startX) / 2) - 10, this.startY + 10, this.startX + Math.abs((this.endX - this.startX) / 2) + 10, this.endY - 10); 101 | } else { 102 | line(this.startX - 10, this.startY + Math.abs((this.endY - this.startY) / 2) + 10, this.endX + 10, this.startY + Math.abs((this.endY - this.startY) / 2) - 10); 103 | } 104 | if (this.busWidthSet) { 105 | noStroke(); 106 | fill(0); 107 | textSize(this.textSize); 108 | textAlign(CENTER, CENTER); 109 | if (this.direction === 0) { 110 | text(this.busWidth, this.startX + Math.abs((this.endX - this.startX) / 2) - 5, this.startY - this.textDistance); 111 | } else { 112 | text(this.busWidth, this.startX + this.textDistance + 2, this.startY + Math.abs((this.endY - this.startY) / 2) + 5); 113 | } 114 | } 115 | } 116 | 117 | /*noStroke(); 118 | fill(0); 119 | if (this.direction === 0) { 120 | text(num, Math.min(this.startX, this.endX) + 10, this.startY - 15); 121 | } else { 122 | text(num, this.startX + 10, Math.min(this.startY, this.endY) + 15); 123 | }*/ 124 | }; -------------------------------------------------------------------------------- /javascripts/classes/busGroup.js: -------------------------------------------------------------------------------- 1 | // File: busGroup.js 2 | 3 | function BusGroup() { 4 | this.inputGates = []; 5 | this.outputGates = []; 6 | this.inputPorts = []; 7 | this.outputPorts = []; 8 | 9 | this.busses = []; 10 | this.busWidth = 0; 11 | 12 | this.states = Array(this.busWidth).fill(false); 13 | } 14 | 15 | BusGroup.prototype.addBus = function (s) { 16 | this.busses.push(s); 17 | }; 18 | 19 | /* 20 | Add a module input to the bus group 21 | module: the module containing the input 22 | port: the module's input bus port 23 | */ 24 | BusGroup.prototype.addInput = function (gate, port) { 25 | this.inputGates.push(gate); 26 | this.inputPorts.push(port); 27 | }; 28 | 29 | /* 30 | Add a module output to the bus group 31 | module: the module containing the output 32 | port: the module's output bus port 33 | */ 34 | BusGroup.prototype.addOutput = function (gate, port) { 35 | this.outputGates.push(gate); 36 | this.outputPorts.push(port); 37 | }; 38 | 39 | /* 40 | Sets this group's bus width to the given width 41 | */ 42 | BusGroup.prototype.updateBusWidth = function(newWidth=this.busWidth) { 43 | this.busWidth = newWidth; 44 | this.states = Array(this.busWidth).fill(false); // Reinitialize the states array 45 | 46 | // Determine the longest bus and only show the bus markers on that bus 47 | let longest = 0; 48 | let longestLength = 0; 49 | for (let i = 0; i < this.busses.length; i++) { 50 | if (this.busses[i].direction === 0) { 51 | let busLength = Math.abs(this.busses[i].endX - this.busses[i].startX); 52 | if (busLength > longestLength) { 53 | longest = i; 54 | longestLength = busLength; 55 | } 56 | } else { 57 | let busLength = Math.abs(this.busses[i].endY - this.busses[i].startY); 58 | if (busLength > longestLength) { 59 | longest = i; 60 | longestLength = busLength; 61 | } 62 | } 63 | this.busses[i].setBusWidth(this.busWidth); 64 | this.busses[i].showBusMarker = false; 65 | } 66 | if (this.busses.length > 0) { 67 | this.busses[longest].showBusMarker = true; 68 | } 69 | } 70 | 71 | BusGroup.prototype.updateAll = function () { 72 | let allOutputs = []; 73 | for (let j = 0; j < this.outputGates.length; j++) { // For all connected elements 74 | let output = this.outputGates[j].getOutput(this.outputPorts[j]); 75 | allOutputs.push(Array(this.busWidth - output.length).fill(false).concat(output)); // get the output vector 76 | } 77 | 78 | for (let i = 0; i < this.busWidth; i++) { // For every signal, OR it with the current bus state 79 | let bitState = false; 80 | for (let j = 0; j < allOutputs.length; j++) { 81 | if (allOutputs[j].length > i) { 82 | bitState = bitState || allOutputs[j][i]; 83 | } 84 | } 85 | this.states[i] = bitState; 86 | } 87 | 88 | // Propagate the state to all inputs 89 | for (let j = 0; j < this.inputGates.length; j++) { 90 | this.inputGates[j].setInput(this.inputPorts[j], this.states); 91 | } 92 | 93 | if (this.busses[0].states !== this.states) { 94 | this.propagateState(); 95 | } 96 | }; 97 | 98 | BusGroup.prototype.show = function () { 99 | for (let i = 0; i < this.busses.length; i++) { 100 | this.busses[i].show(false); 101 | } 102 | }; 103 | 104 | BusGroup.prototype.propagateState = function () { 105 | for (let i = 0; i < this.busses.length; i++) { 106 | this.busses[i].states = this.states; 107 | } 108 | }; -------------------------------------------------------------------------------- /javascripts/classes/busInput.js: -------------------------------------------------------------------------------- 1 | // File: busInput.js 2 | 3 | function BusInput(x, y, busWidth, custPos = 0) { 4 | this.x = x; // X-Position (translated) 5 | this.y = y; // Y-Position 6 | 7 | this.busWidth = busWidth; 8 | 9 | this.w = GRIDSIZE; 10 | this.h = GRIDSIZE; 11 | 12 | this.highColor = color(HRED, HGREEN, HBLUE); 13 | this.lowColor = color(50, 50, 50); // Color for low inputs (dark grey) 14 | 15 | this.outputs = []; // Vector of the output state 16 | 17 | this.custPosition = custPos; // Designated bus position on a custom element 18 | 19 | //this.id = '_' + Math.random().toString(36).substr(2, 9); 20 | this.id = 'bi' + Date.now() + Math.random() + 'b'; 21 | 22 | this.isTop = false; 23 | this.lbl = ''; 24 | this.marked = false; 25 | 26 | // Initialize the outputs 27 | for (let i = 0; i < this.busWidth; i++) { 28 | this.outputs.push(false); // Set all outputs to low 29 | } 30 | 31 | this.clickBox = new ClickBox(this.x - GRIDSIZE / 2, this.y - GRIDSIZE / 2, this.w, this.h, transform); 32 | this.updateClickBox(); 33 | } 34 | 35 | BusInput.prototype.alterPosition = function (x1, y1) { 36 | this.x += x1; 37 | this.y += y1; 38 | this.updateClickBox(); 39 | }; 40 | 41 | BusInput.prototype.getData = function () { 42 | var data = {}; 43 | data.x = JSON.stringify(this.x); 44 | data.y = JSON.stringify(this.y); 45 | if (this.isTop) { 46 | data.istop = JSON.stringify(true); 47 | } 48 | if (this.lbl !== '') { 49 | data.lbl = this.lbl; 50 | } 51 | data.busWidth = this.busWidth; 52 | data.pos = this.custPosition; 53 | return data; 54 | }; 55 | 56 | /* 57 | Sets the input state 58 | */ 59 | BusInput.prototype.setState = function (s) { 60 | this.setFalse(); 61 | s = Array(Math.max(0, this.busWidth - s.length)).fill(false).concat(s).slice(0, this.busWidth); 62 | for (let i = 0; i < this.busWidth; i++) { 63 | this.outputs[i] = s[i]; 64 | } 65 | }; 66 | 67 | BusInput.prototype.setIsTop = function (b) { 68 | this.isTop = b; 69 | }; 70 | 71 | 72 | BusInput.prototype.getOutput = function () { 73 | return this.outputs; 74 | }; 75 | 76 | BusInput.prototype.mark = function (b) { 77 | this.marked = b; 78 | }; 79 | 80 | BusInput.prototype.setFalse = function () { 81 | this.outputs = Array(this.busWidth).fill(false); 82 | }; 83 | 84 | /* 85 | Sets the coordinates of the output, rounded to grid size 86 | */ 87 | BusInput.prototype.setCoordinates = function (nx, ny) { 88 | this.x = Math.round(nx / GRIDSIZE) * GRIDSIZE - GRIDSIZE / 2; 89 | this.y = Math.round(ny / GRIDSIZE) * GRIDSIZE - GRIDSIZE / 2; 90 | }; 91 | 92 | BusInput.prototype.updateClickBox = function () { 93 | this.clickBox.updatePosition(this.x + GRIDSIZE / 2, this.y + GRIDSIZE / 2); 94 | this.clickBox.setTransform(transform); 95 | }; 96 | 97 | /* 98 | Checks if the mouse is inside the clickBox 99 | */ 100 | BusInput.prototype.mouseOver = function () { 101 | return this.clickBox.mouseOver(); 102 | }; 103 | 104 | /* 105 | Checks if a certain point is in the output 106 | */ 107 | BusInput.prototype.pointInOutput = function (dummy, px, py) { 108 | return this.clickBox.checkPoint(px, py); 109 | }; 110 | 111 | /* 112 | Displays the input on the screen 113 | */ 114 | BusInput.prototype.show = function (order = 0) { 115 | stroke(0); 116 | strokeWeight(3); 117 | if (this.marked) { 118 | stroke(MRED, MGREEN, MBLUE); 119 | fill(150); 120 | } else { 121 | fill(this.lowColor); 122 | } 123 | // Draw the rectangle that represents the input 124 | rect(this.x, this.y, this.w, this.h); 125 | noStroke(); 126 | if (this.marked) { 127 | fill(170); 128 | } else { 129 | fill(LARED, LAGREEN, LABLUE); 130 | } 131 | triangle(this.x + 2, this.y + 2, this.x + GRIDSIZE - 2, this.y + 2, this.x + 2, this.y + GRIDSIZE - 2); 132 | 133 | if (this.marked) { 134 | fill(MRED, MGREEN, MBLUE); 135 | } else { 136 | fill(0); 137 | } 138 | textFont('Arial'); 139 | textSize(10); 140 | textAlign(LEFT, TOP); 141 | text(this.busWidth, this.x + 4, this.y + 4); 142 | 143 | noFill(); 144 | if (this.marked) { 145 | stroke(MRED, MGREEN, MBLUE); 146 | } else { 147 | stroke(0); 148 | } 149 | rect(this.x, this.y, this.w, this.h); 150 | 151 | if (this.marked) { 152 | stroke(MRED, MGREEN, MBLUE); 153 | } else { 154 | stroke(0); 155 | } 156 | strokeWeight(3); 157 | line(this.x + 8, this.y + 22, this.x + 22, this.y + 8); 158 | 159 | if (order > 0) { 160 | noStroke(); 161 | fill(255); 162 | textSize(20); 163 | textFont('ArcaMajora3'); 164 | //textAlign(LEFT, TOP); 165 | if (order.toString().length === 1) { 166 | text(order, this.x + 10, this.y + 7); 167 | } else { 168 | text(order, this.x + 4, this.y + 7); 169 | } 170 | } 171 | 172 | //this.clickBox.markClickBox(); 173 | }; 174 | -------------------------------------------------------------------------------- /javascripts/classes/clickBox.js: -------------------------------------------------------------------------------- 1 | // File: clickBox.js 2 | 3 | function ClickBox(x, y, w, h, transform) { 4 | this.x = x; 5 | this.y = y; 6 | 7 | this.w = w; 8 | this.h = h; 9 | this.transform = transform; 10 | 11 | /* 12 | Sets the transformation of the clickBox 13 | */ 14 | this.setTransform = function (transform) { 15 | this.transform = transform; 16 | }; 17 | 18 | /* 19 | Swaps width and height 20 | */ 21 | this.turn = function () { 22 | this.temp = this.h; 23 | this.h = this.w; 24 | this.w = this.temp; 25 | }; 26 | 27 | /* 28 | Updates the position of the clickBox 29 | */ 30 | this.updatePosition = function (nx, ny) { 31 | this.x = nx; 32 | this.y = ny; 33 | }; 34 | 35 | this.updateSize = function (nw, nh) { 36 | this.w = nw; 37 | this.h = nh; 38 | }; 39 | 40 | /* 41 | Draws a rect around the clickBox (debugging purposes) 42 | */ 43 | this.markClickBox = function (select = false) { 44 | if (select) { 45 | noStroke(); 46 | if (currentTheme === 'dark') { 47 | fill(50); 48 | stroke(50); 49 | } else { 50 | fill(255); 51 | stroke(255); 52 | } 53 | strokeWeight(3); 54 | rect(this.x + this.w / 2 - (200 / this.transform.zoom), this.y - this.h / 2 - (50 / this.transform.zoom), 200 / this.transform.zoom, 50 / this.transform.zoom); 55 | } 56 | stroke(50); 57 | fill(0, 30); 58 | rect(this.x - this.w / 2, this.y - this.h / 2, this.w, this.h); 59 | }; 60 | 61 | // Returns if the mouse is in a gridSize sized area around x, y 62 | this.mouseOver = function (selectOffset = false) { 63 | if (!selectOffset) { 64 | return (((mouseX / this.transform.zoom - this.transform.dx) >= (this.x - this.w / 2)) && 65 | ((mouseX / this.transform.zoom - this.transform.dx) <= (this.x + this.w / 2)) && 66 | ((mouseY / this.transform.zoom - this.transform.dy) >= (this.y - this.h / 2)) && 67 | ((mouseY / this.transform.zoom - this.transform.dy) <= (this.y + this.h / 2))); 68 | } else { 69 | return (((mouseX / this.transform.zoom - this.transform.dx) >= Math.min((this.x - this.w / 2), this.x + this.w / 2 - (200 / this.transform.zoom))) && 70 | ((mouseX / this.transform.zoom - this.transform.dx) <= (this.x + this.w / 2)) && 71 | ((mouseY / this.transform.zoom - this.transform.dy) >= (this.y - this.h / 2 - (50 / this.transform.zoom))) && 72 | ((mouseY / this.transform.zoom - this.transform.dy) <= (this.y + this.h / 2))); 73 | } 74 | }; 75 | 76 | /* 77 | Checks if one point (possibly != mouseX/Y) is inside the ClickBox 78 | */ 79 | this.checkPoint = function(px, py) { 80 | return ((px >= (this.x - this.w / 2)) && (px <= (this.x + this.w / 2)) && 81 | (py >= (this.y - this.h / 2)) && (py <= (this.y + this.h / 2))); 82 | }; 83 | } -------------------------------------------------------------------------------- /javascripts/classes/conpoint.js: -------------------------------------------------------------------------------- 1 | // File: conpoint.js 2 | 3 | function ConPoint(x, y, state, g, isBusConpoint = false) { 4 | this.x = x; 5 | this.y = y; 6 | this.state = state; 7 | this.group = g; 8 | this.isBusConpoint = isBusConpoint; 9 | 10 | this.highColor = color(HRED, HGREEN, HBLUE); // Color for high 11 | this.lowColor = color(LRED, LGREEN, LBLUE); // Color for low 12 | 13 | this.marked = false; 14 | this.markColor = color(MRED, MGREEN, MBLUE); 15 | 16 | this.id = 'p' + Date.now() + Math.random(); 17 | } 18 | 19 | ConPoint.prototype.getData = function () { 20 | let data = {}; 21 | data.x = JSON.stringify(this.x); 22 | data.y = JSON.stringify(this.y); 23 | return data; 24 | }; 25 | 26 | ConPoint.prototype.alterPosition = function (x1, y1) { 27 | this.x += x1; 28 | this.y += y1; 29 | }; 30 | 31 | ConPoint.prototype.setGroup = function (ng) { 32 | this.group = ng; 33 | }; 34 | 35 | ConPoint.prototype.show = function () { 36 | strokeWeight(0); 37 | if (this.marked) { 38 | fill(this.markColor); 39 | } else if (this.state) { 40 | fill(this.highColor); 41 | } else { 42 | fill(this.lowColor); 43 | } 44 | if (!this.isBusConpoint) { 45 | rect(this.x - 3, this.y - 3, 7, 7); 46 | } else { 47 | rect(this.x - 5, this.y - 5, 10, 10); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /javascripts/classes/diode.js: -------------------------------------------------------------------------------- 1 | // File: diode.js 2 | 3 | function Diode(x, y, state) { 4 | this.x = x; // X position 5 | this.y = y; // Y position 6 | this.state = state; // State of the diode 7 | 8 | this.highColor = color(HRED, HGREEN, HBLUE); // Color for high 9 | this.lowColor = color(LRED, LGREEN, LBLUE); // Color for low 10 | 11 | this.groupA = -1; // Group A (Horizontal crossing) 12 | this.groupB = -1; // Group B (Vertical Crossing) 13 | 14 | this.clickBox = new ClickBox(this.x, this.y, 20, 20, transform); 15 | 16 | this.marked = false; 17 | 18 | this.id = 'd' + Date.now() + Math.random(); 19 | 20 | this.getData = function () { 21 | var data = {}; 22 | data.x = JSON.stringify(this.x); 23 | data.y = JSON.stringify(this.y); 24 | return data; 25 | }; 26 | 27 | this.alterPosition = function (x1, y1) { 28 | this.x += x1; 29 | this.y += y1; 30 | this.updateClickBox(); 31 | }; 32 | 33 | /* 34 | Sets the state of the diode 35 | */ 36 | this.setState = function (s) { 37 | this.state = s; 38 | }; 39 | 40 | this.setGroups = function (a, b) { 41 | this.groupA = a; 42 | this.groupB = b; 43 | }; 44 | 45 | /* 46 | Sets the coordinates of the diode, rounded to grid size 47 | */ 48 | this.setCoordinates = function (nx, ny) { 49 | this.x = Math.round(nx / GRIDSIZE) * GRIDSIZE; 50 | this.y = Math.round(ny / GRIDSIZE) * GRIDSIZE; 51 | }; 52 | 53 | this.updateClickBox = function () { 54 | this.clickBox.updatePosition(this.x, this.y); 55 | this.clickBox.setTransform(transform); 56 | }; 57 | 58 | this.updateClickBox(); 59 | 60 | /* 61 | Checks if the mouse is inside the clickBox 62 | */ 63 | this.mouseOver = function () { 64 | return this.clickBox.mouseOver(); 65 | }; 66 | 67 | this.show = function () { 68 | noStroke(); 69 | if (this.marked) { 70 | fill(MRED, MGREEN, MBLUE); 71 | } else if (this.state) { 72 | fill(this.highColor); 73 | } else { 74 | fill(this.lowColor); 75 | } 76 | triangle(this.x, this.y + 11, this.x - 11, this.y, this.x + 11, this.y); 77 | //this.clickBox.markClickBox(); 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /javascripts/classes/group.js: -------------------------------------------------------------------------------- 1 | // File: group.js 2 | 3 | function Group() { 4 | this.inputGates = []; 5 | this.outputGates = []; 6 | this.inputPorts = []; 7 | this.outputPorts = []; 8 | 9 | this.wires = []; 10 | 11 | this.state = false; 12 | this.diodeState = false; 13 | this.dstateset = false; 14 | } 15 | 16 | Group.prototype.addWire = function (s) { 17 | this.wires.push(s); 18 | }; 19 | 20 | Group.prototype.addInput = function (gate, port) { 21 | this.inputGates.push(gate); 22 | this.inputPorts.push(port); 23 | }; 24 | 25 | Group.prototype.addOutput = function (gate, port) { 26 | this.outputGates.push(gate); 27 | this.outputPorts.push(port); 28 | }; 29 | 30 | /* 31 | This is evoked when a diode associated with this group is high 32 | */ 33 | Group.prototype.diodeHigh = function () { 34 | this.diodeState = true; 35 | this.dstateset = true; 36 | }; 37 | 38 | Group.prototype.updateAll = function () { 39 | this.state = false; 40 | // Get all states of the gate outputs 41 | for (let j = 0; j < this.outputGates.length; j++) { 42 | if (this.outputGates[j].getOutput(this.outputPorts[j])) { 43 | this.state = true; 44 | for (let j = 0; j < this.outputGates.length; j++) { 45 | this.outputGates[j].outputs[this.outputPorts[j]] = true; 46 | } 47 | break; 48 | } 49 | } 50 | 51 | // If no input is true, take diodeState as state 52 | if (!this.state && this.dstateset) { 53 | this.state = this.diodeState; 54 | this.dstateset = false; 55 | } else if (!this.dstateset) { 56 | this.diodeState = false; 57 | } 58 | 59 | // Propagate the state to all inputs 60 | for (let j = 0; j < this.inputGates.length; j++) { 61 | this.inputGates[j].setInput(this.inputPorts[j], this.state); 62 | } 63 | 64 | if (this.wires[0].state !== this.state) { 65 | this.propagateState(); // Propagate the state to all wires 66 | } 67 | }; 68 | 69 | Group.prototype.show = function () { 70 | for (let i = 0; i < this.wires.length; i++) { 71 | this.wires[i].show(false); 72 | } 73 | }; 74 | 75 | Group.prototype.propagateState = function () { 76 | for (let i = 0; i < this.wires.length; i++) { 77 | this.wires[i].state = this.state; 78 | } 79 | }; -------------------------------------------------------------------------------- /javascripts/classes/input.js: -------------------------------------------------------------------------------- 1 | // File: input.js 2 | 3 | function Input(x, y, custPos = 0) { 4 | this.x = x; // X-Position 5 | this.y = y; // Y-Position 6 | 7 | this.w = GRIDSIZE; // Width of the putput 8 | this.h = GRIDSIZE; // Height of the output 9 | 10 | this.state = false; // Input state 11 | this.outputs = false; // equal to state 12 | 13 | this.framecount = -1; 14 | this.clock = false; 15 | this.speed = 30; 16 | 17 | this.custPosition = custPos; // Designated position on a custom element 18 | 19 | this.highColor = color(HRED, HGREEN, HBLUE); // Color for high inputs 20 | this.lowColor = color(50, 50, 50); // Color for low inputs (dark grey) 21 | 22 | this.isTop = false; 23 | this.lbl = ''; 24 | this.marked = false; 25 | 26 | this.id = 'i' + Date.now() + Math.random(); 27 | 28 | // ClickBox is used for output and global 29 | this.clickBox = new ClickBox(this.x - GRIDSIZE / 2, this.y - GRIDSIZE / 2, this.w, this.h, transform); 30 | this.updateClickBox(); 31 | } 32 | 33 | Input.prototype.alterPosition = function (x1, y1) { 34 | this.x += x1; 35 | this.y += y1; 36 | this.updateClickBox(); 37 | }; 38 | 39 | Input.prototype.getData = function () { 40 | var data = {}; 41 | data.x = JSON.stringify(this.x); 42 | data.y = JSON.stringify(this.y); 43 | if (this.isTop) { 44 | data.istop = JSON.stringify(true); 45 | } 46 | if (this.lbl !== '') { 47 | data.lbl = this.lbl; 48 | } 49 | if (this.framecount === -1) { 50 | data.framecount = JSON.stringify(-1); 51 | } else { 52 | data.framecount = JSON.stringify(0); 53 | } 54 | data.clock = JSON.stringify(this.clock); 55 | if (this.clock) { 56 | data.speed = JSON.stringify(this.speed); 57 | } 58 | data.pos = this.custPosition; 59 | return data; 60 | }; 61 | 62 | Input.prototype.getIsClock = function () { 63 | return this.clock; 64 | }; 65 | 66 | Input.prototype.setClock = function (clk) { 67 | this.clock = Boolean(clk); 68 | }; 69 | 70 | /* 71 | Sets the input state 72 | */ 73 | Input.prototype.setState = function (s) { 74 | this.state = s; 75 | this.outputs = s; 76 | }; 77 | 78 | Input.prototype.setIsTop = function (b) { 79 | this.isTop = b; 80 | }; 81 | 82 | Input.prototype.setSpeed = function (s) { 83 | this.speed = s; 84 | }; 85 | 86 | Input.prototype.resetFramecount = function () { 87 | this.framecount = this.speed; 88 | this.clock = true; 89 | }; 90 | 91 | /* 92 | Toggles the state 93 | */ 94 | Input.prototype.toggle = function () { 95 | this.setState(!this.state); 96 | }; 97 | 98 | Input.prototype.getOutput = function () { 99 | return this.state; 100 | }; 101 | 102 | Input.prototype.mark = function (b) { 103 | this.marked = b; 104 | }; 105 | 106 | /* 107 | Sets the coordinates of the output, rounded to grid size 108 | */ 109 | Input.prototype.setCoordinates = function (nx, ny) { 110 | this.x = Math.round(nx / GRIDSIZE) * GRIDSIZE - GRIDSIZE / 2; 111 | this.y = Math.round(ny / GRIDSIZE) * GRIDSIZE - GRIDSIZE / 2; 112 | // Check bounds 113 | /*if (this.x < 15) { 114 | this.x = 15; 115 | } 116 | if (this.y < 15) { 117 | this.y = 15; 118 | }*/ 119 | }; 120 | 121 | Input.prototype.updateClickBox = function () { 122 | this.clickBox.updatePosition(this.x + GRIDSIZE / 2, this.y + GRIDSIZE / 2); 123 | this.clickBox.setTransform(transform); 124 | }; 125 | 126 | /* 127 | Checks if the mouse is inside the clickBox 128 | */ 129 | Input.prototype.mouseOver = function () { 130 | return this.clickBox.mouseOver(); 131 | }; 132 | 133 | /* 134 | Checks if a certain point is in the output 135 | */ 136 | Input.prototype.pointInOutput = function (dummy, px, py) { 137 | return this.clickBox.checkPoint(px, py); 138 | }; 139 | 140 | /* 141 | Displays the input on the screen 142 | */ 143 | Input.prototype.show = function (order = 0) { 144 | stroke(0); 145 | strokeWeight(3); 146 | if (this.state) { 147 | fill(this.highColor); 148 | } else if (this.marked) { 149 | stroke(MRED, MGREEN, MBLUE); 150 | fill(150); 151 | } else { 152 | fill(this.lowColor); 153 | } 154 | // Draw the rectangle that represents the input 155 | rect(this.x, this.y, this.w, this.h); 156 | noStroke(); 157 | if (this.state) { 158 | fill(HARED, HAGREEN, HABLUE); 159 | } else if (this.marked) { 160 | fill(170); 161 | } else { 162 | fill(LARED, LAGREEN, LABLUE); 163 | } 164 | triangle(this.x + 2, this.y + 2, this.x + GRIDSIZE - 2, this.y + 2, this.x + 2, this.y + GRIDSIZE - 2); 165 | noFill(); 166 | if (this.marked) { 167 | stroke(MRED, MGREEN, MBLUE); 168 | } else { 169 | stroke(0); 170 | } 171 | rect(this.x, this.y, this.w, this.h); 172 | if (this.framecount >= 0 && !this.clock) { 173 | if (this.marked) { 174 | fill(MRED, MGREEN, MBLUE); 175 | } else { 176 | fill(0); 177 | } 178 | if (this.state) { 179 | strokeWeight(7); 180 | } 181 | rect(this.x + 10, this.y + 10, this.w / 3, this.h / 3); 182 | } 183 | 184 | if (this.clock) { 185 | if (this.marked) { 186 | stroke(MRED, MGREEN, MBLUE); 187 | } else { 188 | stroke(0); 189 | } 190 | strokeWeight(3); 191 | line(this.x + 15, this.y + 6, this.x + 15, this.y + 15); 192 | line(this.x + 15, this.y + 15, this.x + 22, this.y + 20); 193 | } 194 | 195 | if (order > 0) { 196 | noStroke(); 197 | fill(255); 198 | textSize(20); 199 | textFont('ArcaMajora3'); 200 | textAlign(LEFT, TOP); 201 | if (order.toString().length === 1) { 202 | text(order, this.x + 10, this.y + 7); 203 | } else { 204 | text(order, this.x + 4, this.y + 7); 205 | } 206 | } 207 | 208 | //this.clickBox.markClickBox(); 209 | }; 210 | -------------------------------------------------------------------------------- /javascripts/classes/label.js: -------------------------------------------------------------------------------- 1 | // File: label.js 2 | 3 | function Label(x, y, txt) { 4 | this.x = x; // X position 5 | this.y = y; // Y position 6 | this.h = 20; 7 | this.w = 0; 8 | this.txt = txt; // Label text 9 | this.lines = []; 10 | this.marked = false; 11 | 12 | this.id = 'l' + Date.now() + Math.random(); 13 | 14 | this.clickBox = new ClickBox(this.x, this.y, this.w, this.h, transform); 15 | 16 | this.getData = function () { 17 | var data = {}; 18 | data.x = JSON.stringify(this.x); 19 | data.y = JSON.stringify(this.y); 20 | data.txt = this.txt; 21 | return data; 22 | }; 23 | 24 | /* 25 | Sets the coordinates of the label, rounded to grid size 26 | */ 27 | this.setCoordinates = function (nx, ny) { 28 | this.x = Math.round(nx / GRIDSIZE) * GRIDSIZE; 29 | this.y = Math.round(ny / GRIDSIZE) * GRIDSIZE; 30 | }; 31 | 32 | this.setCoordinates(x, y); 33 | 34 | this.mark = function (marked) { 35 | this.marked = marked; 36 | }; 37 | 38 | this.alterPosition = function (x1, y1) { 39 | this.x += x1; 40 | this.y += y1; 41 | this.updateClickBox(); 42 | }; 43 | 44 | this.updateClickBox = function () { 45 | this.clickBox.updatePosition(this.x + this.w / 2 - 15, this.y + this.h / 2 - 10); 46 | this.clickBox.updateSize(this.w, this.h + 10); 47 | this.clickBox.setTransform(transform); 48 | }; 49 | 50 | this.alterText = function (txt) { 51 | this.txt = txt; 52 | this.lines = txt.split('\n').filter(e => e !== ''); 53 | if (this.lines.length === 0) { 54 | this.lines = ['New Label']; 55 | } 56 | this.w = Math.ceil((textWidth(this.lines.reduce(function (a, b) { return a.length > b.length ? a : b; })) + 20) / 30) * 30; 57 | this.h = 30 * this.lines.length - 10; 58 | this.updateClickBox(); 59 | }; 60 | 61 | textFont('Gudea'); 62 | textSize(20); 63 | this.alterText(txt); 64 | 65 | /* 66 | Checks if the mouse is inside the clickBox 67 | */ 68 | this.mouseOver = function () { 69 | return this.clickBox.mouseOver(); 70 | }; 71 | 72 | this.show = function () { 73 | strokeWeight(3); 74 | stroke(140); 75 | noStroke(); 76 | fill(150, 200); 77 | rect(this.x, this.y - 15, this.w, this.h + 10); 78 | if (this.marked) { 79 | fill(MRED, MGREEN, MBLUE); 80 | } else { 81 | fill(50); 82 | } 83 | for (let i = 0; i < this.lines.length; i++) { 84 | rect(this.x, this.y - 15 + i * 30, 3, 30); 85 | } 86 | if (this.marked) { 87 | fill(255); 88 | } else { 89 | fill(0); 90 | } 91 | for (let i = 0; i < this.lines.length; i++) { 92 | text(this.lines[i], this.x + 15, this.y - 9 + i * 30, this.w, this.h); 93 | } 94 | //this.clickBox.markClickBox(); 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /javascripts/classes/output.js: -------------------------------------------------------------------------------- 1 | // File: output.js 2 | 3 | function Output(x, y, colr) { 4 | this.x = x; // X-Position 5 | this.y = y; // Y-Position 6 | this.w = GRIDSIZE; // Width of the putput 7 | this.h = GRIDSIZE; // Height of the output 8 | this.state = false; // Output state 9 | this.lbl = ''; 10 | this.colr = colr; // 0 = red, 1 = yellow, 2 = green, 3 = blue 11 | this.marked = false; 12 | this.highColor = color(HRED, HGREEN, HBLUE); // Color for high outputs 13 | this.accentColor = color(HARED, HAGREEN, HABLUE); 14 | //this.lowColor = color(LRED, LGREEN, LBLUE); // Color for low outputs 15 | //this.markColor = color(MRED, MGREEN, MBLUE); // Color for marked outputs 16 | 17 | this.id = 'o' + Date.now() + Math.random(); 18 | 19 | // ClickBox is used for input and global 20 | this.clickBox = new ClickBox(this.x, this.y, this.w, this.h, transform); 21 | 22 | this.updateColor(); 23 | this.updateClickBox(); 24 | } 25 | 26 | /* 27 | Manually sets the output state 28 | */ 29 | Output.prototype.setInput = function (dummy, s) { 30 | this.state = s; 31 | }; 32 | 33 | Output.prototype.getData = function () { 34 | var data = {}; 35 | data.x = JSON.stringify(this.x); 36 | data.y = JSON.stringify(this.y); 37 | data.colr = JSON.stringify(this.colr); 38 | if (this.lbl !== '') { 39 | data.lbl = this.lbl; 40 | } 41 | return data; 42 | }; 43 | 44 | /* 45 | Sets the coordinates of the output, rounded to grid size 46 | */ 47 | Output.prototype.setCoordinates = function (nx, ny) { 48 | this.x = Math.round(nx / GRIDSIZE) * GRIDSIZE; 49 | this.y = Math.round(ny / GRIDSIZE) * GRIDSIZE; 50 | }; 51 | 52 | Output.prototype.updateClickBox = function () { 53 | this.clickBox.updatePosition(this.x, this.y); 54 | this.clickBox.setTransform(transform); 55 | }; 56 | 57 | Output.prototype.alterPosition = function (x1, y1) { 58 | this.x += x1; 59 | this.y += y1; 60 | this.updateClickBox(); 61 | }; 62 | 63 | /* 64 | Checks if the mouse is inside the clickBox 65 | */ 66 | Output.prototype.mouseOver = function () { 67 | return this.clickBox.mouseOver(); 68 | }; 69 | 70 | Output.prototype.pointInInput = function (dummy, px, py) { 71 | return this.clickBox.checkPoint(px, py); 72 | }; 73 | 74 | Output.prototype.mark = function (b) { 75 | this.marked = b; 76 | }; 77 | 78 | Output.prototype.updateColor = function () { 79 | switch (this.colr) { 80 | case 0: 81 | this.highColor = color(HRED, HGREEN, HBLUE); 82 | this.accentColor = color(HARED, HAGREEN, HABLUE); 83 | break; 84 | case 1: 85 | this.highColor = color(YRED, YGREEN, YBLUE); 86 | this.accentColor = color(YARED, YAGREEN, YABLUE); 87 | break; 88 | case 2: 89 | this.highColor = color(GRED, GGREEN, GBLUE); 90 | this.accentColor = color(GARED, GAGREEN, GABLUE); 91 | break; 92 | case 3: 93 | this.highColor = color(BRED, BGREEN, BBLUE); 94 | this.accentColor = color(BARED, BAGREEN, BABLUE); 95 | break; 96 | default: 97 | this.highColor = color(HRED, HGREEN, HBLUE); 98 | this.accentColor = color(HARED, HAGREEN, HABLUE); 99 | console.log('Notice: Output color is invalid, setting to red'); 100 | break; 101 | } 102 | }; 103 | 104 | /* 105 | Displays the output on the screen 106 | */ 107 | Output.prototype.show = function (order = 0) { 108 | stroke(0); 109 | strokeWeight(3); 110 | if (this.state) { 111 | fill(this.highColor); 112 | } else if (this.marked) { 113 | stroke(MRED, MGREEN, MBLUE); 114 | fill(150); 115 | } else { 116 | fill(50); 117 | } 118 | // Draw the circle that represents the output 119 | ellipse(this.x, this.y, this.w, this.h); 120 | if (this.state) { 121 | fill(this.accentColor); 122 | } else if (this.marked) { 123 | fill(170); 124 | } else { 125 | fill(LARED, LAGREEN, LABLUE); 126 | } 127 | arc(this.x, this.y, GRIDSIZE, GRIDSIZE, HALF_PI + QUARTER_PI, PI + HALF_PI + QUARTER_PI, OPEN); 128 | 129 | if (order > 0) { 130 | noStroke(); 131 | fill(255); 132 | textSize(20); 133 | textFont('ArcaMajora3'); 134 | textAlign(LEFT, TOP); 135 | if (order.toString().length === 1) { 136 | text(order, this.x - 6, this.y - 8); 137 | } else { 138 | text(order, this.x - 12, this.y - 8); 139 | } 140 | } 141 | /*if (!this.state) { 142 | stroke(200); 143 | } else { 144 | stroke(255); 145 | }*/ 146 | //strokeWeight(3); 147 | //noFill(); 148 | //arc(this.x, this.y, 20, 20, PI, PI + HALF_PI); 149 | //this.clickBox.markClickBox(); 150 | }; 151 | -------------------------------------------------------------------------------- /javascripts/classes/transformation.js: -------------------------------------------------------------------------------- 1 | // File: transformation.js 2 | 3 | function Transformation(dx, dy, zoom) { 4 | this.dx = dx; 5 | this.dy = dy; 6 | this.zoom = zoom; 7 | } -------------------------------------------------------------------------------- /javascripts/classes/wire.js: -------------------------------------------------------------------------------- 1 | // File: wire.js 2 | 3 | function Wire(dir, startX, startY, mimicBus = false) { 4 | this.highColor = color(HRED, HGREEN, HBLUE); // Color for high 5 | this.lowColor = color(LRED, LGREEN, LBLUE); // Color for low 6 | this.markedColor = color(MRED, MGREEN, MBLUE); // Color for marked 7 | 8 | this.state = false; // Wire state (false low, true high); 9 | 10 | this.direction = dir; // 0 or 1, meaning horizontal or vertical 11 | 12 | this.startX = 0; // Start point of the segment 13 | this.startY = 0; 14 | 15 | this.endX = 0; 16 | this.endY = 0; 17 | 18 | this.mimicBus = mimicBus; 19 | 20 | this.marked = false; 21 | 22 | this.group = -1; 23 | 24 | this.id = 'w' + Date.now() + Math.random(); 25 | 26 | this.changePosition(startX, startY); // Initialize the start point 27 | } 28 | 29 | Wire.prototype.getData = function () { 30 | var data = {}; 31 | data.x1 = JSON.stringify(this.startX); 32 | data.y1 = JSON.stringify(this.startY); 33 | if (this.startX !== this.endX) { 34 | data.x2 = JSON.stringify(this.endX); 35 | } else { 36 | data.y2 = JSON.stringify(this.endY); 37 | } 38 | return data; 39 | }; 40 | 41 | Wire.prototype.alterPosition = function (x1, y1) { 42 | this.endX += x1; 43 | this.endY += y1; 44 | this.startX += x1; 45 | this.startY += y1; 46 | }; 47 | 48 | Wire.prototype.changePosition = function (newX, newY) { 49 | this.startX = Math.round(newX / GRIDSIZE) * GRIDSIZE; 50 | this.startY = Math.round(newY / GRIDSIZE) * GRIDSIZE; 51 | switch (this.direction) { 52 | case 0: 53 | this.endX = this.startX + GRIDSIZE; 54 | this.endY = this.startY; 55 | break; 56 | case 1: 57 | this.endY = this.startY + GRIDSIZE; 58 | this.endX = this.startX; 59 | break; 60 | default: 61 | console.log('No valid direction given!'); 62 | } 63 | }; 64 | 65 | Wire.prototype.setState = function (s) { 66 | this.state = s; 67 | }; 68 | 69 | Wire.prototype.setGroup = function (g) { 70 | this.group = g; 71 | }; 72 | 73 | Wire.prototype.getOutput = function () { 74 | return this.state; 75 | }; 76 | 77 | Wire.prototype.show = function (del = false, num='') { 78 | if (this.state || del) { 79 | strokeWeight(5); 80 | } else { 81 | strokeWeight(3); 82 | } 83 | if (this.mimicBus) { 84 | strokeWeight(6); 85 | } 86 | if (this.state) { 87 | stroke(this.highColor); 88 | } else if (this.marked || del) { 89 | stroke(this.markedColor); 90 | } else { 91 | stroke(this.lowColor); 92 | } 93 | line(this.startX, this.startY, this.endX, this.endY); 94 | /*if (this.mimicBus) { 95 | strokeWeight(3); 96 | if (this.direction === 0) { 97 | line(this.startX + Math.abs((this.endX - this.startX) / 2) - 10, this.startY + 10, this.startX + Math.abs((this.endX - this.startX) / 2) + 10, this.endY - 10); 98 | } else { 99 | line(this.startX - 10, this.startY + Math.abs((this.endY - this.startY) / 2) + 10, this.endX + 10, this.startY + Math.abs((this.endY - this.startY) / 2) - 10); 100 | } 101 | }*/ 102 | /*noStroke(); 103 | fill(0); 104 | if (this.direction === 0) { 105 | text(num, Math.min(this.startX, this.endX) + 10, this.startY - 15); 106 | } else { 107 | text(num, this.startX + 10, Math.min(this.startY, this.endY) + 15); 108 | }*/ 109 | }; -------------------------------------------------------------------------------- /javascripts/constants.js: -------------------------------------------------------------------------------- 1 | // File: constants.js 2 | 3 | const GRIDSIZE = 30; // Standard grid size (plz don't change) 4 | const WIRECBSIZE = 20; // Size of the wire ClickBoxes 5 | const IOCBSIZE = 20; // Size of the in-/outputs ClickBoxes 6 | 7 | const HRED = 200, HGREEN = 50, HBLUE = 50; // Color for high wires, in- and outputs (red) 8 | const LRED = 0, LGREEN = 0, LBLUE = 0; // Color for low wires (black) 9 | const MRED = 169, MGREEN = 8, MBLUE = 28; // Color for marked elements (darker red) 10 | const YRED = 240, YGREEN = 240, YBLUE = 50; // Color for yellow outputs 11 | const GRED = 40, GGREEN = 180, GBLUE = 40; // Color for green outputs 12 | const BRED = 10, BGREEN = 100, BBLUE = 190; // Color for blue outputs 13 | const HARED = 209, HAGREEN = 71, HABLUE = 71; // Accent color for high in- and outputs (red) 14 | const LARED = 70, LAGREEN = 70, LABLUE = 70; // Accent color for low elements (dark grey) 15 | const MARED = 200, MAGREEN = 50, MABLUE = 50; // Accent color for marked elements (red) 16 | const YARED = 255, YAGREEN = 255, YABLUE = 83; // Accent color for yellow outputs 17 | const GARED = 78, GAGREEN = 208, GABLUE = 69; // Accent color for green outputs 18 | const BARED = 63, BAGREEN = 125, BABLUE = 218; // Accent color for blue outputs 19 | 20 | // Array indizees for the param array 21 | const GATENUM = 0; // Index of the gates 22 | const OUTPNUM = 1; // Index of the outputs 23 | const INPNUM = 2; // Index of the inputs 24 | const WIRENUM = 3; // Index of the wires 25 | const CPNUM = 4; // Index of the conPoints 26 | const CUSTNUM = 5; // Index of the customs 27 | const DINUM = 6; // Index of the diodes 28 | const DECNUM = 7; 29 | const BUSNUM = 8; 30 | const BUSINNUM = 9; 31 | const UNWRAPNUM = 10; 32 | const WRAPNUM = 11; 33 | 34 | const BUTCOUNT = 10; // Number of frames the button should be high 35 | 36 | const HIST_LENGTH = 20; // Max number of undos possible -------------------------------------------------------------------------------- /javascripts/modifierMenu.js: -------------------------------------------------------------------------------- 1 | // File: modifierMenu.js 2 | // Contains functions for the modifier mode 3 | 4 | function enterModifierMode() { 5 | customDialog.hide(); 6 | closeSaveDialog(); 7 | screenshotDialog = false; 8 | closeModifierMenu(); 9 | justClosedMenu = false; 10 | hideModuleOptions(); 11 | hideAllOptions(); 12 | setUnactive(); 13 | setControlMode('modify'); 14 | setSelectMode('none'); 15 | editButton.classList.add('active'); 16 | configureButtons('edit'); 17 | document.getElementById('select-tools').style.display = 'none'; 18 | document.getElementById('screenshot-dialog').style.display = 'none'; 19 | mainCanvas.elt.classList.remove('dark-canvas'); 20 | addType = 0; 21 | } 22 | 23 | function closeModifierMenu() { 24 | hideElementMenus(); // Hide all element menus 25 | unmarkPropTargets(); // Unmark all outputs, clocks, etc. 26 | mainCanvas.elt.classList.remove('dark-canvas'); // Lighten up the canvas 27 | } 28 | 29 | /* 30 | Unmarks all objects that can be marked in the modifier mode 31 | */ 32 | function unmarkPropTargets() { 33 | for (const elem of inputs) { 34 | elem.mark(false); 35 | } 36 | for (const elem of outputs) { 37 | elem.mark(false); 38 | } 39 | for (const elem of busInputs) { 40 | elem.mark(false); 41 | } 42 | for (const elem of labels) { 43 | elem.mark(false); 44 | } 45 | inputToModify = -1; 46 | outputToModify = -1; 47 | labelToModify = -1; 48 | } 49 | 50 | /* 51 | Unmarks all markable objects, for example after dragging a selection 52 | */ 53 | function unmarkAll() { 54 | for (const elem of inputs) { 55 | elem.mark(false); 56 | } 57 | for (const elem of outputs) { 58 | elem.mark(false); 59 | } 60 | for (const elem of labels) { 61 | elem.mark(false); 62 | } 63 | for (const elem of gates) { 64 | elem.marked = false; 65 | } 66 | for (const elem of customs) { 67 | elem.marked = false; 68 | } 69 | for (const elem of conpoints) { 70 | elem.marked = false; 71 | } 72 | for (const elem of diodes) { 73 | elem.marked = false; 74 | } 75 | for (const elem of wires) { 76 | elem.marked = false; 77 | } 78 | for (const elem of busses) { 79 | elem.marked = false; 80 | } 81 | for (const elem of busWrappers) { 82 | elem.marked = false; 83 | } 84 | for (const elem of busUnwrappers) { 85 | elem.marked = false; 86 | } 87 | for (const elem of busInputs) { 88 | elem.marked = false; 89 | } 90 | for (const elem of decoders) { 91 | elem.marked = false; 92 | } 93 | for (const elem of segDisplays) { 94 | elem.marked = false; 95 | } 96 | } 97 | 98 | /* 99 | Shows the DOM elements for the input options and unmarks all other 100 | objects that can be marked in modifier mode 101 | */ 102 | function showClockPropMenu() { 103 | hideElementMenus(); 104 | setClockModifierVisibility(true); 105 | clockspeedSlider.value = 61 - inputs[inputToModify].speed; 106 | if (inputs[inputToModify].speed !== 1) { 107 | document.getElementById('cs-label').innerHTML = inputs[inputToModify].speed + ' ticks/toggle'; 108 | } else { 109 | document.getElementById('cs-label').innerHTML = inputs[inputToModify].speed + ' tick/toggle'; 110 | } 111 | } 112 | 113 | /* 114 | Shows the DOM elements for the output options and unmarks all other 115 | objects that can be marked in modifier mode 116 | */ 117 | function showOutputPropMenu() { 118 | hideElementMenus(); 119 | setOutputModifierVisibility(true); 120 | setOutputColor(outputs[outputToModify].colr); 121 | } 122 | 123 | /* 124 | Shows the DOM elements for the label options and unmarks all other 125 | objects that can be marked in modifier mode 126 | */ 127 | function showLabelPropMenu() { 128 | hideElementMenus(); 129 | setLabelModifierVisibility(true); 130 | labelTextBox.value = labels[labelToModify].txt; 131 | } 132 | 133 | function updateModifierMenuPosition() { 134 | mainCanvas.elt.classList.add('dark-canvas'); 135 | if (inputToModify >= 0) { 136 | modifierMenuX = (inputs[inputToModify].x + transform.dx - 1) * transform.zoom; 137 | modifierMenuY = (inputs[inputToModify].y + transform.dy + GRIDSIZE + 2) * transform.zoom; 138 | } else if (outputToModify >= 0) { 139 | modifierMenuX = (outputs[outputToModify].x + transform.dx - GRIDSIZE / 2 - 1) * transform.zoom; 140 | modifierMenuY = (outputs[outputToModify].y + transform.dy + GRIDSIZE / 2 + 2) * transform.zoom; 141 | } else if (labelToModify >= 0) { 142 | modifierMenuX = (labels[labelToModify].x + transform.dx) * transform.zoom; 143 | modifierMenuY = (labels[labelToModify].y + transform.dy + GRIDSIZE / 2 + GRIDSIZE * (labels[labelToModify].lines.length - 1)) * transform.zoom; 144 | } 145 | } 146 | 147 | function positionModifierElements() { 148 | document.getElementById('clock-modifier').style.left = modifierMenuX + 240 + 'px'; 149 | document.getElementById('clock-modifier').style.top = modifierMenuY + 'px'; 150 | 151 | document.getElementById('output-modifier').style.left = modifierMenuX + 240 + 'px'; 152 | document.getElementById('output-modifier').style.top = modifierMenuY + 'px'; 153 | 154 | document.getElementById('label-modifier').style.left = modifierMenuX + 240 + 'px'; 155 | document.getElementById('label-modifier').style.top = modifierMenuY + 'px'; 156 | } 157 | 158 | function swapOutputs(a, b) { 159 | outputs[a] = outputs.splice(b, 1, outputs[a])[0]; 160 | } 161 | 162 | /* 163 | Updates the color of the marked output according to the 164 | selected color in the select box 165 | */ 166 | function newOutputColor(code) { 167 | setOutputColor(code); 168 | outputs[outputToModify].colr = code; 169 | outputs[outputToModify].updateColor(); 170 | } 171 | 172 | function setOutputColor(code) { 173 | setColorButtonsUnactive(); 174 | switch (code) { 175 | case 0: 176 | redButton.classList.add('active'); 177 | break; 178 | case 1: 179 | yellowButton.classList.add('active'); 180 | break; 181 | case 2: 182 | greenButton.classList.add('active'); 183 | break; 184 | case 3: 185 | blueButton.classList.add('active'); 186 | break; 187 | default: 188 | } 189 | hideAllOptions(); 190 | } 191 | 192 | function setOutputModifierVisibility(show) { 193 | if (show) { 194 | document.getElementById('output-modifier').style.display = 'block'; 195 | } else { 196 | document.getElementById('output-modifier').style.display = 'none'; 197 | } 198 | } 199 | 200 | function setClockModifierVisibility(show) { 201 | if (show) { 202 | document.getElementById('clock-modifier').style.display = 'block'; 203 | } else { 204 | document.getElementById('clock-modifier').style.display = 'none'; 205 | } 206 | } 207 | 208 | function setLabelModifierVisibility(show) { 209 | if (show) { 210 | document.getElementById('label-modifier').style.display = 'block'; 211 | } else { 212 | document.getElementById('label-modifier').style.display = 'none'; 213 | } 214 | } 215 | 216 | function hideElementMenus() { 217 | document.getElementById('output-modifier').style.display = 'none'; 218 | document.getElementById('clock-modifier').style.display = 'none'; 219 | document.getElementById('label-modifier').style.display = 'none'; 220 | } 221 | 222 | function elementMenuShown() { 223 | return (controlMode === 'modify' && (inputToModify + outputToModify + labelToModify >= -2)); 224 | } 225 | 226 | function setColorButtonsUnactive() { 227 | redButton.classList.remove('active'); 228 | yellowButton.classList.remove('active'); 229 | greenButton.classList.remove('active'); 230 | blueButton.classList.remove('active'); 231 | } -------------------------------------------------------------------------------- /libraries/stickUp.min.js: -------------------------------------------------------------------------------- 1 | // jshint ignore: start 2 | jQuery(function($){$(document).ready(function(){var contentButton = [];var contentTop = [];var content = [];var lastScrollTop = 0;var scrollDir = '';var itemClass = '';var itemHover = '';var menuSize = null;var stickyHeight = 0;var stickyMarginB = 0;var currentMarginT = 0;var topMargin = 0;$(window).scroll(function(event){var st = $(this).scrollTop();if (st > lastScrollTop){scrollDir = 'down';} else {scrollDir = 'up';}lastScrollTop = st;});$.fn.stickUp = function( options ) {$(this).addClass('stuckMenu');var objn = 0;if(options != null) {for(var o in options.parts) {if (options.parts.hasOwnProperty(o)){content[objn] = options.parts[objn];objn++;}}if(objn == 0) {console.log('error:needs arguments');}itemClass = options.itemClass;itemHover = options.itemHover;if(options.topMargin != null) {if(options.topMargin == 'auto') {topMargin = parseInt($('.stuckMenu').css('margin-top'));} else {if(isNaN(options.topMargin) && options.topMargin.search("px") > 0){topMargin = parseInt(options.topMargin.replace("px",""));} else if(!isNaN(parseInt(options.topMargin))) {topMargin = parseInt(options.topMargin);} else {console.log("incorrect argument, ignored.");topMargin = 0;} }} else {topMargin = 0;}menuSize = $('.'+itemClass).size();}stickyHeight = parseInt($(this).height());stickyMarginB = parseInt($(this).css('margin-bottom'));currentMarginT = parseInt($(this).next().closest('div').css('margin-top'));vartop = parseInt($(this).offset().top);};$(document).on('scroll', function() {varscroll = parseInt($(document).scrollTop());if(menuSize != null){for(var i=0;i < menuSize;i++){contentTop[i] = $('#'+content[i]+'').offset().top;function bottomView(i) {contentView = $('#'+content[i]+'').height()*.4;testView = contentTop[i] - contentView;if(varscroll > testView){$('.'+itemClass).removeClass(itemHover);$('.'+itemClass+':eq('+i+')').addClass(itemHover);} else if(varscroll < 50){$('.'+itemClass).removeClass(itemHover);$('.'+itemClass+':eq(0)').addClass(itemHover);}}if(scrollDir == 'down' && varscroll > contentTop[i]-50 && varscroll < contentTop[i]+50) {$('.'+itemClass).removeClass(itemHover);$('.'+itemClass+':eq('+i+')').addClass(itemHover);}if(scrollDir == 'up') {bottomView(i);}}}if(vartop < varscroll + topMargin){$('.stuckMenu').addClass('isStuck');$('.stuckMenu').next().closest('div').css({'margin-top': stickyHeight + stickyMarginB + currentMarginT + 'px'}, 10);$('.stuckMenu').css("position","fixed");$('.isStuck').css({top: '0px'}, 10, function(){});};if(varscroll + topMargin < vartop){$('.stuckMenu').removeClass('isStuck');$('.stuckMenu').next().closest('div').css({'margin-top': currentMarginT + 'px'}, 10);$('.stuckMenu').css("position","relative");};});});}); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "logijs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "site_scripts/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Simon Buchholz", 10 | "license": "gpl-3.0", 11 | "dependencies": { 12 | "base64url": "^3.0.1", 13 | "body-parser": "^1.19.0", 14 | "config": "^3.2.2", 15 | "cookie-parser": "^1.4.4", 16 | "crypto": "^1.0.1", 17 | "dot-prop": "^5.3.0", 18 | "email-validator": "^2.0.4", 19 | "express": "^4.17.1", 20 | "express-fileupload": "^1.1.9", 21 | "express-session": "^1.16.2", 22 | "fs": "0.0.1-security", 23 | "glob": "^7.1.4", 24 | "joi": "^14.3.1", 25 | "jsonwebtoken": "^8.5.1", 26 | "knex": "^0.19.5", 27 | "mysql": "^2.17.1", 28 | "nodemon": "^2.0.5", 29 | "password-validator": "^5.0.2", 30 | "pug": "^3.0.1", 31 | "sharp": "^0.23.0", 32 | "socket.io": "^2.4.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFswDQYJKoZIhvcNAQEBBQADSgAwRwJAfJ+DXfA7nCBIDcxpNbTBICYSvpLB7MZ3 3 | NqsoBuebNOoZQ8n1zdCJt5wCm4+uX7Ca3we1YXwnvPUsxYmFf14RQwIDAQAB 4 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /site_scripts/create_account.js: -------------------------------------------------------------------------------- 1 | const CreateUser = document.querySelector('.SignUp'); 2 | CreateUser.addEventListener('submit', (e) => { 3 | e.preventDefault(); 4 | const username = CreateUser.querySelector('.username').value; 5 | const email = CreateUser.querySelector('.email').value; 6 | const password = CreateUser.querySelector('.password').value; 7 | post('/createUser', { 8 | username: username, 9 | email: email, 10 | password: password 11 | }).then(function (data) { 12 | if (data.error_code === 0) { 13 | window.location = '/login?signup_success=true'; 14 | } else { 15 | window.location = '/signup?error_code=' + data.error_code; 16 | } 17 | }); 18 | }); 19 | 20 | function post(path, data) { 21 | return window.fetch(path, { 22 | method: 'POST', 23 | headers: { 24 | 'Accept': 'application/json', 25 | 'Content-Type': 'application/json' 26 | }, 27 | body: JSON.stringify(data) 28 | }) 29 | .then(function (res) { console.log(res.ok); return res.json(); }) 30 | .then(function (data) { return data; }); 31 | } 32 | 33 | const currentTheme = localStorage.getItem('theme'); 34 | 35 | if (currentTheme === 'dark') { 36 | document.documentElement.classList.toggle('dark-theme'); 37 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 38 | document.getElementById('mode-button').innerHTML = ''; 39 | } 40 | 41 | document.getElementById('mode-button').addEventListener('click', function () { 42 | let theme = 'light'; 43 | document.documentElement.classList.toggle('dark-theme'); 44 | if (document.documentElement.classList.contains('dark-theme')) { 45 | theme = 'dark'; 46 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 47 | document.getElementById('mode-button').innerHTML = ''; 48 | } else { 49 | theme = 'light'; 50 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 51 | document.getElementById('mode-button').innerHTML = ''; 52 | } 53 | localStorage.setItem('theme', theme); 54 | }); -------------------------------------------------------------------------------- /site_scripts/dashboard.js: -------------------------------------------------------------------------------- 1 | let confButton = ''; 2 | 3 | const Logout = document.querySelectorAll('.Logout'); 4 | for (const button of Logout) { 5 | button.addEventListener('click', (e) => { //jshint ignore:line 6 | e.preventDefault(); 7 | setCookie('access_token', '', -1); 8 | window.location = '/'; 9 | }); 10 | } 11 | 12 | const openButtons = document.querySelectorAll(".btn.open"); 13 | for (const button of openButtons) { 14 | button.addEventListener('click', function (event) { //jshint ignore:line 15 | window.location = '/editor?sketch=' + event.target.id; 16 | }); 17 | } 18 | 19 | const deleteButtons = document.querySelectorAll(".delete"); 20 | for (const button of deleteButtons) { 21 | button.addEventListener('click', function (event) { //jshint ignore:line 22 | if (confButton !== event.target.id) { 23 | button.innerHTML = ' SURE?'; 24 | confButton = event.target.id; 25 | } else { 26 | confButton = ''; 27 | post('/delete', { 28 | sketch: event.currentTarget.id 29 | }); 30 | location.reload(); 31 | } 32 | }); 33 | } 34 | 35 | const downloadButtons = document.querySelectorAll(".download"); 36 | for (const button of downloadButtons) { 37 | button.addEventListener('click', function (event) { //jshint ignore:line 38 | event.preventDefault(); 39 | window.location = '/download?file=' + event.currentTarget.id.substring(2); 40 | }); 41 | } 42 | 43 | function post(path, data) { 44 | return window.fetch(path, { 45 | method: 'POST', 46 | headers: { 47 | 'Accept': 'application/json', 48 | 'Content-Type': 'application/json' 49 | }, 50 | body: JSON.stringify(data) 51 | }); 52 | } 53 | 54 | function setCookie(name, value, days) { 55 | var d = new Date(); 56 | d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days); 57 | document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString(); 58 | 59 | } 60 | 61 | const currentTheme = localStorage.getItem('theme'); 62 | 63 | if (currentTheme === 'dark') { 64 | document.documentElement.classList.toggle('dark-theme'); 65 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 66 | document.getElementById('mode-button').innerHTML = ''; 67 | } 68 | 69 | document.getElementById('mode-button').addEventListener('click', function () { 70 | let theme = 'light'; 71 | document.documentElement.classList.toggle('dark-theme'); 72 | if (document.documentElement.classList.contains('dark-theme')) { 73 | theme = 'dark'; 74 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 75 | document.getElementById('mode-button').innerHTML = ''; 76 | } else { 77 | theme = 'light'; 78 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 79 | document.getElementById('mode-button').innerHTML = ''; 80 | } 81 | localStorage.setItem('theme', theme); 82 | }); 83 | -------------------------------------------------------------------------------- /site_scripts/eduSignup.js: -------------------------------------------------------------------------------- 1 | const CreateUser = document.querySelector('.SignUp'); 2 | CreateUser.addEventListener('submit', (e) => { 3 | e.preventDefault(); 4 | const username = CreateUser.querySelector('.username').value; 5 | const email = CreateUser.querySelector('.email').value; 6 | const password = CreateUser.querySelector('.password').value; 7 | post('/createUser', { 8 | username: username, 9 | email: email, 10 | password: password 11 | }).then(function (data) { 12 | if (data.error_code === 0) { 13 | window.location = '/?signup_success=true'; 14 | } else { 15 | window.location = '/signup?error_code=' + data.error_code; 16 | } 17 | }); 18 | }); 19 | 20 | function post(path, data) { 21 | return window.fetch(path, { 22 | method: 'POST', 23 | headers: { 24 | 'Accept': 'application/json', 25 | 'Content-Type': 'application/json' 26 | }, 27 | body: JSON.stringify(data) 28 | }) 29 | .then(function (res) { console.log(res.ok); return res.json(); }) 30 | .then(function (data) { return data; }); 31 | } 32 | 33 | const currentTheme = localStorage.getItem('theme'); 34 | 35 | if (currentTheme === 'dark') { 36 | document.documentElement.classList.toggle('dark-theme'); 37 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 38 | document.getElementById('mode-button').innerHTML = ''; 39 | } 40 | 41 | document.getElementById('mode-button').addEventListener('click', function () { 42 | let theme = 'light'; 43 | document.documentElement.classList.toggle('dark-theme'); 44 | if (document.documentElement.classList.contains('dark-theme')) { 45 | theme = 'dark'; 46 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 47 | document.getElementById('mode-button').innerHTML = ''; 48 | } else { 49 | theme = 'light'; 50 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 51 | document.getElementById('mode-button').innerHTML = ''; 52 | } 53 | localStorage.setItem('theme', theme); 54 | }); -------------------------------------------------------------------------------- /site_scripts/edu_tutorial.js: -------------------------------------------------------------------------------- 1 | const Logout = document.querySelectorAll('.Logout'); 2 | for (const button of Logout) { 3 | button.addEventListener('click', (e) => { //jshint ignore:line 4 | e.preventDefault(); 5 | setCookie('access_token', '', -1); 6 | window.location = '/'; 7 | }); 8 | } 9 | 10 | function setCookie(name, value, days) { 11 | var d = new Date(); 12 | d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days); 13 | document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString(); 14 | } 15 | 16 | window.onscroll = function () { scrollFunction(); }; 17 | function scrollFunction() { 18 | if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) { 19 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(0.6)"); 20 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "-20px"); 21 | document.getElementById("front_teaser").style.opacity = "0"; 22 | document.getElementById("main-carousel").style.opacity = "1"; 23 | } else { 24 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(1.0)"); 25 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "10px"); 26 | document.getElementById("front_teaser").style.opacity = "1"; 27 | document.getElementById("main-carousel").style.opacity = "0"; 28 | } 29 | } 30 | 31 | const currentTheme = localStorage.getItem('theme'); 32 | 33 | if (currentTheme === 'light') { 34 | document.documentElement.classList.toggle('dark-theme'); 35 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 36 | document.getElementById('mode-button').innerHTML = ''; 37 | } 38 | 39 | document.getElementById('mode-button').addEventListener('click', function () { 40 | let theme = 'light'; 41 | document.documentElement.classList.toggle('dark-theme'); 42 | if (document.documentElement.classList.contains('dark-theme')) { 43 | theme = 'dark'; 44 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 45 | document.getElementById('mode-button').innerHTML = ''; 46 | } else { 47 | theme = 'light'; 48 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 49 | document.getElementById('mode-button').innerHTML = ''; 50 | } 51 | localStorage.setItem('theme', theme); 52 | }); -------------------------------------------------------------------------------- /site_scripts/education.js: -------------------------------------------------------------------------------- 1 | window.onscroll = function () { scrollFunction(); }; 2 | function scrollFunction() { 3 | if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) { 4 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(0.6)"); 5 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "-20px"); 6 | } else { 7 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(1.0)"); 8 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "10px"); 9 | } 10 | } 11 | 12 | const Logout = document.querySelectorAll('.Logout'); 13 | for (const button of Logout) { 14 | button.addEventListener('click', (e) => { //jshint ignore:line 15 | e.preventDefault(); 16 | setCookie('access_token', '', -1); 17 | window.location = '/'; 18 | }); 19 | } 20 | 21 | let currentTheme = localStorage.getItem('theme'); 22 | 23 | if (currentTheme !== 'light') { 24 | currentTheme = 'dark'; 25 | localStorage.setItem('theme', currentTheme); 26 | } 27 | 28 | if (currentTheme === 'dark') { 29 | document.documentElement.classList.toggle('dark-theme'); 30 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 31 | document.getElementById('mode-button').innerHTML = ''; 32 | } 33 | 34 | document.getElementById('mode-button').addEventListener('click', function () { 35 | let theme = 'light'; 36 | document.documentElement.classList.toggle('dark-theme'); 37 | if (document.documentElement.classList.contains('dark-theme')) { 38 | theme = 'dark'; 39 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 40 | document.getElementById('mode-button').innerHTML = ''; 41 | } else { 42 | theme = 'light'; 43 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 44 | document.getElementById('mode-button').innerHTML = ''; 45 | } 46 | localStorage.setItem('theme', theme); 47 | }); 48 | 49 | function setCookie(name, value, days) { 50 | var d = new Date(); 51 | d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days); 52 | document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString(); 53 | } -------------------------------------------------------------------------------- /site_scripts/edulogin.js: -------------------------------------------------------------------------------- 1 | const Login = document.querySelector('.Login'); 2 | if (Login !== null) { 3 | Login.addEventListener('submit', (e) => { 4 | e.preventDefault(); 5 | const username = Login.querySelector('.username').value; 6 | const password = Login.querySelector('.password').value; 7 | post('/login', { username, password }) 8 | .then(function (response) { 9 | if (response.status === 200) { 10 | window.location = '/dashboard'; 11 | } else { 12 | window.location = '/?failed=true'; 13 | } 14 | }); 15 | }); 16 | } 17 | 18 | function post(path, data) { 19 | return window.fetch(path, { 20 | method: 'POST', 21 | headers: { 22 | 'Accept': 'application/json', 23 | 'Content-Type': 'application/json' 24 | }, 25 | body: JSON.stringify(data) 26 | }); 27 | } 28 | 29 | const currentTheme = localStorage.getItem('theme'); 30 | 31 | if (currentTheme === 'dark') { 32 | document.documentElement.classList.toggle('dark-theme'); 33 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 34 | document.getElementById('mode-button').innerHTML = ''; 35 | } 36 | 37 | document.getElementById('mode-button').addEventListener('click', function () { 38 | let theme = 'light'; 39 | document.documentElement.classList.toggle('dark-theme'); 40 | if (document.documentElement.classList.contains('dark-theme')) { 41 | theme = 'dark'; 42 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 43 | document.getElementById('mode-button').innerHTML = ''; 44 | } else { 45 | theme = 'light'; 46 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 47 | document.getElementById('mode-button').innerHTML = ''; 48 | } 49 | localStorage.setItem('theme', theme); 50 | }); -------------------------------------------------------------------------------- /site_scripts/getstarted.js: -------------------------------------------------------------------------------- 1 | const Logout = document.querySelectorAll('.Logout'); 2 | for (const button of Logout) { 3 | button.addEventListener('click', (e) => { //jshint ignore:line 4 | e.preventDefault(); 5 | setCookie('access_token', '', -1); 6 | window.location = '/'; 7 | }); 8 | } 9 | 10 | const currentTheme = localStorage.getItem('theme'); 11 | 12 | if (currentTheme === 'dark') { 13 | document.documentElement.classList.toggle('dark-theme'); 14 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 15 | document.getElementById('mode-button').innerHTML = ''; 16 | document.getElementById('getstarted_teaser').src = 'images/front_teaser.png'; 17 | } 18 | 19 | document.getElementById('mode-button').addEventListener('click', function () { 20 | let theme = 'light'; 21 | document.documentElement.classList.toggle('dark-theme'); 22 | if (document.documentElement.classList.contains('dark-theme')) { 23 | theme = 'dark'; 24 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 25 | document.getElementById('mode-button').innerHTML = ''; 26 | document.getElementById('getstarted_teaser').src = 'images/front_teaser.png'; 27 | } else { 28 | theme = 'light'; 29 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 30 | document.getElementById('mode-button').innerHTML = ''; 31 | document.getElementById('getstarted_teaser').src = 'images/front_teaser_white.png'; 32 | } 33 | localStorage.setItem('theme', theme); 34 | }); 35 | 36 | function setCookie(name, value, days) { 37 | var d = new Date(); 38 | d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days); 39 | document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString(); 40 | } -------------------------------------------------------------------------------- /site_scripts/index_page.js: -------------------------------------------------------------------------------- 1 | window.onscroll = function () { scrollFunction(); }; 2 | function scrollFunction() { 3 | if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) { 4 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(0.6)"); 5 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "-20px"); 6 | document.getElementById("front_teaser").style.opacity = "0"; 7 | document.getElementById("main-carousel").style.opacity = "1"; 8 | } else { 9 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(1.0)"); 10 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "10px"); 11 | document.getElementById("front_teaser").style.opacity = "1"; 12 | if (document.body.clientWidth >= 1024) { 13 | document.getElementById("main-carousel").style.opacity = "0"; 14 | } 15 | } 16 | } 17 | 18 | let button = document.getElementsByClassName("all-samples-button")[0]; 19 | button.addEventListener("click", function () { 20 | let coll = document.getElementsByClassName("collapsible")[0]; 21 | coll.classList.toggle("active"); 22 | if (coll.style.maxHeight) { 23 | coll.style.maxHeight = null; 24 | button.innerHTML = " Show All"; 25 | } else { 26 | coll.style.maxHeight = coll.scrollHeight + "px"; 27 | button.innerHTML = " Show Less"; 28 | } 29 | }); 30 | 31 | const Logout = document.querySelectorAll('.Logout'); 32 | for (const button of Logout) { 33 | button.addEventListener('click', (e) => { //jshint ignore:line 34 | e.preventDefault(); 35 | setCookie('access_token', '', -1); 36 | window.location = '/'; 37 | }); 38 | } 39 | 40 | let currentTheme = localStorage.getItem('theme'); 41 | 42 | if (currentTheme !== 'light') { 43 | currentTheme = 'dark'; 44 | localStorage.setItem('theme', currentTheme); 45 | } 46 | 47 | if (currentTheme === 'dark') { 48 | document.documentElement.classList.toggle('dark-theme'); 49 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 50 | document.getElementById('mode-button').innerHTML = ''; 51 | document.getElementById('front_teaser').src = 'images/front_teaser.png'; 52 | document.getElementById('carousel-1').src = 'images/carousel_1_new_dark.png'; 53 | document.getElementById('carousel-2').src = 'images/carousel_2_new_dark.png'; 54 | document.getElementById('carousel-3').src = 'images/carousel_3_new_dark.png'; 55 | } 56 | 57 | document.getElementById('mode-button').addEventListener('click', function () { 58 | let theme = 'light'; 59 | document.documentElement.classList.toggle('dark-theme'); 60 | if (document.documentElement.classList.contains('dark-theme')) { 61 | theme = 'dark'; 62 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 63 | document.getElementById('mode-button').innerHTML = ''; 64 | document.getElementById('front_teaser').src = 'images/front_teaser.png'; 65 | document.getElementById('carousel-1').src = 'images/carousel_1_new_dark.png'; 66 | document.getElementById('carousel-2').src = 'images/carousel_2_new_dark.png'; 67 | document.getElementById('carousel-3').src = 'images/carousel_3_new_dark.png'; 68 | } else { 69 | theme = 'light'; 70 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 71 | document.getElementById('mode-button').innerHTML = ''; 72 | document.getElementById('front_teaser').src = 'images/front_teaser_white.png'; 73 | document.getElementById('carousel-1').src = 'images/carousel_1_new.png'; 74 | document.getElementById('carousel-2').src = 'images/carousel_2_new.png'; 75 | document.getElementById('carousel-3').src = 'images/carousel_3_new.png'; 76 | } 77 | localStorage.setItem('theme', theme); 78 | }); 79 | 80 | function setCookie(name, value, days) { 81 | var d = new Date(); 82 | d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days); 83 | document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString(); 84 | } -------------------------------------------------------------------------------- /site_scripts/jwt_module.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const jwt = require('jsonwebtoken'); 3 | 4 | // use 'utf8' to get string instead of byte array (512 bit key) 5 | var privateKEY = fs.readFileSync('./private.key', 'utf8'); 6 | var publicKEY = fs.readFileSync('./public.key', 'utf8'); 7 | 8 | module.exports = { 9 | sign: (payload, $Options) => { 10 | /* 11 | sOptions = { 12 | issuer: "Authorization/Resource/This server", 13 | subject: "iam@user.me", 14 | audience: "Client_Identity" // this should be provided by client 15 | } 16 | */ 17 | var signOptions = { 18 | issuer: $Options.issuer, 19 | subject: $Options.subject, 20 | audience: $Options.audience, 21 | expiresIn: "30d", 22 | algorithm: "RS256" 23 | }; 24 | return jwt.sign(payload, privateKEY, signOptions); 25 | }, 26 | verify: (token, $Option) => { 27 | /* 28 | vOption = { 29 | issuer: "Authorization/Resource/This server", 30 | subject: "iam@user.me", 31 | audience: "Client_Identity" // this should be provided by client 32 | } 33 | */ 34 | var verifyOptions = { 35 | issuer: $Option.issuer, 36 | subject: $Option.subject, 37 | audience: $Option.audience, 38 | expiresIn: "30d", 39 | algorithm: ["RS256"] 40 | }; 41 | try { 42 | return jwt.verify(token, publicKEY, verifyOptions); 43 | } catch (err) { 44 | return false; 45 | } 46 | }, 47 | decode: (token) => { 48 | return jwt.decode(token, { complete: true }); 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /site_scripts/lib_front.js: -------------------------------------------------------------------------------- 1 | const downloadButtons = document.querySelectorAll(".btn.download"); 2 | for (const button of downloadButtons) { 3 | button.addEventListener('click', function (event) { //jshint ignore:line 4 | event.preventDefault(); 5 | window.location = '/libDownload?file=' + event.currentTarget.id.substring(2); 6 | }); 7 | } -------------------------------------------------------------------------------- /site_scripts/login.js: -------------------------------------------------------------------------------- 1 | const Login = document.querySelector('.Login'); 2 | Login.addEventListener('submit', (e) => { 3 | e.preventDefault(); 4 | const username = Login.querySelector('.username').value; 5 | const password = Login.querySelector('.password').value; 6 | post('/login', { username, password }) 7 | .then(function (response) { 8 | if (response.status === 200) { 9 | window.location = '/dashboard'; 10 | } else { 11 | window.location = '/login?failed=true'; 12 | } 13 | }); 14 | }); 15 | 16 | function post(path, data) { 17 | return window.fetch(path, { 18 | method: 'POST', 19 | headers: { 20 | 'Accept': 'application/json', 21 | 'Content-Type': 'application/json' 22 | }, 23 | body: JSON.stringify(data) 24 | }); 25 | } 26 | 27 | const currentTheme = localStorage.getItem('theme'); 28 | 29 | if (currentTheme === 'dark') { 30 | document.documentElement.classList.toggle('dark-theme'); 31 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 32 | document.getElementById('mode-button').innerHTML = ''; 33 | } 34 | 35 | document.getElementById('mode-button').addEventListener('click', function () { 36 | let theme = 'light'; 37 | document.documentElement.classList.toggle('dark-theme'); 38 | if (document.documentElement.classList.contains('dark-theme')) { 39 | theme = 'dark'; 40 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 41 | document.getElementById('mode-button').innerHTML = ''; 42 | } else { 43 | theme = 'light'; 44 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 45 | document.getElementById('mode-button').innerHTML = ''; 46 | } 47 | localStorage.setItem('theme', theme); 48 | }); -------------------------------------------------------------------------------- /site_scripts/migrations/20190916195158_create_user_table.js: -------------------------------------------------------------------------------- 1 | exports.up = function (knex) { 2 | return knex.schema.createTable('user', function (t) { 3 | t.increments('id').primary(); 4 | t.string('username').notNullable(); 5 | t.string('password').notNullable(); 6 | t.timestamps(false, false); 7 | }); 8 | }; 9 | 10 | exports.down = function (knex) { 11 | return knex.schema.dropTableIfExists('user'); 12 | }; -------------------------------------------------------------------------------- /site_scripts/migrations/20190916204924_encrypt_user_password.js: -------------------------------------------------------------------------------- 1 | const { saltHashPassword } = require('../store'); 2 | 3 | exports.up = function up(knex) { 4 | return knex.schema 5 | .table('user', t => { 6 | t.string('salt').notNullable(); 7 | t.string('encrypted_password').notNullable(); 8 | }) 9 | .then(() => knex('user')) 10 | .then(users => Promise.all(users.map(convertPassword))) 11 | .then(() => { 12 | return knex.schema.table('user', t => { 13 | t.dropColumn('password'); 14 | }); 15 | }); 16 | function convertPassword(user) { 17 | const { salt, hash } = saltHashPassword(user.password); 18 | return knex('user') 19 | .where({ id: user.id }) 20 | .update({ 21 | salt, 22 | encrypted_password: hash 23 | }); 24 | } 25 | }; 26 | 27 | exports.down = function down(knex) { 28 | return knex.schema.table('user', t => { 29 | t.dropColumn('salt'); 30 | t.dropColumn('encrypted_password'); 31 | t.string('password').notNullable(); 32 | }); 33 | }; -------------------------------------------------------------------------------- /site_scripts/store.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | const knex = require('knex')(require('./knexfile')); 3 | 4 | module.exports = { 5 | createUser({ username, email, password }) { 6 | console.log(`Add user ${username} with email ${email}`); 7 | const { salt, hash } = saltHashPassword({ password }); 8 | return knex('user').where({ username }) 9 | .then(([user]) => { 10 | if (user) { 11 | return { success: false, reason: 'username' }; 12 | } else { 13 | return knex('user').insert({ 14 | salt, 15 | encrypted_password: hash, 16 | username, 17 | email 18 | }).then(function () { 19 | console.log('Success'); 20 | return { success: true, reason: '' }; 21 | }); 22 | } 23 | }); 24 | }, 25 | authenticate({ username, password }) { 26 | console.log(`Authenticating user ${username}`); 27 | return knex('user').where({ username }) 28 | .then(([user]) => { 29 | if (!user || user.username !== username) { 30 | return { success: false }; 31 | } 32 | const { hash } = saltHashPassword({ 33 | password, 34 | salt: user.salt 35 | }); 36 | if (hash === user.encrypted_password) { 37 | return knex('user').where({ username }).update({ updated_at: knex.fn.now() }) 38 | .then(function () { return { success: hash === user.encrypted_password }; }); 39 | } 40 | return { success: false }; 41 | }); 42 | }, 43 | getEmail(user) { 44 | return knex('user').where({ 'username': user }).select('email') 45 | .then(data => { 46 | return data[0].email; 47 | }); 48 | } 49 | }; 50 | 51 | function saltHashPassword({ 52 | password, 53 | salt = randomString() 54 | }) { 55 | const hash = crypto 56 | .createHmac('sha512', salt) 57 | .update(password); 58 | return { 59 | salt, 60 | hash: hash.digest('hex') 61 | }; 62 | } 63 | 64 | function randomString() { 65 | return crypto.randomBytes(4).toString('hex'); 66 | } 67 | -------------------------------------------------------------------------------- /site_scripts/survicate.js: -------------------------------------------------------------------------------- 1 | // Start of Survicate (www.survicate.com) code 2 | if (window.location.href.includes('.com')) { 3 | console.log('Loading Survicate script'); 4 | (function (w) { 5 | var s = document.createElement('script'); 6 | s.src = 'https://survey.survicate.com/workspaces/01d22f9eb05bc4fcdd73eb6342cb3480/web_surveys.js'; 7 | s.async = true; 8 | var e = document.getElementsByTagName('script')[0]; 9 | e.parentNode.insertBefore(s, e); 10 | })(window); 11 | } 12 | // End of Survicate code -------------------------------------------------------------------------------- /site_scripts/tos_legal.js: -------------------------------------------------------------------------------- 1 | const Logout = document.querySelectorAll('.Logout'); 2 | for (const button of Logout) { 3 | button.addEventListener('click', (e) => { //jshint ignore:line 4 | e.preventDefault(); 5 | setCookie('access_token', '', -1); 6 | window.location = '/'; 7 | }); 8 | } 9 | 10 | function setCookie(name, value, days) { 11 | var d = new Date(); 12 | d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days); 13 | document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString(); 14 | } 15 | 16 | window.onscroll = function () { scrollFunction(); }; 17 | function scrollFunction() { 18 | if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) { 19 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(0.6)"); 20 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "-20px"); 21 | } else { 22 | document.getElementsByClassName("navbar-brand")[0].style.setProperty("transform", "scale(1.0)"); 23 | document.getElementsByClassName("navbar-header")[0].style.setProperty("top", "10px"); 24 | } 25 | } 26 | 27 | const currentTheme = localStorage.getItem('theme'); 28 | 29 | if (currentTheme === 'dark') { 30 | document.documentElement.classList.toggle('dark-theme'); 31 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 32 | document.getElementById('mode-button').innerHTML = ''; 33 | } 34 | 35 | document.getElementById('mode-button').addEventListener('click', function () { 36 | let theme = 'light'; 37 | document.documentElement.classList.toggle('dark-theme'); 38 | if (document.documentElement.classList.contains('dark-theme')) { 39 | theme = 'dark'; 40 | document.getElementById('top_logo').src = 'images/logo_index_new_white.png'; 41 | document.getElementById('mode-button').innerHTML = ''; 42 | } else { 43 | theme = 'light'; 44 | document.getElementById('top_logo').src = 'images/logo_index_new.png'; 45 | document.getElementById('mode-button').innerHTML = ''; 46 | } 47 | localStorage.setItem('theme', theme); 48 | }); -------------------------------------------------------------------------------- /site_scripts/user_data.js: -------------------------------------------------------------------------------- 1 | const glob = require('glob'); 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | 5 | module.exports = { 6 | getSketches: (user, callback) => { 7 | glob('./userSketches/' + user + '/*.json', { nodir: true }, function (err, files) { 8 | let sketches = []; 9 | let sketchSizes = []; 10 | let sketchBirthtimes = []; 11 | let sketchModified = []; 12 | let images = []; 13 | let descriptions = []; 14 | for (let i = 0; i < files.length; i++) { 15 | sketches.push(path.basename(files[i], '.json')); 16 | sketchSizes.push(getFilesize(files[i])); 17 | sketchBirthtimes.push(getBirthtime(files[i])); 18 | sketchModified.push(getModifiedDate(files[i])); 19 | if (fs.existsSync('./userSketches/' + user + '/' + path.basename(files[i], '.json') + '.png')) { 20 | images.push(fs.readFileSync('./userSketches/' + user + '/' + path.basename(files[i], '.json') + '.png')); 21 | images[i] = new Buffer(images[i], "binary").toString("base64"); 22 | } else { 23 | images.push(''); 24 | } 25 | if (fs.existsSync('./userSketches/' + user + '/' + path.basename(files[i], '.json') + '.txt')) { 26 | try { 27 | let description = fs.readFileSync('./userSketches/' + user + '/' + path.basename(files[i], '.json') + '.txt'); 28 | try { 29 | description = JSON.parse(description); 30 | if (description.hasOwnProperty('desc')) { 31 | if (description.desc !== '') { 32 | descriptions.push(description.desc); 33 | } else { 34 | descriptions.push('No description available.'); 35 | } 36 | } else { 37 | descriptions.push('No description available.'); 38 | } 39 | } catch (e) { 40 | descriptions.push(fs.readFileSync('./userSketches/' + user + '/' + path.basename(files[i], '.json') + '.txt')); 41 | } 42 | } catch (e) { 43 | 44 | } 45 | } else { 46 | descriptions.push('No description available.'); 47 | } 48 | } 49 | callback({ 50 | sketches: { 51 | sketches: sketches, 52 | sizes: sketchSizes, 53 | birthtimes: sketchBirthtimes, 54 | modified: sketchModified 55 | }, 56 | images: images, 57 | descriptions: descriptions 58 | }); 59 | }); 60 | } 61 | }; 62 | 63 | function getFilesize(filename) { 64 | const stats = fs.statSync(filename); 65 | return Math.round(stats.size / 1000); 66 | } 67 | 68 | function getBirthtime(filename) { 69 | const stats = fs.statSync(filename); 70 | let millis = stats.birthtimeMs; 71 | let newDate = new Date(millis); 72 | return newDate.toLocaleDateString("en-US") + ' ' + newDate.toLocaleTimeString("en-US"); 73 | } 74 | 75 | function getModifiedDate(filename) { 76 | const stats = fs.statSync(filename); 77 | let millis = stats.mtime; 78 | let newDate = new Date(millis); 79 | return newDate.toLocaleDateString("en-US") /*+ ' ' + newDate.toLocaleTimeString("de-DE")*/; 80 | } 81 | -------------------------------------------------------------------------------- /views/css/ArcaMajora3-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/css/ArcaMajora3-Bold.otf -------------------------------------------------------------------------------- /views/eduLogin.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | head 4 | | 5 | | 10 | | 11 | title LogiJS: #{organization} 12 | meta(name='keywords', content='LogiJS, logic, circuit, simulation, simulator, editor, free, open, source, gate, input, output, sketch, electronics, physics, informatics, it, \ 13 | computer, chip, pcb, design, creator, creation, processor, cpu, logi, js, javascript') 14 | meta(name='description', content='LogiJS is a web-based logic circuit simulator for educational use. Discover the world of logic circuits.') 15 | meta(charset='UTF-8') 16 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 17 | link(rel='shortcut icon', href='images/favi.png') 18 | style 19 | include css/bootstrap.css 20 | include css/index_style.css 21 | link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,300', rel='stylesheet', type='text/css') 22 | link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css') 23 | link(rel="stylesheet", type='text/css', href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css") 24 | script(src='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js') 25 | script. 26 | window.addEventListener("load", function () { 27 | window.cookieconsent.initialise({ 28 | "position": "bottom-right", 29 | "content": { 30 | "dismiss": "Allow Cookies" 31 | }, 32 | "palette": { 33 | "popup": { 34 | "background": "#323232", 35 | "text": "#fff", 36 | "link": "#c83232" 37 | }, 38 | "button": { 39 | "background": "#c83232", 40 | "text": "#ffffff" 41 | } 42 | } 43 | }) 44 | }); 45 | body 46 | | 47 | | 49 | | 50 | .edu-bg(style='background-image: url(\'' + background + '\');') 51 | .top-menu#top 52 | .container 53 | .navbar.navbar-default.navbar-fixed-top(role='navigation', style='background: none;') 54 | .container 55 | .navbar-header 56 | a.navbar-brand(href='#', style="transition: 0.2s;") 57 | img#top_logo(src='images/logo_index_new.png', alt='LogiJS logo', title='LogiJS', style='float: left;') 58 | if show_org_name 59 | div#logo-div(style="float: right; margin: 0; padding: 0; border-left: 5px solid #c83232; padding-left: 20px;") 60 | p#logo-text #{org_first_line} 61 | br 62 | | #{org_second_line} 63 | span(style="color: #c83232;") . 64 | .navbar-collapse.collapse 65 | ul.nav.navbar-nav.navbar-right 66 | li 67 | a.internal-link(rel='nofollow', href='#', target='_parent') #{localization.login} 68 | if show_registration 69 | li 70 | a.internal-link(rel='nofollow', href='/signup', target='_parent') #{localization.register} 71 | li 72 | a#mode-button.internal-link(rel='nofollow', href='javascript:;', target='_parent' title=localization.toggle_dark_mode) 73 | .slogan-container(style="margin-top: 150px;") 74 | h1.background-text #{background_text} 75 | .login_container 76 | form.Login.login-background 77 | if failed 78 | p.login-message #{localization.login_failed} 79 | span(style="color: #c83232;") . 80 | else if signup_success 81 | p.login-message #{localization.signup_successful} 82 | span(style="color: #c83232;") . 83 | else 84 | h1.login_title #{localization.login} 85 | span(style="color: #c83232;") . 86 | p 87 | input.username(type='text', placeholder=localization.username) 88 | br 89 | input.password(type='password', placeholder=localization.password) 90 | br 91 | input.btn.btn-lg.btn-orange.login-confirm-button(type='submit', value=localization.login, role='button') 92 | p.login-redirect-text 93 | if allow_enter 94 | a.login-redirect-text(href='/editor') #{localization.continue_without_login} 95 | br 96 | .footer_bottom.footer_bottom_absolute 97 | .footer_bottom_content 98 | .footer_box.footer_box_outer 99 | if refer_to_logijs_com 100 | a(rel='nofollow', href='https://logijs.com/', target='_blank') #{localization.switch_to_logijs_com} 101 | .footer_box.footer_box_inner 102 | .footer_box.footer_box_outer.footer_right 103 | if made_in_luebeck 104 | p(style="text-align: right;") Made with in Lübeck 105 | span(style="color: #c83232;") . 106 | script 107 | include ../libraries/jquery.min.js 108 | include ../libraries/bootstrap.min.js 109 | include ../site_scripts/edulogin.js 110 | 111 | -------------------------------------------------------------------------------- /views/eduSignup.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | head 4 | | 5 | | 10 | | 11 | title LogiJS: #{organization} 12 | meta(name='keywords', content='LogiJS, logic, circuit, simulation, simulator, editor, free, open, source, gate, input, output, sketch, electronics, physics, informatics, it, \ 13 | computer, chip, pcb, design, creator, creation, processor, cpu, logi, js, javascript') 14 | meta(name='description', content='LogiJS is a web-based logic circuit simulator for educational use. Discover the world of logic circuits.') 15 | meta(charset='UTF-8') 16 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 17 | link(rel='shortcut icon', href='images/favi.png') 18 | style 19 | include css/bootstrap.css 20 | include css/index_style.css 21 | link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,300', rel='stylesheet', type='text/css') 22 | link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css') 23 | link(rel="stylesheet", type='text/css', href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css") 24 | script(src='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js') 25 | script. 26 | window.addEventListener("load", function () { 27 | window.cookieconsent.initialise({ 28 | "position": "bottom-right", 29 | "content": { 30 | "dismiss": "Allow Cookies" 31 | }, 32 | "palette": { 33 | "popup": { 34 | "background": "#323232", 35 | "text": "#fff", 36 | "link": "#c83232" 37 | }, 38 | "button": { 39 | "background": "#c83232", 40 | "text": "#ffffff" 41 | } 42 | } 43 | }) 44 | }); 45 | body 46 | | 47 | | 49 | | 50 | .edu-bg(style='background-image: url(\'' + background + '\');') 51 | .top-menu#top 52 | .container 53 | .navbar.navbar-default.navbar-fixed-top(role='navigation', style='background: none;') 54 | .container 55 | .navbar-header 56 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 57 | span.sr-only Toggle navigation 58 | span.icon-bar 59 | span.icon-bar 60 | span.icon-bar 61 | a.navbar-brand(href='/', style="transition: 0.2s;") 62 | img#top_logo(src='images/logo_index_new.png', alt='LogiJS logo', title='LogiJS', style='float: left;') 63 | if show_org_name 64 | div#logo-div(style="float: right; margin: 0; padding: 0; border-left: 5px solid #c83232; padding-left: 20px;") 65 | p#logo-text(style="font-size: 45px; margin-top: 10px; line-height: 1.1; transition: 0.2s; letter-spacing: 2px;") #{org_first_line} 66 | br 67 | | #{org_second_line} 68 | span(style="color: #c83232;") . 69 | .navbar-collapse.collapse 70 | ul.nav.navbar-nav.navbar-right 71 | li 72 | a.internal-link(rel='nofollow', href='/', target='_parent') #{localization.login} 73 | li 74 | a.internal-link(rel='nofollow', href='#', target='_parent') #{localization.register} 75 | li 76 | a#mode-button.internal-link(rel='nofollow', href='javascript:;', target='_parent' title=localization.toggle_dark_mode) 77 | .slogan-container(style="margin-top: 150px;") 78 | h1.background-text #{background_text} 79 | .login_container 80 | - var error = parseInt(error_code); 81 | form.SignUp.login-background 82 | case error 83 | when 1: p.login-message #{localization.username_invalid} 84 | span(style="color: #c83232;") . 85 | when 2: p.login-message #{localization.email_invalid} 86 | span(style="color: #c83232;") . 87 | when 3 88 | p.login-message #{localization.password_invalid} 89 | span(style="color: #c83232;") . 90 | p.login-message.password-tipps #{localization.password_rules} 91 | span(style="color: #c83232;") . 92 | when 4: p.login-message #{localization.username_taken} 93 | span(style="color: #c83232;") . 94 | default: h1.login_title #{localization.register} 95 | span(style="color: #c83232;") . 96 | p 97 | input.username(type='text', placeholder=localization.username) 98 | br 99 | input.email(type='text', placeholder=localization.email) 100 | br 101 | input.password(type='password', placeholder=localization.password) 102 | br 103 | input.btn.btn-lg.btn-orange.login-confirm-button(type='submit', value=localization.register, role='button') 104 | p.login-redirect-text 105 | | #{localization.already_signed_up} 106 | a.login-redirect-text(href='/') #{localization.login} 107 | br 108 | .footer_bottom.footer_bottom_absolute 109 | .footer_bottom_content 110 | .footer_box.footer_box_outer 111 | if refer_to_logijs_com 112 | a(rel='nofollow', href='https://logijs.com/', target='_blank') #{localization.switch_to_logijs_com} 113 | .footer_box.footer_box_inner 114 | .footer_box.footer_box_outer.footer_right 115 | if made_in_luebeck 116 | p(style="text-align: right;") Made with in Lübeck 117 | span(style="color: #c83232;") . 118 | script 119 | include ../libraries/jquery.min.js 120 | include ../libraries/bootstrap.min.js 121 | include ../site_scripts/eduSignup.js 122 | 123 | -------------------------------------------------------------------------------- /views/getstarted.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | head 4 | | 5 | | 10 | | 11 | title LogiJS: Get Started 12 | meta(name='keywords', content='LogiJS, logic, circuit, simulation, simulator, editor, free, open, source, gate, input, output, sketch, electronics, physics, informatics, it, \ 13 | computer, chip, pcb, design, creator, creation, processor, cpu, logi, js, javascript') 14 | meta(name='description', content='LogiJS is a web-based logic circuit simulator for educational use. Discover the world of logic circuits.') 15 | meta(charset='UTF-8') 16 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 17 | link(rel='shortcut icon', href='images/favi.png') 18 | link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,300', rel='stylesheet', type='text/css') 19 | style 20 | include css/bootstrap.css 21 | include css/index_style.css 22 | link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css') 23 | link(rel="stylesheet", type='text/css', href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css") 24 | script(src='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js') 25 | script. 26 | window.addEventListener("load", function () { 27 | window.cookieconsent.initialise({ 28 | "position": "bottom-right", 29 | "content": { 30 | "dismiss": "Allow Cookies" 31 | }, 32 | "palette": { 33 | "popup": { 34 | "background": "#323232", 35 | "text": "#fff", 36 | "link": "#c83232" 37 | }, 38 | "button": { 39 | "background": "#c83232", 40 | "text": "#ffffff" 41 | } 42 | } 43 | }) 44 | }); 45 | body 46 | | 47 | | 49 | | 50 | .top-menu#top 51 | .container 52 | .navbar.navbar-default.navbar-fixed-top(role='navigation') 53 | .container 54 | ul.nav.navbar-nav.navbar-left 55 | li 56 | a.internal-link(rel='nofollow', href='/#features', target='_parent') Features 57 | li 58 | a.internal-link(rel='nofollow', href='/#samples', target='_parent') Samples 59 | li 60 | a.internal-link(rel='nofollow', href='/#about', target='_parent') About 61 | .navbar-header 62 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 63 | span.sr-only Toggle navigation 64 | span.icon-bar 65 | span.icon-bar 66 | span.icon-bar 67 | a.navbar-brand(href='/') 68 | img#top_logo(src='images/logo_index_new.png', alt='LogiJS logo', title='LogiJS') 69 | .navbar-collapse.collapse 70 | ul.nav.navbar-nav.navbar-right 71 | if user !== '' 72 | li 73 | a.user-button.internal-link(rel='nofollow', href='/dashboard', target='_parent') #{user} 74 | li 75 | a.Logout.internal-link(rel='nofollow', href='#', target='_parent') Logout 76 | else 77 | li 78 | a.login-button.internal-link(rel='nofollow', href='/login', target='_parent') Login 79 | li 80 | a.internal-link(rel='nofollow', href='/signup', target='_parent') Register 81 | li 82 | a#mode-button.internal-link(rel='nofollow', href='javascript:;', target='_parent' title='Toggle Dark Mode') 83 | .getstarted-container 84 | h1.background-text(style='top: 90px; left: -300px;') Discover the world 85 | h1.getstarted-title 86 | | Welcome to LogiJS 87 | span.red . 88 | h2.getstarted-subtitle 89 | | Let us show you around or just start with a blank sketch 90 | span.red . 91 | a.btn.btn-lg.btn-orange(href='/editor', rel="nofollow", role='button') 92 | New Sketch 93 | a.btn.btn-lg.btn-orange(href='/editor?tour=true&?sketch=library__5tour', rel="nofollow", role='button') 94 | Start the Tour 95 | .red_square(style="position: absolute; top: 0; right: max(17vw, 320px); height: 20vw; background: #c83232; width: 20vw; z-index: 10000;") 96 | .grey_square 97 | img#getstarted_teaser(src='images/front_teaser_white.png', alt='LogiJS Editor', title='LogiJS Editor') 98 | 99 | .footer_bottom.footer_bottom_absolute 100 | .footer_bottom_content 101 | .footer_box 102 | a.internal-link(rel='nofollow', href='/terms-of-service', target='_parent') Terms of Service 103 | a.internal-link(rel='nofollow', href='/legal', target='_parent') Legal Notice 104 | .footer_box 105 | p(style="text-align: center; display: inline-block; width: 100%;") 106 | a(href='https://twitter.com/logi_js', target='_blank', style="margin-right: 5px;") 107 | img(src="images/twitter.png" style="width: 40px; margin-top: -20px;") 108 | a(href='https://github.com/SimonBuxx/logijs', target='_blank', style="margin-left: 5px;") 109 | img(src="images/github_dark.png" style="width: 40px; margin-top: -20px;") 110 | .footer_box 111 | p(style="text-align: right;") Made with in Lübeck 112 | span.red . 113 | script 114 | include ../libraries/jquery.min.js 115 | include ../libraries/bootstrap.min.js 116 | include ../site_scripts/getstarted.js 117 | script. 118 | if (window.innerHeight > 800) { 119 | document.getElementById("top_logo").style.width = "350px"; 120 | } else { 121 | document.getElementById("top_logo").style.width = "200px"; 122 | } -------------------------------------------------------------------------------- /views/images/alt_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/alt_logo.png -------------------------------------------------------------------------------- /views/images/alt_logo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/alt_logo_dark.png -------------------------------------------------------------------------------- /views/images/alt_logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/alt_logo_small.png -------------------------------------------------------------------------------- /views/images/and-gate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/and-gate.png -------------------------------------------------------------------------------- /views/images/buffer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/buffer.png -------------------------------------------------------------------------------- /views/images/businput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/businput.png -------------------------------------------------------------------------------- /views/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/button.png -------------------------------------------------------------------------------- /views/images/carousel_1_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/carousel_1_new.png -------------------------------------------------------------------------------- /views/images/carousel_1_new_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/carousel_1_new_dark.png -------------------------------------------------------------------------------- /views/images/carousel_2_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/carousel_2_new.png -------------------------------------------------------------------------------- /views/images/carousel_2_new_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/carousel_2_new_dark.png -------------------------------------------------------------------------------- /views/images/carousel_3_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/carousel_3_new.png -------------------------------------------------------------------------------- /views/images/carousel_3_new_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/carousel_3_new_dark.png -------------------------------------------------------------------------------- /views/images/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/clock.png -------------------------------------------------------------------------------- /views/images/counter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/counter.png -------------------------------------------------------------------------------- /views/images/custom_frontpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/custom_frontpage.png -------------------------------------------------------------------------------- /views/images/d-flipflop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/d-flipflop.png -------------------------------------------------------------------------------- /views/images/decoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/decoder.png -------------------------------------------------------------------------------- /views/images/demux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/demux.png -------------------------------------------------------------------------------- /views/images/favi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/favi.png -------------------------------------------------------------------------------- /views/images/front_teaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/front_teaser.png -------------------------------------------------------------------------------- /views/images/front_teaser_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/front_teaser_white.png -------------------------------------------------------------------------------- /views/images/fulladd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/fulladd.png -------------------------------------------------------------------------------- /views/images/fulladd_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/fulladd_old.png -------------------------------------------------------------------------------- /views/images/github_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/github_dark.png -------------------------------------------------------------------------------- /views/images/halfadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/halfadd.png -------------------------------------------------------------------------------- /views/images/jk-flipflop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/jk-flipflop.png -------------------------------------------------------------------------------- /views/images/label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/label.png -------------------------------------------------------------------------------- /views/images/label_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/label_white.png -------------------------------------------------------------------------------- /views/images/logo_index_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/logo_index_new.png -------------------------------------------------------------------------------- /views/images/logo_index_new_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/logo_index_new_white.png -------------------------------------------------------------------------------- /views/images/mux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/mux.png -------------------------------------------------------------------------------- /views/images/not-gate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/not-gate.png -------------------------------------------------------------------------------- /views/images/or-gate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/or-gate.png -------------------------------------------------------------------------------- /views/images/output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/output.png -------------------------------------------------------------------------------- /views/images/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/register.png -------------------------------------------------------------------------------- /views/images/rs-clocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/rs-clocked.png -------------------------------------------------------------------------------- /views/images/rs-flipflop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/rs-flipflop.png -------------------------------------------------------------------------------- /views/images/segments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/segments.png -------------------------------------------------------------------------------- /views/images/switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/switch.png -------------------------------------------------------------------------------- /views/images/t-flipflop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/t-flipflop.png -------------------------------------------------------------------------------- /views/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/twitter.png -------------------------------------------------------------------------------- /views/images/uni-hl-demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/uni-hl-demo.jpg -------------------------------------------------------------------------------- /views/images/unwrapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/unwrapper.png -------------------------------------------------------------------------------- /views/images/wrapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/wrapper.png -------------------------------------------------------------------------------- /views/images/xor-gate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/images/xor-gate.png -------------------------------------------------------------------------------- /views/librarySketches/library__0gates.json: -------------------------------------------------------------------------------- 1 | {"caption":"Gates","gates":[{"x":"510","y":"210","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"510","y":"360","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"or\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"510","y":"510","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"xor\"","outputsInv":"[false]","inputsInv":"[false,false]"}],"outputs":[{"x":"630","y":"240","colr":"0"},{"x":"630","y":"390","colr":"0"},{"x":"630","y":"540","colr":"0"}],"inputs":[{"x":"405","y":"165","framecount":"-1","clock":"false"},{"x":"465","y":"165","framecount":"-1","clock":"false"}],"wires":[{"x1":"420","y1":"240","x2":"510"},{"x1":"420","y1":"390","x2":"510"},{"x1":"420","y1":"540","x2":"510"},{"x1":"480","y1":"570","x2":"510"},{"x1":"480","y1":"180","y2":"570"},{"x1":"480","y1":"270","x2":"510"},{"x1":"480","y1":"420","x2":"510"},{"x1":"420","y1":"180","y2":"540"},{"x1":"570","y1":"540","x2":"630"},{"x1":"570","y1":"390","x2":"630"},{"x1":"570","y1":"240","x2":"630"}],"conpoints":[{"x":"480","y":"270"},{"x":"480","y":"420"},{"x":"420","y":"240"},{"x":"420","y":"390"}],"diodes":[],"customs":[],"labels":[{"x":"720","y":"240","txt":"AND"},{"x":"720","y":"390","txt":"OR"},{"x":"720","y":"540","txt":"XOR"},{"x":"420","y":"60","txt":"This sketch demonstrates the three basic logic gates,\nas well as input and output elements.\nClick on \"Start\" to start the simulation."}],"segDisplays":[]} -------------------------------------------------------------------------------- /views/librarySketches/library__0gates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__0gates.png -------------------------------------------------------------------------------- /views/librarySketches/library__0gates.txt: -------------------------------------------------------------------------------- 1 | {"tops":[],"inputLabels":["",""],"outputLabels":["","",""],"caption":"Basic Gates","inputs":2,"outputs":3,"desc":"This sketch demonstrates the three basic logic gates, AND, OR and XOR. It also shows the usage of input and output elements. Logic gates are the fundamentals of every logic circuit."} -------------------------------------------------------------------------------- /views/librarySketches/library__0gates_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__0gates_frame.png -------------------------------------------------------------------------------- /views/librarySketches/library__1halfadder.json: -------------------------------------------------------------------------------- 1 | {"caption":"Half Adder","gates":[{"x":"210","y":"90","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"210","y":"210","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"xor\"","outputsInv":"[false]","inputsInv":"[false,false]"}],"outputs":[{"x":"390","y":"120","colr":"0"},{"x":"390","y":"240","colr":"0"},{"x":"390","y":"420","colr":"0"},{"x":"390","y":"450","colr":"0"}],"inputs":[{"x":"75","y":"105","framecount":"-1","clock":"false"},{"x":"75","y":"135","framecount":"-1","clock":"false"},{"x":"75","y":"405","framecount":"-1","clock":"false"},{"x":"75","y":"435","framecount":"-1","clock":"false"}],"wires":[{"x1":"90","y1":"120","x2":"210"},{"x1":"180","y1":"240","x2":"210"},{"x1":"180","y1":"120","y2":"240"},{"x1":"90","y1":"150","x2":"210"},{"x1":"150","y1":"270","x2":"210"},{"x1":"150","y1":"150","y2":"270"},{"x1":"270","y1":"240","x2":"390"},{"x1":"270","y1":"120","x2":"390"},{"x1":"90","y1":"420","x2":"210"},{"x1":"90","y1":"450","x2":"210"},{"x1":"270","y1":"420","x2":"390"},{"x1":"270","y1":"450","x2":"390"}],"conpoints":[{"x":"180","y":"120"},{"x":"150","y":"150"}],"diodes":[],"customs":[{"x":"210","y":"390","direction":"0","filename":"\"half_add.json\"","outputsInv":"[]","inputsInv":"[]"}],"labels":[{"x":"450","y":"120","txt":"Carry bit"},{"x":"450","y":"240","txt":"Sum"},{"x":"90","y":"60","txt":"Half adder, adds two single binary digits"},{"x":"90","y":"360","txt":"Half adder as a pre-built element"},{"x":"450","y":"420","txt":"Carry bit"},{"x":"450","y":"450","txt":"Sum"}],"segDisplays":[]} -------------------------------------------------------------------------------- /views/librarySketches/library__1halfadder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__1halfadder.png -------------------------------------------------------------------------------- /views/librarySketches/library__1halfadder.txt: -------------------------------------------------------------------------------- 1 | {"tops":[],"inputLabels":["","","",""],"outputLabels":["","","",""],"caption":"Half Adder","inputs":4,"outputs":4,"desc":"This sketch implements a half adder that is used to add two single binary digits. Half adders can be combined to form full adders, used to add binary numbers."} -------------------------------------------------------------------------------- /views/librarySketches/library__1halfadder_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__1halfadder_frame.png -------------------------------------------------------------------------------- /views/librarySketches/library__2fulladder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__2fulladder.png -------------------------------------------------------------------------------- /views/librarySketches/library__2fulladder.txt: -------------------------------------------------------------------------------- 1 | {"tops":[],"inputLabels":["","","","","","","","",""],"outputLabels":["","","","","",""],"caption":"Full Adder","inputs":9,"outputs":6,"desc":"This sketch implements a full adder that is used to add two single binary digits. Full adders constist of two half adders, taking two binary digits and a carry bit as inputs. Full adders can be combined to build integer adders of any size."} -------------------------------------------------------------------------------- /views/librarySketches/library__2fulladder_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__2fulladder_frame.png -------------------------------------------------------------------------------- /views/librarySketches/library__3traffic.json: -------------------------------------------------------------------------------- 1 | {"caption":"Traffic","gates":[],"outputs":[{"x":"990","y":"120","colr":"0"},{"x":"990","y":"150","colr":"1"},{"x":"990","y":"180","colr":"2"},{"x":"990","y":"300","colr":"0"},{"x":"990","y":"330","colr":"2"}],"inputs":[{"x":"165","y":"135","framecount":"0","clock":"true","speed":"30","lbl":">"}],"wires":[{"x1":"300","y1":"150","x2":"330"},{"x1":"300","y1":"180","x2":"330"},{"x1":"960","y1":"300","x2":"990"},{"x1":"180","y1":"150","x2":"240"},{"x1":"930","y1":"330","y2":"390"},{"x1":"930","y1":"330","x2":"990"},{"x1":"870","y1":"180","y2":"300"},{"x1":"870","y1":"180","x2":"990"},{"x1":"960","y1":"300","y2":"420"},{"x1":"510","y1":"120","y2":"300"},{"x1":"480","y1":"120","y2":"330"},{"x1":"450","y1":"120","y2":"360"},{"x1":"810","y1":"120","x2":"990"},{"x1":"810","y1":"120","y2":"360"},{"x1":"840","y1":"150","y2":"330"},{"x1":"840","y1":"150","x2":"990"},{"x1":"390","y1":"150","x2":"660"},{"x1":"390","y1":"180","x2":"660"},{"x1":"390","y1":"210","x2":"660"},{"x1":"390","y1":"240","x2":"660"},{"x1":"630","y1":"120","y2":"390"},{"x1":"600","y1":"120","y2":"420"},{"x1":"450","y1":"360","x2":"810"},{"x1":"480","y1":"330","x2":"840"},{"x1":"510","y1":"300","x2":"870"},{"x1":"630","y1":"390","x2":"930"},{"x1":"600","y1":"420","x2":"960"}],"conpoints":[],"diodes":[{"x":"450","y":"150"},{"x":"630","y":"150"},{"x":"450","y":"180"},{"x":"480","y":"180"},{"x":"600","y":"180"},{"x":"510","y":"210"},{"x":"600","y":"210"},{"x":"480","y":"240"},{"x":"600","y":"240"}],"customs":[{"x":"330","y":"120","direction":"0","filename":"\"2-decoder.json\"","outputsInv":"[false,false,false,false]","inputsInv":"[false,false]"},{"x":"240","y":"120","direction":"0","filename":"\"2-counter.json\"","outputsInv":"[false,false]","inputsInv":"[false]"}],"labels":[{"x":"60","y":"60","txt":"This sketch simulates a traffic light\nusing a diode matrix"},{"x":"1050","y":"120","txt":"Road traffic"},{"x":"1050","y":"300","txt":"Pedestrians"},{"x":"60","y":"150","txt":"Clock"}],"segDisplays":[]} -------------------------------------------------------------------------------- /views/librarySketches/library__3traffic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__3traffic.png -------------------------------------------------------------------------------- /views/librarySketches/library__3traffic.txt: -------------------------------------------------------------------------------- 1 | {"tops":[],"inputLabels":[">"],"outputLabels":["","","","",""],"caption":"Traffic Lights","inputs":1,"outputs":5,"desc":"This sketch simulates traffic lights using a 4-bit counter (see example #5) and a diode matrix. There are lights for road traffic and for crossing pedestrians. This example shows the usage of diodes, elements that connect wires in one direction only. They are especially helpful for building control units that can be programmed by setting diodes in a matrix. That way, instructions can be fetched and executed successively."} -------------------------------------------------------------------------------- /views/librarySketches/library__3traffic_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__3traffic_frame.png -------------------------------------------------------------------------------- /views/librarySketches/library__44BitCounter.json: -------------------------------------------------------------------------------- 1 | {"caption":"Counter","gates":[{"x":"750","y":"270","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"xor\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"1020","y":"300","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"1380","y":"300","direction":"0","inputCount":"3","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false,false]"},{"x":"1470","y":"270","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"xor\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"1110","y":"270","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"xor\"","outputsInv":"[false]","inputsInv":"[false,false]"}],"outputs":[{"x":"1710","y":"150","colr":"0"},{"x":"1320","y":"150","colr":"0"},{"x":"960","y":"150","colr":"0"},{"x":"690","y":"150","colr":"0"}],"inputs":[{"x":"495","y":"405","lbl":">","framecount":"0","clock":"true","speed":"30"}],"wires":[{"x1":"660","y1":"360","x2":"690"},{"x1":"570","y1":"300","y2":"330"},{"x1":"570","y1":"330","x2":"600"},{"x1":"1560","y1":"360","x2":"1590"},{"x1":"840","y1":"360","x2":"870"},{"x1":"570","y1":"360","x2":"600"},{"x1":"1200","y1":"360","x2":"1230"},{"x1":"810","y1":"300","x2":"840"},{"x1":"840","y1":"300","y2":"330"},{"x1":"840","y1":"330","x2":"870"},{"x1":"930","y1":"330","x2":"960"},{"x1":"720","y1":"300","x2":"750"},{"x1":"1350","y1":"330","x2":"1380"},{"x1":"1350","y1":"390","x2":"1380"},{"x1":"1080","y1":"270","y2":"300"},{"x1":"1080","y1":"300","x2":"1110"},{"x1":"1080","y1":"330","x2":"1110"},{"x1":"990","y1":"330","x2":"1020"},{"x1":"1170","y1":"300","x2":"1200"},{"x1":"1200","y1":"300","y2":"330"},{"x1":"1200","y1":"330","x2":"1230"},{"x1":"1290","y1":"330","x2":"1320"},{"x1":"1440","y1":"270","y2":"300"},{"x1":"1440","y1":"300","x2":"1470"},{"x1":"1440","y1":"330","x2":"1470"},{"x1":"1530","y1":"300","x2":"1560"},{"x1":"1560","y1":"300","y2":"330"},{"x1":"1560","y1":"330","x2":"1590"},{"x1":"1560","y1":"360","y2":"420"},{"x1":"840","y1":"360","y2":"420"},{"x1":"570","y1":"360","y2":"420"},{"x1":"1200","y1":"360","y2":"420"},{"x1":"960","y1":"360","x2":"1020"},{"x1":"1350","y1":"390","y2":"450"},{"x1":"1320","y1":"360","x2":"1380"},{"x1":"1650","y1":"330","x2":"1710"},{"x1":"1680","y1":"270","y2":"330"},{"x1":"690","y1":"300","y2":"360"},{"x1":"720","y1":"330","y2":"390"},{"x1":"660","y1":"330","x2":"750"},{"x1":"570","y1":"300","x2":"690"},{"x1":"720","y1":"210","y2":"300"},{"x1":"1350","y1":"210","y2":"330"},{"x1":"690","y1":"150","y2":"270"},{"x1":"540","y1":"270","y2":"390"},{"x1":"960","y1":"150","y2":"360"},{"x1":"1320","y1":"150","y2":"360"},{"x1":"1080","y1":"270","x2":"1320"},{"x1":"990","y1":"180","y2":"330"},{"x1":"540","y1":"270","x2":"690"},{"x1":"1710","y1":"150","y2":"330"},{"x1":"1440","y1":"270","x2":"1680"},{"x1":"540","y1":"390","x2":"720"},{"x1":"1740","y1":"180","y2":"450"},{"x1":"1350","y1":"450","x2":"1740"},{"x1":"720","y1":"210","x2":"1350"},{"x1":"510","y1":"420","x2":"1560"},{"x1":"690","y1":"180","x2":"1740"}],"conpoints":[{"x":"840","y":"420"},{"x":"570","y":"420"},{"x":"1200","y":"420"},{"x":"960","y":"330"},{"x":"960","y":"210"},{"x":"1320","y":"270"},{"x":"990","y":"180"},{"x":"690","y":"180"},{"x":"1320","y":"330"},{"x":"1680","y":"330"},{"x":"720","y":"330"}],"diodes":[],"customs":[{"x":"600","y":"300","direction":"0","filename":"\"d-flipflop.json\"","outputsInv":"[false,false,false,false,false,false]","inputsInv":"[false,false,false,false,false,false]"},{"x":"870","y":"300","direction":"0","filename":"\"d-flipflop.json\"","outputsInv":"[false,false,false,false,false,false]","inputsInv":"[false,false,false,false,false,false]"},{"x":"1230","y":"300","direction":"0","filename":"\"d-flipflop.json\"","outputsInv":"[false,false,false,false,false,false,false,false]","inputsInv":"[false,false,false,false,false,false,false,false]"},{"x":"1590","y":"300","direction":"0","filename":"\"d-flipflop.json\"","outputsInv":"[false,false,false,false,false,false]","inputsInv":"[false,false,false,false,false,false]"}],"labels":[{"x":"390","y":"420","txt":"Clock"},{"x":"690","y":"90","txt":"LSB (least significant bit)"},{"x":"1710","y":"90","txt":"MSB (most significant bit)"}],"segDisplays":[]} -------------------------------------------------------------------------------- /views/librarySketches/library__44BitCounter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__44BitCounter.png -------------------------------------------------------------------------------- /views/librarySketches/library__44BitCounter.txt: -------------------------------------------------------------------------------- 1 | {"tops":[],"inputLabels":[">"],"outputLabels":["","","",""],"caption":"4-Bit Counter","inputs":1,"outputs":4,"desc":"This sketch implements a simple counter made using D gates. It is connected to a clock, permanently increasing the binary output value. When the value passes the biggest possible value (fifteen in this case), the counter restarts from zero."} -------------------------------------------------------------------------------- /views/librarySketches/library__44BitCounter_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__44BitCounter_frame.png -------------------------------------------------------------------------------- /views/librarySketches/library__5tour.json: -------------------------------------------------------------------------------- 1 | {"caption":"Tour","gates":[{"x":"210","y":"210","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"210","y":"360","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"or\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"210","y":"510","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"xor\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"1380","y":"240","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"or\"","outputsInv":"[true]","inputsInv":"[false,false]"},{"x":"1380","y":"360","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"or\"","outputsInv":"[true]","inputsInv":"[false,false]"},{"x":"1080","y":"600","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"1080","y":"720","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"xor\"","outputsInv":"[false]","inputsInv":"[false,false]"}],"outputs":[{"x":"330","y":"240","colr":"0"},{"x":"330","y":"390","colr":"0"},{"x":"330","y":"540","colr":"0"},{"x":"1560","y":"270","colr":"0"},{"x":"1560","y":"390","colr":"0"},{"x":"1260","y":"630","colr":"0"},{"x":"1260","y":"750","colr":"0"},{"x":"690","y":"60","colr":"0"},{"x":"690","y":"90","colr":"1"},{"x":"690","y":"120","colr":"2"},{"x":"690","y":"150","colr":"3"},{"x":"1200","y":"90","colr":"0"}],"inputs":[{"x":"105","y":"165","framecount":"-1","clock":"false"},{"x":"165","y":"165","framecount":"-1","clock":"false"},{"x":"1275","y":"255","framecount":"-1","clock":"false"},{"x":"1275","y":"405","framecount":"-1","clock":"false"},{"x":"315","y":"705","framecount":"0","clock":"true","speed":"30"},{"x":"945","y":"615","framecount":"-1","clock":"false"},{"x":"945","y":"645","framecount":"-1","clock":"false"},{"x":"315","y":"45","framecount":"0","clock":"true","speed":"15"},{"x":"945","y":"75","framecount":"0","clock":"false"}],"wires":[{"x1":"180","y1":"570","x2":"210"},{"x1":"180","y1":"180","y2":"570"},{"x1":"180","y1":"270","x2":"210"},{"x1":"180","y1":"420","x2":"210"},{"x1":"120","y1":"540","x2":"210"},{"x1":"120","y1":"180","y2":"540"},{"x1":"120","y1":"390","x2":"210"},{"x1":"120","y1":"240","x2":"210"},{"x1":"270","y1":"240","x2":"330"},{"x1":"270","y1":"390","x2":"330"},{"x1":"270","y1":"540","x2":"330"},{"x1":"1350","y1":"360","x2":"1470"},{"x1":"1440","y1":"390","x2":"1560"},{"x1":"1470","y1":"360","y2":"390"},{"x1":"1350","y1":"300","x2":"1380"},{"x1":"1350","y1":"300","y2":"360"},{"x1":"1440","y1":"270","x2":"1560"},{"x1":"1500","y1":"270","y2":"330"},{"x1":"1320","y1":"330","x2":"1500"},{"x1":"1320","y1":"330","y2":"390"},{"x1":"1320","y1":"390","x2":"1380"},{"x1":"1290","y1":"270","x2":"1380"},{"x1":"1290","y1":"420","x2":"1380"},{"x1":"480","y1":"720","x2":"510"},{"x1":"510","y1":"690","y2":"720"},{"x1":"480","y1":"750","x2":"540"},{"x1":"540","y1":"690","y2":"750"},{"x1":"480","y1":"780","x2":"570"},{"x1":"570","y1":"690","y2":"780"},{"x1":"480","y1":"810","x2":"600"},{"x1":"600","y1":"690","y2":"810"},{"x1":"330","y1":"720","x2":"420"},{"x1":"960","y1":"630","x2":"1080"},{"x1":"960","y1":"660","x2":"1080"},{"x1":"1050","y1":"750","x2":"1080"},{"x1":"1050","y1":"630","y2":"750"},{"x1":"1020","y1":"780","x2":"1080"},{"x1":"1020","y1":"660","y2":"780"},{"x1":"1140","y1":"630","x2":"1260"},{"x1":"1140","y1":"750","x2":"1260"},{"x1":"480","y1":"90","x2":"570"},{"x1":"480","y1":"60","x2":"570"},{"x1":"330","y1":"60","x2":"420"},{"x1":"630","y1":"60","x2":"690"},{"x1":"630","y1":"90","x2":"690"},{"x1":"630","y1":"120","x2":"690"},{"x1":"630","y1":"150","x2":"690"},{"x1":"960","y1":"90","x2":"1050"},{"x1":"1110","y1":"90","x2":"1200"}],"conpoints":[{"x":"180","y":"270"},{"x":"180","y":"420"},{"x":"120","y":"390"},{"x":"120","y":"240"},{"x":"1500","y":"270"},{"x":"1470","y":"390"},{"x":"1050","y":"630"},{"x":"1020","y":"660"}],"diodes":[],"customs":[{"x":"420","y":"690","direction":"0","filename":"\"4-counter.json\"","outputsInv":"[]","inputsInv":"[]"},{"x":"570","y":"30","direction":"0","filename":"\"2-decoder.json\"","outputsInv":"[]","inputsInv":"[]"},{"x":"420","y":"30","direction":"0","filename":"\"2-counter.json\"","outputsInv":"[]","inputsInv":"[]"},{"x":"1050","y":"60","direction":"0","filename":"\"not-gate.json\"","outputsInv":"[]","inputsInv":"[]"}],"labels":[],"segDisplays":[{"x":"480","y":"600","inputCount":"4","inputsInv":"[false,false,false,false]"}]} -------------------------------------------------------------------------------- /views/librarySketches/library__hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBuxx/LogiJS/87a03cba7f0443603f538af7653f65ea7f4a219b/views/librarySketches/library__hover.png -------------------------------------------------------------------------------- /views/login.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | head 4 | | 5 | | 10 | | 11 | title LogiJS: Login 12 | meta(name='keywords', content='LogiJS, logic, circuit, simulation, simulator, editor, free, open, source, gate, input, output, sketch, electronics, physics, informatics, it, \ 13 | computer, chip, pcb, design, creator, creation, processor, cpu, logi, js, javascript') 14 | meta(name='description', content='LogiJS is a web-based logic circuit simulator for educational use. Discover the world of logic circuits.') 15 | meta(charset='UTF-8') 16 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 17 | link(rel='shortcut icon', href='images/favi.png') 18 | style 19 | include css/bootstrap.css 20 | include css/index_style.css 21 | link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,300', rel='stylesheet', type='text/css') 22 | link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css') 23 | link(rel="stylesheet", type='text/css', href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css") 24 | script(src='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js') 25 | script. 26 | window.addEventListener("load", function () { 27 | window.cookieconsent.initialise({ 28 | "position": "bottom-right", 29 | "content": { 30 | "dismiss": "Allow Cookies" 31 | }, 32 | "palette": { 33 | "popup": { 34 | "background": "#323232", 35 | "text": "#fff", 36 | "link": "#c83232" 37 | }, 38 | "button": { 39 | "background": "#c83232", 40 | "text": "#ffffff" 41 | } 42 | } 43 | }) 44 | }); 45 | body 46 | | 47 | | 49 | | 50 | .top-menu#top 51 | .container 52 | .navbar.navbar-default.navbar-fixed-top(role='navigation') 53 | .container 54 | ul.nav.navbar-nav.navbar-left 55 | li 56 | a.internal-link(rel='nofollow', href='/#features', target='_parent') Features 57 | li 58 | a.internal-link(rel='nofollow', href='/#samples', target='_parent') Samples 59 | li 60 | a.internal-link(rel='nofollow', href='/#about', target='_parent') About 61 | .navbar-header 62 | a.navbar-brand(href='/#top', style="transition: 0.2s;") 63 | img#top_logo(src='images/logo_index_new.png', alt='LogiJS logo', title='LogiJS', style='float: left;') 64 | div#logo-div 65 | p#logo-text Logic Circuit 66 | br 67 | | Simulation 68 | span(style="color: #c83232;") . 69 | .navbar-collapse.collapse 70 | ul.nav.navbar-nav.navbar-right 71 | li 72 | a.login-button.internal-link(rel='nofollow', href='#', target='_parent') Login 73 | li 74 | a.internal-link(rel='nofollow', href='/signup', target='_parent') Register 75 | li 76 | a#mode-button.internal-link(rel='nofollow', href='javascript:;', target='_parent' title='Toggle Dark Mode') 77 | .slogan-container(style="margin-top: 150px;") 78 | h1.background-text Discover the world 79 | .login_container 80 | form.Login.login-background 81 | if failed 82 | p.login-message Login failed 83 | span(style="color: #c83232;") . 84 | else if signup_success 85 | p.login-message Registration successful 86 | span(style="color: #c83232;") . 87 | else 88 | h1.login_title Login 89 | span(style="color: #c83232;") . 90 | p 91 | input.username(type='text', placeholder='Username') 92 | br 93 | input.password(type='password', placeholder='Password') 94 | br 95 | input.btn.btn-lg.btn-orange.login-confirm-button(type='submit', value='Login', role='button') 96 | p.login-redirect-text 97 | | Don't have an account? 98 | a.login-redirect-text(href='/signup') Register 99 | br 100 | .footer_bottom.footer_bottom_absolute 101 | .footer_bottom_content 102 | .footer_box.footer_box_outer 103 | a.internal-link(rel='nofollow', href='/terms-of-service', target='_parent') Terms of Service 104 | a.internal-link(rel='nofollow', href='/legal', target='_parent') Legal Notice 105 | .footer_box.footer_box_inner 106 | p(style="text-align: center; display: inline-block; width: 100%;") 107 | a(href='https://twitter.com/logi_js', target='_blank', style="margin-right: 5px;") 108 | img(src="images/twitter.png" style="width: 40px; margin-top: -20px;") 109 | a(href='https://github.com/SimonBuxx/logijs', target='_blank', style="margin-left: 5px;") 110 | img(src="images/github_dark.png" style="width: 40px; margin-top: -20px;") 111 | .footer_box.footer_box_outer.footer_right 112 | p(style="text-align: right;") Made with in Lübeck 113 | span(style="color: #c83232;") . 114 | script 115 | include ../libraries/jquery.min.js 116 | include ../libraries/bootstrap.min.js 117 | include ../site_scripts/login.js -------------------------------------------------------------------------------- /views/profile.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | head 4 | | 5 | | 10 | | 11 | title LogiJS: Profile 12 | meta(name='keywords', content='LogiJS, logic, circuit, simulation, simulator, editor, free, open, source, gate, input, output, sketch, electronics, physics, informatics, it, \ 13 | computer, chip, pcb, design, creator, creation, processor, cpu, logi, js, javascript') 14 | meta(name='description', content='LogiJS is a web-based logic circuit simulator for educational use. Discover the world of logic circuits.') 15 | meta(charset='UTF-8') 16 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 17 | link(rel='shortcut icon', href='images/favicon.ico') 18 | style 19 | include css/bootstrap.css 20 | include css/index_style.css 21 | link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,300', rel='stylesheet', type='text/css') 22 | link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css') 23 | link(rel="stylesheet", type='text/css', href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css") 24 | script(src='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js') 25 | script. 26 | window.addEventListener("load", function () { 27 | window.cookieconsent.initialise({ 28 | "palette": { 29 | "popup": { 30 | "background": "#323232", 31 | "text": "#ffffff" 32 | }, 33 | "button": { 34 | "background": "#c83232", 35 | "text": "#ffffff" 36 | } 37 | } 38 | }) 39 | }); 40 | body 41 | | 42 | | 44 | | 45 | .top-menu 46 | .container 47 | .navbar.navbar-default.navbar-fixed-top(role='navigation') 48 | .container 49 | .navbar-header 50 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 51 | span.sr-only Toggle navigation 52 | span.icon-bar 53 | span.icon-bar 54 | span.icon-bar 55 | a.navbar-brand(href='/') 56 | img(src='images/logo_index.png', alt='LogiJS logo', title='LogiJS') 57 | .navbar-collapse.collapse 58 | ul.nav.navbar-nav.navbar-right 59 | li 60 | a.internal-link(rel='nofollow', href='/', target='_parent') HOME 61 | li 62 | a.internal-link(rel='nofollow', href='/samples', target='_parent') SAMPLES 63 | li 64 | a.external-link(rel='nofollow', href='https://www.github.com/SimonBuxx/LogiJS', target='_parent') GITHUB 65 | li 66 | a.user-button(href='/dashboard') #{user.toUpperCase()} 67 | #blurred-background 68 | .profile-mobile-bar.show-in-mobile 69 | form#import-button.Import(title="Coming soon!") 70 | button.btn.btn-lg.btn-orange(disabled="true", type='submit', role='button') 71 | IMPORT FILE 72 | button#profile-button.btn.btn-lg.btn-orange(type='submit', role='button', onclick="window.location.href='#'") 73 | PROFILE 74 | form#logout-button.Logout 75 | button.btn.btn-lg.btn-orange(type='submit', role='button') 76 | LOGOUT 77 | #info-card.card.profile_card 78 | img.profile-pic(src="images/default-profile.svg", alt="Profile picture") 79 | .profile-data 80 | h2 #{user} 81 | h3 #{email} 82 | h3 Maybe a member since date 83 | #password-card.profile_card 84 | .profile-data 85 | h2 Change Password 86 | h3 Here should be two password inputs and one button to change the password. 87 | .sidebar.profile-sidebar.hide-in-mobile 88 | .sticky-bar 89 | button#editor-button.btn.btn-lg.btn-orange(type='submit', rel="nofollow", onclick="window.location.href='/editor'", role='button') 90 | NEW SKETCH 91 | form#import-button.Import(title="Coming soon!") 92 | button.btn.btn-lg.btn-orange(disabled="true", type='submit', role='button') 93 | IMPORT FILE 94 | button#profile-button.btn.btn-lg.btn-orange(type='submit', role='button', onclick="window.location.href='#'") 95 | PROFILE 96 | form#logout-button.Logout 97 | button.btn.btn-lg.btn-orange(type='submit', role='button') 98 | LOGOUT 99 | .footer_bottom 100 | .text-center 101 | .footer_bottom_content 102 | span#footer-line 103 | a.internal-link(rel='nofollow', href='/terms-of-service', target='_parent') Terms of Service 104 | | | 105 | a.internal-link(rel='nofollow', href='/legal', target='_parent') Legal Notice 106 | 107 | script 108 | include ../libraries/jquery.min.js 109 | include ../libraries/bootstrap.min.js 110 | include ../site_scripts/dashboard.js -------------------------------------------------------------------------------- /views/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: * 2 | Allow: / 3 | 4 | -------------------------------------------------------------------------------- /views/signup.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | head 4 | | 5 | | 10 | | 11 | title LogiJS: Register 12 | meta(name='keywords', content='LogiJS, logic, circuit, simulation, simulator, editor, free, open, source, gate, input, output, sketch, electronics, physics, informatics, it, \ 13 | computer, chip, pcb, design, creator, creation, processor, cpu, logi, js, javascript') 14 | meta(name='description', content='LogiJS is a web-based logic circuit simulator for educational use. Discover the world of logic circuits.') 15 | meta(charset='UTF-8') 16 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 17 | link(rel='shortcut icon', href='images/favi.png') 18 | style 19 | include css/bootstrap.css 20 | include css/index_style.css 21 | link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,300', rel='stylesheet', type='text/css') 22 | link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css') 23 | link(rel="stylesheet", type='text/css', href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css") 24 | script(src='https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js') 25 | script. 26 | window.addEventListener("load", function () { 27 | window.cookieconsent.initialise({ 28 | "position": "bottom-right", 29 | "content": { 30 | "dismiss": "Allow Cookies" 31 | }, 32 | "palette": { 33 | "popup": { 34 | "background": "#323232", 35 | "text": "#fff", 36 | "link": "#c83232" 37 | }, 38 | "button": { 39 | "background": "#c83232", 40 | "text": "#ffffff" 41 | } 42 | } 43 | }) 44 | }); 45 | body 46 | | 47 | | 49 | | 50 | .top-menu#top 51 | .container 52 | .navbar.navbar-default.navbar-fixed-top(role='navigation') 53 | .container 54 | ul.nav.navbar-nav.navbar-left 55 | li 56 | a.internal-link(rel='nofollow', href='/#features', target='_parent') Features 57 | li 58 | a.internal-link(rel='nofollow', href='/#samples', target='_parent') Samples 59 | li 60 | a.internal-link(rel='nofollow', href='/#about', target='_parent') About 61 | .navbar-header 62 | a.navbar-brand(href='/#top', style="transition: 0.2s;") 63 | img#top_logo(src='images/logo_index_new.png', alt='LogiJS logo', title='LogiJS', style='float: left;') 64 | div#logo-div 65 | p#logo-text Logic Circuit 66 | br 67 | | Simulation 68 | span(style="color: #c83232;") . 69 | .navbar-collapse.collapse 70 | ul.nav.navbar-nav.navbar-right 71 | li 72 | a.login-button.internal-link(rel='nofollow', href='/login', target='_parent') Login 73 | li 74 | a.internal-link(rel='nofollow', href='#', target='_parent') Register 75 | li 76 | a#mode-button.internal-link(rel='nofollow', href='javascript:;', target='_parent' title='Toggle Dark Mode') 77 | .slogan-container(style="margin-top: 150px;") 78 | h1.background-text Discover the world 79 | .login_container 80 | - var error = parseInt(error_code); 81 | form.SignUp.login-background 82 | case error 83 | when 1: p.login-message Username invalid 84 | span(style="color: #c83232;") . 85 | when 2: p.login-message Email address invalid 86 | span(style="color: #c83232;") . 87 | when 3 88 | p.login-message Password invalid 89 | span(style="color: #c83232;") . 90 | p.login-message.password-tipps Please enter 6 to 50 upper- AND lowercase characters, containing at least one digit 91 | span(style="color: #c83232;") . 92 | when 4: p.login-message Username already taken 93 | span(style="color: #c83232;") . 94 | default: h1.login_title Register 95 | span(style="color: #c83232;") . 96 | p 97 | input.username(type='text', placeholder='Username') 98 | br 99 | input.email(type='text', placeholder='E-Mail') 100 | br 101 | input.password(type='password', placeholder='Password') 102 | br 103 | input.btn.btn-lg.btn-orange.login-confirm-button(type='submit', value='Register', role='button') 104 | p.login-redirect-text 105 | | By continuing, you are accepting our
106 | a.login-redirect-text(href='/terms-of-service') Terms of Service 107 | | . 108 | p.login-redirect-text 109 | | Already have an account? 110 | a.login-redirect-text(href='/login') Login 111 | br 112 | .footer_bottom.footer_bottom_absolute 113 | .footer_bottom_content 114 | .footer_box.footer_box_outer 115 | a.internal-link(rel='nofollow', href='/terms-of-service', target='_parent') Terms of Service 116 | a.internal-link(rel='nofollow', href='/legal', target='_parent') Legal Notice 117 | .footer_box.footer_box_inner 118 | p(style="text-align: center; display: inline-block; width: 100%;") 119 | a(href='https://twitter.com/logi_js', target='_blank', style="margin-right: 5px;") 120 | img(src="images/twitter.png" style="width: 40px; margin-top: -20px;") 121 | a(href='https://github.com/SimonBuxx/logijs', target='_blank', style="margin-left: 5px;") 122 | img(src="images/github_dark.png" style="width: 40px; margin-top: -20px;") 123 | .footer_box.footer_box_outer.footer_right 124 | p(style="text-align: right;") Made with in Lübeck 125 | span(style="color: #c83232;") . 126 | script 127 | include ../libraries/jquery.min.js 128 | include ../libraries/bootstrap.min.js 129 | include ../site_scripts/create_account.js -------------------------------------------------------------------------------- /views/sketches/1-buffer.json: -------------------------------------------------------------------------------- 1 | {"caption":"","gates":[{"x":"540","y":"210","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"}],"outputs":[{"x":"690","y":"240","colr":"0","lbl":"1"}],"inputs":[{"x":"435","y":"225","framecount":"-1","clock":"false"}],"wires":[{"x1":"450","y1":"240","x2":"540"},{"x1":"480","y1":"270","x2":"540"},{"x1":"480","y1":"240","y2":"270"},{"x1":"600","y1":"240","x2":"690"}],"conpoints":[{"x":"480","y":"240"}],"diodes":[],"customs":[],"labels":[],"segDisplays":[]} -------------------------------------------------------------------------------- /views/sketches/1-demux.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "DEMUX", 3 | "gates": [ 4 | { 5 | "x": "990", 6 | "y": "360", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[false,true]" 13 | }, 14 | { 15 | "x": "990", 16 | "y": "450", 17 | "direction": "0", 18 | "inputCount": "2", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[false,false]" 23 | } 24 | ], 25 | "outputs": [ 26 | { 27 | "x": "1080", 28 | "y": "390", 29 | "colr": "0", 30 | "lbl": "0" 31 | }, 32 | { 33 | "x": "1080", 34 | "y": "480", 35 | "colr": "0", 36 | "lbl": "1" 37 | } 38 | ], 39 | "inputs": [ 40 | { 41 | "x": "855", 42 | "y": "375", 43 | "framecount": "-1", 44 | "clock": "false" 45 | }, 46 | { 47 | "x": "915", 48 | "y": "345", 49 | "istop": "true", 50 | "lbl": "2º", 51 | "framecount": "-1", 52 | "clock": "false" 53 | } 54 | ], 55 | "segments": [], 56 | "wires": [ 57 | { 58 | "x1": "960", 59 | "y1": "480", 60 | "x2": "990" 61 | }, 62 | { 63 | "x1": "1050", 64 | "y1": "390", 65 | "x2": "1080" 66 | }, 67 | { 68 | "x1": "1050", 69 | "y1": "480", 70 | "x2": "1080" 71 | }, 72 | { 73 | "x1": "930", 74 | "y1": "420", 75 | "x2": "990" 76 | }, 77 | { 78 | "x1": "930", 79 | "y1": "510", 80 | "x2": "990" 81 | }, 82 | { 83 | "x1": "960", 84 | "y1": "390", 85 | "y2": "480" 86 | }, 87 | { 88 | "x1": "870", 89 | "y1": "390", 90 | "x2": "990" 91 | }, 92 | { 93 | "x1": "930", 94 | "y1": "360", 95 | "y2": "510" 96 | } 97 | ], 98 | "conpoints": [ 99 | { 100 | "x": "960", 101 | "y": "390" 102 | }, 103 | { 104 | "x": "930", 105 | "y": "420" 106 | } 107 | ], 108 | "diodes": [], 109 | "customs": [], 110 | "labels": [], 111 | "segDisplays": [] 112 | } 113 | -------------------------------------------------------------------------------- /views/sketches/1-mux.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "MUX", 3 | "gates": [ 4 | { 5 | "x": "870", 6 | "y": "270", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[true,false]" 13 | }, 14 | { 15 | "x": "870", 16 | "y": "330", 17 | "direction": "0", 18 | "inputCount": "2", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[false,false]" 23 | }, 24 | { 25 | "x": "990", 26 | "y": "270", 27 | "direction": "0", 28 | "inputCount": "2", 29 | "outputCount": "1", 30 | "logicFunction": "\"or\"", 31 | "outputsInv": "[false]", 32 | "inputsInv": "[false,false]" 33 | } 34 | ], 35 | "outputs": [ 36 | { 37 | "x": "1080", 38 | "y": "300", 39 | "colr": "0" 40 | } 41 | ], 42 | "inputs": [ 43 | { 44 | "x": "825", 45 | "y": "255", 46 | "istop": "true", 47 | "lbl": "2º", 48 | "framecount": "-1", 49 | "clock": "false" 50 | }, 51 | { 52 | "x": "795", 53 | "y": "315", 54 | "lbl": "0", 55 | "framecount": "-1", 56 | "clock": "false" 57 | }, 58 | { 59 | "x": "795", 60 | "y": "345", 61 | "lbl": "1", 62 | "framecount": "-1", 63 | "clock": "false" 64 | } 65 | ], 66 | "segments": [], 67 | "wires": [ 68 | { 69 | "x1": "840", 70 | "y1": "300", 71 | "x2": "870" 72 | }, 73 | { 74 | "x1": "840", 75 | "y1": "390", 76 | "x2": "870" 77 | }, 78 | { 79 | "x1": "930", 80 | "y1": "360", 81 | "x2": "960" 82 | }, 83 | { 84 | "x1": "960", 85 | "y1": "330", 86 | "y2": "360" 87 | }, 88 | { 89 | "x1": "960", 90 | "y1": "330", 91 | "x2": "990" 92 | }, 93 | { 94 | "x1": "1050", 95 | "y1": "300", 96 | "x2": "1080" 97 | }, 98 | { 99 | "x1": "810", 100 | "y1": "330", 101 | "x2": "870" 102 | }, 103 | { 104 | "x1": "810", 105 | "y1": "360", 106 | "x2": "870" 107 | }, 108 | { 109 | "x1": "930", 110 | "y1": "300", 111 | "x2": "990" 112 | }, 113 | { 114 | "x1": "840", 115 | "y1": "270", 116 | "y2": "390" 117 | } 118 | ], 119 | "conpoints": [ 120 | { 121 | "x": "840", 122 | "y": "300" 123 | } 124 | ], 125 | "diodes": [], 126 | "customs": [], 127 | "labels": [], 128 | "segDisplays": [] 129 | } 130 | -------------------------------------------------------------------------------- /views/sketches/2-counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "Counter", 3 | "gates": [ 4 | { 5 | "x": "750", 6 | "y": "270", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"xor\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[false,false]" 13 | } 14 | ], 15 | "outputs": [ 16 | { 17 | "x": "960", 18 | "y": "150", 19 | "colr": "0", 20 | "lbl": "2¹" 21 | }, 22 | { 23 | "x": "690", 24 | "y": "150", 25 | "colr": "0", 26 | "lbl": "2º" 27 | } 28 | ], 29 | "inputs": [ 30 | { 31 | "x": "495", 32 | "y": "405", 33 | "lbl": ">", 34 | "framecount": "-1", 35 | "clock": "false" 36 | } 37 | ], 38 | "segments": [], 39 | "wires": [ 40 | { 41 | "x1": "660", 42 | "y1": "360", 43 | "x2": "690" 44 | }, 45 | { 46 | "x1": "570", 47 | "y1": "300", 48 | "y2": "330" 49 | }, 50 | { 51 | "x1": "570", 52 | "y1": "330", 53 | "x2": "600" 54 | }, 55 | { 56 | "x1": "840", 57 | "y1": "360", 58 | "x2": "870" 59 | }, 60 | { 61 | "x1": "570", 62 | "y1": "360", 63 | "x2": "600" 64 | }, 65 | { 66 | "x1": "810", 67 | "y1": "300", 68 | "x2": "840" 69 | }, 70 | { 71 | "x1": "840", 72 | "y1": "300", 73 | "y2": "330" 74 | }, 75 | { 76 | "x1": "840", 77 | "y1": "330", 78 | "x2": "870" 79 | }, 80 | { 81 | "x1": "930", 82 | "y1": "330", 83 | "x2": "960" 84 | }, 85 | { 86 | "x1": "720", 87 | "y1": "300", 88 | "x2": "750" 89 | }, 90 | { 91 | "x1": "840", 92 | "y1": "360", 93 | "y2": "420" 94 | }, 95 | { 96 | "x1": "570", 97 | "y1": "360", 98 | "y2": "420" 99 | }, 100 | { 101 | "x1": "690", 102 | "y1": "300", 103 | "y2": "360" 104 | }, 105 | { 106 | "x1": "720", 107 | "y1": "330", 108 | "y2": "390" 109 | }, 110 | { 111 | "x1": "660", 112 | "y1": "330", 113 | "x2": "750" 114 | }, 115 | { 116 | "x1": "570", 117 | "y1": "300", 118 | "x2": "690" 119 | }, 120 | { 121 | "x1": "720", 122 | "y1": "210", 123 | "y2": "300" 124 | }, 125 | { 126 | "x1": "690", 127 | "y1": "150", 128 | "y2": "270" 129 | }, 130 | { 131 | "x1": "540", 132 | "y1": "270", 133 | "y2": "390" 134 | }, 135 | { 136 | "x1": "960", 137 | "y1": "150", 138 | "y2": "330" 139 | }, 140 | { 141 | "x1": "720", 142 | "y1": "210", 143 | "x2": "960" 144 | }, 145 | { 146 | "x1": "540", 147 | "y1": "270", 148 | "x2": "690" 149 | }, 150 | { 151 | "x1": "540", 152 | "y1": "390", 153 | "x2": "720" 154 | }, 155 | { 156 | "x1": "510", 157 | "y1": "420", 158 | "x2": "840" 159 | } 160 | ], 161 | "conpoints": [ 162 | { 163 | "x": "570", 164 | "y": "420" 165 | }, 166 | { 167 | "x": "960", 168 | "y": "210" 169 | }, 170 | { 171 | "x": "720", 172 | "y": "330" 173 | } 174 | ], 175 | "diodes": [], 176 | "customs": [ 177 | { 178 | "x": "600", 179 | "y": "300", 180 | "direction": "0", 181 | "filename": "\"d-flipflop.json\"", 182 | "outputsInv": "[false,false,false,false,false,false,false,false]", 183 | "inputsInv": "[false,false,false,false,false,false,false,false]" 184 | }, 185 | { 186 | "x": "870", 187 | "y": "300", 188 | "direction": "0", 189 | "filename": "\"d-flipflop.json\"", 190 | "outputsInv": "[false,false,false,false,false,false,false,false]", 191 | "inputsInv": "[false,false,false,false,false,false,false,false]" 192 | } 193 | ], 194 | "labels": [], 195 | "segDisplays": [] 196 | } 197 | -------------------------------------------------------------------------------- /views/sketches/2-decoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "DecoderOld", 3 | "gates": [ 4 | { 5 | "x": "990", 6 | "y": "270", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[true,true]" 13 | }, 14 | { 15 | "x": "990", 16 | "y": "330", 17 | "direction": "0", 18 | "inputCount": "2", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[false,true]" 23 | }, 24 | { 25 | "x": "990", 26 | "y": "390", 27 | "direction": "0", 28 | "inputCount": "2", 29 | "outputCount": "1", 30 | "logicFunction": "\"and\"", 31 | "outputsInv": "[false]", 32 | "inputsInv": "[true,false]" 33 | }, 34 | { 35 | "x": "990", 36 | "y": "450", 37 | "direction": "0", 38 | "inputCount": "2", 39 | "outputCount": "1", 40 | "logicFunction": "\"and\"", 41 | "outputsInv": "[false]", 42 | "inputsInv": "[false,false]" 43 | } 44 | ], 45 | "outputs": [ 46 | { 47 | "x": "1110", 48 | "y": "300", 49 | "colr": "0", 50 | "lbl": "0" 51 | }, 52 | { 53 | "x": "1110", 54 | "y": "360", 55 | "colr": "0", 56 | "lbl": "1" 57 | }, 58 | { 59 | "x": "1110", 60 | "y": "420", 61 | "colr": "0", 62 | "lbl": "2" 63 | }, 64 | { 65 | "x": "1110", 66 | "y": "480", 67 | "colr": "0", 68 | "lbl": "3" 69 | } 70 | ], 71 | "inputs": [ 72 | { 73 | "x": "915", 74 | "y": "255", 75 | "framecount": "-1", 76 | "clock": "false", 77 | "lbl": "2¹" 78 | }, 79 | { 80 | "x": "945", 81 | "y": "255", 82 | "framecount": "-1", 83 | "clock": "false", 84 | "lbl": "2º" 85 | } 86 | ], 87 | "segments": [], 88 | "wires": [ 89 | { 90 | "x1": "960", 91 | "y1": "480", 92 | "x2": "990" 93 | }, 94 | { 95 | "x1": "960", 96 | "y1": "300", 97 | "x2": "990" 98 | }, 99 | { 100 | "x1": "960", 101 | "y1": "360", 102 | "x2": "990" 103 | }, 104 | { 105 | "x1": "960", 106 | "y1": "420", 107 | "x2": "990" 108 | }, 109 | { 110 | "x1": "930", 111 | "y1": "510", 112 | "x2": "990" 113 | }, 114 | { 115 | "x1": "930", 116 | "y1": "450", 117 | "x2": "990" 118 | }, 119 | { 120 | "x1": "930", 121 | "y1": "390", 122 | "x2": "990" 123 | }, 124 | { 125 | "x1": "930", 126 | "y1": "330", 127 | "x2": "990" 128 | }, 129 | { 130 | "x1": "1050", 131 | "y1": "300", 132 | "x2": "1110" 133 | }, 134 | { 135 | "x1": "1050", 136 | "y1": "360", 137 | "x2": "1110" 138 | }, 139 | { 140 | "x1": "1050", 141 | "y1": "420", 142 | "x2": "1110" 143 | }, 144 | { 145 | "x1": "1050", 146 | "y1": "480", 147 | "x2": "1110" 148 | }, 149 | { 150 | "x1": "930", 151 | "y1": "270", 152 | "y2": "510" 153 | }, 154 | { 155 | "x1": "960", 156 | "y1": "270", 157 | "y2": "480" 158 | } 159 | ], 160 | "conpoints": [ 161 | { 162 | "x": "930", 163 | "y": "450" 164 | }, 165 | { 166 | "x": "930", 167 | "y": "390" 168 | }, 169 | { 170 | "x": "930", 171 | "y": "330" 172 | }, 173 | { 174 | "x": "960", 175 | "y": "300" 176 | }, 177 | { 178 | "x": "960", 179 | "y": "360" 180 | }, 181 | { 182 | "x": "960", 183 | "y": "420" 184 | } 185 | ], 186 | "diodes": [], 187 | "customs": [], 188 | "labels": [], 189 | "segDisplays": [] 190 | } 191 | -------------------------------------------------------------------------------- /views/sketches/2-demux.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "DEMUX", 3 | "gates": [ 4 | { 5 | "x": "870", 6 | "y": "270", 7 | "direction": "0", 8 | "inputCount": "3", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[true,true,false]" 13 | }, 14 | { 15 | "x": "870", 16 | "y": "390", 17 | "direction": "0", 18 | "inputCount": "3", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[false,true,false]" 23 | }, 24 | { 25 | "x": "870", 26 | "y": "510", 27 | "direction": "0", 28 | "inputCount": "3", 29 | "outputCount": "1", 30 | "logicFunction": "\"and\"", 31 | "outputsInv": "[false]", 32 | "inputsInv": "[true,false,false]" 33 | }, 34 | { 35 | "x": "870", 36 | "y": "630", 37 | "direction": "0", 38 | "inputCount": "3", 39 | "outputCount": "1", 40 | "logicFunction": "\"and\"", 41 | "outputsInv": "[false]", 42 | "inputsInv": "[false,false,false]" 43 | } 44 | ], 45 | "outputs": [ 46 | { 47 | "x": "990", 48 | "y": "300", 49 | "colr": "0", 50 | "lbl": "0" 51 | }, 52 | { 53 | "x": "990", 54 | "y": "420", 55 | "colr": "0", 56 | "lbl": "1" 57 | }, 58 | { 59 | "x": "990", 60 | "y": "540", 61 | "colr": "0", 62 | "lbl": "2" 63 | }, 64 | { 65 | "x": "990", 66 | "y": "660", 67 | "colr": "0", 68 | "lbl": "3" 69 | } 70 | ], 71 | "inputs": [ 72 | { 73 | "x": "795", 74 | "y": "225", 75 | "istop": "true", 76 | "lbl": "2¹", 77 | "framecount": "-1", 78 | "clock": "false" 79 | }, 80 | { 81 | "x": "825", 82 | "y": "225", 83 | "istop": "true", 84 | "lbl": "2º", 85 | "framecount": "-1", 86 | "clock": "false" 87 | }, 88 | { 89 | "x": "765", 90 | "y": "225", 91 | "framecount": "-1", 92 | "clock": "false" 93 | } 94 | ], 95 | "segments": [], 96 | "wires": [ 97 | { 98 | "x1": "840", 99 | "y1": "300", 100 | "x2": "870" 101 | }, 102 | { 103 | "x1": "840", 104 | "y1": "420", 105 | "x2": "870" 106 | }, 107 | { 108 | "x1": "840", 109 | "y1": "540", 110 | "x2": "870" 111 | }, 112 | { 113 | "x1": "840", 114 | "y1": "660", 115 | "x2": "870" 116 | }, 117 | { 118 | "x1": "810", 119 | "y1": "690", 120 | "x2": "870" 121 | }, 122 | { 123 | "x1": "810", 124 | "y1": "330", 125 | "x2": "870" 126 | }, 127 | { 128 | "x1": "810", 129 | "y1": "450", 130 | "x2": "870" 131 | }, 132 | { 133 | "x1": "810", 134 | "y1": "570", 135 | "x2": "870" 136 | }, 137 | { 138 | "x1": "930", 139 | "y1": "300", 140 | "x2": "990" 141 | }, 142 | { 143 | "x1": "930", 144 | "y1": "420", 145 | "x2": "990" 146 | }, 147 | { 148 | "x1": "930", 149 | "y1": "540", 150 | "x2": "990" 151 | }, 152 | { 153 | "x1": "930", 154 | "y1": "660", 155 | "x2": "990" 156 | }, 157 | { 158 | "x1": "780", 159 | "y1": "360", 160 | "x2": "870" 161 | }, 162 | { 163 | "x1": "780", 164 | "y1": "480", 165 | "x2": "870" 166 | }, 167 | { 168 | "x1": "780", 169 | "y1": "600", 170 | "x2": "870" 171 | }, 172 | { 173 | "x1": "780", 174 | "y1": "720", 175 | "x2": "870" 176 | }, 177 | { 178 | "x1": "840", 179 | "y1": "240", 180 | "y2": "660" 181 | }, 182 | { 183 | "x1": "810", 184 | "y1": "240", 185 | "y2": "690" 186 | }, 187 | { 188 | "x1": "780", 189 | "y1": "240", 190 | "y2": "720" 191 | } 192 | ], 193 | "conpoints": [ 194 | { 195 | "x": "840", 196 | "y": "300" 197 | }, 198 | { 199 | "x": "840", 200 | "y": "420" 201 | }, 202 | { 203 | "x": "840", 204 | "y": "540" 205 | }, 206 | { 207 | "x": "810", 208 | "y": "330" 209 | }, 210 | { 211 | "x": "810", 212 | "y": "450" 213 | }, 214 | { 215 | "x": "810", 216 | "y": "570" 217 | }, 218 | { 219 | "x": "780", 220 | "y": "360" 221 | }, 222 | { 223 | "x": "780", 224 | "y": "480" 225 | }, 226 | { 227 | "x": "780", 228 | "y": "600" 229 | } 230 | ], 231 | "diodes": [], 232 | "customs": [], 233 | "labels": [], 234 | "segDisplays": [] 235 | } 236 | -------------------------------------------------------------------------------- /views/sketches/2-mux.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "MUX", 3 | "gates": [ 4 | { 5 | "x": "780", 6 | "y": "300", 7 | "direction": "0", 8 | "inputCount": "3", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[true,true,false]" 13 | }, 14 | { 15 | "x": "780", 16 | "y": "390", 17 | "direction": "0", 18 | "inputCount": "3", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[false,true,false]" 23 | }, 24 | { 25 | "x": "780", 26 | "y": "480", 27 | "direction": "0", 28 | "inputCount": "3", 29 | "outputCount": "1", 30 | "logicFunction": "\"and\"", 31 | "outputsInv": "[false]", 32 | "inputsInv": "[true,false,false]" 33 | }, 34 | { 35 | "x": "780", 36 | "y": "570", 37 | "direction": "0", 38 | "inputCount": "3", 39 | "outputCount": "1", 40 | "logicFunction": "\"and\"", 41 | "outputsInv": "[false]", 42 | "inputsInv": "[false,false,false]" 43 | }, 44 | { 45 | "x": "960", 46 | "y": "390", 47 | "direction": "0", 48 | "inputCount": "4", 49 | "outputCount": "1", 50 | "logicFunction": "\"or\"", 51 | "outputsInv": "[false]", 52 | "inputsInv": "[false,false,false,false]" 53 | } 54 | ], 55 | "outputs": [ 56 | { 57 | "x": "1080", 58 | "y": "420", 59 | "colr": "0" 60 | } 61 | ], 62 | "inputs": [ 63 | { 64 | "x": "705", 65 | "y": "255", 66 | "istop": "true", 67 | "lbl": "2¹", 68 | "framecount": "-1", 69 | "clock": "false" 70 | }, 71 | { 72 | "x": "735", 73 | "y": "255", 74 | "istop": "true", 75 | "lbl": "2º", 76 | "framecount": "-1", 77 | "clock": "false" 78 | }, 79 | { 80 | "x": "675", 81 | "y": "375", 82 | "lbl": "0", 83 | "framecount": "-1", 84 | "clock": "false" 85 | }, 86 | { 87 | "x": "675", 88 | "y": "465", 89 | "lbl": "1", 90 | "framecount": "-1", 91 | "clock": "false" 92 | }, 93 | { 94 | "x": "675", 95 | "y": "555", 96 | "lbl": "2", 97 | "framecount": "-1", 98 | "clock": "false" 99 | }, 100 | { 101 | "x": "675", 102 | "y": "645", 103 | "lbl": "3", 104 | "framecount": "-1", 105 | "clock": "false" 106 | } 107 | ], 108 | "segments": [], 109 | "wires": [ 110 | { 111 | "x1": "750", 112 | "y1": "330", 113 | "x2": "780" 114 | }, 115 | { 116 | "x1": "750", 117 | "y1": "420", 118 | "x2": "780" 119 | }, 120 | { 121 | "x1": "750", 122 | "y1": "510", 123 | "x2": "780" 124 | }, 125 | { 126 | "x1": "750", 127 | "y1": "600", 128 | "x2": "780" 129 | }, 130 | { 131 | "x1": "930", 132 | "y1": "420", 133 | "x2": "960" 134 | }, 135 | { 136 | "x1": "900", 137 | "y1": "420", 138 | "y2": "450" 139 | }, 140 | { 141 | "x1": "840", 142 | "y1": "510", 143 | "x2": "870" 144 | }, 145 | { 146 | "x1": "870", 147 | "y1": "480", 148 | "y2": "510" 149 | }, 150 | { 151 | "x1": "720", 152 | "y1": "360", 153 | "x2": "780" 154 | }, 155 | { 156 | "x1": "720", 157 | "y1": "450", 158 | "x2": "780" 159 | }, 160 | { 161 | "x1": "720", 162 | "y1": "540", 163 | "x2": "780" 164 | }, 165 | { 166 | "x1": "720", 167 | "y1": "630", 168 | "x2": "780" 169 | }, 170 | { 171 | "x1": "840", 172 | "y1": "420", 173 | "x2": "900" 174 | }, 175 | { 176 | "x1": "900", 177 | "y1": "450", 178 | "x2": "960" 179 | }, 180 | { 181 | "x1": "840", 182 | "y1": "600", 183 | "x2": "900" 184 | }, 185 | { 186 | "x1": "900", 187 | "y1": "510", 188 | "x2": "960" 189 | }, 190 | { 191 | "x1": "1020", 192 | "y1": "420", 193 | "x2": "1080" 194 | }, 195 | { 196 | "x1": "690", 197 | "y1": "390", 198 | "x2": "780" 199 | }, 200 | { 201 | "x1": "690", 202 | "y1": "480", 203 | "x2": "780" 204 | }, 205 | { 206 | "x1": "690", 207 | "y1": "570", 208 | "x2": "780" 209 | }, 210 | { 211 | "x1": "690", 212 | "y1": "660", 213 | "x2": "780" 214 | }, 215 | { 216 | "x1": "930", 217 | "y1": "330", 218 | "y2": "420" 219 | }, 220 | { 221 | "x1": "840", 222 | "y1": "330", 223 | "x2": "930" 224 | }, 225 | { 226 | "x1": "870", 227 | "y1": "480", 228 | "x2": "960" 229 | }, 230 | { 231 | "x1": "900", 232 | "y1": "510", 233 | "y2": "600" 234 | }, 235 | { 236 | "x1": "750", 237 | "y1": "270", 238 | "y2": "690" 239 | }, 240 | { 241 | "x1": "720", 242 | "y1": "270", 243 | "y2": "690" 244 | } 245 | ], 246 | "conpoints": [ 247 | { 248 | "x": "750", 249 | "y": "330" 250 | }, 251 | { 252 | "x": "720", 253 | "y": "360" 254 | }, 255 | { 256 | "x": "750", 257 | "y": "420" 258 | }, 259 | { 260 | "x": "720", 261 | "y": "450" 262 | }, 263 | { 264 | "x": "750", 265 | "y": "510" 266 | }, 267 | { 268 | "x": "720", 269 | "y": "540" 270 | }, 271 | { 272 | "x": "750", 273 | "y": "600" 274 | }, 275 | { 276 | "x": "720", 277 | "y": "630" 278 | } 279 | ], 280 | "diodes": [], 281 | "customs": [], 282 | "labels": [], 283 | "segDisplays": [] 284 | } 285 | -------------------------------------------------------------------------------- /views/sketches/3-buffer.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "3-Buffer", 3 | "gates": [ 4 | { 5 | "x": "180", 6 | "y": "60", 7 | "direction": "0", 8 | "inputCount": "1", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "caption": "\"&\"", 12 | "outputsInv": "[false]", 13 | "inputsInv": "[false]" 14 | }, 15 | { 16 | "x": "270", 17 | "y": "60", 18 | "direction": "0", 19 | "inputCount": "1", 20 | "outputCount": "1", 21 | "logicFunction": "\"and\"", 22 | "caption": "\"&\"", 23 | "outputsInv": "[false]", 24 | "inputsInv": "[false]" 25 | }, 26 | { 27 | "x": "360", 28 | "y": "60", 29 | "direction": "0", 30 | "inputCount": "1", 31 | "outputCount": "1", 32 | "logicFunction": "\"and\"", 33 | "caption": "\"&\"", 34 | "outputsInv": "[false]", 35 | "inputsInv": "[false]" 36 | } 37 | ], 38 | "outputs": [ 39 | { 40 | "x": "450", 41 | "y": "90", 42 | "colr": "0" 43 | } 44 | ], 45 | "inputs": [ 46 | { 47 | "x": "135", 48 | "y": "75", 49 | "framecount": "-1", 50 | "clock": "false" 51 | } 52 | ], 53 | "segments": [], 54 | "wires": [ 55 | { 56 | "x1": "240", 57 | "y1": "90", 58 | "x2": "270", 59 | "y2": "90" 60 | }, 61 | { 62 | "x1": "330", 63 | "y1": "90", 64 | "x2": "360", 65 | "y2": "90" 66 | }, 67 | { 68 | "x1": "420", 69 | "y1": "90", 70 | "x2": "450", 71 | "y2": "90" 72 | }, 73 | { 74 | "x1": "150", 75 | "y1": "90", 76 | "x2": "180", 77 | "y2": "90" 78 | } 79 | ], 80 | "conpoints": [], 81 | "diodes": [], 82 | "customs": [], 83 | "labels": [] 84 | } 85 | -------------------------------------------------------------------------------- /views/sketches/3-counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "Counter", 3 | "gates": [ 4 | { 5 | "x": "750", 6 | "y": "270", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"xor\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[false,false]" 13 | }, 14 | { 15 | "x": "1020", 16 | "y": "300", 17 | "direction": "0", 18 | "inputCount": "2", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[false,false]" 23 | }, 24 | { 25 | "x": "1110", 26 | "y": "270", 27 | "direction": "0", 28 | "inputCount": "2", 29 | "outputCount": "1", 30 | "logicFunction": "\"xor\"", 31 | "outputsInv": "[false]", 32 | "inputsInv": "[false,false]" 33 | } 34 | ], 35 | "outputs": [ 36 | { 37 | "x": "1320", 38 | "y": "150", 39 | "colr": "0", 40 | "lbl": "2²" 41 | }, 42 | { 43 | "x": "960", 44 | "y": "150", 45 | "colr": "0", 46 | "lbl": "2¹" 47 | }, 48 | { 49 | "x": "690", 50 | "y": "150", 51 | "colr": "0", 52 | "lbl": "2º" 53 | } 54 | ], 55 | "inputs": [ 56 | { 57 | "x": "495", 58 | "y": "405", 59 | "lbl": ">", 60 | "framecount": "-1", 61 | "clock": "false" 62 | } 63 | ], 64 | "segments": [], 65 | "wires": [ 66 | { 67 | "x1": "660", 68 | "y1": "360", 69 | "x2": "690" 70 | }, 71 | { 72 | "x1": "570", 73 | "y1": "300", 74 | "y2": "330" 75 | }, 76 | { 77 | "x1": "570", 78 | "y1": "330", 79 | "x2": "600" 80 | }, 81 | { 82 | "x1": "840", 83 | "y1": "360", 84 | "x2": "870" 85 | }, 86 | { 87 | "x1": "570", 88 | "y1": "360", 89 | "x2": "600" 90 | }, 91 | { 92 | "x1": "1200", 93 | "y1": "360", 94 | "x2": "1230" 95 | }, 96 | { 97 | "x1": "810", 98 | "y1": "300", 99 | "x2": "840" 100 | }, 101 | { 102 | "x1": "840", 103 | "y1": "300", 104 | "y2": "330" 105 | }, 106 | { 107 | "x1": "840", 108 | "y1": "330", 109 | "x2": "870" 110 | }, 111 | { 112 | "x1": "930", 113 | "y1": "330", 114 | "x2": "960" 115 | }, 116 | { 117 | "x1": "720", 118 | "y1": "300", 119 | "x2": "750" 120 | }, 121 | { 122 | "x1": "1080", 123 | "y1": "270", 124 | "y2": "300" 125 | }, 126 | { 127 | "x1": "1080", 128 | "y1": "300", 129 | "x2": "1110" 130 | }, 131 | { 132 | "x1": "1080", 133 | "y1": "330", 134 | "x2": "1110" 135 | }, 136 | { 137 | "x1": "990", 138 | "y1": "330", 139 | "x2": "1020" 140 | }, 141 | { 142 | "x1": "1170", 143 | "y1": "300", 144 | "x2": "1200" 145 | }, 146 | { 147 | "x1": "1200", 148 | "y1": "300", 149 | "y2": "330" 150 | }, 151 | { 152 | "x1": "1200", 153 | "y1": "330", 154 | "x2": "1230" 155 | }, 156 | { 157 | "x1": "1290", 158 | "y1": "330", 159 | "x2": "1320" 160 | }, 161 | { 162 | "x1": "840", 163 | "y1": "360", 164 | "y2": "420" 165 | }, 166 | { 167 | "x1": "570", 168 | "y1": "360", 169 | "y2": "420" 170 | }, 171 | { 172 | "x1": "1200", 173 | "y1": "360", 174 | "y2": "420" 175 | }, 176 | { 177 | "x1": "960", 178 | "y1": "360", 179 | "x2": "1020" 180 | }, 181 | { 182 | "x1": "690", 183 | "y1": "300", 184 | "y2": "360" 185 | }, 186 | { 187 | "x1": "720", 188 | "y1": "330", 189 | "y2": "390" 190 | }, 191 | { 192 | "x1": "660", 193 | "y1": "330", 194 | "x2": "750" 195 | }, 196 | { 197 | "x1": "570", 198 | "y1": "300", 199 | "x2": "690" 200 | }, 201 | { 202 | "x1": "720", 203 | "y1": "210", 204 | "y2": "300" 205 | }, 206 | { 207 | "x1": "690", 208 | "y1": "150", 209 | "y2": "270" 210 | }, 211 | { 212 | "x1": "540", 213 | "y1": "270", 214 | "y2": "390" 215 | }, 216 | { 217 | "x1": "960", 218 | "y1": "150", 219 | "y2": "360" 220 | }, 221 | { 222 | "x1": "1320", 223 | "y1": "150", 224 | "y2": "330" 225 | }, 226 | { 227 | "x1": "1080", 228 | "y1": "270", 229 | "x2": "1320" 230 | }, 231 | { 232 | "x1": "990", 233 | "y1": "180", 234 | "y2": "330" 235 | }, 236 | { 237 | "x1": "540", 238 | "y1": "270", 239 | "x2": "690" 240 | }, 241 | { 242 | "x1": "540", 243 | "y1": "390", 244 | "x2": "720" 245 | }, 246 | { 247 | "x1": "720", 248 | "y1": "210", 249 | "x2": "960" 250 | }, 251 | { 252 | "x1": "690", 253 | "y1": "180", 254 | "x2": "990" 255 | }, 256 | { 257 | "x1": "510", 258 | "y1": "420", 259 | "x2": "1200" 260 | } 261 | ], 262 | "conpoints": [ 263 | { 264 | "x": "840", 265 | "y": "420" 266 | }, 267 | { 268 | "x": "570", 269 | "y": "420" 270 | }, 271 | { 272 | "x": "960", 273 | "y": "330" 274 | }, 275 | { 276 | "x": "960", 277 | "y": "210" 278 | }, 279 | { 280 | "x": "1320", 281 | "y": "270" 282 | }, 283 | { 284 | "x": "690", 285 | "y": "180" 286 | }, 287 | { 288 | "x": "720", 289 | "y": "330" 290 | } 291 | ], 292 | "diodes": [], 293 | "customs": [ 294 | { 295 | "x": "600", 296 | "y": "300", 297 | "direction": "0", 298 | "filename": "\"d-flipflop.json\"", 299 | "outputsInv": "[false,false,false,false,false,false]", 300 | "inputsInv": "[false,false,false,false,false,false]" 301 | }, 302 | { 303 | "x": "870", 304 | "y": "300", 305 | "direction": "0", 306 | "filename": "\"d-flipflop.json\"", 307 | "outputsInv": "[false,false,false,false,false,false]", 308 | "inputsInv": "[false,false,false,false,false,false]" 309 | }, 310 | { 311 | "x": "1230", 312 | "y": "300", 313 | "direction": "0", 314 | "filename": "\"d-flipflop.json\"", 315 | "outputsInv": "[false,false,false,false,false,false,false,false]", 316 | "inputsInv": "[false,false,false,false,false,false,false,false]" 317 | } 318 | ], 319 | "labels": [], 320 | "segDisplays": [] 321 | } 322 | -------------------------------------------------------------------------------- /views/sketches/d-flipflop.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "D-FF", 3 | "gates": [ 4 | { 5 | "x": "390", 6 | "y": "90", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[false,false]" 13 | }, 14 | { 15 | "x": "390", 16 | "y": "150", 17 | "direction": "0", 18 | "inputCount": "2", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[true,false]" 23 | }, 24 | { 25 | "x": "240", 26 | "y": "120", 27 | "direction": "0", 28 | "inputCount": "2", 29 | "outputCount": "1", 30 | "logicFunction": "\"and\"", 31 | "outputsInv": "[false]", 32 | "inputsInv": "[true,false]" 33 | } 34 | ], 35 | "outputs": [ 36 | { 37 | "x": "600", 38 | "y": "150", 39 | "colr": "0", 40 | "lbl": "Q" 41 | }, 42 | { 43 | "x": "600", 44 | "y": "180", 45 | "colr": "0", 46 | "lbl": "Q̅" 47 | } 48 | ], 49 | "inputs": [ 50 | { 51 | "x": "345", 52 | "y": "75", 53 | "lbl": "D", 54 | "framecount": "-1", 55 | "clock": "false" 56 | }, 57 | { 58 | "x": "75", 59 | "y": "135", 60 | "lbl": ">", 61 | "framecount": "-1", 62 | "clock": "false" 63 | } 64 | ], 65 | "segments": [], 66 | "wires": [ 67 | { 68 | "x1": "570", 69 | "y1": "150", 70 | "x2": "600" 71 | }, 72 | { 73 | "x1": "570", 74 | "y1": "180", 75 | "x2": "600" 76 | }, 77 | { 78 | "x1": "480", 79 | "y1": "150", 80 | "x2": "510" 81 | }, 82 | { 83 | "x1": "480", 84 | "y1": "120", 85 | "y2": "150" 86 | }, 87 | { 88 | "x1": "450", 89 | "y1": "120", 90 | "x2": "480" 91 | }, 92 | { 93 | "x1": "360", 94 | "y1": "120", 95 | "x2": "390" 96 | }, 97 | { 98 | "x1": "360", 99 | "y1": "180", 100 | "x2": "390" 101 | }, 102 | { 103 | "x1": "210", 104 | "y1": "150", 105 | "x2": "240" 106 | }, 107 | { 108 | "x1": "120", 109 | "y1": "150", 110 | "y2": "180" 111 | }, 112 | { 113 | "x1": "450", 114 | "y1": "180", 115 | "x2": "510" 116 | }, 117 | { 118 | "x1": "330", 119 | "y1": "210", 120 | "x2": "390" 121 | }, 122 | { 123 | "x1": "330", 124 | "y1": "150", 125 | "y2": "210" 126 | }, 127 | { 128 | "x1": "90", 129 | "y1": "150", 130 | "x2": "150" 131 | }, 132 | { 133 | "x1": "300", 134 | "y1": "150", 135 | "x2": "390" 136 | }, 137 | { 138 | "x1": "360", 139 | "y1": "90", 140 | "y2": "180" 141 | }, 142 | { 143 | "x1": "120", 144 | "y1": "180", 145 | "x2": "240" 146 | } 147 | ], 148 | "conpoints": [ 149 | { 150 | "x": "360", 151 | "y": "120" 152 | }, 153 | { 154 | "x": "330", 155 | "y": "150" 156 | }, 157 | { 158 | "x": "120", 159 | "y": "150" 160 | } 161 | ], 162 | "diodes": [], 163 | "customs": [ 164 | { 165 | "x": "510", 166 | "y": "120", 167 | "direction": "0", 168 | "filename": "\"rs-flipflop.json\"", 169 | "outputsInv": "[]", 170 | "inputsInv": "[]" 171 | }, 172 | { 173 | "x": "150", 174 | "y": "120", 175 | "direction": "0", 176 | "filename": "\"3-buffer.json\"", 177 | "outputsInv": "[]", 178 | "inputsInv": "[]" 179 | } 180 | ], 181 | "labels": [ 182 | { 183 | "x": "90", 184 | "y": "270", 185 | "txt": "Three delays are required" 186 | }, 187 | { 188 | "x": "90", 189 | "y": "300", 190 | "txt": "for the flipflop to permanently toggle" 191 | }, 192 | { 193 | "x": "90", 194 | "y": "30", 195 | "txt": "Implementation of a D-Flipflop" 196 | } 197 | ], 198 | "segDisplays": [] 199 | } 200 | -------------------------------------------------------------------------------- /views/sketches/full_add.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "FA", 3 | "gates": [ 4 | { 5 | "x": "1080", 6 | "y": "270", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"or\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[false,false]" 13 | } 14 | ], 15 | "outputs": [ 16 | { 17 | "x": "1170", 18 | "y": "300", 19 | "colr": "0", 20 | "lbl": "C" 21 | }, 22 | { 23 | "x": "1170", 24 | "y": "360", 25 | "colr": "0", 26 | "lbl": "S" 27 | } 28 | ], 29 | "inputs": [ 30 | { 31 | "x": "855", 32 | "y": "345", 33 | "framecount": "0", 34 | "clock": "false", 35 | "lbl": "A" 36 | }, 37 | { 38 | "x": "855", 39 | "y": "315", 40 | "framecount": "0", 41 | "clock": "false", 42 | "lbl": "B" 43 | }, 44 | { 45 | "x": "855", 46 | "y": "285", 47 | "framecount": "0", 48 | "clock": "false", 49 | "lbl": "C" 50 | } 51 | ], 52 | "segments": [], 53 | "wires": [ 54 | { 55 | "x1": "1050", 56 | "y1": "330", 57 | "x2": "1080" 58 | }, 59 | { 60 | "x1": "960", 61 | "y1": "330", 62 | "x2": "990" 63 | }, 64 | { 65 | "x1": "870", 66 | "y1": "330", 67 | "x2": "900" 68 | }, 69 | { 70 | "x1": "870", 71 | "y1": "300", 72 | "x2": "900" 73 | }, 74 | { 75 | "x1": "1140", 76 | "y1": "300", 77 | "x2": "1170" 78 | }, 79 | { 80 | "x1": "960", 81 | "y1": "300", 82 | "x2": "1080" 83 | }, 84 | { 85 | "x1": "870", 86 | "y1": "360", 87 | "x2": "990" 88 | }, 89 | { 90 | "x1": "1050", 91 | "y1": "360", 92 | "x2": "1170" 93 | } 94 | ], 95 | "conpoints": [], 96 | "diodes": [], 97 | "customs": [ 98 | { 99 | "x": "900", 100 | "y": "270", 101 | "direction": "0", 102 | "filename": "\"half_add.json\"", 103 | "outputsInv": "[false,false]", 104 | "inputsInv": "[false,false]" 105 | }, 106 | { 107 | "x": "990", 108 | "y": "300", 109 | "direction": "0", 110 | "filename": "\"half_add.json\"", 111 | "outputsInv": "[false,false]", 112 | "inputsInv": "[false,false]" 113 | } 114 | ], 115 | "labels": [], 116 | "segDisplays": [] 117 | } 118 | -------------------------------------------------------------------------------- /views/sketches/half_add.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "HA", 3 | "gates": [ 4 | { 5 | "x": "810", 6 | "y": "240", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[false]", 12 | "inputsInv": "[false,false]" 13 | }, 14 | { 15 | "x": "810", 16 | "y": "300", 17 | "direction": "0", 18 | "inputCount": "2", 19 | "outputCount": "1", 20 | "logicFunction": "\"xor\"", 21 | "outputsInv": "[false]", 22 | "inputsInv": "[false,false]" 23 | } 24 | ], 25 | "outputs": [ 26 | { 27 | "x": "930", 28 | "y": "270", 29 | "colr": "0", 30 | "lbl": "C" 31 | }, 32 | { 33 | "x": "930", 34 | "y": "330", 35 | "colr": "0", 36 | "lbl": "S" 37 | } 38 | ], 39 | "inputs": [ 40 | { 41 | "x": "705", 42 | "y": "255", 43 | "framecount": "0", 44 | "clock": "false", 45 | "lbl": "A" 46 | }, 47 | { 48 | "x": "705", 49 | "y": "285", 50 | "framecount": "0", 51 | "clock": "false", 52 | "lbl": "B" 53 | } 54 | ], 55 | "segments": [], 56 | "wires": [ 57 | { 58 | "x1": "780", 59 | "y1": "330", 60 | "x2": "810" 61 | }, 62 | { 63 | "x1": "780", 64 | "y1": "270", 65 | "y2": "330" 66 | }, 67 | { 68 | "x1": "750", 69 | "y1": "300", 70 | "y2": "360" 71 | }, 72 | { 73 | "x1": "750", 74 | "y1": "360", 75 | "x2": "810" 76 | }, 77 | { 78 | "x1": "870", 79 | "y1": "330", 80 | "x2": "930" 81 | }, 82 | { 83 | "x1": "870", 84 | "y1": "270", 85 | "x2": "930" 86 | }, 87 | { 88 | "x1": "720", 89 | "y1": "270", 90 | "x2": "810" 91 | }, 92 | { 93 | "x1": "720", 94 | "y1": "300", 95 | "x2": "810" 96 | } 97 | ], 98 | "conpoints": [ 99 | { 100 | "x": "780", 101 | "y": "270" 102 | }, 103 | { 104 | "x": "750", 105 | "y": "300" 106 | } 107 | ], 108 | "diodes": [], 109 | "customs": [], 110 | "labels": [], 111 | "segDisplays": [] 112 | } 113 | -------------------------------------------------------------------------------- /views/sketches/inverter.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "NOT", 3 | "gates": [ 4 | { 5 | "x": "690", 6 | "y": "300", 7 | "direction": "0", 8 | "inputCount": "2", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "caption": "\"&\"", 12 | "outputsInv": "[true]", 13 | "inputsInv": "[false,false]" 14 | } 15 | ], 16 | "outputs": [ 17 | { 18 | "x": "840", 19 | "y": "330", 20 | "colr": "0" 21 | } 22 | ], 23 | "inputs": [ 24 | { 25 | "x": "525", 26 | "y": "315", 27 | "framecount": "-1", 28 | "clock": "false" 29 | } 30 | ], 31 | "segments": [], 32 | "wires": [ 33 | { 34 | "x1": "630", 35 | "y1": "330", 36 | "x2": "630", 37 | "y2": "360" 38 | }, 39 | { 40 | "x1": "630", 41 | "y1": "360", 42 | "x2": "690", 43 | "y2": "360" 44 | }, 45 | { 46 | "x1": "750", 47 | "y1": "330", 48 | "x2": "840", 49 | "y2": "330" 50 | }, 51 | { 52 | "x1": "540", 53 | "y1": "330", 54 | "x2": "690", 55 | "y2": "330" 56 | } 57 | ], 58 | "conpoints": [ 59 | { 60 | "x": "630", 61 | "y": "330" 62 | } 63 | ], 64 | "diodes": [], 65 | "customs": [] 66 | } 67 | -------------------------------------------------------------------------------- /views/sketches/jk-flipflop.json: -------------------------------------------------------------------------------- 1 | {"caption":"JK-FF","gates":[{"x":"480","y":"180","direction":"0","inputCount":"3","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false,false]"},{"x":"480","y":"300","direction":"0","inputCount":"3","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false,false]"},{"x":"330","y":"270","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[true,false]"}],"outputs":[{"x":"930","y":"210","colr":"0","lbl":"Q"},{"x":"930","y":"330","colr":"0","lbl":"Q̅"}],"inputs":[{"x":"255","y":"195","lbl":"J","framecount":"-1","clock":"false"},{"x":"75","y":"285","lbl":">","framecount":"0","clock":"true","speed":"30"},{"x":"255","y":"375","lbl":"K","framecount":"-1","clock":"false"}],"wires":[{"x1":"780","y1":"330","x2":"930"},{"x1":"780","y1":"300","y2":"330"},{"x1":"810","y1":"210","x2":"930"},{"x1":"420","y1":"180","x2":"750"},{"x1":"540","y1":"210","x2":"570"},{"x1":"540","y1":"330","x2":"570"},{"x1":"570","y1":"300","y2":"330"},{"x1":"450","y1":"240","x2":"480"},{"x1":"450","y1":"240","y2":"330"},{"x1":"450","y1":"330","x2":"480"},{"x1":"270","y1":"390","x2":"480"},{"x1":"270","y1":"210","x2":"480"},{"x1":"450","y1":"420","x2":"810"},{"x1":"420","y1":"180","y2":"270"},{"x1":"810","y1":"210","y2":"420"},{"x1":"420","y1":"270","x2":"480"},{"x1":"450","y1":"360","y2":"420"},{"x1":"450","y1":"360","x2":"480"},{"x1":"570","y1":"270","x2":"660"},{"x1":"570","y1":"210","y2":"270"},{"x1":"570","y1":"300","x2":"660"},{"x1":"720","y1":"270","x2":"810"},{"x1":"720","y1":"300","x2":"780"},{"x1":"750","y1":"180","y2":"300"},{"x1":"210","y1":"300","x2":"240"},{"x1":"300","y1":"300","x2":"330"},{"x1":"120","y1":"330","x2":"330"},{"x1":"390","y1":"300","x2":"450"},{"x1":"120","y1":"300","y2":"330"},{"x1":"90","y1":"300","x2":"150"}],"conpoints":[{"x":"750","y":"300"},{"x":"810","y":"270"},{"x":"450","y":"300"},{"x":"120","y":"300"}],"diodes":[],"customs":[{"x":"660","y":"240","direction":"0","filename":"\"rs-flipflop.json\"","outputsInv":"[]","inputsInv":"[]"},{"x":"240","y":"270","direction":"0","filename":"\"1-buffer.json\"","outputsInv":"[]","inputsInv":"[]"},{"x":"150","y":"270","direction":"0","filename":"\"1-buffer.json\"","outputsInv":"[]","inputsInv":"[]"}],"labels":[{"x":"990","y":"210","txt":"Q"},{"x":"990","y":"330","txt":"not Q"},{"x":"180","y":"210","txt":"J"},{"x":"180","y":"390","txt":"K"},{"x":"0","y":"300","txt":"Clk"}],"segDisplays":[]} -------------------------------------------------------------------------------- /views/sketches/not-gate.json: -------------------------------------------------------------------------------- 1 | {"caption":"NOT","gates":[{"x":"510","y":"150","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[true]","inputsInv":"[false,false]"}],"outputs":[{"x":"660","y":"180","colr":"0","lbl":"1"}],"inputs":[{"x":"405","y":"165","framecount":"-1","clock":"false"}],"wires":[{"x1":"420","y1":"180","x2":"510"},{"x1":"450","y1":"210","x2":"510"},{"x1":"450","y1":"180","y2":"210"},{"x1":"570","y1":"180","x2":"660"}],"conpoints":[{"x":"450","y":"180"}],"diodes":[],"customs":[],"labels":[],"segDisplays":[]} -------------------------------------------------------------------------------- /views/sketches/rs-clocked.json: -------------------------------------------------------------------------------- 1 | {"caption":"RS-FF","gates":[{"x":"510","y":"270","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"510","y":"360","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"}],"outputs":[{"x":"870","y":"330","colr":"0","lbl":"Q"},{"x":"870","y":"360","colr":"0","lbl":"Q̅"}],"inputs":[{"x":"375","y":"285","lbl":"S","framecount":"-1","clock":"false"},{"x":"375","y":"345","lbl":">","framecount":"0","clock":"true","speed":"30"},{"x":"375","y":"405","lbl":"R","framecount":"-1","clock":"false"}],"wires":[{"x1":"570","y1":"390","x2":"660"},{"x1":"660","y1":"360","y2":"390"},{"x1":"660","y1":"360","x2":"720"},{"x1":"660","y1":"330","x2":"720"},{"x1":"660","y1":"300","y2":"330"},{"x1":"570","y1":"300","x2":"660"},{"x1":"480","y1":"330","x2":"510"},{"x1":"480","y1":"330","y2":"390"},{"x1":"480","y1":"390","x2":"510"},{"x1":"390","y1":"360","x2":"480"},{"x1":"390","y1":"420","x2":"510"},{"x1":"390","y1":"300","x2":"510"},{"x1":"780","y1":"330","x2":"870"},{"x1":"780","y1":"360","x2":"870"}],"conpoints":[{"x":"480","y":"360"}],"diodes":[],"customs":[{"x":"720","y":"300","direction":"0","filename":"\"rs-flipflop.json\"","outputsInv":"[]","inputsInv":"[]"}],"labels":[{"x":"300","y":"300","txt":"R"},{"x":"300","y":"420","txt":"S"},{"x":"930","y":"330","txt":"Q"},{"x":"930","y":"360","txt":"not Q"}],"segDisplays":[]} -------------------------------------------------------------------------------- /views/sketches/rs-flipflop.json: -------------------------------------------------------------------------------- 1 | { 2 | "caption": "RS-FF", 3 | "gates": [ 4 | { 5 | "x": "300", 6 | "y": "210", 7 | "direction": "0", 8 | "inputCount": "3", 9 | "outputCount": "1", 10 | "logicFunction": "\"and\"", 11 | "outputsInv": "[true]", 12 | "inputsInv": "[false,true,false]" 13 | }, 14 | { 15 | "x": "300", 16 | "y": "90", 17 | "direction": "0", 18 | "inputCount": "2", 19 | "outputCount": "1", 20 | "logicFunction": "\"and\"", 21 | "outputsInv": "[true]", 22 | "inputsInv": "[true,false]" 23 | }, 24 | { 25 | "x": "210", 26 | "y": "270", 27 | "direction": "0", 28 | "inputCount": "1", 29 | "outputCount": "1", 30 | "logicFunction": "\"and\"", 31 | "outputsInv": "[false]", 32 | "inputsInv": "[false]" 33 | }, 34 | { 35 | "x": "420", 36 | "y": "90", 37 | "direction": "0", 38 | "inputCount": "1", 39 | "outputCount": "1", 40 | "logicFunction": "\"and\"", 41 | "outputsInv": "[false]", 42 | "inputsInv": "[false]" 43 | }, 44 | { 45 | "x": "510", 46 | "y": "90", 47 | "direction": "0", 48 | "inputCount": "2", 49 | "outputCount": "1", 50 | "logicFunction": "\"and\"", 51 | "outputsInv": "[false]", 52 | "inputsInv": "[false,false]" 53 | } 54 | ], 55 | "outputs": [ 56 | { 57 | "x": "630", 58 | "y": "120", 59 | "colr": "0", 60 | "lbl": "Q" 61 | }, 62 | { 63 | "x": "630", 64 | "y": "240", 65 | "colr": "0", 66 | "lbl": "Q̅" 67 | } 68 | ], 69 | "inputs": [ 70 | { 71 | "x": "135", 72 | "y": "105", 73 | "lbl": "S", 74 | "framecount": "-1", 75 | "clock": "false" 76 | }, 77 | { 78 | "x": "135", 79 | "y": "255", 80 | "lbl": "R", 81 | "framecount": "-1", 82 | "clock": "false" 83 | } 84 | ], 85 | "segments": [], 86 | "wires": [ 87 | { 88 | "x1": "270", 89 | "y1": "300", 90 | "x2": "300" 91 | }, 92 | { 93 | "x1": "270", 94 | "y1": "240", 95 | "x2": "300" 96 | }, 97 | { 98 | "x1": "270", 99 | "y1": "210", 100 | "y2": "240" 101 | }, 102 | { 103 | "x1": "180", 104 | "y1": "300", 105 | "x2": "210" 106 | }, 107 | { 108 | "x1": "390", 109 | "y1": "120", 110 | "y2": "150" 111 | }, 112 | { 113 | "x1": "480", 114 | "y1": "120", 115 | "x2": "510" 116 | }, 117 | { 118 | "x1": "270", 119 | "y1": "150", 120 | "x2": "300" 121 | }, 122 | { 123 | "x1": "270", 124 | "y1": "150", 125 | "y2": "180" 126 | }, 127 | { 128 | "x1": "420", 129 | "y1": "150", 130 | "y2": "210" 131 | }, 132 | { 133 | "x1": "360", 134 | "y1": "120", 135 | "x2": "420" 136 | }, 137 | { 138 | "x1": "570", 139 | "y1": "120", 140 | "x2": "630" 141 | }, 142 | { 143 | "x1": "480", 144 | "y1": "180", 145 | "y2": "240" 146 | }, 147 | { 148 | "x1": "180", 149 | "y1": "210", 150 | "y2": "300" 151 | }, 152 | { 153 | "x1": "390", 154 | "y1": "150", 155 | "x2": "510" 156 | }, 157 | { 158 | "x1": "150", 159 | "y1": "270", 160 | "x2": "300" 161 | }, 162 | { 163 | "x1": "180", 164 | "y1": "210", 165 | "x2": "420" 166 | }, 167 | { 168 | "x1": "150", 169 | "y1": "120", 170 | "x2": "300" 171 | }, 172 | { 173 | "x1": "270", 174 | "y1": "180", 175 | "x2": "480" 176 | }, 177 | { 178 | "x1": "360", 179 | "y1": "240", 180 | "x2": "630" 181 | } 182 | ], 183 | "conpoints": [ 184 | { 185 | "x": "270", 186 | "y": "210" 187 | }, 188 | { 189 | "x": "390", 190 | "y": "120" 191 | }, 192 | { 193 | "x": "420", 194 | "y": "150" 195 | }, 196 | { 197 | "x": "480", 198 | "y": "240" 199 | } 200 | ], 201 | "diodes": [], 202 | "customs": [], 203 | "labels": [ 204 | { 205 | "x": "60", 206 | "y": "60", 207 | "txt": "Asynchonous RS-Flipflop with no forbidden state" 208 | }, 209 | { 210 | "x": "60", 211 | "y": "120", 212 | "txt": "S" 213 | }, 214 | { 215 | "x": "60", 216 | "y": "270", 217 | "txt": "R" 218 | }, 219 | { 220 | "x": "690", 221 | "y": "120", 222 | "txt": "Q" 223 | }, 224 | { 225 | "x": "690", 226 | "y": "240", 227 | "txt": "not Q" 228 | } 229 | ], 230 | "segDisplays": [] 231 | } 232 | -------------------------------------------------------------------------------- /views/sketches/t-flipflop.json: -------------------------------------------------------------------------------- 1 | {"caption":"T-FF","gates":[{"x":"690","y":"180","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"690","y":"300","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[false,false]"},{"x":"450","y":"240","direction":"0","inputCount":"2","outputCount":"1","logicFunction":"\"and\"","outputsInv":"[false]","inputsInv":"[true,false]"}],"outputs":[{"x":"1080","y":"240","colr":"0","lbl":"Q"},{"x":"1080","y":"270","colr":"0","lbl":"Q̅"}],"inputs":[{"x":"615","y":"225","lbl":"T","framecount":"-1","clock":"false"},{"x":"195","y":"255","lbl":">","framecount":"0","clock":"true","speed":"30"}],"wires":[{"x1":"240","y1":"270","y2":"300"},{"x1":"240","y1":"300","x2":"450"},{"x1":"210","y1":"270","x2":"270"},{"x1":"330","y1":"270","x2":"360"},{"x1":"420","y1":"270","x2":"450"},{"x1":"990","y1":"180","y2":"270"},{"x1":"960","y1":"240","y2":"390"},{"x1":"510","y1":"270","x2":"870"},{"x1":"630","y1":"240","x2":"690"},{"x1":"660","y1":"240","y2":"330"},{"x1":"660","y1":"330","x2":"690"},{"x1":"660","y1":"360","y2":"390"},{"x1":"660","y1":"360","x2":"690"},{"x1":"660","y1":"390","x2":"960"},{"x1":"930","y1":"270","x2":"1080"},{"x1":"660","y1":"210","x2":"690"},{"x1":"660","y1":"180","y2":"210"},{"x1":"660","y1":"180","x2":"990"},{"x1":"930","y1":"240","x2":"1080"},{"x1":"750","y1":"210","x2":"810"},{"x1":"810","y1":"210","y2":"240"},{"x1":"810","y1":"240","x2":"870"},{"x1":"810","y1":"300","x2":"870"},{"x1":"810","y1":"300","y2":"330"},{"x1":"750","y1":"330","x2":"810"}],"conpoints":[{"x":"960","y":"240"},{"x":"990","y":"270"},{"x":"660","y":"240"},{"x":"240","y":"270"}],"diodes":[],"customs":[{"x":"870","y":"210","direction":"0","filename":"\"rs-clocked.json\"","outputsInv":"[false,false]","inputsInv":"[]"},{"x":"360","y":"240","direction":"0","filename":"\"1-buffer.json\"","outputsInv":"[]","inputsInv":"[]"},{"x":"270","y":"240","direction":"0","filename":"\"1-buffer.json\"","outputsInv":"[]","inputsInv":"[]"}],"labels":[{"x":"540","y":"240","txt":"T"},{"x":"120","y":"270","txt":"Clk"}],"segDisplays":[]} --------------------------------------------------------------------------------