RandomInAreaTransitionStrategy.java 4.45 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;

import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;

import java.util.*;

/**
 * Created by Clemens on 15.02.2017.
 */
public class RandomInAreaTransitionStrategy implements ITransitionStrategy
{
    private Random random;

    private LinkedHashSet<AttractionPoint> aPoints = new LinkedHashSet<>();

    private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<>();
    private Map<SimLocationActuator, AttractionPoint> currentTarget = new HashMap<>();

    private List<AttractionAssignmentListener> listeners = new LinkedList<>();

    private int defaultRadius;

    public RandomInAreaTransitionStrategy()
    {
        random = Randoms.getRandom(this.getClass());
    }

    @Override
    public AttractionPoint getAssignment(SimLocationActuator comp)
    {
        return currentTarget.get(comp);
    }

    @Override
    public void addAttractionAssignmentListener(AttractionAssignmentListener listener)
    {
        listeners.add(listener);
    }

    @Override
    public void removeAttractionAssignmentListener(AttractionAssignmentListener listener)
    {
        listeners.remove(listener);
    }

    @Override
    public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
        aPoints.addAll(attractionPoints);
    }

    @Override
    public Set<AttractionPoint> getAllAttractionPoints() {
        return aPoints;
    }

    @Override
    public void addComponent(SimLocationActuator ms) {
        if(!assignments.containsKey(ms))
        {
            AttractionPoint aPoint = aPoints.iterator().next();
            assignments.put(ms, aPoint);
            currentTarget.put(ms, nextRandomPosition(aPoint, defaultRadius));
        }
        listeners.forEach(listener -> listener.updatedAttractionAssignment(ms, currentTarget.get(ms)));
    }

    @Override
    public void reachedAttractionPoint(SimLocationActuator ms) {
        currentTarget.put(ms, nextRandomPosition(assignments.get(ms), defaultRadius));
        listeners.forEach(listener -> listener.updatedAttractionAssignment(ms, currentTarget.get(ms)));
    }

    @Override
    public void updateTargetAttractionPoint(SimLocationActuator comp, AttractionPoint attractionPoint) {
        assignments.put(comp, attractionPoint);
        currentTarget.put(comp, nextRandomPosition(attractionPoint, defaultRadius));
        listeners.forEach(listener -> listener.updatedAttractionAssignment(comp, attractionPoint));
    }

    public void updateTargetAttractionPoint(SimLocationActuator comp, AttractionPoint attractionPoint, int radius)
    {
        assignments.put(comp, attractionPoint);
        currentTarget.put(comp, nextRandomPosition(attractionPoint, radius));
        listeners.forEach(listener -> listener.updatedAttractionAssignment(comp, attractionPoint));
    }

    public void setDefaultRadius(int radius)
    {
        this.defaultRadius = radius;
    }

    private BasicAttractionPoint nextRandomPosition(Location center, int radius)
    {
        double x = center.getLongitude();
        double y = center.getLatitude();

        double newX = -1;
        double newY = -1;

        int tries = 0;

        while(newX < 0.0 || newX > Binder.getComponentOrNull(Topology.class).getWorldDimensions().getX()
                || newY < 0.0 || newY > Binder.getComponentOrNull(Topology.class).getWorldDimensions().getY())
        {
            double calcRadius = random.nextDouble() * radius;
            double calcAngle = random.nextDouble() * 360;

            newX = x + Math.sin(calcAngle) * calcRadius;
            newY = y + Math.cos(calcAngle) * calcRadius;
            tries++;

            if(tries > 100) throw new AssertionError("Unable to find a valid target destination within <100 tries.");
        }

        Monitor.log(this.getClass(), Monitor.Level.DEBUG, "Next random position is " + newX + " / " + newY);

        return new BasicAttractionPoint("RNDPOS", new PositionVector(newX, newY));

    }
}