package pl.edu.agh.simulator;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import pl.edu.agh.assembler.LocationDataJSONAssembler;
import pl.edu.agh.assembler.LocationInfoJSONAssembler;
import pl.edu.agh.assembler.SimpleLocationInfoJSONAssembler;
import pl.edu.agh.jsonrpc.JSONRPCClient;
import pl.edu.agh.jsonrpc.JSONRPCException;
import pl.edu.agh.jsonrpc.JSONRPCHttpClient;
import pl.edu.agh.model.LocationData;
import pl.edu.agh.model.LocationInfo;
import pl.edu.agh.service.LocationLoggerService;
public class LocationDataSender {
private static final int LOCATION_HISTORY_MAX_SIZE = 1000;
private static final long LOCATION_SENDING_INTERVAL = 60; //[s]
protected final JSONRPCClient rpcClient;
private int vehicleNum = 0;
private long beginTime;
private int sends = 0;
private final Date startingTime;
private Date currentTime;
private long maxRequestTime = 0;
private final LocationDataJSONAssembler locationDataJSONAssembler;
private Map<String, LocationEntry> vehicles = new HashMap<String, LocationEntry>();
public LocationDataSender(String serviceUrl, Date startingTime) {
rpcClient = new JSONRPCHttpClient(serviceUrl);
this.startingTime = startingTime;
this.currentTime = startingTime;
SimpleLocationInfoJSONAssembler simpleAssembler = new SimpleLocationInfoJSONAssembler();
LocationInfoJSONAssembler locationInfoAssembler = new LocationInfoJSONAssembler(simpleAssembler);
locationDataJSONAssembler = new LocationDataJSONAssembler(locationInfoAssembler);
beginTime = System.currentTimeMillis();
}
public void put(String vehicleId, double lon, double lat, int time) {
LocationEntry entry = vehicles.get(vehicleId);
if(entry == null) {
entry = new LocationEntry();
vehicles.put(vehicleId, entry);
vehicleNum++;
}
LocationInfo info = new LocationInfo();
info.setLatitude(lat);
info.setLongitude(lon);
Date tempDate = new Date();
tempDate.setTime(this.startingTime.getTime() + time * 1000);
info.setTime(tempDate);
entry.addLocInfo(info);
entry.tick();
}
public void tick() {
currentTime.setTime(this.startingTime.getTime() + 1000);
for(LocationEntry entry : vehicles.values()) {
if(entry.isReady()) {
LocationData data = entry.getData();
entry.clear();
try {
JSONObject object = locationDataJSONAssembler.serialize(data);
long reqBegin = System.currentTimeMillis();
rpcClient.callJSONObject(LocationLoggerService.SEND_LOCATION_DATA_METHOD, object);
long reqTime = System.currentTimeMillis() - reqBegin;
if(reqTime > maxRequestTime) {
maxRequestTime = reqTime;
}
sends ++;
} catch (JSONException e) {
e.printStackTrace();
System.exit(-3);
}
catch (JSONRPCException e) {
e.printStackTrace();
System.exit(-2);
}
}
}
}
public double getSendingRate() {
return (double)sends/(double)(System.currentTimeMillis() - beginTime) * 1000.0;
}
public int getTotalCars() {
return vehicleNum;
}
public long getMaxRequestTime() {
return maxRequestTime;
}
public static class LocationEntry {
private LocationData data = new LocationData(new ArrayList<LocationInfo>());
private int ticks = 0;
public boolean isReady() {
return data.getLocationInfos().size() >= LOCATION_HISTORY_MAX_SIZE
|| ticks >= LOCATION_SENDING_INTERVAL;
}
public void addLocInfo(LocationInfo info) {
this.data.getLocationInfos().add(info);
}
public void tick() {
ticks++;
}
public void clear() {
ticks = 0;
data = new LocationData(new ArrayList<LocationInfo>());
}
public LocationData getData() {
return this.data;
}
}
}