View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.agent.module.utils;
2   
3   import java.util.Collection;
4   import java.util.HashMap;
5   import java.util.HashSet;
6   import java.util.Map;
7   import java.util.Set;
8   
9   
10  import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
11  import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
12  import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils;
13  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
14  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BeginMessage;
15  import cz.cuni.amis.utils.IFilter;
16  
17  /**
18   * This class is a simple implementation of TabooSet (similar to TabooList). It allows you to insert
19   * items that are taboo either for infinite time (via {@link TabooSet#add(Object)}) or for a specified
20   * amount of UT2004 time (via {@link TabooSet#add(Object, double)}).
21   * <p><p>
22   * Items inside taboo set are either removed automatically due to a timeout (a specified amount of time has passed)
23   * or manually via {@link TabooSet#remove(Object)}.
24   */
25  public class TabooSet<T> implements IFilter<T> {
26  	
27  	public static interface IRelaxedTaboo<T> {
28  		
29  		public boolean isTaboo(T item, double remainingTabooTime);
30  		
31  	}
32  	
33  	/**
34  	 * Map of tabu items together with their time until which they are valid (negative time == valid for infinity).
35  	 */
36  	private Map<T, Double> taboo = new HashMap<T, Double>();	
37  	
38  	/**
39  	 * Return how many items are inside taboo set.
40  	 * @return
41  	 */
42  	public int size() {
43  		return taboo.size();
44  	}
45  	
46  	/**
47  	 * If not tabooized forever, it returns remaining time for the item to remain taboo.
48  	 * <p><p>
49  	 * If tabooized forever, returns {@link Double#POSITIVE_INFINITY}.
50  	 * <p><p>
51  	 * If item is not tabooized, returns 0.
52  	 * 
53  	 * @param item
54  	 * @return
55  	 */
56  	public double getTabooTime(T item) {
57  		Double tabooTime = taboo.get(item);
58  		if (tabooTime == null) return 0;
59  		if (tabooTime < 0) return Double.POSITIVE_INFINITY;
60  		if (tabooTime < time) {
61  			taboo.remove(item);
62  			return 0;
63  		} else {
64  			return tabooTime - time;
65  		}
66  	}
67  	
68  	/**
69  	 * Adds a tabu item that is valid for an infinite amount of time.
70  	 * @param item
71  	 */
72  	public void add(T item) {
73  		taboo.put(item, (double)-1);
74  	}
75  	
76  	/**
77  	 * Adds a tabu item that is valid for a period of 'timeout' time (in seconds).
78  	 * @param item
79  	 * @param timeout in seconds
80  	 */
81  	public void add(T item, double timeout) {
82  		taboo.put(item, time+timeout);
83  	}
84  	
85  	/**
86  	 * Removes a tabu item from the set.
87  	 * @param item
88  	 */
89  	public void remove(T item) {
90  		taboo.remove(item);
91  	}
92  	
93  	/**
94  	 * Determines whether an 'item' is inside tabu set or not based on the current
95  	 * UT2004 time.
96  	 * @param item
97  	 * @return
98  	 */
99  	public boolean isTaboo(T item) {
100 		if (taboo.containsKey(item)) {
101 			double tabooTime = taboo.get(item);
102 			if (tabooTime < 0) {
103 				return true;
104 			}
105 			if (tabooTime < time) {
106 				taboo.remove(item);
107 				return false;
108 			} else {
109 				return true;
110 			}
111 		} else {
112 			return false;
113 		}
114 	}
115 	
116 	/**
117 	 * Determines whether an 'item' is considered to be taboo using relaxed 'estimator'.
118 	 * @param item
119 	 * @param estimator
120 	 * @return
121 	 */
122 	public boolean isTaboo(T item, IRelaxedTaboo estimator) {
123 		if (!isTaboo(item)) {
124 			return false;
125 		} else {
126 			return estimator.isTaboo(item, getTabooTime(item));
127 		}
128 	}
129 	
130 	/**
131 	 * Method that is used by {@link DistanceUtils} methods to filter items.
132 	 * @param item
133 	 * @return returns !{@link TabooSet#isTaboo(Object)}
134 	 */
135 	@Override
136 	public boolean isAccepted(T item) {
137 		return !isTaboo(item);
138 	}
139 	
140 	
141 	/**
142 	 * Filters collection according to the current state of the tabu set. It returns a new hash set
143 	 * containing items from 'collection' that are not inside tabu set.
144 	 * 
145 	 * @param collection
146 	 * @return
147 	 */
148 	public Set<T> filter(Collection<T> collection) {
149 		Set<T> set = new HashSet<T>();
150 		for (T t : collection) {
151 			if (isTaboo(t)) continue;
152 			set.add(t);
153 		}
154 		return set;
155 	}
156 	
157 	/**
158 	 * Filters collection according to the current state of the tabu set. It returns a new hash set
159 	 * containing items from 'collection' that are not inside tabu set.
160 	 * 
161 	 * @param collection
162 	 * @return
163 	 */
164 	public Set<T> filter(Collection<T> collection, IRelaxedTaboo estimator) {
165 		Set<T> set = new HashSet<T>();
166 		for (T t : collection) {
167 			if (!isTaboo(t)) {
168 				set.add(t);
169 			} else {
170 				if (!estimator.isTaboo(t, getTabooTime(t))) {
171 						set.add(t);
172 				}
173 			}
174 		}
175 		return set;
176 	}
177 	
178 	
179 	
180 	/**
181 	 * Clears the taboo set.
182 	 */
183 	public void clear() {
184 		taboo.clear();
185 	}
186 	
187 	/**
188 	 * Returns current UT2004 time that is used by the TabooSet.
189 	 */
190 	public double getTime() {
191 		return time;
192 	}
193 	
194 	/**
195 	 * Current UT2004 time updated by {@link TabooSet#beginMessageListener}.
196 	 */
197 	private double time;
198 	
199 	/**
200 	 * {@link BeginMessage} listener that updates {@link TabooSet#time}.
201 	 * @author Jimmy
202 	 */
203 	private class BeginMessageListener implements IWorldEventListener<BeginMessage> {
204 
205 		
206 		public BeginMessageListener(IWorldView worldView) {
207 			worldView.addEventListener(BeginMessage.class, this);
208 		}
209 
210 		@Override
211 		public void notify(BeginMessage event) {
212 			time = event.getTime();
213 		}
214 		
215 	};
216 	
217 	/**
218 	 * {@link BeginMessage} listener that updates {@link TabooSet#time}.
219 	 */
220 	BeginMessageListener beginMessageListener;
221 	
222 	/**
223 	 * Constructor of the TabuSet.
224 	 * @param bot
225 	 */
226 	public TabooSet(UT2004Bot bot) {
227 		beginMessageListener = new BeginMessageListener(bot.getWorldView());
228 	}
229 
230 }