From c976a50051f97f4d521509f560062a353ad4737b Mon Sep 17 00:00:00 2001 From: fabianArbeit Date: Wed, 13 Aug 2025 16:02:29 +0200 Subject: [PATCH] external tools class to handle CLI interaction for LoadingBar and WorkLoadingBar --- .../java/de/szimnau/AbstractLoadingBar.java | 40 +-- .../src/main/java/de/szimnau/LoadingBar.java | 302 +----------------- .../java/de/szimnau/SimpleLoadingBar.java | 6 +- .../main/java/de/szimnau/WorkLoadingBar.java | 68 +--- .../de/szimnau/tools/LoadingBarCliTools.java | 281 ++++++++++++++++ 5 files changed, 332 insertions(+), 365 deletions(-) create mode 100644 zeitlaeufer/src/main/java/de/szimnau/tools/LoadingBarCliTools.java diff --git a/zeitlaeufer/src/main/java/de/szimnau/AbstractLoadingBar.java b/zeitlaeufer/src/main/java/de/szimnau/AbstractLoadingBar.java index d96cfbc..eadfce4 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/AbstractLoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/AbstractLoadingBar.java @@ -35,12 +35,12 @@ public abstract class AbstractLoadingBar { } - protected LocalTime getStartTime() { + public LocalTime getStartTime() { return startTime; } - protected LocalTime getEndTime() { + public LocalTime getEndTime() { return endTime; } @@ -84,32 +84,32 @@ public abstract class AbstractLoadingBar { } - protected void showLoadingBar() { + public void showLoadingBar() { showLoadingBar(false, false, 0); } - protected void showLoadingBarDebug() { - showLoadingBar(true, true, 100L); - } - - - protected void showLoadingBarDebug(long millisWaiting) { - showLoadingBar(true, true, millisWaiting); - } - - - protected void showLoadingBarDebug(boolean passedMinutesZero) { - showLoadingBar(true, passedMinutesZero, 100L); - } - - - protected void showLoadingBar(boolean debug, boolean passedMinutesZero) { + public void showLoadingBar(boolean debug, boolean passedMinutesZero) { showLoadingBar(debug, passedMinutesZero, 100L); } - protected void showLoadingBarDebug(boolean passedMinutesZero, long millisWaiting) { + 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); } diff --git a/zeitlaeufer/src/main/java/de/szimnau/LoadingBar.java b/zeitlaeufer/src/main/java/de/szimnau/LoadingBar.java index 5d5a673..b97c62d 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/LoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/LoadingBar.java @@ -2,59 +2,22 @@ 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.nio.charset.StandardCharsets; import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.*; -import java.util.regex.Pattern; -import java.util.stream.Collectors; +import de.szimnau.tools.LoadingBarCliTools; import static de.szimnau.tools.CommonTools.print; -import static de.szimnau.tools.CommonTools.println; public class LoadingBar extends AbstractProgressBar { - private static final Pattern LUNCH_DURATION_PATTERN = Pattern.compile("\\d+"); - private static final Pattern OFFSET_PATTERN = Pattern.compile("[+-]\\d+"); - private static final int MIN_LUNCH_DURATION = 30; - private static final LocalTime LATEST_LUNCH_TIME = LocalTime.of(13, 30); - private static final long DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH = 5L * CommonTools.MINS_PER_HOUR; - private static final int MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH = 6 * CommonTools.MINS_PER_HOUR; - private static final long MAX_NUMBER_WORK_MINS = 8L * CommonTools.MINS_PER_HOUR; - - - 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; - } - } + 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) { @@ -64,267 +27,36 @@ public class LoadingBar extends AbstractProgressBar { public static void main(String[] args) throws IOException { if (args.length == 0) { - askParametersAndRun(); + LoadingBarCliTools.askParametersAndRun(LoadingBar::new); } else { - parseParametersAndRun(args); + LoadingBarCliTools.parseParametersAndRun(args, LoadingBar::new); } } - private static void askParametersAndRun() 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 lb = new LoadingBar(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); - } - - - protected 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(); - } - } - - - protected 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(MAX_NUMBER_WORK_MINS) - .plusMinutes(mittagspauseDuration != null ? mittagspauseDuration : MIN_LUNCH_DURATION); - println("Endzeit: " + FormatTools.TIME_FORMATTER.format(vorlaeufigeEndzeit)); - print("Feierabend verschieben um (optional): "); - String zapfenstreichOffsetRaw = br.readLine(); - Integer zapfenstreichOffset = null; - if (zapfenstreichOffsetRaw != null && !zapfenstreichOffsetRaw.isBlank()) { - zapfenstreichOffset = Integer.valueOf(zapfenstreichOffsetRaw); - lb.initZapfenstreich(mittagspauseDuration, zapfenstreichOffset); - return; - } - print("Manuelle Uhrzeit Feierabend (optional): "); - String manualZapfenstreichRaw = br.readLine(); - LocalTime manualZapfenstreich = null; - if (manualZapfenstreichRaw != null && !manualZapfenstreichRaw.isBlank()) { - manualZapfenstreich = LocalTime.parse(manualZapfenstreichRaw, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - lb.initZapfenstreich(mittagspauseDuration, manualZapfenstreich); - } else { - lb.initZapfenstreich(mittagspauseDuration); - } - } - - - private static void parseParametersAndRun(String[] args) { - LoadingBar lb = getLoadingBarFromCLI(args); - boolean debug = false; - boolean passedMinutesZero = false; - wl.showLoadingBar(debug, passedMinutesZero); - } - - - protected static LoadingBar getLoadingBarFromCLI(String[] args) { - 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); - return section == DaySection.MITTAG ? getLoadingBarMittagspause(args, startTime) : getLoadingBarZapfenstreich(args, startTime); - } - - - private static LoadingBar getLoadingBarMittagspause(String[] args, LocalTime startTime) { - var lb = new LoadingBar(startTime); - if (args.length == 2) { - lb.initMittagspause(); - return lb; - } - String nextArg = args[2]; - if (OFFSET_PATTERN.matcher(nextArg).matches()) { - lb.initMittagspause(Integer.parseInt(nextArg)); - return lb; - } - verifyTimeFormat(nextArg, "Argument nach " + DaySection.MITTAG.getParam()); - var manualMittagspause = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER).truncatedTo(ChronoUnit.MINUTES); - lb.initMittagspause(manualMittagspause); - return lb; - } - - - private static LoadingBar getLoadingBarZapfenstreich(String[] args, LocalTime startTime) { - var lb = new LoadingBar(startTime); - if (args.length == 2) { - lb.initZapfenstreich(); - return lb; - } - 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 lb; - } - 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 lb; - } - verifyOffsetFormat(nextArg, "Letztes Argument nach " + DaySection.ZAPFENSTREICH.getParam() + " und Enduhrzeit"); - endTimeOffset = Integer.parseInt(nextArg); - lb.initZapfenstreich(lunchDuration, endTimeOffset); - return lb; - } - - - 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 <= " + LATEST_LUNCH_TIME + ")\n" - + FormatTools.TIME_FORMAT + " " + DaySection.MITTAG.getParam() + "\n" - + "Vormittag mit expliziter Mittagspause (<= " + 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 " + MIN_LUNCH_DURATION + " min)\n" - + FormatTools.TIME_FORMAT + " " + DaySection.ZAPFENSTREICH.getParam() + "\n" - + "Nachmittag mit expliziter Länge Mittagspause (Mittagspause unter " + MIN_LUNCH_DURATION + " min wird auf " + 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 " + MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min (" - + MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH / CommonTools.MINS_PER_HOUR + " std): 0\n" - + " - bis " + MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min + " - + MIN_LUNCH_DURATION + " min: Arbeitszeit - " + MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min\n" - + " - ab " + MAX_NUMBER_WORK_MINS_WITHOUT_LUNCH + " min + " + MIN_LUNCH_DURATION + " min: " - + MIN_LUNCH_DURATION + " min\n" - ); - } - - - protected boolean hasMittagspauseArrived() { + public boolean hasMittagspauseArrived() { return hasMittagspauseArrived(false); } - protected boolean hasMittagspauseArrived(boolean debugWithPassedMinutesZero) { + public boolean hasMittagspauseArrived(boolean debugWithPassedMinutesZero) { return getPassedMinutes(debugWithPassedMinutesZero) < DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH; } - private void initMittagspause() { + public void initMittagspause() { LocalTime defaultEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH); realInitMittagspause(defaultEndTime); } - private void initMittagspause(int endTimeOffset) { + public void initMittagspause(int endTimeOffset) { LocalTime offsetEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH + endTimeOffset); realInitMittagspause(offsetEndTime); } - private void initMittagspause(LocalTime manualEndTime) { + public void initMittagspause(LocalTime manualEndTime) { LocalTime effectiveEndTime = manualEndTime != null ? manualEndTime : getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH); realInitMittagspause(effectiveEndTime); } @@ -335,18 +67,18 @@ public class LoadingBar extends AbstractProgressBar { } - private void initZapfenstreich() { + public void initZapfenstreich() { LocalTime trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + MIN_LUNCH_DURATION); realInitZapfenstreich(MIN_LUNCH_DURATION, trueEndTime); } - private void initZapfenstreich(Integer manualLunchDuration) { + public void initZapfenstreich(Integer manualLunchDuration) { initZapfenstreich(manualLunchDuration, 0); } - private void initZapfenstreich(Integer manualLunchDuration, int endTimeOffset) { + 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); @@ -354,7 +86,7 @@ public class LoadingBar extends AbstractProgressBar { } - private void initZapfenstreich(Integer manualLunchDuration, LocalTime manualEndTime) { + public void initZapfenstreich(Integer manualLunchDuration, LocalTime manualEndTime) { LocalTime trueEndTime = manualEndTime; long minLunchDuration = getMinLunchDuration(trueEndTime); long realLunchDuration = getRealLunchDuration(manualLunchDuration, minLunchDuration); diff --git a/zeitlaeufer/src/main/java/de/szimnau/SimpleLoadingBar.java b/zeitlaeufer/src/main/java/de/szimnau/SimpleLoadingBar.java index 506cc6f..a982fba 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/SimpleLoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/SimpleLoadingBar.java @@ -27,7 +27,7 @@ public class SimpleLoadingBar extends AbstractProgressBar { String nextArg = args[0]; verifyTimeFormat(nextArg, "Erstes Argument"); var firstTime = LocalTime.parse(nextArg, FormatTools.TIME_FORMATTER); - LocalTime startTime = null; + LocalTime startTime; String title = ""; LocalTime endTime = null; if (args.length > 1) { @@ -94,8 +94,8 @@ public class SimpleLoadingBar extends AbstractProgressBar { @Override - protected void showLoadingBar() { - showLoadingBar(); + 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/WorkLoadingBar.java index 79230ec..86b5fc8 100644 --- a/zeitlaeufer/src/main/java/de/szimnau/WorkLoadingBar.java +++ b/zeitlaeufer/src/main/java/de/szimnau/WorkLoadingBar.java @@ -1,83 +1,37 @@ package de.szimnau; -import de.szimnau.tools.CommonTools; -import de.szimnau.tools.FormatTools; -import java.io.BufferedReader; -import java.io.InputStreamReader; +import de.szimnau.tools.LoadingBarCliTools; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.time.LocalTime; -import java.time.temporal.ChronoUnit; - -import static de.szimnau.tools.CommonTools.print; -public class WorkLoadingBar extends AbstractProgressBar { +public class WorkLoadingBar extends LoadingBar { private final LoadingBar loadingBar; private final DrinkingBar drinkingBar; - private WorkLoadingBar(LoadingBar loadingBar, DrinkingBar drinkingBar) { - super(loadingBar.getStartTime()); - this.loadingBar = loadingBar; - this.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) { - askParametersAndRun(); + LoadingBarCliTools.askParametersAndRun(WorkLoadingBar::new); } else { - parseParametersAndRun(args); + LoadingBarCliTools.parseParametersAndRun(args, WorkLoadingBar::new); } } - private static void askParametersAndRun() 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 lb = new LoadingBar(startTime); - var db = new DrinkingBar(startTime); - var wlb = new WorkLoadingBar(lb, db); - boolean debug = false; - boolean passedMinutesZero = false; - if (lb.hasMittagspauseArrived(debug && passedMinutesZero)) { - handleMittagspause(br, wlb); - wlb.showLoadingBar(debug, passedMinutesZero); - } - handleZapfenstreich(br, wlb); - wlb.showLoadingBar(debug, passedMinutesZero); - } - - - private static void handleMittagspause(BufferedReader br, WorkLoadingBar wlb) throws IOException { - LoadingBar.handleMittagspause(br, wlb.loadingBar); - wlb.setEndTime(wlb.loadingBar.getEndTime()); - } - - - private static void handleZapfenstreich(BufferedReader br, WorkLoadingBar wlb) throws IOException { - LoadingBar.handleZapfenstreich(br, wlb.loadingBar); - wlb.setEndTime(wlb.loadingBar.getEndTime()); - } - - - private static void parseParametersAndRun(String[] args) { - LoadingBar lb = LoadingBar.getLoadingBarFromCLI(args); - var db = new DrinkingBar(lb.getStartTime()); - var wlb = new WorkLoadingBar(lb, db); - wlb.setEndTime(wlb.loadingBar.getEndTime()); - boolean debug = false; - boolean passedMinutesZero = false; - wlb.showLoadingBar(debug, passedMinutesZero); - } - - @Override protected void extraInitEndTimeTotalMinutes() { - drinkingBar.setEndTime(getEndTime()); + LocalTime endTime = getEndTime(); + loadingBar.setEndTime(endTime); + drinkingBar.setEndTime(endTime); } diff --git a/zeitlaeufer/src/main/java/de/szimnau/tools/LoadingBarCliTools.java b/zeitlaeufer/src/main/java/de/szimnau/tools/LoadingBarCliTools.java new file mode 100644 index 0000000..f27a01d --- /dev/null +++ b/zeitlaeufer/src/main/java/de/szimnau/tools/LoadingBarCliTools.java @@ -0,0 +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" + ); + } +}