summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormvglasow <michael -at- vonglasow.com>2018-08-18 18:54:23 +0200
committermvglasow <michael -at- vonglasow.com>2018-08-18 18:54:23 +0200
commit84be81315d4e5c88758ce9c77daef52baddbaa90 (patch)
tree35a2e1096a97c8ba3b02140c41c9510a39e204e0
parent973b56074f369b2affda26dcdd3573463a695349 (diff)
downloadnavit-84be81315d4e5c88758ce9c77daef52baddbaa90.tar.gz
Refactor:traffic:Prepare for partial road ref matches
Signed-off-by: mvglasow <michael -at- vonglasow.com>
-rw-r--r--navit/traffic.c14
-rw-r--r--navit/util.c41
-rw-r--r--navit/util.h2
3 files changed, 30 insertions, 27 deletions
diff --git a/navit/traffic.c b/navit/traffic.c
index a8a0c07b4..869dfe995 100644
--- a/navit/traffic.c
+++ b/navit/traffic.c
@@ -1234,11 +1234,8 @@ static int traffic_location_match_attributes(struct traffic_location * this_, st
/* road_ref */
if (this_->road_ref) {
maxscore += 4;
- if (item_attr_get(item, attr_street_name_systematic, &attr)) {
- // TODO give partial score for partial matches
- if (!compare_name_systematic(this_->road_ref, attr.u.str))
- score += 4;
- }
+ if (item_attr_get(item, attr_street_name_systematic, &attr))
+ score += (4 * (MAX_MISMATCH - compare_name_systematic(this_->road_ref, attr.u.str))) / MAX_MISMATCH;
}
/* road_name */
@@ -1288,11 +1285,8 @@ static int traffic_point_match_attributes(struct traffic_point * this_, struct i
/* junction_ref */
if (this_->junction_ref) {
maxscore += 4;
- if (item_attr_get(item, attr_ref, &attr)) {
- // TODO give partial score for partial matches
- if (!compare_name_systematic(this_->junction_ref, attr.u.str))
- score += 4;
- }
+ if (item_attr_get(item, attr_ref, &attr))
+ score += (4 * (MAX_MISMATCH - compare_name_systematic(this_->junction_ref, attr.u.str))) / MAX_MISMATCH;
}
/* junction_name */
diff --git a/navit/util.c b/navit/util.c
index 2a32db546..c68f68d28 100644
--- a/navit/util.c
+++ b/navit/util.c
@@ -194,39 +194,42 @@ static char * parse_for_systematic_comparison(const char *s) {
* function performs a fuzzy comparison: Each string is broken down into numeric and non-numeric parts.
* Then both strings are compared part by part. The following rules apply:
*
- * \li Semicolons denote sequences of strings, which will match if any string in `s1` matches any string in `s2`.
+ * \li Semicolons denote sequences of strings, and the best match between any pair of strings from `s1` and `s2` is
+ * returned.
* \li Whitespace bordering on a number is discarded.
* \li Whitespace surrounded by string characters is treated as one string with the surrounding characters.
* \li If one string has more parts than the other, the shorter string is padded with null parts.
- * \li null is less than non-null.
* \li null equals null.
- * \li A numeric part is less than a string part.
- * \li Numeric parts are compared as integers.
- * \li String parts are compared as strings. Comparison is case-insensitive.
+ * \li null does not equal non-null.
+ * \li Numeric parts are compared as integers, hence `'042'` equals `'42'`.
+ * \li Comparison of string parts is case-insensitive.
*
* @param s1 The first string
* @param s2 The second string
*
- * @return 0 if both strings match, nonzero if they do not. Nonzero results are not guaranteed to carry any further
- * information (such as sort order), and callers should not rely on that.
+ * @return 0 if both strings match, nonzero if they do not. Currently `MAX_MISMATCH` is returned for any mismatch;
+ * future versions may express the quality of partial matches (lower values indicating better matches).
*/
int compare_name_systematic(const char *s1, const char *s2) {
- int ret = 0;
+ int ret = MAX_MISMATCH;
+ int tmp;
char *l = NULL, *r = NULL, *l0, *r0;
if (!s1 || !s1[0]) {
if (!s2 || !s2[0])
return 0;
else
- return 1;
+ return MAX_MISMATCH;
} else if (!s2 || !s2[0])
- return -1;
+ return MAX_MISMATCH;
/* break up strings at semicolons and parse each separately, return 0 if any two match */
if (strchr(s1, ';')) {
l = g_strdup(s1);
for (l0 = strtok(l, ";"); l0; l0 = strtok(NULL, ";")) {
- ret = compare_name_systematic(l0, s2);
+ tmp = compare_name_systematic(l0, s2);
+ if (tmp < ret)
+ ret = tmp;
if (!ret)
break;
}
@@ -235,7 +238,9 @@ int compare_name_systematic(const char *s1, const char *s2) {
} else if (strchr(s2, ';')) {
r = g_strdup(s2);
for (r0 = strtok(r, ";"); r0; r0 = strtok(NULL, ";")) {
- ret = compare_name_systematic(s1, r0);
+ tmp = compare_name_systematic(s1, r0);
+ if (tmp < ret)
+ ret = tmp;
if (!ret)
break;
}
@@ -244,6 +249,8 @@ int compare_name_systematic(const char *s1, const char *s2) {
}
/* s1 and s2 are single strings (no semicolons) */
+ ret = 0;
+
l0 = parse_for_systematic_comparison(s1);
r0 = parse_for_systematic_comparison(s2);
@@ -253,14 +260,14 @@ int compare_name_systematic(const char *s1, const char *s2) {
while (!ret && l[0] && r[0]) {
if (atoi(l) || (l[0] == '0')) {
if (atoi(r) || (r[0] == '0'))
- ret = atoi(l) - atoi(r);
+ ret = (atoi(l) == atoi(r)) ? 0 : MAX_MISMATCH;
else
- ret = -1;
+ ret = MAX_MISMATCH;
} else {
if (atoi(r) || (r[0] == '0'))
- ret = 1;
+ ret = MAX_MISMATCH;
else
- ret = strcasecmp(l, r);
+ ret = strcasecmp(l, r) ? MAX_MISMATCH : 0;
}
l += strlen(l) + 1;
@@ -268,7 +275,7 @@ int compare_name_systematic(const char *s1, const char *s2) {
}
if (!ret)
- ret = l[0] - r[0];
+ ret = (l[0] == r[0]) ? 0 : MAX_MISMATCH;
dbg(lvl_debug, "'%s' %s '%s'\n", s1, ret?"does NOT match":"matches", s2);
diff --git a/navit/util.h b/navit/util.h
index f249010c8..140b3b850 100644
--- a/navit/util.h
+++ b/navit/util.h
@@ -24,6 +24,8 @@
#include <time.h>
#include "config.h"
+#define MAX_MISMATCH 100
+
void strtoupper(char *dest, const char *src);
void strtolower(char *dest, const char *src);
int navit_utf8_strcasecmp(const char *s1, const char *s2);