Markov Chain Implementation

A simple class-based markov chain thingy

by asemahle

HTML

<link 
  rel="stylesheet" 
  href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" 
  integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" 
  crossorigin="anonymous">
<script
  src="https://code.jquery.com/jquery-3.3.1.min.js"
  integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
  crossorigin="anonymous"></script>
  
  
<div class="container">
    <div class="content">
        <h1>Markov Seuss</h1>
        <pre id="text">
         
        </pre>

        <div class="input-group"> 
          <label for="order">Order: </label>
          <input type="number" value="5" min="0" step="1" id="order" />
        </div>

        <div class="btn-group" role="group" >
            <button id="btn-generate" type="button" class="btn btn-default">Regenerate!</button>
        </div>

    </div>
</div>

JavaScript

class MarkovChain {
  
  constructor(map, beginnings, order) {
  	this.map = map;
    this.beginnings = beginnings;
    this.order = order;
    this.state = '';
    this.endOfChain = false;
  }
  
  init() {
  	this.state = this.chooseFrom(this.beginnings);
    this.endOfChain = false;
  }
  
  step() {
  	let previousLetters = this.state.substr(this.state.length - this.order)
  	let pool = this.map[previousLetters];
    if (pool) {
      this.state += this.chooseFrom(pool); 
    } else {
      this.endOfChain = true;
    }
  }
  
  chooseFrom(arr) {
  	return arr[Math.floor(Math.random() * arr.length)];
  }
}

class MarkovFactory {
	static build(input, order) {
  	let map = {};
    let beginnings = [];
    for(let i = order; i < input.length; i++) {
    	let prev = input.substr(i - order, order);
      let curr = input[i];
      if (!map[prev]) {
      	map[prev] = [];
      }
      beginnings.push(prev);
      map[prev].push(curr);
    }
    
    return new MarkovChain(map, beginnings, order);
  }
}

class ChainRunner {
	constructor(chain) {
  	this.markovChain = chain;
  }
  
  runToLength(len) {
		this.markovChain.init();
    for (let i = 0; i < len; i++) {
    	this.markovChain.step();
      if (this.markovChain.endOfChain) {
      	break;
      }
    }
    return this.markovChain.state;
  }
}

class Runner {

	init() {
  	$.ajaxSetup({async:false});
  	this.sourceText = $.get('https://raw.githubusercontent.com/robertsdionne/rwet/master/hw2/drseuss.txt').responseText;
  }
	
  run() {
  	let order = $('#order').val();
  	let chain = MarkovFactory.build(this.sourceText, order);
    let chainRunner = new ChainRunner(chain);
    let result = chainRunner.runToLength(500);
    $('#text').text(result);
  }
}

let runner = new Runner();
runner.init();
runner.run();

$('#btn-generate').on('click', () => { runner.run() });