plottoriffic/index.js

166 lines
4.8 KiB
JavaScript
Raw Normal View History

2017-07-31 23:49:10 -05:00
'use strict'
const seedrandom = require('seedrandom');
const plotto = require("./data/plotto.json");
2017-08-02 23:08:17 +00:00
function regEscape(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
2017-07-31 23:49:10 -05:00
function pick(rng, arr) {
2017-08-02 23:08:17 +00:00
if(!arr) {
return null;
}
if(arr.length == 0)
return null;
if(arr.length == 1)
return arr[0];
2017-07-31 23:49:10 -05:00
let min = 0;
let max = arr.length;
2017-08-02 23:08:17 +00:00
let i =Math.floor(rng() * (max - min)) + min;
let ret = arr[i];
//console.log(i, ':', JSON.stringify(ret), '!!!!', JSON.stringify(arr));
return ret;
2017-07-31 23:49:10 -05:00
}
class PlotGenerator {
2017-08-02 23:08:17 +00:00
constructor({ seed=null, flipGenders=undefined } = {}) {
//seedrandom doesn't expose the seed used, so generate one here
this._seed = seed || seedrandom()();
this._rng = seedrandom(this._seed);
2017-07-31 23:49:10 -05:00
if(flipGenders === undefined) {
this._flipGenders = this._rng() < 0.5; //50% chance true/false
} else {
this._flipGenders = flipGenders;
}
}
get seed() { return this._seed; }
2017-07-31 23:49:10 -05:00
get flipGenders() { return this._flipGenders; }
set flipGenders(flip) { this._flipGenders = flip; }
generate() {
2017-08-02 23:08:17 +00:00
let rootTransform = {};
if(this._flipGenders) {
rootTransform = {
"A" : "B",
"A-2": "B-2",
"A-3": "B-3",
"A-4": "B-4",
"A-5": "B-5",
"A-6": "B-6",
"A-7": "B-7",
"A-8": "B-8",
"A-9": "B-9",
"B" : "A",
"B-2": "A-2",
"B-3": "A-3",
"B-4": "A-4",
"B-5": "A-5",
"B-6": "A-6",
"B-7": "A-7",
"B-8": "A-8",
"B-9": "A-9"
};
}
2017-07-31 23:49:10 -05:00
2017-08-02 23:08:17 +00:00
let preamble = pick(this._rng, plotto.masterClauseA);
let resolution = pick(this._rng, plotto.masterClauseC);
let masterPlot = pick(this._rng, plotto.masterClauseB);
let subject = [masterPlot.group, ' / ', masterPlot.subgroup, ': ', masterPlot.description].join('');
let conflict = plotto.conflicts[pick(this._rng, masterPlot.nodes)];
2017-07-31 23:49:10 -05:00
return [
2017-08-02 23:08:17 +00:00
subject,
preamble,
this._expand(conflict, rootTransform, {leadIns:1, carryOns:1}).replace(/\*/g, ''),
2017-08-02 23:08:17 +00:00
resolution
].join('\n\n').trim();
2017-07-31 23:49:10 -05:00
}
2017-08-02 23:08:17 +00:00
_expand(item, transform, ctx, start, end) {
let ret = [];
if(!item)
return 'NULL';
if(ctx.leadIns > 0 && item.leadIns) {
ctx.leadIns -= 1;
ret.push(this._expand(item.leadIns, null, ctx));
}
let carryon = null;
if(ctx.carryOns > 0 && item.carryOns) {
ctx.carryOns -= 1;
carryon = this._expand(item.carryOns, transform, ctx);
}
if(typeof(item) == "string") {
ret.push(this._expand(plotto.conflicts[item], null, ctx));
} else if(Array.isArray(item)) {
ret.push(this._expand(pick(this._rng, item), null, ctx));
} else if(item.conflictid) {
ret.push(item.description);
} else if(item.v) {
if(item.start || item.end) {
ret.push(this._expand(plotto.conflicts[item.v], item.tfm, ctx, item.start, item.end));
} else if(item.op == '+') {
for(let sub of item.v) {
ret.push(this._expand(sub, item.tfm, ctx));
}
} else {
ret.push(this._expand(item.v, item.tfm, ctx));
}
}
if(carryon) {
ret.push(carryon);
}
let str = ret.join('\n\n').trim();
if(transform) {
let ks = Object.keys(transform);
if(ks.length > 0) {
let pattern = '\\b(?:' + ks.map(function(s) {
return '(?:' + regEscape(s) + ')';
}).join('|') + ')(?=^|$| |,|\\.)';
let rg = new RegExp(pattern, 'g');
let cmp = {
before: str,
transform: transform
};
str = str.replace(rg,function(match) {
if(!match || match.length == 0)
return '';
let t = transform[match];
if(!t) {
console.log('Could not replace match in template: ' + match);
return match;
}
return t;
});
cmp.after = str;
//console.log(cmp);
}
}
return str;
2017-07-31 23:49:10 -05:00
}
}
module.exports = PlotGenerator;