Skip to content

Commit 31038d7

Browse files
GH-58 Add a simple progressBar (#58)
* Add a simple progressBar * 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> * Update eternalcode-commons-shared/test/com/eternalcode/commons/progressbar/ProgressBarTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update eternalcode-commons-shared/test/com/eternalcode/commons/progressbar/ProgressBarTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update eternalcode-commons-shared/test/com/eternalcode/commons/progressbar/ProgressBarTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * follow gemini's suggestion --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 08c2e13 commit 31038d7

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package com.eternalcode.commons.progressbar;
2+
3+
public class ProgressBar {
4+
5+
private final String filledToken;
6+
7+
private final String emptyToken;
8+
9+
private final boolean showBrackets;
10+
private final String leftBracket;
11+
private final String rightBracket;
12+
private final String bracketColor;
13+
14+
private final int length;
15+
16+
private ProgressBar(Builder builder) {
17+
this.leftBracket = builder.leftBracket;
18+
this.rightBracket = builder.rightBracket;
19+
this.bracketColor = builder.bracketColor;
20+
this.length = builder.length;
21+
this.showBrackets = builder.showBrackets;
22+
23+
this.filledToken = builder.filledColor + builder.filledChar;
24+
this.emptyToken = builder.emptyColor + builder.emptyChar;
25+
}
26+
27+
public String render(double progress) {
28+
double clampedProgress = Math.max(0, Math.min(1, progress));
29+
int filled = (int) (this.length * clampedProgress);
30+
31+
StringBuilder bar = new StringBuilder();
32+
33+
if (this.showBrackets) {
34+
bar.append(this.bracketColor).append(this.leftBracket);
35+
}
36+
37+
bar.append(this.filledToken.repeat(filled));
38+
bar.append(this.emptyToken.repeat(this.length - filled));
39+
40+
if (this.showBrackets) {
41+
bar.append(this.bracketColor).append(this.rightBracket);
42+
}
43+
44+
return bar.toString();
45+
}
46+
47+
public String render(int current, int max) {
48+
return this.render(current, (long) max);
49+
}
50+
51+
public String render(long current, long max) {
52+
if (max <= 0) {
53+
return this.render(1.0);
54+
}
55+
double progress = (double) current / max;
56+
return this.render(progress);
57+
}
58+
59+
public static Builder builder() {
60+
return new Builder();
61+
}
62+
63+
public static class Builder {
64+
private String filledChar = "█";
65+
private String emptyChar = "░";
66+
private String filledColor = "";
67+
private String emptyColor = "";
68+
private String leftBracket = "[";
69+
private String rightBracket = "]";
70+
private String bracketColor = "";
71+
private int length = 10;
72+
private boolean showBrackets = true;
73+
74+
public Builder filledChar(String filledChar) {
75+
this.filledChar = filledChar;
76+
return this;
77+
}
78+
79+
public Builder emptyChar(String emptyChar) {
80+
this.emptyChar = emptyChar;
81+
return this;
82+
}
83+
84+
public Builder filledColor(String filledColor) {
85+
this.filledColor = filledColor;
86+
return this;
87+
}
88+
89+
public Builder emptyColor(String emptyColor) {
90+
this.emptyColor = emptyColor;
91+
return this;
92+
}
93+
94+
public Builder leftBracket(String leftBracket) {
95+
this.leftBracket = leftBracket;
96+
return this;
97+
}
98+
99+
public Builder rightBracket(String rightBracket) {
100+
this.rightBracket = rightBracket;
101+
return this;
102+
}
103+
104+
public Builder brackets(String left, String right) {
105+
this.leftBracket = left;
106+
this.rightBracket = right;
107+
return this;
108+
}
109+
110+
public Builder bracketColor(String bracketColor) {
111+
this.bracketColor = bracketColor;
112+
return this;
113+
}
114+
115+
public Builder length(int length) {
116+
if (length <= 0) {
117+
throw new IllegalArgumentException("Length must be positive");
118+
}
119+
this.length = length;
120+
return this;
121+
}
122+
123+
public Builder showBrackets(boolean showBrackets) {
124+
this.showBrackets = showBrackets;
125+
return this;
126+
}
127+
128+
public Builder hideBrackets() {
129+
this.showBrackets = false;
130+
return this;
131+
}
132+
133+
public ProgressBar build() {
134+
return new ProgressBar(this);
135+
}
136+
}
137+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package com.eternalcode.commons.progressbar;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.*;
6+
7+
class ProgressBarTest {
8+
9+
@Test
10+
void testRenderFullProgress() {
11+
ProgressBar bar = ProgressBar.builder()
12+
.length(5)
13+
.build();
14+
String rendered = bar.render(1.0);
15+
16+
assertEquals("[█████]", rendered);
17+
}
18+
19+
@Test
20+
void testRenderEmptyProgress() {
21+
ProgressBar bar = ProgressBar.builder()
22+
.length(5)
23+
.build();
24+
String rendered = bar.render(0.0);
25+
26+
assertEquals("[░░░░░]", rendered);
27+
}
28+
29+
@Test
30+
void testRenderHalfProgress() {
31+
ProgressBar bar = ProgressBar.builder()
32+
.length(4)
33+
.build();
34+
String rendered = bar.render(0.5);
35+
36+
assertEquals("[██░░]", rendered);
37+
}
38+
39+
@Test
40+
void testRenderIntOverMax() {
41+
ProgressBar bar = ProgressBar.builder()
42+
.length(3)
43+
.build();
44+
String rendered = bar.render(5, 3);
45+
46+
assertEquals("[███]", rendered);
47+
}
48+
49+
@Test
50+
void testRenderIntWithZeroMax() {
51+
ProgressBar bar = ProgressBar.builder()
52+
.length(3)
53+
.build();
54+
String rendered = bar.render(0, 0);
55+
56+
assertEquals("[███]", rendered);
57+
}
58+
59+
@Test
60+
void testHideBrackets() {
61+
ProgressBar bar = ProgressBar.builder()
62+
.length(3)
63+
.hideBrackets()
64+
.build();
65+
String rendered = bar.render(1.0);
66+
67+
assertEquals("███", rendered);
68+
}
69+
70+
@Test
71+
void testCustomCharacters() {
72+
ProgressBar bar = ProgressBar.builder()
73+
.length(4)
74+
.filledChar("#")
75+
.emptyChar("-")
76+
.brackets("{", "}")
77+
.build();
78+
79+
String rendered = bar.render(0.5);
80+
assertEquals("{##--}", rendered);
81+
}
82+
83+
@Test
84+
void testNegativeProgressClampedToZero() {
85+
ProgressBar bar = ProgressBar.builder()
86+
.length(3)
87+
.build();
88+
String rendered = bar.render(-1.0);
89+
90+
assertEquals("[░░░]", rendered);
91+
}
92+
93+
@Test
94+
void testProgressGreaterThanOneClampedToOne() {
95+
ProgressBar bar = ProgressBar.builder()
96+
.length(3)
97+
.build();
98+
String rendered = bar.render(2.0);
99+
100+
assertEquals("[███]", rendered);
101+
}
102+
103+
@Test
104+
void testInvalidLengthThrowsException() {
105+
assertThrows(IllegalArgumentException.class, () -> ProgressBar.builder().length(0));
106+
assertThrows(IllegalArgumentException.class, () -> ProgressBar.builder().length(-5));
107+
}
108+
}

0 commit comments

Comments
 (0)