ModularMultiTypeMovementModel.java 6.67 KB
Newer Older
1
2
3
4
package de.tud.kom.p2psim.impl.topology.movement.modularosm;

import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
5
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
6
7
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldStreetsMovement;
8
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy;
9
10
import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.Binder;
11
12
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
13
14

import java.util.HashMap;
15
import java.util.HashSet;
16
17

/**
18
 * This class is meant to be used with the RealWorldStreetsMovement
19
20
21
22
 * and allows changes of the movement type and the used {@link ITransitionStrategy} mid-simulation
 * on a per-host basis. It acts like the {@link ModularMovementModel}, but each of the {@link SimLocationActuator}s
 * can have a different movement type and {@link ITransitionStrategy}. All routes and target will be
 * calculated accordingly. <BR><BR>
23
24
 *
 * USAGE:
25
26
27
28
29
30
31
32
33
 * If you want to use different movement types, all you have to do is
 * (besides selecting this model it in your config) call the {@link #setMovementType(SimLocationActuator, String)}
 * for each of your components.<BR>
 *
 * The used {@link ITransitionStrategy} can be changed on runtime, too. However, the first
 * TransitionStrategy specified in the config will be used as default, and will be applied if there is
 * no further strategy specified for a specific host. To use multiple strategies, add them to your
 * config just as the first one. To set a specific strategy for a specific host, call the {@link #setTransitionForComponent(SimLocationActuator, Class)}
 * with the second parameter being the class of the transition strategy you want to use.
34
35
36
37
38
39
40
 *
 * NOTE: All the movement types you are using need to be specified in you config for the
 * {@link RealWorldStreetsMovement}. E.g if you are using 'car' and 'foot' movement types,
 * in you config the MovementType for the {@link RealWorldStreetsMovement} should be specified as 'car,foot'.
 * If not done properly there won't be an error, but the movement behaviour will be strange.
 *
 * @author Clemens Krug
41
42
43
44
 */
public class ModularMultiTypeMovementModel extends ModularMovementModel
{
    private HashMap<SimLocationActuator, String> movementTypes;
45
46
    private HashMap<SimLocationActuator, ITransitionStrategy> transitions;
    private HashMap<Class, ITransitionStrategy> supportedTransitions;
47
48
49
50
51

    public ModularMultiTypeMovementModel()
    {
        super();
        movementTypes = new HashMap<>();
52
53
        transitions = new HashMap<>();
        supportedTransitions = new HashMap<>();
54
55
    }

56
57
58
59
60
61
62
63
64
65
66
67
68
69
    @Override
    public void initialize()
    {
        super.initialize();

        for(ITransitionStrategy strategy : supportedTransitions.values())
        {
            strategy.setAttractionPoints(transition.getAllAttractionPoints());
            strategy.addAttractionAssignmentListener(this);
            for (SimLocationActuator ms : moveableHosts) {
                strategy.addComponent(ms);
            }
        }
    }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

    @Override
    protected void doLocalMovement(SimLocationActuator ms, PositionVector destination)
    {
        assert localMovementStrategy instanceof RealWorldStreetsMovement: "ModularMultiTypeMovementModel can only be used with RealWorldStreetsMovement!";

        Either<PositionVector, Boolean> either;
        if(movementTypes.containsKey(ms)) either =  ((RealWorldStreetsMovement) localMovementStrategy).nextPosition(ms, destination, movementTypes.get(ms));
        else either = localMovementStrategy.nextPosition(ms, destination);

        if (either.hasLeft()) {
            ms.updateCurrentLocation(either.getLeft());
			/*
			 * Check for negative or out of bound coordinates!
			 */
            assert ms.getRealPosition().getX() >= 0.0
                    && ms.getRealPosition().getX() <= Binder
                    .getComponentOrNull(Topology.class)
                    .getWorldDimensions().getX();
            assert ms.getRealPosition().getY() >= 0.0
                    && ms.getRealPosition().getY() <= Binder
                    .getComponentOrNull(Topology.class)
                    .getWorldDimensions().getY();
        } else {
94
95
            if(transitions.containsKey(ms)) transitions.get(ms).reachedAttractionPoint(ms);
            else transition.reachedAttractionPoint(ms);
96
97
98
99
100
101
102
        }
    }

    public void setMovementType(SimLocationActuator ms, String movementType)
    {
        movementTypes.put(ms, movementType);
    }
103
104
105
106
107

    public String getMovementType(SimLocationActuator ms)
    {
        return movementTypes.get(ms);
    }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

    public void setTransitionForComponent(SimLocationActuator ms, Class strategy)
    {
        ITransitionStrategy selectedStrategy = supportedTransitions.get(strategy);
        if(selectedStrategy == null)
        {
            throw new UnsupportedOperationException(
                    String.format("ModularMultiTypeMovementModel: TransitionStrategy %s ist not supported!", strategy.toString()));
        }
        changeTransitionStrategy(ms, selectedStrategy);

    }

    private void changeTransitionStrategy(SimLocationActuator ms, ITransitionStrategy newStrategy)
    {
        ITransitionStrategy usedStrategy = transitions.containsKey(ms) ? transitions.get(ms) : transition;
        newStrategy.updateTargetAttractionPoint(ms, usedStrategy.getAssignment(ms));
        transitions.put(ms, newStrategy);
        Monitor.log(ModularMultiTypeMovementModel.class, Monitor.Level.DEBUG, String.format("Client %s changed his transition strategy from %s to %s", ms.getHost().getId().toString(), usedStrategy.getClass(), newStrategy.getClass()));
    }

    public void returnToDefaultTransition(SimLocationActuator ms)
    {
        transitions.remove(ms);
    }

    @Override
    public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) {
        if(transitions.containsKey(actuator)) transitions.get(actuator).updateTargetAttractionPoint(actuator, ap);
        else transition.updateTargetAttractionPoint(actuator, ap);
    }

    @Override
    public void setITransitionStrategy(ITransitionStrategy transition) {
        if(supportedTransitions.size() == 0) this.transition = transition;
        supportedTransitions.put(transition.getClass(), transition);
    }

    @Override
    public AttractionPoint getTargetLocation(SimLocationActuator actuator) {
        if(transitions.containsKey(actuator)) return transitions.get(actuator).getAssignment(actuator);
        else return transition.getAssignment(actuator);
    }
151
}