[ all classes ]
[ it.polimi.ingsw.view.CLI ]
Coverage Summary for Class: ViewPrinter (it.polimi.ingsw.view.CLI)
Class | Class, % | Method, % | Line, % |
---|---|---|---|
ViewPrinter | 0% (0/ 1) | 0% (0/ 23) | 0% (0/ 226) |
1 package it.polimi.ingsw.view.CLI;
2
3 import com.google.gson.Gson;
4 import it.polimi.ingsw.utils.Observable;
5 import it.polimi.ingsw.utils.Observer;
6 import it.polimi.ingsw.utils.model.Command;
7 import it.polimi.ingsw.view.model.*;
8 import it.polimi.ingsw.view.socket.Parser;
9
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.List;
13 import java.util.stream.Collectors;
14 import java.util.stream.IntStream;
15
16 /**
17 * View Printer for CLI
18 */
19 class ViewPrinter extends Observable<String> implements Observer<ArrayList<Command>> {
20 /**
21 * Player's username
22 */
23 private String username;
24 /**
25 * Status if an update is needed due to server's update or some user's interaction
26 */
27 private boolean needUpdate;
28 /**
29 * Data Parser
30 */
31 private final Parser parser;
32 /**
33 * View Printer status
34 */
35 private boolean status;
36 /**
37 * Last command that user has selected
38 */
39 private Command lastCommand;
40 /**
41 * Set mode that the printer have to manage interaction with user
42 */
43 private boolean confirmMode = false;
44
45 /**
46 * ViewPrinter Constructor
47 *
48 * @param parser data parser
49 */
50 public ViewPrinter(Parser parser) {
51 this.parser = parser;
52 status = false;
53 needUpdate = false;
54 }
55
56 /**
57 * Set Status
58 *
59 * @param status status
60 */
61 public void setStatus(boolean status) {
62 this.status = status;
63 printView();
64 }
65
66 /**
67 * Set username
68 *
69 * @param username player username
70 */
71 public void setUsername(String username) {
72 if (username == null || username.length() == 0)
73 throw new NullPointerException();
74 this.username = username;
75 }
76
77 /**
78 * Clear console
79 */
80 public static void clearConsole() {
81 System.out.print("\033[H\033[2J");
82 System.out.flush();
83 }
84
85 /**
86 * Create a string with the word centered
87 *
88 * @param space string length
89 * @param word word to be centered
90 * @return string of length space with the word centered
91 */
92 private String centerFill(int space, String word) {
93 String out = String.format("%" + space + "s%s%" + space + "s", "", word, "");
94 return out.substring((out.length() - space) / 2, (out.length() + space) / 2);
95 }
96
97 /**
98 * Print in console a list of string
99 *
100 * @param toPrint list of string to be printed
101 */
102 private void printRow(ArrayList<String> toPrint) {
103 for (String x : toPrint)
104 System.out.format("%3s%s\n", "", x);
105 }
106
107 /**
108 * Make a collage between 2 arraylist of string cutting the first column of the
109 * second arraylist. Simply cat row per row, centering the content in the middle
110 *
111 * @param container_1 first arraylist of string
112 * @param container_2 second arraylist of string
113 * @return arraylist of previous two arraylist with a row per row cat and centered
114 * vertically
115 */
116 private ArrayList<String> composeRow(ArrayList<String> container_1, ArrayList<String> container_2) {
117 String patternTop = container_1.get(0) + container_2.get(0).substring(1, container_2.get(0).length());
118 String patternBottom = container_1.get(container_1.size() - 1) + container_2.get(container_2.size() - 1)
119 .substring(1, container_2.get(container_2.size() - 1).length());
120 container_1.remove(0);
121 container_2.remove(0);
122 container_1.remove(container_1.size() - 1);
123 container_2.remove(container_2.size() - 1);
124 int maxH = Math.max(container_1.size(), container_2.size());
125 ArrayList<String> toRes = new ArrayList<>();
126 toRes.add(patternTop);
127 for (int index = 0; index < maxH; index++) {
128 String toAdd = "";
129 if (index - (maxH - container_1.size()) / 2 >= 0 && index < (maxH + container_1.size()) / 2)
130 toAdd += container_1.get(index - (maxH - container_1.size()) / 2);
131 else
132 toAdd += "|" + String.format("%" + (container_1.get(0).length() - 1) + "s", "|");
133
134 if (index - (maxH - container_2.size()) / 2 >= 0 && index < (maxH + container_2.size()) / 2)
135 toAdd += container_2.get(index - (maxH - container_2.size()) / 2).substring(1,
136 container_2.get(index - (maxH - container_2.size()) / 2).length());
137 else
138 toAdd += String.format("%" + (container_2.get(0).length() - 1) + "s", "|");
139 toRes.add(toAdd);
140 }
141 toRes.add(patternBottom);
142 return toRes;
143 }
144
145 /**
146 * Create a string
147 *
148 * @param space length of string
149 * @param start start char of the string
150 * @param end end char of the string
151 * @param fill fill of the string
152 * @param padding white space between start to fill and fill to end.
153 * @return string created
154 */
155 private String breakRow(int space, String start, String end, String fill, int padding) {
156 String toRes = "";
157 space -= 2 * (1 + padding);
158 for (int i = 0; i < space; i++)
159 toRes += fill;
160 toRes = toRes.substring(0, space);
161 if (padding == 0)
162 return start + toRes + end;
163 else
164 return String.format("%s%" + padding + "s%s%" + padding + "s%s", start, "", toRes, "", end);
165 }
166
167 /**
168 * Create a string
169 *
170 * @param space length of string
171 * @param start start char of the string
172 * @param end end char of the string
173 * @param fill fill of the string
174 * @return string created
175 */
176 private String breakRow(int space, String start, String end, String fill) {
177 return breakRow(space, start, end, fill, 0);
178 }
179
180 /**
181 * Create an arraylist of string centering the content in the middle with a
182 * specific end and start char for each row
183 *
184 * @param toPrint arraylist of string to be centered
185 * @param space final length of each string
186 * @param start start char character
187 * @param end end char character
188 * @return arraylist of string created
189 */
190 private ArrayList<String> composeRow(List<ArrayList<String>> toPrint, int space, String start, String end) {
191 ArrayList<String> toRes = new ArrayList<>();
192 int maxH = toPrint.stream().map(e -> e.size()).max(Integer::compare).orElse(0);
193 toRes.add(breakRow(space + 1, start, end, " "));
194 IntStream.range(0, maxH).forEachOrdered(index -> {
195 String toAdd = start;
196 for (ArrayList<String> x : toPrint) {
197 if (index - (maxH - x.size()) / 2 >= 0 && index < (maxH + x.size()) / 2)
198 toAdd += centerFill(space / toPrint.size() - 1, x.get(index - (maxH - x.size()) / 2));
199 else
200 toAdd += centerFill(space / toPrint.size() - 1, "");
201 toAdd += "|";
202 }
203 toAdd = toAdd.substring(0, toAdd.length() - 1) + end;
204 toRes.add(toAdd);
205 });
206 toRes.add(breakRow(space + 1, start, end, " "));
207 return toRes;
208 }
209
210 /**
211 * Standard arraylist centering in the middle, with "|" as start and end char
212 * and a default string length equals to 90
213 *
214 * @param toPrint arraylist of string to be centered
215 * @return arraylist of string created
216 */
217 private ArrayList<String> composeRow(List<ArrayList<String>> toPrint) {
218 return composeRow(toPrint, 90, "|", "|");
219 }
220
221 /**
222 * Get Player's Info as an arraylist of string
223 *
224 * @return Player Info as an arraylist of string
225 */
226 private ArrayList<String> getPlayerInfo() {
227 ArrayList<String> toRes = new ArrayList<>();
228 toRes.addAll(composeRow(new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("PLAYERS"))))));
229 List<ArrayList<String>> toPrint = parser.getPlayers().stream().map(e -> {
230 ArrayList<String> toRet = (ArrayList<String>) e.getRawData();
231 if (e.getUsername().equals(username))
232 toRet.add(0, "(You)");
233 if (e.getUsername().equals(parser.getCurrentPlayer()))
234 toRet.add(0, "- Current Player -");
235 return toRet;
236 }).collect(Collectors.toList());
237 toRes.addAll(composeRow(toPrint));
238 toRes.add(breakRow(91, "|", "|", "-", 3));
239 return toRes;
240 }
241
242 /**
243 * Get Board Info as a arraylist of string
244 *
245 * @return Board Info as a arraylist of string
246 */
247 private ArrayList<String> getBoardInfo() {
248
249 ArrayList<String> toRes = new ArrayList<>();
250 toRes.addAll(composeRow(new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("BOARD"))))));
251 Cell[][] toPrint = parser.getBoard();
252 int position = 0;
253 for (Cell[] row : toPrint) {
254 ArrayList<ArrayList<String>> toPrintRow = new ArrayList<>();
255 String braker = "|";
256 for (Cell cell : row) {
257 ArrayList<String> toPush = (ArrayList<String>) cell.getRawData();
258 toPush.add("[" + position + "]");
259 toPrintRow.add(toPush);
260 braker += breakRow(19, "", " ", "-", 3);
261 position++;
262 }
263 braker = braker.substring(0, braker.length() - 1) + "|";
264 // toRes.add(breakRow(121, "|", "|", "-", 3));
265 toRes.addAll(composeRow(toPrintRow));
266
267 toRes.add(braker);
268 }
269 return toRes;
270 }
271
272 /**
273 * Get Player's Action Info as a arraylist of string
274 *
275 * @return Player Action Info as a arraylist of string
276 */
277 private ArrayList<String> getActionInfo() {
278 if (username == null)
279 return null;
280 int space = 12 * 7;
281 ArrayList<String> toRes = new ArrayList<>();
282 toRes.add(breakRow(space + 1, ".", ".", "-"));
283 if (!parser.getGamePhase().equals("END") && username.equals(parser.getCurrentPlayer())) {
284 toRes.addAll(composeRow(
285 new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("ACTIONS", "It's your turn!")))), space,
286 "|", "|"));
287 ArrayList<ArrayList<String>> toPrint = (ArrayList<ArrayList<String>>) parser.getUsableCommandList().stream()
288 .map(e -> {
289 ArrayList<String> toRet;
290 switch (e.getType()) {
291 case "action":
292 if (e.getInfo() == null)
293 toRet = new ArrayList<>(Arrays.asList("End Turn"));
294 else if (new Gson().fromJson(e.getInfo(), TypeAction.class).getTypeAction()
295 .equals("Swap"))
296 toRet = new Gson().fromJson(e.getInfo(), Swap.class).getRawData();
297 else
298 toRet = (ArrayList<String>) new Gson().fromJson(e.getInfo(), Build.class)
299 .getRawData();
300 break;
301 case "board":
302 toRet = (ArrayList<String>) new Gson().fromJson(e.getInfo(), Cell.class).getRawData();
303 toRet.add("[" + e.getFuncData() + "]");
304 break;
305 case "color":
306 toRet = (ArrayList<String>) new Color(e.getInfo()).getRawData();
307 break;
308 case "god":
309 toRet = (ArrayList<String>) new God(e.getInfo()).getRawData();
310 break;
311 case "godList":
312 toRet = (ArrayList<String>) new God(e.getInfo()).getRawData();
313 break;
314 case "player":
315 toRet = (ArrayList<String>) new Gson().fromJson(e.getInfo(), Player.class).getRawData();
316 break;
317 default:
318 toRet = null;
319 break;
320 }
321 return toRet;
322 }).filter(e -> e != null && e.size() > 0).collect(Collectors.toList());
323 int indexAction = 0;
324 while (toPrint.size() > 0) {
325 List<ArrayList<String>> rowToPrint = (List<ArrayList<String>>) toPrint.subList(0,
326 toPrint.size() < 3 ? toPrint.size() : 3);
327 int i = 0;
328 for (ArrayList<String> x : rowToPrint)
329 x.add(0, "Action: " + (indexAction + i++));
330 indexAction += rowToPrint.size();
331 toRes.addAll(composeRow(rowToPrint, space, "|", "|"));
332 toRes.add(breakRow(space + 1, "|", "|", "-", 3));
333 toPrint.subList(0, toPrint.size() < 3 ? toPrint.size() : 3).clear();
334 }
335 toRes.remove(toRes.size() - 1);
336 } else if (parser.getPlayers().stream()
337 .anyMatch(e -> e.getUsername().equals(username) && e.getStatus().equals("WIN"))) {
338 ArrayList<String> winAsci = new ArrayList<>(
339 Arrays.asList("__ ___ ", "\\ \\ / (_) ", " \\ \\ /\\ / / _ _ __ ",
340 " \\ \\/ \\/ / | | '_ \\ ", " \\ /\\ / | | | | |", " \\/ \\/ |_|_| |_|"));
341 toRes.addAll(composeRow(new ArrayList<>(Arrays.asList(winAsci)), space, "|", "|"));
342
343 } else if (parser.getPlayers().stream()
344 .anyMatch(e -> e.getUsername().equals(username) && e.getStatus().equals("LOSE"))) {
345 ArrayList<String> loseAsci = new ArrayList<>(
346 Arrays.asList(" _ ", "| | ", "| | ___ ___ ___ ",
347 "| | / _ \\/ __|/ _ \\", "| |___| (_) \\__ \\ __/", "|______\\___/|___/\\___|"));
348 toRes.addAll(composeRow(new ArrayList<>(Arrays.asList(loseAsci)), space, "|", "|"));
349 } else {
350 toRes.addAll(composeRow(
351 new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("ACTIONS", "It's not your turn!")))),
352 space, "|", "|"));
353 }
354 toRes.add(breakRow(space + 1, "'", "'", "-"));
355 return toRes;
356 }
357
358 /**
359 * Get a Player Action Command based on the index
360 *
361 * @param index command index
362 * @return command selected, otherwise null
363 */
364 private Command getActionString(int index) {
365 try {
366 return parser.getUsableCommandList().get(index);
367 } catch (Exception e) {
368 return null;
369 }
370 }
371
372 /**
373 * Use a Player Action Command based on the index
374 *
375 * @param index command index
376 */
377 public void useAction(String index) {
378 index = index.trim();
379 if (index.toUpperCase().equals("QUIT")) {
380 status = false;
381 return;
382 }
383 needUpdate = true;
384 Command toSend = null;
385 try {
386 toSend = getActionString(Integer.parseInt(index));
387 if (toSend != null && (toSend.getFuncName().equals("setGodList") || toSend.getFuncName().equals("setGod"))
388 && (lastCommand == null || !new Gson().toJson(lastCommand).equals(new Gson().toJson(toSend)))) {
389 confirmMode = true;
390 printView();
391 System.out.print("\n God " + toSend.getFuncData() + " effect:\n\n "
392 + GodEffect.strConverter(toSend.getFuncData()).getEffect()
393 + "\n\n Retype action code to confirm or Type another God to change: ");
394 lastCommand = toSend;
395 return;
396 }
397 confirmMode = false;
398 } catch (Exception e) {
399 // fail parse
400 }
401 if (toSend != null)
402 notify(Parser.toString(toSend));
403 else
404 printView();
405 }
406
407 /**
408 * Print view
409 */
410 private synchronized void printView() {
411 if (!needUpdate || !status)
412 return;
413 needUpdate = false;
414 clearConsole();
415
416 printLogo();
417 ArrayList<String> gameInfo, Actions;
418 gameInfo = new ArrayList<>(Arrays.asList(breakRow(91, ".", ".", "-")));
419 // gameInfo.addAll(printGameInfo());
420 gameInfo.addAll(getPlayerInfo());
421 gameInfo.addAll(getBoardInfo());
422 gameInfo.remove(gameInfo.size() - 1);
423 gameInfo.add(breakRow(91, "'", "'", "-"));
424 Actions = getActionInfo();
425
426 if (Actions != null)
427 printRow(composeRow(gameInfo, Actions));
428 else
429 printRow(gameInfo);
430
431 if (parser.getGamePhase().equals("END"))
432 System.out.println(" Game ended");
433
434 System.out.print(" Type QUIT to exit from the game\n ");
435
436 if (!confirmMode && username.equals(parser.getCurrentPlayer()) && !parser.getGamePhase().equals("END"))
437 System.out.print(" Type Action number: ");
438
439 if (!username.equals(parser.getCurrentPlayer())
440 && (parser.getGamePhase().equals("SET_GOD_LIST") || parser.getGamePhase().equals("CHOOSE_GOD"))) {
441 List<Command> godList = parser.getCommandList("godList");
442 if (godList.size() == 0)
443 return;
444 System.out.println("\n God to use in this Game:");
445 parser.getCommandList("godList").forEach(e -> {
446 System.out.println(
447 "\n God " + e.getInfo() + "\n\n " + GodEffect.strConverter(e.getInfo()).getEffect());
448 });
449 }
450 }
451
452 @Override
453 public void update(ArrayList<Command> message) {
454 // System.out.println("view: "+ message);
455 if (message == null || message.size() == 0)
456 return;
457 needUpdate = true;
458 printView();
459 }
460
461 /**
462 * Print Logo
463 */
464 public static void printLogo() {
465 ArrayList<String> logoAsci = new ArrayList<>(Arrays.asList(
466 " .----------------. .----------------. .-----------------. .----------------. .----------------. .----------------. .----------------. .-----------------. .----------------. ",
467 " | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |",
468 " | | _______ | || | __ | || | ____ _____ | || | _________ | || | ____ | || | _______ | || | _____ | || | ____ _____ | || | _____ | |",
469 " | | / ___ | | || | / \\ | || ||_ \\|_ _| | || | | _ _ | | || | .' `. | || | |_ __ \\ | || | |_ _| | || ||_ \\|_ _| | || | |_ _| | |",
470 " | | | (__ \\_| | || | / /\\ \\ | || | | \\ | | | || | |_/ | | \\_| | || | / .--. \\ | || | | |__) | | || | | | | || | | \\ | | | || | | | | |",
471 " | | '.___`-. | || | / ____ \\ | || | | |\\ \\| | | || | | | | || | | | | | | || | | __ / | || | | | | || | | |\\ \\| | | || | | | | |",
472 " | | |`\\____) | | || | _/ / \\ \\_ | || | _| |_\\ |_ | || | _| |_ | || | \\ `--' / | || | _| | \\ \\_ | || | _| |_ | || | _| |_\\ |_ | || | _| |_ | |",
473 " | | |_______.' | || ||____| |____|| || ||_____|\\____| | || | |_____| | || | `.____.' | || | |____| |___| | || | |_____| | || ||_____|\\____| | || | |_____| | |",
474 " | | | || | | || | | || | | || | | || | | || | | || | | || | | |",
475 " | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |",
476 " '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' "));
477 System.out.print("\n\n");
478 for (String x : logoAsci)
479 System.out.println(x);
480 System.out.print("\n\n");
481
482 }
483 }