
package uk.me.mjt.ch;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class CheckOsmRouting {
    private static final RoutingTestCase hatfieldToHerbal = new RoutingTestCase(253199386L,18670884L,2347854,   253199386L,247514L,195441L,868249730L, 18670884L);
    private static final RoutingTestCase tiberiusToLivia = new RoutingTestCase(1224756026L,1224756028L,33305,   1224756026L,1224757149L,1224756484L,1224756195L,1224757082L,1224757091L,1224756028L);
    private static final RoutingTestCase avoidMizenWay = new RoutingTestCase(1651312172L,13853101L,125124,      1651312172L,1651312118L,749962849L,13853101L);
    private static final RoutingTestCase expectedIntoMizenWay = new RoutingTestCase(1651312172L,1647192344L,42253, 1651312172L);
    private static final RoutingTestCase sunlightGardensAvoidGate = new RoutingTestCase(1581223475L,158758984L,155196,     1581223475L,158760624L,158760472L,158758984L);
    private static final RoutingTestCase lemsfordRoadNoRightOrUturn = new RoutingTestCase(672630347L,927070648L,31950,     672630347L,30983954L,243206609L,32953194L,927070648L);
    
    private static final ArrayList<RoutingTestCase> testCases = new ArrayList<RoutingTestCase>() {{
            add(hatfieldToHerbal); // Basic test case - check routing works.
            add(tiberiusToLivia); // Test case for oneway=false
            add(avoidMizenWay); // Test case for avoiding private roads
            add(expectedIntoMizenWay); // Test case for using private roads when required
            add(sunlightGardensAvoidGate); // Test case for not going through gates
            add(lemsfordRoadNoRightOrUturn); // Test case for basic turn restrictions
        }};
    
    public static void checkUncontracted(MapData allNodes) {
        check(allNodes,false);
    }
    public static void checkContracted(MapData allNodes) {
        check(allNodes,true);
    }
        
    private static void check(MapData allNodes, boolean contracted) {
        for (RoutingTestCase tc : testCases) {
            boolean foundNonNull = false;
            
            for (Node from : allNodes.getNodeBySourceDataId(tc.fromNode)) {
                for (Node to : allNodes.getNodeBySourceDataId(tc.toNode)) {
                    DijkstraSolution computed;
                    if (contracted)
                        computed = ContractedDijkstra.contractedGraphDijkstra(allNodes, from, to);
                    else
                        computed = Dijkstra.dijkstrasAlgorithm(from, to, Dijkstra.Direction.FORWARDS);
                    
                    if (computed != null) {
                        foundNonNull = true;
                        compare(tc, computed);
                    }
                }
            }
            
            if (!foundNonNull) {
                compare(tc,null);
            }
        }
    }
    
    private static void compare(RoutingTestCase testCase, DijkstraSolution solution) {
        if (solution == null || testCase.driveTimeMs != solution.totalDriveTimeMs || !testCase.waypointsMet(solution)) {
            String error = "OSM routing check failed for " + testCase;
            if (solution == null) {
                error += " solution was null?!";
            } else {
                if (testCase.driveTimeMs != solution.totalDriveTimeMs) {
                    error += " drive times didn't match - " + testCase.driveTimeMs + " vs " + solution.totalDriveTimeMs + " - and ";
                } else {
                    error += " drive times matched but";
                }
                if (!testCase.waypointsMet(solution)) {
                    error += " waypoints were not all met.";
                    error += " GeoJson:" + GeoJson.solution(solution);
                }
            }                        
            throw new RuntimeException(error);
        } else {
            System.out.println("Checked " + testCase + " OK");
        }
    }
    
    private static class RoutingTestCase {
        private final long fromNode;
        private final long toNode;
        private final int driveTimeMs;
        private final long[] waypoints;

        public RoutingTestCase(long fromNode, long toNode, int driveTimeMs, long... waypoints) {
            this.fromNode = fromNode;
            this.toNode = toNode;
            this.driveTimeMs = driveTimeMs;
            this.waypoints = waypoints;
        }
        
        public String toString() {
            return fromNode + "->" + toNode;
        }
        
        public boolean waypointsMet(DijkstraSolution ds) {
            int lastIdx = -1;
            for (long toFind : waypoints) {
                int thisIdx = ds.nodes.indexOf(toFind);
                if (thisIdx<lastIdx)
                    return false;
                lastIdx = thisIdx;
            }
            return true;
        }
    }
    
}

@@ -49,57 +49,8 @@
 st;%0A
-import java.util.HashMap;%0Aimport java.util.List;%0A
 %0A%0Apu
@@ -2005,79 +2005,31 @@
     
-boolean foundNonNull = false;%0A            %0A            for (
+Colocated
 Node
+Set
  from 
-:
+=
  all
@@ -2064,27 +2064,25 @@
 tc.fromNode)
-) %7B
+;
 %0A           
@@ -2086,26 +2086,29 @@
     
-    for (
+Colocated
 Node
+Set
  to 
-:
+=
  all
@@ -2142,18 +2142,18 @@
 (tc.
-to
+from
 Node)
-) %7B
+;
 %0A   
@@ -2161,24 +2161,27 @@
         
+%0A  
         
 Dijkstra
@@ -2172,16 +2172,19 @@
         
+   
 Dijkstra
@@ -2210,32 +2210,24 @@
             
-        
 if (contract
@@ -2229,25 +2229,19 @@
 tracted)
-%0A        
+ %7B%0A
         
@@ -2339,29 +2339,17 @@
     
-    
-   
+%7D
  else
-%0A        
+ %7B%0A
     
@@ -2455,257 +2455,11 @@
     
-        %0A                    if (computed != null) %7B%0A                        foundNonNull = true;%0A                        compare(tc, computed);%0A                    %7D%0A                %7D%0A            %7D%0A            %0A            if (!foundNonNull) %7B%0A    
+%7D%0A%0A
     
@@ -2484,30 +2484,16 @@
 ,null);%0A
-            %7D%0A
         

Simplify check now that ColocatedNodeSet exists.