/***************************************************************************** * Limpet - the Lightweight InforMation ProcEssing Toolkit * http://limpet.info * * (C) 2015-2016, Deep Blue C Technologies Ltd * * This library is free software; you can redistribute it and/or * modify it under the terms of the Eclipse Public License v1.0 * (http://www.eclipse.org/legal/epl-v10.html) * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *****************************************************************************/ package info.limpet.data; import info.limpet.IBaseTemporalCollection; import info.limpet.IChangeListener; import info.limpet.ICollection; import info.limpet.ICommand; import info.limpet.IContext; import info.limpet.IQuantityCollection; import info.limpet.IStore; import info.limpet.IStoreGroup; import info.limpet.IStoreItem; import info.limpet.ITemporalQuantityCollection; import info.limpet.ITemporalQuantityCollection.InterpMethod; import info.limpet.data.csv.CsvParser; import info.limpet.data.impl.MockContext; import info.limpet.data.impl.TemporalObjectCollection; import info.limpet.data.impl.samples.SampleData; import info.limpet.data.impl.samples.StockTypes; import info.limpet.data.impl.samples.StockTypes.NonTemporal; import info.limpet.data.impl.samples.StockTypes.NonTemporal.Location; import info.limpet.data.impl.samples.StockTypes.Temporal; import info.limpet.data.impl.samples.StockTypes.Temporal.SpeedKts; import info.limpet.data.impl.samples.TemporalLocation; import info.limpet.data.operations.CollectionComplianceTests; import info.limpet.data.operations.CollectionComplianceTests.TimePeriod; import info.limpet.data.operations.spatial.DistanceBetweenTracksOperation; import info.limpet.data.operations.spatial.DopplerShiftBetweenTracksOperation; import info.limpet.data.operations.spatial.DopplerShiftBetweenTracksOperation.DSOperation; import info.limpet.data.operations.spatial.DopplerShiftBetweenTracksOperation.DSOperation.TrackProvider; import info.limpet.data.operations.spatial.GenerateCourseAndSpeedOperation; import info.limpet.data.operations.spatial.GeoSupport; import info.limpet.data.operations.spatial.IGeoCalculator; import info.limpet.data.operations.spatial.ProplossBetweenTwoTracksOperation; import info.limpet.data.store.StoreGroup; import java.awt.geom.Point2D; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.measure.converter.ConversionException; import javax.measure.quantity.Frequency; import junit.framework.TestCase; import org.junit.Assert; public class TestGeotoolsGeometry extends TestCase { private IContext context = new MockContext(); public void testCreateTemporalObjectCollection() { TemporalObjectCollection<Point2D> locations = new TemporalObjectCollection<Point2D>("test"); assertNotNull(locations); } public void testGenerateSingleCourse() throws IOException { File file = TestCsvParser.getDataFile("americas_cup/usa.csv"); assertTrue(file.isFile()); CsvParser parser = new CsvParser(); List<IStoreItem> items = parser.parse(file.getAbsolutePath()); assertEquals("correct group", 1, items.size()); StoreGroup group = (StoreGroup) items.get(0); assertEquals("correct num collections", 3, group.size()); ICollection firstColl = (ICollection) group.get(2); assertEquals("correct num rows", 1708, firstColl.getValuesCount()); TemporalLocation track = (TemporalLocation) firstColl; GenerateCourseAndSpeedOperation genny = new GenerateCourseAndSpeedOperation(); List<IStoreItem> sel = new ArrayList<IStoreItem>(); sel.add(track); StoreGroup store = new StoreGroup(); Collection<ICommand<IStoreItem>> ops = genny.actionsFor(sel, store, context); assertNotNull("created command", ops); assertEquals("created operatoins", 2, ops.size()); ICommand<IStoreItem> firstOp = ops.iterator().next(); assertEquals("store empty", 0, store.size()); firstOp.execute(); assertEquals("new coll created", 1, store.size()); ICollection newColl = (ICollection) firstOp.getOutputs().get(0); assertEquals("correct size", firstColl.getValuesCount() - 1, newColl .getValuesCount()); assertNotNull("knows about parent", newColl.getPrecedent()); } public void testGenerateMultipleCourse() throws IOException { File file = TestCsvParser.getDataFile("americas_cup/usa.csv"); assertTrue(file.isFile()); File file2 = TestCsvParser.getDataFile("americas_cup/nzl.csv"); assertTrue(file2.isFile()); CsvParser parser = new CsvParser(); List<IStoreItem> items = parser.parse(file.getAbsolutePath()); assertEquals("correct group", 1, items.size()); StoreGroup group = (StoreGroup) items.get(0); assertEquals("correct num collections", 3, group.size()); ICollection firstColl = (ICollection) group.get(2); assertEquals("correct num rows", 1708, firstColl.getValuesCount()); List<IStoreItem> items2 = parser.parse(file2.getAbsolutePath()); assertEquals("correct group", 1, items2.size()); StoreGroup group2 = (StoreGroup) items2.get(0); assertEquals("correct num collections", 3, group2.size()); ICollection secondColl = (ICollection) group2.get(2); assertEquals("correct num rows", 1708, secondColl.getValuesCount()); TemporalLocation track1 = (TemporalLocation) firstColl; TemporalLocation track2 = (TemporalLocation) secondColl; GenerateCourseAndSpeedOperation genny = new GenerateCourseAndSpeedOperation(); List<IStoreItem> sel = new ArrayList<IStoreItem>(); sel.add(track1); sel.add(track2); StoreGroup store = new StoreGroup(); List<ICommand<IStoreItem>> ops = (List<ICommand<IStoreItem>>) genny.actionsFor(sel, store, context); assertNotNull("created command", ops); assertEquals("created operatoins", 2, ops.size()); ICommand<IStoreItem> courseOp = ops.get(0); assertEquals("store empty", 0, store.size()); courseOp.execute(); assertEquals("new colls created", 2, store.size()); ICollection newColl = (ICollection) courseOp.getOutputs().get(0); assertEquals("correct size", firstColl.getValuesCount() - 1, newColl .getValuesCount()); ICommand<IStoreItem> speedOp = ops.get(1); assertEquals("store empty", 2, store.size()); speedOp.execute(); assertEquals("new colls created", 4, store.size()); newColl = (ICollection) courseOp.getOutputs().get(0); assertEquals("correct size", firstColl.getValuesCount() - 1, newColl .getValuesCount()); } public void testBuilder() { final Location track1 = new StockTypes.NonTemporal.Location("some location data"); IGeoCalculator calc = GeoSupport.getCalculator(); Point2D pos1 = calc.createPoint(-4, 55.8); Point2D pos2 = calc.calculatePoint(pos1, Math.toRadians(54), 0.003); track1.add(pos2); assertEquals("track has point", 1, track1.getValuesCount()); } public void testCreatePoint() { IGeoCalculator builder = GeoSupport.getCalculator(); Point2D point = builder.createPoint(48.44, -123.37); Assert.assertNotNull(point); Point2D point2 = builder.createPoint(48.44, -123.37); Assert.assertNotNull(point2); } public void testRangeCalc() { IGeoCalculator builder = GeoSupport.getCalculator(); Point2D p1 = builder.createPoint(0, 80); Point2D p2 = builder.createPoint(0, 81); Point2D p3 = builder.createPoint(1, 80); final double dest1 = builder.getDistanceBetween(p1, p2); final double dest2 = builder.getDistanceBetween(p1, p3); assertEquals("range 1 right", 111663, dest1, 10); assertEquals("range 2 right", 19393, dest2, 10); } public void testBearingCalc() { IGeoCalculator builder = GeoSupport.getCalculator(); Point2D p1 = builder.createPoint(1, 0); Point2D p2 = builder.createPoint(2, 1); assertEquals("correct result", 45, builder.getAngleBetween(p1, p2), 0.2); } public void testLocationInterp() { TemporalLocation loc1 = new TemporalLocation("loc1"); IGeoCalculator builder = GeoSupport.getCalculator(); loc1.add(1000, builder.createPoint(2, 3)); loc1.add(2000, builder.createPoint(3, 4)); Point2D geo1 = loc1.interpolateValue(1500, InterpMethod.Linear); assertEquals("correct value", 2.5, geo1.getX()); assertEquals("correct value", 3.5, geo1.getY()); geo1 = loc1.interpolateValue(1700, InterpMethod.Linear); assertEquals("correct value", 2.7, geo1.getX()); assertEquals("correct value", 3.7, geo1.getY()); } public void testInterpolatedLocationCalcNonTemporal() { Location loc1 = new Location("loc1"); Location loc2 = new Location("loc2"); Temporal.LengthM len1 = new Temporal.LengthM("dummy2", null); List<IStoreItem> selection = new ArrayList<IStoreItem>(); selection.add(loc1); IStore store = new StoreGroup(); Collection<ICommand<IStoreItem>> ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.add(len1); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.remove(len1); selection.add(loc2); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); // ok, try adding some data IGeoCalculator builder = GeoSupport.getCalculator(); loc1.add(builder.createPoint(4, 3)); loc1.add(builder.createPoint(1, 3)); loc2.add(builder.createPoint(3, 4)); loc2.add(builder.createPoint(2, 4)); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("does work collection", 1, ops.size()); loc2.add(builder.createPoint(2, 1)); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("can't work, since we can't interpolate", 0, ops.size()); } public void testInterpolatedLocationCalcTemporal() { TemporalLocation loc1 = new TemporalLocation("loc1"); TemporalLocation loc2 = new TemporalLocation("loc2"); Temporal.LengthM len1 = new Temporal.LengthM("dummy2", null); List<IStoreItem> selection = new ArrayList<IStoreItem>(); selection.add(loc1); IStore store = new StoreGroup(); Collection<ICommand<IStoreItem>> ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.add(len1); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.remove(len1); selection.add(loc2); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); // ok, try adding some data IGeoCalculator builder = GeoSupport.getCalculator(); loc1.add(1000, builder.createPoint(4, 3)); loc1.add(2000, builder.createPoint(1, 3)); loc2.add(1000, builder.createPoint(3, 4)); loc2.add(2000, builder.createPoint(2, 4)); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("does work collection", 2, ops.size()); loc2.add(3000, builder.createPoint(2, 1)); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("can work, since we can interpolate", 1, ops.size()); // ok, run it, and see how we get on Iterator<ICommand<IStoreItem>> opsIter = ops.iterator(); ICommand<IStoreItem> operation = opsIter.next(); operation.execute(); Iterator<IStoreItem> oIter = operation.getOutputs().iterator(); IStoreItem output = oIter.next(); assertNotNull(output); assertTrue(output instanceof IQuantityCollection<?>); assertTrue("results are temporal", output instanceof ITemporalQuantityCollection<?>); IQuantityCollection<?> iq = (IQuantityCollection<?>) output; assertEquals("correct size", 2, iq.getValuesCount()); } public void testProplossCalc() { TemporalLocation loc1 = new TemporalLocation("loc1"); TemporalLocation loc2 = new TemporalLocation("loc2"); Location loc3 = new Location("loc2"); Temporal.LengthM len1 = new Temporal.LengthM("dummy2", null); List<IStoreItem> selection = new ArrayList<IStoreItem>(); selection.add(loc1); IStore store = new StoreGroup(); Collection<ICommand<IStoreItem>> ops = new ProplossBetweenTwoTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.add(len1); ops = new ProplossBetweenTwoTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.remove(len1); selection.add(loc2); ops = new ProplossBetweenTwoTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); // ok, try adding some data IGeoCalculator builder = GeoSupport.getCalculator(); loc1.add(1000, builder.createPoint(4, 3)); loc1.add(2000, builder.createPoint(3, 4)); loc2.add(1000, builder.createPoint(5, 3)); loc2.add(1500, builder.createPoint(4, 3)); loc3.add(builder.createPoint(2, 2)); ops = new ProplossBetweenTwoTracksOperation().actionsFor(selection, store, context); assertEquals("not empty collection", 2, ops.size()); // make hte series different lengths loc2.add(2000, builder.createPoint(3, 4)); ops = new ProplossBetweenTwoTracksOperation().actionsFor(selection, store, context); assertEquals("not empty collection", 1, ops.size()); // check how it runs ICommand<IStoreItem> thisOp = ops.iterator().next(); thisOp.execute(); IStoreItem thisOut = thisOp.getOutputs().iterator().next(); assertNotNull(thisOut); assertTrue("correct type", thisOut instanceof IQuantityCollection); IQuantityCollection<?> iQ = (IQuantityCollection<?>) thisOut; assertEquals("correct length", 3, iQ.getValuesCount()); // try with a singleton selection.remove(loc2); selection.add(loc3); ops = new ProplossBetweenTwoTracksOperation().actionsFor(selection, store, context); assertEquals("not empty collection", 2, ops.size()); // check how it runs thisOp = ops.iterator().next(); thisOp.execute(); thisOut = thisOp.getOutputs().iterator().next(); assertNotNull(thisOut); assertTrue("correct type", thisOut instanceof IQuantityCollection); iQ = (IQuantityCollection<?>) thisOut; assertEquals("correct length", 2, iQ.getValuesCount()); } public void testLocationCalc() { TemporalLocation loc1 = new TemporalLocation("loc1"); TemporalLocation loc2 = new TemporalLocation("loc2"); Temporal.LengthM len1 = new Temporal.LengthM("dummy2", null); List<IStoreItem> selection = new ArrayList<IStoreItem>(); selection.add(loc1); IStore store = new StoreGroup(); Collection<ICommand<IStoreItem>> ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.add(len1); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); selection.remove(len1); selection.add(loc2); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("empty collection", 0, ops.size()); // ok, try adding some data IGeoCalculator builder = GeoSupport.getCalculator(); loc1.add(1000, builder.createPoint(4, 3)); loc2.add(2000, builder.createPoint(3, 4)); ops = new DistanceBetweenTracksOperation().actionsFor(selection, store, context); assertEquals("not empty collection", 1, ops.size()); } public void testFindingDopplerTracks() { final List<IStoreItem> items = new ArrayList<IStoreItem>(); final DopplerShiftBetweenTracksOperation doppler = new DopplerShiftBetweenTracksOperation(); final StoreGroup store = new StoreGroup(); final CollectionComplianceTests tests = new CollectionComplianceTests(); IContext mockContext = new MockContext(); List<TrackProvider> matches = DopplerShiftBetweenTracksOperation.DSOperation.getTracks( null, items, tests); assertEquals("empty", 0, matches.size()); // create a good track IStore tmpStore = new SampleData().getData(20); IStoreGroup cTrack = (IStoreGroup) tmpStore.get(SampleData.COMPOSITE_ONE); assertNotNull("not found track", cTrack); items.add(cTrack); matches = DopplerShiftBetweenTracksOperation.DSOperation.getTracks( null, items, tests); assertEquals("not empty", 1, matches.size()); // ignore that track matches = DopplerShiftBetweenTracksOperation.DSOperation.getTracks( (IStoreGroup) cTrack, items, tests); assertEquals("empty", 0, matches.size()); // ok, add a singleton location StockTypes.NonTemporal.Location loc1 = (Location) tmpStore.get(SampleData.SINGLETON_LOC_1); assertNotNull("not found track", loc1); items.add(loc1); matches = DopplerShiftBetweenTracksOperation.DSOperation.getTracks( (IStoreGroup) cTrack, items, tests); assertEquals("not empty", 1, matches.size()); IStoreItem loc2 = tmpStore.get(SampleData.SINGLETON_LOC_2); items.add(loc2); matches = DopplerShiftBetweenTracksOperation.DSOperation.getTracks( (IStoreGroup) cTrack, items, tests); assertEquals("not empty", 2, matches.size()); // ok - they work at the top level, see if they work // in a child group items.remove(loc1); items.remove(loc2); // check it's empty matches = DopplerShiftBetweenTracksOperation.DSOperation.getTracks( (IStoreGroup) cTrack, items, tests); assertEquals("empty", 0, matches.size()); IStoreGroup sensors = new StoreGroup("Sensor"); sensors.add(loc1); sensors.add(loc2); items.add(sensors); matches = DopplerShiftBetweenTracksOperation.DSOperation.getTracks( (IStoreGroup) cTrack, items, tests); assertEquals("not empty", 2, matches.size()); // ok, move up a level Collection<ICommand<IStoreItem>> ops = doppler.actionsFor(items, store, mockContext); assertEquals("single action", 0, ops.size()); // ok, give it a top-level sounds speed final IStoreItem soundSpeed = tmpStore.get(SampleData.SPEED_ONE); items.add(soundSpeed); ops = doppler.actionsFor(items, store, mockContext); assertEquals("single action", 1, ops.size()); // ok, we have two static sensors, ets them ICommand<IStoreItem> firstOp = ops.iterator().next(); firstOp.execute(); List<IStoreItem> outputs = firstOp.getOutputs(); assertEquals("two output datasets", 2, outputs.size()); // hmm, ensure we only get updates on tracks that have changed final List<String> messages = new ArrayList<String>(); final IChangeListener listener = new IChangeListener() { @Override public void metadataChanged(IStoreItem subject) { // TODO Auto-generated method stub } @Override public void dataChanged(IStoreItem subject) { messages.add("" + subject.getName()); } @Override public void collectionDeleted(IStoreItem subject) { // TODO Auto-generated method stub } }; Iterator<IStoreItem> iter = outputs.iterator(); while (iter.hasNext()) { IStoreItem iStoreItem = (IStoreItem) iter.next(); iStoreItem.addChangeListener(listener); } // ok, make a change to loc1 loc1.clearQuiet(); loc1.add(new Point2D.Double(22, 33)); loc1.fireDataChanged(); assertEquals("only one update", 1, messages.size()); // restart messages.clear(); // get the freq tmpStore.get(SampleData.FREQ_ONE).fireDataChanged(); assertEquals("both outputs updated", 2, messages.size()); // restart messages.clear(); // get the freq soundSpeed.fireDataChanged(); assertEquals("both outputs updated", 2, messages.size()); // and what if we make the sensors group look like a track? sensors.remove(loc2); sensors.add(tmpStore.get(SampleData.FREQ_ONE)); sensors.add(soundSpeed); ops = doppler.actionsFor(items, store, mockContext); assertEquals("single action", 2, ops.size()); } @SuppressWarnings("unused") public void testDoppler() { // TODO: reinstate me! final ArrayList<IStoreItem> items = new ArrayList<IStoreItem>(); final DopplerShiftBetweenTracksOperation doppler = new DopplerShiftBetweenTracksOperation(); final StoreGroup store = new StoreGroup(); final CollectionComplianceTests tests = new CollectionComplianceTests(); // create datasets TemporalLocation loc1 = new TemporalLocation("loc 1"); TemporalLocation loc2 = new TemporalLocation("loc 2"); NonTemporal.Location loc3 = new NonTemporal.Location("loc 3"); NonTemporal.Location loc4 = new NonTemporal.Location("loc 4"); Temporal.AngleDegrees angD1 = new Temporal.AngleDegrees("ang D 1", null); Temporal.AngleRadians angR2 = new Temporal.AngleRadians("ang R 2", null); NonTemporal.AngleRadians angR3 = new NonTemporal.AngleRadians("ang R 3", null); NonTemporal.AngleDegrees angD4 = new NonTemporal.AngleDegrees("ang D 4", null); Temporal.SpeedKts spdK1 = new Temporal.SpeedKts("speed kts 1", null); Temporal.SpeedMSec spdM2 = new Temporal.SpeedMSec("speed M 2", null); NonTemporal.SpeedKts spdK3 = new NonTemporal.SpeedKts("speed kts 1", null); NonTemporal.SpeedMSec spdM4 = new NonTemporal.SpeedMSec("speed kts 1", null); Temporal.FrequencyHz freq1 = new Temporal.FrequencyHz("freq 1", null); NonTemporal.FrequencyHz freq2 = new NonTemporal.FrequencyHz("freq 2", null); Temporal.SpeedMSec sspdM1 = new Temporal.SpeedMSec("sound speed M 1", null); NonTemporal.SpeedKts sspdK2 = new NonTemporal.SpeedKts("sound speed kts 2", null); IGeoCalculator builder = GeoSupport.getCalculator(); // populate the datasets for (int i = 10000; i <= 90000; i += 5000) { double j = Math.toRadians(i / 1000d); loc1.add(i, builder.createPoint(2 + Math.cos(5 * j) * 5, 4 + Math .sin(6 * j) * 5)); if (i % 2000 == 0) { loc2.add(i, builder.createPoint(4 - Math.cos(3 * j) * 2, 9 - Math .sin(4 * j) * 3)); } if (i % 2000 == 0) { angD1.add(i, 55 + Math.sin(j) * 4); } if (i % 3000 == 0) { angR2.add(i, Math.toRadians(45 + Math.cos(j) * 3)); } if (i % 4000 == 0) { spdK1.add(i, 5 + Math.sin(j) * 2); } if (i % 6000 == 0) { spdM2.add(i, 6 + Math.sin(j) * 2); } if (i % 3000 == 0) { freq1.add(i, 55 + Math.sin(j) * 4); } if (i % 4000 == 0) { sspdM1.add(i, 950 + Math.sin(j) * 4); } } loc3.add(builder.createPoint(4, 9)); loc4.add(builder.createPoint(6, 12)); angR3.add(Math.toRadians(155)); angD4.add(255); freq2.add(55.5); sspdK2.add(400); spdK3.add(4); // check we've got roughly the right amount of data assertEquals("correct items", 17, loc1.getValuesCount()); assertEquals("correct items", 9, loc2.getValuesCount()); assertEquals("correct items", 9, angD1.getValuesCount()); assertEquals("correct items", 6, angR2.getValuesCount()); assertEquals("correct items", 4, spdK1.getValuesCount()); assertEquals("correct items", 3, spdM2.getValuesCount()); assertEquals("correct items", 6, freq1.getValuesCount()); // create some incomplete input data StoreGroup track1 = new StoreGroup("Track 1"); StoreGroup track2 = new StoreGroup("Track 2"); items.add(track1); items.add(track2); assertEquals("empty", 0, doppler.actionsFor(items, store, context).size()); track1.add(loc1); assertEquals("empty", 0, doppler.actionsFor(items, store, context).size()); track1.add(angD1); assertEquals("empty", 0, doppler.actionsFor(items, store, context).size()); assertFalse("valid track", tests.getNumberOfTracks(items) == 1); track1.add(spdK1); assertEquals("empty", 0, doppler.actionsFor(items, store, context).size()); assertTrue("valid track", tests.getNumberOfTracks(items) == 1); // now for track two track2.add(loc2); track2.add(angR2); assertFalse("valid track", tests.getNumberOfTracks(items) == 2); track2.add(spdK3); assertTrue("valid track", tests.getNumberOfTracks(items) == 2); assertEquals("still empty", 0, doppler.actionsFor(items, store, context) .size()); assertEquals("has freq", null, tests.collectionWith(items, Frequency.UNIT .getDimension(), true)); // give one a freq track1.add(freq1); assertEquals("still empty", 0, doppler.actionsFor(items, store, context) .size()); assertEquals("has freq", null, tests.collectionWith(items, Frequency.UNIT .getDimension(), false)); assertNotNull("has freq", tests.collectionWith(items, Frequency.UNIT .getDimension(), true)); assertNotNull("has freq", tests.collectionWith(track1, Frequency.UNIT .getDimension(), true)); assertEquals("has freq", null, tests.collectionWith(track2, Frequency.UNIT .getDimension(), true)); // and now complete dataset (with temporal location) // add the missing sound speed items.add(sspdK2); assertEquals("not empty", 1, doppler.actionsFor(items, store, context) .size()); // and now complete dataset (with one non temporal location) track1.remove(loc1); track1.add(loc3); assertEquals("not empty", 1, doppler.actionsFor(items, store, context) .size()); // try to remove the course/speed for static track = check we still get it // offered. track1.remove(spdK1); assertEquals("not empty", 1, doppler.actionsFor(items, store, context) .size()); track1.remove(angD1); assertEquals("not empty", 1, doppler.actionsFor(items, store, context) .size()); // see if it runs ICommand<IStoreItem> ops = doppler.actionsFor(items, store, context).iterator().next(); ops.execute(); IStoreItem tmpOut = ops.getOutputs().iterator().next(); assertNotNull("received output", tmpOut); // and put them back track1.add(sspdK2); track1.add(angD1); // and now complete dataset (with two non temporal locations) track2.remove(loc2); track2.add(loc4); assertEquals("not empty", 1, doppler.actionsFor(items, store, context) .size()); // back to original type track1.remove(loc3); track1.add(loc1); track2.remove(loc4); track2.add(loc2); assertEquals("not empty", 1, doppler.actionsFor(items, store, context) .size()); // try giving track 2 a frewquency track2.add(freq2); assertEquals("actions for both tracks", 2, doppler.actionsFor(items, store, context).size()); // and remove that freq track2.remove(freq2); assertEquals("actions for just one track", 1, doppler.actionsFor(items, store, context).size()); // quick extra test track1.remove(loc1); assertEquals("empty", 0, doppler.actionsFor(items, store, context).size()); // quick extra test track1.add(loc1); assertEquals("empty", 1, doppler.actionsFor(items, store, context).size()); // ok, now check how the doppler handler organises its data DSOperation op1 = (DSOperation) doppler.actionsFor(items, store, context) .iterator().next(); assertNotNull("found operation", op1); op1.organiseData(); HashMap<String, ICollection> map = op1.getDataMap(); assertEquals("all items", 5, map.size()); // ok, let's try undo redo assertEquals("correct size store", store.size(), 1); op1.execute(); assertEquals("new correct size store", store.size(), 2); op1.undo(); assertEquals("new correct size store", store.size(), 1); op1.redo(); assertEquals("new correct size store", store.size(), 2); op1.undo(); assertEquals("new correct size store", store.size(), 1); op1.redo(); assertEquals("new correct size store", store.size(), 2); } public void testGetOptimalTimes() { CollectionComplianceTests aTests = new CollectionComplianceTests(); Collection<ICollection> items = new ArrayList<ICollection>(); SpeedKts speed1 = new Temporal.SpeedKts("spd1", null); SpeedKts speed2 = new Temporal.SpeedKts("spd2", null); SpeedKts speed3 = new Temporal.SpeedKts("spd3", null); speed1.add(100, 5); speed1.add(120, 5); speed1.add(140, 5); speed1.add(160, 5); speed1.add(180, 5); speed2.add(130, 5); speed2.add(140, 5); speed2.add(141, 5); speed2.add(142, 5); speed2.add(143, 5); speed2.add(145, 5); speed2.add(150, 5); speed2.add(160, 5); speed2.add(230, 5); speed3.add(90, 5); speed3.add(120, 5); speed3.add(160, 5); TimePeriod period = new TimePeriod(120, 180); IBaseTemporalCollection common = aTests.getOptimalTimes(period, items); assertEquals("duh, empty set", null, common); items.add(speed1); period = aTests.getBoundingTime(items); assertEquals("correct period", 100, period.getStartTime()); assertEquals("correct period", 180, period.getEndTime()); common = aTests.getOptimalTimes(period, items); assertNotNull("duh, empty set", common); assertEquals("correct choice", common, speed1); items.add(speed2); common = aTests.getOptimalTimes(period, items); assertNotNull("duh, empty set", common); assertEquals("correct choice", common, speed2); items.add(speed3); common = aTests.getOptimalTimes(period, items); assertNotNull("duh, empty set", common); assertEquals("still correct choice", common, speed2); // step back, test it without the period common = aTests.getOptimalTimes(null, items); assertNotNull("duh, empty set", common); assertEquals("correct choice", common, speed2); } public void testGetCommonTimePeriod() { CollectionComplianceTests aTests = new CollectionComplianceTests(); Collection<ICollection> items = new ArrayList<ICollection>(); SpeedKts speed1 = new Temporal.SpeedKts("spd1", null); SpeedKts speed2 = new Temporal.SpeedKts("spd2", null); SpeedKts speed3 = new Temporal.SpeedKts("spd3", null); speed1.add(100, 5); speed1.add(120, 5); speed1.add(140, 5); speed1.add(160, 5); speed1.add(180, 5); speed2.add(130, 5); speed2.add(230, 5); speed3.add(90, 5); speed3.add(120, 5); speed3.add(160, 5); TimePeriod common = aTests.getBoundingTime(items); assertEquals("duh, empty set", null, common); // ok, now add the items to hte collection items.add(speed1); common = aTests.getBoundingTime(items); assertNotNull("duh, empty set", common); assertEquals("correct times", speed1.start(), common.getStartTime()); assertEquals("correct times", speed1.finish(), common.getEndTime()); items.add(speed2); common = aTests.getBoundingTime(items); assertNotNull("duh, empty set", common); assertEquals("correct times", speed2.start(), common.getStartTime()); assertEquals("correct times", speed1.finish(), common.getEndTime()); items.add(speed3); common = aTests.getBoundingTime(items); assertNotNull("duh, empty set", common); assertEquals("correct times", speed2.start(), common.getStartTime()); assertEquals("correct times", speed3.finish(), common.getEndTime()); } public void testDopplerInterpolation() { final CollectionComplianceTests aTests = new CollectionComplianceTests(); Temporal.SpeedKts sKts = new Temporal.SpeedKts("Speed knots", null); sKts.add(1000, 10); sKts.add(2000, 20); sKts.add(4000, 30); double val = aTests.valueAt(sKts, 1500L, sKts.getUnits()); assertEquals("correct value", 15.0, val); val = aTests.valueAt(sKts, 3000L, sKts.getUnits()); assertEquals("correct value", 25.0, val); // try converting to m_sec val = aTests.valueAt(sKts, 1500L, new Temporal.SpeedMSec().getUnits()); assertEquals("correct value", 7.72, val, 0.01); // try converting to m_sec try { val = aTests.valueAt(sKts, 1500L, new Temporal.AngleDegrees().getUnits()); } catch (ConversionException ce) { assertNotNull("exception thrown", ce); } } }