You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2023/06/19 04:52:55 UTC

[groovy] branch master updated: GROOVY-11103: Provide an ascii barchart method

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new a475136606 GROOVY-11103: Provide an ascii barchart method
a475136606 is described below

commit a4751366065d7623f67c4579493ab9f0a52f9be4
Author: Paul King <pa...@asert.com.au>
AuthorDate: Fri Jun 16 23:20:44 2023 +1000

    GROOVY-11103: Provide an ascii barchart method
---
 .../org/codehaus/groovy/util/StringUtil.groovy     | 29 ++++++++++++++++++++++
 src/test/groovy/GroovyMethodsTest.groovy           | 12 +++++++++
 2 files changed, 41 insertions(+)

diff --git a/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy b/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
index 00fc6b7aae..3f07060096 100644
--- a/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
+++ b/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
@@ -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)
+    }
 }
diff --git a/src/test/groovy/GroovyMethodsTest.groovy b/src/test/groovy/GroovyMethodsTest.groovy
index e4eb16ff7c..0592e73e94 100644
--- a/src/test/groovy/GroovyMethodsTest.groovy
+++ b/src/test/groovy/GroovyMethodsTest.groovy
@@ -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 ] ),