Weka linear regression doesn't load - java

I've been following this tutorial on how to use WEKA and I have reached a point where my code will not run. I realize that I am using a different version of Weka 3.8 as opposed to 3.6 as shown in the tutorial but I thought I made the necessary changes. I get an error message on the line linearRegression.buildClassifier(dataset); and I don't know why.
Error message:
Jul 19, 2016 10:47:21 AM com.github.fommil.netlib.BLAS <clinit>
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS
Jul 19, 2016 10:47:21 AM com.github.fommil.netlib.BLAS <clinit>
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeRefBLAS
Jul 19, 2016 10:47:21 AM com.github.fommil.netlib.LAPACK <clinit>
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeSystemLAPACK
Jul 19, 2016 10:47:21 AM com.github.fommil.netlib.LAPACK <clinit>
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeRefLAPACK
Code:
// Define each attribute (or column), and give it a numerical column
// number
// Likely, a better design wouldn't require the column number, but
// would instead get it from the index in the container
Attribute a1 = new Attribute("houseSize", 0);
Attribute a2 = new Attribute("lotSize", 1);
Attribute a3 = new Attribute("bedrooms", 2);
Attribute a4 = new Attribute("granite", 3);
Attribute a5 = new Attribute("bathroom", 4);
Attribute a6 = new Attribute("sellingPrice", 5);
// Each element must be added to a FastVector, a custom
// container used in this version of Weka.
// Later versions of Weka corrected this mistake by only
// using an ArrayList
ArrayList<Attribute> attrs = new ArrayList<>();
attrs.add(a1);
attrs.add(a2);
attrs.add(a3);
attrs.add(a4);
attrs.add(a5);
attrs.add(a6);
// Each data instance needs to create an Instance class
// The constructor requires the number of columns that
// will be defined. In this case, this is a good design,
// since you can pass in empty values where they exist.
Instance i1 = new DenseInstance(6);
i1.setValue(a1, 3529);
i1.setValue(a2, 9191);
i1.setValue(a3, 6);
i1.setValue(a4, 0);
i1.setValue(a5, 0);
i1.setValue(a6, 205000);
Instance i2 = new DenseInstance(6);
i1.setValue(a1, 3247);
i1.setValue(a2, 10061);
i1.setValue(a3, 5);
i1.setValue(a4, 1);
i1.setValue(a5, 1);
i1.setValue(a6, 224900);
Instance i3 = new DenseInstance(6);
i1.setValue(a1, 4032);
i1.setValue(a2, 10150);
i1.setValue(a3, 5);
i1.setValue(a4, 0);
i1.setValue(a5, 1);
i1.setValue(a6, 197900);
Instance i4 = new DenseInstance(6);
i1.setValue(a1, 2397);
i1.setValue(a2, 14156);
i1.setValue(a3, 4);
i1.setValue(a4, 1);
i1.setValue(a5, 0);
i1.setValue(a6, 189900);
Instance i5 = new DenseInstance(6);
i1.setValue(a1, 2200);
i1.setValue(a2, 9600);
i1.setValue(a3, 4);
i1.setValue(a4, 0);
i1.setValue(a5, 1);
i1.setValue(a6, 195000);
Instance i6 = new DenseInstance(6);
i1.setValue(a1, 3536);
i1.setValue(a2, 19994);
i1.setValue(a3, 6);
i1.setValue(a4, 1);
i1.setValue(a5, 1);
i1.setValue(a6, 325000);
Instance i7 = new DenseInstance(6);
i1.setValue(a1, 2983);
i1.setValue(a2, 9365);
i1.setValue(a3, 5);
i1.setValue(a4, 0);
i1.setValue(a5, 1);
i1.setValue(a6, 230000);
// Each Instance has to be added to a larger container, the
// Instances class. In the constructor for this class, you
// must give it a name, pass along the Attributes that
// are used in the data set, and the number of
// Instance objects to be added. Again, probably not ideal design
// to require the number of objects to be added in the constructor,
// especially since you can specify 0 here, and then add Instance
// objects, and it will return the correct value later (so in
// other words, you should just pass in '0' here)
Instances dataset = new Instances("housePrices", attrs, 7);
dataset.add(i1);
dataset.add(i2);
dataset.add(i3);
dataset.add(i4);
dataset.add(i5);
dataset.add(i6);
dataset.add(i7);
// In the Instances class, we need to set the column that is
// the output (aka the dependent variable). You should remember
// that some data mining methods are used to predict an output
// variable, and regression is one of them.
dataset.setClassIndex(dataset.numAttributes() - 1);
// Create the LinearRegression model, which is the data mining
// model we're using in this example
linearRegression = new LinearRegression();
try {
// This method does the "magic", and will compute the regression
// model. It takes the entire dataset we've defined to this point
// When this method completes, all our "data mining" will be
// complete
// and it is up to you to get information from the results
linearRegression.buildClassifier(dataset);
} catch (Exception e) {
e.printStackTrace();
}
}

That is not an error, but a warning. Weka cannot find some Linear Algebra Libraries (LAPACK, BLAS) during the startup of your little java app. It does not need them anyway, for the linear regression task of fitting a curve to 7 data points.
(Read this for reference https://github.com/fommil/netlib-java)
To get rid of the message, you can redirect the STDERR output of your program to /dev/null .
Using the Package Manager, I just installed the Weka Package netlibNativeLinux (or try netlibNativeWindows or netlibOSX, whatever), included its jars to the build-path, and got this warning:
Jul 20, 2016 10:20:32 AM com.github.fommil.jni.JniLoader liberalLoad
INFO: successfully loaded /tmp/jniloader5044252696376965086netlib-native_system-linux-x86_64.so
Jul 20, 2016 10:20:32 AM com.github.fommil.jni.JniLoader load
INFO: already loaded netlib-native_system-linux-x86_64.so
I also got the output 219328.35717359098 - just as the tutorial said. Did you forget to include the last lines of codes from the tutorial, especially
System.out.println(myHouseValue);
?

Related

LSTM and Dense layers preprocessing

I am trying to build NN with LSTM and Dense layers.
Me net is:
MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
.seed(123)
.weightInit(WeightInit.XAVIER)
.updater(new Adam(0.1))
.list()
.layer(0, new LSTM.Builder().activation(Activation.TANH).nIn(numInputs).nOut(120).build())
.layer(1, new DenseLayer.Builder().activation(Activation.RELU).nIn(120).nOut(1000).build())
.layer(2, new DenseLayer.Builder().activation(Activation.RELU).nIn(1000).nOut(20).build())
.layer(new OutputLayer.Builder(LossFunction.NEGATIVELOGLIKELIHOOD).activation(Activation.SOFTMAX).nIn(20).nOut(numOutputs).build())
.inputPreProcessor(1, new RnnToFeedForwardPreProcessor())
.build();
I read my data like that:
SequenceRecordReader reader = new CSVSequenceRecordReader(0, ",");
reader.initialize(new NumberedFileInputSplit("TRAIN_%d.csv", 1, 17476));
DataSetIterator trainIter = new SequenceRecordReaderDataSetIterator(reader, miniBatchSize, 6, 7, false);
allData = trainIter.next();
//Load the test/evaluation data:
SequenceRecordReader testReader = new CSVSequenceRecordReader(0, ",");
testReader.initialize(new NumberedFileInputSplit("TEST_%d.csv", 1, 8498));
DataSetIterator testIter = new SequenceRecordReaderDataSetIterator(testReader, miniBatchSize, 6, 7, false);
allData = testIter.next();
So, when its going to net it has shape [batch, features, timestamp] = [32,7,60]
I can define it with special made error like that:
Received input with size(1) = 7 (input array shape = [32, 7, 60]); input.size(1) must match layer nIn size (nIn = 9)
So its normally go to the net. After first LSTM layer it must reshape into 2-D and go throw Dense layer next.
But I have next problem:
Labels and preOutput must have equal shapes: got shapes [32, 6, 60] vs
[1920, 6]
It did not reshape before going into Dense layer and I had missed 1 feature (now shape is 32, 6 , 60 instead of 32, 7 , 60), so why ???
if possible you'll want to use setInputType which will set up the pre processors for you.
Here's an example configuration of lstm to dense:
MultiLayerConfiguration conf1 = new NeuralNetConfiguration.Builder()
.trainingWorkspaceMode(wsm)
.inferenceWorkspaceMode(wsm)
.seed(12345)
.updater(new Adam(0.1))
.list()
.layer(new LSTM.Builder().nIn(3).nOut(3).dataFormat(rnnDataFormat).build())
.layer(new DenseLayer.Builder().nIn(3).nOut(3).activation(Activation.TANH).build())
.layer(new RnnOutputLayer.Builder().nIn(3).nOut(3).activation(Activation.SOFTMAX).dataFormat(rnnDataFormat)
.lossFunction(LossFunctions.LossFunction.MCXENT).build())
.setInputType(InputType.recurrent(3, rnnDataFormat))
.build();
RNN format is:
import org.deeplearning4j.nn.conf.RNNFormat;
This is an enum that specifies what your data format should be (channels last or first)
From the javadoc:
/**
* NCW = "channels first" - arrays of shape [minibatch, channels, width]<br>
* NWC = "channels last" - arrays of shape [minibatch, width, channels]<br>
* "width" corresponds to sequence length and "channels" corresponds to sequence item size.
*/
Source here: https://github.com/eclipse/deeplearning4j/blob/1930d9990810db6214829c716c2ae7eb7f59cd13/deeplearning4j/deeplearning4j-nn/src/main/java/org/deeplearning4j/nn/conf/RNNFormat.java#L21
More here in our tests: https://github.com/eclipse/deeplearning4j/blob/1930d9990810db6214829c716c2ae7eb7f59cd13/deeplearning4j/deeplearning4j-core/src/test/java/org/deeplearning4j/nn/layers/recurrent/TestTimeDistributed.java#L58

How to use DateTime Object split Interval Object

I have an Interval object:
Interval firstInterval =
new Interval(new DateTime(2017,06,26,07,55,30),new DateTime(2017,06,26,22,55,30));
and:
DateTime nightToDay = new DateTime(2017, 06, 26, 8, 0, 0);
DateTime dayToNight = new DateTime(2017, 06, 26, 22, 0, 0);
I want to get a Interval[]:
[
[2017-06-26 07:55:30 ~ 2017-06-26 08:00:00],
[2017-06-26 08:00:00 ~ 2017-06-26 22:00:00],
[2017-06-26 22:00:00 ~ 2017-06-26 22:55:30]
]
Of course, these parameters aren't fixed, and it is just an example.
Assuming that your general case is:
have a first interval with start and end
receives a nightToDay and dayToNight dates
output must contain 3 intervals:
start to nightToDay
nightToDay to dayToNight
dayToNight to end
And for each case above, you also need to check if the start of the interval is before the end.
If that's what you need, just do:
List<Interval> list = new ArrayList<Interval>();
if (firstInterval.getStart().isBefore(nightToDay)) {
list.add(new Interval(firstInterval.getStart(), nightToDay));
}
if (nightToDay.isBefore(dayToNight)) {
list.add(new Interval(nightToDay, dayToNight));
}
if (dayToNight.isBefore(firstInterval.getEnd())) {
list.add(new Interval(dayToNight, firstInterval.getEnd()));
}
The list will contain all the Interval objects you need.
If you need an array, it's easy to convert the list:
Interval[] intervals = new Interval[list.size()];
intervals = list.toArray(intervals);
The intervals array will have all the intervals created.

OpenCV 3.0 svm always predicts 0 (java)

I'm new to opencv's svm's. I tried a sample classifier but it only returns 0 as the predicted label. I even used the value 5 for training as well as the prediction.
I've been changing the values for about a hundred times but i just don't get what's wrong. I'm using OpenCV 3.0 with Java. Here's my code:
Mat labels = new Mat(new Size(1,4),CvType.CV_32SC1);
labels.put(0, 0, 1);
labels.put(1, 0, 1);
labels.put(2, 0, 1);
labels.put(3, 0, 0);
Mat data = new Mat(new Size(1,4),CvType.CV_32FC1);
data.put(0, 0, 5);
data.put(1, 0, 2);
data.put(2, 0, 3);
data.put(3, 0, 8);
Mat testSamples = new Mat(new Size(1,1),CvType.CV_32FC1);
testSamples.put(0,0,5);
SVM svm = SVM.create();
TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER,100,0.1);
svm.setKernel(SVM.LINEAR);
svm.setType(SVM.C_SVC);
svm.setGamma(0.5);
svm.setNu(0.5);
svm.setC(1);
svm.setTermCriteria(criteria);
//data is N x 64 trained data Mat , labels is N x 1 label Mat with integer values;
svm.train(data, Ml.ROW_SAMPLE, labels);
Mat results = new Mat();
int predictedClass = (int) svm.predict(testSamples, results, 0);
Even if i change the lables to 1 and 2, I still get 0.0 as a response. So something has to be absolutely wrong... I just don't know what to do. Please help! :)
I had a similar problem in C++. I'm not too sure if it's the same in Java but in C++ the predictions were saved in the results Matrix instead of returned as a float.

Lotus Notes 8.5 : Create a meeting with java

I started to work with Lotus Notes 8.5, and i have to create meetings in Lotus by using Java, lotus.domino and Notes.jar.
So, to do this, i create a new Document and fill it with all the needed fields (i think). This is how i create my meeting :
Document newDocument = db.createDocument();
newDocument.appendItemValue("Body", "Create meeting from java.");
newDocument.appendItemValue("Notes", "Test Notes");
newDocument.appendItemValue("Chair", "Me");
newDocument.appendItemValue("Principal", "Me");
newDocument.appendItemValue("$altPrincipal", "Me");
newDocument.appendItemValue("ExcludeFromView", "D,S");
newDocument.appendItemValue("UpdateSeq", 1);
newDocument.appendItemValue("$CSVersion", "2");
newDocument.appendItemValue("$SMTPKeepNotesItems", "1");
newDocument.appendItemValue("$CSWISL", "$S:1,$L:1,$B:1,$R:1,$E:1,$W:1,$O:1,$M:1,RequiredAttendees:1,INetRequiredNames:1,AltRequiredNames:1,StorageRequiredNames:1,OptionalAttendees:1,INetOptionalNames:1,AltOptionalNames:1,StorageOptionalNames:1,ApptUNIDURL:1,STUnyteConferenceURL:1,STUnyteConferenceID:1,SametimeType:1,WhiteBoardContent:1,STRoomName:1");
newDocument.appendItemValue("WebDateTimeInit", "1");
newDocument.appendItemValue("OrgTable", "C0");
newDocument.appendItemValue("$AlarmDisabled", "1");
newDocument.appendItemValue("$HFFlags", "1");
newDocument.appendItemValue("Form", "Appointment");
newDocument.appendItemValue("$FromPreferredLanguage", "fr");
newDocument.appendItemValue("ApptUNID", "267DEFCD6ADE4EF8C1257DF600464A1B642");
newDocument.appendItemValue("$LangChair", "");
newDocument.appendItemValue("AppointmentType", "3");
newDocument.appendItemValue("$TableSwitcher", "Description");
newDocument.appendItemValue("OnlineMeeting", "");
newDocument.appendItemValue("From", "Me");
newDocument.appendItemValue("AltChair", "Me");
newDocument.appendItemValue("OnlinePlace", "");
newDocument.appendItemValue("IsBroadcast", "");
newDocument.appendItemValue("$ExpandGroups", 3);
newDocument.appendItemValue("IsTeamCalendar", "");
newDocument.appendItemValue("Importance", "");
newDocument.appendItemValue("OrgConfidential", "");
newDocument.appendItemValue("Subject", "Meeting test from Java");
newDocument.appendItemValue("PreventCounter", "");
newDocument.appendItemValue("Location", "R1");
newDocument.appendItemValue("RoomToReserve", "");
newDocument.appendItemValue("Resources", "");
newDocument.appendItemValue("$PaperColor", 1);
newDocument.appendItemValue("STRecordMeeting", "");
newDocument.appendItemValue("WhiteBoardContent", "");
newDocument.appendItemValue("Categories", "");
newDocument.appendItemValue("$BorderColor", "7F96A3");
newDocument.appendItemValue("$WatchedItems", "$S,$L,$B,$R,$E,$W,$O,$M,RequiredAttendees,INetRequiredNames,AltRequiredNames,StorageRequiredNames,OptionalAttendees,INetOptionalNames,AltOptionalNames,StorageOptionalNames,ApptUNIDURL,STUnyteConferenceURL,STUnyteConferenceID,SametimeType,WhiteBoardContent,STRoomName");
newDocument.appendItemValue("CalForwardChairNotificationTo", "");
newDocument.appendItemValue("ReturnReceipt", "");
newDocument.appendItemValue("PreventDelegate", "");
newDocument.appendItemValue("EnterSendTo", "");
newDocument.appendItemValue("EnterCopyTo", "");
newDocument.appendItemValue("EnterBlindCopyTo", "");
newDocument.appendItemValue("ConferenceCallInfo", "");
newDocument.appendItemValue("SchedulerSwitcher", "1");
newDocument.appendItemValue("$Abstract", "");
newDocument.appendItemValue("StartTimeZone", "Z=-1$DO=1$DL=3 -1 1 10 -1 1$ZN=Western/Central Europe");
newDocument.appendItemValue("EndTimeZone", "Z=-1$DO=1$DL=3 -1 1 10 -1 1$ZN=Western/Central Europe");
newDocument.appendItemValue("NewStartTimeZone", "");
newDocument.appendItemValue("NewEndTimeZone", "");
newDocument.appendItemValue("Encrypt", "Représentation invalide. (undefined)");
newDocument.appendItemValue("Sign", "");
newDocument.appendItemValue("MeetingType", "");
newDocument.appendItemValue("$PublicAccess", "1");
newDocument.appendItemValue("StartDate", "27/02/2015");
newDocument.appendItemValue("StartTime", "11:00:00");
newDocument.appendItemValue("STARTDATETIME", s.createDateTime(new GregorianCalendar(2015, 02, 27, 11, 0, 0)));
newDocument.appendItemValue("EndDate", "27/02/2015");
newDocument.appendItemValue("EndTime", "13:00:00");
newDocument.appendItemValue("EndDateTime", s.createDateTime(new GregorianCalendar(2015, 02, 27, 13, 0, 0)));
newDocument.appendItemValue("CalendarDateTime", s.createDateTime(new GregorianCalendar(2015, 02, 27, 11, 0, 0)));
newDocument.appendItemValue("_ViewIcon", 158);
newDocument.appendItemValue("$ShowComments", "Normal");
newDocument.appendItemValue("$ShowDescription", "Show");
newDocument.appendItemValue("$BusyName", "Me");
newDocument.appendItemValue("$BusyPriority", "1");
newDocument.appendItemValue("SequenceNum", 2);
newDocument.appendItemValue("$CSTrack", "Imported from my contacts at 02/24/2015 14:00:17");
newDocument.appendItemValue("$NoPurge", s.createDateTime(new GregorianCalendar(2015, 02, 27, 13, 0, 0)));
newDocument.appendItemValue("$UpdatedBy", "Me");
newDocument.appendItemValue("$Revisions", s.createDateTime(new GregorianCalendar(2015, 02, 24, 13, 48, 31)));
newDocument.appendItemValue("tmpUseLongDate", s.createDateTime(new GregorianCalendar(2015, 02, 27, 11, 0, 0)));
newDocument.appendItemValue("tmpEventLabel", "Meeting from Java (tmpEventLabel)");
newDocument.appendItemValue("dispRepeatText", "Meeting from Java (dispRepeatText)");
newDocument.appendItemValue("tmpHideTimeZone", "");
newDocument.appendItemValue("tmpStartDate1", "27/02/2015");
newDocument.save();
When i came back to Lotus, the meeting is created and shown in the calendar.
The problem is, whatever field i add or remove, when i click on this meeting, Lotus throw me an error, saying (approximate translation from french):
Field : 'tmpStartDate1' : Temporary data required for operator or # function
So i add this new field in java, launch the program, create a meeting, and...
Field : 'tmpHideTimeZone' : Temporary data required for operator or # function
For now, it is the 5th field Lotus asked me with this message....
All 'tmp******' fields are missing, but i don't know them. I thought those fields could be generated by Lotus, because of the 'tmp', but how ?
I compare with other meetings created with Lotus Notes, and there are no such 'tmp' fields.
Any ideas ?
EDIT :
I tried this :
newDocument.computeWithForm(true, true);
It throws a NotesException if your document isn't in a good format.
When i execute my code (approximate translation again...) :
NotesException: Incorrect data type in the field.
I tried computeWithForm in another program where I create and add a contact to Lotus, and i didn't get any errors.
So indeed, there is a problem with meeting's fields...
EDIT :
Any new ideas ? I am a bit confused about how to develop on this software....
Items have types too ! Also a date is not a string, a date is a complicated animal, looks innocuous at first sight, but can bite very hard.
The Document.appendItemValue method coerces the item to be of Text type.
For date/time (not temporary ;-) items you should use Document.ReplaceItemValueCustomData and pass it an argument of class DateTime.

Date interval sum and subtraction in Java

I'm looking for a library or helper class in Java that would allow me to perform date interval sum and subtractions.
For example, lets's say I have the following date intervals:
A = ["2015-01-01 00:00", "2015-01-20 00:00"]
B = ["2015-01-05 00:00", "2015-01-10 00:00"]
C = ["2015-01-11 00:00", "2015-01-14 00:00"]
D = ["2015-01-19 00:00", "2015-01-25 00:00"]
1 A 20
|----------------------------------|
|---------| |----------| |------------|
5 B 10 11 C 14 19 D 25
And let's say I'd like to calculate the following:
A - B - C + D = { ["2015-01-01 00:00", "2015-01-05 00:00"[,
]"2015-01-10 00:00", "2015-01-11 00:00"[,
]"2015-01-14 00:00", "2015-01-25 00:00"] }
1 5 10 11 14 25
|---| |---| |----------------|
I know I can build my own logic using pure Java, but I'd rather not reinvent the wheel...
I was looking into Joda-Time, but I couldn't figure out how to perform such operations using it.
Thanks a lot!
I found exactly what I needed: Ranges, from the guava-libraries.
Works like this:
Range<Date> a = Range.closed(
new GregorianCalendar(2015, 0, 1).getTime(),
new GregorianCalendar(2015, 0, 20).getTime());
Range<Date> b = Range.closed(
new GregorianCalendar(2015, 0, 5).getTime(),
new GregorianCalendar(2015, 0, 10).getTime());
Range<Date> c = Range.closed(
new GregorianCalendar(2015, 0, 11).getTime(),
new GregorianCalendar(2015, 0, 14).getTime());
Range<Date> d = Range.closed(
new GregorianCalendar(2015, 0, 19).getTime(),
new GregorianCalendar(2015, 0, 25).getTime());
RangeSet<Date> result = TreeRangeSet.create();
result.add(a);
result.remove(b);
result.remove(c);
result.add(d);
System.out.println(result);
The code above prints:
[
[Thu Jan 01 00:00:00 BRST 2015‥Mon Jan 05 00:00:00 BRST 2015),
(Sat Jan 10 00:00:00 BRST 2015‥Sun Jan 11 00:00:00 BRST 2015),
(Wed Jan 14 00:00:00 BRST 2015‥Sun Jan 25 00:00:00 BRST 2015]
]
I think it can be done basically using Joda-Time with some custom code. It is assumed that A is the Interval which all other intervals should relate to.
While this code should give the expected results (and should work for different values accordingly) I highly suggest testing it with very different data, especially for the three cases a) an interval not intersecting A at all, b) intersecting A at the beginning and c) an interval which itself intersects B or C or D.
So despite this, it might help for further tests.
Interval a = new Interval(Instant.parse("2015-01-01T00:00Z"), Instant.parse("2015-01-20T00:00Z"));
List<Interval> l = Arrays.asList(
/* b */ new Interval(Instant.parse("2015-01-05T00:00Z"), Instant.parse("2015-01-10T00:00Z")),
/* c */ new Interval(Instant.parse("2015-01-11T00:00Z"), Instant.parse("2015-01-14T00:00Z")),
/* d */ new Interval(Instant.parse("2015-01-19T00:00Z"), Instant.parse("2015-01-25T00:00Z"))
);
List<Interval> results = new ArrayList<Interval>();
for (Interval i : l) {
if (a.contains(i)) {
// if i is completely inside a, then calculate the first part and the remaining part
// whereas the first part will be added to the result
Interval firstPart = new Interval(a.getStart(), i.getStart());
results.add(firstPart);
// followed by i itself (skipped)
// part after i, inside a
Interval remainingPart = new Interval(i.getEnd(), a.getEnd());
a = remainingPart;
} else if (i.overlaps(a)) {
// if the intervals only overlap, then we take the earliest beginning and the latest ending as a result part
DateTime overlapMin = (a.getStart().isBefore(i.getStart())) ? a.getStart() : i.getStart();
DateTime overlapMax = (a.getEnd().isAfter(i.getEnd())) ? a.getEnd() : i.getEnd();
Interval overlapAndBothParts = new Interval(overlapMin, overlapMax);
results.add(overlapAndBothParts);
// if the checked interval i is at the beginning, then a will become the part after this "overlap"
if (i.getStartMillis() < a.getStartMillis()) {
Interval whatsLeft = new Interval(i.getEndMillis(), a.getEndMillis());
a = whatsLeft;
}
}
}
// print result
for (Interval i : results) {
System.out.println("result part: " + i);
}

Categories

Resources