changeset 1904:0625482ac9a5

Implement location search.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 06 Nov 2017 12:03:34 +0200
parents 953c9a2c55f5
children 9e659d0f995f
files mapsearch.c
diffstat 1 files changed, 126 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/mapsearch.c	Mon Nov 06 11:35:46 2017 +0200
+++ b/mapsearch.c	Mon Nov 06 12:03:34 2017 +0200
@@ -73,7 +73,8 @@
 
 typedef struct
 {
-    char *map;
+    BOOL type;
+    char *map, *loc1, *loc2;
     int mx, my, wx, wy;
     int accuracy;
     BOOL centered;
@@ -242,6 +243,8 @@
     char *piece, *start, *fmt = th_strdup(str);
     BOOL ret = FALSE;
 
+    memset(info, 0, sizeof(MAPInfoCtx));
+
     // Check for map filename end
     if ((piece = strchr(fmt, ':')) == NULL)
         goto err;
@@ -845,6 +848,51 @@
 }
 
 
+void mapCreateResultStr(char **buf, size_t *bufLen, const MAPMatch *matches, const int nmatches)
+{
+    size_t bufSize = 0;
+    *bufLen = 0;
+    *buf = NULL;
+
+    th_strbuf_puts(buf, &bufSize, bufLen, "RESULT:[");
+
+    for (int n = 0; n < nmatches; n++)
+    {
+        const MAPMatch *match = &matches[n];
+        char *vstr;
+
+        if (match->type)
+        {
+            vstr = th_strdup_printf(
+                "[%d,%d,\"%s\",%d,%d,%d,%d]%s",
+                match->accuracy,
+                match->centered,
+                match->map,
+                match->mx, match->my,
+                match->wx, match->wy,
+                (n < nmatches - 1) ? "," : "");
+        }
+        else
+        {
+            vstr = th_strdup_printf(
+                "[%d,%d,\"%s\",%d,%d,%d,%d,\"%s\",\"%s\"]%s",
+                match->accuracy,
+                match->centered,
+                match->map,
+                match->mx, match->my,
+                match->wx, match->wy,
+                match->loc1, match->loc2,
+                (n < nmatches - 1) ? "," : "");
+        }
+
+        th_strbuf_puts(buf, &bufSize, bufLen, vstr);
+        th_free(vstr);
+    }
+
+    th_strbuf_puts(buf, &bufSize, bufLen, "]");
+}
+
+
 void mapPerformSearch(struct lws *wsi, const unsigned char *data, const size_t len, char **verr)
 {
     static const char *cleanChars = " *@?%C";
@@ -1022,6 +1070,7 @@
                 // Okay, add the match to our list
                 MAPMatch *match = &matches[nmatches++];
 
+                match->type = TRUE;
                 match->map = info->locFile.continent;
                 match->mx = ox + centerX + 1;
                 match->my = oy + centerY + 1;
@@ -1045,32 +1094,79 @@
         return;
 
     // We got some matches, output them as a JSON array
-    char *buf = NULL;
-    size_t bufLen = 0, bufSize = 0;
+    char *buf;
+    size_t bufLen;
+
+    mapCreateResultStr(&buf, &bufLen, matches, nmatches);
+
+    mapMSG(2, "%s\n", buf);
+    mapLWSWrite(wsi, (unsigned char *) buf, bufLen);
+    th_free(buf);
+}
+
 
-    th_strbuf_puts(&buf, &bufSize, &bufLen, "RESULT:[");
+void mapLocationSearch(struct lws *wsi, const unsigned char *data, const size_t len, char **verr)
+{
+    MAPMatch matches[SET_MAX_MATCHES];
+    int nmatches = 0;
+    char *pattern = NULL;
 
-    for (int n = 0; n < nmatches; n++)
+    // Check search pattern length
+    if (len < 3 || len > 25)
+        goto out;
+
+    char *tmp = th_strndup((char *) data, len);
+    pattern = th_strdup_printf("*%s*", tmp);
+    th_free(tmp);
+
+    //
+    // Search the maps .. enabled or if none specified, all of them
+    //
+    for (int nmap = 0; nmap < optNMaps; nmap++)
     {
-        MAPMatch *match = &matches[n];
-        char *vstr = th_strdup_printf(
-            "[%d,%d,\"%s\",%d,%d,%d,%d]%s",
-            match->accuracy,
-            match->centered,
-            match->map,
-            match->mx, match->my,
-            match->wx, match->wy,
-            (n < nmatches - 1) ? "," : "");
+        MAPInfoCtx *info = &optMaps[nmap];
+        for (int nloc = 0; nloc < info->loc.n; nloc++)
+        {
+            LocMarker *marker = info->loc.locations[nloc];
+            for (int nname = 0; nname < marker->nnames; nname++)
+            if (th_strcasematch(marker->names[nname].name, pattern))
+            {
+                // Okay, add the match to our list
+                MAPMatch *match = &matches[nmatches++];
 
-        th_strbuf_puts(&buf, &bufSize, &bufLen, vstr);
-        th_free(vstr);
+                match->type = FALSE;
+                match->loc1 = marker->names[0].name;
+                match->loc2 = marker->names[nname].name;
+                match->map = info->locFile.continent;
+                match->mx = marker->x + 1;
+                match->my = marker->y + 1;
+                match->wx = optWorldXC + info->locFile.x + marker->x;
+                match->wy = optWorldYC + info->locFile.y + marker->y;
+                match->accuracy = 100;
+                match->centered = TRUE;
+
+                // Check for max matches
+                if (nmatches >= SET_MAX_MATCHES)
+                    goto out;
+            }
+        }
     }
 
-    th_strbuf_puts(&buf, &bufSize, &bufLen, "]");
-    mapMSG(2, "%s\n", buf);
+out:
+    th_free(pattern);
+
+    // If an error occured, bail out now
+    if (*verr != NULL)
+        return;
 
+    // We got some matches, output them as a JSON array
+    char *buf;
+    size_t bufLen;
+
+    mapCreateResultStr(&buf, &bufLen, matches, nmatches);
+
+    mapMSG(2, "%s\n", buf);
     mapLWSWrite(wsi, (unsigned char *) buf, bufLen);
-
     th_free(buf);
 }
 
@@ -1134,6 +1230,16 @@
                 th_free(buf);
             }
             else
+            if (len >= 10 && strncmp(data, "LOCSEARCH:", 10) == 0)
+            {
+                mapMSG(1, "[%p] Location search query.\n", wsi);
+
+                if (len <= 10 + 1)
+                    verr = "Invalid search query.";
+                else
+                    mapLocationSearch(wsi, udata + 10, len - 10, &verr);
+            }
+            else
             {
                 // Unknown or invalid query
                 verr = "Invalid command/search query, not enough data.";
@@ -1272,7 +1378,7 @@
             return FALSE;
         }
 
-        if (!locParseLocStream(fh, &info->locFile, &(info->loc), info->locFile.x, info->locFile.y))
+        if (!locParseLocStream(fh, &info->locFile, &(info->loc), 0, 0))
         {
             fclose(fh);
             return FALSE;