Virtual Abacus

by wio_dude

HTML

<div id="root"></div>

JavaScript

function svgElem(name) {
  return document.createElementNS('http://www.w3.org/2000/svg', name);
}



const root = document.getElementById('root');

class AbacusColumn {
  #high;
  #low;

  constructor() {
    this.#high = [0];
    this.#low = [0, 0, 0, 0];
  }

  get high() {
    return this.#high;
  }

  get low() {
    return this.#low;
  }

  set value(n) {
    if (n < 0 || n > 9) {
      throw new Error(`Value ${n} too high, must be 0-9`);
    }
    if (n >= 5) {
      this.#high = [1];
      this.#low = [0, 0, 0, 0];
      for (let i = 0; i < n - 5; i++) {
      	this.#low[i] = 1;
      }
    } else {
    	this.#high = [0];
      this.#low = [0, 0, 0, 0];
      for (let i = 0; i < n; i++) {
      	this.#low[i] = 1;
      }
    }
  }

  get value() {
  	const high = this.#high[0] > 0.5 ? 1 : 0;
    let low = 0;
    for (let i = 0; i < 4; i++) {
    	if (this.#low[i] > 0.5) {
      	low += 1;
      } else {
      	break;
      }
    }
    return high * 5 + low;
  }
  
  setBead(high, index, value) {
  	if (high) {
    	this.#high[index] = value;
    } else {
    	this.#low[index] = value;
    }
  }

  toJSON() {
    return [this.#high, this.#low];
  }
}

class Abacus {
  #columns;
  #selectedColumnIndex;

  constructor() {
    this.#columns = [];
    for (let i = 0; i < 16; i++) {
      this.#columns.push(new AbacusColumn());
    }
  }
  
  set selectedColumnIndex(n) {
  	this.#selectedColumnIndex = n;
  }

  set value(n) {
    let remaining = n;
    for (let i = 0; i < this.#columns.length; i++) {
      const digit = remaining % 10;
      this.#columns[i].value = digit;
      remaining = (remaining - digit) / 10;
    }
  }

  get value() {
    let total = 0;
    let magnitude = 1;
    for (let i = 0; i < this.#columns.length; i++) {
      total += magnitude * this.#columns[i].value;
      magnitude *= 10;
    }
    return total;
  }
  
  setBead(column, high, bead, value) {
    this.#columns[column].setBead(high, bead, value);
  }

  toJSON() {
    return...