From 1d15cdcb2aa463ce0aa1ab176605036cc15db2be Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Tue, 24 Oct 2023 19:23:33 -0600 Subject: [PATCH] initial turing machine --- turing-machine/css/styles.css | 90 ++++++++++++++++++++++++++++++++ turing-machine/index.html | 14 +++++ turing-machine/js/main.js | 98 +++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 turing-machine/css/styles.css create mode 100644 turing-machine/index.html create mode 100644 turing-machine/js/main.js diff --git a/turing-machine/css/styles.css b/turing-machine/css/styles.css new file mode 100644 index 0000000..02279e5 --- /dev/null +++ b/turing-machine/css/styles.css @@ -0,0 +1,90 @@ +* { + font-family: "Trebuchet MS", sans-serif; +} + +button { + background: #bbbbbb; + border: 1px solid white; + border-radius: 0.2rem; + padding: 0.2rem; +} + +button:hover { + background: #cccccc; +} + +body { + margin: 0; + background-color: #aaaaaa; +} + +.container { + display: flex; + width: 90%; + margin-left: auto; + margin-right: auto; + flex-direction: column; + + padding: 2rem; +} + +.tape { + display: flex; + + padding: 1rem; + + align-items: center; + gap: 1rem; + + height: 5rem; + max-width: 100%; + + border: 1px solid black; + + overflow-x: scroll; + overflow-y: hidden; +} + +.cell { + position: relative; + height: 80%; + border: 3px solid black; + transition: border 0.1s ease-in-out; + transition: background 0.1s ease-in-out; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex: 1; + gap: 0.2rem; + + padding: 0.2rem; +} + +.circle { + position: absolute; + bottom: -15px; + left: 50%; + transform: translateX(-50%); + width: 10px; + height: 10px; + background-color: wheat; + border-radius: 50%; + opacity: 0.001; + transition: opacity 0.1s ease-in-out; +} + +.cell.reading .circle { + opacity: 1; +} + +.reading { + border-color: green; + background-color: wheat; +} + +.cell-input { + width: 50px; + text-align: center; +} diff --git a/turing-machine/index.html b/turing-machine/index.html new file mode 100644 index 0000000..2f65aa3 --- /dev/null +++ b/turing-machine/index.html @@ -0,0 +1,14 @@ + + + + Turing Machine Simulator + + + +
+

Simponic's State System

+
+
+ + + diff --git a/turing-machine/js/main.js b/turing-machine/js/main.js new file mode 100644 index 0000000..68aaa39 --- /dev/null +++ b/turing-machine/js/main.js @@ -0,0 +1,98 @@ +const DISPLAY_CELLS = 15; +const TAPE_LEN = 200; + +const MESSAGES = { + SET_CELL: "SET_CELL", + PAUSE: "PAUSE", + SIMULATE: "SIMULATE", + SET_READER: "SET_READER", +}; + +class Observable { + constructor() { + this.observers = []; + } + + subscribe(f) { + this.observers.push(f); + } + + unsubscribe(f) { + this.observers = this.observers.filter((subscriber) => subscriber !== f); + } + + notify(data) { + this.observers.forEach((observer) => observer(data)); + } +} + +const state = new Observable(); + +const tape = Array(TAPE_LEN).fill(0); +state.subscribe((msg) => { + if (msg.type == MESSAGES.SET_CELL) { + tape[msg.cellId] = msg.value; + } +}); + +const tapeEl = document.getElementById("tape"); + +const inputCellId = (cellId) => `${cellId}-input`; +const updateCellButtonId = (cellId) => `${cellId}-button-update`; + +const setCellFromInput = (cellId, inputId) => { + const input = document.getElementById(inputId); + tape[cellId] = input.value; +}; + +const cell = (cellId, initValue = 0) => { + const cellDiv = document.createElement("div"); + cellDiv.classList.add("cell"); + cellDiv.id = cellId; + + const readingHead = document.createElement("div"); + readingHead.classList.add("circle"); + + const input = document.createElement("input"); + const inputId = inputCellId(cellId); + input.classList.add("cell-input"); + input.id = inputId; + input.value = initValue; + + input.addEventListener("focusin", () => + state.notify({ type: MESSAGES.PAUSE }) + ); + input.addEventListener("focusout", () => + state.notify({ type: MESSAGES.SET_CELL, cell: cellId, value: input.value }) + ); + state.subscribe((msg) => { + if (msg.type == MESSAGES.SET_CELL && msg.cell == cellId) { + input.value = msg.value; + } + if (msg.type == MESSAGES.SET_READER) { + if (msg.cell == cellId) { + cellDiv.classList.add("reading"); + cellDiv.scrollIntoView({ + behavior: "smooth", + }); + } else cellDiv.classList.remove("reading"); + } + }); + + cellDiv.appendChild(input); + cellDiv.appendChild(readingHead); + + return cellDiv; +}; + +const main = () => { + const cells = tape.map((_, cellId) => cell(cellId)); + for (const cell of cells) { + tapeEl.appendChild(cell); + } + state.notify({ type: MESSAGES.SET_READER, cell: 0 }); + + setTimeout(() => {}, 1000); +}; + +main();