Suspect-Manager: allow 999 days for resubmission, track neighbour resubmissions
This commit is contained in:
parent
08161b47fd
commit
d5322667d5
3 changed files with 143 additions and 65 deletions
|
@ -1,69 +1,47 @@
|
||||||
package btools.server;
|
package btools.server;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.ServerSocket;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
|
import btools.mapaccess.OsmNode;
|
||||||
import btools.router.OsmNodeNamed;
|
import btools.router.OsmNodeNamed;
|
||||||
import btools.router.OsmTrack;
|
|
||||||
import btools.router.RoutingContext;
|
|
||||||
import btools.router.RoutingEngine;
|
|
||||||
import btools.server.request.ProfileUploadHandler;
|
|
||||||
import btools.server.request.RequestHandler;
|
|
||||||
import btools.server.request.ServerHandler;
|
|
||||||
|
|
||||||
public class NearRecentWps
|
public class NearRecentWps
|
||||||
{
|
{
|
||||||
private static OsmNodeNamed[] recentWaypoints = new OsmNodeNamed[2000];
|
private OsmNodeNamed[] recentWaypoints = new OsmNodeNamed[2000];
|
||||||
private static int nextRecentIndex = 0;
|
private int nextRecentIndex = 0;
|
||||||
|
|
||||||
public static void add( List<OsmNodeNamed> wplist )
|
public void add( List<OsmNodeNamed> wplist )
|
||||||
{
|
{
|
||||||
synchronized( recentWaypoints )
|
synchronized( recentWaypoints )
|
||||||
{
|
{
|
||||||
for( OsmNodeNamed wp : wplist )
|
for( OsmNodeNamed wp : wplist )
|
||||||
{
|
{
|
||||||
recentWaypoints[nextRecentIndex++] = wp;
|
add( wp );
|
||||||
if ( nextRecentIndex >= recentWaypoints.length )
|
|
||||||
{
|
|
||||||
nextRecentIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int count( long id )
|
public void add( OsmNodeNamed wp )
|
||||||
|
{
|
||||||
|
recentWaypoints[nextRecentIndex++] = wp;
|
||||||
|
if ( nextRecentIndex >= recentWaypoints.length )
|
||||||
|
{
|
||||||
|
nextRecentIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int count( long id )
|
||||||
{
|
{
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
int ilon = (int) ( id >> 32 );
|
OsmNode n = new OsmNode( id );
|
||||||
int ilat = (int) ( id & 0xffffffff );
|
|
||||||
synchronized( recentWaypoints )
|
synchronized( recentWaypoints )
|
||||||
{
|
{
|
||||||
for ( int i=0; i<recentWaypoints.length; i++ )
|
for ( int i=0; i<recentWaypoints.length; i++ )
|
||||||
{
|
{
|
||||||
OsmNodeNamed n = recentWaypoints[i];
|
OsmNodeNamed nn = recentWaypoints[i];
|
||||||
if ( n != null )
|
if ( nn != null )
|
||||||
{
|
{
|
||||||
int dlat = ilat - n.ilat;
|
if ( nn.calcDistance( n ) < 4000 )
|
||||||
int dlon = ilon - n.ilon;
|
|
||||||
if ( dlat > -29999 && dlat < 29999 && dlon > -39999 && dlon < 39999 )
|
|
||||||
{
|
{
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
@ -72,4 +50,29 @@ public class NearRecentWps
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OsmNodeNamed closest( long id )
|
||||||
|
{
|
||||||
|
int dmin = 0;
|
||||||
|
OsmNodeNamed nc = null;
|
||||||
|
OsmNode n = new OsmNode( id );
|
||||||
|
synchronized( recentWaypoints )
|
||||||
|
{
|
||||||
|
for ( int i=0; i<recentWaypoints.length; i++ )
|
||||||
|
{
|
||||||
|
OsmNodeNamed nn = recentWaypoints[i];
|
||||||
|
if ( nn != null )
|
||||||
|
{
|
||||||
|
int d = nn.calcDistance( n );
|
||||||
|
if ( d < 4000 && ( nc == null || d < dmin ) )
|
||||||
|
{
|
||||||
|
dmin = d;
|
||||||
|
nc = nn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nc;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,7 @@ public class RouteServer extends Thread implements Comparable<RouteServer>
|
||||||
|
|
||||||
if ( wplist.size() < 10 )
|
if ( wplist.size() < 10 )
|
||||||
{
|
{
|
||||||
NearRecentWps.add( wplist );
|
SuspectManager.nearRecentWps.add( wplist );
|
||||||
}
|
}
|
||||||
for( Map.Entry<String,String> e : params.entrySet() )
|
for( Map.Entry<String,String> e : params.entrySet() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,12 +11,17 @@ import java.util.HashMap;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import btools.mapaccess.OsmNode;
|
||||||
|
import btools.router.OsmNodeNamed;
|
||||||
import btools.router.SuspectInfo;
|
import btools.router.SuspectInfo;
|
||||||
|
|
||||||
public class SuspectManager extends Thread
|
public class SuspectManager extends Thread
|
||||||
{
|
{
|
||||||
private static SimpleDateFormat dfTimestampZ = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss" );
|
private static SimpleDateFormat dfTimestampZ = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss" );
|
||||||
|
|
||||||
|
static NearRecentWps nearRecentWps = new NearRecentWps();
|
||||||
|
static NearRecentWps hiddenWps = new NearRecentWps();
|
||||||
|
|
||||||
private static String formatZ( Date date )
|
private static String formatZ( Date date )
|
||||||
{
|
{
|
||||||
synchronized( dfTimestampZ )
|
synchronized( dfTimestampZ )
|
||||||
|
@ -73,7 +78,7 @@ public class SuspectManager extends Thread
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void newAndConfirmedJson( SuspectList suspects, BufferedWriter bw, String filter, int level ) throws IOException
|
public static void newAndConfirmedJson( SuspectList suspects, BufferedWriter bw, String filter, int level, Area polygon ) throws IOException
|
||||||
{
|
{
|
||||||
bw.write( "{\n" );
|
bw.write( "{\n" );
|
||||||
bw.write( "\"type\": \"FeatureCollection\",\n" );
|
bw.write( "\"type\": \"FeatureCollection\",\n" );
|
||||||
|
@ -100,6 +105,11 @@ public class SuspectManager extends Thread
|
||||||
continue; // wrong false-positive state
|
continue; // wrong false-positive state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( polygon != null && !polygon.isInBoundingBox( id ) )
|
||||||
|
{
|
||||||
|
continue; // not in selected polygon (pre-check)
|
||||||
|
}
|
||||||
|
|
||||||
String dueTime = null;
|
String dueTime = null;
|
||||||
if ( !"deferred".equals( filter ) )
|
if ( !"deferred".equals( filter ) )
|
||||||
{
|
{
|
||||||
|
@ -132,6 +142,11 @@ public class SuspectManager extends Thread
|
||||||
dueTime = hideTime < 0 ? "(asap)" : formatAge( hideTime + 43200000 );
|
dueTime = hideTime < 0 ? "(asap)" : formatAge( hideTime + 43200000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( polygon != null && !polygon.isInArea( id ) )
|
||||||
|
{
|
||||||
|
continue; // not in selected polygon
|
||||||
|
}
|
||||||
|
|
||||||
File confirmedEntry = new File( "confirmednegatives/" + id );
|
File confirmedEntry = new File( "confirmednegatives/" + id );
|
||||||
String status = suspects.newOrConfirmed[isuspect] ? "new" : "archived";
|
String status = suspects.newOrConfirmed[isuspect] ? "new" : "archived";
|
||||||
if ( confirmedEntry.exists() )
|
if ( confirmedEntry.exists() )
|
||||||
|
@ -186,7 +201,25 @@ public class SuspectManager extends Thread
|
||||||
|
|
||||||
public static void process( String url, BufferedWriter bw ) throws IOException
|
public static void process( String url, BufferedWriter bw ) throws IOException
|
||||||
{
|
{
|
||||||
StringTokenizer tk = new StringTokenizer( url, "/" );
|
try
|
||||||
|
{
|
||||||
|
_process( url, bw );
|
||||||
|
}
|
||||||
|
catch( IllegalArgumentException iae )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bw.write( "<br><br>ERROR: " + iae.getMessage() + "<br><br>\n\n" );
|
||||||
|
bw.write( "(press Browser-Back to continue)\n" );
|
||||||
|
bw.flush();
|
||||||
|
}
|
||||||
|
catch (IOException _ignore){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void _process( String url, BufferedWriter bw ) throws IOException
|
||||||
|
{
|
||||||
|
StringTokenizer tk = new StringTokenizer( url, "/?" );
|
||||||
tk.nextToken();
|
tk.nextToken();
|
||||||
tk.nextToken();
|
tk.nextToken();
|
||||||
long id = 0L;
|
long id = 0L;
|
||||||
|
@ -218,12 +251,26 @@ public class SuspectManager extends Thread
|
||||||
|
|
||||||
SuspectList suspects = getAllSuspects( suspectFilename );
|
SuspectList suspects = getAllSuspects( suspectFilename );
|
||||||
|
|
||||||
|
Area polygon = null;
|
||||||
|
if ( !("/world".equals( country ) || "".equals( country ) ) )
|
||||||
|
{
|
||||||
|
File polyFile = new File( "worldpolys" + country + ".poly" );
|
||||||
|
if ( !polyFile.exists() )
|
||||||
|
{
|
||||||
|
bw.write( "polygon file for country '" + country + "' not found\n" );
|
||||||
|
bw.write( "</body></html>\n" );
|
||||||
|
bw.flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
polygon = new Area( polyFile );
|
||||||
|
}
|
||||||
|
|
||||||
if ( url.endsWith( ".json" ) )
|
if ( url.endsWith( ".json" ) )
|
||||||
{
|
{
|
||||||
StringTokenizer tk2 = new StringTokenizer( tk.nextToken(), "." );
|
StringTokenizer tk2 = new StringTokenizer( tk.nextToken(), "." );
|
||||||
int level = Integer.parseInt( tk2.nextToken() );
|
int level = Integer.parseInt( tk2.nextToken() );
|
||||||
|
|
||||||
newAndConfirmedJson( suspects, bw, filter, level );
|
newAndConfirmedJson( suspects, bw, filter, level, polygon );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,20 +311,6 @@ public class SuspectManager extends Thread
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Area polygon = null;
|
|
||||||
if ( !"/world".equals( country ) )
|
|
||||||
{
|
|
||||||
File polyFile = new File( "worldpolys" + country + ".poly" );
|
|
||||||
if ( !polyFile.exists() )
|
|
||||||
{
|
|
||||||
bw.write( "polygon file for country '" + country + "' not found\n" );
|
|
||||||
bw.write( "</body></html>\n" );
|
|
||||||
bw.flush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
polygon = new Area( polyFile );
|
|
||||||
}
|
|
||||||
|
|
||||||
File suspectFile = new File( "worldsuspects.txt" );
|
File suspectFile = new File( "worldsuspects.txt" );
|
||||||
if ( !suspectFile.exists() )
|
if ( !suspectFile.exists() )
|
||||||
{
|
{
|
||||||
|
@ -365,10 +398,11 @@ public class SuspectManager extends Thread
|
||||||
String command = tk.nextToken();
|
String command = tk.nextToken();
|
||||||
if ( "falsepositive".equals( command ) )
|
if ( "falsepositive".equals( command ) )
|
||||||
{
|
{
|
||||||
int wps = NearRecentWps.count( id );
|
int wps = nearRecentWps.count( id );
|
||||||
if ( wps < 0 ) // FIXME
|
if ( wps < 8 )
|
||||||
{
|
{
|
||||||
message = "marking false-positive requires at least 8 recent nearby waypoints from BRouter-Web, found: " + wps;
|
message = "marking false-positive requires at least 8 recent nearby waypoints from BRouter-Web, found: " + wps
|
||||||
|
+ "<br><br>****** DO SOME MORE TEST-ROUTINGS IN BROUTER-WEB ******* before marking false positive";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -379,10 +413,11 @@ public class SuspectManager extends Thread
|
||||||
}
|
}
|
||||||
if ( "confirm".equals( command ) )
|
if ( "confirm".equals( command ) )
|
||||||
{
|
{
|
||||||
int wps = NearRecentWps.count( id );
|
int wps = nearRecentWps.count( id );
|
||||||
if ( wps < 2 )
|
if ( wps < 2 )
|
||||||
{
|
{
|
||||||
message = "marking confirmed requires at least 2 recent nearby waypoints from BRouter-Web, found: " + wps;
|
message = "marking confirmed requires at least 2 recent nearby waypoints from BRouter-Web, found: " + wps
|
||||||
|
+ "<br><br>****** DO AT LEAST ONE TEST-ROUTING IN BROUTER-WEB ******* before marking confirmed";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -401,13 +436,34 @@ public class SuspectManager extends Thread
|
||||||
if ( tk.hasMoreTokens() )
|
if ( tk.hasMoreTokens() )
|
||||||
{
|
{
|
||||||
String param = tk.nextToken();
|
String param = tk.nextToken();
|
||||||
hideDays = Integer.parseInt( param ); // hiding, not fixing
|
if ( param.startsWith( "ndays=" ) )
|
||||||
|
{
|
||||||
|
param = param.substring( "ndays=".length() );
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
hideDays = Integer.parseInt( param ); // hiding, not fixing
|
||||||
|
}
|
||||||
|
catch( NumberFormatException nfe )
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException( "not a number: " + param );
|
||||||
|
}
|
||||||
|
if ( hideDays < 1 || hideDays > 999 )
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException( "hideDays must be within 1..999" );
|
||||||
|
}
|
||||||
message = "Hide issue " + id + " for " + hideDays + " days";
|
message = "Hide issue " + id + " for " + hideDays + " days";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
message = "Marked issue " + id + " as fixed";
|
message = "Marked issue " + id + " as fixed";
|
||||||
}
|
}
|
||||||
|
if ( hideDays > 0 )
|
||||||
|
{
|
||||||
|
OsmNodeNamed nn = new OsmNodeNamed ( new OsmNode( id ) );
|
||||||
|
nn.name = "" + hideDays;
|
||||||
|
hiddenWps.add( nn );
|
||||||
|
}
|
||||||
id = 0L;
|
id = 0L;
|
||||||
fixedMarker.setLastModified( System.currentTimeMillis() + hideDays*86400000L );
|
fixedMarker.setLastModified( System.currentTimeMillis() + hideDays*86400000L );
|
||||||
}
|
}
|
||||||
|
@ -432,6 +488,11 @@ public class SuspectManager extends Thread
|
||||||
|
|
||||||
// get triggers
|
// get triggers
|
||||||
int triggers = suspects.trigger4Id( id );
|
int triggers = suspects.trigger4Id( id );
|
||||||
|
SuspectList daily = getDailySuspectsIfLoaded();
|
||||||
|
if ( daily != null && daily != suspects )
|
||||||
|
{
|
||||||
|
triggers |= daily.trigger4Id( id ); // hack, because osmoscope does not echo type of analysis
|
||||||
|
}
|
||||||
String triggerText = SuspectInfo.getTriggerText( triggers );
|
String triggerText = SuspectInfo.getTriggerText( triggers );
|
||||||
|
|
||||||
|
|
||||||
|
@ -484,6 +545,11 @@ public class SuspectManager extends Thread
|
||||||
{
|
{
|
||||||
String prefix = "<a href=\"/brouter/suspects" + countryId + "/fixed";
|
String prefix = "<a href=\"/brouter/suspects" + countryId + "/fixed";
|
||||||
String prefix2 = " " + prefix;
|
String prefix2 = " " + prefix;
|
||||||
|
|
||||||
|
OsmNodeNamed nc = hiddenWps.closest( id );
|
||||||
|
String proposal = nc == null ? "" : nc.name;
|
||||||
|
String prefix2d = "<form action=\"/brouter/suspects" + countryId + "/fixed\" method=\"get\">hide for days: <input type=\"text\" name=\"ndays\" value=\"" + proposal + "\" autofocus><button type=\"submit\">OK</button></form>";
|
||||||
|
|
||||||
bw.write( prefix + "\">mark as fixed</a><br><br>\n" );
|
bw.write( prefix + "\">mark as fixed</a><br><br>\n" );
|
||||||
bw.write( "hide for: weeks:" );
|
bw.write( "hide for: weeks:" );
|
||||||
bw.write( prefix2 + "/7\">1w</a>" );
|
bw.write( prefix2 + "/7\">1w</a>" );
|
||||||
|
@ -496,6 +562,7 @@ public class SuspectManager extends Thread
|
||||||
bw.write( prefix2 + "/122\">4m</a>" );
|
bw.write( prefix2 + "/122\">4m</a>" );
|
||||||
bw.write( prefix2 + "/152\">5m</a>" );
|
bw.write( prefix2 + "/152\">5m</a>" );
|
||||||
bw.write( prefix2 + "/183\">6m</a><br><br>\n" );
|
bw.write( prefix2 + "/183\">6m</a><br><br>\n" );
|
||||||
|
bw.write( prefix2d + "<br><br>\n" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -625,6 +692,14 @@ public class SuspectManager extends Thread
|
||||||
|
|
||||||
private static HashMap<String,SuspectList> allSuspectsMap = new HashMap<String,SuspectList>();
|
private static HashMap<String,SuspectList> allSuspectsMap = new HashMap<String,SuspectList>();
|
||||||
|
|
||||||
|
private static SuspectList getDailySuspectsIfLoaded() throws IOException
|
||||||
|
{
|
||||||
|
synchronized( allSuspectsMap )
|
||||||
|
{
|
||||||
|
return allSuspectsMap.get( "dailysuspects.txt" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static SuspectList getAllSuspects( String suspectFileName ) throws IOException
|
private static SuspectList getAllSuspects( String suspectFileName ) throws IOException
|
||||||
{
|
{
|
||||||
synchronized( allSuspectsMap )
|
synchronized( allSuspectsMap )
|
||||||
|
|
Loading…
Reference in a new issue