Introduction
Miss Manners is a program which handles the problem of finding an acceptable seating arrangement for guests at a dinner party. It will attempt to match people with the same hobbies, and to seat everyone next to a member of the opposite sex. Manners is a small program, which has only few rules, and employs a depth-first search approach to the problem.
Running Miss Manners
Change into the drools-examples directory and run the Miss Manners example:
D:\java\workspaces\drools-2.0\drools-examples>maven manners-java
__ __
| \/ |__ _Apache__ ___
| |\/| / _` \ V / -_) ' \ ~ intelligent projects ~
|_| |_\__,_|\_/\___|_||_| v. 1.0
(bunch of output)
manners-java:
[java] Using drl: manners.java.drl
[java] FIRE: find first seat: {name=n14,sex=m,hobbies=[h3, h1]}
[java] FIRE: find seating: {seat1=1,guest1={name=n14,sex=m,hobbies=[h3, h1]},seat2=2,guest2=null} {name=n1,sex=f,hobbies=[h2, h1]}
[java] FIRE: find seating: {seat1=2,guest1={name=n1,sex=f,hobbies=[h2, h1]},seat2=3,guest2=null} {name=n9,sex=m,hobbies=[h2, h3, h1]}
[java] FIRE: find seating: {seat1=3,guest1={name=n9,sex=m,hobbies=[h2, h3, h1]},seat2=4,guest2=null} {name=n5,sex=f,hobbies=[h3, h1, h2]}
[java] FIRE: find seating: {seat1=4,guest1={name=n5,sex=f,hobbies=[h3, h1, h2]},seat2=5,guest2=null} {name=n11,sex=m,hobbies=[h1, h3]}
[java] FIRE: find seating: {seat1=5,guest1={name=n11,sex=m,hobbies=[h1, h3]},seat2=6,guest2=null} {name=n10,sex=f,hobbies=[h2, h1, h3]}
[java] FIRE: find seating: {seat1=6,guest1={name=n10,sex=f,hobbies=[h2, h1, h3]},seat2=7,guest2=null} {name=n7,sex=m,hobbies=[h1, h2]}
[java] FIRE: find seating: {seat1=7,guest1={name=n7,sex=m,hobbies=[h1, h2]},seat2=8,guest2=null} {name=n8,sex=f,hobbies=[h1, h3, h2]}
[java] FIRE: find seating: {seat1=8,guest1={name=n8,sex=f,hobbies=[h1, h3, h2]},seat2=9,guest2=null} {name=n13,sex=m,hobbies=[h2, h1, h3]}
[java] FIRE: find seating: {seat1=9,guest1={name=n13,sex=m,hobbies=[h2, h1, h3]},seat2=10,guest2=null} {name=n3,sex=f,hobbies=[h2, h3]}
[java] FIRE: find seating: {seat1=10,guest1={name=n3,sex=f,hobbies=[h2, h3]},seat2=11,guest2=null} {name=n12,sex=m,hobbies=[h1, h2]}
[java] FIRE: find seating: {seat1=11,guest1={name=n12,sex=m,hobbies=[h1, h2]},seat2=12,guest2=null} {name=n4,sex=f,hobbies=[h2, h1, h3]}
[java] FIRE: find seating: {seat1=12,guest1={name=n4,sex=f,hobbies=[h2, h1, h3]},seat2=13,guest2=null} {name=n15,sex=m,hobbies=[h1, h3]}
[java] FIRE: find seating: {seat1=13,guest1={name=n15,sex=m,hobbies=[h1, h3]},seat2=14,guest2=null} {name=n6,sex=f,hobbies=[h1, h3]}
[java] FIRE: find seating: {seat1=14,guest1={name=n6,sex=f,hobbies=[h1, h3]},seat2=15,guest2=null} {name=n16,sex=m,hobbies=[h2, h3]}
[java] FIRE: find seating: {seat1=15,guest1={name=n16,sex=m,hobbies=[h2, h3]},seat2=16,guest2=null} {name=n2,sex=f,hobbies=[h3, h1, h2]}
[java] FIRE: we are done
[java] {seat=1,name=n14}
[java] {seat=2,name=n1}
[java] {seat=3,name=n9}
[java] {seat=4,name=n5}
[java] {seat=5,name=n11}
[java] {seat=6,name=n10}
[java] {seat=7,name=n7}
[java] {seat=8,name=n8}
[java] {seat=9,name=n13}
[java] {seat=10,name=n3}
[java] {seat=11,name=n12}
[java] {seat=12,name=n4}
[java] {seat=13,name=n15}
[java] {seat=14,name=n6}
[java] {seat=15,name=n16}
[java] {seat=16,name=n2}
[java] Elapsed time: 140ms
BUILD SUCCESSFUL
Total time: 54 seconds
Finished at: Mon Mar 28 01:27:08 CEST 2005
Understanding the Miss Manners Example
<!-- Initialize the root seating element. --> <rule name="find first seat" salience="40"> <parameter identifier="context"> <class>Context</class> </parameter> <parameter identifier="guest"> <class>Guest</class> </parameter> <java:condition> context.isState("start") </java:condition> <java:consequence> System.out.println("FIRE: find first seat: " + guest); drools.assertObject(new Seating(1, guest, null)); context.setState("find_seating"); drools.modifyObject(context); </java:consequence> </rule>
<!-- Find guest for empty seat. --> <rule name="find seating" salience="30"> <parameter identifier="context"> <class>Context</class> </parameter> <parameter identifier="guest"> <class>Guest</class> </parameter> <parameter identifier="seating"> <class>Seating</class> </parameter> <java:condition> context.isState("find_seating") </java:condition> <java:condition> seating.getGuest2() == null </java:condition> <java:condition> !seating.getTabooList().contains(guest) </java:condition> <java:condition> seating.getGuest1().hasOppositeSex(guest) </java:condition> <java:condition> seating.getGuest1().hasSameHobby(guest) </java:condition> <java:consequence> System.out.println("FIRE: find seating: " + seating + " " + guest); Seating nextSeat = new Seating(seating.getSeat2(), guest, seating); drools.assertObject(nextSeat); seating.setGuest2(guest); seating.getTabooList().add(guest); drools.modifyObject(seating); </java:consequence> </rule>
<!-- Reached dead end, try another path. --> <rule name="try another path" salience="20"> <parameter identifier="context"> <class>Context</class> </parameter> <parameter identifier="lastSeat"> <class>LastSeat</class> </parameter> <parameter identifier="seating"> <class>Seating</class> </parameter> <java:condition> context.isState("find_seating") </java:condition> <java:condition> lastSeat.getSeat() > seating.getSeat1() </java:condition> <java:condition> seating.getGuest2() == null </java:condition> <java:consequence> System.out.println("FIRE: try another path: " + seating); Seating prevSeat = seating.getPrevSeat(); prevSeat.setGuest2(null); drools.modifyObject(prevSeat); drools.retractObject(seating); </java:consequence> </rule>
<!-- All seats are taken. --> <rule name="we are done" salience="10"> <parameter identifier="context"> <class>Context</class> </parameter> <parameter identifier="lastSeat"> <class>LastSeat</class> </parameter> <parameter identifier="seating"> <class>Seating</class> </parameter> <java:condition> context.isState("find_seating") </java:condition> <java:condition> lastSeat.getSeat() == seating.getSeat1() </java:condition> <java:consequence> System.out.println("FIRE: we are done"); List list = new ArrayList(); while(seating != null) { Seat seat = new Seat(seating.getSeat1(), seating.getGuest1().getName()); seating = seating.getPrevSeat(); list.add(seat); } for (int i = list.size(); i > 0; i--) { Seat seat = (Seat)list.get(i-1); System.out.println(seat); drools.assertObject(seat); } context.setState("all_done"); drools.modifyObject(context); </java:consequence> </rule>


