diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDay.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDay.java index b33d1e4..b161a41 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDay.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDay.java @@ -6,6 +6,8 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import java.util.Calendar; + /** * @author Robert Vokac * @since 23.02.2024 @@ -19,6 +21,9 @@ public class WorkingDay { private static final String NODATA = "nodata"; + public static String createId(Calendar cal) { + return createId(cal.get(Calendar.YEAR), cal.get((Calendar.MONTH)) + 1, cal.get(Calendar.DAY_OF_MONTH)); + } public static String createId(int year, int month, int day) { return (year + "-" + (month < 10 ? "0" : "") + month + "-" + (day < 10 ? "0" : "") + day); } @@ -40,5 +45,8 @@ public class WorkingDay { public boolean isThisDayTimeOff() { return timeOff || this.note.equals(NODATA); } + public double getArrivalAsDouble() { + return ((double)arrivalHour) + ((double)arrivalMinute / 60d); + } } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDayForStats.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDayForStats.java index 92fcf9d..9275ba3 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDayForStats.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/WorkingDayForStats.java @@ -1,13 +1,19 @@ package org.nanoboot.utils.timecalc.entity; +import lombok.Getter; +import lombok.Setter; +import org.nanoboot.utils.timecalc.app.TimeCalcException; +import org.nanoboot.utils.timecalc.utils.common.TTime; + import java.time.LocalDate; import java.util.ArrayList; import java.util.Calendar; -import lombok.Getter; -import lombok.Setter; - +import java.util.HashMap; +import java.util.HashSet; import java.util.List; -import org.nanoboot.utils.timecalc.utils.common.TTime; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; @Getter @Setter @@ -29,7 +35,107 @@ public class WorkingDayForStats extends WorkingDay { private final TTime departure; public static void fillStatisticsColumns(List list) { - //todo + if(list.isEmpty()) { + //nothing to do + return; + } + Map map = new HashMap<>(); + Set years = new HashSet<>(); + list.forEach(w -> { + if (!years.isEmpty() && !years.contains(w.getYear())) { + throw new TimeCalcException( + "Cannot create statistics, if there are work days for more than one year."); + } + years.add(w.getYear()); + map.put(w.getId(), w); + } + ); + int year = years.stream().findFirst().orElseThrow(() -> new TimeCalcException("Set years is empty.")); + + Calendar cal7DaysAgo = Calendar.getInstance(); + Calendar cal14DaysAgo = Calendar.getInstance(); + Calendar cal28DaysAgo = Calendar.getInstance(); + Calendar cal56DaysAgo = Calendar.getInstance(); + + List list7 = new ArrayList<>(); + List list14 = new ArrayList<>(); + List list28 = new ArrayList<>(); + List list56 = new ArrayList<>(); + for (int month = 1; month <= 12; month++) { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + int dayMaximum = cal.getActualMaximum(Calendar.DAY_OF_MONTH); + for (int day = 1; day <= dayMaximum; day++) { + String id = WorkingDay.createId(year, month, day); + if(!map.containsKey(id)) { + //nothing to do + continue; + } + cal.set(Calendar.DAY_OF_MONTH, day); + cal7DaysAgo.setTime(cal.getTime()); + cal14DaysAgo.setTime(cal.getTime()); + cal28DaysAgo.setTime(cal.getTime()); + cal56DaysAgo.setTime(cal.getTime()); + cal7DaysAgo.add(Calendar.DAY_OF_MONTH, -7); + cal14DaysAgo.add(Calendar.DAY_OF_MONTH, -14); + cal28DaysAgo.add(Calendar.DAY_OF_MONTH, -28); + cal56DaysAgo.add(Calendar.DAY_OF_MONTH, -56); + String id7 = WorkingDay.createId(cal7DaysAgo); + String id14 = WorkingDay.createId(cal14DaysAgo); + String id28 = WorkingDay.createId(cal28DaysAgo); + String id56 = WorkingDay.createId(cal56DaysAgo); + + System.out.println("id7=" + id7); + System.out.println("id14=" + id14); + System.out.println("id28=" + id28); + System.out.println("id56=" + id56); + if (map.containsKey(id7)) { + list7.remove(map.get(id7)); + } + if (map.containsKey(id14)) { + list14.remove(map.get(id14)); + } + if (map.containsKey(id28)) { + list28.remove(map.get(id28)); + } + if (map.containsKey(id56)) { + list56.remove(map.get(id56)); + } + WorkingDayForStats wd = map.get(id); + if(!wd.isThisDayTimeOff()) { + Stream.of(list7, list14, list28, list56).forEach(l -> { + l.add(wd); + }); + } + wd.setArrivalTimeMovingAverage7Days(list7.stream() + .map(WorkingDay::getArrivalAsDouble) + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0)); + wd.setArrivalTimeMovingAverage14Days(list14.stream() + .map(WorkingDay::getArrivalAsDouble) + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0)); + wd.setArrivalTimeMovingAverage28Days(list28.stream() + .map(WorkingDay::getArrivalAsDouble) + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0)); + wd.setArrivalTimeMovingAverage56Days(list56.stream() + .map(WorkingDay::getArrivalAsDouble) + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0)); + System.out.println(WorkingDay.createId(cal) + " 1 :: " + list7.size() ); + System.out.println(WorkingDay.createId(cal) + " 2 :: " + list14.size() ); + System.out.println(WorkingDay.createId(cal) + " 3 :: " + list28.size() ); + System.out.println(WorkingDay.createId(cal) + " 4 :: " + list56.size() ); + } + + } + } public static List createList(List list) { List result = new ArrayList<>(); diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/WorkingDaysWindow.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/WorkingDaysWindow.java index 075340a..6503b6d 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/WorkingDaysWindow.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/WorkingDaysWindow.java @@ -3,7 +3,6 @@ package org.nanoboot.utils.timecalc.swing.common; import java.awt.Color; import java.awt.Dimension; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.List; import javax.swing.JButton; @@ -11,12 +10,12 @@ import javax.swing.JComboBox; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; -import org.nanoboot.utils.timecalc.app.TimeCalcProperty; + import org.nanoboot.utils.timecalc.entity.WorkingDay; import org.nanoboot.utils.timecalc.entity.WorkingDayForStats; import org.nanoboot.utils.timecalc.persistence.api.WorkingDayRepositoryApi; -import static org.nanoboot.utils.timecalc.swing.common.ConfigWindow.CLIENT_PROPERTY_KEY; import org.nanoboot.utils.timecalc.swing.progress.Time; +import org.nanoboot.utils.timecalc.utils.common.NumberFormats; import org.nanoboot.utils.timecalc.utils.common.TTime; /** @@ -29,7 +28,7 @@ public class WorkingDaysWindow extends TWindow { private static final String THREE_DASHES = "---"; // private static final Color RED = new Color(255,153,153); - public static final String E = "?"; + public static final String QUESTION_MARK = "?"; private final WorkingDayRepositoryApi workingDayRepository; private final Time time; @@ -162,28 +161,28 @@ public class WorkingDaysWindow extends TWindow { list2.add(THREE_DASHES); list2.add(wdfs.getNote()); list2.add(wdfs.isTimeOff() ? YES : NO); - list2.add(E); - list2.add(E); - list2.add(E); - list2.add(E); - list2.add(E); + list2.add(QUESTION_MARK); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage7Days() - 7)); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage14Days() - 7)); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage28Days() - 7)); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage56Days() - 7)); } else { list2.add(wdfs.getDayOfWeekAsString()); TTime overtime = new TTime(wdfs.getOvertimeHour(), wdfs.getOvertimeMinute()); list2.add(wdfs.getDayOfWeek() == 6 || wdfs.getDayOfWeek() == 7 ? YES : NO); list2.add(wdfs.getId()); - list2.add(new TTime(wdfs.getArrivalHour(), wdfs.getArrivalMinute()).toString().substring(0, 5)); + list2.add(new TTime(wdfs.getArrivalHour(), wdfs.getArrivalMinute()).toString().substring(0, 5) + " (" + NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalAsDouble())+ ")"); list2.add(new TTime(wdfs.getDepartureHour(), wdfs.getDepartureMinute()).toString().substring(0, 5)); list2.add(overtime.toString().substring(0, overtime.isNegative() ? 6 : 5)); list2.add(TTime.ofMinutes(wdfs.getWorkingTimeInMinutes()).toString().substring(0, 5)); list2.add(TTime.ofMinutes(wdfs.getPauseTimeInMinutes()).toString().substring(0, 5)); list2.add(wdfs.getNote()); list2.add(wdfs.isTimeOff() ? YES : NO); - list2.add(E); - list2.add(E); - list2.add(E); - list2.add(E); - list2.add(E); + list2.add(QUESTION_MARK); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage7Days() - 7)); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage14Days() - 7)); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage28Days() - 7)); + list2.add(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wdfs.getArrivalTimeMovingAverage56Days() - 7)); } }