본문 바로가기

카테고리 없음

Grule - Go Rule Engine 예시 코드

go mod init <myprojectname>
go get -v -u github.com/hyperjumptech/grule-rule-engine

 

// main.go
package main

import (
	"time"

	"github.com/hyperjumptech/grule-rule-engine/ast"
	"github.com/hyperjumptech/grule-rule-engine/builder"
	"github.com/hyperjumptech/grule-rule-engine/engine"
	"github.com/hyperjumptech/grule-rule-engine/logger"
	"github.com/hyperjumptech/grule-rule-engine/pkg"
)

type testCar struct {
	SpeedUp        bool
	Speed          int
	MaxSpeed       int
	SpeedIncrement int
}
type distanceRecord struct {
	TotalDistance int
}

const JSON_RULE = `
[{
	"name": "SpeedUp",
	"desc": "When testcar is speeding up we increase the speed.",
	"salience": 10,
	"when": {
		 "and": [
				 {"eq": [{"obj": "TestCar.SpeedUp"}, {"const": true}]},
				 {"lt": [{"obj": "TestCar.Speed"}, {"obj": "TestCar.MaxSpeed"}]}
		 ]
	},
	"then": [
			{"set": [{"obj": "TestCar.Speed"}, {"plus": [{"obj": "TestCar.Speed"}, {"obj": "TestCar.SpeedIncrement"}]}]},
			{"set": [{"obj": "TestCar.SpeedUp"}, {"const": false}]},
			{"set": [{"obj": "DistanceRecord.TotalDistance"}, {"plus": [{"obj": "DistanceRecord.TotalDistance"}, {"obj": "TestCar.Speed"}]}]},
			{"call": ["Log", {"const": "Speed increased"}]}
	]
}]
`

const RULE_INSTANCE_NAME = "rule-engine-instance-name"
const RULE_INSTANCE_VERSION = "0.0.1"

func main() {
	// grule variable declaration
	var gruleKnowledgeLib = ast.NewKnowledgeLibrary()
	var gruleBuilder = builder.NewRuleBuilder(gruleKnowledgeLib)
	var gruleEngine = engine.NewGruleEngine()
	var gruleKnowledgeBase *ast.KnowledgeBase

	// dataCtx is literally data context used within rule evaluation
	var dataCtx = ast.NewDataContext()

	gruleRuleset, err := pkg.ParseJSONRuleset([]byte(JSON_RULE))
	if nil != err {
		logger.Log.WithError(err).Panicf("failed to parse jsonruleset")
	}
	if err := gruleBuilder.BuildRuleFromResource(RULE_INSTANCE_NAME, RULE_INSTANCE_VERSION, pkg.NewBytesResource([]byte(gruleRuleset))); nil != err {
		logger.Log.WithError(err).Panicf("failed to build rule from resource")
	}
	gruleKnowledgeBase = gruleKnowledgeLib.NewKnowledgeBaseInstance(RULE_INSTANCE_NAME, RULE_INSTANCE_VERSION)

	// custom variable
	car := &testCar{MaxSpeed: 100, SpeedIncrement: 10}
	distRecord := &distanceRecord{TotalDistance: 1000}

	// custom variable must come along with dataCtx for rule to be evaluated
	dataCtx.Add("TestCar", car)
	dataCtx.Add("DistanceRecord", distRecord)

	// just for simple debug purpose
	executedNo := 1
	for {
		logger.Log.WithField("car", car).WithField("distanceRecord", distRecord).Infof("engine executed %d times", executedNo)
		executedNo++
		err = gruleEngine.Execute(dataCtx, gruleKnowledgeBase)
		if nil != err {
			logger.Log.WithError(err).Panicf("failed to execute engine")
		}

		if 30 < car.Speed {
			car.SpeedUp = false
		} else {
			car.SpeedUp = true
		}

		time.Sleep(time.Second * 1)
	}
}

 

실행 화면 예시

 

Reference

- http://hyperjumptech.viewdocs.io/grule-rule-engine/GRL_JSON_en/