From 74f2acda17aad7c3398d9ff53bd42e8b8cb111e1 Mon Sep 17 00:00:00 2001 From: fabianArbeit Date: Mon, 18 Aug 2025 11:38:32 +0200 Subject: [PATCH] - moved files into new project-specific subpackage - adjusted package declarations and imports --- .../{ => zeitlaeufer}/AbstractLoadingBar.java | 340 +++++------ .../AbstractProgressBar.java | 100 ++-- .../{ => zeitlaeufer}/DrinkingBar.java | 192 +++--- .../szimnau/{ => zeitlaeufer}/LoadingBar.java | 278 ++++----- .../{ => zeitlaeufer}/SimpleLoadingBar.java | 204 +++---- .../{ => zeitlaeufer}/WorkLoadingBar.java | 88 +-- .../{ => zeitlaeufer}/tools/CommonTools.java | 52 +- .../{ => zeitlaeufer}/tools/FormatTools.java | 62 +- .../tools/LoadingBarCliTools.java | 562 +++++++++--------- 9 files changed, 939 insertions(+), 939 deletions(-) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/AbstractLoadingBar.java (92%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/AbstractProgressBar.java (92%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/DrinkingBar.java (93%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/LoadingBar.java (92%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/SimpleLoadingBar.java (92%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/WorkLoadingBar.java (89%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/tools/CommonTools.java (89%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/tools/FormatTools.java (93%) rename zeitlaeufer/src/main/java/de/szimnau/{ => zeitlaeufer}/tools/LoadingBarCliTools.java (96%) diff --git a/zeitlaeufer/src/main/java/de/szimnau/AbstractLoadingBar.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/AbstractLoadingBar.java similarity index 92% rename from zeitlaeufer/src/main/java/de/szimnau/AbstractLoadingBar.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/AbstractLoadingBar.java index eadfce4..69f4726 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/AbstractLoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/AbstractLoadingBar.java @@ -1,170 +1,170 @@ -package de.szimnau; - -import de.szimnau.tools.FormatTools; -import java.math.BigDecimal; -import java.time.LocalTime; -import java.time.temporal.ChronoUnit; -import java.util.concurrent.TimeUnit; - -import static de.szimnau.tools.CommonTools.print; -import static de.szimnau.tools.CommonTools.println; - - -public abstract class AbstractLoadingBar { - - private final LocalTime startTime; - private LocalTime endTime; - private long totalMinutes; - private BigDecimal totalMinutesBD; - - - protected AbstractLoadingBar(LocalTime startTime) { - this.startTime = startTime; - } - - - protected AbstractLoadingBar(LocalTime startTime, LocalTime endTime) { - this.startTime = startTime; - setEndTime(endTime); - } - - - protected AbstractLoadingBar(LocalTime startTime, long totalMinutes) { - this.startTime = startTime; - setTotalMinutes(totalMinutes); - } - - - public LocalTime getStartTime() { - return startTime; - } - - - public LocalTime getEndTime() { - return endTime; - } - - - protected final void setEndTime(LocalTime endTime) { - this.endTime = endTime; - this.totalMinutes = startTime.until(endTime, ChronoUnit.MINUTES); - this.totalMinutesBD = BigDecimal.valueOf(totalMinutes); - extraInitEndTimeTotalMinutes(); - } - - - protected void extraInitEndTimeTotalMinutes() {} - - - protected long getTotalMinutes() { - return totalMinutes; - } - - - protected final void setTotalMinutes(long totalMinutes) { - this.totalMinutes = totalMinutes; - this.totalMinutesBD = BigDecimal.valueOf(totalMinutes); - this.endTime = startTime.plusMinutes(totalMinutes); - extraInitEndTimeTotalMinutes(); - } - - - protected BigDecimal getTotalMinutesBD() { - return totalMinutesBD; - } - - - protected long getPassedMinutes() { - return getPassedMinutes(false); - } - - - protected long getPassedMinutes(boolean passedMinutesZero) { - return passedMinutesZero ? 0 : startTime.until(LocalTime.now().truncatedTo(ChronoUnit.MINUTES), ChronoUnit.MINUTES); - } - - - public void showLoadingBar() { - showLoadingBar(false, false, 0); - } - - - public void showLoadingBar(boolean debug, boolean passedMinutesZero) { - showLoadingBar(debug, passedMinutesZero, 100L); - } - - - public void showLoadingBarDebug() { - showLoadingBar(true, true, 100L); - } - - - public void showLoadingBarDebug(long millisWaiting) { - showLoadingBar(true, true, millisWaiting); - } - - - public void showLoadingBarDebug(boolean passedMinutesZero) { - showLoadingBar(true, passedMinutesZero, 100L); - } - - - public void showLoadingBarDebug(boolean passedMinutesZero, long millisWaiting) { - showLoadingBar(true, passedMinutesZero, millisWaiting); - } - - - private void showLoadingBar(boolean debug, boolean passedMinutesZero, long millisWaiting) { - long passedMinutes = getPassedMinutes(debug && passedMinutesZero); - if (passedMinutes > totalMinutes) { - passedMinutes = totalMinutes; - } else if (passedMinutes < 0) { - var now = LocalTime.now().truncatedTo(ChronoUnit.SECONDS); - println("!ACHTUNG! Startzeit \"" + startTime + ":00\" liegt in der Zukunft von jetzt an (" + now + ") gesehen."); - } - println(FormatTools.minutesToTimeString(totalMinutes) + " gesamt; Endzeit: " + FormatTools.TIME_FORMATTER.format(endTime)); - while (passedMinutes < totalMinutes) { - print(fillLoadingBar(passedMinutes, true)); - waitUntilNextMinute(debug, millisWaiting); - passedMinutes++; - } - println(fillLoadingBar(passedMinutes, false)); - } - - - protected abstract String fillLoadingBar(long passedMinutes, boolean progressive); - - - protected void waitUntilNextMinute() { - waitUntilNextMinute(false, 0L); - } - - - protected void waitUntilNextMinuteDebug() { - waitUntilNextMinute(true, 100L); - } - - - protected void waitUntilNextMinuteDebug(long millisWaiting) { - waitUntilNextMinute(true, millisWaiting); - } - - - private void waitUntilNextMinute(boolean debug, long millisWaiting) { - try { - if (debug) { - TimeUnit.MILLISECONDS.sleep(millisWaiting); - return; - } - var now = LocalTime.now(); - var oneMinuteLater = now.plusMinutes(1).truncatedTo(ChronoUnit.MINUTES); - /* We wait whole seconds to not make it overly complicated. - That results in cut milliseconds: if we would have to wait 1 second and 526 milliseconds, we wait only 1 second. - So, adjust for ignored milliseconds, add +1 second as it is better to switch between 00 and 01 as between 59 and 00 */ - TimeUnit.SECONDS.sleep(now.until(oneMinuteLater, ChronoUnit.SECONDS) + 1); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); - } - } -} +package de.szimnau.zeitlaeufer; + +import de.szimnau.zeitlaeufer.tools.FormatTools; +import java.math.BigDecimal; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.TimeUnit; + +import static de.szimnau.zeitlaeufer.tools.CommonTools.print; +import static de.szimnau.zeitlaeufer.tools.CommonTools.println; + + +public abstract class AbstractLoadingBar { + + private final LocalTime startTime; + private LocalTime endTime; + private long totalMinutes; + private BigDecimal totalMinutesBD; + + + protected AbstractLoadingBar(LocalTime startTime) { + this.startTime = startTime; + } + + + protected AbstractLoadingBar(LocalTime startTime, LocalTime endTime) { + this.startTime = startTime; + setEndTime(endTime); + } + + + protected AbstractLoadingBar(LocalTime startTime, long totalMinutes) { + this.startTime = startTime; + setTotalMinutes(totalMinutes); + } + + + public LocalTime getStartTime() { + return startTime; + } + + + public LocalTime getEndTime() { + return endTime; + } + + + protected final void setEndTime(LocalTime endTime) { + this.endTime = endTime; + this.totalMinutes = startTime.until(endTime, ChronoUnit.MINUTES); + this.totalMinutesBD = BigDecimal.valueOf(totalMinutes); + extraInitEndTimeTotalMinutes(); + } + + + protected void extraInitEndTimeTotalMinutes() {} + + + protected long getTotalMinutes() { + return totalMinutes; + } + + + protected final void setTotalMinutes(long totalMinutes) { + this.totalMinutes = totalMinutes; + this.totalMinutesBD = BigDecimal.valueOf(totalMinutes); + this.endTime = startTime.plusMinutes(totalMinutes); + extraInitEndTimeTotalMinutes(); + } + + + protected BigDecimal getTotalMinutesBD() { + return totalMinutesBD; + } + + + protected long getPassedMinutes() { + return getPassedMinutes(false); + } + + + protected long getPassedMinutes(boolean passedMinutesZero) { + return passedMinutesZero ? 0 : startTime.until(LocalTime.now().truncatedTo(ChronoUnit.MINUTES), ChronoUnit.MINUTES); + } + + + public void showLoadingBar() { + showLoadingBar(false, false, 0); + } + + + public void showLoadingBar(boolean debug, boolean passedMinutesZero) { + showLoadingBar(debug, passedMinutesZero, 100L); + } + + + public void showLoadingBarDebug() { + showLoadingBar(true, true, 100L); + } + + + public void showLoadingBarDebug(long millisWaiting) { + showLoadingBar(true, true, millisWaiting); + } + + + public void showLoadingBarDebug(boolean passedMinutesZero) { + showLoadingBar(true, passedMinutesZero, 100L); + } + + + public void showLoadingBarDebug(boolean passedMinutesZero, long millisWaiting) { + showLoadingBar(true, passedMinutesZero, millisWaiting); + } + + + private void showLoadingBar(boolean debug, boolean passedMinutesZero, long millisWaiting) { + long passedMinutes = getPassedMinutes(debug && passedMinutesZero); + if (passedMinutes > totalMinutes) { + passedMinutes = totalMinutes; + } else if (passedMinutes < 0) { + var now = LocalTime.now().truncatedTo(ChronoUnit.SECONDS); + println("!ACHTUNG! Startzeit \"" + startTime + ":00\" liegt in der Zukunft von jetzt an (" + now + ") gesehen."); + } + println(FormatTools.minutesToTimeString(totalMinutes) + " gesamt; Endzeit: " + FormatTools.TIME_FORMATTER.format(endTime)); + while (passedMinutes < totalMinutes) { + print(fillLoadingBar(passedMinutes, true)); + waitUntilNextMinute(debug, millisWaiting); + passedMinutes++; + } + println(fillLoadingBar(passedMinutes, false)); + } + + + protected abstract String fillLoadingBar(long passedMinutes, boolean progressive); + + + protected void waitUntilNextMinute() { + waitUntilNextMinute(false, 0L); + } + + + protected void waitUntilNextMinuteDebug() { + waitUntilNextMinute(true, 100L); + } + + + protected void waitUntilNextMinuteDebug(long millisWaiting) { + waitUntilNextMinute(true, millisWaiting); + } + + + private void waitUntilNextMinute(boolean debug, long millisWaiting) { + try { + if (debug) { + TimeUnit.MILLISECONDS.sleep(millisWaiting); + return; + } + var now = LocalTime.now(); + var oneMinuteLater = now.plusMinutes(1).truncatedTo(ChronoUnit.MINUTES); + /* We wait whole seconds to not make it overly complicated. + That results in cut milliseconds: if we would have to wait 1 second and 526 milliseconds, we wait only 1 second. + So, adjust for ignored milliseconds, add +1 second as it is better to switch between 00 and 01 as between 59 and 00 */ + TimeUnit.SECONDS.sleep(now.until(oneMinuteLater, ChronoUnit.SECONDS) + 1); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); + } + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/AbstractProgressBar.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/AbstractProgressBar.java similarity index 92% rename from zeitlaeufer/src/main/java/de/szimnau/AbstractProgressBar.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/AbstractProgressBar.java index 3ab75a9..67b9b9f 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/AbstractProgressBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/AbstractProgressBar.java @@ -1,50 +1,50 @@ -package de.szimnau; - -import de.szimnau.tools.FormatTools; -import java.math.BigDecimal; -import java.math.MathContext; -import java.time.LocalTime; - - -public abstract class AbstractProgressBar extends AbstractLoadingBar { - - protected static final int LINE_LENGTH = 100; - protected static final BigDecimal ONE_HUNDRED_PERCENT = BigDecimal.valueOf(100); - - - protected AbstractProgressBar(LocalTime startTime) { - super(startTime); - } - - - protected AbstractProgressBar(LocalTime startTime, LocalTime endTime) { - super(startTime, endTime); - } - - - @Override - protected String fillLoadingBar(long passedMinutes, boolean progressive) { - var nonNegativePassedMinutes = BigDecimal.valueOf(passedMinutes < 0 ? 0 : passedMinutes); - BigDecimal wholePercentage = ONE_HUNDRED_PERCENT - // kind of reverse dreisatz to avoid having e.g. 99.9999 instead of 100 % - .multiply(nonNegativePassedMinutes) - .divide(getTotalMinutesBD(), MathContext.DECIMAL64); - int numberOfEquals = wholePercentage.intValue(); - var sb = new StringBuilder("["); - for (int i = 0; i < LINE_LENGTH; i++) { - if (i < numberOfEquals) { - sb.append("="); - } else { - sb.append("-"); - } - } - BigDecimal remainingMinutes = getTotalMinutesBD().subtract(nonNegativePassedMinutes); - sb.append("] ").append(FormatTools.PERCENTAGE_FORMAT.format(wholePercentage)).append("% ") - .append(FormatTools.minutesToTimeString(nonNegativePassedMinutes)).append(" - ") - .append(FormatTools.minutesToTimeString(remainingMinutes)); - if (progressive) { - sb.append("\r"); - } - return sb.toString(); - } -} +package de.szimnau.zeitlaeufer; + +import de.szimnau.zeitlaeufer.tools.FormatTools; +import java.math.BigDecimal; +import java.math.MathContext; +import java.time.LocalTime; + + +public abstract class AbstractProgressBar extends AbstractLoadingBar { + + protected static final int LINE_LENGTH = 100; + protected static final BigDecimal ONE_HUNDRED_PERCENT = BigDecimal.valueOf(100); + + + protected AbstractProgressBar(LocalTime startTime) { + super(startTime); + } + + + protected AbstractProgressBar(LocalTime startTime, LocalTime endTime) { + super(startTime, endTime); + } + + + @Override + protected String fillLoadingBar(long passedMinutes, boolean progressive) { + var nonNegativePassedMinutes = BigDecimal.valueOf(passedMinutes < 0 ? 0 : passedMinutes); + BigDecimal wholePercentage = ONE_HUNDRED_PERCENT + // kind of reverse dreisatz to avoid having e.g. 99.9999 instead of 100 % + .multiply(nonNegativePassedMinutes) + .divide(getTotalMinutesBD(), MathContext.DECIMAL64); + int numberOfEquals = wholePercentage.intValue(); + var sb = new StringBuilder("["); + for (int i = 0; i < LINE_LENGTH; i++) { + if (i < numberOfEquals) { + sb.append("="); + } else { + sb.append("-"); + } + } + BigDecimal remainingMinutes = getTotalMinutesBD().subtract(nonNegativePassedMinutes); + sb.append("] ").append(FormatTools.PERCENTAGE_FORMAT.format(wholePercentage)).append("% ") + .append(FormatTools.minutesToTimeString(nonNegativePassedMinutes)).append(" - ") + .append(FormatTools.minutesToTimeString(remainingMinutes)); + if (progressive) { + sb.append("\r"); + } + return sb.toString(); + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/DrinkingBar.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/DrinkingBar.java similarity index 93% rename from zeitlaeufer/src/main/java/de/szimnau/DrinkingBar.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/DrinkingBar.java index 31f9627..13b6790 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/DrinkingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/DrinkingBar.java @@ -1,96 +1,96 @@ -package de.szimnau; - -import de.szimnau.tools.CommonTools; -import de.szimnau.tools.FormatTools; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; -import java.nio.charset.StandardCharsets; -import java.text.DecimalFormat; -import java.time.LocalTime; -import java.time.temporal.ChronoUnit; - -import static de.szimnau.tools.CommonTools.print; - - -public class DrinkingBar extends AbstractLoadingBar { - - private static final int MINS_PER_HALF_HOUR = CommonTools.MINS_PER_HOUR / 2; - private static final int MINUTES_BEFORE_PAUSE = 4 * CommonTools.MINS_PER_HOUR + MINS_PER_HALF_HOUR; - private static final int MINUTES_WITH_PAUSE = 6 * CommonTools.MINS_PER_HOUR; - private static final int DEFAULT_TOTAL_TIME = 8 * CommonTools.MINS_PER_HOUR + MINS_PER_HALF_HOUR; - private static final BigDecimal DEFAULT_TOTAL_TIME_BD = BigDecimal.valueOf(DEFAULT_TOTAL_TIME); - private static final BigDecimal DEFAULT_TOTAL_LITRES = BigDecimal.valueOf(2.0); - private static final BigDecimal QUARTER_LITRE = BigDecimal.valueOf(0.25); - private static final DecimalFormat LITRE_FORMAT = new DecimalFormat("0.00"); - - private BigDecimal totalLitres; - - - public static void main(String[] args) throws IOException { - var br = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); - print("Ankunftszeit: "); - var startTime = LocalTime.parse(br.readLine(), FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - var db = new DrinkingBar(startTime); - db.showLoadingBar(); - } - - - protected DrinkingBar(LocalTime startTime) { - super(startTime, DEFAULT_TOTAL_TIME); - this.totalLitres = DEFAULT_TOTAL_LITRES; - } - - - @Override - protected void extraInitEndTimeTotalMinutes() { - // correct necessary litres to drink based on the end time. - // lower the volume in quarter litre steps - BigDecimal calcTotalLitres = DEFAULT_TOTAL_LITRES; - BigDecimal totalLitresFromMinutes = DEFAULT_TOTAL_LITRES - .multiply(getTotalMinutesBD()) // reverse dreisatz - .divide(DEFAULT_TOTAL_TIME_BD, MathContext.DECIMAL64); - do { - calcTotalLitres = calcTotalLitres.subtract(QUARTER_LITRE); - } while (calcTotalLitres.compareTo(totalLitresFromMinutes) >= 0); - // add quarter since we always did a step "too many", due to the do ... while loop - this.totalLitres = calcTotalLitres.add(QUARTER_LITRE); - } - - - @Override - protected String fillLoadingBar(long passedMinutes, boolean progressive) { - long effectivePassedMinutes = passedMinutes < 0 ? 0 : passedMinutes; - if (getTotalMinutes() > MINUTES_WITH_PAUSE && passedMinutes > MINUTES_BEFORE_PAUSE && passedMinutes <= MINUTES_WITH_PAUSE) { - effectivePassedMinutes = MINUTES_BEFORE_PAUSE; - } - var effectivePassedMinutesBD = BigDecimal.valueOf(effectivePassedMinutes); - BigDecimal currentLitres = totalLitres - .multiply(effectivePassedMinutesBD) // reverse dreisatz - .divide(getTotalMinutesBD(), MathContext.DECIMAL64) - .add(QUARTER_LITRE); - BigDecimal printedLitres = currentLitres.subtract(currentLitres.remainder(QUARTER_LITRE, MathContext.DECIMAL64)); - /* BigDecimal currentProgressToNextStep = ONE_HUNDRED_PERCENT - .multiply(currentLitres.subtract(printedLitres)) // reverse dreisatz - .divide(QUARTER_LITRE, MathContext.DECIMAL64); */ - BigDecimal minutesToNextStep = getMinutesToNextStep(currentLitres); - String progressivePart = progressive ? "\r" : ""; - return progressivePart + "Aktuelles Volumen: " + LITRE_FORMAT.format(printedLitres) + "L - " - // + FormatTools.PERCENTAGE_FORMAT.format(currentProgressToNextStep) + "% - " - + FormatTools.minutesToTimeString(minutesToNextStep); - } - - - private BigDecimal getMinutesToNextStep(BigDecimal currentLitres) { - // berechne Liter benötigt bis zum nächsten 0.25er Schritt - BigDecimal litresToNextStep = QUARTER_LITRE.subtract(currentLitres.remainder(QUARTER_LITRE)); - // berechne Minuten benötigt für 1 Liter - BigDecimal minutesPerLitre = getTotalMinutesBD().divide(totalLitres, MathContext.DECIMAL64); - // berechne Minuten benötigt bis zum nächsten 0.25er Schritt - // runde auf ganze Zahl, da wir nur ganze Minuten anzeigen und damit 1.999 = 2 Minuten sind - return minutesPerLitre.multiply(litresToNextStep).setScale(0, RoundingMode.HALF_EVEN); - } -} +package de.szimnau.zeitlaeufer; + +import de.szimnau.zeitlaeufer.tools.CommonTools; +import de.szimnau.zeitlaeufer.tools.FormatTools; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.nio.charset.StandardCharsets; +import java.text.DecimalFormat; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; + +import static de.szimnau.zeitlaeufer.tools.CommonTools.print; + + +public class DrinkingBar extends AbstractLoadingBar { + + private static final int MINS_PER_HALF_HOUR = CommonTools.MINS_PER_HOUR / 2; + private static final int MINUTES_BEFORE_PAUSE = 4 * CommonTools.MINS_PER_HOUR + MINS_PER_HALF_HOUR; + private static final int MINUTES_WITH_PAUSE = 6 * CommonTools.MINS_PER_HOUR; + private static final int DEFAULT_TOTAL_TIME = 8 * CommonTools.MINS_PER_HOUR + MINS_PER_HALF_HOUR; + private static final BigDecimal DEFAULT_TOTAL_TIME_BD = BigDecimal.valueOf(DEFAULT_TOTAL_TIME); + private static final BigDecimal DEFAULT_TOTAL_LITRES = BigDecimal.valueOf(2.0); + private static final BigDecimal QUARTER_LITRE = BigDecimal.valueOf(0.25); + private static final DecimalFormat LITRE_FORMAT = new DecimalFormat("0.00"); + + private BigDecimal totalLitres; + + + public static void main(String[] args) throws IOException { + var br = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); + print("Ankunftszeit: "); + var startTime = LocalTime.parse(br.readLine(), FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + var db = new DrinkingBar(startTime); + db.showLoadingBar(); + } + + + protected DrinkingBar(LocalTime startTime) { + super(startTime, DEFAULT_TOTAL_TIME); + this.totalLitres = DEFAULT_TOTAL_LITRES; + } + + + @Override + protected void extraInitEndTimeTotalMinutes() { + // correct necessary litres to drink based on the end time. + // lower the volume in quarter litre steps + BigDecimal calcTotalLitres = DEFAULT_TOTAL_LITRES; + BigDecimal totalLitresFromMinutes = DEFAULT_TOTAL_LITRES + .multiply(getTotalMinutesBD()) // reverse dreisatz + .divide(DEFAULT_TOTAL_TIME_BD, MathContext.DECIMAL64); + do { + calcTotalLitres = calcTotalLitres.subtract(QUARTER_LITRE); + } while (calcTotalLitres.compareTo(totalLitresFromMinutes) >= 0); + // add quarter since we always did a step "too many", due to the do ... while loop + this.totalLitres = calcTotalLitres.add(QUARTER_LITRE); + } + + + @Override + protected String fillLoadingBar(long passedMinutes, boolean progressive) { + long effectivePassedMinutes = passedMinutes < 0 ? 0 : passedMinutes; + if (getTotalMinutes() > MINUTES_WITH_PAUSE && passedMinutes > MINUTES_BEFORE_PAUSE && passedMinutes <= MINUTES_WITH_PAUSE) { + effectivePassedMinutes = MINUTES_BEFORE_PAUSE; + } + var effectivePassedMinutesBD = BigDecimal.valueOf(effectivePassedMinutes); + BigDecimal currentLitres = totalLitres + .multiply(effectivePassedMinutesBD) // reverse dreisatz + .divide(getTotalMinutesBD(), MathContext.DECIMAL64) + .add(QUARTER_LITRE); + BigDecimal printedLitres = currentLitres.subtract(currentLitres.remainder(QUARTER_LITRE, MathContext.DECIMAL64)); + /* BigDecimal currentProgressToNextStep = ONE_HUNDRED_PERCENT + .multiply(currentLitres.subtract(printedLitres)) // reverse dreisatz + .divide(QUARTER_LITRE, MathContext.DECIMAL64); */ + BigDecimal minutesToNextStep = getMinutesToNextStep(currentLitres); + String progressivePart = progressive ? "\r" : ""; + return progressivePart + "Aktuelles Volumen: " + LITRE_FORMAT.format(printedLitres) + "L - " + // + FormatTools.PERCENTAGE_FORMAT.format(currentProgressToNextStep) + "% - " + + FormatTools.minutesToTimeString(minutesToNextStep); + } + + + private BigDecimal getMinutesToNextStep(BigDecimal currentLitres) { + // berechne Liter benötigt bis zum nächsten 0.25er Schritt + BigDecimal litresToNextStep = QUARTER_LITRE.subtract(currentLitres.remainder(QUARTER_LITRE)); + // berechne Minuten benötigt für 1 Liter + BigDecimal minutesPerLitre = getTotalMinutesBD().divide(totalLitres, MathContext.DECIMAL64); + // berechne Minuten benötigt bis zum nächsten 0.25er Schritt + // runde auf ganze Zahl, da wir nur ganze Minuten anzeigen und damit 1.999 = 2 Minuten sind + return minutesPerLitre.multiply(litresToNextStep).setScale(0, RoundingMode.HALF_EVEN); + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/LoadingBar.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/LoadingBar.java similarity index 92% rename from zeitlaeufer/src/main/java/de/szimnau/LoadingBar.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/LoadingBar.java index b97c62d..4fef0f4 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/LoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/LoadingBar.java @@ -1,139 +1,139 @@ -package de.szimnau; - -import de.szimnau.tools.CommonTools; -import de.szimnau.tools.FormatTools; -import java.io.IOException; -import java.time.LocalTime; -import java.time.temporal.ChronoUnit; -import java.util.*; -import de.szimnau.tools.LoadingBarCliTools; - -import static de.szimnau.tools.CommonTools.print; - - -public class LoadingBar extends AbstractProgressBar { - - public static final long MAX_NUMBER_WORK_MINS = 8L * CommonTools.MINS_PER_HOUR; - public static final int MIN_LUNCH_DURATION = 30; - public static final LocalTime LATEST_LUNCH_TIME = LocalTime.of(13, 30); - public static final int MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH = 6 * CommonTools.MINS_PER_HOUR; - protected static final long DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH = 5L * CommonTools.MINS_PER_HOUR; - - - protected LoadingBar(LocalTime startTime) { - super(startTime); - } - - - public static void main(String[] args) throws IOException { - if (args.length == 0) { - LoadingBarCliTools.askParametersAndRun(LoadingBar::new); - } else { - LoadingBarCliTools.parseParametersAndRun(args, LoadingBar::new); - } - } - - - public boolean hasMittagspauseArrived() { - return hasMittagspauseArrived(false); - } - - - public boolean hasMittagspauseArrived(boolean debugWithPassedMinutesZero) { - return getPassedMinutes(debugWithPassedMinutesZero) < DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH; - } - - - public void initMittagspause() { - LocalTime defaultEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH); - realInitMittagspause(defaultEndTime); - } - - - public void initMittagspause(int endTimeOffset) { - LocalTime offsetEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH + endTimeOffset); - realInitMittagspause(offsetEndTime); - } - - - public void initMittagspause(LocalTime manualEndTime) { - LocalTime effectiveEndTime = manualEndTime != null ? manualEndTime : getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH); - realInitMittagspause(effectiveEndTime); - } - - - private void realInitMittagspause(LocalTime theoreticalEndTime) { - setEndTime(theoreticalEndTime.isAfter(LATEST_LUNCH_TIME) ? LATEST_LUNCH_TIME : theoreticalEndTime); - } - - - public void initZapfenstreich() { - LocalTime trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + MIN_LUNCH_DURATION); - realInitZapfenstreich(MIN_LUNCH_DURATION, trueEndTime); - } - - - public void initZapfenstreich(Integer manualLunchDuration) { - initZapfenstreich(manualLunchDuration, 0); - } - - - public void initZapfenstreich(Integer manualLunchDuration, int endTimeOffset) { - long minLunchDuration = getMinLunchDuration(endTimeOffset); - long realLunchDuration = getRealLunchDuration(manualLunchDuration, minLunchDuration); - LocalTime trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + realLunchDuration + endTimeOffset); - realInitZapfenstreich(realLunchDuration, trueEndTime); - } - - - public void initZapfenstreich(Integer manualLunchDuration, LocalTime manualEndTime) { - LocalTime trueEndTime = manualEndTime; - long minLunchDuration = getMinLunchDuration(trueEndTime); - long realLunchDuration = getRealLunchDuration(manualLunchDuration, minLunchDuration); - if (trueEndTime == null) { - trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + realLunchDuration); - } - realInitZapfenstreich(realLunchDuration, trueEndTime); - } - - - private long getMinLunchDuration(int endTimeOffset) { - if (endTimeOffset <= 0) { - return MIN_LUNCH_DURATION; - } - long totalDuration = MAX_NUMBER_WORK_MINS + endTimeOffset; - return getMinLunchDuration(totalDuration); - } - - - private long getMinLunchDuration(LocalTime manualEndTime) { - if (manualEndTime == null) { - return MIN_LUNCH_DURATION; - } - long totalDuration = getStartTime().until(manualEndTime, ChronoUnit.MINUTES); - return getMinLunchDuration(totalDuration); - } - - - private long getMinLunchDuration(long precalculatedTotalDuration) { - long effectiveLunchDuration = precalculatedTotalDuration - MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH; - if (effectiveLunchDuration < 0) { - effectiveLunchDuration = 0; - } - return Math.min(effectiveLunchDuration, MIN_LUNCH_DURATION); - } - - - private long getRealLunchDuration(Integer manualLunchDuration, long minLunchDuration) { - return manualLunchDuration != null && manualLunchDuration >= minLunchDuration ? manualLunchDuration : minLunchDuration; - } - - - private void realInitZapfenstreich(long effectiveLunchDuration, LocalTime effectiveEndTime) { - if (effectiveLunchDuration > 0) { - var totalWorkTime = LocalTime.MIDNIGHT.plusMinutes(getStartTime().until(effectiveEndTime, ChronoUnit.MINUTES) - effectiveLunchDuration); - print("Arbeitszeit: " + FormatTools.TIME_FORMATTER.format(totalWorkTime) + "; "); - } - setEndTime(effectiveEndTime); - } -} +package de.szimnau.zeitlaeufer; + +import de.szimnau.zeitlaeufer.tools.CommonTools; +import de.szimnau.zeitlaeufer.tools.FormatTools; +import de.szimnau.zeitlaeufer.tools.LoadingBarCliTools; +import java.io.IOException; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; +import java.util.*; + +import static de.szimnau.zeitlaeufer.tools.CommonTools.print; + + +public class LoadingBar extends AbstractProgressBar { + + public static final long MAX_NUMBER_WORK_MINS = 8L * CommonTools.MINS_PER_HOUR; + public static final int MIN_LUNCH_DURATION = 30; + public static final LocalTime LATEST_LUNCH_TIME = LocalTime.of(13, 30); + public static final int MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH = 6 * CommonTools.MINS_PER_HOUR; + protected static final long DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH = 5L * CommonTools.MINS_PER_HOUR; + + + protected LoadingBar(LocalTime startTime) { + super(startTime); + } + + + public static void main(String[] args) throws IOException { + if (args.length == 0) { + LoadingBarCliTools.askParametersAndRun(LoadingBar::new); + } else { + LoadingBarCliTools.parseParametersAndRun(args, LoadingBar::new); + } + } + + + public boolean hasMittagspauseArrived() { + return hasMittagspauseArrived(false); + } + + + public boolean hasMittagspauseArrived(boolean debugWithPassedMinutesZero) { + return getPassedMinutes(debugWithPassedMinutesZero) < DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH; + } + + + public void initMittagspause() { + LocalTime defaultEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH); + realInitMittagspause(defaultEndTime); + } + + + public void initMittagspause(int endTimeOffset) { + LocalTime offsetEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH + endTimeOffset); + realInitMittagspause(offsetEndTime); + } + + + public void initMittagspause(LocalTime manualEndTime) { + LocalTime effectiveEndTime = manualEndTime != null ? manualEndTime : getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH); + realInitMittagspause(effectiveEndTime); + } + + + private void realInitMittagspause(LocalTime theoreticalEndTime) { + setEndTime(theoreticalEndTime.isAfter(LATEST_LUNCH_TIME) ? LATEST_LUNCH_TIME : theoreticalEndTime); + } + + + public void initZapfenstreich() { + LocalTime trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + MIN_LUNCH_DURATION); + realInitZapfenstreich(MIN_LUNCH_DURATION, trueEndTime); + } + + + public void initZapfenstreich(Integer manualLunchDuration) { + initZapfenstreich(manualLunchDuration, 0); + } + + + public void initZapfenstreich(Integer manualLunchDuration, int endTimeOffset) { + long minLunchDuration = getMinLunchDuration(endTimeOffset); + long realLunchDuration = getRealLunchDuration(manualLunchDuration, minLunchDuration); + LocalTime trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + realLunchDuration + endTimeOffset); + realInitZapfenstreich(realLunchDuration, trueEndTime); + } + + + public void initZapfenstreich(Integer manualLunchDuration, LocalTime manualEndTime) { + LocalTime trueEndTime = manualEndTime; + long minLunchDuration = getMinLunchDuration(trueEndTime); + long realLunchDuration = getRealLunchDuration(manualLunchDuration, minLunchDuration); + if (trueEndTime == null) { + trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + realLunchDuration); + } + realInitZapfenstreich(realLunchDuration, trueEndTime); + } + + + private long getMinLunchDuration(int endTimeOffset) { + if (endTimeOffset <= 0) { + return MIN_LUNCH_DURATION; + } + long totalDuration = MAX_NUMBER_WORK_MINS + endTimeOffset; + return getMinLunchDuration(totalDuration); + } + + + private long getMinLunchDuration(LocalTime manualEndTime) { + if (manualEndTime == null) { + return MIN_LUNCH_DURATION; + } + long totalDuration = getStartTime().until(manualEndTime, ChronoUnit.MINUTES); + return getMinLunchDuration(totalDuration); + } + + + private long getMinLunchDuration(long precalculatedTotalDuration) { + long effectiveLunchDuration = precalculatedTotalDuration - MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH; + if (effectiveLunchDuration < 0) { + effectiveLunchDuration = 0; + } + return Math.min(effectiveLunchDuration, MIN_LUNCH_DURATION); + } + + + private long getRealLunchDuration(Integer manualLunchDuration, long minLunchDuration) { + return manualLunchDuration != null && manualLunchDuration >= minLunchDuration ? manualLunchDuration : minLunchDuration; + } + + + private void realInitZapfenstreich(long effectiveLunchDuration, LocalTime effectiveEndTime) { + if (effectiveLunchDuration > 0) { + var totalWorkTime = LocalTime.MIDNIGHT.plusMinutes(getStartTime().until(effectiveEndTime, ChronoUnit.MINUTES) - effectiveLunchDuration); + print("Arbeitszeit: " + FormatTools.TIME_FORMATTER.format(totalWorkTime) + "; "); + } + setEndTime(effectiveEndTime); + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/SimpleLoadingBar.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/SimpleLoadingBar.java similarity index 92% rename from zeitlaeufer/src/main/java/de/szimnau/SimpleLoadingBar.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/SimpleLoadingBar.java index a982fba..019757c 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/SimpleLoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/SimpleLoadingBar.java @@ -1,102 +1,102 @@ -package de.szimnau; - -import de.szimnau.tools.FormatTools; -import java.time.LocalTime; -import java.util.*; - -import static de.szimnau.tools.CommonTools.println; - - -public class SimpleLoadingBar extends AbstractProgressBar { - - private final String title; - - - private SimpleLoadingBar(LocalTime startTime, LocalTime endTime, String title) { - super(startTime, endTime); - this.title = initTitle(title); - } - - - public static void main(String[] args) { - if (args.length > 0 && Objects.equals(args[0], "--help")) { - printHelp(); - return; - } - verifyMinimumNumberOfArgs(args); - String nextArg = args[0]; - verifyTimeFormat(nextArg, "Erstes Argument"); - var firstTime = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER); - LocalTime startTime; - String title = ""; - LocalTime endTime = null; - if (args.length > 1) { - nextArg = args[1]; - if ("-msg".equals(nextArg)) { - title = args.length > 2 ? args[2] : title; - } else { - verifyTimeFormat(nextArg, "Zweites Argument"); - endTime = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER); - } - } - if (endTime == null) { - startTime = LocalTime.now(); - endTime = firstTime; - } else { - startTime = firstTime; - } - if (args.length == 2 || !title.isBlank()) { - new SimpleLoadingBar(startTime, endTime, title).showLoadingBar(); - return; - } - // if there are 3 arguments, the third will be discarded. - boolean hasTitleArg = args.length > 3 && "-msg".equals(args[2]); - title = hasTitleArg ? args[3] : title; - new SimpleLoadingBar(startTime, endTime, title).showLoadingBar(); - } - - - private static void printHelp() { - println("Mögliche Argumente für LoadingBar:\n" - + "Startzeit, Endzeit, Endnachricht (Optional)\n" - + FormatTools.TIME_FORMAT + " " + FormatTools.TIME_FORMAT + " -msg \n" - + "Endzeit (Startzeit = jetzt), Endnachricht (Optional)\n" - + FormatTools.TIME_FORMAT + " -msg \n" - ); - } - - - private static void verifyMinimumNumberOfArgs(String[] args) { - if (args.length >= 1) { - return; - } - println("Mindestens 1 Argument muss gegeben sein."); - printHelp(); - System.exit(1); - } - - - private static void verifyTimeFormat(String param, String errMsgPrefix) { - if (FormatTools.TIME_PATTERN.matcher(param).matches()) { - return; - } - println(errMsgPrefix + " \"" + param + "\" muss Uhrzeitformat (" + FormatTools.TIME_FORMAT + ") entsprechen."); - System.exit(1); - } - - - private String initTitle(String inputTitle) { - String fallbackTitle = "Ende! Endzeit " + FormatTools.TIME_FORMATTER.format(getEndTime()) + " erreicht."; - String effectiveTitle = inputTitle == null || inputTitle.isBlank() ? fallbackTitle : inputTitle; - String separator = "*".repeat(effectiveTitle.length()); - return separator + "\n" + effectiveTitle + "\n" + separator; - } - - - @Override - public void showLoadingBar() { - super.showLoadingBar(); - // showLoadingBarDebug(); // DEBUG - println(title); - } -} +package de.szimnau.zeitlaeufer; + +import de.szimnau.zeitlaeufer.tools.FormatTools; +import java.time.LocalTime; +import java.util.*; + +import static de.szimnau.zeitlaeufer.tools.CommonTools.println; + + +public class SimpleLoadingBar extends AbstractProgressBar { + + private final String title; + + + private SimpleLoadingBar(LocalTime startTime, LocalTime endTime, String title) { + super(startTime, endTime); + this.title = initTitle(title); + } + + + public static void main(String[] args) { + if (args.length > 0 && Objects.equals(args[0], "--help")) { + printHelp(); + return; + } + verifyMinimumNumberOfArgs(args); + String nextArg = args[0]; + verifyTimeFormat(nextArg, "Erstes Argument"); + var firstTime = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER); + LocalTime startTime; + String title = ""; + LocalTime endTime = null; + if (args.length > 1) { + nextArg = args[1]; + if ("-msg".equals(nextArg)) { + title = args.length > 2 ? args[2] : title; + } else { + verifyTimeFormat(nextArg, "Zweites Argument"); + endTime = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER); + } + } + if (endTime == null) { + startTime = LocalTime.now(); + endTime = firstTime; + } else { + startTime = firstTime; + } + if (args.length == 2 || !title.isBlank()) { + new SimpleLoadingBar(startTime, endTime, title).showLoadingBar(); + return; + } + // if there are 3 arguments, the third will be discarded. + boolean hasTitleArg = args.length > 3 && "-msg".equals(args[2]); + title = hasTitleArg ? args[3] : title; + new SimpleLoadingBar(startTime, endTime, title).showLoadingBar(); + } + + + private static void printHelp() { + println("Mögliche Argumente für LoadingBar:\n" + + "Startzeit, Endzeit, Endnachricht (Optional)\n" + + FormatTools.TIME_FORMAT + " " + FormatTools.TIME_FORMAT + " -msg \n" + + "Endzeit (Startzeit = jetzt), Endnachricht (Optional)\n" + + FormatTools.TIME_FORMAT + " -msg \n" + ); + } + + + private static void verifyMinimumNumberOfArgs(String[] args) { + if (args.length >= 1) { + return; + } + println("Mindestens 1 Argument muss gegeben sein."); + printHelp(); + System.exit(1); + } + + + private static void verifyTimeFormat(String param, String errMsgPrefix) { + if (FormatTools.TIME_PATTERN.matcher(param).matches()) { + return; + } + println(errMsgPrefix + " \"" + param + "\" muss Uhrzeitformat (" + FormatTools.TIME_FORMAT + ") entsprechen."); + System.exit(1); + } + + + private String initTitle(String inputTitle) { + String fallbackTitle = "Ende! Endzeit " + FormatTools.TIME_FORMATTER.format(getEndTime()) + " erreicht."; + String effectiveTitle = inputTitle == null || inputTitle.isBlank() ? fallbackTitle : inputTitle; + String separator = "*".repeat(effectiveTitle.length()); + return separator + "\n" + effectiveTitle + "\n" + separator; + } + + + @Override + public void showLoadingBar() { + super.showLoadingBar(); + // showLoadingBarDebug(); // DEBUG + println(title); + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/WorkLoadingBar.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/WorkLoadingBar.java similarity index 89% rename from zeitlaeufer/src/main/java/de/szimnau/WorkLoadingBar.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/WorkLoadingBar.java index 86b5fc8..de0a95f 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/WorkLoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/WorkLoadingBar.java @@ -1,44 +1,44 @@ -package de.szimnau; - -import de.szimnau.tools.LoadingBarCliTools; -import java.io.IOException; -import java.time.LocalTime; - - -public class WorkLoadingBar extends LoadingBar { - - private final LoadingBar loadingBar; - private final DrinkingBar drinkingBar; - - - private WorkLoadingBar(LocalTime startTime) { - super(startTime); - this.loadingBar = new LoadingBar(startTime); - this.drinkingBar = new DrinkingBar(startTime); - } - - - public static void main(String[] args) throws IOException { - if (args.length == 0) { - LoadingBarCliTools.askParametersAndRun(WorkLoadingBar::new); - } else { - LoadingBarCliTools.parseParametersAndRun(args, WorkLoadingBar::new); - } - } - - - @Override - protected void extraInitEndTimeTotalMinutes() { - LocalTime endTime = getEndTime(); - loadingBar.setEndTime(endTime); - drinkingBar.setEndTime(endTime); - } - - - @Override - protected String fillLoadingBar(long passedMinutes, boolean progressive) { - String filledLoadingBar = loadingBar.fillLoadingBar(passedMinutes, false); - filledLoadingBar += " | " + drinkingBar.fillLoadingBar(passedMinutes, false); - return filledLoadingBar + (progressive ? "\r" : ""); - } -} +package de.szimnau.zeitlaeufer; + +import de.szimnau.zeitlaeufer.tools.LoadingBarCliTools; +import java.io.IOException; +import java.time.LocalTime; + + +public class WorkLoadingBar extends LoadingBar { + + private final LoadingBar loadingBar; + private final DrinkingBar drinkingBar; + + + private WorkLoadingBar(LocalTime startTime) { + super(startTime); + this.loadingBar = new LoadingBar(startTime); + this.drinkingBar = new DrinkingBar(startTime); + } + + + public static void main(String[] args) throws IOException { + if (args.length == 0) { + LoadingBarCliTools.askParametersAndRun(WorkLoadingBar::new); + } else { + LoadingBarCliTools.parseParametersAndRun(args, WorkLoadingBar::new); + } + } + + + @Override + protected void extraInitEndTimeTotalMinutes() { + LocalTime endTime = getEndTime(); + loadingBar.setEndTime(endTime); + drinkingBar.setEndTime(endTime); + } + + + @Override + protected String fillLoadingBar(long passedMinutes, boolean progressive) { + String filledLoadingBar = loadingBar.fillLoadingBar(passedMinutes, false); + filledLoadingBar += " | " + drinkingBar.fillLoadingBar(passedMinutes, false); + return filledLoadingBar + (progressive ? "\r" : ""); + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/tools/CommonTools.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/CommonTools.java similarity index 89% rename from zeitlaeufer/src/main/java/de/szimnau/tools/CommonTools.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/CommonTools.java index 21c4fe0..d9d060f 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/tools/CommonTools.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/CommonTools.java @@ -1,26 +1,26 @@ -package de.szimnau.tools; - -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - - -public class CommonTools { - - public static final int MINS_PER_HOUR = 60; - public static final BigDecimal MINS_PER_HOUR_BD = BigDecimal.valueOf(MINS_PER_HOUR); - public static final MathContext MC_INTEGER = new MathContext(1, RoundingMode.HALF_EVEN); - - - private CommonTools() {} - - - public static void print(Object o) { - System.out.print(o); - } - - - public static void println(Object o) { - System.out.println(o); - } -} +package de.szimnau.zeitlaeufer.tools; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + + +public class CommonTools { + + public static final int MINS_PER_HOUR = 60; + public static final BigDecimal MINS_PER_HOUR_BD = BigDecimal.valueOf(MINS_PER_HOUR); + public static final MathContext MC_INTEGER = new MathContext(1, RoundingMode.HALF_EVEN); + + + private CommonTools() {} + + + public static void print(Object o) { + System.out.print(o); + } + + + public static void println(Object o) { + System.out.println(o); + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/tools/FormatTools.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/FormatTools.java similarity index 93% rename from zeitlaeufer/src/main/java/de/szimnau/tools/FormatTools.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/FormatTools.java index 47e721e..94e3499 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/tools/FormatTools.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/FormatTools.java @@ -1,31 +1,31 @@ -package de.szimnau.tools; - -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.time.format.DateTimeFormatter; -import java.time.LocalTime; -import java.util.*; -import java.util.regex.Pattern; - - -public class FormatTools { - - public static final String TIME_FORMAT = "HH:mm"; - public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_FORMAT); - public static final Pattern TIME_PATTERN = Pattern.compile("(?>[01]\\d|2[0-4]):[0-5]\\d"); - public static final DecimalFormat PERCENTAGE_FORMAT = new DecimalFormat("00.00"); - - - private FormatTools() {} - - - public static String minutesToTimeString(long minutes) { - return minutesToTimeString(BigDecimal.valueOf(minutes)); - } - - - public static String minutesToTimeString(BigDecimal minutes) { - BigDecimal[] hoursAndMinutes = minutes.divideAndRemainder(CommonTools.MINS_PER_HOUR_BD, CommonTools.MC_INTEGER); - return LocalTime.of(hoursAndMinutes[0].intValue(), hoursAndMinutes[1].intValue()).format(TIME_FORMATTER); - } -} +package de.szimnau.zeitlaeufer.tools; + +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.time.format.DateTimeFormatter; +import java.time.LocalTime; +import java.util.*; +import java.util.regex.Pattern; + + +public class FormatTools { + + public static final String TIME_FORMAT = "HH:mm"; + public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_FORMAT); + public static final Pattern TIME_PATTERN = Pattern.compile("(?>[01]\\d|2[0-4]):[0-5]\\d"); + public static final DecimalFormat PERCENTAGE_FORMAT = new DecimalFormat("00.00"); + + + private FormatTools() {} + + + public static String minutesToTimeString(long minutes) { + return minutesToTimeString(BigDecimal.valueOf(minutes)); + } + + + public static String minutesToTimeString(BigDecimal minutes) { + BigDecimal[] hoursAndMinutes = minutes.divideAndRemainder(CommonTools.MINS_PER_HOUR_BD, CommonTools.MC_INTEGER); + return LocalTime.of(hoursAndMinutes[0].intValue(), hoursAndMinutes[1].intValue()).format(TIME_FORMATTER); + } +} diff --git a/zeitlaeufer/src/main/java/de/szimnau/tools/LoadingBarCliTools.java b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/LoadingBarCliTools.java similarity index 96% rename from zeitlaeufer/src/main/java/de/szimnau/tools/LoadingBarCliTools.java rename to zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/LoadingBarCliTools.java index f27a01d..cd45fbf 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/tools/LoadingBarCliTools.java +++ b/zeitlaeufer/src/main/java/de/szimnau/zeitlaeufer/tools/LoadingBarCliTools.java @@ -1,281 +1,281 @@ -package de.szimnau.tools; - -import de.szimnau.LoadingBar; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.time.LocalTime; -import java.time.temporal.ChronoUnit; -import java.util.*; -import java.util.function.Function; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static de.szimnau.tools.CommonTools.print; -import static de.szimnau.tools.CommonTools.println; - -public class LoadingBarCliTools { - - private static final Pattern OFFSET_PATTERN = Pattern.compile("[+-]\\d+"); - private static final Pattern LUNCH_DURATION_PATTERN = Pattern.compile("\\d+"); - - - private enum DaySection { - MITTAG("-m", "Mittag"), - ZAPFENSTREICH("-z", "Zapfenstreich"); - - private final String param; - private final String description; - - - DaySection(String param, String description) { - this.param = param; - this.description = description; - } - - - public static DaySection byParam(String param) { - return Arrays.stream(DaySection.values()).filter((DaySection section) -> section.getParam().equals(param)).findFirst().orElse(null); - } - - - public String getParam() { - return param; - } - - - public String getDescription() { - return description; - } - } - - - private LoadingBarCliTools() {} - - - public static void askParametersAndRun(Function constructor) throws IOException { - var br = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); - print("Ankunftszeit: "); - var startTime = LocalTime.parse(br.readLine(), FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - LoadingBar lb = constructor.apply(startTime); - boolean debug = false; - boolean passedMinutesZero = false; - if (lb.hasMittagspauseArrived(debug && passedMinutesZero)) { - handleMittagspause(br, lb); - lb.showLoadingBar(debug, passedMinutesZero); - } - handleZapfenstreich(br, lb); - lb.showLoadingBar(debug, passedMinutesZero); - } - - - private static void handleMittagspause(BufferedReader br, LoadingBar lb) throws IOException { - print("Mittagspause verschieben um (optional): "); - String mittagspauseOffsetRaw = br.readLine(); - if (mittagspauseOffsetRaw != null && !mittagspauseOffsetRaw.isBlank()) { - var mittagspauseOffset = Integer.parseInt(mittagspauseOffsetRaw); - lb.initMittagspause(mittagspauseOffset); - return; - } - print("Mittagspause um (optional): "); - String manualMittagspauseRaw = br.readLine(); - if (manualMittagspauseRaw != null && !manualMittagspauseRaw.isBlank()) { - var manualMittagspause = LocalTime.parse(manualMittagspauseRaw, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - lb.initMittagspause(manualMittagspause); - } else { - lb.initMittagspause(); - } - } - - - private static void handleZapfenstreich(BufferedReader br, LoadingBar lb) throws IOException { - print("Mittagspause hat gedauert (optional): "); - String mittagspauseDurationRaw = br.readLine(); - Integer mittagspauseDuration = null; - if (mittagspauseDurationRaw != null && !mittagspauseDurationRaw.isBlank()) { - mittagspauseDuration = Integer.valueOf(mittagspauseDurationRaw); - } - LocalTime vorlaeufigeEndzeit = lb.getStartTime().plusMinutes(LoadingBar.MAX_NUMBER_WORK_MINS) - .plusMinutes(mittagspauseDuration != null ? mittagspauseDuration : LoadingBar.MIN_LUNCH_DURATION); - println("Endzeit: " + FormatTools.TIME_FORMATTER.format(vorlaeufigeEndzeit)); - print("Feierabend verschieben um (optional): "); - String zapfenstreichOffsetRaw = br.readLine(); - if (zapfenstreichOffsetRaw != null && !zapfenstreichOffsetRaw.isBlank()) { - int zapfenstreichOffset = Integer.parseInt(zapfenstreichOffsetRaw); - lb.initZapfenstreich(mittagspauseDuration, zapfenstreichOffset); - return; - } - print("Manuelle Uhrzeit Feierabend (optional): "); - String manualZapfenstreichRaw = br.readLine(); - if (manualZapfenstreichRaw != null && !manualZapfenstreichRaw.isBlank()) { - LocalTime manualZapfenstreich = LocalTime.parse(manualZapfenstreichRaw, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - lb.initZapfenstreich(mittagspauseDuration, manualZapfenstreich); - } else { - lb.initZapfenstreich(mittagspauseDuration); - } - } - - - public static void parseParametersAndRun(String[] args, Function constructor) { - String nextArg = args[0]; - if ("--help".equals(nextArg)) { - printHelp(); - System.exit(1); - } - verifyMinimumNumberOfArgs(args); - verifyTimeFormat(nextArg, "Erstes Argument"); - var startTime = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - nextArg = args[1]; - var section = DaySection.byParam(nextArg); - verifyDaySection(section, nextArg); - LoadingBar lb = constructor.apply(startTime); - if (section == DaySection.MITTAG) { - initLoadingBarMittagspause(args, lb); - } else { - initLoadingBarZapfenstreich(args, lb); - } - boolean debug = false; - boolean passedMinutesZero = false; - lb.showLoadingBar(debug, passedMinutesZero); - } - - - private static void initLoadingBarMittagspause(String[] args, LoadingBar lb) { - if (args.length == 2) { - lb.initMittagspause(); - return; - } - String nextArg = args[2]; - if (OFFSET_PATTERN.matcher(nextArg).matches()) { - lb.initMittagspause(Integer.parseInt(nextArg)); - return; - } - verifyTimeFormat(nextArg, "Argument nach " + DaySection.MITTAG.getParam()); - var manualMittagspause = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - lb.initMittagspause(manualMittagspause); - } - - - private static void initLoadingBarZapfenstreich(String[] args, LoadingBar lb) { - if (args.length == 2) { - lb.initZapfenstreich(); - return; - } - String nextArg = args[2]; - LocalTime maxZapfenstreich = null; - int endTimeOffset = 0; - Integer lunchDuration = null; - if (FormatTools.TIME_PATTERN.matcher(nextArg).matches()) { - maxZapfenstreich = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - } else if (OFFSET_PATTERN.matcher(nextArg).matches()) { - endTimeOffset = Integer.parseInt(nextArg); - } else { - verifyDurationFormat(nextArg, "Argument nach " + DaySection.ZAPFENSTREICH.getParam()); - lunchDuration = Integer.parseInt(nextArg); - } - if (args.length == 3) { - if (maxZapfenstreich == null && endTimeOffset == 0) { - lb.initZapfenstreich(lunchDuration); - } else if (maxZapfenstreich == null) { - lb.initZapfenstreich(lunchDuration, endTimeOffset); - } else { - lb.initZapfenstreich(lunchDuration, maxZapfenstreich); - } - return; - } - nextArg = args[3]; - if (lunchDuration == null) { - println("Letztes Argument darf nur auf Mittagspausendauer folgen."); - System.exit(1); - } - if (maxZapfenstreich == null && !OFFSET_PATTERN.matcher(nextArg).matches()) { - verifyTimeFormat(nextArg, "Letztes Argument nach " + DaySection.ZAPFENSTREICH.getParam() + " und Mittagspausendauer"); - maxZapfenstreich = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - lb.initZapfenstreich(lunchDuration, maxZapfenstreich); - return; - } - verifyOffsetFormat(nextArg, "Letztes Argument nach " + DaySection.ZAPFENSTREICH.getParam() + " und Enduhrzeit"); - endTimeOffset = Integer.parseInt(nextArg); - lb.initZapfenstreich(lunchDuration, endTimeOffset); - } - - - private static void verifyMinimumNumberOfArgs(String[] args) { - if (args.length >= 2) { - return; - } - println("Mindestens 2 Argumente müssen gegeben sein."); - printHelp(); - System.exit(1); - } - - - private static void verifyTimeFormat(String param, String errMsgPrefix) { - verifyInputFormat(FormatTools.TIME_PATTERN, param, errMsgPrefix, "Uhrzeitformat (" + FormatTools.TIME_FORMAT + ")", false); - } - - - private static void verifyDurationFormat(String param, String errMsgPrefix) { - verifyInputFormat(LUNCH_DURATION_PATTERN, param, errMsgPrefix, "Minutenanzahl (ganze Zahl)", true); - } - - - private static void verifyOffsetFormat(String param, String errMsgPrefix) { - verifyInputFormat(OFFSET_PATTERN, param, errMsgPrefix, "Minutendifferenz (ganze Zahl mit Vorzeichen)", false); - } - - - private static void verifyInputFormat(Pattern pattern, String param, String errMsgPrefix, String firstInputPart, boolean timeInputPossible) { - if (pattern.matcher(param).matches()) { - return; - } - var possibleTimeInputPart = timeInputPossible ? " oder Uhrzeitformat (" + FormatTools.TIME_FORMAT + ")" : ""; - println(errMsgPrefix + " \"" + param + "\" muss " + firstInputPart + possibleTimeInputPart + " entsprechen."); - System.exit(1); - } - - - private static void verifyDaySection(DaySection section, String param) { - if (section != null) { - return; - } - List sectionDescs = Arrays.stream(DaySection.values()).map((DaySection ds) -> ds.getDescription() + " (" + ds.getParam() + ")") - .collect(Collectors.toList()); - String sectionDescsJoined = String.join(" oder ", sectionDescs); - println("Argument nach Startzeit \"" + param + "\" muss Angabe für " + sectionDescsJoined + " sein."); - System.exit(1); - } - - - private static void printHelp() { - println("Mögliche Argumente für LoadingBar:\n" - + "Normalfall Vormittag (Mittagspause <= " + LoadingBar.LATEST_LUNCH_TIME + ")\n" - + FormatTools.TIME_FORMAT + " " + DaySection.MITTAG.getParam() + "\n" - + "Vormittag mit expliziter Mittagspause (<= " + LoadingBar.LATEST_LUNCH_TIME + ")\n" - + FormatTools.TIME_FORMAT + " " + DaySection.MITTAG.getParam() + " " + FormatTools.TIME_FORMAT + "\n" - + "Vormittag mit abweichender Minutenanzahl Arbeitszeit\n" - + FormatTools.TIME_FORMAT + " " + DaySection.MITTAG.getParam() + " -+mm\n" - + "Normalfall Nachmittag (Mittagspause " + LoadingBar.MIN_LUNCH_DURATION + " min)\n" - + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + "\n" - + "Nachmittag mit expliziter Länge Mittagspause (Mittagspause unter " + LoadingBar.MIN_LUNCH_DURATION + " min wird auf " - + LoadingBar.MIN_LUNCH_DURATION + " min korrigiert)\n" - + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " mm\n" - + "Nachmittag mit explizitem Feierabend (Mittagspause je nach Minimum (s.u.))\n" - + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " " + FormatTools.TIME_FORMAT + "\n" - + "Nachmittag mit abweichender Minutenanzahl Arbeitszeit\n" - + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " -+mm\n" - + "Nachmittag mit explizitem Feierabend u. expliziter Länge Mittagspause (Mittagspause unter Minimum (s.u.) wird auf Minimum korrigiert)\n" - + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " mm " + FormatTools.TIME_FORMAT + "\n" - + "Nachmittag mit explizitem Feierabend u. abweichender Minutenanzahl Arbeitszeit\n" - + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " " + FormatTools.TIME_FORMAT + " -+mm\n\n" - + "Mittagspause minimum in Minuten:\n" - + " - bis " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min (" - + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH / CommonTools.MINS_PER_HOUR + " std): 0\n" - + " - bis " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min + " - + LoadingBar.MIN_LUNCH_DURATION + " min: Arbeitszeit - " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min\n" - + " - ab " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min + " + LoadingBar.MIN_LUNCH_DURATION + " min: " - + LoadingBar.MIN_LUNCH_DURATION + " min\n" - ); - } -} +package de.szimnau.zeitlaeufer.tools; + +import de.szimnau.zeitlaeufer.LoadingBar; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static de.szimnau.zeitlaeufer.tools.CommonTools.print; +import static de.szimnau.zeitlaeufer.tools.CommonTools.println; + +public class LoadingBarCliTools { + + private static final Pattern OFFSET_PATTERN = Pattern.compile("[+-]\\d+"); + private static final Pattern LUNCH_DURATION_PATTERN = Pattern.compile("\\d+"); + + + private enum DaySection { + MITTAG("-m", "Mittag"), + ZAPFENSTREICH("-z", "Zapfenstreich"); + + private final String param; + private final String description; + + + DaySection(String param, String description) { + this.param = param; + this.description = description; + } + + + public static DaySection byParam(String param) { + return Arrays.stream(DaySection.values()).filter((DaySection section) -> section.getParam().equals(param)).findFirst().orElse(null); + } + + + public String getParam() { + return param; + } + + + public String getDescription() { + return description; + } + } + + + private LoadingBarCliTools() {} + + + public static void askParametersAndRun(Function constructor) throws IOException { + var br = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); + print("Ankunftszeit: "); + var startTime = LocalTime.parse(br.readLine(), FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + LoadingBar lb = constructor.apply(startTime); + boolean debug = false; + boolean passedMinutesZero = false; + if (lb.hasMittagspauseArrived(debug && passedMinutesZero)) { + handleMittagspause(br, lb); + lb.showLoadingBar(debug, passedMinutesZero); + } + handleZapfenstreich(br, lb); + lb.showLoadingBar(debug, passedMinutesZero); + } + + + private static void handleMittagspause(BufferedReader br, LoadingBar lb) throws IOException { + print("Mittagspause verschieben um (optional): "); + String mittagspauseOffsetRaw = br.readLine(); + if (mittagspauseOffsetRaw != null && !mittagspauseOffsetRaw.isBlank()) { + var mittagspauseOffset = Integer.parseInt(mittagspauseOffsetRaw); + lb.initMittagspause(mittagspauseOffset); + return; + } + print("Mittagspause um (optional): "); + String manualMittagspauseRaw = br.readLine(); + if (manualMittagspauseRaw != null && !manualMittagspauseRaw.isBlank()) { + var manualMittagspause = LocalTime.parse(manualMittagspauseRaw, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + lb.initMittagspause(manualMittagspause); + } else { + lb.initMittagspause(); + } + } + + + private static void handleZapfenstreich(BufferedReader br, LoadingBar lb) throws IOException { + print("Mittagspause hat gedauert (optional): "); + String mittagspauseDurationRaw = br.readLine(); + Integer mittagspauseDuration = null; + if (mittagspauseDurationRaw != null && !mittagspauseDurationRaw.isBlank()) { + mittagspauseDuration = Integer.valueOf(mittagspauseDurationRaw); + } + LocalTime vorlaeufigeEndzeit = lb.getStartTime().plusMinutes(LoadingBar.MAX_NUMBER_WORK_MINS) + .plusMinutes(mittagspauseDuration != null ? mittagspauseDuration : LoadingBar.MIN_LUNCH_DURATION); + println("Endzeit: " + FormatTools.TIME_FORMATTER.format(vorlaeufigeEndzeit)); + print("Feierabend verschieben um (optional): "); + String zapfenstreichOffsetRaw = br.readLine(); + if (zapfenstreichOffsetRaw != null && !zapfenstreichOffsetRaw.isBlank()) { + int zapfenstreichOffset = Integer.parseInt(zapfenstreichOffsetRaw); + lb.initZapfenstreich(mittagspauseDuration, zapfenstreichOffset); + return; + } + print("Manuelle Uhrzeit Feierabend (optional): "); + String manualZapfenstreichRaw = br.readLine(); + if (manualZapfenstreichRaw != null && !manualZapfenstreichRaw.isBlank()) { + LocalTime manualZapfenstreich = LocalTime.parse(manualZapfenstreichRaw, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + lb.initZapfenstreich(mittagspauseDuration, manualZapfenstreich); + } else { + lb.initZapfenstreich(mittagspauseDuration); + } + } + + + public static void parseParametersAndRun(String[] args, Function constructor) { + String nextArg = args[0]; + if ("--help".equals(nextArg)) { + printHelp(); + System.exit(1); + } + verifyMinimumNumberOfArgs(args); + verifyTimeFormat(nextArg, "Erstes Argument"); + var startTime = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + nextArg = args[1]; + var section = DaySection.byParam(nextArg); + verifyDaySection(section, nextArg); + LoadingBar lb = constructor.apply(startTime); + if (section == DaySection.MITTAG) { + initLoadingBarMittagspause(args, lb); + } else { + initLoadingBarZapfenstreich(args, lb); + } + boolean debug = false; + boolean passedMinutesZero = false; + lb.showLoadingBar(debug, passedMinutesZero); + } + + + private static void initLoadingBarMittagspause(String[] args, LoadingBar lb) { + if (args.length == 2) { + lb.initMittagspause(); + return; + } + String nextArg = args[2]; + if (OFFSET_PATTERN.matcher(nextArg).matches()) { + lb.initMittagspause(Integer.parseInt(nextArg)); + return; + } + verifyTimeFormat(nextArg, "Argument nach " + DaySection.MITTAG.getParam()); + var manualMittagspause = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + lb.initMittagspause(manualMittagspause); + } + + + private static void initLoadingBarZapfenstreich(String[] args, LoadingBar lb) { + if (args.length == 2) { + lb.initZapfenstreich(); + return; + } + String nextArg = args[2]; + LocalTime maxZapfenstreich = null; + int endTimeOffset = 0; + Integer lunchDuration = null; + if (FormatTools.TIME_PATTERN.matcher(nextArg).matches()) { + maxZapfenstreich = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + } else if (OFFSET_PATTERN.matcher(nextArg).matches()) { + endTimeOffset = Integer.parseInt(nextArg); + } else { + verifyDurationFormat(nextArg, "Argument nach " + DaySection.ZAPFENSTREICH.getParam()); + lunchDuration = Integer.parseInt(nextArg); + } + if (args.length == 3) { + if (maxZapfenstreich == null && endTimeOffset == 0) { + lb.initZapfenstreich(lunchDuration); + } else if (maxZapfenstreich == null) { + lb.initZapfenstreich(lunchDuration, endTimeOffset); + } else { + lb.initZapfenstreich(lunchDuration, maxZapfenstreich); + } + return; + } + nextArg = args[3]; + if (lunchDuration == null) { + println("Letztes Argument darf nur auf Mittagspausendauer folgen."); + System.exit(1); + } + if (maxZapfenstreich == null && !OFFSET_PATTERN.matcher(nextArg).matches()) { + verifyTimeFormat(nextArg, "Letztes Argument nach " + DaySection.ZAPFENSTREICH.getParam() + " und Mittagspausendauer"); + maxZapfenstreich = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); + lb.initZapfenstreich(lunchDuration, maxZapfenstreich); + return; + } + verifyOffsetFormat(nextArg, "Letztes Argument nach " + DaySection.ZAPFENSTREICH.getParam() + " und Enduhrzeit"); + endTimeOffset = Integer.parseInt(nextArg); + lb.initZapfenstreich(lunchDuration, endTimeOffset); + } + + + private static void verifyMinimumNumberOfArgs(String[] args) { + if (args.length >= 2) { + return; + } + println("Mindestens 2 Argumente müssen gegeben sein."); + printHelp(); + System.exit(1); + } + + + private static void verifyTimeFormat(String param, String errMsgPrefix) { + verifyInputFormat(FormatTools.TIME_PATTERN, param, errMsgPrefix, "Uhrzeitformat (" + FormatTools.TIME_FORMAT + ")", false); + } + + + private static void verifyDurationFormat(String param, String errMsgPrefix) { + verifyInputFormat(LUNCH_DURATION_PATTERN, param, errMsgPrefix, "Minutenanzahl (ganze Zahl)", true); + } + + + private static void verifyOffsetFormat(String param, String errMsgPrefix) { + verifyInputFormat(OFFSET_PATTERN, param, errMsgPrefix, "Minutendifferenz (ganze Zahl mit Vorzeichen)", false); + } + + + private static void verifyInputFormat(Pattern pattern, String param, String errMsgPrefix, String firstInputPart, boolean timeInputPossible) { + if (pattern.matcher(param).matches()) { + return; + } + var possibleTimeInputPart = timeInputPossible ? " oder Uhrzeitformat (" + FormatTools.TIME_FORMAT + ")" : ""; + println(errMsgPrefix + " \"" + param + "\" muss " + firstInputPart + possibleTimeInputPart + " entsprechen."); + System.exit(1); + } + + + private static void verifyDaySection(DaySection section, String param) { + if (section != null) { + return; + } + List sectionDescs = Arrays.stream(DaySection.values()).map((DaySection ds) -> ds.getDescription() + " (" + ds.getParam() + ")") + .collect(Collectors.toList()); + String sectionDescsJoined = String.join(" oder ", sectionDescs); + println("Argument nach Startzeit \"" + param + "\" muss Angabe für " + sectionDescsJoined + " sein."); + System.exit(1); + } + + + private static void printHelp() { + println("Mögliche Argumente für LoadingBar:\n" + + "Normalfall Vormittag (Mittagspause <= " + LoadingBar.LATEST_LUNCH_TIME + ")\n" + + FormatTools.TIME_FORMAT + " " + DaySection.MITTAG.getParam() + "\n" + + "Vormittag mit expliziter Mittagspause (<= " + LoadingBar.LATEST_LUNCH_TIME + ")\n" + + FormatTools.TIME_FORMAT + " " + DaySection.MITTAG.getParam() + " " + FormatTools.TIME_FORMAT + "\n" + + "Vormittag mit abweichender Minutenanzahl Arbeitszeit\n" + + FormatTools.TIME_FORMAT + " " + DaySection.MITTAG.getParam() + " -+mm\n" + + "Normalfall Nachmittag (Mittagspause " + LoadingBar.MIN_LUNCH_DURATION + " min)\n" + + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + "\n" + + "Nachmittag mit expliziter Länge Mittagspause (Mittagspause unter " + LoadingBar.MIN_LUNCH_DURATION + " min wird auf " + + LoadingBar.MIN_LUNCH_DURATION + " min korrigiert)\n" + + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " mm\n" + + "Nachmittag mit explizitem Feierabend (Mittagspause je nach Minimum (s.u.))\n" + + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " " + FormatTools.TIME_FORMAT + "\n" + + "Nachmittag mit abweichender Minutenanzahl Arbeitszeit\n" + + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " -+mm\n" + + "Nachmittag mit explizitem Feierabend u. expliziter Länge Mittagspause (Mittagspause unter Minimum (s.u.) wird auf Minimum korrigiert)\n" + + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " mm " + FormatTools.TIME_FORMAT + "\n" + + "Nachmittag mit explizitem Feierabend u. abweichender Minutenanzahl Arbeitszeit\n" + + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + " " + FormatTools.TIME_FORMAT + " -+mm\n\n" + + "Mittagspause minimum in Minuten:\n" + + " - bis " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min (" + + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH / CommonTools.MINS_PER_HOUR + " std): 0\n" + + " - bis " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min + " + + LoadingBar.MIN_LUNCH_DURATION + " min: Arbeitszeit - " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min\n" + + " - ab " + LoadingBar.MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min + " + LoadingBar.MIN_LUNCH_DURATION + " min: " + + LoadingBar.MIN_LUNCH_DURATION + " min\n" + ); + } +}