OSDN Git Service

Initial commit.
[gamerandomizer/gamerandomizer.git] / GameRandomizer / src / jp / sourceforge / gamerandomizerlib / Game.java
1 //
2 // Copyright (c) 2013  Motoyuki Kasahara
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 //
17 package jp.sourceforge.gamerandomizerlib;
18
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.ListIterator;
22
23 /**
24  * <p>
25  * Represents a deck building game (e.g. "Dominion").
26  * </p>
27  *
28  * <p>
29  * Its object manages basic information about a game, expansions and cards.
30  * Basic information of a game is set at construction of an object and it
31  * cannot be changed.  Currently, basic information that an object hanles is
32  * ID, a title, the number of cards to be selected at playing the game.
33  * On the contrary, expansions and cards can be added and modified
34  * successively.
35  * </p>
36  * 
37  * @author   Motoyuki Kasahara
38  * @version  1.0
39  */
40 public class Game implements Comparable<Game> {
41         private String id;
42         private String title;
43         private int selectionSize;
44
45         private List<Expansion> expansions;
46         private List<Card> cards;
47
48         // cards also registered in 'cards', but its expansion is different.
49         private List<Card> duplicateCards;
50
51         /**
52          * Constructs an object.
53          *
54          * The created object has the specified ID, title and number of
55          * cards used at playing the game.
56          *
57          * @param  idArg              ID
58          * @param  titleArg           game title
59          * @param  selectionSizeArg   the number of selections
60          */
61         public Game(String idArg, String titleArg, int selectionSizeArg) {
62                 assert idArg != null;
63                 assert titleArg != null;
64                 assert selectionSizeArg > 0;
65
66                 id            = idArg;
67                 title         = titleArg;
68                 selectionSize = selectionSizeArg;
69
70                 expansions     = new LinkedList<Expansion>();
71                 cards          = new LinkedList<Card>();
72                 duplicateCards = new LinkedList<Card>();
73         }
74
75         /**
76          * Constructs a copy of the specified object.
77          *
78          * @param  game  the source object
79          */
80         public Game(Game game) {
81                 assert game != null;
82
83                 id            = game.id;
84                 title         = game.title;
85                 selectionSize = game.selectionSize;
86
87                 expansions     = new LinkedList<Expansion>(game.expansions);
88                 cards          = new LinkedList<Card>(game.cards);
89                 duplicateCards = new LinkedList<Card>(game.duplicateCards);
90         }
91
92         /**
93          * Returns ID of this game.
94          *
95          * @return  ID
96          */
97         public String getId() {
98                 return id;
99         }
100
101         /**
102          * Returns a title of this game.
103          *
104          * @return  a title
105          */
106         public String getTitle() {
107                 return title;
108         }
109
110         /**
111          * Returns the number of selections.
112          *
113          * The term "the number of selections" means that the number of
114          * kinds of cards used at playing the game.
115          *
116          * @return  the number of selections
117          */
118         public int getSelectionSize() {
119                 return selectionSize;
120         }
121
122         /**
123          * Removes all expansions and cards registered in this object.
124          */
125         public synchronized void clear() {
126                 expansions.clear();
127                 cards.clear();
128                 duplicateCards.clear();
129         }
130
131         /**
132          * Returns the number of expansions registered in this object.
133          *
134          * @return  the number of expansions
135          */
136         public int getExpansionsSize() {
137                 return expansions.size();
138         }
139
140         /**
141          * Returns a registered expansion at the specified position.
142          *
143          * @param  index  position of the expansion
144          * @return  an expansion
145          */
146         public Expansion getExpansion(int index) {
147                 return expansions.get(index);
148         }
149
150         /**
151          * Returns a registered expansion with the specified ID.
152          *
153          * If no card matches, it returns null.
154          *
155          * @param   id  ID of the expansion
156          * @return  the found expansion, or null
157          */
158         public Expansion getExpansion(String id) {
159                 assert id != null;
160
161                 ListIterator<Expansion> it = expansions.listIterator();
162                 while (it.hasNext()) {
163                         Expansion x = it.next();
164                         if (x.getId().equals(id))
165                                 return x;
166                 }
167                 return null;
168         }
169
170         /**
171          * Returns a registered expansion, equal to the specified one.
172          *
173          * If no expansion matches, it returns null.
174          *
175          * @param   expansionArg  an expansion to be searched
176          * @return  the found expansion, or null
177          */
178         public Expansion getExpansion(Expansion expansionArg) {
179                 assert expansionArg != null;
180
181                 ListIterator<Expansion> it = expansions.listIterator();
182                 while (it.hasNext()) {
183                         Expansion x = it.next();
184                         if (x.equals(expansionArg))
185                                 return x;
186                 }
187                 return null;
188         }
189
190         /**
191          * Returns all registered expansions as a list.
192          *
193          * The expansions are sorted by their preference values.
194          *
195          * @return  a list of expansions
196          */
197         public List<Expansion> getExpansions() {
198                 return new LinkedList<Expansion>(expansions);
199         }
200
201         /**
202          * Registers the specified expansion to this object.
203          *
204          * If the specified expansion has already been registered (i.e. they
205          * have the same ID), this method does nothing.
206          *
207          * @param  expansionArg  an expansion to be registered
208          * @return  true if the method registers the specified expansion
209          */
210         public synchronized boolean addExpansion(Expansion expansionArg) {
211                 assert expansionArg != null;
212
213                 if (getExpansion(expansionArg) != null)
214                         return false;
215                 ListIterator<Expansion> it = expansions.listIterator();
216                 while (it.hasNext()) {
217                         Expansion x = it.next();
218                         if (x.preference > expansionArg.preference) {
219                                 it.previous();
220                                 break;
221                         }
222                 }
223                 it.add(expansionArg);
224                 return true;
225         }
226
227         /**
228          * Registers all the specified expansions to this object.
229          *
230          * If the specified expansion has already been registered (i.e. they have
231          * the same ID), this method skips it.
232          *
233          * @param  expansionsArg  a list of expansions to be registered
234          * @return  true if the method registers at least one expansion
235          */
236         public synchronized boolean
237         addExpansions(List<Expansion> expansionsArg) {
238                 assert expansionsArg != null;
239
240                 boolean changed = false;
241                 ListIterator<Expansion> it = expansionsArg.listIterator();
242                 while (it.hasNext()) {
243                         if (addExpansion(it.next()))
244                                 changed = true;
245                 }
246                 return changed;
247         }
248
249         /**
250          * Removes the specified exansion from this object.
251          *
252          * If the specified expansion is registered (i.e. they have the same ID)
253          * in this object, this method removes it.  Otherwise, this method does
254          * nothing.
255          *
256          * This method also removes all cards provided by the specified expansion.
257          * If a card is provided by both the specified expansion and another one,
258          * the card provided by another one is still remained in this object.
259          *
260          * @param  expansionArg  an expansion to be removed
261          * @return  true if this method removes the expansion
262          */
263         public synchronized boolean removeExpansion(Expansion expansionArg) {
264                 assert expansionArg != null;
265
266                 if (!expansions.remove(expansionArg))
267                         return false;
268
269                 ListIterator<Card> it = duplicateCards.listIterator();
270                 while (it.hasNext()) {
271                         Card c = it.next();
272                         if (!c.getExpansion().equals(expansionArg))
273                                 continue;
274                         it.remove();
275                 }
276
277                 List<Card> cl = new LinkedList<Card>();
278                 it = cards.listIterator();
279                 while (it.hasNext()) {
280                         Card c = it.next();
281                         if (!c.getExpansion().equals(expansionArg))
282                                 continue;
283                         it.remove();
284
285                         ListIterator<Card> it2 = duplicateCards.listIterator();
286                         while (it2.hasNext()) {
287                                 Card c2 = it2.next();
288                                 if (c2.equals(c)) {
289                                         it2.remove();
290                                         cl.add(c2);
291                                         break;
292                                 }
293                         }
294                 }
295                 cards.addAll(cl);
296
297                 return true;
298         }
299
300         /**
301          * Removes all the specified exansions from this object.
302          *
303          * If the specified expansion is registered (i.e. they have the same ID)
304          * in this object, this method removes it.  Otherwise, this method skips
305          * it.
306          *
307          * This method also removes all cards provided by the specified
308          * expansions.  If a card is provided by both the specified expansion and
309          * another one, the card provided by another one is still remained in
310          * this object.
311          *
312          * @param  expansionsArg  a list of expansions to be removed
313          * @return  true if this method removes at least one expansion
314          */
315         public synchronized boolean
316         removeExpansions(List<Expansion> expansionsArg) {
317                 assert expansionsArg != null;
318
319                 boolean changed = false;
320                 ListIterator<Expansion> it = expansionsArg.listIterator();
321                 while (it.hasNext()) {
322                         if (removeExpansion(it.next()))
323                                 changed = true;
324                 }
325                 return changed;
326         }
327
328         /**
329          * Removes all exansions not specififed by the argument.
330          *
331          * If the specified expansion is registered (i.e. they have the same ID)
332          * in this object, this method remains it.  This method removes all
333          * unspecified expansions from this object.
334          *
335          * This method also removes all cards provided by unspecified expansions.
336          * If a card is provided by both unspecified and the specified expansions,
337          * the card provided by the specified one is still remained in this
338          * object.
339          *
340          * @param  expansionsArg  a list of expansions
341          * @return  true if this method removes at least one expansion
342          */
343         public synchronized boolean
344         removeOtherExpansions(List<Expansion> expansionsArg) {
345                 assert expansionsArg != null;
346
347                 List<Expansion> xl = new LinkedList<Expansion>();
348                 ListIterator<Expansion> it = expansions.listIterator();
349                 while (it.hasNext()) {
350                         Expansion x = it.next();
351                         if (expansionsArg.indexOf(x) < 0)
352                                 xl.add(x);
353                 }
354                 return removeExpansions(xl);
355         }
356
357         /**
358          * Returns the number of registered cards.
359          *
360          * @return  the number of cards
361          */
362         public int getCardsSize() {
363                 return cards.size();
364         }
365
366         /**
367          * Returns the number of registered cards of the specified expansion.
368          *
369          * @return  the number of cards
370          */
371         public int getCardsSize(Expansion expansionArg) {
372                 int size = 0;
373
374                 if (!expansions.contains(expansionArg))
375                         return 0;
376
377                 ListIterator<Card> it = cards.listIterator();
378                 while (it.hasNext()) {
379                         if (it.next().getExpansion().equals(expansionArg))
380                                 size++;
381                 }
382
383                 it = duplicateCards.listIterator();
384                 while (it.hasNext()) {
385                         if (it.next().getExpansion().equals(expansionArg))
386                                 size++;
387                 }
388                 
389                 return size;
390         }
391
392         /**
393          * Returns a registered card at the specified position.
394          *
395          * @param  index  position of the card
396          * @return  a card
397          */
398         public Card getCard(int index) {
399                 return cards.get(index);
400         }
401
402         /**
403          * Returns a registered card with the specified ID.
404          *
405          * If no card matches, it returns null.
406          *
407          * @param   id  ID of the card
408          * @return  the found card, or null
409          */
410         public Card getCard(String id) {
411                 assert id != null;
412
413                 ListIterator<Card> it = cards.listIterator();
414                 while (it.hasNext()) {
415                         Card c = it.next();
416                         if (c.getId().equals(id))
417                                 return c;
418                 }
419                 return null;
420         }
421
422         /**
423          * Returns a registered card, equal to the specified one.
424          *
425          * If no card matches, it returns null.
426          *
427          * @param   cardArg  a card to be searched
428          * @return  the found card, or null
429          */
430         public Card getCard(Card cardArg) {
431                 assert cardArg != null;
432
433                 ListIterator<Card> it = cards.listIterator();
434                 while (it.hasNext()) {
435                         Card c = it.next();
436                         if (c.equals(cardArg))
437                                 return c;
438                 }
439                 return null;
440         }
441
442         /**
443          * Returns all cards registered in this object as a list.
444          *
445          * @return  a list of cards
446          */
447         public List<Card> getCards() {
448                 return new LinkedList<Card>(cards);
449         }
450
451         /**
452          * Returns all cards provided by the specified expansion.
453          * 
454          * This method searches registered cards and returns all cards provided
455          * by the specified expansion as a list form.
456          *
457          * It returns null if the specified expansion is not registered in this
458          * object.  It returns an empty list if the specified expansion is
459          * registered but no card of the expansion is registered.
460          *
461          * @param  expansionArg  an expansion
462          * @return  a list of cards, or null
463          */
464         public List<Card> getCards(Expansion expansionArg) {
465                 assert expansionArg != null;
466
467                 if (!expansions.contains(expansionArg))
468                         return null;
469
470                 List<Card> cl = new LinkedList<Card>();
471                 ListIterator<Card> it = cards.listIterator();
472                 while (it.hasNext()) {
473                         Card c = it.next();
474                         if (c.getExpansion().equals(expansionArg))
475                                 cl.add(c);
476                 }
477
478                 it = duplicateCards.listIterator();
479                 while (it.hasNext()) {
480                         Card c = it.next();
481                         if (c.getExpansion().equals(expansionArg))
482                                 cl.add(c);
483                 }
484                 
485                 return cl;
486         }
487
488         /**
489          * Registers the specified card to this object.
490          *
491          * If the expansion of the card is not registered, this method also
492          * registers the expansion.
493          *
494          * If the specified card has already been registered (i.e. they have
495          * the same ID), this method doesn't register it again.  However, if it
496          * is provided by a different expansion, this method memories the
497          * specified card as "a duplicate card".  When an expansion of a
498          * registered card is removed, also the card is removed but corresponding
499          * duplicate cards, if exists, are still remained and one of them is
500          * registered instead.
501          *
502          * @param  cardArg  a card to be registered
503          * @return  true if this method registers a card or memories it as a
504          *          duplicate card.
505          */
506         public synchronized boolean addCard(Card cardArg) {
507                 assert cardArg != null;
508
509                 Expansion x = cardArg.getExpansion();
510
511                 Card c = getCard(cardArg);
512                 if (c == null) {
513                         addExpansion(x);
514                         cards.add(cardArg);
515                         return true;
516                 } else if (!c.getExpansion().equals(x)) {
517                         boolean found = false;
518                         ListIterator<Card> it = duplicateCards.listIterator();
519                         while (it.hasNext()) {
520                                 c = it.next();
521                                 if (c.equals(cardArg) && c.getExpansion().equals(x)) {
522                                         found = true;
523                                         break;
524                                 }
525                         }
526                         if (!found)
527                                 duplicateCards.add(cardArg);
528                         return found;
529                 } else {
530                         return false;
531                 }
532         }
533
534         /**
535          * Registers all the specified cards to this object.
536          *
537          * If the expansion of the card is not registered, this method also
538          * registers the expansion.
539          *
540          * If the specified card has already been registered (i.e. they have
541          * the same ID), this method doesn't register it again.  However, if it
542          * is provided by a different expansion, this method memories the
543          * specified card as "a duplicate card".  When an expansion of a
544          * registered card is removed, also the card is removed but corresponding
545          * duplicate cards, if exists, are still remained and one of them is
546          * registered instead.
547          *
548          * @param  cardsArg  cards to be registered
549          * @return  true if this method registers at least one card or
550          *          memories at least one card as a duplicate card.
551          */
552         public synchronized boolean addCards(List<Card> cardsArg) {
553                 assert cardsArg != null;
554
555                 boolean changed = false;
556                 ListIterator<Card> it = cardsArg.listIterator();
557                 while (it.hasNext()) {
558                         if (addCard(it.next()))
559                                 changed = true;
560                 }
561                 return changed;
562         }
563
564         /**
565          * Removes the specified card from this object.
566          *
567          * If the specified card is registered (i.e. they have the same ID) in
568          * this object, this method removes the card.  Otherwise, this method
569          * does nothing.
570          *
571          * @param  cardArg  a card to be removed
572          * @return  true if this method removes a card
573          */
574         public synchronized boolean removeCard(Card cardArg) {
575                 assert cardArg != null;
576
577                 boolean changed = false;
578                 ListIterator<Card> it = cards.listIterator();
579                 while (it.hasNext()) {
580                         Card c = it.next();
581                         if (c.equals(cardArg)) {
582                                 it.remove();
583                                 changed = true;
584                                 break;
585                         }
586                 }
587
588                 it = duplicateCards.listIterator();
589                 while (it.hasNext()) {
590                         Card c = it.next();
591                         if (c.equals(cardArg)) {
592                                 it.remove();
593                                 changed = true;
594                         }
595                 }
596
597                 return changed;
598         }
599
600         /**
601          * Removes all the specified cards from this object.
602          *
603          * If the specified card is registered (i.e. they have the same ID) in
604          * this object, this method removes the card.  Otherwise, this method
605          * skips the card.
606          *
607          * @param  cardsArg  a list of cards to be removed
608          * @return  true if this method removes at least one card
609          */
610         public synchronized boolean removeCards(List<Card> cardsArg) {
611                 assert cardsArg != null;
612
613                 boolean changed = false;
614                 ListIterator<Card> it = cardsArg.listIterator();
615                 while (it.hasNext()) {
616                         if (removeCard(it.next()))
617                                 changed = true;
618                 }
619                 return changed;
620         }
621
622         /**
623          * Returns true if this object is equal the specified one.
624          *
625          * It returns true, if both objects have the same ID, 
626          *
627          * @param  o  an object to be compared
628          * @return  true if both objects have the same ID
629          */
630         public boolean equals(Object o) {
631                 if (o == this)
632                         return true;
633                 if (o == null || !(o instanceof Game))
634                         return false;
635                 Game x = (Game)o;
636                 return id.equals(x.id);
637         }
638
639         /**
640          * Returns a hash value of this object.
641          *
642          * @return  a hash value
643          */
644         @Override
645         public int hashCode() {
646                 if (id == null)
647                         return 0;
648                 else
649                         return id.hashCode();
650         }
651
652         /**
653          * Compares this object and the specified one.
654          * 
655          * It compares ID of both objects.  It returns an integer less than,
656          * equal to, or greater than zero if ID of this object is respectively
657          * less than, equal to, or greater than that of the specified object.
658          *
659          * @param  game  a game object to be compared
660          * @return  a negative integer, zero, or a positive integer according
661          *          with result of the comparison.
662          */
663         public int compareTo(Game game) {
664                 return id.compareTo(game.id);
665         }
666
667         /**
668          * Converts this object to a String.
669          *
670          * @return  a title of this object.
671          */
672         @Override
673         public String toString() {
674                 return title;
675         }
676 }