323 lines
12 KiB
HTML
323 lines
12 KiB
HTML
|
|
|
|
|
|
<!DOCTYPE html>
|
|
<html id="htmlId">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
|
<title>Coverage Report > AsciiTable</title>
|
|
<style type="text/css">
|
|
@import "../../css/coverage.css";
|
|
@import "../../css/idea.min.css";
|
|
</style>
|
|
<script type="text/javascript" src="../../js/highlight.min.js"></script>
|
|
<script type="text/javascript" src="../../js/highlightjs-line-numbers.min.js"></script>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="content">
|
|
<div class="breadCrumbs">
|
|
Current scope: <a href="../../index.html">all classes</a>
|
|
<span class="separator">|</span>
|
|
<a href="../index.html">it.polimi.ingsw.gc14.View.TUI</a>
|
|
</div>
|
|
|
|
<h1>Coverage Summary for Class: AsciiTable (it.polimi.ingsw.gc14.View.TUI)</h1>
|
|
|
|
<table class="coverageStats">
|
|
<tr>
|
|
<th class="name">Class</th>
|
|
<th class="coverageStat
|
|
">
|
|
Class, %
|
|
</th>
|
|
<th class="coverageStat
|
|
">
|
|
Method, %
|
|
</th>
|
|
<th class="coverageStat
|
|
">
|
|
Branch, %
|
|
</th>
|
|
<th class="coverageStat
|
|
">
|
|
Line, %
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td class="name">AsciiTable</td>
|
|
<td class="coverageStat">
|
|
<span class="percent">
|
|
100%
|
|
</span>
|
|
<span class="absValue">
|
|
(1/1)
|
|
</span>
|
|
</td>
|
|
<td class="coverageStat">
|
|
<span class="percent">
|
|
90.9%
|
|
</span>
|
|
<span class="absValue">
|
|
(10/11)
|
|
</span>
|
|
</td>
|
|
<td class="coverageStat">
|
|
<span class="percent">
|
|
52.6%
|
|
</span>
|
|
<span class="absValue">
|
|
(40/76)
|
|
</span>
|
|
</td>
|
|
<td class="coverageStat">
|
|
<span class="percent">
|
|
82.2%
|
|
</span>
|
|
<span class="absValue">
|
|
(60/73)
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
<br/>
|
|
<br/>
|
|
|
|
|
|
<pre>
|
|
<code class="sourceCode" id="sourceCode"> package it.polimi.ingsw.gc14.View.TUI;
|
|
import java.util.*;
|
|
|
|
/**
|
|
* General-purpose helper for building fixed-width ASCII/Unicode tables in a TUI.
|
|
*
|
|
* <p>A table is built by adding rows one at a time, then calling {@link #build()}
|
|
* to obtain the fully rendered string. Column width is computed automatically
|
|
* from the widest cell across all rows.
|
|
*
|
|
* <p>Cell widths are measured in terminal columns, not Java {@code char} units:
|
|
* wide characters (emoji, CJK) count as 2 columns each.
|
|
*
|
|
* <p>Example usage:
|
|
* <pre>{@code
|
|
* AsciiTable table = new AsciiTable(BorderStyle.UNICODE, 3);
|
|
* table.addHeader("Name", "🍖", "⭐");
|
|
* table.addRow("Alice", "4", "12");
|
|
* table.addRow("Bob", "2", "8");
|
|
* System.out.println(table.build());
|
|
* }</pre>
|
|
*/
|
|
public class AsciiTable {
|
|
/** Border style used to draw corners, lines, and junctions. */
|
|
private final BorderStyle s;
|
|
|
|
/** Number of columns in this table. */
|
|
private final int cols;
|
|
|
|
/** All rows of the table, in insertion order. */
|
|
<b class="fc"> private final List<List<String>> rows = new ArrayList<>();</b>
|
|
|
|
/** Indices of rows after which a horizontal separator line is drawn. */
|
|
<b class="fc"> private final List<Integer> separators = new ArrayList<>();</b>
|
|
|
|
/**
|
|
* Creates a new empty table with the given border style and column count.
|
|
*
|
|
* @param s the border style to use when rendering.
|
|
* @param cols the number of columns.
|
|
*/
|
|
<b class="fc"> public AsciiTable(BorderStyle s, int cols) {</b>
|
|
<b class="fc"> this.s = s; this.cols = cols;</b>
|
|
}
|
|
|
|
/**
|
|
* Appends a row using varargs cells.
|
|
*
|
|
* @param cells one value per column.
|
|
*/
|
|
<b class="fc"> public void addRow(String... cells) { rows.add(Arrays.asList(cells)); }</b>
|
|
|
|
/**
|
|
* Appends a row from an existing list.
|
|
*
|
|
* @param cells one value per column.
|
|
*/
|
|
<b class="fc"> public void addRow(List<String> cells) { rows.add(cells); }</b>
|
|
|
|
/**
|
|
* Inserts a header row at position 0 and marks it with a separator line below it.
|
|
*
|
|
* @param cells one header label per column.
|
|
*/
|
|
public void addHeader(String... cells) {
|
|
<b class="fc"> rows.add(0, Arrays.asList(cells));</b>
|
|
<b class="fc"> separators.add(0);</b>
|
|
}
|
|
|
|
/**
|
|
* Marks a separator line to be drawn after the last row added so far.
|
|
*/
|
|
<b class="fc"> public void addSeparator() { separators.add(rows.size() - 1); }</b>
|
|
|
|
/**
|
|
* Renders the table to a multi-line string.
|
|
* Column width is the widest cell in display columns (wide chars = 2), plus 1.
|
|
*
|
|
* @return the fully rendered table as a multi-line string.
|
|
*/
|
|
public String build() {
|
|
<b class="fc"> var sb = new StringBuilder();</b>
|
|
<b class="fc"> int maxWidth = rows.stream()</b>
|
|
<b class="fc"> .mapToInt(x -> x.stream().mapToInt(AsciiTable::displayWidth).max().orElse(0))</b>
|
|
<b class="fc"> .max().orElse(0) + 1;</b>
|
|
<b class="fc"> sb.append(hline(s.tl(), s.mt(), s.tr(), maxWidth)).append('\n');</b>
|
|
|
|
<b class="fc"> for (int i = 0; i < rows.size(); i++) {</b>
|
|
<b class="fc"> sb.append(s.v());</b>
|
|
<b class="fc"> for (String cell : rows.get(i))</b>
|
|
<b class="fc"> sb.append(rpad(" " + cell, maxWidth)).append(s.v());</b>
|
|
<b class="fc"> sb.append('\n');</b>
|
|
<b class="pc"> if (separators.contains(i) && i < rows.size() - 1)</b>
|
|
<b class="fc"> sb.append(hline(s.sl(), s.sx(), s.sr(), maxWidth)).append('\n');</b>
|
|
}
|
|
<b class="fc"> sb.append(hline(s.bl(), s.mb(), s.br(), maxWidth));</b>
|
|
<b class="fc"> return sb.toString();</b>
|
|
}
|
|
/**
|
|
* Builds a single horizontal borderline across all columns.
|
|
*
|
|
* @param l left-end character.
|
|
* @param m middle junction character (between columns).
|
|
* @param r right-end character.
|
|
* @param maxWidth width in display columns of each cell (including padding).
|
|
* @return the rendered horizontal line string.
|
|
*/
|
|
private String hline(String l, String m, String r, int maxWidth) {
|
|
<b class="fc"> var sb = new StringBuilder(l);</b>
|
|
<b class="fc"> for (int i = 0; i < cols; i++) {</b>
|
|
<b class="fc"> sb.repeat(Objects.requireNonNull(s.h()), maxWidth);</b>
|
|
<b class="fc"> if (i < cols - 1) sb.append(m);</b>
|
|
}
|
|
<b class="fc"> return sb.append(r).toString();</b>
|
|
}
|
|
|
|
/**
|
|
* Pads {@code s} with trailing spaces so its display width equals {@code w}.
|
|
* If the string is already at or over {@code w} columns, it is returned as-is.
|
|
*/
|
|
private static String rpad(String s, int w) {
|
|
<b class="fc"> int dw = displayWidth(s);</b>
|
|
<b class="fc"> if (dw >= w) return s;</b>
|
|
<b class="fc"> return s + " ".repeat(w - dw);</b>
|
|
}
|
|
|
|
/**
|
|
* Places two pre-rendered text blocks side by side, separated by a gap.
|
|
* Left-block lines are padded to a uniform display width so the right block
|
|
* always starts at the same column. Uses {@link #displayWidth} for measurement.
|
|
*
|
|
* @param left lines of the left block.
|
|
* @param right lines of the right block.
|
|
* @param gap number of space characters between the two blocks.
|
|
* @return the combined multi-line string.
|
|
*/
|
|
public static String sideBySide(List<String> left, List<String> right, int gap) {
|
|
<b class="nc"> int leftWidth = left.stream().mapToInt(AsciiTable::displayWidth).max().orElse(0);</b>
|
|
<b class="nc"> int maxHeight = Math.max(left.size(), right.size());</b>
|
|
<b class="nc"> String padding = " ".repeat(gap);</b>
|
|
|
|
<b class="nc"> var sb = new StringBuilder();</b>
|
|
<b class="nc"> for (int i = 0; i < maxHeight; i++) {</b>
|
|
<b class="nc"> String l = i < left.size() ? left.get(i) : " ".repeat(leftWidth);</b>
|
|
<b class="nc"> l = rpad(l, leftWidth);</b>
|
|
<b class="nc"> String r = i < right.size() ? right.get(i) : "";</b>
|
|
<b class="nc"> sb.append(l).append(padding).append(r).append('\n');</b>
|
|
}
|
|
<b class="nc"> return sb.toString();</b>
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the number of terminal columns required to display {@code s}.
|
|
* Wide characters (emoji, CJK, full-width) count as 2; all others as 1.
|
|
*
|
|
* @param s the string to measure; ANSI escape sequences are stripped before counting.
|
|
* @return the display width in terminal columns.
|
|
*/
|
|
public static int displayWidth(String s) {
|
|
<b class="fc"> s = s.replaceAll("\033\\[[^m]*m", "");</b>
|
|
<b class="fc"> int w = 0;</b>
|
|
<b class="fc"> for (int i = 0; i < s.length(); ) {</b>
|
|
<b class="fc"> int cp = s.codePointAt(i);</b>
|
|
<b class="fc"> w += isWide(cp) ? 2 : 1;</b>
|
|
<b class="fc"> i += Character.charCount(cp);</b>
|
|
}
|
|
<b class="fc"> return w;</b>
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} when {@code cp} is a wide (2-column) character.
|
|
* Covers CJK blocks, Hangul, full-width forms, and emoji (including
|
|
* the specific emoji used in this project: 🍖 U+1F357, ⭐ U+2B50).
|
|
*/
|
|
private static boolean isWide(int cp) {
|
|
<b class="fc"> if (cp < 0x1100) return false;</b>
|
|
<b class="pc"> if (cp <= 0x115F) return true;</b>
|
|
<b class="pc"> if (cp < 0x2E80) {</b>
|
|
<b class="nc"> return cp == 0x2B50</b>
|
|
|| cp == 0x2B55;
|
|
}
|
|
<b class="pc"> if (cp <= 0x303E) return true;</b>
|
|
<b class="pc"> if (cp < 0x3041) return false;</b>
|
|
<b class="pc"> if (cp <= 0xA4CF) return true;</b>
|
|
<b class="pc"> if (cp < 0xA960) return false;</b>
|
|
<b class="pc"> if (cp <= 0xA97F) return true;</b>
|
|
<b class="pc"> if (cp < 0xAC00) return false;</b>
|
|
<b class="pc"> if (cp <= 0xD7AF) return true;</b>
|
|
<b class="pc"> if (cp < 0xF900) return false;</b>
|
|
<b class="pc"> if (cp <= 0xFAFF) return true;</b>
|
|
<b class="pc"> if (cp < 0xFE10) return false;</b>
|
|
<b class="pc"> if (cp <= 0xFE1F) return true;</b>
|
|
<b class="pc"> if (cp < 0xFE30) return false;</b>
|
|
<b class="pc"> if (cp <= 0xFE6F) return true;</b>
|
|
<b class="pc"> if (cp < 0xFF00) return false;</b>
|
|
<b class="pc"> if (cp <= 0xFF60) return true;</b>
|
|
<b class="pc"> if (cp < 0xFFE0) return false;</b>
|
|
<b class="pc"> if (cp <= 0xFFE6) return true;</b>
|
|
<b class="pc"> if (cp < 0x1F004) return false;</b>
|
|
<b class="pc"> if (cp <= 0x1FAFF) return true;</b>
|
|
|
|
<b class="nc"> if (cp < 0x20000) return false;</b>
|
|
<b class="nc"> return cp <= 0x3FFFD;</b>
|
|
}
|
|
}
|
|
</code>
|
|
</pre>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
(function() {
|
|
var msie = false, msie9 = false;
|
|
/*@cc_on
|
|
msie = true;
|
|
@if (@_jscript_version >= 9)
|
|
msie9 = true;
|
|
@end
|
|
@*/
|
|
|
|
if (!msie || msie && msie9) {
|
|
hljs.highlightAll()
|
|
hljs.initLineNumbersOnLoad();
|
|
}
|
|
})();
|
|
</script>
|
|
|
|
<div class="footer">
|
|
|
|
<div style="float:right;">generated on 2026-06-19 22:53</div>
|
|
</div>
|
|
</body>
|
|
</html>
|