University of Calgary
Rob Kremer
Individual Assignment 3: Conversations



CPSC 662/568: Agent Communication

Winter 2015

Department of Computer Science
Computer
Science

Note: This is an individual assignment. You may brainstorm with other students, but the bulk of the work and the bulk of the ideas must be your own. That entails that you may not share a drawing by copy-and-paste or by any other means. If you do work with other students (or anybody else) you must cite that collaboration explicitly in your submitted assignment. This is good practice in any circumstances.

Your assignment is to create a request-when conversation.  The conversation starts by a client sending a request-when message to the server specifying a event description and an action to do when the event happens. For each request-when message, the action is performed only once.  The event description and action will be specified in the content field of the message as a Lisp list containing the Lisp form of a CASA MessageEventDescriptor and a Lisp Cons list specifying arbitrary Lisp code that is the action.  Thus, a typical request might be:

 ( request-when
   :sender casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient
   :receiver casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer
   :reply-by Tue Mar 10 21:09:43 MDT 2015
   :reply-with casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient--1 :conversation-id casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient--1 :language Lisp
   :content (list (MSGEVENT-DESCRIPTOR event_messageReceived
                                       :=content "(READY 123)"
                                       :=language FIPA-SL
                                       :<performative inform)
                 '(AGENT.SEND
                     (AGENT.MESSAGE "inform" nil ":5402"
                                    :language "FIPA-SL"
                                    :content "(received inform 123)")))
 )

The server agent will normally first reply with an agree (but could reply with a refuse), then wait for the wait for the described event to happen, and then execute the action.  The agree to the above message would be:

  
 ( agree
   :act request-when
   :sender casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer :receiver casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient :reply-by Tue Mar 10 21:09:43 MDT 2015
   :reply-with casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer--1 :in-reply-to casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient--1 :conversation-id casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient--1 :language Lisp
   :content (list (MSGEVENT-DESCRIPTOR event_messageReceived
                                       :=content "(READY 123)"
                                       :=language FIPA-SL
                                       :<performative inform)
                 '(AGENT.SEND
                     (AGENT.MESSAGE "inform" nil ":5402"
                                    :language "FIPA-SL"
                                    :content "(received inform 123)")))
 )
If the event receives the event described in the content field, it will perform the action.  In this case, the event is the receipt of an inform message who's content is "(READY 123)" and who's language field is "FIPA-SL".  For example:
  
 ( inform
   :sender casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient
   :receiver casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer
   :reply-by Tue Mar 10 21:09:44 MDT 2015
   :reply-with casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient--5 :conversation-id casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient--5 :language FIPA-SL
   :content (READY 123)
 )
After receiving the above message, the server should perform the action, which, in this example case, is sending an inform message to the client:
 ( inform
   :sender casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer
   :receiver casa://kremer@192.168.0.7:5402/casa/TestAgent/RequestWhenTestClient
   :from casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer 
:reply-by Tue Mar 10 21:09:37 MDT 2015
   :reply-with casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer--5 :conversation-id casa://kremer@192.168.0.7:5401/casa/TestAgent/RequestWhenTestServer--6 :language FIPA-SL
   :content (received inform 123)
 )
A program to test you agent class follows.  You can use it to test your program.  I will run a similar (but not identical) program to test your agent.
package casa;

import jade.semantics.kbase.QueryResult;
import jade.semantics.lang.sl.grammar.Formula;
import jade.semantics.lang.sl.parser.ParseException;
import jade.semantics.lang.sl.parser.SLParser;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import casa.event.MessageEventDescriptor;
import casa.event.TimeEvent;
import casa.util.CASAUtil;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.print("Class: ");
		InputStreamReader reader = new InputStreamReader(System.in);
		BufferedReader in = new BufferedReader(reader);
		Class<? extends TransientAgent> cls = null; 		
		try {
			String clsName;
			clsName = in.readLine();
			cls = (Class<? extends TransientAgent>) Class.forName(clsName); 
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// Set up the server ************************************************************
		TransientAgent server = CASAUtil.startAnAgent(cls, "RequestWhenTestServer", 5401, null);

		// Set up the client ************************************************************
		TransientAgent client = CASAUtil.startAnAgent(cls, "RequestWhenTestClient", 5402, null);
	
		casa.util.CASAUtil.sleepIgnoringInterrupts(1000, null); // wait to make sure everything gets started.
		
		Formula formula = makeFormula(123), formula2 = makeFormula(124);
		// Send the REQUEST-WHEN message to the server to listen for an INFORM.
		client.sendMessage(ML.REQUEST_WHEN, null, server.getURL(), ML.LANGUAGE, "Lisp", ML.CONTENT, makeContent(formula, server, 123));
		client.sendMessage(ML.REQUEST_WHEN, null, server.getURL(), ML.LANGUAGE, "Lisp", ML.CONTENT, makeContent(formula2, server, 124));
		
		casa.util.CASAUtil.sleepIgnoringInterrupts(1000, null); // wait to make sure everything gets started.
		
		
		runChecker(formula,client);
		runChecker(formula2,client);
	
		// send the INFORM message to server to be the event the REQUEST_WHEN is listening for.
		client.sendMessage(ML.INFORM, null, server.getURL(), ML.LANGUAGE, ML.FIPA_SL, ML.CONTENT, "(READY 123)");
		
		System.out.println("We expect one success and one failure.");
		
	} // end main()

	
	static TimeEvent runChecker(Formula formula, TransientAgent client) {
		final Formula formulaCopy = formula;
		TimeEvent checker = new TimeEvent(ML.EVENT_EXECUTABLE, client, System.currentTimeMillis()+2000) {
			@Override
			public void fireEvent() {
				super.fireEvent();
				QueryResult res = client.kBase.query(formulaCopy); 
				if (res == QueryResult.KNOWN) {
					System.out.println("*** Success ***");
				}
				else if (res == QueryResult.UNKNOWN){
					System.out.println("*** Failure ***");
				}
				else {
					System.out.println("Unexpected result: "+res.toString());
				}
			}
		};
		checker.start();
		return checker;
	}
	
	static Formula makeFormula(int code) {
		try {
			return SLParser.getParser().parseFormula("(received inform "+code+")", true);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;

	static String makeContent(Formula formula, TransientAgent server, int code) {
		return "(list " + 
			new MessageEventDescriptor(server, ML.EVENT_MESSAGE_RECEIVED, ML.PERFORMATIVE, ML.INFORM, ML.LANGUAGE, ML.FIPA_SL, ML.CONTENT, "\"(READY "+code+")\"").toString() +
			" '(AGENT.SEND (AGENT.MESSAGE \"inform\" nil \":5402\" :language \"FIPA-SL\" :content \""+formula.toString()+"\")))";		
	}

}

Hints



What to hand in?

Put your .java files and the .init.lisp file that coresponds to your agent in the D2L dropbox "Group Assignment 3". Nothing more. I will mark it by running it through my JUnit test script. Any resources you use (including collaborations with other students [not copying!]) must be cited in comments.



UofC
CPSC 662/568: Agent Communication
Department of Computer Science

Last updated 2015-02-01
Rob Kremer