1 /*******************************************************************************
2 * jhunters: Pool League
3 * Copyright 2015 Tony Washer
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ********************************************************************************/
17 package net.sourceforge.jhunters.pool.data;
18
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22
23 import javafx.beans.Observable;
24 import javafx.collections.FXCollections;
25 import javafx.collections.ObservableList;
26 import net.sourceforge.jhunters.pool.PoolStatus;
27
28 /**
29 * Player List.
30 */
31 public class PlayerList {
32 /**
33 * Player List Name.
34 */
35 protected static final String LIST_NAME = DataResource.PLAYER_LIST.getValue();
36
37 /**
38 * The list of Players.
39 */
40 private final ObservableList<Player> thePlayers;
41
42 /**
43 * The status of the list.
44 */
45 private PoolStatus theStatus;
46
47 /**
48 * The nextId.
49 */
50 private int theNextId = 1;
51
52 /**
53 * Constructor.
54 */
55 protected PlayerList() {
56 /* Create the player list with an extractor to allow SortedList to work */
57 thePlayers = FXCollections.observableArrayList(p -> new Observable[] { p.nameProperty(), p.contactProperty(), p.selectedProperty() });
58 }
59
60 /**
61 * Obtain player list.
62 * @return the player list
63 */
64 public ObservableList<Player> getPlayers() {
65 return thePlayers;
66 }
67
68 /**
69 * Obtain number of players.
70 * @return # of players
71 */
72 public int size() {
73 return thePlayers.size();
74 }
75
76 /**
77 * Is the list of players empty?
78 * @return true/false
79 */
80 public boolean isEmpty() {
81 return thePlayers.isEmpty();
82 }
83
84 /**
85 * Obtain the status.
86 * @return the status.
87 */
88 public PoolStatus getStatus() {
89 return theStatus;
90 }
91
92 /**
93 * Obtain player iterator.
94 * @return the iterator list
95 */
96 public Iterator<Player> playerIterator() {
97 return thePlayers.iterator();
98 }
99
100 /**
101 * Obtain named player from list.
102 * @param pName the player name.
103 * @return the player (or null if not found)
104 */
105 public Player getNamedPlayer(final String pName) {
106 /* Loop through the list */
107 Iterator<Player> myIterator = thePlayers.iterator();
108 while (myIterator.hasNext()) {
109 Player myPlayer = myIterator.next();
110
111 /* Return if we have found the player */
112 if (pName.equals(myPlayer.getName())) {
113 return myPlayer;
114 }
115 }
116
117 /* Not found */
118 return null;
119 }
120
121 /**
122 * Create unique player.
123 * @return the unique player
124 */
125 public Player createUniquePlayer() {
126 /* Create the builder */
127 StringBuilder myBuilder = new StringBuilder();
128 myBuilder.append("Player");
129 int myLen = myBuilder.length();
130
131 /* Loop through the list */
132 int myIndex = 0;
133 Player myPlayer;
134 String myName;
135
136 /* Loop to find a unique name */
137 do {
138 /* Reset the buffer and adjust index */
139 myBuilder.setLength(myLen);
140 myIndex++;
141
142 /* Create name */
143 myBuilder.append(myIndex);
144 myName = myBuilder.toString();
145 myPlayer = getNamedPlayer(myName);
146
147 /* ReLoop if already exists */
148 } while (myPlayer != null);
149
150 /* Create the player */
151 myPlayer = new Player();
152 myPlayer.setName(myName);
153
154 /* Create a unique id */
155 setUniqueId(myPlayer);
156
157 /* Add the name to the list and return it */
158 thePlayers.add(myPlayer);
159 return myPlayer;
160 }
161
162 /**
163 * Set active status.
164 * @param pValue the active status
165 */
166 protected void setActive(final Boolean pValue) {
167 /* Loop through the list */
168 Iterator<Player> myIterator = thePlayers.iterator();
169 while (myIterator.hasNext()) {
170 Player myPlayer = myIterator.next();
171
172 /* set active status */
173 myPlayer.setActive(pValue);
174 }
175 }
176
177 /**
178 * Add a player to the list.
179 * @param pPlayer the player.
180 */
181 public void addPlayer(final Player pPlayer) {
182 /* If player does not already exist */
183 if ((pPlayer != null)
184 && (getNamedPlayer(pPlayer.getName()) == null)) {
185 /* If the id is not set */
186 Integer myId = pPlayer.getId();
187 if (myId == 0) {
188 /* Create a unique id */
189 setUniqueId(pPlayer);
190
191 /* else adjust next id */
192 } else if (myId >= theNextId) {
193 theNextId = myId + 1;
194 }
195
196 /* Add the player */
197 thePlayers.add(pPlayer);
198 }
199 }
200
201 /**
202 * Set unique id.
203 * @param pPlayer the player to set
204 */
205 private synchronized void setUniqueId(final Player pPlayer) {
206 /* Determine next available id */
207 Integer myNext = theNextId++;
208 pPlayer.setId(myNext);
209 }
210
211 /**
212 * Remove a player from the list.
213 * @param pPlayer the player.
214 */
215 public void removePlayer(final Player pPlayer) {
216 thePlayers.remove(pPlayer);
217 }
218
219 /**
220 * Set players.
221 * @param pSource the source players.
222 */
223 protected void setPlayers(final Iterator<Player> pSource) {
224 /* reset the player list */
225 thePlayers.clear();
226
227 /* Loop through the source list */
228 while (pSource.hasNext()) {
229 Player myPlayer = pSource.next();
230
231 /* Add the player */
232 thePlayers.add(myPlayer);
233
234 /* Adjust next if necessary */
235 Integer myId = myPlayer.getId();
236 if (myId >= theNextId) {
237 theNextId = myId + 1;
238 }
239 }
240 }
241
242 @Override
243 public boolean equals(final Object pThat) {
244 /* Handle trivial cases */
245 if (this == pThat) {
246 return true;
247 }
248 if (pThat == null) {
249 return false;
250 }
251
252 /* Handle wrong class */
253 if (!(pThat instanceof PlayerList)) {
254 return false;
255 }
256
257 /* Access as player list */
258 PlayerList myThat = (PlayerList) pThat;
259
260 /* Test only on player list */
261 return thePlayers.equals(myThat.getPlayers());
262 }
263
264 @Override
265 public int hashCode() {
266 return thePlayers.hashCode();
267 }
268
269 /**
270 * Validate players.
271 * @return the status
272 */
273 public PoolStatus validate() {
274 /* Create id and name maps */
275 Map<String, PoolStatus> myNameMap = new HashMap<String, PoolStatus>();
276 Map<Integer, PoolStatus> myIdMap = new HashMap<Integer, PoolStatus>();
277 theStatus = PoolStatus.VALID;
278
279 /* Loop through the players */
280 Iterator<Player> myIterator = playerIterator();
281 while (myIterator.hasNext()) {
282 Player myPlayer = myIterator.next();
283
284 /* Validate the player */
285 PoolStatus myStatus = myPlayer.validate();
286 if (!myStatus.isValid()) {
287 theStatus = PoolStatus.INVALID;
288 } else {
289 /* Check for preExistence of name */
290 String myName = myPlayer.getName();
291 PoolStatus myExisting = myNameMap.get(myName);
292 myNameMap.put(myName, myExisting == null
293 ? PoolStatus.VALID
294 : PoolStatus.DUPLICATE);
295
296 /* Check for preExistence of id */
297 Integer myId = myPlayer.getId();
298 myExisting = myIdMap.get(myId);
299 myIdMap.put(myId, myExisting == null
300 ? PoolStatus.VALID
301 : PoolStatus.DUPLICATE);
302 }
303 }
304
305 /* If we are valid */
306 if (theStatus.isValid()) {
307 /* Loop through the players */
308 myIterator = playerIterator();
309 while (myIterator.hasNext()) {
310 Player myPlayer = myIterator.next();
311
312 /* Ignore invalid players */
313 if (!myPlayer.getStatus().isValid()) {
314 continue;
315 }
316
317 /* If the name is duplicate */
318 String myName = myPlayer.getName();
319 PoolStatus myStatus = myNameMap.get(myName);
320 if (!myStatus.isValid()) {
321 /* Set as duplicate */
322 theStatus = PoolStatus.DUPLICATE;
323 myPlayer.setStatus(theStatus);
324 }
325
326 /* If the id is duplicate */
327 Integer myId = myPlayer.getId();
328 myStatus = myIdMap.get(myId);
329 if (!myStatus.isValid()) {
330 /* Set as duplicate */
331 theStatus = PoolStatus.DUPLICATE;
332 myPlayer.setStatus(theStatus);
333 }
334 }
335 }
336
337 /* return the status */
338 return theStatus;
339 }
340 }