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 }