Compare commits

...

3 Commits

Author SHA1 Message Date
71daaaff15 Fix thread-safety
properly do time based logging and quit, when done
2025-01-20 14:50:47 +01:00
6e1fb749ad Made calculations more precise 2025-01-20 14:29:26 +01:00
4ed86f7420 - ProgressHandler Threadsafe gemacht
- ermögliche loggen ohne progress, rein Zeitbasiert
  -> möglichst, sodass kein spam entsteht bzw. das reguläre Loggen berücksichtigt wird
2025-01-14 11:39:58 +01:00
2 changed files with 74 additions and 24 deletions

View File

@ -1,6 +1,8 @@
package de.vorsorge.theo.util;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.MathContext;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -8,6 +10,7 @@ import java.text.DecimalFormat;
import java.time.Duration; import java.time.Duration;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;
public class FabianUtil { public class FabianUtil {
@ -65,54 +68,69 @@ public class FabianUtil {
} }
protected BigDecimal getCounter() { protected synchronized BigDecimal getCounter() {
return counter; return counter;
} }
public void tickAndLog() { protected synchronized int getTimeLogDistance() {
return timeLogDistance;
}
public synchronized void tickAndLog() {
tick(); tick();
logIf(); logIf();
} }
protected void tick() { protected synchronized void tick() {
counter = counter.add(BigDecimal.ONE); counter = counter.add(BigDecimal.ONE);
} }
public void logAndTick() { public synchronized void logAndTick() {
logIf(); logIf();
tick(); tick();
} }
public void logIf() { public synchronized void logIf() {
if (counter.remainder(logDistance).signum() == 0 || isBored()) { if (shouldLog()) {
log(); log();
} }
} }
private boolean isBored() { protected synchronized boolean shouldLog() {
ZonedDateTime time = lastLoggedAt == null ? startTime : lastLoggedAt; return counter.remainder(logDistance).signum() == 0 || isBored();
return time.until(ZonedDateTime.now(), ChronoUnit.SECONDS) >= timeLogDistance;
} }
public void log() { private synchronized boolean isBored() {
return getTimeSinceLastLogged() >= timeLogDistance;
}
protected synchronized long getTimeSinceLastLogged() {
ZonedDateTime time = lastLoggedAt == null ? startTime : lastLoggedAt;
return time.until(ZonedDateTime.now(), ChronoUnit.SECONDS);
}
public synchronized void log() {
Duration timePassed = getTimePassed(); Duration timePassed = getTimePassed();
System.out.println(counter + " Stück erledigt. " + formatDuration(timePassed) + " vergangen."); System.out.println(counter + " Stück erledigt. " + formatDuration(timePassed) + " vergangen.");
updateLastLoggedAt(); updateLastLoggedAt();
} }
protected void updateLastLoggedAt() { protected synchronized void updateLastLoggedAt() {
lastLoggedAt = ZonedDateTime.now(); lastLoggedAt = ZonedDateTime.now();
} }
protected Duration getTimePassed() { protected synchronized Duration getTimePassed() {
return Duration.ofSeconds(startTime.until(ZonedDateTime.now(), ChronoUnit.SECONDS)); return Duration.ofSeconds(startTime.until(ZonedDateTime.now(), ChronoUnit.SECONDS));
} }
@ -127,7 +145,7 @@ public class FabianUtil {
} }
public void logFinal() { public synchronized void logFinal() {
Duration timePassed = getTimePassed(); Duration timePassed = getTimePassed();
System.out.println(counter + " Stück (100 %) erledigt. " + formatDuration(timePassed) + " vergangen."); System.out.println(counter + " Stück (100 %) erledigt. " + formatDuration(timePassed) + " vergangen.");
} }
@ -158,16 +176,21 @@ public class FabianUtil {
@Override @Override
public void log() { protected synchronized boolean shouldLog() {
BigDecimal counter = getCounter(); return super.shouldLog() && getCounter().compareTo(total) <= 0;
BigDecimal percentage = BigDecimal.valueOf(100).divide(total, 15, RoundingMode.HALF_UP).multiply(counter); }
@Override
public synchronized void log() {
BigDecimal counter = getCounter();
BigDecimal percentage = BigDecimal.valueOf(100).divide(total, MathContext.DECIMAL64).multiply(counter);
Duration timePassed = getTimePassed(); Duration timePassed = getTimePassed();
String remainingTimePart = ""; String remainingTimePart = "";
if (counter.signum() != 0) { if (counter.signum() != 0) {
BigDecimal secondsPassed = BigDecimal.valueOf(timePassed.getSeconds()); BigDecimal secondsPassed = BigDecimal.valueOf(timePassed.getSeconds());
BigDecimal totalSeconds = secondsPassed.divide(counter, 15, RoundingMode.HALF_UP).multiply(total); BigDecimal totalSeconds = secondsPassed.divide(counter, MathContext.DECIMAL64).multiply(total);
BigDecimal secondsToGo = totalSeconds.subtract(secondsPassed); BigDecimal secondsToGo = totalSeconds.subtract(secondsPassed);
Duration timeToGo = Duration.of(secondsToGo.longValue(), ChronoUnit.SECONDS); Duration timeToGo = Duration.of(secondsToGo.longValue(), ChronoUnit.SECONDS);
remainingTimePart = ", " + formatDuration(timeToGo) + " verbleibend"; remainingTimePart = ", " + formatDuration(timeToGo) + " verbleibend";
@ -178,6 +201,25 @@ public class FabianUtil {
+ formatDuration(timePassed) + " vergangen" + remainingTimePart + "."); + formatDuration(timePassed) + " vergangen" + remainingTimePart + ".");
updateLastLoggedAt(); updateLastLoggedAt();
} }
public void logContinuouslyTimeBased() {
new Thread(this::logTimeBased).start();
}
private synchronized void logTimeBased() {
while (getCounter().compareTo(total) != 0) {
logIf();
long timeSinceLastLogged = getTimeSinceLastLogged();
try {
TimeUnit.SECONDS.sleep(timeSinceLastLogged - getTimeLogDistance());
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
return;
}
}
}
} }

View File

@ -1,3 +1,5 @@
import java.math.BigDecimal;
import java.math.MathContext;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -19,11 +21,12 @@ public class LoadingBar {
private static final DecimalFormat PERCENTAGE_FORMAT = new DecimalFormat("00.00"); private static final DecimalFormat PERCENTAGE_FORMAT = new DecimalFormat("00.00");
private static final int MIN_LUNCH_DURATION = 30; private static final int MIN_LUNCH_DURATION = 30;
private static final LocalTime LATEST_LUNCH_TIME = LocalTime.of(13, 30); private static final LocalTime LATEST_LUNCH_TIME = LocalTime.of(13, 30);
private static final long DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH = 5L * 60;
private static final int MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH = 6 * 60;
private static final long MAX_NUMBER_WORK_MINS = 8L * 60;
private static final int MINS_PER_HOUR = 60; private static final int MINS_PER_HOUR = 60;
private static final long DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH = 5L * MINS_PER_HOUR;
private static final int MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH = 6 * MINS_PER_HOUR;
private static final long MAX_NUMBER_WORK_MINS = 8L * MINS_PER_HOUR;
private static final int LINE_LENGTH = 100; private static final int LINE_LENGTH = 100;
private static final MathContext MC_INTEGER = new MathContext(1, RoundingMode.HALF_EVEN);
private enum DaySection { private enum DaySection {
@ -333,9 +336,11 @@ public class LoadingBar {
private static String fillLoadingBar(long initialMinutes, long passedMinutes, boolean progressive) { private static String fillLoadingBar(long initialMinutes, long passedMinutes, boolean progressive) {
double wholePercentage = ((double) passedMinutes / initialMinutes) * 100; BigDecimal wholePercentage = BigDecimal.valueOf(100)
.divide(BigDecimal.valueOf(initialMinutes), MathContext.DECIMAL64)
.multiply(BigDecimal.valueOf(passedMinutes));
long remainingMinutes = initialMinutes - passedMinutes; long remainingMinutes = initialMinutes - passedMinutes;
int numberOfEquals = (int) wholePercentage; int numberOfEquals = wholePercentage.intValue();
var sb = new StringBuilder("["); var sb = new StringBuilder("[");
for (int i = 0; i < LINE_LENGTH; i++) { for (int i = 0; i < LINE_LENGTH; i++) {
if (i < numberOfEquals) { if (i < numberOfEquals) {
@ -354,6 +359,9 @@ public class LoadingBar {
private static String minutesToTimeString(long minutes) { private static String minutesToTimeString(long minutes) {
return LocalTime.of((int) minutes / MINS_PER_HOUR, (int) minutes % MINS_PER_HOUR).format(TIME_FORMATTER); var minutesBD = BigDecimal.valueOf(minutes);
int hours = minutesBD.divide(BigDecimal.valueOf(MINS_PER_HOUR), MC_INTEGER).intValue();
int rest_minutes = minutesBD.remainder(BigDecimal.valueOf(MINS_PER_HOUR), MC_INTEGER).intValue();
return LocalTime.of(hours, rest_minutes).format(TIME_FORMATTER);
} }
} }