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 }