package cz.agents.agentpolis.tools.geovisio.spy.darptestbed;
import java.awt.Color;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Map;
import org.apache.log4j.Logger;
import org.opengis.referencing.operation.TransformException;
import org.openstreetmap.osm.data.coordinates.LatLon;
import com.google.common.collect.Multimap;
import com.google.inject.Injector;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
import cz.agents.agentpolis.darptestbed.simmodel.agent.TestbedEntityType;
import cz.agents.agentpolis.darptestbed.simmodel.agent.data.Request;
import cz.agents.agentpolis.darptestbed.simmodel.agent.data.TimeWindow;
import cz.agents.agentpolis.darptestbed.simmodel.agent.driver.DriverAgent;
import cz.agents.agentpolis.darptestbed.simmodel.agent.driver.logic.DriverLogic;
import cz.agents.agentpolis.darptestbed.simmodel.agent.passenger.PassengerAgent;
import cz.agents.agentpolis.darptestbed.simmodel.agent.passenger.logic.PassengerLogic;
import cz.agents.agentpolis.simmodel.agent.Agent;
import cz.agents.agentpolis.simmodel.entity.EntityType;
import cz.agents.agentpolis.simmodel.environment.model.citymodel.transportnetwork.elemets.Node;
import cz.agents.agentpolis.tools.geovisio.annotation.spatial.SpatialFieldTypeEnum;
import cz.agents.agentpolis.tools.geovisio.attributesource.AttributeAllocator;
import cz.agents.agentpolis.tools.geovisio.attributesource.AttributeFieldSource;
import cz.agents.agentpolis.tools.geovisio.attributesource.AttributeSource;
import cz.agents.agentpolis.tools.geovisio.attributesource.AttributeSourceContainer;
import cz.agents.agentpolis.tools.geovisio.database.DatabaseComponentFactory;
import cz.agents.agentpolis.tools.geovisio.database.DatabaseTable;
import cz.agents.agentpolis.tools.geovisio.database.connection.DatabaseConnection;
import cz.agents.agentpolis.tools.geovisio.database.connection.DatabaseConnectionSettings;
import cz.agents.agentpolis.tools.geovisio.database.h2.H2GeometryTableInserter;
import cz.agents.agentpolis.tools.geovisio.database.h2.H2InMemoryComponentFactory;
import cz.agents.agentpolis.tools.geovisio.database.h2.H2InMemoryConnection;
import cz.agents.agentpolis.tools.geovisio.database.table.GeometryTableFactory;
import cz.agents.agentpolis.tools.geovisio.geometryadapter.GeometryAdapter;
import cz.agents.agentpolis.tools.geovisio.geometryadapter.GeometryNotCreatedException;
import cz.agents.agentpolis.tools.geovisio.geometryadapter.PointAdapter;
import cz.agents.agentpolis.tools.geovisio.geometryadapter.reader.CoordinateNotCreatedException;
import cz.agents.agentpolis.tools.geovisio.geometryadapter.reader.CoordinateReader;
import cz.agents.agentpolis.tools.geovisio.layer.GeometryRecord;
import cz.agents.agentpolis.tools.geovisio.projection.ProjectionTransformer;
import cz.agents.agentpolis.tools.geovisio.spy.agentpolis.AgentPolisDataReader;
import cz.agents.agentpolis.tools.geovisio.spy.agentpolis.AgentPolisNodeMapCoordinateReader;
import cz.agents.agentpolis.tools.geovisio.spy.darptestbed.RequestStorage.State;
/**
*
* @author Marek Cuchy
*
*/
public class DarpTestbedDataReader extends AgentPolisDataReader {
private static final Logger logger = Logger.getLogger(DarpTestbedDataReader.class);
private final int sourceSrid;
private PointAdapter agentPointAdapter;
private PointAdapter vehiclePointAdapter;
private H2InMemoryConnection connection;
private Collection<Agent> passengerAgents;
private AttributeSourceContainer passengerContainer;
private H2GeometryTableInserter passengerTableInserter;
private Collection<Agent> taxiDriverAgents;
private AttributeSourceContainer taxiDriverContainer;
private H2GeometryTableInserter taxiDriverTableInserter;
private final RequestStorage requestStorage;
private final DatabaseConnectionSettings settings;
private DarpTestbedVisParameterMapper visParameterMapper;
private ProjectionTransformer transformer;
private DatabaseComponentFactory dbFactory = new H2InMemoryComponentFactory();
public DarpTestbedDataReader(DatabaseConnectionSettings settings, Injector injector, String visName, int interval,
int sourceSrid, RequestStorage requestStorage) throws ReflectiveOperationException, InterruptedException {
super(injector, visName, interval);
this.sourceSrid = sourceSrid;
this.requestStorage = requestStorage;
this.settings = settings;
initSources();
}
@Override
public void readAndSaveData() throws IllegalArgumentException, SQLException, TransformException,
ReflectiveOperationException {
long start = System.currentTimeMillis();
logger.debug("Number of passengers saved: " + passengerAgents.size());
addToTable(passengerAgents, passengerContainer, passengerTableInserter, agentPointAdapter);
addToTable(taxiDriverAgents, taxiDriverContainer, taxiDriverTableInserter, vehiclePointAdapter);
long end = System.currentTimeMillis();
logger.debug("Dump time: " + (end - start));
}
private <X extends Geometry> void addToTable(Collection<?> list, AttributeSourceContainer container,
H2GeometryTableInserter inserter, GeometryAdapter<X> adapter) throws SQLException,
IllegalArgumentException, ReflectiveOperationException, TransformException {
AttributeAllocator<X> allocator = new AttributeAllocator<X>(container, visParameterMapper, adapter, transformer);
allocator.openConnections();
for (Object t : list) {
GeometryRecord<X> record;
try {
record = allocator.createRecord(t);
inserter.add(record);
} catch (GeometryNotCreatedException e) {
}
}
inserter.saveToDatabase();
allocator.closeConnections();
}
@Override
public void initReadingAndRead() throws Exception {
logger.info("start initing");
transformer = new ProjectionTransformer(sourceSrid, 4326);
connection = new H2InMemoryConnection(settings);
connection.connect();
// init position reader
Map<String, Long> agentsPositions = getAgentsPositions();
Map<String, Long> vehiclesPositions = getVehiclesPositions();
Map<Long, Node> allNodes = getAllNodes();
CoordinateReader coordinateReader = new AgentPolisNodeMapCoordinateReader(agentsPositions, allNodes);
agentPointAdapter = new PointAdapter(sourceSrid, coordinateReader);
CoordinateReader vehicleCoordinateReader = new AgentPolisNodeMapCoordinateReader(vehiclesPositions, allNodes);
vehiclePointAdapter = new PointAdapter(sourceSrid, vehicleCoordinateReader);
passengerContainer = initAttributeContainerForPassenger();
taxiDriverContainer = initAttributeContainerForTaxiDriver();
visParameterMapper = new DarpTestbedVisParameterMapper(requestStorage, currentTimeSource);
// vis = new Visualisation(visName, sourceSrid, 900913,
// visualisationSettings, boundingBox, visParameterMapper,
// true);
Multimap<EntityType, Agent> agentMap = classifyAgents(getAllAgents().values());
passengerAgents = agentMap.get(TestbedEntityType.PASSENGER);
taxiDriverAgents = agentMap.get(TestbedEntityType.TAXI_DRIVER);
// layer settings
// ColumnType geometryType = ColumnType.POINT;
// String styleName = NameSettings.POINT_PARAMETER_STYLE_NAME;
// boolean enableTimeDimension = true;
// boolean createIndexes = false;
passengerTableInserter = createTableAndInserter(passengerContainer, "passengers");
taxiDriverTableInserter = createTableAndInserter(taxiDriverContainer, "taxi_drivers");
// passengerLayer = vis.visualize(passengerAgents, passengerContainer,
// new LayerSettings(geometryType,
// "passengers", styleName, enableTimeDimension, createIndexes),
// agentPointAdapter);
// taxiDriverlayer = vis.visualize(taxiDriverAgents,
// taxiDriverContainer, new LayerSettings(geometryType,
// "taxi_drivers", styleName, enableTimeDimension, createIndexes),
// vehiclePointAdapter);
visualizeNodes(allNodes);
// init event handler
initHandeling();
logger.info("initing finished");
}
private H2GeometryTableInserter createTableAndInserter(AttributeSourceContainer container, String tableName)
throws SQLException {
GeometryTableFactory tableFactory = new GeometryTableFactory(dbFactory);
DatabaseTable table = tableFactory.createGeomTable(tableName, Point.class, container);
connection.executeUpdate(table.getCreateSQL());
return new H2GeometryTableInserter(table, connection);
}
private void visualizeNodes(Map<Long, Node> allNodes) throws IllegalArgumentException, SQLException,
TransformException, ReflectiveOperationException {
AttributeSourceContainer nodesContainer = createAttributeContainerForNodes();
PointAdapter adapter = new PointAdapter(sourceSrid, new CoordinateReader() {
@Override
public Coordinate getCoordinate(Object source) throws SQLException, CoordinateNotCreatedException {
LatLon ll = (LatLon) source;
return new Coordinate(ll.lon(), ll.lat());
}
@Override
public void connect() throws SQLException, ClassNotFoundException {
}
@Override
public void close() throws SQLException {
}
});
H2GeometryTableInserter nodesInserter = createTableAndInserter(nodesContainer, "nodes");
addToTable(allNodes.values(), nodesContainer, nodesInserter, adapter);
}
private AttributeSourceContainer createAttributeContainerForNodes() throws ReflectiveOperationException {
AttributeSourceContainer container = new AttributeSourceContainer();
container.addToSpatialFields(SpatialFieldTypeEnum.SINGLE_NODE,
reflectionFactory.createAttributeFieldSource(Node.class, "latLon"));
container.add(reflectionFactory.createAttributeFieldSource(Node.class, "id", "node_id"));
return container;
}
private AttributeSourceContainer initAttributeContainerForTaxiDriver() throws ReflectiveOperationException {
AttributeSourceContainer container = createSourceContainerForBasicAgent();
AttributeFieldSource logicSource = reflectionFactory.createAttributeFieldSource(DriverAgent.class, "logic");
AttributeFieldSource vehicleSource = reflectionFactory.createAttributeFieldSource(DriverLogic.class, "vehicle",
logicSource);
container.addAll(createAttributeSourcesForVehicle(vehicleSource));
container.add(reflectionFactory.createAttributeFieldSource(DriverLogic.class, "numOfPassenToGetIn",
"number_of_passengers_to_get_in", logicSource));
container.add(reflectionFactory.createAttributeMethodSource(DriverLogic.class, "isOnTheWay", "is_on_the_way",
logicSource));
container.add(reflectionFactory.createAttributeMethodSource(DriverLogic.class, "isEverybodyOnBoard",
"is_everybody_on_board", logicSource));
return container;
}
private AttributeSourceContainer initAttributeContainerForPassenger() throws ReflectiveOperationException {
AttributeSourceContainer container = createSourceContainerForBasicAgent();
AttributeFieldSource logicSource = reflectionFactory.createAttributeFieldSource(PassengerAgent.class, "logic");
final AttributeFieldSource confirmedRequestSource = reflectionFactory.createAttributeFieldSource(
PassengerLogic.class, "currentRequestConfirmed");
final AttributeFieldSource lastSentRequestSource = reflectionFactory.createAttributeFieldSource(
PassengerLogic.class, "requestLastSent");
AttributeSource requestSource = new AttributeSource(logicSource) {
@Override
protected Object getValueFromSource(Object source) throws IllegalArgumentException,
ReflectiveOperationException {
Object confirmedRequest = confirmedRequestSource.getValue(source);
if (confirmedRequest != null) {
return confirmedRequest;
} else {
return lastSentRequestSource.getValue(source);
}
}
};
AttributeFieldSource agentIdSource = createAgentIdSource();
AttributeSource requestStatusSource = new AttributeSource(agentIdSource, "request_status", String.class) {
@Override
protected Object getValueFromSource(Object source) throws IllegalArgumentException,
ReflectiveOperationException {
long time = currentTimeSource.getValue(source);
State state = requestStorage.getCurrentState((String) source, time);
return state;
}
};
container.add(requestStatusSource);
container.add(reflectionFactory.createAttributeFieldSource(PassengerLogic.class, "currentDriverId",
"current_driver_id", logicSource));
container.add(reflectionFactory.createAttributeFieldSource(PassengerLogic.class, "currentVehicleId",
"current_vehicle_id", logicSource));
AttributeSource successfulArrivalTimeSource = new AttributeSource(logicSource, "successful_arrival_time",
Timestamp.class) {
@Override
protected Object getValueFromSource(Object source) throws IllegalArgumentException, ReflectiveOperationException {
PassengerLogic logic = (PassengerLogic) source;
return logic.getSuccessfulArrivalTime();
}
};
container.add(successfulArrivalTimeSource);
container.add(reflectionFactory.createAttributeFieldSource(Request.class, "fromNode", "request_from_node",
requestSource));
container.add(reflectionFactory.createAttributeFieldSource(Request.class, "toNode", "request_to_node",
requestSource));
AttributeFieldSource timeWindowSource = reflectionFactory.createAttributeFieldSource(Request.class,
"timeWindow", requestSource);
container.add(reflectionFactory.createAttributeFieldSource(TimeWindow.class, "departMin",
"request_departure_min", timeWindowSource, Timestamp.class));
container.add(reflectionFactory.createAttributeFieldSource(TimeWindow.class, "departMax",
"request_departure_max", timeWindowSource, Timestamp.class));
container.add(reflectionFactory.createAttributeFieldSource(TimeWindow.class, "arriveMin",
"request_arrival_min", timeWindowSource, Timestamp.class));
container.add(reflectionFactory.createAttributeFieldSource(TimeWindow.class, "arriveMax",
"request_arrival_max", timeWindowSource, Timestamp.class));
container.add(reflectionFactory.createAttributeFieldSource(Request.class, "callTimeInDayRange",
"request_call_time", requestSource, Timestamp.class));
return container;
}
@Override
public void onSimulationFinished() throws SQLException, TransformException {
// passengerLayer.createIndexes();
// taxiDriverlayer.createIndexes();
passengerTableInserter.createIndexes();
taxiDriverTableInserter.createIndexes();
// layers created by selects from tables created during simulation
// createTaxiToPassengerLayer();
// createRequestLayer();
// vis.closeConnectionToDb();
}
/**
* Create layer with requests from already existing tables
*
* @throws SQLException
* @throws TransformException
*/
private void createRequestLayer() throws SQLException, TransformException {
String layerName = "requests";
DatabaseTable table = dbFactory.createTable(layerName);
table.addColumn(dbFactory.createColumn("geom", LineString.class, true));
table.addColumn(dbFactory.createColumn("from_time", Timestamp.class, true));
table.addColumn(dbFactory.createColumn("passenger", String.class, true));
table.addColumn(dbFactory.createColumn("taxi_driver", String.class, true));
table.addColumn(dbFactory.createColumn("request_status", String.class, true));
table.addColumn(dbFactory.createColumn("request_departure_min", Timestamp.class, true));
table.addColumn(dbFactory.createColumn("request_departure_max", Timestamp.class, true));
table.addColumn(dbFactory.createColumn("request_arrival_min", Timestamp.class, true));
table.addColumn(dbFactory.createColumn("request_arrival_max", Timestamp.class, true));
table.addColumn(dbFactory.createColumn("successful_arrival_time", Timestamp.class, true));
table.addColumn(dbFactory.createColumn("color", double.class, true));
table.addColumn(dbFactory.createColumn("style_parameter", double.class, true));
connection.createComponent(table);
// vis.getGeoserverConnection().publishLayer(
// new Layer<LineString>(layerName, table, visName, visName,
// NameSettings.LINE_PARAMETER_STYLE_NAME, vis
// .getProjectionTransformer().transform(boundingBox), true), 900913);
Color color = Color.MAGENTA;
double styleParam = 2;
DatabaseConnection conn = connection;
conn.executeUpdate("INSERT INTO "
+ table.getFullName()
+ " select st_setsrid(st_makeline(n1.geom,n2.geom),900913) as geom,pas.from_time,pas.agentid as passenger, pas.current_driver_id as taxi_driver,pas.request_status,pas.request_departure_min, pas.request_departure_max,pas.request_arrival_min, pas.request_arrival_max, "
+ color.getRGB() + " as color," + styleParam + "as style_parameter from " + "passengers as pas, "
+ "nodes as n1, "
+ "nodes as n2 where pas.request_from_node = n1.node_id and pas.request_to_node = n2.node_id ");
conn.executeUpdate(table.getCreateIndexesSQL());
}
/**
* Create layer with taxis assigned to passenger from already existing
* tables
*
* @throws SQLException
* @throws TransformException
*/
private void createTaxiToPassengerLayer() throws SQLException, TransformException {
String layerName = "taxi_to_passenger_pair";
DatabaseTable table = dbFactory.createTable(layerName);
table.addColumn(dbFactory.createColumn("geom", LineString.class, true));
table.addColumn(dbFactory.createColumn("from_time", Timestamp.class, true));
table.addColumn(dbFactory.createColumn("passenger", String.class, true));
table.addColumn(dbFactory.createColumn("taxi_driver", String.class, true));
table.addColumn(dbFactory.createColumn("color", double.class, true));
table.addColumn(dbFactory.createColumn("style_parameter", double.class, true));
connection.createComponent(table);
// vis.getGeoserverConnection().publishLayer(
// new Layer<LineString>(layerName, table, visName, visName,
// NameSettings.LINE_PARAMETER_STYLE_NAME, vis
// .getProjectionTransformer().transform(boundingBox), true), 900913);
Color color = Color.CYAN;
double styleParam = 2;
DatabaseConnection conn = connection;
conn.executeUpdate("INSERT INTO "
+ table.getFullName()
+ " select st_setsrid(st_makeline(pas.geom , taxi.geom),900913) as geom,pas.from_time, pas.agentid as passenger, taxi.agentid as taxi_driver, "
+ color.getRGB() + " as color, " + styleParam + " as style_parameter from "
+ "passengers as pas inner join "
+ "taxi_drivers as taxi on pas.current_driver_id = taxi.agentid and pas.from_time = taxi.from_time ");
conn.executeUpdate(table.getCreateIndexesSQL());
}
}