Jess is expert system language like clips but based off java instead of c
This is my code
(import javax.swing.*)
(import java.awt.*)
(import java.awt.event.*)
(set-reset-globals FALSE)
(defglobal ?*crlf* = "
")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Question and answer templates
(deftemplate question
(slot text)
(slot type)
(multislot valid)
(slot ident))
(deftemplate answer
(slot ident)
(slot text))
(do-backward-chaining answer)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Module trigger
(defmodule trigger)
(defrule trigger::supply-answers
(declare (auto-focus TRUE))
(MAIN::need-answer (ident ?id))
(not (MAIN::answer (ident ?id)))
(not (MAIN::ask ?))
=>
(assert (MAIN::ask ?id))
(return))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Rules
(defrule MAIN::Starts-Normally
(declare (auto-focus TRUE))
(answer (ident starter) (text normal))
=>
(recommend-action "Car started normally No Problems")
(halt))
(defrule MAIN::Battery-Dead
(declare (auto-focus TRUE))
(answer (ident starter) (text dead))
(answer (ident lights) (text ~bright))
(answer (ident battery) (text dead))
=>
(recommend-action "Replace Battery")
(halt))
(defrule MAIN::Breaks-Wiring
(declare (auto-focus TRUE))
(answer (ident starter) (text dead))
(answer (ident lights) (text ~bright))
(answer (ident battery) (text ok))
(answer (ident wiring) (text breaks))
=>
(recommend-action "Replace Wiring")
(halt))
(defrule MAIN::Replace-Starter1
(declare (auto-focus TRUE)
(answer (ident starter) (text dead))
(answer (ident lights) (text ~bright))
(answer (ident battery) (text ok))
(answer (ident wiring) (text no-breaks))
(answer (ident lights-starter) (text yes))
=>
(recommend-action "Replace the starter or get it tested")
(halt))
(defrule MAIN::Unknown
(declare (auto-focus TRUE)
(answer (ident starter) (text dead))
(answer (ident lights) (text ~bright))
(answer (ident battery) (text ok))
(answer (ident wiring) (text no-breaks))
(answer (ident lights-starter) (text no))
=>
(recommend-action "Unknown error Consult your local Mechanic")
(halt))
(defrule MAIN::Repalce-Solenoid
(declare (auto-focus TRUE)
(answer (ident starter) (text dead))
(answer (ident lights) (text bright))
(answer (ident shorting-solenoids) (text yes))
=>
(recommend-action "Problem is in the ignition wiring. Replace that wiring)
(halt))
(defrule MAIN::Replace-Bushings
(declare (auto-focus TRUE)
(answer (ident starter) (text dead))
(answer (ident lights) (text bright))
(answer (ident shorting-solenoids) (text no))
(answer (ident bushings) (text bad))
=>
(recoomend-action "Replace the bushings")
(halt))
(defrule MAIN::Replace-Starter2
(declare (auto-focus TRUE)
(answer (ident starter) (text dead))
(answer (ident lights) (text bright))
(answer (ident shorting-solenoids) (text no))
(answer (ident bushings) (text good))
=>
(recoomend-action "Replace the starter")
(halt))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Results output
(deffunction recommend-action (?action)
"Give final instructions to the user"
(call JOptionPane showMessageDialog ?*frame*
(str-cat "I recommend that you " ?action)
"Recommendation"
(get-member JOptionPane INFORMATION_MESSAGE)))
(defadvice before halt (?*qfield* setText "Close window to exit"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Module ask
(defmodule ask)
(deffunction ask-user (?question ?type ?valid)
"Set up the GUI to ask a question"
(?*qfield* setText ?question)
(?*apanel* removeAll)
(if (eq ?type multi) then
(?*apanel* add ?*acombo*)
(?*apanel* add ?*acombo-ok*)
(?*acombo* removeAllItems)
(foreach ?item ?valid
(?*acombo* addItem ?item))
else
(?*apanel* add ?*afield*)
(?*apanel* add ?*afield-ok*)
(?*afield* setText ""))
(?*apanel* validate)
(?*apanel* repaint))
(deffunction is-of-type (?answer ?type ?valid)
"Check that the answer has the right form"
(if (eq ?type multi) then
(foreach ?item ?valid
(if (eq (sym-cat ?answer) (sym-cat ?item)) then
(return TRUE)))
(return FALSE))
(if (eq ?type number) then
(return (is-a-number ?answer)))
;; plain text
(return (> (str-length ?answer) 0)))
(deffunction is-a-number (?value)
(try
(integer ?value)
(return TRUE)
catch
(return FALSE)))
(defrule ask::ask-question-by-id
"Given the identifier of a question, ask it"
(declare (auto-focus TRUE))
(MAIN::question (ident ?id) (text ?text) (valid $?valid) (type ?type))
(not (MAIN::answer (ident ?id)))
(MAIN::ask ?id)
=>
(ask-user ?text ?type ?valid)
((engine) waitForActivations))
(defrule ask::collect-user-input
"Check an answer returned from the GUI, and optionally return it"
(declare (auto-focus TRUE))
(MAIN::question (ident ?id) (text ?text) (type ?type) (valid $?valid))
(not (MAIN::answer (ident ?id)))
?user <- (user-input ?input)
?ask <- (MAIN::ask ?id)
=>
(if (is-of-type ?input ?type ?valid) then
(retract ?ask ?user)
(assert (MAIN::answer (ident ?id) (text ?input)))
(return)
else
(retract ?ask ?user)
(assert (MAIN::ask ?id))))
;; Main window
(defglobal ?*frame* = (new JFrame "Diagnostic Assistant"))
(?*frame* setDefaultCloseOperation (get-member JFrame EXIT_ON_CLOSE))
(?*frame* setSize 520 140)
(?*frame* setVisible TRUE)
;; Question field
(defglobal ?*qfield* = (new JTextArea 5 40))
(bind ?scroll (new JScrollPane ?*qfield*))
((?*frame* getContentPane) add ?scroll)
(?*qfield* setText "Please wait...")
;; Answer area
(defglobal ?*apanel* = (new JPanel))
(defglobal ?*afield* = (new JTextField 40))
(defglobal ?*afield-ok* = (new JButton OK))
(defglobal ?*acombo* = (new JComboBox (create$ "yes" "no")))
(defglobal ?*acombo-ok* = (new JButton OK))
(?*apanel* add ?*afield*)
(?*apanel* add ?*afield-ok*)
((?*frame* getContentPane) add ?*apanel* (get-member BorderLayout SOUTH))
(?*frame* validate)
(?*frame* repaint)
(deffunction read-input (?EVENT)
"An event handler for the user input field"
(assert (ask::user-input (sym-cat (?*afield* getText)))))
(bind ?handler (new jess.awt.ActionListener read-input (engine)))
(?*afield* addActionListener ?handler)
(?*afield-ok* addActionListener ?handler)
(deffunction combo-input (?EVENT)
"An event handler for the combo box"
(assert (ask::user-input (sym-cat (?*acombo* getSelectedItem)))))
(bind ?handler (new jess.awt.ActionListener combo-input (engine)))
(?*acombo-ok* addActionListener ?handler)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Questions
(deffacts MAIN::question-data
(question (ident starter)
(type multi) (vaild normal dead)
(text "How did the car crank?"))
(question (ident lights)
(type multi) (valid bright out very-dim)
(text "Turn on the head lights, What are the status of the lights?"))
(question (ident battery)
(type multi) (valid dead ok)
(text "Check the battery, What is the codition of the battery?"))
(question (ident wiring)
(type multi) (vaild breaks no-breaks)
(text "Check the wiring, Does the wiring have any breaks in it?"))
(question (ident lights-starter)
(type multi) (vaild yes no)
(text "Turn headlights on and crank the car again,Do the headlights dim drastically when crank starter?"))
(question (ident shorting-solenoids)
(type multi) (valid yes no)
(text "Short the two solenoids, Does it crank normally?"))
(question (ident bushings)
(type multi) (valid good bad)
(text "Check the bushing, What are condition of the bushings"))
(ask starter))
(reset)
(run-until-halt)
I get this error when i load this file
Jess reported an error in routine Jesp.parseValuePair
while executing (batch car-starter-gui.clp).
Message: Bad value at token 'answer'.
Program text: ( batch car-starter-gui.clp ) at line 4.
Don't mind the line number the debugger isnt great and often gives different line numbers for same error each time run the program