[Lada-commits] [PATCH 08 of 10] Generalize generation of Proben for (multiples of) months
Wald Commits
scm-commit at wald.intevation.org
Thu Sep 29 16:54:49 CEST 2016
# HG changeset patch
# User Tom Gottfried <tom at intevation.de>
# Date 1475158538 -7200
# Node ID 8ec6a2a3117199107314d87b8a9452a3333cc426
# Parent 7788a805a98df8214a96bc1d2fc0aa9a87bc6ecf
Generalize generation of Proben for (multiples of) months.
diff -r 7788a805a98d -r 8ec6a2a31171 src/main/java/de/intevation/lada/factory/ProbeFactory.java
--- a/src/main/java/de/intevation/lada/factory/ProbeFactory.java Tue Sep 27 16:16:31 2016 +0200
+++ b/src/main/java/de/intevation/lada/factory/ProbeFactory.java Thu Sep 29 16:15:38 2016 +0200
@@ -12,6 +12,7 @@
import java.util.Calendar;
import java.util.Date;
import java.util.List;
+import java.util.Hashtable;
import javax.inject.Inject;
@@ -44,6 +45,143 @@
*/
public class ProbeFactory {
+ private static Hashtable<String, int[]> fieldsTable;
+
+ public ProbeFactory() {
+ int[] M = { Calendar.MONTH, Calendar.DAY_OF_MONTH, 1 };
+ int[] Q = { Calendar.MONTH, Calendar.DAY_OF_MONTH, 3 };
+ int[] H = { Calendar.MONTH, Calendar.DAY_OF_MONTH, 6 };
+
+ this.fieldsTable = new Hashtable<String, int[]>();
+
+ this.fieldsTable.put("M", M);
+ this.fieldsTable.put("Q", Q);
+ this.fieldsTable.put("H", H);
+ }
+
+ private class Intervall {
+ private int teilVon;
+ private int teilBis;
+ private int offset;
+
+ private int intervallField;
+ private int subIntField;
+ private int intervallFactor;
+
+ private Calendar from;
+
+ public Intervall(
+ Messprogramm messprogramm,
+ Calendar start
+ ) {
+ this.teilVon = messprogramm.getTeilintervallVon();
+ this.teilBis = messprogramm.getTeilintervallBis();
+ this.offset = messprogramm.getIntervallOffset();
+
+ this.intervallField = fieldsTable
+ .get(messprogramm.getProbenintervall())[0];
+ this.subIntField = fieldsTable
+ .get(messprogramm.getProbenintervall())[1];
+ this.intervallFactor = fieldsTable
+ .get(messprogramm.getProbenintervall())[2];
+
+ /* Align with beginning of next interval
+ * like first day of next quarter.*/
+ // TODO: Avoid overflow e.g. into next quarter, if e.g. teilBis
+ // greater than sum of actual maxima of months in quarter.
+ int startIntField = start.get(intervallField);
+ this.from = (Calendar)start.clone();
+ from.set(
+ intervallField,
+ startIntField + startIntField % intervallFactor
+ );
+ from = adjustSubIntField(from, teilVon);
+ if (start.after(from)) {
+ // to next intervall if start not at first day of intervall
+ this.roll();
+ }
+ }
+
+ /**
+ * Return given calendar adjusted to start of intervall (e.g. first
+ * day in quarter) plus offset and given amount of days.
+ *
+ * @param cal Calendar to be adjusted
+ * @param int amount of days to be added (plus offset)
+ *
+ * @return the adjusted Calendar object.
+ */
+ private Calendar adjustSubIntField(Calendar cal, int teil) {
+ int intField = cal.get(intervallField);
+ cal.set(
+ intervallField,
+ intField - intField % intervallFactor
+ );
+ cal.set(subIntField, offset + Math.min(teil, getDuration()));
+ return cal;
+ }
+
+ /**
+ * Get sum of actual maxima for given field from actual field value
+ * for the next factor values of iterField.
+ *
+ * @param calendar Time to start from
+ *
+ * @return the sum of maxima for the field values specified with
+ * field and factor.
+ */
+ private int getDuration() {
+ logger.debug("## calculate maximum ##");
+ int duration = 0;
+ Calendar tmp = (Calendar)from.clone();
+ /* reset to beginning of intervall, e.g. first day of quarter
+ * to compensate possible overflow if
+ * teilVon > maximum of intervallField: */
+ int fromIntField = from.get(intervallField);
+ tmp.set(
+ intervallField,
+ fromIntField - fromIntField % intervallFactor
+ );
+ tmp.set(subIntField, tmp.getActualMinimum(subIntField));
+ logger.debug(tmp);
+ for (int i = 0; i < intervallFactor; i++) {
+ logger.debug(tmp.getActualMaximum(subIntField));
+ duration += tmp.getActualMaximum(subIntField);
+ tmp.add(intervallField, 1);
+ }
+ logger.debug(duration);
+ return duration;
+ }
+
+ public Date getFrom() {
+ logger.debug("getFrom() from: " + from);
+ return from.getTime();
+ }
+
+ public Date getTo() {
+ logger.debug("getTo() from: " + from);
+ Calendar to = (Calendar)from.clone();
+ to = adjustSubIntField(to, teilBis);
+ return to.getTime();
+ }
+
+ public boolean startInLeapYear() {
+ return from.getActualMaximum(Calendar.DAY_OF_YEAR) > 364;
+ }
+
+ public int getStartDOY() {
+ return from.get(Calendar.DAY_OF_YEAR);
+ }
+
+ public void roll() {
+ from.add(intervallField, intervallFactor);
+ from = adjustSubIntField(from, teilVon);
+ }
+
+ }
+ // end Intervall class
+
+
@Inject Logger logger;
/**
@@ -80,20 +218,11 @@
start.setTimeInMillis(from);
Calendar end = Calendar.getInstance();
end.setTimeInMillis(to);
+
List<LProbe> proben = new ArrayList<LProbe>();
-
- if ("M".equals(messprogramm.getProbenintervall())) {
- Calendar realStart = getStart ("M", start);
- proben.addAll(generateMonth(messprogramm, realStart, end));
- }
- else if ("Q".equals(messprogramm.getProbenintervall())) {
- Calendar realStart = getStart ("Q", start);
- proben.addAll(generateQuarter(messprogramm, realStart, end));
- }
- else if ("H".equals(messprogramm.getProbenintervall())) {
- Calendar realStart = getStart ("H", start);
- proben.addAll(generateHalf(messprogramm, realStart, end));
+ if (fieldsTable.keySet().contains(messprogramm.getProbenintervall())) {
+ proben.addAll(generateMonthly(messprogramm, start, end));
}
else {
Date[][] intervals = calculateIntervals(start, end, messprogramm);
@@ -161,44 +290,28 @@
}
}
- private List<LProbe> generateMonth(
+ private List<LProbe> generateMonthly(
Messprogramm messprogramm,
Calendar start,
Calendar end
) {
+ logger.debug("start: " + start);
+
int gueltigVon = messprogramm.getGueltigVon();
int gueltigBis = messprogramm.getGueltigBis();
- int offset = messprogramm.getIntervallOffset();
- int teilVon = messprogramm.getTeilintervallVon();
- int teilBis = messprogramm.getTeilintervallBis();
-
List<LProbe> proben = new ArrayList<LProbe>();
- // Create template Calendars to be recomputed/adapted to actual
- // maxima/minima of fields.
- Calendar initSolldatumBeginn = (Calendar)start.clone();
- initSolldatumBeginn.set(Calendar.DAY_OF_MONTH, offset + teilVon);
- Calendar initSolldatumEnde = (Calendar)start.clone();
- initSolldatumEnde.set(Calendar.DAY_OF_MONTH, offset + teilBis);
-
- // Initialize solldatum values for Probe objects, i.e. trigger
- // recomputation of Calendar fields.
- Calendar solldatumBeginn = (Calendar)initSolldatumBeginn.clone();
- Calendar solldatumEnde = (Calendar)initSolldatumEnde.clone();
- solldatumBeginn.add(Calendar.MONTH, 0);
- solldatumEnde.add(Calendar.MONTH, 0);
-
- for (int monthCount = 1; solldatumBeginn.before(end); monthCount++) {
+ for (Intervall intervall = new Intervall(messprogramm, start);
+ intervall.getFrom().before(end.getTime());
+ intervall.roll()
+ ) {
/* Leap year adaption of validity period.
* It is assumed here (and should be enforced by the data model)
* that gueltigVon and gueltigBis are always given relative to
* a non-leap year. E.g. a value of 59 is assumed to denote
* March 1 and thus has to be adapted in a leap year. */
- int leapDay =
- solldatumBeginn.getActualMaximum(Calendar.DAY_OF_YEAR) > 364
- ? 1
- : 0;
+ int leapDay = intervall.startInLeapYear() ? 1 : 0;
int actualGueltigVon =
gueltigVon > 58
? gueltigVon + leapDay
@@ -208,7 +321,7 @@
? gueltigBis + leapDay
: gueltigBis;
- int solldatumBeginnDOY = solldatumBeginn.get(Calendar.DAY_OF_YEAR);
+ int solldatumBeginnDOY = intervall.getStartDOY();
if ((
// Validity within one year
@@ -224,113 +337,16 @@
) {
LProbe probe = createObjects(
messprogramm,
- solldatumBeginn.getTime(),
- solldatumEnde.getTime()
+ intervall.getFrom(),
+ intervall.getTo()
);
if (probe != null) {
proben.add(probe);
}
+ } else {
+ logger.debug(solldatumBeginnDOY + " not within validity "
+ + actualGueltigVon + " to " + actualGueltigBis);
}
-
- // Reset solldatumBeginn to align DAY_OF_MONTH with initial value
- solldatumBeginn = (Calendar)initSolldatumBeginn.clone();
- solldatumEnde = (Calendar)initSolldatumEnde.clone();
-
- // Move to next month.
- // This may change DAY_OF_MONTH due to actual maximum.
- solldatumBeginn.add(Calendar.MONTH, monthCount);
- solldatumEnde.add(Calendar.MONTH, monthCount);
- }
-
- return proben;
- }
-
- private List<LProbe> generateQuarter(
- Messprogramm messprogramm,
- Calendar start,
- Calendar end
- ) {
- int offset = messprogramm.getIntervallOffset();
- int teilVon = messprogramm.getTeilintervallVon() - 1;
- int teilBis = messprogramm.getTeilintervallBis();
- int manualDuration = teilBis - teilVon;
-
- List<LProbe> proben = new ArrayList<LProbe>();
-
- int currentLength = getDurationQuarter(start);
- if (manualDuration > 0) {
- currentLength = manualDuration;
- }
- Calendar quarterStart = (Calendar)start.clone();
- Calendar quarterEnd = Calendar.getInstance();
- quarterStart.add(Calendar.DAY_OF_YEAR, offset + teilVon);
- quarterEnd.setTime(start.getTime());
- quarterEnd.add(Calendar.DAY_OF_YEAR, currentLength);
- for (;quarterStart.before(end);) {
- int startDOY = quarterStart.get(Calendar.DAY_OF_YEAR);
- if (startDOY > messprogramm.getGueltigVon()
- && startDOY < messprogramm.getGueltigBis()) {
- LProbe probe = createObjects(
- messprogramm,
- quarterStart.getTime(),
- quarterEnd.getTime()
- );
- if (probe != null) {
- proben.add(probe);
- }
- }
- quarterStart.set(Calendar.DAY_OF_MONTH, 2);
- quarterStart = getStart("Q", quarterStart);
- quarterStart.add(Calendar.DAY_OF_YEAR, offset + teilVon);
- if (manualDuration <= 0) {
- currentLength = getDurationQuarter(quarterStart);
- }
- quarterEnd.setTime(quarterStart.getTime());
- quarterEnd.add(Calendar.DAY_OF_YEAR, currentLength);
- }
-
- return proben;
- }
-
- private List<LProbe> generateHalf(
- Messprogramm messprogramm,
- Calendar start,
- Calendar end
- ) {
- int offset = messprogramm.getIntervallOffset();
- int teilVon = messprogramm.getTeilintervallVon() - 1;
- int teilBis = messprogramm.getTeilintervallBis();
- int manualDuration = teilBis - teilVon;
-
- List<LProbe> proben = new ArrayList<LProbe>();
-
- int currentLength = getDurationHalf(start);
- if (manualDuration > 0) {
- currentLength = manualDuration;
- }
- Calendar halfStart = (Calendar)start.clone();
- Calendar halfEnd = Calendar.getInstance();
- halfStart.add(Calendar.DAY_OF_YEAR, offset + teilVon);
- halfEnd.setTime(halfStart.getTime());
- halfEnd.add(Calendar.DAY_OF_YEAR, currentLength);
- for (;halfStart.before(end);) {
- int startDOY = halfStart.get(Calendar.DAY_OF_YEAR);
- if (startDOY > messprogramm.getGueltigVon()
- && startDOY < messprogramm.getGueltigBis()) {
- LProbe probe = createObjects(
- messprogramm, halfStart.getTime(), halfEnd.getTime());
- if (probe != null) {
- proben.add(probe);
- }
- }
- halfStart.set(Calendar.DAY_OF_MONTH, 2);
- halfStart = getStart("H", halfStart);
- halfStart.add(Calendar.DAY_OF_YEAR, offset + teilVon);
- if (manualDuration <= 0) {
- currentLength = getDurationHalf(halfStart);
- }
- halfEnd.setTime(halfStart.getTime());
- halfEnd.add(Calendar.DAY_OF_YEAR, currentLength);
}
return proben;
@@ -368,97 +384,6 @@
return proben;
}
- private int getDurationMonth(Calendar month) {
- return month.getActualMaximum(Calendar.DAY_OF_MONTH);
- }
-
- private int getDurationQuarter(Calendar month) {
- if ((month.get(Calendar.MONTH)) % 3 != 0) {
- logger.debug("not a valid month!");
- return 91; // Fallback to not generate to much probe objects.
- }
- int duration = 0;
- Calendar tmp = (Calendar)month.clone();
- for (int i = 0; i < 3; i++) {
- duration += tmp.getActualMaximum(Calendar.DAY_OF_MONTH);
- tmp.set(Calendar.MONTH, tmp.get(Calendar.MONTH) + 1);
- }
- return duration;
- }
-
- private int getDurationHalf(Calendar month) {
- if ((month.get(Calendar.MONTH)) % 6 != 0) {
- logger.debug("not a valid month!");
- return 183; // Fallback to not generate to much probe objects.
- }
- int duration = 0;
- Calendar tmp = (Calendar)month.clone();
- for (int i = 0; i < 6; i++) {
- duration += tmp.getActualMaximum(Calendar.DAY_OF_MONTH);
- tmp.set(Calendar.MONTH, tmp.get(Calendar.MONTH) + 1);
- }
- return duration - 1;
- }
-
- private Calendar getStart(String interval, Calendar date) {
- Calendar start = Calendar.getInstance();
- start.setTime(date.getTime());
- if ("M".equals(interval)) {
- if (start.get(Calendar.DAY_OF_MONTH) > 1) {
- int month = start.get(Calendar.MONTH) + 1;
- start.set(Calendar.MONTH, month);
- start.set(Calendar.DAY_OF_MONTH, 1);
- }
- }
- else if ("Q".equals(interval)) {
- int month = start.get(Calendar.MONTH); /* 0 through 11 */
- int quarter = (month / 3) + 1;
- Calendar tmp = (Calendar)start.clone();
- logger.debug("in " + quarter + ". quarter");
-
- tmp.set(Calendar.MONTH, (quarter * 3));
- logger.debug("its the " + tmp.get(Calendar.MONTH) + ". month");
- tmp.set(Calendar.DAY_OF_MONTH, 1);
- int firstDayOfQuarter = tmp.get(Calendar.DAY_OF_YEAR);
- if (start.get(Calendar.DAY_OF_YEAR) > firstDayOfQuarter) {
- if (quarter < 4) {
- start.set(Calendar.MONTH, (quarter + 1) * 3 - 2);
- start.set(Calendar.DAY_OF_MONTH, 1);
- }
- else {
- // Next year...
- start.set(Calendar.MONTH, 0);
- start.set(Calendar.YEAR, start.get(Calendar.YEAR) + 1);
- start.set(Calendar.DAY_OF_MONTH, 1);
- }
- }
- else {
- start = (Calendar)tmp.clone();
- }
- }
- else if ("H".equals(interval)) {
- int month = start.get(Calendar.MONTH);
- int half = (month / 6) + 1;
- Calendar tmp = (Calendar)start.clone();
- tmp.set(Calendar.MONTH, half * 6 - 6);
- tmp.set(Calendar.DAY_OF_MONTH, 1);
- int firstDayOfHalf = tmp.get(Calendar.DAY_OF_YEAR);
- if (start.get(Calendar.DAY_OF_YEAR) > firstDayOfHalf) {
- if (half == 1) {
- start.set(Calendar.MONTH, (half + 1) * 6 - 6);
- start.set(Calendar.DAY_OF_MONTH, 1);
- }
- else {
- // Next year...
- start.set(Calendar.MONTH, 0);
- start.set(Calendar.YEAR, start.get(Calendar.YEAR) + 1);
- start.set(Calendar.DAY_OF_MONTH, 1);
- }
- }
- }
- return start;
- }
-
private Calendar getMonday(Calendar week) {
if (week.get(Calendar.DAY_OF_WEEK) > 1) {
week.set(Calendar.WEEK_OF_YEAR,
@@ -651,43 +576,6 @@
return intervals;
}
- /**
- * Parse an interval string.
- * Posible values are: J, H, Q, M, W4, W2, W, T
- *
- * @param interval the interval string.
- *
- * @return the amount of days for the given interval.
- */
- private int parseInterval(String interval) {
- if ("J".equals(interval)) {
- return 365;
- }
- else if ("H".equals(interval)) {
- return 183;
- }
- else if ("Q".equals(interval)) {
- return 91;
- }
- else if ("M".equals(interval)) {
- return 30;
- }
- else if ("W4".equals(interval)) {
- return 28;
- }
- else if ("W2".equals(interval)) {
- return 14;
- }
- else if ("W".equals(interval)) {
- return 7;
- }
- else if ("T".equals(interval)) {
- return 1;
- }
- else {
- return 0;
- }
- }
/**
* Search for the umwelt id using the 'deskriptor'.
@@ -737,6 +625,7 @@
return messprogramm;
}
+
/**
* Find the umwelt id for a given deskriptor.
*
More information about the Lada-commits
mailing list