From b0f7db47eeb68cb1d36f1e2b83d0a3271f84f801 Mon Sep 17 00:00:00 2001 From: Piotr Zych <77621271+P1otrulla@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:49:36 +0200 Subject: [PATCH 1/5] Added SimpleDurationUtil --- .../commons/time/SimpleDurationUtil.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java diff --git a/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java new file mode 100644 index 0000000..7f9f9c2 --- /dev/null +++ b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java @@ -0,0 +1,48 @@ +package com.eternalcode.commons.time; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; + +public class SimpleDurationUtil { + + private static final Duration ONE_SECOND = Duration.ofSeconds(1); + private static final String ZERO_SECONDS = "0s"; + + private static final TemporalAmountParser WITHOUT_MILLIS_FORMAT = new DurationParser() + .withUnit("s", ChronoUnit.SECONDS) + .withUnit("m", ChronoUnit.MINUTES) + .withUnit("h", ChronoUnit.HOURS) + .withUnit("d", ChronoUnit.DAYS) + .withUnit("w", ChronoUnit.WEEKS) + .withUnit("mo", ChronoUnit.MONTHS) + .withUnit("y", ChronoUnit.YEARS) + .roundOff(ChronoUnit.MILLIS); + + private static final TemporalAmountParser STANDARD_FORMAT = new DurationParser() + .withUnit("ms", ChronoUnit.MILLIS) + .withUnit("s", ChronoUnit.SECONDS) + .withUnit("m", ChronoUnit.MINUTES) + .withUnit("h", ChronoUnit.HOURS) + .withUnit("d", ChronoUnit.DAYS) + .withUnit("w", ChronoUnit.WEEKS) + .withUnit("mo", ChronoUnit.MONTHS) + .withUnit("y", ChronoUnit.YEARS); + + public static String format(Duration duration, boolean removeMillis) { + if (removeMillis) { + if (duration.toMillis() < ONE_SECOND.toMillis()) { + return "0s"; + } + + return WITHOUT_MILLIS_FORMAT.format(duration); + } + + return STANDARD_FORMAT.format(duration); + } + + public static String format(Duration duration) { + return format(duration, false); + } + + +} From 24fa44a64f40e5ef760f3707b18e3e56e66d8564 Mon Sep 17 00:00:00 2001 From: Piotr Zych <77621271+P1otrulla@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:50:03 +0200 Subject: [PATCH 2/5] Created tests for SimpleDurationUtil --- .../commons/time/SimpleDurationUtilTest.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 eternalcode-commons-shared/test/com/eternalcode/commons/time/SimpleDurationUtilTest.java diff --git a/eternalcode-commons-shared/test/com/eternalcode/commons/time/SimpleDurationUtilTest.java b/eternalcode-commons-shared/test/com/eternalcode/commons/time/SimpleDurationUtilTest.java new file mode 100644 index 0000000..e73e186 --- /dev/null +++ b/eternalcode-commons-shared/test/com/eternalcode/commons/time/SimpleDurationUtilTest.java @@ -0,0 +1,89 @@ +package com.eternalcode.commons.time; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.time.Duration; +import org.junit.jupiter.api.Test; + +public class SimpleDurationUtilTest { + + @Test + public void testFormatWithoutMillis() { + Duration duration = Duration.ofMillis(500); + String result = SimpleDurationUtil.format(duration, true); + assertEquals("0s", result); + + duration = Duration.ofSeconds(30); + result = SimpleDurationUtil.format(duration, true); + assertEquals("30s", result); + + duration = Duration.ofMinutes(5); + result = SimpleDurationUtil.format(duration, true); + assertEquals("5m", result); + + duration = Duration.ofHours(2); + result = SimpleDurationUtil.format(duration, true); + assertEquals("2h", result); + + duration = Duration.ofDays(1); + result = SimpleDurationUtil.format(duration, true); + assertEquals("1d", result); + + duration = Duration.ofDays(14); + result = SimpleDurationUtil.format(duration, true); + assertEquals("2w", result); + + duration = Duration.ofDays(60); + result = SimpleDurationUtil.format(duration, true); + assertEquals("2mo", result); + + duration = Duration.ofDays(365 * 3); + result = SimpleDurationUtil.format(duration, true); + assertEquals("3y", result); + } + + @Test + public void testFormatWithMillis() { + Duration duration = Duration.ofMillis(500); + String result = SimpleDurationUtil.format(duration, false); + assertEquals("500ms", result); + + duration = Duration.ofSeconds(30); + result = SimpleDurationUtil.format(duration, false); + assertEquals("30s", result); + + duration = Duration.ofMinutes(5); + result = SimpleDurationUtil.format(duration, false); + assertEquals("5m", result); + + duration = Duration.ofHours(2); + result = SimpleDurationUtil.format(duration, false); + assertEquals("2h", result); + + duration = Duration.ofDays(1); + result = SimpleDurationUtil.format(duration, false); + assertEquals("1d", result); + + duration = Duration.ofDays(14); + result = SimpleDurationUtil.format(duration, false); + assertEquals("2w", result); + + duration = Duration.ofDays(60); + result = SimpleDurationUtil.format(duration, false); + assertEquals("2mo", result); + + duration = Duration.ofDays(365 * 3); + result = SimpleDurationUtil.format(duration, false); + assertEquals("3y", result); + } + + @Test + public void testFormatDefault() { + Duration duration = Duration.ofSeconds(610); + String result = SimpleDurationUtil.format(duration); + assertEquals("10m10s", result); + + duration = Duration.ofMillis(120); + result = SimpleDurationUtil.format(duration); + assertEquals("120ms", result); + } +} From 482047fd4832ed76b93c83f734e8df9af49811fc Mon Sep 17 00:00:00 2001 From: Piotr Zych <77621271+P1otrulla@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:52:50 +0200 Subject: [PATCH 3/5] Added missing String value --- .../java/com/eternalcode/commons/time/SimpleDurationUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java index 7f9f9c2..a982811 100644 --- a/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java +++ b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java @@ -31,7 +31,7 @@ public class SimpleDurationUtil { public static String format(Duration duration, boolean removeMillis) { if (removeMillis) { if (duration.toMillis() < ONE_SECOND.toMillis()) { - return "0s"; + return ZERO_SECONDS; } return WITHOUT_MILLIS_FORMAT.format(duration); From 2ec90a6638d012d923d9cdbc8ab224385ec75105 Mon Sep 17 00:00:00 2001 From: Piotr Zych <77621271+P1otrulla@users.noreply.github.com> Date: Tue, 26 Aug 2025 03:27:42 +0200 Subject: [PATCH 4/5] Add a simple progressBar --- .../commons/progressbar/ProgressBar.java | 152 ++++++++++++++++++ .../commons/progressbar/ProgressBarTest.java | 114 +++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java create mode 100644 eternalcode-commons-shared/test/com/eternalcode/commons/progressbar/ProgressBarTest.java diff --git a/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java new file mode 100644 index 0000000..ffebd5f --- /dev/null +++ b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java @@ -0,0 +1,152 @@ +package com.eternalcode.commons.progressbar; + +public class ProgressBar { + + private final String filledToken; + + private final String emptyToken; + + private final boolean showBrackets; + private final String leftBracket; + private final String rightBracket; + private final String bracketColor; + + private final int length; + + private ProgressBar(Builder builder) { + String filledChar = builder.filledChar; + String emptyChar = builder.emptyChar; + String filledColor = builder.filledColor; + String emptyColor = builder.emptyColor; + + this.leftBracket = builder.leftBracket; + this.rightBracket = builder.rightBracket; + this.bracketColor = builder.bracketColor; + this.length = builder.length; + this.showBrackets = builder.showBrackets; + + this.filledToken = filledColor + filledChar; + this.emptyToken = emptyColor + emptyChar; + } + + public String render(double progress) { + double clampedProgress = Math.max(0, Math.min(1, progress)); + int filled = (int) (this.length * clampedProgress); + + StringBuilder bar = new StringBuilder(); + + if (this.showBrackets) { + bar.append(this.bracketColor).append(this.leftBracket); + } + + for (int i = 0; i < this.length; i++) { + if (i < filled) { + bar.append(this.filledToken); + } + else { + bar.append(this.emptyToken); + } + } + + if (this.showBrackets) { + bar.append(this.bracketColor).append(this.rightBracket); + } + + return bar.toString(); + } + + public String render(int current, int max) { + if (max <= 0) { + return this.render(1.0); + } + double progress = (double) current / max; + return this.render(progress); + } + + public String render(long current, long max) { + if (max <= 0) { + return this.render(1.0); + } + double progress = (double) current / max; + return this.render(progress); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String filledChar = "█"; + private String emptyChar = "░"; + private String filledColor = ""; + private String emptyColor = ""; + private String leftBracket = "["; + private String rightBracket = "]"; + private String bracketColor = ""; + private int length = 10; + private boolean showBrackets = true; + + public Builder filledChar(String filledChar) { + this.filledChar = filledChar; + return this; + } + + public Builder emptyChar(String emptyChar) { + this.emptyChar = emptyChar; + return this; + } + + public Builder filledColor(String filledColor) { + this.filledColor = filledColor; + return this; + } + + public Builder emptyColor(String emptyColor) { + this.emptyColor = emptyColor; + return this; + } + + public Builder leftBracket(String leftBracket) { + this.leftBracket = leftBracket; + return this; + } + + public Builder rightBracket(String rightBracket) { + this.rightBracket = rightBracket; + return this; + } + + public Builder brackets(String left, String right) { + this.leftBracket = left; + this.rightBracket = right; + return this; + } + + public Builder bracketColor(String bracketColor) { + this.bracketColor = bracketColor; + return this; + } + + public Builder length(int length) { + if (length <= 0) { + throw new IllegalArgumentException("Length must be positive"); + } + this.length = length; + return this; + } + + public Builder showBrackets(boolean showBrackets) { + this.showBrackets = showBrackets; + return this; + } + + public Builder hideBrackets() { + this.showBrackets = false; + return this; + } + + public ProgressBar build() { + return new ProgressBar(this); + } + } +} diff --git a/eternalcode-commons-shared/test/com/eternalcode/commons/progressbar/ProgressBarTest.java b/eternalcode-commons-shared/test/com/eternalcode/commons/progressbar/ProgressBarTest.java new file mode 100644 index 0000000..3f509ed --- /dev/null +++ b/eternalcode-commons-shared/test/com/eternalcode/commons/progressbar/ProgressBarTest.java @@ -0,0 +1,114 @@ +package com.eternalcode.commons.progressbar; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ProgressBarTest { + + @Test + void testRenderFullProgress() { + ProgressBar bar = ProgressBar.builder() + .length(5) + .build(); + String rendered = bar.render(1.0); + + assertTrue(rendered.contains("█")); + assertFalse(rendered.contains("░")); + assertEquals(7, rendered.length()); + } + + @Test + void testRenderEmptyProgress() { + ProgressBar bar = ProgressBar.builder() + .length(5) + .build(); + String rendered = bar.render(0.0); + + assertTrue(rendered.contains("░")); + assertFalse(rendered.contains("█")); + assertEquals(7, rendered.length()); + } + + @Test + void testRenderHalfProgress() { + ProgressBar bar = ProgressBar.builder() + .length(4) + .build(); + String rendered = bar.render(0.5); + + assertTrue(rendered.contains("█")); + assertTrue(rendered.contains("░")); + assertEquals(6, rendered.length()); + } + + @Test + void testRenderIntOverMax() { + ProgressBar bar = ProgressBar.builder() + .length(3) + .build(); + String rendered = bar.render(5, 3); + + assertEquals("[███]", rendered); + } + + @Test + void testRenderIntWithZeroMax() { + ProgressBar bar = ProgressBar.builder() + .length(3) + .build(); + String rendered = bar.render(0, 0); + + assertEquals("[███]", rendered); + } + + @Test + void testHideBrackets() { + ProgressBar bar = ProgressBar.builder() + .length(3) + .hideBrackets() + .build(); + String rendered = bar.render(1.0); + + assertEquals("███", rendered); + } + + @Test + void testCustomCharacters() { + ProgressBar bar = ProgressBar.builder() + .length(4) + .filledChar("#") + .emptyChar("-") + .brackets("{", "}") + .build(); + + String rendered = bar.render(0.5); + assertEquals("{##--}", rendered); + } + + @Test + void testNegativeProgressClampedToZero() { + ProgressBar bar = ProgressBar.builder() + .length(3) + .build(); + String rendered = bar.render(-1.0); + + assertEquals("[░░░]", rendered); + } + + @Test + void testProgressGreaterThanOneClampedToOne() { + ProgressBar bar = ProgressBar.builder() + .length(3) + .build(); + String rendered = bar.render(2.0); + + assertEquals("[███]", rendered); + } + + @Test + void testInvalidLengthThrowsException() { + assertThrows(IllegalArgumentException.class, () -> ProgressBar.builder().length(0)); + assertThrows(IllegalArgumentException.class, () -> ProgressBar.builder().length(-5)); + } +} From 28a9bf0f26b2754b90e69600e5e30aa2f1342b48 Mon Sep 17 00:00:00 2001 From: Piotr Zych <77621271+P1otrulla@users.noreply.github.com> Date: Tue, 26 Aug 2025 03:31:03 +0200 Subject: [PATCH 5/5] Update eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../com/eternalcode/commons/progressbar/ProgressBar.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java index ffebd5f..324af49 100644 --- a/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java +++ b/eternalcode-commons-shared/src/main/java/com/eternalcode/commons/progressbar/ProgressBar.java @@ -14,19 +14,14 @@ public class ProgressBar { private final int length; private ProgressBar(Builder builder) { - String filledChar = builder.filledChar; - String emptyChar = builder.emptyChar; - String filledColor = builder.filledColor; - String emptyColor = builder.emptyColor; - this.leftBracket = builder.leftBracket; this.rightBracket = builder.rightBracket; this.bracketColor = builder.bracketColor; this.length = builder.length; this.showBrackets = builder.showBrackets; - this.filledToken = filledColor + filledChar; - this.emptyToken = emptyColor + emptyChar; + this.filledToken = builder.filledColor + builder.filledChar; + this.emptyToken = builder.emptyColor + builder.emptyChar; } public String render(double progress) {