1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sourceforge.jhunters.pool.data;
18
19 import java.security.SecureRandom;
20 import java.time.DayOfWeek;
21 import java.time.LocalDate;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28
29 import javafx.beans.property.IntegerProperty;
30 import javafx.beans.property.SimpleIntegerProperty;
31 import javafx.collections.ObservableList;
32 import net.sourceforge.jhunters.pool.PoolStatus;
33
34
35
36
37 public class FixtureSet {
38
39
40
41 protected static final String OBJECT_NAME = DataResource.FIXTURESET_NAME.getValue();
42
43
44
45
46 private static final String FIELD_WEEKNO = DataResource.FIXTURESET_WEEKNO.getValue();
47
48
49
50
51 private final List<Fixture> theFixtures;
52
53
54
55
56 private final IntegerProperty theWeekNo;
57
58
59
60
61 private PoolStatus theStatus;
62
63
64
65
66 protected FixtureSet() {
67 theFixtures = new ArrayList<Fixture>();
68 theWeekNo = new SimpleIntegerProperty(this, FIELD_WEEKNO);
69 }
70
71
72
73
74
75
76 protected void setNamedProperty(final String pName,
77 final String pValue) {
78 if (pName.equals(FIELD_WEEKNO)) {
79 setWeekNo(DataParser.parseInteger(pValue));
80 }
81 }
82
83 @Override
84 public String toString() {
85
86 StringBuilder myBuilder = new StringBuilder();
87
88
89 Iterator<Fixture> myIterator = fixtureIterator();
90 while (myIterator.hasNext()) {
91 Fixture myFixture = myIterator.next();
92
93 myBuilder.append(myFixture.toString());
94 myBuilder.append('\n');
95 }
96 return myBuilder.toString();
97 }
98
99
100
101
102
103
104 protected void addFixture(final Player pHome,
105 final Player pAway) {
106
107 Fixture myFixture = new Fixture();
108 myFixture.setHomePlayer(pHome);
109 myFixture.setAwayPlayer(pAway);
110
111
112 addFixture(myFixture);
113 }
114
115
116
117
118
119 protected void addFixture(final Fixture pFixture) {
120 theFixtures.add(pFixture);
121 }
122
123
124
125
126
127 public IntegerProperty weekNoProperty() {
128 return theWeekNo;
129 }
130
131
132
133
134
135 public Integer getWeekNo() {
136 return theWeekNo.getValue();
137 }
138
139
140
141
142
143 public PoolStatus getStatus() {
144 return theStatus;
145 }
146
147
148
149
150
151 private void setWeekNo(final Integer pWeekNo) {
152 theWeekNo.setValue(pWeekNo);
153 }
154
155
156
157
158
159 public List<Fixture> getFixtures() {
160 return theFixtures;
161 }
162
163
164
165
166
167
168 protected void getFixtures(final ObservableList<Fixture> pList,
169 final LocalDate pNow) {
170
171 Iterator<Fixture> myIterator = fixtureIterator();
172 while (myIterator.hasNext()) {
173 Fixture myCurr = myIterator.next();
174
175
176 if (!myCurr.isBye()
177 && pNow.compareTo(myCurr.getDate()) >= 0) {
178 pList.add(myCurr);
179 }
180 }
181 }
182
183
184
185
186
187 public Iterator<Fixture> fixtureIterator() {
188 return theFixtures.iterator();
189 }
190
191
192
193
194
195 protected void setByePlayer(final Player pPlayer) {
196
197 Iterator<Fixture> myIterator = fixtureIterator();
198 while (myIterator.hasNext()) {
199 Fixture myCurr = myIterator.next();
200
201
202 if (myCurr.isBye()) {
203 myCurr.setByePlayer(pPlayer);
204 break;
205 }
206 }
207 }
208
209
210
211
212
213 protected void randomise(final SecureRandom pRandom) {
214 Collections.shuffle(theFixtures, pRandom);
215 }
216
217
218
219
220
221
222 protected void setDates(final Integer pWeekNo,
223 final LocalDate pDate) {
224
225 setWeekNo(pWeekNo);
226
227
228 LocalDate myDate = pDate.with(DayOfWeek.TUESDAY);
229 int mySplit = theFixtures.size() >> 1;
230
231
232 int i = 1;
233 Iterator<Fixture> myIterator = fixtureIterator();
234 while (myIterator.hasNext()) {
235 Fixture myCurr = myIterator.next();
236
237
238 myCurr.setDate(myDate);
239
240
241 if (i++ == mySplit) {
242
243 myDate = myDate.plusDays(1);
244 }
245 }
246 }
247
248 @Override
249 public boolean equals(final Object pThat) {
250
251 if (this == pThat) {
252 return true;
253 }
254 if (pThat == null) {
255 return false;
256 }
257
258
259 if (!(pThat instanceof FixtureSet)) {
260 return false;
261 }
262
263
264 FixtureSet myThat = (FixtureSet) pThat;
265
266
267 if (!DataSet.isEqual(getWeekNo(), myThat.getWeekNo())) {
268 return false;
269 }
270
271
272 return theFixtures.equals(myThat.getFixtures());
273 }
274
275 @Override
276 public int hashCode() {
277 return (theFixtures.hashCode() * DataSet.HASH_PRIME)
278 + theWeekNo.hashCode();
279 }
280
281
282
283
284
285
286 protected PoolStatus validate(final PlayerList pParticipants) {
287
288 Map<String, PoolStatus> myMap = new HashMap<String, PoolStatus>();
289 theStatus = PoolStatus.VALID;
290 int myByeCount = 0;
291
292
293 Iterator<Fixture> myIterator = fixtureIterator();
294 while (myIterator.hasNext()) {
295 Fixture myCurr = myIterator.next();
296
297
298 PoolStatus myStatus = myCurr.validate(pParticipants);
299 if (!myStatus.isValid()) {
300 theStatus = PoolStatus.INVALID;
301 } else {
302
303 Player myHome = myCurr.getHomePlayer();
304 Player myAway = myCurr.getAwayPlayer();
305
306
307 if (myHome != null) {
308 String myName = myHome.getName();
309 PoolStatus myExisting = myMap.get(myName);
310 myMap.put(myName, myExisting == null
311 ? PoolStatus.VALID
312 : PoolStatus.DUPLICATE);
313 }
314 if (myAway != null) {
315 String myName = myAway.getName();
316 PoolStatus myExisting = myMap.get(myName);
317 myMap.put(myName, myExisting == null
318 ? PoolStatus.VALID
319 : PoolStatus.DUPLICATE);
320 }
321
322
323 if (myCurr.isBye()) {
324 myByeCount++;
325 }
326 }
327 }
328
329
330 if (theStatus.isValid()) {
331
332 boolean badBye = myByeCount > 1;
333
334
335 myIterator = fixtureIterator();
336 while (myIterator.hasNext()) {
337 Fixture myCurr = myIterator.next();
338
339
340 if (!myCurr.getStatus().isValid()) {
341 continue;
342 }
343
344
345 Player myHome = myCurr.getHomePlayer();
346 Player myAway = myCurr.getAwayPlayer();
347
348
349 if (myHome != null) {
350 PoolStatus myStatus = myMap.get(myHome.getName());
351 if (!myStatus.isValid()) {
352
353 theStatus = PoolStatus.DUPLICATE;
354 myCurr.setStatus(theStatus);
355 }
356 } else if (badBye) {
357
358 theStatus = PoolStatus.DUPLICATE;
359 myCurr.setStatus(theStatus);
360 }
361
362
363 if (myAway != null) {
364 PoolStatus myStatus = myMap.get(myAway.getName());
365 if (!myStatus.isValid()) {
366
367 theStatus = PoolStatus.DUPLICATE;
368 myCurr.setStatus(theStatus);
369 }
370 } else if (badBye) {
371
372 theStatus = PoolStatus.DUPLICATE;
373 myCurr.setStatus(theStatus);
374 }
375 }
376 }
377
378
379 if (theStatus.isValid()) {
380
381 int myNumFixtures = 1 + ((pParticipants.size() - 1) / 2);
382 if (myNumFixtures != theFixtures.size()) {
383 theStatus = PoolStatus.INVALID;
384 }
385 }
386
387
388 return theStatus;
389 }
390 }