From a4eb2566c73bbb0a6c267106042e127ad55393b8 Mon Sep 17 00:00:00 2001 From: ShayanEdalatjoo Date: Fri, 17 Jul 2026 23:17:31 +0330 Subject: [PATCH] Adding progress bar download speed and ETA from Bonus --- src/main/java/.idea/.gitignore | 10 +++++ src/main/java/.idea/misc.xml | 6 +++ src/main/java/.idea/modules.xml | 8 ++++ src/main/java/.idea/vcs.xml | 6 +++ src/main/java/DownloadWorker.java | 3 -- src/main/java/ProgressMonitor.java | 64 ++++++++++++++++++++---------- 6 files changed, 74 insertions(+), 23 deletions(-) create mode 100644 src/main/java/.idea/.gitignore create mode 100644 src/main/java/.idea/misc.xml create mode 100644 src/main/java/.idea/modules.xml create mode 100644 src/main/java/.idea/vcs.xml diff --git a/src/main/java/.idea/.gitignore b/src/main/java/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/src/main/java/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/src/main/java/.idea/misc.xml b/src/main/java/.idea/misc.xml new file mode 100644 index 0000000..a20905f --- /dev/null +++ b/src/main/java/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/.idea/modules.xml b/src/main/java/.idea/modules.xml new file mode 100644 index 0000000..122a905 --- /dev/null +++ b/src/main/java/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/java/.idea/vcs.xml b/src/main/java/.idea/vcs.xml new file mode 100644 index 0000000..c2365ab --- /dev/null +++ b/src/main/java/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/DownloadWorker.java b/src/main/java/DownloadWorker.java index aab6865..ccd6620 100644 --- a/src/main/java/DownloadWorker.java +++ b/src/main/java/DownloadWorker.java @@ -24,8 +24,6 @@ public class DownloadWorker implements Runnable { chunkStatus.setStartTimeMs(System.currentTimeMillis()); double downloaded = 0.0; - System.out.println("Chunk " + chunkStatus.getChunkId() + " started downloading."); - while (downloaded < chunkStatus.getChunkSizeMB()) { try { int delay = config.getMinStepDelayMs() @@ -50,7 +48,6 @@ public class DownloadWorker implements Runnable { } chunkStatus.setCompleted(true); chunkStatus.setEndTimeMs(System.currentTimeMillis()); - System.out.println("[Worker-" + chunkStatus.getChunkId() + "] Download completed."); } } diff --git a/src/main/java/ProgressMonitor.java b/src/main/java/ProgressMonitor.java index 4a50402..7cf598d 100644 --- a/src/main/java/ProgressMonitor.java +++ b/src/main/java/ProgressMonitor.java @@ -16,16 +16,7 @@ public class ProgressMonitor implements Runnable { @Override public void run() { - // TODO: - // Repeatedly check chunk progress until all chunks are completed. - // In each loop: - // 1. Read the downloaded size from every chunk - // 2. Add all downloaded amounts to totalDownloadedMB - // 3. Count completed chunks - // 4. Print a progress message - // 5. If completedChunks == chunks.size(), print a final monitor message and stop - // 6. Otherwise sleep for monitorDelayMs and continue - + long startTimeMs = System.currentTimeMillis(); while (true) { double totalDownloadedMB = 0.0; @@ -33,29 +24,49 @@ public class ProgressMonitor implements Runnable { for (ChunkStatus chunk : chunks) { totalDownloadedMB += chunk.getDownloadedMB(); - if (chunk.isCompleted()) { completedChunks++; } } - double percent = 0.0; - if (totalSizeMB > 0) { - percent = (totalDownloadedMB * 100.0) / totalSizeMB; - } + long elapsedMs = System.currentTimeMillis() - startTimeMs; + double elapsedSeconds = elapsedMs / 1000.0; + + double speedMBps = elapsedSeconds > 0.0 + ? totalDownloadedMB / elapsedSeconds + : 0.0; + + double percent = totalSizeMB > 0 + ? totalDownloadedMB * 100.0 / totalSizeMB + : 100.0; + percent = Math.max(0.0, Math.min(100.0, percent)); + + double remainingMB = Math.max(0.0, totalSizeMB - totalDownloadedMB); + long etaSeconds = speedMBps > 0.0 + ? (long) Math.ceil(remainingMB / speedMBps) + : 0L; + + int barWidth = 40; + int filled = (int) Math.round(percent / 100.0 * barWidth); + filled = Math.max(0, Math.min(barWidth, filled)); + + String bar = "#".repeat(filled) + "-".repeat(barWidth - filled); System.out.printf( - "Progress for %s: %.1f/%.1f MB (%.2f%%), completed chunks: %d/%d%n", - fileName, - totalDownloadedMB, - (double) totalSizeMB, + "\r[%s] %6.2f%% %7.1f/%d MB | %6.2f MB/s | ETA %s | chunks %d/%d", + bar, percent, + totalDownloadedMB, + totalSizeMB, + speedMBps, + formatEta(etaSeconds), completedChunks, chunks.size() ); - + System.out.flush(); if (completedChunks == chunks.size()) { + System.out.println(); System.out.println("All chunks completed."); break; } @@ -63,9 +74,22 @@ public class ProgressMonitor implements Runnable { try { Thread.sleep(monitorDelayMs); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println(); System.out.println("Progress monitor interrupted."); return; } } } + + private String formatEta(long totalSeconds) { + long minutes = totalSeconds / 60; + long seconds = totalSeconds % 60; + + if (minutes > 0) { + return String.format("%dm %02ds", minutes, seconds); + } + + return String.format("%ds", seconds); + } }