diff options
author | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-10-24 19:23:33 -0600 |
---|---|---|
committer | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-10-24 19:23:33 -0600 |
commit | 1d15cdcb2aa463ce0aa1ab176605036cc15db2be (patch) | |
tree | 544224007471f43a52994dc41aa7adb831557a0d /turing-machine/js/main.js | |
parent | 22258746502640c8b48b94f9f6dc10edfd5a7073 (diff) | |
download | simponic.xyz-1d15cdcb2aa463ce0aa1ab176605036cc15db2be.tar.gz simponic.xyz-1d15cdcb2aa463ce0aa1ab176605036cc15db2be.zip |
initial turing machine
Diffstat (limited to 'turing-machine/js/main.js')
-rw-r--r-- | turing-machine/js/main.js | 98 |
1 files changed, 98 insertions, 0 deletions
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(); |