package io.hummer.prefetch.sim; import io.hummer.osm.OpenStreetMap; import io.hummer.prefetch.PrefetchingService.ServiceInvocation; import io.hummer.prefetch.context.Location; import io.hummer.prefetch.context.Path; import io.hummer.prefetch.context.Path.PathPoint; import io.hummer.prefetch.context.Time; import io.hummer.prefetch.impl.UsagePattern; import io.hummer.prefetch.sim.swisscom.CellularCoverage; import io.hummer.prefetch.sim.swisscom.NetworkOutagePath; import io.hummer.prefetch.sim.util.Util; import java.io.Serializable; import java.util.LinkedList; import java.util.List; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; /** * Evaluation scenario for service prefetching (vehicle simulation). * @author Waldemar Hummer (hummer@dsg.tuwien.ac.at) */ public class VehicleSimulation { @XmlRootElement public static class MovingEntities implements Serializable { private static final long serialVersionUID = 1L; @XmlElement(name="e") public List<MovingEntity> entities = new LinkedList<>(); public boolean containsID(String id) { return getEntity(id) != null; } public MovingEntity getEntity(String id) { for(MovingEntity e : entities) { if(id.equals(e.id)) return e; } return null; } } @XmlRootElement public static class ServiceUsagePattern { @XmlElement(name="inv") public ServiceInvocation invocation; @XmlElement(name="pat") public UsagePattern pattern; public ServiceUsagePattern() { } public ServiceUsagePattern(ServiceInvocation inv, UsagePattern pat) { this.invocation = inv; this.pattern = pat; } } @XmlRootElement public static class MovingEntity implements Serializable { private static final long serialVersionUID = 1L; @XmlElement(name="path") public final Path path = new Path(); @XmlAttribute public String id; @XmlTransient public List<ServiceUsagePattern> usagePatterns = new LinkedList<ServiceUsagePattern>(); public void addPathPoint(double time, double east, double north, double height, boolean loadDetails) { Time t = new Time(); t.time = time; Location c = new Location(); c.x = east; c.y = north; c.z = height; double[] coords = Util.convertSwissToGPS(east, north, height); c.lat = coords[0]; c.lon = coords[1]; PathPoint p = new PathPoint(); p.time = t; p.coordinates = c; p.cellNetworkCoverage = CellularCoverage.getCoverage(c.lat, c.lon); if(loadDetails) { p.isUndergroundTunnel = OpenStreetMap.isInTunnel(c.lat, c.lon); if(p.isUndergroundTunnel) { System.out.println("! Is in tunnel (length " + OpenStreetMap.getTunnelLength(c.lat, c.lon) + "): " + c.lat + "," + c.lon); } } path.add(p); } public List<NetworkOutagePath> getNetworkOutages() { List<NetworkOutagePath> result = new LinkedList<>(); NetworkOutagePath tmp = null; for(PathPoint p : path.points) { if(!p.cellNetworkCoverage.hasSufficientCoverage()) { if(tmp == null) tmp = new NetworkOutagePath(); tmp.path.add(p); } else { if(tmp != null) { result.add(tmp); System.out.println("No cell coverage here: " + tmp.path.get(0).coordinates + ", " + tmp.path.size() + " nodes, " + tmp.getLengthKM() + "km"); } tmp = null; } } return result; } public PathPoint getLocationAtTime(double t) { return path.getLocationAtTime(t); } public Path getFuturePathAt(double t) { return path.getFuturePathAt(t); } // public double getMissingDataSizeAtTime(double t) { // PathPoint pt = getLocationAtTime(t); // if(pt == null) // return 0; // double usage = predictNetworkUsage(t); // double capacity = // pt.cellNetworkCoverage.getMaxSpeed().getCapacityKbitPerSec(); // if(usage > capacity) // return usage - capacity; // return 0; // } // public double predictNetworkUsage(double time) { // List<UsagePattern> patterns = new LinkedList<UsagePattern>(); // for(ServiceUsagePattern p : usagePatterns) { // patterns.add(p.pattern); // } // return UsagePattern.combine( // patterns.toArray(new UsagePattern[0]) // ).predictUsage(time); // } } }