home *** CD-ROM | disk | FTP | other *** search
- # From: "Dat Nguyen" <thucdat@hotmail.com>
- # Subject: Module rule-engine
- # Date: Wed, 19 May 2004 01:16:37 -0400
- #
- # Animal Taxonomy is a favorite subject of specialized rule-based programming
- # languages. With some creative construction, C-Kermit can solve that problem
- # in the same manner. The cheetah.kr script exposes the same look and feel of
- # many rule-based programs. Many configuration problems in computer
- # administration and network should be solvable similarly, provided the rule
- # set can be identified.
- #
- # This demonstration comes in two modules: rule-engine and cheetah.
- # To run the demonstration, tell Kermit to TAKE the cheetah module.
- #
- # Here is rule-engine:
-
- define say {
- echo \%1
- return 1
- }
-
- define askContent {
- local \%v
- ask \%v {[\%1]: }
- _asg \%1 \%v
- return \%1
- }
-
- define askYesNo {
- local ans
- while true {
- ask ans {\%1 (y|n): }
- if \find(y,\m(ans)) return 1
- if \find(n,\m(ans)) return 0
- }
- }
-
- define askANumber {
- local \%n
- while true {
- echo Enter a Value
- ask \%n {[\%1]: }
- if numeric \%n return \%n
- }
- }
-
- define disableRule {
- local \%i
- for \%i 1 \v(argc)-1 1 {
- asg RuleDatabase \m(RuleDatabase)\&_[\%i]|
- incr RuleNumber
- }
- }
-
- define enableRule {
- local \%i
- for \%i 1 \v(argc)-1 1 {
- asg RuleDatabase \freplace(\m(RuleDatabase),|\&_[\%i]|,|)
- decr RuleNumber
- }
- }
-
- define availableRule {
- if \find(\%1,\m(RuleDatabase)) return 0
- disableRule {\%1}
- return 1
- }
-
- define eligibleRule {
- (! \find(\%1,\m(RuleDatabase)))
- }
-
- define clearRuleDatabase {
- asg RuleDatabase |
- (setq RuleNumber 0)
- }
-
- define addFact {
- local \%i
- for \%i 1 \v(argc)-1 1 {
- if \find(\&_[\%i],\m(FactDatabase)) continue
- asg FactDatabase \m(FactDatabase)\&_[\%i]|
- incr FactNumber
- }
- # showFact
- }
-
- define addATrueFact {
- # \%1 Name of the Boolean fact
- # \%2 Value of Boolean fact
- # Overwrite previous value
- local \%s \%w \%f
- asg \%s \fword(\%1,1)_\fword(\%1,2)
- asg \%w \freplace(\%1,{\fword(\%1,1) \fword(\%1,2) })
- _asg \%s |\%w|
- addFact {\%s}
- return 1
- }
-
- define addAlsoTrueFact {
- local \%s \%w \%f
- asg \%s \fword(\%1,1)_\fword(\%1,2)_also
- asg \%w \freplace(\%1,{\fword(\%1,1) \fword(\%1,2) })
- _asg \%s \m(\%s)|\%w|
- addFact {\%s}
- return 1
- }
-
- define addTrueFact {
- # add and initialize with True
- _asg \%1 1
- addFact {\%1}
- }
-
- define addFalseFact {
- _asg \%1 0
- # add and initialize with False
- addFact {\%1}
- }
-
- define addValueFact {
- if \find(\%1,\m(FactDatabase)) return \m(\%1)
- _asg \%1 \fsexpr(askANumber '(\%1))
- addFact {\%1}
- return \m(\%1)
- }
-
- define addcontentFact {
- if \find(\%1,\m(FactDatabase)) return \m(\%1)
- _asg \%1 \fsexpr(askContent '(\%1))
- addFact {\%1}
- return \m(\%1)
- }
-
- define removeFact {
- local \%i
- for \%i 1 \v(argc)-1 1 {
- asg FactDatabase \freplace(\m(FactDatabase),|\&_[\%i]|,|)
- decr FactNumber
- }
- # showFact
- }
-
- define isItTrueThat {
- # Use for fact that can have only one of two possible value.
- # a buble can be either ON of OFF
- local \%s \%w \%f
- asg \%s \fword(\%1,1)_\fword(\%1,2)
- asg \%w \freplace(\%1,{\fword(\%1,1) \fword(\%1,2) })
- asg \%f \find(\%s,\m(FactDatabase))
- if \%f {
- # term in factdatabase
- if \find(|\%w|,\m(\%s)) return 1
- return 0
- } else {
- # term not in factdatabase
- local \%a
- asg \%a \fsexpr(askYesNo '(\%1))
- if \%a {
- _asg \%s |\%w|
- # save fact only when not in database before
- if not \%f addFact {\%s}
- }
- return \%a
- }
- }
-
- define isTrueFact {
- # This responds with the content of the fact (True or False)
- if \find(\%1,\m(FactDatabase)) return \m(\%1)
- _asg \%1 \fsexpr(askYesNo '(\%1))
- addFact {\%1}
- return \m(\%1)
- }
-
- define gotFact {
- # This gives user a chance to create a state fact with y(yes) or n(no)
- if \find(\%1,\m(FactDatabase)) return 1
- echo \%1
- local \%a
- asg \%a \fexec(askYesNo)
- if \%a { # yes, create fact
- addFact {\%1}
- }
- return \%a
- }
-
- define hasFact {
- # This does not expect user to respond
- (\find(\%1,\m(FactDatabase)))
- }
-
- define anyFact {
- (FactNumber)
- }
-
- define removeAllFact {
- asg FactDatabase |
- (setq FactNumber 0)
- }
-
- define showFact {
- show mac FactDatabase
- show mac FactNumber
- }
-
- define addGoal {
- local \%i
- for \%i 1 \v(argc)-1 1 {
- asg GoalDatabase \m(GoalDatabase)\&_[\%i]|
- incr GoalNumber
- }
- # showGoal
- }
-
- define removeGoal {
- local \%i
- for \%i 1 \v(argc)-1 1 {
- asg GoalDatabase \freplace(\m(GoalDatabase),|\&_[\%i]|,|)
- decr GoalNumber
- }
- # showGoal
- }
-
- define allGoalDone {
- (! GoalNumber)
- }
-
- define hasGoal {
- (\find(\%1,\m(GoalDatabase)))
- }
-
- define removeAllGoal {
- asg GoalDatabase |
- (setq GoalNumber 0)
- }
-
- define showGoal {
- show mac GoalDatabase
- show mac GoalNumber
- }
-
- define fireRule {
- local \&e[] \%n \%i \%f
- asg \%n \fsplit(\%1,&e,{ })
- while true {
- for \%i 1 \%n 1 {
- if define \m(\&e[\%i]) {
- asg \%f \fexec(\&e[\%i])
- # if rule was fired, reevaluate all rules
- if > \%f 0 {
- asg firedRules \m(firedRules)|\&e[\%i]
- echo \&e[\%i] was fired
- if = 2 \%f END
- break
- }
- }
- }
- if not \%f break # no rule was fired
- if = 1 \fexec(allGoalDone) break # all goals achieved
- }
- echo
- echo {That's all there is}
- echo
- }
-
- define rule_sample {
- (if (hasGoal 'Goal_xxx)
- (if (hasFact 'Fact_yyy)
- (if (not (hasGoal 'Goal_zzz))
- (.
- (removeGoal 'Goal_xxx) # Goal achieved
- (removeFact 'Fact_yyy) # Fact changed
- (addGoal 'Fact_www) # New goal
- (addFact 'Fact_yyy) # New fact
- (1)
- )
- (0)
- )
- (0)
- )
- (0)
- )
- }
- define mutual_exclude {
- local \%i \%s
- asg \%s +
- for \%i 1 \v(argc)-1 1 {
- asg \%s \%s\&_[\%i]+
- }
- _asg \v(macro)_term \m(\v(macro)_term)|\%s
- }
-
- define addThisFact {
- asg allTheFacts \m(allTheFacts)|\%1
- registerThisFact {\%1} 1 0
- }
-
- define excludeThisFact {
- asg allTheFacts \freplace(\m(allTheFacts),|\%1|,|)
- registerThisFact {\%1} 0 1
- }
-
- define showAllFacts {
- local \%i \&w[]
- for \%i 1 \fsplit(\m(allTheFacts),&w,|) 1 {
- echo \&w[\%i]
- }
- }
-
- define clearAllFacts {
- asg allTheFacts
- }
-
- define registerThisFact {
- local \%i \%k \%n \&w[] \%f
- asg \%n \fsplit(\m(mutual_exclude_term),&w,|)
- if \%n {
- local \%m \&e[]
- # There is mutual exclusive fact
- asg \%f \farraylook(^+\%1+*,&w)
- if > \%f 0 {
- asg \%m \fsplit(\&w[\%f],&e,{+})
- # This is a mutual exclusive fact
- if \%2 {
- # This is a true fact, turn off all others
- for \%i 1 \%m 1 {
- _asg \&e[\%i] \%3
- }
- } else {
- # This is a false fact, turn off only for boolean fact
- if = 2 \%m {
- # This is a boolean fact
- for \%i 1 \%m 1 {
- _asg \&e[\%i] \%3
- }
- }
- }
- }
- }
- _asg \%1 \%2
- }
-
- define consultUser {
- asg consult_user 1
- }
-
- define donotConsultUser {
- asg consult_user 0
- }
- donotConsultUser
-
- define isThisFactTrue {
- if define \m(\%1) return \m(\%1)
- local \%a
- if == \m(consult_user) 1 {
- asg \%a \fsexpr(askYesNo '(\%1))
- } else {
- asg \%a 0
- }
- if \find(+\%1+,\m(mutual_exclude_term)) {
- # term with mutual exclusion
- if = 1 \%a {
- addThisFact {\%1}
- } else {
- excludeThisFact {\%1}
- }
- } else {
- # term withOUT mutual exclusion
- _asg \%1 \%a
- }
- return \%a
- }
-
- # \farraylook(oofa*,&a)
-