farhanrahman / kyoto

18 stars 7 forks source link

TradeProtocol behaviour #119

Closed piotroslaw closed 12 years ago

piotroslaw commented 12 years ago

I have asked about it at uni, but could you (Farhan) write here or in wiki when exactly certain events happen?

What I mean is, say you broadcast an offer in tick 0 - when is the processInput function of other agents triggered? Straight away, at the very beginning of tick 1, during or after executing behaviour() in tick 1? Likewise, if you respond to offer in processInput, when is acceptTrade function triggered of the original poster? And finally, when is tradeWasX function called?

While we are at that, are the tradeWasX functions triggered for both sides of the trade, or just the responder?

Knowing this is absolutely vital to implementing the tradeProtocol in startegy for agents. On my part, I want to deal with only one transaction at the time, as keeping track of what I commited to but what could be rejected would be massively complicated. So, additionaly, is there some public function I could call to get info whether I'm engaded in any conversation at the moment? If not, I can write that using semaphores or even boolean flags, but for that I need to know when stuff happens.

Cheers in advance

farhanrahman commented 12 years ago

Thats a very good question...im outside now hold on to that..ill get back to you when I get home..

piotroslaw commented 12 years ago

No worries, I'll start implementing that at uni tomorrow anyway

farhanrahman commented 12 years ago

Okay in order to explain this I need to go through the internals of TradeProtocol. Apologies if I am repeating stuff here and if it gets too much into the TradeProtocol, but its the only way to answer the specific questions. Here goes:

So lets say there are two agents Pitt and Yiannis. In the example below Pitt = responder and Yiannis=initiator in the FSMProtocol. Pitt=broadcaster

1) Pitt decides to buy carbon and sends a broadcast message. In AbstractCountry you have a function called:

protected final OfferMessage broadcastBuyOffer(int quantity, double unitCost){
....
}

This creates an OfferMessage object which contains the unitcost and quantity that Pitt is interested in buying. Once created it returns the OfferMessage object. Note that here is where you get to keep a record of the object that was sent in the network. The way you keep track of the uniqueness is by querying the tradeID which is a unique UUID that is created for every offerMessage that gets sent into the network. Also note that the FSMProtocol has not been started yet i.e. no conversation exists yet.

2) Yiannis aggress to the offer and spawns a new message via functions given in the wiki page. This happens in the processInput function. Yiannis will receive the message possibly in the next tick. I am not too sure how the networking works precisely in Presage (this is a presage thing) so I assume that Yiannis receives the message in the next tick. I tested it and it seems to be the case. Not too sure if its otherwise. This starts an FSM Conversation. FSMProtocols works in state machines so Yiannis now transitions from START state to TRADE_PROPOSED state where he waits for Pitt to accept the offer.

3) Pitt receives the input message which calls a function in the FSMProtocol called processInitialMessage which makes Pitt transit from START to WAIT_FOR_CONFIRMATION state and CALLS THE acceptTrade() function which gives you as an agent the ability to decide whether you want to accept it. So summarising till now Pitt sends a message in tick 0, Yiannis receives it and starts a conversation in tick1, Pitt engages in the conversation that Yiannis started in tick2 which calls the acceptTrade() function. I assume that message transferring takes a single tick.

4) Pitt returns true to the acceptTrade() function and the TradeProtocol tries to adjust the carbonOffset and cash. If some exception is called during this, such as not enough cash exception then the changes are reverted and you as a responder agent get a notification that the trade has failed via the tradeHasFailed() notification (which you have to override if you want to get notified). Pitt still transits to the WAIT_FOR_CONFIRMATION state.

5) Lets say the changes made to carbonOffset and cash of Pitt were successful. Yiannis then receives the message (Yiannis is in the TRADE_PROPOSED state). TradeProtocol then tries to adjust the cash and carbonOffset of Yiannis. If there is an exception then the changes to Yiannis will be reverted and a revert message is sent to Pitt telling him that things messed up and you have to revert. Yiannis transits from TRADE_PROPOSED state to TRADE_DONE state. Here Yiannis gets notified that trade failed via the tradeHasFailed() function.

6) Going back to Pitt... two things can happen now. If Yiannis messed up then Pitt goes to REVERT state where the changes from the start of the conversation will be reverted and Pitt will be immediately notified that trade has failed via the tradeHasFailed() function. Note that at this point it is as though trade has never happened. You might think that why would you have to revert. Its because carbonOffset and cash has to be adjusted for both responder and initiator and this happens in different points of the conversation, so trade can fail at any point during the conversation. This is a mechanism to prevent this kind of a problem

7) On the other hand if Yiannis didn't mess up then Pitt will be notified that the trade was succesful via the tradeWasSuccessful() function. If trade was successful or if Pitt initially rejected then at this point Pitt transits from WAIT_FOR_CONFIRMATION to TRADE_DONE state where the whole conversation ends.

A VERY IMPORTANT thing to note here is that acceptTrade function is an asynchronous function. It gets called anytime (not in the execute function).

In order to know whether you are in conversation with a particular agent you should call the TradeProtocol function getActiveConversationMembers(). This returns a Set which is the set of participants you are currently in conversation with. This can be called from any point of the agent's allowed entry points.

Also if you want to see all the trades that has happened have a look at the TradeHistory interface. You can use that to get details of all the trades that has happened since tick 0.