diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java new file mode 100644 index 0000000..7f6b1fc --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -0,0 +1,48 @@ +package it.polimi.ingsw.gc14.View.TUI; +import java.util.*; + +// Helper generale per costruire tabelle ASCII +public class AsciiTable { + private final BorderStyle s; + private final int cols, colWidth; + private final List> rows = new ArrayList<>(); + private final List separators = new ArrayList<>(); + + public AsciiTable(BorderStyle s, int cols, int colWidth) { + this.s = s; this.cols = cols; this.colWidth = colWidth; + } + + public void addRow(String... cells) { rows.add(Arrays.asList(cells)); } + public void addRow(List cells) { rows.add(cells); } + public void addHeader(String... cells) { rows.add(0, Arrays.asList(cells)); separators.add(0); } + public void addSeparator() { separators.add(rows.size()); } + + public String build() { + var sb = new StringBuilder(); + sb.append(hline(s.tl(), s.mt(), s.tr())).append('\n'); + for (int i = 0; i < rows.size(); i++) { + sb.append(s.v()); + for (String cell : rows.get(i)) + sb.append(rpad(" " + cell, colWidth)).append(s.v()); + sb.append('\n'); + if (separators.contains(i) && i < rows.size() - 1) + sb.append(hline(s.sl(), s.sx(), s.sr())).append('\n'); + } + sb.append(hline(s.bl(), s.mb(), s.br())); + return sb.toString(); + } + + private String hline(String l, String m, String r) { + var sb = new StringBuilder(l); + for (int i = 0; i < cols; i++) { + sb.append(s.h().repeat(colWidth)); + if (i < cols - 1) sb.append(m); + } + return sb.append(r).toString(); + } + + private String rpad(String s, int w) { + if (s.length() >= w) return s.substring(0, w); + return s + " ".repeat(w - s.length()); + } +} \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/BorderStyle.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/BorderStyle.java new file mode 100644 index 0000000..13b365d --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/BorderStyle.java @@ -0,0 +1,39 @@ +package it.polimi.ingsw.gc14.View.TUI; + +public enum BorderStyle { + UNICODE("╔","╗","╚","╝","═","║","╠","╣","╦","╩","╬","├","┤","─","┼"), + ASCII ("+","+","+","+","-","|","+","+","+","+","+","+","+","-","+"), + ROUNDED("╭","╮","╰","╯","─","│","├","┤","┬","┴","┼","├","┤","─","┼"); + + private final String tl,tr,bl,br,h,v,ml,mr,mt,mb,x,sl,sr,sh,sx; + + BorderStyle(String tl,String tr,String bl,String br, + String h, String v, String ml,String mr, + String mt,String mb,String x, + String sl,String sr,String sh,String sx) { + this.tl = tl; this.tr = tr; + this.bl = bl; this.br = br; + this.h = h; this.v = v; + this.ml = ml; this.mr = mr; + this.mt = mt; this.mb = mb; + this.x = x; + this.sl = sl; this.sr = sr; + this.sh = sh; this.sx = sx; + } + + public String tl() { return tl; } + public String tr() { return tr; } + public String bl() { return bl; } + public String br() { return br; } + public String h() { return h; } + public String v() { return v; } + public String ml() { return ml; } + public String mr() { return mr; } + public String mt() { return mt; } + public String mb() { return mb; } + public String x() { return x; } + public String sl() { return sl; } + public String sr() { return sr; } + public String sh() { return sh; } + public String sx() { return sx; } +} diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java new file mode 100644 index 0000000..1880c51 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java @@ -0,0 +1,93 @@ +package it.polimi.ingsw.gc14.View.TUI; +import it.polimi.ingsw.gc14.Model.Game; + +public class TUI { + + // ── dati di stato ─────────────────────────────────────────── + private BorderStyle style = BorderStyle.UNICODE; + private Game model; + // ── punto di ingresso ─────────────────────────────────────── + public String render() { + var sb = new StringBuilder(); + sb.append(renderHeader()); + sb.append(renderTurnOrder()); + sb.append(renderOfferTrack()); + sb.append(renderCardRows()); + sb.append(renderTableaux()); + sb.append(renderFooter()); + return sb.toString(); + } + + // ── sezioni ───────────────────────────────────────────────── + private String renderTurnOrder() { + var table = new AsciiTable(style, 4, 10); // 4 colonne, largh 10 + table.addRow(model.getPlayers().stream() + .map(p -> + ". " + p.getUserName()) + .toList()); + table.addRow(state.getPlayers().stream() + .map(p -> p.getTotemPosition() != null + ? "totem: " + p.getTotemPosition() + : "(da piaz)") + .toList()); + return " TURN ORDER\n" + table.build() + "\n"; + } + + private String renderOfferTrack() { + var table = new AsciiTable(style, 5, 14); + table.addRow(state.getOfferTiles().stream() + .map(t -> t.getId() + ": " + t.getLabel()).toList()); + table.addRow(state.getOfferTiles().stream() + .map(OfferTile::getRowsLabel).toList()); + table.addRow(state.getOfferTiles().stream() + .map(t -> state.getTotemOnTile(t.getId())).toList()); + return " OFFER TRACK\n" + table.build() + "\n"; + } + + private String renderCardRows() { + int cols = state.getTopRow().size(); + var table = new AsciiTable(style, cols, 13); + table.addRow(state.getTopRow().stream() + .map(c -> "[" + c.getTypeLabel() + "]").toList()); + table.addRow(state.getTopRow().stream() + .map(Card::getName).toList()); + table.addSeparator(); + table.addRow(state.getBotRow().stream() + .map(c -> "[" + c.getTypeLabel() + "]").toList()); + table.addRow(state.getBotRow().stream() + .map(Card::getName).toList()); + return " CARTE IN GIOCO\n" + prefix("TOP ", "BOT ", table.build()) + "\n"; + } + + private String renderTableaux() { + var sb = new StringBuilder(" TABLEAU GIOCATORI\n\n"); + for (Player p : state.getPlayers()) { + String marker = p.isActive() ? ">>>" : " "; + sb.append(String.format(" %s %s%s Food:%d PP:%d%n", + marker, p.getName(), + p.isActive() ? " [TUO TURNO]" : "", + p.getFood(), p.getPP())); + sb.append(renderPlayerTableau(p)); + sb.append("\n"); + } + return sb.toString(); + } + + private String renderPlayerTableau(Player p) { + var table = new AsciiTable(style, 3, 14); + table.addHeader("PERSONAGGI", "EDIFICI", "RISORSE"); + int rows = Math.max(p.getChars().size(), + Math.max(p.getBuildings().size(), 3)); + for (int i = 0; i < rows; i++) { + String ch = i < p.getChars().size() ? p.getChars().get(i) : ""; + String bd = i < p.getBuildings().size() ? p.getBuildings().get(i) : ""; + String rs = switch (i) { + case 0 -> "Food: " + "O".repeat(p.getFood()); + case 1 -> "PP: " + p.getPP(); + case 2 -> "Chars:" + p.getChars().size() + " Edif:" + p.getBuildings().size(); + default -> ""; + }; + table.addRow(ch, bd, rs); + } + return " " + table.build().replace("\n", "\n "); + } +}