/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see .
*
*/
package de.tud.kom.p2psim.impl.topology.placement;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.BitSet;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* A configurable grid where occupied positions in the grid are configured via a
* simple matrix. Scales with the world-size.
*
* Format of the matrix: lines with 0,1,0,0,0,1\n0,1,...
*
* where 1 means: position a node and 0 means: empty cell.
*
*
* @author Bjoern Richerzhagen
* @version 1.0, Sep 19, 2013
*/
public class ConfigurableGridPositionDistribution implements PlacementModel {
private int numberOfComponents = 0;
private boolean randInCell = true;
private final String SEP = ",";
private final String OCCUPIED = "1";
private final String EMPTY = "0";
private int placedComponents = 0;
private int cols = -1;
private int rows = -1;
private BitSet occupiedBits = new BitSet();
private PositionVector worldDimensions = null;
private Random random = Randoms
.getRandom(ConfigurableGridPositionDistribution.class);
private List positions = new Vector();
@Override
public void addComponent(TopologyComponent comp) {
if (worldDimensions == null) {
worldDimensions = comp.getTopology().getWorldDimensions();
}
numberOfComponents++;
if (numberOfComponents == positions.size() + 1) {
System.err
.println("WARNING: Your specified positioning-topology does not contain enough places for the number of components in your scenario!");
}
}
@Override
public PositionVector place(TopologyComponent comp) {
if (positions.isEmpty()) {
calcPositions2D();
}
PositionVector pos = positions.get(placedComponents);
placedComponents = (placedComponents + 1) % positions.size();
return pos;
}
private void calcPositions2D() {
assert rows > 0 && cols > 0;
// float ratio = (float) (worldDimensions.getX() /
// worldDimensions.getY());
// float ratio_1 = 1 / ratio;
// int anz_x = ((int) Math.sqrt(ratio * cols * rows)) + 1;
int anz_x = cols;
// int anz_y = ((int) Math.sqrt(ratio_1 * cols * rows)) + 1;
int anz_y = rows;
int dist_x = (int) worldDimensions.getX() / anz_x;
int dist_y = (int) worldDimensions.getY() / anz_y;
for (int y = 0; y < anz_y; y++) {
for (int x = 0; x < anz_x; x++) {
if (occupiedBits.get(y * cols + x)) {
// valid
double xcenter = x * dist_x + dist_x / 2;
double ycenter = y * dist_y + dist_y / 2;
if (randInCell) {
xcenter += random.nextDouble() * dist_x / 4 - dist_x
/ 8;
ycenter += random.nextDouble() * dist_y / 4 - dist_y
/ 8;
}
PositionVector vec = new PositionVector(xcenter, ycenter);
positions.add(vec);
}
}
}
}
/**
* Allow a random offset between the grid points and the actual node
* position.
*
* @param randomOffset
* default: true
*/
public void setRandomOffset(boolean randomOffset) {
this.randInCell = randomOffset;
}
/**
* The given file is parsed.
*
* @param filename
*/
public void setPlacementFile(String file) {
BufferedReader csv = null;
try {
csv = new BufferedReader(new FileReader(file));
while (csv.ready()) {
String line = csv.readLine();
if (line.startsWith("#")) {
continue;
}
if (line.indexOf(SEP) > -1) {
String[] parts = line.split(SEP);
if (cols == -1) {
cols = parts.length;
}
assert cols == parts.length;
if (rows == -1) {
rows = 0;
}
int actCol = 0;
for (String part : parts) {
if (part.equals(OCCUPIED)) {
occupiedBits.set(rows * cols + actCol);
} else if (part.equals(EMPTY)) {
// ok.
} else {
throw new AssertionError("Unknown entry " + part);
}
actCol++;
}
rows++;
}
}
} catch (Exception e) {
throw new AssertionError("Positioning-Input failed!");
} finally {
if (csv != null) {
try {
csv.close();
} catch (IOException e) {
//
}
}
}
}
}