少し複雑な条件でのサンプルプログラム
- プログラム概要
- 車両保険の割引率計算のプログラムです。Factはサンプルプログラム2のものに、ゴールド免許か否か、利用用途加えたものになります。
免許
ゴールド免許
+5%割引
年齢
18<=年齢<25 0%
25<=年齢<35 10%
35<=年齢<50 13%
50<=年齢 5%
利用目的
30歳以上、40歳未満で
日常・レジャー(近距離)の利用は+2%OFF
通勤利用 0%
- ファクト
- 省略しますが、PurposeType,LicenseTypeはenumです。割引率をdiscountで定義しています。
public class Profile {
private int age;
private String name;
private PurposeType purpose;
private LicenseType licenseType;
private int discount;
public Profile(String name, int age, PurposeType purpose, LicenseType licenseType) {
this.name = name;
this.age = age;
this.purpose=purpose;
this.licenseType = licenseType;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public PurposeType getPurpose() {
return purpose;
}
public LicenseType getLicenseType() {
return licenseType;
}
public void setDiscount(int discount) {
this.discount = discount;
}
public int getDiscount() {
return discount;
}
}
public class Discount {
public static final void main(String[] args) {
try {
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase
.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory
.newFileLogger(ksession, "test");
Profile uzr = new Profile("uzr",29,PurposeType.CLOSE,LicenseType.GOLD);
ksession.insert(uzr);
ksession.fireAllRules();
System.out.println(uzr.getDiscount());
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory
.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("sample3/Discount.drl"),
ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error : errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}
}
- ルール
- 新たな試みが二つ。ひとつはデバッグ文出力のため、functionを利用しました。
- もうひとつはno-loopです。たとえば、25歳以上で、ゴールド免許のデータがファクトとして入ってきた場合、ゴールド免許で評価されたあとに、25歳以上というルールでも評価され、またゴールド免許で・・・という風にループしてしまいます。これを防ぐのがno-loopです。一度評価されたものは再評価しません。
function void printDiscount(Profile p) {
System.out.println(p.getName() + ":" + p.getDiscount());
}
rule "ゴールド免許割引"
no-loop
when
p:Profile(licenseType==LicenseType.GOLD)
then
p.setDiscount(p.getDiscount() + 5);
printDiscount(p);
end
rule "年齢割引(25歳以上35歳未満は10%OFF)"
no-loop
when
p:Profile(age>=25,age<35)
then
p.setDiscount(p.getDiscount() + 10);
printDiscount(p);
end
rule "年齢割引(35歳以上50歳未満は13%OFF)"
no-loop
when
p:Profile(age>=35,age<50)
then
p.setDiscount(p.getDiscount() + 13);
printDiscount(p);
end
rule "年齢割引(50歳以上5%OFF)"
no-loop
when
p:Profile(age>=50)
then
p.setDiscount(p.getDiscount() + 5);
printDiscount(p);
end
rule "30歳-40歳で近距離利用は2%OFF"
no-loop
when
p:Profile(age>=30,age<40,purpose==PurposeType.CLOSE)
then
p.setDiscount(p.getDiscount() + 2);
printDiscount(p);
end
uzr:10
uzr:15
15