package com.almende.eve.ggdemo;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import org.apache.http.annotation.ThreadSafe;
import com.almende.eve.protocol.jsonrpc.annotation.Access;
import com.almende.eve.protocol.jsonrpc.annotation.AccessType;
import com.almende.eve.protocol.jsonrpc.annotation.Name;
import com.almende.eve.protocol.jsonrpc.annotation.Sender;
import com.almende.eve.protocol.jsonrpc.formats.JSONRPCException;
import com.almende.util.jackson.JOM;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode;
@Access(AccessType.PUBLIC)
@ThreadSafe
public class LinPathAgent extends AbstractLampAgent {
public void handleGoal(@Name("goal") Goal goal, @Sender URI sender)
throws IOException, JSONRPCException, JsonProcessingException {
if (neighbours == null) {
neighbours = getNeighbours();
}
final List<String> nbs = Arrays.asList(neighbours.toArray(new String[0]));
Integer pointer = getState().get(goal.getId(), Integer.class);
if (pointer == null) {
for (int i = 0; i < nbs.size(); i++) {
if (nbs.get(i).equals(sender)) {
pointer = i;
}
}
if (pointer == null) {
pointer = 0; // should not happen.
}
}
Integer stepSize = getState().get("stepSize", Integer.class);
if (!getState().containsKey(goal.getId())) {
// Determine my own influence on the goal
double noOn = (goal.getPercentage() * goal.getAgentCnt()) / 100;
goal.setAgentCnt(goal.getAgentCnt() + 1);
double plus = (((noOn + 1) * 100) / (goal.getAgentCnt()));
double minus = (((noOn) * 100) / (goal.getAgentCnt()));
if (plus - goal.getGoalPct() < goal.getGoalPct() - minus) {
lampOn();
goal.setPercentage(plus);
} else {
lampOff();
goal.setPercentage(minus);
}
goal.setTtl(0);
} else {
double noOn = (goal.getPercentage() * goal.getAgentCnt()) / 100;
double newPerc = (((noOn + (isOn() ? -1 : 1)) * 100) / (goal
.getAgentCnt()));
if (Math.abs(goal.getGoalPct() - goal.getPercentage()) > Math
.abs(goal.getGoalPct() - newPerc)) {
goal.setPercentage(newPerc);
if (isOn()) {
lampOff();
} else {
lampOn();
}
goal.setTtl(0);
} else {
goal.setTtl(goal.getTtl() + 1);
}
}
if (goal.getTtl() > 15) {
// No changes, drop this goal.
return;
}
// Send goal further to neighbours
ObjectNode params = JOM.createObjectNode();
params.set("goal", JOM.getInstance().valueToTree(goal));
int count = 0;
int original_pointer = pointer;
boolean stop = false;
while (count < stepSize && !stop) {
String neighbour = nbs.get(pointer);
pointer++;
if (pointer >= nbs.size()) {
pointer = 0;
}
getState().put(goal.getId(), pointer);
if (nbs.size() > 1) {
if (neighbour.equals(sender)) {
continue;
}
if (pointer == original_pointer) {
stop = true;
}
}
count++;
call(URI.create(neighbour), "handleGoal", params, null);
}
getState().put("goal", goal);
}
}