Coverage Summary for Class: CharacterCardsPanel (it.polimi.ingsw.Client.GUI.Panels)
| Class | Class, % | Method, % | Branch, % | Line, % |
|---|---|---|---|---|
| CharacterCardsPanel | 0% (0/1) | 0% (0/5) | 0% (0/80) | 0% (0/228) |
1 package it.polimi.ingsw.Client.GUI.Panels; 2 3 import it.polimi.ingsw.Client.GUI.ActionType; 4 import it.polimi.ingsw.Client.GUI.Components.NoEntryTileComponent; 5 import it.polimi.ingsw.Client.GUI.Components.StudentButton; 6 import it.polimi.ingsw.Client.GUI.Listeners.CheckBoxListener; 7 import it.polimi.ingsw.Client.GUI.Listeners.GUISocketListener; 8 import it.polimi.ingsw.Controller.Actions.PlayCharacterCard; 9 import it.polimi.ingsw.Misc.OptionalValue; 10 import it.polimi.ingsw.Model.*; 11 import it.polimi.ingsw.Model.Enums.PawnColour; 12 import it.polimi.ingsw.Model.Enums.StateType; 13 import it.polimi.ingsw.Network.SocketWrapper; 14 import it.polimi.ingsw.Server.Messages.Events.Requests.PlayerActionRequest; 15 16 import javax.swing.*; 17 import java.awt.*; 18 import java.io.IOException; 19 import java.util.ArrayList; 20 import java.util.EnumMap; 21 import java.util.List; 22 import java.util.stream.Collectors; 23 24 import static it.polimi.ingsw.Client.GUI.IconLoader.*; 25 26 /** 27 * Class used to draw the 3 characterCards and their eventual contents; it also handles all 12 characterCards actions. 28 * This class will be initialized only in advanced Game 29 */ 30 public class CharacterCardsPanel extends JPanel { 31 public CharacterCardsPanel(Model model, SocketWrapper socketWrapper, GUISocketListener guiSocketListener) { 32 UIManager.put("ToolTip.font", new Font("Arial", Font.BOLD, 14)); 33 //List containing game's characterCards 34 ArrayList<CharacterCard> characterCards = new ArrayList<>(model.getCharacterCards()); 35 //Label that will contain all others components 36 JLabel pageBackground = new JLabel(sky); 37 pageBackground.setBounds(0, 0, 1080, 720); 38 this.add(pageBackground); 39 //list containing characterCards' buttons 40 ArrayList<JButton> characterCardsButton = new ArrayList<>(characterCards.size()); 41 //list containing coins' labels 42 ArrayList<JLabel> coinLabels = new ArrayList<>(characterCards.size()); 43 //list containing characterCardsStates' labels 44 ArrayList<JLabel> characterCardsStatelabes = new ArrayList<>(characterCards.size()); 45 //repeat for all 3 characterCards 46 for (int i = 0; i < characterCards.size(); i++) { 47 //add a new coin's label to coinLabels list and make it invisible 48 coinLabels.add(new JLabel(coin)); 49 coinLabels.get(i).setVisible(false); 50 //add a new characterCardState's label to characterCardsStatelabes list and make it invisible 51 characterCardsStatelabes.add(new JLabel()); 52 characterCardsStatelabes.get(i).setVisible(false); 53 JButton button; 54 //create a new characterCard's button with the proper image 55 switch (characterCards.get(i)) { 56 case Card01 ignored -> { 57 button = new JButton(card01); 58 characterCardsButton.add(button); 59 } 60 case Card02 ignored -> { 61 button = new JButton(card02); 62 characterCardsButton.add(button); 63 } 64 case Card03 ignored -> { 65 button = new JButton(card03); 66 characterCardsButton.add(button); 67 } 68 case Card04 ignored -> { 69 button = new JButton(card04); 70 characterCardsButton.add(button); 71 } 72 case Card05 ignored -> { 73 button = new JButton(card05); 74 characterCardsButton.add(button); 75 } 76 case Card06 ignored -> { 77 button = new JButton(card06); 78 characterCardsButton.add(button); 79 } 80 case Card07 ignored -> { 81 button = new JButton(card07); 82 characterCardsButton.add(button); 83 } 84 case Card08 ignored -> { 85 button = new JButton(card08); 86 characterCardsButton.add(button); 87 } 88 case Card09 ignored -> { 89 button = new JButton(card09); 90 characterCardsButton.add(button); 91 } 92 case Card10 ignored -> { 93 button = new JButton(card10); 94 characterCardsButton.add(button); 95 } 96 case Card11 ignored -> { 97 button = new JButton(card11); 98 characterCardsButton.add(button); 99 } 100 case Card12 ignored -> { 101 button = new JButton(card12); 102 characterCardsButton.add(button); 103 } 104 default -> button = new JButton(); 105 } 106 //add characterCard's info with ToolTipManager CLASS 107 button.setToolTipText(printCharacterCardInfo(characterCards.get(i))); 108 ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE); 109 int finalI = i; 110 //add on-click actionListener to characterCard's button 111 button.addActionListener(e -> { 112 // skip execution of the action if a previous action still hasn't been processed by the server 113 if (guiSocketListener.awaitingPlayerActionFeedback()) { 114 JOptionPane.showMessageDialog(null, "Please wait for the server to process your previous" + 115 "request before making a new one"); 116 return; 117 } 118 PlayCharacterCard playCharacterCard = null; 119 PlayerActionRequest playerActionRequest = null; 120 //get JTabbedPane (necessary to switch to another JPanel) 121 Container parent = this.getParent(); 122 while (!(parent instanceof GameInProgressPanel gameInProgressPanel)) { 123 parent = parent.getParent(); 124 } 125 switch (characterCards.get(finalI)) { 126 case Card01 card01 -> { 127 PawnColour toMove; 128 //list containing CharacterCard's pawns 129 PawnColour[] options = card01.getState().toArray(new PawnColour[0]); 130 //create and show JOptionPane 131 int option = JOptionPane.showOptionDialog(null, "Select pawnColour to move to an island", "Select PawnColour", 132 JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, 133 null, options, options[0]); 134 //get pawn to move 135 toMove = PawnColour.getPawnColourFromText(options[option].toString()); 136 //switch to first JTabbedPane's tab 137 gameInProgressPanel.setSelectedIndex(0); 138 IslandFieldPanel islandFieldPanel = (IslandFieldPanel) gameInProgressPanel.getSelectedComponent(); 139 JOptionPane.showMessageDialog(null, "click on the island on which you want to move the pawn"); 140 //set IslandFieldPanel to play this characterCard 141 islandFieldPanel.setCharacterCardAction(ActionType.CHARACTERCARD, OptionalValue.of(finalI), OptionalValue.of(toMove)); 142 return; 143 } 144 case Card02 ignored2 -> { 145 //create playCharacterCard and its playerActionReqeust 146 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 147 finalI, OptionalValue.empty(), OptionalValue.empty(), OptionalValue.empty()); 148 playerActionRequest = new PlayerActionRequest(playCharacterCard); 149 } 150 case Card03 ignored3 -> { 151 //switch to first JTabbedPane's pane 152 gameInProgressPanel.setSelectedIndex(0); 153 IslandFieldPanel islandFieldPanel = (IslandFieldPanel) gameInProgressPanel.getSelectedComponent(); 154 JOptionPane.showMessageDialog(null, "click on the island on which you want to calculate the influence"); 155 //set IslandFieldPanel to play this characterCard 156 islandFieldPanel.setCharacterCardAction(ActionType.CHARACTERCARD, OptionalValue.of(finalI), OptionalValue.empty()); 157 return; 158 } 159 case Card04 ignored -> { 160 //create playCharacterCard and its playerActionReqeust 161 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 162 finalI, OptionalValue.empty(), OptionalValue.empty(), OptionalValue.empty()); 163 playerActionRequest = new PlayerActionRequest(playCharacterCard); 164 } 165 case Card05 ignored5 -> { 166 //switch to first JTabbedPane's pane 167 gameInProgressPanel.setSelectedIndex(0); 168 IslandFieldPanel islandFieldPanel = (IslandFieldPanel) gameInProgressPanel.getSelectedComponent(); 169 JOptionPane.showMessageDialog(null, "click on the island on which you want to move NoEntry tile"); 170 //set IslandFieldPanel to play this characterCard 171 islandFieldPanel.setCharacterCardAction(ActionType.CHARACTERCARD, OptionalValue.of(finalI), OptionalValue.empty()); 172 return; 173 } 174 case Card06 ignored6 -> { 175 //create playCharacterCard and its playerActionRequest 176 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 177 finalI, OptionalValue.empty(), OptionalValue.empty(), OptionalValue.empty()); 178 playerActionRequest = new PlayerActionRequest(playCharacterCard); 179 180 } 181 case Card07 card07 -> { 182 //create list of PawnColour from characterCard's state 183 ArrayList<PawnColour> pawnsFromCard = card07.getState().stream().map(o -> (PawnColour) o).collect(Collectors.toCollection(ArrayList::new)); 184 //create array of JCheckBox having the same size as the previous list 185 JCheckBox[] checkBoxes = new JCheckBox[pawnsFromCard.size()]; 186 //create a new CheckBoxListener 187 CheckBoxListener checkBoxListener = new CheckBoxListener(3, checkBoxes); 188 //panel used for showing components inside JOptionPane 189 JPanel optionPanel = new JPanel(); 190 for (int j = 0; j < pawnsFromCard.size(); j++) { 191 //create a new JCheckBox and add it to checkBoxes array 192 checkBoxes[j] = new JCheckBox(pawnsFromCard.get(j).toString()); 193 //add checkBoxListener to checkBox 194 checkBoxes[j].addItemListener(checkBoxListener); 195 //add checkBox to optionPanel 196 optionPanel.add(checkBoxes[j]); 197 } 198 //create and show JOptionPane 199 int result = JOptionPane.showConfirmDialog(this, optionPanel, 200 "Select pawns ", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 201 if (result == -1 || result == 2) return; 202 //clear and reuse pawnsFromCard 203 pawnsFromCard.clear(); 204 for (JCheckBox checkBox : checkBoxes) { 205 if (checkBox.isSelected()) { 206 //add a PawnColour of that colour only if the corresponding checkBox has been selected 207 pawnsFromCard.add(PawnColour.getPawnColourFromText(checkBox.getText())); 208 } 209 } 210 for (int h = 0; h < gameInProgressPanel.getTabCount(); h++) { 211 Component component = gameInProgressPanel.getComponentAt(h); 212 //search for CurrentPlayer's PlayerBoardPanel 213 if ((component instanceof PlayerBoardPanel playerBoardPanel) && playerBoardPanel.getPlayerBoardNickname().equals(model.getMutableTurnOrder().getMutableCurrentPlayer().getNickname())) { 214 //switch to that Panel 215 gameInProgressPanel.setSelectedIndex(h); 216 //delegate the remaining part of execution to PlayerBoardPanel 217 playerBoardPanel.PlayCharacterCardEffect(7, finalI, OptionalValue.of(pawnsFromCard)); 218 } 219 } 220 return; 221 } 222 case Card08 ignored8 -> { 223 //create playCharacterCard and its playerActionRequest 224 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 225 finalI, OptionalValue.empty(), OptionalValue.empty(), OptionalValue.empty()); 226 playerActionRequest = new PlayerActionRequest(playCharacterCard); 227 } 228 case Card09 ignored9 -> { 229 PawnColour toExclude; 230 //Array of strings containing all PawnColours 231 String[] options = new String[]{"RED", "PINK", "GREEN", "YELLOW", "BLUE"}; 232 //create and show JOptionPane 233 int option = JOptionPane.showOptionDialog(null, "Select pawnColour to make it irrelevant", "Select PawnColour", 234 JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, 235 null, options, options[0]); 236 //get selected pawn to exclude 237 toExclude = PawnColour.getPawnColourFromText(options[option]); 238 //create playCharacterCard action and its playerActionRequest 239 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 240 finalI, OptionalValue.empty(), OptionalValue.of(toExclude), OptionalValue.empty()); 241 playerActionRequest = new PlayerActionRequest(playCharacterCard); 242 } 243 case Card10 ignored10 -> { 244 for (int h = 0; h < gameInProgressPanel.getTabCount(); h++) { 245 Component component = gameInProgressPanel.getComponentAt(h); 246 //search for CurrentPlayer's PlayerBoardPanel 247 if ((component instanceof PlayerBoardPanel playerBoardPanel) && playerBoardPanel.getPlayerBoardNickname().equals(model.getMutableTurnOrder().getMutableCurrentPlayer().getNickname())) { 248 //switch to that Panel 249 gameInProgressPanel.setSelectedIndex(h); 250 //delegate the remaining part of execution to PlayerBoardPanel 251 playerBoardPanel.PlayCharacterCardEffect(10, finalI, OptionalValue.empty()); 252 } 253 } 254 return; 255 } 256 case Card11 card11 -> { 257 PawnColour toMove; 258 //get characterCard's state and convert its elements to String 259 String[] options = card11.getState().stream().map(Object::toString).toArray(String[]::new); 260 //create and show JOptionPane 261 int option = JOptionPane.showOptionDialog(null, "Select the pawn to move", "Select PawnColour", 262 JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, 263 null, options, options[0]); 264 if (option == -1) return; 265 //get selected pawn to move 266 toMove = PawnColour.getPawnColourFromText(options[option]); 267 //create playCharacterCard action and its playerActionRequest 268 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 269 finalI, OptionalValue.empty(), OptionalValue.of(toMove), OptionalValue.empty()); 270 playerActionRequest = new PlayerActionRequest(playCharacterCard); 271 } 272 case Card12 ignored12 -> { 273 PawnColour toRemove; 274 String[] options = new String[]{"RED", "PINK", "GREEN", "YELLOW", "BLUE"}; 275 int option = JOptionPane.showOptionDialog(null, "Select the pawn to remove", "Select a colour", 276 JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, 277 null, options, options[0]); 278 if (option == -1) return; 279 //get selected pawn to remove 280 toRemove = PawnColour.getPawnColourFromText(options[option]); 281 //create playCharacterCard action and its playerActionRequest 282 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 283 finalI, OptionalValue.empty(), OptionalValue.of(toRemove), OptionalValue.empty()); 284 playerActionRequest = new PlayerActionRequest(playCharacterCard); 285 } 286 default -> { 287 } 288 } 289 //save action inside guiReader then send the request to Server 290 guiSocketListener.savePlayerActionRequest(playCharacterCard); 291 try { 292 socketWrapper.sendMessage(playerActionRequest); 293 } catch (IOException ex) { 294 throw new RuntimeException(ex); 295 } 296 }); 297 //print eventual characterCard's state 298 checkStatefulCard(characterCards.get(i), characterCardsStatelabes.get(i)); 299 //draw Coin's image whether the card has been used at least once 300 if (characterCards.get(i).getTimeUsed() > 0) coinLabels.get(i).setVisible(true); 301 } 302 //--ABSOLUTE POSITIONING-- 303 coinLabels.get(0).setBounds(30, 195, 150, 160); 304 coinLabels.get(1).setBounds(371, 195, 150, 160); 305 coinLabels.get(2).setBounds(712, 195, 150, 160); 306 characterCardsButton.get(0).setBounds(100, 133, 205, 340); 307 characterCardsButton.get(1).setBounds(441, 133, 205, 340); 308 characterCardsButton.get(2).setBounds(782, 133, 205, 340); 309 characterCardsStatelabes.get(0).setBounds(100, 485, 205, 200); 310 characterCardsStatelabes.get(1).setBounds(441, 485, 205, 200); 311 characterCardsStatelabes.get(2).setBounds(782, 485, 205, 200); 312 //add all labels to container 313 coinLabels.forEach(pageBackground::add); 314 characterCardsButton.forEach(pageBackground::add); 315 characterCardsButton.forEach(button -> button.setLayout(null)); 316 characterCardsStatelabes.forEach(pageBackground::add); 317 } 318 319 /** 320 * Support method for printing characterCard's info 321 * 322 * @param characterCard CharacterCard desired by the player 323 * @return String containing all card's information 324 */ 325 private String printCharacterCardInfo(CharacterCard characterCard) { 326 String info; 327 switch (characterCard) { 328 case Card01 ignored9 -> 329 info = "<html><p width = 300px>EFFECT: Take 1 Student from this card and place it on " + 330 "an Island of your choice. Then, draw a new Student from the Bag and place it on this card.</p></html>"; 331 case Card02 ignored -> info = "<html><p width = 300px>EFFECT: During this turn, you take control of any" + 332 " number of Professors even if you have the same number of Students as the player who currently controls them.</p></html>"; 333 case Card03 ignored1 -> 334 info = "<html><p width = 300px>EFFECT: Choose an Island and resolve the Island as if " + 335 "Mother Nature had ended her movement there. Mother " + 336 "Nature will still move and the Island where she ends her movement will also be resolved.</p></html>"; 337 case Card04 ignored2 -> info = "<html><p width = 300px>EFFECT: You may move Mother Nature up to 2" + 338 " additional Islands than is indicated by the Assistant card you've played.</p></html>"; 339 case Card05 ignored3 -> 340 info = "<html><p width = 300px>EFFECT: Place a No Entrytile on an Island of your choice. " + 341 "The first time Mother Nature ends her movement there, put the No Entry tile back onto this card " + 342 "DO NOT calculate influence on that Island, or place any Towers.</p></html>"; 343 case Card06 ignored4 -> 344 info = "<html><p width = 300px>EFFECT: When resolving a Conquering on an Island, Towers do not count towards influence.</p></html>"; 345 case Card07 ignored7 -> 346 info = "<html><p width = 300px>EFFECT: you may take up to 3 students from this card and replace them with " + 347 "the same number of Students from your Entrance</html>"; 348 case Card08 ignored5 -> 349 info = "<html><p width = 300px>EFFECT: During the influence calculation this turn, you count as having 2 more influence</p></html>"; 350 case Card09 ignored6 -> 351 info = "<html><p width = 300px>EFFECT: Choose a color of Student: during the influence calculation this turn, that color adds no influence</p></html>"; 352 case Card10 ignored7 -> 353 info = "<html><p width = 300px>EFFECT: You may exchange up to 2 Students between your entrance and your Dining Room</p></html>"; 354 case Card11 ignored11 -> 355 info = "<html><p width = 300px>EFFECT: Take 1 Student from this card and place it in your Dining Room. " + 356 "Then, draw a new Student from the Bag and place it on this card.</p></html>"; 357 case Card12 ignored8 -> 358 info = "<html><p width = 300px>EFFECT: Choose a type of Student: every player (including yourself) must return 3 Students of that type " + 359 "from their Dining Room to the bag. If any player has fewer than 3 Students of that type " + 360 "return as many Students as they have.</p></html>"; 361 case default -> info = "CharacterCard not recognized"; 362 } 363 return info; 364 } 365 366 /** 367 * Support method, responsible for checking whether the characterCard contains some elements (statefulEffect) 368 * 369 * @param characterCard CharacterCard to check 370 * @param container Container that will contain eventual characterCard's state 371 */ 372 private void checkStatefulCard(CharacterCard characterCard, JLabel container) { 373 //continue only if characterCard has a state 374 if (!(characterCard instanceof StatefulEffect)) return; 375 //make CharacterCard's state's container visible 376 container.setVisible(true); 377 ArrayList<StudentButton> studentButtons; 378 // arranges student and tiles under card horizontally 379 container.setLayout(new FlowLayout()); 380 //check for CharacterCard's state's type 381 if (((StatefulEffect) characterCard).getStateType() == StateType.PAWNCOLOUR) { 382 //get characterCard's buttons and add them to container 383 studentButtons = getStudentButton(((StatefulEffect) characterCard).getState().stream().map(o -> (PawnColour) o).collect(Collectors.toList())); 384 studentButtons.forEach(container::add); 385 } else if (((StatefulEffect) characterCard).getStateType() == StateType.NOENTRY) { 386 //get NoEntryTiles' labels and add them to container 387 container.add(new NoEntryTileComponent(((StatefulEffect) characterCard).getState().size())); 388 } 389 } 390 391 /** 392 * Support method used for getting a list of StudentButtons starting from a list of PawnColours 393 * 394 * @param pawns List of pawnColours that will be used for creating the studentButtons 395 * @return list of StudentButton 396 */ 397 private ArrayList<StudentButton> getStudentButton(List<PawnColour> pawns) { 398 EnumMap<PawnColour, Integer> colourIntegerEnumMap = new EnumMap<>(PawnColour.class); 399 ArrayList<StudentButton> studentButtons = new ArrayList<>(); 400 //Count all pawnColours occurrences inside list received as input 401 for (PawnColour p : pawns) { 402 colourIntegerEnumMap.merge(p, 1, Integer::sum); 403 } 404 //create and add studentButtons 405 for (PawnColour p : colourIntegerEnumMap.keySet()) { 406 studentButtons.add(new StudentButton(p, colourIntegerEnumMap.get(p), false)); 407 } 408 return studentButtons; 409 } 410 411 412 }