From 3201c4c86428a2ae0b55374932b828b4039cdd9d Mon Sep 17 00:00:00 2001
From: FrederickPi1969 <pixinyudeyouxiang@gmail.com>
Date: Thu, 4 Feb 2021 21:50:01 -0600
Subject: [PATCH] mend

Gurantee performance of card validation & updation (test done)
---
 .../sp21-cs242-assignment1/CardManager.class  | Bin 3530 -> 3548 bytes
 .../sp21-cs242-assignment1/Game.class         | Bin 2670 -> 2869 bytes
 .../RuleControllerTest.class                  | Bin 9858 -> 10399 bytes
 src/Test/RuleControllerTest.java              |  52 ++++++++++++++++--
 src/UNO/CardManager.java                      |  11 ++--
 src/UNO/Game.java                             |   2 +-
 6 files changed, 54 insertions(+), 11 deletions(-)

diff --git a/out/production/sp21-cs242-assignment1/CardManager.class b/out/production/sp21-cs242-assignment1/CardManager.class
index bc11383ba8d1990ad64464166c8f003d107eeb1e..3b553b8e9cce60d30360c982042f9805d8b9eeae 100644
GIT binary patch
delta 277
zcmX|*xk>|36o$W>aSELUMM&Xgv=U;NB5sLGP&0)(h^Uo~lETyqHo*mh8;I@ge2OU~
z;4AnHK8l6^q_8;ach33GxBan2E0{1LK4U=Fb%Mkuw*E;nB<pS2q}Q%1?H<|>{Iqaa
zL1WM)((Ix(mIzrUrb(3+v#e2Los<ocO;y|E>~KVfb24tVwIZb&lRWZ(S1NMHy<(X?
zsb_R4=UKj@Smj0L@hV<+Mr?-uKkN$*1jnhwzbv>$xH>=W*&!ESTpH3s%;QEr9?9)8
d#U69)yZ7+gKi2yv&P2I6bq7(~oVm9s`vYOGDuVz3

delta 248
zcmca3eM)+RIX4%>F9ucy76t}}(8-S6vVy|WT3Z-ow=p=S*l7W&c;CsD+y=~g4BV5~
zaLd-~G1xHJGuSe?GT1Q$16fr-eI`Kt8Vqa<jSO`R%ph|Zsu^m4G>Fv%6k}u%1FCEW
zl1xBajG+aHnHgGv@*ok2Tsd5>94J>0l;dPz;`_rO&(0vgPzK~OF|+~k<NzLZRas`~
zZ4Ajf8S)qzbT$B`m>DX8Bp=vrX9htA7Y2C-*U58uidcOaco_U93-fw1hD?s-wPB2$
IJd4)}0DAi<RR910

diff --git a/out/production/sp21-cs242-assignment1/Game.class b/out/production/sp21-cs242-assignment1/Game.class
index cc388d7240516f9285c00e9039b390411bff60f3..d5c853fa460b7ce595a9af05c64a4e50bd7a828d 100644
GIT binary patch
delta 1669
zcmY*ZTXR!Y6#n)}n$w(aLP<+#38WVav?--1l}igqFI=K+sRg--*aJD%KuF3-LZK)T
z#rutNyn$EHnZ7wA*f2w9L}#3F#uuM__RS~9AK<9??Q=@2lgU2otiAU7zV)rO&mYy(
z5#y(S?tBZN3pXZ>q0u195t3MlN`a~-GncdMd@7sC^`&y=v9y&G5QlYy1!_*1XUz7r
znHg>Gz8|&2wzIZ@MeylZEKt#F+Q|VkV~$$%R>P-~*GSZ2>EuLH!!m);a3O8=W;1y^
zn@+2ss25ZxQICenyLIbUNHk$3xg@RQsid_tW#{rkY4e<AC;9~Z&54%%L99lzjuweH
zTAh$sFWQ_Q(OA)rbvho9co6HItms_z5VN?X3;9&Kz1z0UbN#7Y-av;3x=CU)I-Q?I
zQ}-5ufQMpGm~9eecv!$_PW10GPgz|p`<1&}qDN5+CT(+Em6}tj`XqK>r_-U;Z`mzS
zIS)8&W|G-c26n-xmPaM}F(9C4th4z<ChrxKP!jEt7;-Lak@6^pCH7*U^OaUx*Ma>K
z2XK&qxzvOu;A?J4D8&v-Jb@$5Z`#VhQHiH8;w<uYly~5m#Bn5@0bhMn7oL_FML<A~
zQM^4FYdBlTB*PFmY7p^+#7Sq;S6w_Mkx^mc!dTMGTZ80wUu^?pIIY8$$YGzr!ukI9
zra319k))MN*;aCH9QNkTd?BZ!K<Sh|L#EAfGLZN5J}Yq!6I6Q4^^;rwt>1myM94Al
zF5c7ezN+Q}XH(e^;;Qp^S-tqki3N^`Po49Dxc_s3m~$ZzbAAkji{&s>E{^e1oQGst
z&(hZL9RC%32R$4p_sQvVpX@cg7u>ia<AzjRWsMqr`U2c5!%D8t^Kb}${($lLZHTyk
z8v0EvxQ0m7e;vVSWzqN&6*E|L=r*eE#%EAXBQlL8G@~?^Pa_tOme6<;tHNtaSWABg
z{TrsS(YJM3^adJd&~<1TlW!ettJF)_9{&a#+e+v?a7hzW_kR7F*gjn3+KCX?C1kSz
zLDZm;x2dhjk~VP?wqiMlFUC?DI4O-Vv4UN1V&fWc2CMJ_kH&e_WRWl85>pOy_azpt
zac3Ma;}t%Y^{Ol4YqS@`e~;-k9pwVh|3bU?lW8?|Ej@K`u*gh4#)fCGi*+Ri;%iv$
zBhwgE#5I?A$c<RbVQc3HVx7yS-a9pi8=l2g?R*_?@T8{3aTaER(WHP*iW4j0v8$+w
z(;W1V6qQ^hJU&LmDJ=KA$yw*fe>UfJ47>f@K%kAN<GtUEEiNTBJ4$6w3MGIaT3s!P
zoSY+annaXfZOj~tmvE@a#?mH}J9rXM9VQ{=DZ%^>UHz>kSo2auI9Wh1rRZb#cAyzM
zu?D+c{D_x%7QdO1Z?aMR>f)_A{KBjd3STe#0;`vJ`1&0@<Dr+3BCoXbeXvSgbbble
z6;<oK+S>kK8(PWZ?YZ1NE<O+qmzR*e2HigezwZ_n%plL!p1Fnb`9cggILHfQKuJ{w
nO>XCh3GeVl!(~kJ8KQM%DGT@zSGZoo$8;LBKEY?Wj@o|#iM2PM

delta 1421
zcmY*ZTT>fl7=FHN$in91&=ffoN&<qyLQ1s=LTPQK7Gfzyv;}I5tRzy}kkA}TOIuU5
z9_kslI^%^m-f&%OmKm6FbjB<HfS3LP9lh<0#pm0N9nDU@@7?$KywCe4#kxOgjb9#a
z{Q%$~zFIdXBRZ-Cf+JQYe$q-=i;0YZN@x`*$1aHwcCY``-ujq8)l@#27)hscnRGI#
zoN7I%28l-Ou>&F;XqMQE7Q0)7gAugqXp?vx?e=MLKs;gJ5pBUvbm=f9y3u1hVo2<>
z{}K(AQ7_R`5>MlRUFT~*`iwweGHG2?W%@86QHEy)jLz8jsI{Cp*mXv!ha@{_5vYh~
ztW^a+Yaoh45{L1eeccx+92Ka!XkD>-^SPyD@068_r<V;Jfu@dQ5-;GmfSyWR&BanV
z0e@$#E2i2WlZZhIR4?Q+nM5k*A&DJREuWAW$4RoWn8?MlBgyo_rPZZuLO|>6I;-lR
zl9<Fx%$D7~wC3q!D)42AS8&>nY8`=Ti5bk=Gg@DH6t7C0!+HCz78&ltYZCJa2*?#S
ze=3!jO6ODY5Co<T;#!c1D{C;5PyK6D`ZpvN?LW2pu#P3Nq^Ov*GFe651&`XK#4=L%
z=lmx`)%ylMz#SbQDij~tn`J+XPwX3ki1^I@CU8!CVLu3%{=0&6{5#NMAJ;<#9fk_$
z#_T~Fl5kci`*4}xAm2d^SHQiwFYe7rQk!x8vh*XNlmpb2p@nCTZ@<IO2beQAAxwV}
zy19+Y*-cazQA4qoVqFo1db7zv({~7mIvhMnLzITzBKB*Cnw!2w+cx@Uo0+43B3h$6
z7&O1f{-}fD>DxZBvGdzKme7#r+0VrW>RGfB6=>j88WAS&b~K}ht2=-Qm!}nDXu||o
zcbf0#QRu)GhM5c-Lp4@$mFWf<bd5dvXqm$ruJcyX4VRyrly||mLpM!Fxe&ku=JTna
zN2&Q4Cei2?+Qt#K^ZZG(hh2^oF{<$TT)b7TM<L1??_<7R7e~YkdsH)2s#(q{y@>)t
zeOPpvRvfR<o7FKyQtBPN_%#|#ilhE{#gc=G6;|B9UQZb>DgSG{S75luU&tL-KMM_z
zw?RI`E+n-QEK!1_n)kyOZX^)yYpLJM%%RANDj=qVDbCXavV}8%8Y}@Rjf1m4qHnz0
z!JJD4xv(ErG<B#U)Ok5dl{&dhw>S>L=Pj?2eb}h$Qi=5~SYBEOud`mloTbt~&n?^7
z`L(nY_Dv(art*3nME~Cb|E9|E_M;Be{M0A7jSHOE#rwFV(g=4{s!fm>4e#*w;Wpmo
XT}A0VT0VBqPw~0yBd`t|U!w6J?y&g2

diff --git a/out/test/sp21-cs242-assignment1/RuleControllerTest.class b/out/test/sp21-cs242-assignment1/RuleControllerTest.class
index d81b897b07ecfc6a709c8c887add8725d235eada..9999d71a7bba788c9c2c9c63cffae4034f977b94 100644
GIT binary patch
literal 10399
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
LC(MqCwiNt7k@l<9

literal 9858
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

diff --git a/src/Test/RuleControllerTest.java b/src/Test/RuleControllerTest.java
index be37cfc..ddae6d4 100644
--- a/src/Test/RuleControllerTest.java
+++ b/src/Test/RuleControllerTest.java
@@ -8,7 +8,12 @@ import java.util.ArrayList;
 import java.util.Random;
 
 
-// Test for judging whether a play is legal
+/**
+ * A comprehensive test for RuleController class, Including
+ * 1. validating each card in given contexts (including behavior of wildDraw4)
+ * 2. updating the gameState (matchable color, number, symbol) when player plays a specific card
+ * 3. Initialization of initial game state
+ */
 
 class RuleControllerTest {
     private static CardParser parser = new CardParser();
@@ -256,28 +261,34 @@ class RuleControllerTest {
         ArrayList<Integer> groundTruth = groundTruthGenerator(ruler, player,
                 ruler.getMatchableColor(), ruler.getMatchableNumber(), ruler.getMatchableSymbol());
 
-        ruler.isValidPlay(player, 25, true); // check behavior of red 0
+        // current player plays red 0
+        ruler.isValidPlay(player, 25, true);
         assert(checkStateUpdatedCorrectly(ruler, "red", "none", "0", 0));
 
+        // current player plays red skip card
         setCurrentState(ruler, "red", "none", "8", 0);
-        ruler.isValidPlay(player, 20,true); // red skip card
+        ruler.isValidPlay(player, 20,true);
         assert(checkStateUpdatedCorrectly(ruler, "red", "skip", "none", 3));
 
+        // current player plays red reverse card
         setCurrentState(ruler, "red", "none", "8", 0);
-        ruler.isValidPlay(player, 22,true); // red reverse card
+        ruler.isValidPlay(player, 22,true);
         assert(checkStateUpdatedCorrectly(ruler, "red", "reverse", "none", 0));
         assert(!ruler.getIsClockwise());
 
+        // current player plays red draw 2
         ruler.changeGameOrder();
         setCurrentState(ruler, "red", "none", "8", 0);
-        ruler.isValidPlay(player, 24,true); // red draw2 card
+        ruler.isValidPlay(player, 24,true);
         assert(checkStateUpdatedCorrectly(ruler, "red", "draw2", "none", 1));
         assert(ruler.getPenaltyDraw() == 2); // next player should draw 2
 
+        // current player plays blue 8
         setCurrentState(ruler, "red", "none", "8", 0);
-        ruler.isValidPlay(player, 58, true); // blue 8
+        ruler.isValidPlay(player, 58, true);
         assert(checkStateUpdatedCorrectly(ruler, "blue", "none", "8", 0));
 
+        // current player plays wild card
         setCurrentState(ruler, "red", "none", "8", 0);
         ruler.isValidPlay(player, 102, true); // wild card, color should be NA, a special state
         assert(checkStateUpdatedCorrectly(ruler, "NA", "none", "none", 0));
@@ -319,8 +330,37 @@ class RuleControllerTest {
     }
 
 
+    /**
+     *  12. Test initialization of beginning game state is done properly
+     *  As this is a random process, it should be repeated many times using for loop
+     */
+    @Test
+    void testInitialization() {
+        ArrayList<String> colors = new ArrayList<>();
+        colors.add("red");
+        colors.add("green");
+        colors.add("blue");
+        colors.add("yellow");
+
+        ArrayList<String> numbers = new ArrayList<>();
+        for(int i = 0; i <= 9; i++) {
+            numbers.add((Integer.toString(i)));
+        }
+
+        for (int i = 0; i < 500; i++) {
+            RuleController ruler = new RuleController();
+            assert(colors.contains(ruler.getMatchableColor()));
+            assert(numbers.contains(ruler.getMatchableNumber()));
+            assert(ruler.getMatchableSymbol().equals("none"));
+        }
+
+    }
+
+
+
 
     /**
+     *  helper function:
      *  extract all the cards that the ruler think as legal
      */
     private ArrayList<Integer> getAllLegalCardsByRuler(RuleController ruler, Player player) {
diff --git a/src/UNO/CardManager.java b/src/UNO/CardManager.java
index 4dcf7bf..949e588 100644
--- a/src/UNO/CardManager.java
+++ b/src/UNO/CardManager.java
@@ -51,21 +51,24 @@ public class CardManager {
             return null;
         }
 
-        ArrayList<Integer> cardsDrawnFromDiscard = new ArrayList<Integer>();
+        ArrayList<Integer> cardsDrawnFromDiscard = new ArrayList<>();
         if (numCardLeft() < numToDraw) {
             int numToDrawFromDiscard = numToDraw - cardPile.size();
+            numToDraw -= numToDrawFromDiscard;
             cardsDrawnFromDiscard = drawCardsfromDiscardPile(numToDrawFromDiscard);
+            if (numToDraw == 0) return cardsDrawnFromDiscard; // we don't need to check cardPile anymore
         }
 
-        ArrayList<Integer> drawnCards = new ArrayList<Integer>(cardPile.subList(0, numToDraw));
+
+        ArrayList<Integer> drawnCards = new ArrayList<>(cardPile.subList(0, numToDraw));
         drawnCards.addAll(cardsDrawnFromDiscard);
         cardPile.subList(0, numToDraw).clear(); // erase the drawn cards
         return drawnCards;
     }
 
     private ArrayList<Integer> drawCardsfromDiscardPile(int numToDraw) {
-        ArrayList<Integer> drawnCards = new ArrayList<Integer>(discardPile.subList(0, numToDraw));
-        cardPile.subList(0, numToDraw).clear(); // erase the drawn cards
+        ArrayList<Integer> drawnCards = new ArrayList<>(discardPile.subList(0, numToDraw));
+        discardPile.subList(0, numToDraw).clear(); // erase the drawn cards
         return drawnCards;
 
     }
diff --git a/src/UNO/Game.java b/src/UNO/Game.java
index 9009612..7d5ec00 100644
--- a/src/UNO/Game.java
+++ b/src/UNO/Game.java
@@ -21,6 +21,7 @@ public class Game {
      * @param playerNum
      */
     public Game(int playerNum) {
+        assert(playerNum >= 1 && playerNum <= 10); // UNO is intended for 1-10 players
         gameCardManager = new CardManager();
         ruler = new RuleController();
         decideFirstPlayerID(playerNum);
@@ -46,7 +47,6 @@ public class Game {
         currentPlayerID = rand.nextInt(playerNum);
     }
 
-
     /**
      * find the next player in the sequence, regardless whether he or not should be skipped
      */
-- 
GitLab