/**
*
*/
package iamrescue.communication.messages.codec.property;
import iamrescue.belief.entities.RoutingInfoBlockade;
import iamrescue.communication.messages.codec.BitStreamDecoder;
import iamrescue.communication.messages.codec.BitStreamEncoder;
import iamrescue.routing.WorldModelConverter;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.Property;
import rescuecore2.worldmodel.properties.IntArrayProperty;
/**
* @author Sebastian
*
*/
public class BlockedNeighboursCodec implements PropertyCodec {
// private WorldModelConverter converter;
private static final Logger LOGGER = Logger
.getLogger(BlockedNeighboursCodec.class);
public BlockedNeighboursCodec() {// WorldModelConverter converter) {
// this.converter = converter;
}
/*
* (non-Javadoc)
*
* @see
* iamrescue.communication.messages.codec.property.PropertyCodec#decode(
* rescuecore2.worldmodel.Entity,
* iamrescue.communication.messages.codec.BitStreamDecoder)
*/
@Override
public Property decode(Entity object, BitStreamDecoder decoder) {
WorldModelConverter converter = decoder.getBeliefBase().getConverter();
IntArrayProperty property = new IntArrayProperty(
RoutingInfoBlockade.BLOCK_INFO_URN);
int arrayLength = decoder.readNumber();
if (arrayLength == 0) {
property.setValue(new int[0]);
} else {
List<Integer> list = new ArrayList<Integer>();
boolean[] edges = new boolean[arrayLength];
for (int i = 0; i < arrayLength; i++) {
edges[i] = decoder.readBoolean();
}
// This works out the number of neighbours based on length of array
// (quadratic formula)
int neighbours = (int) Math.round(0.5 + Math
.sqrt(0.25 + 2 * arrayLength));
int counter = 0;
for (int i = 0; i < neighbours - 1; i++) {
for (int j = i + 1; j < neighbours; j++) {
if (edges[counter++]) {
list.add(i);
list.add(j);
}
}
}
int[] blocked = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
blocked[i] = list.get(i);
}
property.setValue(blocked);
}
return property;
}
/*
* (non-Javadoc)
*
* @see
* iamrescue.communication.messages.codec.property.PropertyCodec#encode(
* rescuecore2.worldmodel.Entity, rescuecore2.worldmodel.Property,
* iamrescue.communication.messages.codec.BitStreamEncoder)
*/
@Override
public void encode(Entity object, Property property,
BitStreamEncoder encoder) {
WorldModelConverter converter = encoder.getBeliefBase().getConverter();
RoutingInfoBlockade b = (RoutingInfoBlockade) object;
//LOGGER.info(b.getFullDescription());
// Work out all possible edges
EntityID position = b.getPosition();
int positionInt = position.getValue();
List<Integer> neighbours = converter.getSortedNeighbours(positionInt);
RoutingInfoBlockade block = (RoutingInfoBlockade) object;
int[] blockedEdges = block.getBlockedEdges();
// int highestIndex = 0;
// List<Integer> encoded = new ArrayList<Integer>();
boolean[] encoded = new boolean[neighbours.size()
* (neighbours.size() - 1) / 2];
int counterBlocked = 0;
int counterEncoded = 0;
boolean atLeastOne = false;
for (int i = 0; i < neighbours.size() - 1
&& counterBlocked < blockedEdges.length; i++) {
for (int j = i + 1; j < neighbours.size()
&& counterBlocked < blockedEdges.length; j++) {
if (blockedEdges[counterBlocked] == i
&& blockedEdges[counterBlocked + 1] == j) {
encoded[counterEncoded] = true;
atLeastOne = true;
counterBlocked += 2;
} else {
encoded[counterEncoded] = false;
}
counterEncoded++;
}
}
if (counterBlocked != blockedEdges.length) {
throw new IllegalStateException("Did not encode all blocks!");
}
if (atLeastOne) {
encoder.appendNumber(encoded.length);
for (int i = 0; i < encoded.length; i++) {
encoder.appendBoolean(encoded[i]);
}
} else {
encoder.appendNumber(0);
}
}
/*
* (non-Javadoc)
*
* @see
* iamrescue.communication.messages.codec.property.PropertyCodec#getPropertyKey
* ()
*/
@Override
public String getPropertyKey() {
return RoutingInfoBlockade.BLOCK_INFO_URN;
}
}