我的任务是在我们的网站上制作一些选项取决于已完成任务的先决条件。
现在我使用字符串先决条件存储对象。例如:
Task1 = {...};
Task2 = {preq:'Task1', ...}
因此,我可以轻松检查Task2仅在Task1完成时可用。
问题是任务变得越来越复杂,我需要允许AND / OR逻辑。理想情况下,我可以使用诸如
之类的表达式Task4 = {prereq:'(Task1&Task2)|Task3}, ...}
如果任务1和2已完成或任务3已完成,将使task4可用。
我不确定最好的方法。我觉得我可能需要一个解析器或类似的东西,所以我很欣赏一个解决方案,或者至少指向正确的方向。
修改
现在,我正在使用类似于此的系统:http://jsfiddle.net/jEzaz/
我希望能够使用一系列AND和OR条件。现在,我被要求允许不止一个这么容易(例如,完成task1或task2意味着你现在可以完成任务3) - 但我可以看到将来需要更多功能。
我希望一切都有意义!
答案 0 :(得分:2)
对于样本,您可以尝试使用下一个结构和函数进行检查
如果没有先决条件将设置为null
如果一个 - 将设置字符串名称
如果有几个或者 - 将使用对象{or: ["task1","task2"...]}
如果有几个和 - 将使用对象{and: ["task1","task2"...]}
也用于组合 - 将使用{and: [{or:["task1","task2"]},"task3",{or:{"task5"...}}]}
所以示例任务列表可能就像这样
var myObj = {
task1: {name: 'Hello', prereq:null, selected: false},
task2: {name: 'World', prereq:'task1', selected: false},
task3: {name: 'Foo', prereq:{or:["task4","task2"]}, selected: false},
task4: {name: 'Bar', prereq:null, selected: false},
task5: {name: 'Baz', prereq:{and:[{or: ["task4","task6"]},"task1"]}, selected: false},
task6: {name: 'Barrr', prereq:null, selected: false}
};
用于检查使用功能,如
function preq(arr,config){
if(!config) return true;
if(typeof config === "string") return arr[config].selected;
if('or' in config){
for(var i=0,L=config['or'].length;i<L;i++){
if(preq(arr,config['or'][i])) return true;
}
return false;
}
if('and' in config){
for(var i=0,L=config['and'].length;i<L;i++){
if(!preq(arr,config['and'][i])) return false;
}
return true;
}
return false;
}
您也可以查看JSFiiddle
上的工作样本答案 1 :(得分:1)
您可以实现一个简单的解析器,将字符串先决条件转换为返回true / false的函数。检查这个小提琴http://jsfiddle.net/tarabyte/a9F6Z/
var Task = (function() {
//string to function converter
var parse = function(str) {
str = "return " + str.replace(/\|/g, '||')
.replace(/&/g, '&&')
.replace(/(\w+\d+)/g, function($1) {
return 'all["' + $1 + '"].done';
});
return new Function("all", str);
},
returnTrue = function() {
return true;
},
all = {};
/**
* Task constructor
*/
function Task(params) {
this.name = params.name;
//task is available by default
this.prereq = params.prereq ? parse(params.prereq) : returnTrue;
//task is not done.
this.done = false;
//register a task.
Task.all[this.name] = this;
};
/**
* All tasks map storage.
*/
Task.all = all;
/**
* Make a task complete
*/
Task.prototype.complete = function() {
this.done = true;
};
/**
* Make a task incomplete.
*/
Task.prototype.reopen = function() {
this.done = false;
};
/**
* Check if task is available due to prerequsites.
*/
Task.prototype.isAvailable = function() {
return this.prereq(all);
};
return Task;
}());