Compare commits
22 commits
master
...
suspectsca
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c7b5f2b5de | ||
![]() |
be1ef91a0c | ||
![]() |
3d81c7938f | ||
![]() |
b81ebca103 | ||
![]() |
2c6617f99a | ||
![]() |
8ee4f57375 | ||
![]() |
448b1db2a2 | ||
![]() |
761feb4ac7 | ||
![]() |
ff31300a6a | ||
![]() |
0fe6773536 | ||
![]() |
02520733cc | ||
![]() |
aecb3f3707 | ||
![]() |
10931da3a7 | ||
![]() |
7881952682 | ||
![]() |
313def7f7c | ||
![]() |
17aba8d04d | ||
![]() |
bacc956ac2 | ||
![]() |
971a5e904b | ||
![]() |
230765106e | ||
![]() |
1f358b3d48 | ||
![]() |
e5d8bd9bf4 | ||
![]() |
e6601b9a61 |
11 changed files with 605 additions and 89 deletions
|
@ -287,8 +287,23 @@ abstract class OsmPath implements OsmLinkHolder
|
|||
}
|
||||
if ( !hasPositive && ( hasAnyPositive || hasNegative ) )
|
||||
{
|
||||
cost = -1;
|
||||
return;
|
||||
if ( rc.considerTurnRestrictions && !detailMode )
|
||||
{
|
||||
cost = -1;
|
||||
return;
|
||||
}
|
||||
if ( !rc.considerTurnRestrictions && detailMode ) // detect effective (=suspect) TRs
|
||||
{
|
||||
if ( rc.suspectTRs != null && priorityclassifier > 20 && cost > 2000 && cost < rc.maxcost - 2000 )
|
||||
{
|
||||
Long id = Long.valueOf( sourceNode.getIdFromPos() );
|
||||
if ( rc.suspectTRs.get( id ) == null )
|
||||
{
|
||||
System.out.println( "bad TR candidate: " + id );
|
||||
rc.suspectTRs.put( id, Integer.valueOf( priorityclassifier ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,8 +387,12 @@ abstract class OsmPath implements OsmLinkHolder
|
|||
double elevation = ele2 == Short.MIN_VALUE ? 100. : ele2/4.;
|
||||
|
||||
double sectionCost = processWaySection( rc, dist, delta_h, elevation, angle, cosangle, isStartpoint, nsection, lastpriorityclassifier );
|
||||
if ( ( sectionCost < 0. || costfactor > 9998. && !detailMode ) || sectionCost + cost >= 2000000000. )
|
||||
if ( ( sectionCost < 0. || costfactor > 9996. && !detailMode ) || sectionCost + cost >= 2000000000. )
|
||||
{
|
||||
if ( ( costfactor == 9998. && priorityclassifier == lastpriorityclassifier ) || costfactor == 9997. )
|
||||
{
|
||||
rc.foundWayBlock = Math.max( rc.foundWayBlock, priorityclassifier );
|
||||
}
|
||||
cost = -1;
|
||||
return;
|
||||
}
|
||||
|
@ -462,6 +481,17 @@ abstract class OsmPath implements OsmLinkHolder
|
|||
double targetCost = processTargetNode( rc );
|
||||
if ( targetCost < 0. || targetCost + cost >= 2000000000. )
|
||||
{
|
||||
if ( rc.suspectNodes != null && priorityclassifier > 20 && rc.inverseDirection == rc.inverseRouting )
|
||||
{
|
||||
rc.foundNodeBlock = true;
|
||||
Long id = Long.valueOf( targetNode.getIdFromPos() );
|
||||
Integer val = rc.suspectNodes.get( id );
|
||||
if ( val == null || priorityclassifier > val.intValue() )
|
||||
{
|
||||
rc.suspectNodes.put( id, Integer.valueOf( priorityclassifier ) );
|
||||
}
|
||||
}
|
||||
|
||||
cost = -1;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package btools.router;
|
|||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -35,6 +36,13 @@ public final class RoutingContext
|
|||
|
||||
public String rawTrackPath;
|
||||
|
||||
public Map<Long,Integer> suspectNodes;
|
||||
public Map<Long,Integer> suspectTRs;
|
||||
public boolean foundNodeBlock;
|
||||
public int foundWayBlock;
|
||||
|
||||
public int maxcost;
|
||||
|
||||
public String getProfileName()
|
||||
{
|
||||
String name = localFunction == null ? "unknown" : localFunction;
|
||||
|
@ -57,7 +65,7 @@ public final class RoutingContext
|
|||
public int uphillcutoff;
|
||||
public boolean carMode;
|
||||
public boolean bikeMode;
|
||||
public boolean considerTurnRestrictions;
|
||||
public boolean considerTurnRestrictions = true;
|
||||
public boolean processUnusedTags;
|
||||
public boolean forceSecondaryData;
|
||||
public double pass1coefficient;
|
||||
|
@ -131,7 +139,7 @@ public final class RoutingContext
|
|||
bikeMode = 0.f != expctxGlobal.getVariableValue( "validForBikes", 0.f );
|
||||
|
||||
// turn-restrictions used per default for car profiles
|
||||
considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue( "considerTurnRestrictions", carMode ? 1.f : 0.f );
|
||||
considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue( "considerTurnRestrictions", carMode && considerTurnRestrictions ? 1.f : 0.f );
|
||||
|
||||
// process tags not used in the profile (to have them in the data-tab)
|
||||
processUnusedTags = 0.f != expctxGlobal.getVariableValue( "processUnusedTags", 0.f );
|
||||
|
@ -161,7 +169,7 @@ public final class RoutingContext
|
|||
trafficSourceMinDist = expctxGlobal.getVariableValue( "trafficSourceMinDist", 3000.f );
|
||||
|
||||
showspeed = 0.f != expctxGlobal.getVariableValue( "showspeed", 0.f );
|
||||
inverseRouting = 0.f != expctxGlobal.getVariableValue( "inverseRouting", 0.f );
|
||||
inverseRouting = 0.f != expctxGlobal.getVariableValue( "inverseRouting", inverseRouting ? 1.f : 0.f );
|
||||
|
||||
int tiMode = (int)expctxGlobal.getVariableValue( "turnInstructionMode", 0.f );
|
||||
if ( tiMode != 1 ) // automatic selection from coordinate source
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.io.Writer;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import btools.mapaccess.NodesCache;
|
||||
import btools.mapaccess.OsmLink;
|
||||
|
@ -279,16 +280,43 @@ public class RoutingEngine extends Thread
|
|||
|
||||
|
||||
public void doSearch()
|
||||
{
|
||||
doSearch(0);
|
||||
}
|
||||
|
||||
public void doSearch( int radius )
|
||||
{
|
||||
try
|
||||
{
|
||||
MatchedWaypoint seedPoint = new MatchedWaypoint();
|
||||
seedPoint.waypoint = waypoints.get(0);
|
||||
List<MatchedWaypoint> listOne = new ArrayList<MatchedWaypoint>();
|
||||
listOne.add( seedPoint );
|
||||
matchWaypointsToNodes( listOne );
|
||||
List<MatchedWaypoint> wpList = new ArrayList<MatchedWaypoint>();
|
||||
for( OsmNodeNamed wp : waypoints )
|
||||
{
|
||||
MatchedWaypoint seedPoint = new MatchedWaypoint();
|
||||
seedPoint.waypoint = wp;
|
||||
wpList.add( seedPoint );
|
||||
}
|
||||
|
||||
findTrack( "seededSearch", seedPoint, null, null, null, false );
|
||||
resetCache( false );
|
||||
nodesCache.waypointMatcher = new WaypointMatcherImpl( wpList, 250., islandNodePairs );
|
||||
for( MatchedWaypoint mwp : wpList )
|
||||
{
|
||||
preloadPosition( mwp.waypoint );
|
||||
}
|
||||
|
||||
for( MatchedWaypoint mwp : wpList )
|
||||
{
|
||||
if ( mwp.crosspoint != null )
|
||||
{
|
||||
if ( radius > 0 )
|
||||
{
|
||||
boundary = new SearchBoundary( mwp.waypoint, radius, 0 );
|
||||
routingContext.inverseRouting = !routingContext.inverseRouting; // hack
|
||||
routingContext.inverseDirection = routingContext.inverseRouting;
|
||||
}
|
||||
MAXNODES_ISLAND_CHECK = -1;
|
||||
findTrack( "seededSearch", mwp, null, null, null, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( IllegalArgumentException e)
|
||||
{
|
||||
|
@ -978,6 +1006,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
|
||||
routingContext.firstPrePath = null;
|
||||
routingContext.maxcost = maxTotalCost;
|
||||
|
||||
for( OsmLink link = currentNode.firstlink; link != null; link = link.getNext( currentNode) )
|
||||
{
|
||||
|
@ -1004,28 +1033,35 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
int nPathPossible = 0;
|
||||
routingContext.foundNodeBlock = false;
|
||||
routingContext.foundWayBlock = 0;
|
||||
|
||||
for( OsmLink link = currentNode.firstlink; link != null; link = link.getNext( currentNode) )
|
||||
{
|
||||
OsmNode nextNode = link.getTarget( currentNode );
|
||||
|
||||
if ( ! nodesCache.obtainNonHollowNode( nextNode ) )
|
||||
{
|
||||
nPathPossible++;
|
||||
continue; // border node?
|
||||
}
|
||||
if ( nextNode.firstlink == null )
|
||||
{
|
||||
continue; // don't care about dead ends
|
||||
}
|
||||
if ( nextNode == sourceNode )
|
||||
{
|
||||
continue; // border node?
|
||||
}
|
||||
if ( nextNode.firstlink == null )
|
||||
{
|
||||
nPathPossible++;
|
||||
continue; // don't care about dead ends
|
||||
}
|
||||
|
||||
if ( guideTrack != null )
|
||||
{
|
||||
int gidx = path.treedepth + 1;
|
||||
if ( gidx >= guideTrack.nodes.size() )
|
||||
{
|
||||
nPathPossible++;
|
||||
continue;
|
||||
}
|
||||
OsmPathElement guideNode = guideTrack.nodes.get( routingContext.inverseRouting ? guideTrack.nodes.size() - 1 - gidx : gidx );
|
||||
|
@ -1035,11 +1071,14 @@ public class RoutingEngine extends Thread
|
|||
// not along the guide-track, discard, but register for voice-hint processing
|
||||
if ( routingContext.turnInstructionMode > 0 )
|
||||
{
|
||||
Map<Long,Integer> trSuspects = routingContext.suspectTRs;
|
||||
routingContext.suspectTRs = null;
|
||||
OsmPath detour = routingContext.createPath( path, link, refTrack, true );
|
||||
if ( detour.cost >= 0. && nextId != startNodeId1 && nextId != startNodeId2 )
|
||||
{
|
||||
guideTrack.registerDetourForId( currentNode.getIdFromPos(), OsmPathElement.create( detour, false ) );
|
||||
}
|
||||
routingContext.suspectTRs = trSuspects;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1080,6 +1119,8 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
if ( bestPath != null )
|
||||
{
|
||||
nPathPossible++;
|
||||
|
||||
boolean trafficSim = endPos == null;
|
||||
|
||||
bestPath.airdistance = trafficSim ? keepPathAirdistance : ( isFinalLink ? 0 : nextNode.calcDistance( endPos ) );
|
||||
|
@ -1116,6 +1157,29 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
// report oneway dead-ends as suspects
|
||||
if ( routingContext.suspectNodes != null && path.priorityclassifier > 20 && currentNode.virgin && path.cost > 2000 && routingContext.inverseDirection == routingContext.inverseRouting && guideTrack == null )
|
||||
{
|
||||
int suspectPrio = 0;
|
||||
if ( nPathPossible == 0 && (!routingContext.foundNodeBlock) )
|
||||
{
|
||||
suspectPrio = path.priorityclassifier;
|
||||
}
|
||||
else if ( routingContext.foundWayBlock != 0 )
|
||||
{
|
||||
suspectPrio = routingContext.foundWayBlock;
|
||||
}
|
||||
if ( suspectPrio > 20 )
|
||||
{
|
||||
Long id = Long.valueOf( currentNode.getIdFromPos() );
|
||||
Integer val = routingContext.suspectNodes.get( id );
|
||||
if ( val == null || suspectPrio > val.intValue() )
|
||||
{
|
||||
routingContext.suspectNodes.put( id, Integer.valueOf( suspectPrio ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path.unregisterUpTree( routingContext );
|
||||
}
|
||||
|
||||
|
@ -1214,7 +1278,7 @@ public class RoutingEngine extends Thread
|
|||
track.buildMap();
|
||||
|
||||
// for final track..
|
||||
if ( guideTrack != null )
|
||||
if ( guideTrack != null && routingContext.turnInstructionMode > 0 )
|
||||
{
|
||||
track.copyDetours( guideTrack );
|
||||
track.processVoiceHints( routingContext );
|
||||
|
|
|
@ -40,6 +40,8 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
public boolean virgin = true;
|
||||
|
||||
public OsmNode()
|
||||
{
|
||||
}
|
||||
|
@ -107,9 +109,9 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||
double l4 = l2 * l2;
|
||||
double coslat = 1. - l2 + l4 / 6.;
|
||||
|
||||
double dlat = ( ilat - p.getILat() ) / 1000000.;
|
||||
double dlon = ( ilon - p.getILon() ) / 1000000. * coslat;
|
||||
double d = Math.sqrt( dlat * dlat + dlon * dlon ) * 110984.; // 6378000. / 57.3;
|
||||
double dlat = ( ilat - p.getILat() );
|
||||
double dlon = ( ilon - p.getILon() ) * coslat;
|
||||
double d = Math.sqrt( dlat * dlat + dlon * dlon ) * 0.110984; // 6378000. / 57.3;
|
||||
return (int) ( d + 1.0 );
|
||||
}
|
||||
|
||||
|
@ -232,6 +234,8 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||
|
||||
public final void unlinkLink( OsmLink link )
|
||||
{
|
||||
virgin = false;
|
||||
|
||||
OsmLink n = link.clear( this );
|
||||
|
||||
if ( link == firstlink )
|
||||
|
|
|
@ -51,7 +51,7 @@ public class Area
|
|||
{
|
||||
for( int j=0; j<neglist.size(); j++)
|
||||
{
|
||||
if ( neglist.get(i).isInPolygon( id ) )
|
||||
if ( neglist.get(j).isInPolygon( id ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ public class BRouter
|
|||
}
|
||||
|
||||
|
||||
private static OsmNodeNamed readPosition( String[] args, int idx, String name )
|
||||
public static OsmNodeNamed readPosition( String[] args, int idx, String name )
|
||||
{
|
||||
OsmNodeNamed n = new OsmNodeNamed();
|
||||
n.name = name;
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package btools.server;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import btools.mapaccess.OsmNode;
|
||||
import btools.router.OsmNodeNamed;
|
||||
import btools.router.RoutingContext;
|
||||
import btools.router.RoutingEngine;
|
||||
import btools.router.SearchBoundary;
|
||||
|
||||
public class BadTRDetector
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
System.out.println("BadTRDetector / 12092018 / abrensch");
|
||||
if ( args.length < 7 )
|
||||
{
|
||||
System.out.println("Find bad TR candidates in OSM");
|
||||
System.out.println("usage: java BadTRDetector <segmentdir> <lon-from> <lat-from> <lon-to> <lat-to> <profile> <nshots>");
|
||||
return;
|
||||
}
|
||||
|
||||
int x0 = Integer.parseInt( args[1]);
|
||||
int y0 = Integer.parseInt( args[2]);
|
||||
int x1 = Integer.parseInt( args[3]);
|
||||
int y1 = Integer.parseInt( args[4]);
|
||||
String profile = args[5];
|
||||
int radius = Integer.parseInt( args[6] );
|
||||
double overlap = Double.parseDouble( args[7] );
|
||||
|
||||
|
||||
Random rand = new Random();
|
||||
Map<Long,Integer> suspectTRs = new HashMap<Long,Integer>();
|
||||
|
||||
for( int y = y0; y < y1; y++ )
|
||||
{
|
||||
for( int x = x0; x < x1; x++ )
|
||||
{
|
||||
// calculate n-circles for this latitude
|
||||
int lon0 = 1000000 * ( x + 180 );
|
||||
int lat0 = 1000000 * ( y + 90 );
|
||||
OsmNode n0 = new OsmNode( lon0, lat0 );
|
||||
double arect = n0.calcDistance( new OsmNode( lon0, lat0 + 1000000 ) );
|
||||
arect *= n0.calcDistance( new OsmNode( lon0 + 1000000, lat0 ) );
|
||||
double adisc = ( Math.PI * radius ) * radius;
|
||||
int shots = (int)(1. + overlap * arect / adisc);
|
||||
|
||||
System.out.println( "shots for y=" + y + " x=" + x + " -> " + shots );
|
||||
|
||||
List<OsmNodeNamed> wplist = new ArrayList<OsmNodeNamed>();
|
||||
for( int shot=0; shot<shots; shot++ )
|
||||
{
|
||||
OsmNodeNamed n = new OsmNodeNamed();
|
||||
n.name = "from";
|
||||
n.ilon = lon0 + rand.nextInt( 1000000 );
|
||||
n.ilat = lat0 + rand.nextInt( 1000000 );
|
||||
wplist.add( n );
|
||||
}
|
||||
RoutingContext rc = new RoutingContext();
|
||||
rc.localFunction = profile;
|
||||
rc.memoryclass = (int) ( Runtime.getRuntime().maxMemory() / 1024 / 1024 );
|
||||
rc.suspectNodes = suspectTRs;
|
||||
rc.inverseRouting = rand.nextBoolean();
|
||||
|
||||
RoutingEngine re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, rc );
|
||||
re.doSearch( radius );
|
||||
if ( re.getErrorMessage() != null )
|
||||
{
|
||||
System.out.println( re.getErrorMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
// write tr-suspects to file
|
||||
String suspectsFile = "deadend.suspects";
|
||||
BufferedWriter bw = new BufferedWriter( new FileWriter( new File( suspectsFile ) ) );
|
||||
for( Long suspect : suspectTRs.keySet() )
|
||||
{
|
||||
bw.write( suspect + " " + suspectTRs.get( suspect ) + "\r\n" );
|
||||
}
|
||||
bw.close();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package btools.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
public class IssueArchiver
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
if ( args.length < 3 )
|
||||
{
|
||||
System.out.println( "usage : IssueArchiver <new-suspect-dir> <old-suspect-dir> <suspect-archive>" );
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
File newSuspectDir = new File( args[0] );
|
||||
if ( !newSuspectDir.isDirectory() )
|
||||
{
|
||||
throw new IllegalArgumentException( "not a directory: " + newSuspectDir );
|
||||
}
|
||||
File oldSuspectDir = new File( args[1] );
|
||||
if ( !oldSuspectDir.isDirectory() )
|
||||
{
|
||||
throw new IllegalArgumentException( "not a directory: " + oldSuspectDir );
|
||||
}
|
||||
File suspectArchive = new File( args[2] );
|
||||
if ( !suspectArchive.isDirectory() )
|
||||
{
|
||||
throw new IllegalArgumentException( "not a directory: " + suspectArchive );
|
||||
}
|
||||
|
||||
File[] newFiles = newSuspectDir.listFiles();
|
||||
for ( File newFile : newFiles )
|
||||
{
|
||||
String name = newFile.getName();
|
||||
if ( name.startsWith( "suspects_" ) && name.endsWith( ".txt" ) )
|
||||
{
|
||||
File oldFile = new File( oldSuspectDir, name );
|
||||
if ( !oldFile.exists() ) continue;
|
||||
|
||||
System.out.println( "archiving " + oldFile );
|
||||
|
||||
BufferedReader br = new BufferedReader( new FileReader( oldFile ) );
|
||||
for(;;)
|
||||
{
|
||||
String line = br.readLine();
|
||||
if ( line == null ) break;
|
||||
StringTokenizer tk = new StringTokenizer( line );
|
||||
long id = Long.parseLong( tk.nextToken() );
|
||||
int prio = Integer.parseInt( tk.nextToken() );
|
||||
|
||||
File archiveEntry = new File( suspectArchive, "" + id );
|
||||
if ( !archiveEntry.exists() )
|
||||
{
|
||||
archiveEntry.createNewFile();
|
||||
}
|
||||
}
|
||||
br.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
brouter-server/src/main/java/btools/server/IssueFilter.java
Normal file
40
brouter-server/src/main/java/btools/server/IssueFilter.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
package btools.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
public class IssueFilter
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
if ( args.length != 2 )
|
||||
{
|
||||
System.out.println( "usage : IssueFilter <in-file> <out-file> " );
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
BufferedReader br = new BufferedReader( new FileReader( new File( args[0] ) ) );
|
||||
BufferedWriter bw = new BufferedWriter( new FileWriter( new File( args[1] ) ) );
|
||||
for(;;)
|
||||
{
|
||||
String line = br.readLine();
|
||||
if ( line == null ) break;
|
||||
|
||||
if ( line.startsWith( "bad TR candidate: " ) )
|
||||
{
|
||||
bw.write( line.substring( "bad TR candidate: ".length() ) );
|
||||
bw.write( "\r\n" );
|
||||
}
|
||||
}
|
||||
br.close();
|
||||
bw.close();
|
||||
}
|
||||
}
|
121
brouter-server/src/main/java/btools/server/IssueSorter.java
Normal file
121
brouter-server/src/main/java/btools/server/IssueSorter.java
Normal file
|
@ -0,0 +1,121 @@
|
|||
package btools.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
public class IssueSorter
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
if ( args.length < 2 )
|
||||
{
|
||||
System.out.println( "usage : IssueSorter <in-file> <out-file> [<osm-filter>]" );
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
File osmFilter = args.length > 2 ? new File( args[2] ) : null;
|
||||
|
||||
Set<Long> filterSet = null;
|
||||
|
||||
// if the osm-filter exists, read it
|
||||
if ( osmFilter != null && osmFilter.exists() )
|
||||
{
|
||||
filterSet = new HashSet<Long>();
|
||||
BufferedReader r = new BufferedReader( new FileReader( osmFilter ) );
|
||||
for(;;)
|
||||
{
|
||||
String line = r.readLine();
|
||||
if ( line == null ) break;
|
||||
int idx0 = line.indexOf( "<node id=\"" );
|
||||
if ( idx0 < 0 ) continue;
|
||||
idx0 += 10;
|
||||
int idx1 = line.indexOf( '"', idx0 );
|
||||
long nodeId = Long.parseLong( line.substring( idx0, idx1 ) );
|
||||
filterSet.add( Long.valueOf( nodeId ) );
|
||||
}
|
||||
r.close();
|
||||
}
|
||||
|
||||
TreeMap<String,TreeMap<Long,Integer>> keys = new TreeMap<String,TreeMap<Long,Integer>>();
|
||||
|
||||
BufferedReader br = new BufferedReader( new FileReader( new File( args[0] ) ) );
|
||||
for(;;)
|
||||
{
|
||||
String line = br.readLine();
|
||||
if ( line == null ) break;
|
||||
StringTokenizer tk = new StringTokenizer( line );
|
||||
long id = Long.parseLong( tk.nextToken() );
|
||||
int prio = Integer.parseInt( tk.nextToken() );
|
||||
|
||||
if ( filterSet != null && !filterSet.contains( Long.valueOf( id ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int ilon = (int) ( id >> 32 );
|
||||
int ilat = (int) ( id & 0xffffffff );
|
||||
|
||||
String key = getKey( ilon, ilat );
|
||||
TreeMap<Long,Integer> map = keys.get( key );
|
||||
if ( map == null )
|
||||
{
|
||||
map = new TreeMap<Long,Integer>();
|
||||
keys.put( key, map );
|
||||
}
|
||||
map.put( Long.valueOf( id ), Integer.valueOf( prio ) );
|
||||
}
|
||||
br.close();
|
||||
|
||||
// write suspects to file
|
||||
BufferedWriter bw = new BufferedWriter( new FileWriter( new File( args[1] ) ) );
|
||||
for( String key : keys.keySet() )
|
||||
{
|
||||
TreeMap<Long,Integer> map = keys.get( key );
|
||||
for( Long suspect : map.keySet() )
|
||||
{
|
||||
bw.write( suspect + " " + map.get( suspect ) + "\r\n" );
|
||||
}
|
||||
}
|
||||
bw.close();
|
||||
|
||||
// if the osm-filter does not exist, write it
|
||||
if ( osmFilter != null && !osmFilter.exists() )
|
||||
{
|
||||
bw = new BufferedWriter( new FileWriter( osmFilter ) );
|
||||
bw.write( "<?xml version='1.0' encoding='UTF-8'?>\n" );
|
||||
bw.write( "<osm version=\"0.6\">\n" );
|
||||
for( String key : keys.keySet() )
|
||||
{
|
||||
TreeMap<Long,Integer> map = keys.get( key );
|
||||
for( Long suspect : map.keySet() )
|
||||
{
|
||||
long id = suspect.longValue();
|
||||
int ilon = (int) ( id >> 32 );
|
||||
int ilat = (int) ( id & 0xffffffff );
|
||||
double dlon = (ilon-180000000)/1000000.;
|
||||
double dlat = (ilat-90000000)/1000000.;
|
||||
bw.write( "<node id=\"" + id + "\" version=\"1\" timestamp=\"2017-01-10T12:00:00Z\" uid=\"1\" user=\"me\" changeset=\"1\" lat=\"" + dlat + "\" lon=\"" + dlon + "\"/>\n" );
|
||||
}
|
||||
}
|
||||
bw.write( "</osm>\n" );
|
||||
bw.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static String getKey( int ilon, int ilat )
|
||||
{
|
||||
int lon = (ilon / 1000000 );
|
||||
int lat = (ilat / 1000000 );
|
||||
return "" + (100000 + lon*360 + lat);
|
||||
}
|
||||
}
|
|
@ -24,7 +24,11 @@ public class SuspectManager extends Thread
|
|||
|
||||
private static String formatAge( File f )
|
||||
{
|
||||
long age = System.currentTimeMillis() - f.lastModified();
|
||||
return formatAge( System.currentTimeMillis() - f.lastModified() );
|
||||
}
|
||||
|
||||
private static String formatAge( long age )
|
||||
{
|
||||
long minutes = age / 60000;
|
||||
if ( minutes < 60 )
|
||||
{
|
||||
|
@ -67,7 +71,7 @@ public class SuspectManager extends Thread
|
|||
while ( tk.hasMoreTokens() )
|
||||
{
|
||||
String c = tk.nextToken();
|
||||
if ( "all".equals( c ) || "new".equals( c ) )
|
||||
if ( "all".equals( c ) || "new".equals( c ) || "confirmed".equals( c ) )
|
||||
{
|
||||
filter = c;
|
||||
break;
|
||||
|
@ -93,6 +97,7 @@ public class SuspectManager extends Thread
|
|||
{
|
||||
String url2 = "/brouter/suspects" + country + "/" + c;
|
||||
String linkNew = "<td> <a href=\"" + url2 + "/new\">new</a> </td>";
|
||||
String linkCnf = "<td> <a href=\"" + url2 + "/confirmed\">confirmed</a> </td>";
|
||||
String linkAll = "<td> <a href=\"" + url2 + "/all\">all</a> </td>";
|
||||
|
||||
String linkSub = "";
|
||||
|
@ -100,7 +105,7 @@ public class SuspectManager extends Thread
|
|||
{
|
||||
linkSub = "<td> <a href=\"" + url2 + "\">sub-regions</a> </td>";
|
||||
}
|
||||
bw.write( "<tr><td>" + c + "</td>" + linkNew + linkAll + linkSub + "\n" );
|
||||
bw.write( "<tr><td>" + c + "</td>" + linkNew + linkCnf + linkAll + linkSub + "\n" );
|
||||
}
|
||||
bw.write( "</table>\n" );
|
||||
bw.write( "</body></html>\n" );
|
||||
|
@ -127,6 +132,7 @@ public class SuspectManager extends Thread
|
|||
bw.flush();
|
||||
return;
|
||||
}
|
||||
SuspectList suspects = getAllSuspects( suspectFile );
|
||||
|
||||
boolean showWatchList = false;
|
||||
if ( tk.hasMoreTokens() )
|
||||
|
@ -146,35 +152,48 @@ public class SuspectManager extends Thread
|
|||
{
|
||||
bw.write( "watchlist for " + country + "\n" );
|
||||
bw.write( "<br><a href=\"/brouter/suspects\">back to country list</a><br><br>\n" );
|
||||
BufferedReader r = new BufferedReader( new FileReader( suspectFile ) );
|
||||
for ( ;; )
|
||||
{
|
||||
String line = r.readLine();
|
||||
if ( line == null )
|
||||
break;
|
||||
StringTokenizer tk2 = new StringTokenizer( line );
|
||||
id = Long.parseLong( tk2.nextToken() );
|
||||
String countryId = country + "/" + filter + "/" + id;
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
|
||||
for( int isuspect = 0; isuspect<suspects.cnt; isuspect++ )
|
||||
{
|
||||
id = suspects.ids[isuspect];
|
||||
|
||||
if ( !polygon.isInBoundingBox( id ) )
|
||||
{
|
||||
continue; // not in selected polygon (pre-check)
|
||||
}
|
||||
if ( new File( "falsepositives/" + id ).exists() )
|
||||
{
|
||||
continue; // known false positive
|
||||
}
|
||||
File confirmedEntry = new File( "confirmednegatives/" + id );
|
||||
if ( !( isFixed( id, suspectFile ) && confirmedEntry.exists() ) )
|
||||
File fixedEntry = new File( "fixedsuspects/" + id );
|
||||
if ( !fixedEntry.exists() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
long age = System.currentTimeMillis() - confirmedEntry.lastModified();
|
||||
if ( age / 1000 < 3600 * 24 * 8 )
|
||||
long fixedTs = fixedEntry.lastModified();
|
||||
if ( fixedTs < suspects.timestamp )
|
||||
{
|
||||
continue;
|
||||
continue; // that would be under current suspects
|
||||
}
|
||||
long hideTime = fixedTs - timeNow;
|
||||
if ( hideTime < 0 )
|
||||
{
|
||||
File confirmedEntry = new File( "confirmednegatives/" + id );
|
||||
if ( confirmedEntry.exists() && confirmedEntry.lastModified() > suspects.timestamp )
|
||||
{
|
||||
continue; // that would be under current suspects
|
||||
}
|
||||
}
|
||||
if ( !polygon.isInArea( id ) )
|
||||
{
|
||||
continue; // not in selected polygon
|
||||
}
|
||||
String hint = " confirmed " + formatAge( confirmedEntry ) + " ago";
|
||||
|
||||
String countryId = country + "/" + filter + "/" + id;
|
||||
String dueTime = hideTime < 0 ? "(asap)" : formatAge( hideTime + 43200000 );
|
||||
String hint = " due in " + dueTime;
|
||||
int ilon = (int) ( id >> 32 );
|
||||
int ilat = (int) ( id & 0xffffffff );
|
||||
double dlon = ( ilon - 180000000 ) / 1000000.;
|
||||
|
@ -182,7 +201,6 @@ public class SuspectManager extends Thread
|
|||
String url2 = "/brouter/suspects" + countryId;
|
||||
bw.write( "<a href=\"" + url2 + "\">" + dlon + "," + dlat + "</a>" + hint + "<br>\n" );
|
||||
}
|
||||
r.close();
|
||||
bw.write( "</body></html>\n" );
|
||||
bw.flush();
|
||||
return;
|
||||
|
@ -230,8 +248,15 @@ public class SuspectManager extends Thread
|
|||
if ( tk.hasMoreTokens() )
|
||||
{
|
||||
String param = tk.nextToken();
|
||||
hideDays = Integer.parseInt( param );
|
||||
fixedMarker.setLastModified( System.currentTimeMillis() + hideDays*86400000L );
|
||||
hideDays = Integer.parseInt( param ); // hiding, not fixing
|
||||
}
|
||||
else // touch the confirmed entry when marking fixed
|
||||
{
|
||||
File confirmedEntry = new File( "confirmednegatives/" + id );
|
||||
if ( confirmedEntry.exists() )
|
||||
{
|
||||
confirmedEntry.setLastModified( System.currentTimeMillis() );
|
||||
}
|
||||
}
|
||||
fixedMarker.setLastModified( System.currentTimeMillis() + hideDays*86400000L );
|
||||
}
|
||||
|
@ -246,7 +271,7 @@ public class SuspectManager extends Thread
|
|||
double dlat = ( ilat - 90000000 ) / 1000000.;
|
||||
|
||||
String profile = "car-eco";
|
||||
File configFile = new File( "configs/" + country + ".cfg" );
|
||||
File configFile = new File( "configs/profile.cfg" );
|
||||
if ( configFile.exists() )
|
||||
{
|
||||
BufferedReader br = new BufferedReader( new FileReader( configFile ) );
|
||||
|
@ -271,7 +296,7 @@ public class SuspectManager extends Thread
|
|||
String url4a = "https://overpass-turbo.eu/?Q=[date:"" + formatZ( weekAgo ) + "Z"];way[highway]({{bbox}});out meta geom;&C="
|
||||
+ dlat + ";" + dlon + ";18&R";
|
||||
|
||||
String url4b = "https://overpass-turbo.eu/?Q=(node(around%3A1%2C%7B%7Bcenter%7D%7D)-%3E.n%3Bway(bn.n)%3Brel(bn.n%3A%22via%22)%5Btype%3Drestriction%5D%3B)%3Bout%20meta%3B%3E%3Bout%20skel%20qt%3B&C="
|
||||
String url4b = "https://overpass-turbo.eu/?Q=(node(around%3A1%2C%7B%7Bcenter%7D%7D)-%3E.n%3Bway(bn.n)%5Bhighway%5D%3Brel(bn.n%3A%22via%22)%5Btype%3Drestriction%5D%3B)%3Bout%20meta%3B%3E%3Bout%20skel%20qt%3B&C="
|
||||
+ dlat + ";" + dlon + ";18&R";
|
||||
|
||||
String url5 = "https://tyrasd.github.io/latest-changes/#16/" + dlat + "/" + dlon;
|
||||
|
@ -286,7 +311,7 @@ public class SuspectManager extends Thread
|
|||
bw.write( "Overpass: <a href=\"" + url4a + "\">minus one week</a> <a href=\"" + url4b + "\">node context</a><br><br>\n" );
|
||||
bw.write( "<a href=\"" + url5 + "\">Open in Latest-Changes / last week</a><br><br>\n" );
|
||||
bw.write( "<br>\n" );
|
||||
if ( isFixed( id, suspectFile ) )
|
||||
if ( isFixed( id, suspects.timestamp ) )
|
||||
{
|
||||
bw.write( "<br><br><a href=\"/brouter/suspects/" + country + "/" + filter + "/watchlist\">back to watchlist</a><br><br>\n" );
|
||||
}
|
||||
|
@ -299,11 +324,17 @@ public class SuspectManager extends Thread
|
|||
String prefix = "<a href=\"/brouter/suspects" + countryId + "/fixed";
|
||||
String prefix2 = " " + prefix;
|
||||
bw.write( prefix + "\">mark as fixed</a><br><br>\n" );
|
||||
bw.write( "hide for " );
|
||||
bw.write( prefix2 + "/7\">1 week</a>" );
|
||||
bw.write( prefix2 + "/30\">1 month</a>" );
|
||||
bw.write( prefix2 + "/91\">3 months</a>" );
|
||||
bw.write( prefix2 + "/182\">6 months</a><br><br>\n" );
|
||||
bw.write( "hide for: weeks:" );
|
||||
bw.write( prefix2 + "/7\">1w</a>" );
|
||||
bw.write( prefix2 + "/14\">2w</a>" );
|
||||
bw.write( prefix2 + "/21\">3w</a>" );
|
||||
bw.write( " months:" );
|
||||
bw.write( prefix2 + "/30\">1m</a>" );
|
||||
bw.write( prefix2 + "/61\">2m</a>" );
|
||||
bw.write( prefix2 + "/91\">3m</a>" );
|
||||
bw.write( prefix2 + "/122\">4m</a>" );
|
||||
bw.write( prefix2 + "/152\">5m</a>" );
|
||||
bw.write( prefix2 + "/183\">6m</a><br><br>\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -318,38 +349,20 @@ public class SuspectManager extends Thread
|
|||
bw.write( "<br><a href=\"/brouter/suspects" + country + "/" + filter + "/watchlist\">see watchlist</a>\n" );
|
||||
bw.write( "<br><a href=\"/brouter/suspects\">back to country list</a><br><br>\n" );
|
||||
int maxprio = 0;
|
||||
for ( int pass = 1; pass <= 2; pass++ )
|
||||
{
|
||||
if ( pass == 2 )
|
||||
for( int isuspect = 0; isuspect<suspects.cnt; isuspect++ )
|
||||
{
|
||||
bw.write( "current level: " + getLevelDecsription( maxprio ) + "<br><br>\n" );
|
||||
}
|
||||
|
||||
BufferedReader r = new BufferedReader( new FileReader( suspectFile ) );
|
||||
for ( ;; )
|
||||
{
|
||||
String line = r.readLine();
|
||||
if ( line == null )
|
||||
id = suspects.ids[isuspect];
|
||||
int prio = suspects.prios[isuspect];
|
||||
int nprio = ( ( prio + 1 ) / 2 ) * 2; // normalize (no link prios)
|
||||
if ( nprio < maxprio )
|
||||
{
|
||||
if ( maxprio == 0 )
|
||||
{
|
||||
bw.write( "current level: " + getLevelDecsription( maxprio ) + "<br><br>\n" );
|
||||
}
|
||||
break;
|
||||
StringTokenizer tk2 = new StringTokenizer( line );
|
||||
String idString = tk2.nextToken();
|
||||
|
||||
int prio = Integer.parseInt( tk2.nextToken() );
|
||||
prio = ( ( prio + 1 ) / 2 ) * 2; // normalize (no link prios)
|
||||
|
||||
if ( pass == 1 )
|
||||
{
|
||||
if ( prio <= maxprio )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( prio < maxprio )
|
||||
continue;
|
||||
}
|
||||
|
||||
id = Long.parseLong( idString );
|
||||
|
||||
if ( !polygon.isInBoundingBox( id ) )
|
||||
{
|
||||
continue; // not in selected polygon (pre-check)
|
||||
|
@ -358,22 +371,26 @@ public class SuspectManager extends Thread
|
|||
{
|
||||
continue; // known false positive
|
||||
}
|
||||
if ( isFixed( id, suspectFile ) )
|
||||
if ( isFixed( id, suspects.timestamp ) )
|
||||
{
|
||||
continue; // known fixed
|
||||
}
|
||||
if ( "new".equals( filter ) && new File( "suspectarchive/" + id ).exists() )
|
||||
{
|
||||
continue; // known fixed
|
||||
continue; // known archived
|
||||
}
|
||||
if ( "confirmed".equals( filter ) && !new File( "confirmednegatives/" + id ).exists() )
|
||||
{
|
||||
continue; // showing confirmed suspects only
|
||||
}
|
||||
if ( !polygon.isInArea( id ) )
|
||||
{
|
||||
continue; // not in selected polygon
|
||||
}
|
||||
if ( pass == 1 )
|
||||
if ( maxprio == 0 )
|
||||
{
|
||||
maxprio = prio;
|
||||
continue;
|
||||
maxprio = nprio;
|
||||
bw.write( "current level: " + getLevelDecsription( maxprio ) + "<br><br>\n" );
|
||||
}
|
||||
String countryId = country + "/" + filter + "/" + id;
|
||||
File confirmedEntry = new File( "confirmednegatives/" + id );
|
||||
|
@ -389,7 +406,6 @@ public class SuspectManager extends Thread
|
|||
String url2 = "/brouter/suspects" + countryId;
|
||||
bw.write( "<a href=\"" + url2 + "\">" + dlon + "," + dlat + "</a>" + hint + "<br>\n" );
|
||||
}
|
||||
r.close();
|
||||
}
|
||||
}
|
||||
bw.write( "</body></html>\n" );
|
||||
|
@ -398,10 +414,82 @@ public class SuspectManager extends Thread
|
|||
}
|
||||
|
||||
|
||||
private static boolean isFixed( long id, File suspectFile )
|
||||
private static boolean isFixed( long id, long timestamp )
|
||||
{
|
||||
File fixedEntry = new File( "fixedsuspects/" + id );
|
||||
return fixedEntry.exists() && fixedEntry.lastModified() > suspectFile.lastModified();
|
||||
return fixedEntry.exists() && fixedEntry.lastModified() > timestamp;
|
||||
}
|
||||
|
||||
|
||||
private static final class SuspectList
|
||||
{
|
||||
int cnt;
|
||||
long[] ids;
|
||||
int[] prios;
|
||||
long timestamp;
|
||||
|
||||
SuspectList( int count, long time )
|
||||
{
|
||||
cnt = count;
|
||||
ids = new long[cnt];
|
||||
prios = new int[cnt];
|
||||
timestamp = time;
|
||||
}
|
||||
}
|
||||
|
||||
private static SuspectList allSuspects;
|
||||
private static Object allSuspectsSync = new Object();
|
||||
|
||||
private static SuspectList getAllSuspects( File suspectFile ) throws IOException
|
||||
{
|
||||
synchronized( allSuspectsSync )
|
||||
{
|
||||
if ( allSuspects != null && suspectFile.lastModified() == allSuspects.timestamp )
|
||||
{
|
||||
return allSuspects;
|
||||
}
|
||||
|
||||
// count prios
|
||||
int[] prioCount = new int[100];
|
||||
BufferedReader r = new BufferedReader( new FileReader( suspectFile ) );
|
||||
for ( ;; )
|
||||
{
|
||||
String line = r.readLine();
|
||||
if ( line == null ) break;
|
||||
StringTokenizer tk2 = new StringTokenizer( line );
|
||||
tk2.nextToken();
|
||||
int prio = Integer.parseInt( tk2.nextToken() );
|
||||
int nprio = ( ( prio + 1 ) / 2 ) * 2; // normalize (no link prios)
|
||||
prioCount[nprio]++;
|
||||
}
|
||||
r.close();
|
||||
|
||||
// sum up
|
||||
int pointer = 0;
|
||||
for( int i=99; i>=0; i-- )
|
||||
{
|
||||
int cnt = prioCount[i];
|
||||
prioCount[i] = pointer;
|
||||
pointer += cnt;
|
||||
}
|
||||
|
||||
// sort into suspect list
|
||||
allSuspects = new SuspectList( pointer, suspectFile.lastModified() );
|
||||
r = new BufferedReader( new FileReader( suspectFile ) );
|
||||
for ( ;; )
|
||||
{
|
||||
String line = r.readLine();
|
||||
if ( line == null ) break;
|
||||
StringTokenizer tk2 = new StringTokenizer( line );
|
||||
long id = Long.parseLong( tk2.nextToken() );
|
||||
int prio = Integer.parseInt( tk2.nextToken() );
|
||||
int nprio = ( ( prio + 1 ) / 2 ) * 2; // normalize (no link prios)
|
||||
pointer = prioCount[nprio]++;
|
||||
allSuspects.ids[pointer] = id;
|
||||
allSuspects.prios[pointer] = prio;
|
||||
}
|
||||
r.close();
|
||||
return allSuspects;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue