<commit_before>var fs = require('fs');
var markov = require('markov');

/* This bot is based on a simple Markov chain.
 * https://github.com/substack/node-markov
 */
var method = MarkovBot.prototype;

function MarkovBot(room, parent = null) {
    this.room = room;
	this.parent = parent;

    this.markov = markov(Math.floor(Math.random() * 5));

    var seed = fs.createReadStream(__dirname + '/statements.txt');
    this.markov.seed(seed);

    this.lastResponded = new Date().getTime();
    this.cooldownDelay = 6000; // milliseconds
}

// Send a message to the bot. The sender is optional.
method.send = function(message, sender) {
    // Don't respond if it's too soon after the last response.
    var now = new Date().getTime();
    if ((now-this.lastResponded) > this.cooldownDelay) {
        var key = this.markov.search(message);
				var name;
				if(this.parent != null) {
					name = this.parent;
				}
				else {
					name = this;
				}
        if (message.toLowerCase().includes(this.room.getPlayerName(name).toLowerCase())) {
            this.respondWithProbability(message, 0.95);
        } else if (typeof key !== undefined) {
            // If there's a key, the Markov chain hopefully has a better response.
            return this.respondWithProbability(message, 0.6);
        } else {
            return this.respondWithProbability(message, 0.3);
        }
    }
}

method.respondWithProbability = function(message, probability) {
    if (Math.random() < probability) {
        this.lastResponded = new Date().getTime();
        var timeout = 1000 + Math.random() * 4000;
        var that = this;
        setTimeout(function () {
			if(that.parent == null) {
		        that.sendResponse(message);
			}
			else {
				that.parent.chooseMess(that.markov.respond(message, 1+Math.floor(Math.random() * 9)).join(' '), null);
			}
        }, timeout);
    }
}

method.sendResponse = function(message) {
    var response = this.markov.respond(message, 1+Math.floor(Math.random() * 9)).join(' ');
    this.room.broadcast(response, this);
}<commit_msg>The Markov bot now works when statements.txt is empty.<commit_after>var fs = require('fs');
var markov = require('markov');
var request = require('request');

const STATEMENTS_FILE = __dirname + '/statements.txt';
// If STATEMENTS_FILE does not exist, we can use this high-quality content.
const DEFAULT_SEED = 'https://raw.githubusercontent.com/zanchi/random-bee-movie/master/text';

/* This bot is based on a simple Markov chain.
 * https://github.com/substack/node-markov
 */
var method = MarkovBot.prototype;

function MarkovBot(room, parent = null) {
    this.room = room;
	this.parent = parent;

    this.markov = markov(Math.floor(Math.random() * 5));

    // Add at least a minimum amount of text because the Markov library doesn't
    // like empty seeds at all.
    this.markov.seed('beep beep detective');
    // Add user-created statements to the seed.
    if (fs.existsSync(STATEMENTS_FILE)) {
        var seed = fs.createReadStream(STATEMENTS_FILE);
        this.markov.seed(seed);
    } else {
        // If the statements file does not exist, try and get a seed from online.
        var that = this;
        request.get(DEFAULT_SEED, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                that.markov.seed(body);
            }
        });
    }

    this.lastResponded = new Date().getTime();
    this.cooldownDelay = 6000; // milliseconds
}

// Send a message to the bot. The sender is optional.
method.send = function(message, sender) {
    // Don't respond if it's too soon after the last response.
    var now = new Date().getTime();
    if ((now-this.lastResponded) > this.cooldownDelay) {
        var key = this.markov.search(message);
				var name;
				if(this.parent != null) {
					name = this.parent;
				}
				else {
					name = this;
				}
        if (message.toLowerCase().includes(this.room.getPlayerName(name).toLowerCase())) {
            this.respondWithProbability(message, 0.95);
        } else if (typeof key !== undefined) {
            // If there's a key, the Markov chain hopefully has a better response.
            return this.respondWithProbability(message, 0.6);
        } else {
            return this.respondWithProbability(message, 0.3);
        }
    }
}

method.respondWithProbability = function(message, probability) {
    if (Math.random() < probability) {
        this.lastResponded = new Date().getTime();
        var timeout = 1000 + Math.random() * 4000;
        var that = this;
        setTimeout(function () {
			if(that.parent == null) {
		        that.sendResponse(message);
			}
			else {
				that.parent.chooseMess(that.markov.respond(message, 1+Math.floor(Math.random() * 9)).join(' '), null);
			}
        }, timeout);
    }
}

method.sendResponse = function(message) {
    try {
        var response = this.markov.respond(message, 1+Math.floor(Math.random() * 9)).join(' ');
        this.room.broadcast(response, this);
    } catch (error) {
        // This Markov library sometimes throws "TypeError: Cannot read property
        // 'words' of undefined". It seems to only happen when the seed is very small.
        console.error(error);
    }
}
{'fraction_non_alphanumeric': 0.13372871628084942, 'fraction_numerical': 0.009757030801607041, 'mean_word_length': 2.6790992258972555, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '724414', 'n_tokens_mistral': 1707, 'n_tokens_neox': 1547, 'n_words': 407}