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.security.SecureRandom;
20 import java.time.LocalDate;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27
28 import net.sourceforge.jhunters.pool.PoolStatus;
29
30 /**
31 * Competition Fixture.
32 */
33 public class FixtureList {
34 /**
35 * FixtureList Name.
36 */
37 protected static final String OBJECT_NAME = DataResource.FIXTURELIST_NAME.getValue();
38
39 /**
40 * List of FixtureSets.
41 */
42 private final List<FixtureSet> theFixtures;
43
44 /**
45 * The status of the list.
46 */
47 private PoolStatus theStatus;
48
49 /**
50 * Constructor.
51 */
52 public FixtureList() {
53 theFixtures = new ArrayList<FixtureSet>();
54 }
55
56 /**
57 * Obtain the status.
58 * @return the status.
59 */
60 public PoolStatus getStatus() {
61 return theStatus;
62 }
63
64 /**
65 * Obtain the number of FixtureSets.
66 * @return the # fixture sets.
67 */
68 public Integer size() {
69 return theFixtures.size();
70 }
71
72 /**
73 * Obtain the numbered fixtureSet.
74 * @param pWeek the week #
75 * @return the fixture set.
76 */
77 public FixtureSet getFixtureSet(final Integer pWeek) {
78 return ((pWeek > 0) && (pWeek <= theFixtures.size()))
79 ? theFixtures.get(pWeek - 1)
80 : null;
81 }
82
83 /**
84 * Reset fixtures.
85 */
86 protected void reset() {
87 theFixtures.clear();
88 }
89
90 /**
91 * Add fixtureSet.
92 * @param pSet the fixture set.
93 */
94 protected void addFixtureSet(final FixtureSet pSet) {
95 /* Add to the fixture set list */
96 theFixtures.add(pSet);
97 }
98
99 /**
100 * Set fixtures.
101 * @param pSource the source fixtures.
102 */
103 protected void setFixtures(final Iterator<FixtureSet> pSource) {
104 /* Reset the fixtures */
105 reset();
106
107 /* Loop through the source list */
108 while (pSource.hasNext()) {
109 FixtureSet mySet = pSource.next();
110
111 /* Add the set */
112 theFixtures.add(mySet);
113 }
114 }
115
116 /**
117 * Obtain fixture list.
118 * @return the fixtures
119 */
120 private List<FixtureSet> getFixtures() {
121 return theFixtures;
122 }
123
124 /**
125 * Obtain fixtureIterator.
126 * @return the iterator
127 */
128 public Iterator<FixtureSet> fixtureIterator() {
129 return theFixtures.iterator();
130 }
131
132 /**
133 * Set Bye player.
134 * @param pPlayer the final player
135 */
136 protected void setByePlayer(final Player pPlayer) {
137 /* Loop through the fixtureSets */
138 Iterator<FixtureSet> myIterator = fixtureIterator();
139 while (myIterator.hasNext()) {
140 FixtureSet myCurr = myIterator.next();
141
142 /* Set the bye player */
143 myCurr.setByePlayer(pPlayer);
144 }
145 }
146
147 /**
148 * Randomise the fixtures.
149 * @param pRandom the random generator
150 */
151 protected void randomise(final SecureRandom pRandom) {
152 /* Randomise the fixture sets */
153 Collections.shuffle(theFixtures, pRandom);
154
155 /* Loop through the fixtureSets */
156 Iterator<FixtureSet> myIterator = fixtureIterator();
157 while (myIterator.hasNext()) {
158 FixtureSet myCurr = myIterator.next();
159
160 /* Randomise the fixtureSet */
161 myCurr.randomise(pRandom);
162 }
163 }
164
165 /**
166 * Set dates.
167 * @param pDate the base date.
168 */
169 protected void setDates(final LocalDate pDate) {
170 /* Loop through the fixtureSets */
171 int myWeekNo = 1;
172 LocalDate myDate = pDate;
173 Iterator<FixtureSet> myIterator = fixtureIterator();
174 while (myIterator.hasNext()) {
175 FixtureSet myCurr = myIterator.next();
176
177 /* Set the dates */
178 myCurr.setDates(myWeekNo, myDate);
179
180 /* Shift values */
181 myWeekNo++;
182 myDate = myDate.plusWeeks(1);
183 }
184 }
185
186 @Override
187 public boolean equals(final Object pThat) {
188 /* Handle trivial cases */
189 if (this == pThat) {
190 return true;
191 }
192 if (pThat == null) {
193 return false;
194 }
195
196 /* Handle wrong class */
197 if (!(pThat instanceof FixtureList)) {
198 return false;
199 }
200
201 /* Access as fixtureList */
202 FixtureList myThat = (FixtureList) pThat;
203
204 /* Test only on fixtures */
205 return theFixtures.equals(myThat.getFixtures());
206 }
207
208 @Override
209 public int hashCode() {
210 return theFixtures.hashCode();
211 }
212
213 /**
214 * validate the fixture list.
215 * @param pParticipants the participants
216 * @return the status
217 */
218 protected PoolStatus validate(final PlayerList pParticipants) {
219 /* Create the fixture map */
220 Map<String, List<String>> myMap = new HashMap<String, List<String>>();
221 theStatus = PoolStatus.VALID;
222
223 /* Loop through the fixture sets */
224 Iterator<FixtureSet> myIterator = fixtureIterator();
225 while (myIterator.hasNext()) {
226 FixtureSet myCurr = myIterator.next();
227
228 /* Validate the fixture */
229 PoolStatus myStatus = myCurr.validate(pParticipants);
230 if (!myStatus.isValid()) {
231 theStatus = PoolStatus.INVALID;
232 }
233
234 /* Loop through the fixtures */
235 Iterator<Fixture> myFixIterator = myCurr.fixtureIterator();
236 while (myFixIterator.hasNext()) {
237 Fixture myFixture = myFixIterator.next();
238
239 /* Ignore byes */
240 if (myFixture.isBye()) {
241 continue;
242 }
243
244 /* Access players */
245 Player myHome = myFixture.getHomePlayer();
246 Player myAway = myFixture.getAwayPlayer();
247
248 /* Register match-up */
249 registerMatch(myMap, myHome, myAway);
250 registerMatch(myMap, myAway, myHome);
251 }
252 }
253
254 /* If we are valid */
255 if (theStatus.isValid()) {
256 /* Determine the number of fixtures */
257 int myNumFixtures = pParticipants.size() - 1;
258
259 /* Loop through the fixture map */
260 Iterator<List<String>> myMapIterator = myMap.values().iterator();
261 while (myMapIterator.hasNext()) {
262 List<String> myList = myMapIterator.next();
263
264 /* Note If the list is the wrong size */
265 if (myList.size() != myNumFixtures) {
266 theStatus = PoolStatus.INVALID;
267 }
268 }
269 }
270
271 /* Return the status */
272 return theStatus;
273 }
274
275 /**
276 * register a match up.
277 * @param pMap the fixture map
278 * @param pFirst the first player
279 * @param pSecond the second player
280 */
281 protected void registerMatch(final Map<String, List<String>> pMap,
282 final Player pFirst,
283 final Player pSecond) {
284 /* Obtain the list */
285 String myFirst = pFirst.getName();
286 List<String> myList = pMap.get(myFirst);
287 if (myList == null) {
288 myList = new ArrayList<String>();
289 pMap.put(myFirst, myList);
290 }
291
292 /* Add second player if not already in list */
293 String mySecond = pSecond.getName();
294 if (!myList.contains(mySecond)) {
295 myList.add(mySecond);
296 }
297 }
298 }