134 lines
4.2 KiB
JavaScript
134 lines
4.2 KiB
JavaScript
import Model from "./Model";
|
|
|
|
class Custom extends Model {
|
|
constructor() {
|
|
super("Custom",
|
|
[["S", 0.97, "#1F85DE"], ["I", 0.03, "#de1f50"]],
|
|
[["S", "I", 0.5]],
|
|
20, 0.05);
|
|
this.state = {input: ""};
|
|
this.defaultColors = ["#0fa75f", "#ff225b", "#03aaf9", "#fffb00", "#cc0080"];
|
|
}
|
|
|
|
textFieldChanged = (e) => {
|
|
let input = e.target.value;
|
|
this.setState({input: input});
|
|
let parsedInput = this.parseInput(e.target.value);
|
|
//check if the input is correct, if yes then update
|
|
if (parsedInput == null) {
|
|
return;
|
|
}
|
|
this.rules = parsedInput.rules;
|
|
this.states = parsedInput.states;
|
|
}
|
|
|
|
parseInput(input) {
|
|
//regex for filtering valid rules (this is longer than it is complicated)
|
|
let re = /[[(]"?[\w\d]+"?,"?[\w\d]+"?,([0-9]*[.])?[0-9]+[)\]][\s\t]*|[([][([]("?[\w\d]+"?,)+"?[\w\d]+"?[\])],[([]("?[\w\d]+"?,)+"?[\w\d]+"?[\])],([0-9]*[.])?[0-9]+[\])][\s\t]*/g;
|
|
//strip spaces, tabs and newlines
|
|
input = input.replaceAll(" ", "");
|
|
input = input.replaceAll("\t", "");
|
|
input = input.replaceAll("\n", "");
|
|
|
|
let cleaned = input.match(re);
|
|
if(cleaned == null) {
|
|
return null;
|
|
}
|
|
|
|
let newStates = [];
|
|
let newRules = [];
|
|
//regex to match states
|
|
cleaned.forEach((element) => {
|
|
element = element.split(",");
|
|
//test if we have a simple or complex rule
|
|
if (element.length === 3) {
|
|
newRules.push(this.parseValidRule(element, newStates));
|
|
} else {
|
|
//check if there are an equal number of states left and right
|
|
if (element.length % 2 === 0) {
|
|
return;
|
|
}
|
|
//check if there is a split in the middle if not left != right
|
|
if (!element[((element.length - 1) / 2)].includes("(")) {
|
|
return;
|
|
}
|
|
//this rule is correct, we can continue
|
|
newRules.push(this.parseValidRule(element, newStates));
|
|
}
|
|
});
|
|
if (newRules.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
//parse states
|
|
//for (var i = 0; i < newRules.length; i++) {
|
|
//for (var j = 0; j < newRules[i].length - 1; j++) {
|
|
//let currentState = newRules[i][j];
|
|
//if (!newStates.includes(currentState)) {
|
|
//newStates.push(currentState);
|
|
//}
|
|
//}
|
|
//}
|
|
|
|
//convert states to states with distribution and color
|
|
//newStates = newStates.map((x) => [x, 1/newStates.length, "#ffffff"]);
|
|
let i = -1;
|
|
newStates = newStates.map((x) => {
|
|
i++;
|
|
if(i < 5) {
|
|
return [x, 1/newStates.length, this.defaultColors[i]];
|
|
}
|
|
return [x, 1/newStates.length, "#ffffff"];
|
|
});
|
|
|
|
|
|
return {rules: newRules, states: newStates};
|
|
}
|
|
|
|
parseValidRule(rule, newStates) {
|
|
//filter states
|
|
let subString = rule.slice(0, rule.length - 1);
|
|
|
|
//match states
|
|
let re = /[\w\d]+/g;
|
|
subString = subString.map((x) => x.match(re)[0]);
|
|
//match probability
|
|
re = /([0-9]*[.])?[0-9]+/g
|
|
let probability = rule[rule.length - 1].match(re);
|
|
//add states
|
|
subString.forEach((e) => {
|
|
if(!newStates.includes(e)) {
|
|
newStates.push(e);
|
|
}
|
|
})
|
|
//spontaneous rule
|
|
if(subString.length === 2) {
|
|
return [...subString, Number(probability)];
|
|
}
|
|
//complex (edge) rule
|
|
let leftSide = [subString.slice(0, subString.length / 2)];
|
|
let rightSide = [subString.slice(subString.length / 2, subString.length)];
|
|
let out = [leftSide, rightSide, Number(probability)];
|
|
return out;
|
|
//let out = [0,0,0];
|
|
//out[0] = (leftSide);
|
|
//out[1] = (rightSide);
|
|
//out[2] = (Number(probability));
|
|
//return out;
|
|
}
|
|
|
|
//override render
|
|
render() {
|
|
return(<div>
|
|
<h3>Enter the rules like: <code>("S","I",0.1), (("I","S"),("I","I"),0.3)</code></h3>
|
|
<textarea className="CustomInput CustomModel" type="text" onChange={this.textFieldChanged}
|
|
value={this.state.input} required pattern="[[(]'?[\w\d]+'?,'?[\w\d]+'?,([0-9]*[.])?[0-9]+[)\]][\s\t]*|[([][([]('?[\w\d]+'?,)+'?[\w\d]+'?[\])],[([]('?[\w\d]+'?,)+'?[\w\d]+'?[\])],([0-9]*[.])?[0-9]+[\])][\s\t]*"
|
|
placeholder='("S","I",0.1), (("I","S"),("I","I"),0.3)'/>
|
|
<h3 id="selectDistributionHeader">Initial Distribution</h3>
|
|
{this.buildSlidersDistribution()}
|
|
</div>);
|
|
}
|
|
}
|
|
|
|
export default Custom;
|