package environment;
import agent.Agent;
import java.io.FileNotFoundException;
import parameters.LocalWorldParams;
import java.util.Observable;
import java.util.Observer;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
import constants.EnvironmentConstants;
import constants.EventConstants;
import constants.ResourceConstants;
import functions.EnvironmentFunction;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import resource.ColorResource;
import resource.Resource;
import resource.TraceResource;
import time.TimeEventDispatcher;
/**
*
* @author Marco Celesti
*/
public class World extends Observable implements Runnable, Observer {
private short idWorld;
private Thread thisThread;
private Cell[][] grid;
private List<Cell> bufferCells = new Vector<Cell>();
private Map<Short, Short> registry = new Hashtable<Short, Short>();
private boolean alive;
private LocalWorldParams params;
public World(short idWorld) {
this.idWorld = idWorld;
}
public void initializeEnviroinment() throws IOException {
grid = getGridFromFile(params.getMapFile());
for (short i = 0; i < params.getCols(); i++) {
for (short j = 0; j < params.getRows(); j++) {
grid[i][j].addObserver(this);
}
}
}
private Cell[][] getGridFromFile(File fileMap) throws FileNotFoundException, IOException {
Cell[][] localGrid;
Scanner scanner = new Scanner(fileMap);
String line = scanner.nextLine();
params.setCols(Short.parseShort(line.split("x")[0]));
params.setRows(Short.parseShort(line.split("x")[1]));
localGrid = new Cell[params.getCols()][params.getRows()];
String cellString = null;
String xString = null;
String yString = null;
String typeString = null;
String[] colorString = null;
short x = -1;
short y = -1;
Resource resource = null;
while (scanner.hasNextLine()) {
line = scanner.nextLine();
cellString = line.split("#")[0];
xString = (cellString.split(",")[0]).substring(1);
x = Short.parseShort(xString);
yString = (cellString.split(",")[1]).substring(0, cellString.split(",")[1].length() - 1);
y = Short.parseShort(yString);
xString = null;
yString = null;
cellString = null;
typeString = line.split("#")[1];
line = null;
if (typeString.startsWith(EnvironmentConstants.COLOR_RESOURCE)) {
colorString = typeString.split("@");
if (colorString.length == 1) {
resource = new ColorResource();
} else if (colorString.length > 1) {
resource = new ColorResource(colorString[1]);
}
} else if (typeString.startsWith(EnvironmentConstants.TRACE_RESOURCE)) {
resource = new TraceResource();
}
localGrid[x][y] = new Cell(x, y, resource, params);
}
scanner.close();
return localGrid;
}
public void setParams(LocalWorldParams params) {
this.params = params;
}
public LocalWorldParams getParams() {
return params;
}
public Cell getCell(int i, int j) {
return getCell((short) i, (short) j);
}
public Cell getCell(short i, short j) {
i = EnvironmentFunction.getNormalizedX(i, params.getCols());
j = EnvironmentFunction.getNormalizedY(j, params.getRows());
return grid[i][j];
}
public Cell[][] getGrid() {
return grid;
}
public void addGridObserver(Cell[][] gridToObserve, short cols, short rows) {
for (short i = 0; i < cols; i++) {
for (short j = 0; j < rows; j++) {
if (gridToObserve[i][j].countObservers() == 0) {
gridToObserve[i][j].addObserver(this);
}
}
}
}
public short getId() {
return idWorld;
}
public void startThread() {
if (thisThread != null) {
thisThread = null;
}
thisThread = new Thread(this);
thisThread.setName("world" + idWorld);
TimeEventDispatcher.getInstance().addThread(thisThread.getName());
alive = true;
thisThread.start();
}
public void stopThread() {
TimeEventDispatcher.getInstance().deleteThread(thisThread.getName());
}
public void run() {
while (alive) {
String timeEvent = TimeEventDispatcher.getInstance().getEvent(thisThread.getName());
}
}
private void worldChanged(Cell cell) {
if (countObservers() > 0) {
bufferCells.add(cell);
setChanged();
notifyObservers(EventConstants.CELL_EVENT);
}
}
public Cell getChangedCell() {
if (countObservers() > 0) {
return bufferCells.remove(0);
}
return null;
}
public short getNextAgentId(short progenitor) {
short id = 0;
if (registry.containsKey(progenitor)) {
id = registry.get(progenitor);
id++;
registry.remove(progenitor);
registry.put(progenitor, id);
} else {
registry.put(progenitor, id);
}
return id;
}
public void deleteTail(Agent tracer) {
System.err.println("\n[World.deleteTail]");
Cell birthCell = tracer.getBirthCell();
System.err.println("birthCell: " + birthCell);
TraceResource resource = (TraceResource) birthCell.getResource();
boolean oneSegment = false;
if (resource.getTracer().equals(tracer.toString())) {
oneSegment = deleteTail(birthCell);
}
if (!oneSegment) {
Cell deathCell = tracer.getDeathCell();
System.err.println("deathCell: " + deathCell);
resource = (TraceResource) deathCell.getResource();
if (resource.getTracer().equals(tracer.toString())) {
deleteTail(deathCell);
}
} else {
System.err.println("Only one segment");
}
}
private boolean deleteTail(Cell refCell) {
boolean clean = false;
boolean oneSegment = false;
Cell tmpCell = null;
while (!clean) {
short counter = -1;
Set<Cell> surroundings = EnvironmentFunction.getSurroundings(grid, refCell, 1, params.getCols(), params.getRows(), false);
for (Cell surrCell : surroundings) {
Resource artResource = surrCell.getResource();
if (artResource.getType() == ResourceConstants.ARTISTIC_TRACE_RESOURCE) {
counter++;
if (!surrCell.equals(refCell)) {
tmpCell = null;
tmpCell = new Cell(surrCell.getX(), surrCell.getY(), surrCell.getResource(), null);
}
}
}
if (counter <= 1) {
ColorResource newResource = new ColorResource();
grid[refCell.getX()][refCell.getY()].setResource(newResource);
grid[refCell.getX()][refCell.getY()].cellChanged();
if (counter == 0) {
oneSegment = true;
clean = true;
}
refCell = tmpCell;
} else {
clean = true;
}
}
return oneSegment;
}
@Override
public String toString() {
StringBuilder text = new StringBuilder();
for (int i = 0; i < params.getCols(); i++) {
for (int j = 0; j < params.getRows(); j++) {
text.append(grid[i][j].toString()).append("\n");
}
}
return text.toString();
}
public void update(Observable o, Object evt) {
String event = (String) evt;
if (event.equals(EventConstants.CELL_EVENT)) {
Cell cell = (Cell) o;
worldChanged(cell);
}
}
}