Suspect-Manager: allow 999 days for resubmission, track neighbour resubmissions

This commit is contained in:
Arndt Brenschede 2022-07-17 11:38:28 +02:00
parent 08161b47fd
commit d5322667d5
3 changed files with 143 additions and 65 deletions

View file

@ -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;
}
} }

View file

@ -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() )
{ {

View file

@ -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 = " &nbsp;&nbsp;" + prefix; String prefix2 = " &nbsp;&nbsp;" + 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: &nbsp;&nbsp;<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 )