Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
QUORUM ?= 2
QUORUM ?= 3
PATH_PROJECT_JAR = target/simple_voting_structure-0.0.1-SNAPSHOT.jar
PROJECT_GROUP = simple_voting_structure
JADE_AGENTS = simple_voting_structure:$(PROJECT_GROUP).App($(QUORUM));
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/simple_voting_structure/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.Random;


/**
Expand Down Expand Up @@ -39,8 +38,6 @@ protected void setup() {
votersQuorum = Integer.parseInt(args[0].toString());
}

Random rand = new Random();

int votingStarter = rand.nextInt(votersQuorum);

logger.log(Level.INFO, "Agent number " + votingStarter + " will request to the mediator!");
Expand Down
96 changes: 92 additions & 4 deletions src/main/java/simple_voting_structure/BaseAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;

import java.util.logging.Logger;
import java.util.Random;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;

Expand All @@ -21,6 +25,11 @@ public abstract class BaseAgent extends Agent {
public static final String ANSWER = "ANSWER";
public static final String THANKS = "THANKS";
public static final String START = "START";
public static final String VOTEID = "VOTEID";
public static final String INVITE = "INVITE";
public static final String REGISTERED = "REGISTERED";
public static final String INFORM = "INFORM";
public static final String VOTE = "VOTE";

public static final String ANSI_RESET = "\u001B[0m";
public static final String ANSI_BLUE = "\u001B[34m";
Expand All @@ -32,23 +41,84 @@ public abstract class BaseAgent extends Agent {
public static final String ANSI_CYAN = "\u001B[36m";
public static final String ANSI_WHITE = "\u001B[37m";

protected static final Random rand = new Random();

protected int votingCode;

protected static final Logger logger = Logger.getLogger(BaseAgent.class.getName());

@Override
protected void setup() {}

protected CyclicBehaviour handleMessages () {
CyclicBehaviour handleMessages = new CyclicBehaviour(this) {
private static final long serialVersionUID = 1L;

public void action() {
ACLMessage msg = receive();

if ( msg == null ) block();
else {
switch ( msg.getPerformative() ) {
case ACLMessage.INFORM:
addBehaviour(handleInform(msg));
break;
case ACLMessage.REQUEST:
addBehaviour(handleRequest(msg));
break;
default:
logger.log(Level.INFO,
String.format("%s RECEIVED UNEXPECTED MESSAGE PERFORMATIVE FROM %s", getLocalName(), msg.getSender().getLocalName()));
}
}
}
};

return handleMessages;
}

protected OneShotBehaviour handleInform ( ACLMessage msg ) {
OneShotBehaviour handleInform = new OneShotBehaviour(this) {
private static final long serialVersionUID = 1L;

public void action () {}
};

return handleInform;
}

protected OneShotBehaviour handleRequest ( ACLMessage msg ) {
OneShotBehaviour handleRequest = new OneShotBehaviour(this) {
private static final long serialVersionUID = 1L;

public void action () {}
};

return handleRequest;
}

protected void registerDF(Agent regAgent, String sdName, String sdType) {
try {
DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(getAID());


ServiceDescription sd = new ServiceDescription();
sd.setType(sdType);
sd.setName(sdName);


DFAgentDescription [] found = DFService.search(this, dfd);

dfd.addServices(sd);

DFService.register(regAgent, dfd);
if ( found.length == 0 ) {
DFService.register(regAgent, dfd);
} else {
found[0].addServices(sd);
DFService.modify(regAgent, found[0]);
}

logger.log(Level.INFO, getLocalName()+" REGISTERED WITH THE DF" );
} catch (FIPAException e) {
e.printStackTrace();
Expand Down Expand Up @@ -79,6 +149,26 @@ protected DFAgentDescription[] searchAgentByType (String type) {
return foundAgents;
}

protected DFAgentDescription[] searchAgentByType (String [] type) {
DFAgentDescription search = new DFAgentDescription();

DFAgentDescription [] foundAgents = null;

for ( int i = 0; i < type.length; ++i ) {
ServiceDescription sd = new ServiceDescription();
sd.setType(type[i]);
search.addServices(sd);
}

try {
foundAgents = DFService.search(this, search);
} catch ( Exception any ) {
any.printStackTrace();
}

return foundAgents;
}

protected void takeDown() {
// Deregister with the DF
try {
Expand All @@ -92,10 +182,8 @@ protected void takeDown() {

protected void loggerSetup() {
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(new Formatter());
handler.setFormatter(new LogFormatter());
logger.setUseParentHandlers(false);
logger.addHandler(handler);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@

import java.util.logging.LogRecord;

public class Formatter extends java.util.logging.Formatter {

public Formatter() {
// TODO Auto-generated constructor stub
}
public class LogFormatter extends java.util.logging.Formatter {

@Override
public String format(LogRecord record) {
Expand Down
164 changes: 102 additions & 62 deletions src/main/java/simple_voting_structure/Mediator.java
Original file line number Diff line number Diff line change
@@ -1,88 +1,128 @@
package simple_voting_structure;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;

import FIPA.stringsHelper;
import jade.core.AID;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class Mediator extends BaseAgent {

private static final long serialVersionUID = 1L;

private int answersCnt = 0;

private int inpA, inpB;
private static final int MAX_VOTING_CODE = 9999;
private static final int MIN_VOTING_VALUE = 1;
private static final int MAX_VOTING_VALUE = 100;

private int votingAnswer = 0;
private int registeredQuorum = 0;
private int totalQuorum = 0;

@Override
protected void setup() {

logger.log(Level.INFO, "I'm the mediator!");

Object[] args = getArguments();
ArrayList<String> votersName = new ArrayList<String>();
this.registerDF(this, "Mediator", "mediator");

addBehaviour(handleMessages());
}

@Override
protected OneShotBehaviour handleInform ( ACLMessage msg ) {
OneShotBehaviour handleInform = new OneShotBehaviour(this) {
private static final long serialVersionUID = 1L;

public void action () {
if (msg.getContent().startsWith(START)) {
// send them a message requesting for a number;

votingCode = votingCodeGenerator();

setAns();

registerDF(myAgent, Integer.toString(votingCode), Integer.toString(votingCode));

registeredQuorum = 0;

logger.log(Level.INFO, String.format("%s AGENT GENERATED VOTING WITH CODE %d!", getLocalName(), votingCode));

ACLMessage msg2 = msg.createReply();

msg2.setContent(String.format("VOTEID %d MINVALUE %d MAXVALUE %d", votingCode, MIN_VOTING_VALUE, MAX_VOTING_VALUE));

send(msg2);
logger.log(Level.INFO, String.format("%s SENT VOTING CODE TO %s", getLocalName(), msg.getSender().getLocalName()));
} else if ( msg.getContent().startsWith(INFORM) ) {
String [] splittedMsg = msg.getContent().split(" ");

totalQuorum = Integer.parseInt(splittedMsg[2]);

logger.log(Level.INFO, String.format("EXPECTED QUORUM BY %s: %d VOTERS!", getLocalName(), totalQuorum));
} else if ( msg.getContent().startsWith(REGISTERED) ) {
++registeredQuorum;

if ( registeredQuorum == totalQuorum ) {
logger.log(Level.INFO, "TOTAL QUORUM REACHED! REQUESTING VOTES!");

requestVotes();
}
} else {
logger.log(Level.INFO,
String.format("%s RECEIVED AN UNEXPECTED MESSAGE FROM %s", getLocalName(), msg.getSender().getLocalName()));
}
}
};

if (args != null && args.length > 0) {
for (Object voter : args) {
votersName.add(voter.toString());
return handleInform;
}

private void requestVotes() {
try {
ACLMessage requestVoteMsg = new ACLMessage(ACLMessage.REQUEST);
requestVoteMsg.setContent(String.format("%s VOTE FOR %d", REQUEST, votingCode));

ArrayList<DFAgentDescription> foundVotingParticipants = new ArrayList<>();
String [] types = { Integer.toString(votingCode), "voter" };
foundVotingParticipants = new ArrayList<DFAgentDescription>(
Arrays.asList(searchAgentByType(types)));

if ( foundVotingParticipants.size() != registeredQuorum ) {
throw new Exception(String.format("FOUND VOTERS DIFFERS FROM REGISTERED QUORUM! (%d x %d)",
foundVotingParticipants.size(), registeredQuorum));
}

foundVotingParticipants.forEach(ag -> {
requestVoteMsg.addReceiver(ag.getName());
});

send(requestVoteMsg);
logger.log(Level.INFO,
String.format("%s REQUESTED A VOTE FOR ALL %d VOTERS!", getLocalName(), foundVotingParticipants.size()));
} catch (Exception e) {
e.printStackTrace();
}
}

private int votingCodeGenerator () {
int proposedCode;
DFAgentDescription [] foundAgents;

this.registerDF(this, "Mediator", "mediator");

addBehaviour(new CyclicBehaviour(this) {
public void action() {
// listen if a greetings message arrives
ACLMessage msg = receive(MessageTemplate.MatchPerformative(ACLMessage.INFORM));
if (msg != null) {
if (ANSWER.equalsIgnoreCase(msg.getContent().split(" ")[0])) {
// if an ANSWER to a greetings message is arrived
// then send a THANKS message
logger.log(Level.INFO, myAgent.getLocalName() + " RECEIVED ANSWER MESSAGE FROM " + msg.getSender().getLocalName());
ACLMessage replyT = msg.createReply();
replyT.setContent(THANKS);
myAgent.send(replyT);
logger.log(Level.INFO, myAgent.getLocalName() + " SENT THANKS MESSAGE");

if (msg.getSender().getLocalName().equals(votersName.get(0))) {
inpA = Integer.parseInt(msg.getContent().split(" ")[1]);
} else {
inpB = Integer.parseInt(msg.getContent().split(" ")[1]);
}

answersCnt++;
if (answersCnt == 2) {
ACLMessage replyW = new ACLMessage(ACLMessage.INFORM);

replyW.setContent((((inpA + inpB) % 2 != 0) ? ODD + " " + votersName.get(0)
: EVEN + " " + votersName.get(1)) + " WINNER!");
replyW.addReceiver(new AID(votersName.get(0), AID.ISLOCALNAME));
replyW.addReceiver(new AID(votersName.get(1), AID.ISLOCALNAME));
myAgent.send(replyW);
do {
proposedCode = rand.nextInt(MAX_VOTING_CODE);

foundAgents = searchAgentByType(Integer.toString(proposedCode));
} while ( foundAgents.length > 0 );

logger.log(Level.INFO, myAgent.getLocalName() + " SENT WINNER MESSAGE");
}
} else if (START.equalsIgnoreCase(msg.getContent())) {
// send them a message requesting for a number;
ACLMessage msg2 = new ACLMessage(ACLMessage.INFORM);
msg2.setContent(REQUEST);

msg2.addReceiver(new AID(votersName.get(0), AID.ISLOCALNAME));
msg2.addReceiver(new AID(votersName.get(1), AID.ISLOCALNAME));
return proposedCode;
}

send(msg2);
logger.log(Level.INFO, getLocalName() + " SENT REQUEST MESSAGE TO " + votersName.get(0) + " AND " + votersName.get(1));
} else {
logger.log(Level.INFO,
myAgent.getLocalName() + " Unexpected message received from " + msg.getSender().getLocalName());
}
} else {
// if no message is arrived, block the behaviour
block();
}
}
});
private void setAns(){
votingAnswer = rand.nextInt(MIN_VOTING_VALUE, MAX_VOTING_VALUE + 1);
}
}
Loading