GKRuleSystemという複数の条件を管理する機能を使ってみました。
使い方は下の通りです。
- GKRuleSystemにGKRuleを追加する
- GKRuleSystemにパラメータをセットする
- GKRuleSystemの評価メソッド(evaluate)を呼ぶ
- 評価の結果を取得する
コードは下の通りです。
評価の結果は、GKRuleの引数のgradeの数字が返ってきます。
system.add
がルールの追加、system.state["value1"] = 0
がパラメータのセット、system.evaluate()
が評価メソッドの呼び出し、system.grade(forFact: NSString(string: "fact1"))
が結果の取得になります。
let system = GKRuleSystem() system.add([ GKRule(predicate: NSPredicate(format: "$value1 = 0"), assertingFact: NSString(string: "fact1"), grade: 0.9), ]) system.state["value1"] = 0 system.reset() system.evaluate() print(system.grade(forFact: NSString(string: "fact1"))) // → 0.9
条件式がfalseの場合、結果は0になります。
let system = GKRuleSystem() system.add([ GKRule(predicate: NSPredicate(format: "$value1 = 0"), assertingFact: NSString(string: "fact1"), grade: 0.9), ]) system.state["value1"] = 1 // → 今回は1をセット system.reset() system.evaluate() print(system.grade(forFact: NSString(string: "fact1"))) // → 0.0
GKRuleは複数渡す事ができます。
複数の条件を満たす場合、結果は全ての条件の和になります。
let system = GKRuleSystem() system.add([ GKRule(predicate: NSPredicate(format: "$value1 = 0"), assertingFact: NSString(string: "fact1"), grade: 0.1), GKRule(predicate: NSPredicate(format: "$value2 = 1"), assertingFact: NSString(string: "fact1"), grade: 0.2), ]) system.state["value1"] = 0 system.state["value2"] = 1 system.reset() system.evaluate() print(system.grade(forFact: NSString(string: "fact1"))) // → 0.3
しかし結果は1.0以上にはならないので注意が必要です。
和が1.0以上の場合は、1.0が返ってきます。
let system = GKRuleSystem() system.add([ GKRule(predicate: NSPredicate(format: "$value1 = 0"), assertingFact: NSString(string: "fact1"), grade: 1.1), GKRule(predicate: NSPredicate(format: "$value2 = 1"), assertingFact: NSString(string: "fact1"), grade: 2.2), ]) system.state["value1"] = 0 system.state["value2"] = 1 system.reset() system.evaluate() print(system.grade(forFact: NSString(string: "fact1"))) // → 1.0
GKRuleの初期化のassertingFactをretractingFactに変えると、条件を満たした時にgradeを減算するようになります。
これも和の時と同じように0.0以下にはなりません。
let system = GKRuleSystem() system.add([ GKRule(predicate: NSPredicate(format: "$value1 = 0"), assertingFact: NSString(string: "fact1"), grade: 0.5), GKRule(predicate: NSPredicate(format: "$value2 = 1"), retractingFact: NSString(string: "fact1"), grade: 0.2), ]) system.state["value1"] = 0 system.state["value2"] = 1 system.reset() system.evaluate() print(system.grade(forFact: NSString(string: "fact1"))) // → 0.3
GKRuleはNSPredicateではなくブロックで評価をする事もできます。
GKRule(blockPredicate: { system in return true }, action: { system in print("条件を満たした") })
GKRuleのサブクラスを作って、そこに評価式を書くこともできます。
複雑な条件の時はこれを使うのも良さそうです。
class MyRule: GKRule { override func evaluatePredicate(in system: GKRuleSystem) -> Bool { return true } override func performAction(in system: GKRuleSystem) { print("条件を満たした") } }