Skip to content

Commit

Permalink
GROOVY-11103: Provide an ascii barchart method
Browse files Browse the repository at this point in the history
  • Loading branch information
paulk-asert committed Jun 19, 2023
1 parent ceb167a commit a475136
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,33 @@ class StringUtil {
text
}
}

private static String BLOCK = '\u2588'
private static char FRACTIONAL_OFFSET = BLOCK.codePointAt(0) + 7

/**
* Draw a band whose width is proportional to (x - min) and equal to width
* when x equals max. Unicode block element characters are used to draw
* fractional blocks. A 1/8 block is always added at the start of the bar.
*
* If using Windows command-line, make sure you are using the Unicode
* codepage (65001) and a font that supports block elements (like Cascadia).
*
* @param x the value for the bar to be drawn
* @param min the minimum value
* @param max the maximum value
* @param width how many characters should the maximum value be rendered as (default 40)
* @return the rendered ascii barchart string
* @since 5.0.0
*/
static String bar(Number x, Number min, Number max, int width = 40) {
int fracWidth = width * 8
assert min < max && x >= min && x <= max
Number interval = max - min
int barWidth = ((x - min) / interval * fracWidth).intValue()
int fullChunks = barWidth.intdiv(8)
int remainder = barWidth % 8
// unicode for fractional blocks (7/8, 6/8, etc.) are adjacent
BLOCK * fullChunks + Character.valueOf(FRACTIONAL_OFFSET - remainder as char)
}
}
12 changes: 12 additions & 0 deletions src/test/groovy/GroovyMethodsTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,18 @@ class GroovyMethodsTest extends GroovyTestCase {
assert 'Hello, World!'.tr(' --', 'Z') == 'HelloZZWorldZ'
}

void testBar() {
assert StringUtil.bar(0, 0, 39) == '\u258f'
assert StringUtil.bar(1, 0, 39) == '\u2588\u258f'
assert StringUtil.bar(2, 0, 39) == '\u2588\u2588\u258f'
assert StringUtil.bar(0, 0, 39, 80) == '\u258f'
assert StringUtil.bar(1, 0, 39, 80) == '\u2588\u2588\u258f'
assert StringUtil.bar(2, 0, 39, 80) == '\u2588\u2588\u2588\u2588\u258f'
assert StringUtil.bar(0, 0, 39, 20) == '\u258f'
assert StringUtil.bar(1, 0, 39, 20) == '\u258b'
assert StringUtil.bar(2, 0, 39, 20) == '\u2588\u258f'
}

void testListTake() {
def data = [
new ArrayList( [ 1, 2, 3 ] ),
Expand Down

0 comments on commit a475136

Please sign in to comment.