All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jadex.bdi.planlib.protocols.englishauction.EAReceiverPlan Maven / Gradle / Ivy

Go to download

The Jadex applib BDI package contains ready to use functionalities for BDI agents mostly in form of modules called capabilities.

The newest version!
package jadex.bdi.planlib.protocols.englishauction;

import java.util.List;

import jadex.bdi.planlib.protocols.AbstractReceiverPlan;
import jadex.bdi.planlib.protocols.AuctionDescription;
import jadex.bdiv3.runtime.IGoal;
import jadex.bdiv3.runtime.impl.GoalFailureException;
import jadex.bdiv3x.runtime.IMessageEvent;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.fipa.SFipa;
import jadex.commons.TimeoutException;
import jadex.commons.collection.SCollection;

/**
 *  This plan implements the receiver of the "FIPA Dutch Auction Interaction
 *  Protocol Specification" (XC00032 - Experimental).
 *  
 *  An English auction is one where bidders continuously can increase the current
 *  offer until no one is willing to increase any more.
 */
public class EAReceiverPlan extends AbstractReceiverPlan
{
	/**
	 *  The plan body.
	 */
	public void body()
	{
		super.body();	// Hack???
		
		// Fetch the auction information.
		IMessageEvent me = (IMessageEvent)getParameter("message").getValue();
		
		// HACK!!! Problem, there is no reply message sent in this protocol. 
		// So that agent has no open active conversations.
		IMessageEvent	dummy	= createMessageEvent("ea_propose");	// Hack??? Need some conversation message to wait for
		dummy.getParameter(SFipa.CONVERSATION_ID).setValue(me.getParameter(SFipa.CONVERSATION_ID).getValue());
		getWaitqueue().addReply(dummy);
		
		AuctionDescription auctiondesc = (AuctionDescription)me.getParameter(SFipa.CONTENT).getValue();
		
		getLogger().info(getComponentName()+": Received inform_start_auction message with auction description " +
			"start time: "+auctiondesc.getStarttime()+" Round time "+auctiondesc.getRoundTimeout()
			+" topic: "+auctiondesc.getTopic());
		if(auctiondesc.getRoundTimeout()<=0)
		{
			getLogger().warning(getComponentName()+"No round timeout specified");
			fail();
		}
		
		// Offer the possibility to decide not to participate in the auction
		Object[] tmp = decideParticipation(auctiondesc, (IComponentIdentifier)me.getParameter(SFipa.SENDER).getValue());
		boolean participate = ((Boolean)tmp[0]).booleanValue();
		Object auctioninfo = tmp[1];
		
		// Have to use larger round timeout, because initiator will wait for timeout too before sending new cfp
		long buftimeout = auctiondesc.getRoundTimeout() * 2;
		long firsttimeout = auctiondesc.getStarttime()==0 || (auctiondesc.getStarttime()-getTime()<=0)
			? -1 : auctiondesc.getStarttime()-getTime()+buftimeout;
	
		List offers = SCollection.createArrayList();
		boolean running = true;
		Object winning_offer = null; // my winning offer
		Object auction_wo = null; // the winning offer of the auction
		int missing_cnt = 0;
		
		//System.out.println(getAgentName()+" timeout: "+timeout);
			
		while(participate && running)
		{
			try
			{
				//System.out.println(getAgentName()+" waiting for: "+(firsttimeout==-1? buftimeout: firsttimeout));
				getLogger().info(getComponentName()+" waiting for: "+(firsttimeout==-1? buftimeout: firsttimeout));
				IMessageEvent msg = (IMessageEvent)waitForReply(dummy, firsttimeout==-1? buftimeout: firsttimeout);
				getLogger().info(getComponentName()+" received msg: "+msg.getType());
				missing_cnt = 0; // Reset missing_cnt as auction continues
				firsttimeout=-1;
				//System.out.println(getAgentName()+" received msg: "+msg.getType());
				
				
				if(msg.getType().equals("ea_cfp"))
				{
					// If has sitting out last round and a new round has been
					// issued reset winning_offer and sitting_out and continue
					// the auction
						
					if(winning_offer!=null)
					{
						//System.out.println(getAgentName()+" sitting out: "+msg.getContent());
						getLogger().info(getComponentName()+" sitting out: "+msg.getParameter(SFipa.CONTENT).getValue());
						winning_offer = null;
					}
					else
					{
						handleCFP(msg, auctiondesc, auctioninfo, offers);
					}
				}
				else if(msg.getType().equals("ea_accept_proposal"))
				{
					winning_offer = msg.getParameter(SFipa.CONTENT).getValue();
					getLogger().info(getComponentName()+" is currently winner for "+winning_offer);
					//System.out.println(getAgentName()+" is currently winner for "+winning_offer);
				}
				else if(msg.getType().equals("ea_reject_proposal"))
				{
					winning_offer = null;
				}
				else if(msg.getType().equals("ea_inform_end_auction"))
				{
					// res contains [boolean won, Object winning_offer] 
					Object[] res = (Object[])msg.getParameter(SFipa.CONTENT).getValue();
					
					if(!((Boolean)res[0]).booleanValue())
						winning_offer = null;
					
					auction_wo = res[1];
					running = false;
				}
				else
				{
					getLogger().warning((getComponentName()+" could not understand: "+msg));
				}
			}
			catch(TimeoutException e)
			{
				getLogger().info(getComponentName()+" "+e.getMessage());
				// Exit when no offers are received any more (for 3 times).
				//System.out.println(getAgentName()+" missed cfp: "+missing_cnt);
				if(++missing_cnt==3)
				{
					getLogger().info(getComponentName()+" leaving auction due to 3 missed cfps");
					//System.out.println(getAgentName()+" leaving auction due to 3 missed cfps");
					running = false;
				}
			}
		}
		
		//System.out.println(getAgentName()+" end");
		getLogger().info(getComponentName()+" auction end");
			
		if(!running)
			getParameter("result").setValue(new Object[]{winning_offer, auction_wo});
		
		getWaitqueue().removeReply(dummy);
	}
	
	/**
	 *  Decide about participation.
	 *  If the goal is not handled participation is true.
	 *  @param auctiondesc The auction description.
	 *  @return The participation state (Boolean) and the local auction info (Object).
	 */
	protected Object[] decideParticipation(AuctionDescription auctiondesc, IComponentIdentifier initiator)
	{
		Object[] ret = new Object[2];
		ret[0] = Boolean.TRUE; // participate
		ret[1] = null; // auction info
		
		try
		{
			IGoal dp = getScope().getGoalbase().createGoal("ea_decide_participation");
			dp.getParameter("auction_description").setValue(auctiondesc);
			dp.getParameter("initiator").setValue(initiator);
			dispatchSubgoalAndWait(dp);
			ret[1] = dp.getParameter("auction_info").getValue();
			Boolean part = (Boolean)dp.getParameter("participate").getValue();
			ret[0] = part==null? Boolean.TRUE: part;
		}
		catch(GoalFailureException e)
		{
			// Participate if no explicit decision was made.
			getLogger().info("Optional goal ea_decide_request has not been handled.");
		}
		
		return ret;
	}
	
	/**
	 *  Handle a cfp message.
	 *  @param auctiondesc The auction description.
	 *  @return The participation state (Boolean) and the local auction info (Object).
	 */
	protected Object[] handleCFP(IMessageEvent cfp, AuctionDescription auctiondesc, Object auctioninfo, List offers)
	{
		//System.out.println(getAgentName()+" handleCFP: "+cfp);
	
		Object[] ret = new Object[2];
		ret[0] = Boolean.TRUE; // participate
		ret[1] = auctioninfo;
		
		// Instantiate make_proposal-goal with the offer of the received CFP.
		IGoal mp = createGoal("ea_make_proposal");
		Object offer = cfp.getParameter(SFipa.CONTENT).getValue();
		offers.add(offer);
		mp.getParameter("cfp").setValue(offer);
		mp.getParameter("auction_description").setValue(auctiondesc);
		mp.getParameter("auction_info").setValue(auctioninfo);
		mp.getParameterSet("history").addValues(offers.toArray());
		try
		{
			dispatchSubgoalAndWait(mp, auctiondesc.getRoundTimeout());
		}
		catch(TimeoutException e)
		{
			getLogger().info(getComponentName() + e.getMessage());
		}
		ret[1] = mp.getParameter("auction_info").getValue();
		Boolean leave = (Boolean)mp.getParameter("leave").getValue();
		Boolean accept = (Boolean)mp.getParameter("accept").getValue();
		if(leave!=null && leave.booleanValue())
		{
			getLogger().info(getComponentName() + " informs the initiator of the auction "
				+auctiondesc.getTopic()+" that it doesn't want to participate.");
		
			sendMessage(getEventbase().createReply(cfp, "ea_not_understood"));
			
			// Set participate to false.
			ret[0] = Boolean.FALSE;
		}
		else if(accept!=null && accept.booleanValue())
		{
			//System.out.println(getAgentName()+" sending proposal: "+offer);
			getLogger().info(getComponentName()+" sending proposal: "+offer);
			// Send propsal.
			sendMessage(getEventbase().createReply(cfp, "ea_propose"));
		}
		
		return ret;
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy