From cf9d3c077921a8a761509c539a70522b8c0bb901 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Mon, 2 Dec 2013 09:01:31 +0100 Subject: [PATCH] add tests verifying open-routes --- .../core/algorithm/recreate/Inserter.java | 2 - .../TestCalculatesServiceInsertion.java | 5 +- .../core/algorithm/recreate/TestInserter.java | 115 ++ ...LocalActivityInsertionCostsCalculator.java | 42 + ...LevelActivityInsertionCostsCalculator.java | 7 + .../route/VehicleRouteBuilderTest.java | 65 +- ...ckups_and_deliveries_solomon_r101_open.xml | 1236 +++++++++++++++++ 7 files changed, 1461 insertions(+), 11 deletions(-) create mode 100644 jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestLocalActivityInsertionCostsCalculator.java create mode 100644 jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestRouteLevelActivityInsertionCostsCalculator.java create mode 100644 jsprit-examples/input/pickups_and_deliveries_solomon_r101_open.xml diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java index 9ea0f15f..61422bb3 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java @@ -72,7 +72,6 @@ class Inserter { } private void setEndLocation(VehicleRoute route, Service service) { - route.getEnd().setCoordinate(service.getCoord()); route.getEnd().setLocationId(service.getLocationId()); } @@ -106,7 +105,6 @@ class Inserter { } private void setEndLocation(VehicleRoute route, Shipment shipment) { - route.getEnd().setCoordinate(shipment.getDeliveryCoord()); route.getEnd().setLocationId(shipment.getDeliveryLocation()); } diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java index c634b076..72e9f6c0 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java @@ -267,9 +267,6 @@ public class TestCalculatesServiceInsertion { assertEquals(2, iData.getDeliveryInsertionIndex()); } - @Test - public void whenInsertingAndRouteIsOpen(){ - assertTrue(false); - } + } diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java index 20e28113..a9887a1b 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java @@ -1,7 +1,122 @@ package jsprit.core.algorithm.recreate; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import jsprit.core.algorithm.recreate.listener.InsertionListeners; +import jsprit.core.problem.driver.Driver; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.job.Shipment; +import jsprit.core.problem.solution.route.VehicleRoute; +import jsprit.core.problem.vehicle.Vehicle; + +import org.junit.Test; + public class TestInserter { + @Test + public void whenInsertingServiceAndRouteIsClosed_itInsertsCorrectly(){ + Service service = mock(Service.class); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + when(vehicle.isReturnToDepot()).thenReturn(true); + when(vehicle.getId()).thenReturn("vehId"); + + VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addService(service).build(); + //start - pick(shipment) - del(shipment) - end + Service serviceToInsert = mock(Service.class); + when(serviceToInsert.getLocationId()).thenReturn("delLoc"); + + InsertionData iData = mock(InsertionData.class); + when(iData.getDeliveryInsertionIndex()).thenReturn(1); + when(iData.getSelectedVehicle()).thenReturn(vehicle); + + Inserter inserter = new Inserter(mock(InsertionListeners.class)); + inserter.insertJob(serviceToInsert, iData, route); + + assertEquals(2,route.getTourActivities().getActivities().size()); + assertEquals(route.getTourActivities().getActivities().get(1).getLocationId(),serviceToInsert.getLocationId()); + assertEquals(route.getEnd().getLocationId(),vehicle.getLocationId()); + } + + @Test + public void whenInsertingServiceAndRouteIsOpen_itInsertsCorrectlyAndSwitchesEndLocation(){ + Service service = mock(Service.class); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + when(vehicle.isReturnToDepot()).thenReturn(false); + when(vehicle.getId()).thenReturn("vehId"); + + VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addService(service).build(); + Service serviceToInsert = mock(Service.class); + when(serviceToInsert.getLocationId()).thenReturn("delLoc"); + + InsertionData iData = mock(InsertionData.class); + when(iData.getDeliveryInsertionIndex()).thenReturn(1); + when(iData.getSelectedVehicle()).thenReturn(vehicle); + + Inserter inserter = new Inserter(mock(InsertionListeners.class)); + inserter.insertJob(serviceToInsert, iData, route); + + assertEquals(2,route.getTourActivities().getActivities().size()); + assertEquals(route.getTourActivities().getActivities().get(1).getLocationId(),serviceToInsert.getLocationId()); + assertEquals(route.getEnd().getLocationId(),serviceToInsert.getLocationId()); + } + + + @Test + public void whenInsertingShipmentAndRouteIsClosed_itInsertsCorrectly(){ + Shipment shipment = mock(Shipment.class); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + when(vehicle.isReturnToDepot()).thenReturn(true); + when(vehicle.getId()).thenReturn("vehId"); + + VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addPickup(shipment).addDelivery(shipment).build(); + //start - pick(shipment) - del(shipment) - end + Shipment shipmentToInsert = mock(Shipment.class); + when(shipmentToInsert.getDeliveryLocation()).thenReturn("delLoc"); + when(shipmentToInsert.getPickupLocation()).thenReturn("pickLoc"); + InsertionData iData = mock(InsertionData.class); + when(iData.getPickupInsertionIndex()).thenReturn(2); + when(iData.getDeliveryInsertionIndex()).thenReturn(2); + when(iData.getSelectedVehicle()).thenReturn(vehicle); + + Inserter inserter = new Inserter(mock(InsertionListeners.class)); + inserter.insertJob(shipmentToInsert, iData, route); + + assertEquals(4,route.getTourActivities().getActivities().size()); + assertEquals(route.getTourActivities().getActivities().get(2).getLocationId(),shipmentToInsert.getPickupLocation()); + assertEquals(route.getTourActivities().getActivities().get(3).getLocationId(),shipmentToInsert.getDeliveryLocation()); + assertEquals(route.getEnd().getLocationId(),vehicle.getLocationId()); + } + + @Test + public void whenInsertingShipmentAndRouteIsOpen_itInsertsCorrectlyAndSwitchesEndLocation(){ + Shipment shipment = mock(Shipment.class); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + when(vehicle.isReturnToDepot()).thenReturn(false); + when(vehicle.getId()).thenReturn("vehId"); + + VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addPickup(shipment).addDelivery(shipment).build(); + //start - pick(shipment) - del(shipment) - end + Shipment shipmentToInsert = mock(Shipment.class); + when(shipmentToInsert.getDeliveryLocation()).thenReturn("delLoc"); + when(shipmentToInsert.getPickupLocation()).thenReturn("pickLoc"); + InsertionData iData = mock(InsertionData.class); + when(iData.getPickupInsertionIndex()).thenReturn(2); + when(iData.getDeliveryInsertionIndex()).thenReturn(2); + when(iData.getSelectedVehicle()).thenReturn(vehicle); + + Inserter inserter = new Inserter(mock(InsertionListeners.class)); + inserter.insertJob(shipmentToInsert, iData, route); + + assertEquals(4,route.getTourActivities().getActivities().size()); + assertEquals(route.getTourActivities().getActivities().get(2).getLocationId(),shipmentToInsert.getPickupLocation()); + assertEquals(route.getTourActivities().getActivities().get(3).getLocationId(),shipmentToInsert.getDeliveryLocation()); + assertEquals(route.getEnd().getLocationId(),shipmentToInsert.getDeliveryLocation()); + } } diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestLocalActivityInsertionCostsCalculator.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestLocalActivityInsertionCostsCalculator.java new file mode 100644 index 00000000..824a04ce --- /dev/null +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestLocalActivityInsertionCostsCalculator.java @@ -0,0 +1,42 @@ +package jsprit.core.algorithm.recreate; + +import static org.mockito.Mockito.mock; +import jsprit.core.problem.cost.VehicleRoutingActivityCosts; +import jsprit.core.problem.cost.VehicleRoutingTransportCosts; + +import org.junit.Before; +import org.junit.Test; + +public class TestLocalActivityInsertionCostsCalculator { + + VehicleRoutingTransportCosts tpCosts; + + VehicleRoutingActivityCosts actCosts; + + LocalActivityInsertionCostsCalculator calc; + + @Before + public void doBefore(){ + tpCosts = mock(VehicleRoutingTransportCosts.class); + actCosts = mock(VehicleRoutingActivityCosts.class); + calc = new LocalActivityInsertionCostsCalculator(tpCosts, actCosts); + } + + @Test + public void whenInsertingActBetweenTwoRouteActs_itCalcsMarginalTpCosts(){ + VehicleRoutingTransportCosts tpCosts = mock(VehicleRoutingTransportCosts.class); + VehicleRoutingActivityCosts actCosts = mock(VehicleRoutingActivityCosts.class); + + LocalActivityInsertionCostsCalculator calc = new LocalActivityInsertionCostsCalculator(tpCosts, actCosts); + } + + @Test + public void whenInsertingActBeforeEndANDRouteIsOpen_itReturnsTransportCostsToLastAct(){ + + } + + @Test + public void whenInsertingActBeforeEndANDRouteIsClosed_itReturnsMarginalTpCosts(){ + + } +} diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestRouteLevelActivityInsertionCostsCalculator.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestRouteLevelActivityInsertionCostsCalculator.java new file mode 100644 index 00000000..55d4d9a1 --- /dev/null +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestRouteLevelActivityInsertionCostsCalculator.java @@ -0,0 +1,7 @@ +package jsprit.core.algorithm.recreate; + +public class TestRouteLevelActivityInsertionCostsCalculator { + + + +} diff --git a/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java b/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java index 5d998aaa..3a584e17 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java @@ -1,8 +1,8 @@ package jsprit.core.problem.solution.route; -import static org.junit.Assert.*; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import jsprit.core.problem.driver.Driver; import jsprit.core.problem.job.Shipment; import jsprit.core.problem.vehicle.Vehicle; @@ -60,18 +60,73 @@ public class VehicleRouteBuilderTest { } @Test - public void whenBuildingOpenRoute(){ - assertTrue(false); + public void whenBuildingClosedRoute_routeEndShouldHaveLocationOfVehicle(){ + Shipment s = mock(Shipment.class); + Shipment s2 = mock(Shipment.class); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.isReturnToDepot()).thenReturn(true); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)); + builder.addPickup(s); + builder.addPickup(s2); + builder.addDelivery(s); + builder.addDelivery(s2); + VehicleRoute route = builder.build(); + assertEquals(route.getEnd().getLocationId(), vehicle.getLocationId()); + } + + @Test + public void whenBuildingOpenRoute_routeEndShouldHaveLocationOfLastActivity(){ + Shipment s = mock(Shipment.class); + Shipment s2 = mock(Shipment.class); + when(s2.getDeliveryLocation()).thenReturn("delLoc"); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.isReturnToDepot()).thenReturn(false); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)); + builder.addPickup(s); + builder.addPickup(s2); + builder.addDelivery(s); + builder.addDelivery(s2); + VehicleRoute route = builder.build(); + assertEquals(route.getEnd().getLocationId(), s2.getDeliveryLocation()); } @Test public void whenSettingDepartureTime(){ - assertTrue(false); + Shipment s = mock(Shipment.class); + Shipment s2 = mock(Shipment.class); + when(s2.getDeliveryLocation()).thenReturn("delLoc"); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.isReturnToDepot()).thenReturn(false); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)); + builder.addPickup(s); + builder.addPickup(s2); + builder.addDelivery(s); + builder.addDelivery(s2); + builder.setDepartureTime(100); + VehicleRoute route = builder.build(); + assertEquals(100.0,route.getDepartureTime(),0.01); + assertEquals(100.0,route.getStart().getEndTime(),0.01); } @Test public void whenSettingEndTime(){ - assertTrue(false); + Shipment s = mock(Shipment.class); + Shipment s2 = mock(Shipment.class); + when(s2.getDeliveryLocation()).thenReturn("delLoc"); + Vehicle vehicle = mock(Vehicle.class); + when(vehicle.isReturnToDepot()).thenReturn(false); + when(vehicle.getLocationId()).thenReturn("vehLoc"); + VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)); + builder.addPickup(s); + builder.addPickup(s2); + builder.addDelivery(s); + builder.addDelivery(s2); + builder.setRouteEndArrivalTime(100.0); + VehicleRoute route = builder.build(); + assertEquals(100.0,route.getEnd().getArrTime(),0.01); } } diff --git a/jsprit-examples/input/pickups_and_deliveries_solomon_r101_open.xml b/jsprit-examples/input/pickups_and_deliveries_solomon_r101_open.xml new file mode 100644 index 00000000..758cfab0 --- /dev/null +++ b/jsprit-examples/input/pickups_and_deliveries_solomon_r101_open.xml @@ -0,0 +1,1236 @@ + + + + INFINITE + HOMOGENEOUS + + + + solomonVehicle + solomonType + + 0 + + + + 0.0 + 230.0 + + false + + + + + solomonType + 200 + + 100.0 + 1.0 + + + + + + + [x=63.0][y=65.0] + + 8 + 10.0 + + + 143.0 + 153.0 + + + + + [x=2.0][y=60.0] + + 5 + 10.0 + + + 41.0 + 51.0 + + + + + [x=53.0][y=52.0] + + 11 + 10.0 + + + 37.0 + 47.0 + + + + + [x=65.0][y=55.0] + + 14 + 10.0 + + + 117.0 + 127.0 + + + + + [x=60.0][y=12.0] + + 31 + 10.0 + + + 44.0 + 54.0 + + + + + [x=20.0][y=20.0] + + 8 + 10.0 + + + 134.0 + 144.0 + + + + + [x=5.0][y=5.0] + + 16 + 10.0 + + + 83.0 + 93.0 + + + + + [x=23.0][y=3.0] + + 7 + 10.0 + + + 132.0 + 142.0 + + + + + [x=24.0][y=12.0] + + 5 + 10.0 + + + 31.0 + 41.0 + + + + + [x=42.0][y=7.0] + + 5 + 10.0 + + + 97.0 + 107.0 + + + + + [x=40.0][y=25.0] + + 9 + 10.0 + + + 85.0 + 95.0 + + + + + [x=45.0][y=10.0] + + 18 + 10.0 + + + 97.0 + 107.0 + + + + + [x=55.0][y=5.0] + + 29 + 10.0 + + + 68.0 + 78.0 + + + + + [x=65.0][y=35.0] + + 3 + 10.0 + + + 153.0 + 163.0 + + + + + [x=65.0][y=20.0] + + 6 + 10.0 + + + 172.0 + 182.0 + + + + + [x=45.0][y=30.0] + + 17 + 10.0 + + + 132.0 + 142.0 + + + + + [x=35.0][y=40.0] + + 16 + 10.0 + + + 37.0 + 47.0 + + + + + [x=41.0][y=37.0] + + 16 + 10.0 + + + 39.0 + 49.0 + + + + + [x=64.0][y=42.0] + + 9 + 10.0 + + + 63.0 + 73.0 + + + + + [x=55.0][y=45.0] + + 13 + 10.0 + + + 116.0 + 126.0 + + + + + [x=35.0][y=17.0] + + 7 + 10.0 + + + 50.0 + 60.0 + + + + + [x=41.0][y=49.0] + + 10 + 10.0 + + + 161.0 + 171.0 + + + + + [x=40.0][y=60.0] + + 21 + 10.0 + + + 71.0 + 81.0 + + + + + [x=20.0][y=50.0] + + 5 + 10.0 + + + 81.0 + 91.0 + + + + + [x=25.0][y=30.0] + + 3 + 10.0 + + + 99.0 + 109.0 + + + + + [x=15.0][y=30.0] + + 26 + 10.0 + + + 34.0 + 44.0 + + + + + [x=35.0][y=69.0] + + 23 + 10.0 + + + 141.0 + 151.0 + + + + + [x=55.0][y=20.0] + + 19 + 10.0 + + + 149.0 + 159.0 + + + + + [x=31.0][y=52.0] + + 27 + 10.0 + + + 50.0 + 60.0 + + + + + [x=55.0][y=60.0] + + 16 + 10.0 + + + 97.0 + 107.0 + + + + + [x=10.0][y=43.0] + + 9 + 10.0 + + + 95.0 + 105.0 + + + + + [x=15.0][y=60.0] + + 17 + 10.0 + + + 76.0 + 86.0 + + + + + [x=5.0][y=30.0] + + 2 + 10.0 + + + 157.0 + 167.0 + + + + + [x=20.0][y=40.0] + + 12 + 10.0 + + + 87.0 + 97.0 + + + + + [x=30.0][y=5.0] + + 8 + 10.0 + + + 61.0 + 71.0 + + + + + [x=10.0][y=20.0] + + 19 + 10.0 + + + 75.0 + 85.0 + + + + + [x=30.0][y=25.0] + + 23 + 10.0 + + + 159.0 + 169.0 + + + + + [x=15.0][y=10.0] + + 20 + 10.0 + + + 32.0 + 42.0 + + + + + [x=20.0][y=65.0] + + 12 + 10.0 + + + 67.0 + 77.0 + + + + + [x=50.0][y=35.0] + + 19 + 10.0 + + + 63.0 + 73.0 + + + + + [x=45.0][y=20.0] + + 11 + 10.0 + + + 62.0 + 72.0 + + + + + [x=45.0][y=65.0] + + 9 + 10.0 + + + 126.0 + 136.0 + + + + + [x=20.0][y=26.0] + + 9 + 10.0 + + + 83.0 + 93.0 + + + + + [x=18.0][y=18.0] + + 17 + 10.0 + + + 185.0 + 195.0 + + + + + [x=19.0][y=21.0] + + 10 + 10.0 + + + 58.0 + 68.0 + + + + + [x=25.0][y=21.0] + + 12 + 10.0 + + + 133.0 + 143.0 + + + + + [x=22.0][y=27.0] + + 11 + 10.0 + + + 135.0 + 145.0 + + + + + [x=25.0][y=24.0] + + 20 + 10.0 + + + 39.0 + 49.0 + + + + + [x=26.0][y=27.0] + + 27 + 10.0 + + + 100.0 + 110.0 + + + + + [x=18.0][y=24.0] + + 22 + 10.0 + + + 188.0 + 198.0 + + + + + [x=22.0][y=22.0] + + 2 + 10.0 + + + 18.0 + 28.0 + + + + + [x=15.0][y=19.0] + + 1 + 10.0 + + + 160.0 + 170.0 + + + + + [x=31.0][y=67.0] + + 3 + 10.0 + + + 95.0 + 105.0 + + + + + [x=30.0][y=60.0] + + 16 + 10.0 + + + 124.0 + 134.0 + + + + + [x=26.0][y=52.0] + + 9 + 10.0 + + + 74.0 + 84.0 + + + + + [x=26.0][y=35.0] + + 15 + 10.0 + + + 176.0 + 186.0 + + + + + [x=57.0][y=48.0] + + 23 + 10.0 + + + 92.0 + 102.0 + + + + + [x=61.0][y=52.0] + + 3 + 10.0 + + + 96.0 + 106.0 + + + + + [x=53.0][y=43.0] + + 14 + 10.0 + + + 179.0 + 189.0 + + + + + [x=15.0][y=47.0] + + 16 + 10.0 + + + 55.0 + 65.0 + + + + + [x=14.0][y=37.0] + + 11 + 10.0 + + + 44.0 + 54.0 + + + + + [x=56.0][y=37.0] + + 6 + 10.0 + + + 182.0 + 192.0 + + + + + [x=55.0][y=54.0] + + 26 + 10.0 + + + 94.0 + 104.0 + + + + + [x=4.0][y=18.0] + + 35 + 10.0 + + + 94.0 + 104.0 + + + + + [x=28.0][y=18.0] + + 26 + 10.0 + + + 93.0 + 103.0 + + + + + [x=11.0][y=31.0] + + 7 + 10.0 + + + 101.0 + 111.0 + + + + + [x=16.0][y=22.0] + + 41 + 10.0 + + + 91.0 + 101.0 + + + + + [x=67.0][y=5.0] + + 25 + 10.0 + + + 83.0 + 93.0 + + + + + [x=49.0][y=73.0] + + 25 + 10.0 + + + 127.0 + 137.0 + + + + + [x=37.0][y=47.0] + + 6 + 10.0 + + + 50.0 + 60.0 + + + + + [x=56.0][y=39.0] + + 36 + 10.0 + + + 142.0 + 152.0 + + + + + [x=37.0][y=56.0] + + 5 + 10.0 + + + 182.0 + 192.0 + + + + + [x=57.0][y=68.0] + + 15 + 10.0 + + + 77.0 + 87.0 + + + + + [x=47.0][y=16.0] + + 25 + 10.0 + + + 35.0 + 45.0 + + + + + [x=44.0][y=17.0] + + 9 + 10.0 + + + 78.0 + 88.0 + + + + + [x=46.0][y=13.0] + + 8 + 10.0 + + + 149.0 + 159.0 + + + + + [x=49.0][y=11.0] + + 18 + 10.0 + + + 69.0 + 79.0 + + + + + [x=49.0][y=42.0] + + 13 + 10.0 + + + 73.0 + 83.0 + + + + + [x=21.0][y=24.0] + + 28 + 10.0 + + + 18.0 + 28.0 + + + + + [x=36.0][y=26.0] + + 18 + 10.0 + + + 200.0 + 210.0 + + + + + [x=32.0][y=12.0] + + 7 + 10.0 + + + 101.0 + 111.0 + + + + + [x=53.0][y=12.0] + + 6 + 10.0 + + + 130.0 + 140.0 + + + + + [x=63.0][y=23.0] + + 2 + 10.0 + + + 136.0 + 146.0 + + + + + [x=15.0][y=77.0] + + 9 + 10.0 + + + 73.0 + 83.0 + + + + + [x=62.0][y=77.0] + + 20 + 10.0 + + + 51.0 + 61.0 + + + + + [x=24.0][y=58.0] + + 19 + 10.0 + + + 58.0 + 68.0 + + + + + [x=27.0][y=69.0] + + 10 + 10.0 + + + 34.0 + 44.0 + + + + + [x=17.0][y=34.0] + + 3 + 10.0 + + + 162.0 + 172.0 + + + + + [x=12.0][y=24.0] + + 13 + 10.0 + + + 76.0 + 86.0 + + + + + [x=6.0][y=68.0] + + 30 + 10.0 + + + 108.0 + 118.0 + + + + + [x=13.0][y=52.0] + + 36 + 10.0 + + + 165.0 + 175.0 + + + + + [x=6.0][y=38.0] + + 16 + 10.0 + + + 32.0 + 42.0 + + + + + [x=11.0][y=14.0] + + 18 + 10.0 + + + 69.0 + 79.0 + + + + + [x=8.0][y=56.0] + + 27 + 10.0 + + + 51.0 + 61.0 + + + + + [x=2.0][y=48.0] + + 1 + 10.0 + + + 117.0 + 127.0 + + + + + [x=49.0][y=58.0] + + 10 + 10.0 + + + 88.0 + 98.0 + + + + + [x=27.0][y=43.0] + + 9 + 10.0 + + + 52.0 + 62.0 + + + + + [x=37.0][y=31.0] + + 14 + 10.0 + + + 95.0 + 105.0 + + + + + [x=57.0][y=29.0] + + 18 + 10.0 + + + 140.0 + 150.0 + + + + + [x=47.0][y=47.0] + + 13 + 10.0 + + + 124.0 + 134.0 + + + + +