Compare commits
23 Commits
73c270fe1c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| cea8d25eea | |||
| 12c8898252 | |||
| 9e65158901 | |||
| 67c341a091 | |||
| c74d63c178 | |||
| 5f2c7ffeab | |||
| 8d1e6aed7a | |||
| dc690f3350 | |||
| 8be9cf81d7 | |||
| 7df22a2d1f | |||
| 664c6108a5 | |||
| 094dfd9daf | |||
| 4dd18d03f0 | |||
| 5a596e28da | |||
| 3929ce2666 | |||
| c872efa459 | |||
| 31d8cfd43d | |||
| 96fee5b19c | |||
| 847d899a2a | |||
| 941e15389f | |||
| 9addfe51d7 | |||
| a21c318d90 | |||
| b473dcf264 |
+4
-2
@@ -1,3 +1,5 @@
|
|||||||
target/
|
/target/
|
||||||
dist/
|
/dist/
|
||||||
*.class
|
*.class
|
||||||
|
/.idea/
|
||||||
|
/*.iml
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
# when executed as executable file in "git for windows" bash some things won't work, so always run with prefixed command
|
||||||
|
rm -rf /tmp/zeitlaeufer_*;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
|
# when executed as executable file in "git for windows" bash some things won't work, so always run with prefixed command
|
||||||
if [[ $# -ge 1 && $1 == "clean" ]]; then
|
if [[ $# -ge 1 && $1 == "clean" ]]; then
|
||||||
rm -r target/;
|
rm -r target/;
|
||||||
fi
|
fi
|
||||||
|
|||||||
+10
-4
@@ -1,8 +1,14 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
if [[ -d dist/ ]]; then
|
# when executed as executable file in "git for windows" bash some things won't work, so always run with prefixed command
|
||||||
rm -r dist/;
|
if [[ ! -e dist ]]; then
|
||||||
|
mkdir dist;
|
||||||
fi
|
fi
|
||||||
|
rm -r dist/* 2>/dev/null;
|
||||||
cp -r target/ dist/;
|
dir=$(pwd)
|
||||||
|
cd target;
|
||||||
|
# jar [...] --manifest=[...] with main class does work when running with "java -jar" but not with "java --module-path"
|
||||||
|
# --create --file <=> cf
|
||||||
|
jar --create --file=../dist/zeitlaeufer.jar --main-class=de.szimnau.zeitlaeufer.Main ./**/*;
|
||||||
|
cd $dir
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
# when executed as executable file in "git for windows" bash some things won't work, so always run with prefixed command
|
||||||
|
jarDir=/g/zeitlaeufer/dist/;
|
||||||
|
if [[ $# == 0 || ($1 != -quick && $1 != -class) ]]; then
|
||||||
|
tmpDir=/tmp/zeitlaeufer_$RANDOM;
|
||||||
|
mkdir $tmpDir;
|
||||||
|
cp ${jarDir}zeitlaeufer.jar $tmpDir;
|
||||||
|
jarDir=$tmpDir;
|
||||||
|
elif [[ $1 == -quick ]]; then
|
||||||
|
shift;
|
||||||
|
elif [[ $1 == -class ]]; then
|
||||||
|
originDir=$(pwd);
|
||||||
|
cd /g/zeitlaeufer/target/;
|
||||||
|
java de.szimnau.zeitlaeufer.$2;
|
||||||
|
exitCode=$?;
|
||||||
|
cd originDir;
|
||||||
|
return $exitCode;
|
||||||
|
fi
|
||||||
|
# java -jar $tmpDir/zeitlaeufer.jar $@;
|
||||||
|
# -p <=> --module-path | -m <=> --module
|
||||||
|
java --module-path $jarDir/zeitlaeufer.jar --module zeitlaeufer $@;
|
||||||
|
if [[ -n $tmpDir && -d $tmpDir ]]; then
|
||||||
|
rm -r $tmpDir;
|
||||||
|
fi
|
||||||
@@ -21,7 +21,8 @@ public class DrinkingBar extends AbstractLoadingBar implements WorkdayLoadingBar
|
|||||||
|
|
||||||
private static final int MINS_PER_HALF_HOUR = CommonTools.MINS_PER_HOUR / 2;
|
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_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 MAX_MINUTES_WITHOUT_PAUSE = 6 * CommonTools.MINS_PER_HOUR;
|
||||||
|
private static final int MAX_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 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_TIME_BD = BigDecimal.valueOf(DEFAULT_TOTAL_TIME);
|
||||||
private static final BigDecimal DEFAULT_TOTAL_LITRES = BigDecimal.valueOf(2.0);
|
private static final BigDecimal DEFAULT_TOTAL_LITRES = BigDecimal.valueOf(2.0);
|
||||||
@@ -65,7 +66,10 @@ public class DrinkingBar extends AbstractLoadingBar implements WorkdayLoadingBar
|
|||||||
@Override
|
@Override
|
||||||
protected String fillLoadingBar(long passedMinutes, boolean progressive) {
|
protected String fillLoadingBar(long passedMinutes, boolean progressive) {
|
||||||
long effectivePassedMinutes = passedMinutes < 0 ? 0 : passedMinutes;
|
long effectivePassedMinutes = passedMinutes < 0 ? 0 : passedMinutes;
|
||||||
if (getTotalMinutes() > MINUTES_WITH_PAUSE && passedMinutes > MINUTES_BEFORE_PAUSE && passedMinutes <= MINUTES_WITH_PAUSE) {
|
/* the pause in counting up passed minutes could be more precise.
|
||||||
|
there IS a way to find out how LONG the lunch break was (known until WorkdayLoadingBar.realInitZapfenstreich),
|
||||||
|
but NOT the exact time slot from when to when the lunch break did take place... */
|
||||||
|
if (getTotalMinutes() > MAX_MINUTES_WITHOUT_PAUSE && passedMinutes > MINUTES_BEFORE_PAUSE && passedMinutes <= MAX_MINUTES_WITH_PAUSE) {
|
||||||
effectivePassedMinutes = MINUTES_BEFORE_PAUSE;
|
effectivePassedMinutes = MINUTES_BEFORE_PAUSE;
|
||||||
}
|
}
|
||||||
var effectivePassedMinutesBD = BigDecimal.valueOf(effectivePassedMinutes);
|
var effectivePassedMinutesBD = BigDecimal.valueOf(effectivePassedMinutes);
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
package de.szimnau.zeitlaeufer;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static de.szimnau.zeitlaeufer.tools.CommonTools.print;
|
||||||
|
import static de.szimnau.zeitlaeufer.tools.CommonTools.println;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
|
||||||
|
if (args.length == 0) {
|
||||||
|
askParametersAndRun();
|
||||||
|
} else {
|
||||||
|
parseParametersAndRun(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void askParametersAndRun() throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
|
var br = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
|
||||||
|
SortedMap<Integer, Class<?>> classes = getAllrelevantClasses();
|
||||||
|
String printedClasses = classes.entrySet().stream()
|
||||||
|
.map(e -> e.getKey() + ": " + e.getValue().getCanonicalName().substring(e.getValue().getCanonicalName().lastIndexOf('.') + 1))
|
||||||
|
.reduce("", (a, b) -> a + "\n" + b);
|
||||||
|
print("Welcher Zeitläufer soll verwendet werden? " + printedClasses + "\n: ");
|
||||||
|
var num = Integer.parseInt(br.readLine());
|
||||||
|
Class<?> selectedClass = classes.get(num);
|
||||||
|
Method mainMethod = selectedClass.getMethod("main", String[].class);
|
||||||
|
mainMethod.invoke(null, (Object) new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static SortedMap<Integer, Class<?>> getAllrelevantClasses() {
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
URL resourceUrl = classLoader.getResource("de/szimnau/zeitlaeufer");
|
||||||
|
if (resourceUrl == null) {
|
||||||
|
throw new RuntimeException("Kann ausführbare Klassen nicht eruieren, da keine Ressource \"de/szimnau/zeitlaeufer\" verfügbar.");
|
||||||
|
}
|
||||||
|
Set<String> fileNames;
|
||||||
|
if (resourceUrl.getPath().contains(".jar")) {
|
||||||
|
fileNames = getFileNamesStreamFromJar(resourceUrl);
|
||||||
|
} else {
|
||||||
|
fileNames = getFileNamesStreamFromPackage(resourceUrl);
|
||||||
|
}
|
||||||
|
var increment = new AtomicInteger();
|
||||||
|
return Collections.unmodifiableSortedMap(new TreeMap<>(
|
||||||
|
fileNames.stream()
|
||||||
|
.filter(line -> line.endsWith(".class") && !line.endsWith("module-info.class") && !line.endsWith("Main.class"))
|
||||||
|
.sorted()
|
||||||
|
.map(Main::getClass)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(clazz ->
|
||||||
|
Arrays.stream(clazz.getMethods()).anyMatch(m ->
|
||||||
|
"main".equals(m.getName()) && m.getParameterCount() == 1 && m.getParameterTypes()[0] == String[].class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.collect(Collectors.toMap(c -> increment.incrementAndGet(), Function.identity()))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Set<String> getFileNamesStreamFromJar(URL resourceUrl) {
|
||||||
|
Set<String> fileNames = new HashSet<>();
|
||||||
|
String path = resourceUrl.getPath().split(":", 2)[1];
|
||||||
|
String cleanPath = path.substring(0, path.lastIndexOf('!'));
|
||||||
|
Enumeration<JarEntry> entries;
|
||||||
|
try (var jarFile = new JarFile(URLDecoder.decode(cleanPath, StandardCharsets.UTF_8))) {
|
||||||
|
entries = jarFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
JarEntry entry = entries.nextElement();
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fileNames.add(entry.getName());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Kann JAR-Datei zwecks Reflection nicht öffnen:", e);
|
||||||
|
}
|
||||||
|
return fileNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Set<String> getFileNamesStreamFromPackage(URL resourceUrl) {
|
||||||
|
try (InputStream stream = resourceUrl.openStream();
|
||||||
|
var br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
|
||||||
|
return br.lines()
|
||||||
|
.map(line -> "de/szimnau/zeitlaeufer." + line)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("ausführbare Klassen nicht eruieren, da Ressource " + resourceUrl + " nicht auslesbar.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Class<?> getClass(String className) {
|
||||||
|
String classWithPath = className.replace("/", ".");
|
||||||
|
return getClassForName(classWithPath.substring(0, className.lastIndexOf('.')));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Class<?> getClassForName(String className) {
|
||||||
|
try {
|
||||||
|
return Class.forName(className);
|
||||||
|
} catch (ClassNotFoundException cnfe) {
|
||||||
|
println("ERROR: could not find Class for Name: de.szimnau.zeitlaeufer." + className);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void parseParametersAndRun(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
|
Class<?> selectedClass = getClassForName("de.szimnau.zeitlaeufer." + args[0]);
|
||||||
|
if (selectedClass == null) {
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
var mainMethod = selectedClass.getMethod("main", String[].class);
|
||||||
|
mainMethod.invoke(null, (Object) Arrays.copyOfRange(args, 1, args.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,12 +20,12 @@ public interface WorkdayLoadingBar {
|
|||||||
void showLoadingBar(boolean debug, boolean passedMinutesZero);
|
void showLoadingBar(boolean debug, boolean passedMinutesZero);
|
||||||
|
|
||||||
|
|
||||||
default boolean hasMittagspauseArrived() {
|
default boolean couldHaveHadNoMittagspauseYet() {
|
||||||
return hasMittagspauseArrived(false);
|
return couldHaveHadNoMittagspauseYet(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default boolean hasMittagspauseArrived(boolean debugWithPassedMinutesZero) {
|
default boolean couldHaveHadNoMittagspauseYet(boolean debugWithPassedMinutesZero) {
|
||||||
return getPassedMinutes(debugWithPassedMinutesZero) < DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH;
|
return getPassedMinutes(debugWithPassedMinutesZero) < DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,6 +33,12 @@ public interface WorkdayLoadingBar {
|
|||||||
long getPassedMinutes(boolean passedMinutesZero);
|
long getPassedMinutes(boolean passedMinutesZero);
|
||||||
|
|
||||||
|
|
||||||
|
default LocalTime estimateMittagspause() {
|
||||||
|
LocalTime defaultEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH);
|
||||||
|
return calculateRealMittagspause(defaultEndTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
default void initMittagspause() {
|
default void initMittagspause() {
|
||||||
LocalTime defaultEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH);
|
LocalTime defaultEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH);
|
||||||
realInitMittagspause(defaultEndTime);
|
realInitMittagspause(defaultEndTime);
|
||||||
@@ -43,7 +49,7 @@ public interface WorkdayLoadingBar {
|
|||||||
|
|
||||||
|
|
||||||
default void initMittagspause(int endTimeOffset) {
|
default void initMittagspause(int endTimeOffset) {
|
||||||
LocalTime offsetEndTime = getStartTime().plusMinutes(DEFAULT_NUMBER_WORK_MINS_BEFORE_LUNCH + endTimeOffset);
|
LocalTime offsetEndTime = estimateMittagspause().plusMinutes(endTimeOffset);
|
||||||
realInitMittagspause(offsetEndTime);
|
realInitMittagspause(offsetEndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,13 +61,24 @@ public interface WorkdayLoadingBar {
|
|||||||
|
|
||||||
|
|
||||||
private void realInitMittagspause(LocalTime theoreticalEndTime) {
|
private void realInitMittagspause(LocalTime theoreticalEndTime) {
|
||||||
setEndTime(theoreticalEndTime.isAfter(LATEST_LUNCH_TIME) ? LATEST_LUNCH_TIME : theoreticalEndTime);
|
setEndTime(calculateRealMittagspause(theoreticalEndTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private LocalTime calculateRealMittagspause(LocalTime theoreticalMittagspause) {
|
||||||
|
return theoreticalMittagspause.isAfter(LATEST_LUNCH_TIME) ? LATEST_LUNCH_TIME : theoreticalMittagspause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setEndTime(LocalTime endTime);
|
void setEndTime(LocalTime endTime);
|
||||||
|
|
||||||
|
|
||||||
|
default LocalTime estimateZapfenstreich(Integer mittagspauseDuration) {
|
||||||
|
int estMittagspauseDuration = mittagspauseDuration != null ? mittagspauseDuration : MIN_LUNCH_DURATION;
|
||||||
|
return getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + estMittagspauseDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
default void initZapfenstreich() {
|
default void initZapfenstreich() {
|
||||||
LocalTime trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + MIN_LUNCH_DURATION);
|
LocalTime trueEndTime = getStartTime().plusMinutes(MAX_NUMBER_WORK_MINS + MIN_LUNCH_DURATION);
|
||||||
realInitZapfenstreich(MIN_LUNCH_DURATION, trueEndTime);
|
realInitZapfenstreich(MIN_LUNCH_DURATION, trueEndTime);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class LoadingBarCliTools {
|
|||||||
WorkdayLoadingBar lb = constructor.apply(startTime);
|
WorkdayLoadingBar lb = constructor.apply(startTime);
|
||||||
boolean debug = false;
|
boolean debug = false;
|
||||||
boolean passedMinutesZero = false;
|
boolean passedMinutesZero = false;
|
||||||
if (lb.hasMittagspauseArrived(debug && passedMinutesZero)) {
|
if (lb.couldHaveHadNoMittagspauseYet(debug && passedMinutesZero)) {
|
||||||
handleMittagspause(br, lb);
|
handleMittagspause(br, lb);
|
||||||
lb.showLoadingBar(debug, passedMinutesZero);
|
lb.showLoadingBar(debug, passedMinutesZero);
|
||||||
}
|
}
|
||||||
@@ -71,6 +71,8 @@ public class LoadingBarCliTools {
|
|||||||
|
|
||||||
|
|
||||||
private static void handleMittagspause(BufferedReader br, WorkdayLoadingBar lb) throws IOException {
|
private static void handleMittagspause(BufferedReader br, WorkdayLoadingBar lb) throws IOException {
|
||||||
|
LocalTime vorlaeufigeEndzeit = lb.estimateMittagspause();
|
||||||
|
println("Mittagspause: " + FormatTools.TIME_FORMATTER.format(vorlaeufigeEndzeit));
|
||||||
print("Mittagspause verschieben um (optional): ");
|
print("Mittagspause verschieben um (optional): ");
|
||||||
String mittagspauseOffsetRaw = br.readLine();
|
String mittagspauseOffsetRaw = br.readLine();
|
||||||
if (mittagspauseOffsetRaw != null && !mittagspauseOffsetRaw.isBlank()) {
|
if (mittagspauseOffsetRaw != null && !mittagspauseOffsetRaw.isBlank()) {
|
||||||
@@ -96,8 +98,7 @@ public class LoadingBarCliTools {
|
|||||||
if (mittagspauseDurationRaw != null && !mittagspauseDurationRaw.isBlank()) {
|
if (mittagspauseDurationRaw != null && !mittagspauseDurationRaw.isBlank()) {
|
||||||
mittagspauseDuration = Integer.valueOf(mittagspauseDurationRaw);
|
mittagspauseDuration = Integer.valueOf(mittagspauseDurationRaw);
|
||||||
}
|
}
|
||||||
LocalTime vorlaeufigeEndzeit = lb.getStartTime().plusMinutes(WorkdayLoadingBar.MAX_NUMBER_WORK_MINS)
|
LocalTime vorlaeufigeEndzeit = lb.estimateZapfenstreich(mittagspauseDuration);
|
||||||
.plusMinutes(mittagspauseDuration != null ? mittagspauseDuration : WorkdayLoadingBar.MIN_LUNCH_DURATION);
|
|
||||||
println("Endzeit: " + FormatTools.TIME_FORMATTER.format(vorlaeufigeEndzeit));
|
println("Endzeit: " + FormatTools.TIME_FORMATTER.format(vorlaeufigeEndzeit));
|
||||||
print("Feierabend verschieben um (optional): ");
|
print("Feierabend verschieben um (optional): ");
|
||||||
String zapfenstreichOffsetRaw = br.readLine();
|
String zapfenstreichOffsetRaw = br.readLine();
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
module zeitlaeufer {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user