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.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeSet;
import btools.mapaccess.OsmNode;
import btools.router.OsmNodeNamed;
import btools.router.SuspectInfo;
public class SuspectManager extends Thread {
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) {
synchronized (dfTimestampZ) {
return dfTimestampZ.format(date);
}
}
private static String formatAge(File f) {
return formatAge(System.currentTimeMillis() - f.lastModified());
}
private static String formatAge(long age) {
long minutes = age / 60000;
if (minutes < 60) {
return minutes + " minutes";
}
long hours = minutes / 60;
if (hours < 24) {
return hours + " hours";
}
long days = hours / 24;
return days + " days";
}
private static String getLevelDecsription(int level) {
switch (level) {
case 30:
return "motorway";
case 28:
return "trunk";
case 26:
return "primary";
case 24:
return "secondary";
case 22:
return "tertiary";
default:
return "none";
}
}
private static void markFalsePositive(SuspectList suspects, long id) throws IOException {
new File("falsepositives/" + id).createNewFile();
for (int isuspect = 0; isuspect < suspects.cnt; isuspect++) {
if (id == suspects.ids[isuspect]) {
suspects.falsePositive[isuspect] = true;
}
}
}
public static void newAndConfirmedJson(SuspectList suspects, BufferedWriter bw, String filter, int level, Area polygon) throws IOException {
bw.write("{\n");
bw.write("\"type\": \"FeatureCollection\",\n");
bw.write("\"features\": [");
int n = 0;
for (int isuspect = 0; isuspect < suspects.cnt; isuspect++) {
long id = suspects.ids[isuspect];
int prio = suspects.prios[isuspect];
int nprio = ((prio + 1) / 2) * 2; // normalize (no link prios)
if (nprio < level) {
continue; // not the given level
}
if (("new".equals(filter) || "deferred".equals(filter)) && !suspects.newOrConfirmed[isuspect]) {
continue; // known archived
}
if ("fp".equals(filter) ^ suspects.falsePositive[isuspect]) {
continue; // wrong false-positive state
}
if (polygon != null && !polygon.isInBoundingBox(id)) {
continue; // not in selected polygon (pre-check)
}
String dueTime = null;
if (!"deferred".equals(filter)) {
if (isFixed(id, suspects.timestamp)) {
continue; // known fixed
}
} else {
File fixedEntry = new File("fixedsuspects/" + id);
if (!fixedEntry.exists()) {
continue;
}
long fixedTs = fixedEntry.lastModified();
if (fixedTs < suspects.timestamp) {
continue; // that would be under current suspects
}
long hideTime = fixedTs - System.currentTimeMillis();
if (hideTime < 0) {
File confirmedEntry = new File("confirmednegatives/" + id);
if (confirmedEntry.exists() && confirmedEntry.lastModified() > suspects.timestamp) {
continue; // that would be under current suspects
}
}
dueTime = hideTime < 0 ? "(asap)" : formatAge(hideTime + 43200000);
}
if (polygon != null && !polygon.isInArea(id)) {
continue; // not in selected polygon
}
File confirmedEntry = new File("confirmednegatives/" + id);
String status = suspects.newOrConfirmed[isuspect] ? "new" : "archived";
if (confirmedEntry.exists()) {
status = "confirmed " + formatAge(confirmedEntry) + " ago";
}
if (dueTime != null) {
status = "deferred";
}
if (n > 0) {
bw.write(",");
}
int ilon = (int) (id >> 32);
int ilat = (int) (id & 0xffffffff);
double dlon = (ilon - 180000000) / 1000000.;
double dlat = (ilat - 90000000) / 1000000.;
String slevel = getLevelDecsription(nprio);
bw.write("\n{\n");
bw.write(" \"id\": " + n + ",\n");
bw.write(" \"type\": \"Feature\",\n");
bw.write(" \"properties\": {\n");
bw.write(" \"issue_id\": \"" + id + "\",\n");
bw.write(" \"Status\": \"" + status + "\",\n");
if (dueTime != null) {
bw.write(" \"DueTime\": \"" + dueTime + "\",\n");
}
bw.write(" \"Level\": \"" + slevel + "\"\n");
bw.write(" },\n");
bw.write(" \"geometry\": {\n");
bw.write(" \"type\": \"Point\",\n");
bw.write(" \"coordinates\": [\n");
bw.write(" " + dlon + ",\n");
bw.write(" " + dlat + "\n");
bw.write(" ]\n");
bw.write(" }\n");
bw.write("}");
n++;
}
bw.write("\n ]\n");
bw.write("}\n");
bw.flush();
}
public static void process(String url, BufferedWriter bw) throws IOException {
try {
_process(url, bw);
} catch (IllegalArgumentException iae) {
try {
bw.write("
ERROR: " + iae.getMessage() + "
\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();
long id = 0L;
String country = "";
String challenge = "";
String suspectFilename = "worldsuspects.txt";
String filter = null;
while (tk.hasMoreTokens()) {
String c = tk.nextToken();
if ("all".equals(c) || "new".equals(c) || "confirmed".equals(c) || "fp".equals(c) || "deferred".equals(c)) {
filter = c;
break;
}
if (country.length() == 0 && !"world".equals(c)) {
if (new File(c + "suspects.txt").exists()) {
suspectFilename = c + "suspects.txt";
challenge = "/" + c;
continue;
}
}
country += "/" + c;
}
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("