Skip to content

Commit 064e68d

Browse files
committed
2 parents 0c23426 + 8898a16 commit 064e68d

File tree

19 files changed

+805
-64
lines changed

19 files changed

+805
-64
lines changed

.github/checkstyle.xml

Lines changed: 335 additions & 0 deletions
Large diffs are not rendered by default.

.github/workflows/gradle-check.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Gradle Checkstyle CI
2+
3+
on: [push]
4+
5+
permissions:
6+
checks: write
7+
actions: read
8+
contents: read
9+
10+
jobs:
11+
build:
12+
name: Gradle Test
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v3
16+
17+
- name: Set up Java JDK
18+
uses: actions/setup-java@v3
19+
with:
20+
java-version: '19'
21+
distribution: 'adopt'
22+
23+
- name: Gradle Wrapper Validation
24+
uses: gradle/wrapper-validation-action@v1
25+
26+
- name: Setup Gradle with Dependency Cache
27+
uses: gradle/[email protected]
28+
29+
- name: Gradle Checkstyle
30+
run: ./gradlew check

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@ Final Project for CSC207
99
* [Repo in CSC207 Organization](https://github.com/CSC207-2022F-UofT/mcpm)
1010
* [File Server Backend](https://mcpm.hydev.org)
1111

12+
## Development
13+
14+
### Run a specific class in an external terminal
15+
16+
This is very useful to test terminal operations since the Gradle running environment isn't a tty, and IntelliJ IDEA's built-in terminal barely supports Xterm escape sequences.
17+
18+
For this, I've set up a custom gradle task `printCp` that will print out the classpath needed to run the classes with dependencies. It will print in stderr instead of stdout in order for bash to easily separate out the classpath. You can obtain the classpath in a bash variable by:
19+
20+
`cp="$(./gradlew classes testClasses printCp 2>&1 > /dev/null)" && echo "$cp"`
21+
22+
(Unfortunately since Windows doesn't support Bash, you'll need to use a Bash-compatible environment on Windows, either cygwin / git bash or WSL)
23+
24+
Then, you can run your class with:
25+
26+
`java19 -cp "$cp" org.hydev.mcpm.<class>`
27+
28+
For example, you can test the progress bar with:
29+
30+
`java19 -cp "$cp" org.hydev.mcpm.client.interaction.ProgressBar`
31+
32+
If you don't have JDK 19 installed or if you don't know where it's installed, you can use our JDK downloader tool to download a local version of JDK 19 without installing on the system. (TODO: Add tutorial after merging PR #8)
33+
1234
## Brainstorm
1335

1436
Server file/endpoint structure:

backups/kotlin/CreateTeam.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,20 @@ import java.util.*
99
import kotlin.text.Charsets.UTF_8
1010
import io.ktor.client.*
1111
import io.ktor.client.engine.cio.*
12+
import io.ktor.client.plugins.*
1213
import io.ktor.client.request.*
1314

1415

1516
val GSON = Gson()
1617
val HTTP = OkHttpClient()
17-
val KTOR = HttpClient(CIO)
18+
val KTOR = HttpClient(CIO) {
19+
install(HttpTimeout) {
20+
requestTimeoutMillis = 5000
21+
}
22+
install(HttpRequestRetry) {
23+
retryOnServerErrors(maxRetries = 5)
24+
}
25+
}
1826

1927
/**
2028
* fromJson patch for Kotlin

build.gradle

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
id 'java'
33
id 'maven-publish'
4+
id 'checkstyle'
45
}
56

67
group 'org.hydev.csc207'
@@ -16,6 +17,15 @@ java {
1617
}
1718
}
1819

20+
checkstyle {
21+
// assign the latest checkstyle version explicitly, since the default version is very old
22+
toolVersion = '10.3.4'
23+
configFile = rootProject.file('.github/checkstyle.xml')
24+
25+
ignoreFailures = false
26+
maxWarnings = 5
27+
}
28+
1929

2030
dependencies {
2131
// Apache HTTP Client
@@ -40,6 +50,9 @@ dependencies {
4050
// https://mvnrepository.com/artifact/org.jetbrains/annotations
4151
implementation 'org.jetbrains:annotations:16.0.1'
4252

53+
// https://mvnrepository.com/artifact/org.fusesource.jansi/jansi
54+
implementation 'org.fusesource.jansi:jansi:2.4.0'
55+
4356
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
4457
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
4558
}
@@ -72,6 +85,13 @@ if (hasProperty('buildScan')) {
7285
}
7386
}
7487

88+
task printCp {
89+
doLast {
90+
System.err.println sourceSets.main.runtimeClasspath.asPath
91+
}
92+
}
93+
7594
test {
7695
useJUnitPlatform()
96+
testLogging.showStandardStreams = true
7797
}

src/main/java/org/hydev/mcpm/client/Downloader.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.hydev.mcpm.client;
22

33
import java.io.File;
4-
import java.util.List;
54
import java.util.Map;
65

76
/**

src/main/java/org/hydev/mcpm/client/database/LocalPluginTracker.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.hydev.mcpm.client.database;
22

3-
import org.hydev.mcpm.client.models.Plugin;
43
import org.hydev.mcpm.client.models.PluginVersion;
54

65
import java.io.File;
Lines changed: 111 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
package org.hydev.mcpm.client.interaction;
22

3+
import org.fusesource.jansi.AnsiConsole;
4+
import org.hydev.mcpm.utils.ConsoleUtils;
5+
6+
import java.io.PrintStream;
7+
import java.util.*;
8+
9+
import static java.lang.String.format;
10+
import static org.fusesource.jansi.internal.CLibrary.STDOUT_FILENO;
11+
import static org.fusesource.jansi.internal.CLibrary.isatty;
12+
import static org.hydev.mcpm.utils.GeneralUtils.safeSleep;
13+
314
/**
4-
* TODO: Write a description for this class!
15+
* Terminal progress bar based on Xterm escape codes
516
*
617
* @author Azalea (https://github.com/hykilpikonna)
718
* @since 2022-09-27
819
*/
920
public class ProgressBar implements AutoCloseable
1021
{
22+
private final ConsoleUtils cu;
1123
private final ProgressBarTheme theme;
24+
private final PrintStream out;
25+
private int cols;
26+
27+
private final List<ProgressRow> activeBars;
28+
29+
private long lastUpdate;
30+
31+
private double frameDelay;
32+
33+
private final boolean istty;
1234

1335
/**
1436
* Create and initialize a progress bar
@@ -18,61 +40,118 @@ public class ProgressBar implements AutoCloseable
1840
public ProgressBar(ProgressBarTheme theme)
1941
{
2042
this.theme = theme;
21-
this.init();
22-
}
43+
this.out = System.out;
44+
this.cu = new ConsoleUtils(this.out);
45+
this.activeBars = new ArrayList<>();
46+
this.cols = AnsiConsole.getTerminalWidth();
2347

24-
/**
25-
* Initialize the progress bar (print the first line)
26-
*/
27-
public void init()
28-
{
29-
// TODO: Implement this
30-
throw new UnsupportedOperationException("TODO");
48+
// Default to 70-char width if the width can't be detected (like in a non-tty output)
49+
if (this.cols == 0) this.cols = 70;
50+
51+
// Last update time
52+
this.lastUpdate = System.nanoTime();
53+
54+
// Default frame delay is 0.01666 (60 fps)
55+
this.frameDelay = 1 / 60d;
56+
57+
// Check if output is a TTY. If not, change frame rate to 0.5 fps to avoid spamming a log.
58+
this.istty = isatty(STDOUT_FILENO) == 0;
59+
if (istty) this.frameDelay = 1 / 0.5;
3160
}
3261

3362
/**
3463
* Append a progress bar at the end
3564
*
36-
* @return Unique identifier of the progress bar
65+
* @param bar Row of the progress bar
66+
* @return bar for fluent access
3767
*/
38-
public String appendBar()
68+
public ProgressRow appendBar(ProgressRow bar)
3969
{
40-
// TODO: Implement this
41-
throw new UnsupportedOperationException("TODO");
70+
this.activeBars.add(bar);
71+
bar.setPb(this);
72+
73+
out.println();
74+
update();
75+
return bar;
4276
}
4377

44-
/**
45-
* Set progress for a bar
46-
*
47-
* @param id Unique identifier
48-
* @param progress Progress as a ratio in range 0-1
49-
*/
50-
public void setBar(String id, float progress)
78+
protected void update()
79+
{
80+
// Check time to limit for framerate (default 60fps)
81+
// Performance of the update heavily depends on the terminal's escape code handling
82+
// implementation, so frequent updates will degrade performance on a bad terminal
83+
var curTime = System.nanoTime();
84+
if ((curTime - lastUpdate) / 1e9d < frameDelay) return;
85+
lastUpdate = curTime;
86+
87+
forceUpdate();
88+
}
89+
90+
private void forceUpdate()
5191
{
52-
// TODO: Implement this
53-
throw new UnsupportedOperationException("TODO");
92+
// Roll back to the first line
93+
if (istty) cu.curUp(activeBars.size());
94+
activeBars.forEach(bar -> out.println(bar.toString(theme, cols)));
5495
}
5596

5697
/**
5798
* Finish a progress bar
5899
*
59-
* @param id Unique identifier of the progress bar
100+
* @param bar Progress bar
60101
*/
61-
public void finishBar(String id)
102+
public void finishBar(ProgressRow bar)
62103
{
63-
// TODO: Implement this
64-
throw new UnsupportedOperationException("TODO");
104+
if (!activeBars.contains(bar)) return;
105+
106+
forceUpdate();
107+
this.activeBars.remove(bar);
65108
}
66109

67110
/**
68111
* Finalize and close the progress bar (print the final line)
69-
*
70-
* @throws Exception e
71112
*/
72113
@Override
73-
public void close() throws Exception
114+
public void close()
115+
{
116+
}
117+
118+
public ProgressBar setFrameDelay(double frameDelay)
119+
{
120+
this.frameDelay = frameDelay;
121+
return this;
122+
}
123+
124+
/**
125+
* Set frame rate in the unit of frames per second
126+
*
127+
* @param fps FPS
128+
* @return Self for fluent access
129+
*/
130+
public ProgressBar setFps(int fps)
131+
{
132+
this.frameDelay = 1d / fps;
133+
return this;
134+
}
135+
136+
public List<ProgressRow> getActiveBars()
74137
{
75-
// TODO: Implement this
76-
throw new UnsupportedOperationException("TODO");
138+
return activeBars;
139+
}
140+
141+
public static void main(String[] args)
142+
{
143+
try (var b = new ProgressBar(ProgressBarTheme.ASCII_THEME))
144+
{
145+
var all = new ArrayList<ProgressRow>();
146+
for (int i = 0; i < 1300; i++)
147+
{
148+
if (i < 1000 && i % 100 == 0)
149+
all.add(b.appendBar(new ProgressRow(300).unit("MB").desc(format("File %s.tar.gz", all.size()))).descLen(30));
150+
all.forEach(a -> a.increase(1));
151+
safeSleep(3);
152+
}
153+
154+
System.out.println("Done");
155+
}
77156
}
78157
}

src/main/java/org/hydev/mcpm/client/interaction/ProgressBarTheme.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
* @since 2022-09-27
1313
*/
1414
public record ProgressBarTheme(
15-
String ipr,
1615
String done,
17-
int iprLen,
18-
int doneLen
16+
String ipr,
17+
String prefix,
18+
String suffix,
19+
int doneLen,
20+
int iprLen
1921
)
2022
{
21-
public static final ProgressBarTheme ASCII_THEME = new ProgressBarTheme("#", "-", 1, 1);
22-
public static final ProgressBarTheme CLASSIC_THEME = new ProgressBarTheme("█", ".", 1, 1);
23-
public static final ProgressBarTheme EMOJI_THEME = new ProgressBarTheme("✅", "🕑", 2, 2);
24-
public static final ProgressBarTheme FLOWER_THEME = new ProgressBarTheme("🌸", "🥀", 2, 2);
23+
public static final ProgressBarTheme ASCII_THEME = new ProgressBarTheme("#", "-", "[", "]", 1, 1);
24+
public static final ProgressBarTheme CLASSIC_THEME = new ProgressBarTheme("█", ".", "", "", 1, 1);
25+
public static final ProgressBarTheme EMOJI_THEME = new ProgressBarTheme("✅", "🕑", "", "", 2, 2);
26+
public static final ProgressBarTheme FLOWER_THEME = new ProgressBarTheme("🌸", "🥀", "", "", 2, 2);
2527
}

0 commit comments

Comments
 (0)