at.uni_salzburg.cs.ckgroup.cpcc.mapper.algorithms.RandomTaskGenerator.java Source code

Java tutorial

Introduction

Here is the source code for at.uni_salzburg.cs.ckgroup.cpcc.mapper.algorithms.RandomTaskGenerator.java

Source

/*
 * @(#) RandomTaskGenerator.java
 *
 * This code is part of the CPCC project.
 * Copyright (c) 2012  Clemens Krainer
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package at.uni_salzburg.cs.ckgroup.cpcc.mapper.algorithms;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import at.uni_salzburg.cs.ckgroup.course.CartesianCoordinate;
import at.uni_salzburg.cs.ckgroup.course.IGeodeticSystem;
import at.uni_salzburg.cs.ckgroup.course.PolarCoordinate;
import at.uni_salzburg.cs.ckgroup.course.WGS84;
import at.uni_salzburg.cs.ckgroup.cpcc.mapper.api.IMapper;
import at.uni_salzburg.cs.ckgroup.cpcc.mapper.api.IMappingAlgorithm;
import at.uni_salzburg.cs.ckgroup.cpcc.mapper.api.IVirtualVehicleInfo;
import at.uni_salzburg.cs.ckgroup.cpcc.mapper.api.IVirtualVehicleStatus;

public class RandomTaskGenerator implements IMappingAlgorithm {

    private static final Logger LOG = Logger.getLogger(RandomTaskGenerator.class);

    private Map<String, VirtualVehicleInfo> vvInfo = new HashMap<String, RandomTaskGenerator.VirtualVehicleInfo>();

    private double minLatitude;

    private double maxLatitude;

    private double minLongitude;

    private double maxLongitude;

    private double minAltitude;

    private double maxAltitude;

    private int actionPointsPerVirtualVehicle;

    private double actionPointsArrivalRate;

    private IGeodeticSystem geodeticSystem = new WGS84();

    private long minimumIdleCyclesBeforeExport;

    private long idleCycles = 0;

    private String exportFileName;

    private File exportFile;

    private boolean tokenBucketDisabled;

    public RandomTaskGenerator() {
        // TODO get from properties file
        this.minLatitude = 47.69018658;
        this.maxLatitude = 47.69467816;
        this.minLongitude = 13.38173950;
        this.maxLongitude = 13.38841213;
        this.minAltitude = 1.0;
        this.maxAltitude = 1.0;
        this.actionPointsPerVirtualVehicle = 100;
        this.actionPointsArrivalRate = 0.1;
        this.minimumIdleCyclesBeforeExport = 10;
        this.exportFileName = "/tmp/vvRandomTaskExport.txt";
        this.exportFile = new File(this.exportFileName);
        this.tokenBucketDisabled = false;
    }

    @Override
    public void execute(IMapper mapper) {

        tokenBucketTick();

        boolean idle = true;

        List<IVirtualVehicleInfo> vehicleList = mapper.getVirtualVehicleList();

        for (IVirtualVehicleInfo vehicleInfo : vehicleList) {
            IVirtualVehicleStatus s = vehicleInfo.getVehicleStatus();
            String id = s.getId();

            VirtualVehicleInfo vvi = vvInfo.get(id);
            if (vvi == null) {
                vvi = new VirtualVehicleInfo(actionPointsPerVirtualVehicle, actionPointsArrivalRate);
                vvi.bucket = new TokenBucket(tokenBucketDisabled);
                vvInfo.put(id, vvi);
                idle = false;
            }

            ActionPoint ap = vvi.getNextActionPoint();
            if (ap != null) {
                idle = false;
                try {
                    addActionPointToVirtualVehicle(vehicleInfo, ap);
                } catch (IOException e) {
                    e.printStackTrace();
                    LOG.error("Bugger in addActionPointToVirtualVehicle", e);
                }
            }
        }

        if (idle) {
            if (idleCycles <= minimumIdleCyclesBeforeExport) {
                ++idleCycles;
            }
        } else {
            idleCycles = 0;
        }

        if (idleCycles > minimumIdleCyclesBeforeExport && !exportFile.exists()) {
            exportStatus(mapper);
        }
    }

    private void exportStatus(IMapper mapper) {
        LOG.info("Exporting VVs to file " + exportFile.getAbsolutePath());

        try {
            PrintWriter w = new PrintWriter(exportFile);
            w.print("VV;ACTION_POINT_NUMBER;LATITUDE;LONGITUDE;ALTITUDE;DISTANCE;ARRIVAL_TIME;ARRIVAL_TIME_DIFF;BUCKET_PASSED_TIME;BUCKET_DELAY;COMPLETED_TIME;DURATION\n");

            List<IVirtualVehicleInfo> vehicleList = mapper.getVirtualVehicleList();

            for (IVirtualVehicleInfo vehicleInfo : vehicleList) {
                try {
                    mergeVehicleData(vehicleInfo);
                } catch (Throwable e) {
                    e.printStackTrace();
                    LOG.error("Bugger in exportStatus 1", e);
                }

                IVirtualVehicleStatus s = vehicleInfo.getVehicleStatus();
                String vvId = s.getId();

                VirtualVehicleInfo info = vvInfo.get(vvId);

                int k = 0;
                ActionPoint oldAp = null;
                for (ActionPoint ap : info.actionPoints) {
                    long bucketDelay = ap.bucketPassedTime - ap.arrivalTime;
                    String bucketDelayString = bucketDelay > 0 ? String.format(Locale.US, "%d", bucketDelay) : "";
                    String distanceString = "";
                    String arrivalTimeDiffString = "";
                    if (oldAp != null) {
                        CartesianCoordinate X0 = geodeticSystem.polarToRectangularCoordinates(oldAp.position);
                        CartesianCoordinate X1 = geodeticSystem.polarToRectangularCoordinates(ap.position);
                        double distance = X0.subtract(X1).norm();
                        distanceString = String.format(Locale.US, "%.2f", distance);
                        arrivalTimeDiffString = String.format(Locale.US, "%d", ap.arrivalTime - oldAp.arrivalTime);
                    }
                    String completedTimeString = "";
                    String durationString = "";
                    if (ap.completedTime > 0) {
                        completedTimeString = String.format(Locale.US, "%d", ap.completedTime);
                        durationString = String.format(Locale.US, "%d", ap.completedTime - ap.arrivalTime);
                    }

                    w.printf(Locale.US, "\"%s\";%d;%.8f;%.8f;%.3f;%s;%d;%s;%d;%s;%s;%s\n", vvId, k++,
                            ap.position.getLatitude(), ap.position.getLongitude(), ap.position.getAltitude(),
                            distanceString, ap.arrivalTime, arrivalTimeDiffString, ap.bucketPassedTime,
                            bucketDelayString, completedTimeString, durationString);
                    oldAp = ap;
                }

            }

            w.close();
        } catch (IOException e) {
            e.printStackTrace();
            LOG.error("Bugger in exportStatus 2", e);
        }

    }

    private void mergeVehicleData(IVirtualVehicleInfo vehicleInfo)
            throws IOException, IllegalStateException, ParseException {

        String url = vehicleInfo.getEngineUrl() + "/json/vehicleDetails/" + vehicleInfo.getVehicleName();

        HttpGet httpGet = new HttpGet(url);
        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response = httpclient.execute(httpGet);

        HttpEntity entity = response.getEntity();
        if (entity != null) {
            JSONParser parser = new JSONParser();
            JSONObject vv = (JSONObject) parser.parse(new InputStreamReader(entity.getContent()));

            String vvId = (String) vv.get("vehicle.id");
            VirtualVehicleInfo info = vvInfo.get(vvId);
            if (info == null) {
                LOG.error("Virtual Vehicle " + vvId + " not known! URL=" + url);
                return;
            }

            JSONArray tasks = (JSONArray) vv.get("tasks");
            int k = 0;
            for (ActionPoint ap : info.actionPoints) {
                if (k >= tasks.size()) {
                    break;
                }
                JSONObject actionPoint = (JSONObject) tasks.get(k++);
                JSONArray actions = (JSONArray) actionPoint.get("actions");

                long time = 0;
                for (int j = 0; j < actions.size(); ++j) {
                    JSONObject a = (JSONObject) actions.get(j);
                    Long newTime = (Long) a.get("time");
                    if (newTime != null && newTime > time) {
                        time = newTime;
                    }
                }

                if (time > 0) {
                    ap.completedTime = time;
                }
            }
        }
    }

    private void addActionPointToVirtualVehicle(IVirtualVehicleInfo vehicleInfo, ActionPoint ap)
            throws IOException {

        String url = vehicleInfo.getEngineUrl() + "/vehicle/text/vehicleAddTask/" + vehicleInfo.getVehicleName();

        HttpPost httppost = new HttpPost(url);
        BasicHttpEntity entity1 = new BasicHttpEntity();
        entity1.setContent(ap.getInputStream());
        httppost.setEntity(entity1);

        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response = httpclient.execute(httppost);

        LOG.info("Add AP: " + response.getStatusLine());
    }

    private void tokenBucketTick() {
        for (Entry<String, VirtualVehicleInfo> entry : vvInfo.entrySet()) {
            entry.getValue().bucket.tick();
        }
    }

    private class VirtualVehicleInfo {
        public TokenBucket bucket = null;
        public List<ActionPoint> actionPoints = new ArrayList<RandomTaskGenerator.ActionPoint>();
        public int lastProcessedActionPoint = -1;

        public VirtualVehicleInfo(int apsToGenerate, double lambda) {
            long now = System.currentTimeMillis();
            for (int k = 0; k < apsToGenerate; ++k) {
                ActionPoint ap = new ActionPoint(now);
                ap.position = generatePosition();
                actionPoints.add(ap);
                now += (Math.random() * 2.0 * 1000.0 / lambda);
            }
        }

        private PolarCoordinate generatePosition() {
            double latitude = minLatitude + Math.random() * (maxLatitude - minLatitude);
            double longitude = minLongitude + Math.random() * (maxLongitude - minLongitude);
            double altitude = minAltitude + Math.random() * (maxAltitude - minAltitude);
            return new PolarCoordinate(latitude, longitude, altitude);
        }

        public ActionPoint getNextActionPoint() {
            int l = lastProcessedActionPoint + 1;
            if (l >= actionPoints.size()) {
                return null;
            }

            long now = System.currentTimeMillis();

            ActionPoint ap = actionPoints.get(l);
            if (ap.arrivalTime >= now) {
                return null;
            }

            //         The first has free pass, it just passes the bucket as though the bucket does not exists, i.e. A1_1 = A2_1.

            if (l == 0) {
                ++lastProcessedActionPoint;
                ap.bucketPassedTime = now;
                return ap;
            }

            //         For i >1, calculate V1_i = (X_i - X_(i-1)) / (A1_i - A2_(i-1)),

            ActionPoint oldAp = actionPoints.get(l - 1);

            CartesianCoordinate X0 = geodeticSystem.polarToRectangularCoordinates(oldAp.position);
            CartesianCoordinate X1 = geodeticSystem.polarToRectangularCoordinates(ap.position);

            double distance = X0.subtract(X1).norm();

            double v1 = 1000.0 * distance / (now - oldAp.bucketPassedTime);

            //         if V1_i <= nb, the i-th task passes the bucket, A1_i = A2_i, V1_i tokens are consumed.

            if (bucket.checkFreeTokens((int) v1)) {
                bucket.consumeTokens((int) v1);
                ++lastProcessedActionPoint;
                ap.bucketPassedTime = now;
                return ap;
            }

            //         If V1_i > nb, increase A2_i until V2_i = (X_i - X_(i-1)) / (A2_i - A2_(i-1)) <= nb, then the tasks passes the bucket.

            return null;
        }
    }

    private class ActionPoint {
        public PolarCoordinate position = null;
        public long arrivalTime;
        public long bucketPassedTime = 0;
        public long completedTime = 0;

        public ActionPoint(long arrivalTime) {
            this.arrivalTime = arrivalTime;
        }

        public InputStream getInputStream() {
            //         Point 47.69271040 13.38747686 20.00 tolerance 5 Picture Temperature Airpressure
            //         String v = String.format(Locale.US, "Point %.8f %.8f %.3f Tolerance 5 Picture Temperature Airpressure", position.getLatitude(), position.getLongitude(), position.getAltitude());
            String v = String.format(Locale.US, "Point %.8f %.8f %.3f Tolerance 5 Temperature",
                    position.getLatitude(), position.getLongitude(), position.getAltitude());
            return new ByteArrayInputStream(v.getBytes());
        }
    }

    private class TokenBucket {
        private double c;
        private double nb;
        private double B;
        private boolean passThrough;

        public TokenBucket(boolean passThrough) {
            c = 0.1;
            nb = 1;
            B = 1;
            this.passThrough = passThrough;
        }

        public void tick() {
            if (nb < B)
                nb += c;
            if (nb > B)
                nb = B;
        }

        public boolean checkFreeTokens(int tokens) {
            return passThrough ? true : tokens <= nb;
        }

        public void consumeTokens(int tokens) {
            if (passThrough) {
                return;
            }
            nb -= tokens;
        }
    }

}