/*
* 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.movement.modularosm.attraction;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedList;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* Generates attraction points out of real data from osm
* The maximal number of attraction points can be set
*
* @author Martin Hellwig
* @version 1.0, 02.07.2015
*
* Added an upper limit for the number of attraction points. Use 0 to allow all APs in the JSON file.
* @author Julian Zobel
* @version 1.1, November 2018
*
* You now can set an upper limit for the radius.
* @author Julian Zobel
* @version 1.2, January 2019
*
*
*/
public class JSONAttractionGenerator extends AbstractAttractionProvider {
protected int numberOfAttractionPoints;
protected String placementJsonFile = "";
protected double maximumRadius = -1; // Values >= 0, or -1 if radius taken from file
/**
* You have to set a json-file, which has set some POIs
* Sample-query for "bar"-POIs in Darmstadt (Bounding Box from [49.4813, 8.5590] to [49.9088, 8,7736]:
http://overpass-api.de/api/interpreter?data=%5Bout:json%5D;node%5Bamenity=bar%5D%2849%2E4813%2C8%2E5590%2C49%2E9088%2C8%2E7736%29%3Bout%3B
*/
@XMLConfigurableConstructor({"numberOfAttractionPoints", "maximumRadius", "placementJsonFile"})
public JSONAttractionGenerator(int numberOfAttractionPoints, double maximumRadius, String placementJsonFile) {
this.numberOfAttractionPoints = numberOfAttractionPoints;
this.maximumRadius = maximumRadius;
this.placementJsonFile = placementJsonFile;
createAttractionPoints();
}
@Override
public LinkedList getAttractionPoints() {
if(super.getAttractionPoints().size() == 0) {
createAttractionPoints();
}
return super.getAttractionPoints();
}
protected JSONArray getPOIArray() {
assert !placementJsonFile.equals("");
String poiString = "";
JSONArray allPOI = null;
FileInputStream inputStream;
try {
inputStream = new FileInputStream(placementJsonFile);
poiString = IOUtils.toString(inputStream);
JSONObject poiData = new JSONObject(poiString);
allPOI = poiData.getJSONArray("elements");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return allPOI;
}
private void createAttractionPoints() {
assert super.getAttractionPoints().size() == 0;
JSONArray allPOI = getPOIArray();
if(allPOI == null) {
throw new UnsupportedOperationException("[JSONAttractionGenerator] POI Data Array cannot be NULL.");
}
int limit = 0;
if(numberOfAttractionPoints == 0 || numberOfAttractionPoints > allPOI.length()) {
limit = allPOI.length();
}
else {
limit = numberOfAttractionPoints;
}
for(int i = 0; i < limit; i++) {
try {
String barname = allPOI.getJSONObject(i).getJSONObject("tags").getString("name");
double lat = allPOI.getJSONObject(i).getDouble("lat");
double lon = allPOI.getJSONObject(i).getDouble("lon");
AttractionPoint ap;
// check that the point is within the simulation boundaries
if(GPSCalculation.isWithinGPSBoundaries(lat, lon)) {
// initialize the attraction point with basic information, will be filled now...
ap = new AttractionPoint(barname, GPSCalculation.transformGPSWindowToOwnWorld(lat, lon));
// the following setters are allowed to fail
// AP weight
if(allPOI.getJSONObject(i).getJSONObject("tags").has("weight")) {
ap.setWeight(allPOI.getJSONObject(i).getJSONObject("tags").getDouble("weight"));
}
// AP radius
if(allPOI.getJSONObject(i).getJSONObject("tags").has("radius")) {
double radius = allPOI.getJSONObject(i).getJSONObject("tags").getDouble("radius");
if(maximumRadius == -1) {
ap.setRadius(radius);
}
else {
ap.setRadius(Math.min(maximumRadius, radius));
}
}
if(allPOI.getJSONObject(i).getJSONObject("tags").has("pauseTimeMin") && allPOI.getJSONObject(i).getJSONObject("tags").has("pauseTimeMax")) {
ap.setPauseTime( allPOI.getJSONObject(i).getJSONObject("tags").getLong("pauseTimeMin"), allPOI.getJSONObject(i).getJSONObject("tags").getLong("pauseTimeMax"));
}
addAttractionPoint(ap);
}
}
catch (JSONException e) {
//This bar had no name defined, so there was an error. Not so bad
System.out.println(e);
}
}
}
}